Anthyの変換精度を上げる方法

http://www.josw.net/blog/?p=1203
変完成度って…。

こんな感じで誤変換が多いAnthyですが、いつまでたっても頭が悪いままなのは、学習データをすぐ忘れちゃうかららしいです。

つまり、学習データの記憶容量が小さすぎて、覚えたことをどんどん忘れていってしまうみたいです。

実際、何時間も入力作業をしていると最初の方の結果は覚えてないし、すぐさま忘れるものもあります。

んで、これを解決するために、学習データの格納容量を大きくするっていうパッチがあるみたいなんですが、やはりパッチ当てるのも、その後自分で管理するのも面倒。

そのうえ、方法がやや複雑だったりデメリットもあるみたいです。

なので、良い方法無いかなーと考えたら、思いつきました。

学習データを格納する辞書ファイルを、行の削除が出来ないようにしてやればいいんだ、ということを。

つまり、追記のみ許可をしてあげるわけですね。

というわけで、やり方を書いておきます。

$ sudo chattr +a ~/.anthy/last-record2_default.utf8


いやまあ、多くの場合1行で済んじゃいます。最近のディストリビューション使ってるなら。

こうすると、Ext2,Ext3の機能でアクセス制御を行い、ファイルの追記のみを許可するということになります。

なので、Anthyが「これ忘れよう!」として学習データを削除しようとしても、削除できないということになります。

でも、教えられたことはどんどん覚えていくので、どんどん頭がよくなっていきます。

ちょっとDirty Hackな感じですが、変換効率は確実によくなっているので、試してみる価値はあると思いますよ。

ああ、もちろん自己責任ですからね。

まだ3日目なんで何とも言えませんが、不都合は起こってないので大丈夫だとは思います。

ご指摘があれば、コメントをお願い致しますね。



追記1

~/.anthy/last-record1_default.utf8

のほうなんですが、これの追記のみ許可はまだ試していません。

こっちもやると良くなるのかは、みなさんで試してみてください!

試した方は、結果の報告、ぜひお願いしますね!

歩行者優先の当たりとはずれ

http://www.josw.net/blog/?p=1101

普通、車を運転する人は、歩行者(正確には弱者ですが、歩行者と書きます)優先を心がけないといけません。

当たり前ですが、信号の無い横断歩道を渡れないことがあってはならず、道を渡りたそうにしてる人がいたら一時停止して、渡り終るまでの安全を見届けるというものです。

車を運転してなくても、それが出来てない人が多いことはわかりますよね。

しかし、視点を変えてみましょう。

彼らは実は、悲しい善者なのです。

一時停止出来ない人たちなのです。

なぜかというと、一時停止をするということは、もう一度車を加速させる必要がありますね。

この加速による燃料の大量消費を抑えるべく、歩行者に申し訳ない気持ちで通過してるんです。

そう、彼らは地球環境悪化を引き起こさないためにそのような行動をとっていたのです。

しかしそれなら車に乗るなという感じではありますが、そこは悲しい善者。車に乗ることを強いられているわけです。

車がないと生きていけない社会によって。

彼らを攻めてはいけません…。



一応書いておきますがネタです。

しかし、正直なところ確かにもったいないとも思ったりしてます。

たった一人通るために数十台の車を停めさて、その数十台が加速により燃料を大量に消費させる。

通行者が車の途切れを待つ数十秒と、数十台による余分な環境汚染。

果たして汚染に見合う価値はあるのか?と思ったりします。

ちなみに、僕は一時停止している悪者です。

Turbogears(SQLAlchemy)でテーブルを動的に読み込む

http://www.josw.net/blog/?p=1053

というわけで__new__の続きです。

Turbogearsでは、model.pyでテーブルとクラスを定義してそれらをマッピングしますね。

で、controller.pyでsession使ってmodel.Userみたいな感じでデータを読み出します。

ここまでは普通に紹介されてることですね。

では本題に移ります。

まず、同じ構造のテーブルが、時間が経つごとに名前を変えて増えていく、というシチュエーションを思い浮かべてください。

違うのはテーブル名だけなので、model.pyには以下のような定義があればよさそうな感じがします。


name = 'foo'
tablename = 'user_' + name
table_user = Table(tablename, metadata,
Column('id', Integer, primary_key=True),
Column('hitokoto', Unicode(400)),
)

class TableUser(object):
def __init__(self, hitokoto):
self.hitokoto = hitokoto

mapper(TableUser, table_user)

これでとりあえずtg-admin sql createが通り、実際に動作させることができます。

