高级数据库 项目流程记录
md文件中的问题回答记录在文件里面了,不在笔记里。
选择了project1:
任务总体描述
对于一个CMRC2018数据集,使用向量模型对该数据集进行向量化,构建向量数据库并使用向量数据库对向量化后的数据进行索引和存储。最后对于用户输入的问题,应该在数据库中检索与问题最相关的QA对并输出该QA对。
具体任务如下:
1. 说明使用的环境,使用的模型和向量数据库。
2. 分别说明预处理数据集,向量化数据集,索引和存储到向量数据库的方式。对于向量数据库,应该在代码层面体现如何存储和读取数据库。
3. 思考不同的相关度算法的优缺点,尝试解决其缺点。
4. 说明如何构建根据用户问题检索相关QA对的相关性算法,并对算法进行性能分析。性能分析包括但不限于:
- 当一个问题在语义不变的情况下被重写,算法能否正确检索。
- 当一个问题语义上不相关,但有关键词命中时,算法能否正确检索。
将问题交给了gpt,得到以下答复:
gpt给出的整体思路
这个实验可以分为几个主要步骤。以下是每个步骤的具体操作和思路:
1. 环境、模型与向量数据库的选择
- 环境:推荐使用 Python,并且安装必要的库,如
transformers
、faiss
或chroma
、sentence-transformers
等。 - 模型选择:可以使用 BERT 或 RoBERTa 等预训练模型,它们在句子嵌入方面表现较好。特别推荐
sentence-transformers
提供的预训练模型distilbert-base-nli-stsb-mean-tokens
,专为句子向量化设计,适合 QA 数据。 - 向量数据库:可以选择 FAISS 或 Chroma,它们在大规模向量检索中效果不错。FAISS 适合离线检索,Chroma 更适合在线和大规模分布式环境。
2. 数据集预处理、向量化、索引与存储
数据预处理:
- 对 CMRC2018 数据集进行清洗,提取出问题(Q)、段落(P)和答案(A)。
- 将每个 QA 对分为
(Q, A)
或(P, Q, A)
的形式,统一结构。
向量化:
- 使用选定的模型对每个 QA 对进行编码。可以用
sentence-transformers
中的模型,将每个问题和答案对向量化得到其句向量表示:python
复制代码
from sentence_transformers import SentenceTransformer model = SentenceTransformer('distilbert-base-nli-stsb-mean-tokens') embeddings = model.encode([qa['question'] + " " + qa['answer'] for qa in dataset])
索引与存储:
-
创建向量数据库(以 FAISS 为例):
python
复制代码
import faiss import numpy as np # 假设 embeddings 是二维 numpy 数组,每行是一个向量化的QA对 dimension = embeddings.shape[1] index = faiss.IndexFlatL2(dimension) index.add(np.array(embeddings)) faiss.write_index(index, "qa_index.faiss")
-
读取和查询数据库:
python
复制代码
index = faiss.read_index("qa_index.faiss") query_embedding = model.encode("用户的查询问题") D, I = index.search(np.array([query_embedding]), k=5) # 返回 top-5 个结果
3. 相关度算法分析与改进
常用的相似度算法有以下几种:
- 欧几里得距离(L2):简单直接,但可能对语义相似度表现欠佳。
- 余弦相似度:更适合高维向量、句子或文档相似度,但在向量较短或稀疏时效果可能下降。
- 点积相似度:计算快,但受向量长度影响,需要正则化。
改进: 可以在相似度算法上加入一些加权处理,例如针对常见停用词的降权处理,或通过细化模型来使模型对重要词的匹配更加敏感。
4. 基于用户问题的检索及性能分析
构建用户问题的检索流程如下:
- 预处理用户输入:将用户输入向量化。
- 在数据库中检索最相关的 QA 对:
python
复制代码
user_query = "用户的问题" query_embedding = model.encode(user_query) D, I = index.search(np.array([query_embedding]), k=5) # 输出结果 results = [dataset[i] for i in I[0]]
性能分析:
- 语义等效重写:可以测试同义词、短语替换等,检查模型是否能返回一致的结果。
- 关键字误导:通过引入一些无关问题但含关键词的输入,测试模型对无关问题的鲁棒性。
- 准确率与召回率:对于已知答案的测试集,通过准确率和召回率来定量评估模型表现。
通过这些步骤,您可以完成这个实验并进一步分析算法的适用性和性能。
下一步是下载数据集。
数据集下载
CMRC 2018: 中文阅读理解数据集入门指南-CSDN博客
https://github.com/ymcui/cmrc2018/blob/master/README_CN.md
主要参考了上面两个文章。通过第二个的教程,通过huggingface的dataset库快速下载的数据集。
数据集保存在了C:\Users\<用户名>\.cache\huggingface\datasets目录中,只有20MB,存在c盘也没关系。
代码书写
就按照gpt给出的思路写就可以了。
有几个关键点:
#获取相似QA对的索引
index = faiss.read_index("qa_index.faiss")
#默认使用了IndexFlatL2(L2 距离)来计算向量距离,用print(type(index))来知晓。
欧几里得距离(L2 距离):
- 定义:度量两个向量之间的直线距离。
- 优点:计算简单,适用于标准化的向量。
- 缺点:对长度敏感,若两个向量方向相近但模长不同,可能导致较大的距离。
print('本次提问为:',test_quary)
query_embedding = model.encode(test_quary)
D, I = index.search(np.array([query_embedding]), k=1) # 返回 top-1 个结果
#这里返回的是距离和索引。
算法与改进
常见的相似度算法
-
余弦相似度(Cosine Similarity):
- 定义:通过计算两个向量的夹角余弦值来度量相似度。余弦值越接近 1,相似度越高。
- 优点:特别适合高维空间中稠密向量的相似度计算,因为它只关注向量的方向,不受向量长度影响。
- 缺点:当向量较稀疏或维度较低时,效果可能不如其他方法。
-
欧几里得距离(L2 距离):
- 定义:度量两个向量之间的直线距离。
- 优点:计算简单,适用于标准化的向量。
- 缺点:对长度敏感,若两个向量方向相近但模长不同,可能导致较大的距离。
-
点积(Dot Product):
- 定义:将两个向量的对应元素相乘并求和。
- 优点:计算高效,可以用于已正则化的向量。
- 缺点:对向量长度敏感,通常需要先将向量归一化。
改进方法
-
归一化处理:如果使用欧几里得距离或点积,向量归一化可以减少因长度不同带来的影响,使得不同文本的相似度比较更合理。
-
加权余弦相似度:有时可以对关键字或重要词语赋予更高的权重,例如通过 TF-IDF 加权来增强这些词的相似度计算权重,使模型更加关注问题中的关键信息。
-
使用训练好的相似度模型:在一些高级应用中,我们可以使用专门的模型来学习相似度,例如利用 Siamese Network(孪生神经网络)或 Triplet Loss(三元组损失)模型进行微调,使得模型在特定任务下学会分辨相似和不同的文本对。
默认方法是欧几里得距离(L2 距离)。只需要index = faiss.read_index("qa_index.faiss")就可以了。