2008-04-30

Python用の自動要約モジュールをcodereposにimportしたよ

けっこう前からのんびり作っていた自動要約モジュールをCodereposにimportしました。

http://coderepos.org/share/browser/lang/python/yoyaku

この自動要約モジュールはまだあまり精度はよくないです。
が、どのぐらい良くないかを知るには、以下のサイトでいちおうサービスとして設置していますので、お試しいただけます。

自動要約サービス Civory

今の所は単純なMMRアルゴリズムで文を抜粋するだけのものですので、まあ、あまり、、、。

今取り組んでいるのは、英文の自動要約の際に、文をまずトピックごとに分割して、その上で要約をかけようとしています。
トピックに分けるアルゴリズムは以下の論文を参考にしています。
Advances in domain independent linear text segmentation
いちおうこれの実装はひとまず終わっていて、それに対応するソースは以下になります。
TopicSegmentationEN.py
今後これにバグがないか注意しながらいろんな例で実験を重ねていく予定です。

NLTKでstemming

nltkにはステミングの有名なアルゴリズムであるporterアルゴリズムが用意されている。

>>> import nltk
>>> nltk.PorterStemmer().stem("application")
'applic'
>>>

2008-04-23

自分のサイトでのユーザーの視線の流れを調べてみる

プレゼンにも最適、ページ内のユーザーの視線をシミュレートする -Feng GUI heatmap

Feng GUI heatmapは、独自のアルゴリズムに基づいて、ユーザーの視線がどのようにページ内で移動するかとその頻度を表示するヒートマップを作成するサービスです。

ということなので、自分のサイトTekTekでもユーザーの視線をシミュレートしてみました。
対象ページ: 書籍「ハイパフォーマンスWebサイト」の詳細ページ

ぱっと見、書籍の画像とAmazonへのリンクに視線が集中するようだ。
しかし、このページのメインはレビューを眺めてもらうことなので、そちらがもっと読みやすくなるようにすべきかもしれない。
なんかよいアイデアはないだろうか。

ついでだが、上記書籍がまだ手元に届かない。早くしてよ〜。

2008-04-20

NLTKで英文の文末判定

英文の文末を判定する簡易なルールベースのアルゴリズム。

Separating sentences

1年前にこの手のアルゴリズムを実装しようとしたが、この問題は非常にやっかいです。
たとえばこんな例:

CELLULAR COMMUNICATIONS INC. sold 1,550,000 common shares at $21.75 each
yesterday, according to lead underwriter L.F. Rothschild & Co.

"INC."の直後や"$21.75"、"L.F."などのピリオドを文末と認識しては大間違いになるのです。

この問題を解決するのに自分が1年前に着目していた論文は以下のもの。

Unsupervised Multilingual Sentence Boundary Detection

この論文では、特に言語を英語だけに限定しない方法を提案しています。
大規模な生のテキストデータから得られる統計情報のみで、文末判定を行えます。
難点はルールベースなどとは違って、事前の綿密な統計の作成、統計処理後の各種特別処理の実装が面倒くさいこと。
昨年途中まで実装したが、Python用の自然言語処理ライブラリNLTKでどうも実装予定との情報を見つけて半端でやめていました。

それで久しぶりに調べてみたら、このアルゴリズムがすでにNLTKで実装されて公開されているではないですか!

早速インストールして使ってみました。

インストール
% wget http://prdownloads.sourceforge.net/nltk/nltk-0.9.2.tar.gz
% tar zxvf nltk-0.9.2.tar.gz
% cd nltk-0.9.2
% sudo python setup.py install
% cd ..
% sudo mkdir /usr/share/nltk
% cd /usr/share/nltk
% sudo wget http://prdownloads.sourceforge.net/nltk/nltk-data-0.9.2.zip
% sudo unzip nltk-data-0.9.2.zip
% sudo chmod -R g+r data
% export NLTK_DATA=/usr/share/nltk/data
% python
>>> import nltk
>>> nltk.corpus.brown.words()
['The', 'Fulton', 'County', 'Grand', 'Jury', 'said', ...]
>>>

ここまでできればインストール完了。

生テキストデータを用意
例えば、Google News(英語版)などからリンクをたどって、ひたすらニュース本文をファイルnews.txtにコピペする。
実験でやるんであれば1000行程度で十分でした。

実験!!
まず生テキストを食わせて学習
>>> from nltk.tokenize import PunktSentenceTokenizer
>>> p = PunktSentenceTokenizer()
>>> fp = file("news.txt")
>>> p.train(fp.read())


