【機器學習】聚類(一):原型聚類:K-means聚類

文章目錄

  • 一、實驗介紹
    • 1. 算法流程
    • 2. 算法解釋
    • 3. 算法特點
    • 4. 應用場景
    • 5. 注意事項
  • 二、實驗環境
    • 1. 配置虛擬環境
    • 2. 庫版本介紹
  • 三、實驗內容
    • 0. 導入必要的庫
    • 1. Kmeans類
      • a. 構造函數
      • b. 閔可夫斯基距離
      • c. 初始化簇心
      • d. K-means聚類
      • e. 聚類結果可視化
    • 2. 輔助函數
    • 3. 主函數
      • a. 命令行界面 (CLI)
      • b. 數據加載
      • c. 模型訓練及可視化
    • 4. 運行腳本的命令
    • 5. 代碼整合

??原型聚類中的K均值算法是一種常用的聚類方法,該算法的目標是通過迭代過程找到數據集的簇劃分,使得每個簇內的樣本與簇內均值的平方誤差最小化。這一過程通過不斷迭代更新簇的均值來實現。

一、實驗介紹

在這里插入圖片描述

1. 算法流程

  1. 初始化: 從樣本集中隨機選擇k個樣本作為初始均值向量。
  2. 迭代過程: 重復以下步驟直至均值向量不再更新:
    • 對每個樣本計算與各均值向量的距離。
    • 將樣本劃分到距離最近的均值向量所對應的簇。
    • 更新每個簇的均值向量為該簇內樣本的平均值。
  3. 輸出: 返回最終的簇劃分。

2. 算法解釋

  • 步驟1中,通過隨機選擇初始化k個均值向量。
  • 步驟2中,通過計算樣本與均值向量的距離,將每個樣本分配到最近的簇。然后,更新每個簇的均值向量為該簇內樣本的平均值。
  • 算法通過迭代更新,不斷優化簇內樣本與均值向量的相似度,最終得到較好的聚類結果。

3. 算法特點

  • K均值算法是一種貪心算法,通過局部最優解逐步逼近全局最優解。
  • 由于需要對每個樣本與均值向量的距離進行計算,算法復雜度較高。
  • 對于大型數據集和高維數據,K均值算法的效果可能受到影響。

4. 應用場景

  • K均值算法適用于樣本集可以被均值向量較好表示的情況,特別是當簇呈現球形或近似球形分布時效果較好。
  • 在圖像分割、用戶行為分析等領域廣泛應用。

5. 注意事項

  • 對于K均值算法,初始均值向量的選擇可能影響最終聚類結果,因此有時需要多次運行算法,選擇最優的結果。
  • 算法對異常值敏感,可能導致簇的均值向量被拉向異常值,因此在處理異常值時需要謹慎。

二、實驗環境

1. 配置虛擬環境

conda create -n ML python==3.9
conda activate ML
conda install scikit-learn matplotlib seaborn

2. 庫版本介紹

軟件包本實驗版本
matplotlib3.5.2
numpy1.21.5
python3.9.13
scikit-learn1.0.2
seaborn0.11.2

三、實驗內容

0. 導入必要的庫

import numpy as np
import random
import seaborn as sns
import matplotlib.pyplot as plt
import argparse

1. Kmeans類

  • __init__ :初始化K均值聚類的參數,包括聚類數目 k、數據 data、初始化模式 mode(默認為 “random”)、最大迭代次數 max_iters、閔可夫斯基距離的階數 p、隨機種子 seed等。
  • minkowski_distance 函數:計算兩個樣本點之間的閔可夫斯基距離。
  • center_init 函數:根據指定的模式初始化聚類中心。
  • fit 方法:執行K均值聚類的迭代過程,包括分配樣本到最近的簇、更新簇中心,直到滿足停止條件。
  • visualization 函數:使用Seaborn和Matplotlib可視化聚類結果。

a. 構造函數

class Kmeans(object):def __init__(self, k, data: np.ndarray, mode="random", max_iters=0, p=2, seed=0):self.k = kself.data = dataself.mode = modeself.max_iter = max_iters if max_iters > 0 else int(1e8)self.p = pself.seed = seedself.centers = Noneself.clu_idx = np.zeros(len(self.data), dtype=np.int32)  # 樣本的分類簇self.clu_dist = np.zeros(len(self.data), dtype=np.float64)  # 樣本與簇心的距離
  • 參數:
    • 聚類數目 k
    • 數據集 data
    • 初始化模式 mode
    • 最大迭代次數 max_iters
    • 閔可夫斯基距離的階數 p 以及隨機種子 seed
  • 初始化類的上述屬性,此外
    • self.centers 被初始化為 None,表示簇心尚未計算
    • self.clu_idxself.clu_dist 被初始化為全零數組,表示每個樣本的分類簇和與簇心的距離。

