【GoogLeNet】海洋生物识别

这篇具有很好参考价值的文章主要介绍了【GoogLeNet】海洋生物识别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1. 项目准备

1.1. 问题导入

图像分类是根据图像的语义信息将不同类别图像区分开来,是计算机视觉中重要的基本问题。本实践使用卷积神经网络GoogLeNet模型构建深度学习模型,自动提取高质量的特征,来解决海洋鱼类识别的问题。

1.2. 数据集简介

本次实验使用的是台湾电力公司、台湾海洋研究所和垦丁国家公园在2010年10月1日至2013年9月30日期间,在中国台湾南湾海峡、兰屿岛和胡比湖的水下观景台收集的鱼类图像数据集。该数据集包括23类鱼种,共27370张鱼的图像,本次实验将取其中的90%作为训练集,剩下的10%作为测试集。

【GoogLeNet】海洋生物识别

这是数据集的下载链接:Fish4Knowledge 23种鱼类数据集 - AI Studio

2. GoogLeNet模型

GoogLeNet模型是由Google团队在论文中提出的卷积神经网络,是2014年ILSVRC竞赛的冠军模型。相比于AlexNet模型,GoogLeNet模型的网络结构更深,共包括87层。尽管模型结构变得更复杂,但它的参数量仅为AlexNet模型参数量的1/10,这主要归功于它创新性地采用了Inception模块。如下图所示,Inception模块是一种多路并联结构,它能够提取并整合不同视野范围的特征,能极大地提升分类模型的性能。
【GoogLeNet】海洋生物识别

GoogLeNet模型由多个模块串联而成,其网络结构如下图所示。以前的模型是将二维的卷积层输出的特征图直接拉成一维的全连接层输入,而在GoogLeNet模型中,作者在卷积层和全连接层之间插入一个全局平均池化层,直接生成一维的全连接层输入,这样做还能减少模型参数。需要注意的是,原始的GoogLeNet模型包含两个辅助分类器,由于辅助分类器在后续的深度卷积网络演化中并没有被再次使用,故我们去除了这两个辅助分类器。
【GoogLeNet】海洋生物识别


3. 实验步骤

【GoogLeNet】海洋生物识别

3.0. 前期准备

  • 导入模块

注意:本案例仅适用于PaddlePaddle 2.0+版本

import os
import zipfile
import random
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

import paddle
from paddle import nn
from paddle import metric as M
from paddle.io import DataLoader, Dataset
from paddle.nn import functional as F
from paddle.optimizer import Adam
from paddle.optimizer.lr import NaturalExpDecay
  • 设置超参数
BATCH_SIZE = 64      # 每批次的样本数
EPOCHS = 5           # 训练轮数
LOG_GAP = 200        # 输出训练信息的间隔

INIT_LR = 3e-4       # 初始学习率
LR_DECAY = 0.5       # 学习率衰减率

SRC_PATH = "./data/data14492/fish_image23.zip"          # 压缩包路径
DST_PATH = "./data"                                     # 解压路径
DATA_PATH = DST_PATH + "/fish_image"                    # 实验数据集路径
INFER_LIST = [("./work/pm.jpg", "Pomacentrus moluccensis"),
              ("./work/ac.jpg", "Amphiprion clarkii")]  # 预测数据
MODEL_PATH = "GoogLeNet.pdparams"                       # 模型参数保存路径

