Tensorflow high level API-keras

一.引入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正则化,默认是无正则化的。

扫描二维码关注公众号,回复: 2438601 查看本文章

代码:这里直接将官网的代码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)

运行的时候需要我指定一个设备,不知道怎么搞?

猜你喜欢

转载自blog.csdn.net/m0_37393514/article/details/81169170