讓我們一起ML吧(一)聚類分析


 

讓我們一起ML(Make Love Machine Learning)吧!

ML.NET是微軟推出的一個免費的開源跨平台機器學習框架,可用於生成自定義機器學習解決方案並將其集成到 .NET 應用程序。ML.NET當前最新版本為0.7,目前處於預覽狀態,本文中用到的例子來自於微軟的官方教程,但隨時可能更改,請注意版本變更造成的例子無法運行的狀況。

 

准備工作

你需要一個安裝了.NET Core 的VS2017 15.6或更高版本。

 

了解問題

在本篇中我們將對鳶尾花的數據進行聚類分析,並通過訓練出來的模型來判斷給出的數據是哪種鳶尾花。

此問題的本質即基於花卉特征將鳶尾花數據歸入不同的組。 這些特征包括:花萼的長度和寬度以及花瓣的長度和寬度。 此教程假設每朵花的類型都是未知的。 需通過這些特征了解數據集的結構,並預測數據實例與此結構的擬合程度。

 

淺解算法

本例中選擇K-Means算法解決問題,K-Means算法是個什么算法?不懂也沒關系,簡單給你介紹一下(我也是剛查的,想詳細了解的自己wiki百科),K-Means算法簡單來說就是給出n個數據,然后指定一個K(這個K是個大於1小於n的正整數),n個數據就被分成K堆,這個堆被稱為聚類,再給出一個樣例數據,用同樣的方法將樣例分入其中某一聚類完成聚類分析。

 

這K堆或者K類或者K組(K個聚類)如何分呢?假設n個數據為二維平面中的點 P1(x1,y1),P2(x2,y2),...,Pn(xn,yn) ,從n個點中隨機選出K個點,這K個點被稱作形心(有人也翻譯成質心),然后計算其他n-K個點與這K個形心的歐氏距離(即兩點之間的直線距離,歐氏即歐幾里得),一個點距離哪個形心的距離最短即被分到哪個組,然后循環更換形心再次計算,直到K個組中的點都不再變化,至此n個點即被分為K組數據(K個聚類)。K-Means算法的優點是簡單易行,只用指定一個參數K,難點是K值的選取。如果對算法有興趣可以移步這里看看如何實現算法。

 

 示例代碼

本示例所有官方教程源代碼都在這里,我的示例與官方示例略有不同。

  • 打開VS創建一個控制台應用(.NET Core)命名為IrisClustering
  • 安裝Microsoft.ML Nuget包(當前最新版本為0.7)
  • 在項目根路徑下創建一個Data文件夾,從這里下載鳶尾花的數據保存到剛建好的Data文件夾下命名為iris_data.txt,點擊iris_data.txt 將文件屬性中復制到輸出目錄項的值改為如果較新則復制

 

在項目中添加實體類IrisData.cs如下:

 1 using Microsoft.ML.Runtime.Api;
 2 
 3 namespace IrisClustering
 4 {
 5     public class IrisData
 6     {
 7         [Column("0")]
 8         public float SepalLength;
 9 
10         [Column("1")]
11         public float SepalWidth;
12 
13         [Column("2")]
14         public float PetalLength;
15 
16         [Column("3")]
17         public float PetalWidth;
18     }
19 
20     public class ClusterPrediction
21     {
22         [ColumnName("PredictedLabel")]
23         public uint PredictedClusterId;
24 
25         [ColumnName("Score")]
26         public float[] Distances;
27     }
28 }

 其中IrisData類是輸入數據類,通過使用Column屬性在數據集文件中指定源列的索引。

ClusterPrediction類表示應用到IrisData實例的聚類分析模型的輸出。通過使用ColumnName屬性將PredictedClusterIdDistances 字段分別綁定至PredicatedLabelScore 列。

  • PredictedLabel 包含所預測群集的ID。
  • Score 包含一個數組,這個數組中的數即為與群集形心之間歐氏距離的平方。這個數組的長度等於群集數(K-Means算法中的K值)。

接下來在Program.cs中添加預測模型的訓練方法並通過Main方法訓練預測模型並預測給出的樣例屬於哪種鳶尾花

 1 using System;
 2 using System.IO;
 3 using System.Threading.Tasks;
 4 using Microsoft.ML.Legacy;
 5 using Microsoft.ML.Legacy.Data;
 6 using Microsoft.ML.Legacy.Trainers;
 7 using Microsoft.ML.Legacy.Transforms;
 8 
 9 namespace IrisClustering
10 {
11     public static class Program
12     {
13         //數據文件路徑
14         static readonly string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "iris_data.txt");
15         //預測模型保存路徑
16         static readonly string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "IrisClusteringModel.zip");
17         //預測模型訓練方法
18         private static PredictionModel<IrisData, ClusterPrediction> Train()
19        {
20             var pipeline = new LearningPipeline
21             {
22                 new TextLoader(_dataPath).CreateFrom<IrisData>(separator: ','), //加載數據
23                 new ColumnConcatenator( //指定數據列名
24                 "Features",      //特征 學習算法將通過ColumnConcatenator類將數據轉化為特征列的值
25                 "SepalLength",   //花萼長度
26                 "SepalWidth",    //花萼寬度
27                 "PetalLength",   //花瓣長度
28                 "PetalWidth"),   //花瓣寬度
29                 new KMeansPlusPlusClusterer() { K = 3 }  //指定K-Means算法,這里因為數據中已經給出三個分類,所以我們指定K值為3
30             };
31             var model = pipeline.Train<IrisData, ClusterPrediction>();
32             return model;
33         }
34 
35         //在Main方法前加async關鍵字是c#7.1及以后的新功能 
36         //應當右鍵單擊項目名稱(IrisClustering) 屬性->生成->高級->語言版本 中將語言改為c#7.1
37         private static async Task Main(string[] args)
38         {
39             PredictionModel<IrisData, ClusterPrediction> model = Train();
40             await model.WriteAsync(_modelPath);
41             var prediction = model.Predict(TestIrisData.Setosa);
42             Console.WriteLine($"Cluster:{prediction.PredictedClusterId}");
43             Console.WriteLine($"Distances:{string.Join(" ",prediction.Distances)}");
44             Console.Read();
45         }
46     }
47 }

被用於預測的樣例數據如下TestIrisData.cs

 1 namespace IrisClustering
 2 {
 3     static class TestIrisData
 4     {
 5         internal static readonly IrisData Setosa = new IrisData
 6         {
 7             SepalLength = 5.1f,
 8             SepalWidth = 3.5f,
 9             PetalLength = 1.4f,
10             PetalWidth = 0.2f
11         };
12     }
13 }

 

程序運行結果如下:

PS:我多次運行后發現結果並不一定是同一個,如果你運行的結果與我不同也可能是正確的。另外PredictedClusterId並不是Distances數組的下標。

最后讓我們看一下訓練后得到的預測模型是什么東西吧

 

IrisClusteringModel.zip解壓后得到DataLoaderModel和TrainingInfo兩個文件夾,其中TrainingInfo中只有一個version.txt保存了一個版本號,而DataLoaderModel中存在數個名為model.key的二進制文件,這就是我們通過ML.NET訓練出來的模型。

 

這樣你就使用ML.NET完成了一次聚類分析。

******************************

歡迎隨意打賞


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM