非常偏斜的计数数据的聚类:有什么建议(转换等)?

机器算法验证 聚类 数据转换 k-均值 计数数据 组成数据
2022-01-25 10:03:33

基本问题

这是我的基本问题:我正在尝试对包含一些带有计数的非常倾斜的变量的数据集进行聚类。这些变量包含许多零,因此对于我的聚类过程来说信息量不是很大——这可能是 k-means 算法。

好吧,你说,只需使用平方根、box cox 或对数来转换变量。但是由于我的变量是基于分类变量的,我担心我可能会通过处理一个变量(基于分类变量的一个值)来引入偏差,而让其他变量(基于分类变量的其他值)保持原样.

让我们更详细地介绍一下。

数据集

我的数据集代表物品的购买。这些项目具有不同的类别,例如颜色:蓝色、红色和绿色。然后将购买组合在一起,例如按客户。这些客户中的每一个都由我的数据集的一行表示,因此我必须以某种方式汇总客户的购买。

我这样做的方法是计算购买次数,其中商品是某种颜色。color因此,我最终得到了三个变量count_redcount_blue和 ,而不是单个变量count_green

这是一个示例:

-----------------------------------------------------------
customer | count_red  |    count_blue   | count_green     |
-----------------------------------------------------------
c0       |    12      |        5        |       0         |
-----------------------------------------------------------
c1       |     3      |        4        |       0         |
-----------------------------------------------------------
c2       |     2      |       21        |       0         |
-----------------------------------------------------------
c3       |     4      |        8        |       1         |
-----------------------------------------------------------

实际上,我最后不使用绝对计数,我使用比率(每个客户购买的所有商品中绿色商品的比例)。

-----------------------------------------------------------
customer | count_red  |    count_blue   | count_green     |
-----------------------------------------------------------
c0       |    0.71    |        0.29     |       0.00      |
-----------------------------------------------------------
c1       |    0.43    |        0.57     |       0.00      |
-----------------------------------------------------------
c2       |    0.09    |        0.91     |       0.00      |
-----------------------------------------------------------
c3       |    0.31    |        0.62     |       0.08      |
-----------------------------------------------------------

结果是一样的:对于我的一种颜色,例如绿色(没有人喜欢绿色),我得到一个包含许多零的左偏变量。因此,k-means 无法为这个变量找到一个好的分区。

另一方面,如果我标准化我的变量(减去均值,除以标准差),绿色变量由于其小的方差而“爆炸”,并且从比其他变量大得多的范围内取值,这使它看起来更多对 k-means 来说比实际更重要。

下一个想法是转换 sk(r)ewed green 变量。

转换偏态变量

如果我通过应用平方根来转换绿色变量,它看起来不那么偏斜。(这里绿色变量以红色和绿色绘制以确保混淆。)

在此处输入图像描述

红色:原始变量;蓝色:按平方根变换。

假设我对这种转换的结果感到满意(我不满意,因为零点仍然强烈地扭曲分布)。我现在是否也应该缩放红色和蓝色变量,尽管它们的分布看起来不错?

底线

换句话说,我是否通过一种方式处理绿色来扭曲聚类结果,但根本不处理红色和蓝色?最后,所有三个变量都属于一起,所以它们不应该以相同的方式处理吗?

编辑

澄清一下:我知道 k-means 可能不是基于计数的数据的方法。然而,我的问题实际上是关于因变量的处理。选择正确的方法是另一回事。

我的变量的内在约束是

count_red(i) + count_blue(i) + count_green(i) = n(i),其中n(i)是客户的总购买次数i

(或者,等效地,count_red(i) + count_blue(i) + count_green(i) = 1当使用相对计数时。)

如果我以不同方式转换变量,这对应于对约束中的三个项赋予不同的权重。如果我的目标是最佳地分离客户组,我是否必须关心违反此约束?还是“目的证明手段合理”?

2个回答

单独转换变量是不明智的,因为它们属于一起(正如您所注意到的)并且因为数据是计数而执行 k-means 是不明智的(您可能会,但 k-means 更好地用于连续属性,例如长度) .

在你的位置,我会根据包含计数的变量计算每对客户之间的卡方距离(非常适合计数)。然后进行层次聚类(例如,平均链接方法或完全链接方法 - 它们不计算质心,因此不需要欧几里德距离)或使用任意距离矩阵的其他聚类。

从问题中复制示例数据:

-----------------------------------------------------------
customer | count_red  |    count_blue   | count_green     |
-----------------------------------------------------------
c0       |    12      |        5        |       0         |
-----------------------------------------------------------
c1       |     3      |        4        |       0         |
-----------------------------------------------------------
c2       |     2      |       21        |       0         |
-----------------------------------------------------------
c3       |     4      |        8        |       1         |
-----------------------------------------------------------

考虑配对c0c1计算其频率表的卡方统计量。2x3取它的平方根(就像你在计算通常的欧几里得距离时取它一样)。那是你的距离。如果距离接近 0,则两个客户相似。

c0表中的行中的总和不同可能会让您感到困扰,因此当您与c1vsc0进行比较时,它会影响卡方距离c2然后计算Phi 平方距离的(根) :Phi-sq = Chi-sq/N其中N是当前考虑的两行(客户)中的总计数。因此,它是对总计数的归一化距离。

Here is the matrix of sqrt(Chi-sq) distance between your four customers
 .000   1.275   4.057   2.292
1.275    .000   2.124    .862
4.057   2.124    .000   2.261
2.292    .862   2.261    .000

