如何利用機器學習甄別淘寶優質店鋪


轉自 | 數據團學社,微信搜索metrodata_xuexi 即可關注


本文約2400字,閱讀需要7分鐘

關鍵詞:Python sklearn 決策樹 KNN 邏輯迴歸 SVM

本文講述了使用python分別構建決策樹、KNN、邏輯迴歸、SVM、神經網絡共五種不同的模型甄別淘寶優質店鋪的過程。


目錄

1. 背景知識介紹

2. 數據和工具準備

3. 模型介紹、代碼示範和結果比較

4. 調參方法

5. 模型進階:隨機森林


背景知識介紹


在經歷數年雙十一血拼,雙十二剁手之後,作爲一名優秀的數據分析師,我覺得我需要研究一下如何精準的定位優質店鋪,看穿套路,理性消費。


今天的數據來自於阿里雲天池。

這是一份包含2000家店鋪的評分,等級,評論等信息和數年交易記錄的數據。

數據維度可以查看明細:



通過這份數據,我們可以構建一套選店模型,爲即將到來的各種大小節日做準備。這個過程我們將使用sklearn包來完成。


我們要做的事情,就是構建模型,根據店鋪的訪問、購買信息等數據,來評測該店鋪是否爲優質店鋪。一部分數據將用來作爲訓練集,另一部分數據會用來測試已經訓練好模型的精確度。我們這裏將重點關注模型的擬合情況,對每個模型進行調參比較,選出最適合的那一個~


欠擬合指模型沒有很好地捕捉到數據特徵,不能夠很好地擬合數據:



過擬合通俗一點地說就是模型把數據學習的太徹底,以至於把噪聲數據的特徵也學習到了,這樣就會導致在後期測試的時候不能夠很好地識別數據,即不能正確的分類,模型泛化能力太差:



數據和工具準備


一組數據到手,清理整合等預處理工作是繞不開的。我們可以得到了一份適合建模使用的樣本數據:



準備好數據以後,文末導入所需的包、填充數據空值,再拆分提取訓練集測試集數據,並將數據進行標準化,爲後續的模型構建做足準備~


訓練集(Training Set):幫助我們訓練模型,簡單的說就是通過訓練集的數據讓我們確定擬合曲線的參數。 


驗證集(Validation Set):用來做模型選擇(model selection),即做模型的最終優化及確定的,用來輔助我們的模型的構建,可選。 


測試集(Test Set):用來測試已經訓練好的模型的精確度。 


實際應用中,一般只將數據集分成兩類,即訓練集Training set 和測試集Test set。


既然數據都準備好了,那就開始我的表演~對於每個模型,我都會給出模型介紹代碼、簡單的調參過程和查看模型結果的混淆矩陣。

*考慮這份數據比較粗糙,我們僅使用0分店鋪和4分店鋪的數據。


不同模型的構建及其效果


模型一:決策樹


#決策樹
max_depth_l = [2,3,4,5,6,7,8,9,10]
for max_depth in max_depth_l:
    dt_model = DecisionTreeClassifier(max_depth=max_depth)
    dt_model.fit(x_train_scaled,y_train)
    train_accuracy = dt_model.score(x_train_scaled,y_train)
    test_accuracy = dt_model.score(x_test_scaled,y_test)
    print('max depth',max_depth)
    print('訓練集上的準確率:{:2f}%'.format(train_accuracy*100))
    print('測試集上的準確率:{:2f}%'.format(test_accuracy*100))


決策樹是一個類似於人們決策過程的樹結構,從根節點開始,每個分枝代表一個新的決策事件,會生成兩個或多個分枝,每個葉子代表一個最終判定所屬的類別。


決策樹,需要調節的主要參數是樹的深度。深度越淺,容易造成欠擬合;而深度越深,則會過擬合。我們建立一個列表,羅列不同的深度,建立模型進行嘗試,最終選擇在測試集上表現最好的模型。


我們看到,隨着深度的增加,模型在訓練集上的準確率越來越高,而在測試集上的效果則越來越差,這是過擬合的表現,而在深度爲5的時候,測試集的準確率爲73.39,達到最高值,所以這組模型爲決策樹的最佳模型。



繪製混淆矩陣查看模型效果:


