Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
XinyuDu committed Aug 23, 2024
1 parent 003a559 commit 94c6fb9
Showing 1 changed file with 77 additions and 28 deletions.
105 changes: 77 additions & 28 deletions _teaching/2024-RL-DQN.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,102 @@
---
title: "神经网络出现后的强化学习(深度强化学习)-DQN(deep Q-network)算法-2"
title: "BM25在RAG场景上的优化"
collection: teaching
type: "强化学习教程-3"
permalink: /teaching/2022-RL-3
venue: "杜新宇,联通"
type: "RAG-1"
permalink: /teaching/2024-RAG-1
venue: "杜新宇,中国联通AI创新中心"
date: 2024-08-23
location: "中国, 北京"
---

<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script>

## 1.神经网络
# BM25 for RAG with Milvus

### 1.1 网络结构
## 1. TF-IDF

神经网络就是由输入层,隐藏层和输出层构成,如下图所示。一个神经网络只有一个输入层和一个输出层,可以有多个隐藏层。圆圈内的符号$$b_j^l$$是偏移量,上角标为所处的层数,下角标为位于本层从上到下数第几个。连线上的符号$$w_{jk}^l$$是权重,上角标表示箭头指向的神经元所处的层数,下角标第一个数字代表箭头指向的神经元所处的位置,第二个数字代表发起箭头的神经元所处的位置。输出箭头上的符号$$a_j^l$$表示第l层,第j个神经元的激活函数。
TF-IDF中TF代表词频,IDF代表逆词频。一个关键词x,在某个文档y中出现了多少次,即为词频TF(x,y),词频越高则该文档y与关键词x越相关。公式如下:
$$
TF(x,y) = 关键词x在文档y中出现的次数
$$

IDF逆词频,度量的是关键词x,在整个文档库中以文档为单位出现的频率(在某个文档中出现多次算一次),出现的越多该词的重要性越低。如:“这,那,的,是”,这样的词在语料中出现的概率很高,因此,其逆词频值就很低,意味着这些词的重要程度比较低。公式如下:
$$
IDF(x)=log(\frac{文档总数}{包含关键词x的文档数})
$$


TF-IDF需要把TF和IDF两个值相乘,结果就是关键词x,与文档y的相关性分数。
$$
TF-IDF(x,y)=TF(x,y)*IDF(x)
$$
其中TF部分表征的是关键词和文档的相关程度,IDF部分表征的是关键词的重要性。如果一个query由若干个关键词[x_1, x_2, ..]组成,则最终文档y与该query的相关性得分为所有TF-IDF之和,即:
$$
score(query,y) = TF-IDF(x_1,y)+TF-IDF(x_2,y)+...\\
=TF(x_1,y)*IDF(x_1)+TF(x_2,y)*IDF(x_2)+..
$$
观察上式可以发现,其值为一系列乘积之和,这与向量内积形式一致。因此,可以表示为两个向量的内积形式。
$$
\overrightarrow{TF(y)}=[TF(x_1,y),TF(x_2,y),TF(x_3,y)...]\\
\overrightarrow{IDF(query)}=[IDF(x_1),IDF(x_2),...]
$$
上式中,两个向量的维度并不一致。TF向量的维度是文档y中包含词的个数。IDF向量维度是query包含词的个数。要想求内积,两个向量维度必须一致。因此,首先需要基于语料库构建词表向量。即整个语料库都有哪些词。并将上述两向量对应到词表上形成两个维度一致的稀疏向量。假设,整个语料库由5个词(x_1, x_2, x_3, x_4, x_5)组成,文档y包含其中的4个词(x_1, x_2, x_3, x_4), query包含其中两个词(x_1, x_5),则上述两个向量可以写为:
$$
\overrightarrow{TF(y)}=[TF(x_1,y),TF(x_2,y),TF(x_3,y),TF(x_4,y),0]\\
\overrightarrow{IDF(query)}=[IDF(x_1),0,0,0,IDF(x_5)]
$$
如上,将两个向量的维度就统一成词表的长度了。query和文档y的相关性得分即为这两个向量的内积:
$$
score(query,y)=\overrightarrow{TF(y)}\cdot\overrightarrow{IDF(query)}
$$

<img src="./2018-NeuralNetwork/1-6.png" />
## 2. 标准BM25

### 1.2 训练机制
### 2.1 词频饱和

当我们构建了一个神经网络后,其最初的权重$$w_k$$和偏移量$$b_l$$都是随机的。这种神经网络并不能正确执行任务。我们还需要对其进行训练,使其在给定输入数据$$x$$时的输出$$o$$$$x$$的标注值$$L(x)$$尽量相近,这种用于训练神经网络的数据集称为训练数据集。我们希望$$L(x)和o$$这两个向量之差的几何距离$$\parallel L(x)-o\parallel$$越短越好,该函数称为Loss function。几何距离越短神经网络的实际输出和我们期望的输出越相近。而且我们希望神经网络在训练数据集的所有训练数据上都实现短的几何距离,即要求$$\sum_{i=1}^n \parallel L(x)-o\parallel$$尽量小,该函数称为Cost function。我们可以通过梯度下降及其衍生方法,来调整网络中的参数(权重和偏移量),使得Cost function达到最小值。该过程就称作神经网络的训练过程。
考虑两种情景:情景一,有一个关键词,在文档A中出现了2次,在文档B中出现了4次,在A和B长度相同的情况下,B的TF值是A的2倍。情景二,关键词在文档A中出现了200次,在文档B中出现了400次。在A和B长度相同的情况下,B的TF值也是A的2倍。然而,直观上认为在情景二,文档A和B的相关性应该是差不多的,关键词都出现了许多次。这就涉及到词频**饱和**的问题。即希望相关性和词频不是成线性关系,是成某种饱和曲线的关系。所以,BM25算法对TF部分做如下改动:
$$
TF(x,y)=\frac{TF(x,y)}{TF(x,y)+k}
$$
### 2.2 文档长度

