当前位置: 首页 > news >正文

课题学习笔记2——中华心法问答系统

1 任务

进行环境配置,对基本代码进行阅读,理解代码的结构、主要功能模块的代码实现。

该系统是基于语义相似度的问答系统。利用BERT 将文本(问题)转化为具有强语义表示能力的向量。

该系统核心目标是:当用户输入一个查询问题时,系统能从已有的问答库中找到与查询语义最相似的问题,并返回对应的答案。

2 系统主要流程

2 代码分析

2.1 导入和库

  • 核心库: Python 的标准库, oscsvjson,处理文件 I/O 操作和数据存储。

  • 自然语言处理(NLP):使用 jieba 库进行中文分词,torch 用于深度学习处理。

  • Transformers:使用 Hugging Face 的 transformers 库加载 BERT(双向编码器表示模型),用于文本嵌入和分类。

  • Flask:使用 Flask 框架来提供一个 Web 服务接口,供用户通过 HTTP 请求访问问答系统。

2.2 类与关键功能

TagConfig

  • 功能:该类负责加载包含标签信息(一级标签和二级标签)的 CSV 文件,将标签信息存储在集合和字典中。

  • 方法

    加载并处理 CSV 文件,提取一级标签和二级标签,并将其存储为 LEVEL1LEVEL2

Config

  • 功能:配置类,用于存储应用程序中使用的常量和路径,包括 BERT 模型路径、QA 文件路径、停用词文件路径以及其他系统参数。

QASystem

  • 功能:核心类,负责管理问答对、查询模型并返回结果。

  • 方法

    • _load_model():加载 BERT 的 tokenizer 和模型。

    • _load_data():从 CSV 文件加载问答对和相关标签。

    • _prepare_vectors():将所有问题转换为 BERT 嵌入(向量表示)。

    • _get_embedding():计算给定查询的 BERT 嵌入。

    • search_with_tags():按选择的标签过滤搜索结果,并根据相似度对其进行排序。

    • search():基于查询进行相似度搜索,使用 BERT 嵌入和关键词匹配对结果进行排序。

(BERT在后文解释) 

API 路由(Flask 路由)

  • /:渲染首页。

  • /submit:显示提交新问题和答案的页面。

  • /search:接受一个 JSON 请求,包含问题和选择的标签,搜索并返回最相似的问题。

  • /submit_question:允许用户提交新的问题、答案和标签。输入验证通过后,会将新数据存储到 CSV 文件中,并更新内存中的数据。

2.3 文本处理与嵌入 

2.3.1  文本清洗

clean_text 函数对输入文本进行预处理,移除非字母数字字符,进行分词,并根据提供的停用词文件过滤掉停用词。

假设输入文本是:“追名逐利是欲,那对孩子和亲人的有所期待是不是欲?如果是,怎样放下?”

1. 移除非字母数字字符(保留核心文字)

  • 操作:用正则表达式去掉文本中除了 “中文、英文、数字、常见标点(?!)” 之外的符号(如逗号、引号、空格等)。

  • 效果
    原文本 → “追名逐利是欲那对孩子和亲人的有所期待是不是欲如果是怎样放下”
    (去掉了逗号、问号,只保留核心文字)

  • 为什么要做:特殊符号(如 “,”“?”)本身没有实际语义,留着会增加后续处理的 “噪音”。

2. 分词(把句子拆成单个词)

  • 操作:用 jieba.posseg.cut 对文本进行分词(同时标注每个词的词性,如名词、动词)。

  • 效果
    处理后的文本 → [追名逐利, 是, 欲, 那, 对, 孩子, 和, 亲人, 的, 有所期待, 是, 不, 是, 欲, 如果, 是, 怎样, 放下]
    (同时标注词性:“孩子” 是名词(n),“放下” 是动词(v)等)

  • 为什么要做:计算机无法直接理解完整句子,需要拆成最小单位(词)才能进一步分析。

3. 过滤停用词(去掉无意义的 “填充词”)

  • 操作:参考 stopwords.txt 中的停用词表,过滤掉 “无实际语义、对句子意思影响极小” 的词;同时保留核心词性(名词、动词、形容词等)。

  • 停用词举例“的”“是”“那”“和”“如果”(这些词在中文里很常见,但单独存在时没有具体含义)。

  • 效果
    最终保留的词 → [追名逐利, 欲, 孩子, 亲人, 有所期待, 欲, 放下]
    (去掉了 “是”“那”“和” 等停用词,只留核心词)

  • 为什么要做:停用词会 “稀释” 核心语义。比如原句中 “的”“是” 出现多次,但去掉后不影响句子核心意思(“追名逐利、欲、孩子、亲人、期待” 才是关键)。

经过这三步处理,文本从 “冗余的句子” 变成 “简洁的核心词集合”,后续用 BERT 模型生成向量时,就能更聚焦于 “真正有意义的语义”,避免被噪音干扰。

