【发布时间】:2021-11-27 14:38:08
【问题描述】:
问题:
- 如何在 python 中使用面板数据调整随机森林的超参数?
- 是否有已经实现的包和功能?
我在以下方面寻找答案:
- https://towardsdatascience.com/time-series-nested-cross-validation-76adba623eb9
- https://stats.stackexchange.com/questions/326228/cross-validation-with-time-series
- https://stats.stackexchange.com/questions/369397/correct-cross-validation-procedure-for-single-model-applied-to-panel-data
这一切都引导我进入当前的代码状态。
问题:
我试图预测一周内售出的每种产品的数量。我有大约 5000 种产品(按类别分组)和 1.5 年的历史。由于产品太多,为每个产品创建单独的模型似乎没有意义,因此一个大模型还要考虑产品的一个类别。
我理解时间敏感的交叉验证和嵌套交叉验证的概念,但缺乏有效实施它们的能力。
示例数据:
import pandas as pd
import numpy as np
from random import seed
from random import randint
seed(1)
Panel_data = pd.DataFrame({
'Product': ["A", "B"] * 10,
'Time': [ele for ele in range(1, 11) for i in range(2)],
'Z': [randint(0, 10) for ele in range(1, 21)],
'X': [randint(0, 10) for ele in range(1, 21)]})
Panel_data['Y'] = Panel_data['X'] + [randint(0, 10) for ele in range(1, 21)]
我目前对嵌套滑动窗口 CV 的处理方法(如 link 中所述)
我创建了一个循环,该循环正确地允许模型学习数据,然后使用来自sklearn.model_selection 包的RandomizedSearchCV 我找到给定子集中的最佳超参数。在遍历数据中的所有时间 id 后,我选择中值超参数。
这种方法非常耗时!我想知道这是否是正确的方法,是否有更好的方法?
from sklearn.metrics import mean_squared_error
from sklearn import linear_model
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import RandomizedSearchCV
import statistics
from statistics import mode
rf_beseline = RandomForestRegressor(n_estimators = 2, random_state = 42)
OLS_baseline = linear_model.LinearRegression()
random_grid = {'n_estimators': [100, 500],
'max_features': ['auto', 'sqrt'],
'max_depth': [3, None],
'min_samples_split': [3, 10],
'min_samples_leaf': [3, 10]}
rf_MSE = list()
n_estimators = list()
min_samples_split = list()
min_samples_leaf = list()
max_features = list()
max_depth = list()
for i in range(1, 10):
print(i)
X_train = Panel_data.loc[Panel_data['Time'] == i, ['X', 'Z']]
Y_train = Panel_data.loc[Panel_data['Time'] == i, 'Y']
X_test = Panel_data.loc[Panel_data['Time'] == i + 1, ['X', 'Z']]
Y_test = Panel_data.loc[Panel_data['Time'] == i + 1, 'Y']
#random forest
rf_beseline.fit(X_train, Y_train)
y_pred = rf_beseline.predict(X_test)
mse = mean_squared_error(Y_test, y_pred)
rf_MSE = rf_MSE + [mse]
# hiperparamiters
rf_rs = RandomizedSearchCV(estimator = rf_beseline, param_distributions = random_grid, n_iter = 5, cv = 2, verbose = 2, random_state = 42, n_jobs = -1)
rf_rs.fit(X_train, Y_train)
n_estimators = n_estimators + [rf_rs.best_params_.get('n_estimators')]
min_samples_split = min_samples_split + [rf_rs.best_params_.get('min_samples_split')]
min_samples_leaf = min_samples_leaf + [rf_rs.best_params_.get('min_samples_leaf')]
max_features = max_features + [rf_rs.best_params_.get('max_features')]
max_depth = max_depth + [rf_rs.best_params_.get('max_depth')]
np.mean(rf_MSE)
#selected hiperparamiters
sel_n_estimators = np.median(n_estimators)
sel_min_samples_split = np.median(min_samples_split)
sel_min_samples_leaf = np.median(min_samples_leaf)
sel_max_features = mode(max_features)
sel_max_depth = None if np.median([100 if v is None else v for v in max_depth]) == 100 else np.median([100 if v is None else v for v in max_depth])
rf_best = RandomForestRegressor(n_estimators = sel_n_estimators,
random_state = 42,
min_samples_split = sel_min_samples_split,
min_samples_leaf = sel_min_samples_leaf,
max_features = sel_max_features,
max_depth = sel_max_depth,
bootstrap = True)
我的期望和希望:
我希望已经很容易实现使用RandomizedSearchCV的函数,它比我实现的for循环更快
【问题讨论】:
标签: python time-series random-forest cross-validation panel-data