卷积神经网络(CNN)识别验证码

文章目录

  • 一、前言
  • 二、前期工作
    • 1. 设置GPU(如果使用的是CPU可以忽略这步)
    • 2. 导入数据
    • 3. 查看数据
    • 4.标签数字化
  • 二、构建一个tf.data.Dataset
    • 1.预处理函数
    • 2.加载数据
    • 3.配置数据
  • 三、搭建网络模型
  • 四、编译
  • 五、训练
  • 六、模型评估
  • 七、保存和加载模型
  • 八、预测

一、前言

我的环境:

  • 语言环境:Python3.6.5
  • 编译器:jupyter notebook
  • 深度学习环境:TensorFlow2.4.1

往期精彩内容:

  • 卷积神经网络(CNN)实现mnist手写数字识别
  • 卷积神经网络(CNN)多种图片分类的实现
  • 卷积神经网络(CNN)衣服图像分类的实现
  • 卷积神经网络(CNN)鲜花识别
  • 卷积神经网络(CNN)天气识别
  • 卷积神经网络(VGG-16)识别海贼王草帽一伙
  • 卷积神经网络(ResNet-50)鸟类识别
  • 卷积神经网络(AlexNet)鸟类识别

来自专栏:机器学习与深度学习算法推荐

二、前期工作

1. 设置GPU(如果使用的是CPU可以忽略这步)

import tensorflow as tf

gpus = tf.config.list_physical_devices("GPU")

if gpus:
    tf.config.experimental.set_memory_growth(gpus[0], True)  #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpus[0]],"GPU")

2. 导入数据

import matplotlib.pyplot as plt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

import os,PIL,random,pathlib

# 设置随机种子尽可能使结果可以重现
import numpy as np
np.random.seed(1)

# 设置随机种子尽可能使结果可以重现
import tensorflow as tf
tf.random.set_seed(1)
data_dir = "code"
data_dir = pathlib.Path(data_dir)

all_image_paths = list(data_dir.glob('*'))
all_image_paths = [str(path) for path in all_image_paths]

# 打乱数据
random.shuffle(all_image_paths)

# 获取数据标签
all_label_names = [path.split("\\")[5].split(".")[0] for path in all_image_paths]

image_count = len(all_image_paths)
print("图片总数为:",image_count)

3. 查看数据

plt.figure(figsize=(10,5))

for i in range(20):
    plt.subplot(5,4,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    
    # 显示图片
    images = plt.imread(all_image_paths[i])
    plt.imshow(images)
    # 显示标签
    plt.xlabel(all_label_names[i])

plt.show()

在这里插入图片描述

4.标签数字化

number   = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
char_set       = number + alphabet
char_set_len   = len(char_set)
label_name_len = len(all_label_names[0])


# 将字符串数字化
def text2vec(text):
    vector = np.zeros([label_name_len, char_set_len])
    for i, c in enumerate(text):
        idx = char_set.index(c)
        vector[i][idx] = 1.0
    return vector

all_labels = [text2vec(i) for i in all_label_names]

二、构建一个tf.data.Dataset

1.预处理函数

def preprocess_image(image):
    image = tf.image.decode_jpeg(image, channels=1)
    image = tf.image.resize(image, [50, 200])
    return image/255.0

def load_and_preprocess_image(path):
    image = tf.io.read_file(path)
    return preprocess_image(image)

2.加载数据

构建 tf.data.Dataset 最简单的方法就是使用 from_tensor_slices 方法。

AUTOTUNE = tf.data.experimental.AUTOTUNE

path_ds  = tf.data.Dataset.from_tensor_slices(all_image_paths)
image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE)
label_ds = tf.data.Dataset.from_tensor_slices(all_labels)

image_label_ds = tf.data.Dataset.zip((image_ds, label_ds))
image_label_ds
<ZipDataset shapes: ((50, 200, 1), (5, 36)), types: (tf.float32, tf.float64)>
train_ds = image_label_ds.take(1000)  # 前1000个batch
val_ds   = image_label_ds.skip(1000)  # 跳过前1000,选取后面的

3.配置数据

先复习一下prefetch()函数。prefetch()功能详细介绍:CPU 正在准备数据时,加速器处于空闲状态。相反,当加速器正在训练模型时,CPU 处于空闲状态。因此,训练所用的时间是 CPU 预处理时间和加速器训练时间的总和。prefetch()将训练步骤的预处理和模型执行过程重叠到一起。当加速器正在执行第 N 个训练步时,CPU 正在准备第 N+1 步的数据。这样做不仅可以最大限度地缩短训练的单步用时(而不是总用时),而且可以缩短提取和转换数据所需的时间。如果不使用prefetch(),CPU 和 GPU/TPU 在大部分时间都处于空闲状态:

BATCH_SIZE = 16

train_ds = train_ds.batch(BATCH_SIZE)
train_ds = train_ds.prefetch(buffer_size=AUTOTUNE)

val_ds = val_ds.batch(BATCH_SIZE)
val_ds = val_ds.prefetch(buffer_size=AUTOTUNE)
val_ds

三、搭建网络模型

from tensorflow.keras import datasets, layers, models

model = models.Sequential([
    
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(50, 200, 1)),#卷积层1,卷积核3*3
    layers.MaxPooling2D((2, 2)),                   #池化层1,2*2采样
    layers.Conv2D(64, (3, 3), activation='relu'),  #卷积层2,卷积核3*3
    layers.MaxPooling2D((2, 2)),                   #池化层2,2*2采样
    
    layers.Flatten(),                              #Flatten层,连接卷积层与全连接层
    layers.Dense(1000, activation='relu'),         #全连接层,特征进一步提取
    
    layers.Dense(label_name_len * char_set_len),
    layers.Reshape([label_name_len, char_set_len]),
    layers.Softmax()                               #输出层,输出预期结果
])
# 打印网络结构
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 48, 198, 32)       320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 24, 99, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 22, 97, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 11, 48, 64)        0         
_________________________________________________________________
flatten (Flatten)            (None, 33792)             0         
_________________________________________________________________
dense (Dense)                (None, 1000)              33793000  
_________________________________________________________________
dense_1 (Dense)              (None, 180)               180180    
_________________________________________________________________
reshape (Reshape)            (None, 5, 36)             0         
_________________________________________________________________
softmax (Softmax)            (None, 5, 36)             0         
=================================================================
Total params: 33,991,996
Trainable params: 33,991,996
Non-trainable params: 0
_________________________________________________________________

四、编译

model.compile(optimizer="adam",
              loss='categorical_crossentropy',
              metrics=['accuracy'])

五、训练

epochs = 20

history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs
)
Epoch 1/20
63/63 [==============================] - 4s 21ms/step - loss: 3.2998 - accuracy: 0.0934 - val_loss: 2.2876 - val_accuracy: 0.2943
Epoch 2/20
63/63 [==============================] - 1s 9ms/step - loss: 1.7016 - accuracy: 0.5195 - val_loss: 1.2014 - val_accuracy: 0.6314
Epoch 3/20
63/63 [==============================] - 1s 10ms/step - loss: 0.5267 - accuracy: 0.8379 - val_loss: 0.9039 - val_accuracy: 0.7286
Epoch 4/20
63/63 [==============================] - 1s 10ms/step - loss: 0.1911 - accuracy: 0.9442 - val_loss: 0.8609 - val_accuracy: 0.7457
Epoch 5/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0916 - accuracy: 0.9714 - val_loss: 0.8937 - val_accuracy: 0.7886
Epoch 6/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0680 - accuracy: 0.9798 - val_loss: 0.5842 - val_accuracy: 0.8429
Epoch 7/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0443 - accuracy: 0.9900 - val_loss: 0.6235 - val_accuracy: 0.8200
Epoch 8/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0203 - accuracy: 0.9947 - val_loss: 0.7697 - val_accuracy: 0.8029
Epoch 9/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0131 - accuracy: 0.9975 - val_loss: 0.6660 - val_accuracy: 0.8314
Epoch 10/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0227 - accuracy: 0.9940 - val_loss: 0.6018 - val_accuracy: 0.8229
Epoch 11/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0093 - accuracy: 0.9985 - val_loss: 0.5714 - val_accuracy: 0.8429
Epoch 12/20
63/63 [==============================] - 1s 10ms/step - loss: 0.0010 - accuracy: 1.0000 - val_loss: 0.5793 - val_accuracy: 0.8571
Epoch 13/20
63/63 [==============================] - 1s 10ms/step - loss: 2.6284e-04 - accuracy: 1.0000 - val_loss: 0.5920 - val_accuracy: 0.8571
Epoch 14/20
63/63 [==============================] - 1s 10ms/step - loss: 1.8502e-04 - accuracy: 1.0000 - val_loss: 0.6031 - val_accuracy: 0.8571
Epoch 15/20
63/63 [==============================] - 1s 10ms/step - loss: 1.4164e-04 - accuracy: 1.0000 - val_loss: 0.6120 - val_accuracy: 0.8571
Epoch 16/20
63/63 [==============================] - 1s 10ms/step - loss: 1.1334e-04 - accuracy: 1.0000 - val_loss: 0.6198 - val_accuracy: 0.8571
Epoch 17/20
63/63 [==============================] - 1s 10ms/step - loss: 9.4027e-05 - accuracy: 1.0000 - val_loss: 0.6269 - val_accuracy: 0.8571
Epoch 18/20
63/63 [==============================] - 1s 10ms/step - loss: 8.0025e-05 - accuracy: 1.0000 - val_loss: 0.6335 - val_accuracy: 0.8514
Epoch 19/20
63/63 [==============================] - 1s 9ms/step - loss: 6.9294e-05 - accuracy: 1.0000 - val_loss: 0.6396 - val_accuracy: 0.8486
Epoch 20/20
63/63 [==============================] - 1s 10ms/step - loss: 6.0775e-05 - accuracy: 1.0000 - val_loss: 0.6448 - val_accuracy: 0.8486