次に実際に判定してみる。
判定に使うテキストは次のような少々意地の悪い例
The Finland-based company expects a weaker dollar and slower economic growth in the U.S. and parts of Europe to dampen the overall handset market this year. About half of Nokia's (NOK) sales are in dollars or currencies tied to it; a weaker dollar makes imports more expensive.

"What spooked us was its outlook for the industry in general," said Rick Franklin, equities analyst at Edward Jones.

Nokia reiterated projections that the industry shipments of handsets will grow 10% this year over last. In the first quarter, though, global shipments rose 17%, suggesting a slowdown in the remainder of the year.

For the quarter that ended March 31, Nokia earned $1.9 billion (1.2 euros), up 25% from the same quarter last year but short of an expected $2.3 billion. Overall sales rose 28% to $20.1 billion (12.6 billion euros), roughly in line with views.


>>> a=p.tokenize("""The Finland-based company expects
a weaker dollar and slower economic growth in the U.S. and parts of Europe to
dampen the overall handset market this year. About half of Nokia's (NOK) sales
are in dollars or currencies tied to it; a weaker dollar makes imports more
expensive.

"What spooked us was its outlook for the industry in general," said Rick Franklin,
equities analyst at Edward Jones.

Nokia reiterated projections that the industry shipments of handsets will grow 10%
this year over last. In the first quarter, though, global shipments rose 17%,
suggesting a slowdown in the remainder of the year.

For the quarter that ended March 31, Nokia earned $1.9 billion (1.2 euros), up 25%
from the same quarter last year but short of an expected $2.3 billion. Overall
sales rose 28% to $20.1 billion (12.6 billion euros), roughly in line with views.""")
>>> for x in a:
... print x
... print "-"*20
The Finland-based company expects a weaker dollar and slower economic growth
in the U.S. and parts of Europe to dampen the overall handset market this year.
--------------------
About half of Nokia's (NOK) sales are in dollars or currencies tied to it;
a weaker dollar makes imports more expensive.
--------------------
"What spooked us was its outlook for the industry in general," said Rick Franklin,
equities analyst at Edward Jones.
--------------------
Nokia reiterated projections that the industry shipments of handsets will
grow 10% this year over last.
--------------------
In the first quarter, though, global shipments rose 17%, suggesting a slowdown
in the remainder of the year.
--------------------
For the quarter that ended March 31, Nokia earned $1.9 billion (1.2 euros), up
25% from the same quarter last year but short of an expected $2.3 billion.
--------------------
Overall sales rose 28% to $20.1 billion (12.6 billion euros), roughly in line
with views.
--------------------
>>>

きちんと、ピリオドで文をわけつつも、"U.S."や、"1.2 euros"などで区切るのは避けていることが分かります。

精度を上げるには、もっともっと大量の生テキストを食わせる必要があります。

モンティ・ホール問題

以下のリンク先の問題が興味深い。

Python: モンティ・ホール問題

「プレイヤーは、三つのドアを見せられる。ドアの一つの後ろにはプレイヤーが獲得できる車(アタリ)があり、一方、他の二つのドアには山羊(ハズレ)が 入っている。ホストであるモンティは、それぞれのドアの後ろに何があるか知っているのに対し、もちろんプレイヤーは知らない。

プレイヤーはまず三つのドアの一つを選ぶ。次にモンティは他の二つのドアのうち一つを開け、山羊をみせる。そしてモンティはプレイヤーに、初めの選択のま までよいか、もう一つの閉じているドアに変更するか、どちらかの選択権を提供する。プレイヤーは、選択を変更すべきだろうか?」


変更しない場合: 普通に3つのうちの一つが当たりなので、当たる確率は1/3

変更する場合:
 最初の選択でもしも当たっていたら、(これは1/3の確率でおこる)->変更するためかならずはずれになる。
 最初の選択でもしもはずれていたら、(これは2/3の確率でおこる)->モンティがもう一つのはずれを引いていてくれるので、変更することで必ず当たりになる。
 そのため、変更する場合に当たる確率は2/3

なので、変更したほうが当たる確率が二倍になる!!!

2008-04-14

partty

parttyが面白い。

自分のterminalを晒すことができるwebサービスだそうです。

面識がないにも関わらずtwitterでこっそりfollow している西尾さんが使っているのを見てシビレました。

自分はMacOS 10.4.11だが、上記サイトで配布されているparttyソフトがbus errorとやらで起動しなかったので、ソースをconfigure & makeしました。

gnu screen で複数画面を立ち上げていても、それらがきちんと公開されます。
mysql -uaaa -pxxx somedb
などとうっかり打つと、パスワードが晒されますのでご注意を。

