AI入门学习--用python实现意图识别

1、意图识别基础知识

1.1意图识别是什么

意图识别是自然语言处理(NLP)中的一项核心任务,旨在从用户的文本或语音输入中,自动识别其潜在的目的或需求。简单来说,就是让机器 “理解” 用户说这句话想做什么,比如是想查询信息、下达指令、表达情感,还是提出请求等。通过分析用户输入的语言(词汇、语法、语境等),将其归类到预定义的意图类别中。

1.2意图识别的应用场景

  1. 智能客服:识别用户的咨询意图(如投诉、查询订单、售后问题),自动转接对应服务或提供解决方案。
  2. 语音助手:如 Siri、小爱同学,通过识别用户意图(如设置闹钟、播放音乐、导航)执行相应操作。
  3. 聊天机器人:在对话中理解用户的核心需求(如闲聊、寻求建议、获取知识),生成合适的回应。
  4. 智能推荐:根据用户的搜索或提问意图(如找电影、买衣服),推荐相关内容或商品。

1.3意图识别的实现方法

  1. 基于规则的方法
    通过人工定义关键词或模板来匹配意图。例如,包含 “天气”“温度” 的句子归为 “查询天气” 意图;包含 “订”“买”“预约” 的句子归为 “预订 / 购买” 意图。

    • 优点:简单易实现,解释性强。
    • 缺点:覆盖范围有限,难以处理复杂句式或歧义,维护成本高(需不断更新规则)。
  2. 基于机器学习的方法
    将意图识别视为分类问题,通过标注好的训练数据(输入文本 + 对应意图标签)训练分类模型。常见模型包括:

    • 传统机器学习:如支持向量机(SVM)、朴素贝叶斯,需先对文本进行特征工程(如提取词袋、TF-IDF 特征)。
    • 深度学习:如循环神经网络(RNN)、卷积神经网络(CNN)、BERT 等预训练模型,可自动学习文本的深层语义特征,处理复杂语境的能力更强。
    • 优点:泛化能力强,能处理多样的表达方式。
    • 缺点:需要大量标注数据,模型训练和调优成本较高。
  3. 混合方法
    结合规则和机器学习的优势,例如用规则处理明确的简单意图,用模型处理模糊或复杂的意图,提高识别准确率。

1.4意图识别的挑战

  • 歧义性:同一表达可能对应多个意图,如 “苹果多少钱” 可能是问水果价格,也可能是问苹果手机价格。
  • 口语化与不规范性:用户输入可能包含错别字、缩写、方言或不完整句子(如 “明儿去广州,票”)。
  • 领域依赖性:不同领域的意图差异大(如电商领域的 “退换货” 和医疗领域的 “挂号”),模型需针对特定领域优化。
  • 上下文关联:部分意图需要结合对话历史才能确定,例如用户说 “帮我取消它”,需结合前文知道 “它” 指的是订单还是预约。

2、代码实战

2.1代码实现原理

  1. 数据准备:我们创建了一个小型数据集,包含四种意图(查询天气、播放音乐、设置闹钟、发送消息)和每种意图对应的例句。

  2. 文本预处理(分词+去停用词):使用jieba进行准确分词,过滤标点、停用词。

  3. 特征提取:使用 TF-IDF(词频 - 逆文档频率)将文本转换为数值特征,这有助于捕捉词语在句子中的重要性。或者使用预训练词向量,捕捉深层语义。

  4. 结合规则系统:对高频明确意图(如含 “天气”→查询天气)用规则兜底,减少模型错误。

  5. 模型训练:使用朴素贝叶斯分类器、或者逻辑回归、SVM,或深度学习模型。

  6. 模型评估:通过准确率和分类报告评估模型性能,查看模型在不同意图上的识别效果。

  7. 预测功能:实现了一个函数,可以对新的句子进行意图预测并返回置信度。

2.2提高意图识别准确率措施

  1. 扩充与优化训练数据

    • 增加样本数量:每个意图至少包含 50 + 样本
    • 增强样本多样性:覆盖同义词、不同句式、口语化表达(如 “明儿”“咋” 等)。
    • 数据增强:通过同义词替换、句式变换(主动 / 被动)、随机插入虚词等生成新样本。
  2. 精细化文本预处理

    • 中文分词:使用jieba进行准确分词(中文无空格,分词是基础)。
    • 去除噪声:过滤标点、停用词(如 “的”“吗”)、特殊符号。
    • 标准化:小写转换、错别字修正(可选)。
  3. 升级特征表示

    • 替换 TF-IDF:使用预训练词向量(如 Word2Vec、GloVe)或上下文感知嵌入(如 BERT),捕捉深层语义。
  4. 选择更优模型

    • 使用逻辑回归、SVM,或深度学习模型(如 LSTM、BERT 微调),这些模型对语义的理解更强。
  5. 结合规则系统

    • 对高频明确意图(如含 “天气”→查询天气)用规则兜底,减少模型错误。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值