机器学习是从数据中自动分析获得规律(模型),并利用规律对未知数据进行预测或分类。
机器学习是实现人工智能的一种技术手段。
模型可以理解为特殊的对象,在对象内部集成或封装了某种形式的方程,不过这些方程还无法进行求解。
模型的作用是用于对未知数据进行预测或分类。
样本数据是整体数据的一部分,在一定程度上可以反映出整体数据所蕴含的某些规律。
样本数据包括特征和标签。
特征是方程输入的自变量,标签是方程输出的因变量。
样本数据的载体
样本数据一般存储于文件中,例如csv,而不会存储于数据库中。
原因:
训练模型是将样本数据输入到模型的方程中,获得方程的参数,使得方程可以求解。
模型实现的预测或分类可以理解为向模型的方程中输入数据进行计算的结果。
有监督学习
向模型输入的样本数据中包含数据和标签,获得能够将数据映射到标签的方程。
无监督学习
向模型输入的样本数据中只需要包含特征数据,没有任何标签。
数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。
特征工程是指将原始数据转变为模型可以直接使用的训练数据的过程,纯净的训练数据能够更好地反映出模型的潜在规律。
特征工程的目的是最大限度地从原始数据中提取出有价值的特征以供模型使用,使得模型能够逼近机器学习的上限,因此特征工程就是对特征的处理,直接影响模型的性能和输出结果。
特征抽取是对数据进行某种变换以突出代表性特征的操作。
对于非数值型特征的特征抽取称为特征值化。
特征值化是将非数值型特征转换成数值型特征。
特征值化过程中将训练文本中的词汇单独视为一列特征,只考虑每个词的出现次数,不考虑其出现顺序,每一行表示一个训练文本的词频统计结果。
CountVectorizer实例化的对象用于对文本数据进行特征值化处理。
from sklearn.feature_extraction.text import CountVectorizer
demo_list = ['Lift is short, Ben love python.', 'Lift is too long, Ben hate python.']
cv = CountVectorizer()
cv_fit = cv.fit_transform(demo_list)
print(cv.get_feature_names()) # 获取特征列名,重复的词汇只统计1次。
'''
['ben', 'hate', 'is', 'lift', 'long', 'love', 'python', 'short', 'too']
'''
print(cv_fit) # Sparse矩阵
'''
(0, 3) 1
(0, 2) 1
(0, 7) 1
(0, 0) 1
(0, 5) 1
(0, 6) 1
(1, 3) 1
(1, 2) 1
(1, 0) 1
(1, 6) 1
(1, 8) 1
(1, 4) 1
(1, 1) 1
'''
print(cv_fit.toarray()) # 将结果转化为数组
'''
[[1 0 1 1 0 1 1 1 0]
[1 1 1 1 1 0 1 0 1]]
'''
print(cv_fit.toarray().sum(axis=0)) # 统计每个词出现的次数
'''
[2 1 2 2 1 1 2 1 1]
'''
print(cv.inverse_transform(cv_fit.toarray())) # 将特征矩阵还原成原始数据
'''
[array(['ben', 'is', 'lift', 'love', 'python', 'short'], dtype='
对字典数据进行特征值化,将由特征与值的映射字典组成的列表转换成向量。
from sklearn.feature_extraction import DictVectorizer
demo_list = [
{
'city': 'BJ', 'temp': 33},
{
'city': 'GZ', 'temp': 42},
{
'city': 'SH', 'temp': 40}
]
dv = DictVectorizer(sparse=False)
dv_fit = dv.fit_transform(demo_list) # 进行特征值化
print(type(dv_fit)) #
print(dv_fit) # 返回sparse矩阵
'''
[[ 1. 0. 0. 33.]
[ 0. 1. 0. 42.]
[ 0. 0. 1. 40.]]
'''
print(dv.get_feature_names()) # 获取特征列名
'''
['city=BJ', 'city=GZ', 'city=SH', 'temp']
'''
print(dv.inverse_transform(dv_fit)) # 将特征矩阵还原成原始数据
'''
[{'city=BJ': 1.0, 'temp': 33.0}, {'city=GZ': 1.0, 'temp': 42.0}, {'city=SH': 1.0, 'temp': 40.0}]
'''
稀疏矩阵(sparse matrix),0元素的数量远多于非0元素的数量,且非0元素的分布没有规律。
dv = DictVectorizer()
dv = DictVectorizer(sparse=True) # 默认值
from sklearn.feature_extraction import DictVectorizer
demo_list = [
{
'city': 'BJ', 'temp': 33},
{
'city': 'GZ', 'temp': 42},
{
'city': 'SH', 'temp': 40}
]
dv = DictVectorizer()
# dv = DictVectorizer(sparse=True)
dv_fit = dv.fit_transform(demo_list) # 进行特征值化
print(type(dv_fit)) #
print(dv_fit) # 返回的是sparse矩阵
'''
(0, 0) 1.0
(0, 3) 33.0
(1, 1) 1.0
(1, 3) 42.0
(2, 2) 1.0
(2, 3) 40.0
'''
print(dv.get_feature_names()) # 获取特征列名
'''
['city=BJ', 'city=GZ', 'city=SH', 'temp']
'''
print(dv.inverse_transform(dv_fit)) # 将特征矩阵还原成原始数据
'''
[{'city=BJ': 1.0, 'temp': 33.0}, {'city=GZ': 1.0, 'temp': 42.0}, {'city=SH': 1.0, 'temp': 40.0}]
'''
One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都拥有独立的寄存器位,并且在任意时候只有一位有效。
Sparse矩阵中的0和1就是One-Hot编码。
One-Hot编码,主要用于对非数值型的数据进行特征值化处理。
优点:处理的结果中特征之间都是独立的,没有权重或优先级的差别。
import pandas as pd
df = pd.DataFrame([
['green', 'M', 20, 'class1'],
['red', 'L', 21, 'class2'],
['blue', 'XL', 30, 'class3']])
df.columns = ['color', 'size', 'weight', 'class label']
'''
color size weight class label
0 green M 20 class1
1 red L 21 class2
2 blue XL 30 class3
'''
# One-Hot编码
pd.get_dummies(df['color'])
'''
blue green red
0 0 1 0
1 0 0 1
2 1 0 0
'''
pd.concat((pd.get_dummies(df['color']), df), axis = 1)
'''
blue green red color size weight class label
0 0 1 0 green M 20 class1
1 0 0 1 red L 21 class2
2 1 0 0 blue XL 30 class3
'''
from sklearn.feature_extraction.text import CountVectorizer
demo_list = ['人生苦短,我用Python。','人生漫长,不用Python。']
cv = CountVectorizer()
cv_fit = cv.fit_transform(demo_list)
print(cv.get_feature_names())
'''
['不用python', '人生漫长', '人生苦短', '我用python']
'''
print(cv_fit.toarray())
'''
[[0 0 1 1]
[1 1 0 0]]
'''
手动加入空格
from sklearn.feature_extraction.text import CountVectorizer
demo_list = ['人生 苦短,我用 Python。','人生 漫长,不用 Python。']
cv = CountVectorizer()
cv_fit = cv.fit_transform(demo_list)
print(cv.get_feature_names())
'''
['python', '不用', '人生', '我用', '漫长', '苦短']
'''
print(cv_fit.toarray())
'''
[[1 0 1 1 0 1]
[1 1 1 0 1 0]]
'''
可以看出,CountVectorizer在对中文的特征提取过程中无法正确识别中文词汇,仅通过标点符号或空格等分隔符对文本数据进行特征抽取。
import jieba
demo_str = '“拳愿竞技”是企业、商人们赌上巨额利益,雇用斗技者并令其对打之空手格斗竞技。'
seg_list = list(jieba.cut(demo_str))
print(seg_list)
'''
['“', '拳愿', '竞技', '”', '是', '企业', '、', '商人', '们', '赌', '上', '巨额', '利益', ',', '雇用', '斗技', '者', '并', '令', '其', '对', '打', '之', '空手', '格斗', '竞技', '。']
'''
print('/'.join(seg_list))
'''
“/拳愿/竞技/”/是/企业/、/商人/们/赌/上/巨额/利益/,/雇用/斗技/者/并/令/其/对/打/之/空手/格斗/竞技/。
'''
data1_str = '“拳愿竞技”是企业、商人们赌上巨额利益,雇用斗技者并令其对打之空手格斗竞技。'
data2_str = '原为平息商人斗争之手段,始于江户中期,并传承至现代。'
data1_seg_list = list(jieba.cut(data1_str))
data2_seg_list = list(jieba.cut(data2_str))
data1_seg_str = ' '.join(data1_seg_list)
data2_seg_str = ' '.join(data2_seg_list)
data_total_seg_list = [data1_seg_str, data2_seg_str]
# 特征值化处理
cv = CountVectorizer()
cv_fit = cv.fit_transform(data_total_seg_list)
print(cv.get_feature_names())
'''
['中期', '企业', '传承', '利益', '商人', '始于', '巨额', '平息', '手段', '拳愿', '斗争', '斗技', '格斗', '江户', '现代', '空手', '竞技', '雇用']
'''
print(cv_fit.toarray())
'''
[[0 1 0 1 1 0 1 0 0 1 0 1 1 0 0 1 2 1]
[1 0 1 0 1 1 0 1 1 0 1 0 0 1 1 0 0 0]]
'''
通过特征提取可以得到数据原始的特征,此时特征可能存在以下问题:
数据集使用sklearn提供的的IRIS(鸢尾花)数据集。
IRIS数据集由Fisher在1936年整理,包含4个特征:
Sepal.Length - 花萼长度
Sepal.Width - 花萼宽度
Petal.Length - 花瓣长度
Petal.Width - 花瓣宽度
特征值均为正浮点数,单位为厘米。
目标值为鸢尾花的分类,包括
Iris Setosa - 山鸢尾
Iris Versicolour - 杂色鸢尾
Iris Virginica - 维吉尼亚鸢尾
from sklearn.datasets import load_iris
iris = load_iris() # 导入IRIS数据集
iris.data # 特征矩阵
iris.target # 目标向量
无量纲化用于使不同规格的数据转换到同一规格,包括标准化和区间缩放法。
标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。
标准化需要计算特征的均值 X ‾ \overline X X和标准差 S S S:
x ′ = x − X ‾ S x^{\prime} = \frac {x - \overline X}{S} x′=Sx−X
import numpy as np
from sklearn.preprocessing import StandardScaler
feature = np.random.randint(50,100,size=(3, 5))
'''
array([[70, 79, 72, 59, 50],
[67, 94, 52, 86, 91],
[51, 80, 82, 66, 85]])
'''
# 标准化操作,返回的是标准化处理后的数据。
StandardScaler().fit_transform(feature)
'''
array([[ 1.37699742, 1.25491161, 0.57289595, -1.35244738, 0.20203051],
[-0.40937761, -0.06274558, -1.40619914, 1.03422447, -1.31319831],
[-0.96761981, -1.19216603, 0.83330319, 0.31822291, 1.1111678 ]])
'''
使用IRIS数据集
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
iris = load_iris()
# 标准化操作,返回的是标准化处理后的数据。
StandardScaler().fit_transform(iris.data)
区间缩放法利用边界值(即数据集中的最大值和最小值),将特征的取值区间缩放到某个指定范围。
范围为[0, 1]的区间缩放法为归一化。
标准化
x ′ = x − M i n M a x − M i n x^{\prime} = \frac {x - Min}{Max - Min} x′=Max−Minx−Min
区间缩放法
x ′ ′ = x ′ × ( M a x − M i n ) + M i n x^{\prime\prime} = x^{\prime} \times (Max - Min) + Min x′′=x′×(Max−Min)+Min
import numpy as np
from sklearn.preprocessing import MinMaxScaler
feature = np.random.randint(50,100,size=(3, 5))
'''
array([[50, 92, 76, 72, 98],
[50, 58, 87, 86, 57],
[90, 90, 77, 82, 84]])
'''
# 范围默认为[0, 1]
MinMaxScaler().fit_transform(feature)
'''
array([[0. , 1. , 0. , 0. , 1. ],
[0. , 0. , 1. , 1. , 0. ],
[1. , 0.94117647, 0.09090909, 0.71428571, 0.65853659]])
'''
# 指定范围为[1, 10]
MinMaxScaler((1, 10)).fit_transform(feature)
'''
array([[ 1. , 10. , 1. , 1. , 10. ],
[ 1. , 1. , 10. , 10. , 1. ],
[10. , 9.47058824, 1.81818182, 7.42857143, 6.92682927]])
'''
使用IRIS数据集
from sklearn.datasets import load_iris
from sklearn.preprocessing import MinMaxScaler
iris = load_iris()
# 区间缩放,返回值为缩放到[0, 1]区间的数据。
MinMaxScaler().fit_transform(iris.data)
如果数据中存在的异常值比较多,例如存在极大的异常值,对于归一化,异常值会影响特征的最大值或最小值,因此归一化受异常值的影响较大,此时建议使用标准化。
当数据预处理完成后,需要选择有意义的特征输入模型中进行训练。
在做特征选择前,需要与数据提供者进行联系、沟通、开会等。一定要与提供数据的人沟通,尤其是理解业务和数据含义的人,目的是理解业务。
技术能够让模型起飞,前提是开发者能够做到和业务人员一样理解数据,理解每个特征代表的意义。所以说特征选择的第一步,其实是根据我们的目标,用业务常识来选择特征。
Filter过滤法的主要服务对象是需要遍历特征的算法模型,主要目的是在维持算法表现的前提下,降低计算成本。
Filter过滤法包括方差选择法、相关系数法、卡方检验等,这里主要介绍方差选择法。
方差选择法是通过计算各个特征的方差来筛选特征。首先计算各个特征的方差,然后根据阈值选择方差大于阈值的特征。
feature = np.random.randint(0,100,size=(3, 5))
'''
array([[18, 48, 48, 70, 90],
[ 1, 64, 88, 96, 15],
[71, 81, 0, 84, 54]])
'''
feature.var(axis=0) # 方差
'''
array([ 888.66666667, 181.55555556, 1294.22222222, 112.88888889,938. ])
'''
from sklearn.feature_selection import VarianceThreshold
# 方差选择法,返回值为特征选择后的数据。
VarianceThreshold(threshold=800).fit_transform(feature) # 指定阈值为800
'''
array([[18, 48, 90],
[ 1, 88, 15],
[71, 0, 54]])
'''
如果将方差为0或者方差极低的特征去除后,剩余的特征还有很多,同时模型的效果没有得到显著改善,则可以尝试留下一半的特征,设定一个让特征总数减半的方差阈值,即将特征方差的中位数设定为阈值。
from sklearn.feature_selection import VarianceThreshold
vt = VarianceThreshold(threshold=np.median(feature.var(axis=0)))
vt.fit_transform(feature)
'''
[[48 90]
[88 15]
[ 0 54]]
'''
当特征选择完成后,可以直接训练模型了,但是可能由于特征矩阵过大,使得计算量巨大,导致训练时间非常长,因此需要进一步降低特征矩阵维度,即降维。
降维的维度值指的是特征的种类。对于特征数量巨大的特征矩阵,需要压缩数据维度,在尽量减少损失信息的前提下,尽可能降低数据维度。
常见的降维方法包括主成分分析法(PCA)和线性判别分析(LDA)等,这里主要介绍主成分分析法(PCA)。
主成分分析法,PCA(Principal Component Analysis),本质是要将原始的样本映射到维度更低的样本空间中,PCA的目标是为了让映射后的样本具有最大的发散性,因此PCA是一种无监督的降维方法。
from sklearn.decomposition import PCA
# 主成分分析法
pca = PCA(n_components=2)
# 对于参数n_components,
# 如果是小数,表示保留特征的百分比,
# 如果是整数,表示减少后的特征数量。
pca.fit_transform([[0, 2, 4, 3], [0, 3, 7, 3], [0, 9, 6, 3]])
'''
array([[-2.88362421, -1.25443227],
[-1.45140588, 1.56492061],
[ 4.33503009, -0.31048834]])
'''
机器学习是从数据中自动分析获得规律,并利用规律对未知数据进行预测。因此机器学习的前提是使用样本数据对模型进行训练,使模型学习到数据中的规律。
sklearn提供的数据集分为Toy和Real World两种,
Toy表示轻量级的数据集,适用于学习和理解算法,
Real World表示真实的数据集,适用于模拟真实环境下的工作。
sklearn.datasets.load_<数据集名称>
导入鸢尾花数据集
The Iris Dataset
import sklearn.datasets as datasets
iris = datasets.load_iris() # 导入鸢尾花数据集
dir(iris) # 属性一览
'''
['DESCR', 'data', 'feature_names', 'filename', 'target', 'target_names']
'''
数据集属性介绍
DESCR - describe,数据集的完整描述
data - 所有数据
feature_names - 特征名称
target - 标签
target_names - 标签名称
sklearn.datasets.fetch_<数据集名称>
导入带标签的人脸数据集
Faces recognition example using eigenfaces and SVMs
import sklearn.datasets as datasets
iris = datasets.fetch_lfw_people() # 导入带标签的人脸数据集
数据集需要按照一定比利划分为训练集和测试集。
训练集用于训练模型,测试集用于评估模型。
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(train_data, train_target, test_size=None, random_state=None)
参数:
train_data - 待划分样本数据
train_target - 待划分样本数据的结果,即标签
test_size - 测试数据占样本数据的比例,若是整数则表示样本数量
random_state - 设置随机数种子,保证每次都是同一个随机数,若为0或不填,则每次得到数据都不一样。
返回值:
x_train - 特征数据的训练集
y_train - 标签数据的训练集
x_test - 特征数据的测试集
y_test - 标签数据的测试集
切分样本数据
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(feature, target, test_size=0.2, random_state=2020)
# 测试数据占样本数据的比例设定为0.2。
x_test.shape # (30, 4) 特征数据的测试集 150*0.2=30
x_train.shape # (120, 4) 特征数据的训练集 150*(1-0.2)=120
机器学习模型的最终预测结果都是通过相关的算法计算出来的,所以说在机器学习中算法是核心,数据是基础。
机器学习中的数据类型分为两大类:离散型数据和连续型数据。
机器学习中的算法主要分为两大类:分类问题和回归问题。
分类问题主要的任务是将一个未知归类的样本归属到某一个已知的类群中;
回归问题主要的任务是根据数据的规律计算出一个未知的数据。
分类算法基于的是【标签数据】为【离散型】数据;
回归算法基于的是【标签数据】为【连续型】数据。
开发流程中前4步可以统称为探索性数据分析EDA (Exploratory Data Analysis),是整个开发流程中的核心。