Share This
Связаться со мной
Крути в низ
Categories
//Реализация сверточной нейронной сети при помощи Keras

Реализация сверточной нейронной сети при помощи Keras

20.09.2023Category : Python

Keras — это простая в использовании, но мощная библиотека глубокого обучения для Python. В этом посте мы построим простую сверточную нейронную сеть (CNN) и обучим ее решению реальной задачи с помощью Keras.

Этот пост предназначен для начинающих пользователей Keras, но предполагает наличие базовых знаний о CNN.

Нужен только код? Полный исходный код находится в конце.

Проблема: классификация цифр в MNIST

Мы будем решать классическую вводную задачу компьютерного зрения: классификация рукописных цифр по MNIST. Все просто: необходимо классифицировать изображение как цифру.

realizacija svertochnoj nejronnoj seti pri pomoshhi keras 4418f3d - Реализация сверточной нейронной сети при помощи Keras

Примеры изображений из набора данных MNIST

Каждое изображение в наборе данных MNIST имеет размер 28×28 и содержит центрированную полутоновую цифру. Наша CNN принимает изображение и выдает один из 10 возможных классов (по одному на каждую цифру).

1. Настройка

Я предполагаю, что у вас уже есть базовая установка Python (скорее всего, так и есть). Давайте сначала загрузим некоторые пакеты, которые нам понадобятся:

$ pip install tensorflow numpy mnist

Примечание. Нам не нужно устанавливать пакет keras, поскольку теперь он поставляется вместе с TensorFlow в качестве официального API высокого уровня! Теперь рекомендуется использовать Keras из TensorFlow, а не отдельный пакет keras.

Теперь вы можете импортировать эти пакеты и работать с набором данных MNIST:

import numpy as np import mnist from tensorflow import keras  # The first time you run this might be a bit slow, since the # mnist package has to download and cache the data. train_images = mnist.train_images() train_labels = mnist.train_labels()  print(train_images.shape) # (60000, 28, 28) print(train_labels.shape) # (60000,)

2. Подготовка данных

Перед началом работы мы нормализуем значения пикселей изображения с [0, 255] до [-0,5, 0,5], чтобы облегчить обучение нашей сети (использование меньших, центрированных значений обычно приводит к лучшим результатам). Мы также изменим форму каждого изображения с (28, 28) на (28, 28, 1), поскольку Keras требует третьего измерения.

import numpy as np import mnist  train_images = mnist.train_images() train_labels = mnist.train_labels() test_images = mnist.test_images() test_labels = mnist.test_labels()  # Normalize the images. train_images = (train_images / 255) - 0.5 test_images = (test_images / 255) - 0.5  # Reshape the images. train_images = np.expand_dims(train_images, axis=3) test_images = np.expand_dims(test_images, axis=3)  print(train_images.shape) # (60000, 28, 28, 1) print(test_images.shape)  # (10000, 28, 28, 1)

Мы готовы приступить к созданию нашей CNN!

3. Построение модели

Любая модель Keras строится либо с помощью класса Sequential, который представляет собой линейный стек слоев, либо с помощью функционального класса Model, который является более настраиваемым. Мы будем использовать более простую модель Sequential, поскольку наша CNN будет представлять собой линейный стек слоев.

Начнем с инициализации модели Sequential:

from tensorflow.keras.models import Sequential  # WIP model = Sequential([   # layers... ])

Конструктор Sequential принимает массив Layers Keras. Для нашей CNN мы будем использовать 3 типа слоев: Convolutional, Max Pooling и Softmax.

realizacija svertochnoj nejronnoj seti pri pomoshhi keras bf0c772 - Реализация сверточной нейронной сети при помощи Keras

from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten  num_filters = 8 filter_size = 3 pool_size = 2  model = Sequential([   Conv2D(num_filters, filter_size, input_shape=(28, 28, 1)),   MaxPooling2D(pool_size=pool_size),   Flatten(),   Dense(10, activation='softmax'), ])
  • num_filters, filter_size и pool_size — это необъяснимые переменные, задающие гиперпараметры для нашей CNN.
  • Первый слой в любой Sequential модели должен задавать форму входа input_shape, поэтому мы делаем это на Conv2D. После задания формы входа Keras автоматически определяет формы входов для последующих слоев.
  • Выходной слой Softmax имеет 10 узлов, по одному на каждый класс.

