AttributeError:该层从未被调用,因此没有定义的输入形状

2024-04-27

我尝试通过创建三个类在 TensorFlow 2.0 中构建自动编码器:Encoder、Decoder 和 AutoEncoder。 由于我不想手动设置输入形状,因此我尝试从编码器的 input_shape 推断解码器的输出形状。

import os
import shutil

import numpy as np
import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense, Layer


def mse(model, original):
    return tf.reduce_mean(tf.square(tf.subtract(model(original), original)))


def train_autoencoder(loss, model, opt, original):
    with tf.GradientTape() as tape:
        gradients = tape.gradient(
            loss(model, original), model.trainable_variables)
        gradient_variables = zip(gradients, model.trainable_variables)
        opt.apply_gradients(gradient_variables)


def log_results(model, X, max_outputs, epoch, prefix):
    loss_values = mse(model, X)

    sample_img = X[sample(range(X.shape[0]), max_outputs), :]
    original = tf.reshape(sample_img, (max_outputs, 28, 28, 1))
    encoded = tf.reshape(
        model.encode(sample_img), (sample_img.shape[0], 8, 8, 1))
    decoded = tf.reshape(
        model(tf.constant(sample_img)), (sample_img.shape[0], 28, 28, 1))
    tf.summary.scalar("{}_loss".format(prefix), loss_values, step=epoch + 1)
    tf.summary.image(
        "{}_original".format(prefix),
        original,
        max_outputs=max_outputs,
        step=epoch + 1)
    tf.summary.image(
        "{}_encoded".format(prefix),
        encoded,
        max_outputs=max_outputs,
        step=epoch + 1)
    tf.summary.image(
        "{}_decoded".format(prefix),
        decoded,
        max_outputs=max_outputs,
        step=epoch + 1)

    return loss_values


