小能豆

AttributeError:'NoneType'对象在 Keras 中没有属性'_inbound_nodes'

py

我想定义我自己的 Lstm 模型如下:

from keras import backend as K
from keras.callbacks import ModelCheckpoint
from keras.layers.core import Dense, Activation, Flatten, Dropout
from keras.layers import Input,Concatenate, Average, Maximum
from keras.layers.normalization import BatchNormalization
from keras.layers import LSTM, Bidirectional
from keras.models import Model
from keras.optimizers import Adam

class LSTMModel(object):

    def __init__(self, config):
        self.num_batch = config['num_batch']
        self.maxlen = config['maxlen']
        self.embedding_dims = config['embedding_dims']
        self.lstm_dims = config['lstm_dims']
        self.hidden_dims = config['hidden_dims']
        self.epochs = config['epochs']
        self.classes = config['classes']
        self.optimizer = config['optimizer']

    def load_data(self):
        (X_train, y_train), (X_test, y_test) = \
            imdb.load_data(num_words=self.max_features, seed=11)

        X_train = sequence.pad_sequences(X_train, maxlen=self.maxlen)
        X_test = sequence.pad_sequences(X_test, maxlen=self.maxlen)

        return (X_train, y_train), (X_test, y_test)

    def build_model(self, loss, P=None):

        input = Input(shape=(self.maxlen , self.embedding_dims))

        rnn_outputs, forward_h, forward_c, backward_h, backward_c  =\
        Bidirectional(LSTM(self.lstm_dims, return_sequences = True, return_state = True,
                           kernel_initializer='uniform'))(input)
        avg_pool = K.mean(rnn_outputs, axis = 1)
        max_pool = K.max(rnn_outputs, axis = 1)
        print(avg_pool)
        print(max_pool)
        x = Concatenate()([avg_pool, max_pool])
        print(x)
        #Add a dense layer
        x = Dense(self.hidden_dims, kernel_initializer = 'he_normal')(x)
        x = Activation('relu')(x)
        x = BatchNormalization(momentum = 0.5)(x)
        x = Dropout(0.5)(x)

        output = Dense(self.classes, kernel_initializer = 'he_normal')(x)

        if loss in yes_bound:
            output = BatchNormalization(axis=1)(output)

        if loss in yes_softmax:
            output = Activation('softmax')(output)

        model = Model(inputs=input, outputs=output)
        self.compile(model, loss, P)


if __name__ == "__main__":

    config = {
        "maxlen": 100,
        "embedding_dims": 31,
        "lstm_dims":20,
        "hidden_dims": 80,
        "classes": 21,
        "epochs": 50,
        "num_batch": 24,
        "optimizer": None
    }

    model = LSTMModel(config)
    model.build_model('crossentropy')

但是,我遇到一个错误:

AttributeError: 'NoneType' object has no attribute '_inbound_nodes'

详细信息如下:

  File "F:\models.py", line 169, in build_model
    model = Model(inputs=input, outputs=output)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
    return func(*args, **kwargs)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 93, in __init__
    self._init_graph_network(*args, **kwargs)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 237, in _init_graph_network
    self.inputs, self.outputs)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1353, in _map_graph_network
    tensor_index=tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1340, in build_map
    node_index, tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1340, in build_map
    node_index, tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1340, in build_map
    node_index, tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1340, in build_map
    node_index, tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1340, in build_map
    node_index, tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1340, in build_map
    node_index, tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1340, in build_map
    node_index, tensor_index)

  File "E:\SoftwareInstall\anaconda3.5.2.0\lib\site-packages\keras\engine\network.py", line 1312, in build_map
    node = layer._inbound_nodes[node_index]

AttributeError: 'NoneType' object has no attribute '_inbound_nodes'

阅读 24

收藏
2024-12-08

共1个答案

小能豆

你的错误 AttributeError: 'NoneType' object has no attribute '_inbound_nodes' 主要是由 Keras 层的连接或构建方式的问题引起的。在你提供的代码中,可能有以下几个问题导致这个错误。

问题 1:Bidirectional(LSTM) 层的输出没有正确连接

你在定义 Bidirectional(LSTM) 时,使用了 return_state=Truereturn_sequences=True,这导致 Bidirectional(LSTM) 会返回四个输出:rnn_outputs, forward_h, forward_c, backward_h, backward_c。但是,你并没有正确使用这些输出中的任何一个,且你可能想要的只是 rnn_outputs

