Python实现Mean Shift算法

article/2025/11/6 16:32:13

       声明:代码的运行环境为Python3。Python3与Python2在一些细节上会有所不同,希望广大读者注意。本博客以代码为主,代码中会有详细的注释。相关文章将会发布在我的个人博客专栏《Python从入门到深度学习》,欢迎大家关注~


       在K-Means算法中,聚类的类别个数需要提前指定,对于类别个数未知的数据集,K-Means算法和K-Means++算法将很难对其进行求解,所以需要一些能够处理未知类别个数的算法来处理此类问题。Mean Shift算法,又称作均值漂移算法,它跟K-Means算法一样,都是基于聚类中心的聚类算法,不同的是,它不需要提前指定聚类中心的个数,聚类中心是通过在给定区域中样本的均值来确定的,通过不断更新聚类中心,直至聚类中心不再改变为止。

一、Mean Shift向量与核函数

1、Mean Shift向量

       对于给定的n维空间中的m个样本点,对于其中的一个样本X,其Mean Shift的向量为:

       其中,指的是一个半径为h的高维球区域,定义为:

2、核函数

       通过上述方式求出的Mean Shift向量时存在问题的,即在区域内每一个对样本X的贡献是一样的,然而实际上,每一个样本对样本X的贡献是不一样的,我们可以通过核函数对每一个样本的贡献进行度量。

       核函数的定义如下:

       设Z是输入空间,H是特征空间,如果存在一个Z到H的映射:使得所有,函数满足条件:,则称为核函数,为映射函数。

       我们在Mean Shift算法中使用的是高斯核函数,这也是最常用的核函数之一,高斯核函数的表达式为:

       其中,h为带宽,当带宽一定时,样本点之间的距离越近,核函数的值越大;当样本点距离一定时,带宽越大,核函数的值越小。

       下面我们使用Python代码实现高斯核函数:

import numpy as np
import mathdef gs_kernel(dist, h):'''高斯核函数:param dist: 欧氏距离:param h: 带宽:return: 返回高斯核函数的值'''m = np.shape(dist)[0]  # 样本个数one = 1 / (h * math.sqrt(2 * math.pi))two = np.mat(np.zeros((m, 1)))for i in range(m):two[i, 0] = (-0.5 * dist[i] * dist[i].T) / (h * h)two[i, 0] = np.exp(two[i, 0])gs_val = one * tworeturn gs_val

二、Mean Shift原理

       在Mean Shift中通过迭代的方式找到最终的聚类中心,即对每一个样本点计算其漂移均值,以计算出来的漂移均值点作为新的起始点重复上述步骤,直到满足终止条件,得到的最终的漂移均值点即为最终的聚类中心。

       Mean Shift算法实现过程如下:

def mean_shift(points, h=2, MIN_DISTANCE=0.000001):'''训练Mean Shift模型:param points: 特征点:param h: 带宽:param MIN_DISTANCE: 最小误差:return: 返回特征点、均值漂移点、类别'''mean_shift_points = np.mat(points)max_min_dist = 1iteration = 0  # 迭代的次数m = np.shape(mean_shift_points)[0]  # 样本的个数need_shift = [True] * m  # 标记是否需要漂移# 计算均值漂移向量while max_min_dist > MIN_DISTANCE:max_min_dist = 0iteration += 1print("iteration : " + str(iteration))for i in range(0, m):if not need_shift[i]:  # 判断每一个样本点是否需要计算偏移均值continuepoint_new = mean_shift_points[i]point_new_start = point_newpoint_new  = shift_point(point_new, points, h)  # 对样本点进行漂移计算dist = distince(point_new, point_new_start)  # 计算该点与漂移后的点之间的距离if dist > max_min_dist:max_min_dist = distif dist < MIN_DISTANCE:need_shift[i] = Falsemean_shift_points[i] = point_new# 计算最终的类别lb = lb_points(mean_shift_points)  # 计算所属的类别return np.mat(points), mean_shift_points, lb

       其中,shift_point()方法目的在于计算漂移量,lb_points()方法的目的在于计算最终所属分类,distance()方法用于计算欧氏距离,三个方法的实现过程分别如下:

(1)shift_point()方法

def shift_point(point, points, h):'''计算漂移向量:param point: 需要计算的点:param points: 所有的样本点:param h: 带宽:return: 返回漂移后的点'''points = np.mat(points)m = np.shape(points)[0]  # 样本的个数# 计算距离point_dist = np.mat(np.zeros((m, 1)))for i in range(m):point_dist[i, 0] = distince(point, points[i])# 计算高斯核函数point_weights = gs_kernel(point_dist, h)# 计算分母all_sum = 0.0for i in range(m):all_sum += point_weights[i, 0]# 计算均值偏移point_shifted = point_weights.T * points / all_sumreturn point_shifted

(2)lb_points()

