Python新手搭建LSTM自编码器遇模型未构建错误求助
问题:LSTM自编码器提取瓶颈层时出现"This model has not yet been built"错误
我是Python新手,尝试用以下代码搭建LSTM自编码器,目标提取瓶颈层的压缩数据。但运行到编码器部分时,总会报错:This model has not yet been built. Build the model first by calling build()`,试过Stack Overflow上的一些建议,还是反复出错,请问哪里漏了?
完整代码
from google.colab import drive drive.mount('/content/drive') data=pd.read_csv(r'/content/drive/MyDrive/Datasets/All_Autoencoder_Data.csv') data1 = data.drop('Labels', axis=1) data1.shape (225711, 68) def create_sequences(X, time_steps=5): Xs = [] for i in range(0, len(X)-time_steps, 5): Xs.append(X.iloc[i:(i+time_steps)].values) return np.array(Xs) X_train=create_sequences(data1) X_train.shape (45142, 5, 68) inputs = Input(shape=(X_train.shape[1], X_train.shape[2])) eL0 = LSTM(68, activation='tanh', return_sequences=True, recurrent_activation="sigmoid", kernel_initializer="glorot_uniform", recurrent_regularizer=regularizers.l2(0.001), kernel_regularizer=regularizers.l2(0.001))(inputs) eL1 = LSTM(32, activation='tanh', return_sequences=True, recurrent_activation="sigmoid", kernel_initializer="glorot_uniform", recurrent_regularizer=regularizers.l2(0.001), kernel_regularizer=regularizers.l2(0.001))(eL0) eL2 = LSTM(8, activation='tanh', return_sequences=False)(eL1) # eL3 = LSTM(16, activation='relu', return_sequences=False)(eL2) h = RepeatVector(X_train.shape[1])(eL2) dL2 = LSTM(32, activation='tanh', return_sequences=True)(h) dL3 = LSTM(68, activation='tanh', return_sequences=True)(dL2) output = TimeDistributed(Dense(X_train.shape[2]))(dL3) #output = Dense(X_train.shape[2])(dL4) model = Model(inputs=inputs, outputs=output) #return model model.summary() model.build(input_shape=(None, 5, 68)) # fit the model to the data callback = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=3) nb_epochs = 200 batch_size = 250 opt = keras.optimizers.Adam(learning_rate=0.001) model.compile(optimizer=opt, loss='log_cosh', metrics=['accuracy']) history = model.fit(X_train, X_train, epochs=nb_epochs, batch_size=batch_size, validation_split=0.3, callbacks=[callback] ).history # plot the training losses fig, ax = plt.subplots(figsize=(6, 4), dpi=80) ax.plot(history['loss'], 'b', label='Train', linewidth=2) ax.plot(history['val_loss'], 'r', label='Validation', linewidth=2) ax.set_title('Model loss', fontsize=16) ax.set_ylabel('Loss (mse)') ax.set_xlabel('Epoch') ax.legend(loc='upper right') plt.show() #Encoder enc=Sequential() enc.add(model.layers[1]) enc.add(model.layers[2]) enc.add(model.layers[3]) enc.summary()
报错信息
ValueError Traceback (most recent call last) <ipython-input-50-225773931044> in <module> 3 enc.add(model.layers[2]) 4 enc.add(model.layers[3]) ----> 5 enc.summary() /usr/local/lib/python3.9/dist-packages/keras/engine/training.py in summary(self, line_length, positions, print_fn, expand_nested, show_trainable, layer_range) 3290 """ 3291 if not self.built: -> 3292 raise ValueError( 3293 "This model has not yet been built. " 3294 "Build the model first by calling `build()` or by calling " ValueError: This model has not yet been built. Build the model first by calling `build()` or by calling the model on a batch of data.
解决方案
问题根源
你直接从训练好的自编码器中提取层到新的Sequential模型,但这些层的输入维度没有被新模型继承,导致Keras无法确定编码器的输入形状,因此模型未完成构建。
方法一:直接基于原模型创建编码器(推荐)
不需要重新搭建Sequential,直接用Model类指定原模型的输入和瓶颈层输出,这样能完整继承原模型的层参数和输入形状:
# 瓶颈层是原模型的第4层(索引3),也就是eL2 encoder = Model(inputs=model.input, outputs=model.layers[3].output) encoder.summary() # 提取压缩数据 compressed_data = encoder.predict(X_train)
方法二:给Sequential编码器指定输入形状
如果一定要用Sequential,必须先明确输入形状,要么添加Input层,要么手动调用build方法:
enc = Sequential() # 添加输入层,和原模型输入形状一致 enc.add(Input(shape=(X_train.shape[1], X_train.shape[2]))) enc.add(model.layers[1]) enc.add(model.layers[2]) enc.add(model.layers[3]) enc.summary() # 或者不添加Input层,手动构建 # enc.build(input_shape=(None, X_train.shape[1], X_train.shape[2])) # enc.summary()
内容的提问来源于stack exchange,提问作者Frenzy
相关产品推荐
相关产品推荐

