本章我们将学习以下内容:

l  什么是微基准测试

l  如何将它应用到代码中

l  什么是激活函数

l  如何绘制和基准测试激活函数

每个开发人员都需要有一个好的基准测试工具。质量基准无处不在;你们每天都能听到,这个减少了10%那个增加了25%还记得那句老话吗,当你听到一个数字被抛出时,98.4%的情况下这个数字是假的。顺便说一下,这个数字也是我编的。当你听到这样的话,让那个人证明一下,你会得到什么?我们不需要定性的结果;我们需要能够被证明和持续复制的量化结果。可重复的结果是非常重要的,不仅对一致性,而且对可信度和准确性。这就是微基准测试发挥作用的地方。

我们将使用BenchmarkDotNet库,您可以在这里找到:https://github.com/dotnet/BenchmarkDotNet。我认为它是您可以使用的最不可替代的框架之一,我认为它的重要性不亚于单元测试和集成测试

为了展示这个工具的价值,我们将绘制几个激活函数并比较它们的运行时。作为其中的一部分,我们将考虑预热、遗留和RyuJIT、冷启动以及程序执行的更多方面。最后,我们会得到一组定量的结果来证明函数的精确度量。如果在2.0版本中,我们看到某些东西运行得比较慢,我们可以重新运行基准并进行比较。

我强烈建议将其集成到您的持续集成/持续构建过程中,以便在每个版本中都可以比较基准数据。

在本章中,我们将有两个样本。第一个是激活函数查看器;它将绘制每个激活函数,以便我们可以看到它的外观。可以在Colin Green的SharpNEAT中找到它,它是开源的。这个包绝对是不可思议的。我在它的基础上创建了新的ui以及高级版本来满足我的需求,它是目前能找到的最灵活的工具。第一个示例应用程序带有最新的SharpNEAT包,可以在https://github.com/colgreen/sharpneat找到它。

使用视觉绘图方法

下面是一个局部和全局最小值的图,它是由SharpNEAT的自定义版本绘制的。

如前所述,我们将绘制并测试几个激活函数。我们到处都听到激活函数这个词,但我们真的知道它的意思吗?让我们从一个快速的解释开始。

一个激活函数用来决定一个神经元是否被激活。有些人喜欢用fired来代替activated。不管怎样,它最终决定了某个东西是开还是关,是被触发还是没有,是被激活还是没有。

.让我们首先看一个单个激活函数的图:

这是逻辑陡峭近似和Swish激活函数单独绘制时的样子,因为有很多类型的激活函数,这是我们所有的激活函数一起绘制时的样子:

在这一点上,你可能会想,我们为什么还要关心情节是什么样的呢?好问题。我们关心这些,因为一旦你进入神经网络或其他领域,你会经常用到这些。这是非常方便的,能够知道你的激活函数是否将你的神经元的值在开或关的状态,以及它将保持或需要的值在什么范围内。毫无疑问,你将在作为机器学习开发人员的职业生涯中遇到和/或使用激活函数,了解TanH和LeakyReLU激活函数之间的区别非常重要。

绘制所有函数

所有激活函数的绘图都是在一个函数内完成的,这个函数名为PlotAllFunctions:

private void PlotAllFunctions()
{
// 首先,从母版窗格中清除所有旧的GraphPane
collection MasterPane master = zed.MasterPane;
master.PaneList.Clear();
// 显示母版窗格标题,并设置
outer margin to points
master.Title.IsVisible = true;
master.Margin.All = ;
// 在主窗格上绘制多个函数.
PlotOnMasterPane(Functions.LogisticApproximantSteep,"Logistic Steep (Approximant)");
PlotOnMasterPane(Functions.LogisticFunctionSteep,"Logistic Steep (Function)");
PlotOnMasterPane(Functions.SoftSign, "Soft Sign");
PlotOnMasterPane(Functions.PolynomialApproximant,"Polynomial Approximant");
PlotOnMasterPane(Functions.QuadraticSigmoid,"Quadratic Sigmoid");
PlotOnMasterPane(Functions.ReLU, "ReLU");
PlotOnMasterPane(Functions.LeakyReLU, "Leaky ReLU");
PlotOnMasterPane(Functions.LeakyReLUShifted,"Leaky ReLU (Shifted)");
PlotOnMasterPane(Functions.SReLU, "S-Shaped ReLU");
PlotOnMasterPane(Functions.SReLUShifted,"S-Shaped ReLU (Shifted)");
PlotOnMasterPane(Functions.ArcTan, "ArcTan");
PlotOnMasterPane(Functions.TanH, "TanH");
PlotOnMasterPane(Functions.ArcSinH, "ArcSinH");
PlotOnMasterPane(Functions.ScaledELU,"Scaled Exponential Linear Unit");
// 重新设置GraphPanes的轴范围。
zed.AxisChange();
// 使用默认窗格布局布局GraphPanes.
using (Graphics g = this.CreateGraphics())
{
master.SetLayout(g, PaneLayout.SquareColPreferred);
}

主绘制函数

在后台,Plot函数负责执行和绘制每个函数:

private void Plot(Func<double, double> fn, string fnName,Color graphColor, GraphPane gpane = null)
{
const double xmin = -2.0;
const double xmax = 2.0;
const int resolution = ;
zed.IsShowPointValues = true;
zed.PointValueFormat = "e";
var pane = gpane ?? zed.GraphPane;
pane.XAxis.MajorGrid.IsVisible = true;
pane.YAxis.MajorGrid.IsVisible = true;
pane.Title.Text = fnName;
pane.YAxis.Title.Text = string.Empty;
pane.XAxis.Title.Text = string.Empty;
double[] xarr = new double[resolution];
double[] yarr = new double[resolution];
double incr = (xmax - xmin) / resolution;
double x = xmin;
for(int i=; i < resolution; i++, x+=incr)
{
xarr[i] = x;
yarr[i] = fn(x);
}
PointPairList list1 = new PointPairList(xarr, yarr);
LineItem li=pane.AddCurve(string.Empty,list1,graphColor,SymbolType.None);
li.Symbol.Fill = new Fill(Color.White);
pane.Chart.Fill = new Fill(Color.White,
Color.LightGoldenrodYellow, 45.0F);
}

这是执行我们传入的激活函数的地方,它的值用于y轴标绘值。著名的ZedGraph开源绘图包用于所有图形绘制。一旦执行了每个函数,就会生成相应的图。

确定基准点

BenchmarkDotNet生成了几个报告,其中一个是HTML报告,类似于在这里看到的:

Excel报告提供了运行程序时使用的每个参数的详细信息,是最广泛的信息来源。在很多情况下,这些参数中的大多数都使用默认值,超出了我们的需要,但至少我们可以选择删除我们需要删除的内容:

我们将在下一节中描述其中的一些参数,当我们回顾创建之前看到的内容的源代码时:

static void Main(string[] args)
{
var config = ManualConfig.Create(DefaultConfig.Instance);
// 建立一个结果导出器。
// 请注意。默认情况下,结果文件将位于.BenchmarkDotNet.Artifactsresults目录
config.Add(new CsvExporter
          (CsvSeparator.CurrentCulture,
          new BenchmarkDotNet.Reports.SummaryStyle
           {
          PrintUnitsInHeader = true,
          PrintUnitsInContent = false,
          TimeUnit = TimeUnit.Microsecond,
          SizeUnit = BenchmarkDotNet.Columns.SizeUnit.KB
           }
          )
  );
// 遗留JITter 测试.
config.Add(new Job(EnvMode.LegacyJitX64,EnvMode.Clr, RunMode.Short)
  {
  Env = { Runtime = Runtime.Clr, Platform = Platform.X64 },
  Run = { LaunchCount = , WarmupCount = ,
  TargetCount = , RunStrategy =
       BenchmarkDotNet.Engines.RunStrategy.Throughput },
       Accuracy = { RemoveOutliers = true }
    }.WithGcAllowVeryLargeObjects(true)
  );
  // RyuJIT测试。
  config.Add(new Job(EnvMode.RyuJitX64, EnvMode.Clr,RunMode.Short)
    {
      Env = { Runtime = Runtime.Clr, Platform = Platform.X64 },
      Run = { LaunchCount = , WarmupCount = ,
      TargetCount = , RunStrategy =
      BenchmarkDotNet.Engines.RunStrategy.Throughput },
      Accuracy = { RemoveOutliers = true }
    }.WithGcAllowVeryLargeObjects(true)
  );
  // 取消注释以允许对未优化的程序集进行基准测试。
  //config.Add(JitOptimizationsValidator.DontFailOnError);
  // 运行基准测试。
  var summary = BenchmarkRunner.Run<FunctionBenchmarks>(config);
}

让我们进一步分析这段代码:

首先,我们将创建一个手动配置对象,其中包含用于基准测试的配置参数:

var config = ManualConfig.Create(DefaultConfig.Instance);

接下来,我们将设置一个导出器来保存用于导出结果的参数。我们将使用微秒计时和千字节大小将结果导出到.csv文件:

config.Add(new CsvExporter
        (CsvSeparator.CurrentCulture,
         new BenchmarkDotNet.Reports.SummaryStyle
         {
           PrintUnitsInHeader = true,
           PrintUnitsInContent = false,
           TimeUnit = TimeUnit.Microsecond,
           SizeUnit = BenchmarkDotNet.Columns.SizeUnit.KB
         }
        )
);

接下来,我们将创建一个基准作业,它将处理x64体系结构上LegacyJitX64的度量。您可以随意更改此参数和任何其他参数,以进行实验,或者包含测试场景所需或需要的任何结果。在我们的例子中,我们将使用x64平台;启动计数、预热计数和目标计数为1;以及吞吐量的运行策略。我们也会对RyuJIT做同样的事情,但是我们不会在这里显示代码:

config.Add(new Job(EnvMode.LegacyJitX64, EnvMode.Clr,RunMode.Short)
       {
         Env = { Runtime = Runtime.Clr, Platform = Platform.X64 },
        Run = { LaunchCount = , WarmupCount = , TargetCount = ,
        RunStrategy = Throughput },
        Accuracy = { RemoveOutliers = true }
      }.WithGcAllowVeryLargeObjects(true)
);

最后,我们将运行BenchmarkRunner来执行我们的测试:

var summary = BenchmarkRunner.Run<FunctionBenchmarks>(config);

BenchmarkDotNet将作为DOS命令行应用程序运行,下面是执行上述代码的一个例子:

让我们来看一个被绘制的激活函数的例子:

[Benchmark]
public double LogisticFunctionSteepDouble()
{
  double a = 0.0;
  for(int i=; i<__loops; i++)
  {
    a = Functions.LogisticFunctionSteep(_x[i % _x.Length]);
  }
  return a;
}

此处使用了[Benchmark]属性。这向BenchmarkDotNet表明,这将是一个需要进行基准测试的测试。在内部调用如下函数:

对于logisticfunction陡峭函数,其实现与大多数激活函数一样简单(假设你知道公式)。在这种情况下不是绘制激活函数,而是对其进行基准测试。

你将注意到函数接受并返回double。我们也通过使用和返回浮点变量对相同的函数进行基准测试,因此我们使用double对函数之间的差异进行基准测试和浮动。因此,人们可以看到,有时性能影响比他们想象的要大:

总结

在本章中,我们学习了如何将微基准测试应用到代码中。我们还了解了如何绘制和基准测试激活函数,以及如何使用微基准测试。现在,您有了一个最强大的基准测试库,可以将其添加到所有代码中。在下一章中,我们将深入探讨直观的深度学习,并向您展示c#开发人员可以使用的最强大的机器学习测试框架之一。

基于C#的机器学习--微基准测试和激活功能的更多相关文章

  1. 基于C#的机器学习--目录

    转载请注明出处:https://www.cnblogs.com/wangzhenyao1994/p/10223666.html 文章发表的另一个地址:https://blog.csdn.net/wyz ...

  2. 基于C#的机器学习--深层信念网络

    我们都听说过深度学习,但是有多少人知道深度信念网络是什么?让我们从本章开始回答这个问题.深度信念网络是一种非常先进的机器学习形式,其意义正在迅速演变.作为一名机器学习开发人员,对这个概念有一定的了解是 ...

  3. Java12新特性 -- 微基准测试套件

    JMH,即Java Microbenchmark Harness,是专门用于代码微基准测试的工具套件.何谓Micro Benchmark呢?简单的来说就是基于方法层面的基准测试,精度可以达到微秒级.当 ...

  4. [译]使用JMH进行微基准测试:不要猜,要测试!

    英文原文:Micro Benchmarking with JMH: Measure, don't guess!翻译地址:使用JMH进行微基准测试:不要猜,要测试!原文作者:Antonio翻译作者:Ho ...

  5. Java监控工具介绍,VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,Java微基准测试

    本文是本人前一段时间做一个简单Java监控工具调研总结,主要包括VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,以及对Java微基准测试的简单介绍, ...

  6. 基于Spring Cloud的微服务入门教程

    (本教程的原地址发布在本人的简书上:http://www.jianshu.com/p/947d57d042e7,若各位看官有什么问题或不同看法请在这里或简书留言,谢谢!) 本人也是前段时间才开始接触S ...

  7. 基于Python的机器学习实战:KNN

    1.KNN原理: 存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系.输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应 ...

  8. 干货|基于 Spring Cloud 的微服务落地

    转自 微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的 ...

  9. 基于Spring Cloud的微服务落地

    微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持. 在Java生态圈,目前使用较多的微服务 ...

随机推荐

  1. 了解 XML 数字签名

    http://www.cnblogs.com/flyxing/articles/91734.html http://www.cnblogs.com/wuhong/archive/2010/12/20/ ...

  2. SqlServer 使用脚本创建分发服务及事务复制的可更新订阅

    原文:SqlServer 使用脚本创建分发服务及事务复制的可更新订阅 [创建使用本地分发服务器] /************************[使用本地分发服务器配置发布]*********** ...

  3. ARTS 12.10 - 12.14

    从陈皓博主的专栏里学到一个概念,争取可以坚持下去: 我在我的读者群中推荐出 ARTS 的任务,每个人每周一个 Algorithm,Review 一篇英文文章,总结一个工作中的技术 Tip,以及 Sha ...

  4. 算法之--字符串包含【python实现】

    题目描述 给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短.请问,如何最快地判断字符串B中所有字母是否都在字符串A里? 为了简单起见,我们规定输入的字符串只包含大写英文字母,请实 ...

  5. Win10的UWP之进度条

    原文:Win10的UWP之进度条 关于UWP的进度条的处理的方案有两种方案 我们新建一个项目,然后处理的界面如下的代码 <Grid.RowDefinitions> <RowDefin ...

  6. 微软Skype实时口译增加中文

    直击现场 在机器翻译技术上,微软的 Skype 业务也算是行业内名列前茅.日前其实时口语翻译技术再次跃升一个台阶,新增了对中文(普通话)的翻译支持. 据美国科技新闻网站 TheVerge 报道,此前, ...

  7. 开启Qt Lite Project

    发布: http://blog.qt.io/blog/2017/01/23/qt-5-8-released/ 说法一:Qt Lite” is not a tool, but a concept tha ...

  8. nice-validator表单验证插件的简单使用

    前言 前端表单校验是过滤无效数据.假数据.有毒数据的第一步,是数据安全的第一道关卡,虽然我们不能100%相信客户端提交的数据(真正的校验还得在服务端进行),但设置前端表单校验也是至关重要的,自己写逻辑 ...

  9. Spring Boot的学习之路(01):缘起

    有人说,Spring Boot的出现,让Java迎来了又一春,它是Java应用开发的颠覆者,彻底改变了Java应用开发的模式. 2017年,SpringBoot闯入我的生活, 也让我迎来了又一春 我开 ...

  10. 如何使用VS Code编写Spring Boot (第二弹)

    本篇文章是续<如何使用VS Code编写Spring Boot> 之后,结合自己.net经验捣鼓的小demo,一个简单的CRUD,对于习惯了VS操作模式的.net人员非常方便,强大的智能提 ...