(自用)机器学习K-MEANS

在各处收集的大佬的文章,自用学习,非原创,在下面也有标注,感谢各位大佬的讲解。

1. K-means聚类定义: 

K-means算法是用来解决著名的聚类问题的最简单的非监督学习算法之一,是很典型的基于距离的聚类算法。该算法采用距离作为相似性的评价指标。即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。

原理参考这篇,讲的很清楚的博主:

【海量数据挖掘/数据分析】之 K-Means 算法(K-Means算法、K-Means 中心值计算、K-Means 距离计算公式、K-Means 算法迭代步骤、K-Means算法实例)_kmeans聚类算法-优快云博客icon-default.png?t=N7T8https://blog.youkuaiyun.com/u014361280/article/details/131547468

2. K-means的局限性

 当聚类的大小、密度、形状不同时,K-means 聚类的结果不理想
 数据集包含离群点时,K-means 聚类结果不理想
 两个类距离较近时,聚类结果不合理

3. 改进的K-means算法


上面介绍的k-means 算法是一种非常简单并且使用广泛的聚类算法,但是

  • k 值需要预先给定,很多情况下 k 值的估计很困难。
  • K-Means 算法对初始选取的聚类中心点很敏感,不同的中心点聚类结果有很大的不同。也就是说,有可能陷入局部最优解。
  • 对离群点敏感,聚类结果易产生误差。
  • 相似性度量的函数不同也会对聚类结果产生影响。

接下来针对 k-means 的缺陷,总结对k-means的改进。从初始中心点的选取、离群点的检测与去除、相似性度量等几个方面进行概括、比较。

3.1 距离和相似性度量

传统的 k-means 算法使用欧几里得距离来度量相似度。
改进的措施是:

        采用了欧式距离、平方欧式距离、曼哈顿距离、余弦距离、谷本距离分别作为相似度度量对文本数据进行处理,实验结果显示余弦距离、谷本距离者在文本聚类中的表现更优。不同的测度距离作为相似性度量对聚类结果会产生不同的影响,对于不同类型的数据也应采用不同的距离函数作为相似度度量。
        针对 k-means 算法不能求解非线性流形聚类的缺陷,用空间密度相似性度量来代替欧几里得距离,使 k-means算法能够适应数据集的分布。同一簇中的数据点应位于高密度区域,不同簇中的数据点应该用低密度区域分隔开来。所以需要压缩高密度区域的距离,放大低密度区域的距离。
针对比例数据,提出用 Aitchison 距离度量来对比例数据进行聚类。使用 Aitchison 距离、欧几里德对数距离、余弦距离、Kullback 距离、Matisuita 距离进行了对比实验,聚类结果显示 Aitchison 距离度量最适合所有,因为较高的轮廓值,聚类更合适。对于图像比例数据聚类,使用 Aitchison 距离作为初始化步骤可以提供适用于比例数据的更好的混合结果。


3.2 初始聚类中心的选取
       

初始聚类中心的选取对 k-means 算法聚类结果的影响很大,不同的初始聚类中心,可能会产生不同的聚类结果。也可以说,k-means算法是一种贪心算法,容易陷入局部最优解。解决办法如下:

      类簇中心都处在局部密度比较大的位置,且距离具有比它更大的局部密度的对象相对较远的思想。运用此思想可以确定最佳初始聚类中心及数据集的最佳类簇数目。在这个思想的基础上,为了避免密度对截断距离的依赖性,重新定义了计算样本局部密度 ρ i 的方法,计算样本点到具有比它更高的局部密度数据对象的最近距离 δ i (当样本点 x i 是数据集中具有最大局部密度的样本点时,δ i 定义为 x i 和距离他最远的样本点之间的欧氏距离)。根据 ρ i 和 δ i 构造决策图,运用统计学中残差分析的方法,选取残差绝对值大于阈值的异常点,即为聚类中心。在二维以及高维数据集上的实验结果均验证了该算法的有效性。但是不足之处在于这个算法适用于比较集中的数据集,稀疏的数据集结果并不理想。
       采用减法聚类的算法确定初始聚类中心。首先是计算每个样本点的山峰函数值,选取山峰函数值最大的点作为聚类中心。选取下一个聚类中心时要消除已经确定的聚类中心的影响,就修改山峰函数,减去上一个确定的聚类中心的比例高斯函数,如此反复,直到得到足够多的聚类中心。这个方法的缺点在于对于离群点、异常值抗干扰能力比较弱,且需要设置的参数较多(一般需要 3 个)。
        采用了四分位数的概念来确定初始聚类中心。首先采用特征选择的方法选取数据有意义的属性。然后将将属性的值按照顺序排列,以分成两类为例,将数据集的上四分位点和下四分位点作为初始聚类中心,计算所有样本点到到这两个聚类中心的距离,进行分类;接下来更新聚类中心,将每类所有样本点的均值作为新的聚类中心,直到类簇不再发生变化。这个方法不足之处是当数据集比较大时,花费时间会比较长。
        采用最大 - 最小准则算法初步确定初始聚类中心,然后通过FLANN(快速最近邻搜索库)将聚类中心偏移到尽可能地靠近实际的聚类中心。最大 - 最小准则算法是首先随机选取一个点作为第一个聚类中心,选取距离这个点最远的点作为第二个聚类中心,然后计算每个点到这两个聚类中心的距离,选取较小的距离加入到集合 V 中,在集合 V 中选取距离最远的点作为下一个聚类中心,依次类推,直到最大最小距离不大于θ•D 1,2 (D 1,2 为第一个和第二个聚类中心的距离)。 FLANN 是一个在高维空间中快速搜索k 个最近邻居的库。使用 FLANN 找到聚类中心的 k 近邻,计算中心点即为新的聚类中心。


