大家好,又见面了,我是你们的朋友全栈君。
本文是根据https://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/79767043这篇博客写出来的。其中的公式什么的可以去这个博客里面看。 本文主要讲述的是关于其中的线性回归算法中每一段的意思,以供自己以后参考学习。
代码语言:javascript复制import numpy as np #引入numpy科学计算库
import matplotlib.pyplot as plt #引入绘图库
from sklearn.model_selection import train_test_split#从sklearn里面引出训练与测试集划分
np.random.seed(123) #随机数生成种子
代码语言:javascript复制x=2*np.random.rand(500,1)#随机生成一个0-2之间的,大小为(500,1)的向量
y=5 3*x np.random.randn(500,1)#随机生成一个线性方程的,大小为(500,1)的向量
fig=plt.figure(figsize=(8,6))#确定画布大小
plt.scatter(x,y)#设置为散点图
plt.title("Dataset")#标题名
plt.xlabel("First feature")#x轴的标题
plt.ylabel("Second feature")#y轴的标题
plt.show()#绘制出来
通过观察此图,可以发现x轴的大小限制在0-2之间,而y则是根据是那上面的线性方程y=5 3*x n,这个n是一个呈正态分布的随机量。 上面的一切都是在随机生成数据,为的就是能够自己生成一个小型的数据集。
代码语言:javascript复制x_train,x_test,y_train,y_test=train_test_split(x,y)#将上面得到的数据集进行划分,按照3:1的比例分给训练集
#和测试集
print(f'Shape x_train:{x_train.shape}')#输出x轴训练集的大小
print(f'Shape y_train:{y_train.shape}')#同上
print(f'Shape x_test:{x_test.shape}')#同上
print(f'Shape y_test:{y_test.shape}')#同上
Shape x_train:(375, 1) Shape y_train:(375, 1) Shape x_test:(125, 1) Shape y_test:(125, 1)
上面的数据就是上一代码块所能得到输出。从此我们可以看出,数据集已经成功按照3:1的比例分成了训练集和测试集。 现在开始写线性回归的类:
代码语言:javascript复制class LinearRegression:#类名
def _init_(self):#初始化
pass#什么也不做,只是单纯的防止语句错误
def train_gradient_descent(self,x,y,learning_rate=0.01,n_iters=100):#梯度下降法训练,x,y不用解释,
#学习率就是学习的速度,n_iters是迭代的次数
n_samples,n_features=x.shape#将x的大小x=500,y=1分别分给样品和特征
self.weights=np.zeros(shape=(n_features,1))#以下都是第零步,给权值赋为0,这里的n_features==1
self.bias=0#偏差赋值为0
costs=[]#申请一个损失数组
for i in range(n_iters):#迭代n_iters次
y_predict=np.dot(x,self.weights) self.bias#第一步:y_predict=X*w b
cost=(1/n_samples)*np.sum((y_predict-y)**2)#第二步,得训练集的损失
costs.append(cost)#将损失加到损失数组里面
if i0==0:#每过一百次输出一下损失
print(f"Cost at iteration{i}:{cost}")
dJ_dw=(2/n_samples)*np.dot(x.T,(y_predict-y))#第三步 第一个公式,得对应偏导数的梯度
dJ_db=(2/n_samples)*np.sum((y_predict-y))#第三步 第二个公式
self.weights=self.weights-learning_rate*dJ_dw#第四步 第一个公式,刷新权值
self.bias=self.bias-learning_rate*dJ_db#第四步 第二个公式,刷新偏差
return self.weights,self.bias,costs#返回所得参数
def train_normal_equation(self,x,y):#正规的方程训练
self.weights=np.dot(np.dot(np.linalg.inv(np.dot(x.T,x)),x.T),y)#正规方程公式
self.bias=0
return self.weights,self.bias
def predict(self,x):
return np.dot(x,self.weights) self.bias
以下步骤,皆属于复制的置顶博客中的 步骤 a) 梯度下降法
第 0 步:
用0 (或小的随机值)来初始化权重向量和偏置量,或者直接使用正态方程计算模型参数
第 1 步(只有在使用梯度下降法训练时需要):
计算输入的特征与权重值的线性组合,这可以通过矢量化和矢量传播来对所有训练样本进行处理:
其中 X 是所有训练样本的维度矩阵,其形式为
;· 表示点积。
第 2 步(只有在使用梯度下降法训练时需要):
用均方误差计算训练集上的损失:
第 3 步(只有在使用梯度下降法训练时需要):
对每个参数,计算其对损失函数的偏导数:
所有偏导数的梯度计算如下:
第 4 步(只有在使用梯度下降法训练时需要):
更新权重向量和偏置量:
其中,表示学习率。
b) 正态方程(封闭形式解):
其中 X 是一个矩阵,其形式为
,包含所有训练样本的维度信息。
代码语言:javascript复制regressor=LinearRegression() #梯度下降法的一个实例化对象
w_trained,b_trained,costs=regressor.train_gradient_descent(x_train,y_train,learning_rate=0.005,n_iters=600)
#对该对象进行训练,并获取训练之后的权值与偏差
fig=plt.figure(figsize=(8,6))#设置画布大小
plt.plot(np.arange(600),costs)#设置绘画内容,x轴为迭代次数,y轴为训练集的损失
plt.title("Development of cost during training")#标题
plt.xlabel("Numbers of iterations: ")#x轴标题
plt.ylabel("Cost")#y轴标题
plt.show()#显示
代码语言:javascript复制n_samples,_=X_train.shape#这里想要的只有训练集的行数,_代表的也是一个变量名,只是为1,为什么用
#相当于被抛弃的那种。之所以写在这里,也是为了防止程序出错
n_samples_test,_=X_test.shape#这里想要的是测试集的行数
y_p_train=regressor.predict(X_train)#计算训练集中的特征与权值的线性组合,借鉴梯度下降法中的第一步
y_p_test=regressor.predict(X_test)#计算测试集中的特征与权值的线性组合
error_train=(1/n_samples)*np.sum((y_p_train-y_train)**2)#这里计算的是训练集的的误差
error_test=(1/n_samples_test)*np.sum((y_p_test-y_test)**2)#这里计算的是测试集的的误差
print(f"error on training set:{np.round(error_train,4)}")#输出训练集的误差,保留四位小数
print(f"error on testing set:{np.round(error_test)}")#输出测试集的误差
Error on training set: 1.0955
Error on test set: 1.0 以上为上代码块的输出。
代码语言:javascript复制X_b_train=np.c_[np.ones(n_samples),X_train]#按行进行组合两个矩阵,组合之后的矩阵大小为(375,2)
X_b_test=np.c_[np.ones(n_samples_test),X_test]#按行进行组合两个矩阵,,组合之后的矩阵大小为(125,2)
reg_normal=LinearRegression()#建立一个使用正态方程的实例化对象
w_trained=reg_normal.train_normal_equation(X_b_train,y_train)#使用了正态方程训练之后的权值
以上代码块是正态方程的训练。
代码语言:javascript复制y_p_train=reg_normal.predict(X_b_train)#计算正态训练集中的特征与权值的线性组合,借鉴梯度下降法中的第一步
y_p_test=reg_normal.predict(X_b_test)#计算正态测试集中的特征与权值的线性组合
error_train=(1/n_samples)*np.sum((y_p_train-y_train)**2)#下面这四个我就不赘述了!解释就在前面的代码块中
error_test=(1/n_samples_test)*np.sum((y_p_test-y_test)**2)
print(f"Error on training set:{np.round(error_train,4)}")
print(f"Error on test set:{np.round(error_test,4)}")
Error on training set: 1.0228
Error on test set: 1.0432 以上是上面代码块的输出。
代码语言:javascript复制fig=plt.figure(figsize=(8,6))#设置画布大小
plt.scatter(X_train,y_train)#绘制训练集的散点图
plt.scatter(X_test,y_p_test)#绘制测试集的散点图,注意这里的y_p_test是正态之后的测试集的y
plt.xlabel("First feature")#x轴的标题
plt.ylabel("Second feature")#y轴的标题
plt.show()#显示
完结撒花!
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/171755.html原文链接:https://javaforall.cn