代码来源:https://github.com/eriklindernoren/ML-From-Scratch

卷积神经网络中卷积层Conv2D(带stride、padding)的具体实现:https://www.cnblogs.com/xiximayou/p/12706576.html

激活函数的实现(sigmoid、softmax、tanh、relu、leakyrelu、elu、selu、softplus):https://www.cnblogs.com/xiximayou/p/12713081.html

损失函数定义(均方误差、交叉熵损失):https://www.cnblogs.com/xiximayou/p/12713198.html

优化器的实现(SGD、Nesterov、Adagrad、Adadelta、RMSprop、Adam):https://www.cnblogs.com/xiximayou/p/12713594.html

本节将根据代码继续学习卷积层的反向传播过程。

这里就只贴出Conv2D前向传播和反向传播的代码了:

def forward_pass(self, X, training=True):
batch_size, channels, height, width = X.shape
self.layer_input = X
# Turn image shape into column shape
# (enables dot product between input and weights)
self.X_col = image_to_column(X, self.filter_shape, stride=self.stride, output_shape=self.padding)
# Turn weights into column shape
self.W_col = self.W.reshape((self.n_filters, -1))
# Calculate output
output = self.W_col.dot(self.X_col) + self.w0
# Reshape into (n_filters, out_height, out_width, batch_size)
output = output.reshape(self.output_shape() + (batch_size, ))
# Redistribute axises so that batch size comes first
return output.transpose(3,0,1,2) def backward_pass(self, accum_grad):
# Reshape accumulated gradient into column shape
accum_grad = accum_grad.transpose(1, 2, 3, 0).reshape(self.n_filters, -1) if self.trainable:
# Take dot product between column shaped accum. gradient and column shape
# layer input to determine the gradient at the layer with respect to layer weights
grad_w = accum_grad.dot(self.X_col.T).reshape(self.W.shape)
# The gradient with respect to bias terms is the sum similarly to in Dense layer
grad_w0 = np.sum(accum_grad, axis=1, keepdims=True) # Update the layers weights
self.W = self.W_opt.update(self.W, grad_w)
self.w0 = self.w0_opt.update(self.w0, grad_w0) # Recalculate the gradient which will be propogated back to prev. layer
accum_grad = self.W_col.T.dot(accum_grad)
# Reshape from column shape to image shape
accum_grad = column_to_image(accum_grad,
self.layer_input.shape,
self.filter_shape,
stride=self.stride,
output_shape=self.padding) return accum_grad

而在定义卷积神经网络中是在neural_network.py中  

   def train_on_batch(self, X, y):
""" Single gradient update over one batch of samples """
y_pred = self._forward_pass(X)
loss = np.mean(self.loss_function.loss(y, y_pred))
acc = self.loss_function.acc(y, y_pred)
# Calculate the gradient of the loss function wrt y_pred
loss_grad = self.loss_function.gradient(y, y_pred)
# Backpropagate. Update weights
self._backward_pass(loss_grad=loss_grad) return loss, acc

还需要看一下self._forward_pas和self._backward_pass:

    def _forward_pass(self, X, training=True):
""" Calculate the output of the NN """
layer_output = X
for layer in self.layers:
layer_output = layer.forward_pass(layer_output, training) return layer_output def _backward_pass(self, loss_grad):
""" Propagate the gradient 'backwards' and update the weights in each layer """
for layer in reversed(self.layers):
loss_grad = layer.backward_pass(loss_grad)

我们可以看到,在前向传播中会计算出self.layers中每一层的输出,把包括卷积、池化、激活和归一化等。然后在反向传播中从后往前更新每一层的梯度。这里我们以一个卷积层+全连接层+损失函数为例。网络前向传播完之后,最先获得的梯度是损失函数的梯度。然后将损失函数的梯度传入到全连接层,然后获得全连接层计算的梯度,传入到卷积层中,此时调用卷积层的backward_pass()方法。在卷积层中的backward_pass()方法中,如果设置了self.trainable,那么会计算出对权重W以及偏置项w0的梯度,然后使用优化器optmizer,也就是W_opt和w0_opt进行参数的更新,然后再计算对前一层的梯度。最后有一个colun_to_image()方法。

def column_to_image(cols, images_shape, filter_shape, stride, output_shape='same'):
batch_size, channels, height, width = images_shape
pad_h, pad_w = determine_padding(filter_shape, output_shape)
height_padded = height + np.sum(pad_h)
width_padded = width + np.sum(pad_w)
images_padded = np.empty((batch_size, channels, height_padded, width_padded)) # Calculate the indices where the dot products are applied between weights
# and the image
k, i, j = get_im2col_indices(images_shape, filter_shape, (pad_h, pad_w), stride) cols = cols.reshape(channels * np.prod(filter_shape), -1, batch_size)
cols = cols.transpose(2, 0, 1)
# Add column content to the images at the indices
np.add.at(images_padded, (slice(None), k, i, j), cols) # Return image without padding
return images_padded[:, :, pad_h[0]:height+pad_h[0], pad_w[0]:width+pad_w[0]]

该方法是将之间为了方便计算卷积进行的形状改变image_to_column()重新恢复成images_padded的格式。

像这种计算期间的各种的形状的变换就挺让人头疼的,还会碰到numpy中各式各样的函数,需要去查阅相关的资料。只要弄懂其中大致过程就可以了,加深相关知识的理解。

