美文网首页我爱编程
用转换器提取特征(学习笔记一)

用转换器提取特征(学习笔记一)

作者: 糖逗ovo | 来源:发表于2018-01-07 19:47 被阅读0次

参考书目《Python数据挖掘入门与实践》

学习目的及意义

大多数数据挖掘算法都依赖于数值或类别型特征。所以,如何从数据集中抽取数值和类别型特征,并选出最佳特征,成为数据挖掘任务最为重要的一个环节。

降低特征数量的优点
  • 降低复杂度:随着特征数量的增加,很多数据挖掘算法需要更多的时间和资源。减少特征数量,是提高算法运行速度,减少资源使用的好方法。
  • 降低噪音:增加额外特征并不总会提升算法的表现。额外特征可能扰乱算法的正常工作,这些额外特征间的相关性和模式没有实际应用价值(这种情况在小数据集上很常见)。只选择合适的特征有助于减少出现没有实际意义的相关性的几率。
  • 增加模型可读性:根据成千上万个特征创建的模型来解答一个问题,对计算机来说很容易,但模型对我们自己来说就晦涩无比。因此,使用更少的特征,创建我们自己可以理解的模型,就很有必要。

数据来源及解释

http://archive.ics.uci.edu/ml/datasets/Adult
点击Data Folder链接。下载adult.data和adult.names文件。其中,adult.names文件中包含对数据的解释。(adult.data没有表头,需要参照adult.names)

adult.data中表头信息

读入数据并加入表头信息

import pandas as pd
adult = pd.read_csv('adult.csv', 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"])

去除包含na空值所在的行

adult.dropna(how='all', inplace=True)

设置inplace参数为真,表示改动当前数据框,而不是新建一个

数据处理和简单描述

  • 连续型数据
adult["Hours-per-week"].describe()

count 32561.000000
mean 40.437456
std 12.347429
min 1.000000
25% 40.000000
50% 40.000000
75% 45.000000
max 99.000000
Name: Hours-per-week, dtype: float64

  • 类别型特征
    类别型特征二值化后就变成了数值型特征
    二值化,例如:网球的话特征向量是[1, 0, 0],棒球[0, 1, 0],足球[0, 0, 1]。这些特征都只有两个取值,很多算法都可以把它们作为连续型特征使用。二值化的好处是,便于直接进行数字上的比较(例如计算个体之间的距离)。
  • 得到列的所有取值(不重复)
adult["Work-Class"].unique()

array([' State-gov', ' Self-emp-not-inc', ' Private', ' Federal-gov',
' Local-gov', ' ?', ' Self-emp-inc', ' Without-pay', ' Never-worked'], dtype=object)
数据集部分数据缺失,但不会影响这里的计算。

  • 离散化
    数值型特征可以通过离散化过程转换为类别型特征。但是,细节的丢失是离散化不好的一面,也是建模时需要考虑解决的问题。

确保特征值是不同的(基础性测试之一)

scikit-learn中的VarianceThreshold转换器可用来删除特征值的方差达不到最低标准的特征。
具体用法如下:

import numpy as np
X = np.arange(30).reshape((10, 3))
X

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]])

X[:,1] = 1
X

array([[ 0, 1, 2],
[ 3, 1, 5],
[ 6, 1, 8],
[ 9, 1, 11],
[12, 1, 14],
[15, 1, 17],
[18, 1, 20],
[21, 1, 23],
[24, 1, 26],
[27, 1, 29]])

from sklearn.feature_selection import VarianceThreshold
vt = VarianceThreshold()
Xt = vt.fit_transform(X)
Xt

array([[ 0, 2],
[ 3, 5],
[ 6, 8],
[ 9, 11],
[12, 14],
[15, 17],
[18, 20],
[21, 23],
[24, 26],
[27, 29]])

print(vt.variances_)

[ 74.25 0. 74.25]

选择最佳特征

  • 选取下述特征,从pandas数据框中抽取一部分数据。
X = adult[["Age", "Education-Num", "Capital-gain", "Capital-loss",
"Hours-per-week"]].values
  • 创建目标类别列表,判断Earnings-Raw(税前收入)是否达到五万美元。
y = (adult["Earnings-Raw"] == ' >50K').values

计算相关性有两种方法
1.使用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)
  • 得到每一列的相关性,可以知道都使用了哪些特征。
print(transformer.scores_)

[ 8.60061182e+03 2.40142178e+03 8.21924671e+07 1.37214589e+06
6.47640900e+03]
相关性最好(值最大)的分别是第一、三、四列,分别对应着Age(年龄)、Capital-Gain(资本收益)和Capital-Loss(资本损失)三个特征。从单变量特征选取角度来说,这些就是最佳特征。
2.皮尔逊(Pearson)相关系数

  • 从SciPy导入pearsonr函数
from scipy.stats import pearsonr

SciPy的pearsonr函数参数为两个数组,但要注意的是第一个参数x为一维数组。我们来实现一个包装器函数,这样就能像前面那样处理多维数组。

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

[ 0.2340371 0.33515395 0.22332882 0.15052631 0.22968907]
返回的特征跟用卡方检验计算相关性得到的特征不一样!这回得到的是第一、二、五列:Age、Education和Hours-per-week。
特征是最好的这个问题没有标准答案——取决于度量标准。

比较两种方法
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("Chi2 performance: {0:.3f}".format(scores_chi2.mean()))
print("Pearson performance: {0:.3f}".format(scores_pearson.mean()))

Chi2 performance: 0.829
Pearson performance: 0.771

请注意实验结果也只表明对于特定分类器和(或)特征子集效果更好——在数据挖掘领域,一种方法在任何情况下都比另一种方法好的情况几乎没有!

比较结果:chi2方法的平均正确率为0.83,而皮尔逊相关系数正确率为0.77。用卡方检验得到的特征组合效果更好!

相关文章

网友评论

    本文标题:用转换器提取特征(学习笔记一)

    本文链接:https://www.haomeiwen.com/subject/abopnxtx.html