全连接神经网络的概念我就不介绍了,对这个不是很了解的朋友,可以移步其他博主的关于神经网络的文章,这里只介绍我使用基本工具实现全连接神经网络的方法。

  所用工具:

    numpy == 1.16.4

    matplotlib 最新版

  我的思路是定义一个layer类,在这个类里边构建传播的前向传播的逻辑,以及反向传播的逻辑,然后在构建一个model类,在model类里边,将layer类中的对象拼接,就可以得到我们想要的模型。

  在Layers类的传播中,在Dense层中,我是按照公式output = X*w+b,来计算输出。X 是 (m,n)的矩阵,表示有m行数据,每一个数据是n维的向量。w是一个(n,1)的矩阵,是我们要优化的参数。b是一个(m,1)的矩阵,是偏置。在Activation层中,我是按照公式 output = f激活(X) 来计算输出的。f激活是激活函数,是逐元素函数。将Dense层与Activation层叠加,就能实现output = f激活(X*w+b)的效果,如果多次交替叠加,就相当于在计算output = f激活( f激活(f激活(X*w+b)*w+b)*w+b),这里只演示了三层,实际上这个就是全连接神经网络的基本数学表达式。

  构建这个模型的难点在于梯度的计算以及反向传播逻辑。中间层的每一层的输出对输入以及偏置求导,都是一个矩阵对另一个矩阵的求导。而矩阵的求导不同于高数中所学的导数,链式法则也有一些不同。关于这部分内容可参考:矩阵求导术(上)矩阵求导术(下),这里不再讲述。笔者正是在参考了这两篇文章的前提下实现这个过程的。

  导入工具包:

  

  1. import numpy as np
  2. import matplotlib.pyplot as plt

  定义Layer类中的Dense类中类:(这里可以把layers类单独拿出来作为一个父类,其余的层可以继承layers,然后钉子自己的反向传播逻辑,可以减少重复代码,这里为了方便展示,没有那么做)

  1. class Layers:
  2. class Dense:
  3. '''
  4. 全连接层
  5. '''
  6.  
  7. def __init__(self, output_category):
  8. '''
  9. 接收并初始化一个输出维度,用于确定这一层w的维度,以及用于梯度计算
  10. :param output_category:
  11. '''
  12. self.output_category = output_category
  13.  
  14. def __call__(self, Input):
  15. '''
  16. 使用魔法方法,实例化对象后,随机的方式初始化w参数,
  17. 实例化输入数据,计算本层前向传播方式
  18. :param Input:
  19. :return:
  20. '''
  21. w_shape = (Input.shape[1], self.output_category)
  22. b_shape = (Input.shape[0], self.output_category)
  23. self.w = np.mat(np.random.random(size=w_shape))
  24. self.b = np.mat(np.random.random(size=b_shape))
  25. self.Input = Input
  26. result = self.Input * self.w +self.b
  27. self.result = result
  28. return result
  29.  
  30. def backpropagation(self, w_grad_from_next_layer=None, learning_rate=None, use_bias=False):
  31. '''
  32. 反向传播算法的数学描述,公式参考
  33. https://zhuanlan.zhihu.com/p/24863977
  34. 公式 Y = X * w +b ,
  35. dY = dX * w + X * dw + db
  36. = I * dX * w + X * dw * I + I * db * I (I是单位矩阵,
  37. 公式里每个I都不一样维度,具体是多少要参考它与谁相乘)
  38. vec(dY) = np.kron(w,I)*vec(dX) + np.kron(I,w)*vec(dw) + np.kron(I,I)*vec(db)
  39. :param w_grad_from_next_layer:从下一层传过来的梯度
  40. :param learning_rate:学习率
  41. :return:
  42. '''
  43. mid_w_grad = np.mat(np.kron(np.eye(self.output_category), self.Input))
  44. self.w_grad = w_grad_from_next_layer * mid_w_grad
  45.  
  46. mid_x_grad = np.kron(self.w.T, np.eye(self.Input.shape[0]))
  47. self.x_grad = w_grad_from_next_layer * mid_x_grad
  48.  
  49. if use_bias == True:
  50. mid_b_grad = np.kron(np.eye(self.output_category), np.eye(self.Input.shape[0]))
  51. self.b_grad = w_grad_from_next_layer * mid_b_grad
  52.  
  53. if learning_rate is not None:
  54. self.w = self.w - learning_rate * self.w_grad.T
  55. if use_bias == True:
  56. self.b = self.b - learning_rate * self.b_grad
  57. return self.x_grad

  定义Layers 中的Activation类:(这里初始化的时候必须传入一个激活函数,这个激活函数应该是一个类,应该有一个call方法来定义它的前向逻辑,应该有一个grad方法来计算梯度)

  1. class Layers:
  2.   class Activation:
  3. '''
  4. 激活层
  5. '''
  6. def __init__(self, activate_func):
  7. '''
  8. 传入激活方程类
  9. :param output_category:
  10. '''
  11. self.activate_func = activate_func
  12.  
  13. def __call__(self, Input):
  14. '''
  15. 使用魔法方法,实例化对象后,随机的方式初始化w参数,
  16. 实例化输入数据,计算本层前向传播方式
  17. :param Input:
  18. :return:
  19. '''
  20. self.Input = Input
           self.activate_func_obj = self.activate_func(self.Input)
  21. result = self.activate_func_obj.call()
  22. self.result = result
  23. return result
  24.  
  25. def backpropagation(self, w_grad_from_next_layer=None, learning_rate=None, ):
  26. '''
  27. 反向传播算法的数学描述,公式参考
  28. https://zhuanlan.zhihu.com/p/24863977
  29. 公式 Y = f(X) (f是逐元素函数)
  30. dY = df(X)
  31. = f'(X) dX (⊙表示出逐元素相乘,也就是通缩意义上的对应位置相乘)
  32. 所以
  33. vec(dY) = np.diagflat(f'(X))* vec(dX)
  34.  
  35. :param w_grad_from_next_layer:从下一层传过来的梯度
  36. :param learning_rate:学习率
  37. :return:
  38. '''
  39.  
  40. mid_x_grad = self.activate_func_obj.grad()
  41. self.x_grad = w_grad_from_next_layer * mid_x_grad
  42.  
  43. return self.x_grad

  定义了Activation后,但这个方程需要传入一个激活函数类,现在我们顺从定义一个函数类,用来给激活层提供激活函数类。这个类有两个功能,一是定义正向传播方法,一种是定义梯度计算。

  1. class Funcs:
  2. '''
  3. 方程
  4. '''
  5. class Relu:
  6. '''
  7. Relu函数
  8. '''
  9.  
  10. def __init__(self,Input):
  11. self.Input = Input
  12. pass
  13.  
  14. def call(self):
  15. '''
  16. 计算结果,并返回
  17. :return:
  18. '''
  19.  
  20. result = np.multiply((self.Input>0),self.Input)
  21. return result
  22.  
  23. def grad(self):
  24. '''
  25. 梯度计算
  26. :return:
  27. '''
  28.  
  29. mid_grad = (self.Input>0)*1.0 #乘1 讲bollen类型转化为float类型
  30. result = np.diagflat(mid_grad)
  31. return result

  类似的,我们可以定义更多的种类的激活函数,比如selu,sigmoid等等。到目前为止,如果我们可以定义一个常用的损失函数,那么我们就具备了搭建简单的神经网络的基本要求了。这里我们的定义一个平方差损失函数。

  1. class Funcs:
  2. '''
  3. 方程
  4. '''
  5.  
  6. class SqureLossError:
  7. '''
  8. 平方误差类
  9. '''
  10. def __init__(self,y,pred):
  11. self.y=y
  12. self.pred = pred
  13.  
  14. def call(self):
  15. '''
  16. 计算损失,并返回
  17. :return:
  18. '''
  19. result = np.linalg.norm(self.y-self.pred)
  20. return result
  21.  
  22. def grad(self):
  23. '''
  24. 梯度计算
  25. :return:
  26. '''
  27. result = np.mat(2*(self.pred-self.y).T)
  28. return result

  到这里,我们已经具备了搭建神经网络的基本板块了,我们可以用这些基本模块来搭建一个简单的神经网络模型。下一章,我会继续详述一下这个过程。