b. 閔可夫斯基距離

    def minkowski_distance(self, x, y=0):return np.linalg.norm(x - y, ord=self.p)
  • 使用了NumPy的 linalg.norm 函數,其中 ord 參數用于指定距離的階數。

c. 初始化簇心

    def center_init(self):random.seed(self.seed)if self.mode == "random":ids = random.sample(range(len(self.data)), k=self.k)  # 隨機抽取k個樣本下標self.centers = self.data[ids]  # 選取k個樣本作為簇中心else:ids = [random.randint(0, self.data.shape[0])]for _ in range(1, self.k):max_idx = 0max_dis = 0for i, x in enumerate(self.data):if i in ids:continuedis = 0for y in self.data[ids]:dis += self.minkowski_distance(x - y)if max_dis < dis:max_dis = dismax_idx = iids.append(max_idx)self.centers = self.data[ids]
  • 根據指定的初始化模式,選擇隨機樣本或使用 “far” 模式。
    • 在 “random” 模式下,通過隨機抽樣選擇 k 個樣本作為簇心;
    • 在 “far” 模式下,通過計算每個樣本到已選簇心的距離之和,選擇距離總和最大的樣本作為下一個簇心。

d. K-means聚類

    def fit(self):self.center_init()  # 簇心初始化for _ in range(self.max_iter):flag = False  # 判斷是否有樣本被重新分類# 遍歷每個樣本for i, x in enumerate(self.data):min_idx = -1  # 最近簇心下標min_dist = np.inf  # 最小距離for j, y in enumerate(self.centers):  # 遍歷每個簇,計算與該樣本的距離# 計算樣本i到簇j的距離distdist = self.minkowski_distance(x, y)if min_dist > dist:min_dist = distmin_idx = jif self.clu_idx[i] != min_idx:# 有樣本改變分類簇,需要繼續迭代更新簇心flag = True# 記錄樣本i與簇的最小距離min_dist,及對應簇的下標min_idxself.clu_idx[i] = min_idxself.clu_dist[i] = min_dist# 樣本的簇劃分好之后,用樣本均值更新簇心for i in range(self.k):x = self.data[self.clu_idx == i]# 用樣本均值更新簇心self.centers[i] = np.mean(x, axis=0)if not flag:break
  • 在每次迭代中
    • 遍歷每個樣本,計算其到各個簇心的距離,將樣本分配到距離最近的簇中。
    • 更新每個簇的均值(簇心)為該簇內所有樣本的平均值。
  • 上述過程迭代進行,直到滿足停止條件(樣本不再重新分配到不同的簇)或達到最大迭代次數。

e. 聚類結果可視化

    def visualization(self, k=3):current_palette = sns.color_palette()sns.set_theme(context="talk", palette=current_palette)for i in range(self.k):x = self.data[self.clu_idx == i]sns.scatterplot(x=x[:, 0], y=x[:, 1], alpha=0.8)sns.scatterplot(x=self.centers[:, 0], y=self.centers[:, 1], marker="+", s=500)plt.title("k=" + str(k))plt.show()

2. 輔助函數

def order_type(v: str):if v.lower() in ("-inf", "inf"):return -np.inf if v.startswith("-") else np.infelse:try:return float(v)except ValueError:raise argparse.ArgumentTypeError("Unsupported value encountered")def mode_type(v: str):if v.lower() in ("random", "far"):return v.lower()else:raise argparse.ArgumentTypeError("Unsupported value encountered")
  • order_type 函數:用于處理命令行參數中的 -p(距離測量參數),將字符串轉換為浮點數。
  • mode_type 函數:用于處理命令行參數中的 --mode(初始化模式參數),將字符串轉換為合法的初始化模式。

3. 主函數

a. 命令行界面 (CLI)

  • 使用 argparse 解析命令行參數
    parser = argparse.ArgumentParser(description="Kmeans Demo")parser.add_argument("-k", type=int, default=3, help="The number of clusters")parser.add_argument("--mode", type=mode_type, default="random", help="Initial centroid selection")parser.add_argument("-m", "--max-iters", type=int, default=40, help="Maximum iterations")parser.add_argument("-p", type=order_type, default=2., help="Distance measurement")parser.add_argument("--seed", type=int, default=0, help="Random seed")parser.add_argument("--dataset", type=str, default="./kmeans.2.txt", help="Path to dataset")args = parser.parse_args()

