背景
這是我在優(yōu)達學城的一個實驗項目,使用的是優(yōu)達學城提供的數據集,主要的目的是兩個:1)通過歷史數據,建立一個分類模型,用來預測針對特定消費者屬性和活動特點,活動推送后,消費者會不會參與。消費者洞察是數據科學的熱門領域,隨著數字化的深入,數據的可獲得性越來越高,將數據工程,數據科學應用到消費者洞察中,是當下企業(yè)最重要的行動之一。
數據集
這個實驗提供了三個數據文件:
portfolio.json – 包括推送的 id 和每個推送的元數據(持續(xù)時間、種類等等)
profile.json – 每個顧客的人口統(tǒng)計數據
transcript.json – 交易、收到的推送、查看的推送和完成的推送的記錄
以下是文件中每個變量的類型和解釋 :
portfolio.json
id (string) – 推送的id
offer_type (string) – 推送的種類,例如 BOGO、打折(discount)、信息(informational)
difficulty (int) – 滿足推送的要求所需的最少花費
reward (int) – 滿足推送的要求后給與的優(yōu)惠
duration (int) – 推送持續(xù)的時間,單位是天
channels (字符串列表)
profile.json
age (int) – 顧客的年齡
became_member_on (int) – 該顧客第一次注冊app的時間
gender (str) – 顧客的性別(注意除了表示男性的 M 和表示女性的 F 之外,還有表示其他的 O)
id (str) – 顧客id
income (float) – 顧客的收入
transcript.json
event (str) – 記錄的描述(比如交易記錄、推送已收到、推送已閱)
person (str) – 顧客id
time (int) – 單位是小時,測試開始時計時。該數據從時間點 t=0 開始
value - (dict of strings) – 推送的id 或者交易的數額
基本步驟
我選擇切入的一個角度是,建立一個模型,可以用來評估客戶是否會對推送做出回應,哪些因子會對成功回應起關鍵作用。我分了三個大的步驟:
第一步:數據整理,主要是對三個文件的數據做些格式處理,對某些類別字段做獨熱編碼,最后并合并成一個大的文件,用于數據分析和建模
第二步:數據分析,這一步主要是探索數據,做些可視化的展現,得到一些顯性的結論,包括什么因素對活動推送的效果起作用
第三步:數據建模和評估,我根據Scikit Learn官方的Machine Learning Map,找出適合我們這個案例的三個分類模型,做了初步比較,然后再用網格搜索對潛力最大的一個模型進行參數遍歷,驗證準確率和F1分數值,最后展示因子重要程度
經過三步之后,我給出結論。
衡量指標
對于模型的衡量指標,分類模型有準確率,精確率,召回率和F1分數,比較有用的是準確率和F1分數,我會用F1分數來選擇最優(yōu)的模型,并根據優(yōu)化后的模型給出結論。同時,根據模型,還可以對各個因子的重要性有認識和把握。我是用的數據分析環(huán)境是anaconda的Python 3.7版本,用到的建模工具是Scikit Learn庫。
數據集
一共有三個數據文件:
portfolio.json – 包括推送的 id 和每個推送的元數據(持續(xù)時間、種類等等)
profile.json – 每個顧客的人口統(tǒng)計數據
transcript.json – 交易、收到的推送、查看的推送和完成的推送的記錄
以下是文件中每個變量的類型和解釋 :
portfolio.json
id (string) – 推送的id
offer_type (string) – 推送的種類,例如 BOGO、打折(discount)、信息(informational)
difficulty (int) – 滿足推送的要求所需的最少花費
reward (int) – 滿足推送的要求后給與的優(yōu)惠
duration (int) – 推送持續(xù)的時間,單位是天
channels (字符串列表)
profile.json
age (int) – 顧客的年齡
became_member_on (int) – 該顧客第一次注冊app的時間
gender (str) – 顧客的性別(注意除了表示男性的 M 和表示女性的 F 之外,還有表示其他的 O)
id (str) – 顧客id
income (float) – 顧客的收入
transcript.json
event (str) – 記錄的描述(比如交易記錄、推送已收到、推送已閱)
person (str) – 顧客id
time (int) – 單位是小時,測試開始時計時。該數據從時間點 t=0 開始
value - (dict of strings) – 推送的id 或者交易的數額
業(yè)務邏輯
一個活動推送給消費者,就會產生一條推送已收到記錄。活動持續(xù)時間,這個持續(xù)時間是有效期,在推送接收后,有效期范圍內,系統(tǒng)會記錄瀏覽行為和完成動作(消費滿足了活動門檻),所以一個推送的有效指標就是推送后,有效期內有瀏覽,并且有完成動作。對于每次推送,lookup出相關的活動信息,消費者信息,就可以運用機器學習的方法,找出這些信息,哪些是對活動效果起決定作用。這對后期活動的設置,定位消費者具有重大的指導意義。
具體過程
首先數據需要進行整理,尤其是transcript數據集,里頭混雜了推送接收記錄,瀏覽記錄和完成記錄,需要拆分出來,從而三個子數據集進行數據連接和匹配后,才能得到推送記錄是否產生效果的判斷。這一步處理,至關重要。數據集加載進來后,就可以查看數據的內容,決定后續(xù)的數據整理步驟,比如在portfolio里頭,是推送活動的著信息,channels字段其實包含了多中信息,應該做成獨立的標識字段(email, mobile, social)。offer_type是一個類別字段,不方便預測模型進行學習,也要做one-ho編碼t處理,pandas.get_dummies,是很有用的工具。

