Понимание свертки и фильтрации изображений в сверточных нейронных сетях

глубокое обучение

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

LeNet является создателем различных глубоких сверточных нейронных сетей. Впервые он был предложен Яном Лекуном в 1989 году, а также является одной из первых сверточных нейронных сетей, которая способствовала развитию глубокого обучения. После многих успешных итераций он был назван LeNet5. , когда фреймворк LeNet в основном использовался для задач распознавания символов.

В ранней традиционной нейронной сети, такой как нейронная сеть BP, люди обычно полагаются на опыт экспертов для разработки вектора входных признаков. По опыту последних нескольких десятилетий признаки, найденные вручную, не обязательно эффективны.Среди них, алгоритмы раннего распознавания лиц, как правило, приняли идею объединения искусственных признаков и классификаторов.Пик искусственных признаков приходится на CVPR 2013 MSRA" Благословение многомерности: функция большого размера и ее эффективное сжатие для проверки лиц», статья о том, как использовать функции высокой размерности при проверке лица. Существуют зрелые схемы для классификаторов, такие как нейронные сети, машины опорных векторов, байесовские и т. д. Это выглядит многообещающе, но у нас мало специалистов и недостаточная вычислительная мощность для удовлетворения потребностей в многомерных вычислениях.

Давайте сначала сделаем простое и интуитивно понятное решение. Если какой-либо признак извлекается из изображения, все изображение используется в качестве признака для обучения нейронной сети.Объем данных поражает! В этом случае приходится делать уменьшение размерности, поэтому вводится понятие свертки.

С 2012 года, после того как на ILSVRC-2012 засветилось глубокое обучение, были продемонстрированы и применены возможности сверточной нейронной сети в классификации изображений, и ядро ​​свертки, полученное в результате обучения, явно лучше, чем комбинация искусственно созданных признаков и классификаторов. Исследователи в области распознавания лиц используют сверточную нейронную сеть (CNN) для обучения на массивных изображениях лиц, а затем извлекают векторы признаков, полезные для различения лиц разных людей на входном изображении, заменяя искусственно созданные черты.

DeepFace — это метод, предложенный Facebook на CVPR 2014. Он является основой глубокой сверточной нейронной сети в области распознавания лиц, использует классическую функцию кросс-энтропийных потерь (Softmax) для оптимизации задачи и, наконец, использует встраивание функций (Feature Embedding). ) Получите вектор признаков лица фиксированной длины. DeepFace достиг точности 97,35% на LFW, что близко к человеческому уровню. По сравнению со шкалой данных 40 человек и 400 фотографиями 40 человек на основе сверточной нейронной сети в 1997 году Facebook собрал 4 миллиона фотографий 4000 человек для обучения модели.Может быть, можно сделать вывод: искусственный интеллект больших данных добился успеха!

1. Основные принципы свертки

В функциональном анализе свертка — это определение функции. Это математический оператор, порождающий третью функцию через две функции f и g и характеризующий площадь перекрывающейся части функции f и g после переворачивания и переноса.

Математическое определение свертки выглядит следующим образом:在这里插入图片描述В области компьютерного зрения ядра свертки и фильтры обычно представляют собой матрицы небольшого размера, такие как 3×3, 5×5 и т. д., а цифровые изображения представляют собой двумерные тензоры относительно больших размеров.Операции свертки изображений и операции корреляции Отношения показаны на рисунке ниже. где F — фильтр, x — входное изображение, а O — выход.在这里插入图片描述 在这里插入图片描述Формула расчета дискретной свертки выглядит следующим образом:在这里插入图片描述

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

import skimage.color
import skimage.io
import numpy
import numpy as np
import matplotlib
import sys

def conv_(img, conv_filter):
    filter_size = conv_filter.shape[0]

    result = numpy.zeros((img.shape))
    padding_size = 1
    #在输入图像中循环应用卷积操作.

    #滤波图像行的取值范围
    for row in range(0, img.shape[0]-filter_size + padding_size):
        for col in range(0, img.shape[1]-filter_size + padding_size):
            #按滤波器尺寸获取筛选区域.
            curr_region = img[row:row+filter_size, col:col+filter_size]
            #筛选区域与滤波器相乘.
            curr_result = curr_region * conv_filter
            conv_sum = numpy.sum(curr_result) #相乘后求和
            result[row + padding_size, col + padding_size] = conv_sum #卷积层特征映射中求和的保存
            
    #剪裁结果矩阵.
    final_result = result[padding_size:result.shape[0]-padding_size,padding_size:result.shape[1]-padding_size]
    return final_result