4. Компиляция модели

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

  • Оптимизатор. Мы остановимся на довольно хорошем оптимизаторе по умолчанию: градиентном оптимизаторе Adam. В Keras есть множество других оптимизаторов, которые также можно рассмотреть.
  • Функция потерь. Поскольку мы используем выходной слой Softmax, мы будем использовать потери от перекрестной энтропии. Keras различает binary_crossentropy (2 класса) и categorical_crossentropy (>2 классов), поэтому мы будем использовать последнюю. См. все потери Keras.
  • Список метрик. Поскольку это задача классификации, мы просто попросим Keras вывести метрику точности.

Вот как выглядит эта компиляция:

model.compile(   'adam',   loss='categorical_crossentropy',   metrics=['accuracy'], )

Вперед!

5. Обучение модели

Обучение модели в Keras буквально сводится к вызову функции fit() и указанию некоторых параметров. Возможных параметров очень много, но мы ограничимся только этими:

  • Данные для обучения (изображения и метки), известные как X и Y соответственно.
  • Количество эпох (итераций по всему набору данных) для обучения.
  • Данные проверки (или тестовые данные), которые используются в процессе обучения для периодического измерения производительности сети на данных, с которыми она ранее не сталкивалась.

Есть один нюанс: Keras ожидает, что обучающие цели будут 10-мерными векторами, поскольку в нашем выходном слое Softmax 10 узлов. Сейчас наши массивы train_labels и test_labels содержат одиночные целые числа, представляющие класс для каждого изображения:

import mnist  train_labels = mnist.train_labels() print(train_labels[0]) # 5

Удобно, что в Keras есть метод-утилита, который решает именно эту проблему: to_categorical. Он превращает наш массив целых чисел класса в массив однокатегорийных векторов. Например, 2 превратится в [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] (он индексирован нулями).

Вот как это выглядит:

from tensorflow.keras.utils import to_categorical  model.fit(   train_images,   to_categorical(train_labels),   epochs=3,   validation_data=(test_images, to_categorical(test_labels)), ) 

Теперь мы можем собрать все вместе, чтобы обучить нашу сеть:

import numpy as np import mnist from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten from tensorflow.keras.utils import to_categorical  train_images = mnist.train_images() train_labels = mnist.train_labels() test_images = mnist.test_images() test_labels = mnist.test_labels()  # Normalize the images. train_images = (train_images / 255) - 0.5 test_images = (test_images / 255) - 0.5  # Reshape the images. train_images = np.expand_dims(train_images, axis=3) test_images = np.expand_dims(test_images, axis=3)  num_filters = 8 filter_size = 3 pool_size = 2  # Build the model. model = Sequential([   Conv2D(num_filters, filter_size, input_shape=(28, 28, 1)),   MaxPooling2D(pool_size=pool_size),   Flatten(),   Dense(10, activation='softmax'), ])  # Compile the model. model.compile(   'adam',   loss='categorical_crossentropy',   metrics=['accuracy'], )  # Train the model. model.fit(   train_images,   to_categorical(train_labels),   epochs=3,   validation_data=(test_images, to_categorical(test_labels)), )

Выполнение этого кода на полном наборе данных MNIST дает следующие результаты:

Epoch 1 loss: 0.2433 - acc: 0.9276 - val_loss: 0.1176 - val_acc: 0.9634 Epoch 2 loss: 0.1184 - acc: 0.9648 - val_loss: 0.0936 - val_acc: 0.9721 Epoch 3 loss: 0.0930 - acc: 0.9721 - val_loss: 0.0778 - val_acc: 0.9744

С помощью этой простой CNN мы достигаем 97,4% точности тестирования!

6. Использование модели

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

model.save_weights('cnn.h5')

Теперь мы можем в любой момент перезагрузить обученную модель, перестроив ее и загрузив сохраненные веса:

from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten  num_filters = 8 filter_size = 3 pool_size = 2  # Build the model. model = Sequential([   Conv2D(num_filters, filter_size, input_shape=(28, 28, 1)),   MaxPooling2D(pool_size=pool_size),   Flatten(),   Dense(10, activation='softmax'), ])  # Load the model's saved weights. model.load_weights('cnn.h5')

