0

Just pondering this question I discovered this algorithm that works in O(mn) time if the convolutional 2d array is mn.

see how. just computing the same for a 1D case where we need to find the answer of maximum in every window of size k in an array. using deque. See this for more details https://www.geeksforgeeks.org/sliding-window-maximum-maximum-of-all-subarrays-of-size-k/

Assume in 2D case k is filter size , stride is 1 0 padding and n*m matrix.

Step1 then computing max of all window of size k gives the answer of maximum window of size k in each row. after computing this over all rows.

Step2 After that in transformed matrix do the same for columns that is maximum in sliding window of size k over each column in the modified matrix. After repeating that you will get maximum of whole sub array of size k*k which start at cell i ,j as top left corner and i+k-1 , j+k-1 as bottom right corner in position i,j of the matrix.

Proof is simple.

when you have maximum of k rows then computing maximum in a window of size k over column gives the maximum over whole matrix.

Example

5 3 2 1 4

2 3 1 5 3

1 2 3 4 6

1 2 3 4 5

5 4 3 2 1

assume n=5 m=5 and k=3.

modified matrix looks like

5 3 4

3 5 3

3 4 6

3 4 5

5 4 3

Further applying step2 looks like.

5 5 6

3 5 6

5 4 6

And that's it we have max pooling layer in front of us.

Is it a good algorithm that can bring optimization to the CNN models or is there any better existing algorithm for this? Please post your opinion?

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
Mohnish
  • 41
  • 1
  • 5

1 Answers1

0

2D max-pooling Best Time Complexity is O(nm)

Here is my C++ code:

#include <iostream>
#include <vector>
#include <deque>
#include <cstring>

using namespace std;

typedef long long LL;

const int N = 1e3;
int g[N][N];

void max_window(int l1, int l2, int r1, int r2, int k) {
    vector<int> nums;

    // Time: max(n, m)
    for (int i = l1; i <= r1; i ++) {
        for (int j = l2; j <= r2; j ++) {
            nums.push_back(g[i][j]);
        }
    }

    vector<int> res;
    deque<int> q;
    for (int i = 0; i < nums.size(); i ++) {
        while (q.size() && i - q.front() >= k) q.pop_front();

        while (q.size() && nums[q.back()] <= nums[i]) q.pop_back();

        q.push_back(i);        
        if (i >= k - 1) res.push_back(nums[q.front()]);
    }

    int cnt = 0;
    for (int i = l1; i <= r1; i ++) {
        for (int j = l2; j <= r2; j ++) {
            if (cnt >= res.size()) break;
            g[i][j] = res[cnt];
            cnt ++;
        }
    }
    return;
}


int main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif

    int n, m, a, b;
    cin >> n >> m >> a >> b;
    for (int i = 0; i < n; i ++) {
        for (int j = 0; j < m; j ++) {
            cin >> g[i][j];
        }
    }

    for (int i = 0; i < n; i ++) {
        for (int j = 0; j < m; j ++) {
            cout << g[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;

    // shape: n x m
    for (int i = 0; i < n; i ++) {  
        max_window(i, 0, i, n - 1, b);
    }


    for (int j = 0; j < m - b + 1; j ++) {  // shape:n x (m - b + 1)
        max_window(0, j, m - 1, j, a);
    }

    // shape:(n - a + 1) x (m - b + 1)
    for (int i = 0; i < n - a + 1; i ++) {
        for (int j = 0; j < m - b + 1; j ++) {
            cout << g[i][j] << " ";
        }
        cout << endl;
    }
    
    return 0;
}

Input:

5 5 3 3
5 3 2 1 4
2 3 1 5 3
1 2 3 4 6
1 2 3 4 5
5 4 3 2 1

Output:

5 3 2 1 4 
2 3 1 5 3
1 2 3 4 6
1 2 3 4 5
5 4 3 2 1

5 5 6
3 5 6
5 4 6

Btw, here is the 1-dim max-pooling example whose best time complexity is O(n). https://leetcode.com/problems/sliding-window-maximum/

Patrick J. Holt
  • 516
  • 4
  • 7