1、意图识别基础知识
1.1意图识别是什么
意图识别是自然语言处理(NLP)中的一项核心任务,旨在从用户的文本或语音输入中,自动识别其潜在的目的或需求。简单来说,就是让机器 “理解” 用户说这句话想做什么,比如是想查询信息、下达指令、表达情感,还是提出请求等。通过分析用户输入的语言(词汇、语法、语境等),将其归类到预定义的意图类别中。
1.2意图识别的应用场景
- 智能客服:识别用户的咨询意图(如投诉、查询订单、售后问题),自动转接对应服务或提供解决方案。
- 语音助手:如 Siri、小爱同学,通过识别用户意图(如设置闹钟、播放音乐、导航)执行相应操作。
- 聊天机器人:在对话中理解用户的核心需求(如闲聊、寻求建议、获取知识),生成合适的回应。
- 智能推荐:根据用户的搜索或提问意图(如找电影、买衣服),推荐相关内容或商品。
1.3意图识别的实现方法
-
基于规则的方法
通过人工定义关键词或模板来匹配意图。例如,包含 “天气”“温度” 的句子归为 “查询天气” 意图;包含 “订”“买”“预约” 的句子归为 “预订 / 购买” 意图。- 优点:简单易实现,解释性强。
- 缺点:覆盖范围有限,难以处理复杂句式或歧义,维护成本高(需不断更新规则)。
-
基于机器学习的方法
将意图识别视为分类问题,通过标注好的训练数据(输入文本 + 对应意图标签)训练分类模型。常见模型包括:- 传统机器学习:如支持向量机(SVM)、朴素贝叶斯,需先对文本进行特征工程(如提取词袋、TF-IDF 特征)。
- 深度学习:如循环神经网络(RNN)、卷积神经网络(CNN)、BERT 等预训练模型,可自动学习文本的深层语义特征,处理复杂语境的能力更强。
- 优点:泛化能力强,能处理多样的表达方式。
- 缺点:需要大量标注数据,模型训练和调优成本较高。
-
混合方法
结合规则和机器学习的优势,例如用规则处理明确的简单意图,用模型处理模糊或复杂的意图,提高识别准确率。
1.4意图识别的挑战
- 歧义性:同一表达可能对应多个意图,如 “苹果多少钱” 可能是问水果价格,也可能是问苹果手机价格。
- 口语化与不规范性:用户输入可能包含错别字、缩写、方言或不完整句子(如 “明儿去广州,票”)。
- 领域依赖性:不同领域的意图差异大(如电商领域的 “退换货” 和医疗领域的 “挂号”),模型需针对特定领域优化。
- 上下文关联:部分意图需要结合对话历史才能确定,例如用户说 “帮我取消它”,需结合前文知道 “它” 指的是订单还是预约。
2、代码实战
2.1代码实现原理
-
数据准备:我们创建了一个小型数据集,包含四种意图(查询天气、播放音乐、设置闹钟、发送消息)和每种意图对应的例句。
-
文本预处理(分词+去停用词):使用
jieba进行准确分词,过滤标点、停用词。 -
特征提取:使用 TF-IDF(词频 - 逆文档频率)将文本转换为数值特征,这有助于捕捉词语在句子中的重要性。或者使用预训练词向量,捕捉深层语义。
-
结合规则系统:对高频明确意图(如含 “天气”→查询天气)用规则兜底,减少模型错误。
-
模型训练:使用朴素贝叶斯分类器、或者逻辑回归、SVM,或深度学习模型。
-
模型评估:通过准确率和分类报告评估模型性能,查看模型在不同意图上的识别效果。
-
预测功能:实现了一个函数,可以对新的句子进行意图预测并返回置信度。
2.2提高意图识别准确率措施
-
扩充与优化训练数据
- 增加样本数量:每个意图至少包含 50 + 样本
- 增强样本多样性:覆盖同义词、不同句式、口语化表达(如 “明儿”“咋” 等)。
- 数据增强:通过同义词替换、句式变换(主动 / 被动)、随机插入虚词等生成新样本。
-
精细化文本预处理
- 中文分词:使用
jieba进行准确分词(中文无空格,分词是基础)。 - 去除噪声:过滤标点、停用词(如 “的”“吗”)、特殊符号。
- 标准化:小写转换、错别字修正(可选)。
- 中文分词:使用
-
升级特征表示
- 替换 TF-IDF:使用预训练词向量(如 Word2Vec、GloVe)或上下文感知嵌入(如 BERT),捕捉深层语义。
-
选择更优模型
- 使用逻辑回归、SVM,或深度学习模型(如 LSTM、BERT 微调),这些模型对语义的理解更强。
-
结合规则系统
- 对高频明确意图(如含 “天气”→查询天气)用规则兜底,减少模型错误。
2.3代码示例
import numpy as np
import pandas as pd
import jieba
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report, accuracy_score
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import LabelEncoder
# --------------------------
# 1. 扩充训练数据(增加样本多样性)
# --------------------------
data = [
# 查询天气(20条样本,覆盖不同句式和同义词)
("今天天气怎么样?", "查询天气"),
("明天会下雨吗?", "查询天气"),
("北京的气温是多少?", "查询天气"),
("后天适合出门吗?", "查询天气"),
("未来一周的天气预报", "查询天气"),
("上海今天热不热?", "查询天气"),
("杭州下周有没有雨?", "查询天气"),
("西安的温度大概多少度", "查询天气"),
("明儿天气咋样啊", "查询天气"), # 口语化表达
("下周适合旅游吗?看天气", "查询天气"),
("查一下广州的天气情况", "查询天气"),
("明天用不用带伞?", "查询天气"),
("后天的天气如何", "查询天气"),
("未来三天会降温吗", "查询天气"),
("深圳今天的湿度是多少", "查询天气"),
("哈尔滨冷不冷现在", "查询天气"),
("重庆下周的天气怎么样", "查询天气"),
("成都明天会不会下雨呀", "查询天气"),
("武汉的天气 forecast", "查询天气"), # 夹杂英文
("郑州今天的天气状况", "查询天气"),
# 播放音乐(20条样本)
("给我放首歌", "播放音乐"),
("播放周杰伦的歌曲", "播放音乐"),
("我想听流行音乐", "播放音乐"),
("换一首曲子", "播放音乐"),
("停止播放", "播放音乐"),
("放首英文歌听听", "播放音乐"),
("帮我点播一首周杰伦的晴天", "播放音乐"),
("切换到摇滚模式", "播放音乐"),
("暂停当前歌曲", "播放音乐"),
("我想听歌", "播放音乐"),
("来点轻音乐", "播放音乐"),
("播放最近流行的歌", "播放音乐"),
("放首王菲的歌", "播放音乐"),
("停止当前播放", "播放音乐"),
("换首歌吧", "播放音乐"),
("给我来首欢快的曲子", "播放音乐"),
("播放列表里的下一首歌", "播放音乐"),
("我想听周杰伦的歌", "播放音乐"),
("打开音乐播放器放歌", "播放音乐"),
("放首歌听听呗", "播放音乐"),
# 设置闹钟(20条样本)
("明天早上7点叫我起床", "设置闹钟"),
("定一个早上的闹钟", "设置闹钟"),
("半小时后提醒我", "设置闹钟"),
("取消明天的闹钟", "设置闹钟"),
("帮我设个下午3点的提醒", "设置闹钟"),
("早上6点半叫我", "设置闹钟"),
("定一个明天8点的闹钟", "设置闹钟"),
("取消所有闹钟", "设置闹钟"),
("1小时后提醒我开会", "设置闹钟"),
("设个晚上10点的闹钟", "设置闹钟"),
("明天早上别叫我了", "设置闹钟"),
("定个周末9点的闹钟", "设置闹钟"),
("半小时后提醒我吃药", "设置闹钟"),
("帮我取消下午的闹钟", "设置闹钟"),
("早上7点叫醒我,谢谢", "设置闹钟"),
("设一个每天8点的闹钟", "设置闹钟"),
("20分钟后提醒我", "设置闹钟"),
("取消早上的闹钟", "设置闹钟"),
("定个下午5点的提醒", "设置闹钟"),
("明天6点半的闹钟别忘了", "设置闹钟"),
# 发送消息(20条样本)
("给妈妈发个短信", "发送消息"),
("帮我联系张三", "发送消息"),
("告诉小李我晚点到", "发送消息"),
("发微信给同事", "发送消息"),
("给爸爸打电话", "发送消息"),
("帮我给老王发条信息", "发送消息"),
("联系一下李四", "发送消息"),
("给女朋友发个微信", "发送消息"),
("告诉妈妈我今晚不回家", "发送消息"),
("给客户打个电话", "发送消息"),
("发个短信给小明", "发送消息"),
("帮我联系一下张经理", "发送消息"),
("告诉同事会议推迟了", "发送消息"),
("给老婆发个微信说晚点回", "发送消息"),
("打电话给爸爸", "发送消息"),
("给同学发条信息问作业", "发送消息"),
("联系客户确认订单", "发送消息"),
("告诉小李明天见", "发送消息"),
("发微信给闺蜜", "发送消息"),
("帮我给老师发条短信请假", "发送消息")
]
# --------------------------
# 2. 文本预处理(分词+去停用词)
# --------------------------
# 中文停用词表(简单示例)
stopwords = {"的", "了", "吗", "呀", "吧", "我", "给", "帮", "个", "是", "在", "到"}
def preprocess_text(text):
# 1. 分词
words = jieba.cut(text) # 精确分词
# 2. 过滤停用词和标点
filtered_words = [word for word in words if word.strip() and word not in stopwords]
# 3. 拼接为字符串(供TF-IDF使用)
return " ".join(filtered_words)
# 处理数据
df = pd.DataFrame(data, columns=['text', 'intent'])
df['processed_text'] = df['text'].apply(preprocess_text) # 新增预处理后的文本列
# --------------------------
# 3. 划分数据集
# --------------------------
X = df['processed_text']
y = df['intent']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y) # stratify保证类别比例
# --------------------------
# 4. 构建模型(TF-IDF+逻辑回归,带超参数调优)
# --------------------------
# 模型管道:TF-IDF向量化 + 逻辑回归(逻辑回归在文本分类中通常优于朴素贝叶斯)
pipeline = Pipeline([
('tfidf', TfidfVectorizer(ngram_range=(1, 2))), # 加入2-gram捕捉短语(如“天气预报”)
('clf', LogisticRegression(max_iter=1000, class_weight='balanced')) # 平衡类别权重,处理潜在不平衡
])
# 超参数网格搜索(优化模型)
param_grid = {
'tfidf__min_df': [1, 2], # 最小文档频率
'tfidf__max_df': [0.9, 1.0], # 最大文档频率
'clf__C': [0.1, 1, 10] # 正则化强度(越小正则化越强)
}
# 网格搜索+5折交叉验证
grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring='f1_macro', n_jobs=-1)
grid_search.fit(X_train, y_train)
# 最佳模型
best_model = grid_search.best_estimator_
print(f"最佳参数: {grid_search.best_params_}")
# --------------------------
# 5. 模型评估
# --------------------------
y_pred = best_model.predict(X_test)
print(f"\n模型准确率: {accuracy_score(y_test, y_pred):.2f}")
print("\n分类报告:")
print(classification_report(y_test, y_pred))
# --------------------------
# 6. 规则补充(处理边缘案例)
# --------------------------
def predict_intent(text):
# 先尝试规则匹配(优先级高于模型)
text_lower = text.lower()
if any(keyword in text_lower for keyword in ["天气", "下雨", "气温", "温度", "预报"]):
return "查询天气", 1.0 # 明确关键词直接返回
if any(keyword in text_lower for keyword in ["歌", "音乐", "播放", "暂停", "切换"]):
return "播放音乐", 1.0
# 规则未匹配则用模型预测
processed_text = preprocess_text(text)
intent = best_model.predict([processed_text])[0]
confidence = max(best_model.predict_proba([processed_text])[0])
return intent, confidence
# --------------------------
# 7. 测试新句子
# --------------------------
test_sentences = [
"上海明天会下雨吗?",
"播放一首摇滚乐",
"明天早上6点叫醒我",
"给女朋友发条信息",
"杭州的天气如何?",
"取消我的闹钟",
"明儿北京冷不冷呀", # 口语化+分词测试
"帮我放首周杰伦的歌",
"30分钟后提醒我开会",
"发微信告诉妈妈我晚点回"
]
print("\n意图预测结果:")
for sentence in test_sentences:
intent, confidence = predict_intent(sentence)
print(f"句子: {sentence}")
print(f"意图: {intent}, 置信度: {confidence:.2f}\n")
运行后返回内容:
最佳参数: {'clf__C': 0.1, 'tfidf__max_df': 0.9, 'tfidf__min_df': 1}
模型准确率: 1.00
分类报告:
precision recall f1-score support
发送消息 1.00 1.00 1.00 4
播放音乐 1.00 1.00 1.00 4
查询天气 1.00 1.00 1.00 4
设置闹钟 1.00 1.00 1.00 4
accuracy 1.00 16
macro avg 1.00 1.00 1.00 16
weighted avg 1.00 1.00 1.00 16
意图预测结果:
句子: 上海明天会下雨吗?
意图: 查询天气, 置信度: 1.00
句子: 播放一首摇滚乐
意图: 播放音乐, 置信度: 1.00
句子: 明天早上6点叫醒我
意图: 设置闹钟, 置信度: 0.30
句子: 给女朋友发条信息
意图: 发送消息, 置信度: 0.28
句子: 杭州的天气如何?
意图: 查询天气, 置信度: 1.00
句子: 取消我的闹钟
意图: 设置闹钟, 置信度: 0.30
句子: 明儿北京冷不冷呀
意图: 查询天气, 置信度: 0.26
句子: 帮我放首周杰伦的歌
意图: 播放音乐, 置信度: 1.00
句子: 30分钟后提醒我开会
意图: 设置闹钟, 置信度: 0.27
句子: 发微信告诉妈妈我晚点回
意图: 发送消息, 置信度: 0.29
724

被折叠的 条评论
为什么被折叠?



