如何为接受各种形状的多个输入的 `tf.keras` 模型创建 `tf.data.Dataset`?
How can I create a `tf.data.Dataset` for a `tf.keras` model that accepts multiple inputs of various shapes?
我有一个 tf.keras
模型需要接受多个形状的多个输入。我的目标是以这样一种方式构建它,即我可以使用它的 fit
和 evaluate
API.
轻松地训练和评估它
至此,模型构建如下:
class MultipleLSTM(Model):
def __init__(self, lstm_dims=128, name='multi_lstm', **kwargs):
super(MultipleLSTM, self).__init__(name=name)
# initialize encoders for every attribute
self.encoders = []
for key, value in kwargs.items():
self.encoders.append(self._create_encoder(lstm_dims, value))
# initialize the rest of the network layers
self.concat = Concatenate(axis=0)
self.conv_1 = Conv2D(6, 4, activation='relu')
self.flatten = Flatten()
self.dense = Dense(128, activation='relu')
self.out = Dense(1, activation='sigmoid')
def call(self, inputs):
x_1 = self.encoders[0](inputs[0])
x_2 = self.encoders[1](inputs[1])
x_3 = self.encoders[2](inputs[2])
x_4 = self.encoders[3](inputs[3])
x = self.concat([x_1, x_2, x_3, x_4])
# fix the shape for the convolutions
x = tf.expand_dims(x, axis=0)
x = tf.expand_dims(x, axis=3)
x = self.conv_1(x)
x = self.flatten(x)
x = self.dense(x)
x = self.out(x)
return x
def _create_encoder(self, lstm_dims, conf):
with tf.name_scope(conf['name']) as scope:
encoder = tf.keras.Sequential(name=scope)
encoder.add(Embedding(conf['vocab'],
conf['embed_dim'],
input_length=conf['input_length']))
encoder.add(Bidirectional(LSTM(lstm_dims)))
return encoder
有四种不同的输入,不同长度的文本句子,被馈送到四个不同的 Embedding
和 LSTM
层 (encoders
)。然后将这些层的输出连接起来以创建一个转发到后续层的单个张量。
为了训练这个网络,我将一个列表列表作为输入传递给不同的标记化句子。标签只是数字,0 或 1(二进制分类)。例如,输入可以是:
x = [[1, 2, 3, 4],
[2, 3, 5],
[3, 5, 6, 7],
[1, 5, 7]]
y = 0
目前,我已经实现了一个接受此类输入并训练网络的自定义循环:
def train(data, model, loss_fn, optimizer, metric, epochs=10, print_every=50):
for epoch in range(epochs):
print(f'Start of epoch {epoch+1}')
for step, (x_batch, y_batch) in enumerate(data):
with GradientTape() as tape:
output = model(x_batch)
loss = loss_fn(y_batch, output)
grads = tape.gradient(loss, model.trainable_weights)
optimizer.apply_gradients(zip(grads, model.trainable_weights))
metric(loss)
if step % print_every == 0:
print(f'step {step}: mean loss = {metric.result()}')
但这使我无法利用易于使用的 tf.keras API 到 fit
和 evaluate
模型,甚至无法将数据集拆分为训练集和测试集.因此,问题是:如何从这样的 x 和 y 创建一个 tf.data.Dataset
并将其传递给 tf.keras
的 fit
函数?
您可以使用 keras 的功能 api 来做到这一点。这是关于多输入的 keras 文档的 link,如果需要输出:Multi-input and multi-output models
您可以直接将不同的输入作为列表传递,并拟合和评估方法。
model.fit([X_train[:,0], X_train[:,1]], y_train, ...)
我有一个 tf.keras
模型需要接受多个形状的多个输入。我的目标是以这样一种方式构建它,即我可以使用它的 fit
和 evaluate
API.
至此,模型构建如下:
class MultipleLSTM(Model):
def __init__(self, lstm_dims=128, name='multi_lstm', **kwargs):
super(MultipleLSTM, self).__init__(name=name)
# initialize encoders for every attribute
self.encoders = []
for key, value in kwargs.items():
self.encoders.append(self._create_encoder(lstm_dims, value))
# initialize the rest of the network layers
self.concat = Concatenate(axis=0)
self.conv_1 = Conv2D(6, 4, activation='relu')
self.flatten = Flatten()
self.dense = Dense(128, activation='relu')
self.out = Dense(1, activation='sigmoid')
def call(self, inputs):
x_1 = self.encoders[0](inputs[0])
x_2 = self.encoders[1](inputs[1])
x_3 = self.encoders[2](inputs[2])
x_4 = self.encoders[3](inputs[3])
x = self.concat([x_1, x_2, x_3, x_4])
# fix the shape for the convolutions
x = tf.expand_dims(x, axis=0)
x = tf.expand_dims(x, axis=3)
x = self.conv_1(x)
x = self.flatten(x)
x = self.dense(x)
x = self.out(x)
return x
def _create_encoder(self, lstm_dims, conf):
with tf.name_scope(conf['name']) as scope:
encoder = tf.keras.Sequential(name=scope)
encoder.add(Embedding(conf['vocab'],
conf['embed_dim'],
input_length=conf['input_length']))
encoder.add(Bidirectional(LSTM(lstm_dims)))
return encoder
有四种不同的输入,不同长度的文本句子,被馈送到四个不同的 Embedding
和 LSTM
层 (encoders
)。然后将这些层的输出连接起来以创建一个转发到后续层的单个张量。
为了训练这个网络,我将一个列表列表作为输入传递给不同的标记化句子。标签只是数字,0 或 1(二进制分类)。例如,输入可以是:
x = [[1, 2, 3, 4],
[2, 3, 5],
[3, 5, 6, 7],
[1, 5, 7]]
y = 0
目前,我已经实现了一个接受此类输入并训练网络的自定义循环:
def train(data, model, loss_fn, optimizer, metric, epochs=10, print_every=50):
for epoch in range(epochs):
print(f'Start of epoch {epoch+1}')
for step, (x_batch, y_batch) in enumerate(data):
with GradientTape() as tape:
output = model(x_batch)
loss = loss_fn(y_batch, output)
grads = tape.gradient(loss, model.trainable_weights)
optimizer.apply_gradients(zip(grads, model.trainable_weights))
metric(loss)
if step % print_every == 0:
print(f'step {step}: mean loss = {metric.result()}')
但这使我无法利用易于使用的 tf.keras API 到 fit
和 evaluate
模型,甚至无法将数据集拆分为训练集和测试集.因此,问题是:如何从这样的 x 和 y 创建一个 tf.data.Dataset
并将其传递给 tf.keras
的 fit
函数?
您可以使用 keras 的功能 api 来做到这一点。这是关于多输入的 keras 文档的 link,如果需要输出:Multi-input and multi-output models
您可以直接将不同的输入作为列表传递,并拟合和评估方法。
model.fit([X_train[:,0], X_train[:,1]], y_train, ...)