草庐IT

Python 实现深度学习(3): 神经网络的forward实现

修雨轩陈 2023-03-28 原文

 

写在最前:

写在最前, 我把代码和整理的文档放在github上了

https://github.com/Leezhen2014/python_deep_learning

 

 

Forward指的是神经网络推理,forward与感知机相比,多了一个激活函数的模块。因此本章需要实现激活函数,另外也需要重新实现y=w*x+b。本章的顺序如下:

 

3.1 激活函数的实现

在感知机中讲到用阈值来切换输出,这样的函数称为“阶跃函数”:一旦输入超出了阈值,就切换输出。阶跃函数也算是一种激励函数

需要注意激励函数应该具有以下数学特性:

第一:由于后期训练过程中会对激励函数求导,因此这些函数必须符合数学上的可导。

第二:必须为非线性的函数。这可以用公式推一下:

若激励函数为线性函数

从本质上看,激活函数等同于原来的输入的:

 

即:

第i层的输入是第i+1层的k倍。

从表象上看,加深网络层次已经失去了意义等效于无隐含层的网络

 

3.1.1 Sigmoid 函数的实现

Sigmoid函数在(-1,1)区间内变化较大,超出这个范围以后变化较小,可以很好的影响。

 

 

 

  1 def Sigmoid(x):
  2     return 1/(np.exp(-x) +1)
  3 
  4 if __name__ == '__main__':
  5     x = np.arange(-5.0, 5.0, 0.1)
  6     y = Sigmoid(x)
  7 
  8     plt.plot(x,y)
  9     plt.ylim(-0.1,1.1)
 10     plt.show()

3.1.2 阶跃函数

  1 def step_func(x):
  2     temp = x.copy()
  3     temp = np.where(x > 0, temp, 0)
  4     temp = np.where(x <= 0, temp, 1)
  5     return temp
  6 
  7 
  8 if __name__ == '__main__':
  9     x = np.arange(-5.0, 5.0, 0.1)
 10 
 11     y = step_func(x)
 12 
 13     plt.plot(x,y)
 14     plt.ylim(-1.1,1.1)
 15     plt.show()

 

 

3.1.3 Relu 系列

 

 

Relu(Rectified Linear Unit) 函数在输入值大于0的情况下保持不变,在输入值小于0的情况下,输出等于0。

阶跃函数和sigmoid函数都属于非线性的函数,

  1 def Relu(x):
  2     return np.maximum(0,x)
  3 
  4 if __name__ == '__main__':
  5     x = np.arange(-5.0, 5.0, 0.1)
  6 
  7     y = Relu(x)
  8 
  9     plt.plot(x,y)
 10     plt.ylim(-1.1,5.1)
 11     plt.show()

 

 

3.2 forward的流程

主要是介绍y=WX+b的实现。神经网络的forward本质是多维数组的运算+激励函数。激活函数已经实现了,因此只要将多维数组的运算了解清楚,便可以实现forward。forward的流程如下:

p.s.: f即为激活函数

本质上是矩阵的乘法,借助np.dot可以实现;在此不赘述

 

3.3 输出层的设计与实现

目前来看,神经网络在分类的问题上可以大致分为两类:

1. 分类问题:数据属于哪个类别,可以使用恒等函数,直接获取预测结果。

2. 回归问题:根据输入,预测一个连续的数值问题。可以使用softmax。

Ps分类问题的输出层也是可以使用softmax的,只不过用softmax以后得到的数值是一个线性的数值,还需要选取阈值才能划分为类别。

恒等函数是不需要实现了,神经网络的输出节点就是label的输出,如下图所示:

Softmax函数的数学公式如下:

Equation 3 softmax函数

从公式中可以看出,输出层的各个神经元的输出都会受到输入信号的影响,如下图所示。

Figure 3 softmax 的表达图

  1 def softmax(x):
  2     '''
  3     softmax 实现,没有考虑数值溢出
  4     :param x: ndarray
  5     :return: y, ndarray
  6     '''
  7     a = np.exp(x)
  8     sum_exp = np.sum(a)
  9     y= a/sum_exp
 10     return y

 

上图的代码是按照公式实现的,但是没有考虑数值溢出的情况;由于是exp是指数函数,当指数特别大的时候,进行除法的时候会的时候会出现数值溢出。为了避免以上情况,将分子和分母同时乘上常量C(必须足够大)

 

  1 def softmax(x):
  2     '''
  3     softmax 实现
  4     :param x: ndarray
  5     :return: y, ndarray
  6     '''
  7     C = np.max(x)
  8     exp_a = np.exp(x - C)
  9     sum_exp = np.sum(exp_a)
 10     y= exp_a / sum_exp
 11     return y

 

3.4测试神经网络的推理

在经过上述的准备工作后, 我们就可以组装成一个简单的推理网络;

假设, 我们的神经网络是简单的全连接层, 且手里已经有了网络的权重(sample_weight.pkl)。

我们要做的是对minst手写体识别,数据集用load_mnist()方法获取。

具体代码可以看github: https://github.com/Leezhen2014/python_deep_learning

  1 # -*- coding: utf-8 -*-
  2 # @File  : day7.py
  3 # @Author: lizhen
  4 # @Date  : 2020/2/4
  5 # @Desc  : 第二篇的实现: 对文件的实现
  6 
  7 import sys, os
  8 import numpy as np
  9 import pickle
 10 from src.datasets.mnist import load_mnist
 11 from src.common.functions import sigmoid, softmax
 12 
 13 
 14 def get_data():
 15     (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
 16     return x_test, t_test
 17 
 18 
 19 def init_network():
 20     with open("../datasets/sample_weight.pkl", 'rb') as f:
 21         network = pickle.load(f)
 22     return network
 23 
 24 
 25 def predict(network, x):
 26     W1, W2, W3 = network['W1'], network['W2'], network['W3']
 27     b1, b2, b3 = network['b1'], network['b2'], network['b3']
 28 
 29     a1 = np.dot(x, W1) + b1
 30     z1 = sigmoid(a1)
 31     a2 = np.dot(z1, W2) + b2
 32     z2 = sigmoid(a2)
 33     a3 = np.dot(z2, W3) + b3
 34     y = softmax(a3)
 35 
 36     return y
 37 
 38 
 39 x, t = get_data()
 40 network = init_network()
 41 accuracy_cnt = 0
 42 for i in range(len(x)):
 43     y = predict(network, x[i])
 44     p= np.argmax(y)
 45     if p == t[i]:
 46         accuracy_cnt += 1
 47 
 48 print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

 

打印输出正确率:

输出:

Accuracy: 0.9352

 

 

------------------------

好了,今天到此为止。

有关Python 实现深度学习(3): 神经网络的forward实现的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  4. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  5. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  6. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  7. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  10. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

随机推荐