日本語wikipediaにおける助詞・助動詞の使用頻度

先のいくつかの記事で示しているように、ロボットが知識的文章を短く語る時に、削除した語を繋ぐ助詞をAI的に選択させようとしている。(体言1:名詞・動詞)+(助詞1:助詞・助動詞)+(体言2:名詞・動詞)+(助詞2:助詞・助動詞)の語の並びの中で、体言1、体言2、助詞2が与えられた時に適切な、助詞1を選択させたい。これができれば、うまく、文章を短くできるだろうということである。

そこで、この並びを、日本語wikipediaの前文から拾い出して、それを元に、ディープラーニング用の学習データを作ろうということである。

4語対は、6千万個取れて、語は、word2vecのウェイトベクトルであらわすのだが、そのベクトルを取れる語は、さらに半分以下になってしまう。また、助詞、助動詞部分のパーターンがとてつもなく大きくなってしまう。「の」とか「を」などはたくさんあるが、全体で1回しか現れないようなものも拾ってしまう。これは、広い方のアルゴリズムにも依存するのだが。

そこで、いったいどのような助詞、助動詞が、どのような頻度で現れているのかを調べてみた。

まず、助詞2(ニューラルネットの入力になる)は次のようになっている。

の 	4848543
を 	3418017
に 	3153274
が 	2271523
は 	1676994
と 	1359190
で 	1134953
た 	833487
な 	515517
から 	481586
や 	449712
も 	403445
て 	391692
である 	384000
として 	321609
ている 	278220
には 	264654
では 	242007
ていた 	141653
によって 	117531
であり 	109701
により 	109549
であった 	107166
による 	101919
へ 	97715
でも 	97698
との 	95020
という 	95008
まで 	94623
への 	88007
にも 	87645
ない 	80116
での 	77605
たが 	71719
だった 	71462
など 	69269
ており 	69104
だ 	68336
ず 	64151
などの 	62250
より 	56385
とは 	53537
において 	50758
たと 	47488
からの 	46761
における 	45079
について 	38801
ば 	34365
たり 	33421
に対して 	32896
なかった 	32558
はと 	31786
としては 	31599
か 	31034
に対する 	30519
であると 	30483
としての 	30440
うと 	30412
とも 	29750
とともに 	29742
ていたが 	29645
だが 	29500
などを 	28746
までの 	28607
ながら 	27353
と共に 	26439
へと 	25588
に関する 	25518
だと 	25209
よりも 	24233
であるが 	24219
などが 	23941
ではなく 	23687
については 	23225
であったが 	21177
ているが 	20375
にて 	20046
てきた 	19284
でいる 	19168
からは 	19166
ても 	18992
ていない 	18033
などで 	17049
に対し 	16993
といった 	16725
だったが 	16552
をと 	16238
ていく 	15419
などに 	15401
ていると 	15107
てしまう 	14659
までに 	14412
にと 	14395
においては 	13755
でいた 	13566
ずに 	12898
のみ 	12697
なく 	12433
たものの 	12417
にかけて 	12292

明らかに、代表的助詞型を圧倒している。だから、全部を対象にすることはない。だいたい、上位128個くらいの使い方がわかればそれでいいのではないかと思う。入力に関しては次のようになっている。

