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

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

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

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


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

查看所有标签

猜你喜欢:

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

Mastering Regular Expressions, Second Edition

Mastering Regular Expressions, Second Edition

Jeffrey E F Friedl / O'Reilly Media / 2002-07-15 / USD 39.95

Regular expressions are an extremely powerful tool for manipulating text and data. They have spread like wildfire in recent years, now offered as standard features in Perl, Java, VB.NET and C# (and an......一起来看看 《Mastering Regular Expressions, Second Edition》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具