Jumanの死

1億1千万ツイートのprolog化も、最終局面に来ている。トラブルがなければ、明日の朝には、終わっているはずだ。

前の記事からの進展は、サーバーモードのJumanが、耐えられなくなって死んでしまうという現象を回避するようにしたことだ。

全てのツイッターを4分割して、その三つ目をやっているときに、どうしてもSocketExceptionエラーが発生して、サーバーモードのJumanのソケットが死んでしまって、そのスレッド自体がフリーズしてしまうという現象が発生するようになった。そうなると、他はうまくやっているようなのだが、私の方が続ける気が無くなって、全体を止めてしまうというのが繰り返された。(一つのスレッドに、一つのJumanを、ポートを変えて立ち上げているので、他のJumanには影響を与えない)

よくよく原因を調べると、異常なツイートにJumanが疲弊してしまったようだ。ツイートの中に、次のような二つのツイートが続いてあった。

かぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁわぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁいぃぃぃぃぃぃぃぃぃぃぃぃぃぃぃε=ε=(ノ≧∇≦)ノ#ボタンインコ#インコ
【1週間限定】セブン-イレブン、かわいすぎるXmasスイーツが登場sCMXcバニラといちごのサンタケーキ、チョコとクッキーのトナカイケーキ、いちごムースを使った柊のケーキを展開しています。 https…

この二つのツイート、それぞれ単独では、prolog 化できるのだが、続けると必ず、二つ目の文章のJumanによる形態素解析の場面で、SocketExceptionエラーが発生してしまう。Jumanのプログラムを調べていないので(ソースはあるが、面倒でできない)よくわからないが、最初の文章でJumanが内部エラーを引き起こしてしまっているようなのだ。

さらに調べると、最初の「ぁぁぁぁぁぁぁぁ」あるいは「ぃぃぃぃぃ」というような文字の連続を一部やめる(少し短くする)と、続けても問題なくprolog化できる。およそ、このツイートは日本語ではないので、Jumanが投げ出してしまう気持ちもよく理解できる。(元文章はなるべくいじらず、可能な限り受け入れようというのがポリシーだ。そうすることによって、どんな文章にもprolog化アルゴリズムが適用できるだろうと思っているので)

内部エラーを起こして、フリーズしてしまうのは実は係り受け解析のKNPなのだ。なぜそうなるのかというと、Jumanの内部エラーで、中途半端に構文解析終えて、最後にEOSを返さないのだ。そのために、EOSをKNPがいつまでも待つという形でスレッドがフリーズする。だから、最後にEOSをあえてつけるようにしたが、それでKNPはフリーズしなくなるのだが、その後Jumanは動かなくなってしまうので、処理が進まない。

結局、先のような同一文字が5文字以上続いているような文章は、prolog化の対象から外すことにした。正規表現の後方参照で、そのような連続文字をチェックできる。

ただ、そうしてみると、ツイッターの中には、そうした同一文字の連続うちという現象がいたるところで観れる。だから、多少躊躇したが、そんなの文章じゃないだろうという思いの方が打ち勝って、この基準を導入することにした。

今、最後の1/4を実行している。210このスレッドが動いている。早くて超高機能のパソコンのおかげで、大きな問題なくここまできた。

TweetsのProlog化を高速で処理する

集めた1億1千万のツイートサンプルを全部、prologの宣言文にしたい。それが、日本語wikipediaの本文全文のprolog化よりも何倍も深刻なものだとわかった。wikipediaと同じアルゴリズムでやろうとすると、core_i9のlinuxを動かし続けても、50日くらいかかる。動かせば良いというのはそうなのだが、そうすると途中でミスやバグに気づいても、もうやり直すリスク異常に高くなる。

長いこと悩んだが、最適な解決方法がわかった。それは、一番、時間コストがかかっている構文解析のknpを高速化することだ。knpは、それまで使っていたCabochaと比べるととてつもなく時間をかけて解析する。それで、カテゴリなどの面白い結果を出してくるのだから仕方がないと思っていたのだが、もう、ここを高速化するしかないと思って調べると、

-dpnd-fast -no-ne

の二つのオプションをつけると高速化することがわかった。knpを供給していただいているサイトには、

-dpnd-fast: 精度を犠牲にした高速な係り受け解析,高速に固有表現認識を行いたい場合などに用いる
-no-ne: 固有表現認識を行わないオプション,-dpnd-fastと合わせて使うことで高速に係り受け解析を行える

と解説されている。そもそも固有表現認識が何かわかっていないのだが、カテゴリなどのこちらの必要としているものが犠牲にならないならば、問題ないと試みてみた。すると、立ち上がり時間も含めて、3倍早くなった。しかし、我々の場合、サーバーモードだから、立ち上がりのオーバーヘッドは考慮しなくて良い。それで、実際やってみた印象では、10倍から20倍早くなる!!

これでやってみると、というか、現在やらせているのだが、およそ二日で計算を終える勘定だ。

1スレッドで80万ツイートを処理すべく、ファイル単位で処理するため、短い処理しか必要がない場合もあり、180スレッドくらいを立ち上げる。

途中で、停電などのアクシデントがないことを願うばかりだ。cpuは、12コア24スレッドの並列処理を3.5Gのクロックスピードで実行する。実質、切り替えをやっているので、オーバーヘッドが発生するが、実行スレッドを小さくすると、CPUの稼働率が大きく下がってしまうので、かなり無理させている。CPU温度は、どのコアについても70度を超えることがないことがわかっているので、なんとかなるだろうと思っている。何しろ30数万円もの金をかけたコンピュータだ、それくらい、働いてもらわないと困る。

xwindowが落ちる: GL error: GL_OUT_OF_MEMORY in glTexSubImage

先に作ったCore-i9 9920X の128Gメモリマシンで、1億1000万ツイートの処理という作業をやっていたら、数十分から1時間ほどするとマシンがリセットされてしまうという厄介な現象ぶち当たった。

残されたsyslogは、添付のようなものだ。gdmのメモリエラーのようだ。確かに、100を超えるスレッドを平行に動かしていて、メモリの消費量がすごいのではあるのが、そんなことでリセットされたのではたまらない。腹立たしくはある。基本的にバグだと思う。ネットで探すと、海外のサイトに同じような現象の問題が出されている。どう解決したかのかまでフォローできなかった。

gnome以外のウィンドウマネージャに変えれば、解決するかもしれないと思ったが、探すのは面倒なので、ubuntuをCUIモードで立ち上げて、gdmを使わないでやってみることにしている。ただ、スレッドを一旦止めるというのが、プログラムからできるようにしていたのが、できなくなっているが、まあ、最後までやりきるということだろうと思う。

GUIとCUIの変換は、次のコマンドで実現する。
# ubuntsモードの変更
sudo systemctl set-default multi-user.target
sudo systemctl set-default graphical.target

ログの一部
/var/log/syslog

Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) glamor0: GL error: GL_OUT_OF_MEMORY in glTexSubImage
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (WW) glamor: Failed to allocate 148x12 FBO due to GL_OUT_OF_MEM
ORY.
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (WW) glamor: Expect reduced performance.
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE)
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) Backtrace:
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 0: /usr/lib/xorg/Xorg (OsLookupColor+0x139) [0x5636db9b9459]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 1: /lib/x86_64-linux-gnu/libpthread.so.0 (funlockfile+0x50) [0x7f613c5368df]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 2: /usr/lib/xorg/modules/libglamoregl.so (glamor_get_pixmap_texture+0x7d) [0x7f6138fd355d]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 3: /usr/lib/xorg/modules/libglamoregl.so (glamor_create_gc+0x78f4) [0x7f6138fe5644]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 4: /usr/lib/xorg/modules/libglamoregl.so (glamor_create_gc+0x7caf) [0x7f6138fe5d6f]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 5: /usr/lib/xorg/modules/libglamoregl.so (glamor_create_gc+0x8668) [0x7f6138fe6888]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 6: /usr/lib/xorg/modules/libglamoregl.so (glamor_create_gc+0xa26f) [0x7f6138fea07f]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 7: /usr/lib/xorg/Xorg (DamageRegionAppend+0x6c6) [0x5636db93c996]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 8: /usr/lib/xorg/modules/libglamoregl.so (glamor_create_gc+0x1110f) [0x7f6138ff845f]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 9: /usr/lib/xorg/Xorg (AddTraps+0x423d) [0x5636db9355ed]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 10: /usr/lib/xorg/Xorg (SendErrorToClient+0x368) [0x5636db85c498]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 11: /usr/lib/xorg/Xorg (InitFonts+0x3c8) [0x5636db860478]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 12: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xe7) [0x7f613c154b97]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) 13: /usr/lib/xorg/Xorg (_start+0x2a) [0x5636db84a13a]
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE)
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) Segmentation fault at address 0x0
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE)
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: Fatal server error:
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) Caught signal 11 (Segmentation fault). Server aborting
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: Please consult the The X.Org Foundation support
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: #011 at http://wiki.x.org
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: for help.
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) Please also check the log file at "/home/washida/.local/sh
are/xorg/Xorg.0.log" for additional information.
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE)
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (II) AIGLX: Suspending AIGLX clients for VT switch
Apr 14 08:26:18 corei-9 /usr/lib/gdm3/gdm-x-session[15336]: (EE) Server terminated with error (1). Closing log file.
Apr 14 08:26:18 corei-9 systemd[1]: Starting Process error reports when automatic reporting is enabled...
Apr 14 08:26:24 corei-9 gnome-terminal-[15774]: gnome-terminal-server: Fatal IO error 11 (リソースが一時的に利用できません)
on X server :0.
Apr 14 08:26:24 corei-9 update-notifier[15673]: update-notifier: Fatal IO error 11 (リソースが一時的に利用できません) on X server :0.

