无需深度学习框架,如何从零开始用Python构建神经网络

作者: 机器之心 2018-05-28 13:12:49

动机:为了深入了解深度学习,我决定从零开始构建神经网络,并且不使用类似 Tensorflow 的深度学习库。我相信,对于任何有理想的数据科学家而言,理解神经网络内部的运作方式都非常重要。

本文涵盖了我学到的所有东西,希望你也能从中获益!

一、什么是神经网络?

许多有关神经网络的介绍资料会将神经网络与大脑进行类比。但我发现,将神经网络简单地描述为一个从输入映射到输出的数学函数理解起来更容易。

神经网络由以下部分组成:

  • 一个输入层,x
  • 任意数量的隐藏层
  • 一个输出层,ŷ
  • 每两层之间都有一组权重和偏置,W 和 b
  • 每个隐藏层都要选择一个激活函数 σ。在本文中,我们选用 Sigmoid 激活函数。

下图展示了 2 层神经网络的结构(请注意,在计算神经网络层数的时候,通常不计入输入层)。

二层神经网络的结构

利用 Python 建立神经网络非常容易。

  1. class NeuralNetwork: 
  2.     def __init__(self, x, y): 
  3.         self.input      = x 
  4.         self.weights1   = np.random.rand(self.input.shape[1],4)  
  5.         self.weights2   = np.random.rand(4,1)                  
  6.         self.y          = y 
  7.         self.output     = np.zeros(y.shape) 

1. 训练神经网络

一个简单 2 层神经网络的输出 ŷ 可以表示为:

你可能注意到,在上面的等式当中,权重 W 和偏置 b 是影响输出 ŷ 的唯一变量。

自然,权重和偏差的正确值决定了预测的强度。根据输入数据微调权重和偏置的过程称为神经网络训练。

训练过程的每一次迭代包含以下步骤:

  • 计算预测的输出 ŷ,称为前向传播
  • 更新权重和偏置,称为反向传播

以下流程图说明了这个过程:

2. 前向传播

正如我们在上图中所看到的,前向传播只是一个简单的计算。对于一个基本的 2 层神经网络,神经网络的输出计算如下:

我们可以在 Python 代码中添加一个前向传播函数来做到这一点。简单起见,我们假设偏置为 0。

  1. class NeuralNetwork: 
  2.     def __init__(self, x, y): 
  3.         self.input      = x 
  4.         self.weights1   = np.random.rand(self.input.shape[1],4)  
  5.         self.weights2   = np.random.rand(4,1)                  
  6.         self.y          = y 
  7.         self.output     = np.zeros(self.y.shape) 
  8.  
  9.     def feedforward(self): 
  10.         self.layer1 = sigmoid(np.dot(self.input, self.weights1)) 
  11.         self.output = sigmoid(np.dot(self.layer1, self.weights2)) 

然而,我们仍然需要一种方法来评估我们的预测的「优秀程度」(即,我们的预测与真实值相差多少?)这就需要用到损失函数了。

3. 损失函数

损失函数有很多种,而我们问题的性质会决定我们使用哪种损失函数。在本文中,我们将采用简单的误差平方和。

误差平方和,即每个预测值和真实值之间差值的平均值。这个差值是取了平方项的,所以我们测量的是差值的绝对值。

在训练过程中,我们的目标是找到一组最佳的权重和偏置,使损失函数最小化。

4. 反向传播

现在,我们已经找到了预测误差的方法(损失函数),那么我们需要一种方法将错误「传播」回去,从而更新权重和偏置。

为了确定权重和偏置调整的适当值,我们需要知道损失函数对权重和偏置的偏导数。

从微积分的角度来看,函数的偏导数也就是函数的斜率。

梯度下降算法

如果我们知道了偏导数,我们可以通过简单增加或减少偏导数(如上图所示)的方式来更新权重和偏置。这就是所谓的梯度下降。

然而,由于损失函数的方程不包含权重和偏置,所以我们不能直接计算损失函数对权重和偏置的偏导数。因此,我们需要链式法则来帮助计算。

以上是用于计算损失函数对权重偏导数的链式法则。简单起见,我们只展示了一层神经网络的偏导数。

唷!这看起来不大好看,但这能让我们获得所需——损失函数对权重的偏导数(斜率),以便相应调整权重。

既然我们已经有了链式法则公式,接下来我们把反向传播函数添加到 Python 代码中。

  1. class NeuralNetwork: 
  2.     def __init__(self, x, y): 
  3.         self.input      = x 
  4.         self.weights1   = np.random.rand(self.input.shape[1],4)  
  5.         self.weights2   = np.random.rand(4,1)                  
  6.         self.y          = y 
  7.         self.output     = np.zeros(self.y.shape) 
  8.  
  9.     def feedforward(self): 
  10.         self.layer1 = sigmoid(np.dot(self.input, self.weights1)) 
  11.         self.output = sigmoid(np.dot(self.layer1, self.weights2)) 
  12.  
  13.     def backprop(self): 
  14.         # application of the chain rule to find derivative of the loss function with respect to weights2 and weights1 
  15.         d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output) * sigmoid_derivative(self.output))) 
  16.         d_weights1 = np.dot(self.input.T,  (np.dot(2*(self.y - self.output) * sigmoid_derivative(self.output), self.weights2.T) * sigmoid_derivative(self.layer1))) 
  17.  
  18.         # update the weights with the derivative (slope) of the loss function 
  19.         self.weights1 += d_weights1 
  20.         self.weights2 += d_weights2 

