C#开源跨平台机器学习框架ML.NET----结合SqlSugar进行多类分类

点击蓝字关注我们

前一篇文章《C#开源跨平台机器学习框架ML.NET----二元分类情绪分析》我们做了ML.NET中二元分类任务的一个小Demo,今天我们来试一下多类分类的Demo。

说明

由于前面我们刚刚学习了SqlSugar的框架,检验学习效果的其中一个方法就是输出,所以这次我们的多类分类里面就把训练数据改为数据库中的数据。

视频演示

实现目标

我们数据库中存在商品信息(tbSpXinXi)和品类信息(tbSpPLXinXi)两个表,商品信息中有一个品类编码(stype)的字段,通过对商品信息的对应的品类码进行训练,实现我们输一个商品名称后系统自动预测出输入的商品属于什么品类的效果。

数据源

品类信息表

上面红框中我们只用到三位数级别的,商品信息中因为是5位的最小级别,我们这里只取到三位对应

商品信息表

商品信息表中字段较多,我们只查询出编码incode,品名fname和品类stype三个字段使用

创建项目

我们用VS2017创建了一个名称为MLSqlSugar的项目,在Nuget安装包中安装上Microsoft.ML和SqlSugar。

SqlSugar

在sqlsugar文件夹下,我们建了一个DBConnect的类,另一个是SqlSugar我们说过的二级缓存的类,详细可以看我以前的文章

窗体布局

  • 窗体布局中我们加入一个ToolStrip里面写了多级分类,主要是以后的分类也在这个Demo中加入,所以用的这个

  • 主界面上加入一个输入文本框,一个按钮和下部的显示文本框

定义类

Goods类

定义的Goods类,对应的就是我们的商品信息类里面就是incode,fname,stype三项,分别是编码,品名和品类码

ResGoods类

ResGoods类为我们预测后的返回类,其中stype就是预测后的结果,Probability为概率,Score为得到的分数。

多类分类实现

流程

进行多类分析的实现顺序

  1. 从数据库获取训练数据

  2. 训练数据并将训练模型存入本地

  3. 输入要预测的数据

  4. 加载训练模型进行数据预测

01

创建训练模型

点击初始化数据按钮

上面是点击初始化数据按钮,实现在提取数据及训练数据并保存到本地

训练

采集数据库数据

获取数据

从数据库中获取商品信息并存入List<Good>集合中,我们把品类stype只取到前三位,通过Order by newid()全部打乱顺序再输出,后面有个分页为取了1200条,这里最后我们说原因

训练

训练并保存数据模型

1

2

3

4

5

02

预测数据

按钮事件

加载模型并预测数据

MLMultiApi代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ML;


namespace MLSqlSugar.Multiclass
{
    /// <summary>
    /// 多类分类训练API
    /// </summary>
    public class MLMultiApi
    {
        //训练数据存档位置
        private string _modelpath = Path.Combine(
            Environment.CurrentDirectory, "stypemodel.zip");
        //定义ML的基本参数
        private MLContext _ml;
        private DataOperationsCatalog.TrainTestData _dataView;
        private IDataView _tranDataView;
        private ITransformer _trainedModel, _testModel;
        private PredictionEngine<Goods, ResGoods> _predEngine;


        /// <summary>
        /// 初始化数据
        /// </summary>
        /// <param name="list"></param>
        public void InitData(IEnumerable<Goods> list)
        {
            //加载数据
            LoadData(list);
            //训练数据
            var pipe = TrainData();
            BuildAndTrainModel(_tranDataView, pipe);
            //测试并保存训练数据
            EvaluateAndSaveModel();
        }


        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="list"></param>
        private void LoadData(IEnumerable<Goods> list)
        {
            _ml = new MLContext(0);
            //加载数据
            _tranDataView = _ml.Data.LoadFromEnumerable(list);
            //拆分数据集进行模拟训练和测试
            _dataView = _ml.Data.TrainTestSplit(_tranDataView, 0.2);
        }


        /// <summary>
        /// 训练数据
        /// </summary>
        /// <returns></returns>
        private IEstimator<ITransformer> TrainData()
        {
            //将stype转换为数字键类型Label(分类算法所接受的格式)
            //并将其添加为新的数据集列
            var pipeline = _ml.Transforms.Conversion
                .MapValueToKey(inputColumnName: "stype"
                    , outputColumnName: "Label")
            //将fname转换为名为fnameFeaturized的值的数字向量,
            //并将特征化附加到管道
            .Append(_ml.Transforms.Text
                    .FeaturizeText(inputColumnName: "fname"
                        , outputColumnName: "fnameFeaturized"))
                //                .Append(_ml.Transforms.Text
                //                .FeaturizeText(inputColumnName: "incode"
                //                    , outputColumnName: "incodeFeaturized"))
                //Concatenate() 方法将所有特征合并到“特征”列 。
                //默认情况下,学习算法仅处理“特征”列的特征 
                .Append(_ml.Transforms.Concatenate(
                    "Features", "fnameFeaturized"));


            return pipeline;
        }