【python实现卷积神经网络】卷积层Conv2D反向传播过程的更多相关文章

  1. 关于LeNet-5卷积神经网络 S2层与C3层连接的参数计算的思考???

    https://blog.csdn.net/saw009/article/details/80590245 关于LeNet-5卷积神经网络 S2层与C3层连接的参数计算的思考??? 首先图1是LeNe ...

  2. 卷积神经网络(CNN)的训练过程

    卷积神经网络的训练过程 卷积神经网络的训练过程分为两个阶段.第一个阶段是数据由低层次向高层次传播的阶段,即前向传播阶段.另外一个阶段是,当前向传播得出的结果与预期不相符时,将误差从高层次向底层次进行传 ...

  3. 《神经网络的梯度推导与代码验证》之CNN前向和反向传播过程的代码验证

    在<神经网络的梯度推导与代码验证>之CNN的前向传播和反向梯度推导 中,我们学习了CNN的前向传播和反向梯度求导,但知识仍停留在纸面.本篇章将基于深度学习框架tensorflow验证我们所 ...

  4. Batch训练的反向传播过程

    Batch训练的反向传播过程 本文试图通过Softmax理解Batch训练的反向传播过程 采用的网络包含一层全连接和一层softmax,具体网络如下图所示: 交叉熵成本函数: \[L = - \fra ...

  5. 深度学习原理与框架-卷积神经网络基本原理 1.卷积层的前向传播 2.卷积参数共享 3. 卷积后的维度计算 4. max池化操作 5.卷积流程图 6.卷积层的反向传播 7.池化层的反向传播

    卷积神经网络的应用:卷积神经网络使用卷积提取图像的特征来进行图像的分类和识别       分类                        相似图像搜索                        ...

  6. 深度学习原理与框架-Tensorflow卷积神经网络-卷积神经网络mnist分类 1.tf.nn.conv2d(卷积操作) 2.tf.nn.max_pool(最大池化操作) 3.tf.nn.dropout(执行dropout操作) 4.tf.nn.softmax_cross_entropy_with_logits(交叉熵损失) 5.tf.truncated_normal(两个标准差内的正态分布)

    1. tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')  # 对数据进行卷积操作 参数说明:x表示输入数据,w表示卷积核, stride ...

  7. Python3 卷积神经网络卷积层,池化层,全连接层前馈实现

    # -*- coding: utf-8 -*- """ Created on Sun Mar 4 09:21:41 2018 @author: markli " ...

  8. 深度神经网络(DNN)反向传播算法(BP)

    在深度神经网络(DNN)模型与前向传播算法中,我们对DNN的模型和前向传播算法做了总结,这里我们更进一步,对DNN的反向传播算法(Back Propagation,BP)做一个总结. 1. DNN反向 ...

  9. 深度学习——深度神经网络(DNN)反向传播算法

    深度神经网络(Deep Neural Networks,简称DNN)是深度学习的基础. 回顾监督学习的一般性问题.假设我们有$m$个训练样本$\{(x_1, y_1), (x_2, y_2), …, ...

随机推荐

  1. 还记得第一个看到的Flutter组件吗?

    注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 MaterialApp 在学习Flutter的过程中我们第 ...

  2. JavaScript每日学习日记(0)

    8.10.2019 1.JavaScript能改变HTML内容.属性.样式,能隐藏或显示HTML元素. 2.JavaScript函数可以任意数量被放置在<body>.<head> ...

  3. 2018 巅峰极客CTF misc writeup

    flows 拿到一个pcap包,用wireshark打开,发现是USB协议,尝试在kali下使用tshark提取,提取失败,发现异常.回到wireshark分析数据.在其中一个数据包中发现了tip 把 ...

  4. [剑指offer]6.从尾到头打印链表+18.删除链表节点

    链表 6.从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 方法一 迭代 创建空列表res,将链表值head.val依次存进res,返回翻转后的res 代码 cl ...

  5. ModelForm理解简单运用(增删改查)

    from django.shortcuts import render, redirect,HttpResponse# Create your views here.from django.forms ...

  6. 故事:走进JVM的世界(图文并茂)

    注意!本文较长,建议先收藏再阅读.更多文章可以关注作者公众号:码上实战 你也可以 star 我的 GitHub上本文所属仓库:https://github.com/flyhero/MarkNote 说 ...

  7. Elasticsearch系列---使用中文分词器

    前言 前面的案例使用standard.english分词器,是英文原生的分词器,对中文分词支持不太好.中文作为全球最优美.最复杂的语言,目前中文分词器较多,ik-analyzer.结巴中文分词.THU ...

  8. 接口自动化框架pyface详细介绍

    版权说明 本框架系本人结合一些实践经验和开源框架设计思想,在家基于兴趣爱好独立完成的代码开发. 源码只保存在私人电脑,办公电脑上无.github开源与公司无关,先把关系撇清,不涉及侵权. 嘘. 框架定 ...

  9. 类与对象 CG作业1. 复数类Comple 。

    问题描述]一个完整的复数由实数部分和序数部分构成,请定义一个复数类,含有两个私有属性realPart和imagPart分别表示复数的实部和虚部,三个成员函数:initComplex实现复数成员变量的初 ...

  10. 数据分析之上篇---numpy模块

    目录 一.简介 二.ndarray -多维数组对象 1.为什么要是用ndarray? 2.创建ndarray对象 3.ndarray多维数组创建 4.常用属性 5.数据类型 6.ndarray 数组创 ...