3.2 线性回归的从零开始实现
%matplotlib inline
import torch
from IPython import display
from matplotlib import pyplot as plt
import numpy as np
import random
3.2.1 生成数据集
num_inputs = 2
num_examples = 1000
true_w = [2,-3.4]
true_b = 4.2
features = torch.from_numpy(np.random.normal(0,1,(num_examples,num_inputs)))
labels = true_w[0] * features[:,0] + true_w[1] * features[:,1] + true_b
labels += torch.from_numpy(np.random.normal(0,0.01,size = labels.size()))
print(features[0],labels[0])
tensor([0.6324, 1.5551], dtype=torch.float64) tensor(0.2032, dtype=torch.float64)
def use_svg_display():
# 用矢量图显示
display.set_matplotlib_formats('svg')
def set_figsize(figsize = (3.5,2.5)):
use_svg_display()
# 设置图的尺寸
plt.rcParams['figure.figsize'] = figsize
set_figsize()
plt.scatter(features[:,1].numpy(),labels.numpy(),1)
<matplotlib.collections.PathCollection at 0x220da1a6ba8>
3.2.2 读取数据
读取小批量数据
def data_iter(batch_size, features, labels):
num_examples = len(features)
indices = list(range(num_examples))
random.shuffle(indices)
for i in range(0,num_examples,batch_size):
# print(i)
j = torch.LongTensor(indices[i:min(i +batch_size,num_examples)])
yield features.index_select(0,j),labels.index_select(0,j)
batch_size = 10
for X,y in data_iter(batch_size,features,labels):
print(X,y)
break
tensor([[-1.3137, -1.6132],
[ 0.1923, -0.4359],
[-0.7929, -0.4088],
[ 0.3640, -2.7373],
[-0.6725, 0.1442],
[ 0.5874, -0.3863],
[ 2.2049, 1.3518],
[-0.2108, -0.6305],
[-0.2961, -0.4947],
[ 0.7193, 2.7268]], dtype=torch.float64) tensor([ 7.0628, 6.0627, 3.9909, 14.2296, 2.3753, 6.6761, 4.0003, 5.9209,
5.3056, -3.6368], dtype=torch.float64)
3.2.3 初始化模型参数
# 初始化 权重 和 偏差
w = torch.tensor(np.random.normal(0, 0.01, (num_inputs,1)),dtype = torch.float64)
b = torch.zeros(1, dtype = torch.float64)
w.requires_grad_(requires_grad = True)
b.requires_grad_(requires_grad = True)
tensor([0.], dtype=torch.float64, requires_grad=True)
3.2.4 定义模型
def linreg(X, w, b):
return torch.mm(X, w) + b
3.2.5 定义损失函数
def squared_loss(y_hat, y):
return (y_hat - y.view(y_hat.size())) ** 2 /2
3.2.6 定义优化算法
def sgd(params, lr, batch_size):
for param in params:
param.data -= lr * param.grad / batch_size
3.2.7 训练模型
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, features,labels):
# print(X)
# print(y)
# print(w)
# print(net(X, w, b))
l = loss(net(X, w, b), y).sum() # l 是有关小批量X 和y 的 损失
l.backward() # 求梯度
sgd([w,b],lr, batch_size)
# 梯度清零
w.grad.data.zero_()
b.grad.data.zero_()
train_l = loss(net(features, w, b), labels)
print('epoch %d, loss %f' % (epoch + 1, train_l.mean().item()))
epoch 1, loss 0.045305
epoch 2, loss 0.000189
epoch 3, loss 0.000052
print(true_w, '
',w)
print(true_b, '
',b)
[2, -3.4]
tensor([[ 1.9989],
[-3.4000]], dtype=torch.float64, requires_grad=True)
4.2
tensor([4.1998], dtype=torch.float64, requires_grad=True)
【总结】
初步尝试了数据训练 反馈调节 训练后的参数 后续加强