前言
VGG是由Simonyan 和Zisserman在文献《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷积神经网络模型,其名称来源于作者所在的牛津大学视觉几何组(Visual Geometry Group)的缩写。
该模型参加2014年的 ImageNet图像分类与定位挑战赛,取得了优异成绩:在分类任务上排名第二,在定位任务上排名第一。
VGG16的网络结构如下图所示:
Kaggle 于2013年举办的猫狗大战比赛,判断一张输入图像是“猫”还是“狗”。该教程使用在 ImageNet 上预训练 的 VGG16 网络进行测试。因为原网络的分类结果是1000类,所以这里进行迁移学习,对原网络进行 fine-tune (即固定前面若干层,作为特征提取器,只重新训练最后几层)。
步骤
- 从AI研习社练习赛的网站上下载用于训练、验证和测试的数据集
- 改进VGG16模型,利用训练数据集训练新的模型
- 使用验证数据集对新模型进行验证,并调整参数
- 用测试数据集得到最终结果,上传到练习赛的网站查看排名。
Python 实现
1.预处理工作
- 判断是否有GPU
# 判断是否存在GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
- 数据存放也需要的进行一定更改
原始的目录存放格式如下:
更改后的目录结构:
# 数据存放目录
data_dir = './data/cat_dog'
# 在train数据集中创建cats和dogs子文件夹,方便ImageFolder的读取
train_dir = os.path.join(data_dir, 'train')
train_cats_dir = os.path.join(train_dir, 'cats')
train_dogs_dir = os.path.join(train_dir, 'dogs')
list_dir = os.listdir(train_dir)
os.mkdir(train_cats_dir)
os.mkdir(train_dogs_dir)
for i in list_dir:
if 'cat' in i:
shutil.copyfile(os.path.join(train_dir, i), os.path.join(train_cats_dir, i))
else:
shutil.copyfile(os.path.join(train_dir, i), os.path.join(train_dogs_dir, i))
# 在val数据集中创建cats和dogs子文件夹,方便ImageFolder的读取
val_dir = os.path.join(data_dir, 'val')
val_cats_dir = os.path.join(val_dir, 'cats')
val_dogs_dir = os.path.join(val_dir, 'dogs')
list_dir = os.listdir(val_dir)
os.mkdir(val_cats_dir)
os.mkdir(val_dogs_dir)
for i in list_dir:
if 'cat' in i:
shutil.copyfile(os.path.join(val_dir, i), os.path.join(val_cats_dir, i))
else:
shutil.copyfile(os.path.join(val_dir, i), os.path.join(val_dogs_dir, i))
# 在test数据集中创建raw子文件夹,方便ImageFolder的读取
test_dir = os.path.join(data_dir, 'test')
test_raw_dir = os.path.join(test_dir, 'raw')
list_dir = os.listdir(test_dir)
os.mkdir(test_raw_dir)
for i in list_dir:
filename = ''.join(i.zfill(8))
shutil.copyfile(os.path.join(test_dir, i), os.path.join(test_raw_dir, filename))
- 定义数据集的loader
# 读取三个数据集
transform = transforms.Compose([
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
data_sets = {
'train': datasets.ImageFolder(train_dir, transform),
'val': datasets.ImageFolder(val_dir, transform),
'test': datasets.ImageFolder(test_dir, transform)}
# data_sets的行数
data_set_sizes = {
x: len(data_sets[x]) for x in ['train',