Sklearn 凝聚聚类自定义亲和性

Posted

技术标签:

【中文标题】Sklearn 凝聚聚类自定义亲和性【英文标题】:Sklearn Agglomerative Clustering Custom Affinity 【发布时间】:2019-05-19 19:40:54 【问题描述】:

我正在尝试使用具有自定义距离度量(即亲和力)的凝聚聚类,因为我想通过序列相似性而不是像欧几里德距离这样没有意义的东西来聚类整数序列。

我的数据看起来像这样

>> dat.values 

array([[860, 261, 240, ..., 300, 241,   1],
   [860, 840, 860, ..., 860, 240,   1],
   [260, 860, 260, ..., 260, 220,   1],
   ...,
   [260, 260, 260, ..., 260, 260,   1],
   [260, 860, 260, ..., 840, 860,   1],
   [280, 240, 241, ..., 240, 260,   1]]) 

我创建了以下相似度函数

def sim(x, y): 
    return np.sum(np.equal(np.array(x), np.array(y)))/len(x)

所以我只用 numpy 返回两个序列中匹配值的百分比,然后进行以下调用

cluster = AgglomerativeClustering(n_clusters=5, affinity=sim, linkage='average')
cluster.fit(dat.values)

但我收到一个错误提示

TypeError: sim() missing 1 required positional argument: 'y'

我不确定为什么会出现此错误;我认为该函数会将成对的行聚集在一起,以便传递每个必需的参数。

对此的任何帮助将不胜感激

【问题讨论】:

【参考方案1】:

常见的做法是放入affinity='precomputed并拟合距离矩阵(参见此处的示例:https://gist.github.com/codehacken/8b9316e025beeabb082dda4d0654a6fa)

UPD 在 sklearn.hierarchical.py (https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/cluster/hierarchical.py#L460) 中,您可以看到您的自定义亲和度必须仅获取 X(而不是 y)作为输入。输入应该是linkage_tree。所以,你需要重写你的 sim() 函数。

但我认为第一种方式更方便。

【讨论】:

【参考方案2】:

'affinity' 作为可调用对象需要单个输入 X(这是您的特征或观察矩阵),然后调用其中所有点(样本)之间的距离。

所以你需要修改你的方法为:

# Your method to calculate distance between two samples
def sim(x, y): 
    return np.sum(np.equal(np.array(x), np.array(y)))/len(x)


# Method to calculate distances between all sample pairs
from sklearn.metrics import pairwise_distances
def sim_affinity(X):
    return pairwise_distances(X, metric=sim)

cluster = AgglomerativeClustering(n_clusters=5, affinity=sim_affinity, linkage='average')
cluster.fit(X)

或者您可以按照@avchauzov 的建议使用affinity='precomputed'。为此,您必须在fit() 中为您的观察传递预先计算的距离矩阵。比如:

cluster = AgglomerativeClustering(n_clusters=5, affinity='precomputed', linkage='average')
distance_matrix = sim_affinity(X)
cluster.fit(distance_matrix)

注意:您已指定相似度来代替距离。因此,请确保您了解集群在此处的工作方式。或者也许调整您的相似性函数以返回距离。比如:

def sim(x, y): 
    # Subtracted from 1.0 (highest similarity), so now it represents distance
    return 1.0 - np.sum(np.equal(np.array(x), np.array(y)))/len(x)

【讨论】:

这个注释非常有帮助,谢谢!我以为我可以通过相似性,但我看到我需要从 1.0 中减去以获得我想要的东西加上代码示例是有意义的并且有效。干杯

以上是关于Sklearn 凝聚聚类自定义亲和性的主要内容,如果未能解决你的问题,请参考以下文章

sklearn 具有距离链接准则的凝聚聚类

如何根据集群之间的距离阈值来决定集群的数量,以便使用 sklearn 进行凝聚聚类?

使用 DTW 距离矩阵的凝聚聚类

Scikit-learn 凝聚聚类连接矩阵

聚类算法:凝聚层次聚类

类自定义排序的 C++ 向量