如何协同机制构建框架一个python框架

Copyright & 2012 - .Python部落()组织翻译,禁止转载,欢迎转发。
在这篇博客里,我们将从零开始搭建一个三层的神经网络。我们不会对用到的数学原理一一赘述,但我保证你可以直观地了解到我们在做什么。另外,你也可以通过文章内的链接来获取更详细的信息。这儿我就假定你已经熟悉基础的微积分和机器学习的一些概念,比如分类和规范化,最好还能懂得一些优化神经网络的技术,比如梯度下降法。当然,即便你对以上提到的这些都不是很了解,我相信你还是能从这篇文章找到乐子的;-)那从头来做到底有什么意义?我想,即便是以后使用神经网络库来做开发,比如PyBrain,一次(甚至多次)从头开始搭建网络的经历仍然可以作为极其宝贵的练习经验。它能够帮助你更好地了解神经网络的运作机制。而这也是设计高效的模型必经之路。本文所展示的实例代码追求简单易懂,因此在效率上会打折扣。在我的下一篇推文中,我将展示如何通过Theano来实现一个高效率的神经网络。
生成数据集
让我们从生成所需要的数据集开始吧。幸运的是,scikit-learn提供了一些很有用的数据集生成器,让我们不必为之再造轮子,我们先试试make_moons。
生成了两类数据集,分别用红点和蓝点表示。你可以把蓝点想象成男性病人,红点想象成女性病人,把x轴和y轴想象成药物治疗剂量。我们希望通过训练使得机器学习分类器能够在给定的x轴y轴坐标上预测正确的分类情况。我们无法用直线就把数据划分,可见这些数据样本呈非线性。那么,除非你手动构造非线性功能(例如多项式),否则,诸如逻辑回归(Logistic Regression)这类线性分类器将无法适用于这个案例。事实上,这也正是神经网络的一大主要优势。神经网络的隐藏层会为你去学习特征,所以你不需要为构造特征这件事去操心。
为了证明(学习特征)这点,让我们来训练一个逻辑回归分类器吧。以x轴,y轴的值为输入,它将输出预测的类(0或1)。为了简单起见,这儿我们将直接使用scikit-learn里面的逻辑回归分类器。
图表向我们展示了逻辑回归分类器经过学习最终得到的决策边界。尽管它尽可能地将数据区分为两类,却不能捕获到数据呈“月亮形状”的特性。
训练一个神经网络
现在,我们搭建由一个输入层,一个隐藏层,一个输出层组成的三层神经网络。输入层中的节点数由数据的维度来决定,也就是2个。相应的,输出层的节点数则是由类的数量来决定,也是2个。(因为我们只有一个预测0和1的输出节点,所以我们只有两类输出,实际中,两个输出节点将更易于在后期进行扩展从而获得更多类别的输出)。以x,y坐标作为输入,输出的则是两种概率,一种是0(代表女),另一种是1(代表男)。结果如下:
我们可以选择隐藏层的维度。放进去的节点越多,实现的功能就可以越复杂。但是维度过高也是会有代价的。首先,更多的预测以及学习网络参数意味着更高的计算强度,更多的参数也会带来过拟合的风险。那么该如何判断隐藏层的规模呢?尽管总会有许多通用性很好的引导和推荐,但问题的差异性也不该被忽视。在我看来,选择规模这件事绝不仅仅是门科学,它更像是一门艺术。通过待会儿的演示,我们可以看到隐藏层里的节点数是怎么影响我们的输出的。另外,我们还需要为隐藏层选择激活函数(activation function)。激活函数会将输入转化成输出。非线性的激活函数可以帮助我们处理非线性的假设。通常选用的激活函数有tanh, the sigmoid function, ReLUs。在这里我们将使用tanh这样一个适用性很好地函数。这些函数有一个优点,就是通过原始的函数值便可以计算出它们的导数。例如tanh的导数就是1-tanh2x。这让我们可以在推算出tanhx一次后就重复利用这个得到导数值。鉴于我们希望我们的网络输出的值为概率,所以我们将使用softmax作为输出层的激活函数,这个函数可以将原始的数值转化为概率。如果你很熟悉逻辑回归函数,你可以把它当做是逻辑回归的一般形式。
我们的网络是如何做出预测的呢?
神经网络通过前向传播做出预测。前向传播仅仅是做了一堆矩阵乘法并使用了我们之前定义的激活函数。如果该网络的输入x是二维的,那么我们可以通过以下方法来计算其预测值 :
zi是第i层的输入,ai是该层应用激活函数后的输出i,Wi,bi是需要我们通过训练数据来获取的神经网络参数,你可以把它们当作在网络的层与层之间用于转化数据的矩阵。这些矩阵的维度可以通过上面的矩阵乘法看出来。如果我们在隐藏层上使用500个节点,那么就有 , , , 。可以看出,隐藏层的规模与可以用在隐藏层的节点数是呈正相关的。
研究参数是为了找到能够使我们的训练数据集错误率最小化的参数()。但该如何定义错误呢?我们在这里会用损失函数(loss function)来检测错误。通常对softmax的输出,我们会选择明确的交叉熵损失(cross-entropy loss)(或者叫负对数似然)。如果我们有 N个训练示例,C个类别,那么预测相对于真实的有标签数据的损失则可以通过如下方法来计算获得:
这个公式看起来很复杂,它的功能就是对我们的训练示例进行求和,并加上预测值错误造成的损失。所以,标签值与预测值相差越大,损失就越大。通过寻找降低错误率的参数,我们可以实现最大似然。我们可以使用梯度下降法来找到这些参数,这里,我会使用一种最普遍的方法:批量梯度下降法。这种方法的学习速率是固定的。它的衍化版例如SGD(随机梯度下降stochastic gradient descent)或者最小批量梯度下降(minibatch gradient descent)通常在实际使用中会有更好的效果。所以,如果您真的想要学习或者使用,那么请选择这些方法,最好还要能够实现逐渐衰减学习速率。作为输入,梯度下降法需要各参数对应损失函数的梯度(导数的参数),
。为了计算这些梯度,我们使用著名的后向传播算法。这种方法在通过输出计算梯度方面效率很高。您可以通过这些链接(链接1,链接2)来了解它,在这里我就不详细介绍它的原理了。通过后向传播公式,我们找到了下面这些数据:
接下来我们就要实现这个三层的神经网络了。首先,我们需要定义一些对用于梯度下降法的变量和参数。
首先,我们先实现之前定义的损失函数,这将用来评估我们的模型。
我们还要实现一个用于计算输出的辅助函数。它会通过定义好的前向传播方法来返回拥有最大概率的类别。
最后是训练神经网络的函数。它会使用我们之前找到的后向传播导数来进行批量梯度下降运算。
一个隐藏层规模为3的网络
让我们看看训练一个隐藏层规模为3的网络会发生什么。
喔~这看起来相当不错。我们的神经网络能够成功地找到区分不同类别的决策边界了。
变更隐藏层规模
在刚刚的示例中,我们选择了一个隐藏层规模为3的网络,现在我们来看看不同规模的隐藏层会带来什么样的效果。
我们可以看到,低维度的隐藏层很好地抓住了数据的整体趋势。高维度的隐藏层则显现出过拟合的状态。相对于整体性适应,它们更倾向于精确记录各个点。如果我们要在一个分散的数据集上进行测试(你也应该这么做),那么隐藏层规模较小的模型会因为更好的通用性从而获得更好的表现。虽然我们可以通过强化规范化来抵消过拟合,但选择正确的隐藏层规模相对来说会更“经济实惠”一点。
这儿有些可以帮助你更进一步理解代码的干货:1.
用最小批量梯度下降法替换梯度下降法来训练网络,这会帮助你的模型在实战中获得更好的表现。2.
我们使用的是固定学习速率来进行梯度下降。试着去实现学习速率逐步衰减的方法。3.
本文中,我们用tanh作为激活函数。试试其他的激活函数(有些我们之前已经提到过)。记住,改变激活函数也就意味着改变了后向传播导数。4.
将网络从两个类别拓展到三个类别。您将需要为此准备一个合适的数据集。5.
将网络拓展到四层,对不同层的规模进行测试。增加新的隐藏层意味着你的前向传播和后向传播代码都需要调整。所有的代码都可以在Github的iPython notebook上找到。欢迎您提出问题或者反馈:-)
英文原文:/2015/09/implementing-a-neural-network-from-scratch/
译者:海獭先生
了解野狗,请点击阅读原文
本文来自微信公众账号提交,由微讯啦收录,转载请注明出处。
微信扫码 分享文章<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&使用Web框架 - 廖雪峰的官方网站
使用Web框架
了解了WSGI框架,我们发现:其实一个Web App,就是写一个WSGI的处理函数,针对每个HTTP请求进行响应。
但是如何处理HTTP请求不是问题,问题是如何处理100个不同的URL。
每一个URL可以对应GET和POST请求,当然还有PUT、DELETE等请求,但是我们通常只考虑最常见的GET和POST请求。
一个最简单的想法是从environ变量里取出HTTP请求的信息,然后逐个判断:
def application(environ, start_response):
method = environ[&#39;REQUEST_METHOD&#39;]
path = environ[&#39;PATH_INFO&#39;]
if method==&#39;GET&#39; and path==&#39;/&#39;:
return handle_home(environ, start_response)
if method==&#39;POST&#39; and path=&#39;/signin&#39;:
return handle_signin(environ, start_response)
只是这么写下去代码是肯定没法维护了。
代码这么写没法维护的原因是因为WSGI提供的接口虽然比HTTP接口高级了不少,但和Web App的处理逻辑比,还是比较低级,我们需要在WSGI接口之上能进一步抽象,让我们专注于用一个函数处理一个URL,至于URL到函数的映射,就交给Web框架来做。
由于用Python开发一个Web框架十分容易,所以Python有上百个开源的Web框架。这里我们先不讨论各种Web框架的优缺点,直接选择一个比较流行的Web框架——来使用。
用Flask编写Web App比WSGI接口简单(这不是废话么,要是比WSGI还复杂,用框架干嘛?),我们先用easy_install或者pip安装Flask:
$ easy_install flask
然后写一个app.py,处理3个URL,分别是:
GET /:首页,返回Home;
GET /signin:登录页,显示登录表单;
POST /signin:处理登录表单,显示登录结果。
注意噢,同一个URL/signin分别有GET和POST两种请求,映射到两个处理函数中。
Flask通过Python的在内部自动地把URL和函数给关联起来,所以,我们写出来的代码就像这样:
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route(&#39;/&#39;, methods=[&#39;GET&#39;, &#39;POST&#39;])
def home():
return &#39;&h1&Home&/h1&&#39;
@app.route(&#39;/signin&#39;, methods=[&#39;GET&#39;])
def signin_form():
return &#39;&#39;&#39;&form action=&/signin& method=&post&&
&p&&input name=&username&&&/p&
&p&&input name=&password& type=&password&&&/p&
&p&&button type=&submit&&Sign In&/button&&/p&
&/form&&#39;&#39;&#39;
@app.route(&#39;/signin&#39;, methods=[&#39;POST&#39;])
def signin():
# 需要从request对象读取表单内容:
if request.form[&#39;username&#39;]==&#39;admin&#39; and request.form[&#39;password&#39;]==&#39;password&#39;:
return &#39;&h3&Hello, admin!&/h3&&#39;
return &#39;&h3&Bad username or password.&/h3&&#39;
if __name__ == &#39;__main__&#39;:
运行python app.py,Flask自带的Server在端口5000上监听:
$ python app.py
* Running on http://127.0.0.1:5000/
打开浏览器,输入首页地址http://localhost:5000/:
首页显示正确!
再在浏览器地址栏输入http://localhost:5000/signin,会显示登录表单:
输入预设的用户名admin和口令password,登录成功:
输入其他错误的用户名和口令,登录失败:
实际的Web App应该拿到用户名和口令后,去数据库查询再比对,来判断用户是否能登录成功。
除了Flask,常见的Python Web框架还有:
:全能型Web框架;
:一个小巧的Web框架;
:和Flask类似的Web框架;
:Facebook的开源异步Web框架。
当然了,因为开发Python的Web框架也不是什么难事,我们后面也会自己开发一个Web框架。
有了Web框架,我们在编写Web应用时,注意力就从WSGI处理函数转移到URL+对应的处理函数,这样,编写Web App就更加简单了。
在编写URL处理函数时,除了配置URL外,从HTTP请求拿到用户数据也是非常重要的。Web框架都提供了自己的API来实现这些功能。Flask通过request.form[&#39;name&#39;]来获取表单的内容。
Make a Comment
Sign In to Make a Comment
You can sign in directly without register:
You need authorize to allow connect to your social passport for the first time.
WARNING: You are using an old browser that does not support HTML5.
Please choose a modern browser ( /
/ ) to get a good experience.}

我要回帖

更多关于 前端框架构建 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信