以向量化方式连接给定开始、停止编号的范围数组 - NumPy

2024-04-11

我有两个感兴趣的矩阵,第一个是“词袋”矩阵,有两列:文档 ID 和术语 ID。例如:

bow[0:10]

Out[1]:
    array([[ 0, 10],
           [ 0, 12],
           [ 0, 19],
           [ 0, 20],
           [ 1,  9],
           [ 1, 24],
           [ 2, 33],
           [ 2, 34],
           [ 2, 35],
           [ 3, 2]])

此外,我有一个“索引”矩阵,其中矩阵中的每一行都包含词袋矩阵中给定文档 ID 的第一行和最后一行的索引。例如:第 0 行是 doc id 0 的第一个和最后一个索引。例如:

index[0:4]

Out[2]:
    array([[ 0,  4],
           [ 4,  6],
           [ 6,  9],
           [ 9, 10]])

我想做的是随机抽取文档 ID 样本,并获取这些文档 ID 的所有单词行包。词袋矩阵大约有 150M 行(~1.5Gb),因此使用 numpy.in1d() 太慢。我们需要快速返回这些数据以供下游任务使用。

我想出的天真的解决方案如下:

def get_rows(ids):
    indices = np.concatenate([np.arange(x1, x2) for x1,x2 in index[ids]])
    return bow[indices]

get_rows([4,10,3,5])

通用样本

提出问题的通用示例是这样的 -

indices = np.array([[ 4, 7],
                    [10,16],
                    [11,18]]

预期输出是 -

array([ 4,  5,  6, 10, 11, 12, 13, 14, 15, 11, 12, 13, 14, 15, 16, 17])

我想我终于破解了它cumsum https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.cumsum.html矢量化解决方案的技巧 -

def create_ranges(a):
    l = a[:,1] - a[:,0]
    clens = l.cumsum()
    ids = np.ones(clens[-1],dtype=int)
    ids[0] = a[0,0]
    ids[clens[:-1]] = a[1:,0] - a[:-1,1]+1
    out = ids.cumsum()
    return out

样本运行 -

In [416]: a = np.array([[4,7],[10,16],[11,18]])

In [417]: create_ranges(a)
Out[417]: array([ 4,  5,  6, 10, 11, 12, 13, 14, 15, 11, 12, 13, 14, 15, 16, 17])

In [425]: a = np.array([[-2,4],[-5,2],[11,12]])

In [426]: create_ranges(a)
Out[426]: array([-2, -1,  0,  1,  2,  3, -5, -4, -3, -2, -1,  0,  1, 11])

如果我们给定开始和停止两个1D数组,我们只需要使用它们来代替第一列和第二列。为了完整起见,这是完整的代码 -

def create_ranges(starts, ends):
    l = ends - starts
    clens = l.cumsum()
    ids = np.ones(clens[-1],dtype=int)
    ids[0] = starts[0]
    ids[clens[:-1]] = starts[1:] - ends[:-1]+1
    out = ids.cumsum()
    return out
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以向量化方式连接给定开始、停止编号的范围数组 - NumPy 的相关文章

随机推荐