下溢(underflow):当接近零的数被四舍五入为零时发生下溢。许多函数在其参数为零而不是一个很小的正数时才会表现出质的不同。例如,我们通常要避免被零除或避免取零的对数。

上溢(overflow):当大量级的数被近似为∞或-∞时发生上溢。进一步的运算通常会导致这些无限值变为非数字。

必须对上溢和下溢进行数值稳定的一个例子是softmax函数(softmax function).softmax函数经常用于预测与Multinoulli分布相关联的概率,定义为:

考虑一下当所有xi都等于某个常数c时会发生什么。从理论分析上说,我们可以发现所有的输出都应该为1/n。从数值计算上说,当c量级很大时,这可能不会发生。如果c是很小的负数,exp(c)就会下溢。这意味着softmax函数的分母会变成0,所以最后的结果是未定义的。当c是非常大的正数时,exp(c)的上溢再次导致整个表达式未定义。这两个困难能通过计算softmax(z)同时解决,其中z=x-maxixi.简单的代数计算表明,softmax解析上的函数值不会因为从输入向量减去或加上标量而改变。减去maxixi导致exp的最大参数为0,这排除了上溢的可能性。同样地,分母中至少有一个值为1的项,这就排除了因分母下溢而导致被零除的可能性。

还有一个小问题。分子中的下溢仍可以导致整体表达式被计算为零。这意味着,如果我们在计算log(softmax(x))时,先计算softmax再把结果传给log函数,会错误地得到-∞。相反,我们必须实现一个单独的函数,并以数值稳定的方式计算log(softmax)。我们可以使用相同的技巧来稳定log(softmax)函数。

Softmax函数:在数学,尤其是概率论和相关领域中,Softmax函数,或称归一化指数函数,是逻辑函数的一种推广。它能将一个含任意实数的K维的向量z的”压缩”到另一个K维实向量σ(z)中,使得每一个元素的范围都在(0,1)之间,并且所有元素的和为1。该函数的形式通常按下面的式子给出:其中,j=1,…,K.

Softmax函数实际上是有限项离散概率分布的梯度对数归一化。因此,Softmax函数在包括多项逻辑回归,多项线性判别分析,朴素贝叶斯分类器和人工神经网络等的多种基于概率的多分类问题方法中都有着广泛应用。

The softmax function is often used in the final layer of a neural network-based classifier. Such networks are commonly trained under a log loss (or cross-entropy) regime, giving a non-linear variant of multinomial logistic regression.

Softmax可作为神经网络中的输出层,用于多分类(sigmoid只能用于二分类,而softmax可用于多分类。使用Logistic函数来实现二分类问题,对于多分类问题,可以使用多项Logistic回归,该方法也被称之为softmax函数);Softmax还可以解决学习速度衰退的问题;softmax还可作为loss function。

softmax函数的导数如下:

以上内容主要摘自:《深度学习中文版》 和 维基百科

以下是C++实现的测试code:

  1. #include "funset.hpp"
  2. #include <math.h>
  3. #include <iostream>
  4. #include <string>
  5. #include <vector>
  6. #include <opencv2/opencv.hpp>
  7. #include "common.hpp"
  8.  
  9. // ========================= Activation Function: softmax =====================
  10. template<typename _Tp>
  11. int activation_function_softmax(const _Tp* src, _Tp* dst, int length)
  12. {
  13. const _Tp alpha = *std::max_element(src, src + length);
  14. _Tp denominator{ 0 };
  15.  
  16. for (int i = 0; i < length; ++i) {
  17. dst[i] = std::exp(src[i] - alpha);
  18. denominator += dst[i];
  19. }
  20.  
  21. for (int i = 0; i < length; ++i) {
  22. dst[i] /= denominator;
  23. }
  24.  
  25. return 0;
  26. }
  27.  
  28. template<typename _Tp>
  29. int activation_function_softmax_derivative(const _Tp* src, _Tp* dst, int length)
  30. {
  31. std::vector<_Tp> y(length, (_Tp)0);
  32. activation_function_softmax(src, y.data(), length);
  33.  
  34. fprintf(stderr, "Error: activation_function_softmax_derivative to do ...\n");
  35. return -1;
  36. }
  37.  
  38. int test_activation_function()
  39. {
  40. std::vector<float> src{ 1.23f, 4.14f, -3.23f, -1.23f, 5.21f, 0.234f, -0.78f, 6.23f };
  41. int length = src.size();
  42. std::vector<float> dst(length);
  43.  
  44. fprintf(stderr, "source vector: \n");
  45. fbc::print_matrix(src);
  46. fprintf(stderr, "calculate activation function:\n");
  47.  
  48. fprintf(stderr, "type: sigmoid result: \n");
  49. fbc::activation_function_sigmoid(src.data(), dst.data(), length);
  50. fbc::print_matrix(dst);
  51. fprintf(stderr, "type: sigmoid derivative result: \n");
  52. fbc::activation_function_sigmoid_derivative(src.data(), dst.data(), length);
  53. fbc::print_matrix(dst);
  54. fprintf(stderr, "type: sigmoid fast result: \n");
  55. fbc::activation_function_sigmoid_fast(src.data(), dst.data(), length);
  56. fbc::print_matrix(dst);
  57.  
  58. fprintf(stderr, "type: softplus result: \n");
  59. fbc::activation_function_softplus(src.data(), dst.data(), length);
  60. fbc::print_matrix(dst);
  61. fprintf(stderr, "type: softplus derivative result: \n");
  62. fbc::activation_function_softplus_derivative(src.data(), dst.data(), length);
  63. fbc::print_matrix(dst);
  64.  
  65. fprintf(stderr, "type: ReLU result: \n");
  66. fbc::activation_function_ReLU(src.data(), dst.data(), length);
  67. fbc::print_matrix(dst);
  68. fprintf(stderr, "type: ReLU derivative result: \n");
  69. fbc::activation_function_ReLU_derivative(src.data(), dst.data(), length);
  70. fbc::print_matrix(dst);
  71.  
  72. fprintf(stderr, "type: Leaky ReLUs result: \n");
  73. fbc::activation_function_Leaky_ReLUs(src.data(), dst.data(), length);
  74. fbc::print_matrix(dst);
  75. fprintf(stderr, "type: Leaky ReLUs derivative result: \n");
  76. fbc::activation_function_Leaky_ReLUs_derivative(src.data(), dst.data(), length);
  77. fbc::print_matrix(dst);
  78.  
  79. fprintf(stderr, "type: Leaky ELUs result: \n");
  80. fbc::activation_function_ELUs(src.data(), dst.data(), length);
  81. fbc::print_matrix(dst);
  82.  
  83. fprintf(stderr, "type: softmax result: \n");
  84. fbc::activation_function_softmax(src.data(), dst.data(), length);
  85. fbc::print_matrix(dst);
  86. fprintf(stderr, "type: softmax derivative result: \n");
  87. fbc::activation_function_softmax_derivative(src.data(), dst.data(), length);
  88. fbc::print_matrix(dst);
  89.  
  90. return 0;
  91. }