解决方案:

你可以修改 Bidirectional(LSTM) 层的定义,确保它的输出能够正确地连接到后续层。考虑到你的代码,假设你只关心 rnn_outputs,你可以简单地将其修改为:

rnn_outputs = Bidirectional(LSTM(self.lstm_dims, return_sequences=True))(input)

问题 2:错误的 K.meanK.max 用法

你在计算 avg_poolmax_pool 时使用了 K.meanK.max,这些是 Keras 后端的操作。它们的输入应该是层输出的张量,因此你应确保这些操作与 rnn_outputs 正确连接。

解决方案:

修改你的代码来确保 rnn_outputs 是一个可以应用 K.meanK.max 操作的张量:

avg_pool = K.mean(rnn_outputs, axis=1)
max_pool = K.max(rnn_outputs, axis=1)

问题 3:输出层的激活函数和损失函数

在输出层,你将 activation='softmax'loss='crossentropy' 配对,这通常是没问题的,但你还需要确保输出层的定义是合适的。你可能想使用 activation='softmax' 进行多类别分类。

解决方案:

output = Dense(self.classes, activation='softmax', kernel_initializer='he_normal')(x)

完整代码修改:

from keras import backend as K
from keras.callbacks import ModelCheckpoint
from keras.layers.core import Dense, Activation, Flatten, Dropout
from keras.layers import Input, Concatenate
from keras.layers.normalization import BatchNormalization
from keras.layers import LSTM, Bidirectional
from keras.models import Model
from keras.optimizers import Adam
from keras.preprocessing import sequence
from keras.datasets import imdb

class LSTMModel(object):

    def __init__(self, config):
        self.num_batch = config['num_batch']
        self.maxlen = config['maxlen']
        self.embedding_dims = config['embedding_dims']
        self.lstm_dims = config['lstm_dims']
        self.hidden_dims = config['hidden_dims']
        self.epochs = config['epochs']
        self.classes = config['classes']
        self.optimizer = config['optimizer']

    def load_data(self):
        (X_train, y_train), (X_test, y_test) = \
            imdb.load_data(num_words=10000, seed=11)  # You need to specify max_features if needed.

        X_train = sequence.pad_sequences(X_train, maxlen=self.maxlen)
        X_test = sequence.pad_sequences(X_test, maxlen=self.maxlen)

        return (X_train, y_train), (X_test, y_test)

    def build_model(self, loss, P=None):

        input = Input(shape=(self.maxlen , self.embedding_dims))

        # Bidirectional LSTM layer
        rnn_outputs = Bidirectional(LSTM(self.lstm_dims, return_sequences=True))(input)

        # Apply mean and max pooling
        avg_pool = K.mean(rnn_outputs, axis=1)
        max_pool = K.max(rnn_outputs, axis=1)

        # Concatenate the two pooled outputs
        x = Concatenate()([avg_pool, max_pool])

        # Add a dense layer
        x = Dense(self.hidden_dims, kernel_initializer='he_normal')(x)
        x = Activation('relu')(x)
        x = BatchNormalization(momentum=0.5)(x)
        x = Dropout(0.5)(x)

        # Output layer
        output = Dense(self.classes, activation='softmax', kernel_initializer='he_normal')(x)

        model = Model(inputs=input, outputs=output)

        self.compile(model, loss, P)

    def compile(self, model, loss, P=None):
        if self.optimizer is None:
            optimizer = Adam()
        else:
            optimizer = self.optimizer

        model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])

if __name__ == "__main__":

    config = {
        "maxlen": 100,
        "embedding_dims": 31,
        "lstm_dims": 20,
        "hidden_dims": 80,
        "classes": 21,
        "epochs": 50,
        "num_batch": 24,
        "optimizer": None
    }

    model = LSTMModel(config)
    model.build_model('categorical_crossentropy')  # Assuming this is the loss for classification

主要变化:

  1. 修改了 Bidirectional(LSTM) 层的输出。
  2. 使用 K.meanK.max 正确计算平均池化和最大池化。
  3. 修复了 output 层的激活函数。

注意事项:

  • 确保 loss 是适合你任务的类型,比如 categorical_crossentropy 用于多类别分类。
  • 如果你不使用 Adam 优化器,可以在配置中指定你自己的优化器。

通过这些修正,应该可以解决你遇到的 AttributeError: 'NoneType' object has no attribute '_inbound_nodes' 错误。

2024-12-08