2012年1月27日金曜日

JSONICを使ってみる

ちょっとJavaでJSON形式のデータを扱う必要があったので、JSONICというJSON Parserを利用して見ました。JavaのライブラリではJSON-libというのが定番らしいのだけれど、他に依存するライブラリがあったりして面倒そうだったので、とりあえず一番シンプルそうなJSONICを使いました。

僕はFacebookのGraph APIで返ってきたJSON形式のデータをJavaのオブジェクトとして取り込みたかっただけなので、decodeだけ利用しました。使い方はとても簡単で、JSONのフィールドと対応する変数とaccesserを持ったクラスを指定してやるだけ。

まず、Graph APIはユーザの情報を以下のような形で返してくれます。

{
  "id": "123456789", 
  "name": "Foo Bar", 
  "first_name": "Foo", 
  "last_name": "Bar", 
  .....
}

で、以下のようにidとnameの変数とアクセッサを持ったクラスを定義してやります。

public class FBUser {
   private String id;
   private String name;
 
   public FBUser(){ }

   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   } 
}

そして、以下のようにJSONのデータとクラスの型を引数にしてdecodeを呼ぶと、勝手に個々のフィールドに値を入れてくれます。おそらく、リフレクションを使ってJSONのフィールド名からsetterの名前を推測しているのでしょう。例えばフィールドが'id'だったら'FBUser.class.getMethod("setId")'とかね。ちゃんとidとnameがログに出力されました。

String jsonFbUser = FBLoginUtil.getResponseFromURL(FBLoginUtil.getGraphApiUrl() + "me"  + "?access_token=" + accessToken);
final FBUser fbUser = JSON.decode(jsonFbUser, FBUser.class);  
log.info("id:" + fbUser.getId());
log.info("name:" + fbUser.getName());

このブログを書くよりは遥かに短い時間でオブジェクトとして取り込むとこまで出来てしまいました。オジサンの知らない間に世の中便利になってますな。賢い人達、いつもどうもありがとうございます。

2012年1月26日木曜日

gitを使ってみた

gitを使ってDropboxにレポジトリを作ってみた。ついでに、EGITをインストールしてEclipseからcommitとpushができるようにもしました。

最近、一人で開発を始めたのですが、ワークスペースが全部ローカルのMacに入っているので気持ち悪いと思い、Dropboxをレポジトリにしてgitを導入してみた。僕はsubversionしか使ったことないのですが最近の若者に流行りらしいのであえて。一番の違いは、serverで一元的に管理するsubversionとは対照的に、gitはすべてのコピーがマスタレポジトリのフルコピーを持っていて、ヒストリーの確認は勿論、コミットもできる分散レポジトリであるという点みたいですね。

とりあえず、Mac OS X 用のインストーラーがココにあるので、ダウンロードしてインストール。git help とコマンドを打ってみると、add/checkout/diff/commitなどsubversionで見慣れたコマンドが並んでいて一安心。

まず、user.name、user.emailをgit config コマンドで登録します。

git config --global user.name foo
git config --global user.email foo@bar.com

どうやらversion1.7.5からはレポジトリとワークスペースのディレクトリを別にする--separate-git-dirというオプションが追加されたようなのでDropboxだけでレポジトリを管理しようかとも思ったのですが、DropboxをマスタにしてLocalドライブを自分用にした方が分散レポジトリというgitの哲学に合ってるんじゃないかなぁと感じたのでそうしました。毎回マスタにPushするのはちょっと面倒かもしれないけど。


レポジトリを作るのはアホみたいに簡単で、Dropboxに適当なディレクトリを作って(e.g. $HOME/Dropbox/git_repos/MyProject.git)、そこにcdしてgit --bare init とコマンドを打つだけ。

