菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
232
0

CNN

原创
05/13 14:22
阅读数 41890

参考博文:

https://www.cnblogs.com/further-further-further/p/10430073.html

https://www.cnblogs.com/TimVerion/p/11396882.html

 

 

注:
1) 窗口滑动,与卷积核对应相乘;
2) 卷积核个数 = 输出结果的个数;
3) 输出窗口的大小(即输出矩阵的维度) = (输入窗口宽 - 卷积核宽 + 2*pad)/2 + 1;

 

  卷积函数代码实现:

 1 def conv_fun(cache):
 2     x, w, b = cache["a"], cache["w"], cache["b"]
 3     pad, stride = cache["pad"], cache["stride"]
 4     N, C, H, W = x.shape
 5     F, C, HH, WW = w.shape
 6     # numpy提供的可以填充0的api,constant代表用一样的值填充前两维不填,后两维各自填充pad行
 7     x_padded = np.pad(x, ((0, 0), (0, 0), (pad, pad), (pad, pad)), mode='constant')
 8     H_new = int((H + 2 * pad - HH) / stride) + 1
 9     W_new = int((W + 2 * pad - WW) / stride) + 1
10     s = stride
11     out = np.zeros((N, F, H_new, W_new))
12     for i in range(N):  # ith image
13         for f in range(F):  # fth filter
14             for j in range(H_new):
15                 for k in range(W_new):
16                     out[i, f, j, k] = np.sum
17                     (x_padded[i, :, j * s:(HH + j * s), k * s:(WW + k * s)] * w[f]) +b[f]
18 
19     return out

 

 1     # 前向池化
 2     def max_pool_forward(cache):
 3         x, HH, WW, s = cache["net"], cache["HH"], cache["WW"], cache["s"]
 4         N, C, H, W = x.shape
 5         H_new = 1 + int((H - HH) / s)
 6         W_new = 1 + int((W - WW) / s)
 7         out = np.zeros((N, C, H_new, W_new))
 8         for i in range(N):
 9             for j in range(C):
10                 for k in range(H_new):
11                     for l in range(W_new):
12                         # 定位到某个窗口
13                         window = x[i, j, k * s:HH + k * s, l * s:WW + l * s]
14                         # 找到该窗口的最大值,然后赋值
15                         out[i, j, k, l] = np.max(window)
16         return out

1 #全连接代码实现:
2 def fc(net, w, b):
3     N = net.shape[0]
4     # 把每个像素提取出来
5     x_row = net.reshape(N, -1)
6     out = np.dot(x_row, w) + b
7     return out

 


一:卷积层工作原理

卷积层的作用:就是提取图片每个小部分里具有的特征。

  假定我们有一个尺寸为6*6 的图像,每一个像素点里都存储着图像的信息。我们再定义一个卷积核(相当于权重),用来从图像中提取一定的特征。卷积核与数字矩阵对应位相乘再相加,得到卷积层输出结果。

(429 = 181+540+511+550+1211+750+351+240+204*1)

  卷积核的取值在没有以往学习的经验下,可由函数随机生成,再逐步训练调整;

  当所有的像素点都至少被覆盖一次后,就可以产生一个卷积层的输出(下图的步长为1)

  机器一开始并不知道要识别的部分具有哪些特征,是通过与不同的卷积核相作用得到的输出值,相互比较来判断哪一个卷积核最能表现该图片的特征——比如我们要识别图像中的某种特征(比如曲线),也就是说,这个卷积核要对这种曲线有很高的输出值,对其他形状(比如三角形)则输出较低。卷积层输出值越高,就说明匹配程度越高,越能表现该图片的特征。

  注:

    1、权重矩阵 'WEIGHT' 称为卷积核(convolution kernel);

    2、其覆盖位置称为感受野(receptive field); 

    3、参数共享; 

    4、滑动的像素数量叫做步长(stride); 

 

  卷积层具体工作过程:比如我们设计的一个卷积核如下左,想要识别出来的曲线如下右:

  现在我们用上面的卷积核,来识别这个简化版的图片——一只漫画老鼠:

  当机器识别到老鼠的屁股的时候,卷积核与真实区域数字矩阵作用后,输出较大:6600;

  而用同一个卷积核,来识别老鼠的耳朵的时候,输出则很小:0;

  我们就可以认为:现有的这个卷积核保存着曲线的特征匹配识别出来了老鼠的屁股是曲线的。我们则还需要其他特征的卷积核,来匹配识别出来老鼠的其他部分。卷积层的作用其实就是通过不断的改变卷积核,来确定能初步表征图片特征的有用的卷积核是哪些,再得到与相应的卷积核相乘后的输出矩阵

  注:以卷积核的边还是中心点作为开始/结束的依据,决定了卷积的补齐(padding)方式。如下左图是valid方式(这种方式新的矩阵维度可能会降低),而右图的same方式则会在图像边缘用0补齐(这种方式图像维度不会降低)。

                                                                          

二:池化层工作原理

三:全连接层工作原理

 

 

发表评论

0/200
232 点赞
0 评论
收藏