线性回归是机器学习中形式比较简单的模型,能够很好的进行推导和求解,也便于图形化展示。关于线性回归的概念和表示,在线性回归的概念与表示有比较详细的的介绍。本文通过手动实现、调用scikit-learn类库两种方式演示了线性回归模型,并通过matplotlib进行了可视化展示。
实现过程
本次实践的流程如下图所示:
实践分为四个步骤:数据准备、模型求解、查看结果、可视化展示。每一步要做的工作如下:
第一步:准备数据
机器学习就是从数据中进行学习的科学。关于数据的处理,已经逐步成为一门专门的科学和工作,数据的质量也成了模型好歪的关键之一。
本次实践的核心是展示线性回归模型的逻辑,为了处理简单,也为了把精力聚焦在模型上,这里通过一段简单的代码自己生成数据,这样就可以减少数据预处理的工作。
第二步:模型求解
关于机器学习,有很多著名的类库可以使用,这里我们采用两种方式:
1、手动编码实践一下推演的过程
2、使用现在比较流行的类库直接进行求解
第三步:查看结果
这一步主要用来查看在第2步求解的结果,并与第1步中设置的真相(truth)是否吻合。
第四步:可视化展示
线性回归是最经典的、也最容易理解、也是少有的能够直观查看结果效果的,在这里加入了一个绘图的步骤,可以直观查看求解出来的模型与现实情况的吻合度情况。
在这个实践中,这一步不是必须的,但是可视化能够让人的感觉更加直观。同时,可视化技术也是当今比较热门的技术之一。
数据准备
先设置样本数量,x取值在0~2之间,然后按照 y=3x+7 的方式生成y;
因为在后面的求解中,会把 b 的系数当做 1 一起进行矩阵运算,因此这里把x向量进行了扩展。
# 导入科学计算包
import numpy as np
# 定义样本数量, 方便调试
nums = 100
# 0-2之间的数
x_p = 2 * np.random.rand(nums, 1)
# 定义一个 不管三七二十一 模型
y = 3 * x_p + np.random.randn(nums, 1) + 7
b = np.ones((nums, 1))
x = np.concat((x_p, b), 1)
模型求解
手动实现
定义个线性回归的求解器。根据西瓜书上的(3.11) 这个公式来计算结果。公式定义如下:
使用NumPy之后,矩阵计算非常方便:
# 导入科学计算包
import numpy as np
def lr_solver(x_list, y_list):
# 将list数据转换为矩阵
x_mat = np.asmatrix(x_list)
# 将矩阵转置
y_mat = np.asmatrix(y_list)
# 计算出x的转置*x
xTx = x_mat.T * x_mat
# 判断行列式值是否为0,为0则矩阵不可逆
if np.linalg.det(xTx) == 0.0:
print("矩阵不可逆")
return
# 计算系数w的公式
w = xTx.I * (x_mat.T * y_mat)
return w
使用类库
从下面的代码可以看到,使用类库的话只需要从 scikit-learn 中引入线性回归求解器,然后就可以进行直接求解,代码只有两行。
值得注意的是:接下来的代码是为了将求解的结果转换成和手动实现的输出格式一致,便于直观对比。
# 导入科学计算包
import numpy as np
# 导入 scikit-learn 中的线性回归模型
from sklearn.linear_model import LinearRegression
def lib_solver(x_list, y_list):
lr_model = LinearRegression()
# 使用库求解
lr_model.fit(x_list, y_list)
# 这里为了验证结果,仅作事例,将输出结果简单化了
ar = np.array([lr_model.coef_[0][0], lr_model.intercept_[0]])
lib_w = np.asmatrix(ar).T
return lib_w
查看结果
调用求解器,进行求解,并打印结果
# 使用手动实现的求解器求解
w1 = lr_solver(x, y)
# 使用sklearn求解
w2 = lib_solver(x, y)
print(w1)
print(w2)
运行结果如下:
[[2.8179187 ]
[7.28867782]]
[[2.8179187 ]
[7.28867782]]
还记得在数据准备时,我们设定的 三七吗?结果与(3,7)很接近。发现两个求解结果一样的,可以思考下为什么!
可视化展示
为了直观的查看效果,还可以定义一个散点图和求解的结果。
# 导入matplotlib绘图库
import matplotlib.pyplot as plt
# 打印出散点图
def ploter(x_mat, y_mat, w):
# 绘制散点图
plt.scatter(x_mat[:, 0].tolist(), y_mat.tolist())
# 绘制拟合直线图
plt.plot(x_mat[:, 0].tolist(), x_mat * w.tolist(), color='red')
plt.show()
在调用代码里加上可视化
w1 = lr_solver(x, y)
w2 = lib_solver(x, y)
print(w1)
print(w2)
# 图形展示
ploter(np.asmatrix(x), np.asmatrix(y), w1)
ploter(np.asmatrix(x), np.asmatrix(y), w2)
再次运行,发现结果变了,但离我们设定的(3,7)比较接近;
这是因为测试样本数据每次都是随机生成的,不同的数据产生了不同的偏差。
[[2.90457685]
[7.2602735 ]]
[[2.90457685]
[7.2602735 ]]
相对应的散点图及求解结果(红线)如下:
运行环境
本次使用PyCharm编写。
Python版本:python 3.11。
手动实现,依赖:NumPy
使用类库,依赖:NumPy,scikit-learn
可视化,依赖:matplotlib
后记
手动实践到这一步就暂时告一段落了,但这里实现的是有确定解的情况,但在很多情况下,没有确定的解,那么该如何解决呢?
后面继续关注吧。
标签:动手做,mat,求解,Python,list,线性,可视化,np From: https://blog.csdn.net/jiangshuiy/article/details/143799745