我以前是tensorflow1.x的用户,当时tensorflow还没合并keras,很多接口比较原始,还有session和napescope等概念。最近接触了下tf2.9, 发现写法都变了,作为一个tf2.x的初学者,记录下自己刚开始的一些心得。
我看到tf2.9的接口已经很接近pytorch了,但是还是没有pytorch好用。我看到教程里搭建模型主要就是实例化一个tf.keras.Model并对它进行各种设置,实例化一个tf.keras.Model对象竟然同时存在多种方式,这也不是“灵活”能解释的通的,感觉还是没有实现一种好用的方式达到“一招鲜”,多种方式并存的原因可能还是设计不够简单。
tf.keras.models.Sequential继承自tf.keras.Model,所以实例化一个Sequential对象也可以。Sequential主要用于结构简单的层级网络,无法构建结构复杂的网络,这点从名字里也可看出来。
接口定义:
tf.keras.Sequential(
layers=None, name=None
)
初始化的时候可以传图两个参数,第一个是网络层的列表,第二个是名字。
同时tf.keras.models.Sequential也是它的别名。
教程里的例子:
import tensorflow as tf
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])
这里传入了多个layers对象,组成了这个模型。这是比较简单的一种方式。
构造时不传参,构造后可以使用add接口一层层往上加
model = tf.keras.Sequential()
model.add(tf.keras.Input(shape=(16,)))
model.add(tf.keras.layers.Dense(8))
model.add(tf.keras.layers.Dense(4))
这里构造了一个两层全连接的网络。
Sequential只能搭建简单的网络,如果内部有复杂的结构,就需要直接使用tf.keras.Model构造。
这也是最像pytorch的方式。主要就是实现call()函数,其原型:
call(
inputs, training=None, mask=None
)
教程里的例子:
class MyModel(tf.keras.Model):
def __init__(self):
super(MyModel, self).__init__()
self.conv1 = Conv2D(32, 3, activation='relu')
self.flatten = Flatten()
self.d1 = Dense(128, activation='relu')
self.d2 = Dense(10, activation='softmax')
def call(self, x):
x = self.conv1(x)
x = self.flatten(x)
x = self.d1(x)
return self.d2(x)
model = MyModel()
如果是多输入输出的话,输入用[inoput1, input2]这样的方式来传入就可以,输出用[out1,out2]的方式来返回。
最简单的方式构造一个单输入输出的网络:
inputs = tf.keras.layers.Input(shape=(3,))
outputs = tf.keras.layers.Dense(2)(inputs)
model = tf.keras.models.Model(inputs=inputs, outputs=outputs)
也可构建多输入输出的网络。这里是一个两个输出的例子:
inputs = tf.keras.layers.Input(shape=(3,))
d = tf.keras.layers.Dense(2, name='out')
output_1 = d(inputs)
output_2 = d(inputs)
model = tf.keras.models.Model(
inputs=inputs, outputs=[output_1, output_2])