機器學習框架ML.NET學習筆記【2】入門之二元分類

1、準備樣本html

接上一篇文章提到的問題:根據一我的的身高、體重來判斷一我的的身材是否很好。但我手上沒有樣本數據,只能僞造一批數據了,僞造的數據比較標準,用來學習仍是蠻合適的。git

下面是我用來僞造數據的代碼:github

           string Filename = "./figure_full.csv";
            StreamWriter sw = new StreamWriter(Filename, false);
            sw.WriteLine("Height,Weight,Result");

            Random random = new Random();
            float height, weight;
            Result result;

            for (int i = 0; i < 2000; i++)
            {
                height = random.Next(150, 195);
                weight = random.Next(70, 200);

                if (height > 170 && weight < 120)
                    result = Result.Good;
                else
                    result = Result.Bad;
               
                sw.WriteLine($"{height},{weight},{(int)result}");
            }


   enum Result
    {
        Bad=0,
        Good=1
    }
View Code

制形成功後的數據以下:算法

 用記事本打開:數組

 

2、源碼框架

數據準備好了,咱們就用準備好的數據進行學習了,先貼出所有代碼,而後再逐一解釋:dom

namespace BinaryClassification_Figure
{
    class Program
    {
        static readonly string DataPath = Path.Combine(Environment.CurrentDirectory, "Data", "figure_full.csv");
        static readonly string ModelPath = Path.Combine(Environment.CurrentDirectory, "Data", "FastTree_Model.zip");

        static void Main(string[] args)
        {
            TrainAndSave();
            LoadAndPrediction();

            Console.WriteLine("Press any to exit!");
            Console.ReadKey();
        }

        static void TrainAndSave()
        {
            MLContext mlContext = new MLContext();           

            //準備數據
            var fulldata = mlContext.Data.LoadFromTextFile<FigureData>(path: DataPath, hasHeader: true, separatorChar: ',');           
            var trainTestData = mlContext.Data.TrainTestSplit(fulldata,testFraction:0.2);
            var trainData = trainTestData.TrainSet;
            var testData = trainTestData.TestSet;

            //訓練 
            IEstimator<ITransformer> dataProcessPipeline = mlContext.Transforms.Concatenate("Features", new[] { "Height", "Weight" })
                .Append(mlContext.Transforms.NormalizeMeanVariance(inputColumnName: "Features", outputColumnName: "FeaturesNormalizedByMeanVar"));
            IEstimator<ITransformer> trainer = mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Result", featureColumnName: "FeaturesNormalizedByMeanVar");
            IEstimator<ITransformer> trainingPipeline = dataProcessPipeline.Append(trainer); 
            ITransformer model = trainingPipeline.Fit(trainData);

            //評估
            var predictions = model.Transform(testData);
            var metrics = mlContext.BinaryClassification.Evaluate(data: predictions, labelColumnName: "Result", scoreColumnName: "Score");
            PrintBinaryClassificationMetrics(trainer.ToString(), metrics);

            //保存模型
            mlContext.Model.Save(model, trainData.Schema, ModelPath);
            Console.WriteLine($"Model file saved to :{ModelPath}");
        }      

        static void LoadAndPrediction()
        {
            var mlContext = new MLContext();
            ITransformer model = mlContext.Model.Load(ModelPath, out var inputSchema);
            var predictionEngine = mlContext.Model.CreatePredictionEngine<FigureData, FigureDatePredicted>(model);

            FigureData test = new FigureData();
            test.Weight = 115;
            test.Height = 171;

            var prediction = predictionEngine.Predict(test);
            Console.WriteLine($"Predict Result :{prediction.PredictedLabel}");
        }      
    }

    public class FigureData
    {
        [LoadColumn(0)]
        public float Height { get; set; }

        [LoadColumn(1)]
        public float Weight { get; set; }

        [LoadColumn(2)]
        public bool Result { get; set; }       
    }

    public class FigureDatePredicted : FigureData
    {
        public bool PredictedLabel;
    }
}
View Code

 

3、對代碼的解釋機器學習

一、讀取樣本數據ide

        string DataPath = Path.Combine(Environment.CurrentDirectory, "Data", "figure_full.csv");
        MLContext mlContext = new MLContext();          

            //準備數據
            var fulldata = mlContext.Data.LoadFromTextFile<FigureData>(path: DataPath, hasHeader: true, separatorChar: ',');           
            var trainTestData = mlContext.Data.TrainTestSplit(fulldata,testFraction:0.2);
            var trainData = trainTestData.TrainSet;
            var testData = trainTestData.TestSet;    

 LoadFromTextFile<FigureData>(path: DataPath, hasHeader: true, separatorChar: ',')用來讀取數據到DataView函數

FigureData類是和樣本數據對應的實體類,LoadColumn特性指示該屬性對應該條數據中的第幾個數據。

    public class FigureData
    {
        [LoadColumn(0)]
        public float Height { get; set; }

        [LoadColumn(1)]
        public float Weight { get; set; }

        [LoadColumn(2)]
        public bool Result { get; set; }       
    }

 path:文件路徑

hasHeader:文本文件是否包含標題

separatorChar:用來分割數據的字符,咱們用的是逗號,經常使用的還有跳格符‘\t’

TrainTestSplit(fulldata,testFraction:0.2)用來隨機分割數據,分紅學習數據和評估用的數據,一般狀況,若是數據較多,測試數據取20%左右比較合適,若是數據量較少,測試數據取10%左右比較合適。

