Python 实现MeanShift算法

article/2025/11/6 16:21:06

原理

大家自行百度吧,我懒得码字了

推荐一下原理原理https://blog.csdn.net/jinshengtao/article/details/30258833

代码

直接上代码了,看不懂,就参照一下原理

# author: wdq
# contact: 1920132572@qq.com
# datetime:2022/3/15 17:40
# software: PyCharm
import random
from collections import Counter
from typing import Listimport numpy as np
from numpy import ndarrayclass MeanShift:def __init__(self, nums: ndarray, band_width: float):""":param nums: 要划分的ndarray:param band_width: 窗口大小"""# 要划分的ndarrayself.__nums = nums# 窗口大小self.__band_width = band_width# 停止步长self.__stop_band_width = 10 ** -4 * self.__band_width# 访问数组self.__is_visited = [False] * self.__nums.shape[0]# 聚类中心self.__cluster_centers = []# 聚类self.__cluster = []def mean_shift(self) -> List[List[List[int]]]:# 判断是否所有点都被访问过while not self.__is_all_visited():my_member = []# 在没被访问的点随机选一个点start_point = random.choice([i for i in range(self.__nums.shape[0]) if not self.__is_visited[i]])my_mean = self.__nums[start_point]while True:# 得到到各点的距离,以及权重distance, gaussian = self.__get_shift(my_mean)# 找到在窗口的点in_the_area = self.__find__points(distance)# 保留当前的位置old_mean = my_mean.copy()# 得到新的位置my_mean = self.__get_new_mean(gaussian, in_the_area)# 将范围的点划到当次的聚类my_member.extend(in_the_area)# 更新当前的访问数组self.__update_visited(in_the_area)# 判断是否小于停止步长if self.__get_distance(old_mean, my_mean) < self.__stop_band_width:merge_width = None# 遍历当前聚类for i in range(len(self.__cluster_centers)):# 判断中心点离得太近if self.__get_distance(my_mean, self.__cluster_centers[i]) < self.__band_width / 2:merge_width = ibreak# 如果太近了就合并这2个聚类if merge_width is not None:# 合并中心点self.__cluster_centers[merge_width] = self.__get_new_center(my_mean,self.__cluster_centers[merge_width])# 合并聚类中的点self.__cluster[merge_width].extend(my_member)# 否则就添加一个聚类else:self.__cluster_centers.append(my_mean.tolist())self.__cluster.append(my_member)break# 返回分好类的结果return self.__get_result()def __is_all_visited(self) -> bool:""":return: 是否全部访问"""# 遍历访问数组for i in self.__is_visited:if not i:return Falsereturn Truedef __get_distance(self, start: any, end: any) -> float:""":param start: 起始点:param end: 终点:return: 两点之间的距离"""# 类型转换if type(start) != ndarray:start = np.array(start)if type(end) != ndarray:end = np.array(end)# 返回欧式距离return np.linalg.norm(start - end)def __get_shift(self, start: ndarray) -> (ndarray, ndarray):""":param start: 开始的点:return: 计算滑动的距离"""# 距离distance = np.zeros((self.__nums.shape[0], 1))# 权重gaussian = np.zeros((self.__nums.shape[0], 1))for i in range(distance.shape[0]):temp = self.__get_distance(start, self.__nums[i])gaussian[i] = self.__gaussian_kernel(temp, self.__band_width)distance[i] = tempreturn distance, gaussiandef __gaussian_kernel(self, distance: float, bandwidth: float) -> float:"""高斯核函数:param distance: 距离:param bandwidth: 窗口大小:return: 权重"""return (1 / (bandwidth * np.sqrt(2 * np.pi))) * np.exp(-0.5 * (distance / bandwidth) ** 2)def __get_new_mean(self, gaussian: ndarray, in_the_area: List[int]) -> ndarray:""":param gaussian: 权重:param in_the_area: 在区域的点:return:"""# 权重weight = 0.# 在范围的点new_mean = np.array([self.__nums[i].tolist() for i in in_the_area])for i in range(len(in_the_area)):new_mean[i] = new_mean[i] * gaussian[in_the_area[i]]weight += gaussian[in_the_area[i]]# 对范围的点进行加权,并算出漂移到的点return np.sum(new_mean, axis=0) / weight if weight != 0 else np.sum(new_mean, axis=0)def __find__points(self, distance: ndarray) -> List[int]:""":param distance: 距离ndarray:return: 在窗口大小内的点"""return [i for i, j in enumerate(distance) if j < self.__band_width ** 2]def __update_visited(self, in_the_area: List[int]) -> None:"""更新访问过的点:param in_the_area: 在窗口大小内的点:return:"""for i in in_the_area:self.__is_visited[i] = Truedef __get_new_center(self, mymean: ndarray, old_center: List[int]) -> List[int]:"""合并中心点:param mymean: 现在的中心点:param old_center: 以前的中心点:return:"""return [(i + j) / 2 for i, j in zip(mymean.tolist(), old_center)]def __get_result(self) -> List[List[List[int]]]:"""将结果分好类并返回这段代码比较丑陋,将就看看,不看也行,我自己都不想看大致意思就是找这些点应该分到那个类:return:"""count = []result = [[] for i in range(len(self.__cluster))]# 计数,计出每个点到每个聚类的次数for i in self.__cluster:count.append(dict(Counter(i)))belong = []# 遍历找出每个点到到那个聚类的最大值,那我们就可以认为它在那个聚类for num in range(len(self.__nums)):# 最大次数的索引index = 0for i in range(1, len(count)):if count[i].get(num, 0) > count[index].get(num, 0):index = ibelong.append(index)# 分类for i in range(len(self.__nums)):result[belong[i]].append(self.__nums[i].tolist())# 把空的聚类移除return [i for i in result if i]

