当前位置: 首页 > news >正文

.Net 9下使用Tensorflow.net---DNN_Eager

.Net 9下使用Tensorflow.net---DNN_Eager

  • 1、创建控制台应用项目
  • 2、导入Tensorflow.net等依赖
  • 3、开始示例
    • 引入类库
    • 定义神经网络训练权重
      • 定义一个DNN的模型
      • 定义损失函数
      • 定义一个运行优化器
      • 定义一个获取最终模型预测准确率的函数
      • 开始调用以上准备好的函数
        • 1、加载MNIST数据,进行预处理
        • 2、初始化网络权重变量x,b,初始化优化器
        • 3、训练模型,并且在测试集上进行性能评估
        • 4、console的主函数中调用以上代码,获取输出结果

本示例演示通过Tensorflow.net训练的基本操作步骤:
一、数据加载,预处理
二、选择网络训练模型(本例使用 Eager的 DNN)
三、定义损失函数、优化函数
四、训练模型且通过优化函数优化网络权重参数
五、评估结果

1、创建控制台应用项目

首先,创建一个控制台应用:
在这里插入图片描述
选择.net9
在这里插入图片描述
其他选项先忽略,直接创建

2、导入Tensorflow.net等依赖

通过nuget包管理器,导入如下依赖:
1、TensorFlow.Net
2、TensorFlow.keras – keras是一个神经网络的重要的API,在Tensorflow中用于加载数据、获取模型、生成优化器,生成损失函数等重要作用。
3、SciSharp.TensorFlow.Redist – 这是TensorFlow的核心包,封装了TensorFlow的核心函数,分为GPU和CPU两个版本,具有跨平台、高性能的特点。
4、NumSharp–.net环境下实现的python中的numpy库,用于科学计算
在这里插入图片描述

3、开始示例

引入类库

using Tensorflow;
using Tensorflow.Keras.Optimizers;
using static Tensorflow.Binding;
using static Tensorflow.KerasApi;
using Tensorflow.Keras.Engine;

定义神经网络训练权重

说明:
//MNIST数据集还是一个手写数字识别的数据集,用于入门和测试的首选
//这个数据集包含70000张28x28像素的手写灰度数字图像,分为10类,分别对应0到9的数字。具体来说,数据集分为四个部分:

‌训练集图像‌:包含60000张训练图像。
‌训练集标签‌:包含60000个训练标签。
‌测试集图像‌:包含10000张测试图像。
‌测试集标签‌:包含10000个测试标签‌
在这里插入图片描述

 int num_classes = 10;
 //本示例中使用MNIST数字数据集作为数据集,该数据集中按字符(0--9)分类,所以分了10类
 

 int num_features = 784;
//该数据集对应的图像像素尺寸为28*28=784


//--以下为训练使用参数--//
 float learning_rate = 0.001f;//学习率
 int training_steps = 1000;//训练轮数
 int batch_size = 256; //训练集批次大小
 int display_step = 100;//训练集数据显示周期

 //--以下定义了神经网络相关的参数,因为本示例使用DNN模型,定义两层的神经网络
 int n_dnn_1 = 128; //隐藏层1的神经元数量
 int n_dnn_2 = 256;// 隐藏层2的神经元数量

 IDatasetV2 train_data; //MNIST数据集
 //定义训练变量
 IVariableV1 w_dnn1, w_dnn2, wout, b_dnn1, b_dnn2, bout;
 float accuracy_dnn_test = 0f; //测试机准确率输出

定义一个DNN的模型

本示例借助Eager方式(暂不使用Keras方式)搭建神经网络中经典的DNN模型,采用了两个隐藏层。
该函数作用其实还是遵循线性函数输出y=wout*x+bout的模式,得到最终的输出层的结果,
函数中包含几个关键因素:
1、layer_1第一层隐藏层
2、layer_2第二层隐藏层
3、激活函数tf.nn.sigmoid():
sigmoid函数的数学表达式为:
在这里插入图片描述
作用是该函数将输入映射到(0, 1)区间,常用于二分类问题中表示概率。
除此之外,还有 tf.nn.softmax()激活函数:
在这里插入图片描述
作用是:Softmax函数将每个元素映射到(0, 1)区间,并且所有元素的和为1,表示概率分布。

