2017-06-08 5 views
0

Ich möchte einen Textklassifikator mit sklearn erstellen und dann in iOS11-Maschinenlerndatei mit coremltools-Paket konvertieren. Ich habe drei verschiedene Klassifikatoren mit Logistic Regression, Random Forest und Linear SVC gebaut und alle von ihnen funktionieren gut in Python. Das Problem ist das Coremltools-Paket und die Art und Weise, wie es das Sklearn-Modell in eine iOS-Datei konvertiert. Wie its documentation sagt, es unterstützt nur diese Modelle:Erstellen eines Sklearn-Textklassifizierers und Konvertieren mit coremltools

  • Lineare und logistische Regression
  • LinearSVC und LinearSVR
  • SVC und SVR
  • NuSVC und NuSVR
  • Gradient Boosting Classifier und Regressor
  • Entscheidung Baum Klassifikator und Regressor
  • Random Forest Klassifikator und Regressor
  • Normalizer
  • imputer
  • Standard-Scaler
  • DictVectorizer
  • One Hot Encoder

es ist also nicht zulassen, dass ich meinen Text-Datensatz (I TfidfVectorizer Paket habe vektorisiert in meinem Klassifizierer verwendet):

import coremltools 
coreml_model = coremltools.converters.sklearn.convert(model, input_features='text', output_feature_names='category') 

Traceback (most recent call last): 

File "<ipython-input-3-97beddbdad10>", line 1, in <module> 
    coreml_model = coremltools.converters.sklearn.convert(pipeline, input_features='Message', output_feature_names='Label') 

    File "/usr/local/lib/python2.7/dist-packages/coremltools/converters/sklearn/_converter.py", line 146, in convert 
    sk_obj, input_features, output_feature_names, class_labels = None) 

    File "/usr/local/lib/python2.7/dist-packages/coremltools/converters/sklearn/_converter_internal.py", line 147, in _convert_sklearn_model 
    for sk_obj_name, sk_obj in sk_obj_list] 

    File "/usr/local/lib/python2.7/dist-packages/coremltools/converters/sklearn/_converter_internal.py", line 97, in _get_converter_module 
    ",".join(k.__name__ for k in _converter_module_list))) 

ValueError: Transformer 'TfidfVectorizer(analyzer='word', binary=False, decode_error=u'strict', 
     dtype=<type 'numpy.int64'>, encoding=u'utf-8', input=u'content', 
     lowercase=True, max_df=1.0, max_features=None, min_df=3, 
     ngram_range=(1, 2), norm=u'l2', preprocessor=None, smooth_idf=1, 
     stop_words='english', strip_accents='unicode', sublinear_tf=1, 
     token_pattern='\\w+', tokenizer=None, use_idf=1, vocabulary=None)' not supported; 
supported transformers are coremltools.converters.sklearn._dict_vectorizer,coremltools.converters.sklearn._one_hot_encoder,coremltools.converters.sklearn._normalizer,coremltools.converters.sklearn._standard_scaler,coremltools.converters.sklearn._imputer,coremltools.converters.sklearn._NuSVC,coremltools.converters.sklearn._NuSVR,coremltools.converters.sklearn._SVC,coremltools.converters.sklearn._SVR,coremltools.converters.sklearn._linear_regression,coremltools.converters.sklearn._LinearSVC,coremltools.converters.sklearn._LinearSVR,coremltools.converters.sklearn._logistic_regression,coremltools.converters.sklearn._random_forest_classifier,coremltools.converters.sklearn._random_forest_regressor,coremltools.converters.sklearn._decision_tree_classifier,coremltools.converters.sklearn._decision_tree_regressor,coremltools.converters.sklearn._gradient_boosting_classifier,coremltools.converters.sklearn._gradient_boosting_regressor. 

Gibt es eine Möglichkeit, einen sklearn-Textklassifizierer zu erstellen und keine TfidfVectorizer- oder CountVectorizer-Modelle zu verwenden?

Antwort

1

Momentan können Sie keinen tf-idf-Vektorisierer in Ihre Pipeline aufnehmen, wenn Sie ihn in das .ml-Format konvertieren möchten. Der Weg dahin ist, Ihre Daten separat zu vektorisieren und dann das Modell (Linear SVC, Random Forest, ...) mit den vektorisierten Daten zu trainieren. Sie müssen dann die tf-idf-Darstellung auf dem Gerät berechnen, die Sie dann in das Modell einstecken können. Hier ist eine Kopie der tf-IDF-Funktion, die ich geschrieben habe.

func tfidf(document: String) -> MLMultiArray{ 
    let wordsFile = Bundle.main.path(forResource: "words_ordered", ofType: "txt") 
    let dataFile = Bundle.main.path(forResource: "data", ofType: "txt") 
    do { 
     let wordsFileText = try String(contentsOfFile: wordsFile!, encoding: String.Encoding.utf8) 
     var wordsData = wordsFileText.components(separatedBy: .newlines) 
     let dataFileText = try String(contentsOfFile: dataFile!, encoding: String.Encoding.utf8) 
     var data = dataFileText.components(separatedBy: .newlines) 
     let wordsInMessage = document.split(separator: " ") 
     var vectorized = try MLMultiArray(shape: [NSNumber(integerLiteral: wordsData.count)], dataType: MLMultiArrayDataType.double) 
     for i in 0..<wordsData.count{ 
      let word = wordsData[i] 
      if document.contains(word){ 
       var wordCount = 0 
       for substr in wordsInMessage{ 
        if substr.elementsEqual(word){ 
         wordCount += 1 
        } 
       } 
       let tf = Double(wordCount)/Double(wordsInMessage.count) 
       var docCount = 0 
       for line in data{ 
        if line.contains(word) { 
         docCount += 1 
        } 
       } 
       let idf = log(Double(data.count)/Double(docCount)) 
       vectorized[i] = NSNumber(value: tf * idf) 
      } else { 
       vectorized[i] = 0.0 
      } 
     } 
     return vectorized 
    } catch { 
     return MLMultiArray() 
    } 
} 

Edit: Schrieb einen ganzen Beitrag auf, wie dies bei http://gokulswamy.me/imessage-spam-detection/ zu tun.

Verwandte Themen