防止sigmoid和tanh激活函数溢出的C++实现

499 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

引言

上一期,我们介绍了softmax函数的C++实现,但是考虑到sigmoid和tanh函数也是带ee的次幂,所以现在我们来考虑该函数的防止溢出实现。

sigmoid函数

原理

该函数的公式为:

11+ex\frac{1}{1+e^{-x}}

x0x\geq 0的时候,ex1e^{-x} \leq 1,不会溢出,但是在x<0x < 0的时候,就有可能溢出了。所以在x<0x<0时,我们可以做如下变换:

11+ex=1ex(1+ex)ex=exex+1\frac{1}{1+e^{-x}}=\frac{1\cdot e^x}{(1+e^{-x})\cdot e^x}=\frac{e^x}{e^x+1}

这样ex<1e^x<1,也不会溢出了。

实现

    double sigmoid(double x)
    {
        if (x > 0)
            return 1.0 / (1.0 + exp(-x));
        else
            return exp(x) / (1.0 + exp(x));
    }

tanh函数

原理

该函数的公式为:

exexex+ex\frac{e^x-e^{-x}}{e^x+e^{-x}}

那么在xx很大或者很小时,都有可能溢出,所以我们分开考虑。

1、x0x\geq0

这时exe^x可能溢出,ex<1e^{-x}<1不会溢出。我们进行如下变换:

exexex+ex=ex(exex)ex(ex+ex)=1e2x1+e2x\frac{e^x-e^{-x}}{e^x+e^{-x}}=\frac{e^{-x}\cdot (e^x-e^{-x})}{e^{-x}\cdot (e^x+e^{-x})}=\frac{1-e^{-2x}}{1+e^{-2x}}

1、x<0x<0

这时exe^{-x}可能溢出,ex<1e^{x}<1不会溢出。我们进行如下变换:

exexex+ex=ex(exex)ex(ex+ex)=e2x1e2x+1\frac{e^x-e^{-x}}{e^x+e^{-x}}=\frac{e^{x}\cdot (e^x-e^{-x})}{e^{x}\cdot (e^x+e^{-x})}=\frac{e^{2x}-1}{e^{2x}+1}

这样就都不会溢出了。

实现

    double tanh(double x)
    {
        if(x > 0)
            return (1-exp(-2*x))/(1+exp(-2*x));
        else
            return (exp(2*x)-1)/(1+exp(2*x));
    }