如何修改SVR测试数据,实现precomputed核函数无错预测?
使用自定义核函数的SVR预测报错解决方案及原理说明
问题分析
你遇到的报错核心原因是:自定义核函数的使用逻辑和内置核函数(如rbf、sigmoid)完全不同——内置核会自动处理特征向量到核矩阵的转换,但自定义核要求你手动提供测试样本与训练样本之间的核矩阵,而不是直接传入测试特征数据。
一、修正代码实现正常预测
要解决这个问题,你需要做两处关键修改:
1. 修正自定义核函数的逻辑
你的my_kernel函数目前计算的是X与自身的内积,这不符合核函数的定义(核函数应该计算两组样本X和Y之间的相似性)。正确的自定义核函数应该返回形状为[n_samples_X, n_samples_Y]的核矩阵:
def my_kernel(X, Y): # 计算X(n_samples_X, n_features)和Y(n_samples_Y, n_features)之间的内积核矩阵 return np.dot(X, Y.T)
2. 预测时传入测试-训练样本的核矩阵
在调用predict时,不能直接传入测试特征x_t,而是需要先计算x_t与训练集x之间的核矩阵,再将这个矩阵传入predict:
# 计算测试样本与训练样本的核矩阵 test_kernel_matrix = my_kernel(x_t, x) # 使用核矩阵进行预测 y_preds = svr.predict(test_kernel_matrix)
修改后的完整可运行代码
from sklearn import svm import pandas as pd import numpy as np # 生成模拟数据(修正原代码中的变量名错误) density = np.random.randint(0,100, size=(3000, 1)) speed = np.random.randint(20,80, size=(3000, 1)) + np.random.random(size=(3000, 1)) label = np.random.randint(20,80, size=(3000, 1)) + np.random.random(size=(3000, 1)) d = np.hstack((density, speed, label)) data = pd.DataFrame(d, columns=['density', 'speed', 'label']) data.density = data.density.astype(dtype=np.int32) # 修正后的自定义核函数 def my_kernel(X,Y): return np.dot(X, Y.T) svr = svm.SVR(kernel=my_kernel) x = data[['density', 'speed']].iloc[:2000] y = data['label'].iloc[:2000] x_t = data[['density', 'speed']].iloc[2000:3000] y_t = data['label'].iloc[2000:3000] svr.fit(x,y) # 计算测试-训练核矩阵并预测 test_kernel_matrix = my_kernel(x_t, x) y_preds = svr.predict(test_kernel_matrix)
二、为什么precomputed核的predict输入与其他核不同?
这本质是内置核与预计算核的设计逻辑差异:
- 内置核函数(如rbf、sigmoid):sklearn会自动处理特征向量的转换。训练时,它会计算训练样本之间的核矩阵;预测时,它会自动计算每个测试样本与训练阶段选出的支持向量之间的核函数值,整个过程对用户透明,你只需要传入特征向量即可。
- precomputed核(包括自定义核函数):sklearn假设你已经完成了核矩阵的计算。训练时你传入的是
[n_train, n_train]的训练样本核矩阵;预测时,必须传入[n_test, n_train]的测试-训练核矩阵——因为模型需要用这个矩阵来结合训练得到的支持向量权重,计算最终的预测值。你的自定义核函数本质是让sklearn以precomputed模式运行,所以必须遵循这个输入规则。
内容的提问来源于stack exchange,提问作者masouduut94
相关产品推荐
相关产品推荐

