Hatena::ブログ(Diary)

駄文生産所 このページをアンテナに追加 RSSフィード

2011-06-03

マルコフ辞書で文章生成

Igoという形態素解析器をつかって圧縮新聞っぽいものを作ってみる 面白げだったんでやってみた。

で、Amazon中古ゴッツい値段が付けられているが、こちら数年前に500円で確保して放置な本を引っ張り出して、概ねその通りに書いて、ガワを付けた。

サンプル画像は、カオスな文章を学習させた結果、やっぱりカオスな文章ができていて、オリジナルの文章から変わっているのかよく分からないものになってしまっているが、一応ちゃんと生成されている。

こういうのには、新聞などの硬い文章のほうが前後のギャップが大きくて面白いようだ。


恋するプログラム―Rubyでつくる人工無脳

恋するプログラム―Rubyでつくる人工無脳


登録して、

f:id:kaminami:20110603141301j:image

登録して、、、を繰り返した後、

f:id:kaminami:20110603141822j:image

生成する。

f:id:kaminami:20110603142940j:image

2011-05-29

形態素解析エンジン Goist for Squeak

形態素解析エンジンGoistをSqueakでも使えるようにした。

バイナリ辞書VisualWorks版と互換

使い方はVisualWorks版と同じなのでそちらを参照のこと。



Goist速度計測

形態素解析エンジンGoistの速度を計測した。

以前行ったIgoの結果を含めて簡単に比較する。


環境



測定内容


結果

実行時間
Java(Igo)VW(Igo)VW(Goist)CogVM(Goist)SqueakVM(Goist)
834222926393582 (2回目)
4272 (初回)
27362

単位ミリ


実行時間
Java(Igo)VW(Igo)VW(Goist)CogVM(Goist)SqueakVM(Goist)
12.673.164.29 (2回目)
5.12 (初回)
32.8
0.320.8411.36 (2回目)
1.62 (初回)
10.37
0.230.620.741 (2回目)
1.19 (初回)
7.64

同じロジックで解を出しているのだが、VW(Igo)に比べてVW(Goist)は少々遅い。これは、わかりやすさ優先で冗長に書いた分、辞書構造が変わっていたり、メソッド呼び出しが増えるなどしているので想定通り。まずまず。

CogVMの性能がVisualWorksVMの性能に迫っていて驚かされた。まぁ同じ人が作っているわけだが。SqueakUIフレームワークであるMorphicが絡むと、そこにCPUパワーが取られてしまいがちだが、Webアプリプラットフォームとしてなら、かなりやれそう。ただ、IO周りが遅いので、そちらに引っ張られるかもしれない。

素のSqueakVMにはそろそろ引退かな。

辞書の読み込み時間については、最初に一度読み込んだ後はそれを使いまわすことを想定しているため、重視していない。概ね、Java(Igo)は一瞬、VW(Igo)は7秒、VW(Goist)は15秒、CogVM(Goist)は30秒、SqueakVM(Goist)は75秒程度で、Javaの速さが際立つ。というよりはSmalltalk陣営が遅い。Ruby(Igo)も3秒程度であった。

(追記)

実装が悪かった。VW(Goist)は4秒、CogVM(Goist)は10秒程度まで縮められた。それでもまだJavaRubyが速いが、際立って遅いというわけではないと思われる。


おまけ

CogVMの場合の、各回の結果を載せる。

JITが効いている様子が窺える。

"Squeak-CogVM(Goist) 初回"
6422 milliseconds
4355 milliseconds
4094 milliseconds
3947 milliseconds
4045 milliseconds
4114 milliseconds
4176 milliseconds
4226 milliseconds
3459 milliseconds
3883 milliseconds
Average: 4272 milliseconds
"Squeak-CogVM(Goist) 2回目"
3358 milliseconds
3391 milliseconds
3931 milliseconds
3395 milliseconds
3832 milliseconds
3373 milliseconds
3869 milliseconds
3381 milliseconds
3916 milliseconds
3375 milliseconds
Average: 3582 milliseconds

使用コード

