AI与.NET技术实操系列(六):实现图像分类模型的部署与调用
引言
人工智能(AI)技术的迅猛发展推动了各行各业的数字化转型。图像分类,作为计算机视觉领域的核心技术之一,能够让机器自动识别图像中的物体、场景或特征,已广泛应用于医疗诊断、安防监控、自动驾驶和电子商务等领域。
与此同时,.NET 平台凭借其高效性、跨平台能力和强大的 C# 编程语言支持,成为开发者构建企业级应用的首选技术栈。将 AI 图像分类模型与 .NET 技术结合,不仅能充分发挥两者的优势,还能为开发者提供一种高效、直观的实现方式。
本文将详细介绍如何在 .NET 环境下使用 C# 部署和调用 AI 图像分类模型。我们将从环境搭建、模型选择,到模型调用,再到实际应用场景,逐步展开讲解,并提供丰富的代码示例和实践指导,帮助开发者快速上手并应用到实际项目中。
准备工作
在开始实现图像分类之前,我们需要准备必要的开发环境和工具。以下是所需的软件和库:
- Visual Studio:Visual Studio 2022。
- .NET SDK:安装 .NET 6.0 或更高版本,确保支持最新的功能和性能优化。
- ML.NET:微软提供的开源机器学习框架,专为 .NET 开发者设计,支持模型训练和推理。
- 模型文件:我们将使用预训练的图像分类模型 tensorflow_inception_graph.pb。
安装步骤
创建项目并添加依赖:在命令行中运行以下命令,创建一个控制台应用程序并安装必要的 NuGet 包:
dotnet new console -n ImageClassificationDemo
cd ImageClassificationDemo
dotnet add package Microsoft.ML
dotnet add package Microsoft.ML.ImageAnalytics
dotnet add package Microsoft.ML.TensorFlow
dotnet add package SciSharp.TensorFlow.Redist
完成以上步骤后,你的环境就准备好了。接下来,我们将选择一个合适的图像分类模型。
图像分类模型的选择
图像分类模型是基于监督学习的神经网络,其目标是将输入图像分配到预定义的类别中。在选择模型时,我们需要考虑模型的性能、计算复杂度和适用场景。以下是几种常见的图像分类模型:
- 卷积神经网络(CNN):如 LeNet、AlexNet 和 VGGNet,适合基本的图像分类任务,但层数较深时可能面临梯度消失问题。
- 残差网络(ResNet):通过引入残差连接(skip connections),解决了深层网络的训练难题,适用于高精度分类任务。
- EfficientNet:通过平衡网络深度、宽度和分辨率,提供高效的性能,适合资源受限的场景。
模型训练与导出
考虑到时间和资源成本,我们将直接使用预训练的 tensorflow_inception_graph.pb 模型。如果你有自定义需求,可以使用以下步骤训练并导出模型:
- 数据准备:收集并标注图像数据集,分为训练集和验证集。
- 训练模型:使用 TensorFlow 或 PyTorch 等框架训练模型。
- 导出模型:利用框架提供的导出工具导出模型。
在本文中,我们选择 tensorflow_inception_graph.pb 作为示例模型,这是一种由Google开发的高性能卷积神经网络(CNN)架构。
该模块通过并行使用不同大小的卷积核(如1x1、3x3、5x5)和池化层,提取图像的多尺度特征。这种设计提高了模型在图像分类任务中的表现,同时保持了计算效率。支持 1000 个类别的分类,且可以轻松集成到 .NET 中。
大家可以直接点击 tensorflow_inception_graph.pb 下载(文章最后也有下载方式)预训练的模型文件和分类文件,并将其放入项目目录中。
也可以到github上下载(文章最后也有下载方式),里面的内容相对来说也更丰富些。
在 .NET 中调用模型
现在,我们进入核心部分:在 .NET 中调用 tensorflow_inception_graph.pb。以下是逐步实现的过程。
1. 创建 .NET 项目
使用命令行创建一个控制台应用,项目基本结构如下:
ImageClassificationDemo/
├── ImageClassificationDemo.csproj
├── Program.cs
├── assets/inputs/inception/tensorflow_inception_graph.pb
├── assets/inputs/inception/imagenet_comp_graph_label_strings.txt
2. 定义输入和输出数据结构
如果在运行的时候报错说找不到模型或者label文件,可以进行如下操作:
输入类中定义数据的结构如下,后续会使用 TextLoader 加载数据时引用该类型。此处的类名为 ImageNetData:
public class ImageNetData{[LoadColumn(0)]public string ImagePath;[LoadColumn(1)]public string Label;public static IEnumerable<ImageNetData> ReadFromCsv(string file, string folder){return File.ReadAllLines(file).Select(x => x.Split('\t')).Select(x => new ImageNetData { ImagePath = Path.Combine(folder, x[0]), Label = x[1] } );}}public class ImageNetDataProbability : ImageNetData{public string PredictedLabel;public float Probability { get; set; }}
需要强调的是,ImageNetData 类中的标签在使用 TensorFlow 模型进行评分时并没有真正使用。而是在测试预测时使用它,这样就可以将每个样本数据的实际标签与 TensorFlow 模型提供的预测标签进行比较。
输出类的结构如下:
public class ImageNetPrediction
{[ColumnName(TFModelScorer.InceptionSettings.outputTensorName)]public float[] PredictedLabels;
}
Inception 模型还需要几个传入的默认参数:
public struct ImageNetSettings
{public const int imageHeight = 224;public const int imageWidth = 224;public const float mean = 117;public const bool channelsLast = true;
}
3. 定义 estimator 管道
在处理深度神经网络时,必须使图像适应网络期望的格式。这就是图像被调整大小然后转换的原因(主要是像素值在所有R,G,B通道上被归一化)。
var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: imagesFolder, inputColumnName: nameof(ImageNetData.ImagePath)).Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input")).Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean)).Append(mlContext.Model.LoadTensorFlowModel(modelLocation).ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2" }, inputColumnNames: new[] { "input" },addBatchDimensionInput:true));
运行代码后,模型将被成功加载到内存中,接下来我们可以调用它进行图像分类。
通常情况下,这里经常报的错就是输入/输出节点的名称不正确,你可以通过 Netron (https://netron.app/)工具查看输入/输出节点的名称。
因为这两个节点的名称后面会在 estimator 的定义中使用:在 inception 网络的情况下,输入张量命名为 ‘input’,输出命名为 ‘softmax2’。
下图是通过 Netron 读取的 tensorflow_inception_graph.pb 模型分析图:
4. 提取预测结果
填充 estimator 管道
ITransformer model = pipeline.Fit(data);
var predictionEngine = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(model);
当获得预测结果后,我们会在属性中得到一个浮点数数组。数组中的每个位置都会分配到一个标签。
例如,如果模型有5个不同的标签,则数组将为length = 5。数组中的每个位置都表示标签在该位置的概率;所有数组值(概率)的和等于1。
然后,您需要选择最大的值(概率),并检查配给了该位置的那个以填充 estimator 管道标签。
调用模型进行图像分类
接下来我们需要编写代码来加载图像、进行预测并解析结果。
1. 准备素材与分类文件
定义图像文件夹目录和图像分类目录。以下代码加载并预处理图像:
string assetsRelativePath = @"../../../assets";
string assetsPath = GetAbsolutePath(assetsRelativePath);string tagsTsv = Path.Combine(assetsPath, "inputs", "images", "tags.tsv");
string imagesFolder = Path.Combine(assetsPath, "inputs", "images");
string inceptionPb = Path.Combine(assetsPath, "inputs", "inception", "tensorflow_inception_graph.pb");
string labelsTxt = Path.Combine(assetsPath, "inputs", "inception", "imagenet_comp_graph_label_strings.txt");
2. 加载模型
private PredictionEngine<ImageNetData, ImageNetPrediction> LoadModel(string dataLocation, string imagesFolder, string modelLocation)
{ConsoleWriteHeader("Read model");Console.WriteLine($"Model location: {modelLocation}");Console.WriteLine($"Images folder: {imagesFolder}");Console.WriteLine($"Training file: {dataLocation}");Console.WriteLine($"Default parameters: image size=({ImageNetSettings.imageWidth},{ImageNetSettings.imageHeight}), image mean: {ImageNetSettings.mean}");var data = mlContext.Data.LoadFromTextFile<ImageNetData>(dataLocation, hasHeader: true);var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: imagesFolder, inputColumnName: nameof(ImageNetData.ImagePath)).Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input")).Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean)).Append(mlContext.Model.LoadTensorFlowModel(modelLocation).ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2" },inputColumnNames: new[] { "input" }, addBatchDimensionInput:true));ITransformer model = pipeline.Fit(data);var predictionEngine = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(model);return predictionEngine;
}
3. 解析输出结果
protected IEnumerable<ImageNetData> PredictDataUsingModel(string testLocation, string imagesFolder, string labelsLocation, PredictionEngine<ImageNetData, ImageNetPrediction> model)
{ConsoleWriteHeader("Classify images");Console.WriteLine($"Images folder: {imagesFolder}");Console.WriteLine($"Training file: {testLocation}");Console.WriteLine($"Labels file: {labelsLocation}");var labels = ReadLabels(labelsLocation);var testData = ImageNetData.ReadFromCsv(testLocation, imagesFolder);foreach (var sample in testData){var probs = model.Predict(sample).PredictedLabels;var imageData = new ImageNetDataProbability(){ImagePath = sample.ImagePath,Label = sample.Label};(imageData.PredictedLabel, imageData.Probability) = GetBestLabel(labels, probs);imageData.ConsoleWrite();yield return imageData;}
}
在 Main
方法中调用,完整代码如下:
static void Main(string[] args)
{string assetsRelativePath = @"../../../assets";string assetsPath = GetAbsolutePath(assetsRelativePath);string tagsTsv = Path.Combine(assetsPath, "inputs", "images", "tags.tsv");string imagesFolder = Path.Combine(assetsPath, "inputs", "images");string inceptionPb = Path.Combine(assetsPath, "inputs", "inception", "tensorflow_inception_graph.pb");string labelsTxt = Path.Combine(assetsPath, "inputs", "inception", "imagenet_comp_graph_label_strings.txt");try{TFModelScorer modelScorer = new TFModelScorer(tagsTsv, imagesFolder, inceptionPb, labelsTxt);modelScorer.Score();}catch (Exception ex){ConsoleHelpers.ConsoleWriteException(ex.ToString());}ConsoleHelpers.ConsolePressAnyKey();
}
运行程序后,你将看到类似以下的输出:
其他实现方式
在实际应用中,我们也可以使用ONNX模型,此处不做额外叙述。由于模型的性能和效率至关重要,只是提供一些优化建议:
- 模型量化:使用 ONNX Runtime 的量化工具,将模型从浮点数(FP32)转换为整数(INT8),减少模型大小和推理时间。
- 硬件加速:结合 ONNX Runtime 的 GPU 支持,利用 CUDA 或 DirectML 加速推理。
- 批处理:如果需要处理多张图像,可以将输入组织为批次(batch),提高吞吐量。例如:
var inputs = new List<ImageInput> { input1, input2, input3 };
var batchPrediction = mlContext.Data.LoadFromEnumerable(inputs);
var predictions = model.Transform(batchPrediction);
- 缓存机制:对于频繁使用的模型,保持预测引擎的单例实例,避免重复加载。
通过这些优化,模型可以在 .NET 环境中实现更高的性能,满足实时应用的需求。
实际应用场景
图像分类模型在 .NET 应用中有广泛的用途,以下是几个典型场景:
-
医疗影像分析
在医疗系统中,部署图像分类模型可以辅助医生识别 X 光片或 MRI 图像中的异常。例如,检测肺部结节或肿瘤。 -
智能安防
在监控系统中,模型可以实时识别可疑物体或行为,如检测闯入者或遗留物品。 -
电子商务
在商品管理系统中,自动分类上传的商品图像,提升搜索和推荐的准确性。
挑战与解决方案
- 数据隐私:通过加密传输和本地推理保护用户数据。
- 模型更新:定期从云端下载新模型,并使用版本控制管理。
- 计算资源:在资源受限的设备上,使用轻量化模型(如 MobileNet)。
结论
本文详细介绍了如何在 .NET 环境下使用 C# 部署和调用 AI 图像分类模型。从环境搭建到模型选择、部署与调用,再到性能优化和应用场景,我们提供了一套完整的实践指南。通过 ML.NET 和预测模式的支持,开发者可以轻松地将强大的 AI 能力集成到 .NET 应用中。
随着 AI 技术的不断进步和 .NET 平台的持续发展,二者的结合将为开发者带来更多可能性。无论是构建智能桌面应用、Web 服务还是跨平台解决方案,图像分类模型都能为项目增添创新价值。希望本文能为你的 AI 之旅提供启发和帮助!
参考资料
- 素材下载地址: https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
- Netron工具地址: https://netron.app/
- 224x224图像素材: https://www.kaggle.com/datasets/abhinavnayak/catsvdogs-transformed/data
- tensorflow教程及模型文件和label文件: https://github.com/martinwicke/tensorflow-tutorial
- Image Classification - Scoring sample: https://github.com/dotnet/machinelearning-samples/blob/main/samples/csharp/getting-started/DeepLearning_ImageClassification_TensorFlow/README.md
- ML.NET 官方文档: https://dotnet.microsoft.com/apps/machinelearning-ai/ml-dotnet
- ONNX Model Zoo: https://github.com/onnx/models
相关文章:
AI与.NET技术实操系列(六):实现图像分类模型的部署与调用
引言 人工智能(AI)技术的迅猛发展推动了各行各业的数字化转型。图像分类,作为计算机视觉领域的核心技术之一,能够让机器自动识别图像中的物体、场景或特征,已广泛应用于医疗诊断、安防监控、自动驾驶和电子商务等领域…...
PP-YOLOE-SOD学习笔记1
项目:基于PP-YOLOE-SOD的无人机航拍图像检测案例全流程实操 - 飞桨AI Studio星河社区 一、安装环境 先准备新环境py>3.9 1.先cd到源代码的根目录下 2.pip install -r requirements.txt 3.python setup.py install 这一步需要看自己的GPU情况,去飞浆…...
Axure系统原型设计列表版方案
列表页面是众多系统的核心组成部分,承担着数据呈现与基础交互的重要任务。一个优秀的列表版设计,能够极大提升用户获取信息的效率,优化操作体验。下面,我们将结合一系列精心设计的列表版方案图片,深入探讨如何打造出实…...
腾讯音乐二面
ReentrantLock 的源码及实现 ReentrantLock 是 Java 中的一种可重入的互斥锁。它通过 AQS(AbstractQueuedSynchronizer)框架来实现。AQS 使用一个 FIFO 队列来管理获取锁的线程。ReentrantLock 有公平锁和非公平锁两种模式。非公平锁:当线程尝…...
服务器操作系统调优内核参数(方便查询)
fs.aio-max-nr1048576 #此参数限制并发未完成的异步请求数目,应该设置避免I/O子系统故障 fs.file-max1048575 #该参数决定了系统中所允许的文件句柄最大数目,文件句柄设置代表linux系统中可以打开的文件的数量 fs.inotify.max_user_watches8192000 #表…...
MySQL5.7导入MySQL8.0的文件不成功
文章目录 问题检查原因及解决方法原因解决办法 问题 检查 检查自己的mysql版本自己检查,搜索“0900_ai_ci”,如果能搜索到,说明这个sql文件是从8的版本导出的 原因及解决方法 原因 MySQL 8.0默认使用utf8mb4字符集和utf8mb4_0900_ai_ci排…...
vscode连接WSL卡住
原因:打开防火墙 解决: 使用sudo ufw disable关闭防火墙...
springAI调用deepseek模型使用硅基流动api的配置信息
查看springai的官方文档,调用deepseek的格式如下: spring.ai.deepseek.api-key${your-api-key} spring.ai.deepseek.chat.options.modeldeepseek-chat spring.ai.deepseek.chat.options.temperature0.8 但是硅基流动的格式不是这样,这个伞兵…...
symbol【ES6】
你一闭眼世界就黑了,你不是主角是什么? 目录 什么是Symbol?Symbol特点:创建方法:注意点:不能进行运算:显示调用toString() --没有意义隐式转换boolean 如果属性名冲突了怎么办?o…...
如何用数据可视化提升你的决策力?
在数字化浪潮席卷全球的当下,数据已然成为企业和组织发展的核心资产。然而,单纯的数据堆积犹如未经雕琢的璞玉,难以直接为决策提供清晰有力的支持。数据可视化作为一种强大的工具,能够将海量、复杂的数据转化为直观、易懂的图形、…...
【C++】vector容器实现
目录 一、vector的成员变量 二、vector手动实现 (1)构造 (2)析构 (3)尾插 (4)扩容 (5)[ ]运算符重载 5.1 迭代器的实现: (6&…...
C语言求1到n的和(附带源码和解析)
在C语言中,使用 for 循环求 1 到 n 的和是一个常见的编程任务。这个任务不仅可以帮助初学者理解循环的基本概念,还能培养他们的逻辑思维能力。 要计算 1 到 n 的和,我们需要创建一个循环,从 1 开始,一直累加到 n。for…...
springboot3+vue3融合项目实战-大事件文章管理系统-文章分类也表查询(条件分页)
在pojo实体类中增加pagebean实体类 Data NoArgsConstructor AllArgsConstructor public class PageBean <T>{private Long total;//总条数private List<T> items;//当前页数据集合 }articlecontroller增加代码 GetMappingpublic Result<PageBean<Article&g…...
java中定时任务的实现及使用场景
在 Java 需要中,定时任务的实现方式有单线程模型的 Timer 类、线程池定时任务的 ScheduleExecutorService、spring 框架提供的注解Schedule 定时任务,第三个框架定时任务比如 XX-Job,Quartz 等。 Java 任务调度组件对比与使用指南 一、核心功能对比 特…...
使用 OpenCV 实现哈哈镜效果
在计算机视觉和图像处理领域,OpenCV 提供了非常强大的图像几何变换能力,不仅可以用于纠正图像,还能制造各种“有趣”的视觉效果。今天,我们就来实现一个经典的“哈哈镜”效果,让图像像在游乐园里一样被拉伸、压缩、扭曲…...
【Java高阶面经:微服务篇】9.微服务高可用全攻略:从架构设计到自动容灾
一、架构层:构建抗故障的分布式基石 1.1 多维度冗余设计 1.1.1 跨可用区部署策略 # Kubernetes跨可用区反亲和性配置 apiVersion: apps/v1 kind: Deployment metadata:name: product-service spec:replicas: 3template:spec:affinity:podAntiAffinity:requiredDuringSchedu…...
读一本书第一遍是快读还是细读?
在时间充足且计划对重要书籍进行多遍阅读的前提下,第一遍阅读的策略可以结合**「快读搭建框架」与「标记重点」**,为后续细读奠定基础。以下是具体建议及操作逻辑: 一、第一遍:快读为主,目标是「建立全局认知」 1. 快…...
COMPUTEX 2025 | 广和通5G AI MiFi解决方案助力移动宽带终端迈向AI新未来
随着5G与AI不断融合,稳定高速、智能的移动网络已成为商务、旅行、户外作业等场景的刚需。广和通5G AI MiFi方案凭借领先技术与创新设计,重新定义5G移动网络体验。 广和通5G AI MiFi 方案搭载高通 4nm制程QCM4490平台,融合手机级超低功耗技术…...
JAVA批量发送邮件(含excel内容)
EmailSenderHtmlV1 是读取配置文件《批量发送邮件.xlsx》,配置sheet获取 发件人邮箱 邮箱账号 口令,发送excel数据sheet获取收件人邮箱 抄送人邮箱 邮件标题 第N行开始(N>1,N0默认表头) 第M行结束(M>1,M0默认表头) 附件文件夹…...
MyBatis 关联映射深度解析:_association_ 与 _collection_ 实战教程
一、核心概念与适用场景 在 MyBatis 中,<association> 和 <collection> 用于处理对象间的关联关系,简化复杂查询到对象结构的映射。 标签用途对应关系示例场景<association>映射 单个嵌套对象(“有一个”关系)一对一、多对一员工 (Emp) 属于一个部门 (D…...
NSSCTF [watevrCTF 2019]Wat-sql
90.[watevrCTF 2019]Wat-sql(逻辑漏洞) [watevrCTF 2019]Wat-sql (1) 1.准备 motalymotaly-VMware-Virtual-Platform:~$ file sql sql: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linu…...
C++ 前缀和数组
一. 一维数组前缀和 1.1. 定义 前缀和算法通过预处理数组,计算从起始位置到每个位置的和,生成一个新的数组(前缀和数组)。利用该数组,可以快速计算任意区间的和,快速求出数组中某一段连续区间的和。 1.2. …...
免费使用GPU的探索笔记
多种有免费时长的平台 https://www.cnblogs.com/java-note/p/18760386 Kaggle免费使用GPU的探索 https://www.kaggle.com/ 注册Kaggle账号 访问Kaggle官网,使用邮箱注册账号。 发现gpu都是灰色的 返回home,右上角的头像点开 验证手机号 再次code-you…...
【css】 flex布局基本知识
Flexible Box 模型,是一种一维的布局模型。一个 flexbox 一次只能处理一个维度上的元素布局,一行或者一列。 轴线 flex 属性与主轴和交叉轴有关,通过flex-direction定义 主轴由 flex-direction 定义,可以取 4 个值:…...
3D Gaussian Splatting for Real-Time Radiance Field Rendering——文章方法精解
SfM → Point-NeRF → 3D Gaussian Splatting 🟦SfM Structure-from-Motion(运动恢复结构,简称 SfM)是一种计算机视觉技术,可以: 利用多张从不同角度拍摄的图像,恢复出场景的三维结构和相机的…...
RestTemplate 发送的字段第二个大写字母变成小写的问题探究
在使用RestTemplate 发送http 请求的时候,发现nDecisonVar 转换成了ndecisonVar ,但是打印日志用fastjson 打印的没有问题,换成jackson 打印就有问题。因为RestTemplate 默认使用的jackson 作为json 序列化方式,导致的问题,但是为…...
第二次中医知识问答微调
由于昨天微调效果并不理想,因此更换数据集和参数进行重新进行了微调 本次微调参数如下: llamafactory-cli train \ --stage sft \ --do_train True \ --model_name_or_path /home/qhyz/zxy/LLaMA-Factory/model \ --preprocessing_num_workers 16 \ --…...
Linux查 ssh端口号和服务状态
一、检查SSH服务运行状态 通过进程查看命令验证服务是否启动: ps -ef | grep ssh当输出包含sshd进程时,表示SSH服务正在运行。示例输出: root 1234 1 0 10:00 ? 00:00:00 /usr/sbin/sshd二、查看服务监听端口 使用网络…...
C++ 11(1):
C11的发展史: C11中的{}: 看这个图片,我们的C11是所有的对象都可以使用{}来进行初始化,之前我们的int类型的数据要使用赋值符号来进行初始化,现在的话我们可以直接使用花括号来进行,并且连赋值符号都可以去…...
数据结构(4)线性表-链表-双链表
一、链表的分类 迟来的分类,主要如果在学习单链表前去讲分类,可能就云里雾里的,所以放在讲完单链表后讲。 划分链表的标准如下: 有没有头结点、指针的方向、循环与否 头结点就是一个占位结点,也被叫做哨兵位&#x…...
Spring Framework 的 spring-core 和 Spring Security 兼容版本
Spring Framework 的 spring-core 和 Spring Security 兼容版本 Spring Framework 的 spring-core 和 Spring Security 的版本需要保持兼容性,尤其是在旧版本(如 Spring 4.x)中。以下是它们的版本对应关系: Spring 4.x (spring-c…...
《国家职业教育平台:点亮职业教育新灯塔》
职教新航标:平台诞生记 国家职业教育智慧教育平台 在科技飞速发展的今天,数字化浪潮席卷全球,深刻地改变着我们生活的方方面面,教育领域也不例外。随着信息技术的不断进步,教育数字化已成为当今世界教育发展的重要趋势…...
Java多线程深度解析:从核心机制到高阶实战
Java多线程深度解析:从核心机制到高阶实战 摘要:本文系统解析Java多线程全体系知识,涵盖线程实现原理、并发工具实战、锁机制底层实现、线程池参数调优策略,并提供20可运行代码片段。附内存模型原理与性能优化指南。 目录 线程基…...
大量程粗糙度轮廓仪适用于哪些材质和表面?
大量程粗糙度轮廓仪是一种能够在广泛的测量范围内对工件表面进行粗糙度分析的精密仪器。它通常采用接触式或非接触式传感器,通过对工件表面的扫描,捕捉表面微观的起伏和波动,从而获取粗糙度数据。该仪器不仅能测量微小的表面细节,…...
NC028NQ472美光固态颗粒NQ484NQ485
深度解析:NC028NQ472、NQ484与NQ485美光固态颗粒 技术架构解析:堆叠式存储与算法优化 美光NC028NQ472、NQ484及NQ485系列固态颗粒均采用自研3D TLC NAND闪存技术,其核心架构通过垂直堆叠存储单元实现高密度集成。以NQ472为例,采…...
Cursor神一样的存在,核心能力codebase是如何工作的?
最近宣布达到 3 亿美元年度经常性收入,已经成为vibe coding标配。核心能力来自于Codebase。根据官方说法,codebase实现是依赖使用 Merkle 树来快速索引代码。但是没有竞品模仿这种方法。 Merkle是如何工作的那? Merkle 树简单解释 Merkle …...
python代码绘制某只股票最近90天的K线图、均线、量能图
运行代码,要求输入股票代码和名称,其他参数可省略 import akshare as ak import matplotlib.pyplot as plt import pandas as pd import mplfinance as mpf import matplotlib.dates as mdates import numpy as np import os from datetime import date…...
upload-labs通关笔记-第15关 文件上传之getimagesize绕过(图片马)
目录 一、图片马 二、文件包含 三、文件包含与图片马 四、图片马制作方法 五、源码分析 六、制作图片马 1、创建脚本并命名为test.php 2、准备制作图片马的三类图片 3、 使用copy命令制作图片马 七、渗透实战 1、GIF图片马渗透 (1)上传gif图…...
反弹shell
shell了解 shell其xxxx是交互,点鼠标敲键盘与计算机进行交互,还有常见的shell(cmd,powershell) shell反弹 当远程连接shell(windows远程桌面,linux有SSH之类),从外面远…...
【动手学深度学习】1.3. 各种机器学习问题
目录 1.3. 各种机器学习问题1)监督学习(supervisedlearning)(1)回归(regression)(2)分类(classification)(3)标记问题&…...
OS进程调度
tss Q1:你是如何保证两个进程不能同时访问共享资源的? ✅ 推荐回答: 我实现了基于结构体的互斥锁,使用 mutex_lock() 来加锁资源。如果已有任务持有锁,则当前任务会被阻塞并加入等待队列,直到被唤醒。解锁…...
MCP和 AI agent 有什么区别和联系
MCP 是什么? MCP(Model Context Protocol,模型上下文协议)是一种开源通信协议,旨在为大型语言模型(LLM)与外部数据源、工具或服务之间建立标准化、安全且灵活的双向连接。它类似于“AI 的 USB-…...
用Recommenders,实现个性化推荐
文章目录 引言一、Recommenders简介二、选择Recommenders的原因三、智能推荐系统的设计与实现四、总结 引言 在这个信息如洪流般涌来的时代,你是否常常在茫茫的信息海洋中迷失方向,为找不到自己心仪的内容而苦恼?今天咱们就来聊聊基于Micros…...
MCP-1:MCP组件与工作流程
MCP-1:MCP组件与工作流程 1.什么是MCP2.MCP架构组件2.1.MCP Hosts2.2.MCP Client2.3.MCP Server3.交互流程3.1.用户提问3.2.LLM 推理选择MCP Server(大模型规划)3.3.调用 MCP Tool3.4.返回结果3.5.数据清洗3.6.反馈信息给用户1.什么是MCP MCP(Model Context Proto…...
NVIDIA GPU 性能调优与诊断完全指南
本文为多 GPU 用户(如 3*RTX A4000 系统)提供一份全面的调优与诊断手册,涵盖功率限制、风扇控制、频率锁定、缓存清理、GPU 重置与性能测试工具等操作命令,适合开发者与研究人员在部署前进行系统级优化与验证。 📌 目录…...
从运维告警到业务决策:可观测性正在重新定义企业数据基础设施
可观测性(Observability)与传统监控(Monitoring)的核心差异,本质上是一种数据维度的主动暴露与被动采集的范式转变。传统监控就像在黑暗森林中设置有限的探照灯,运维人员必须预先假设可能的故障路径&#x…...
配电网运行状态综合评估方法研究
1评估指标体系的构建 [1]冷华,童莹,李欣然,等.配电网运行状态综合评估方法研究[J].电力系统保护与控制,2017,45(01):53-59. 1.1评估范围 图1为配电系统组成示意图,其中A、B、C分别表示高、中、低压配电系统。高压配变(也称主变)将35kV或110kV的电压降到10kV&#…...
Linux中I/O复用机制epoll
1. 为什么会出现 epoll? 在早期的网络编程中,select 是一个非常常用的 I/O 复用机制,用于在多个文件描述符(如套接字)上进行 I/O 操作的检测。select 会将多个文件描述符传入,轮询检查它们的状态ÿ…...
数据库表关系详解
一、一对多关系 特征:表A的一条记录对应表B的多条记录,表B的一条记录仅对应表A的一条记录 示例: 学生表(子表) | id | name | class_id | |-----|------|----------| |1001| 张三 | 111 | |1002| 张四 | 222 | 班级表…...
Agentic Loop与MCP:大模型能力扩展技术解析
一、什么是MCP MCP(Model Context Protocol)是一种用于大语言模型与外部工具交互的协议框架。它允许大语言模型能够调用各种外部工具来扩展其能力边界,如访问文件系统、搜索引擎、数据库等。 MCP的核心价值 能力扩展:使大语言模…...