DrWhiter 发表于 前天 11:29

关于使用BERT进行意图识别与槽位填充的问题

本帖最后由 DrWhiter 于 2025-10-19 13:02 编辑

项目需要对网易云的私信消息进行筛选 首先需要将投稿(e.g. "午间歌单 周杰伦 《告白气球》")与普通的推广信息区分开 然后需要进行槽类填充来获取相关的歌手信息 听说BERT模型可以完成这样的工作 但是找了一圈也没有发现相关的示例代码 希望有大佬可以提供相关的示例或者说明 非常感谢

FishC 发表于 前天 11:30

当然可以!使用BERT模型进行意图识别和槽位填充是一个常见的自然语言处理任务。下面我将用简洁的示例代码和说明来帮助你理解如何实现。请注意,这些代码基于Python和Hugging Face的Transformers库,你需要先安装相关依赖(如transformers和torch)。

1. 意图识别(区分投稿和推广信息)
意图识别可以看作一个文本分类任务。我们使用BERT的序列分类模型,将输入文本分类为“投稿”或“推广”。

示例代码:

from transformers import BertTokenizer, BertForSequenceClassification
import torch

# 加载预训练模型和分词器(假设你已有一个训练好的模型,这里用示例模型)
model_name = 'bert-base-chinese'# 使用中文BERT模型
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2)# 2个类别:投稿和推广

# 示例文本
text = "午间歌单 周杰伦 《告白气球》"
inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)

# 预测
outputs = model(**inputs)
logits = outputs.logits
predicted_class = torch.argmax(logits, dim=1).item()

# 输出结果(假设0代表推广,1代表投稿)
if predicted_class == 1:
    print("这是投稿消息")
else:
    print("这是推广信息")


说明:
- 你需要用自己的数据训练模型,或者使用预训练模型微调。这里只是一个预测示例。
- 训练时,你需要准备带标签的数据集(文本和对应的意图标签)。

2. 槽位填充(提取歌手信息)
槽位填充是序列标注任务,我们使用BERT的标记分类模型,为每个token分配标签(如B-ARTIST、I-ARTIST、O)。

示例代码:

from transformers import BertTokenizer, BertForTokenClassification
import torch

# 加载预训练模型和分词器(假设已训练好槽位填充模型)
model_name = 'bert-base-chinese'
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertForTokenClassification.from_pretrained(model_name, num_labels=3)# 假设3个标签:O, B-ARTIST, I-ARTIST

# 示例文本
text = "午间歌单 周杰伦 《告白气球》"
inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)

# 预测
outputs = model(**inputs)
logits = outputs.logits
predictions = torch.argmax(logits, dim=2)

# 提取槽位(歌手信息)
tokens = tokenizer.convert_ids_to_tokens(inputs['input_ids'])
labels = predictions.tolist()
artist = []
for token, label in zip(tokens, labels):
    if label == 1:# 假设1代表B-ARTIST
      artist.append(token)
    elif label == 2:# 假设2代表I-ARTIST
      artist.append(token)
# 合并token并清理(如去除##子词)
artist_text = tokenizer.convert_tokens_to_string(artist).replace(' ##', '')
print(f"提取的歌手:{artist_text}")


说明:
- 标签定义示例:O(其他)、B-ARTIST(歌手开始)、I-ARTIST(歌手中间)。
- 实际应用中,你需要用标注数据训练模型(每个token都有标签)。
- 处理子词:BERT分词可能会将词拆开,代码中使用了简单清理。

结合使用建议
- 先进行意图识别,如果是投稿,再执行槽位填充。
- 训练模型需要标注数据:意图标签和槽位标签。
- 如果没有现成数据,你可以从少量样本开始,手动标注并微调BERT。

如果你有更多问题,欢迎继续讨论!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

DrWhiter 发表于 前天 13:13

如何进行训练

FishC 发表于 前天 13:14

DrWhiter 发表于 2025-10-19 13:13
如何进行训练

当然可以!训练BERT模型进行意图识别和槽位填充需要准备数据、加载预训练模型并进行微调。下面我将分步骤说明,并提供示例代码。请注意,这些代码基于Python和Hugging Face的Transformers库,你需要先安装依赖(如transformers、torch和datasets)。

