R中快速计算欧式距离
这个办法是一个QQ群里的朋友一帆教我的,我有点小修改。之前我一直用的R里的dist函数,非常笨重。
现在有一个2000*1000维的矩阵。从数据的观点看,每一行代表一个记录,一列是一个特征。现在要计算记录之间两两的欧式距离,结果保存成一个2000*2000的矩阵。
计算方法及结果对比如下。
> mat <- matrix(runif(2000*1000),nrow=2000)
> system.time({
+ smat <- apply(mat, 1, crossprod)
+ mat1 <- matrix(smat, nrow=2000, ncol=2000)
+ mat3 <- tcrossprod(mat)
+ mat4 <- mat1 + t(mat1) - 2*mat3
+ diag(mat4) <- 0
+ mat5 <- sqrt(mat4)
+ })
user system elapsed
1.100 0.460 0.511
> print(mat5[1:6, 1:6])
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0.00000 13.05566 12.98108 13.14579 13.08746 12.61098
[2,] 13.05566 0.00000 13.37668 13.02377 13.02189 13.12892
[3,] 12.98108 13.37668 0.00000 13.52206 13.21246 13.25907
[4,] 13.14579 13.02377 13.52206 0.00000 13.14706 13.36026
[5,] 13.08746 13.02189 13.21246 13.14706 0.00000 13.16084
[6,] 12.61098 13.12892 13.25907 13.36026 13.16084 0.00000
> system.time(mat7 <- as.matrix(dist(mat)))
user system elapsed
41.460 0.000 41.493
> print(mat7[1:6, 1:6])
1 2 3 4 5 6
1 0.00000 13.05566 12.98108 13.14579 13.08746 12.61098
2 13.05566 0.00000 13.37668 13.02377 13.02189 13.12892
3 12.98108 13.37668 0.00000 13.52206 13.21246 13.25907
4 13.14579 13.02377 13.52206 0.00000 13.14706 13.36026
5 13.08746 13.02189 13.21246 13.14706 0.00000 13.16084
6 12.61098 13.12892 13.25907 13.36026 13.16084 0.00000
>
这个东东在核方法,特别是计算高斯核的时候,是非常有用的。
现在有一个2000*1000维的矩阵。从数据的观点看,每一行代表一个记录,一列是一个特征。现在要计算记录之间两两的欧式距离,结果保存成一个2000*2000的矩阵。
计算方法及结果对比如下。
> mat <- matrix(runif(2000*1000),nrow=2000)
> system.time({
+ smat <- apply(mat, 1, crossprod)
+ mat1 <- matrix(smat, nrow=2000, ncol=2000)
+ mat3 <- tcrossprod(mat)
+ mat4 <- mat1 + t(mat1) - 2*mat3
+ diag(mat4) <- 0
+ mat5 <- sqrt(mat4)
+ })
user system elapsed
1.100 0.460 0.511
> print(mat5[1:6, 1:6])
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0.00000 13.05566 12.98108 13.14579 13.08746 12.61098
[2,] 13.05566 0.00000 13.37668 13.02377 13.02189 13.12892
[3,] 12.98108 13.37668 0.00000 13.52206 13.21246 13.25907
[4,] 13.14579 13.02377 13.52206 0.00000 13.14706 13.36026
[5,] 13.08746 13.02189 13.21246 13.14706 0.00000 13.16084
[6,] 12.61098 13.12892 13.25907 13.36026 13.16084 0.00000
> system.time(mat7 <- as.matrix(dist(mat)))
user system elapsed
41.460 0.000 41.493
> print(mat7[1:6, 1:6])
1 2 3 4 5 6
1 0.00000 13.05566 12.98108 13.14579 13.08746 12.61098
2 13.05566 0.00000 13.37668 13.02377 13.02189 13.12892
3 12.98108 13.37668 0.00000 13.52206 13.21246 13.25907
4 13.14579 13.02377 13.52206 0.00000 13.14706 13.36026
5 13.08746 13.02189 13.21246 13.14706 0.00000 13.16084
6 12.61098 13.12892 13.25907 13.36026 13.16084 0.00000
>
这个东东在核方法,特别是计算高斯核的时候,是非常有用的。