深度学习 海洋生物识别

编程入门 行业动态 更新时间:2024-10-25 06:26:20

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

深度学习 海洋生物识别

背景目的

针对海洋鱼类识别难的问题,本实践使用卷积神经网络构建深度学习模型,自动提取高质量的特征,从而解决海洋鱼类识别的问题。接下来,我将分享如何使用百度深度学习框架飞桨来搭建卷积神经网络,实现海洋鱼类资源的识别。(本次实践所使用的是台湾电力公司、台湾海洋研究所和垦丁国家公园在2010年10月1日至2013年9月30日期间,在台湾南湾海峡、兰屿岛和胡比湖的水下观
景台收集的鱼类图像数据集。)

本实践选取5种鱼类数据作为数据集进行训练,被划分为两个子集,训练集和测试集比例为9:1

数据集的大小、数据条数、数据格式。

444.34M、 该数据集包括23类鱼种 ,共27370张鱼的图像、 图像数据集JPEG

网络结构

这个网络结构采用了一个比较经典的卷积神经网络(Convolutional Neural Network,CNN)架构。以下是该网络结构的描述:MyCNN (Custom Conwolutional Neural Network);-第1层卷积层(Conv2D):输入通道数为3(RGB图像),输出通道数为20,卷积核大小为5x5,ReLU激活函数,无填充。
-第1层池化层(Pool2D):最大池化,池化窗口大小为2x2,池化步长为2x2。-第1层批归一化层(BatchNorm): 20通道。
-第⒉层卷积层(Conv2D):输入通道数为20,输出通道数为50,卷积核大小为5x5,ReLu 激活函数,无填充。
–第⒉层池化层(Pool2D):最大池化,池化窗口大小为2x2,池化步长为2x2。-第⒉层批归一化层(BatchNorm): 50通道。
-第3层卷积层(Conv2D):输入通道数为50,输出通道数为50,卷积核大小为5x5,ReLU激活函数,无填充。
-第3层池化层(Pool2D):最大池化,池化窗口大小为2x2,池化步长为2x2。
-全连接层(Linear):输入维度为200,输出维度为23(23个类别,对应不同的海洋生物类别),采用Softmax激活函数。
这个网络结构包含了三个卷积层,两个池化层和一个全连接层,是一个典型的卷积神经网络架构。
 

导入包


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 #解压原始数据集,将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()
#存放所有类别的信息
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

首先,代码会解压名为`fish_image23.zip`文件到指定路径`/home/aistudio/data/fish_image`下。如果目标路径不存在,则会创建该文件夹。

接下来,代码会获取目标路径下所有文件夹的名称,存储在`class_dirs`列表中。

然后,代码定义了两个存储训练和评估数据的文件路径,即`train.txt`和`eval.txt`。

之后,代码会清空`train.txt`和`eval.txt`文件的内容,以便接下来将数据写入这两个文件。

这段代码的作用是为数据处理做准备工作,如解压文件、创建文件夹、清空文件内容等,以便后续的数据处理步骤可以顺利进行。

#总的图像数量
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 ('生成数据列表完成!')

上图作用是读取文件夹中的图片,将其划分为训练集和测试集,并将其路径和类别标签写入到train.txt和eval.txt文件中。同时,生成一个readme.json文件,其中记录着各个类别的数量、训练集和测试集的数量等信息。

定义cnn网络
#定义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网络的代码。这个网络包含了两个卷积层和一个全连接层。

在初始化函数中,首先定义了三个卷积层,分别为`conv1`、`conv2`和`conv3`。这些卷积层分别使用了不同的参数设置,包括输入通道数、输出通道数、卷积核大小和激活函数等。

接下来定义了三个池化层,分别为`pool1`、`pool2`和`pool3`。这些池化层用于对卷积层的输出进行下采样,减小特征图的尺寸。

然后定义了两个批归一化层,分别为`_batch_norm_1`和`_batch_norm_2`。批归一化层用于加速网络的收敛,并提高网络的泛化能力。

