import torch
import torchvision
import torch.nn.functional as F
from torch.utils import data as torchData
import torchvision.transforms as transforms
from Accumulat import Accumulator
from util import *
def init_weights(m):
if type(m) == torch.nn.Linear:
torch.nn.init.normal_(m.weight, std=0.01)
# 定义网络模型
class LinearNet(torch.nn.Module):
def __init__(self,num_inputs, hidden_num, class_num):
super().__init__()
self.linear1 = torch.nn.Linear(num_inputs, hidden_num)
self.linear2 = torch.nn.Linear(hidden_num, class_num)
self.linear1.apply(init_weights)
self.linear2.apply(init_weights)
self.flatten = torch.nn.Flatten()
self.relu = torch.nn.ReLU()
def forward(self, x):
x = self.flatten(x)
y = self.linear1(x)
y = self.relu(y)
y = self.linear2(y)
return y
def load_FashionMNIST(batch_size, resize=None):
trans = transforms.ToTensor()
# if resize:
# trans.insert(0,transforms.Resize(resize))
# trans = transforms.Compose(trans)
mnist_train = torchvision.datasets.FashionMNIST(
root="../data/", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(
root="../data/", train=False, transform=trans, download=True)
train_loader = torchData.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=4)
test_loader = torchData.DataLoader(mnist_test, 1500, shuffle=False, num_workers=4)
return train_loader, test_loader
def train_epoch_ch3(net, train_iter,loss_fn, optimizer):
"""训练模型一个迭代周期(定义见第3章)。"""
# 训练损失总和、训练准确度总和、样本数
metric = Accumulator(3)
for x,y in train_iter:
# 计算梯度并更新参数
optimizer.zero_grad()
y_hat = net(x)
softmax_y = F.softmax(y_hat, dim=1)
loss = loss_fn(y_hat, y)
loss.backward()
optimizer.step()
train_acc = accuracy(y_hat, y)
metric.add(float(loss), train_acc, y.numel())
# 返回训练损失和训练准确率
return metric[0] / metric[2], metric[1] / metric[2]
def train_ch3(net, train_iter, test_iter, num_epochs, loss_fn, optimizer):
"""训练模型(定义见第3章)。"""
for epoch in range(num_epochs):
train_metrics = train_epoch_ch3(net, train_iter,loss_fn, optimizer)
test_acc = evaluate_accuracy(net, test_iter)
print(f'epoch:{epoch}, train loss is:{train_metrics[0]:.5f}, train acc is:{train_metrics[1]:.3f}, test acc is:{test_acc:f}')
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
if __name__ == '__main__':
batch_size = 10
train_iter, test_iter = load_FashionMNIST(batch_size=batch_size)
# 定义损失函数 和 优化器
num_inputs = 784
hidden_num = 256
class_num = 10
net = LinearNet(num_inputs, hidden_num, class_num)
loss_fn = torch.nn.CrossEntropyLoss() # pytorch的交叉熵损失计算里已经包含了 softmax,所以在forward里面不应该加上 softmax
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
num_epochs = 30
lr = 0.1
train_ch3(net, train_iter, test_iter, num_epochs, loss_fn, optimizer)
print('ok')