不久前,研究人员Hornik等58发现,一个隐藏层足以模拟任何分段连续函数。他们的定理非常好,值得在这里重申一下:
Hornik等人的定理:设F是n维空间有界子集上的连续函数,那么存在一个包含有限个隐藏单元的双层神经网络
,它近似等于F。也就是说,对于F域中的所有的x,。
这是一个了不起的定理。实际上,对于任何连续函数F和一定的容错ε,可以构建一个单隐藏层的神经网络用于计算F。这至少在理论上说明,一个隐藏层对于很多问题是足够的。
当然,实际情况略有不同。首先,现实世界的决策函数可能并不连续,该定理并没有指定所需的隐藏层神经元数量。对于现实世界的很多问题,看上去需要多个隐藏层来实现精确的分类和预测。
如果决策规则可以通过复杂函数进行数学建模,那么就可以使用DNN。重要的是,你不需要事先知道函数的形式。再看一下Jechang Jeong教授的去雾算法。注意,在这个例子中,研究人员承认去雾的功能(对他们)是未知的。可喜的事,他们的DNN找到了一个很好的解决方案。
(此处已添加圈子卡片,请到今日头条客户端查看)欢迎加入程序员读书会,每日分享it好书,不定期免费赠书
现在我们用Python来构建一个DNN来近似一个函数。我们将构建DNN来近似y = x2。首先,导入一些使用的基础包,这通过使用import关键字完成:
import numpy as np
import pandas as pd
import random
让我们讲解一下上面的代码。
下面生成有50个随机值的x,然后赋值y = x2。
random.seed(2016)
sample_size=50
sample = pd.Series(random.sample(
range(-10000,10000),sample_size))
x=sample/10000
y=x**2
Python代码的一个好处是非常容易阅读。上面的代码就是一个很好的例子。下面让我们详细分析一下:
说明
可以使用type关键字来查看Python对象的“类型”。例如,查看sample的类型:
type(sample)
<class'pandas.core.series.Series'>
Series是pandas的一个核心类型。
不时地查看一下数据是一个好主意。那么让我们看一下x中的前10个观察值:
print x.head(10)
0 0.4758
1 -0.1026
2 0.7847
3 0.7506
4 -0.4870
5 0.3657
6 0.8647
7 -0.8361
8 -0.4067
9 -0.8568
dtype: float64
第一个观测值为0.4758,第十个观测值为–0.8568。注意,输出也包含了numpy的 dtype62,这里为float64。Numpy数组包含dtype对象的元素。
接着看一下y的前10个观察值:
print y.head(10)
0 0.226386
1 0.010527
2 0.615754
3 0.563400
4 0.237169
5 0.133736
6 0.747706
7 0.699063
8 0.165405
9 0.734106
第一次观测值为0.226386,第十次观测值为0.734106。快速抽查表明,第一个观测值(0.4758)2 = 0.226386,第十个观测值(0.4758)2 = 0.226386,所以数字和预期的y值一样为x的平方。图4.7显示了模拟数据的可视化图。
图4.7 模拟数据y = x2 的图表
也可以用.describe()方法快速查看数据的摘要信息。这里检查一下x的摘要:
print x.describe()
count 50.000000
mean -0.100928
std 0.534392
min -0.937000
25% -0.562275
50% -0.098400
75% 0.359750
max 0.864700
.describe()函数提供了样本的最大值、最小值、观测值数量以及四分位数等细节。正如我们所期望的,x值位于±1之间,最大值为0.8647,最小值为–0.937。
在这个例子中,我们使用的neuralpy包63——这是一个专门研究神经网络的机器学习库。它的接口非常直观,让你可以快速地开始训练数据,并测试深度学习模型。
为了使用该包,我们需要把数据转换成一个合适的格式。为此,我们将创建一个名为dataSet的Python对象。该对象是一个观察值x和y的列表。我们可以通过一个while循环来完成格式的变换。
count = 0
dataSet = [([x.ix[count]],[y.ix[count]])]
count=1
while (count < sample_size):
print "Working on data item: ", count
dataSet = (dataSet+[([x.ix[count,0]], [y.ix[count]])])
count = count +
下面分析一下上述代码。
模型运行时,你能看到如下的输出。
Working on data item: 1
Working on data item: 2
Working on data item: 3
. . .
Working on data item: 47
Working on data item: 48
Working on data item: 49
说明
注意dataSet是一个列表对象:
type(dataSet)
<type 'list'>
这是neuralpy包所需要的类型。
我们将拟合一个有两个隐藏层的DNN。第一个隐藏层包含3个神经元,第二个隐藏层有7个神经元,如图4.8所示。这可以通过neuralpy.Network方法指定:
import neuralpy
fit = neuralpy.Network(1, 3,7,1)
图4.8 neuralpy 神经网络模型的结构
模型通过学习算法迭代的最大次数由epochs参数控制,我们将此值设置为100。学习速率控制梯度下降算法的步长大小,设置为1。
epochs = 100
learning_rate = 1
现在我们可以使用fit.train函数来拟合模型了。
print "fitting model right now"
fit.train(dataSet, epochs, learning_rate)
可以看到,传递给fit.train的第一个参数是样本,然后是迭代最大次数和学习速率。最后,经过一段时间后模型收敛得到一个解决方案。
让我们看一下模型在逼近y值时的表现有多好。预测值可以使用fit.forward函数获得。我们使用一个简单的while循环将预测结果存储在Python对象out中,并使用print函数将结果显示在屏幕上。
count = 0
pred=[]
while (count < sample_size):
out=fit.forward(x[count])
print("Obs: ",count+1,
" y = ", round(y[count],4),
" prediction = ",
round(pd.Series(out),4))
pred.append(out)
count = count + 1
当模型运行时,会将结果打印到屏幕上。对于前5个观测值,你应该能看到如下内容:
当然,显示在屏幕上的数字与上面显示的不同。为什么呢?因为neuralpy随机设置权重和偏差。每次模型运行这些值,结果都是不同的。尽管如此,整体结果会非常接近实际的观测值。
记录的数据表明该DNN提供了一个虽然不是精确的,但已经是对实际函数非常好的近似。图4.9显示了所有观测值所预测的y和x值。你自己判断一下,DNN模型的准确性如何?结果与显示的有多相似?你会怎样来提高整体的性能?
图4.9 使用neuralpy的x和预测值
留言与评论(共有 0 条评论) |