赞
踩
本文已经是今年的第31篇大模型相关的技术文章了,如果说
我和我司更非常高兴通过博客、课程、内训、项目,与大家共同探讨如何把先进的大模型技术更好、更快的落地到各个行业的业务场景中,赋能千千万万公司的实际业务
而本文一开始是属于:因我司第三项目组「知识库问答项目」而起的此文《知识库问答LangChain+LLM的二次开发:商用时的典型问题及其改进方案》中的1.2节(该1.2节初稿来自我司LLM项目团队第三项目组的bingo),但为把Text Embedding模型阐述的更为精准、全面,特把那部分的内容抽取出来,不断完善成此文
最终尽可能相比网上已有的其他资料都更细致化
判断哪些文本嵌入模型效果较好,通常需要一个评估指标来进行比较,《MTEB: Massive Text Embedding Benchmark(海量文本嵌入基准)》就是一个海量文本嵌入模型的评估基准
榜单地址:https://huggingface.co/spaces/mteb/leaderboard
从Chinese Massive Text Embedding Benchmark中可以看到目前最新的针对中文海量文本embedding的各项任务的排行榜,针对不同的任务场景均有单独的排行榜。
任务榜单包括:
其中,在本地知识库任务中,主要是根据问题query的embedding表示到向量数据库中检索相似的本地知识文本片段。因此,该场景主要是Retrieval检索任务。检索任务榜单如下:
目前检索任务榜单下效果最好的是bge系列的bge-large-zh模型,langchain-chatchat项目中默认的m3e-base也处于比较靠前的位置
text-embedding-ada-002是OpenAI于2022年12月提供的一个embedding模型,但需要调用接口付费使用。其具有如下特点:
以下是OpenAI官方文档中给出的用于文本搜索的代码实例
- from openai.embeddings_utils import get_embedding, cosine_similarity
-
- def search_reviews(df, product_description, n=3, pprint=True):
- embedding = get_embedding(product_description, model='text-embedding-ada-002')
- df['similarities'] = df.ada_embedding.apply(lambda x: cosine_similarity(x, embedding))
- res = df.sort_values('similarities', ascending=False).head(n)
- return res
-
- res = search_reviews(df, 'delicious beans', n=3)
ada v2 | text-embedding-3-small | text-embedding-3-large | ||||
Embedding size | 1536 | 512 | 1536 | 256 | 1024 | 3072 |
Average MTEB score | 61.0 | 61.6 | 62.3 | 62.0 | 64.1 | 64.6 |
从上图可知,text-embedding-3-small/large这两个新嵌入模型允许开发者通过在 dimensions API 参数中传递嵌入而不丢失其概念表征属性,从而缩短嵌入(即从序列末尾删除一些数字)
OpenAI 所使用的「缩短嵌入」方法,随后引起了研究者们的广泛注意,最终发现,这种方法和 2022 年 5 月的一篇论文所提出的「Matryoshka Representation Learning」方法是相同的(MRL 的一作 Aditya Kusupati 也评论道:OpenAI 在 v3 嵌入 API 中默认使用 MRL 用于检索和 RAG!其他模型和服务应该很快就会迎头赶上)
不同于常规的fix的embedding表征,Matryoshka representation learning提出了一个方法,生成的表征是按照x下标进行重要性排序的,所以在资源受限的环境,可以只使用前面top-k维表征就可以
如下所示,对于,考虑一组表示尺寸
,对于输入数据
中的数据点
,其的目标是学习一个
维表示向量
,对于每一个
,MRL的目标是让前
维的表征向量
独立地成为可转移的通用表征向量
再比如,在ImageNet-1K上训练ResNet50,将224×224像素的图像嵌入d=2048表示向量,然后通过线性分类器在个标签中进行预测
M3E是Moka Massive Mixed Embedding的简称,解释一下
其有多个版本,分为m3e-small、m3e-base、m3e-large,m3e GitHub地址:GitHub - wangyingdong/m3e-base,其
以下是m3e的一些重大更新
此外,m3e团队建议
- from datasets import load_dataset
-
- from uniem.finetuner import FineTuner
-
- dataset = load_dataset('shibing624/nli_zh', 'STS-B')
- # 指定训练的模型为 m3e-small
- finetuner = FineTuner.from_pretrained('moka-ai/m3e-small', dataset=dataset)
- finetuner.run(epochs=3)
详细教程暂放在「大模型项目开发线上营」中,至于本文后续更新
2023年8月2日,北京智源人工智能研究院发布的中英文语义向量模型BGE(hf地址:https://huggingface.co/BAAI/bge-large-zh,GitHub地址:https://github.com/FlagOpen/FlagEmbedding/blob/master/README_zh.md),以下是BGE的技术亮点
目前主流的语言模型的预训练任务都是token级别的,比如MLM或者Seq2Seq,但是这种训练任务难以让模型获得一个高质量的基于句子级别的句向量,这限制了语言模型在检索任务上的潜力。针对这个弊端,目前有两者针对检索模型的预训练策略
基于此,研究人员提出了RetraoMAE(RetroMAE论文:https://arxiv.org/abs/2205.12035),它包括两个模块,其一是一个类似于BERT的编码器,用于生成句向量,其二是一个一层transformer的解码器,用于重建句子,如下图所示
所谓编码,即Mask(EN)掉一小部分token然后通过BERT编码得到句子嵌入sentence embedding,具体步骤如下
所谓解码,即Mask(DE)很大一部分token然后结合句子嵌入sentence embedding,让解码器重构原始句子
具体而言,即是联合以下两个部分,好让解码器在该两部分的基础上重构原始句子
有个细节是,这里的Mask(DE)输入带上位置嵌入了,即句子嵌入
和带有位置的掩码输入被组合成以下序列
其中,表示
的嵌入,在
的基础上增加了一个额外的位置嵌入
接下来,通过优化以下目标,学习解码器
来重构原始句子
其中,是交叉熵损失
由于在解码器部分采用了极其简单的网络结构跟非常激进的mask比例,从而使得解码任务变得极具挑战性,迫使encoder去生成高质量的句向量才能最终准确地完成原文本重建
前面提及的解码策略有一种缺陷,就是训练信号只来源于被mask掉的token,而且每个mask掉的token都是基于同一个上下文重建的。于是研究人员提出了一种新的解码方法:Enhanced Decoding,具体做法如下
其中一个和常规decoder不一样的地方是,H1作为Q,H2作为KV
H1中的每个token embedding去H2中查找比较重要的上下文:包括H2被采样到的 token,以及初始token embedding都能看到[这里的初始embedding就是sentence embedding],至于对角线上的因代表的各自自身,故看不到
为方便大家更好、更快的理解,我再举个例子,比如:
P0上的
能看见P1上的
(
x0、x1)
P1上的能看见P0、P2上的
、
(x0、
x1、x2)
P2上的能看见P0、P1上的
、
(x0、x1、
x2)
P3上的能看见P0、P4上的
、
(x0、_ 、 _、
x3、x4)
P4上的能看见P0、P3上的
、
(x0、_ 、 _、x3、
x4)
之后,每个token xi基于对矩阵M的第i行可见的上下文进行重构(each token xi is recon-structed based on the context which are visible tothe i-th row of matrix M),该矩阵即如下所示
主对角线位置填充为-∞(因为其代表自身,故不可见),可见上下文的位置填充为0,代表可见
最后,再总结一下RetroMAE 预训练步骤
{"query": str, "pos": List[str], "neg":List[str]}
- python -m FlagEmbedding.baai_general_embedding.finetune.hn_mine \
- --model_name_or_path BAAI/bge-base-en-v1.5 \
- --input_file toy_finetune_data.jsonl \
- --output_file toy_finetune_data_minedHN.jsonl \
- --range_for_sampling 2-200 \
- --use_gpu_for_searching
- torchrun --nproc_per_node {number of gpus} \
- -m FlagEmbedding.baai_general_embedding.finetune.run \
- --output_dir {path to save model} \
- --model_name_or_path BAAI/bge-large-zh-v1.5 \
- --train_data ./toy_finetune_data.jsonl \
- --learning_rate 1e-5 \
- --fp16 \
- --num_train_epochs 5 \
- --per_device_train_batch_size {large batch size; set 1 for toy data} \
- --dataloader_drop_last True \
- --normlized True \
- --temperature 0.02 \
- --query_max_len 64 \
- --passage_max_len 256 \
- --train_group_size 2 \
- --negatives_cross_device \
- --logging_steps 10 \
- --query_instruction_for_retrieval ""

近日,智源发布了BGE家族新成员——通用语义向量模型BGE-M3(其开源仓库及技术报告、模型链接)
在训练数据上,包括
“You are a curious AI assistant, please generate one specific and valuable question based on the following text.
The generated question should revolve around the core content of this text, and avoid using pronouns (e.g., ”this”). Note that you should generate only one question, without including additional content:”
最终得到的数据分布如下:
如BGE模型一致,BGE-M3模型训练分为三个阶段:
从形式上看,在给定一个
表示的查询
时,从语料库
中检索出以
表示的文档
:
其中
属于密集检索、稀疏/词汇检索或多维检索中的任何一种函数
可以是另一种语言,也可以是与
相同的语言
M3-Embedding统一了嵌入模型的所有三种常见检索功能,即稠密检索、词性(稀疏)检索和多向量检索
最后,由于嵌入模型的多功能性,检索过程可以采用混合过程
嵌入模型经过训练,可以区分正样本和负样本。对于每一种检索方法,它都有望为查询的正样本分配一个更高的分数,因此,进行训练过程是为了最小化In-foNCE损失,如下表示
其中
在知识蒸馏阶段,以总得分sinter为教师模型监督信号,其中的任何一个得分作为学生模型
将每种检索方法的损失函数修改为:
进一步对修正后的损失函数进行积分和归一化处理:
最后使用线性组合推导出自我知识蒸馏的最终损失函数
整个训练过程是一个两阶段的工作流程,如下所示:
- 首先,使用弱监督数据对文本编码器进行预训练,其中只有密集检索是以对比学习的基本形式进行训练的
- 其次,自我知识蒸馏应用于第二阶段,在此阶段对嵌入模型进行微调,以建立三种检索功能。在这一阶段中,将使用标注数据和合成数据,并根据ANCE方法为每个查询引入硬负样本
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。