惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 聂微东
大猫的无限游戏
大猫的无限游戏
IT之家
IT之家
月光博客
月光博客
博客园_首页
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AWS News Blog
AWS News Blog
S
Securelist
T
Tailwind CSS Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
罗磊的独立博客
D
Docker
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
Scott Helme
Scott Helme
H
Help Net Security
Project Zero
Project Zero
P
Proofpoint News Feed
D
DataBreaches.Net
Recorded Future
Recorded Future
Simon Willison's Weblog
Simon Willison's Weblog
V2EX - 技术
V2EX - 技术
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
I
Intezer
Engineering at Meta
Engineering at Meta
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
I
InfoQ
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
S
Secure Thoughts
GbyAI
GbyAI
U
Unit 42
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
The Last Watchdog
The Last Watchdog
Y
Y Combinator Blog
F
Fortinet All Blogs
博客园 - Franky
T
The Blog of Author Tim Ferriss
Hacker News: Ask HN
Hacker News: Ask HN
Microsoft Security Blog
Microsoft Security Blog
Stack Overflow Blog
Stack Overflow Blog
S
Security @ Cisco Blogs
Cyberwarzone
Cyberwarzone

博客园 - harrychinese

机器学习实战示例和基础知识查漏补缺 jupyter notebook上的java kernel 数据分析中几个常用的java类 我认为 C# 几个重要的设计缺陷 Jupyter notebook 最简安装方法 使用Tribuo分析波士顿房产数据 Java 语言常用的技巧 Java AI agent框架 java jbang 工具让java作为脚本语言 VS code + Jypyter 插件构建 Java notebook 环境 使用 VS code + Oracle java 插件搭建java语言原生的notebook环境 【计算机科学速成课】[40集全/精校] - Crash Course Computer Science Handy toolbox for IT developers 中学学校教材下载 深度学习模型训练5个关键步骤 使用SpringBoot实现一个执行通用SQL的Rest接口 学益升X1和国悦K3阅读器 状态机 使用场景规则匹配模式代替复杂的if else条件判断 vscode 数据处理的插件 iPhone XR 升级非最新版IOS duckdb nuget打包部署完整步骤 机器学习资料汇总 优化算法知识和类库 C# XML 序列化器 画草图和示意图的好工具 .net debug tools 运筹学/最优化讲义.pdf Lazarus
ML.Net机器学习基本知识
harrychinese · 2025-05-05 · via 博客园 - harrychinese

安装依赖包:

  • Microsoft.ML : ML.Net的主要依赖包, 一般安装这个就够了, 提供标准算法库和ML context和pipeline的核心类库
  • Microsoft.Extensions.ML , 为ML包支持依赖注入
  • Microsoft.ML.FastTree, 提供随机森林相关的回归算法
  • Microsoft.ML.LightGbm, 提供 LightGbm 梯度提升集成算法
  • Microsoft.ML.OnnxTransformer, 提供导入 onnx 模型能力
  • Microsoft.ML.OnnxConverter, 提供导出 onnx 模型能力
  • Microsoft.ML.AutoML, 实现自动超参调优

除了常规的机器学习外, Microsoft.ML 可基于下面深度学习框架, 搭建常用的深度神经网络:

  • TorchSharp
  • TensorFlow.NET

自定义模型的 ModelInput 类:

ModelInput 作为模型输入数据 IDataView 的 Row class, 为模型提供 Feature列(1个或多个) 和 Label(1个).

两个特性的作用:

  • [ColumnName] 用来设定列名, 如果没有使用该特性, 模型将按照C#字段名来使用该列.
  • [LoadColumn] 用来设定该类对应 Txt 的第几个列, 需要从 0 开始.

如前所述, ModelInput将为模型提供 Feature 列(1个或多个) 和 Label(1个). 其中 Label 列将作为模型train data的结果标签, 对于回归类模型, Label 字段应该为 float, 对于分类模型, Label 列可以使字符串或数值类型, 如果是字符串型, 需要在pipeline中将它转成数值型. Label 列可以在 ModelInput 类字段上使用 ColumnName("Label") 特性来设定, 也可以在 pipeline 中使用 Context.Transforms.CopyColumns() 来动态指定 Label 对应的字段名.

模型还需要 Features 信息, 不能直接使用C#特性来设定, 需要在Pipeline中用代码设定.

public class ModelInput
 {
    [ColumnName("Temperature"), LoadColumn(0)]
    public float Temperature { get; set; }

    [ColumnName("Luminosity"), LoadColumn(1)]
    public float Luminosity { get; set; }

    [ColumnName("Infrared"), LoadColumn(2)]
    public float Infrared { get; set; }

    [ColumnName("Distance"), LoadColumn(3)]
    public float Distance { get; set; }

    [ColumnName("CreatedAt"), LoadColumn(4)]
    public string CreatedAt { get; set; }

    [ColumnName("Label"), LoadColumn(5)]
    public string Source { get; set; }
    }

