T7:咖啡豆识别

2024-09-07 09:52
文章标签 识别 t7 咖啡豆

本文主要是介绍T7:咖啡豆识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

T7:咖啡豆识别

      • **一、前期工作**
        • 1.设置GPU,导入库
        • 2.导入数据
        • 3.查看数据
      • **二、数据预处理**
        • 1.加载数据
        • 2.可视化数据
        • 3.配置数据集
      • **三、构建CNN网络模型**
        • 1、手动搭建
        • 2、直接调用官方模型
      • **四、编译模型**
      • **五、训练模型**
      • **六、模型评估**
      • **七、预测**
        • 八、暂时总结

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊
  • 时间:9月4日-9月x日

🍺 要求:

  1. 自己搭建VGG-16网络框架 ✅
  2. 调用官方的VGG-16网络框架 ✅

🍻 拔高(可选):

  1. 验证集准确率达到100% ❌
  2. 使用PPT画出VGG-16算法框架图(发论文需要这项技能)❌

🔎 探索(难度有点大)

  1. 在不影响准确率的前提下轻量化模型❌
  • VGG16总参数量是134,276,942

由于本人没GPU算力了,所以代码跑贼慢,结果后补

⛽ 我的环境

  • 语言环境:Python3.10.12
  • 编译器:Google Colab
  • 深度学习环境:
    • TensorFlow2.17.0

⛽ 参考学习博客汇总(暂时):

  • ResNet、VGGNet和AlexNet创新点及优缺点

一、前期工作

1.设置GPU,导入库
#os提供了一些与操作系统交互的功能,比如文件和目录操作
import os
#提供图像处理的功能,包括打开和显示、保存、裁剪等
import PIL
from PIL import Image
#pathlib提供了一个面向对象的接口来处理文件系统路径。路径被表示为Path对象,可以调用方法来进行各种文件和目录操作。
import pathlib#用于绘制图形和可视化数据
import tensorflow as tf
import matplotlib.pyplot as plt
#用于数值计算的库,提供支持多维数组和矩阵运算
import numpy as np
#keras作为高层神经网络API,已被集成进tensorflow,使得训练更方便简单
from tensorflow import keras
#layers提供了神经网络的基本构建块,比如全连接层、卷积层、池化层等
#提供了构建和训练神经网络模型的功能,包括顺序模型(Sequential)和函数式模型(Functional API)
from tensorflow.keras import layers, models
#导入两个重要的回调函数:前者用于训练期间保存模型最佳版本;后者监测到模型性能不再提升时提前停止训练,避免过拟合
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
tf.__version__
'2.17.0'

由于本人没有GPU了,该部分跳过↓

# 获取所有可用的GPU设备列表,储存在变量gpus中
gpus = tf.config.list_physical_devices("GPU")# 如果有GPU,即列表不为空
if gpus:# 获取第一个 GPU 设备gpu0 = gpus[0]# 设置 GPU 内存增长策略。开启这个选项可以让tf按需分配gpu内存,而不是一次性分配所有可用内存。tf.config.experimental.set_memory_growth(gpu0, True)#设置tf只使用指定的gpu(gpu[0])tf.config.set_visible_devices([gpu0],"GPU")gpus
2.导入数据
from google.colab import drive
drive.mount("/content/drive/")
%cd "/content/drive/MyDrive/Colab Notebooks/jupyter notebook/data"
Mounted at /content/drive/
/content/drive/MyDrive/Colab Notebooks/jupyter notebook/data
data_dir = "./7"
data_dir = pathlib.Path(data_dir)
3.查看数据
# 使用glob方法获取当前目录的子目录里所有以'.png'为结尾的文件
# '*/*.jpg' 是一個通配符模式
# 第一个星号表示当前目录
# 第二个星号表示子目录
image_count = len (list(data_dir.glob("*/*.png")))print("图片总数:", image_count)
图片总数: 1200
ex = list(data_dir.glob("Green/*.png"))
image=PIL.Image.open(str(ex[8]))
#查看图像属性
print(image.format, image.size,image.mode)
plt.axis("off")
plt.imshow(image)
plt.show()
PNG (224, 224) RGB

在这里插入图片描述

二、数据预处理