の 	6087401
は 	2794515
に 	2311801
を 	1850357
が 	1667993
で 	1144968
と 	1039936
た 	1026311
な 	563759
や 	531865
から 	515033
て 	502233
には 	461876
では 	405320
も 	340662
である 	297177
として 	239221
ている 	200314
という 	145218
であり 	141251
ていた 	140480
との 	135622
により 	135543
による 	124273
への 	116794
での 	114556
たが 	110351
によって 	100663
まで 	99795
などの 	99002
ており 	98666
など 	95691
でも 	91841
ず 	91712
とは 	87425
であった 	78465
ない 	76015
にも 	73529
より 	69404
だ 	67224
において 	65830
からの 	63813
における 	59617
だった 	59331
ば 	53503
へ 	50134
としての 	44902
に対する 	40913
に対して 	40079
だが 	39554
としては 	38818
に関する 	37624
について 	37003
ていたが 	36863
までの 	35317
とともに 	33629
からは 	33043
ながら 	32942
たり 	31465
であるが 	31366
については 	30835
と共に 	30434
か 	28826
はと 	28675
ではなく 	27939
なかった 	27507
といった 	26896
などを 	25960
に対し 	25781
であったが 	25642
よりも 	24764
においては 	24509
ているが 	24095
ても 	22715
にかけて 	22410
にて 	22061
とも 	20988
だったが 	20078
てきた 	18660
までは 	15710
はの 	15630
などで 	15530
たものの 	15429
などが 	15169
うと 	14569
へと 	14314
までに 	14160
にとって 	13547
ていない 	13388
たという 	13324
でいる 	12949
ずに 	12844
についての 	12823
のの 	12695
でいた 	12154
ので 	12077
ほど 	11709
のみ 	11541
であると 	11315
だと 	11167
はという 	11122
がと 	11042
をと 	11024
ていく 	10883
てしまう 	10794
などに 	10719
においても 	10605
にと 	10454
を通じて 	10373
たと 	9804
だけでなく 	9448
ての 	9116
しか 	9065
にの 	9027
によっては 	8952
かの 	8682
であるという 	8620
に関しては 	8216
てしまった 	8172
ほどの 	8126
ていて 	8058
はなく 	8000
からも 	7909
ては 	7779
てくる 	7631
てから 	7518
にという 	7329
つつ 	7309

上位グループの順序は微妙に変わっている。助詞の位置が影響しているのだ。が、上位グループのメンバーはあまり変わらない。

助詞推定AIの改訂(1)

ロボットが知識データを言い換える時に、助詞を適切なものに切り替える必要があり、前後の体言や助詞からそれを推計するシステムを作ったと、先の記事で書いた。そのシステムを、いざ、即興漫才システムに組み込もうとした時に、いくつか問題が起こって、最初のデータから作り直すことにした。

まず、助詞だけにして助動詞を対象から外していたのを、加える必要がある。名詞や動詞が連続する場合、1語として扱えるようにする。助詞、助動詞も連続して現れる可能性があるので、それも対応する必要があった。

データ作成は、まず、日本語wikipediaから、元データを作成する。基本的に、文章の中にある、

体言1(動詞、名詞) → 助詞2(助動詞も)→ 体言3→ 助詞3(助動詞も)

という4つの語の流れを拾ってくる。例えば、次のようなものである。

肥満::は::一般的::に
一般的::に::正常::な
正常::な::状態::に
状態::に::比べ::て
比べ::て::体重::が
体脂肪::が::過剰::に
過剰::に::蓄積し::た
蓄積し::た::状況::を

ある生存中::の::当事者同士::が
当事者同士::が::有効::に
有効::に::成立し::た
成立し::た::婚姻::を
婚姻::を::婚姻後::に
婚姻後::に::生じ::た
生じ::た::事情::を
事情::を::理由::として
理由::として::将来::に
将来::に::向かっ::て
向かっ::て::解消すること::を

ペットボトル::は::合成樹脂::の
合成樹脂::の::一種::である
一種::である::ポリエチレンテレフタラート::を
ポリエチレンテレフタラート::を::材料::として

パンダ::は::ネコ目::に
ネコ目::に::属するジャイアントパンダ::と
属するジャイアントパンダ::と::レッサーパンダ::の
レッサーパンダ::の::2種::に対する
2種::に対する::概念上::の
概念上::の::総称::である

この助詞1を体言1、体言2、助詞2から推計しようというのである。後者をword2vecのベクトルデータを用いるなどして入力データに変換して、出力が助詞1のいずれかに推計する。

上記の4語のデータを、日本語wikipediaデータについて、すべてやる。日本語wikipediaデータは、word2vecの時に使用下処理済みデータを用いる。

24スレッドをフル稼働させるプログラムにしたら、10分程度で、全データを処理終えて、4つの語の組み合わせを、63,600,830個拾い出してきた。6千万個以上である。すごい。データは、2ギガくらいのファイルに保存んした。

ディープラーニングのプログラムを組み直す(2)

相当基本的なところから組み直した。ごちゃごちゃしたプログラムをだいぶ整理した。直しはバグのもとであり、結局、MNISTの手書き文字の認識まで戻ってテストせざるを得なくなった。

