基于Mahout實現K-Means聚類

需求分析

需要對數據集進行預處理,選擇合適的特征進行聚類分析,確定聚類的數量和初始中心點,調用Mahout提供的K-Means算法進行聚類計算,評估聚類結果的準確性和穩定性。同時,需要對Mahout的使用和參數調優進行深入學習和實踐,以保證聚類結果的有效性和可靠性。

系統實現

? ? 1.對實驗整體的理解:

????本次實驗,我們的目的是理解聚類的原理,并且掌握常見聚類的算法,以及掌握使用Mahout實現K-Means聚類分析算法的過程。

? ? ?2.實驗整體流程分析:

  • 創建項目,導入開發依賴包
  • 編寫工具類
  • 編寫聚類分析的代碼
  • 將聚類結果輸出
  • 評估聚類的效果

? ? ?3.準備工作:

  • 使用IDEA創建一個Maven項目:mahout_kmeans_demo

?

  • 修改pom.xml文件,導入開發MapReduce所需的Jar包
 <dependencies><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-hdfs</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-common</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-mapreduce-client-common</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-mapreduce-client-core</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.apache.mahout</groupId><artifactId>mahout-mr</artifactId><version>0.13.0</version></dependency><dependency><groupId>org.apache.mahout</groupId><artifactId>mahout-math</artifactId><version>0.13.0</version></dependency><dependency><groupId>org.apache.mahout</groupId><artifactId>mahout-hdfs</artifactId><version>0.13.0</version></dependency><dependency><groupId>org.apache.mahout</groupId><artifactId>mahout-integration</artifactId><version>0.13.0</version></dependency><dependency><groupId>org.apache.mahout</groupId><artifactId>mahout-examples</artifactId><version>0.13.0</version></dependency>
</dependencies>

下載相關依賴包

等待pom.xml文件不再出現錯誤即可?

  • 準備實驗數據并下載

  • 啟動Hadoop集群。

終端輸入start-all.sh

可以使用jps命令查看集群啟動情況。

? ? ?4.執行聚類過程:

  • 編寫工具類HdfsUtil,對HDFS的基本操作進行封裝
package com;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.mapred.JobConf;import java.io.IOException;
import java.net.URI;public class HdfsUtil {private static final String HDFS = "hdfs://master:9000/";private String hdfsPath;private Configuration conf;public HdfsUtil(Configuration conf) {this(HDFS, conf);}public HdfsUtil(String hdfs, Configuration conf) {this.hdfsPath = hdfs;this.conf = conf;}public static JobConf config() {JobConf conf = new JobConf(HdfsUtil.class);conf.setJobName("HdfsDAO");return conf;}public void mkdirs(String folder) throws IOException {Path path = new Path(folder);FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);if (!fs.exists(path)) {fs.mkdirs(path);System.out.println("Create: " + folder);}fs.close();}public void rmr(String folder) throws IOException {Path path = new Path(folder);FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);fs.deleteOnExit(path);System.out.println("Delete: " + folder);fs.close();}public void ls(String folder) throws IOException {Path path = new Path(folder);FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);FileStatus[] list = fs.listStatus(path);System.out.println("ls: " + folder);System.out.println("==========================================================");for (FileStatus f : list) {System.out.printf("name: %s, folder: %s, size: %d\n", f.getPath(), f.isDir(), f.getLen());}System.out.println("==========================================================");fs.close();}public void createFile(String file, String content) throws IOException {FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);byte[] buff = content.getBytes();FSDataOutputStream os = null;try {os = fs.create(new Path(file));os.write(buff, 0, buff.length);System.out.println("Create: " + file);} finally {if (os != null)os.close();}fs.close();}public void copyFile(String local, String remote) throws IOException {FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);fs.copyFromLocalFile(new Path(local), new Path(remote));System.out.println("copy from: " + local + " to " + remote);fs.close();}public void download(String remote, String local) throws IOException {Path path = new Path(remote);FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);fs.copyToLocalFile(path, new Path(local));System.out.println("download: from" + remote + " to " + local);fs.close();}public void cat(String remoteFile) throws IOException {Path path = new Path(remoteFile);FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);FSDataInputStream fsdis = null;System.out.println("cat: " + remoteFile);try {fsdis = fs.open(path);IOUtils.copyBytes(fsdis, System.out, 4096, false);} finally {IOUtils.closeStream(fsdis);fs.close();}}
}
  • 編寫KMeansMahout類,執行聚類過程
