らんだむな記憶

blogというものを体験してみようか!的なー

Darknet-53 のネットワーク構造

https://github.com/pjreddie/darknet/blob/a028bfa0da8eb96583c05d5bd00f4bfb9543f2da/cfg/darknet53.cfg

これが対応する。パーサを書くのに存分に苦労したが、一応丁寧にパースすると YOLOv3 の論文の Table 1. Darknet-53 の内容と一致していた。

ついでに動作確認をしたかったのだが、

image = np.random.randint(0, 255, (256, 256, 3)).astype(np.uint8)
# 訓練済みウェイトを読み込ませないとうまく動かないかも?
net = cv2.dnn.readNetFromDarknet('darknet53.cfg')
inputBlob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size=(256,256), swapRB=False, crop=False)
outputName = net.getUnconnectedOutLayersNames()
net.setInput(inputBlob)
out = net.forward(outputName)

したら例外が飛んでしまった・・・。訓練済みパラメータを読み込ませていないので、色々と不完全な状態なのかもしれない・・・。他のメソッドも色々と例外が出てしまう。

YOLO: Real-Time Object Detection を参考に https://pjreddie.com/media/files/darknet53.weights をダウンロードして、

net = cv2.dnn.readNetFromDarknet('darknet53.cfg', 'darknet53.weights')

とすれば例外は出なくなった。

>>> out[0].shape
(1, 1000, 1, 1)

なので、一応それっぽい結果かな?

>>> out = net.forward('shortcut_74')
>>> out[0].shape
(1024, 8, 8)
>>> out = net.forward('avgpool_75')
>>> out[0].shape
(1024, 1, 1)
>>> out = net.forward('conv_76')
>>> out[0].shape
(1000, 1, 1)
>>> out = net.forward('softmax_77')
>>> out[0].shape
(1000, 1, 1)

というのが終わりのほうの特徴量のサイズのようで、avgpool_layer.c#L14-L15 より、平均プーリングの実装が「グローバル平均プーリング」であって、各チャネルごとに出力がスカラになることに注意して読んでみると論文の通りかなと思う。