Keras:基于Python的深度学习库
Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow、Theano以及CNTK后端。Keras适用的Python版本是:Python 2.7-3.6。
1 - 一些基本概念
1.1 - 符号计算
Keras的底层库使用Theano或TensorFlow,这两个库也称为Keras的后端。无论是Theano还是TensorFlow,都是一个“符号式”的库。
因此,这也使得Keras的编程与传统的Python代码有所差别。笼统的说,符号主义的计算首先定义各种变量,然后建立一个“计算图”,计算图规定了各个变量之间的计算关系。建立好的计算图需要编译以确定其内部细节,然而,此时的计算图还是一个“空壳子”,里面没有任何实际的数据,只有当你把需要运算的输入放进去后,才能在整个模型中形成数据流,从而形成输出值。
就像用管道搭建供水系统,当你在拼水管的时候,里面是没有水的。只有所有的管子都接完了,才能送水。Keras的模型搭建形式就是这种方法,在你搭建Keras模型完毕后,你的模型就是一个空壳子,只有实际生成可调用的函数后,输入数据,才会形成真正的数据流。符号计算的优点是能够提供关键的计算优化、自动求导等功能。
1.2 - 张量
张量的阶数有时候也称为维度,或者轴,轴这个词翻译自英文axis。譬如一个矩阵[[1,2],[3,4]],是一个2阶张量,有两个维度或轴,沿着第0个轴(为了与python的计数方式一致,本文档维度和轴从0算起)你看到的是[1,2],[3,4]两个向量,沿着第1个轴你看到的是[1,3],[2,4]两个向量。
1.3 - shuffle和validation_split的顺序
模型的fit函数有两个参数,shuffle用于将数据打乱,validation_split用于在没有提供验证集的时候,按一定比例从训练集中取出一部分作为验证集
这里有个陷阱是,程序是先执行validation_split,再执行shuffle的,所以会出现这种情况:
假如你的训练集是有序的,比方说正样本在前负样本在后,又设置了validation_split,那么你的验证集中很可能将全部是负样本
同样的,这个东西不会有任何错误报出来,因为Keras不可能知道你的数据有没有经过shuffle,保险起见如果你的数据是没shuffle过的,最好手动shuffle一下
2 - Sequentail model
2.1 create computation graph
通过.add()方法一个个的将layer加入模型中
model = Sequential()
model.add(Dense(32, input_shape=(784,)))
model.add(Activation('relu'))
模型需要知道输入数据的shape,因此,Sequential的第一层需要接受一个关于输入数据shape的参数,后面的各个层则可以自动的推导出中间数据的shape,因此不需要为每个层都指定这个参数。有几种方法来为第一层指定输入数据的shape:
- 传递一个input_shape的关键字参数给第一层,input_shape是一个tuple类型的数据,其中也可以填入None,如果填入None则表示此位置可能是任何正整数。数据的batch大小不应包含在其中。
- 有些2D层,如Dense,支持通过指定其输入维度input_dim来隐含的指定输入数据shape,是一个Int类型的数据。一些3D的时域层支持通过参数input_dim和input_length来指定输入shape。
- 如果你需要为输入指定一个固定大小的batch_size(常用于stateful RNN网络),可以传递batch_size参数到一个层中,例如你想指定输入张量的batch大小是32,数据shape是(6, 8),则你需要传递batch_size=32和input_shape=(6,8)。
2.2 - compile the model
model.compile(optimizer = '...', loss = '...', metrics = )
Examples:
# For a multi-class classification problem
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# For a binary classification problem
model.compile(optimizer='adagrad',
loss='binary_crossentropy',
metrics=['accuracy'])
# For a mean squared error regression problem
model.compile(optimizer='sgd',
loss='mse')
# For custom metrics
import keras.backend as K
def mean_pred(y_true, y_pred):
return K.mean(y_pred)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy', mean_pred])
2.3 - train the model
model.fit(x =, y =, epochs =, batch_size =)
2.4 - examples
2.4.1 - MLP for binary classification
import matplotlib.pyplot as plt
import numpy as np
import keras
import sklearn
from sklearn import datasets
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
# describe the model
model = Sequential()
model.add(Dense(24, input_dim = 2, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(10, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(1, activation = "sigmoid"))
# prepare dataset
train_X, train_Y = sklearn.datasets.make_moons(n_samples=300, noise=.2)
test_X, test_Y = sklearn.datasets.make_moons(n_samples=100, noise=.2)
plt.rcParams['figure.figsize'] = (9, 3)
plt.subplot(121)
plt.scatter(train_X[:,0], train_X[:,1], c = train_Y, s = 40, cmap = plt.cm.Spectral)
train_Y = np.reshape(train_Y, (train_Y.shape[0], 1))
# configure
model.compile(optimizer='adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
# training
hist = model.fit(x=train_X, y=train_Y, epochs=500, batch_size=64, verbose=0)
plt.subplot(122)
plt.plot(hist.history['acc'])
plt.show()
# evaluate the model
preds = model.evaluate(x=test_X, y=test_Y)
print("accuracy in the test set: " + str(preds[1]))
100/100 [==============================] - 0s 600us/step
accuracy in the test set: 0.94
2.4.2 - MLP for softmax classification
from keras.optimizers import SGD
model = Sequential()
model.add(Dense(32, activation='relu', input_dim = 20))
model.add(Dropout(0.5))
model.add(Dense(32, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
# create dataset
x_train = np.random.randn(1000, 20)
y_train = keras.utils.to_categorical(np.random.randint(2, size=(1000, 1)), 10) # keras.utils.to_categorical(y, classes)
print("x_train.shape: " + str(x_train.shape))
print("y_train.shape: " + str(y_train.shape))
model.compile(optimizer=SGD(lr=0.01, decay=1e-6, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])
hist = model.fit(x=x_train, y=y_train, epochs=5, batch_size=64)
x_train.shape: (1000, 20)
y_train.shape: (1000, 10)
WARNING:tensorflow:Variable *= will be deprecated. Use variable.assign_mul if you want assignment to the variable value or 'x = x * y' if you want a new python Tensor object.
Epoch 1/5
1000/1000 [==============================] - 0s 227us/step - loss: 1.9975 - acc: 0.2770
Epoch 2/5
1000/1000 [==============================] - 0s 26us/step - loss: 0.9966 - acc: 0.5120
Epoch 3/5
1000/1000 [==============================] - 0s 30us/step - loss: 0.7938 - acc: 0.5290
Epoch 4/5
1000/1000 [==============================] - 0s 27us/step - loss: 0.7581 - acc: 0.5010
Epoch 5/5
1000/1000 [==============================] - 0s 26us/step - loss: 0.7526 - acc: 0.4930
2.4.3 - 类似VGG
from keras.layers import Conv2D, Flatten, MaxPool2D
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(3, 3), activation="relu", input_shape = (100, 100, 3)))
model.add(Conv2D(filters=32, kernel_size=(3, 3), activation="relu"))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation="relu"))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(10, activation='softmax'))
# create data
x_train = np.random.randn(30, 100, 100, 3)
y_train = keras.utils.to_categorical(np.random.randint(10, size=(30, 1)), 10)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5, batch_size=64)
Epoch 1/5
30/30 [==============================] - 2s 63ms/step - loss: 2.3240 - acc: 0.0333
Epoch 2/5
30/30 [==============================] - 1s 40ms/step - loss: 10.9195 - acc: 0.1667
Epoch 3/5
30/30 [==============================] - 1s 40ms/step - loss: 7.5836 - acc: 0.1667
Epoch 4/5
30/30 [==============================] - 1s 41ms/step - loss: 4.2055 - acc: 0.1667
Epoch 5/5
30/30 [==============================] - 1s 40ms/step - loss: 3.0748 - acc: 0.1000
<keras.callbacks.History at 0x286f402bf60>
2.4.4 - 使用LSTM的序列分类
from keras.layers import Embedding
from keras.layers import LSTM
model = Sequential()
model.add(Embedding(max_feature, output_dim=256))
model.add(LSTM(128))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(x = , y = , epochs= , batch_size= )
2.4.5 - 使用1D卷积的序列分类
from keras.layers import Conv1D, GlobalAveragePooling1D, MaxPooling1D
model = Sequential()
model.add(Conv1D(64, 3, activation='relu', input_shape=(seq_length, 100)))
model.add(Conv1D(64, 3, activation='relu'))
model.add(MaxPooling1D(3))
model.add(Conv1D(128, 3, activation='relu'))
model.add(Conv1D(128, 3, activation='relu'))
model.add(GlobalAveragePooling1D())
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)
3 - Functional model
该类模型能够表达任意张量映射, Keras函数式模型接口是用户定义多输出模型、非循环有向模型或具有共享层的模型等复杂模型的途径。一句话,只要你的模型不是类似VGG一样一条路走到黑的模型,或者你的模型需要多于一个的输出,那么你总应该选择函数式模型。函数式模型是最广泛的一类模型,序贯模型(Sequential)只是它的一种特殊情况。
3.1 - 第一个模型:全连接网络
from keras.models import Model
from keras.layers import Input
x_input = Input(shape = (784, ))
x = Dense(64, activation='relu')(x_input)
x = Dense(64, activation='relu')(x)
x = Dense(10, activation='softmax')(x)
model = Model(inputs=x_input, outputs=x)
x_train = np.random.randn(200, 784)
y_train = keras.utils.to_categorical(np.random.randint(10, size=(200, 1)))
model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5, batch_size=32)
Epoch 1/5
200/200 [==============================] - 0s 1ms/step - loss: 2.6034 - acc: 0.1100
Epoch 2/5
200/200 [==============================] - 0s 78us/step - loss: 2.4080 - acc: 0.1600
Epoch 3/5
200/200 [==============================] - 0s 78us/step - loss: 2.2671 - acc: 0.2150
Epoch 4/5
200/200 [==============================] - 0s 78us/step - loss: 2.1440 - acc: 0.2500
Epoch 5/5
200/200 [==============================] - 0s 78us/step - loss: 2.0384 - acc: 0.3000
<keras.callbacks.History at 0x286872c7eb8>
所有的模型都是可调用的,就像层一样
利用函数式模型的接口,我们可以很容易的重用已经训练好的模型:你可以把模型当作一个层一样,通过提供一个tensor来调用它。注意当你调用一个模型时,你不仅仅重用了它的结构,也重用了它的权重。
x = Input(shape=(784, ))
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)
3.2 - 多输入和多输出模型
使用函数式模型的一个典型场景是搭建多输入、多输出的模型。
考虑这样一个模型。我们希望预测Twitter上一条新闻会被转发和点赞多少次。模型的主要输入是新闻本身,也就是一个词语的序列。但我们还可以拥有额外的输入,如新闻发布的日期等。这个模型的损失函数将由两部分组成,辅助的损失函数评估仅仅基于新闻本身做出预测的情况,主损失函数评估基于新闻和额外信息的预测的情况,即使来自主损失函数的梯度发生弥散,来自辅助损失函数的信息也能够训练Embeddding和LSTM层。在模型中早点使用主要的损失函数是对于深度网络的一个良好的正则方法。总而言之,该模型框图如下:
from keras.layers import Embedding
from keras.layers import LSTM
main_input = Input(shape=(100, ))
x = Embedding(input_dim=10000, output_dim=512, input_length=100)(main_input)
lstm_1 = LSTM(32)(x)
aux_output = Dense(1, activation='sigmoid', name='auxiliary_output')(lstm_1)
aux_input = Input(shape=(5, ))
x = keras.layers.concatenate([lstm_1, aux_input])
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
main_output = Dense(1, activation='sigmoid', name='main_output')(x)
我们定义整个2输入,2输出的模型
model_multi_io = Model(inputs=[main_input, aux_input], outputs=[main_output, aux_output])
我们给额外的损失赋0.2的权重。我们可以通过关键字参数loss_weights或loss来为不同的输出设置不同的权值或者是损失函数。这两个参数均可为Python的列表或字典。这里我们给loss传递单个损失函数,这个损失函数会被应用于所有输出上
model_multi_io.compile(optimizer='adam', loss='binary_crossentropy', loss_weights=[1, 0.2])
或者是用如下的方式分别指定:
model_multi_io.compile(optimizer='adam', loss={'main_output':'binary_crossentropy', 'axuiliary_output':'binary_crossentropy'}, loss_wights = {'main_output':1, 'axuiliary_output':0.2})
传递训练数据和目标值训练该模型
model.fit([headline_data, additional_data], [labels, labels], epochs=50, batch_size=32)
3.3 - 共享层
另一个使用函数式模型的场合是使用共享层的时候。
考虑微博数据,我们希望建立模型来判别两条微博是否是来自同一个用户,这个需求同样可以用来判断一个用户的两条微博的相似性。
一种实现方式是,我们建立一个模型,它分别将两条微博的数据映射到两个特征向量上,然后将特征向量串联并加一个logistic回归层,输出它们来自同一个用户的概率。这种模型的训练数据是一对对的微博。
因为这个问题是对称的,所以处理第一条微博的模型当然也能重用于处理第二条微博。所以这里我们使用一个共享的LSTM层来进行映射。
首先,我们将微博的数据转为(140,256)的矩阵,即每条微博有140个单词,每个单词的特征由一个256维的词向量表示,向量的每个元素为1表示某个字符出现,为0表示不出现,这是一个one-hot编码。
之所以是(140,256)是因为一条微博最多有140个字符,而扩展的ASCII码表编码了常见的256个字符。原文中此处为Tweet,所以对外国人而言这是合理的。如果考虑中文字符,那一个单词的词向量就不止256了。
a_input = Input(shape=(140, 256))
b_input = Input(shape=(140, 256))
# take as input a matrix and will return a vector of size 64
share_lstm = LSTM(64)
# When we reuse the same layer instance
# multiple times, the weights of the layer
# are also being reused
lstm_out1 = share_lstm(a_input)
lstm_out2 = share_lstm(b_input)
merge_vector = keras.layers.concatenate([lstm_out1, lstm_out2])
pre = Dense(1, activation='sigmoid')(merge_vector)
model = Model(inputs=[a_input, b_input], outputs=pre)
3.4 - 层节点
无论何时,当你在某个输入上调用层时,你就创建了一个新的张量(即该层的输出),同时你也在为这个层增加一个“(计算)节点”。这个节点将输入张量映射为输出张量。当你多次调用该层时,这个层就有了多个节点,其下标分别为0,1,2…。在如下的代码示例中因为lstm层有两个不同的“输出节点”,所以直接使用lstm.output为报错,而应该使用lstm.get_output_at(0)或者是lstm.get_output_at(1)。
a = Input(shape=(140, 256))
b = Input(shape=(140, 256))
lstm = LSTM(32)
encoded_a = lstm(a)
encoded_b = lstm(b)
lstm.output
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-6-c7b7678a5257> in <module>()
6 encoded_b = lstm(b)
7
----> 8 lstm.output
D:\Software_robin\ada\lib\site-packages\keras\engine\topology.py in output(self)
969 if len(self._inbound_nodes) > 1:
970 raise AttributeError('Layer ' + self.name +
--> 971 ' has multiple inbound nodes, '
972 'hence the notion of "layer output" '
973 'is ill-defined. '
AttributeError: Layer lstm_2 has multiple inbound nodes, hence the notion of "layer output" is ill-defined. Use `get_output_at(node_index)` instead.
assert lstm.get_output_at(0) == encoded_a
assert lstm.get_output_at(1) == encoded_b
a = Input(shape=(32, 32, 3))
b = Input(shape=(64, 64, 3))
conv = Conv2D(16, (3, 3), padding='same')
conved_a = conv(a)
# Only one input so far, the following will work:
assert conv.input_shape == (None, 32, 32, 3)
conved_b = conv(b)
# now the `.input_shape` property wouldn't work, but this does:
assert conv.get_input_shape_at(0) == (None, 32, 32, 3)
assert conv.get_input_shape_at(1) == (None, 64, 64, 3)
assert conv.get_output_at(0) == conved_a
assert conv.get_output_at(1) == conved_b
3.5 - 关于共享层的更多的例子
3.5.1 - inception
one layer of inception network
from keras.layers import MaxPooling2D
x_input = Input(shape=(256, 256, 3))
tower1 = Conv2D(filters=64, kernel_size=(1, 1), padding="same", activation="relu")(x_input)
tower2 = Conv2D(filters=64, kernel_size=(1, 1), padding='same', activation='relu')(x_input)
tower2 = Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu')(tower2)
tower3 = Conv2D(filters=64, kernel_size=(1, 1), padding="same", activation='relu')(x_input)
tower3 = Conv2D(filters=64, kernel_size=(5, 5), padding="same", activation='relu')(tower3)
tower4 = MaxPooling2D(pool_size=(3, 3), padding="same", strides=(1, 1))(x_input)
tower4 = Conv2D(filters=64, kernel_size=(1, 1), activation="relu")(tower4)
x = keras.layers.concatenate([tower1, tower2, tower3, tower4], axis=1)
3.5.2 - residual network
from keras.layers import BatchNormalization
x_input = Input(shape=(64, 64, 32))
x = Conv2D(filters=32, kernel_size=(3, 3), strides=(1, 1), padding="same")(x_input)
x = BatchNormalization(axis = 3)(x)
x = Activation('relu')(x)
x = Conv2D(filters=32, kernel_size=(1, 1), strides=(1, 1), padding="same")(x)
x = BatchNormalization(axis = 3)(x)
x = keras.layers.add([x_input, x])
x = Activation('relu')(x)
3.5.3 - 共享视觉模型
该模型在两个输入上重用了图像处理的模型,用来判别两个MNIST数字是否是相同的数字
x_input = Input(shape=(27, 27, 1))
x = Conv2D(32, (3, 3), strides=(1, 1), padding="same")(x_input)
x = BatchNormalization(axis=3)(x)
x = Activation('relu')(x)
x = MaxPooling2D((2, 2), strides=(1, 1))(x)
x = Flatten()(x)
vision_model = Model(inputs=x_input, outputs=x)
a_input = Input(shape=(27, 27, 1))
b_input = Input(shape=(27, 27, 1))
a_output = vision_model(a_input)
b_output = vision_model(b_input)
concatenated = keras.layers.concatenate([a_output, b_output])
x = Dense(1, activation='softmax')(concatenated)
classifier_model = Model(inputs=[a_input, b_input], outputs=x)
3.5.4 - 视觉问答模型
在针对一幅图片使用自然语言进行提问时,该模型能够提供关于该图片的一个单词的答案。
解决方案:将自然语言的问题和图片分别映射为特征向量,将二者合并后训练一个logistic回归层,从一系列可能的回答中挑选一个。
# first, define a vision model to encode an image into a vector
img_input = Input(shape=(224, 224, 3))
x = Conv2D(64, (3, 3), activation='relu', padding="same")(img_input)
x = Conv2D(64, (3, 3), activation="relu")(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(128, (3, 3), activation='relu', padding="same")(x)
x = Conv2D(128, (3, 3), activation='relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)
x = Conv2D(256, (3, 3), activation='relu')(x)
x = Conv2D(256, (3, 3), activation='relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
img_output = Flatten()(x)
# second 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, ))
x = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
question_encode = LSTM(256)(x)
# let's concatenate the question vector and the image vector:
merged = keras.layers.concatenate([img_output, question_encode])
# train a softmax classification over 1000 answer words
qa_output = Dense(1000, activation='softmax')(merged)
# build the our final model
qa_model = Model(inputs=[img_input, question_input], outputs=qa_output)
3.5.5 - 视频问答模型
在做完图片问答模型后,我们可以快速将其转为视频问答的模型。在适当的训练下,你可以为模型提供一个短视频(如100帧)然后向模型提问一个关于该视频的问题,如
“what sport is the boy playing?”
“football”
from keras.layers import TimeDistributed
video_input = Input(shape=(100, 224, 224, 3))
vision_model = Model(inputs = img_input, outputs=img_output)
encoded_frame_sequence = TimeDistributed(vision_model)(video_input)
video_output = LSTM(256)(encoded_frame_sequence)
video_question_input = Input(shape=(100, ))
# This is a model-level representation of the question encoder, reusing the same weights as before
question_encoder = Model(inputs=question_input, outputs=question_encode)
video_question_output = question_encoder(video_question_input)
vedio_merged = keras.layers.concatenate([video_output, video_question_output])
qa_video_output = Dense(1000, activation='softmax')(vedio_merged)
video_qa_model = Model(inputs=[video_input, video_question_input], outputs=qa_video_output)
4 - Keras模型的通用方法
Keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。
两类模型有一些方法是相同的:
model.summary():
打印出模型概况model.get_config():
返回包含模型配置信息的Python字典。模型也可以从它的config信息中重构回去
python
model = Model.from_config(config)
# or, for Sequential:
model = Sequential.from_config(config)
model.save_weight(filepath):
将模型权重保存到指定路径,文件类型是HDF5(后缀是.h5)model.load_weight(filepath, by_name=False):
从HDF5文件中加载权重到当前模型中, 默认情况下模型的结构将保持不变。如果想将权重载入不同的模型(有些层相同)中,则设置by_name=True,只有名字匹配的层才会载入权重model.get_layer():
依据层名或下标获得层对象model.get_weights():
返回模型权重张量的列表,类型为numpy array
model.set_weights():
从numpy array
里将权重载入给模型,要求数组具有与model.get_weights()
相同的形状model.to_json():
返回代表模型的JSON字符串,仅包含网络结构,不包含权值from models import model_from_json json_string = model.to_json() model = model_from_json(json_string)
5 - Sequential模型接口
compile
compile(self, optimizer, loss, metrics=None, sample_weight_mode=None)
optimizer:
字符串(预定义优化器名)或优化器对象loss:
字符串(预定义损失函数名)或目标函数metrics:
列表,包含评估模型在训练和测试时的网络性能的指标
fit
hist = fit(self, x, y, batch_size=32, epochs=10, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)
x:
输入数据。如果模型只有一个输入,那么x的类型是numpy array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy arrayy:
标签,numpy arraybatch_size:
整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步epochs:
遍历数据集的次数verbose:
日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录validation_split:
0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀validation_data:
形式为(X,y)的tuple,是指定的验证集。此参数将覆盖validation_spiltshuffle:
布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱initial_epoch:
从该参数指定的epoch开始训练,在继续之前的训练时有用。class_weight:
字典,对不同的类别设置不同的权值,该参数在处理非平衡的训练数据(某些类的训练样本数很少)时,可以使得损失函数对样本数不足的数据更加关注。sample_weight:
numpy array, 对样本设置权重值,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权
fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况
evaluate
evaluate(self, x, y, batch_size=32, verbose=1,sample_weight=None)
本函数返回一个测试误差的标量值(如果模型没有其他评价指标),或一个标量的list(如果模型还有其他的评价指标)。model.metrics_names将给出list中各个值的含义。
predict
predict(self, x, batch_size=32, verbose=0)
本函数按batch获得输入数据对应的输出
6 - Model模型接口
6.1 - model的常用属性
model.layers:
组成模型图的各个层model.inputs:
模型的输入张量列表model.outputs
模型的输出张量列表
6.2 - model的常用方法
compile
compile(self, optimizer, loss, metrics=None, loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)
如果你只是载入模型并利用其predict,可以不用进行compile。在Keras中,compile主要完成损失函数和优化器的一些配置,是为训练服务的。
- fit
“`python
fit(self, x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0, steps_per_epoch=None, validation_steps=None)
- fit
“`
- evaluate
python
evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
7 - callback
import matplotlib.pyplot as plt
import numpy as np
import sklearn
from sklearn import datasets
from keras.models import Sequential, load_model
from keras.layers import Dense, Dropout
from keras.callbacks import ModelCheckpoint
plt.rcParams['figure.figsize'] = (9, 3)
# describe the model
model = Sequential()
model.add(Dense(24, input_dim = 2, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(10, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(1, activation = "sigmoid"))
# prepare dataset
train_X, train_Y = sklearn.datasets.make_moons(n_samples=300, noise=.2)
test_X, test_Y = sklearn.datasets.make_moons(n_samples=100, noise=.2)
train_Y = np.reshape(train_Y, (train_Y.shape[0], 1))
# callback function
checkpointer = ModelCheckpoint(filepath="result/best.h5", monitor='val_acc',
verbose=1, save_best_only=True)
# configure
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# training
hist = model.fit(x=train_X, y=train_Y, epochs=500, batch_size=64, verbose=1,
validation_split=0.1, callbacks=[checkpointer])
# evaluate the model
preds = model.evaluate(x=test_X, y=test_Y)
print("accuracy in the test set: " + str(preds[1]))
model.save('result/model.h5')
plt.subplot(121)
plt.scatter(train_X[:,0], train_X[:,1], c = train_Y, s = 40, cmap = plt.cm.Spectral)
plt.subplot(122)
plt.plot(hist.history['acc'])
plt.show()
# test load_model
print("*" * 50)
# test_X, test_Y = sklearn.datasets.make_moons(n_samples=100, noise=.2)
model_last = load_model('result/model.h5')
model_best = load_model('result/best.h5')
preds_last = model_last.evaluate(x=test_X, y=test_Y)
preds_best = model_best.evaluate(x=test_X, y=test_Y)
print('accuracy(last): ' + str(preds_last[1]))
print('accuracy(best): ' + str(preds_best[1]))