3.3离群点的检测


        K-means 算法对于离群点敏感,对聚类结果产生很大的影响,因此离群点的检测与删除极为重要。解决的方法有:

       基于密度的方法是一种流行的异常值检测方法。 它计算每个点的局部离群因子(LOF)。 一个点的 LOF 是基于该点附近区域的密度和它的邻居的局部密度的比值。LOF 方法依赖于用户提供的最小数量点,用于确定邻居的大小。
       建立了一个基于本地距离的离群因子(LDOF)来测量分散的数据集对象的离群程度。LDOF 使用一个对象到它的邻居的相对位置,以确定物体偏离其邻近区域的程度。为了方便实际应用中的参数设置,在离群值检测方法中使用了一种 top-n 技术,其中只有具有最高值的对象才被视为离群值。与传统的方法(如前 n 和顶 n)相比,方法是在分散的数据中检测出离群值。
       通过添加上限范数和一种有效的迭代重加权算法,来减小离群点的影响。离群点的检测发生在每次聚类中心迭代时,每个样本点到聚类中心的距离大于给定的参数 ε,便会被去除。并且重新给样本分配权重,低错误率的样本具有更高的权重。这个方面的缺陷在于参数 ε 需要人为的设置与调整,不同的ε值导致的聚类结果准确率不同。
        提出了k-means-sharp 算法,通过从点到质心距离的分布得到的全局阈值自动检测离群点。离群点检测过程和聚类过程同时完成。假设 k-means的数据呈高斯分布,离群点检测发生在每次聚类中心更新时,计算每个样本点到聚类中心的距离,如果距离大于 3σ,则为离群点,其中σ=1.4826MADe, MADe 为每个点到中值点的距离组成的所有数据的中值点。因此,每次更新聚类中心时,就会去除一部分离群点。


3.4 k-means算法的其他改进


      最近几年出现了遗传算法、粒子群算法、萤火虫算法、蚁群算法等与传统的 kmeans 算法相结合的改进算法,这几类算法的共同点是具有一定的全局优化能力,理论上可以在一定的时间内找到最优解或近似最优解。通常是使用这些算法来寻找 k-means 算法的初始聚类中心。

        将k-means和遗传算法结合的 k-means 算法优于传统的 k-means 算法。遗传 k-means 算法就是把每个聚类中心坐标当成染色体基因。聚类中心个数就是染色体长度,对若干相异染色体进行初始化操作并将其当成一个种群进行遗传操作,最终获得适应度最大染色体,而最优聚类中心坐标就是解析出的各中心点坐标。
       将粒子群算法与 k-means算法结合,多子群多于多子群粒子群伪均值(PK-means)聚类算法,理论分析和实验表明,该算法不但可以防止空类出现,而且同时还具有非常好的全局收敛性和局部寻优能力,并且在孤立点问题的处理上也具有很好的效果。
基于萤火虫优化的加权 K-means 算法。该算法在提升聚类性能的同时,有效增强了算法的收敛速度。在实验阶段,通过 UCI 数据集中的几组数据对该算法进行了聚类实验及有效性测试,实验结果充分表明了该算法的有效性及优越性。可见,将k-means算法与其他算法相结合,可以弥补 k-means 算法的不足,获得更好的聚类效果。