b. 數據加載

  • 從指定路徑加載數據集。
	dataset = np.loadtxt(args.dataset)

在這里插入圖片描述

c. 模型訓練及可視化

	model = Kmeans(k=args.k, data=dataset, mode=args.mode, max_iters=args.max_iters, p=args.p,seed=args.seed)model.fit()# 聚類結果可視化model.visualization(k=args.k)

4. 運行腳本的命令

  • 通過命令行傳遞參數來運行腳本,指定聚類數目、初始化模式、最大迭代次數等。
python kmeans.py -k 3 --mode random -m 40 -p 2 --seed 0 --dataset ./kmeans.2.txt

在這里插入圖片描述

5. 代碼整合

import numpy as np
import random
import seaborn as sns
import matplotlib.pyplot as plt
import argparseclass Kmeans(object):def __init__(self, k, data: np.ndarray, mode="random", max_iters=0, p=2, seed=0):self.k = kself.data = dataself.mode = modeself.max_iter = max_iters if max_iters > 0 else int(1e8)self.p = pself.seed = seedself.centers = Noneself.clu_idx = np.zeros(len(self.data), dtype=np.int32)  # 樣本的分類簇self.clu_dist = np.zeros(len(self.data), dtype=np.float64)  # 樣本與簇心的距離def minkowski_distance(self, x, y=0):return np.linalg.norm(x - y, ord=self.p)# 簇心初始化def center_init(self):random.seed(self.seed)if self.mode == "random":ids = random.sample(range(len(self.data)), k=self.k)  # 隨機抽取k個樣本下標self.centers = self.data[ids]  # 選取k個樣本作為簇中心else:ids = [random.randint(0, self.data.shape[0])]for _ in range(1, self.k):max_idx = 0max_dis = 0for i, x in enumerate(self.data):if i in ids:continuedis = 0for y in self.data[ids]:dis += self.minkowski_distance(x - y)if max_dis < dis:max_dis = dismax_idx = iids.append(max_idx)self.centers = self.data[ids]def fit(self):self.center_init()  # 簇心初始化for _ in range(self.max_iter):flag = False  # 判斷是否有樣本被重新分類# 遍歷每個樣本for i, x in enumerate(self.data):min_idx = -1  # 最近簇心下標min_dist = np.inf  # 最小距離for j, y in enumerate(self.centers):  # 遍歷每個簇,計算與該樣本的距離# 計算樣本i到簇j的距離distdist = self.minkowski_distance(x, y)if min_dist > dist:min_dist = distmin_idx = jif self.clu_idx[i] != min_idx:# 有樣本改變分類簇,需要繼續迭代更新簇心flag = True# 記錄樣本i與簇的最小距離min_dist,及對應簇的下標min_idxself.clu_idx[i] = min_idxself.clu_dist[i] = min_dist# 樣本的簇劃分好之后,用樣本均值更新簇心for i in range(self.k):x = self.data[self.clu_idx == i]# 用樣本均值更新簇心self.centers[i] = np.mean(x, axis=0)if not flag:breakdef visualization(self, k=3):current_palette = sns.color_palette()sns.set_theme(context="talk", palette=current_palette)for i in range(self.k):x = self.data[self.clu_idx == i]sns.scatterplot(x=x[:, 0], y=x[:, 1], alpha=0.8)sns.scatterplot(x=self.centers[:, 0], y=self.centers[:, 1], marker="+", s=500)plt.title("k=" + str(k))plt.show()def order_type(v: str):if v.lower() in ("-inf", "inf"):return -np.inf if v.startswith("-") else np.infelse:try:return float(v)except ValueError:raise argparse.ArgumentTypeError("Unsupported value encountered")def mode_type(v: str):if v.lower() in ("random", "far"):return v.lower()else:raise argparse.ArgumentTypeError("Unsupported value encountered")if __name__ == '__main__':parser = argparse.ArgumentParser(description="Kmeans Demo")parser.add_argument("-k", type=int, default=3, help="The number of clusters")parser.add_argument("--mode", type=mode_type, default="random", help="Initial centroid selection")parser.add_argument("-m", "--max-iters", type=int, default=40, help="Maximum iterations")parser.add_argument("-p", type=order_type, default=2., help="Distance measurement")parser.add_argument("--seed", type=int, default=0, help="Random seed")parser.add_argument("--dataset", type=str, default="./kmeans.2.txt", help="Path to dataset")args = parser.parse_args()dataset = np.loadtxt(args.dataset)model = Kmeans(k=args.k, data=dataset, mode=args.mode, max_iters=args.max_iters, p=args.p,seed=args.seed)  # args.seed)model.fit()# 聚類結果可視化model.visualization(k=args.k)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/167820.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167820.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167820.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ElasticSearch之虛擬內存