2.3.2 BERT 嵌入

人类能通过文字直接理解语义(比如知道 “追名逐利” 和 “追求名利” 是一个意思),但计算机只能处理数字。BERT 嵌入的作用就是把文本的语义 “翻译” 成一串数字(向量),让计算机能通过比较向量的相似度,判断文本语义是否相近。

“传统问答系统常依赖关键词匹配(比如用户问‘亲人期待算欲吗?’,必须包含‘期待’‘欲’等词才能匹配),但实际中用户表述多样(比如‘对家人的期望是不是欲望?’),容易漏检。
因此,引入 BERT 模型 —— 它能理解文本语义,把‘意思相近但表述不同’的问题映射到相似的向量,从根本上解决关键词匹配的局限性。”

BERT 嵌入的过程:
“文本→标记化(拆成模型能懂的单位)→多层语义计算(获取不同层面的理解)→加权融合(综合多层语义)→最终向量(语义的数字表达)”

  • 第一步:文本预处理
    “用户输入或知识库中的问题,会先经过 clean_text 函数清洗:去除逗号、引号等无关符号,用结巴分词拆分成词语,再过滤‘的’‘是’等停用词,只保留核心词汇(如名词、动词)。这一步是为了减少噪音,让 BERT 更专注于有意义的内容。”

  • 第二步:BERT 生成语义向量
    “清洗后的文本会通过 BERT 转化为向量:
    ① 标记化:把文本拆成 BERT 能识别的小单位(比如‘对亲人的期待’拆成‘[CLS]、对、亲人、的、期待、[SEP]’),并转化为数字编码;
    ② 提取多层语义:BERT 的 12 层神经网络会输出不同深度的特征(底层抓字面意思,高层抓抽象语义);
    ③ 融合优化:最后 4 层特征按权重融合(权重 [0.15, 0.25, 0.35, 0.25]),既保留字面信息,又突出深层语义,最终生成 768 维的语义向量。”

  • 第三步:基于向量的问答匹配
    “系统启动时,会提前把知识库中所有问题的向量计算好;用户提问时,实时生成问题向量,通过计算‘余弦相似度’找到最相似的已有问题,返回对应的答案。比如‘对孩子的期待是不是欲?’和‘亲人的期待属于欲望吗?’的向量相似度很高,会匹配到同一个答案。”

2.4 相似度计算与排序

  • 余弦相似度:系统使用余弦相似度来比较问题的嵌入,并按相似度对结果进行排序。

  • 校准相似度:使用sigmoid函数对原始相似度进行校准,以提高排序准确性。

原始余弦相似度可能存在 “区分度不足” 的问题:比如两个答案的相似度分别是 0.8 和 0.82,原始差异很小,难以判断哪个更优。
逻辑函数(Sigmoid 函数)的作用是放大相似与不相似的差距,让排序更明确。

  • 关键词匹配:此外,系统还通过关键词匹配来进一步优化搜索结果。

BERT 向量擅长捕捉深层语义,但有时会忽略 “字面强相关” 的情况(比如用户问题和答案包含完全相同的核心词,理应优先匹配)。
关键词匹配的作用是补充字面信息,强化 “核心词重叠” 的答案权重

2.5 提交新的问答对

  • 用户可以通过 /submit_question 提交新的问题和答案。系统会验证输入内容,处理并将其存储到 CSV 文件中,此外,还会更新内存中的数据结构,供后续查询使用。

3 BERT模型详解

(参考B站视频小白也能听懂的 bert模型原理解读 预训练语言模型_哔哩哔哩_bilibili)

BERT(Bidirectional Encoder Representations from Transformers)是由 Google 在 2018 年提出的预训练语言模型,它的核心突破在于 **“双向预训练”**,彻底改变了自然语言处理(NLP)的范式。

3.1 BERT 的核心思想

是自编码模型,BERT 的核心结构是多层 Transformer 编码器(仅用 Transformer 的编码器部分,不用解码器)

  • BERT-Base:12 层 Transformer 编码器,12 个注意力头,隐藏层维度 768,总参数约 110M。
  • BERT-Large:24 层 Transformer 编码器,16 个注意力头,隐藏层维度 1024,总参数约 340M。
Transformer 编码器层

BERT 的核心计算单元是 Transformer 编码器,每层包含两个核心模块(与原 Transformer 一致):

 
  • 多头自注意力(Multi-Head Self-Attention):让每个词 “关注” 文本中其他相关词(如 “他” 关注前文的 “小明”),捕捉上下文依赖。
    原理:将输入向量拆分为多个子空间(“多头”),每个子空间独立计算注意力,再拼接结果,提升模型对不同语义关系的捕捉能力。
  • 前馈神经网络(Feed-Forward Network, FFN):对每个词的注意力输出进行非线性转换(先升维再降维),增强模型拟合能力。
 

此外,每层还包含残差连接(Residual Connection) 和层归一化(Layer Normalization),用于缓解梯度消失,加速训练。

