test: 对比时间顺序划分特征方案

This commit is contained in:
luochen570
2026-06-08 23:40:44 +08:00
parent 0026c4bf84
commit 2d3d36b47c
3 changed files with 157 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
特征方案,模型,特征数,训练集样本数,测试集样本数,训练日期起,训练日期止,测试日期起,测试日期止,RMSE,MAE,R2,测试预测最小值,测试预测最大值,未来预测最小值,未来预测最大值,未来预测均值
13特征_日期sin_cos,梯度提升树,13,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1035.393806499406,869.0366952335274,0.6949404951600915,1193.005865875163,7448.828701180003,1862,6350,3848.46
12特征_仅日期sin,梯度提升树,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1037.9787565353552,864.907988042832,0.6934153789548839,1570.2284280500735,7557.904184096963,1752,6174,3687.28
11特征_无日期,梯度提升树,11,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1065.8819685946905,903.8377254645945,0.6767104504461063,1526.0106661213501,7445.060381049142,1927,6896,4029.71
12特征_日期数值,线性回归,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1100.6960028141114,802.9604968933488,0.6552468729685021,1667.5505098104527,7202.426019549715,1341,5571,3322.7
11特征_无日期,线性回归,11,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1102.6619968627012,803.6253768758826,0.6540142203549053,1677.5487160817047,7191.784877243726,1775,6001,3756.0
12特征_仅日期sin,线性回归,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1109.0855745651786,812.0301896212464,0.6499713857316858,1680.4361958712066,7184.255023908034,1772,6010,3754.92
13特征_日期sin_cos,线性回归,13,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1111.9746531184803,816.5536163460256,0.6481454179049195,1691.5799618779006,7248.332307970662,1775,5909,3690.63
12特征_日期数值,梯度提升树,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1115.505147894367,754.6104141829828,0.6459076101057781,2210.8052037892908,7886.894463218566,3884,8023,6177.22
12特征_日期数值,随机森林,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1211.6404640631436,857.2259950393145,0.5822456578217434,3362.6023664502195,7437.1805507936515,3778,7634,5700.92
11特征_无日期,随机森林,11,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1243.2258138091481,1038.575310261998,0.5601815197920028,2508.394888672439,7396.9488500000025,1991,6107,3698.12
11特征_无日期,SVR,11,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1256.1142258603181,1110.5200812033272,0.5510151326775178,2435.653600556283,6728.154381038747,1857,5138,3785.22
12特征_仅日期sin,随机森林,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1300.1505289996633,1061.3027606571065,0.5189826853858082,2349.546295021645,7412.202957142856,1966,5800,3536.75
12特征_日期数值,SVR,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1302.8065606379432,1122.631254189851,0.517015371360585,3038.4325167245174,6793.0357932052375,3203,5408,4553.72
13特征_日期sin_cos,随机森林,13,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1362.4036579408184,1162.7424853677699,0.47181624787772836,2337.0508269841275,7378.615926190471,1981,5446,3498.99
13特征_日期sin_cos,SVR,13,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1500.6745922933299,1355.960815132986,0.35916459954458013,2458.0732583146823,6405.637428945096,1864,4975,3596.58
12特征_仅日期sin,SVR,12,584,147,2011-01-01,2012-08-06,2012-08-07,2012-12-31,1514.2320642644604,1364.971543352133,0.3475333594320331,2414.919176938589,6342.6982615190545,1813,4998,3673.18
1 特征方案 模型 特征数 训练集样本数 测试集样本数 训练日期起 训练日期止 测试日期起 测试日期止 RMSE MAE R2 测试预测最小值 测试预测最大值 未来预测最小值 未来预测最大值 未来预测均值
2 13特征_日期sin_cos 梯度提升树 13 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1035.393806499406 869.0366952335274 0.6949404951600915 1193.005865875163 7448.828701180003 1862 6350 3848.46
3 12特征_仅日期sin 梯度提升树 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1037.9787565353552 864.907988042832 0.6934153789548839 1570.2284280500735 7557.904184096963 1752 6174 3687.28
4 11特征_无日期 梯度提升树 11 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1065.8819685946905 903.8377254645945 0.6767104504461063 1526.0106661213501 7445.060381049142 1927 6896 4029.71
5 12特征_日期数值 线性回归 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1100.6960028141114 802.9604968933488 0.6552468729685021 1667.5505098104527 7202.426019549715 1341 5571 3322.7
6 11特征_无日期 线性回归 11 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1102.6619968627012 803.6253768758826 0.6540142203549053 1677.5487160817047 7191.784877243726 1775 6001 3756.0
7 12特征_仅日期sin 线性回归 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1109.0855745651786 812.0301896212464 0.6499713857316858 1680.4361958712066 7184.255023908034 1772 6010 3754.92
8 13特征_日期sin_cos 线性回归 13 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1111.9746531184803 816.5536163460256 0.6481454179049195 1691.5799618779006 7248.332307970662 1775 5909 3690.63
9 12特征_日期数值 梯度提升树 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1115.505147894367 754.6104141829828 0.6459076101057781 2210.8052037892908 7886.894463218566 3884 8023 6177.22
10 12特征_日期数值 随机森林 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1211.6404640631436 857.2259950393145 0.5822456578217434 3362.6023664502195 7437.1805507936515 3778 7634 5700.92
11 11特征_无日期 随机森林 11 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1243.2258138091481 1038.575310261998 0.5601815197920028 2508.394888672439 7396.9488500000025 1991 6107 3698.12
12 11特征_无日期 SVR 11 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1256.1142258603181 1110.5200812033272 0.5510151326775178 2435.653600556283 6728.154381038747 1857 5138 3785.22
13 12特征_仅日期sin 随机森林 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1300.1505289996633 1061.3027606571065 0.5189826853858082 2349.546295021645 7412.202957142856 1966 5800 3536.75
14 12特征_日期数值 SVR 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1302.8065606379432 1122.631254189851 0.517015371360585 3038.4325167245174 6793.0357932052375 3203 5408 4553.72
15 13特征_日期sin_cos 随机森林 13 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1362.4036579408184 1162.7424853677699 0.47181624787772836 2337.0508269841275 7378.615926190471 1981 5446 3498.99
16 13特征_日期sin_cos SVR 13 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1500.6745922933299 1355.960815132986 0.35916459954458013 2458.0732583146823 6405.637428945096 1864 4975 3596.58
17 12特征_仅日期sin SVR 12 584 147 2011-01-01 2012-08-06 2012-08-07 2012-12-31 1514.2320642644604 1364.971543352133 0.3475333594320331 2414.919176938589 6342.6982615190545 1813 4998 3673.18

