3. 人工智能与机器学习
人工智能是研究开发用于模拟和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。
机器学习是基于大量数据而成,让计算机像人类一样学习和行动的科学,通过以观察和现实世界互动的形式向他们提供数据和信息,以自主的方式改善他们的学习。机器学习包括深度学习、强化学习、传统机器学习等。
深度学习是模拟人脑所构成的,支持从大量数据中学习,学习这些样本数据中的内在规律和表示层次。
强化学习是构建一个智能体,在一个复杂的环境下去最大可能获得奖励,通过感知环境所处的状态对动作的反应来指导获取更好的动作,从而获得最大的收益。
传统机器学习是从一些观测(训练)样本出发,使用统计学、线性代数、优化算法等数学方法,从已有数据中学习并构建预测模型,进而用于对未知数据的预测和分类。
1.1 机器学习
那么如何达到我们定义中像人类学习和行动呢,下面以一个线性回归的例子讲解什么是机器学习。
在X-Y坐标上给定一些样点值,求解一条直线,求该直线可以表示样点值的趋势。这是最基础的线性回归问题,回归分析中,只用一个自变量和一个因变量,且两者的关系可以用一条直线近似表示。
该直线可以看成y=ax函数,其中a代表直线的斜率。如果是依靠我们大致绘制的直线,并测量其a,这样只需要提供x值即可推测出y值。
但这仅局限于数量很少的样点,如果大量的样点数据,依靠人脑是绘制的趋势直线是不准确的。
假设我们设计一个程序求解样点的趋势线,先定义趋势线公式为y=ax,然后如下操作:
-
先随机选取a的值,将样本点的x值代入求出y'值,差值e=(y'-y)^2。如此计算所有样本点的差值,所有差值相加得到总误差E_1 。
-
再将a的值增大或减小:a = a + delta,这个增大或减小的区间值称为步长值。重新计算总误差E_2。
-
对比 E_1和E_2 的值,如果 E_2小于 E_1 ,则代表总误差减小,步长方向正确。如果 E_2大于 E_1 ,则代表总误差增大,步长方向错误,需要修改步长方向: delta = - delta。
-
从步骤2继续循环,直到误差变化不再降低为止。
在这个循环过程中,如果误差比较大,可以加大delta值以减少循环次数;如果误差已经比较小了,可以减小delta值以提高精度。
例如:假设a_1=a_0+步长值,再将所有的样本点重新计算得出新的误差 E_2。对比 E_1和E_2 的值,如果 E_2小于 E_1 ,则代表总误差减小,步长方向正确。如果 E_2大于 E_1 ,则代表总误差增大,步长方向错误,需要修改步长方向。
例如:假设原来的步长值为-0.6,在下次迭代时将 ,
此时步长值=+1 ,使原始的a值增加,然后继续迭代。如果在新迭代后,总误差E值降低了,则证明步长方向修改正确。再按照一定的步长与刚刚a值的方向迭代下去,直到总误差值E不再降低为止,此时得到的a就是对所以已知样本点的最佳拟合函数f(x)=ax的参数。
根据误差的变化趋势决定参数的调整方向,力度(误差越大步长值越大,反之则越小)从而获取最低误差的方式就被称为梯度下降法。
**问:**为什么叫做梯度下降法呢?
**答:**我们在线性回归模型中我们需要根据误差来确定步长的调整,计算的 方式是均方误差函数(损失函数),公式为:
那么我们肯定是想计算出该均方误差公式的最小值,那么想要求得函数最小值,在数学方法中,我们就会想到求导,并求二阶偏导函数的驻点。下面展示均方误差函数J(w)求偏导后的结果:
权重w的迭代过程是以负梯度的方向(减少误差的方向)来决定每次迭代时权重w的变化方向,从而使每次迭代后目标函数(误差函数)的值逐渐减小。
每次迭代都会修改权重w值,使其以α学习速率沿着偏导数的反方向进行移动。
均方误差函数是一个二次函数。它实际的函数图像可能是如图所示的一个抛物线。图中的损失值Cost就是误差值。假设我们在初始a值的点时,我们的损失值很大,我们想要降低损失值,需要沿着函数的梯度方向(函数的方向)往下走,直到找到损失值的最低点(即找到最低的误差值)。
如果是计算大量样本点的时候,可以知道整个迭代过程中运算量是很大,计算机需要不断的在大量样本点中运算、分析、试错、调整、重新计算,这个过程称为训练。线性回归求解训练过程如图所示:
如图所示的回归分析中,训练的目的就是在大量样本点中找出描述样本点之间规律的函数的参数。上述基本线性模型的整个过程称为机器学习。
1.2 模型和拟合
通过前面的线性回归学习我们知道,建立的模型需要与数据集对应,简单的数据集需要对应简单的模型,复杂的数据集需要对应复杂的模型。以求回归问题为例,求下面两个数据集的回归线:
通过观察上面两个数据集可以发现,我们可以发现样本数据集1可以通过建立简单的y=ax+b的线性模型求得该样本的回归线;样本数据集2数据集较为复杂,如果直接使用简单的y=ax+b的线性模型,无法拟合出样本数据集2的回归线,我们称为不拟合,此时需要建立一个更为复杂的模型,如y=ax^2等,对样本数据集进行回归拟合。
从上图可以看出,模型的复杂度需要和数据集的复杂程序对应,如果复杂数据使用简单模型可能会出现不拟合的情况。
如果机器学习的结果拟合度不够高,结果相差很大,称为不拟合。可以加入高次项。但如果加入了过多的高次幂项,可能会导致正确率不升反降,此现象称为过度拟合。过拟合为得到高精度的拟合结果,而使模型变得过度复杂,导致模型参数不合理、表现力、预测力变差。
1.3 线性回归模型
1.3.1 实现简单线性回归
假设提供一些样本点数据,样本点数据为:[1, 3.5], [2, 4.7], [3, 5.3], [4, 7.1],[5, 9.6],[6, 13.5], [7, 16.2], [8, 19.4],[9, 23.2], [10, 33.8],该样本点在图像中的位置如下图所示:
预先构建一个直线函数y=wx,其中w为权重,不考虑偏置值。使用该直线绘制这样本点的线性回归直线,其中权重更新公式如下所示:
下面基于这些样本点我们来构建一个python程序实现,对样本点进行线性回归预测。下面展示代码的流程框图:
代码流程为:
-
导入numpy包,该包是数组处理包,提供了处理 n 维数组的工具,即提供矩阵运算能力。
-
导入matplotlib包,该包可支持Python 的 2D 可视化绘图库,可创建静态、动画和交互式可视化图像。
-
调用求解权重函数,计算直线函数y=wx中的w值。
- 判断是否达到迭代次数。
- 使用权重值w,代入x值计算预测值h
- 计算预测值h和真实值y的差值
- 求解梯度值
- 更新权重值w
- 计算损失值
- 当没有达到迭代次数,继续返回步骤2。当达到迭代次数,则返回权重值。
-
使用新权重值预测数据。
-
将样本点和回归直线绘制到坐标轴上。
1.3.2 简单线性回归代码解析
导入拓展包,支持矩阵运算和可视化
导入numpy包,该包数组处理包,提供了处理 n 维数组 的工具,即提供矩阵运算能力。
导入matplotlib包,该包可支持Python 的 2D 可视化绘图库,可创建静态、动画和交互式可视化图像。
import numpy as np
import matplotlib.pyplot as plt
初始化样本点数据
使用多维数组存储样本点数据,并获得该数组的行数和列数
#样本点数据
x = np.array([[1, 3.5], [2, 4.7], [3, 5.3], [4, 7.1],[5, 9.6],
[6, 13.5], [7, 16.2], [8, 19.4],[9, 23.2], [10, 33.8]])
m, n = np.shape(x) #获得样本点数据的行数和列数 m:行数 10 n:列数 2
print("x样本点数据的行数m和列数n:",m,n)
获得样本点的x值和y值
创建一个10行2列的多维数组,并将其置为0。将每一行的第一列存储样本点数据的x值,存储结果保存在x_data中。
将样本点数据的y值,存储在y_data中。
x_data = np.zeros((m, n)) #新建10行2列矩阵,并将值都置为0
x_data[:, :-1] = x[:, :-1] #获取样本点数据中除最后一列之外的所有行和所有列,即样本点数据中的x
y_data = x[:, -1] #获取样本点数据中所有行和最后一列,-1代表最后一列,即样本点数据中的y
初始化权重值
创建一个权重矩阵,矩阵为[1,0]。
m, n = np.shape(x_data) #获得样本点数据中的x行数和列数 m:行数 10 n:列数 2
theta = np.array([1,0]).reshape(2) #创建一个权重矩阵,初始化权重为[1,0]
定义权重函数
由于我们定义的直线的函数为y=wx,其中w为权重。该函数主要用于求解权重w值,其中实现了权重更新公式和损失函数,如下所示的两个公式:
#求解权重函数
#iter:迭代次数 x:横坐标 y:纵坐标 w:权重 alpha:学习率
def gradientDescent(iter, x, y, w, alpha):
x_train = x.transpose() #交换矩阵的两个维度
for i in range(0, iter):
pre = np.dot(x, w) #矩阵乘法
loss = (pre - y) #预测值和真实值的差值
#权重更新公式
gradient = np.dot(x_train, loss) / m #求解梯度
w = w - alpha * gradient #更新权重
#使用损失函数求解损失值
cost = (1.0 / (2 * m)) * np.sum(np.square((np.dot(x, w)) - y))
print("第{}次梯度下降损失值为: {}".format(i,round(cost,2)))
return w
1.交换矩阵的两个维度
x_train = x.transpose()
2.计算预测值
pre = np.dot(x, w) #矩阵乘法
假设是第一次进行计算,那么x为样本点的x值,w权重为[1,1],计算方式为:
3.计算差值
差值等于预测值减真实值,计算权重更新公式中的h(x)-y部分。公式如下所示:
loss = (pre - y) #预测值和真实值的差值
计算过程如下所示:
4.权重更新
计算梯度值,即将差值 乘 样本点的x值,再除以样本点的个数,公式如下所示:
gradient = np.dot(x_train, loss) / m #求解梯度
计算过程如下所示:
计算新权重
新权重 等于 原权重 减 梯度值 乘 学习率,计算公式如下图所示:
w = w - alpha * gradient #更新权重
计算过程如下所示:
5.计算损失值
损失函数公式为:
cost = (1.0 / (2 * m)) * np.sum(np.square((np.dot(x, w)) - y))
这段程序直接完整实现了损失函数,程序较为复杂,我们直接把该程序从里到外拆开来看。
从括号最里层来看:
np.dot(x, w)
该程序作用是将权重与样本点的x值 相乘 求得预测值。代码实现公式部分为:
(np.dot(x, w)) - y)
该程序作用是求预测值和真实值的差值。代码实现公式部分为:
np.square((np.dot(x, w)) - y)
该程序作用是针对差值进行求平方的操作。代码实现公式部分为:
np.sum(np.square((np.dot(x, w)) - y))
该程序作用是将括号内的矩阵元素进行求和,即将矩阵中的每一个元素进行相加 求和,最终得到一个数。
(1.0 / (2 * m)) * np.sum(np.square((np.dot(x, w)) - y))
该程序主要实现公式前面的1/2m与后面的计算出来的数进行相乘,代码实现公式部分为:
获得新权重
调用求解权重函数后,获得新权重。使用新权重计算预测值,打印输出新权重的值。
result = gradientDescent(1000, x_data, y_data, theta, 0.01) #调用求解权重函数
y_pre = np.dot(x_data, result) #使用新权重求解预测值
print("线性回归模型 w: ", result)
绘制可视化图像
使用matplotlib包中的plt工具绘制坐标系,并将样本点的值绘制在坐标系中,使用绿色的点进行表示;绘制线性回归直线在坐标系中,使用红色的线进行表示;使用一个窗口显示绘制的图像。
plt.scatter(x[:, 0], x[:, 1], color='g',label ="Points") #在XY坐标轴上绘制样本点,样本点的颜色为绿色,标签值为Points
plt.plot(x[:, 0], y_pre, color='r',label ="Linear Regression") #在XY坐标轴上绘制线性回归直线,颜色为红色
plt.xlabel('x') #横坐标的标签
plt.ylabel('y') #纵坐标的标签
plt.legend() #给图像加图例,将样本点和直线的标签值增加到图像中
plt.show() #显示所有打开的图形,即打开一个窗口显示图片
总结
该程序主要带大家了解使用python中的numpy库进行求解线性回归问题,手动实现一个最简单的线性回归模型,了解在机器学习中的训练、损失函数、梯度等概念,同时学习如何在python程序中实现矩阵进行加减乘除操作。大家如果对公式不太理解,可查看线性回归梯度下降公式推导。
1.3.3 Sklearn实现房价预测模型
这里参考经典的波士顿房价预测问题,假设你是一个房产经理人,现在你需要根据手上拥有的房产数据回答客户的问题,客户会提出想购买的房屋面积,你需要根据房屋面积给客户进行报价。
想要解决这个问题,我们需要建立的一个回归模型,并使用房产数据进行训练,训练出的模型可以根据当前地区的房屋面积预测平均价格。这里收集了本地的房地产市场数据,使用开源的机器学习库Scikit-learn,对数据进行回归模型的训练,将训练结果进行线性回归和预测。
下面展示100个房地产数据样本的散点图,横坐标为房屋面积,纵坐标为房屋价格。
使用表格的形式将房地产数据样本存储在HousePrice.csv
表格文件下,使用pandas读取表格文件下的样本数据,使用Scikit-learn库中内置的线性回归建立模型,并使用HousePrice.csv
文件中的数据进行训练,训练完成之后,将回归直线绘制在房地产数据样本的散点图上。程序流程图如下所示:
代码流程为:
- 导入numpy包,该包是数组处理包,提供了处理 n 维数组的工具,即提供矩阵运算能力。
- 导入matplotlib包,该包可支持Python 的 2D 可视化绘图库,可创建静态、动画和交互式可视化图像。
- 导入pandas包,该包是数据分析支持库,提供强大的数据处理和分析工具,可支持数据的导入、清洗、转换和分析。
- 导入sklearn包,该包是开源机器学习库,它基于NumPy、SciPy和matplotlib,支持各种机器学习模型,包括分类、回归、聚类和降维等。
- 使用pandas库读取csv文件,获取表格文件中房产样本数据,包括房屋面积和售价。
- 拆分数据集,将1/4的数据集划分为测试数据集,剩下3/4的数据集划分为训练数据集,用于构建线性回归模型。
- 使用sklearn内置的LinearRegression函数构建线性回归模型,将训练数据集作为参数传入,并进行训练得到线性模型的权重值和偏置值,即函数y=wx+b中的w和b。
- 使用训练得到的线性模型传入测试数据集中的数据进行预测,得到预测值。
- 使用matplotlib的工具将样本点和回归直线绘制到坐标轴上。
1.3.4 Sklearn房价预测代码解析
导入拓展包,支持矩阵运算、可视化、
-
导入numpy包,该包数组处理包,提供了处理 n 维数组的工具,即提供矩阵运算能力。
-
导入matplotlib包,该包可支持Python 的 2D 可视化绘图库,可创建静态、动画和交互式可视化图像。
-
导入pandas包,该包是数据分析支持库,提供强大的数据处理和分析工具,可支持数据的导入、清洗、转换和分析。我们主要使用该包用于读取文件中的房产数据。
-
导入sklearn包,该包是开源机器学习库,它基于NumPy、SciPy和matplotlib,支持各种机器学习模型,包括分类、回归、聚类和降维等。我们主要是使用该包中预先定义好的线性回归模型,帮助我们拆分数据集,并训练文件中的房产数据。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
读取数据文件中的样本
使用pandas库中read_csv函数读取数据集文件,该函数读取文件后会返回一个reader对象,该对象遍历csv文件的每一行,并返回每一行作为一个列表。
使用pandas库iloc函数读取数据的某行或者某列,将数据集中的除了第一列的所有数据,将所有数据转换为numpy数据,并存放在X中;将数据集中的最后一列的的所有数据,将所有数据转换为numpy数据,并存放在Y中;
dataset = pd.read_csv('HousePrice.csv') #读取csv文件,即读取数据集文件
X = dataset.iloc[ : , : 1 ].values #获取样本点数据中的所有行和除了第1列,即样本点数据中的x
Y = dataset.iloc[ : , 1 ].values #获取样本点数据中所有行和第1列,1代表第一列,即样本点数据中的y
拆分数据集
使用sklearn库中train_test_split函数可以将样本数据拆分为训练数据集和测试数据集,X
为输入数据,Y
为结果数据,test_size = 1/4
为拆分四分之一的数据出来作为测试数据集。
#将数据集拆分为训练数据集X_train,Y_train和测试数据集X_test,Y_test
X_train, X_test, Y_train, Y_test = train_test_split( X, Y, test_size = 1/4)
使用sklearn创建线性回归模型
使用sklearn库中LinearRegression函数创建一个普通最小二乘法的线性回归,使用fit方法传入训练数据集,拟合线性模型,其中权重更新和损失函数的公式与上一小节我们手动构建的线性回归是一致的。公式如下所示:
model = LinearRegression() #创建线性回归模型
model = model.fit(X_train, Y_train) #训练拟合线性模型
print("****************************")
print("House Price Prediction Done!")
print("model Regression coefficient:",model.coef_) #打印输出权重
print("model Regression intercep",model.intercept_) #打印输出偏置
使用训练后的模型预测新数据
将测试集中的数据传入训练后的线性回归模型进行预测,并打印真实数据和预测数据。
Y_pred = model.predict(X_test) #模型预测
print("测试集中的真实值:",Y_test)
print("测试集中的预测值:",Y_pred)
绘制可视化图
使用matplotlib包中的plt工具绘制坐标系,并将样本点的值绘制在坐标系中,使用绿色的点进行表示;绘制线性回归直线在坐标系中,使用红色的线进行表示;使用一个窗口显示绘制的图像。
plt.scatter(X , Y, color = 'green') #在坐标轴上绘制样本点,颜色为绿色
plt.plot(X , model.predict(X), color ='red') #在坐标轴上绘制回归直线,颜色为为红色
plt.xlabel('Size/m^2') #横坐标的标签
plt.ylabel('Price/w') #纵坐标的标签
plt.show() #显示所有打开的图形,即打开一个窗口显示图片
总结
该程序主要是使用pandas库读取数据集表格文件,读取出房产样本数据后,使用Sklearn库中的回归算法建立模型文件,将房产样本数据传入后训练生成符合房产数据集的线性回归模型。我们使用预先定义好的线性回归模型就可以不用从头开始实现数学公式,可以快速的帮助我们解决线性回归问题,只需要关注训练后的模型是否符合自己的目标。