我使用当前稳定版0.13的scikit-learn。我使用类sklearn.svm.LinearSVC
将线性支持向量分类器应用于某些数据。
在scikit-learn文档的chapter about preprocessing中,我已阅读以下内容:
在学习算法的目标函数中使用的许多元素(例如支持向量机的RBF内核或线性模型的l1和l2正则化器)假设所有特征都以零为中心并且具有相同顺序的方差。如果某个要素的方差比其他要大一个数量级,那么它可能会主导目标函数并使估算工具无法按预期正确地学习其他要素。
问题1:标准化对一般的SVM是否有用,对于那些具有线性核函数的人来说也是如此?
问题2:据我了解,我必须计算训练数据的均值和标准差,并使用类sklearn.preprocessing.StandardScaler
对测试数据应用相同的转换。但是,我不明白的是,在将训练数据提供给SVM分类器之前,我是否还必须转换训练数据或仅转换测试数据。
也就是说,我必须这样做:
scaler = StandardScaler()
scaler.fit(X_train) # only compute mean and std here
X_test = scaler.transform(X_test) # perform standardization by centering and scaling
clf = LinearSVC()
clf.fit(X_train, y_train)
clf.predict(X_test)
或者我必须这样做:
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train) # compute mean, std and transform training data as well
X_test = scaler.transform(X_test) # same as above
clf = LinearSVC()
clf.fit(X_train, y_train)
clf.predict(X_test)
简而言之,我是否必须在培训数据上使用scaler.fit(X_train)
或scaler.fit_transform(X_train)
才能通过LinearSVC
获得合理的结果?
答案 0 :(得分:34)
都不是。
scaler.transform(X_train)
没有任何效果。 transform
操作不在原地。
你必须这样做
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
或
X_train = scaler.fit(X_train).transform(X_train)
您始终需要对训练或测试数据执行相同的预处理。是的,如果标准化反映了您对数据的信任,那么标准化总是好的。 特别是对于kernel-svms,它通常是至关重要的。
答案 1 :(得分:5)
为什么不一次使用Pipeline
链接(或组合)变换器和估算器?为您省去单独拟合和转换数据的麻烦,然后使用估算器。它也会节省一些空间。
from sklearn.pipeline import Pipeline
pipe_lrSVC = Pipeline([('scaler', StandardScaler()), ('clf', LinearSVC())])
pipe_lrSVC.fit(X_train, y_train)
y_pred = pipe_lrSVC.predict(X_test)