学习Pytorch-计算机视觉-03

以下都是我学习的一些笔记,记录一下。
这次我们用经典项目:猫狗大战来进行学习。
首先是数据集下载,这里就不提供下载了,网上有很多的
1.首先我们导入可能要用到的包,如下:

import torch
import torchvision
from torchvision import datasets,transforms
import  os   #os包集成了一些对文件路径和目录操作的类
import matplotlib.pyplot as plt
import  time
from torch.autograd import  Variable

2.数据的载入以及装载,代码如下:

data_dir = "DogsVSCats"
data_transform = {x:transforms.Compose([transforms.Resize([64,64]),#统一将图片缩放至64*64
                                        transforms.ToTensor()])
                                        for x in ["train","valid"]}

image_datasets = {x:datasets.ImageFolder(root=os.path.join(data_dir,x),
                                         transform = data_transform[x])
                                         for x in ["train","valid"]}

dataloader = {x:torch.utils.data.DataLoader(dataset = image_datasets[x],
                                            batch_size = 16,
                                            shuffle = True)
                                            for x in ["train","valid"]}

3.数据的预览
代码如下:

X_example,y_example = next(iter(dataloader["train"]))

print(u"X_example个数{}".format(len(X_example)))
print(u"y_example个数{}".format(len(y_example)))

index_classes = image_datasets["train"].class_to_idx
print(index_classes)
example_clasees = image_datasets["train"].classes  #example_clasees 变量其实就是一个列表
print(example_clasees)

img = torchvision.utils.make_grid(X_example)
img = img.numpy().transpose([1,2,0])
print([example_clasees[i] for i in y_example])
plt.imshow(img)
plt.show()

结果如图所示:
在这里插入图片描述
4.构建网络模型,这边先自定义一个VGG网络,搭建一个简单的VGG网络。
代码如下:

#Vgg自定义框架
class Models(torch.nn.Module):
    def __init__(self):
        super(Models,self).__init__()
        self.Conv = torch.nn.Sequential(
            torch.nn.Conv2d(3,64,kernel_size=3,stride=1,padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(64,64,kernel_size=3,stride=1,padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2,stride=2),

            torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2),

            torch.nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2),

            torch.nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2),
        )
        self.Classes = torch.nn.Sequential(
            torch.nn.Linear(4*4*512,1024),
            torch.nn.ReLU(),
            torch.nn.Dropout(p=0.5),
            torch.nn.Linear(1024,1024),
            torch.nn.ReLU(),
            torch.nn.Dropout(p=0.5),
            torch.nn.Linear(1024, 2),
        )

    def forward(self,input):
        x = self.Conv(input)
        x = x.view(-1,4*4*512)
        x = self.Classes(x)
        return x

5.训练即可,代码如下:

loss_f = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr = 0.00001)

epoch_n = 10
time_open = time.time()

for epoch in range(epoch_n):
    print("Epoch {}/{}".format(epoch, epoch_n - 1))
    print("-" * 10)

    for phase in ["train","valid"]:
        if phase == "train":
            print("Training.....")
            model.train(True)
        else:
            print("Validing....")
            model.train(False)

        running_loss = 0.0  # 损失的数值
        running_corrects = 0  # 预测的正确数目

        for batch,data in enumerate(dataloader[phase],1):
            X,y = data
            X,y = Variable(X),Variable(y)
            y_pred = model(X)

            _,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 += loss.item()  # 累计所有的损失值
            running_corrects += torch.sum(pred == y.data)  # 累计所有的正确次数

            if batch%500 == 0 and phase =="train":
               print("Batch{},Train Loss:{:.4f},Train ACC:{:.4f}".format(
                  batch,torch.true_divide(running_loss,batch),100*torch.true_divide(running_corrects,16*batch)
                ))
        epoch_loss = torch.true_divide(running_loss*16,len(image_datasets[phase]))
        epoch_acc = 100*torch.true_divide(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)

到这里就结束训练与测试了,建议大家用GPU,不然CPU会花费很多的时间。
这不是今天讲的重点,今天我要记录的重点是迁移模型,很明显大家去运行测试结果发现,效果并不理想,我们可以适当的换其他模型试试。
(1)VGG16
既然要用到VGG16,那么如何使用呢,请看代码:

#迁移Vgg16
model = models.vgg16(progress=True)  #迁移代码

