CNN属于网络架构的一种,其一般被用于影像领域。

如何去做图像分类

图片在计算机中的存储通常是以3维张量来进行的。例如一张图片是100像素*100像素,每个像素由RGB3个channel组成(这个数值代表这个颜色的强度);那么要表示这张图片就需要31001003\cdot100\cdot100个数据。我们将这些数据做成应该向量作为神经网络的输入。

那么就会面临一个问题:例如第一层的神经元共1000个,输入向量为31001003\cdot100\cdot100个,那么光第一层所需要的weight数量就高达31001001000=31073\cdot100\cdot100\cdot1000=3\cdot10^7个,这样会拖慢训练进度,还容易造成过拟合。

因此我们需要进行优化:

  • 和人眼一样,图片分类时机器也只需要关注这张图片中最关键的部分就可以了。因此每个神经元的输入不需要是完整的图片。

    image-20241206183628370

    我们为每个神经元分配一个Receptive field,该神经元只需要输入该Receptive field中的数据即可。Receptive field之间可以重叠,甚至可以多个神经元共用一个Receptive field。

    在设计Receptive field时,其可以有不同的大小(不一定要是3×33\times3的,n×nn\times n的都行);可以只看一个channel(比如只看RED);也可以是长方形;甚至不相连都行,关键是要看图片是啥样的,图片的关键在哪里。

    经典的设计方法是这样的:

    • 使用全部的channel,field大小一般取正方形(3×33\times 3比如)

    • 每个Receptive field对应多个神经元(例如64个、128个这种)

    • 每两个Receptive field间有重叠部分,以最左上角的Receptive field为基准,向右或向下移动stride个单位(stride一般取1或2,也是一个超参数)。如此以保证当图像特征出现在中间时能有神经元关注这一块。

    • 由于是3×33\times 3,所以肯定会有突出的几块,这些采用padding进行处理,例如取0、取平均这种

      image-20241207201249863
  • 对不同的图片而言,虽然是相同的特征,但是该特征分布在两张图片的不同位置,而这两种位置会对应两组不同的神经元。这两组神经元的参数是相似的,因此可以进行参数共享来减小总参数量。

    image-20241207201937248

    上图中的两个神经元,其weight参数完全一样。

    当然,如果Receptive field相同的神经元之间没必要共享参数,因为那样搞的话输出都是一样的了。

    经典的设计方法是这样的:

    image-20241207202644836

    这里颜色相同的神经元代表共享参数的神经元,依次记作filter xx这样子。

CNN的训练流程是什么样的?

image-20241207205558864

Convolution卷积层:假设我们已经通过梯度下降得到了每一个神经元filter的权重。然后将filter的权重与图片数据各项相乘并相加。

image-20241208161450021

在上图中,filter的斜线上全是1,就代表在图片上扫的时候,碰到同样的形状时,产生的值最大。

然后,对于每一个filter都搞相同的操作:

image-20241208164505085

上图中,有几个filter就代表会有多少层这样的结果数据。我们把这些结果数据称为Feather Map。假设我们这一层卷积层有64个神经元,那么产生的Feather Map就会有64个channel,我们可以把这个Feather Map也看作是一个“图片”。

我们可以把这个Feather Map再扔进新的卷积层中,让这个新“图片”再和新的filter作用,注意这里的filter的channel数应该与Feather Map的channel数相同。

Pooling层:我们对原来的图片进行抽样,例如取图片中所有的偶数行、奇数列这样子,图片大小变为原来的14\frac{1}{4},但是并不会影响识别结果。

在做Pooling时,我们会将由每一个filter产生的数字几个几个分组:

image-20241208181327023

然后我们就需要在每个分组中选一个“代表”来表示这一组。以Max Pooling这种方法为例,就会取每个分组中的最大值(当然也会有Average Pooling、Min Pooling这种)

image-20241208181517793

我们通常会在卷积层后使用Pooling(交替使用),可以缩小处理数据的大小:

image-20241208181647391

当然,Pooling会造成信息损失,并不是必要的。如果要侦测微小的特征或者算力够够,不加Pooling是应该的。

HM3

Medium

首先给训练管道加上了数据增强操作(这里要注意不能增强过度),然后将训练epoch加了一点。

1
2
3
4
5
6
7
8
9
10
11
train_tfm = transforms.Compose(
[
transforms.Resize((128, 128)),
transforms.RandomHorizontalFlip(p=0.5),#随机水平翻转
transforms.RandomRotation(degrees=30),#随机旋转
transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),#随机颜色变换
transforms.RandomResizedCrop(size=(128, 128), scale=(0.8, 1.0)),#随机裁剪
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),#标准化
]
)