LAB_DICT = {'fish_1': 'Dascyllus reticulatus', 'fish_2': 'Plectroglyphidodon dickii',
            'fish_3': 'Chromis chrysura', 'fish_4': 'Amphiprion clarkii',
            'fish_5': 'Chaetodon lunulatus', 'fish_6': 'Chaetodon trifascialis',
            'fish_7': 'Myripristis kuntee', 'fish_8': 'Acanthurus nigrofuscus',
            'fish_9': 'Hemigymnus fasciatus', 'fish_10': 'Neoniphon sammara',
            'fish_11': 'Abudefduf vaigiensis', 'fish_12': 'Canthigaster valentini',
            'fish_13': 'Pomacentrus moluccensis', 'fish_14': 'Zebrasoma scopas',
            'fish_15': 'Hemigymnus melapterus', 'fish_16': 'Lutjanus fulvus',
            'fish_17': 'Scolopsis bilineata', 'fish_18': 'Scaridae',
            'fish_19': 'Pempheris vanicolensis', 'fish_20': 'Zanclus cornutus',
            'fish_21': 'Neoglyphidodon nigroris', 'fish_22': 'Balistapus undulatus',
            'fish_23': 'Siganus fuscescens'}     # 用于将文件名和标签相对应

3.1. 数据准备

  • 解压数据集
    由于数据集中的数据是以压缩包的形式存放的,因此我们需要先解压数据压缩包。
if not os.path.isdir(DATA_PATH):
    z = zipfile.ZipFile(SRC_PATH, "r")   # 打开压缩文件,创建zip对象
    z.extractall(path=DST_PATH)          # 解压zip文件至目标路径
    z.close()
print("数据集解压完成!")
  • 划分数据集
    我们需要按1:9比例划分测试集和训练集,分别生成两个包含数据路径和标签映射关系的列表。
type_num, lab_dict = 0, {}          # 方便动物类别在字符型和整型之间转换
train_list, test_list = [], []           # 存放数据的路径及标签的映射关系
file_folders = os.listdir(DATA_PATH)     # 统计数据集下的文件夹

for folder in file_folders:
    lab_dict[str(type_num)] = LAB_DICT[folder]   # 记录标签和数字代号的对应关系
    imgs = os.listdir(os.path.join(DATA_PATH, folder))
    for idx, img in enumerate(imgs):
        path = os.path.join(DATA_PATH, folder, img)
        if idx % 10 == 0:      # 按照1:9的比例划分数据集
            test_list.append([path, type_num])
        else:
            train_list.append([path, type_num])
    type_num += 1
  • 数据预处理
    我们需要对数据集图像进行缩放和归一化处理。
class MyDataset(Dataset):
    ''' 自定义的数据集类 '''
    
    def __init__(self, label_list, transform):
        '''
        * `label_list`: 标签与文件路径的映射列表
        * `transform`:数据处理函数
        '''
        super(MyDataset, self).__init__()
        random.shuffle(label_list)      # 打乱映射列表
        self.label_list = label_list
        self.transform = transform        

    def __getitem__(self, index):
        ''' 根据位序获取对应数据 '''
        img_path, label = self.label_list[index]
        img = self.transform(img_path)
        return img, int(label)

    def __len__(self):
        ''' 获取数据集样本总数 '''
        return len(self.label_list)


def data_mapper(img_path, show=False):
    ''' 图像处理函数 '''
    img = Image.open(img_path)
    if show:     # 展示图像
        display(img)
    # 将其缩放为224*224的高质量图像:
    img = img.resize((224, 224), Image.ANTIALIAS)
    # 把图像变成一个numpy数组以匹配数据馈送格式:
    img = np.array(img).astype("float32")
    # 将图像矩阵由“rgb,rgb,rbg...”转置为“rr...,gg...,bb...”:
    img = img.transpose((2, 0, 1))
    # 将图像数据归一化,并转换成Tensor格式:
    img = paddle.to_tensor(img / 255.0)
    return img
train_dataset = MyDataset(train_list, data_mapper)  # 训练集
test_dataset = MyDataset(test_list, data_mapper)    # 测试集
  • 定义数据提供器
    我们需要分别构建用于训练和测试的数据提供器,其中训练数据提供器是乱序、按批次提供数据的。
train_loader = DataLoader(train_dataset,            # 训练数据集
                          batch_size=BATCH_SIZE,    # 每批读取的样本数
                          num_workers=0,            # 加载数据的子进程个数
                          shuffle=True,             # 打乱训练数据集
                          drop_last=False)          # 不丢弃不完整的样本

