一直想總結一下這次的比賽,拖啊拖。。。一直等到現在,趁著現在要找實習,好好總結一下。
比賽題目
比賽的官方網站在這,IJCAI SocInf`16。
這次比賽的題目是給定 2015 年 7 ~ 11 月份的使用者在不同地點口碑購買記錄,以及 2015 年 7 ~ 11 月淘寶上使用者的購物行為資料,來預測 12 月這一整月使用者來到一個地點之後會光顧哪些口碑商鋪。這個比賽有一個很有意思的地方,就是它關注的是一個使用者來到一個他之前沒有去過的新地點之後,他會去哪些店鋪消費,有一點像推薦系統中經典的冷啟動問題。比賽提供的資料也有這個特點:
-
在測試集中,只有 10 % 的使用者用之前使用口碑的記錄;
-
有 5 % 的使用者雖然有之前使用口碑的記錄,但是在測試集中,這些使用者來到了新的地點;
-
所有使用者都有他們淘寶購物的行為資料。
如果題目只是這樣的,其實還不算奇怪,奇怪的是題目的評價標準上加上了 budget 這個神奇的東西,先來看看評價指標:
$$P = frac{sum_i min(|S_i cap S_i^*, b_i|)}{sum_i| S_i^* |}$$
$$R = frac{sum_i min(|S_i cap S_i^*, b_i|)}{sum_i min(|S_i, b_i|)}$$
$$F_1 = frac{2 ast P ast R}{P + R}$$
最後考核的目標是 F1 值。簡單來說一下這個 budget:
我們的目標是在使用者來到一個地點之後,給他推薦他可能會去的店鋪。這裡,把問題轉換一下,我們要給很多店鋪來推薦可能會來這裡購物的人。這裡推薦的人數要受到 budget 的限制,即不能超過店鋪的最大承載量以及口碑提供給這家店鋪的優惠券的個數。
先詳細介紹一下比賽提供的資料格式:
-
Online user behavior before Dec. 2015. (ijcai2016 taobao.csv)
2015 年 7 ~ 11 月淘寶上使用者的購物行為資料,包括使用者的點選、購買,購買物品種類等屬性。
-
Users shopping records at brick-and-mortar stores before Dec. 2015. (ijcai2016 Koubei train.csv)
2015 年 7 ~ 11 月份的使用者在不同地點口碑購買記錄,資料格式:(user_id, loc_id, merchant_id, time_stamp)
-
Merchant information (ijcai2016 merchant info.csv)
不同口碑商鋪的位置分佈情況,有的商鋪有連鎖店,資料格式:(merchan_id, loc_id1:loc_id2:…)
-
Prediction result. (ijcai2016 Koubei test.csv)
最後要提交的資料格式
user_id, loc_id, merchant_id1:merchant_id2…
對於這個問題,我們的想法是,要充分利用每一個使用者和每一個口碑商鋪的歷史資料。更準確的說,我們要從訓練集中提取足夠的可訓練的特徵,然後利用一些經典的模型,比如 Xgboost 來構建分類模型。同時最需要注意的是,我們要時刻考慮 budget 的影響。
如何來利用歷史資料 ?
我們分析了題目所給的訓練集,然後將資料切分為兩部分,第一部分是 2015 年 11 月 23 號之前的資料,我們把這當做本地訓練集;另一部分是 2015 年 11 月 23 號之後的資料,我們把這當做本地測試集。通過對這些資料的整理和分析,我發現幾條條重大的規律:
-
如果地點確定的話,對於一個使用者,他最有可能去的是他曾經光顧過的店。
-
從口碑店鋪的角度來講,如果這家店鋪曾經的銷量很好,那麼它也將在未來吸引更多的顧客去消費。
從這兩條觀察出來的規律來看,我們將探索資料的方向劃分為兩條道路:一條是從使用者的角度出發;另外則是從口碑商店的角度出發。
從使用者的歷史資訊來看
基於我們的觀察,當一個人來到一個他之前去過的地點,他們更傾向於去之前購物過的商店消費。因此,一個在過去的一段時間內在一家商鋪的消費次數能夠在很大程度上影響我們的推薦質量。頻率越高,越能代表這個人在未來會再次來到這家店消費。
我們做了一個統計,如果一個使用者在過去曾經關顧過一家口碑店鋪超過 6 次的話,當我們在之後再向這位使用者推薦這家店的話,我們會得到超過 90 % 的準確率。
不過從另一方面說,每一家口碑店鋪都有 budget 限制,這意味著,如果按照使用者之前光顧過哪家店鋪來推薦的話,肯定會有部分店鋪的 budget 超標。
我們在使用者的資料中找尋這樣一個鍵值對 (user, location, merchant),通過計算這樣一個鍵值對出現的頻率,我們可以統計出 (user, location, merchant, frequency) 的鍵值對,將這個鍵值對按照 frequency 來從高到低排序,然後按照這個順序,從高到低來給 (user, query) 這樣一個查詢來推薦店鋪,直到這家店鋪的 budget 耗盡為止。
經過統計發現,平均每一個使用者在一個地點只會關顧 1.3 個商家,所以在這裡我們限制最大的推薦個數為 4。
從商家的歷史資訊來看
經過之前的分析,我們發現不同的店鋪有著不同的“受歡迎度”。舉個例子,“820”這個商家在整個訓練集中幾乎出現 1/4。問題是我們怎麼定義這個“受歡迎度”呢?
為了解決這個問題,我們首先定義,在不同地點的同一家口碑商鋪是不一樣。因為在題目給定的資料中,存在大量的連鎖商鋪,但是這些連鎖店鋪在不同地點的“受歡迎度”是完全不同的。
接下來我們設想這樣一種情況,90 % 來到地點 A 的人都會去 商鋪 B 消費,在這種情況下,如果我們給所有的來地點 A 的人都推薦 B 商鋪的話,我們就能得到 90 % 的準確率。所以,在一個地點某家店鋪消費的總人數佔該地點所有人數的比例,我們稱之為該店鋪的 “受歡迎度” (Popularity)。
因此我們將所有店鋪按照 Popularity 從大到小來進行排序,依次推薦來到該地點的所有使用者,直到超過 budget。經過一些線下的實驗,我們取這個 Popularity 的值的閾值為 0.25。
引入淘寶資料來提升推薦質量
我們之前的推薦完全沒有用到每個人的特徵,相當於無法做到“千人千面”。於是接下來我們就想辦法,如何利用淘寶的資料來提升推薦質量。
從直觀上而且,淘寶的資料應該很有幫助,比如,在淘寶上經常瀏覽或者購買電子產品的人往往不太會去關顧口碑商鋪裡面那些賣女式服裝的。受到這個的啟發,我們就建立了一個這樣的表:如果存在這樣一條記錄,一個使用者在淘寶上瀏覽或者購買的商鋪 A;同時也線上下口碑上的商鋪 B 消費,我們就把 (A, B) 這個關係連結串列放入表中。基於這樣的表,我們對那些之前沒有口碑消費記錄的新使用者,如果他們曾在淘寶上購買或瀏覽了商鋪 A, 那麼我們就只給他推薦在關係連結串列中與 A 相連的口碑商鋪。線上的結果證明,我們的預測質量提升了。
引入機器學習模型
目前為止我們都沒有怎麼用機器學習模型,用普通的規則就可以在天池上面排一個不錯的名次。但是為了取得更好的成績,我們嘗試著去探尋每一個使用者、地點和商鋪的各種各樣可能的特徵。下面我將詳細介紹這些我們的做法。
我們將這個問題看成是一個二分類問題。我們的方法是對每一個店鋪建模,比如說,在資料集中,使用者 u 在地點 l 的店鋪 m 消費了。我們可以產生一個三元組 (u, l, m)。對應於這個三元組,我們可以產生一些訓練資料,首先,對於我們而言,正樣本即是那些消費過的使用者,即 (u, l, m) 是 True;第二,我們的負例是那些同樣是這個地點的其他商鋪,比如說 m‘,我們將 (u, l, m`) 定義為 False。按照這個方法,我們可以產生供二分類的訓練集。根據這個道理,對於賽題要我們預測的使用者來到一個地點之後會去哪些店鋪的情況,我們也可以根據這個三元組,產生一個每一個店鋪的預測概率。
這麼做其實負樣本是很多的。。。為了避免正負樣本不平衡的問題,我們採取取樣的方法去提取負樣本。
特徵工程
特徵工程對應機器學習來說十分重要,俗話說,特徵是模型的上限。我們觀察到,有些使用者喜歡關顧那些他們之前去過的店,有些喜歡光顧該地點上最熱門的店鋪,有些則喜歡去那些剛開張的店鋪。
所以,針對 (u, l, m) 這樣一個三元組,我們試圖找尋關於他們其中任意一個的特徵。
我們找尋的特徵如下:
-
鍵值對 (u, l, m) 出現的次數,即 frequence,使用者關顧這家店的頻率。
-
鍵值對 (u, l, m) 是否出現過,True or False。
-
user_id 的 onehot 編碼。
-
merchant_id 編碼。
-
(l, m) 出現次數,即這個地點這個商店的總銷量。
-
open_interval:店鋪的開業時間。
-
使用者 u 在淘寶上購物的次數
-
使用者 u 在淘寶上瀏覽的次數
-
使用者 u 在淘寶上購買過的商品的種類的 onehot 編碼
-
使用者 u 在淘寶上購買過的商鋪的 id 的 onehot 編碼
-
使用者 u 在淘寶上購買的比例 (購買數 / (購買 + 點選)
-
使用者 u 在淘寶上購買的次數
-
使用者 u 在淘寶上點選的次數
-
通過 SVD 算出來的使用者 u 的潛在矩陣
-
通過 SVD 算出來的商店 m 的潛在矩陣
模型融合
之前的規則可以得出一個結果,之後的模型也可以得出一個結果,在比賽的最後階段,我們對模型進行融合,嘗試各種不同的引數,達到了這個名次。