您是否需要在sklearn中缩放Vectorizer?

iva*_*lan 2 python machine-learning scikit-learn

我有一组自定义功能以及使用Vectorizers创建的一组功能,在本例中为TfidfVectorizer。

我所有的自定义功能都是简单的np.arrays(例如[0、5、4、22、1])。我正在使用StandardScaler缩放所有功能,正如您在“管道”中通过在“自定义管道”之后调用StandardScaler所看到的那样。问题是,是否有办法缩放我在“ vectorized_pipeline”中使用的矢量化器。在矢量化器上应用StandardScaler似乎不起作用(出现以下错误:“ ValueError:无法居中稀疏矩阵”)。

另一个问题是,在我将所有功能加入FeatureUnion后是否缩放我的所有功能,还是我分别缩放每个功能(在我的示例中,分别在“ pos_cluster”和“ stylistic_features”中调用缩放器而不是调用他们两个都加入之后),这样做的更好方法是什么?

from sklearn.pipeline import FeatureUnion, Pipeline
from sklearn import feature_selection
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC

X = ['I am a sentence', 'an example']
Y = [1, 2]
X_dev = ['another sentence']

inner_scaler = StandardScaler()
# classifier
LinearSVC1 = LinearSVC(tol=1e-4,  C = 0.10000000000000001)

# vectorizers
countVecWord = TfidfVectorizer(ngram_range=(1, 3), max_features=2000, analyzer=u'word', sublinear_tf=True, use_idf = True, min_df=2, max_df=0.85, lowercase = True)
countVecWord_tags = TfidfVectorizer(ngram_range=(1, 4), max_features= 1000, analyzer=u'word', min_df=2, max_df=0.85, sublinear_tf=True, use_idf = True, lowercase = False)


pipeline = Pipeline([
    ('union', FeatureUnion(
            transformer_list=[

            ('vectorized_pipeline', Pipeline([
                ('union_vectorizer', FeatureUnion([

                    ('stem_text', Pipeline([
                        ('selector', ItemSelector(key='stem_text')),
                        ('stem_tfidf', countVecWord)
                    ])),

                    ('pos_text', Pipeline([
                        ('selector', ItemSelector(key='pos_text')),
                        ('pos_tfidf', countVecWord_tags)
                    ])),

                ])),
                ])),


            ('custom_pipeline', Pipeline([
                ('custom_features', FeatureUnion([

                    ('pos_cluster', Pipeline([
                        ('selector', ItemSelector(key='pos_text')),
                        ('pos_cluster_inner', pos_cluster)
                    ])),

                    ('stylistic_features', Pipeline([
                        ('selector', ItemSelector(key='raw_text')),
                        ('stylistic_features_inner', stylistic_features)
                    ]))

                ])),
                    ('inner_scale', inner_scaler)
            ])),

            ],

            # weight components in FeatureUnion
            # n_jobs=6,

            transformer_weights={
                'vectorized_pipeline': 0.8,  # 0.8,
                'custom_pipeline': 1.0  # 1.0
            },
    )),

    ('clf', classifier),
    ])

pipeline.fit(X, Y)
y_pred = pipeline.predict(X_dev)
Run Code Online (Sandbox Code Playgroud)

lej*_*lot 6

首先要注意的是:

错误“无法居中稀疏矩阵”

原因很简单-StandardScaler有效地应用了按功能转换:

f_i = (f_i - mean(f_i)) / std(f_i)
Run Code Online (Sandbox Code Playgroud)

对于稀疏矩阵,这将导致密集矩阵,因为均值(f_i)通常不为零。实际上,只有等于其均值的要素最终将为零。Scikit learning不想这样做,因为这是对数据的巨大修改,这可能会导致代码其他部分出现故障,大量使用内存等。如何处理呢?如果您确实要执行此操作,则有两种选择:

  • 通过.toarray()压缩矩阵,这将需要大量的内存,但会给您确切的期望
  • 毫无意义地创建StandardScaler,从而StandardScaler(with_mean = False)适用于willl f_i = f_i / std(f_i),但将保留数据的稀疏格式。

是否需要scalind?

这是另一个完全不同的问题-通常,缩放(任何形式)都只是一种启发式方法。这不是您必须应用的东西,无法保证它会有所帮助,当您不知道数据是什么样时,这只是一件合理的事情。诸如tfidf之类的“智能”矢量化程序实际上已经在这样做。idf转换应该创建一种合理的数据缩放。无法保证哪个会更好,但总的来说,tfidf应该足够。特别是考虑到事实,它仍然支持稀疏计算,而StandardScaler不支持。