しかしこれだけだと、user_fooというテーブル以外を扱おうとすると、それなりに労力がかかりそうです。

というわけでこいつを以下のように書き換えて、もう少し扱いやすくします。


username = 'foo'
class MetaTableUser(object):
def __new__(cls, name):
tablename = 'user_' + name
table_user = Table(tablename, metadata,
Column('id', Integer, primary_key=True),
Column('hitokoto', Unicode(400)),
)
return table_user

table_user = MetaTableUser(username)

class TableUser(object):
def __init__(self, hitokoto):
self.hitokoto = hitokoto

mapper(TableUser, table_user)
metadata.remove(table_user)

はい。ここで出てきました我らが__new__さん。関数返してます。

何のためにこういうことしてるかというと、普通の関数に初期値を与えて扱えるようにするためなのと、controller.pyに同じ内容を書かなくて済むようにです。メタ関数(適当言ってます)。

それから、最後の行はおまじないです。さらっと言ってますが、この1行のために1日ほどかかってます。

ではでは下準備も済んだので、controller.pyの記述に入って行きましょう。

とりあえずこんなかんじです。


@expose(template="alchemymytest.templates.userpage")
def user(self, username='anonymous'):
flash(("This is", username, "\'s page."))

meta_table_user = model.MetaTableUser(username)

othermapper = mapper(model.MetaUser, meta_table_user, non_primary=True)
hitokotos = [hitokoto.hitokoto for hitokoto in session.query(othermapper)]
metadata.remove(meta_table_user)
return dict(username=username, hitokotos=hitokotos)

簡単に説明します。まず、http://localhost:8080/user/ というページを定義しました。

そして、そのページにはuser_hogehogeに当たる部分を引数として与えます。http://localhost:8080/user/hoge/ みたいな感じです。

次に、5行目は__new__さんがusernameのテーブル名を持ったTableオブジェクト(関数)を返してきてます。

そして7行目でマッピングするわけですが、そのままマッピングしちゃうとmodel.pyでマップしたものとかぶっちゃうので、別物としてマッピングします。

そして8行目でuser_usernameなテーブルを読み出していくというわけです。

そして9行目ですが、同じテーブルを定義しようとすると怒られるので、今定義したテーブルを削除してます。


では http://localhost:8080/user/ にアクセスしてみましょう。あ、テンプレートの準備がまだでしたね。


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
py:extends="'master.kid'">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
<title>user page - ${username}</title>
</head>
<body>
<h1>${username}'s hitokoto</h1>
<ul>
<li py:for="hitokoto in hitokotos">
<${hitokoto}</a>
</li>
</ul>
</body>
</html>

これをuserpage.kidとして保存します。それから、ついでにuser_hogeとかでテーブルを何個か作って(user_anonymousは必須)、その中に適当なデータを格納しておいてください。

ここまでうまく行ってれば、user_anonymousに格納したデータがずらっとでてくるはずです。せっかくなので他のもみてみましょう。

さて、こんなところです。

眠さの限界なので考えずに書いてます。ごめんなさい。

わからないことあったらコメントで聞いてくださいね!


2008/4/2追記
本文に入れよう入れようと思って忘れてました。
別に、__new__を使わなくても出来ます。
こっちのほうが好きだったし、こういうやり方もあるよ的な感じです。

__new__

http://www.josw.net/blog/?p=1051

Pythonでクラスを定義するとき__new__っていう特殊メソッド使えるんですが、これが便利です。

普通、クラス定義のときはコンストラクタとして__init__を使いますね。

この__init__はコンストラクタのため返り値の指定はできず、常にインスタンスオブジェクトを返すというのは当たり前の話ですね。

それに対し、__new__は返り値を返すことが出来るのです。

意味の無い例ですが、以下のような感じ。


>>> class TestSpecialName(object):
... def __new__(cls, arg_int):
... return arg_int ** 2
...
>>> TestSpecialName(4)
16
で、これを利用すると、関数を返すことも出来るんですね。

>>> def foo():
... return range(5)
...
>>> class Return_foo(object):
... def __new__(cls):
... return foo
...
>>> hoge = Return_foo()
>>> hoge

>>> hoge()
[0, 1, 2, 3, 4]
とりあえず今日はここまで。

近日中にこれを利用した便利かもしれないこと実験して投稿します。

自動公衆送信出来る状態

http://www.josw.net/blog/?p=1046

http://internet.watch.impress.co.jp/cda/news/2008/03/25/18935.html

最近、この手のニュースを見ると思う。

WindowsMacLinux、またはその他のネットワーク通信に対応したOS使ってて、そのOSのローカルストレージに他人の著作物が記録された時点で「自動公衆送信出来る状態」になるんじゃないのかな。

