1.1 机器学习简介
机器学习目的并不是为了得到最后的运算结果,而是对计算过程进行分析,总结出一套运算的规则。只要数据量足够多,运算规则就越准确。最后可以根据这套规则对没有通过验证的数据进行预算,得到预算后的值。只要使用的规则正确,预算的结果的正确率往往可以达到95%以上。
1.1.1 机器学习的本质
基本思路:无论使用什么样的算法和数据,机器学习的基本思路都可以归结为以下三个核心步骤。
-
问题抽象与数学建模:把现实生活中的问题抽象成数学模型,并且很清楚模型中不同参数的作用
-
模型求解与学习:利用数学方法对这个数学模型进行求解,从而解决现实生活中的问题
-
模型评估与反馈:评估这个数学模型,是否真正地解决了现实生活中的问题,以及解决的效果如何?
一、机器学习的本质
基本思路:无论使用什么样的算法和数据,机器学习的基本思路都可以归结为以下三个核心步骤。
-
问题抽象与数学建模:把现实生活中的问题抽象成数学模型,并且很清楚模型中不同参数的作用
-
模型求解与学习:利用数学方法对这个数学模型进行求解,从而解决现实生活中的问题
-
模型评估与反馈:评估这个数学模型,是否真正地解决了现实生活中的问题,以及解决的效果如何?
1.1.2 机器学习的原理
机器学习的原理:机器学习是通过使用训练集数据,识别和提取特征,建立预测模型,并将所学规律应用于新数据进行预测或分类的过程。
-
训练集:提供标签化的数据,用于训练模型。例如,识字卡片帮助小朋友了解汉字与特征的关系。
-
特征:数据中的可测量属性,用于区分不同类别。如“一条横线”帮助区分汉字“一”。
-
建模:通过算法从数据中学习,构建预测模型。小朋友通过重复学习建立汉字认知模型。
-
模型应用:学习到的规律用于新数据预测或分类。学会识字后,小朋友能识别并区分不同汉字。
机器学习的步骤:收集数据、数据准备、选择模型、训练、评估、参数调整和预测。
案例:机器学习通过酒精度和颜色来区分红酒和啤酒。
-
步骤1:收集数据
-
任务:购买多种啤酒和红酒,并使用设备测量其颜色和酒精度。
-
输出:创建一个包含颜色、酒精度和种类的数据表格。
-
步骤2:数据准备
-
任务:检查数据质量,可能需要进行数据清洗。
-
数据划分:将数据分为训练集(60%)、验证集(20%)和测试集(20%)。
-
步骤3:选择模型
-
任务:根据问题的性质和数据特征选择一个合适的模型。
-
示例:在本例中,由于只有两个特征(颜色和酒精度),可以选择一个简单的线性模型。
-
步骤4:训练
-
任务:使用训练集数据对模型进行训练。
-
自动化:训练过程由机器自动完成,类似于解决数学问题。
-
步骤5:评估
-
任务:使用验证集和测试集评估模型的性能。
-
评估指标:主要关注准确率、召回率和F值等指标。
-
步骤6:参数调整
-
任务:根据评估结果对模型参数进行调整,以优化性能。
-
方法:通过人为地调整参数来改善模型表现。
-
步骤7:预测
-
任务:利用训练好的模型对新数据进行预测。
-
应用场景:在本例中,可以输入新酒的颜色和酒精度,模型将预测其为啤酒或红酒。
1.2 深度学习简介
深度学习开始只是机器学习的一分支领域,它更强调从连续的层中进行学习,这种层级结构中的每一层代表不同程度的抽象,层级越高,抽象程度越大。这些层主要通过神经网络的模型学习得到的,最大的模型会有上百层之多。而最简单的神经网络分为输入层,中间层(中间层往往会包含多个隐藏层),输出层。
经过多年的发展,深度学习的应用层面越来越广,从而诞生出 Tensorflow、Keras、Theano、CNTK 等框架的支持,逐渐发展形成独立的技术领域。根据不同的应用场景,深度学习又分为多层感知器MLP、深度神经网络DNN、卷积神经网络CNN、递归神经网络RNN、生成对抗网络BNN等多个方面。
1.3 机器学习分类
三、分类与算法
机器学习的分类:根据训练方法可以分为3大类,监督学习、非监督学习、强化学习。
从给定的训练数据集中学习出一个函数(模型参数),当新的数据到来时,可以根据这个函数预测结果。
监督学习(Supervised Learning):
-
标签信息: 监督学习使用带有标签的训练数据。这意味着每个训练样本都有一个相关联的标签,即对应的输出或目标值。
-
任务类型: 监督学习用于解决分类和回归等任务。在分类任务中,模型预测输入数据属于哪个类别;而在回归任务中,模型预测一个连续值。
-
学习过程: 模型通过学习输入与相应标签之间的关系来进行训练。算法通过最小化预测值与实际标签之间的差距来优化模型。
-
例子: 支持向量机(SVM)、决策树、神经网络等都是监督学习的例子。
无监督学习(Unsupervised Learning)
-
标签信息: 无监督学习使用没有标签的训练数据。训练样本不包含对应的输出或目标值。
-
任务类型: 无监督学习用于聚类、降维和关联规则挖掘等任务。在聚类任务中,算法试图将数据集中的样本分为不同的组;在降维任务中,算法试图减少数据的维度;在关联规则挖掘中,算法试图找到数据中的关联性。
-
学习过程: 模型在没有明确目标的情况下,自动发现数据中的结构和模式。它不需要事先知道正确的输出。
-
例子: K均值聚类、主成分分析(PCA)、Apriori算法等都是无监督学习的例子。
区别
-
数据标签: 监督学习使用带有标签的数据,而无监督学习使用没有标签的数据。
-
任务类型: 监督学习用于分类和回归等有标签任务,而无监督学习用于聚类、降维和关联规则挖掘等无标签任务。
-
学习过程: 监督学习侧重于模型预测与真实标签的关系,而无监督学习侧重于发现数据中的模式和结构,不依赖事先提供的输出信息。
2.1 监督学习
监督学习的训练集要求包括输入输出,也可以说是特征和目标。训练集中的目标是由人标注的。
从输入 / 输出中总结运算规律进行机械学习的算法叫做监督学习。在监督学习中,每个实例都是由一个输入对象(通常为矢量)和一个期望的输出值(也称为监督信号)组成。监督学习算法是分析该数据的输入对象与输出值 ,总结当中的运算规律并产生一个推断的逻辑,并可以把此逻辑用于映射出的新实例,对没有运算过的数据结果进行预测。
其过程就像读小学时候的数学应用题,课堂上老师会先讲解应用题的公式与计算方法,然后学生可以在做作业时根据此计算规律完成类似的题目。
常见的监督学习包含了线性回归、k近邻、朴素贝叶斯分类 、决策树、随机森林与梯度提升决策树、支持向量机等多种算法,在下面将用不同实例介绍其应用场景。
2.2 无监督学习
在非监督学习中,数据没有附带任何标签,学习过程中并不知道分类结果是否正确。
相比之下无监督学习只有输入数据,没有提供输出结果,只能通过计算评估其中的运行规律。
就好比在考试中遇到作业上没有做过的应用题,只能通过思考总结才能得出答案。它的最大挑战在于实例没有包含最终结果,所以无法在学习中评估算法是否学到了有用的东西。
常见的无监督学习分为聚类、降维两大类,包含了PCA(主成分分析)、NMF(非负矩阵分解)、t-SNE(流形学习)、k均值聚类、DBSCAN 等多种算法,
2.3 强化学习
-
定义:智能体通过与环境互动,学习在不同状态下采取最佳行为以获得最大累积回报。
-
示例:AlphaStar 通过强化学习训练,在星际争霸游戏中战胜职业选手。
-
特点:模拟生物学习过程,有望实现更高智能,关注智能体的决策过程。
机器学习可分为监督学习与无监督学习两种
1.4 机器学习算法分类
传统机器学习算法主要包括以下五类:
-
回归:建立一个回归方程来预测目标值,用于连续型分布预测
-
分类:给定大量带标签的数据,计算出未知标签样本的标签取值
-
聚类:将不带标签的数据根据距离聚集成不同的簇,每一簇数据有共同的特征
-
关联分析:计算出数据之间的频繁项集合
-
降维:原高维空间中的数据点映射到低维度的空间中
二、基本概念
在机器学习里,每一行的数据实例被看作是一个样本,每一列的数据被看作是一个特征。学过面向对象开发的朋友应该好理解,这相当于一个类与其属性的关系。而监督学习是通过一系列样本计算,总结出特征与计算结果之间的关系,这被称为特征提取。
2.1 分类与回归的区别
监督学习分成分类与回归两大类:分类与回归
分类的目标是预测类别标签,类似于通过人脸识别分出黄种人、白种人、黑种人。
回归的目标则是预测一个连续值,相当于数学里面的坐标图,它可以通过已有的数据计算出坐标的走向,从而对末知值进行预测。类似于气温预计,GDP增速预算。
其实区分分类与回归很简单,只要判断输出值是否具备连续性,具有连续性的就是回归,只有若干个固定值的就是分类。
2.2 数据划分
从监督学习的概念可以了解,其学习目标是要从已有的数据中总结出各个特征与结果之间的关系,然而这个计算模型的泛化能力如何,我们无法从已通过运算过的数据中得知。所以在运算前,一般会先对数据进行划分,一部分是训练数据,专门用作模型的学习,另一部分是测试数据,用作模型的测试,其比例一般是75%对25%。
为了方便数据划分,sklearn 提供 train_test_split 函数方便日常使用,下一节将有介绍。
2.3 过拟合与欠拟合
对于训练数据最重要的目标是将其泛化,总结出每个特征的比重,因此并非正确率越高越好。
如果在训练过程中,得到的正确率是100%,然而在测试时候,正常率却很低,不能泛化到测试数据当中。这往往是因为训练过程中存在过似合,过度重视某些特征,而忽略某些关键因素。
相反,如果模型过分简单,考虑的因素太少,甚至导致在训练过程中的正确率就很低,这可能就是因为模型的欠拟合造成。
过拟合 :训练误差小,泛化误差大
欠拟合:训练误差大,泛化误差大
所以在选择模型的时候,需要在过拟合与欠拟合之间作出权衡(如图)。
2.4 损失函数
损失函数一方面跟数学计算原理的应用关系比较密切,另一个方面它也是机器学习的基层原理,
在日常对数据模型的测试中,预测值与真实值总会存在一定的偏差,以直线方程 y=a*x+b 为例,如下图。在预测值 [x1,y1] [x2,y2] [x3,y3] ....... [x(i),y(i)] 中,并非每个点与方程匹配,而是存在一定的误差。所以在测试中,当误差值最小时,可以看作这条直线的正确答案。
损失函数就是用来评价模型的预测值和真实值不一样的程度,当损失值越小,证明预计值越接近真实值,模型的训练程度就越好。为了让预测值 y^ (i) 尽量接近于真实值 y(i) ,学者提出了多个方法进行计算损失值,最常见的损失函数有均方误差(MSE)、交叉熵误差(CEE)等。
均方误差(MSE)
均方误差(MSE)中,因为每个预测值与真实值大小不同,为了解决差值的正负值之分,所以误差大小就用差值平方来表示,差值越小,平方值小,误差越小。
均方误差计算公式就是求预测值与真实值之间的方差平均值,如果均方误差越小,那就证明预测值越接近于真实值。
交叉熵误差(CEE)
交叉熵误差(CEE)的公式如下,其中 为实际的分类结果, 为预测的结果
把它用于分类模型时有一个很好的特性,可以真实的反应出真实分类结果和预测结果的误差,假设 , 即真实的分类结果是 , 则 交叉熵误差可以简化为 ,那函数图像如下。可以看到, 越接近 ,即预测结果和真实分类结果越接近,误差越接近, 即误差越小。
关于损失函数有多种算法,下面介绍两种最常用也是最容易理解的算法:最小二乘法(OLS)与梯度下降法(GD)
2.4.1 最小二乘法
最小二乘法是基于 MSE 均方误差而来,它的目标就是求出 n 个 y^ (i) 与 y(i) 误差值平方和最小时各常量参数的值。还是以上面提到的直线方程 y=a*x+b 为例,均方误差越小,证明预测值越接近于真实值,这时候只要求出最小均方误差时 a,b的值,也就可以得出此直线的方程。因为 n 是个常数,所以求最小均方误差的公式可以转化为求预测值 y^ (i) 与真实值之 y(i) 间的最小方差,这就是最小二乘法的由来。
代入 y=a*x+b 后,计算公式可得到转换成下图,由于计算的是平方和,所以表达式必然存在最小值,通过偏导数为 0 时得极值的原理,可得到计算公式:
此时好办,最小二乘法已经变成高考的导数题,要了解求解过程的程序猿建议去复习一下高考时偏导数求解的方法(若怕麻烦通过几条简单的语法计算也可得到最终结果)。根据以下得出的公式,代入已知的数据点 [x1,y1] [x2,y2] [x3,y3] ....... [x(i),y(i)] 便可得到最后的 a、b 参数值,最后把 a、b 值代入直线方程就是最终的答案。
第四节介绍的线性回归模型中,有部分就是使用最小二乘法来实现的,敬请留意。
当然,现实情形下数据模型是复杂的,不可能完全按照直线模型来走,所以复杂的线性模型还可以通过多次方程式,基函数,线性分割等多种方法来处理,在后面章节将会详细讲述。
2.4.2 梯度下降法
上面提到损失函数就是用来评价模型的预测值和真实值不一样的程度,损失值越小证明参数的预测值越接近于真实值。
梯度下降法就是用于求损失值最小时的参数值,相对于最小二乘法复杂的数学公式,它可以通过偏导数斜率的变化更形象地描述解决的过程。
先介绍梯度下降法用到的基本概念:
切线斜率:从数学的角度可知,一维函数在点 x 的导数叫做函数在点 x 的切线斜率,二维函数在点(x0,x1) 的偏导数称为点(x0,x1) 的切线斜率,如此类推。
鞍点:函数的极小值(最小值)被称为鞍点,从数学原理可知当到达鞍点时,切线斜率接近于 0。
梯度:以常用的二元方程 f(x0,x1)=x02+x12 为例子,把全部变量的偏导数(切线斜率)汇总成的向量称为梯度
下面以一个二次方程 f(x)=x2+1 为例,介绍一下如何通过梯度下降法求极值
首先,切线的斜率可以通过导数原理求得,例如 f(x) 分别经过点 A(- 4,17) ,B(- 5,26),此时会发现,两点之间的距离越小,它们所组成的直线就越接近于该点的切线。两点距离无限接近于0时,此时可认为这条直线就是该点的切线,这也是微积分的基本原理。
下面的例子就是实现上述的原理,画出与点(- 4,17) 间 x 轴的距离分别为 0.3、0.2、0.001,0.0001 的直线。调用 tangent()可以返回该直线的斜率,当 h 使用默认值 0.0001 值,该直线斜率已经无限接近于导数值(即切线斜率)。
class gradient_drop():
def __init__(self):
return
def f(self, x):
return x*x+1
def polt_line(self):
# 画出 y=x*x+1 图
x = np.linspace(-5, 5, 100)
plt.plot(x.reshape(-1, 1), self.f(x))
plt.xlabel('x')
plt.ylabel('f(x)')
def tangent(self, x, h=0.0001):
# 根据 y=ax+b 直线公式
# 求导数,即切线斜率
a = (self.f(x+h)-self.f(x))/h
# 求截距
b = self.f(x+h)-a*x+h
# 划出切线
self.plot_tangent(a, b)
return a
def plot_tangent(self, a, b):
# 划出直线 y=ax+b
x = np.linspace(-5, -1, 100)
y = a*x+b
plt.plot(x.reshape(-1, 1), y, '--')
gradientdrop = gradient_drop()
gradientdrop.plot_line()
# 分别以 h 等于 -0.3,-0.2,-0.001, 0.0001求斜率
# 将发现 h 越小,所得斜率越接于近切线斜率
for h in [-0.3, -0.2, 0.001, 0.0001]:
print('h={0}, tangent={1}'.format(h, gradientdrop.tangent(-4, h)))
plt.show()
#在这个字符串中,{0} 和 {1} 是占位符,分别表示要插入的第一个和第二个变量。
#format() 方法中的参数 h 和 gradientdrop.tangent(-4,h) 分别对应这两个占位符的位置。
运行结果
梯度下降法最终的目标是求得切线斜率接近无限于0时的数据点(鞍点), 所以函数可以使用最简单的方法,使取值沿着当前梯度方向不断前进,然后重复计算梯度。通过此递归方式,切线斜率就是无限接近于0。
用数学公式表达如下图,η 表示学习率,学习率可以根据实际需要而改变,将学习率乘以该点的切线斜率代表学习量。
根据此公式,可以在上面的代码中加入一个简单的方法gradient(),以 0.01 的学习率,重复1000次进行计算。随着梯度不断地下降,x 坐标就会根据学习量不断接近鞍点,在重复1000后可以看到在数据点(0,1)处的切线斜率 tangent 为 -1.0098588631990424e-08,已无限接近于 0 ,此时鞍点的函数值 f(x)=1 就是此函数的最小值。
class gradient_drop():
def __init__(self):
return
def f(self, x):
return x*x+1
def plot_line(self):
# 画出 y=x*x+1 图
x = np.linspace(-5, 5, 100)
plt.plot(x.reshape(-1, 1), self.f(x))
plt.xlabel('x')
plt.ylabel('f(x)')
def tangent(self, x, h=0.0001):
# 根据 y=ax+b 直线公式
# 求导数(切线斜率)
a = (self.f(x+h)-self.f(x))/h
# 求截距
b = self.f(x+h)-a*x+h
# 随机画出切线
n = np.random.randint(100)
if n == 5:
self.plot_tangent(a, b)
return a
def plot_tangent(self, a, b):
# 划出切线 y=ax+b
x = np.linspace(-5, 1, 100)
y = a*x+b
plt.plot(x.reshape(-1, 1), y, '--')
def gradient(self, x, rate=0.01, n=1000):
# 学习率默认为0.01,默认重复1000次
for i in range(n):
x -= self.tangent(x) * rate
print('x={0}, f(x)={1}, tangent slope={2}'.format(x, self.f(x), self.tangent(x)))
gradientdrop = gradient_drop()
gradientdrop.plot_line()
# 使用学习率默认0.01,默认重复1000次求出鞍点
gradientdrop.gradient(-3)
plt.show()
运行结果
到此不防思考一下使用梯度下降法找到鞍点的目标是什么,其实只要把简单的二次方程 f(x) 替换成为损失函数便会豁然开朗。以均方误差 MSE 为例,当找到鞍点,意味着找到函数最小值,即在该点时均方误差最小,在这点得到的参数值就是该函数的常量。
同样以最小二乘法中的直线 y=a*x+b 为例,把代码稍微修改一下。首先把方程改为均方误差公式,通过 sympy 包中的函数 diff 分别对 a,b 求偏导数,把学习率设置为0.01,训练1000次,a,b的默认初始值均为 1。使用 sklearn 中的测试数据 make_regression 进行训练,最后画出该直线并输出斜率和截距。
梯度下降法的步骤如下:
-
初始化参数:选择初始参数值。目标函数是 损失函数
-
计算梯度:计算目标函数相对于参数的梯度(导数),即确定当前参数值的下降方向。
-
更新参数:根据梯度和学习率的乘积,更新参数值,以便沿着梯度的反方向移动一小步。学习率决定了每次更新的步长大小。参数新=参数旧−学习率×偏导数
-
重复步骤2和3,直到满足停止条件,例如达到最大迭代次数或参数变化小于某个阈值。
class gradient_drop():
def __init__(self, train_x, train_y):
# 定义测试数据
self.x = train_x
self.y = train_y
return
def mes(self, a, b):
# 均方误差计算公式
return mean((self.y-a*self.x-b)**2)
def partial_derivative(self, a, b):
# 求 mes(a,b)对 a,b 的偏导数
partial_derivative_a = sp.diff(self.mes(a, b), a)
partial_derivative_b = sp.diff(self.mes(a, b), b)
return [partial_derivative_a, partial_derivative_b]
def gradient(self, rate=0.01, n=1000):
# 学习率默认为0.01,默认重复1000次
# 把 y=a*x+b 参数 a,b 的初始值设为 1,1
a1 = 1
b1 = 1
# 默认训练1000次,找到最小均方误差时的 a,b 值
for i in range(n):
deri = self.partial_derivative(a1, b1)
a1 -= deri[0].subs({a: a1, b: b1}) * rate
b1 -= deri[1].subs({a: a1, b: b1}) * rate
# 输出直线参数 a,b 值
print('y=a*x+b\n a={0},b={1}'.format(a1, b1))
return [a1, b1]
def plot_line(self, param):
# 根据a,b参数值划出直线 y=a*x+b
x = np.linspace(-3, 3, 100)
y = param[0]*x + param[1]
plt.plot(x, y, 'r')
plt.legend(['train data', 'line'])
# 输入测试数据
X, y = dataset.make_regression(n_features=1, noise=5)
gradient_drop = gradient_drop(np.squeeze(X), y)
# 画出数据点
plt.plot(X, y, '.')
# 训练数据找出最小均方误差时的参数 a,b 值
param = gradient_drop.gradient()
# 画出训练后的直线
gradient_drop.plot_line(param)
plt.show()
运行结果
可见计算后的直线与训练库中的点已相当接近,使用梯度下降法只需要牢记一点:计算目标是求出鞍点,在损失值最低时的参数值就是该函数的常量。下面介绍到的 SGD 模型正是使用梯度下降法进行计算,后面将有详细说明。
对损失函数就介绍到这里,希望对各位的理解有所帮助。
三、常用方法介绍
Scikit-Learn 是目录最常用的机器学习库,所以在本文当中大部实例都是运用当中的方法完成。
在 sklearn.datasets 中包含了大量的数据集,可为运算提供测试案例。例如鸢尾花数据集 load_iris()、癌症数据集 load_breast_cancer()、波士顿放假数据集 load_boston() 这些都是各大技术文章里常用的数据集,为了方便阅读下面大部分的例子中都会用到这些数据作为例子进行解说。
3.1 train_test_split 方法
train_test_split
方法是用于将数据集划分为训练集和测试集的函数。
这个方法通常在机器学习库(如Scikit-learn)中提供,其功能是将数据集按照指定的比例或数量划分为训练集和测试集。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
train_test_split( * arrays, test_size=None, train_size=None, random_state=None, shuffle=True,stratify=None)
-
arrays
:要划分的数据集,可以是列表、NumPy数组、SciPy稀疏矩阵或Pandas的数据框。 -
test_size
:测试集的大小。可以是浮点数、整数或None,默认为None。①若为浮点时,表示测试集占总样本的百分比
②若为整数时,表示测试样本样本数
③若为None时,test size自动设置成0.25
-
train_size
:训练集的大小。可以是浮点数、整数或None,默认为None。含义与test_size
类似。 -
random_state
:随机种子,用于控制数据的随机划分。可以是整数、RandomState实例或None,默认为None。①若为None时,每次生成的数据都是随机,可能不一样
②若为整数时,每次生成的数据都相同 (,如果你需要多次运行同样的实验,或者 在不同的环境中重复实验,你会得到相同的训练集和测试集划分,从而可以确保实验 结果的可重现性。)
-
stratify
:用于处理不均衡数据集,可以是类似数组或None。①若为None时,划分出来的测试集或训练集中,其类标签的比例也是随机的
②若不为None时,划分出来的测试集或训练集中,其类标签的比例同输入的数组中 类标签的比例相同,用于处理不均衡数据集
在一个垃圾邮件分类器的任务中,我们的目标是根据邮件的内容将其分类为"垃圾邮件"或"非垃圾邮件"。在这种情况下,"垃圾邮件"和"非垃圾邮件"就是类别标签。在
train_test_split
方法中,stratify
参数的作用是保持划分后训练集和测试集中类标签的分布与原始数据集中的类标签分布相同。
from sklearn.datasets import make_wave
from sklearn.model_selection import train_test_split
# 将1000个数据集按照默认比例划分为训练集和测试集
X, y = make_wave(n_samples=1000)
X_train, X_test, y_train, y_test = train_test_split(X, y)
# train_size 和 test_size 默认值为 75% 和 25%
# 所以上面的例子与下面的例子得到的结果相同
X, y = make_wave(n_samples=1000)
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.75, test_size=0.25)
# 为了每次测试得到相同的数据集,可以将 RandomState 设置为相同的值
# 只要 RandomState 相同,则产生的数据集相同
# 因为 RandomState 默认为空,因此在不填写的情况下,每次产生的数据集都是随机数据
X, y = make_wave(n_samples=1000)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
3.2 predict 方法与 accuracy_score 方法
在分类模型中,通常使用 predict(selt, X:any)方法预测新数据的标签,通常在完成训练后,就是通过此方法输入测试数据,把计算结果与测试结果进行对比。
accuracy_score 主要用于对比预测结果的准备率
下面的代码就是最简单的流程,先划分训练数据与测试数据,然后选择模型,输入训练数据进行泛化,输入测试数据求出计算结果,最后把计算结果与已有的测试结果进行对比,查看其正确率。
1 X,y=make_blobs(n_samples=150,n_features=2) 2 #划分训练数据与测试数据 3 X_train,X_test,y_train,y_test=train_test_split(X,y) 4 #绑定模型 5 knn_classifier=KNeighborsClassifier(n_neighbors=7) 6 #输入训练数据 7 knn_classifier.fit(X_train,y_train) 8 #运行测试数据 9 y_model=knn_classifier.predict(X_test) 10 #把运行结果与测试结果进行对比 11 print(accuracy_score(y_test,y_model))
3.3 score 方法
在回归模型当中,由于测试结果并非固定值,所以一般通过使用 score(self, X, y, sample_weight=None) 方法,通过对 R^2(判定系数)来衡量与目标均值的对比结果。
R^2=1,则表示模型与数据完成吻合,如果R^2为负值,侧表示模型性能非常差。
1 X,y=make_wave(1000) 2 X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0) 3 linearReg=LinearRegression() 4 linearReg.fit(X_train,y_train) 5 print(linearReg.score(X_train,y_train))
3.4 numpy.meshgrid 方法
生成网格点矩阵坐标,往往用于对平面内数据的预测值进行评估。生成一定范围内的网格数据,再把数据代入公式内进行计算,得到预测结果。
1 x=np.array([1,2,3]) 2 y=np.array([4,5]) 3 #显示网格矩阵坐标 4 X,Y=np.meshgrid(x,y) 5 print('X:\n '+str(X)) 6 print('Y:\n '+str(Y))
运行结果
3.5 contour 和 contourf 方法
pyplot 的 contour 和 contourf 方法都是画三维等高线图的,不同点在于contour 是绘制轮廓线,contourf 会填充轮廓。本文在分类模型中,将会大量地使用此方法,让各位可以更直观的看到模型预测值的分布。
pyplot.contour (X,Y,Z,levels , linestyles,alpha,cmap )
X、Y : 必须是 2-D,且形状与 Z 相同。
Z:绘制轮廓的高度值。
levels:int 数组,可选填,确定需要显示的轮廓线区域的数量和位置。例如: levels = [-2,-1,0,1,2] 表示显示从-2级到2级的线区轮廓。
linestyles:数组,可选填,确定线条形状,例如:linestyles = [ '--' , '-' , '=' ] 。
alpha: 透明度
cmap:颜色
1 def f(x,y): 2 return 3*x**2+x+y**+1 3 4 x=np.linspace(-3,3,100) 5 y=np.linspace(-3,15,100) 6 X,Y=np.meshgrid(x,y) 7 plt.contourf(X,Y,f(X,Y)) 8 plt.show()
运行结果
3.6 decision_function 方法
在分类模型中,通常使用 decision_function(self, X) 方法计算预测新数据的距离值。
与 predict 方法不同的是:predict 得到的标签值, decision_function 得到的是与分隔超平面的距离值。
1 # 训练数据 2 X,y=dataset.make_blobs(centers=2,random_state=2,n_features=2) 3 # 使用 LinearSVC 模型,设置 C=100 4 linear=LinearSVC(C=100) 5 linear.fit(X,y) 6 # 画出数据点 7 plt.scatter(X[:,0],X[:,1],c=y,marker='^',s=50) 8 # 建立网格数据 9 xx=np.linspace(-5,6,2) 10 yy=np.linspace(-13,3,2) 11 XX,YY=np.meshgrid(xx,yy) 12 ZZ=np.c_[XX.ravel(),YY.ravel()] 13 # 根据网络数据推算出预测值 14 zz=linear.decision_function(ZZ) 15 aa=linear.predict(ZZ) 16 print('predict: '+str(aa)) 17 print('decision_function:'+str(zz))
运行结果
predict 得到的最终的分类结果:0或1,而 decision_function 得到的是与分隔平面的距离,正值代表分类是 1,负值代表分类为 0,值越大代表与分隔面的距离越大。
3.7 confusion_matrix 混淆矩阵
在数据分析的过程中,往往需要观察各分类数据的占比,准确数,错误数等相关信息,为此 sklearn 特意预备了混沌矩阵 confusion_matrix 函数帮助分析数据,完成分析后用 Seaborn 把图画出来。
下面的例子就可以通过混淆矩阵把测试中的 0,1,2,3 ..... 9 的数字分布数量很明确显示出来。
1 (X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data() 2 # 把28*28图像数据进行转换 3 X_train = X_train.reshape(-1, 784) 4 X_test = X_test.reshape(-1, 784) 5 # 使用SGDClassfier模式,使用多核计算,学习率为0.01 6 sgd_classifier = SGDClassifier(learning_rate='constant', early_stopping=True, 7 eta0=0.001, loss='squared_hinge', 8 n_jobs=-1, max_iter=10000) 9 sgd_classifier.fit(X_train, y_train) 10 y_model=sgd_classifier.predict(X_test) 11 #建立混淆矩阵 12 mat=confusion_matrix(y_test,y_model) 13 #显示分类数据的测试分布 14 heatmap(mat,square=True,annot=True,fmt='d') 15 plt.show()
运行结果
3.8 validation_curve 验证曲线
上一节曾经讲过,要提高模型的质量,应该在过拟合跟欠拟合当中,选择一个平衡点。
有见及此,为了更直观地了解模型的质量,sklearn 特意准备了 validation_curve 方法 ,可以更直观与观察到验证曲线的示意图。
validation_curve(estimator, X, y, *, param_name, param_range, groups=None,
cv=None, scoring=None, n_jobs=None, pre_dispatch="all",
verbose=0, error_score=np.nan, fit_params=None)
- estimator:实现了fit 和 predict 方法的对象
- X : 训练的向量
- y : 目标相对于X分类或回归
- param_name:将被改变的变量名称
- param_range:param_name对应的变量的取值
- cv:如果传入整数,测试数据将分成对应的分数,其中一份作为cv集,其余n-1作为traning(默认为3份)
只需要简单地绑定模型,输入数据,便可得到模型的准确率变化曲线
1 # validation_curve 绑定 SVC 2 X, y = load_digits(return_X_y=True) 3 param_range = np.logspace(-6, -1, 5) 4 train_scores, test_scores = validation_curve( 5 SVC(), X, y, param_name="gamma", param_range=param_range, 6 scoring="accuracy", n_jobs=1) 7 #训练数据与测试数据的平均得分 8 train_scores_mean = np.mean(train_scores, axis=1) 9 test_scores_mean = np.mean(test_scores, axis=1) 10 #显示数据 11 plt.title("Validation Curve with SVM") 12 plt.xlabel(r"$\gamma$") 13 plt.ylabel("Score") 14 plt.ylim(0.0, 1.1) 15 lw = 2 16 plt.semilogx(param_range, train_scores_mean, label="Training score", 17 color="darkorange", lw=lw) 18 plt.semilogx(param_range, test_scores_mean, label="Cross-validation score", 19 color="navy", lw=lw) 20 plt.legend(loc="best") 21 plt.show()
运行结果
下面的章节开始介绍 sklearn 中监督学习的一些常用模型,可能模型的使用方法基本一致,看起来似乎千篇一律。实则不然,因为机器学习与一般的开发不一样,主要是了解不同模型的运算规则和适用场景。从原理中理解实质,希望读者能够明白。