这段直接调用VGG16,没有的会自动下载,建议下载好放到对应的文件中,不然速度感人。
打印一下模型,可以看到(没截全):
在这里插入图片描述
当然现在还不能用,因为我们可以看到原来的VGG16模型最终从全连接层输出的是4096个结果,而我们只需要输出两个,增加如下代码:

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)
                                       )

上面的代码第一行,将他置为False就是不进行梯度更新,就是我们所说的冻结操作,只修改最后的地方即可。
其他的代码都没有变化,运行之后发现结果会比上一次好很多。
VGG16完整代码如下:

import torch
import torchvision
from torchvision import datasets,transforms,models
import  os   #os包集成了一些对文件路径和目录操作的类
import matplotlib.pyplot as plt
import  time
from torch.autograd import  Variable

data_dir = "DogsVSCats"
data_transform = {x:transforms.Compose([transforms.Resize([64,64]),#统一将图片缩放至64*64
                                        transforms.ToTensor()])
                                        for x in ["train","valid"]}

image_datasets = {x:datasets.ImageFolder(root=os.path.join(data_dir,x),
                                         transform = data_transform[x])
                                         for x in ["train","valid"]}

dataloader = {x:torch.utils.data.DataLoader(dataset = image_datasets[x],
                                            batch_size = 16,
                                            shuffle = True)
                                            for x in ["train","valid"]}

X_example,y_example = next(iter(dataloader["train"]))

print(u"X_example个数{}".format(len(X_example)))
print(u"y_example个数{}".format(len(y_example)))

index_classes = image_datasets["train"].class_to_idx
print(index_classes)
example_clasees = image_datasets["train"].classes  #example_clasees 变量其实就是一个列表
print(example_clasees)

img = torchvision.utils.make_grid(X_example)
img = img.numpy().transpose([1,2,0])
print([example_clasees[i] for i in y_example])
plt.imshow(img)
plt.show()

# #Vgg自定义框架
# class Models(torch.nn.Module):
#     def __init__(self):
#         super(Models,self).__init__()
#         self.Conv = torch.nn.Sequential(
#             torch.nn.Conv2d(3,64,kernel_size=3,stride=1,padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(64,64,kernel_size=3,stride=1,padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2,stride=2),
#
#             torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2, stride=2),
#
#             torch.nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2, stride=2),
#
#             torch.nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2, stride=2),
#         )
#         self.Classes = torch.nn.Sequential(
#             torch.nn.Linear(4*4*512,1024),
#             torch.nn.ReLU(),
#             torch.nn.Dropout(p=0.5),
#             torch.nn.Linear(1024,1024),
#             torch.nn.ReLU(),
#             torch.nn.Dropout(p=0.5),
#             torch.nn.Linear(1024, 2),
#         )
#
#     def forward(self,input):
#         x = self.Conv(input)
#         x = x.view(-1,4*4*512)
#         x = self.Classes(x)
#         return x
#迁移Vgg16
model = models.vgg16(progress=True)  #迁移代码


#调整迁移过来的模型   原来的模型输出有1000个,我们只需要两个

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(model)
loss_f = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr = 0.00001)

epoch_n = 10
time_open = time.time()

for epoch in range(epoch_n):
    print("Epoch {}/{}".format(epoch, epoch_n - 1))
    print("-" * 10)

    for phase in ["train","valid"]:
        if phase == "train":
            print("Training.....")
            model.train(True)
        else:
            print("Validing....")
            model.train(False)

        running_loss = 0.0  # 损失的数值
        running_corrects = 0  # 预测的正确数目

        for batch,data in enumerate(dataloader[phase],1):
            X,y = data
            X,y = Variable(X),Variable(y)
            y_pred = model(X)

            _,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 += loss.item()  # 累计所有的损失值
            running_corrects += torch.sum(pred == y.data)  # 累计所有的正确次数

            if batch%500 == 0 and phase =="train":
               print("Batch{},Train Loss:{:.4f},Train ACC:{:.4f}".format(
                  batch,torch.true_divide(running_loss,batch),100*torch.true_divide(running_corrects,16*batch)
                ))
        epoch_loss = torch.true_divide(running_loss*16,len(image_datasets[phase]))
        epoch_acc = 100*torch.true_divide(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)