インテル Core i9-9920Xのメモリ128Gバイトマシンを組み立てる(2)

3. 組み立て(その2)

前回からの続きだ。(前にも書きましたが、組み立てはあくまで自己責任でやってください。)

(9)マザーボードの取り付け
準備が終わったので、マザーボードをケースに設置する。CPUクーラーがでかいので、ケールの幅に収まるかどうかが心配だったが、なんとかなった。

マザーボードを固定するネジがどれなのか、少し迷った。が、8個あり、ぴったりのが見つかった。

(10)グラフィックボードの設置
PCIのスロットを選択し、2枚分の側面カバーを外し、グラフィックボードをはめ込む。再び、ネジで固定する。

このグラフィックボードは、追加電源などは必要としないタイプなので、これで終わりである。

(11)CPUファンの付け直し
前に書いたが、このあたりで、CPUのファイン方向とケースファンの方向がバッティングしているの気づいて、付け直した。これがとても面倒な作業になったが、なんとかそれをやり終えた。

ただ、これが本当に正しいかどうかは、いまだにわからない。なんとなく、ケースの内側にむき出しのファンがあるのが気持ち悪い。方向はこのまま、写真で、下のファンを中間に挟み込んで、今中間にあるものを上のラジエターの外側に設置する方法もあったと、この写真を見ながら思った。でも、まあ、ファンに支障がないようにすればいいのではないかと思う。

(12)配線
つけるパーツはこれで全てつけ終えて、あとは配線である。面倒だった〜〜〜。
まず、フロントパネルの電源スイッチなどの配線をやった。コネクターを間違えると、壊れてしまいそうな気がしたので、慎重に、何度も確認しながらやった。なぜ注意が必要かというと、方向が固定化されていないからだ。
他、LED配線、USB配線(Ver.2とVer.3がある)、ケースファンの配線。DVDのSATAの配線(0番のSATAにつないだ)DVDの電源、外付けオーディオの配線。そして最後に、マザーボードのメイン電源への配線やった。

(13)BIOSが立ち上がらない!!(わざと物語風にした、でも本当の話)
配線も終えたので、いよいよ、ディスプレイなどを接続して、電源スイッチを入れた。スイッチ周りの配線は無事正常だった。電源が入った。よかったと思ったら、一瞬全てのファンがちょっとだけ回って、なんか、止まってしまう。ディスプレイは真っ暗なままだ。

ええ!!想定していた一番悪い事態。何が問題なのか。冷静に考えた。まず、マザーボードとか、CPUとか、メモリの故障。別なマシンで、BIOSが立ち上がらなかった時は、メモリのはめ込み不足だった。今回は、そのあたりはきっちりとやった。故障を想定すると、やることがなくなってしまう。うろうろしながら、何かのミスであることを前提にして色々チェックした。