普通はOSが自動でファイルをアップロードするってことは無いから、何かしらデータ通信を行うソフトが立ち上がってる必要があるとは思うけど。

例えばファイル転送機能を有するIMソフト(Windows Live Messengerとか)に、任意のコードを実行出来る脆弱性(機能)があったとする。

あ、別にファイル転送機能もってなくてもいいか。大事なのは脆弱性(機能)のほうだし。

で、その脆弱性(機能)を持ったソフトを実行した時点で、好きなファイルを好きなだけ自動的にいろんなところへ送信出来る状態になっちゃうわけですね。

つまり、記事で取り上げられているWinnyのように、ファイルアップロード要求に応えてファイルを送信しちゃう環境ができちゃってるわけです。細かい違いはありますが。

さらに言うと、任意のコードを実行できちゃうわけなので、同じIMソフトを好きなだけ中継して手元に届けることも可能なわけです。もう一つ言うと、通信路を暗号化しちゃったりアップロードデータを暗号化しちゃったりもできます。これ何てWinny?って感じです。

そうか。任意のコードを実行できる脆弱性っていうのはOS自体にも存在するから、ネットワーク通信に対応したOS使ってる時点で表題のような環境になっちゃう可能性があるわけか。

そういうわけなので、ローカルストレージに他人の著作物を記録する場合、必ず事前にネットワークインターフェースを物理的に切り離すようにしましょう。捕まりたくなければね。

turbogears.database.session

http://www.josw.net/blog/?p=1044

PythonでSQLAlchemy使ってるとき、データベースからデータを取得するにはsessionmaker()使います。以下のような感じです。
ここで、モデル定義は済んでおり、既にデータベースにデータが格納されているとします。


from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

engine = create_engine('sqlite:///hoge.sqlite')
Session = sessionmaker(bind=engine, autoflush=True, transactional=True)
session = Session()

for data in session.query(Model):
print data.username

簡単に説明すると、4〜6行目でデータベースを指定してセッションを作ってます。
で、7行目のsession.query()にSQLAlchemyのmapperを指定すると、mapされたテーブルの行がクラスとしてdataへ渡されます。
そして8行目で表示してます。カラム名がクラスのデータメンバとして格納されてるわけですね。

で、これと同じ動きをTurbogearsで行う方法を発見したので備忘録的に投稿してみるわけです。
ここではSQLAlchemyを使うプロジェクトを作成してあり、モデル定義とデータ追加は…話が長いですね:)


from turbogears.database import session

s = session()
for data in s.query(Model):
print data.age

もっと短く書くとこうなります。


from turbogears.database import session as s
for data in s.query(Model):
print data.myfavoriteanimals

カラム名が長すぎてタイピング数は変わらないみたいですね。

しかし、3行でデータベースからデータを取得出来るのはいい話だと思います。

無茶をしない程度に利用してみてください。

そうそう。取得したデータをリスト形式で保持したければ、リストの内包表記を使うと少し幸せになれます。蛇足でした。

Fedora 8でSkypeの音が出るようになった

http://www.josw.net/blog/?p=1028


試行錯誤の末、ようやくSkypeの音が出るようになりました。

どうやらFedora8では音声関連の取扱いが変わってしまって、アプリケーション側で対応してないと音を出せなくなってしまったらしい。

それで現行バージョン使ってても音が出なかったわけです。

で、どうすればいいかというと、ちょっと古いバージョンのskypeを使います。

Skype for Linuxにある、Static OSSというやつです。ちなみに執筆時点のファイル名はskype_static-1.4.0.118-oss.tar.bz2です。

ダウンロードしてきたら展開して、その中にあるバイナリを実行すればいいわけですが、実行する際、ちょっと付け加えることがあります。

とりあえず以下のコマンドです。

$ padsp ./skype

このpadspって何かというと、OSSという仕組みを用いて音を出そうとしてるプログラムが、今の仕組みに対応できるような感じにしてくれるプログラムなんです。

いわゆるWrapperというやつです。

んで、現行バージョンのskypeは、OSSではなく(多分)ALSAという仕組みのものを使おうとしてるんですね。

そのため、このpadspでは対処出来ないうえ、設定をいくらいじっても音が出なかったという訳です。

逆に言うと、現行バージョンのものが今の仕組みに対応するまで、古いバージョンのskypeを使いつづける必要があるんですけどね…。

ビデオチャットするわけじゃないんで別にいいですけどね!

このPCだけかもしれませんが、同様の症状で困ってる方はお試しください。