Tensor Dnn_neural_net(Tensor x)
{

    //隐藏层1采用128个神经元
    var layer_1=tf.add(tf.matmul(x,w_dnn1.AsTensor()),b_dnn1.AsTensor());
    //使用Sigmoid激活函数,增加层输出的非线性特征
    layer_1=tf.nn.sigmoid(layer_1);            
    var layer_2=tf.add(tf.matmul(layer_1, w_dnn2.AsTensor()),b_dnn2.AsTensor());
    layer_2=tf.nn.sigmoid(layer_2);

    //输出层的神经元数量和标签类型数量相同
    var out_layer=tf.matmul(layer_2,wout.AsTensor())+bout.AsTensor();

    return tf.nn.softmax(out_layer);
}

定义损失函数

本示例是一个分类的训练,所以损失函数依旧使用交叉熵损失函数
说明:
1、y_pred参数获取以上模型的输出层结果,y_true参数获取训练集中的标签结果,
2、tf.one_hot()处理函数,
该函数作用是将输入的数值转换为one-hot编码的输出。
one-hot编码指的是:将张量中的变量映射为0,1这种二进制的值,并且张量中只有一个变量是1,其余全为0,本例做的是仍然是分类训练,所以适合使用。
tf.clip_by_value(),函数的作用是将张量y_pred中的数值限制在一个范围之内。(避免一些运算错误)

Tensor cross_entroy(Tensor y_pred, Tensor y_true)
{ 
   y_true=tf.one_hot(y_true,depth:num_classes);
   y_pred = tf.clip_by_value(y_pred, 1e-9f, 1.0f);
   return tf.reduce_mean(-tf.reduce_sum(y_true * tf.math.log(y_pred)));
}

定义一个运行优化器

TensorFlow具备自动求导的机制,该函数中,首先创建梯度记录器,自动跟踪神经网络中的梯度,自动求导并进行梯度下降和网络权重变化的更新优化。
说明:
1、参数:optimizer :梯度下降函数,本例中将会传入 kerasAPI中 keras.optimizers.SGD()
x:训练数据集,y:训练标签集,trainble_variables:需要通过该函数优化的网络权重参数
2、tf.GradientTape() 获取梯度计数器
3、g.gradient() 计算梯度

void run_optimization(IOptimizer optimizer,Tensor x,Tensor y, IVariableV1[] trainble_variables) 
{
    using var g = tf.GradientTape();
    var pred = Dnn_neural_net(x);
    var loss=cross_entroy(pred, y);

    //计算梯度
    var gradients = g.gradient(loss, trainble_variables);

    //利用梯度下降函数更新模型权重和偏置项
    var a = zip(gradients, trainble_variables.Select(x => x as ResourceVariable));
    optimizer.apply_gradients(zip(gradients, trainble_variables.Select(x => x as ResourceVariable)));

}

定义一个获取最终模型预测准确率的函数

说明:
tf.reduce_mean 函数用于计算张量y_pred 沿着指定的数轴的均值,axis=-1表示不限制维度,0表示第一维度,即是行,1表示第二维度,即是列

 Tensor accuary(Tensor y_pred, Tensor y_true)
 { 
     var correct_prediction=tf.equal(tf.arg_max(y_pred,1), tf.cast(y_true,tf.int64));
     return tf.reduce_mean(tf.cast(correct_prediction,tf.float32),axis:-1);
 }

开始调用以上准备好的函数

1、加载MNIST数据,进行预处理

预处理步骤为 加载–>展平(通过resharp函数获取想要的维度)–>归一化(数据格式上需要统一)–>转为可以处理的格式(本例子中转化为Dataset格式)–>复制

        public void FNN()
        {
 //准备基本数据
            var ((x_train, y_train), (x_test, y_test)) = keras.datasets.mnist.load_data();//下载或加载本地MNIST
            //步骤一:进行数据的整理,包括 1、数据集的维度--shape,2、数据集的数据格式--float
            (x_train, x_test) = (x_train.reshape((-1, num_features)), x_test.reshape((-1, num_features)));//展平输入数据
            (x_train, x_test) = (x_train / 255f, x_test / 255f);//归一化
            //步骤二:进一步初始化,该函数作用很广泛:就是将数据集切片化,将一个张量切片为多个张量
            //后续通过 tensorflow的API进行处理 from_tensor_slices--将数据集切片化,将一个张量切片为多个张量
            //repeat()--复制,shuffle--打乱顺序,batch--按参数分成对应的批次,
            train_data = tf.data.Dataset.from_tensor_slices(x_train, y_train);
            train_data = train_data.repeat()
                .shuffle(5000)
                .batch(batch_size)
                .prefetch(1)
                .take(training_steps);
              //以上预处理结束,获取到 后续要用到 训练集
}
2、初始化网络权重变量x,b,初始化优化器