結局、気づいたのは、CPUへの電源、ATX12Vが繋いでなかったのだ。マザーボードのメイン電源につなげば、CPUへの電源供給は済むだろうと思っていたのだ。錯覚だった。CPUへは、自立した別系統で電源を送ることになっているのだ。電源ユニットとマザーボード上部に8ピンのEPS12Vコネクタが二つついていて、その一つのコネクタの右側4つがATX12Vのコネクタになっている。CPU電源も2系統ついていることになる。この辺り、ちょっと理解が面倒だったのだが、確かにマニュアルにはそう書いてあった。

(14)CMOSの設定
BIOSが立ち上がりました!!ただ、画面には、CMOSの設定がされていないのでこれ以上仕事はやらないよ、というようなメッセージが出ている。指定のキー(DELだった)を叩いてBIOSの設定画面が出てきた。

トップ画面に、CPUが正しく把握されていること、クロック、そして何よりもメモリが128GBちゃんと認識されている。よかったよかった。時間を設定し、システムの起動順序で、DVDが最初に来ていることを確認して一旦終了した。

あとは、Ubuntu18.04.2のイメージディスクから、インストールをした。

以上

インテル Core i9-9920Xのメモリ128Gバイトマシンを組み立てる(1)

日本語wikipediaや1億超のツイートを全文をprologの二分木化する場合、数日間あるいはそれ以上、コンピュータを動かし続けなければならない。さらに、実行時に、それらはメモリに展開すると数十Gバイトのメモリを占有する。メインに使っているMacProでもギリギリ限界まで動かす。すると、通常業務ができない。というわけで、圧倒的なパワーのPCが欲しくなった。

戦略を、インテルのCore i9-9920、12コア24スレッド、クロック3.5GのCPUと、メインメモリが128GバイトのLinuxマシンを作るということにした。相当な資金を投入しなければならず、動かなかった時のリスクを考えると冷や汗ものだが、挑戦した。実質、組み立てに半日ほどかけて、なんとかubuntu18.04.2を動かせたので、今後のために、ここに、経過をできるだけ細かく、記録しておくことにした。

以下はあくまで私がやったことで、これを読めばうまくいくということではない。読んでやって失敗してもそれはあなたの責任であることを前提に、ただ参考にしてください。

1. パーツ(価格は税込)

(1)ケース: Define R5,  Fractal Design社製, FD-CA-DEF-R5-BK(ブラック):価格 10,980円(購入先の記載がない場合は「秋葉の店舗」)
(ケースにはこだわりはない。入ればいい。ケース売り場の店員に販売の情熱を感じられなかったが、型落ちだけと、人気があり、静音のものという基準で選ぶ。最終的にPCIの穴が狭いのではないかと思うが、大きな問題はなかった)

(2)CPU:インテル Core i9-9920X:価格 150,834円(Amazon)
秋葉店舗と24,000円の差があったので、Amazonにした。多少の差ならば店舗を優先するのだけれど、この差は痛い。コア数を上げて14コアにしたり、逆に10コアにすることも考えたが、コア数だけのパフォーマンスの差を見れば、程よくというのと、MacProのコア数に揃えて、比較してみたい気もあり、このレベルにした。値段がチョー高いが、ここは仕方がない。こずかいをはたく。

(3)メモリ:CORSAIR, DDR4,  32G(16Gボードx2)x4=128G: 価格 99,272円
Amazonの方が安いと思う。64Gに抑えることも一瞬考えたが、128Gの世界観に憧れた。

(4)マザーボード:ASRock, X299, EXTREME 4: 価格 29,800円
基準は、i9が刺さるソケットであること。メモリが128G積めることだった。日本語解説もあって、分かりやすそうだったし、値段もそこそこだった。Amazonが数千円安いが店舗にした。結果的にも悪くなかった。

(5)ディスク:MZ-V7S500B, サムスン, M.2タイプ:価格 13,870円
SATAのディスクは使わず、マザーボードに直接はめ込むM.2タイプのSSDにした。容量は大していらない500Gもあれば十分だった。SATAのSSDにするよりも、スピードアップになるだろうと思った。はめ込みも楽だった。

(6)CPUクーラー:Noctua サイレント タワーヒートシンク [NH-D15]:価格 11,999円(Amazon)
店舗と大して差はなかったが、Amazonにした。MacProでも、大規模な自然言語処理をするとCPUが悲鳴をあげて、1個しかないファンがブンブン唸る。i9だと、きちんと冷却しないと面倒臭いことになるのはわかっているので、手を抜けなかった。ソケットの相性などで選んだ。比べてないので、他はよくわからないが、本当は、もっと下調べをすべきだったかもしれないと思う。