ディープラーニングのエンジンである、バックプロパゲーションのところだけは、流石にいじらなかった(笑)ここをいじり始めたら収拾がつかなくなる。

以前は、学習とテストを同じ関数でやっていたが、きちんと切り分けた。CUIからGUIにインターフェイスをレベルアップさせた。

かなり拡張性も出てきたと思う。MNISTの正解率も以前のものと同じものに戻った。オブジェクトというか、クラスをかなり整理したので見やすいプログラムになったと思う。

これで、最適助詞選択プロジェクトに入る。

twitter データを最初から作り直す

この間、twitterやwikipediaのウェイトデータをmariadbのデータベースにしたり、言葉の距離の近いものをリストする場合のデータを事前作成したりしたが、データ量を減らすために、4文字以上のアルファベットのある言葉を排除してきたり、全てがアルファベットの言葉を排除したりした。この制約が、いろいろ面倒なことになってきた。ので、全て作り直す。10時間くらい浪費するような気がする。

Twitterデータは、その後集めたデータも含めて、最初のコーパスから作り直す。結局、利用する総ツイート数は、
25,188,425ツイート
になった。まだ1億個までは程遠い。ので、毎日せっせと収集スクリプトを動かして集めている。24時間動かし続けて、100万個程度集まるので、1ヶ月かけても1000万しか集まらない。スレッドを複数にして集めようとしたが、結局、twitterがサンプリングしているのは同じのようで、同じものを複数買い集めていることにしかならないので、一個のプログラムでひたすら集めている。

word2vecのdistanceで、入っている任意の言葉のすべてについて、相互の距離を計算するので、計算量は膨大であり、自宅の12コア、24スレッド動くmacで20スレッド程度を並列で動かしてまず、テキストデータを作成し、それを次にmariadbに登録する。

word2vecのネットワークウェイトをmariadbに入れる in raspberrypi

raspberrypiのメモリ制約や、ディスク容量のおかげで丸一日、いや二日、苦労している。なんとか、辞書やwikipediaがらみのデータベースは、raspberrypiに収まったが、次は、word2vecのバイナリデータをラズパイ上で読み込もうとするとmapのサイズやそれと直結したラズパイのメモリ制約で、データを全部読み込めない。wikipediaから作ったもの90万語分、twitterから作ったもの50万語分あり、確かにこんなものをmapにするのは、ラズパイでは無理だと諦めた。代わりに、まだ、mariadbならなんとかなりそうだということで、バイナリデータを読み込んで、データベースへ登録した。小数点いか5位までしか入れていないのが若干不安だが、容量を大きくしないギリギリだった。

これでも二つのデータで、データベース上で2.5ギガくらいになるのだから。

何れにしても、こんな変換が簡単にできるのは、ウィトのバイナリデータをjavaで扱えるからだ。本当は自分で作らなければと思ったのだが、バイナリファイルから読み込むのがうまく行かなかった。それをちゃんとやっていただいている、javaプログラムが、以下のところにあったので、使わせていただいた。
https://gist.github.com/RoyZhengGao/1c8229413881cf551dd3
全く、優れたプログラムだ。とてもありがたい。

RaspberryPi にコマンドラインでbluetoothを制御する

HALは、一旦組み上げると、USBを新たにつなげることができないので、キーボードもマウスも使えない。ただ、どうしても必要な時(例えば、何かの拍子でどのIPで繋がっているかわわからない時など)があるので、bluetoothのキーボード(マウスパッド付きの小型のもの)を使っていた。
ただ、たまに、繋がらなくなる時がある。すると、マウスが使えないのでラズパイのウィンドウ操作で再接続ができなくなり、にっちもさっちも行かなくなる。sshでターミナルには接続できるので、それでbluetoothがコントロールできないかと思ったら、bluetoothctlというラインコマンドがあった。なぜか、すでに入っていたのでありがたい。使い方は簡単だ。

$ Bluetoothctl

で起動する。
詳細はこちらに記載されているhttps://qiita.com/propella/items/6daf3c56e26f709b4141

基本的なものは次のようになる。

[bluetooth]# show

で状態表示。スキャンは次のようにする

[bluetooth]# scan on

