能自己实现的都重新写了函数。(pycharm)
文章目录
多层感知机从零开始实现
import torch
from torch import nn
import torchvision # 计算机视觉相关库
from d2l import torch as d2l
from torch.utils import data
from torchvision import transforms
import matplotlib.pyplot as plt
def get_dataloader_workers(): #@save
"""使用4个进程来读取数据"""
return 4 # 并行
def load_data_fashion_mnist(batch_size, resize=None): #@save
"""下载Fashion-MNIST数据集,然后将其加载到内存中"""
trans = [transforms.ToTensor()]
if resize:
trans.insert(0, transforms.Resize(resize))
#transforms.Resize:调整PILImage对象的尺寸。transforms.Resize([h, w])或transforms.Resize(x)等比例缩放
trans = transforms.Compose(trans) # 串联多个图片变换的操作
mnist_train = torchvision.datasets.FashionMNIST(
root="D:/code/动手学深度学习/pytorch/data", train=True, transform=trans, download=False)
mnist_test = torchvision.datasets.FashionMNIST(
root="D:/code/动手学深度学习/pytorch/data", train=False, transform=trans, download=False)
return (data.DataLoader(mnist_train, batch_size, shuffle=True,
num_workers=get_dataloader_workers()),
data.DataLoader(mnist_test, batch_size, shuffle=False,
num_workers=get_dataloader_workers()))
def get_fashion_mnist_labels(labels):
"""Return text labels for the Fashion-MNIST dataset."""
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
# 激活函数
def relu(X):
a = torch.zeros_like(X) # 生成形状相同的0矩阵
return torch.max(X, a)
#模型
def net(X):
X = X.reshape((-1, num_inputs)) # 每张图片都拉成向量
H = relu(X@W1 + b1) # 这里“@”代表矩阵乘法
return (H@W2 + b2)
loss = nn.CrossEntropyLoss(reduction='none') # 损失函数
class Accumulater: #@save
def __init__(self, n):
self.data = [0.0] *n
def add(self, *args):
self.data = [a + float(b) for a,b in zip(self.data, args)]
def reset(self):
self.data = [0.0] * len(self.data)
def __getitem__(self, idx):
return self.data[idx]
# 精度
def accuracy(y_hat, y):
"""Compute the number of correct predictions.
Defined in :numref:`sec_softmax_scratch`"""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = d2l.argmax(y_hat, axis=1)
cmp = d2l.astype(y_hat, y.dtype) == y
return float(d2l.reduce_sum(d2l.astype(cmp, y.dtype)))
# 训练一轮
def train_epoch_ch3(net, train_iter, loss, updater):
if isinstance(net, torch.nn.Module):
net.train()
metric = Accumulater(3)
for X, y in train_iter:
y_hat = net(X)
l = loss(y_hat, y)
if isinstance(updater, torch.optim.Optimizer): # 使用torch内置优化器
updater.zero_grad()
l.mean().backward()
updater.step()
else:
l.sum().backward()
updater(X.shape[0])
metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
return metric[0]/metric[2], metric[1]/metric[2]
# 准确率
def evaluate_accuracy(net, data_iter): #@save
if isinstance(net, torch.nn.Module):
net.eval()
metric = Accumulater(2) # 累加
with torch.no_grad():
for X, y in data_iter:
metric.add(accuracy(net(X), y), y.numel())
return metric[0]/metric[1]
# 训练全部
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):
animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9], # 可视化
legend=['train loss', 'train acc', 'test acc'])
for epoch in range(num_epochs):
train_metrics = train_epoch_ch3(net, train_iter, loss, updater)
test_acc = evaluate_accuracy(net, test_iter)
animator.add(epoch + 1, train_metrics + (test_acc,))
train_loss, train_acc = train_metrics
assert train_loss < 0.5, train_loss
assert train_acc <=1 and train_acc > 0.7, train_acc
assert test_acc <= 1 and test_acc > 0.7, test_acc
# 预测
def predict_ch3(net, test_iter, n = 6):
for X, y in test_iter:
break
trues = get_fashion_mnist_labels(y)
preds = get_fashion_mnist_labels(net(X).argmax(axis= 1))
titles = [true + '\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(X[0:n].reshape((n,28,28)), 1, n, titles = titles[0:n])
if __name__ == '__main__':
batch_size = 256
train_iter, test_iter = load_data_fashion_mnist(batch_size)
# 初始化模型参数
num_inputs, num_outputs, num_hiddens = 784, 10, 256 # 28*28=784,10个输出类别,但隐藏层有256个隐藏单元
# nn.Parameter()声明是一个torch parameter
W1 = nn.Parameter(torch.randn(
num_inputs, num_hiddens, requires_grad=True) * 0.01)
# 试一下全部设置成0,(会全部参数更新都一致?)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(
num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
params = [W1, b1, W2, b2]
# 训练
num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
plt.show()
# 测试集上应用
predict_ch3(net, test_iter)
plt.show()
多层感知机简洁实现
用到了一些d2l的内容
import torch
from torch import nn
from d2l import torch as d2l
import matplotlib.pyplot as plt
net = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10))
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std = 0.1)
net.apply(init_weights)
batch_size, lr, num_epochs = 256, 0.1, 10
loss = nn.CrossEntropyLoss(reduction='none')
trainer = torch.optim.SGD(net.parameters(), lr=lr)
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
plt.show()
d2l.predict_ch3(net, test_iter)
plt.show()