test_loader = DataLoader(test_dataset,              # 测试数据集
                         batch_size=BATCH_SIZE,     # 每批读取的样本数
                         num_workers=0,             # 加载数据的子进程个数
                         shuffle=False,             # 不打乱测试数据集
                         drop_last=False)           # 不丢弃不完整的样本

3.2. 网络配置

GoogLeNet模型的网络参数设置如下表所示:
【GoogLeNet】海洋生物识别

class ConvBN2d(nn.Layer):
    ''' Conv2D with BatchNorm2D '''

    def __init__(self, in_channels: int, out_channels: int,
                 kernel_size: int, stride=1, padding=0):
        '''
        * `in_channels`: 输入通道数
        * `out_channels`: 输出通道数
        * `kernel_size`: 卷积核大小
        * `stride`: 卷积运算的步长
        * `padding`: 卷积填充的大小
        '''
        super(ConvBN2d, self).__init__()
        self.net = nn.Sequential(
            nn.Conv2D(in_channels, out_channels, kernel_size, stride, padding),
            nn.BatchNorm2D(out_channels)
        )

    def forward(self, x):
        return self.net(x)
class Inception(nn.Layer):
    ''' Inception v1 in GoogLeNet '''

    def __init__(self, in_channels: int, c1: int, 
                 c2: tuple, c3: tuple, c4: int):
        '''
        * `in_channels`: 输入通道数
        * `c1`: 第1路卷积层的通道参数
        * `c2`: 第2路卷积层的通道参数
        * `c3`: 第3路卷积层的通道参数
        * `c4`: 第4路卷积层的通道参数
        '''
        super(Inception, self).__init__()

        self.conv1 = nn.Sequential(
            ConvBN2d(in_channels, c1, 1, 1, 0),
            nn.ReLU()
        )
        self.conv2 = nn.Sequential(
            ConvBN2d(in_channels, c2[0], 1, 1, 0),
            nn.ReLU(),
            ConvBN2d(c2[0], c2[1], 3, 1, 1),
            nn.ReLU()
        )
        self.conv3 = nn.Sequential(
            ConvBN2d(in_channels, c3[0], 1, 1, 0),
            nn.ReLU(),
            ConvBN2d(c3[0], c3[1], 5, 1, 2),
            nn.ReLU()
        )
        self.conv4 = nn.Sequential(
            nn.MaxPool2D(3, 1, 1),
            ConvBN2d(in_channels, c4, 1, 1, 0),
            nn.ReLU()
        )

    def forward(self, x):
        y1 = self.conv1(x)
        y2 = self.conv2(x)
        y3 = self.conv3(x)
        y4 = self.conv4(x)
        y = paddle.concat([y1, y2, y3, y4], axis=1)  # Depth Concat
        return y