Использовать обученную модель для прогнозирования очень просто: мы передаем массив входных данных в функцию predict(), а она возвращает массив выходных данных. Следует помнить, что на выходе нашей сети 10 вероятностей (из-за softmax), поэтому мы будем использовать np.argmax(), чтобы превратить их в реальные цифры.

# Predict on the first 5 test images. predictions = model.predict(test_images[:5])  # Print our model's predictions. print(np.argmax(predictions, axis=1)) # [7, 2, 1, 0, 4]  # Check our predictions against the ground truths. print(test_labels[:5]) # [7, 2, 1, 0, 4]

7. Расширения

Мы можем еще много чего сделать для экспериментов и улучшения нашей сети — в этом официальном примере Keras MNIST CNN достигла точности 99 тестов после 15 эпох. Давайте рассмотрим, какие модификации можно внести в нашу CNN.

Глубина сети

Что произойдет, если мы добавим или удалим конволюционные слои? Как это повлияет на обучение и/или конечную производительность модели?

model = Sequential([   Conv2D(num_filters, filter_size, input_shape=(28, 28, 1)),   Conv2D(num_filters, filter_size),   MaxPooling2D(pool_size=pool_size),   Flatten(),   Dense(10, activation='softmax'), ])

Dropout

А что если попробовать добавить слои Dropout, которые обычно используются для предотвращения перебора?

from tensorflow.keras.layers import Dropout  model = Sequential([   Conv2D(num_filters, filter_size, input_shape=(28, 28, 1)),   MaxPooling2D(pool_size=pool_size),   Dropout(0.5),   Flatten(),   Dense(10, activation='softmax'), ])

Полносвязные слои

Что если добавить полностью связанные слои между конволюционными выходами и конечным слоем Softmax? Это обычно делается в CNN, используемых для компьютерного зрения.

from tensorflow.keras.layers import Dense  model = Sequential([   Conv2D(num_filters, filter_size, input_shape=(28, 28, 1)),   MaxPooling2D(pool_size=pool_size),   Flatten(),   Dense(64, activation='relu'),   Dense(10, activation='softmax'), ])

Параметры конволюции

А что если поиграть с параметрами Conv2D? Например:

# These can be changed, too! num_filters = 8 filter_size = 3  model = Sequential([   # See https://keras.io/layers/convolutional/#conv2d for more info.   Conv2D(     num_filters,     filter_size,     input_shape=(28, 28, 1),     strides=2,     padding='same',     activation='relu',   ),   MaxPooling2D(pool_size=pool_size),   Flatten(),   Dense(10, activation='softmax'), ])

Заключение

Вы реализовали свою первую CNN с помощью Keras! Мы достигли точности тестирования 97,4% с нашей простой начальной сетью. Ниже я снова приведу полный исходный код для ознакомления.

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

Спасибо за чтение! Полный исходный код приведен ниже.

Полный код

# The full CNN code! #################### import numpy as np import mnist from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten from tensorflow.keras.utils import to_categorical  train_images = mnist.train_images() train_labels = mnist.train_labels() test_images = mnist.test_images() test_labels = mnist.test_labels()  # Normalize the images. train_images = (train_images / 255) - 0.5 test_images = (test_images / 255) - 0.5  # Reshape the images. train_images = np.expand_dims(train_images, axis=3) test_images = np.expand_dims(test_images, axis=3)  num_filters = 8 filter_size = 3 pool_size = 2  # Build the model. model = Sequential([   Conv2D(num_filters, filter_size, input_shape=(28, 28, 1)),   MaxPooling2D(pool_size=pool_size),   Flatten(),   Dense(10, activation='softmax'), ])  # Compile the model. model.compile(   'adam',   loss='categorical_crossentropy',   metrics=['accuracy'], )  # Train the model. model.fit(   train_images,   to_categorical(train_labels),   epochs=3,   validation_data=(test_images, to_categorical(test_labels)), )  # Save the model to disk. model.save_weights('cnn.h5')  # Load the model from disk later using: # model.load_weights('cnn.h5')  # Predict on the first 5 test images. predictions = model.predict(test_images[:5])  # Print our model's predictions. print(np.argmax(predictions, axis=1)) # [7, 2, 1, 0, 4]  # Check our predictions against the ground truths. print(test_labels[:5]) # [7, 2, 1, 0, 4]

Перевод статьи «Keras for Beginners: Implementing a Convolutional Neural Network».

  • 0 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Связаться со мной
Close