数据挖掘(五)
文章目录
-
- 数据挖掘(五)
-
- 特征抽取
-
- 在模型中表示事实
- 通用的特征创建模式
- 创建好的特征
- 特征选择
- 创建特征
- 创建自己的转换器
-
- 转换器API
- 完整代码1
- 完整代码2
数据集可以是用特征来描述的,可以使交易类型的数据,此外还有其他数据集,比如文本、图像、声音、视频甚至是真实的物体。大多数数据挖掘算法都依赖于数值或者类别性特征。这表明在使用数据挖掘算法处理之前,需要找到一种表示它们的方法。
特征抽取
特征抽取是数据挖掘任务最为重要的一环,对最终结果的影响要高于数据挖掘算法本身。关于如何选区好的特征,还没有严格、快捷的规则可寻。创建好的规则离不开直觉,还需要专业领域知识和数据挖掘经验,光有这些还不够,还得不停地尝试、摸索,在试错中前进。
在模型中表示事实
-
不是所有数据集都是用特征来表示的,数据集可以使一位作家写的全部书籍,也可以是电影胶片,还可以是馆藏的历史文物。我们对以上数据集可以做数据挖掘,对于作家的作品,我们想知道这位作家写过哪些主题;对于电影,我们想知道女性形象怎么塑造的;对于文物,我们想要知道它们是何方产物。我们没办法把实物直接塞进决策树来得到结果。
-
只有先把现实用特征表示出来,才能借助数据挖掘的力量找到问题的答案。特征可以用于建模,模型以机器挖掘算法能够理解的近似的方式来表示现实。模型描述了客观世界中对象的某些方面。特征选择的优点在于降低真实世界的复杂度,模型比现实更容易操纵。实物的复杂性对目前的算法来说太过复杂,我们可以使用简洁的模型来表示实物。
-
简化以数据挖掘应用的目标为核心,降低复杂度有好处,但是会忽略很多细节。我们要关注如何用模型来表示现实,多考虑数据挖掘的目标,而不是轻率地用我们过去用过的特征。不是所有的特征必须是数值或类别型值,直接用于文本、图像和其他数据结构的算法已经研究出来了。
-
用[Adult数据集](Adult - UCI Machine Learning Repository)演示如何借助特征为复杂的世界建模。
import os
import pandas as pd
data_folder = os.path.join(os.getcwd(), 'adult')
adult_filename = os.path.join(data_folder, 'adult.data')
# 加载数据集文件,文件末尾有两处空行,pandas默认会把倒数第二行空行作为一条有效数据读取
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"])
# 删除包含无效数据的行,inplace=True表示改动当前数据框,而不是新建一个
adult.dropna(how='all', inplace=True)
# 查看所有特征的名称
adult.columns
Index([‘Age’, ‘Work-Class’, ‘fnlwgt’, ‘Education’, ‘Education-Num’, ‘Marital-Status’, ‘Occupation’, ‘Relationship’, ‘Race’, ‘Sex’, ‘Capital-gain’, ‘Capital-loss’, ‘Hours-per-week’, ‘Native-Country’, ‘Earnings-Raw’], dtype=‘object’)
通用的特征创建模式
- 特征创建方法多种多样,但其中有一些是适用于不同学科的通用模式。选择合适的特征是项技术活,需要考虑特征和最终结果之间的相互关系。一些通用特征关注研究对象的物理属性。空间属性比如对象的长、宽、高,重量和密度,年龄、使用年限或成分,种类,品质。另一些特征可能与对象的使用后历史相关,比如生产商、出版商或创造者,生产历史,使用方法。还有一些特征从组成成分角度。次级成分的频率,比如一本书中某个单词的词频;次级成分的数量或成分种类的数量;次级成分的平均大小,比如平均句长。
- 序数特征可对其排序、分组,特征可以是数值或类别型特征。数值特征通常是有顺序的。adult数据集包含连续特征和序数特征。比如Hours-per-week特征表示一个人每周的工作时间。这个特征可以用来计算平均工作时间、标准差、最大值和最小值。这些统计方法对其他特征比如受教育程度可能没有意义,但是我们可以找到一种近似的表示方法,比如受教育年限特征,它的取值基本上就是每个教育阶段的年限。
# pandas提供了常见统计量的计算方法
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
adult['Education-Num'].median()
10.0
- 特征值也可以是类别型的,比如一个球可以是足球、网球等。类别型特征也叫做名义特征。几个值之间要么相同要么不同。类别型特征二值化后就变成了数值型特征,二值化后可以直接进行数字上的比较。Adult数据集包含了一些类别型特征,比如工作Work-Class,其中它的有些值可以进行量级上的比较,比如不同的就业状况影响收入。数值型特征也可以进行离散化转换为类别型特征。比如高于1.7m的人我们称其为高个子。
#使用unique函数获得所有工作的情况,发现部分数据确实,但是不会影响这里的计算
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)
# 创建LongHours时长特征用来表示一个人每周工作时长是否多于40个小时,把连续值转换为类别型特征
adult['LongHours'] = adult['Hours-per-week'] > 40
创建好的特征
建模过程中需要对真实世界中的对象进行简化,这样会导致信息的丢失,这就是为什么没有一套能够用于任何数据集的通用的数据挖掘方法。数据挖掘的行家手里需要拥有数据来源领域的知识,如果没有就需要去掌握。我们需要在弄清楚问题是什么,有哪些可用数据后,才能创建解决问题所需要的模型。
特征选择
通常特征数量很多,但是我们只想选用其中一小部分,这样可以降低复杂度、降低噪音和增加模型可读性。开展数据挖掘工作前,需要做一些基础性测试,比如确保特征值是不同的。
scikit-learn
中的VarianceThreshold转换器可以删除特征值的方差达不到最低标准的特征。无论何时,拿到数据后,先做下类似简单直接的分析,对数据的特点做到心中有数。
import numpy as np
# np.arange(30)返回0~29的连续整数数组
# reshape方法将数组变成10行3列的矩阵,可以看成10个个体、3个特征的数据集
X = np.arange(30).reshape((10, 3))
# 把第二列的数值都为1,那么第一、三列特征值的方差很大,第二列的方差为0
X[:,1] = 1
# 创建VarianceThreshold转换器处理数据集后第二列消失了
from sklearn.feature_selection import VarianceThreshold
vt = VarianceThreshold()
Xt = vt.fit_transform(X)
# 输出每一列的方差
print(vt.variances_)
- 选择最佳特征与解决数据挖掘问题自身相关,计算量很大。一个变通方法是不要找表现好的子集,而只是去找表现好的单个特征,依据是它们各自能达到的精确度。分类任务通常是这样的,我们一般只要测试变量和目标类别之间的某种相关性。
scikit-learn
提供了几个用于选择单变量特征的转换器,SelectKBest返回k个最佳特征,SelectPercentile返回表现最佳的前r%个特征。单个特征和某一类别之间相关性常用的计算方法有卡方检验、互信息和信息熵。
# 从pandas数据框中抽取一部分数据,判断税前收入Earnings-Raw是否达到5万美元,创建目标类别列表,如果达到类别为True
X = adult[['Age', 'Education-Num', 'Capital-gain', 'Capital-loss', 'Hours-per-week']].values
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)
# 输出每一列的相关性,相关性最好的是第一、三、五列分别对应着Age年龄、Capital-Gain资本收益和Hours-per-week每周工作时长三个特征
print(transformer.scores_)
[8.60061182e+03 2.40142178e+03 8.21924671e+07 1.37214589e+06 6.47640900e+03]
- 我们还可以用其他方法计算相关性,比如皮尔逊相关系数,用于科学计算的
SciPy
库实现了该方法。其中p值为-1到