def preprocess_mnist(batch_size):
    (X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()

    X_train = X_train / np.max(X_train)
    X_train = X_train.reshape(X_train.shape[0],
                              X_train.shape[1] * X_train.shape[2]).astype(
                                  np.float32)
    train_dataset = tf.data.Dataset.from_tensor_slices(X_train).batch(
        batch_size)

    y_train = y_train.astype(np.int32)
    train_labels = tf.data.Dataset.from_tensor_slices(y_train).batch(
        batch_size)

    X_test = X_test / np.max(X_test)
    X_test = X_test.reshape(
        X_test.shape[0], X_test.shape[1] * X_test.shape[2]).astype(np.float32)

    y_test = y_test.astype(np.int32)

    return X_train, X_test, train_dataset, y_train, y_test, train_labels


class Encoder(Layer):
    def __init__(self, units):
        super(Encoder, self).__init__()
        self.units = units

    def build(self, input_shape):
        self.output_layer = Dense(units=self.units, activation=tf.nn.relu)

    @tf.function
    def call(self, X):
        return self.output_layer(X)


class Decoder(Layer):
    def __init__(self, encoder):
        super(Decoder, self).__init__()
        self.encoder = encoder

    def build(self, input_shape):
        self.output_layer = Dense(units=self.encoder.input_shape)

    @tf.function
    def call(self, X):
        return self.output_layer(X)


class AutoEncoder(Model):
    def __init__(self, units):
        super(AutoEncoder, self).__init__()
        self.units = units

    def build(self, input_shape):
        self.encoder = Encoder(units=self.units)
        self.encoder.build(input_shape)
        self.decoder = Decoder(encoder=self.encoder)

    @tf.function
    def call(self, X):
        Z = self.encoder(X)
        return self.decoder(Z)

    @tf.function
    def encode(self, X):
        return self.encoder(X)

    @tf.function
    def decode(self, Z):
        return self.decode(Z)


def test_autoencoder(batch_size,
                     learning_rate,
                     epochs,
                     max_outputs=4,
                     seed=None):

    tf.random.set_seed(seed)

    X_train, X_test, train_dataset, _, _, _ = preprocess_mnist(
        batch_size=batch_size)

    autoencoder = AutoEncoder(units=64)
    opt = tf.optimizers.Adam(learning_rate=learning_rate)

    log_path = 'logs/autoencoder'
    if os.path.exists(log_path):
        shutil.rmtree(log_path)

    writer = tf.summary.create_file_writer(log_path)

    with writer.as_default():
        with tf.summary.record_if(True):
            for epoch in range(epochs):
                for step, batch in enumerate(train_dataset):
                    train_autoencoder(mse, autoencoder, opt, batch)

                # logs (train)
                train_loss = log_results(
                    model=autoencoder,
                    X=X_train,
                    max_outputs=max_outputs,
                    epoch=epoch,
                    prefix='train')

                # logs (test)
                test_loss = log_results(
                    model=autoencoder,
                    X=X_test,
                    max_outputs=max_outputs,
                    epoch=epoch,
                    prefix='test')

                writer.flush()

                template = 'Epoch {}, Train loss: {:.5f}, Test loss: {:.5f}'
                print(
                    template.format(epoch + 1, train_loss.numpy(),
                                    test_loss.numpy()))

    if not os.path.exists('saved_models'):
        os.makedirs('saved_models')
    np.savez_compressed('saved_models/encoder.npz',
                        *autoencoder.encoder.get_weights())


if __name__ == '__main__':
    test_autoencoder(batch_size=128, learning_rate=1e-3, epochs=20, seed=42)

由于编码器的输入形状用于解码器的构建函数,因此我希望当我训练自动编码器时,首先构建编码器,然后构建解码器,但情况似乎并非如此。我还尝试通过调用在解码器的构建函数中构建编码器self.encoder.build()在解码器的构建函数开始时,但没有任何区别。我究竟做错了什么?

我收到的错误:

AttributeError: The layer has never been called and thus has no defined input shape.

你已经快到了,只是事情有点过于复杂了。您收到此错误是因为Decoder层依赖于Encoder layer 尚未建成(作为调用build不成功)并且它是input_shape属性was not set.

解决方案是传递正确的输出形状AutoEncoder像这样的对象:

class Decoder(Layer):
    def __init__(self, units):
        super(Decoder, self).__init__()
        self.units = units

    def build(self, _):
        self.output_layer = Dense(units=self.units)

    def call(self, X):
        return self.output_layer(X)


class AutoEncoder(Model):
    def __init__(self, units):
        super(AutoEncoder, self).__init__()
        self.units = units

    def build(self, input_shape):
        self.encoder = Encoder(units=self.units)
        self.decoder = Decoder(units=input_shape[-1])

注意我已经删除了@tf,function装饰器,因为你不太可能获得任何效率提升(keras已经在后台为您创建了静态图)。

此外,正如人们所看到的,您的构建并不依赖于input_shape信息,以便所有创建都可以安全地移至构造函数,如下所示:

class Encoder(Layer):
    def __init__(self, units):
        super(Encoder, self).__init__()
        self.output_layer = Dense(units=units, activation=tf.nn.relu)

    def call(self, X):
        return self.output_layer(X)


class Decoder(Layer):
    def __init__(self, units):
        super(Decoder, self).__init__()
        self.output_layer = Dense(units=units)

    def call(self, X):
        return self.output_layer(X)


class AutoEncoder(Model):
    def __init__(self, units):
        super(AutoEncoder, self).__init__()
        self.units = units

    def build(self, input_shape):
        self.encoder = Encoder(units=self.units)
        self.decoder = Decoder(units=input_shape[-1])

    def call(self, X):
        Z = self.encoder(X)
        return self.decoder(Z)

    def encode(self, X):
        return self.encoder(X)

    def decode(self, Z):
        return self.decode(Z)

上面引出了一个问题是否分开Decoder and Encoder确实需要层。在我看来,这些应该被忽略,这样我们就只剩下这个简短易读的片段:

class AutoEncoder(Model):
    def __init__(self, units):
        super(AutoEncoder, self).__init__()
        self.units = units

    def build(self, input_shape):
        self.encoder = Dense(units=self.units, activation=tf.nn.relu)
        self.decoder = Dense(units=input_shape[-1])

    def call(self, X):
        Z = self.encoder(X)
        return self.decoder(Z)

    def encode(self, X):
        return self.encoder(X)

    def decode(self, Z):
        return self.decode(Z)

顺便提一句。你有一个错误sample但毫无疑问,这是一个你可以自己处理的未成年人。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AttributeError:该层从未被调用,因此没有定义的输入形状 的相关文章

随机推荐

  • RSS:刷新率?

    我正在编写一个供自己使用的小应用程序 它将使用公开发布的 RSS 提要 据我所知 该协议中没有订阅 发布机制 我需要让我的应用程序定期通过 HTTP GET 获取 RSS 提要 如果是这样的话 我想每隔十分钟左右就抢一次 但我担心被视为施虐
  • 使用 Process.Start() 启动后等待 WPF 应用程序加载

    我有一个 WinForms 应用程序 它启动一个运行的 wpf 进程Process Start 我想知道 WPF 进程何时完成加载并且我可以访问process MainWindowHandle属性 在完全加载之前其值为 0 我尝试轮询 但句
  • 如何为列表中的项目添加背景颜色

    我有一个有序列表 ol li class odd Lorem ipsum dolor sit amet consectetur li li class even Some more text li ol 看起来像这样 Lorem ipsum
  • C++ 条件变量通知未按预期工作

    我正在尝试在之前的工作完成后立即启动新线程worker thread has started 但也许结束了 也可能没有结束 我已经用时间延迟替换了开始和结束的工作 我的代码是 include
  • jquery ajax - 返回 json 或纯 html 更好

    当时间从ajax返回时 我应该返回 json 编码 并使用 jquery parseJSON 并使用 document createElement 并将数据附加到刚刚创建的元素内 或者最好以 html 文本形式返回 example div
  • 如何使用 C# 从数据库中检索多个图像

    我有一个包含9张图像的数据库 这些图像不断变化 所以我无法直接设置src在 HTML 中 img 标签来显示 9 个图像 我必须从数据库中选择它们并相应地绑定它们 我可以使用以下命令检索并打印 1 张图像Response BinaryWri
  • AVAudioPlayer 不播放声音

    我有一个 WatchKit 应用程序 当点击手表上的按钮时 它会向 iOS 应用程序发出播放声音的信号 由于某种原因 当我使用自定义类来处理设置实例时 声音没有播放AVAudioPlayer并播放声音 如果我在里面做那部分session d
  • 好的 Clojure 代码示例? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在第一次查看 Clojure 我发现查看 Clojure 核心库的 doc xxx 和 sourc
  • 使用 jquery deferreds 处理可变数量的 ajax 请求

    当我有可变数量的 ajax 请求时 如何使用 deferreds 调用它们 我猜 qty of gets 3 function getHTML productID qty of gets var dfd Deferred i 0 c 0 t
  • Hudson 与 UCM ClearCase 集成

    我有一台安装了 JBoss UCM ClearCase 和 ant 的 Linux 构建机器 我想了解如何使用 Hudson 和 Hudson Clearcase 插件配置持续集成 我可以使用已创建的现有动态视图吗 请给我一些基本步骤 先感
  • Angular 4 单元测试:de.query(By.css(...)) 与 de.nativeElement.querySelector(...) 的 Native Web API

    使用有什么好处吗el de query By css h2 nativeElement 通过原生元素 APIel de nativeElement querySelector h2 它们提供相同的结果 刚开始使用 Angular 4 单元测
  • 使用只有一个元组值的变体类型构造函数

    type foo Foo of int int let t 1 2 Foo t Error The constructor Foo expects 2 argument s but is applied here to 1 argument
  • 在函数中调用 patsy 时出现命名空间问题

    我正在尝试为 statsmodels 公式 API 编写一个包装器 这是一个简化版本 该函数的作用远不止于此 import statsmodels formula api as smf def wrapper formula data kw
  • 更改卡片布局中的活动项目。扩展JS

    我有一个使用卡片布局的面板 如下所示 var cardpanel new Ext Panel id cardPanel title Card Layout region center layout card activeItem 0 aut
  • 我应该如何将我的语言服务器与我的客户端打包?

    我正在尝试为 VSCode 创建语言服务器 它由客户端和服务器组成 通过 RPC 进行通信 官方文档有一个工作示例 https code visualstudio com docs extensions example language s
  • Oracle 日期索引很慢。没有它查询速度快 300 倍

    我有一个 Oracle 查询 如下所示 运行时间为 10 分钟或更长时间 select r range text as duration range nvl count c call duration 0 as calls nvl SUM
  • 如何在 Bootstrap Modal 中使用 CKEditor?

    如果我使用CKEditor http cksource com ckeditor基于 Bootstrap 模板的 HTML 页面中的插件 效果很好 但是如果我像这样在 Bootstrap Modal 上插入编辑器 div class mod
  • 在 socket.on() 的回调上调度操作

    所以基本上我得到了这个套接字 它工作正常 向我发送 新订单 消息 我正在使用 redux 并且我想分派一个操作 然后减速器会得到它并且我的商店将会更新 但这段代码没有做任何事情 socket on new order order gt re
  • Twitter 错误无法发布推文

    这个错误可能是什么 Could not post Tweet Error 403 Reason Status is a duplicate 实际上这是一条经过编辑的消息 我得到的错误代码为403和原因为Status is a duplica
  • AttributeError:该层从未被调用,因此没有定义的输入形状

    我尝试通过创建三个类在 TensorFlow 2 0 中构建自动编码器 Encoder Decoder 和 AutoEncoder 由于我不想手动设置输入形状 因此我尝试从编码器的 input shape 推断解码器的输出形状 import