• 基于CNTK/C#实现逻辑回归【附源码】



    前言

    本文基于CNTK实现逻辑回归二分类,并以之前的不同,本次使用C#实现,不适用python,python版的CNTK比较简单,而且python版的cntk个人感觉没什么必要,毕竟是微软的框架因此本人强迫症犯了,所以使用C#实现CNTK
    环境版本:
    Visualstudio 2022
    C# .net4.6
    cntk 2.7
    cuda 10.1


    一、VS2022+CNTK环境搭建

    首先把CNTK的需要的dll解压出来,可直接从此处免费下载:
    CNTK安装
    然后再项目上引入dll,如图:
    在这里插入图片描述


    二、逻辑回归代码构建

    1.逻辑回归构建

    在这里插入图片描述
    从网上对逻辑回归的图的解释,可以使用CNTK很容易就可以构建逻辑回归的结构

    private static Function CreateLinearModel(Variable input, int outputDim, DeviceDescriptor device)
    {
        int inputDim = input.Shape[0];
        var weightParam = new Parameter(new int[] { outputDim, inputDim }, DataType.Float, 1, device, "w");
        var biasParam = new Parameter(new int[] { outputDim }, DataType.Float, 0, device, "b");
    
        return CNTKLib.Times(weightParam, input) + biasParam;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里的可以简单的理解为y=kx+b的结构。

    2.训练数据的生成

    这里主要是每次训练的时候会生成一批数据,首先对输入批次/输出批次构建数组,然后使用随机数种子,生成一批数据,服从高斯分布随机数,注意这里的mean和std

    private static double GenerateGaussianNoise(double mean, double stdDev, Random random)
    {
         double u1 = 1.0 - random.NextDouble();
         double u2 = 1.0 - random.NextDouble();
         double stdNormalRandomValue = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
         return mean + stdDev * stdNormalRandomValue;
     }
     private static void GenerateRawDataSamples(int sampleSize, int inputDim, int numOutputClasses, out float[] features, out float[] oneHotLabels)
     {
         Random random = new Random(0);
    
         features = new float[sampleSize * inputDim];
         oneHotLabels = new float[sampleSize * numOutputClasses];
    
         for (int sample = 0; sample < sampleSize; sample++)
         {
             int label = random.Next(numOutputClasses);
             for (int i = 0; i < numOutputClasses; i++)
             {
                 oneHotLabels[sample * numOutputClasses + i] = label == i ? 1 : 0;
             }
    
             for (int i = 0; i < inputDim; i++)
             {
                 features[sample * inputDim + i] = (float)GenerateGaussianNoise(3, 1, random) * (label + 1);
             }
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    3.模型训练

    static void Main(string[] args)
    {
        //设置逻辑回归的输入和输出的量,三入二出,因逻辑回归基本是二分类,因此这里输出的是2
        int inputDim = 3;
        int numOutputClasses = 2;
        
        //使用GPU模块
        var device = DeviceDescriptor.GPUDevice(0);
        
        //设置输入输出
        Variable featureVariable = Variable.InputVariable(new int[] { inputDim }, DataType.Float);
        Variable labelVariable = Variable.InputVariable(new int[] { numOutputClasses }, DataType.Float);
    
        //网络结构的构建及损失计算,这里使用CNTK的Softmax
        var classifierOutput = CreateLinearModel(featureVariable, numOutputClasses, device);
        var loss = CNTKLib.CrossEntropyWithSoftmax(classifierOutput, labelVariable);
        var evalError = CNTKLib.ClassificationError(classifierOutput, labelVariable);
        
        //学习率的设置
        TrainingParameterScheduleDouble learningRatePerSample = new TrainingParameterScheduleDouble(0.02, 1);
        IList<Learner> parameterLearners = new List<Learner>() { Learner.SGDLearner(classifierOutput.Parameters(), learningRatePerSample) };
    
        //构建训练迭代器
        var trainer = Trainer.CreateTrainer(classifierOutput, loss, evalError, parameterLearners);
    
        //训练批次
        int minibatchSize = 64;
        int numMinibatchesToTrain = 10000;
        int updatePerMinibatches = 10;
    
        // 循环训练
        for (int minibatchCount = 0; minibatchCount < numMinibatchesToTrain; minibatchCount++)
        {
            Value features, labels;
            GenerateValueData(minibatchSize, inputDim, numOutputClasses, out features, out labels, device);
    
            trainer.TrainMinibatch(new Dictionary<Variable, Value>() { { featureVariable, features }, { labelVariable, labels } }, device);
    
            PrintTrainingProgress(trainer, minibatchCount, updatePerMinibatches);
        }
        Console.ReadLine();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    三、效果展示

    在这里插入图片描述

  • 相关阅读:
    K210+MLX90614红外测温
    《上海悠悠接口自动化平台》-2.extract 提取结果与validate 校验结果
    java项目之高校奖学金管理系统(ssm框架+源码+文档)
    几个算法题解
    SpringBoot 基础篇——基于SpringBoot实现ssm/ssmp整合
    10月10日,每日信息差
    JVM相关面试题及常用命令参数
    java word 转html 的两种方法
    sobel边缘检测算法
    微信答题小程序产品研发-系统架构设计
  • 原文地址:https://blog.csdn.net/ctu_sue/article/details/127628164