一.原有代码
1.1导入相关的包
1.2数据标准化
1.3加载训练集和测试集
1.4创建VGG模型
1.5训练模型(训练集)
'''
第一步:创建损失函数和优化器
损失函数 NLLLoss() 的 输入 是一个对数概率向量和一个目标标签.
它不会为我们计算对数概率,适合最后一层是log_softmax()的网络.
'''
criterion = nn.NLLLoss()
# 学习率
lr = 0.001
# 随机梯度下降
optimizer_vgg = torch.optim.SGD(model_vgg_new.classifier[6].parameters(),lr = lr)
'''
第二步:训练模型
'''
def train_model(model,dataloader,size,epochs=1,optimizer=None):
model.train()
for epoch in range(epochs):
running_loss = 0.0
running_corrects = 0
count = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes)
optimizer = optimizer
optimizer.zero_grad()
loss.backward()
optimizer.step()
_,preds = torch.max(outputs.data,1)
# statistics
• running_loss += loss.data.item()
• running_corrects += torch.sum(preds == classes.data)
• count += len(inputs)
• print('Training: No. ', count, ' process ... total: ', size)
• epoch_loss = running_loss / size
• epoch_acc = running_corrects.data.item() / size
• print('Loss: {:.4f} Acc: {:.4f}'.format(
• epoch_loss, epoch_acc))
•
•
# 模型训练
train_model(model_vgg_new,loader_train,size=dset_sizes['train'], epochs=1,
optimizer=optimizer_vgg)
1.6测试模型(测试集)
二.AI研习社测试
2.1导入相关的包
import numpy as np
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import torchvision
from torchvision import models,transforms,datasets
import time
import json
2.2加载数据集
2.3划分数据集
这里分别在train和val文件夹下面新建cats和dogs子文件夹,然后分别把猫狗的照片放在里面,然后在test文件夹下面新建img文件夹,方便后面的datasets.ImageFolder()的正常使用。
%%shell
for filename in `ls ./drive/MyDrive/cat_dog/train`
do
if [ ${filename: 0:3} == "cat" ]
then
mkdir -p ./drive/MyDrive/cat_dog/train/cats
mv -i ./drive/MyDrive/cat_dog/train/$filename ./drive/MyDrive/cat_dog/train/cats/$filename
fi
done
for filename in `ls ./drive/MyDrive/cat_dog/train`
do
if [ ${filename: 0:3} == "dog" ]
then
mkdir -p ./drive/MyDrive/cat_dog/train/dogs
mv -i ./drive/MyDrive/cat_dog/train/$filename ./drive/MyDrive/cat_dog/train/dogs/$filename
fi
done
for filename in `ls ./drive/MyDrive/cat_dog/val`
do
if [ ${filename: 0:3} == "cat" ]
then
mkdir -p ./drive/MyDrive/cat_dog/val/cats
mv -i ./drive/MyDrive/cat_dog/val/$filename ./drive/MyDrive/cat_dog/val/cats/$filename
fi
done
for filename in `ls ./drive/MyDrive/cat_dog/val`
do
if [ ${filename: 0:3} == "dog" ]
then
mkdir -p ./drive/MyDrive/cat_dog/val/dogs
mv -i ./drive/MyDrive/cat_dog/val/$filename ./drive/MyDrive/cat_dog/val/dogs/$filename
fi
done
for filename in `ls ./drive/MyDrive/cat_dog/test`
do
mkdir -p ./drive/MyDrive/cat_dog/test/img
mv -i ./drive/MyDrive/cat_dog/test/$filename ./drive/MyDrive/cat_dog/test/img/$filename
done
结果:
2.4数据标准化及图像处理
#数据标准化
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
#图像预处理成224*224*3大小
vgg_format = transforms.Compose([
transforms.CenterCrop(224),
transforms.ToTensor(),
normalize,
])
data_dir = './drive/MyDrive/cat_dog'
dsets = {x: datasets.ImageFolder(os.path.join(data_dir, x), vgg_format)
for x in ['train', 'val']}
dset_sizes = {x: len(dsets[x]) for x in ['train', 'val']}
dset_classes = dsets['train'].classes
# 通过下面代码可以查看 dsets 的一些属性
print(dsets['val'].classes)
print(dsets['val'].class_to_idx)
print(dsets['val'].imgs[:5])
print('dset_sizes: ', dset_sizes)
2.6加载训练集和测试集,创建模型
#加载训练集和测试集
loader_train = torch.utils.data.DataLoader(dsets['train'], batch_size=64, shuffle=True, num_workers=6)
loader_valid = torch.utils.data.DataLoader(dsets['val'], batch_size=5, shuffle=False, num_workers=6)
#创建模型
model_vgg = models.vgg16(pretrained=True)
model_vgg = model_vgg.to(device)
print(model_vgg)
#修改最后一层,冻结前面层的参数
model_vgg_new = model_vgg;
for param in model_vgg_new.parameters():
param.requires_grad = False
model_vgg_new.classifier._modules['6'] = nn.Linear(4096, 2)
model_vgg_new.classifier._modules['7'] = torch.nn.LogSoftmax(dim = 1)
model_vgg_new = model_vgg_new.to(device)
print(model_vgg_new.classifier)
2.7开始训练并保存模型
'''
第一步:创建损失函数和优化器
损失函数 NLLLoss() 的 输入 是一个对数概率向量和一个目标标签.
它不会为我们计算对数概率,适合最后一层是log_softmax()的网络.
'''
criterion = nn.NLLLoss()
# 学习率
lr = 0.0001
# 随机梯度下降
optimizer_vgg = torch.optim.SGD(model_vgg_new.classifier[6].parameters(),lr = lr)
'''
第二步:训练模型
'''
def train_model(model,dataloader,size,epochs=1,optimizer=None):
model.train()
for epoch in range(epochs):
running_loss = 0.0
running_corrects = 0
count = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes)
optimizer = optimizer
optimizer.zero_grad()
loss.backward()
optimizer.step()
_,preds = torch.max(outputs.data,1)
# statistics
running_loss += loss.data.item()
running_corrects += torch.sum(preds == classes.data)
count += len(inputs)
print('Training: No. ', count, ' process ... total: ', size)
epoch_loss = running_loss / size
epoch_acc = running_corrects.data.item() / size
print('epoch: ', epoch)
print('Loss: {:.8f} Acc: {:.8f}'.format(
epoch_loss, epoch_acc))
# 测试准确率大于0.966时保存模型
if epoch_acc > 0.96600000:
torch.save(model, './drive/MyDrive/model/model_' + str(epoch_acc)[2:] + '_' + str(epoch) + '.pth')
# 模型训练
train_model(model_vgg_new,loader_train,size=dset_sizes['train'], epochs=10,
optimizer=optimizer_vgg)
最后结果:
可以看到10轮训练完之后,预测的准确率达到了96.8%,这个结果比较可信。
最后保存下来有三个模型准确率比较高。
2.8处理未分类的数据集test,并将结果提交到AI研习社
data_dir = './drive/MyDrive/cat_dog/test'
dsets = {'test': datasets.ImageFolder(data_dir, vgg_format)}
dset_sizes = len(dsets['test'])
loader_test = torch.utils.data.DataLoader(dsets['test'], batch_size=1, num_workers=6)
#从上述保存下来的模型中选择准确率最高的模型对未分类的数据进行测试
model_vgg_new = torch.load('./drive/MyDrive/model/model_9804_60.pth');
model_vgg_new = model_vgg_new.to(device)
import csv
def test_model(model,dataloader,size):
model.eval()
predictions = np.zeros(size)
i = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
• outputs = model(inputs)
• _,preds = torch.max(outputs.data,1)
• \# statistics
• predictions[int(dsets['test'].imgs[i][0][33:-4])] = preds.to('cpu').numpy()
• i += 1
• print('Testing: No. ', i, ' process ... total: ', size)
csvFile = open("./drive/MyDrive/cat_dog_result/result.csv", "w")
writer = csv.writer(csvFile)
for i in range(dset_sizes):
writer.writerow([i, predictions[i]])#把预测的数据写进CSV文件里面 ,0代表猫,1代表狗
print("Save successfully!!!")
return predictions
predictions = test_model(model_vgg_new,loader_test,size=dset_sizes)
保存下来的csv文件:
研习社结果:
三.实验分析
1.最后结果的准确率为96.85%左右,准确率并不是很高,我们小组刚开始的时候进行了100轮的训练,训练到后面的时候,准确率达到了98%左右,但是发现colab这个平台训练久了容易掉线,所以我们把训练轮数调到了10轮左右,最后成功显示了结果。
2.另外,训练中学习率不能过小,过小的话损失值曲线收敛的很慢,在有限的epochs中不能训练出很好地结果。学习率如果过大开始时loss下降得快,但后面会产生无法拟合的现象。因此学习率应该选取合适的值不应该过大或过小。 3.进一步改进需要采用更好的模型,如使用其他深度学习网络,增加网络深度,或者是选择别的优化器可能会产生更好的效果。