选自 | medium

作者 | Vladimir Iglovikov

转自 | 机器之心

那些被遗忘的竞赛项目代码、权重可能也是一笔宝藏。

很多人可能参加过许多比赛,做过许多项目,但比赛或项目结束之后,曾经写过的代码、用过的模型就被丢到了一边,甚至不久就被删掉。

这种情况并不只存在于比赛中,在学术领域同样存在。当学生训练完模型、写完论文并被学术会议接收后,该模型的 pipeline 就会被抛弃,训练数据也随之被删除。这是不是有点太可惜了?

长期参加 Kaggle 比赛的 Vladimir Iglovikov 在自己的博客中指出了这个问题,并提出了一些重新利用这些资源的建议。

Vladimir Iglovikov 是一位 Kaggle Grandmaster,曾在 Kaggle 全球榜单中排名第 19,拿到过 Carvana 图像遮蔽挑战的冠军(他的个人经历参见:《Kaggle Grandmaster 是怎样炼成的》)。

在他看来,竞赛中曾经用到的代码、权重等资源是一笔宝贵的财富,可以帮助你巩固技术知识、树立个人品牌、提高就业机会

为了解释这些资源资源的价值,他还专门创建了一个 GitHub 项目(retinaface)来讲述文本的建议。

项目链接:https://github.com/ternaus/retinaface

以下是博客的具体内容。

花 5 分钟将代码发布到公开的 GitHub 存储库

很多时候,你的代码可能已经存到 GitHub 上了,但是是存在私人库里。那公开又有什么损失呢?

某些情况下,有些代码确实不宜公开,但你在 Kaggle 里做的那些练手项目、解决方案和论文或许没这个必要。

为什么有些人不愿公开呢?因为很多人认为,「所有公开发布的代码都应该是完美的,否则就会遭到批判。」

但实际情况是,其他人根本不 care,你只管发布就行。

公开代码是心理防线的一次重大突破,公开不完美的代码更是一个自信、大胆的举动。所有后续步骤也都在这一步的基础上展开。

花 20 分钟提升代码可读性

你可以通过添加语法格式化工具和检查工具来提升 python 代码的可读性。

这并不困难,也并不费时。检查工具和格式化程序不会将烂代码变成好代码,但其可读性会有所提升。以下是具体步骤:

步骤 1:文件配置

将这些文件添加到存储库的根目录。

  • setup.cfg — flake8 和 mypy 的配置。

  • pyproject.toml — black 的配置。

步骤 2:requirements

用以下命令安装所需的库:

pip install black flake8 mypy

步骤 3:black

格式化代码的方法有 100500 多种。诸如 black 或 yapf 之类的格式化工具会按照一组预定义的规则来修改代码。

阅读具有一定标准的代码库会更加容易。当你花费几个小时编写代码并需要在不同的编码风格之间切换语境时,你的意志力会被消耗殆尽。因此,没有充分的理由就不要这么做。

运行以下命令将重新格式化所有的 python 文件以遵循 black 的规则。

black .

步骤 4:flake8

运行以下命令不会修改代码,但会检查代码中的语法问题并将其输出到屏幕上。然后修改这些问题。

flake8

步骤 5:mypy

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

class MyModel(nn.Module):....def forward(x: torch.Tensor) -> torch.Tensor:....return self.final(x)

你应该在代码中添加键入内容。这会让代码读起来更容易。你可以使用 mypy 包检查参数和函数类型的一致性。更新代码后,在整个存储库上运行 mypy:

mypy .

如果 mypy 出现问题,修复它们。

步骤 6:预提交钩子(hook)

一直手动运行 flake8、black 和 mypy 会觉得厌倦。一个名为 pre-commit 的钩子能够解决这个问题。要启用它,可以将以下文件复制到你的存储库中:https://github.com/ternaus/retinaface/blob/master/.pre-commit-config.yaml

你需要使用以下命令安装 pre-commit 包。

pip install pre-commit

使用以下命令进行初始化:

pre-commit install

安装完成后,每次提交都会经历一组检查。当提交中有错误时,检查不会允许提交通过。这和手动运行 black、flake8 以及 mypy 的不同之处在于,它不会乞求你修复问题,而是强制要求你做这件事。因此,这种方法不会浪费你的意志力、

步骤 7:Github 操作

你已经向 pre-commit 钩子中添加了检查步骤,并在本地运行了这些步骤。但是你还需要第二道防线——让 GitHub 在每个拉取请求上运行这些检查步骤。

