如何基于TensorFlow/Keras实现文本多标签分类?
实现带原因标签的文本分类模型修改方案
1. 修改数据加载逻辑
原加载函数仅处理单标签,现在需要拆分主标签(Approve/Disapprove)和原因标签。根据数据格式,行拆分后长度为2时对应Approve(无原因),长度为3时对应Disapprove+具体原因:
def load_data(file_path): with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines() posts, main_labels, reason_labels = [], [], [] for line in lines: parts = line.strip().split('³') post = parts[0] posts.append(post) if len(parts) == 2: # 对应Approve场景 main_labels.append(parts[1]) reason_labels.append("Approved") # 用特殊值标记无原因 else: # 对应Disapprove+原因场景 main_labels.append(parts[2]) reason_labels.append(parts[1]) return posts, main_labels, reason_labels # 加载数据 train_posts, train_main_labels, train_reason_labels = load_data('mixed_train_data.csv') test_posts, test_main_labels, test_reason_labels = load_data('mixed_test_data.csv')
2. 构建双标签映射字典
分别为主标签和原因标签创建索引映射,原因标签需包含所有可能的类别(包括Approve对应的"Approved"):
# 主标签映射(保持原逻辑) main_label_to_index = { 'Approve': 0, 'Disapprove': 1 } # 收集所有原因标签并创建映射 all_reasons = list(set(train_reason_labels + test_reason_labels)) reason_label_to_index = {reason: idx for idx, reason in enumerate(all_reasons)}
3. 预处理标签数据
将标签转换为模型可接受的索引数组:
import numpy as np from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences # 文本分词与填充(保持原逻辑) tokenizer = Tokenizer() tokenizer.fit_on_texts(train_posts) max_sequence_length = 7500 # 训练数据 sequences = tokenizer.texts_to_sequences(train_posts) X_train = pad_sequences(sequences, maxlen=max_sequence_length) y_train_main = np.array([main_label_to_index[label] for label in train_main_labels]) y_train_reason = np.array([reason_label_to_index[label] for label in train_reason_labels]) # 测试数据 test_sequences = tokenizer.texts_to_sequences(test_posts) X_test = pad_sequences(test_sequences, maxlen=max_sequence_length) y_test_main = np.array([main_label_to_index[label] for label in test_main_labels]) y_test_reason = np.array([reason_label_to_index[label] for label in test_reason_labels])
4. 重构模型为多输出结构
使用Keras Functional API构建共享特征提取层的双输出模型:一个分支预测主标签,另一个分支预测原因标签:
from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Embedding, Flatten, Dense # 输入层 input_layer = Input(shape=(max_sequence_length,)) # 共享特征提取层 embedding = Embedding(input_dim=len(tokenizer.word_index)+1, output_dim=50)(input_layer) # +1是因为Tokenizer从1开始索引 flatten = Flatten()(embedding) dense_shared = Dense(128, activation='relu')(flatten) # 主标签输出分支 main_output = Dense(len(main_label_to_index), activation='softmax', name='main_output')(dense_shared) # 原因标签输出分支 reason_output = Dense(len(reason_label_to_index), activation='softmax', name='reason_output')(dense_shared) # 构建模型 model = Model(inputs=input_layer, outputs=[main_output, reason_output])
5. 编译与训练模型
针对双输出设置损失函数和评估指标,训练时传入两组标签数据:
from tensorflow.keras.optimizers import Adam # 编译模型 learning_rate = 0.001 model.compile( optimizer=Adam(learning_rate=learning_rate), loss={ 'main_output': 'sparse_categorical_crossentropy', 'reason_output': 'sparse_categorical_crossentropy' }, metrics={ 'main_output': 'accuracy', 'reason_output': 'accuracy' } ) # 训练模型(假设你已定义checkpoint_callback) model.fit( X_train, {'main_output': y_train_main, 'reason_output': y_train_reason}, epochs=100, batch_size=32, validation_data=(X_test, {'main_output': y_test_main, 'reason_output': y_test_reason}), callbacks=[checkpoint_callback] )
预测示例
预测时可同时得到主标签和原因标签,再转换回原始文本:
# 反向映射字典 index_to_main_label = {v: k for k, v in main_label_to_index.items()} index_to_reason_label = {v: k for k, v in reason_label_to_index.items()} # 预测单条文本 sample_post = ["你真蠢"] sample_seq = tokenizer.texts_to_sequences(sample_post) sample_pad = pad_sequences(sample_seq, maxlen=max_sequence_length) main_pred, reason_pred = model.predict(sample_pad) # 获取预测结果 pred_main_label = index_to_main_label[np.argmax(main_pred)] pred_reason_label = index_to_reason_label[np.argmax(reason_pred)] print(f"预测结果:{pred_main_label} + {pred_reason_label}")
内容的提问来源于stack exchange,提问作者Menrion
相关产品推荐
相关产品推荐

