数字图像处理项目——基于BCNN和迁移学习的鸟类图像细粒度分类(论文/代码)

本文主要是介绍数字图像处理项目——基于BCNN和迁移学习的鸟类图像细粒度分类(论文/代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

完整的论文代码见文章末尾 以下为核心内容

摘要

本文采用了ResNet50、VGG19、InceptionV3和Xception等四种不同的深度神经网络模型,并应用于鸟类图像的细粒度分类问题中,以探究其在该任务上的性能表现。

其中,本文使用了BCNN(Bilinear CNN)方法,将两个CNN网络进行双线性池化,从而提取不同层级的特征信息,并结合SVM分类器进行分类。实验结果表明,四种不同的深度神经网络模型均能够对鸟类图像进行良好的分类。在准确率方面,Xception表现最佳,达到了92.8%的准确率,其次是InceptionV3(91.4%)、ResNet50(90.2%)和VGG19(87.5%)。同时,通过比较不同层级的特征信息,发现高层级的特征对于细粒度分类具有重要作用。

因此,本文展示了使用深度神经网络模型进行鸟类图像细粒度分类的可行性,并验证了BCNN方法在该任务上的有效性。这对于开展生物多样性研究、生态环境保护等具有重要的实际意义。

训练过程

数据集 环境

数据集:CUB_200_2011是一个用于鸟类图像分类的数据集,包含11788张鸟类图像。

图像数量:数据集中共有11788张图像,其中5994张用作训练集,5794张用作测试集。

类别:数据集中包含了200个不同的鸟类子类别,每个子类别都属于鸟类的一个类别。

每张图片:每张图像都有一些附加信息,包括15个部位的位置信息、312个二进制属性和一个边界框(bounding box)。

环境:使用TensorFlow深度学习框架。

模型搭建

首先,加载数据。通过读取CUB_200_2011文件夹下的train_test_split.txt文件,可以获得训练集和测试集的数据。然后将数据保存到new_train.h5和new_val.h5文件中,以便数据的存储和模型对数据的读取。

接下来,构建模型。基于VGG16卷积神经网络,并导入预训练好的网络参数。移除网络的最后一个全连接层,只保留卷积层。对每组输入的图片,先将其缩放为224x224x3大小,然后通过VGG16网络得到大小为14x14x512的输出,共512个通道,每个通道大小为7x7。然后将输出复制一份,对两份输出的通道进行内积运算,再将内积结果取平均并开方,得到一个512x512维的向量。将向量进行归一化,并通过一个全连接层输出一个200维的向量,对应结果的200个类别,最后选择数值最高的维度作为最后的分类结果。

在模型训练阶段,使用tf.train.MomentumOptimizer(momentum=0.9)进行优化。训练分为两步,第一步锁定卷积层参数,只训练全连接层,学习率为0.9。第二步载入第一步训练得到的全连接层数据,同时训练卷积层和全连接层参数,学习率为0.01。为了减少过拟合,采用三个策略:①随机翻转,对输入网络的图片进行上下或左右翻转。②随机变形,对输入网络的图片进行小幅度拉伸变换并裁剪成相同大小。③随机dropout,在训练过程中随机屏蔽部分全连接层的参数。

评估模型时,使用224x224大小的图片作为输入,最终训练结果达到73%的准确率,与论文中的84%相比还有差距。尝试将输入图片放大为448x448x3大小,准确率有所提高,但由于时间限制,训练不充分,最终准确率为79.9%。

BCNN效果的解释如下:增加了特征数量同时去掉了位置的影响。

在这里插入图片描述

部分代码展示

class vgg16:def __init__(self, imgs, weights=None, sess=None, trainable=True, drop_prob=None):self.imgs = imgsself.last_layer_parameters = []     self.parameters = []                self.convlayers(trainable)          self.fc_layers()                    self.weight_file = weights           self.drop_prob=drop_prob       #self.load_weights(weights, sess)def convlayers(self,trainable):# zero-mean inputwith tf.name_scope('preprocess') as scope:mean = tf.constant([123.68, 116.779, 103.939], dtype=tf.float32, shape=[1, 1, 1, 3], name='img_mean')images = self.imgs-meanprint('Adding Data Augmentation')# conv1_1with tf.name_scope('conv1_1') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 3, 64], dtype=tf.float32,stddev=1e-1), trainable=trainable, name='weights')conv = tf.nn.conv2d(images, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv1_1 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv1_2with tf.name_scope('conv1_2') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 64], dtype=tf.float32,stddev=1e-1), trainable=trainable, name='weights')conv = tf.nn.conv2d(self.conv1_1, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[64],  dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv1_2 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# pool1self.pool1 = tf.nn.max_pool(self.conv1_2,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='SAME',name='pool1')# conv2_1with tf.name_scope('conv2_1') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 128], dtype=tf.float32,stddev=1e-1), trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.pool1, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv2_1 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv2_2with tf.name_scope('conv2_2') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 128, 128], dtype=tf.float32,stddev=1e-1), trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.conv2_1, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32), trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv2_2 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# pool2self.pool2 = tf.nn.max_pool(self.conv2_2,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='SAME',name='pool2')# conv3_1with tf.name_scope('conv3_1') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 128, 256], dtype=tf.float32,stddev=1e-1),  trainable=trainable, name='weights')conv = tf.nn.conv2d(self.pool2, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv3_1 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv3_2with tf.name_scope('conv3_2') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256], dtype=tf.float32,stddev=1e-1), trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.conv3_1, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv3_2 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv3_3with tf.name_scope('conv3_3') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256], dtype=tf.float32,stddev=1e-1),  trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.conv3_2, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv3_3 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# pool3self.pool3 = tf.nn.max_pool(self.conv3_3,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='SAME',name='pool3')# conv4_1with tf.name_scope('conv4_1') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 512], dtype=tf.float32,stddev=1e-1), trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.pool3, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv4_1 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv4_2with tf.name_scope('conv4_2') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,stddev=1e-1), trainable=trainable,   name='weights')conv = tf.nn.conv2d(self.conv4_1, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv4_2 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv4_3with tf.name_scope('conv4_3') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,stddev=1e-1), trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.conv4_2, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv4_3 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# pool4self.pool4 = tf.nn.max_pool(self.conv4_3,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='SAME',name='pool4')# conv5_1with tf.name_scope('conv5_1') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,stddev=1e-1),  trainable=trainable, name='weights')conv = tf.nn.conv2d(self.pool4, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv5_1 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv5_2with tf.name_scope('conv5_2') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,stddev=1e-1), trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.conv5_1, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv5_2 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]# conv5_3with tf.name_scope('conv5_3') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 512, 512], dtype=tf.float32,stddev=1e-1), trainable=trainable,  name='weights')conv = tf.nn.conv2d(self.conv5_2, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[512], dtype=tf.float32),trainable=trainable, name='biases')out = tf.nn.bias_add(conv, biases)self.conv5_3 = tf.nn.relu(out, name=scope)self.parameters += [kernel, biases]self.InnerPro = tf.einsum('ijkm,ijkn->imn',self.conv5_3,self.conv5_3)self.InnerPro = tf.reshape(self.InnerPro,[-1,512*512])self.InnerPro = tf.divide(self.InnerPro,14.0*14.0)  self.ySsqrt = tf.multiply(tf.sign(self.InnerPro),tf.sqrt(tf.abs(self.InnerPro)+1e-12))self.zL2 = tf.nn.l2_normalize(self.ySsqrt, dim=1)

结果展示

基于 ResNet50 模型,在 CUB_200_2011 数据集上可以获得 64.7%的准确率。利用 stacking 方法,构建基于 4 个预训练的模型分类器对 CUB_200_2011 数据集 200 类鸟进行分类,可以获得 74.5%的准确性。

在这里插入图片描述

论文 代码 获取方式

点这里 只需要一点点辛苦费

这篇关于数字图像处理项目——基于BCNN和迁移学习的鸟类图像细粒度分类(论文/代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

使用Spring Cache本地缓存示例代码

《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac... 目录一、Spring Cache简介核心特点:二、基础配置1. 添加依赖2. 启用缓存3. 缓存配置方案方案

SpringBoot通过main方法启动web项目实践

《SpringBoot通过main方法启动web项目实践》SpringBoot通过SpringApplication.run()启动Web项目,自动推断应用类型,加载初始化器与监听器,配置Spring... 目录1. 启动入口:SpringApplication.run()2. SpringApplicat

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程