1435-郭同学

, , ,

# 使用pytorch构建神经网络系列

## 第五章 经典卷积神经网络

### 1.Lenet5

class Lenet5(nn.Module):
"""
for cifar10 dataset.
"""
def __init__(self):
super(Lenet5, self).__init__()

self.conv_unit= nn.Sequential(
# x:[b, 3, 32, 32]

)
self.fc_unit = nn.Sequential(
nn.Linear(16*5*5, 120),
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84, 10)
)

self.criterion = nn.CrossEntropyLoss()


forward

    def forward(self, x):
"""

:param x: [b, 3, 32, 32]
:return:
"""
batchsz = x.size(0)
# [b, 3, 32, 32] ==> [b, 16, 5, 5]
x = self.conv_unit(x)
# [b, 16, 5, 5] ==> [b, 16*5*5]
x = x.view(batchsz, 16*5*5)
#  [b, 16*5*5] ==> [b, 10]
logits = self.fc_unit(x)

return logits


import torch
from torchvision import datasets
from torchvision import transforms
from torch import nn, optim
from Lenet5 import Lenet5

def main():
batchsz = 256
cifar_train = datasets.CIFAR10('cifar', True, transform=transforms.Compose([
transforms.Resize(32, 32),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])

cifar_test = datasets.CIFAR10('cifar', False, transform=transforms.Compose([
transforms.Resize(32, 32),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])



 	device = torch.device('cuda')
model = Lenet5()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr = 1e-3) #传入网络参数
print(model)


    for epoch in range(150):

model.train()

for batchidx, (x, label) in enumerate(cifar_train):
# x, label = x.to(divice), label.to(divice)
# [b, 10]
# loss:

logits = model(x)

loss = criterion(logits, label)
# loss(tensor scalar)
# backpropagation

loss.backward() #BP
optimizer.step() #更新
print('epoch:', epoch, 'loss:', loss.item()) #loss标量转化为array打印

model.eval()
# test ，包在不进行梯度更新内完成
total_correct = 0
total_num = 0
for  x, label in cifar_train:
logits = model(x) # [b, 10]
pred = logits.argmax(dim = 1)
total_correct += torch.eq(pred, label).float().sum().item()
# eq返回一个 byte tensor 转换成float后累加，
# 是一个scalar tensor，使用.item（）转换成numpy
total_num += x.size(0)

acc = total_correct / total_num
print("accuracy:", acc)


epoch: 58 loss: 0.007965920493006706
accuracy: 1.0
epoch: 59 loss: 0.009623807854950428
accuracy: 1.0
epoch: 60 loss: 0.00962372962385416
accuracy: 1.0
epoch: 61 loss: 0.009976484812796116
accuracy: 1.0
epoch: 62 loss: 0.004600073676556349
accuracy: 1.0


### 2.ResNet

ResBlk实现每一个短接的block，其中包含两层卷积层

import torch
from torch import nn
from torch.nn import functional as F

class ResBlk(nn.Module):
"""
resnet block
"""
def __init__(self, chan_in, chan_out, stride=1):
"""
:param chan_in:
:param chan_out:
"""
super(ResBlk, self).__init__()

self.conv1 = nn.Conv2d(chan_in, chan_out, kernel_size=3, stride=stride, padding=1)
self.bn1 = nn.BatchNorm2d(chan_out)
self.conv2 = nn.Conv2d(chan_out, chan_out, kernel_size=3, stride=1, padding=1)
self.bn2 = nn.BatchNorm2d(chan_out)

self.extra = nn.Sequential()
if chan_in != chan_out:
self.extra = nn.Sequential(
nn.Conv2d(chan_in, chan_out, kernel_size=1, stride=stride),
nn.BatchNorm2d(chan_out)
)

def forward(self, x):
"""
:param x: [b, chan, h, w]
:return:
"""
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
# shortcut
# [b, chan_in, h, w] ==> [b, chan_out, h, w]

out = self.extra(x) + out

return out

class ResNet18(nn.Module):
def __init__(self):
super(ResNet18, self).__init__()

self.conv1 = nn.Sequential(
nn.BatchNorm2d(64)
)
# followed 4 blocks
# [b, 64, h, w] ==> [b, 128, h, w]
self.blk1 = ResBlk(64, 128, stride=2)
# [b, 128, h, w] ==> [b, 256, h, w]
self.blk2 = ResBlk(128, 256, stride=2)
# [b, 256, h, w] ==> [b, 512, h, w]
self.blk3 = ResBlk(256, 512, stride=2)
# [b, 512, h, w] ==> [b, 512, h, w]
self.blk4 = ResBlk(512, 512, stride=2)

self.outlayer = nn.Linear(512*1*1, 10)

def forward(self, x):
"""

:param x:
:return:
"""
x = F.relu(self.conv1(x))

# [b, 64, h, w] ==> [b, 512, h, w]
x = self.blk1(x)
x = self.blk2(x)
x = self.blk3(x)
x = self.blk4(x)
print('after conv:', x.shape)
print('after pooling:', x.shape)
x = x.view(x.size(0), -1)

x = self.outlayer(x)

return x

#测试x输出的shape
def main():
blk = ResBlk(64, 128, stride=2)
tmp = torch.randn(2, 64, 32, 32)
out = blk(tmp)
print('block :', out.shape)

x = torch.randn(2, 3, 32, 32)
model = ResNet18()
out = model(x)
print('resnet:', out.shape)

if __name__ == '__main__':
main()


block : torch.Size([2, 128, 16, 16])
after conv: torch.Size([2, 512, 2, 2])
after pooling: torch.Size([2, 512, 1, 1])
resnet: torch.Size([2, 10])


Vieu3.3主题

Q Q 登 录