博士課程での研究やソフトウェア開発の話とかを,思いついた時につらつらと書いています


Software::JINKOU-MUNOU - MIU開発(4)


とりあえず配列をバイナリに落としたり,読み込んだりするモジュールはかけました.
書き込める値が数値しか無理なんですが,
今後の拡張性も考慮してるので,いろんなクラスを設計して,継承させて,という状況になってます.

次は書き込める値を文字列にしたり複雑なデータ構造にも対応させていくのが目標ですね.
文字列を要素とする配列の読み書きへの拡張は一瞬で終わりそうな気がします.
pack, unpackのテンプレートを変えたクラス作ればいいので.
C++のテンプレートみたいに,パラメータとして型を与えれば
数値の配列の読み書きをするクラス,文字列の配列の読み書きをするクラスになる
っていう設計にしていきたいですね.

で,最終的に複雑なデータ構造でもバイナリに落としたり読み出したりできるようにする.
MIUのシナリオデータに最適化されたバイナリへシナリオを落とす,と.
結局標準モジュールで実現できる話やん!で終わらないようにしたいと思います.

Labels: ,

0 comments:

Post a comment


Software::JINKOU-MUNOU - MIU開発(3)


次は会話データのバイナリファイル構造だと思って,今日はそのファイルのレイアウトを考えていました.
インデックス領域とデータ領域にわけて,でインデックス領域にはこの情報とこの情報を書き込んで,
型はこいつはlongでこいつはshortで・・・と考えていたのですが.
あれ,これってなんか汎用性のある設計にできるんじゃね?とか思って
頭の中がジェネリックプログラマー化する私.
上のは完全に造語ですけど,ようはTemplate使ったジェネリックプログラミングをしたがる気分になったってことで.
だもんで設計するのは基底クラス.
どういうメソッドがあって,どういうクラスがあればいろいろと使いまわせるのか,というのを考え始めます.
言語がPerlでCPANモジュールを使わないという制限のもとですから,
標準以外のモジュールを使わずに実現できる方法を考えないといけません.

設計しているのはバイナリファイルをある一定のルールで読み書きする抽象クラス.
細かな処理はサブクラスに任せる.
なーんかDBMでも作ってる?とかいう気分になってきました.
DBMの詳細な設計なんて,専門外なので詳しくは知りませんが.
すばやく,コンパクトに,という点を念頭に置くのは共通しているんじゃないでしょうか.

考えているのが,基本的にインデックス領域とデータ領域の二種類の領域を読み書きできるクラス.
しかしMIUの場合,書き込みが完了したファイルに追加書き込みなんてしなくてもいいので,
書き込み専用,読み込み専用のクラスがあればいいのです.
ファイルを作るのはクライアント(ローカル)マシン,読み込むのはWebサーバマシンなので.
で,インデックスとデータ領域だけだったら,いわば1次元の配列,ハッシュでしかない.
n次元配列や,ハッシュを返すハッシュ,複数のメンバを持つ構造体みたいなのを
バイナリへ落としたいとかなると,インデックスとデータ領域,という考えじゃだめでして.
あ,Data::DumperやStorableを使えばいいじゃんとかいうのは無し.
必要なキーがそろっていれば,最小限のメモリ消費かつ最速で目的のデータにアクセスできなきゃいけない
という制約がある場合,一通りの(シリアライズ済み)データを読み込んでしまう上記のモジュールはちょっと,ね.
SDBMとかでしたらなんかオーバーヘッドでかそう.
一レコードの容量も確か制限があったような.

ということで,データ領域も,インデックス領域として置き換えることができれば,
複雑なデータ構造も保存できるんじゃないかと.
ん?となると結局木構造やん,汎用的な,ということになり.
先日書いたモジュールも,今書こうとしているモジュールで書き直せそうです.
一番最初に書いた,配列をバイナリに落とすモジュールも書き直せるかも.
配列やら何やらをバイナリに落とすモジュールがあるけども,
元をたどれば一つの基底クラスですよ,と.
なんかいいですねー.

そういう設計部分でうほうほしてしまっている私.
目標はMIU開発やっちゅーのにベクトルがずれてる気が.

Labels: ,

0 comments:

Post a comment


Software::JINKOU-MUNOU - MIU開発(2)


今日は木構造をバイナリへ落とす処理を書いていました.
前回シリアライズ処理を書くとか書いてましたが,
よくよく考えてみたらシリアライズじゃないですね.
いや,デシリアライズできなくはないですがそんなん書きません.
やりたいことは,木構造や配列をバイナリへ落とし,任意のインデックスへ高速にアクセスできる,というもの.
それでいてバイナリサイズはコンパクト,っていう.

コンパクトにすることを念頭においていたのですが,
木構造のバイナリ化の際に,ノード数の許容量を2の16乗 - 1個にしてしまいました.

