Kaggle GrandMaster在训练完模型后还会做什么?

在这里插入图片描述


原作者:Vladimir I. Iglovikov,翻译已获得原作者授权,原文链接

Vladimir I. Iglovikov, Lyft 的计算机视觉工程师,主要研究自动驾驶。曾服役于俄罗斯空降部队。UC Davis 获得过理论凝聚态物理学博士的学位。Kaggler(Grandmaster),曾获得过 Carvana 图像遮蔽挑战的冠军,以及 Dstl 卫星图像特征检测挑战的第三名。


我参加kaggle和其他机器学习平台的竞赛来增加我对机器学习的理解,我的kaggle排名是全球第19名,拿到了Kaggle Grandmaster头衔
每项机器学习项目都以新知识,新代码和新模型权重结束。
我喜欢新的知识,但忽略了旧的项目流水线可以带来的价值。代码保留在Github私有仓库中。模型权重遗落在硬盘,最后都被清理掉。
这个情况并不是kaggle 独有的。在学术界也发生着一模一样的事,学生训练模型,写论文。论文被学术会议接收后,流水线就抛弃,训练artifacts被删除然后学生继续做下一个。
这篇文章将会讨论每次机器学习挑战结束后,你可以尝试的几个小步骤。
这些步骤将:

  • 增强技术知识
  • 建立个人品牌
  • 改善职业机会
  • 让世界更美好:)

我将用这个Github仓库示范
https://github.com/ternaus/retinaface
这些步骤不是kaggle 挑战的一部分,而是来讲清楚这个项目在干什么。

I: +5 min: 把代码发布到Github公共仓库

大部分情况是代码在github上,但是是私有仓库。
如果将其公开,我们又会损失什么呢?
在某些情况下,私有仓库确实应该保证私有,但是在你的试验项目,你的kaggle解决方案,或者你的论文中,不应该是这样的。
我见过的最完美的理由是:人们认为所有公共代码都应该是完美的,如果不是的话他们可能会遭受非议。
但事实上,没有人在意的。只管做你的,照原样发布,不需要任何润色。
公开代码是心理上很重要的一步。发布不完美的代码是一种自信,大胆的行动。
此外,所有后续步骤都基于公开代码。
示例:https://github.com/ternaus/retinaface

II: +20 min: 增加可读性

你可以通过添加语法格式化工具和检查器来提高python代码的可读性。
这并不困难并且也不费时,检查器和格式化工具并不会把糟糕的代码变成优秀的,但是可读性会提高。考虑将语法规范当成个人习惯,就像喝水吃饭一样。
我有一篇文章叫9步让你拥有更专业的python代码。大家有兴趣可以看看。

第一步: 配置文件

将这些文件加到你仓库的根目录

第二步: 需求环境

使用下面的命令安装所需的库

pip install black flake8 mypy

第三步: black

有100500种格式化代码的方法,像black或yapf之类的格式化工具会修改代码来满足一组预先定义好的规则
阅读具有某些标准的代码库会容易很多。当我们花几个小时来编写代码并在不同代码风格之间切换,我们的“意志力”会被吸干。所以没有充分原因就不需要这样做。
运行

black .

将会重新格式化所有代码文件以遵循black的规则

第四步: flake8

运行

flake8

不会修改代码,但是会检查代码中的语法问题并输出到屏幕。
然后去改正他们。

第五步: mypy

Python并没有强制性的静态类型化,但是建议将类型添加到函数中并返回类型。
例如:

class MyModel(nn.Module):
    ....

def forward(x: torch.Tensor) -> torch.Tensor:
    ....
	return self.final(x)

你应该在代码中标注类型,

  1. 它会使你读代码更加容易
  2. 你也可以使用mypy包来检查参数和函数类型的一致性
    在更新代码后,在整个仓库上运行mypy
mypy .

如果mypy找到了问题,就解决它们吧

第六步: Pre-commit hook

一直手动运行flake8, black, mypy是很麻烦的。
一个叫做pre-commit hook的工具可以帮你解决该问题。
.pre-commit-config.yaml复制到仓库里面来启用它
你首先需要在你电脑上下载pre-commit hook:

pip install pre-commit

安装并初始化

pre-commit install

安装成功后,它将会在每次提交时运行检查,检查发现错误就无法提交。
和手动运行black, flake8, mypy相比,他不仅是求着你,而是强迫你必须修复问题。因此,我们的“意志力”就不会被浪费

第七步: Github动作

你刚刚在pre-commit hook里面添加了所有的检查,然后你在本地运行了他们。但是你仍然仍然需要二道检查,你 需要在github上所有拉取请求上运行这些检查。
这样做的方法是把 .github/workflows/ci.yaml添加到仓库中:

	- name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
        pip install black flake8 mypy
    - name: Run black
      run:
        black --check .
    - name: Run flake8
      run: flake8
    - name: Run Mypy
      run: mypy retinaface

