【自然语言处理】基于python的问答系统实现

news2024/10/5 14:20:39

一,文件准备

        该问答系统是基于已知的问题和其一一对应的答案进行实现的。首先需要准备两个文本文件,分别命名为“question.txt”和“answer.txt”,分别是问题文件和答案文件,每一行是一个问题以及对应的答案。

        问题文件:

                中国的首都是哪个城市?

                今天气温多少度?

                天津距离北京有多远?

                小明正在干什么?

        答案文件:

                北京市

                26度

                135公里

                在上课

二,实现原理

(1)导入模块

import jieba
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer

(2)读取数据集:输入为文件名,输出为列表

def read_corpus(file):
    lt = []
    with open(file, 'r', encoding='utf-8') as f:
        for line in f:
            lt.append(line.strip())
return lt

执行结果:

>>> q_list = read_corpus("questions.txt")

>>> q_list

['中国的首都是哪个城市?', '今天气温多少度?', '天津距离北京有多远?', '小明正在干什么?']

>>> a_list = read_corpus("answers.txt")

>>> a_list

['北京市', '26度', '135公里', '在上课']

(3)分词

def preprocess_text(q_list):
    lt = []
    for q in q_list:
        q = word_segment(q)
        lt.append(q)
return lt

preprocess_text()函数将列表q_list中的句子逐个切词,并放入lt列表中。

在preprocess_text()函数调用word_segment()函数。

def word_segment(sentence):
return ",".join(jieba.cut(sentence))

>>> s = "今天气温多少度?"

>>> word_segment(s)

'今天,气温,多少度,?'

将(2)中的q_list作为参数,传递给preprocess_text(),执行结果如下:

>>> q_list = preprocess_text(q_list)

>>> q_list

['中国,的,首都,是,哪个,城市,?', '今天,气温,多少度,?', '天津,距离,北京,有多远,?', '小明,正在,干什么,?']

4)将问题列表q_list向量化,计算每一个特征的权重

def convert2tfidf(q_list):
    vectorizer, q_tfidf = calc_tfidf(q_list)
return vectorizer, q_tfidf

def calc_tfidf(q_list, ngram_range=(1, 1)):
    # 实例化一个tfidf对象
    vectorizer = TfidfVectorizer(min_df=1, norm='l2', \
                                 smooth_idf=True, \
                                 use_idf=True, \
                                 ngram_range=ngram_range)
    # 计算每个词的tfidf值
    features = vectorizer.fit_transform(q_list)
return vectorizer, features

将(3)中的问题列表q_list作为参数,传递给convert2tfidf()函数

>>> vectorizer, q_tfidf = convert2tfidf(q_list) # vectorizer是一个向量化器

>>> type(q_tfidf) # q_tfidf是一个稀疏矩阵

<class 'scipy.sparse.csr.csr_matrix'>

>>> q_tfidf.toarray().round(2) # 将稀疏矩阵转化为普通矩阵,保留两位小数

array([[0.5, 0., 0., 0.5, 0.5, 0., 0., 0., 0., 0., 0., 0., 0., 0.5],

[0., 0.58, 0., 0., 0., 0.58, 0., 0., 0., 0., 0., 0.58, 0., 0.],

[0., 0., 0.5, 0., 0., 0., 0.5, 0., 0., 0.5, 0., 0., 0.5, 0.],

[0., 0., 0., 0., 0., 0., 0., 0.58, 0.58, 0., 0.58, 0., 0., 0.]])

>>> q_tfidf.toarray()[0] # 查看q_tfidf矩阵的第一行

array([0.5, 0. , 0. , 0.5, 0.5, 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.5])

上述矩阵就是问题“中国的首都是哪个城市?”向量化后的结果。

>>> vectorizer.vocabulary_ # 向量化器vectorizer的词典

{'中国': 0, '首都': 13, '哪个': 3, '城市': 4, '今天': 1, '气温': 11, '多少度': 5, '天津': 6, '距离': 12, '北京': 2, '有多远': 9, '小明': 7, '正在': 10, '干什么': 8}

由上述可知,向量的第一个特征是“中国”,第二个特征是“今天”,第三个特征是“北京”,依次类推其他特征。

(5)响应用户的“查询”

def answer(query):
    query = word_segment(query)				# 对查询语句进行切词
    query = vectorizer.transform([query])		# 将查询语句向量化
    best_idx = idx_of_largest_sim(query, q_tfidf)	# 得到与查询语句最相似问题的下标