如何使用numpy实现一个全连接神经网络?(上)的更多相关文章

  1. TensorFlow之DNN(二):全连接神经网络的加速技巧(Xavier初始化、Adam、Batch Norm、学习率衰减与梯度截断)

    在上一篇博客<TensorFlow之DNN(一):构建“裸机版”全连接神经网络>中,我整理了一个用TensorFlow实现的简单全连接神经网络模型,没有运用加速技巧(小批量梯度下降不算哦) ...

  2. TensorFlow之DNN(一):构建“裸机版”全连接神经网络

    博客断更了一周,干啥去了?想做个聊天机器人出来,去看教程了,然后大受打击,哭着回来补TensorFlow和自然语言处理的基础了.本来如意算盘打得挺响,作为一个初学者,直接看项目(不是指MINIST手写 ...

  3. 【TensorFlow/简单网络】MNIST数据集-softmax、全连接神经网络,卷积神经网络模型

    初学tensorflow,参考了以下几篇博客: soft模型 tensorflow构建全连接神经网络 tensorflow构建卷积神经网络 tensorflow构建卷积神经网络 tensorflow构 ...

  4. Tensorflow 多层全连接神经网络

    本节涉及: 身份证问题 单层网络的模型 多层全连接神经网络 激活函数 tanh 身份证问题新模型的代码实现 模型的优化 一.身份证问题 身份证号码是18位的数字[此处暂不考虑字母的情况],身份证倒数第 ...

  5. tensorflow中使用mnist数据集训练全连接神经网络-学习笔记

    tensorflow中使用mnist数据集训练全连接神经网络 ——学习曹健老师“人工智能实践:tensorflow笔记”的学习笔记, 感谢曹老师 前期准备:mnist数据集下载,并存入data目录: ...

  6. 深度学习tensorflow实战笔记(1)全连接神经网络(FCN)训练自己的数据(从txt文件中读取)

    1.准备数据 把数据放进txt文件中(数据量大的话,就写一段程序自己把数据自动的写入txt文件中,任何语言都能实现),数据之间用逗号隔开,最后一列标注数据的标签(用于分类),比如0,1.每一行表示一个 ...

  7. MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网络训练实现及比较(三)

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 在前两篇文章MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网 ...

  8. tensorflow 添加一个全连接层

    对于一个全连接层,tensorflow都为我们封装好了. 使用:tf.layers.dense() tf.layers.dense( inputs, units, activation=None, u ...

  9. 基于MNIST数据集使用TensorFlow训练一个包含一个隐含层的全连接神经网络

    包含一个隐含层的全连接神经网络结构如下: 包含一个隐含层的神经网络结构图 以MNIST数据集为例,以上结构的神经网络训练如下: #coding=utf-8 from tensorflow.exampl ...

随机推荐

  1. MySQL数据库~~~~~锁和事务

    一 锁 innodb存储引擎默认是行级锁 行级锁定最大的特点就是锁定对象的颗粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的.由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予 ...

  2. Keepalived集群软件高级使用(工作原理和状态通知)

    1.介绍 Keeaplived主要有两种应用场景,一个是通过配置keepalived结合ipvs做到负载均衡(LVS+Keepalived),有此需求者可参考以往博文:http://lizhenlia ...

  3. Opencv中图像height width X 轴 Y轴 rows cols之间的对应关系

    这里做一个备忘录:

  4. mysql实践:sql优化

    ---恢复内容开始--- 设计表的时候 1. 不同的表涉及同一个公共意义字段不要使用不同的数据类型(可能导致索引不可用,查询结果有偏差) 2. 不要一张表放太多的数据     主表20~30个字段   ...

  5. IT兄弟连 HTML5教程 HTML5表单 H5表单提交综合实例

    这里我们创建一个填写个人基本信息的表单,使用了表单元素有<input>输入框.<datalist>选项列表.<textarea>文本框,通用的表单输入类型有text ...

  6. SpringCloud微服务(03):Hystrix组件,实现服务熔断

    本文源码:GitHub·点这里 || GitEE·点这里 写在前面:阅读本文前,你可能需要熟悉一下内容. 微服务组件:Eureka管理注册中心 微服务组件:Ribbon和Feign服务调用 Sprin ...

  7. ASP.NET Core SignalR:基础概述

    一.简介 ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程. 实时 Web 功能使服务器端代码能够即时将内容推送到客户端. SignalR 的适用 ...

  8. JPA的entityManager的find方法与getReference方法的区别

    场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...

  9. 剑指offer笔记面试题10----斐波那契数列

    题目:求斐波那契数列的第n项.写一个函数,输入n,求斐波那契数列的第n项.斐波那契数列的定义如下:f(0) = 0, f(1) = 1,f(n) = f(n - 1) + f(n - 2). 测试用例 ...

  10. JS基础研语法---函数基础总结---定义、作用、参数、返回值、arguments伪数组、作用域、预解析

    函数: 把一些重复的代码封装在一个地方,在需要的时候直接调用这个地方的代码就可以了 函数作用: 代码重用 函数的参数: 形参:函数定义的时候,函数名字后面的小括号里的变量 实参:函数调用的时候,函数名 ...