dt_model = DecisionTreeClassifier(max_depth=5)
dt_model.fit(x_train_scaled,y_train)
predictions = dt_model.predict(x_test_scaled)
test_accuracy = dt_model.score(x_test_scaled,y_test)
print(classification_report(y_test,predictions))
print('決策樹的準確率:{:2f}%'.format(test_accuracy*100))

cnf_matrix = confusion_matrix(y_test,predictions)
plot_confusion_matrix(cnf_matrix, classes=[0,1],
                      title='Confusion matrix')


*橫座標是預測值,即“模型認爲該店鋪爲差評/優質店鋪”,縱座標代表真實值,即“該店鋪爲差評/優質店鋪”。0爲差評,1爲優質


模型在預測優質店鋪上容易誤殺,把優質店鋪預測爲差評店鋪,錯誤達到43個,不過店鋪茫茫多,錯過這個還有下個,本着寧可錯殺,不能放過的原則,模型還是可以的。


模型二:KNN


k_values = range(3,13)
for k_value in k_values:
    knn_model = KNeighborsClassifier(n_neighbors=k_value)
    knn_model.fit(x_train_scaled,y_train)
    train_accuracy = knn_model.score(x_train_scaled,y_train)
    test_accuracy = knn_model.score(x_test_scaled,y_test)   
    print('k value:',k_value)
    print('訓練集上的準確率:{:2f}%'.format(train_accuracy*100))
    print('測試集上的準確率:{:2f}%'.format(test_accuracy*100))


K最近鄰(k-Nearest Neighbor,KNN)分類算法是最簡單的機器學習算法。 KNN算法的指導思想是“近朱者赤,近墨者黑”——由你的鄰居來推斷出你的類別。


KNN同樣需要調節超參數,我們需要選取不同的鄰近點個數,調試模型達到最優狀態。



參數n_neighbors達到10的時候,效果最棒


knn_model = KNeighborsClassifier(n_neighbors=10)
knn_model.fit(x_train_scaled,y_train)
predictions = knn_model.predict(x_test_scaled)
print(classification_report(y_test,predictions))
accuracy = knn_model.score(x_test_scaled,y_test)
print('KNN預測準確率:{:2f}%'.format(accuracy*100))
cnf_matrix = confusion_matrix(y_test,predictions)
plot_confusion_matrix(cnf_matrix, classes=[0,1],
                      title='Confusion matrix')


*橫座標是預測值,即“模型認爲該店鋪爲差評/優質店鋪”,縱座標代表真實值,即“該店鋪爲差評/優質店鋪”。0爲差評,1爲優質


模型在判斷差評店鋪方面效果比決策樹更好,但錯殺優質店鋪的數量也達到51,好像多了一點。


模型三:邏輯迴歸


c_list = [0.01,0.1,1,1e1,1e2,1e3,1e4]
for c in c_list:
    lg_model = LogisticRegression(C=c)
    lg_model.fit(x_train_scaled,y_train)
    train_accuracy = lg_model.score(x_train_scaled,y_train)
    test_accuracy = lg_model.score(x_test_scaled,y_test)   
    print('C value:',c)
    print('訓練集上的準確率:{:2f}%'.format(train_accuracy*100))
    print('測試集上的準確率:{:2f}%'.format(test_accuracy*100))


迴歸分析是一種預測建模技術的方法,研究因變量(目標)和自變量(預測器)之前的關係。邏輯迴歸是一種廣泛應用於分類問題的迴歸方法。


邏輯迴歸是一種廣義線性迴歸,原理是在線性迴歸的結果外套用sigmoid函數,

把輸出結果壓縮在0-1之間,如果結果>0.5,也就意味着概率大於一半,我們把它判定爲1,反之爲-1,從而起到分類的作用。


Sklearn的邏輯迴歸中,默認加入正則化超參數用於防止過擬合。可調節的參數是C,C越小、抵抗過擬合的力度越大;C越大則效果越小,我們也需要根據實際情況調節。

*參數中1e1,1e2……爲科學計數法,表示10,100……以此類推



我們看到C在100的時候,效果就已經達到最優,而C越小模型的擬合程度越差,所以並不是任何情況,都需要使用過擬合調節。


