В современном мире искусственный интеллект и машинное обучение стремительно развиваются, меняя нашу повседневную жизнь и открывая новые горизонты в различных областях. Одной из ключевых технологий, лежащих в основе этих достижений, являются сверточные нейронные сети (Convolutional Neural Networks, CNN). Эти мощные алгоритмы позволяют эффективно обрабатывать и анализировать изображения, что находит применение в самых разных сферах: от медицинской диагностики до систем безопасности.

CNN подходит для классификации изображений, что делает её отличным выбором для задачи распознавания рукописных цифр.

CNN состоит из:

  1. Сверточные слои (Conv2D): Эти слои выполняют операции свертки, которые помогают модели извлекать ключевые признаки из изображений, такие как края, текстуры и формы.

  2. Слои подвыборки (MaxPooling2D): Эти слои уменьшают размерность данных, сохраняя при этом важные признаки, что помогает ускорить обучение и снизить риск переобучения.

  3. Полносвязные слои (Dense): Эти слои отвечают за классификацию, принимая вектор признаков от предыдущих слоев и принимая решение о классе (цифре) изображения.

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

Содержание:

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

  • Создание проекта.

  • Импорт библиотек.

  • Задание параметров.

  • Функция для загрузки и предобработки изображений.

  • Загрузка и предобработка данных.

  • Создание модели нейросети.

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

  • Оценка модели.

  • Сохранение модели в формате Keras.

  • Функции для загрузки и предсказания изображения.

  • Пример использования.

  • Полный код нейросети.

  • Заключение.


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

Архитектура дата-сета:

data/

└── train/

    ├── 0/

    │   ├── 0_1.png

    │   ├── 0_2.png

    │   └── 0_3.png

    ├── 1/

    ├── ...

    └── 9/

└── test/

    ├── 0/

    ├── ...

    └── 9/

train/ cодержит данные, используемые для обучения модели нейросети. Именно эти данные модель будет анализировать и использовать для того, чтобы "научиться" распознавать цифры. Каждая поддиректория (0, 1, 2, ..., 9) представляет собой класс цифры и содержит изображения, на которых изображена соответствующая цифра. Эти данные подаются на вход модели во время фазы обучения (model.fit), и модель настраивает свои параметры на основе этих данных.


test/ cодержит данные, используемые для тестирования производительности обученной модели. Эти данные модель не видит во время обучения и используется для оценки её способности обобщать на новые данные. Аналогично папке train, каждая поддиректория (0, 1, 2, ..., 9) представляет собой класс цифры и содержит изображения с соответствующей цифрой. Эти данные подаются на вход модели во время фазы оценки (model.evaluate), чтобы определить точность модели на новых, невидимых ранее данных. Разделение данных на train и test помогает избежать переобучения модели и позволяет честно оценить её производительность на новых данных, что является важным этапом в процессе машинного обучения. Это делает модель более надежной и способной обобщать, а не просто "запоминать" тренировочные данные.

Каждый файл должен содержать изображение одной цифры (0-9).
data/train/0/: фотографии рукописных нулей.
data/train/1/: фотографии рукописных единиц.
...
data/test/0/: фотографии рукописных нулей для тестирования.
data/test/1/: фотографии рукописных единиц для тестирования.
...

Минимальное количество:

Для каждого класса (0-9): рекомендуется иметь не менее 100 изображений. В идеале, чем больше, тем лучше. Например, 500-1000 изображений на класс даст более стабильные результаты.

Общий ориентир:

  • Тренировочный набор (train): 1000-5000 изображений для каждого класса.

  • Тестовый набор (test): 200-500 изображений для каждого класса.

Для обучения и тестирования моделей машинного обучения, включая нейросети, обычно используется стандартное соотношение данных. Наиболее распространённое соотношение - это 80/20 или 70/30. Это означает, что 80% (или 70%) данных используется для обучения модели (train), а оставшиеся 20% (или 30%) - для тестирования (test).


