NIN网络

代码(Pytorch):

 

'''

串联多个卷积层和‘全连接层’构成的小网络来构建一个深层网络
'''

import time
import torch
from torch import nn, optim
import torchvision

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# nin块
def nin_block(in_channels, out_channels, kernel_size, stride, padding):
blk = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding),
nn.ReLU(),
nn.Conv2d(out_channels, out_channels, kernel_size=1),
nn.ReLU(),
nn.Conv2d(out_channels, out_channels, kernel_size=1),
nn.ReLU()
)
return blk
# 池化层
def avg_pool2d(X, pool_size):
# X = X.to(device)
X = X.float()
p_h, p_w = pool_size
Y = torch.zeros(X.shape[0], X.shape[1], X.shape[2] - p_h + 1, X.shape[3] - p_w + 1)
for i in range(Y.shape[2]):
for j in range(Y.shape[3]):
Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
return Y
# 全局平均池化层可以通过将池化窗口设置成输入的宽高实现
class GlobalAngPool2d(nn.Module):
def __init__(self):
super(GlobalAngPool2d, self).__init__()
def forward(self, x):
return avg_pool2d(x, pool_size=x.size()[2:])
# 展平
class FlattenLayer(nn.Module):
def __init__(self):
super(FlattenLayer, self).__init__()
def forward(self, x): # x shape: (batch, *, *, ...)
return x.view(x.shape[0], -1)
net = nn.Sequential(
nin_block(1, 96, kernel_size=11, stride=4, padding=0),
nn.MaxPool2d(kernel_size=3, stride=2),
nin_block(96, 256, kernel_size=5, stride=1, padding=2),
nn.MaxPool2d(kernel_size=3, stride=2),
nin_block(256, 384, kernel_size=3, stride=1, padding=1),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Dropout(0.5),
# 类额标签为10
nin_block(384, 10, kernel_size=3, stride=1, padding=1),
GlobalAngPool2d(),
# 将4为转换为2维,形状维(批量大小, 10)
FlattenLayer()
)

# 查看每一层的输出形状
# X = torch.rand(1, 1, 224, 224)
# for name, blk in net.named_children():
# X = blk(X)
# print(name, 'output shape:', X.shape)

batch_size = 128
# 数据集
def load_data_fashion_mnist(batch_size, resize=None, root='./Datasets/FashionMNIST/FashionMNIST'):
trans = []
if resize:
trans.append(torchvision.transforms.Resize(size=resize))
trans.append(torchvision.transforms.ToTensor())

transform = torchvision.transforms.Compose(trans)

mnist_train = torchvision.datasets.FashionMNIST(root=root, train=True, download=True, transform=transform)
mnist_test = torchvision.datasets.FashionMNIST(root=root, train=False, download=True, transform=transform)
train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=0)
test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=0)
return train_iter, test_iter
train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=224)

lr, num_epochs = 0.002, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)

# 模型训练
# evaluiate_accuracy # 测试集准确率
def evaluate_accuracy(data_iter, net, device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')):
acc_sum = 0.0

n = 0

with torch.no_grad():
for x, y in data_iter:
if isinstance(net, torch.nn.Module):
net.eval() # 评估模式,关闭dropout
acc_sum += (net(x.to(device)).argmax(dim=1)==y.to(device)).float().cpu().sum().item()
net.train() # 训练模式
else: # 自定义模型
if ('is_training' in net.__code__.co_varnames):
acc_sum += (net(x, is_training=False).argmax(dim=1)==y).float().sum().item()
else:
acc_sum += (net(x).argmax(dim=1)==y).float().sum().item()
n += y.shape[0]
return acc_sum / n
# 模型训练
def train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):
net = net.to(device) # 将网络模型放到CUDA上
print('training on:', device)
loss = torch.nn.CrossEntropyLoss() # 分类损失函数
# loss = loss.to(device)
batch_count = 0
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0, time.time()
for x, y in train_iter:
x = x.to(device) # 输入数据放到CUDA上
y = y.to(device) # 输入数据放到CUDA上
y_hat = net(x)
y_hat = y_hat.to(device) # 计算得到的数据放到CUDA上
l = loss(y_hat, y)
optimizer.zero_grad()
l.backward()
optimizer.step()
train_l_sum += l.cpu().item()
train_acc_sum += (y_hat.argmax(dim=1)==y).sum().cpu().item()
n += y.shape[0]
batch_count += 1

test_acc = evaluate_accuracy(test_iter, net)
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f,time % .1f sec'% (epoch + 1, train_l_sum / batch_count,train_acc_sum / n, test_acc, time.time() - start))
# 开始训练
# 图片太大,数据集数量大,训练完一个批次的训练时间太长了
train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

 

posted on 2020-09-13 11:18  WhitePinkJ  阅读(332)  评论(0)    收藏  举报