这是一个简单的线性的卷积神经网络
然而有很多更为复杂的卷积神经网络。
Google Net 也叫Inception V1,是由Inception模块堆叠而成的卷积神经网络。
详情请见我的另一篇博客
注意:只有所有特征图大小一样(W、H一样),才能进行拼接,通道数可以不同。
# design model using class
class InceptionA(nn.Module):
def __init__(self, in_channels):
super(InceptionA, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)#padding=2,大小不变
self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)#padding=1,大小不变
self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)#padding=1,大小不变
self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)#1*1卷积
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch5x5 = self.branch5x5_1(x)
branch5x5 = self.branch5x5_2(branch5x5)
branch3x3 = self.branch3x3_1(x)
branch3x3 = self.branch3x3_2(branch3x3)
branch3x3 = self.branch3x3_3(branch3x3)
branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
branch_pool = self.branch_pool(branch_pool)
outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
return torch.cat(outputs, dim=1) # b,c,w,h c对应的是dim=1
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.incep1 = InceptionA(in_channels=10) # 与conv1 中的10对应
self.conv2 = nn.Conv2d(88, 20, kernel_size=5) # 88 = 24x3 + 16
self.incep2 = InceptionA(in_channels=20) # 与conv2 中的20对应
self.mp = nn.MaxPool2d(2)
self.fc = nn.Linear(1408, 10)#1408=88*4*4,是x展开之后的值;其实可以不用自己计算
def forward(self, x):
in_size = x.size(0)
x = F.relu(self.mp(self.conv1(x)))#W、H=12
x = self.incep1(x)
x = F.relu(self.mp(self.conv2(x)))#W、H=4
x = self.incep2(x)
x = x.view(in_size, -1)
x = self.fc(x)
return x
import numpy as np
import torch
import torch.nn as nn
from matplotlib import pyplot as plt
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
# prepare dataset
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 归一化,均值和方差
train_dataset = datasets.MNIST(root='dataset', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_dataset = datasets.MNIST(root='dataset', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
# design model using class
class InceptionA(nn.Module):
def __init__(self, in_channels):
super(InceptionA, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)#padding=2,大小不变
self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)#1*1卷积
self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)#padding=1,大小不变
self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)#padding=1,大小不变
self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)#1*1卷积
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch5x5 = self.branch5x5_1(x)
branch5x5 = self.branch5x5_2(branch5x5)
branch3x3 = self.branch3x3_1(x)
branch3x3 = self.branch3x3_2(branch3x3)
branch3x3 = self.branch3x3_3(branch3x3)
branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
branch_pool = self.branch_pool(branch_pool)
outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
return torch.cat(outputs, dim=1) # b,c,w,h c对应的是dim=1
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.incep1 = InceptionA(in_channels=10) # 与conv1 中的10对应
self.conv2 = nn.Conv2d(88, 20, kernel_size=5) # 88 = 24x3 + 16
self.incep2 = InceptionA(in_channels=20) # 与conv2 中的20对应
self.mp = nn.MaxPool2d(2)
self.fc = nn.Linear(1408, 10)#1408=88*4*4,是x展开之后的值;其实可以不用自己计算
def forward(self, x):
in_size = x.size(0)
x = F.relu(self.mp(self.conv1(x)))#W、H=12
x = self.incep1(x)
x = F.relu(self.mp(self.conv2(x)))#W、H=4
x = self.incep2(x)
x = x.view(in_size, -1)
x = self.fc(x)
return x
model = Net()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#定义device,如果有GPU就用GPU,否则用CPU
model.to(device)
# 将所有模型的parameters and buffers转化为CUDA Tensor.
criterion=torch.nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
def train(epoch):
running_loss=0.0
for batch_id,data in enumerate(train_loader,0):
inputs,target=data
inputs,target=inputs.to(device),target.to(device)
#将数据送到GPU上
optimizer.zero_grad()
# forward + backward + update
outputs=model(inputs)
loss=criterion(outputs,target)
loss.backward()
optimizer.step()
running_loss +=loss.item()
if batch_id% 300==299:
print('[%d,%5d] loss: %.3f' % (epoch+1,batch_id,running_loss/300))
running_loss=0.0
accracy = []
def test():
correct=0
total=0
with torch.no_grad():
for data in test_loader:
inputs,target=data
inputs,target=inputs.to(device),target.to(device)
#将数据送到GPU上
outputs=model(inputs)
predicted=torch.argmax(outputs.data,dim=1)
total+=target.size(0)
correct+=(predicted==target).sum().item()
print('Accuracy on test set : %d %% [%d/%d]'%(100*correct/total,correct,total))
accracy.append([100*correct/total])
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()
x=np.arange(10)
plt.plot(x, accracy)
plt.xlabel("Epoch")
plt.ylabel("Accuracy")
plt.grid()
plt.show()
卷积层是不是越多越好?
**残差连接:
class ResidualBlock(torch.nn.Module):
def __init__(self,channels):
super(ResidualBlock,self).__init__()
self.channels=channels
self.conv1=torch.nn.Conv2d(channels,channels,kernel_size=3,padding=1)#保证输出输入通道数都一样
self.conv2=torch.nn.Conv2d(channels,channels,kernel_size=3,padding=1)
self.conv3=torch.nn.Conv2d(channels,channels,kernel_size=1)
def forward(self,x):
y=F.relu(self.conv1(x))
y=self.conv2(y)
return F.relu(x+y)
Accuracy on test set : 98 % [9872/10000]
[7, 299] loss: 0.027
[7, 599] loss: 0.032
[7, 899] loss: 0.032
Accuracy on test set : 98 % [9874/10000]
[8, 299] loss: 0.028
[8, 599] loss: 0.026
[8, 899] loss: 0.026
Accuracy on test set : 99 % [9901/10000]
[9, 299] loss: 0.022
[9, 599] loss: 0.025
[9, 899] loss: 0.027
Accuracy on test set : 99 % [9900/10000]
[10, 299] loss: 0.024
[10, 599] loss: 0.019
[10, 899] loss: 0.027
Accuracy on test set : 98 % [9895/10000]