Постановка задачи
Задача состоит в том, чтобы написать программное обеспечение, которое будет принимать изображение в качестве входных данных и давать рекомендации по сопоставлению шрифтов с уровнем достоверности. Программа будет протестирована на заданном наборе изображений.
Мы можем предположить следующее.
- Все изображения имеют известный текст «Hello, World!»
- Все изображения имеют белый фон с черным текстом.
- Количество шрифтов, которым мы сопоставляем, ограничено шрифтами, указанными ниже.
https://fonts.google.com/specimen/Освальд
https://fonts.google.com/specimen/Roboto
https://fonts.google.com/specimen/Open+Sans
https://fonts.google.com/specimen/Ubuntu
https://fonts.google.com/specimen/PT+Serif
https://fonts.google.com/specimen/Dancing+Script
https://fonts.google.com/specimen/Fredoka+One
https://fonts.google.com/specimen/Аримо
https://fonts.google.com/specimen/Noto+Sans
https://fonts.google.com/specimen/Patua+One
- Наше программное обеспечение должно иметь возможность добавлять больше шрифтов позже
Подход к решению
Проблема разбита на три части.
- Генерация обучающего набора данных
- Преобразование модели CNN и настройка модели
- Оценка модели и тестирование
Создание обучающего набора данных
Генерация набора обучающих данных является важной частью любой классификации на основе CNN. Качество набора данных напрямую влияет на качество обучения и результаты. Для этого проекта нам дали 10 шрифтов для сравнения.
Затем нам нужно создать разные наборы изображений для каждого шрифта с разным размером шрифта и положением текста. Текстовый фон для этой проблемы исправлен.
min_size = 30 max_size = 75 image_w = 224 image_h = 448 positions = [(0,image_w/3),(0,0), (0,image_w/2), (0,image_w/4)]
Мы создаем и сохраняем изображения в правильной структуре папок, чтобы мы могли легко загрузить их позже для обучения. В папке dataset/train мы создаем новые папки с именами шрифтов. Изображения сохраняются в соответствующих папках.
for f in all_fonts: count=0; folderpath = "./dataset/train/" + os.path.basename(f[:-4]) os.mkdir(folderpath) order.append(os.path.basename(f[:-4])) for size in range(min_size, max_size, 2): for p in positions: #Create image and save
Мы сохраняем изображения после изменения их размера до размера 224x224, так как это стандартный размер, используемый многими стандартными моделями. Мы повторяем те же шаги с меньшим количеством вариантов, чтобы создать набор данных проверки.
Обучение моделей
Когда мы обучаем сеть с нуля, мы сталкиваемся со следующими двумя ограничениями:
- Требуются огромные данные. Поскольку сеть имеет миллионы параметров, для получения оптимального набора параметров нам нужно иметь много данных.
- Требуется огромная вычислительная мощность. Даже если у нас много данных, обучение обычно требует нескольких итераций, что сказывается на вычислительных ресурсах.
Задача тонкой настройки сети состоит в том, чтобы настроить параметры уже обученной сети, чтобы она адаптировалась к новой задаче. Тонкая настройка позволяет избежать обоих ограничений, описанных выше.
Первым шагом является загрузка модели VGG16 с весами, сохраненными из базы данных imagenet. Мы удаляем верхние слои FC, чтобы его можно было обучить на нашем наборе данных.
conv_base = VGG16(weights='imagenet', include_top=False,input_shape=(img_width, img_height, 3))
Затем мы замораживаем все слои, кроме последних 4 слоев. При этом мы извлекаем уроки из наших данных только в последних 4 слоях. Мы переносим веса из предварительно обученной модели.
# Freeze the layers except the last 4 layers for layer in conv_base.layers[:-4]: layer.trainable = False
Теперь мы создаем нашу собственную модель CNN. Важным моментом здесь является убедиться, что длина функции совпадает, а последний слой — «softmax» с выходными классами 10, то есть для 10 классов для шрифтов.
# Create the model model = models.Sequential() # Add the vgg convolutional base model model.add(conv_base) # Add new layers model.add(layers.Flatten()) model.add(layers.Dense(1024, activation='relu')) model.add(layers.Dropout(0.5)) model.add(layers.Dense(no_classes, activation='softmax')) model.summary()
Резюме нашей модели выглядит так.
Layer (type) Output Shape Param # ================================================================= vgg16 (Model) (None, 7, 7, 512) 14714688 _________________________________________________________________ flatten_4 (Flatten) (None, 25088) 0 _________________________________________________________________ dense_12 (Dense) (None, 1024) 25691136 _________________________________________________________________ dropout_6 (Dropout) (None, 1024) 0 _________________________________________________________________ dense_13 (Dense) (None, 10) 10250 ================================================================= Total params: 40,416,074 Trainable params: 32,780,810 Non-trainable params: 7,635,264 _________________________________________________________________
мы компилируем модель с кросс-энтропийными потерями и оптимизаторами RMSprop.
model.compile(loss='categorical_crossentropy', optimizer=optimizers.RMSprop(lr=1e-4), metrics=['acc'])
Наконец, мы обучаем модель. Keras предоставляет ImageDataGenerator и flow_from_directory для хорошей обработки изображений для обучения. Наконец модель сохраняется как файл h5.
# Train the model history = model.fit_generator(train_generator, steps_per_epoch=train_generator.samples/train_generator.batch_size, epochs=30, validation_data=validation_generator, validation_steps=validation_generator.samples/validation_generator.batch_size, verbose=1)
Заключительная тренировка закончилась при указанных ниже точности и потерях. Учебная модель дает и точность 87%.
404s 2s/step - loss: 0.4848 - acc: 0.8717 - val_loss: 1.1505 - val_acc: 0.7667
Когда мы сейчас запустим модель на данных проверки, мы увидим, как работает модель.
Found 90 images belonging to 10 classes. 18/18 [==============================] — 21s 1s/step Correct detection = 69/90
Несколько примеров правильного и неудачного обнаружения показаны ниже.
Наконец, мы пишем еще один скрипт для загрузки модели и запуска для каждого пакета изображений. Здесь вывод изменен, чтобы выдать рекомендацию, а не одно совпадение, как требуется в постановке задачи. Сценарий перечисляет 3 наиболее подходящих шрифта с перечисленными значениями достоверности.
Результаты записываются в текстовый файл и сохраняются в рабочем каталоге.
Будущая работа
- Учебный набор и обучение были ограничены низкой вычислительной мощностью. Нам нужно увеличить тренировочный набор с большим количеством вариаций. Нам нужно добавить повороты, размеры шрифта и размеры изображения в тренировочный набор для большей точности.
- Мы не использовали обучение преобразованию предварительно обученной модели, где мы используем предварительно обученную модель только в качестве средства извлечения признаков изображения. Это также связано с меньшим диапазоном доступных наборов данных.