Python 聚类算法的编程结构是什么

Python 聚类算法的编程结构是什么,python,data-structures,cluster-analysis,hierarchical-clustering,Python,Data Structures,Cluster Analysis,Hierarchical Clustering,我正在尝试实现以下(分裂)聚类算法(以下是该算法的简短形式,完整描述可用): 从样本x开始,i=1,…,n被视为n个数据点的单个簇,并为所有点对定义了相异矩阵D。修复一个阈值T,用于决定是否拆分群集 首先确定所有数据点对之间的距离,并选择它们之间距离最大(Dmax)的一对 比较Dmax和T。如果Dmax>T,则使用所选对作为两个新簇中的第一个元素,将单个簇一分为二。剩下的n-2个数据点被放入两个新集群中的一个。如果D(x_i,x_l)=2: 实际值=构造新记录(距离,结果[i]) 最大动作=最大

我正在尝试实现以下(分裂)聚类算法(以下是该算法的简短形式,完整描述可用):

从样本x开始,i=1,…,n被视为n个数据点的单个簇,并为所有点对定义了相异矩阵D。修复一个阈值T,用于决定是否拆分群集

  • 首先确定所有数据点对之间的距离,并选择它们之间距离最大(Dmax)的一对

  • 比较Dmax和T。如果Dmax>T,则使用所选对作为两个新簇中的第一个元素,将单个簇一分为二。剩下的n-2个数据点被放入两个新集群中的一个。如果D(x_i,x_l)
  • 在第二阶段,在两个新簇中的一个簇中找到值D(x_i,x_j),以在簇中找到它们之间具有最大距离Dmax的对。如果Dmax
  • 输出是群集数据记录的层次结构。我恳请您就如何实现聚类算法提出建议

    编辑1:我附加了定义距离(相关系数)的Python函数和在数据矩阵中查找最大距离的函数

    # Read data from GitHub
    import pandas as pd
    df = pd.read_csv('https://raw.githubusercontent.com/nico/collectiveintelligence-book/master/blogdata.txt', sep = '\t', index_col = 0)
    data = df.values.tolist()
    data = data[1:10]
    
    # Define correlation coefficient as distance of choice
    def pearson(v1, v2):
      # Simple sums
      sum1 = sum(v1)
      sum2 = sum(v2)
      # Sums of the squares
      sum1Sq = sum([pow(v, 2) for v in v1])
      sum2Sq = sum([pow(v, 2) for v in v2]) 
      # Sum of the products
      pSum=sum([v1[i] * v2[i] for i in range(len(v1))])
      # Calculate r (Pearson score)
      num = pSum - (sum1 * sum2 / len(v1))
      den = sqrt((sum1Sq - pow(sum1,2) / len(v1)) * (sum2Sq - pow(sum2, 2) / len(v1)))
      if den == 0: return 0
      return num / den
    
    
    # Find largest distance
    dist={}
    max_dist = pearson(data[0], data[0])
    # Loop over upper triangle of data matrix
    for i in range(len(data)):
      for j in range(i + 1, len(data)):
         # Compute distance for each pair
         dist_curr = pearson(data[i], data[j])
         # Store distance in dict
         dist[(i, j)] = dist_curr
         # Store max distance
         if dist_curr > max_dist:
           max_dist = dist_curr
    
    编辑2:下面粘贴的是来自Dschoni答案的函数

    # Euclidean distance
    def euclidean(x,y):
      x = numpy.array(x)
      y = numpy.array(y) 
      return numpy.sqrt(numpy.sum((x-y)**2))
    
    # Create matrix
    def dist_mat(data):
      dist = {}
      for i in range(len(data)):
        for j in range(i + 1, len(data)):
          dist[(i, j)] = euclidean(data[i], data[j])
      return dist
    
    
    # Returns i & k for max distance
    def my_max(dict):
        return max(dict)
    
    # Sort function
    list1 = []
    list2 = []
    def sort (rcd, i, k):
      list1.append(i)
      list2.append(k)
      for j in range(len(rcd)):
        if (euclidean(rcd[j], rcd[i]) < euclidean(rcd[j], rcd[k])):
          list1.append(j)
        else:
          list2.append(j)
    
    结果如下:

    [24]、[17]、[4]、[7]、[40]、[13]、[14]、[15]、[26、27、38]、[3、16、, 39], [25], [42], [18, 20, 45], [43], [1, 2, 11, 46], [12, 37, 41], [5], [21], [22], [10, 23, 28, 29], [6, 34, 48], [0, 8, 33, 36, 44], [31]、[32]、[19]、[30]、[35]、[9,47]]

    一些数据点仍然聚集在一起。我通过向
    排序
    函数中的
    实际
    字典添加少量数据噪声来解决此问题:

    # Add small random noise
    for key in actual:    
      actual[key] +=  np.random.normal(0, 0.005)
    

    你知道如何正确地解决这个问题吗?

    欧几里德距离的正确工作示例:

    import numpy as np
    #For random number generation
    
    
    def create_distance_list(l):
    '''Create a distance list for every
    unique tuple of pairs'''
        dist={}
        for i in range(len(l)):
            for k in range(i+1,len(l)):
                dist[(i,k)]=abs(l[i]-l[k])
        return dist
    
    def maximum(distance_dict):
    '''Returns the key of the maximum value if unique
    or a random key with the maximum value.'''
        maximum = max(distance_dict.values())
        max_key = [key for key, value in distance_dict.items() if value == maximum]
        if len(max_key)>1:
            random_key = np.random.random_integers(0,len(max_key)-1)
            return (max_key[random_key],)
        else:
            return max_key
    
    def construct_new_dict(distance_dict,index_list):
    '''Helper function to create a distance map for a subset
    of data points.'''
        new={}
        for i in range(len(index_list)):
            for k in range(i+1,len(index_list)):
                m = index_list[i]
                n = index_list[k]
                new[(m,n)]=distance_dict[(m,n)]
        return new
    
    def sort(distance_dict,idl,threshold=4):
        result=[idl]
        i=0
        try:
            while True:
                if len(result[i])>=2:
                actual=construct_new_dict(dist,result[i]) 
                    act_max=maximum(actual)
                    if distance_dict[act_max[0]]>threshold:
                        j = act_max[0][0]
                        k = act_max[0][1]
                        result[i].remove(j)
                        result[i].remove(k)
                        l1=[j]
                        l2=[k]
                        for iterr in range(len(result[i])):
                            s = result[i][iterr]
                            if s>j:
                                c1=(j,s)
                            else:
                                c1=(s,j)
                            if s>k:
                                c2=(k,s)
                            else: 
                                c2=(s,k)
                            if actual[c1]<actual[c2]:
                                l1.append(s)
                            else:
                                l2.append(s)
                        result.remove(result[i])
        #What to do if distance is equal?
                        l1.sort()
                        l2.sort()
                        result.append(l1)
                        result.append(l2)
                    else:
                        i+=1
                else:
                    i+=1
        except:
            return result
    
    
    #This is the dataset
    a = [1,2,2.5,5]
    #Giving each entry a unique ID
    idl=range(len(a))
    dist = create_distance_list(a)
    print sort(dist,idl)  
    
    将numpy导入为np
    #用于生成随机数
    def创建距离列表(l):
    ''为每个项目创建一个距离列表
    对“”的唯一元组
    dist={}
    对于范围内的i(len(l)):
    对于范围(i+1,len(l))中的k:
    dist[(i,k)]=abs(l[i]-l[k])
    返回区
    def最大值(距离):
    ''如果唯一,则返回最大值的键
    或具有最大值的随机键。“”
    最大值=最大值(距离值()
    max\u key=[键对键,距离中的值\u dict.items(),如果值==最大值]
    如果len(最大键)>1:
    random\u key=np.random.random\u整数(0,len(max\u key)-1)
    返回(最大密钥[随机密钥],)
    其他:
    返回max_键
    定义构造新目录(距离目录、索引列表):
    ''帮助函数为子集创建距离贴图
    数据点的数量
    新={}
    对于范围内的i(len(索引列表)):
    对于范围内的k(i+1,len(索引列表)):
    m=索引列表[i]
    n=索引列表[k]
    新的[(m,n)]=距离
    还新
    def排序(距离、idl、阈值=4):
    结果=[idl]
    i=0
    尝试:
    尽管如此:
    如果len(结果[i])>=2:
    实际值=构造新记录(距离,结果[i])
    最大动作=最大(实际)
    如果距离[act\U max[0]]>阈值:
    j=最大值[0][0]
    k=最大值[0][1]
    结果[i]。删除(j)
    结果[i]。删除(k)
    l1=[j]
    l2=[k]
    对于范围内的iterr(len(结果[i]):
    s=结果[i][iterr]
    如果s>j:
    c1=(j,s)
    其他:
    c1=(s,j)
    如果s>k:
    c2=(k,s)
    其他:
    c2=(s,k)
    如果实际[c1]
    一些数据点仍然聚集在一起。我用计算机解决这个问题
    向排序中的实际字典添加少量数据噪声
    功能

    如果Dmax>T,则将单个集群一分为二

    您的描述不一定会创建
    n
    集群。
    如果集群有两条距离小于
    T
    的记录,

    它们将聚集在一起(我是否遗漏了什么?

    我不完全确定如何回答所问的问题。如果您指的是数据结构,那么您的算法的哪些部分需要结构,以及对数据结构的要求是什么?如果您只想重复拆分元素集合,而不关心数据最终是如何表示的,那么数组或链表可能会起作用。或者,你可以考虑某种形式的树(像二进制搜索树)。我只需要重复地分割数据点。我想一个数组就足够了。你知道从哪里开始/如何开始吗?你有一种编程语言吗?你有一个算法,所以你只需要把算法的步骤转换成一些代码。我想从编写函数开始。我用Python编程,但不管哪种语言都可以。我只需要两个人的帮助。三,。我附加了我最初尝试的代码。我在上面粘贴了适当的函数。你能帮我处理排序函数中的递归吗?你需要按层次顺序排列的簇吗?或者仅仅是集群?结果是将输入中数据列表的索引聚集在一起。如果您需要数据值,只需将索引列表中的每个值设置为输入列表的值。您能告诉我这是否是您要查找的吗?是的,这正是我要查找的。谢谢
    import numpy as np
    #For random number generation
    
    
    def create_distance_list(l):
    '''Create a distance list for every
    unique tuple of pairs'''
        dist={}
        for i in range(len(l)):
            for k in range(i+1,len(l)):
                dist[(i,k)]=abs(l[i]-l[k])
        return dist
    
    def maximum(distance_dict):
    '''Returns the key of the maximum value if unique
    or a random key with the maximum value.'''
        maximum = max(distance_dict.values())
        max_key = [key for key, value in distance_dict.items() if value == maximum]
        if len(max_key)>1:
            random_key = np.random.random_integers(0,len(max_key)-1)
            return (max_key[random_key],)
        else:
            return max_key
    
    def construct_new_dict(distance_dict,index_list):
    '''Helper function to create a distance map for a subset
    of data points.'''
        new={}
        for i in range(len(index_list)):
            for k in range(i+1,len(index_list)):
                m = index_list[i]
                n = index_list[k]
                new[(m,n)]=distance_dict[(m,n)]
        return new
    
    def sort(distance_dict,idl,threshold=4):
        result=[idl]
        i=0
        try:
            while True:
                if len(result[i])>=2:
                actual=construct_new_dict(dist,result[i]) 
                    act_max=maximum(actual)
                    if distance_dict[act_max[0]]>threshold:
                        j = act_max[0][0]
                        k = act_max[0][1]
                        result[i].remove(j)
                        result[i].remove(k)
                        l1=[j]
                        l2=[k]
                        for iterr in range(len(result[i])):
                            s = result[i][iterr]
                            if s>j:
                                c1=(j,s)
                            else:
                                c1=(s,j)
                            if s>k:
                                c2=(k,s)
                            else: 
                                c2=(s,k)
                            if actual[c1]<actual[c2]:
                                l1.append(s)
                            else:
                                l2.append(s)
                        result.remove(result[i])
        #What to do if distance is equal?
                        l1.sort()
                        l2.sort()
                        result.append(l1)
                        result.append(l2)
                    else:
                        i+=1
                else:
                    i+=1
        except:
            return result
    
    
    #This is the dataset
    a = [1,2,2.5,5]
    #Giving each entry a unique ID
    idl=range(len(a))
    dist = create_distance_list(a)
    print sort(dist,idl)