看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可
赞一个
此解法 匹配性强 完成度高 革天明 发表于 2022-5-29 08:23
看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可
谢谢分享~
之前觉得应该是用机器学习或者深度学习可能才能得到这个,但之前没有认真学过,不懂聚类。
于是学习了一下,颇有收获
以下是用ANACONDA的SPYDER编写PYTHON代码,主要用的sklearn
# 参考 https://www.tutorialspoint.com/machine_learning_with_python/machine_learning_with_python_clustering_algorithms_k_means.htm
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
XY=np.array([[-3,0], [-2.5,1], [-3.5,3], [-0.5,0], , , , , ])
#显示原始数据
plt.scatter(XY[:, 0], XY[:, 1], s = 30);
plt.show()
#人为定义为3组,y_kmeans就是预测的分组
kmeans = KMeans(n_clusters = 3)
kmeans.fit(XY)
y_kmeans = kmeans.predict(XY)
#显示聚类后的数据
plt.scatter(XY[:, 0], XY[:, 1], c = y_kmeans, s = 30, cmap = 'rainbow')
#显示聚类后的类中心
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c = 'blue', s = 100, alpha = 0.9);
plt.show()
结果如下:左是归类前,右是归类后
不过这个里面,人为规定了类数是3个,不知道有没有更好的自动算类的方法,但看到一般的KMEANS算法好像都有这个
后续:
假如用飞狐兄的PYCAD,估计可以编入PY插件
或者可以试试看ML.NET,看看编个C#插件可能也可以
qjchen 发表于 2022-5-31 12:09
谢谢分享~
用C++、Python不是根本
至于为什么人为规定是3个,是为了保持程序的通用性,否则此问题是无解的
人眼在看到这个图片时,其实是经过加工过的,会认为是“3列”,这个3实际是这个图片表现出的特例,换个图片,就算让不同的人来去决定,不同的人给出的列数可能都不同 qjchen 发表于 2022-5-31 12:09
谢谢分享~
@qjchen,@革天明,治学严谨已到代码阶段 本帖最后由 landsat99 于 2022-5-31 17:07 编辑
响应大佬,也来一段代码,, Canopy算法的,也算一种簇类分析定质心。
Github : https://github.com/AlanConstantine/CanopyByPython
修改: 添加了核心参数T1,T2的粗略判断。取为整体矩阵 Data[:,0] 最大值和最小值区间的比例参数。
用楼上大咖的点位数据 再次试算。
# -*- coding: utf-8 -*-
# @Title: Algorithm.Canopy :: Class.Canopy.py
# @From: https://github.com/AlanConstantine/CanopyByPython
# @Date: 2022.05.31
import math
import random
import numpy as np
from datetime import datetime
from pprint import pprint as p
import matplotlib.pyplot as plt
class Canopy:
def __init__(self, dataset):
self.dataset = dataset
self.t1 = 0
self.t2 = 0
# 设置初始阈值
def setThreshold(self, t1, t2):
if t1 > t2:
self.t1 = t1
self.t2 = t2
else:
print('t1 needs to be larger than t2!')
# 使用欧式距离进行距离的计算
def euclideanDistance(self, vec1, vec2):
return math.sqrt(((vec1 - vec2)**2).sum())
# 根据当前dataset的长度随机选择一个下标
def getRandIndex(self):
return random.randint(0, len(self.dataset) - 1)
def clustering(self):
if self.t1 == 0:
print('Please set the threshold.')
else:
canopies = []# 用于存放最终归类结果
while len(self.dataset) != 0:
rand_index = self.getRandIndex()
current_center = self.dataset# 随机获取一个中心点,定为P点
current_center_list = []# 初始化P点的canopy类容器
delete_list = []# 初始化P点的删除容器
self.dataset = np.delete(
self.dataset, rand_index, 0)# 删除随机选择的中心点P
for datum_j in range(len(self.dataset)):
datum = self.dataset
distance = self.euclideanDistance(
current_center, datum)# 计算选取的中心点P到每个点之间的距离
if distance < self.t1:
# 若距离小于t1,则将点归入P点的canopy类
current_center_list.append(datum)
if distance < self.t2:
delete_list.append(datum_j)# 若小于t2则归入删除容器
# 根据删除容器的下标,将元素从数据集中删除
self.dataset = np.delete(self.dataset, delete_list, 0)
canopies.append((current_center, current_center_list))
return canopies
def showCanopy(canopies, dataset, t1, t2):
fig = plt.figure()
sc = fig.add_subplot(111)
colors = ['brown', 'green', 'blue', 'y', 'r', 'tan', 'dodgerblue', 'deeppink', 'orangered', 'peru', 'blue', 'y', 'r',
'gold', 'dimgray', 'darkorange', 'peru', 'blue', 'y', 'r', 'cyan', 'tan', 'orchid', 'peru', 'blue', 'y', 'r', 'sienna']
markers = ['*', 'h', 'H', '+', 'o', '1', '2', '3', ',', 'v', 'H', '+', '1', '2', '^',
'<', '>', '.', '4', 'H', '+', '1', '2', 's', 'p', 'x', 'D', 'd', '|', '_']
for i in range(len(canopies)):
canopy = canopies
center = canopy
components = canopy
sc.plot(center, center, marker=markers,
color=colors, markersize=30)
t1_circle = plt.Circle(
xy=(center, center), radius=t1, color='dodgerblue', fill=False)
t2_circle = plt.Circle(
xy=(center, center), radius=t2, color='skyblue', alpha=0.2)
sc.add_artist(t1_circle)
sc.add_artist(t2_circle)
for component in components:
sc.plot(component, component,
marker=markers, color=colors, markersize=1.5)
maxvalue = np.amax(dataset)
minvalue = np.amin(dataset)
plt.xlim(minvalue - t1, maxvalue + t1)
plt.ylim(minvalue - t1, maxvalue + t1)
plt.show()
# 随机生成600个二维[0,1)平面点
# dataset = np.random.rand(600, 2)
dataset = np.array([[-3,0], [-2.5,1], [-3.5,3], [-0.5,0], , , , , ])
if __name__ == '__main__':
NMax = np.max(dataset[:, 0])
NMin = np.min(dataset[:, 0])
t1 = (NMax - NMin) * 0.7
t2 = t1 * 0.75
gc = Canopy(dataset)
gc.setThreshold(t1, t2)
canopies = gc.clustering()
print('Get %s initial centers.' % len(canopies))
showCanopy(canopies, dataset, t1, t2)
红框内,指定的参数T1 ,T2。 缩小区间,质心数量增加。
另外,聚类分析好像还有 Kmeans++ ,Kmeans II 等算法估CenterPoi。
页:
1
[2]