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

Вы можете использовать любой язык, Python или R, или можете использовать любую библиотеку, такую ​​как Tensorflow, TFlearn или keras и т. д. На самом деле это не имеет значения, если вы понимаете концепцию.

Цель этой статьи — показать, как создавать собственные данные и применять к ним CNN с помощью TFlearn, и я запустил этот код в Google Colab.

По определению: TFlearn — это модульная и прозрачная библиотека глубокого обучения, построенная на основе Tensorflow. Он был разработан, чтобы предоставить API более высокого уровня для TensorFlow, чтобы облегчить и ускорить эксперименты, оставаясь при этом полностью прозрачным и совместимым с ним.

В. Почему CNN?

А. CNN — это сверточная нейронная сеть, которая обычно используется для распознавания изображений. Практическая выгода заключается в том, что меньшее количество параметров значительно сокращает время, необходимое для обучения, а также уменьшает объем данных, необходимых для обучения модели. Вместо полносвязной сети весов каждого пикселя у CNN достаточно весов, чтобы просмотреть небольшой участок изображения.

В. Но тогда зачем использовать пользовательские данные?

A. Были бы тысячи статей о наборе данных MNIST, но затем в этом предварительно обработанном наборе данных вы на самом деле не знаете, как извлекать новые изображения и создавать набор данных самостоятельно, изменять размер изображений, упорядочивать изображения. и пометить их .
Установите google_images_download, чтобы загружать пользовательские изображения по нашему выбору. Введите это в cmd.

! pip install google_images_download

СВЕРТОЧНАЯ НЕЙРОННАЯ СЕТЬ

СЛОЙ CNN

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

В. Но что будут делать эти фильтры?
A.
Теперь каждый из этих фильтров фактически является детектором признаков. Например, на изображениях ниже вы можете видеть, что каждый фильтр обнаруживает разные функции. Чтобы понять это немного лучше, если ваше изображение было КОШКА, тогда, возможно, один фильтр детектора признаков обнаруживает глаза, другой — нос, третий — уши и т. д.
Аналогично в этом изображение под каждым фильтром ищет и обнаруживает функцию, и мы получаем карту функций. И, наконец, после использования различных фильтров у нас есть коллекция карт объектов, которые составляют наш сверточный слой.
Теперь, что касается понимания процесса обнаружения объектов, это видео Эндрю Нг — лучшее, что вы можете найти.

В. Почему ReLU используется в качестве функции активации?
A . Что ж, мы используем ReLU в качестве функции активации, чтобы увеличить нелинейность. Тогда на ум приходит вопрос, почему нелинейность.
Итак, ReLU — это выпрямленная линейная единица, и она определяется как y = max(0, x), где x — это входные данные для нейрона.

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

Здесь у нас есть карта признаков из одного фильтра, и она черно-белая, теперь после применения ReLU у нас есть только неотрицательные значения, т.е. вся черная окраска удалена. Теперь переход пикселей на карте признаков для перехода от области черного цвета к области белого цвета является линейным, т. е. сначала черный, затем темно-сероватый, затем сероватый, а затем белый. Но при применении ReLU у нас появляется резкий контраст цвета и, следовательно, увеличивается нелинейность.

ОБЪЕДИНЯЮЩИЙ СЛОЙ

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

В. Но что делает этот максимальный пул?
A.
Максимальный пул делается для того, чтобы получить максимум в пуле. Теперь этот шаг выполняется после слоя свертки, и во время свертки мы обнаруживаем признаки. Итак, давайте возьмем пример, чтобы лучше понять. Если бы изображение было изображением кошки, то, возможно, одной из особенностей, обнаруженных сверточным слоем, могли бы быть глаза, теперь эти глаза могут быть расположены в любом месте изображения, на некоторых изображениях есть только морда кошки, на некоторых может быть целая тело, некоторые, возможно, вид сбоку и так далее… но наш CNN должен идентифицировать всех как «КОШКИ». Таким образом, объединение помогает идентифицировать функции, даже если они слегка искажены. А с помощью фильтра 2 * 2 мы уменьшаем размер и параметры на 75%. Таким образом, это предотвращает переобучение.

В. Как достигается цель обработки искажений в функциях?
A.
Когда фильтр перемещается с размером 2*2 и шагом 2 . Он сканирует и берет максимальное значение из этой группы 2 * 2, тем самым гарантируя, что будут взяты основные функции из всех групп и, таким образом, обработано пространственное искажение. Просто интуитивный пример: номер 9 показывает нам кошачьи уши, расположенные во 2-м ряду 1-го столбца, теперь, если изображение было искажено, а 9 сдвинулось вверх или вправо, то после объединения мы все равно восстановим эту функцию с помощью Максимальный пулинг. Воспринимайте это не как буквальное объяснение, а как интуитивный пример для понимания концепции объединения.

