Ich habe zusammengefasst, welche Art von Aktivierungsfunktion es gibt. ** Das neueste Swish and Mish sowie tanhExp! ** ** ** Ich ziele auf die Ebene, auf der ich keine gute finden kann, selbst wenn ich die Liste durchsuche. Neue werden hinzugefügt, sobald sie gefunden werden. Wenn Sie Informationen zu neuen Funktionen oder Funktionen in der TODO-Liste unten haben, lassen Sie es uns bitte wissen!
--Überprüfen Sie die Zusatzinformationen der hardShrink-Funktion --Überprüfen Sie die Zusatzinformationen der SoftShrink-Funktion --Überprüfen Sie die Zusatzinformationen der Schwellenwertfunktion --Überprüfen Sie die Zusatzinformationen der logSigmoid-Funktion --Überprüfen Sie die Zusatzinformationen der Funktion tanhShrink --Überprüfen Sie die Zusatzinformationen der Hardtanh-Funktion --Überprüfen Sie die Zusatzinformationen der ReLU6-Funktion --Überprüfen Sie die Zusatzinformationen der CELU-Funktion --Überprüfen Sie die Zusatzinformationen der Softmin-Funktion --Überprüfen Sie die Zusatzinformationen der logSoftmax-Funktion
Zuerst von der Schrittfunktion. Wahrscheinlich die älteste Aktivierungsfunktion. Zu dieser Zeit wurde es verwendet, um Perceptron zu implementieren, aber es wird heutzutage selten im Deep Learning gesehen. Der Grund dafür ist, dass das Differential für alle reellen Zahlen $ 0 $ beträgt ($ x \ ne 0 $), sodass Parameter nicht durch Backpropagation optimiert werden können.
Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
1 & (x \gt 0) \\
0 & (x \le 0)
\end{array}
\right.
So ist die Backpropagation-Formel natürlich
\cfrac{\partial y}{\partial x} = 0
Und multiplizieren Sie dies mit dem fließenden Fehler. Mit anderen Worten, nichts wird vergossen. Aus diesem Grund konnte die Methode der Fehlerrückausbreitung nicht angewendet werden und wurde beim tiefen Lernen in den Schatten gezwungen.
Die Gleichheitsfunktion gibt die Eingabe so aus, wie sie ist. Es wird für die Aktivierungsfunktion der Ausgabeschicht der Regressionsanalyse verwendet. In der mittleren Schicht gibt es keine Wende. Der Zweck der Verwendung einer solchen Aktivierungsfunktion besteht darin, sie eindeutig zu implementieren. Die eindeutige Implementierung soll hier die Verarbeitung nicht durch bedingte Verzweigung oder dergleichen teilen. Da der Differenzwert $ 1 $ ist, wird der Fehler unverändert auf die vorherige Ebene übertragen. Da bei der Fehlerberechnung der quadratische Fehler verwendet wird, beträgt die Ausbreitung zur nächsten Schicht $ y - t $ ~
Die Formel für die Vorwärtsausbreitung lautet
y = x
Und die Rückenausbreitung ist
\cfrac{\partial y}{\partial x} = 1
Es wird sein. Sie können sehen, dass der Wert, der gerade geflossen ist, fließen wird!
Es ist eine ähnliche Funktion wie [Identitätsfunktion](# Konstante Funktionsidentität). Es ist jedoch nicht gerade, sondern leicht gebogen.
Die Formel für die Vorwärtsausbreitung lautet
y = \cfrac{1}{2}(\sqrt{x^2 + 1} - 1) + x
So, Rückausbreitung
\cfrac{\partial y}{\partial x} = \cfrac{x}{2 \sqrt{x^2 + 1}} + 1
Es wird sein. Irgendwie sieht es aus wie [ReLU-Funktion](# Relu-Funktion) (persönlicher Eindruck). Ich konnte den auf Japanisch vorgestellten Artikel nicht auf einen Blick finden, daher denke ich, dass es sich um eine geringfügige Aktivierungsfunktion handelt.
Von Pytorch vorerst nur eine Einführung. ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
x & (x \lt -\lambda \quad \textrm{or} \quad \lambda \lt x) \\
0 & (\textrm{otherwise})
\end{array}
\right.
Und die Rückenausbreitung ist
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
1 & (x \lt -\lambda \quad \textrm{or} \quad \lambda \lt x) \\
0 & (\textrm{otherwise})
\end{array}
\right.
Es wird sein. Der Standardwert für $ \ lambda $ ist $ 0.5 $.
Dies ist auch nur eine Einführung von Pytorch. ** Überprüfen Sie die TODO-Zusatzinformationen *** Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
x + \lambda & (x \lt -\lambda) \\
x - \lambda & (x \gt \lambda) \\
0 & (\textrm{otherwise})
\end{array}
\right.
Und die Rückenausbreitung ist
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
1 & (x \lt -\lambda \quad \textrm{or} \quad \lambda \lt x) \\
0 & (\textrm{otherwise})
\end{array}
\right.
Es wird sein. Der Anfangswert von $ \ lambda $ beträgt hier ebenfalls $ 0,5 $.
Dies ist nur eine Einführung von Pytorch. ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
x & (x \gt threshold) \\
value & (\textrm{otherwise})
\end{array}
\right.
Und die Rückenausbreitung ist
y = \left\{
\begin{array}{cc}
1 & (x \gt threshold) \\
0 & (\textrm{otherwise})
\end{array}
\right.
Es wird sein. Wobei die Variablen Schwelle und Wert Werte sind, die im Voraus angegeben werden sollten. Vorerst passend in der Grafik
threshold = -1 \\
value = -2
Es wird gesagt.
Die Sigmoidfunktion ist eine Aktivierungsfunktion, die häufig verwendet wurde, als die Backpropagation-Methode eingeführt wurde. Es wird jedoch derzeit selten in der mittleren Schicht verwendet, und es wird häufig in der Ausgabeschicht von binären Klassifizierungsproblemen verwendet. Der Grund ist der später beschriebene Nachteil. Vorwärtsausbreitung
y = \cfrac{1}{1 + e^{-x}}
Backpropagation
\cfrac{\partial y}{\partial x} = y(1 - y)
Kann geschrieben werden als Das größte Merkmal ist, dass die Differenzierung leicht von der Ausgabe erhalten werden kann, aber die Reaktion auf extrem große und kleine Eingaben schlecht ist und der maximale Wert der Differenzierung 0,25 $ beträgt. Wenn Sie also Ebenen ** Gradienten stapeln Es gibt auch Nachteile wie das Problem des Verschwindens **. Da es exponentielle Berechnungen und Divisionen gibt, ist die Berechnungslast zwangsläufig höher als die von einfachen Funktionen wie [ReLU-Funktion](# Relu-Funktion).
Die hardSigmoid-Funktion ist eine lineare Annäherung an die Sigmoid-Funktion, beispielsweise eine lineare Funktion. Mathematisch Vorwärtsausbreitung
y = \left\{
\begin{array}{cc}
1 & (x \gt 2.5) \\
0.2x + 0.5 & (-2.5 \le x \le 2.5) \\
0 & (x \lt -2.5)
\end{array}
\right.
Backpropagation
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
0.2 & (-2.5 \le x \le 2.5) \\
0 & (\textrm{otherwise})
\end{array}
\right.
Es sieht aus wie. Es gibt einen Artikel im Detail überprüft. Wenn Sie also mehr wissen möchten, gehen Sie bitte dorthin! Es gibt einen so komplizierten theoretischen Grund, dass der Koeffizient der linearen Funktion $ 0,2 $ beträgt ... ~~ Ich habe es gelesen, aber überhaupt nicht verstanden ~~
Dies ist auch nur eine Einführung von Pytorch. Nimmt den Logarithmus von [Sigmoidfunktion](# Sigmoidfunktion Sigmoid). ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y = \log \left( \cfrac{1}{1 + e^{-x}} \right)
Und Backpropagation
\cfrac{\partial y}{\partial x} = \cfrac{1}{1 + e^x}
Es wird sein. Beachten Sie, dass der Nenner der Backpropagation nicht die Potenz $ -x $ ist.
Die Tanh-Funktion, die eine der Bikurvenfunktionen ist, wurde als eine der Funktionen vorgeschlagen, um die Schwäche zu lösen, dass der Maximalwert der Differenzierung von [Sigmoidfunktion](# Sigmoidfunktion Sigmoid) $ 0,25 $ beträgt. Wie Sie in der Abbildung sehen können, beträgt der Maximalwert des Differentials $ 1 $, und die Ursache für das Verschwinden des Gradienten kann beseitigt werden. Es besteht jedoch immer noch das Problem, dass die Unterscheidung mit extrem großen und kleinen Eingaben $ 0 $ beträgt.
y = \tanh x = \cfrac{e^x - e^{-x}}{e^x + e^{-x}}
Backpropagation
\cfrac{\partial y}{\partial x} = \textrm{sech}^2 x = \cfrac{1}{\cosh^2 x} = \cfrac{4}{(e^x + e^{-x})^2}
Es wird sein. In letzter Zeit wurde es teilweise für erwartete neue Sterne wie [Mischfunktion](# Mischfunktion) und [tanhExp-Funktion](# Tanhexp-Funktion) verwendet. Es scheint eine Funktion mit hoher Aufmerksamkeit zu sein.
Dies ist auch von Pytorch. Es ist nur eine Einführung. ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y = x - \tanh x
Und die Rückenausbreitung ist
\cfrac{\partial y}{\partial x} = \tanh^2 x
Es wird sein.
Dies ist auch Pytorch. Nur zur Einführung ... ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
1 & (x \gt 1) \\
-1 & (x \lt -1) \\
x & (\textrm{otherwise})
\end{array}
\right.
Und die Rückenausbreitung ist
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
0 & (x \lt -1 \quad \textrm{or} \quad 1 \le x) \\
1 & (\textrm{otherwise})
\end{array}
\right.
Es wird sein.
Die ReLU-Funktion (allgemein als Rampenfunktion bezeichnet) ist eine kürzlich vorgeschlagene Aktivierungsfunktion, die die Vorherrschaft innehat. Das Merkmal ist diese einfache und schnelle Berechnung. Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
x & (x \gt 0) \\
0 & (x \le 0)
\end{array}
\right.
Backpropagation
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
1 & (x \gt 0) \\
0 & (x \le 0)
\end{array}
\right.
Es wird sein. Wenn die Eingabe ein positiver Wert ist, beträgt der Gradient immer $ 1 $, sodass der Gradient weniger leicht verschwindet und es einfach ist, Ebenen zu stapeln. Es gibt jedoch auch den Nachteil, dass das Lernen für negative Eingaben überhaupt nicht fortgesetzt wird. Außerdem wird die Diskontinuität bei $ x = 0 $ grundsätzlich ignoriert. Bei der Fehler-Rück-Ausbreitungsmethode wird das Lernen basierend auf der Ausbreitung des Gradienten unter Verwendung des Kettengesetzes vorangetrieben, so dass die Aktivierungsfunktion mit allen reellen Zahlen differenzierbar sein sollte, aber in Wirklichkeit ist sie perfekt $ x = 0 $ Es gibt sowieso weniger Fälle, in denen es zu & $ 0 $ wird, also spielt es keine Rolle.
Nur eine Einführung von Pytorch. ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
0 & (x \le 0) \\
6 & (x \ge 6) \\
x & (\textrm{otherwise})
\end{array}
\right.
Und Backpropagation
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
0 & (x \le 0 \quad \textrm{or} \quad 6 \le x) \\
1 & (\textrm{otherwise})
\end{array}
\right.
Es wird sein.
Die Leaky-ReLU-Funktion gibt bei einem negativen Eingang eine lineare Funktion mit einem sehr kleinen Gradienten aus, um den Nachteil der [ReLU-Funktion](# Relu-Funktion) zu kompensieren, dass "das Lernen für negative Eingänge nicht fortgesetzt wird". Es ist so etwas. In der Grafik ist wenig zu sehen, aber in der Formel
y = \left\{
\begin{array}{cc}
x & (x \gt 0) \\
0.01x & (x \le 0)
\end{array}
\right.
Der Ausgang ist unterschiedlich, wenn der Eingang negativ ist. Daher Backpropagation
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
1 & (x \gt 0) \\
0.01 & (x \le 0)
\end{array}
\right.
Es wird sein. Dies ist auch bei $ x = 0 $ diskontinuierlich. Ich habe es auch an verschiedenen Stellen während meiner Recherche gesehen, aber es scheint, dass der Name dieser Funktion lautet: "Es hatte keinen besonderen Sinn, dies zu verwenden." Es ist ein wenig überraschend. Es sieht so aus, als würde es sich ein wenig verbessern ...
Ein Graph, dessen Form der [ReLU-Funktion](# Relu-Funktion) ähnelt, einer der glatteren Funktionen, wenn $ x = 0 $ ist, ist die ELU-Funktion. Wie Sie in der Grafik sehen können, führen negative Eingaben nicht zu einem Gradienten von $ 0 $ ($ 0 $ für $ x \ to- \ infty $). In der Formel
y = \left\{
\begin{array}{cc}
x & (x \ge 0) \\
\alpha (e^x - 1) & (x \lt 0)
\end{array}
\right.
Und Backpropagation
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
1 & (x \ge 0) \\
\alpha e^x & (x \lt 0)
\end{array}
\right.
Es wird sein. Es scheint, dass der Wert von ~~ $ \ alpha $ in der nächsten [SELU-Funktion](# selu-Funktion) (wahrscheinlich) häufig einen theoretisch angemessenen Wert annimmt. ~~ ** Überarbeitet am 02.06.2020 ** Der Standardwert für $ \ alpha $ scheint normalerweise $ 1 $ zu sein. Ich werde es durch ein Diagramm von $ \ alpha = 1 $ ersetzen. Es tut mir leid, dass ich die falschen Informationen gesendet habe ...
Die SELU-Funktion ist die Ausgabe der [ELU-Funktion](# elu-Funktion) multipliziert mit $ \ lambda $. In der Formel
y = \left\{
\begin{array}{cc}
\lambda x & (x \ge 0) \\
\lambda \alpha (e^x - 1) & (x \lt 0)
\end{array}
\right.
Und Backpropagation
\cfrac{\partial y}{\partial x} = \left\{
\begin{array}{cc}
\lambda & (x \ge 0) \\
\lambda \alpha e^x & (x \lt 0)
\end{array}
\right.
Es wird wie in mit $ \ lambda $ multipliziert. Es scheint, dass der theoretisch optimale Parameterwert erhalten werden kann, und dieser Wert ist
\alpha = 1.67326\ldots, \quad \lambda = 1.0507\ldots
Es scheint so als. Ich könnte die Zeitung bald lesen ... Ich werde sie ergänzen, wenn ich sie lese.
Dies ist auch eine Einführung nur von Pytorch. ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y = \left\{
\begin{array}{cc}
x & (x \ge 0) \\
\alpha \left( e^{\frac{x}{\alpha}} - 1 \right) & (\textrm{otherwise})
\end{array}
\right.
Und die Formel für die Rückausbreitung lautet
y = \left\{
\begin{array}{cc}
1 & (x \ge 0) \\
e^{\frac{x}{\alpha}} & (\textrm{otherwise})
\end{array}
\right.
Es wird sein.
Die Softmax-Funktion wird als Aktivierungsfunktion für die Ausgabeschicht von mehrwertigen Klassifizierungsproblemen verwendet. Aufgrund der Eigenschaften der Berechnung kann die Ausgabe als Wahrscheinlichkeit angesehen werden. Sorgen Sie sich nicht zu sehr um die vertikale Achse des Diagramms. Alles, was zählt, ist, dass Sie bei der Integration (der Computer ist diskret, also fassen Sie es zusammen) $ 1 $ erhalten. Mathematisch
y_i = \cfrac{e^{x_i}}{\displaystyle\sum_{k=1}^{n}{e^{x_k}}} \quad (i = 1, 2, \ldots, n)
Es ist wie es ist. Die Rückenausbreitung ist vorläufig
\left( \cfrac{\partial y}{\partial x} \right)_i = e^{x_i} \cfrac{\displaystyle\sum_{k=1}^{n}{e^{x_k}} - e^{x_i}}{\left( \displaystyle\sum_{k=1}^{n}{e^{x_k}} \right)^2}
** Kreuzentropiefehler **
Error = t \log y
Durch Aufnehmen der Rückausbreitung von der Ausgangsschicht zur Zwischenschicht
y - t
Es wird sehr einfach sein. Dies ist übrigens kein Zufall, der Kreuzentropiefehler ist eine Funktion, die so ausgelegt ist, dass sie zur Softmax-Funktion passt, sodass der Gradient $ y-t $ beträgt. Ich kann es eines Tages in ein Berechnungsdiagramm einführen.
Dies ist auch von Pytorch. Im Gegensatz zu [Softmax-Funktion](# Softmax-Funktion Softmax) steigt die Wahrscheinlichkeit kleiner Werte. ** Überprüfen Sie die TODO-Zusatzinformationen ** Die Formel für die Vorwärtsausbreitung lautet
y_i = \cfrac{e^{-x_i}}{\displaystyle\sum_{k=1}^{n}{e^{-x_k}}} \quad (i = 1, 2, \ldots, n)
Und die Formel für die Rückausbreitung lautet
\left( \cfrac{\partial y}{\partial x} \right)_i = e^{-x_i} \cfrac{\displaystyle\sum_{k=1}^{n}{e^{-x_k}} - e^{-x_i}}{\left( \displaystyle\sum_{k=1}^{n}{e^{-x_k}} \right)^2}
Es wird sein. Wenn der Kreuzentropiefehler auch hier verwendet wird, breitet sich der Fehler sauber zurück ... Ich werde ihn das nächste Mal untersuchen.
Von Pytorch ist dies der Logarithmus von [softmax function](#softmax function softmax). ** Überprüfen Sie die TODO-Zusatzinformationen ** Es sieht fast gerade aus. Ich frage mich, ob es passt ... Ich denke, der Code ist korrekt. Die Formel für die Vorwärtsausbreitung lautet
y_i = \log \left( \cfrac{e^{x_i}}{\displaystyle\sum_{k=1}^{n}{e^{x_k}}} \right)
Und die Rückenausbreitung ist
\left( \cfrac{\partial y}{\partial x} \right)_i = \cfrac{\displaystyle\sum_{k=1}^{n}{e^{x_k}} - e^{x_i}}{\displaystyle\sum_{k=1}^{n}{e^{x_k}}}
Es wird sein.
Die Softplus-Funktion hat einen ähnlichen Namen wie [Softmax-Funktion](# Softmax-Funktion Softmax), ähnelt jedoch im Wesentlichen der [ReLU-Funktion](# Relu-Funktion).
In der Formel
y = \log{(1 + e^x)} = \ln{(1 + e^x)}
Ausgedrückt als Backpropagation
\cfrac{\partial y}{\partial x} = \cfrac{e^x}{1 + e^x} = \cfrac{1}{1 + e^{-x}}
Es sieht aus wie. Es sieht genauso aus wie die [ReLU-Funktion](# relu-Funktion) und die Differenzierung.
Übrigens soll $ \ ln x $ klarstellen, dass die Basis eine logarithmische Funktion von Napier-Zahlen ist. Mit anderen Worten
\ln x = \log_ex
Es ist das.
Auch hier ähnelt der Name [softmax function](#softmax function softmax), in Wirklichkeit ähnelt er jedoch [tanh function](#tanh function) (Vorwärtsausbreitung).
Die Vorwärtsausbreitung sieht genauso aus wie die Tanh-Funktion, aber die Rückwärtsausbreitung ist völlig anders. Es ist sehr scharf. Blick auf die Vorwärtsausbreitung mit einer mathematischen Formel
y = \cfrac{x}{1 + |x|}
Und Backpropagation
\cfrac{\partial y}{\partial x} = \cfrac{1}{(1 + |x|)^2}
Es ist geworden. Bei ~~ $ x = 0 $ ist die Differenzierung zu einer diskontinuierlichen Funktion geworden. ~~ ** Überarbeitet am 02.06.2020 ** Ich habe die Kontinuität der Funktion falsch verstanden. Es ist nicht diskontinuierlich richtig. Es kann nicht unterschieden werden.
\lim_{x \to \pm 0}{\cfrac{1}{(1 + |x|)^2}} = 1
\Leftrightarrow
\lim_{x \to 0}{\cfrac{1}{(1 + |x|)^2}} = 1
Und
\cfrac{\partial y}{\partial x} = \cfrac{1}{(1 + |0|)^2} = 1 \quad (\because x = 0)
Damit
\lim_{x \to 0}{\cfrac{1}{(1 + |x|)^2}} = \cfrac{1}{(1 + |0|)^2}
Wird als kontinuierlich angezeigt.
Dies ist die Swish-Funktion, die voraussichtlich der Nachfolger der 2017 erschienenen [ReLU-Funktion](# relu-Funktion) sein wird. Es sieht genauso aus wie die [ReLU-Funktion](# Relu-Funktion), aber im Gegensatz zu [ELU-Funktion](# Elu-Funktion) und [SELU-Funktion](# Selu-Funktion) wird es auch mit $ x = 0 $ zu einer stetigen Funktion. Ich bin. Ein weiteres Merkmal ist, dass es sich um eine $ C ^ {\ infty} $ -Klassenfunktion handelt. Darüber hinaus können Sie auch sehen, dass für negative Eingaben nur wenige negative Werte erforderlich sind. Der schöne Punkt ist, dass es einen Minimalwert und keinen Maximalwert gibt. Wenn die Vorwärtsausbreitung durch eine mathematische Formel ausgedrückt wird
y = x \sigma_{sigmoid}(\beta x) = \cfrac{x}{1 + e^{-\beta x}}
Es ist wie es ist. In der obigen Grafik ist $ \ beta = 1 $ festgelegt. Übrigens scheint es, dass $ \ beta $ durch die Fehler-Back-Propagation-Methode (nicht implementiert) optimiert werden kann. Backpropagation
\cfrac{\partial y}{\partial x} = \beta y + \sigma_{sigmoid}(\beta x)(1 - \beta y) = \beta y + \cfrac{1 - \beta y}{1 + e^{-\beta x}}
Sie können so schreiben. Es fühlt sich an wie ein Blick auf die [Sigmoid-Funktion](# Sigmoid-Funktion Sigmoid).
Die Mish-Funktion ist der Nachfolger der 2019 vorgeschlagenen [ReLU-Funktion](# Relu-Funktion), die noch aktueller ist als die [Swish-Funktion](# Swish-Funktion). Papiere haben gezeigt, dass es oft die Swish-Funktion übertrifft. (Ich habe die Zeitung noch nicht richtig gelesen, aber er hat sie geschrieben) Es sieht fast genauso aus wie die Swish-Funktion, ist aber etwas anders. Die Grafik ganz rechts zeigt den größten Unterschied. Dieses Diagramm ist die Berechnung jeder doppelten Differenzierung. Mit anderen Worten, es repräsentiert den Grad der Änderung des Gradienten. Was Sie aus dem Diagramm ablesen können, ist, dass die Mish-Funktion deutlichere Fehler übermittelt, insbesondere bei der $ \ Rightarrow $ -Gradientenberechnung, die sich dynamisch um $ x = 0 $ ändert. Als Vorwärtsausbreitungsformel
y = x \tanh{(\varsigma(x))} = x \tanh{(\ln{(1 + e^x)})}
Die Rückausbreitung ist etwas kompliziert
\cfrac{\partial y}{\partial x} = \cfrac{e^x \omega}{\delta^2}\\
\omega = 4(x + 1) + 4e^{2x} + e^{3x} + (4x + 6)e^x \\
\delta = 2e^x + e^{2x} + 2
Es wird berechnet als. Daher dauert das Lernen länger als die ReLU-Funktion. In Bezug auf die Genauigkeit ist dies jedoch häufig besser als die Verwendung der ReLU-Funktion. Berücksichtigen Sie daher bei der Auswahl einer Aktivierungsfunktion den Kompromiss zwischen Lernzeit und Genauigkeit.
Dies ist die tanhExp-Funktion von @ reppy4620! Laut Paper ist es ab März 2020 ~ Es ist schrecklich neu. Wie Sie in diesem Artikel sehen können, ist es ein Mitglied der [ReLU-Funktion](# relu-Funktion) (heißt es die ReLU-Familie?). Anscheinend übertrifft es die [Mish-Funktion](# mish-Funktion) in berühmten Datensätzen wie MNIST, CIFER-10 und CIFER-100 (ich habe es noch nicht gelesen). Vergleiche mit [Swish-Funktion](# Swish-Funktion) Die Ausgabe der Vorwärtsausbreitung sieht fast gleich aus, aber die tanhExp-Funktion hat eine steilere Steigung und einen kleineren Bereich über dem Differenzwert von $ 1 $ bei der Rückwärtsausbreitung. Der Gradient ist sehr empfindlich, und wenn der absolute Wert des Differentials weniger als $ 1 $ beträgt, verschwindet der Gradient sofort, und umgekehrt, wenn er mehr als $ 1 $ beträgt, tritt eine Gradientenexplosion auf. Die tanhExp-Funktion sieht auch in dieser Hinsicht hervorragend aus. Dann vergleiche mit [Mischfunktion](# Mischfunktion). Die Mish-Funktion folgt eher der tanhExp-Funktion als der Swish-Funktion. Bei steilen Hängen um $ 0 $ ist die tanhExp-Funktion jedoch immer noch besser. Betrachten wir die Vorwärtsausbreitung mit einer mathematischen Formel.
y = x \tanh(e^x)
Sie verwenden sowohl die Tanh-Funktion als auch die Mish-Funktion. Bekommt die Tanh-Funktion jetzt nicht mehr Aufmerksamkeit? Backpropagation
\begin{align}
\cfrac{\partial y}{\partial x} &= \tanh(e^x) + xe^x\textrm{sech}^2(e^x) \\
&= \tanh(e^x) - xe^x(\tanh^2(e^x) - 1)
\end{align}
Es wird sein. Es ist schön, viel einfacher berechnen zu können als die Mish-Funktion ~
Hier ist ein Beispiel für den Code, der beim Zeichnen des Diagramms verwendet wird. Bitte verwenden Sie es als Referenz bei der Implementierung. Ich benutze ein Jupyter-Notebook.
activators.py
import numpy as np
class Activator():
def __init__(self, *args,**kwds):
pass
def forward(self, *args,**kwds):
raise Exception("Not Implemented")
def backward(self, *args,**kwds):
raise Exception("Not Implemented")
def update(self, *args,**kwds):
pass
class step(Activator):
def forward(self, x, *args,**kwds):
return np.where(x > 0, 1, 0)
def backward(self, x, *args,**kwds):
return np.zeros_like(x)
class identity(Activator):
def forward(self, x, *args,**kwds):
return x
def backward(self, x, *args,**kwds):
return np.ones_like(x)
class bentIdentity(Activator):
def forward(self, x, *args,**kwds):
return 0.5*(np.sqrt(x**2 + 1) - 1) + x
def backward(self, x, *args,**kwds):
return 0.5*x/np.sqrt(x**2 + 1) + 1
class hardShrink(Activator):
def __init__(self, lambda_=0.5, *args,**kwds):
self.lambda_ = lambda_
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return np.where((-self.lambda_ <= x) & (x <= self.lambda_),
0, x)
def backward(self, x, *args,**kwds):
return np.where((-self.lambda_ <= x) & (x <= self.lambda_),
0, 1)
class softShrink(Activator):
def __init__(self, lambda_=0.5, *args,**kwds):
self.lambda_ = lambda_
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return np.where(x < -self.lambda_, x + self.lambda_,
np.where(x > self.lambda_, x - self.lambda_, 0))
def backward(self, x, *args,**kwds):
return np.where((-self.lambda_ <= x) & (x <= self.lambda_),
0, 1)
class threshold(Activator):
def __init__(self, threshold, value, *args,**kwds):
self.threshold = threshold
self.value = value
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return np.where(x > self.threshold, x, self.value)
def backward(self, x, *args,**kwds):
return np.where(x > self.threshold, 1, 0)
class sigmoid(Activator):
def forward(self, x, *args,**kwds):
return 1/(1 + np.exp(-x))
def backward(self, x, y, *args,**kwds):
return y*(1 - y)
class hardSigmoid(Activator):
def forward(self, x, *args,**kwds):
return np.clip(0.2*x + 0.5, 0, 1)
def backward(self, x, *args,**kwds):
return np.where((x > 2.5) | (x < -2.5), 0, 0.2)
class logSigmoid(Activator):
def forward(self, x, *args,**kwds):
return -np.log(1 + np.exp(-x))
def backward(self, x, *args,**kwds):
return 1/(1 + np.exp(x))
class act_tanh(Activator):
def forward(self, x, *args,**kwds):
return np.tanh(x)
def backward(self, x, *args,**kwds):
return 1 - np.tanh(x)**2
class hardtanh(Activator):
def forward(self, x, *args,**kwds):
return np.clip(x, -1, 1)
def backward(self, x, *args,**kwds):
return np.where((-1 <= x) & (x <= 1), 1, 0)
class tanhShrink(Activator):
def forward(self, x, *args,**kwds):
return x - np.tanh(x)
def backward(self, x, *args,**kwds):
return np.tanh(x)**2
class ReLU(Activator):
def forward(self, x, *args,**kwds):
return np.maximum(0, x)
def backward(self, x, *args,**kwds):
return np.where(x > 0, 1, 0)
class ReLU6(Activator):
def forward(self, x, *args,**kwds):
return np.clip(x, 0, 6)
def backward(self, x, *args,**kwds):
return np.where((0 < x) & (x < 6), 1, 0)
class leakyReLU(Activator):
def __init__(self, alpha=1e-2, *args,**kwds):
self.alpha = alpha
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return np.maximum(self.alpha * x, x)
def backward(self, x, *args,**kwds):
return np.where(x < 0, self.alpha, 1)
class ELU(Activator):
def __init__(self, alpha=1., *args,**kwds):
self.alpha = alpha
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return np.where(x >= 0, x, self.alpha*(np.exp(x) - 1))
def backward(self, x, *args,**kwds):
return np.where(x >= 0, 1, self.alpha*np.exp(x))
class SELU(Activator):
def __init__(self, lambda_=1.0507, alpha=1.67326, *args,**kwds):
self.lambda_ = lambda_
self.alpha = alpha
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return np.where(x >= 0,
self.lambda_*x,
self.lambda_*self.alpha*(np.exp(x) - 1))
def backward(self, x, *args,**kwds):
return np.where(x >= 0,
self.lambda_,
self.lambda_*self.alpha*np.exp(x))
class CELU(Activator):
def __init__(self, alpha=1., *args,**kwds):
self.alpha = alpha
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return np.where(x >= 0,
x,
self.alpha*(np.exp(x/self.alpha) - 1))
def backward(self, x, *args,**kwds):
return np.where(x >= 0, 1, np.exp(x/self.alpha))
class softmax(Activator):
def forward(self, x, *args,**kwds):
return np.exp(x)/np.sum(np.exp(x))
def backward(self, x, *args,**kwds):
return np.exp(x)*(np.sum(np.exp(x))
- np.exp(x))/np.sum(np.exp(x))**2
class softmin(Activator):
def forward(self, x, *args,**kwds):
return np.exp(-x)/np.sum(np.exp(-x))
def backward(self, x, *args,**kwds):
return -(np.exp(x)*(np.sum(np.exp(-x)) - np.exp(x))
/np.sum(np.exp(-x))**2)
class logSoftmax(Activator):
def forward(self, x, *args,**kwds):
return np.log(np.exp(x)/np.sum(np.exp(x)))
def backward(self, x, *args,**kwds):
y = np.sum(np.exp(x))
return (y - np.exp(x))/y
class softplus(Activator):
def forward(self, x, *args,**kwds):
return np.logaddexp(x, 0)
def backward(self, x, *args,**kwds):
return 1/(1 + np.exp(-x))
class softsign(Activator):
def forward(self, x, *args,**kwds):
return x/(1 + np.abs(x))
def backward(self, x, *args,**kwds):
return 1/(1 + np.abs(x)) ** 2
class Swish(Activator):
def __init__(self, beta=1, *args,**kwds):
self.beta = beta
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
return x/(1 + np.exp(-self.beta*x))
def backward(self, x, y, *args,**kwds):
return self.beta*y + (1 - self.beta*y)/(1 + np.exp(-self.beta*x))
def d2y(self, x, *args,**kwds):
return (-0.25*self.beta*(self.beta*x*np.tanh(0.5*self.beta*x) - 2)
*(1 - np.tanh(0.5*self.beta*x)**2))
class Mish(Activator):
def forward(self, x, *args,**kwds):
return x*np.tanh(np.logaddexp(x, 0))
def backward(self, x, *args,**kwds):
omega = (4*(x + 1) + 4*np.exp(2*x)
+ np.exp(3*x) + (4*x + 6)*np.exp(x))
delta = 2*np.exp(x) + np.exp(2*x) + 2
return np.exp(x)*omega/delta**2
def d2y(self, x, *args,**kwds):
omega = (2*(x + 2)
+ np.exp(x)*(np.exp(x)*(-2*np.exp(x)*(x - 1) - 3*x + 6)
+ 2*(x + 4)))
delta = np.exp(x)*(np.exp(x) + 2) + 2
return 4*np.exp(x)*omega/delta**3
class tanhExp(Activator):
def forward(self, x, *args,**kwds):
return x*np.tanh(np.exp(x))
def backward(self, x, *args,**kwds):
tanh_exp = np.tanh(np.exp(x))
return tanh_exp - x*np.exp(x)*(tanh_exp**2 - 1)
def d2y(self, x, *args,**kwds):
tanh_exp = np.tanh(np.exp(x))
return (np.exp(x)*(-x + 2*np.exp(x)*x*tanh_exp - 2)
*(tanh_exp**2 - 1))
class maxout(Activator):
def __init__(self, n_prev, n, k, wb_width=5e-2, *args,**kwds):
self.n_prev = n_prev
self.n = n
self.k = k
self.w = wb_width*np.random.rand((n_prev, n*k))
self.b = wb_width*np.random.rand(n*k)
super().__init__(*args,**kwds)
def forward(self, x, *args,**kwds):
self.x = x.copy()
self.z = np.dot(self.w.T, x) + self.b
self.z = self.z.reshape(self.n, self.k)
self.y = np.max(self.z, axis=1)
return self.y
def backward(self, g, *args,**kwds):
self.dw = np.sum(np.dot(self.w, self.x))
test_activators.py
import numpy as np
import matplotlib.pyplot as plt
_act_dic = {"step": step,
"identity": identity,
"bent-identity": bentIdentity,
"hard-shrink": hardShrink,
"soft-shrink": softShrink,
"threshold": threshold,
"sigmoid": sigmoid,
"hard-sigmoid": hardSigmoid,
"log-sigmoid": logSigmoid,
"tanh": act_tanh,
"tanh-shrink": tanhShrink,
"hard-tanh":hardtanh,
"ReLU": ReLU,
"ReLU6": ReLU6,
"leaky-ReLU": leakyReLU,
"ELU": ELU,
"SELU": SELU,
"CELU": CELU,
"softmax": softmax,
"softmin": softmin,
"log-softmax": logSoftmax,
"softplus": softplus,
"softsign": softsign,
"Swish": Swish,
"Mish": Mish,
"tanhExp": tanhExp,
}
def get_act(name, *args,**kwds):
for act in _act_dic:
if name == act:
activator = _act_dic[name](*args,**kwds)
break
else:
raise ValueError(name, ": Unknown activator")
return activator
def plot_graph(x, name, *args,**kwds):
activator = get_act(name, *args,**kwds)
y = activator.forward(x, *args,**kwds)
dx = activator.backward(x, y, *args,**kwds)
plt.plot(x, y, label="forward")
plt.plot(x, dx, label="backward")
plt.title(name)
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
plt.legend(loc="best")
plt.savefig("{}.png ".format(name))
plt.show()
def vs_plot(x, A, B):
A_activator = get_act(A)
B_activator = get_act(B)
y_A = {}
y_B = {}
y_A["{} y".format(A)] = A_activator.forward(x)
y_B["{} y".format(B)] = B_activator.forward(x)
y_A["{} dy".format(A)] = A_activator.backward(x,
y_A["{} y".format(A)])
y_B["{} dy".format(B)] = B_activator.backward(x,
y_B["{} y".format(B)])
y_A["{} d2y".format(A)] = A_activator.d2y(x, y_A["{} y".format(A)])
y_B["{} d2y".format(B)] = B_activator.d2y(x, y_B["{} y".format(B)])
fig, ax = plt.subplots(1, 3, figsize=(18, 6))
for i, key in enumerate(y_A):
ax[i].plot(x, y_A[key], label=key)
ax[i].set_xlabel("x")
ax[i].set_ylabel("y")
ax[i].grid()
for i, key in enumerate(y_B):
ax[i].plot(x, y_B[key], label=key)
ax[i].legend(loc="best")
ax[0].set_title("forward")
ax[1].set_title("backward")
ax[2].set_title("second-order derivative")
fig.tight_layout()
fig.savefig("{}_vs_{}.png ".format(A, B))
plt.show()
x = np.arange(-5, 5, 5e-2)
plot_graph(x, "step")
plot_graph(x, "identity")
plot_graph(x, "bent-identity")
plot_graph(x, "hard-shrink")
plot_graph(x, "soft-shrink")
plot_graph(x, "threshold", -1, -2)
plot_graph(x, "sigmoid")
plot_graph(x, "hard-sigmoid")
plot_graph(x, "log-sigmoid")
plot_graph(x, "tanh")
plot_graph(x, "tanh-shrink")
plot_graph(x, "hard-tanh")
plot_graph(x, "ReLU")
plot_graph(x + 2, "ReLU6")
plot_graph(x, "leaky-ReLU")
plot_graph(x, "ELU")
plot_graph(x, "SELU")
plot_graph(x, "CELU")
plot_graph(x, "softmax")
plot_graph(x, "softmin")
plot_graph(x, "log-softmax")
plot_graph(x, "softplus")
plot_graph(x, "softsign")
plot_graph(x, "Swish")
plot_graph(x, "Mish")
plot_graph(x, "tanhExp")
vs_plot(x, "Swish", "Mish")
vs_plot(x, "Swish", "tanhExp")
vs_plot(x, "Mish", "tanhExp")
Es gibt einige andere, die implementiert werden. Ich denke, ich werde es bald hinzufügen ...
Künstliche Intelligenz Unterscheidet sich von der Art der Aktivierungsfunktion. Verdienst und Fehler. ](Https://fresopiya.com/2019/05/14/activefunc/)
--- @ reppy4620 gab uns Informationen über die tanhExp-Funktion! Vielen Dank, dass Sie den Link des Papiers höflich gepostet haben!
Recommended Posts