深度学习 海洋识别

编程入门 行业动态 更新时间:2024-10-25 00:31:38

<a href=https://www.elefans.com/category/jswz/34/1769690.html style=深度学习 海洋识别"/>

深度学习 海洋识别

 1. 前言

       近几十年来,海洋生物多样性的成像技术飞速进步。由于海洋生态的特殊性及复杂性,大量的图像或视频无法全部由人工处理,迫切需要识别相关内容。所以,建立健全完善、分布广泛的识别技术是长久以来研究者们关注的问题。这种识别技术可以提供充足的有效信息与变量,并且能准确识别所观测物种的生态动态。   

1. 问题导入

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

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

2. 神经网络GoogLeNet模型

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

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

3.实验步骤

前期导入

!pip install -U paddlepaddle-gpu==1.7.1-post97  -i  

       这段代码是用pip命令在Python环境里安装PaddlePaddle深度学习框架的GPU版本1.7.1-post97。其中`-U`参数表示升级安装,如果之前已经安装了其他版本,会更新到最新版本。`-i`参数指定使用百度的PyPI镜像服务器下载安装包,加速下载速度。

#使用 zipfile 模块处理压缩文件相关的操作。
#使用 os 模块处理文件和目录相关的操作。
#使用 random 模块生成随机数。
#使用 paddle 模块进行深度学习相关的操作。
#使用 matplotlib.pyplot 模块进行图像的显示和绘制。
#使用 paddle.fluid.dygraph 模块进行动态图模型的构建和训练。
#使用 sys 模块获取系统相关信息。
#使用 numpy 模块进行数值计算。
#使用 PIL.Image 模块进行图像处理。
#使用 PIL.ImageEnhance 模块进行图像增强。
#使用 paddle.fluid 模块进行深度学习框架相关操作。
#使用 multiprocessing 模块进行多进程相关操作。
#使用 json 模块处理 JSON 格式的数据。
#导入必要的包
import zipfile
import os
import random
import paddle
import matplotlib.pyplot as plt
from paddle.fluid.dygraph import Pool2D,Conv2D,BatchNorm
from paddle.fluid.dygraph import Linear
import sys
import numpy as np
from PIL import Image
from PIL import ImageEnhance
import paddle.fluid as fluid
from multiprocessing import cpu_count
import matplotlib.pyplot as plt
import json 

    通过import语句导入了需要使用的库和模块,包括 zipfile、os、random、paddle、matplotlib.pyplot、paddle.fluid.dygraph、sys、numpy、PIL.Image、PIL.ImageEnhance、paddle.fluid 和 multiprocessing。

然后,可以根据需要使用这些库和模块进行图像数据处理、模型的构建和训练等操作。

 数据准备

#解压原始数据集,将fish_image.zip解压至data目录下
src_path="/home/aistudio/data/data14492/fish_image23.zip"
target_path="/home/aistudio/data/fish_image"
if(not os.path.isdir(target_path)):z = zipfile.ZipFile(src_path, 'r')z.extractall(path=target_path)z.close()

           这段代码将压缩文件 `fish_image.zip` 解压到目标路径 `/home/aistudio/data/fish_image` 下。

首先,定义了变量 `src_path` 和 `target_path`,分别表示压缩文件的路径和目标路径。然后通过 `os.path.isdir` 方法判断目标路径是否存在,如果不存在则执行解压操作。

使用 `zipfile` 模块打开压缩文件,然后调用 `extractall` 方法将文件解压到目标路径下,并关闭压缩文件。最终将解压操作后的文件存放在 `/home/aistudio/data/fish_image` 路径中。