Создание проекта

Создаем новый проект и два .py файла: create_model.py и test_model.py

Скрипт create_model.py предназначен для создания и обучения модели сверточной нейронной сети (CNN), которая сможет распознавать цифры на изображениях, как рукописные, так и машинописные.

Основные функции и шаги в скрипте:

  • Импорт необходимых библиотек и модулей (TensorFlow, NumPy, PIL).

  • Определение параметров изображения (например, высота и ширина).

  • Функция для загрузки и предобработки изображений из папок train и test.

  • Загрузка и предобработка данных.

  • Создание архитектуры модели CNN с использованием слоев Conv2D, MaxPooling2D, Flatten и Dense.

  • Компиляция модели с указанием оптимизатора, функции потерь и метрик.

  • Обучение модели на тренировочных данных.

  • Оценка модели на тестовых данных.

  • Сохранение обученной модели в формате Keras.

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

Основные функции и шаги в скрипте:

  • Импорт необходимых библиотек и модулей (TensorFlow, NumPy, PIL).

  • Загрузка обученной модели из файла, сохраненного в create_model.py.

  • Функция для загрузки и предобработки нового изображения для предсказания.

  • Функция для выполнения предсказания на загруженном изображении с использованием модели.

  • Пример использования функции предсказания для нового изображения.

  • Вывод предсказанной цифры и сравнение с ожидаемой цифрой.


Импорт библиотек (create_model.py).

# Импорт модулей
import tensorflow as tf  # pip install tensorflow
import numpy as np  # pip install numpy
from PIL import Image  # pip install pillow
import os

TensorFlow. Мощная библиотека для машинного обучения и глубокого обучения, созданная Google. В этом проекте она используется для создания и тренировки нейронной сети. Мы используем TensorFlow для создания модели нейронной сети, определения слоев модели, компиляции и тренировки модели. TensorFlow предоставляет гибкость, масштабируемость и множество инструментов для построения и тренировки нейронных сетей. Он также поддерживает высокоуровневый API Keras, который упрощает процесс разработки.

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

Pillow (Python Imaging Library, PIL). Библиотека для работы с изображениями. Она предоставляет инструменты для открытия, манипулирования и сохранения различных форматов изображений. В этом проекте Pillow используется для загрузки изображений, преобразования их в градации серого и изменения их размера до нужных параметров. Pillow является стандартной библиотекой для работы с изображениями в Python, предоставляя широкий набор инструментов и поддержку множества форматов изображений.

os. Встроенная библиотека Python, которая предоставляет функции для взаимодействия с операционной системой. В этом проекте os используется для навигации по файловой системе, получения списка файлов в директории и создания путей к файлам. os предоставляет все необходимые функции для работы с файлами и директориями, делая код платформенно-независимым.

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


Задание параметров (create_model.py).

# Параметры
img_height = 28  # Высота изображений в пикселях
img_width = 28  # Ширина изображений в пикселях

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

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

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


Функция для загрузки и предобработки изображений (create_model.py).

# Функция для загрузки и предобработки изображений
def load_images_from_folder(folder):
    images = []
    labels = []
    for label in range(10):
        path = os.path.join(folder, str(label))
        for filename in os.listdir(path):
            img_path = os.path.join(path, filename)
            img = Image.open(img_path).convert('L')
            img = img.resize((img_width, img_height))
            img = np.asarray(img)
            img = img / 255.0
            images.append(img)
            labels.append(label)
    return np.array(images), np.array(labels)

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

images = []
labels = []

images: список для хранения предобработанных изображений.
labels: список для хранения меток (классов) изображений.

for label in range(10):
path = os.path.join(folder, str(label))

Итерируемся по числам от 0 до 9, что соответствует 10 классам изображений. Генерируем путь к папке с изображениями каждого класса.

for filename in os.listdir(path):
img_path = os.path.join(path, filename)

Проходим по каждому файлу в папке.
Генерируем полный путь к каждому изображению.

