その数学が戦略を決める Super Crunchers

R1050460

その数学が戦略を決める-イアン・エアーズ

原題 Super Crunchers: Why thinking-by-numbers is the new way to be smart.
なぜ数学的思考が新たな知性への道なのか?

図書館で借りておもしろかったので、Amazonで購入。

回帰分析やニューラルネット、データマイニング、無作為抽出、ベイズ確率などを使って世界を定量的に把握しようとするSuper Crunchers:絶対計算者の話。計算方法もそれを適用する分野も多岐に渡るので読んでいて飽きない。ヤバイ経済学が分析結果から得られる結論のヤバさにフォーカスしているとすれば、こちらはその一歩手前の分析で使うツールを面白く見せてくれる。訳者の山形浩生氏があとがきで参考文献と感想あげているのがかなり参考になります。
(あとがきが参考になるのは、書籍 数学で犯罪を解決する のほうでした)

統計学で使われる多くのツールは18世紀ごろには発明されていて、ベイズ定理(1763年)なんかも新しいものではないけど、21世紀になって計算機とネットの高速化、大容量化を背景に応用範囲がめちゃくちゃ広がってるんだぜ。ということなんだと思う。

  • 葡萄がワインになる前からビンテージワインの将来価格を正確に予測する
  • 出会い系サービス大手は回帰分析を使ってうまくいきそうなカップルをマッチングする。
  • カジノでは客の居住区の年収、人種、年齢、プレイ内容と勝敗を計算して、長期的にできるだけ多く金を使わせるよう対応する。
  • まだ監督も配役も決定していない脚本をニューラルネットにかけてその興行収入を誤差1億円程度で予測する。
  • クレジットカードの使用状況と返済状況から離婚率や自動車の事故率を算出できる。
  • Amazon.comは客によって販売価格を変える実験を行っている(現在は停止中らしい)
  • etc ..

    この本の話を友人にしたところ「興行収入を正確に予測できるなら、映画はより大衆受けするものに収束して面白くなくなるのではないか?」と言われた。これに対し著者は、収益リスクを今までよりも高い精度で判断できるのであれば、計画的な冒険(例えば4つの映画は手堅く作って、残り1本は実験的にやろう等)が可能になるのでむしろ逆だとも言っている。作れば売れる「いい時代」のように無謀な冒険で大きく当てるよりは、利に適っている気もする。冒険は常に無謀である必要はない。

    Posted: June 12th, 2010 | Author: | Filed under: 技術, | No Comments »

    Fixture + GoogleAppEngine

    fixtureをGoogleAppEngineのDataStoreテストで使う。json編

    参考 Using Fixture To Test A Google App Engine Site

    DataSetsをjson化するのにfixture.dataset.converterでdataset_to_jsonが提供されていたりもする。ただdate_created(auto_now_add=True)のようなフィールドはDataSetsで前もって値を指定できないので、ここでjson化したデータを、実際(date_createdの付いた)のjsonのレスポンスと比較しても同じにはならない。

    .zshrc

    gaedir=/usr/local/google_appengine
    if [ -d $gaedir ] ; then ;
        export PATH=${PATH}:$gaedir
        export PYTHONPATH=${PYTHONPATH}:${gaedir}:${gaedir}/lib/antlr3:\
    ${gaedir}/lib/cacerts:${gaedir}/lib/django:${gaedir}/lib/ipaddr:\
    ${gaedir}/lib/webob:${gaedir}/lib/yaml/lib
    fi;
    
    $ source ~/.zshrc
    $ pip install WebTest
    $ pip install nose
    $ pip install NoseGAE
    

    app.yaml

    application: sampleblog # _ はapplicationの識別子として使えないので注意
    version: 1
    runtime: python
    api_version: 1
    
    handlers:
    - url: /.*
      script: blog.py
    

    blog.py

    #coding:utf-8
    import logging
    from google.appengine.ext import webapp
    from google.appengine.ext.webapp.util import run_wsgi_app
    from google.appengine.ext import db
    from django.utils import simplejson
    
    
    class Entry(db.Model):
        title = db.StringProperty()
        body = db.TextProperty()
        date_created = db.DateTimeProperty(auto_now_add=True)
    
    
    class Comment(db.Model):
        entry = db.ReferenceProperty(Entry)
        comment = db.TextProperty()
        date_created = db.DateTimeProperty(auto_now_add=True)
    
    
    class EntriesHandler(webapp.RequestHandler):
        def get(self):
            self.response.headers['Content-Type'] = 'application/json;charset=utf-8'
            entries = []
            for entry in Entry.all():
                comments = []
                for comment in Comment.all().filter("entry =", entry):
                    comment_dict = \
                        dict(comment=comment.comment,
                             date_created=comment.date_created.isoformat())
                    comments.append(comment_dict)
                entry_dict = dict(title=entry.title,
                                  body=entry.body,
                                  date_created=entry.date_created.isoformat(),
                                  comments=comments)
                entries.append(entry_dict)
            json = simplejson.dumps(entries, indent=True)
            #logging.info(json)
            self.response.out.write(json)
    
    
    routing = [('/entries', EntriesHandler)]
    
    application = webapp.WSGIApplication(
            routing,
            debug=True)
    
    
    def main():
        run_wsgi_app(application)
    
    if __name__ == '__main__':
        main()
    

    tests/datasets.py (http://fixture.googlecode.com/hg/fixture/examples/google_appengine_example/tests/datasets.py)

    from fixture import DataSet
    
    
    class EntryData(DataSet):
        class great_monday:
            title = "Monday Was Great"
            body = """\
    Monday was the best day ever.  I got up (a little late, but that's OK) then I ground some coffee.
    Mmmm ... coffee!  I love coffee.  Do you know about
    <a href="http://www.metropoliscoffee.com/">Metropolis</a> coffee?  It's amazing.  Delicious.
    I drank a beautiful cup of french pressed
    <a href="http://www.metropoliscoffee.com/shop/coffee/blends.php">Spice Island</a>, had a shave
    and went to work.  What a day!
    """
    
    
    class CommentData(DataSet):
    
        class monday_liked_it:
            entry = EntryData.great_monday
            comment = """\
    I'm so glad you have a blog because I want to know what you are doing everyday.  Heh, that sounds
    creepy.  What I mean is it's so COOL that you had a great Monday.  I like Mondays too.
    """
    
        class monday_sucked:
            entry = EntryData.great_monday
            comment = """\
    Are you serious?  Mannnnnn, Monday really sucked.
    """
    

    load_data_locally.py
    (http://fixture.googlecode.com/hg/fixture/examples/google_appengine_example/load_data_locally.py)一部修正

    import sys
    import os
    import optparse
    from fixture import GoogleDatastoreFixture
    from fixture.style import NamedDataStyle
    
    
    def main():
        p = optparse.OptionParser(usage="%prog [options]")
        default = "/tmp/dev_appserver.datastore"
        p.add_option("--datastore_path", default=default, help=(
                "Path to datastore file.  This must match the value used for "
                "the same option when running dev_appserver.py if you want to view the data.  "
                "Default: %s" % default))
        default = "/tmp/dev_appserver.datastore.history"
        p.add_option("--history_path", default=default, help=(
                "Path to datastore history file.  This doesn't need to match the one you use for "
                "dev_appserver.py.  Default: %s" % default))
        default = "/usr/local/google_appengine"
        p.add_option("--google_path", default=default, help=(
                "Path to google module directory.  Default: %s" % default))
        (options, args) = p.parse_args()
    
        if not os.path.exists(options.google_path):
            p.error("Could not find google module path at %s.  You'll need to specify the path" % options.google_path)
    
        groot = options.google_path
        sys.path.append(groot)
        sys.path.append(os.path.join(groot, "lib/django"))
        sys.path.append(os.path.join(groot, "lib/webob"))
        sys.path.append(os.path.join(groot, "lib/yaml/lib"))
    
        from google.appengine.tools import dev_appserver
        import blog
        from tests import datasets
    
        config, explicit_matcher = dev_appserver.\
            LoadAppConfig(os.path.dirname(__file__), {})
        dev_appserver.SetupStubs(
            config.application,
            clear_datastore=False,  # just removes the files when True
            datastore_path=options.datastore_path,
            history_path=options.history_path,
            blobstore_path=None,  # 追加 KeyError: 'blobstore_path' を避ける
            login_url=None)
    
        datafixture = GoogleDatastoreFixture(env={'EntryData': blog.Entry,
                                                  'CommentData': blog.Comment})
    
        data = datafixture.data(datasets.CommentData, datasets.EntryData)
        data.setup()
        print "Data loaded into datastore %s" % \
            (options.datastore_path or "[default]")
    
    if __name__ == '__main__':
        main()
    

    tests/test_entries.py

    #coding:utf-8
    import unittest
    from fixture import GoogleDatastoreFixture
    from webtest import TestApp
    import blog
    from datasets import CommentData, EntryData
    from django.utils import simplejson
    
    datafixture = GoogleDatastoreFixture(env={'EntryData': blog.Entry,
                                              'CommentData': blog.Comment})
    
    
    class TestListEntries(unittest.TestCase):
        def setUp(self):
            self.app = TestApp(blog.application)
            self.data = datafixture.data(CommentData, EntryData)
            self.data.setup()
    
        def tearDown(self):
            self.data.teardown()
    
        def test_entries(self):
            response = self.app.get("/entries")
            assert simplejson.dumps(EntryData.great_monday.title) in response
            assert simplejson.dumps(EntryData.great_monday.body) in response
            assert simplejson.dumps(CommentData.monday_liked_it.comment) \
                in response
            assert simplejson.dumps(CommentData.monday_sucked.comment) \
                in response
    

    Create custom datasets.

    $ ./load_data_locally.py --datastore_path=./my.datastore
    

    Run server with custom data.

    $ dev_appserver.py . --datastore_path=./my.datastore
    

    Run tests.

    $ nosetests -v --with-gae
    
    test_entries (tests.test_entries.TestListEntries) ... ok
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.296s
    OK
    
    Posted: May 26th, 2010 | Author: | Filed under: 技術 | Tags: , , , , , | No Comments »

    SnowLeopard Screeshot tip

    command + shift + 4 でスペースキーを押すと、カーソルの下にあるウィンドウのスクリーンショットが撮れる。がデフォルトでは影が入っていてあまり使い勝手が良くない。

    デフォルト

    terminalから以下のコマンドでshadowを切れる

    $defaults write com.apple.screencapture disable-shadow -bool true
    $killall SystemUIServer
    

    TIP: Change default screen shot filenames, format and location | Snow Leopard Tips

    Posted: May 24th, 2010 | Author: | Filed under: 技術 | Tags: , , , | No Comments »

    Twitter OAuth on GoogleAppEngine

    Google App EngineでTwitter OAuthを使う。
    自分のタイムラインを取得してtweetできるまでのサンプル。

    参考
    tweepyでtwitterの3-legged OAuth認証を試してみた(GoogleAppEngine)

    コードのなかで使用しているsimple_cookieは
    Google Cookbook – Google App Engine A simple Cookie class のもの。

    注意する点は
    Twitter application settingでcallback URLを正しく設定すること。
    スクリーンショット(2010-05-23 2010-5-23-Sunday 18.00.31)
    callback URLに127.0.0.1を指定しているからかもしれないけど、なにも入力しないと
    TweepError: HTTP Error 401: Unauthorized になる。

    tweepy
    はapp engineのディレクトリにモジュールのディレクトリをコピーして使った。

    以下サンプルコードと実行

    Read the rest of this entry »

    Posted: May 23rd, 2010 | Author: | Filed under: 技術 | Tags: , , , , | No Comments »

    アノニマスケイプこんにちは二十世紀

    Najimiを知る友達に言われてamazonで注文。新品なのになんで名前書いてあるんだよと思ったら
    作家の直筆サインだった。客死した身元不明の人と、その死んでいた場所を百年分記録した写真集。

    読んだ(というか観た)後味は孤独のグルメにとても近い。人と場所の記録・記憶にまつわる作品。

    R0019511.JPG

    細川文昌 / アノニマスケイプ:こんにちは二十世紀

    “行旅死亡人” という法律用語をご存知だろうか。旅行中などに死亡したが、住所氏名を判別できるものを所持していなかったがため、引取り手の不明な人のことを指す。その場合、死亡した当地の当該市町村は、死亡日時、死亡現場やその状況と共に、死亡した人の推定年齢、身体特徴や、服装、所持品などを記し、引取り手を捜すことを目的とした、公告を掲示することが、法律で義務づけられている。

    この法律は1899年 (明治32年) に施行され、以来、数多の公告が、官僚たちの手により記されてきた。そして、その “行旅死亡人公告” という、冷徹でありながらも、詳細微に入った (詳細すぎて、ときに滑稽でさえある) テキストに着眼した写真作家がいる。彼は、法律が施行されて以降の1901年 (明治34年) から、2000年(平成12年) までの100年間に公示された、数ある公告の中から、1年につき1件、計100件を抽出。そして、それぞれの公告のコピー・テキストに、“行旅死亡人” の最後となった場の風景 (写真) を並列する。

    Posted: May 13th, 2010 | Author: | Filed under: | Tags: | No Comments »

    Fixture + SQLAlchemy

    Using LoadableFixtureを読む

    A DataSet class is loaded via some storage medium, say, an object that implements a Data Mapper or Active Record pattern. A Fixture is an environment that knows how to load data using the right objects. Behind the scenes the rows and columns of the DataSet are simply passed to the storage medium so that it can save the data.

    DataSetクラスはなんらかの格納媒体(以下ORMapper)例えばDataMapperやActiveRecordパターンで実装されたオブジェクトによってロードされる。Fixtureは正しいオブジェクトを使って、どのようにデータをロードするかを知っている環境だ。内部的にはDataSetの行と列は単純にORMapperに渡されて、ORMapperがデータを保存する。

    The Fixture class is designed to support many different types of databases and other storage media by hooking into 3rd party libraries that know how to work with that media. There is also a section later about creating your own Fixture.

    Fixtureクラスは多くの異なるタイプのデータベースやストレージメディアに対し、どのように接続するかを知っているサードパーティーのライブラリにフックすることで、それらをサポートするようデザインされている。後のほうに独自のFixtureを作るセクションがある。

    Fixture is designed for applications that already have a way to store data; the LoadableFixture just hooks in to that interface.

    Fixture はデータの格納方法を既にそなえたアプリケーションのためにデザインされている。LoadableFixture はただそのインターフェースにフックしているに過ぎない。
    —————-
    以下An Example of Loading Data Using SQLAlchemy を参考にデータセットとテストコードを書いた。

    Read the rest of this entry »

    Posted: May 13th, 2010 | Author: | Filed under: 技術 | Tags: , , , , | No Comments »

    アーキテクチャの生態系を読んだ

    R1050276.JPG

    友達から聞いて買いました。消化中。

    山形浩生氏が、当初ブログに否定的展望をもっていたが現実は違っていた。という話を例示する著者。しかし今度は著者がTwitterは日本であまり受け入れられないだろうと予測している(2008年当時)。2010年の今から見れば、図らずもまさにアーキテクチャの進化を予測する困難さを示しているようで面白かった。

    blogがまだウェブログとかブロッグとかいわれていた頃、技術的には新しいのものではないという理由でその価値に懐疑的だったひとも結構いた。けど実際には技術というよりはユーザビリティーの革新性から日本でも今では完全に一般化している。Twitterについて言えば、2008年11月のアメリカ大統領選や2009年6月のイランの選挙を経て日本のマスメディアでも露出が大きくなった状態については、本書もすこし予想がズレた結果になっている。

    生態系の進化について考えるときに、まず突然変異があり、そのあとそれらが複雑な環境によって機能主義的に淘汰・存続してくという二段のプロセスを分けて考えるというのは大事だなと思った。この考え方だと

    A.初期段階では偶然の産物がボコボコでてきているだけなので、それらから未来の生態系を予測することなど不可能に近い。

    B.にもかかわらず現在から過去を見た場合には淘汰されず存続した結果だけが前景化するので、あたかもそういう必然的な道筋があったように錯覚しがち。

    というジレンマをうまく説明できる。

    これを書いて2006年偉大なプログラマー達への
    コンピュータ言語の次のBig Thingはなにか? X指向?Y言語?量子コンピューター?なに?
    という問いに対してGuido Van Rossum(Pythonの作者)の回答が面白かったのを思い出した。

    Stifflog – Stiff asks, great programmers answer

    Sorry, I’m not much of a crystal ball person. I predicted CGI about 5 years after it had been invented. :-)

    ごめん、占いはヘタなんだよ。僕はCGIが考案されるのを、その5年後に予測したことがあるしね。 キリッ

    Posted: May 10th, 2010 | Author: | Filed under: 技術, | Tags: , , , , , | No Comments »

    DBまわりのテストを簡単にするfixture

    fixutre というpythonモジュールは、テストに関するDBの面倒をみてくれる様子。
    個人的にはteardown, setupをリッチに一元管理できるという感覚で捉えています。
    http://farmdev.com/projects/fixture

    • テストDBにデータをロードし、アサーションするときに簡単に参照したい
    • 外部キーとリレーションのあるデータを自動的にロードし、integritty errorなしに簡単に削除したい
    • IDではなく意味のある名前で接続された行を参照したい
    • auto-incrementを気にしたくない
    • バグを検証するためにDBの実際のデータにSQLを発行し、環境を再構築したい
    • ファイルについてファイルシステムに依存せずテストしたい

    意訳するとこんなとき便利らしい。

    Loading and referencing test data

    There are a couple ways to test a database-backed application. You can create mock objects and concentrate entirely on unit testing individual components without testing the database layer itself, or you can simply load up sample data before you run a test. Thanks to sqlite in-memory connections, the latter may be more efficient than you think.

    But it’s easy enough to insert data line by line in code, right? Or simply load a SQL file? Yes, but this has two major downsides: you often have to worry about and manage complex chains of foreign keys manually; and when referencing data values later on, you either have to copy / paste the values or pass around lots of variables.

    The fixture module simplifies this by breaking the process down to two independent components:

    DataSet
    Defines sets of sample data
    Fixture
    Knows how to load data

    DBアプリをテストする方法はいくつかある。DBのレイヤーそのもののテストはせずに、モックオブジェクトをつくって完全に個々のコンポーネントのユニットテストに集中するとか、または単純にテストを走らせる前にサンプルデータをロードする手もある。sqliteのin-memory 接続のおかげで、後者は思ったより効果的。

    でも一行一行コードにデータを入れていくのってホントに簡単か?それかシンプルにSQLファイルをロードしてまう? いいけどでもこれは2つの大きな欠点がある。しばしば外部キーの連鎖に配慮したり、手で管理したりしなければならない。そしてその後にデータの値を参照するときに、値をコピペするか、たくさんの変数をたらい回しにしなければならない。

    fixture moduleはこれを、二つの独立したコンポーネントにそのプロセスを分けることで単純化している。

    DataSet
    サンプルデータのセットを定義
    Fixture
    データのロードの仕方を知ってる

    (意訳終わり)

    個人的に使いたい状況は、例えばUserとEmailの2つのテーブルがあるとする。Userのあるレコード(仮にbob)を削除すると、bobの持つメールアドレスbob@example.com, bob@bob.netもEmailから消したい。ORMapperのセッティングを間違えると、これがメールアドレスを削除するとユーザが削除されたりして、とても危険(実際にあった)なのでこういう基本的なところは日々のテストで確認したい。

    Posted: May 10th, 2010 | Author: | Filed under: 技術 | Tags: , , | No Comments »

    Windows rescue disk

    親のPCを再インストールして自前のリカバリディスクを作った.

    Macrium Reflect Free Edition

    http://www.macrium.com/ReflectFree.asp

    Gigazine http://gigazine.net/index.php?/news/comments/20090206_macrium_reflect_free_edition/

    今回はこれを使って、CドライブのバックアップをDVDに直接焼き、さらにLinuxベースのレスキューCDを作った。(有料版はWindowsのブートメニューから復元できるらしくレスキューCDは不要らしい)。

    無料版の復旧手順は

    1.レスキューCDからブート

    2.レスキューCDを取り出し、バックアップイメージを焼いたDVDをいれてリストア。

    テストのためHDDのWindowsをubuntuで上書きして、リカバリディスクからリストアしたところ見事成功。だいたい30-40分でDVDに焼いた環境がきちんと再現できた。

    その他バックアップの際に役にたったソフトウェア

    OverDisk Windowsのディスク使用量を視覚化する

    http://users.forthnet.gr/pat/efotinis/programs/overdisk.html

    DVD一枚4.7GBにバックアップ対象をすべて収めたかったので大きなファイルサイズのデータにあたりをつけるとき役に立った。調べてみるとC:\WINDOWS\SoftwareDistribution\Download にWindowsUpdate用にダウンロードされたキャッシュが1.2GBあったのでこれを削除した。http://pctrouble.lessismore.cc/running/softwaredistribution_download.html

    CCleaner Windowsの不要なデータを削除する

    CCleaner is the number-one tool for cleaning your Windows PC. It protects your privacy online and makes your computer faster and more secure. Easy to use and a small, fast download.

    http://www.piriform.com/ccleaner

    まとめると、Windowsの環境を整備し終えたらOverDiskとCCleanerで不要なデータを削除して、Macrium Reflect でリカバリDVDを作るという流れ。

    Posted: May 4th, 2010 | Author: | Filed under: 技術 | Tags: , , , | No Comments »

    PEP8 and pyflakes for emacs

    flymake+pep8 for emacs
    Emacs flymake-mode and python code styles PEP8 script enables you to
    have realtime checking for python coding style.
    In addition, you can check common errors with pyflakes.
    
    Combine PEP8 and pylakes to one command.
    
    /Users/k01/mypy/bin/mypychechers
    
    #!/bin/bash
    /Users/k01/mypy/bin/pyflakes "$1"
    /Users/k01/mypy/bin/pep8 --repeat "$1"
    true
    

    .emacs

    (add-hook 'python-mode-hook
              '(lambda ()
                 (flymake-mode t)))
    (load-library "flymake-cursor.el")
    (when (load "flymake" t)
      (defun flymake-pylint-init ()
        (let* ((temp-file (flymake-init-create-temp-buffer-copy
                           'flymake-create-temp-inplace))
               (local-file (file-relative-name
                            temp-file
                            (file-name-directory buffer-file-name))))
          (list "/Users/k01/mypy/bin/mypycheckers" (list local-file))))
      (add-to-list 'flymake-allowed-file-name-masks
                   '("\\.py\\'" flymake-pylint-init)))
    
    Posted: May 1st, 2010 | Author: | Filed under: 技術 | Tags: , , , , | No Comments »