• 猫狗图像数据集上的深度学习模型性能对比


    LeNet模型简介

    1. LeNet

    LeNet-5由七层组成(不包括输入层),每一层都包含可训练权重。通过卷积、池化等操作进行特征提取,最后利用全连接实现分类识别,下面是他的网络结构示意图:
    在这里插入图片描述
    C:卷积层
    S:池化层
    F:全连接层
    输入为3232像素图片
    **(一)C1层-卷积层(5
    5)**
    有6个55的卷积核的卷积层(convolution),输入图片(3232)经过C1卷积层后输出特征图片大小为2828(32-5+1),这样可以防止输入图像的信息掉出卷积核边界。
    C1包含156个((5
    5+1)6)可训练参数(权重)和122304个((55+1)62828)连接。 通过取值共享我们只需要学习156各参数。
    (二)S2层-池化层(下采样层)
    将28
    28的6个特征图经过22的池化单元进行下采样后输出6个(1414)的特征图,相当于对特征进行了进一步的提取,下面是下采样过程:
    将S2中池化核(22)的四个输入相加,然后乘以可训练系数w(权重),然后加到可训练偏差b(bias),S1中包含可训练参数12个(26)和5880个((22+1)61414)连接。
    在这里插入图片描述

    (三) C3层-卷积层
    有16个55的卷积核的卷积层(convolution),输入特征图(1414)经过C31卷积层后输出特征图片大小为1010(14+5-1)。
    C3包含1516个(6
    (355+1)+6*(455+1)+3*(455+1)+1*(655+1))可训练参数(权重)和151600个((10101516)连接。
    在这里插入图片描述
    需要注意的是C3层与S2的层并不是全部连接C3,前6个特征图以S2中3个相邻的特征图子集为输入。接下来6个特征图以S2中4个相邻特征图子集为输入。然后的3个以不相邻的4个特征图子集为输入。最后一个将S2中所有特征图为输入。通过这种方式提取更多特征,连接的规则如下表所示:
    在这里插入图片描述

    (四) S4层-池化层(下采样层)
    将1010的16个特征图经过22的池化单元进行下采样后输出16个(55)的特征图,相当于对特征进行了进一步的提取,下面是下采样过程:
    将S4中池化核(2
    2)的四个输入相加,然后乘以可训练系数w(权重),然后加到可训练偏差b(bias),S1中包含可训练参数32个(216)和2000个((22+1)1655)连接。
    (五)C5层-卷积层
    有120个5
    5的卷积核的卷积层(convolution),输入图片(55)经过C5卷积层后输出特征图片大小为11(5-5+1),这样可以防止输入图像的信息掉出卷积核边界。
    C5包含48120 个 ((120*(1655+1))可训练参数(权重)和48120个((120*(1655+1))连接。
    在这里插入图片描述
    (六)F6层-全连接层
    F6完全连接到C5,输出84张特征图,征图大小与C5一样都是1×1。它有10164个可训练参数。这里84与输出层的设计有关。
    F6包含10164个((120+1)*84)可训练参数(权重)和10164个((120+1)84)连接。
    (七)OUTPUT层(输出层)
    Output层也是全连接层,与F6层的84张(1
    1)的特征图全连接,最后输出10个节点,分别代表数字0到9,且如果节点i的值为0,则网络识别的结果是数字i。

    2. AlexNet

    AlexNet网络结构相对简单,使用了8层卷积神经网络,前5层是卷积层,剩下的3层是全连接层,具体如下所示。
    在这里插入图片描述

    从上图看,在网络设计上其实并非如上图所示,上图包含了GPU通信的部分。这是由当时GPU内存的限制引起的,作者使用两块GPU进行计算,因此分为了上下两部分。但是,以目前GPU的处理能力,单GPU足够了,因此其结构图可以如下所示:
    在这里插入图片描述

    值得注意的一点:原图输入224 × 224,实际上进行了随机裁剪,实际大小为227 × 227。
    2.1 卷积层C1
        C1的基本结构为:卷积–>ReLU–>池化
    卷积:输入227 × 227 × 3,96个11×11×3的卷积核,不扩充边缘padding = 0,步长stride = 4,因此其FeatureMap大小为(227-11+0×2+4)/4 = 55,即55×55×96;
    激活函数:ReLU;
    池化:池化核大小3 × 3,不扩充边缘padding = 0,步长stride = 2,因此其FeatureMap输出大小为(55-3+0×2+2)/2=27, 即C1输出为27×27×96(此处未将输出分到两个GPU中,若按照论文将分成两组,每组为27×27×48);
    2.2 卷积层C2
        C2的基本结构为:卷积–>ReLU–>池化
    卷积:输入27×27×96,256个5×5×96的卷积核,扩充边缘padding = 2, 步长stride = 1,因此其FeatureMap大小为(27-5+2×2+1)/1 = 27,即27×27×256;
    激活函数:ReLU;
    池化:池化核大小3 × 3,不扩充边缘padding = 0,步长stride = 2,因此其FeatureMap输出大小为(27-3+0+2)/2=13, 即C2输出为13×13×256(此处未将输出分到两个GPU中,若按照论文将分成两组,每组为13×13×128);
    2.3 卷积层C3
        C3的基本结构为:卷积–>ReLU。注意一点:此层没有进行MaxPooling操作。
    卷积:输入13×13×256,384个3×3×256的卷积核, 扩充边缘padding = 1,步长stride = 1,因此其FeatureMap大小为(13-3+1×2+1)/1 = 13,即13×13×384;
    激活函数:ReLU,即C3输出为13×13×384(此处未将输出分到两个GPU中,若按照论文将分成两组,每组为13×13×192);
    2.4 卷积层C4
        C4的基本结构为:卷积–>ReLU。注意一点:此层也没有进行MaxPooling操作。
    卷积:输入13×13×384,384个3×3×384的卷积核, 扩充边缘padding = 1,步长stride = 1,因此其FeatureMap大小为(13-3+1×2+1)/1 = 13,即13×13×384;
    激活函数:ReLU,即C4输出为13×13×384(此处未将输出分到两个GPU中,若按照论文将分成两组,每组为13×13×192);
    2.5 卷积层C5
        C5的基本结构为:卷积–>ReLU–>池化
    卷积:输入13×13×384,256个3×3×384的卷积核,扩充边缘padding = 1,步长stride = 1,因此其FeatureMap大小为(13-3+1×2+1)/1 = 13,即13×13×256;
    激活函数:ReLU;
    池化:池化核大小3 × 3, 扩充边缘padding = 0,步长stride = 2,因此其FeatureMap输出大小为(13-3+0×2+2)/2=6, 即C5输出为6×6×256(此处未将输出分到两个GPU中,若按照论文将分成两组,每组为6×6×128);
    2.6 全连接层FC6
        FC6的基本结构为:全连接–>>ReLU–>Dropout
    全连接:此层的全连接实际上是通过卷积进行的,输入6×6×256,4096个6×6×256的卷积核,扩充边缘padding = 0, 步长stride = 1, 因此其FeatureMap大小为(6-6+0×2+1)/1 = 1,即1×1×4096;
    激活函数:ReLU;
    Dropout:全连接层中去掉了一些神经节点,达到防止过拟合,FC6输出为1×1×4096;
    2.7 全连接层FC7
        FC7的基本结构为:全连接–>>ReLU–>Dropout
    全连接:此层的全连接,输入1×1×4096;
    激活函数:ReLU;
    Dropout:全连接层中去掉了一些神经节点,达到防止过拟合,FC7输出为1×1×4096;
    2.8 全连接层FC8
        FC8的基本结构为:全连接–>>softmax
    全连接:此层的全连接,输入1×1×4096;
    softmax:softmax为1000,FC8输出为1×1×1000;

    3. VGGNet

    VGGNet模型有A-E五种结构网络,深度分别为11,11,13,16,19.实际使用的网络包括VGG16和VGG19.本篇文章主要介绍VGG16,并分享VGG16的Keras实现。下图为VGGNet的结构说明。
    在这里插入图片描述

    从图中可以看出VGGNet的一个特点就是简单,通过对卷积的堆叠,在卷积之后进行pooling处理构成一个block,共5个block.
    通过对上述的分析,VGG16共包含:
    13个卷积层,用conv3-xxx表示;
    5个池化层,用maxpool表示;
    3个全连接层,用FC-xxx表示。
    由于VGG16模型中只有13个卷积层和3个全连接层能产生权重参数,故VGG16的16来自于13+3。

    4. ResNet20

    ResNet旨在解决网络加深后训练难度增大的现象。其提出了residual模块,包含两个3×3卷积和一个shortcut connection。shortcut connection可以有效缓解反向传播时由于深度过深导致的梯度消失现象,这使得网络加深之后性能不会变差。短路连接是深度学习又一重要思想,除计算机视觉外,短路连接也被用到了机器翻译、语音识别/合成领域。此外,具有短路连接的ResNet可以看作是许多不同深度而共享参数的网络的集成,网络数目随层数指数增加。
    ResNet的关键点是:
    利用残差结构让网络能够更深、收敛速度更快、优化更容易,同时参数相对之前的模型更少、复杂度更低
    ResNet大量使用了批量归一层,而不是Dropout。
    对于很深的网络(超过50层),ResNet使用了更高效的瓶颈(bottleneck)结构极大程度上降低了参数计算量。

    5. ResNet50

    block_sizes=[3, 4, 6, 3]指的是stage1(first pool)之后的4个layer的block数, 分别对应res2, res3, res4, res5。
    每一个layer的第一个block在shortcut上做conv+BN, 即Conv Block
    inputs: (1, 720, 1280, 3)
    initial_conv:
    conv2d_fixed_padding()
    1. kernel_size=7, 先做padding(1, 720, 1280, 3) -> (1, 726, 1286, 3)
    2. conv2d kernels=[7, 7, 3, 64], stride=2, VALID 卷积. 7x7的kernel, padding都为3, 为了保证左上角和卷积核中心点对其
    (1, 726, 1286, 3) -> (1, 360, 640, 64)
    3. BN, Relu (只有resnetv1在第一次conv后面做BN和Relu)
    initial_max_pool:
    k=3, s=2, padding=‘SAME’, (1, 360, 640, 64) -> (1, 180, 320, 64)
    以下均为不使用bottleneck的building_block
    block_layer1:
    (有3个block, layer间stride=1(上一层做pool了), 64个filter, 不使用bottleneck(若使用bottleneck 卷积核数量,需乘4))
    1. 第一个block:
    Conv Block有projection_shortcut, 且strides可以等于1或者2
    Identity Block没有projection_shortcut, 且strides只能等于1
    inputs = block_fn(inputs, filters, training, projection_shortcut, strides, data_format)
    shortcut做[1, 1, 64, 64], stride=1的conv和BN, shape不变
    然后和主要分支里input做3次卷积后的结果相加, 一起Relu, 注意block里最后一次卷积后只有BN没有Relu
    input: conv-bn-relu-conv-bn-relu-conv-bn 和shortcut相加后再做relu
    shortcut: conv-bn
    shortcut: [1, 1, 64, 64], s=1, (1, 180, 320, 64) -> (1, 180, 320, 64)
    input做两次[3, 3, 64, 64], s=1的卷积, shape不变(1, 180, 320, 64) -> (1, 180, 320, 64) -> (1, 180, 320, 64)
    inputs += shortcut, 再relu
    2. 对剩下的2个block, 每个block操作相同:
    inputs = block_fn(inputs, filters, training, None, 1, data_format)
    shortcut直接和input卷积结果相加, 不做conv-bn
    input做两次[3, 3, 64, 64], s=1的卷积, shape不变(1, 180, 320, 64) -> (1, 180, 320, 64) -> (1, 180, 320, 64)
    inputs += shortcut, 再relu
    block_layer2/3/4同block_layer1, 只是每个layer的identity block数量不同, 卷积核数量和layer间stride也不同, 不过仍然只有第一个conv block的shortcut做conv-bn
    block_layer2: 4个block, 128个filter, layer间stride=2 (因为上一层出来后没有pool)
    1. 第一个block:
    对shortcut做kernel=[1, 1, 64, 128], s=2的conv和BN, (1, 180, 320, 64) -> (1, 90, 160, 128)
    对主要分支先做kernel=[3, 3, 64, 128], s=2的卷积, padding=‘VALID’, (1, 180, 320, 64) -> (1, 90, 160, 128)
    再做kernel=[3, 3, 128, 128], s=1的卷积, padding=‘SAME’, (1, 90, 160, 128) -> (1, 90, 160, 128)
    2. 剩下的3个block, 每个block操作相同:
    shortcut不操作直接和结果相加做Relu
    对主要分支做两次[3, 3, 128, 128], s=1的卷积, padding=‘SAME’, (1, 90, 160, 128) -> (1, 90, 160, 128) -> (1, 90, 160, 128)
    block_layer3: 6个block, 256个filter, layer间stride=2
    1. 第一个block:
    对shortcut做kernel=[1, 1, 128, 256], s=2的conv和BN, (1, 90, 160, 128) -> (1, 45, 80, 256)
    对主要分支先做kernel=[3, 3, 128, 256], s=2的卷积, padding=‘VALID’, (1, 90, 160, 128) -> (1, 45, 80, 256)
    再做kernel=[3, 3, 256, 256], s=1的卷积, padding=‘SAME’, (1, 45, 80, 256) -> (1, 45, 80, 256)
    2. 剩下的5个block, 每个block操作相同:
    shortcut不操作直接和结果相加做Relu
    对主要分支做两次[3, 3, 256, 256], s=1的卷积, padding=‘SAME’, (1, 45, 80, 256) -> (1, 45, 80, 256) -> (1, 45, 80, 256)
    block_layer4: 3个block, 512个filter, layer间stride=2
    1. 第一个block:
    对shortcut做kernel=[1, 1, 256, 512], s=2的conv和BN, (1, 45, 80, 256) -> (1, 23, 40, 512)
    对主要分支先做kernel=[3, 3, 256, 512], s=2的卷积, padding=‘VALID’, (1, 45, 80, 256) -> (1, 23, 40, 512)
    再做kernel=[3, 3, 512, 512], s=1的卷积, padding=‘SAME’, (1, 23, 40, 512) -> (1, 23, 40, 512)
    2. 剩下的2个block, 每个block操作相同:
    shortcut不操作直接和结果相加做Relu
    对主要分支做两次[3, 3, 512, 512], s=1的卷积, padding=‘SAME’, (1, 23, 40, 512) -> (1, 23, 40, 512)
    avg_pool, 7*7
    FC, output1000
    softmax
    输出prediction
    Resnet-18,Resnet-50,等等,不过是层数不一罢了

    6. GoogLeNet

    googlenet并没有采用之前的sequential的conv,pooling,fc这样的序列的结构,而是在串行中引入了并行操作,使得每个并行的操作都成为了一个模块,每个模块就叫做一个inception,每个inception里包含了不同大小的卷积核和池化层。因此具有更好的表达能力,并且为了在应用inception这种模块的时候降低运算量,引入了bottleneck机制。

    7. MobileNet

    mobilenet是Google提出的。
    优点:体积小,计算量小,适用于移动设备的卷积神经网络。
    可以实现分类/目标检测/语义分割;
    小型化:
    卷积核分解,使用1xN和Nx1的卷积核替换NxN的卷积核。
    采用bottleneck结构 ,以SqueezeNet为代表
    以低精度浮点数保存,例如Deep Compression
    冗余卷积核剪枝及哈弗曼编码。
    MobileNet的网络结构如表所示。首先是一个3x3的标准卷积,然后后面就是堆积depthwise separable convolution,并且可以看到其中的部分depthwise convolution会通过strides=2进行down sampling。然后采用average pooling将feature变成1x1,根据预测类别大小加上全连接层,最后是一个softmax层。如果单独计算depthwise
    在这里插入图片描述

    convolution和pointwise convolution,整个网络有28层(这里Avg Pool和Softmax不计算在内)。我们还可以分析整个网络的参数和计算量分布,如表2所示。可以看到整个计算量基本集中在1x1卷积上,如果你熟悉卷积底层实现的话,你应该知道卷积一般通过一种im2col方式实现,其需要内存重组,但是当卷积核为1x1时,其实就不需要这种操作了,底层可以有更快的实现。对于参数也主要集中在1x1卷积,除此之外还有就是全连接层占了一部分参数。
    MobileNet到底效果如何,这里与GoogleNet和VGG16做了对比,如表3所示。相比VGG16,MobileNet的准确度稍微下降,但是优于GoogleNet。然而,从计算量和参数量上MobileNet具有绝对的优势。
    在这里插入图片描述

    8. DenseNet

    DenseNet模型,它的基本思路与ResNet一致,也是建立前面层与后面层的短路连接,不同的是,但是它建立的是前面所有层与后面层的密集连接。
    DenseNet还有一个特点是实现了特征重用。
    这些特点让DenseNet在参数和计算成本更少的情形下实现比ResNet更优的性能。
    在这里插入图片描述

    9. EfficientNet

    EfficientNet系列模型的主要结构要从该模型的构建⽅法说起。该模型的构建⽅法主要包括以下2个步骤:
    (1)使⽤强化学习算法实现的MnasNet模型⽣成基线模型EfficientNet-B0。
    (2)采⽤复合缩放的⽅法,在预先设定的内存和计算量⼤⼩的限制条件下,对EfficientNet-B0模型的深度、宽度(特征图的通道数)、
    图⽚⼤⼩这三个维度都同时进⾏缩放,这三个维度的缩放⽐例由⽹格搜索得到。最终输出了EfficientNet模型。

    10. Inception

    Inception v1的网络,将1x1,3x3,5x5的conv和3x3的pooling,堆叠在一起,一方面增加了网络的width,另一方面增加了网络对尺度的适应性
    在这里插入图片描述

    如图1所示是最原始的版本,所有的卷积核都在上一层的所有输出上来做,5×5的卷积核所需的计算量就太大,造成了特征图厚度很大。为了避免这一现象提出的inception具有如下结构,在3x3前,5x5前,max pooling后分别加上了1x1的卷积核起到了降低特征图厚度的作用,也就是Inception v1的网络结构。
    Inception v2模型
    一方面了加入了BN层,减少了Internal Covariate Shift(内部neuron的数据分布发生变化),使每一层的输出都规范化到一个N(0, 1)的高斯;
    另外一方面学习VGG用2个3x3的conv替代inception模块中的5x5,既降低了参数数量,也加速计算;
    在这里插入图片描述

    使用3×3的已经很小,那么更小的虽然能使得参数进一步降低,但是不如另一种方式更加有效,就是Asymmetric方式,即使用1×3和3×1两种来代替3×3的卷积核。这种结构在前几层效果不太好,但对特征图大小为12~20的中间层效果明显 。
    在这里插入图片描述
    https://baike.baidu.com/pic/Inception%E7%BB%93%E6%9E%84/22761220/0/91529822720e0cf31eb4102b0646f21fbf09aa9b?fr=lemma&ct=single
    Inception v3模型
    V3一个最重要的改进是分解(Factorization),将7x7分解成两个一维的卷积(1x7,7x1),3x3也是一样(1x3,3x1),这样的好处,既可以加速计算(多余的计算能力可以用来加深网络),又可以将1个conv拆成2个conv,使得网络深度进一步增加,增加了网络的非线性,还有值得注意的地方是网络输入从224x224变为了299x299,更加精细设计了35x35/17x17/8x8的模块 [3] 。
    Inception v4模型
    v4研究了Inception模块结合Residual Connection能不能有改进。发现ResNet的结构可以极大地加速训练,同时性能也有提升,得到一个Inception-ResNet v2网络,同时还设计了一个更深更优化的Inception v4模型,能达到与Inception-ResNet v2相媲美的性能 [4] 。https://baike.baidu.com/pic/Inception%E7%BB%93%E6%9E%84/22761220/0/d62a6059252dd42af31a5f7b0f3b5bb5c8eab8cb?fr=lemma&ct=singlehttps://baike.baidu.com/pic/Inception%E7%BB%93%E6%9E%84/22761220/0/6a600c338744ebf8ccb538efd5f9d72a6159a71e?fr=lemma&ct=single

    预训练模型的加载

    # 加载模型
    import tensorflow as tf
    IMG_SHAPE = (IMG_SIZE, IMG_SIZE, 3)
    
    # 以 MobileNet V2为基础模型。
    base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                                   include_top=False,
                                                   weights='imagenet')
    feature_batch = base_model(image_batch)
    # 修改模型
    
    global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
    
    # 分类层, Dense中的参数为输出的类别数量,这里分1类,即只识别狗。
    prediction_layer = keras.layers.Dense(1)
    # 加载模型
    import tensorflow as tf
    IMG_SHAPE = (IMG_SIZE, IMG_SIZE, 3)
    # 以 MobileNet V2为基础模型。
    base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                                   include_top=False,
                                                   weights='imagenet')
    feature_batch = base_model(image_batch)
    # 修改模型
    
    global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
    
    # 分类层, Dense中的参数为输出的类别数量,这里分1类,即只识别狗。
    prediction_layer = keras.layers.Dense(1)
    
    model = tf.keras.Sequential([
      base_model,
      global_average_layer,
      prediction_layer
    ])
    base_learning_rate = 0.0001  # 学习率,代表每次优化的大小,一般1e-3与1e-4比较合适
              
    initial_epochs = 5  # 训练的轮数
    
    model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=base_learning_rate),
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    
    model.fit(train_batches,
              epochs=initial_epochs,
              validation_data=validation_batches)
    
    weight_path = os.path.join('cat_vs_dogs')
    model.save_weights(weight_path)  # 保存模型参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    猫狗数据集的加载

    import tensorflow_datasets as tfds
    tfds.disable_progress_bar()
    
    SPLIT_WEIGHTS = (8, 1, 1)  # 将数据集按8:1:1分为训练集,验证集,测试集。
    splits = tfds.Split.TRAIN.subsplit(weighted=SPLIT_WEIGHTS)
    
    # 加载数据集
    (raw_train, raw_validation, raw_test), metadata = tfds.load('cats_vs_dogs', 
    															split=list(splits),with_info=True, 
    															as_supervised=True)
    
    
    print(raw_train)
    print(raw_validation)
    print(raw_test)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    模型对比

    from PIL import Image
    
    weight_path = os.path.join('cat_vs_dogs')
    model.load_weights(weight_path)
    
    
    def format_test(image):
      #对输入做预处理
      image = np.array(image)
      image = tf.cast(image, tf.float32)
      image = (image/127.5) - 1
      image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE))
      return image
    
    image = Image.open("dog2.jpg")
    plt.imshow(image)
    test_image = format_test(image)
    test_image = test_image[np.newaxis,:,:,:]  # 给输入增加一个维度变为[1, h, w, c], 这里batch为1
    
    pred = model.predict(test_image)
    print(pred)
    
    # 结果大于0为狗,小于0为猫
    pred[pred>0]=1
    pred[pred<=0]=0
    print(pred)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    结果与对比分析

    结果中的predict为[batch, 1]维数组,在文章的例子中,batch取1,所以一次训练一张图。同时,由于二分类可以只识别狗,概率大于0的是狗,小于0的是猫, 这是模型中的分类层决定的。
    结果:
    在这里插入图片描述
    在这里插入图片描述

    出现的问题及解决方法

    1.产生过拟合 降低过拟合:增加数据集的规模;使模型本身简单化;正则化处理。数据:扩充数据集。训练模型:可以使用droupout,L2正则化,BN,适当增大学习率或减少训练轮次等方式进行改善。
    2. 在模型训练代码执行时,我们可能会遇到could not import PIL.Image. 的错误
    这是需要使用pip install pillow下载pillow包,并且在训练数据代码前添加
    from IPython.display import display
    from PIL import Image
    3. 对数据做数据增强以使模型适应数据中不存在但实际中会存在的情况。
    4. 进行误差分析,统计下验证集或测试集中错误样本的原因,根据不同情况再去整理数据和改善训练方案。
    5. 可以尝试每轮进行训练和验证,并根据最优验证集精度保存模型。
    6. 简单的CNN模型的损失会比较大,可以增加模型复杂度、增加数据量、进行数据增强、调整训练集和验证集的比例并观察验证集精度,直至验证集精度趋于稳定;

    总结

    应该把握二分类和多分类的相同与不同点,明确训练集、验证集和测试集的对模型精度的作用;深度学习模型的精度与模型的复杂度、数据量、正则化、数据扩增等因素直接相关;深度学习原理少但实践性非常强,许多的模型的验证只能通过训练来完成;深度学习有众多的网络结构和超参数,在优化的过程中需要反复调整参数不断尝试;初步阶段可以构建简单的CNN模型,熟悉跑通训练、验证和预测的流程;数据增强:利用多种数字图像处理方法(旋转,剪切,错切,缩放,翻转,边缘填充)生成可信图像. 其目标是,模型在训练时不会两次查看完全相同的图像。这让模型能够观察到数据的更多内容,从而具有更好的泛化能力。掌握了基本的CV,学会了一些数据处理的基本操作,包括对文件的处理。
    欢迎大家加我微信交流讨论(请备注csdn上添加)
    在这里插入图片描述

  • 相关阅读:
    AVR汇编(五):算术和逻辑指令
    Ganglia python metric扩展
    2022杭电多校七 1007-Weighted Beautiful Tree(树形DP)
    1分钟搞定跨境支付!什么GPT,Calude2不在话下!
    程序员内功-设计模式篇
    【JVM基础】程序计数器
    【服务器数据恢复】戴尔某型号服务器raid故障的数据恢复案例
    ConstraintLayout新手玩家避坑指南
    破局存量客群营销,试一下客户分群管理(含聚类模型等实操效果评估)
    利用大模型&知识图谱技术,告别繁重文案,实现非结构化数据高效管理
  • 原文地址:https://blog.csdn.net/weixin_45962068/article/details/125495082