virtualenv, zsh, and rprompt

導入したので覚え書きを残す
  • virtualenv 入れないと pip list が荒れたり依存関係で人が死んだりする
  • virtualenv はひとまず ~/.venv のように共通化しておいて、alias ve='source ~/.venv/bin/activate' とする
  • python3は必要になってないからまだ作ってないけど、.venv3とかにすれば良さそう
  • venv が activate されている状態の PROMPT がダサい
    • いつもは PROMPT='%F{cyan}(✿ >ヮ<)ノシ%f ' にしている(かわいい)
    • 右側は RPROMPT='%F{cyan}[%~]%f' にしている(いまあなたがどこにいるかだけ知りたい)
    • 標準だと (.venv) (✿ >ヮ<)ノシ になっちゃう(かわいくない)
  • ~/.venv/bin/activate を編集する
    • PS1を変更するような処理になっているのでコメントアウトしておく
    • 同じ所に export RPROMPT='%F{cyan}(ev)[%~]%f' を足しておく(良い案が思いつかなかったのでベタ書きです)
    • deactivate 関数の中に export RPROMPT='%F{cyan}[%~]%f' を足しておく(またベタ書きです)
  • どうせ RPROMPT なんてそうそう変更する気にならないだろうという予知が入っています

Training, Validation, Development and Test set の区別について曖昧さがあった

Show, Attend and Tell の再現をやる

