landsat99 发表于 2022-5-30 09:55:11

革天明 发表于 2022-5-29 08:23
看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可

赞一个

此解法 匹配性强 完成度高

qjchen 发表于 2022-5-31 12:09:59

革天明 发表于 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#插件可能也可以

革天明 发表于 2022-5-31 13:51:40

qjchen 发表于 2022-5-31 12:09
谢谢分享~




用C++、Python不是根本
至于为什么人为规定是3个,是为了保持程序的通用性,否则此问题是无解的
人眼在看到这个图片时,其实是经过加工过的,会认为是“3列”,这个3实际是这个图片表现出的特例,换个图片,就算让不同的人来去决定,不同的人给出的列数可能都不同

landsat99 发表于 2022-5-31 15:19:26

qjchen 发表于 2022-5-31 12:09
谢谢分享~




@qjchen,@革天明,治学严谨已到代码阶段

landsat99 发表于 2022-5-31 15:55:33

本帖最后由 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]
查看完整版本: 请教各位大佬:如何求最右边的所有点