谢霍华德大佬的邀啊,受宠若惊。
咱先把定义弄明白吧。
文本匹配其实是nlp中的一个任务,之前叫语义相似度,现在所谓的文本匹配其实也是在做类似的事,说白了就是看俩句子有多相似,可以是01的分类问题,也可以是一个打分。
后面的这事我理解其实是一个检索任务,在整个库里面找到和给定query最相似的句子。而所谓的“相似”,却是需要定义的,不同的定义将会决定了查询和匹配的逻辑,如果把这个相似定义为语义或者文本相似,那就是对应所谓的“相似的标准“就是上面的文本匹配任务,看好,是标准是上面的语义匹配任务,我要吃肯德基和我要吃kfc很相似,所以召回的时候出现前者就应该查到后者,然而,如果定的相似的标准是“共现点击”,那又有另一套方法了。
讲到这,一言蔽之,nlp文本匹配问题是判断两个句子在语义层面的相似性,而后者,则是一个搜索问题,只不过在一定的场景下,可以用前者作为判断相似,判断搜索效果好坏的问题。
展开聊聊,nlp文本匹配主要分两个大的阶段,也形成了现在两个大的方法,文本和语义。最早没有深度学习的时候,文本匹配,就是字词层面的匹配就是主流,用户输入我要去长城,那带有长城的内容,还有带有“我要去"信息都可能被认为相似,八达岭长城,长城宽带,长城汽车,长城电影都有,也会有“我要去北京”,只不过因为我要去这种的idf比较低所以没那么相似,语义匹配则可以上升到更加模糊的语义层面,因为有我要去的存在,长城应该是地点,长城宽带之类的相似度也就下去了。具体不再展开了,有关领域我有总结自己的一套方法,可以参考一下:
而后面的检索任务,其实说白了就是一个查的问题,首先题主说的遍历,应该是最基本简单但不是最高效的方法,经典的搜索用的是“倒排索引”,文本层面最直接,数据库里面是存储的是“词汇-带有该词汇的文档id”,当查询的时候其实就是查这个词汇对应的文档,然后合并算分,复杂度可以被拉到和文档数无关的级别(体会到算法与数据结构的魅力了没?),对于现在流行的向量召回,其实就是把文档转化向量存到一个空间里,查询的时候找到空间里最接近的那几个文档,向量可就不能直接倒排索引了,有特定的一套方法来处理,这个问题叫做“最近邻相似”,比较经典的方法就是统计学习方法knn那章提到的kdtree,后续有了ball tree等,到了现在hnsw,annoy,ngt之类的方案已经能让这个检索速度非常快(我自己的实验hnsw基本在十几纳秒每条的水平,应该没记错),具体的方案也可以去查查。
有关向量召回和向量表征的概念,我专门有写过文章,可以看看。有助于理解这些概念背后做的事,他们两者在应用场景下是非常相关的,一定程度的混淆非常正常。
另外再提醒一个事,有关“相似”,这个概念非常模糊,什么叫做相似往往是落地场景非常头疼问题,“六一节的由来”和“五一节的由来”,在直观的感受下是非常接近的,文本数字啥的很接近,但是因为我们赋予了五一和六一新的含义才导致了他们其实不相似,这些问题我们都要在定义清楚后告诉模型,模型才能够学到,这又是另一个问题了,这个问题先聊到这。
不是,我觉得所有匹配问题,本质都是在学习一个度量,就是所谓的metric learning。例如,人脸识别,本质就是人脸和人脸的匹配问题,两张脸之间如何定义相似与距离。
传统的分类任务,每一类的样本会被按比例划分到训练集和测试集上,所以测试样本有“从训练数据集里寻找最相似的pair”的意味。
但在匹配任务的setting上,训练集和测试集里的类可以是完全不同的,所以并不存在你说的“从训练数据集里寻找最相似的pair”的情况。
而对于NLP文本匹配,一方面也和人脸识别一样,会有一个metric learning的过程,特别是对于双塔模型,如Sentence-Bert,句子pair分别编码,然后匹配。模型会把句子里相似的词的距离拉近,同时还会给每个词赋上一个词权重(体现在self- attention里了),其实就是教会模型文本匹配的时候要看哪里,类似人脸识别里教会模型要看鼻子嘴巴眼睛来辨别两个人是否相同。
另一方面,在传统文本匹配中,长期使用的是文本pair无监督的一些match pattern作为metric,例如BM25一系列方法。在深度学习里,match pattern是双塔模型学不到的,一般要单塔模型才能学到。如下图,单塔BERT中可以清晰的看到“我在伊朗长大”的匹配情况。当然match pattern也是一种metric了,只是说不同模型结构使得有些metric能学到,有些metric学不到。
真正的挑战: @纳米酱 曾提出过一个纳米酱难题
已知句对训练数据, 知乎网红是傻 与 知乎网红不是傻 -> 不相似
判断测试数据:知乎网红是不是傻 与 知乎网红不是傻 -> 是否相似?
Reference: