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

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

本示例演示通过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调用效率真的很高

相关推荐
thinkMoreAndDoMore2 小时前
深度学习(3)-TensorFlow入门(梯度带)
人工智能·深度学习·tensorflow
晴天_QingTian2 小时前
.NET8入门:13.ASP.NET Core MVC
asp.net·mvc·.net
升讯威在线客服系统4 小时前
如何通过 Docker 在没有域名的情况下快速上线客服系统
java·运维·前端·python·docker·容器·.net
五VV17 小时前
Note25021902_TIA Portal V18 WinCC BCA Ed 需要.NET 3.5 SP1
.net
刀客1231 天前
python3+TensorFlow 2.x(六)自编码器
人工智能·python·tensorflow
code_shenbing1 天前
.NET MVC实现电影票管理
mvc·.net
shepherd枸杞泡茶1 天前
第3章 3.3日志 .NET Core日志 NLog使用教程
c#·asp.net·.net·.netcore
时光追逐者2 天前
推荐几款开源免费的 .NET MAUI 组件库
microsoft·开源·c#·.net·.net core·maui
蜗牛沐雨2 天前
如何生成美观且内容稳定的PDF文档:从基础到进阶的全方案解析
人工智能·pdf·tensorflow