XGB for Rank

常規參數

  XGBoost全名叫(eXtreme Gradient Boosting)極端梯度提升,經常被用在一些比賽中,其效果顯著。它是大規模並行boosted tree的工具,它是目前最快最好的開源boosted tree工具包。XGBoost 所應用的算法就是 GBDT(gradient boosting decision tree)的改進,既可以用於分類也可以用於迴歸問題中。

  1、迴歸與分類  

  事實上,分類與迴歸是一個型號的東西,只不過分類的結果是離散值,迴歸是連續的,本質是一樣的,都是特徵(feature)到結果/標籤(label)之間的映射。分類樹的樣本輸出(即響應值)是類的形式,如判斷蘑菇是有毒還是無毒,週末去看電影還是不去。而回歸樹的樣本輸出是數值的形式,比如給某人發放房屋貸款的數額就是具體的數值,可以是0到120萬元之間的任意值。

    2、背景

對某個query召回的多條list進行排序
檢索詞條(query):query分析----------->------------文檔(doc):檢索結果----------->------------搜索結果(list),排序處理

搜索這一過程的本質是自動選取與用戶輸入的關鍵詞(query)最相關的一組文檔(docs,或稱網頁,urls)的過程。目前主要通過如下兩個步驟實現:

(1)query-doc匹配:尋找與當前輸入的query相關度高的docs(粗排)

(2)高相關度docs精確排序:對(1)中返回的docs,選取更多特徵並按照用戶點擊該doc的可能性大小精確排序。有時我們還會選擇不同的特徵,召回多組(1)並將它們通過排序算法融合爲一組。(精排)

Learning to Rank是一種用來實現步驟(2)的機器學習模型。它使用機器學習的方法,可以把各個現有排序模型的輸出作爲特徵,然後訓練一個新的模型,並自動學得這個新模型的參數,從而很方便的可以組合多個現有的排序模型來生成新的排序模型。

Learning to Rank算法
下圖爲機器學習排序的原理圖,機器學習排序系統由4個步驟組成——人工標註訓練數據、文檔特徵抽取、學習分類函數、在實際搜索系統中採用機器學習模型。

  • 關於樣本集

選取了兩個月用戶的搜索數據特徵,以用戶的點擊行爲爲標籤。

數據處理:每個不同query會存在多個召回列表,有的存在點擊行爲,有的無點擊行爲,需要對同query不同list及不同query的list的點擊行爲量化,使其具有可比性,由於不同query的熱度有差異,所以不同query的點擊行爲沒有可比性,因此對query召回的list做歸一化處理(包括特徵和點擊),這樣每個query的點擊及各特徵都是一個歸一化的數據,從而使得不同query的list具有可比性。

訓練前進一步處理,雖然已經歸一化處理過,但在訓練前對數據進一步歸一化是很有必要的,代碼如下,實驗證明該部分對模型的準確性影響很大。

ss = MinMaxScaler()
ss=StandardScaler()
X_train = ss.fit_transform(X_train)
  • 關於特徵

搜索引擎會使用一系列特徵來決定結果的排序。一個特徵稱之爲一個“feature”。按照我的理解,

feature可以分爲3大類:

(1)Doc本身的特徵:Pagerank、內容豐富度、是否是spam、質量值、CTR等

(2)Query-Doc的特徵:Query-Doc的相關性、Query在文檔中出現的次數,査詢詞的Proximity值(即在文檔中多大的窗口內可以出現所有査詢詞)等。當然,有些Query-Doc的特徵不是顯式的,而是有Semantic的,即雖然Query在文檔中沒有出現,但是語義上是有關係的。

(3)Query的特徵:Query 在所有Query 中的出現次數、比率等。此階段就是要抽取出所有的特徵,供後續訓練使用。


特徵選擇:type_id,num_comment,num_photo,text_score,recall_intention,recall_term,recall_food,recall_prefix,recall_match,tag_match

type_id:POI類型
num_comment:峯評數num_photo:圖片數text_score:質量分recall_intention:意圖召回源標記recall_term:精準召回源標記recall_food:美食召回源標記recall_prefix:前綴召回源標記recall_match:模糊召回源標記tag_match:標籤召回源標記


  • 關於模型

Learning to Rank主要包含pointwise方法、pairwise方法和listwise方法三種類型。

(1)pointwise方法:對於某一個query,它將每個doc分別判斷與這個query的相關程度,由此將docs排序問題轉化爲了分類(比如相關、不相關)或迴歸問題(相關程度越大,迴歸函數的值越大)。

(2)pairwise方法:pairwise方法並不關心某一個doc與query相關程度的具體數值,而是將排序問題轉化爲任意兩個不同的docs di和dj誰與當前的query更相關的相對順序的排序問題。一般分爲di比dj更相關、更不相關和相關程度相等三個類別,分別記爲{+1, -1, 0},由此便又轉化爲了分類問題。