测试代码

import matplotlib
from matplotlib import pyplot as plt
from sklearn import datasetsfrom MeanShift import MeanShiftmatplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False
iris = datasets.load_iris()  # 引入数据集
# 分的类不好就重新分,多试一哈
mean_shift = MeanShift(nums=iris.data, band_width=1.34)  # 对于iris,窗口大小为1.34,别问为什么,别问,问就是好用
colors = ['red', 'green', 'blue', 'black', 'yellow']
a = mean_shift.mean_shift()
for i in range(len(a)):for j in a[i]:plt.scatter(j[0], j[1], c=colors[i])
plt.title("Mean-Shift")
plt.xlabel('萼片长度')
plt.ylabel('萼片宽度')
plt.show()"""___________.__                   __               _____                 _____  .__      ._.\__    ___/|  |__ _____    ____ |  | __  ______ _/ ____\___________    /     \ |__| ____| ||    |   |  |  \\__  \  /    \|  |/ / /  ___/ \   __\/  _ \_  __ \  /  \ /  \|  |/    \ ||    |   |   Y  \/ __ \|   |  \    <  \___ \   |  | (  <_> )  | \/ /    Y    \  |   |  \||____|   |___|  (____  /___|  /__|_ \/____  >  |__|  \____/|__|    \____|__  /__|___|  /_\/     \/     \/     \/     \/                               \/        \/\/      """

运行结果

标准答案

MeanShift算法

只用来学习,借鉴,错的话,欢迎批评和指导!

邮箱:cse.dqwu19@gzu.edu.cn


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

相关文章

Sklearn聚类算法之meanshift

以二维来说明可能更容易理解&#xff0c;下图中的很多的红点就是我们的样本特征点&#xff0c;meanshift就是在这些点中的任意一个点为圆心&#xff0c;然后以半径R画一个圆&#xff08;在opencv中是一个矩形&#xff09;&#xff0c;然后落在这个圆中的所有点和圆心都会对应的…

Python实现Mean Shift聚类算法

Mean Shift算法&#xff0c;又称均值聚类算法&#xff0c;聚类中心是通过在给定区域中的样本均值确定的&#xff0c;通过不断更新聚类中心&#xff0c;直到聚类中心不再改变为止&#xff0c;在聚类、图像平滑、分割和视频跟踪等方面有广泛的运用。 Mean Shift向量 对于给定的…

mean shift 跟踪算法

说明一&#xff1a; Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束. 1. Meanshift推导 给定d维空间Rd的n个样本点 ,i1,…,n,在空间中任选一点x&#xff0c;那么Mean Shift向量…

Python实现Mean Shift算法

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

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…