您的位置:首页 > 教育 > 培训 > 网络营销推广的公司_php原生态开发公司网站_优秀营销软文范例500字_品牌营销推广要怎么做

网络营销推广的公司_php原生态开发公司网站_优秀营销软文范例500字_品牌营销推广要怎么做

2025/5/18 17:04:03 来源:https://blog.csdn.net/zhang_adrian/article/details/145964280  浏览:    关键词:网络营销推广的公司_php原生态开发公司网站_优秀营销软文范例500字_品牌营销推广要怎么做
网络营销推广的公司_php原生态开发公司网站_优秀营销软文范例500字_品牌营销推广要怎么做

.Net 9下使用Tensorflow.net---DNN_使用卷积模型识别手写数字

  • 一、创建项目,并导入各依赖项
  • 二、初始化
    • 1、添加命名空间
    • 2、直接在窗口类中定义变量
    • 3、在窗口类构造函数中初始化后续用到的变量
    • 4、加载MNIST数据集并归一化
  • 三、创建模型
    • 1、layers.Conv2D,本例中使用该二维卷积层函数,说明下几个重要的参数:
    • 2、layers.MaxPooling2D 该层称为 二维最大池化层
    • 3、layers.Flatten 展平层
  • 四、训练模型,保存模型
    • 1、model.fit() 该函数就是 训练创建好的模型
    • 2、model.evaluate()评估函数,评估模型的损失度和精度
    • 3、model.save_weights()将模型作为文件保存,后面可以加载使用
  • 五、通过MNIST测试集验证效果
  • 六、通过手写数字来验证效果
    • 1、在picturebox上实现手写数字,
      • 1)、定义变量
      • 2)窗体构造方法中定义事件
      • 3)通过事件实现picturebox绘图
      • 4)定义工具类,将手绘的图片orginal.bmp实现 灰度转化和归一化
      • 5)测试效果

在这个例子里,使用了Tensorflow.net中的典型的卷积网络神经模型,加载MNIST数据集,经过训练,可以识别手写的数字,正确率可以达到 95%左右。
本例的基本步骤为
1、导入数据集并初始化获得训练集、测试集;
2、创建CNN模型,定义各神经网络层,并选择激活函数,各神经网络超参数;
3、训练完成后 保存模型;
4、并使用模型 通过MNIST测试集验证效果;
5、通过picturebox手写数字,测试效果。

一、创建项目,并导入各依赖项

本例子使用.net9的winform作为示例。
在这里插入图片描述
在这里插入图片描述
创建后,通过nuget,添加依赖项
TensorFlow.NET
TensorFlow.Keras
SciSharp.TensorFlow.Redist–如果使用GPU训练,请使用不同的依赖包

二、初始化

1、添加命名空间

using Tensorflow;
using Tensorflow.Keras.Engine;
using Tensorflow.Keras.Layers;
//using NumSharp;
using static Tensorflow.Binding;
using static Tensorflow.KerasApi;
using Tensorflow.NumPy;
using Newtonsoft.Json.Linq;

2、直接在窗口类中定义变量

        //--定义模型IModel model;//Keras中的层API,用于定义神经网络各个层,包括卷积层、池化层、全连接层LayersApi layers = new LayersApi();//定义示例中使用的,训练集、测试集NDArray x_train, y_train, x_test, y_test, x_test_raw;//x_test_raw for image show//本例中保存训练好的模型,后续随时可以load出来使用const string modelFile = "model.wts";//以下是使用picturebox绘制手写数字的变量Bitmap drawingBitmap;bool isDrawing = false;Point previousPoint;

3、在窗口类构造函数中初始化后续用到的变量