img = Image.open(img_path).convert('L')
img = img.resize((img_width, img_height))
img = np.asarray(img)
img = img / 255.0

Открываем изображение и преобразуем его в градации серого с помощью convert('L').
Изменяем размер изображения до заданных параметров (28x28 пикселей).
Преобразуем изображение в массив NumPy для дальнейшей обработки.
Нормализуем значения пикселей в диапазоне от 0 до 1, разделяя их на 255.

images.append(img)
labels.append(label)

Добавляем предобработанное изображение в список images.
Добавляем соответствующую метку (номер класса) в список labels.

return np.array(images), np.array(labels)

Преобразуем списки images и labels в массивы NumPy и возвращаем их.


Загрузка и предобработка данных (create_model.py).

# Загрузка и предобработка данных
x_train, y_train = load_images_from_folder('data/train')
x_test, y_test = load_images_from_folder('data/test')

Этот блок кода выполняет загрузку и предобработку данных для обучения и тестирования модели нейронной сети.

Вызов функции load_images_from_folder для загрузки обучающих данных:

  • x_train: Массив изображений, используемых для обучения модели.

  • y_train: Массив меток (классов), соответствующих обучающим изображениям.

  • 'data/train': Путь к директории, содержащей обучающие изображения, разделенные по папкам для каждого класса (0-9).

Вызов функции load_images_from_folder для загрузки тестовых данных:

  • x_test: Массив изображений, используемых для тестирования модели.

  • y_test: Массив меток (классов), соответствующих тестовым изображениям.

  • 'data/test': Путь к директории, содержащей тестовые изображения, разделенные по папкам для каждого класса (0-9).

Функция load_images_from_folder загружает и предобрабатывает изображения, выполняя такие действия, как изменение размера, преобразование в градации серого и нормализация. Полученные массивы данных (x_train, y_train, x_test, y_test) затем используются для обучения и тестирования модели.

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

# Убедимся, что данные имеют правильные формы перед reshape
print(f'Количество train-изобр.: {x_train.shape[0]}, высота/ширина: {x_train.shape[1]}x{x_train.shape[2]}px')
print(f'Количество test-изобр.: {x_test.shape[0]}, высота/ширина: {x_test.shape[1]}x{x_test.shape[2]}px')

x_train = x_train.reshape(-1, img_height, img_width, 1)
x_test = x_test.reshape(-1, img_height, img_width, 1)

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

Проверка формы данных:
print(f'Количество train-изобр.: {x_train.shape[0]}, высота/ширина: {x_train.shape[1]}x{x_train.shape[2]}px')
print(f'Количество test-изобр.: {x_test.shape[0]}, высота/ширина: {x_test.shape[1]}x{x_test.shape[2]}px')

Эти строки выводят информацию о количестве изображений и их размерах (высота и ширина) в тренировочном (x_train) и тестовом (x_test) наборах данных. Это полезно для проверки, что данные загружены корректно и имеют ожидаемые размеры (28x28 пикселей).

Изменение формы данных:
x_train = x_train.reshape(-1, img_height, img_width, 1)
x_test = x_test.reshape(-1, img_height, img_width, 1)

reshape изменяет форму массивов данных, добавляя четвертое измерение, которое представляет канал (в данном случае, один канал для градаций серого).
-1 указывает, что размер первого измерения (количество изображений) вычисляется автоматически, исходя из общего количества элементов и указанных размеров (высота, ширина, каналы).
Теперь данные имеют форму (количество изображений, 28, 28, 1), что соответствует требуемому формату входных данных для сверточных нейронных сетей в TensorFlow/Keras.
Пример для тренировочного набора данных (x_train):
Перед reshape: (количество изображений, 28, 28)
После reshape: (количество изображений, 28, 28, 1)
Эти изменения важны для корректной обработки данных нейронной сетью, так как сверточные слои ожидают данные в формате (batch_size, height, width, channels).


Создание модели нейросети (create_model.py).

