20、自动驾驶与CAPTCHA破解:从训练到实战

自动驾驶与CAPTCHA破解:从训练到实战

自动驾驶训练与成果

在自动驾驶的训练过程中,我们使用了一系列的函数和参数设置。首先,定义了一些关键的参数和函数:

from keras import backend as K
import numpy as np
import shutil, os
import pandas as pd
from scipy import misc
import pickle
import matplotlib.pyplot as plt
from sklearn.externals import joblib

huber_loss_thresh = 1 
action_list = np.array([
    [0.0, 0.0, 0.0],  # Brake
    [-0.6, 0.05, 0.0],  # Sharp left
    [0.6, 0.05, 0.0],  # Sharp right
    [0.0, 0.3, 0.0]  # Straight
])
rgb_mode = True
num_actions = len(action_list)

def sel_action(action_index):
    return action_list[action_index]

def sel_action_index(action):
    for i in range(num_actions):
        if np.all(action == action_list[i]):
            return i
    raise ValueError('Selected action not in list')

def huber_loss(y_true, y_pred):
    error = (y_true - y_pred)
    cond = K.abs(error) <= huber_loss_thresh
    if cond == True:
        loss = 0.5 * K.square(error)
    else:
        loss = 0.5 * huber_loss_thresh**2 + huber_loss_thresh*(K.abs(error) - huber_loss_thresh)
    return K.mean(loss)

def rgb2gray(rgb, norm=True):
    gray = np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
    if norm:
        gray = gray.astype('float32') / 128 - 1
    return gray

def data_store(path, action, reward, state):
    if not os.path.exists(path):
        os.makedirs(path)
    else:
        shutil.rmtree(path)
        os.makedirs(path)
    df = pd.DataFrame(action, columns=["Steering", "Throttle", "Brake"])
    df["Reward"] = reward
    df.to_csv(path + 'car_racing_actions_rewards.csv', index=False)
    for i in range(len(state)):
        if rgb_mode == False:
            image = rgb2gray(state[i])
        else:
            image = state[i]
        misc.imsave(path + "img" + str(i) + ".png", image)

def model_save(path, name, agent, R):
    if not os.path.exists(path):
        os.makedirs(path)
    agent.DQN.model.save(path + name)
    print(name, "saved")
    print('...')
    joblib.dump(agent.memory, path + name + 'Memory')
    joblib.dump([agent.epsilon, agent.steps, agent.DQN.opt.get_config()], path + name + 'AgentParam')
    joblib.dump(R, path + name + 'Rewards')
    print('Memory pickle dumped')

训练自动驾驶模型可以使用以下命令:

python main.py --environment_name 'CarRacing-v0' --model_path '/home/santanu/Autonomous Car/train/' --train_mode True --test_mode False --epsilon_greedy True --render True --width 96 --height 96 --num_stack 4 --huber_loss_thresh 1 --dropout 0.2 --memory_size 10000 --batch_size 128 --max_num_episodes 500

训练初期,自动驾驶汽车会犯错,但随着训练的进行,它会从错误中学习并不断改进。以下是训练过程的简单流程图:

graph LR
    A[开始训练] --> B[执行动作]
    B --> C[获取奖励和新状态]
    C --> D[存储数据]
    D --> E[更新模型]
    E --> F{是否达到最大训练轮数}
    F -- 否 --> B
    F -- 是 --> G[训练结束]

训练成果通过截图展示,初期汽车会犯错,而经过足够的训练后,汽车能够成功驾驶。

CAPTCHA相关知识与操作
CAPTCHA简介

CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart)是一种用于区分人类用户和机器或机器人的计算机程序,通常作为防止垃圾邮件和数据滥用的安全措施。其概念最早于1997年由AltaVista的首席科学家Andrei Broder提出,2003年由Luis von Ahn等人完善。常见的CAPTCHA形式是要求用户识别扭曲图像中的字母和数字,人类能够轻松识别,而自动化程序或机器人则难以做到。近年来,CAPTCHA的作用不仅限于防止机器人欺诈,例如谷歌在数字化《纽约时报》档案和谷歌图书时使用了CAPTCHA及其变体reCAPTCHA。

技术要求
  • 具备Python 3、TensorFlow、Keras和OpenCV的基础知识。
  • 代码文件可在GitHub上找到:https://github.com/PacktPublishing/Intelligent-Projects-using-Python/tree/master/Chapter10
  • 查看代码运行视频:http://bit.ly/2SgwR6P
生成基本CAPTCHA

可以使用Python的Claptcha包生成由数字和字母组成的四位CAPTCHA图像。以下是生成代码:

import numpy as np
from claptcha import Claptcha
import matplotlib.pyplot as plt

alphabets = 'abcdefghijklmnopqrstuvwxyz'
alphabets = alphabets.upper()
font = "/home/santanu/Android/Sdk/platforms/android-28/data/fonts/DancingScript-Regular.ttf"
char_num_ind = list(np.random.randint(0, 2, 4))
text = ''
for ind in char_num_ind:
    if ind == 1:
        loc = np.random.randint(0, 26, 1)
        text = text + alphabets[np.random.randint(0, 26, 1)[0]]
    else:
        text = text + str(np.random.randint(0, 10, 1)[0])
c = Claptcha(text, font)
text, image = c.image
plt.imshow(image)

生成的CAPTCHA图像会添加一些噪声,如水平方向的扭曲线条。

生成训练数据

为了训练用于破解CAPTCHA的CNN模型,需要生成训练集、验证集和测试集。以下是生成数据的脚本 CaptchaGenerator.py

from claptcha import Claptcha
import os
import numpy as np
import cv2
import fire 
from elapsedtimer import ElasedTimer

def generate_captcha(outdir, font, num_captchas=20000):
    alphabets = 'abcdefghijklmnopqrstuvwxyz'
    alphabets = alphabets.upper()
    try:
        os.mkdir(outdir)
    except:
        'Directory already present, writing captchas to the same'
    for i in range(num_captchas):
        char_num_ind = list(np.random.randint(0, 2, 4))
        text = ''
        for ind in char_num_ind:
            if ind == 1:
                loc = np.random.randint(0, 26, 1)
                text = text + alphabets[np.random.randint(0, 26, 1)[0]]
            else:
                text = text + str(np.random.randint(0, 10, 1)[0])
        c = Claptcha(text, font)
        text, image = c.image
        image.save(outdir + text + '.png')

def main_process(outdir_train, num_captchas_train,
                 outdir_val, num_captchas_val,
                 outdir_test, num_captchas_test,
                 font):
    generate_captcha(outdir_train, font, num_captchas_train)
    generate_captcha(outdir_val, font, num_captchas_val)
    generate_captcha(outdir_test, font, num_captchas_test)

if __name__ == '__main__':
    with ElasedTimer('main_process'):
        fire.Fire(main_process)

可以使用以下命令生成大小为16000、4000和4000的训练集、验证集和测试集:

python CaptchaGenerator.py --outdir_train '/home/santanu/Downloads/Captcha Generation/captcha_train/' --outdir_test '/home/santanu/Downloads/Captcha Generation/captcha_test/' --num_captchas_test 4000 --fo

脚本生成这些数据大约需要3.328分钟。

CAPTCHA破解CNN架构

使用CNN架构识别CAPTCHA中的字符,该架构在密集层之前有两对卷积和池化层。将CAPTCHA拆分为四个字符,分别输入模型,最终输出层预测36个类别之一(26个字母和10个数字)。以下是模型定义代码:

from keras.layers import Input, Conv2D, MaxPooling2D, Dropout, Flatten, Dense
from keras.models import Model