profolio數據集,是消費者相關的主數據,數據集里頭有許多年齡超過100,性別為空/“O”的,會被刪除。age字段用pandas.cut函數做成幾個范圍(比如沒20年一個年齡段)并做成one hot編碼處理。gender字段也一樣,也可以做one hot編碼處理

transcript數據集是處理重點,實際上用event字段的值進行拆分,可以拆成四個數據集,分別代表交易,推送接收,推送瀏覽,推送完成。不同的數據表,原始的value值,可以提取出amount或者offer id信息。

1.2 數據整理
經過以上的分析,使用python和pandas的相關處理函數,分別將數據集處理成以下的結果:
對于portfolio數據集,留意channels和offer_type字段派生出來的字段

對于profile數據集,會員注冊的年份,年齡范圍,性別,都用one-hot編碼的方式做成了新的字段,方便后續(xù)機器學習處理

對于transcript數據集中event為"offer received", "offer viewed", "offer complete"的記錄,處理成三個獨立數據集,并從value字段提取出offer id。這里time字段是從0開始的時間戳,是從0開始的小時數:

這三個表,以offer_received作為主表,連接另外兩個,就可以得到對于每個接收到的推送,知否能在有效期內(有效期在offer主數據里頭,單位是天)能從offer_viewed和offer_completed里頭找到相應記錄,且完成的時間遲于瀏覽的時間(有時候用戶沒有瀏覽也達到一個推送的條件,也被視為完成動作,這個需要考慮)。做法有很多,用python做一個循環(huán),或者借用SQL用一個語句實現都可以,如:

這時候,一次推送,什么時候送達,結束的時間戳,在有效期范圍內什么時間瀏覽,什么時間完成,是否是一次有效的活動推送,就已經有了,用一個標志位字段記住它。
第二步 數據分析
接下來,結合消費者數據集和活動數據集,可以對推送,通過各種分組匯總,進行觀察,得到一些顯見的結論,比如,可以對活動門檻,活動期限,消費者性別,注冊年份,年齡段和收入區(qū)間進行分組,發(fā)現:1)門檻高的活動,互動成功的效果差些;2)女性比男性更容易被推送影響;3)年輕人不太關注推送的信息等等。這些信息,對未來的offer design和consumer targetting已經有很大的指導意義了。

第三步:數據建模
但有些影響因素,靠觀察,容易遺漏,可以用這個數據集做個建模,我最終使用Scikit Learn隨機森林模型,進行的模型優(yōu)化。如何選擇一個合適的模型呢?這個和問題的類別,數據集的大小等都有關系,SK-Learn有個很好的machine learning map,可供參考

根據我們手頭的數據和問題的類型(60K的記錄數,分類問題)從這個官方的指引中,我們可以看到,應該嘗試的模型有LinearSVC,KNeighbors分類器以及繼承模型里頭的分類器(比如隨機森林)。我的思路是:選擇這三個模型,先默認參數試一下,是不是都可用,對于指標比較好的,進一步進行參數調優(yōu):
1. LinearSVC