class GoogLeNet(nn.Layer):
    def __init__(self, in_channels=3, n_classes=2):
        '''
        * `in_channels`: 输入的通道数
        * `n_classes`: 输出分类数量
        '''
        super(GoogLeNet, self).__init__()
        # Conv2D(输入通道数,输出通道数,卷积核大小,卷积步长,填充长度)
        # MaxPool2D(池化核大小,池化步长,填充长度)

        self.block1 = nn.Sequential(
            ConvBN2d(in_channels, 64, 7, 2, 3),  # 64*112*112
            nn.ReLU(),
            nn.MaxPool2D(3, 2, 1),             # 64*56*56
        )
        self.block2 = nn.Sequential(
            ConvBN2d(64, 64, 1, 1, 0),           # 64*56*56
            nn.ReLU(),
            ConvBN2d(64, 192, 3, 1, 1),          # 192*56*56
            nn.ReLU(),
            nn.MaxPool2D(3, 2, 1),             # 192*28*28
        )
        self.block3 = nn.Sequential(
            Inception(192, 64, (96, 128), (16, 32), 32),      # 3a:256*28*28
            Inception(256, 128, (128, 192), (32, 96), 64),    # 3b:480*28*28
            nn.MaxPool2D(3, 2, 1),             # 480*14*14
        )
        self.block4 = nn.Sequential(
            Inception(480, 192, (96, 208), (16, 48), 64),     # 4a:512*14*14
            Inception(512, 160, (112, 224), (24, 64), 64),    # 4b:512*14*14
            Inception(512, 128, (128, 256), (24, 64), 64),    # 4c:512*14*14
            Inception(512, 112, (144, 288), (32, 64), 64),    # 4d:528*14*14
            Inception(528, 256, (160, 320), (32, 128), 128),  # 4e:832*14*14
            nn.MaxPool2D(3, 2, 1),             # 832*7*7
        )
        self.block5 = nn.Sequential(
            Inception(832, 256, (160, 320), (32, 128), 128),  # 5a:832*7*7
            Inception(832, 384, (192, 384), (48, 128), 128),  # 5b:1024*7*7
            nn.AdaptiveAvgPool2D(1),           # 1024*1*1
        )
        self.block6 = nn.Sequential(
            nn.Flatten(1, -1),                 # 1024
            nn.Dropout(p=0.4),
            nn.Linear(1024, n_classes),        # n_classes
        )

    def forward(self, x):
        x = self.block1(x)
        x = self.block2(x)
        x = self.block3(x)
        x = self.block4(x)
        x = self.block5(x)
        y = self.block6(x)
        return y
  • 实例化模型
model = GoogLeNet(in_channels=3, n_classes=type_num)

3.3. 模型训练

model.train()                # 开启训练模式
scheduler = NaturalExpDecay(
    learning_rate=INIT_LR,
    gamma=LR_DECAY
)                            # 定义学习率衰减器
optimizer = Adam(
    learning_rate=scheduler,
    parameters=model.parameters()
)                            # 定义Adam优化器
loss_arr, acc_arr = [], []   # 用于可视化

for ep in range(EPOCHS):
    for batch_id, data in enumerate(train_loader()):
        x_data, y_data = data
        y_data = y_data[:, np.newaxis]          # 增加一维维度
        y_pred = model(x_data)                  # 预测结果
        acc = M.accuracy(y_pred, y_data)        # 计算准确率
        loss = F.cross_entropy(y_pred, y_data)  # 计算交叉熵
        if batch_id % LOG_GAP == 0:   # 定期输出训练结果
            print("Epoch:%d,Batch:%3d,Loss:%.5f,Acc:%.5f"\
                % (ep, batch_id, loss, acc))
        acc_arr.append(acc.item())
        loss_arr.append(loss.item())
        optimizer.clear_grad()
        loss.backward()
        optimizer.step()
    scheduler.step()       # 每轮衰减一次学习率

paddle.save(model.state_dict(), MODEL_PATH)  # 保存训练好的模型

模型训练的结果如下:

Epoch:0,Batch:  0,Loss:3.50096,Acc:0.09375
Epoch:0,Batch:200,Loss:0.41797,Acc:0.90625
Epoch:1,Batch:  0,Loss:0.33822,Acc:0.89062
Epoch:1,Batch:200,Loss:0.04866,Acc:0.98438
Epoch:2,Batch:  0,Loss:0.04856,Acc:0.98438
Epoch:2,Batch:200,Loss:0.15580,Acc:0.96875
Epoch:3,Batch:  0,Loss:0.04368,Acc:0.98438
Epoch:3,Batch:200,Loss:0.03558,Acc:0.98438
Epoch:4,Batch:  0,Loss:0.00756,Acc:1.00000
Epoch:4,Batch:200,Loss:0.00995,Acc:1.00000
  • 可视化训练过程
fig = plt.figure(figsize=[10, 8])