僕はEclipseでGoogle App Engineのアプリケーションを書いているのでEGITというEclipseから使える管理ツールをインストールしました。subversionで言うsubclipseみたいなもので、ちょっと触ったところ使い方は殆ど同じなので、10分位でレポジトリ作ってcommitしてDropboxにpushするところまでできてしまいました。試しに、マスタレポジトリからgit clone で適当なディレクトリにコピーしてみたらちゃんとディレクトリ構造がコピーされました。Dropboxはディレクトリごとに他のユーザと共有とかできるはずなので、$HOME/Dropbox/git_repos/MyProject.git を他のユーザと共有すればマスタリポジトリの共有も出来ますね。

今回の作業では以下のページを参照しました。どうもありがとうございました。
Subversion ユーザーが Git を使ってみた (基本操作編)
Dropboxを利用してGitのプライベートリポジトリをつくる方法
git 1.7.5で追加されたオプションを使ってgit on Dropboxの運用を見直す
EGit/User Guide

2012年1月16日月曜日

読書日記「Web開発者のための 大規模サービス技術入門」

株式会社はてなの伊藤さん(現GREE)と田中さんという、Webに興味のある人なら名前くらいは聞いたことがあるだろう人達の書いた、「Web開発者のための 大規模サービス技術入門」というその名の通り大規模なWebサービスをどう運用していくかを説明している本です。理論的な説明だけではなく、実際にはてなで使われている運用方法などの「泥臭い」部分をかなり詳しく説明してくれているとても実践的な本でした。

この本を読んで、もし自分で大規模サービスを運用が必要になる時には絶対に自分でインフラは持たずにGoogle App Engineのようなクラウドサービスを使おうと思ってしまいました。さすがに自分でここまでする気にはならないですね…。

基本的にはパフォーマンスの問題はCPUかI/Oのどちらかがボトルネックになります。そういう時は単順にtopやsarでどちらの問題か切り分けます。どのプロセスがCPUをどれくらい使ってるかとかI/Oの待ち時間がどれくらいあるのかとかを確認すれば、だいたい目星はつくでしょう。

CPUがボトルネックの場合は以下のような解決方法があります。単純に計算量が足りないだけなので、比較的解決は簡単なようです。
  • サーバを増やして処理を分散させる。この場合はDBと違ってデータのレプリケーションなども必要無いので、比較的簡単にスケールする。
  • アルゴリズムを改善して計算量を減らす

I/O側はCPUのように、サーバの台数を増やすだけでは簡単にスケーリングできないので対応が難しいようですね。Googleが独自の分散ファイルシステムやデータベースを持っているのもそれが理由でしょう。対応の仕方としては以下の方法があるそうです。
  • できる限りキャッシュやメモリのヒット率を高めてディスクアクセスがないようにする。(メモリはディスクアクセスの10万倍以上高速)
  • プログラム変更でメモリの利用が減らせるならそうする。
  • 足りなければメモリを増やす。できないならデータを複数サーバに分散させる。
  • データベース側のスケーリングをする(最終手段)。マスタDB(書き込みを担当するDB)のスケールアウトはACIDが求められるため難しいが、テーブル毎やエントリー毎に別サーバにデータを分散させるようなトリッキーな事をすることもあるようです。TwitterもMySQLの分散とmemcachedで運用しているみたいですね。

RDBの分散やデータの圧縮の話はとても面白いと思いました。RDBのデータを分散するのにテーブル毎に別サーバに分散させたりするので(勿論できるだけ局所性を保つように分散する)、INNER JOINを使わずに複数回クエリを投げるプログラムを書いたりするらしいです。もはや、RDBではないですね。

他にも、データ圧縮をI/Oを減らすためだけとかに使ったりとか、データをページキャッシュにのせるためにアプリケーションで使われる大規模データを一度catしたりとか、面白いノウハウが載っていました。そういえば、僕のサポートしているシステムでもデータをキャッシュに入れるために、再起動するたびにウォームアップさせてるなぁなんて思いながら読みました。

後半のインフラ系の話の部分はまだ読めていないので、また後日にでも。ちらっと見た感じ、SSDを使った高速化とか面白そうだな。明日、Macbook Airが届く僕としては…

2012年1月7日土曜日

読書日記「Webを支える技術-HTTP、URI、HTML、そしてREST 」

