鲸鱼和海豚识别竞赛解析:全流程概述
背景描述我们可以使用人类的指纹和面部特征来识别具体的人(指纹识别,人脸识别),类似地,我们也可以根据海洋生物的尾巴,背鳍,头部等特征识别并跟踪海洋生物。
然而,依赖于研究人员人眼观察的识别方法效率太低,而借助自动化鲸鱼和海豚识别模型,研究人员可以将图像识别时间减少99%以上。
查看数据集数据集格式如下:
其中,test_images和train_images文件夹中分别存储了测试图片和训练图片,就像这样:
train.csv总共有3列,如下:
第一列是图片文件名(image),第二列是该图片中的生物所属种类(species),第三列是该图片中的生物的专属id(indivadual_id)。
sample_submission.csv是所需提交文件的样例,包含每张图片对应的预测结果,由于题目需要预测的是该图片最有可能属于的前5个individual_id,因此这里的predictions中包含5个不同的indivisual_id:
任务描述使用train_images作为训练集,对test_images中的每张图片中的生物individual_id进行预测。
每一个生物个体对应一个不同的 ...
交叉验证时划分数据的方式
交叉验证是机器学习中常用的一种策略,其核心是对数据集进行划分,本文介绍sklearn中的3种交叉验证时划分数据集的方法:
123KFoldStratifiedKFoldGroupKFold
这里来举例说明各个方法的使用。
先来导入这些方法,并创建一个简单的数据集:
12345from sklearn.model_selection import KFold,StratifiedKFold,GroupKFoldx=[1,2,3,4,5,6,7,8,9,10]# 特征y=[0,0,0,0,0,1,1,1,1,1]# 标签group=['a','a','a','b','b','b','b','c','c','c']# 样本所在的组
KFoldKFold只需要特征x就能够完成数据划分
123kf = KFold(n_splits=3,shuffle=True)# n_splits不能超过总的样本 ...
目标检测:Two-stage
RPN寻找每一个anchor匹配到的GT box,所以是多对一(不一定每个anchor都能找到匹配的GT box,原因见第三行)
假设有m个GT box,n个anchor,则有一个mxn的矩阵M, M[i,j]代表第j个anchor与第i个GT box之间的IOU
anchor和GT box的IOU大于0.7,则该anchor为正样本,小于0.2则该anchor为负样本,其余不考虑直接忽略该anchor(除非启用set_low_quliaty,解释:注意还有一个特殊情况,可能有一个gt没有与之匹配的anchor,即该groud-truth和所有的bbox的iou都小于high_threshold,那么我们允许“与这个gt最大iou的bbox”被认为是正样本,确保每个gt都有配对的bbox)
之后再使用nms过滤得到包含正样本和负样本的anchor
最终的正负样本数量是不一致的,并且负样本数量远远大于正样本数量(emm,也不完全是)
选取一定数量的正负样本anchor用于loss计算(可以控制正负样本比例以及正负样本的总个数,比如总个数是256,正负样本比例是0.5,如果正样本不足128 ...
ToothSeg项目总结
项目目标是打造一款牙齿分割器,它可以将一张人脸露齿图分割成共3个类别:上牙,下牙以及其他。
采集露齿微笑的图片作为样本,每个人通过摆出不同嘴型来贡献多个样本。在剔除牙齿比较模糊的图片后,总共得到2000+样本,使用labelme进行标定。
将标定好的数据处理成PascalVOC格式。
按照8:2划分训练集和验证集,基于DeepLabV3+搭建baseline.
输入网络的图片是512*512的。
数据增强:
随机翻转
随机旋转
随机模糊
中心随机裁剪
mIoU=0.8638.
修改网络结构:参考fpn的思想,原先的网络只使用了backbone提取的特征图的高层信息和低层信息,我们把中间层的信息也提取出来,自上而下的进行特征融合(插值上采样,求和或拼接),代码实现在decoder模块中。
mIoU=0.874,有提升。
将交叉熵损失改为Focal Loss,mIoU不升反降,由于调参花费时间会较长,因此不用Focal Loss.
将交叉熵损失改为dice,mIoU=0.8812.
为了使得边缘更平滑,设计了如下方案:
1)制作边缘掩码。具体地,以mask中每个像素点在坐标轴上的位置 ...
如何在网页上部署深度学习模型?
当训练好你的深度学习模型后,就可以考虑部署了。
今天介绍一种简易的部署方式:使用Flask作为后端,将PyTorch模型部署到网页上。
网络模型使用的是torchvision中集成的densenet121,并且已经在imagenet数据集上进行了预训练,网络的输入是1张图片,输出是这张图片的类别(1 from 1000)。
简而言之,这是一个用于1000分类的模型。
原代码来自PyTorch官方教程,本文在此基础上做了些小的改动:
增加将用户上传的图片保存至服务器的static文件夹的功能,图片采用时间戳进行命名,防止因重名而被覆盖。
微调前端代码,使得在预测完成后能够在前端同时展示图片和对应的预测结果。
代码文件的结构如下:
配置好环境后,直接运行app.py即可,根据提示在浏览器中打开地址(蓝色):
进入这个界面:
(南极logo,逃~)
单击选择文件按钮,选择一张jpg,jpeg或png格式的图片,点击上传按钮,等候几秒,就能看到预测结果了:
本来想着在heroku上部署一下,结果发现整个项目占用内存900多兆,而免费版的heroku只提供最大500兆的服务,不能白嫖的话就算 ...
经典语义分割网络:UNet
UNetUNet是为了解决医学图像分割任务提出的,它基于FCN,并设计了更为巧妙的网络结构:
由于网络结构看起来像一个U字母,因此得名UNet.
从整体来看,左侧是编码器部分,负责提取输入图像的高层语义信息;右侧是解码器部分,负责解码高层语义信息并输出最终的分割图。
在解码阶段,还引入了类似跳连的结构,将编码阶段的中间结果直接加了进来。
观察UNet的网络结构,可以发现:
编码器重复如下结构:两次卷积使得通道数加倍,后接一次池化使得特征图尺寸减半。
解码器重复如下结构:上采样使得特征图尺寸加倍,后接两次卷积使得通道数减半。
值得注意的是,在语义分割中,输入与输出的尺寸一般都是是一致的,而UNet却不同。
UNet是为医学图像分割任务而设计的,为了更好的预测图像边界区域,采用了Overlap-tile strategy,这种策略将待预测区域使用镜像进行了填充。
如下图所示,黄色部分是待预测区域,而真正输入UNet的是蓝色区域:
PyTorch实现UNet具体实现与原论文中有些许不同。
这里实现的UNet会保证输入与输出的尺寸一致,且能够适应任意(合理范围内,不能太小)的输入尺寸。
先导入 ...
经典语义分割网络:FCN
从分类任务说起语义分割是一个像素级的分类任务。
在图像分类任务中,输入一张图片,输出这张图片的类别。
在语义分割任务中,输入一张图片,输出这张图片中每一个像素所属类别,因此,语义分割中输入的图像(通道数为3,一般的图片通常含有RGB这3个通道)尺寸和输出结果(也是一张图,通道数为1,每个像素点的取值代表该像素点所属类别对应的取值)的尺寸是一样的。
在之前,我们已经实现过许多的分类网络,这些网络最后都在卷积层后面接上全连接层,以输出分类结果。
但是语义分割的输出是一张单通道的图片,所以直接将以上网络拿过来用是行不通的。
FCN的网络结构FCN( Fully Convolutional Networks, 全卷积网络)开创性的将分类网络中的全连接层改成了卷积层,从而使得整个网络只含有卷积层,这也是FCN名字的由来。
输入的图像经过分类网络的最后一层卷积层之后,往往的得到的是通道数较大,而尺寸较小的特征图,比如6000*7*7。
在这个卷积层后面接一个1*1卷积,可以将输出特征图的通道数设置成总的类别数,而特征图尺寸不变。
之后,对1*1卷积得到的特征图进行上采样操作(插值or转置卷积)就 ...
经典推荐模型:NFM
NFM将FM中的二阶交叉项替换成了一个神经网络,使得NFM能够进行二阶以及二阶之上的特征交叉,增强了模型的表达能力。
NFM模型如下:
其中的f(x)便是上面提及的用于替换FM中二阶交叉项的神经网络。
NFM的结构如下,注意,这里并没有画出来一阶部分,只展示了f(x):
自下往上看。
将输入的稀疏特征向量经过Embedding层,得到对应的稠密编码向量。注意图中的$v_i,i=2,4,7,…$是一个n*k的矩阵,n是第i个特征域所含不同特征取值总数,k是Embedding的维度。
接下来进入BiInteraction Pooling层进行特征交叉,该层所执行的操作如下:
$x_iv_i$是一个长度为k的向量(k是Embedding的维度,其实这个向量就是第i个类别特征取值对应的Embedding向量),$x_jv_j$同样也是一个长度为k的向量,两者做element-wise product,即使对应位置相乘,此时得到的还是一个长度为k的向量。在进行完所有特征交叉(即element-wise product操作)后,将得到的所有长度为k的向量进行相加,得到一个新的长度为k的向量,这就是 ...