其实线性回归就是一个不加激活函数的全连接层
import torch
import torch.nn as nn
import numpy as np
x_values = [i for i in range(11)]
x_train = np.array(x_values, dtype=np.float32)
x_train = x_train.reshape(-1, 1)
y_values = [2*i+1 for i in x_values]
y_train = np.array(y_values, dtype=np.float32)
y_train = y_train.reshape(-1, 1)
class Linear_RegressionModel(nn.Module):
def __init__(self, input_dim, output_dim):
super(Linear_RegressionModel, self).__init__()
self.linear = nn.Linear(input_dim, output_dim)
def forward(self, x):
out = self.linear(x)
return out
input_dim = 1
output_dim = 1
model = Linear_RegressionModel(input_dim, output_dim)
print(model)
指定好参数和损失函数
epoches = 1000
learning_rate = 0.01
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
criterion = nn.MSELoss()
for epoch in range(epoches):
epoch += 1
# 转换为tensor
inputs = torch.from_numpy(x_train)
labels = torch.from_numpy(y_train)
# 梯度要清零每一次迭代
optimizer.zero_grad()
# 前向传播
outputs = model(inputs)
# 计算损失
loss = criterion(outputs, labels)
# 反向传播
loss.backward()
optimizer.step()
if epoch % 50 == 0:
print('epoch:{}, loss:{}'.format(epoch, loss))
print(model.linear.weight)
模型的保存和读取
torch.save(model.state_dict(), 'model.pkl')
torch.load_state_dict(torch.load('model.pkl'))
小小修改一下
torch.save(model.state_dict(), 'model.pkl')
model.linear.weight.data.fill_(0) # 更改一个参数
print(model.linear.weight) # 0
model.load_state_dict(torch.load('model.pkl')) # 变回来了
model.eval()
# 请记住,在运行推理之前,务必调用model.eval()
# 去设置 dropout 和 batch normalization 层为评估模式。
# 如果不这么做,可能导致 模型推断结果不一致。
print(model(torch.from_numpy(x_train)))
放进GPU(数据和模型)
device = torch.device('cuda:0' if torch.cuda.is_avaiable() else 'cpu')
model.to(device)
inputs = torch.from_numpy(x_train).to(device)
labels = torch.from_numpy(y_train).to(device)
# 最简单的model = model.cuda()也可以
查看每层的参数
model = CNN()
print(model) # 1
print(model.conv1.weight.shape) # 2
print(model.fc1.weight.shape) # 3
>>
CNN(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 12, kernel_size=(5, 5), stride=(1, 1))
)
>>
torch.Size([6, 1, 5, 5])
>>
torch.Size([120, 192])
用Mnist的小例子
import torch
import random
import matplotlib.pyplot as plt
from torch.utils import data
# 构造一个线性数据集
def synthetic_data(w, b, num_examples): #@save
"""生成 y = Xw + b + 噪声。"""
X = torch.normal(0, 1, (num_examples, len(w)))
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)
def load_array(data_arrays, batch_size, is_train=True): #@save
"""构造一个PyTorch数据迭代器。"""
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch_size, shuffle=is_train)
batch_size = 10
data_iter = load_array((features, labels), batch_size)
next(iter(data_iter))
# `nn` 是神经网络的缩写
from torch import nn
# 在 PyTorch 中,全连接层在 Linear 类中定义。
# 将两个参数传递到 nn.Linear 中。第一个指定输入特征形状,即 2,第二个指定输出特征形状,输出特征形状为单个标量,因此为 1。
net = nn.Sequential(nn.Linear(2, 1))
#正如我们在构造 nn.Linear 时指定输入和输出尺寸一样。
# 现在我们直接访问参数以设定初始值。
# 我们通过 net[0] 选择网络中的第一个图层,然后使用 weight.data 和 bias.data 方法访问参数。
# 然后使用替换方法 normal_ 和 fill_ 来重写参数值。
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)
# 计算均方误差使用的是MSELoss类,也称为平方 L2 范数。默认情况下,它返回所有样本损失的平均值。
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() # pytorch自动sum了
trainer.step()
l = loss(net(features), labels)
print(f'epoch {epoch + 1}, loss {l:f}')
w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)