してしまいました,というのは,この木構造の利用目的.
MINAなどでいうトピックの扱いなのです.
MINAのトピックは,別にスーパーセット,サブセットという関係はなかったんですが,
MIUでは木構造であらわすので,上位トピックから会話文を適当に選んで!とか命令してやれば,
下位トピックも含めて会話文を検索します.
今回実装している木構造のバイナリ化はトピックツリー保存のためのものです.
で,トピックの種類が2の16乗 - 1個存在するかというと・・・
まぁ単純に考えてそんなにいくはずはなく.
もうちょい縮めると,2の8乗 - 1個で,255個トピックを作れるという仕様にすることも可能です.
255っていう数字は,普通にトピックつくっていけば別に全然あまるくらいの容量だとは思うんですよね.
ただ,何かしらへんな使い方を思いついた場合,このぎりぎり感は怖いものがありまして.
そこでもうちょい広い領域を,と考えれば2の16乗-1個なので65535個ですね.
そんなにトピック作るかい!とか思ってしまいます.l

トピック数の上限を255個にしてしまえば,このトピックツリー領域をもっと縮められるんですが,
まぁ数バイト単位の話なんで,別に無理して縮めなくてもいいかとか思いました.

明日は昨日作成した配列のバイナリ化モジュールを拡張して,会話文の保存処理のバイナリ化です.
MIUの発話文とユーザの発言選択肢というデータ構造になってますので,
配列バイナリ化モジュールの拡張を行うだけで簡単に済みそうです.

それが終われば,xmlファイルからバイナリへの変換処理ですね.
今xmlから内部表現に落とし込んだデータの形式で,バイナリ化のテストしてますから.
xmlから内部表現への変換処理を書いて,バイナリ化までの処理を完成させる.

そこまでできれば,MIUの会話処理に入っていけます.

Labels: ,

0 comments:

Post a comment


Software::JINKOU-MUNOU - MIU開発(1)


パトリンさんとこでMINAエンジンの人工無能さんと戯れたのがきっかけで,
ちょっと新しい人工無能を作るモチベーションが出てきました