ちょっとWeb系の技術の基本的な部分を勉強してみようと思って、「Webを支える技術」という本を読んで見ました。RESTfulな設計の大切さ、URIとHTTPの説明、ハイパーメディアフォーマットなどのWebに使われている基本技術の説明がメインで、最後に少しWebサービスの設計例が載っています。僕のような、コンピュータの基本的な知識はあって、勿論HTMLやJavascriptはある程度書いたことはあるけれども、体系的に勉強した経験がないような人間に丁度よい本でした。

本書ではRoy Fieldingが提唱したREST(Representational State Transfer)というWebのアーキテクチャースタイルを良しとしており、URI(リソース)、HTTP、ハイパーメディアフォーマットについて説明すると同時に、いかにそれらをRESTfulに利用するかについても言及しています。本書では、以下の6つの制約を合わせたアーキテクチャースタイルがRESTであり、実際のアプリケーションは必要に応じていくつかの制約を除外しながら実装すれば良いと述べています。

  1. クライアント/サーバ
  2. ステートレスサーバ
  3. キャッシュ
  4. 統一インターフェース
  5. 階層化システム
  6. コードオンデマンド

個人的には一番印象に残ったのはMethodの説明です。僕が学生時代にWebを少しかじった頃はちょうどSOAPが出てきた頃で、たしかSOAPで実装されたGoogleのWeb検索APIとかで遊んだ記憶があるのですが、今は完全にRESTに基づいてHTTPメソッドを使い分けるのが主流のようですね。5年前の僕がしていたPOSTだけですべての処理をこなすなんていう処理は完全なるアンチパターンのようですね。HTTPには以下の8つのMethodが用意されており、個々の役割は決まっているので用途に応じて使い分けるべきらしいです。
  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • OPTIONS
  • TRACE
  • CONNECT

後はHTTP、URIやデータフォーマット(HTML、JSON、microformats、Atom)の説明や、通信プロトコル、ヘッダー、ステータスなどのリファレンス的な情報などの説明もあり、基本的な技術をおさらいするのにはとても便利でした。


2012年1月5日木曜日

ソーシャルゲームで遊んでみた

MobageやGREEなどのソーシャルゲームが流行っているようなので、どのようなものかと興味本位でちょっと遊んで見ました。とりあえず、以下にリストアップしたものをチョコチョコやってみました。

Mobage
怪盗ロワイヤル
忍者ロワイヤル
大熱狂プロ野球カード

GREE
FIFA
ドリランド
Gantz
クリノッペ

どれもゲームシステムはかなり似通っているという印象を受けました。どのゲームもガチャでカードを入手して、ミッション(クエスト)でレベルを上げたり、他のプレーヤーとバトルをするという楽しみ方ですね。で、ガチャとアイテムの課金で収益をあげると。これ、上手くやったらソーシャルゲームフレームワークみたいなものを作って、中身のコンテンツを差し替えるだけで色々なゲームが作れるようになってしまうのではないだろうか。ていうか、もうあるのかもね。少なくとも、コードの大部分は使いまわせるはず。

以下、キーワードの説明。

カード
「ガチャ」でカードを入手。無料ガチャと有料ガチャがあり、だいたい一回100円(ノーマル)か300円(レア)でガチャれる。各カードには攻撃力、防御力などのパラメータがある。基本的にはレアカードの方が強い。カードは合成して強くしたりもできる。

ミッション(クエスト)
基本的には「ミッションの実行」というボタンを押していると、カードを入手したり、レベルが上がったりする。たまにボスなどとのバトルになったりもする。実行するたびに行動ポイントを消費して、それがなくなると数時間回復を待つ、もしくはアイテムを使って回復できる。

バトル
他のプレイヤーとバトルができる。勝つと相手のアイテムを奪える。ボスバトルなどでは他のプレーヤーと協力して戦うこともできる。殆どのゲームではバトルは勝手にコンピュータが行う。バトルではチームメンバーの選択や配置などの戦略的な要素もそれなりにあるのだが、バトルの中身はスキップして結果だけを表示するゲームも多数あります。

