加权 k 最近邻和 R kknn 包

Weighted k-nearest neighbors and R kknn package

我想了解 R kknn 包如何计算二元 class 化问题的权重、距离和 class 概率。在下面的 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"]]

调用 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 转换为 1 行 (p=1)、3 列 (k=3)

的矩阵 W <- matrix(W, p, k)

拟合值

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)