(7)電源:Seasonic Prime Ultra 650W Titanium:価格 25,980円
十分なパワーを供給し得る最上位機種。秋葉の売り場の店員が親切で、相談してこれにした。

(8)グラフィックボード:Gforce GTX 1050 2GB : 価格 11,980円
ゲーム用ではないので、特にこだわりはなかった。ただ、CUDAでGPUプログラミングはする可能性があるので、それができるものと思ったが、多分できるだろうと思う。

(9)DVDドライブ:DVR-S21WBK, パイオニア:価格 2,680円
ブルーレイは必要ないので、安かった。単なるDVDライター。もちろん読み込みもできる。店員さんが、パイオニアを勧めたので、そのまま購入した。

総額:356,945円になった。あらためて、チョー高い買い物だが、コンピュータと付き合い始めて40年以上の歳月が過ぎて、かつては想像できないくらいの、自分が手にした最高スペックのコンピュータだから仕方がない。

2.組み立て(その1)

組み立ての順番はとても大事だな。

(1)最初にしたことは、ケースにDVDを組み込むことだった。前から差し込んで、側面のネジを4箇所止めればOKだった。SATAのコードはまだまだ後だ。

(2)電源ユニットの設置

電源ユニットの設置では、電源のクーラファンをケースの内側に向けて設置することが求められていた。

(3)マザーボードにCPUを取り付ける。

マザーボード側のバネを外してケースを跳ね上げ、CPUを置く。向きが重要なので、切れ込みや矢印を参考に正しく置く。再びバネで押さえたあと、マザーボードにくっついていたケースを外す。CPUクーラーを置かなければならないので不要だ。

(4)CPUを置く台をCPUの周りにセットする。NH-15の場合、向きが大事である。メモリや他のマザーボードの要素と軋轢を起こさないようにしなければならない。私の場合は、くらーの風が前後に流れるような方向でセットした。

(5)CPUクーラー本体は巨大なので、それを置くと、CPUの両側にあるメモリが取り付けられなくなるので、先にメモリを取り付ける。

メモリは、先にフォルダの爪を開いておいて、前後を確認しながらゆっくりと差し込む。爪は開き過ぎたら壊れる!(壊した経験が過去にあるので)間違いなく入ったら、少し強めに押して爪がぱちっと自動で戻るまで押し込む。1枚16Gで8スロットに全部差し込む必要がある。(128G以下の場合は、差し込む位置が決まっているので、マニュアルをよく読んでその通りにセットすること)

(6)CPUクーラーをセットする。CPUの上にグリスを塗るが、マニュアルによれば直径4〜5mmになるくらいの量を中央に垂らしておくということだ。大きすぎると、冷却効率が悪くなると書いてあった。こういう、曖昧さがとても面倒臭い。

クーラーは、箱から取り出すと、一旦、ファンを全て外す。ファンは二つついているが、マニュアルによれば1個の場合もあるとして、2個の方がいいよ、と書いてある。CPUの台の2箇所のネジに、止めたあと、ファンを取り付ける。ファンに取り付けてあるバネのようなものでシンクにはめ込むのだが実に面倒だ。この写真では左から右に風が流れるようにつけたが、ケースファンと風が逆方向になるので、最終局面で、方向を付け直したという、厄介な事件があった。何しろ、でっかいクーラーなのだ。

(7)CPUファンの電源コードの接続
この時点で、コードをマザーボードにつなげて良いと思う。マザーボードのマニュアルを見て、コネクタの位置を確認して接続する。この場合は、上部右側にあった。ファンが二つついているので、2箇所に繋ぐ必要がある。逆に、2箇所のコネクタがマザーボードになければならない。

(8)マザーボードの取り付け準備
マザーボードを取り付ける前に、リアパネルのカバーをケースに設置しなければならない。

マザーボードに、グラフィックボードがないので、少しシンプル。今時、PS2の穴があることが不思議だ。このパネルは、ケースの穴に、パチン、と嵌め込まなければならない。そのための小さな突起がパネル版の側面にいくつかついている。
もう一つの準備は、ケースに取り付けるためのオスメス一体化したネジを8個つけることである。つけるときに、手で回してもはめ込みにくい。ラジオペンチで回そうとしたがとても面倒。すると、それを簡単にする小さな道具がついていた。

