反向支持向量机:计算预测
Reverse support vector machine: calculating the predictions
我想知道,给定 svm 回归模型的回归系数,是否可以计算该模型做出的预测 'by hand'。
更准确地说,假设:
svc = SVR(kernel='rbf', epsilon=0.3, gamma=0.7, C=64)
svc.fit(X_train, y_train)
那么你可以很容易地使用
获得预测
y_pred = svc.predict(X_test)
我想知道如何通过直接计算得到这个结果。从决策函数开始,
其中 K
是 RBF 核函数,b
是截距,alpha 是对偶系数。
因为我使用 RBF 内核,所以我是这样开始的:
def RBF(x,z,gamma,axis=None):
return np.exp((-gamma*np.linalg.norm(x-z, axis=axis)**2))
for i in len(svc.support_):
A[i] = RBF(X_train[i], X_test[0], 0.7)
然后我算了算
np.sum(svc._dual_coef_*A)+svc.intercept_
然而,这个计算的结果与y_pred
的第一项不同。我怀疑我的推理不完全正确 and/or 我的代码不是它应该的样子,如果这不是正确的问题,我深表歉意。在过去的 2 个小时里,我一直在盯着这个问题看,所以非常感谢任何帮助!
更新
经过更多研究,我发现了以下 post: and 。
在第一个 post 中,他们谈论回归,在第二个中谈论分类,但思想保持不变。在这两种情况下,OP 基本上都在问同样的事情,但是当我尝试实现他们的代码时,我总是 运行 在步骤
中出错
diff = sup_vecs - X_test
形式
ValueError: operands could not be broadcast together with shapes
(number equal to amount of support vectors,7) (number equal to len(Xtest),7)
我不明白为什么支持向量的数量应该等于测试数据的数量。据我了解,几乎从来没有这种情况。那么谁能阐明应该如何更普遍地解决这个问题,即如何改进代码以使其适用于多维数组?
P.S。与问题无关,但准确地说:7 是特征数。
你犯的错误在for i in len(svc.support_):
这个循环中。
您遍历第一个 n_SV(支持向量数)个训练点,不一定是支持向量。因此,只需遍历 svc.support_vectors_
即可获得实际的支持向量。您的其余代码保持不变。下面我提供了更正的代码。
from sklearn import datasets
from sklearn.svm import SVR
# Load the IRIS dataset for demonstration
iris = datasets.load_iris()
X = iris.data
y = iris.target
# Train-test split
X_train, y_train = X[:140], y[:140]
X_test, y_test = X[140:], y[140:]
print(X.shape, X_train.shape, X_test.shape) # prints (150, 4) (140, 4) (10, 4)
# Fit a rbf kernel SVM
svc = SVR(kernel='rbf', epsilon=0.3, gamma=0.7, C=64)
svc.fit(X_train, y_train)
# Get prediction for a point X_test using train SVM, svc
def get_pred(svc, X_test):
def RBF(x,z,gamma,axis=None):
return np.exp((-gamma*np.linalg.norm(x-z, axis=axis)**2))
A = []
# Loop over all suport vectors to calculate K(Xi, X_test), for Xi belongs to the set of support vectors
for x in svc.support_vectors_:
A.append(RBF(x, X_test, 0.7))
A = np.array(A)
return (np.sum(svc._dual_coef_*A)+svc.intercept_)
for i in range(X_test.shape[0]):
print(get_pred(svc, X_test[i]))
print(svc.predict(X_test[i].reshape(1,-1))) # The same oputput by both
我想知道,给定 svm 回归模型的回归系数,是否可以计算该模型做出的预测 'by hand'。 更准确地说,假设:
svc = SVR(kernel='rbf', epsilon=0.3, gamma=0.7, C=64)
svc.fit(X_train, y_train)
那么你可以很容易地使用
获得预测y_pred = svc.predict(X_test)
我想知道如何通过直接计算得到这个结果。从决策函数开始,
K
是 RBF 核函数,b
是截距,alpha 是对偶系数。
因为我使用 RBF 内核,所以我是这样开始的:
def RBF(x,z,gamma,axis=None):
return np.exp((-gamma*np.linalg.norm(x-z, axis=axis)**2))
for i in len(svc.support_):
A[i] = RBF(X_train[i], X_test[0], 0.7)
然后我算了算
np.sum(svc._dual_coef_*A)+svc.intercept_
然而,这个计算的结果与y_pred
的第一项不同。我怀疑我的推理不完全正确 and/or 我的代码不是它应该的样子,如果这不是正确的问题,我深表歉意。在过去的 2 个小时里,我一直在盯着这个问题看,所以非常感谢任何帮助!
更新
经过更多研究,我发现了以下 post:
diff = sup_vecs - X_test
形式
ValueError: operands could not be broadcast together with shapes
(number equal to amount of support vectors,7) (number equal to len(Xtest),7)
我不明白为什么支持向量的数量应该等于测试数据的数量。据我了解,几乎从来没有这种情况。那么谁能阐明应该如何更普遍地解决这个问题,即如何改进代码以使其适用于多维数组?
P.S。与问题无关,但准确地说:7 是特征数。
你犯的错误在for i in len(svc.support_):
这个循环中。
您遍历第一个 n_SV(支持向量数)个训练点,不一定是支持向量。因此,只需遍历 svc.support_vectors_
即可获得实际的支持向量。您的其余代码保持不变。下面我提供了更正的代码。
from sklearn import datasets
from sklearn.svm import SVR
# Load the IRIS dataset for demonstration
iris = datasets.load_iris()
X = iris.data
y = iris.target
# Train-test split
X_train, y_train = X[:140], y[:140]
X_test, y_test = X[140:], y[140:]
print(X.shape, X_train.shape, X_test.shape) # prints (150, 4) (140, 4) (10, 4)
# Fit a rbf kernel SVM
svc = SVR(kernel='rbf', epsilon=0.3, gamma=0.7, C=64)
svc.fit(X_train, y_train)
# Get prediction for a point X_test using train SVM, svc
def get_pred(svc, X_test):
def RBF(x,z,gamma,axis=None):
return np.exp((-gamma*np.linalg.norm(x-z, axis=axis)**2))
A = []
# Loop over all suport vectors to calculate K(Xi, X_test), for Xi belongs to the set of support vectors
for x in svc.support_vectors_:
A.append(RBF(x, X_test, 0.7))
A = np.array(A)
return (np.sum(svc._dual_coef_*A)+svc.intercept_)
for i in range(X_test.shape[0]):
print(get_pred(svc, X_test[i]))
print(svc.predict(X_test[i].reshape(1,-1))) # The same oputput by both