Raspberry Pi に統計機械翻訳システムをインストール!

最近いろいろなところで話題となっている Raspberry Pi ですが、この中に統計機械翻訳システムをインストールしてみます。

IMAG0600

インストールするだけです。実際に使えるかどうかは別問題で、512MBのRAMでは多分まともな翻訳ができないでしょう。もしまともに翻訳できるようになれば、それこそ猫型ロボットのマンガに出てくる蒟蒻サイズの翻訳機になります。食べられませんけど。

さて、機械翻訳には大きく分けてルールベースの翻訳(Excite翻訳など)と、統計ベースの翻訳(Google翻訳など)があります。ルールベースのものは人手によって並べ替え規則や単語の置き換え規則を列挙するものであり、ルールを適用できるきれいな原文に対しては高い精度で翻訳できますが、くだけた表現やルールに載っていないものには適用しにくいという問題があります。一方統計ベースのものは、大量の対訳コーパスから翻訳ルールを自動的に抽出して学習するもので、精度は学習の仕組みや学習文の量によって変わり、最近はこちらのものが盛んに研究されています。

今回は、統計ベースに機械翻訳システムのうち、構文木を利用した翻訳機である「Travatar」をRaspberry Piにインストールしてみます。(もちろん、TravatarはLGPLのフリーソフトウェアです。)

因みに私の Raspberry Pi は jessie にアップグレードされています。

では、まず依存パッケージの marisa をインストールしましょう。marisa は travatar の中にも含まれていますが、順調にいけば今後Debianに入る予定なので、そちらを入れます。
(途中パッケージが足りないと言われたら、それらを apt-get でインストール。)

1
2
3
4
5
$ dget -u http://mentors.debian.net/debian/pool/main/m/marisa/marisa_0.2.4-4.dsc
$ cd marisa-0.2.4
$ debuild -us -uc
$ cd ..
$ sudo dpkg -i libmarisa0_0.2.4-4_armhf.deb libmarisa-dev_0.2.4-4_armhf.deb

次に travatar ですが、いくつか変更を施したものを上げておいたので、そちらをビルドしてください。変更点は

  • ビルドエラーの修正
  • 実行ファイル名の変更(ファイル名の先頭に travatar- を追加)
  • システムの marisa を使用するように変更
  • ライブラリーのリンクを、実行ファイルに対してでなく libtravatar にするように変更
1
2
3
$ dget http://mentors.debian.net/debian/pool/main/t/travatar/travatar_0.1.0+git20131221-1.dsc
$ cd travatar-0.1.0+git20131221
$ debuild -us -uc

ここまでで大体6時間くらいかかりますが、一応ビルドはでき、プログラムも動きます。
あとは翻訳モデルの作成と、実際に翻訳できるかどうかですが、Raspberry Pi の中で翻訳モデルを作成するのは超厳しすぎるので、クラスターマシンを使いましょう。
学習の仕方は Travatar のページを参照して下さい。

Ren’Py ドキュメント日本語化率50%超

Ren'Py のドキュメントが50%以上日本語化されているので、途中経過を公開します。
2013年8月31日時点で80%以上(changelogなどを除くと実質95%くらい)になりました。

Launchpadでの翻訳作業に尽力されている赤恐竜さんと、過去の翻訳を提供して下さった高瀬有広さんに、大感謝です。
日本語版ドキュメント

もう少し翻訳が進んだら上流に取り込んでもらう予定です。
追記: そろそろ確認作業に入ります。

翻訳作業というのは殆ど人海戦術であり、目標を早く達成できるようにする方法は、翻訳者が増えることです。
追記: 日本語ドキュメントの通し読みして、おかしいと思ったところを指摘してくれるだけでも大丈夫です。
ドキュメントの翻訳に興味を持っている方や、Ren'Pyが大好きな方が作業に参加してくれることを期待しています。
作業はここでやってます: https://launchpad.net/renpy-doc
Launchpadにアカウント登録するだけで翻訳作業を始められます。お気軽にご参加ください。