140
time_split_experiment.py Normal file
View File

@@ -0,0 +1,140 @@
from pathlib import Path
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor
from sklearn.linear_model import LinearRegression
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 = ['', '季节', '', '节假日', '星期', '工作日', '天气', '气温', '体感温度', '湿度', '风速']
CATEGORICAL_BASE = ['', '季节', '', '节假日', '星期', '工作日', '天气']
def rmse(y_true, y_pred):
return float(np.sqrt(mean_squared_error(y_true, y_pred)))
def make_pipeline(name, estimator, features, categorical):
numeric = [col for col in features if col not in categorical]
need_scale = name in {'线性回归', 'SVR'}
preprocessor = ColumnTransformer(
transformers=[
('cat', OneHotEncoder(handle_unknown='ignore'), categorical),
('num', StandardScaler() if need_scale else 'passthrough', numeric),
],
verbose_feature_names_out=False,
)
return Pipeline([('preprocess', preprocessor), ('model', estimator)])
def add_date_features(frame, min_date):
frame = frame.copy()
frame['日期数值'] = (frame['日期'] - min_date).dt.days
day_of_year = frame['日期'].dt.dayofyear
frame['日期_sin'] = np.sin(2 * np.pi * day_of_year / 365.25)
frame['日期_cos'] = np.cos(2 * np.pi * day_of_year / 365.25)
return frame
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_date_features(daily, min_date)
future = add_date_features(future, min_date)
split_idx = int(len(daily) * 0.8)
train = daily.iloc[:split_idx].copy()
test = daily.iloc[split_idx:].copy()
feature_sets = {
'11特征_无日期': {
'features': BASE_FEATURES,
'categorical': CATEGORICAL_BASE,
},
'12特征_日期数值': {
'features': ['日期数值'] + BASE_FEATURES,
'categorical': CATEGORICAL_BASE,
},
'13特征_日期sin_cos': {
'features': ['日期_sin', '日期_cos'] + BASE_FEATURES,
'categorical': CATEGORICAL_BASE,
},
'12特征_仅日期sin': {
'features': ['日期_sin'] + BASE_FEATURES,
'categorical': CATEGORICAL_BASE,
},
}
model_factories = {
'线性回归': lambda: LinearRegression(),
'随机森林': lambda: RandomForestRegressor(n_estimators=500, random_state=42, min_samples_leaf=2, n_jobs=-1),
'梯度提升树': lambda: GradientBoostingRegressor(random_state=42, n_estimators=300, learning_rate=0.05, max_depth=3),
'SVR': lambda: SVR(C=200, gamma='scale', epsilon=50),
}
rows = []
future_rows = []
for fs_name, spec in feature_sets.items():
features = spec['features']
categorical = spec['categorical']
for model_name, factory in model_factories.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({
'特征方案': fs_name,
'模型': model_name,
'特征数': len(features),
'训练集样本数': len(train),
'测试集样本数': len(test),
'训练日期起': train['日期'].min().date().isoformat(),
'训练日期止': train['日期'].max().date().isoformat(),
'测试日期起': test['日期'].min().date().isoformat(),
'测试日期止': test['日期'].max().date().isoformat(),
'RMSE': rmse(test[TARGET], pred),
'MAE': float(mean_absolute_error(test[TARGET], pred)),
'R2': float(r2_score(test[TARGET], pred)),
'测试预测最小值': float(pred.min()),
'测试预测最大值': float(pred.max()),
'未来预测最小值': int(future_pred.min()),
'未来预测最大值': int(future_pred.max()),
'未来预测均值': float(future_pred.mean()),
})
if model_name == '梯度提升树':
temp = future[['日期'] + BASE_FEATURES].copy()
temp['特征方案'] = fs_name
temp['模型'] = model_name
temp['预测总骑行量'] = future_pred
future_rows.append(temp)
result = pd.DataFrame(rows).sort_values(['RMSE', 'R2'], ascending=[True, False])
result.to_csv(OUT_DIR / 'time_split_feature_model_comparison.csv', index=False, encoding='utf-8-sig')
pd.concat(future_rows, ignore_index=True).to_excel(OUT_DIR / 'gbdt_future_predictions_by_feature_set.xlsx', index=False)
print('时间顺序划分:')
print(f"训练集 {len(train)} 条:{train['日期'].min().date()}{train['日期'].max().date()}")
print(f"测试集 {len(test)} 条:{test['日期'].min().date()}{test['日期'].max().date()}")
print('\n按 RMSE 排序:')
print(result[['特征方案', '模型', 'RMSE', 'MAE', 'R2', '未来预测最小值', '未来预测最大值', '未来预测均值']].to_string(index=False, float_format=lambda x: f'{x:.3f}'))
print(f"\n结果已保存:{OUT_DIR}")
if __name__ == '__main__':
main()