概要

  • paper: Show, Attend and Tell: Neural Image Caption Generation with Visual Attention
  • Attention 能力を備えたキャプション生成
  • CNN で特徴抽出
  • 抽出した特徴からキャプションを生成するように LSTM を学習
  • 論文の著者は2週間くらい訓練にかけたらしい
  • 私は大学のDeepLearning講座(http://ail.tokyo)で題材にして再現を試みました
  • この記事は「初心者がとりあえず訓練回して簡単な例を生成できるとこまでいった」経緯を書いているだけ(自分はそこまでが大変だったので……)なので、申し訳ないのですがうまくいってる例などは論文を参照してください
  • もし間違ってる(あるいは非効率な)ことがあったら指摘してもらえると幸いです

再現

  • ソース
  • データセット
    • 今回は flickr30k にした(入手に名前とメールアドレスが要る)
    • 3万件の画像と5文ずつの説明文からなる
    • http://shannon.cs.illinois.edu/DenotationGraph/
    • 他に flickr8k と MSCOCO 向けにoptionがある
  • 環境構築
  • 特徴抽出まで:
    • 画像から抽出した特徴量と正解キャプションをpklファイルで固めたい
    • 単語のベクトル表現作るためのdictionary.pklも要る
    • pklファイル生成のコードはkelvinxuさんのところには置いてない(たかが前処理やんけという勢い)
    • 揉めてる: https://github.com/kelvinxu/arctic-captions/issues/1
      • pklファイルのフォーマットはここのコメント4つめくらいに書いてある
    • どうやって作るの: https://github.com/asampat3090/arctic-captions の make_flickr_data.py を使わせていただく
    • ただし dictionary.pkl の作成はうまくいってない(他のissuesで指摘されてる)
      • 正しい dictionary.pkl は気合で作る: カンマなども含めて頻度順に2からインデックスを振っていく(flickr30kは23462まで、cocoは35630までありました)
    • 注意1: caffe の load model は 絶対パスにすること
    • 注意2: asampat3090さんの caffe_cnn 用のコードも手元に置いてimportできるようにしておかなければならない
    • CPU mode のときは caffe_cnn.py L23 set_mode_gpuコメントアウト
    • でもCPUじゃ絶対やらないほうがいいです、現実的な時間では終わらないので(私はCNN側はCPUでやりましたが、LSTM側はGPU使いました)
    • という感じで、kelvinxu/arctic-captions/flickr30k.pyの末尾でロードしているような形のpklファイルを錬成する
  • CNN: 事前に訓練されてる caffe_model を使う
  • メインの訓練:
    • evaluate_coco.py が実行の本体
    • evaluate_flickr30k.py みたいな形でコピーして、オプションを変える
      • 最低限 dataset="flickr30k" とすれば無問題?
    • THEANO_FLAGS='floatX=float32' python eval_flickr30k.py をつける
      • GPU使うときは THEANO_FLAGS='mode=FAST_RUN,device=gpu0,floatX=float32' python evaluate_flickr30.py みたいにする
      • GPU状況の確認はターミナルで $ nvidia-smi すれば見られる
    • もしかしたら flickr30k.py L13 feat_list.append(features[cc[1]]) でエラー吐くかもしれない
      • 変数 features が scipy.sparse.csr_matrix(列重視の疎行列の型)ではなく scipy.sparse.coo_matrix(疎行列の基礎の型) になってるのが問題だった、このままだと列の切り出しがうまくできないので、 features = featurs.tocsr() という操作を挟んでおくと(もしかしたらcopulaにする必要ないかも)おっけー
      • pklからのロードしたときは元がcsrでもcoo扱いになるみたい(そこまで不思議なことでもないけれど)
  • 動作やスペックまわり
    • データちっちゃくして試しにやってみよって思っても精度は出ないし
    • ちっちゃくするときは batch_size あたりも変えましょう
    • 訓練すると途中でも my_caption_model が保存されるのでうまく区切りましょう
    • my_caption_modelはpkl付いてるほうがoptionの情報が保存されてる(と思う)
    • MacBookAir(core i5)のcpu_modeでは1epoch終わらせるのに10時間単位でかかった
    • そもそも pkl ファイルが計8-9GBくらいあるしラップトップでやるのは非理性的
    • 講座で貸し出されていたGPUありインスタンス使ったら100倍以上速くなった
  • 訓練が終わったら
    • generate_caps.py がテスト用の呼び出しをしてくれる

まとめ

  • GPU至上主義
  • 今回初めてまともにCNNやらLSTMやら回してるコード弄った
  • 結局データセットの前処理やら扱いやらが一番面倒なのでは?

という感じでした。一週間くらいずっとコードとにらめっこしてた。

mallet CRF の確率出力

状態の番号がよくわからんかったという話。
参考は http://mallet.cs.umass.edu/fst.php

// 各クラスの import や crfの宣言は済んでいるということにして...
CRFTrainerByLabelLikelihood trainer = new CRFTrainerByLabelLikelihood(crf);
trainer.setGaussianPriorVariance(10.0);
trainer.train(trainingData);

// transducer は何か便利なwrapperらしい
transducer = trainer.getTransducer();

// SumLattice は確率出力用のクラス(?)
// input はデータの系列、本例ではinput末尾のラベルが予測したいとする
// もちろん番号を弄れば好きな位置の予測分布が得られます
SumLattice latt = new SumLatticeDefault(transducer, input);
Sequence result = transducer.transduce(input);

// stnum は状態数(候補となるラベルの数)
int stnum = transducer.numStates();
String names[] = new String[stnum];
double probs[] = new double[stnum];
for (int i = 0; i < stnum; i++) {
    names[i] = transducer.getState(i).getName();
    // 次に予想される周辺確率の出力(resultの末尾で予測される各ラベルの確率)
    // result.size() の位置を知ればinput末尾の予測分布を知ることができる、のが大事
    probs[i] = latt.getGammaProbability(result.size(), transducer.getState(i));
}

// input末尾における各ラベルの予測確率
System.out.println("[Labels]" + Arrays.toString(names));
System.out.println("[Probs]" + Arrays.toString(probs));

// input末尾について予測されるラベル
System.out.println("[Predict]" + result.get(result.size()-1).toString());

めでたしめでたし。

pythonのword2vecがインストールできなかった

でも唸っていたらできたのでメモ
環境はOSX(10.10)でgccは(homebrew gcc47)です

$ pip install word2vec
すると
ValueError: 'word2vec/word2vec_noop.pyx' doesn't match any files
Command "python setup.py egg_info" failed with error code 1 in ...
などと言われる。

よくわからないから手動で入れる:
GitHub - danielfrg/word2vec: Python interface to Google word2vec
を好きなフォルダでgit cloneする

$ python setup.py install
すると
('Compilation command:', 'gcc [...]word2vec.c -o bin/word2vec -lm -pthread -O3 -Wall -march=native -funroll-loops -Wno-unused-result -I /usr/include/malloc')
no such instruction: `vzeroupper'
から始まる「命令ないよ」エラーがたくさん出てくる
エラーメッセージで検索すると
 -march=native
を削ればできるんじゃねみたいなのが出てくる(最適化のオプションらしい)
gcc - Erroring on "no such instruction" while assembling project on Mac OS X Lion - Stack Overflow
ということでsetup.pyの中をいじってみたらうまくできました。

Java, jar, javac

ジャバのジャーをクラスファイルから再錬成して実行したいときの話。
さっぱり知らなかったけど関連のコマンドが複数あって「(全部javaコマンドに適切なオプションつけて投げたらOK、ってわけじゃないのか……)」という気持ちになった。

# class ファイルをつくる (hogehoge.classができる)
$ javac hogehoge.java

# jar ファイルを作る(すでにmanifestファイルがあって、全部突っ込みたいとき)
$ jar cvfm hoge.jar MANIFEST.MF *

# jar ファイルを実行する
$ java -jar hoge.jar

python, json, unicode

なんでうまくいったのかよくわからないけど、unicodeでいろいろ書いてあるjsonファイルを読み込んでまた書き込みたいときの処理。

import json, codecs

## 読み込み
fin = codecs.open(fin_name,'r','utf-8')
jdata = json.load(fin)
fin.close()

## jdata の処理

## 書き込み
fout = codecs.open(fout_name, 'w', 'utf-8')
json.dump(jdata, fout, indent=5, ensure_ascii=False) #indentを設定すると整形される
fout.close()