ではでは。

DBusを使ってRen’Pyにメッセージを送る(Twitterを表示する)

ノベルゲームエンジンの Ren'Py をうまく使えば Python の愛好家に嬉しいプレゼンソフトにもなるわけですが、今回は最近流行りの? プレゼン画面にTwitterを表示する演出を Ren'Py を使って実現しようと思います。

Twitter のストリームを取得するには、サーバーとの接続を維持する必要があります。単純に考えればマルチスレッド化して処理することになると思います。
しかし Ren'Py の場合、ゲームスクリプトの終了をスクリプト側から検出することが出来ないため、ゲームの終了時に Twitter を処理をするスレッドを終了できません。

そこで今回は Twitter を処理するプログラムから DBus を使ってゲーム側にデータを転送する方法を取ります。

色々言ってても仕方ないので、サンプルスクリプトを貼ります。

ゲームスクリプト:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
init python:

    style.default.font = "VL-Gothic-Regular.ttf"

    import dbus
    import dbus.service
    from dbus.mainloop.glib import DBusGMainLoop
    import glib
   
    class RenpyDBusService(dbus.service.Object):
   
        msg_stack = []
       
        def __init__(self):
            bus_name = dbus.service.BusName("org.renpy.message", bus=dbus.SessionBus())
            dbus.service.Object.__init__(self, bus_name, "/org/renpy/message")
 
        @dbus.service.method("org.renpy.message")
        def setMessage(self, msg):
            self.msg_stack.append(msg)
           
    DBusGMainLoop(set_as_default=True)
    myservice = RenpyDBusService()
    glibloop = glib.MainLoop()
    gcontext = glibloop.get_context()
   
    def get_tweets(st, at):
   
        global myservice, gcontext
        gcontext.iteration(False)
        if myservice.msg_stack:
            msg = myservice.msg_stack.pop(0)
            return Text(msg, color="#fff", size=24), 8
        else:
            return Text("", color="#fff", size=24), .1

image tweet = DynamicDisplayable(get_tweets)

label start:

    show tweet at Position(xalign=.1, yalign=.1)
   
    "This is a test for renpy-twitter"

    return

ツイッター取得スクリプト:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/python
import json
import urllib2
import oauth2

import dbus

CONSUMER_KEY = "VVVVVVVVVVVVVVVVVVV"
CONSUMER_SECRET = "WWWWWWWWWWWWWWWWWWWW"
ACCESS_TOKEN_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx"
ACCESS_TOKEN_SECRET = "YYYYYYYYYYYYYYYYYYYYYYYY"

consumer = oauth2.Consumer(key=CONSUMER_KEY, secret=CONSUMER_SECRET)
token = oauth2.Token(key=ACCESS_TOKEN_KEY, secret=ACCESS_TOKEN_SECRET)

query = {"track": "linux"} # linux を含むツイートを表示

request = oauth2.Request.from_consumer_and_token(consumer, token,
                                                 http_url="https://stream.twitter.com/1/statuses/filter.json",
                                                 parameters=query)

request.sign_request(oauth2.SignatureMethod_HMAC_SHA1(), consumer, token)
res = urllib2.urlopen(request.to_url())

bus = dbus.SessionBus()
renpydbusservice = bus.get_object("org.renpy.message", "/org/renpy/message")
renpySetMessage = renpydbusservice.get_dbus_method("setMessage", "org.renpy.message")

for r in res:
    data = json.loads(r)
    msg = "@%s %s" % (data["user"]["screen_name"], data["text"])
    print(msg)
    renpySetMessage(msg)

DBus のドキュメントには glib の Mainloop を使ってイベントを処理するように書かれていますが、今回はSDLを使っているため glib のループが使えません。そこで glib.MainContext.iteration() を定期的に実行することで、送信側から送られてくるイベントを処理するようにしています。

今回は Twitter でしたが、送るメッセージは自由に変えられるので応用範囲が広そうですね。

スクリーンショット:
renpy-twitter