这样GitHub就知道哪些部分需要检查。

我并不建议将代码直接推送到master分支。

创建一个新分支,修改代码,提交,推送到Github,创建拉取请求,然后合并到master。

这是行业中的标准,但是在学术界和Kagglers中却极少见。

如果您不熟悉这些工具,则可能需要20多分钟才能添加它们并修复错误和警告。

这次记住,下一个项目中,在开始添加代码前,就把这些检查添加到第一次提交中。 从这时起,每个小提交都会被检查,并且每次最多就修改几行代码,这将会逐渐养成事半功倍的好习惯。

我还建议您读一本书Atomic Habits: An Easy & Proven Way to Build Good Habits & Break Bad Ones. 它谈到了你在行为上的细微变化可以提高生产力和生活质量。

III: +20 min: 创建好的自述(Readme)文件

好的自述文件有两个作用:

  • 对于自己:假设你绝不会再使用此代码(但别轻易说要说绝不)。 您将,而且您将不记得这里发生了什么。 自述文件将为您提供帮助。
  • 对于其他人:自述文件是一个卖点。 如果人们不知道回购的目的和解决的问题,他们将不会使用它。 您所做的所有工作不会对他人产生积极影响。

对于机器学习存储库,最低要求是:

  • 通过可视化的图说明任务是什么以及解决任务的方式。不需要任何文字。项目进行几周后,您很可能在存储栏里已经有了几万张照片,这些并不应该属于readme的一部分,记得处理好它们。
  • 将数据放在哪里。
  • 如何开始训练
  • 如何用模型进行预测。

如果您需要写100500个单词来描述如何进行训练或进行预测,这是一个危险信号。您需要重构代码以提升可读性。人们经常问-我怎样才能成为更好的程序员?重写代码将是很有帮助的练习。尝试从其他人的角度看您的自述文件。这也有助于养成从用户角度看产品的习惯。

就像那句老话:“客户就是上帝。”

示例:对于RetinaFace,我写了一个模型封装程序,来隐藏数据后处理的细节。

后期处理非常复杂,但对不关心它的人们却没有价值=>用户应该能够隐藏它。

IV: +20 min: 使你的训练模型使用更加方便.

人们大概会写以下的代码来读取模型预训练的参数:

model = MyFancyModel()
state_dict = torch.load(<path to weights>)
model.load_state_dict(state_dict)

这样写可以运行,并且步骤清晰, 但也需要我们将权重信息放在了我们的电脑上,并指明它们的具体被放在了哪里。but it requires weights on the disk and knowing where they are. 更优雅的方式是通过使用torchvision里的 torch.utils.model_zoo.load_url函数 (TensorFlow,Keras也有类似函数)
以下代码提供了改善的版本:

from retinaface.pre_trained_models import get_model

model = get_model("resnet50_2020-07-20", max_size=2048)

如果权重并没有存储在本地,它们会先从云端被下载下来并存储在本地,并初始化模型以及加载参数。
这对用户更加友好,这也是torchvision/timm 库的做法。

第一步: 保存预训练模型的权重

这曾是最困扰我的一点:如果你不想用AWS,GCP之类,这些该储存在哪儿呢?
其实,还有一个绝佳的解决方式(或者说漏洞),你可以把这些参数发布在Github(release)上。
在这里插入图片描述
存储上限是每个文件20GB,但这对大部分深度学习模型来说都够了

第二步: 编写函数来初始化模型并加载权重参数

在我来看

当我们构建Colab Notebook和WebApp时,将利用此功能。

V +20 min: 建立一个库

这一步降低了你建立的模型使用要求,换句话说是不使用git clone retinaface来进行预测。

第一步: 在requirements.txt 增加必要的依赖环境参数。

你可以使用:

pip freeze > requirments.txt

或者直接手动更新。

第二步: 调整路径里的文件布局

创建一个‘main folder’,(在此例中,叫‘retinaface’)

  • 把所有重要的codes移到这
  • 不要包含示例图,自述文件,notebooks或者测试文件

手动完成这一步并更新所有imports选项会比较麻烦, pycharm或者类似的ide可以帮你做这些。

这是很常见的重构路径里的代码文件组织方式的做法。

希望以后你可以从项目开始就保持这个习惯,如果你想要更加规范的结构,可以看一下 Cookie Cutter

第三步: 加 config 文件

  • 增加一个 setup.py 到根文件夹,可参考 setup.py
  • 为该库增加一个版本号,在此例子里,我加在了“main” 文件夹里的 init file

第四步: 在PyPI里建立一个账户

是时候有一个自己的PyPI 账号了!

第五步: 建立一个库,并上传到PyPI

python setup.py sdist
python setup.py sdist upload

大功告成。 你成功将你的代码文件变成了一个库,所有人都可以用

