作业代码(交作业用)

K-means

使用的校内数据集

楼主彩笔
#by ql_Da-qiong
import dm2022exp #老师的数据集
import numpy as np
import matplotlib.pyplot as plot
from numpy import random
import math
from sklearn.model_selection import train_test_split


X, y = dm2022exp.load_ex4_data()
# print(X)
# print(y)


class KMeans(object):

    def __init__(self, num_cluster: int, max_iter: int = 1000,
                 tol: float = 1e-4):
        self.num_cluster = num_cluster
        self.max_iter = max_iter
        self.tol = tol
        """
        参数解释:
            - num_cluster : 需要将数据分成几个簇,一簇表示一类
            - max_iter    : 最大迭代次数,kmeans算法当本次计算的候选点和上次
                            候选点的距离小于某个值之后才会停止,如果始终没有收
                            敛就会一直算下去,这个值表示最大的迭代次数,当大于
                            这个迭代次数即使没有收敛也要停下来,如果实验当中
                            你没有实现这个参数可能会造成超时的情况
            - tol         : 在参数 `max_iter` 中提到的本次候选点和上次候选点
                            之间的距离,这个距离可以用高维空间中两个点之间的距
			    离表示
        """

    def fit(self, X: np.ndarray) -> np.ndarray:
        # init pre list
        pre_list = [-1]*len(X)
        centre_list = []
        high = len(X)
        i = np.random.randint(low=0, high=high, size=self.num_cluster)
        for t in i:
            centre_list.append(X[t])
        print(centre_list)
        return self.k_means(X, 0, pre_list, centre_list)

        """
        参数解释:
            - X : 训练数据,数据维度为(n, m),其中 n 表述数据个数,m 表示属性个数
        返回值:
            返回值是一个 np.ndarray 对象,内容是每个属性的属于的那一簇,从0开始标记
            比如一共5个属性,分成三个簇你的返回值可以是
            [0, 0, 1, 2, 2] 或者 [1, 1, 2, 0, 0] 或者 [2, 2, 1, 0, 0]
            你只需要用某个值表示某一类即可,具体用哪个数字表示无所谓,你只需要
            保证同一类别的数据用的是同一个数字即可
        """
        pass

    def distance(self, a, b):
        return (a[0] - b[0])**2 + (a[1] - b[1])**2

    def k_means(self, X, depth, pre_list, centre_list):
        print("iter: ",depth + 1,"times")
        if depth >= self.max_iter:
            return np.array(pre_list)

        # classify
        for i in range(len(X)):
            min_dis = 99999
            for j in range(self.num_cluster):
                dis = self.distance(X[i], centre_list[j])
                if dis <= min_dis:
                    min_dis = dis
                    pre_list[i] = j

        # print(pre_list)
        # re_cal centre
        centre_list_t = []
        for i in range(self.num_cluster):
            sum_x = 0
            sum_y = 0

            t = []
            for j in pre_list:
                if i == j:
                    t.append(True)
                else:
                    t.append(False)

            # print("***************************")
            # print(pre_list)
            # print(sum(t))
            # print(X[t])
            len_ = sum(t)
            if len_ > 0:
                # print(X[t])
                sum_x = sum(X[t][i][0] for i in range(len(X[t])))
                sum_y = sum(X[t][i][1] for i in range(len(X[t])))
                # print(sum_x)
                # print(sum_y)
                list_ = [sum_x / len_, sum_y / len_]
                # print("cen:" , list_)
                centre_list_t.append(np.array(list_))
            else:
                centre_list_t.append(centre_list[i])

        flag = True
        for i in range(self.num_cluster):
            if self.distance(centre_list[i], centre_list_t[i]) >= self.tol:
                flag = False
        if flag:
            return np.array(pre_list)


        return(self.k_means(X, depth + 1, pre_list, centre_list_t))


m = KMeans(num_cluster = 8, max_iter = 1000,tol = 1e-4)
pre = m.fit(X)
dm2022exp.show_exp4_data(X, pre)

结果可视化
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值