def _model_(n_classes):
    input_ = Input(shape=(40, 25, 1))
    x = Conv2D(20, (5, 5), padding="same", activation="relu")(input_)
    x = MaxPooling2D(pool_size=(2, 2), strides=(2, 2))(x)
    x = Dropout(0.2)(x)
    x = Conv2D(50, (5, 5), padding="same", activation="relu")(x)
    x = MaxPooling2D(pool_size=(2, 2), strides=(2, 2))(x)
    x = Dropout(0.2)(x)
    x = Flatten()(x)
    x = Dense(1024, activation="relu")(x)
    out = Dense(n_classes, activation='softmax')(x)
    model = Model(inputs=[input_], outputs=out)
    model.compile(loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
    return model

该模型的架构可以用以下表格简单概括:
| 层类型 | 描述 |
| ---- | ---- |
| 输入层 | 形状为(40, 25, 1) |
| 卷积层1 | 20个滤波器,(5, 5)卷积核,ReLU激活函数 |
| 池化层1 | 池化大小(2, 2),步长(2, 2) |
| 丢弃层1 | 丢弃率0.2 |
| 卷积层2 | 50个滤波器,(5, 5)卷积核,ReLU激活函数 |
| 池化层2 | 池化大小(2, 2),步长(2, 2) |
| 丢弃层2 | 丢弃率0.2 |
| 全连接层1 | 1024个节点,ReLU激活函数 |
| 输出层 | 36个节点,Softmax激活函数 |

自动驾驶与CAPTCHA破解:从训练到实战

训练CAPTCHA破解模型

在生成了训练所需的CAPTCHA数据后,接下来就是训练CAPTCHA破解模型。为了实现这一目标,还需要定义一些辅助函数和类。

import cv2
import keras
import numpy as np
import pandas as pd

def load_img(path, dim=(100, 40)):
    img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
    img = cv2.resize(img, dim)
    img = img.reshape((dim[1], dim[0], 1))
    return img / 255.

def create_dict_char_to_index():
    chars = 'abcdefghijklmnopqrstuvwxyz0123456789'.upper()
    chars = list(chars)
    index = np.arange(len(chars))
    char_to_index_dict, index_to_char_dict = {}, {}
    for v, k in zip(index, chars):
        char_to_index_dict[k] = v
        index_to_char_dict[v] = k
    return char_to_index_dict, index_to_char_dict

class DataGenerator(keras.utils.Sequence):
    def __init__(self, dest, char_to_index_dict, batch_size=32, n_classes=36, dim=(40, 100, 1), shuffle=True):
        self.dest = dest
        self.files = os.listdir(self.dest)
        self.char_to_index_dict = char_to_index_dict
        self.batch_size = batch_size
        self.n_classes = n_classes
        self.dim = (40, 100)
        self.shuffle = shuffle
        self.on_epoch_end()

    def __len__(self):
        return int(np.floor(len(self.files) / self.batch_size))

    def __getitem__(self, index):
        indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]
        list_files = [self.files[k] for k in indexes]
        X, y = self.__data_generation(list_files)
        return X, y

    def on_epoch_end(self):
        self.indexes = np.arange(len(self.files))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)

    def __data_generation(self, list_files):
        dim_h = self.dim[0]
        dim_w = self.dim[1] // 4
        channels = 1
        X = np.empty((4 * len(list_files), dim_h, dim_w, channels))
        y = np.empty((4 * len(list_files)), dtype=int)
        k = -1
        for f in list_files:
            target = list(f.split('.')[0])
            target = [self.char_to_index_dict[c] for c in target]
            img = load_img(self.dest + f)
            img_h, img_w = img.shape[0], img.shape[1]
            crop_w = img.shape[1] // 4
            for i in range(4):
                img_crop = img[:, i * crop_w:(i + 1) * crop_w]
                k += 1
                X[k, ] = img_crop
                y[k] = int(target[i])
        return X, y

训练CAPTCHA破解模型的函数如下:

def train(dest_train, dest_val, outdir, batch_size, n_classes, dim, shuffle, epochs, lr):
    char_to_index_dict, index_to_char_dict = create_dict_char_to_index()
    model = _model_(n_classes)
    train_generator = DataGenerator(dest_train, char_to_index_dict, batch_size, n_classes, dim, shuffle)
    val_generator = DataGenerator(dest_val, char_to_index_dict, batch_size, n_classes, dim, shuffle)
    model.fit_generator(train_generator, epochs=epochs, validation_data=val_generator)
    model.save(outdir + 'captcha_breaker.h5')

可以使用以下命令运行 captcha_solver.py 脚本进行训练:

python captcha_solver.py train --dest_train '/home/santanu/Downloads/Captcha Generation/captcha_train/'

