一.引入tf.keras
代码:
import tensorflow as tf
from tensorflow import keras
你可以查看其版本,这个我就不展示了。
当你保存模型的权重的时候,tf.keras默认保存为检查点形式,所以你需要“ save_format='h5' "来使用HDF5。
二.建造简单的模型
2.1 sequential 模型
最简单的模型是一种层的堆叠,使用的是tf.keras.Sequential模型。我们这里构造的是简单的全连接层的堆叠。
你可以使用以下的方法进行模型的层的叠加,当然你也可以使用下面的方式。
代码:
model=keras.models.Sequential(
[
keras.layers.Dense(64,activation='relu'),
keras.layers.Dense(64,activation='relu'),
keras.layers.Dense(10,activation='softmax')
]
)
代码2:
model=keras.models.Sequential()
model.add(keras.layers.Dense(64,activation='relu'))
model.add(keras.layers.Dense(64,activation=tf.nn.relu))
model.add(keras.layers.Dense(10,activation='softmax'))
2.2 配置层
在这里有不少tf.keras.layers共有的一些相同的构造参数。
1.activation:设置成的激活函数,这个参数可以由函数名来指定,当然也可以是一个调用的实体。默认是没有激活器的。
2.kernel_initializer和bias_initializer:用来初始化层的参数,参数可以是一个名字,当然也可以是一个调用的实体。默认使用的是"Glorot uniform"
3.kernel_regularizer和bias_regularizer:给我们的参数加上正则化,包含L1或者L2正则化,默认是无正则化的。
代码:这里直接将官网的代码copy下来的。
# Create a sigmoid layer:
layers.Dense(64, activation='sigmoid')
# Or:
layers.Dense(64, activation=tf.sigmoid)
# A linear layer with L1 regularization of factor 0.01 applied to the kernel matrix:
layers.Dense(64, kernel_regularizer=keras.regularizers.l1(0.01))
# A linear layer with L2 regularization of factor 0.01 applied to the bias vector:
layers.Dense(64, bias_regularizer=keras.regularizers.l2(0.01))
# A linear layer with a kernel initialized to a random orthogonal matrix:
layers.Dense(64, kernel_initializer='orthogonal')
# A linear layer with a bias vector initialized to 2.0s:
layers.Dense(64, bias_initializer=keras.initializers.constant(2.0))
三.训练和评估
3.1 训练的准备活动
当我们将模型构建好了之后,我们需要配置它的学习的过程,这个我们称之为compile方法。
代码:
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
解释:
compile具有下面比较主要的参数:
(1):optimizer,指定了训练的过程,可以通过tf.train模块,例如AdamOptimizer,RMSPropOptimizer或者是GradientDescentOptimizer。
(2):loss,在优化过程中最小化的函数,一般的选择有mean_square_error(mse),categorical_crossentropy,binary-crossentropy.可以通过名字或者是调用实体(tf.keras.losses)
(3)metrics:来监视训练的过程,使用的是名字或者是tf.keras.metrics模块的调用实体。
代码:这个是直接从官网上拷贝下来的,没有什么好解释的。
# Configure a model for mean-squared error regression.
model.compile(optimizer=tf.train.AdamOptimizer(0.01),
loss='mse', # mean squared error
metrics=['mae']) # mean absolute error
# Configure a model for categorical classification.
model.compile(optimizer=tf.train.RMSPropOptimizer(0.01),
loss=keras.losses.categorical_crossentropy,
metrics=[keras.metrics.categorical_accuracy])
3.2 输入numpy数组
对于小的数据集,我们直接使用numpy数组来训练和评估模型。模型通过fit来拟合我们的训练集数据。
代码:
import numpy as np
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
model.fit(data, labels, epochs=10, batch_size=32)
结果展示:
Epoch 1/10
2018-07-23 16:07:00.034873: I tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
32/1000 [..............................] - ETA: 6s - loss: 12.0619 - acc: 0.0938
864/1000 [========================>.....] - ETA: 0s - loss: 11.6286 - acc: 0.0984
1000/1000 [==============================] - 0s 270us/step - loss: 11.6498 - acc: 0.1010
Epoch 2/10
32/1000 [..............................] - ETA: 0s - loss: 11.7107 - acc: 0.0000e+00
736/1000 [=====================>........] - ETA: 0s - loss: 11.5116 - acc: 0.0978
1000/1000 [==============================] - 0s 72us/step - loss: 11.6074 - acc: 0.0960
Epoch 3/10
32/1000 [..............................] - ETA: 0s - loss: 11.4286 - acc: 0.0000e+00
768/1000 [======================>.......] - ETA: 0s - loss: 11.6153 - acc: 0.0990
1000/1000 [==============================] - 0s 80us/step - loss: 11.5988 - acc: 0.1070
Epoch 4/10
32/1000 [..............................] - ETA: 0s - loss: 11.8794 - acc: 0.0938
832/1000 [=======================>......] - ETA: 0s - loss: 11.6395 - acc: 0.1214
1000/1000 [==============================] - 0s 63us/step - loss: 11.5910 - acc: 0.1140
Epoch 5/10
32/1000 [..............................] - ETA: 0s - loss: 11.6141 - acc: 0.2500
800/1000 [=======================>......] - ETA: 0s - loss: 11.5900 - acc: 0.1250
1000/1000 [==============================] - 0s 68us/step - loss: 11.5857 - acc: 0.1260
Epoch 6/10
32/1000 [..............................] - ETA: 0s - loss: 11.4691 - acc: 0.2188
896/1000 [=========================>....] - ETA: 0s - loss: 11.5732 - acc: 0.1373
1000/1000 [==============================] - 0s 60us/step - loss: 11.5814 - acc: 0.1370
Epoch 7/10
32/1000 [..............................] - ETA: 0s - loss: 11.6447 - acc: 0.1250
608/1000 [=================>............] - ETA: 0s - loss: 11.5602 - acc: 0.1382
1000/1000 [==============================] - 0s 90us/step - loss: 11.5768 - acc: 0.1310
Epoch 8/10
32/1000 [..............................] - ETA: 0s - loss: 11.4899 - acc: 0.0938
704/1000 [====================>.........] - ETA: 0s - loss: 11.5351 - acc: 0.1364
1000/1000 [==============================] - 0s 73us/step - loss: 11.5716 - acc: 0.1480
Epoch 9/10
32/1000 [..............................] - ETA: 0s - loss: 11.4985 - acc: 0.1875
768/1000 [======================>.......] - ETA: 0s - loss: 11.5749 - acc: 0.1719
1000/1000 [==============================] - 0s 71us/step - loss: 11.5698 - acc: 0.1610
Epoch 10/10
32/1000 [..............................] - ETA: 0s - loss: 11.2773 - acc: 0.1875
672/1000 [===================>..........] - ETA: 0s - loss: 11.5233 - acc: 0.1786
1000/1000 [==============================] - 0s 83us/step - loss: 11.5632 - acc: 0.1790
tf.keras.Model.fit存在下面三个重要的参数:
(1):epochs,一次epoch表示一次在所有的输入数据上的迭代
(2):batch_size,当我们输入的是numpy数组的时候,这个模型将数据切分成很多的小的批次,训练的过程中通过批次来迭代。这个整数展示了每一个批次的大小。最后一个批次的数量可能小于其他的批次的size,毕竟不一定整除嘛!
(3):validation_data:我们希望检测一下模型对于新的数据的性能,使得模型可以展示在交叉验证集上的损失和metrics的数据结果。
代码:修改之前的代码,加上交叉验证集
import numpy as np
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
val_data = np.random.random((100, 32))
val_labels = np.random.random((100, 10))
model.fit(data, labels, epochs=10, batch_size=32,
validation_data=(val_data, val_labels))
结果展示:
Train on 1000 samples, validate on 100 samples
Epoch 1/10
32/1000 [..............................] - ETA: 6s - loss: 11.2842 - acc: 0.0938
832/1000 [=======================>......] - ETA: 0s - loss: 11.5433 - acc: 0.0925
1000/1000 [==============================] - 0s 328us/step - loss: 11.5484 - acc: 0.0950 - val_loss: 11.6482 - val_acc: 0.1300
Epoch 2/10
32/1000 [..............................] - ETA: 0s - loss: 11.6269 - acc: 0.1250
864/1000 [========================>.....] - ETA: 0s - loss: 11.4853 - acc: 0.1100
1000/1000 [==============================] - 0s 66us/step - loss: 11.5068 - acc: 0.1090 - val_loss: 11.6458 - val_acc: 0.0700
Epoch 3/10
32/1000 [..............................] - ETA: 0s - loss: 11.6363 - acc: 0.0938
704/1000 [====================>.........] - ETA: 0s - loss: 11.5435 - acc: 0.1207
1000/1000 [==============================] - 0s 78us/step - loss: 11.4980 - acc: 0.1130 - val_loss: 11.6452 - val_acc: 0.0500
Epoch 4/10
32/1000 [..............................] - ETA: 0s - loss: 11.5251 - acc: 0.1562
736/1000 [=====================>........] - ETA: 0s - loss: 11.5585 - acc: 0.1250
1000/1000 [==============================] - 0s 74us/step - loss: 11.4932 - acc: 0.1300 - val_loss: 11.6434 - val_acc: 0.0700
Epoch 5/10
32/1000 [..............................] - ETA: 0s - loss: 11.8754 - acc: 0.0312
832/1000 [=======================>......] - ETA: 0s - loss: 11.4917 - acc: 0.1334
1000/1000 [==============================] - 0s 72us/step - loss: 11.4875 - acc: 0.1340 - val_loss: 11.6461 - val_acc: 0.0600
Epoch 6/10
32/1000 [..............................] - ETA: 0s - loss: 12.0629 - acc: 0.1875
864/1000 [========================>.....] - ETA: 0s - loss: 11.4409 - acc: 0.1551
1000/1000 [==============================] - 0s 68us/step - loss: 11.4834 - acc: 0.1460 - val_loss: 11.6495 - val_acc: 0.1300
Epoch 7/10
32/1000 [..............................] - ETA: 0s - loss: 11.6350 - acc: 0.0938
608/1000 [=================>............] - ETA: 0s - loss: 11.4943 - acc: 0.1579
1000/1000 [==============================] - 0s 83us/step - loss: 11.4804 - acc: 0.1480 - val_loss: 11.6508 - val_acc: 0.0900
Epoch 8/10
32/1000 [..............................] - ETA: 0s - loss: 12.5630 - acc: 0.0938
672/1000 [===================>..........] - ETA: 0s - loss: 11.4119 - acc: 0.1354
1000/1000 [==============================] - 0s 78us/step - loss: 11.4758 - acc: 0.1390 - val_loss: 11.6493 - val_acc: 0.0700
Epoch 9/10
32/1000 [..............................] - ETA: 0s - loss: 11.2529 - acc: 0.1250
704/1000 [====================>.........] - ETA: 0s - loss: 11.4514 - acc: 0.1364
1000/1000 [==============================] - 0s 85us/step - loss: 11.4716 - acc: 0.1390 - val_loss: 11.6496 - val_acc: 0.0900
Epoch 10/10
32/1000 [..............................] - ETA: 0s - loss: 11.5364 - acc: 0.1562
800/1000 [=======================>......] - ETA: 0s - loss: 11.4675 - acc: 0.1400
1000/1000 [==============================] - 0s 69us/step - loss: 11.4675 - acc: 0.1370 - val_loss: 11.6540 - val_acc: 0.0700
Process finished with exit code 0
3.3输入tf.data.Datasets
对于较大的数据集或者对于多设备的训练,我们使用tf.data.Dataset实体。
这里我运行代码出现了错误,并不知道怎么解决。。。。上网百度了一下,没找到解决方法
就是说我提供的数据不对,要么给模型提供一个数组,要么给他提供一个数组的list。但是我提供的是。。。,但是不知道怎么改啊!!!
代码:难不成是版本问题。
import tensorflow as tf
from tensorflow import keras
import numpy as np
model=keras.models.Sequential()
model.add(keras.layers.Dense(64,activation='relu'))
model.add(keras.layers.Dense(64,activation='relu'))
model.add(keras.layers.Dense(10,activation='softmax'))
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
data=np.random.random((1000,32))
labels=np.random.random((1000,10))
# val_data=np.random.random((100,32))
# val_labels=np.random.random((100,10))
#实例化一个小的数据集
# Instantiates a toy dataset instance:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32).repeat()
model.fit(dataset, epochs=10, steps_per_epoch=30)
结果:
ValueError: Please provide as model inputs either a single array or a list of arrays. You passed: x=<RepeatDataset shapes: ((?, 32), (?, 10)), types: (tf.float64, tf.float64)>
代码:这个带上的是交叉验证集,肯定也是一样的错误,。。。
import tensorflow as tf
from tensorflow import keras
import numpy as np
model=keras.models.Sequential()
model.add(keras.layers.Dense(64,activation='relu'))
model.add(keras.layers.Dense(64,activation='relu'))
model.add(keras.layers.Dense(10,activation='softmax'))
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
data=np.random.random((1000,32))
labels=np.random.random((1000,10))
val_data=np.random.random((100,32))
val_labels=np.random.random((100,10))
#实例化一个小的数据集
# Instantiates a toy dataset instance:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32).repeat()
val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels))
val_dataset = val_dataset.batch(32).repeat()
model.fit(dataset, epochs=10, steps_per_epoch=30,
validation_data=val_dataset,
validation_steps=3)
结果:
ValueError: Please provide as model inputs either a single array or a list of arrays. You passed: x=<RepeatDataset shapes: ((?, 32), (?, 10)), types: (tf.float64, tf.float64)>
3.4 评估和预测
tf.keras.Model.evaluate和tf.keras.Model.predict可以使用numpy数组或者使用tf.data.Dataset
为了评估数据的损失和metrics,使用下面的代码:
model.evaluate(x, y, batch_size=32)
model.evaluate(dataset, steps=30)
为了预测输入数据的输出结果:
model.evaluate(x, y, batch_size=32)
model.evaluate(dataset, steps=30)
四.建造更高级的模型
4.1 function API
tf.keras.Sequential模型仅仅只是层的堆叠,无法表示复杂的模型。但是使用keras functional API可以来构建复杂拓扑结构的模型:
例如:多输入,多输出,带有共享层的模型,非序列的数据流模型例如残差连接
一个functional API模型:
第一:一个层实体可以被调用,返回tensor
第二:输入的tensor和输出的tensor被使用来定义tf.keras.Model实体。
第三:模型就像Sequential模型一样的训练。
下面的代码来实现一个全连接层的模型:
import tensorflow as tf
from tensorflow import keras
import numpy as np
data=np.random.random((1000,32))
labels=np.random.random((1000,10))
input=keras.layers.Input(shape=(32,))
x=keras.layers.Dense(64,activation='relu')(input)
x=keras.layers.Dense(64,activation='relu')(x)
predictions=keras.layers.Dense(10,activation='softmax')(x)
model=keras.Model(inputs=input,outputs=predictions)
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data,labels,batch_size=32,epochs=5)
结果:
Epoch 1/5
32/1000 [..............................] - ETA: 6s - loss: 11.0258 - acc: 0.0938
928/1000 [==========================>...] - ETA: 0s - loss: 11.6636 - acc: 0.1067
1000/1000 [==============================] - 0s 280us/step - loss: 11.6335 - acc: 0.1060
Epoch 2/5
32/1000 [..............................] - ETA: 0s - loss: 11.5678 - acc: 0.1250
864/1000 [========================>.....] - ETA: 0s - loss: 11.5843 - acc: 0.1019
1000/1000 [==============================] - 0s 66us/step - loss: 11.5482 - acc: 0.0980
Epoch 3/5
32/1000 [..............................] - ETA: 0s - loss: 11.3860 - acc: 0.0938
960/1000 [===========================>..] - ETA: 0s - loss: 11.5154 - acc: 0.0865
1000/1000 [==============================] - 0s 60us/step - loss: 11.5292 - acc: 0.0850
Epoch 4/5
32/1000 [..............................] - ETA: 0s - loss: 11.5566 - acc: 0.0938
800/1000 [=======================>......] - ETA: 0s - loss: 11.5084 - acc: 0.0988
1000/1000 [==============================] - 0s 65us/step - loss: 11.5198 - acc: 0.1040
Epoch 5/5
32/1000 [..............................] - ETA: 0s - loss: 11.4288 - acc: 0.0938
928/1000 [==========================>...] - ETA: 0s - loss: 11.5246 - acc: 0.1272
1000/1000 [==============================] - 0s 58us/step - loss: 11.5097 - acc: 0.1260
下面我们将介绍一个较为复杂的模型,这个太简单了,看不出来其特性:搭建一个多输入多输出的模型
下面介绍几点更深一点的东西:
(1)所有的模型都是可调用的,就像层一样。你可以将模型当做一个层一样,通过提供一个tensor来调用它,注意当你调用一个模型的时候,你不仅仅重用了它的结构,也重用了它的权重。
x=keras.layers.Input(shape=(784,))
y=model(x)
(2)这种方法可以快速的让你创建能处理序号信号的模型,你可以很快将一个图像分类的模型变成一个对视频分类的模型:
#这个输入的数据,包含20个时间步是序列,每个序列的是32维度
input_sequences=keras.layers.Input(shape=(20,32))
#我们之前建立的模型运用到每个时间步上,这样我们存在一个序列,包含大小为10的20个向量。
processed_sequences=keras.layers.TimeDistributed(model)(input_sequences)
(3)多输入多输出的模型:
import tensorflow as tf
from tensorflow import keras
import numpy as np
#假设我们的数据是长度为100的单词序列,每个单词由整数代替,数字在1-10000之间。
main_input=keras.layers.Input(shape=(100,),dtype='int32',name='main_input')
#embedding层将输入序列编码成一个序列包含很多512维度的向量。
embedding=keras.layers.Embedding(input_dim=10000,input_length=100,
output_dim=512)(main_input)
#一个长短时记忆网络将向量序列变成一个一个单向量,包含整个序列的信息。
lstm_1=keras.layers.LSTM(32)(embedding)
aux_out=keras.layers.Dense(1,activation='sigmoid',name='aux_out')(lstm_1)
#需要将LSTM和额外的输入串联起来,送入到模型。
aux_input=keras.layers.Input(shape=(5,),name='aux_input')
x=keras.layers.concatenate([lstm_1,aux_input])
x=keras.layers.Dense(64,activation='relu')(x)
x=keras.layers.Dense(64,activation='relu')(x)
x=keras.layers.Dense(64,activation='relu')(x)
main_output=keras.layers.Dense(1,activation='sigmoid',name='main_output')(x)
#最后,模型是一个2输入,2输出的模型:
model=keras.Model(input=[main_input,aux_input],output=[main_output,aux_out])
#编译模型,我们可以使用loss_weights或者loss来为不同的输出设置不同的损失函数或者权值,这
#两个参数都可以为字典或者列表,这里loss设置了单个损失函数,这个损失函数用于所有的输出
model.compile(optimizer='rmsprop',loss='binary_crossentropy',
loss_weights=[1.,0.2])
#这里我们没有定义数据,仅仅用来解释这个模型。
model.fit([headline_data,addtional_data],[labels,labels],epochs=50,batch_size=32)
我们上面给很多层命名了,所以这里我们将使用这些名字来编译和训练模型:
import tensorflow as tf
from tensorflow import keras
import numpy as np
#假设我们的数据是长度为100的单词序列,每个单词由整数代替,数字在1-10000之间。
main_input=keras.layers.Input(shape=(100,),dtype='int32',name='main_input')
#embedding层将输入序列编码成一个序列包含很多512维度的向量。
embedding=keras.layers.Embedding(input_dim=10000,input_length=100,
output_dim=512)(main_input)
#一个长短时记忆网络将向量序列变成一个一个单向量,包含整个序列的信息。
lstm_1=keras.layers.LSTM(32)(embedding)
aux_out=keras.layers.Dense(1,activation='sigmoid',name='aux_out')(lstm_1)
#需要将LSTM和额外的输入串联起来,送入到模型。
aux_input=keras.layers.Input(shape=(5,),name='aux_input')
x=keras.layers.concatenate([lstm_1,aux_input])
x=keras.layers.Dense(64,activation='relu')(x)
x=keras.layers.Dense(64,activation='relu')(x)
x=keras.layers.Dense(64,activation='relu')(x)
main_output=keras.layers.Dense(1,activation='sigmoid',name='main_output')(x)
#最后,模型是一个2输入,2输出的模型:
model=keras.Model(input=[main_input,aux_input],output=[main_output,aux_out])
#编译模型,我们可以使用loss_weights或者loss来为不同的输出设置不同的损失函数或者权值,这
#两个参数都可以为字典或者列表,这里loss设置了单个损失函数,这个损失函数用于所有的输出
model.compile(optimizer='rmsprop',loss={'main_output':'binary_crossentropy','aux_out':'bianry_crossentropy'},
loss_weights={'main_output':1.,'aux_out':0.2})
#这里我们没有定义数据,仅仅用来解释这个模型。
model.fit({'main_input':headline_data,'aux_input':addtional_data},['main_output':labels,'aux_out':labels],epochs=50,batch_size=32)
(4)共享层
我们希望给任意的两个微博,我们可以判断其是否是属于同一个人?这样的模型当然也可以运用到下一对微博中:我们可以使用一个共享的LSTM层来实现现在这个功能。
import tensorflow as tf
from tensorflow import keras
import numpy as np
tweet_a=keras.layers.Input(shape=(140,256))
tweet_b=keras.layers.Input(shape=(140,256))
#若要对不同的输入层共享同一层,就初始化一次,然后多次调用它
#输入一个矩阵,输出一个向量大小为64
shared_lstm=keras.layers.LSTM(64)
#当我们重新使用这一层的实体的时候,参数也被多次使用
encoded_a=shared_lstm(tweet_a)
encoded_b=shared_lstm(tweet_b)
#我们可以连接这两个向量,然后传入逻辑回归层
merged_vector=keras.layers.concatenate([encoded_a,encoded_b],axis=-1)
predictions=keras.layers.Dense(1,activation='sigmoid')(merged_vector)
model=keras.Model(inputs=[tweet_a,tweet_b],outputs=predictions)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit([data_a, data_b], labels, epochs=10)
(5)无论何时,当你在某个输入上调用层时,你就创建了一个新的张量(该层的输出),同时你也在位这个层增加了一个计算节点,这个节点将输入张量映射为输出张量。当你多次调用该层的时候,这个层就存在多个节点,其下标为0,1,2,。。。
layer.output()来获取该层的输出张量。但是如果存在多个输出的话,使用layer.get_output_at(0),同意的layer.input_shape,output_shape.
代码一:
a=keras.layers.Input(shape=(20,784))
lstm=keras.layers.LSTM(32)
encoded_a=lstm(a)
print(lstm.output)
assert lstm.output==encoded_a
代码二:
import tensorflow as tf
from tensorflow import keras
import numpy as np
a=keras.layers.Input(shape=(20,784))
b=keras.layers.Input(shape=(20,784))
lstm=keras.layers.LSTM(32)
encoded_a=lstm(a)
encoded_b=lstm(b)
#报错
# assert lstm.output==encoded_a
# assert lstm.output==encoded_b
assert lstm.get_output_at(0)==encoded_a
assert lstm.get_output_at(1)==encoded_b
代码三:
import tensorflow as tf
from tensorflow import keras
import numpy as np
a = keras.layers.Input(shape=(32, 32, 3))
b = keras.layers.Input(shape=(64, 64, 3))
conv = keras.layers.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)
4.2 定义自己的模型--tf.keras.Model
在__init__里面创建层,将他们当成类实体的属性;
在call里面定义层功能;
import tensorflow as tf
from tensorflow import keras
import numpy as np
(train_data,train_labels),(test_data,test_labels)=keras.datasets.mnist.load_data()
train_data=train_data[:1000].reshape((-1,784))/255.0
train_labels=train_labels[:1000]
class mymodel(keras.Model):
def __init__(self,num_classes=10):
super(mymodel,self).__init__(name='mymodel')
self.num_classes=num_classes
#在这里定义你的层
self.dense_1=keras.layers.Dense(32,activation='relu')
self.dense_2=keras.layers.Dense(num_classes,activation='sigmoid')
def call(self,inputs):
#利用你之前在init里面创建的层来定义前进
x=self.dense_1(inputs)
return self.dense_2(x)
def compute_output_shape(self, input_shape):
# You need to override this function if you want to use the subclassed model
# as part of a functional-style model.
# Otherwise, this method is optional.
shape=tf.TensorShape(input_shape).as_list()
shape[-1]=self.num_classes
return tf.TensorShape(shape)
#实例化你的模型
model=mymodel(num_classes=10)
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(train_data,train_labels,epochs=10,batch_size=32)
4.3 custom层-定义自己的层-tf.keras.layers.Layer
build:创造层的权重,使用add_weight来增加权重
call:定义forward pass,定义层功能,除非你写的层要支持masking,否则你只需要关心call的第一个参数:输入张量
compute_output_shape:指定你根据输入shape怎么计算输出的shape,如果你更改了输入数据的shape,这里你应该指定shape变化的方法,这个函数keras可以自动的判断shape
可选,一个层可以通过get-config和from_config来归类。
下面定义一个普通的层:实现的是输入和一个核矩阵相乘:
class MyLayer(keras.layers.Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
shape = tf.TensorShape((input_shape[1], self.output_dim))
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=shape,
initializer='uniform',
trainable=True)
# Be sure to call this at the end
super(MyLayer, self).build(input_shape)
def call(self, inputs):
return tf.matmul(inputs, self.kernel)
def compute_output_shape(self, input_shape):
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.output_dim
return tf.TensorShape(shape)
def get_config(self):
base_config = super(MyLayer, self).get_config()
base_config['output_dim'] = self.output_dim
@classmethod
def from_config(cls, config):
return cls(**config)
# Create a model using the custom layer
model = keras.Sequential([MyLayer(10),
keras.layers.Activation('softmax')])
# The compile step specifies the training configuration
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# Trains for 5 epochs.
model.fit(data, targets, batch_size=32, epochs=5)
五.回调callbacks---tf.keras.callbacks
回调函数用来在训练的时候扩展行为。
(1):tf.keras.callbacks.ModelCheckpoint:时隔一定时间来保存你的模型的检查点
(2):tf.keras.callbacks.LearningRateScheduler:动态的改变学习率
(3):tf.keras.callbacks.EarlyStopping:提早的打断训练,当你的交叉验证集性能不再提高。
(4):tf.keras.callbacks.TensorBoard:监视模型的性能使用tensorboard
当你定义了callback,只需要将其传递个你的fit就行:
callbacks = [
# Interrupt training if `val_loss` stops improving for over 2 epochs
keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),
# Write TensorBoard logs to `./logs` directory
keras.callbacks.TensorBoard(log_dir='./logs')
]
model.fit(data, labels, batch_size=32, epochs=5, callbacks=callbacks,
validation_data=(val_data, val_targets))
六.保存模型和恢复模型
6.1 仅保存权重--tf.keras.Model.save_weights
# Save weights to a TensorFlow Checkpoint file
model.save_weights('./my_model')
# Restore the model's state,
# this requires a model with the same architecture.
model.load_weights('my_model')
默认存储为检查点的形式,但是也可以存储在HDF5形式。
# Save weights to a HDF5 file
model.save_weights('my_model.h5', save_format='h5')
# Restore the model's state
model.load_weights('my_model.h5')
6.2 仅保存配置
一个存储的配置可以重建和初始化一个同样的模型,甚至不需要之前的定义模型的代码。支持JSON和YAML两张形式::
# Serialize a model to JSON format
json_string = model.to_json()
# Recreate the model (freshly initialized)
fresh_model = keras.models.from_json(json_string)
# Serializes a model to YAML format
yaml_string = model.to_yaml()
# Recreate the model
fresh_model = keras.models.from_yaml(yaml_string)
注意:子类模型不能被这样,因为它的结构实在call方法中创建的。
6.3 保存整个模型
整个模型也可以被存储,包括权重,配置,优化配置等。
# Create a trivial model
model = keras.Sequential([
keras.layers.Dense(10, activation='softmax', input_shape=(32,)),
keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, targets, batch_size=32, epochs=5)
# Save entire model to a HDF5 file
model.save('my_model.h5')
# Recreate the exact same model, including weights and optimizer.
model = keras.models.load_model('my_model.h5')
七 .eager execution
eager execution是一个立即评估操作的必要的编程环境。它不是keras所必须的,但是受keras支持。
八. 分布
8.1 评估器
estimator API用来在分布的环境下训练模型,一个tf.keras.Model可以通过tf.estimator进行训练,通过将其转化成tf.estimator.Estimator实体,调用函数tf.keras.estimator.model_to_estimator.
model = keras.Sequential([layers.Dense(10,activation='softmax'),
layers.Dense(10,activation='softmax')])
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
estimator = keras.estimator.model_to_estimator(model)
8.2 多个GPU
tf.keras的模型可以在多个GPU上运行,通过使用tf.contrib.distribute.DistributionStrategy。这个可以极少的更改我们的代码就可以在多个设备上运行。
当前,tf.contrib.distribute.MirroredStrategy是唯一的一个支持的分布策略。MirroredStrategy对图进行复制,以同步的方式训练,并且梯度最后聚集到一个机器上。为了通过keras使用这个DistributionStrategy,我们必须将tf.keras.Model转化成tf.estimator.Estimator,怎么转呢,当然是通过tf.keras.estimator.model_to_estimator,然后训练这个评估器。
下面的案例展示了分布一个tf.keras.Model在一个机器的很多GPU上
首先定义一个模型:
model = keras.Sequential()
model.add(keras.layers.Dense(16, activation='relu', input_shape=(10,)))
model.add(keras.layers.Dense(1, activation='sigmoid'))
optimizer = tf.train.GradientDescentOptimizer(0.2)
model.compile(loss='binary_crossentropy', optimizer=optimizer)
model.summary()
其次:定义输入,input_fn返回的是tf.data.Dataset实体,用来分布数据在不同的设备上。每个设备处理一点数据。
def input_fn():
x = np.random.random((1024, 10))
y = np.random.randint(2, size=(1024, 1))
x = tf.cast(x, tf.float32)
dataset = tf.data.Dataset.from_tensor_slices((x, y))
dataset = dataset.repeat(10)
dataset = dataset.batch(32)
return dataset
接着:创造一个tf.estimator.RunConfig,然后设置train_distribute参数给tf.contrib.distribute.MirroredStrategy实体。当创造MirroredStrategy,你可以指定一系列的设备,或者设置num_gpus这个参数。tf.estimator.Estimator初始化的时候可以在config中的train_distribute设置相应的分布式策略,
strategy = tf.contrib.distribute.MirroredStrategy()
config = tf.estimator.RunConfig(train_distribute=strategy)
接着:转化model成为tf.stimator.Estimator
keras_estimator = keras.estimator.model_to_estimator(
keras_model=model,
config=config,
model_dir='/tmp/model_dir')
最后:训练这个Estimator,通过提供参数input_fn和steps
keras_estimator.train(input_fn=input_fn, steps=10)
运行的时候需要我指定一个设备,不知道怎么搞?