Python でアソシエーション分析 - Orange3-Associate
前回 と同様のアソシエーション分析を Python の Orange で試してみました。
ソースは http://github.com/fits/try_samples/tree/master/blog/20180109/
はじめに
データセット
前回 と同じデータファイルを使います。
data.basket
C,S,M,R T,Y,C P,Y,C,M O,W,L R O,U,R,L P W,C T,O,W,B,C C,T,W,B,Y,F,D ・・・ R,P,S B, B,S B,F C,F,N
インストール
今回は Orange3 を使います。
Orange3 ではアソシエーション分析に関する処理を Orange3-Associate へ分離しているようなので、これらをインストールしておきます。
Orange3 インストール
Orange3 自体は conda コマンドでインストールできるようです。
Orange3 インストール例
> conda install orange3
より新しいバージョンをインストールするには conda-forge
を使えば良さそうです。
Orange3 インストール例(conda-forge 利用)
> conda config --add channels conda-forge > conda install orange3
Orange3-Associate インストール
試した時点では、Orange3-Associate を conda や pip でインストールできなかったので、ソースを取得してインストールしました。
Orange3-Associate インストール例
> git clone https://github.com/biolab/orange3-associate.git > cd orange3-associate > python setup.py install
実装と実行
前回 と同様の処理を実装してみます。
(a) リフト値なし
まずは、Orange.data.Table
でデータファイルを読み込みます。 (ファイル名の拡張子は .basket
とする必要がありそう)
その結果、tbl
変数の内容は [[C=1.000, S=1.000, M=1.000, R=1.000], [C=1.000, T=1.000, Y=1.000], ・・・]
のようになります。
C や S のような文字列では処理できないようなので、OneHot.encode
で One hot 表現化します。
その結果、X
変数の内容は [[0, 1, 2, 3], [0, 4, 5], ・・・]
のようになります。(出現した順に 0 からの連番が割り当てられるようです)
frequent_itemsets
で組み合わせ毎の発生件数をカウントします。
第 2引数の min_support
で抽出する support(支持度)の最小値を指定できます。以下のサンプルでは 5
と指定しているので 5件以上のものが抽出されます。(比率の指定も可能)
itemsets
変数の内容は {frozenset({11}): 42, frozenset({0}): 41, frozenset({0, 11}): 12, ・・・}
のようになります。
association_rules
でアソシエーションルールの抽出を行います。
第 2引数の min_confidence
で抽出する confidence(確信度)の最小値を指定できます。
ただし、association_rules ではリフト値を取得できないようです。
P
や Q
変数の内容は frozenset({11, 7})
のようになるので、元の文字列へ戻すために OneHot.decode
で処理します。
OneHot.decode の結果は [(11, ContinuousVariable(name='B', number_of_decimals=3), 0), (7, ContinuousVariable(name='O', number_of_decimals=3), 0)]
のようになるので ContinuousVariable の name の値を取り出しています。
sample.py
import sys import Orange from orangecontrib.associate.fpgrowth import * data_file = sys.argv[1] # データファイル読み込み tbl = Orange.data.Table(data_file) X, mapping = OneHot.encode(tbl) itemsets = dict(frequent_itemsets(X, 5)) # アソシエーションルールの抽出 rules = association_rules(itemsets, 0.7) def decode_onehot(d): items = OneHot.decode(d, tbl, mapping) # ContinuousVariable の name 値を取得 return list(map(lambda v: v[1].name, items)) for P, Q, support, confidence in rules: lhs = decode_onehot(P) rhs = decode_onehot(Q) print(f"lhs = {lhs}, rhs = {rhs}, support = {support}, confidence = {confidence}")
実行結果は以下の通り。
実行結果
> python sample.py data.basket lhs = ['B', 'O'], rhs = ['W'], support = 5, confidence = 0.8333333333333334 lhs = ['B', 'T'], rhs = ['C'], support = 5, confidence = 1.0 lhs = ['N'], rhs = ['C'], support = 10, confidence = 0.7142857142857143 lhs = ['T'], rhs = ['C'], support = 8, confidence = 0.8
(b) リフト値あり
リフト値の取得には rules_stats
を使います。
rules_stats の第 3引数にはデータセットの件数(今回は 100)を指定します。(この値はリフト値の算出に使われる)
sample2.py
import sys import Orange from orangecontrib.associate.fpgrowth import * data_file = sys.argv[1] tbl = Orange.data.Table(data_file) X, mapping = OneHot.encode(tbl) itemsets = dict(frequent_itemsets(X, 5)) # アソシエーションルールの抽出 rules = association_rules(itemsets, 0.7) # リフト値を含んだ結果を取得 stats = rules_stats(rules, itemsets, len(X)) def decode_onehot(d): items = OneHot.decode(d, tbl, mapping) return list(map(lambda v: v[1].name, items)) # リフト値(7番目の要素)でソート for s in sorted(stats, key = lambda x: x[6], reverse = True): lhs = decode_onehot(s[0]) rhs = decode_onehot(s[1]) support = s[2] confidence = s[3] lift = s[6] print(f"lhs = {lhs}, rhs = {rhs}, support = {support}, confidence = {confidence}, lift = {lift}")
実行結果は以下の通り。
R の arules を使った 前回 と概ね同じ結果になりました。
実行結果
> python sample2.py data.basket lhs = ['B', 'O'], rhs = ['W'], support = 5, confidence = 0.8333333333333334, lift = 3.333333333333334 lhs = ['B', 'T'], rhs = ['C'], support = 5, confidence = 1.0, lift = 2.4390243902439024 lhs = ['T'], rhs = ['C'], support = 8, confidence = 0.8, lift = 1.951219512195122 lhs = ['N'], rhs = ['C'], support = 10, confidence = 0.7142857142857143, lift = 1.7421602787456447