你要做的就是将以下文件添加到存储库中:https://github.com/ternaus/retinaface/blob/master/.github/workflows/ci.yml

执行以下代码来告诉 GitHub 要检查什么:

- name: Install dependenciesrun: |python -m pip install --upgrade pippip install -r requirements.txtpip install black flake8 mypy- name: Run blackrun:black --check .- name: Run flake8run: flake8- name: Run Mypyrun: mypy retinaface

我还建议放弃将代码直接推送到 master 分支的做法。你可以创建一个新的分支、修改代码、提交、放到 Github 上、创建 PR 请求,然后合并到 master。这是一项行业标准,但是在学术研究和 Kaggle 参赛者中却不常见。如果你对这些工具不熟悉,可能需要花 20 分钟添加它们并修复错误和警告。

记住这次的操作。在下个项目中,你可以在没写代码之前就在第一次提交中添加这些检查。从这个时候开始,每次小的提交都会被检查,你每次最多只需要修复几行代码。这么做开销很小,也是一个良好的习惯。

花 20 分钟写一个优秀的 readme

好的 readme 有两个作用:

  • 对你自己而言:可能你认为你永远都不会再用到这些代码了,但实际上并不一定。下次用的时候你可能也记不得它的具体内容了,但 readme 可以帮到你。

  • 对其他人而言:readme 是一个卖点。如果人们看不出该存储库的用途以及它所解决的问题,大家就不会使用它,你所做的所有工作都不会对他人产生积极影响。

一个机器学习库的最低要求是说明以下问题:

  • 用一张图来说明任务是什么以及如何解决,而不需要任何文字。在花了几周解决问题之后,你可能有 100500 张图,但你不能把他们放在 readme 里;

  • 数据放在哪里;

  • 怎样开始训练;

  • 如何进行推理。

如果你需要写 100500 个词来描述怎样运行训练或者推理,那就说明你的项目存在问题了。你需要重构代码,使它对用户更加友好。

人们经常会问:如何提高写代码的能力?这便是一个锻炼你的机会。你可能需要重写代码,尝试站在别人的角度看待你的 Readme。

这是一个很好的锻炼机会,它能够让你学会从用户的角度看待问题。

花 20 分钟提高模型易用性

我猜你会编写如下代码来加载预训练模型权重。

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

这样的方法虽然有用且步骤清晰,但是它需要磁盘上的权重,并且要知道它们的位置。一个更好的解决方案是在 TensorFlow 或 Keras 上使用 torchvision 中的 torch.utils.model_zoo.load_url 函数:

from retinaface.pre_trained_models import get_model
model = get_model("resnet50_2020-07-20", max_size=2048)

用上面的代码从 retinaface.pre_trained_models 中引入 get_modelmodel = get_model("resnet50_2020-07-20", max_size=2048)。

如果权重不在磁盘上,那就会从网络上先下载下来再缓存到磁盘上。初始化模型,并加载权重,这对用户来说是很友好的,也是你在 torchvision 和 timm 库中所看到的。

步骤 1:托管预训练模型的权重

这对我来说是最大的障碍。如果不想使用 AWS、GCP,我要把模型的权重放在哪里?GitHub 上的 releases 是一个不错的选择。

每个文件的大小限制是 2Gb,对大多数深度学习模型来说够用了。

步骤 2:编写一个初始化模型和加载权重的函数。

我给出的示例代码如下:

# https://github.com/ternaus/retinaface/blob/master/retinaface/pre_trained_models.py from collections import namedtuple from torch.utils import model_zoo from retinaface.predict_single import Model model = namedtuple("model", ["url", "model"]) models = { "resnet50_2020-07-20": model( url="https://github.com/ternaus/retinaface/releases/download/0.01/retinaface_resnet50_2020-07-20-f168fae3c.zip", # noqa: E501 model=Model, ) } def get_model(model_name: str, max_size: int, device: str = "cpu") -> Model: model = models[model_name].model(max_size=max_size, device=device) state_dict = model_zoo.load_url(models[model_name].url, progress=True, map_location="cpu") model.load_state_dict(state_dict) return model

在构建 Colab Notebook 和 WebApp 时会用到这个函数。

花 20 分钟创建一个库

这一步是为了降低你模型的入口点。

步骤 1:向 requirements.txt 中添加必要的依赖,你可以手动更新或使用如下代码:

pip freeze > requiements.txt

步骤 2:改变存储库的文件结构

创建一个「主文件夹」,在我给出的示例中,这个文件夹叫「retinaface」。