VisualWorks Smalltalk
dictionaryDirectoryPath := 'C:\ipadic-test'.
dictionary := GDictionary from: dictionaryDirectoryPath.
tagger := dictionary newTagger.
contents := ('c:\temp\igo\kokoro.txt' asFilename withEncoding: #'utf-8') readStream contents.
sum := 0.
10 timesRepeat: [
    | timeToRun |
    timeToRun := Time millisecondsToRun: [tagger parse: contents].
    
    sum := sum + timeToRun.
    Transcript cr; show: timeToRun printString , ' milliseconds'.
].
Transcript cr; show: 'Average: ' , (sum // 10) printString , ' milliseconds'. 
Squeak Smalltalk
dictionaryDirectoryPath := 'C:\ipadic-squeak-test'.
dictionary := GDictionary from: dictionaryDirectoryPath.
tagger := dictionary newTagger.
fs := FileStream readOnlyFileNamed: 'c:\temp\igo\kokoro.txt'.
contents := fs contents.
fs close.
sum := 0.
10 timesRepeat: [
    | timeToRun |
    timeToRun := Time millisecondsToRun: [tagger parse: contents].
    
    sum := sum + timeToRun.
    Transcript cr; show: timeToRun printString , ' milliseconds'.
].
Transcript cr; show: 'Average: ' , (sum // 10) printString , ' milliseconds'. 

2011-05-28

形態素解析エンジン Goist for VisualWorks

形態素解析エンジンIgo(http://igo.sourceforge.jp/)を参考に、Cincom Smalltalk VisualWorksで実装しなおしたもの。解析結果は互換となる。多分。バイナリ辞書ファイル互換性はない。

概ねMeCab互換日本語形態素解析Smalltalkネイティブ環境で行える。



辞書作成

MeCab用のIPA辞書(http://sourceforge.net/projects/mecab/files/mecab-ipadic/)をダウンロードし、適当場所に展開した後、以下のスクリプトを実行する。

| builder |
builder := GDictionaryBuilder
            outputDir: 'C:\goist\ipadic-goist' "Goist用バイナリ辞書の出力先を指定”
            inputDir: 'C:\goist\mecab-ipadic-2.7.0-20070801' "IPA辞書のディレクトリを指定"
            encoding: #'EUC-JP'. "IPA辞書の文字エンコーディングを指定"
builder buildAll.
builder saveAll.
^ builder asGDictionary

数分の後(参考: Core2Duo 1.4GHz、WinXP環境で4分弱程度)、指定した出力先に以下のファイルが出力される。

  • char.bin
  • matrix.bin
  • trie.bin
  • unknown.bin
  • word.bin

使用例

| dictionaryDirectoryPath dictionary tagger1 tagger2 tagger3 |

"辞書の読み込み。辞書はキープして使いまわす"
dictionaryDirectoryPath := 'C:\goist\ipadic-goist'.
dictionary := GDictionary from: dictionaryDirectoryPath.


"形態素解析"
"出力は次の順:表層形, 品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音"
tagger1 := dictionary newTagger.
(tagger1 parse: '吾輩は猫である。名前はまだ無い。') 
    do: [:each | Transcript cr; show: each printString].
"==>
吾輩	名詞,代名詞,一般,*,*,*,吾輩,ワガハイ,ワガハイ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
猫	名詞,一般,*,*,*,*,猫,ネコ,ネコ
で	助動詞,*,*,*,特殊・ダ,連用形,だ,デ,デ
ある	助動詞,*,*,*,五段・ラ行アル,基本形,ある,アル,アル
。	記号,句点,*,*,*,*,。,。,。
名前	名詞,一般,*,*,*,*,名前,ナマエ,ナマエ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
まだ	副詞,助詞類接続,*,*,*,*,まだ,マダ,マダ
無い	形容詞,自立,*,*,形容詞・アウオ段,基本形,無い,ナイ,ナイ
。	記号,句点,*,*,*,*,。,。,。"


"分かち書き"
tagger2 := dictionary newTagger.
(tagger2 wakati: '吾輩は猫である。名前はまだ無い。') 
    do: [:each | Transcript show: each]
    separatedBy: [Transcript show: '|'].
"==>
吾輩|は|猫|で|ある|。|名前|は|まだ|無い|。"


"読み"
tagger3 := dictionary newTagger.
(tagger3 yomi: '吾輩は猫である。名前はまだ無い。') 
    do: [:each | Transcript show: each].
"==>
ワガハイハネコデアル。ナマエハマダナイ。"