作者:Mercy Markus

翻译:陈之炎

校对:丁楠雅

本文约3700字,建议阅读10+分钟。

一支深度学习的新手队如何在kaggle竞赛中获得第三名?

图:亚历山大·纳格斯塔德 (AlexanderNaglestad)

WiDS数据马拉松由女性数据科学工作者与她们的伙伴联合发起,她们面临的挑战是需要建立一个模型,来预测一批卫星图像中存在油棕人工林种植园的情况。

数据集是称为“行星”的人造卫星新近拍摄的经加注后的卫星图像数据集,该图像数据集具有3米的空间分辨率,每幅图像都是基于图像中是否存在油棕种植园进行标记的(0表示没有油棕种植园,1表示有油棕种植园)。任务是需要训练一个模型,该模型以卫星图像为输入,并输出对油棕种植园的图像预测的概率。竞赛创建者为模型开发提供了经过标记后的训练和测试数据集。

详情见这里:https://www.kaggle.com/c/widsdatathon2019

我的队友(Abundshakur,Halimah,和IfeomaOkoh)和我采用了fast.ai框架来应对这一挑战。感谢托马斯·卡贝尔(ThomasCapelle)提供了Kaggle上的入门内核,它给出了如何处理这个问题的深刻见解,同时也为fast.ai团队创造了一门神奇的深度学习课程,从而简化了许多复杂的深度学习的概念。现在,深度学习的初学者也可以赢得kaggle比赛了。

我们从一个简单易学的关于深度学习的教程开始吧

目前,无需为理解所有的东西而担心,文中会伴随着大量的练习。本教程旨在展示fast.ai对于深度学习的初学者来说的神奇之处,前提是假设读者会python语言,并且接触过一些ML(机器学习)。如果你已经具备上述技能,那我们就可以走上正轨了。