lg_model = LogisticRegression(C=100)
lg_model.fit(x_train_scaled,y_train)
predictions = lg_model.predict(x_test_scaled)
print(classification_report(y_test,predictions))
accuracy = lg_model.score(x_test_scaled,y_test)
print('邏輯迴歸預測準確率:{:2f}%'.format(accuracy*100))
cnf_matrix = confusion_matrix(y_test,predictions)
plot_confusion_matrix(cnf_matrix, classes=[0,1],
                      title='Confusion matrix')


*橫座標是預測值,即“模型認爲該店鋪爲差評/優質店鋪”,縱座標代表真實值,即“該店鋪爲差評/優質店鋪”。0爲差評,1爲優質


預測準確率約爲70.39%,效果相較於前兩個模型要差一點。錯殺還是51,也不少~


模型四:支持向量機


c_list = [1,1e1,1e2,1e3,1e4,1e5,1e6]
for c in c_list:
    svm_model = SVC(C=c)
    svm_model.fit(x_train_scaled,y_train)
    train_accuracy = svm_model.score(x_train_scaled,y_train)
    test_accuracy = svm_model.score(x_test_scaled,y_test)   
    print('C value:',c)
    print('訓練集上的準確率:{:2f}%'.format(train_accuracy*100))
    print('測試集上的準確率:{:2f}%'.format(test_accuracy*100))


什麼是SVM:支持向量機就是使用一條直線(二維)或超平面(多維)將數據分成兩類,同時保證離超平面最近的點與超平面的間隔儘可能小。就像下圖那樣。


C爲懲罰項,同樣是爲了防止過擬合。不同的C值可以有不同的結果:



svm_model = SVC(C=1e6)
svm_model.fit(x_train_scaled,y_train)
predictions = svm_model.predict(x_test_scaled)
print(classification_report(y_test,predictions))
accuracy = svm_model.score(x_test_scaled,y_test)
print('支持向量機預測準確率:{:2f}%'.format(accuracy*100))
cnf_matrix = confusion_matrix(y_test,predictions)
plot_confusion_matrix(cnf_matrix, classes=[0,1],
                      title='Confusion matrix')



預測準確率爲75.11%,是目前爲止效果最好的模型了~


模型五:神經網絡


mlp =MLPClassifier(hidden_layer_sizes=(100,50),max_iter=1000,activation='relu')
mlp.fit(x_train_scaled,y_train)
train_accuracy = mlp.score(x_train_scaled,y_train)
test_accuracy = mlp.score(x_test_scaled,y_test)   
print('訓練集上的準確率:{:2f}%'.format(train_accuracy*100))
print('測試集上的準確率:{:2f}%'.format(test_accuracy*100))
predictions = mlp.predict(x_test_scaled)
cnf_matrix = confusion_matrix(y_test,predictions)
plot_confusion_matrix(cnf_matrix, classes=[0,1],
                      title='Confusion matrix')

*這個原理比較複雜,文末提供了參考資料供大家閱讀~


使用sklearn中BP神經網絡的包,建立神經網絡模型進行預測,我們可以調節的超參數有神經網絡隱藏層的層數,激活函數等。



預測準確率爲71.67%,結果一般般吧~


我們用了這麼多模型,我相信有同學一定會問,每個模型都有一種甚至數種超參數需要調節,那麼哪種排列組合是最佳組合呢?

呵呵~~~這個問題難度有點高哦!如果我說每次都是蒙的,你會信嗎?


如何調節超參數


對於模型的超參數調節,並沒有固定的套路,通常需要經過數輪嘗試和以往的經驗才能找到最正確的那個。當然,每次手動調節也確實是一件挺麻煩的事,所以,這裏分享一個一勞永逸的方法——網格搜索,交叉驗證。


原理很簡單,我們把測試集再分成數份作爲驗證集。比如分成10份,我們叫10折,然後選取一組參數,分別在每個折上進行運行,得到10個結果,求出平均結果作爲這一組最後的結果,最後得到最優結果的那一組參數。


好!下面我們來看下具體代碼實現過程。

首先建立一個字典,字典裏包含我們需要比較的模型,和每個模型中參數的選取範圍。