def conv(img, conv_filter):
    if len(img.shape) > 2 or len(conv_filter.shape) > 3: # 检查图像通道数与滤波器通道数是否一致.
        if img.shape[-1] != conv_filter.shape[-1]:
            print("Error: Number of channels in both image and filter must match.")
            sys.exit()
    if conv_filter.shape[1] != conv_filter.shape[2]: # Check if filter dimensions are equal.
        print('Error: Filter must be a square matrix. I.e. number of rows and columns must match.')
        sys.exit()
    if conv_filter.shape[1]%2==0: # Check if filter diemnsions are odd.
        print('Error: Filter must have an odd size. I.e. number of rows and columns must be odd.')
        sys.exit()

    # 初始化输出特征图为0,大小尺寸与输入图形一致
    feature_maps = numpy.zeros((img.shape[0]-conv_filter.shape[1]+1, 
                                img.shape[1]-conv_filter.shape[1]+1, 
                                conv_filter.shape[0]))

    # 使用滤波器进行卷积操作.
    for filter_num in range(conv_filter.shape[0]):
        print("Filter ", filter_num + 1)
        curr_filter = conv_filter[filter_num, :] # getting a filter from the bank.
        """ 
        Checking if there are mutliple channels for the single filter.
        If so, then each channel will convolve the image.
        The result of all convolutions are summed to return a single feature map.
        """
        if len(curr_filter.shape) > 2:
            conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0]) 
            for ch_num in range(1, curr_filter.shape[-1]): 
                conv_map = conv_map + conv_(img[:, :, ch_num], curr_filter[:, :, ch_num])
        else: # There is just a single channel in the filter.
            conv_map = conv_(img, curr_filter)
        feature_maps[:, :, filter_num] = conv_map
    return feature_maps 
    
img = skimage.io.imread("timg1.jpg")
img = skimage.color.rgb2gray(img)

l1_filter = numpy.zeros((2,3,3))  #定义卷积核
l1_filter[0, :, :] = numpy.array([[[-1, 0, 1], 
                                   [-1, 0, 1], 
                                   [-1, 0, 1]]])
l1_filter[1, :, :] = numpy.array([[[1,   1,  1], 
                                   [0,   0,  0], 
                                   [-1, -1, -1]]])

l1_feature_map = conv(img, l1_filter)

# 画出结果图
fig0, ax0 = matplotlib.pyplot.subplots(nrows=1, ncols=1)
ax0.imshow(img).set_cmap("gray")
ax0.set_title("Input Image")
matplotlib.pyplot.savefig("in_img.png", bbox_inches="tight")
matplotlib.pyplot.close(fig0)

fig1, ax1 = matplotlib.pyplot.subplots(nrows=1, ncols=2)
ax1[0].imshow(l1_feature_map[:, :, 0]).set_cmap("gray")
ax1[0].set_title("Map1")

ax1[1].imshow(l1_feature_map[:, :, 1]).set_cmap("gray")
ax1[1].set_title("Map2")

matplotlib.pyplot.savefig("Out_Map.png", bbox_inches="tight")
matplotlib.pyplot.close(fig1)matplotlib.pyplot.close(fig1)

Изображение отфильтровано программой, эффект показан на рисунке ниже, и захвачены контурные элементы.在这里插入图片描述

2. Ядро свертки

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

Форма ядра обычно необычная. Например, 3 × 3, 5 × 5, 7 × 7, это может гарантировать, что должна быть центральная точка (количество пикселей является наименьшей единицей, понятие числа субпикселей отсутствует), в основном с точки зрения кодирование пикселей, нечетные числа, кажется, подчеркивают. Если эту точку пикселя удалить, четное число вызовет баланс или смещение, устраняя характеристики этой точки. 3×3 — это наименьший размер, способный зафиксировать информацию о соседстве размером восемь пикселей. Значение каждого элемента ядра свертки обычно добавляется равным 1. Причина этого заключается в том, чтобы гарантировать, что яркость исходного изображения за счет действия ядра свертки останется неизменной (но этот принцип не требуется). На рисунке 9-3 Схематическая диаграмма процесса вычисления свертки входная двумерная матрица 6×7 фильтруется ядром свертки, а выходным результатом является матрица 4×5 с отступами по краям. добавление "0" вокруг.在这里插入图片描述Операция свертки уменьшит изображение. Чтобы сохранить размер изображения после свертки, его необходимо дополнить 0. В тензорном потоке, если padding = 'same', в соответствии с эффектом предыдущей практики, легко неправильно понять, размер матрицы после свертки не изменяется, а формула фактического размера выглядит следующим образом: Установите высоту входного изображения как Hin и ширину как Win, высоту ядра свертки как HF и ширину как WF, а выходной результат как старший бит Hout, ширину как Wout и шаг как шаг.在这里插入图片描述Когда шаг = 1, размер изображения не изменяется после операции свертки padding = 'same' и должен быть заполнен 0; когда padding = 'valid', размер изображения становится равным Hout, Wout, а результат округляется. вверх. Когда шаг не равен 1, Wout=Win/шаг, Hout=Hin/шаг (результат округляется в большую сторону), и после свертки изображение все равно становится меньше. Насколько велико ядро ​​свертки? Текущий опыт в отрасли — 3 × 3, который имеет очень хорошие результаты и производительность.