# 训练误差图像:
ax1 = fig.add_subplot(211, facecolor="#E8E8F8")
ax1.set_ylabel("Loss", fontsize=18)
plt.tick_params(labelsize=14)
ax1.plot(range(len(loss_arr)), loss_arr, color="orangered")
ax1.grid(linewidth=1.5, color="white")  # 显示网格

# 训练准确率图像:
ax2 = fig.add_subplot(212, facecolor="#E8E8F8")
ax2.set_xlabel("Training Steps", fontsize=18)
ax2.set_ylabel("Accuracy", fontsize=18)
plt.tick_params(labelsize=14)
ax2.plot(range(len(acc_arr)), acc_arr, color="dodgerblue")
ax2.grid(linewidth=1.5, color="white")  # 显示网格

fig.tight_layout()
plt.show()
plt.close()

【GoogLeNet】海洋生物识别

3.4. 模型评估

model.eval()                 # 开启评估模式
test_costs, test_accs = [], []

for batch_id, data in enumerate(test_loader()):
    x_data, y_data = data
    y_data = y_data[:, np.newaxis]          # 增加一维维度
    y_pred = model(x_data)                  # 预测结果
    acc = M.accuracy(y_pred, y_data)        # 计算准确率
    loss = F.cross_entropy(y_pred, y_data)  # 计算交叉熵
    test_accs.append(acc.item())
    test_costs.append(loss.item())
test_loss = np.mean(test_costs)    # 每轮测试的平均误差
test_acc = np.mean(test_accs)      # 每轮测试的平均准确率
print("Eval \t Loss:%.5f,Acc:%.5f" % (test_loss, test_acc))

模型评估的结果如下:

Eval 	 Loss:0.04160,Acc:0.99019

3.5. 模型预测

model.eval()                 # 开启评估模式
model.set_state_dict(
    paddle.load(MODEL_PATH)
)   # 载入预训练模型参数

for idx, (img_path, truth_lab) in enumerate(INFER_LIST):
    image = data_mapper(img_path, show=True)        # 获取预测图片
    result = model(image[np.newaxis, :, :, :])
    infer_lab = lab_dict[str(np.argmax(result))]    # 获取推理结果
    print("图%d的真实标签:%s,预测结果:%s" % (idx+1, truth_lab, infer_lab))

模型预测的结果如下:

【GoogLeNet】海洋生物识别

图1的真实标签:Pomacentrus moluccensis,预测结果:Pomacentrus moluccensis

【GoogLeNet】海洋生物识别文章来源地址https://www.toymoban.com/news/detail-490482.html

图2的真实标签:Amphiprion clarkii,预测结果:Amphiprion clarkii

写在最后

  • 如果您发现项目存在问题,或者如果您有更好的建议,欢迎在下方评论区中留言讨论~
  • 这是本项目的链接:实验项目 - AI Studio,点击fork可直接在AI Studio运行~
  • 这是我的个人主页:个人主页 - AI Studio,来AI Studio互粉吧,等你哦~
  • 【友链滴滴】欢迎大家随时访问我的个人博客~

