編譯工具:PyCharm
文章目錄
- 編譯工具:PyCharm
- lightGBM原理
- lightGBM的基礎使用
- 案例1:鳶尾花
- 案例2:絕對求生玩家排名預測
- 一、數據處理部分
- 1.數據獲取及分析
- 2.缺失數據處理
- 3.數據規范化
- 4.規范化輸出部分數據
- 5.異常數據處理
- 5.1刪除開掛數據沒有移動卻kill了的
- 5.2刪除駕車殺敵數異常的數據
- 5.3 刪除一局中殺敵數超過30的
- 5.4刪除爆頭率異常數據:認為殺敵人數大于9且爆頭率為100%為異常數據
- 5.5 最大殺敵距離大于1km的玩家
- 5.6運動距離異常
- 5.7武器收集異常
- 5.8使用治療藥品數量異常
- 6.類別型數據處理one-hot處理
- 7.數據截取
- 二、模型訓練部分
- 1.使用隨機森林進行模型訓練
- 2.使用lightgbm進行模型訓練
lightGBM原理
lightGBM主要基于以下幾個方面進行優化,提升整體特性
1.基于Histogram(直方圖)的決策樹算法
2.Lightgbm的Histogram(直方圖)做差加速
3.帶深度限制的Leaf-wise的葉子生長策略
4.直接支持類別特征
5.直接支持高效并行
直方圖算法降低內存消耗,不僅不需要額外存儲與排序的結果,而且可以只保存特征離散化后的值。
一個葉子的直方圖可以由他的父親節點的直方圖與它兄弟節點的直方圖做差得到,效率會高很多。
lightGBM的基礎使用
先安裝包,直接安裝可能會出現問題,建議改成清華大學提供的網站進行安裝,安裝速度快不會出錯,命令行模式安裝的話:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名稱
pycharm安裝的話-i https://pypi.tuna.tsinghua.edu.cn/simple 包名稱
參數
案例1:鳶尾花
# 使用lightgbm模型訓練
import pandas as pd
# sklearn提供的數據集
from sklearn.datasets import load_iris
# 數據分割
from sklearn.model_selection import train_test_split
#
from sklearn.model_selection import GridSearchCV
#
from sklearn.metrics import mean_squared_error
# lightGBM
import lightgbm as lgb# 獲取數據
iris = load_iris()
data = iris.data
target = iris.target# 數據基本處理
# 數據分割
x_train,x_test,y_train,y_test = train_test_split(data,target,test_size=0.2)# 模型訓練
gbm = lgb.LGBMRegressor(objective="regression",learning_rate=0.05,n_estimators=200)
gbm.fit(x_train, y_train, eval_set=[(x_test,y_test)], eval_metric="l1",callbacks=[lgb.early_stopping(stopping_rounds=3)]) #看到訓練過程
print("----------基礎模型訓練----------")
print(gbm.score(x_test, y_test))# 網格搜索進行調優訓練
estimators = lgb.LGBMRegressor(num_leaves=31)
param_grid = {"learning_rate":[0.01,0.1,1],"n_estmators":[20,40,60,80]
}
gbm = GridSearchCV(estimators,param_grid,cv=5)
gbm.fit(x_train,y_train,callbacks=[lgb.log_evaluation(show_stdv=False)])
print("----------最優參數----------")
print(gbm.best_params_)# 獲取到最優參數后,將參數值帶入到里面
gbm = lgb.LGBMRegressor(objective="regression",learning_rate=0.1,n_estimators=20)
gbm.fit(x_train, y_train, eval_set=[(x_test,y_test)], eval_metric="l1",callbacks=[lgb.early_stopping(stopping_rounds=3)]) #看到訓練過程
print("----------帶入最優參數后----------")
print(gbm.score(x_test, y_test))
這里看到基礎模型訓練的結果比帶入最優參數后的結果更好,原因在于基礎訓練里面,我們設置了200步,而最優參數才只需要20步。
案例2:絕對求生玩家排名預測
數據集:https://download.csdn.net/download/m0_51607165/84819953
一、數據處理部分
1.數據獲取及分析
# 絕對求生玩家排名預測
import numpy as np
import numpy as py
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns# 獲取數據以及數據查看分析
train = pd.read_csv("./data/train_V2.csv")
# print(train.head())
print("----------查看一共有多少數據----------")
print(train.shape)
print("----------數據的整體描述----------")
print(train.describe()) # 數據的整體描述
print("----------數據的字段基本描述----------")
print(train.info()) # 數據的字段基本描述
print("----------一共有多少場比賽----------")
# print(train["matchId"])
# 去重
print(np.unique(train["matchId"]).shape)
print("----------有多少隊伍----------")
print(np.unique(train["groupId"]).shape)# 數據處理
# 查看缺失值
# print(np.any(train.isnull()))
2.缺失數據處理
# 查看缺失值
print("----------查看哪里有缺失值----------")
# print(np.any(train.isnull())) # 這個只能打印出True說明存在缺失值
print(train.isnull().any()) # 打印缺失值的情況
# 查看發現只有winPlacePerc有缺失值
# 尋找缺失值,打印出來即可獲取行號為 2744604
print("----------缺失值位置----------")
print(train[train["winPlacePerc"].isnull()])
# 刪除缺失值
train = train.drop(2744604)
print(train.shape)
3.數據規范化
我的pycharm跑不出來了。。。我用轉用線上的 jupyter notebook來寫剩下的部分。
感覺jupyter notebook比pycharm方便
# 數據規范化
# 對每場比賽參加的人數進行統計
count = train.groupby("matchId")["matchId"].transform("count")
# 在train數據中添加一列,為當前該場比賽總參加人數
train["playersJoined"]=count
# print(train.head())
# 參賽人數排序小到大并顯示
# print(train["playersJoined"].sort_values().head())
# 可視化顯示
plt.figure(figsize=(20,8))
sns.countplot(train["playersJoined"])
plt.grid()
plt.show()
# 這里顯示有些比賽人數差距很大,可以添加篩選條件
plt.figure(figsize=(20,8))
sns.countplot(train[train["playersJoined"]>=75]["playersJoined"])
plt.grid()
plt.show()
4.規范化輸出部分數據
每局玩家數不一樣,不能僅靠殺敵數等來進行比較
# kills(殺敵數),damageDealt(總傷害數)、maxPlace(本局最差名次)、matchDuration(比賽時長)
train["killsNorm"]=train["kills"]*((100-train["playersJoined"])/100+1)
train["damageDealtNorm"]=train["damageDealt"]*((100-train["playersJoined"])/100+1)
train["maxPlaceNorm"]=train["maxPlace"]*((100-train["playersJoined"])/100+1)
train["matchDurationNorm"]=train["matchDuration"]*((100-train["playersJoined"])/100+1)train.head()# 比較經過規范化的特征值和原始特征值的值
to_show = ['Id','kills','killsNorm','damageDealt','damageDealtNorm','maxPlace','maxPlaceNorm','matchDuration','matchDurationNorm']
train[to_show][0:11]train['healsandboosts']=train['heals']+train['boosts']train[["heals","boosts","healsandboosts"]].tail()
5.異常數據處理
jupyter
我們認為以下數據為異常數據:
5.1沒有移動有殺敵數的
5.2駕車殺敵大于10的
5.3一局中殺敵超過30的
5.4爆頭率異常的數據:認為殺敵人數大于9且爆頭率為100%為異常數據
5.5最大殺敵距離大于1km的玩家
5.6運動距離異常
5.7武器收集異常
5.8shiyong治療藥品數量異常
5.1刪除開掛數據沒有移動卻kill了的
# 刪除有擊殺但是完全沒有移動的玩家(開掛)
train["totalDistance"]=train["rideDistance"]+train["walkDistance"]+train["swimDistance"]
train.head()train["killwithoutMoving"]=(train["kills"]>0)&(train["totalDistance"]==0)# 查看開掛的數據
train[train["killwithoutMoving"] == True]# 統計以下開掛的數據
train[train["killwithoutMoving"] == True].shape
# 刪除開掛數據
train.drop(train[train["killwithoutMoving"] == True].index,inplace=True)
# 刪除后的整體train數據
train.shape
5.2刪除駕車殺敵數異常的數據
# 刪除駕車殺敵大于10數據
train.drop(train[train["roadKills"] >10].index,inplace=True)
# 刪除后整體train數據情況
train.shape
5.3 刪除一局中殺敵數超過30的
# 刪除一局中殺敵數超過30的
# 先查看
train[train["kills"]>30].head()
train.drop(train[train["kills"]>30].index,inplace=True)
train.shape
5.4刪除爆頭率異常數據:認為殺敵人數大于9且爆頭率為100%為異常數據
# 刪除爆頭率異常的數據
# 計算爆頭率
train["headshot_rate"]=train["headshotKills"]/train["kills"]
train["headshot_rate"].head()# 對NaN的數據進行替換為0
train["headshot_rate"]=train["headshot_rate"].fillna(0)
train.head()# 先檢索有沒有爆頭率有問題的數據:認為殺敵人數大于9且爆頭率為100%為異常數據
train [(train["headshot_rate"]==1)&(train["kills"]>9)].head()# 刪除
train.drop(train[(train["headshot_rate"]==1)&(train["kills"]>9)].index,inplace=True)
train.shape
5.5 最大殺敵距離大于1km的玩家
# 最大殺敵距離大于1km的玩家
train[train["longestKill"]>=1000].shapetrain[train["longestKill"]>=1000]["longestKill"].head()train.drop(train[train["longestKill"]>=1000].index,inplace=True)train.shape
5.6運動距離異常
train[train['walkDistance']>=10000].shapetrain.drop(train[train['walkDistance']>=10000].index,inplace=True)
train.shape
# 載具
train[train['rideDistance']>=20000].shapetrain.drop(train[train['rideDistance']>=20000].index,inplace=True)
train.shape# 游泳距離
train[train['swimDistance']>=2000].shape
train.drop(train[train['swimDistance']>=2000].index,inplace=True)
train.shape
5.7武器收集異常
# 武器收集異常
train[train['weaponsAcquired']>=80].index
train.drop(train[train['weaponsAcquired']>=80].index,inplace=True)
train.shape
5.8使用治療藥品數量異常
# 使用治療藥品數量異常
train[train['heals']>=80].index
train.drop(train[train['heals']>=80].index,inplace=True)
train.shape
6.類別型數據處理one-hot處理
# 查看比賽類別
train["matchType"].unique()
# 將比賽數據轉換
train = pd.get_dummies(train,columns=["matchType"])
train.head()
# 正則化
matchType_encoding = train.filter(regex="matchType")
matchType_encoding.head()
# 對groupId數據轉換
train["groupId"].head()
# 將類型轉為category
train["groupId"]=train["groupId"].astype("category")
train["groupId"].head()
train["groupId_cat"]=train["groupId"].cat.codes
train["groupId_cat"].head()# 處理matchId
train["matchId"]=train["matchId"].astype("category")
# train["matchId"].head()
train["matchId_cat"]=train["matchId"].cat.codes
train["matchId_cat"].head()# 將原來的groupId和matchId刪除,axis=1按照列刪除
train.drop(["groupId","matchId"],axis=1,inplace=True)
train.head()
7.數據截取
df_sample = train.sample(100000)
df_sample.shape# 確定特征值和目標值
df = df_sample.drop(["winPlacePerc","Id"],axis=1)
y=df_sample["winPlacePerc"]
df.shape# 分割測試集和測試集
from sklearn.model_selection import train_test_splitx_train,x_valid,y_train,y_valid = train_test_split(df,y,test_size=0.2)
二、模型訓練部分
兩種模型訓練結果進行對比:
1.使用隨機森林進行模型訓練
2.使用lightgbm進行模型訓練
1.使用隨機森林進行模型訓練
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error
# 初步訓練
# n_jobs = -1表示訓練的時候,并行數和cpu的核數一樣,如果傳入具體的值,表示用幾個核去泡
m1 = RandomForestRegressor(n_estimators=40,min_samples_leaf=3,max_features='sqrt',n_jobs=-1)
m1.fit(x_train,y_train)y_pre = m1.predict(x_valid)
m1.score(x_valid,y_valid)mean_absolute_error(y_valid,y_pre)# 再次使用隨機森林進行模型訓練
# 去除冗余特征
m1.feature_importances_
imp_df = pd.DataFrame({"cols":df.columns,"imp":m1.feature_importances_})
imp_df.head()imp_df = imp_df.sort_values("imp",ascending=False)
imp_df.head()imp_df.plot("cols","imp",figsize=(20,8),kind="barh")imp_df[:20].plot("cols","imp",figsize=(20,8),kind="barh")# 找到相對比較重要的特征,去除一些冗余特征
to_keep=imp_df[imp_df.imp>0.005].cols
to_keepdf_keep = df[to_keep]
x_train,x_valid,y_train,y_valid=train_test_split(df_keep,y,test_size=0.2)
x_train.shape
m2 = RandomForestRegressor(n_estimators=40,min_samples_leaf=3,max_features='sqrt',n_jobs=-1)
m2.fit(x_train,y_train)# 模型評估
y_pre = m2.predict(x_valid)
m2.score(x_valid,y_valid)mean_absolute_error(y_valid,y_pre)
2.使用lightgbm進行模型訓練
import lightgbm as lgb# 初步lightgbm訓練
x_train,x_valid,y_train,y_valid = train_test_split(df,y,test_size=0.2)
x_train.shapegbm = lgb.LGBMRegressor(objective="regression",num_leaves=31,learning_rate=0.05,n_estimators=20)
gbm.fit(x_train,y_train,eval_set=[(x_valid,y_valid)],eval_metric="l1",early_stopping_rounds=5)y_pre = gbm.predict(x_valid,num_iteration=gbm.best_iteration_)
mean_absolute_error(y_valid,y_pre)# 第二次調優:網格搜索進行參數調優
from sklearn.model_selection import GridSearchCVestimator = lgb.LGBMRegressor(num_leaves=31)
param_grid={"learning_rate":[0.01,0.1,1],00"n_estimators":[40,60,80,100,200,300]}
gbm = GridSearchCV(estimator,param_grid,cv=5,n_jobs=-1)
gbm.fit(x_train,y_train,eval_set=[(x_valid,y_valid)],eval_metric="l1",early_stopping_rounds=5)y_pred = gbm.predict(x_valid)
mean_absolute_error(y_valid,y_pred)gbm.best_params_# 第三次調優
# n_estimators
scores = []
n_estimators = [100,500,1000]
for nes in n_estimators:lgbm = lgb.LGBMRegressor(boosting_type='gbdt',num_leaves=31,max_depth=5,learning_rate=0.1,n_estimators=nes,min_child_samples=20,n_jobs=-1)lgbm.fit(x_train,y_train,eval_set=[(x_valid,y_valid)],eval_metric='l1',early_stopping_rounds=5)y_pre = lgbm.predict(x_valid)mae = mean_absolute_error(y_valid,y_pre)scores.append(mae)mae
# 可視化
import numpy as np
plt.plot(n_estimators,scores,'o-')
plt.ylabel("mae")
plt.xlabel("n_estimator")
print("best n_estimator {}".format(n_estimators[np.argmin(scores)]))# 通過這種方式,可以繼續對其他的參數調優,找到最優的參數
# ......