为什么在不同数量的功能下standardscaler会有不同的效果

问题描述

我用scikit-learn的乳腺癌数据进行了实验。

  1. 使用所有功能而不使用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
  2. 使用所有功能并使用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
  3. 仅使用两个功能,而不使用standardscaler:

    cancer = datasets.load_breast_cancer()
    x = cancer.data[:,[27,22]]
    y = cancer.target
    x_train,y_pred))
    
    • 结果3:0.37719298245614036
  4. 仅使用两个功能并使用standardscaler:

    cancer = datasets.load_breast_cancer()
    x = cancer.data[:,y_pred))
    
    • 结果4:0.9824561403508771

结果1,结果2,结果3,结果4显示,使用Standardscaler进行准确性提高,同时训练较少的功能

所以我想知道为什么在不同数量功能下standardscaler会有不同的效果

PS。这是我选择的两个功能

  • enter image description here

解决方法

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])

enter image description here

再一次,线性相关特征与感知器准确性无关。

结论。

请勿在任何算法之前选择功能,除非您完全确定自己在做什么以及这样做的后果。不要混淆不同的选择和学习算法,因为不同的算法对于重要和不重要有不同的看法。对于一种算法不重要的功能可能对另一种算法很重要。线性算法与非线性算法尤其如此。

如果您想提高算法的准确性,请改为执行数据清理或功能工程。