Answers:
这是一个相对较旧的话题,但是我最近在工作中遇到了这个问题,偶然发现了这个讨论。该问题已得到解答,但我认为尚未解决将行标准化而不是分析单位的危险(请参见上述@DJohnson的答案)。
要点是,对行进行归一化可能不利于任何后续分析,例如最近邻居或k均值。为简单起见,我将保留针对均值居中的特定答案。
为了说明这一点,我将在超立方体的角上使用模拟的高斯数据。幸运的是,R
其中有一个方便的功能(代码位于答案的结尾)。在2D情况下,直接以行均值为中心的数据将落在以135度穿过原点的线上。然后使用具有正确聚类数的k均值对模拟数据进行聚类。数据和聚类结果(在原始数据上使用PCA在2D中可视化)看起来像这样(最左侧图的轴不同)。聚类图中点的不同形状是指真实的聚类分配,而颜色是k均值聚类的结果。
当数据以行平均为中心时,左上和右下群集将减少一半。因此,以行平均为中心的距离会失真,并且意义不大(至少基于数据知识)。
在2D中并不奇怪,如果我们使用更多尺寸会怎样?这是3D数据发生的情况。行均值居中后的聚类解决方案是“不好的”。
并且与4D数据相似(为简便起见,现在显示)。
为什么会这样呢?以行均值为中心将数据推入某个空间,某些功能会比其他功能更接近。这应该反映在特征之间的相关性上。让我们看一下(对于2D和3D案例,首先查看原始数据,然后查看以行均值为中心的数据)。
[,1] [,2]
[1,] 1.000 -0.001
[2,] -0.001 1.000
[,1] [,2]
[1,] 1 -1
[2,] -1 1
[,1] [,2] [,3]
[1,] 1.000 -0.001 0.002
[2,] -0.001 1.000 0.003
[3,] 0.002 0.003 1.000
[,1] [,2] [,3]
[1,] 1.000 -0.504 -0.501
[2,] -0.504 1.000 -0.495
[3,] -0.501 -0.495 1.000
因此,看起来以行均值为中心正在引入要素之间的相关性。这对功能数量有何影响?我们可以做一个简单的模拟来弄清楚这一点。仿真结果如下所示(再次在代码末尾)。
因此,随着特征数量的增加,行均值居中的影响似乎减弱,至少在引入的相关性方面。但是我们只是使用均匀分布的随机数据进行此模拟(这在研究维数诅咒时很常见)。
那么当我们使用真实数据时会发生什么呢?很多时候,数据的固有维数较低,因此诅咒可能不适用。在这种情况下,我猜想以行平均为中心可能是一个“糟糕”的选择,如上所示。当然,需要进行更严格的分析才能做出任何明确的主张。
集群模拟代码
palette(rainbow(10))
set.seed(1024)
require(mlbench)
N <- 5000
for(D in 2:4) {
X <- mlbench.hypercube(N, d=D)
sh <- as.numeric(X$classes)
K <- length(unique(sh))
X <- X$x
Xc <- sweep(X,2,apply(X,2,mean),"-")
Xr <- sweep(X,1,apply(X,1,mean),"-")
show(round(cor(X),3))
show(round(cor(Xr),3))
par(mfrow=c(1,1))
k <- kmeans(X,K,iter.max = 1000, nstart = 10)
kc <- kmeans(Xc,K,iter.max = 1000, nstart = 10)
kr <- kmeans(Xr,K,iter.max = 1000, nstart = 10)
pc <- prcomp(X)
par(mfrow=c(1,4))
lim <- c(min(min(X),min(Xr),min(Xc)), max(max(X),max(Xr),max(Xc)))
plot(X[,1], X[,2], xlim=lim, ylim=lim, xlab="Feature 1", ylab="Feature 2",main="Data",col=1,pch=1)
points(Xc[,1], Xc[,2], col=2,pch=2)
points(Xr[,1], Xr[,2], col=3,pch=3)
legend("topleft",legend=c("Original","Center-cols","Center-rows"),col=c(1,2,3),pch=c(1,2,3))
abline(h=0,v=0,lty=3)
plot(pc$x[,1], pc$x[,2], col=rainbow(K)[k$cluster], xlab="PC 1", ylab="PC 2", main="Cluster original", pch=sh)
plot(pc$x[,1], pc$x[,2], col=rainbow(K)[kc$cluster], xlab="PC 1", ylab="PC 2", main="Cluster center-col", pch=sh)
plot(pc$x[,1], pc$x[,2], col=rainbow(K)[kr$cluster], xlab="PC 1", ylab="PC 2", main="Cluster center-row", pch=sh)
}
用于增加功能仿真的代码
set.seed(2048)
N <- 1000
Cmax <- c()
Crmax <- c()
for(D in 2:100) {
X <- matrix(runif(N*D), nrow=N)
C <- abs(cor(X))
diag(C) <- NA
Cmax <- c(Cmax, max(C, na.rm=TRUE))
Xr <- sweep(X,1,apply(X,1,mean),"-")
Cr <- abs(cor(Xr))
diag(Cr) <- NA
Crmax <- c(Crmax, max(Cr, na.rm=TRUE))
}
par(mfrow=c(1,1))
plot(Cmax, ylim=c(0,1), ylab="Max. cor.", xlab="#Features",col=1,pch=1)
points(Crmax, ylim=c(0,1), col=2, pch=2)
legend("topright", legend=c("Original","Center-row"),pch=1:2,col=1:2)
编辑
经过一些谷歌搜索后,此页面上的模拟显示了相似的行为,并建议以行均值居中引入的相关性为。
行规范化有多种形式,OP并未说明要记住哪一个。
行标准化的一种特定形式(欧几里得规范化)很受欢迎,其中每行都经过标准化(由其欧几里得范数划分)。
例如,如果原始数据居中(如该图像中的黑点),并且对其应用行归一化,则将获得红色星号。
library(car)
p = 2
n = 1000
m = 10
C = matrix(.9, p, p)
diag(C) = 1
set.seed(123)
x = matrix(runif(n * p, -1, 1), n, p) %*% chol(C)
z = sweep(x, 1, sqrt(rowSums(x * x)), FUN = '/')
plot(rbind(x, z), pch = 16, type = 'n', ann = FALSE, xaxt = 'n', yaxt = 'n')
points(x, pch = 16)
points(z, pch = 8, col = 'red')
绿点表示原始数据中的少量异常值。如果将行归一化转换应用于它们,则将获得蓝星。
x_1 = sweep(matrix(runif(m * p, -1, 1), m, p), 2, c(2, -2))
z_1 = sweep(x_1, 1, sqrt(rowSums(x_1 * x_1)), FUN = '/')
plot(rbind(x, x_1, z, z_1), pch = 16, type = 'n', ann = FALSE, xaxt = 'n', yaxt = 'n')
points(x, pch = 16)
points(x_1, pch = 16, col = 'green')
points(z, pch = 8, col = 'red')
points(z_1, pch = 8, col = 'blue')
通过将依次拟合的形状矩阵(或轮廓椭圆)与数据,其污染版本以及其行归一化转换进行比较,可以最清楚地看到这一点:
ellipse(crossprod(rbind(x, x_1)) / (n + m - 1) / det(crossprod(rbind(x, x_1)) / (n + m - 1))^(1 / p), center = rep(0, p), col = 'green', radius = 1)
ellipse(crossprod(rbind(z, z_1)) / (n + m - 1) / det(crossprod(rbind(z, z_1)) / (n + m - 1))^(1 / p), center = rep(0, p), col = 'red', radius = 1)
ellipse(crossprod(rbind(x)) / (n - 1) / det(crossprod(rbind(x)) / (n - 1))^(1 / p), center = rep(0, p), col = 'black', radius = 1)
执行行规范化有一些特定于字段的原因。在文本分析中,用包含的单词的直方图表示文本非常普遍。从每行的单词数开始,原始标准化将其转换为直方图。
以及计算原因。如果使用稀疏矩阵,则无法轻松地逐列居中和缩放数据。如果将其嵌入密集矩阵中,数据可能会变得太大而无法容纳在内存中。但是,逐行缩放不会影响所需的内存总量。