参考:
网络模型讲解和搭建:B站 刘二大人 ,传送门PyTorch深度学习实践——卷积神经网络(高级篇)
动态化学习率:https://blog.csdn.net/a906958671/article/details/104967447
采用的是使用文件夹名进行数据集分组:
dog:crab
训练集二分类各450张;验证集:50张
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.optim as optim
import matplotlib.pyplot as plt
import cv2
import copy
import numpy as np
batch_size = 32
LR = 0.002
Mom = 0.02
transform = transforms.Compose([
# transforms.Resize(224), # 缩放图片(Image),保持长宽比不变,最短边为32像素
# transforms.CenterCrop(224), # 从图片中间切出32*32的图片
transforms.ToTensor(), # 将图片(Image)转成Tensor,归一化至[0, 1]
transforms.Normalize(mean=[0.492, 0.461, 0.417], std=[0.256, 0.248, 0.251]) # 标准化至[-1, 1],规定均值和标准差
])
train_dataset = datasets.ImageFolder(root="D:\\VScode_workfile\\CNN_test\\train", transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
val_dataset = datasets.ImageFolder(root="D:\\VScode_workfile\\CNN_test\\val", transform=transform)
val_loader = DataLoader(val_dataset, shuffle=False, batch_size=batch_size)
# img, label = train_dataset[0] #print show me what is this
# print(label)
# print(img.size)
# design model using class
#InceptionA 类,方便待会做网络的拼接
class InceptionA(nn.Module):
def __init__(self, in_channels):
super(InceptionA, self).__init__()
self.branch1x1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)
self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)
self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)
self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=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(3,10,kernel_size = 5)
self.conv2 = nn.Conv2d(88,20,kernel_size = 5)
self.incep1 = InceptionA(in_channels = 10)
self.incep2 = InceptionA(20)
self.mp = nn.MaxPool2d(2)
self.fc = nn.Linear(247192,10)
def forward(self, x):
in_size = x.size(0)
x = F.relu(self.mp(self.conv1(x)))
x = self.incep1(x)
x = F.relu(self.mp(self.conv2(x)))
x = self.incep2(x)
x = x.view(in_size, -1)
#print(x.size()) 可以先进行打印出来看看最后输出多少
x = self.fc(x)
return x
model = Net()
#使用GPU训练数据,和进行梯度的求解
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
# construct loss and optimizer
#交叉熵损失函数
criterion = torch.nn.CrossEntropyLoss()
criterion = criterion.to(device)
#动态化学习率
optimizer = optim.SGD(model.parameters(), lr = LR, momentum = Mom)
scheduler = optim.lr_scheduler.StepLR(optimizer,step_size=4,gamma = 0.65)
# training cycle forward, backward, update
def train(epoch):
running_loss = 0.0
epoch_loss = 10.0
for batch_idx, data in enumerate(train_loader,0):
input,target = data
input,target = input.to(device),target.to(device)
optimizer.zero_grad()
output = model(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
print("loss = %.3f" % running_loss)
if batch_idx % 15 == 14:
av_epoch_loss = running_loss/15
print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, av_epoch_loss))
if av_epoch_loss < epoch_loss:
epoch_loss = av_epoch_loss
running_loss = 0.0
return epoch_loss
def val():
correct = 0
total = 0
with torch.no_grad():
for data in val_loader:
images, labels = data
images,labels = images.to(device),labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('accuracy on test set: %d %% ' % (100*correct/total))
return correct/total
if __name__ == '__main__':
epoch_list = []
loss_list = []
val_list = []
val_acc = 0
best_model = None
min_loss_val = 10 # 任取一个大数
Cheng_loss = 1.0
for epoch in range(20):
Cheng_loss = train(epoch)
val_acc = val()
print("------------------------------------------------------")
print('Epoch : %5d loss: %.3f acc: %.3f' % (epoch+1, Cheng_loss, val_acc))
if Cheng_loss <= min_loss_val:
min_loss_val = Cheng_loss
best_model = copy.deepcopy(model)#might something wrong with it 、
#将最好的模型保存下来
torch.save(model,"D:\\VScode_workfile\\CNN_test\\best.pkl")
epoch_list.append(epoch)
if Cheng_loss>1:
Cheng_loss = 1.0
loss_list.append(Cheng_loss)
val_list.append(val_acc)
# lenth = loss_list.size()
fig, ax = plt.subplots()
ax.plot(epoch_list, val_list, label='val')
ax.plot(epoch_list, loss_list, label='loss')
# ax.scatter([1, 2, 3, 4], [20, 10, 30, 15], label='Point')
ax.set(ylabel='val and loss ', xlabel='epoch', title='A total train and val')
ax.legend()
plt.show()
关于训练结果,分析下来还是太少,看不出来了,batch_size 越大越好,能够减少震荡,学习记录。