六、模型评估

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)


plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

七、保存和加载模型

# 保存模型
model.save('model/12_model.h5')
# 加载模型
new_model = tf.keras.models.load_model('model/12_model.h5')

八、预测

def vec2text(vec):
    """
    还原标签(向量->字符串)
    """
    text = []
    for i, c in enumerate(vec):
        text.append(char_set[c])
    return "".join(text)

plt.figure(figsize=(10, 8))            # 图形的宽为10高为8


for images, labels in val_ds.take(1):
    for i in range(6):
        ax = plt.subplot(5, 2, i + 1)  
        # 显示图片
        plt.imshow(images[i])

        # 需要给图片增加一个维度
        img_array = tf.expand_dims(images[i], 0) 

        # 使用模型预测验证码
        predictions = model.predict(img_array)
        plt.title(vec2text(np.argmax(predictions, axis=2)[0]))

        plt.axis("off")

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/189886.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年网络安全比赛--综合渗透测试②(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 1.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将扫描开放的所有端口当作flag提交(例:21,22,23); 2.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将初…

Linux内核--内存管理(一)任务空间管理

目录 一、引言 二、基本概念梳理 三、用户态进程内存管理 ------>3.1、用户态 ------>3.2、内核态 ------>3.3、内存管理结构 ------>3.4、mm_struct ------>4.5、vm_area_struct 四、内核态结构 ------>4.1、32位内核态结构 ------>4.2、64位…

电源的纹波

电源纹波的产生 我们常见的电源有线性电源和开关电源&#xff0c;它们输出的直流电压是由交流电压经整流、滤波、稳压后得到的。由于滤波不干净&#xff0c;直流电平之上就会附着包含周期性与随机性成分的杂波信号&#xff0c;这就产生了纹波。 在额定输出电压、电流的情况下…

【精选必看】MyBatis映射文件及动态SQL,一级,二级缓存介绍

文章目录 MyBatis映射文件 < r e s u l t M a p > <resultMap> <resultMap>resultMap < sql>&< include>特殊字符处理 动态SQL < i f > < if> <if> < w h e r e > <where> <where> < s e t > <…

Redis分片集群

文章目录 Redis分片集群搭建分片集群散列插槽插槽原理小结 集群伸缩需求分析创建新的redis实例添加新节点到redis转移插槽 故障转移自动故障转移手动故障转移 RedisTemplate访问分片集群 Redis分片集群 搭建分片集群 主从和哨兵可以解决高可用、高并发读的问题。但是依然有两…

大数据数据仓库,Sqoop--学习笔记

数据仓库介绍 1. 数据仓库概念 数据仓库概念创始人在《建立数据仓库》一书中对数据仓库的定义是&#xff1a;数据仓库&#xff08;Data Warehouse&#xff09;是一个面向主题的&#xff08;Subject Oriented&#xff09;、数据集成的&#xff08;Integrated&#xff09;、相对…

【C++】String类

目录 本文将对string常用函数进行说明 string基础介绍 string类的常用接口说明 string() &&string(const char* s) 拷贝:string (const string& str, size_t pos, size_t len npos) 拷贝前n个进行构造&#xff1a;string (const char* s, size_t n);​编辑 …

快速幂算法详解(C++实现)

文章目录 1. 什么是快速幂2. 暴力求解代码实现缺陷分析 3. 优化一&#xff1a;取模运算的性质4. 优化二&#xff1a;快速幂算法的核心思想5. 终极优化&#xff1a;位运算优化6. 源码 这篇文章我们来一起学习一个算法——快速幂算法。 1. 什么是快速幂 顾名思义&#xff0c;快速…

将本地项目上传到gitee

本文详细介绍如何将本地项目上传到gitee 1.登录gitee创建一个与本地项目名相同的仓库 2.进入本地项目所在路径&#xff0c;打开Git Bash 3.执行初始化命令 git init4.添加远程仓库 4.1 点击复制你的HTTPS仓库路径 4.2 执行添加远程仓库命令 git remote add origin 你的…

【Vue】filter的用法

上一篇&#xff1a; vue的指令 https://blog.csdn.net/m0_67930426/article/details/134599378?spm1001.2014.3001.5502 本篇所使用指令 v-for v-on v-html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&…

vivado产生报告阅读分析23-时序路径特性报告

时序路径特性报告 下图显示了在“ Timing Mode ” &#xff08; 时序模式 &#xff09; 下运行“ Report Design Analysis ” &#xff08; 设计分析报告 &#xff09; 的输出示例 &#xff0c; 其中显示了设计中 10 条最差建立路径的路径特性。在 Vivado IDE 中选中“ Repo…

【教学类-06-12】20231126 (一)二位数 如何让加减乘除题目从小到大排序(以1-20之间加法为例,做正序排列用)

结果展示 优化后 优化前 背景需求&#xff1a; 生成列表 单独抽取显示题目排序方法 存在问题: 我希望 00 01 02……这样排序&#xff0c;但是实际上&#xff0c;除了第一个加数会从小到大排序&#xff0c;第二个被加数的第十位数和个位数都会从小到大排序&#xff0c;也就是…

Blender学习--模型贴图傻瓜级教程

Blender 官方文档 1. Blender快捷键&#xff1a; 快捷键说明 按住鼠标滚轮&#xff1a;移动视角Tab&#xff1a;切换编辑模式和物体模式鼠标右键&#xff1a; 编辑模式&#xff1a; 物体模式&#xff1a; 其他&#xff1a; 2. 下面做一个球体贴一张纹理的操作 2.1 效果如下…

智能优化算法应用:基于粒子群算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于粒子群算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于粒子群算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.粒子群算法4.实验参数设定5.算法结果6.参考文献7.…

C++局域网从服务器获取已连接用户的列表(linux to linux)

目录 服务器端 代码 客户端 代码解析 服务器端 原理 遇到的阻碍以及解决办法 客户端 原理 遇到的阻碍以及解决办法 运行结果截图 总结 服务器端 代码 #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet…

安捷伦E4404B频谱分析仪,100 Hz 至 6.7 GHz

E4404B是安捷伦ESA-E系列频谱分析仪&#xff0c;它是一款能够适应未来发展需求的中高端频谱分析仪解决方案。该系列在频谱分析仪的测量速度、动态范围、精度和功率分辨能力等方面&#xff0c;都为类似价位的产品树立了性能标杆。其灵活的平台设计使得研发、制造和现场服务工程师…

这一款 Mac 系统终端工具,已经用的爱不释手了!

&#x1f525;&#x1f525;&#x1f525;作为程序员或者运维管理人员&#xff0c;我们经常需要使用终端工具来进行服务器管理及各种操作&#xff0c;比如部署项目、调试代码、查看/优化服务、管理服务器等。 相信大家用的最多的终端工具就是 Xshell、iTerm2和Mobaxterm&#…

利用ngrok实现内网穿透(全网最详细教程)

准备工具&#xff1a; 1、phpstudy 用于在本地搭建网站 2、ngrok 用于将自己的本地端口暴露到公网上&#xff0c;从而实现内网穿透 文章开始前给大家分享一个学习人工智能的网站&#xff0c;通俗易懂&#xff0c;风趣幽默 人工智能https://www.captainbed.cn/myon/ ~~~~~…

ESP32和ESP8266的ESP-MESH

ESP32和ESP8266的ESP-MESH 功能介绍一、介绍ESP-MESH二、安装painlessMesh库三、ESP-MESH基本示例&#xff08;广播消息&#xff09;四、示范 功能介绍 了解如何使用ESP-MESH网络协议通过ESP32和ESP8266 NodeMCU板构建网状网络。 ESP-MESH允许多个设备&#xff08;节点&#x…

单例模式与多线程

目录 前言 正文 1.立即加载/饿汉模式 2.延迟加载/懒汉模式 1.延迟加载/懒汉模式解析 2.延迟加载/懒汉模式的缺点 3.延迟加载/懒汉模式的解决方案 &#xff08;1&#xff09;声明 synchronized 关键字 &#xff08;2&#xff09;尝试同步代码块 &#xff08;3&am…