public Form1()
{InitializeComponent();this.DoubleBuffered = true; // 启用双缓冲以减少闪烁this.pictureBox_Image.MouseDown += PictureBox_Image_MouseDown; ;pictureBox_Image.MouseMove += PictureBox_Image_MouseMove; ;pictureBox_Image.MouseUp += PictureBox_Image_MouseUp ;pictureBox_Image.Paint += PictureBox_Image_Paint;//pictureBox_Image.Paint += new PaintEventHandler(Redraw); // 重绘事件处理this.DoubleBuffered = true;// 创建绘图画布drawingBitmap = new Bitmap(pictureBox_Image.Width, pictureBox_Image.Height, PixelFormat.Format24bppRgb);using (Graphics g = Graphics.FromImage(drawingBitmap)){g.Clear(Color.Black);}
}

4、加载MNIST数据集并归一化

 private void button1_Click_1(object sender, EventArgs e){(x_train, y_train, x_test_raw, y_test) = keras.datasets.mnist.load_data();x_train = x_train.reshape((60000, 28, 28, 1)) / 255f;x_test = x_test_raw.reshape((10000, 28, 28, 1)) / 255f;}

以上这几个步骤,前几篇示例中都有相同的操作,就不再赘述解释

三、创建模型

这是本示例的重点,本示例需要做图像识别,而卷积神经网络(CNN)就是专业用于视觉图像分类和视觉图像目标检测的。本例的重点是使用了哪些神经网络层及各层中的激活函数。

1、layers.Conv2D,本例中使用该二维卷积层函数,说明下几个重要的参数:

1、filters:filters指的是这个卷积层中卷积核的数量,也就是指定输出特征图(feature maps)的深度(通道数)。卷积核越多,每个卷积核可以学习一个单独的特征,比如 纹理啊,颜色啊等,这样 模型的表达能力、学习能力就更强,但是也就意味着更大的计算。所以 一般的浅层网络中,较小的学习任务中,通常使用较小的 filters 值(例如 32、64)。而对应的
在深层网络中,使用大一些的 filters 的值(例如 128、256、512)。
2、kernel_size: kernel_size 参数定义了卷积核(filter)的大小,本示例中,kernel_size=(3, 3) 表示一个 3x3 的卷积核。而在实际训练中,卷积核在输入数据上滑动,通过点乘和求和操作提取局部特征。
所以 kernel_size 控制卷积核的空间尺寸(高度和宽度)。
filters 控制卷积核的数量,即输出特征图的深度。卷积层的参数量由 kernel_size 和 filters 共同决定。
一般通用的为 3*3
3、激活函数,这个就不再赘述了,这里用的就是具有生物特征的 Relu

2、layers.MaxPooling2D 该层称为 二维最大池化层

它的主要作用是通过下采样(downsampling)减少特征图的空间尺寸,从而降低计算复杂度并提取主要特征。换句话说就是 他的主要作用是就是按照池化层的最大二维参数,以保留最大特征值的方式,减少特征图的空间尺寸,最大池化层可以显著减少后续层的参数量和计算量,也就是降维,保留有效值。

3、layers.Flatten 展平层

用于将多维的输出张量进行展开,变为一维张量