查看當前Linux系統中vm.max_map_count變量的值&#xff0c;命令如下&#xff1a; sysctl vm.max_map_count執行結果的樣例&#xff0c;如下&#xff1a; vm.max_map_count 65530修改參數vm.max_map_count的值&#xff0c;命令如下&#xff1a; sysctl -w vm.max_map_count2…

數組題目: 665. 非遞減數列、453. 最小移動次數使數組元素相等、283. 移動零、189. 旋轉數組、396. 旋轉函數

665. 非遞減數列 題解&#xff1a; 題目要求一個非遞減數列&#xff0c;我們可以考慮需要更改的情況&#xff1a; nums {4, 2, 5} 對于這個nums&#xff0c;由于2的出現導致非遞減&#xff0c;更改的情況就是要么4調到<2&#xff0c;要么2調到4,5. nums {1, 4, 2, 5} …

人工智能-注意力機制之注意力匯聚:Nadaraya-Watson 核回歸

查詢&#xff08;自主提示&#xff09;和鍵&#xff08;非自主提示&#xff09;之間的交互形成了注意力匯聚&#xff1b; 注意力匯聚有選擇地聚合了值&#xff08;感官輸入&#xff09;以生成最終的輸出。 本節將介紹注意力匯聚的更多細節&#xff0c; 以便從宏觀上了解注意力機…

Lubuntu 23.10用戶可使用LXQt 1.4桌面

導讀在眾多 Lubuntu 用戶的要求下&#xff0c;Lubuntu 開發人員決定將 LXQt 1.4 桌面環境向后移植到最新的 Lubuntu 23.10 &#xff08;Mantic Minotaur&#xff09; 版本。 是的&#xff0c;您沒看錯&#xff0c;您現在可以使用官方的 Lubuntu Backports PPA&#xff08;個人軟…

黑馬點評筆記 分布式鎖

文章目錄 分布式鎖基本原理和實現方式對比Redis分布式鎖的實現核心思路實現分布式鎖版本一Redis分布式鎖誤刪情況說明解決Redis分布式鎖誤刪問題分布式鎖的原子性問題分布式鎖-Redission分布式鎖-redission可重入鎖原理分布式鎖-redission鎖重試和WatchDog機制分布式鎖-redissi…

01、Tensorflow實現二元手寫數字識別

01、Tensorflow實現二元手寫數字識別&#xff08;二分類問題&#xff09; 開始學習機器學習啦&#xff0c;已經把吳恩達的課全部刷完了&#xff0c;現在開始熟悉一下復現代碼。對這個手寫數字實部比較感興趣&#xff0c;作為入門的素材非常合適。 基于Tensorflow 2.10.0 1、…

pandas獲取年月第一天、最后一天,加一秒、加一天、午夜時間

Timestamp對象 # ts = pandas.Timestamp(year=2023, month=10, day=15, # hour=15, minute=5, second=50, tz="Asia/Shanghai") ts = pandas.Timestamp("2023-10-15 15:05:50", tz="Asia/Shanghai") # 2023-10-15 15:05…

數據丟失預防措施包括什么

數據丟失預防措施是保護企業或個人重要數據的重要手段。以下是一些有效的預防措施&#xff1a; 可以通過域之盾軟件來實現數據防丟失&#xff0c;具體的功能包括&#xff1a; https://www.yuzhidun.cn/https://www.yuzhidun.cn/ 1、備份數據 定期備份所有重要數據&#xff0…

unittest指南——不拼花哨,只拼實用

&#x1f4e2;專注于分享軟件測試干貨內容&#xff0c;歡迎點贊 &#x1f44d; 收藏 ?留言 &#x1f4dd; 如有錯誤敬請指正&#xff01;&#x1f4e2;交流討論&#xff1a;歡迎加入我們一起學習&#xff01;&#x1f4e2;資源分享&#xff1a;耗時200小時精選的「軟件測試」資…

