线性回归

yao
yao
2022-12-14 / 0 评论 / 33 阅读 / 正在检测是否收录...

线性回归

一元函数线性回归,通过输入值x和输出值y进行模型训练,得到一个预测函数为$ y=w_{0}+w_{1}x $ 这里的$w_{0},w_{1}$是我们需要的模型训练的值.

损失函数:用来评价模型的好坏。线性回归用均方误差来进行评估真实值与预测值得差异,且通过损失函数来优化模型,使其损失函数取得极小值。方式如下(其中的除以二是为了后面求导后方便计算)

$loss =\frac{1}{2m} \sum_{i=1}^m(w_{0}+w_{1}x_{i} -y)^{2} 即 \frac{1}{2m} \sum_{i=1}^m (y_{i}`-y)^{2}$

自定义梯度下降

通过自定义梯度下降算法规则,求出$w_{0},w_{1}$绘制回归

  • 初始参数设置:随机初始值w1,w0,设置迭代次数,设置学习率(更新模型的速率,一般在0~1范围)
  • 求损失函数关于w0,w1的偏导数,从而去迭代更新模型的参数w0,w1
# 自定义梯度下降方法求线性回归
import numpy as np
import matplotlib.pyplot as plt 
train_x = np.array([0.5,0.6,0.8,1.1,1.4]) #创建训练的数据x和对应的y
train_Y = np.array([5.0,5.5,6.0,6.8,7.0])
w0,w1 = 1,1 #设置w0,w1初始值,后去更新这个权重和偏执
times = 1000 #更新次数
lrate = 0.01 #学习率,用来更新的模型的速率
for i in range(1,times+1):
    #求损失函数关于w0,w1的偏导数,从而去更新模型的参数
    d0 = (w0+w1*train_x-train_y).mean()
    d1 = ((w0+w1*train_x-train_y)*train_x).mean()
    #根据梯度下降的公式,更新w0,w1
    w0 = w0- lrate*d0
    w1 = w1-lrate*d1      
y = w0+w1*train_x #预测数据
plt.title("linear regeression")
plt.grid()
plt.plot(train_x,train_y,"or",label="samples")
plt.plot(train_x,y,"-",label="regression line")
plt.legend()
plt.show()
print("w0:",w0)
print('w1:',w1)
print("loss:",((w0+w1*train_x-train_y)**2).mean())

如图是运行后的结果:

lbmmf02z.png

我们可以修改以下代码,将每次更新的点进行保存起来,其观看损失函数和w0,w1的变化,代码如下:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np

train_x = np.array([0.5,0.6,0.8,1.1,1.4]) #创建训练的数据x和对应的y
train_y = np.array([5.0,5.5,6.0,6.8,7.0])

n = 500
w0_grid,w1_grid = np.meshgrid(
    np.linspace(0,9,n),
    np.linspace(0,3.5,n)
    ) #生成网格点坐标矩阵。
loss_grid = 0  #损失函数值
for x,y in zip(train_x,train_y):
    loss_grid  +=  (w0_grid+w1_grid*x-y)**2/2
plt.figure('loss function',figsize=(20,8))
ax3d = plt.subplot(projection='3d')
ax3d.set_xlabel("w0")
ax3d.set_ylabel("w0")
ax3d.set_zlabel("loss")
ax3d.plot_surface(w0_grid,w1_grid,loss_grid/len(train_x),cstride=20,rstride=20,cmap="jet",alpha=0.7)
# 生成训练数据
w0,w1,losses= [1],[1],[] 
times = 1000 #更新次数
lrate = 0.1 #学习率,用来更新的模型的速率
for i in range(1,times+1):
    losses.append(((w0[-1]+w1[-1]*train_x-train_y)**2).mean()/2)
    #求损失函数关于w0,w1的偏导数,从而去更新模型的参数
    d0 = (w0[-1]+w1[-1]*train_x-train_y).mean()
    d1 = ((w0[-1]+w1[-1]*train_x-train_y)*train_x).mean()
    #根据梯度下降的公式,更新w0,w1
    w0.append(w0[-1]- lrate*d0)
    w1.append(w1[-1]-lrate*d1)       
ax3d.plot3D(w0[:-1],w1[:-1],losses,'o-',color='r')
plt.tight_layout()
plt.show()

以下图示:是代码运行结果
lbmmfaom.png

我们可以从这个图中我们看到w0与w1的更新路径,都是沿着损失函数的的梯度下降,

在设置学习率的时候,过大时候会梯度爆炸和梯度消失,以下是取不同的学习率w0,w1,loss的变化:

lbmmfysa.png
lbmmg1gq.png
lbmmg52a.png

lbmmg82s.png

线性回归api

import numpy as np
import matploylib.pyplot as plt
import sklearn.linear_model as lm #线性回归模型包

# 读取数据
x, y = np.loadtxt(file_path,delimiter=",", unpack=True) # file_path: 是一个二维数据的txt文件
x = x.reshape(-1,1) # 变维:n行一列
model = lm.LinearRegression()    # 构建模型
model.fit(x,y) # 训练模型
pred_y = model.predict(x) #输入x,获得预测值y

评价线性模型

评价线性模型函数: 平均绝对值误差,平均平方误差,中位绝对误差,R2评分误差

平均绝对误差: $\frac{1}{m}\sum_{m}|(y`-y)|$

平均平方误差: $\sqrt{\frac{1}{m}\sum_{m}(y`-y)^{2}}$

中位绝对值误差:$median(|y`-y|)$

$决定系数:r^{2}得分,(0,1)区间的分值,分数越高,误差越小.R^{2}=1-\frac{\sum(y_{i}-y`_{i})^{2}}{\sum(y_{i}-y_{mean})^{2}}$

import sklearm.metrics as sm
# 平均绝对误差
sm.mean_absolute_error(y,pred_y)
# 平均平方误差
sm.mean_squared_error(y,pred_y)
# 中位数绝对值误差:
sm.median_absoulute_error(y,pred_y)
# 决定系数
sm.r2_score(y.pred_y)

模型的保存和加载

我们训练完后需要保存模型,在下一次使用直接加载模型,这样就不用在使用的时候再一次训练模型.且训练模型的时间是一个耗时的过程

api

import pickle
pickle.dump(model,file_path) #保存模型, model为训练的模型,file_path为保存文件,一般为pkl文件
model = pickle.load(file_path) # 加载模型

#保存模型
with open(file_path,"wb") as f:
    pickle.dump(model,f)
# 加载和使用模型
with open(file_path,"rb") as f:
    model = pickle.load(f)
pred_y = model.predict(x) # 使用模型预测

0

评论 (0)

取消