aplmikex / deduplication_mnbvc

文本去重
MIT License
67 stars 11 forks source link

请问去重使用的是什么方法呢 #4

Closed CoinCheung closed 1 year ago

CoinCheung commented 1 year ago

如果两段文本大差不差,但是又不是每个字都相同的话,也可以检测出来吗

aplmikex commented 1 year ago

考虑到速度和精准度的权衡,现在是使用基于行的md5值的去重方式,我在做基于字的以及基于embedding向量的去重方式。

CoinCheung commented 1 year ago

md5值就表示每个字都一样,才算是重复的,但是有一些文档,大部分内容都是相同的,可以认为内容基本完全一样,这种也应该去掉是吧

另外,老哥你觉得用什么方法得到embedding的效果更好呢,貌似句子长度不同应该分开考虑?

aplmikex commented 1 year ago

我们项目是服务于MNBVC语料库这个项目的清洗的,现在的基于行的一个去重主要的目标是把不同来源的同一个文件筛选出来,避免进一步浪费算力。

md5值就表示每个字都一样,才算是重复的,但是有一些文档,大部分内容都是相同的,可以认为内容基本完全一样,这种也应该去掉是吧

这个地方就是我说的基于字的,现在在探索一种更快更准确的方式来计算相似度,毕竟1GB的数据就有接近4亿个字,算力负担太大了。

另外,老哥你觉得用什么方法得到embedding的效果更好呢,貌似句子长度不同应该分开考虑?

我们做embedding的目的主要是为了筛选出质量较低的语料,例如涉黄,涉政,以及出现次数较高的广告。主要做的是语料分类的辅助工作,这类的工作召回率较低也没太大影响的。

CoinCheung commented 1 year ago

老哥,请问怎么衡量一个语料里面的一段文本属于质量高还是质量低呢

aplmikex commented 1 year ago

我们不对语料进行质量的排序,这个问题太大了,我们只会进行筛选出确定低质量的语料。比如对于大模型来说,一段连续的重复的字就属于低质量,乱码的也是。然后如果一个广告在语料库出现过很多次,他对训练来说也是无价值的,甚至是会对大模型有负面影响。然后比如common crawl里面有很多涉黄涉政的言论,作为语料库公开,也是要筛出去的。

CoinCheung commented 1 year ago

原来是这样,请问怎么筛选出相似度特别高的文本呢,两段文本的内容几乎是完全相同的,但是又有个别的字不一样这种,类似于公众号文章洗稿这种情况,有什么办法能找出来吗

aplmikex commented 1 year ago

如果仅有个别字不一样的话,现在是用simhash以连续的10个字为单位计算文章的向量,只要不是字改变的密度太高都能查出来,如果说像论文降重的那种方式的话以文本为单位是看不出来的,可以考虑句向量聚类。

CoinCheung commented 1 year ago

@aplmikex 大佬好, 请问,把文本转成simhash之后,然后怎么实现的去重呢,怎么根据两两之间的相似度去掉重复的向量呢

aplmikex commented 1 year ago

手动指定一个阈值,按照谷歌的做法,在simhash的汉明距离相差3以内,具体的实现可以参考python的simhash库的simhashindex,他做了lsh这种分桶而不是两两比较,我基于他简单修改了一下更适合我们项目,具体参考 https://github.com/aplmikex/deduplication_mnbvc/blob/main/utils/customSimhash.py 。我实测在单机单进程情况下,百万个simhash值以上的查找就比较慢了,我们组在探索更高效的查找方案。

CoinCheung commented 1 year ago

@aplmikex 好的,请问如果没办法设阈值的时候怎么办呢,如果转成的向量的模长也有参考意义,这样就只能使用欧氏距离判断相似度,这种情况下其实就没办法指定一个阈值进行过滤,这个时候有什么办法去重吗

aplmikex commented 1 year ago

没理解你说的这个没办法设阈值,simhash是64位的二进制字符串,他的汉明距离一定会是整数,为什么没办法设阈值呢?你的意思是想做word2vec或者sentence2vec这种转化出来的embedding向量?如果是这种比较稠密的浮点向量的话,目前比较流行的方法就是向量数据库,比如annoy,faiss,milvus这种。距离的话L1范数和无穷范数也可以考虑,不止是L2范数,simhash计算的方式其实就是L1范数的,在某些情况下或许会表现的更好。

CoinCheung commented 1 year ago

@aplmikex 请问这种转成的embedding,向量的距离不在一个范围之内的情况下,怎么判断哪些样本属于重复样本应该去掉呢,faiss这种貌似是用来检索的?

aplmikex commented 1 year ago

向量的距离不在一个范围之内是指的什么?我理解的话,阈值多少是一个比较经验性的东西,主要是根据你的数据和算embedding的方法,可以多尝试几次找到更合适的阈值。像我举的例子里面,通常是计算topK个最近点,一般把K取大一点,并筛出距离低于阈值的视为重复。或者利用KD-Tree,R-Tree之类的方法,可以直接计算低于阈值的点。

aplmikex commented 1 year ago

其实如果只考虑重复的情况,我现在做simhash的时候是可以只查找到Top1,低于阈值就认为重复,然后放到数据库里,其实就是默认由先进数据库的给后进的去重了。

CoinCheung commented 1 year ago

@aplmikex 我的意思是说,cosine相似度的范围是[-1, 1],可以设一个阈值thr=0.9这种,如果是使用欧氏距离衡量相似度的时候,要怎么取这个阈值呢

aplmikex commented 1 year ago

这俩不是一个概念啊,在只有所有向量的模长都相等的时候才能算出余弦相似度和欧氏距离之间的关系。其他情况根本转换不了,一个是两个向量之间的余弦值,另一个是欧氏距离。你可以根据你数据的数据特征找一个模长密度最大的区域,用它来计算对应的欧氏距离呗,或者根据经验取一个值。