1.加载数据
#设置批量大小,即每次训练模型时输入图像数量
#每次训练迭代时,模型需处理32张图像
batch_size = 32
#图像的高度,加载图像数据时,将所有的图像调整为相同的高度
img_height = 224
#图像的宽度,加载图像数据时,将所有的图像调整为相同的宽度
img_width = 224
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
tr_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,#指定数据集中分割出多少比例数据当作验证集,0.1表示10%数据会被用来当验证集subset="training",#指定是用于训练还是验证的数据子集,这里设定为trainingseed=123,#用于设置随机数种子,以确保数据集划分的可重复性和一致性image_size=(img_height, img_width),batch_size=batch_size)
Found 1200 files belonging to 4 classes.
Using 960 files for training.
val_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split = 0.2,subset = "validation",seed = 123,image_size=(img_height,img_width),batch_size=batch_size
)
Found 1200 files belonging to 4 classes.
Using 240 files for validation.
class_names = tr_ds.class_names
# 可以通过class_names输出数据集的标签。标签将按字母顺序对应于目录名称
class_names
['Dark', 'Green', 'Light', 'Medium']
# #数据增强---参考博客:https://blog.csdn.net/afive54/article/details/135004174# def augment_images(image, label):
#     image = tf.image.random_flip_up_down(image)  # 随机水平翻转
#     image = tf.image.random_flip_left_right(image)
#     image = tf.image.random_contrast(image, lower=0.1, upper=1.2)  # 随机对比度
#     image = tf.image.random_brightness(image, max_delta=0.2)  # 随机亮度
#     image = tf.image.random_saturation(image, lower=0.1, upper=1.2)  # 随机饱和度
#     #noise = tf.random.normal(tf.shape(image), mean=0.0, stddev=0.1)
#     #image = tf.clip_by_value(image, 0.0, 0.5)  # 添加高斯噪声并将像素值限制在0到1之间
#     return image, label
# # 对训练集数据进行增强
# augmented_tr_ds = tr_ds.map(augment_images)
2.可视化数据
plt.figure(figsize=(10, 4))  # 图形的宽为10高为5for images, labels in tr_ds.take(1):for i in range(10):ax = plt.subplot(2, 5, i + 1)plt.imshow(images[i].numpy().astype("uint8"))plt.title(class_names[labels[i]])plt.axis("off")

在这里插入图片描述

for image_batch, labels_batch in tr_ds:print(image_batch.shape)print(labels_batch.shape)break#`(32, 224, 224, 3)`--最后一维指的是彩色通道RGB
#`label_batch`是形状(32,)的张量
(32, 224, 224, 3)
(32,)
3.配置数据集
#自动调整数据管道性能
AUTOTUNE = tf.data.AUTOTUNE
# 使用 tf.data.AUTOTUNE 具体的好处包括:
#自动调整并行度:自动决定并行处理数据的最佳线程数,以最大化数据吞吐量。
#减少等待时间:通过优化数据加载和预处理,减少模型训练时等待数据的时间。
#提升性能:自动优化数据管道的各个环节,使整个训练过程更高效。
#简化代码:不需要手动调整参数,代码更简洁且易于维护。#使用cache()方法将训练集缓存到内存中,这样加快数据加载速度
#当多次迭代训练数据时,可以重复使用已经加载到内存的数据而不必重新从磁盘加载
#使用shuffle()对训练数据集进行洗牌操作,打乱数据集中的样本顺序
#参数1000指缓冲区大小,即每次从数据集中随机选择的样本数量
#prefetch()预取数据,节约在训练过程中数据加载时间tr_ds = tr_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds  = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
normalization_layer = layers.Rescaling(1./255)tr_ds = tr_ds.map(lambda x, y: (normalization_layer(x), y))
val_ds  = val_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(val_ds))
first_image = image_batch[0]# 查看归一化后的数据,将每张图片的像素归一至0-1间的数值
print(np.min(first_image), np.max(first_image))
0.0 1.0

三、构建CNN网络模型

[引1]- VGGNet (Visual Geometry Group Network):

创新:VGGNet的创新在于采用了相对简单的卷积层堆叠的结构,其中使用了多个小卷积核(3*3)来替代较大的卷积核。这种结构使网络更深,同时参数共享更多,有助于提取丰富的特征。

  • 优点:
  • 相对简单而易于理解的网络结构。
  • 良好的性能在图像分类任务中得到了验证。
  • 网络结构可提取更丰富的特征信息
  • 缺点:
  • 参数量较大,网络结构比较深,需要消耗大量计算资源和时间来训练。
  • 网络结构比较复杂,容易出现梯度消失或爆炸等问题
  • 相对于一些后续的模型,不够高效。

网络结构如下图:

在这里插入图片描述

