Python中从头开始实现神经网络 - 介绍

原文出处:
http://www.wildml.com/2015/09/implementing-a-neural-network-from-scratch/
Posted on September 3, 2015 by Denny Britz
这篇文章帮助我们用python实践一下从零开始训练一个神经网络。
以下是中文翻译:

获取代码
在这篇文章中,我们将从头开始实现一个简单的3层神经网络。 我们不会推导出所有需要的数学运算,但是我会尽量直观地解释我们正在做什么。 我也会指点资源给你阅读细节。
在这里,我假设你熟悉基本的微积分和机器学习的概念,例如 你知道什么是分类和正规化。 理想情况下,您也可以了解梯度下降等优化技术的工作原理。 但是,即使你不熟悉以上任何一点,这篇文章仍然会变得有趣;
但为什么从头开始实施一个神经网络呢? 即使您计划在将来使用像PyBrain这样的神经网络库,从头开始至少实施一次网络也是非常有价值的练习。 它可以帮助您了解神经网络是如何工作的,这对于设计有效的模型是至关重要的。
有一点要注意的是,这里的代码示例并不是非常有效。 他们的意思是很容易理解。 在即将发布的文章中,我将探讨如何使用Theano编写高效的神经网络实现。 (更新:现在可用)

生成数据集
让我们开始生成一个我们可以玩的数据集。 幸运的是,scikit-learn有一些有用的数据集生成器,所以我们不需要自己编写代码。 我们将使用make_moons函数。

# Generate a dataset and plot it
np.random.seed(0)
X, y = sklearn.datasets.make_moons(200, noise=0.20)
plt.scatter(X[:,0], X[:,1], s=40, c=y, cmap=plt.cm.Spectral)

这里写图片描述

我们生成的数据集有两个类,绘制成红色和蓝色的点。 你可以把蓝点看作是男性患者,将红点看作是女性患者,x轴和y轴是医学测量。

我们的目标是训练一个机器学习分类器,预测给定x和y坐标的正确类别(女性的男性)。 请注意,数据不是线性可分的,我们不能绘制一条直线来分隔两个类。 这意味着线性分类器(如Logistic回归)将无法适用数据,除非您手动设计对于给定数据集非常有效的非线性特征(例如多项式)。

事实上,这是神经网络的主要优势之一。 您不需要担心功能工程。 神经网络的隐藏层将为您学习功能。

Logistic回归

为了证明这一点,让我们训练一个Logistic回归分类器。 它的输入是x和y值,输出是预测的类(0或1)。 为了让我们的生活更轻松,我们使用scikit-learn的Logistic Regression类。

# Train the logistic rgeression classifier
clf = sklearn.linear_model.LogisticRegressionCV()
clf.fit(X, y)

# Plot the decision boundary
plot_decision_boundary(lambda x: clf.predict(x))
plt.title("Logistic Regression")

这里写图片描述

该图显示了我们的Logistic回归分类器学到的决策边界。 它使用直线将数据尽可能分离,但无法捕捉数据的“月亮形状”。

训练一个神经网络

现在我们来构建一个具有一个输入层,一个隐藏层和一个输出层的三层神经网络。 输入层中节点的数量取决于我们数据的维数2.类似地,输出层中节点的数量是由我们所拥有的类的数量决定的,也是2.(因为我们只有2个类, 实际上只能有一个输出节点预测为0或1,但有2个可以使网络稍后扩展到更多类)。 网络的输入将是x和y坐标,其输出将是两个概率,一个是0级(“女性”),一个是1级(“男性”)。 它看起来像这样:
这里写图片描述

我们可以选择隐藏层的维数(节点数)。我们放入隐藏层的节点越多,我们就可以适应更复杂的功能。但更高的维度是有代价的。首先,需要更多的计算来进行预测并学习网络参数。更多的参数也意味着我们更容易过拟合我们的数据。

如何选择隐藏层的大小?虽然有一些一般的指导方针和建议,但它总是取决于你的具体问题,更多的是艺术而不是科学。稍后我们将使用隐藏的节点数来看看它是如何影响我们的输出的。

我们还需要为隐藏层选择一个激活函数。激活功能将图层的输入转换为其输出。非线性激活函数使我们能够拟合非线性假设。用于激活功能的常见选择是tanh,sigmoid函数或ReLU。我们将使用tanh,在许多场景中表现相当好。这些函数的一个很好的属性是可以使用原始函数值来计算它们的派生值。例如,tanh x的导数是1- (tanh x)^2。这很有用,因为它可以让我们计算一次tanh x并稍后重新使用它的值来得到导数。

因为我们希望我们的网络输出概率,输出层的激活函数将是softmax,这只是将原始分数转换为概率的一种方法。如果您熟悉逻辑功能,您可以将softmax视为对多个类的归纳

猜你喜欢

转载自blog.csdn.net/yushupan/article/details/79236616
今日推荐