はじめに
頻出パターンをマイニングするためのアルゴリズムとして、Aprioriアルゴリズムはデータセットを複数回スキャンする必要があり、I/Oは大きなボトルネックとなる。この問題を解決するために、FP-TreeアルゴリズムまたはFP-Growthアルゴリズムとも呼ばれる手法を用いる。またFP-Treeアルゴリズムでは並列計算の手法も施して大量のデータマイニングに対応可能となる。
アルゴリズム
概要
まずは下記例のdataSetのように、Aはデータセットからカントして計8回出現したため、最初の位置に配置されるようにヘッダテーブル(Header Table)をまとめる。それからアイテムをFP-Treeにマッピングする。ヘッダテーブルにあるアイテムはFP-Treeに指して紐付けられる。最後にヘッダテーブルの下のアイテムから上への順でマイニングして、頻出アイテムセットを取得する流れになる。
miniSupport = 2 step1 dataSet: [['A', 'B', 'C', 'E', 'F', 'O'], ['A', 'C', 'G'], ['E', 'I'], ['A', 'C', 'D', 'E', 'G'], ['A', 'C', 'E', 'G', 'L'], ['E', 'J'], ['A', 'B', 'C', 'E', 'F', 'P'], ['A', 'C', 'D'], ['A', 'C', 'E', 'G', 'M'], ['A', 'C', 'E', 'G', 'N']] step2 sorted dataset: {frozenset({'F', 'C', 'O', 'A', 'E', 'B'}): 1, frozenset({'A', 'G', 'C'}): 1, frozenset({'E', 'I'}): 1, frozenset({'C', 'D', 'A', 'G', 'E'}): 1, frozenset({'C', 'A', 'G', 'L', 'E'}): 1, frozenset({'J', 'E'}): 1, frozenset({'F', 'C', 'P', 'A', 'E', 'B'}): 1, frozenset({'A', 'D', 'C'}): 1, frozenset({'C', 'M', 'A', 'G', 'E'}): 1, frozenset({'C', 'N', 'A', 'G', 'E'}): 1} step3 headerTable: {'F': [2, <__main__.treeNode object at 0x7f4bcea88240>], 'C': [8, <__main__.treeNode object at 0x7f4bcea88f28>], 'A': [8, <__main__.treeNode object at 0x7f4bcea882b0>], 'E': [8, <__main__.treeNode object at 0x7f4bcea882e8>], 'B': [2, <__main__.treeNode object at 0x7f4bcea88ef0>], 'G': [5, <__main__.treeNode object at 0x7f4bcea88390>], 'D': [2, <__main__.treeNode object at 0x7f4bcea88470>]} conditional tree for: {'B'}
ヘッダテーブルの作成
下記Header Tableのようにヘッダテーブルをまとめる。
step3 headerTable: {'A': 8, 'C': 8, 'E': 8, 'G': 5, 'B': 2, 'D': 2, 'F': 2}
FP-Treeの作成
下記FP-TreeのようにFP木をまとめる。
step3 FP-Tree: Null Set : 1 A : 8 C : 8 E : 6 B : 2 F : 2 G : 4 D : 1 G : 1 D : 1 E : 2
FP-Treeのマイニング
ヘッダテーブルの下のアイテムから上への順でマイニングする。ヘッダテーブルのアイテムに対して、条件パターンベース(Conditional Pattern Base)をまとめて条件FP-Tree(Conditional FP-Tree)を得られる。また頻出度が少ないノードを削除する。この方法で頻出パターンをマイニングする。
step4 conditional tree for: {'B'} Null Set : 1 A : 2 C : 2 E : 2 step4 conditional tree for: {'C', 'B'} Null Set : 1 A : 2 step4 conditional tree for: {'E', 'B'} Null Set : 1 A : 2 C : 2 step4 conditional tree for: {'C', 'E', 'B'} Null Set : 1 A : 2 step4 conditional tree for: {'C'} Null Set : 1 A : 8 step4 conditional tree for: {'D'} Null Set : 1 A : 2 C : 2 step4 conditional tree for: {'C', 'D'} Null Set : 1 A : 2 step4 conditional tree for: {'E'} Null Set : 1 A : 6 C : 6 step4 conditional tree for: {'C', 'E'} Null Set : 1 A : 6 step4 conditional tree for: {'F'} Null Set : 1 A : 2 B : 2 C : 2 E : 2 step4 conditional tree for: {'F', 'B'} Null Set : 1 A : 2 step4 conditional tree for: {'F', 'C'} Null Set : 1 A : 2 B : 2 step4 conditional tree for: {'F', 'B', 'C'} Null Set : 1 A : 2 step4 conditional tree for: {'F', 'E'} Null Set : 1 A : 2 B : 2 C : 2 step4 conditional tree for: {'F', 'E', 'B'} Null Set : 1 A : 2 step4 conditional tree for: {'F', 'E', 'C'} Null Set : 1 A : 2 B : 2 step4 conditional tree for: {'F', 'E', 'B', 'C'} Null Set : 1 A : 2 step4 conditional tree for: {'G'} Null Set : 1 A : 5 C : 5 E : 4 step4 conditional tree for: {'C', 'G'} Null Set : 1 A : 5 step4 conditional tree for: {'G', 'E'} Null Set : 1 A : 4 C : 4 step4 conditional tree for: {'C', 'G', 'E'} Null Set : 1 A : 4 step4&5 frequentItemList: [{'A'}, {'B'}, {'A', 'B'}, {'C', 'B'}, {'C', 'B', 'A'}, {'E', 'B'}, {'A', 'E', 'B'}, {'C', 'E', 'B'}, {'C', 'E', 'B', 'A'}, {'C'}, {'C', 'A'}, {'D'}, {'A', 'D'}, {'C', 'D'}, {'C', 'A', 'D'}, {'E'}, {'A', 'E'}, {'C', 'E'}, {'C', 'E', 'A'}, {'F'}, {'F', 'A'}, {'F', 'B'}, {'F', 'B', 'A'}, {'F', 'C'}, {'F', 'A', 'C'}, {'F', 'B', 'C'}, {'F', 'B', 'A', 'C'}, {'F', 'E'}, {'F', 'E', 'A'}, {'F', 'E', 'B'}, {'F', 'E', 'B', 'A'}, {'F', 'E', 'C'}, {'F', 'E', 'A', 'C'}, {'F', 'E', 'B', 'C'}, {'F', 'C', 'A', 'E', 'B'}, {'G'}, {'A', 'G'}, {'C', 'G'}, {'C', 'G', 'A'}, {'G', 'E'}, {'A', 'G', 'E'}, {'C', 'G', 'E'}, {'C', 'G', 'E', 'A'}]
手順のまとめ
1・データセット(Data Set)をスキャンして、すべての1アイテムのカウントを取得する。次に、サポート度がしきい値(miniSupport例えば=2)より低いアイテム(非頻出アイテム)を削除して、ヘッダーテーブル(Header Table)に1アイテムを入れて、サポート度の降順(Sort 大→小)に並べる。
2・データセットを再度スキャンして、サブセット(トランザクションセット)毎に非頻出アイテムを除外して、サポートの降順(大→小)に並べて用意しておく。
3・上記用意したサブセットを読み取って、FP-Treeに挿入する。ソートされた順序で最初ソートされたノードは親ノード(Parent Node)で、あとにソートされたノードは子ノード(Child Node)にする。共通の親ノードが存在する場合、対応する共通の親ノードのカウントは1つ増やす。挿入後、新しいノードが生成される場合、ヘッダーテーブルに対応するノードは、ノードリスト(Node List)を介して新しいノードにリンク(Node Link)される。すべてのデータがFPツリーに挿入されるまで、FP-Treeを作成する。
4・ヘッダーテーブルの一番下のアイテムから上へ条件付きパターンベース(Conditional Pattern Base)を見つける。条件付きパターンベースからの再帰マイニングによって、ヘッダーテーブルアイテムの頻出アイテムセット(Frequent Item Set)を取得する。
5・頻出アイテムセット内のアイテム数が制限されていない場合、ステップ4を繰り返して、すべての頻出アイテムセットを取得する。それ以外の場合、アイテム数の要件を満たす頻出アイテムセットのみを取得する。
ソースコード
以下Peter氏が作成したソースコードをご参照ください。
https://github.com/pbharrin/machinelearninginaction3x/tree/master/Ch12
参考文献
[1] PeterHarrington. Machine Learning in Action.