# Создание модели нейросети с использованием Input
model = tf.keras.models.Sequential([
    tf.keras.layers.Input(shape=(img_height, img_width, 1)),
    tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

Этот блок кода создает архитектуру модели нейронной сети для распознавания рукописных цифр с использованием библиотеки TensorFlow/Keras.

Создание модели с использованием Sequential:

model = tf.keras.models.Sequential()

Цель: Sequential — это простой способ создать модель нейронной сети в Keras. Слои добавляются последовательно, один за другим.
Почему именно Sequential: Удобен для создания линейных моделей, где каждый слой имеет ровно один вход и один выход.

Слой Input:

tf.keras.layers.Input(shape=(img_height, img_width, 1))

Цель: Задает форму входных данных, ожидаемых моделью. В данном случае, входные данные — это изображения размером 28x28 пикселей с одним каналом (градации серого).
Почему именно Input: Использование Input слоя упрощает создание моделей и делает их более читаемыми.

Первый слой свертки (Conv2D):

tf.keras.layers.Conv2D(32, (3, 3), activation='relu')

Цель: Этот слой применяет 32 фильтра размером 3x3 к входным данным, извлекая важные признаки, такие как края и текстуры.
Активация relu: Применяется функция активации relu (Rectified Linear Unit), которая делает выход неотрицательным и добавляет нелинейность модели.

Первый слой подвыборки (MaxPooling2D):

tf.keras.layers.MaxPooling2D((2, 2))

Цель: Уменьшает размерность данных, агрегируя значения в области 2x2 пикселя и выбирая максимальное значение в каждой области.
Почему MaxPooling2D: Помогает уменьшить количество параметров и вычислительные затраты, сохраняя важные признаки.

Второй слой свертки (Conv2D):

tf.keras.layers.Conv2D(64, (3, 3), activation='relu')

Цель: Применяет 64 фильтра размером 3x3 к данным, извлекая более сложные признаки.
Активация relu: Применяется функция активации relu для сохранения положительных значений и добавления нелинейности.

Второй слой подвыборки (MaxPooling2D):

tf.keras.layers.MaxPooling2D((2, 2))

Цель: Опять уменьшает размер данных, агрегируя значения в области 2x2 пикселя, выбирая максимальное значение в каждой области.
Почему MaxPooling2D: Продолжает уменьшать размер данных, сохраняя важные признаки, и помогает снизить вычислительные затраты.

Слой выравнивания (Flatten):

tf.keras.layers.Flatten()

Цель: Преобразует многомерный массив данных в одномерный вектор. Это необходимо для подключения к полносвязным (Dense) слоям.
Почему Flatten: Готовит данные для подачи в полносвязные слои, объединяя все признаки в одномерный вектор.

Полносвязный слой (Dense):

tf.keras.layers.Dense(64, activation='relu')

Цель: Обрабатывает данные, используя 64 нейрона. В каждом нейроне происходит линейная комбинация входных данных и применение функции активации relu.
Почему Dense с relu: Dense слои позволяют нейронной сети обучаться сложным паттернам. relu добавляет нелинейность, что помогает модели лучше обучаться на сложных данных.

Выходной полносвязный слой (Dense):

tf.keras.layers.Dense(10, activation='softmax')

Цель: Обрабатывает выходные данные и использует 10 нейронов, соответствующих 10 классам (цифры 0-9). Применяет функцию активации softmax для получения вероятностей классов.
Почему Dense с softmax: softmax функция нормализует выходные значения, преобразуя их в вероятности классов, которые суммируются до 1. Это позволяет модели предсказывать наиболее вероятный класс для входного изображения.

  • Sequential: Линейная модель, добавляем слои последовательно.

  • Input: Задает форму входных данных.

  • Conv2D (32 фильтра): Извлекает основные признаки.

  • MaxPooling2D (2x2): Уменьшает размер данных.

  • Conv2D (64 фильтра): Извлекает более сложные признаки.

  • MaxPooling2D (2x2): Снова уменьшает размер данных, сохраняя важные признаки.

  • Flatten: Преобразует данные в одномерный вектор для полносвязных слоев.

  • Dense (64 нейрона): Обрабатывает данные и обучается сложным паттернам с функцией активации relu.

  • Dense (10 нейронов, softmax): Выходной слой, предсказывающий вероятности для 10 классов (цифры 0-9).


Обучение модели (create_model.py).

# Компиляция и обучение модели
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)

Этот блок кода отвечает за компиляцию модели нейронной сети, установку параметров обучения и выполнение самого процесса обучения.

model.compile(optimizer='adam', - Adam (Adaptive Moment Estimation) — это оптимизатор, который комбинирует преимущества методов AdaGrad и RMSProp. Он адаптируется к обучению моделей, изменяя скорость обучения на основе момента первого и второго порядка. Он обладает хорошей производительностью на большом количестве задач и является стандартным выбором для многих моделей глубокого обучения.

loss='sparse_categorical_crossentropy', - Функция потерь sparse_categorical_crossentropy используется для задач многоклассовой классификации, где метки представлены в виде целых чисел. Она измеряет разницу между предсказанными вероятностями и истинными метками. sparse_categorical_crossentropy подходит для наших данных, где метки являются целыми числами (0-9), что упрощает вычисления и улучшает производительность.

metrics=['accuracy']) - Метрика, по которой будет оцениваться производительность модели. В данном случае мы используем точность (accuracy), которая показывает, какой процент предсказаний модели правильный. Эта метрика проста для понимания и широко используется для задач классификации.

model.fit(x_train, y_train, epochs=5) - Обучение модели. x_train, y_train - обучающие данные (изображения и метки), которые будут использоваться для обучения модели. epochs=5 - количество эпох обучения. Одна эпоха представляет собой один полный проход по всему обучающему набору данных. Почему именно 5 эпох? Это начальное значение, которое можно увеличить для более длительного и тщательного обучения модели. Большее количество эпох может улучшить точность, но также может привести к переобучению.

Процесс обучения:

  • Компиляция: Устанавливает параметры обучения и подготавливает модель к тренировке.

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

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


Оценка модели (create_model.py).

# Оценка модели
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'Точность на тестовом наборе данных: {test_acc}')

