おすすめ商品を画像の似てる感から自動作成する簡単レコメンドエンジン

EC-CUBEのレコメンドエンジンというのは有料で提供されているものもありますが結構高かったり、EC-CUBEの利用パターンにある数百件の商品と数百件の顧客といったレベルでは既存のユーザー行動ベースのレコメンドエンジンでは成果がでないと思われる方が多いのではないかと思います。

今回はEC-CUBEに登録した商品画像情報から画像の類似度を計算して似た画像の商品を「おすすめ商品」としてセットする仕組みを簡単にですがつくってみましょう。

ちょっと難しめの話になりますが、画像の類似度というのは特徴を画像から計算して、その特徴を比べることで似ているか計算します。特徴はいろいろな出し方があるのですが(A君とB君は似ていると思うのが人それぞれのように、特徴の出し方によって似てる・似ていないの判定は変わってきます)今回はその特徴としてCCVを利用し、CCVの値のユークリッド距離を計算して、似てる度を出しましょう。
今回は管理画面で商品を保存した際に、既に登録済みの商品のCCV値の距離をとってきて似ている商品六件をおすすめしています。本当は登録するたびに全件計算して、すべての商品にセットすべきですが、そのへん手抜きです。なので、全件商品登録が終わった後に、全部再度更新とかをしないといけません(泣)。また距離計算も何らかの最近傍探索アルゴリズムを使うべきですが、やってないです。あとCCVの計算がなんかあやしいような気がします。ごめんなさい。以下実装になります。

まず、以下のCCV計算用コードを取得して data/module/ に置きます。
http://hakaselab.sakura.ne.jp/make/pictniteru/pictniteru.library.phps

1. 取得したファイルを読み込みます。
data/class/pages/admin/products/LC_Page_Admin_Products_Product.php

require_once(DATA_PATH . "module/pictniteru.library.php");

2. 画像を計算するため商品登録前に画像を保存場所に登録するようにします。
data/class/pages/admin/products/LC_Page_Admin_Products_Product.php#process

// 一時ファイルを本番ディレクトリに移動する
$this->objUpFile->moveTempFile();
$this->arrForm['product_id'] = $this->lfRegistProduct($_POST);		// データ登録

3. 特徴度を計算する。
data/class/pages/admin/products/LC_Page_Admin_Products_Product.php#lfRegistProduct

// CCV の計算
$ccv_src            = imagecreatefromjpeg(IMAGE_SAVE_DIR . $sqlval['main_image']);
$ccv_set            = $ccv_src !== FALSE ? pictniteru_make_ccv($ccv_src) : null;
$ccv_str            = serialize($ccv_set);
$sqlval['file1']    = $ccv_str;
$arrList['ccv_set'] = $ccv_set;

4. 関連商品をセット。
data/class/pages/admin/products/LC_Page_Admin_Products_Product.php#lfInsertRecommendProducts

// 一旦オススメ商品をすべて削除する
$objQuery->delete("dtb_recommend_products", "product_id = ?", array($product_id));
$sqlval['product_id'] = $product_id;
$arrRet = $objQuery->select("product_id, file1", "dtb_products", "del_flg = 0");
$ccvRet = array();
for($i = 0; $i < count($arrRet); $i++) {
    $product = $arrRet[$i];
    $ccv_set = unserialize($product['file1']);
    if(is_array($ccv_set)) $ccvRet[$product['product_id']] = $ccv_set;
}
$result = pictniteru_k_distance($arrList['ccv_set'], $ccvRet);
asort($result);
$rank = RECOMMEND_PRODUCT_MAX;
$i    = 0;
foreach($result as $k => $v) {
    if(RECOMMEND_PRODUCT_MAX < $i) break;
    if($k != $product_id) {
        $sqlval['recommend_product_id'] = $k;
        $sqlval['rank']                 = $rank--;
        $sqlval['creator_id']           = $_SESSION['member_id'];
        $sqlval['create_date']          = "now()";
        $sqlval['update_date']          = "now()";
        $objQuery->insert("dtb_recommend_products", $sqlval);
    }
    $i++;
}

以上で実装は完了です。商品の登録が完了すると以下のように似た画像の商品がレコメンドされます。ちょっと商品数が少なかったので(だと信じたい)、あんま似てないっぽいのもまざってますが、だいたいいいかんじなので、これでよしとします。
200908072113

開発にあたっては以下のサイトを参考にしました。ありがとうございます。
http://d.hatena.ne.jp/audioswitch/20080924/1222258823
http://d.hatena.ne.jp/nowokay/20081007/1223327913