В прошлой статье мы предварительно обработали изображение и построили набор данных, сегодня мы будем использовать этот набор данных для обучения нейронной сети.
обучающий набор данных
Мы должны сначала наблюдать за любым набором данных. Во-первых, нам нужно научиться различать себя, чтобы мы могли направить нейронную сеть на более целенаправленную классификацию; во-вторых, увидеть сложность проблемы, с которой мы имеем дело, что также легко понять, насколько сложна наша нейронная сеть (или более "глубокая").
Изображение выше является скриншотом нашего набора данных. Замечено, что пять символов «0», «1», «9», «I» и «O» не имеют изображения. Это наши данные неверны? Проверка исходного изображения капчи показала, что эти символы действительно отсутствуют. На самом деле, если подумать, то можно узнать, что это символы, которые легко спутать с другими символами, поэтому велика вероятность, что их можно исключить при генерации проверочного кода. Наблюдение также обнаружило, что количество изображений в каждой папке с персонажами одинаково, это также позволяет нейронной сети находить оптимальные параметры для каждого персонажа без какой-либо предвзятости.
Проектирование нейронных сетей
Сказав все это, наконец пришло время приступить к проектированию нейронных сетей. использоватьPython
Существует множество библиотек для написания нейронных сетей, таких какTensorFlow
,PyTorch
иKeras
Подождите, мы не будем обсуждать преимущества и недостатки каждого здесь, я используюKeras
, так что здесь мы используемKeras
.
Поскольку это классификация изображений, мы используем наиболее часто используемую магическую технику в задачах класса изображений — сверточную нейронную сеть (CNN).
from keras.layers import Flatten, Input, Dropout, Conv2D, MaxPooling2D, Dense
from keras.models import Model
from keras.optimizers import Adam
def model(input_size, class_num):
input = Input(shape=input_size)
x = Conv2D(16, (3,3), activation='relu', padding='same')(input)
x = MaxPooling2D((2,2), strides=(2,2))(x)
x = Conv2D(64, (3,3), activation='relu', padding='same')(input)
x = MaxPooling2D((2,2), strides=(2,2))(x)
x = Conv2D(256, (3,3), activation='relu', padding='same')(input)
x = MaxPooling2D((2,2), strides=(2,2))(x)
x = Flatten()(x)
x = Dense(1024, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(2048, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(class_num, activation='softmax')(x)
model = Model(input=input, output = x)
model.compile(optimizer=Adam(lr=1e-4), loss='categorical_crossentropy', metrics=['accuracy'])
return model
Это в основном простейшая CNN Структура модели примерно следующая:
Это простая структура свертка-объединение-свертка-объединение-свертка-объединение-полное соединение-полное соединение-выпадение Поскольку проблема очень проста, структура модели не должна быть сложной.
обучать нейронную сеть
После того, как сеть спроектирована, она готова начать обучение, то есть найти способ передать обучающие изображения в модель и позволить ей автоматически обновлять параметры. Поскольку мы уже проделали некоторую работу на ранней стадии, нам нужно только прочитать изображение в соответствии с категорией, а затем ввести его в область модели.Код для чтения изображения и создания метки выглядит следующим образом:
image_path = './chars'
data = []
labels = []
imagePaths = []
for label in os.listdir(image_path):
for image in os.listdir(os.path.join(image_path, label)):
imagePaths.append(os.path.join(image_path, label, image))
# 拿到图像数据路径,方便后续读取
imagePaths = sorted(imagePaths)
random.seed(42)
random.shuffle(imagePaths)
# 遍历读取数据
for imagePath in imagePaths:
# 读取图像数据
image = cv2.imread(imagePath, 0)
image = cv2.resize(image, (16, 16))
image = np.expand_dims(image, axis=-1)
data.append(image)
# 读取标签
label = imagePath.split(os.path.sep)[-2]
labels.append(label)
# 对图像数据做scale操作
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)
# 数据集切分
(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.25, random_state=42)
# 转换标签为one-hot encoding格式
lb = LabelBinarizer()
trainY = lb.fit_transform(trainY)
testY = lb.transform(testY)
Код для обучения модели выглядит следующим образом:
print("------准备训练网络------")
# 设置初始化超参数
EPOCHS = 50
BS = 16
# 建立卷积神经网络
model = model(input_size=(16,16,1), class_num=31)
H = model.fit(trainX, trainY, validation_data=(testX, testY), epochs=EPOCHS, batch_size=BS)
Кода для обучения модели минимум.Вы обнаружили, что обучение нейронной сети на самом деле совсем не сложно?
Взгляните на вывод при обучении нейронной сети:
Train on 332 samples, validate on 111 samples
Epoch 1/50
16/332 [>.............................] - ETA: 7s - loss: 3.4399 - accuracy: 0.0625
32/332 [=>............................] - ETA: 4s - loss: 3.4547 - accuracy: 0.0312
48/332 [===>..........................] - ETA: 3s - loss: 3.4442 - accuracy: 0.0208
64/332 [====>.........................] - ETA: 2s - loss: 3.4401 - accuracy: 0.0312
80/332 [======>.......................] - ETA: 2s - loss: 3.4368 - accuracy: 0.0250
96/332 [=======>......................] - ETA: 2s - loss: 3.4366 - accuracy: 0.0208
112/332 [=========>....................] - ETA: 1s - loss: 3.4371 - accuracy: 0.0179
128/332 [==========>...................] - ETA: 1s - loss: 3.4373 - accuracy: 0.0156
144/332 [============>.................] - ETA: 1s - loss: 3.4358 - accuracy: 0.0139
160/332 [=============>................] - ETA: 1s - loss: 3.4337 - accuracy: 0.0188
176/332 [==============>...............] - ETA: 1s - loss: 3.4330 - accuracy: 0.0170
192/332 [================>.............] - ETA: 1s - loss: 3.4310 - accuracy: 0.0156
208/332 [=================>............] - ETA: 0s - loss: 3.4313 - accuracy: 0.0192
224/332 [===================>..........] - ETA: 0s - loss: 3.4325 - accuracy: 0.0179
240/332 [====================>.........] - ETA: 0s - loss: 3.4300 - accuracy: 0.0208
256/332 [======================>.......] - ETA: 0s - loss: 3.4315 - accuracy: 0.0195
272/332 [=======================>......] - ETA: 0s - loss: 3.4334 - accuracy: 0.0184
288/332 [=========================>....] - ETA: 0s - loss: 3.4341 - accuracy: 0.0208
304/332 [==========================>...] - ETA: 0s - loss: 3.4349 - accuracy: 0.0197
320/332 [===========================>..] - ETA: 0s - loss: 3.4315 - accuracy: 0.0281
332/332 [==============================] - 2s 7ms/step - loss: 3.4340 - accuracy: 0.0271 - val_loss: 3.4193 - val_accuracy: 0.0270
Нейронная сеть будет обновлять параметры при запуске каждой эпохи, чтобы она продолжала обновляться и, наконец, достигла оптимума:
Epoch 50/50
16/332 [>.............................] - ETA: 1s - loss: 0.0155 - accuracy: 1.0000
32/332 [=>............................] - ETA: 1s - loss: 0.0132 - accuracy: 1.0000
48/332 [===>..........................] - ETA: 1s - loss: 0.0259 - accuracy: 1.0000
64/332 [====>.........................] - ETA: 1s - loss: 0.0289 - accuracy: 1.0000
80/332 [======>.......................] - ETA: 1s - loss: 0.0247 - accuracy: 1.0000
96/332 [=======>......................] - ETA: 1s - loss: 0.0271 - accuracy: 1.0000
112/332 [=========>....................] - ETA: 1s - loss: 0.0251 - accuracy: 1.0000
128/332 [==========>...................] - ETA: 1s - loss: 0.0243 - accuracy: 1.0000
144/332 [============>.................] - ETA: 1s - loss: 0.0230 - accuracy: 1.0000
160/332 [=============>................] - ETA: 1s - loss: 0.0234 - accuracy: 1.0000
176/332 [==============>...............] - ETA: 0s - loss: 0.0318 - accuracy: 0.9943
192/332 [================>.............] - ETA: 0s - loss: 0.0372 - accuracy: 0.9896
208/332 [=================>............] - ETA: 0s - loss: 0.0354 - accuracy: 0.9904
224/332 [===================>..........] - ETA: 0s - loss: 0.0395 - accuracy: 0.9866
240/332 [====================>.........] - ETA: 0s - loss: 0.0521 - accuracy: 0.9833
256/332 [======================>.......] - ETA: 0s - loss: 0.0491 - accuracy: 0.9844
272/332 [=======================>......] - ETA: 0s - loss: 0.0531 - accuracy: 0.9816
288/332 [=========================>....] - ETA: 0s - loss: 0.0510 - accuracy: 0.9826
304/332 [==========================>...] - ETA: 0s - loss: 0.0488 - accuracy: 0.9836
320/332 [===========================>..] - ETA: 0s - loss: 0.0488 - accuracy: 0.9844
332/332 [==============================] - 2s 6ms/step - loss: 0.0478 - accuracy: 0.9849 - val_loss: 0.0197 - val_accuracy: 0.9910
Ниже приведена кривая значения каждого параметра в течение всего тренировочного процесса:
Просто в процессе обучения, будь то обучающий набор или проверочный набор, их значения потерь продолжают падать до бесконечно близких к 0, в то время как точность модели бесконечно близка к 1.
Протестируйте нейронную сеть
Давайте проверим два случайных символа:
Код теста выглядит следующим образом:
# 加载测试数据并进行相同预处理操作
image = cv2.imread('./test_chars/3/1.jpg', 0)
output = image.copy()
image = cv2.resize(image, (16, 16))
# scale图像数据
image = image.astype("float") / 255.0
image = np.expand_dims(image, axis=-1)
# 对图像进行拉平操作
image = image.reshape((1, image.shape[0], image.shape[1],image.shape[2]))
# 读取模型和标签
print("------读取模型和标签------")
model = load_model('./output/cnn.model')
lb = pickle.loads(open('./output/cnn_lb.pickle', "rb").read())
# 预测
preds = model.predict(image)
# 得到预测结果以及其对应的标签
i = preds.argmax(axis=1)[0]
label = lb.classes_[i]
# 在图像中把结果画出来
text = "{}: {:.2f}%".format(label, preds[0][i] * 100)
print(text)
Результат:
Попробуйте еще:
Результат:
Результаты обоих экспериментов показывают, что производительность нашей модели нейронной сети приемлема.
постскриптум
На этом идентификация проверочного кода завершена.
Весь исходный код этой серии будет размещен в репозитории github ниже, вы можете обратиться к нему, если вам это нужно.Если у вас есть какие-либо вопросы, пожалуйста, поправьте меня, спасибо!
https://github.com/TitusWongCN/AutoTokenAppointment
Получайте последние новости, последние памятные монеты будут зарезервированы 19 числа этого месяца, поэтому эта серия закончится примерно в это время. Пожалуйста, дождитесь последней части автоматического бронирования~
Выпуск 1: Одна из серии памятных монет Python Disk: Введение
Фаза 2: Памятная монета «Диск Python», серия II: Идентификационный проверочный код 01
Фаза 3: Памятная монета «Диск Python», серия II: Идентификационный проверочный код 02
Выпуск 4: Памятные монеты Python Disk Series II: Идентификационный проверочный код 03