[Глубокое обучение] Многоканальный процесс свертки изображений и метод расчета

глубокое обучение алгоритм Нейронные сети
[Глубокое обучение] Многоканальный процесс свертки изображений и метод расчета

Ранее я написал сообщение в блоге,[Введение в глубокое обучение] - Реализация операции свертки изображения вручнуюВнесите соответствующие знания о свертке, но эта статья больше объясняет свертку с точки зрения фильтра. Но на самом деле содержание поста в блоге в нейросети не подходит.

Чтобы облегчить демонстрацию, предыдущая статья направлена ​​​​на двумерную свертку. Например, изображение имеет три цветовых канала RGB. Мой метод состоит в том, чтобы свернуть каждый канал отдельно, а затем объединить каждый канал в изображение и визуализировать его. . Но в реальном проекте такого не будет, и многие вещи нужно объяснять дополнительно.

Студенты, знакомые с TensorFlow, вероятно, знакомы с этой функцией.

tf.nn.conv2d(
    input,
    filter,
    strides,
    padding,
    use_cudnn_on_gpu=True,
    data_format='NHWC',
    dilations=[1, 1, 1, 1],
    name=None
)

Вход, естественно, является входом свертки, а фильтр, естественно, является фильтром. Описание их формата выглядит следующим образом:

input:
[batch, in_height, in_width, in_channels]

filter
[filter_height, filter_width, in_channels, out_channels]

Четыре параметра ввода хорошо понятны, а именно: номер пакета, высота, ширина и количество каналов.

Однако я сомневался и не мог понять, когда учился, почему у фильтра 2 параметра, относящихся к каналу?

По предложениям в интернете я, наверное, знаю, что in_channels ввода и in_channels фильтра должны совпадать, а out_channels — это количество каналов featuremap, сгенерированных после свертки, но я не знаю деталей расчет.

Почему изображение с цветовым каналом 3 после свертки может иметь 128 каналов или что-то в этом роде? Это мое сомнение.

Позже у меня возник этот вопрос, потому что я не понимал концепцию свертки.

Я ошибочно подумал, что фильтр в процессе свертки 2-мерный, только ширина и высота, а количество каналов равно 1.

这里写图片描述

На самом деле реальная ситуация такова, что в процессе свертки, сколько каналов есть у входного слоя, столько же каналов и у фильтра, но количество фильтров произвольное, а количество фильтров определяет канал карты признаков после свертки номер.

在这里插入图片描述

Если вход рассматривать как куб, то фильтр — тоже куб, результат их свертки — тоже куб, а каналы ввода, фильтра и результата в приведенном выше — одни и те же.

Однако последний шаг процесса свертки включает в себя генерацию признаков, Это очень просто, Признаки генерируются путем сложения значений соответствующих координат каждого канала Результата, что эквивалентно сжатию многомерного Результата в 2-х мерный признак.

Некоторые студенты могут спросить, зачем вам нужно сжимать Result до 2-х измерений?

Повторим, формулу свертки.

y (n) =∑ ∞ i =−∞ x( i)∗ h(n − i) y(n)=∑i=−∞∞x(i)∗h(n−i) y(n) = \ sum_{i=-\infty}^{\infty} x(i)*h(ni) y ( n)= i=-∞ ∑ ∞ ​ x(i) ∗ h(n− i )

Свертка есть не что иное, как процесс умножения и последующего накопления, так что с математической точки зрения это не нарушает правил.На самом деле реальная ситуация такова для канального соответствия процесса свертки.Причины анализируются ниже.

Раньше мы были обеспокоены тем, что во всей литературе фильтры упоминались как 3x3 или 5x5, что заставляло нас ошибочно думать, что фильтры могут быть только 2-мерными.

Есть также осторожные студенты спросят,Как изменить количество каналов во входном слое в процессе свертки?

Например, входной слой — это цветное изображение, у него 3 канала RGB, но карта характеристик после свертки имеет 128 каналов, так как же это реализовано?

Секрет в количестве фильтров
在这里插入图片描述