この白いものをネジにかぶせると、あとはドライバで回すと押し込めるのだ。超便利。考えてあるね。

(9)準備その2
M.2のSSDドライブをマザーボードに取り付けるのも、この段階だ。

このマザーボードの場合、2つのM.2ソケットがついている。ちょっと大きさが違うみたいだ。さしあたっては、一つしか使わないので、後で使いにくい、CPUに近い側のソケットに差し込んだ。真横から差し込み、最後は左端のネジで固定する。小さなネジが3個、マザーボードについている。3個目は、WIFI用だ。

写真が多くなって重くなるので、これ以降は次の記事にする。

ツイッターの二分木化で、絵文字問題

集めた1億1千万のツイートを二分木化している。ただ、wikipediaと違って、およそ、どこまでが日本語なのかが曖昧で、記号がやたら繰り返されていたり、何よりも膨大な絵文字がはめ込まれている。jumanやknpの自然言語処理でどう扱われるかも、問題だ。

事前に加工して、絵文字などを取り除いたほうがいいかとか、色々迷ったが、まず、やってみようとやったら、特にエラーもなく処理している。検索結果でも、次のようにそれらしく処理できる形だ。

line_436_0: 毎日/1回/ご応募可能ですのでまたのチャレンジをお待ちしてます/☺️❣️//
line_449_0: 新入生の皆さん🌸入学/おめでとうございます/🌸〇〇大学野球サークル/〇〇🐝です野球をするのはもちろん/楽しくて/たまらない/イベント

(〇〇は、元は固有名詞)

このままでいいような気がする。

およそ、元の文章はなるべくいじらないほうがいい。それはつまり、応用が効くということだ。

こう考えると、会社や組織で、膨大な文章を抱えているところで、このprolog二分木は、結構使えるのではないかと思ったりしている。

一体、1億1千万ツイートとで、どれだけコンピュータのリソースを使うか。どれだけ、素早く、シンプルに目的の文章にたどり着くか、調べてみようと思う。

prolog 二分木作成の改良

wikipedia二分木検索例の出力の冒頭文がおかしい。つまりこんな風になっている。

wiki_1_line_3385_2: ロボットは/いわゆる脳を持た関わらないにもずまるで/生きているかのように行動する//

「持たないにも関わらず」が「持た関わらないにもず」になっている。この原因は、この行の二分木が、

jawiki(wiki_1_line_3385_0,
    node(の,
        node([],
            node(と,
                node([],
                    node(に,
                        これ,
                        [基づいた, 基づく]
                    ),
                    ゲンギス
                ),
                [[呼ば, 呼ぶ], れる]
            ),
            [[[六, 数量], 本], [足, '動物-部位']]
        ),
        node(は,
            [ロボット, '人工物-その他'],
            node(を,
                node(いわゆる,
                    [],
                    [脳, '動物-部位']
                ),
                node('にもず',
                    [[[持た, 持つ], ない], [関わら, 関わる]],
                    node('か|の',
                        node([],
                            まるで,
                            [[生きて, 生きる], いる]
                        ),
                        node(に,
                            よう,
                            node([],
                                [[行動, 抽象物], する],
                                [ ]
                            )
                        )
                    )
                )
            )
        )
    )
).

という感じで、nodeの語が「にもず」になっているからだ。その理由は、knpの出力にまで遡る。その該当箇所のknpの出力は、

