『cs231n』作业2选讲_通过代码理解卷积层&池化层

卷积层

卷积层向前传播示意图:

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 width
  W. We convolve each input with F different filters, where each filter spans
  all 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 the
      horizontal 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 by
    H‘ = 1 + (H + 2 * pad - HH) / stride
    W‘ = 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.shape
  F, _, HH, WW = w.shape
  H0 = 1 + (H + 2 * pad - HH) / stride
  W0 = 1 + (W + 2 * pad - WW) / stride
  x_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_naive

  Returns 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 = cache
  pad = conv_param[‘pad‘]
  stride = conv_param[‘stride‘]
  N, C, H, W = x.shape
  F, _, HH, WW = w.shape
  _, _, H0, W0 = out.shape

  x_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

池化层(亦下采样层)

池化层向前传播:

和卷积层类似,但是更简单一点,只要在对应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.shape
    H_new = 1 + (H - HH) / s
    W_new = 1 + (W - WW) / s
    out = 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 = cache
    HH, WW = pool_param[‘pool_height‘], pool_param[‘pool_width‘]
    s = pool_param[‘stride‘]
    N, C, H, W = x.shape
    H_new = 1 + (H - HH) / s
    W_new = 1 + (W - WW) / s
    dx = 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
时间: 2024-11-13 14:52:50

『cs231n』作业2选讲_通过代码理解卷积层&池化层的相关文章

『cs231n』作业2选讲_通过代码理解优化器

1).Adagrad一种自适应学习率算法,实现代码如下: cache += dx**2 x += - learning_rate * dx / (np.sqrt(cache) + eps) 这种方法的好处是,对于高梯度的权重,它们的有效学习率被降低了:而小梯度的权重迭代过程中学习率提升了.要注意的是,这里开根号很重要.平滑参数eps是为了避免除以0的情况,eps一般取值1e-4 到1e-8. 2).RMSpropRMSProp方法对Adagrad算法做了一个简单的优化,以减缓它的迭代强度: ca

『cs231n』作业1问题1选讲_通过代码理解K近邻算法&交叉验证选择超参数参数

通过K近邻算法探究numpy向量运算提速 茴香豆的"茴"字有... ... 使用三种计算图片距离的方式实现K近邻算法: 1.最为基础的双循环 2.利用numpy的broadca机制实现单循环 3.利用broadcast和矩阵的数学性质实现无循环 图片被拉伸为一维数组 X_train:(train_num, 一维数组) X:(test_num, 一维数组) 方法验证 import numpy as np a = np.array([[1,1,1],[2,2,2],[3,3,3]]) b

『cs231n』作业3问题4选讲_图像梯度应用强化

[注],本节(上节也是)的model是一个已经训练完成的CNN分类网络. 随机数图片向前传播后对目标类优化,反向优化图片本体 def create_class_visualization(target_y, model, **kwargs): """ Perform optimization over the image to generate class visualizations. Inputs: - target_y: Integer in the range [0,

『cs231n』计算机视觉基础

线性分类器损失函数明细: 『cs231n』线性分类器损失函数 最优化Optimiz部分代码: 1.差劲的方案,随机搜索 bestloss = float('inf') # 无穷大 for num in range(1000): W = np.random.randn(10, 3073) * 0.0001 loss = L(X_train, Y_train, W) if loss < bestloss: bestloss = loss bestW = W scores = bsetW.dot(Xt

『cs231n』视频数据处理

视频信息 和我之前的臆想不同,视频数据不仅仅是一帧一帧的图片本身,还包含个帧之间的联系,也就是还有一个时序的信息维度,包含人的动作判断之类的任务都是要依赖动作的时序信息的 视频数据处理的两种基本方法 - 使用3D卷积网络引入时间维度:由于3D卷积网络每次的输入帧是有长度限定的,所以这种方法更倾向于关注局部(时域)信息的任务 - 使用RNN/LSTM网络系列处理时序信息:由于迭代网络的特性,它更擅长处理全局视频信息 发散:结合两种方法的新思路 上面的具体实现也未必需要3D卷积,毕竟递归网络自己已经

ufldl学习笔记与编程作业:Feature Extraction Using Convolution,Pooling(卷积和池化抽取特征)

ufldl出了新教程,感觉比之前的好,从基础讲起,系统清晰,又有编程实践. 在deep learning高质量群里面听一些前辈说,不必深究其他机器学习的算法,可以直接来学dl. 于是最近就开始搞这个了,教程加上matlab编程,就是完美啊. 新教程的地址是:http://ufldl.stanford.edu/tutorial/ 学习链接: http://ufldl.stanford.edu/tutorial/supervised/FeatureExtractionUsingConvolution

『cs231n』Faster_RCNN(待续)

前言 研究了好一阵子深度学习在计算机视觉方面的实际应用意义不大的奇技淫巧,感觉基本对研究生生涯的工作没啥直接的借鉴意义,硬说收获的话倒是加深了对tensorflow的理解,是时候回归最初的兴趣点--物体检测了,实际上对cs231n的Faster RCNN讲解理解的不是很好,当然这和课上讲的比较简略也是有关系的,所以特地重新学习一下,参考文章链接在这,另: Faster RCNN github : https://github.com/rbgirshick/py-faster-rcnn Faste

『cs231n』RNN之理解LSTM网络

概述 LSTM是RNN的增强版,1.RNN能完成的工作LSTM也都能胜任且有更好的效果:2.LSTM解决了RNN梯度消失或爆炸的问题,进而可以具有比RNN更为长时的记忆能力.LSTM网络比较复杂,而恰好找到一篇不错的介绍文章,和课程的讲述范围差不多,所以这里摘下来(自己截图记录好麻烦),另外找到一篇推了公式的LSTM介绍,这个cs231n的课程并没有涉及,我暂时也不做这方面的研究,不过感觉内容不错,链接记下来以备不时之需. 本篇原文链接 RNN以及LSTM的介绍和公式梳理 按照老师的说法,LST

『cs231n』卷积神经网络的可视化与进一步理解

cs231n的第18课理解起来很吃力,听后又查了一些资料才算是勉强弄懂,所以这里贴一篇博文(根据自己理解有所修改)和原论文的翻译加深加深理解. 可视化理解卷积神经网络 原文地址 一.相关理论 本篇博文主要讲解2014年ECCV上的一篇经典文献:<Visualizing and Understanding Convolutional Networks>,可以说是CNN领域可视化理解的开山之作,这篇文献告诉我们CNN的每一层到底学习到了什么特征,然后作者通过可视化进行调整网络,提高了精度.最近两年