TensorFlow什么的都弱爆了,强者只用Numpy搭建神经网络

栏目: Python · 发布时间: 5年前

TensorFlow什么的都弱爆了,强者只用Numpy搭建神经网络

大数据文摘出品

作者:蒋宝尚

很多同学入门机器学习之后,直接用TensorFlow调包实现神经网络,对于神经网络内在机理知之甚少。

编程语言与技术框架变化更新非常之快,理解背后的原理才是王道。下面文摘菌和大家一起用Numpy实现一步一步实现神经网络。

此篇文章旨在帮大家梳理神经网络知识点,且此篇文章是第一部分,只是简单搭一个简单的框架。暂时不涉及梯度下降、学习率调参等知识点。

TensorFlow什么的都弱爆了,强者只用Numpy搭建神经网络

最简单的神经网络包含三个要素,输入层,隐藏层以及输出层。关于其工作机理其完全可以类比成一个元函数:Y=W*X+b。

一个简单的神经网络可以理解为两次一元函数的输入和输出。

第一次:Y 1 = A 1 (W 1 *X+b 1 ) ,其中X是原始数据的输入,A 1 代表激活函数。

第二次:Y 2 = A 2 (W 2 *Y 1 +b 2 ),其中Y 1 是第一次的输出, A 2 是激活函数。参数W 1 、W 2 、b 1 、b 2 原则上各不相同。

本篇文章我们用到的激活函数有两个,一个是tan(x),另一个是softmax。两者的函数曲线如下。

TensorFlow什么的都弱爆了,强者只用Numpy搭建神经网络

两个函数都有相同的特点,即函数值在零点左右变化较大,当输入值远离零点,其输出较稳定。

首先导入相关的库,需要两个库,一个用于科学计算的Numpy,另一个是math。

<span>import numpy as np</span>

<span>import math</span>

然后定义激活函数,

<span><span>def</span> <span>tanh(x)</span>:</span>

<span> <span>return</span> np.tanh(x)</span>

<span><br /></span>

<span><span>def</span> <span>softmax(x)</span>:</span>

<span> exp=np.exp(x-x.max())</span>

<span> <span>return</span> exp/exp.sum()</span>

这两个激活函数,其中tanh函数,Numpy直接内嵌。softmax根据数学定义进行设置。第二个激活函数因为是指数函数,其值会变化较大,所以我们用x-x.max 缩小其变化范围,这对结果不影响。

我们使用的图片大小是 28*28像素。以后会用手写数字数据集训练网络,所以会有10个数字输入,分别是[1,2,3,4,5,6,7,8,9,10]。所以要先定义三个列表。

<span>dinensions=[<span>28</span>*<span>28</span>,<span>10</span>]</span>

<span><br /></span>

<span>activation=[<span>tanh</span>,softmax]</span>

<span><br /></span>

<span>distribution=[{<span>'b'</span>:[<span>0</span>,<span>0</span>]},</span>

<span> {<span>'b'</span>:[<span>0</span>,<span>0</span>],<span>'w'</span>:[-math.<span>sqrt</span>(<span>6</span>/(dinensions[<span>0</span>]+dinensions[<span>1</span>])),math.<span>sqrt</span>(<span>6</span>/(dinensions[<span>0</span>]+dinensions[<span>1</span>]))]}]</span>

dinensions列表里面包含两个数,第一个是图片的像素大小,第二个是数字的输入变化量。

activation列表包含两个激活函数,分别为tanh,softmax。

distribution 列表里面对应的是字典格式的数据,分别对应神经网络参数取值范围。

其中第一层不包含参数W。

<span>def init<span>_parameters_</span>b(layer):</span>

<span> dist=distribution[<span>layer</span>][<span>'b'</span>]</span>

<span> return np.random.rand(dinensions[layer])*(dist[1]-dist[0])+dist[0] #使得生成的随机数在 b 的区间内</span>

<span><br /></span>

<span>def init<span>_parameters_</span>w(layer):</span>

<span> dist=distribution[<span>layer</span>][<span>'w'</span>]</span>

<span> return np.random.rand(dinensions[layer-1],dinensions[layer])*(dist[1]-dist[0])+dist[0] #使得生成的随机数在 b 的区间内</span>

上面代码是对b和w这两个参数初始化,因为我们输入的是28*28个数字,输出的是10个数字。所以第一层的 b 也有28*28个数字组成。根据矩阵的乘法规则,第二层的时候,w的维度只有是28*28行,10列才能满足输出的10个数字。因此第二层的b是10个数字。