if test_acc < 0.6:
  print("Низкая точность. Рекомендуется улучшить модель и данные.")
elif 0.6 <= test_acc < 0.8:
  print("Средняя точность. Неплохо, но есть куда стремиться.")
elif 0.8 <= test_acc < 0.9:
  print("Хорошая точность. Модель работает хорошо.")
else:
  print("Отличная точность. Модель отлично справляется с задачей.")

Этот блок кода оценивает производительность обученной модели на тестовом наборе данных и выводит точность предсказаний.

Функция model.evaluat() - оценивает модель на основе тестовых данных. Функция принимает тестовые данные (x_test) и метки (y_test) и возвращает значение функции потерь (test_loss) и метрику точности (test_acc). Оценка на тестовом наборе данных позволяет понять, насколько хорошо модель обобщается на новых, ранее невидимых данных, что является важным показателем её качества.
print(f'Точность на тестовом наборе данных: {test_acc}') - выводит точность модели на тестовом наборе данных в читаемом формате. Это позволяет быстро и наглядно оценить производительность модели, понять её текущий уровень и определить направления для дальнейших улучшений.

Для оценки производительности модели сверточной нейронной сети (CNN) в задаче распознавания цифр можно использовать следующие диапазоны точности:

  • Низкая точность (менее 60%)

  • Средняя точность (60-80%)

  • Хорошая точность (80-90%)

  • Отличная точность (более 90%)


Сохранение модели в формате Keras (create_model.py).

# Сохранение модели в новом формате Keras
model.save('my_model.keras')
print(f'Модель создана!')

