『TensorFlow』卷积层、池化层详解
一、前向计算和反向传播数学过程讲解
这里讲解的是平均池化层,最大池化层见本文第三小节
二、测试代码
数据和上面完全一致,自行打印验证即可。
1、前向传播
import tensorflow as tf
import numpy as np# 输入张量为3×3的二维矩阵
M = np.array([[[1], [-1], [0]],[[-1], [2], [1]],[[0], [2], [-2]]
])
# 定义卷积核权重和偏置项。由权重可知我们只定义了一个2×2×1的卷积核
filter_weight = tf.get_variable('weights', [2, 2, 1, 1], initializer=tf.constant_initializer([[1, -1],[0, 2]]))
biases = tf.get_variable('biases', [1], initializer=tf.constant_initializer(1))# 调整输入格式符合TensorFlow要求
M = np.asarray(M, dtype='float32')
M = M.reshape(1, 3, 3, 1)# 计算输入张量通过卷积核和池化滤波器计算后的结果
x = tf.placeholder('float32', [1, None, None, 1])# 我们使用了带Padding,步幅为2的卷积操作,因为filter_weight的深度确定了卷积核的数量
conv = tf.nn.conv2d(x, filter_weight, strides=[1, 2, 2, 1], padding='SAME')
bias = tf.nn.bias_add(conv, biases)# 使用带Padding,步幅为2的平均池化操作
pool = tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')# 执行计算图
with tf.Session() as sess:tf.global_variables_initializer().run()convoluted_M = sess.run(bias, feed_dict={x: M})pooled_M = sess.run(pool, feed_dict={x: M})print("convoluted_M: \n", convoluted_M)print("pooled_M: \n", pooled_M)
2、反向传播
import tensorflow as tf
import numpy as np# 输入张量为3×3的二维矩阵
M = np.array([[[1], [-1], [0]],[[-1], [2], [1]],[[0], [2], [-2]]
])
# 定义卷积核权重和偏置项。由权重可知我们只定义了一个2×2×1的卷积核
filter_weight = tf.get_variable('weights', [2, 2, 1, 1], initializer=tf.constant_initializer([[1, -1],[0, 2]]))
biases = tf.get_variable('biases', [1], initializer=tf.constant_initializer(1))# 调整输入格式符合TensorFlow要求
M = np.asarray(M, dtype='float32')
M = M.reshape(1, 3, 3, 1)# 计算输入张量通过卷积核和池化滤波器计算后的结果
x = tf.placeholder('float32', [1, None, None, 1])# 我们使用了带Padding,步幅为2的卷积操作,因为filter_weight的深度确定了卷积核的数量
conv = tf.nn.conv2d(x, filter_weight, strides=[1, 2, 2, 1], padding='SAME')
bias = tf.nn.bias_add(conv, biases)d_filter = tf.gradients(bias,filter_weight)
d_biases = tf.gradients(bias,biases)
d_conv = tf.gradients(bias,conv)
d_conv_x = tf.gradients(conv,x)
d_conv_w = tf.gradients(conv,filter_weight)
# d_bias_x = tf.gradients(bias,x)# 使用带Padding,步幅为2的平均池化操作
pool = tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')d_pool = tf.gradients(pool,x)# 执行计算图
with tf.Session() as sess:tf.global_variables_initializer().run()# convoluted_M = sess.run(bias, feed_dict={x: M})# pooled_M = sess.run(pool, feed_dict={x: M})## print("convoluted_M: \n", convoluted_M)# print("pooled_M: \n", pooled_M)print("d_filter:\n", sess.run(d_filter, feed_dict={x: M}))print("d_biases:\n", sess.run(d_biases, feed_dict={x: M}))print("d_conv:\n", sess.run(d_conv, feed_dict={x: M}))print("d_conv_x:\n", sess.run(d_conv_x, feed_dict={x: M}))print("d_conv_w:\n", sess.run(d_conv_w, feed_dict={x: M}))
四、CS31n上实现的卷积层池化层API
1、卷积层
卷积层向前传播示意图:
def conv_forward_naive(x, w, b, conv_param):"""A naive implementation of the forward pass for a convolutional layer.The input consists of N data points, each with C channels, height H and widthW. We convolve each input with F different filters, where each filter spansall C channels and has height HH and width HH.Input:- x: Input data of shape (N, C, H, W)- w: Filter weights of shape (F, C, HH, WW)- b: Biases, of shape (F,)- conv_param: A dictionary with the following keys:- 'stride': The number of pixels between adjacent receptive fields in thehorizontal and vertical directions.- 'pad': The number of pixels that will be used to zero-pad the input.Returns a tuple of:- out: Output data, of shape (N, F, H', W') where H' and W' are given byH' = 1 + (H + 2 * pad - HH) / strideW' = 1 + (W + 2 * pad - WW) / stride- cache: (x, w, b, conv_param)"""out = None############################################################################## TODO: Implement the convolutional forward pass. ## Hint: you can use the function np.pad for padding. #############################################################################pad = conv_param['pad'] stride = conv_param['stride']N, C, H, W = x.shapeF, _, HH, WW = w.shapeH0 = 1 + (H + 2 * pad - HH) / strideW0 = 1 + (W + 2 * pad - WW) / stridex_pad = np.pad(x, ((0,0),(0,0),(pad,pad),(pad,pad)),'constant') # 填充后的输入out = np.zeros((N,F,H0,W0)) # 初始化的输出# 以输出的每一个像素点为单位写出其前传表达式for n in range(N):for f in range(F):for h0 in range(H0):for w0 in range(W0):out[n,f,h0,w0] = np.sum(x_pad[n,:,h0*stride:HH+h0*stride,w0*stride:WW+w0*stride] * w[f]) + b[f]############################################################################## END OF YOUR CODE ##############################################################################cache = (x, w, b, conv_param)return out, cache
卷积层反向传播示意图:
def conv_backward_naive(dout, cache):"""A naive implementation of the backward pass for a convolutional layer.Inputs:- dout: Upstream derivatives.- cache: A tuple of (x, w, b, conv_param) as in conv_forward_naiveReturns a tuple of:- dx: Gradient with respect to x- dw: Gradient with respect to w- db: Gradient with respect to b"""dx, dw, db = None, None, None############################################################################## TODO: Implement the convolutional backward pass. ##############################################################################x, w, b, conv_param = cachepad = conv_param['pad'] stride = conv_param['stride']N, C, H, W = x.shapeF, _, HH, WW = w.shape_, _, H0, W0 = out.shapex_pad = np.pad(x, [(0,0), (0,0), (pad,pad), (pad,pad)], 'constant')dx, dw = np.zeros_like(x), np.zeros_like(w)dx_pad = np.pad(dx, [(0,0), (0,0), (pad,pad), (pad,pad)], 'constant') # 计算b的梯度(F,)db = np.sum(dout, axis=(0,2,3)) # dout:(N,F,H0,W0)# 以每一个dout点为基准计算其两个输入矩阵x(:,:,窗,窗)和w(f)的梯度,注意由于这两个矩阵都是多次参与运算,所以都是累加的关系for n in range(N):for f in range(F):for h0 in range(H0):for w0 in range(W0):x_win = x_pad[n,:,h0*stride:h0*stride+HH,w0*stride:w0*stride+WW]dw[f] += x_win * dout[n,f,h0,w0]dx_pad[n,:,h0*stride:h0*stride+HH,w0*stride:w0*stride+WW] += w[f] * dout[n,f,h0,w0]dx = dx_pad[:,:,pad:pad+H,pad:pad+W]############################################################################## END OF YOUR CODE ##############################################################################return dx, dw, db
2、最大池化层
池化层向前传播:
和卷积层类似,但是更简单一点,只要在对应feature map的原输入上取个窗口然后池化之即可,
def max_pool_forward_naive(x, pool_param):HH, WW = pool_param['pool_height'], pool_param['pool_width']s = pool_param['stride']N, C, H, W = x.shapeH_new = 1 + (H - HH) / sW_new = 1 + (W - WW) / sout = np.zeros((N, C, H_new, W_new))for i in xrange(N): for j in xrange(C): for k in xrange(H_new): for l in xrange(W_new): window = x[i, j, k*s:HH+k*s, l*s:WW+l*s] out[i, j, k, l] = np.max(window)cache = (x, pool_param)return out, cache
池化层反向传播:
反向传播的时候也是还原窗口,除最大值处继承上层梯度外(也就是说本层梯度为零),其他位置置零。
池化层没有过滤器,只有dx梯度,且x的窗口不像卷积层会重叠,所以不用累加,
def max_pool_backward_naive(dout, cache):x, pool_param = cacheHH, WW = pool_param['pool_height'], pool_param['pool_width']s = pool_param['stride']N, C, H, W = x.shapeH_new = 1 + (H - HH) / sW_new = 1 + (W - WW) / sdx = np.zeros_like(x)for i in xrange(N): for j in xrange(C): for k in xrange(H_new): for l in xrange(W_new): window = x[i, j, k*s:HH+k*s, l*s:WW+l*s] m = np.max(window) dx[i, j, k*s:HH+k*s, l*s:WW+l*s] = (window == m) * dout[i, j, k, l]return dx
五、实际框架实现方法
实际框架当然不会才用这种大循环的手段实现卷积操作,矩阵化运算才是正路。
1、Theano
常见的一种拆法是将二维 input 展开成一维向量([in_h * in_w] ->
[out_h * out_w]),将卷积核展开为([in_h * in_w, out_h * out_w]),
上面仅讨论了2维输入,其实由于 input 的 channels 和 kernal 的 channels 数一致,所以情况延申起来原理并无改变。最后的运算如下:
y = C·xT
2、Caffe
caffe的卷积矩阵化如下,其直接把 input 的各个通道的值放在了一个矩阵种,将各个 kernals 的各个通道值放入同一个矩阵,一次解决所有运算,感觉比上面的做法高明了一点(不过都是很厉害的算法)。
转载于:https://www.cnblogs.com/hellcat/p/7850048.html
『TensorFlow』卷积层、池化层详解相关推荐
- 【深度学习入门到精通系列】卷积和池化计算详解
文章目录 1 卷积 2 填充 3 池化 4 注意 1 卷积 卷积层由一组滤波器组成,滤波器可以视为二维数字矩阵.这是一个示例3x3滤波器: 在图像的某个位置上覆盖滤波器:将滤波器中的值与图像中的对应像 ...
- 深度学习笔记(一):卷积层+池化层+激活函数+全连接层
写在前面:大家好!我是[AI 菌],一枚爱弹吉他的程序员.我热爱AI.热爱分享.热爱开源! 这博客是我对学习的一点总结与记录.如果您也对 深度学习.机器视觉.算法.Python.C++ 感兴趣,可以关 ...
- 卷积神经网络——池化层学习——最大池化
池化层(Pooling layers) 除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性,我们来看一下. 先举一个池化层的例子,然后我们再讨论池化层的必要 ...
- keras中的卷积层池化层
文章目录 卷积层 创建卷积层 卷积层的格式及参数: 卷积层中的参数数量 卷积层的形状 池化层 keras中的最大池化层 参数 卷积层 创建卷积层 首先导入keras中的模块 from keras.la ...
- cs231n-(7)卷积神经网络:架构,卷积层/池化层
架构总览 常用的层 卷积层 概述 池化层 归一化层 全连接层 全连接层转为卷积层 卷积网络架构 层模式 层大小设计模式 实例 计算资源考虑 额外资源 卷积神经网络和普通神经网络非常类似.卷积神经网络由 ...
- CNN模型中 卷积层 RELU层 池化层 作用及顺序
卷积层 Convolutional layer 卷积运算的目的是提取输入的不同特征 类似于CV中的滤波,通过滑动窗口来得到特征图像 非线性激活层 Relu f(x)=max(0,x) 非线性激活层 ...
- TensorFlow实现卷积、池化操作
1.调用tf.nn.conv2d()实现卷积 首先是调用卷积函数实现卷积操作: 这里说明一下conv2d的定义及参数含义: 参考 [定义:] tf.nn.conv2d (input, filter, ...
- 卷积神经网络 池化层上采样(upsampling、interpolating)、下采样(subsampled、downsampled)是什么?(上采样为放大图像或图像插值、下采样为缩小图像)
缩小图像:或称为下采样(subsampled)或降采样(downsampled) 主要目的有两个:1.使得图像符合显示区域的大小:2.生成对应图像的缩略图. 放大图像:或称为上采样(upsamplin ...
- 『Linux』第九讲:Linux多线程详解(三)_ 线程互斥 | 线程同步
「前言」文章是关于Linux多线程方面的知识,上一篇是 Linux多线程详解(二),今天这篇是 Linux多线程详解(三),内容大致是线程互斥与线程同步,讲解下面开始! 「归属专栏」Linux系统编程 ...
最新文章
- 安装lua及问题解决
- 又是一卦测感情,这卦很是霸气
- 《Fabric 云存储的电子健康病历系统》(2)病历结构体 Records
- 【竞赛相关】Kaggle知识点:入门到进阶的10个问题
- IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm
- fifa15服务器位置,《FIFA 15》全系统教程图文攻略
- 《设计模式其实很简单》
- ioc控制反转_深入理解依赖注入(DI)和控制反转(IOC)
- [webpack]手写一个mvp版本的webpack
- 以太坊系列之十四: solidity特殊函数
- 坦克大战游戏java代码_Java实现坦克大战游戏的源码示例
- 六款Linux常用远程连接工具介绍,看看哪一款最适合你
- 详解正向代理与反向代理
- 适合计算机中职生见到打拼音的软件,中职计算机基础教案设计(18页)-原创力文档...
- 合肥有哪些不错的 IT 公司?
- mysql error 1236_MySQL Got fatal error 1236原因和解决方法
- matlab示波器多个接口,simulink在一个图形中画出多个示波器曲线的方法
- linux安装android x86_64,在VirtualBox上安装Android-X86
- UE4-(光照)光照贴图
- 华为GAUSS数据库常用的单行操作函数介绍