欢迎来到@一夜看尽长安花 博客,您的点赞和收藏是我持续发文的动力
对于文章中出现的任何错误请大家批评指出,一定及时修改。有任何想要讨论的问题可联系我:3329759426@qq.com 。发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。
专栏:
文章概述:对 深入“纯手工”解析解的方式求解多元线性回归_扩展随机种子概念_增加维度代码的变换的介绍
关键词:解析解的方式求解多元线性回归 扩展随机种子概念 增加维度
本文目录:
回顾一下线性回归的LOSS函数
解析解:
代码实战求解线性回归算法模型
代码实战解析解求解模型
规范的表头,还有作者名字
中间导入这个脚本需要的模块,numpy是去做数值计算的,matplotlib是关于绘图的,as是给模块起个名字,方便后面调用模块的一些函数方法
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 文件名: linear_regression_0.py
import numpy as np
import matplotlib.pyplot as plt
__author__ = 'yasaka'
我们通过numpy随机创建数据用于训练,这里相当于是随机X维度X1,rand是随机均匀分布,是在创建用于训练的X矩阵,100行一列的数组
X=2*np.random.rand(100,1)
rand的源码说明,这里三个双引号是docstring,作为方法的注释说明,可以通过help()方法名去查看到这些注释,如果只是#来注释方法无法看到
这里[)左边闭区间,右边开区间,也就是每个数字随机的时候有可能是0,绝不可能是1,然后它随机的时候
很多时候我们可以直接看example例子来学习函数方法如何去用,我们看到array这是numpy封装的数组,原生的python是没有array数组这个类型的,它只有tuple元组,list列表,dict字典等。
接下来人为的设置真实的Y一列,这里的4其实就是我们把W1=4,然后5就是W0=5,
y = 5 + 4 * X + np.random.randn(100, 1)
np.random.randn(100, 1)是设置error,因为randn是标准正太分布,符合我们前面讲过的误差服从均值为0的正太分布,这就意味着这样构建的X和Y的关系去使用我们前面讲过的多元线性回归去拟合求解会很合适。
error
同时,我们有100个真实值y,我们有5+4X就是100个y_hat,那么我们的误差就是真实值减去预测值也会有100个误差值。所以这也就是我们去用randn去创建100行1列的数组的原因。
解析解的方式求解多元线性回归_求解模型_使用模型_绘制图形
前面我们讲过在多元线性回归中,W的个数其实是和X特征的数量一一对应的,比如我们有X1、X2两个特征,我们通过多元线性回归就可以求解得到W1、W2两个参数,比如我们有X0、X1两个特征,我们通过多元线性回归就可以求解得到W0、W1两个参数。
那么此时我们只有X1一列向量,我们还需要一列X0才可以去求得W0,因为我们上面的式子中有个W0=5嘛,所以接下来整合X0和X1
X_b = np.c_[np.ones((100, 1)), X]
print(X_b)
这里的c_就是拼接,可以把它理解为concatenate拼接,而且我们把X0一列都设置为1,这样多元线性回归公式就可以把1去乘以W0,这样就符合公式的定义,还有注意拼接的顺序就是求得对应W的顺序。
X0 | X1 | |
m行 | 1 | 0.14 |
1 | 0.96 | |
... | ... | |
1 | 0.37 |
接下来数据准备好了,我们就可以应用我们之前推导出来的解析解公式
X_b = np.c_[np.ones((100, 1)), X]
print(X_b)
这里的.T就是transpose转置的作用,dot就是向量点乘, np.linalg.inv是矩阵求逆
np.linalg
我们计算结果很有意思,就是你会发现最后并不能准确的计算出来5和4,而是计算出来一个接近期望的值
我这里结果代码演示就换个数值然后用后面的知识给大家先看看结果是啥样
import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
X1 = 2*np.random.rand(100, 1)
X = np.c_[X1]
y = 4 + 3*X1 + np.random.randn(100, 1)
reg = LinearRegression(fit_intercept=True)
reg.fit(X, y)
print(reg.intercept_, reg.coef_)
X_new = np.array([[0,],
[2],
[4]])
y_predict = reg.predict(X_new)
# 绘图进行展示真实的数据点和我们预测用的模型
#plt.plot(X_new[:, 0], y_predict, 'r-')
plt.plot(X_new, y_predict, 'r-')
plt.plot(X1, y, 'b.')
plt.axis([0, 2, 0, 25])
plt.show()
如果是我们给y不设定误差项,那么计算出来的结果是什么?还有形状是什么形状?
回到原来的讲解过程中
下面我们去把model模型使用起来,只有model模型预测的准,那么才有价值
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
print(theta_best)
这里我们同样构建一个两行一列的新的X,然后给它添加上一列恒为1的X0
X_new = np.array([[0],
[2]])
X_new_b = np.c_[(np.ones((2, 1))), X_new]
print(X_new_b)
y_predict = X_new_b.dot(theta_best)
print(y_predict)
计算的期望应该在10、4附近对吧,接下来我们图示出来
plt.plot(X_new, y_predict, 'r-')
plt.plot(X, y, 'b.')
plt.axis([0, 2, 0, 15])
plt.show()
红色的是代码模型那条直线,蓝色的点100个我们随机出来的真实数据,通过图示可以很清楚的看到我们用多元线性回归算法拟合的效果
解析解的方式求解多元线性回归_扩展随机种子概念_增加维度代码的变换
随机数种子
np.random.seed(42)
扩展
如果我们影响y的因为有两个,而不是前面例子只有一个的话呢?
y = 5 + 4 * X1 + 3*X2 + np.random.randn(100, 1)
那么我们是不是就还得有一个X2一列数据
X1 = 2 * np.random.rand(100, 1)
X2 = 3 * np.random.rand(100, 1)
X_b = np.c_[np.ones((100, 1)), X1, X2]
print(X_b)
纯手工绘制
绘制三维的回归模型
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 固定随机种子
np.random.seed(42)
# 生成数据
X1 = 2 * np.random.rand(100, 1)
X2 = 3 * np.random.rand(100, 1)
y = 5 + 4 * X1 + 3 * X2 + np.random.randn(100, 1)
# 创建X_b矩阵,并求解θ
X_b = np.c_[np.ones((100, 1)), X1, X2]
θ = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
# 为三维绘图准备数据
X1_grid, X2_grid = np.meshgrid(np.linspace(X1.min(), X1.max(), 20),
np.linspace(X2.min(), X2.max(), 20))
X_grid = np.c_[X1_grid.ravel(), X2_grid.ravel()]
X_grid_b = np.c_[np.ones((X_grid.shape[0], 1)), X_grid]
y_pred_grid = X_grid_b.dot(θ).reshape(X1_grid.shape)
# 绘制三维图形
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# 绘制散点图
ax.scatter(X1, X2, y, color='blue', label='Data Points')
# 绘制回归面
ax.plot_surface(X1_grid, X2_grid, y_pred_grid, color='red', alpha=0.5)
# 设置轴标签
ax.set_xlabel('X1')
ax.set_ylabel('X2')
ax.set_zlabel('y')
# 显示图形
plt.show()
1. 生成网格点
X1_grid, X2_grid = np.meshgrid(np.linspace(X1.min(), X1.max(), 20),
np.linspace(X2.min(), X2.max(), 20))
np.linspace(X1.min(), X1.max(), 20)
创建了一个从X1
的最小值到最大值的线性间隔为 20 的数组(20
是网格的分辨率)。np.meshgrid
函数利用这两个数组生成了两个二维网格数组X1_grid
和X2_grid
。这两个网格数组分别代表了 X1 和 X2 的所有可能的组合,形成一个网格。
2. 将网格点展平
X_grid = np.c_[X1_grid.ravel(), X2_grid.ravel()]
X1_grid.ravel()
和X2_grid.ravel()
将二维网格数组展平成一维数组。np.c_
将这两个一维数组按列合并,形成一个二维数组X_grid
,其中每一行都是一个 (X1, X2) 点的组合。
3. 添加偏置项并计算预测值
X_grid_b = np.c_[np.ones((X_grid.shape[0], 1)), X_grid]
np.ones((X_grid.shape[0], 1))
创建了一个全为 1 的列向量,用于表示偏置项 (截距项)。np.c_
将偏置项列和X_grid
结合,形成新的数组X_grid_b
,这表示在每个网格点上加上一个偏置项。
y_pred_grid = X_grid_b.dot(θ).reshape(X1_grid.shape)
X_grid_b.dot(θ)
计算每个网格点的预测值y_pred_grid
,其中θ
是模型的参数。reshape(X1_grid.shape)
将预测值数组y_pred_grid
重新塑形为与网格数组X1_grid
和X2_grid
相同的形状,以便能够在三维图中绘制表面。
4. 创建图形对象和三维坐标轴
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.figure()
创建一个新的图形对象fig
,这将是你要绘制的图的容器。fig.add_subplot(111, projection='3d')
在图形中添加一个三维坐标轴(ax
)。111
是一个子图的代码,表示在一行一列的第一个位置,projection='3d'
指定这是一个三维坐标轴。
5. 绘制散点图
ax.scatter(X1, X2, y, color='blue', label='Data Points')
ax.scatter(X1, X2, y, color='blue', label='Data Points')
用于绘制数据点的散点图。
-
X1
,X2
和y
分别是数据点的 x 轴、y 轴和 z 轴坐标。color='blue'
指定数据点的颜色为蓝色。label='Data Points'
为数据点指定标签,通常在图例中显示。
6. 绘制回归面
ax.plot_surface(X1_grid, X2_grid, y_pred_grid, color='red', alpha=0.5)
ax.plot_surface(X1_grid, X2_grid, y_pred_grid, color='red', alpha=0.5)
用于绘制回归面。
-
X1_grid
,X2_grid
是回归面的 x 轴和 y 轴坐标网格。y_pred_grid
是每个 (X1, X2) 网格点的预测值,即回归面在这些点上的高度。color='red'
指定回归面的颜色为红色。alpha=0.5
设置回归面的透明度,使其半透明,以便更好地显示数据点。-
- 移动一下平面,就可以展现一下视角