pip install <your_library_name>

来安装。

如果你去查看 package’s page at PyPI , 你可以看到他会用你提供的自述(Readme)文件来介绍你的项目。

我们将针对Google Colab和Web App使用此步骤的功能。

VI: +20 min: 建立一个Google Colab Notebook

加一个jupyter notebook到你的Github仓库以解释如何启动,运用你的模型也是很好的习惯。例如这个

通过启用一个炫酷的模型初始化以及前两步中万能的pip install ,我们甚至可以做的很好。

这样,我们就可以创建一个google golab notebook。

现在,人们使用你的model的唯一要求便是一个浏览器!这使更多的人能够接触你的项目。

例如这个

不要忘记在自述文件中添加笔记本的链接并在PyPi上更新版本。

VII: +20 min: 建一个网页应用

很多数据科学家认为建一个网页应用是个很复杂的过程,其中涉及过多的专业知识。

这么想也没错,建一个网页应用自然是个复杂的项目,大多数数据科学家并不是做这个的。
但是建一个简单的网页去展示模型并没那么麻烦。
我建立了一个分离的 GitHub 仓库 给网页应用。当然,你可以放在原路径里。

该博客里的操作细节可供参考:How to Deploy Streamlit on Heroku

第一步: 加入App Code

代码

"""Streamlit web app"""

import numpy as np
import streamlit as st
from PIL import Image
from retinaface.pre_trained_models import get_model
from retinaface.utils import vis_annotations
import torch

st.set_option("deprecation.showfileUploaderEncoding", False)


@st.cache
def cached_model():
    m = get_model("resnet50_2020-07-20", max_size=1048, device="cpu")
    m.eval()
    return m


model = cached_model()

st.title("Detect faces and key points")

uploaded_file = st.file_uploader("Choose an image...", type="jpg")

if uploaded_file is not None:
    image = np.array(Image.open(uploaded_file))
    st.image(image, caption="Before", use_column_width=True)
    st.write("")
    st.write("Detecting faces...")
    with torch.no_grad():
        annotations = model.predict_jsons(image)

    if not annotations[0]["bbox"]:
        st.write("No faces detected")
    else:
        visualized_image = vis_annotations(image, annotations)

        st.image(visualized_image, caption="After", use_column_width=True)

不过40行而已。

第二步: 添加 config文件

以下文件需要添加:

  • setup.sh – 你可直接借用这个模版,不需改变.
  • Procfile – 你需要手动调整一下该文件里的路径参数.

第三步: 增加 requirements.txt

第四步: 在herokuapp上注册

第五步: 推送以下代码

heroku login
heroku create
git push heroku master

大功告成. 详细的例子在https://retinaface.herokuapp.com/

VIII: +4 hrs: 写篇博客吧

很多人都低估了这项工作,他们假设如果他们知道怎么做,所有人都会知道怎么做。事实并非如此。

一个人的垃圾是另一个人的财宝

你的文章可以帮助他人并增加你的求职机会。

我在Lyft Level5工作,并且在自动驾驶问题中应用深度学习技术。在这之前,我在TrueAccord贷款管理公司工作。你可以在我的这篇博客看我怎么找工作的: “Shifting Careers to Autonomous Vehicles.”

我能换方向找到工作的其中一个原因是我在博客和一些会议上分享了我的知识见解。这将会吸引hr的注意。

对于我适用的,也会对你适用

对于机器学习,我会推荐写一段文字介绍:

  • 要解决的问题是什么?
  • 你怎么解决的?

如果你读到这里并且发现这篇文章有用,你就可以尝试写一篇博客来介绍你怎样面对并如何解决一个机器学习问题。

例子:
• 挑战: IEEE’s Signal Processing Society - Camera Model Identification
• 博客: Forensic Deep Learning: Kaggle Camera Model Identification Challenge

IX: Days: 写篇论文来描述你在机器学习挑战中解决的问题

即便你的文章不是巨大突破,它仍然可以被发表并对他人有研究价值。写学术论文是一个不同的技巧,可能是你现在还没有的。但这不是大问题。你可以和那些知道如何以学术界格式写论文的人一起合作。

例子:

只需要看看我的Google Scholar,前几年的迅速增长就是来源于我总结了我参加过的不同机器学习竞赛 。
在这里插入图片描述

此外,你也不仅仅只会写一篇论文。你的论文应该和这些东西一起:

  • Github仓库来存储干净的代码和详细的ReadMe自述文件。
  • library让那些不会机器学习的人都能使用。
  • Colab notebook能让你的模型快速地在浏览器中运行。
  • 网页应用展示给非技术人员。
  • 博客能用自然语言讲述了整个项目流程。

这就不仅仅是一篇论文了,这是一个展示你“所有权”和“交流能力”的周密策略。至于这两点如何影响你的职业发展,且听下回分解。😃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值