CaffeでDeep Learning つまずきやすいところを中心に
こちらを見ると、build/tools/convert_imageset.binを使うと学習画像やテスト画像をDBに取り込んでくれるらしい。
デフォルトのDBは、lmdbというもののようだ。
あれ、私は画像じゃなくて、他のをやりたいのだが・・・
というわけで、どういうデータを入れたらいいのか、mnistで取り込んだデータを見てみることにした。
$ sudo apt-get install lmdb-utils
$ mdb_stat examples/mnist/mnist_test_lmdb
Status of Main DB
Tree depth: 3
Branch pages: 13
Leaf pages: 2500
Overflow pages: 0
Entries: 10000
ほう。
$ mdb-dump
ない、と怒られた。。。
こちらを見ると、「ppa:cz.nic-labs/knot-dnsがあるよ」ということだった。
PPAってなんだっけねぇ、と調べると、allaboutのページがあった。
私はxubuntuなので、メニューの「Settings > Software & Updates」で、"Other Software"タブを選び、Addした。
こういうのって、apt-get upgradeで何とかなるものだろうか?
$ sudo apt-get update
$ sudo apt-get upgrade
$ mdb_dump
おー、出てきた!
$ mdb_dump examples/mnist/mnist_test_lmdb
VERSION=3
format=bytevalue
type=btree
mapsize=1099511627776
maxreaders=126
db_pagesize=4096
HEADER=END
3030303030303030
0801101c181c229006.....002807
3030303030303031
0801101c181c229006.....002802
(中略)
DATA=END
データの部分の、1行目は連番で、2行目がデータのようだ。
データは、1byte2桁なので、795byteある。
画像は28x28=784。
ということは、795 - 784 = 11byteが付加データ。
こちらによると、MNISTのヘッダは16byteらしいので、それがそのまま載っているわけではない。
MNIST 手書き数字データを画像ファイルに変換する - y_uti のブログ
最初に付いている
0801101c181c22900600...
と、最後に付いている
...000280n
が付加データだろうが、さて、どこからどこまでなのか。
0x1c=28なので、画像のサイズなのだろうが、それだとあまりに画像データに特化しすぎてるよな。。。
あきらめて、検索した。
Caffe: Understanding expected lmdb datastructure for blobs - Stack Overflow
頭の9byteと、お尻の2byteが付加データだった。
データの並びは、caffe.protoのDatumを見ればよいらしい。
message Datum {optional int32 channels = 1;optional int32 height = 2;optional int32 width = 3;// the actual image data, in bytes
optional bytes data = 4;optional int32 label = 5;
// Optionally, the datum could also hold float data.
repeated float float_data = 6;// If true data contains an encoded image that need to be decoded
optional bool encoded = 7 [default = false];}
(?_?
protobufの方を見てみよう。
encodingの説明を見てみると・・・
message Test1 {required int32 a = 1;}
こういう設定で、「a=150」とすると、データはこうなるらしい。
08 96 01
へー。0x96 = 150なので、そこはわかるが、前後がわからん。
まず、7bit表現かつリトルエンディアン表現とのこと。
そしてMessageはkey-valueのペアになっていて、最初はkey。
keyは、 (field_number << 3) | wire_type)、という構成。
08
→ 0000_1000 (2進数)
→ 000_1000 (7bit化)
→ field_number : 0001、wire_type : 000
wire_typeが0なのは、表を見ると意味が「Varint」。
field_numberが1なのは、message Test1の「a」という意味。
96 01
→ 1001_0110 0000_0001 (2進数)
→ 001_0110 000_0001 (7bit化)
→ 000_0001 001_0110 (リトルエンディアン)
→ 1001_0110 (つなげた)
→ 0x96 (16進数)
→ 150 (10進数)
他にもルールがあるけど、ごめん、きつい。
あとは、もう、ここのヘッダだけ見ていこう。
0801101c181c229006.....280n
08 : key - field_number=1="channels", wire_type=0=varint型
01 : channels = 0x01
10 : key - field_number=2="height", wire_type=0=varint型
1c : height=28
18 : key - field_number=3="width", wire_type=0=varint型
1c : width=28
22 : key - field_number=4="data", wire_type=2=Length-delimited型
90 06 : Length=0x310=784byte28 : key - field_number=5="label", wire_type=0=varint型
0n : label=n
データを見ると、頭の方は固定で、labelだけが変わっている。
ここでは、labelが手書き文字が表す数字なのだろう。
最初のリンクで「データセット用意」のクラスに当たるところが、labelになるのかな。
これを、音声や文章のようなストリーミングというか1次元のデータで扱いたいなら、高さか幅を1にして並べればよいのだろう。
でも、lenet_train_test.prototxtを見ても、データが2次元とか、高さとか幅とか、そういうのが見えてこないのよねぇ。
畳み込みニューラルネットって、「深層学習」を読むと2次元のマップに見立て、入力層の広さよりも中間層の広さの方が狭い、みたいな図になっているのだ。
狭いので、中間層の1つのユニットに、入力層のMxNのユニットが結合される、みたいなことになっている。
そういうのが、prototxtになさそうなのだ。
まあ、まだ畳み込みニューラルネットを読んでないので、先走りすぎたかな。
参考にさせていただきました。
返信削除mdb-dump → mdb_dump
の間違いのようです。
ありがとうございます。
削除apt-upgradeした後は「mdb_dump」と入力しているので、実は最初から入っていて、単に打ち間違えて気付かなかっただけかもしれませんね。
お恥ずかしい。。。