(3)listwise方法:將一個query對應的所有相關文檔看做一個整體,作爲單個訓練樣本。

  3、代碼

  • 模型的訓練:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Oct 14 15:29:52 2019

poi排序模塊xgb模型訓練

@author: huamin
"""

import numpy as np
import pandas as pd
from xgboost.sklearn import XGBClassifier
from sklearn import metrics
import xgboost as xgb
# from sklearn.grid_search import GridSearchCV
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import MinMaxScaler  # 最大最小歸一化
from sklearn.preprocessing import StandardScaler  # 標準化
from sklearn.model_selection import train_test_split  # 劃分數據集
from sklearn.model_selection import cross_val_score
from xgboost import plot_importance
import matplotlib.pyplot as plt


def trainandTest(X_train, y_train, X_test, y_test):
    # XGBoost訓練過程,下面的參數就是剛纔調試出來的最佳參數組合
    model = xgb.XGBRegressor(
        base_score=0.5,
        booster='gbtree',
        colsample_bylevel=1,
        colsample_bytree=0.9,
        gamma=0,
        importance_type='gain',
        learning_rate=0.1,
        max_delta_step=0,
        max_depth=5,
        min_child_weight=0.2,
        missing=None,
        n_estimators=250,
        n_jobs=1,
        nthread=None,
        objective='reg:linear',
        random_state=0,
        reg_alpha=0,
        reg_lambda=0.8,
        scale_pos_weight=1,
        seed=None,
        silent=True,
        subsample=1
    )
   
    model.fit(X_train, y_train)
    model.save_model('/Users/huamin/Desktop/xgb1029d.model')  # 用於存儲訓練出的模型
    test_preds = pd.DataFrame({"label": y_test})
    test_preds['y_pred'] = model.predict(X_test)
    stdm = metrics.r2_score(test_preds['label'], test_preds['y_pred'])
    print(stdm)
    ans = model.predict(X_test)
    
    ans_len = len(ans)
    id_list = np.arange(10441, 177441)
    data_arr = []
    for row in range(0, ans_len):
        data_arr.append([int(id_list[row]), ans[row]])
    np_data = np.array(data_arr)
    
    pd_data = pd.DataFrame(np_data, columns=['id', 'y'])
    pd_data.to_csv('submit.csv', index=None)
    # 顯示重要特徵
    plot_importance(model)
    plt.show()
    print(model.feature_importances_)


if __name__ == '__main__':
    data = pd.read_csv('/Users/huamin/Desktop/file/iris11.csv', header=None)
    # 0-9列爲特徵
    X = data.iloc[:, 0:10]
    # 第10列爲標籤
    y = data.iloc[:, 10]
    # 劃分訓練集和測試集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=0)
    # 此處採用最大最小歸一化, 可以換成StandardScaler()歸一化方法,如果用StandardScaler()方法的話,則不能使用MultinomialNB()模型
    ss = MinMaxScaler()
    ss=StandardScaler()
    X_train = ss.fit_transform(X_train)
    X_test = ss.transform(X_test)
    trainandTest(X_train, y_train, X_test, y_test)
   
    
  • 預測效果:
def predict():
    #測試數據
    dtest = loadtxt( '/Users/huamin/Desktop/ttt.csv', delimiter=",")
    dtest = dtest[:,1:11]
    dt = loadtxt( '/Users/huamin/Desktop/ttt.csv', delimiter=",",usecols=(0,0), dtype=int )#每條數據對應的id信息
    dtest=xgb.DMatrix(dtest)
    model = xgb.Booster(model_file='/Users/huamin/Desktop/xgb111.model')
    plot_importance(model)
    plt.show()
    print(model.feature_importances_)
    ans = model.predict(dtest)  #預測的結果,標籤
    #print(ans)
    ans_len = len(ans)
    data_arr = []
    for row in range(0, ans_len):
        data_arr.append([dt[row][0], ans[row]])   #預測結果poiid,得分值對
        np_data = np.array(data_arr)
        pd_data = pd.DataFrame(np_data)
        #將預測結果寫入文件
        pd_data.to_csv('/Users/huamin/Desktop/submit.csv', index=None)
    test = loadtxt( '/Users/huamin/Desktop/submit.csv', delimiter=",")
    print(test)
    print("預測結束,請查看桌面submit.csv")
  • 調參篇:
if __name__ == '__main__':
    data=pd.read_csv('/Users/huamin/Desktop/iris0.csv',header=None)
    #0-10列爲特徵
    file_out = '/Users/huamin/Desktop/data/cvsdata.csv'
    file_in = '/Users/huamin/Desktop/data/data.txt'
    file_mid = '/Users/huamin/Desktop/data/mid.csv'
    file_result = "/Users/huamin/Desktop/data/result.csv"
    mfile = '/Users/huamin/Desktop/xgb111.model'
    X=data.iloc[:,0:10]
    #第11列爲標籤                           
    y=data.iloc[:,10] 
    #劃分訓練集和測試集  
    X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=0) 
    #此處採用最大最小歸一化, 可以換成StandardScaler()歸一化方法,如果用StandardScaler()方法的話,則不能使用MultinomialNB()模型
    ss=MinMaxScaler()
    ss=StandardScaler()
    X_train=ss.fit_transform(X_train)
    X_test=ss.transform(X_test)
    #trainandTest(X_train, y_train, X_test)
    pred(mfile, file_out,file_mid)
    
    '''
    cv_params = {'n_estimators': [0,10,20,30,40,45,50,55,60,70,80,90, 100,150, 200]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 500, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}
    #參數的最佳取值:{'n_estimators': 45}
    #最佳模型得分:0.40957357613460915
    '''
    '''
    cv_params = {'max_depth': 4, 'min_child_weight': [1, 2, 3, 4, 5, 6]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 45, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}
    #參數的最佳取值:{'max_depth': 4, 'min_child_weight': 3}
    #最佳模型得分:0.41168308360707423
    '''
    '''
    cv_params = {'gamma': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 45, 'max_depth': 4, 'min_child_weight': 3, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}
    #參數的最佳取值:{'gamma': 0.2}
    #最佳模型得分:0.410086903491763
    '''
    '''
    cv_params = {'subsample': [0.6, 0.7, 0.8, 0.9], 'colsample_bytree': [0.6, 0.7, 0.8, 0.9]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 45, 'max_depth': 4, 'min_child_weight': 3, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0.2, 'reg_alpha': 0, 'reg_lambda': 1}
    #參數的最佳取值:{'colsample_bytree': 0.8, 'subsample': 0.8}
    #最佳模型得分:0.410086903491763
    '''
    '''
    cv_params = {'reg_alpha': [0,0.05, 0.1, 1, 2, 3], 'reg_lambda': [2,2.5, 3,3.5, 4,5,6]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 45, 'max_depth': 4, 'min_child_weight': 3, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0.2, 'reg_alpha': 0, 'reg_lambda': 1}
    #參數的最佳取值:{'reg_alpha': 0.05, 'reg_lambda': 3}
    #最佳模型得分:0.4104793873864756
    '''
    '''
    cv_params = {'learning_rate': [0.01, 0.05, 0.07, 0.1,0.15, 0.2]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 45, 'max_depth': 4, 'min_child_weight': 3, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0.2, 'reg_alpha': 0.05, 'reg_lambda': 3}
    #參數的最佳取值:{'learning_rate': 0.1}
    #最佳模型得分:0.4104793873864756
    

    model = xgb.XGBRegressor(**other_params)
    optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5, verbose=1, n_jobs=4)
    optimized_GBM.fit(X_train, y_train)
    evalute_result = optimized_GBM.cv_results_['mean_test_score']
    print('每輪迭代運行結果:{0}'.format(evalute_result))
    print('參數的最佳取值:{0}'.format(optimized_GBM.best_params_))
    print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
    '''
    

4、參數

模型參數

n_estimatores:總共迭代的次數,即決策樹的個數
early_stopping_rounds:在驗證集上,當連續n次迭代,分數沒有提高後,提前終止訓練。防止overfitting。
max_depth:樹的深度,默認值爲6,典型值3-10。值越大,越容易過擬合;值越小,越容易欠擬合。
min_child_weight:默認值爲1。值越大,越容易欠擬合;值越小,越容易過擬合(值較大時,避免模型學習到局部的特殊樣本)。
subsample:訓練每棵樹時,使用的數據佔全部訓練集的比例。默認值爲1,典型值爲0.5-1。防止overfitting。
colsample_bytree:訓練每棵樹時,使用的特徵佔全部特徵的比例。默認值爲1,典型值爲0.5-1。防止overfitting。

學習任務參數

learning_rate:學習率,控制每次迭代更新權重時的步長,默認0.3。值越小,訓練越慢,典型值爲0.01-0.2。
objective 目標函數,迴歸任務
reg:linear 
reg:logistic
二分類
binary:logistic 概率
binary:logitraw 類別
多分類
multi:softmax num_class=n 返回類別
multi:softprob num_class=n 返回概率
rank:pairwise
eval_metric
迴歸任務(默認rmse)
rmse--均方根誤差
mae--平均絕對誤差
分類任務(默認error)
auc--roc曲線下面積
error--錯誤率(二分類)
merror--錯誤率(多分類)
logloss--負對數似然函數(二分類)
mlogloss--負對數似然函數(多分類)

gamma
懲罰項係數,指定節點分裂所需的最小損失函數下降值。

調參數:https://blog.csdn.net/sinat_35512245/article/details/79700029

參考:https://blog.csdn.net/sinat_35512245/article/details/79700029

           https://blog.csdn.net/u012735708/article/details/83651832

           https://blog.csdn.net/anshuai_aw1/article/details/86018105

           https://blog.csdn.net/seasongirl/article/details/100178083

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