model_dict = {
              'Decision Tree':(DecisionTreeClassifier(),
                               {'max_depth':[2,3,4,5,6,7,8,9,10],}
                              ),

              'KNN':(KNeighborsClassifier(),
                     {'n_neighbors':list(range(1,21)),
                      'p':[1,2],}
                              ),

              'Logistic Regression':(LogisticRegression(),
                                     {'C':[1,1e1,1e2,1e3,1e4,1e5,1e6],}
                              ),

              'SVM':(SVC(),
                     {'C':[1,1e1,1e2,1e3,1e4,1e5,1e6],}
                              ),

              'MLP':(MLPClassifier(),
                     {'hidden_layer_sizes':[(100,50),(100,30),(100,50,30),(100,100)],
                      'max_iter':[200,500,1000,5000,10000],
                      'activation':['relu','logistic','tanh']
                         }
                              ),
             }


然後我們使用GridSearchCV,遍歷參數,並排列組合,然後再進行交叉驗證,選取最佳參數組合。我們採用5折對訓練集進行劃分:


for model_name,(model,model_params) in model_dict.items():
    clf = GridSearchCV(estimator=model,param_grid=model_params,cv=5)
    clf.fit(x_train_scaled,y_train)
    best_model = clf.best_estimator_

    acc = best_model.score(x_test_scaled,y_test)
    print('{}模型預測準確率:{:2f}%'.format(model_name,acc*100))
    print('{}模型最佳參數:{}'.format(model_name,clf.best_params_))



因爲經過了驗證集進一步的驗證,最後的結果有所變化,神經網絡模型的結果爲最優結果,並且這裏羅列了每個模型的最佳參數組合。


我們使用了5種模型,並通過反覆調節,正確率達到了74.3%,顯然,這並不是一個十分滿意的結果。那麼是否還有其他更強大的模型,可以再進一步提升呢?


更強大的模型:隨機森林


既然任何的一種模型都達不到要求,那麼我們就用許多模型,把他們組合在一起,這叫強強聯手。對於這類把許多模型組合在一起,成爲一個整體的模型我們稱之爲集成模型


下面,我使用一種集成模型——隨機森林來進一步探索數據。主要原理是構建多棵決策樹,每棵決策樹都會有一個結果,最後通過投票機制,選出最終結果。


from sklearn.ensemble import RandomForestClassifier
tree_param_grid = {'n_estimators':[10,20,30,50,80],
                   'min_samples_split':[2,8,10,20,30,50,60,70,80],
                   'min_samples_leaf':[2,5,10,20,30,50],
                   'random_state':[2]
                  }
grid = GridSearchCV(RandomForestClassifier(),param_grid=tree_param_grid,cv=5)
grid.fit(x_train_scaled,y_train)
best_model = grid.best_estimator_
acc1 = best_model.score(x_train_scaled,y_train)
acc2 = best_model.score(x_test_scaled,y_test)
print('隨機森林模型訓練準確率:{:2f}%'.format(acc1*100))
print('隨機森林模型預測準確率:{:2f}%'.format(acc2*100))
print('隨機森林模型最佳參數:{}'.format(grid.best_params_))


同樣採用交叉驗證來調節參數。特別注意的是random_state參數,一定要限定一下隨機數種子,否則每次運行模型,採用的是不同的隨機數,呈現的結果不同,就無法對比了。


隨機森林模型訓練準確率:76.559140%
隨機森林模型預測準確率:78.111588%
隨機森林模型最佳參數:{'min_samples_leaf': 2, 'min_samples_split': 70, 'n_estimators': 50, 'random_state': 2}


從結果上看,有了比較明顯的提升,在預測集上達到了78.11%的準確率,對比前面的模型有了較大的提升。


集成模型有很多種,每一種都嘗試下,最終的準確率應該可以達到80%。但是,相比起模型,數據更爲重要。受限於數據量,數據精度和數據維度,模型離願望中的90%準確性還有很大的距離。如果有更大的樣本,比如2W條數據,更精細的分類,比如score精確到小數點後一位4.0,4.1,4.2……和更多的字段,比如成交金額,成交數量,店鋪年份等等,那麼模型一定會更精確。

畢竟模型不是魔法,我們討論的也只是科學而不是玄學。最後,最重要的不是買買買,學到模型纔是正事,再來了解下跟模型相關的算法吧。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章