[TOC]
安装,配置和测试
安装
keras需要依赖多个python库,包括numpy,scipy,pyyaml,HDF5, h5py,如果使用CNN的推荐安装cuDNN。
keras可以用TensorFlow,Theano,CNTK当后端,这边选的是tf。
安装环境建议选择Linux,配好python环境,windows上也可以装,据说坑比较多
命令如下:
conda install numpy scipy pyyaml h5py
安装tf
pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.8.0rc0-cp27-none-linux_x86_64.whl
需要注意下,我这边用的conda,后面编码的时候,也要用conda里的python,具体配置根据编译器的不同而不同。
配置
keras的建议配置是
主板:X299型号或Z270型号
CPU: i7-6950X或i7-7700K 及其以上高级型号
内存:品牌内存,总容量32G以上,根据主板组成4通道或8通道
SSD: 品牌固态硬盘,容量256G以上
显卡:NVIDIA GTX TITAN(XP) NVIDIA GTX 1080ti、NVIDIA GTX TITAN、NVIDIA GTX 1080、NVIDIA GTX 1070、NVIDIA GTX 1060 (顺序为优先建议,并且建议同一显卡,可以根据主板插槽数量购买多块,例如X299型号主板最多可以采用×4的显卡)
电源:由主机机容量的确定,一般有显卡总容量后再加200W即可
最低配置
CPU:Intel第三代i5和i7以上系列产品或同性能AMD公司产品
内存:总容量4G以上
有条件还是建议上显卡,毕竟深度学习涉及大量矩阵运算,cpu没有显卡来的方便。我这边条件不够,没用显卡,CUDA安装跳过。
下面就是配tf和keras,代码如下:
sudo pip install -U --pre pip setuptools wheel
sudo pip install -U --pre numpy scipy matplotlib scikit-learn scikit-image
sudo pip install -U --pre tensorflow-gpu
sudo pip install -U --pre keras
测试
安装好之后,需要测试一下,常用的是一个手写识别的程序,也就是mnist,代码如下
>>> git clone https://github.com/fchollet/keras.git
>>> cd keras/examples/
>>> python mnist_mlp.py
参考文档 https://keras.io/
模型
keras里有两种模型,分别是Sequential和Functional,下面分别论述,对于详细的api文档,参见参考文档3
Sequential
Sequential是多个网络层的线性堆叠,这边是一个模型定义和优化的例子,优化器暂时不用管,后面会提到
model = Sequential()
model.add(Dense(32, input_dim=784))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
这边就是先import一个model,然后制定数据的shape,并指定优化器和相关参数,接着就是数据的训练。
我们以lstm为例,做训练数据
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers import Embedding
from keras.layers import LSTM
model = Sequential()
model.add(Embedding(max_features, output_dim=256))
model.add(LSTM(128))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=16, epochs=10)
score = model.evaluate(x_test, y_test, batch_size=16)
训练的结果集可以用hdf5保存
Functional
Functional是一个能表达任意张量映射的model,Keras中Functional模型接口是用户定义多输出模型、非循环有向模型或具有共享层的模型等复杂模型的途径。
利用函数式模型的接口,我们可以很容易的重用已经训练好的模型:你可以把模型当作一个层一样,通过提供一个tensor来调用它。注意当你调用一个模型时,你不仅仅重用了它的结构,也重用了它的权重。
x = Input(shape=(784,))
# This works, and returns the 10-way softmax we defined above.
y = model(x)
这种方式可以允许你快速的创建能处理序列信号的模型,你可以很快将一个图像分类的模型变为一个对视频分类的模型,只需要一行代码:
from keras.layers import TimeDistributed
# Input tensor for sequences of 20 timesteps,
# each containing a 784-dimensional vector
input_sequences = Input(shape=(20, 784))
# This applies our previous model to every timestep in the input sequences.
# the output of the previous model was a 10-way softmax,
# so the output of the layer below will be a sequence of 20 vectors of size 10.
processed_sequences = TimeDistributed(model)(input_sequences)
另一个使用函数式模型的场合是使用共享层的时候。
考虑微博数据,我们希望建立模型来判别两条微博是否是来自同一个用户,这个需求同样可以用来判断一个用户的两条微博的相似性。
训练
这边选择了一个视觉问答的例子,让机器看一副图片,然后问问题并回答,这种工作,在有深度学习之前,可能需要一个team的人才能完成,现在也就十来行代码的工作量。
from keras.layers import Conv2D, MaxPooling2D, Flatten
from keras.layers import Input, LSTM, Embedding, Dense
from keras.models import Model, Sequential
# First, let's define a vision model using a Sequential model.
# This model will encode an image into a vector.
vision_model = Sequential()
vision_model.add(Conv2D(64, (3, 3) activation='relu', padding='same', input_shape=(3, 224, 224)))
vision_model.add(Conv2D(64, (3, 3), activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
vision_model.add(Conv2D(128, (3, 3), activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
vision_model.add(Conv2D(256, (3, 3), activation='relu'))
vision_model.add(Conv2D(256, (3, 3), activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Flatten())
# Now let's get a tensor with the output of our vision model:
image_input = Input(shape=(3, 224, 224))
encoded_image = vision_model(image_input)
# Next, let's define a language model to encode the question into a vector.
# Each question will be at most 100 word long,
# and we will index words as integers from 1 to 9999.
question_input = Input(shape=(100,), dtype='int32')
embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
encoded_question = LSTM(256)(embedded_question)
# Let's concatenate the question vector and the image vector:
merged = keras.layers.concatenate([encoded_question, encoded_image])
# And let's train a logistic regression over 1000 words on top:
output = Dense(1000, activation='softmax')(merged)
# This is our final model:
vqa_model = Model(inputs=[image_input, question_input], outputs=output)
# The next stage would be training this model on actual data.
参考文档 http://arxiv.org/abs/1409.4842
http://arxiv.org/abs/1512.03385
https://keras.io/models/model/
优化器
优化器是编译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()时传递一个预定义优化器名。在后者情形下,优化器的参数将使用默认值。
参数clipnorm和clipvalue是所有优化器都可以使用的参数,用于对梯度进行裁剪。
常用的优化器有SGD,Adam,Adadelta等。
SGD是随机梯度下降法,支持动量参数,支持学习衰减率,支持Nesterov动量
参数如下
lr:大于0的浮点数,学习率
momentum:大于0的浮点数,动量参数
decay:大于0的浮点数,每次更新后的学习率衰减值
nesterov:布尔值,确定是否使用Nesterov动量
Adam
Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。
参数如下
lr:大于0的浮点数,学习率
beta_1/beta_2:浮点数, 0
Adadelta
Adadelta是对Adagrad的扩展,最初方案依然是对学习率进行自适应约束,但是进行了计算上的简化。 Adagrad会累加之前所有的梯度平方,而Adadelta只累加固定大小的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值。
参数如下
lr:大于0的浮点数,学习率
rho:大于0的浮点数
epsilon:大于0的小浮点数,防止除0错误
参考文档 http://cs229.stanford.edu/proj2015/054_report.pdf
http://www.cs.toronto.edu/~fritz/absps/momentum.pdf
http://arxiv.org/abs/1212.5701
目标函数
目标函数,或称损失函数,是编译一个模型必须的两个参数之一
可以通过传递预定义目标函数名字指定目标函数,也可以传递一个Theano/TensroFlow的符号函数作为目标函数,该函数对每个数据点应该只返回一个标量值,并以下列两个参数为参数:
- y_true:真实的数据标签,Theano/TensorFlow张量
- y_pred:预测值,与y_true相同shape的Theano/TensorFlow张量
真实的优化目标函数是在各个数据点得到的损失函数值之和的均值