2008-04-10

Google App Engineが待ち遠しすぎる。。。

TekTekGoogle App Engine対応は完了したのだが、まだ登録の順番が回ってこない!!

なので、ちょっとメモなど

* Google App Engineではdjangoのauth、sessionは使えないようだ。sessionが使えないのは、djangoのsessionがdjangoのmodelに依存しているからだそうな。この制限は厳しいが誰かが簡単な解決を探してくれるんじゃないかな。
* TekTekでは、sessionをやめて、できる限りCookieに保存するようにした。

2008-04-09

Google App Engine と格闘中

昨晩、数時間ほどGoogle App Engineで自作のdjangoアプリを移植していた際に気づいたこと。

* printデバッグをしていると、HTTPヘッダの前にprintの結果が出力され、HTTPヘッダもろともブラウザに表示されてしまう。
* urlopenは使えず、Googleが用意したURL Fetch APIを用いる。
* 手元のマシンのpythonのsite-packagesはそのままではどうも見てくれないようだ。
* django の ContextProcessorは通常内部的にrequest.userを使っているようで、以下のようにしてTEMPLATE_CONTEXT_PROCESORSからauthを外す必要がある。

TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media"
)


早く本登録来い!!

Google App Engine SDKインストール編

TekTekで使えたらいいなと思って、Google App EngineのSDKをインストールしてみた。
(まだ登録は順番待ちなのです。(T_T)
ひとまずHello worldまで実験完了したので書いておきます。

1. SDKのダウンロード
http://code.google.com/appengine/downloads.html


2. インストール
ダウンロードしたパッケージをひたすらクリックしてインストールして行きます。
その間表示されるメッセージには、以下のようなことが書いてあります。

開発用サーバーは、/usr/local/bin/dev_appserver.py にインストールされます。
その他の部品は /usr/local/google_appengine へインストールされます。

開発サーバーの起動
/usr/local/bin/dev_appserver.py [options] <application root>

"application root"は、文字通りアプリケーションのルートディレクトリで、
正式なフォーマットのapp.yamlかapp.ymlファイルを置いていなければならない。


追加で、以下のコマンドを実行し、各アプリをPythonにインストール。
% sudo ln -s /usr/local/google_appengine/google /usr/local/Python25/lib/python2.5/site-packages/google
※上記"/usr/local/Python25/lib/python2.5/site-packages/"の部分は、
あなたがお使いのPythonのインストールパスに合わせてください。

% cd /usr/local/google_appengine/lib/webob
% sudo python setup.py install
% cd /usr/local/google_appengine/lib/yaml
% sudo python setup.py
※djangoをインストールしていない方は、さらに
% cd /usr/local/google_appengine/lib/django
% sudo python setup.py

3. 確認
% python
>>> from google.appengine.ext import webapp
※このimportで何もエラーがでなければ、OKのようだ。
>>> ^D


4. Hello worldを書く。
% mkdir helloworld
% cd helloworld
※ここでこのディレクトリに以下の2ファイルを作成。
% cat helloworld.py
print 'Content-Type: text/plain'
print ''
print 'Hello, world!'

% cat app.yaml
application: helloworld
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
script: helloworld.py

5. hello worldアプリを起動
先ほどのhelloworldディレクトリ内にいる場合は、その上の階層へ
% cd ..

そして、以下を実行
ayu@~/work% /usr/local/google_appengine/dev_appserver.py helloworld
Allow dev_appserver to check for updates on startup? (Y/n): n
※上でdev_appserver.pyのアップデートをするかを聞かれるが、あせってnを選びました。。。

WARNING 2008-04-09 01:31:55,128 datastore_file_stub.py] Could not read datastore data from /tmp/dev_appserver.datastore
WARNING 2008-04-09 01:31:55,128 datastore_file_stub.py] Could not read datastore data from /tmp/dev_appserver.datastore.history
INFO 2008-04-09 01:31:55,131 dev_appserver_main.py] Running application helloworld on port 8080: http://localhost:8080

ここまでできたら、以下のURLをブラウザで開く。
http://127.0.0.1:8080/

これでhello world!が画面に表示されるはず!!!

2008-04-08

MySQL5のFederatedはまだまだ使えないという話

Every query to a federated table results in a full scan of MyISAM table.

Federatedエンジンでselect count(*) from ...をすると、いちいちテーブルの全レコードをリモートに送り込むというバグがあるそうで、期待のFederatedであったがまだまだ使い物にはならない。
5.1以上で直すことになると見えるが、現時点ではChange logにその修正の旨は発見できず。

PythonでLatent semantic analysis

Latent Semantic Analysis in Python

興味深い。

【要点】
* TFIDFをベクトルの成分とする。
* scipy のsvdルーチンを使う。(次元が100万とかになっても大丈夫なんだろうか?Lanczos法のような手法を内部で使っているか?)

Blogの記事のような、極端に短い内容の記事も大量にあるような文書集合だと、こういった手法でぼかした検索ができるといいのかもしれません。

でもこういうのは実運用の場合はC++で書くべきと思うよ。

2008-04-07

optparseのhelp文で改行を生かす方法

pythonのoptparseモジュールは便利だが、help文に改行を使ってもうまく表示されない。
解決の参考になるのはここの議論だろう。
以下にそのソースを抜粋。

import optparse
import textwrap

class IndentedHelpFormatterWithNL(optparse.IndentedHelpFormatter):
def format_description(self, description):
if not description: return ""
desc_width = self.width - self.current_indent
indent = " "*self.current_indent
bits = description.split('\n')
formatted_bits = [
textwrap.fill(bit,
desc_width,
initial_indent=indent,
subsequent_indent=indent)
for bit in bits]
result = "\n".join(formatted_bits) + "\n"
return result

def format_option(self, option):
"""
The help for each option consists of two parts:
* the opt strings and metavars
eg. ("-x", or "-fFILENAME, --file=FILENAME")
* the user-supplied help string
eg. ("turn on expert mode", "read data from FILENAME")

If possible, we write both of these on the same line:
-x turn on expert mode

But if the opt string list is too long, we put the help
string on a second line, indented to the same column it would
start in if it fit on the first line.
-fFILENAME, --file=FILENAME
read data from FILENAME
"""
result = []
opts = self.option_strings[option]
opt_width = self.help_position - self.current_indent - 2
if len(opts) > opt_width:
opts = "%*s%s\n" % (self.current_indent, "", opts)
indent_first = self.help_position
else: # start help on same line as opts
opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts)
indent_first = 0
result.append(opts)
if option.help:
help_text = self.expand_default(option)
help_lines = []
for para in help_text.split("\n"):
help_lines.extend(textwrap.wrap(para, self.help_width))
result.append("%*s%s\n" % (
indent_first, "", help_lines[0]))
result.extend(["%*s%s\n" % (self.help_position, "", line)
for line in help_lines[1:]])
elif opts[-1] != "\n":
result.append("\n")
return "".join(result)

if __name__ == "__main__":
parser = optparse.OptionParser(
formatter=IndentedHelpFormatterWithNL(),
usage=u"""....""")
....

2008-04-05

「ケータイマルチキャリア高機能テスター」を使ってみるよ。

ケータイマルチキャリア高機能テスター P1エミュレーター
を使ってみる事にした。

ほとんどの最近のケータイのエミュレーターになるそうで、携帯用サイトの作成に役立ちそうです。

これでTekTekのi-mode版、SB版も作ってみることにしよう。

2008-04-04

Amazon.comから尻を叩かれた話

TekTekを作った時に、米国のAmazon.comのアフィリエイトにも加入したのだが、今日、そのAmazon.comから「売り上げが上がってないぞ!」ということをやんわりと伝えるメールが来た。

Hello Associate,
We noticed that you were accepted to the Amazon.com Associate Program
several weeks ago but have yet to refer a sale. Here are a few quick
and easy steps to help you get started:

訳:
こんにちは、
数週間前にAmazon.comのアソシエイトプログラムに加入させてあげましたが、
まだ売り上げが上がってないようですねえ。助け舟として、すぐに&簡単に
できることを教えておきます、、、


あ、、、ありがとう、、、。がんばるよ。米国かーーー、、、どうやって宣伝すればいいものか。

2008-04-02

TekTekモバイル for EZwebをオープンしました!

TekTekのモバイル版TekTek mobile for EZwebをオープンしました。
今の所はEZwebのまあここ2〜3年ぐらいの機種のみ対応です。(古い機種での動作は確認していませんので保証できません。)

URLは以下になります。
http://www.tektek.in/d/tk/m/   → TekTek mobile for EZweb

TekTekを最初に作ろうと思った動機が、本屋で本を選ぶ時にAmazonの書評と評価点数をすばやく見たいからでした。
また、場合によってはその場で本を買わずに、Amazonに注文して届けてほしいと思う事もあります。
そんな用途を考えて、このモバイル版を作っています。

今後さらなる機能追加も行って行きますが、これでひとまず自分が使いたい最低ラインに到達です。