第七周:机器学习周报

摘要

这一周对CNN进行了理论上的学习还有代码上的学习,在理论上通过李宏毅的机器学习视频学习了CNN的理论知识,在代码实践上学会了如何搭建nn,并对基本的输入-卷积计算-输出过程进行了理解和实践。

Abstract

This week, I conducted theoretical and code learning on CNN. In theory, I learned the theoretical knowledge of CNN through Li Hongyi’s machine learning video. In code practice, I learned how to build NN and understood and practiced the basic input convolution calculation output process.

机器学习——神经卷积网络(CNN)

1. 基于Neuron理解CNN

我们用CNN最常见的就是影响分析,也就是我们之前常常讲的classification。
即通过输入一张图片,最后判断出这个图片是什么?
注意:输入的图片都是相同尺寸的(即需要进行预处理)
过程如下图所示:
其中Ŷ表示识别出物体各个种类的真实值,有多少维度就是有多少种可以识别出物品
通过Cross entropy算法,得到最终预测结果
在这里插入图片描述
复习Cross entropy算法
在这里插入图片描述
问题是怎么把一张影像当做一个模型的输入呢?
其实我们的图片都是三维的tensor(张量,其实就是是多维(>2维)数组)
在这里插入图片描述
1.其中一维代表图片的宽
2.另外一维代表图片的高
3.还有一维代表图片的channel的数目(3通道)
一张彩色的图片的每一个pixel都是由RGB三个颜色所组成的,所以这三个channel就代表了RGB三个颜色

然后就要把这一个三维的tensor把它拉直,拉直就可以丢到一个network里面去了
在这里插入图片描述
所以我们的network输入都是一个向量
所以只要能够把一张图片变成一个向量,我们就可以把它当做是network的输入。

但是怎么把这个三维的tensor变成一个向量呢?
在上面图片的例子里面有100×100×3个数字,所以这一张图片是由100×100×3个数字所组成的,把这些数字通通拿出来,排成一排就是一个巨大的向量。
这个向量可以作为的输入,而这个向量里面每一维它里面存的数值其实就是某一个pixel
(一个pixel有RGB三个颜色所组成,每个颜色都有一个数值代表这个颜色的强度。
所以在这个向量里面,每一维它的数值就代表了某一个位置的某一个颜色的强度。)

如果我们把这个向量当做输入,feature vector的长度就是100×100×3。
1、假设现在的第一层neuron(神经元)的数目有1000个
计算一下第一层总共有多少个weight?
我们每一个neuron跟输入的向量的每一个数值都会有一个weight,所以如果输入的向量长度是100×100×3有1000个neuron。也就是1000 * 100 * 100 * 3 = 3 * 10⁷,是一个非常庞大的数值

