tensorflow2.0 Keras自定义层与网络
使用keras通常的写法都是先调Sequential类(仅用于层的线性堆叠),如:
nn = Sequential([layers.Dense(128,activation='relu),
layers.Dense(64,activation='relu),
layers.Dense(10)])
有时用已有的layer并不能满足我们的需要,比如在层中加入:
x = x-1
这时就不得不加载自定义的Layer或Model,以适应各种需求,自定义层继承于keras.layers.Layer,自定义网络继承于keras.Model.
自定义层或者网络时需定义 init 方法以及 call 方法:
class MyDenseLayer(layers.Layer):
def __init__(self, input_dim, output_dim):
super(MyDenseLayer, self).__init__()
# add_variable已定义在父类中,用于添加trainable的变量
self.kernel = self.add_variable('weight', [input_dim, output_dim])
self.bias = self.add_variable('bias', [output_dim])
#这里使用inputs作为输入参数,training用于控制训练或测试
def call(self, inputs, training=None):
out = inputs @ self.kernel + self.bias
return out
类似地,通过继承Model自定义网络实现fashion_mnist数据集的训练。继承Model父类后,仍然可以很方便地调用keras提供的compile、fit、predict等方法。
import tensorflow as tf
from tensorflow import keras
import datetime
# 自定义网络
class MyModel(keras.Model):
def __init__(self):
super(MyModel, self).__init__()
self.layer1 = keras.layers.Dense(128, activation=tf.nn.relu)
self.layer2 = keras.layers.Dense(64, activation=tf.nn.relu)
self.layer3 = keras.layers.Dense(10)
def call(self, inputs, training=False):
inputs = tf.reshape(inputs, [-1, 28*28])
inputs = self.layer1(inputs)
inputs = self.layer2(inputs)
inputs = self.layer3(inputs)
return inputs
# 转换数据为tensor类型
def preprocessing(x,y):
x = tf.cast(x, tf.float32) / 255
y = tf.cast(y, tf.float32)
return x,y
# 加载数据
(train_images,train_labels),(test_images,test_labels) = keras.datasets.fashion_mnist.load_data()
# 预处理数据并定义iterator
train_labels = tf.one_hot(tf.convert_to_tensor(train_labels),depth=10)
test_labels = tf.one_hot(tf.convert_to_tensor(test_labels),depth=10)
train_iterator = tf.data.Dataset.from_tensor_slices((train_images,train_labels))
test_iterator = tf.data.Dataset.from_tensor_slices((test_images,test_labels))
train_iterator = train_iterator.map(preprocessing).shuffle(train_images.shape[0]).batch(100)
test_iterator = test_iterator.map(preprocessing).shuffle(test_images.shape[0]).batch(100)
sample_x,sample_y = next(iter(train_iterator))
print(sample_x.shape, sample_y.shape)
model = MyModel()
model.compile(optimizer=keras.optimizers.Adam(1e-2),
loss=tf.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(train_iterator.repeat(), epochs=10, steps_per_epoch=500, verbose=1,
validation_data=test_iterator.repeat(),
validation_steps=2)