一、写在前面
这一期,我们介绍支持向量机(SVM)回归。
同样,这里使用这个数据:
《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Renal Syndrome in Jiangsu Province, China》文章的公开数据做演示。数据为江苏省2004年1月至2012年12月肾综合症出血热月发病率。运用2004年1月至2011年12月的数据预测2012年12个月的发病率数据。
二、随机森林回归
(1)代码解读
scikit-learn 提供了3种支持向量机 (SVM) 的回归器:sklearn.svm.SVR、sklearn.svm.NuSVR和sklearn.svm.LinearSVR:
(a)SVR (Support Vector Regression)
说明:SVR是基于libsvm的支持向量回归的实现。
核函数:可以使用多种核函数,例如线性、多项式、RBF(径向基函数)和sigmoid等。
主要参数:
sklearn.svm.SVR(*, kernel='rbf', degree=3, gamma='scale', coef0=0.0, tol=0.001, C=1.0, epsilon=0.1, shrinking=True, cache_size=200, verbose=False, max_iter=-1)
C: 误差项的惩罚参数。C越大,模型对误差的容忍度越低。
epsilon: ε-不敏感损失函数中的ε。它指定了没有惩罚的训练样本的边界。
kernel: 使用的核函数。例如 'linear', 'poly', 'rbf', 'sigmoid', 'precomputed' 或者是一个自定义的函数。
degree: 多项式核函数的度(只在kernel='poly'时使用)。
gamma: 'rbf', 'poly' 和 'sigmoid' 的核函数系数。
coef0: 多项式和sigmoid核函数的独立项。
shrinking: 是否使用收缩启发式。
其他参数还有tol, cache_size, verbose, max_iter等。
(b)NuSVR
说明:NuSVR与SVR相似,但它使用了ν-SVM形式的参数化。它允许用户对支持向量的数量进行参数化。
核函数:与SVR相同,可以使用多种核函数。
主要参数:
sklearn.svm.NuSVR(*, nu=0.5, C=1.0, kernel='rbf', degree=3, gamma='scale', coef0=0.0, shrinking=True, tol=0.001, cache_size=200, verbose=False, max_iter=-1)
nu: 控制支持向量的数量。实际上是支持向量的上限和下限之间的比例。
C, kernel, degree, gamma, coef0, shrinking, tol, cache_size, verbose, max_iter等参数与SVR中的相同。
(c)LinearSVR
说明:LinearSVR是基于liblinear的线性支持向量回归的实现。与SVR不同,它只处理线性核函数,并且通常比SVR(kernel='linear')更快。
核函数:仅线性。
主要参数:
sklearn.svm.LinearSVR(*, epsilon=0.0, tol=0.0001, C=1.0, loss='epsilon_insensitive', fit_intercept=True, intercept_scaling=1.0, dual='warn', verbose=0, random_state=None, max_iter=1000)
epsilon: 与SVR中的相同。
C: 误差项的惩罚参数。
loss: 指定损失函数。可选值有 'epsilon_insensitive' 和 'squared_epsilon_insensitive'。
dual: 是否解决对偶问题。对于大规模数据,推荐设置为False。
其他参数还有tol, fit_intercept, intercept_scaling, verbose, random_state, max_iter等。
(d)异同总结:
-SVR和NuSVR可以处理非线性问题,因为它们支持多种核函数。而LinearSVR仅处理线性问题。
-NuSVR通过ν参数提供了对支持向量数量的控制。
-对于具有线性核的问题,LinearSVR通常比SVR(kernel='linear')更快。
-三者在误差控制方面都使用了epsilon参数。
-C参数在所有三种模型中都存在,表示误差项的惩罚。
-LinearSVR有一个独特的loss参数,而NuSVR有一个独特的nu参数。
下面我们以最经典的SVR (Support Vector Regression)演示。
(2)单步滚动预测
# 读取数据
import pandas as pd
import numpy as np
from sklearn.metrics import mean_absolute_error, mean_squared_error
from sklearn.svm import SVR
from sklearn.model_selection import GridSearchCV
data = pd.read_csv('data.csv')
# 将时间列转换为日期格式
data['time'] = pd.to_datetime(data['time'], format='%b-%y')
# 拆分输入和输出
lag_period = 6
# 创建滞后期特征
for i in range(lag_period, 0, -1):
data[f'lag_{i}'] = data['incidence'].shift(lag_period - i + 1)
# 删除包含NaN的行
data = data.dropna().reset_index(drop=True)
# 划分训练集和验证集
train_data = data[(data['time'] >= '2004-01-01') & (data['time'] <= '2011-12-31')]
validation_data = data[(data['time'] >= '2012-01-01') & (data['time'] <= '2012-12-31')]
# 定义特征和目标变量
X_train = train_data[['lag_1', 'lag_2', 'lag_3', 'lag_4', 'lag_5', 'lag_6']]
y_train = train_data['incidence']
X_validation = validation_data[['lag_1', 'lag_2', 'lag_3', 'lag_4', 'lag_5', 'lag_6']]
y_validation = validation_data['incidence']
# 初始化SVR模型
svr_model = SVR()
# 定义参数网格
param_grid = {
'C': [0.1, 1, 10],
'epsilon': [0.01, 0.1, 1],
'kernel': ['linear', 'rbf']
}
# 初始化网格搜索
grid_search = GridSearchCV(svr_model, param_grid, cv=5, scoring='neg_mean_squared_error')
# 进行网格搜索
grid_search.fit(X_train, y_train)
# 获取最佳参数
best_params = grid_search.best_params_
# 使用最佳参数初始化SVR模型
best_svr_model = SVR(**best_params)
# 在训练集上训练模型
best_svr_model.fit(X_train, y_train)
# 对于验证集,我们需要迭代地预测每一个数据点
y_validation_pred = []
for i in range(len(X_validation)):
if i == 0:
pred = best_svr_model.predict([X_validation.iloc[0]])
else:
new_features = list(X_validation.iloc[i, 1:]) + [pred[0]]
pred = best_svr_model.predict([new_features])
y_validation_pred.append(pred[0])
y_validation_pred = np.array(y_validation_pred)
# 计算验证集上的MAE, MAPE, MSE和RMSE
mae_validation = mean_absolute_error(y_validation, y_validation_pred)
mape_validation = np.mean(np.abs((y_validation - y_validation_pred) / y_validation))
mse_validation = mean_squared_error(y_validation, y_validation_pred)
rmse_validation = np.sqrt(mse_validation)
# 计算训练集上的MAE, MAPE, MSE和RMSE
y_train_pred = best_svr_model.predict(X_train)
mae_train = mean_absolute_error(y_train, y_train_pred)
mape_train = np.mean(np.abs((y_train - y_train_pred) / y_train))
mse_train = mean_squared_error(y_train, y_train_pred)
rmse_train = np.sqrt(mse_train)
print("Train Metrics:", mae_train, mape_train, mse_train, rmse_train)
print("Validation Metrics:", mae_validation, mape_validation, mse_validation, rmse_validation)
看结果:
(3)多步滚动预测-vol. 1
SVR(支持向量机回归)与RandomForestRegressor有一些关键的不同,主要的不同之处在于SVR只对一个目标变量进行预测,而RandomForestRegressor可以同时对多个目标变量进行预测。
(4)多步滚动预测-vol. 2
同样,做不了。
(5)多步滚动预测-vol. 3
import pandas as pd
import numpy as np
from sklearn.svm import SVR
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_absolute_error, mean_squared_error
# 数据读取和预处理
data = pd.read_csv('data.csv')
data_y = pd.read_csv('data.csv')
data['time'] = pd.to_datetime(data['time'], format='%b-%y')
data_y['time'] = pd.to_datetime(data_y['time'], format='%b-%y')
n = 6
for i in range(n, 0, -1):
data[f'lag_{i}'] = data['incidence'].shift(n - i + 1)
data = data.dropna().reset_index(drop=True)
train_data = data[(data['time'] >= '2004-01-01') & (data['time'] <= '2011-12-31')]
X_train = train_data[[f'lag_{i}' for i in range(1, n+1)]]
m = 3
X_train_list = []
y_train_list = []
for i in range(m):
X_temp = X_train
y_temp = data_y['incidence'].iloc[n + i:len(data_y) - m + 1 + i]
X_train_list.append(X_temp)
y_train_list.append(y_temp)
for i in range(m):
X_train_list[i] = X_train_list[i].iloc[:-(m-1)]
y_train_list[i] = y_train_list[i].iloc[:len(X_train_list[i])]
# 模型训练
param_grid = {
'C': [0.1, 1, 10],
'epsilon': [0.01, 0.1, 1],
'kernel': ['linear', 'rbf']
}
best_svr_models = []
for i in range(m):
grid_search = GridSearchCV(SVR(), param_grid, cv=5, scoring='neg_mean_squared_error')
grid_search.fit(X_train_list[i], y_train_list[i])
best_svr_model = SVR(**grid_search.best_params_)
best_svr_model.fit(X_train_list[i], y_train_list[i])
best_svr_models.append(best_svr_model)
validation_start_time = train_data['time'].iloc[-1] + pd.DateOffset(months=1)
validation_data = data[data['time'] >= validation_start_time]
X_validation = validation_data[[f'lag_{i}' for i in range(1, n+1)]]
y_validation_pred_list = [model.predict(X_validation) for model in best_svr_models]
y_train_pred_list = [model.predict(X_train_list[i]) for i, model in enumerate(best_svr_models)]
def concatenate_predictions(pred_list):
concatenated = []
for j in range(len(pred_list[0])):
for i in range(m):
concatenated.append(pred_list[i][j])
return concatenated
y_validation_pred = np.array(concatenate_predictions(y_validation_pred_list))[:len(validation_data['incidence'])]
y_train_pred = np.array(concatenate_predictions(y_train_pred_list))[:len(train_data['incidence']) - m + 1]
mae_validation = mean_absolute_error(validation_data['incidence'], y_validation_pred)
mape_validation = np.mean(np.abs((validation_data['incidence'] - y_validation_pred) / validation_data['incidence']))
mse_validation = mean_squared_error(validation_data['incidence'], y_validation_pred)
rmse_validation = np.sqrt(mse_validation)
print("验证集:", mae_validation, mape_validation, mse_validation, rmse_validation)
mae_train = mean_absolute_error(train_data['incidence'][:-(m-1)], y_train_pred)
mape_train = np.mean(np.abs((train_data['incidence'][:-(m-1)] - y_train_pred) / train_data['incidence'][:-(m-1)]))
mse_train = mean_squared_error(train_data['incidence'][:-(m-1)], y_train_pred)
rmse_train = np.sqrt(mse_train)
print("训练集:", mae_train, mape_train, mse_train, rmse_train)
结果:
三、数据
链接:https://pan.baidu.com/s/1EFaWfHoG14h15KCEhn1STg?pwd=q41n
提取码:q41n