test: 扩展12特征非线性日期编码对比
This commit is contained in:
128
extended_12_feature_experiment.py
Normal file
128
extended_12_feature_experiment.py
Normal file
@@ -0,0 +1,128 @@
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from sklearn.compose import ColumnTransformer
|
||||
from sklearn.ensemble import ExtraTreesRegressor, GradientBoostingRegressor, HistGradientBoostingRegressor, RandomForestRegressor
|
||||
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
|
||||
from sklearn.pipeline import Pipeline
|
||||
from sklearn.preprocessing import OneHotEncoder, StandardScaler
|
||||
from sklearn.svm import SVR
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
DATA_PATH = Path('/root/.hermes-web-ui/upload/default/28752a235eb6ef9d.xlsx')
|
||||
OUT_DIR = BASE_DIR / 'outputs' / 'time_split_experiment'
|
||||
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
TARGET = '总骑行量'
|
||||
BASE_FEATURES = ['年', '季节', '月', '节假日', '星期', '工作日', '天气', '气温', '体感温度', '湿度', '风速']
|
||||
BASE_CAT = ['年', '季节', '月', '节假日', '星期', '工作日', '天气']
|
||||
|
||||
|
||||
def rmse(y_true, y_pred):
|
||||
return float(np.sqrt(mean_squared_error(y_true, y_pred)))
|
||||
|
||||
|
||||
def add_features(df, min_date):
|
||||
df = df.copy()
|
||||
df['日期数值'] = (df['日期'] - min_date).dt.days
|
||||
df['一年中的第几天'] = df['日期'].dt.dayofyear
|
||||
df['月内日'] = df['日期'].dt.day
|
||||
df['周序号'] = df['日期'].dt.isocalendar().week.astype(int)
|
||||
df['日期_sin'] = np.sin(2 * np.pi * df['一年中的第几天'] / 365.25)
|
||||
df['日期_cos'] = np.cos(2 * np.pi * df['一年中的第几天'] / 365.25)
|
||||
df['周序号_sin'] = np.sin(2 * np.pi * df['周序号'] / 52.18)
|
||||
df['月内日_sin'] = np.sin(2 * np.pi * df['月内日'] / 31)
|
||||
df['年内进度'] = df['一年中的第几天'] / 365.25
|
||||
df['季度内月份'] = ((df['月'] - 1) % 3) + 1
|
||||
df['是否月初'] = (df['月内日'] <= 7).astype(int)
|
||||
df['是否月末'] = (df['月内日'] >= 24).astype(int)
|
||||
df['日期分箱4'] = pd.qcut(df['日期数值'], q=4, labels=False, duplicates='drop').astype(int)
|
||||
df['日期分箱8'] = pd.qcut(df['日期数值'], q=8, labels=False, duplicates='drop').astype(int)
|
||||
return df
|
||||
|
||||
|
||||
def make_pipeline(model_name, estimator, features, categorical):
|
||||
numeric = [col for col in features if col not in categorical]
|
||||
need_scale = model_name == 'SVR'
|
||||
preprocessor = ColumnTransformer(
|
||||
transformers=[
|
||||
('cat', OneHotEncoder(handle_unknown='ignore', sparse_output=False), categorical),
|
||||
('num', StandardScaler() if need_scale else 'passthrough', numeric),
|
||||
],
|
||||
verbose_feature_names_out=False,
|
||||
)
|
||||
return Pipeline([('preprocess', preprocessor), ('model', estimator)])
|
||||
|
||||
|
||||
def main():
|
||||
daily = pd.read_excel(DATA_PATH, sheet_name='每天数据')
|
||||
future = pd.read_excel(DATA_PATH, sheet_name='预测集')
|
||||
daily['日期'] = pd.to_datetime(daily['日期'])
|
||||
future['日期'] = pd.to_datetime(future['日期'])
|
||||
daily = daily.sort_values('日期').reset_index(drop=True)
|
||||
future = future.sort_values('日期').reset_index(drop=True)
|
||||
min_date = daily['日期'].min()
|
||||
daily = add_features(daily, min_date)
|
||||
future = add_features(future, min_date)
|
||||
|
||||
split_idx = int(len(daily) * 0.8)
|
||||
train = daily.iloc[:split_idx].copy()
|
||||
test = daily.iloc[split_idx:].copy()
|
||||
|
||||
feature_schemes = {
|
||||
'12_日期数值': (['日期数值'] + BASE_FEATURES, BASE_CAT),
|
||||
'12_日期sin': (['日期_sin'] + BASE_FEATURES, BASE_CAT),
|
||||
'12_日期cos': (['日期_cos'] + BASE_FEATURES, BASE_CAT),
|
||||
'12_年内第几天': (['一年中的第几天'] + BASE_FEATURES, BASE_CAT),
|
||||
'12_年内进度': (['年内进度'] + BASE_FEATURES, BASE_CAT),
|
||||
'12_周序号': (['周序号'] + BASE_FEATURES, BASE_CAT + ['周序号']),
|
||||
'12_周序号sin': (['周序号_sin'] + BASE_FEATURES, BASE_CAT),
|
||||
'12_月内日': (['月内日'] + BASE_FEATURES, BASE_CAT + ['月内日']),
|
||||
'12_月内日sin': (['月内日_sin'] + BASE_FEATURES, BASE_CAT),
|
||||
'12_季度内月份': (['季度内月份'] + BASE_FEATURES, BASE_CAT + ['季度内月份']),
|
||||
'12_是否月初': (['是否月初'] + BASE_FEATURES, BASE_CAT + ['是否月初']),
|
||||
'12_是否月末': (['是否月末'] + BASE_FEATURES, BASE_CAT + ['是否月末']),
|
||||
'12_日期分箱4': (['日期分箱4'] + BASE_FEATURES, BASE_CAT + ['日期分箱4']),
|
||||
'12_日期分箱8': (['日期分箱8'] + BASE_FEATURES, BASE_CAT + ['日期分箱8']),
|
||||
}
|
||||
|
||||
models = {
|
||||
'梯度提升树': lambda: GradientBoostingRegressor(random_state=42, n_estimators=300, learning_rate=0.05, max_depth=3),
|
||||
'随机森林': lambda: RandomForestRegressor(n_estimators=500, random_state=42, min_samples_leaf=2, n_jobs=-1),
|
||||
'极端随机树': lambda: ExtraTreesRegressor(n_estimators=500, random_state=42, min_samples_leaf=2, n_jobs=-1),
|
||||
'HistGBDT': lambda: HistGradientBoostingRegressor(random_state=42, max_iter=300, learning_rate=0.05, max_leaf_nodes=31),
|
||||
'SVR': lambda: SVR(C=200, gamma='scale', epsilon=50),
|
||||
}
|
||||
|
||||
rows = []
|
||||
for scheme_name, (features, categorical) in feature_schemes.items():
|
||||
for model_name, factory in models.items():
|
||||
pipe = make_pipeline(model_name, factory(), features, categorical)
|
||||
pipe.fit(train[features], train[TARGET])
|
||||
pred = pipe.predict(test[features])
|
||||
future_pred = np.maximum(np.round(pipe.predict(future[features])), 0).astype(int)
|
||||
rows.append({
|
||||
'方案': scheme_name,
|
||||
'模型': model_name,
|
||||
'RMSE': rmse(test[TARGET], pred),
|
||||
'MAE': float(mean_absolute_error(test[TARGET], pred)),
|
||||
'R2': float(r2_score(test[TARGET], pred)),
|
||||
'未来预测最小值': int(future_pred.min()),
|
||||
'未来预测最大值': int(future_pred.max()),
|
||||
'未来预测均值': float(future_pred.mean()),
|
||||
})
|
||||
|
||||
result = pd.DataFrame(rows)
|
||||
result.to_csv(OUT_DIR / 'extended_12_feature_nonlinear_comparison.csv', index=False, encoding='utf-8-sig')
|
||||
print('各模型最佳前5:')
|
||||
for model_name, group in result.groupby('模型'):
|
||||
print('\n[' + model_name + ']')
|
||||
print(group.sort_values('RMSE').head(5).to_string(index=False, float_format=lambda x: f'{x:.3f}'))
|
||||
print('\n总体前15:')
|
||||
print(result.sort_values('RMSE').head(15).to_string(index=False, float_format=lambda x: f'{x:.3f}'))
|
||||
print('\n保存:', OUT_DIR / 'extended_12_feature_nonlinear_comparison.csv')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,71 @@
|
||||
方案,模型,RMSE,MAE,R2,未来预测最小值,未来预测最大值,未来预测均值
|
||||
12_日期数值,梯度提升树,1115.505147894367,754.6104141829828,0.6459076101057781,3884,8023,6177.22
|
||||
12_日期数值,随机森林,1211.6404640631436,857.2259950393145,0.5822456578217434,3778,7634,5700.92
|
||||
12_日期数值,极端随机树,1016.4235733532818,804.2402630385485,0.7060165426206524,2681,6504,4381.72
|
||||
12_日期数值,HistGBDT,1081.1379394711937,734.543109383189,0.667389732676323,3657,8062,5775.15
|
||||
12_日期数值,SVR,1302.8065606379432,1122.631254189851,0.517015371360585,3203,5408,4553.72
|
||||
12_日期sin,梯度提升树,1037.9787565353552,864.907988042832,0.6934153789548839,1752,6174,3687.28
|
||||
12_日期sin,随机森林,1300.1505289996633,1061.3027606571065,0.5189826853858082,1966,5800,3536.75
|
||||
12_日期sin,极端随机树,1019.3127219314714,823.7222013605436,0.7043428918888557,1914,5888,3584.54
|
||||
12_日期sin,HistGBDT,1065.2572354517981,863.3337389503802,0.6770893113579488,2111,7633,4194.25
|
||||
12_日期sin,SVR,1514.2320642644604,1364.971543352133,0.3475333594320331,1813,4998,3673.18
|
||||
12_日期cos,梯度提升树,1102.1009812913542,934.5573526964807,0.654366194091462,1451,6394,3750.99
|
||||
12_日期cos,随机森林,1349.2073040509797,1168.881334404296,0.4819987561114465,1960,5927,3613.88
|
||||
12_日期cos,极端随机树,1167.5748397557088,989.3852519274374,0.6120793570853851,1898,5622,3508.44
|
||||
12_日期cos,HistGBDT,1207.8821487389928,1031.8720725902147,0.5848332530139425,1864,7623,4161.42
|
||||
12_日期cos,SVR,1266.5629805240928,1123.6204857013158,0.5435144697239268,1868,5162,3719.4
|
||||
12_年内第几天,梯度提升树,910.5720267585195,741.091899857133,0.7640597451116528,1626,6348,3648.54
|
||||
12_年内第几天,随机森林,1125.0275082985734,915.0238153129942,0.6398364829590523,1971,5152,3349.19
|
||||
12_年内第几天,极端随机树,1010.022890809697,801.2023117913834,0.7097074645417395,1906,5624,3509.47
|
||||
12_年内第几天,HistGBDT,1015.9546264325356,824.2028863511464,0.7062877500933793,1971,7453,4134.83
|
||||
12_年内第几天,SVR,1408.7450455752507,1271.6382669589445,0.4352734075175475,1913,4987,3632.62
|
||||
12_年内进度,梯度提升树,910.5720267585195,741.091899857133,0.7640597451116528,1626,6348,3648.54
|
||||
12_年内进度,随机森林,1125.0275082985734,915.0238153129942,0.6398364829590523,1971,5152,3349.41
|
||||
12_年内进度,极端随机树,1010.0228908096968,801.2023117913834,0.7097074645417396,1906,5624,3509.47
|
||||
12_年内进度,HistGBDT,1015.9546264325356,824.2028863511464,0.7062877500933793,1971,7453,4134.83
|
||||
12_年内进度,SVR,1408.7450455752507,1271.6382669589445,0.4352734075175476,1913,4987,3632.62
|
||||
12_周序号,梯度提升树,1069.803614918048,903.2622617081902,0.6743271479086517,2006,6530,3973.86
|
||||
12_周序号,随机森林,1243.5446976109674,1041.5134963439052,0.5599558665365664,1983,6140,3651.16
|
||||
12_周序号,极端随机树,1035.7721993969274,826.6126054421767,0.694717481574221,1964,5895,3568.12
|
||||
12_周序号,HistGBDT,1112.59713175554,920.3983467960975,0.6477513742747558,1935,7559,4098.05
|
||||
12_周序号,SVR,1292.2405499799693,1150.5398648996525,0.5248177985800409,1860,5149,3786.9
|
||||
12_周序号sin,梯度提升树,1063.281232768076,882.1390025824226,0.6782861689221613,1934,6414,3830.73
|
||||
12_周序号sin,随机森林,1292.9475995090163,1061.5729066667654,0.524297664357741,1983,5483,3536.65
|
||||
12_周序号sin,极端随机树,1014.1497745380785,816.5771680272105,0.7073303876817728,1887,5788,3534.99
|
||||
12_周序号sin,HistGBDT,1102.938167765176,893.2039949691602,0.6538408885976152,2032,7599,4183.36
|
||||
12_周序号sin,SVR,1503.9741029680147,1354.4278894326096,0.35634351127843267,1807,5003,3670.59
|
||||
12_月内日,梯度提升树,1075.2787348073598,910.5418237040739,0.6709851125668345,1823,6745,4072.24
|
||||
12_月内日,随机森林,1243.6349732406059,1038.4677767446087,0.5598919738542543,1942,6236,3665.28
|
||||
12_月内日,极端随机树,1022.4506637906521,825.6662979591832,0.7025197362733295,1971,5942,3609.59
|
||||
12_月内日,HistGBDT,1098.717892872152,907.8006929324015,0.6564849019907664,1965,7569,4085.0
|
||||
12_月内日,SVR,1295.0430615629316,1151.4692010654137,0.522754486650163,1842,5183,3805.16
|
||||
12_月内日sin,梯度提升树,1067.22297417614,906.8146759377944,0.6758964657440301,1878,6598,3910.3
|
||||
12_月内日sin,随机森林,1242.2027167294766,1044.5619603560458,0.5609051081316705,1972,6006,3668.2
|
||||
12_月内日sin,极端随机树,995.1317369549822,783.5088700680266,0.7182041522270597,1885,5868,3581.37
|
||||
12_月内日sin,HistGBDT,1105.813282654649,918.9424734351023,0.6520338164721056,1821,7375,4119.0
|
||||
12_月内日sin,SVR,1294.6875882479544,1143.1041218806386,0.5230164466831182,1735,5223,3787.08
|
||||
12_季度内月份,梯度提升树,1030.8840120603018,873.0194697266488,0.6975921616220541,1949,6684,3925.74
|
||||
12_季度内月份,随机森林,1253.0127757589096,1049.3735973230855,0.5532295571774203,1912,6205,3643.17
|
||||
12_季度内月份,极端随机树,1022.5707998779073,823.3960331065751,0.7024498253900622,1963,6010,3627.72
|
||||
12_季度内月份,HistGBDT,1104.0353223349737,907.1740751082931,0.6531518582216439,2021,7502,4113.82
|
||||
12_季度内月份,SVR,1279.4999059696324,1136.644561330494,0.5341415772015901,1813,5170,3795.71
|
||||
12_是否月初,梯度提升树,1074.707109174901,911.4478533502376,0.6713348327770166,2009,6741,4032.85
|
||||
12_是否月初,随机森林,1251.1986686370237,1047.3387084749343,0.5545222857849463,1996,6222,3699.8
|
||||
12_是否月初,极端随机树,1004.7715101011122,798.0876673469379,0.7127182352012016,1952,5982,3692.01
|
||||
12_是否月初,HistGBDT,1090.5958037531236,900.8674504846922,0.6615448864141861,2005,7533,4136.36
|
||||
12_是否月初,SVR,1266.2996781493812,1123.4419542652251,0.5437042450965154,1820,5174,3796.87
|
||||
12_是否月末,梯度提升树,1051.1491771051826,889.5436406255417,0.6855858052834116,1934,6997,4023.66
|
||||
12_是否月末,随机森林,1252.4058220639308,1048.5324678294116,0.553662279492491,2037,6112,3700.39
|
||||
12_是否月末,极端随机树,1023.9819170179634,821.4061183673467,0.7016280380651778,1955,5912,3665.4
|
||||
12_是否月末,HistGBDT,1099.3134078227854,912.4381059898651,0.6561124245479075,1990,7477,4095.89
|
||||
12_是否月末,SVR,1266.3037333555528,1118.853560743366,0.5437013226029602,1840,5168,3791.36
|
||||
12_日期分箱4,梯度提升树,1159.7677465407507,959.746334523742,0.6172497448666919,1082,6711,3760.55
|
||||
12_日期分箱4,随机森林,1354.8648153138981,1127.6347175619164,0.4776454707850357,1242,6317,3767.98
|
||||
12_日期分箱4,极端随机树,1045.4835916765785,878.4472097505668,0.6889659912708692,1464,5909,3542.3
|
||||
12_日期分箱4,HistGBDT,1081.9800025011405,878.4483264538926,0.6668714123558845,1264,7770,4128.71
|
||||
12_日期分箱4,SVR,1416.8450442399799,1279.3344630153172,0.4287606105220405,1600,5424,3788.31
|
||||
12_日期分箱8,梯度提升树,1132.6317366268574,943.8527579349204,0.6349512308901111,1356,6726,4009.71
|
||||
12_日期分箱8,随机森林,1303.8402293998106,1094.8299032973075,0.516248650968877,1246,6253,3806.88
|
||||
12_日期分箱8,极端随机树,1386.534777125338,1147.028979138322,0.4529399894883904,1012,6887,3894.88
|
||||
12_日期分箱8,HistGBDT,1039.4639834179268,842.3983219405343,0.6925373773716995,1388,7779,4362.77
|
||||
12_日期分箱8,SVR,1366.5766542260164,1225.520011226714,0.4685756746775356,1775,5362,3841.55
|
||||
|
Reference in New Issue
Block a user