Все обращают внимание на приведенный выше рисунок.Мы предполагаем, что N используется для представления количества фильтров, тогда каждый фильтр будет генерировать двумерный признак, N фильтров будут генерировать N признаков, а N признаков будут формировать свернутую карту признаков, а N - это количество каналов карты характеристик.

input:
[batch, in_height, in_width, in_channels]

filter
[filter_height, filter_width, in_channels, out_channels]

Давайте посмотрим на описание параметра фильтра в Tensorflow, понятно ли оно с первого взгляда?

Мы также можем хорошо понять красоту результата свертки одного фильтра, который нужно сжать в 2 измерения, что гарантирует, что количество выходных каналов после свертки соответствует количеству фильтров свертки.

Код

В предыдущей статье я рассматривал только 2 измерения в процессе реализации свертки, и способ реализации был более традиционным.

def _con_each(src_block,kernel):
    pixel_count = kernel.size;
    pixel_sum = 0;
    _src = src_block.flatten();
    _kernel = kernel.flatten();
    
    
    for i in range(pixel_count):
        pixel_sum += _src[i]*_kernel[i];
        
    return pixel_sum 

Теперь можно делать улучшения.

Я сказал раньше,Суть формулы свертки — это процесс умножения, а затем накопления, а его результат — числовое значение. И скалярное произведение двух векторов в линейной алгебре можно представить именно так, так что его можно полностью переписать.

import numpy as np

def _conv_epoch(src_block,filter):
    input = src_block.flatten()
    filter = filter.flatten().T

    return np.dot(input,filter)

Конечно, свертка полного изображения должна повторяться по сканам много раз.

"""
input_size:(h,w,c)
filter_size:(h,w,ic,oc)
"""
def conv(img,input_size,filter_size,stride=1):
    ih = input_size[0]
    iw = input_size[1]
    ic = input_size[2]

    filter_oc = filter_size[3]
    filter_h = filter_size[0]
    filter_w = filter_size[1]
    filter_ic = filter_size[2]

    l = int((ih - filter_h) / stride + 1)
    m = int((iw - filter_w) / stride + 1)

    result = np.zeros(shape=(l,m,filter_oc),dtype=np.uint8)

    for i in range(l):
        for j in range(m):
            for k in range(filter_oc):
                f = np.random.uniform(0,1,filter_w*filter_h*filter_ic).T
                input = img[i:i+filter_h,j:j+filter_w,:]

                result[i,j,k] = _conv_epoch(input,f)

    return result

Теперь мы можем проверить эффект нашего кода.

def test():
    img = plt.imread("../datas/cat.jpg")

    print("img shape ",img.shape)

    result = conv(img,img.shape,(3,3,img.shape[2],3))

    plt.figure()
    plt.subplot(121)
    plt.imshow(img)
    plt.subplot(122)
    plt.imshow(result)
    plt.show()

test()

Прочитайте фотографию кошки и сравните ее эффект свертки.Обратите внимание, что я установил количество фильтров равным 3 для демонстрационных целей.

Окончательный эффект выглядит следующим образом:
在这里插入图片描述

Следует отметить, что значения фильтров полностью случайны, но с точки зрения эффекта они все же извлекают некоторые детали контура. Видно, что мощность операции свертки велика. При глубоком обучении нейронная сеть обычно имеет сотни или тысячи фильтров, и благодаря повторному обучению они, наконец, формируют надежную способность выражения признаков.

Наконец, что я хочу отметить, так это то, что процесс свертки очень медленный, и специальное изменение реализовано в python, хотя я изменил код свертки на основе предыдущей статьи, так что цикл for заменен на метод векторного скалярного произведения. Но процесс свертки всего изображения также можно улучшить, что включает в себя процесс, называемыйim2colОбщий принцип состоит в том, чтобы сделать матричное умножение более тщательно вовлеченным в процесс свертки. Наконец, весь процесс свертки представлен матричным умножением. Из-за ограниченного места заинтересованные студенты могут самостоятельно искать соответствующую литературу.