上一篇博文咱们介绍了ML.NET 的入门:html
本文咱们继续,研究分享一下聚类算法k-means.github
1、k-means算法简介算法
k-means算法是一种聚类算法,所谓聚类,即根据类似性原则,将具备较高类似度的数据对象划分至同一类簇,将具备较高相异度的数据对象划分至不一样类簇。
1. k-means算法的原理是什么样的?参考:https://baijiahao.baidu.com/s?id=1622412414004300046&wfr=spider&for=pcsql
k-means算法中的k表明类簇个数,means表明类簇内数据对象的均值(这种均值是一种对类簇中心的描述),所以,k-means算法又称为k-均值算法。机器学习
k-means算法是一种基于划分的聚类算法,以距离做为数据对象间类似性度量的标准,即数据对象间的距离越小,则它们的类似性越高,则它们越有可能在同一个类簇。ide
数据对象间距离的计算有不少种,k-means算法一般采用欧氏距离来计算数据对象间的距离。算法详细的流程描述以下:函数
2. k-means算法的优缺点:post
优势: 算法简单易实现; 学习
缺点: 须要用户事先指定类簇个数; 聚类结果对初始类簇中心的选取较为敏感; 容易陷入局部最优; 只能发现球形类簇;
接下来咱们说一下k-means算法的经典应用场景:鸢尾花
2、鸢尾花
首先,鸢尾花是一种植物,有四个典型的属性:
鸢尾花有三大品种setosa、versicolor 或 virginica ,每一个品种对应的以上四个属性各不相同。
鸢尾花数据集中一共包含了150条记录,每一个样本的包含它的萼片长度和宽度,花瓣的长度和宽度以及这个样本所属的具体品种。每一个品种的样本量为50条。
鸢尾花样本数据格式:
5.2,3.4,1.4,0.2,Iris-setosa 4.7,3.2,1.6,0.2,Iris-setosa 4.8,3.1,1.6,0.2,Iris-setosa 6.0,2.2,4.0,1.0,Iris-versicolor 6.1,2.9,4.7,1.4,Iris-versicolor 5.6,2.9,3.6,1.3,Iris-versicolor 5.7,2.5,5.0,2.0,Iris-virginica 5.8,2.8,5.1,2.4,Iris-virginica 6.4,3.2,5.3,2.3,Iris-virginica
上述数据中,第一列是鸢尾花花萼长度,第二列是鸢尾花花萼宽度,第三列是鸢尾花花瓣长度,第四列是鸢尾花花瓣宽度。
基于上述数据作机器学习、训练,造成一个模型。
3、ML.NET k-means
基于上述的场景,咱们先准备样本数据,https://github.com/dotnet/machinelearning/blob/master/test/data/iris.data
另存为iris.data文件,每一个属性逗号间隔。
而后,大体梳理了一下实现步骤:
好,让咱们开始搞吧:
1. 新建一个.Net Core Console Project
先看下用的VS的版本:
新建一个.Net Core Console的Project KMeansDemo
2. 添加Microsoft.ML nuget 1.2.0版本
将iris.data文件放到Project下的Data目录中,同时右键iris.data,设置为:始终复制
3. 添加鸢尾花数据、预测类实体类IrisData、ClusterPrediction
using System; using System.Collections.Generic; using System.Text; namespace KMeansDemo { using Microsoft.ML.Data; /// <summary> /// 鸢尾花数据 /// </summary> class IrisData { /// <summary> /// 鸢尾花花萼长度 /// </summary> [LoadColumn(0)] public float SepalLength; /// <summary> /// 鸢尾花花萼宽度 /// </summary> [LoadColumn(1)] public float SepalWidth; /// <summary> /// 鸢尾花花瓣长度 /// </summary> [LoadColumn(2)] public float PetalLength; /// <summary> /// 鸢尾花花瓣宽度 /// </summary> [LoadColumn(3)] public float PetalWidth; } }
using System; using System.Collections.Generic; using System.Text; namespace KMeansDemo { using Microsoft.ML.Data; public class ClusterPrediction { /// <summary> /// 预测的族群 /// </summary> [ColumnName("PredictedLabel")] public uint PredictedClusterId; [ColumnName("Score")] public float[] Distances; } }
4. 构造MLContext、从iris.data构造IDataView,采用Trainers.KMeans进行模型训练,造成模型文件:IrisClusteringModel.zip
在Main函数中,开始编码 ,首先添加引用
using Microsoft.ML;
声明样本数据文件和模型文件的文件路径
static readonly string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "iris.data"); static readonly string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "IrisClusteringModel.zip");
构造MLContext、IDataView,采用Trainer.KMeans进行模型训练,造成模型文件:IrisClusteringModel.zip
var mlContext = new MLContext(seed: 0); IDataView dataView = mlContext.Data.LoadFromTextFile<IrisData>(_dataPath, hasHeader: false, separatorChar: ','); string featuresColumnName = "Features"; var pipeline = mlContext.Transforms .Concatenate(featuresColumnName, "SepalLength", "SepalWidth", "PetalLength", "PetalWidth") .Append(mlContext.Clustering.Trainers.KMeans(featuresColumnName, numberOfClusters: 3)); var model = pipeline.Fit(dataView); using (var fileStream = new FileStream(_modelPath, FileMode.Create, FileAccess.Write, FileShare.Write)) { mlContext.Model.Save(model, dataView.Schema, fileStream); } Console.WriteLine("完成模型训练!"); Console.WriteLine("模型文件:"+ _modelPath);
5. 输入一个测试数据,进行预测。
输入一个测试数据,使用生成的模型,进行预测:
var predictor = mlContext.Model.CreatePredictionEngine<IrisData, ClusterPrediction>(model); var Setosa = new IrisData { SepalLength = 5.1f, SepalWidth = 3.5f, PetalLength = 1.4f, PetalWidth = 0.2f }; var prediction = predictor.Predict(Setosa); Console.WriteLine($"Cluster: {prediction.PredictedClusterId}"); Console.WriteLine($"Distances: {string.Join(" ", prediction.Distances)}"); Console.WriteLine("Press any key!");
所有的代码:
1 using Microsoft.ML; 2 using System; 3 using System.IO; 4 5 namespace KMeansDemo 6 { 7 class Program 8 { 9 static readonly string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "iris.data"); 10 static readonly string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "IrisClusteringModel.zip"); 11 12 static void Main(string[] args) 13 { 14 var mlContext = new MLContext(seed: 0); 15 IDataView dataView = mlContext.Data.LoadFromTextFile<IrisData>(_dataPath, hasHeader: false, separatorChar: ','); 16 string featuresColumnName = "Features"; 17 var pipeline = mlContext.Transforms 18 .Concatenate(featuresColumnName, "SepalLength", "SepalWidth", "PetalLength", "PetalWidth") 19 .Append(mlContext.Clustering.Trainers.KMeans(featuresColumnName, numberOfClusters: 3)); 20 var model = pipeline.Fit(dataView); 21 using (var fileStream = new FileStream(_modelPath, FileMode.Create, FileAccess.Write, FileShare.Write)) 22 { 23 mlContext.Model.Save(model, dataView.Schema, fileStream); 24 } 25 Console.WriteLine("完成模型训练!"); 26 Console.WriteLine("模型文件:"+ _modelPath); 27 28 //预测 29 var predictor = mlContext.Model.CreatePredictionEngine<IrisData, ClusterPrediction>(model); 30 31 var Setosa = new IrisData 32 { 33 SepalLength = 5.1f, 34 SepalWidth = 3.5f, 35 PetalLength = 1.4f, 36 PetalWidth = 0.2f 37 }; 38 39 var prediction = predictor.Predict(Setosa); 40 Console.WriteLine($"Cluster: {prediction.PredictedClusterId}"); 41 Console.WriteLine($"Distances: {string.Join(" ", prediction.Distances)}"); 42 Console.WriteLine("Press any key!"); 43 } 44 } 45 }
Run,看一下输出:
以上就是经过ML.NET 的KMeans算法,实现聚类。
上面的数据是一个监督学习的样本,同时是一个数值类型的数据,比较好奇的是,能不能对文本数据+值数据进行聚类,下一篇,咱们将继续完成文本数据+值数据的聚类分析。
以上,分享给你们。
周国庆
2019/7/14