SVR模型R²高、MSE低但比特币价格预测值与实际值偏差过大求助
我帮你梳理下几个关键问题,这些应该是导致预测偏差极大的核心原因:
1. 归一化时混淆了特征与标签的处理逻辑
你当前把特征(date_delta)和标签(Close)放在一起用MinMaxScaler做归一化,后续的预测和逆变换操作完全搞错了维度对应关系:
- 训练SVR时,我们的目标是用
date_delta(单特征)预测Close(标签),但你把两者混在一起做归一化,导致模型学习的是两个变量的联合分布,而非我们需要的“日期→价格”映射关系。 - 预测时你构造了
[[1654.0,0.0]]做变换,随后只取归一化后的date_delta值去预测——这相当于把模型当成单特征输入,但训练时模型接收的是两维输入(date_delta+Close),输入维度不匹配,结果自然毫无意义。 - 逆变换时传入的
[[predicted_val[0],0]]里,0是完全无意义的填充值,因为scaler是基于训练集的两个特征拟合的,逆变换需要对应正确的特征位置,但我们预测的是Close,应该单独对标签做归一化,而非和特征绑定。
正确的处理方式:
把特征和标签分开,分别做归一化:
# 分离特征与标签 X_train = btc_train[['date_delta']] y_train = btc_train[['Close']] X_test = btc_test[['date_delta']] y_test = btc_test[['Close']] # 特征归一化(针对date_delta) scaler_X = MinMaxScaler() X_train_scaled = scaler_X.fit_transform(X_train) X_test_scaled = scaler_X.transform(X_test) # 标签归一化(针对Close价格) scaler_y = MinMaxScaler() y_train_scaled = scaler_y.fit_transform(y_train) y_test_scaled = scaler_y.transform(y_test)
训练模型时使用正确的输入输出:
from sklearn.svm import SVR model = SVR(kernel='poly') # 注意要把y转成一维数组,用ravel() model.fit(X_train_scaled, y_train_scaled.ravel())
预测时的正确流程:
# 处理输入的date_delta input_date = np.array([[1654.0]]) # 用特征归一器做变换 scaled_input = scaler_X.transform(input_date) # 预测得到归一化后的价格 pred_scaled = model.predict(scaled_input) # 用标签归一器逆变换得到真实价格 pred_price = scaler_y.inverse_transform(pred_scaled.reshape(-1,1))
2. 时间序列数据不能随机划分训练/测试集
你用np.random.rand(len(btc_select)) < 0.8随机划分数据,这是时间序列任务的致命错误!时间序列具有时序依赖性,未来的数据绝对不能出现在训练集中——这种随机划分会导致数据泄露,模型看似在测试集上表现不错,但实际对未来数据的预测能力极差。
正确的划分方式:按时间顺序拆分,前80%作为训练集,后20%作为测试集:
train_size = int(len(btc_select) * 0.8) btc_train = btc_select.iloc[:train_size] btc_test = btc_select.iloc[train_size:]
3. 预测输入超出了训练集的特征分布范围
从你给出的transform_inp[0,0] = 1.000604960677556可以看出,1654.0这个date_delta已经超出了训练集中date_delta的最大值(MinMaxScaler会把数据缩放到[0,1]区间,超出范围的值会大于1或小于0)。
SVR(尤其是多项式核)的外推能力非常弱,对于训练数据分布之外的输入,预测结果往往偏差极大。你需要确认这个1654.0是否属于训练集覆盖的日期范围,如果是未来的日期,模型从未见过这么晚的数据,自然无法给出准确预测。
内容的提问来源于stack exchange,提问作者Rakshit Singh
相关产品推荐
相关产品推荐

