在 spacy 的帮助下合并几乎相似的行

2023-12-31


如果某些行几乎相似,我想合并它们。
可以使用 spaCy 检查相似性。

df:

string                     
yellow color       
yellow color looks like 
yellow color bright
red color okay
red color blood

output:

string
yellow color looks like bright
red color okay blood

解决方案:
暴力方法是 - 对于字符串中的每个项目,检查与其他 n-1 个项目的相似性,如果大于某个阈值,则合并。
还有其他办法吗?
因为我与很多人接触不多,所以不知道他们是如何做到的
我想到的一个想法是——我们可以传递一些函数来合并吗?如果为真则合并,否则不合并。

欢迎任何其他流行的方法。


如果您通过常见单词的出现来衡量相似性,那么您甚至不需要 Spacy:只需使用字数统计对文本进行矢量化并馈送到任何聚类算法即可。AgglomerativeClustering就是其中之一——对于大型数据集来说,它的时间效率不是很高,但它是高度可控的。您需要为数据集调整的唯一参数是distance_threshold:越小,簇就越多。

对文本进行聚类后,您可以连接每个聚类中的所有唯一单词(或者做一些更聪明的事情,具体取决于您要解决的最终问题)。整个代码可能如下所示:

texts = '''yellow color       
yellow color looks like 
yellow color bright
red color okay
red color blood'''.split('\n')

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.preprocessing import Normalizer, FunctionTransformer
from sklearn.cluster import AgglomerativeClustering
from sklearn.pipeline import make_pipeline
model = make_pipeline(
    CountVectorizer(), 
    Normalizer(), 
    FunctionTransformer(lambda x: x.todense(), accept_sparse=True),
    AgglomerativeClustering(distance_threshold=1.0, n_clusters=None),
)
clusters = model.fit_predict(texts)
print(clusters)  # [0 0 0 1 1]

from collections import defaultdict
cluster2words = defaultdict(list)
for text, cluster in zip(texts, clusters):
    for word in text.split():
        if word not in cluster2words[cluster]:
            cluster2words[cluster].append(word)
result = [' '.join(wordlist) for wordlist in cluster2words.values()]
print(result)  # ['yellow color looks like bright', 'red color okay blood']

仅当常用词不够并且您想要捕获语义相似性时,您才需要 Spacy 或任何其他具有预训练模型的框架。整个管道只会改变一点点。

# !python -m spacy download en_core_web_lg
import spacy
import numpy as np
nlp = spacy.load("en_core_web_lg")

model = make_pipeline(
    FunctionTransformer(lambda x: np.stack([nlp(t).vector for t in x])),
    Normalizer(), 
    AgglomerativeClustering(distance_threshold=0.5, n_clusters=None),
)
clusters = model.fit_predict(texts)
print(clusters)  # [2 0 2 0 1]

您会看到这里的聚类显然是不正确的,因此 Spacy 词向量似乎不适合这个特定问题。

如果您想使用预训练模型来捕获文本之间的语义相似性,我建议您使用Laser反而。它明确基于句子嵌入,并且是高度多语言的:

# !pip install laserembeddings
# !python -m laserembeddings download-models
from laserembeddings import Laser
laser = Laser()

model = make_pipeline(
    FunctionTransformer(lambda x: laser.embed_sentences(x, lang='en')),
    Normalizer(), 
    AgglomerativeClustering(distance_threshold=0.8, n_clusters=None),
)
clusters = model.fit_predict(texts)
print(clusters)  # [1 1 1 0 0]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 spacy 的帮助下合并几乎相似的行 的相关文章

随机推荐