1、手动搭建
from tensorflow.keras import layers, models, Input
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
#functional model的搭建模式,之前是sequential
def VGG16(nb_classes, input_shape):input_tensor = Input(shape=input_shape)# 1st blockx = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv1')(input_tensor)x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block1_pool')(x)# 2nd blockx = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv1')(x)x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block2_pool')(x)# 3rd blockx = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv1')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv2')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block3_pool')(x)# 4th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block4_pool')(x)# 5th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block5_pool')(x)# full connectionx = Flatten()(x)x = Dense(4096, activation='relu',  name='fc1')(x)x = Dense(4096, activation='relu', name='fc2')(x)predictions = Dense(nb_classes, activation='softmax', name='predictions')(x)model = Model(inputs=input_tensor, outputs=predictions)return modelmodel = VGG16(len(class_names), (img_width, img_height, 3))
model.summary()
Model: "functional"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type)                         ┃ Output Shape                ┃         Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ input_layer (InputLayer)             │ (None, 224, 224, 3)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block1_conv1 (Conv2D)                │ (None, 224, 224, 64)        │           1,792 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block1_conv2 (Conv2D)                │ (None, 224, 224, 64)        │          36,928 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block1_pool (MaxPooling2D)           │ (None, 112, 112, 64)        │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block2_conv1 (Conv2D)                │ (None, 112, 112, 128)       │          73,856 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block2_conv2 (Conv2D)                │ (None, 112, 112, 128)       │         147,584 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block2_pool (MaxPooling2D)           │ (None, 56, 56, 128)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block3_conv1 (Conv2D)                │ (None, 56, 56, 256)         │         295,168 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block3_conv2 (Conv2D)                │ (None, 56, 56, 256)         │         590,080 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block3_conv3 (Conv2D)                │ (None, 56, 56, 256)         │         590,080 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block3_pool (MaxPooling2D)           │ (None, 28, 28, 256)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block4_conv1 (Conv2D)                │ (None, 28, 28, 512)         │       1,180,160 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block4_conv2 (Conv2D)                │ (None, 28, 28, 512)         │       2,359,808 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block4_conv3 (Conv2D)                │ (None, 28, 28, 512)         │       2,359,808 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block4_pool (MaxPooling2D)           │ (None, 14, 14, 512)         │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block5_conv1 (Conv2D)                │ (None, 14, 14, 512)         │       2,359,808 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block5_conv2 (Conv2D)                │ (None, 14, 14, 512)         │       2,359,808 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block5_conv3 (Conv2D)                │ (None, 14, 14, 512)         │       2,359,808 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ block5_pool (MaxPooling2D)           │ (None, 7, 7, 512)           │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ flatten (Flatten)                    │ (None, 25088)               │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ fc1 (Dense)                          │ (None, 4096)                │     102,764,544 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ fc2 (Dense)                          │ (None, 4096)                │      16,781,312 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ predictions (Dense)                  │ (None, 4)                   │          16,388 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
 Total params: 134,276,932 (512.23 MB)
 Trainable params: 134,276,932 (512.23 MB)
 Non-trainable params: 0 (0.00 B)
2、直接调用官方模型
#调用-去除顶层自定义全连接层,加imagenet权重参数,冻结conv,加BN和dropout
from tensorflow.keras.applications import VGG16# 加载VGG16模型,不包括全连接层,使用ImageNet的权重
base_model = VGG16(weights="imagenet",include_top=False,input_shape=(img_height, img_width, 3),pooling = "max")# 冻结VGG16的卷积层,不进行训练
# base_model.trainable = False#部分解冻?
# 冻结直到某一层的所有层
#仅微调卷积基的最后的两三层
base_model.trainable = Trueset_trainable = False
for layer in base_model.layers[:-2]:if layer.name == 'block5_conv1':set_trainable = Trueif set_trainable:layer.trainable = Trueprint(layer)else:set_trainable = Falselayer.trainable = False
print(base_model.summary(),end="\n")# 在VGG16基础上添加自定义的全连接层
model = models.Sequential([base_model,#layers.GlobalAveragePooling2D(),#layers.GlobalMaxPooling2D(),layers.Flatten(),layers.Dense(1024, activation="relu"),layers.BatchNormalization(),layers.Dropout(0.4),layers.Dense(128, activation= "relu"),layers.BatchNormalization(),layers.Dropout(0.4),layers.Dense(len(class_names), activation="softmax")
])# 打印网络结构
model.summary()# model.load_weights("/content/drive/Othercomputers/My laptop/jupyter notebook/xunlianying/vgg16_1_final.weights.h5")

四、编译模型

在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:

  • 损失函数(loss):用于衡量模型在训练期间的准确率。
  • 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
  • 指标(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。
#本次使用代码
# 设置初始学习率
initial_learning_rate = 1e-4lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate,decay_steps=30,decay_rate=0.92,staircase=True)# 将指数衰减学习率送入优化器
optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)model.compile(optimizer=optimizer,loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),metrics=['accuracy'])#Adam优化器是一种常用的梯度下降优化算法,用于更新模型的权重以最小化训练过程中的损失函数
#由于是多分类问题这里使用categorical crossentropy损失函数

五、训练模型

