「今起きた」「おそよう^^」
./hometime.sh 2Dcat
みたいにして使う.2Dcat
に書いてく.2Dcat
を読んで前回の続きから再開する.in_reply_to_status_id_str
があるものについて発言先を取ってくる
mkdir inreplyto
cat 2Dcat | awk '$0=$2' | grep -v null | while read id; do
if [ ! -f "inreplyto/$id" ]; then
twurl "/1.1/statuses/show.json?id=${id}" | jq -r .text > inreplyto/$id;
sleep 10;
fi;
done
for f in inreplyto/*; do if [ "$(cat $f)" == "null" ]; then echo $f; fi; done
いわゆるNNs の型は [float; m] -> [float; n]
である.
ここで [float; m]
は長さ m
で要素がすべて float
とある配列を表現する型.
RNN (recurrent-NNs) の一つであるLSTMは [float; m] -> [float; m]
である.
ただし、この機械は状態を持つ.
状態は一回の入出力によって変化する.
その状態で入出力が変化するので ([float; m], State) -> ([float; m], State)
と書くのが正確である.
また初期状態という状態が定まっている.
応答文生成や自動翻訳にRNNが期待されている.
どちらともに、長さが不明な文1を入力に与えると、長さがやはり不明な文2が出力されるという機械にほかならない.
RNNの枠組みでこの機械を再現する素朴な方法は単純である.
文1を [float; m]
に変換する.
これを x1 x2 .. xm
とする.
これは例えば文字やトークンの列に相当する.
機械 RNN に x1
x2
.. xm
を順に与える.
出力は初め気にしないが、xm
を与えて出てきた出力を y1
として記録する.
次からは y1
を与えて出力を y2
とする
y2
を与えて出力を y3
とする
これを繰り返すことで無限長の出力列を得るが、
特殊な制御文字 </s>
を考える.
これは決して他とは被らないという意味で特殊である.
出力 yn
が </s>
になったとき、機械をとめ、それまでを出力とする.
初めの入力の最後 xm
をやはり制御文字 </s>
とする方法もあるし、別の制御文字を敢えて使うことも考えられる.
双方向RNNというのもある.
これは初め、x1 x2 .. xm
と読むのではなく
xm .. x2 x1 x1 x2 .. xm
と、まずはじめに逆順に読んで、その後に順に読むのである.
LSTMは昔読んだ入力を徐々に忘れていく.
繰り返し読むことでうまい具合に記憶しているっていう、技巧である.
./test.input
./train.py -i test.input -o test.model --iteration 1000
.gen.py ./test.model
./gen.py test.model
> おはよう
おはようございます
> おはようございます
おやすみ
> おっはー
おやすみ
> 起きた
はい、おはよう
> 寝る
おはようございます
> もう寝よう
もう寝るの?!
> 寝ます
おやすみなさい
>
平面ねこさんからは結局、1035の対話事例が得られた. 決して多くはないが、平面ろぼさんからコレ以上取るのは難しそうだ. 他のソースも考えよう.
とりあえずこれで演ってみる.
./train.py -i 2Dcat.txt -o 2Dcat.model --iteration 10000
実は公平に事例を選んでるわけではないのだが、平均的に10epoch学習したことになる.
ちなみに CPU 1個で22分かかった.
$ ./gen.py 2Dcat.model
> あ
うんんんだ
> ねえ
その話
> 元気?
うんんんんだ
> 元気してる?
そう
> ねえねえ
その話
> 大丈夫ですか
そう
> おい
そうだね
> しっかりして
そうだね
> ごめんね
なんだ
> おはよー
ふうん
> 今まで寝てた
その話しない
> 寝てた
その話しない
> …
そう
> ……
そうなの
> やたのしい
そんなの
> 楽しい
そう
> やだ
そう
> よし死のう
そうだね
> なにそれ
なんだ
> @@;
ふふむ
> ふふふ…
そう
> wwwwwwwwwwwwwwwwwwwwww
ふふふ
> テンション高いねー
なんだ
>
絶望