将所有重要代码都放进这个文件夹,但不要把 helper 图像、Readme、notebook 或 test 放进去。手动操作这一步骤并更新所有的 import 会很累。PyCharm 或者类似的 IDE 会为你执行这一步骤。

这是存储库中构建代码结构的常用方法。如果你想让其更加结构化,请查看 Cookie Cutter 包。

步骤 3:添加配置文件

向根目录中添加 setup.py,内容类似于示例文件「setup.py」中的内容。添加包的版本,在我的示例中,我将它添加到了主文件夹的 init 文件中。

步骤 4:在 PyPI 上创建一个账户。

步骤 5:搭建一个库并上传到 PyPI 上。

python setup.py sdist
python setup.py sdist upload

你的存储库是一个库,每个人都可以使用如下命令安装它:

pip install <your_library_name>

如果你在 PyPI 上查看包的页面,你就会看到它使用你存储库中的 Readme 文件来陈述项目。我们将会在 Google Colab 和 Web App 上使用这一步的功能。

花 20 分钟创建 Google Colab notebook

将 Jupiter notebook 添加到存储库是一个好习惯,以展示如何初始化模型和执行推理功能。

在前两个步骤中,我们使用了模型初始化和 pip install。接下来创建 Google Golab notebook。

现在,只需要一个浏览器,就会有更多的人尝试你的模型了。别忘了在 readme 中添加 notebook 的链接,并在 PyPi 上更新版本。

花 20 分钟创建 WebApp

许多数据科学家认为构建 web 应用程序是一个复杂的过程,需要专业知识。这种想法是正确的。一个复杂项目的 web 应用程序确实需要很多数据科学家并不具备的专业知识,但构建一个简单的 web 应用程序来展示模型还是很容易的。

我为一个 web 应用程序创建了一个单独的 GitHub 存储库。不过,你仍然可以在你的存储库中用你的模型来操作。这里有一篇描述具体细节的技术博客:https://towardsdatascience.com/deploy-streamlit-on-heroku-9c87798d2088。

步骤 1:为应用程序添加代码:

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

步骤 2:添加配置文件

你需要添加以下文件:

  • setup.sh — 该文件可以直接使用,不需要更改。

  • Procfile — 你需要使用应用程序修改文件的路径。

步骤 3:添加 requirements.txt 文件

步骤 4:在 herokuapp 上注册

步骤 5:执行以下代码:

heroku login
heroku create
git push heroku master

花 4 小时写一篇技术博客

很多人低估了他们研究的价值。实际上你的文章很可能能够帮助别人,并且能够为自己的职业生涯提供更多的机会。

如果要写机器学习方面的文章,我建议你包含以下内容:

  • 研究问题是什么?

  • 你是如何解决这个问题的?

示例如下:

  • 项目:https://www.kaggle.com/c/sp-society-camera-model-identification

  • 博客:http://ternaus.blog/machine_learning/2018/12/05/Forensic-Deep-Learning-Kaggle-Camera-Model-Identification-Challenge.html

花时间写篇论文,描述你在这场机器学习竞赛中的解决方案

即使你的论文中没有重大突破,它也会被发表并帮到别人。撰写学术论文也是一项技能。你现在可能还不具备这种技能,但你可以与擅长学术写作的人合作。

下面是我的 Google Scholar 引用情况,这几年引用量的猛增都得益于我写的那些总结机器学习竞赛的论文。

当然,你的论文也包含在一个大包里,这个包里还有:

  • GitHub 存储库,里面有整洁的代码和良好的 readme 文件。

  • 非机器学习人员能够使用的库。

  • 允许在浏览器中用你的模型进行快速实验的 Colab notebook。

  • 吸引非技术受众的 WebApp。

  • 用人类语言讲故事的博客文章。

有了这些之后,它就不再只是一篇论文,而是一种综合性的策略,可以显示你对该项目的所有权,还能帮助你与他人进行沟通。这两者对于你的职业生涯都是至关重要的。

原文链接:https://medium.com/kaggle-blog/i-trained-a-model-what-is-next-d1ba1c560e26


感谢你的分享,点赞,在看三连↓

