集合知プログラミングを読む - 2章

データマイニングについての勉強とLaTeXの練習を兼ねて,集合知プログラミングを写経しながら読んでみようと思う.他の文法事項とか解説してある類の入門書は実際に打ち込む気がわかないが,本書については実際に手を動かしながら読むのがよい.


集合知プログラミング


目次:

1章 集合知への招待
2章 推薦を行う
3章 グループを見つけ出す
4章 検索とランキング
5章 最適化
6章 ドキュメントフィルタリング
7章 決定木によるモデリング
8章 価格モデルの構築
9章 高度な分類手法:カーネルメソッドとSVM
10章 特徴を発見する
11章 進化する知性
12章 アルゴリズムのまとめ

写経というのは,プログラムを実際に打ち込んで挙動を確認するだけでなく,読んだ内容をLaTeXでまとめ直す行為も含む……ので,1つの章をこなすのでも結構時間がかかる.で,とりあえず2章まで終えたので,ここまでの感想など.


まず,本書はデータマイニングの話題を扱っているが,データマイニングに用いる理論(アルゴリズム)をどのようにコードに落とし込むかを示してくれる.理論的にはわかるが,実際にはどうすればよいのかわからないときの指南となる.まだ序盤も序盤なのでアレだが,数式の詳細には触れず,あまり知識は要求されない感じだろうか.また,Pythonコードで例を示しており,他言語使用者も疑似コードとして読むことができる.しかも,実際にインタラクティブ・シェルで動くわけだからCやJavaで書かれているよりも,試しやすいし,紙面的にもコンパクトで読みやすい.ただ,ページにまたがったコードのインデントレベルがわかりにくいかもしれない.もちろん,やっていることが理解できていればあまり問題にはならないとは思うが.


というよりそれ以上に問題があって.それはコードが間違っていたり,示されている実行結果と異なった結果が得られたりすること.そして,コーディング規則?が統一的でないのが疑問だったりする.

例えば,本書で最初に実装する類似性スコアを算出する関数はユークリッド距離を用いるもので,以下のようになっている.

from math import sqrt

def sim_distance(prefs, person1, person2):
    # 二人とも評価しているアイテムのリストを得る
    si={}
    for item in prefs[person1]:
        if item in prefs[person2]:
            si[item]=1

    # 両者共に評価しているものが一つもなければ0を返す
    if len(si)==0: return 0
    
    # すべての差の平方を足し合わせる
    sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2)
                        for item in prefs[person1] if item in prefs[person2]])
    
    return 1/(1+sum_of_squares)

また,本書の付録Bに数式という項があり,B.1に数式と実装コードが書かれている.


ユークリッド距離は次のように表現される(一部改).


{\it Euclidean} = \sqrt{\sum^n_{i=1} (p_i - q_i)^2}


と共に,明快な実装が示されている.

def euclidean(p,q):
  sumSq=0.0
  # 差の平方を足し合わせる
  for i in range(len(p)):
    sumSq+=(p[i]-q[i])**2
  
  # 平方根をとる
  return (sumSq**0.5)

これらを見てまず,sim_distanceは値を返すときに平方根をとっていないし,また,math.sqrtをインポートしているが,euclideanでは0.5乗(**0.5)になっているし,powerだったり2乗(**2)だったり,何故表記に統一性を与えないのか.それに変数も小文字+アンダーバーなのとキャメルスタイルなのが混在.略称だったりそうでなかったりも……これは微妙ー.


他言語使用者がPythonの特徴をおさえるときに便利なPython チュートリアルの9.10 ジェネレータ式にも書かれているように,sum()ではわざわざ角括弧で囲む必要はない.というのも含めて書き直すとこう書けるのではないだろうか:

from math import sqrt

def sim_distance(prefs, person1, person2):
    si = {}
    for item in [i for i in prefs[person1] if i in prefs[person2]] : si[item] = 1
    
    if len(si) == 0 : return 0
    
    sum_of_squares = \
        sum((prefs[person1][item] - prefs[person2][item])**2 for item in si)
    
    return 1 / (1 + sqrt(sum_of_squares))

とか勝手に修正しつつLaTeXにまとめ直してみた.この調子でやってると1冊終えるのにどれだけかかるだろうかと不安になるが,そこは辛抱.本書自体のテーマは興味深いし,LaTeXも出来るだけ使うようにしていかないと.3章以降も続けてみようと思う.ちなみにまとめ直すことによって2章は約60%のページ数圧縮を実現(ぇ


集合知プログラミング
Toby Segaran
オライリージャパン
売り上げランキング: 1894
おすすめ度の平均: 4.5
4 プログラムはいまいち
4 ようこそ、Web 2.0の世界へ
5 知的好奇心が刺激された!!
5 機械学習の現実世界での応用
3 私には敷居が高かったかも・・・


Pythonチュートリアル
Pythonチュートリアル
posted with amazlet at 09.04.14
Guido van Rossum
オライリー・ジャパン
売り上げランキング: 196745
おすすめ度の平均: 4.5
3 買ってはみたものの...
5 Python作者による解説書
5 中級者以上のための本