训练过程的流程图如下:

graph LR
    A[开始训练] --> B[创建数据生成器]
    B --> C[加载模型]
    C --> D[训练模型]
    D --> E[保存模型]
    E --> F[训练结束]

在仅20个训练周期内,模型在CAPTCHA字符级别的验证准确率约达到98.3%。以下是训练过程的部分输出日志:

Epoch 17/20
1954/1954 [==============================] - 14s 7ms/step - loss: 0.0340 - acc: 0.9896 - val_loss: 0.0
Epoch 18/20
1954/1954 [==============================] - 13s 7ms/step - loss: 0.0310 - acc: 0.9904 - val_loss: 0.0
Epoch 19/20
1954/1954 [==============================] - 13s 7ms/step - loss: 0.0315 - acc: 0.9904 - val_loss: 0.0
Epoch 20/20
1954/1954 [==============================] - 13s 7ms/step - loss: 0.0297 - acc: 0.9910 - val_loss: 0.0
4.412 min: captcha_solver

使用GeForce GTX 1070 GPU进行20个周期的训练,大约需要4.412分钟,建议使用基于GPU的机器以加快训练速度。

测试CAPTCHA破解模型

训练好模型后,需要在测试数据集上评估模型的性能。以下是用于运行测试集推理的 evaluate 函数:

def evaluate(model_path, eval_dest, outdir, fetch_target=True):
    char_to_index_dict, index_to_char_dict = create_dict_char_to_index()
    files = os.listdir(eval_dest)
    model = keras.models.load_model(model_path)
    predictions, targets = [], []
    for f in files:
        if fetch_target == True:
            target = list(f.split('.')[0])
            targets.append(target)
        pred = []
        img = load_img(eval_dest + f)
        img_h, img_w = img.shape[0], img.shape[1]
        crop_w = img.shape[1] // 4
        for i in range(4):
            img_crop = img[:, i * crop_w:(i + 1) * crop_w]
            img_crop = img_crop[np.newaxis, :]
            pred_index = np.argmax(model.predict(img_crop), axis=1)
            pred_char = index_to_char_dict[pred_index[0]]
            pred.append(pred_char)
        predictions.append(pred)
    df = pd.DataFrame()
    df['files'] = files
    df['predictions'] = predictions
    if fetch_target == True:
        match = []
        df['targets'] = targets
        accuracy_count = 0
        for i in range(len(files)):
            if targets[i] == predictions[i]:
                accuracy_count += 1
                match.append(1)
            else:
                match.append(0)
        print(f'Accuracy: {accuracy_count / float(len(files))} ')
        eval_file = outdir + 'evaluation.csv'
        df['match'] = match
        df.to_csv(eval_file, index=False)
        print(f'Evaluation file written at: {eval_file} ')

可以使用以下命令运行 captcha_solver.py 脚本的 evaluate 函数进行推理:

python captcha_solver.py evaluate --model_path /home/santanu/ML_DS_Catalog-/captcha/model/captcha_breaker.h5 --eval_dest '/home/santanu/Downloads/Captcha Generation/captcha_test/' --outdir /home/santanu/ML_DS_Catalog-/captcha/ --fetch_target True

在4000个CAPTCHA的测试数据集上,模型的准确率约为93%。以下是运行 evaluate 函数的输出:

Accuracy: 0.9320972187421699 
Evaluation file written at: /home/santanu/ML_DS_Catalog-/captcha/evaluation.csv 
13.564 s: captcha_solver

推理4000个CAPTCHA大约需要14秒,评估结果会写入 /home/santanu/ML_DS_Catalog-/captcha/evaluation.csv 文件。同时,还可以查看模型在哪些CAPTCHA上表现不佳,这有助于进一步分析和改进模型。

综上所述,通过一系列的步骤,我们实现了自动驾驶模型的训练和CAPTCHA破解模型的训练与测试。自动驾驶模型从最初的犯错到逐渐学会正确驾驶,而CAPTCHA破解模型在测试集上也取得了较高的准确率。这些成果展示了深度学习在实际应用中的强大能力,但同时也提醒我们需要不断改进CAPTCHA技术以应对日益强大的破解手段。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值