迁移学习篇之如何迁移经典CNN网络-附迁移学习Alexnet,VGG,Googlenet,Resnet详细代码注释和方法-pytorch

简介: 迁移学习篇之如何迁移经典CNN网络-附迁移学习Alexnet,VGG,Googlenet,Resnet详细代码注释和方法-pytorch

鸽了好久的迁移学习篇学习终于打算更新,这次我们来学习一个机器学习中经典常用的简单快速提高网络指标的trick,迁移学习,迁移学习本身是机器学习中的一个trick,但是近些年在深度学习中应用广泛。之前我在学习迁移学习的时候想做到随便迁移任何一个网络但是我又看不太懂CNN的代码,然后就很懵,这篇博客的目的在于让大家只需要简单修改代码即可实现各种经典CNN网络的迁移。当然迁移学习是一门很大的学科,我们这里只介绍微调的方法。


一般来说不管针对任何数据集,使用迁移学习的方法一定是比不使用迁移学习要效果好的,记住我这里说的是


一定,一定,一定!!!重要的事情说三遍。


好的,废话少说,我们来简单介绍一下迁移学习的概念,迁移学习的思想可以理解成为,我们人类的学习,简单来说如果一个人需要学习python编程语言,但是他从来没有学过任何编程语言,这样他重新开始学编程语言就会学的很慢,但是如果他之前就学过C语言,或者C++,亦或者matlab的脚本语言,那么学python的时候就会很快,对,没错,我们基于已有的知识去重新学习新知识的过程便是迁移学习。


不论是深度学习模型还是各种神经网络,我们都可以理解成人类的大脑,大脑如果最开始一片空白(即模型还未开始训练,没有任何信息),然后开始学习一个知识(识别一个简单的目标)会学的非常慢,因为我们都知道从0开始学习是非常慢的,但是如果这个人已经学过数学,比如说高等数学,那么我们再开始学习线性代数,概率论,我们学习的速度一定是要快于什么都没学过的人的(假设双方智力相等),而且我们也会学的比没学过的人好。


对,如果我们的模型在训练之前,不是新的模型,是已经训练过可以识别其他对象的模型,那么我们在这个的基础上再次训练这个模型识别一个新对象的时候我们也许简单跑几个epoch就能达到很高的识别率。


好的,到这里我想我们经对迁移学习的概念有所了解,所谓迁移学习,就是我们在已经学会旧事物的基础上去学习类似的新事物,这样会让我们学的更快更好。


事实上这也是为什么我们经常将迁移学习用在数据量较少的数据上,因为我们完全可以将模型在数据量较大的数据上进行集中训练,训练出很好的效果,对于我们目标数据集量很少的情况,我们只需要迁移学习一下,很少的数据就能达到很好的效果。


说到这里,我们就需要介绍一下Imagenet数据集了(详细的自行百度),身为最庞大的开源数据集之一,他包含1000类数据,这也是没什么我们从他上面下载的预训练模型的结构的输出都是1000的原因。


              image.png


好,到这里我们又提出了预训练模型的概念,所谓预训练模型是个比较专业的叫法,其实说白了就是我们提到的已经训练过的模型。但是面临一个问题,每当我们需要训练模型的时候,需要采用迁移学习方法的时候我们需要去哪里寻找好的预训练模型呢?


这个时候Imagenet数据集的重要性已经体现了出来,按照我们经常使用的TensorFlow和pytorch来说,这些深度学习框架里面已经在Imagenet数据集上训练好了各种常见的CNN模型的预训练模型,我们只需要在代码上稍作修改,就可以在训练的时候下载相应的预训练模型,并且在他的最后再加一层全连接层,全连接层的输出改成我们数据集的种类,即可得到我们想要的结果。


例如我们常见的Resnet模型的迁移学习,


image.png


这就是Resnet预训练模型的下载过程


下面以alexnet为例:预训练模型下载代码

alexnet1 = torchvision.models.alexnet(pretrained=True) #下载预训练模型,pretrained=True则是下载预训练模型,如果下载好了就设置为False
    #这里是下载的alexnet预训练模型,你想下载那个,就把这个alexnet修改成相应模型的名字即可
    num_calss = 5  #数据种类,你有几种数据,就设置为几
    alexnet1.add_module("linear", nn.Linear(1000, num_calss)) #我们一般需要在模型的最后添加一个全连接层,然后这里的

下面附上完整的基于迁移学习的alexnet,VGG,Googlenet,Resnet代码:

