在上一篇文章中介绍了神经网感知器模型中用到的一些算法,在这篇文章中,将继续介绍这些常用的算法,首先是随机数的生成,因为感知器模型必须用随机数来初始化连接权值,其次是求导数,因为感知器学习算法是,会用到梯度下降算法,涉及到求导问题。
在讨论随机数生成算法之前,我们先来讨论一下共享变量,这很像C语言中的静态变量,假设我们要对网站的内容的热度进行统计分析,我们用hottness来表示热度,用visitWeight来表示访问的权重,每次用户访问该内容时,该内容对应的hottness就增加visitWeight,使用Theano可以用下面的代码来实现:
import theano import theano.tensor as T from theano import function from theano import shared hottness = shared(0) visitWeight = T.iscalar("visitWeight") calculateHottness = function([visitWeight], hottness, updates=[(hottness, hottness + visitWeight)]) minusValue = T.iscalar("minusValue") decreaseHottness = function([minusValue], hottness, updates=[(hottness, hottness - minusValue)]) visitWeight1 = 5 calculateHottness(visitWeight1) print("hottness=%d" % hottness.get_value()) visitWeight2 = 10 calculateHottness(visitWeight2) print("hottness=%d" % hottness.get_value()) minusValue1 = 3 decreaseHottness(minusValue1) print("hottness=%d" % hottness.get_value()) hottness.set_value(0) print("hottness=%d" % hottness.get_value())
运行上面的代码,可以得到5和15两个值,表明我们的共享变量是起作用的。如果我们想重复热度值时,如一个统计周期结束时,只需调用hottness.set_value(0)即可实现,同时,如果我们系统踩的功能,假设每获得一个踩,热度降低一定值,我们可以定义一个新的decreaseHottness函数,两个函数可以共享同一个hottness变量。
假设有一些内容,我们采用了用户打分系统,分为1~5分,用户每次评分,在热度加上用户的评分值,为重用上述逻辑,只需要将用到hottness的地方,换成一个新的变量例如score就可以了,代码如下所示:
newHottness = hottness + visitWeight score = T.scalar(dtype=hottness.dtype) calculateScore = function([visitWeight, score], newHottness, givens=[(hottness, score)]) print("score=%d; hottness=%d!" % (calculateScore(5, 100), hottness.get_value()))上面可以正确地计算出score的值为105,而hottness的仍为原来的值不变。
显然,如果我们要统计某个项目用户打分的总分情况,更好的方法是利用Theano的函数拷贝机制,将hottness替换为新的rateScores,而此时visitWeight就对应于用户的评分值,下面代码将实现这一目的:
rateScores = shared(0) calculateRateScores = calculateHottness.copy(swap={hottness: rateScores}) calculateRateScores(5) print("rateScores=%d" % rateScores.get_value())下面来看一下在Theano中随机数的使用问题。由于Theano是先用符号化的东西来进行表达式定义,之后系统编译这些表达式为函数,最后你再调用这些函数来执行相应的功能,所以在Theano中使用随机数,是一个相对复杂的过程。对于这个问题,Theano采用RandomStream来进行解决,也就是在需要随机数的地方,定义一个RandomStream,然后在实际运行过程中,当需要随机数参与运算时,从RandomStream中读出随机数。
随机数在神经网络中,主要用于权值中,因此我们会初始化一个权值矩阵,在Theano中,我们可以使用uniform分布来获得这些在0~1的随机权值,代码如下所示:
from theano.tensor.shared_randomstreams import RandomStreams from theano import function randStrm = RandomStreams(seed=299) uniformValue = randStrm.uniform((2, 2)) normalValue = randStrm.normal((2, 2)) getUniformValue = function([], uniformValue) getNormalValue = function([], normalValue, no_default_updates=True) getRandomNumber = function([], uniformValue + uniformValue - 2 * uniformValue) print(getUniformValue()) print(getNormalValue()) print(getRandomNumber())上面代码会生成2*2的随机权值矩阵,上述代码还可以用来获得normal分布的随机数权值矩阵,而且我们通过使用no_default_updates=True,使我们每次获得的随机数是相等的,最后一个函数是获得接近于零的随机数。
需要注意的是,上述代码只能在CPU上运行,如果想让代码在CPU和GPU上均可运行,则只需将上面代码的第一句修改为:from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams即可。
在Theano中,函数的缺省参数的处理也不同于python的标准方法。代码如下所示:
from theano import In from theano import function from theano import tensor as T x, y = T.dscalars("x", "y") z = x + y add = function([x, In(y, value=100)], z) print("add=%d" % add(20))如上代码所示,采用In语法,可以定义y的缺省值为100。需要注意的是,与python标准语法相同,具有缺省值的参数,需要放在没有缺省值的参数后面。