【问题标题】:Weighted k-nearest neighbors and R kknn package加权 k 最近邻和 R kknn 包
【发布时间】:2021-04-15 15:58:12
【问题描述】:

我想了解 R kknn 包如何计算二元分类问题的权重、距离和类别概率。在下面的 R 代码中,训练样本中有 3 个观察值,保留样本中有 1 个观察值。两个预测变量是身高和体重。使用欧几里得距离,训练样本中每个观测值的距离为:

sqrt((6-8)^2 + (4-5)^2) = 2.24

sqrt((6-3)^2 + (4-7)^2) = 4.24

sqrt((6-7)^2 + (4-3)^2) = 1.41。

在 k=3 且权重相等的情况下,我得到的坚持概率为:

(1/3 * 1) + (1/3 * 0) + (1/3 * 1) = 0.67。

在 k=2 且权重相等的情况下,我得到的坚持概率为:

(1/2 * 1) + (1/2 * 1) = 1.00。

我想了解 R kknn 包如何使用“三角形”、“高斯”和“反”权重(以及更普遍的)进行这些相同的计算。

library(kknn)

training <- data.frame(class = c(1, 0, 1), height = c(8, 3, 7), weight = c(5, 7, 3))

holdouts <- data.frame(class = 1, height = 6, weight = 4)

triangular_kernel <- kknn(class ~., training, holdouts, distance = 2, kernel = "triangular", k = 3)

triangular_kernel[["fitted.values"]]

triangular_kernel[["W"]]

triangular_kernel[["D"]]

gaussian_kernel <- kknn(class ~., training, holdouts, distance = 2, kernel = "gaussian", k = 3)

gaussian_kernel[["fitted.values"]]

gaussian_kernel[["W"]]

gaussian_kernel[["D"]]

inverse_kernel <- kknn(class ~., training, holdouts, distance = 2, kernel = "inv", k = 3)

inverse_kernel[["fitted.values"]]

inverse_kernel[["W"]]

inverse_kernel[["D"]]

【问题讨论】:

  • 看起来这个包是同一作者写的论文的实现。在谷歌上,我在这里找到了该论文的 pdf 版本(不知道它是否是合法副本):epub.ub.uni-muenchen.de/1769/1/paper_399.pdf。我不知道你的问题的答案,但可以想象你可以在论文中找到它。
  • 距离加权 k 近邻 (DWKNN)

标签: r machine-learning nearest-neighbor


【解决方案1】:

调用kknn::kknn 会在控制台中打印 kknn 函数的源代码。有了它,就可以逐行浏览函数的作用了。

距离

kknn 调用已编译的 C 代码 dmEuclid。获取它的源代码,我们关注this guide,用R编写如下代码:

untar(download.packages(pkgs = "kknn", destdir = ".", type = "source")[,2])

然后打开工作目录(getwd())中的 kknn_1.3.1.tar 的 src 目录,使用任意文本编辑器查找并打开 dm.C。滚动大约一半以找到 dmEuclid。要测试dmEuclid 的确切输出,您可以安装构建工具,并通过在下拉菜单中选择它在 Rstudio 中打开一个 C++ 文件,然后使用不同的输入运行代码。

在函数输出之后,在您的情况下,dmtmp$dm 会导致

3.779645e-01  1.133893e+00 1.000000e+150 3.685210e-156

根据您的规范 k,前 3 个值被选为距离 D。 这是由包作者手动转换为maxdist = 1e-06,因为最大距离小于您的情况。

权重

kknn 函数使用以下部分根据您定义的内核分配权重方案。

 W <- D/maxdist
 W <- pmin(W, 1 - (1e-06))
 W <- pmax(W, 1e-06)

此时您的 W 值大于 1,因此 W 被强制为大约 1。

if (kernel == "inv" 
        W <- 1/W
if (kernel == "triangular") 
        W <- 1 - W
if (kernel == "gaussian") {
        alpha = 1/(2 * (k + 1))
        qua = abs(qnorm(alpha))
        W = W * qua
        W = dnorm(W, sd = 1)
    }

可以在 gowerc 链接的论文中找到解释。 然后将 W 转换为矩阵 W &lt;- matrix(W, p, k),1 行 (p=1),3 列 (k=3)

拟合值

p = 1 在你的情况下是 1,k=3cl = c(1,0,1)

C <- matrix(dmtmp$cl, nrow = p, ncol = k + 1)
C <- C[, 1:k] + 1
CL <- matrix(cl[C], nrow = p, ncol = k)
W <- matrix(W, p, k)
fit <- rowSums(W * CL)/pmax(rowSums(W), 1e-06)

【讨论】:

  • 文章指出,“为了在计算距离时对每个协变量赋予相同的权重,必须对值进行标准化。”标准化意味着将变量除以它们的标准差。我假设这些距离是 dmtmp$dm 给出的。但是当我计算标准化距离时,我得到: d(x, x(1)) = sqrt(((6/sd(c(8,3,7))) - (8/sd(c(8,3, 7))))^2 + ((4/sd(c(5,7,3))) - (5/sd(c(5,7,3))))^2) 和 d(x, x (2)) = sqrt(((6/sd(c(8,3,7))) - (3/sd(c(8,3,7))))^2 + ((4/sd(c (5,7,3))) - (7/sd(c(5,7,3))))^2),依此类推。这些与 dmtmp$dm 不匹配,这是第一步。
  • 来自文章——“各种协变量的标准化仅基于来自学习集的观察。” kknn通过几个步骤构造learn,并通过一些步骤制作称为d.sd的sds向量。然后,`sweep(learn, 2L, d.sd, "/", check.margin = FALSE)` 是将值除以d.sd 的代码行。这一切都发生在之前 dmtmp 被计算出来,因为dmEuclid 函数将learn 作为输入变量。
  • 感谢您的帮助和耐心等待。你的答案是迄今为止最好的。但我真正希望的是直接回答以下问题:鉴于我示例中的数字,请使用数学(不是复杂的计算机代码)向我展示 kknn 函数如何获得其数字?
猜你喜欢
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 2019-01-03
  • 2020-06-17
  • 2018-04-08
相关资源
最近更新 更多