SVR:尽管 r 平方高且 MSE 低,但预测值与实际值相差甚远

Posted

技术标签:

【中文标题】SVR:尽管 r 平方高且 MSE 低,但预测值与实际值相差甚远【英文标题】:SVR: Predicted values are way off from the actual ones despite high r-squared and and low MSE 【发布时间】:2018-11-06 04:58:52 【问题描述】:

我使用 scikit learn 训练了一个 SVR 模型,该模型通过使用比特币在之前日期的收盘价来预测比特币的未来价格。我已使用以下函数将日期从第一个可用日期转换为增量:

btc['Date'] = pd.to_datetime(btc['Date'])     
btc['date_delta'] = (btc['Date'] - btc['Date'].min())  / np.timedelta64(1,'D')

我的数据框的头部看起来像这样:

<table>
  <tr>
    <th>date_delta</th>
    <th>Close</th>
  </tr>
  <tr>
    <td>1654.0</td>
    <td>7144.38</td>
  </tr>
  <tr>
    <td>1653.0</td>
    <td>7022.76</td>
  </tr>
</table>

然后我将测试和训练数据集拆分如下:

msk = np.random.rand(len(btc_select)) < 0.8
btc_train = btc_select[msk]
btc_test = btc_select[~msk]

并在训练模型之前对数据集进行最小最大缩放,如下所示:

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(btc_train)
btc_train = scaler.transform(btc_train)
btc_test = scaler.transform(btc_test)

我的模型使用以下函数进行训练,我发现多项式内核给出了最好的结果:

def predict_prices(dates_train, prices_train, dates_test, price_test):
    dates_train=np.reshape(dates_train, (len(dates_train),1))
    dates_test=np.reshape(dates_test, (len(dates_test),1))
    svr_lin = SVR(kernel='linear', C=1e3)
    svr_poly = SVR(kernel = 'poly', C=1e3, degree=8)
    svr_rbf = SVR(kernel='rbf', C=1e3, gamma=0.8)
    svr_lin.fit(dates_train,prices_train)
    svr_poly.fit(dates_train,prices_train)
    svr_rbf.fit(dates_train,prices_train)
    plt.figure(figsize=(14,10))
    plt.scatter(dates_train, prices_train, color='black', label='Data')
    plt.plot(dates_train, svr_rbf.predict(dates_train), color='red', label='RBF model')
    plt.plot(dates_train, svr_lin.predict(dates_train), color='green', label='Linear model')
    plt.plot(dates_train, svr_poly.predict(dates_train), color='blue', label='Polynomial model')
    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title('Support Vector Regression')
    plt.legend()
    plt.show()
    print('Lin Score:', svr_lin.score(dates_test, price_test))
    print('Poly Score:', svr_poly.score(dates_test, price_test))
    print('Rbf Score:', svr_rbf.score(dates_test, price_test))
    scores = cross_val_score(svr_poly, dates_train, prices_train, cv=6, scoring='neg_mean_squared_error')
    accuracy = metrics.r2_score(price_test, svr_poly.predict(dates_test))
    print('R-Squared Value for the Polynomial Kernel:', accuracy)
    print('Cross Validation Mean Squared Error for the Polynomial Kernel:', scores)
    return svr_poly

我得到以下准确度和交叉验证分数:

Lin Score: 0.3290332147578777
Poly Score: 0.8724266575682722
Rbf Score: 0.836449334307112
R-Squared Value for the Polynomial Kernel: 0.8724266575682722
Cross Validation Mean Squared Error for the Polynomial Kernel: [-0.13853584 -0.00069995 -0.00043713 -0.00041959 -0.00341142 -0.00352207]

但是,当我在转换 date_delta 并对预测输出进行逆变换后尝试预测数据点的 btc 价格时,结果却大相径庭。需要帮助了解问题所在。

transform_inp = scaler.transform([[1654.0,0.0]])
transform_inp[0,0]
1.000604960677556

predicted_val = model.predict(np.array(transform_inp[0,0]))
predicted_val
array([0.73674025])

现在做逆变换得到以下结果:

scaler.inverse_transform([[predicted_val[0],0]])
array([[1217.83164131,   68.43      ]])

输出为 1217 美元,与实际价格 7144 美元相差甚远。你能告诉我这里有什么问题吗?

【问题讨论】:

【参考方案1】:

很多话要说:

    我不太明白您的目标是什么:基本上,您尝试将原始日期的天数与实际上不相关的 btc 价格匹配(增量的数值是完全独立的)。您最好尝试将某一天的btc价格与前几天的btc价格匹配

    您通过随机选择 80% 进行训练来拆分训练/测试数据。为什么不将前 80% 的点用于学习,而将后 20% 的点用于预测?在您当前的配置中,数据采样方式存在偏差

    现在想象一下您的模型过拟合(它学习了一条非常复杂的 date_delta/price 曲线),非常适合您的训练点。对测试数据的预测很可能与事实相去甚远。尝试改变支持向量回归的参数。

您的结果仍然与应有的结果相去甚远。我可能会问您从哪里获取值 1654.0 ?您是否使用线性模型查看了结果?

【讨论】:

感谢您的回复。我相信 SVR 不是这种分析的最佳模型,因为即使我将日期分成年、日、月,结果仍然不正确。 1654 是我为检查结果而输入的随机日期偏移值。关于随机拆分,我同意我们可以按顺序拆分。我正在考虑尝试 LSTM 进行相同的分析。 我的意思是,如果你的训练增量在 0 到 1000 之间,并且你最终给你的模型 1600,你不能指望它给出一个好的预测,因为你不处理问题的正确方法。无论如何,您都不应该尝试拟合日期,除非您只想查看拟合曲线的形状。

以上是关于SVR:尽管 r 平方高且 MSE 低,但预测值与实际值相差甚远的主要内容,如果未能解决你的问题,请参考以下文章

数学基础--MATLAB 数据拟合 SSE,MSE,RMSE,R-square

数学基础--MATLAB 数据拟合 SSE,MSE,RMSE,R-square

均方误差(MSE)和均方根误差(RMSE)和平均绝对误差(MAE)

mse是啥需要看吗spss

回归评价指标MSERMSEMAER-Squared

如何评价模型的好坏