2. KNeighbors分類器

3. 隨機森林分類器

經過初步嘗試,隨機森林的表現較好,而且是一個比較可用的程度。進一步對參數進行調優(yōu),我又參考了官方文檔。根據官方文檔,這個模型,主要可用調整的參數是兩個:n_estimatiors(接近一個閾值之前,越大越好),max_features(基本即使兩個選項None或者sqrt),見下面的官方文檔截圖:

要搜索出比默認參數最優(yōu)的參數,最好的工具是GridSerchCV,列出兩個參數的取值范圍,這個搜索機制會遍歷所有可能的組合,選取出最合適的參數形成模型。但是選取最佳模型用哪個評判標準呢(scorer參數),我使用的是F1分數。對于分類模型,有幾個重要的指標,說明如下:
準確率:這個指標評估一個模型在所有數據上的表現。在及其特殊的情況下,準確率高,不代表模型實用。以信用卡欺詐識別為例,信用卡欺詐本身是一個樣本集里頭非常少出現的情況,一個模型,只要對所有的樣本都預測不是一個欺詐,就可以達到很高的準確率。但是這個模型并沒有什么用。我們的數據沒有那么特殊,準確率是一個的評估指標
精確率:這個指標主要衡量預測結果為1的樣本,有多大的比例真實是1,這個指標對于促銷類的推送有意義,因為我們希望模型幫我門找出真正感興趣的消費者,以免對不感興趣的消費者產生困擾,或者浪費促銷成本(當然現在的成本在降低)
召回率:這個指標主要衡量樣本中為1的,有多大比例被模型準確預測。在特定的場合,比如目前的疾病檢測,要盡可能多的預測到正樣本,哪怕有些負樣本被預測為正樣本,也不要緊。這個指標對我們的例子也很有用,因為獲取消費者數據不容易,要從現有的消費者數據里頭盡量找到合適的消費者
F Beta Score:是精確率和召回率的平衡,是綜合考慮精確率和召回率的指標,以下從維基百科中下載的圖片能解釋這個指標的作用。將Beta值設為1(就是所謂的F1 Score),其實就能同時反映精確率和召回率的影響

在我們這個案例中,準確率重要,精確率和召回率也重要,我綜合考慮,選定F1分數值來作為模型選擇參數,我的代碼示例如下:

經過3折交叉驗證,對8個參數組合,它運行完就找出最好的參數,這個最好的參數在GridSearchCV返回的模型變量的best_params里頭,可供查看。可以看到,最好的n_estimator達到了800。

最后用返回的這個模型,就可以做測試集驗證,示例代碼如下(模型性能嘛,比調整前稍好點了):

另外訓練出來的分類模型,有個重要參數叫best_estimator_.feature_importances_,這個參數返回找到的最好的分類器的因子重要程度屬性,揭示了預測因子的重要性,我通過可視化的方式展現了出來,代碼示例供參考:

可見,許多我們僅僅通過數據觀察可能會未必能發(fā)現其中一些重要的影響因素。比如對整個數據集而言,對推送效果影響最大的是收入(income),獎勵力度(reward),推送渠道(social),有效時長(duration),活動門檻(difficulty)。我們光從數據觀察,可能會被忽略。
結語
數據分析,數據工程和數據科學,在數字化浪潮中,在數據極大豐富的背景下,將在商業(yè)世界中扮演更加重要角色,發(fā)揮更加重大的指導作用。讓我們一起,學好python,學好數據科學,為未來做好準備。
參考
以下是實驗進行中的參考文獻和鏈接:
【1】https://retailanalysis.igd.com/ (一個很好的網站,提供很多關于零售業(yè)數據洞察的最新進展)
【2】https://scikit-learn.org/stable/tutorial/machine_learning_map/index.html (Scikit-Learn官方一個關于預測模型選擇的實用指引)
【3】https://scikit-learn.org/stable/modules/ensemble.html#forests-of-randomized-trees (官方文檔有參數調整的建議)
【4】http://www.itdecent.cn/p/1afbda3a04ab (關于模型指標的解釋,這里有篇很明細的文章)
【5】https://www.w3school.com.cn/sql/index.asp (這里有一個SQL語法的速查鏈接,我常用)
【6】https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html#sklearn.svm.LinearSVC
【7】https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifier