9 月 2008

You are currently browsing the monthly archive for 9 月 2008.

IIRことIntroduction to Information Retrieval輪講の第14回目に行きました。

山下たつをさん主催のこの輪講、私は初回から参加しています。
進め方は、英語テキストを読んでいき内容をしっかり理解しながら、関連の話題についても話し合うという感じです。
私は数学をちゃんと勉強していないので、数式には苦労します。記号の読み方が分からなかったりしますし。
アルゴリズムが擬似コードで書かれている箇所があるのはありがたいです。数式よりコードのほうが長いですが、私には分かりやすいです。
このブログで内容を紹介するにあたっては、数式もコードも使わずに、文章で振り返りながら自分の理解を確認してみたいと思います。

今回は 第13章、”Text classification and Naive Bayes”を読みました。長いので13.5.5までになりました。
テキスト分類のポピュラーな手法、ナイーブベイズについての章です。

テキスト分類の必要性の話から始まっています。メールの分類など、文章によってテキストを分類したいということはよくあります。
「どの単語が含まれる場合」など細かいルールを作っておけばうまく分類できますが、新しいテキストに対応しつづけるのは大変です。
そこで、機械学習、特に教師付き学習を使います。
教師付き学習とは、あらかじめトレーニング用文書セットを用意し、それぞれの文書がどのクラス(「迷惑メール」など)に分類するかを人間が教えておくものです。

機会学習の方法として、多項ナイーブベイズモデルと、ベルヌーイモデルの二つが出てきます。
やり方はよく似ていますが、計算方法が違います。
多項モデルは同じ単語が文書中に何回出てきたかによって結果が変わります。
他方、ベルヌーイモデルでは、ある単語がある文書に出現したか、しなかったかだけで表されます。

やり方を文章で書いてみます。
まずは準備です。人手で分類済みのトレーニングセットを用意し、全部のクラスに対して以下を行います。
トレーニング文書セット中、各クラスに該当した文書の割合を数えておきます。
そして、クラスと単語の組み合わせごとに、その単語が出てくる文書が、そのクラスに分類された確率(条件付き確率)を求めておきます。
求め方は、多項モデルの場合は、「その単語の出現数 + 1」を、「そのクラスに含まれたトークン数(単語の重複を含む数) + テストセット全体の語彙数(重複を含まない数)」で割ります。
+1するのは、ゼロにならないようにです。
これで準備完了。

未知の文書に対して自動分類を実行する時は、それぞれのクラスに分類される事後確率を調べます。
そのクラスになる事前確率(割合)に、出現した単語がそのクラスに分類される条件付き確率を全部かけていきます。
なお、小数が小さくなりすぎるとコンピュータで扱いづらくなるので、それぞれの確率は対数にします。
これを全部のクラスに対して行います。結果としてその文書は、一番値が高かったクラスに割り振られることになります。

注意点として、計算される数値はクラスを比較するための相対的な意味しか持たないものです。最高の値が0.8だったか0.1だったかにはあまり意味がありません。
そのため、「どのクラスでもない」という結果が必要な場合は、「どれでもない」というクラスを用意しておく必要があるのだと思います。
トレーニングはクラス数×語彙数に、テストはクラス数×文書中の単語数に比例する時間で処理できます。実用的だということです。

次に、考慮する単語を絞ってしまう素性(そせい)選択の手法が紹介されています。
たまたまトレーニングセットで特徴的な語彙の使われ方があると、それに影響されて精度が悪くなるという問題があります。
素性選択は、処理効率を上げるだけでなく、これに対して有効な手法だと紹介されています。

やり方としては、相互情報量、カイ二乗検定、頻度による方法が挙げられています。
頻度による方法は、多くの文書に出ている単語を使う、というもので、単純なので失敗することもあります。
相互情報量とカイ二乗検定は、クラスと単語の関連性が偶然っぽいか、偶然ではなさそうかを数値で出すものです。
あるクラスCとある単語Tについて、CであってTを含む文書、CであってTを含まない文書、CでないがTを含む文書、CでなくTを含まない文書の四通りの文書数を挙げ、それを式に当てはめます。
式についてはすみません、意味があまりよく理解できていないので省略します。

