识别列表中的元素 - 机器学习

时间:2014-02-14 01:12:42

标签: python list machine-learning

所以我有多个列表:

['disney','england','france']
['disney','japan']
['england', 'london']
['disney', 'france']

现在我需要确定这些列表中的内容是否会一起出现。

例如,如果我们看一下这个小例子,我们发现'迪士尼','法国'经常在列表中。随着文件/清单数量的增加,我们可能会发现'英格兰',总是在'伦敦'的列表中

我看过诸如元组之类的东西,但这种情况更多发生在语言和大型文本文档中。这里的问题是如何识别出同时出现的这些配对/三元组/ n属性。

编辑:这不只是看对。如果你有三个字符串重复出现怎么办呢!

6 个答案:

答案 0 :(得分:2)

也许这样的事情可能是一个起点:

import numpy as np

# I'll use numbers instead of words,
# but same exact concept
points_list = [[0,1,2],
               [0,3],
               [1,4],
               [0,2]]

scores = np.zeros((5,5))

for points in points_list:
    temp = np.array(points)[:, np.newaxis]       
    scores[temp, points] += 1

结果:

>>> scores
array([[ 3.,  1.,  2.,  1.,  0.],
       [ 1.,  2.,  1.,  0.,  1.],
       [ 2.,  1.,  2.,  0.,  0.],
       [ 1.,  0.,  0.,  1.,  0.],
       [ 0.,  1.,  0.,  0.,  1.]])

对角元素告诉你一个变量总共出现了多少次,对角线元素告诉你多少次,两个变量一起出现。这个矩阵显然是对称的,因此有可能对此进行优化。

另外,如果你的子列表很长(你有很多变量),但你没有太多的变量,你可以考虑使用稀疏矩阵。

修改

这是关于如何获得三胞胎等的想法。

import numpy as np

# I'll use numbers instead of words,
# but same exact concept
points_list = [[0,1,2],
               [0,3],
               [1,4],
               [0,2],
               [0,1,2,3],
               [0,1,2,4]]

scores = np.zeros((5,5))

for points in points_list:
    temp = np.array(points)[:, np.newaxis]       
    scores[temp, points] += 1


diag = scores.diagonal()

key_col = (scores/diag)[:, 0]
key_col[0] = 0

points_2 = np.where(key_col > 0.5)[0]      # suppose 0.5 is the threshold 
temp_2 = np.array(points_2)[:, np.newaxis] # step 1: we identified the points that are
                                           # close to 0
inner_scores = scores[temp_2, points_2]    # step 1: we are checking if those points are
                                           # are close to each other

打印输出

>>> scores
array([[ 5.,  3.,  4.,  2.,  1.], # We identified that 1 and 2 are close to 0
       [ 3.,  4.,  3.,  1.,  2.],
       [ 4.,  3.,  4.,  1.,  1.],
       [ 2.,  1.,  1.,  2.,  0.],
       [ 1.,  2.,  1.,  0.,  2.]])
>>> inner_scores
array([[ 4.,  3.],                # Testing to see whether 1 and 2 are close together
       [ 3.,  4.]])               # Since they are, we can conclude that (0,1,2) occur 
                                  # together

正如我现在看到的,为了使这个想法正常工作,我们需要一个谨慎的递归实现,但我希望这会有所帮助。

答案 1 :(得分:0)

您可以创建一个字典,其中键是您的分组(例如,作为单词的排序列表),并为每个出现次数保留一个计数器。

答案 2 :(得分:0)

当内存不足时,磁盘可以提供帮助,我通常会这样做。

step1. count compute the partition id of each pair and output the respecting partition-file directly ( partition_id = (md5 of pair)/partition_count, the partition process is the keypoint) 

step2. merge the count output by step1 use dict(this process is done in memory per partition,if you are short of memory, choose larger partition_count)

答案 3 :(得分:0)

你应该建立一个倒排索引(见here),然后更频繁地检查哪些术语一起出现(即取两个术语,计算它们一起出现的次数)。也就是说,您为每个术语记录它出现的列表。如果字典的大小(列表中的术语)不是太大,这可能非常有效。

答案 4 :(得分:0)

我会使用某种设定逻辑。如果事情变得很大,我会把它们推向n。

100k列表确实不是那么大,特别是如果它们只是单个单词。(我花了一个星期的时间研究这个问题的6gb版本,超过8亿条目)。我更关心你有多少 LISTS

这显然只是一个黑客攻击,但这是我将如何解决这个问题的方向。

import itertools

a = ['disney','england','france']
b = ['disney','japan']
c = ['england', 'london']
d = ['disney', 'france']

g = [a, b, c, d]

for i in range(2, len(g)): 
    for ii in itertools.combinations(g, i):# combinations of list g in sequences from 2 to len(g)
        rr = map(set, ii)
        ixx = None
        for ix in rr:
            if ixx == None:
                ixx = ix
                continue
            ixx = ixx & ix
        if len(ixx) > 1:
            print ixx

结果:     set(['disney','france'])

显然,这并不能跟踪频率。但是,在将列表缩减为组合重复后,这很容易。

我认为你对跨越列表的关系感兴趣..如果你不是那么我不理解你的问题,也不知道为什么你有多个列表。

答案 5 :(得分:0)

简单的解决方案计数对(在纯python中)

from string import split
from itertools import combinations, imap, chain
from collections import Counter
from functools import partial

data = iter([
    'disney england france',
    'disney japan',
    'england london',
    'disney france',
])  # NOTE could have been: data = open('file.txt')

split_data = imap(split, data)

pair = partial(combinations, r=2)
observed_pairs = chain.from_iterable(
    imap(pair, split_data)
)
sorted_observed_pairs = imap(sorted, observed_pairs)
hashable_sorted_observed_pairs = imap(tuple, sorted_observed_pairs)
pair_count = lambda: Counter(hashable_sorted_observed_pairs)  # tada!
print(pair_count())