2015-09-01 19 views

cevap

22

Can I extend the default one?

Gerçekten değil. Varsayılan Tokenizer, pyspark.ml.wrapper.JavaTransformer'un bir alt sınıfıdır ve pyspark.ml.feature'dan diğer transfromerler ve tahmin edicilerle aynıdır, gerçek işleme Scala karşılığı için temsil eder. Python'u kullanmak istediğinizden, doğrudan pyspark.ml.pipeline.Transformer'u uzatmalısınız.

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)) 

Örnek kullanım (ML - Features verileri): Özel Python Estimator için

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() 

Bu cevap iç API bağlıdır ve Spark 2.0.3, 2.1 ile uyumludur ⚠

How to Roll a Custom Estimator in PySpark mllib görüyoruz. 1, 2.2.0 veya üstü (SPARK-19348). Önceki Spark sürümleriyle uyumlu kod için lütfen bkz. revision 8.

+1

Bunu bir Boru Hattı'nda bir adım olarak uygulamaya çalıştım ve şu hatayı aldım: AttributeError: 'NLTKWordPunctTokenizer' nesnesi '_to_java' özelliğine sahip değil. Bu, Pipeline diski yazmaya çalıştığımda ortaya çıkar (bu adımı eklemeden önce iyi çalıştı). Tanımlanması gereken bazı sınıf yöntemleri var mıdır? –

+0

@EvanZamir Evet, hem 'Pipeline' hem de 'PipelineModel' her aşamada '_to_java' komutunu uygular ve ilgili Java nesnesini kullanarak yüklenebilir. Ne yazık ki, bu aslında 'JavaWrapper' var varsayımı altında çalışır. Bununla ilgili bir JIRA'yı gördüğüm bu belirsiz anılarım var ama yanılıyor olabilirim. – zero323

+0

Bu, sıfır323 mü? https://issues.apache.org/jira/browse/SPARK-17025 Görünüşe göre, bu sorun gerçekten dün yapıldı. –