二、整合

既然我们已经有了做前向传播和反向传播的完整 Python 代码,我们可以将神经网络应用到一个示例中,看看它的效果。

我们的神经网络应该能够习得理想的权重集合以表示这个函数。请注意,对于我们来说,仅通过检查来计算权重并非一件小事。

如果我们将神经网络进行 1500 次迭代,看看会发生什么。下图展示了每次迭代的损失函数值,我们可以清晰地发现损失函数单调下降到最小值。这与我们前面讨论的梯度下降算法是一致的。

让我们看看神经网络在进行 1500 次迭代后的最终预测(输出):

进行 1500 次迭代后的预测值

我们成功了!我们的前向传播和反向传播算法成功训练了神经网络,且预测值收敛到了真实值。

请注意,预测值和真实值之间还是有一些轻微差异的。这是可取的,因为它防止了过度拟合,并且使得神经网络具有更强的泛化能力。

三、下一步

幸运的是,我们的探索还没有结束。关于神经网络和深度学习还有很多需要学习的地方。例如:

  • 除了 Sigmoid 函数之外,我们还可以使用哪些激活函数?
  • 在训练神经网络时使用学习率
  • 使用卷积进行图像分类任务

四、最后一点想法

在撰写此文的过程中,我已经学到了很多,希望本文也能对你有所帮助。

在没有完全了解神经网络内部工作原理的情况下,虽然使用诸如 TensorFlow 和 Keras 之类的深度学习库可以让我们很容易地建立深度网络,但我认为对于有抱负的数据科学家而言,深入理解神经网络还是大有裨益的。

原文链接:

https://towardsdatascience.com/how-to-build-your-own-neural-network-from-scratch-in-python-68998a08e4f6

【本文是51CTO专栏机构“机器之心”的原创译文,微信公众号“机器之心( id: almosthuman2014)”】

戳这里,看该作者更多好文

深度学习 Python 神经网络
上一篇:5种使用人工智能来扩展业务的策略 下一篇:人工智能太高大上?看完这一篇就人人都能看懂人工智能史了
评论
取消
暂无评论,快去成为第一个评论的人吧

更多资讯推荐

18个挑战项目带你快速入门深度学习

AlphaGo 大战李世?h之后,深度学习技术便在国内变得异常火。吸引了大批的技术人员争相学习,那么到底如何才能更快速的入门深度学习呢?下面给大家介绍的 18 个挑战项目,通过实践动手带你快速入门深度学习!

实验楼 ·  2019-10-10 14:48:19
盘点 | 8个你可能不知道的深度学习应用案例

深度学习与传统机器学习系统的不同之处在于,它能够在分析大型数据集时进行自我学习和改进,因此能应用在许多不同的领域。

天极网 ·  2019-10-10 14:15:18
预测分析:重新考虑组织中的时间和数据

时间序列是一种标准的分析方法,但是较为先进的机器学习工具引入了统计技术,来建立更精确的预测模型。时间是无法倒流的,但是使用现有的工具,您有更多的机会预测时间,更准确地说,是可以预测时间序列样本中的事件是否会继续影响决策趋势。

IT168 ·  2019-09-27 09:57:09
微众银行AI首席科学家NeurIPS论文揭示“神经网络防盗最新技术”

随着深度神经网络(DNN)的快速发展,机器学习服务(MLaaS)等有潜力的商业模式迅速崛起,AI产业化进入发展快车道。然而,保护训练好的DNN模型免于被非法复制,重新分发或滥用(即知识产权侵权)是AI产业化进程中必须要面临和解决的问题。尤其是当下各国企业在深度学习模型和平台方面进行巨额研发投入,对知识产权的保护刻不容缓。

屈鑫 ·  2019-09-26 15:27:09
2019年较热门的5大深度学习课程

今天,我们将和大家盘点一下,当下较流行的深度学习资源/课程,可以帮助你们提升深度学习技能。

猿哥 ·  2019-09-26 05:16:24
十个基本的Python数据科学软件包

过去五年人们对数据科学的兴趣显著上升。尽管有许多编程语言适合数据科学和机器学习,但Python是最受欢迎的。

布加迪 ·  2019-09-25 09:20:33
DeepMind一次性开源3个新框架!深度强化学习应用落地即将迎来春天?

深度强化学习(Deep Reinforcement Learning,DRL)一直是近年来人工智能的一些重大突破的核心。然而,尽管 DRL 有了很大的进步,但由于缺乏工具和库,DRL 方法在主流解决方案中仍然难以应用。

杨鲤萍 ·  2019-09-20 09:38:18
脆弱的神经网络:UC Berkeley详解对抗样本生成机制!

用于「欺骗」神经网络的对抗样本(adversarial example)是近期计算机视觉,以及机器学习领域的热门研究方向。只有了解对抗样本,我们才能找到构建稳固机器学习算法的思路。本文中,UC Berkeley 的研究者们展示了两种对抗样本的制作方法,并对其背后的原理进行了解读。

机器之心 ·  2019-09-18 19:20:28
Copyright©2005-2019 51CTO.COM 版权所有 未经许可 请勿转载