首页 > 解决方案 > 使用滑动窗口分类器在 2D 阵列上进行 1-in-N 分类的高效多数投票

问题描述

简短版本:我想使用二维数组中的值来索引更大数组的相应子集的第三维 - 然后增加这些元素。

我将不胜感激帮助使两个合并投票算法更快。实际上,在数组上滑动分类器并计算最佳步幅并不是这里的重点。

长版:我有一个算法,它将 R1xC1 2D 数组中的每个元素分类为 N 个类中的 1 个。

我想对大小为 R2xC2 的较大二维数组进行分类。我不想将较大的阵列细分为多个 R1xC1 2D 阵列,而是将分类器滑到较大的阵列上,以便对较大阵列中的每个元素进行多次分类。这意味着我将有一个 R2xC2xN 数组来存储结果,并且当窗口在大数组中滑动时,窗口中的每个像素都会增加第三维中的一个元素(即 N 类之一)。

在所有的滑动完成后,我们可以简单地得到分类对应维度中的argmax,得到每个元素的分类。

我打算将其放大以对具有几十个像素的数百万像素的数组进行分类,因此我关心使用分类结果在每个元素的分类维度中增加一个值的效率。

下面是我在 Python3 中整晚都在制作的问题的玩具版本。它有一个简单的 double for 循环实现和一个稍微好一点的通过 index swizzling 和一些智能索引获得的。分类器只是随机的。

import numpy as np

map_rows = 8
map_cols = 10
num_candidates = 3
vote_rows = 6
vote_cols = 5


def display_tally(the_tally):
    print("{:25s}{:25s}{:25s}".format("Class 0", "Class 1", "Class 2"))
    for i in range(map_rows):
        for k in range(num_candidates):
            for j in range(map_cols):
                print("{:<2}".format(the_tally[i, j, k]), end='')
            print("     ", end='')
        print("")


def incorporate_votes(current_tally, this_vote, left, top):
    for i in range(vote_rows):
        for j in range(vote_cols):
            current_tally[top + i, left + j, this_vote[i, j]] += 1
    return current_tally


def incorporate_votes2(current_tally, this_vote, left, top):
    for i in range(num_candidates):
        current_tally[i, top:top + vote_rows, left:left + vote_cols][this_vote == i] += 1
    return current_tally


tally = np.zeros((map_rows, map_cols, num_candidates), dtype=int)
swizzled_tally = np.zeros((num_candidates, map_rows, map_cols), dtype=int)
print("Before voting")
display_tally(tally)

print("\n Votes from classifier A (centered at (2,2))")
votes = np.random.randint(num_candidates, size=vote_rows*vote_cols).reshape((vote_rows, vote_cols))
print(votes)

tally = incorporate_votes(tally, votes, 0, 0)
swizzled_tally = incorporate_votes2(swizzled_tally, votes, 0, 0)

print("\nAfter classifier A voting (centered at (2,2))")
display_tally(tally)

print("\n Votes from classifier B (Centered at (5, 4))")
votes2 = np.random.randint(num_candidates, size=vote_rows*vote_cols).reshape((vote_rows, vote_cols))
print(votes2)

tally = incorporate_votes(tally, votes2, 3, 2)
swizzled_tally = incorporate_votes2(swizzled_tally, votes2, 3, 2)

print("\nAfter classifier B voting (Centered at (5, 4))")
print("Naive vote counting")
display_tally(tally)
print("\nSwizzled vote counting")
display_tally(np.moveaxis(swizzled_tally, [-2, -1], [0, 1]))

new_tally = np.moveaxis(tally, -1, 0)
classifications = np.argmax(swizzled_tally, axis=0)
print("\nNaive classifications")
print(classifications)

print("\nSwizzled classifications")
classifications = np.argmax(tally, axis=2)
print(classifications)

还有一些示例输出:

Before voting
Class 0                  Class 1                  Class 2                  
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      

 Votes from classifier A (centered at (2,2))
[[1 1 2 2 1]
 [0 2 0 2 1]
 [0 2 2 0 2]
 [1 1 1 2 0]
 [1 0 0 2 1]
 [2 1 1 1 0]]