自定义回归模型的 ModelOutput 类:

针对不同的 estimator, ModelOuput 需要有不同的 IDataView Row class, 可以使用 [ColumnName()] 特性为C#字段设定成estimator要求的列名.

Regression

  • Label: Original regression value of the example.
  • Score: Predicted regression value.

Binary Classification

  • Label: Original Label of the example.
  • Score: Raw score from the learner (e.g. value before applying sigmoid function to get probability).
  • Probability: Probability of being in certain class
  • PredictedLabel: Predicted class.

Multi-class Classification

  • Label: Original Label of the example.
  • Score: Its an array whose length is equal to number of classes and contains probability for each class.
  • PredictedLabel: Predicted class.

Clustering

  • Label: Original cluster Id of the example.
  • Score: Its an array whose length is equal to number of clusters. It contains square distance from the cluster centeriod.
  • PredictedLabel: Predicted cluster Id.
  public class ModelOutput
    {
        [ColumnName("Score")]
        public float TotalStockQty;
    }

Pipeline 的构成

  • Pipeline 包含一系列前置 transformers 和一个 estimator 和一系列后置的 transformers
  • 前置 transformer 完成数据的预处理过程, transformer 的输入和输出都是 IDataView 数据. IDataView 数据是一个带有 schema 信息的、 immutable、lazy loading的高效数据容器. 通常预处理包括: 删除某些列、 Categorical 矢量化 、Label 列数值化、归一化处理、 聚合 Features 。
  • estimator 用作模型训练.
  • 后置 transformer 完成数据的后处理过程, transformer 的输入和输出都是 IDataView 数据, 后处理过程不像前处理过程复杂, 很多情况下没有后处理过程, 除非前处理过程中包含了Label 列数值化, 这时候我们需要加一个后处理过程将 PredictedLabel 列进行可读性处理, 即将数值key转换成value。

Pipeline 的预处理

Label 列数值化: 对于分类模型, Label 往往是一个类别字符串, 比如颜色分类或产品分类, 在训练的Pipeline中需要将它们做数值化. 调用的函数是 Transforms.Conversion.MapValueToKey() , 该函数会为 Label 的所有可能值分配一个唯一正整数, 在训练过程中, 会使用该正整数值来代替原始值.
如果预处理阶段做了 Label 列数值化处理, 通常在pipeline后处理中要增加一个 MapKeyToValue() 逆向转换, 以便使用该模型做推理时候, 输出的label具有更好的可读性, 如果推理结果出现了未知类别, 默认会分配0值.

mlContext.Transforms.Conversion.MapValueToKey("Label")

OneHot Encoding(即Categorical 信息矢量化)
对于 ModelInput 类, 如果要将某个文本字段被我们识别需要作为一个特征 Feature, 通常这类文本可以看做是 Categorical 类别信息, 我们需要先将类别信息做矢量化, 然后再进行 Features 聚合前置处理, 以便机器学习 estimator 能处理这些特征.
一般 Categorical 字段有两种取值:

  1. 一种取值为 "abc" 这样的字段
  2. 另一种是代表编号的数值字段, 编号虽然是数值, 但它并不是数学上的数值, 因为无法做大小比较, 无法做数学运算.

矢量化方式通常是采用 One-hot encoding 编码, 经过这样的编码后, 它们在内存中被映射成一个稀疏的数值矩阵.

mlContext.Transforms.Categorical.OneHotEncoding(outputColumnName: "label_hotencoded", inputColumnName: "label")

特征值归一化处理

  • 背景: 不同特征的取值范围差异可能很大, 比如有的特征其中范围是[0,1], 有的特征是[0,1000]之间; 或者特征值的单位不同, 一个是质量一个是长度, 可以在模型训练之前, 先对特征值进行归一化处理,尽量将各个特征的参数值规范到一个合理的差异水平, 避免因为个别特征值太大主导模型训练.

  • 模型类型:
    (1) 对于线性模型 SdcaRegressionTrainer、SdcaMaximumEntropyTrainer 等, 这些模型对于特征值大小比较敏感, 如果特征值取值范围差异过大, 模型权重可能会失衡, 会影响到模型效果.

    (2) 对于决策树类模型, 它们是通过特征分裂进行决策的, 并不直接依赖特征值, 所以一般不需要做归一化, 当然也可以通过归一化加速模型收敛速度.

    (3) 对于NLP类模型, 无需进行归一化处理.

  • 归一化算法
    (1) Min-Max Normalization , 将特征统一缩放到 [0,1] 之间. 适用于数值差异较大的情况, 但它对于 outliers 数值很敏感, 此时可以考虑使用其他归一化算法, 或者提前将这些 outliers 过滤掉.
    (2) Mean Variance Normalization, 将均值设定为0, 标准差设定为1, 适用于正态分布的数据.
    (3) Logarithmic Scaling 指数缩放算法, 将特征值有数量级差异, 适用于数据差异非常大, 呈指数增长.
    (4) Binning Normalization, 将连续值转换成离散值.

  • 强调:
    (1) 归一化操作仅仅需要在训练的pipeline中设置, 完成模型训练后, 归一化的操作已经保存到模型参数中了, 所以在推理时候无需显式做归一化处理, 模型在推理时自动会应用归一化算法.
    (2) 归一化操作放在pipeline