若是不經過分割,準備兩個數據文件,一個用來訓練、一個用來評估,效果是同樣的。

 

二、訓練 

            //訓練 
            IEstimator<ITransformer> dataProcessPipeline = mlContext.Transforms.Concatenate("Features", new[] { "Height", "Weight" })
                .Append(mlContext.Transforms.NormalizeMeanVariance(inputColumnName: "Features", outputColumnName: "FeaturesNormalizedByMeanVar"));
            IEstimator<ITransformer> trainer = mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Result", featureColumnName: "FeaturesNormalizedByMeanVar");
            IEstimator<ITransformer> trainingPipeline = dataProcessPipeline.Append(trainer); 
            ITransformer model = trainingPipeline.Fit(trainData);

  IDataView這個數據集就相似一個表格,它的列(Column)是能夠動態增長的,一開始咱們經過LoadFromTextFile得到的數據集包括:Height、Weight、Result這幾個列,在進行訓練以前,咱們還要對這個數據集進行處理,造成符合咱們要求的數據集。

Concatenate這個方法是把多個列,組合成一個列,由於二元分類的機器學習算法只接收一個特徵列,因此要把多個特徵列(Height、Weight)組合成一個特徵列Features(組合的結果應該是個float數組)。

NormalizeMeanVariance是對列進行歸一化處理,這裏輸入列爲:Features,輸出列爲:FeaturesNormalizedByMeanVar,歸一化的含義見本文最後一節介紹。

數據集就緒之後,就要選擇學習算法,針對二元分類,咱們選擇了快速決策樹算法FastTree,咱們須要告訴這個算法特徵值放在哪一個列裏面(FeaturesNormalizedByMeanVar),標籤值放在哪一個列裏面(Result)。

連接數據處理管道和算法造成學習管道,將數據集中的數據逐一經過學習管道進行學習,造成機器學習模型。

有了這個模型咱們就能夠經過它進行實際應用了。但咱們通常不會如今就使用這個模型,咱們須要先評估一下這個模型,而後把模型保存下來。之後應用時再經過文件讀取出模型,而後進行應用,這樣就不用等待學習的時間了,一般學習的時間都比較長。

 

三、評估 

            //評估
            var predictions = model.Transform(testData);
            var metrics = mlContext.BinaryClassification.Evaluate(data: predictions, labelColumnName: "Result");
            PrintBinaryClassificationMetrics(trainer.ToString(), metrics);

  評估的過程就是對測試數據集進行批量轉換(Transform),轉換過的數據集會多出一個「PredictedLabel」的列,這個就是模型評估的結果,逐條將這個結果和實際結果(Result)進行比較,就最終造成了效果評估數據。

咱們能夠打印這個評估結果,查看其成功率,通常成功率大於97%就是比較好的模型了。因爲咱們僞造的數據比較整齊,因此咱們此次評估的成功率爲100%。

注意:評估過程不會提高現有的模型能力,只是對現有模型的一種檢測。

 

四、保存模型 

//保存模型
           string ModelPath = Path.Combine(Environment.CurrentDirectory, "Data", "FastTree_Model.zip");
            mlContext.Model.Save(model, trainData.Schema, ModelPath);
            Console.WriteLine($"Model file saved to :{ModelPath}");

 這個沒啥好解釋的。

 

五、讀取模型並建立預測引擎 

           //讀取模型
            var mlContext = new MLContext();
            ITransformer model = mlContext.Model.Load(ModelPath, out var inputSchema);

            //建立預測引擎
            var predictionEngine = mlContext.Model.CreatePredictionEngine<FigureData, FigureDatePredicted>(model);

 建立預測引擎的功能和Transform是相似的,不過Transform是處理批量記錄,這裏只處理一條數據,並且這裏的輸入輸出是實體對象,定義以下:

   public class FigureData
    {
        [LoadColumn(0)]
        public float Height { get; set; }

        [LoadColumn(1)]
        public float Weight { get; set; }

        [LoadColumn(2)]
        public bool Result { get; set; }       
    }

    public class FigureDatePredicted : FigureData
    {
        public bool PredictedLabel;
    }

 因爲預測結果裏放在「PredictedLabel」字段中,因此FigureDatePredicted類必需要包含PredictedLabel屬性,目前FigureDatePredicted 類是從FigureData類繼承的,因爲咱們只用到PredictedLabel屬性,因此不繼承也沒有關係,若是繼承的話,後面要調試的話會方便一點。

 

六、應用 

            FigureData test = new FigureData
            {
                Weight = 115,
                Height = 171
            };

            var prediction = predictionEngine.Predict(test);
            Console.WriteLine($"Predict Result :{prediction.PredictedLabel}");

 這部分代碼就比較簡單,test是咱們要預測的對象,預測後打印出預測結果。

 

4、附:數據歸一化

 機器學習的算法中通常會有不少的乘法運算,當運算的數字過大時,很容易在屢次運算後溢出,爲了防止這種狀況,就要對數據進行歸一化處理。歸一化的目標就是把參與運算的特徵數變爲(0,1)或(-1,1)之間的浮點數,常見的處理方式有:min-max標準化、Log函數轉換、對數函數轉換等。

咱們此次採用的是平均方差歸一化方法。

 

5、資源

源碼下載地址:https://github.com/seabluescn/Study_ML.NET

工程名稱:BinaryClassification_Figure

點擊查看機器學習框架ML.NET學習筆記系列文章目錄

相關文章
相關標籤/搜索