TF-IDF 嵌入与余弦检索
目标
用numpy直接计算TF-IDF嵌入,用余弦相似度搜索文档,用数字确认降维的代价。
为什么重要
调用嵌入式API就会产生向量。虽然即使不知道里面发生了什么,也可以使用,但搜索结果异常时无法缩小原因。
TF-IDF比神经网络嵌入要简单得多,但核心结构是一样的。将文本转换为向量,将长度归一化,内在地测量相似性的骨架是一样的。所以在这里忽略归一化的话,可以直接看到长文档在所有查询中花费的时间现象,这种经验在实际调试实际向量搜索时会直接使用。
最后一个阶段的哈希技巧也有意义。减少维度可以获得内存和速度,但由于碰撞而丢失信息。如果用数字来衡量这种损失的实际程度,就会产生选择向量维度的感觉。
阶段
工作目录是/root/llm是。对象是docs表格中的文件有30件。
- 将各文档进行令牌化
/root/llm/doc_tokens.tsv保存到。docs.id<탭>공백으로 구분한 토큰들是格式,30行。令牌化规则是将小写字母转换后用正则表达式[가-힣a-z0-9]+是通过抽出。 - 按项目文档频率
/root/llm/df.tsv在항<탭>df以格式保存。项目按升序排列,即使一个文档出现多次,也会被视为1。 - IDF
/root/llm/idf.tsv在항<탭>idf以格式保存。项顺序和2号相同,值为六位小数。公式是ln((1 + N) / (1 + df)) + 1其中N是文档数。 - TF-IDF矩阵
/root/llm/tfidf.npy保存为。形状是(文档数,项数),项顺序与第2次相同。值是将idf乘以出现次数,然后将每行的L2长度归一化为1。 - 各文档的最近邻居
/root/llm/sim_top.tsv在docs.id<탭>가장 비슷한 docs.id<탭>점수保存为。除自己以外,分数为六位小数,如果同分的话docs.id选择较小的那个。 - 关于下面的3个问题,将前3个文档
/root/llm/query_top3.tsv在질의번호<탭>순위<탭>docs.id<탭>점수保存为。共9行。- 1号:
인덱스가 왜 안 타는지 알고 싶다 - 2号:
TCP 연결이 안 될 때 무엇을 보나 - 3号:
GPU 는 왜 메모리 때문에 느려지나问题向量也使用与同一个token化相同的idf进行L2正则化。如果平分的话docs.id小的那个在前面。
- 1号:
- 用哈希技巧制作1024维矩阵
/root/llm/hashed.npy保存为。桶是int(md5(항).hexdigest(), 16) % 1024并且,在每个桶里등장 횟수 곱하기 idf累积后将行L2归一化。 - 两种方式的最近邻匹配文档数量和比例
/root/llm/compare.tsv在一行일치수<탭>비율以格式保存。比例以三位小数点为准。
参考
numpy已安装。np.save,np.load,np.linalg.norm写。- 一旦确定了文件和抗议的顺序,就必须一直保持相同的顺序。
- 常见的错误1:Python内置
hash()每次执行都会有不同的值。必须hashlib.md5请使用。 - 常见的错误2:忘记除以正则化会导致长文档在所有查询中失败。请确认每行的长度是否为1。
文档令牌化
将各文档进行令牌化/root/llm/doc_tokens.tsv保存到。docs.id<탭>공백으로 구분한 토큰들是格式,30行。令牌化规则是将小写字母转换后用正则表达式[가-힣a-z0-9]+是通过抽出。
换成小写字母后,只剩下韩文、英文、数字连续的块。一个正则表达式就行了。
计数文档频率
按项目文档频率/root/llm/df.tsv在항<탭>df以格式保存。项目按升序排列,即使一个文档出现多次,也会被视为1。
即使在同一文档中出现多次,也会被视为1。项按升序排列。
计算IDF
IDF/root/llm/idf.tsv在항<탭>idf以格式保存。项顺序和2号相同,值为六位小数。公式是ln((1 + N) / (1 + df)) + 1其中N是文档数。
在分子和分母中加上1,最后加上1,写上平滑公式。
创建TF-IDF矩阵
TF-IDF矩阵/root/llm/tfidf.npy保存为。形状是(文档数,项数),项顺序与第2次相同。值是将idf乘以出现次数,然后将每行的L2长度归一化为1。
将idf乘以出现次数,然后按行长度调整为1。改变顺序的话,值会变。
寻找最近的邻居
各文档的最近邻居/root/llm/sim_top.tsv在docs.id<탭>가장 비슷한 docs.id<탭>점수保存为。除自己以外,分数为六位小数,如果同分的话docs.id选择较小的那个。
因为已经归一化了,所以内积就是余弦相似度。请不要把自己排除在候选人之外。
通过查询搜索文档
关于下面的3个问题,将前3个文档/root/llm/query_top3.tsv在질의번호<탭>순위<탭>docs.id<탭>점수保存为。共9行。
- 1号:
인덱스가 왜 안 타는지 알고 싶다 - 2号:
TCP 연결이 안 될 때 무엇을 보나 - 3号:
GPU 는 왜 메모리 때문에 느려지나问题向量也使用与同一个token化相同的idf进行L2正则化。如果平分的话docs.id小的那个在前面。
问题也用相同的idf制作向量并归一化。忽略学习中没有的单词。
用哈希技巧减少次元
用哈希技巧制作1024维矩阵/root/llm/hashed.npy保存为。桶是int(md5(항).hexdigest(), 16) % 1024并且,在每个桶里등장 횟수 곱하기 idf累积后将行L2归一化。
Python内置hash每次运行都会改变值。必须使用md5才能重现。
比较两种方式的结果
两种方式的最近邻匹配文档数量和比例/root/llm/compare.tsv在一行일치수<탭>비율以格式保存。比例以三位小数点为准。
计算每个文档最近邻在两种方式中是否相同,并输出比例。