2015-09-01 16 views
11

Tôi mới sử dụng Spark SQL DataFrames và ML trên chúng (PySpark). Làm cách nào để tạo trình chỉnh sửa trang phục, ví dụ: loại bỏ từ dừng và sử dụng một số thư viện từ ? Tôi có thể mở rộng mặc định không?Tạo Biến tùy chỉnh trong PySpark ML

Cảm ơn.

Trả lời

22

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.

+1

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? –

+0

@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

+0

Đâ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. –

Các vấn đề liên quan