原始 Python 'for' 循环是否会降低 TensorFlow 的训练性能
Does the raw Python 'for' loop reduce training performance of TensorFlow
只有 1 个输入(输入占位符)时,使用 tf.data.Dataset 是最佳选择:
Data = tf.data.Dataset.from_tensor_slices((Inp,Exp));
Data = Data.repeat().shuffle(Dsize).batch(Bsize);
Steps = 1000;
Epochs = round(Steps/(Dsize/Bsize));
...
Model.fit(Data, epochs=Epochs, steps_per_epoch=round(Dsize/Bsize));
但是,当有多个输入(提供给多个占位符)时,Keras 不允许提供多个数据集,因此使用原始 Python 'for' 循环来提供批次:
Data = tf.data.Dataset.from_tensor_slices((Inp1,Inp2,Exp));
Data = Data.repeat().shuffle(Dsize).batch(Bsize);
Iter = iter(Data);
Steps = 1000;
...
for I in range(Steps):
X1,X2,Y = next(Iter);
Model.fit(x=[X1,X2], y=Y);
因为Python是解释器并且在字节码上运行,所以'for'循环应该很慢。恐怕使用自定义 'for' 循环会降低训练性能。是真的吗?
我发现没有必要使用 'for' 循环。我可以通过仅使用 Keras 来避免使用 'for' 循环,同时我仍然可以使用多个 Xes,但不再使用 tf.data.Dataset:
Steps = 1000;
Epochs = round(Steps/(Dsize/Bsize));
Lline = 10;
Lafte = round(Epochs/Lline);
if Lafte==0: Lafte=1;
#Train: Loop
L = Model.evaluate(x=[Inp1,Inp2], y=Exp, steps=round(Dsize/Bsize), batch_size=Bsize,
verbose=0);
print(f"Initavg batch loss: {L:.9f}");
Model.fit(x=[Inp1,Inp2], y=Exp, epochs=Epochs, batch_size=Bsize, shuffle=True,
verbose=0, callbacks=[callback()]);
您可以调整 from_tensor_slices 使其保持为 2 个元素的元组,而第一个元素本身就是一个元组。
工作示例:
import numpy as np
import tensorflow as tf
input_1 = tf.keras.Input(shape=(10,))
dense_1 = tf.keras.layers.Dense(4)(input_1)
input_2 = tf.keras.Input(shape=(10,))
dense_2 = tf.keras.layers.Dense(4)(input_2)
x = tf.keras.layers.Concatenate()([dense_1, dense_2])
y = tf.keras.layers.Dense(2)(x)
model = tf.keras.Model([input_1, input_2], y)
model.summary()
dataset_size = 16
batch_size = 4
input_1_values = np.random.random((dataset_size, 10))
input_2_values = np.random.random((dataset_size, 10))
output_values = np.random.random((dataset_size, 2))
dataset = tf.data.Dataset.from_tensor_slices(((input_1_values, input_1_values), output_values))
dataset = dataset.repeat().shuffle(buffer_size=4).batch(batch_size)
steps = 10
model.compile(optimizer="adam", loss="binary_crossentropy")
model.fit(dataset, epochs=1, steps_per_epoch=steps)
另一种将数据集合并为单个数据集的方法也可以是使用 zip method
只有 1 个输入(输入占位符)时,使用 tf.data.Dataset 是最佳选择:
Data = tf.data.Dataset.from_tensor_slices((Inp,Exp));
Data = Data.repeat().shuffle(Dsize).batch(Bsize);
Steps = 1000;
Epochs = round(Steps/(Dsize/Bsize));
...
Model.fit(Data, epochs=Epochs, steps_per_epoch=round(Dsize/Bsize));
但是,当有多个输入(提供给多个占位符)时,Keras 不允许提供多个数据集,因此使用原始 Python 'for' 循环来提供批次:
Data = tf.data.Dataset.from_tensor_slices((Inp1,Inp2,Exp));
Data = Data.repeat().shuffle(Dsize).batch(Bsize);
Iter = iter(Data);
Steps = 1000;
...
for I in range(Steps):
X1,X2,Y = next(Iter);
Model.fit(x=[X1,X2], y=Y);
因为Python是解释器并且在字节码上运行,所以'for'循环应该很慢。恐怕使用自定义 'for' 循环会降低训练性能。是真的吗?
我发现没有必要使用 'for' 循环。我可以通过仅使用 Keras 来避免使用 'for' 循环,同时我仍然可以使用多个 Xes,但不再使用 tf.data.Dataset:
Steps = 1000;
Epochs = round(Steps/(Dsize/Bsize));
Lline = 10;
Lafte = round(Epochs/Lline);
if Lafte==0: Lafte=1;
#Train: Loop
L = Model.evaluate(x=[Inp1,Inp2], y=Exp, steps=round(Dsize/Bsize), batch_size=Bsize,
verbose=0);
print(f"Initavg batch loss: {L:.9f}");
Model.fit(x=[Inp1,Inp2], y=Exp, epochs=Epochs, batch_size=Bsize, shuffle=True,
verbose=0, callbacks=[callback()]);
您可以调整 from_tensor_slices 使其保持为 2 个元素的元组,而第一个元素本身就是一个元组。
工作示例:
import numpy as np
import tensorflow as tf
input_1 = tf.keras.Input(shape=(10,))
dense_1 = tf.keras.layers.Dense(4)(input_1)
input_2 = tf.keras.Input(shape=(10,))
dense_2 = tf.keras.layers.Dense(4)(input_2)
x = tf.keras.layers.Concatenate()([dense_1, dense_2])
y = tf.keras.layers.Dense(2)(x)
model = tf.keras.Model([input_1, input_2], y)
model.summary()
dataset_size = 16
batch_size = 4
input_1_values = np.random.random((dataset_size, 10))
input_2_values = np.random.random((dataset_size, 10))
output_values = np.random.random((dataset_size, 2))
dataset = tf.data.Dataset.from_tensor_slices(((input_1_values, input_1_values), output_values))
dataset = dataset.repeat().shuffle(buffer_size=4).batch(batch_size)
steps = 10
model.compile(optimizer="adam", loss="binary_crossentropy")
model.fit(dataset, epochs=1, steps_per_epoch=steps)
另一种将数据集合并为单个数据集的方法也可以是使用 zip method