numpy创建神经网络框架

目录
  • 神经网络框架使用方法及设计思想
    • 项目介绍
    • 框架介绍

神经网络框架使用方法及设计思想

  • 在框自己手写架上基本模仿pytorch,用以学习神经网络的基本算法,如前向传播、反向传播、各种层、各种激活函数
  • 采用面向对象的思想进行编程,思路较为清晰
  • 想要神经网络的同学们可以参考一下
  • 代码大体框架较为清晰,但不否认存在丑陋的部分,以及对于pytorch的拙劣模仿

项目介绍

  • MINST_recognition:

手写数字识别,使用MINST数据集

训练30轮可以达到93%准确度,训练500轮左右达到95%准确度无法继续上升

  • RNN_sin_to_cos:

使用循环神经网络RNN,用sin的曲线预测cos的曲线

目前仍有bug,无法正常训练

框架介绍

  • 与框架有关的代码都放在了mtorch文件夹中
  • 使用流程

与pytorch相似,需要定义自己的神经网络、损失函数、梯度下降的优化算法等等

在每一轮的训练中,先获取样本输入将其输入到自己的神经网络中获取输出。然后将预测结果和期望结果交给损失函数计算loss,并通过loss进行梯度的计算,最后通过优化器对神经网络的参数进行更新。

结合代码理解更佳👇:

以下是使用MINST数据集的手写数字识别的主体代码

	# 定义网络 define neural network
	class DigitModule(Module):
	    def __init__(self):
	        # 计算顺序就会按照这里定义的顺序进行
	        sequential = Sequential([
	            layers.Linear2(in_dim=ROW_NUM * COLUM_NUM, out_dim=16, coe=2),
	            layers.Relu(16),
	            layers.Linear2(in_dim=16, out_dim=16, coe=2),
	            layers.Relu(16),
	            layers.Linear2(in_dim=16, out_dim=CLASS_NUM, coe=1),
	            layers.Sigmoid(CLASS_NUM)
	        ])
	        super(DigitModule, self).__init__(sequential)

	module = DigitModule()  # 创建模型 create module
	loss_func = SquareLoss(backward_func=module.backward)  # 定义损失函数 define loss function
	optimizer = SGD(module, lr=learning_rate)  # 定义优化器 define optimizer

	for i in range(EPOCH_NUM):  # 共训练EPOCH_NUM轮
	    trainning_loss = 0  # 计算一下当前一轮训练的loss值,可以没有
	    for data in train_loader:  # 遍历所有样本,train_loader是可迭代对象,保存了数据集中所有的数据
	        imgs, targets = data  # 将数据拆分成图片和标签
	        outputs = module(imgs)  # 将样本的输入值输入到自己的神经网络中
	        loss = loss_func(outputs, targets, transform=True)  # 计算loss / calculate loss
	        trainning_loss += loss.value
	        loss.backward()  # 通过反向传播计算梯度 / calculate gradiant through back propagation
	        optimizer.step()  # 通过优化器调整模型参数 / adjust the weights of network through optimizer
	    if i % TEST_STEP == 0:  # 每训练TEST_STEP轮就测试一下当前训练的成果
	        show_effect(i, module, loss_func, test_loader, i // TEST_STEP)
	        print("{} turn finished, loss of train set = {}".format(i, trainning_loss))

接下来逐个介绍编写的类,这些类在pytorch中都有同名同功能的类,是仿照pytorch来的:

  • Module类

与pytorch不同,只能有一个Sequential类(序列),在该类中定义好神经网络的各个层和顺序,然后传给Module类的构造函数
正向传播:调用Sequential的正向传播
反向传播:调用Sequential的反向传播
目前为止,这个类的大部分功能与Sequential相同,只是套了个壳保证与pytorch相同

  • lossfunction

有不同的loss函数,构造函数需要给他指定自己定义的神经网络的反向传播函数
调用loss函数会返回一个Loss类的对象,该类记录了loss值。
通过调用Loss类的.backward()方法就可以实现反向传播计算梯度
内部机制:
内部其实就是调用了自己定义的神经网络的反向传播函数
也算是对于pytorch的一个拙劣模仿,完全没必要,直接通过Module调用就好

  • 优化器:

目前只实现了随机梯度下降SGD
构造函数的参数是自己定义的Module。在已经计算过梯度之后,调用optimizer.step()改变Module内各个层的参数值
内部机制:
目前由于只有SGD一种算法,所以暂时也只是一个拙劣模仿
就是调用了一下Module.step(),再让Module调用Sequential.step(),最后由Sequential调用内部各个层的Layer.step()实现更新
梯度值在loss.backward的时候计算、保存在各个层中了

  • Layer类

有许多不同的层

共性
前向传播:

接受一个输入进行前向传播计算,输出一个输出
会将输入保存起来,在反向传播中要用

反向传播:

接受前向传播的输出的梯度值,计算自身参数(如Linear中的w和b)的梯度值并保存起来
输出值为前向传播的输入的梯度值,用来让上一层(可能没有)继续进行反向传播计算
这样不同的层之间就可以进行任意的拼装而不妨碍前向传播、反向传播的进行了

.step方法

更新自身的参数值(也可能没有,如激活层、池化层)

  • Sequential类

这个类也是继承自Layer,可以当作一层来使用

它把多个层按照顺序拼装到一起,在前向、反向传播时按照顺序进行计算

结合它的forward、backward方法来理解:

	def forward(self, x):
	    out = x
	    for layer in self.layers:
	        out = layer(out)
	    return out

	def backward(self, output_gradiant):
	    layer_num = len(self.layers)
	    delta = output_gradiant
	    for i in range(layer_num - 1, -1, -1):
	        # 反向遍历各个层, 将期望改变量反向传播
	        delta = self.layers[i].backward(delta)

	def step(self, lr):
	    for layer in self.layers:
	        layer.step(lr)
  • RNN类:循环神经网络层

继承自Layer,由于内容比较复杂故单独说明一下

RNN内部由一个全连接层Linear和一个激活层组成

前向传播

    def forward(self, inputs):
	        """
	        :param inputs: input = (h0, x) h0.shape == (batch, out_dim) x.shape == (seq, batch, in_dim)
	        :return: outputs: outputs.shape == (seq, batch, out_dim)
	        """
	        h = inputs[0]  # 输入的inputs由两部分组成
	        X = inputs[1]
	        if X.shape[2] != self.in_dim or h.shape[1] != self.out_dim:
	            # 检查输入的形状是否有问题
	            raise ShapeNotMatchException(self, "forward: wrong shape: h0 = {}, X = {}".format(h.shape, X.shape))

	        self.seq_len = X.shape[0]  # 时间序列的长度
	        self.inputs = X  # 保存输入,之后的反向传播还要用
	        output_list = []  # 保存每个时间点的输出
	        for x in X:
	            # 按时间序列遍历input
	            # x.shape == (batch, in_dim), h.shape == (batch, out_dim)
	            h = self.activation(self.linear(np.c_[h, x]))
	            output_list.append(h)
	        self.outputs = np.stack(output_list, axis=0)  # 将列表转换成一个矩阵保存起来
	        return self.outputs

反向传播

	def backward(self, output_gradiant):
	    """
	    :param output_gradiant: shape == (seq, batch, out_dim)
	    :return: input_gradiant
	    """
	    if output_gradiant.shape != self.outputs.shape:
	        # 期望得到(seq, batch, out_dim)形状
	        raise ShapeNotMatchException(self, "__backward: expected {}, but we got "
	                                           "{}".format(self.outputs.shape, output_gradiant.shape))

	    input_gradients = []
	    # 每个time_step上的虚拟weight_gradient, 最后求平均值就是总的weight_gradient
	    weight_gradients = np.zeros(self.linear.weights_shape())
	    bias_gradients = np.zeros(self.linear.bias_shape())
	    batch_size = output_gradiant.shape[1]

	    # total_gradient: 前向传播的时候是将x, h合成为一个矩阵,所以反向传播也先计算这个大矩阵的梯度再拆分为x_grad, h_grad
	    total_gradient = np.zeros((batch_size, self.out_dim + self.in_dim))
	    h_gradient = None

	    # 反向遍历各个时间层,计算该层的梯度值
	    for i in range(self.seq_len - 1, -1, -1):
	        # 前向传播顺序: x, h -> z -> h
	        # 所以反向传播计算顺序:h_grad -> z_grad -> x_grad, h_grad, w_grad, b_grad

	        # %%%%%%%%%%%%%%计算平均值的版本%%%%%%%%%%%%%%%%%%%%%%%
	        # h_gradient = (output_gradiant[i] + total_gradient[:, 0:self.out_dim]) / 2
	        # %%%%%%%%%%%%%%不计算平均值的版本%%%%%%%%%%%%%%%%%%%%%%%
	        #  计算h_grad: 这一时间点的h_grad包括输出的grad和之前的时间点计算所得grad两部分
	        h_gradient = output_gradiant[i] + total_gradient[:, 0:self.out_dim]  

	        # w_grad和b_grad是在linear.backward()内计算的,不用手动再计算了
	        z_gradient = self.activation.backward(h_gradient)  # 计算z_grad
	        total_gradient = self.linear.backward(z_gradient)  # 计算x_grad和h_grad合成的大矩阵的梯度

	        # total_gradient 同时包含了h和x的gradient, shape == (batch, out_dim + in_dim)
	        x_gradient = total_gradient[:, self.out_dim:]

	        input_gradients.append(x_gradient)
	        weight_gradients += self.linear.gradients["w"]
	        bias_gradients += self.linear.gradients["b"]

	    # %%%%%%%%%%%%%%%%%%计算平均值的版本%%%%%%%%%%%%%%%%%%%%%%%
	    # self.linear.set_gradients(w=weight_gradients / self.seq_len, b=bias_gradients / self.seq_len)
	    # %%%%%%%%%%%%%%%%%%不计算平均值的版本%%%%%%%%%%%%%%%%%%%%%%%
	    self.linear.set_gradients(w=weight_gradients, b=bias_gradients)  # 设置梯度值

	    list.reverse(input_gradients)  # input_gradients是逆序的,最后输出时需要reverse一下
	    print("sum(weight_gradients) = {}".format(np.sum(weight_gradients)))

	    # np.stack的作用是将列表转变成一个矩阵
	    return np.stack(input_gradients), h_gradient

以上就是numpy创建神经网络框架的详细内容,更多关于numpy神经网络的资料请关注我们其它相关文章!

(0)

相关推荐

  • pytorch之深度神经网络概念全面整理

    目录 1.神经网络训练过程 2.基础概念 2.1数学知识 2.1.1导数 2.1.2 梯度 2.2前向传播和反向传播 3.数据预处理手段 3.1 归一化  (normalization) 3.2 标准化(Standardization) 3.3 正则化 3.4 独热码编码(one hot) 4.数据处理库 4.1 numpy 4.2 pandas 4.3 matplotlib 5.训练集.测试集,测试集 6.损失函数 7.优化器 8.激活函数 9.hello world 10.总结 推荐阅读 点

  • Python如何使用神经网络进行简单文本分类

    深度学习无处不在.在本文中,我们将使用Keras进行文本分类. 准备数据集 出于演示目的,我们将使用  20个新闻组  数据集.数据分为20个类别,我们的工作是预测这些类别.如下所示: 通常,对于深度学习,我们将划分训练和测试数据. 导入所需的软件包 Python import pandas as pd import numpy as np import pickle from keras.preprocessing.text import Tokenizer from keras.models

  • pytorch动态神经网络(拟合)实现

    (1)首先要建立数据集 import torch #引用torch模块 import matplotlib.pyplot as plt #引用画图模块 x=torch.unsqueeze(torch.linspace(-1,1,100),dim=1)#产生(-1,1)的100个点横坐标,dim表示维度,表示在这里增加第二维 y=x.pow(2)+0.2*torch.rand(x,size()) #0.2*torch.rand(x,size())是为了产生噪点使数据更加真实 (2)建立神经网络 i

  • 教你使用Python建立任意层数的深度神经网络

    目录 一.神经网络介绍: 二.数据集 三.激活函数 四.正向传播 五.损失函数 六.反向传播 七.总体思路 一.神经网络介绍: 神经网络算法参考人的神经元原理(轴突.树突.神经核),在很多神经元基础上构建神经网络模型,每个神经元可看作一个个学习单元.这些神经元采纳一定的特征作为输入,根据自身的模型得到输出. 图1 神经网络构造的例子(符号说明:上标[l]表示与第l层:上标(i)表示第i个例子:下标i表示矢量第i项) 图2 单层神经网络示例 神经元模型是先计算一个线性函数(z=Wx+b),接着再计

  • python神经网络编程之手写数字识别

    写在之前 首先是写在之前的一些建议: 首先是关于这本书,我真的认为他是将神经网络里非常棒的一本书,但你也需要注意,如果你真的想自己动手去实现,那么你一定需要有一定的python基础,并且还需要有一些python数据科学处理能力 然后希望大家在看这边博客的时候对于神经网络已经有一些了解了,知道什么是输入层,什么是输出层,并且明白他们的一些理论,在这篇博客中我们仅仅是展开一下代码: 然后介绍一下本篇博客的环境等: 语言:Python3.8.5 环境:jupyter 库文件: numpy | matp

  • python机器学习之神经网络

    手写数字识别算法 import pandas as pd import numpy as np from sklearn.neural_network import MLPRegressor #从sklearn的神经网络中引入多层感知器 data_tr = pd.read_csv('BPdata_tr.txt') # 训练集样本 data_te = pd.read_csv('BPdata_te.txt') # 测试集样本 X=np.array([[0.568928884039633],[0.37

  • numpy创建神经网络框架

    目录 神经网络框架使用方法及设计思想 项目介绍 框架介绍 神经网络框架使用方法及设计思想 在框自己手写架上基本模仿pytorch,用以学习神经网络的基本算法,如前向传播.反向传播.各种层.各种激活函数 采用面向对象的思想进行编程,思路较为清晰 想要神经网络的同学们可以参考一下 代码大体框架较为清晰,但不否认存在丑陋的部分,以及对于pytorch的拙劣模仿 项目介绍 MINST_recognition: 手写数字识别,使用MINST数据集 训练30轮可以达到93%准确度,训练500轮左右达到95%

  • 使用 pytorch 创建神经网络拟合sin函数的实现

    我们知道深度神经网络的本质是输入端数据和输出端数据的一种高维非线性拟合,如何更好的理解它,下面尝试拟合一个正弦函数,本文可以通过简单设置节点数,实现任意隐藏层数的拟合. 基于pytorch的深度神经网络实战,无论任务多么复杂,都可以将其拆分成必要的几个模块来进行理解. 1)构建数据集,包括输入,对应的标签y 2) 构建神经网络模型,一般基于nn.Module继承一个net类,必须的是__init__函数和forward函数.__init__构造函数包括创建该类是必须的参数,比如输入节点数,隐藏层

  • idea创建springMVC框架和配置小文件的教程图解

    这个框架主要还是思想,之后,,,还是创建项目好了, 1.新建一个项目 新建一个maven,并且选择webapp类型. 2.点击next选项 这里面的两个选项可以随便填,但是Artifactid一般是项目名,第一个可以是自己定义的名称了, 3.继续点next 在这我们可以添加name=archetypeCatalog,internal,可以在创建项目的时候快一点,3.创建好了项目之后就把我创建的一个小案例放上了 1.创建项目的流程01.引入需要的pom文件节点02.web.xml文件中配置核心控制

  • numpy创建单位矩阵和对角矩阵的实例

    在学习linear regression时经常处理的数据一般多是矩阵或者n维向量的数据形式,所以必须对矩阵有一定的认识基础. numpy中创建单位矩阵借助identity()函数.更为准确的说,此函数创建的是一个n*n的单位数组,返回值的dtype=array数据形式.其中接受的参数有两个,第一个是n值大小,第二个为数据类型,一般为浮点型.单位数组的概念与单位矩阵相同,主对角线元素为1,其他元素均为零,等同于单位1.而要想得到单位矩阵,只要用mat()函数将数组转换为矩阵即可. >>>

  • 使用idea创建web框架和配置struts的方法详解

    如何用idea创建web框架和配置struts 创建好一个project右键project,选择第二项 选中Web Application,然后点击OK 创建文件夹名为lib(用来存放jar包)和classes(用来存放输出文件) 在官网下载struts,把jar放入lib中,然后右键lib,选择 add as library(导入成功) 点击file-project structure-modules-path 把两个路径都改为web文件夹下面的classes(刚创建的) 总结 到此这篇关于使

  • 创建与框架无关的JavaScript插件

    JavaScript 中的插件使我们能够扩展语言,以实现所需的某些强大(或不够强大)的功能.插件/库本质上是打包的代码,可以使我们免于一遍又一遍地编写相同的东西(功能). 在 JavaScript 生态系统中,有数百个框架,这些框架中的每一个都为我们提供了一个创建插件的系统,以便为框架添加新的东西. 如果你看一下 NPM 注册表,几乎所有的 JavaScript 插件都是在那里发布的,你会看到有超过一百万个插件以简单库和框架的形式发布. 为每个框架创建插件的方式可能会有很大不同.例如,Vue.j

  • Python 用NumPy创建二维数组的案例

    前言 上位机实战开发先放一放,今天来学习一个新的内容-NumPy的使用 1 一维数组 例:用普通方法生成一维数组 num = [0 for i in range(1,5)] # 创建一维数组 print(num) # 打印数组 print("-"*50) # 分割线 num[2]=6 # 将第三个元素修改位6 print(num) # 打印数组 print("-"*50) # 分割线 运行结果 例:用numpy生成一维数组 from numpy import * m

  • 浅谈Python numpy创建空数组的问题

    一.问题描述: 有一个shape为(308, 2)的二维数组,以及单独的一个数字,需要保存到csv文件中,这个单独的数字让其保存到第3列第一行的位置. 二.具体的实现: 首先要想把一个(308, 2)的二维数组和一个数字给拼接起来,直接拼接没办法实现,因为行数和列数都不同的两个ndarry是无法拼接的(此处按照目前我学的理解,是无法直接拼接的,如果可以的话,麻烦评论一下). 然后我首先想到的解决方法就是先建一个(308,1)的二维数组,然后令这个二维数组的第一个元素设置成那个数字,然后进行拼接,

  • C++实现神经网络框架SimpleNN的详细过程

    目录 Features Dependencies Platform To Do Usage SimpleNN is a simple neural network framework written in C++.It can help to learn how neural networks work. 源码地址:https://github.com/Kindn/SimpleNN Features Construct neural networks. Configure optimizer a

  • 纯用NumPy实现神经网络的示例代码

    摘要: 纯NumPy代码从头实现简单的神经网络. Keras.TensorFlow以及PyTorch都是高级别的深度学习框架,可用于快速构建复杂模型.前不久,我曾写过一篇文章,对神经网络是如何工作的进行了简单的讲解.该文章侧重于对神经网络中运用到的数学理论知识进行详解.本文将利用NumPy实现简单的神经网络,在实战中对其进行深层次剖析.最后,我们会利用分类问题对模型进行测试,并与Keras所构建的神经网络模型进行性能的比较. Note:源码可在我的GitHub中查看. 在正式开始之前,需要先对所

随机推荐