说明:以下是通过随机函数得到隐藏层1、隐藏层2、并且定义 权重参数w,偏移值b的初始化值,
后续通过 优化函数进行迭代优化,
注意:dnn1和dnn2 需要满足矩阵的乘法要求。dnn1的列数=dnn2的行数

        public void FNN()
        {
            //接上 上一段代码 :  以上预处理结束,获取到 后续要用到 训练集
            //随机初始化网络权重变量并打包成数组,方便后续在梯度求导中作为参数
            var random_normal = tf.random_normal_initializer();         
            
            w_dnn1 = tf.Variable(random_normal.Apply(new InitializerArgs((num_features, n_dnn_1),dtype:TF_DataType.TF_FLOAT)));
            w_dnn2 = tf.Variable(random_normal.Apply(new InitializerArgs((n_dnn_1, n_dnn_2), dtype: TF_DataType.TF_FLOAT)));
            wout = tf.Variable(random_normal.Apply(new InitializerArgs((n_dnn_2, num_classes), dtype: TF_DataType.TF_FLOAT)));

            b_dnn1 = tf.Variable(tf.zeros(n_dnn_1));
            b_dnn2 = tf.Variable(tf.zeros(n_dnn_2));
            bout=tf.Variable(tf.zeros(num_classes));
            var trainable_variables=new IVariableV1[]{w_dnn1, w_dnn2, wout,b_dnn1,b_dnn2,bout};

            //采用keras的随机梯度下降优化器
            var optimizer = keras.optimizers.SGD(learning_rate); 
3、训练模型,并且在测试集上进行性能评估
        public void FNN()
        {
         //接上 上一段代码 :
			foreach (var (step, (batch_x, batch_y)) in enumerate(train_data, 1))
			{
			    run_optimization(optimizer, batch_x, batch_y, trainable_variables);
			    if (step % display_step == 0)
			    {
			        var pred = Dnn_neural_net(batch_x);
			        var loss=cross_entroy(pred, batch_y);
			        var acc=accuary(pred, batch_y);
			        print($"step:{step},loss:{(float)loss},accuray:{acc}");
			    }
			}
			
			{ 
			    var pred= Dnn_neural_net(x_test);
			    accuracy_dnn_test=(float)accuary(pred, y_test);
			    print($"Test Accuracy:{accuracy_dnn_test}");
			}
	}
4、console的主函数中调用以上代码,获取输出结果
DNN_Eager eager = new DNN_Eager();
eager.FNN();

输出如下:
在这里插入图片描述
最终输出预测准确率为0.858,率低于0.863,基本合格。但是.net调用效率真的很高

相关文章:

  • RabbitMQ死信队列
  • 「云原生」「云原生应用的构建与部署」
  • 阻抗和电阻
  • Linux提权之docker提权(十三) 链接第八篇完整版
  • 如何在docker上部署java服务
  • 学习路之PHP --TP6异步执行功能 (无需安装任何框架)
  • Linux 日志系统·
  • 蓝桥杯手把手教你备战(C/C++ B组)(最全面!最贴心!适合小白!)
  • Linux提权之详细总结版(完结)
  • (八)趣学设计模式 之 装饰器模式!
  • 【阮一峰】19.类型工具
  • 用AI写游戏3——用java实现坦克大战游戏1
  • Springboot使用Milvus的基本操作
  • Linux红帽:RHCSA认证知识讲解(三)Linux基础指令与Vim编辑器的使用
  • css实现左右切换平滑效果
  • Gurobi 并行计算的一些问题
  • Rk3568驱动开发_点亮led灯代码完善(手动挡)_6
  • 博客系统笔记总结 2( Linux 相关)
  • 集合与反射
  • 计算机视觉(opencv-python)入门之常见图像处理基本操作(待补充)
  • 网上做一道题2元的网站/合肥网络科技有限公司
  • 手机网站制作行业排行/天堂网长尾关键词挖掘网站
  • 增城网络推广/杭州网站优化公司哪家好
  • 青岛的网站设计公司/今天重大新闻
  • 营销型网站设计文章/seo课程培训机构