激活函数
一、 Sigmoid 函数
sigmoid基本性质
Sigmoid函数是一个在生物学中常见的S型函数,也称为S型生长曲线。在信息科学中,由于其单增以及反函数单增等性质,Sigmoid函数常被用作神经网络的阈值函数,将变量映射到0,1之间 。公式如下:
σ
(
x
)
=
1
1
+
e
−
x
\sigma(x) = \frac{1}{1+e^{-x}}
σ(x)=1+e−x1
σ
(
x
)
\sigma(x)
σ(x)导函数为:
σ
′
(
x
)
=
σ
∗
(
1
−
σ
)
\sigma'(x) = \sigma*(1-\sigma)
σ′(x)=σ∗(1−σ)
σ
(
x
)
\sigma(x)
σ(x)和
σ
′
(
x
)
\sigma'(x)
σ′(x)的曲线图为:
σ
(
x
)
\sigma(x)
σ(x)函数的基本性质:
- 定义域: ( − ∞ , + ∞ ) (-\infty, +\infty) (−∞,+∞).
- 值域: ( 0 , 1 ) (0, 1) (0,1).
- 函数在定义域内为连续和光滑函数.
- 函数值在很大区间内达到饱和0或1.
- 导函数 σ ′ ( x ) ≤ 0.25 \sigma'(x) \leq 0.25 σ′(x)≤0.25.
逻辑回归
机器学习中一个重要的预测模型逻辑回归(LR)就是基于Sigmoid函数实现的。LR模型的主要任务是给定一些历史的{X,Y},其中X是样本n个特征值,Y的取值是{0,1}代表正例与负例,通过对这些历史样本的学习,从而得到一个数学模型,给定一个新的X,能够预测出Y。LR模型是一个二分类模型,即对于一个X,预测其发生或不发生。但事实上,对于一个事件发生的情况,往往不能得到100%的预测,因此LR可以得到一个事件发生的可能性,超过50%则认为事件发生,低于50%则认为事件不发生。
逻辑回归公式如下:
f
(
x
)
=
W
X
+
b
=
∑
i
n
w
i
x
i
+
b
f(x) = WX+b = \sum_i^nw_ix_i+b
f(x)=WX+b=i∑nwixi+b
X
=
(
x
1
,
x
2
,
.
.
.
,
x
n
)
X=(x_1,x_2,...,x_n)
X=(x1,x2,...,xn)是输入,
W
=
(
w
1
,
w
2
,
.
.
.
,
w
n
)
W=(w_1,w_2,...,w_n)
W=(w1,w2,...,wn)是参数,
b
b
b是偏置。构造预测函数:
σ
=
1
1
+
e
−
(
w
x
+
b
)
\sigma = \frac{1}{1+e^{-(wx+b)}}
σ=1+e−(wx+b)1
结果大于
0.5
0.5
0.5预测结果为正,小于
0.5
0.5
0.5预测结果为负。
从LR的目的上来看,在选择函数时,有两个条件是必须要满足的:
- 取值范围在0~1之间。
- 对于一个事件发生情况,50%是其结果的分水岭,选择函数应该在0.5中心对称。
keras实现逻辑回归
def logistic_regression(self, x_data,y_data, name='lr'):
m, n = x_data.shape
# 输入数据 维度 n X = (x1,x2,...,xn)
inputs = Input(shape=(n,), dtype='float32')
# 全连接层 参数 (n+1)*1 WX+b W = (w1,w2,...,wn), 激活函数sigmoid
layer_1 = Dense(1, activation='sigmoid')(inputs)
model = Model(inputs, layer_1)
model.summary()
model.compile(loss='mse', optimizer=Adam(), metrics=["acc"])
# 模型结构
tensor_board = TensorBoard(log_dir='log')
checkpoint = ModelCheckpoint(MODEL_NAME.format(name), verbose=1, save_best_only=True, mode='auto')
callbacks = [checkpoint, tensor_board]
model.fit(x_data, y_data, validation_split=0.1, epochs=20, batch_size=50, callbacks=callbacks, verbose=1)
Model Graph
LSTM
在深度学习早期,RNN结构在很多应用中取得了成功,但同时,这个简单模型的瓶颈也不断显现,这不仅涉及到优化本身(如梯度爆炸、梯度消失)的问题,还有模型的复杂度的问题。例如一句话“小张已经吃过饭了,小李呢?”,这句话是在询问“小李是否吃过饭”,但在RNN看来,信息是从左到右不断流入的,所以最后很难分清到底是在问小张是否过饭,还是在问小李是否吃过饭。于是带有遗忘机制的新结构就诞生了——长短时记忆网络(Long Short Term Memory Network,LSTM)。
Sigmoid主要用于遗忘门,输入门,输出门的激活函数:
f
t
=
σ
(
w
f
∗
[
x
t
+
h
t
]
+
b
f
)
f_t = \sigma(w_f*[x_t+h_t]+b_f)
ft=σ(wf∗[xt+ht]+bf)
i
t
=
σ
(
w
i
∗
[
x
t
+
h
t
]
+
b
i
)
i_t = \sigma(w_i*[x_t+h_t]+b_i)
it=σ(wi∗[xt+ht]+bi)
o
t
=
σ
(
w
o
∗
[
x
t
+
h
t
]
+
b
o
)
o_t = \sigma(w_o*[x_t+h_t]+b_o)
ot=σ(wo∗[xt+ht]+bo)
C
~
=
t
a
n
h
(
w
C
∗
[
x
t
+
h
t
]
+
b
C
)
\tilde{C} = tanh(w_C*[x_t+h_t]+b_C)
C~=tanh(wC∗[xt+ht]+bC)
c
t
=
f
t
∗
c
t
−
1
+
i
t
∗
C
~
c_t = f_t*c_{t-1}+i_t*\tilde{C}
ct=ft∗ct−1+it∗C~
h
t
=
o
t
∗
t
a
n
h
(
c
t
)
h_t = o_t*tanh(c_t)
ht=ot∗tanh(ct)
Keras实现两层LSTM
def keras_lstm():
inputs = Input(shape=(28, 28,), dtype='float32')
# 参数:(100*(28+100) + 100)*4=51600
lstm_1 = LSTM(units=100, return_sequences=True)(inputs)
# 参数:(100*(100+100) +100)*4=80400
lstm_2 = LSTM(units=100)(lstm_1) # (100*(100+100) +100)*4=80400
preds = Dense(10, activation='softmax')(lstm_2) # 100*10 +100
model = Model(inputs, preds)
model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['acc'])
model.summary()
tensorboard = TensorBoard(log_dir='log', histogram_freq=1)
callbacks = [tensorboard]
model.fit(x_train, y_train, epochs=10, batch_size=100, callbacks=callbacks, verbose=1)
Model Graph
二、双曲正切函数
tanh基本性质
t
a
n
h
tanh
tanh是双曲函数中的一个,
t
a
n
h
(
)
tanh()
tanh()为双曲正切。在数学中,双曲正切 “
t
a
n
h
tanh
tanh” 是由基本双曲函数双曲正弦和双曲余弦推导而来。
t
a
n
h
tanh
tanh定义如下:
t
a
n
h
(
x
)
=
s
i
n
h
(
x
)
c
o
s
h
(
x
)
=
e
x
−
x
−
x
e
x
+
x
−
x
tanh(x) = \frac{sinh(x)}{cosh(x)} = \frac{e^{x}-x^{-x}}{e^{x}+x^{-x}}
tanh(x)=cosh(x)sinh(x)=ex+x−xex−x−x
双曲正切函数的导函数为:
t
a
n
h
′
(
x
)
=
1
−
t
a
n
h
2
(
x
)
tanh'(x) = 1-tanh^2(x)
tanh′(x)=1−tanh2(x)
t
a
n
h
tanh
tanh及其导数的曲线图为:
t
a
n
h
(
x
)
tanh(x)
tanh(x)函数的基本性质:
- 定义域: ( − ∞ , + ∞ ) (-\infty, +\infty) (−∞,+∞).
- 值域: ( − 1 , 1 ) (-1, 1) (−1,1).
- t a n h ( x ) tanh(x) tanh(x)是奇函数.
- 函数在定义域内为连续和光滑函数.
- 导函数 t a n h ′ ( x ) ≤ 1 tanh'(x) \leq 1 tanh′(x)≤1.
RNN
RNN的激活函数通常使用双曲正切函数
t
a
n
h
(
x
)
tanh(x)
tanh(x), rnn定义如下:
s
t
=
t
a
n
h
(
W
∗
[
x
t
,
s
t
−
1
]
+
b
)
s_t = tanh(W*[x_t,s_t-1]+b)
st=tanh(W∗[xt,st−1]+b)
o
t
=
s
o
f
t
m
a
x
(
U
∗
s
t
+
b
)
o_t = softmax(U*s_t+b)
ot=softmax(U∗st+b)
Keras实现RNN
def k_rnn():
inputs = Input(shape=(28, 28,), dtype='float32')
# 参数: (100*(28+100) + 100)*4=51600
lstm_1 = SimpleRNN(units=100, activation='tanh')(inputs)
# 参数: 100*10 +100
preds = Dense(10, activation='softmax')(lstm_1)
model = Model(inputs, preds)
model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['acc'])
model.summary()
tensorboard = TensorBoard(log_dir='log', histogram_freq=1)
callbacks = [tensorboard]
model.fit(x_train, y_train, epochs=10, batch_size=100, callbacks=callbacks, verbose=1)
Model Graph
三、 ReLU
ReLU基本性质
Sigmoid 函数曾经被使用的很多,不过近年来,用它的人越来越少了。主要是因为它的缺点(输入较大或较小的时候,最后梯度会接近于0),最终导致网络学习困难。所以,出现了另一种激活函数:ReLU
f
(
x
)
=
m
a
x
(
0
,
x
)
=
{
x
,
if
x
>
0
0
,
if
x
≤
0
f(x) = max(0, x) = \begin{cases} x, & \text{if $x>0$ } \\ 0, & \text{if $x \leq 0$} \end{cases}
f(x)=max(0,x)={x,0,if x>0 if x≤0
优点:
使用 ReLU得到的SGD的收敛速度会比 sigmoid / tanh 快。这是因为它是linear,而且ReLU只需要一个阈值就可以得到激活值,不用去计算复杂的运算。
缺点:
训练过程该函数不适应较大梯度输入,因为在参数更新以后,ReLU的神经元不会再有激活的功能,导致梯度永远都是零。为了针对以上的缺点,又出现Leaky-ReLU、P-ReLU、R-ReLU、E-ReLU四种拓展激活函数。
Leaky ReLUs 该函数用来解决ReLU的缺点,不同的是:
f
(
x
)
=
m
a
x
(
0
,
x
)
=
{
x
,
if
x
>
0
α
x
,
if
x
≤
0
f(x) = max(0, x) = \begin{cases} x, & \text{if $x>0$ } \\ \alpha x, & \text{if $x \leq 0$} \end{cases}
f(x)=max(0,x)={x,αx,if x>0 if x≤0
这里的
α
\alpha
α 是一个很小的常数。这样,即修正了数据分布,又保留了一些负轴的值,使得负轴信息不会全部丢失。
P-ReLU
Parametric ReLU 对于 Leaky ReLU 中的 α \alpha α,通常都是通过先验知识人工赋值,可以观察到损失函数对α的导数是可以求得的,可以将它作为一个参数进行训练。
R-ReLU
Randomized Leaky ReLU 是 Leaky ReLU 的随机版本( α \alpha α 是随机选取)。 它首次是在NDSB 比赛中被提出。核心思想就是,在训练过程中, α \alpha α是从一个高斯分布 U ( l , u ) U(l,u) U(l,u)中随机出来的,然后再测试过程中进行修正(与Dropout的用法相似)。
E-ReLU
Exponential ReLU 是指数线性单元,表达式为:
f
(
x
)
=
m
a
x
(
0
,
x
)
=
{
x
,
if
x
>
0
α
(
x
x
−
1
)
,
if
x
≤
0
f(x) = max(0, x) = \begin{cases} x, & \text{if $x>0$ } \\ \alpha (x^x-1), & \text{if $x \leq 0$} \end{cases}
f(x)=max(0,x)={x,α(xx−1),if x>0 if x≤0
Keras实现CNN:
def k_cnn():
inputs = Input(shape=(28, 28,), dtype='float32')
inputs_1 = Reshape((28, 28, 1))(inputs)
# 卷积层+激活relu 28*28*10
conv_1 = Conv2D(filters=10, kernel_size=(5, 5), strides=(1, 1), padding='same', activation='relu')(inputs_1)
# 池化层 14*14*10
pool_1 = MaxPool2D(pool_size=(2, 2))(conv_1) # 14*14*10
pool_1 = Flatten()(pool_1)
dense_1 = Dense(10, activation='softmax')(pool_1)
model = Model(inputs, dense_1)
model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['acc'])
model.summary()
tensorboard = TensorBoard(log_dir='log', histogram_freq=1)
callbacks = [tensorboard]
model.fit(x_train, y_train, epochs=100, batch_size=100, validation_data=[x_test, y_test], callbacks=callbacks, verbose=1)
Model Graph
四、Softmax
softmax用于多分类过程中,它将多个神经元的输出,映射到(0,1)区间内,可以看成概率来理解,从而来进行多分类!
假设我们有一个数组,V,Vi表示V中的第i个元素,那么这个元素的softmax值就是:
S
i
=
e
v
i
∑
i
=
1
n
v
i
S_i = \frac{e^{v_i}}{\sum_{i=1}^nv_i}
Si=∑i=1nvievi
softmax直白来说就是将原来输出是数组如3,1,-3通过softmax函数一作用,就映射成为(0,1)的值,softmax([3, 1, -3]) = [0.87887824, 0.11894324, 0.00217852], 而这些值的累和为1(满足概率的性质),那么我们就可以将它理解成概率,在最后选取输出结点的时候,我们就可以选取概率最大(也就是值对应最大的)结点,作为我们的预测目标!