Features 列向量化前置处理
如果Features列是自然语言, 需要将文本转换成特征向量.
mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: "SentimentText")

Features 聚合前置处理
如果我们的 ModelInput 类有多个 feature 列, 则需要将这些列聚合到一个名称 Features 列, 这样 estimator 就知道需要将哪些列作为特征来对待.

mlContext.Transforms.Concatenate("Features",
    new string[] { "Temperature", "Luminosity", "Infrared", "Distance" })

Pipeline 的后处理

后置 transformer 完成数据的后处理过程, transformer 的输入和输出都是 IDataView 数据, 后处理过程不像前处理过程复杂, 很多情况下没有后处理过程, 除非前处理过程中包含了Label 列数值化, 这时候我们需要加一个后处理过程将 PredictedLabel 列进行可读性处理, 即将数值key转换成value。

mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel");

分析模型的特征重要度

在模型训练完毕, 通常我们需要了解各个特征的重要程度, 分析的目的有: (1) 理解模型是如何决策的, 尤其对于黑箱模型, 如随机森林和梯度提升树. (2) 排除无关或冗余的特征, 然后重新训练, 以提供模型的泛化能力.

常用方法

批量和单一推理

  //对测试数据集进行批量预测.
  var metrics = mlContext.Regression.Evaluate(model.Transform(testData), labelColumnName: "Target");

  //使用 predictor单独一个数据进行预测.
  var predictor = mlContext.Model.CreatePredictionEngine<IrisInput, IrisPrediction>(model);
  var prediction = predictor.Predict(new IrisInput
    {
        SepalLength = 4.1f,
        SepalWidth = 0.1f,
        PetalLength = 3.2f,
        PetalWidth = 1.4f
    });

当模型训练完成后, 获取混淆矩阵

 var metrics = mlContext.MulticlassClassification.Evaluate(predictions, Label, Score, PredictedLabel);
 Console.WriteLine(metrics.ConfusionMatrix.GetFormattedConfusionTable());

当模型训练完成后, 可以获取模型的权重和偏置项.

  VBuffer <float>[] weights = default;
  model.Model.GetWeights(ref weights,   out int numClasses);
  var biases = model.Model.GetBiases();

输出特征重要性

var featureImportance = mlContext.Regression.PermutationFeatureImportance(
    model.LastTransformer,
    transformedTestData,
    labelColumnName: "Label");

// 输出特征重要性分数, 分数越接近0的特征越不重要
for (int i = 0; i < featureImportance.Length; i++)
{
    Console.WriteLine($"Feature {i}: Importance = {featureImportance[i].Rms.Mean:F4}");
}

关于交叉验证

最常用的是 5 折交叉验证法, 因为它符合20:80数据分割规则. 5折交叉验证的程是, 先将数据集分成 5 等份, 然后开始 5 次验证过程, 所以交叉验证是比较耗时的.
交叉验证完整过程:

  • 第1次验证: 将第1等份数据作为验证数据集, 其他4份作为训练数据集, 先训练后验证, 得出第1次的验证.
  • 第2次验证: 将第2等份数据作为验证数据集, 其他4份作为训练数据集, 先训练后验证, 得出第2次的验证.
  • 第3次验证: 将第3等份数据作为验证数据集, 其他4份作为训练数据集, 先训练后验证, 得出第3次的验证.
  • 第4次验证: 将第4等份数据作为验证数据集, 其他4份作为训练数据集, 先训练后验证, 得出第4次的验证.
  • 第5次验证: 将第5等份数据作为验证数据集, 其他4份作为训练数据集, 先训练后验证, 得出第5次的验证.
  • 最后将5次验证的指标做平均/方差计算得到交叉验证的指标.

评估模型

https://www.todaysoftmag.com/article/3286/machine-learning-101-with-microsoft-ml-net-part-1-3
https://www.todaysoftmag.com/article/3290/machine-learning-101-with-microsoft-ml-net-part-2-3
https://rubikscode.net/2021/04/12/machine-learning-with-ml-net-evaluation-metrics/
https://learn.microsoft.com/en-us/dotnet/machine-learning/resources/metrics

Auto ML

https://accessibleai.dev/post/ml_net-video-game-classification/
https://learn.microsoft.com/en-us/dotnet/machine-learning/automate-training-with-model-builder#how-long-should-i-train-for