関数を使用する代わりに、caffe python で手動で python の重みを更新する SGD 機能を実装しようとしてい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
次の 2 つのテストがあります。
Test1: 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's を実行しますsolver.step(5)
。
さて、私が期待しているのは、2 つのテストが 2 回の反復後にまったく同じ重みを生成することです。
上記の各テストの後に重み値を保存し、2 つのテストで重みベクトル間のノルム差を計算すると、それらがビット正確ではないことがわかります。私が見逃しているかもしれない何かを誰かが見つけることができますか?
以下は、参照用のコード全体です。
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)
重みを 2 つのテストと比較する最後の行は、次の結果を生成します。
after iter 5 : weight diff: 0.000203027766144 and bias diff: 1.78390789051e-05
この差は0.0になると予想しています
何か案は?