読者です 読者をやめる 読者になる 読者になる

日記とか、工作記録とか

自分に書けることを何でも書いてゆきます。作った物、買ったもの、コンピュータ系の話題が多くなるかもしれません。

Raspberry pi 2 + word2vec(動くところまで)

word2vecというソフトウェアがあります。

Google Code Archive - Long-term storage for Google Code Project Hosting.

人工知能の研究の中で作られたソフトウェアで、Googleの作成したものです。Apache Licenseで配布されています。

膨大な量の文章を入力として、それぞれの単語の前後5語との相関関係から、単語同士の関係を200次元のベクトルで表現するものです。内容は例えばオライリーの本で紹介されています。

www.oreilly.co.jp

配布元では、この200次元のベクトルを用いることで、興味深いことができると紹介しています。例えば、

  • ある単語に近い単語を推測する(France -> Spain)
  • 単語同士の連想のようなものをベクトルの計算で求める(France -> Paris ならば Italy -> ? という問いにRomeと答える)

というようなものです。詳しくは多くのサイトで紹介されているので、探してみてください。本来こういった人工知能の問題は、それなりに速いCPU、豊富なメモリのマシンで動かすものですが、word2vecはそれが比較的安価なコンピューティングパワーで実現できる、という特徴を持っています。であれば、Raspberry piで動かしてみようというわけです。

ダウンロード

Google Code Archiveで配布されていますので、Subversionコマンド(svn)でダウンロードします。trunkディレクトリに必要なファイルが入ります。注目すべきはプログラムのコンパクトさです。word2vec.cはC言語で702行しかありませんからね。

pi@raspberrypi:~$ svn checkout http://word2vec.googlecode.com/svn/trunk/
A    trunk/word2phrase.c
A    trunk/LICENSE
A    trunk/word-analogy.c
A    trunk/compute-accuracy.c
A    trunk/demo-analogy.sh
A    trunk/demo-classes.sh
A    trunk/demo-train-big-model-v1.sh
A    trunk/demo-word-accuracy.sh
A    trunk/demo-phrases.sh
A    trunk/questions-words.txt
A    trunk/demo-phrase-accuracy.sh
A    trunk/demo-word.sh
A    trunk/distance.c
A    trunk/README.txt
A    trunk/questions-phrases.txt
A    trunk/word2vec.c
A    trunk/makefile
リビジョン 42 をチェックアウトしました。
pi@raspberrypi:~$

コンパイル

コンパイルにはgccが必要です。まずは普通にmakeしてみました。すると……

pi@raspberrypi:~/trunk$ make
gcc word2vec.c -o word2vec -lm -pthread -O3 -march=native -Wall -funroll-loops -Wno-unused-result
cc1: error: bad value (native) for -march switch
makefile:8: recipe for target 'word2vec' failed
make: *** [word2vec] Error 1
pi@raspberrypi:~/trunk$

コンパイルに失敗します。エラーメッセージから、どうやら-march=nativeというコンパイルオプションに問題があるようです。このオプションは搭載されているCPUに応じたコンパイルをするためのものです。しかし、このオプションがうまく機能しない場合があるようです。情報を探してみたら、以下のサイトにたどり着きました。この情報をもとに解決策を探してゆきます。

GCCの最適化 - Gentoo Wiki

Raspberry pi 2はARM v7というプロセッサを搭載しています。これはcpuinfoで確認できます。

pi@raspberrypi:~/trunk$ cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 5 (v7l)
BogoMIPS        : 57.60
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc07
CPU revision    : 5
(以下だいたい同じ情報が4回(コアの数だけ)繰り返し出力される)

また、gccのオプションでも、現在の環境についてのヘルプが得られます。★のところがenabledになっているのに注目しました。

