技术信息:
操作系统:Mac OS X 10.9.5
IDE:Eclipse Mars.1 Release (4.5.1),带有 PyDev 和 Anaconda 解释器(语法版本 3.4)
显卡:NVIDIA GeForce GT 650M
库:numpy、aeosa、Sphinx-1.3.1、Theano 0.7、nltk-3.1
我的背景:我对 theano 和 numpy 非常陌生,还没有上过机器学习或离散数学的正式课程。
我目前使用的自然语言处理的递归神经网络取自这里:
https://github.com/dennybritz/rnn-tutorial-gru-lstm/blob/master/gru_theano.py
对该文件所做的唯一更改是将引用替换theano.config.floatX
为字符串'float32'
。
我还使用存储库中包含的 utils.py 和 train.py 模块,只进行了微小的更改。
我计划合并的亚当优化器代替示例存储库中实现的 sgd/rms 代码可在此处找到:https ://gist.github.com/skaae/ae7225263ca8806868cb
在这里转载(再次引用.config.floatX
替换为硬编码的'float32'
):
(theano
作为th
,theano.shared
作为thsh
,theano.tensor
作为T
,numpy
作为np
)
def adam(loss, all_params, learning_rate=0.001, b1=0.9, b2=0.999, e=1e-8, gamma=1-1e-8):
"""
ADAM update rules
Default values are taken from [Kingma2014]
References:
[Kingma2014] Kingma, Diederik, and Jimmy Ba.
"Adam: A Method for Stochastic Optimization."
arXiv preprint arXiv:1412.6980 (2014).
http://arxiv.org/pdf/1412.6980v4.pdf
"""
updates = []
all_grads = th.grad(loss, all_params)
alpha = learning_rate
t = thsh(np.float32(1))
b1_t = b1*gamma**(t-1) #(Decay the first moment running average coefficient)
for theta_previous, g in zip(all_params, all_grads):
m_previous = thsh(np.zeros(theta_previous.get_value().shape.astype('float32')))
v_previous = thsh(np.zeros(theta_previous.get_value().shape.astype('float32')))
m = b1_t*m_previous + (1 - b1_t)*g # (Update biased first moment estimate)
v = b2*v_previous + (1 - b2)*g**2 # (Update biased second raw moment estimate)
m_hat = m / (1-b1**t) # (Compute bias-corrected first moment estimate)
v_hat = v / (1-b2**t) # (Compute bias-corrected second raw moment estimate)
theta = theta_previous - (alpha * m_hat) / (T.sqrt(v_hat) + e) #(Update parameters)
updates.append((m_previous, m))
updates.append((v_previous, v))
updates.append((theta_previous, theta) )
updates.append((t, t + 1.))
return updates
我的问题是这样的:
您将如何修改 GRUTheano 模块以使用上面的 Adam 方法代替内置的 sgd/rmsprop 函数?
看起来关键的变化是 GRUTheano 的第 99-126 行:
# SGD parameters
learning_rate = T.scalar('learning_rate')
decay = T.scalar('decay')
# rmsprop cache updates
mE = decay * self.mE + (1 - decay) * dE ** 2
mU = decay * self.mU + (1 - decay) * dU ** 2
mW = decay * self.mW + (1 - decay) * dW ** 2
mV = decay * self.mV + (1 - decay) * dV ** 2
mb = decay * self.mb + (1 - decay) * db ** 2
mc = decay * self.mc + (1 - decay) * dc ** 2
self.sgd_step = theano.function(
[x, y, learning_rate, theano.Param(decay, default=0.9)],
[],
updates=[(E, E - learning_rate * dE / T.sqrt(mE + 1e-6)),
(U, U - learning_rate * dU / T.sqrt(mU + 1e-6)),
(W, W - learning_rate * dW / T.sqrt(mW + 1e-6)),
(V, V - learning_rate * dV / T.sqrt(mV + 1e-6)),
(b, b - learning_rate * db / T.sqrt(mb + 1e-6)),
(c, c - learning_rate * dc / T.sqrt(mc + 1e-6)),
(self.mE, mE),
(self.mU, mU),
(self.mW, mW),
(self.mV, mV),
(self.mb, mb),
(self.mc, mc)
])