Many URLs

日頃Webを使っていて面白いなーと思うのはURLのことです。本来はWeb上の文書を指し示すためのアドレスですが、現在では色々な使い方がされています。

Googleなどの検索結果やマップのURLはパラメータがたくさんついてとても長くなっていますよね。近年のWebサービスではURLがきれいに整理されたものが多いですが、ここで言いたいのは、URLは状態を表すこともできるということです。

長すぎるURLを短縮するためのサービスも色々出ていますね。TinyURLやBit.lyなどがよく使われています。

 

最近知ったサービスで、シンプルだけど便利だと思ったのはこれです。

Splicd

YouTubeのあるビデオの一部を再生できます。どこからどこまで再生したいかを時間で指定すると、それに対応したURLを発行してくれます。

そのURLを開くと、指定された時間だけ再生されるようになってます。

 

そのコンテンツの中で、ある人がどの部分に注目したか、というのがURLとして切り出されるわけです。一度URLにしてしまえば、記録したり共有することが簡単になります。

 

こんな風に、あるコンテンツに対して様々な状態だとか、あるいは様々な視点を表現すると、無数のURLを発行することになりますね。

しかし実体は一つなので、検索エンジンなどはそれらのURLを一つのものとして扱ったりしています。検索エンジン実装者には面倒な問題です。

でも、他の人がどんな見方をしているかというのが気になることもあります。

実体の検索と、実体に対する表現の検索は別物なのかもしれません。

先週ニューヨークでWeb 2.0 Expoというイベントが開催されていたそうです。

サマリで書き起こされていたプレゼンテーションの一つをいい加減に読んでみました。

Jason Fried - Things We’ve Learned at 37signals | Kris Jordan

Jason Friedさんは37 Signalsのメンバーで、デザイナーの方です。

この講演では14個の「学び」について語っていますが、私はそのうちの一つが印象に残りました。

 

13. Give up on hard problems - there is nothing wrong
with being lazy. There is an abundance of easy problems that need to be
solved. The really hard problems are probably better left to your
competitors. Solve a bunch of simple things. Most people’s problems are
simple and you can probably solve 10 in a month over 1 in 10 months.

 

簡単なものだけれど、誰かが解決するべき問題がたくさんある、と彼は言っていますね。

例えば、当たり前の生活のなかのちょっとした不便とかがそうなんでしょう。

そういう問題を、問題として見つけることにもある種の才能が必要なのかもしれませんけれど。

 

自分(たち)にしかできないことをやろうとした場合、まずは問題をしっかりと見つけること。

他の誰かが見つけた問題に安易に飛びつかないこと、と自戒した私です。

今日は、最近面白いと思った海外のサイトをご紹介します。

Stack Overflow

 

Joel on Software“で有名なJoel Spolskyさんと、同じくプログラマ向けのコラム執筆で知られるJeff Atwoodさんらが立ち上げた、プログラマのためのQ & Aサイトです。数日前にプライベートベータから公開ベータ版になりました。

プログラマ同士で疑問を解決しあうサイトは他にも色々ありますが、このサイトにはいくつか面白い特徴があります。

リッチな編集インタフェース

リッチと言っても必要なものをしっかりそろえているという感じですが、ソースコードの貼り付け、アンドゥ・リドゥなどができるようになっています。

画像も貼り付けられるので、このような見ているだけで楽しい質問も出てきています。

Stack Overflow screenshot
What’s your favorite “programmer” cartoon. - Stack Overflow

行動や評判を表す色々な種類のバッジ

質問や回答に対して、善し悪しを投票することができます。その投票結果や、質問や回答などの回数に応じて、GuruやScholar、Specialistといった色々なバッジが与えられます。

これを見るとコミュニティ内の行動と評判が一目で分かるようになっています。

作成済みの質問を他人が編集できる