#存放所有类别的信息
class_detail = []
#获取所有类别保存的文件夹名称
class_dirs = os.listdir(target_path+"/fish_image")data_list_path="/home/aistudio/data/"TRAIN_LIST_PATH=data_list_path + "train.txt"
EVAL_LIST_PATH=data_list_path + "eval.txt"#每次执行代码,首先清空train.txt和eval.txt
with open(TRAIN_LIST_PATH, 'w') as f: pass
with open(EVAL_LIST_PATH, 'w') as f: pass

       首先,定义了空列表 class_detail,用于存放所有类别的信息。然后使用 os.listdir 方法获取 fish_image 目录下所有子目录的名称,并将名称列表保存到 class_dirs 变量中。

        然后,定义了两个文件路径常量,分别表示训练清单和验证清单的路径。接着,使用 with open 语句打开这两个文件,并使用 pass 语句占位,清空这两个文件的内容。这样保证每次重

新运行代码时,训练和验证清单都是最新的。

 设置参数

#总的图像数量
all_class_images = 0
#存放类别标签
class_label=0
# 设置要生成文件的路径
data_root_path="/home/aistudio/data/fish_image/fish_image"
#存储要写进test.txt和train.txt中的内容
trainer_list=[]
eval_list=[]
#读取每个类别,['fish_01', 'fish_02', 'fish_03']
for class_dir in class_dirs:   #每个类别的信息class_detail_list = {}eval_sum = 0trainer_sum = 0#统计每个类别有多少张图片class_sum = 0#获取类别路径 path = data_root_path + "/" + class_dir# 获取所有图片img_paths = os.listdir(path)for img_path in img_paths:                                  # 遍历文件夹下的每个图片name_path = path + '/' + img_path                       # 每张图片的路径if class_sum % 10 == 0:                                 # 每10张图片取一个做验证数据eval_sum += 1                                       # test_sum为测试数据的数目eval_list.append(name_path + "\t%d" % class_label + "\n")else:trainer_sum += 1 trainer_list.append(name_path + "\t%d" % class_label + "\n")#trainer_sum测试数据的数目class_sum += 1                                          #每类图片的数目all_class_images += 1                                   #所有类图片的数目class_label += 1  # 说明的json文件的class_detail数据class_detail_list['class_name'] = class_dir             #类别名称,如jiangwenclass_detail_list['class_label'] = class_label          #类别标签class_detail_list['class_eval_images'] = eval_sum       #该类数据的测试集数目class_detail_list['class_trainer_images'] = trainer_sum #该类数据的训练集数目class_detail.append(class_detail_list)         random.shuffle(eval_list)
with open(data_list_path + "eval.txt", 'a') as f:for eval_image in eval_list:f.write(eval_image) random.shuffle(trainer_list)
with open(data_list_path + "train.txt", 'a') as f2:for train_image in trainer_list:f2.write(train_image) # 说明的json文件信息
readjson = {}
readjson['all_class_name'] = data_root_path                  #文件父目录
readjson['all_class_sum'] = class_sum 
readjson['all_class_images'] = all_class_images
readjson['class_detail'] = class_detail
jsons = json.dumps(readjson, sort_keys=True, indent=4, separators=(',', ': '))
with open(data_list_path + "readme.json",'w') as f:f.write(jsons)
print ('生成数据列表完成!')

        这段代码的作用是生成训练和测试数据的列表文件以及元数据文件。

代码首先设置了一些变量,如总图像数量(all_class_images)、类别标签(class_label)和数据的根目录路径(data_root_path)。

然后,代码遍历每个类别的文件夹,统计每个类别中的图片数量,并将图片路径和对应的标签添加到训练列表(trainer_list)和测试列表(eval_list)中。同时,class_detail_list字典记录了每个类别的名称、标签、测试集数目和训练集数目,最后将这个字典添加到class_detail列表中。

           接着,通过随机打乱eval_list和trainer_list两个列表的顺序,并将它们分别写入eval.txt和train.txt文件中。

最后,生成readme.json文件,记录了数据集的相关信息,包括所有类别的名称、总的类别数量、总图像数量以及每个类别的详细信息。


