做者:chen_h
微信号 & QQ:862251340
微信公众号:coderpai
简书地址:https://www.jianshu.com/p/0da...html
这篇教程是翻译 Peter Roelants写的神经网络教程,做者已经受权翻译,这是 原文。
该教程将介绍如何入门神经网络,一共包含五部分。你能够在如下连接找到完整内容。python
这篇教程中的代码是由 Python 2 IPython Notebook产生的,在教程的最后,我会给出所有代码的连接,帮助学习。神经网络中有关矩阵的运算咱们采用NumPy来构建,画图使用Matplotlib来构建。若是你来没有按照这些软件,那么我强烈建议你使用Anaconda Python来安装,这个软件包中包含了运行这个教程的全部软件包,很是方便使用。git
咱们先导入教程须要的软件包github
from __future__ import print_function import numpy as np import matplotlib.pyplot as plt
本教程主要包含三部分:算法
首先咱们来构建一个最简单的神经网络,这个神经网络只有一个输入,一个输出,用来构建一个线性回归模型,从输入的x
来预测一个真实结果t
。神经网络的模型结构为y = x * w
,其中x
是输入参数,w
是权重,y
是预测结果。神经网络的模型能够被表示为下图:微信
在常规的神经网络中,神经网络结构中有多个层,非线性激活函数和每一个节点上面的误差单元。在这个教程中,咱们只使用一个只有一个权重w
的层,而且没有激活函数和误差单元。在简单线性回归中,权重w
和误差单元通常都写成一个参数向量β
,其中误差单元是y
轴上面的截距,w
是回归线的斜率。在线性回归中,咱们通常使用最小二乘法来优化这些参数。网络
在这篇教程中,咱们的目的是最小化目标损失函数,使得实际输出的y
和正确结果t
尽量的接近。损失函数咱们定义为:app
对于损失函数的优化,咱们采用梯度降低,这个方法是神经网络中常见的优化方法。dom
在这个例子中,咱们使用函数f
来产生目标结果t
,可是对目标结果加上一些高斯噪声N(0, 0.2)
,其中N
表示正态分布,均值是0
,方差是0.2
,f
定义为f(x) = 2x
,x
是输入参数,回归线的斜率是2
,截距是0
。因此最后的t = f(x) + N(0, 0.2)
。函数
咱们将产生20个均匀分布的数据做为数据样本x
,而后设计目标结果t
。下面的程序咱们生成了x
和t
,以及画出了他们之间的线性关系。
# Define the vector of input samples as x, with 20 values sampled from a uniform distribution # between 0 and 1 x = np.random.uniform(0, 1, 20) # Generate the target values t from x with small gaussian noise so the estimation won't be perfect. # Define a function f that represents the line that generates t without noise def f(x): return x * 2 # Create the targets t with some gaussian noise noise_variance = 0.2 # Variance of the gaussian noise # Gaussian noise error for each sample in x noise = np.random.randn(x.shape[0]) * noise_variance # Create targets t t = f(x) + noise
# Plot the target t versus the input x plt.plot(x, t, 'o', label='t') # Plot the initial line plt.plot([0, 1], [f(0), f(1)], 'b-', label='f(x)') plt.xlabel('$x$', fontsize=15) plt.ylabel('$t$', fontsize=15) plt.ylim([0,2]) plt.title('inputs (x) vs targets (t)') plt.grid() plt.legend(loc=2) plt.show()
咱们将优化模型y = w * x
中的参数w
,使得对于训练集中的N
个样本,损失函数达到最小。
即,咱们的优化目标是:
从函数中,咱们能够发现,咱们将全部样本的偏差都进行了累加,这就是所谓的批训练(batch training)。咱们也能够在训练的时候,每次训练一个样本,这种方法在在线训练中很是经常使用。
咱们利用如下函数画出损失函数与权重的关系。从图中,咱们能够看出损失函数的值达到最小时,w
的值是2
。这个值就是咱们函数f(x)
的斜率。这个损失函数是一个凸函数,而且只有一个全局最小值。
nn(x, w)
函数实现了神经网络模型,cost(y, t)
函数实现了损失函数。
# Define the neural network function y = x * w def nn(x, w): return x*w # Define the cost function def cost(y, t): return ((t - y) ** 2).sum()
对于教程中简单的损失函数,可能你看一眼就能知道最佳的权重是什么。可是对于复杂的或者更高维度的损失函数,这就是咱们为何要使用各类优化方法的缘由了。
在训练神经网络中,梯度降低算法是一种比较经常使用的优化算法。梯度降低算法的原理是损失函数对于每一个参数进行求导,而且利用负梯度对参数进行更新。权重w
经过循环进行更新:
其中,w(k)
表示权重w
更新到第k
步时的值,Δw
为定义为:
其中,μ
是学习率,它的含义是在参数更新的时候,每一步的跨度大小。∂ξ/∂w
表示损失函数 ξ
对于 w
的梯度。对于每个训练样本i
,咱们能够利用链式规则推导出对应的梯度,以下:
其中,ξi
是第i
个样本的损失函数,所以,∂ξi/∂yi
能够这样进行推导:
由于y(i) = x(i) ∗ w
,因此咱们对于∂yi/∂w
能够这样进行推导:
所以,对于第i
个训练样本,Δw
的完整推导以下:
在批处理过程当中,咱们将全部的梯度都进行累加:
在进行梯度降低以前,咱们须要对权重进行一个初始化,而后再使用梯度降低算法进行训练,最后直至算法收敛。学习率做为一个超参数,须要单独调试。
gradient(w, x, t)
函数实现了梯度∂ξ/∂w
,delta_w(w_k, x, t, learning_rate)
函数实现了Δw
。
# define the gradient function. Remember that y = nn(x, w) = x * w def gradient(w, x, t): return 2 * x * (nn(x, w) - t) # define the update function delta w def delta_w(w_k, x, t, learning_rate): return learning_rate * gradient(w_k, x, t).sum() # Set the initial weight parameter w = 0.1 # Set the learning rate learning_rate = 0.1 # Start performing the gradient descent updates, and print the weights and cost: nb_of_iterations = 4 # number of gradient descent updates w_cost = [(w, cost(nn(x, w), t))] # List to store the weight, costs values for i in range(nb_of_iterations): dw = delta_w(w, x, t, learning_rate) # Get the delta w update w = w - dw # Update the current weight parameter w_cost.append((w, cost(nn(x, w), t))) # Add weight, cost to list # Print the final w, and cost for i in range(0, len(w_cost)): print('w({}): {:.4f} \t cost: {:.4f}'.format(i, w_cost[i][0], w_cost[i][1])) # output w(0): 0.1000 cost: 23.3917 w(1): 2.3556 cost: 1.0670 w(2): 2.0795 cost: 0.7324 w(3): 2.1133 cost: 0.7274 w(4): 2.1091 cost: 0.7273
从计算结果中,咱们很容易的看出来了,梯度降低算法很快的收敛到了2.0
左右,接下来可视化一下梯度降低过程。
# Plot the first 2 gradient descent updates plt.plot(ws, cost_ws, 'r-') # Plot the error curve # Plot the updates for i in range(0, len(w_cost)-2): w1, c1 = w_cost[i] w2, c2 = w_cost[i+1] plt.plot(w1, c1, 'bo') plt.plot([w1, w2],[c1, c2], 'b-') plt.text(w1, c1+0.5, '$w({})$'.format(i)) # Show figure plt.xlabel('$w$', fontsize=15) plt.ylabel('$\\xi$', fontsize=15) plt.title('Gradient descent updates plotted on cost function') plt.grid() plt.show()
上图展现了梯度降低的可视化过程。图中蓝色的点表示在第k
轮中w(k)
的值。从图中咱们能够得知,w
的值愈来愈收敛于2.0
。该模型训练10
次就能收敛,以下图所示。
w = 0 # Start performing the gradient descent updates nb_of_iterations = 10 # number of gradient descent updates for i in range(nb_of_iterations): dw = delta_w(w, x, t, learning_rate) # get the delta w update w = w - dw # update the current weight parameter
# Plot the fitted line agains the target line # Plot the target t versus the input x plt.plot(x, t, 'o', label='t') # Plot the initial line plt.plot([0, 1], [f(0), f(1)], 'b-', label='f(x)') # plot the fitted line plt.plot([0, 1], [0*w, 1*w], 'r-', label='fitted line') plt.xlabel('input x') plt.ylabel('target t') plt.ylim([0,2]) plt.title('input vs. target') plt.grid() plt.legend(loc=2) plt.show()
做者:chen_h
微信号 & QQ:862251340
简书地址:https://www.jianshu.com/p/0da...
CoderPai 是一个专一于算法实战的平台,从基础的算法到人工智能算法都有设计。若是你对算法实战感兴趣,请快快关注咱们吧。加入AI实战微信群,AI实战QQ群,ACM算法微信群,ACM算法QQ群。长按或者扫描以下二维码,关注 “CoderPai” 微信号(coderpai)