训练步骤概述
1. 准备数据:标注意图标签(用于分类)和槽位标签(用于序列标注)。
2. 加载预训练模型:使用BERT基础模型。
3. 微调模型:在自定义数据上训练。
4. 评估和保存模型。

1. 意图识别训练(文本分类)
意图识别是将文本分类为预定义类别(如“投稿”或“推广”)。以下是训练示例:


from transformers import BertTokenizer, BertForSequenceClassification, Trainer, TrainingArguments
from datasets import Dataset
import torch

# 步骤1: 准备示例数据(假设数据格式:文本和标签)
texts = ["午间歌单 周杰伦 《告白气球》", "推广优惠券", ...]# 你的文本列表
labels = # 标签:0=推广,1=投稿

# 创建数据集
dataset = Dataset.from_dict({"text": texts, "label": labels})

# 步骤2: 加载分词器和模型
model_name = "bert-base-chinese"
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2)

# 分词函数
def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True, max_length=128)

tokenized_dataset = dataset.map(tokenize_function, batched=True)

# 步骤3: 设置训练参数
training_args = TrainingArguments(
    output_dir="./results",
    num_train_epochs=3,
    per_device_train_batch_size=8,
    evaluation_strategy="no",# 假设无验证集,实际应添加
    save_strategy="epoch",
)

# 步骤4: 训练
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
)
trainer.train()

# 保存模型
trainer.save_model("./intent_model")


说明:
- 数据准备:你需要一个带标签的数据集。标签应为整数(如0和1)。
- 训练参数:根据数据量调整epochs和batch_size。
- 评估:建议添加验证集以监控性能。

2. 槽位填充训练(序列标注)
槽位填充是为每个token分配标签(如B-ARTIST、I-ARTIST、O)。以下是训练示例:


from transformers import BertTokenizer, BertForTokenClassification, Trainer, TrainingArguments
from datasets import Dataset
import torch

# 步骤1: 准备示例数据(文本和每个token的标签)
texts = ["午间歌单 周杰伦 《告白气球》", ...]
labels = [, ...]# 标签列表:0=O, 1=B-ARTIST, 2=I-ARTIST(假设)

# 创建数据集
dataset = Dataset.from_dict({"tokens": texts, "ner_tags": labels})

# 步骤2: 加载分词器和模型
model_name = "bert-base-chinese"
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertForTokenClassification.from_pretrained(model_name, num_labels=3)# 3个标签

# 分词和对齐标签函数
def tokenize_and_align_labels(examples):
    tokenized_inputs = tokenizer(examples["tokens"], truncation=True, padding="max_length", max_length=128, is_split_into_words=True)
    labels = []
    for i, label in enumerate(examples["ner_tags"]):
      word_ids = tokenized_inputs.word_ids(batch_index=i)
      previous_word_idx = None
      label_ids = []
      for word_idx in word_ids:
            if word_idx is None:
                label_ids.append(-100)# 忽略特殊token
            elif word_idx != previous_word_idx:
                label_ids.append(label)
            else:
                label_ids.append(-100)# 或处理子词(这里简单忽略)
            previous_word_idx = word_idx
      labels.append(label_ids)
    tokenized_inputs["labels"] = labels
    return tokenized_inputs

tokenized_dataset = dataset.map(tokenize_and_align_labels, batched=True)

# 步骤3: 设置训练参数(类似意图识别)
training_args = TrainingArguments(
    output_dir="./slot_results",
    num_train_epochs=3,
    per_device_train_batch_size=8,
    save_strategy="epoch",
)

# 步骤4: 训练
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
)
trainer.train()

# 保存模型
trainer.save_model("./slot_model")


说明:
- 数据准备:标签必须与token对齐。例如,文本“周杰伦”可能被分词为[“周”, “杰”, “伦”],标签应为。
- 标签对齐:代码中使用word_ids处理BERT分词产生的子词,将子词标签设为-100(被忽略)。
- 实际应用:你需要大量标注数据来获得好效果。

重要提示
- 数据质量:确保标注准确。可以从少量数据开始,逐步扩展。
- 资源:训练需要GPU支持,否则可能很慢。
- 测试:训练后使用验证集评估模型性能。

如果你有具体数据或问题,欢迎进一步讨论!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 关于使用BERT进行意图识别与槽位填充的问题