首页 > 试题广场 >

聚类

[编程题]聚类
  • 热度指数:578 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 128M,其他语言256M
  • 算法知识视频讲解
铁柱在研究一个区域的小黄车使用分布。他得到了服务器上最近10000个用户的二维位置,现在他想把这些用户聚成K(K<10) 组,每组有一个中心C_i。他想评价聚类算法的好坏,把每个数据点到中心的l1距离作为总距离。即
D = sum_j || X_j - C( X_j ) ||_1
其中C(X_j)代表X_j所属的中心。现在他想找一个尽可能好的聚类算法,使得这个总距离尽可能小。要求你输出K个中心的位置(顺序不限)
比如如果有5个数据点
1 1
1 2
1 4
3 4
3 5
给定2个中心1 2, 3 4的话
总距离就是1+0+2+0+1 = 4

输入描述:
本题总是会有10000个数据点
第一个输入为K,表示需要聚类的个数,
之后10000行,为每个点的x和y
例如:
2
2-5001行 每行都是 0 0
5002-10001行 每行都是 2 2


输出描述:
依次输出每个类中心
示例1

输入

2
2-5001行 每行都是 0 0
5002-10001行 每行都是 2 2

输出

0.00000 0.00000
2.00000 2.00000
题目的预期输出41909.991042应该是损失值,即样本点到对应簇心的距离
实现代码如下
dim = 2      #二维
n_data = 10000    #10000个数据点
iter_times = 10

def l2_dist(x1, x2):          #欧氏距离
    sum = 0
    for i in range(len(x1)):
        sum += (x1[i] - x2[i]) ** 2
    return sum ** (1/2)

#计算中心
def centroid(l):
    res = [0] * dim
    for i in range(dim):
        for a in l:
            res[i] += data[a][i]
    for i in range(dim):
        res[i] /= len(l)
    return res

def CalCentroids(l):
    res = []
    for i in l:
        res.append(centroid(i))
    return res

K = int(input())

data = []
for i in range(n_data):
    data += [list(map(float, input().strip().split()))]

#随机分配
clusters= []
for i in range(K):
    clusters.append([])
for i in range(n_data):
    pos = i % K
    clusters[pos].append(i)

#迭代
for _ in range(iter_times):
    sum_dist = 0
    centroids = CalCentroids(clusters)
    for i in range(K):
        clusters[i] = []
    for i in range(n_data):
        best_c = 0
        best_d = 9999999999
        for j in range(K):
            d = l2_dist(centroids[j], data[i])
            if d < best_d:
                best_c = j
                best_d = d
        sum_dist += best_d
        if len(clusters[best_c]) == 0:
            clusters[best_c] = []
        clusters[best_c].append(i)

print(sum_dist)

# for i in range(K):
#     print(f'{clusters[i][0]} {clusters[i][1]}')
实现出来输出为35380

发表于 2022-03-28 19:16:28 回复(0)