ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

TensorFlow.NET机器学习入门【5】采用神经网络实现手写数字识别(MNIST)

2021-12-28 09:03:35  阅读:200  来源: 互联网

标签:layers keras int float height TensorFlow NET model MNIST


 从这篇文章开始,终于要干点正儿八经的工作了,前面都是准备工作。这次我们要解决机器学习的经典问题,MNIST手写数字识别。

首先介绍一下数据集。请首先解压:TF_Net\Asset\mnist_png.tar.gz文件

 文件夹内包括两个文件夹:training和validation,其中training文件夹下包括60000个训练图片validation下包括10000个评估图片,图片为28*28像素,分别放在0~9十个文件夹中。

程序总体流程和上一篇文章介绍的BMI分析程序基本一致,毕竟都是多元分类,有几点不一样。

1、BMI程序的特征数据(输入)为一维数组,包含两个数字,MNIST的特征数据为28*28的二位数组;

2、BMI程序的输出为3个,MNIST的输出为10个;

 

网络模型构建如下:

        private readonly int img_rows = 28;
        private readonly int img_cols = 28;
        private readonly int num_classes = 10;  // total classes
        /// <summary>
        /// 构建网络模型
        /// </summary>     
        private Model BuildModel()
        {
            // 网络参数          
            int n_hidden_1 = 128;    // 1st layer number of neurons.     
            int n_hidden_2 = 128;    // 2nd layer number of neurons.                                
            float scale = 1.0f / 255;

            var model = keras.Sequential(new List<ILayer>
            {
                keras.layers.InputLayer((img_rows,img_cols)),
                keras.layers.Flatten(),
                keras.layers.Rescaling(scale),
                keras.layers.Dense(n_hidden_1, activation:keras.activations.Relu),
                keras.layers.Dense(n_hidden_2, activation:keras.activations.Relu),
                keras.layers.Dense(num_classes, activation:keras.activations.Softmax)
            });

            return model;
        }

这个网络里用到了两个新方法,需要解释一下:

1、Flatten方法:这里表示拉平,把28*28的二维数组拉平为含784个数据的一维数组,因为二维数组无法进行运算;

2、Rescaling 方法:就是对每个数据乘以一个系数,因为我们从图片获取的数据为每一个位点的灰度值,其取值范围为0~255,所以乘以一个系数将数据缩小到1以内,以免后面运算时溢出。

 

其它基本和上一篇文章介绍的差不多,全部代码如下:

    /// <summary>
    /// 通过神经网络来实现多元分类
    /// </summary>
    public class NN_MultipleClassification_BMI
    {
        private readonly Random random = new Random(1);

        // 网络参数
        int num_features = 2; // data features       
        int num_classes = 3;  // total output .

        public void Run()
        {
            var model = BuildModel();
            model.summary();          

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();

            (NDArray train_x, NDArray train_y) = PrepareData(1000);
            model.compile(optimizer: keras.optimizers.Adam(0.001f),
              loss: keras.losses.SparseCategoricalCrossentropy(),
              metrics: new[] { "accuracy" });
            model.fit(train_x, train_y, batch_size: 128, epochs: 300);

            test(model);
        }

        /// <summary>
        /// 构建网络模型
        /// </summary>     
        private Model BuildModel()
        {
            // 网络参数          
            int n_hidden_1 = 64; // 1st layer number of neurons.     
            int n_hidden_2 = 64; // 2nd layer number of neurons.           

            var model = keras.Sequential(new List<ILayer>
            {
                keras.layers.InputLayer(num_features),
                keras.layers.Dense(n_hidden_1, activation:keras.activations.Relu),
                keras.layers.Dense(n_hidden_2, activation:keras.activations.Relu),
                keras.layers.Dense(num_classes, activation:keras.activations.Softmax)
            });

            return model;
        }

        /// <summary>
        /// 加载训练数据
        /// </summary>
        /// <param name="total_size"></param>    
        private (NDArray, NDArray) PrepareData(int total_size)
        {
            float[,] arrx = new float[total_size, num_features];
            int[] arry = new int[total_size];

            for (int i = 0; i < total_size; i++)
            {
                float weight = (float)random.Next(30, 100) / 100;
                float height = (float)random.Next(140, 190) / 100;
                float bmi = (weight * 100) / (height * height);

                arrx[i, 0] = weight;
                arrx[i, 1] = height;

                switch (bmi)
                {
                    case var x when x < 18.0f:
                        arry[i] = 0;
                        break;

                    case var x when x >= 18.0f && x <= 28.0f:
                        arry[i] = 1;
                        break;

                    case var x when x > 28.0f:
                        arry[i] = 2;
                        break;
                }
            }

            return (np.array(arrx), np.array(arry));
        }

        /// <summary>
        /// 消费模型
        /// </summary>      
        private void test(Model model)
        {
            int test_size = 20;
            for (int i = 0; i < test_size; i++)
            {
                float weight = (float)random.Next(40, 90) / 100;
                float height = (float)random.Next(145, 185) / 100;
                float bmi = (weight * 100) / (height * height);

                var test_x = np.array(new float[1, 2] { { weight, height } });
                var pred_y = model.Apply(test_x);

                Console.WriteLine($"{i}:weight={(float)weight} \theight={height} \tBMI={bmi:0.0} \tPred:{pred_y[0].numpy()}");
            }
        }
    }
View Code

另有两点说明:

1、由于对图片的读取比较耗时,所以我采用了一个方法,就是把读取到的数据序列化到一个二进制文件中,下次直接从二进制文件反序列化即可,大大加快处理速度。

2、我没有采用validation图片进行评估,只是简单选了20个样本测试了一下。

 

【相关资源】

 源码:Git: https://gitee.com/seabluescn/tf_not.git

项目名称:NN_MultipleClassification_MNIST

目录:查看TensorFlow.NET机器学习入门系列目录

标签:layers,keras,int,float,height,TensorFlow,NET,model,MNIST
来源: https://www.cnblogs.com/seabluescn/p/15592834.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有