集合知プログラミング勉強会 7章(前半)
TRANSCRIPT
まずは状況設定
•アカウント登録制のWEBサイトを運営
•無料トライアル版あり
•トライアル終了時に有料ユーザーへ移行 or 離脱
•どんな特徴の無料ユーザーが有料ユーザーに移行しやすいか知りたい
•無料ユーザー登録時にユーザー情報を収集する
•その無料ユーザーが最終的に有料ユーザーになったか調べる
こんなデータが取れましたユーザーの行動と購入サービス (学習データ)リファラー 住所 FAQ読? 見たページ数 購入サービスSlashdot USA Yes 18 NoneGoogle France Yes 23 PremiumSlashdot UK No 21 NoneDigg USA Yes 24 Basic
Kiwitobes France Yes 23 Basic・・・その他9件のユーザーのデータ
そこに新規無料ユーザー来たる!
リファラー 住所 FAQ読? 見たページ数 購入サービスSlashdot USA Yes 18 NoneGoogle France Yes 23 PremiumSlashdot UK No 21 NoneDigg USA Yes 24 Basic
Kiwitobes France Yes 23 Basic・・・その他9件のユーザーのデータ
リファラー 住所 FAQ読? 見たページ数 購入サービス(直接) USA Yes 5 ???
ユーザーの行動と購入サービス (学習データ)
購入サービスのわからない新規無料ユーザーの行動(評価データ)
そこに新規無料ユーザー来たる!
リファラー 住所 FAQ読? 見たページ数 購入サービスSlashdot USA Yes 18 NoneGoogle France Yes 23 PremiumSlashdot UK No 21 NoneDigg USA Yes 24 Basic
Kiwitobes France Yes 23 Basic・・・その9件のユーザーのデータ
リファラー 住所 FAQ読? 見たページ数 購入サービス(直接) USA Yes 5 ???
ユーザーの行動と購入サービス (学習データ)
購入サービスのわからない新規無料ユーザーの行動(評価データ)
サービスを購入するのか?生データからは判断困難。
学習データから決定木を構築
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 3
no yes
※注 本章のプログラム・サンプルデータで生成される決定木は 正確には「None : 3, Basic : 1」の部分がさらに分類されます。
決定木とは
• 予測モデルの一つ
• 目的変数が同じデータがなるべく同グループに属するようデータを分類する分岐条件を表す木構造。分岐条件は説明変数によって表される。
• 目的変数:予測したい変数(「購入サービス」)
• 説明変数:目的変数の要因となる変数(「リファラ」「住所」など)
• 決定木の構成要素
• 枝(ノード):分岐条件のこと
• 葉(帰結):条件分岐を辿った結果の帰結
ref = google ?
Basic : 4
評価データの購入サービスを予測
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 1
no yes
ref = (direct)address = USA
FAQ = Yespage = 5
評価データ
評価データの購入サービスを予測
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 1
no yes
ref = (direct)address = USA
FAQ = Yespage = 5
評価データ
評価データの購入サービスを予測
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 1
no yes
ref = (direct)address = USA
FAQ = Yespage = 5
評価データ
評価データの購入サービスを予測
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 1
no yes
ref = (direct)address = USA
FAQ = Yespage = 5
評価データ
評価データの購入サービスを予測
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 1
no yes
ref = (direct)address = USA
FAQ = Yespage = 5
評価データ
Basicサービス購入者4人の帰結に到達。評価データのユーザーはBasicサービスを購入すると予測できる。
もう一度決定木を眺めてみると・・
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 3
no yes
もう一度決定木を眺めてみると・・
ref = google ?
ref = slashdot ? page >= 21 ?
FAQ = Yes ? FAQ = Yes ?
None : 3Basic : 1 Basic : 4
None : 3
None : 1 Basic : 1
Premium : 3
no yes
なぜ「リファラーがgoogleか否か」で分類するのか??
そもそも有効な分類条件とは?
①なぜリファラーがgoogleか否かで分岐すれば良いとわかるの?
リファラー 住所 FAQ読? 見たページ数 購入サービスSlashdot USA Yes 18 NoneGoogle France Yes 23 BasicSlashdot UK No 21 NoneDigg USA Yes 24 Basic
Kiwitobes France Yes 23 Basic
そもそも有効な分類条件とは?
①なぜリファラーがgoogleか否かで分岐すれば良いとわかるの?
リファラー 住所 FAQ読? 見たページ数 購入サービスSlashdot USA Yes 18 NoneGoogle France Yes 23 BasicSlashdot UK No 21 NoneDigg USA Yes 24 Basic
Kiwitobes France Yes 23 Basic
address = USA ? page >= 23 ?
None : 2 Basic : 3None : 1Basic : 2
None : 1Basic : 1
no yes no yesどっち?
そもそも有効な分類条件とは?
①なぜリファラーがgoogleか否かで分岐すれば良いとわかるの?
リファラー 住所 FAQ読? 見たページ数 購入サービスSlashdot USA Yes 18 NoneGoogle France Yes 23 BasicSlashdot UK No 21 NoneDigg USA Yes 24 Basic
Kiwitobes France Yes 23 Basic
page >= 23 ?
None : 2 Basic : 3
no yes
こっち!address = USA ?
None : 1Basic : 2
None : 1Basic : 1
no yes
購入サービスがよりきれいに分類される条件の方が良い
「きれいに分類される」を定量的に評価するために
•ジニ不純度、エントロピー
•集合に属する要素の分布のバラつき加減を表す尺度
•情報ゲイン
•分類により集合に属する要素のバラつき加減がどの程度減少したかを表す尺度
0246
None Basic Premium
集合に属する要素の分布とは・・↓
ジニ不純度とは
•集合中のアイテムの一つに、ランダムに帰結を当てはめる場合の期待誤差率
• 値が高いほど集合の要素はバラついている
• giniimpurity = Σ (P( a ) × P( a ))
• a ∈ A = {None, Basic, Premium}
• P( a ) :集合A内の要素aが選ばれる確率
• P( a ) :要素aに対して誤った帰結が当てはめられる確率
a ∈ A
ジニ不純度の計算例None : 7Basic : 6
Premium : 30246
None Basic Premiumginiimpurity = (7/16 × 9/16) + (6/16 × 10/16) + (3/16 × 13/16) = 0.6328
None : 3Basic : 1
0246
None Basicginiimpurity = (3/4 × 1/4) + (1/4 × 3/4) = 0.375
①
②
ジニ不純度を算出するプログラムdef giniimpurity(rows): total=len(rows) counts=uniquecounts(rows) imp=0 for k1 in counts: p1=float(counts[k1])/total for k2 in counts: if k1==k2: continue p2=float(counts[k2])/total imp+=p1*p2 return imp
rows →ジニ不純度計算対象のデータ集合uniquecounts(rows) →集合に属す要素の目的変数に関する 度数分布を算出
None : 7Basic : 6
Premium : 3
エントロピー
•集合中の無秩序の量 (p161 より引用)
• 値が大きいほど集合は無秩序。
• entropy = -1 × Σ(P( a ) × logP( a ))
• a ∈ A = { None, Basic, Premium }
• logの底は2
a ∈ A
エントロピーの計算例None : 7Basic : 6
Premium : 30246
None Basic Premiumentropy = -1 × ((7/16 × log(7/16)) + (6/16 × log(6/16)) + (3/16 × log(3/16))) = 1.5052
None : 3Basic : 1
0246
None Basicentropy = -1 × ((3/4 × log(3/4)) + (1/4 × log(1/4))) = 0.8112
①
②
エントロピーの比較①(集合の要素数固定で比較してみた)
None : 5Basic : 1
0
2
4
6
None Basicentropy = -1 ×((5/6 × log(5/6)) + (1/6 × log(1/6))) = 0.6500
None : 3Basic : 3
0
2
4
6
None Basicentropy = -1 ×((3/6 × log(3/6)) + (3/6 × log(3/6))) = 1.0000
①
②
エントロピーの比較②(各クラスの要素数固定で比較してみた)
None : 2Basic : 2
0
2
4
6
None Basicentropy = -1 × ((2/4 × log(2/4)) + (2/4 × log(2/4))) = 1.0000
None : 2Basic : 2
Premium : 20
2
4
6
None Basic Premiumentropy = -1 × ((2/6 × log(2/6)) + (2/6 × log(2/6)) + (2/6 × log(2/6))) = 1.5850
①
②
エントロピーを算出するプログラム
def entropy(rows): from math import log log2=lambda x:log(x)/log(2) results=uniquecounts(rows) ent=0.0 for r in results.keys(): p=float(results[r])/len(rows) ent=ent-p*log2(p) return ent
rows →エントロピー計算対象のデータ集合uniquecounts(rows) →集合に属す要素の目的変数に関する 度数分布を算出
None : 7Basic : 6
Premium : 3
情報ゲイン
•集合の分類操作によるエントロピーの減少量
• 分類後のエントロピーは、真集合のエントロピーと偽集合のエントロピーの加重平均としている
• 分類操作によってどれだけ集合がきれいに分割されたかを示す
• (エントロピーではなくジニ不純度を使っても良い)
gain = [分類前のentropy] - [分類後のentropy]
[分類後のentropy] = tr × entropy(真集合) + (1 - tr) × entropy(偽集合)
(tr = [分類後の真集合要素数] / [分類前の集合要素数])
情報ゲインの計算例(分岐条件を決めて、集合を分類)
None : 7Basic : 6
Premium : 3
None : 6Basic : 5
Premium : 0
None : 1Basic : 1
Premium : 3
ref = google ?
no yes
情報ゲインの計算例(各集合のエントロピーを計算)
None : 7Basic : 6
Premium : 3
None : 6Basic : 5
Premium : 0
None : 1Basic : 1
Premium : 3
ref = google ?
no yes
1.5052
1.37100.9940
情報ゲインの計算例(分類後集合のエントロピーを加重平均で計算)
None : 7Basic : 6
Premium : 3
None : 6Basic : 5
Premium : 0
None : 1Basic : 1
Premium : 3
ref = google ?
no yes
1.5052
1.37100.9940
0.9940 × 11/16 + 1.3710 × 5 / 16 = 1.1118
情報ゲインの計算例(分類後の集合エントロピーを加重平均で計算)
None : 7Basic : 6
Premium : 3
None : 6Basic : 5
Premium : 0
None : 1Basic : 1
Premium : 3
ref = google ?
no yes
1.5052
1.37100.9940
0.9940 × 11/16 + 1.3710 × 5 / 16 = 1.1118
Gain = 1.5052 - 1.1118 = 0.3934
分類条件の決定
• 全ての分類条件で情報ゲイン計算して、情報ゲインが最大になる条件を選んでいるだけ。
• リファラーがGoogle?
• FAQ読んだ?
• 見たページ数 >= 18 ?
• 見たページ数 >= 21 ?
• ・・・etc (全部です)
• 本章のデータでは「 リファラーがGoogle?」で分類すると情報ゲインが最大になる。
あとは再帰的に分類して決定木を構築None : 7Basic : 6
Premium : 3
None : 6Basic : 5
Premium : 0
None : 1Basic : 1
Premium : 3
ref = google ?
no yes
さらに分類処理 さらに分類処理
あとは再帰的に分類して決定木を構築None : 7Basic : 6
Premium : 3
None : 6Basic : 5
Premium : 0
None : 1Basic : 1
Premium : 3
ref = google ?
no yes
さらに分類処理 さらに分類処理
集合に対する(最良の)分類による情報ゲインが正( > 0)である限り分類を繰り返す。
決定木の構築プログラム
def buildtree(rows,scoref=entropy): if len(rows)==0: return decisionnode() current_score=scoref(rows)
best_gain=0.0 best_criteria=None best_sets=None column_count=len(rows[0])-1 for col in range(0,column_count): column_values={} for row in rows: column_values[row[col]]=1###(続く)
分類前のエントロピー( or ジニ不純度)
各説明変数に対するループ
決定木の構築プログラム
###(続き) for value in column_values.keys(): (set1,set2)=divideset(rows,col,value) # Information gain p=float(len(set1))/len(rows) gain=current_score-p*scoref(set1)-(1-p)*scoref(set2) if gain>best_gain and len(set1)>0 and len(set2)>0: best_gain=gain best_criteria=(col,value) best_sets=(set1,set2) if best_gain>0: trueBranch=buildtree(best_sets[0]) falseBranch=buildtree(best_sets[1]) return decisionnode(col=best_criteria[0],value=best_criteria[1], tb=trueBranch,fb=falseBranch) else: return decisionnode(results=uniquecounts(rows))
情報ゲイン
現ループの説明変数が取り得る各値に対するループ
分類した真集合と偽集合に対して再帰的に木を構築
部分木のルートノード返却
帰結を返却
構築した決定木による予測プログラム
def classify(observation,tree): if tree.results!=None: return tree.results else: v=observation[tree.col] branch=None if isinstance(v,int) or isinstance(v,float): if v>=tree.value: branch=tree.tb else: branch=tree.fb else: if v==tree.value: branch=tree.tb else: branch=tree.fb return classify(observation,branch)
葉に辿り着いたら、帰結を返却する
再帰的に木を辿る
ありがとうございました
「集合知プログラミング」書籍http://www.amazon.co.jp/集合知プログラミング-Toby-Segaran/dp/4873113644