Skip to main content
 首页 » 编程设计

python之Sklearn 凝聚聚类自定义亲和性

2025年05月04日13落叶

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

我的数据看起来像这样

>> 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' 

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

如有任何帮助,我们将不胜感激

请您参考如下方法:

'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)