Discovery started
[CHG] Controller B8:27:EB:7D:14:E6 Discovering: yes
[NEW] Device 79:50:86:95:3F:CB 79-50-86-95-3F-CB
[NEW] Device 78:7B:8A:F3:B6:F7 78-7B-8A-F3-B6-F7
[CHG] Device 79:50:86:95:3F:CB RSSI: -68
[NEW] Device CC:C5:0A:28:6E:BA CC-C5-0A-28-6E-BA
[CHG] Device CC:C5:0A:28:6E:BA LegacyPairing: no
[CHG] Device CC:C5:0A:28:6E:BA Name: Bluetooth 3.0 Macro Keyboard
[CHG] Device CC:C5:0A:28:6E:BA Alias: Bluetooth 3.0 Macro Keyboard

接続対象のデバイスは、

[bluetooth]# devices
Device 79:50:86:95:3F:CB 79-50-86-95-3F-CB
Device 78:7B:8A:F3:B6:F7 78-7B-8A-F3-B6-F7
Device CC:C5:0A:28:6E:BA Bluetooth 3.0 Macro Keyboard
[CHG] Device 79:50:86:95:3F:CB RSSI: -68
[CHG] Device 78:7B:8A:F3:B6:F7 RSSI: -48
[CHG] Device 78:7B:8A:F3:B6:F7 RSSI: -69

接続は、次のようにデバイスアドレスを使う。

[bluetooth]# connect CC:C5:0A:28:6E:BA
Attempting to connect to CC:C5:0A:28:6E:BA
[CHG] Device CC:C5:0A:28:6E:BA Connected: yes
[CHG] Device CC:C5:0A:28:6E:BA Modalias: usb:v0A5Cp8502d011B
[CHG] Device CC:C5:0A:28:6E:BA UUIDs: 00001000-0000-1000-8000-00805f9b34fb
[CHG] Device CC:C5:0A:28:6E:BA UUIDs: 00001124-0000-1000-8000-00805f9b34fb
[CHG] Device CC:C5:0A:28:6E:BA UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device CC:C5:0A:28:6E:BA ServicesResolved: yes
[CHG] Device CC:C5:0A:28:6E:BA Paired: yes
Connection successful

今まで、接続できずに結構パニックに陥ったが、これで随分助かる。

即興ロボット漫才システム・・・・自分への約束を果たすために

M-1の1回戦の一週間前になってようやく、即興ロボット漫才システムの全体が出来上がった。明日は、ロボットに実装して、細かい調整をしていこうと思う。

舞台でやることを前提に、基礎的なところをできるだけしっかりさせた。ネタ時間(尺)が2分しかない。お客さんからお題をもらうので、途中でデータができなかったではすまない。

一般の国語辞書、シソーラス辞書、wikipedia、twitterなどの膨大なデータを必要なだけ利用している。さらに、wikipediaの全部とtwitterの2千数百万ツイートを人工知能的手法 word2vecを利用して、言葉の意味を理解しているような共感を引き出すようにしている。

今まで使っていなかった、類似語の距離計測モジュールも利用した。これもとても大事な役割をしている。記録しておく。レーベンシュタイン距離とジャロ・ウィンクラー距離という二つがあるが、ライブラリが問題なく利用できた後者を使った。
https://blogs.yahoo.co.jp/dk521123/36655532.html
ここのサイトの情報を利用させていただいた。luceneのサイトからダウンロードしたjavaライブラリでは、レーベンシュタイン距離の方を出す計算が、使わないようにという指示がされているようだった。

さて、M-1どうなることやら。去年は、謎かけだけやったのだが、その時、来年はもっと高いレベルのものをお客さんに見ると自分に約束した。今回の即興漫才がうまくいけば、その自分への約束を果たせことになる。

twitterデータをword2vecで解析し、wikipedia と比較する

この間、wikipediaデータを元にword2vec用のデータベースを作成した。それはそれで、十分実用性があるが、さらに実際の言葉の、喋り口調の使われ方を見るためにTwitterのAPIを使ったサンプリングデータをコーパスにして作成してみることにした。

Twitterのサンプリングは、APIを使って、昨年末から今年にかけて2000万ツイートを集めていた。さらに最近200万ほど追加して、総計 24,173,335ツイートである。

手順はwikipediaの場合と同じである。ほぼ100万ツイートずつ分かれていたものを一つのファイルにまとめる。