And here is the matrix of sqrt(Phi-sq) distance 
.000    .260    .641    .418
.260    .000    .388    .193
.641    .388    .000    .377
.418    .193    .377    .000

因此,任何两行数据之间的距离是频率表的卡方phi 方统计量(平方根) (是数据中的列数)。如果当前表中的任何列完全为零,则切断该列并根据剩余的非零列计算距离(没关系,例如,SPSS 在计算距离时就是这样做的)。卡方距离实际上是加权欧几里德距离。2 x pp2 x p

@ttnphns 提供了一个很好的答案。

做好聚类通常需要非常认真地考虑数据,所以让我们做一些。在我看来,您的数据最基本的方面是它们是组合的。

另一方面,您主要关心的似乎是您有很多绿色产品的 0,并且特别想知道您是否可以仅转换绿色值以使其与其他值更相似。但是因为这些是组成数据,所以您不能独立于其他计数来考虑一组计数。此外,您似乎真正感兴趣的是客户购买不同颜色产品的概率,但由于许多人没有购买任何绿色产品,您担心无法估计这些概率。解决这个问题的一种方法是使用一种有点贝叶斯的方法,在这种方法中,我们将客户的估计比例推向平均比例,偏移量受他们与平均值的距离以及您需要多少数据来估计他们的真实比例的影响。概率。

下面我使用您的示例数据集来说明(在 R 中)处理您的情况的一种方法。我读入数据并将它们转换为按行比例,然后按列计算平均比例。我将平均值添加回每个计数以获取调整后的计数和新的按行比例。这将每个客户的估计比例推向每种产品的平均比例。如果您想要更强的推动力,您可以使用多种方式(例如,15*mean.props)来代替。

d = read.table(text="id  red    blue    green
...
c3  4   8   1", header=TRUE)
tab = as.table(as.matrix(d[,-1]))
rownames(tab) = paste0("c", 0:3)
tab
#    red blue green
# c0  12    5     0
# c1   3    4     0
# c2   2   21     0
# c3   4    8     1
props = prop.table(tab, 1)
props
#           red       blue      green
# c0 0.70588235 0.29411765 0.00000000
# c1 0.42857143 0.57142857 0.00000000
# c2 0.08695652 0.91304348 0.00000000
# c3 0.30769231 0.61538462 0.07692308
mean.props = apply(props, 2, FUN=function(x){ weighted.mean(x, rowSums(tab)) })
mean.props
#        red       blue      green 
# 0.35000000 0.63333333 0.01666667 
adj.counts = sweep(tab, 2, mean.props, FUN="+");  adj.counts
#            red        blue       green
# c0 12.35000000  5.63333333  0.01666667
# c1  3.35000000  4.63333333  0.01666667
# c2  2.35000000 21.63333333  0.01666667
# c3  4.35000000  8.63333333  1.01666667
adj.props = prop.table(adj.counts, 1);  adj.props
#             red         blue        green
# c0 0.6861111111 0.3129629630 0.0009259259
# c1 0.4187500000 0.5791666667 0.0020833333
# c2 0.0979166667 0.9013888889 0.0006944444
# c3 0.3107142857 0.6166666667 0.0726190476

这有几个结果。其中之一是您现在对购买绿色产品的潜在概率有非零估计,即使客户实际上还没有任何购买任何绿色产品的记录。另一个结果是你现在有一些连续的值,而原始比例更加离散;也就是说,可能的估计值的限制较少,因此像平方欧几里得距离这样的距离度量现在可能更有意义。

我们可以可视化数据以查看发生了什么。因为这些是成分数据,我们实际上只有两条信息,我们可以将它们绘制在一个散点图中。对于红色和蓝色类别中的大多数信息,将它们用作轴是有意义的。您可以看到调整后的比例(红色数字)与原来的位置略有不同。

windows()
  plot(props[,1], props[,2], pch=as.character(0:3),
       xlab="Proportion Red", ylab="Proportion Blue", xlim=c(0,1), ylim=c(0,1))
  points(adj.props[,1], adj.props[,2], pch=as.character(0:3), col="red")

在此处输入图像描述

在这一点上,你有数据,很多人会从标准化它们开始。同样,因为这些是组成数据,我会在不进行任何标准化的情况下运行聚类分析——这些值已经相称,标准化会破坏一些关系信息。事实上,从情节上看,我认为您在这里确实只有一维信息。(至少在样本数据集中;您的真实数据集可能会有所不同。)除非从商业角度来看,您认为将有很大可能购买绿色产品的人识别为不同的客户群很重要,否则我将提取第一个主成分的分数(占该数据集中方差的 99.5%)并对其进行聚类。

pc.a.props = prcomp(adj.props[,1:2], center=T, scale=T)
cumsum(pc.a.props$sdev^2)/sum(pc.a.props$sdev^2)
# [1] 0.9946557 1.000000
pc.a.props$x
#           PC1         PC2
# c0 -1.7398975 -0.03897251
# c1 -0.1853614 -0.04803648
# c2  1.6882400 -0.06707115
# c3  0.2370189  0.15408015
library(mclust)
mc = Mclust(pc.a.props$x[,1])
summary(mc)
# ----------------------------------------------------
# Gaussian finite mixture model fitted by EM algorithm 
# ----------------------------------------------------
# 
# Mclust E (univariate, equal variance) model with 3 components:
# 
#  log.likelihood n df       BIC       ICL
#       -2.228357 4  6 -12.77448 -12.77448
# 
# Clustering table:
# 1 2 3 
# 1 2 1