最终通过 keras.Model() 方法 来构建模型,通过model.compile()【来编译该模型,编译过程其实就是 给模型设置训练参数,创建静态、动态图,为接下来的训练Model.fit()做好准备】

        private IModel CreateModel(){// input layer 输入层,每个手写的数字,像素都是28*28的,所以这里标准输入,按照MNIST的格式,就是 28,28,1var inputs = keras.Input(shape: (28, 28, 1));// 第一层,卷积层,用于二维图像var outputs = layers.Conv2D(32, kernel_size: (3, 3), activation: keras.activations.Relu).Apply(inputs);// 第二层,池化层,用于降维outputs = layers.MaxPooling2D(2, strides: 2).Apply(outputs);//  第三层,卷积层outputs = layers.Conv2D(64, kernel_size: (3, 3), activation: keras.activations.Relu).Apply(outputs);// 第四层,池化层outputs = layers.MaxPooling2D(2, strides: 2).Apply(outputs);// 第五层,展平层,用于将多维的输出张量进行展开,变为一维张量outputs = layers.Flatten().Apply(outputs);outputs = layers.Dense(128, activation: keras.activations.Relu).Apply(outputs);outputs = layers.Dense(10).Apply(outputs);model = keras.Model(inputs, outputs, name: "mnist_model");// model.summary()---输出模型的内容摘要model.summary();// 构建编译,配置参数,生成静态图model.compile(loss: keras.losses.SparseCategoricalCrossentropy(from_logits: true),optimizer: keras.optimizers.Adam(learning_rate: 0.001f),metrics: new[] { "accuracy" });return model;}

四、训练模型,保存模型

训练模型代码如下:

private void TrainModel()
{(x_train, y_train, x_test_raw, y_test) = keras.datasets.mnist.load_data();x_train = x_train.reshape((60000, 28, 28, 1)) / 255f;x_test = x_test_raw.reshape((10000, 28, 28, 1)) / 255f;model = CreateModel();// train model by feeding data and labels.model.fit(x_train, y_train, batch_size: 64, epochs: 5, validation_split: 0.2f);// evluate the modelmodel.evaluate(x_test, y_test, verbose: 2);model.save_weights(modelFile, true);}

重点是三个函数:

1、model.fit() 该函数就是 训练创建好的模型

batch_size:指的是样本批次的数量,
epchs:一共训练几轮
validation_split:验证集划分比,指的是 按照该参数比例,从训练集中划分出数据作为验证集。

2、model.evaluate()评估函数,评估模型的损失度和精度

其中参数 verbose:
verbose=0:静默模式,不输出任何日志信息。

verbose=1:输出进度条和每个 epoch 的评估结果。

verbose=2:输出每个 batch 的评估结果,但不显示进度条。

3、model.save_weights()将模型作为文件保存,后面可以加载使用

五、通过MNIST测试集验证效果

以下直接粘贴代码:
思路是 从 测试集中(x_test)随机挑选 一个张量 进行预测,看预测的结果和 测试标签集中(y_test)中的实际结果是否一致。
本例中没有 其他要注意事项,仅仅用到了 model.load_weights()来加载模型,model.predict()来进行模型预测。
唯一要注意的是 预测的张量的shape要和 训练使用的训练集保持一致,此处为new[] { 1, 28, 28, 1 }

private void button1_Click(object sender, EventArgs e)
{if (System.IO.File.Exists(modelFile)){model = CreateModel();model.load_weights(modelFile);}int num = Convert.ToInt32(txtResult.Text);string str = "真实数字是" + y_test[num];textBox_history.Text += "\r\n" + "Real Label is:" + y_test[num] + "\r\n";var predict_result = model.predict(x_test[num].reshape(new[] { 1, 28, 28, 1 }));var predict_label = np.argmax(predict_result[0].numpy(), axis: 1);str += "测试结果是:" + predict_label[0].ToString();label1.Text = str;}

测试结果,准确率能达到 98%

六、通过手写数字来验证效果

1、在picturebox上实现手写数字,

1)、定义变量


//以下是使用picturebox绘制手写数字的变量
Bitmap drawingBitmap;
bool isDrawing = false;
Point previousPoint;

2)窗体构造方法中定义事件

 public Form1()
{InitializeComponent();this.DoubleBuffered = true; // 启用双缓冲以减少闪烁this.pictureBox_Image.MouseDown += PictureBox_Image_MouseDown; ;pictureBox_Image.MouseMove += PictureBox_Image_MouseMove; ;pictureBox_Image.MouseUp += PictureBox_Image_MouseUp ;pictureBox_Image.Paint += PictureBox_Image_Paint;//pictureBox_Image.Paint += new PaintEventHandler(Redraw); // 重绘事件处理this.DoubleBuffered = true;// 创建绘图画布drawingBitmap = new Bitmap(pictureBox_Image.Width, pictureBox_Image.Height, PixelFormat.Format24bppRgb);using (Graphics g = Graphics.FromImage(drawingBitmap)){g.Clear(Color.Black);}
}

