GoogLeNet を微調整して、Caffe でマルチラベル分類を行いたいと考えています。すでに単一ラベルの分類に微調整していますが、マルチラベルへの移行はまだできません。
私が行っている主な手順は次のとおりです。
データとグラウンド トゥルース用の LMDB を作成する
こことここでコードを変更して、1 つの LMDB をデータで作成し、もう 1 つをグラウンド トゥルースで作成します。
SoftmaxWithLoss を SigmoidCrossEntropyLoss に置き換える
train_val.prototxt を更新して、SoftmaxWithLoss レイヤーを SigmoidCrossEntropyLoss に置き換え、両方の DB が読み込まれるようにデータ レイヤーを設定します。単一ラベル分類問題で行ったように、学習率パラメーターを設定します。
この手順は機能しているようです。データフロー、および Solver.step(1) を実行することが可能です。データとラベルが正しくロードされていることを確認するために、数式を使用して明示的に損失を計算し、Caffe と同じ結果を得ました。
問題
ネットワークが収束しません。数百回の反復を実行すると、さまざまなクラスのそれぞれがクラス母集団の平均になります。つまり、クラス a の母集団に 0.35 個の 1 と 0.65 個の 0 がある場合、ネットワークは、真のラベルに関係なく、観測ごとに ~0.35 の分類確率に収束します。
考えられるエラー 1
問題は、GoogLeNet の事前トレーニング済みモデルが画像から学習できるように、画像を caffe に正しくロードできなかったためだと思われます。これまでの私の以前の経験は、完全に機能する convert_imageset です。現在、shelhamer コードを使用して画像を LMDB に保存しています。
im = np.array(Image.open(os.path.join(data_dir,in_)))
im = im[:,:,::-1]
im = im.transpose((2,0,1))
im_dat = caffe.io.array_to_datum(im)
in_txn.put('{:0>10d}'.format(in_idx), im_dat.SerializeToString())
画像を読み込むときに、データ層の平均を正規化します。それは正しいと思いますか?それを行う別の方法はありますか?
考えられるエラー 2
また、train_val.prototxt の定義が間違っている可能性もあります。SoftmaxWithLoss -> SigmoidCrossEntropyLoss を切り替える以外に必要なことはありますか?
どんな助けでも大歓迎です!ありがとう!