《统计学习方法》 第十四章 聚类方法

news2025/4/26 17:01:59

聚类方法

1.聚类是针对给定的样本,依据它们属性的相似度或距离,将其归并到若干个“类”或“簇”的数据分析问题。一个类是样本的一个子集。直观上,相似的样本聚集在同类,不相似的样本分散在不同类。

2.距离或相似度度量在聚类中起着重要作用。

常用的距离度量有闵可夫斯基距离,包括欧氏距离曼哈顿距离、切比雪夫距离、、以及马哈拉诺比斯距离。常用的相似度度量有相关系数、夹角余弦。
用距离度量相似度时,距离越小表示样本越相似;用相关系数时,相关系数越大表示样本越相似。

3.类是样本的子集,比如有如下基本定义:
G G G表示类或簇,用 x i x_i xi, x j x_j xj;等表示类中的样本,用 d i j d_{ij} dij表示样本 x i x_i xi与样本 x j x_j xj之间的距离。如果对任意的 x i , x j ∈ G x _ { i } , x _ { j } \in G xi,xjG,有 d i j ≤ T d _ { i j } \leq T dijT
则称 G G G为一个类或簇。

描述类的特征的指标有中心、直径、散布矩阵、协方差矩阵。

4.聚类过程中用到类与类之间的距离也称为连接类与类之间的距离包括最短距离、最长距离、中心距离、平均距离。

5.层次聚类假设类别之间存在层次结构,将样本聚到层次化的类中层次聚类又有聚合或自下而上、分裂或自上而下两种方法。

聚合聚类开始将每个样本各自分到一个类;之后将相距最近的两类合并,建立一个新的类,重复此操作直到满足停止条件;得到层次化的类别。分裂聚类开始将所有样本分到一个类;之后将已有类中相距最远的样本分到两个新的类,重复此操作直到满足停止条件;得到层次化的类别。

聚合聚类需要预先确定下面三个要素:

(1)距离或相似度;
(2)合并规则;
(3)停止条件。

根据这些概念的不同组合,就可以得到不同的聚类方法。

6. k k k均值聚类是常用的聚类算法,有以下特点。基于划分的聚类方法;类别数k事先指定;以欧氏距离平方表示样本之间的距离或相似度,以中心或样本的均值表示类别;以样本和其所属类的中心之间的距离的总和为优化的目标函数;得到的类别是平坦的、非层次化的;算法是迭代算法,不能保证得到全局最优。

k k k均值聚类算法,首先选择k个类的中心,将样本分到与中心最近的类中,得到一个聚类结果;然后计算每个类的样本的均值,作为类的新的中心;重复以上步骤,直到收敛为止。


层次聚类

  1. 聚合(自下而上):聚合法开始将每个样本各自分裂到一个类,之后将相距最近的两类合并,建立一个新的类,重复次操作知道满足停止条件,得到层次化的类别。

  2. 分裂(自上而下): 分裂法开始将所有样本分到一个类,之后将已有类中相距最远的样本分到两个新的类,重复此操作直到满足停止条件,得到层次化的类别。


k均值聚类

k均值聚类是基于中心的聚类方法,通过迭代,将样本分到k个类中,使得每个样本与其所属类的中心或均值最近,得到k个平坦的,非层次化的类别,构成对空间的划分


代码实现

import math
import random
import numpy as np
from sklearn import datasets,cluster
import matplotlib.pyplot as plt

# 定义聚类数的节点

class ClusterNode:
    def __init__(self, vec, left=None, right=None, distance=-1, id=None, count=1):
        """
        :param vec: 保存两个数据聚类后形成新的中心
        :param left: 左节点
        :param right:  右节点
        :param distance: 两个节点的距离
        :param id: 用来标记哪些节点是计算过的
        :param count: 这个节点的叶子节点个数
        """
        self.vec = vec
        self.left = left
        self.right = right
        self.distance = distance
        self.id = id
        self.count = count
        
def euler_distance(point1: np.ndarray, point2: list) -> float:
    """
    计算两点之间的欧拉距离,支持多维
    """
    distance = 0.0
    for a, b in zip(point1, point2):
        distance += math.pow(a - b, 2)
    return math.sqrt(distance)
# 层次聚类(聚合法)

class Hierarchical:
    def __init__(self, k):
        self.k = k
        self.labels = None
        
    def fit(self, x):
        nodes = [ClusterNode(vec=v, id=i) for i, v in enumerate(x)]
        distances = {}
        point_num, feature_num = x.shape
        self.labels = [-1] * point_num
        currentclustid = -1
        while(len(nodes)) > self.k:
            min_dist = math.inf
            nodes_len = len(nodes)
            closest_part = None
            for i in range(nodes_len - 1):
                for j in range(i+1, nodes_len):
                    d_key = (nodes[i].id, nodes[j].id)
                    if d_key not in distances:
                        distances[d_key] = euler_distance(nodes[i].vec, nodes[j].vec)
                    d = distances[d_key]
                    if d < min_dist:
                        min_dist = d
                        closest_part = (i, j)
                        
            part1, part2 = closest_part
            node1, node2 = nodes[part1], nodes[part2]
            new_vec = [ (node1.vec[i] * node1.count + node2.vec[i] * node2.count ) / (node1.count + node2.count)
                        for i in range(feature_num)]
            new_node = ClusterNode(vec=new_vec,
                                   left=node1,
                                   right=node2,
                                   distance=min_dist,
                                   id=currentclustid,
                                   count=node1.count + node2.count)
            currentclustid -= 1
            del nodes[part2], nodes[part1]
            nodes.append(new_node)
            
        self.nodes = nodes
        self.calc_label()
        
    def calc_label(self):
        """
        调取聚类的结果
        """
        for i, node in enumerate(self.nodes):
            # 将节点的所有叶子节点都分类
            self.leaf_traversal(node, i)

    def leaf_traversal(self, node: ClusterNode, label):
        """
        递归遍历叶子节点
        """
        if node.left == None and node.right == None:
            self.labels[node.id] = label
        if node.left:
            self.leaf_traversal(node.left, label)
        if node.right:
            self.leaf_traversal(node.right, label)

iris = datasets.load_iris()
my = Hierarchical(3)
my.fit(data)
labels = np.array(my.labels)
# visualize result

cat1 = data[np.where(labels==0)]
cat2 = data[np.where(labels==1)]
cat3 = data[np.where(labels==2)]

plt.scatter(cat1[:,0], cat1[:,1], color='green')
plt.scatter(cat2[:,0], cat2[:,1], color='red')
plt.scatter(cat3[:,0], cat3[:,1], color='blue')
plt.title('Hierarchical clustering with k=3')
plt.xlim(4, 8)
plt.ylim(1, 5)
plt.show()

在这里插入图片描述


# kmeans

class MyKmeans:
    def __init__(self, k, n=20):
        self.k = k
        self.n = n
        
    def fit(self, x, centers=None):
        # 第一步,随机选择 K 个点, 或者指定
        if centers is None:
            idx = np.random.randint(low=0, high=len(x), size=self.k)
            centers = x[idx]
        #print(centers)
        
        inters = 0
        while inters < self.n:
            #print(inters)
            #print(centers)
            points_set = {key: [] for key in range(self.k)}

            # 第二步,遍历所有点 P,将 P 放入最近的聚类中心的集合中
            for p in x:
                nearest_index = np.argmin(np.sum((centers - p) ** 2, axis=1) ** 0.5)
                points_set[nearest_index].append(p)

            # 第三步,遍历每一个点集,计算新的聚类中心
            for i_k in range(self.k):
                centers[i_k] = sum(points_set[i_k])/len(points_set[i_k])
                
            inters += 1

        
            
        return points_set, centers

