kmeans算法python实现

from random import randint


class Cluster(object):
    def _init_(self):
        #簇的所有特征向量
        self._fcs = []
        # 簇的中心点
        self._center = None

    def set_center(self, new_center):
        """
        设置中心点
        :param new_center:
        :return:
        """
        self._center = new_center

    def get_center(self):
        return self._center

    def add_fc(self, fc):
        """
        簇中添加特征向量的场景
        :param fc:
        :return:
        """
        self._fcs.append(fc)

    def updata_center(self):
        """
        根据簇中所有特征向量更新中心点
        :return:
        """

        #特征向量中特征的数量
        feature_num = len(self._fcs[0])
        # 特征向量的数量
        fc_num = len(self._fcs)
        for i in range(feature_num):
            #开始计算当前特征在所有特征向量上的总和
            current_sum = 0
            for fc in self._fcs:
                current_sum += fc[i]
            #将中心点对应特征的值更新为均值
            self._center[i] = current_sum / fc_num

    def distance(self, fc):
        """
        计算簇的中心点到特征向量fc的距离
        :param fc:
        :return:
        """
        length = len(fc)
        distance = 0
        for i in range(length):
            distance += (self._center[i] - fc[i])**2
        return sqrt(distance)

class KMeans(object):
    def _init_(self, k):
        self._k = k
        self._clusters = [Cluster() for i  in range(self._k)]

    def _select_k_indexs(self, total_num):
        """
        选择k个索引,选出来的索引用于从数据集中随机挑选k个簇的中心点
        :param total_num:
        :return:
        """

        k_indexes = []
        while len(k_indexes) < self._k:
            #生成一个随机的索引
            index = randint(0, total_num - 1)
            #如果当前的索引不在索引list里,把它加到k_indexes中
            if index not in k_indexes:
                k_indexes.append(index)
        return  k_indexes

    def _init_clusters(self, dataset):
        """
        c初始化kmeans的k个c簇
        :param dataset:
        :return:
        """
        k_indexes = self._select_k_indexs(self._k, len(dataset))
        for i in range(self._k):
            self._clusters[i].set_center(dataset[k_indexes[i]])

    def train(self, dataset, iter_times):
        """

        :param dataset:
        :param iter_times: 迭代次数
        :return:
        """
        #先初始化所有的k个簇
        self._init_clusters(dataset)
        #特征向量的个数
        fc_num = len(dataset)
        #进行iter_times次迭代
        for i  in range(iter_times):
            #开始循环数据集中的数据
            for j in range(fc_num):
                #当前的特征向量
                current_fc = dataset[j]
                #记录当前特征向量的归属cluster的索引为0,最小距离为和第一个簇的距离
                cluster_index = 0
                min_dist = self._clusters[0].distance(current_fc)
                #计算当前特征向量和所有簇的距离
                for k in range(1, self._k):
                    current_dist = self._clusters[k].distance(current_fc)
                    #这里使用了打擂台算法,求的最小距离,节省了求出所有距离之后进行排序的过程
                    if current_dist < min_dist:
                        cluster_index = k
                        min_dist = current_dist
                #所有k个距离计算完之后把当前的特征向量加入到指定的簇中
                self._clusters[cluster_index].add_fc(current_fc)
            #数据集中所有数据都迭代完之后开始更新每个簇的中心点
            for cluster in self._clusters:
                cluster.updata_center()

        def get_clusters(self):
            return  self._clusters

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haimianjie2012

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值