C#中的深度學習(二):預處理識別硬幣的數據集

在文章中,咱們將對輸入到機器學習模型中的數據集進行預處理。數組

這裏咱們將對一個硬幣數據集進行預處理,以便之後在監督學習模型中進行訓練。在機器學習中預處理數據集一般涉及如下任務:dom

  1. 清理數據——經過對周圍數據的平均值或使用其餘策略來填補數據缺失或損壞形成的漏洞。
  2. 規範數據——將數據縮放值標準化到一個標準範圍,一般是0到1。具備普遍值範圍的數據可能會致使不規範,所以咱們將全部數據都放在一個公共範圍內。
  3. 一種熱編碼標籤——將數據集中對象的標籤或類編碼爲N維二進制向量,其中N是類的總數。數組元素都被設置爲0,除了與對象的類相對應的元素,它被設置爲1。這意味着在每一個數組中都有一個值爲1的元素。
  4. 將輸入數據集分爲訓練集和驗證集——訓練集被用於訓練模型,驗證集是用於檢查咱們的訓練結果。

這個例子咱們將使用Numpy.NET,它基本上是Python中流行的Numpy庫的.NET版本。機器學習

Numpy是一個專一於處理矩陣的庫。學習

爲了實現咱們的數據集處理器,咱們在PreProcessing文件夾中建立Utils類和DataSet類。Utils類合併了一個靜態Normalize 方法,以下所示:ui

public class Utils
   {
       public static NDarray Normalize(string path)
       {
           var colorMode = Settings.Channels == 3 ? "rgb" : "grayscale";
           var img = ImageUtil.LoadImg(path, color_mode: colorMode, target_size: (Settings.ImgWidth, Settings.ImgHeight));
           return ImageUtil.ImageToArray(img) / 255;
       }

   }

在這種方法中,咱們用給定的顏色模式(RGB或灰度)加載圖像,並將其調整爲給定的寬度和高度。而後咱們返回包含圖像的矩陣,每一個元素除以255。每一個元素除以255是使它們標準化,由於圖像中任何像素的值都在0到255之間,因此經過將它們除以255,咱們確保了新的範圍是0到1,包括255。編碼

咱們還在代碼中使用了一個Settings類。該類包含用於跨應用程序使用的許多常量。另外一個類DataSet,表示咱們將要用來訓練機器學習模型的數據集。這裏咱們有如下字段:spa

  1. _pathToFolder—包含圖像的文件夾的路徑。
  2. _extList—要考慮的文件擴展名列表。
  3. _labels—_pathToFolder中圖像的標籤或類。
  4. _objs -圖像自己,表示爲Numpy.NDarray。
  5. _validationSplit—用於將總圖像數劃分爲驗證集和訓練集的百分比,在本例中,百分比將定義驗證集與總圖像數之間的大小。
  6. NumberClasses-數據集中惟一類的總數。
  7. TrainX -訓練數據,表示爲Numpy.NDarray。
  8. TrainY -訓練標籤,表示爲Numpy.NDarray。
  9. ValidationX—驗證數據,表示爲Numpy.NDarray。
  10. ValidationY-驗證標籤,表示爲Numpy.NDarray。

這是DataSet類:rest