4. 总结


       K-means 的发展已经经历了很长的一段时间,它所具有的独特优势使得其被广大研究者不断地优化和使用。本文对 k-means 进行简单介绍。同时对 k-means 的研究和改进还应注意以下几点:

(1)随着互联网技术的发展,数据量呈现出一种指数级增长。如何高效地对这些海量数据进行处理和分析已成为当前研究热点。传统的 k-means 算法难以有效处理大的数据集。所以将并行计算和 k-means 算法结合,并不断地对其加以改进和优化,是处理海量数据的有效途径。
(2)k-means 聚类算法的改进有许多依然需要用户输入参数,传统的 k-means 算法的k 值的确定研究不多。所以参数的自确定是一个不断需要发展研究的问题。
(3)从文中可以看出,现在存在着各种各样的数据类型,文本、图像、混合型数据等等,现有的多是处理二维数据,对高维数据处理的研究不多,需要对 k-means 算法进行扩展,以得到一个能够适应大多数类型数据类型的 k-means 算法模型。

以上内容来自:机器学习(九)-k-means算法及优化和Python_k均值聚类算法优化python-优快云博客

 5. 手撕:


# coding=utf-8 
from numpy import *

# 加载数据 
def loadDataSet(fileName):  # 解析文件,按tab分割字段,得到一个浮点数字类型的矩阵
    dataMat = []              # 文件的最后一个字段是类别标签
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = map(float, curLine)    # 将每个元素转成float类型
        dataMat.append(fltLine)
    return dataMat

# 计算欧几里得距离 
def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA - vecB, 2))) # 求两个向量之间的距离

# 构建聚簇中心,取k个(此例中为4)随机质心 
def randCent(dataSet, k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((k,n)))   # 每个质心有n个坐标值,总共要k个质心
    for j in range(n):
        minJ = min(dataSet[:,j])
        maxJ = max(dataSet[:,j])
        rangeJ = float(maxJ - minJ)
        centroids[:,j] = minJ + rangeJ * random.rand(k, 1)
    return centroids

# k-means 聚类算法 
def kMeans(dataSet, k, distMeans =distEclud, createCent = randCent):
    m = shape(dataSet)[0]
    clusterAssment = mat(zeros((m,2)))    # 用于存放该样本属于哪类及质心距离
    # clusterAssment第一列存放该数据所属的中心点,第二列是该数据到中心点的距离
    centroids = createCent(dataSet, k)
    clusterChanged = True   # 用来判断聚类是否已经收敛
    while clusterChanged:
        clusterChanged = False;
        for i in range(m):  # 把每一个数据点划分到离它最近的中心点
            minDist = inf; minIndex = -1;
            for j in range(k):
                distJI = distMeans(centroids[j,:], dataSet[i,:])
                if distJI < minDist:
                    minDist = distJI; minIndex = j  # 如果第i个数据点到第j个中心点更近,则将i归属为j
            if clusterAssment[i,0] != minIndex: clusterChanged = True;  # 如果分配发生变化,则需要继续迭代
            clusterAssment[i,:] = minIndex,minDist**2   # 并将第i个数据点的分配情况存入字典
        print centroids
        for cent in range(k):   # 重新计算中心点
            ptsInClust = dataSet[nonzero(clusterAssment[:,0].A == cent)[0]]   # 去第一列等于cent的所有列
            centroids[cent,:] = mean(ptsInClust, axis = 0)  # 算出这些数据的中心点
    return centroids, clusterAssment

# --------------------测试----------------------------------------------------
# 用测试数据及测试kmeans算法 
datMat = mat(loadDataSet('testSet.txt')) 
myCentroids,clustAssing = kMeans(datMat,4) 


 