Для любознательных….
В. Одно интересное сомнение, которое может возникнуть, заключается в том, почему просто следует использовать Max Pooling, а не какой-либо другой тип объединения, например, усреднение пула?
A. Пожалуйста, обратитесь к этой исследовательской статье Доминика Шерера, Андреаса Мюллера и Свена Бенке. Это всего лишь 10-страничный исследовательский документ, в котором подробно объясняется эта тема.
Также зайдите на этот сайт, чтобы ознакомиться с функциональными возможностями CNN.

КОД :

import tflearn
from tflearn.layers.core import input_data, fully_connected, dropout from tflearn.layers.conv import conv_2d,max_pool_2d from tflearn.layers.estimator import regression import numpy as np import matplotlib.pyplot as plt 
import cv2 
import os 
from random import shuffle 
from google_images_download import google_images_download 
from PIL import Image

Здесь:
Ключевые слова: название объектов, изображения которых необходимо загрузить.
Ограничение: количество изображений, которые вы хотите загрузить сразу.
Print_urls: распечатать URL всех загружаемых изображений.

Здесь было сохранено ограничение 100, и мы получили 94 изображения, потому что некоторые изображения будут повреждены. Обратитесь к этой странице для лучшего разъяснения различных параметров и примеров.

# getting random images of Forest Fire and Natural Vegetation in
response  = google_images_download.googleimagesdownload()
arguments = {"keywords":"Forest Fire,Natural Vegetation","limit":100,"print_urls":False}

path = response.download(arguments)
print(path)

# got 94 images of forest_fire and 94 images of natural vegetation

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

# removing corrupted images

FOREST_FIRE_DIR = '/content/downloads/Forest Fire'
NATURAL_VEG_DIR = '/content/downloads/Natural Vegetation'

url_list = [FOREST_FIRE_DIR,NATURAL_VEG_DIR]
for i in url_list :
    
  for image in os.listdir(i):

    try:
      with Image.open(i+"/"+image) as im :
        pass

    except:
      print(i+"/"+image)
      os.remove(i+"/"+image)

Теперь здесь мы переименовываем существующие изображения. Это делается для добавления меток ко второй группе изображений, на которых мы будем выполнять классификацию с использованием CNN. Часть маркировки объясняется позже.

# renaming the files
for i in url_list:
    
  for num , image in enumerate(os.listdir(i)):

    if i == '/content/downloads/Forest Fire':
      os.rename(i+"/"+image,i+"/"+"forest_fire."+str(num)+".jpg")
    else:
      os.rename(i+"/"+image,i+"/"+"natural_veg."+str(num)+".jpg")

Если вы не используете Google Colab, вы можете пропустить эту строку кода.
Google Colab создает контрольные точки, которые часто вызывают проблемы, поэтому с помощью этого кода эта проблема решается.

# removing corrupted images  
FOREST_FIRE_DIR = '/content/downloads/Forest Fire' 
NATURAL_VEG_DIR = '/content/downloads/Natural Vegetation'  
url_list = [FOREST_FIRE_DIR,NATURAL_VEG_DIR]
for i in url_list :
    
  for image in os.listdir(i):

    try:
      with Image.open(i+"/"+image) as im :
        # print(i+"/"+image)
        pass

    except:
      print(i+"/"+image)
      if image == '.ipynb_checkpoints':
        pass
      else:
        os.remove(i+"/"+image)
# getting the count of the no of images available under each category 

print("forest fire image count: "+ str(len([x for x in os.listdir(FOREST_FIRE_DIR)])))

print("natural vegetation image count: "+ str(len([x for x in os.listdir(NATURAL_VEG_DIR)])))

Пометка изображений как [1,0], если их имя начинается с forest_fire, иначе [0,1].
Здесь помогает ранее переименование изображений.

from tqdm import tqdm

def label_img(img):

  word_label = img.split('.')[0]
  if word_label == "forest_fire":
    return [1,0]

  else:
    return [0,1]

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

1. Чтение изображений из файлов:

train_url = [TRAIN_DIR_Fire,TRAIN_DIR_Nature]
для я в train_url:
для изображения в tqdm(os.listdir(i)):
label = label_img(image)
path = os.path.join(i,image)

2. Здесь мы читаем изображение и изменяем его размер до размера изображения, этот размер изображения будет определен позже.
3. Затем и изображение, и метка добавляются в массив numpy один за другим
4. Ваши данные перемешиваются, чтобы изменить порядок изображений

еще:
image = cv2.resize(cv2.imread(path),(IMG_SIZE,IMG_SIZE))
training_data.append([ np.array(image),np. массив(метка)])
перетасовать(обучающие_данные)
np.save('обучающие_данные.npy',обучающие_данные)

