一、特征抽取
特征抽取是数据挖掘任务最为重要的一个环节。特征可用于建模, 模型以机器挖掘算法能够理解的近似的方式来表示现实 。
特征分为数值型特征或类别型特征。
数值型特征通常被看做是有顺序的。数值型特征又分为连续特征和序数特征。可以用连续特征计算平均值、标准差、最大值和最小值。
类别型特征也可以称为名义特征(nominal)。对于名义特征而言,几个值之间要么相同要么不同。
数值型特征与类别型特征的相互转化:类别型特征二值化后就变成了数值型特征,数值型特征也可以通过离散化过程转换为类别型特征。
Adult数据集是预测一个人是否年收入多于五万美元。数据集下载地址为http://archive.ics.uci.edu/ml/ datasets/Adult。
如:代码实现把Adult数据集中的连续值(Hours-per-week,每周工作时长)转换为类别型特征。
创建LongHour(时长)特征,用来表示一个人每周工作时长是否多余40个小时。
adult = pd.read_csv("./data/Adult/adult.data", 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"])
# 删除包含无效数字的行,设置inplace参数为真,表示改动当前数据框,而不是新建一个
adult.dropna(how='all', inplace=True)
adult["LongHours"] = adult["Hours-per-week"] > 40
二、特征选择
特征选择的原因
降低复杂度、降低噪音、增加模型可读性。
拿到数据后,先做下简单、直接的分析。如确保特征值是不同的。scikit-learn中的VarianceThreshold转换器可用来删除特征值的方差达不到最低标准的特征。下面通过代码来讲下它的用法:
from sklearn.feature_selection import VarianceThreshold
X = np.arange(30).reshape((10, 3))
X[:, 1] = 1
vt = VarianceThreshold()
Xt = vt.fit_transform(X)
print(Xt)
print(vt.variances_) # 输出每一列的方差
![](https://img-blog.csdnimg.cn/img_convert/2995d64bd9c226fe9dc346e60923912c.png)
输出Xt后,我们发现第二列消失了,输出每一列的方差结果表明第一、三列包含有价值信息,第二列方差为0,不包含具有区别意义的信息。
如何选择最佳特征
方法是不要找表现好的子集,而只是去找表现好的单个特征(单变量),依据是它们各自所能达到的精确度。分类任务通常是这么做的,我们一般只要测量变量和目标类别之间的某种相关性就行。
scikit-learn提供了几个用于选择单变量特征的转换器,其中SelectKBest返回k个最佳特征,SelectPercentile返回表现最佳的前r%个特征
单个特征和某一类别之间相关性的计算方法有很多。最常用的有卡方检验(χ2)。其他方法还有皮尔逊(Pearson)相关系数、互信息和信息熵。
2.1 卡方检验
# 选取特征
X = adult[["Age", "Education-Num", "Capital-gain", "Capital-loss", "Hours-per-week"]].values
# 创建目标类别列表(判断Earnings-Raw(税前收入)是否达到五万美元)
y = (adult["Earnings-Raw"] == " >50K").values
# 使用SelectKBest转换器类,用卡方函数打分,初始化转换器
from sklearn.feature_selection import SelectKBest, chi2
transformer = SelectKBest(score_func=chi2, k=3)
Xt_chi2 = transformer.fit_transform(X, y)
print(transformer.scores_)
![](https://img-blog.csdnimg.cn/img_convert/29f453aef4dab9d593c49daaa13a01df.png)
相关性最好的分别是第一、三、四列,分别对应着Age(年龄)、Capital-Gain(资本收 益)和Capital-Loss(资本损失)三个特征。从单变量特征选取角度来说,这些就是最佳特征
2.2 皮尔逊(Pearson)相关系数
from scipy.stats import pearsonr
def multivariate_pearsonr(X, y):
scores, pvalues = [], []
for column in range(X.shape[1]):
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(transformer.scores_)
![](https://img-blog.csdnimg.cn/img_convert/b10834d5cd00f1f50a6334731d569dce.png)
返回的特征跟用卡方检验计算相关性得到的特征不一样!这回得到的是第一、二、五列 。
分别用卡方检验和皮尔逊相关系数得到的特征评估分类准确度。
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
clf = DecisionTreeClassifier()
score_chi2 = cross_val_score(clf, Xt_chi2, y, scoring='accuracy')
score_pearson = cross_val_score(clf, Xt_pearson, y, scoring='accuracy')
print("The accuracy of Xt_chi2 is {0:1f}%".format(score_chi2.mean() * 100))
print("The accuracy of Xt_pearson is {0:1f}%".format(score_pearson.mean() * 100))
![](https://img-blog.csdnimg.cn/img_convert/788ae63d14291ec5287376acaf499e9b.png)
三、创建特征
用不同的方法从已有特征中发掘新特征,比如前面用到的一位有效编码(one-hot encoding),我们可以用它把有A、B、C三个选项的类别型特征转换为三个新的特征:“是A吗?”“是B吗?”和“是C吗?”。
1、加载新数据集
数据集链接http://archive.ics.uci.edu/ml/datasets/Internet+Advertisement s
数据集问题一:前几个特征是数值,但是pandas会把它们当成字符串。定义一个转换函数,将字符串转换成数值。
数据集问题二:数据集中有些值缺失,缺失的值用"?"表示。问号不会被转换为浮点型数据。因此,我们也可以把它们转换为“NaN”。
ad = pd.read_csv('./data/AD/ad.data')
# 定义一个转换函数
def convert_number(x):
try:
return float(x)
except ValueError:
return np.nan
# 存储所有特征及其转换结果
converters = defaultdict(convert_number)
converters[1558] = lambda x: 1 if x.strip() == "ad." else 0
ads = pd.read_csv('./data/AD/ad.data', header=None, converters=converters) # converters参数:列转换函数的字典
print(ads)
# 抽取x矩阵和y数组
X = ads.dropna(1558, axis=1).values
y = ads[1558]
2、主成分分析(PCA)创建特征
特征间的相关性信息在某些场合会很有用,但是数据挖掘算法通常不需要这些冗余信息。
主成分分析算法(Principal Component Analysis,PCA)的目的是找到能用较少信息描述数据集的特征组合。它意在发现彼此之间没有相关性、能够描述数据集的特征,确切说这些特征的方差跟整体方差没有多大差距,这样的特征也被称为主成分。这也就意味着,借助这种方法,就能通过更少的特征捕获到数据集的大部分信息。
PCA转换器参数:主成分数量。返回值:默认返回数据集中的所有特征。PCA会对返回结果根据方差由大到小排序。sklearn.decomposition .PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=5)
Xd = pca.fit_transform(X)
np.set_printoptions(precision=3, suppress=True)
print(pca.explained_variance_ratio_)
![](https://img-blog.csdnimg.cn/img_convert/5543c1c2f340e0fa251658dcfb8cf296.png)
# 评估主成分分析抽取的特征在分类结果上的准确度。
dtc = DecisionTreeClassifier(random_state=14)
score = cross_val_score(dtc, Xd, y, scoring='accuracy')
print("The accuracy of pca is {0:1f}%".format(score.mean()*100))
![](https://img-blog.csdnimg.cn/img_convert/43d87278f620471645aaf4db3f5c5030.png)
from mpl_toolkits.mplot3d import Axes3D
data = ads.dropna(axis=0,how='any')
Y = data[1558]
classes = set(Y)
colors = ['red', 'green']
fig = plt.figure()
ax = Axes3D(fig)
for cur_class, color in zip(classes, colors):
mask = (Y == cur_class).values
ax.scatter(Xd[mask,0], Xd[mask,1],Xd[mask,2],color=color, label=int(cur_class),marker='o')
plt.legend()
plt.show()
![](https://img-blog.csdnimg.cn/img_convert/108c87c143a9f906c89618a8449b157b.png)
四、创建自己的转换器
转换器像极了转换函数。它接收一种形式的数据,输出另外一种形式。转换器可以用训练集训练,训练得到的参数可以用来转换测试数据集。
转化器两个关键函数:
fit():接收训练数据,设置内部参数。
transform():转换过程,接收训练数据集或相同格式的新数据集。
举例:转换器接收numpy数组作为输入,根据均值将其离散化。任何高于均值的特征值(训练集中)替换为1,小于或等于均值的替换为0。
TransformerMixin类:sklearn.base.TransformerMixin用来设置转换器API的类。
as_float_array函数:sklearn.utils.as_float_array判断输入类型是否合法的函数。
# 1.导入所需模块
from sklearn.base import TransformerMixin
from sklearn.utils import as_float_array
# 2.创建继承自mixin的类
class MeanDiscrete(TransformerMixin):
def fit(self, X):
X = as_float_array(X)
self.mean = X.mean(axis=0)
return self
def transform(self, X):
X = as_float_array(X)
assert X.shape[1] == self.mean.shape[0] # 检查输入的列数是否一致
X[X > self.mean] = 1
X[X <= self.mean] = 0
return X
mean_discreate = MeanDiscrete()
X_mean = mean_discreate.fit_transform(X)
五、单元测试
def test_meandiscrete():
X_test = np.array([[0, 2],
[3, 5],
[6, 8],
[9, 11],
[12, 14],
[15, 17],
[18, 20],
[21, 23],
[24, 26],
[27, 29]])
mean_discreate = MeanDiscrete()
mean_discreate.fit(X_test)
assert_array_equal(mean_discreate.mean, np.array(13.5, 15.5))
X_transformed = mean_discreate.transform(X_test)
X_expected = np.array([[0, 0],
[0, 0],
[0, 0],
[0, 0],
[0, 0],
[1, 1],
[1, 1],
[1, 1],
[1, 1],
[1, 1]])
test_meandiscrete()
六、组装
from sklearn.pipeline import Pipeline
# 第一步使用MeanDiscrete转换器
pipeline = Pipeline([('mean_discrete', MeanDiscrete()),
('classifier', DecisionTreeClassifier(random_state=14))])
# 第二步使用决策树分类器,然后进行交叉检验,输出结果
scores_mean_discrete = cross_val_score(pipeline, X, y, scoring='accuracy')
print("Mean Discrete performance:{0:3f}".format(scores_mean_discrete.mean()))