        /// <summary>
        /// 训练数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="pipeline"></param>
        /// <returns></returns>
        private IEstimator<ITransformer> BuildAndTrainModel(
            IDataView data, IEstimator<ITransformer> pipeline)
        {
            //SdcaMaximumEntropy 即多类分类训练算法
            var trainingPipeline = pipeline.Append(_ml.MulticlassClassification
                    .Trainers.SdcaMaximumEntropy("Label", "Features"))
                .Append(_ml.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
            //定型模型
            _trainedModel = trainingPipeline.Fit(data);
            //定义训练的模型进行预测
            _predEngine = _ml.Model.CreatePredictionEngine
                <Goods, ResGoods>(_trainedModel);


            Goods good=new Goods();
            good.incode = "00090";
            good.fname = "神行鞋垫";


            var prediction = _predEngine.Predict(good);
            Console.WriteLine("stype:" + prediction.stype + " percent:"+ prediction.Percent + " score:"+ prediction.Score[0] + "," + prediction.Score[1]);


            return trainingPipeline;
        }


        /// <summary>
        /// 评估模型
        /// </summary>
        public void EvaluateAndSaveModel()
        {
            //用测试数据进行预测
            var testMetrics = _ml.MulticlassClassification
                .Evaluate(_trainedModel.Transform(_dataView.TestSet));
            Console.WriteLine($"Metrics for Multi-class Classification model - Test Data     ");
            Console.WriteLine($"MicroAccuracy:    {testMetrics.MicroAccuracy:0.###}");
            Console.WriteLine($"MacroAccuracy:    {testMetrics.MacroAccuracy:0.###}");
            Console.WriteLine($"LogLoss:          {testMetrics.LogLoss:#.###}");
            Console.WriteLine($"LogLossReduction: {testMetrics.LogLossReduction:#.###}");
            //保存模型
            _ml.Model.Save(_trainedModel, _dataView.TrainSet.Schema, _modelpath);
        }


        /// <summary>
        /// 初始化并加载保存的模型
        /// </summary>
        public void InitFinalModel()
        {
            _ml = new MLContext(0);
            _testModel = _ml.Model.Load(_modelpath, out var modelInputSchema);
        }


        /// <summary>
        /// 进行预测
        /// </summary>
        /// <param name="good"></param>
        /// <returns></returns>
        public ResGoods Predict(Goods good)
        {
            _predEngine = _ml.Model.CreatePredictionEngine
                <Goods, ResGoods>(_testModel);


            return _predEngine.Predict(good);
        }
    }
}


运行效果

划重点

多类分类做的时候遇到的几个问题

上图中我们获取数据训练时分页数据用的是1200条,我这里试过,只要写到1300或再大的,就直接没有训练成功,怀疑过是有个临界点超过后需要训练时间非常长?所以花了9个半小时晚上训练20000条还是没有结果,这里有知道什么原因的小伙伴可以留言告诉我,我也非常困惑。

GitHub代码地址

    https://github.com/Vaccae/MLSqlSugar.git

-END-

Vaccae的往期经典

OpenCV

《C++ OpenCV案例实战---卡号获取

《C++ OpenCV案例实战---卡片截取(附代码)

《C++ OpenCV透视变换---切换手机正面图片》

《C++ OpenCV实战---获取数量

《C++ OpenCV实战---利用颜色分割获取数量》

《OpenCV4Android NDK方式进行Canny边缘检测》

《OpenCV4Android NDK方式TesserartOCR实时进行识别》

《OpenCV4Android NDK级联方式实时进行人脸检测》

OpenCV4Android NDK稠密光流调用

Android

《Android利用SurfaceView结合科大讯飞修改语音实别UI

《Android关于语音识别的功能实现分析(一)---结构化思维》

《Android关于语音识别的功能实现分析(二)---语义解析》

《Android根据类生成签名字符串

《Android碎片化布局fragment的实战应用

《Android中RecyclerView嵌套RecyclerView

《Android里用AsyncTask后的接口回调

.Net C#

《C#自定义特性(Attribute)讲解与实际应用

《C#根据类生成签名字符串(附DEMO下载地址)

《C++创建动态库C#调用》

《C#与三菱PLC(型号FX2N)串口通讯类

数据库及其它

《Oracel存储过程写报表实战》

《Delphi轮播视频和图片程序(用于双屏显示程序)

《SQL随机增加销售数据的脚本编写(附脚本下载地址)

SQL Server中With As的介绍与应用(三)--递归的实战应用

《Oracle通过ODBC连接SQL Server数据库

Oracle利用row_number()over()方式解决插入数据时重复键的问题

 

请扫码

给个关注

微卡智享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值