'''TRAIN SET '''
def create_train_set(): 
  training_data = []
  TRAIN_DIR_Fire = '/content/downloads/Forest Fire'
  TRAIN_DIR_Nature = '/content/downloads/Natural Vegetation'

  train_url = [TRAIN_DIR_Fire,TRAIN_DIR_Nature]
  for i in train_url:
    for image in tqdm(os.listdir(i)):
      label = label_img(image)
      path  = os.path.join(i,image)
      if path in ["/content/downloads_img/ForestFire/.ipynb_checkpoints"]:      
        pass
      else:
          
        image = cv2.resize(cv2.imread(path),(IMG_SIZE,IMG_SIZE))
        
        training_data.append([ np.array(image),np.array(label)])

  shuffle(training_data)
  np.save('training_data.npy',training_data)
  return training_data
'''TEST SET'''
def create_test_set():
  testing_data = []
  TEST_DIR_Fire = '/content/test/Forest_Fire'
  TEST_DIR_Nature = '/content/test/Natural_Vegetation'
  test_url = [TEST_DIR_Fire,TEST_DIR_Nature]
  for i in test_url:
      
    for image in tqdm(os.listdir(i)):
      label = label_img(image)
      path  = os.path.join(i,image)
      if path in ["/content/downloads_img/Forest Fire/.ipynb_checkpoints"]:
        
        pass
      else:
          
        image = cv2.resize(cv2.imread(path),(IMG_SIZE,IMG_SIZE))
        testing_data.append([ np.array(image),np.array(label)])

  np.save('testing_data.npy',testing_data)
  return testing_data

Здесь мы объявляем размер изображения, скорость обучения и количество эпох, не стесняйтесь экспериментировать с этим. Теперь мы создаем поезд и тестовый набор.

Причина, по которой эта статья посвящена пользовательскому набору данных, заключается в том, что в большинстве примеров CNN выполняется в наборе данных MNIST или Fashion MNIST. Проблема в том, что все вышеперечисленные предварительные обработки, которые мы делали до сих пор, уже сделаны и готовы для нас, и у нас нет никаких знаний, чтобы справиться с реальными проектами. В реальных проектах нам необходимо:
1. Извлекать пользовательские данные
2. Очищать изображения и разделять разные изображения по папкам.
3. Изменять размер и переименовывать, а затем
4. Называть images
5. Преобразуйте изображения в массив Numpy.

Все эти вышеперечисленные шаги выполняются для нас в этих существующих наборах данных.

IMG_SIZE = 50
learning_rate = 1e-3
N_EPOCH = 5

MODEL_NAME = "fireVSnature-{}-{}-{}.model".format(learning_rate,'6-conv-basic',N_EPOCH)
train_data = create_train_set()
test_data = create_test_set()

Мы строим нашу CNN, используя tflearn в этом фрагменте кода. У нас есть 2 слоя Convolutional и MaxPool с 2 полносвязными слоями, используемый оптимизатор — «adam», метрика для классификации — «точность».

convnet = input_data([None,IMG_SIZE,IMG_SIZE,3],name='inputs')

convnet = conv_2d(convnet,64,3,activation='relu')
convent = max_pool_2d(convnet,2)

convnet = conv_2d(convnet,32,3,activation='relu')
convent = max_pool_2d(convnet,2)

convnet = fully_connected(convnet,512,activation='relu')

convnet = fully_connected(convnet,2,activation='sigmoid')
convnet = regression(convnet,optimizer='adam',name='targets',learning_rate=learning_rate,loss='binary_crossentropy',metric = 'accuracy')
model = tflearn.DNN(convnet,tensorboard_dir='log')

Получение изображений и меток из тестовых и обучающих данных.

X = np.array( [ i[0] for i in train_data ])
y = np.array([i[1] for i in train_data])

test_X = np.array( [ i[0] for i in test_data ])
test_y = np.array([i[1] for i in test_data])

Подгонка модели.

model.fit({'inputs':X},{'targets':y},n_epoch=3,validation_set=({'inputs':test_X},'targets':test_y}),show_metric=True,snapshot_step=10,run_id=MODEL_NAME,batch_size=10)
model.save(MODEL_NAME)

Прогнозирование классификации и визуализация результатов. Если у вас меньше изображений, чем у меня (менее 100 изображений), то ваша точность будет невелика.

%matplotlib inline
fig = plt.figure(figsize=(10,6))
import matplotlib.image as mpimg
for num, image in enumerate(test_data):
  # image = mpimg.imread(image)
  y_plot = fig.add_subplot(3,6,num+1)
  model_out = model.predict([image[0]])[0][0]
  # print(model_out)
  if  model_out == 1:
    label = "FOREST_FIRE"
  else:
    label="NATURAL_VEG"
  y_plot.imshow(image[0])
  plt.title(label)
  y_plot.axis('off')
plt.show()

Для проверки полного кода. Обратитесь к этой странице.

Если у вас есть какие-либо вопросы относительно этой статьи, пожалуйста, добавьте их в раздел комментариев. Я хотел бы ответить на них как можно скорее. Я бы также внес соответствующие изменения в статью.