Идентификация простого изображения Captcha с TensorFlow

машинное обучение искусственный интеллект TensorFlow Python

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

Во-первых, потому что проверочный код относительно прост, изображение несложное и состоит из цифр. Поэтому я попытался использовать традиционный метод и просто сам изменил его в соответствии с онлайн-руководством, используя идентификацию PHP. Общий процесс заключается в том, чтобы вырезать предварительную обработку, такую ​​​​как бинаризация и шумоподавление, а затем сохранить ее в виде массива строк.После идентификации входящих изображений сравните сходство строк после той же предварительной обработки и выберите категорию с наивысшим значением. степень знакомства. Скорость распознавания не идеальна (проверочный код относительно прост и должен быть лучше оптимизирован), а смутная память может превышать только 60%.

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

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

В этой статье описаны лишь некоторые поверхностные представления рядового разработчика.Весь код и данные хранятся на GitHub после публикации статьи., рекомендуется читать эту статью вместе с кодом. Если есть какие-либо недоразумения или ошибки, пожалуйста, оставьте сообщение для обмена ^_^

Что такое ТензорФлоу

TensorFlow — это фреймворк машинного обучения от Google. Как следует из названия, TensorFlow — это «tensorflow». Эм-м-м. . Что такое тензор? Тензор, как я понимаю, это данные. Тензоры имеют свою форму, например, тензор ранга 0 — скаляр, ранг 1 — вектор, а ранг 2 — матрица. . . Итак, далее мы увидим, что величины, используемые в TensorFlow, почти должны определять свою форму, потому что все они являются тензорами.

Мы можем думать о TensorFlow как о черном ящике с несколькими конвейерами внутри, скармливать ему какие-то «тензоры», он выдает какие-то «тензоры», и то, что мы выплевываем, и есть нужный нам результат.

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

Для получения дополнительных вводных концепций вы можете проверить этоРуководство для начинающих по keras » Некоторые основные понятия

Зачем использовать TensorFlow

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

Общий процесс

  1. Получите код подтверждения
  2. Отметьте код подтверждения
  3. предварительная обработка изображений
  4. сохранить набор данных
  5. Обучение построению модели
  6. Извлеките модель, используя

Получите код подтверждения

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

Отметьте код подтверждения

Здесь проверочных кодов 750. Если вы вручную помечаете каждый проверочный код, это должно быть утомительно. В настоящее время мы можем использовать услугу ручного кодирования, чтобы помочь нам сделать это с дешевой рабочей силой. После ручного кодирования результаты распознавания сохраняются. Код здесь не предоставляется, в зависимости от того, какой сервис кодов подтверждения вы используете, я думаю, вы сможете решить его с умом :)

предварительная обработка изображений

  1. информация об изображении:Этот проверочный код имеет размер 68x23, формат JPG.
  2. Бинаризация:Я уверен, что эта капча достаточно проста и все еще узнаваема после потери информации о цвете изображения. И сложность модели может быть уменьшена, поэтому мы можем бинаризировать изображение. То есть есть только два цвета, все черное или все белое.
  3. Вырезать проверочный код:Соблюдайте проверочный код, особых искажений и прилипаний нет, поэтому мы можем разрезать проверочный код в среднем на 4 части и идентифицировать их отдельно, так что модели распознавания изображений нужно будет обработать только 10 категорий (если есть буквы, она будет быть только 36 категорий) В связи с проверкой есть граница снаружи кода, поэтому граница кстати тоже убрана.
  4. результат процесса:16x21, черно-белое, 2 бита

Соответствующий код Python выглядит следующим образом:

img = Image.open(file).convert('L') # 读取图片并灰度化

img = img.crop((2, 1, 66, 22)) # 裁掉边变成 64x21

# 分离数字
img1 = img.crop((0, 0, 16, 21))
img2 = img.crop((16, 0, 32, 21))
img3 = img.crop((32, 0, 48, 21))
img4 = img.crop((48, 0, 64, 21))

img1 = np.array(img1).flatten() # 扁平化,把二维弄成一维
img1 = list(map(lambda x: 1 if x <= 180 else 0, img1)) # 二值化
img2 = np.array(img2).flatten()
img2 = list(map(lambda x: 1 if x <= 180 else 0, img2))
img3 = np.array(img3).flatten()
img3 = list(map(lambda x: 1 if x <= 180 else 0, img3))
img4 = np.array(img4).flatten()
img4 = list(map(lambda x: 1 if x <= 180 else 0, img4))

сохранить набор данных

Набор данных имеет входные входные данные и данные меток, обучающие данные и тестовые данные. Поскольку объем данных невелик, для простоты данные сохраняются непосредственно в виде файла python для вызова модели. Не сохраняйте его как другой файл, а затем используйтеpandasчто-нибудь почитать.

Окончательная форма данных для нашей входной модели:[[0,1,0,1,0,1,0,1...],[0,1,0,1,0,1,0,1...],...]Данные метки очень особенные, по сути, мы классифицируем входные данные, поэтому, хотя метка должна быть числом от 0 до 9, здесь мы делаем формат данных метки какone-hot vectors [[1,0,0,0,0,0,0,0,0,0,0],...]В однократном векторе, за исключением того, что число одной цифры равно 1, другие числа измерений равны 0**, например [1,0,0,0,0,0,0,0,0,0] представляет 1 , [0,1,0,0,0,0,0,0,0,0] означает 2. Кроме того, горячий вектор здесь фактически представляет вероятность того, что соответствующие данные разделены на эти десять категорий. Вероятность 1 является правильной классификацией.