from sklearn.cluster import KMeans

loss = []

for i in range(1, 10):
    kmeans = KMeans(n_clusters=i, max_iter=100).fit(data)
    loss.append(kmeans.inertia_ / len(data) / 3)

plt.title('K with loss')
plt.plot(range(1, 10), loss)
plt.show()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/40401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

压力传感器

压力传感器 压力传感器是最常用的一种传感器&#xff0c;其应用范围有各种工业互通环境&#xff0c;涉及航空&#xff0c;航天&#xff0c;军工&#xff0c;石化&#xff0c;电力等。按照不同的测试&#xff0c;压力类型可分表压传感器&#xff0c;差压传感器&#xff0c;绝压…

现代密码学导论-19-基于伪随机函数的CPA安全

目录 3.5.2 基于伪随机函数的CPA安全 基于伪随机函数的加密示意图 CONSTRUCTION 3.28 构造基于伪随机函数的CPA安全的加密方案 THEOREM 3.29 方案3.28是CPA安全的 THEOREM 3.29 的证明 3.5.2 基于伪随机函数的CPA安全 基于伪随机函数的加密示意图 CONSTRUCTION 3.28 构造…

历史中的密码

角色 发送者、接收者和窃听者 当某个人向另一个人发送信息时&#xff0c;发出信息的人称为发送者&#xff0c;而收到信息的人称为接收者&#xff0c;被发送的信息有时也统称为消息&#xff08; message )。 窃听者 Eve 并不一定是人类&#xff0c;有可能是安装在通信设备上的某…

【JVM】jvm中的方法区简介

jvm中的方法区简介一、JVM体系结构二、方法区是什么&#xff1f;三、方法区能干什么&#xff1f;四、方法区总结一、JVM体系结构 二、方法区是什么&#xff1f; 本文所讲内容在上图中处于运行时数据区内的左侧部分&#xff0c;即 Method Area&#xff08;方法区&#xff09;&a…

REHL7.6静默安装Oracle19C

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&#x1f61…

【轨迹跟踪】基于matlab拓展卡尔曼滤波时序四旋翼无人机状态跟踪【含Matlab源码 2246期】

⛄一、拓展卡尔曼滤波时序四旋翼无人机状态跟踪 卡尔曼滤波算法为获得最优估计和最小误差方差&#xff0c;将从目标模型中得到的测量值一步步递推&#xff0c;实时获取新时刻的状态估计值。 假设目标状态方程和观测方程分别为&#xff1a; 其中&#xff0c;k为离散时间&…

投入产出公开数据集:世界投入产出表(1995-2014)、全国投入产出表(1990-2018)、分省市投入产出表(1997-2017)

一、数据介绍 数据名称&#xff1a;世界、全国、各省-投入产出表 数据年份&#xff1a;世界投入产出表(1995-2014)、全国投入产出表(1990-2018)、分省市投入产出表(1997-2017) 数据来源&#xff1a;WIOD、自计算 ① 世界投入产出表&#xff08;1995-2014&#xff09; downlo…

用JSX来写Vue3,瞬间找到React 的感觉

Ⅰ. vue3 的 JSX 写法 对于熟悉react 的小伙伴, 可以通过 jsx 来 做 vue3喜欢 jsx 写法做 vue&#xff0c;代码结构更加美观&#xff0c;让我们一起来踩坑 &#x1f447; 文章目录Ⅰ. vue3 的 JSX 写法Ⅱ. JSX 安装和配置1. 通过 webpack 构建的2. 通过 vite 构建的Ⅳ. JSX 的…

Yocto buildhistory介绍

Yocto buildhistory介绍 在yocto中会频繁的编译修改镜像&#xff0c;当多人多次修改镜像的时候会导致镜像难以维护&#xff0c;我们希望能有一个类似git一样的工具能够显示每次编译的差异性修改&#xff0c;这样当我想要回退到某个日期的某个镜像时能够清晰的知道镜像内部的具…

Dockerfile文件详解

组成部分 说明 基础镜像信息 使用 FROM 关键字指定基础镜像信息&#xff0c;必须是 Dockerfile 文件的第1条指令。 维护者信息 使用 MAINTAINER 关键字指定&#xff0c;可以使用 Dockerfile 文件创建者的姓名或者电子邮件作为维护者信息。 镜像操作指令 每执行一条镜像操…

vue3+Element-plus el-select 下拉选择 多选增加全选封装组件

一、效果图&#xff08;含适用于条件查询组件中使用&#xff09; 二、参数配置 1、代码示例&#xff1a; <t-selectplaceholder"请选择工序"v-model"selectVlaue":optionSource"state.stepList"valueKey"label"change"selec…

部署SpringBoot+Vue3 项目实战,打造企业级在线办公系统

文章目录一、安装docker二、安装2.1. 安装mysql2.2. 安装MongoDB2.3. 安装Redis程序2.4. 安装RabbitMQ2.5. 在云主机上面开放端口三、部署后端项目3.1. 下载JDK镜像3.2. 部署工作流项目3.3. 部署emos-api项目四、在Docker中部署前端项目4.1. 修改前端代码4.2. 打包VUE项目4.3. …

【Hack The Box】linux练习-- time

HTB 学习笔记 【Hack The Box】linux练习-- time &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月24日&#x1f334; &#x1f36d…

Android~Compose脚手架和Toast

系列文章目录 Android~Compose初探Android~Compose之自定义ViewAndroid~Compose相关概念总结Android~Compose脚手架和ToastAndroid~Compose路由Navigation和传参 文章目录系列文章目录目标脚手架基于Snackbar自定义Toast实现效果目标 熟悉Compose中脚手架使用自定义Toast样式…

人工智能轨道交通行业周刊-第24期(2022.11.21-11.27)

追风赶月莫停留&#xff0c;平芜尽处是春山。 --《田歆华夏说》 本期关键词&#xff1a;BIM应用、地铁控制中心、车辆检修智能化、模型轻量化、隧道通风 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交…

【树莓派不吃灰】Linux篇⑥ 正规表示法与文件格式化处理(核心概念)

目录1. 什么是正则表示法2. 基础正规表示法&#xff08;grep、sed&#xff09;3. 延伸正规表示法4. 文件的格式化与相关处理&#xff08;printf、awk&#xff09;5. 重点回顾❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-11…

FPGA实现视频拼接,纯逻辑资源搭建,提供4套工程源码和技术支持

目录1.本方案的实用价值2.总体设计方案3.视频拼接方案算法4.工程1&#xff1a;单路视频输出5.工程2&#xff1a;2路视频拼接输出6.工程3&#xff1a;3路视频拼接输出7.工程4&#xff1a;4路视频拼接输出8.上板调试验证9.福利&#xff1a;工程源码获取1.本方案的实用价值 FPGA实…

【软件测试】测试与开发一对欢喜冤家......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 大伙普遍的看法&…

28.开机默认启动系统-ubuntu和win10

在win10下安装了Ubuntu20.04系统&#xff0c;默认情况下&#xff0c;启动的是Ubuntu系统。 要将默认启动系统设置成win10&#xff0c;方法如下&#xff1a; 1、进入ubuntu系统&#xff0c;按住CtrlAltT键&#xff0c;打开终端。 2、输入命令&#xff1a; sudo gedit /etc/d…

TCP常见问题

一、TCP连接的保活机制 在一段时间内&#xff0c;如果TCP连接两方都没有数据交互&#xff0c;TCP的保活机制**&#xff08;TCP keepalive&#xff09;**会起作用&#xff0c;每隔一个时间段会发送一个探测报文&#xff0c;如果连着好几个探测报文都没有得到相应&#xff0c;则…