自定义实现
import randomimport torchdef synthetic_data(w, b, num_examples):"""生成y=Xw+b+噪声 数据X: 代表原始的样本y: 代表特征值或者结果值"""X = torch.normal(0, 1, (num_examples, len(w)))y = torch.matmul(X, w) + by += torch.normal(0, 0.01, y.shape)return X, y.reshape((-1, 1))def data_iter(batch_size, features, labels):"""定义迭代器, 支持训练过程每个epochs"""num_exaples = len(features)indices = list(range(num_exaples))random.shuffle(indices)for i in range(0, num_exaples, batch_size):batch_indices = torch.tensor(indices[i: min(i + batch_size, num_exaples)])yield features[batch_indices], labels[batch_indices]def linreg(X, w, b):"""定义线性模型"""return torch.matmul(X, w) + bdef squared_loss(y_hat, y):"""定义损失函数, 均方差损失函数"""return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2def sgd(params, lr, batch_size):"""定义优化方法, 小批量随机梯度下降"""with torch.no_grad():for param in params:param -= lr * param.grad / batch_sizeparam.grad.zero_()if __name__ == '__main__':true_w = torch.tensor([2, -3.4])true_b = 4.2batch_size = 10features, labels = synthetic_data(true_w, true_b, 1000)w = torch.normal(0, 0.01, (2, 1), requires_grad=True)b = torch.zeros(1, requires_grad=True)lr = 0.0001num_epochs = 3000net = linregloss = squared_losssgd = sgdfor 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('epoch %d, loss %f' % (epoch + 1, train_l.mean().item()))print("w的估计误差: ", true_w - w.reshape(true_w.shape))print("b的估计误差: ", true_b - b)
简洁实现
import randomimport torch
from torch import nndef synthetic_data(w, b, num_examples):"""生成y=Xw+b+噪声 数据X: 代表原始的样本y: 代表特征值或者结果值"""X = torch.normal(0, 1, (num_examples, len(w)))y = torch.matmul(X, w) + by += torch.normal(0, 0.01, y.shape)return X, y.reshape((-1, 1))def load_array(data_arrays, batch_size, is_train=True):"""构造一个数据迭代器"""dataset = torch.utils.data.TensorDataset(*data_arrays)return torch.utils.data.DataLoader(dataset, batch_size, shuffle=is_train)if __name__ == '__main__':true_w = torch.tensor([2, -3.4])true_b = 4.2batch_size = 10features, labels = synthetic_data(true_w, true_b, 1000)w = torch.normal(0, 0.01, (2, 1), requires_grad=True)b = torch.zeros(1, requires_grad=True)data_iter = load_array((features, labels), batch_size)lr = 0.003net = nn.Sequential(nn.Linear(2, 1))net[0].weight.data.normal_(0, 0.01)net[0].bias.data.fill_(0)loss = nn.MSELoss()sgd = torch.optim.SGD(net.parameters(), lr=0.03)num_epochs = 3for epoch in range(num_epochs):for X, y in data_iter:l = loss(net(X), y)sgd.zero_grad()l.backward()sgd.step()l = loss(net(features), labels)print(f'epoch {epoch + 1}, loss {l:f}')w = net[0].weight.dataprint('w的估计误差:', true_w - w.reshape(true_w.shape))b = net[0].bias.dataprint('b的估计误差:', true_b - b)