我有一组自定义特征和一组使用Vectorizers创建的特征,在这种情况下使用的是TfidfVectorizer。
我所有的自定义特征都是简单的np.arrays(例如[0, 5, 4, 22, 1])。我使用StandardScaler来缩放所有特征,你可以在我的Pipeline中看到,在我的“custom pipeline”之后调用StandardScaler。问题是,我是否有必要或有方法来缩放我在“vectorized_pipeline”中使用的Vectorizers。在Vectorizers上应用StandardScaler似乎不起作用(我得到以下错误:“ValueError: Cannot center sparse matrices”)。
还有另一个问题,在我将它们合并到FeatureUnion之后,是否有必要缩放所有特征,还是应该分别缩放它们(在我的例子中,通过在“pos_cluster”和“stylistic_features”中分别调用缩放器,而不是在它们合并之后调用),哪种做法更好?
from sklearn.pipeline import FeatureUnion, Pipelinefrom sklearn import feature_selectionfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.preprocessing import StandardScalerfrom sklearn.svm import LinearSVCX = ['I am a sentence', 'an example']Y = [1, 2]X_dev = ['another sentence']inner_scaler = StandardScaler()# classifierLinearSVC1 = LinearSVC(tol=1e-4, C = 0.10000000000000001)# vectorizerscountVecWord = 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)
回答:
首先要说的是:
错误“Cannot center sparse matrices”
原因很简单 – StandardScaler有效地应用了按特征的变换:
f_i = (f_i - mean(f_i)) / std(f_i)
对于稀疏矩阵,这将导致密集矩阵,因为mean(f_i)通常不为零。实际上,只有等于其均值的特征才会变为零。Scikit learn不希望这样做,因为这会对你的数据进行巨大的修改,可能会导致代码的其他部分出现故障,占用大量内存等。如何处理这个问题?如果你真的想这样做,有两个选项:
- 通过.toarray()将你的矩阵密集化,这将需要大量内存,但会给你期望的结果
- 创建一个不计算均值的StandardScaler,即
StandardScaler(with_mean = False)
,这将应用f_i = f_i / std(f_i)
,但会保留数据的稀疏格式。
是否需要缩放?
这是一个完全不同的问题 – 通常,任何形式的缩放只是一种启发式方法。这不是你必须应用的东西,没有保证它会有所帮助,这只是当你不知道你的数据是什么样子时,合理的事情。“智能”向量化器,如tfidf,实际上已经在做这件事了。idf变换的目的是创建一种合理的数据缩放。没有保证哪一种会更好,但总的来说,tfidf应该足够了。特别是考虑到它仍然支持稀疏计算,而StandardScaler则不支持。