数据挖掘实战(六)--用转换器抽取特征

一、特征抽取

  1. 特征抽取是数据挖掘任务最为重要的一个环节。特征可用于建模, 模型以机器挖掘算法能够理解的近似的方式来表示现实 。

  1. 特征分为数值型特征类别型特征

数值型特征通常被看做是有顺序的。数值型特征又分为连续特征序数特征。可以用连续特征计算平均值、标准差、最大值和最小值。

类别型特征也可以称为名义特征(nominal)。对于名义特征而言,几个值之间要么相同要么不同。

  1. 数值型特征与类别型特征的相互转化:类别型特征二值化后就变成了数值型特征,数值型特征也可以通过离散化过程转换为类别型特征。

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

二、特征选择

  1. 特征选择的原因

降低复杂度、降低噪音、增加模型可读性。

拿到数据后,先做下简单、直接的分析。如确保特征值是不同的。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_) # 输出每一列的方差

输出Xt后,我们发现第二列消失了,输出每一列的方差结果表明第一、三列包含有价值信息,第二列方差为0,不包含具有区别意义的信息。

  1. 如何选择最佳特征

方法是不要找表现好的子集,而只是去找表现好的单个特征(单变量),依据是它们各自所能达到的精确度。分类任务通常是这么做的,我们一般只要测量变量和目标类别之间的某种相关性就行。

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

相关性最好的分别是第一、三、四列,分别对应着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_)

返回的特征跟用卡方检验计算相关性得到的特征不一样!这回得到的是第一、二、五列 。

分别用卡方检验皮尔逊相关系数得到的特征评估分类准确度

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

三、创建特征

用不同的方法从已有特征中发掘新特征,比如前面用到的一位有效编码(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_)
# 评估主成分分析抽取的特征在分类结果上的准确度。
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))
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()

四、创建自己的转换器

转换器像极了转换函数。它接收一种形式的数据,输出另外一种形式。转换器可以用训练集训练,训练得到的参数可以用来转换测试数据集。

转化器两个关键函数

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值