【发布时间】:2016-07-27 08:04:24
【问题描述】:
我正在尝试实现 SGD 功能以在 caffe python 中手动更新 python 中的权重,而不是使用solver.step() 函数。目标是在执行solver.step() 之后匹配权重更新,并通过手动更新权重。
设置如下:
使用 MNIST 数据。将solver.prototxt中的随机种子设置为:random_seed: 52。确保momentum: 0.0 和base_lr: 0.01、lr_policy: "fixed"。上面是这样完成的,我可以简单地实现 SGD 更新方程(没有动量、正则化等)。方程很简单:
W_t+1 = W_t - mu * W_t_diff
以下是两个测试:
测试1: 使用caffe的forward()和backward()计算前向传播和后向传播。 对于包含权重的每一层,我都会这样做:
for k in weight_layer_idx:
solver.net.layers[k].blobs[0].diff[...] *= lr # weights
solver.net.layers[k].blobs[1].diff[...] *= lr # biases
接下来,将权重/偏差更新为:
solver.net.layers[k].blobs[0].data[...] -= solver.net.layers[k].blobs[0].diff
solver.net.layers[k].blobs[1].data[...] -= solver.net.layers[k].blobs[1].diff
我运行了 5 次迭代。
Test2:运行 caffe 的 solver.step(5)。
现在,我希望这两个测试在两次迭代后产生完全相同的权重。
我在上述每个测试之后保存权重值,并通过两个测试计算权重向量之间的范数差,我发现它们并不精确。有人能找出我可能遗漏的东西吗?
以下是整个代码供参考:
import caffe
caffe.set_device(0)
caffe.set_mode_gpu()
import numpy as np
niter = 5
solver = None
solver = caffe.SGDSolver('solver.prototxt')
# Automatic SGD: TEST2
solver.step(niter)
# save the weights to compare later
w_solver_step = copy(solver.net.layers[1].blobs[0].data.astype('float64'))
b_solver_step = copy(solver.net.layers[1].blobs[1].data.astype('float64'))
# Manual SGD: TEST1
solver = None
solver = caffe.SGDSolver('solver.prototxt')
lr = 0.01
momentum = 0.
# Get layer types
layer_types = []
for ll in solver.net.layers:
layer_types.append(ll.type)
# Get the indices of layers that have weights in them
weight_layer_idx = [idx for idx,l in enumerate(layer_types) if 'Convolution' in l or 'InnerProduct' in l]
for it in range(1, niter+1):
solver.net.forward() # fprop
solver.net.backward() # bprop
for k in weight_layer_idx:
solver.net.layers[k].blobs[0].diff[...] *= lr
solver.net.layers[k].blobs[1].diff[...] *= lr
solver.net.layers[k].blobs[0].data[...] -= solver.net.layers[k].blobs[0].diff
solver.net.layers[k].blobs[1].data[...] -= solver.net.layers[k].blobs[1].diff
# save the weights to compare later
w_fwdbwd_update = copy(solver.net.layers[1].blobs[0].data.astype('float64'))
b_fwdbwd_update = copy(solver.net.layers[1].blobs[1].data.astype('float64'))
# Compare
print "after iter", niter, ": weight diff: ", np.linalg.norm(w_solver_step - w_fwdbwd_update), "and bias diff:", np.linalg.norm(b_solver_step - b_fwdbwd_update)
将权重与两个测试进行比较的最后一行生成:
after iter 5 : weight diff: 0.000203027766144 and bias diff: 1.78390789051e-05
我预计这个差异是 0.0
有什么想法吗?
【问题讨论】:
-
您是否在solver.prototxt 中将
weight_decay设置为零? -
是的,我之前忘了提,但
weight_decay: 0.0已设置。发生的情况是,如果我只对 1 次迭代运行这两个测试,我会从所有层得到完全匹配的权重向量,但不会得到后续迭代。 -
可能是渐变中的动量。尝试将动量设置为零。