def data_mapper(sample):img_path, label = sample# 进行图片的读取,由于数据集的像素维度各不相同,需要进一步处理对图像进行变换img = paddle.dataset.image.load_image(img_path)       #进行了简单的图像变换,这里对图像进行crop修剪操作,输出img的维度为(3, 47, 47)img = paddle.dataset.image.simple_transform(im=img,         resize_size=47, #剪裁图片crop_size=47, is_color=True,   #是否彩色图像is_train=True)   #是否训练集#将img数组进行进行归一化处理,得到0到1之间的数值img= img.flatten().astype('float32')/255.0return img, labeldef data_r(file_list, buffered_size=1024):def reader():with open(file_list, 'r') as f:lines = [line.strip() for line in f]for line in lines:img_path, lab = line.strip().split('\t')yield img_path, int(lab) return paddle.reader.xmap_readers(data_mapper, reader,cpu_count(), buffered_size)

       定义了两个函数:data_mapper和data_r。

data_mapper函数接受一个样本作为输入,并对图像进行预处理。首先,它根据样本中的图像路径加载图像。然后,它对图像进行变换,包括剪裁、调整大小和归一化等操作。最后,返回处理后的图像和对应的标签。

       data_r函数是一个数据读取器函数,它接受一个文件列表file_list和一个缓冲区大小buffered_size作为输入。在这个函数中,打开文件列表并逐行读取文件中的内容。每行包含图像路径和标签,通过yield语句将其作为一个样本输出。最后,使用paddle.reader.xmap_readers函数将data_mapper应用到每个样本上,并指定cpu_count()获取CPU核心数量和缓冲区大小。这个函数返回一个数据读取器,可以用于后续的数据读取。

BATCH_SIZE = 128
BUF_SIZE= 1024
#构造训练数据提供器
train_r= data_r(file_list=TRAIN_LIST_PATH)
train_reader = paddle.batch(paddle.reader.shuffle(reader=train_r,buf_size=BUF_SIZE),batch_size=BATCH_SIZE)#构造测试数据提供器
eval_r = data_r(file_list=EVAL_LIST_PATH)
eval_reader = paddle.batch(eval_r,batch_size=BATCH_SIZE)

构建训练数据和测试数据的数据提供器的部分。

           首先,声明了BATCH_SIZE和BUF_SIZE两个变量,分别表示每个批次的样本数量和缓冲区的大小。

然后,使用data_r函数创建了训练数据读取器train_r,并传入训练数据的文件列表路径TRAIN_LIST_PATH。这里data_r函数会返回一个数据读取器,用于读取训练数据。

           接下来,使用paddle.batch函数构建了一个训练数据提供器train_reader。首先,通过paddle.reader.shuffle函数将训练数据读取器train_r的样本顺序进行随机洗牌,设置缓冲区大小为BUF_SIZE。然后,使用paddle.batch函数将洗牌后的样本按照BATCH_SIZE进行分批,得到一个批次大小为BATCH_SIZE的训练数据提供器。

类似地,使用data_r函数创建了测试数据读取器eval_r,并传入测试数据的文件列表路径EVAL_LIST_PATH。然后,使用paddle.batch函数将测试数据读取器eval_r的样本按照BATCH_SIZE进行分批,得到一个批次大小为BATCH_SIZE的测试数据提供器eval_reader。

这段代码的结果是得到了两个数据提供器train_reader和eval_reader,可以分别用于训练和测试模型。这些数据提供器可以按照批次读取数据,方便输入给模型进行训练和评估。

 网络配置