dinensions[X] 意思是取切片,dinensions[1] 取得是10,dinensions[0],取得是28*28。

又因为np.random.rand()这一函数输出值的范围在[0,1],括号里面的参数(即dinensions[layer]只是确保输出的数字个数满足要求),所以为了让输出的值在一开始设置的 b 的区间内,我们设置先乘(dist[1]-dist[0])然后加上dist[0]。dist[1]和dist[0]分别对应参数的上下限。

<span><span>def</span> <span>init_parameters()</span>:</span>

<span> parameters=[]</span>

<span> <span>for</span> i <span>in</span> range(len(distribution)):</span>

<span> layer_parameters={}</span>

<span> <span>for</span> j <span>in</span> distribution[i].keys():</span>

<span> <span>if</span> j==<span>'b'</span>:</span>

<span> layer_parameters[<span>'b'</span>]=init_parameters_b(i)</span>

<span> <span>continue</span></span>

<span> <span>if</span> j==<span>'w'</span>:</span>

<span> layer_parameters[<span>'w'</span>]=init_parameters_w(i)</span>

<span> <span>continue</span></span>

<span> parameters.append(layer_parameters)</span>

<span> <span>return</span> parameters</span>

上面代码是将三个参数的初始化集成达到一个函数里面。

先定义一个空列表(不要写错成空字典)是为了将三个参数统一输出。

注:字典类型不能用append,列表可以用,列表.append(字典) 也是可以的。

然后从零开始遍历distribution。 用if循环语句,目的是把参数全部包含进来。

第二层for循环和if语句是判断,并正确添加参数。

<span>parameters=init_parameters() <span>#将参数赋值给新的变量。</span></span>

<span><span>def</span> <span>predict(img,parameters)</span>:</span>

<span> I0_in=img+parameters[<span>0</span>][<span>'b'</span>]</span>

<span> I0_out=activation[<span>0</span>](I0_in)</span>

<span> I1_in=np.dot(I0_out,parameters[<span>1</span>][<span>'w'</span>]+parameters[<span>1</span>][<span>'b'</span>])</span>

<span> I1_out=activation[<span>1</span>](I1_in)</span>

<span> <span>return</span> I1_out</span>

定义输出函数,思路是这样的:输入数据后,根据函数:y=wx+b,进行变换,第一层w全为1。然后经过激活函数(第一个激活函数是tanh,所以用activation[0]),得出第一层的输入I0_out。 然后进入第二层,第一层的输出作为输入,根据函数:y=wx+b,进行变换,第二层的w为parameters[1]['w'],第二层的b为parameters[1]['b']。然后再经过激活函数softmax,得到输出。

predict(np.random.rand(784),parameters).argmax()

最后,随便输入一个784维数据(像素),都可以输出一个图片标签。

TensorFlow什么的都弱爆了,强者只用Numpy搭建神经网络

预测图片中的数字

好了,我们第一个简单的神经网络就搭建好了,关于如何使用梯度下降和学习率,如何训练网络以及如何加载图片数据,我们在以后的文章中会介绍。

注:此篇文章受B站up主大野喵渣的启发,并参考了其代码,感兴趣的同学可以去B站观看他关于神经网络的教学视频。

视频地址:

https://www.bilibili.com/video/av51197008

实习/全职编辑记者招聘ing

加入我们,亲身体验一家专业科技媒体采写的每个细节,在最有前景的行业,和一群遍布全球最优秀的人一起成长。坐标北京·清华东门,在大数据文摘主页对话页回复 “招聘” 了解详情。简历请直接发送至zz@bigdatadigest.cn

点「在看」的人都变好看了哦


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

刘强东自述

刘强东自述

刘强东 / 中信出版集团 / 2016-6-1 / 49.00

京东 1998年,京东还只是中关村一个经营光磁生意的小柜台,月营业额仅有几万元,如今则已经成长为中国营收规模超大的互联网企业,2015年全年营收1813亿,总交易额达到4627亿元; 为解决电商“最后一公里”的痛点,创立并自建B2C物流模式; 经常被争议,却始终坚持“不挣快钱”,选择上市不是因为“缺钱”,只为让合作伙伴睡得着觉,为用户和社会创造价值,由此成就让整个华尔街一片京东红......一起来看看 《刘强东自述》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具