こんにちは、ECナビ システム本部 システムソリューショングループの大竹(@tokosa)です。

ECナビではDWHのNetezzaを使用し、データマートを構築しております。

Netezzaに関しては、日本ネティーザのサイトをご覧下さい。

実際Netezzaの性能がどの位なのか?何が出来るのかをご紹介します。

Netezzaを使用して2つの集合の類似度を計る

2つの集合の類似度を計る方法としてTanimoto係数(Jaccard係数の拡張)があります。

式は下記の通り。

==================================================================
Tb = Nc/ (Na + Nb - Nc)
==================================================================
Tb:Tanimoto係数 (二値データ)
Na:Aのアイテム数 
Nb:Bのアイテム数 
Nc:共通集合

Tbは0~1の間で0に近ければ類似度が低く1に近づく程類似度が高くなります。

では、実際にDBで集計を行います。

テーブル構成

NETEZZA => d PUR_TEST

Attribute | Type | Modifier | Default Value -----------------+------------------------+----------+--------------- USER_ID | INTEGER | | ITEM_ID | INTEGER | | DATE | DATE | | distribute key (USER_ID) レコード数:50万 集計対象数(アイテム数):1000

テンポラリーテーブルは作成せず、自己結合でSQLを実行させます。

1.Nc=アイテム共通集合をもとめるSQL
  select m.ITEM_ID as MY_ITEM,o.ITEM_ID as OTHER_ITEM ,COUNT(distinct(o.USER_ID)) as match
  from PUR_TEST m INNER JOIN PUR_TEST o on m.ITEM_ID != o.ITEM_ID
  and m.USER_ID =o.USER_ID 
  group by m.ITEM_ID,o.ITEM_ID

2.Naのアイテム数
  select item_id,count(distinct(user_id)) NA from pur_test group by item_id

3.Nbのアイテム数
   select item_id,count(distinct(user_id)) NB from pur_test group by item_id

4.1~3の結果をTanimoto係数の公式へ。

 select MY_ITEM,NA,OTHER_ITEM,NB,NC,trunc(cast(NC as dec)/(NA+NB-NC),2) as T from (
   select m.ITEM_ID as MY_ITEM,o.ITEM_ID as OTHER_ITEM ,COUNT(distinct(o.USER_ID)) as NC
   from PUR_TEST m INNER JOIN PUR_TEST o on m.ITEM_ID != o.ITEM_ID
   and m.USER_ID =o.USER_ID 
   group by m.ITEM_ID,o.ITEM_ID
 ) ma,
 (select ITEM_ID,count(distinct(user_id)) NA from pur_test group by item_id) na,
 (select ITEM_ID,count(distinct(user_id)) NB from pur_test group by item_id) nb 
 WHERE 
 ma.MY_ITEM =na.ITEM_ID AND
 ma.OTHER_ITEM =nb.ITEM_ID 

単純に計算量はO(n^2)です。

アイテム数が1000位なら一瞬です。

実行時間================
real    0m6.680s
user    0m0.156s
sys     0m0.031s

アイテム数が10000超えると。。

実行時間================
real    29m53.769s
user    1m10.785s
sys     0m3.777s

まとめ

実際にはテンポラリテーブルを作成するべきです、アイテム毎のアイテム数(Na ,Nb) は先に集計しておくと良いでしょう。

Netzzaは自己結合も弱いのでこちらは別にするべきです。

今回はNetezzaの性能計る為、こんなSQLを書いています。

Netezzaにもstddev(標準偏差)、stddev_pop(母標準偏差)、variance(式の分散)、var_pop(母分散)などなど

解析関数が用意されています。協調フィルタリングの相関係数法もできますね。