pytorch实现vgg-16
import torch
from torch.autograd import Variable
import torchvision
from torchvision import datasets, transforms, models
import os
import matplotlib.pyplot as plt
import time
%matplotlib inline
data_dir = "E:/01-论文指导/04-代码/莫烦/PyTorch-Tutorial-master/kaggle_DogsVSCats"
# 定义要对数据进行的处理
data_transform = {x: transforms.Compose([transforms.Resize([224, 224]),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])])
for x in ["train"]}
# 数据载入
image_datasets = {x: datasets.ImageFolder(root=os.path.join(data_dir, x),
transform=data_transform[x])
for x in ["train"]}
# 数据装载
dataloader = {x: torch.utils.data.DataLoader(dataset=image_datasets[x],
batch_size=16,
shuffle=True)
for x in ["train"]}
X_example, y_example = next(iter(dataloader["train"]))
print(u'X_example个数{}'.format(len(X_example)))
print(u'y_example个数{}'.format(len(y_example)))
print(X_example.shape)
print(y_example.shape)
#torch.Size([16, 3, 224, 224])第一位表示batchsize,第二维表示输入的channels,第三位表示图片height,第四位表示图片的width
# 验证独热编码的对应关系
index_classes = image_datasets["train"].class_to_idx
# print(index_classes)
# 使用example_classes存放原始标签的结果
example_classes = image_datasets["train"].classes
# print(example_classes)
# 图片预览
img = torchvision.utils.make_grid(X_example)
# print(img.shape)
img = img.numpy().transpose([1, 2, 0])
for i in range(len(y_example)):
index = y_example[i]
print(example_classes[index], end=' ')
if (i + 1) % 8 == 0:
print()
# print(img.max())
# print(img.min())
# print(img.shape)
std = [0.5, 0.5, 0.5]
mean = [0.5, 0.5, 0.5]
img = img * std + mean
# print(img.max())
# print(img.min())
# print(img.shape)
plt.imshow(img)
plt.show()
# 下载已经具备最优参数的VGG16模型
model = models.vgg16(pretrained=True)
# 查看迁移模型细节
# print("迁移VGG16:\n", model)
# 对迁移模型进行调整
for parma in model.parameters():
parma.requires_grad = False
model.classifier = torch.nn.Sequential(torch.nn.Linear(25088, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(p=0.5),
torch.nn.Linear(4096, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(p=0.5),
torch.nn.Linear(4096, 2))
# 查看调整后的迁移模型
# print("调整后VGG16:\n", model)
# 判断计算机的GPUs是否可用
Use_gpu = torch.cuda.is_available()
if Use_gpu:
model = model.cuda()
# 定义代价函数和优化函数
loss_f = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.classifier.parameters(), lr=0.00001)
# 模型训练和参数优化
epoch_n = 5
time_open = time.time()
for epoch in range(epoch_n):
print("Epoch {}/{}".format(epoch + 1, epoch_n))
print("-" * 10)
for phase in ["train"]:
if phase == "train":
print("Training...")
# 设置为True,会进行Dropout并使用batch mean和batch var
model.train(True)
else:
print("Validing...")
# 设置为False,不会进行Dropout并使用running mean和running var
model.train(False)
running_loss = 0.0
running_corrects = 0
# enuerate(),返回的是索引和元素值,数字1表明设置start=1,即索引值从1开始
for batch, data in enumerate(dataloader[phase], 1):
# X: 图片,16*3*224*224; y: 标签,16
X, y = data
# 修改处
if Use_gpu:
X, y = Variable(X.cuda()), Variable(y.cuda())
else:
X, y = Variable(X), Variable(y)
# y_pred: 预测概率矩阵,16*2
y_pred = model(X)
# pred,概率较大值对应的索引值,可看做预测结果
_, pred = torch.max(y_pred.data, 1)
# 梯度归零
optimizer.zero_grad()
# 计算损失
loss = loss_f(y_pred, y)
# 若是在进行模型训练,则需要进行后向传播及梯度更新
if phase == "train":
loss.backward()
optimizer.step()
# 计算损失和
running_loss += float(loss)
# 统计预测正确的图片数
running_corrects += torch.sum(pred == y.data)
# 共20000张测试图片,1250个batch,在使用500个及1000个batch对模型进行训练之后,输出训练结果
if batch % 500 == 0 and phase == "train":
print("Batch {}, Train Loss:{:.4f}, Train ACC:{:.4F}%".format(batch, running_loss / batch,
100 * running_corrects / (16 * batch)))
epoch_loss = running_loss * 16 / len(image_datasets[phase])
epoch_acc = 100 * running_corrects / len(image_datasets[phase])
# 输出最终的结果
print("{} Loss:{:.4f} Acc:{:.4f}%".format(phase, epoch_loss, epoch_acc))
# 输出模型训练、参数优化用时
time_end = time.time() - time_open
print(time_end)
结果:

遇到的问题很多。。。
import torch from torch.autograd import Variable import torchvision from torchvision import datasets, transforms, models import os import matplotlib.pyplot as plt import time %matplotlib inline
1、导包
报错:ModuleNotFoundError: No module named 'matplotlib'
之前还可以运行,后来就报错这句,解决办法是cmd到当前环境下,然后运行pip install matplotlib安装后重启不管是jupyter notebook还是pycharm都可以了
另外%matplotlib inline前面%后不要空格
# 数据载入
image_datasets = {x: datasets.ImageFolder(root=os.path.join(data_dir, x),
transform=data_transform[x])
for x in ["train"]}
2、数据载入
报错:Found 0 files in subfolders....
开始还以为是读不到文件。后来才知道这句代码和数据集不匹配有问题:
ImageFolder假设所有的文件按文件夹保存好,每个文件夹下面存贮同一类别的图片,文件夹的名字为分类的名字
数据集中是猫和狗的图片,没有分文件夹,不能从train中文件夹获得标签,手动建了文件夹就可以了。
3、数据装载
dataloader = {x: torch.utils.data.DataLoader(dataset=image_datasets[x],
batch_size=16,
shuffle=True)
for x in ["train"]}
PyTorch中数据读取的一个重要接口是torch.utils.data.DataLoader。
只要是用PyTorch来训练模型基本都会用到该接口,该接口主要用来将自定义的数据读取接口的输出或者PyTorch已有的数据读取接口的输入按照batch size封装成Tensor,后续只需要再包装成Variable即可作为模型的输入
(1)dataset,这个就是PyTorch已有的数据读取接口(比如torchvision.datasets.ImageFolder)或者自定义的数据接口的输出,该输出要么是torch.utils.data.Dataset类的对象,要么是继承自torch.utils.data.Dataset类的自定义类的对象。
(2)batch_size,根据具体情况设置即可。
(3)shuffle,一般在训练数据中会采用。
(4)collate_fn,是用来处理不同情况下的输入dataset的封装,一般采用默认即可,除非你自定义的数据读取输出非常少见。
(5)batch_sampler,从注释可以看出,其和batch_size、shuffle等参数是互斥的,一般采用默认。
(6)sampler,从代码可以看出,其和shuffle是互斥的,一般默认即可。
(7)num_workers,从注释可以看出这个参数必须大于等于0,0的话表示数据导入在主进程中进行,其他大于0的数表示通过多个进程来导入数据,可以加快数据导入速度。
(8)pin_memory,注释写得很清楚了: pin_memory (bool, optional): If True, the data loader will copy tensors into CUDA pinned memory before returning them. 也就是一个数据拷贝的问题。
(9)timeout,是用来设置数据读取的超时时间的,但超过这个时间还没读取到数据的话就会报错。
4、遍历图片?
打印#torch.Size([16, 3, 224, 224])第一位表示batchsize,第二维表示输入的channels,第三位表示图片height,第四位表示图片的width
X_example, y_example = next(iter(dataloader["train"]))
print(u'X_example个数{}'.format(len(X_example)))
print(u'y_example个数{}'.format(len(y_example)))
print(X_example.shape)
print(y_example.shape)

浙公网安备 33010602011771号