* 12D <否定表現><モ><ニ><読点><助詞><〜ない><〜ぬ><用言:動><係:連用><レベル:B><区切:3-5><ID:〜にもかかわらず><連用要素><連用節><動態述語><正規化代表表記:持つ/もつ><主辞代表表記:持つ/もつ>
+ 13D <否定表現><モ><ニ><読点><助詞><〜ない><〜ぬ><用言:動><係:連用><レベル:B><区切:3-5><ID:〜にもかかわらず><連用要素><連用節><動態述語><正規化代表表記:持つ/もつ><用言代表表記:持つ/もつ><時制-未来><格関係8:ヲ:脳><格解析結果:持つ/もつ:動3:ガ/U/-/-/-/-;ヲ/C/脳/8/0/1;ニ/U/-/-/-/-;デ/U/-/-/-/-;ヨリ/U/-/-/-/-;マデ/U/-/-/-/-;時間/U/-/-/-/-;外の関係/U/-/-/-/-;ノ/U/-/-/-/-;修飾/U/-/-/-/-;トスル/U/-/-/-/-;ニオク/U/-/-/-/-;ニツク/U/-/-/-/-;ニカンスル/U/-/-/-/->
持た もた 持つ 動詞 2 * 0 子音動詞タ行 6 未然形 3 "代表表記:持つ/もつ" <代表表記:持つ/もつ><正規化代表表記:持つ/もつ><かな漢字><活用語><自立><内容語><タグ単位始><文節始><文節主辞>
ない ない ない 接尾辞 14 形容詞性述語接尾辞 5 イ形容詞アウオ段 18 基本形 2 "代表表記:ない/ない" <代表表記:ない/ない><正規化代表表記:ない/ない><かな漢字><ひらがな><活用語><否定><付属>
に に に 助詞 9 格助詞 1 * 0 * 0 NIL <かな漢字><ひらがな><付属>
も も も 助詞 9 副助詞 2 * 0 * 0 NIL <かな漢字><ひらがな><付属>
関わら かかわら 関わる 動詞 2 * 0 子音動詞ラ行 10 未然形 3 "代表表記:係わる/かかわる" <代表表記:係わる/かかわる><正規化代表表記:係わる/かかわる><かな漢字><活用語><付属>
ず ず ぬ 助動詞 5 * 0 助動詞ぬ型 27 基本連用形 4 NIL <かな漢字><ひらがな><活用語><付属>

となっている。情報がいっぱい詰まっているが、基本*から始まるのが、一つのフレーズなのだが、ここでは、「持た」という動詞があり、「ないにも」という助詞系の語が続いて、さらに「関わら」という動詞が来て、さらに「ず」という助動詞が来ている。二つのフレーズにして良いものが、一つのフレーズの中に押し込められているのだ。助詞、助動詞はnodeにするというのが、この二分木の原則なので、「ないにも」と「ず」がつなげられてしまうのだ。

「持た」→「ないにも」→「関わら」→「ず」、となっているが、第1と第3の要素はleafになるべきで、第2と第4の要素はnodeになるべき要素なのだが、これらが一つのフレーズなので、leaf要素とnode要素が、それぞれ接合されてしまっているというわけだ。

そこで、面倒だったが、こういう場合には、二つのフレーズに分割するように、二分木を作成するプログラムを改良した。結果、次のように出力するようになった。

jawiki(wiki_1_line_3385_0,
    node(の,
        node([],
            node(と,
                node([],
                    node(に,
                        これ,
                        [基づいた, 基づく]
                    ),
                    ゲンギス
                ),
                [[呼ば, 呼ぶ], れる]
            ),
            [[[六, 数量], 本], [足, '動物-部位']]
        ),
        node(は,
            [ロボット, '人工物-その他'],
            node(を,
                node(いわゆる,
                    [],
                    [脳, '動物-部位']
                ),
                node(にも,
                    [[持た, 持つ], ない],
                    node(かの,
                        node([],
                            node(ず,
                                [関わら, 関わる],
                                まるで
                            ),
                            [[生きて, 生きる], いる]
                        ),
                        node(に,
                            よう,
                            node([],
                                [[行動, 抽象物], する],
                                [ ]
                            )
                        )
                    )
                )
            )
        )
    )
).

少しわかりにくいかもしれないが、「にも」と「ず」が二分木の中で分かれている。これでよし。

Prolog 二分木をWebから利用可能にした

日本語Wikipediaの全本文をWebから利用できるようにした。

Prolog 二分木検索の使い方

Javascript経由でブラウザから、データを受け取り、phpで、prologサーバーにアクセスし、prologサーバーがwikipediaの二分木データにアクセスし、回答すると言う手順になっている。

prologサーバーがメモリ上に展開し、wikipediaの二分木を咥え込むと、26Gバイトくらいになるので、VPSでは対応できないので、このサーバーだけ、自宅のPCにおいて、そこにアクセスするようになっている。自宅PCは、メモリを64G積んでいるので、なんとか対応できる。大学のPCも16Gなので、メモリエラーになってしまうのだ。