ウィキのように、質問を他の人が編集することができます。誰がどのように編集したかの履歴はちゃんと残ります。

これはずいぶん思い切った機能だと思いますが、サイトの説明には以下のようにあります。

Like Wikipedia, this site is collaboratively edited. If you are not comfortable with the idea of your questions and answers being edited by other trusted users, this may not be the site for you.

このやり方が嫌なら参加しなくていいよ、と。

良い答えを得るには良い質問を練り上げること、というのは確かに正しいアプローチかもしれません。質問そのものがコラボレーションによってバージョンアップしていき、結果としてQ & Aデータベースが有用なものになっていくという仕組みなのでしょう。このあたりがうまく行くかどうかには、評判の要素も効いてくるのかもしれません。ただし今のところは、タグを増やしたりスペルミスを修正したりということに主に使われているようです。

 

コミュニティのサポートがしっかりしたプログラマ向けのQ & Aサイト、Stack Overflowをご紹介しました。

コンピュータ中毒で眠れない問題など技術的な内容以外の質問も多いので、楽しいサイトだと思います。

Python Code Reading 04

Python Code Reading 04に参加しました。Python Code Readingとは、Pythonのモジュールを読んで達人の技術を学ぼうという集まりです。今回も新橋にあるミラクルリナックスさんのセミナールームで行われ、参加者は会場いっぱいの40人ほどでした。

テーマはstringモジュールのTemplateクラスで、fgshunさんが発表されました。

Templateクラスは、文字列の雛型とそれへの埋め込みを扱うシンプルなクラスで、Python組み込みの文字列フォーマッティングと、ループやマクロ定義や継承などを実装する高機能なテンプレートエンジンの隙間を埋める存在です。

記法としてはUnixライクなプレースホルダが特徴なのですが、定義を一部変更することもでき、このカスタマイズにメタクラスの機構が使われています。最後の質疑ではこの設計の妥当性が話題になりました。

メタクラスを使うことによって、カスタマイズした正規表現の構築を、インスタンス生成時ではなくクラスの定義時に行うことができるというメリットがあるのでは、と私が発言したのですが、それに対して、クラス属性として直接渡してしまえば同じことができるという指摘がありました。確かにそうですね・・・。メタクラスを使ってクラスそのものの定義としてカスタマイズできたほうがすっきりと書ける気はしますが。

また、Templateクラスの文字列置換メソッドであるsubstituteメソッドとメタクラス内の正規表現定義とのあいだには依存関係があり、メタクラスに定義されている正規表現をTemplateクラスに移したほうが良いのではないかという意見がありました。

細かいテクニックの他に、小規模なコードでも設計の勉強になるというのがこの勉強会の良いところです。

勉強会の後は30名弱が残ってピザパーティーをしました。こちらも楽しかったです。

Plone導入の理由、チューニングの方針

このサイトはPython製のCMS、Ploneを使って構築しました。

私がPythonを好きというのもあるのですが、ページ編集などの高機能さと、COREBlog2などのアドオンプロダクトが豊富なことがPloneの魅力です。今回は特にブログを複数置こうと思ったことと、技術者ではないメンバーも簡単に操作できるようにということでPloneを選びました。

Ploneはその高機能さや保守性の高い設計と引き替えに動作が遅いという話もよく聞きます。確かに普通にインストールして使っている分にはもっさりした感じになります。今回の場合は、外部からのアクセス=非メンバーによるアクセスに素早くレスポンスを返すことができれば良いと考え、そこに絞ってチューニングしようと考えました。

サーバ構成

サーバのハード構成は以下のようになっています。海外のVPSを利用しており、メモリは正直言って貧弱です。本来Ploneを使う場合はもう少しメモリを積んでおくべきだと思います。

  • Core2 Quad 2.4GHz
  • 512MB RAM

ソフトウェア構成は以下のようになっています。

  • CentOS 5
  • Apache 2.2系
  • Plone 3.0系

Apacheの設定

