线性回归作为最简单的一个线性网络模型揭示了神经网络的原理,作为理解神经网络有非常大的好处
到这里一直使用的是自己创建生成的数据进行训练模拟神经网络拟合的全过程,接下来会使用真是场景中的数据进行训练模拟
import torch
from torch import nn
from torch.utils.data import DataLoader
import numpy as np
# 获取训练数据集 训练集及真值
def get_datas(ws, b, n):
"""
:param ws: [2, 3] 给定包含所有权重w的列表
:param b: 5 偏置项
:param n: 128 数据组数量
:return: 生成的数据组,最后一列是标注。
"""
x = np.random.rand(n, len(ws)) # 随机初始化x 这里为训练集
y = (x * ws).sum(axis=1) + b # 计算y 这里为真值
datas = np.column_stack((x, y)) # 将x, y转置合并为一个矩阵
datas = datas.astype(np.float32) # 数据变为float32类型
return datas
class LinearReg(nn.Module):
# 初始化子类
def __init__(self, n_features):
# 继承父类属性
# super(Linear_Reg, self).__init__() # 第一种继承方法 python2 python3通用
super().__init__() # 第二种继承方法 python3适用
# nn.Module.__init__(self) # 第三种继承方法 python2 python3通用
# 初始化权值
self.linear = nn.Linear(n_features, 1, bias=True) # 第一种方法 初始化Linear类 变量分别是权重项w个数 偏置项b个数 以及是否打乱
# self.W = nn.Parameter(torch.rand(n_features,1)) # 第二种方法
# self.b = nn.Parameter(torch.rand(1))
# 前向传播
def forward(self, x):
y = self.linear(x)
# y=x.matmul(self.W)+self.b
y = torch.squeeze(y) # 对一维的矩阵进行压缩
return y
def train(epochs=200, batch_size=24, lr=0.05):
datas = get_datas(ws=[2, 3], b=5, n=128) # 得到数据 通过给定权值确定训练值与真值
net = LinearReg(len(datas[0])-1) # 初始化线性回归模型 同时随机初始化权重
criterion = torch.nn.MSELoss() # 平方差损失函数 计算损失值 损失函数可选
optimizer = torch.optim.SGD(net.parameters(), lr=lr) # 随机梯度下降 梯度下降法可选
for e in range(epochs):
# 直接在函数里对数据集进行batch_size的块划分 取出数据直接为tensor格式
for datas in DataLoader(datas, batch_size=batch_size, shuffle=True):
optimizer.zero_grad() # 梯度归0
x = datas[:, :-1] # 获取X
y = datas[:, -1] # 获取y
y_pr = net.forward(x) # 得到预测值y
loss = criterion(y_pr, y) # 将预测的y与真实的y带入损失函数计算损失值
loss.backward() # 反馈
optimizer.step() # 沿梯度下降方向更新所有参数
print('epoch{}, loss={:.4f}'.format(e, loss))
for p in net.parameters(): # 打印权值参数
print(p)
if __name__ == '__main__':
train()
生成训练数据及真值共128对,batch_size选取为24,学习率lr为0.05
真实权重项ws=[2, 3], b=5
贴出200个epoch训练后的结果,非常逼近真实值了
经过2000个epoch训练之后已经几乎没有误差了