vgg16网络模型的实现
这里只讲怎么实现
百度搜到vgg16的网络模型图,用pytorch框架进行实现
图是这样,用pytorch实现就行,pyotrch不太熟悉的话可以去看小土堆的视频
命名mode.py 也可以使用其他名字,在后面的train.py里面改一下也行
import torch
import torch.nn as nn
class VGG16(nn.Module):
def __init__(self):
super(VGG16, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(3, 64, 3, 1, 1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.Conv2d(64, 64, 3, 1, 1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
self.layer2 = nn.Sequential(
nn.Conv2d(64, 128, 3, 1, 1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.Conv2d(128, 128, 3, 1, 1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
self.layer3 = nn.Sequential(
nn.Conv2d(128, 256, 3, 1, 1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.Conv2d(256, 256, 3, 1, 1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.Conv2d(256, 256, 3, 1, 1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
self.layer4 = nn.Sequential(
nn.Conv2d(256, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(512, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(512, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
self.layer5 = nn.Sequential(
nn.Conv2d(512, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(512, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.Conv2d(512, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
self.fc1 = nn.Sequential(
nn.Flatten(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Dropout()
)
self.fc2 = nn.Sequential(
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout()
)
self.fc3 = nn.Linear(256, 10)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.layer5(x)
x = self.fc1(x)
x = self.fc2(x)
x = self.fc3(x)
return x
if __name__ == '__main__':
VGG16 = VGG16()
input = torch.ones((64, 3, 32, 32))
output = VGG16(input)
print(output.shape)
训练文件的编写
具体的都在注释里,需要注意的是 命名train.py
- 模型文件与训练文件在同一文件夹下
- batch_size以及epoch和学习率lr根据自己的需要进行更改,同时更改生成的模型文件名以及日志名(在代码里)要不会乱套
- 数据集设置的是假如没有会自动下载,因此不用担心下载数据集
- 本人的实验环境 ubuntu 18.04 显卡:2080ti window下的可以尝试应该没问题
import torchvision
from torch import optim
from torch.utils.data import DataLoader
import torch.nn as nn
from model import *
import matplotlib.pyplot as plt
import time
from torch.utils.tensorboard import SummaryWriter
device = torch.device("cuda:0")
train_data = torchvision.datasets.CIFAR10(root="data", train=True, transform=torchvision.transforms.ToTensor(),
download=True)
test_data = torchvision.datasets.CIFAR10(root="data", train=False, transform=torchvision.transforms.ToTensor(),
download=True)
train_dataloader = DataLoader(train_data, batch_size=128)
test_dataloader = DataLoader(test_data, batch_size=128)
file = open('logs_epoch50_bt128_lr0.015.txt', 'w')
# 查看测试集,训练集的大小
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
file.write("训练数据集的长度为:{}".format(train_data_size) + '\n')
print("测试数据集的长度为:{}".format(test_data_size))
file.write("测试数据集的长度为:{}".format(test_data_size) + '\n')
# 创建网络模型
vgg16 = VGG16()
vgg16 = vgg16.to(device)
# 损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)
# 优化器
learning_rate = 0.015 # 设置学习速率
optimizer = torch.optim.SGD(vgg16.parameters(), lr=learning_rate)
# 设置训练网络的参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 50
# 添加tensorboard画图可视化
writer = SummaryWriter("logs_train")
for i in range(epoch):
print("--------第{}轮训练开始---------".format(i + 1))
file.write("--------第{}轮训练开始---------".format(i + 1) + '\n')
for data in train_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
outputs = vgg16(imgs)
loss = loss_fn(outputs, targets)
# 梯度调0
optimizer.zero_grad()
# 反向传播 梯度
loss.backward()
# 调优
optimizer.step()
# 记录训练次数
total_train_step = total_train_step + 1
# 每100打印loss
if total_train_step % 100 ==0:
print("训练次数:{},Loss:{}".format(total_train_step,
loss.item()))
file.write("训练次数:{},Loss:{}".format(total_train_step,
loss.item()) + '\n')
writer.add_scalar("train_loss", loss.item(), total_train_step)
# 测试,没梯度没有调优代码
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
outputs = vgg16(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss.item()
# 计算整体测试集上的正确率
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy = total_accuracy + accuracy
print("整体测试集上的loss:".format(total_test_loss))
file.write("整体测试集上的loss:".format(total_test_loss) + '\n')
# 使用/进行的tensor整数除法不再支持,可以使用true_divide代替
print("整体测试集上的正确率:{}".format(total_accuracy.true_divide(test_data_size)))
file.write("整体测试集上的正确率:{}".format(total_accuracy.true_divide(test_data_size)) + '\n')
writer.add_scalar("test_loss", total_test_loss, total_test_step)
total_test_step = total_test_step + 1
# 可视化正确率
writer.add_scalar("test_accuracy", total_accuracy.true_divide(test_data_size), total_test_step)
# 保存每一轮的模型 这是第一种保存方式非官方推荐
torch.save(vgg16, "epoch50_bt128_lr0.015/vgg16_{}.pth".format(i+1))
print("模型已保存")
writer.close()
训练日志如下(具体大家自行训练)
训练数据集的长度为:50000
测试数据集的长度为:10000
--------第1轮训练开始---------
训练次数:100,Loss:1.8452614545822144
训练次数:200,Loss:1.3886604309082031
训练次数:300,Loss:1.4469469785690308
整体测试集上的loss:
整体测试集上的正确率:0.5472999811172485
--------第2轮训练开始---------
训练次数:400,Loss:1.108359694480896
训练次数:500,Loss:1.1589107513427734
训练次数:600,Loss:1.156502604484558
训练次数:700,Loss:0.886533796787262
整体测试集上的loss:
整体测试集上的正确率:0.6538000106811523
--------第3轮训练开始---------
训练次数:800,Loss:0.884425163269043
训练次数:900,Loss:0.8080787062644958
训练次数:1000,Loss:0.7888829112052917
训练次数:1100,Loss:0.6955403089523315
整体测试集上的loss:
整体测试集上的正确率:0.7030999660491943