アイテム
消費したパラメータを回復するアイテムとか、宝を守るアイテムとかがある。100円くらいで買える。

ゲームシステムがここまで似ていると、レアカードを強くしたりアイテムを集めたりというコレクション的な要素で差をつけるんでしょうね。後はユーザ間のコミュニケーションなどもアクセントになっていると思うのだけれども、そこまではやりこめませんでした。

2011年11月30日水曜日

読書日記「その数学が戦略を決める」

イアン・エアーズの「その数学が戦略を決める」という本を飛行機の中で一気に読んで見ました。統計解析やデータマイニングが如何にして応用されているかを述べた本です。実際の統計手法に関しては殆ど説明していないので、数学が苦手な人にでも簡単に理解できるはずです。

本書では統計や、データ分析に基づいて答えを求めることを「絶対計算」と定義しています。そして経験と直感に頼る専門家の意見よりも、「絶対計算」の方が優っているという主張をしています。専門家の意見と統計とでどちらの意見が正しかったかという例をいくつも示し、人間は感情や先入観に左右されるため、ほぼ例外なく絶対計算が勝つと述べています。

まず、過去の大量データを利用し、様々な要因がどのような結果に繋がるかを分析する「回帰分析」により、以下のような分析ができ、それらが専門家の意見に勝ったという例を挙げています。
  • ワインの値段を回帰分析で判断
  • 野球選手の価値をデータで判断
  • カジノでギャンブラーがいくら損してもリピートしてくれるか

また、大量の過去データがない場合でも、母集団から無作為にグループ分けをして、どのような違いが起こるか検査する、「無作為抽出テスト」をすることにより、以下のような判断ができると説明しています。
  • AdSenseで複数のタイトルのうち、どのタイトルのクリック率が高いかテスト
  • 金利を下げるのと、DMの広告に微笑む女の子の写真を使うのと、どちらが新規融資顧客開拓に有効か

また、この例のように、国民から無作為にサンプルを選んで、政策の有効性を検証することができるとも述べています。

  • 失業者に求職支援をするのは有効か?->求職支援をした失業者には、その出費を上回る失業手当削減と税収が得られた

さらに、著者は情報処理の発達により以下の例のように専門家の仕事が絶対計算により置き換えられ、人間の役割は絶対計算のための仮説検証の仕事が主になっていき、専門家の地位が下がっていくと考えています。そのため、当然ですが専門家達は大きな反発をしているそうです。
  • 医療データベースによる臨床医師の仕事の単純化
  • ダイレクトインストラクションによる教師の仕事のマニュアル化
  • 映画のシナリオさえニューラルネットワークによって判断されてしまう。(エパゴギクス社の例)

「絶対計算」という言葉はなんだか曖昧で好きではないのだけれども、統計やデータ処理に基づいた意思決定が専門家の直感より信頼できるという点は私も賛成です。情報処理の発達によって、今後もどんどんと今まで専門家が担っていたような領域に侵食していくようなことも容易に想像できます。

ただ、個人的には、データ分析などをするにしても、分析方法の決定(回帰分析の変数設定など)には専門家の関わる余地は大いにあると思います。ある特定分野への専門知識を持ち、基本的な統計知識をもった人が必要とされていくと考えられます。私が先行していた言語処理や、今の仕事の金融などの分野ではそれが当然のように行われているのですが、今後は政治、法律、医療など様々な分野に幅広く応用されていくのでしょう。

2011年10月10日月曜日

某CTOと面談

最近、知り合いの紹介でとあるインターネット企業のCTOと面談をさせて頂く機会を得ることが出来ました。Web上で保険などの商品を比較や購入できるようなサービスを提供している、技術部門は20人程度の中規模な会社です。会社の業務内容や環境について分かりやすく教えていただくことができ、とても有意義な面談でした。

会社の環境としては、今僕が働いている環境とは正反対のようでした。簡単に言うと自由で自分でなんでもやる。開発環境にソフトウェアをインストールするような権限すらない僕とは反対で、root権限があるのは当然でハードウェアの設置まで自分たちでしてしまったりするそうです。一週間以上前にリクエストを上げて上司の承認を得て計画通りにリリースしなければならない僕とは違い、一日に複数回リリースをしてしまうこともあるそうです。仕事内容もある程度自分の興味に応じて決められるようです。お会いした方は研修や海外展開のためにかなり頻繁に海外出張をされているようで羨ましい限りでした。

話をして一番面白いと思ったことは、ある特定のユーザー行動に関するデータが全く違うビジネスに使える可能性があるという事です。例えば、引越しをした人に光ファイバーなどのインターネットの勧誘をかけると成立する確率が高いそうです。後から考えると確かに関連がありそうに思えますが、このような仮説と検証を繰り返して、まだ他社が全く気づいていないルールを発見でれば、他社に先んじて一気に収益を上げられるような可能性もあります。ユーザのトラフィックは多いのに、その解析が十分にできていないような企業ではそのポテンシャルがとても高いだろうと思います。

余談ですが、僕の働いている投資銀行業界も他社が気づいていないようなルールや、マーケットの歪みを見つけ出して収益を上げるという歴史だったみたいですよね(って昔以下の本で読みました)。黒木亮さんの本はすべて読んでいますが、若干小難しいですが、ストーリーはエキサイティングだし、国際金融を理解するのにとても良いので興味のある方は是非読んでみてください。



ウイークポイントとしては、技術的な面を強みとはできていない点でしょうか。Webページも商品を紹介する程度に留まっていて、UIなどにもイマイチ統一感がないように感じます。SPSSなどの分析ツールを導入しようなどと試みているようですが、統計をある程度理解している人材がいないようで、まだ活用しきれていないそうです。

トップレベルのエンジニアがひしめくGoogleやMicrosoftのような大企業で末端のエンジニアとして働くのか、このような比較的小規模な会社で大きな権限をもって働くのか、どちらがやりがいのある仕事かって判断が難しいところですよね。自分以上の能力を持った人達に囲まれて仕事をしたいという気も強いし、自分で人を動かして新しいビジネスを作るような仕事がしたいとも思いますから。今の会社に入ってからは前者の立場で仕事をしていて、このままで良いのか疑問を持っているわけですが。

2011年9月21日水曜日

論理的な話し方

たまにはソフトスキルの事も考えてみる。Mailなどの文書にして要点をまとめたり、整理した情報をプレゼンテーションしたりというのは英語、日本語問わず比較的得意なのだけれども、普段口頭で論理的に物事を伝えるのが少し不得意だと感じています。なので、改善するために意識すべきポイントを本を読んだりWebページを見たりしながら考えて見ました。

改善余地が大いにあると思ったのは以下の点です。
  • 結論を先に言う
  • 具体的に話す(具体例を使う)
  • 余計な言い訳、前置きを言わない
  • 平常心
  • 間、抑揚、ペースを上手く使う
  • 積極的に相手の話を聞く

結論を先に言う
まず結論や主張を言う。次にその理由を説明する。さらに、必要であれば説得力を持たせるためにその具体例をあげる。最後にまとめのためにもう一度結論。以下のような構成が有名みたいですね。

結論 -> 理由 (-> 具体例) -> 結論
結論 -> 序論-> 本論 -> 結論

僕が苦手だなと感じているのが、「結論から述べる」ということ。説明から入ってしまうことが多いので、意識してできるだけ結論から話せるようにしたいと思います。ただ、自分でも答えが明確ではない事を質問されると、さすがに話しながら考えないと無理だと思う。その場合には結論が最後になったとしても、その結論に至るまでを分かりやすく論理的に導きだすことが大事だと思う。後は漠然としてでも良いので始めに結論とディレクションを伝えることかな。

あと、ミーティングなどで聞かれそうな質問はあらかじめ結論を考えておいたほうが良いでしょうね。そうすれば簡単に結論から入れるし。まぁ、それくらい考えておかないと相手に対して失礼だしね。