Что касается ядра свертки, ранняя точка зрения заключалась в том, что чем больше ядро ​​свертки, тем в AlexNet используются некоторые очень большие ядра свертки, такие как ядра свертки 11 × 11 и 5 × 5. Чем больше информации на картинке, тем лучше полученные черты. Однако большое ядро ​​свертки приведет к резкому увеличению объема вычислений, что не способствует увеличению глубины модели, а также снизится производительность вычислений. Следовательно, в VGG (самое раннее использование) и сети Inception комбинация двух ядер свертки 3×3 более эффективна, чем одно ядро ​​свертки 5×5, а количество параметров (3×3×2+1 и 5×5 ×1+1 контрастность) уменьшается, поэтому в дальнейшем в различных моделях широко используются ядра свертки 3×3.

3. Свертка и изображение

Фильтрация изображения заключается в применении к изображению небольшого ядра свертки, чтобы выделить нужные нам функции изображения. Далее, давайте взглянем на магию некоторых простых, но не простых ядер свертки. Следующий код основан на функции свертки Tensorflow tf.nn.conv2d, которая использует различные ядра свертки для фильтрации изображений.

import tensorflow as tf
import skimage.color
import skimage.io
import numpy as np
import matplotlib

img = skimage.io.imread("timg1.jpg")
img = skimage.color.rgb2gray(img)

img1 = img #img.flatten() #转为一维数组

l1_filter1 = np.array([[-1, 0, 1], 
                       [-1, 0, 1], 
                       [-1, 0, 1]])

l1_filter1 = l1_filter1.astype("float64")
x_image = tf.reshape(img1, [1,420,300,1])
W_filter = tf.reshape(l1_filter1, [3,3,1,1])

input_tensor = tf.Variable(x_image,  name='input')
input_weight = tf.Variable(W_filter, dtype="float64",  name='weight')

op = tf.nn.conv2d(input_tensor,input_weight, strides=[1, 1, 1, 1], padding='SAME')

init = tf.initialize_all_variables() 
with tf.Session() as sess:
    sess.run(init)
    feature_map = sess.run(op)

# 画出结果图
fig0, ax0 = matplotlib.pyplot.subplots(nrows=1, ncols=1)
ax0.imshow(img).set_cmap("gray")
ax0.set_title("Input Image")
matplotlib.pyplot.savefig("in_img1.png", bbox_inches="tight")
matplotlib.pyplot.close(fig0)

fig1, ax1 = matplotlib.pyplot.subplots(nrows=1, ncols=1)
ax1.imshow(feature_map[0,:, :, 0]).set_cmap("gray")
ax1.set_title("Map1")
matplotlib.pyplot.savefig("Out_Map1.png", bbox_inches="tight")
matplotlib.pyplot.close(fig1)

Примечание. Среди них, что касается свертки Tensorflow, требования в conv2d следующие:

Четыре измерения ввода: [партия, in_height, in_width, in_channels], Четыре измерения фильтра: [filter_height, filter_width, in_channels, out_channels].

Пример эффекта отфильтрованного изображения с использованием различных ядер свертки показан ниже.在这里插入图片描述

在这里插入图片描述

Ссылаться на:

«Используйте пакет научных вычислений Python для создания практики алгоритма CNN (1)»Блог CSDN Сяо Юнвэй 2018.05

«Сверточная нейронная сеть TensorFlow CNN реализует классификацию и распознавание условий работы (1)»Блог CSDN Сяо Юнвэй 2019.03