到了这里,关于【GoogLeNet】海洋生物识别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《生物识别技术:面对安全挑战的绝佳选择?》

    随着科技的不断发展,安全问题日益凸显,传统的密码学和身份验证方式已经不能满足对安全性和便利性的需求。在这个背景下,生物识别技术作为一种新兴的安全措施备受关注。但生物识别技术是否能够成为应对安全挑战的绝佳选择呢?让我们来探讨一下。 生物识别技术是

    2024年03月17日
    浏览(33)
  • 生物识别:即使用生物特征来标识用户身份,能够提供额外的安全保障。例如,指纹和虹膜技术。

    作者:禅与计算机程序设计艺术 生物识别(Biometric Identification)也称为生物特征识别(Biometric Fingerprinting),是利用生物特征进行身份认证的一项重要技术。通过对生物特征的比对,可以确定一个人的身份。生物识别已广泛应用于企业、金融、政府、法律等领域,能够提高个

    2024年02月03日
    浏览(43)
  • 面部识别技术VS其他生物识别技术:哪种更安全、更准确、更可靠?

           面部识别技术是一种生物识别技术,通过分析人脸特征,识别和验证个体身份。与其他生物识别技术相比,面部识别技术具有一些独特的优点和局限性。下面将从技术原理、应用场景、准确性、安全性、可用性等方面,对面部识别技术与其他生物识别方法进行比较。

    2024年02月16日
    浏览(43)
  • AI助力林业有害生物防治,基于YOLOv5开发构建林业有害生物检测识别系统

    林业有害生物防治是指针对危害森林健康的昆虫、病原菌、杂草等有害生物进行预防和控制的活动。这些有害生物可能会导致树木的衰弱、死亡,破坏森林生态系统的平衡,影响木材产量和质量,甚至对人类社会造成经济和环境损失。 以下是一些常见的林业有害生物防治方法

    2024年02月12日
    浏览(33)
  • 生物识别技术是否可以成为应对安全挑战的最佳选择?

    随着科技的快速发展,人们对于个人信息安全和物质财富保护的需求越来越高。同时,在恐怖主义和犯罪活动日益增多的当下,各国政府也在积极探索新的安全保障手段。生物识别技术应运而生,其能够通过人体生理特征或行为模式进行身份验证,受到了广泛关注。但是,生

    2024年02月05日
    浏览(28)
  • 2023身份识别技术大会 | 安全证件 | 数字认证 | 生物识别 | 公共安全安防身份技术展览会

    展会名称:  2023身份识别技术大会 | 安全证件 | 数字认证 | 生物识别 | 公共安全安防身份技术展览会 举办时间: 2023年5月17-18日 举办地点:  北京 国家会议中心 指导单位:  公安部科技信息化局 主办单位:  多维身份识别与可信认证技术国家工程研究中心 中国国际科技促

    2024年02月07日
    浏览(40)
  • 大模型时代下的“金融业生物识别安全挑战”机遇

    作者:中关村科金 AI 安全攻防实验室 冯月 金融行业正在面临着前所未有的安全挑战,人脸安全事件频发,国家高度重视并提出警告,全行业每年黑产欺诈涉及资金额超过1100亿元。冰山上是安全事件,冰山下隐藏的是“裸奔”的技术防御系统,快速发展的生成式算法平均每

    2024年04月23日
    浏览(24)
  • 微软官方Windows_Hello生物识别驱动设计指南

    如题,微软官方Windows_Hello生物识别驱动设计指南(2022版) 资源下载链接: 微软官方Windows_Hello生物识别驱动设计指南-WindowsServer文档类资源-CSDN下载 本文介绍了如何编写适用于 Windows 生物识别驱动程序接口 (WBDI) 的用户模式驱动程序。 WBDI 是Windows 生物识别框架 (WBF) 的驱动程

    2024年02月05日
    浏览(30)
  • 自主系统的生物识别与身份验证:实现安全与私密性

    生物识别和身份验证技术在过去的几年里发生了巨大的变化。随着人工智能、大数据和云计算技术的发展,生物识别技术已经成为了一种可靠、高效的身份验证方法。这篇文章将涵盖生物识别技术的背景、核心概念、算法原理、实际应用以及未来发展趋势。 生物识别技术的发

    2024年02月22日
    浏览(31)
  • 【前沿技术】非侵入式生物识别安全与区块链的集成方式

    发表时间:2022年7月15日 信息来源:bsvblockchain.org 在科幻小说和我们展望未来的蓝本中,都预测了一种数字经济的出现。在这种数字经济中,关于我们的身份以及财产的方方面面信息都会被写入微型芯片并植入人体。 难道想要容身于无缝数字经济、智慧城市,必须进行人体改

    2024年02月06日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包