def lb_points(mean_shift_points):'''计算所属类别:param mean_shift_points: 漂移向量:return: 返回所属的类别'''lb_list = []m, n = np.shape(mean_shift_points)index = 0index_dict = {}for i in range(m):item = []for j in range(n):item.append(str(("%5.2f" % mean_shift_points[i, j])))item_1 = "_".join(item)if item_1 not in index_dict:index_dict[item_1] = indexindex += 1for i in range(m):item = []for j in range(n):item.append(str(("%5.2f" % mean_shift_points[i, j])))item_1 = "_".join(item)lb_list.append(index_dict[item_1])return lb_list

(3)distince()方法

def distince(pointA, pointB):'''计算欧氏距离:param pointA: A点坐标:param pointB: B点坐标:return: 返回得到的欧氏距离'''return math.sqrt((pointA - pointB) * (pointA - pointB).T)

三、Mean Shift算法举例

1、数据集:数据集含有两个特征,如下图所示:

2、加载数据集

       我们此处使用如下方法加载数据集,也可使用其他的方式进行加载,此处可以参考我的另外一篇文章《Python两种方式加载文件内容》。加载文件内容代码如下:

def load_data(path, feature_num=2):'''导入数据:param path: 路径:param feature_num: 特行总数:return: 返回数据特征'''f = open(path)data = []for line in f.readlines():lines = line.strip().split("\t")data_tmp = []if len(lines) != feature_num:  # 判断特征的个数是否正确,把不符合特征数的数据去除continuefor i in range(feature_num):data_tmp.append(float(lines[i]))data.append(data_tmp)f.close()return data

3、保存聚类结果

       通过Mean Shift聚类后,我们使用一下方法进行聚类结果的保存

def save_result(file_name, data):'''保存聚类结果:param file_name: 保存的文件名:param data: 需要保存的文件:return:'''f = open(file_name, "w")m, n = np.shape(data)for i in range(m):tmp = []for j in range(n):tmp.append(str(data[i, j]))f.write("\t".join(tmp) + "\n")f.close()

4、调用Mean Shift算法

if __name__ == "__main__":data = load_data("F://data", 2)points, shift_points, cluster = mean_shift(data, 2)save_result("sub", np.mat(cluster))save_result("center", shift_points)

5、结果展示

       得到的聚类结果如下所示:

        你们在此过程中遇到了什么问题,欢迎留言,让我看看你们都遇到了哪些问题。


http://chatgpt.dhexx.cn/article/oncxbXO4.shtml

相关文章

meanshift算法 java_Meanshift,聚类算法

记得刚读研究生的时候&#xff0c;学习的第一个算法就是meanshift算法&#xff0c;所以一直记忆犹新&#xff0c;今天和大家分享一下Meanshift算法&#xff0c;如有错误&#xff0c;请在线交流。 Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其…

保边滤波之Mean shift filter

Mean shift filter 目录 Mean shift filter 一、算法原理 二、练手实现的算法代码如下&#xff1a; 三、实现结果 一、算法原理 在OpenCV中&#xff0c;meanshift filter函数为 pyrMeanShiftFiltering&#xff0c; 它的函数调用格式如下&#xff1a; C: void pyrMeanShif…

mean shift

参考&#xff1a; http://blog.csdn.net/google19890102/article/details/51030884 http://www.cvvision.cn/5778.html https://wenku.baidu.com/view/5862334827d3240c8447ef40.html http://blog.csdn.net/qq_23968185/article/details/51804574 https://www.cnblogs.com…

机器学习算法原理与实践(二)、meanshift算法图解以及在图像聚类、目标跟踪中的应用

【原创】Liu_LongPo 转载请注明出处 【CSDN】http://blog.csdn.net/llp1992 最近在关注跟踪这一块的算法&#xff0c;对于meanshift的了解也是来自论文和博客&#xff0c;本博客将对meanshift算法进行总结&#xff0c;包括meanshift算法原理以及公式推导&#xff0c;图解&…

基于MeanShift的目标跟踪算法及实现

这次将介绍基于MeanShift的目标跟踪算法&#xff0c;首先谈谈简介&#xff0c;然后给出算法实现流程&#xff0c;最后实现了一个单目标跟踪的MeanShift算法【matlab/c两个版本】 csdn贴公式比较烦&#xff0c;原谅我直接截图了… 一、简介 首先扯扯无参密度估计理论&#xff0c…

聚类算法:Mean Shift

目录 简介 mean shift 算法理论 Mean Shift算法原理 算法步骤 算法实现 其他 聚类算法之Mean Shift Mean Shift算法理论 Mean Shift向量 核函数 引入核函数的Mean Shift向量 聚类动画演示 Mean Shift的代码实现 算法的Python实现 scikit-learn MeanShift演示 s…

meanshift算法通俗讲解

这几天学习《学习OpenCV》中的第十章运动跟踪&#xff0c;里面讲到了meanshift算法&#xff0c;根据书上所讲实在难以理解&#xff0c;meanshift在运动跟踪这个过程中到底起到什么作用&#xff0c;于是经过几天不断地看相关资料和别人的博客文章&#xff0c;慢慢思路清晰了&…

