高速神经网络与普通神经网络相比,引入了门机制,对于训练深层网络有显著的性能提升
传统的前馈神经网络只有一个非线性激活函数我们把它记做y = H(x,W_H)
其中H表示非线性激活函数,x表示输入,W_H表示权重,y表示输出。而高速神经网络中引入的门机制,其实就是增加了两个非线性函数,论文中把他们分别叫做T(Transform Gate)
,C(Carry Gate)
,从而把输出变为y = H(x,W_H)*T(x, W_T) + x*C(x,W_C)
,为了方便论文中设置C = 1 - T
,因此最后的输出就变为y = H(x,W_H) * T(x, W_T) + x * (1 - T(x, W_T))
,这里W_H表示非线性函数H的权重。
除此之外,我们还可以得到如下等式:
y
=
{
x
,
i
f
T
(
x
,
W
T
)
=
0
H
(
x
,
W
H
)
,
i
f
T
(
x
,
W
T
)
=
1
y=\left\{
所以不难发现,实际上高速神经网络就是对一部分的输入保留不变,一部分的输入正常按照一般的前馈神经网络一样处理
对于transform gate,论文中将其定义为 T ( x ) = σ ( W T T x + b T ) T(x)=\sigma(W_T^Tx + b_T) T(x)=σ(WTTx+bT),其中 b T b_T bT一般初始化为-1或-3。
对于carry gate,与一般的非线性函数一致,并没有什么特殊之处
import tensorflow as tf
class HighwayLayer(tf.keras.layers.Layer):
def __init__(self, units, t_bias):
super(HighwayLayer, self).__init__()
self.units = units # 定义输出单元个数
self.t_bias = t_bias
self.activationT = tf.nn.relu
self.activationH = tf.nn.sigmoid
def build(self, input_shape):
print(input_shape[-1])
self.W_H = self.add_weight(name="w_H",
shape=(input_shape[-1], self.units), initializer="random_normal", trainable = True
) # 添加激活函数H的权重
self.W_T = self.add_weight(name="w_T",
shape=(input_shape[-1], self.units), initializer="random_normal", trainable = True
) # 添加激活函数T的权重
self.b_H = self.add_weight(name="b", shape=(self.units,), initializer="random_normal", trainable=True)
self.b_T = tf.Variable(tf.constant(self.t_bias, shape=self.units), name='bias', trainable=True, dtype=tf.float32)
def call(self, inputs):
h = self.activationH(tf.matmul(inputs, self.W_H) + self.b_H)
t = self.activationT(tf.matmul(inputs, self.W_T) + self.b_T)
y = tf.add(tf.multiply(h, t) , tf.multiply(inputs, (1 - t)))
return y
class HighwayNetwork(tf.keras.Model):
def __init__(self, t_bias = -3.0, num_classes=10, num_of_layers=3): #这里对于激活函数t来说,论文给出的误差值为-1或-3
super(HighwayNetwork, self).__init__()
self.projection = tf.keras.layers.Dense(128)
self.mlplayers = [HighwayLayer(128, t_bias=t_bias) for _ in range(num_of_layers)]
self.classifier = tf.keras.layers.Dense(num_classes, activation='softmax')
def call(self, x):
X = self.projection(x)
for layer in self.mlplayers:
X = layer(X)
y = self.classifier(X)
return y