package com;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.mahout.clustering.Cluster;
import org.apache.mahout.clustering.canopy.CanopyDriver;
import org.apache.mahout.clustering.conversion.InputDriver;
import org.apache.mahout.clustering.kmeans.KMeansDriver;
import org.apache.mahout.common.HadoopUtil;
import org.apache.mahout.common.distance.EuclideanDistanceMeasure;
import org.apache.mahout.utils.clustering.ClusterDumper;public class KMeansMahout {private static final String HDFS = "hdfs://master:9000";public static void main(String[] args) throws Exception {String localFile = "/home/data/iris.dat";//  mahout輸出至HDFS的目錄String outputPath = HDFS + "/user/hdfs/kmeans/output";//  mahout的輸入目錄String inputPath = HDFS + "/user/hdfs/kmeans/input/";//  canopy算法的t1和t2double t1 = 2;double t2 = 1;//  收斂閥值double convergenceDelta = 0.5;//  最大迭代次數int maxIterations = 10;Path output = new Path(outputPath);Path input = new Path(inputPath);Configuration conf = new Configuration();HdfsUtil hdfs = new HdfsUtil(HDFS, conf);hdfs.rmr(inputPath);hdfs.mkdirs(inputPath);hdfs.copyFile(localFile, inputPath);hdfs.ls(inputPath);//  每次執行聚類前,刪除掉上一次的輸出目錄HadoopUtil.delete(conf, output);//  執行聚類run(conf, input, output, new EuclideanDistanceMeasure(), t1, t2, convergenceDelta, maxIterations);}private static void run(Configuration conf, Path input, Path output,EuclideanDistanceMeasure euclideanDistanceMeasure, double t1, double t2,double convergenceDelta, int maxIterations) throws Exception {Path directoryContainingConvertedInput = new Path(output, "data");System.out.println("Preparing  Input");//  將輸入文件序列化,并選取RandomAccessSparseVector作為保存向量的數據結構InputDriver.runJob(input, directoryContainingConvertedInput,"org.apache.mahout.math.RandomAccessSparseVector");System.out.println("Running  Canopy  to  get  initial  clusters");//  保存canopy的目錄Path canopyOutput = new Path(output, "canopies");//  執行Canopy聚類CanopyDriver.run(conf, directoryContainingConvertedInput, canopyOutput,euclideanDistanceMeasure, t1, t2, false, 0.0, false);System.out.println("Running  KMeans");//  執行k-means聚類,并使用canopy目錄KMeansDriver.run(conf, directoryContainingConvertedInput,new Path(canopyOutput, Cluster.INITIAL_CLUSTERS_DIR + "-final"),output, convergenceDelta, maxIterations, true, 0.0, false);System.out.println("run  clusterdumper");//  將聚類的結果輸出至HDFSClusterDumper clusterDumper = new ClusterDumper(new Path(output, "clusters-*-final"),new Path(output, "clusteredPoints"));clusterDumper.printClusters(null);}
}

在KmeansMahout類上點擊右鍵并執行程序

?執行結果在HDFS目錄中

? ? ?5.解析聚類結果:

  • 從Mahout的輸出目錄下提取出所要的信息

  • 編寫ClusterOutput類,解析聚類后結果
package com;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.SequenceFile;
import org.apache.mahout.clustering.classify.WeightedPropertyVectorWritable;
import org.apache.mahout.math.Vector;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;public class ClusterOutput {private static final String HDFS = "hdfs://master:9000";public static void main(String[] args) {try {//   需要被解析的mahout的輸出文件String clusterOutputPath = "/user/hdfs/kmeans/output";//   解析后的聚類結果,將輸出至本地磁盤String resultPath = "/home/data/result.txt";BufferedWriter bw;Configuration conf = new Configuration();conf.set("fs.default.name", HDFS);FileSystem fs = FileSystem.get(conf);SequenceFile.Reader reader = null;reader = new SequenceFile.Reader(fs, new Path(clusterOutputPath + "/clusteredPoints/part-m-00000"), conf);bw = new BufferedWriter(new FileWriter(new File(resultPath)));//   key為聚簇中心IDIntWritable key = new IntWritable();WeightedPropertyVectorWritable value = new WeightedPropertyVectorWritable();while (reader.next(key, value)) {//   得到向量Vector vector = value.getVector();String vectorValue = "";//   將向量各個維度拼接成一行,用\t分隔for (int i = 0; i < vector.size(); i++) {if (i == vector.size() - 1) {vectorValue += vector.get(i);} else {vectorValue += vector.get(i) + "\t";}}bw.write(key.toString() + "\t" + vectorValue + "\n\n");}bw.flush();reader.close();} catch (Exception e) {e.printStackTrace();}}
}

在ClusterOutput類上右鍵執行程序

?執行結果被保存在/home/data/result.txt文件中,打開終端執行以下命令

? ? ?6.評估聚類效果:

  • 編寫InterClusterDistances類,計算平均簇間距離
package com;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.Writable;
import org.apache.mahout.clustering.Cluster;
import org.apache.mahout.clustering.iterator.ClusterWritable;
import org.apache.mahout.common.distance.DistanceMeasure;
import org.apache.mahout.common.distance.EuclideanDistanceMeasure;import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class InterClusterDistances {private static final String HDFS = "hdfs://master:9000";public static void main(String[] args) throws Exception {String inputFile = HDFS + "/user/hdfs/kmeans/output";System.out.println("聚類結果文件地址:" + inputFile);Configuration conf = new Configuration();Path path = new Path(inputFile + "/clusters-2-final/part-r-00000");System.out.println("Input Path:" + path);FileSystem fs = FileSystem.get(path.toUri(), conf);List<Cluster> clusters = new ArrayList<Cluster>();SequenceFile.Reader reader = new SequenceFile.Reader(fs, path, conf);Writable key = (Writable) reader.getKeyClass().newInstance();ClusterWritable value = (ClusterWritable) reader.getValueClass().newInstance();while (reader.next(key, value)) {Cluster cluster = value.getValue();clusters.add(cluster);value = (ClusterWritable) reader.getValueClass().newInstance();}System.out.println("Cluster In Total:" + clusters.size());DistanceMeasure measure = new EuclideanDistanceMeasure();double max = 0;double min = Double.MAX_VALUE;double sum = 0;int count = 0;Set<Double> total = new HashSet<Double>();// 如果聚類的個數大于1才開始計算if (clusters.size() != 1 && clusters.size() != 0) {for (int i = 0; i < clusters.size(); i++) {for (int j = 0; j < clusters.size(); j++) {double d = measure.distance(clusters.get(i).getCenter(), clusters.get(j).getCenter());min = Math.min(d, min);max = Math.max(d, max);total.add(d);sum += d;count++;}}System.out.println("Maximum Intercluster Distance:" + max);System.out.println("Minimum Intercluster Distance:" + min);System.out.println("Average Intercluster Distance:" + sum / count);for (double d : total) {System.out.print("[" + d + "] ");}} else if (clusters.size() == 1) {System.out.println("只有一個類,無法判斷聚類質量");} else if (clusters.size() == 0) {System.out.println("聚類失敗");}}
}

同樣右鍵執行程序,得到下圖結果

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

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

相關文章

頂會ICLR2024論文Time-LLM:基于大語言模型的時間序列預測

文青松 松鼠AI首席科學家、AI研究院負責人 美國佐治亞理工學院(Georgia Tech)電子與計算機工程博士&#xff0c;人工智能、決策智能和信號處理方向專家&#xff0c;在松鼠AI、阿里、Marvell等公司超10年的技術和管理經驗&#xff0c;近100篇文章發表在人工智能相關的頂會與頂刊…

Cloud整合Zookeeper代替Eureka

微服務間通信重構與服務治理筆記-CSDN博客 Zookeeper是一個分布式協調工具,可以實現注冊中心功能 安裝Zookeeper 隨便 就用最新版本吧 進入Zookeeper 包目錄 cd /usr/local/develop/ 解壓 tar -zxvf apache-zookeeper-3.9.1-bin.tar.gz -C /usr/local/develop 進入配置文件…

uniapp 獲取頁面來源

獲取當前頁面棧的實例&#xff0c;以數組形式按棧的順序給出&#xff0c;數組中的元素為頁面實例&#xff0c;第一個元素為首頁&#xff0c;最后一個元素為當前頁面。 let pages getCurrentPages(); if (pages.length > 1) { // 若頁面棧長度大于1則表示不止一個頁面被打開…

在 JavaScript 中用 var, let, 以及 const 有什么差別?什么時候該用哪個?

「在 JavaScript 中用 var, let, 以及 const 有什么差別?」是在前端、JavaScript 面試中常見的考題。在面試時可以先大方向地列點說出異同之處,然后再針對每一個點進行深入說明。以下是以第一人稱撰寫的參考擬答。 var, let, 以及 const 都是在 JavaScript 用來做變數宣告的…

前端導入導出

1、將后端excel二進制文件導出excel下載 import { read, utils, writeFileXLSX } from "xlsx";const useExportExcel (excelData: string, fileName: string) > {const wb read(excelData);const ws wb.Sheets[wb.SheetNames[0]];// 從工作表生成數據行const …

Android 將圖片網址url轉化為bitmap

1. 圖片網址url轉化為bitmap 1.1. 方法一 通過 HttpURLConnection 請求 要使用一個線程去訪問&#xff0c;因為是網絡請求&#xff0c;這是一個一步請求&#xff0c;不能直接返回獲取&#xff0c;要不然永遠為null&#xff0c;在這里得到BitMap之后記得使用Hanlder或者EventBu…

React之useState hook

實現useState js實現一個useState&#xff0c;簡單的原理就是賦值然后更新渲染&#xff0c;大概偽代碼如下&#xff1a; function useState(initValue) {let value initValue;function setValue(v) {if (typeof v "function") {value v(initValue);} else {value…

StarRocks實戰——首汽約車實時數倉實踐

目錄 前言 一、引入背景 二、OLAP引擎選型 三、架構演進 四、實時數倉構建 五、業務實踐價值未來規劃 原文大佬的這篇首汽約車實時數倉實踐有借鑒意義&#xff0c;這里摘抄下來用作學習和知識沉淀。 前言 首汽約車&#xff08;以下簡稱“首約”&#xff09;是首汽集團打造…

物體檢測-系列教程20:YOLOV5 源碼解析10 (Model類前向傳播、forward_once函數、_initialize_biases函數)

&#x1f60e;&#x1f60e;&#x1f60e;物體檢測-系列教程 總目錄 有任何問題歡迎在下面留言 本篇文章的代碼運行界面均在Pycharm中進行 本篇文章配套的代碼資源已經上傳 點我下載源碼 14、Model類 14.2 前向傳播 def forward(self, x, augmentFalse, profileFalse):if augm…

MySQL 8.0 架構 之錯誤日志文件(Error Log)(2)

文章目錄 MySQL 8.0 架構 之錯誤日志文件&#xff08;Error Log&#xff09;&#xff08;2&#xff09;MySQL錯誤日志文件&#xff08;Error Log&#xff09;錯誤日志相關參數log_errorlog_error_services過濾器&#xff08;Filter Error Log Components&#xff09;寫入/接收器…

Vue+SpringBoot打造大學計算機課程管理平臺

目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 實驗課程檔案模塊2.2 實驗資源模塊2.3 學生實驗模塊 三、系統設計3.1 用例設計3.2 數據庫設計3.2.1 實驗課程檔案表3.2.2 實驗資源表3.2.3 學生實驗表 四、系統展示五、核心代碼5.1 一鍵生成實驗5.2 提交實驗5.3 批閱實…

131. 分割回文串(力扣LeetCode)

文章目錄 131. 分割回文串題目描述回溯代碼 131. 分割回文串 題目描述 給你一個字符串 s&#xff0c;請你將 s 分割成一些子串&#xff0c;使每個子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正著讀和反著讀都一樣的字符串。 示例 1&#xff1a; 輸入&#xf…

Android 架構MVI、MVVM、MVC、MVP

目錄 一、MVC&#xff08;Model-View-Controller&#xff09; 二、 MVP&#xff08;Model-View-Presenter&#xff09; 三. MVVM&#xff08;Model-View-ViewModel&#xff09; 四. MVI&#xff08;Model-View-Intent&#xff09; 五.MVI簡單實現 先簡單了解一下MVC、MVP和…

索引使用規則6——單列索引聯合索引

1、單列索引 單列索引&#xff1a;即一個索引只包含單個列 舉個例子 1.1、給phone和那么建立索引 create index index_name on tb_qianzhui(name); create index index_phone on tb_qianzhui(phone);1.2、查詢發現可能的索引有好幾個&#xff0c;但是最終選擇了phone的索引…

軟考 系統分析師系列知識點之詳細調查(2)

接前一篇文章&#xff1a;軟考 系統分析師系列知識點之詳細調查&#xff08;1&#xff09; 所屬章節&#xff1a; 第10章. 系統分析 第2節. 詳細調查 在系統規劃階段&#xff0c;通過初步調查&#xff0c;系統分析師已經對企業的組織結構、系統功能等有了大致的了解。但是&…

蘿卜大雜燴 | 提高數據科學工作效率的 8 個 Python 庫

本文來源公眾號“蘿卜大雜燴”&#xff0c;僅用于學術分享&#xff0c;侵權刪&#xff0c;干貨滿滿。 原文鏈接&#xff1a;提高數據科學工作效率的 8 個 Python 庫 在進行數據科學時&#xff0c;可能會浪費大量時間編碼并等待計算機運行某些東西。所以我選擇了一些 Python 庫…

Vue3中的Hooks詳解

vue3帶來了Composition API&#xff0c;其中Hooks是其重要組成部分。之前我寫過一篇關于vue3 hooks的文章比較簡單 Vue3從入門到刪庫 第十一章&#xff08;自定義hooks&#xff09; 所以本文將深入探討Vue3中Hooks&#xff0c;幫助你在Vue3開發中更加得心應手。 一、Vue3 Hoo…

貪吃蛇(C語言)步驟講解

一&#xff1a;文章大概 使用C語言在windows環境的控制臺中模擬實現經典小游戲 實現基本功能&#xff1a; 1.貪吃蛇地圖繪制 2.蛇吃食物的功能&#xff08;上&#xff0c;下&#xff0c;左&#xff0c;右方向控制蛇的動作&#xff09; 3.蛇撞墻死亡 4.計算得分 5.蛇身加…

[C語言]——C語言常見概念(1)

目錄 一.C語言是什么、 二.C語言的歷史和輝煌 三.編譯器的選擇&#xff08;VS2022為例&#xff09; 1.編譯和鏈接 2.編譯器的對比 3.VS2022 的優缺點 四.VS項目和源文件、頭文件介紹 五.第?個C語言程序 ??????? 一.C語言是什么、 ?和?交流使?的是?然語?&…

【python】爬取鏈家二手房數據做數據分析【附源碼】

一、前言、 在數據分析和挖掘領域中&#xff0c;網絡爬蟲是一種常見的工具&#xff0c;用于從網頁上收集數據。本文將介紹如何使用 Python 編寫簡單的網絡爬蟲程序&#xff0c;從鏈家網上海二手房頁面獲取房屋信息&#xff0c;并將數據保存到 Excel 文件中。 二、效果圖&#…