Pytorch实现卷积神经网络
用 python 的 Pytorch 模块实现卷积神经网络。网络结构为一个输入层、两个卷积层、一个全连接层、一个输出层。
本次实验完全在itc的虚拟环境中操作并且运行。为了突出重点,操作流程不再赘述,对编程流程进行详细地描述。
首先是输入的图片, 经过一层卷积层, 然后在用池化方式处理卷积的信息, 然后再经过一次同样的处理, 把得到的第二次处理的信息传入全连接的神经层,最后在接上一个分类器进行分类预测。
详细流程:
卷积神经网络相比与上次实验的全连接神经网络增加了卷积层和池化层,与此同时,不再是全连接,而是局部连接,并且采用了权值共享的策略。其中,局部连接和权值共享降低了参数的规模,使训练的复杂度大大下降并且减轻了过拟合,池化层的降采样则进一步降低了输出的参数规模,提高了模型的泛化能力。
入门卷积神经网络其实并不难,但是想在这个领域学深学精还是需要花费一定时间和精力的。在学习卷积神经网络时需要多了解几种网络结构,由浅入深,思考为什么这么做,这么做的好处和意义。多实践多动手,不仅可以让我们对卷积神经网络的流程有更加深刻的了解和掌握,而且可以让我们打好坚实的基础,更有基础和实力去深入钻研。
import torch
from torch import nn
import torchvision
from tqdm import tqdm
torch.cuda.is_available()
BATCH_SIZE = 100
EPOCHS = 10
learning_rate = 1e-4
keep_prob_rate = 0.7
device = "cuda:0" if torch.cuda.is_available() else "cpu"
transform = torchvision.transforms.Compose(
[torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(mean = [0.5], std = [0.5])]m
)
path = './data/'
trainData = torchvision.datasets.MNIST(
path, train = True, transform = transform, download= True
)
testData = torchvision.datasets.MNIST(
path, train = False, transform = transform
)
trainDataLoader = torch.utils.data.DataLoader(
dataset = trainData, batch_size = BATCH_SIZE,shuffle = True
)
testDataLoader = torch.utils.data.DataLoader(
dataset = testData, batch_size = BATCH_SIZE
)
class Net(torch.nn.Module):
def __init__(self):
super(Net,self).__init__()
self.model = torch.nn.Sequential(
torch.nn.Conv2d(
in_channels=1,out_channels=32,
kernel_size=7,padding=3,stride=1
),
torch.nn.ReLU(),
torch.nn.MaxPool2d(
kernel_size=2,stride=2
),
torch.nn.Conv2d(
in_channels=32,out_channels=64,
kernel_size=5,stride=1,padding=2
),
torch.nn.ReLU(),
torch.nn.MaxPool2d(
kernel_size=2,stride=2
),
torch.nn.Flatten(),
torch.nn.Linear(in_features=7*7*64, out_features= 1024),
torch.nn.ReLU(),
torch.nn.Dropout(1-keep_prob_rate),
torch.nn.Linear(in_features=1024,out_features=10),
torch.nn.Softmax(dim=1)
)
def forward(self, input):
output = self.model(input)
return output
net = Net()
print(net.to(device))
lossF = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(params=net.parameters(),lr=learning_rate)
history = {'Test Loss':[], 'Test Accuracy':[]}
for epoch in range(1,EPOCHS+1):
processBar = tqdm(trainDataLoader,unit='step')
net.train(True)
for step,(trainImgs, labels) in enumerate(processBar):
trainImgs = trainImgs.to(device)
labels = labels.to(device)
net.zero_grad()
outputs = net(trainImgs)
loss = lossF(outputs,labels)
predictions = torch.argmax(outputs,dim=1)
accuracy = torch.sum(predictions==labels)/labels.shape[0]
loss.backward()
optimizer.step()
processBar.set_description(
"[%d/%d] Loss: %.4f, Acc: %.4f" %(
epoch,EPOCHS,loss.item(),accuracy.item()
)
)
if step == len(processBar)-1:
correct, totalLoss = 0,0
net.train(False)
for testImgs,labels in testDataLoader:
testImgs = testImgs.to(device)
labels = labels.to(device)
outputs = net(testImgs)
loss = lossF(outputs,labels)
predicions = torch.argmax(outputs,dim=1)
totalLoss+=loss
correct+=torch.sum(predicions==labels)
testAccuracy = correct/(BATCH_SIZE*len(testDataLoader))
testLoss = totalLoss/len(testDataLoader)
history['Test Loss'].append(testLoss.item())
history['Test Accuracy'].append(testAccuracy.item())
processBar.set_description(
"[%d/%d] Loss: %.4f, Acc: %.4f, Test Loss: %.4f, Test Acc: %.4f" % (
epoch,EPOCHS,loss.item(),accuracy.item(),
testLoss.item(),testAccuracy.item()
)
)
processBar.close()