GitHubhttps://github.com/fengbingchun/NN_Test

激活函数之softmax介绍及C++实现的更多相关文章

  1. 02tensorflow非线性回归以及分类的简单实用,softmax介绍

    import tensorflow as tf import numpy as np import matplotlib.pyplot as plt # 使用numpy生成200个随机点 x_data ...

  2. Tensorflow 2.0 深度学习实战 —— 详细介绍损失函数、优化器、激活函数、多层感知机的实现原理

    前言 AI 人工智能包含了机器学习与深度学习,在前几篇文章曾经介绍过机器学习的基础知识,包括了监督学习和无监督学习,有兴趣的朋友可以阅读< Python 机器学习实战 >.而深度学习开始只 ...

  3. 激活函数Sigmoid、Tanh、ReLu、softplus、softmax

    原文地址:https://www.cnblogs.com/nxf-rabbit75/p/9276412.html 激活函数: 就是在神经网络的神经元上运行的函数,负责将神经元的输入映射到输出端. 常见 ...

  4. 直白介绍卷积神经网络(CNN)【转】

    英文地址:https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/ 中文译文:http://mp.weixin.qq.com/s ...

  5. 激活函数(relu,prelu,elu,+BN)对比on cifar10

    激活函数(relu,prelu,elu,+BN)对比on cifar10   可参考上一篇: 激活函数 ReLU.LReLU.PReLU.CReLU.ELU.SELU  的定义和区别   一.理论基础 ...

  6. softmax 杂谈

    在多分类问题中,我们可以使用 softmax 函数,对输出的值归一化为概率值.下面举个例子: import sys sys.path.append("E:/zlab/") from ...

  7. Keras手写识别例子(1)----softmax

    转自:https://morvanzhou.github.io/tutorials/machine-learning/keras/2-2-classifier/#测试模型 下载数据: # downlo ...

  8. 【NLP面试QA】激活函数与损失函数

    目录 Sigmoid 函数的优缺点是什么 ReLU的优缺点 什么是交叉熵 为什么分类问题的损失函数为交叉熵而不能是 MSE? 多分类问题中,使用 sigmoid 和 softmax 作为最后一层激活函 ...

  9. DL基础补全计划(二)---Softmax回归及示例(Pytorch,交叉熵损失)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

随机推荐

  1. Java中private、protected、public和default的区别-001

    public: 具有最大的访问权限,可以访问任何一个在classpath下的类.接口.异常等.它往往用于对外的情况,也就是对象或类对外的一种接口的形式. protected: 主要的作用就是用来保护子 ...

  2. Python基础笔记系列十二:requests模块的简单应用

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! httpbin httpbin这个网站能测试 HTTP 请求和响应的各种信 ...

  3. java 获取今天,昨天,上个月的日期

    获取今天,昨天,上个月的日期 的方法: Calendar cal = Calendar.getInstance(); //获取今天的日期 cal.setTime(new Date()); int ye ...

  4. 12 Essential Bootstrap Tools for Web Designers

    12 Essential Bootstrap Tools for Web Designers Posted by vikas on June 6, 2014, filed in: Tools, Web ...

  5. Kotlin Android Studio 环境搭建

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源. Kotlin 可以编译成Java字节码,也可以编 ...

  6. linux五大搜索命令学习

    五大搜索命令学习 分别解释locate,find,which,whereis,grep 五大linux搜索命令 locate 解释:由man手册可以看出,locate查找就是根据文件名进行查找,只是依 ...

  7. Java中unicode增补字符(辅助平面)相关用法简介

    转载自 http://blog.csdn.net/gjb724332682/article/details/51324036 前言 Java从1.5版本开始,加入了unicode辅助平面的支持.相关的 ...

  8. Java编码方式再学

    一直以来对编码方式对了解不是很深入.建议读下这几篇博文 学点编码知识又不会死:Unicode的流言终结者和编码大揭秘 编码研究笔记 这几篇博文上回答了内心存在的一些问题,这些问题可能也是大家经常遇到的 ...

  9. Python绘图技巧

    转自:https://www.cnblogs.com/zhizhan/p/5615947.html Python--matplotlib绘图可视化知识点整理 强烈推荐ipython 原文:http:/ ...

  10. C++调用Python脚本中的函数

    1.环境配置 安装完python后,把python的include和lib拷贝到自己的工程目录下 然后在工程中包括进去 2.例子 先写一个python的测试脚本,如下 这个脚本里面定义了两个函数Hel ...