我需要在一组5000个样本中找到相关多个单词的相互关系。
示例: -
我们看到1和2彼此非常接近。 3几乎接近1和2.我们也有4和5彼此非常接近。
我们可以使用哪种方法和技术来检查这种相关性?
提前致谢!
修订:在分组方面也需要帮助,例如A组包括第1,2,3行和B组包含4和5.?
答案 0 :(得分:3)
这是解决此问题的一种方法。我使用scikit-learn将每个列表转换为文档术语矩阵。然后使用scipy.spacial.distance
计算每行之间的余弦相似度矩阵。
from sklearn.feature_extraction.text import CountVectorizer
from scipy.spatial import distance
count_vect = CountVectorizer(tokenizer=lambda x: x.split(', '))
ls = ['mango, guava, litchi, apple',
'mango, guava, litchi, orange',
'mango, guava, pineapple, grape',
'pen, pencil, book, copy, notebook',
'pen, pencil, book, copy, scale']
X = count_vect.fit_transform(ls).toarray()
D = distance.cdist(X, X, metric='cosine')
输出是每行之间的距离矩阵。它看起来如下:
[[ 0. , 0.25, 0.5 , 1. , 1. ],
[ 0.25, 0. , 0.5 , 1. , 1. ],
[ 0.5 , 0.5 , 0. , 1. , 1. ],
[ 1. , 1. , 1. , 0. , 0.2 ],
[ 1. , 1. , 1. , 0.2 , 0. ]])
例如D[0, 1]
表示第1行靠近第2行,因为两行之间的距离很小。此外,您可以看到D[3, 4]
很小,这意味着第4行接近第5行。
注意您还可以考虑使用distance.pdist(X, metric='cosine')
,它只给出矩阵的较低对角线,因为下对角线和上对角线相等。
分组文件
为了更加花哨,您可以使用分层聚类将每行与计算的距离矩阵聚类在一起。
from scipy.cluster import hierarchy
D = distance.pdist(X, metric='cosine')
Z = hierarchy.linkage(D, metric='euclidean')
partition = hcluster.fcluster(Z, t=0.8, criterion='distance') # [2, 2, 2, 1, 1]
表示文档1,2,3在第2组中组合在一起,4,5在第1组中组合在一起。如果绘制树形图,则可以看到每行如何聚集在一起
from scipy.cluster.hierarchy import dendrogram
import matplotlib.pyplot as plt
hierarchy.dendrogram(Z, above_threshold_color='#bcbddc',
orientation='top')
答案 1 :(得分:1)
另一种方法,或者可能是另一种解决问题的新方法:
import re
from itertools import chain
a = ['mango, guava, litchi, apple',
'mango, guava, litchi, orange',
'mango, guava, pineapple, grape',
'pen, pencil, book, copy, notebook',
'pen, pencil, book, copy, scale']
def get_words(lst):
return [re.findall(r'[\w]+', k) for k in a]
def get_percent(lst):
groupped_valid_dict = {}
for k in range(len(lst)):
sub = []
for j in range(k+1, len(lst)):
s = sum([1 if m == n else 0 for m, n in zip(lst[k], lst[j])])
#percent = (1 - float(len(lst[k]) - s)/len(lst[k])) * 100
#fmt = '%.2f%%' % percent
#print 'Words of lines: %d and %d are %s close' %(k+1, j+1, fmt)
if s > 0:
sub.append("Line{}".format(j+1))
if sub:
groupped_valid_dict["Line{}".format(k+1)] = sub
return groupped_valid_dict
lst = get_words(a)
lines = get_percent(lst)
groups = [[k] + lines[k] for k in lines if k not in chain.from_iterable(lines.values())]
groups.sort(key=lambda x: x[0])
for k, v in enumerate(groups, 1):
print "Group%d" %k, v
输出:
Group1 ['Line1', 'Line2', 'Line3']
Group2 ['Line4', 'Line5']