#定义CNN网络
class MyCNN(fluid.dygraph.Layer):def __init__(self):super(MyCNN,self).__init__()self.conv1 = Conv2D(num_channels=3, num_filters=20, filter_size=5, padding=0, act='relu')self.pool1 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')self._batch_norm_1 = BatchNorm(num_channels = 20 , act = None)self.conv2 = Conv2D(num_channels=20, num_filters=50, filter_size=5, padding=0, act='relu')self.pool2 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')self._batch_norm_2 = BatchNorm(num_channels = 50 , act = None)self.conv3 = Conv2D(num_channels=50, num_filters=50, filter_size=5, padding=0, act='relu')self.pool3 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')self.fc1 = Linear(input_dim=200, output_dim=23,act="softmax")def forward(self,input):x = self.conv1(input)x = self.pool1(x)x = self._batch_norm_1(x)x = self.conv2(x)x = self.pool2(x)x = self._batch_norm_2(x)x = self.conv3(x)x = self.pool3(x)x = fluid.layers.reshape(x, [x.shape[0], -1])y = self.fc1(x)return y

定义一个简单的 CNN(Convolutional Neural Network)模型,并使用 Paddle 2.0 提供的动态图机制进行构建。

首先,使用fluid.dygraph.Layer作为基类创建自己的CNN模型。在__init__()函数中定义模型中的各个层。具体来说,创建两个卷积层self.conv1self.conv2,每个卷积层后跟随一个池化层self.pool1self.pool2。之后,定义两层全连接层self.fc1self.fc2,最后的输出表示24个分类。

然后,通过forward()函数实现模型的前向计算。输入参数input表示输入数据,通过卷积层self.conv1进行卷积操作,再通过池化层self.pool1进行下采样,接着通过卷积层self.conv2和池化层self.pool2进行二次卷积和下采样。之后使用fluid.layers.reshape()函数将每个样本的特征展平为一维向量,再通过self.fc1self.fc2进行两次全连接操作,得到最终的分类结果。同时,在定义每个层时,设定合适的输入图片通道数、卷积核个数、卷积核大小、池化层大小等参数。

       定义了一个名为 `MyCNN` 的类,继承自 `fluid.dygraph.Layer`。在类的构造函数中,通过调用 `super` 函数初始化父类,然后创建了一些卷积层(`Conv2D`)、池化层(`Pool2D`)和批标准化层(`BatchNorm`),以及一个全连接层(`Linear`)。这些网络层的参数具体含义如下:

- `Conv2D`:卷积层,用于提取图像特征;

  - `num_channels`:输入数据的通道数,这里是 RGB 彩图,设置为 3;

  - `num_filters`:卷积核个数,表示在当前层中卷积的输出特征图个数;

  - `filter_size`:卷积核大小,设为 5;

  - `padding`:填充大小,设为 0,表示没有填充;

  - `act`:激活函数,设为 `relu`。

- `Pool2D`:池化层,用于对特征图进行下采样降维;

  - `pool_size`:池化窗口大小,设为 2;

  - `pool_stride`:池化步长,设为 2;

  - `pool_type`:池化类型,设为 `max`。

- `BatchNorm`:批标准化层,用于对输入数据进行归一化;

  - `num_channels`:输入数据的通道数;

  - `act`:激活函数,设为 `None`。

- `Linear`:全连接层,用于将提取的特征进行分类;

  - `input_dim`:输入数据的维度,这里是经过卷积和池化后的特征图大小,设为 200;

  - `output_dim`:输出数据的维度,这里是分类的类别数,设为 23;

  - `act`:激活函数,设为 `softmax`。

接下来,定义了 `forward` 函数,该函数将输入数据 `input` 通过卷积、池化、批标准化和全连接层依次进行计算并输出分类结果 `y`。函数中,使用了创建卷积、池化和批标准化层时设定的各种参数进行计算。在最后一层全连接层中,通过将卷积和池化后的特征使用 `reshape` 函数将其展平为一维向量,然后输入到全连接层中进行分类。

 可视化处理

#绘制训练过程
def draw_train_process(title,iters,costs,accs,label_cost,lable_acc):plt.title(title, fontsize=24)plt.xlabel("iter", fontsize=20)plt.ylabel("cost/acc", fontsize=20)plt.plot(iters, costs,color='red',label=label_cost) plt.plot(iters, accs,color='green',label=lable_acc) plt.legend()plt.grid()plt.show()def draw_process(title,color,iters,data,label):plt.title(title, fontsize=24)plt.xlabel("iter", fontsize=20)plt.ylabel(label, fontsize=20)plt.plot(iters, data,color=color,label=label) plt.legend()plt.grid()plt.show()

