TTSneoという日本語プログラミング言語があります。2004年前後にかなり張り切って書いていたのですが,しばらく疎遠になっていました。故に,その後継とも言えるプロデルはついぞ今日まで触ったことがありませんでした。今回ふと思い立って,プロデルを使ってみることにしました。
プロデルとは
プロデルは,TTSneoの作者でもあるゆうと氏が開発している日本語プログラミング言語です。
文法の特徴
なるべく自然な日本語になるように設計されています。実際には,上手にクラスやメソッドを定義する言語能力が必要です。日本語は英語と異なり語順で格が決まらない言語です。従って,引数の順番を覚えなくても良いなどのメリットがあります。これは極端な例ですが,JavaScript等のjoin()とPythonのjoin()を混同するようなこともありません。プロデルでは
配列を「,」で繋げる
あるいは,
「,」で配列を繋げる
と書けます。
尤も,「繋げる」が配列に属すのか文字列に属すのかはこの文からは分からなくなります。
ところで,英語プログラミング言語というのは聞いたことがありません。主流の言語は,英単語を使っていますが,英語っぽくはありません。特に,大きいものから順に書いていくのは英語っぽくないと思っています(プロパティ of オブジェクトのような書き方の方が自然)。
Join the array with ' '.
などと書けば動くプログラミング言語があると嬉しくなります(嬉しいかどうかと自然言語っぽいかどうかは別)。
概観
Visual C#.NETで開発されている言語ですので,.NET用の中間コードにコンパイルできます。インタプリタもあります。Visual Basic 6.0よろしくフォームデザイナがついており,Windowsアプリケーションを作るのに向いていると思います。Office連携やWWWサーバなどもできます。
プロデルは,初心者向け言語ではありません。ドキュメントの整備が進んでいないので(故にこのアドベントカレンダーの意義は高い),懇切丁寧なチュートリアルのあったTTSneoと比べると参入障壁は大きいと言えます。しかし,他の言語を経験していれば,特にこれといって悩むことはないと感じました。
動作環境
.NETなので,基本的にはMicrosoft Windowsで動作しますが,マッキントッシュ用のOSやLinuxでも動作するようです。
使ってみる
とりあえず何か書いてみたいと思います。ちょうど手元に,日本語版Wikipediaから作られたtext8で学習したSkip-gramモデルがありましたので,これを読み込んでみたいと思います。
今回,データのファイル名は,ja.text8.dim300.w2.txt
です。word2vecを使って,ウィンドウサイズ2,次元数300で学習させたものです。
生データは,「ja.text8.dim300.w2.txt」から読み込んだものの行区切り。
メタデータは,生データ(1)を「 」で分割したもの。
【ベクトル:辞書】
2からメタデータ(1)まで【カウンタ】にカウントして繰り返す
行は,生データ(カウンタ)を「 」で分割したもの。
ベクトル(「[行(1)]」)は,行の2番目からメタデータ(2)個切り出したもの。
繰り返し終わり
最大値は,{-1,「」}。
ベクトルの見出しを【単語】へそれぞれ繰り返す
もし単語が「_こんにちは」でないなら
現在値は,ベクトル(「こんにちは」)とベクトル(単語)でコサイン距離を計算したもの。
もし現在値が最大値(1)より大きいなら
最大値は,{現在値,単語}。
もし終わり
もし終わり
繰り返し終わり
最大値を表示。
[ベクトルA:配列]と[ベクトルB:配列]でコサイン距離を計算する手順
もし ベクトルAの個数が,ベクトルBの個数でないなら
「大きさの違うベクトルです」というエラーを発生させる。
もし終わり
【コサイン】は,0.0。
【大きさ:配列】
大きさは,{0.0,0.0}。
ベクトルAの個数回【カウンタ】にカウントして繰り返す
大きさ(1)は,大きさ(1)+ベクトルA(カウンタ)^2。
大きさ(2)は,大きさ(2)+ベクトルB(カウンタ)^2。
コサインは,コサイン+ベクトルA(カウンタ)×ベクトルB(カウンタ)。
繰り返し終わり
もし大きさ(1)×大きさ(2)が0なら
0を返す。
もし終わり
コサイン÷((大きさ(1)×大きさ(2))の平方根)を返す。
終わり
[文字列:文字列]を[区切り文字:文字列]で分割する手順:配列
【配列】は,{}。
【現在位置】は,1。
【次の位置】。
繰り返す
次の位置は,文字列の現在位置文字目から区切り文字を探したもの。
もし次の位置が0なら
文字列の現在位置文字目以降を配列に加える。
繰り返しから抜ける
でないなら
文字列の現在位置文字目から次の位置-現在位置文字,取り出したものを配列に加える。
現在位置は,次の位置+1。
もし終わり
もし現在位置が文字列の文字数より大きいなら,
繰り返しから抜ける
もし終わり
繰り返し終わり
配列を返す。
終わり
「こんにちは」と最もコサイン距離の近い単語を出力しています。
結果は以下のようになりました。
{0.738469664846242,_春夏秋冬}
「こんにちは」に近いのは「春夏秋冬」です。納得の結果ですね。
プロデルデザイナ上で実行するとかなり時間がかかりますので,コンパイルして実行しました。
簡単な解説
日本語で書かれているので,大抵のことはソースコードを読めば分かってしまうものと思われます。そこで,プロデル独特の表現を用いている部分のみ説明します。
まず,【 】
ですが,これは変数の宣言です。
手順というのは,perlでいうところのサブルーチン,Visual Basicでいうところのサブプロシージャに相当するものです。関数の引数は,助詞と型によって同定されます。戻り値を使う場合は,~したもの
という表現を用います。
一つ目の手順は,コサイン類似度を計算するものです。二つ目の手順は,いわゆるsplitです。プロデルにはjoin相当の手順はありますが,split相当の手順がない(配列化という手順はありますが……)ので,実装しました。