K-Means 手写实现


手写K-Means的python实现

K-Means 算法流程图

kmeans

python代码实现

kmeans_tool.py

# -*- coding:utf-8 -*-
'''
    description: kmeans tool kit
    time: 2020/12/10
'''

import random
import math


class Cluster(object):

    def __init__(self, samples):
        if len(samples) == 0:
            raise Exception("sample is empty")
        
        self.n_dim = samples[0].n_dim
        self.samples = samples
        # calculate center sample
        self.center = self.calculate_center()

    def __repr__(self):
        '''
            print the cluser
            __repr__ print the cluster info
        '''
        return str(self.samples)
    
    def update(self, samples):
        '''
            update the samples in this clusers
        '''
        old_center = self.center
        self.samples = samples
        self.center = self.calculate_center()
        return get_distance(old_center, self.center)


    def calculate_center(self):
        '''
            calculate the center of the cluser
        '''
        coords = [sample.coords for sample in self.samples]
        return Sample([ sum(item)/len(item) for item in zip(*coords)])


class Sample(object):

    def __init__(self, coords):
        self.coords = coords
        self.n_dim = len(coords)
    
    def __repr__(self):
        return str(self.coords)
    

def get_distance(a, b):
    '''
        calculate the distance of two samples
    '''
    sum = 0.0
    for i in range(a.n_dim):
        sum += pow((a.coords[i] - b.coords[i]), 2)
    return math.sqrt(sum)
    

def generate_sample(n_dim, low, high):
    '''
        generate a sample
    '''
    return Sample([random.uniform(low, high) for _ in range(n_dim)])

kmean_process.py

# -*- coding:utf-8 -*-

'''
    description: kmeans progress
    time: 2020/12/10
'''

import random
from kmeans_tool import Cluster, Sample, get_distance, generate_sample
import matplotlib.pyplot as plt

def kmeans(samples, k, cut_off):
    # random select k samples as the init cluster
    init_samples = random.sample(samples, k)
    # init the cluser with center
    clusters = [Cluster([sample]) for sample in init_samples]
    loop = 0
    while True:
        # use to save the samples
        cluser_samples = [[] for _ in range(k)]
        loop += 1
        for sample in samples:
            # calculate the min distance with cluster center
            min_distance = float('inf')
            cluster_index = 0
            for i in range(len(clusters)):
                distance = get_distance(sample, clusters[i].center)
                if distance < min_distance:
                    min_distance = distance
                    cluster_index = i
            cluser_samples[cluster_index].append(sample)
        
        #calculate the biggest_shift
        biggest_shift = 0.0
        for i in range(k):
            shift = clusters[i].update(cluser_samples[i])
            biggest_shift = max(biggest_shift, shift)
        
        if biggest_shift < cut_off:
            print("{} iteration ".format(loop))
            break
    return clusters



def main():
    """
        main progress
    """


    # number of samples
    n_samples = 1000

    # dimension
    n_feat = 2


    lower = 0
    upper = 200

    # number of clusters
    n_cluster = 5

    # generate the samples
    samples = [generate_sample(n_feat, lower, upper) for _ in range(n_samples)]

    # threshold
    cutoff = 0.2

    # execute kmeans
    clusters = kmeans(samples, n_cluster, cutoff)

    # print out enumerate generate (index, item) for iteration
    for i, c in enumerate(clusters):
        for sample in c.samples:
            print('cluster--{},samples--{}'.format(i, sample))

if __name__ == '__main__':
    main()
对于MNIST手写数字集,k-means聚类算法可以用来对数字进行分组。K-means算法是一种无监督学习算法,它将数据样本划分为K个不同的簇,每个簇都有一个代表性的中心点,即聚类中心。在使用k-means算法对MNIST数据集进行聚类时,你可以按照以下步骤进行操作: 1. 读取MNIST数据集:首先,你需要读取MNIST手写数字集的图像数据。这些图像通常是28x28像素的灰度图像。 2. 特征提取:将每个图像转换为特征向量。这可以通过将图像的像素值展平为一维向量来实现。例如,将28x28的图像转换为包含784个特征的向量。 3. 数据预处理:对特征向量进行预处理,例如归一化或标准化。这有助于将不同特征的值放缩到相似的范围内,避免某些特征对聚类结果产生过大的影响。 4. 选择K值:确定需要聚类的簇数K。一种常用的方法是通过肘部法则来选择K值,即通过绘制簇内平方和与K值的关系图,并选择拐点处的K值。 5. 初始化聚类中心:随机选择K个数据点作为初始的聚类中心。 6. 迭代优化:通过交替的分配数据点到最近的聚类中心和更新聚类中心的方式,迭代优化聚类结果。这可以使用欧氏距离或其他相似度度量来判断数据点与聚类中心的距离。 7. 收敛判断:当聚类中心不再变化或达到预定的迭代次数时,算法收敛,停止迭代。 8. 聚类结果分析:根据聚类的结果,将每个样本分配到对应的簇中。你可以通过可视化每个簇中的样本来观察聚类效果,并对每个簇进行数字识别。 需要注意的是,k-means算法对于MNIST数据集的聚类可能会受到数字形状和大小的变化影响,因此结果可能不太稳定。此外,由于MNIST数据集是有标签的,你还可以使用有监督学习方法进行数字分类任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值