2、如果参数越多,会有什么样的问题呢?
虽然随着参数的增加,我们可以增加模型的弹性,也可以增加它的能力,但是我们也增加了overfitting的风险。
在这里插入图片描述
那我们怎么减少在做影像识别的时候避免使用这么多的参数呢?
基于影像的特性,我们其实不需要每一个neuron跟input的每一个dimension都有一个weight。
比如需要识别一只鸟,机器如果看到鸟嘴 、 鸟的眼睛、鸟的爪子 就可以判断这张图片是一张鸟了(这些称之为 critical pattern,关键图案

其实我们人在辨别物体的时候何尝不是通过辨别这些关键特征来进行判断的呢。
所以其实按照这样的思路,机器没有必要去看完一张完整的图片去再给出判断,只需要关注某些特征就可以做出判断,这会大大减少需要计算的参数。
如下图,这一些重要的pattern,比如鸟嘴、眼睛、鸟爪,并不需要看整张完整的图片才能够得到这些信息。所以这些neuron根本就不需要把整张图片当做输入,他们只需要把图片的一小部分当做输入就足以让他们侦测某些特别关键的pattern。
在这里插入图片描述

1.1 receptive field(感受野)

那怎么通过这个观察来设计我们的neural network呢?
在CNN里面有这样一个做法。它会设定一个区域,叫做receptive field(感受野)
每一个neuron都只关心自己的receptive feel里面发生的事情即可。
比如
先定义说这一个蓝色的neuron,他的负责范围就是这一个有333个数字的立方体的receptive field,那对这个蓝色receptive field来说,它只需要关心这一个小范围,不需要在意整张图片里面有什么东西。
在这里插入图片描述
怎么考虑这个蓝色负责的receptive field发生什么样的事情呢?
1、它要做的事情就是把这333个数值拉直变成一个长度是3×3×3即27维的向量
2、再把这27维的向量作为这个neuron的输入,这个neuron会给27维的向量的每一个dimension给定一个weight,所以这个neuron有333 = 27个weight,再加上bias的然后输出
3、这个输出再送给下一层的neuron当做输入
在这里插入图片描述
那这个receptive filed要怎么决定呢?
这个可以根据自己的情况决定
如下图:
1、不同的receptive field可以负责的不同的范围
蓝色的neuron就负责左上角这个范围,另外又有一个黄色的neuron负责右下角这个3×3×3的范围.

2、receptive filed彼此之间可以是重叠的
比如下图中的receptive filed,在这个地方它是绿色的neuron的范围跟蓝色的跟黄色的都有一些重叠的空间。

3、同个范围可以有多个不同的neuron,多个neuron可以去负责同一个receptive filed。

4、receptive field可以有大有小
因为毕竟pattern有大有小,有的在3×3的范围内就可以被侦测出来,有的pattern也许要11×11的范围才能被侦测出来

5、receptive field可以只考虑某些channel
因为上述的resettive field啊是rgb三个channel都考虑。
因为有些patterns在红色的圈头会出现、有些patterns在蓝色的圈头会出现,但在一般CNN里面,有这样子的做法但不经常这样考虑。

6、上面的receptive field都是正方形的,也可以是长方形的

这完全都是你自己设计的,是你自己定义的,你完全可以根据对问题的理解定义receptive field 与 neuron,所以对receptive filed 与 neuron的定义还可以有各式各样怪怪的想法
在这里插入图片描述
虽然你可以任意设计,最经典的的安排方式还是需要学习的
第一个就是会看所有的channel,然后同一个receptive field 会有一组neuron去负责(比如64个neuron为一组,每一个neuron负责发现一个特征)
我们在描述一个receptive field的时候,只要考虑它的高跟宽
这个高跟宽合起来叫做kernel size(卷积核),常见的receptive filed设定方式kernel size 是3×3
在这里插入图片描述

1.2 stride(步幅)

各个不同receptive field之间的关系是什么样呢?
下图中最左上角的这个receptive field 往右移一点,然后就制造一个新的范围
这个移动的量叫做stride(步幅)像下图的例子里面,stride = 2(具体由自己决定),但这个stride往往不会设太大,stride往往设1或2就可以了,因为我们希望这些receptive field之间是有重叠
假设receptive field完全没有重叠,会发生什么?
那有一个pattern正好出现在两个receptive field的交界上面,就会变成没有任何neuron发现这个pattern,那
可能会忽略掉这个patent。

所以我们希望receptive field彼此之间有高度的重叠。
在这里插入图片描述

1.3 padding(填充)

假设我们stride = 2,那第一个receptive field和第二个receptive field如下如所示,当到第三个receptive field就遇到一个问题了,它超出了影像的范围,怎么办呢?
超出范围就做padding(填充,填充的地方补0(不一定非要是0可以是其他值))
在这里插入图片描述
除了这个水平方向的移动,也会有垂直方向的移动
垂直的移动同样是按照stride的值来上下移动的
stride = 2,所以一个receptive field在这边垂直方向移动两格,就有制造一个新的receptive field你按照这个方式扫过整张图片。
在这里插入图片描述
以上是第一个简化fully connected的方式

说第二个方式前,先说一下我们观察到的东西
我们可以观察到同样的pattern会出现在图片的不同区域
比如下图中的鸟嘴,它可能出现在图片的左上角,也可能出现在图片的中间。
在这里插入图片描述
按照刚刚的方式一
以同样的出现在图片的不同的位置,似乎也不是太大的问题
因为出现在左上角的瞄准,它一定它落在某一个receptive field里面,又因为receptive field是盖满整个图片的,所以图片里面任何地方都在某个neuron的负责范围内。这些地方一定是某一个neuron的receptive field
所以假设在左上角的receptive field里面有一个neuron,它的工作就是侦测鸟嘴的话,那鸟嘴就会被侦测出来。
就算鸟嘴出现在中间也没有关系
因为一定在其中的某一个receptive field的范围里,那个receptive field其中的neurons有一个nuero它可以侦测鸟嘴的话,那出现在图片的中间也会被侦测出来。
在这里插入图片描述

1.4 filter(滤波器)

那么问题来了
这些侦测鸟嘴的neuron,他们做的事情其实是一样的,只是他们守备的范围是不一样
那我们真的需要每一个receptive field都去放一个侦测鸟嘴的neuron吗?
那每一个都需要的话,参数量就会过多了

那如果参数能够共享的话是不是就不用在每一个receptive field都设置一个这样的neuron了
所以方式二就是:
让不同receptive field的neuron他们共享参数

在这里插入图片描述
那共享参数是什么意思呢?
所谓共享参数就是这两个neuron它们的weight完全是一样的
如下图中:两个neuron负责的receptive field是不一样的,但是它们的参数(w₁、w₂、…)是一模一样的。
在这里插入图片描述
那有人可能就会问,它的参数是一模一样那它会不会输出永远都是一样的?
不会,因为他们的输入是不一样的。 这两个neuron的参数一模一样,但是他们负责的范围是不一样的,所以输出也不一样。
如下图所示x₁、x₂未必等于x₁’、x₂’
在这里插入图片描述
共享的方式可以由我们自己定义,但是常见的影像识别上面的共享的方法是怎么设定的还是需要学习的。
那我们刚才已经讲说每一个receptive field,它都有一组neurons(假设一组neurons比如有64个neuron),所以这个receptive field有64个neuron
那它们彼此之间会怎么共享参数呢?
如下图,有一样的颜色的neuron(代表这两个neuron共享一样的参数)
每一个receptive field的neuron都只有一组参数(就是一个receptive field的第一个neuron跟另外一个receptive field的第一个neuron共用参数,它的第二个neuron跟其他的receptive field第二个neuron共用参数,以此类推)
这些共享的参数有一个名字叫做filter(滤波器),所以这两个neuron他们共用同一组参数,这组参数就叫filter 1,第二个同颜色的两个neuron它们共用同一组参数,这组参数就叫filter 2以此类推。
在这里插入图片描述

1.5 convolution Layer(卷积层)

那我们来整理一下,我们学到了什么?
1、首先是fully connected network,它是弹性最大的。当我们强制一个neuron只能看一张图片里面的一个范围的时候,它的弹性是变小的。如果是fully connected的,他可以决定看整张图片还是只看一个范围就。如果他只想只看一个范围就把很多weight设成零,所以fully connected layer是由它自己决定,就是所谓的弹性大
2、但是因为我们不需要看整张图片,也许只要看图片的一小部分就可以侦测出重要的pattern,所以我们有了receptive field。但加上receptive field的概念以后意思就是就只能看一个小范围,所以加入receptive field以后,你的network的弹性是变小。
3、接下来我们还有参数共享
参数共享这件事又更进一步限制了network的弹性。原来其可以决定说这两个neuron的参数要是什么,每一个neuron可以各自有不同的参数,但是加入参数共享以后就意味着说某一些neuron无论什么参数都要一模一样,所以这又更增加了对neuron的限制。
而receptive field加上 parameters sharing就是convolution Layer(卷积层)
convolution Layer(卷积层) = receptive field(感受野) + parameters sharing(参数共享)
在这里插入图片描述
那有convolutional layer的network就叫Convolutional Neural Network就是CNN。
所以下图可以看出其实CNN它的bias比较大
它的model的bias比较大model bias大,不一定是坏事
因为当model bias小model的灵活度很高的时候,它比较容易overfitting,所以fully connected layer它可以做各式各样的事情,它可以有各式各样的变化,但是它可能没有办法在任何特定的任务上做好。

而convolutional layer它是专门为影像识别设计的,所以它在影像上仍然可以做得好。虽然它的model bias很大,但这个在影像上不是问题
但是如果它用在影像之外的任务,那你就要很小心了
在这里插入图片描述

2. 基于filter理解CNN

第二种方式是比较常见的教学理解方式(基于filter),具体如下:
什么叫做convolution layer?
如下图所示
convolutional layer就是里面有很多的filter,大小是3×3×channel
(channel就是是彩色图片的话就是rgb,channel = 3;如果是黑白的图片channel = 1。)
所以在这里convolution里面就是有一排的filter,每一个filter它都是一个3×3×channel这么大的tensor。
那每一个filter的作用就是要去图片里面捕获某一个pattern(这些pattern要在3×3×channel那么小的范围内)
在这里插入图片描述
那这些filter怎么去图片里面捕获pattern的呢?
下面用一个例子解释说明:
如下图:
假设channel = 1(黑白图)
假设这些filter的参数是已知的,filter就是一个一个的tensor(即tensor里面的数值已知)
在方式一中:实际上这些tensor里面的数值其实就是model里面的parameter(即w₁、w₂、…),是通过gradient descent找出来的
假设我们有一张6*6的黑白图
在这里插入图片描述
那么我们如何通过filter识别图像的pattern呢?
1、首先把这个filter里面的九个值跟左上角范围里面的九个值做相乘再相加
在这里插入图片描述
2、接下来这个filter本来在左上角,接下来就往右移一点,那这个移动的距离叫做stride(步幅),这里设stride = 1,所以往右移动一格(垂直方向同理)
在这里插入图片描述
3、再重复步骤1,算出结果
在这里插入图片描述
4、以此类推,得出如下结果
在这里插入图片描述
那接下来呢,我们把每一个filter都做重复的计算,结果如下:
filter 2:
在这里插入图片描述

2.1 Feature Map(特征图)

所以每一个filter都会给我们一群数字,如果我们有64个filter,我们就得到64群的数字。
这一群数字有一个名字叫做feature Map(特征图)

在这里插入图片描述
当我们把一张图片通过一个convolutional layer,其里面有一堆filter的时候,我们产生出来了一个Feature Map。
那假设convolutional layer里面,它有64个filter,那产生出来的这个feature map就有64组数字
(每一组在如上例子里面是4×4,第一个filter产生4×4个数字,第二个filter也产生4×4的数字…以此类推到64个filter都产生4×4的数字)
那这个feature map可以看成是另外一张新的图片,只是这个图片的channel啊不是rgb,这个图片的channel有64个
即本来一张图片channel = 3,通过一个convolution变成一张新的图片channel = 64。

在这里插入图片描述
convolutional layer是可以叠很多层的
那如果叠第二层要注意什么呢?
第二层的convolution里面也有一堆的filter,这堆filter的大小我们这边也设3×3。
那它的高度呢?
它的高度必须设为64
因为filter的高度就是它要处理的影像的channel数

所以跟刚才第一层的假设输入的影像是黑白的,channel = 1。那我们的filter的高度就是一输入的影像。如果是彩色的channel = 3,那filter的高度就是3。

那在第二层里面,我们也会得到一张图片,对第二个convolutional layer来说它的输入也是一张图片。那第二层图片的channel是多少?
这个图片的channel是64,这个64是前一个convolutional layer的filter数目。前一个convolutional layer它filter数目64,那输出以后就是64个channel,所以第二层想把这个图片当做输入,那filter的高度也得是64。
在这里插入图片描述
如果我们的的大小一直设3×3,会不会让我们的network没有办法看比较大范围的呢?
(顺便回答1.1中的卷积核默认大小3x3的问题)

其实不会
因为如果我们在第二层convolutional layer,我们的filter的大小一样设3×3
当我们看最左上角这个数值的时候,最左上角这个红色框框的数值在图片上其实是对应到红色范围。
当我们看最右下角这个红色框框数值的时候,右下角的数值在图像上其实对应到右下角红色框框范围。
所以当我们看这3×3的范围的时候,**看第一个convolutional layer的输出的这个feature map的3×3的范围的时候,我们在原来的影像上其实是考虑了一个5×5的范围。**所以虽然我们的filter只有3×3,但它在原来图片上考虑的范围是比较大的5×5。
只要你的network叠的越深,同样是3×3的大小的filter,它看的范围就会越来越大
所以network够深,你不用怕你检测不到比较大的pattern,它还是可以探测到比较大的patter的。
在这里插入图片描述
总结两种理解方式
我们在第一个方式里面说到了有一些neuron,这些neuron会共用参数,就是第二个理解方式里面的filter。
在这里插入图片描述
方式一中的share weight(共享参数)其实就是方式二中filter扫过一张图片,把filter扫过一张图片其实就是convolution,所以把filter扫过一张图片其实就是convolution。
在这里插入图片描述
总结如下:
在这里插入图片描述

3. Pooling(池化层)

那convolutional layer在做图像识别的时候其实还有第三个常用的东西,叫做Pooling(池化)
那Pooling是什么呢?
我们拿一张很大的图片做subsampling(二次采样)。比如,就是把一张图的偶数的color都去除,奇数的color都取出,图片变成为原来的四分之一,但是不会影响里面是什么东西。
如下图:
把一张大的图片缩小,这是一只鸟,这张小图片看起来还是一只鸟。
在这里插入图片描述
Pooling的行为都是固定好的,没有要根据data学任何东西(类似一个sigmoid函数)

3.1 Max Pooling

Pooling有很多版本,但是我们常见的版本是Max Pooling

我们刚才说每一个filter都产生一组数字
要做Pooling的时候,我们就把这些数字几个几个一组
如下图中就是2×2个一组
在这里插入图片描述
每一组里面选一个代表,在max pooling里面,我们选的代表就是最大的那一个
如下图:
为什么是选最大的那一个呢?
因为这是Max pooling规定的,当然也有mean pooling(取平均值)等等
也未必要2×2一组,自己可以决定4×4或者3×3一组也可以。
在这里插入图片描述
所以我们做完convolution以后,一般后面还会搭配pooling
pooling做的事情,就是把图片变小。
本来64个channel还是64个channel。(channel不变,pooling不改变channel)
但是会把图片变得小一点
在刚才的例子里面,本来4×4的图片经过pooling变成了2×2的一组

在实践上,一般就是convolution跟pooling交替使用
可能做几次convolution,做一次pooling,比如两次convolution,一次pooling。在这里插入图片描述
不过你可以想见说pooling和对于performance还是有不好的影响的,假设要侦测的是非常微小的东西,那使用pooling最终的效果肯定不好。

CNN的常见框架如下:
flatten就是把图像本来排成矩阵的样子的东西,拉直把所有的数值拉直变成一个向量
在这里插入图片描述

4. CNN的实际应用——下围棋

CNN最耳熟能详的应用,就是用来下围棋。
怎么用这个CNN来下围棋呢?
下围棋其实就是一个分类的问题,你的network的输入是棋盘上黑子跟白子的位置,你的输出就是下一步应该要落子的位置。
学习过后我们知道network的输入就是一个向量

那怎么把棋盘表示成一个向量呢?
棋盘上就是有19×19个位置嘛,那我们就把一个棋盘表示成一个19×19维的向量。
在这个向量里面,如果某一个位置。有一个黑子那个位置我们就填1,如果白子我们就填-1,如果没有子我们就填0
把这个向量输到一个network里面,然后就可以把下围棋当这个分类的问题叫这个network去预测,下一步应该落子的位置落在哪里最好。
在这里插入图片描述
所以下围棋就是一个有19×19个类别的分类的问题

这个问题可以用fully connected network解决,但是用CNN的效果更好,为什么用CNN的效果更好呢?
1、首先你完全可以把一个棋盘。看作是一张图片,一个棋盘可以看作是一个解析度19×19的图片,这个图片里面每一个像素就代表棋盘上一个可以落子的位置。

2、那channel呢?在阿尔法狗的原始论文里面,他告诉你说。每一个棋盘的位置,每一个棋盘上的pixel,它是用48个channel来描述。那至于为什么是这48个,那这个显然是围棋高手设计出来的。这个棋盘它就是19×19的解析度的图片,它的channel就是48。
但是为什么CNN可以用在下围棋上呢?
今天既然在下围棋,可以用CNN那意味着围棋跟影像有共同的特性。
那有什么共同的特性呢?
我们刚才讲说在图像上的第一个观察是很多重要的pattern,你只需要看小范围就知道了
下围棋是也是一样,举例来说,有一个pattern就算不用看整个棋盘的盘式都知道发生了什么事。
那其实在alpha go里面它的第一层的layer,它的filter的大小就是5×5,所以显然在设计这个network的人觉得棋盘上很多重要的pattern,也许看5×5的范围就可以知道。再来是我们说影像上的第二个观察是同样的pattern,可能会出现在不同的位置。
所以图像识别跟下围棋有很多共通之处。
除此之外:
Alpha Go的论文中可以看到
没有用pooling,所以不要看影像上面都有用pooling,就觉得pooling一定是好的
在下围棋的时候就是不适合用pooling,所以你要想清楚说你今天用一个network架构的时候,我这个network的架构到底代表什么意思,它适不适合用在我现在这个任务上。
在这里插入图片描述

Pytorch学习

1.神经网络的基本骨架——nn.Moudle的使用

神经网络的搭建,神经网络的搭建是一个非常重要的环节。
接下来我们对其进行学习。
任然是老样子,我们先进入pytorch官网查看用法,按照下图提示,找到orch.nn板块(nn是neural network(神经网络)的缩写)
在这里插入图片描述
在这里插入图片描述
然后我们找到NN中的Containers,这就是我们这一小节需要学习的内容。
通过Containers我们可以完成对神经网络的基本搭建,包括后面红色箭头都是CNN(Convolutional Neural Networks,神经卷积网络)里面非常重要的内容。
在这里插入图片描述
我们点击进入Containers,其中我们最重要的就是Module,其旁边的注释称其为最基本的类
在这里插入图片描述
点击进入Module进行查看,可以看到其用法
其中参数中的Module为父类
那么
什么是父类?分父类和子类有什么用
下面举个例子:
比如小时候我们买了的那些四驱儿童玩具车,难免会有自己DIY的想法比如,换个电池、换个马达…,但是怎么DIY都是基于这个原有的基础上修改的。相当于这个汽车就是一个父类,我们父类原来内容的基础上对其进行修改或者拓展,但又不影响父类的本身的内容(这里的父类相当于四驱车的框架)
子类的意义,其继承了父类的内容,并对其进行修改和拓展。相当于我用了你的框架,并在你的框架基础上衍生各种东西
下面的def,就是修改的东西
在这里插入图片描述
forward就是前向传播,类似与下图过程:
在这里插入图片描述
在这个示例中,我们可以看到在forward中
其进行了一次卷积操作跟非线性的处理,最后在return前又经过了一次卷积和非线性处理

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

接下来我们使用pycharm感受一下
以下代码的操作就是将input的数值+1,然后在输出

import torch
from torch import nn


class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()

    def forward(self, input):
        ouput = input + 1
        return ouput


neuralnetwork = NeuralNetwork()
x = torch.tensor(1.0)
output = neuralnetwork(x)
print(output)

在这里插入图片描述
Debug的过程如下,可以看到我们的input经过了neuralnetwork后+1,就打印了
在这里插入图片描述

2.卷积操作

我们经常说的CNN(卷积神经网络),那么到底什么是卷积呢?
我们先从官方文档入手,以代码的方式去理解
在这里插入图片描述
conv是convolution(卷积)的缩写
可以看到卷积也分维度,我们的图片是二维的,因此我们选择用conv2d进行操作。
在这里插入图片描述
我们可以看到API上有nn与nn.functional,他们之间的关系如下:
平时的使用,我们掌握nn即可
在这里插入图片描述
我们要深入了解,因此就要学习functional里面的内容。
看到functional中从卷积二维
我们可以看到parameters中包含:

  • input(输入):形状的输入张量。
  • output(输出):形状的过滤器。
  • bias(偏置值):形状的可选偏置张量。
  • stride(步幅):卷积内核的步幅。
  • padding(填充值):输入两侧的隐式填充。
  • dilation(膨胀值):内核元素之间的间距。
  • groups(组):将输入分成几组。
    在这里插入图片描述

2.1 stride

下面我们通过图像来理解卷积过程:
假设我们有以下55的输入图像,跟33的卷积核。
现在进行卷积运算(实际上就是把卷积核贴上去,对应位置相乘再相加):
在这里插入图片描述
当stride = 1时运算过程如下:
在这里插入图片描述
向下移动时,依然遵守stride = 1 的值移动。
如下图的对应位置相乘得 18
在这里插入图片描述
以此类推得到如下结果:
在这里插入图片描述
接下来我们通过代码去感受一下卷积操作

我们用以下格式来输入矩阵:
在这里插入图片描述
但是会出现如下图问题:

所以我们可以使用reshape函数解决这个问题,将其转换为须要的格式
在这里插入图片描述
可以看到修改过后,其格式就变为我们需要的。
在这里插入图片描述
输入如下代码:
调用conv2d,计算出output(padding和groups后面再说明用法,先使用默认值)

import torch
import torch.nn.functional as F

input = torch.tensor([[1, 2, 0, 3, 1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 3, 1, 1],
                      [2, 1, 0, 1, 1]])

kernel = torch.tensor([[1, 2, 1],
                       [0, 1, 0],
                       [2, 1, 0]])

input = torch.reshape(input, (1, 1, 5, 5))
kernel = torch.reshape(kernel, (1, 1, 3, 3))

print(input.shape)
print(kernel.shape)

output = F.conv2d(input, kernel, stride=1)
print(output)

在这里插入图片描述
当stride = 2 时,可以看到输出的结果不一样

拓展:
假设
输入图片(Input)大小为I*I
卷积核(Filter)大小为K*K
步长(stride)为S
填充(Padding)的像素数为P
那卷积层输出(Output)的特征图大小为多少呢?

O = ( I − K + 2 P ) S + 1 ,结果向下取整 {\color{Red} O= \frac{(I-K+2P)}{S} +1},结果向下取整 O=SIK+2P+1,结果向下取整

所以当stride = 2 、padding = 0时可以算出 ,output为[(5 - 3 + 0 ) / 2 ] + 1 = 2
在这里插入图片描述

2.2 padding

padding其实就可以理解为边界拓展
当padding为1时就会像上下左右各拓展一行,拓展的格子的值为0
在这里插入图片描述
在程序中就是:

output3 = F.conv2d(input, kernel, stride=1, padding=1)
print(output3)

经过公式的计算[(5-3+21)/1] +1 = 5,所以output大小为55
在这里插入图片描述
计算过程同上,把拓展的格子当作0计算即可。
在这里插入图片描述

总结

这一周对CNN(卷积神经网络)进行了学习,主要从理论和代码实践方面进行了前面基础部分的学习。在理论学习中,学会了两种方式理解CNN其中一种是基于Neuron,另外一种是基于filter。我们在第一个方式里面说到了有一些neuron,这些neuron会共用参数,就是第二个理解方式里面的filter。方式一中的share weight(共享参数)其实就是方式二中filter扫过一张图片,把filter扫过一张图片其实就是convolution,所以把filter扫过一张图片其实就是convolution。
在代码实践中,学会了nn.Moudle的使用,了解到网络框架通过父子类的定义完成基本的搭建,然后还学习了nn.functional中conv2d的内容,了解了卷积操作的基本原理,还学会了如何reshape对input和kernel的格式进行转换、如何使用stride、padding参数以及output大小与个参数的计算公式。
下一周计划继续学习李宏毅的机器学习视频,以及学习pytorch的CNN部分的卷积层、最大池化、非线性激活层等等的代码学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值