特征工程
1 机器学习
机器学习简单来说就是选择一种学习算法,从数据中学习并建立成模型来对新的数据进行预测的计算机科学 。
机器学习是人工智能的一个分支。人工智能的研究是从以“推理”为重点—以“知识”为重点—再到以“学习”为重点,一条自然、清晰的脉络。机器学习是实现人工智能的一个途径,即以机器学习为手段解决人工智能中的问题。机器学习算法是一类从数据中自动分析获得规律(模型),并利用规律对未知数据进行预测的算法。
我们的数据量越来越多,硬件越来越强悍。急需要解放人的生产力,自动去寻找数据的规律。解决更多专业领域的问题。机器学习已广泛应用于数据挖掘、计算机视觉、自然语言处理、生物特征识别、搜索引擎、医学诊断、检测信用卡欺诈、证券市场分析、DNA序列测序、语音和手写识别、战略游戏和机器人等领域。
机器学习适用于以下等问题:
- 不存在已知算法解决方案的复杂问题
- 需要大量手动调整或者规则列表超长的问题
- 可以适应环境波动的系统
1.1 基础概念
标签是提供给算法的包含所需解决方案的训练数据,是我们要预测的事物,即简单线性回归中的 y 变量。
样本每一条数据叫一个样本,即数据的特定实例:x
。
属性加上其值 就是特征,也可以理解为输入变量,即简单线性回归中的 x
变量。
关注预测值和真实值之间的差别,就是通过给定的特征来预测一个目标数值。
用于训练模型的数据叫训练集
用于测试模型精度的数据叫测试集
从字面的意义上理解就是过度拟合的意思,常发生在线性分类器或者线性模型的训练和预测当中。过拟合的原理就是机器学习算法过度学习了训练集数据。反之欠拟合。
是指创建或学习模型。也就是说,向模型展示有标签样本,让模型逐渐学习特征与标签之间的关系。通过训练数据找到算法最合适的参数。
1.2 机器学习执行流程
-
理解实际问题,抽象为机器学习能处理的数学问题
理解实际业务场景问题是机器学习的第一步, 机器学习中特征工程和模型训练都是非常费时的,深入理解要处理的问题,能避免走很多弯路。理解问题,明确可以获得的数据。
-
获取数据
获取数据包括获取原始数据,以及从原始数据中经过特征工程,从原始数据中提取训练、测试数据。数据数量不要有多个数量级的差距。不仅如此还要对评估数据的量级,样本数量、特征数量,估算训练模型对内存的消耗。
-
特征工程
特征工程包括从原始数据中特征构建、特征提取、特征选择。特征工程做的好能发挥原始数据的最大效力,往往能够使得算法的效果和性能得到显著的提升,有时能使简单的模型的效果比复杂的模型效果好。
-
模型训练、诊断、调优
对算法的理解、调节参数,使模型达到最优。模型诊断中至关重要的是判断过拟合、欠拟合,常见的方法是绘制学习曲线,交叉验证。通过增加训练的数据量、降低模型复杂度来降低过拟合的风险,提高特征的数量和质量、增加模型复杂来防止欠拟合。诊断后的模型需要进行进一步调优, 调优后的新模型需要重新诊断,这是一个反复迭代不断逼近的过程,需要不断的尝试,进而达到最优的状态。
-
模型预测,获得结果
我们通过训练数据集得到模型,然后将想要预测的数据加入模型中进行测试,得到测试结果。
这就是我们大致的机器学习流程。
1.3 数据处理与特征工程
“数据决定了机器学习的上限,而算法只是尽可能逼近这个上限”,这句话很好的阐述了数据在机器学习中的重要性。大部分直接拿过来的数据都是特征不明显的、没有经过处理的或者说是存在很多无用的数据,那么需要进行一些特征处理,特征的缩放等等,满足训练数据的要求。
数据处理主要解决的问题是:
-
数据量不足
-
训练数据不具备代表性
-
质量差的数据
-
特征筛选
机器学习的关键是 提取出一组好的用来训练的特征集,这个过程叫特征工程,包括:
-
特征选择 从现有特征中选择最有用的特征进行训练
-
特征提取 将现有特征进行整合,产生更有用的特征,比 如降维算法
-
通过收集 新数据创造新特征
2 Scikit-learn 与特征工程
2.1 Scikit-learn概述
2007年发布以来,scikit-learn已经成为最给力的Python机器学习库(library)了。scikit-learn支持的机器学习算法包括分类,回归,降维和聚类。还有一些特征提取(extracting features)、数据处理(processing data)和模型评估(evaluating models)的模块。作为Scipy库的扩展,scikit-learn也是建立在Python的NumPy和matplotlib库基础之上。NumPy可以让Python支持大量多维矩阵数据的高效操作,matplotlib提供了可视化工具,SciPy带有许多科学计算的模型。
- Python语言的机器学习工具
- 可在不同的上下文中重用
- 基于NumPy、SciPy和matplotlib构建
- 开源、商业可用 - BSD许可
2.2 数据的特征工程
从数据中抽取出来的对预测结果有用的信息,通过专业的技巧进行数据处理,使得特征能在机器学习算法中发挥更好的作用。优质的特征往往描述了数据的固有结构。 最初的原始特征数据集可能太大,或者信息冗余,因此在机器学习的应用中,一个初始步骤就是选择特征的子集,或构建一套新的特征集,减少功能来促进算法的学习,提高泛化能力和可解释性。
2.2.1 特征工程的意义
- 更好的特征意味着更强的鲁棒性
- 所谓“鲁棒性”,指控制系统在一定(结构,大小)的参数摄动下,维持其它某些性能的特性。
- 更好的特征意味着只需用简单模型
- 更好的特征意味着更好的结果
2.2.2 特征处理
特征工程中最重要的一个环节就是特征处理,特征处理包含了很多具体的专业技巧
- 单个特征
- 归一化
- 标准化
- 缺失值
- 多个特征
- 降维
类 | 功能 | 说明 |
---|---|---|
StandardScaler |
无量纲化 | 标准化,基于特征矩阵的列,将特征值转换至服从标准正态分布 |
MinMaxScaler |
无量纲化 | 区间缩放,基于最大最小值,将特征值转换到[0, 1]区间上 |
Normalizer |
归一化 | 基于特征矩阵的行,将样本向量转换为“单位向量” |
Binarizer |
二值化 | 基于给定阈值,将定量特征按阈值划分 |
OneHotEncoder |
哑编码 | 将定性数据编码为定量数据 |
Imputer |
缺失值计算 | 计算缺失值,缺失值可填充为均值等 |
PolynomialFeatures |
多项式数据转换 | 多项式数据转换 |
FunctionTransformer |
自定义单元数据转换 | 使用单变元的函数来转换数据函数来转换数据 |
2.2.3 特征选择与特征抽取
如果说特征处理其实就是在对已有的数据进行运算达到我们目标的数据标准。特征抽取则是将任意数据格式(例如文本和图像)转换为机器学习的数字特征。而特征选择是在已有的特征中选择更好的特征。后面会详细介绍特征选择主要区别于降维。
2.3 数据的来源与类型
通过爬虫爬取、购买数据、网上的开放数据等。
按照机器学习的数据分类我们可以将数据分成:
- 标称型:标称型目标变量的结果只在有限目标集中取值,如真与假
- 数值型:数值型目标变量则可以从无限的数值集合中取值,
按照数据的本身分布特性
- 离散型【无规律】
- 连续型【有规律】
- 离散变量是指其数值只能用自然数或整数单位计算的则为离散变量。例如,班级人数
- 连续型数据是指在指定区间内可以是任意一个数值。例如,票房数据
2.4 数据的特征抽取
现实世界中多数特征都不是连续变量,比如分类、文字等,为了对非连续变量做特征表述,需要对这些特征做数学化表述,因此就用到了特征提取. sklearn.feature_extraction提供了特征提取的很多方法
2.4.1 分类特征提取变量
我们将城市和环境作为字典数据,来进行特征的提取。将映射列表转换为Numpy数组。
from sklearn.feature_extraction import DictVectorizer
# sparse 是否转换为scipy.sparse矩阵表示,默认开启,如果结果不用toarray,请开启sparse= False
onehot = DictVectorizer(sparse= False)
instances = [{
'city': '北京', 'temperature': 100}, {
'city': '上海', 'temperature': 60}, {
'city': '深圳', 'temperature': 30}]
# 应用并转化映射列表X,y为目标类型
X = onehot.fit_transform(instances)
# 将Numpy数组或scipy.sparse矩阵转换为映射列表
Y = onehot.inverse_transform(X)
2.4.2 文本特征处理(只限英文)
文本的特征提取应用于很多方面,比如说文档分类、垃圾邮件分类和新闻分类。那么文本分类是通过词是否存在、以及词的概率(重要性)来表示。
from sklearn.feature_extraction.text import CountVectorizer
# 构建文章【英文】
content = ['This is the first document.', 'This is the second second document.', 'And the third one.', 'Is this the first document? i x y']
#构建实例
con_vet = CountVectorizer()
#进行提取词语
x = con_vet.fit_transform(content)
print(x) # (0, 1) 1 (文章下标,分词下标) 词在文章中出现的次数 sparse矩阵
print(x.toarray()) # 将 sparse矩阵 转化为 数组
# 获取提取到词语
names = con_vet.get_feature_names()
print(names) # 提取到的词
- 处理中文,我们可以使用jieba分词,进行分词之后,进行处理
# pip install jieba
import jieba
from sklearn.feature_extraction.text import CountVectorizer
# 构建文章【中文】
content = ["今天阳光真好","我要去看北京天安门","逛完天安门之后我要去王府井","吃烤蝎子与烤蜈蚣","晚上去后海蹦个迪"]
content_list = []
for tmp in content:
# 使用精确模式进行分词 cut_all默认为精确模式
res = jieba.cut(tmp,cut_all= False)
res_str = ','.join(res)
content_list.append(res_str)
#构建实例
con_vet = CountVectorizer()
#进行提取词语
x = con_vet.fit_transform(content_list)
print(x) # (0, 1) 1 (文章下标,分词下标) 词在文章中出现的次数 sparse矩阵
print(x.toarray()) # 将 sparse矩阵 转化为 数组
# 获取提取到词语
names = con_vet.get_feature_names()
print(names) # 提取到的词
2.5 特征预处理
单个特征
-
归一化
归一化首先在特征(维度)非常多的时候,可以防止某一维或某几维对数据影响过大,也是为了把不同来源的数据统一到一个参考区间下,这样比较起来才有意义,其次可以程序可以运行更快。】常用的方法是通过对原始数据进行线性变换把数据映射到[0,1]之间,变换的函数为:
X ′ = x − m i n m a x − m i n X^{'}{=}\frac{x-min}{max-min} X′=max−minx−min
其中min是样本中最小值,max是样本中最大值,注意在数据流场景下最大值最小值是变化的,另外,最 大值与最小值非常容易受异常点影响,所以这种方法鲁棒性较差,只适合传统精确小数据场景。
-
标准化
将数据转化为同一量级,避免量级对结果产生不利的影响①离差标准化②标准差标准化③小数定标标准化常用的方法是z-score标准化,经过处理后的数据均值为0,标准差为1,处理方法是:
X ′ = x − μ σ X^{'}{=}\frac{x-\mu}{\sigma} X′=σx−μ
其中μ是样本的均值,σ是样本的标准差,它们可以通过现有的样本进行估计,在已有的样本足够多的情 况下比较稳定,适合嘈杂的数据场景
-
缺失值
由于各种原因,许多现实世界的数据集包含缺少的值,通常编码为空白,NaN或其他占位符。然而,这样的数据集与scikit的分类器不兼容,它们假设数组中的所有值都是数字,并且都具有和保持含义。使用不完整数据集的基本策略是丢弃包含缺失值的整个行和/或列。然而,这是以丢失可能是有价值的数据(即使不完整)的代价。更好的策略是估算缺失值,即从已知部分的数据中推断它们。
- 删除 ----会对数据产生很大的影响,造成数据缺失,所以在数据大部分为缺失值,才使用删除法;
- 填充 — 填充之后对结果影响不大的情况,可以使用(均值,中位数,众数);
- 插值(线性插值;多项式插值;样条插值)
多个特征
- PCA(Principal component analysis),主成分分析。特点是保存数据集中对方差影响最大的那些特征,PCA极其容易受到数据中特征范围影响,所以在运用PCA前一定要做特征标准化,这样才能保证每维度特征的重要性等同。
class PCA(n_components, whiten, svd_solver)
"""
主成成分分析
:param n_components: int, float, None or string
这个参数可以帮我们指定希望PCA降维后的特征维度数目。最常用的做法是直接指定降维到的维度数目,此时n_components是一个大于1的整数。
我们也可以用默认值,即不输入n_components,此时n_components=min(样本数,特征数)
:param whiten: bool, optional (default False)
判断是否进行白化。所谓白化,就是对降维后的数据的每个特征进行归一化。对于PCA降维本身来说一般不需要白化,如果你PCA降维后有后续的数据处理动作,可以考虑白化,默认值是False,即不进行白化
:param svd_solver:
选择一个合适的SVD算法来降维,一般来说,使用默认值就够了。
"""
2.6 数据特征选择
降维本质上是从一个维度空间映射到另一个维度空间,特征的多少别没有减少,当然在映射的过程中特征值也会相应的变化。举个例子,现在的特征是1000维,我们想要把它降到500维。降维的过程就是找个一个从1000维映射到500维的映射关系。原始数据中的1000个特征,每一个都对应着降维后的500维空间中的一个值。假设原始特征中有个特征的值是9,那么降维后对应的值可能是3。而对于特征选择来说,有很多方法:
- Filter(过滤式):VarianceThreshold
- Embedded(嵌入式):正则化、决策树
- Wrapper(包裹式)
其中过滤式的特征选择后,数据本身不变,而数据的维度减少。而嵌入式的特征选择方法也会改变数据的值,维度也改变。Embedded方式是一种自动学习的特征选择方法,后面讲到具体的方法的时候就能理解了。
特征选择主要有两个功能:
- 减少特征数量,降维,使模型泛化能力更强,减少过拟合
- 增强特征和特征值之间的理解
3 sklearn 数据集
sklearn中的数据集类,模块包括用于加载数据集的实用程序,包括加载和获取流行参考数据集的方法。它还具有一些人工数据生成器。
3.1 数据集概述
datasets.load_*() # 获取小规模数据集,数据包含在datasets里
# 获取大规模数据集,需要从网络上下载,函数的第一个参数是data_home,表示数据集下载的目录,默认是 ~/scikit_learn_data/,要修改默认目录,可以修改环境变量SCIKIT_LEARN_DATA
datasets.fetch_*()
datasets.make_*() # 本地生成数据集
-
load*和 fetch* 函数返回的数据类型是 datasets.base.Bunch,本质上是一个 dict,它的键值对可用通过对象的属性方式访问。主要包含以下属性:
- data:特征数据数组,二维 数组
- target:标签数组,一维 数组
- DESCR:数据描述
- feature_names:特征名
- target_names:标签名
-
数据集目录可以通过datasets.get_data_home()获取,clear_data_home(data_home= None)删除所有下载数据
-
datasets.get_data_home(data_home= None)
返回scikit学习数据目录的路径。这个文件夹被一些大的数据集装载器使用,以避免下载数据。默认情况下,数据目录设置为用户主文件夹中名为“scikit_learn_data”的文件夹。或者,可以通过“SCIKIT_LEARN_DATA”环境变量或通过给出显式的文件夹路径以编程方式设置它。’〜'符号扩展到用户主文件夹。如果文件夹不存在,则会自动创建。
-
sklearn.datasets.clear_data_home(data_home= None)
删除存储目录中的数据
-
3.2 获取小数据集
- 加载虹膜数据集
名称 | 数量 |
---|---|
类别 | 3 |
特征 | 4 |
样本数量 | 150 |
每个类别数量 | 50 |
from sklearn.datasets import load_iris
data = load_iris()
# 查看数据
data
- 加载数字数据集
名称 | 数量 |
---|---|
类别 | 10 |
特征 | 64 |
样本数量 | 1797 |
from sklearn.datasets import load_digits
digits = load_digits()
# 数据格式
digits.data.shape
# 标签
digits.target
# 标签名
digits.target_names
# 数据展示
digits.images
- 加载波士顿房价数据集
名称 | 数量 |
---|---|
目标类别 | 5-50 |
特征 | 13 |
样本数量 | 506 |
from sklearn.datasets import load_boston
boston = load_boston()
# 数据格式
boston.data.shape
# 数据列名
boston.feature_names
3.3 获取大数据集
- 加载20个新闻组数据集中的文件名和数据【14兆左右】
参数说明 | |
---|---|
subset | ‘train’或者’test’,‘all’,可选,选择要加载的数据集:训练集的“训练”,测试集的“测试”,两者的“全部”,具有洗牌顺序 |
data_home | 可选,默认值:无,指定数据集的下载和缓存文件夹。如果没有,所有scikit学习数据都存储在’〜/ scikit_learn_data’子文件夹中 |
categories | 无或字符串或Unicode的集合,如果没有(默认),加载所有类别。如果不是无,要加载的类别名称列 |