Keras 之父的新年清单,2019 你值得拥有
By 超神经
这篇长长的清单是 Keras 的发明人 Francois Chollet 曾发布在自己 Medium 上的一篇博客,记录了他在十多年的科研和职业生涯中的研发工作上经验总结。
这列清单被他自己称为「A laundry list of personal reminders」。本篇文章提供中英对照版本,并在文末附上 Keras 的常用功能记忆手册,以帮助大家阅读和理解。
开发中注意事项
Code isn’t just meant to be executed. Code is also a means of communication across a team, a way to describe to others the solution to a problem. Readable code is not a nice-to-have, it is a fundamental part of what writing code is about. This involves factoring code clearly, picking self-explanatory variable names, and inserting comments to describe anything that’s implicit.
你写的代码不仅是被你自己运行的。代码也是一种跨团队交流的方式,一种是向同事和用户描述一个问题解决方案的方式。易读的代码并不是「有就更好、没有也行」的东西,而是编写代码最重要的部分之一。要想确保代码的易读性,就涉及到清晰地分解代码、选择恰当的自解释变量名、通过添加注释来描述所有隐含内容。
Ask not what your pull request can do for your next promotion, ask what your pull request can do for your users and your community. Avoid “conspicuous contribution” at all cost. Let no feature be added if it isn’t clearly helping with the purpose of your product.
不要只想着你的pull request,能为你的下一次职场晋升带来什么帮助,而要想着你的能为你的用户和社区带来什么。如果一项功能对于实现这个产品想要实现的目的没有明显的帮助,就不要添加这个功能。
Taste applies to code, too. Taste is a constraint-satisfaction process regularized by a desire for simplicity. Keep a bias toward simplicity.
保持简单。
It’s okay to say no — just because someone asks for a feature doesn’t mean you should do it. Every feature has a cost that goes beyond the initial implementation: maintenance cost, documentation cost, and cognitive cost for your users. Always ask: Should we really do this? Often, the answer is simply no.
学会拒绝。并不是说有人要求做某个功能就意味着你就应该这么做。开发每个功能都需要投入一定的成本:维护成本、文档成本和用户认知成本。要时刻问自己这样的问题:我们真的应该这样做吗? 答案通常是否定的。
When you say yes to a request for supporting a new use case, remember that literally adding what the user requested is often not the optimal choice. Users are focused on their own specific use case, and you must counter this with a holistic and principled vision of the whole project. Often, the right answer is to extend an existing feature.
当你准备答应满足对一个新的使用场景的支持时,要知道添加用户表面上需要满足的需求通常不是最好的办法。用户关注的是他们自己的特定使用场景,你必须从整个项目的角度出发,兼顾产品的整体愿景。通常,正确的做法是基于现有的功能特性进行拓展;
Invest in continuous integration and aim for full unit test coverage. Make sure you are in an environment where you can code with confidence; if that isn’t the case, start by focusing on building the right infrastructure.
投入精力持续集成,以实现完整的单元测试覆盖为目标。确保你处在一个可以信心满满地写代码的环境中;如果不是这样,你首先需要构建一个正确的基础架构。
It’s okay not to plan everything in advance. Try things and see how they turn out. Revert incorrect choices early. Make sure you create an environment where that is possible.
不一定非要提前规划好一切。先测试一下,看看效果怎样。这样可以尽早避免做出错误的选择。当然,你首先要确保打造了易用稳定全面的开发环境。
Good software makes hard things easy. Just because a problem looks difficult at first doesn’t mean the solution will have to be complex or hard to use. Too often, engineers go with reflex solutions that introduce undesirable complexity (Let’s use ML! Let’s build an app! Let’s add blockchain!) in situations where a far easier, though maybe less obvious, alternative is available. Before you write any code, make sure your solution of choice cannot be made any simpler. Approach everything from first principles.
好的软件能让困难的事情变得简单。一个问题第一眼很困难,并不意味着对应的解决方案必须很复杂或难用。在很多情况下,工程师会习惯性给出的解决方案非常复杂,而实际上是有更简单容易的解决方案的,只是这个简单的解决方案可能没那么显而易见。在编写代码之前,请确保你所选择的解决方案是最简单的解决方案。
Avoid implicit rules. Implicit rules that you find yourself developing should always be made explicit and shared with others or automated. Whenever you find yourself coming up with a recurring, quasi-algorithmic workflow, you should seek to formalize it into a documented process, so that other team members will benefit from the experience. In addition, you should seek to automate in software any part of such a workflow that can be automated (e.g., correctness checks).
避免隐性规则。要将你形成的所有隐性规则都变成显性规则,并与他人共享,或让它自动化。当你发现自己提出了一个反复出现的、准算法工作流时,你应该想办法将这个流程标准化并形成流程文档固定下来,这样其他团队成员也能够从中受益。此外,对于可以自动化的工作流,你应该在软件中尽量让其自动化。
The total impact of your choices should be taken into account in the design process, not just the bits you want to focus on — such as revenue or growth. Beyond the metrics you are monitoring, what total impact does your software have on its users, on the world? Are there undesirable side effects that outweigh the value proposition? What can you do to address them while preserving the software’s usefulness?
在设计过程中,要将所选择方案的整体影响考虑进去,而不仅仅考虑营收或增长。除了已经监控的指标外,软件对用户以及整个世界还会产生哪些影响? 是不是存在一些不好的副作用? 在确保软件可用性的同时,你能做什么来解决这些问题呢?
如何写一个更好的 API?
Your API has users, thus it has a user experience. In every decision you make, always keep the user in mind. Have empathy for your users, whether they are beginners or experienced developers.
你的 API 是有用户的,因此它也涉及到用户体验。在你做的每一个决策中,都要将用户考虑进去。要站在用户的角度考虑问题,无论用户是小白还是经验丰富的开发人员。
Always seek to minimize the cognitive load imposed on your users in the course of using your API. Automate what can be automated, minimize the actions and choices needed from the user, don’t expose options that are unimportant, design simple and consistent workflows that reflect simple and consistent mental models.
要尽量减少用户在使用产品 API 过程中存在的认知负荷。自动化所有可以自动化的步骤,让用户需要做的操作和选择最少化,不显示不重要的选项,设计能反映简单一致思维模型的简单一致的工作流。
Simple things should be simple, complex things should be possible. Don’t increase the cognitive load of common use cases for the sake of niche use cases, even minimally.
简单的事情要简单处理,复杂的事情尽可能简单化。不要为了少量特殊的使用场景而增加普通使用场景的认知负荷。
If the cognitive load of a workflow is sufficiently low, it should be possible for a user to go through it from memory (without looking up a tutorial or documentation) after having done it once or twice.
如果一个工作流的认知门槛足够低,那么用户在使用一两次后就能够凭感觉和记忆完成操作 ,而无需查找教程文档。
Seek to have an API that matches the mental models of domain experts and practitioners. Someone who has domain experience, but no experience with your API, should be able to intuitively understand your API using minimal documentation, mostly just by looking at a couple of code examples and seeing what objects are available and what their signatures are.
努力做出与领域专家和实践者的心智模型相匹配的 API。有领域经验但没有使用过你的API 的人应该通过借助最少的说明文档就能直观地了解你的 API, 比如通常通过查看一些代码示例、看看哪些对象可用以及它们的特征是什么就能很好地了解你的 API。
The meaning of an argument should be understandable without having any context about the underlying implementation. Arguments that have to be specified by users should relate to the mental models that the users have about the problem, not to implementation details in your code. An API is all about the problem it solves, not about how the software works in the background.
一个参数的含义应该在不需要任何关于底层实现背景信息的情况下就能很容易理解。必须由用户指定的参数应该与用户关于这个问题的模型相关,而不是与代码中的实现细节相关。API 的核心在于它要解决的问题,与软件在后台的工作流程是没有关系的。
The most powerful mental models are modular and hierarchical: simple at a high level, yet precise as you need to go into details. In the same way, a good API is modular and hierarchical: easy to approach, yet expressive. There is a balance to strike between having complex signatures on fewer objects, and having more objects with simpler signatures. A good API has a reasonable number of objects, with reasonably simple signatures.
最强大的模型是模块化、有层次化的:在高层次上很简单,在细节上很精确。同理,一个好的 API 也应该是模块化和层次化的:容易使用、富有表现力。一个好的 API 要有合理数量的对象,并具有简单的特性。
Your API is inevitably a reflection of your implementation choices, in particular your choice of data structures. To achieve an intuitive API, you must choose data structures that naturally fit the domain at hand — that match the mental models of domain experts.
你的 API 是你选择的实现方式的必然反映,特别是你选择的数据结构。要实现一个直观的 API,你必须选择适合相关领域的数据结构,即与领域专家的模型相匹配。
Deliberately design end-to-end workflows, not a set of atomic features. Most developers approach API design by asking: What capabilities should be available? Let’s have configuration options for them. Instead, ask: What are the use cases for this tool? For each use case, what is the optimal sequence of user actions? What’s the easiest API that could support this workflow?Atomic options in your API should answer a clear need that arises in a high-level workflow — they should not be added “because someone might need it.”
要有意识地设计端到端工作流,而非一组原子特性。大多数开发人员在设计 API 时都会问:应该提供哪些功能特性? 让我们为这些功能提供配置选项吧。实际上,开发人员正确的问法应该是:这个工具的使用场景有哪些? 对于每个使用场景,用户的最佳操作顺序是什么? 能够支持这个工作流的最简单的 API 是什么?
Error messages, and in general any feedback provided to a user in the course of interacting with your API, is part of the API. Interactivity and feedback are integral to the user experience. Design your API’s error messages deliberately.
报错以及在与 API 交互过程中向用户提供的任何反馈都是 API 的一部分。交互性和反馈是用户体验中不可缺少的一部分。你需要谨慎的设计 API 的出错消息。
Because code is communication, naming matters — whether naming a project or a variable. Names reflect how you think about a problem. Avoid overly generic names (x, variable, parameter), avoid OverlyLongAndSpecificNamingPatterns, avoid terms that can create unnecessary friction (master, slave), and make sure you are consistent in your naming choices. Naming consistency means both internal naming consistency (don’t call “dim” what is called “axis” in other places) and consistency with established conventions for the problem domain. Before settling on a name, make sure to look up existing names used by domain experts (or other APIs).
因为代码就是交流,因此命名很重要,不管是命名项目还是命名变量都是如此。名称反映了你对一个问题的思考方式。避免使用过于通用的名称,避免使用过于冗长的命名模式,避免使用可能造成不必要误解的术语 ,确保你的命名选择上是前后一致的。命名一致性既意味着内部命名一致性,也意味着与该问题所在领域的既定规范保持一致。在确定名称之前,请确保查找该领域专家已经在使用的名称。
Documentation is central to the user experience of your API. It is not an add-on. Invest in high-quality documentation; you will see higher returns than investing in more features.
文档是 API 用户体验的关键。它不是一个附加部件。投入精力写出高质量的文档,这能带来的回报比开发更多功能带来的回报更高。
Show, don’t tell: Your documentation should not talk about how the software works, it should show how to use it. Show code examples for end-to-end workflows; show code examples for each and every common use case and key feature of your API.
告诉用户不如直接表现给用户:你的文档不应该讨论软件是如何工作的,而是应该直接展示如何使用这个软件。展示端到端工作流的代码示例;为你的API 的每个常见使用场景和关键特性展示代码示例。
如果 Keras 有考试,我已经准备好了小抄
超神经百科
单词
univariate
[ju:nɪ'veərɪrt] adj. 单变量的
multivariate
[mʌltɪ'veərɪɪt] adj. 多变量的
词组
logistic regression 逻辑回归
service implementation 服务实现
历史文章(点击图片阅读)
一个宇宙学实验验证,整个宇宙都是高级文明编写的代码?
让计算机教授找回被劫车辆的贪心算法,究竟多实用?
如果重新读大学,你会选择 AI 专业么?
AI 百科
教程
数据集
商店
更多
http://hyper.ai