聚类(Clustering):hierarchical clustering 层次聚类及其应用

聚类(Clustering):hierarchical clustering 层次聚类及其应用

clustering实现:

from numpy import *
import math
#基于matrix计算的pakage#定义树形结构图的结点,当再往上两则分为一类时则将其连接起来
#用面向对象(class)的方法实现此次的代码:
class cluster_node:def __init__ (self,vec,left=None,right=None,distance=0.0,id=None,count=1):#初始化的函数,每次实例化这个类的时候都会自动调用次函数(同java中的构造函数,self同java中的this)'''vec:传入的数据为numpy array,每一行就是一个vec;left:左节点;right=右节点;distance:结点之间距离id:给节点定义一个名字,算节点平均值时要区分哪些节点包含在哪count:节点计数'''self.vec = vecself.left = leftself.right = rightself.distance = distanceself.id = idself.count = count #only used for weighted average #找出最近的两点的距离:
def L2dist(v1,v2):return math.sqrt(sum((v1-v2)**2)) #2维的两点(向量计算)的直线距离,向量为坐标形式,一个坐标包含x,y两个数值def L1dist(v1,v2): #计算一维的距离时使用return sum(abs(v1-v2))# def Chi2dist(v1,v2):#     return sqrt(sum((v1-v2)**2))#实现 HC的具体树状结构
def hcluster(features,distance=L2dist):'''features:类型为numpy arraydistance:默认为2D距离'''distances = {} #用来储存所有distance,注意字典distances和函数distance的区别currentid = -1 #初始化实例的clusterid#最开始每一个单独的数据就是一个单独的cluster,对应的就是feature(array/matrix)中的每一行==> # clusters are initially just the individual rowsclust = [cluster_node(array(features[i]),id=i) for i in range(len(features))]#注意这里array赋值属性的用法和for循环的使用方法'''features的每一组[]里的数据对应一个点,每一个点都赋值一个类别i,调用cluster_node'''#进行分类,知道所有分类个数为1时结束循环:while len(clust)>1:lowestpair = (0,1)#初始化以(0,1)为最近的组closest = distance(clust[0].vec,clust[1].vec)#首先取前两个向量,只有两个向量,他们的距离也就是最小的(调用了L2dist计算最小距离)# loop through every pair looking for the smallest distancefor i in range(len(clust)):for j in range(len(clust)):# distances is the cache of distance calculationif (clust[i].id,clust[j].id) not in distances:distances[clust[i].id,clust[j].id] = distance(clust[i].vec,clust[j].vec)'''将i,j两点的距离计算并传到字典distances中'''d = distances[(clust[i].id,clust[j].id)]if d < closest: #比较出最小距离,赋值给closest,同时更新最近距离的对组closest = dlowestpair = (i,j) # calculate the average of the two clusters.有多种定义分类的方法(最近距离、最远距离、均值、中值),这里取平均距离print(clust[lowestpair[0].vec[0]])mergevec = [(clust[lowestpair[0]].vec[i]+clust[lowestpair[1]].vec[i])/2.0 for i in range(len(clust[0].vec))]# create the new clusternewcluster = cluster_node(array(mergevec),left=clust[lowestpair[0]],right=clust[lowestpair[1]],distance=closest,id=currentid)# cluster ids that weren't in the original set are negative# 不在原始的数据集合中currentid为负数currentid -= 1#每执行完一次结点计算就将之前的结点坐标值删除?del clust[lowestpair[0]]del clust[lowestpair[1]]clust.append(newcluster)return clust[0]# (以上已经建立好树状图了)def extract_cluster(clust,dist): #dist为预设的距离值# extract list of sub-tree clusters from hcluster tree with distance<distcluster = {}if clust.distance<dist:# we have found a cluster subtreereturn [clust]else:# check the right and left branchescl = []cr = []if clust.left != None:#这里可以直接.left?cl = extract_cluster(clust.left,dist=dist)if clust.right != None:cr = extract_cluster(clust.right,dist=dist)return cl+crdef get_cluster_elements(clust):# return ids for elements in a cluster sub-tree# 如果该要求的clust没有子集,那就返回他本身,如果有子集就返回左子集和右子集相加if clust.id>=0:# positive id means that this is a leafreturn clust.idelse:# check the right and left branchescl = []cr = []if clust.left != None:cl = get_cluster_elements(clust.left)if clust.right !=None:cr = get_cluster_elements(clust.right)return cl+crdef printclust(clust,labels=None,n=0):for i in range(n): print(''),if clust.id<0:# negative id means that this is branchprint('-')else:# positive id means that this is an endpointif labels==None: print(clust.id)else: print(labels[clust.id])if clust.left != None: printclust(clust.left,labels=labels,n=n+1)if clust.right !=None: printclust(clust.right,labels=labels,n=n+1)def getheight(clust):# Is this an endpoint? Then the height is just 1if clust.left == None and clust.right ==None: return 1# Otherwise the height is the same of the heights of each branchreturn getheight(clust.left)+getheight(clust.right) #为什么还要加上getheight这个函数?def getdepth(clust):  #深度是?# The distance of an endpoint is 0.0if clust.left == None and clust.right == None: return 0    # The distance of a branch is the greater of its two sides plus its own distance  return max(getdepth(clust.left),getdepth(clust.right))+clust.distance

