构建一个 sklearn 文本分类器并使用 coremltools 进行转换

Posted

技术标签:

【中文标题】构建一个 sklearn 文本分类器并使用 coremltools 进行转换【英文标题】:building a sklearn text classifier and converting it with coremltools 【发布时间】:2017-11-10 04:32:40 【问题描述】:

我想用 sklearn 构建一个文本分类器,然后使用 coremltools 包将其转换为 ios11 机器学习文件。 我用Logistic Regression、Random Forest 和Linear SVC 构建了三个不同的分类器,它们都可以在Python 中正常工作。 问题在于 coremltools 包以及它将 sklearn 模型转换为 iOS 文件的方式。正如its documentation 所说,它只支持这些模型:

线性回归和逻辑回归 LinearSVC 和 LinearSVR SVC 和 SVR NuSVC 和 NuSVR 梯度提升分类器和回归器 决策树分类器和回归器 随机森林分类器和回归器 规范化器 计算机 标准定标器 DictVectorizer 一个热编码器

所以它不允许我对文本数据集进行矢量化(我在分类器中使用了 TfidfVectorizer 包):

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.

有什么方法可以构建 sklearn 文本分类器而不使用 TfidfVectorizer 或 CountVectorizer 模型?

【问题讨论】:

【参考方案1】:

如果您想将 tf-idf 矢量化器转换为 .mlmodel 格式,现在您不能在管道中包含它。解决此问题的方法是分别对数据进行矢量化,然后使用矢量化数据训练模型(线性 SVC、随机森林……)。然后您需要计算设备上的 tf-idf 表示,然后您可以将其插入模型。这是我写的 tf-idf 函数的副本。

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

编辑:在http://gokulswamy.me/imessage-spam-detection/ 写了一篇关于如何执行此操作的完整帖子。

【讨论】:

以上是关于构建一个 sklearn 文本分类器并使用 coremltools 进行转换的主要内容,如果未能解决你的问题,请参考以下文章

sklearn中带有词袋和附加情感特征的文本分类器

如何在 sklearn 中编写自定义估算器并对其使用交叉验证?

sklearn 除了文本之外的其他输入用于文本分类

算法 | 使用sklearn自带的贝叶斯分类器进行文本分类和参数调优

使用gensim和sklearn搭建一个文本分类器:文档向量化

如何使用 sklearn 库使用朴素贝叶斯执行文本分类?