竞赛比完,代码、模型怎么处理?Kaggle 大神:别删,这都是宝藏相关推荐

  1. 印度裔Kaggle大神自述:我是如何获得所有4个类别的Grandmaster

    杨净 发自 凹非寺 量子位 报道 | 公众号 QbitAI Kaggle大神是如何炼成的? 最近,一个印度裔Kaggle大神在论坛上分享了他获得4个类别的Grandmaster的经历. 嗯,一共就只有 ...

  2. 独家 | Kaggle 大神Dan Becker与你分享他的数据科学之旅!

    作者:ANALYTICS VIDHYA 翻译:吴振东 校对:和中华 本文约4000字,建议阅读10分钟 本文中Kaggle大佬Dan Becker谈论了自己从经济学向数据科学的转变,从零开始成为数据科 ...

  3. 《第一行代码》作者郭霖大神安卓问题解答

    列举了几个郭大神解答的有关Android的问题,虽然只有几个问题,但是基本涵盖了各个安卓开发阶段的困惑,郭大神的回答简洁深刻,收获颇丰. 1.工作有点吃力怎么办? 首先你要自信,公司都信任你了,你又何 ...

  4. Kaggle大神:竞赛代码别删,这都是宝藏

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 选自medium 作者:Vladimir Iglovikov 机器之心编译 那些被遗忘 ...

  5. Kaggle 大神 Eureka 的高手进阶之路

    转自:https://baijiahao.baidu.com/s?id=1594269125827729365&wfr=spider&for=pc 雷锋网 AI 研习社按:作为全球首屈 ...

  6. java连接数据库代码写在哪里,jdbc连接数据库怎么做的。代码写哪里呀 求大神

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 我在网上找了这个代码.是不是只要打开myslese 建一个类 复制进去就可以了. import java.awt.*; import java.awt.e ...

  7. 编程开发工具一览:新手到大神,程序员都用什么写代码?

    俗话说的好:工欲善其事,必先利其器.一款好的开发工具对程序员来说是至关重要的,可以降低开发成本.提高开发的效率和代码质量. 所以今天分享一些主流的编程开发工具,基本都是我曾经或正在使用的,附带一些使用 ...

  8. python恶搞代码打开对方摄像头_大神们救命啊!!如何实现把摄像头读入的视频在tk界面呈现出来?...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这里 找到一个 代码..可以仿照来 import wx import wx.xrc import VideoCapture ############### ...

  9. 白嫖GPU!Kaggle大神带你打比赛!

    小白怎么从0入门打比赛?(文末有GPU福利~) 第一步先解决赛题选择的问题:什么样的比赛适合你入门? 我建议想打比赛的同学首先想明白一件事--你想从事什么方向?人的精力是有限的,与其面面俱到,不如在1 ...

最新文章

  1. 弃用消息队列!这个新一代消息系统,腾讯、华为都用疯了?
  2. python多态_多态是什么?为什么要使用多态?
  3. 【python opencv 计算机视觉零基础到实战】二、 opencv文件格式与摄像头读取
  4. c#设计一个方法,与使用
  5. 秘籍分享:如何将负载均衡按量付费实例转换为包年包月实例
  6. jeecg标签属性exp 用法
  7. 4x4矩阵键盘工作原理及扫描程序_基于复杂可编程逻辑器件实现键盘接口电路的设计...
  8. 作者:​林旺群(1983-),男,博士,北京系统工程研究所助理研究员。
  9. 网络基础---IP编址
  10. 使用docker-compose 大杀器来部署服务 上(转)
  11. python实现自动化打印
  12. 【FME】常见转换器功能介绍
  13. 极速office(excel)根据身份证号如何提取年龄
  14. sendto 函数中的struct iov_iter结构 (linux-5.0)
  15. centos查询 硬盘序列号查询_centos 查看硬盘SMART健康信息
  16. 正确理解jmeter线程组之Ramp-Up
  17. oracle创建用户并授权管理员,Oracle创建用户并授权【数据库】
  18. 322. Coin Change
  19. ASP.NET MVC 音乐商店 - 2.控制器
  20. 分布式系统之CAP和BASE理论

热门文章

  1. 【青少年编程】绘制五角星
  2. 【怎样写代码】确保对象的唯一性 -- 单例模式(六):扩展案例
  3. Python 中少为人知的 10 个安全陷阱
  4. 终于有人把 Python 讲清楚了!
  5. 60分钟看懂HMM的基本原理
  6. 程序员:我受够了!不想再在小厂里干Java了!
  7. 200 个工具分析机器学习十年:开源是大势,工程师是核心
  8. 多场景下的AI疫情防控“天网”:解读云边端联动下的全栈AI技术
  9. 人工智能时代,开发者是逆袭还是走向末日?
  10. 逼疯懒癌:“机器学习100天大作战”正式开始!