使用Java實現K-Means聚類算法

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

?

關于K-Means介紹很多,還不清楚可以查一些相關資料。

個人對其實現步驟簡單總結為4步:

1.選出k值,隨機出k個起始質心點。?
?
2.分別計算每個點和k個起始質點之間的距離,就近歸類。?
?
3.最終中心點集可以劃分為k類,分別計算每類中新的中心點。?
?

4.重復2,3步驟對所有點進行歸類,如果當所有分類的質心點不再改變,則最終收斂。

?

下面貼代碼。

1.入口類,基本讀取數據源進行訓練然后輸出。 數據源文件和源碼后面會補上。

package com.hyr.kmeans;import au.com.bytecode.opencsv.CSVReader;import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;public class KmeansMain {public static void main(String[] args) throws IOException {// 讀取數據源文件CSVReader reader = new CSVReader(new FileReader("src/main/resources/data.csv")); // 數據源FileWriter writer = new FileWriter("src/main/resources/out.csv");List<String[]> myEntries = reader.readAll(); // 6.8, 12.6// 轉換數據點集List<Point> points = new ArrayList<Point>(); // 數據點集for (String[] entry : myEntries) {points.add(new Point(Float.parseFloat(entry[0]), Float.parseFloat(entry[1])));}int k = 6; // K值int type = 1;KmeansModel model = Kmeans.run(points, k, type);writer.write("====================   K is " + model.getK() + " ,  Object Funcion Value is " + model.getOfv() + " ,  calc_distance_type is " + model.getCalc_distance_type() + "   ====================\n");int i = 0;for (Cluster cluster : model.getClusters()) {i++;writer.write("====================   classification " + i + "   ====================\n");for (Point point : cluster.getPoints()) {writer.write(point.toString() + "\n");}writer.write("\n");writer.write("centroid is " + cluster.getCentroid().toString());writer.write("\n\n");}writer.close();}}

?

2.最終生成的模型類,也就是最終訓練好的結果。K值,計算的點距離類型以及object function value值。

package com.hyr.kmeans;import java.util.ArrayList;
import java.util.List;public class KmeansModel {private List<Cluster> clusters = new ArrayList<Cluster>();private Double ofv;private int k;  // k值private int calc_distance_type;public KmeansModel(List<Cluster> clusters, Double ofv, int k, int calc_distance_type) {this.clusters = clusters;this.ofv = ofv;this.k = k;this.calc_distance_type = calc_distance_type;}public List<Cluster> getClusters() {return clusters;}public Double getOfv() {return ofv;}public int getK() {return k;}public int getCalc_distance_type() {return calc_distance_type;}
}

?

3.數據集點對象,包含點的維度,代碼里只給出了x軸,y軸二維。以及點的距離計算。通過類型選擇距離公式。給出了幾種常用的距離公式。

package com.hyr.kmeans;public class Point {private Float x;     // x 軸private Float y;    // y 軸public Point(Float x, Float y) {this.x = x;this.y = y;}public Float getX() {return x;}public void setX(Float x) {this.x = x;}public Float getY() {return y;}public void setY(Float y) {this.y = y;}@Overridepublic String toString() {return "Point{" +"x=" + x +", y=" + y +'}';}/*** 計算距離** @param centroid 質心點* @param type* @return*/public Double calculateDistance(Point centroid, int type) {// TODODouble result = null;switch (type) {case 1:result = calcL1Distance(centroid);break;case 2:result = calcCanberraDistance(centroid);break;case 3:result = calcEuclidianDistance(centroid);break;}return result;}/*計算距離公式*/private Double calcL1Distance(Point centroid) {double res = 0;res = Math.abs(getX() - centroid.getX()) + Math.abs(getY() - centroid.getY());return res / (double) 2;}private double calcEuclidianDistance(Point centroid) {return Math.sqrt(Math.pow((centroid.getX() - getX()), 2) + Math.pow((centroid.getY() - getY()), 2));}private double calcCanberraDistance(Point centroid) {double res = 0;res = Math.abs(getX() - centroid.getX()) / (Math.abs(getX()) + Math.abs(centroid.getX()))+ Math.abs(getY() - centroid.getY()) / (Math.abs(getY()) + Math.abs(centroid.getY()));return res / (double) 2;}@Overridepublic boolean equals(Object obj) {Point other = (Point) obj;if (getX().equals(other.getX()) && getY().equals(other.getY())) {return true;}return false;}
}

?

4.訓練后最終得到的分類。包含該分類的質點,屬于該分類的點集合該分類是否收斂。

package com.hyr.kmeans;import java.util.ArrayList;
import java.util.List;public class Cluster {private List<Point> points = new ArrayList<Point>(); // 屬于該分類的點集private Point centroid; // 該分類的中心質點private boolean isConvergence = false;public Point getCentroid() {return centroid;}public void setCentroid(Point centroid) {this.centroid = centroid;}@Overridepublic String toString() {return centroid.toString();}public List<Point> getPoints() {return points;}public void setPoints(List<Point> points) {this.points = points;}public void initPoint() {points.clear();}public boolean isConvergence() {return isConvergence;}public void setConvergence(boolean convergence) {isConvergence = convergence;}
}

?

5.K-Meams訓練類。按照上面所說四個步驟不斷進行訓練。

package com.hyr.kmeans;import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class Kmeans {/*** kmeans** @param points 數據集* @param k      K值* @param k      計算距離方式*/public static KmeansModel run(List<Point> points, int k, int type) {// 初始化質心點List<Cluster> clusters = initCentroides(points, k);while (!checkConvergence(clusters)) { // 所有分類是否全部收斂// 1.計算距離對每個點進行分類// 2.判斷質心點是否改變,未改變則該分類已經收斂// 3.重新生成質心點initClusters(clusters); // 重置分類中的點classifyPoint(points, clusters, type);// 計算距離進行分類recalcularCentroides(clusters); // 重新計算質心點}// 計算目標函數值Double ofv = calcularObjetiFuncionValue(clusters);KmeansModel kmeansModel = new KmeansModel(clusters, ofv, k, type);return kmeansModel;}/*** 初始化k個質心點** @param points 點集* @param k      K值* @return 分類集合對象*/private static List<Cluster> initCentroides(List<Point> points, Integer k) {List<Cluster> centroides = new ArrayList<Cluster>();// 求出數據集的范圍(找出所有點的x最小、最大和y最小、最大坐標。)Float max_X = Float.NEGATIVE_INFINITY;Float max_Y = Float.NEGATIVE_INFINITY;Float min_X = Float.POSITIVE_INFINITY;Float min_Y = Float.POSITIVE_INFINITY;for (Point point : points) {max_X = max_X < point.getX() ? point.getX() : max_X;max_Y = max_Y < point.getY() ? point.getY() : max_Y;min_X = min_X > point.getX() ? point.getX() : min_X;min_Y = min_Y > point.getY() ? point.getY() : min_Y;}System.out.println("min_X" + min_X + ",max_X:" + max_X + ",min_Y" + min_Y + ",max_Y" + max_Y);// 在范圍內隨機初始化k個質心點Random random = new Random();// 隨機初始化k個中心點for (int i = 0; i < k; i++) {float x = random.nextFloat() * (max_X - min_X) + min_X;float y = random.nextFloat() * (max_Y - min_Y) + min_X;Cluster c = new Cluster();Point centroide = new Point(x, y); // 初始化的隨機中心點c.setCentroid(centroide);centroides.add(c);}return centroides;}/*** 重新計算質心點** @param clusters*/private static void recalcularCentroides(List<Cluster> clusters) {for (Cluster c : clusters) {if (c.getPoints().isEmpty()) {c.setConvergence(true);continue;}// 求均值,作為新的質心點Float x;Float y;Float sum_x = 0f;Float sum_y = 0f;for (Point point : c.getPoints()) {sum_x += point.getX();sum_y += point.getY();}x = sum_x / c.getPoints().size();y = sum_y / c.getPoints().size();Point nuevoCentroide = new Point(x, y); // 新的質心點if (nuevoCentroide.equals(c.getCentroid())) { // 如果質心點不再改變 則該分類已經收斂c.setConvergence(true);} else {c.setCentroid(nuevoCentroide);}}}/*** 計算距離,對點集進行分類** @param points   點集* @param clusters 分類* @param type     計算距離方式*/private static void classifyPoint(List<Point> points, List<Cluster> clusters, int type) {for (Point point : points) {Cluster masCercano = clusters.get(0); // 該點計算距離后所屬的分類Double minDistancia = Double.MAX_VALUE; // 最小距離for (Cluster cluster : clusters) {Double distancia = point.calculateDistance(cluster.getCentroid(), type); // 點和每個分類質心點的距離if (minDistancia > distancia) { // 得到該點和k個質心點最小的距離minDistancia = distancia;masCercano = cluster; // 得到該點的分類}}masCercano.getPoints().add(point); // 將該點添加到距離最近的分類中}}private static void initClusters(List<Cluster> clusters) {for (Cluster cluster : clusters) {cluster.initPoint();}}/*** 檢查收斂** @param clusters* @return*/private static boolean checkConvergence(List<Cluster> clusters) {for (Cluster cluster : clusters) {if (!cluster.isConvergence()) {return false;}}return true;}/*** 計算目標函數值** @param clusters* @return*/private static Double calcularObjetiFuncionValue(List<Cluster> clusters) {Double ofv = 0d;for (Cluster cluster : clusters) {for (Point point : cluster.getPoints()) {int type = 1;ofv += point.calculateDistance(cluster.getCentroid(), type);}}return ofv;}
}

?

最終訓練結果:

====================   K is 6 ,  Object Funcion Value is 21.82857036590576 ,  calc_distance_type is 3   ====================
====================   classification 1   ====================
Point{x=3.5, y=12.5}centroid is Point{x=3.5, y=12.5}====================   classification 2   ====================
Point{x=6.8, y=12.6}
Point{x=7.8, y=12.2}
Point{x=8.2, y=11.1}
Point{x=9.6, y=11.1}centroid is Point{x=8.1, y=11.75}====================   classification 3   ====================
Point{x=4.4, y=6.5}
Point{x=4.8, y=1.1}
Point{x=5.3, y=6.4}
Point{x=6.6, y=7.7}
Point{x=8.2, y=4.5}
Point{x=8.4, y=6.9}
Point{x=9.0, y=3.4}centroid is Point{x=6.671428, y=5.2142863}====================   classification 4   ====================
Point{x=6.0, y=19.9}
Point{x=6.2, y=18.5}
Point{x=5.3, y=19.4}
Point{x=7.6, y=17.4}centroid is Point{x=6.275, y=18.800001}====================   classification 5   ====================
Point{x=0.8, y=9.8}
Point{x=1.2, y=11.6}
Point{x=2.8, y=9.6}
Point{x=3.8, y=9.9}centroid is Point{x=2.15, y=10.225}====================   classification 6   ====================
Point{x=6.1, y=14.3}centroid is Point{x=6.1, y=14.3}

?

代碼下載地址:

http://download.csdn.net/download/huangyueranbbc/10267041

github:?

https://github.com/huangyueranbbc/KmeansDemo?

?

轉載于:https://my.oschina.net/u/4074730/blog/3007470

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

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

相關文章

在PowerShell中顯示高級進度條

如果你需要編寫一些PowerShell腳本&#xff0c;尤其在處理一些相對復雜的任務時&#xff0c;你可能希望添加進度條的功能&#xff0c;以便隨時可以了解進展情況。Write-Progress 這個命令可以幫助你完成簡單的需求&#xff0c;請參考官方文檔即可&#xff0c;但下圖一個示例&am…

當檢測到運動時如何自動打開門燈

If it’s dark out and someone comes to your door, you probably can’t see them unless your porch light is on. Furthermore, if a potential burglar approaches your front door, a motion light can help scare them away. 如果天黑了&#xff0c;有人進了您的門&…

分布式系統的那些事兒(六) - SOA架構體系

有十來天沒發文了&#xff0c;實在抱歉&#xff01;最近忙著錄視頻&#xff0c;同時也做了個開源的后臺管理系統LeeCX&#xff0c;目前比較簡單&#xff0c;但是后續會把各類技術完善。具體可以點擊“原文鏈接”。 那么今天繼續說分布式系統的那些事。 我們現在動不動就講分布式…

rest_framework07:權限/頻率/過濾組件/排序/異常處理封裝Response對象

權限 寫一個類&#xff0c;繼承BasePermission&#xff0c;如果通過返回True&#xff0c;否則False 這里需要配合認證使用&#xff0c;否則沒有user_type屬性。 from rest_framework.permissions import BasePermissionclass UserPermission(BasePermission):def has_permis…

在阿里,我們如何管理測試環境

為什么80%的碼農都做不了架構師&#xff1f;>>> 作者&#xff1a;林帆&#xff08;花名金戟&#xff09;&#xff0c;阿里巴巴研發效能部技術專家 相關閱讀&#xff1a;在阿里&#xff0c;我們如何管理代碼分支 前言 阿里的許多實踐看似簡單&#xff0c;背后卻蘊涵…

數據庫_7_SQL基本操作——表操作

SQL基本操作——表操作 建表的過程就是聲明列的過程。 表與字段是密不可分的。 一、新增數據表 create table [if not exists] 表名( 字段名字 數據類型, 字段名字 數據類型 -- 最后一行不需要逗號 )[表選項];if not exists:如果表名不存在&#xff0c;那么就創建&#xff0c;…

EXT.NET 更改lable和Text的顏色

2019獨角獸企業重金招聘Python工程師標準>>> &#xfeff;&#xfeff; <ext:TextField ID"TextField1" " runat"server" FieldLabel"編號" LabelWidth"60" LabelAlign"Left" LabelStyle"color:red…

rest_framework08:分頁器/根據ip進行頻率限制

分頁器 # 查詢所有&#xff0c;才需要分頁 from rest_framework.generics import ListAPIView# 內置三種分頁方式 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPaginationPageNumberPaginationclass MyPageNumberPagination(Pag…

NYOJ746 整數劃分

該題是一道區間DP的題目&#xff0c;做了幾道區間DP&#xff0c;說起來高大上&#xff0c;也就是DP在區間內的形式而已&#xff0c;核心思想還是要想到轉移->規劃。 題意是在n位數中間加m個稱號&#xff0c;使得最終乘積最大。 狀態轉移方程如下&#xff1a; dp[ i ][ j ]ma…

Spring MVC實現文件下載

方法一&#xff1a; RequestMapping("/testHttpMessageDown")public ResponseEntity<byte[]> download(HttpServletRequest request) throws IOException {File file new File(request.getSession().getServletContext().getClassLoader().getResource("…

[MobX State Tree數據組件化開發][3]:選擇正確的types.xxx

?系列文章目錄? 定義Model時&#xff0c;需要正確地定義props中各字段的類型。本文將對MST提供的各種類型以及類型的工廠方法進行簡單的介紹&#xff0c;方便同學們在定義props時挑選正確的類型。 前提 定義props之前&#xff0c;有一個前提是&#xff0c;你已經明確地知道這…

ubuntu系統備份和還原_如何使用Aptik在Ubuntu中備份和還原您的應用程序和PPA

ubuntu系統備份和還原If you need to reinstall Ubuntu or if you just want to install a new version from scratch, wouldn’t it be useful to have an easy way to reinstall all your apps and settings? You can easily accomplish this using a free tool called Apti…

rest_framework09:自動生成接口文檔(簡略)

coreapi 參考 python/Django-rest-framework框架/8-drf-自動生成接口文檔 | Justin-劉清政的博客 Swagger 很多語言都支持&#xff0c;看起來用的人多。 參考fastapi的界面

AppDomainManager后門的實現思路

本文講的是AppDomainManager后門的實現思路&#xff0c;0x00 前言從Casey SmithsubTee學到的一個技巧&#xff1a;針對.Net程序&#xff0c;通過修改AppDomainManager能夠劫持.Net程序的啟動過程。 如果劫持了系統常見.Net程序如powershell.exe的啟動過程&#xff0c;向其添加…

所有內耗,都有解藥。

你是否常常會有這種感覺&#xff1a;剛開始接手一件事情&#xff0c;腦海中已經幻想出無數個會發生的問題&#xff0c;心里也已篤定自己做不好&#xff1b;即使別人不經意的一句話&#xff0c;也會浮想一番&#xff0c;最終陷入自我懷疑&#xff1b;隨便看到點什么&#xff0c;…

ABAP 通過sumbit調用另外一個程序使用job形式執行-簡單例子

涉及到兩個程序&#xff1a; ZTEST_ZUMA02 (主程序)ZTEST_ZUMA(被調用的程序&#xff0c;需要以后臺job執行)"ztest_zuma 的代碼DATA col TYPE i VALUE 0.DO 8 TIMES.MESSAGE JOB HERE TYPE S.ENDDO.程序ZTEST_ZUMA是在程序ZTEST_ZUMA02中以job的形式調用的&#xff0c;先…

那些影響深遠的彎路

靜兒最近反思很多事情&#xff0c;不僅是當時做錯了。錯誤定式形成的思維習慣對自己的影響比事情本身要大的多。經常看到周圍的同事&#xff0c;非常的羨慕。他們都很聰明、有自己的方法。就算有些同事工作經驗相對少一些&#xff0c;但是就像在廢墟上創建一個輝煌的城市要比在…

如何使用APTonCD備份和還原已安裝的Ubuntu軟件包

APTonCD is an easy way to back up your installed packages to a disc or ISO image. You can quickly restore the packages on another Ubuntu system without downloading anything. APTonCD是將安裝的軟件包備份到光盤或ISO映像的簡便方法。 您可以在不下載任何東西的情況…

rest_framework10:base64補充/修改頭像

base64補充 # base64 變長&#xff0c;可反解 # md5 固定長度&#xff0c;不可反解# base64 編碼和解碼 import base64 import json dic{name:test,age:18} dic_strjson.dumps(dic)retbase64.b64encode(dic_str.encode(utf-8)) print(ret)# 解碼 ret2base64.b64decode(ret) pri…

next_permutation(全排列算法)

next_permutation(全排列算法) STL提供了兩個用來計算排列組合關系的算法&#xff0c;分別是next_permutation和prev_permutation。 首先解釋下全排列&#xff0c;顧名思義&#xff0c;即一組數的全部排列的情況。 next_permutation 即列出一組數的全部排列情況&#xff0c;不過…