具体的に話す(具体例を使う)
数字を使う(かなりの確率、ではなく約80%など)、具体例を使うというのがポイントです。数字を使って話そうというのは日頃から心がけているのですが、できるだけ会話を単純にするために具体例などを省く事が多い傾向にあるので、必要に応じて上手く具体例を使って話に説得力を持たせたいですね。

余計な言い訳、前置きを言わない
「ちょっとこの件には詳しくないのですが」、などという言い訳を先に言ってしまう傾向にある。また、同じ質問などを聞かれた時に、「前にも言ったとはずなのだけれども」という軽い嫌味を言ってしまうことも頻繁にあります。これはどちらも相手の感情を害す事のほうが多い、意見を伝えるときには邪魔となる可能性があるものなので、気をつけようと思います。

平常心
どんな相手でも、落ち着いて冷静にはっきりと話す事ですね。まぁ、殆どの人がそうだと思いますが、苦手な相手や緊張する相手と話す時には、焦ってシドロモドロになってしまうことが多いです。で、さらに関係が悪くなり、余計緊張するようになり、という悪循環にもなりかねませんよね。僕は会社で苦手なトレーダーと話すときは常にこうなります。ただ、日頃から意識していれば、ある程度は改善できることだと思うので、今後意識していきたいと思います。リラックス、リラックス。

間、抑揚、ペースを上手く使う
淡々と話すタイプだと言われることがよくあります。友達と話すときはそうでもないと思うのですが、フォーマルな場で話すときや、細かい説明などをする時にその傾向がある気がします。大事なポイントだけは間をあけた後にはっきりゆっくり話すなどを意識するべきですね。

積極的に相手の話を聞く
相手の目を見る、相槌をうつ、相手のポイントを的確に言いなおすなどにより、もっと積極的に相手の話を引き出す聞き方ができるようになりたいですね。自分の興味のある話の場合にはある程度できていると思うのですが、そうでない場合にも上手く自分の興味のある話を引き出すなど積極的な聞き方ができるように心がけたいです。

まぁ、こんなものは一朝一夕で身につくものではないので、頑張って常日頃から意識するようにしないと。これだけのポイントを意識しながら話すなんてかなり難しいのだけれども。

2011年9月20日火曜日

読書日記「集合知プログラミング」

O'Reillyの「集合知プログラミング」という本を買ってみました。この本はWeb APIや簡単なPythonのスクリプトを使って最近流行っているデータマイニングを広く浅く紹介している本です。



本当はもう少し統計的な面から捉えた、Rなどで説明している本を読もうかとも思ったのですが、僕から失われたWebサービス対する「勘」のようなものを取り戻すきっかけにならないかと思い、実際に公開されているAPIなどを多く利用しているこの本を選びました。

今回は、協調フィルタリングとクラスタリングを説明した2章と3章だけ読んで見ました。


第二章「推薦を行う」

協調フィルタリング(Collaborative Filtering)の説明です。これはAmazonの行なっているユーザの購入履歴から商品を推薦する機能や、似たようなアイテムを推薦する機能などに応用されている技術です。基本的なコンセプトは単純で、ユークリッド距離や相関係数でユーザやアイテムの類似度を測った後に、その類似度を重みとした加重平均を行ない、その結果を推薦度とします。主に、アイテムベースとユーザベースの2種類の方法があるそうです。

アイテムベース: まず、アイテム間の類似性を測り、ユーザが評価(購入)したアイテムに対し、その類似度に応じた加重平均をして、推薦度を算出。

ユーザベース: まず、ユーザ間の類似性を測り、その類似度に応じた加重平均をして(勿論、似たユーザの重みが大きい)推薦度を算出。

一般に、アイテムベースだと、アイテム間の関係はユーザ間の関係ほど頻繁に変わらないので、バッチなどで前もってデータを用意しておくことができるため、データのメンテナンスは必要になるがパフォーマンスは良く、疎なデータセットに対しても強いそうです。一方、小規模で変更が頻繁に起こるようなデータに対してはユーザベースが強いそうです。