最后定义了一个全连接层`fc1`,将卷积层的输出展平后连接到全连接层,最终输出分类的结果。该全连接层的输入维度为200,输出维度为23,并使用softmax作为激活函数。

在前向传播函数中,输入通过卷积层、池化层和批归一化层进行处理,最后通过全连接层得到最终的输出。

这个网络适用于图像分类任务,输入为3通道的图像数据,输出为23个类别的概率分布。

损失函数

损失函数采用的是交叉熵损失函数(Cross-Entropy Loss)

交叉熵损失函数是一种常用的分类损失函数,用于衡量模型预测结果与真实标签之间的差异。它在分类任务中非常常见,特别是多分类问题。

在优化过程中,通过最小化交叉熵损失函数,可以使模型更好地拟合真实标签,提高分类准确度。

定义交叉熵损失函数;

loss = fluid.layers.cross_entropy(predict, label)
avg_loss = fluid.layers.mean(loss)

优化方法;

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()
)

这段代码定义了一个Adam优化器`opt`,用于更新模型的参数。

在Adam优化器的构造函数中,指定了学习率参数`learning_rate`,并使用了指数衰减的方式来调整学习率。具体地,通过`fluid.dygraph.ExponentialDecay`函数定义了一个指数衰减的学习率衰减策略。

该衰减策略的学习率初始值为0.002,每经过3000个训练步骤,学习率会按照衰减率0.1进行衰减。此外,`staircase=True`表示衰减过程是阶梯状的,即每经过指定的`decay_steps`个训练步骤后学习率进行衰减,而不是连续衰减。

在优化器的参数列表`parameter_list`中传入了模型的参数`model.parameters()`,这样优化器会自动更新这些参数。

综上所述,该优化器使用Adam算法,并在训练过程中使用指数衰减的学习率来更新模型的参数。

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)loss=fluid.layers.cross_entropy(predict,label)avg_loss=fluid.layers.mean(loss)acc=fluid.layers.accuracy(predict,label)avg_loss.backward()opt.minimize(avg_loss)model.clear_gradients()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))

这里是一个使用PaddlePaddle深度学习框架训练卷积神经网络(CNN)模型的示例代码。

首先使用`with fluid.dygraph.guard()`语句开启动态图模式。`MyCNN()`是定义好的CNN模型类,`model`是模型的实例化对象。然后使用Adam优化器来最小化交叉熵损失函数,`learning_rate`使用指数衰减策略,`optimizer.minimize()`方法对模型参数进行更新,`model.clear_gradients()`方法清除梯度。

代码中有两个 for 循环,一个是外层的迭代次数,另一个是读取 batch 数据集。在训练模型时,首先将数据集通过`train_reader()`函数逐步读取,将每一个 batch 的图像数据和标签数据放入一个 list 中,然后将其转换为NumPy数组,通过`fluid.dygraph.to_variable()`函数将数据转换成动态图变量,将输入的数据喂入 CNN 模型中,计算损失函数并反向传播误差,最后通过`opt.minimize(avg_loss)`来优化模型参数。

代码的末尾有一个用于测试模型的块,它与训练模型的过程类似,不过这里需要使用`model.eval()`语句来进入评估模式。在每个 batch 的迭代中,将图像和标签转换为变量,通过 CNN 模型计算预测结果并计算准确率。该过程中使用`fluid.layers.accuracy()`来获取模型在当前 batch 的准确率。在测试完所有数据后,计算所有 batch 的准确率的平均值并保存最佳模型。

在训练和验证过程中平均误差是在逐步降低的,训练与验证的准确率逐步趋近于100%

模型预测

with fluid.dygraph.guard():model = MyCNN() model_dict, _ = fluid.load_dygraph(model_save_dir) model.load_dict(model_dict) 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) 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])]) 

结束

更多推荐

深度学习 海洋生物识别

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

发布评论

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

>www.elefans.com

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