clustering代码应用:(借用链接:https://blog.csdn.net/weixin_41790863/article/details/81412564 )

from PIL import ImageDraw, Image
import numpy as np
import os
import sysnodeList = []  # 用于存储所有的节点,包含图片节点,与聚类后的节点
distance = {}  # 用于存储所有每两个节点的距离,数据格式{(node1.id,node2.id):30.0,(node2.id,node3.id):40.0}class node:def __init__(self, data):'''每个样本及样本合并后节点的类data:接受两种格式,1、当为字符(string)时,是图片的地址,同时也表示这个节点就是图片2、合并后的类,传入的格式为(leftNode,rightNode) 即当前类表示合并后的新类,而对应的左右节点就是子节点'''self.id = len(nodeList)  # 设置一个ID,以nodeList当然长度为ID,在本例中ID本身没太大用处,只是如果看代码时,有时要看指向时有点用self.parent = None  # 指向合并后的类self.pos = None  # 用于最后绘制节构图使用,赋值时为(x,y,w,h)格式if type(data) == type(""):'''节点为图片'''self.imgData = Image.open(data)self.left = Noneself.right = Noneself.level = 0  # 图片为最终的子节点,所有图片的层级都为0,设置层级是为了最终绘制结构图npTmp = np.array(self.imgData).reshape(-1, 3)  # 将图片数据转化为numpy数据,shape为(高,宽,3)3为颜色通道npTmp = npTmp.reshape(-1, 3)  # 重新排列,shape为(*宽,3)self.feature = npTmp.mean(axis=0)  # 计算RGB三个颜色通道均值else:'''节点为合成的新类'''self.imgData = Noneself.left = data[0]self.right = data[1]self.left.parent = selfself.right.parent = selfself.level = max(self.left.level, self.right.level) + 1  # 层级为左右节高层级的级数+1self.feature = (self.left.feature + self.right.feature) / 2  # 两类的合成一类时,就是左右节点的feature相加/2# 计算该类与每个其他类的距离,并存入distancefor x in nodeList:distance[(x, self)] = np.sqrt(np.sum((x.feature - self.feature) ** 2))nodeList.append(self)  # 将本类加入nodeList变量def drawNode(self, img, draw, vLineLenght):# 绘制结构图if self.pos == None: returnif self.left == None:# 如果是图片self.imgData.thumbnail((self.pos[2], self.pos[3])) #thumbnail将图片变小成缩略图img.paste(self.imgData, (self.pos[0], self.pos[1]))draw.line((int(self.pos[0] + self.pos[2] / 2), self.pos[1] - vLineLenght, int(self.pos[0] + self.pos[2] / 2), self.pos[1]), fill=(255, 0, 0))else:# 如果不是图片draw.line((int(self.pos[0]), self.pos[1], int(self.pos[0] + self.pos[2]), self.pos[1]), fill=(255, 0, 0))draw.line((int(self.pos[0] + self.pos[2] / 2), self.pos[1], int(self.pos[0] + self.pos[2] / 2), self.pos[1] - self.pos[3]), fill=(255, 0, 0))def loadImg(path):'''path 图片目录,根据自己存的地方改写'''files = Nonetry:files = os.listdir(path)except:print('未正确读取目录:' + path + ',图片目录,请根据自己存的地方改写,并保证没有hierarchicalResult.jpg,该文件为最后生成文件')return Nonefor i in files:if os.path.splitext(i)[1].lower() == '.jpg' and os.path.splitext(i)[0].lower() != 'hierarchicalresult':fileName = os.path.join(path, i)node(fileName)return os.path.join(path, 'hierarchicalResult.jpg')def getMinDistance():'''从distance中过滤出未分类的结点,并读取最小的距离'''vars = list(filter(lambda x: x[0].parent == None and x[1].parent == None, distance))minDist = vars[0]for x in vars:if minDist == None or distance[x] < distance[minDist]:minDist = xreturn minDistdef createTree():while len(list(filter(lambda x: x.parent == None, nodeList))) > 1:  # 合并到最后时,只有一个类,只要有两个以上未合并,就循环minDist = getMinDistance()# 创建非图片的节点,之所以把[1]做为左节点,因为绘图时的需要,# 在不断的产生非图片节点时,在nodeList的后面的一般是新节点,但绘图时绘在左边node((minDist[1], minDist[0]))return nodeList[-1]  # 最后一个插入的节点就是要节点def run():root = createTree()  # 创建树结构# 一句话的PYTON,实现二叉树的左右根遍历,通过通过遍历,进行排序后,取出图片,做为最底层的打印sortTree = lambda node: ([] if node.left == None else sortTree(node.left)) + ([] if node.right == None else sortTree(node.right)) + [node]treeTmp = sortTree(root)treeTmp = list(filter(lambda x: x.left == None, treeTmp))  # 没有左节点的,即为图片thumbSize = 60  # 缩略图的大小,,在60X60的小格内缩放thumbSpace = 20  # 缩略图间距vLineLenght = 80  # 上下节点,即每个level之间的高度imgWidth = len(treeTmp) * (thumbSize + thumbSpace)imgHeight = (root.level + 1) * vLineLenght + thumbSize + thumbSpace * 2img = Image.new('RGB', (imgWidth, imgHeight), (255, 255, 255))draw = ImageDraw.Draw(img)for item in enumerate(treeTmp):# 为所有图片增加绘图数据x = item[0] * (thumbSize + thumbSpace) + thumbSpace / 2y = imgHeight - thumbSize - thumbSpace / 2 - ((item[1].parent.level - 1) * vLineLenght)w = item[1].imgData.widthh = item[1].imgData.heightif w > h:h = h / w * thumbSizew = thumbSizeelse:w = w / h * thumbSizeh = thumbSizex += (thumbSize - w) / 2item[1].pos = (int(x), int(y), int(w), int(h))item[1].drawNode(img, draw, vLineLenght)for x in range(1, root.level + 1):# 为所有非图片增加绘图的数据items = list(filter(lambda i: i.level == x, nodeList))for item in items:x = item.left.pos[0] + (item.left.pos[2] / 2)w = item.right.pos[0] + (item.right.pos[2] / 2) - xy = item.left.pos[1] - (item.level - item.left.level) * vLineLenghth = ((item.parent.level if item.parent != None else item.level + 1) - item.level) * vLineLenghtitem.pos = (int(x), int(y), int(w), int(h))item.drawNode(img, draw, vLineLenght)img.save(resultFile)resultFile = loadImg(r"G:\Pythonnotes\test\HierarchicalClusterDataset")  # 读取数据,并返回最后结果要存储的文件名,目录根据自己存的位置进行修改
if resultFile != 'None':run()print("结构图生成成功,最终结构图存储于:" + resultFile)

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

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

相关文章

具有IOctl的简单字符驱动

http://www.cnblogs.com/geneil/archive/2011/12/04/2275372.html 驱动层 #include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/module.h> #i…

智慧交通day02-车流量检测实现11:yoloV3模型

yoloV3以V1&#xff0c;V2为基础进行的改进&#xff0c;主要有&#xff1a;利用多尺度特征进行目标检测&#xff1b;先验框更丰富&#xff1b;调整了网络结构&#xff1b;对象分类使用logistic代替了softmax,更适用于多标签分类任务。 1.算法简介 YOLOv3是YOLO (You Only Loo…

bzoj1992鬼谷子的钱袋(二分乱搞 二进制)

1192: [HNOI2006]鬼谷子的钱袋 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3223 Solved: 2333Descriptio 鬼谷子非常聪明&#xff0c;正因为这样&#xff0c;他非常繁忙&#xff0c;经常有各诸侯车的特派员前来向他咨询时政。有一天&#xff0c;他在咸阳游历的时候&…

聚类(Clustering): K-means算法

聚类(Clustering): K-means算法 1.归类: 聚类(clustering)属于非监督学习(unsupervised learning) 无类别标记( class label) 3. K-means 算法&#xff1a; 3.1 Clustering 中的经典算法&#xff0c;数据挖掘十大经典算法之一 3.2 算法接受参数 k &#xff1b;然后将事先输入…

ubuntu12.04

http://blog.sina.com.cn/s/blog_92942dba01014r7z.html

智慧交通day02-车流量检测实现12:基于yoloV3的目标检测

在本章节代码编写中&#xff0c;发现之前的代码所处的环境是python3&#xff0c;因此导致了cv2.dnn.readNetFromDarknet()在代码运行中导致了i[0]的获值失败&#xff0c;故总结如下&#xff1a; cv2.dnn.readNetFromDarknet()在python3上遇到的问题_李大狗的读研日记-CSDN博客…

非线性回归(Non-linear Regression)

非线性回归应用&#xff08;Logistic Regression Application&#xff09; 理论实际应用整合到一起链接 import numpy as np import random# 一个函数为梯度下降的算法 def GradientDescent(x,y,theta,alpha,m,numInterations):# m denotes the number of examples here, not…

cv2.dnn.readNetFromDarknet()在python3上遇到的问题

问题描述&#xff1a; 代码如下 net cv2.dnn.readNetFromDarknet(configPath,weightsPath) #获取YOLO每一层的名称 #getLayerNames&#xff08;&#xff09;&#xff1a;获取网络所有层的名称。 ln net.getLayerNames() # 获取输出层的名称: [yolo-82,yolo-94,yolo-106] # …

企业的网站遭受木马攻击了,导致网站目录下所有文件都被篡改了

问题&#xff1a; 一个 lamp 的服务器站点目录下所有文件均被植入如下内容 <script languagejavascript srchttp://luoahong.blog.51cto.com/504977/1827164> 包括图片文件也被植入了&#xff0c;网站打开时就会调用这个地址&#xff0c;造成的影响很恶劣。 实际解决办法…

智慧交通day02-车流量检测实现13:基于虚拟线圈法的车辆统计+视频中的车流量统计原理解析

1.基于虚拟线圈法的车辆统计 基于虚拟线圈的车流量统计算法原理与交通道路上的常见的传统的物理线圈类似&#xff0c;由于物理线圈需要埋设在路面之下&#xff0c;因此会有安装、维护费用高&#xff0c;造成路面破坏等问题&#xff0c;而采用基于视频的虚拟线圈的车辆计数方法…

ValueError: Found array with dim 4. Estimator expected和ValueError: Expected 2D array, got 1D array i

python3中对numpy数组进行降维或升维 解决报错如&#xff1a; 1.ValueError: Found array with dim 4. Estimator expected 2.ValueError: Expected 2D array, got 1D array instead: 报错1ValueError: Found array with dim 4. Estimator expected——解决方式&#xff1a…

ubuntu 12.04 eclipse 安装

方法二&#xff1a;(优点是安装内容清爽&#xff0c;缺点是配置麻烦) 1、安装JDK&#xff0c;参考 Ubuntu 12.04 下安装 JDK 7 2、下载 Eclipse 从 http://www.eclipse.org/downloads/index-developer.php下载合适版本&#xff0c;如&#xff1a;Eclipse IDE for C/C Develope…

智慧交通day02-车流量检测实现14:代码汇总+问题修正

代码权重文件资源https://download.csdn.net/download/qq_39237205/43072746https://download.csdn.net/download/qq_39237205/43072746 环境要求&#xff1a;python2.7 环境配置&#xff1a;见文末requirements.txt 1.YOLO.py # encoding:utf-8 import imutils import tim…

终端mysql Operation not permitted错误解决方案

前言 前段时间装mysql&#xff0c;就遇到了ln: /usr/bin/mysql: Operation not permitted的错误&#xff0c;网上好多方法都过时了&#xff0c;下边是我的解决方法 原因 这是因为苹果在OS X 10.11中引入的SIP特性使得即使加了sudo&#xff08;也就是具有root权限&#xff09;也…

从资源池和管理的角度理解物理内存

早就想搞一下内存问题了&#xff01;这次正趁着搞bigmemory内核&#xff0c;可以写一篇文章了。本文旨在记录&#xff0c;不包含细节&#xff0c;细节的话&#xff0c;google&#xff0c;百度均可&#xff0c;很多人已经写了不少了。我只是按照自己的理解记录一下内存的点点滴滴…

TypeError: object of type 'zip' has no len()、'zip' object is not subscriptable

TypeError: object of type ‘zip’ has no len()、‘zip’ object is not subscriptable zip 对象没有length属性不可以遍历 代码报错&#xff1a; print(len(training_data)) # TypeError: object of type zip has no len() print(training_data[0][0].shape) # TypeError…

【VBA编程】06.控制语句

【IF...THEN...语句】 If condition Then [statements1] else [statements2] end if condition 为一个逻辑表达式&#xff0c;表示做选择时需要判别的条件&#xff0c;其结果为布尔类型&#xff0c;当其值为真时&#xff0c;执行statements1语句&#xff0c;为假是则执行ELSE中…

从头开始学一个android activity

一、类层次结构&#xff1a; 二、什么是Activity&#xff0c;如何理解Activity 1、 用户与应用程序的交互的接口 2、 控件的容器&#xff0c;我们要把控件摆放在这个容器中 三、如何创建一个Activity 新建一个类&#xff1a; 1、 继承Activity类 [java] view plaincopyprint…

python3 numpy中矩阵np.dot(a,b)乘法运算

python np.dot(a,b)乘法运算 首先我们知道矩阵运算是不满足交换律的&#xff0c;np.dot(a, b)与np.dot(b, a)是不一样的 另外np.dot(a,b)和a.dot(b)果是一样的 1.numpy中数组&#xff08;矩阵&#xff09;相乘np.dot(a,b)运算&#xff1a; 对于两数组a和b &#xff1a; 示例…