Этот блок кода отвечает за сохранение обученной модели нейронной сети в формате Keras и вывод сообщения о завершении процесса сохранения.

Функция model.save() сохраняет текущую версию обученной модели на диск с указанным именем и в указанном формате. Файл сохраняется в формате Keras (.keras), который включает в себя архитектуру модели, её веса, конфигурацию тренировки (если применимо), и оптимизатор. Использование model.save позволяет легко загружать и использовать модель в будущем без необходимости повторного обучения.

print(f'Модель создана!') выводит сообщение в консоль, подтверждающее, что модель успешно сохранена. Подтверждение успешного сохранения модели помогает понять, что процесс завершен корректно и модель готова к использованию или дальнейшим операциям.


Функции для загрузки и предсказания изображения (test_model.py).

import tensorflow as tf
import numpy as np
from PIL import Image

# Параметры
img_height = 28
img_width = 28

# Загрузка модели
model = tf.keras.models.load_model('my_model.keras')

# Функции для загрузки и предсказания изображения
def load_image(filepath):
    img = Image.open(filepath).convert('L')
    img = img.resize((img_height, img_width))
    img = np.array(img)
    img = img / 255.0
    img = img.reshape(-1, img_height, img_width, 1)
    return img

def predict_digit(test_img):
    img = load_image(test_img)
    prediction = model.predict(img)
    return np.argmax(prediction)

model = tf.keras.models.load_model('my_model.keras') - Этот код загружает ранее обученную и сохраненную модель нейронной сети из файла my_model.keras. Это позволяет использовать модель для выполнения предсказаний на новых данных без необходимости повторного обучения.

def load_image(filepath): - функция загружает изображение из указанного файла, преобразует его в формат, подходящий для модели нейронной сети, и возвращает предобработанное изображение.

  • img = Image.open(filepath).convert('L') - открыть изображение и преобразовать его в градации серого (оттенки серого). Модель была обучена на черно-белых изображениях, поэтому важно привести новые данные к такому же формату.

  • img = img.resize((img_height, img_width)) - изменить размер изображения до 28x28 пикселей. Модель была обучена на изображениях размером 28x28 пикселей, поэтому входные данные должны иметь такой же размер.

  • img = np.array(img) - Преобразовать изображение в массив для дальнейшей обработки. Модель принимает на вход данные в формате массива.

  • img = img / 255.0 - Нормализовать значения пикселей в диапазоне от 0 до 1. Нормализация улучшает производительность модели, так как она была обучена на нормализованных данных.

  • img = img.reshape(-1, img_height, img_width, 1) - Изменить форму массива, добавив дополнительное измерение для канала (один канал для черно-белого изображения). Модель ожидает данные в формате (batch_size, height, width, channels).

def predict_digit(test_img): - функция выполняет предсказание на основе загруженной модели и возвращает предсказанную цифру.

  • img = load_image(test_img) - Загрузить и предобработать изображение для модели. Предобработка данных необходима для корректного выполнения предсказаний.

  • prediction = model.predict(img) - Получить предсказание модели для данного изображения. Модель возвращает вероятности для каждого класса (цифры от 0 до 9).

  • return np.argmax(prediction) - Определить класс (цифру) с наибольшей вероятностью. Вернуть наиболее вероятную цифру, предсказанную моделью.


Пример использования (test_model.py).

# Пример использования
test_image = 'data\sample_a.png'
predicted_digit = predict_digit(test_image)

print(f'Цифра на изображении: {predicted_digit}')

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

test_image = 'data/sample_a.png' - Задает путь к изображению, на котором необходимо выполнить предсказание. В данном случае это изображение sample_a.png, расположенное в папке data.

predicted_digit = predict_digit(test_image) - Функция принимает путь к изображению, загружает и предобрабатывает изображение, выполняет предсказание с использованием модели и возвращает предсказанную цифру.

print(f'Цифра на изображении: {predicted_digit}') - Выводит предсказанную моделью цифру для указанного изображения в читаемом формате.


