深度学习算法实践4---Theano常用技巧

在上一篇文章中介绍了神经网感知器模型中用到的一些算法,在这篇文章中,将继续介绍这些常用的算法,首先是随机数的生成,因为感知器模型必须用随机数来初始化连接权值,其次是求导数,因为感知器学习算法是,会用到梯度下降算法,涉及到求导问题。

在讨论随机数生成算法之前,我们先来讨论一下共享变量,这很像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标准语法相同,具有缺省值的参数,需要放在没有缺省值的参数后面。







你可能感兴趣的:(python,深度学习,theano)