Can I extend the default one?
Không thực sự. Mặc định Tokenizer
là một phân lớp của pyspark.ml.wrapper.JavaTransformer
và, giống như các bộ chuyển đổi và ước tính khác từ pyspark.ml.feature
, ủy quyền xử lý thực tế cho đối tác Scala của nó. Vì bạn muốn sử dụng Python, bạn nên mở rộng trực tiếp pyspark.ml.pipeline.Transformer
.
import nltk
from pyspark import keyword_only ## < 2.0 -> pyspark.ml.util.keyword_only
from pyspark.ml import Transformer
from pyspark.ml.param.shared import HasInputCol, HasOutputCol, Param
from pyspark.sql.functions import udf
from pyspark.sql.types import ArrayType, StringType
class NLTKWordPunctTokenizer(Transformer, HasInputCol, HasOutputCol):
@keyword_only
def __init__(self, inputCol=None, outputCol=None, stopwords=None):
super(NLTKWordPunctTokenizer, self).__init__()
self.stopwords = Param(self, "stopwords", "")
self._setDefault(stopwords=set())
kwargs = self._input_kwargs
self.setParams(**kwargs)
@keyword_only
def setParams(self, inputCol=None, outputCol=None, stopwords=None):
kwargs = self._input_kwargs
return self._set(**kwargs)
def setStopwords(self, value):
self._paramMap[self.stopwords] = value
return self
def getStopwords(self):
return self.getOrDefault(self.stopwords)
def _transform(self, dataset):
stopwords = self.getStopwords()
def f(s):
tokens = nltk.tokenize.wordpunct_tokenize(s)
return [t for t in tokens if t.lower() not in stopwords]
t = ArrayType(StringType())
out_col = self.getOutputCol()
in_col = dataset[self.getInputCol()]
return dataset.withColumn(out_col, udf(f, t)(in_col))
Ví dụ sử dụng (dữ liệu từ ML - Features):
sentenceDataFrame = spark.createDataFrame([
(0, "Hi I heard about Spark"),
(0, "I wish Java could use case classes"),
(1, "Logistic regression models are neat")
], ["label", "sentence"])
tokenizer = NLTKWordPunctTokenizer(
inputCol="sentence", outputCol="words",
stopwords=set(nltk.corpus.stopwords.words('english')))
tokenizer.transform(sentenceDataFrame).show()
Đối với tùy chỉnh Python Estimator
thấy How to Roll a Custom Estimator in PySpark mllib
⚠ Câu trả lời này phụ thuộc vào API nội bộ và tương thích với Spark 2.0.3, 2.1. 1, 2.2.0 hoặc mới hơn (SPARK-19348). Đối với mã tương thích với các phiên bản Spark trước, vui lòng xem revision 8.
Cố gắng thực hiện điều này dưới dạng một bước trong Đường ống và nhận được lỗi sau đối tượng 'AttributeError: 'NLTKWordPunctTokenizer' không có thuộc tính '_to_java''. Điều này xảy ra khi tôi cố gắng để viết đường ống vào đĩa (làm việc tốt trước khi thêm bước này). Tôi giả sử có một số phương pháp lớp học cần phải được xác định? –
@EvanZamir Có, cả hai 'Pipeline' và' PipelineModel' đều mong rằng mỗi giai đoạn thực hiện '_to_java' và có thể được nạp bằng cách sử dụng đối tượng Java tương ứng. Thật không may này hoạt động theo giả định rằng bạn thực sự có 'JavaWrapper'. Tôi có bộ nhớ mơ hồ này mà tôi đã thấy một số JIRA liên quan đến điều đó nhưng tôi có thể sai. – zero323
Đây có phải là @ zero323 không? https://issues.apache.org/jira/browse/SPARK-17025 Rõ ràng vấn đề này đã được tạo ra ngày hôm qua theo nghĩa đen. –