public class DataSet
    {
        private string _pathToFolder;
        private string[] _extList;
        private List<int> _labels;
        private List<NDarray> _objs;
        private double _validationSplit;
        public int NumberClasses { get; set; }
        public NDarray TrainX { get; set; }
        public NDarray ValidationX { get; set; }
        public NDarray TrainY { get; set; }
        public NDarray ValidationY { get; set; }

        public DataSet(string pathToFolder, string[] extList, int numberClasses, double validationSplit)
        {
            _pathToFolder = pathToFolder;
            _extList = extList;
            NumberClasses = numberClasses;
            _labels = new List<int>();
            _objs = new List<NDarray>();
            _validationSplit = validationSplit;
        }

        public void LoadDataSet()
        {
            // Process the list of files found in the directory.
            string[] fileEntries = Directory.GetFiles(_pathToFolder);
            foreach (string fileName in fileEntries)
                if (IsRequiredExtFile(fileName))
                    ProcessFile(fileName);

            MapToClassRange();
            GetTrainValidationData();
        }

        private bool IsRequiredExtFile(string fileName)
        {
            foreach (var ext in _extList)
            {
                if (fileName.Contains("." + ext))
                {
                    return true;
                }
            }

            return false;
        }

        private void MapToClassRange()
        {
            HashSet<int> uniqueLabels = _labels.ToHashSet();
            var uniqueLabelList = uniqueLabels.ToList();
            uniqueLabelList.Sort();

            _labels = _labels.Select(x => uniqueLabelList.IndexOf(x)).ToList();
        }

        private NDarray OneHotEncoding(List<int> labels)
        {
            var npLabels = np.array(labels.ToArray()).reshape(-1);
            return Util.ToCategorical(npLabels, num_classes: NumberClasses);
        }

        private void ProcessFile(string path)
        {
            _objs.Add(Utils.Normalize(path));
            ProcessLabel(Path.GetFileName(path));
        }

        private void ProcessLabel(string filename)
        {
            _labels.Add(int.Parse(ExtractClassFromFileName(filename)));
        }

        private string ExtractClassFromFileName(string filename)
        {
            return filename.Split('_')[0].Replace("class", "");
        }

        private void GetTrainValidationData()
        {
            var listIndices = Enumerable.Range(0, _labels.Count).ToList();
            var toValidate = _objs.Count * _validationSplit;
            var random = new Random();
            var xValResult = new List<NDarray>();
            var yValResult = new List<int>();
            var xTrainResult = new List<NDarray>();
            var yTrainResult = new List<int>();

            // Split validation data
            for (var i = 0; i < toValidate; i++)
            {
                var randomIndex = random.Next(0, listIndices.Count);
                var indexVal = listIndices[randomIndex];
                xValResult.Add(_objs[indexVal]);
                yValResult.Add(_labels[indexVal]);
                listIndices.RemoveAt(randomIndex);
            }

            // Split rest (training data)
            listIndices.ForEach(indexVal => 
            { 
                xTrainResult.Add(_objs[indexVal]);
                yTrainResult.Add(_labels[indexVal]);
            });

            TrainY = OneHotEncoding(yTrainResult);
            ValidationY = OneHotEncoding(yValResult);
            TrainX = np.array(xTrainResult);
            ValidationX = np.array(xValResult);
        }
}

下面是每一個方法的說明:code

  1. LoadDataSet()——類的主方法,咱們調用它來加載_pathToFolder中的數據集。它調用下面列出的其餘方法來完成此操做。
  2. IsRequiredExtFile(filename) - 檢查給定文件是否包含至少一個應該爲該數據集處理的擴展名(在_extList中列出)。
  3. MapToClassRange() -獲取數據集中惟一標籤的列表。
  4. ProcessFile(path) -使用Utils.Normalize方法對圖像進行規格化,並調用ProcessLabel方法。
  5. ProcessLabel(filename)——將ExtractClassFromFileName方法的結果添加爲標籤。
  6. ExtractClassFromFileName(filename) -從圖像的文件名中提取類。
  7. GetTrainValidationData()——將數據集劃分爲訓練子數據集和驗證子數據集。

在本系列中,咱們將使用https://cvl.tuwien.ac.at/research/cvl-databases/coin-image-dataset/上的硬幣圖像數據集。orm

要加載數據集,咱們能夠在控制檯應用程序的主類中包含如下內容:

var numberClasses = 60;
var fileExt = new string[] { ".png" };
var dataSetFilePath = @"C:/Users/arnal/Downloads/coin_dataset";
var dataSet = new PreProcessing.DataSet(dataSetFilePath, fileExt, numberClasses, 0.2);
dataSet.LoadDataSet();

咱們的數據如今能夠輸入到機器學習模型中。下一篇文章將介紹監督機器學習的基礎知識,以及訓練和驗證階段包括哪些內容。它是爲沒有AI經驗的讀者準備的。

歡迎關注個人公衆號,若是你有喜歡的外文技術文章,能夠經過公衆號留言推薦給我。

相關文章
相關標籤/搜索