线性支持向量机模型中的权重(在R中)?

5

我使用kernlab训练了一个模型,代码如下:

my.model <- ksvm(result ~ f1+f2+f3, data=gold, kernel="vanilladot")

由于这是一个线性模型,我更喜欢在运行时将得分计算为特征值的简单加权和,而不是使用完整的SVM机制。如何将模型转换为类似这样的内容(这里有一些虚构的权重):

> c(.bias=-2.7, f1=0.35, f2=-0.24, f3=2.31)
.bias    f1    f2    f3 
-2.70  0.35 -0.24  2.31 

其中.bias是偏置项,其余的是特征权重?

编辑:

这里有一些示例数据。

gold <- structure(list(result = c(-1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), f1 = c(0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 
1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1), f2 = c(13.4138113499447, 
13.2216999857095, 12.964145772169, 13.1975227965938, 13.1031520152764, 
13.59351759447, 13.1031520152764, 13.2700658838026, 12.964145772169, 
13.1975227965938, 12.964145772169, 13.59351759447, 13.59351759447, 
13.0897162110721, 13.364151238365, 12.9483051847806, 12.964145772169, 
12.964145772169, 12.964145772169, 12.9483051847806, 13.0937231331592, 
13.5362700880482, 13.3654209223623, 13.4356400945176, 13.59351759447, 
13.2659406408724, 13.4228886221088, 13.5103065354936, 13.5642812689161, 
13.3224757352068, 13.1779418771704, 13.5601730479315, 13.5457299603578, 
13.3729010596517, 13.4823595997866, 13.0965264603473, 13.2710281801434, 
13.4489887206797, 13.5132372154748, 13.5196188787197), f3 = c(0, 
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 
0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0)), .Names = c("result", 
"f1", "f2", "f3"), class = "data.frame", row.names = c(NA, 40L
))

1
提供一个小的可重现的例子总是很有用的... - hadley
2个回答

7

为了得到偏差,只需使用全零特征向量对模型进行评估。为了获得第一个特征的系数,需要使用在第一位置带有“1”且其他位置都是零的特征向量对模型进行评估,然后减去已知的偏差。我不熟悉R语法,但从概念上讲,您需要这样做:

bias = my.model.eval([0, 0, 0])
f1 = my.model.eval([1, 0, 0]) - bias
f2 = my.model.eval([0, 1, 0]) - bias
f3 = my.model.eval([0, 0, 1]) - bias

为了测试你是否做得正确,你可以尝试像这样做:
assert(bias + f1 + f2 + f3 == my.model.eval([1, 1, 1]))

5

如果我没记错的话,我想你是在询问如何提取SVM的W向量,其中W的定义为:

W = \sum_i y_i * \alpha_i * example_i

Ugh: 我不知道在这里写方程的最佳方法,但这只是权重*支持向量的总和。计算W后,您可以提取所需特征的“权重”。

假设这是正确的,您需要:

  1. 获取支持向量数据的索引
  2. 获取它们的权重(α)
  3. 计算 W

kernlab将支持向量索引及其值存储在列表中(因此它也适用于多类问题),无论如何,任何列表操作都只是为了获取真实数据(如果您只有2类问题,则通过alpha和alphaindex返回的列表长度仅为1,我假设您就是这种情况)。

my.model <- ksvm(result ~ f1+f2+f3, data=gold, kernel="vanilladot", type="C-svc")
alpha.idxs <- alphaindex(my.model)[[1]]  # Indices of SVs in original data
alphas <- alpha(my.model)[[1]]
y.sv <- gold$result[alpha.idxs]
# for unscaled data
sv.matrix <- as.matrix(gold[alpha.idxs, c('f1', 'f2', 'f3')])
weight.vector <- (y.sv * alphas) %*% sv.matrix
bias <- b(my.model)

kernlab实际上会在执行相关操作之前对数据进行缩放。您可以按以下方式获取(经过缩放的)权重(在这里,我猜偏差应该为0(?))。

weight.vector <- (y.sv * alphas) %*% xmatrix(my.model)[[1]]

如果我理解您的问题,这应该能帮助您得到您想要的东西。

无法使其正常工作。使用基向量评估方法和上面的示例数据,我得到偏差=-39.97968,权重=(0.274949, 3.014561, -0.02817000)。我可以使用predict()在一些示例中进行确认。然而,当我尝试使用您的直接提取方法时,我得到偏差=-0.1310986,权重=(4.048555, 325.5573, 7.994651)。请注意,alphaindex()和alpha()实际上似乎不返回列表,而是向量。 - Ken Williams
抱歉,现在无法查看这个......我只是想发表评论,因为我在代码中修正了一个或两个错别字(顺便说一下,如果你没有明确设置类型,它会默认执行回归)......老实说,我认为存在一些缩放问题。另外,如果你再次运行它,f3的权重应该使用两种方法都为0。 - Steve Lianoglou
是的,我确信这也是一个缩放问题,但我似乎找不到正确的方法来解决缩放。 - Ken Williams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接