【问题标题】:merge nearly similar rows with help of spacy在 spacy 的帮助下合并几乎相似的行
【发布时间】:2020-05-12 09:51:31
【问题描述】:


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

df:

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

输出:

string
yellow color looks like bright
red color okay blood

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

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

【问题讨论】:

  • 如果你有 3 个相似的字符串,你想把它们合并在一起吗?
  • @GuillermoMosse 是的。
  • 如果您遵循这种思路,我认为您最终会使用聚类方法。查看我的回答并告诉我您是否需要一个示例来使事情更清楚:-)
  • @GuillermoMosse 好的。谢谢。我得到了这种方法。它肯定对我有用。生病尝试实施。我也在等待其他人分享他们的想法。

标签: python merge nlp data-science spacy


【解决方案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]

【讨论】:

    【解决方案2】:

    我想你还没有想到有的可能性,例如:

    yellow color bright
    yellow color I like
    yellow color looks like
    

    在这些情况下,您需要决定要做什么:只随机合并其中的 2 个?三个?

    想了想,你可能会发现你真正想做的是cluster这个词嵌入,也就是把它们分成不重叠的相似元素组(一个组的大小可以等于1 )。

    幸运的是,有很多现有的解决方案,每一种都有其优缺点。例如DBSCAN,运行时间为 O(n log n)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-16
      • 2019-04-26
      • 1970-01-01
      • 2019-07-16
      相关资源
      最近更新 更多