python 如何连接编码器和解码器

h7appiyu  于 2022-12-25  发布在  Python
关注(0)|答案(4)|浏览(197)

我构建了以下编码器-解码器架构,编码器和解码器分别工作良好:

from tensorflow.keras.layers import LSTM, Input, Reshape, Lambda
from tensorflow.keras.models import Model
from tensorflow.keras import backend as K

WORD_TO_INDEX = {"foo": 0, "bar": 1}

MAX_QUERY_WORD_COUNT = 10
QUERY_ENCODING_SIZE = 15

# ENCODER
query_encoder_input = Input(shape=(None, len(WORD_TO_INDEX)), name="query_encoder_input")
query_encoder_output = LSTM(QUERY_ENCODING_SIZE, name="query_encoder_lstm")(query_encoder_input)
query_encoder = Model(inputs=query_encoder_input, outputs=query_encoder_output)

# DECODER
query_decoder_input = Input(shape=(QUERY_ENCODING_SIZE,), name="query_decoder_input")
query_decoder_reshape = Reshape((1, QUERY_ENCODING_SIZE), name="query_decoder_reshape")(query_decoder_input)
query_decoder_lstm = LSTM(QUERY_ENCODING_SIZE, name="query_decoder_lstm", return_sequences=True, return_state=True)
recurrent_input, state_h, state_c = query_decoder_lstm(query_decoder_reshape)
states = [state_h, state_c]
query_decoder_outputs = []
for _ in range(MAX_QUERY_WORD_COUNT):
    recurrent_input, state_h, state_c = query_decoder_lstm(recurrent_input, initial_state=states)
    query_decoder_outputs.append(recurrent_input)
    states = [state_h, state_c]
query_decoder_output = Lambda(lambda x: K.concatenate(x, axis=1), name="query_decoder_concat")(query_decoder_outputs)
query_decoder = Model(inputs=query_decoder_input, outputs=query_decoder_output)

但是当我试图将它们结合在一起创建一个自动编码器时,我得到了一个奇怪的错误,我不知道为什么。

# AUTOENCODER
# apply the reshape layer to the output of the encoder
query_autoencoder_output = query_decoder.layers[1](query_encoder_output)
# rebuild the autoencoder by applying each layer of the decoder to the output of the encoder
for decoder_layer in query_decoder.layers[2:]:
    # this fails and I don't know why
    query_autoencoder_output = decoder_layer(query_autoencoder_output)
# the code never gets here
query_autoencoder = Model(inputs=query_encoder_input, outputs=query_autoencoder_output)

这将抛出错误:
值错误:形状必须为等级3,但对于具有输入形状的"{{节点查询解码器连接/连接_1}} =连接V2 [N = 3,T = DT_FLOAT,Tidx = DT_INT32](查询解码器lstm/分区调用_11:1,查询解码器lstm/分区调用_11:2,查询解码器lstm/分区调用_11:3,查询解码器连接/连接_1/轴)",形状的等级为2:[?、1、15]、[?、15]、[?、15]、[]。
This是我用于解码器的模板(参见"如果我不想使用教师强制训练怎么办?"部分)。
我依靠theseStackOverflowquestions(尤其是最后一个)来弄清楚如何将模型组合在一起。

    • 此错误是什么意思?如何修复?**
nafvub8i

nafvub8i1#

你可以把一个模型当作一个层来处理。使用自动编码器,它就像这样简单:

autoencoder = Sequential([encoder, decoder])
pw136qt2

pw136qt22#

如果你想要一些额外的灵活性,你可以子类化tf.keras.Model

class AutoEncoder(tf.keras.Model):
    def __init__(self, encoder, decoder):
        super(AutoEncoder, self).__init__()
        self.encoder = encoder
        self.decoder = decoder

    def call(self, inputs, training=None, **kwargs):
        x = self.encoder(inputs)
        x = self.decoder(x)
        return x

ae = AutoEncoder(encoder, decoder)

ae.fit(...

完整可重现示例:

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from tensorflow import keras
import tensorflow as tf
physical_devices = tf.config.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)
import numpy as np

(xtrain, ytrain), (xtest, ytest) = keras.datasets.cifar10.load_data()

train_ix = np.where(ytrain.ravel() == 1)
test_ix = np.where(ytest.ravel() == 1)

cars_train = xtrain[train_ix]
cars_test = xtest[test_ix]

cars = np.vstack([cars_train, cars_test]).astype(np.float32)/255

X = tf.data.Dataset.from_tensor_slices(cars).batch(8)

class Encoder(keras.Model):
    def __init__(self):
        super(Encoder, self).__init__()
        self.flat = keras.layers.Flatten(input_shape=(32, 32, 3))
        self.dense1 = keras.layers.Dense(128)
        self.dense2 = keras.layers.Dense(32)

    def call(self, inputs, training=None, **kwargs):
        x = self.flat(inputs)
        x = keras.activations.selu(self.dense1(x))
        x = keras.activations.selu(self.dense2(x))
        return x

class Decoder(keras.Model):
    def __init__(self):
        super(Decoder, self).__init__()
        self.dense1 = keras.layers.Dense(128, input_shape=[32])
        self.dense2 = keras.layers.Dense(32 * 32 * 3)
        self.reshape = keras.layers.Reshape([32, 32, 3])

    def call(self, inputs, training=None, **kwargs):
        x = keras.activations.selu(self.dense1(inputs))
        x = keras.activations.sigmoid(self.dense2(x))
        x = self.reshape(x)
        return x

class AutoEncoder(keras.Model):
    def __init__(self, encoder, decoder):
        super(AutoEncoder, self).__init__()
        self.encoder = encoder
        self.decoder = decoder

    def call(self, inputs, training=None, **kwargs):
        x = self.encoder(inputs)
        x = self.decoder(x)
        return x

ae = AutoEncoder(Encoder(), Decoder())

loss_object = keras.losses.BinaryCrossentropy()

reconstruction_loss = keras.metrics.Mean(name='reconstruction_loss')

optimizer = keras.optimizers.Adam()

@tf.function
def reconstruct(inputs):
    with tf.GradientTape() as tape:
        out = ae(inputs)
        loss = loss_object(inputs, out)

    gradients = tape.gradient(loss, ae.trainable_variables)
    optimizer.apply_gradients(zip(gradients, ae.trainable_variables))

    reconstruction_loss(loss)

if __name__ == '__main__':
    template = 'Epoch {:2} Reconstruction Loss {:.4f}'
    for epoch in range(50):
        reconstruction_loss.reset_states()
        for input_batches in X:
            reconstruct(input_batches)
        print(template.format(epoch + 1, reconstruction_loss.result()))

输出:

Epoch 35 Reconstruction Loss 0.5794
Epoch 36 Reconstruction Loss 0.5793
Epoch 37 Reconstruction Loss 0.5792
Epoch 38 Reconstruction Loss 0.5791
Epoch 39 Reconstruction Loss 0.5790
Epoch 40 Reconstruction Loss 0.5789
nimxete2

nimxete23#

基于M Z's answer,但不使用Sequential,您可以执行以下操作:

query_autoencoder = Model(inputs=query_encoder_input, outputs=query_decoder(query_encoder_output))
query_autoencoder.summary()

这个总结也比MZ的回答分为更多的层次。

2o7dmzc5

2o7dmzc54#

对于任何使用Javascript和Tensorflow JS的人来说,这里有一个如何建立更深层次网络的例子。
我想我会包括这一点,因为大多数自动编码器的Javascript示例只显示一个编码和解码层。

function buildModel (layers)
{
    const model = tf.sequential();
    layers.forEach(layer =>
    {
        model.add(layer);
    });
    return model;
}

然后,您可以通过以下方式创建具有更多编码和解码层的更深网络:

//               [ encoder ]   [ decoder ]
// Model layers: 20 -> 10 -> 2 -> 10 -> 20

// Encoding Layers
const encoder = [
    tf.layers.dense({ inputShape: [20], units: 10, activation: 'relu' }),
    tf.layers.dense({ units: 2, activation: 'relu' })
];

// Decoding Layers
const decoder = [
    tf.layers.dense({ units: 10, activation: 'relu' }),
    tf.layers.dense({ units: 20, activation: 'relu' })
];

// Build model
const model = buildModel([...encoder, ...decoder]);

// ... Then compile and Train ...

在训练之后,可以通过以下方式进行预测:

const predictionModel = buildModel([...encoder]);
predictionModel.predict(data);

相关问题