目錄
一:python語(yǔ)法回顧
1.1? print()
1.2? 列表與字典
1.3自定義函數(shù)與return
1.4火車(chē)類(lèi)(面向?qū)ο螅?
實(shí)例化總結(jié):
二:LightGBM 代碼精讀
2.1導(dǎo)入庫(kù)
2.2數(shù)據(jù)準(zhǔn)備與參數(shù)設(shè)置
?2.3時(shí)間特征函數(shù)
??2.4優(yōu)化
?2.5訓(xùn)練與預(yù)測(cè)
三:優(yōu)化講解
3.1:
3.2優(yōu)化建議:
一:python語(yǔ)法回顧
1.1? print()
-
每一個(gè)print()會(huì)默認(rèn)換行,若不想換行則:print("",end=""),默認(rèn)end="\t"
-
單行注釋 使用“#”開(kāi)頭,只能寫(xiě)在一行中~
1.2? 列表與字典
-
列表是一種序列,他是可變的:容器的唯一作用就是打包、解包、內(nèi)容傳遞】
-
列表定義:p2s = []
-
字典是鍵值對(duì)的集合
-
定義一個(gè)集合:Dw_set = set() 用add()函數(shù)將詩(shī)句插入集合中
-
定義一個(gè)字典:dw_dict = {"d":"Data","w":"whale"} # key:value 鍵:值;
-
字典可以利用鍵去查詢(xún)對(duì)應(yīng)的值
-
字典的更新:dw_dict["w"] = "whale"
1.3自定義函數(shù)與return
? ? ?回調(diào)函數(shù)(callback)
1.4火車(chē)類(lèi)(面向?qū)ο螅?/strong>?
-
發(fā)車(chē)函數(shù)里,有一個(gè)"_"意思是不賦值給任何變量,是一個(gè)黑洞
實(shí)例化總結(jié):
?
二:LightGBM 代碼精讀
2.1導(dǎo)入庫(kù)
!pip install -U lightgbm
!unzip data/data227148/data.zip
#特別適合處理大規(guī)模數(shù)據(jù)集。
#當(dāng)處理大規(guī)模數(shù)據(jù)集、需要高效訓(xùn)練和預(yù)測(cè)速度,并且希望獲得較好的性能時(shí),LightGBM通常是一個(gè)不錯(cuò)的選擇。
# 導(dǎo)入所需的庫(kù)
import pandas as pd # 讀取和處理csv文件的數(shù)據(jù)
#用于處理數(shù)據(jù)的工具,常用于數(shù)據(jù)加載、數(shù)據(jù)清洗和數(shù)據(jù)預(yù)處理。
import lightgbm as lgb # 機(jī)器學(xué)習(xí)模型 LightGBM
#構(gòu)建梯度提升樹(shù)模型,是一種高效的機(jī)器學(xué)習(xí)算法。
from sklearn.metrics import mean_absolute_error # 評(píng)分 MAE 的計(jì)算函數(shù)
#從sklearn.metrics模塊中導(dǎo)入評(píng)分函數(shù)
#平均絕對(duì)誤差(MAE),是用于回歸問(wèn)題的一個(gè)評(píng)價(jià)指標(biāo)。
from sklearn.model_selection import train_test_split # 拆分訓(xùn)練集與驗(yàn)證集工具
#用于將數(shù)據(jù)集拆分為訓(xùn)練集和驗(yàn)證集,以便進(jìn)行模型訓(xùn)練和評(píng)估。
#sklearn.model_selection:對(duì)機(jī)器學(xué)習(xí)模型進(jìn)行參數(shù)調(diào)優(yōu)、數(shù)據(jù)集拆分、交叉驗(yàn)證和性能評(píng)估等任務(wù)。
#train_test_split函數(shù):將數(shù)據(jù)集劃分為訓(xùn)練集和測(cè)試集,并且可以靈活地設(shè)置拆分比例和隨機(jī)種子。
from tqdm import tqdm # 顯示循環(huán)的進(jìn)度條工具
#循環(huán)過(guò)程中顯示進(jìn)度條,方便查看代碼執(zhí)行進(jìn)度。
2.2數(shù)據(jù)準(zhǔn)備與參數(shù)設(shè)置
# 數(shù)據(jù)準(zhǔn)備
train_dataset = pd.read_csv("C:\\Users\\86198\\OneDrive\\桌面\\train.csv") # 原始訓(xùn)練數(shù)據(jù)。
test_dataset = pd.read_csv("C:\\Users\\86198\\OneDrive\\桌面\\test.csv") # 原始測(cè)試數(shù)據(jù)(用于提交)。
submit = pd.DataFrame() # 定義提交的最終數(shù)據(jù)。
submit["序號(hào)"] = test_dataset["序號(hào)"] # 對(duì)齊測(cè)試數(shù)據(jù)的序號(hào),保持與原始測(cè)試數(shù)據(jù)的一致性。
MAE_scores = dict() # 定義評(píng)分項(xiàng)。
# 模型參數(shù)設(shè)置
pred_labels = list(train_dataset.columns[-34:]) #訓(xùn)練數(shù)據(jù)集的最后34列是需要預(yù)測(cè)的目標(biāo)變量。
train_set, valid_set = train_test_split(train_dataset, test_size=0.2) # 拆分?jǐn)?shù)據(jù)集。
# 設(shè)定 LightGBM 訓(xùn)練參,查閱參數(shù)意義:https://lightgbm.readthedocs.io/en/latest/Parameters.html
lgb_params = {
'boosting_type': 'gbdt', #使用的提升方法,使用梯度提升決策樹(shù)gbdt。
'objective': 'regression', #優(yōu)化目標(biāo),這里設(shè)置為'regression',表示使用回歸任務(wù)進(jìn)行優(yōu)化。
'metric': 'mae', #評(píng)估指標(biāo),使用MAE,表示使用平均絕對(duì)誤差作為評(píng)估指標(biāo)。
'min_child_weight': 5, #子節(jié)點(diǎn)中樣本權(quán)重的最小和,用于控制過(guò)擬合。
'num_leaves': 2 ** 5, #每棵樹(shù)上的葉子節(jié)點(diǎn)數(shù),影響模型的復(fù)雜度。
'lambda_l2': 10, #L2正則化項(xiàng)的權(quán)重,用于控制模型的復(fù)雜度。
'feature_fraction': 0.8, #隨機(jī)選擇特征的比例,用于防止過(guò)擬合。
'bagging_fraction': 0.8, #隨機(jī)選擇數(shù)據(jù)的比例,用于防止過(guò)擬合。
'bagging_freq': 4, # 隨機(jī)選擇數(shù)據(jù)的頻率,用于防止過(guò)擬合。
'learning_rate': 0.05, #學(xué)習(xí)率,控制每次迭代的步長(zhǎng)。
'seed': 2023, #隨機(jī)種子,用于產(chǎn)生隨機(jī)性,保持結(jié)果的可重復(fù)性。
'nthread' : 16, #并行線(xiàn)程數(shù),用于加速模型訓(xùn)練。
'verbose' : -1, #控制訓(xùn)練日志輸出,-1表示禁用輸出。
}
#調(diào)整參數(shù)是優(yōu)化模型性能的重要手段
no_info = lgb.callback.log_evaluation(period=-1) # 回調(diào)函數(shù)no_info:禁用訓(xùn)練日志輸出。
#LightGBM通常會(huì)輸出一些訓(xùn)練過(guò)程的信息,通過(guò)回調(diào)函數(shù)可以避免輸出這些信息,使得訓(xùn)練過(guò)程更簡(jiǎn)潔。
?2.3時(shí)間特征函數(shù)
# 時(shí)間特征函數(shù) 特征提取
def time_feature(data: pd.DataFrame, pred_labels: list = None) -> pd.DataFrame:
"""提取數(shù)據(jù)中的時(shí)間特征。
輸入:
data: Pandas.DataFrame
需要提取時(shí)間特征的數(shù)據(jù)。
pred_labels: list, 默認(rèn)值: None
需要預(yù)測(cè)的標(biāo)簽的列表。如果是測(cè)試集,不需要填入。
輸出: data: Pandas.DataFrame
提取時(shí)間特征后的數(shù)據(jù)。
"""
# 接收數(shù)據(jù)集DataFrame和可選參數(shù)pred_labels,返回處理后的DataFrame
data = data.copy() # 復(fù)制數(shù)據(jù),避免后續(xù)影響原始數(shù)據(jù)。
data = data.drop(columns=["序號(hào)"]) # 去掉”序號(hào)“特征。
data["時(shí)間"] = pd.to_datetime(data["時(shí)間"]) # 將”時(shí)間“特征的文本內(nèi)容轉(zhuǎn)換為 Pandas 可處理的格式。
data["month"] = data["時(shí)間"].dt.month # 添加新特征“month”,代表”當(dāng)前月份“。
data["day"] = data["時(shí)間"].dt.day # 添加新特征“day”,代表”當(dāng)前日期“。
data["hour"] = data["時(shí)間"].dt.hour # 添加新特征“hour”,代表”當(dāng)前小時(shí)“。
data["minute"] = data["時(shí)間"].dt.minute # 添加新特征“minute”,代表”當(dāng)前分鐘“。
data["weekofyear"] = data["時(shí)間"].dt.isocalendar().week.astype(int) # 添加新特征“weekofyear”,代表”當(dāng)年第幾周“,
# 并轉(zhuǎn)換成 int整數(shù)類(lèi)型,否則 LightGBM 無(wú)法處理。
data["dayofyear"] = data["時(shí)間"].dt.dayofyear # 添加新特征“dayofyear”,代表”當(dāng)年第幾日“。
data["dayofweek"] = data["時(shí)間"].dt.dayofweek # 添加新特征“dayofweek”,代表”當(dāng)周第幾日“。
data["is_weekend"] = data["時(shí)間"].dt.dayofweek // 6 # 添加新特征“is_weekend”,代表”是否是周末“,1 代表是周末,0 代表不是周末。
data = data.drop(columns=["時(shí)間"]) # LightGBM 無(wú)法處理這個(gè)特征,它已體現(xiàn)在其他特征中,故丟棄。
??2.4優(yōu)化
# 新加入特征代碼展示(不必運(yùn)行)
# 交叉特征
for i in range(1,18):
train[f'流量{i}/上部溫度設(shè)定{i}'] = train[f'流量{i}'] / train[f'上部溫度設(shè)定{i}']
test[f'流量{i}/上部溫度設(shè)定{i}'] = test[f'流量{i}'] / test[f'上部溫度設(shè)定{i}']
train[f'流量{i}/下部溫度設(shè)定{i}'] = train[f'流量{i}'] / train[f'下部溫度設(shè)定{i}']
test[f'流量{i}/下部溫度設(shè)定{i}'] = test[f'流量{i}'] / test[f'下部溫度設(shè)定{i}']
train[f'上部溫度設(shè)定{i}/下部溫度設(shè)定{i}'] = train[f'上部溫度設(shè)定{i}'] / train[f'下部溫度設(shè)定{i}']
test[f'上部溫度設(shè)定{i}/下部溫度設(shè)定{i}'] = test[f'上部溫度設(shè)定{i}'] / test[f'下部溫度設(shè)定{i}']
# 歷史平移
for i in range(1,18):
train[f'last1_流量{i}'] = train[f'流量{i}'].shift(1)
train[f'last1_上部溫度設(shè)定{i}'] = train[f'上部溫度設(shè)定{i}'].shift(1)
train[f'last1_下部溫度設(shè)定{i}'] = train[f'下部溫度設(shè)定{i}'].shift(1)
test[f'last1_流量{i}'] = test[f'流量{i}'].shift(1)
test[f'last1_上部溫度設(shè)定{i}'] = test[f'上部溫度設(shè)定{i}'].shift(1)
test[f'last1_下部溫度設(shè)定{i}'] = test[f'下部溫度設(shè)定{i}'].shift(1)
# 差分特征
for i in range(1,18):
train[f'last1_diff_流量{i}'] = train[f'流量{i}'].diff(1)
train[f'last1_diff_上部溫度設(shè)定{i}'] = train[f'上部溫度設(shè)定{i}'].diff(1)
train[f'last1_diff_下部溫度設(shè)定{i}'] = train[f'下部溫度設(shè)定{i}'].diff(1)
test[f'last1_diff_流量{i}'] = test[f'流量{i}'].diff(1)
test[f'last1_diff_上部溫度設(shè)定{i}'] = test[f'上部溫度設(shè)定{i}'].diff(1)
test[f'last1_diff_下部溫度設(shè)定{i}'] = test[f'下部溫度設(shè)定{i}'].diff(1)
# 窗口統(tǒng)計(jì)
for i in range(1,18):
train[f'win3_mean_流量{i}'] = (train[f'流量{i}'].shift(1) + train[f'流量{i}'].shift(2) + train[f'流量{i}'].shift(3)) / 3
train[f'win3_mean_上部溫度設(shè)定{i}'] = (train[f'上部溫度設(shè)定{i}'].shift(1) + train[f'上部溫度設(shè)定{i}'].shift(2) + train[f'上部溫度設(shè)定{i}'].shift(3)) / 3
train[f'win3_mean_下部溫度設(shè)定{i}'] = (train[f'下部溫度設(shè)定{i}'].shift(1) + train[f'下部溫度設(shè)定{i}'].shift(2) + train[f'下部溫度設(shè)定{i}'].shift(3)) / 3
test[f'win3_mean_流量{i}'] = (test[f'流量{i}'].shift(1) + test[f'流量{i}'].shift(2) + test[f'流量{i}'].shift(3)) / 3
test[f'win3_mean_上部溫度設(shè)定{i}'] = (test[f'上部溫度設(shè)定{i}'].shift(1) + test[f'上部溫度設(shè)定{i}'].shift(2) + test[f'上部溫度設(shè)定{i}'].shift(3)) / 3
test[f'win3_mean_下部溫度設(shè)定{i}'] = (test[f'下部溫度設(shè)定{i}'].shift(1) + test[f'下部溫度設(shè)定{i}'].shift(2) + test[f'下部溫度設(shè)定{i}'].shift(3)) / 3
if pred_labels: # 如果提供了 pred_labels 參數(shù),則執(zhí)行該代碼塊。
data = data.drop(columns=[*pred_labels]) # 去掉所有待預(yù)測(cè)的標(biāo)簽。在模型訓(xùn)練時(shí)不使用這些標(biāo)簽。
return data # 返回最后處理的數(shù)據(jù)。
test_features = time_feature(test_dataset) # 處理測(cè)試集的時(shí)間特征,無(wú)需 pred_labels。
?2.5訓(xùn)練與預(yù)測(cè)
# 從所有待預(yù)測(cè)特征中依次取出標(biāo)簽進(jìn)行訓(xùn)練與預(yù)測(cè)。
for pred_label in tqdm(pred_labels):
# print("當(dāng)前的pred_label是:", pred_label)
train_features = time_feature(train_set, pred_labels=pred_labels) # 處理訓(xùn)練集的時(shí)間特征。
# train_features = enhancement(train_features_raw)
# 調(diào)用time_feature函數(shù)處理訓(xùn)練集train_set的時(shí)間特征,并將處理后的訓(xùn)練集數(shù)據(jù)賦值給train_features
train_labels = train_set[pred_label] # 訓(xùn)練集的標(biāo)簽數(shù)據(jù)。
# print("當(dāng)前的train_labels是:", train_labels)
# 獲取當(dāng)前特征標(biāo)簽pred_label在訓(xùn)練集中的真實(shí)值,并賦值給train_labels。
train_data = lgb.Dataset(train_features, label=train_labels) # 將訓(xùn)練集轉(zhuǎn)換為 LightGBM 可處理的類(lèi)型。
# 將train_features和train_labels轉(zhuǎn)換為L(zhǎng)ightGBM可處理的數(shù)據(jù)類(lèi)型,創(chuàng)建訓(xùn)練數(shù)據(jù)集train_data。
valid_features = time_feature(valid_set, pred_labels=pred_labels) # 處理驗(yàn)證集的時(shí)間特征。
# valid_features = enhancement(valid_features_raw)
# 調(diào)用time_feature函數(shù)處理驗(yàn)證集valid_set的時(shí)間特征,并將處理后的驗(yàn)證集數(shù)據(jù)賦值給valid_features。
valid_labels = valid_set[pred_label] # 驗(yàn)證集的標(biāo)簽數(shù)據(jù)。
# print("當(dāng)前的valid_labels是:", valid_labels)
# 獲取當(dāng)前特征標(biāo)簽pred_label在驗(yàn)證集中的真實(shí)值,并賦值給valid_labels。
valid_data = lgb.Dataset(valid_features, label=valid_labels) # 將驗(yàn)證集轉(zhuǎn)換為 LightGBM 可處理的類(lèi)型。
# 訓(xùn)練模型,參數(shù)依次為:導(dǎo)入模型設(shè)定參數(shù)、導(dǎo)入訓(xùn)練集、設(shè)定模型迭代次數(shù)(5000)、導(dǎo)入驗(yàn)證集、禁止輸出日志
model = lgb.train(lgb_params, train_data, 5000, valid_sets=valid_data, callbacks=[no_info])
valid_pred = model.predict(valid_features, num_iteration=model.best_iteration) # 選擇效果最好的模型進(jìn)行驗(yàn)證集預(yù)測(cè)。
test_pred = model.predict(test_features, num_iteration=model.best_iteration) # 選擇效果最好的模型進(jìn)行測(cè)試集預(yù)測(cè)。
MAE_score = mean_absolute_error(valid_pred, valid_labels) # 計(jì)算驗(yàn)證集預(yù)測(cè)數(shù)據(jù)與真實(shí)數(shù)據(jù)的 MAE。
MAE_scores[pred_label] = MAE_score # 將對(duì)應(yīng)標(biāo)簽的 MAE 值 存入評(píng)分項(xiàng)中。
submit[pred_label] = test_pred # 將測(cè)試集預(yù)測(cè)數(shù)據(jù)存入最終提交數(shù)據(jù)中。
submit.to_csv(r"C:\Users\86198\OneDrive\桌面\submit_result.csv", index=False) # 保存最后的預(yù)測(cè)結(jié)果到 submit_result.csv
# 保存文件并查看結(jié)果
submit.to_csv(r"C:\Users\86198\OneDrive\桌面\submit_result.csv", index=False) # 保存最后的預(yù)測(cè)結(jié)果到 submit_result.csv。
print(MAE_scores) # 查看各項(xiàng)的 MAE 值。
三:優(yōu)化講解
3.1:
具體地,我們可以嘗試提取更多特征改善最終結(jié)果,這也是數(shù)據(jù)挖掘比賽中的主要優(yōu)化方向,很多情況下決定著最終的成績(jī)。
這里主要構(gòu)建了交叉特征、歷史平移特征、差分特征、和窗口統(tǒng)計(jì)特征;每種特征都是有理可據(jù)的,具體說(shuō)明如下:
(1)交叉特征:主要提取流量、上部溫度設(shè)定、下部溫度設(shè)定之間的關(guān)系;
(2)歷史平移特征:通過(guò)歷史平移獲取上個(gè)階段的信息;
(3)差分特征:可以幫助獲取相鄰階段的增長(zhǎng)差異,描述數(shù)據(jù)的漲減變化情況。在此基礎(chǔ)上還可以構(gòu)建相鄰數(shù)據(jù)比值變化、二階差分等;
(4)窗口統(tǒng)計(jì)特征:窗口統(tǒng)計(jì)可以構(gòu)建不同的窗口大小,然后基于窗口范圍進(jìn)統(tǒng)計(jì)均值、最大值、最小值、中位數(shù)、方差的信息,可以反映最近階段數(shù)據(jù)的變化情況。
3.2優(yōu)化建議:
1、過(guò)擬合現(xiàn)象
在代碼運(yùn)行的時(shí)候可以將callbacks=[no_info]
去除,以查看模型運(yùn)行的日志,運(yùn)行結(jié)束后也可以利用代碼print(MAE_scores)
來(lái)打印出最終的損失,觀(guān)察不難看出,模型會(huì)在一定時(shí)間后進(jìn)入過(guò)擬合,因此可以嘗試以一些措施來(lái)緩解這種現(xiàn)象。
- 利用lightgbm自帶的early_stopping_rounds參數(shù)。
- 采用多折驗(yàn)證的方式擴(kuò)大數(shù)據(jù)量,使得模型泛化能力增強(qiáng)。
2、 參數(shù)設(shè)定
此次基線(xiàn)沒(méi)有做精確的調(diào)參處理,因此可以調(diào)參的范圍還是挺大的,常用的搜索參數(shù)策略有兩種:
-
網(wǎng)格搜索(Grid Search):這是一種傳統(tǒng)的參數(shù)調(diào)整方法,它會(huì)測(cè)試指定參數(shù)的所有可能組合來(lái)找出最佳參數(shù)。但是,當(dāng)參數(shù)空間較大時(shí),這種方法可能會(huì)消耗大量計(jì)算資源和時(shí)間。
-
隨機(jī)搜索(Random Search):與網(wǎng)格搜索相比,隨機(jī)搜索不會(huì)測(cè)試所有的參數(shù)組合,而是在參數(shù)空間中隨機(jī)選擇一定數(shù)量的參數(shù)組合進(jìn)行測(cè)試。盡管隨機(jī)搜索可能無(wú)法找到最優(yōu)的參數(shù)組合,但在計(jì)算資源有限的情況下,它是一個(gè)有效的選擇。
3、 模型設(shè)定
我們此次基線(xiàn)采用的是LightGBM,我們也可以試試XGBoost, Adaboost, Catboost等等傳統(tǒng)的模型,并且也可以使用深度學(xué)習(xí)的方法構(gòu)建循環(huán)神經(jīng)網(wǎng)絡(luò)來(lái)處理此次任務(wù),因?yàn)楸举|(zhì)是一個(gè)時(shí)序任務(wù),在采用機(jī)器學(xué)習(xí)的同時(shí)也可以保存模型的參數(shù)配置,嘗試進(jìn)行模型集成的訓(xùn)練。
4、 特征
在特征選擇方面,目前給出的特征僅僅是單獨(dú)對(duì)時(shí)間處理,與對(duì)流量\上\下\部溫度設(shè)定進(jìn)行處理,并未結(jié)合時(shí)間與其他特征的關(guān)系,可以嘗試自己構(gòu)建合理的新特征。
5、 后處理
對(duì)已經(jīng)給出的csv文件仍然可以分析其趨勢(shì),抓住評(píng)估的關(guān)鍵來(lái)調(diào)整文件內(nèi)容使得結(jié)果更加精確。
6、 迭代步數(shù) 目前設(shè)置的迭代步數(shù)為200輪,其實(shí)這對(duì)于某些預(yù)測(cè)數(shù)據(jù)來(lái)說(shuō)是不夠的,可以嘗試自己增大迭代步數(shù)
baseline進(jìn)行修改優(yōu)化后并跑通,結(jié)果可觀(guān)如下:
調(diào)整參數(shù)后:?
參考文章:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-621160.html
datawhale暑期夏令營(yíng):datawhale開(kāi)源項(xiàng)目文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-621160.html
到了這里,關(guān)于【Datawhale夏令營(yíng)】任務(wù)二學(xué)習(xí)筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!