这个问题的目的是寻求一个最低限度的指南来使某人快速使用TensorFlow 1和TensorFlow2。我觉得没有一个连贯的指南可以解释TF1和TF2之间的差异,而TF已经通过主要修订和快速发展。
供我引用时,
我的问题是
最佳答案
TF1/TF2如何工作?和他们之间的差异
TF1
TF1遵循一种称为define-then-run的执行方式。这与“运行定义”相反,例如,“Python定义”执行样式。但是,这是什么意思?定义然后运行意味着,仅因为您调用/定义了某项而未执行。您必须明确执行定义的内容。
TF具有图的概念。首先,定义所需的所有计算(例如,神经网络的所有层计算,损失计算以及使损失最小化的优化器-这些表示为操作或操作)。定义计算/数据流图之后,您可以使用Session执行这些操作。让我们来看一个简单的例子。
# Graph generation
tf_a = tf.placeholder(dtype=tf.float32)
tf_b = tf.placeholder(dtype=tf.float32)
tf_c = tf.add(tf_a, tf.math.multiply(tf_b, 2.0))
# Execution
with tf.Session() as sess:
c = sess.run(tf_c, feed_dict={tf_a: 5.0, tf_b: 2.0})
print(c)
计算图(也称为数据流图)如下所示。
tf_a tf_b tf.constant(2.0)
\ \ /
\ tf.math.multiply
\ /
tf.add
|
tf_c
类比:考虑您做蛋糕。您可以从互联网上下载配方。然后,您开始执行实际制作蛋糕的步骤。配方就是图表,制作蛋糕的过程就是 session 执行的操作(即图表的执行)。
TF2
TF2遵循立即执行样式或按运行定义。您调用/定义一些东西,它就被执行了。让我们来看一个例子。
a = tf.constant(5.0)
b = tf.constant(3.0)
c = tf_a + (tf_b * 2.0)
print(c.numpy())
哇!与TF1示例相比,它看起来如此干净。一切看起来都像Python一样。
类比:现在认为您正在动手做蛋糕工作坊。您正在按照老师的说明做蛋糕。然后讲师立即解释每个步骤的结果。因此,与前面的示例不同,您不必等到烤蛋糕就看是否做对了(这是无法调试代码的事实的引用)。但是您会得到有关您的表现的即时反馈(您知道这意味着什么)。
这是否意味着TF2无法建立图表?惊恐发作
是的,不是。关于eager execution和AutoGraph函数,您应该了解TF2中的两个功能。
急于执行
急切的执行可以立即执行
Tensor
和Operation
。这是您在TF2示例中观察到的。但不利的一面是,它没有建立图表。因此,例如,您使用急切的执行来实现和运行神经网络,它将非常慢(因为神经网络一遍又一遍地执行非常重复的任务(正向计算-损失计算-向后传递)。签名
这就是自动图形功能的急救之处。 AutoGraph是TF2中我最喜欢的功能之一。这样做的作用是,如果您在函数中执行“TensorFlow”操作,它将分析该函数并为您构建图形(烦死了)。因此,例如,您执行以下操作。 TensorFlow构建图。
@tf.function
def do_silly_computation(x, y):
a = tf.constant(x)
b = tf.constant(y)
c = tf_a + (tf_b * 2.0)
return c
print(do_silly_computation(5.0, 3.0).numpy())
因此,您所需要做的就是定义一个函数,该函数接受必要的输入并返回正确的输出。最重要的是添加
@tf.function
装饰器,因为这是TensorFlow AutoGraph分析给定功能的触发器。TF1和TF2之间的区别
tf.Session()
对象来执行图形,而TF2不需要TF1和TF2中有哪些不同的数据类型?
您已经看过许多主要的数据类型。但是您可能对它们的功能以及行为方式有疑问。好了,本节就是关于这一点的。
TF1数据类型/数据结构
tf.placeholder
:这是您向计算图提供输入的方式。顾名思义,它没有附加值。而是在运行时输入值。 tf_a
和tf_b
是这些示例。将此视为一个空盒子。您可以根据需要将水/沙/蓬松的泰迪熊装满。 tf.Variable
:这是您用来定义神经网络参数的方法。与占位符不同,变量使用一些值初始化。但是它们的值(value)也可以随着时间而改变。这就是在反向传播过程中神经网络的参数发生的情况。 tf.Operation
:操作是可以在占位符,张量和变量上执行的各种转换。例如tf.add()
和tf.mul()
是操作。这些操作(大多数情况下)返回张量。如果您想证明操作不返回张量,请检查this。 tf.Tensor
:就其具有初始值而言,它类似于变量。但是,一旦定义它们,它们的值就无法更改(即它们是不可变的)。例如,上一个示例中的tf_c
是tf.Tensor
。 TF2数据类型/数据结构
tf.Variable
tf.Tensor
tf.Operation
就行为而言,从TF1到TF2的数据类型没有太大变化。唯一的主要区别是,
tf.placeholders
不见了。您也可以看看full list of data types。什么是Keras,它如何适合所有这些?
Keras曾经是一个单独的库,提供主要用于深度学习模型的组件(例如层和模型)的高级实现。但是从TensorFlow的更高版本开始,Keras已集成到TensorFlow中。
因此,正如我所解释的,如果要使用裸骨TensorFlow,Keras隐藏了许多不必要的复杂处理。 Keras为实现NN提供了主要的两件事
Layer
对象和Model
对象。 Keras还具有两个最常见的模型API,可用于开发模型:顺序API和功能API。在一个简单的示例中,让我们看看Keras和TensorFlow有何不同。让我们构建一个简单的CNN。height=64
width = 64
n_channels = 3
n_outputs = 10
Keras(顺序API)示例
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(2,2),
activation='relu',input_shape=(height, width, n_channels)))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(filters=64, kernel_size=(2,2), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(n_outputs, activation='softmax'))
model.compile(loss='binary_crossentropy', optimizer='adam')
model.summary()
优点
缺点
Keras(功能性API)示例
inp = Input(shape=(height, width, n_channels))
out = Conv2D(filters=32, kernel_size=(2,2), activation='relu',input_shape=(height, width, n_channels))(inp)
out = MaxPooling2D(pool_size=(2,2))(out)
out = Conv2D(filters=64, kernel_size=(2,2), activation='relu')(out)
out = MaxPooling2D(pool_size=(2,2))(out)
out = Flatten()(out)
out = Dense(n_outputs, activation='softmax')(out)
model = Model(inputs=inp, outputs=out)
model.compile(loss='binary_crossentropy', optimizer='adam')
model.summary()
优点
缺点
TF1示例
# Input
tf_in = tf.placeholder(shape=[None, height, width, n_channels], dtype=tf.float32)
# 1st conv and max pool
conv1 = tf.Variable(tf.initializers.glorot_uniform()([2,2,3,32]))
tf_out = tf.nn.conv2d(tf_in, filters=conv1, strides=[1,1,1,1], padding='SAME') # 64,64
tf_out = tf.nn.max_pool2d(tf_out, ksize=[2,2], strides=[1,2,2,1], padding='SAME') # 32,32
# 2nd conv and max pool
conv2 = tf.Variable(tf.initializers.glorot_uniform()([2,2,32,64]))
tf_out = tf.nn.conv2d(tf_out, filters=conv2, strides=[1,1,1,1], padding='SAME') # 32, 32
tf_out = tf.nn.max_pool2d(tf_out, ksize=[2,2], strides=[1,2,2,1], padding='SAME') # 16, 16
tf_out = tf.reshape(tf_out, [-1, 16*16*64])
# Dense layer
dense = conv1 = tf.Variable(tf.initializers.glorot_uniform()([16*16*64, n_outputs]))
tf_out = tf.matmul(tf_out, dense)
优点
缺点
注意事项和陷阱
在这里,我将列出使用TF时需要注意的几件事(根据我的经验)。
TF1-忘记提供所有相关的占位符以计算结果
tf_a = tf.placeholder(dtype=tf.float32)
tf_b = tf.placeholder(dtype=tf.float32)
tf_c = tf.add(tf_a, tf.math.multiply(tf_b, 2.0))
with tf.Session() as sess:
c = sess.run(tf_c, feed_dict={tf_a: 5.0})
print(c)
出现错误的原因是,您尚未向
tf_b
输入值。因此,请确保将所有依赖项占位符的值都提供给,以计算结果。TF1-务必非常小心数据类型
tf_a = tf.placeholder(dtype=tf.int32)
tf_b = tf.placeholder(dtype=tf.float32)
tf_c = tf.add(tf_a, tf.math.multiply(tf_b, 2.0))
with tf.Session() as sess:
c = sess.run(tf_c, feed_dict={tf_a: 5, tf_b: 2.0})
print(c)
您能发现错误吗?这是因为在将数据类型传递给操作时必须匹配数据类型。否则,请使用
tf.cast()
操作将您的数据类型转换为兼容的数据类型。Keras-了解每一层期望的输入形状
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(2,2),
activation='relu',input_shape=(height, width)))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(filters=64, kernel_size=(2,2), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(n_outputs, activation='softmax'))
model.compile(loss='binary_crossentropy', optimizer='adam')
在此,您已定义了输入形状
[None, height, width]
(添加批次尺寸时)。但是Conv2D
需要4D输入[None, height, width, n_channels]
。因此,您会收到上述错误。一些通常被误解/容易出错的层是,Conv2D
层-需要4D输入[None, height, width, n_channels]
。要更详细地了解卷积层/操作,请查看此answer LSTM
层-需要3D输入[None, timesteps, n_dim]
ConvLSTM2D
层-需要5D输入[None, timesteps, height, width, n_channels]
Concatenate
层-除轴外,在所有其他维度上串联的数据必须是相同的Keras-在
fit()
期间输入错误的输入/输出形状height=64
width = 64
n_channels = 3
n_outputs = 10
Xtrain = np.random.normal(size=(500, height, width, 1))
Ytrain = np.random.choice([0,1], size=(500, n_outputs))
# Build the model
# fit network
model.fit(Xtrain, Ytrain, epochs=10, batch_size=32, verbose=0)
你应该知道这一点。当我们应该输入
[batch size, height, width, 1]
输入时,我们正在输入[batch size, height, width, 3]
形状的输入。TF1和TF2之间的性能差异
这已经在here讨论中了。因此,我不会重复其中的内容。
我希望我能谈论但不能的事情
我将留下一些链接以供进一步阅读。
tf.data.Dataset
tf.RaggedTensor
关于python - TensorFlow和Keras上的引物: The past (TF1) the present (TF2),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59112527/