明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 892|回复: 9

机器学习中的KMeans算法实现_AutoLISP版本

  [复制链接]
发表于 2024-2-29 21:59:14 | 显示全部楼层 |阅读模式
本帖最后由 伊江痕 于 2024-3-4 10:22 编辑

算法流程如下:

输入:
    X: 数据集
    K: 簇的数量
    max_iterations: 最大迭代次数
    tolerance: 簇中心变化的容忍度

过程:
1. 初始化:
    从X中随机选择K个数据点作为初始簇中心centroids
2. 迭代直到达到最大迭代次数或簇中心变化小于tolerance:
    a. 对于X中的每个点x_i,找到距离最近的簇中心c_j,并将x_i分配给相应的簇S_j
    b. 对于每个簇S_j,更新簇中心c_j为S_j中所有点的平均值
    c. 计算簇中心的变化量,如果所有簇中心的变化量都小于tolerance,则结束迭代

输出:
    簇分配结果
    簇中心


代码如下:
  1. ;在CAD中随机绘制一些半径相同的圆,这些圆最好能肉眼可见的一簇一簇的(效果会好点),当然这些簇之间也不用完全的分离开,可以相互有些交错的那种(真实的数据集肯定不是那么的泾渭分明的),然后运行本代码,框选所有圆即可。
  2. ;这里的k代表你想把这些圆分成多少簇。
  3. (defun kmeans(k / max_i)
  4.   (setq x (ssget))
  5.   ;最大迭代次数
  6.   (setq max_i 20)
  7.   (setq lx (sslength x))
  8.   ;centroids用来放属于不同簇的圆
  9.   (setq centroids nil)
  10.   ;centroids_core_p用来放簇中心的点坐标
  11.   (setq centroids_core_p nil)
  12.   ;从X中随机选择K个数据点作为初始簇中心centroids
  13.   (repeat k
  14.     (setq ent (ssname x (randrange 0 (- lx 1))))
  15.     (setq cen (list ent))
  16.     (setq centroids (append centroids (list cen)))
  17.     (setq ent_p (cdr (assoc 10 (entget ent))))
  18.     (setq centroids_core_p (append centroids_core_p (list ent_p)))
  19.     )
  20.   (setq ii 0)
  21.   (repeat max_i
  22.     (princ (strcat "第" (itoa ii) "次迭代"))
  23.     (setq i 0)
  24.     (repeat lx
  25.       ;获取选择集中的一个圆圈
  26.       (setq ci (ssname x i))
  27.       (setq cip (cdr (assoc 10 (entget ci))))
  28.       ;分别和centroids_core_p的圆心计算距离,看哪个距离最小就属于哪个簇
  29.       (setq min_dist nil)
  30.       (setq min_index 0)
  31.       (setq j 0)
  32.       (repeat k
  33.         (setq centroidp (nth j centroids_core_p))
  34.         (setq dist (distance cip centroidp))
  35.         (if (/= dist 0)
  36.           (if (or (< dist min_dist) (= min_dist nil))
  37.             (progn
  38.               (setq min_dist dist)
  39.               (setq min_index j)
  40.               )

  41.             )
  42.          
  43.           )
  44.         (setq j (+ j 1))
  45.         )
  46.       ;更新centroids
  47.       (setq centroids
  48.              (subst
  49.                (append (nth min_index centroids) (list ci))
  50.                (nth min_index centroids)
  51.                centroids
  52.                )
  53.              )
  54.       ;更新centroids_core_p
  55.       (setq centroids_min_index (nth min_index centroids))
  56.       (setq center_min_index
  57.              (mapcar
  58.                '(lambda (c)(cdr (assoc 10 (entget c))))
  59.                centroids_min_index
  60.                )
  61.              )
  62.       (setq x_lst (mapcar '(lambda (l)(car l)) center_min_index))
  63.       (setq x_total (apply '+ x_lst))
  64.       (setq x_average (/ x_total (length x_lst)))
  65.       (setq y_lst (mapcar '(lambda (l)(cadr l)) center_min_index))
  66.       (setq y_total (apply '+ y_lst))
  67.       (setq y_average (/ y_total (length y_lst)))
  68.       (setq z_lst (mapcar '(lambda (l)(caddr l)) center_min_index))
  69.       (setq z_total (apply '+ z_lst))
  70.       (setq z_average (/ z_total (length z_lst)))
  71.       (setq newp (list x_average y_average z_average))
  72.       (setq centroids_core_p
  73.              (subst
  74.                newp
  75.                (nth min_index centroids_core_p)
  76.                centroids_core_p
  77.                )
  78.              )

  79.       (setq i (+ i 1))
  80.       )
  81.     (setq ii (+ ii 1))
  82.     )
  83.   ;给不同簇中的圆上不同色
  84.   (setq index 0)
  85.   (repeat k
  86.     (setq centroids_index (nth index centroids))
  87.     (setq l (length centroids_index))
  88.     (setq i 0)
  89.     (repeat l
  90.       (setq e (nth i centroids_index))
  91.       (setq e_data (entget e))
  92.       (if (= (assoc 62 e_data) nil)
  93.         (setq e_data (cons (cons 62 (+ index 1)) e_data))
  94.         (setq e_data
  95.              (subst
  96.                (cons 62 (+ index 1))
  97.                (assoc 62 e_data)
  98.                e_data
  99.                )
  100.              )
  101.         )
  102.       
  103.       (entmod e_data)
  104.       (setq i (+ i 1))
  105.       )
  106.     (setq index (+ index 1))
  107.     )
  108.   
  109.   )
  110. (defun rand ( / a c m )
  111.     (setq m   4294967296.0
  112.           a   1664525.0
  113.           c   1013904223.0
  114.           $xn (rem (+ c (* a (cond ($xn) ((getvar 'date))))) m)
  115.     )
  116.     (/ $xn m)
  117. )
  118. (defun randrange ( a b )
  119.     (+ (min a b) (fix (* (rand) (1+ (abs (- a b))))))
  120. )

评分

参与人数 3明经币 +3 收起 理由
bssurvey + 1 赞一个!
ssyfeng + 1 赞一个!
tigcat + 1 很给力!

查看全部评分

发表于 2024-2-29 22:03:07 | 显示全部楼层
伊神牛鼻plus
发表于 2024-3-1 10:03:06 | 显示全部楼层
我K=4,max_i=50,(kmeans 4),好像结果有些问题,是否迭代次数不够多的原因,结果如下:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
 楼主| 发表于 2024-3-1 10:26:12 | 显示全部楼层
ssyfeng 发表于 2024-3-1 10:03
我K=4,max_i=50,(kmeans 4),好像结果有些问题,是否迭代次数不够多的原因,结果如下:

出现这种情况很正常,大多都是迭代次数不够。你也可以把簇之间的距离弄得靠拢一点,重合一点,增加点难度。
 楼主| 发表于 2024-3-1 10:27:24 | 显示全部楼层
ssyfeng 发表于 2024-3-1 10:03
我K=4,max_i=50,(kmeans 4),好像结果有些问题,是否迭代次数不够多的原因,结果如下:

还有可能是,初始随机选取簇中心的时候,两个簇中心选到一块去了,就会这样。
发表于 2024-3-1 10:34:07 | 显示全部楼层
伊江痕 发表于 2024-3-1 10:27
还有可能是,初始随机选取簇中心的时候,两个簇中心选到一块去了,就会这样。

应该还有优化空间
 楼主| 发表于 2024-3-1 10:47:38 | 显示全部楼层
ssyfeng 发表于 2024-3-1 10:34
应该还有优化空间

是的,这只是按照基础的算法流程撸下来的
发表于 2024-3-1 18:45:07 来自手机 | 显示全部楼层
写个c#的看看
 楼主| 发表于 2024-3-4 10:20:09 | 显示全部楼层

我想看你写
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 04:51 , Processed in 0.195111 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表