文中的所有代码都可以在Google Colaboratory(https://colab.research.google.com/notebooks/welcome.ipynb)上获得,这是一个免费的Jupyter笔记本环境,无需安装,运行在云上。可以采用协作的方式编写和执行代码,存盘和共享分析结果,访问功能强大的计算资源,所有这些都是免费的。点击这里可以访问到我们将要使用到的代码。


导入fast.ai和将要用到的其他库

# This ensures that any edits to libraries you make are reloaded here automatically,
# and also that any charts or images displayed are shown in this notebook.
%reload_ext autoreload
%autoreload 2
%matplotlib inline导入库
# Import libraries
from fastai import *
from fastai.vision import *
from fastai.callbacks import CSVLogger, SaveModelCallback
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')

获取竞赛数据


为了尽可能地直观,Abdishakur将竞赛数据文件上传到dropbox.com,可以在这个竞赛页面上找到竞赛数据文件,而且只有接受竞争规则之后才能访问到这些数据文件。

# Get the data from dropbox link
!wget https://www.dropbox.com/s/6kltw0kqynlijxv/widsdatathon2019.zip    # The downloaded competition data is zipped, let us unzip it
!unzip widsdatathon2019.zip
# The training and testing data have already been seperated, Unzip them as well
!unzip train_images.zip
!unzip leaderboard_holdout_data.zip
!unzip leaderboard_test_data.zip

查看数据


在处理这个问题之前,首先要做的是查看可用的数据。在知道如何解决问题之前,我们首先需要了解问题和数据是什么样子。查看数据意味着了解数据目录的结构,标签是什么,以及一些示例图像是什么。

# Overview of the labels of the training data;
df = pd.read_csv('data/traininglabels.csv')
df.head()

使用pandas库读取数据

训练模型过程中使用到的数据标签

处理图像分类数据集和表格数据集的主要区别在于标签的存储方式,这里的标签指的是图像中的内容。在这个特定的数据集中,标签存储在CSV文件中。

要了解如何计算分数列的详细信息,请访问此链接:https://success.figure-eight.com/hc/en-us/articles/201855939-How-to-Calculate-a-Confidence-Score

利用countplot函数来查看培训数据的分布情况,从图中可以看到:大约有14,300幅图片没有油棕榈种植园,而只有942幅图片有油棕榈种植园,这可以称为非均衡数据集,关于非均衡数据集这个深度学习问题,我们不打算在此讨论;目前,可以从这里开始起步:

sns.countplot(df.has_oilpalm)

对两类进行计数

训练数据集的分布情况

准备数据


所提供的测试数据位于两个独立的文件夹中,即排行榜预留数据(leaderboard holdout data)和排行榜测试数据(leaderboard test data)这两个文件夹。由于竞赛要求对两个数据集提交预测结果,所以我们将二者组合起来,这样一共得到6534张图片。

test_imgs = [i for i in test.iterdir()]
hold_imgs = [i for i in lb_test.iterdir()]
combined_test = test_imgs + hold_imgs
len(combined_test)

将排行榜预留数据(leaderboard holdout data )与排行榜测试数据(leaderboard test data)组合起来

采用fast.ai的DataBlock API来构造数据,这是向模型输送数据集的一种简易的方法。

src = (ImageList.from_df(df, path, folder='train_images')    .random_split_by_pct(0.2, seed=14) .label_from_df('has_oilpalm') .add_test(combined_test))   data = (src.transform(get_transforms(flip_vert=True), size=164)  .databunch()    .normalize(imagenet_stats))

创建一个ImageList来保存数据

此步骤要点:

  • 利用ImageList的from_df方法来保存训练数据,这样做是因为将有关训练集的信息存储在名字为df的数据帧中,让它能找到训练图像所在的路径和保存图像的文件夹名称,train_images.

  • 接下来,使用随机分割来对训练集进行分割,留出20%的数据来监控模型在训练过程中的性能。选择一颗种子,以确保再次检查时能得到同样的结果,我们必须知道什么在起作用,什么不起作用。

  • 告诉ImageList在训练集中的数据的标签所在地,利用has_oilpalm方法将组合后的数据添加到测试数据中。

  • 最后,对数据进行转换,使用flip_vert = True翻转图像有助于模型识别图像。利用imagenet_stats对图像归一化处理。注意:这是一种转移学习技术,我要说的是需要保持操作尽可能简单。

图像预览

不管有没有油棕种植园,卫星图像是这样的:

data.show_batch(2)

显示2批图像

有油棕的图像标记为1,无油棕的图像标记为0

训练模型


现在开始训练模型,采用卷积神经网络骨干,并使用预先训练的权重,这个权重从一个已经训练好的图像分类的resnet模型中直接获得,无须担心这种方法的细节。目前为止,我们正在构建一个以卫星图像为输入并输出这两种分类的预测概率模型。

learn = create_cnn(data, models.resnet50, metrics=[accuracy, error_rate],    callback_fns=[ShowGraph, SaveModelCallback])
# View model architecture
learn.model()

卷积神经网络

learn.lr_find()
learn.recorder.plot()

找出最优的模型学习率

接下来,使用lr_find()找到理想的学习率,并利用recorder.plot().对它可视化。

找出最优的模型学习率

选择一个接近坡度最陡之处的学习速率,在这个示例中是1e-2。

learn.fit_one_cycle(5, slice(1e-2))

学习率为1e-2的5个循环的训练模型

利用fit_one_cycle函数对模型训练5个周期 (对所有数据训练5个周期)。

训练和验证损失

注意到显示出来的结果,如training_loss 和valid_loss没有?后续,会用它们来监控模型的改进。

在第四个循环,得到了最佳的模型。

训练模型的输出;训练和验证损失的过程

fast.ai在运行训练和验证数据集时,内部自动选取和保存最优的那个模型。

评估模型

竞赛组委会根据预测概率与观测目标has_oilpalm之间的工作特性曲线下的面积对参赛作品进行评价。通过以下开发者速成班、视频或Kaggle学习论坛的帖子,可以了解到更多关于AUC 的咨询。

开发者速成班: 

https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc

视频: 

https://www.dataschool.io/roc-curves-and-auc-explained/ Kaggle

学习论坛: 

https://www.kaggle.com/learn-forum/5378

默认情况下,Fast.ai没有提供这个评价标准的指标度量,所以我们将用到Scikit-Learning库。

from sklearn.metrics import roc_auc_score
def auc_score(y_score,y_true):  return torch.tensor(roc_auc_score(y_true,y_score[:,1]))
probs,val_labels = learn.get_preds(ds_type=DatasetType.Valid)
print('Accuracy',accuracy(probs,val_labels)),
print('Error Rate', error_rate(probs, val_labels))
print('AUC', auc_score(probs,val_labels))

打印出验证指标

使用预训练模型和fast.ai的优点是,可以得到一个非常好的预测精度,在这个示例中,在没有多做其他工作的情况下,获得了99.44%精确度。

训练第一阶段的指标

将模型存盘,绘制出预测的混淆矩阵。

learn.save('resnet50-stg1')


利用混淆矩阵查看结果

interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix(dpi=120)

绘制混淆矩阵

混淆矩阵是一种图形化的方法,用来查看模型准确或不准确预测的图像数量。

第一阶段训练的混淆矩阵

从这幅图中可以看出,模型准确地预测了2863幅没有油棕人工林的图像,对168幅油棕人工林的图像进行了正确的分类。将10幅含有油棕人工林的图像分类为无油棕人工林图像,并将7幅无油棕人工林图像分类为有油棕人工林图像。

对于一个简单的模型来说这个结果还不错。

接下来,找出这个训练迭代理想的学习率。

learn.lr_find()
learn.recorder.plot()

找出理想的学习率

选择介于1e-6和1e-4之间的一个学习率

利用介于1e-6和1e-4之间的一个学习率最大值对模型进行拟合。

learn.fit_one_cycle(7, max_lr=slice(1e-6,1e-4))

学习率在1e-6和1e-4的范围范围内,对模型进行7次循环训练

训练和验证损失

在每个训练周期后,以图形的方式观察训练指标,从而监测模型的性能。

训练模型的输出;训练和验证损失的进度

保存第二阶段的模型训练结果。

learn.save('resnet50-stg2')
probs,val_labels = learn.get_preds(ds_type=DatasetType.Valid)
print('Accuracy',accuracy(probs,val_labels)),
print('Error Rate', error_rate(probs, val_labels))
print('AUC', auc_score(probs,val_labels))

准确度、误差率和AUC评分

打印出模型的精度、错误率和曲线下面的面积。

第二阶段训练指标

你会注意到,此时,模型的准确度从99.44%提高到99.48%,错误率从0.0056降低到0.0052,AUC也有改善,从99.82%提高到99.87%。

interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix(dpi=120)

绘制混淆矩阵

通过与我们绘制的上一个混淆矩阵的比较,可以发现模型做出了更精准的预测。

第二阶段训练的混淆矩阵

先前没有油棕种植园的7张图片被错误分类,现在降到了3张,性能有所提高。

你会注意到在训练过程中遵循了一个模式,在这个过程中调整了一些参数,这便是所谓的精调,绝大多数深度学习训练均遵循类似的迭代模式。

图像变换

我们将对数据执行更多的图像变换,通过这些变换对模型进行改进。

关于每种变换的详细描述,可以在fast.ai的相关文档中找到:https://docs.fast.ai/vision.transform.html

 tfms = get_transforms(flip_vert=True, max_lighting=0.1, max_zoom=1.05, max_warp=0.)
data = (src.transform(tfms, size=200) .databunch().normalize(imagenet_stats)) learn.data = data  data.train_ds[0][0].shape

应用不同的变换改进模型

  • hting:如果非空 None,则在概率p_lighting下使用由max_light控制的随机亮度和对比度变化。

  • max_zoom:如果非1,或是一个比1更小的数,则在概率p_affine下使用max_zoom到1之间的随机缩放比

  • max_warp:如果非空None,则使用概率p_affine应用-max_warp和max_warp之间的随机对称翘曲。

再次找出最优学习率:

learn.lr_find()
learn.recorder.plot()

找出理想的学习率

选择学习率为1e-6

循环训练模型5次:

learn.fit_one_cycle(5, 1e-6)

循环训练模型5次

训练和验证损失

将训练指标与先前的指标进行比较,模型在0.0169与0.0163之间的迭代稍差,但是不要失望。

训练模型的输出结果,在第3次迭代时获得了最佳模型

将第三阶段的训练模型保存,并打印出指标。可以注意到,目前,模型的准确度是99.38%,在前一阶段是99.48%,AUC评分从99.87%提高到99.91%,达到了比赛评分的标准。

learn.save('resnet50-stg3')
probs,val_labels = learn.get_preds(ds_type=DatasetType.Valid)
print('Accuracy',accuracy(probs,val_labels)),
print('Error Rate', error_rate(probs, val_labels))
print('AUC', auc_score(probs,val_labels))

准确度、误差率和AUC评分

第三阶段训练指标

最终训练阶段


可以注意到,我们从最初图像大小size = 164的图像开始,然后逐渐递增,最终达到了 size = 256 。这样做是为了利用FAST.ai的累进图像大小进行分类,即在训练开始时使用小图像,并随着训练的进展逐渐增大大小。这样,即便模型早期训练时非常不准确,它也可以快速地看到大量图像并加快进度,在后续的训练中,可以看到更大的图像,从而了解更细粒度的区别。

若要有关此信息,请访问此链接:https://www.fast.ai/2018/08/10/fastai-diu-imagenet/

tfms = get_transforms(flip_vert=True, max_lighting=0.1, max_zoom=1.05, max_warp=0.)
data = (src.transform(tfms, size=256) .databunch().normalize(imagenet_stats)) learn.data = data  data.train_ds[0][0].shape

应用不同的变换来改进模型

将图像大小增加到256

再次找出优化后的学习率:

learn.lr_find()
learn.recorder.plot()

找出理想的学习率

找出理想的学习率

learn.fit_one_cycle(5, slice(1e-4)) 

学习率设置为1e-4,训练模型5次循环

训练和验证损失

来看一下训练指标,并与过去的指标进行比较,模型略有改进,从0.0169提高到0.0168。

训练模型的输出,在第2次循环时获得最优的模型

将最后阶段的模型训练结果保存,并打印出指标:

learn.save('resnet50-stg4') 
probs,val_labels = learn.get_preds(ds_type=DatasetType.Valid)
print('Accuracy',accuracy(probs,val_labels)),
print('Error Rate', error_rate(probs, val_labels))
print('AUC', auc_score(probs,val_labels))

准确度、误差率和AUC评分

你会注意到,模型的准确度现在是99.44%,比上一阶段的99.38%有所提高:

第四阶段训练指标

准备竞赛提交文件


现在可以看到模型是如何对数据进行预测的:

p,t = learn.get_preds(ds_type=DatasetType.Test)   p = to_np(p);
p.shape ids = np.array([f.name for f in (combined_test)]);
ids.shape   sample_sub = Path('data/SampleSubmission.csv')
df_sample = pd.read_csv(sample_sub)    sub = pd.DataFrame(np.stack([ids, p[:,1]], axis=1), columns=df_sample.columns)   sub.to_csv(path/'wids-notebook.csv', index=False)

准备CSV格式的提交文件

向WiDS数据马拉松提交文件


现在可以参加WiDS的竞赛,并提交参赛文件了,请转到此处(https://www.kaggle.com/c/widsdatathon2019)的竞赛页面,单击“加入竞赛”并接受竞赛规则,便可以提交参赛内容,如果你参加,看看你会排名第几。

我提交了自己的模型的预测之后

获得的私有和公开分数

免责声明:按照文章中的说明操作后,不会像我那样位列第三,为确保过程尽可能简单,请参看链接(https://www.kaggle.com/c/widsdatathon2019/discussion/82252)中Abdishakur的帖子。

原文标题:

How a team of deep learning newbies came 3rd place in a kaggle contest——Classifying images of oil palm plantations using fast.ai

原文链接:

https://towardsdatascience.com/how-a-team-of-deep-learning-newbies-came-3rd-place-in-a-kaggle-contest-644adcc143c8

译者简介

陈之炎,北京交通大学通信与控制工程专业毕业,获得工学硕士学位,历任长城计算机软件与系统公司工程师,大唐微电子公司工程师,现任北京吾译超群科技有限公司技术支持。目前从事智能化翻译教学系统的运营和维护,在人工智能深度学习和自然语言处理(NLP)方面积累有一定的经验。业余时间喜爱翻译创作,翻译作品主要有:IEC-ISO 7816、伊拉克石油工程项目、新财税主义宣言等等,其中中译英作品“新财税主义宣言”在GLOBAL TIMES正式发表。能够利用业余时间加入到THU 数据派平台的翻译志愿者小组,希望能和大家一起交流分享,共同进步

翻译组招募信息

工作内容:需要一颗细致的心,将选取好的外文文章翻译成流畅的中文。如果你是数据科学/统计学/计算机类的留学生,或在海外从事相关工作,或对自己外语水平有信心的朋友欢迎加入翻译小组。

你能得到:定期的翻译培训提高志愿者的翻译水平,提高对于数据科学前沿的认知,海外的朋友可以和国内技术应用发展保持联系,THU数据派产学研的背景为志愿者带来好的发展机遇。

其他福利:来自于名企的数据科学工作者,北大清华以及海外等名校学生他们都将成为你在翻译小组的伙伴。

点击文末“阅读原文”加入数据派团队~

转载须知

如需转载,请在开篇显著位置注明作者和出处(转自:数据派ID:datapi),并在文章结尾放置数据派醒目二维码。有原创标识文章,请发送【文章名称-待授权公众号名称及ID】至联系邮箱,申请白名单授权并按要求编辑。

发布后请将链接反馈至联系邮箱(见下方)。未经许可的转载以及改编者,我们将依法追究其法律责任。

点击“阅读原文”拥抱组织

独家 | kaggle季军新手笔记:利用fast.ai对油棕人工林图像进行快速分类(附代码)...相关推荐

  1. python抓取朋友圈动态_如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下)...

    原标题:如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下) 前天给大家分享了如何利用Python网络爬虫爬取微信朋友圈数据的上篇(理论篇),今天给大家分享一下代码实现(实战篇),接着上篇往 ...

  2. 《算法图解》学习笔记(八):贪婪算法和NP完全问题(附代码)

    欢迎关注WX公众号:[程序员管小亮] python学习之路 - 从入门到精通到大师 文章目录 欢迎关注WX公众号:[程序员管小亮] [python学习之路 - 从入门到精通到大师](https://b ...

  3. 手把手带你复现AI+区块链写码全过程!(附代码视频)

    作者:Siraj Raval 来源:AI科技评论 本文约1000字,建议阅读7分钟. 本文和大家讨论AI和区块链如何一起工作,并且在在 python 中编写工作证明算法,然后在高层次上讨论一些其他的共 ...

  4. 独家 | 如何用简单的Python为数据科学家编写Web应用程序?(附代码链接)

    作者:拉胡尔·阿加瓦尔(Rahul Agarwal), Walmart 实验室的数据科学家 翻译:陈之炎 校对:闫晓雨 本文约4300字,建议阅读10分钟. 本文阐述如何使用StreamLit创建支持 ...

  5. 独家 | 带你认识HDFS和如何创建3个节点HDFS集群(附代码案例)

    作者:尼廷·兰詹(Nitin Ranjan) 翻译:陈之炎 校对:王威力 本文约1500字,建议阅读5分钟. 在本文中,大数据专家将为您介绍如何使用HDFS以及如何利用HDFS创建HDFS集群节点. ...

  6. 如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下)

    前天给大家分享了如何利用Python网络爬虫爬取微信朋友圈数据的上篇(理论篇),今天给大家分享一下代码实现(实战篇),接着上篇往下继续深入. 一.代码实现 1.修改Scrapy项目中的items.py ...

  7. 史上最全AI开源项目集结,近万篇附代码的论文分门别类整理好

    点上方蓝字计算机视觉联盟获取更多干货 在右上方 ··· 设为星标 ★,与你不见不散 这个资源一经分享出来,Twitter的评论区就成了"大型英文赞美词汇堆叠现场",几千人争相转发点 ...

  8. python朋友圈动态_如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下)

    前天给大家分享了如何利用Python网络爬虫爬取微信朋友圈数据的上篇(理论篇),今天给大家分享一下代码实现(实战篇),接着上篇往下继续深入. 一.代码实现 1.修改Scrapy项目中的items.py ...

  9. 最新版学习笔记---Python机器学习基础教程(1)Irises(鸢尾花)分类---附完整代码

    开始学习机器学习基础,在此留下学习心得与自己的理解. 啥也不说,先看一下鸢尾花啥样 好看吧~~~~ Iris 1.环境搭建 2.了解数据 2.1读取数据 2.2查看数据 3.分离数据 4.构建模型(k ...

最新文章

  1. c++把数组所有元素剔除_C语言基础之数组,第一节,C语言必学知识点剖析
  2. 3月14号,oracle的说道多多
  3. 祝博客园里的所有朋友 新年快乐!
  4. python变量如何声明_如何确定变量是否在Python中声明?
  5. namespace nvinfer1
  6. file_operations结构体分析 (设备文件的操作)
  7. 高达100亿美元!美国国防部将IBM和甲骨文双双踢出了云计算合同;华为任正非说了,华为对向苹果等对手出售5G芯片保持开放的态度...
  8. 【Liunx】manjaro双系统安装(折腾)教程
  9. Log4j2使用总结
  10. 荣耀30 Pro+价格曝光:顶配真的高攀不起!
  11. 【Java】jstack报错Unable to open socket file: target process not responding or HotSpot VM not loaded
  12. C++语言vector容器介绍和示例
  13. 上传文件到阿里云OSS报错-Unable to execute HTTP request: You have no right to access this object because of buc
  14. client_hello_cb、get_session_cb、servername_cb、cert_cb
  15. 移动的宽带真的很垃圾
  16. 中专考的计算机一级b有用吗,白城计算机一级B资格证真实可查么
  17. 什么是支付账户、备付金、网络支付、银行卡清算、贷记卡、代扣、代付....
  18. SDCC编译器 + VSCode开发 8位微控制器
  19. 启动SparkSql,报javax.jdo.JDOFatalInternalException: Error creating transactional connection factory
  20. 常用插件:分享12款超级好用的 Chrome 插件

热门文章

  1. 第九次作业-测试报告和用户使用手册
  2. Ubuntu 新装服务器部署流程
  3. leetcode解题报告:188 Best Time to Buy and Sell Stock IV
  4. [leetcode]Multiply Strings @ Python
  5. too many levels of symbolic links的错误
  6. C语言库函数大全及应用实例二
  7. 苹果无线耳机使用方法_安卓党可以使用 AirPods 吗?实测结果.....
  8. c语言编程取模运算ppt,c语言的取模运算
  9. JVM 方法区 ORACLE官方文档
  10. GBDT原来是这么回事