return a_list[best_idx]						# 返回与best_idx下标对应的答案
def idx_of_largest_sim(query, q_tfidf): 			# 下标idx = index
    lt = []
    # 将query由稀疏矩阵转为普通矩阵,并取其第1行,此处目的是将其转为一维矩阵。
    query = query.toarray()[0]  				# 其实query二维矩阵只有一行
    for q in q_tfidf:
        q = q.toarray()        				# 将q由稀疏矩阵转换为普通矩阵
        num = float(np.matmul(q, query))    	# 计算矩阵的点积
        denom = np.linalg.norm(q) * np.linalg.norm(query)	
        if denom == 0:
            cos = 0.0
        else:
            cos = num / denom				# 规范化,denom分母
        lt.append(cos)
    best_idx = lt.index(max(lt))
    return best_idx						# 返回值是与查询语句最相似的问题下标
np.linalg.norm(q)是问题向量的长度:

>>> np.linalg.norm([1, 3, 2])

3.7416573867739413

上述代码计算了1的值

np.linalg.norm(q)是查询向量的长度

三,完整代码

import jieba
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer

def read_corpus(file):
    lt = []
    with open(file, 'r', encoding='utf-8') as f:
        for line in f:
            lt.append(line.strip())
    return lt

def preprocess_text(q_list):
    lt = []
    for q in q_list:
        q = word_segment(q)
        lt.append(q)
    return lt

# 度量查询query与问题库中各个问题的相似程度similarity
def idx_of_largest_sim(query, q_tfidf): # idx = index
    lt = []
    # 将query由稀疏矩阵转换为普通矩阵,并取其第1行
    query = query.toarray()[0]  
    for q in q_tfidf:
        q = q.toarray()         # 将q由稀疏矩阵转换为普通矩阵
        num = float(np.matmul(q, query))    # 计算矩阵的点积
        denom = np.linalg.norm(q) * np.linalg.norm(query)
        if denom == 0:
            cos = 0.0
        else:
            cos = num / denom
        lt.append(cos)
    best_idx = lt.index(max(lt))
    return best_idx

def calc_tfidf(q_list, ngram_range=(1, 1)):
    # 实例化一个tfidf对象
    vectorizer = TfidfVectorizer(min_df=1, norm='l2', \
                                 smooth_idf=True, \
                                 use_idf=True, \
                                 ngram_range=ngram_range)
    # 计算每个词的tfidf值
    features = vectorizer.fit_transform(q_list)
    return vectorizer, features

def convert2tfidf(q_list):
    vectorizer, q_tfidf = calc_tfidf(q_list)
    return vectorizer, q_tfidf

def word_segment(sentence):
    return ",".join(jieba.cut(sentence))

def answer(query):
    query = word_segment(query)
    query = vectorizer.transform([query])
    best_idx = idx_of_largest_sim(query, q_tfidf)
    return a_list[best_idx]

if __name__ == "__main__":
    q_list = read_corpus("questions.txt")    # 问题列表
    a_list = read_corpus("answers.txt")      # 答案列表
    # 分词后的问题列表,每个问题的分词字符串为一个列表元素
    q_list = preprocess_text(q_list)
    vectorizer, q_tfidf = convert2tfidf(q_list)
    
    flag = True
    while flag:
        print("\n请输入查询,输入结束后按回车键:")
        query = input()
        if query.lower() == 'q':
            break
        print("正在为您查询,请稍后!")
        print("查询结果:", answer(query), sep="")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1189397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytorch模型使用与修改、保存与加载

模型的使用及修改、保存与加载 以图像处理中torchvision为例&#xff0c;PyTorch通过torchvision.models模块提供了更多的预训练模型. 在图像分类当中&#xff0c;包括许多模型 import torchvision import warnings import torch warnings.filterwarnings("ignore&quo…

3D Gaussian Splatting:用于实时的辐射场渲染

Kerbl B, Kopanas G, Leimkhler T, et al. 3d gaussian splatting for real-time radiance field rendering[J]. ACM Transactions on Graphics (ToG), 2023, 42(4): 1-14. 3D Gaussian Splatting 是 Siggraph 2023 的 Best Paper&#xff0c;法国团队在会议上展示了其实现的最…

软件测试|iOS 自动化测试——技术方案、环境配置

移动端的自动化测试&#xff0c;最常见的是 Android 自动化测试&#xff0c;我个人觉得 Android 的测试优先级会更高&#xff0c;也更开放&#xff0c;更容易测试&#xff1b;而 iOS 相较于 Android 要安全稳定的多&#xff0c;但也是一个必须测试的方向&#xff0c;这个系列文…

Bean作用域

从笔者之前的博客&#xff0c;我们可以看出 Spring 是⽤来读取和存储 Bean&#xff0c;因此在 Spring 中 Bean 是最核⼼的操作 资源&#xff0c;所以接下来我们深⼊学习⼀下 Bean 对象&#xff1a;Bean作用域&#xff01; 限定程序中变量的可用范围叫做作用域&#xff01;或者…

