如何使用numpy实现一个全连接神经网络?(上)
全连接神经网络的概念我就不介绍了,对这个不是很了解的朋友,可以移步其他博主的关于神经网络的文章,这里只介绍我使用基本工具实现全连接神经网络的方法。
所用工具:
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),这里只演示了三层,实际上这个就是全连接神经网络的基本数学表达式。
构建这个模型的难点在于梯度的计算以及反向传播逻辑。中间层的每一层的输出对输入以及偏置求导,都是一个矩阵对另一个矩阵的求导。而矩阵的求导不同于高数中所学的导数,链式法则也有一些不同。关于这部分内容可参考:矩阵求导术(上),矩阵求导术(下),这里不再讲述。笔者正是在参考了这两篇文章的前提下实现这个过程的。
导入工具包:
import numpy as np
import matplotlib.pyplot as plt
定义Layer类中的Dense类中类:(这里可以把layers类单独拿出来作为一个父类,其余的层可以继承layers,然后钉子自己的反向传播逻辑,可以减少重复代码,这里为了方便展示,没有那么做)
class Layers:
class Dense:
'''
全连接层
''' def __init__(self, output_category):
'''
接收并初始化一个输出维度,用于确定这一层w的维度,以及用于梯度计算
:param output_category:
'''
self.output_category = output_category def __call__(self, Input):
'''
使用魔法方法,实例化对象后,随机的方式初始化w参数,
实例化输入数据,计算本层前向传播方式
:param Input:
:return:
'''
w_shape = (Input.shape[1], self.output_category)
b_shape = (Input.shape[0], self.output_category)
self.w = np.mat(np.random.random(size=w_shape))
self.b = np.mat(np.random.random(size=b_shape))
self.Input = Input
result = self.Input * self.w +self.b
self.result = result
return result def backpropagation(self, w_grad_from_next_layer=None, learning_rate=None, use_bias=False):
'''
反向传播算法的数学描述,公式参考
https://zhuanlan.zhihu.com/p/24863977
公式 Y = X * w +b ,
dY = dX * w + X * dw + db
= I * dX * w + X * dw * I + I * db * I (I是单位矩阵,
公式里每个I都不一样维度,具体是多少要参考它与谁相乘)
vec(dY) = np.kron(w,I)*vec(dX) + np.kron(I,w)*vec(dw) + np.kron(I,I)*vec(db)
:param w_grad_from_next_layer:从下一层传过来的梯度
:param learning_rate:学习率
:return:
'''
mid_w_grad = np.mat(np.kron(np.eye(self.output_category), self.Input))
self.w_grad = w_grad_from_next_layer * mid_w_grad mid_x_grad = np.kron(self.w.T, np.eye(self.Input.shape[0]))
self.x_grad = w_grad_from_next_layer * mid_x_grad if use_bias == True:
mid_b_grad = np.kron(np.eye(self.output_category), np.eye(self.Input.shape[0]))
self.b_grad = w_grad_from_next_layer * mid_b_grad if learning_rate is not None:
self.w = self.w - learning_rate * self.w_grad.T
if use_bias == True:
self.b = self.b - learning_rate * self.b_grad
return self.x_grad
定义Layers 中的Activation类:(这里初始化的时候必须传入一个激活函数,这个激活函数应该是一个类,应该有一个call方法来定义它的前向逻辑,应该有一个grad方法来计算梯度)
class Layers:
class Activation:
'''
激活层
'''
def __init__(self, activate_func):
'''
传入激活方程类
:param output_category:
'''
self.activate_func = activate_func def __call__(self, Input):
'''
使用魔法方法,实例化对象后,随机的方式初始化w参数,
实例化输入数据,计算本层前向传播方式
:param Input:
:return:
'''
self.Input = Input
self.activate_func_obj = self.activate_func(self.Input)
result = self.activate_func_obj.call()
self.result = result
return result def backpropagation(self, w_grad_from_next_layer=None, learning_rate=None, ):
'''
反向传播算法的数学描述,公式参考
https://zhuanlan.zhihu.com/p/24863977
公式 Y = f(X) (f是逐元素函数)
dY = df(X)
= f'(X) ⊙ dX (⊙表示出逐元素相乘,也就是通缩意义上的对应位置相乘)
所以
vec(dY) = np.diagflat(f'(X))* vec(dX) :param w_grad_from_next_layer:从下一层传过来的梯度
:param learning_rate:学习率
:return:
''' mid_x_grad = self.activate_func_obj.grad()
self.x_grad = w_grad_from_next_layer * mid_x_grad return self.x_grad
定义了Activation后,但这个方程需要传入一个激活函数类,现在我们顺从定义一个函数类,用来给激活层提供激活函数类。这个类有两个功能,一是定义正向传播方法,一种是定义梯度计算。
class Funcs:
'''
方程
'''
class Relu:
'''
Relu函数
''' def __init__(self,Input):
self.Input = Input
pass def call(self):
'''
计算结果,并返回
:return:
''' result = np.multiply((self.Input>0),self.Input)
return result def grad(self):
'''
梯度计算
:return:
''' mid_grad = (self.Input>0)*1.0 #乘1 讲bollen类型转化为float类型
result = np.diagflat(mid_grad)
return result
类似的,我们可以定义更多的种类的激活函数,比如selu,sigmoid等等。到目前为止,如果我们可以定义一个常用的损失函数,那么我们就具备了搭建简单的神经网络的基本要求了。这里我们的定义一个平方差损失函数。
class Funcs:
'''
方程
''' class SqureLossError:
'''
平方误差类
'''
def __init__(self,y,pred):
self.y=y
self.pred = pred def call(self):
'''
计算损失,并返回
:return:
'''
result = np.linalg.norm(self.y-self.pred)
return result def grad(self):
'''
梯度计算
:return:
'''
result = np.mat(2*(self.pred-self.y).T)
return result
到这里,我们已经具备了搭建神经网络的基本板块了,我们可以用这些基本模块来搭建一个简单的神经网络模型。下一章,我会继续详述一下这个过程。
如何使用numpy实现一个全连接神经网络?(上)的更多相关文章
- TensorFlow之DNN(二):全连接神经网络的加速技巧(Xavier初始化、Adam、Batch Norm、学习率衰减与梯度截断)
在上一篇博客<TensorFlow之DNN(一):构建“裸机版”全连接神经网络>中,我整理了一个用TensorFlow实现的简单全连接神经网络模型,没有运用加速技巧(小批量梯度下降不算哦) ...
- TensorFlow之DNN(一):构建“裸机版”全连接神经网络
博客断更了一周,干啥去了?想做个聊天机器人出来,去看教程了,然后大受打击,哭着回来补TensorFlow和自然语言处理的基础了.本来如意算盘打得挺响,作为一个初学者,直接看项目(不是指MINIST手写 ...
- 【TensorFlow/简单网络】MNIST数据集-softmax、全连接神经网络,卷积神经网络模型
初学tensorflow,参考了以下几篇博客: soft模型 tensorflow构建全连接神经网络 tensorflow构建卷积神经网络 tensorflow构建卷积神经网络 tensorflow构 ...
- Tensorflow 多层全连接神经网络
本节涉及: 身份证问题 单层网络的模型 多层全连接神经网络 激活函数 tanh 身份证问题新模型的代码实现 模型的优化 一.身份证问题 身份证号码是18位的数字[此处暂不考虑字母的情况],身份证倒数第 ...
- tensorflow中使用mnist数据集训练全连接神经网络-学习笔记
tensorflow中使用mnist数据集训练全连接神经网络 ——学习曹健老师“人工智能实践:tensorflow笔记”的学习笔记, 感谢曹老师 前期准备:mnist数据集下载,并存入data目录: ...
- 深度学习tensorflow实战笔记(1)全连接神经网络(FCN)训练自己的数据(从txt文件中读取)
1.准备数据 把数据放进txt文件中(数据量大的话,就写一段程序自己把数据自动的写入txt文件中,任何语言都能实现),数据之间用逗号隔开,最后一列标注数据的标签(用于分类),比如0,1.每一行表示一个 ...
- MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网络训练实现及比较(三)
版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 在前两篇文章MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网 ...
- tensorflow 添加一个全连接层
对于一个全连接层,tensorflow都为我们封装好了. 使用:tf.layers.dense() tf.layers.dense( inputs, units, activation=None, u ...
- 基于MNIST数据集使用TensorFlow训练一个包含一个隐含层的全连接神经网络
包含一个隐含层的全连接神经网络结构如下: 包含一个隐含层的神经网络结构图 以MNIST数据集为例,以上结构的神经网络训练如下: #coding=utf-8 from tensorflow.exampl ...
随机推荐
- Mysql安装、配置、优化
MYSQL定义 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最 ...
- CSS新特性之3D转换
1. 三维坐标系 x轴:水平向右(右边是正,左边是负) y轴:垂直向下(向下是正,向上是负) z轴:垂直屏幕(向外是正,向里是负) 2. 3D转换 3D转换中最常用的是3D位移和3D旋转.主要知识点如 ...
- git 分布式控制版本管理器(上)
git的作用: 1.更方便的存储版本 2.恢复之前的版本 3.更方便的对比 4.协同合作 下载地址git官网: https://git-scm.com/ 可自选自己电脑的操作系统 安装: 一路next ...
- Tkinter使frame填充整个区域
在未设置默认情况下效果为 设置之后出现效果 使用方法: 增加 fill=X/Y/BOTH 以我为例: leftFrame.pack(side='left',fill=Y)
- 上手OrangePi Zero+
一.安装系统 所需材料:系统镜像文件.镜像烧录工具.至少2G的内存卡(推荐8G以上).读卡器 1.下载系统镜像 官方系统下载地址,由于官方系统更新截止到17年,所以我选择的是Armbian系统.下载地 ...
- 富文本编辑器 tinymce 的安装与使用
百度的富文本编辑器大家都熟悉,那么下面给大家介绍一款富文本编辑器tinymce ,个人感觉比百度的界面好看,调用方便,就不知道各位大神怎么看咯! tinymce中文文档 以下是vue中使用示例,献上最 ...
- 【RTOS】基于V7开发板的uCOS-III,uCOS-II,RTX4,RTX5,FreeRTOS原版和带CMSIS-RTOS V2封装层版全部集齐
RTOS模板制作好后,后面堆各种中间件就方便了. 1.基于V7开发板的最新版uCOS-II V2.92.16程序模板,含MDK和IAR,支持uC/Probe https://www.cnblogs.c ...
- 【Java基础】JDBC简明教程
目录 1. 常用类 2. JDBC编程步骤 3. 事务处理 4. 数据库连接池 5. JDBC列子代码 6. 使用Apache的JDBC工具类 虽然在平时的开发过程中我们不会直接使JDBC的API来操 ...
- 常用类-ExcelHelper
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...
- vue发送ajax请求
一.vue-resource 1.简介 一款vue插件,用于处理ajax请求,vue1.x时广泛应用,现不被维护. 2.使用流程 step1:安装 [命令行输入] npm install vue-re ...