精华内容
下载资源
问答
  • 2017-08-29 13:28:04

    完成数据的预处理,接下进入分类学习中的重点–模型训练。在前面我们得到了一批数据,现在我们需要从中提取出一部分数据作为我们训练的数据,当然我们也可以把全部的数据作为我们训练的数据,但是如果我们把全部的数据都拿来作为训练就没有数据来测试我们模型的性能了,因为训练数据和测试数据不能重叠,不然就是作弊了,这样性能测试结果并不能真实的反应模型的性能了。同时在提取训练数据过程中,按照随机的原则,不然也是作弊的行为。一般我们从数据中提取75%作为训练数据,提取25%作为测试数据。

    # 使用sklearn.cross_valiation里的train_test_split模块用于分割数据。
    from sklearn.cross_validation import train_test_split
    
    # 随机采样25%的数据用于测试,剩下的75%用于构建训练集合。
    X_train, X_test, y_train, y_test = train_test_split(data[column_names[1:10]], 
                                                        data[column_names[10]], 
                                                        test_size=0.25, 
                                                        random_state=33)
    #column_names[1:10]]所要划分的样本的特征集
    #data[column_names[10]]所要划分的样本的结果
    #test_size测试样本的占比,如果是整数的话就是测试样本的数量
    #random_state随机数的种子

    在我们得到的数据中,第0列是序号,第1到第9列是样本的特征,第10列是样本的结果。
    得到了训练数据,接下来我们就需要建立并训练模型了。在此之前需要一个小小的数据调整–标准化数据,即将数据收缩到同一个范围内,比如说一丈和两米的比较,在计算机中我们输入的是1和2并没有带单位,这样对计算机来说肯定是2更长,但是我们知道是一丈更长,所以我们进行比较时要先将一丈标准化为3.33米,又或者将2米标准化为0.6丈,这个是凭个人习惯。

    # 从sklearn.preprocessing里导入StandardScaler。
    from sklearn.preprocessing import StandardScaler
    # 标准化数据,保证每个维度的特征数据方差为1,均值为0。使得预测结果不会被某些维度过大的特征值而主导。
    ss = StandardScaler()
    X_train = ss.fit_transform(X_train)
    X_test = ss.transform(X_test)

    下面利用逻辑回归模型训练数据。

    from sklearn.linear_model import LogisticRegression
    lr = LogisticRegression()
    # 调用LogisticRegression中的fit函数/模块用来训练模型参数。
    lr.fit(X_train, y_train)
    

    最终我们得到了lr这个逻辑回归模型。

    更多相关内容
  • Pytorch使用预训练模型进行图像分类

    千次阅读 2021-11-27 19:14:03
    在本文中,我们将介绍一些使用预训练网络的实际例子,这些网络出现在TorchVision模块的图像分类中。 Torchvision包包括流行的数据集,模型体系结构,和通用的图像转换为计算机视觉。基本上,如果你进入计算机视觉...

    在本文中,我们将介绍一些使用预训练网络的实际例子,这些网络出现在TorchVision模块的图像分类中。

    Torchvision包包括流行的数据集,模型体系结构,和通用的图像转换为计算机视觉。基本上,如果你进入计算机视觉并使用PyTorch, Torchvision将会有很大的帮助!

    1. Pre-trained Models for Image Classification

    预训练模型是在大型 benchmark数据集(如ImageNet)上训练的神经网络模型。深度学习社区从这些开源模式中获益匪浅。此外,预先训练的模型是计算机视觉研究快速发展的一个主要因素。其他研究人员和从业人员可以使用这些最先进的模型,而不是重新发明一切从零开始。

    下面给出了一个粗略的时间轴,说明了这些先进的模型是如何随着时间的推移而改进的。我们只包括那些模型是在Torchvision包。
    在这里插入图片描述
    在详细介绍如何使用预先训练的模型进行图像分类之前,让我们看看有哪些预先训练的模型。我们将在这里讨论AlexNet和ResNet101作为两个主要的例子。这两个网络都接受过ImageNet数据集的训练。

    ImageNet数据集拥有超过1400万张由斯坦福大学维护的图像。它被广泛用于各种图像相关的深度学习项目。这些图像属于不同的类别或标签。像AlexNet和ResNet101这样的预训练模型的目的是将图像作为输入并预测它的类别。

    这里的“预训练”指的是深度学习架构,例如AlexNet和ResNet101,已经在一些(巨大的)数据集上进行了训练,因此产生了权重和偏差。架构与权重和偏差之间的区别应该非常清楚,因为我们将在下一节中看到,TorchVision既有架构,又有预训练的模型。

    1.1. 模型推理过程

    由于我们将关注如何使用预先训练的模型来预测输入的类(标签),所以让我们也讨论其中涉及的过程。这个过程被称为模型推理。整个过程由以下主要步骤组成。

    • 1.读取输入图像
    • 2.在图像上执行变换。例如,调整大小,中央裁剪,正规化等等。
    • 3.前向传递:使用预先训练的权值找出输出向量。这个输出向量中的每个元素描述模型预测输入图像属于某个特定类的置信度。
    • 4.根据得到的分数(我们在步骤3中提到的输出向量的元素),显示预测。

    1.2 使用TorchVision加载预训练网络

    现在,我们已经具备了模型推理的知识,并了解了预训练模型的含义,让我们看看如何在TorchVision模块的帮助下使用它们。

    首先,让我们使用下面给出的命令安装TorchVision模块。

    pip install torchvision
    

    接下来,让我们从torchvision模块导入模型,看看我们有哪些不同的模型和架构可用。

    from torchvision import models
    import torch
    
    dir(models)
    

    仔细观察我们得到的输出

    ['AlexNet',
     'DenseNet',
     'GoogLeNet',
     'Inception3',
     'MobileNetV2',
     'ResNet',
     'ShuffleNetV2',
     'SqueezeNet',
     'VGG',
    ...
     'alexnet',
     'densenet',
     'densenet121',
     'densenet161',
     'densenet169',
     'densenet201',
     'detection',
     'googlenet',
     'inception',
     'inception_v3',
    ...
    ]
    

    注意,有一个条目叫AlexNet,另一个叫AlexNet。大写的名称指的是Python类(AlexNet),而AlexNet是一个方便的函数,它返回从AlexNet类实例化的模型。这些方便的函数也可能有不同的参数集。例如,densenet121densenet161densenet169densenet201都是DenseNet类的实例,但层数不同——分别为121,161,169和201

    1.3. 利用AlexNet进行图像分类

    让我们先从AlexNet开始。它是图像识别领域早期的突破性网络之一。如果你有兴趣了解AlexNet的架构,你可以看看我们在理解AlexNet上的帖子。
    在这里插入图片描述
    AlexNet架构
    步骤1:加载预训练模型
    在第一步中,我们将创建一个网络实例。我们还将传递一个参数,以便函数可以https://github.com/spmallick/learnopencv/tree/master/Inference-for-PyTorch-Models/ONNX-Caffe2d模型的权重。

    alexnet = models.alexnet(pretrained=True)
    
    # You will see a similar output as below
    # Downloading: "https://download.pytorch.org/models/alexnet-owt- 4df8aa71.pth" to /home/hp/.cache/torch/checkpoints/alexnet-owt-4df8aa71.pth
    

    注意,通常PyTorch模型的扩展名为.pt或.pth
    一旦下载了权重,我们就可以继续其他步骤。我们还可以检查网络架构的一些细节,如下所示。

    print(alexnet)
    

    步骤2:图像变换

    一旦我们有了模型,下一步就是变换输入图像,使它们具有正确的形状和其他特征,如平均值和标准差。这些值应该与训练模型时使用的值一样。这确保了网络将产生有意义的答案。

    我们可以利用TochVision模块中的变换对输入图像进行预处理。在这种情况下,我们可以对AlexNet和ResNet使用以下转换。

    from torchvision import transforms
    transform = transforms.Compose([            #[1]
     transforms.Resize(256),                    #[2]
     transforms.CenterCrop(224),                #[3]
     transforms.ToTensor(),                     #[4]
     transforms.Normalize(                      #[5]
     mean=[0.485, 0.456, 0.406],                #[6]
     std=[0.229, 0.224, 0.225]                  #[7]
     )])
    

    让我们试着理解上面的代码片段中发生了什么。

    • 行[1]:在这里,我们定义了一个transform,它是对输入图像进行的所有图像变换的组合。
    • 行[2]:调整图像的大小为256×256像素。
    • 行[3]:裁切图像到224×224像素左右的中心。
    • 行[4]:将图像转换为PyTorch张量数据类型。
    • 行[5-7]:对图像进行归一化,将其平均值和标准差设置为规定值。

    第三步:加载输入图像并进行预处理
    接下来,让我们加载输入图像并执行上面指定的图像转换。请注意,我们将在TorchVision中广泛使用Pillow (PIL)模块,因为它是TorchVision支持的默认图像后端。

    # Import Pillow
    from PIL import Image
    img = Image.open("dog.jpg")
    

    在这里插入图片描述
    接下来,对图像进行预处理,并准备批处理以通过网络。

    img_t = transform(img)
    batch_t = torch.unsqueeze(img_t, 0)
    

    步骤4:模型推理
    最后,是时候使用预先训练的模型来查看模型认为图像是什么。
    首先,我们需要将模型置于eval模式

    alexnet.eval()
    

    接下来,让我们执行推论。

    out = alexnet(batch_t)
    print(out.shape)
    

    这一切都很好,但我们如何处理这个输出向量,其中包含1000个元素?我们仍然没有得到图像的类(或标签)。为此,我们将首先从一个包含所有1000个标签列表的文本文件中读取和存储标签。注意,行号指定了类号,所以确保不改变顺序是非常重要的。

    with open('imagenet_classes.txt') as f:
      classes = [line.strip() for line in f.readlines()]
    

    因为AlexNetResNet已经在相同的ImageNet数据集上进行了训练,所以我们可以对两个模型使用相同的Class列表。
    现在,我们需要找出输出向量out中最大分数出现的索引。我们将使用这个指标来找出预测。

    _, index = torch.max(out, 1)
    
    percentage = torch.nn.functional.softmax(out, dim=1)[0] * 100
    
    print(labels[index[0]], percentage[index[0]].item())
    

    该模型预测的图像是拉布拉多犬有41.58%的置信度。
    但这听起来太低了。让我们看看模型认为图像还属于什么类别。
    这里是输出:

    [('Labrador retriever', 41.585166931152344),
     ('golden retriever', 16.59166145324707),
     ('Saluki, gazelle hound', 16.286880493164062),
     ('whippet', 2.8539133071899414),
     ('Ibizan hound, Ibizan Podenco', 2.3924720287323)]
    

    这个模型成功地预测出这是一只狗,但它对狗的品种不是很确定。

    让我们对草莓和汽车的图像做同样的尝试,看看我们得到的输出。
    在这里插入图片描述
    这是上述草莓图像得到的输出。我们可以看到,得分最高得分是“草莓”,得分接近99.99%。

    [('strawberry', 99.99365997314453),
     ('custard apple', 0.001047826954163611),
     ('banana', 0.0008201944874599576),
     ('orange', 0.0007371827960014343),
     ('confectionery, confectionary, candy store', 0.0005758354091085494)]
    

    在这里插入图片描述
    类似地,对于上面给出的汽车图像,输出如下。

    [('cab, hack, taxi, taxicab', 33.30569839477539),
     ('sports car, sport car', 14.424001693725586),
     ('racer, race car, racing car', 10.685123443603516),
     ('beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon',
      7.846532821655273),
     ('passenger car, coach, carriage', 6.985556125640869)]
    

    就是这样!通过这4个步骤,就可以使用预先训练好的模型进行图像分类。
    我们在ResNet上试试同样的方法怎么样?

    1.4. 使用ResNet进行图像分类

    我们将使用resnet101 - 101层卷积神经网络。Resnet101在训练过程中调整了大约4450万个参数。这是巨大的!

    让我们快速浏览一下使用resnet101进行图像分类所需的步骤。

    # First, load the model
    resnet = models.resnet101(pretrained=True)
    
    # Second, put the network in eval mode
    resnet.eval()
    
    # Third, carry out model inference
    out = resnet(batch_t)
    
    # Forth, print the top 5 classes predicted by the model
    _, indices = torch.sort(out, descending=True)
    percentage = torch.nn.functional.softmax(out, dim=1)[0] * 100
    [(labels[idx], percentage[idx].item()) for idx in indices[0][:5]]
    

    这是resnet101的预测。

    [('Labrador retriever', 48.25556945800781),
     ('dingo, warrigal, warragal, Canis dingo', 7.900787353515625),
     ('golden retriever', 6.916920185089111),
     ('Eskimo dog, husky', 3.6434383392333984),
     ('bull mastiff', 3.0461232662200928)]
    

    就像AlexNet一样,ResNet成功地预测出这是一只狗,并以48.25%的自信预测出这是一只拉布拉多寻回犬。

    2. 模型比较

    到目前为止,我们已经讨论了如何使用预先训练的模型来执行图像分类,但我们还没有回答的一个问题是,我们如何决定为特定的任务选择哪个模型。在本节中,我们将根据以下标准比较预训练模型:

    • Top-1误差:如果最有把握的模型预测的类与真实的类不一样,就会出现Top-1误差。
      -top-5错误:当真实的类不在模型预测的前5个类中(根据置信度排序),就会出现top-5错误。
    • CPU上的推理时间:推理时间是模型推理步骤所花费的时间。
    • GPU上的推理时间
      模型大小:这里的大小表示PyTorch提供的预训练模型的.pth文件所占用的物理空间

    一个好的模型会有较低的Top-1错误,较低的Top-5错误,较低的CPUGPU推理时间和较低的模型尺寸。
    所有的实验都是在相同的输入图像上进行的,并进行多次,以便对特定模型的所有结果进行平均,以便进行分析。实验是在谷歌Colab上进行的。现在,让我们看看所获得的结果。

    2.1. 模型精度比较

    我们要讨论的第一个标准包括Top-1和Top-5错误。top -1误差是指top预测类与真实情况不同时的误差。由于这是一个相当困难的问题,有另一个误差测量称为Top-5误差。如果前5个预测类别中没有一个是正确的,那么该预测将被归类为错误。
    在这里插入图片描述
    从图中可以看出,这两个error遵循相似的趋势。AlexNet是基于深度学习的第一次尝试,从那时起在错误方面有了改进。值得一提的是GoogLeNet, ResNet, VGGNet, ResNext。

    2.2. 推理时间比较

    接下来,我们将基于模型推理所花费的时间来比较模型。一个图像被多次提供给每个模型,所有迭代的推理时间被平均。在谷歌Colab上对CPUGPU执行了类似的过程。即使在顺序上有一些变化,我们可以看到SqueezeNet, ShuffleNetResNet-18的推断时间非常低,这正是我们想要的。
    在这里插入图片描述
    在这里插入图片描述

    2.3. 模型的大小比较

    很多时候,当我们在android或iOS设备上使用深度学习模型时,模型大小成为一个决定性因素,有时甚至比准确性更重要。SqueezeNet的模型尺寸最小(5 MB),其次是ShuffleNet V2 (6 MB)和MobileNet V2 (14 MB)。很明显,这些模型在使用深度学习的移动应用中更受欢迎。
    在这里插入图片描述
    2.4. 整体比较
    我们讨论了在特定标准的基础上哪个模型表现得更好。我们可以将所有这些重要的细节压缩到一个气泡图中,然后根据我们的需求来决定使用哪个模型。
    我们使用的x坐标是Top-1误差(越低越好)。y坐标是GPU上的推断时间,以毫秒为单位(越低越好)。气泡大小代表模型大小(越小越好)。

    注意:

    • 较小的气泡在模型尺寸方面更好。
    • 靠近原点的气泡在精度和速度方面都更好。

    在这里插入图片描述

    3.结论
    从上图可以看出,ResNet50在所有三个参数上都是最好的模型(尺寸小,更接近原点)

    • DenseNetsResNext101在推理时间上是昂贵的。
    • AlexNetSqueezeNet的错误率都很高。

    好了,就到这里吧!在这篇文章中,我们介绍了如何使用Torchvison模块进行图像分类,使用预训练的模型-只有4个步骤的过程。我们也进行了模型比较,根据我们的项目需求来决定选择什么样的模型。在下一篇文章中,我们将介绍如何使用迁移学习来使用PyTorch训练自定义数据集上的模型。

    源代码地址下载

    展开全文
  • 1. 搭建自己的简单二分类网络,使用pytorch训练和测试; 2. 将pytorch训练的pth模型转换成ONNX,并编码测试; 3. 含训练和测试数据,含训练ok的pth模型和ONNX模型,含完整python和C++实现; 4. 使用方法:首先...
  • 本博客将尝试使用预训练模型进行猫狗分类。 实验所用数据集及工具 数据集 本实验使用实验数据基于kaggle Dogs vs. Cats 竞赛提供的官方数据集,数据集可在百度网盘中进行下载: 链接:https://pan.baidu.com/s/13...

    前言

    预训练模型顾名思义就是使用别人已经训练好的模型参数放到自己的任务里面进行特定任务的微调。这里的模型参数包括:神经网络的结构、神经网络的权值参数。
    本博客将尝试使用预训练模型进行猫狗分类。
    代码地址:https://github.com/jmhIcoding/dogsVScats.git

    实验所用数据集及工具

    数据集

    本实验使用实验数据基于kaggle Dogs vs. Cats 竞赛提供的官方数据集,数据集可在百度网盘中进行下载:
    链接:https://pan.baidu.com/s/13hw4LK8ihR6-6-8mpjLKDA 密码:dmp4。
    数据集的目录划分如下:
    dataset
    |— train
    |— dogs
    |— cats
    |— validation
    |— dogs
    |— cats

    将数据集划分为训练集(training dataset)和验证集(validation dataset),均包含dogs和cats两个目录,且每个目录下包含与目录名类别相同的RGB图。数据集共25000张照片,其中训练集猫狗照片各10000张,验证集猫狗照片各2500张。(注:可根据计算资源情况自己调整训练集和验证集的大小,但最好按比例调整)
    原始数据集如图3、4、5、6所示。

    在这里插入图片描述
    图3
    在这里插入图片描述
    图4

    在这里插入图片描述
    图5
    在这里插入图片描述
    图6

    Slim工具

    Slim是 TensorFlow 中一个用来构建、训练、评估复杂模型的轻量化库,TF-Slim 模块可以和 TensorFlow 中其它API混合使用。参见:
    https://github.com/tensorflow/models/tree/master/research/slim。
    这里简要介绍Tensorflow Slim的代码结构:

    1. datasets/:定义一些训练时用的数据集,预先定义了4个数据集:MNIST、CIFAR-10、Flowers、ImageNet,如果需要训练自己的数据,则可以在datasets文件夹中定义。
    2. nets/:定义了一些常用的网络结构如AlexNet、VGG16、Inception系列等。
    3. preprocessing/:定义了一些图片预处理和数据增强方法。
    4. train_image_classifer.py:训练模型的入口代码。
    5. eval_image_claasifer.py:验证模型的入口代码。

    实验步骤与方法

    对猫狗照片识别分类的卷积神经网络模型可以自行设计,本实验指导书给出的方法是利用Slim工具包中预定义好的网络结构并进行微调的方法实现,具体是基于nets文件夹中预定义好的Inception V3进行微调。

    处理数据集,转换为TFRecord

    • 下载数据集,把train文件夹的25000个图片中,随机取出2500个猫和2500个狗放到train同级目录下的validation目录。
    • 编写TFRecord生成函数

    生成train和validdation的TF_Record文件,代码见 convert_kaggle.py
    TF_Record文件是tensorflow里面结构化组织训练数据的一种方法,这种方法的本质就是把分散在磁盘中的训练样本集中起来放在一起,使得模型读取数据更加快速。
    Slim框架里面使用的数据格式默认就需要先转换为TF_Record。
    对于 图片分类 而言,convert_kaggle代码是可以复用的。
    只需要根据需要把代码中feature做相应的填充即可:

    ···
    example = tf.train.Example(features=tf.train.Features(
            feature={
                        'image/height': _int64_feature(height), #图片高度
                        'image/width': _int64_feature(width),   #图片宽度
                        'image/colorspace': _bytes_feature(colorspace),
                        'image/channels': _int64_feature(channels),#通道个数
                        'image/class/label': _int64_feature(label),#label
                        'image/class/text': _bytes_feature(text),
                        'image/format': _bytes_feature(image_format),#'JPEG'
                        'image/filename': _bytes_feature(os.path.basename(filename)), #文件名
                        'image/encoded': _bytes_feature(image_buffer)#图片的内容
                    }
                    )
                    )
    ···
    
    #coding:utf-8
    __author__ = 'jmh081701'
    import numpy as np
    import tensorflow as tf
    import sys
    import  os
    def _int64_feature(value):
        if not isinstance(value, list):
            value = [value]
        return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
    def _bytes_feature(value):
        return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
    
    def _convert_example(filename, image_buffer, label, text, height, width):
        colorspace = 'RGB'.encode()
        channels = 3
        image_format = 'JPEG'.encode()
        if not isinstance(label,int):
            label=int(label)
        if not isinstance(text,bytes):
            text = text.encode()
        if not isinstance(filename,bytes):
            filename = filename.encode()
        example = tf.train.Example(features=tf.train.Features(
            feature={
                        'image/height': _int64_feature(height), #图片高度
                        'image/width': _int64_feature(width),   #图片宽度
                        'image/colorspace': _bytes_feature(colorspace),
                        'image/channels': _int64_feature(channels),#通道个数
                        'image/class/label': _int64_feature(label),#label
                        'image/class/text': _bytes_feature(text),
                        'image/format': _bytes_feature(image_format),#'JPEG'
                        'image/filename': _bytes_feature(os.path.basename(filename)), #文件名
                        'image/encoded': _bytes_feature(image_buffer)#图片的内容
                    }
                    )
                    )
        return example
    
    def convert_kaggle_image(datadir,usage='train'):
    
        _decode_jpeg_data = tf.placeholder(dtype=tf.string)#place holder
        _decode_jpeg = tf.image.decode_jpeg(_decode_jpeg_data, channels=3)
    
        with tf.Session() as sess:
            for root,subdirs,files in os.walk(datadir):
                counter = 0
                shard   = 5
                each_shard=int(len(files)/shard)
                writers=[0,1,2,3,4]
                writers[0] = tf.python_io.TFRecordWriter('.\\dogsVScats_%s_0-of-5.tfrecord'%usage)
                writers[1] = tf.python_io.TFRecordWriter('.\\dogsVScats_%s_1-of-5.tfrecord'%usage)
                writers[2] = tf.python_io.TFRecordWriter('.\\dogsVScats_%s_2-of-5.tfrecord'%usage)
                writers[3] = tf.python_io.TFRecordWriter('.\\dogsVScats_%s_3-of-5.tfrecord'%usage)
                writers[4] = tf.python_io.TFRecordWriter('.\\dogsVScats_%s_4-of-5.tfrecord'%usage)
                for file in files:
                    writer = writers[int(counter/each_shard)]
                    label = 0 if file.split('.')[0] == 'cat' else 1  #0 is cat,while 1 is dog
                    filename=root+"\\"+file
                    # Read the image file, mode:read and binary
                    image_data_raw=tf.gfile.GFile(filename,"rb").read()
                    # Convert 2 tensor,转换的目的是为了提取height和width,也可以使用PIL库来转换
                    image= sess.run(_decode_jpeg,feed_dict={_decode_jpeg_data:image_data_raw})
                    height=image.shape[0]
                    width =image.shape[1]
    
                    example=_convert_example(filename,image_buffer=image_data_raw,label=label,text="",height=height,width=width)
                    writer.write(example.SerializeToString())
                    counter+=1
                    print("Finish:%s"%str(counter/len(files)))
                    sys.stdout.flush()
                writers[0].close()
                writers[1].close()
                writers[2].close()
                writers[3].close()
                writers[4].close()
    if __name__ == '__main__':
        convert_kaggle_image(datadir=r"G:\bdndisk\kaggle\train\validation",usage='validation')
    convert_kaggle_image(datadir=r"G:\bdndisk\kaggle\train\train",usage='train')
    

    运行脚本,将生成10个tfrecord文件,其中有5个是训练集另外5个是验证集。
    在这里插入图片描述

    安装TF-slim识别库

    安装TF-slim 图像识别库

    Tensorflow 1.0以后就支持TF-Slim了,但是要使用TF-Slim进行图像分类就还得安装TF-Slim image models library.

    安装方法:
    在这里插入图片描述

    git clone  https://github.com/tensorflow/models/
    

    创建数据库声名文件

    在刚刚clone的目录下的models\research\slim\datasets新建一个dogVScats.py文件,把flowers.py内容拷贝下来。修改其中的内容:
    在这里插入图片描述
    主要是_FILE_PATTERN,SPLITS_TO_SIZES以及_NUM_CLASSES 三个值。
    _FILE_PATTERN 用于表示刚刚生成的TF_RECORD文件的文件名的格式,%s_* 带了通配符号。
    SPLITES_TO_SIZES表示训练集和测试集的大小。
    _NUM_CLASSES表示分类类别数目。
    dogVScats内容:https://github.com/jmhIcoding/dogsVScats/blob/master/dogsVScats.py

    在dataset_factory.py注册dogsVScats

    在这里插入图片描述
    注意箭头指向的地方是需要修改的。
    修改后的dataset_factory.py: https://github.com/jmhIcoding/dogsVScats/blob/master/dataset_factory.py

    训练模型:

    训练脚本

    main.py

    __author__ = 'jmh081701'
    import os
    cmd="python train_image_classifier.py --train_dir=dogsVScats/train_dir " \
        "--dataset_name=dogsVScats --dataset_split_name=train " \
        "--dataset_dir=dogsVScats/data --model_name=inception_v3 " \
        "--checkpoint_path=dogsVScats/pretrained/inception_v3.ckpt " \
        "--checkpoint_exclude_scopes=InceptionV3/Logits,InceptionV3/AuxLogits " \
        "--trainable_scopes=InceptionV3/Logits,InceptionV3/AuxLogits " \
        "--max_number_of_steps=25000 --batch_size=32 " \
        "--learning_rate=0.001 " \
        "--learning_rate_decay_type=fixed " \
        "--save_interval_secs=300 --save_summaries_secs=2 " \
        "--log_every_n_steps=10 " \
        "--optimizer=rmsprop --weight_decay=0.00004"
    if __name__ == '__main__':
    os.system(cmd)
    

    其中trainable_scopes指定只训练Logits和AuxLogits部分,checkpoint_exclue_scope则是说明Logits和AuxLogits不要保存,这是因为InceptionV3的顶层是包含1001个神经元,而我们的分类只是二分类。

    训练模型过程:

    在这里插入图片描述

    使用tensorboard查看训练过程

    在这里插入图片描述

    Losses的结果图:在这里插入图片描述

    训练过程中错误解决

    报错1:

    tensorflow.python.framework.errors_impl.InvalidArgumentError: Cannot assign a device for operation 'InceptionV3/Predictions/Softmax': Could not satisfy explicit device specification '/device:GPU:0' because no supported kernel for GPU devices is available.
             [[Node: InceptionV3/Predictions/Softmax = Softmax[T=DT_FLOAT, _device="/device:GPU:0"](InceptionV3/Predictions/Reshape)]]
    

    解决方法:
    把slim文件夹下的train_image_classfier.py最后几行改掉:

        ###########################
        # Kicks off the training. #
        ###########################
        session_config= tf.ConfigProto(allow_soft_placement=True)
        slim.learning.train(
            train_tensor,
            logdir=FLAGS.train_dir,
            master=FLAGS.master,
            is_chief=(FLAGS.task == 0),
            init_fn=_get_init_fn(),
            summary_op=summary_op,
            number_of_steps=FLAGS.max_number_of_steps,
            log_every_n_steps=FLAGS.log_every_n_steps,
            save_summaries_secs=FLAGS.save_summaries_secs,
            save_interval_secs=FLAGS.save_interval_secs,
            sync_optimizer=optimizer if FLAGS.sync_replicas else None,
            session_config=session_config
    )
    

    报错2:

    InvalidArgumentError (see above for traceback): Assign requires shapes of both tensors to match. lhs shape= [2] rhs shape= [1001]
    

    解决方法:
    检查 --checkpoint_exclude_scopes 参数名以及参数值是否正确,本人一开始把exclude写成了execlue就报错了。

    验证(测试)模型

    因为Kagggle给的数据里面test数据是没有标注好的,因此我们得从train中划分一部分数据出来做验证或测试用,这部分数据就是刚刚划分出来的validation。
    在训练25000个step,共计1小时后,我们对模型进行验证。

    验证脚本:
    代码见main.py

    cmdValid="python eval_image_classifier.py " \
             "--checkpoint_path=dogsVScats/train_dir " \
             "--eval_dir=dogsVScats/eval_dir " \
             "--dataset_name=dogsVScats " \
             "--dataset_split_name=validation " \
             "--dataset_dir=dogsVScats/data " \
             "--model_name=inception_v3"
    if __name__ == '__main__':
        #os.system(cmd)
    os.system(cmdValid)
    

    验证结果:
    在这里插入图片描述
    在训练25000个step后,在5000个图片中的验证结果为:
    Recall_5: 100 %,说明所有的狗样本都被找到.
    Accuracy:95.54%,

    实验总结

    本实验通过猫狗分类的实例来体会如何使用Slim框架来对预训练模型进行微调。使用Slim框架进行微调的主要步骤就是提前准备好TF-Record的训练集验证集数据,同时在datasets目录下注册新的数据集。

    剩下的模型微调就只是调用train_image_classfier.py脚本,然后根据需要设置不同参数而已。

    一开始本人的疑惑在于InceptionV3都是一个1001分类的模型,如何使用这个预训练好的模型对猫狗二分类进行分类呢?后面发现是在train_image_classfier脚本运行过程中指定trainable_scopes和checkpoint_exclude_scope来实现的。正如官方文档写的那样:
    When fine-tuning a model, we need to be careful about restoring checkpoint weights. In particular, when we fine-tune a model on a new task with a different number of output labels, we wont be able restore the final logits (classifier) layer. For this, we’ll use the --checkpoint_exclude_scopes flag. This flag hinders certain variables from being loaded. When fine-tuning on a classification task using a different number of classes than the trained model, the new model will have a final ‘logits’ layer whose dimensions differ from the pre-trained model. For example, if fine-tuning an ImageNet-trained model on Flowers, the pre-trained logits layer will have dimensions [2048 x 1001] but our new logits layer will have dimensions [2048 x 5]. Consequently, this flag indicates to TF-Slim to avoid loading these weights from the checkpoint.

    当微调模型的时候,我们要十分慎重的选择载入哪些权重。因为猫狗分类是2个输出,而InceptionV3是1001个输出,我们不能载入最后一个分类层的参数,而—checkpoint_exclude_scopes就是起得这个作用,它会显式在载入预训练模型时不去加载最后一层的值,而是使用slim的初始值。

    展开全文
  • 前面两篇我们分别进行了在不用数据增强和用数据增强技术的条件下在一个小数据集上训练一个小的...本文我们将考虑如何在(已经在大数据集上训练过的)预训练模型的基础上,在小数据集上进一步训练得到最终模型的效果。

    目录

    0. 前言

    1. 为什么可以用预训练模型?

    1.1 特征提取

    1.2 模型微调

    2. 加载预训练模型

    3. 特征提取

    4. 训练以及评估

    4.1 训练

     4.2 loss和accuracy曲线

    4.3. 在测试集进行模型性能评估 

    5. 小结


    0. 前言

            本文(以及接下来的几篇)介绍如何搭建一个卷积神经网络用于图像分类的深度学习问题,尤其是再训练数据集比较小的场合。通常来说,深度学习需要大量的数据进行训练,尤其是像在图像处理这种通常数据维度非常高的场合。但是当你没有一个足够大的数据集进行训练的时候应该怎么办呢?

            解决训练数据集太小的方法通常有两种:

    (1) 使用数据增强策略

    (2) 使用预训练模型

            前面两篇我们分别进行了在不用数据增强和用数据增强技术的条件下在一个小数据集上训练一个小的卷积神经网络。采用数据增强可以获得相当程度的改善,但是由于原始数据集毕竟太小,所以很难达到90%的预测准确度。

            本文我们将考虑如何在(已经在大数据集上训练过的)预训练模型的基础上,在小数据集上进一步训练得到最终模型的效果。

            本文中将略去数据下载和预处理,相关细节请参考前面两篇。

    深度学习笔记:在小数据集上从头训练卷积神经网络https://blog.csdn.net/chenxy_bwave/article/details/122260520

    深度学习笔记:利用数据增强在小数据集上从头训练卷积神经网络https://blog.csdn.net/chenxy_bwave/article/details/122276708

    1. 为什么可以用预训练模型?

            换句话说,为什么预训练模型会有效?

            预训练网络(pre-trained)是指一个之前在大型数据集(通常是大规模图像分类任务)上训练并保存好的网络模型。如果这个原始数据集足够大且足够通用,那么预训练模型学到的特征的空间层次结构可以有效地作为视觉世界的通用模型,因此这些特征可用于各种不同的计算机视觉问题,即时这些新问题涉及的类别和原始问题完全不同。举个例子,你在ImageNet(其类别主要是动物和日常用品)上训练了一个模型,然后将这个训练好的模型应用于某个不相干的任务,比如说在图像中识别家具。这种学到的特征在不同问题之间的可移植性,是深度学习与许多早期浅层学习方法相比的重要优势,它使得深度学习对小数据问题也能够做到非常有效。

            使用预训练模型有两种方法:

    (1) 特征提取: feature extraction

    (2) 模型微调: fine-tuning

            本文先做关于特征提取的实验。模型微调将留到下一篇讨论。

    1.1 特征提取

            特征提取就是使用预训练模型学到的表示来从新样本中提取出感兴趣的特征。然后将这些特征输入一个新的分类器,从头开始训练。

            一个用于图像分类的卷积神经网络通常包含两部分。第一部分是一系列卷积层和池化层,通常称为卷积基(convolutional base, 简记为convbase);第二部分就是最后连接的密集连接分类器。

            对于卷积神经网络而言,特征提取就是用卷积基对新数据进行处理,生成新数据的特征表示。然后再基于这些所提取的特征去训练一个新的分类器。

            为什么仅重复使用卷积基呢?原因在于卷积基学到的表示更有通用性,因此更适合于重复使用。卷积神经网络的特征图表示通用概念在图像中是否存在,无论面对什么样的计算机视觉问题,这种特征图都可能有用。而最后的分类器学到的表示必然是针对有模型训练的类别,其中仅包含某个类别出现在整张图像中的概率信息。比如说,从猫狗分类中学习到的表示信息不太可能对于家具分类有什么帮助,但是不管是猫狗的图像还是家具的图像,都会有边缘啊、条纹啊之类的东西。此外,密集连接层的表示不再包含物体在输入图像中的位置信息,它舍弃了空间概念。物体的位置信息再卷积特征图中有描述,如果物体位置对于问题很重重要,那么密集连接层的特征在很大程度上是无用的。

            进一步,卷积神经网络中不同的卷积层所学习到的表示的通用性也是不同的。通常来说,处于模型的前级的层提取的局部的有更高通用性的特征图(比如,边缘,颜色,纹理等等),而靠后的卷积层提取的是更加抽象的概念(比如说‘猫耳朵’、‘狗眼睛’等等)。因此,如果你的新数据与原始数据有很大的差异,那么最好只使用卷积基的前面基层来做特征提取。比如说如果你是在猫狗数据集上训练出的模型,想要用作预训练模型用于家具分类识别,后级卷积层所提取的整体的、抽象的特征(比如说‘猫耳朵’、‘狗眼睛’等等)对于家具分类显然没有什么意义。

    1.2 模型微调

            参见后续篇章。

    2. 加载预训练模型

            在这个例子中我们将使用在ImageNet上训练的VGG16网络的卷积基从猫狗图像数据集中提取特征,然后用于训练一个猫狗分类器。

            由于ImageNet数据集中也包含了很多猫和狗的图片,所以可以直接使用VGG16网络进行猫狗图像数据集的图像分类其实是可以的。但是出于本文的演示目的,我们只使用VGG16的卷积基。

            在keras中内置了很多卷积神经网络的经典模型(其实也就是过去不到十年的事情,但是深度学习发展过于迅速,几年的时间已经使得当年的新模型成为今天的经典。当然在这个加速发展的世界里,成为经典意味着它的性能可能已经远远落后与SOTA模型,只是它的思想被传承下去了),如下所示:

    (1) Xception

    (2) Inception X3

    (3) ResNet50

    (4) VGG16

    (5) VGG19

    (6) MobileNet

            以下VGG16模型实例化中,将include_top置为False,意思就是剔除最顶层(即最终的密集分类层)。weights指定模型初始化的权重检查点,input_shape则指定输入数据形状。可以不指定,不指定的话,可以处理任意形状的输入。

    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    from tensorflow.keras import utils
    import numpy as np
    import matplotlib.pyplot as plt
    from PIL import Image
    print(tf.__version__)
    
    conv_base = keras.applications.vgg16.VGG16(
        weights="imagenet",
        include_top=False,
        input_shape=(180, 180, 3))
    conv_base.summary()

    3. 特征提取

            以下我们同样先实例化生成ImageDataGenerator对象,然后分别生成训练集、验证集和测试集的数据生成器,这里我们先不考虑数据增强(step-by-step地累进式地前进有助于我们看清楚每一个技术要素所发挥的作用)。然后利用以上加载的VGG16的conv_base提取这些数据集中的特征。

    # Data generators
    import os
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    
    batch_size = 32
    train_dir = os.path.join('F:\DL\cats_vs_dogs_small', 'train')
    test_dir = os.path.join('F:\DL\cats_vs_dogs_small', 'test')
    train_datagen = ImageDataGenerator(rescale=1./255,validation_split=0.3)
    test_datagen = ImageDataGenerator(rescale=1./255)
    
    train_generator = train_datagen.flow_from_directory(
        directory=train_dir,
        target_size=(180, 180),
        color_mode="rgb",
        batch_size=batch_size,
        class_mode="binary",
        subset='training',
        shuffle=True,
        seed=42
    )
    valid_generator = train_datagen.flow_from_directory(
        directory=train_dir,
        target_size=(180, 180),
        color_mode="rgb",
        batch_size=batch_size,
        class_mode="binary",
        subset='validation',
        shuffle=True,
        seed=42
    )
    test_generator = test_datagen.flow_from_directory(
        directory=test_dir,
        target_size=(180, 180),
        color_mode="rgb",
        batch_size=batch_size,
        class_mode='binary',
        shuffle=False,
        seed=42
    )
    import numpy as np
    
    def get_features_and_labels(dataGenerator):
        all_features = []
        all_labels = []
        k = 0
        for images, labels in dataGenerator:
            features = conv_base.predict(images)
            all_features.append(features)
            all_labels.append(labels)
            k += 1
            if dataGenerator.batch_size * (k+1) > dataGenerator.n:
                break
        print('Totally, {0}-batches with batch_size={1}'.format(k,dataGenerator.batch_size))
        return np.concatenate(all_features), np.concatenate(all_labels)
    
    train_features, train_labels =  get_features_and_labels(train_generator)
    val_features, val_labels =  get_features_and_labels(valid_generator)
    test_features, test_labels =  get_features_and_labels(test_generator)
    print(train_features.shape,train_labels.shape)

             需要注意的一点是,Generator是可以永远持续地生成数据的,而并不是说输出完一遍数据后就退出,因此需要有一个break机制。参见以上get_features_and_lables()中的break语句。

    4. 训练以及评估

    4.1 训练

            由于这里的训练只涉及到最后的Dense Layer,因此训练会非常快(相比前面两篇中从头训练而言)。当然,由于本模型采用了VGG16的卷积基,所以在预测阶段所需要的运算量是远远地大于前两篇中训练的小型卷积网络。毕竟VGG16的卷积基虽然不用重新训练,但是预测时是需要全部参与的运算的。

    from tensorflow.keras import optimizers
    inputs = keras.Input(shape=(5, 5, 512)) # This shape has to be the same as the output shape of the convbase
    x = layers.Flatten()(inputs)
    x = layers.Dense(256,activation='relu')(x)
    x = layers.Dropout(0.5)(x)
    outputs = layers.Dense(1, activation="sigmoid")(x)
    model = keras.Model(inputs, outputs)
    model.compile(loss="binary_crossentropy",
                  optimizer=optimizers.RMSprop(learning_rate=2e-5),
                  metrics=["accuracy"])
    
    callbacks = [
        keras.callbacks.ModelCheckpoint(
          filepath="feature_extraction.keras",
          save_best_only=True,
          monitor="val_loss")
    ]
    history = model.fit(
        train_features, train_labels,
        epochs=32,
        validation_data=(val_features, val_labels),
        callbacks=callbacks)

     4.2 loss和accuracy曲线

    import matplotlib.pyplot as plt
    accuracy = history.history["accuracy"]
    val_accuracy = history.history["val_accuracy"]
    loss = history.history["loss"]
    val_loss = history.history["val_loss"]
    epochs = range(1, len(accuracy) + 1)
    plt.plot(epochs, accuracy, "bo", label="Training accuracy")
    plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
    plt.title("Training and validation accuracy")
    plt.legend()
    plt.figure()
    plt.plot(epochs, loss, "bo", label="Training loss")
    plt.plot(epochs, val_loss, "b", label="Validation loss")
    plt.title("Training and validation loss")
    plt.legend()
    plt.show()

    4.3. 在测试集进行模型性能评估 

    print(test_features.shape,test_labels.shape)
    test_model = keras.models.load_model("feature_extraction.keras")
    test_loss, test_acc = test_model.evaluate(test_features,test_labels)
    print(f"Test accuracy: {test_acc:.3f}")

    5. 小结

            本文基于keras内置的VGG16做了一个基于预训练模型的特征提取(without data augmentation)的实验。

            实验结果表明(unsurprisingly)存在明显的过拟合。但是相对地来看的话,在验证集和测试集上也分别得到了91%和89%的准确度(accuracy),而上一篇基于数据增强技术从头开始训练的网络只有80%出头而已,可以说是一个巨大的进步。

            接下来我们来看看,在基于预训练模型的基础上再加上数据增强能不能取得更好的性能呢?

    Reference: Francois, Chollet: Deep Learning with Python.

    展开全文
  • MMclassification 是一个分类工具库,这篇文章是简单记录一下如何用该工具库来训练自己的分类模型,包括数据准备,模型修改,模型训练模型测试等等。 MMclassification链接:...
  • 基于BERT预训练模型的中文文本分类任务的实现
  • 训练模型简介

    千次阅读 2021-11-25 12:37:15
    训练模型训练模型把迁移学习很好地用起来了,让我们感到眼前一亮。这和小孩子读书一样,一开始语文、数学、化学都学,读书、网上游戏等,在脑子里积攒了很多。当他学习计算机时,实际上把他以前学到的所有知识...
  • 使用opencv_traincascade 分类器的训练模型包括两个主要阶段:于HAAR或LBP模型的训练阶段和检测阶段。本文档概述了训练自己的弱分类器的级联所需的功能。当前指南将逐步完成所有不同阶段:收集训练数据,准备训练...
  • 使用PyTorch中的预训练模型进行图像分类

    千次阅读 多人点赞 2020-02-10 23:10:35
    PyTorch的TorchVision模块中包含多个用于图像分类的预训练模型,TorchVision包由流行的数据集、模型结构和用于计算机视觉的通用图像转换函数组成。一般来讲,如果你进入计算机视觉和使用PyTorch,TorchVision可以...
  • pytorch 构建训练模型的几大步骤 1、数据准备 2、模型构建 3、定义代价函数和优化器 4、迭代训练 5、模型保存 1、数据准备 将要训练使用的数据进行前期的处理,提取到需要学习的特征表示,包括数据特征和对应的数据...
  • Bert预训练模型-中文文本分类

    万次阅读 热门讨论 2019-01-20 21:59:19
    Bert-用于短文本分类
  • 需求描述:基于构建简单的多分类模型需求,使用的是keras深度学习库实现的,实现代码简单可用,模型优点是训练速度快,准确率达97%,适合粗粒度分类。 实现步骤:1、预处理数据:包括构建自定义词典、分词、去停用...
  • 文本分类(三)专栏主要是对Github优秀文本分类项目的解析,该文本分类项目,主要基于预训练语言模型,包括bert、bert + CNN/RNN/RCNN/DPCNN、ERNIE等,使用PyTorch实现。 本博客还讲解了一种预训练语言模型的通用...
  • 训练模型综述

    万次阅读 多人点赞 2020-09-16 10:00:00
    训练模型综述摘要:近年来,预训练模型的出现将自然语言处理带入了一个新的时代。本文概述了面向自然语言处理领域的预训练模型技术。我们首先概述了预训练模型及其发展历史。并详细介绍自然语言处理...
  • 作者:PURVA HUILGOL编译:ronghuaiyang导读文本分类是NLP的基础任务之一,今天给大家介绍6个最新的预训练模型,做NLP的同学一定要用用看。介绍我们正站在语言和...
  • K210模型训练(物体分类

    千次阅读 2021-11-10 21:05:50
    我们采用的是MaixHub模型训练平台,当然除了这个训练平台还有很多种方法进行训练。 比如: 1.本地模型训练——Linux https://wiki.sipeed.com/soft/maixpy/zh/course/ai/train/local.html 2.本地训练——windows ...
  • pytorch 修改预训练模型

    千次阅读 多人点赞 2020-08-22 15:27:31
    pytorch 修改预训练模型
  • 若自己对模型结构进行修改,就不能直接载入完整的预训练模型。 方法 方法一 载入权重之后,将最后一个全连接层的输出大小改为 5(默认是 1000 )。 import os import torch import torch.nn as nn from model import...
  • 深入理解深度学习——预训练模型

    万次阅读 2022-02-06 12:59:01
    近些年基于深度学习的NLP技术的重大进展主要包括NNLM(2003)、Word Embedding(2013)、Seq2Seq(2014)、Attention(2015)、Transformer(2017)、GPT(2018)、BERT(2018)、XLNet(...,主要预训练模型的大致发展脉络见下图...
  • 如何训练出优秀的图像分类模型?飞桨图像分类套件 PaddleClas 来助力。今天咱们来聊聊计算机视觉领域最核心的技术之一——图像分类。顾名思义图像分类是指根据图像信息把不同类别的图像自...
  • 三十多年来,许多研究人员在图像识别算法和...在 2000 年代初期,大多数 AI 研究人员都专注于图像分类问题的模型算法,但缺乏数据样本,研究人员需要大量图像和相应的标签来训练模型。这激发了 ImageNet 的创建。 Imag
  • 最近看了常用的图像分类网络,分别使用迁移学习和直接构建模型自己训练。找一个模型把使用过程写下来吧。 文章目录1、加载数据集并预处理2、加载模型和预训练权重文件3. 修改网络模型4. 设置网络参数5. 训练6、测试...
  • BERT模型—2.BERT模型训练与微调

    千次阅读 多人点赞 2021-07-20 15:22:03
    文章目录引言一、预训练语言模型1.为什么要进行预训练? 引言   本节将按照思维导图逐步了解BERT语言模型(基于transformer的网络结构)。 一、预训练语言模型   大规模的预训练语言模型模型参数量呈几何倍数...
  • train.py import torch from torch import nn from torch.nn import functional as F from torchvision import transforms from torch.utils.data import DataLoader,Dataset from torch import optim ...
  • pytorch(pytorch v0.1 这个是早期版本了)应该是深度学习框架...下面就使用pytorch预训练模型分类和特征提取,pytorch文档可以参考:pytorch docs , 模型是imagenet2012训练的标签可参考:imagenet2012 labels ,...
  • 什么叫训练模型

    千次阅读 2019-09-04 14:21:57
    马克-to-win @ 马克java社区:根据上面的计算过程可知,下图的神经网络模型果然比较符合现实情况。带游泳池的首先大概率属于高档房,其次价格也比较高。不带游泳池的 属于低档房,而且价格较低。 为什么同样的模型,...
  • 本文用于记录如何进行 PyTorch 的预训练模型的加载,模型的保存与读取,如何更新模型参数以及如何利用多 GPU 训练模型
  • 训练模型

    万次阅读 多人点赞 2019-04-26 10:03:12
    训练模型是深度学习架构,已经过训练以执行大量数据上的特定任务(例如,识别图片中的分类问题)。这种训练不容易执行,并且通常需要大量资源,超出许多可用于深度学习模型的人可用的资源,我就没有大批次GPU。...
  • keras深度学习之猫狗分类

    万次阅读 2022-02-09 10:34:51
    在计算机视觉图像分类中,在实践...在这里使用通用的猫狗样本进行二分类模型训练,在训练的过程中来研究怎样采取一些措施提高模型预测的准确率。 1 训练样本的下载 猫狗的分类样本采用kaggle上的猫狗样本,网址为: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 325,628
精华内容 130,251
关键字:

分类的训练模型