第三章「グループを見つけ出す」


この章では教師なし学習の一種であるクラスタリングについて説明しています。第二章で測定したようなアイテムやユーザ間の類似度(もしくは距離)を元にして、似たアイテムをクラスタとして集めていくという方法です。本書ではブログをクラスタリング対象とし、ブログ内の単語の出現頻度をベクトル(列)とすることによってブログ間の距離を表現するという例を用いています。階層型クラスタリングとK-mean法によるクラスタリング手法を説明しています。

階層型クラスタリング: 
まず個々のブログをクラスタとし、すべての個々のクラスタ間の距離を測り、一番近い2つのクラスタを結合し新たなクラスタとする、という処理を繰り返す。これにより、すべてのブログを階層的に並べることができます。すべてのクラスタ間の距離を測る必要があるため計算量が膨大(クラスタリング対象の数の二乗 x ベクトル数)になる。(学生の時に悩まされました。疎なベクトルに対して使えるトリッキーなベクトル圧縮や計算方法を利用した記憶があります。)ブログと単語の列、行を入れ替えても動作するが、行(単語)の数が多くなるため計算量が増し、列(ブログ)の数が減るため精度が下がる可能性が高い。

K-mean法:
まず、任意の数の重心ををランダムに配置し、それに近い単語群でクラスタを形成する。さらに、形成されたクラスタの重心から近い単語群で新たなクラスタを作るという処理を、クラスタ内の単語が変化しなくなるまで繰り返す。はじめに選択されてた重心に結果が左右されるが、個々の単語の距離を測る必要がないため高速に動作するという利点がある。

その他、形成されたクラスタの二次元座標へのプロットの方法なども解説してありましたが、今回は読み飛ばしました。


実際のWeb APIなどを利用しており、簡単なスクリプトの例によって説明しているためとても実用性の高い本だと思います。簡単なレコメンデーションシステムなら2章のコードをコピペしてしまうだけで作れてしまうでしょう。

今回は2章と3章を少し時間をかけて読み込みましたが、本書のイメージは掴めましたし、さすがに全部このペースで読んでレビューまでこなすのはヘビーなので、一度簡単に全体をポイントだけ理解しながら読みつつ、興味のある部分は改めて細かく見てみたいと思います。

で、僕から失われたWebサービス対する「勘」が多少なりとも戻ったかというと。「Amazonのこの部分の推薦はアイテムベースでを使っているだろう」とか、「この間話した携帯ゲーム会社の人が話していたHadoopのバッチ処理もこのアイテムベースの類似度データを作ってるんだな」、くらいのイメージは湧きます。でも何か応用できる分野が見つかるかと言われると、、、うーん、例えば広告のWebクリック率履歴を利用してユーザ毎にカスタマイズした広告を出すとか?いやー、そんなものGoogleとかで確実にもう実装されてるよな。もう少し訓練が必要ですね。

2011年9月12日月曜日

読書日記「Googleを支える技術」

ちょっと分散システムの仕組みについて復習してみたかったので、昔読んで面白かった本を引っ張り出してみました。Googleの大規模検索システムが、どのような仕組みで動いていいるのかを、検索エンジンのクローリングやインデクシングから分散システムのハード(データセンターなど)とソフト(データベースやデータ処理)、さらにおまけで開発手法まで説明した本です。Googleのオフィシャルな本ではないですが、Googleの大規模検索システムの概要をとても分かりやすく易しく説明しています。コンピュータサイエンスのバックグラウンドがあれば専門領域が違っても一日で理解できるくらいの内容です。




今回は分散処理の仕組みだけチェックしておきたかったので、3章の「分散ストレージ」と4章の「分散データ処理」の部分を中心に読みました。Googleのシステムはデータやその処理を複数のコンピューターに分散することによって高速化やデータの扱う大規模化を図っています。また、処理を分散させるためのデータのコピーや、ハードウェアが壊れた時のフェイルオーバー機能をもたせており、2章と3章ではそれら仕組みが説明されています。