(2)迁移ResNet50
废话不多说,与之前的都一样,调用以及只需修改全连接层的输出部分,代码如下:

model = models.resnet50(pretrained=True)  #迁移代码
for parma in model.parameters():
    parma.requires_grad = False
model.fc = torch.nn.Linear(2048,2)

此处附上完整代码:

import torch
import torchvision
from torchvision import datasets,transforms,models
import  os   #os包集成了一些对文件路径和目录操作的类
import matplotlib.pyplot as plt
import  time
from torch.autograd import  Variable

data_dir = "DogsVSCats"
data_transform = {x:transforms.Compose([transforms.Resize([64,64]),#统一将图片缩放至64*64
                                        transforms.ToTensor()])
                                        for x in ["train","valid"]}

image_datasets = {x:datasets.ImageFolder(root=os.path.join(data_dir,x),
                                         transform = data_transform[x])
                                         for x in ["train","valid"]}

dataloader = {x:torch.utils.data.DataLoader(dataset = image_datasets[x],
                                            batch_size = 16,
                                            shuffle = True)
                                            for x in ["train","valid"]}

X_example,y_example = next(iter(dataloader["train"]))

print(u"X_example个数{}".format(len(X_example)))
print(u"y_example个数{}".format(len(y_example)))

index_classes = image_datasets["train"].class_to_idx
print(index_classes)
example_clasees = image_datasets["train"].classes  #example_clasees 变量其实就是一个列表
print(example_clasees)

img = torchvision.utils.make_grid(X_example)
img = img.numpy().transpose([1,2,0])
print([example_clasees[i] for i in y_example])
plt.imshow(img)
plt.show()

# #Vgg自定义框架
# class Models(torch.nn.Module):
#     def __init__(self):
#         super(Models,self).__init__()
#         self.Conv = torch.nn.Sequential(
#             torch.nn.Conv2d(3,64,kernel_size=3,stride=1,padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(64,64,kernel_size=3,stride=1,padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2,stride=2),
#
#             torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2, stride=2),
#
#             torch.nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2, stride=2),
#
#             torch.nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
#             torch.nn.ReLU(),
#             torch.nn.MaxPool2d(kernel_size=2, stride=2),
#         )
#         self.Classes = torch.nn.Sequential(
#             torch.nn.Linear(4*4*512,1024),
#             torch.nn.ReLU(),
#             torch.nn.Dropout(p=0.5),
#             torch.nn.Linear(1024,1024),
#             torch.nn.ReLU(),
#             torch.nn.Dropout(p=0.5),
#             torch.nn.Linear(1024, 2),
#         )
#
#     def forward(self,input):
#         x = self.Conv(input)
#         x = x.view(-1,4*4*512)
#         x = self.Classes(x)
#         return x
#迁移Resnet50
model = models.resnet50(pretrained=True)  #迁移代码


#调整迁移过来的模型   原来的模型输出有1000个,我们只需要两个
for parma in model.parameters():
    parma.requires_grad = False
model.fc = torch.nn.Linear(2048,2)
print(model)

loss_f = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr = 0.00001)

epoch_n = 10
time_open = time.time()

for epoch in range(epoch_n):
    print("Epoch {}/{}".format(epoch, epoch_n - 1))
    print("-" * 10)

    for phase in ["train","valid"]:
        if phase == "train":
            print("Training.....")
            model.train(True)
        else:
            print("Validing....")
            model.train(False)

        running_loss = 0.0  # 损失的数值
        running_corrects = 0  # 预测的正确数目

        for batch,data in enumerate(dataloader[phase],1):
            X,y = data
            X,y = Variable(X),Variable(y)
            y_pred = model(X)

            _,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 += loss.item()  # 累计所有的损失值
            running_corrects += torch.sum(pred == y.data)  # 累计所有的正确次数

            if batch%500 == 0 and phase =="train":
               print("Batch{},Train Loss:{:.4f},Train ACC:{:.4f}".format(
                  batch,torch.true_divide(running_loss,batch),100*torch.true_divide(running_corrects,16*batch)
                ))
        epoch_loss = torch.true_divide(running_loss*16,len(image_datasets[phase]))
        epoch_acc = 100*torch.true_divide(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)

笔记记的不好,尽情谅解,代码参考的书籍《深度学习之Pytorch实战计算机视觉》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值