双向预训练 + 微调

传统语言模型(如 ELMo、GPT)多为 “单向”(如 GPT 仅从左到右预测),而 BERT 通过双向 Transformer 编码器学习文本的上下文信息,实现 “真正的双向理解”。其核心流程分为两步:

  • 预训练(Pre-training):在大规模无标注文本(如维基百科)上训练模型,学习通用语言知识(语法、语义、逻辑等)。
  • 微调(Fine-tuning):针对具体任务(如文本分类、问答),用少量标注数据调整预训练模型参数,适配任务需求。

这种 “预训练 + 微调” 模式的优势:避免重复训练,用通用知识提升任务性能,尤其在小数据场景下效果显著。

3.1.1 预训练(Pre-training)

任务一:MLM(Mask Language Model)

在训练的时候随机选择一些要预测的词用mask遮掩,让模型根据标签去学习这个地方应该填的词

  随机屏蔽15%的单词,但是这样会在预训练和微调之间产生差异,因为微调中的句子没有mask标记,为解决该问题利用了“80、10、10”规则。对于随机屏蔽的15%的单词,百分之80是mask,百分之10用随机单词,剩下的百分之10保持原来的单词。将这样处理过后的数据喂给标记嵌入、片段嵌入和位置嵌入层得到输入嵌入,然后将三者相加喂给BERT模型

任务二:NSP(Next Sentence Prediction)

下一个句子的预测,在双向语言模型的基础之上增加了一个句子级别的连续性预测任务。

判断两段文本是否为连续的文本,二分类任务

BERT如何进行预训练

输入:字向量、文本向量、位置向量求和作为BERT的输入

输出:每个标记的嵌入

在transformer的encoder部分的输入Xt也是由两个向量进行相加(文本embedding+位置embedding),BERT特殊的点是有一个字向量(可以随机初始化也可以用word2vct进行预训练作为初始值),由于BERT拥有字向量可以考虑到颗粒度比较细的token信息,最后BERT将字向量、文本向量、位置向量求和作为BERT的输入,BERT返回每个标记的嵌入作为输出。

补充语言建模知识

  • 自回归语言建模:是单向的,一类为从左到右,一类为从右到左
  • 自编码语言建模:双向的,在预测时读入两端的数据

 BERT预训练目标就是预测被掩盖的词,接着将BERT预测的词输入到一个带有softmax(softmax适用于多分类,输出多个概率值,且和为 1,强制类别间为 “互斥关系”)的前馈神经网络,最后输出是各个词的概论。

预训练的本质是让 BERT 学习 “语言规律”—— 通过预测掩码词,BERT 被迫理解上下文之间的语义关联(比如 “他在吃 [MASK]” 中,结合上下文能推断出 [MASK] 可能是 “苹果”“米饭” 等)。这种学习过程让 BERT 掌握了强大的语义理解能力,而这种能力可以被迁移到各种 NLP 任务中,包括系统中的 “文本转向量”。

http://www.dtcms.com/a/293359.html

相关文章:

  • 汽车行业数字化——解读52页汽车设计制造一体化整车产品生命周期PLM解决方案【附全文阅读】
  • 记录更新时间用java的new date还是数据库的now
  • 深入理解 C 语言数据类型:从内存到应用的全面解析
  • CAN基础知识 - 进阶版
  • 消息推送功能设计指南:精准触达与用户体验的平衡之道
  • Spring Boot 中集成ShardingSphere-JDBC的基本使用
  • Kibana报错[security_exception] current license is non-compliant for [security]
  • HCIA/IP(一二章)笔记
  • TTL+日志的MDC实现简易链路追踪
  • 强化学习理论
  • 计算机是怎么样工作的
  • 在 Ubuntu 22.04 上安装并优化 Nginx nginx入门操作 稍难,需要有一定理论 多理解 多实践
  • Class13预测房价代码
  • Google Gemini 体验
  • 从零开始学CTF(第二十五期)
  • 万界星空科技铜线/漆包线行业智能化MES系统解决方案
  • postgresql导入导出数据;pg_restore: error: did not find magic string in file header
  • 基础算法思想(递归篇)
  • 厚铜板载流革命与精密压合工艺——高可靠性PCB批量制造的新锚点
  • Android AppCompat:实现Material Design向后兼容的终极指南
  • IDEA-通过IDEA导入第三方的依赖包
  • [Semantic Seg][KD]FreeKD: Knowledge Distillation via Semantic Frequency Prompt
  • Bigemap Pro自动获取面要素所属行政区划
  • XSS(跨站脚本)
  • 拓展三字棋
  • NumPy库使用教学,简单详细。
  • 星巴克推出免费自习室,拓展第三空间意欲何为?
  • Python的界面美化库 QDarkStyleSheet
  • 使用 Ansys Fluent 软件参数化工作流程对搅拌罐中的稳态涡流进行仿真
  • 大模型后训练——DPO实践