土曜日にさくっと作ろうとか思っていたのですが,
システム全体図をまず練って,ここはこういう技術使おうとか考えて.
さくっと作れるようなもんじゃなくなりました(笑
まず設置場所が公共のサーバとなると次のような制約をもとで開発しなければいけません.

  • PerlのCPANやPPMでインストールできるようなモジュール,
    つまり標準モジュール以外のモジュールを利用するのは避けないといけない.
  • サーバリソースを食いまくるような処理は避けないといけない.
    たとえば以下のような処理.
    • 形態素解析を利用する
    • サーバ上で初めて辞書などを解析する,つまり前処理をまったくローカルで行わない 
辞書の問題はMINAのころから凄い気になっていて,
辞書4など文字列置換用辞書なんかもうちょい前もってどないか処理できないか,
と考えたこともありました.
ただ,入力としてユーザの発言を受け取り,
しかもその発言内容をMINAの発言内容として利用できるような仕様にしていたため,
MINAの発言は静的に決定できるものでもありませんでした.
ま,それでもある程度は辞書に対して前処理をある程度ほどこせたような気もします.


今回開発する人工無能,というか今までの人工無能とずいぶん違う気がするので
その名称は使わず,ロボットチャットでいいかなぁと思っています.
で,今回のロボットチャットMIUさん(漢字表記だと美羽.
MIUを漢字変換したらこれしか出てこなかったから美羽という安直な由来です).
辞書改めシナリオデータをバイナリに変換しちゃいます.
で,そのバイナリをサーバ上に設置したMIUサーバが読み取り,
クライアントプログラムであるブラウザとAjaxによる非同期通信で会話を進めていきます.

一個一個詳細を書きますと,
  • なぜ辞書じゃなくてシナリオデータとかいう呼称になっているのか
    • 会話の主導権をMIUに渡すとなると,MIU側である程度話の流れを作ることができるし作らないといけない.MINAなど辞書型でも過去発言検索機能により話の流れを作ることができたが,ユーザの自由な発言によりいくらでもその流れは壊すことはできた.MIUではユーザができる発言の自由度は限定されるので,MIUでは辞書というよりもシナリオを作っていく作業になる.
  • なぜバイナリに変換するのか
    • 上述した前処理の話と関連するが,シナリオデータになにがしかの前処理を加えてサーバ上でシナリオデータを読み込み,会話文を返すためにはメモリ節約の面からみてバイナリへの変換が有効.数値データを文字列として保存しておくのは阿呆.
    • またシナリオデータはxml形式にするが,xmlのパースのためには別途パースに必要なモジュールが必要であり,またパースする処理をサーバで行う必要がある.別途モジュールをサーバへインストールする必要がなく,かつサーバ上で最小限の処理でシナリオデータを読み込めるようにするためには,プログラムが解釈しやすい形へシナリオデータを変換する必要がある.
    • メモリ節約,プログラムが解釈しやすいフォーマットという面から,シナリオデータをバイナリへの変換することを選んだ
  • なぜAjaxなのか
    • 非同期通信+イベント・タイマー処理により,MINAよりも表現の幅が広がる.リッチインターフェースの実現や,ページ遷移がない円滑な会話処理などの実現が考えられる.またMIUがあたかもリアルタイムに考え,メッセージを入力しているという演出が可能になる.
という考えの下,MIUの構成を練っていました.
今日は,とりあえずIO部分ができないとテストしずらい!ってことで
Perlの配列をバイナリに落とす,つまりシリアライズ処理を書いていました.
シリアライズするんだったらSotrableや,データベースであるSDBMとかGDBM,DB_File使えよって話なんですが,
シナリオデータ読み取りの効率性を考えると,
独自フォーマットのシリアライズを実装したほうがいいんですよね.
やりたい処理というのが,StorableやDB_Fileとかじゃいまひとつ達成できないのです.
MLDBMなら達成できるんだけどなーと思ったりもしますが.
MLDBMにしちゃうとローカルで前処理,というのが実現しにくくなります.
確かDB_Fileとか,データベースファイルのバージョン互換性がなくて,
ローカルで作ったデータベースファイルがサーバ側では読めない,というケースがありえる.
ちなみに大学の実験ではMLDBM使ってます.
便利ですよねーあれ.

で,今日はとりあえずpack, unpack使って配列データをバイナリに落とし込んだり読み込んだりする処理を書いてました.
シリアライズ対象となるデータ構造が,配列と木構造,あとは構造体かなぁ.
構造体といっても,スカラーや配列をメンバに持つようなデータ構造です.
配列ができてしまえばちゃちゃっと作れちゃいそうな感はあります.

自前シリアライズを使う理由は,MLDBMとかじゃちょっと使うのに気が引ける,という理由以外にもあります.
仕様さえ決めておけば,他の言語でもシリアライズ可能だからです.
今回開発するMIUは,別にPerlをローカルマシンにインストールしなくてもよいかもしれないのです.
MINAは辞書のテストを行うためにローカルにPerlをインストールしなければなりませんでした.
このテストは,ほとんど辞書の書き方があっているかどうか,を確認するためのものです.
まぁ,学習データを作る,という目的でローカル上で走らせる,ということもあるでしょうけど.

MIUの場合,シナリオデータをバイナリへ変換する過程を踏みますから,
そこで文法チェックができます.
ま,xmlファイルをパースするってのが文法チェックということになるんですが,
そのほかデータがでかすぎだとかそのIDの振り方は変だとかいうチェックもできます.
ちなみにデータサイズの制限もあるんですよね,バイナリ変換すると.
走らせるマシンが,まぁ今はほとんど32ビットマシンです.
long型へpackしてもビット長は32ビットです.
どこにシナリオ文字列があるのかという,つまり文字列の位置を指し示すアドレスをlong値で保存するんで,
シナリオ文字列合計の上限が4GB(packできるlong値はなんか知りませんけど4byteなんで,
2の32乗byteが上限)になってしまうとかあります.
テキストデータで4G超えはなかなかないと思うんで,その制限はあってないようなもんだと思いますけど.

他の言語でもシリアライズ(つまりバイナリ変換)が可能と書きましたが,
つまるところ他の言語でのシリアライズを想定しています.
きっと誰かが他の言語でシリアライズしたがるだろうとかそんな理由じゃないです.
理由として,
  • Perlをローカルマシンにインストールしなくてもよいようにしたい
  • バイナリ変換プログラムをウインドウアプリケーションにしたい
    • Perl/Tkとかじゃなしに,たとえばC#とかでウインドウアプリケーションを書きたい
というところです.
バイナリ変換する手前のフォーマットがxmlである時点で,
手作業でシナリオデータ作成->xmlへのなにがしかの変換処理->xml->バイナリ
を考えていました.
xmlを簡単に作成するつったら,.NETでxmlへのシリアライズライブラリがありますよね.
人手でシナリオデータを作成するとき,そのシナリオデータの仕様をどうするのか,
エディタを自前で作る必要があるのかという話になりますが,とりあえずそこは深く練らず.
人手によるシナリオデータからバイナリファイルまでのパスができあがったので,
とかくxmlをバイナリへおとす処理を書けば簡単なテストはできるし,開発着手してっても大丈夫かなと思い,
今日は配列シリアライズプログラムを書いていました.

操作する対象が配列なんで,ついでにTIEARRAY使って
バイナリファイル読み込んでいる雰囲気を隠蔽してみました.
隠蔽すれば,いろんなアルゴリズム,サブルーチンへ応用できますしね.
たとえば,
fetch($index)
とかやって要素を取得するとかよりも,配列のようにアクセスできればforeach文も使えます.

なんだかさくっと,というレベルの話じゃないんですが,
夢のような話をしているわけでもなく,
毎晩帰宅後に開発していけば大丈夫そうなレベルです.

Ajaxを使ったインターフェース開発や,テスト用のシナリオデータ作成とか,
可能ならシナリオエディタ,そのほかなにがしかのエディタ向けシナリオ作成プラグインとか
作らないといけないんですが.
とりあえず明日は木構造シリアライズモジュール作成ですね.

Labels: ,

0 comments:

Post a comment

About me

  • I'm mikken
  • From Japan
  • 学生の頃は博士課程で感性情報処理の研究をやっていました。今はベンチャー企業でWeb系システム、看護管理系システムを開発しているSEやってます。
  • My profile

Twitter

Last posts

Archives

Links


ATOM 0.3