epochs = 20# 保存最佳模型参数
checkpointer = ModelCheckpoint("/content/drive/My Drive/Colab Notebooks/jupyter notebook/xunlianying/T7_shou1.weights.h5",monitor='val_accuracy',verbose=1,mode = "max",save_best_only=True,save_weights_only=True)# 设置早停
earlystopper = EarlyStopping(monitor='val_accuracy',min_delta=0.0001,patience=5,mode = "max",verbose=1)
history = model.fit(tr_ds,validation_data=val_ds,epochs=epochs,callbacks=[checkpointer, earlystopper])

在这里插入图片描述训练过程。。。。漫长。。。。

六、模型评估

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.load_weights("/content/drive/My Drive/Colab Notebooks/jupyter notebook/xunlianying/T7_shou1.weights.h5")
from PIL import Imageimport numpy as npimg = Image.open("/content/drive/MyDrive/Colab Notebooks/jupyter notebook/data/7/Dark/dark (133).png")  #这里选择你需要预测的图片
image = tf.image.resize(img, [img_height, img_width])img_array = tf.expand_dims(image, 0)predictions = model.predict(img_array) # 这里选用你已经训练好的模型
print("预测结果为:",class_names[np.argmax(predictions)])
八、暂时总结
  • 由于没有GPU算力嘞,cpu跑得一天。。。慢慢来吧,最近也好忙,慢慢学,抽空去补点基础知识了。。。
  • 后续模型调整再跑什么的感觉得好久了。。。(每次调整优化其实也很耗时)

这篇关于T7:咖啡豆识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1144738

相关文章

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

Clion不识别C代码或者无法跳转C语言项目怎么办?

如果是中文会显示: 此时只需要右击项目,或者你的源代码目录,将这个项目或者源码目录标记为项目源和头文件即可。 英文如下:

BERN2(生物医学领域)命名实体识别与命名规范化工具

BERN2: an advanced neural biomedical named entity recognition and normalization tool 《Bioinformatics》2022 1 摘要 NER和NEN:在生物医学自然语言处理中,NER和NEN是关键任务,它们使得从生物医学文献中自动提取实体(如疾病和药物)成为可能。 BERN2:BERN2是一个工具,

行为智能识别摄像机

行为智能识别摄像机 是一种结合了人工智能技术和监控摄像技术的先进设备,它能够通过深度学习算法对监控画面进行实时分析,自动识别和分析监控画面中的各种行为动作。这种摄像机在安防领域有着广泛的应用,可以帮助监控人员及时发现异常行为,并采取相应的措施。 行为智能识别摄像机可以有效预防盗窃事件。在商场、超市等公共场所安装这种摄像机,可以通过识别异常行为等情况,及时报警并阻止不安全行为的发生

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题 GitHub Pages是一个直接从GitHub存储库托管的静态站点服务,‌它允许用户通过简单的配置,‌将个人的代码项目转化为一个可以在线访问的网站。‌这里使用flutter build web来构建web发布到GitHub Pages。 最近通过flutter build web,通过发布到GitHu

T1打卡——mnist手写数字识别

🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 1.定义GPU import tensorflow as tfgpus=tf.config.list_physical_devices("GPU")if gpus:gpu0=gpus[0]tf.config.experimental.set_memort_groth(gpu0,True) #设置GPU现存用量按需

使用 VisionTransformer(VIT) FineTune 训练驾驶员行为状态识别模型

一、VisionTransformer(VIT) 介绍 大模型已经成为人工智能领域的热门话题。在这股热潮中,大模型的核心结构 Transformer 也再次脱颖而出证明了其强大的能力和广泛的应用前景。Transformer 自 2017年由Google提出以来,便在NLP领域掀起了一场革命。相较于传统的循环神经网络(RNN)和长短时记忆网络(LSTM), Transformer 凭借自注意力机制

mysql无法启动以及cmd下mysql命令无法识别的

1.mysql无法启动 解决方式: Win+R,输入services.msc,找到mysql服务 即默认的服务名是mysql55而不是mysql 2.mysql命令无法识别 直接输入mysql进入数据库报错 这是因为系统并不知道mysql是什么,我们需要在环境变量里添加mysql的安装地址中的bin目录地址。 C:\Program Files\My

Selenium 实现图片验证码识别

前言 在测试过程中,有的时候登录需要输入图片验证码。这时候使用Selenium进行自动化测试,怎么做图片验证码识别?本篇内容主要介绍使用Selenium、BufferedImage、Tesseract进行图片 验证码识别。 环境准备 jdk:1.8 tessdata:文章末尾附下载地址 安装Tesseract 我本地是ubuntu系统 sudo apt install tesserac

【DL--22】实现神经网络算法NeuralNetwork以及手写数字识别

1.NeuralNetwork.py #coding:utf-8import numpy as np#定义双曲函数和他们的导数def tanh(x):return np.tanh(x)def tanh_deriv(x):return 1.0 - np.tanh(x)**2def logistic(x):return 1/(1 + np.exp(-x))def logistic_derivati