3)通过事件实现picturebox绘图

private void PictureBox_Image_MouseUp(object? sender, MouseEventArgs e)
{isDrawing = false;drawingBitmap.Save("orginal.bmp");
}private void PictureBox_Image_MouseMove(object? sender, MouseEventArgs e)
{if (isDrawing){// 在绘图画布上绘制线条using (Graphics g = Graphics.FromImage(drawingBitmap)){                    g.DrawLine(new Pen(Color.White, 10), previousPoint, e.Location);}// 更新上一个点的位置previousPoint = e.Location;// 刷新 PictureBoxpictureBox_Image.Invalidate();}
}private void PictureBox_Image_MouseDown(object? sender, MouseEventArgs e)
{if (e.Button == MouseButtons.Left){isDrawing = true;previousPoint = e.Location;}
}private void PictureBox_Image_Paint(object? sender, PaintEventArgs e)
{e.Graphics.DrawImage(drawingBitmap, Point.Empty);
}

绘图完成后保存成了 图片 orginal.bmp

4)定义工具类,将手绘的图片orginal.bmp实现 灰度转化和归一化

using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tensorflow;
using Tensorflow.NumPy;namespace WinFormCNN
{public class MnistConverter{public static float[] ConvertToMnistFormat(){//1、灰度化Bitmap grayBitmap = ConvertToGrayscale();// 2. 归一化像素值并转换为 MNIST 格式float[] mnistData = new float[28 * 28];for (int y = 0; y < 28; y++){for (int x = 0; x < 28; x++){Color pixel = grayBitmap.GetPixel(x, y);float normalizedValue = pixel.R / 255.0f; // 归一化到 0-1 之间mnistData[y * 28 + x] = normalizedValue;}}return mnistData;}private static Bitmap ConvertToGrayscale(){Bitmap bitmap = new Bitmap(Image.FromFile("orginal.bmp"),28,28);Bitmap grayBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb);for (int y = 0; y < bitmap.Height; y++){for (int x = 0; x < bitmap.Width; x++){Color pixel = bitmap.GetPixel(x, y);if (pixel.R > 0 || pixel.G > 0 || pixel.B > 0) {Console.WriteLine(pixel.R + "," + pixel.G + "," + pixel.B);}var test= (pixel.R * 0.299 + pixel.G * 0.587 + pixel.B * 0.114);int grayValue = (int)(pixel.R * 0.299 + pixel.G * 0.587 + pixel.B * 0.114);grayBitmap.SetPixel(x, y, Color.FromArgb(grayValue, grayValue, grayValue));}}          return grayBitmap;}       }
}

5)测试效果

要先 加载数据集

 private void button1_Click_1(object sender, EventArgs e){(x_train, y_train, x_test_raw, y_test) = keras.datasets.mnist.load_data();x_train = x_train.reshape((60000, 28, 28, 1)) / 255f;x_test = x_test_raw.reshape((10000, 28, 28, 1)) / 255f;}

跳过模型训练,直接加载模型后进行预测

       private void button1_Click(object sender, EventArgs e){           if (System.IO.File.Exists(modelFile)){model = CreateModel();model.load_weights(modelFile);}//将上面步骤绘制的数字转化为浮点数组float[] imageBytes = MnistConverter.ConvertToMnistFormat();//将浮点型数组转化为预测张量var tensor = tf.constant(imageBytes, dtype: tf.float32);tensor = tf.reshape(tensor, (1, 28, 28, 1));//进行预测,观察结果var predict_result = model.predict(tensor);var predict_label = np.argmax(predict_result[0].numpy(), axis: 1);var str = "测试结果是:" + predict_label[0].ToString();label1.Text = str;}

经过多次测试,准确率很高。
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com