After classifier A voting (centered at (2,2))
Class 0                  Class 1                  Class 2                  
0 0 0 0 0 0 0 0 0 0      1 1 0 0 1 0 0 0 0 0      0 0 1 1 0 0 0 0 0 0      
1 0 1 0 0 0 0 0 0 0      0 0 0 0 1 0 0 0 0 0      0 1 0 1 0 0 0 0 0 0      
1 0 0 1 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 1 1 0 1 0 0 0 0 0      
0 0 0 0 1 0 0 0 0 0      1 1 1 0 0 0 0 0 0 0      0 0 0 1 0 0 0 0 0 0      
0 1 1 0 0 0 0 0 0 0      1 0 0 0 1 0 0 0 0 0      0 0 0 1 0 0 0 0 0 0      
0 0 0 0 1 0 0 0 0 0      0 1 1 1 0 0 0 0 0 0      1 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      0 0 0 0 0 0 0 0 0 0      

 Votes from classifier B (Centered at (5, 4))
[[2 2 2 0 0]
 [0 1 2 1 2]
 [2 0 0 2 0]
 [2 2 1 1 1]
 [1 2 0 2 1]
 [1 1 1 1 2]]

After classifier B voting (Centered at (5, 4))
Naive vote counting
Class 0                  Class 1                  Class 2                  
0 0 0 0 0 0 0 0 0 0      1 1 0 0 1 0 0 0 0 0      0 0 1 1 0 0 0 0 0 0      
1 0 1 0 0 0 0 0 0 0      0 0 0 0 1 0 0 0 0 0      0 1 0 1 0 0 0 0 0 0      
1 0 0 1 0 0 1 1 0 0      0 0 0 0 0 0 0 0 0 0      0 1 1 1 2 1 0 0 0 0      
0 0 0 1 1 0 0 0 0 0      1 1 1 0 1 0 1 0 0 0      0 0 0 1 0 1 0 1 0 0      
0 1 1 0 1 1 0 1 0 0      1 0 0 0 1 0 0 0 0 0      0 0 0 2 0 0 1 0 0 0      
0 0 0 0 1 0 0 0 0 0      0 1 1 1 0 1 1 1 0 0      1 0 0 1 1 0 0 0 0 0      
0 0 0 0 0 1 0 0 0 0      0 0 0 1 0 0 0 1 0 0      0 0 0 0 1 0 1 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 1 1 1 1 0 0 0      0 0 0 0 0 0 0 1 0 0      

Swizzled vote counting
Class 0                  Class 1                  Class 2                  
0 0 0 0 0 0 0 0 0 0      1 1 0 0 1 0 0 0 0 0      0 0 1 1 0 0 0 0 0 0      
1 0 1 0 0 0 0 0 0 0      0 0 0 0 1 0 0 0 0 0      0 1 0 1 0 0 0 0 0 0      
1 0 0 1 0 0 1 1 0 0      0 0 0 0 0 0 0 0 0 0      0 1 1 1 2 1 0 0 0 0      
0 0 0 1 1 0 0 0 0 0      1 1 1 0 1 0 1 0 0 0      0 0 0 1 0 1 0 1 0 0      
0 1 1 0 1 1 0 1 0 0      1 0 0 0 1 0 0 0 0 0      0 0 0 2 0 0 1 0 0 0      
0 0 0 0 1 0 0 0 0 0      0 1 1 1 0 1 1 1 0 0      1 0 0 1 1 0 0 0 0 0      
0 0 0 0 0 1 0 0 0 0      0 0 0 1 0 0 0 1 0 0      0 0 0 0 1 0 1 0 0 0      
0 0 0 0 0 0 0 0 0 0      0 0 0 1 1 1 1 0 0 0      0 0 0 0 0 0 0 1 0 0      

Naive classifications
[[1 1 2 2 1 0 0 0 0 0]
 [0 2 0 2 1 0 0 0 0 0]
 [0 2 2 0 2 2 0 0 0 0]
 [1 1 1 0 0 2 1 2 0 0]
 [1 0 0 2 0 0 2 0 0 0]
 [2 1 1 1 0 1 1 1 0 0]
 [0 0 0 1 2 0 2 1 0 0]
 [0 0 0 1 1 1 1 2 0 0]]

Swizzled classifications
[[1 1 2 2 1 0 0 0 0 0]
 [0 2 0 2 1 0 0 0 0 0]
 [0 2 2 0 2 2 0 0 0 0]
 [1 1 1 0 0 2 1 2 0 0]
 [1 0 0 2 0 0 2 0 0 0]
 [2 1 1 1 0 1 1 1 0 0]
 [0 0 0 1 2 0 2 1 0 0]
 [0 0 0 1 1 1 1 2 0 0]]

标签: pythonarrayspython-3.xnumpymatrix-indexing

解决方案


推荐阅读