mod_proxyでPloneにリクエストを転送します。メモリに余裕もないことから、MPMにはworkerを使用しました。ただし、それほど多くのアクセスがあるわけではないので、スレッド数などの値はデフォルトより低めに設定しました。静的ファイルを効率よく返すために、KeepAliveはOnにしています。

また、mod_cacheでCSS、画像などの各種静的ファイルをキャッシュしています。Squidなどのプロキシサーバを利用するケースもよくあるようですが、サーバリソースに余裕がないこともあって今回はmod_cacheを使いました。動的ページのうち、アクセス数の多いトップページだけはキャッシュ対象にしたかったのですが、ルートを指定するとそれ以下が全て対象になってしまうため、うまい指定方法が分かりませんでした。

Ploneの設定

Ploneを使っていて遅い印象を受ける要因の一つが、ページがロードされてCSSが適用されるまでに少しの間があることです。Firefoxの場合などでは、CSSの適用されていない状態が最初に表示されてしまいます。そこで、デバッグ時はdisabledにしていますが、ZMIのportal_cssでキャッシュとマージを忘れずにEnabledに戻し、前述のようにApacheにもキャッシュさせます。

また、CacheFuというキャッシングプロダクトをインストールすれば、全体に動きが速くなります。

チューニングの結果

ローカルでApache Benchを使った簡易ベンチマークテストでは、動的ページに対して3リクエスト/秒程度だったところが、40リクエスト/秒程度まで向上しました。ただしCOREBlog2のページだけは、CacheFuが適用されていないのか、変化が見られませんでした。また、ロゴなどの小さな画像は、直接Ploneにリクエストすると250リクエスト/秒程度のところが、Apache+mod_cacheを通すことで数千リクエスト/秒に高速化できました。

手元で使っているMacBook AirのFirefoxでFirebugにより計測したところ、各ページ1秒前後のロード時間に抑えることができています。

その他: RSS出力

Ploneは各ページでRSSの出力を設定できるのですが、最初設定方法が分からなくて困りました。

Zope Management Interfaceから、Ploneサイト -> portal_actions -> object -> syndicationと辿って、Visible?にチェックをつけると、Ploneの各ページにRSSタブが表示されるようになります。最初からオンになってればいいような気がします。

その他: COREBlog2のカテゴリポートレット

here.getCategoryCount(obj.Title)の箇所でUnicodeDecodeErrorが出て、うまく表示できませんでした。

調査してフィードバックできればよいのですが、時間がない & 内部についてちゃんと把握できていないので、この処理が行われているエントリのカウント部分を外すことで回避しました。

 

以上、特別変わったことはしていませんが、Ploneの導入メモでした。

参考書籍

Plone 完全活用ガイド (Gihyo Expert Books): 柴田 淳, 鈴木 たかのり, 木下 文史, 他, ウェブコア(株)

What is this blog?

マリーチで企画・開発を担当している道須です。会社のサイトでブログを書くことになりました。

私は大学は文学部で、海外小説とか哲学のような本を読むのが好きな昭和風の文学青年だったのですが、その後いつのまにかウェブ系のエンジニア、プログラマになっていました。

子供の頃にはMSXというおもちゃのコンピュータでBASICをかじったりしていたこともありましたが、技術は基本的に独学で、社会に出てからその都度周りにいた人に教えてもらってきました。その辺はよくあるパターンです。ちょっと変わったことがあるとしたら、私の場合は検索エンジンや自然言語処理のような分野で仕事をすることになり、その分野では周りに詳しい人が少なかったので自分で調べたり考えたりしながらやってきたことです。

しかし基礎的なところを含めて勉強不足を日々感じているので、最近では勉強会や技術系のイベントにもなるべく顔を出すようにしてます。すごいなと思う人がたくさんいます。そういった勉強内容をこのブログにアウトプットしていこうと思います。

他にはこんなことを書きたいと思ってます。

  • 海外を含むウェブサイトの情報、感想。いつも何か面白いものがないか探しているので。
  • 技術的なメモ、備忘録。
  • 会社でのサービス企画、構築についてのお話。

週二、三回を目標にマイペースで更新していきます。