## 2.用神经网络替换Q表格
BM25对于TF-IDF的另外一部分改动与文档**长度**相关。TF部分只考虑了词频没有考虑文档的长度。考虑两个文档A和B,A有10个词,关键词x出现1次,B有10000个词,关键词x出现10次。显然文档A的相关度大于文档B。但是其TF值只有B的十分之一。因此,BM25对TF部分做了进一步的改进:
$$
TF(x,y)=\frac{TF(x,y)}{TF(x,y)+k*\frac{D(y)}{avg(D)}}
$$
其中D为文档y的长度,avg(D)是语料库中所有文档的长度均值。

上一节,介绍TD和Q-Learning算法时,用了一个简单的例子-卖拐。在卖拐的ENV中,状态是离散值,要么是0代表相遇,要么是1代表卖拐。这种场景可以很好的用TD或Q-Learning算法解决。因为状态值离散且有限,意味着Q表格的行数是一定的。而在有些场景下,状态是连续的,即使强行使其离散化,也会导致状态数目太多,由于内存无法存储超多行数的Q表格而无法计算。因此,我们需要找到一种方法,该方法可以接收连续状态值,输出该状态下不同action的Q值。这时,神经网络就走上了舞台中央。在强化学习中,神经网络(**NN**-Neural Network)的作用是拟合Q值。通过agent和ENV的多次互动来获得训练NN的数据。
该公式看似合理,但是也有一定的弊端,在不同的语料库中,文档长度对TF值的影响是不同的。有的语料对长度敏感,而有的语料对长度不敏感。所以,BM25算法对长度影响部分加入了权重b,改进公式如下:
$$
TF(x,y)=\frac{TF(x,y)}{TF(x,y)+k*(1-b+b*\frac{D(y)}{avg(D)})}
$$
上式中,b=0则长度影响部分则完全不被考虑。

在Q-Learning算法中,更新Q值的公式为:<br>
BM25也对IDF部分做了改进:
$$
\begin{array}{l}
Q(S_t,A_t)\leftarrow Q(S_t,A_t)+\alpha [R_{t+1}+\gamma \max \limits_{a \in A} Q(S_{t+1},a)-Q(S_t,A_t)] \\
TargetQ = R_{t+1}+\gamma \max \limits_{a \in A} Q(S_{t+1},a)
\end{array}
IDF(x)=log(\frac{N-DF(x)+0.5}{DF(x)+0.5}) \qquad if \qquad IDF(x)\geq 0 \\
IDF(x)=\epsilon*avg(IDF) \qquad if \qquad IDF(x)<0
$$
<br>
式中N为语料中文档总数,DF(x)为包含关键词x的文档数。如该值为负,则用词表上所有IDF的均值乘以一个参数当做IDF值,该参数经验值为0.25。

## 3. 近似BM25

当语料库构建完毕后,通过BM25算法可以构建每个文档的TF向量,然后存入Milvus向量数据库中。并且词表中每个词的IDF值也可以提前计算好,存入BM25模型中。用户查询时,首先将用户query进行分词。然后将每个词的IDF值查出来并构成IDF向量。用该向量与向量数据库中的TF向量做内积(IP,inner product)。内积值即为query和文档的相关性。

我们将上式中括号内,减号左边的项称为TargetQ值。在Q-Learning算法中,就是让Q值去不断的逼近TargetQ值。一旦Q=TargetQ,上式中括号内为0,Q值不再更新,训练也就完成了。当然这是理想情况,一般不会发生。
### 3.1 动态语料库

因此,我们可以构建NN的Loss function为:<br>
当有新文档添加到语料库时,对TF和IDF值都有影响,如TF部分的平均文档长度会改变,IDF部分的N值会增加,甚至词表也会有改变比如出现了新的词。这就导致已经存储在milvus向量库中的文档TF向量全部需要重新生成更新。所有的IDF值也得重新计算。这个流程在每次添加新文档时都要进行一遍,其时间成本非常高。

因此,有必要对标准的BM25算法做一些近似,以提高效率。在RAG场景下,文件都是按照chunksize拆分为文本块的,文本块就是语料库中的文档。因此可以用chunksize代替avg(D),使得该值在插入新的文档后不变。这样,已经存储的TF向量就不用重新构建了。词表和词表的IDF向量是需要重建的,但只需要把词表中相关的词的词频加一,再把N值加一,重新计算即可,计算耗时很少。
$$
\begin{array}{l}
LOSS_{DQN}=\parallel Target Q-Q \parallel \\
\quad \quad \quad\quad\quad=[R_{t+1}+\gamma \max \limits_{a \in A} Q(S_{t+1},a)-Q(S_t,A_t)]^2
\end{array}
TF(x,y)=\frac{TF(x,y)}{TF(x,y)+k*(1-b+b*\frac{D(y)}{chunksize})}
$$
<br>

因此,我们只需要用梯度下降等方法,根据Loss function来优化NN的参数即可。至此,我们找到了用神经网络代替Q表格,来进行强化学习的方法。这种将多层神经网络和强化学习相结合的方法称为深度强化学习**DRL**
### 3.2 增量构建流程

1.对新增文档分词然后去重

2.每个词在词频向量中查询,如有则其值加一,没有则扩充词表,词频设为一。

## 3.DQN算法
3.文档总数N加一

## 4.OpenAI gym环境
4.重新计算IDF向量

0 comments on commit 94c6fb9

Please sign in to comment.