import math
import time
import numpy as np
import torch
from d2l import torch as d2l
import matplotlib
import matplotlib.pyplot as plt
import random
from torch.utils import data
from torch import nn
def normal (x, mu, sigma) :
p = 1 / math.sqrt(2 * math.pi * sigma ** 2)
return p * np.exp(-0.5 / sigma ** 2 * (x - mu) ** 2)
x = np.arange(-7, 7, 0.01)
print(x)
params = [(0, 1), (0, 2), (3, 1)]
plt.plot(x, normal(x, 0, 1), x, normal(x, 0, 2), x, normal(x, 3, 1))
def synthetic_data (w, b, num_examples) :
'''生成 y = Xw + b + 噪声'''
'''torch.normal(means, std, out = None)
返回一个张量,means 和 std 均为张量,包含从给定参数的离散正态分布中抽取随机数
out 可选的输出张量
'''
X = torch.normal(0, 1, (num_examples, len(w)))
'''torch.matmul 没有强制规定维度和大小,可以利用广播机制进行不同维度的相乘操作'''
y = torch.matmul(X, w) + b
y += torch.normal(0, 0.01, y.shape)
return X, y.reshape((-1, 1))
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features : ', features[0], '\nlabel : ', labels[0])
plt.scatter(features[:, (1)].detach().numpy(), labels.detach().numpy(), 1)
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) :
batch_indices = torch.tensor(indices[i:min(i + batch_size, num_examples)])
yield features[batch_indices], labels[batch_indices]
batch_size = 10
for X, y in data_iter(batch_size, features, labels) :
print(X, '\n', y)
w = torch.normal(0, 0.01, size = (2, 1), requires_grad = True)
b = torch.zeros(1, requires_grad = True)
print(w, '\n', b)
def linreg (X, w, b) :
'''线性回归模型'''
return torch.matmul(X, w) + b
def squared_loss (y_hat, y) :
'''均方损失'''
return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
def sgd(params, lr, batch_size) :
'''小批量随机梯度下降'''
with torch.no_grad() :
for param in params :
param -= lr * param.grad / batch_size
param.grad.zero_()
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) :
l = loss(net(X, w, b), y)
l.sum().backward()
sgd([w, b], lr, batch_size)
with torch.no_grad() :
train_l = loss(net(features, w, b), labels)
print(f'epoch {epoch + 1}, loss {float(train_l.mean()) : f}')
print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
print(features, '\n', labels)
def load_array (data_arrays, batch_size, is_train = True) :
'''构造一个 PyTorch 数据迭代器'''
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch_size, shuffle = is_train)
batch_szie = 0
data_iter = load_array((features, labels), batch_size)
print(next(iter(data_iter)))
net = nn.Sequential(nn.Linear(2, 1))
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)
loss = nn.MSELoss()
trainer = torch.optim.SGD(net.parameters(), lr = 0.03)
num_epochs = 3
for epoch in range (num_epochs) :
for X, y in data_iter :
l = loss(net(X), y)
trainer.zero_grad()
l.backward()
trainer.step()
l = loss (net(features), labels)
print(f'epoch {epoch + 1}, loss {l : f}')