如何在Keras模型中替换Embedding层并保留其余架构与权重
问题背景
我用Gensim的Word2Vec库搭建了一个针对推特数据的情感分析Keras序列神经网络。先在大规模推特文本语料上训练Word2Vec生成嵌入词典,再把它用到Keras的Embedding层里,整个流程能正常运行。
为了在随机数据集上多次运行模型以获得更鲁棒的结果,我想在其他数据上预训练模型,保存模型的架构和权重,但要适配新数据集重新构建Embedding层。
核心问题
如何加载带有架构与权重的预训练Keras模型,并用新数据集生成的新Embedding层/嵌入矩阵替换原有层?
原模型构建代码
from tensorflow import keras from keras.preprocessing.text import Tokenizer from keras.utils import pad_sequences from keras.models import Sequential from keras import layers maxlen= 100 EMBEDDING_DIM = 100 embedding_layer = layers.Embedding(len(word_index) + 1, EMBEDDING_DIM, weights=[embedding_matrix], input_length=maxlen, trainable=True) model = Sequential() model.add(embedding_layer) model.add(layers.Flatten()) model.add(layers.Dense(10, activation='relu')) model.add(layers.Dense(3, activation='softmax')) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
尝试的加载方式(出现问题)
pretrained_model = keras.models.load_model("my_model") weights = pretrained_model.get_weights() model.set_weights(weights)
运行后遇到各层权重数量不匹配的问题,尽管两个模型构建方式一致,仅Embedding层存在差异,且词汇表大小一致,不确定是模型保存加载函数导致的不匹配,还是Word2Vec嵌入词典的问题。
嵌入矩阵构建代码
model = Word2Vec(sentences=texts, max_final_vocab=1000) tokenizer = Tokenizer(num_words=vocab_size) tokenizer.fit_on_texts(df.iloc[:,7]) tokenized = tokenizer.texts_to_sequences(df.iloc[:,7]) word_index = tokenizer.word_index EMBEDDING_DIM = 100 embedding_matrix = np.zeros((len(word_index) + 1, EMBEDDING_DIM)) for word, i in word_index.items(): embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector
解决方案
问题出在直接用set_weights()会替换所有层的权重,而新模型的Embedding层参数维度(或映射逻辑)和预训练模型不匹配。正确做法是仅替换除Embedding层外的其他层权重,步骤如下:
- 加载预训练模型
pretrained_model = keras.models.load_model("my_model")
构建适配新数据集的新模型
按照原模型结构,用新数据集生成的word_index和embedding_matrix创建新的Embedding层,搭建完整模型(和原模型结构一致,仅Embedding层参数不同)。提取预训练模型中除Embedding层外的权重
预训练模型的层顺序是:Embedding → Flatten → Dense(10) → Dense(3),跳过第0层(Embedding层)提取后续层的权重:
# 提取预训练模型中第1层及之后的权重 non_embedding_weights = pretrained_model.get_weights()[1:]
- 将权重设置到新模型对应层
新模型结构和预训练模型一致,同样跳过第0层,设置权重:
# 给新模型的第1层及之后设置预训练权重 new_model.set_weights(non_embedding_weights)
- 验证与编译
确认权重设置成功后,重新编译模型(可沿用原配置或按需调整):
new_model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
额外注意事项
- 确保新模型和预训练模型的非Embedding层结构完全一致:比如Dense层的神经元数量、激活函数,Flatten层的位置等,否则权重维度仍会不匹配。
- 若新数据集词汇表大小和预训练时不同,Embedding层输入维度变化,必须只替换后续层权重,不能全量替换。
- 若想让Embedding层在新数据上继续训练,保持
trainable=True;若要固定嵌入向量,设置trainable=False。
内容的提问来源于stack exchange,提问作者Klara Lundgren
相关产品推荐
相关产品推荐

