首页 > 解决方案 > 当我尝试在 Colab 上修改加载的 LSTM 模型参数时出现属性错误

问题描述

我正在尝试从 Colab 上的 Keras 加载 LSTM 模型并更改其单位,但出现以下错误:“AttributeError:无法设置属性“单位”,可能是因为它与现有的只读 @property 冲突对象。请选择其他名称”。我尝试修改其他图层参数并且效果很好。我能做些什么来修复它?

我用来加载模型并修改它的代码:

model = keras.models.load_model('model.h5')
model.summary() #the model is composed by embedding, dropout, LSTM, dropout then dense layer

model.layers[2].units = 100
new_model = model_from_json(model.to_json())

我用来生成初始模型的代码:

def lstm(vocab_size, tokenizer, X_train, X_validation, y_train, y_validation):

  model = Sequential()

  model.add(Embedding(input_dim=vocab_size,
                      output_dim=embedding_dim,
                      input_length=length_size,
                      name='embedding'))
  
  #droupout layer
  model.add(Dropout(rate = first_dropout_rate))

  #lstm layer
  model.add(LSTM(units = units))

  #dropout layer
  model.add(Dropout(rate = last_dropout_rate))

  #output layer
  model.add(Dense(units=1, activation='sigmoid'))

  model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
  #model_random.summary()

  history_random = model.fit(X_train, 
                             y_train,
                             batch_size=batch_size,
                             epochs=epochs,
                             validation_data=(X_validation, y_validation))
    
  return model

标签: pythontensorflowkeraslstm

解决方案


错误消息有些误导。您不能直接更改参数,例如 LSTM 中的单元数,因为这会更改层权重的大小。
您必须构建一个与第一个模型具有相同结构的新模型,但 LSTM 层的单元数量不同。然后你需要复制模型权重,除了 LSTM 层和下一层(因为 LSTM 输出的大小发生了变化)。

下面是一些代码(参数的值是任意的):

from tensorflow.keras.layers import Embedding, Dropout, LSTM, Dense 
from tensorflow.keras import Sequential

vocab_size = 41
embedding_dim = 100
length_size = 50

first_dropout_rate=0.2
last_dropout_rate = 0.2
units=2

def create_lstm_model(vocab_size, embedding_dim, length_size, first_dropout_rate, last_dropout_rate, units):
    model = Sequential()
    model.add(Embedding(input_dim=vocab_size,
                    output_dim=embedding_dim,
                    input_length=length_size,
                    name='embedding'))
    #droupout layer
    model.add(Dropout(rate=first_dropout_rate))
    #lstm layer
    model.add(LSTM(units=units, name='mylstm'))  # give a name to the layer

    #dropout layer
    model.add(Dropout(rate=last_dropout_rate))

    #output layer
    model.add(Dense(units=1, activation='sigmoid', name='mydense'))  # give a name to the layer
    return model

# create and compile model with 2 LSTM units
model = create_lstm_model(vocab_size, embedding_dim, length_size, first_dropout_rate, last_dropout_rate, units=2)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

# do model.fit

# create a new model with 3 LSTM units
new_model = create_lstm_model(vocab_size, embedding_dim, length_size, first_dropout_rate, last_dropout_rate, units=3)

# copy weights
for count, (layer, new_layer) in enumerate(zip(model.layers, new_model.layers)): 
    if layer.name in ['mylstm', 'mydense']:  # the weights of these two layers have different sizes in the two models 
        continue
    print(new_layer)
    new_layer.set_weights(layer.get_weights())

new_model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
new_model.summary()

推荐阅读