pi@raspberrypi:~/trunk$ gcc -c -Q -march=native --help=target
cc1: error: bad value (native) for -march switch
The following options are target specific:
  -mabi=
  -mabort-on-noreturn                   [disabled]
  -mandroid                             [disabled]
  -mapcs                                [disabled]
  -mapcs-float                          [disabled]
  -mapcs-frame                          [disabled]
  -mapcs-reentrant                      [disabled]
  -mapcs-stack-check                    [disabled]
  -march=                               native
  -marm★                               [enabled]
  -mbig-endian                          [disabled]
  -mbionic                              [disabled]
  -mcallee-super-interworking           [disabled]
  -mcaller-super-interworking           [disabled]
  -mcirrus-fix-invalid-insns            [disabled]
  -mcpu=
  -mfix-cortex-m3-ldrd                  [enabled]
  -mfloat-abi=                          hard
  -mfp16-format=
  -mfp=
  -mfpe                                 [disabled]
  -mfpe=
  -mfpu=                                vfp
  -mglibc                               [enabled]
  -mhard-float                          [disabled]
  -mlittle-endian                       [enabled]
  -mlong-calls                          [disabled]
  -mpic-register=
  -mpoke-function-name                  [disabled]
  -msched-prolog                        [enabled]
  -msingle-pic-base                     [disabled]
  -msoft-float                          [disabled]
  -mstructure-size-boundary=
  -mthumb                               [disabled]
  -mthumb-interwork                     [enabled]
  -mtp=
  -mtpcs-frame                          [disabled]
  -mtpcs-leaf-frame                     [disabled]
  -mtune=
  -muclibc                              [disabled]
  -mvectorize-with-neon-quad            [disabled]
  -mword-relocations                    [disabled]
  -mwords-little-endian                 [disabled]

pi@raspberrypi:~/trunk$

makefileをviで開いてCFLAGSを書き換えます。-march=nativeを消して、-marmとします。

CFLAGS = -lm -pthread -O3 -marm -Wall -funroll-loops -Wno-unused-result

これでmakeを再度実行すると、今度は成功しました。warningはでていますが、これはgccにはよくあること、ということで……

pi@raspberrypi:~/trunk$ make
gcc word2vec.c -o word2vec -lm -pthread -O3 -marm -Wall -funroll-loops -Wno-unused-result
word2vec.c: In function ‘TrainModelThread’:
word2vec.c:366:36: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
word2vec.c:372:50: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
word2vec.c:413:54: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
gcc word2phrase.c -o word2phrase -lm -pthread -O3 -marm -Wall -funroll-loops -Wno-unused-result
gcc distance.c -o distance -lm -pthread -O3 -marm -Wall -funroll-loops -Wno-unused-result
distance.c: In function ‘main’:
distance.c:31:8: warning: unused variable ‘ch’ [-Wunused-variable]
gcc word-analogy.c -o word-analogy -lm -pthread -O3 -marm -Wall -funroll-loops -Wno-unused-result
word-analogy.c: In function ‘main’:
word-analogy.c:31:8: warning: unused variable ‘ch’ [-Wunused-variable]
gcc compute-accuracy.c -o compute-accuracy -lm -pthread -O3 -marm -Wall -funroll-loops -Wno-unused-result
compute-accuracy.c: In function ‘main’:
compute-accuracy.c:29:109: warning: unused variable ‘ch’ [-Wunused-variable]
chmod +x *.sh
pi@raspberrypi:~/trunk$

コンパイルに成功すると、デモンストレーション用のプログラムに実行権限が付与されます。さっそくdemo-word.shを実行してみます。これはかなり時間がかかります。何をしているのかというと、ネットから人工知能を学習させるためのまとまった量のテキストをダウンロードし、これを読み込みながら人工知能に学習させていくのです。別途vmstatコマンドでCPUとメモリの様子を観察していましたが、swapメモリまで使用してなんとか処理を終えていました。

私の環境では2時間半かかりました。Raspberry pi 2に搭載するSDカードの性能で少し必要な時間が変わることがあるかもしれません。

pi@raspberrypi:~/trunk$ ./demo-word.sh
make: Nothing to be done for 'all'.
--2016-03-12 19:10:43--  http://mattmahoney.net/dc/text8.zip
mattmahoney.net (mattmahoney.net) をDNSに問いあわせています... 98.139.135.129
mattmahoney.net (mattmahoney.net)|98.139.135.129|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 31344016 (30M) [application/zip]
`text8.gz' に保存中

100%[===========================================================================>] 31,344,016   732K/s 時間 42s

2016-03-12 19:11:25 (735 KB/s) - `text8.gz' へ保存完了 [31344016/31344016]

Starting training using file text8
Vocab size: 71291
Words in train file: 16718843
Alpha: 0.000005  Progress: 100.10%  Words/thread/sec: -346.25k
real    147m4.148s
user    560m58.090s
sys     0m48.780s
Enter word or sentence (EXIT to break):

さぁ、いよいよ学習が終わり、動き始めました。長くなりますので、今回はこれまでということで。