这段代码定义了两个绘图函数 `draw_train_process` 和 `draw_process`,用于绘制训练过程中的损失和准确率变化曲线。

- `draw_train_process` 函数用于绘制训练过程中损失和准确率的变化曲线。它接受以下参数:

  - `title`:图像标题;

  - `iters`:训练迭代次数列表;

  - `costs`:损失列表;

  - `accs`:准确率列表;

  - `label_cost`:损失曲线的标签;

  - `label_acc`:准确率曲线的标签。

在函数内部,使用 `plt` 模块绘制了两条曲线,分别表示损失和准确率的变化情况。在绘制曲线之前,先设置了图像的标题、横坐标和纵坐标标签。然后,调用 `plt.plot` 函数绘制曲线,其中 `iters` 是横坐标,`costs` 和 `accs` 是纵坐标,`color` 参数表示曲线颜色,`label` 参数表示曲线的标签。最后,通过调用 `plt.legend` 函数显示曲线的图例,并调用 `plt.grid` 函数显示网格线。调用 `plt.show` 函数显示绘制结果。

- `draw_process` 函数用于绘制任意数据随迭代次数变化的曲线。它接受以下参数:

  - `title`:图像标题;

  - `color`:曲线颜色;

  - `iters`:迭代次数列表;

  - `data`:数据列表;

  - `label`:数据曲线的标签。

该函数内部的实现与 `draw_train_process` 类似,只是绘制的曲线是任意数据随迭代次数变化的情况。

调用这两个函数可以方便地可视化训练过程中的损失和准确率的变化,帮助分析和评估模型的训练效果。

 模型评估

#用动态图进行训练
all_train_iter=0
all_train_iters=[]
all_train_costs=[]
all_train_accs=[]best_test_acc = 0.0
model_save_dir = "./work/sea.inference"with fluid.dygraph.guard():model=MyCNN() #模型实例化model.train() #训练模式opt=fluid.optimizer.Adam(learning_rate=fluid.dygraph.ExponentialDecay(learning_rate=0.002,decay_steps=3000,decay_rate=0.1,staircase=True), parameter_list=model.parameters())epochs_num=35 #迭代次数for pass_num in range(epochs_num):lr = opt.current_step_lr()print("learning-rate:", lr)for batch_id,data in enumerate(train_reader()):images=np.array([x[0].reshape(3,47,47) for x in data],np.float32)labels = np.array([x[1] for x in data]).astype('int64')labels = labels[:, np.newaxis]image=fluid.dygraph.to_variable(images)label=fluid.dygraph.to_variable(labels)predict=model(image)#预测#print(predict)loss=fluid.layers.cross_entropy(predict,label)avg_loss=fluid.layers.mean(loss)#获取loss值acc=fluid.layers.accuracy(predict,label)#计算精度avg_loss.backward()opt.minimize(avg_loss)model.clear_gradients()all_train_iter=all_train_iter+BATCH_SIZEall_train_iters.append(all_train_iter)all_train_costs.append(avg_loss.numpy()[0])all_train_accs.append(acc.numpy()[0])if batch_id!=0 and batch_id%50==0:print("train_pass:{},batch_id:{},train_loss:{},train_acc:{}".format(pass_num,batch_id,avg_loss.numpy(),acc.numpy()))with fluid.dygraph.guard():accs = []model.eval()#评估模式for batch_id,data in enumerate(eval_reader()):#测试集images=np.array([x[0].reshape(3,47,47) for x in data],np.float32)labels = np.array([x[1] for x in data]).astype('int64')labels = labels[:, np.newaxis]image=fluid.dygraph.to_variable(images)label=fluid.dygraph.to_variable(labels)predict=model(image)#预测acc=fluid.layers.accuracy(predict,label)accs.append(acc.numpy()[0])avg_acc = np.mean(accs)if avg_acc >= best_test_acc:best_test_acc = avg_accif pass_num > 10:fluid.save_dygraph(model.state_dict(),model_save_dir)#保存模型print('Test:%d, Accuracy:%0.5f, Best: %0.5f'%  (pass_num, avg_acc, best_test_acc))print('训练模型保存完成!')
print("best_test_acc", best_test_acc)
#draw_train_process("training",all_train_iters,all_train_costs,all_train_accs,"trainning cost","trainning acc")  
draw_process("trainning loss","red",all_train_iters,all_train_costs,"trainning loss")
draw_process("trainning acc","green",all_train_iters,all_train_accs,"trainning acc")  

