为啥缩放训练和测试数据后我的 SVM 的性能会下降?
Posted
技术标签:
【中文标题】为啥缩放训练和测试数据后我的 SVM 的性能会下降?【英文标题】:Why does my SVM's performance drop after scaling the training and test data?为什么缩放训练和测试数据后我的 SVM 的性能会下降? 【发布时间】:2014-11-28 01:30:16 【问题描述】:我正在使用 scikit-learn 对文本进行情感分析。我现在的功能只是词频计数。
当我执行以下操作时,平均 F 值约为 59%:
from sklearn import svm
clf = svm.LinearSVC(class_weight='auto');
clf.fit(Xfeatures, YLabels);
......
predictedLabels = clf.predict(XTestFeatures);
但是当我使用 StandardScalar() 来缩放我的特征向量时,平均 F-measure 下降到 49%:
from sklearn import svm
clf = svm.LinearSVC(class_weight='auto');
Xfeatures = scaler.fit_transform(Xfeatures);
clf.fit(Xfeatures, YLabels);
......
XTestFeatures = scaler.transform(XTestFeatures);
predictedLabels = clf.predict(XTestFeatures);
缩放应该可以提高我的 SVM 的性能,但在这里,它似乎会降低性能。为什么会这样?我怎样才能使它正确?
【问题讨论】:
【参考方案1】:按均值和方差进行缩放并不是词频的好策略。假设您有两个包含三个术语的术语直方图(我们就称它们为0, 1, 2
):
>>> X = array([[100, 10, 50], [1, 0, 2]], dtype=np.float64)
然后你缩放它们;然后你得到
>>> from sklearn.preprocessing import scale
>>> scale(X)
array([[ 1., 1., 1.],
[-1., -1., -1.]])
缩放只是让我们无法判断第 2 项在 X[1]
中出现的频率高于第 0 项。事实上,术语 1 没有出现在 X[1]
中的事实已经无法区分。
当然,这是一个非常极端的例子,但在更大的集合中也会出现类似的效果。你应该做的是标准化直方图:
>>> from sklearn.preprocessing import normalize
>>> normalize(X)
array([[ 0.89087081, 0.08908708, 0.4454354 ],
[ 0.4472136 , 0. , 0.89442719]])
这会保留您感兴趣的术语的相对频率; 更多积极词比消极词是线性情感分类器关心的,而不是实际频率或它的缩放变体。
(对于单个特征的比例实际上并不重要的领域,建议使用比例缩放,通常是因为特征以不同的单位测量。)
【讨论】:
【参考方案2】:至少有几件事需要考虑:
缩放数据可能降低准确性。不应该,但可以 准确度是不平衡问题的错误度量,您使用“class_weight='auto'”,所以这是您的情况。请改用一些平衡的度量,例如平均准确度或 MCC。 你似乎使用线性SVM的默认超参数,意思是C=1
和;它可能会带来任何几乎随机的结果,您必须通过某种优化技术(至少是网格搜索)来拟合最佳超参数,以便比较两种不同的数据处理(例如您的缩放)
【讨论】:
- 我使用平均 F 度量来比较这两种方法。 - 我正在使用带有默认参数的 LinearSVC。我会研究网格搜索,但你能告诉我为什么默认参数会产生随机结果吗?LinearSVC
不使用内核。以上是关于为啥缩放训练和测试数据后我的 SVM 的性能会下降?的主要内容,如果未能解决你的问题,请参考以下文章