我有十个列表,我想得到它们的“相似性”。这是我输入的内容:
data = [
['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'SeasonNumber', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],
['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'SeasonNumber', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],
['RuntimeInMinutes', 'Genres', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', '_StudioName', 'Type', 'LanguageOfMetadata', 'ReleaseDate', 'Studio', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'TVSeriesID', 'Locales', 'EpisodeNumber', 'Name', 'Synopsis', 'Products', 'SeasonNumber', 'Platform'],
['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'LanguageOfMetadata', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],
['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],
['RuntimeInMinutes', 'Genres', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', '_StudioName', 'Type', 'LanguageOfMetadata', 'ReleaseDate', 'Studio', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'TVSeriesID', 'Locales', 'EpisodeNumber', 'Name', 'Synopsis', 'Products', 'SeasonNumber', 'Platform'],
['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],
['RuntimeInMinutes', 'ReleaseDate', 'Genres', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],
['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales'],
['RuntimeInMinutes', 'EpisodeNumber', 'Genres', 'ReleaseDate', 'Name', 'Platform', 'PlatformID', 'BaseURL', 'Languages', 'ArtworkURL', 'Synopsis', 'TVSeriesID', 'Products', '_NetworkName', 'ReleaseYear', '_ContentProviderName', 'Studio', '_StudioName', 'Type', 'Locales']
]
我当前的方法是将这些值的长度与总长度进行比较。因此,在上面将是:
>>> len(set(data))/len(data)
0.5
但是,这很粗糙,因为我想得到一个并非“全有或全无”的相似性。换句话说,类似概念上的相似性,上面的内容可能具有98%的相似性(很抱歉,如果我在这里无法准确解释自己想要的内容,但是我的意思是要评估相似性不仅是列表本身,而且是列表其元素的相似性。
答案 0 :(得分:2)
看看datasketch library及其MinHash数据结构。这是基于集合的Jaccard Similarity的集合,即交集(它们的共同点)除以并集(所有可能的元素)。
这里是一个例子:
from datasketch import MinHash
data1 = ['minhash', 'is', 'a', 'probabilistic', 'data', 'structure', 'for',
'estimating', 'the', 'similarity', 'between', 'datasets']
data2 = ['minhash', 'is', 'a', 'probability', 'data', 'structure', 'for',
'estimating', 'the', 'similarity', 'between', 'documents']
m1, m2 = MinHash(), MinHash()
for d in data1:
m1.update(d.encode('utf8'))
for d in data2:
m2.update(d.encode('utf8'))
print("Estimated Jaccard for data1 and data2 is", m1.jaccard(m2))
如果集合很大,则可以为您提供相似性的估计。否则,只需使用内置的set操作:
s1 = set(data1)
s2 = set(data2)
actual_jaccard = float(len(s1.intersection(s2)))/float(len(s1.union(s2)))
print("Actual Jaccard for data1 and data2 is", actual_jaccard)
如果要获取两个以上的Jaccard相似度,只需计算成对比较并取所有值的平均值(平均值)即可。
from datasketch import *
import itertools
minhash_data = list()
for element in data:
m = MinHash()
for d in element:
m.update(d.encode('utf-8'))
minhash_data.append(m)
jaccard_sims = list()
for pair in itertools.combinations(minhash_data, 2):
jaccard_sims.append(pair[0].jaccard(pair[1]))
average = sum(jaccard_sims) / float(len(jaccard_sims))
print("Average Jaccard similarity: {}".format(average))
Jaccard平均相似度:0.9512152777777778
答案 1 :(得分:0)
当您说要获得两个列表之间的相似性时,有多种方法可以做到这一点。就像@Nick Pandey Jaccard相似。另一种称为tanimoto ratio的比率也很有效。
这是我的实现:
def tanimoto (list1, list2):
intersection = [common_item for common_item in list1 if common_item in list2]
return float(len(c))/(len(a) + len(b) - len(c))
现在,要解决您必须同时比较10个列表的问题。您只能使用上述类似的方法同时比较两个元素。但是,您可以开发自己的逻辑以大致了解彼此之间的相似程度。
例如,您可以一次提取五个列表并进行比较,或者更好的选择是比较前两个列表,存储tanimoto coeff,比较下两个并重复。最后取平均系数。用代码更好:
def grouped(iterable, n):
return zip(*[iter(iterable)]*n)
coeffs = []
for i, j in grouped(data, 2): # data refers to the variable in the question
coeffs.append(tanimoto(i, j))
similarity = sum(coeffs)/len(coeffs)
希望这会有所帮助:)