机器学习实验 - MeanShift聚类

目录 一、报告摘要1.1 实验要求1.2 实验思路1.3 实验结论 二、实验内容2.1 方法介绍2.2 实验细节2.2.1 实验环境2.2.2 实验过程2.2.3 实验与理论内容的不同点 2.3 实验数据介绍2.4 评价指标介绍2.5 实验结果分析 三、总结及问题说明四、参考文献附录&#xff1a;实验代码 报告内…

聚类 之 MeanShift

文章目录 Meanshift 聚类基本原理Meanshift 聚类流程简述实例演示MeanShift聚类简易应用示例总结拓展阅读 上篇博客介绍了基于距离的K-Means聚类&#xff0c;这次给大家推荐一个基于密度的聚类算法&#xff1a;Meanshift&#xff08;均值漂移&#xff09;。 Meanshift 聚类基本…

Muduo源码剖析

1、总体流程 1. acceptor 进行listen阶段后&#xff0c; 往channel中注册可读事件。 2. acceptor可读处理中生成TcpConnection指针&#xff0c;通过EventloopThreadPool 轮询出其中一个线程的eventloop, 并将此TcpConnection的可读、可写等事件注册到自己Channel&#xff08;ev…

Muduo - Reactor模式

Muduo - Reactor模式 一、Reactor 是什么 wiki的中文定义&#xff1a;Reactor模式是事件驱动的&#xff0c;有一个或多个并发输入源&#xff0c;有一个Service Handler&#xff0c;有多个Request Handler&#xff0c;这个Service Handler会同步的将输入的请求&#xff08;Even…

muduo网络库——ThreadPool

模型 源码分析 1&#xff09;接口 class ThreadPool : noncopyable {public:typedef std::function<void ()> Task;explicit ThreadPool(const string& nameArg string("ThreadPool"));~ThreadPool();void setMaxQueueSize(int maxSize) { maxQueueSize…

muduo网络库——Channel

模型 实现流程&#xff1a; 前面已经介绍了EPoller类&#xff0c;EPoller主要监听的是Channel对象&#xff0c;每一个Channel对象会绑定一个文件描述符&#xff08;fd_&#xff09;&#xff0c;fd_上绑定要监听的事件。当epoll监听到就绪事件时&#xff0c;会将就绪事件添加到…

muduo源码分析之Buffer

这一次我们来分析下muduo中Buffer的作用&#xff0c;我们知道&#xff0c;当我们客户端向服务器发送数据时候&#xff0c;服务器就会读取我们发送的数据&#xff0c;然后进行一系列处理&#xff0c;然后再发送到其他地方&#xff0c;在这里我们想象一下最简单的EchoServer服务器…

从实例看muduo网络库各模块交互过程

文章目录 muduo网络库的核心代码模块各模块功能解释ChannelPollerEpollPoller EventLoopEventLoopThreadEventLoopThreadPoolTcpServerTcpConnection 从实际应用出发 muduo网络库的核心代码模块 1、channel 2、Poller 和它的子类 EpollPoller 3、EventLoop 4、Thread、EventLo…

muduo总结

本文重点在muduo TcpServer的启动&#xff0c;I/O线程池的启动&#xff0c;以及各种回调 文章目录 baseAsyncLogging.{h,cc}Atomic.hBlockinQueue.hBoundedBlockinQueue.hCondition.hcopyable.hCountDownLatch.{h,cc}Date.{h,cc}Exception.{h,cc}Logging.{h,cc}Mutex.hProcess…

muduo网络库——日志处理

测试程序 #include "muduo/base/AsyncLogging.h" #include "muduo/base/Logging.h" #include "muduo/base/Timestamp.h"#include <stdio.h> #include <sys/resource.h> #include <unistd.h>off_t kRollSize 500*1000*1000;m…

Muduo日志模块详解

Muduo日志模块解析 图片取自muduo网络库源码解析(1):多线程异步日志库(上)_李兆龙的技术博客_51CTO博客也是很好的日志讲解博客,这篇讲解流程基本上和它差不多,并且写的比我条理清楚很多 AppendFile::append() 这个函数是日志写入文件的最终函数,并且AppendFile这个类里面也是…

Muduo 定时器

TimeQueue定时器 图片转载自:muduo网络库源码解析(4):TimerQueue定时机制_李兆龙的技术博客_51CTO博客 添加新的定时器 TimerId TimerQueue::addTimer(TimerCallback cb, //用户自定义回调Timestamp when, //定时器的超时时刻double interval) //重复触发间隔,小于0则不重…

《muduo网络库》学习笔记——muduo学习总结

muduo是基于非阻塞的IO和事件驱动的网络库&#xff08;Reactor模式&#xff09;&#xff0c;其核心是一个事件循环EventLoop&#xff0c;用于响应计时器和IO事件。muduo采用基于对象&#xff08;object-based&#xff09;而非面向对象&#xff08;object-oriented&#xff09;的…