一、手动实现线性回归
# 线性回归的手动实现
%matplotlib inline
import torch
import random
from d2l import torch as d2l
# 随机按照参数w和b外加一些噪音来创造训练数据集data和labels
def synthetic_data(w, b, num_examples):
X = torch.normal(0, 1, (num_examples, len(w)))
y = torch.matmul(X, w) + b
y += torch.normal(0, 0.1, y.shape)
return X, y.reshape((-1,1))
# 可以按照一定的批次大小来获得一个迭代器,迭代器每次可以取出batch_size大小的data和labels
def data_iter(batch_size, train_data, train_label):
num_examples = len(train_data)
indices = list(range(num_examples))
random.shuffle(indices)
for i in range(0, num_examples, batch_size):
batch_indices = torch.tensor(indices[i:min(i+batch_size, num_examples)])
yield train_data[batch_indices], train_label[batch_indices]
# 线性回归模型
def linreg(X, w, b):
return torch.matmul(X, w) + b
# 计算平方损失
def square_loss(y_hat, y_real):
return (y_hat - y_real.reshape(y_hat.shape)) ** 2 / 2
# 小批量梯度下降
def sgd(params, lr, batch_size):
# with块中禁止继续构造计算图来减少性能损失
# 因为仅仅更新梯度的操作不需要用来计算梯度
with torch.no_grad():
for param in params:
param -= lr * param.grad / batch_size # /batch_szie是因为计算loss的时候没有除以num
param.grad.zero_() # 清理梯度防止累计
w = torch.tensor([2, -3.4])
b = 4.2
train_x, train_y = synthetic_data(w, b, 100)
true_w = torch.normal(0, 0.1, size = (2, 1), requires_grad = True)
true_b = torch.zeros(1, requires_grad = True)
# 开始训练:
batch_size = 10
lr = 0.01
num_epochs = 10 # 最大迭代次数
net = linreg
loss = square_loss
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, train_x, train_y):
l = loss(net(X, true_w, true_b), y)
l.sum().backward()
sgd([true_w, true_b], lr, batch_size)
with torch.no_grad():
train_l = loss(net(train_x, true_w, true_b) , train_y)
print('epoch:{}'.format(epoch), 'loss:{:.3f}'.format(train_l.mean()))
二、利用pytorch框架实现
# 线性回归的简洁实现
import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn #neural network
def load_array(data_arrays, batch_size, is_train = True):
# 可以通过dataset[i]来访问第i个样本的数据和标签
dataset = data.TensorDataset(*data_arrays)
# 返回的DataLoader实例可以按照batch_size的大小来取数据的迭代器,而且是已经shuffle
return data.DataLoader(dataset, batch_size, shuffle=is_train)
true_w = torch.tensor([2,-3.4])
true_b = 4.2
batch_size = 5
train_x, train_y = d2l.synthetic_data(true_w, true_b, 100) # 人造初始化训练数据集
data_iter = load_array((train_x,train_y), batch_size)
# for data,label in data_iter:
# print(data)
# print(label)
net = nn.Sequential(
nn.Linear(2, 1) # 表示只有一个神经元,接受的输入维度为2,输出的维度为1,并且使用线性函数作为激活函数
)
net[0].weight.data.normal_(0, 0.01) # 初始化网络中的参数w,使用符合均值0,方差0.01的正态分布的值来替换w
net[0].bias.data.fill_(0) # 初始化偏置项b,初始为0
loss = nn.MSELoss() # 损失函数定义为均方误差(L2范数)
trainer = torch.optim.SGD(net.parameters(), lr=0.01) # 使用随机梯度下降优化器,学习率为0.01
num_epoch = 10
for epoch in range(num_epoch):
for data, label in data_iter:
l = loss(net(data), label)
trainer.zero_grad() # 先利用trainer把参数w、b的梯度清0
l.backward()
trainer.step() # 通过梯度下降优化参数
train_l = loss(net(train_x), train_y)
print('epoch:{}'.format(epoch),'loss:{:.3f}'.format(train_l))
标签:python,true,torch,batch,线性,train,李沐,data,size
From: https://blog.csdn.net/yuzixuan233/article/details/143471590