python - 每行 Numpy 中二维矩阵的滚动窗口或事件?

标签 python numpy matrix window find-occurrences

在矩阵的每一行上寻找模式的出现,我发现对于具有良好性能的非常大的矩阵,没有明确的解决方案可以在 python 上执行此操作。

我有一个类似的矩阵

matrix = np.array([[0,1,1,0,1,0],
                         [0,1,1,0,1,0]])
print 'matrix: ', matrix

考虑到重叠,我想在每一行上检查模式 [0,0]、[0,1] [1,0] 和 [1,1] 的出现情况。对于给出的示例,如果两行相等,则每个模式的结果都相等:

  • 模式[0,0] = [0,0]
  • 模式[0,1] = [2,2]
  • 模式[1,0] = [2,2]
  • 模式[1,1] = [1,1]

此示例中的矩阵非常小,但我正在寻找性能,因为我有一个巨大的矩阵。您可以使用 matrix = numpy.random.randint(2, size=(100000,10)) 或更大的矩阵来测试矩阵以查看差异

首先,我虽然在一个可能的答案上将行转换为字符串并查找基于 this answer 的事件( string count with overlapping occurrences ):

def string_occurrences(matrix):
    print '\n===== String count with overlapping ====='
    numRow,numCol = np.shape(matrix)
    Ocur = np.zeros((numRow,4))
    for i in range(numRow):
        strList = ''.join(map(str,matrix[i,:]))
        Ocur[i,0] = occurrences(strList,'00')
        Ocur[i,1] = occurrences(strList,'01')
        Ocur[i,2] = occurrences(strList,'10')
        Ocur[i,3] = occurrences(strList,'11')
    return Ocur

使用答案的函数occurrences

def occurrences(string, sub):
    count = start = 0
    while True:
        start = string.find(sub, start) + 1
        if start > 0:
            count+=1
        else:
            return count

但是考虑到真正的数组是巨大的,这个解决方案非常非常慢,因为它使用循环,字符串,... 因此,为了寻找一个 numpy 解决方案,我使用了一个技巧来将值与模式进行比较,并在 axis=1 上滚动矩阵以检查所有出现的情况。 我称它为 2D 上的伪滚动窗口,因为窗口不是方形的,计算方式也不同。有 2 个选项,其中第二个(选项 2)更快,因为它避免了 numpy.roll

的额外计算
def pseudo_rolling_window_Opt12(matrix):
    print '\n===== pseudo_rolling_window ====='
    numRow,numCol = np.shape(matrix)
    Ocur = np.zeros((numRow,4))
    index = 0
    for i in np.arange(2):
        for j in np.arange(2):
            #pattern = -9*np.ones(numCol)   # Option 1
            pattern = -9*np.ones(numCol+1)  # Option 2
            pattern[0] = i
            pattern[1] = j
            for idCol in range(numCol-1):
                #Ocur[:,index] += np.sum(np.roll(matrix,-idCol, axis=1) == pattern, axis=1) == 2    # Option 1: 219.398691893 seconds (for my real matrix)
                Ocur[:,index] += np.sum(matrix[:,idCol:] == pattern[:-(idCol+1)], axis=1) == 2      # Option 2:  80.929688930 seconds (for my real matrix)
            index += 1
    return Ocur

在寻找其他可能性时,我发现了“滚动窗口”,这似乎是性能的最佳答案,因为它使用了 numpy 函数。期待this answer ( Rolling window for 1D arrays in Numpy? ) 及其上的链接,我检查了以下功能。但实际上,我不理解输出,因为窗口的计算似乎与我对结果的预期相匹配。

def rolling_window(a, size):
    shape = a.shape[:-1] + (a.shape[-1] - size + 1, size)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

用作:

a = rolling_window(matrix, 2)
print a == np.array([0,1])
print np.all(rolling_window(matrix, 2) == [0,1], axis=1)

有人知道最后一个案例出了什么问题吗?或者是否有可能获得更好的性能?

最佳答案

您使用了错误的 numpy 数组轴。您应该将 np.all 中的轴从 1 更改为 2。 使用以下代码:

a = rolling_window(matrix, 2)
print np.all(rolling_window(matrix, 2) == [0,1], axis=2)

你得到:

>>>[[ True False False  True False]
    [ True False False  True False]]

因此,为了获得您正在寻找的结果:

print np.sum(np.all(rolling_window(matrix, 2) == [0,1], axis=2),axis=1)

>>>[2 2]

关于python - 每行 Numpy 中二维矩阵的滚动窗口或事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35031976/

相关文章:

python - 从单词列表中创建句子 x 次

python - 如何使用 pandas 查找内存泄漏

python - 无法在 scipy 中创建非空 csr.matrix()

python - 挑战蛮力方法的谜题?

python - 使用 TensorRT 部署语义分割网络(U-Net)(不支持上采样)

java - 如何在 Java 中打印矩阵的所有对角线

mongodb - MongoDb中的增量矩阵结构

c++ - 有没有办法在opencv c++中检查矩阵中的数据

python - 将参数传递给通用 View Django 查询集

python - 数据帧中每行的相关系数和 p 值