多文本特征场景下Keras Embedding层的使用方法请教
我太懂这种纠结了——单文本任务里用Keras的Embedding层顺得不行,一碰到多文本特征就突然卡壳。针对你这个有「诊断文本」和「申请流程」两个特征的二分类任务,我给你两种落地性很强的实现思路,附带可直接复用的代码示例:
方法1:独立Embedding层+特征拼接
如果你的两个文本特征词汇差异很大(比如诊断文本是医学术语、申请流程是行政类表述),这种方法最合适——让每个特征独立学习专属的词向量,再把提取到的特征融合后做分类。
实现步骤&代码
假设你已经完成了数据预处理:分别对诊断文本、申请流程做了分词、转序列、padding,得到了train_diagnose_seq、train_process_seq,以及对应的标签train_labels:
from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Embedding, GlobalAveragePooling1D, Dense, Concatenate # 定义两个输入层,对应两个文本特征的长度 diagnose_input = Input(shape=(max_len_diagnose,), name='diagnose_text') process_input = Input(shape=(max_len_process,), name='process_text') # 为每个特征创建独立的Embedding层(可根据词汇量调整input_dim) embedding_diagnose = Embedding( input_dim=vocab_size_diagnose, # 诊断文本的词汇表大小 output_dim=128, # 词向量维度 input_length=max_len_diagnose # 诊断文本的固定长度 )(diagnose_input) embedding_process = Embedding( input_dim=vocab_size_process, output_dim=128, input_length=max_len_process )(process_input) # 提取文本特征(这里用全局平均池化,也可以换成LSTM/GRU) diagnose_features = GlobalAveragePooling1D()(embedding_diagnose) process_features = GlobalAveragePooling1D()(embedding_process) # 拼接两个特征向量,合并成一个全局特征 combined_features = Concatenate()([diagnose_features, process_features]) # 搭建分类头 output = Dense(64, activation='relu')(combined_features) output = Dense(1, activation='sigmoid')(output) # 构建并编译模型 model = Model(inputs=[diagnose_input, process_input], outputs=output) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 训练时传入两个输入特征 model.fit( [train_diagnose_seq, train_process_seq], train_labels, epochs=10, batch_size=32, validation_split=0.2 )
方法2:共享Embedding层(适合词汇重叠度高的场景)
如果两个文本特征的词汇重合度很高(比如都围绕「医疗申请」相关表述),可以让它们共享同一个Embedding层——这样能减少模型参数,还能让相似词汇的表示更统一,提升泛化能力。
实现步骤&代码
这种方法需要先把两个文本特征的所有语料合并,训练一个统一的Tokenizer,得到共享的词汇表:
from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Embedding, GlobalAveragePooling1D, Dense, Concatenate # 定义共享的Embedding层(用统一的词汇表大小) shared_embedding = Embedding( input_dim=vocab_size_unified, # 合并两个特征语料后的词汇表大小 output_dim=128, input_length=None # 允许输入不同长度的序列(也可以取两个特征的最大长度) ) # 两个输入层 diagnose_input = Input(shape=(max_len_diagnose,), name='diagnose_text') process_input = Input(shape=(max_len_process,), name='process_text') # 用同一个Embedding层处理两个输入 embedding_diagnose = shared_embedding(diagnose_input) embedding_process = shared_embedding(process_input) # 提取特征+拼接+分类头(和方法1一致) diagnose_features = GlobalAveragePooling1D()(embedding_diagnose) process_features = GlobalAveragePooling1D()(embedding_process) combined_features = Concatenate()([diagnose_features, process_features]) output = Dense(64, activation='relu')(combined_features) output = Dense(1, activation='sigmoid')(output) # 构建模型并训练 model = Model(inputs=[diagnose_input, process_input], outputs=output) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.fit( [train_diagnose_seq, train_process_seq], train_labels, epochs=10, batch_size=32 )
额外注意事项
- 特征融合方式:除了
Concatenate拼接,你还可以尝试Add(特征相加)、Multiply(特征相乘),甚至用注意力机制给重要特征加权,不过拼接是最稳妥的起步方案。 - 预处理细节:如果用独立Embedding,要给每个特征单独训练Tokenizer;如果用共享Embedding,一定要把两个特征的所有文本合并后训练Tokenizer,保证词汇表统一。
- 进阶优化:如果想进一步提升效果,可以把Embedding层换成预训练的词向量(比如GloVe),只需要把Embedding层的
weights参数设置为预训练矩阵,再根据需求选择是否冻结。
内容的提问来源于stack exchange,提问作者user2202866
相关产品推荐
相关产品推荐

