我的编程空间,编程开发者的网络收藏夹
学习永远不晚

numpy创建神经网络框架

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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神经网络的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

numpy创建神经网络框架

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Linux下怎么安装卷积神经网络框架caffe

这篇文章主要介绍了Linux下怎么安装卷积神经网络框架caffe的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Linux下怎么安装卷积神经网络框架caffe文章都会有所收获,下面我们一起来看看吧。caffe是一
2023-06-27

Keras中怎么创建一个神经网络模型

在Keras中创建神经网络模型通常包括以下步骤:1.导入必要的库:import tensorflow as tffrom tensorflow import keras2.定义模型架构:model = keras.Sequentia
Keras中怎么创建一个神经网络模型
2024-03-14

如何在PyTorch中创建一个神经网络模型

在PyTorch中创建神经网络模型通常需要定义一个继承自torch.nn.Module类的自定义类。下面是一个简单的示例:import torchimport torch.nn as nnclass SimpleNN(nn.Module
如何在PyTorch中创建一个神经网络模型
2024-03-05

pytorch如何搭建卷积神经网络

在PyTorch中搭建卷积神经网络通常涉及以下步骤:导入必要的库和模块:import torchimport torch.nn as nnimport torch.nn.functional as F定义卷积神经网络模型类:class
pytorch如何搭建卷积神经网络
2024-04-08

Python卷积神经网络图片分类框架的示例分析

小编给大家分享一下Python卷积神经网络图片分类框架的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!整体结构config在config文件夹下的config.py中主要定义数据集的位置,训练轮数,batch_si
2023-06-25

如何用tensorflow搭建卷积神经网络

要用TensorFlow搭建卷积神经网络(CNN),首先需要导入TensorFlow库并定义网络的结构。以下是一个简单的示例代码,展示了如何在TensorFlow中搭建一个包含两个卷积层和两个全连接层的CNN:import tensorf
如何用tensorflow搭建卷积神经网络
2024-04-03

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录