问题描述
我用scikit-learn的乳腺癌数据进行了实验。
-
使用所有功能而不使用standardscaler:
cancer = datasets.load_breast_cancer() x = cancer.data y = cancer.target x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=42) pla = Perceptron().fit(x_train,y_train) y_pred = pla.predict(x_test) print(accuracy_score(y_test,y_pred))
- 结果1:0.9473684210526315
-
使用所有功能并使用standardscaler:
cancer = datasets.load_breast_cancer() x = cancer.data y = cancer.target x_train,random_state=42) sc=StandardScaler() sc.fit(x_train) x_train=sc.transform(x_train) x_test=sc.transform(x_test) pla = Perceptron().fit(x_train,y_pred))
- 结果2:0.9736842105263158
-
仅使用两个功能,而不使用standardscaler:
cancer = datasets.load_breast_cancer() x = cancer.data[:,[27,22]] y = cancer.target x_train,y_pred))
- 结果3:0.37719298245614036
-
仅使用两个功能并使用standardscaler:
cancer = datasets.load_breast_cancer() x = cancer.data[:,y_pred))
- 结果4:0.9824561403508771
结果1,结果2,结果3,结果4显示,使用Standardscaler进行准确性提高,同时训练较少的功能。
所以我想知道为什么在不同数量的功能下standardscaler会有不同的效果?
PS。这是我选择的两个功能:
解决方法
TL; DR
只要您不完全了解为什么要选择功能,就不要进行功能选择,否则它可能会帮助您的算法更好地学习和推广。首先,请阅读Max Kuhn的http://www.feat.engineering/selection.html
完整阅读。
我怀疑您试图选择最佳特征子集,并遇到了[任意]子集的性能优于整个数据集的情况。在这里,StandardScaling毫无疑问,因为它被认为是针对您的算法的标准预处理程序。因此,您真正的问题应该是:“为什么子集的功能要比完整的数据集表现更好?”
为什么您的选择算法是任意的? 2个原因。
首先。没有人证明最线性相关的功能可以改善您的算法。第二。最佳特征子集与最佳关联特征所必需的子集不同。
让我们看一下代码。
具有最佳准确性的功能子集(请注意a
)
让我们做蛮力
acc_bench = 0.9736842105263158 # accuracy on all features
res = {}
f = x_train.shape[1]
pcpt = Perceptron(n_jobs=-1)
from itertools import combinations
for i in tqdm(range(2,10)):
features_list = combinations(range(f),i)
for features in features_list:
pcpt.fit(x_train[:,features],y_train)
preds = pcpt.predict(x_test[:,features])
acc = accuracy_score(y_test,preds)
if acc > acc_bench:
acc_bench = acc
res["accuracy"] = acc_bench
res["features"] = features
print(res)
{'accuracy': 1.0,'features': (0,15,22)}
所以您看到,功能[0,22]
相对于验证数据集具有完美的准确性。
最佳功能与目标关联是否相关?
让我们找到按线性相关程度排序的列表。
featrues = pd.DataFrame(cancer.data,columns=cancer.feature_names)
target = pd.DataFrame(cancer.target,columns=['target'])
cancer_data = pd.concat([featrues,target],axis=1)
features_list = np.argsort(np.abs(cancer_data.corr()['target'])[:-1].values)[::-1]
feature_list
array([27,22,7,20,2,23,3,6,26,5,25,10,12,13,21,24,28,1,17,4,8,29,16,19,14,9,11,18])
您看到,蛮力发现的最佳特征子集与关联无关。
线性相关性可以解释Perceptron的准确性吗?
让我们尝试绘制以上列表中的特征数量(从2个最相关的位置开始)与结果精度。
res = dict()
for i in tqdm(range(2,10)):
features=features_list[:i]
pcpt.fit(x_train[:,y_train)
preds = pcpt.predict(x_test[:,features])
acc = accuracy_score(y_test,preds)
res[i]=[acc]
pd.DataFrame(res).T.plot.bar()
plt.ylim([.9,1])
再一次,线性相关特征与感知器准确性无关。
结论。
请勿在任何算法之前选择功能,除非您完全确定自己在做什么以及这样做的后果。不要混淆不同的选择和学习算法,因为不同的算法对于重要和不重要有不同的看法。对于一种算法不重要的功能可能对另一种算法很重要。线性算法与非线性算法尤其如此。
如果您想提高算法的准确性,请改为执行数据清理或功能工程。