第六章 Python 机器学习
1、机器学习基础
1.1 机器学习分类
1.1.1 机器学习定义
- 机器学习 (Machine Learning, ML) 是一门综合性非常强的多领域
交叉学科
,涉及线性代数、概率论、统计学、算法复杂度理论等多门学科。 - 机器学习根据已知
数据
来不断学习和积累经验
,然后总结出规律并尝试预测未知数据的属性
。机器学习可利用数据或经验等不断改善自身的性能
。 - 机器学习是目前
弱人工智能
的核心,其应用十分广泛,如计算机视觉、自然语言处理、生物特征识别、搜索引擎、垃圾邮件过滤、推荐系统、广告投放、信用评价、欺诈检测、股票交易和医疗诊断等应用。
1.1.2 机器学习分类
可以定义为:机器学习是从
数据
中自动分析获得模型
,并利用模型对未知数据进行预测
。可分为:监督学习(supervised learning)
1)监督学习:主要特点是要在训练模型时提供给学习系统训练样本以及样本对应的类别标签
,因此又称为有导师学习。例:学生从老师那里获取知识、信息,老师提供对错指示、告知最终答案的学习过程。
2)典型的监督学习方法:决策树、支持向量机(SVM)、监督式神经网络等分类算法和线性回归等回归算法。
3)监督学习目标:利用一组带有标签
的数据,学习从输入到输出的映射
,然后将这种映射关系应用到未知数据
上,达到分类(输出是离散
的)或回归(输出是连续
的)的目的。
4)监督学习(supervised learning)
• 目标值:类别——分类问题。
• 目标值:连续型的数据——回归问题。
5)示例
➢ 预测明天的气温是多少度?
➢ 预测明天天气是晴、阴或雨?
➢ 人的年龄预测?
➢ 人脸识别?无监督学习(unsupervised learning)
1)无监督学习:主要特点是训练时只提供
给学习系统训练样本
,而没有样本对应的类别标签信息。例:没有老师的情况下,学生从书本或网络自学的过程。
2)无监督学习中,训练数据包含一组输入向量而没有相应的目标值
。这类算法的目标可能是发现原始数据中相似样本的组合(称作聚类)
,或者确定数据的分布(称作密度估计)
,或者把数据从高维空间投影到低维空间(称作降维
)以便进行可视化。
3)典型的无监督学习方法:聚类学习、自组织神经网络学习。半监督学习(semi-supervised learning)
1)半监督学习方式下,训练数据有部分被标识
,部分没有被标识
,这种模型首先需要学习数据的内在结构,以便合理的组织数据来进行预测。算法上,包括一些对常用监督式学习算法的延伸,这些算法首先试图对未标识数据进行建模
,在此基础上再对标识的数据进行预测
。
2)例:给学生很多未分类的书本与少量的清单,清单上说明哪些书属于同一类别,要求对其他所有书本进行分类。强化学习(reinforcement learning,增强学习)
1)强化学习:主要特点是通过试错来发现最优行为策略而不是带有标签的样本学习。
2)主要包含四个元素,agent,环境状态,行动,奖励, 强化学习的目标就是获得最多的累计奖励。
3)例:小孩学走路、下棋 (包括下围棋和象棋)、机器人、自动驾驶等。
1.2 监督学习-分类
1.2.1 分类学习
输入:一组有
标签
的训练数据(也称观察和评估),标签表明了这些数据(观察)的所署类别。输出:分类模型根据这些训练数据,训练自己的
模型参数
,学习出一个适合这组数据的分类器
,当有新数据(非训练数据)需要进行类别判断,就可以将这组新数据作为输入送给学习好的分类器进行判断。数据集
1)训练集(training set):顾名思义用来训练模型的已标注数据
,用来建立模型,发现规律。
2)测试集(testing set):也是已标注数据
,通常做法是将标注隐藏
,输送给训练好的模型,通过结果与真实标注进行对比,评估模型
的学习能力。训练集/测试集划分方法
根据已有标注数据,随机选出一部分数据(70%)作为训练数据,余下的作为测试数据,此外还有交叉验证法等用来评估分类模型。分类学习评价标准
1)精确率:针对预测结果而言,也称查全率,是所有样本中被识别为A类
的样本数量与实际属于A类
的样本数量的比值。以二分类为例,它表示的是预测为正
的样本中有多少是真正的正
样本。那么就有两种可能:一种就是把正类预测为正类(TP),另一种就是把负类预测为正类(FP)。精确率P=TP/(TP+FP)
2)召回率:针对原样本而言,它表示的是样本中的正例有多少被预测正确。那也有两种可能:一种是把原来的正类预测成正类(TP),另一种就是把原来的正类预测为负类(TN)。召回率P=TP/(TP+TN)分类学习评价标准——例:
• 假设我们手上有60个正样本,40个负样本,我们要找出所有的正样本。
• TP: 将正类预测为正类数40;TN: 将正类预测为负类数20;FP: 将负类预测为正类数10;FN: 将负类预测为负类数30。
• 准确率(accuracy)=预测对的/所有=(TP+FN)/(TP+FN+FP+TN)=(40+30)/100=70%
• 精确率(precision)=TP/(TP+FP)=40/(40+10)=80%
• 召回率(recall)=TP/(TP+TN)=40/(40+20)=66.7%分类学习应用
• 金融:贷款是否批准进行评估。
• 医疗诊断:判断一个肿瘤是恶性还是良性。
• 欺诈检测:判断一笔银行的交易是否涉嫌欺诈。
• 网页分类:判断网页的所属类别,财经或者是娱乐?
• 垃圾邮件分类:判定邮件是否为垃圾邮件。
1.2.2 分类学习常用算法
K近邻分类器(KNN)
KNN:通过计算待分类数据点,与已有数据集中的所有数据点的距离。取距离最小的前K个点,根据“少数服从多数“的原则,将这个数据点划分为出现次数最多的那个类别。决策树
1)决策树是一种树形结构的分类器,通过顺序询问分类点的属性决定分类点最终的类别。
2)通常根据特征的信息增益或其他指标,构建一颗决策树。
3)在分类时,只需要按照决策树中的结点依次进行判断,即可得到样本所属类别。朴素贝叶斯
1)朴素贝叶斯分类器是一个以贝叶斯定理为基础的多分类的分类器。
2)对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。
$$P(A|B)=\frac{P(B|A)P(A)}{P(B)}$$
1.3 监督学习-回归分析
1.3.1 回归分析
回归:统计学分析数据的方法,目的在于了解两个或多个
变数间是否相关
、研究其相关方向与强度
,并建立数学模型
以便观察特定变数
来预测
研究者感兴趣的变数
。回归分析可以帮助人们了解在
自变量变化时因变量的变化量
。一般来说,通过回归分析我们可以由给出的自变量估计因变量的条件期望。回归分析应用:回归方法适合对一些带有时序信息的数据进行预测或者趋势拟合,常用在金融及其他涉及时间序列分析的领域:
1)股票趋势预测
2)交通流量预测
3)房价预测
1.3.2 回归分析方法
- 线性回归
线性回归 (Linear Regression) 是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,其使用形如 y=wx+b 的线性模型
拟合数据输入和输出之间的映射关系。
线性回归——实际用途
1)利用数据拟合模型进行预测
:如果目标是预测或者映射,线性回归可以用来对观测数据集的 y 和 X 的值拟合出一个预测模型。当完成这样一个模型以后,对于一个新增的 X 值,在没有给定与它相配对的 y 的情况下,可以用这个拟合过的模型预测出一个 y 值。
2)相关性分析去除冗余
:给定一个变量 y 和一些变量 $X_1-X_n$,这些变量有可能与 y 相关,线性回归分析可以用来量化 y 与 $X_i$ 之间相关性的强度,评估出与 y 不相关的 $X_i$ ,并识别出哪些 $X_i$ 的子集包含了关于 y 的冗余信息。房价与房屋尺寸关系的线性拟合
1)背景:我们可以根据已知的房屋成交价和房屋的尺寸进行线性回归,继而可以对已知房屋尺寸,而未知房屋成交价格的实例进行成交价格的预测。
2)目标:对房屋成交信息建立回归方程,并依据回归方程对房屋价格进行预测。非线性拟合:多项式回归
1)多项式回归(Polynomial Regression)是研究一个因变量与一个或多个自变量间多项式的回归分析方法。
2)如果自变量只有一个时,称为一元多项式回归;如果自变量有多个时,称为多元多项式回归。什么时候用多项式回归
1)在一元回归分析中,如果依变量 y 与自变量 x 的关系为非线性的
,但是又找不到适当的函数曲线来拟合,则可以采用一元多项式回归。
2)多项式回归的最大优点就是可以通过增加x的高次项对实测点进行逼近
,直至满意为止。
3)事实上,多项式回归可以处理相当一类非线性问题,它在回归分析中占有重要的地位,因为任一函数都可以分段用多项式来逼近。
2、Scikit-learn 库
2.1 Sklearn 库概述
2.1.1 Scikit-learn 库概述
- Scikit-learn 项目最早由数据科学家 David Cournapeau 在2007年发起,使用需要 NumPy 和 SciPy 等其他库的支持,是 Python 中专门针对机器学习应用而发展起来的一款开源扩展库。
- 和其他众多的开源项目一样,Scikit-learn 目前主要由社区成员自发进行维护。
- Scikit-learn 相比其他开源项目显得更为保守,主要体现在:一是Scikit-learn 从来不做除机器学习领域之外的其他扩展,二是 Scikit-learn 从来不采用未经广泛验证的算法。
- http://scikit-learn.org/stable/index.html
2.1.2 Scikit-learn 库数据集
在机器学习中,经常需要使用各种各样的数据集,Scikit-learn 库提供了一些常用的数据集:
序号 | 数据集名称 | 调研方式 | 数据描述 |
---|---|---|---|
1 | 鸢尾花数据集 | Load_iris() | 用于多分类任务的数据集 |
2 | 波士顿房价数据集 | Load_boston() | 用于回归任务的经典数据集 |
3 | 糖尿病数据集 | Load_diabetes() | 用于回归任务的经典数据集 |
4 | 手写数字数据集 | Load_digits() | 用于多分类任务的数据集 |
5 | 乳腺癌数据集 | Load_breast_cancer() | 经典的用于二分类任务的数据集 |
6 | 体能训练数据集 | Load_linnerud() | 经典的用于多变量回归任务的数据集 |
2.1.3 Scikit-learn 库功能
分类
1)分类是指识别给定对象的所属类别,属于监督学习的范畴,最常见的应用场景包括垃圾邮件检测和图像识别等。
2)目前 Scikit-learn 已经实现的算法包括:支持向量机(SVM),最近邻,逻辑回归,随机森林,决策树以及多层感知器(MLP)神经网络等。回归
1)回归是指预测与给定对象相关联的连续值属性,最常见的应用场景包括预测药物反应和预测股票价格等。
2)目前 Scikit-learn 已经实现的算法包括:支持向量回归(SVR),脊回归,Lasso 回归,弹性网络(Elastic Net),最小角回归(LARS),贝叶斯回归,以及各种不同的鲁棒回归算法等。
3)回归算法几乎涵盖了所有开发者的需求范围,而且更重要的是,Scikit-learn 还针对每种算法都提供了简单明了的用例参考。聚类
1)聚类是指自动识别具有相似属性的给定对象,并将其分组为集合,属于无监督学习的范畴。
2)最常见的应用场景包括顾客细分和试验结果分组。目前 Scikit-learn 已经实现的算法包括:K-均值聚类,谱聚类,均值偏移,分层聚类,DBSCAN 聚类等。数据降维
数据降维是指使用主成分分析(PCA)、非负矩阵分解(NMF)或特征选择等降维技术来减少要考虑的随机变量的个数,其主要应用场景包括可视化处理和效率提升。模型选择
模型选择是指对于给定参数和模型的比较、验证和选择,其主要目的是通过参数调整来提升精度。目前 Scikitlearn 实现的模块包括:格点搜索,交叉验证和各种针对预测误差评估的度量函数。数据预处理
1)数据预处理是指数据的特征提取和归一化,是机器学习过程中的第一个也是最重要的一个环节。
2)归一化是指将输入数据转换为具有零均值和单位权方差的新变量,但因为大多数时候都做不到精确等于零,因此会设置一个可接受的范围,一般都要求落在 0-1 之间。
3)特征提取是指将文本或图像数据转换为可用于机器学习的数字变量。
2.2 Sklearn 库分类算法
2.2.1 Scikit-learn 库分类算法
- K近邻分类器(KNN)
KNN:通过计算待分类数据点,与已有数据集中的所有数据点的距离。取距离最小的前 K 个点,根据“少数服从多数“的原则,将这个数据点划分为出现次数最多的那个类别。
K近邻算法
- Sklearn 中的 k 邻分类器
在 sklearn 库中,可以使用 sklearn.neighbors.KNeighborsClassifier 创建一个 K 近邻分类器,主要参数有:
1)n_neighbors:用于指定分类器中K的大小(默认值为5)。
2)Weights:设置选中的K个点对分类结果影响的权重(默认值为平均权重”uniform”,可以选择“distance”代表越近的点权重越高,或者传入自己编写的以距离为参数的权重计算函数)。
3)algorithm:设置用于计算临近点的方法 ( 选项中有ball_tree、kd_tree 和 brute,分别代表不同的寻找邻居的优化算法,默认值为 auto,根据训练数据自动选择)。
k值的选择
① 如果 k 值较小,就相当于用较小邻域中的训练实例进行预测,极端情况下 k=1,测试实例只和最接近的一个样本有关,训练误差很小(0),但是如果这个样本恰好是噪声,预测就会出错。也就是说,如果k值过小,容易产生过拟合,误差过大。
② 如果 k 值较大,就相当于用很大邻域中的训练实例进行预测,相当于和估计数据不相近的样本也参与了,造成模型偏差过大。极端情况是 k=n,测试实例的结果是训练数据集中实例最多的类,这样会产生欠拟合。
③ 在应用中,一般选择较小 k 并且 k 是奇数。通常采用交叉验证的方法来选取合适的 k 值,或者 k 一般低于训练样本数的平方根。
Sklearn 中的 k 邻分类器——示例
from sklearn.neighbors import KNeighborsClassifier
# 创建一组数据X和它对应的标签y
X=[[0],[1],[2],[3],[4],[5]]
y=[0,0,0,1,1,1]
# 使用最近的3个邻居作为分类的依据,得到分类器
neigh = KNeighborsClassifier(n_neighbors=3)
# 将训练数据 X 和标签 y 送入分类器进行学习
neigh.fit(X, y)
# 调用 predict() 函数,对未知分类样本 [1.1]分类,可以直接并将需要分类的数据构造为数组形式作为参数传入,得到分类标签作为返回值
print(neigh.predict([[1.4]]))
print(neigh.predict([[2.4]]))
print(neigh.predict([[2.5]]))
print(neigh.predict([[2.6]]))
运行结果
[0]
[0]
[0]
[1]
决策树
1)决策树是一种树形结构的分类器,通过顺序询问分类点的属性决定分类点最终的类别。
2)通常根据特征的信息增益或其他指标,构建一颗决策树。
3)在分类时,只需要按照决策树中的结点依次进行判断,即可得到样本所属类别。
Sklearn中的决策树
在 sklearn 库中 , 可以使用sklearn.tree.DecisionTreeClassifier 创建一个决策树用于分类,其主要参数有:
1)criterion :用于选择属性的准则,可以传入 “gini” 代表基尼系数,或者 “entropy” 代表信息增益。
2)max_features :表示在决策树结点进行分裂时,从多少个特征中选择最优特征。可以设定固定数目、百分比或其他标准,默认值是所有特征个数。
Sklearn中的决策树算法示例
from sklearn import datasets # 导入方法类
iris = datasets.load_iris() # 加载 iris 数据集
iris_feature = iris.data # 特征数据
iris_target = iris.target # 分类数据
from sklearn.model_selection import train_test_split
feature_train, feature_test, target_train, target_test = train_test_split(iris_feature, iris_target, test_size=0.33, random_state=42)
from sklearn.tree import DecisionTreeClassifier
dt_model = DecisionTreeClassifier() # 所以参数均置为默认状态
dt_model.fit(feature_train,target_train) # 使用训练集训练模型
predict_results = dt_model.predict(feature_test) # 使用模型对测试集进行预测
print('predict_results:', predict_results)
print('target_test:', target_test)
# 通过scikit-learn中提供的评估计算方法查看预测结果的准确度
from sklearn.metrics import accuracy_score
print(accuracy_score(predict_results, target_test))
运行结果
predict_results: [1 0 2 1 1 0 1 2 2 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1
0 0 0 2 1 1 0 0 1 1 2 1 2]
target_test: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1
0 0 0 2 1 1 0 0 1 2 2 1 2]
0.96
- Sklearn 中的朴素贝叶斯
• 在 sklearn 库中,实现了三个朴素贝叶斯分类器,如下表所示
分类器 | 描述 |
---|---|
naive_bayes.GussianNB | 高斯朴素贝叶斯 |
naive_bayes.MultinomialNB | 针对多项式模型的斯朴素贝叶斯分类器 |
naive_bayes.BernoulliNB | 针对多元伯努利模型的斯朴素贝叶斯分类器 |
区别在于假设某一特征的所有属于某个类别的观测值符合特定分布,如,分类问题的特征包括人的身高,身高符合高斯分布,这类问题适合高斯朴素贝叶斯
Sklearn中的朴素贝叶斯算法示例
import numpy as np
from sklearn.naive_bayes import GaussianNB
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
Y = np.array([1, 1, 1, 2, 2, 2])
#使用默认参数,创建一个高斯朴素贝叶斯分类器,并将该分类器赋给变量
clf = GaussianNB(priors=None)
clf.fit(X, Y)
print(clf.predict([[-0.8, -1]]))
运行结果
[1]
2.3 Sklearn 库回归算法
2.3.1 Scikit-learn 库回归算法
Sklearn 中的回归算法
• 线性回归函数包括:普通线性回归函数(LinearRegression),岭回归(Ridge), Lasso回归(Lasso)。
• 非线性回归函数,如多项式回归(Polynomial Features)通过
sklearn.preprocessing 子模块进行调用Sklearn 中的线性回归:房价与房屋尺寸线性拟合
• 技术路线:sklearn.linear_model.LinearRegression
• 调用 sklearn.linear_model.LinearRegression() 所需参数:
1)fit_intercept : 布尔型参数,表示是否计算该模型截距。可选参数;
2)normalize : 布尔型参数,若为 True,则X在回归前进行归一化。可选参数。默认值为 False;
3)copy_X : 布尔型参数,若为True,则X将被复制;否则将被覆盖。 可选参数。默认值为 True;
4)n_jobs : 整型参数,表示用于计算的作业数量;若为 -1,则用所有的 CPU。可选参数。默认值为 1;
2.3.2 Sklearn中的线性回归:房价与房屋尺寸线性拟合
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
# 读取数据集
datasets_X = []#房屋面积
datasets_Y = []#房屋价格
fr = open('prices.txt','r')
lines = fr.readlines()
for line in lines:
items = line.strip().split(',')
datasets_X.append(int(items[0])) # 注意加上类型转换
datasets_Y.append(int(items[1]))
# 将 datasets_X 转换为二维数组,以符合 linear.fit 函数的参数要求
datasets_X = np.array(datasets_X).reshape([-1,1])
datasets_Y = np.array(datasets_Y)
# 以数据datasets_X的最大值和最小值为范围,建立等差数列,方便后续画图。
minX = min(datasets_X)
maxX = max(datasets_X)
X = np.arange(minX,maxX).reshape([-1,1])
linear = linear_model.LinearRegression()
linear.fit(datasets_X, datasets_Y)
# 图像中显示
plt.scatter(datasets_X, datasets_Y, color = 'red',label='origin data')
plt.plot(X, linear.predict(X), color = 'blue',label='linear regression prediction')
plt.legend() #使label生效
plt.xlabel('Area')
plt.ylabel('Price')
plt.show()
3、线性回归预测实战
3.1 线性回归原理
3.1.1 “回归”的由来
“回归” 是由高尔顿在研究人类遗传问题时提出来的。
为研究父代与子代身高的关系,高尔顿搜集了 1078 对父亲及其儿子的身高数据并进行了深入分析,发现了回归效应:
当父亲高于平均身高时,他们的儿子身高比他更高的概率要小于比他更矮的概率;父亲矮于平均身高时,他们的儿子身高比他更矮的概率要小于比他更高的概率。
即这两种身高父亲的儿子的身高,有向他们父辈的平均身高回归的趋势,解释为:大自然约束使人类身高分布相对稳定而非两极分化,就是所谓的“回归效应”。
3.1.2 回归分析概念
- 回归分析法:指将具有相关关系的两个变量之间的数量关系进行测定,通过建立一个数学表达式进行统计估计和预测的统计研究方法。
- 自变量:一般把作为估测依据的变量叫做自变量
- 因变量: 待估测的变量
- 回归方程:反映自变量和因变量之间联系的数学表达式
- 回归模型:某一类回归方程的总称
3.1.3 回归分析步骤
3.2 线性回归模型原理
3.3 预测儿童身高实战
3.3.1 线性回归预测实战
线性回归预测儿童身高
• 假定一个人的身高只受年龄、性别、父母身高、祖父母身高和外祖父母身高这几个因素的影响,并假定大致符合线性关系。
• 在其他条件不变的情况下,随着年龄的增长,会越来越高;
• 同样,对于其他条件都相同的儿童,其父母身高较高的话,儿童也会略高一些。
• 假定到18岁后身高会长期保持固定而不再变化(不考虑年龄太大之后会稍微变矮一点的情况)。
• 根据给定训练数据和对应标签
,线性拟合出儿童身高模型,预测测试数据儿童身高。线性回归预测儿童身高
• 训练数据:每行表示一个样本,包含信息为:儿童年龄,性别(0女1田)、父亲、母亲、祖父、祖母、外祖父、和外祖母的身高。
[[1, 0, 180, 165, 175, 165, 170, 165],
[3, 0, 180, 165, 175, 165, 173, 165],
[4, 0, 180, 165, 175, 165, 170, 165],
[6, 0, 180, 165, 175, 165, 170, 165],
[8, 1, 180, 165, 175, 167, 170, 165],
[10, 0, 180, 166, 175, 165, 170, 165],
[11, 0, 180, 165, 175, 165, 170, 165],
[12, 0, 180, 165, 175, 165, 170, 165],
[13, 1, 180, 165, 175, 165, 170, 165],
[14, 0, 180, 165, 175, 165, 170, 165],
[17, 0, 170, 165, 175, 165, 170, 165]]
• 对应标签数据:儿童身高
[60, 90, 100, 110, 130, 140, 150, 164, 160, 163, 168]线性回归预测儿童身高
1)导入扩展库
import copy
import numpy as np
from sklearn import linear_model
2)训练数据准备
x = np.array([[1, 0, 180, 165, 175, 165, 170, 165],[3, 0, 180, 165, 175, 165, 173, 165],[4, 0, 180, 165, 175, 165, 170, 165],[6, 0, 180, 165, 175, 165, 170, 165],[8, 1, 180, 165, 175, 167, 170, 165],[10, 0, 180, 166, 175, 165, 170, 165],[11, 0, 180, 165, 175, 165, 170, 165],[12, 0, 180, 165, 175, 165, 170, 165],[13, 1, 180, 165, 175, 165, 170, 165],[14, 0, 180, 165, 175, 165, 170, 165],[17, 0, 170, 165, 175, 165, 170, 165]])
y = np.array([60, 90, 100, 110, 130, 140, 150, 164, 160, 163, 168])
3)创建线性回归模型,得出拟合直线
# 创建线性回归模型
lr = linear_model.LinearRegression()
# 根据已知数据拟合最佳直线
lr.fit(x, y)
4)待预测数据准备
xs = np.array([[10, 0, 180, 165, 175, 165, 170, 165],[17, 1, 173, 153, 175, 161, 170, 161],[34, 0, 170, 165, 170, 165, 170, 165]])
5)预测并输出结果
for item in xs:
# 为不改变原始数据,进行深复制,并假设超过18岁以后就不再长高了
# 对于18岁以后的年龄,返回18岁时的身高
item1 = copy.deepcopy(item)
if item1[0] > 18:
item1[0] = 18
print(item, ':', lr.predict(item1.reshape(1,-1)))
运行结果
[ 10 0 180 165 175 165 170 165] : [140.56153846]
[ 17 1 173 153 175 161 170 161] : [158.41]
[ 34 0 170 165 170 165 170 165] : [176.03076923]
4、贝叶斯分类实战
4.1 分类基本概念
4.1.1 什么是分类
超市物品分类
垃圾分类
生活信息分类
4.1.2 分类在数据挖掘中的定义
• 分类就是把一些新的数据项映射到给定类别
的中的某一个类别。
• 分类属于有监督学习
(supervised learning),与之相对于的是无监督学习
(unsupervised learning),比如聚类。
• 分类与聚类的最大区别在于,分类数据中的一部分的类别是已知
的,而聚类数据的类别未知
。
4.1.3 分类问题
动物分类问题
根据现有的知识,我们得到了一些关于哺乳动物和鸟类的信息,我们能否对新发现的物种,比如动物A,动物B进行分类?
动物种类 | 体型 | 翅膀数量 | 脚的只数 | 是否产蛋 | 是否有毛 | 类别 |
---|---|---|---|---|---|---|
狗 | 中 | 0 | 4 | 否 | 是 | 哺乳动物 |
猪 | 大 | 0 | 4 | 否 | 是 | 哺乳动物 |
牛 | 大 | 0 | 4 | 否 | 是 | 哺乳动物 |
麻雀 | 小 | 2 | 2 | 是 | 是 | 鸟类 |
天鹅 | 中 | 2 | 2 | 是 | 是 | 鸟类 |
大雁 | 中 | 2 | 2 | 是 | 是 | 鸟类 |
动物A | 大 | 0 | 2 | 是 | 无 | ? |
动物B | 中 | 2 | 2 | 否 | 是 | ? |
4.1.4 分类的流程
- 步骤一:将样本转化为等维的数据特征(
特征提取
)。所有样本必须具有相同数量的特征。兼顾特征的全面性和独立性。 - 步骤二:选择与类别相关的特征(
特征选择
)。比如,绿色代表与类别非常相关,黑色代表部分相关,浅蓝色代表完全无关。 - 步骤三:建立分类模型或分类器。
- 分类器通常可以看作一个函数,它把特征映射到类的空间上。
- $$f(x_{i1}, x_{i2}, x_{i3}, …,x_{in})→y_i$$
动物种类 | 体型 | 翅膀数量 | 脚的只数 | 是否产蛋 | 是否有毛 | 类别 |
---|---|---|---|---|---|---|
狗 | 中 | 0 | 4 | 否 | 是 | 哺乳动物 |
猪 | 大 | 0 | 4 | 否 | 是 | 哺乳动物 |
牛 | 大 | 0 | 4 | 否 | 是 | 哺乳动物 |
麻雀 | 小 | 2 | 2 | 是 | 是 | 鸟类 |
天鹅 | 中 | 2 | 2 | 是 | 是 | 鸟类 |
大雁 | 中 | 2 | 2 | 是 | 是 | 鸟类 |
4.1.5 分类的方法
1)常用分类算法主要包括相似函数,关联规则分类算法,K近邻分类算法,决策树分类算法,贝叶斯分类算法和基于模糊逻辑,遗传算法,粗糙集和神经网络的分类算法。
2)分类算法有很多种,都有各自的优缺点和应用范围,本课程我们以贝叶斯分类算法为例。
4.2 贝叶斯分类概述
背景
1)贝叶斯分类基于贝叶斯
定理,贝叶斯定理是由 18 世纪概率论和决策论的研究者 Thomas Bayes 发明的,故用其名字命名为贝叶斯定理。
2)通过对分类算法的比较研究发现,朴素贝叶斯分类法可以与决策树和经过挑选的神经网络分类器相媲美。用于大型数据库,贝叶斯分类法也具有很高准确率和速度。先验概率与后验概率
1)先验概率:由以往
的数据分析得到的概率;
2)后验概率:得到信息之后
重新加以修正的概率。贝叶斯理论
1)简单的说,贝叶斯定理是基于假设的先验概率
、给定假设下观察到不同数据的概率,提供了一种计算后验概率的方法。
2)在人工智能领域,贝叶斯方法是一种非常具有代表性的不确定性知识表示和推理方法
。贝叶斯定理
1)P(A) 是 A 的先验概率或边缘概率
。之所以称为“先验”是因为它不考虑任何B方面的因素。
2)P(A|B) 是已知 B 发生后 A 的条件概率
,也由于得自 B 的取值而被称作 A 的后验概率
。
3)P(B|A ) 是已知 A 发生后 B 的条件概率
,也由于得自 A 的取值而被称作B的后验概率
。
4)P(B)是B的先验概率或边缘概率
,也作标准化常量(normalized constant)。
$$P(A|B)=P(A)\frac{P(B|A)}{P(B)}$$
贝叶斯公式提供了从先验概率 P(A)、P(B) 和 P(B|A) 计算后验概率 P(A|B) 的方法。朴素贝叶斯
假设待分类项的各个属性相互独立的情况下构造的分类算法就是朴素贝叶斯算法。
基本思想
给定的待分类项 X{a1,a2,…,an},求解在此项出现条件下各个类别 $y_i$ 出现的概率,哪个 P($y_i$|X) 最大,就把此待分类项归属哪个类别。
- 四种贝叶斯分类器
1)Naïve Bayes:朴素贝叶斯,假定各特征变量 x 是相互独立的。
2)TAN:对朴素贝叶斯进行了扩展,允许各特征变量所对应的节点构成一棵树。
3)BAN:对 TAN 扩展,允许各特征变量所对应的节点间关系构成一个图,而不止是树。
4)GBN:一种无约束的贝叶斯网络分类器。
贝叶斯分类流程
1)准备阶段:主要是依据具体情况确定特征属性
,并且对特征属性进行适当划分。然后就是对一部分待分类项进行人工划分,以确定训练样本。输入是所有的待分类项,输出是特征属性和训练样本
。
2)分类器训练阶段:计算每个类别在训练样本中出现频率以及每个特征属性划分对每个类别的条件概率估计。输入是特征属性和训练样本,输出是分类器
。
3)应用阶段:使用分类器对待分类项进行分类,其输入是分类器和待分类项,输出是待分类项与类别的映射关系
。
4.3 垃圾邮件分类实战
训练数据:
垃圾邮件(0.txt至150.txt),其中 0-127 为垃圾邮件,128 至 150 为正常邮件,151 至 156 为测试邮件。
4.3.1 问题分析
① 读取全部训练集,删除其中的干扰字符
,例如【】*。、,等等,然后分词
,再删除长度为 1
的单个字,这样的单个字对于文本分类没有贡献,剩下的词汇认为是有效词汇。
② 统计全部训练集中每个有效词汇的出现次数
,截取出现次数最多的前N个
。
③ 根据第 1 步预处理后的垃圾邮件和非垃圾邮件内容生成特征向量,统计第 2 步中得到的N个词语分别在该邮件中的出现频率。
④ 根据第 3 步中得到特征向量和已知邮件分类创建并训练朴素贝叶斯模型。
⑤ 读取测试邮件,参考第 1 步,对邮件文本进行预处理,提取特征向量。
⑥ 使用第 4 步中训练好的模型,根据第 5 步提取的特征向量对邮件进行分类。
4.3.2 垃圾邮件分类实战
- 导入扩展库
from re import sub
from collections import Counter
from itertools import chain
from numpy import array
from jieba import cut
from sklearn.naive_bayes import MultinomialNB
- 获取文件中所有词
def getWordsFromFile(txtFile):
words = []
with open(txtFile, encoding='utf8') as fp:
for line in fp:
line = line.strip()
line = sub(r'[.【】0-9、—。,!~\*]', '', line)
line = cut(line)
line = filter(lambda word: len(word)>1, line)
words.extend(line)
return words
- 获得全部训练集中出现次数最多的词
allWords = []
def getTopNWords(topN):
txtFiles = [str(i)+'.txt' for i in range(151)]
for txtFile in txtFiles:
allWords.append(getWordsFromFile(txtFile))
freq = Counter(chain(*allWords))
return [w[0] for w in freq.most_common(topN)]
topWords = getTopNWords(600)
- 获取特征向量、创建模型训练
vectors = []
for words in allWords:
temp = list(map(lambda x: words.count(x), topWords))
vectors.append(temp)
vectors = array(vectors)
labels = array([1]*127 + [0]*24)
model = MultinomialNB()
model.fit(vectors, labels)
- 预测未知邮件,进行分类,看是否为垃圾邮件
def predict(txtFile):
words = getWordsFromFile(txtFile)
currentVector = array(tuple(map(lambda x: words.count(x),topWords)))
result = model.predict(currentVector.reshape(1, -1))[0]
return '垃圾邮件' if result==1 else '正常邮件'
for mail in ('%d.txt'%i for i in range(151, 156)):
print(mail, predict(mail), sep=':')