$ cat tweets1* > tweets_all_180907.txt

という感じ。

これをneologdを使ったmecabで分かち書きをする。

$ mecab -Owakati -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd/ tweets_all_180907.txt -o twitter_wakati_data.txt

これをword2vecにかけて、ウェイトデータを作成する。

$ word2vec -train twitter_wakati_data.txt -output twitter_wakati.bin -size 200 -window 5 -sample 1e-3 -negative 5 -hs 0 -binary 1

ウェイトデータは、477メガバイトになって、wikipediaの場合の795メガバイトよりもだいぶ小さい。

あとは、distanceで分析できる。関連語検索を、wikipediaの場合と比べてみるととても面白い。
例えば、コンビニを調べる。
wikipediaの場合

Word: コンビニ	Position in vocabulary: 16062
Word	 Cosine distance
-------------------------------
コンビニエンスストア	0.870578
量販店	0.772738
家電量販店	0.751852
ファーストフード店	0.721780
スーパーマーケット	0.720924
100円ショップ	0.718245
ファミリーレストラン	0.713548
キヨスク	0.712224
ホームセンター	0.709059
NEWDAYS	0.703931
自販機	0.699429
ディスカウントショップ	0.695208
玩具店	0.692847
セブンイレブン	0.689320
飲食店	0.687436
売店	0.687210
ドラッグストア	0.686923
キオスク	0.684569
パチンコ店	0.682252
セブン-イレブン	0.681514
小売店	0.679067
大型書店	0.676887
大衆食堂	0.674396
レンタルビデオ店	0.669804
パソコンショップ	0.669721
うどん店	0.669188
弁当店	0.668718
駄菓子屋	0.668227
ブックオフ	0.667262
外食チェーン	0.666742
ファストフード店	0.665017
トイザらス	0.662631
コインランドリー	0.661140
アニメショップ	0.659252
ゲームセンター	0.658729
デイリーヤマザキ	0.652585
ローソン	0.651909
ガソリンスタンド	0.650547
インターネットカフェ	0.650438
自動販売機	0.650044

となる。まあ、なるほどという感じ。これに対して、Twitterコーパスを使った場合は、次のようになる。

Word: コンビニ	Position in vocabulary: 1768
Word	 Cosine distance
---------------------------------
スーパー	0.667722
自販機	0.642148
セブイレ	0.633234
レジ	0.631955
ファミマ	0.627591
セブン	0.625176
ミスド	0.618061
ローソン	0.614712
西友	0.614702
業務スーパー	0.612738
マック	0.597435
スタバ	0.596482
ガソスタ	0.596407
ファミレス	0.593658
ブックオフ	0.592258
LAWSON	0.577262
ツルハ	0.571627
カルディ	0.570277
デパ地下	0.568725
マツキヨ	0.568646
セコマ	0.568199
ドンキ	0.568019
ホムセン	0.567909
生協	0.567643
スーパーマーケット	0.565221
喫茶店	0.565085
セブンイレブン	0.562578
本屋	0.561266
ドラッグストア	0.556287
売店	0.555747
飲食店	0.555709
ゲーセン	0.555684
マクド	0.550563
自動販売機	0.549253
すき家	0.549123
薬局	0.548373
売り場	0.548229
駅前	0.548090
コストコ	0.543193
イオン	0.540342

しゃべり言葉の中で使われた関連語という感じが実によく出ている。セブイレなんて、私は使ったことがないが、使われているようだ。

使い分けが大事になる。

QRコードの読み取り

ロボットが案内ができるように、あるいは位置を把握するために、QRコードを読み取る能力をもたせたいと考えた。

Raspberrypiのカメラ、それで撮ったのをgoogleのzxingというコード認識ライブラリを経由してコードを認識させる、というものだ。

このライブラリを使えば、認識とコード生成が極めて簡単に行える。以下のようなところを参考にさせていただいた。
https://qiita.com/tool-taro/items/1923f948a1908255d5df
https://qiita.com/yoshi389111/items/0fee2be43e5135b1bb15

これで、単にQRコードがきちっと入った画像だけではなく、ゴタゴタした背景の中にあってもそれを認識できる。
例えば

こんな画像でも認識できる。あとは、頭の部分についている、このカメラの動かし、このQRコードを認識させることができればいい。