Subordinating conjunctions vs. Conjunctive prepositions について

Subordinating conjunctions vs. Conjunctive prepositions

  • Aarts 2011, Oxford Modern English Grammar における文法について
  • 一般的に従属接続詞 (subordinating conjunctions) と呼ばれている語が Aarts の文法では接続前置詞 (conjunctive prepositions) として定義されるという話

Conjunctions 接続詞の分類 (3.9)

  • Coordinating conj. と subordinating conj. に区別する
  • すなわち、等位接続詞と従属接続詞
  • Coodinating conjunctions:
    • and, or, and but
  • Subordinating conjunctions:
    • that, if (interrogative), whether, and for
    • if は疑問として使われる場合のみ
    • for は "There is nothing I want for you to say anyway." のように non-finite (節内の動詞が時制を示さないような性質) な従属節を導く
    • Subordinate clauses を matrix clauses (main clauses) に埋め込ませるものだけを subordinating conjunctions と呼ぶ
    • ここでの埋め込みは Subject, Object, Complement を指している(と思う)
    • Subordinating conjunctions に導かれるものだけが subordinat clauses というわけではない(部分集合)

Prepositions 前置詞の分類 (3.7)

  • Transitive prep., intransitive prep., complex prep., postpositions and deverbal prep.
  • 順に 他前置詞, 自前置詞, 複合前置詞, 後置詞, 脱動詞前置詞(分詞前置詞?) くらいの訳だろうか(定訳があるのかもしれないですが調べきれてないです、注意)
  • Transitive prepositions:
    • 補語をとる前置詞
    • さらに regular prepositions と conjunctive prepositions に区別する
    • Regular prep. は名詞句、形容詞句、副詞句、前置詞句を補語にとる
      • いわば普通の前置詞
      • 前置詞句を取る例は "Wait until after tomorrow tonight." のような文
    • Conjunctive prep. は節を補語にとる (5.5.1.5)
  • Intransitive prepositions:
    • 補語をとらない前置詞
    • 典型的には動詞の補語となる、例えば look in や go out など
  • Complex prepositions:
    • 複合的な前置詞
    • next to, out of, and by means of etc.
  • Postpositions
    • 主に名詞句にたいして後置されて全体として前置詞句となるもの
    • ago, apart, aside, notwithstanding, and through
    • 例は "twn years ago" や "our aloofness from the eurozone notwithstanding" など
  • Deverbal prepositions
    • Transitive prep. の機能を持つ分詞
    • according, concerning, given, and granted, etc.
    • 例は "including some of stars gathered here tonight" や "Regarding the issue of diagnosis, ..." など

Clauses functioning as Complement in prepositional phrases (5.5.1.5)

  • 前置詞句における補語として機能する節
  • 一般的には従属接続詞と呼ばれるものが Aarts の文法では前置詞として扱われる
  • 例えば although, because, since, when, where, and while は前置詞
    • 複合形も同様に前置詞扱い
  • Functions:
    • Time, Reason, Concession, Condition, Contrast, Purpose, and Result etc.
  • List of conjunctive prepositions: P157 Table 5.14

The classification of finite subordinate clauses (7.3)

  • Content clauses, comparative clauses, relative clauses に分類される
  • Content clauses:
    • finite かつ比較や関係詞がない従属節
    • 前置詞の補語になるような節も該当する
      • つまり前置詞句の中に従属節がある、という構造
    • 下位分類として次の3つがある:
      • declarative content clauses
      • interrogative content clauses
      • exclamative content clauses
    • Subject, Object, Complement になるのが中心
    • Adjunct の場合は接続詞を伴わない
      • "Had I spent my time in some other hostelry, ..." のような倒置条件節の場合のみ該当
  • Comparative clauses:
    • 比較級の文
    • ただし原級の as や比較の than は前置詞
      • それに続く節が comparative clauses
  • Relative clauses:
    • 関係詞節
    • ただし when, where, and whlie etc. は前置詞
    • 例は "In the period when he was writing in the fifties, ..."

2016-04-13

  • 明らかに接続詞として扱われるものを「節を導く前置詞」として扱うのはどう考えても変だと思ったのだけど、こうすると接続詞が何であるかを明確に規定できるので良いのかもしれない
    • この記事にまとめたときの感想
  • 最初はスマートだなと思っていたのだが、いざ「これが良いのですよ!」と説明するための整理を考えようとすると全然ダメという気がしてくる
    • 論文に「Aartsはこんな感じに整理していて、便利だから使います」という議論を書きたかった
  • 機能的な分類ではなく語的な分類を優先しているような印象
    • e.g. I know what you said. という文の what は subordinate clause を導いているものの、conjunction ではなく conjunctive preposition
    • 手元に本を置いてない状態で書いているのであとで確定します
  • 結局のところ、接続詞はどのように分類するのがスマートなのか?
    • 名詞節を導く接続詞はこれで〜
    • 形容詞節を導くのはこれで〜
    • 副詞節を導くのはこれ……
    • という感じの分類をすべきでは?
  • 「ひとつの語が複数の機能/役割を持つことがある」という前提があると考えると、語よりも PoS や Grammatical function を優先したほうがよい
  • 端から端まで読んだらどうしてこんな分類をしたのかが書いてあるのだろうか……
    • Cambridge grammar などと比較してみます

matplotlib, pylab

要は pylab は matplotlib.pyplot だけでなく numpy や matplotlib.mlab の関数も呼べるようになるらしい。

たしかに、

>>> import pylab as pl
>>> len(dir(pl))
948
>>> import numpy as np
>>> len(dir(np))
585
>>> import matplotlib.pyplot as plt
>>> len(dir(plt))
231

多い(その確認の仕方はどうなんだ)。間違っても

>>> from pylab import *

などの操作をインタプリタでなく通常のファイル上でやろうものなら名前空間がひどいことになって大変だと思う。手間を惜しんで打つならこれが一番楽そうだけど。

で、あーだこーだ言いながら捻って出てきた数式のプロットがやりたくて、次のことをした。

>>> from pylab import *
>>> t = linspace(0, 2*pi, 100)
>>> x = sin(2*t)
>>> y = cos(t)
>>> plot(x,y)
(ここで挙動不審になる)
>>> show()
(グラフの窓が出てくる)

係数は面倒なので含めなかった。
電荷は、xy平面内でy軸にそう縦軸を持った対象な8字型の軌道を運動する。運動の周期は、パラメータtの0から2πまでの変化に対応する。」
とのこと。
蛇足ですが8字って聞くとハチの8字ダンスを思い浮かべて「志向的表象じゃん!」みたいな反応をしがちです。志向的表象はいいぞ。

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());

めでたしめでたし。