Соответствующий код Python выглядит следующим образом:

# 保存输入数据
def px(prefix, img1, img2, img3, img4):
    with open('./data/' + prefix + '_images.py', 'a+') as f:
        print(img1, file=f, end=",\n")
        print(img2, file=f, end=",\n")
        print(img3, file=f, end=",\n")
        print(img4, file=f, end=",\n")

# 保存标签数据
def py(prefix, code):
    with open('./data/' + prefix + '_labels.py', 'a+') as f:
        for x in range(4):
            tmp = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            tmp[int(code[x])] = 1
            print(tmp, file=f, end=",\n")

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

Обучение построению модели

Данные готовы, пора строить «конвейер». То есть нужно сказать TensorFlow:

1. Какова форма входных данных?

x = tf.placeholder(tf.float32, [None, DLEN])

None означает, что мы не определяем, сколько данных для обучения у нас есть.DLEN составляет 16 * 21, что является размером одномерного изображения.

2. Какова форма выходных данных?

y_ = tf.placeholder("float", [None, 10])

Точно так же None означает, что он не определяет, сколько у нас обучающих данных 10 — это размер данных метки, то есть изображение имеет 10 категорий. Каждая классификация соответствует вероятности, поэтому это тип с плавающей запятой.

3. Как согласовать входные данные, модель и данные этикетки?

W = tf.Variable(tf.zeros([DLEN, 10])) # 权重
b = tf.Variable(tf.zeros([10])) # 偏置

y = tf.nn.softmax(tf.matmul(x, W) + b)

Это очень простая модель? грубоy = softmax(Wx+b)Там, где W и b — переменные в TensorFlow, они содержат данные модели во время обучения и должны быть определены. Цель обучения нашей модели — определить значения W и b, чтобы эта формула могла лучше соответствовать данным.softmaxЭто так называемая функция активации, которая преобразует линейный результат в нужный нам стиль, то есть распределение вероятности классификации. оsoftmaxДополнительные пояснения см. по ссылке.

4. Как оценить качество модели?

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

cross_entropy = -tf.reduce_sum(y_*tf.log(y))

5. Как минимизировать ошибку?

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

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

подготовка к обучению

Всем известно, что Python, как интерпретируемый язык, нельзя считать очень эффективным, и такого рода машинное обучение в основном требует больших вычислительных мощностей. TensorFlow написан на C++ на нижнем уровне и является просто рабочим портом на стороне Python, и все вычисления должны быть переданы на нижний уровень для обработки. Это естественным образом приводит кбеседаКонцепция, согласно которой нижний уровень и вызывающий уровень должны взаимодействовать. Также благодаря этой функции TensorFlow поддерживает доступ ко многим другим языкам, таким как Java, C, а не только к Python. Связь с нижележащими уровнями осуществляется через сеансы. Мы можем начать сеанс с одной строки кода:

sess = tf.Session()
# 代码...
sess.close()

Не забудьте закрыть сеанс, когда закончите его использовать. Конечно, вы также можете использовать PythonwithЗаявление для автоматического управления.

В TensorFlow переменные должны быть инициализированы после запуска сеанса, прежде чем их можно будет использовать.

sess.run(tf.global_variables_initializer())

начать обучение

for i in range(DNUM):
    batch_xs = [train_images.data[i]]
    batch_ys = [train_labels.data[i]]
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

Мы передаем модель и обучающие данные в сеанс, и нижний слой автоматически обрабатывает их за нас. Мы можем передать любой объем данных в модель за один раз (эффект установки None выше), а для эффекта обучения мы можем соответствующим образом настроить данные для каждой партии обучения. Иногда для получения лучших результатов обучения требуется даже случайный отбор данных. Здесь мы будем тренироваться по очереди, так или иначе, конечный эффект в порядке. Чтобы узнать больше, перейдите по справочной ссылке.

Проверьте результаты обучения

Вот где наши тестовые данные пригодятся

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print(sess.run(accuracy, feed_dict={x: test_images.data, y_: test_labels.data}))

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

Извлеките модель, используя

Мы обучили модель выше, и эффект неплохой, показатель точности почти 99% может быть выше, чем у ручного кодирования (часто возвращаются значения ошибок при получении тестовых данных). Но тут возникает вопрос, что мне теперь делать, если я хочу использовать эту модель в продакшене, каждый раз обучать ее невозможно. Здесь мы собираемся использовать функции сохранения и загрузки модели TensorFlow.

сохранить модель

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

saver = tf.train.Saver()
# 训练代码
# ...
saver.save(sess, 'model/model')
sess.close()

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

модель восстановления

Та же модель восстановления также очень проста

saver.restore(sess, "model/model")

Конечно, вам все равно нужно определить модель для восстановления. Насколько я понимаю, модель сохраняет здесь значение каждой переменной в процессе обучения, смещение веса и т. д., поэтому структурную основу все же необходимо настроить заранее.

Наконец

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

Ссылки по теме

  1. https://github.com/purocean/tensorflow-simple-captcha
  2. https://keras-cn.readthedocs.io/en/latest/for_beginners/concepts/
  3. http://wiki.jikexueyuan.com/project/tensorflow-zh/