赞
踩
在之前的教程中,我们介绍了 Keras 网络的模型与网络层,并且通过许多示例展示了网络的搭建方式。大家都注意到了,在构建网络的过程中,损失函数、优化器、激活函数等都是需要自定义的网络配置项,下面我们对这些网络配置进行详细的介绍。
目标函数,或称损失函数,是编译一个模型必须的两个参数之一:
model.compile(loss='mean_squared_error', optimizer='sgd')
可以通过传递预定义目标函数名字指定目标函数,也可以传递一个 Theano/TensroFlow 的符号函数作为目标函数,该函数对每个数据点应该只返回一个标量值,并以下列两个参数为参数:
- from keras import losses
-
- model.compile(loss=losses.mean_squared_error, optimizer='sgd')
真实的优化目标函数是在各个数据点得到的损失函数值之和的均值。
(nb_samples, nb_classes)
的二值序列np.expand_dims(y,-1)
(predictions - targets * log(predictions))
的均值注意: 当使用”categorical_crossentropy”作为目标函数时,标签应该为多类模式,即 one-hot 编码的向量,而不是单个数值.。可以使用工具中的 to_categorical
函数完成该转换,示例如下:
- from keras.utils.np_utils import to_categorical
-
- categorical_labels = to_categorical(int_labels, num_classes=None)
优化器是编译 Keras 模型必要的两个参数之一。
- from keras import optimizers
-
- model = Sequential()
- model.add(Dense(64, init='uniform', input_shape=(10,)))
- model.add(Activation('tanh'))
- model.add(Activation('softmax'))
-
- sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
- model.compile(loss='mean_squared_error', optimizer=sgd)
可以在调用 model.compile()
之前初始化一个优化器对象,然后传入该函数(如上所示),也可以在调用 model.compile()
时传递一个预定义优化器名。在后者情形下,优化器的参数将使用默认值。
- # 传递一个预定义优化器名
- model.compile(loss='mean_squared_error', optimizer='sgd')
参数 clipnorm
和 clipvalue
是所有优化器都可以使用的参数,用于对梯度进行裁剪。示例如下:
- from keras import optimizers
-
- # 所有参数的梯度会被剪裁到最大范数为1.
- sgd = optimizers.SGD(lr=0.01, clipnorm=1.)
- from keras import optimizers
-
- # 所有参数梯度会被剪裁到最大值为0.5,最小值为-0.5
- sgd = optimizers.SGD(lr=0.01, clipvalue=0.5)
随机梯度下降法,支持动量参数,支持学习衰减率,支持 Nesterov 动量。
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
除学习率可调整外,建议保持优化器的其他默认参数不变。该优化器通常是面对递归神经网络时的一个良好选择。
keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=1e-06)
该优化器的默认值来源于参考文献。
keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
激活函数用于在模型中引入非线性。激活函数 sigmoidsigmoid 与 tanhtanh 曾经很流行,但现在很少用于视觉模型了,主要原因在于当输入的绝对值较大时,其导数接近于零,梯度的反向传播过程将被中断,出现梯度消散的现象。
ReLUReLU 是一个很好的替代:
相比于 sigmoidsigmoid 与 tanhtanh,它有两个优势:
ReLUReLU 有一个缺陷,就是它可能会永远“死”掉:
假如有一组二维数据 XX (x1,x2)(x1,x2) 分布在 x1:[0,1],x2:[0,1]x1:[0,1],x2:[0,1] 的区域内,有一组参数 WW (w1,w2)(w1,w2)对 XX 做线性变换,并将结果输入到 ReLUReLU。 F=w1∗x1+w2∗x2F=w1∗x1+w2∗x2 如果 w1=w2=−1w1=w2=−1,那么无论 XX 如何取值,FF 必然小于等于零。那么 ReLUReLU 函数对 FF 的导数将永远为零。这个 ReLUReLU 节点将永远不参与整个模型的学习过程。
造成上述现象的原因是 ReLUReLU 在负区间的导数为零,为了解决这一问题,人们发明了 Leaky ReLULeaky ReLU、 Parametric ReLUParametric ReLU、 Randomized ReLURandomized ReLU 等变体。他们的中心思想都是为 ReLUReLU 函数在负区间赋予一定的斜率,从而让其导数不为零(这里设斜率为 αα)。
Leaky ReLULeaky ReLU 就是直接给 αα 指定一个值,整个模型都用这个斜率:
Parametric ReLUParametric ReLU 将 αα 作为一个参数,通过学习获取它的最优值。Randomized ReLURandomized ReLU 为 αα 规定一个区间,然后在区间内随机选取 αα 的值。
在实践中,Parametric ReLUParametric ReLU 和 Randomized ReLURandomized ReLU 都是可取的。
激活函数可以通过设置单独的激活层实现,也可以在构造层对象时通过传递 activation
参数实现。
- from keras.layers import Activation, Dense
-
- model.add(Dense(64))
- model.add(Activation('tanh'))
等价于:
model.add(Dense(64, activation='tanh'))
也可以通过传递一个逐元素运算的 Theano/TensorFlow 函数来作为激活函数:
- from keras import backend as K
-
- def tanh(x):
- return K.tanh(x)
-
- model.add(Dense(64, activation=tanh))
- model.add(Activation(tanh)
(nb_samples, nb_timesteps, nb_dims)
或 (nb_samples, nb_dims)
对于简单的 Theano/TensorFlow 不能表达的复杂激活函数,如含有可学习参数的激活函数,可通过高级激活函数实现,如 PReLU,LeakyReLU 等。下面我们详细介绍一下高级激活层。
LeakyRelU 是修正线性单元(Rectified Linear Unit,ReLU)的特殊版本,当不激活时,LeakyReLU 仍然会有非零输出值,从而获得一个小梯度,避免 ReLU 可能出现的神经元“死亡”现象。
keras.layers.advanced_activations.LeakyReLU(alpha=0.3)
该层输入 shape 任意,当使用该层为模型首层时需指定 input_shape
参数,输出 shape 与输入相同。
该层为参数化的 ReLU(Parametric ReLU),表达式是:f(x)={α∗x,x<0x,x≥0f(x)={α∗x,x<0x,x≥0,此处的 αα 为一个与 xshape 相同的可学习的参数向量。
keras.layers.advanced_activations.PReLU(shared_axes=None)
(batch, height, width, channels)
这样的 shape,则或许你会希望在空域共享参数,这样每个 filter 就只有一组参数,设定 shared_axes=[1,2]
可完成该目标ELU 层是指数线性单元(Exponential Linera Unit),表达式为: 该层为参数化的 ReLU(Parametric ReLU),表达式是:f(x)={α∗(exp(x)−1),x<0x,x≥0f(x)={α∗(exp(x)−1),x<0x,x≥0。
keras.layers.advanced_activations.ELU(alpha=1.0)
该层输入 shape 任意,当使用该层为模型首层时需指定 input_shape
参数,输出 shape 与输入相同。
该层是带有门限的 ReLU,表达式是:f(x)={x,x>θ0,otherwisef(x)={x,x>θ0,otherwise。
keras.layers.advanced_activations.ThresholdedReLU(theta=1.0)
该层输入 shape 任意,当使用该层为模型首层时需指定 input_shape
参数,输出 shape 与输入相同。
将长为 nb_samples 的序列(标量序列)转化为形如 (nb_samples,nb_timesteps) 的 2D numpy array。如果提供了参数 maxlen,nb_timesteps=maxlen
,否则其值为最长序列的长度。其他短于该长度的序列都会在后部填充 0以达到该长度。长于 nb_timesteps
的序列将会被截断,以使其匹配目标长度。padding 和截断发生的位置分别取决于 padding
和 truncating
。
- keras.preprocessing.sequence.pad_sequences(sequences, maxlen=None, dtype='int32',
- padding='pre', truncating='pre', value=0.)
返回值返回形如 (nb_samples,nb_timesteps)
的 2D 张量。
本函数将一个句子拆分成单词构成的列表。
keras.preprocessing.text.text_to_word_sequence(text, filters=base_filter(), lower=True, split=" ")
base_filter()
,包含标点符号,制表符和换行符等返回值为字符串列表。
本函数将一段文本编码为 one-hot 形式的码,即仅记录词在词典中的下标。
从定义上,当字典长为 n 时,每个单词应形成一个长为 n 的向量,其中仅有单词本身在字典中下标的位置为 1,其余均为 0,这称为 one-hot。
为了方便起见,函数在这里仅把“1”的位置,即字典中词的下标记录下来。
keras.preprocessing.text.one_hot(text, n, filters=base_filter(), lower=True, split=" ")
base_filter()
,包含标点符号,制表符和换行符等返回值为整数列表,每个整数是 [1,n][1,n] 之间的值,代表一个单词(不保证唯一性,即如果词典长度不够,不同的单词可能会被编为同一个码)。
Tokenizer 是一个用于向量化文本,或将文本转换为序列(即单词在字典中的下标构成的列表,从 1 算起)的类。
keras.preprocessing.text.Tokenizer(nb_words=None, filters=base_filter(), lower=True, split=" ")
nb_words-1
个单词base_filter()
,包含标点符号,制表符和换行符等类方法:
texts_to_sequences
的生成器函数版(len(texts), nb_words)
的 numpy array(len(sequences), nb_words)
的 numpy array属性:
fit_on_texts
之后设置。fit_on_texts
之后设置。fit_on_texts
之后设置。fit_on_texts
或 fit_on_sequences
之后设置。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。