2017-06-08 2 views
0

Je veux construire un classificateur de texte avec sklearn, puis le convertir en fichier d'apprentissage machine iOS11 en utilisant le paquet coremltools. J'ai construit trois classificateurs différents avec Logistic Regression, Random Forest, et Linear SVC et tous fonctionnent bien en Python. Le problème est le paquetage coremltools et la façon dont il convertit le modèle sklearn en fichier iOS. Comme its documentation dit, il ne supporte que ces modèles:construire un classificateur de texte sklearn et le convertir avec coremltools

  • linéaire et régression logistique
  • LinearSVC et LinearSVR
  • SVC et SVR
  • NuSVC et NuSVR
  • gradient Dynamiser classificateur et régresseur
  • Décision Classificateur d'arbres et régresseur
  • Classificateur de forêt aléatoire et régresseur
  • Normalizer
  • imputer Scaler standard
  • DictVectorizer
  • One Hot Encoder

Il ne me permet pas de vectoriser mon jeu de données de texte (je l'ai utilisé paquet TfidfVectorizer dans mes classificateurs):

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. 

Est-il possible de créer un classificateur de texte sklearn et de ne pas utiliser les modèles TfidfVectorizer ou CountVectorizer?

Répondre

1

À l'heure actuelle, vous ne pouvez pas inclure un vectorizer tf-idf dans votre pipeline si vous voulez le convertir au format .mlmodel. Le moyen de contourner ceci est de vectoriser vos données séparément et ensuite d'entrainer le modèle (Linear SVC, Random Forest, ...) avec les données vectorisées. Vous devez ensuite calculer la représentation de tf-idf sur le périphérique que vous pouvez ensuite brancher sur le modèle. Voici une copie de la fonction tf-idf que j'ai écrite.

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: A écrit un poste tout sur la façon de le faire à http://gokulswamy.me/imessage-spam-detection/.