3章の「分散ストレージ」ではGFS、Big TableとChunkという3つの分散ストレージを紹介し、データの分散方法や、多重化されたデータベースに対するアップデート、エラー時の対応などが説明されています。

GFS
ハードディスク上のデータの大容量化、分散化を可能にする技術です。チャンクと呼ばれる細かい単位に分けられ、マスタによって場所などが保持される。データの読み込みはマスタにデータの場所を問い合わせるのみで簡単に行うことができる。ただ、書き込み時にはロック機能がないため不整合が起こる可能性がある。その代わり、ファイル末尾にレコード追加するような機能を備えており、これだとアトミックな操作はできるが同じデータを重複して書きこむ可能性もある。読み込み、書き込みともにスケールアウトするが、書き込み時にはデータ多重化のためにチャンクのコピーを伴うため読み込みより時間がかかる。

Big Table
ある程度構造化された大規模データを扱うためのテーブル。他のテーブルとのリレーションは持たないが、フィールドにはどんなデータでも格納できるというデータ構造。行キーのカラムキーとタイムスタンプの3つによってデータを特定することができる。ロックは行単位でのみ可能。データはタブレットと呼ばれる単位で分散して格納され、マスタによって管理される。タブレットへの書き込み操作はmemorableというログにジャーナルされ、それがある程度のサイズになったところで新しいタブレットが作られて、タブレットの分割や結合が起こる。

Chunk
ロックとイベント通知の機能を備えた小規模データ向けのストレージ。GSFやBig Tableなどの外部リソースのロック制御や、DNSとして使われている。レプリカと呼ばれるマシンで5重に多重化されており、その一つがマスタとして働く。

4章の「分散データ処理」ではMapReduceによる分散処理の仕組みの説明や、Sanzallという簡単にMapReduceの仕組みを使うためのスクリプト言語について説明しています。ほぼマシン台数に応じて比例してスケールするというかなり優秀な結果がでているそうです(サーバを50台から600台に増やしても1.3倍程度しかトランザクションが増加しないらしい)。

MapReduce
言わずと知れた分散データ処理技術です。データはKeyとValueのセットで扱われ、Map、シャッフル、Reduceという3つのステップにより行われます。Mapが個々のデータに対して分散して処理を行い、シャッフルが処理を終えたデータからKeyに応じてデータの並び替えを行い、ReduceがKeyごとにデータを集約し書きだすという仕組みのようです。

Sanzall
MapReduceの仕組みを使うためのとても簡単なスクリプト言語です。Map処理をスクリプト内に書き、Reduce処理はアグリゲータと呼ばれるパラメータ(Sum, Maxなど)を指定すると自動的に行われるようです。インプットとアウトプットのレコードを実行時に引数で指定すると自動的にGFS(BIG Table)からデータを読み込み、指定したMapReduceの処理を分散して行い、GFSへ結果を書き込みます。本書にいくつかプログラムの例があるのですが、使い方はとても簡単で、分散処理どころかプログラミングの経験すらない人でも簡単にデータ処理ができてしまうと思います。

MapReduceの分散処理のアイデア自体はとても単純なものだけれども、しっかりスケールアウトさせるためにどうデータやトランザクションを効率的に分散させるかであったり、エラー時や機器の故障時にも処理をとめることなくファイルオーバーさせる技術は、(本書ではコンセプトしか説明していませんが)とても複雑であることがよく分かります。その複雑な部分を隠蔽して、単純なスクリプトで扱えるようにしてしまう点には感心しますね。

本書はGoogleを支えているシステムの基本的な技術を知るにはとても良い本だと思います。完全に読み物的な本で、著者もGoogleのシステムに触れるわけではなく、コードの例が豊富にはなかったのでコードレベルでのイメージがしにくかったのがちょっと残念ですが、その辺りはHadoopをちょっと勉強してカバーしたほうがいいかもしれないですね。少なくともGFSやMapReduceに対応する仕組みがどのようなもので、どうやって使うかくらいは簡単に把握しておこうかな。