【遮天】荒古禁地采取圣药,姬老自己走上绝路,故事扣人心悬

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 深度爆料&#xff0c;《遮天》动漫第30话最新剧情解析&#xff0c;姬云峰&#xff0c;姬家的长老&#xff0c;地位崇高&#xff0c;深受家族成员的尊敬和信赖。他的智慧和经验在家族中享有极高的声望&#xf…

【MATLAB源码-第72期】基于matlab的OFDM-IM索引调制系统在高斯,瑞利,莱斯信道误码率对比,对比传统OFDM系统。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OFDM-IM索引调制技术是一种新型的无线通信技术&#xff0c;它将正交频分复用&#xff08;OFDM&#xff09;和索引调制&#xff08;IM&#xff09;相结合&#xff0c;以提高频谱效率和系统容量。OFDM-IM索引调制技术的基本思想…

【字符串】【完整程序+倒序输出+每个区间倒序输出】KamaCoder55

【字符串】【完整程序倒序输出每个区间倒序输出】KamaCoder55 解法1 完整程序书写kama 倒序输出每个区间倒序输出 ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f388;------------------- 解法1 完整程序书写kama 倒序输出每个区间倒序输出 时间…

docker部署redis6

前言&#xff1a;在离线服务器上&#xff08;无联网&#xff09;&#xff0c;部署redis的方式&#xff0c;采用docker是比较方便的。下面将描述如何使用docker部署单机版redis 环境&#xff1a;centos 7 redis&#xff1a;6.2.14 docker&#xff1a;20.10.9 1.下载 redis 镜像…

取产品之道、赚效率的钱,锅圈万店背后的赢家法则

万店&#xff0c;一个真正意义上的规模壁垒&#xff0c;当它出现在任何行业时&#xff0c;都意味着这个玩家身上存在许多领先于行业的优势。 这一点&#xff0c;在刚于近日登录港交所的锅圈食品&#xff08;以下简称“锅圈”&#xff09;身上尤其明显——2017年&#xff0c;锅…

浅谈插接母线温度在线监测系统研究与应用-安科瑞黄安南

摘要 低压封闭式插接母线是供配电设施的关键部件&#xff0c;安装在生产车间内部高空&#xff0c;不易保养和维护&#xff0c;在安装不良或保养不当时易发生故障。插接点温度的异常变化与母线故障的发生有着密切的关系&#xff0c;以汽车整车制造工厂为例&#xff0c;提出母线接…

梓航DIY无限建站-3.5.8(企业官网 应用首页 PC建站 14套模板切换,自由组合页面,无限多开)

梓航DIY无限建站是一款支持无限建站的公众号应用。 自定义网址 全局样式设置 极速建站 更灵活 更方便。 1、默认页面指定设置&#xff0c;更灵活、更方便&#xff1b; 2、全局样式设置&#xff0c;减少页面重复设置工作&#xff1b; 3、不限数量网站制作装修&#xff08;想做…

VR虚拟现实:VR技术如何进行原型制作

VR虚拟现实原型制作 利用VR虚拟现实软件进行原型制作可以用于增强原型测试期间的沉浸感&#xff0c;减少产品设计迭代次数&#xff0c;并将与产品原型制作相关的成本降低40-65%。 VR虚拟现实原型制作市场规模 用于原型制作的虚拟现实 (VR) 市场在 2017 年估计为 2.104 亿美元…

ChineseChess.2023.11.09.01

中国象棋残局模拟器ChineseChess.2023.11.09.01

淘宝天猫京东苏宁1688等平台关键词监控价格API接口(店铺商品价格监控API接口调用展示)

淘宝天猫京东苏宁1688等平台关键词监控价格API接口&#xff08;店铺商品价格监控API接口调用展示&#xff09;代码对接如下&#xff1a; item_get-获得淘宝商品详情 公共参数 请求地址: https://o0b.cn/anzexi 名称类型必须描述keyString是调用key&#xff08;必须以GET方式…

Android系统中设置TextView的行间距

Android系统中TextView默认显示中文时会比较紧凑&#xff0c;不是很美观。 为了让每行保持一定的行间距&#xff0c;可以设置属性android:lineSpacingExtra或android:lineSpacingMultiplier。 1、设置行间距&#xff1a;android:lineSpacingExtra&#xff0c;取值范围&#xf…

VsCode的一些配置

tab提示 代码的清晰显示

ZYNQ_project:key_breath

[Synth 8-327] inferring latch for variable led_breath_reg ["C:/Users/warrior/Desktop/ZYNQ/pl/key_breath/rtl/led_breath.v":66] 因为在组合逻辑中&#xff0c;用了非阻塞赋值的方式赋值信号。 组合逻辑自己给自己赋值会产生组合回环&#xff0c;输出不稳定。 …

Python(四)字符串

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…