[编辑本段]Turbo C2.0    介绍      Turbo C2.0不仅是一个快捷、高效的编译程序,同时还有一个易学、易用的集成开发环境。使用Turbo C2.0无需独立地编辑、编译和连接程序,就能建立并运行C语言程序。因为这些功能都组合在Turbo 2.0的集成开发环境内,并且可以通过一个简单的主屏幕使用这些功能。    基本配置要求   Turbo C 2.0可运行于IBM-PC系列微机,包括XT,AT及IBM 兼容机。此时要求DOS2.0或更高版本支持,并至少需要448K的RAM,可在任何彩、单色80列监视器上运行。支持数学协处理器芯片,也可进行浮点仿真,这将加快程序的执行。 [编辑本段]Turbo C 2.0的主要文件的简单介绍   INSTALL.EXE 安装程序文件   TC.EXE 集成编译   TCINST.EXE 集成开发环境的配置设置程序   TCHELP.TCH 帮助文件   THELP.COM 读取TCHELP.TCH的驻留程序README 关于Turbo C的信息文件   TCCONFIG.EXE 配置文件转换程序MAKE.EXE   项目管理工具TCC.EXE   命令行编译TLINK.EXE   Turbo C系列连接器TLIB.EXE   Turbo C系列库管理工具C0?.OBJ 不   同模式启动代码C?.LIB   不同模式运行库GRAPHICS.LIB   图形库EMU.LIB   8087仿真库FP87.LIB 8087库   *.H Turbo C头文件   *.BGI 不同显示器图形驱动程序   *.C Turbo C例行程序(源文件)   其中:上面的?分别为:T Tiny(微型模式)S Small(小模式)C Compact(紧凑模式)M Medium(中型模式)L Large(大模式)H Huge(巨大模式)    Turbo C++ 3.0   “Turbo C++ 3.0”软件是Borland公司在1992年推出的强大的——C语言程序设计与C++面向对象程序设计 的集成开发工具。它只需要修改一个设置选项,就能够在同一个IDE集成开发环境下设计和编译以标准 C 和 C++ 语法设计的程序文件。 [编辑本段]C 语言   C语言起始于1968年发表的CPL语言,它的许多重要思想都来自于Martin Richards在1969年研制的BCPL语言,以及以BCPL语言为基础的与Ken Thompson在1970年研制的B语言。Ken Thompson用B语言写了第一个UNIX操作系统。M.M.Ritchie1972年在B语言的基础上研制了C语言,并用C语言写成了第一个在PDP-11计算机上研制的UNIX操作系统。1977年出现了独立于极其的C语言编译文本《看移植C语言编译程序》,从而大大简化了把C语言编译程序移植到新环境中所做的工作,这本身也就使UNIX的日益广泛使用,C语言也迅速得到推广。   1983年美国国家标准化协会(ANSI)根据C语言问世以来的各种版本,对C语言的发展和扩充制定了新的标准,成为ANSI C。1987年ANSI又公布了新标准————87ANSI C。   目前在微型计算机上使用的有Microsoft C、Quick C、Turbo C等多种版本。这些不同的C语言版本,基本部分是相同的,但是在有关规定上有略有差异。   C 语言发展如此迅速, 而且成为最受欢迎的语言之一, 主要因为它具有强大的功能。许多著名的系统软件, 如DBASE Ⅲ PLUS、DBASE Ⅳ 都是由C 语言编写的。用C 语言加上一些汇编语言子程序, 就更能显示C 语言的优势了,象PC- DOS ,WORDSTAR等就是用这种方法编写的。归纳起来C 语言具有下列特点:   1. C是中级语言   它把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以象汇编语言一样对位、字节和地址进行操作, 而这三者是计算机最基本的工作单元。   2. C是结构式语言   结构式语言的显著特点是代码及数据的分隔化, 即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰, 便于使用、维护以及调试。C 语言是以函数形式提供给用户的, 这些函数可方便的调用, 并具有多种循环、条件语句控制程序流向, 从而使程序完全结构化。   3. C语言功能齐全   C 语言具有各种各样的数据类型, 并引入了指针概念, 可使程序效率更高。另外C 语言也具有强大的图形功能, 支持多种显示器和驱动器。而且计算功能、逻辑判断功能也比较强大, 可以实现决策目的。   4. C语言适用范围大   C 语言还有一个突出的优点就是适合于多种操作系统, 如DOS、UNIX,也适用于多种机型。   C语言的优点很多,但是也存在一些缺点,如运算优先级太多,运算能力方面不像其它高级语言那样强,语法定义不严格等。但是这些都不能阻止C语言成为一门广受欢迎的计算机编程语言
Turbo C2.0 介绍   Turbo C2.0不仅是一个快捷、高效的编译程序,同时还有一个易学、易用的集成开发环境。使用Turbo C2.0无需独立地编辑、编译和连接程序,就能建立并运行C语言程序。因为这些功能都组合在Turbo 2.0的集成开发环境内,并且可以通过一个简单的主屏幕使用这些功能。 基本配置要求   Turbo C 2.0可运行于IBM-PC系列微机,包括XT,AT及IBM 兼容机。此时要求DOS2.0或更高版本支持,并至少需要448K的RAM,可在任何彩、单色80列监视器上运行。支持数学协处理器芯片,也可进行浮点仿真,这将加快程序的执行。 主要文件的简单介绍   INSTALL.EXE 安装程序文件   TC.EXE 集成编译   TCINST.EXE 集成开发环境的配置设置程序   TCHELP.TCH 帮助文件   THELP.COM 读取TCHELP.TCH的驻留程序README 关于Turbo C的信息文件   TCCONFIG.EXE 配置文件转换程序MAKE.EXE   项目管理工具TCC.EXE   命令行编译TLINK.EXE   Turbo C系列连接器TLIB.EXE   Turbo C系列库管理工具C0?.OBJ 不   同模式启动代码C?.LIB   不同模式运行库GRAPHICS.LIB   图形库EMU.LIB   8087仿真库FP87.LIB 8087库   *.H Turbo C头文件   *.BGI 不同显示器图形驱动程序   *.C Turbo C例行程序(源文件)   其中:上面的?分别为:T Tiny(微型模式)S Small(小模式)C Compact(紧凑模式)M Medium(中型模式)L Large(大模式)H Huge(巨大模式)
### 回答1: 在 TURBO C 2.0 中,您可以使用 biosdisk() 函数来格式化软盘。 下面是一段代码示例: ``` #include <stdio.h> #include <dos.h> int main() { // 定义扇区的大小 unsigned int sector_size[3] = {512, 512, 1024}; // 定义填充字节 unsigned char fill_char[3] = {0xF6, 0xF6, 0x48}; // 格式化磁道 700 的前三个扇区 for (int i = 0; i < 3; i++) { int result = biosdisk(2, 0, 70, 0, i + 1, 1, sector_size[i], fill_char[i]); if (result != 0) { printf("格式化扇区 %d 失败,返回码: %d\n", i + 1, result); } } return 0; } ``` 请注意,在使用 biosdisk() 函数之前,需要包含 dos.h 头文件。 希望这能帮到您! ### 回答2使用TURBO C 2.0语言,可以通过以下代码格式化软盘的70磁道0面,并分别格式化3个扇区,大小分别为512字节、512字节和1024字节。其中,前两个扇区使用F6填充,第三个扇区使用48填充。 ```c #include<stdlib.h> #include<stdio.h> #include<dos.h> void formatFloppyDisk(){ union REGS regs; regs.h.ah = 0x0;// To format a floppy disk, we set AH=0 regs.h.dl = 0;// Drive number (0=A, 1=B, etc.) regs.x.cx = 0;// Track number to format regs.h.dh = 0;// Head number regs.h.al = 0;// Sector size (0=default, 1=512 bytes, 2=1024 bytes, 3=2048 bytes etc.) int FILL_BYTE = 0;// The byte value to fill the sectors with during formatting int NUM_SECTORS = 3;// Number of sectors to format // To format 70th track 0th head regs.x.ax = 0x1301; // 0x13 = Reset disk system, 01H = Reset only specified drive int86(0x13, &regs, &regs); // BIOS interrupt to reset disk system for (int i=0; i<NUM_SECTORS; i++){ regs.x.ax = 0x3101; // 0x31 = Write Format, 01H = Format only current track regs.x.bx = 0x0001; // 0x00 = Drive A:, 01H = Head 1, 0 = Generate ID Field depending on the disk in the drive 1 = Keep the ID Field all zeros regs.x.cx = 0x0170; // Track number=70(0-79 range) regs.h.dh = 0x00; // Head number=0 or 1 regs.h.al = 0x02; // Control byte=always zero regs.x.dx = i+1; // Sector number starting from 1 regs.x.si = 0x0000; // segment and offset of read/write buffer regs.x.di = 0x0000; // segment and offset of result if(i == 2){ FILL_BYTE = 0x48; // Fill the third sector with 48 regs.x.ax = 0x3102; // 0x31 = Write Format, 02H = Format sequential tracks immediately following the one being formatted }else{ FILL_BYTE = 0xF6; // Fill the first two sectors with F6 } regs.h.ah = FILL_BYTE; // Fill the sector with specified byte int86(0x13, &regs, &regs); // BIOS interrupt to format the specified sector } } int main(){ formatFloppyDisk(); return 0; } ``` 上述代码使用了INT 0x13,即BIOS中断服务例程,来执行软盘格式化操作。通过设置寄存器的不同参数,可以指定要格式化的磁道、面、扇区大小和填充字节。在这个例子中,我们格式化了软盘70磁道0面的3个扇区,前两个扇区使用F6填充,第三个扇区使用48填充。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值