Файл create_model.py:

# Импорт модулей
import tensorflow as tf  # pip install tensorflow
import numpy as np  # pip install numpy
from PIL import Image  # pip install pillow
import os

# Параметры
img_height = 28
img_width = 28

# Функция для загрузки и предобработки изображений
def load_images_from_folder(folder):
    images = []
    labels = []
    for label in range(10):
        path = os.path.join(folder, str(label))
        for filename in os.listdir(path):
            img_path = os.path.join(path, filename)
            img = Image.open(img_path).convert('L')
            img = img.resize((img_width, img_height))
            img = np.asarray(img)
            img = img / 255.0
            images.append(img)
            labels.append(label)
    return np.array(images), np.array(labels)

# Загрузка и предобработка данных
x_train, y_train = load_images_from_folder('data/train')
x_test, y_test = load_images_from_folder('data/test')

# Убедимся, что данные имеют правильные формы перед reshape
print(f'Количество train-изобр.: {x_train.shape[0]}, высота/ширина: {x_train.shape[1]}x{x_train.shape[2]}px')
print(f'Количество test-изобр.: {x_test.shape[0]}, высота/ширина: {x_test.shape[1]}x{x_test.shape[2]}px')

x_train = x_train.reshape(-1, img_height, img_width, 1)
x_test = x_test.reshape(-1, img_height, img_width, 1)

# Создание модели нейросети с использованием Input
model = tf.keras.models.Sequential([
    tf.keras.layers.Input(shape=(img_height, img_width, 1)),
    tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

# Компиляция и обучение модели
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)

# Оценка модели
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'Точность на тестовом наборе данных: {test_acc}')

# Сохранение модели в новом формате Keras
model.save('my_model.keras')
print(f'Модель создана!')

Файл test_model.py:

import tensorflow as tf
import numpy as np
from PIL import Image

# Параметры
img_height = 28
img_width = 28

# Загрузка модели
model = tf.keras.models.load_model('my_model.keras')

# Функции для загрузки и предсказания изображения
def load_image(filepath):
    img = Image.open(filepath).convert('L')
    img = img.resize((img_height, img_width))
    img = np.array(img)
    img = img / 255.0
    img = img.reshape(-1, img_height, img_width, 1)
    return img

def predict_digit(test_img):
    img = load_image(test_img)
    prediction = model.predict(img)
    return np.argmax(prediction)

# Пример использования
test_image = 'data\sample_a.png'
predicted_digit = predict_digit(test_image)

print(f'Цифра на изображении: {predicted_digit}')

Заключение

Сверточные нейронные сети (CNN) представляют собой мощный инструмент для решения задач, связанных с обработкой и анализом изображений. В этой статье мы рассмотрели, как создать собственную CNN для распознавания цифр, будь то рукописные или машинописные. Мы прошли через все этапы — от подготовки данных и создания проекта до обучения и оценки модели, а также научились сохранять модель и использовать её для предсказаний.

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

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

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

Комментарии (7)


  1. berng
    06.11.2024 10:55

    90% - это не отличная точность, это - так себе. У ЛеКуна в 1998 году, через 10 лет как он изобрел сверточную сеть, была 98.4% . Сейчас датасет рукописных цифр MNIST выработан. Сейчас в тестовом датасете не определяются сетями только 5 или 7 изображений (из 10000), которые даже человек не способен разобрать.


    1. NeroMiLow
      06.11.2024 10:55

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


      1. AiBurner
        06.11.2024 10:55

        Если берем собственный датасет, то от 90 % для распознования текста в данной модели - достаточно.


    1. Ruzweelt
      06.11.2024 10:55

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


  1. Ergistael
    06.11.2024 10:55

    Попробовали бы они числа в преферансной пуле разобрать...


  1. Dynasaur
    06.11.2024 10:55

    Статье явно не хватает картинок с результатами распознавания и набором данных


    1. Artemy_Dev Автор
      06.11.2024 10:55

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