centos7 docker開啟認證的遠程端口2376配置

docker開啟2375會存在安全漏洞 暴露了2375端口的Docker主機。因為沒有任何加密和認證過程&#xff0c;知道了主機IP以后&#xff0c;&#xff0c;任何人都可以管理這臺主機上的容器和鏡像&#xff0c;以前貪圖方便&#xff0c;只開啟了沒有認證的docker2375端口&#xff0c;后…

代碼隨想錄算法訓練營第五十三天|1143.最長公共子序列 1035.不相交的線 53. 最大子序和

文檔講解&#xff1a;代碼隨想錄 視頻講解&#xff1a;代碼隨想錄B站賬號 狀態&#xff1a;看了視頻題解和文章解析后做出來了 1143.最長公共子序列 class Solution:def longestCommonSubsequence(self, text1: str, text2: str) -> int:dp [[0] * (len(text2) 1) for _ i…

機器學習入門

簡介 https://huggingface.co/是一個AI社區&#xff0c;類似于github的地位。它開源了許多機器學習需要的基礎組件如&#xff1a;Transformers, Tokenizers等。 許多公司也在不斷地往上面提交新的模型和數據集&#xff0c;利用它你可以獲取以下內容&#xff1a; Datasets : 數…

hikariCP 數據庫連接池配置

springBoot 項目默認自動使用 HikariCP &#xff0c;HikariCP 的性能比 alibaba/druid快。 一、背景 系統中多少個線程在進行與數據庫有關的工作&#xff1f;其中&#xff0c;而多少個線程正在執行 SQL 語句&#xff1f;這可以讓我們評估數據庫是不是系統瓶頸。 多少個線程在…

基于法醫調查算法優化概率神經網絡PNN的分類預測 - 附代碼

基于法醫調查算法優化概率神經網絡PNN的分類預測 - 附代碼 文章目錄 基于法醫調查算法優化概率神經網絡PNN的分類預測 - 附代碼1.PNN網絡概述2.變壓器故障診街系統相關背景2.1 模型建立 3.基于法醫調查優化的PNN網絡5.測試結果6.參考文獻7.Matlab代碼 摘要&#xff1a;針對PNN神…

【學生成績管理】數據庫示例數據(MySQL代碼)

【學生成績管理】數據庫示例數據&#xff08;MySQL代碼&#xff09; 目錄 【學生成績管理】數據庫示例數據&#xff08;MySQL代碼&#xff09;一、創建數據庫二、創建dept&#xff08;學院&#xff09;表1、創建表結構2、添加示例數據3、查看表中數據 三、創建stu&#xff08;學…

35.邏輯運算符

目錄 一.什么是邏輯運算符 二.C語言中的邏輯運算符 三.邏輯表達式 三.視頻教程 一.什么是邏輯運算符 同時對倆個或者倆個以上的表達式進行判斷的運算符叫做邏輯運算符。 舉例&#xff1a;比如去網吧上網&#xff0c;只有年滿十八周歲并且帶身份證才可以上網。在C語言中如果…

為什么 Flink 拋棄了 Scala

曾經紅遍一時的Scala 想當初Spark橫空出世之后&#xff0c;Scala簡直就是語言界的一顆璀璨新星&#xff0c;惹得大家紛紛側目&#xff0c;連Kafka這類技術框架也選擇用Scala語言進行開發重構。 可如今&#xff0c;Flink竟然公開宣布棄用Scala 在Flink1.18的官方文檔里&#x…

國家開放大學的學子們 練習題 走起!

試卷代號&#xff1a;1356 高級英語聽說(2) 參考 試題 Section One (20 points, 2 points each) Directions: Listen to the conversation and fill in the blanks with the words you hear. Write the words on the Answer Sheet The conversation will be read TWICE. M…

windows11上安裝WSL

Windows電腦上要配置linux&#xff08;這里指ubuntu&#xff09;開發環境&#xff0c;主要有三種方式&#xff1a; 1&#xff09;在windows上裝個虛擬機&#xff08;比如vmware&#xff09;。缺點是vmware加載ubuntu后系統會變慢很多&#xff0c;而且需要通過samba來實現window…

使用Java連接Hbase

我在網上試 了很多代碼&#xff0c;但是大部分都不能實現&#xff0c;Java連接Hbase&#xff0c;一直報一個錯 java.util.concurrent.ExecutionException: org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode NoNode for /hbase/hbaseid一直也不清楚為什…