用动态图进行训练。

        首先,使用`fluid.dygraph.guard()`将程序切换到动态图模式。然后,实例化模型对象`model=MyCNN()`,并进入训练模式`model.train()`。接下来,定义优化器`opt=fluid.optimizer.Adam(...)`,设置学习率为指数衰减的形式。然后,进入迭代训练的循环,循环次数由`epochs_num`指定。

       在每个训练迭代中,首先计算当前的学习率`lr = opt.current_step_lr()`,然后遍历训练数据集并进行训练。在每个batch中,先将输入数据转换为`fluid.dygraph.to_variable`形式,然后通过模型`model(image)`进行预测。然后计算损失函数`loss`和平均损失`avg_loss`,以及精度`acc`。在计算了梯度之后,调用`opt.minimize(avg_loss)`来更新模型参数,并清除梯度`model.clear_gradients()`。最后记录训练过程中的损失值和精度,以便后续分析和可视化。

       在每个epoch的训练过程中,可以打印出每个batch的训练损失和精度,以及当前的学习率。

上述代码是在使用动态图模式下对模型进行评估的示例。首先,使用`fluid.dygraph.guard()`将程序切换到动态图模式。接着,将模型设置为评估模式`model.eval()`。

      然后,在每个batch中,通过`eval_reader()`获取测试数据集,并对其进行预处理。将输入数据转换为适合模型的形状,并将其转换为`fluid.dygraph.to_variable`形式。然后通过模型`model(image)`进行预测,计算预测准确度`acc`,并将其保存在`accs`列表中。

在完成对测试数据集的评估后,计算平均准确度`avg_acc`。

       接下来,判断当前的平均准确度`avg_acc`是否大于等于历史最佳准确度`best_test_acc`。若是,则更新`best_test_acc`并将模型保存到指定的路径`model_save_dir`。

      最后,打印当前epoch的测试准确度`avg_acc`和历史最佳准确度`best_test_acc`的值。

      在代码的下一部分,绘制了训练过程中的损失和精度曲线。`all_train_iters`记录了每个训练迭代的次数,`all_train_costs`记录了每个迭代的训练损失,`all_train_accs`记录了每个迭代的训练精度。通过调用`draw_process()`函数,分别绘制了训练损失和训练精度曲线的图像。

最后,打印出模型保存完成的提示信息,以及历史最佳准确度`best_test_acc`的值。

 模型预测

