特征抽取是数据挖掘任务最为重要的一个环节,一般而言,它对最终结果的影响要高过数据挖掘算法本身。但怎样选取好的特征,还没有严格、快捷的规则可循,这也是数据挖掘科学更像是一门艺术的所在。创建好的规则离不开直觉,还需要专业领域知识和数据挖掘经验,光有这些还不够,还得不停地尝试、摸索,在试错中前进,有时多少还要靠点运气。
特征选择的另一个优点在于:降低真实世界的复杂度,模型比现实更容易操纵。实物的复杂性对目前的算法而言过于复杂,我们退而求其次,使用更为简洁的模型来表示实物。
简化要以数据挖掘应用的目标为核心。降低复杂性有好处,但也有不足,简化会忽略很多细节,甚至会抛弃很多对数据挖掘算法能起到帮助作用的信息。
Adult数据集包括15项特征,而最终的目的是预测一个人是否年收入多于五万美元,在现实生活中每一项特征对最终的预测结果的权重或者说重要性是不一样的,我们需要找到对收入影响最大的前90%的特征即可,当然不同的算法是不同的。
该笔记主要通过皮尔逊相关系数和用卡方检验计算进行主成分分析。
代码示例
代码语言:javascript复制import os
import pandas as pd
#http://archive.ics.uci.edu/ml/datasets/Adult, Data Folder,adult.data and adult.names
data_folder = ''
adult_filename = os.path.join(data_folder, "adult.data")
adult = pd.read_csv(adult_filename, header=None,
names=["Age", "Work-Class", "fnlwgt", "Education", "Education-Num", "Marital-Status",
"Occupation", "Relationship", "Race", "Sex", "Capital-gain", "Capital-loss",
"Hours-per-week", "Native-Country", "Earnings-Raw"])
#观察数据
print(adult[:5])
#删除包含无效数字的行
adult.dropna(how='all', inplace=True)
print(adult.columns )
adult["LongHours"] = adult["Hours-per-week"] > 40
print(adult[:5])
#------------------------特征选取---------------------
# 降低复杂度:随着特征数量的增加,很多数据挖掘算法需要更多的时间和资源。减少特征数量,是提高算法运行速度,减少资源使用的好方法。
# 降低噪音:增加额外特征并不总会提升算法的表现,只选择合适的特征有助于减少出现没有实际意义的相关性的几率。
# 增加模型可读性:根据成千上万个特征创建的模型对我们自己来说就晦涩无比。因此,使用更少的特征,创建我们自己可以理解的模型,就很有必要
#VarianceThreshold转换器可用来删除特征值的方差达不到低标准的特征
import numpy as np
X = np.arange(30).reshape((10, 3))
#将第二列的值置为1,这样第一、三列特征值方差很大,而第二列方差为0
X[:,1] = 1
from sklearn.feature_selection import VarianceThreshold
#创建VarianceThreshold转换器,用它处理数据集。
vt = VarianceThreshold()
Xt = vt.fit_transform(X)
#因第二列方差为0,故转换器把第二列删除掉了
print(Xt)
print(vt.variances_)
#[74.25 0. 74.25]
#----------------------选取最近特征-------------------
#scikit-learn提供了几个用于选择单变量特征的转换器
# SelectKBest返回k个佳 特征,
# SelectPercentile返回表现佳的前r%个特征
#首先,选取下述特征,从pandas数据框中抽 取一部分数据。
X = adult[["Age", "Education-Num", "Capital-gain", "Capital-loss", "Hours-per-week"]].values
#判断Earnings-Raw(税前收入)是否达到五万美元,创建目标类别列表。如果达到, 类别为True,否则,类别为False。
y = (adult["Earnings-Raw"] == ' >50K').values
#再使用SelectKBest转换器类,用卡方函数打分,初始化转换器。
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
transformer = SelectKBest(score_func=chi2, k=3)
#调用fit_transform方法,对相同的数据集进行预处理和转换
#生成分类效果好的三个特征
Xt_chi2 = transformer.fit_transform(X, y)
#目前只能通过Xt_chi2的数据样例才知道保留了哪几列
#生成的矩阵只包含三个特征。我们还可以得到每一列的相关性,这样就可以知道都使用了哪些特征
#相关性好的分别是第一、三、四列,分别对应着Age(年龄)、Capital-Gain(资本收 益)和Capital-Loss(资本损失)三个特征
print(Xt_chi2[:5])
print(transformer.scores_)
#[8.60061182e 03 2.40142178e 03 8.21924671e 07 1.37214589e 06 6.47640900e 03]
#皮尔逊相关系数
from scipy.stats import pearsonr
def multivariate_pearsonr(X, y):
#创建scores和pvalues数组,遍历数据集的每一列。
scores, pvalues = [], []
for column in range(X.shape[1]):
#只计算该列的皮尔逊相关系数和p值,并将其存储到相应数组中。
cur_score, cur_p = pearsonr(X[:, column], y)
scores.append(abs(cur_score))
pvalues.append(cur_p)
return (np.array(scores), np.array(pvalues))
#以像之前那样使用转换器类,根据皮尔逊相关系数对特征进行排序。
transformer = SelectKBest(score_func=multivariate_pearsonr, k=3)
Xt_pearson = transformer.fit_transform(X, y)
print(Xt_pearson[:5])
#第一、二、五列:Age、 Education和Hours-per-week
print(transformer.scores_)
from sklearn.tree import DecisionTreeClassifier
from sklearn.cross_validation import cross_val_score
clf = DecisionTreeClassifier(random_state=14)
scores_chi2 = cross_val_score(clf, Xt_chi2, y, scoring='accuracy')
scores_pearson = cross_val_score(clf, Xt_pearson, y, scoring='accuracy')
print(scores_chi2)
print(scores_pearson)
print("Chi2 performance: {0:.3f}".format(scores_chi2.mean()))
print("Pearson performance: {0:.3f}".format(scores_pearson.mean()))
#chi2方法的平均正确率为0.83,而皮尔逊相关系数正确率为0.77。用卡方检验得到的特征组 合效果更好!