Python: Реализация im2col, которая использует преимущества 6-мерного массива? - PullRequest
0 голосов

Я читаю реализацию im2col из книги глубокого обучения (в главе 7, CNN), цель которой - преобразовать 4-мерный массив в 2-мерный. Я не знаю, почему в реализации есть 6-мерный массив. Меня очень интересует идея алгоритма, использованного автором.

Я пытался найти во многих статьях реализацию im2col, но ни в одной из них не было такого многомерного массива. В настоящее время материалы, которые я нашел полезными для визуализации процесса im2col, представляют собой изображение этой бумаги - HAL Id: inria-00112631


def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
    """
    Parameters
    ----------
    input_data : (batch size, channel, height, width), or (N,C,H,W) at below
    filter_h : kernel height
    filter_w : kernel width
    stride : size of stride
    pad : size of padding
    Returns
    -------
    col : two dimensional array
    """
    N, C, H, W = input_data.shape
    out_h = (H + 2*pad - filter_h)//stride + 1
    out_w = (W + 2*pad - filter_w)//stride + 1

    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

    for y in range(filter_h):
        y_max = y + stride*out_h
        for x in range(filter_w):
            x_max = x + stride*out_w
            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
    return col

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Давайте попробуем визуализировать, что делает im2col. Он принимает в качестве входных данных стек цветных изображений, стек имеет размеры изображения id, цветовой канал, вертикальное положение, горизонтальное положение. Давайте для простоты предположим, что у нас есть только одно изображение:

enter image description here

Первое, что он делает, это заполнение:

enter image description here

Затем он разрезает его на окна. Размер окон контролируется filter_h/w, перекрытие strides.

enter image description here

Вот откуда берутся шесть измерений: идентификатор изображения (отсутствует в примере, потому что у нас только одно изображение), высота / ширина сетки, цветовой канал. высота / ширина окна.

enter image description here

Алгоритм в его нынешнем виде немного неуклюж, он собирает выходные данные в неправильном порядке измерений и затем должен исправить это, используя transpose.

Лучше понять все правильно:

def im2col_better(input_data, filter_h, filter_w, stride=1, pad=0):
    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
    N, C, H, W = img.shape
    out_h = (H - filter_h)//stride + 1
    out_w = (W - filter_w)//stride + 1
    col = np.zeros((N, out_h, out_w, C, filter_h, filter_w))
    for y in range(out_h):
        for x in range(out_w):
            col[:, y, x] = img[
                ..., y*stride:y*stride+filter_h, x*stride:x*stride+filter_w]
    return col.reshape(np.multiply.reduceat(col.shape, (0, 3)))

Как примечание: мы можем сделать еще лучше, используя stride_tricks и избегая вложенного цикла for:

def im2col_best(input_data, filter_h, filter_w, stride=1, pad=0):
    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
    N, C, H, W = img.shape
    NN, CC, HH, WW = img.strides
    out_h = (H - filter_h)//stride + 1
    out_w = (W - filter_w)//stride + 1
    col = np.lib.stride_tricks.as_strided(img, (N, out_h, out_w, C, filter_h, filter_w), (NN, stride * HH, stride * WW, CC, HH, WW)).astype(float)
    return col.reshape(np.multiply.reduceat(col.shape, (0, 3)))

Последнее, что делает алгоритм, это изменение формы, объединяя первые три измерения (опять только два в нашем примере, потому что только одно изображение). Красные стрелки показывают, как отдельные окна выстроены в первое новое измерение:

enter image description here

Последние три измерения цветовой канал, координата y в окне, координата x в окне объединяются во второе выходное измерение. Отдельные пиксели выровнены, как показано желтыми стрелками:

enter image description here

0 голосов
/ 13 мая 2018

Похоже, что эта функция просто переставляет каждый из C цветовых каналов в каждом из N изображений в (out_h x out_w) сетку перекрывающихся фрагментов изображения размером (filter_h x filter_w), а затем выравнивает это в 2d массив, где каждая строка представляет собой вектор пикселей в патче изображения.

Размеры 6-D col (до транспонирования и изменения формы):

[sample, channel, y_position_within_patch, x_position_within_patch, y_patch_index, x_patch_index]

Так, например, col[n, c, :, :, i, j] будет патчем для 2-го изображения (i-й патч сверху и j-й слева в сетке патчей изображения).

После транспонирования и изменения формы, col[n*c*i*j, :] будет ссылаться на этот же патч изображения, но со всеми пикселями, сплющенными в вектор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...