#图片预处理
def load_image(file):im = Image.open(file)im = im.resize((47, 47), Image.ANTIALIAS)                 #resize image with high-quality 图像大小为28*28im = np.array(im).reshape(1, 3, 47, 47).astype(np.float32)#返回新形状的数组,把它变成一个 numpy 数组以匹配数据馈送格式。im = im / 255.0                            #归一化到【-1~1】之间return iminfer_path ='/home/aistudio/data/data13981/00009598_05281.png'img = Image.open(infer_path)
plt.imshow(img)   #根据数组绘制图像
plt.show()        #显示图像image=load_image(infer_path)#构建预测动态图过程with fluid.dygraph.guard():model=MyCNN()#模型实例化model_dict,_=fluid.load_dygraph(model_save_dir)model.load_dict(model_dict)#加载模型参数model.eval()#评估模式infer_img = load_image(infer_path)infer_img=np.array(infer_img).astype('float32')infer_img = fluid.dygraph.to_variable(infer_img)results=model(infer_img)print('results',results)label_list = ["fish_21", "fish_19", "fish_15", "fish_20", "fish_1","fish_5","fish13","fish2","fish4","fish_14","fish_16","fish_6","fish_18","fish_17","fish_22","fish_8","fish_3","fish_23","fish_9","fish_7","fish_12","fish_11","fish_10"]print("infer results: %s" % label_list[np.argmax(results[0])])

使用已经训练好的模型进行图片分类预测的示例。

       首先,通过load_image()函数读取要进行预测的图片,并进行预处理。将图片缩放到指定的大小(47x47),转换为numpy数组,并进行归一化处理。

       接着,使用fluid.dygraph.guard()将程序切换到动态图模式。实例化模型,并加载之前保存的模型参数。

       然后,将预测的图片转换为动态图的fluid.dygraph.to_variable形式,并通过模型进行预测。预测结果存储在results变量中。

最后,根据预测结果的最大值对应的索引,在标签列表中找到对应的分类名称,并打印出预测结果。

最后得到结果: 

  • 推理结果的名称为 “tmp_ _23”。

  • 推理结果的数据类型为浮点型(float),具体的精度为 FP32。

  • 推理结果的形状为 [1, 23],表示结果是一个形状为 1 行 23 列的矩阵。

  • 推理结果的布局为 NCHW,其中 N 表示批次大小(batch size),C 表示通道数(channel),H 和 W 表示高度和宽度。

  • 推理结果的具体数值是一个长度为 23 的浮点数数组,表示每个类别的预测概率或置信度。

  • 从给定的数据中,可以看出各个类别的概率值,这些概率值是模型对测试图片所属类别的预测结果。以 “fish_21” 为例,该类别具有较高的概率值。

  • 至此,已经成功搭建了一个简单的卷积神经网络并实现了海洋生物的识别。

总结:

针对以上海洋识别代码中的数据预处理、神经网络构建、模型训练、模型评估和预测应用步骤可以使用更好的处理方式:

1. 数据预处理:可以通过增加更多的图像增强操作,如旋转、翻转、随机裁剪等,增加数据的丰富性和多样性,进一步提高模型的泛化能力。此外,可以尝试使用自适应大小的图像处理技术,如将图像调整为相同的长宽比,并在其中心部位对图像进行裁剪,以更好地利用图像关键部分的信息。

2. 神经网络构建:可以尝试使用更先进的模型结构和技术,如 EfficientNet, ResNeSt 等,这些模型可以在相同参数量的情况下获得更好的性能,能够进一步提升模型的准确率和鲁棒性。

3. 模型训练:可以通过更复杂的模型训练策略和方法,如在模型训练过程中引入注意力机制、切换学习率和自适应学习率等方法,在不同训练阶段使用不同的损失函数等,来进一步提升模型的性能和训练效果。

4. 模型评估:可以针对不同的评价指标进行更为全面和深入的评估,如 precision-recall 曲线、F1 值等,以更全面地评估模型的性能和效果。

5. 预测应用:可以应用一些高级技术来提高处理速度和准确率,如模型量化、模型蒸馏等技术,以在保证预测质量的同时,提高预测速度,适应更大规模和更严格的实时预测应用场景。

本次海洋识别代码中各步骤采用了较为基础和常见的方法,造成了一定的局限性。使用更先进的深度学习模型、更复杂的训练和评估策略,可以进一步提高深度学习模型在海洋图像分类任务中的性能。

更多推荐

深度学习 海洋识别

本文发布于:2024-02-25 20:01:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1700135.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:深度   海洋

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!