高效的knn算法
Efficient knn algorithm
我正在尝试实现对 R 中的一维向量进行运算的 knn 算法,但它与标准算法略有不同,因为它在平局的情况下采用较小的元素(因此距离只是属性之间差异的绝对值)。更准确地说,我试图找到最接近给定数字的 k 个数字,如果有平局,我希望选择较小的数字。
听起来很简单,但我的算法需要几秒钟才能完成,而 class 包 (knn) 中的算法会立即输出答案(尽管在平局或随机元素的情况下它需要所有元素)...我的如下:
- 我抽取了一个训练样本,并对其进行了越来越多的排序。
- 我取一个元素(一个数字)
2.5.并搜索训练样本中第一个小于某个数字的地方。
- 我从训练样本中取2k+1个数字——k在2.5中找到的数字左边,k在右边(如果这样的数字少于k个,我会尽可能多地取) .
- 最后,我计算了所选元素与我在 2 中采用的元素的距离,并将它们与相应的元素一起递增排序(以便元素及其距离递增排序)
- 然后我从 4 中创建的列表中取出第 k 个元素。(这样没有两个元素的距离相同)
但是孩子,需要 6 或 7 秒才能完成...你有什么改进的想法吗? (这不是特定于 R 的问题,只是我在 R 中做的)。
编辑。代码:
dec <- function(u, x, k) {
## u is the training sample sorted increasingly
## x is an object for classification
## k is a knn parameter
knn <- list()
i <- 1
div <- 0
for (j in u) {
if (x < j) {
div <- 0
break
}
i <- i+1
}
if (div == 0) {
distances <- array(0,dim=c(2,k))
z <- 1
for (j in 1:k) {
distances[1,z] <- u[10000-j]
distances[2,z] <- abs(u[10000-j]-x)
}
} else {
end1 <- div+k
end2 <- div-k
if (div<k) {
distances <- array(0,dim=c(2,(div+k)))
a <- 1
for (j in u[1:end1]) {
distances[1,a] <- j
distances[2,a] <- abs(j-x)
a <- a+1
}
} else if (10000-div<k) {
distances <- array(0,dim=c(2,(1000-div+k)))
a <- 1
for (j in u[end2:10000]) {
distances[1,a] <- j
distances[2,a] <- abs(j-x)
a <- a+1
}
} else {
a <- 1
distances <- array(0,dim=c(2,(2*k+1)))
for (j in u[end1:end2]) {
distances[1,a] <- j
distances[2,a] <- abs(j-x)
a <- a+1
}
}
distances <- t(distances)
distances <- distances[ order( distances[,2], distances[,1]), ]
distances <- t(distances)
}
for (i in 1:k) {
if (i>1 && distances[1,i-1] != distances[1,i])
knn[i] <- distances[1,i]
}
## and sth later...
}
一维中的 kNN 很简单。
对值进行递增排序。要执行查询,请通过二分法搜索在已排序的序列中定位值。然后通过步进到最接近的任一侧(更小或更大)k 次来找到 k 个最接近的值。
我正在尝试实现对 R 中的一维向量进行运算的 knn 算法,但它与标准算法略有不同,因为它在平局的情况下采用较小的元素(因此距离只是属性之间差异的绝对值)。更准确地说,我试图找到最接近给定数字的 k 个数字,如果有平局,我希望选择较小的数字。
听起来很简单,但我的算法需要几秒钟才能完成,而 class 包 (knn) 中的算法会立即输出答案(尽管在平局或随机元素的情况下它需要所有元素)...我的如下:
- 我抽取了一个训练样本,并对其进行了越来越多的排序。
- 我取一个元素(一个数字) 2.5.并搜索训练样本中第一个小于某个数字的地方。
- 我从训练样本中取2k+1个数字——k在2.5中找到的数字左边,k在右边(如果这样的数字少于k个,我会尽可能多地取) .
- 最后,我计算了所选元素与我在 2 中采用的元素的距离,并将它们与相应的元素一起递增排序(以便元素及其距离递增排序)
- 然后我从 4 中创建的列表中取出第 k 个元素。(这样没有两个元素的距离相同)
但是孩子,需要 6 或 7 秒才能完成...你有什么改进的想法吗? (这不是特定于 R 的问题,只是我在 R 中做的)。
编辑。代码:
dec <- function(u, x, k) {
## u is the training sample sorted increasingly
## x is an object for classification
## k is a knn parameter
knn <- list()
i <- 1
div <- 0
for (j in u) {
if (x < j) {
div <- 0
break
}
i <- i+1
}
if (div == 0) {
distances <- array(0,dim=c(2,k))
z <- 1
for (j in 1:k) {
distances[1,z] <- u[10000-j]
distances[2,z] <- abs(u[10000-j]-x)
}
} else {
end1 <- div+k
end2 <- div-k
if (div<k) {
distances <- array(0,dim=c(2,(div+k)))
a <- 1
for (j in u[1:end1]) {
distances[1,a] <- j
distances[2,a] <- abs(j-x)
a <- a+1
}
} else if (10000-div<k) {
distances <- array(0,dim=c(2,(1000-div+k)))
a <- 1
for (j in u[end2:10000]) {
distances[1,a] <- j
distances[2,a] <- abs(j-x)
a <- a+1
}
} else {
a <- 1
distances <- array(0,dim=c(2,(2*k+1)))
for (j in u[end1:end2]) {
distances[1,a] <- j
distances[2,a] <- abs(j-x)
a <- a+1
}
}
distances <- t(distances)
distances <- distances[ order( distances[,2], distances[,1]), ]
distances <- t(distances)
}
for (i in 1:k) {
if (i>1 && distances[1,i-1] != distances[1,i])
knn[i] <- distances[1,i]
}
## and sth later...
}
一维中的 kNN 很简单。
对值进行递增排序。要执行查询,请通过二分法搜索在已排序的序列中定位值。然后通过步进到最接近的任一侧(更小或更大)k 次来找到 k 个最接近的值。