import torch
import torchvision
import torchvision.models
from matplotlib import pyplot as plt
from tqdm import tqdm
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
data_transform = {
    "train": transforms.Compose([transforms.RandomResizedCrop(120),
                                 transforms.RandomHorizontalFlip(),
                                 transforms.ToTensor(),
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),
    "val": transforms.Compose([transforms.Resize((120, 120)),  # cannot 224, must (224, 224)
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
def main():
    train_data = torchvision.datasets.ImageFolder(root = "./data/train" ,   transform = data_transform["train"])
    #导入自己的数据,自己的数据放在跟代码相同的文件夹下新建一个data文件夹,data文件夹里的新建一个train文件夹用于放置训练集的图片。同理新建一个val文件夹用于放置测试集的图片。
    traindata = DataLoader(dataset= train_data , batch_size= 32 , shuffle= True , num_workers=0 ) # 将训练数据以每次32张图片的形式抽出进行训练
    test_data = torchvision.datasets.ImageFolder(root = "./data/val" , transform = data_transform["val"])
    train_size = len(train_data) # 训练集的长度
    test_size = len(test_data) # 测试集的长度
    print(train_size)  # 输出训练集长度看一下,相当于看看有几张图片
    print(test_size)  # 输出测试集长度看一下,相当于看看有几张图片
    testdata = DataLoader(dataset = test_data , batch_size= 32 , shuffle= True , num_workers=0 )# 将训练数据以每次32张图片的形式抽出进行测试
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("using {} device.".format(device))
    # class alexnet(nn.Module):
    #     def __init__(self):
    #         super(alexnet , self).__init__()
    #         self.model = nn.Sequential(
    #
    #             nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),  # input[3, 120, 120]  output[48, 55, 55]
    #
    #             nn.ReLU(inplace=True),
    #             nn.MaxPool2d(kernel_size=3, stride=2),  # output[48, 27, 27]
    #             nn.Conv2d(48, 128, kernel_size=5, padding=2),  # output[128, 27, 27]
    #
    #             nn.ReLU(inplace=True),
    #             nn.MaxPool2d(kernel_size=3, stride=2),  # output[128, 13, 13]
    #             nn.Conv2d(128, 192, kernel_size=3, padding=1),  # output[192, 13, 13]
    #
    #             nn.ReLU(inplace=True),
    #             nn.Conv2d(192, 192, kernel_size=3, padding=1),  # output[192, 13, 13]
    #
    #             nn.ReLU(inplace=True),
    #             nn.Conv2d(192, 128, kernel_size=3, padding=1),  # output[128, 13, 13]
    #
    #             nn.ReLU(inplace=True),
    #             nn.MaxPool2d(kernel_size=3, stride=2),  # output[128, 6, 6]
    #             nn.Flatten(),
    #             nn.Dropout(p=0.5),
    #             nn.Linear(512, 2048),
    #             nn.ReLU(inplace=True),
    #             nn.Dropout(p=0.5),
    #             nn.Linear(2048, 1024),
    #             nn.ReLU(inplace=True),
    #             nn.Linear(1024, 7),
    #
    #         )
    #     def forward(self , x):
    #         x = self.model(x)
    #         return x
    alexnet1 = torchvision.models.alexnet(pretrained=True) #下载预训练模型,pretrained=True则是下载预训练模型,如果下载好了就设置为False
    #这里是下载的alexnet预训练模型,你想下载那个,就把这个alexnet修改成相应模型的名字即可
    num_calss = 5  #数据种类,你有几种数据,就设置为几
    alexnet1.add_module("linear", nn.Linear(1000, num_calss)) #我们一般需要在模型的最后添加一个全连接层,然后这里的
    print(alexnet1) #打印模型结构,看看模型的构成
    alexnet1.to(device)
    test1 = torch.ones(64, 3, 120, 120)  #输出一个测试数据看看模型的输出
    test1 = alexnet1(test1.to(device))
    print(test1.shape)
    epoch = 15  # 迭代次数即训练次数
    learning = 0.001  # 学习率
    optimizer = torch.optim.Adam(alexnet1.parameters(), lr=learning)  # 使用Adam优化器-写论文的话可以具体查一下这个优化器的原理
    loss = nn.CrossEntropyLoss()  # 损失计算方式,交叉熵损失函数
    train_loss_all = []  # 存放训练集损失的数组
    train_accur_all = []  # 存放训练集准确率的数组
    test_loss_all = []  # 存放测试集损失的数组
    test_accur_all = []  # 存放测试集准确率的数组
    for i in range(epoch):  # 开始迭代
        train_loss = 0  # 训练集的损失初始设为0
        train_num = 0.0  #
        train_accuracy = 0.0  # 训练集的准确率初始设为0
        alexnet1.train()  # 将模型设置成 训练模式
        train_bar = tqdm(traindata)  # 用于进度条显示,没啥实际用处
        for step, data in enumerate(train_bar):  # 开始迭代跑, enumerate这个函数不懂可以查查,将训练集分为 data是序号,data是数据
            img, target = data  # 将data 分位 img图片,target标签
            optimizer.zero_grad()  # 清空历史梯度
            outputs = alexnet1(img.to(device))  # 将图片打入网络进行训练,outputs是输出的结果
            loss1 = loss(outputs, target.to(device))  # 计算神经网络输出的结果outputs与图片真实标签target的差别-这就是我们通常情况下称为的损失
            outputs = torch.argmax(outputs, 1)  # 会输出10个值,最大的值就是我们预测的结果 求最大值
            loss1.backward()  # 神经网络反向传播
            optimizer.step()  # 梯度优化 用上面的abam优化
            train_loss += loss1.item() # 将所有损失的绝对值加起来
            accuracy = torch.sum(outputs == target.to(device))  # outputs == target的 即使预测正确的,统计预测正确的个数,从而计算准确率
            train_accuracy = train_accuracy + accuracy  # 求训练集的准确率
            train_num += img.size(0)  #
        print("epoch:{} , train-Loss:{} , train-accuracy:{}".format(i + 1, train_loss / train_num,  # 输出训练情况
                                                                    train_accuracy / train_num))
        train_loss_all.append(train_loss / train_num)  # 将训练的损失放到一个列表里 方便后续画图
        train_accur_all.append(train_accuracy.double().item() / train_num)  # 训练集的准确率
        test_loss = 0  # 同上 测试损失
        test_accuracy = 0.0  # 测试准确率
        test_num = 0
        alexnet1.eval()  # 将模型调整为测试模型
        with torch.no_grad():  # 清空历史梯度,进行测试  与训练最大的区别是测试过程中取消了反向传播
            test_bar = tqdm(testdata)
            for data in test_bar:
                img, target = data
                outputs = alexnet1(img.to(device))
                loss2 = loss(outputs, target.to(device))
                outputs = torch.argmax(outputs, 1)
                test_loss = test_loss + loss2.item()
                accuracy = torch.sum(outputs == target.to(device))
                test_accuracy = test_accuracy + accuracy
                test_num += img.size(0)
        print("test-Loss:{} , test-accuracy:{}".format(test_loss / test_num, test_accuracy / test_num))
        test_loss_all.append(test_loss / test_num)
        test_accur_all.append(test_accuracy.double().item() / test_num)
    # 下面的是画图过程,将上述存放的列表  画出来即可
    plt.figure(figsize=(12, 4))
    plt.subplot(1, 2, 1)
    plt.plot(range(epoch), train_loss_all,
             "ro-", label="Train loss")
    plt.plot(range(epoch), test_loss_all,
             "bs-", label="test loss")
    plt.legend()
    plt.xlabel("epoch")
    plt.ylabel("Loss")
    plt.subplot(1, 2, 2)
    plt.plot(range(epoch), train_accur_all,
             "ro-", label="Train accur")
    plt.plot(range(epoch), test_accur_all,
             "bs-", label="test accur")
    plt.xlabel("epoch")
    plt.ylabel("acc")
    plt.legend()
    plt.show()
    torch.save(alexnet1, "alexnet-transfer-learning.pth")
    print("模型已保存")
if __name__ == '__main__':
    main()

完整的基于迁移学习的VGG代码:

import torch
import torchvision
import torchvision.models
from matplotlib import pyplot as plt
from tqdm import tqdm
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
data_transform = {
    "train": transforms.Compose([transforms.RandomResizedCrop(120),
                                 transforms.RandomHorizontalFlip(),
                                 transforms.ToTensor(),
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),
    "val": transforms.Compose([transforms.Resize((120, 120)),  # cannot 224, must (224, 224)
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
def main():
    train_data = torchvision.datasets.ImageFolder(root = "./data/train" ,   transform = data_transform["train"])
    #导入自己的数据,自己的数据放在跟代码相同的文件夹下新建一个data文件夹,data文件夹里的新建一个train文件夹用于放置训练集的图片。同理新建一个val文件夹用于放置测试集的图片。
    traindata = DataLoader(dataset= train_data , batch_size= 32 , shuffle= True , num_workers=0 ) # 将训练数据以每次32张图片的形式抽出进行训练
    test_data = torchvision.datasets.ImageFolder(root = "./data/val" , transform = data_transform["val"])
    train_size = len(train_data) # 训练集的长度
    test_size = len(test_data) # 测试集的长度
    print(train_size)  # 输出训练集长度看一下,相当于看看有几张图片
    print(test_size)  # 输出测试集长度看一下,相当于看看有几张图片
    testdata = DataLoader(dataset = test_data , batch_size= 32 , shuffle= True , num_workers=0 )# 将训练数据以每次32张图片的形式抽出进行测试
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("using {} device.".format(device))
    VGG = torchvision.models.vgg16(pretrained=True) #下载预训练模型,pretrained=True则是下载预训练模型,如果下载好了就设置为False
    #这里是下载的alexnet预训练模型,你想下载那个,就把这个alexnet修改成相应模型的名字即可
    num_calss = 5  #数据种类,你有几种数据,就设置为几
    VGG.add_module("linear", nn.Linear(1000, num_calss)) #我们一般需要在模型的最后添加一个全连接层,然后这里的
    print(VGG) #打印模型结构,看看模型的构成
    VGG.to(device)
    test1 = torch.ones(64, 3, 120, 120)  #输出一个测试数据看看模型的输出
    test1 = VGG(test1.to(device))
    print(test1.shape)
    epoch = 15  # 迭代次数即训练次数
    learning = 0.0001  # 学习率
    optimizer = torch.optim.Adam(VGG.parameters(), lr=learning)  # 使用Adam优化器-写论文的话可以具体查一下这个优化器的原理
    loss = nn.CrossEntropyLoss()  # 损失计算方式,交叉熵损失函数
    train_loss_all = []  # 存放训练集损失的数组
    train_accur_all = []  # 存放训练集准确率的数组
    test_loss_all = []  # 存放测试集损失的数组
    test_accur_all = []  # 存放测试集准确率的数组
    for i in range(epoch):  # 开始迭代
        train_loss = 0  # 训练集的损失初始设为0
        train_num = 0.0  #
        train_accuracy = 0.0  # 训练集的准确率初始设为0
        VGG.train()  # 将模型设置成 训练模式
        train_bar = tqdm(traindata)  # 用于进度条显示,没啥实际用处
        for step, data in enumerate(train_bar):  # 开始迭代跑, enumerate这个函数不懂可以查查,将训练集分为 data是序号,data是数据
            img, target = data  # 将data 分位 img图片,target标签
            optimizer.zero_grad()  # 清空历史梯度
            outputs = VGG(img.to(device))  # 将图片打入网络进行训练,outputs是输出的结果
            loss1 = loss(outputs, target.to(device))  # 计算神经网络输出的结果outputs与图片真实标签target的差别-这就是我们通常情况下称为的损失
            outputs = torch.argmax(outputs, 1)  # 会输出10个值,最大的值就是我们预测的结果 求最大值
            loss1.backward()  # 神经网络反向传播
            optimizer.step()  # 梯度优化 用上面的abam优化
            train_loss += loss1.item() # 将所有损失的绝对值加起来
            accuracy = torch.sum(outputs == target.to(device))  # outputs == target的 即使预测正确的,统计预测正确的个数,从而计算准确率
            train_accuracy = train_accuracy + accuracy  # 求训练集的准确率
            train_num += img.size(0)  #
        print("epoch:{} , train-Loss:{} , train-accuracy:{}".format(i + 1, train_loss / train_num,  # 输出训练情况
                                                                    train_accuracy / train_num))
        train_loss_all.append(train_loss / train_num)  # 将训练的损失放到一个列表里 方便后续画图
        train_accur_all.append(train_accuracy.double().item() / train_num)  # 训练集的准确率
        test_loss = 0  # 同上 测试损失
        test_accuracy = 0.0  # 测试准确率
        test_num = 0
        VGG.eval()  # 将模型调整为测试模型
        with torch.no_grad():  # 清空历史梯度,进行测试  与训练最大的区别是测试过程中取消了反向传播
            test_bar = tqdm(testdata)
            for data in test_bar:
                img, target = data
                outputs = VGG(img.to(device))
                loss2 = loss(outputs, target.to(device))
                outputs = torch.argmax(outputs, 1)
                test_loss = test_loss + loss2.item()
                accuracy = torch.sum(outputs == target.to(device))
                test_accuracy = test_accuracy + accuracy
                test_num += img.size(0)
        print("test-Loss:{} , test-accuracy:{}".format(test_loss / test_num, test_accuracy / test_num))
        test_loss_all.append(test_loss / test_num)
        test_accur_all.append(test_accuracy.double().item() / test_num)
    # 下面的是画图过程,将上述存放的列表  画出来即可
    plt.figure(figsize=(12, 4))
    plt.subplot(1, 2, 1)
    plt.plot(range(epoch), train_loss_all,
             "ro-", label="Train loss")
    plt.plot(range(epoch), test_loss_all,
             "bs-", label="test loss")
    plt.legend()
    plt.xlabel("epoch")
    plt.ylabel("Loss")
    plt.subplot(1, 2, 2)
    plt.plot(range(epoch), train_accur_all,
             "ro-", label="Train accur")
    plt.plot(range(epoch), test_accur_all,
             "bs-", label="test accur")
    plt.xlabel("epoch")
    plt.ylabel("acc")
    plt.legend()
    plt.show()
    torch.save(VGG, "VGG-transfer-learning.pth")
    print("模型已保存")
if __name__ == '__main__':
    main()

完整的基于迁移学习的Googlenet代码:

import torch
import torchvision
import torchvision.models
from matplotlib import pyplot as plt
from tqdm import tqdm
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
data_transform = {
    "train": transforms.Compose([transforms.RandomResizedCrop(120),
                                 transforms.RandomHorizontalFlip(),
                                 transforms.ToTensor(),
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),
    "val": transforms.Compose([transforms.Resize((120, 120)),  # cannot 224, must (224, 224)
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
def main():
    train_data = torchvision.datasets.ImageFolder(root = "./data/train" ,   transform = data_transform["train"])
    #导入自己的数据,自己的数据放在跟代码相同的文件夹下新建一个data文件夹,data文件夹里的新建一个train文件夹用于放置训练集的图片。同理新建一个val文件夹用于放置测试集的图片。
    traindata = DataLoader(dataset= train_data , batch_size= 32 , shuffle= True , num_workers=0 ) # 将训练数据以每次32张图片的形式抽出进行训练
    test_data = torchvision.datasets.ImageFolder(root = "./data/val" , transform = data_transform["val"])
    train_size = len(train_data) # 训练集的长度
    test_size = len(test_data) # 测试集的长度
    print(train_size)  # 输出训练集长度看一下,相当于看看有几张图片
    print(test_size)  # 输出测试集长度看一下,相当于看看有几张图片
    testdata = DataLoader(dataset = test_data , batch_size= 32 , shuffle= True , num_workers=0 )# 将训练数据以每次32张图片的形式抽出进行测试
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("using {} device.".format(device))
    Googlenet = torchvision.models.googlenet(pretrained=True) #下载预训练模型,pretrained=True则是下载预训练模型,如果下载好了就设置为False
    #这里是下载的alexnet预训练模型,你想下载那个,就把这个alexnet修改成相应模型的名字即可
    num_calss = 5  #数据种类,你有几种数据,就设置为几
    Googlenet.add_module("linear", nn.Linear(1000, num_calss)) #我们一般需要在模型的最后添加一个全连接层,然后这里的
    print(Googlenet) #打印模型结构,看看模型的构成
    Googlenet.to(device)
    test1 = torch.ones(64, 3, 120, 120)  #输出一个测试数据看看模型的输出
    test1 = Googlenet(test1.to(device))
    print(test1.shape)
    epoch = 15  # 迭代次数即训练次数
    learning = 0.0001  # 学习率
    optimizer = torch.optim.Adam(Googlenet.parameters(), lr=learning)  # 使用Adam优化器-写论文的话可以具体查一下这个优化器的原理
    loss = nn.CrossEntropyLoss()  # 损失计算方式,交叉熵损失函数
    train_loss_all = []  # 存放训练集损失的数组
    train_accur_all = []  # 存放训练集准确率的数组
    test_loss_all = []  # 存放测试集损失的数组
    test_accur_all = []  # 存放测试集准确率的数组
    for i in range(epoch):  # 开始迭代
        train_loss = 0  # 训练集的损失初始设为0
        train_num = 0.0  #
        train_accuracy = 0.0  # 训练集的准确率初始设为0
        Googlenet.train()  # 将模型设置成 训练模式
        train_bar = tqdm(traindata)  # 用于进度条显示,没啥实际用处
        for step, data in enumerate(train_bar):  # 开始迭代跑, enumerate这个函数不懂可以查查,将训练集分为 data是序号,data是数据
            img, target = data  # 将data 分位 img图片,target标签
            optimizer.zero_grad()  # 清空历史梯度
            outputs = Googlenet(img.to(device))  # 将图片打入网络进行训练,outputs是输出的结果
            loss1 = loss(outputs, target.to(device))  # 计算神经网络输出的结果outputs与图片真实标签target的差别-这就是我们通常情况下称为的损失
            outputs = torch.argmax(outputs, 1)  # 会输出10个值,最大的值就是我们预测的结果 求最大值
            loss1.backward()  # 神经网络反向传播
            optimizer.step()  # 梯度优化 用上面的abam优化
            train_loss += loss1.item() # 将所有损失的绝对值加起来
            accuracy = torch.sum(outputs == target.to(device))  # outputs == target的 即使预测正确的,统计预测正确的个数,从而计算准确率
            train_accuracy = train_accuracy + accuracy  # 求训练集的准确率
            train_num += img.size(0)  #
        print("epoch:{} , train-Loss:{} , train-accuracy:{}".format(i + 1, train_loss / train_num,  # 输出训练情况
                                                                    train_accuracy / train_num))
        train_loss_all.append(train_loss / train_num)  # 将训练的损失放到一个列表里 方便后续画图
        train_accur_all.append(train_accuracy.double().item() / train_num)  # 训练集的准确率
        test_loss = 0  # 同上 测试损失
        test_accuracy = 0.0  # 测试准确率
        test_num = 0
        Googlenet.eval()  # 将模型调整为测试模型
        with torch.no_grad():  # 清空历史梯度,进行测试  与训练最大的区别是测试过程中取消了反向传播
            test_bar = tqdm(testdata)
            for data in test_bar:
                img, target = data
                outputs = Googlenet(img.to(device))
                loss2 = loss(outputs, target.to(device))
                outputs = torch.argmax(outputs, 1)
                test_loss = test_loss + loss2.item()
                accuracy = torch.sum(outputs == target.to(device))
                test_accuracy = test_accuracy + accuracy
                test_num += img.size(0)
        print("test-Loss:{} , test-accuracy:{}".format(test_loss / test_num, test_accuracy / test_num))
        test_loss_all.append(test_loss / test_num)
        test_accur_all.append(test_accuracy.double().item() / test_num)
    # 下面的是画图过程,将上述存放的列表  画出来即可
    plt.figure(figsize=(12, 4))
    plt.subplot(1, 2, 1)
    plt.plot(range(epoch), train_loss_all,
             "ro-", label="Train loss")
    plt.plot(range(epoch), test_loss_all,
             "bs-", label="test loss")
    plt.legend()
    plt.xlabel("epoch")
    plt.ylabel("Loss")
    plt.subplot(1, 2, 2)
    plt.plot(range(epoch), train_accur_all,
             "ro-", label="Train accur")
    plt.plot(range(epoch), test_accur_all,
             "bs-", label="test accur")
    plt.xlabel("epoch")
    plt.ylabel("acc")
    plt.legend()
    plt.show()
    torch.save(Googlenet, "Googlenet-transfer-learning.pth")
    print("模型已保存")
if __name__ == '__main__':
    main()


完整的基于迁移学习的Resnet代码:

import torch
import torchvision
import torchvision.models
from matplotlib import pyplot as plt
from tqdm import tqdm
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
data_transform = {
    "train": transforms.Compose([transforms.RandomResizedCrop(120),
                                 transforms.RandomHorizontalFlip(),
                                 transforms.ToTensor(),
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),
    "val": transforms.Compose([transforms.Resize((120, 120)),  # cannot 224, must (224, 224)
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
def main():
    train_data = torchvision.datasets.ImageFolder(root = "./data/train" ,   transform = data_transform["train"])
    #导入自己的数据,自己的数据放在跟代码相同的文件夹下新建一个data文件夹,data文件夹里的新建一个train文件夹用于放置训练集的图片。同理新建一个val文件夹用于放置测试集的图片。
    traindata = DataLoader(dataset= train_data , batch_size= 32 , shuffle= True , num_workers=0 ) # 将训练数据以每次32张图片的形式抽出进行训练
    test_data = torchvision.datasets.ImageFolder(root = "./data/val" , transform = data_transform["val"])
    train_size = len(train_data) # 训练集的长度
    test_size = len(test_data) # 测试集的长度
    print(train_size)  # 输出训练集长度看一下,相当于看看有几张图片
    print(test_size)  # 输出测试集长度看一下,相当于看看有几张图片
    testdata = DataLoader(dataset = test_data , batch_size= 32 , shuffle= True , num_workers=0 )# 将训练数据以每次32张图片的形式抽出进行测试
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print("using {} device.".format(device))
    Resnet = torchvision.models.resnet18(pretrained=True) #下载预训练模型,pretrained=True则是下载预训练模型,如果下载好了就设置为False
    #这里是下载的alexnet预训练模型,你想下载那个,就把这个alexnet修改成相应模型的名字即可
    num_calss = 5  #数据种类,你有几种数据,就设置为几
    Resnet.add_module("linear", nn.Linear(1000, num_calss)) #我们一般需要在模型的最后添加一个全连接层,然后这里的
    print(Resnet) #打印模型结构,看看模型的构成
    Resnet.to(device)
    test1 = torch.ones(64, 3, 120, 120)  #输出一个测试数据看看模型的输出
    test1 = Resnet(test1.to(device))
    print(test1.shape)
    epoch = 15  # 迭代次数即训练次数
    learning = 0.0001  # 学习率
    optimizer = torch.optim.Adam(Resnet.parameters(), lr=learning)  # 使用Adam优化器-写论文的话可以具体查一下这个优化器的原理
    loss = nn.CrossEntropyLoss()  # 损失计算方式,交叉熵损失函数
    train_loss_all = []  # 存放训练集损失的数组
    train_accur_all = []  # 存放训练集准确率的数组
    test_loss_all = []  # 存放测试集损失的数组
    test_accur_all = []  # 存放测试集准确率的数组
    for i in range(epoch):  # 开始迭代
        train_loss = 0  # 训练集的损失初始设为0
        train_num = 0.0  #
        train_accuracy = 0.0  # 训练集的准确率初始设为0
        Resnet.train()  # 将模型设置成 训练模式
        train_bar = tqdm(traindata)  # 用于进度条显示,没啥实际用处
        for step, data in enumerate(train_bar):  # 开始迭代跑, enumerate这个函数不懂可以查查,将训练集分为 data是序号,data是数据
            img, target = data  # 将data 分位 img图片,target标签
            optimizer.zero_grad()  # 清空历史梯度
            outputs = Resnet(img.to(device))  # 将图片打入网络进行训练,outputs是输出的结果
            loss1 = loss(outputs, target.to(device))  # 计算神经网络输出的结果outputs与图片真实标签target的差别-这就是我们通常情况下称为的损失
            outputs = torch.argmax(outputs, 1)  # 会输出10个值,最大的值就是我们预测的结果 求最大值
            loss1.backward()  # 神经网络反向传播
            optimizer.step()  # 梯度优化 用上面的abam优化
            train_loss += loss1.item() # 将所有损失的绝对值加起来
            accuracy = torch.sum(outputs == target.to(device))  # outputs == target的 即使预测正确的,统计预测正确的个数,从而计算准确率
            train_accuracy = train_accuracy + accuracy  # 求训练集的准确率
            train_num += img.size(0)  #
        print("epoch:{} , train-Loss:{} , train-accuracy:{}".format(i + 1, train_loss / train_num,  # 输出训练情况
                                                                    train_accuracy / train_num))
        train_loss_all.append(train_loss / train_num)  # 将训练的损失放到一个列表里 方便后续画图
        train_accur_all.append(train_accuracy.double().item() / train_num)  # 训练集的准确率
        test_loss = 0  # 同上 测试损失
        test_accuracy = 0.0  # 测试准确率
        test_num = 0
        Resnet.eval()  # 将模型调整为测试模型
        with torch.no_grad():  # 清空历史梯度,进行测试  与训练最大的区别是测试过程中取消了反向传播
            test_bar = tqdm(testdata)
            for data in test_bar:
                img, target = data
                outputs = Resnet(img.to(device))
                loss2 = loss(outputs, target.to(device))
                outputs = torch.argmax(outputs, 1)
                test_loss = test_loss + loss2.item()
                accuracy = torch.sum(outputs == target.to(device))
                test_accuracy = test_accuracy + accuracy
                test_num += img.size(0)
        print("test-Loss:{} , test-accuracy:{}".format(test_loss / test_num, test_accuracy / test_num))
        test_loss_all.append(test_loss / test_num)
        test_accur_all.append(test_accuracy.double().item() / test_num)
    # 下面的是画图过程,将上述存放的列表  画出来即可
    plt.figure(figsize=(12, 4))
    plt.subplot(1, 2, 1)
    plt.plot(range(epoch), train_loss_all,
             "ro-", label="Train loss")
    plt.plot(range(epoch), test_loss_all,
             "bs-", label="test loss")
    plt.legend()
    plt.xlabel("epoch")
    plt.ylabel("Loss")
    plt.subplot(1, 2, 2)
    plt.plot(range(epoch), train_accur_all,
             "ro-", label="Train accur")
    plt.plot(range(epoch), test_accur_all,
             "bs-", label="test accur")
    plt.xlabel("epoch")
    plt.ylabel("acc")
    plt.legend()
    plt.show()
    torch.save(Resnet, "Resnet-transfer-learning.pth")
    print("模型已保存")
if __name__ == '__main__':
    main()
相关文章
|
5天前
|
机器学习/深度学习 数据采集 算法
基于GWO灰狼优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB2022a,展示了时间序列预测算法的运行效果(无水印)。核心程序包含详细中文注释和操作视频。算法采用CNN-GRU-SAM网络,结合灰狼优化(GWO),通过卷积层提取局部特征、GRU处理长期依赖、自注意力机制捕捉全局特征,最终实现复杂非线性时间序列的高效预测。
|
1月前
|
机器学习/深度学习 算法 计算机视觉
基于CNN卷积神经网络的金融数据预测matlab仿真,对比BP,RBF,LSTM
本项目基于MATLAB2022A,利用CNN卷积神经网络对金融数据进行预测,并与BP、RBF和LSTM网络对比。核心程序通过处理历史价格数据,训练并测试各模型,展示预测结果及误差分析。CNN通过卷积层捕捉局部特征,BP网络学习非线性映射,RBF网络进行局部逼近,LSTM解决长序列预测中的梯度问题。实验结果表明各模型在金融数据预测中的表现差异。
125 10
|
1月前
|
机器学习/深度学习 数据采集 算法
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB2022a实现时间序列预测,采用CNN-GRU-SAM网络结构。卷积层提取局部特征,GRU层处理长期依赖,自注意力机制捕捉全局特征。完整代码含中文注释和操作视频,运行效果无水印展示。算法通过数据归一化、种群初始化、适应度计算、个体更新等步骤优化网络参数,最终输出预测结果。适用于金融市场、气象预报等领域。
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
|
2月前
|
机器学习/深度学习 数据采集 算法
基于PSO粒子群优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目展示了基于PSO优化的CNN-GRU-SAM网络在时间序列预测中的应用。算法通过卷积层、GRU层、自注意力机制层提取特征,结合粒子群优化提升预测准确性。完整程序运行效果无水印,提供Matlab2022a版本代码,含详细中文注释和操作视频。适用于金融市场、气象预报等领域,有效处理非线性数据,提高预测稳定性和效率。
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
深入理解深度学习中的卷积神经网络(CNN)##
在当今的人工智能领域,深度学习已成为推动技术革新的核心力量之一。其中,卷积神经网络(CNN)作为深度学习的一个重要分支,因其在图像和视频处理方面的卓越性能而备受关注。本文旨在深入探讨CNN的基本原理、结构及其在实际应用中的表现,为读者提供一个全面了解CNN的窗口。 ##
|
2月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于贝叶斯优化CNN-GRU网络的数据分类识别算法matlab仿真
本项目展示了使用MATLAB2022a实现的贝叶斯优化、CNN和GRU算法优化效果。优化前后对比显著,完整代码附带中文注释及操作视频。贝叶斯优化适用于黑盒函数,CNN用于时间序列特征提取,GRU改进了RNN的长序列处理能力。
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
深入理解深度学习中的卷积神经网络(CNN)
深入理解深度学习中的卷积神经网络(CNN)
|
2月前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
86 17
|
2月前
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。
|
2月前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字化时代,网络安全和信息安全已成为我们日常生活中不可或缺的一部分。本文将深入探讨网络安全漏洞、加密技术和安全意识等方面的问题,并提供一些实用的建议和解决方案。我们将通过分析网络攻击的常见形式,揭示网络安全的脆弱性,并介绍如何利用加密技术来保护数据。此外,我们还将强调提高个人和企业的安全意识的重要性,以应对日益复杂的网络威胁。无论你是普通用户还是IT专业人士,这篇文章都将为你提供有价值的见解和指导。

热门文章

最新文章

推荐镜像

更多