だから、自宅PCでサーバーを動かしている時しか検索できない。問い合わせいただければ、動かす時間をお知らせすることができる。

これで、prologでやろうとしたことの1クールが終わったことになる。

次は、twitterデータを使って、話し言葉でこれに対応してみたい。そして、もっと人間の言葉、日本語の言葉の知能的処理に挑戦したいと思っている。

CentoOSのVPSにswi-prologをインストールした

手続き的に言うと、この間、日本語wikipediaのデータをprologの二分木化して、それをprologサーバに処理させて、tcpクライアントからデータ検索できるようにすると言う作業をやっていた。なんのことやら、と思う方がいるかと思うが、こればっかりは、話が長くなるので、このサイトの過去の記事を読んでいただかないといけない。

さて、その7Gもある二分木もそれを検索するprologプログラムも、それを利用可能にするprologのtcpサーバーもできた。直にそれをtcpクライアントから利用してもいいのだが、何かと不便なのでウェッブで使えるようにした。

つまり、ブラウザから、javascriptのajax経由で、サーバーサイトのphpを起動して、tcpクライアントを動かして、検索し、その出力をブラウザに表示すると言うシステムはできたのだ。Macのwebサーバーとprologサーバーでこれが機能することを確かめた。Macはローカルなので、これをこのブログも動かしている「お名前.com」のVPS上において、どこからでも利用できるようにしようと言う段取りになった。

VPSは、なぜかCentoOSで動いている。今は、Ubuntuにすればよかったと思うが、入れ替えると、また色々1から作り直さないけない。一時期、私が管理するネットワークサーバーは、CentoOSと決めていたことがあって、その勢いでのこと。まあ、仕方がない。

このVPSにswi-prologを入れようとしてちょっと詰まってしまった。Linuxなので、ソースからコンパイルする必要がある。まず、cmakeのバージョンが古いと怒られた。cmake 新しくしようとすると、g++のバージョンが古いと怒られた。 g++のバージョンアップは、こちらのサイトを参考にインストールできた。さしあたって、

gcc version 4.8.2 20140120 (Red Hat 4.8.2-15) (GCC) 

ここまで、バージョンアップした(もっと新しいバージョンもあるが、そこまでは必要なかった)。さらに、この辺りかそこらで、zlibが見つからないと言うエラーもあったので、これは、こちらを参考に、簡単に最新バージョンをインストールできた。そして、cmakeを新たにコンパイルし直した。cmakeは、

cmake version 3.14.1

ここまで、バージョンアップした。さらに、swi-prologのインストールページにある、事前準備をしようとしたら(※ dnfをyumに変える必要があった)

エラー:  Multilib version problems found. ・・・・・・続く

と言うことで止まってしまった。経験的に、これがちゃんとインストールできていないと、swi-prologのコンパイルに失敗する。これはやや戸惑ったが、こちらにある通り対処したら、クリアできた。

このような過程を経て、無事、swi-prologはちょっと古びたCentOSにインストールできましたとさ。

(追記:結局VPSはメモリとパワー不足でprologサーバーを動かすことができなかった、笑)

コニュニケーションへの衝動としての笑い

コンピュータないしはロボット(単にAIとよぼう)は、人に対するコミュニケーション衝動のようなものを持たなければならないと、何回か書いてきた。人に伝えたいことがあってこそ、それをどのように伝えるのかが問題になるのだ。AIは、衝動に基づいて、言葉を選ぶ、構成する。言葉を編集する。外的な刺激に対して、独自の、創造的な衝動を構成する。それをなんとか言語的に相手に伝えようとするわけだ。

衝動は、AIの側に、それを必要とする内的な環境・状態・理由があるから形成される。それをまた明確にしていくことはとても高度の情報処理、知能的活動などが必要になる。

しかし、「笑い」あるいは「人を笑わせる」というのは、極めて単純な動機、衝動となりうる。単純というのは、簡単という意味ではない。明確という意味に近い。

人としての相手を笑わせるためのコミュニケーションである。どのような言葉を選び、どのように言葉を構成し、どのように編集し、どのように文章をつなげれば、人を笑わせることができるのか。これがとてもわかりやすい衝動なのだ。

そういう衝動をAIの側に持たせることは不可能ではないだろう。可能性はある。その衝動から、言葉を創造するのだ。