GitHub 热门:机器学习 100 天(中文版)

(给Python开发者加星标,提升Python技能

100 Days Of ML Code (机器学习 100 天英文版)刚出来时,我们推荐过。目前英文版已经快 20k Stars 了。

 

后来有人跟进翻译成中文版。所以今天再次推荐,喜欢的读者,请收藏。

 

https://github.com/Avik-Jain/100-Days-of-ML-Code-Chinese-Version

GitHub 热门:机器学习 100 天(中文版)

GitHub 热门:机器学习 100 天(中文版)

GitHub 热门:机器学习 100 天(中文版)


GitHub 链接:

https://github.com/Avik-Jain/100-Days-of-ML-Code-Chinese-Version

中文版,已同步更新到第 54 天了!

 

GitHub 热门:机器学习 100 天(中文版)

转自:https://mp.weixin.qq.com/s/vtslaWecAVyuf5aaZcRrsg

清华开源「天授」强化学习平台,纯PyTorch实现

来源:机器之心

训练模型的极速,与 1500 行源代码的精简,清华大学新开源强化学习平台「天授」。值得注意的是,该项目的两位主要作者目前都是清华大学的本科生。
是否你也有这样的感觉,成熟 ML 工具的源码很难懂,各种继承与处理关系需要花很多时间一点点理清。在清华大学开源的「天授」项目中,它以极简的代码实现了很多极速的强化学习算法。重点是,天授框架的源码很容易懂,不会有太复杂的逻辑关系
项目地址:https://github.com/thu-ml/tianshou
天授(Tianshou)是纯 基于 PyTorch 代码的强化学习框架,与目前现有基于 TensorFlow 的强化学习库不同,天授的类继承并不复杂,API 也不是很繁琐。最重要的是,天授的训练速度非常快,我们试用 Pythonic 的 API 就能快速构建与训练 RL 智能体。
目前天授支持的 RL 算法有如下几种:
  • Policy Gradient (PG)

  • Deep Q-Network (DQN)

  • Double DQN (DDQN) with n-step returns

  • Advantage Actor-Critic (A2C)

  • Deep Deterministic Policy Gradient (DDPG)

  • Proximal Policy Optimization (PPO)

  • Twin Delayed DDPG (TD3)

  • Soft Actor-Critic (SAC)

另外,对于以上代码天授还支持并行收集样本,并且所有算法均统一改写为基于 replay-buffer 的形式。
速度与轻量:「天授」的灵魂
天授旨在提供一个高速、轻量化的 RL 开源平台。下图为天授与各大知名 RL 开源平台在 CartPole 与 Pendulum 环境下的速度对比。所有代码均在配置为 i7-8750H + GTX1060 的同一台笔记本电脑上进行测试。值得注意的是,天授实现的 VPG(vanilla policy gradient)算法在 CartPole-v0 任务中,训练用时仅为 3 秒。

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

以上测试使用了 10 个不同的 seed。CartPole 和 Pendulum 任务中的累积奖赏阈值分别设置为 195.0 与-250.0。可能会有读者感觉这两个任务比较简单,不太能突出框架的优势。该项目也表示,在这几天内,他们会更新天授在 Atari Pong / Mujoco 任务上的性能。
天授,只需 1500 行代码
非常令人惊讶的是,天授平台整体代码量不到 1500 行,其实现的 RL 算法大多数都少于百行代码。单从数量上来说,这样的代码量已经非常精简了,各种类与函数之间的关系应该也容易把握住。
项目表示,天授虽然代码量少,但可读性并不会有损失。我们可以快速浏览整个框架,并理解运行的流程与策略到底是什么样的。该项目提供了很多灵活的 API,例如可以便捷地使用如下代码令策略与环境交互 n 步:
result = collector.collect(n_step=n)
或者,如果你想通过采样的批量数据训练给定的策略,可以这样写:
result = policy.learn(collector.sample(batch_size))
正是通过大量精简的 API 构造 RL 模型,天授才能保持在 1500 行代码内。例如我们可以看看 DQN 的模型代码,它是非常流行的一种强化学习模型,在天授内部,DQN 模型真的只用了 99 行代码就完成了。当然,这 99 行代码是不包含其它公用代码块的。
如下为 DQN 的主要代码结构,我们省略了部分具体代码,各个 RL 策略都会继承基本类的结构,然后重写就够了。可以发现,在常规地定义好模型后,传入这个类就能创建策略。DQN 策略的各种操作都会写在一起,后续配置 Collector 后就能直接训练。

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

项目作者把所有策略算法都模块化为 4 部分:
  • __init__:初始化策略

  • process_fn:从 replay buffer 中处理数据

  • __call__:给定环境观察结果计算对应行动

  • learn:给定批量数据学习策略

实际体验
天授很容易安装,直接运行「pip install tianshou」就可以。下面我们将该项目克隆到本地,实际测试一下。
!git clone https://github.com/thu-ml/tianshou
!pip3 install tianshou
import os
os.chdir('tianshou')
该项目在 test 文件夹下提供了诸多算法的测试示例,下面我们在 CartPole 任务下逐个测试一番。
!python test/discrete/test_pg.py

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

!python test/discrete/test_ppo.py

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

!python test/discrete/test_a2c.py

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

!python test/discrete/test_dqn.py

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

以上分别为 VPG、PPO、A2C 与 DQN 在 P100 GPU 上的训练结果。可以看到,我们的测试结果与项目提供的结果出入不大。
由于 CartPole 任务在强化学习中相对简单,相当于图像识别中的 MNIST。为更进一步测试该 RL 框架的性能,我们也在 MinitaurBulletEnv-v0 任务中对其进行了测试。
Minitaur 是 PyBullet 环境中一个四足机器人运动控制任务,其观测值为该机器人的位置、姿态等 28 个状态信息,控制输入为电机的转矩(每条腿 2 个电机,总共 8 个电机),策略优化的目标为最大化机器人移动速度的同时最小化能量消耗。也就是说,agent 需要根据奖赏值自主地学习到由 28 个状态信息到 8 个控制输入的映射关系。

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

使用 SAC 算法在 Minitaur 任务中的训练结果如下图所示:

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

需要注意的是,天授的 SAC 实现在 Minitaur 任务中仅训练了不到 200k 步即能获得以上控制策略,效果可以说是很不错的。
项目作者,清华本科生
在 GitHub 中,其展示了该项目的主要作者是 Jiayi Weng 与 Minghao Zhang,他们都是清华的本科生。其中 Jiayi Weng 今年 6 月份本科毕业,在此之前作为本科研究者与清华大学苏航、朱军等老师开展强化学习领域的相关研究。Minghao Zhang 目前是清华大学软件学院的本科二年级学生,同时还修了数学专业。

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

作为本科生,该项目的两位作者已经有了非常丰富的研究经验,Jiayi Weng 去年夏季就作为访问学生到访 MILA 实验室,并与 Yoshua Bengio 开展了关于意识先验相关的研究。在 Jiayi Weng 的主页中,我们可以看到在本科期间已经发了 IJCAI 的 Oral 论文。

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

Minghao Zhang 也有丰富的研究经验,之前他在软件学院 iMoon Lab 做关于 3D 视觉相关的研究,而后目前在清华交叉信息学院做研究助理,从事强化学习方面的研究。尽管离毕业还有不短的时间,Minghao Zhang 已经做出了自己的研究成果。

来自本科生的暴击:清华开源「天授」强化学习平台,纯PyTorch实现

所以综合来看,因为在本科已经有了丰富的科研经验,并且做过多个项目,那么在这个阶段能做一个非常不错的强化学习开源项目也就理所当然了。
接下来的工作
天授目前还处于初期开发阶段,尚有一些未实现的功能或有待完善的地方。项目作者表示今后主要在以下几个方面来完善该 RL 框架:
  • Prioritized replay buffer

  • RNN support

  • Imitation Learning

  • Multi-agent

  • Distributed training

它们分别是提供更多 RL 环境的 benchmark、优先经验回放、循环神经网络支持、模仿学习、多智能体学习以及分布式训练。

2019 年 10 大顶级 Python 支持库

来自公众号:Python大咖谈

原文作者:Fabián Torres

原文链接:https://tryolabs.com/blog/2019/12/10/top-10-python-libraries-of-2019/

欢迎回来,这是我们第五次推出年度顶级 Python 支持库榜单。在这里,我们列出了隐匿于开源世界里的瑰宝,既可以帮你启动新的项目,也可以为你现有的项目添光加彩。本榜单覆盖了各个领域,包括机器学习与非机器学习的支持库。

希望你能和我们一样喜欢本年度的顶级支持库榜单,话不多说,题归正文!

1. HTTPX

2019 年 10 大顶级 Python 支持库

项目网址:
https://www.encode.io/httpx/

经常进行 API 交互的 Python 忠粉,对 requests 应该是运用自如了。不过,对于日趋普及的现代高性能应用而言,在用到异步范式时,requests 就显得有点捉襟见肘了。

为了解决这一问题,大咖 Tom Christie 和他的小伙伴给大家带来了新世代异步 HTTP 客户端 ~ HTTPX。

紧跟 requests 步伐,HTTPX 在支持 requests 标准功能的同时,还支持 HTTP/2 与 HTTP/1,以及通过 ASGI 协议直接调用 Python 网络应用,此外还有完善的类型注释。

要执行大规模并发请求?HTTPX 就是你要找的答案。

注意:HTTPX 仍在 alpha 版开发阶段,目前只开发了异步客户端,将来还会引入同步客户端。

2. Starlette

2019 年 10 大顶级 Python 支持库

项目网址:
https://www.starlette.io/

Starlette 打包了 WebSocket、GraphQL、进程内后台任务等多种功能,是真正高性能的轻量级 ASGI 框架与工具箱。所有功能都完全支持类型注释代码库,且不需要任何硬性依赖项。可以把它当成非常轻量级的现代异步版 Flask。

Starlette 的灵活性很强,既可以用作完整的网络框架,也可以只用作 ASGI 工具箱。

Starlette 运行在 uvicorn 之上,这个支持库入选了去年的 10 大顶级 Python 支持库榜单。

如果想开发新型网络应用,强烈建议您给 Starlette 一个发光发热的机会。

3. FastAPI

2019 年 10 大顶级 Python 支持库

项目网址:
https://github.com/tiangolo/fastapi

Starlette 很赞,但它太迷你了,虽然给了开发者很大的自由,但有时,用户要的其实只是一个能快速完成任务的框架。

Sebastián Ramírez 就是出于这个目的开发的 FastAPI,怎么说呢?这个支持库的各个方面都很 Fast。

这个用 Python 开发 API 的新框架具有超高性能,而且可以基于 OpenAPI 标准自动生成交互式文档。默认支持 Swagger UI 与 ReDoc,允许直接从浏览器调用、测试 API,从而提高开发效率。用这个框架开发 API,真的是又快又简单。

该支持库还支持现代 Python 最佳实用功能之一:类型提示。FastAPI 在很多方面都使用了类型提示,其中最酷的一个功能是由 Pydantic 加持的自动数据验证与转换。

FastAPI 基于 Starlette 开发,性能与 NodeJS 和 GO 相当,还自带 WebSocket 与 GraphQL 原生支持。

最后,对于开源支持库而言,它的技术支持文档也非常不错。说真的,去看一下吧!

4. Immutables

2019 年 10 大顶级 Python 支持库

项目网址:
https://github.com/magicstack/immutables

MagicStack 的兄弟回归了,这次他们带来的是一个简单、优雅的不可变映射类型(“冻结字典”)。

这东西的好处在哪儿?呃,希望你能听得懂下面这句话,Haskell 等函数编程语言里使用的哈希数组映射字典树(HAMT)的底层数据结构。最值得注意的是,不管 set() 还是 get() 操作的性能都为  O(log N),且对于相对较小的映射,可以达到 O(1)。

如果你的应用里字典的规模较大,并且想提高一下性能,这个酷酷的新支持库值得一试。

5. Pyodide

项目网址:
https://github.com/iodide-project/pyodide/

Pyodide 是本榜单里最刷三观的项目。通过 WebAssembly,它把 Python 科学引入到了浏览器界面,把科学计算提升到了全新的层面。

想用 Numpy 搞定一些数字?用 Pandas 处理大型 DataFrame?用 Matplotlib 为计算结果进行可视化?有了 Pyodide,这些操作在浏览器里就可以轻轻松松地实现了。

这还不算完,还有好消息:这个库可用的 Python 支持库已经超过了 35 个,您这是要上天啊。

6. Modin

2019 年 10 大顶级 Python 支持库

项目网址:
https://github.com/modin-project/modin

Modin 的口号是“只改一行代码,就能加速 Pandas”,没错,就是这么简单。只要安装 Modin,更改 import 语句,在多核笔记本上,处理数据的速度就能提高 4 倍。

我滴个神 ~~ 这是怎么做到的?Modin 有自带的 modin.pandas.DataFrame 对象,这是一个轻量级的并行 DataFrame 对象。因为与 Pandas API 兼容,使用这个对象就跟是透明的一样,在后台,该支持库使用 Ray 或 Dask 作为计算引擎,执行分布式数据计算。

有的时候,获得更快的速度就是那么简单,改一两行代码就可以了,Modin 就是证明。

7. Streamlit

2019 年 10 大顶级 Python 支持库

项目网址:
https://github.com/streamlit/streamlit

不论机器学习项目多么的超凡脱俗,都免不了要手动与模型和数据交互的工作。

与其投入无数小时,开发数千行代码的应用,Streamlit 让你可以快速搭建用来分享模型与分析的 APP。构建交互式 UI、实现数据可视化、输出分析模型现在就是小菜一碟。

有了 Streamlit,只要添加几行代码,嗖的一下,就能从 Python 脚本代码飞升为产品级 APP。TensorFlow、Keras、PyTorch、Pandas,只要是你能想到的数据科学工具,Streamlit 都已经支持了。

8. Transformers

2019 年 10 大顶级 Python 支持库

项目网址:
https://github.com/huggingface/transformers

从事机器学习相关工作的读者,一定会对过去的一年中自然语言处理(NLP)领域里的重大突破有所耳闻。

BERT、XLNet、roBERTa 等新涌现出来的高性能模型已经取得了长足的发展,尤其是在文本分类、机器翻译、命名实体识别等众多 NLP 领域里的高精尖突破层出不穷,让人眼花缭乱。

对业界人士来说,找到一款既能在产品级程序上利用这些模型,又不会太过复杂的工具,尤为重要。对研究者而言,一个既不用花费太多时间编写模板代码,又能调校支持库内核,不断开发、实验新模型的支持库,也非常重要。

Hugging Face 的小伙伴给我们带来了变形金刚(Transformers),这个支持库支持最现代的 NLP 模型打包、预训练等功能,而且还开箱即用。TensorFlow 2.0 与 PyTorch 之间的互操作,让该支持库达到了业界标准,完全可以为研究工作与产品级应用程序加持。该支持库由研究人员开发,因此,它的更新速度非常快,而且还在不断引入新式模型。

锦上添花:Hugging Face 团队开发了 DistilBERT,这是基于 BERT 提炼出来的,更小、更快、更省钱、更轻量的版本。

还在犹豫要不要用 Hugging Face 的变形金刚处理现代 NLP 任务?看到这篇文章就是缘分,快来试下这个在线演示,感受变形金刚的魔力吧。

2019 年 10 大顶级 Python 支持库

9. Detectron2

2019 年 10 大顶级 Python 支持库

项目网址:
https://github.com/facebookresearch/detectron2

Facebook AI 研究团队(FAIR)在开发对象探知、姿态估测、语义/实例分隔、全景分割等模型的同时,不断将计算机视觉(CV)推向新的高度。

就在短短的几年前,上述这些技术就像是科幻小说。我们从未对 FAIR 有过什么期望,但这回他们再一次震撼全场。

Detectron2 是 Detectron 的延续,该支持库建立在 PyTorch 之上,整合了多种高精尖的计算机视觉算法。

鉴于支持用例类型多种多样,这类支持库的开发难度特别大。与 Hugging Face 的 Transformers 类似,FAIR 团队的 Detectron2 真的很强大,其延展性与模块化的设计风格,让它在计算机视觉研究应用中独领风骚。同时,Detectron2 的应用极其简单,非常适合那些只想快速得到结果,不想了解核心算法的人。没错,只要几行 Python 代码,就可以通过 Detectron2 让你开发的软件“理解”图片。

Detectron2 能否形成生机勃勃的社区,还需要些时间来验证,但到目前为止,它的前途还是蛮光明的。很多研究人员都在为 Detectron2 研发更新、更快、更好的模型,因此,它成为计算机视觉应用“首选”解决方案的可能性很大。如果你从事计算机视觉工作,一定要对这个支持库保持密切的关注!

10. Metaflow

项目网址:
https://docs.metaflow.org/introduction/what-is-metaflow

Metaflow 这个支持库实在太新了,差点就没赶上 2019 年榜单评选!但不要因此就小瞧它:别看它 12 月 3 日才正式发布,其实它是 Netfilx 两年精雕细琢的成果,通过了长期内部实测,Netflix 才决定开源。

Metaflow 这个 Python 支持库能帮助数据科学家与数据工程师开发在现实世界中应用的实战项目。它的目标是,减轻非技术型数据科学家学习技术的负担,比如,如何利用计算资源、怎么实现并行运算、架构设计、版本控制等。Netflix 与 AWS 合作,让用户通过开箱即用的分布式计算即可轻松定义复杂数据流。

我们在 Tryolabs 内部已经评测了几个 Metaflow 核心项目。如果你也对这个工具感兴趣,请参阅 Netflix 博客的发布贴。

结论

这一年,或者说又一个10 年马上就要过去了,开源社区这些年的对世界的贡献将对今后几年产生深远的影响。想要了解这些年的优秀开源库,就来看下我们这几年的榜单吧:2015、2016、2017、2018。

本文由 Elías Masquil, Alan Descoins 与 Germán Hoffman 合作编撰。


转自:https://mp.weixin.qq.com/s/ltty16HXd09P3lCMUB4hHQ

2020年1月Github上最热门Python开源项目!

来自:开源最前线(ID:OpenSourceTop) 

1月份GitHub上最热门的Python开源项目排行已经出炉啦,一起来看看上榜详情:

 

1
fastapi

https://github.com/tiangolo/fastapi Star 9051

 

FastAPI 是一个 Rails 库用来快速查询相互依存的数据集合并返回时候人类阅读的、标准的 API 输出。通过构造复杂的 SQL 查询并高效使用 JOIN 和子查询。

 

2
ALBERT

https://github.com/google-research/ALBERT Star 3802

 

ALBERT模型是BERT的改进版,与最近其他State of the art的模型不同的是,这次是预训练小模型,效果更好、参数更少。它对BERT进行了三个改造:
  • 词嵌入向量参数的因式分解
  • 跨层参数共享
  • 段落连续性任务

 

3
spiderfoot

https://github.com/smicallef/spiderfoot Star 3802

 

2020年1月Github上最热门Python开源项目!

 

SpiderFoot是一个免费的、开源的网站信息收集工具,你可以根据指定域名获得信息,如网站子域、电子邮件地址、web服务器版本等等,可以帮助渗透测试人员自动化的实现网站信息收集、资产发现的过程,提高工作效率

 

4
JobFunnel

https://github.com/PaulMcInnis/JobFunnel Star 1244

 

抓取工作网站,过滤和检查工作清单的工具,可用于将职位发布爬到.csv文件中。

 

5
SlowFast

https://github.com/facebookresearch/SlowFast Star 2005

PySlowfast是一个基于PyTorch的代码库, 让研究者可以轻而易举的复现从基础至前沿的视频识别(Video Classification)和行为检测(Action Detection)算法。

 

2020年1月Github上最热门Python开源项目!

 

不但如此,PySlowFast代码库同时开源了大量预训练模型(pretrain models),让研究者省去了反复训练模型的烦恼,可以直接使用FAIR预训练的前沿(cutting edge performance)模型。由Facebook开源

 

6
system-design-primer

https://github.com/donnemartin/system-design-primer Star 82155

 

2020年1月Github上最热门Python开源项目!

 

该项目是关于如何设计大型系统,以及如何应对系统设计面试。系统设计是一个很宽泛的话题。在互联网上,关于系统设计原则的资源也是多如牛毛。这个仓库就是这些资源的组织收集,它可以帮助你学习如何构建可扩展的系统。

 

7
ansible

https://github.com/ansible/ansible Star  41269

 

Ansible是一个配置管理和配置工具,类似于Chef,Puppet或Salt。这是一款很简单也很容易入门的部署工具,它使用SSH连接到服务器并运行配置好的任务,服务器上不用安装任何多余的软件,只需要开启ssh,所有工作都交给client端的ansible负责。

 

8
pandas

https://github.com/pandas-dev/pandas Star  23377

 

 

2020年1月Github上最热门Python开源项目!

 

Pandas 是python的一个数据分析包,最初由AQR Capital Management于2008年4月开发,并于2009年底开源出来,目前由专注于Python数据包开发的PyData开发team继续开发和维护,属于PyData项目的一部分。Pandas最初被作为金融数据分析工具而开发出来,因此,pandas为时间序列分析提供了很好的支持。Pandas的名称来自于面板数据(panel data)和python数据分析(data analysis)。panel data是经济学中关于多维数据集的一个术语,在Pandas中也提供了panel的数据类型。

 

9
GitHub-Chinese-Top-Charts

https://github.com/kon9chunkit/GitHub-Chinese-Top-Charts Star 14343

 

GitHub中文排行榜,帮助你发现高分优秀中文项目、更高效地吸收国人的优秀经验成果;榜单每周更新一次。

 

10
mlflow

https://github.com/mlflow/mlflow Star 5832

 

MLflow 是由 Apache Spark 技术团队开源的一个机器学习平台,主打开放性:

开放接口:可与任意 ML 库、算法、部署工具或编程语言一起使用。

开源:开发者可轻松地对其进行扩展,并跨组织共享工作流步骤和模型。

MLflow的当前版本是alpha版本。这意味着API和数据格式可能会发生变化!

 

11
spinningup

https://github.com/openai/spinningup Star 4105

 

Spinning Up 是大名鼎鼎的Open AI推出的免费强化学习教学项目,旨在降低强化学习的门槛,让初学者能在项目实践的过程中一步一步循序渐进地学习。项目不仅提供了详细的理论介绍,同时还有完整的练习代码,真的不不愧是学习深度强化学习的良心之作。

转自:https://mp.weixin.qq.com/s/rdfP0PNdz0OKOS7ZU1QdRw

这些方法,能够让你的 Python 程序快如闪电

来源:机器之心

讨厌 Python 的人总是会说,他们不想用 Python 的一个重要原因是 Python 很慢。而事实上,无论使用什么编程语言,特定程序的运行速度很大程度上取决于编写程序的开发人员以及他们优化程序、加快程序运行速度的技能。
那么,让我们证明那些人错了!本文将介绍如何提升 Python 程序的效率,让它们运行飞快!
这些方法,能够让你的 Python 程序快如闪电
计时与性能分析
在开始优化之前,我们首先需要找到代码的哪一部分真正拖慢了整个程序。有时程序性能的瓶颈显而易见,但当你不知道瓶颈在何处时,这里有一些帮助找到性能瓶颈的办法:
注:下列程序用作演示目的,该程序计算 e 的 X 次方(摘自 Python 文档):
# slow_program.py
from decimal import *

def exp(x):
    getcontext().prec += 2
    i, lasts, s, fact, num = 00111
while s != lasts:
        lasts = s
        i += 1
        fact *= i
        num *= x
        s += num / fact
    getcontext().prec -= 2
return +s

exp(Decimal(150))
exp(Decimal(400))
exp(Decimal(3000))
最懒惰的「性能分析」
首先,最简单但说实话也很懒的方法——使用 Unix 的 time 命令:

nbsp;time python3.8 slow_program.py

real    0m11,058s
user    0m11,050s
sys     0m0,008s
如果你只想给整个程序计时,这个命令即可完成目的,但通常是不够的……
最细致的性能分析
另一个极端是 cProfile,它提供了「太多」的信息:

nbsp;python3.8 -m cProfile -s time slow_program.py
1297 function calls (1272 primitive calls) in 11.081 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
3   11.079    3.693   11.079    3.693 slow_program.py:4(exp)
1    0.000    0.000    0.002    0.002 {built-in method _imp.create_dynamic}
4/1    0.000    0.000   11.081   11.081 {built-in method builtins.exec}
6    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x9d12c0}
6    0.000    0.000    0.000    0.000 abc.py:132(__new__)
23    0.000    0.000    0.000    0.000 _weakrefset.py:36(__init__)
245    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}
10    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1233(find_spec)
8/4    0.000    0.000    0.000    0.000 abc.py:196(__subclasscheck__)
15    0.000    0.000    0.000    0.000 {built-in method posix.stat}
6    0.000    0.000    0.000    0.000 {built-in method builtins.__build_class__}
1    0.000    0.000    0.000    0.000 __init__.py:357(namedtuple)
48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:57(_path_join)
48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:59(<listcomp>)
1    0.000    0.000   11.081   11.081 slow_program.py:1(<module>)
...
这里,我们结合 cProfile 模块和 time 参数运行测试脚本,使输出行按照内部时间(cumtime)排序。这给我们提供了大量信息,上面你看到的行只是实际输出的 10%。从输出结果我们可以看到 exp 函数是罪魁祸首(惊不惊喜,意不意外),现在我们可以更加专注于计时和性能分析了……
计时专用函数
现在我们知道了需要关注哪里,那么我们可能只想要给运行缓慢的函数计时而不去管代码的其他部分。我们可以使用一个简单的装饰器来做到这点:
def timeit_wrapper(func):
    @wraps(func)
def wrapper(*args, **kwargs):
        start = time.perf_counter()  # Alternatively, you can use time.process_time()
        func_return_val = func(*args, **kwargs)
end = time.perf_counter()
        print('{0:<10}.{1:<8} : {2:<8}'.format(func.__module__, func.__name__end - start))
return func_return_val
return wrapper
接着,将该装饰器按如下方式应用在待测函数上:
@timeit_wrapper
def exp(x):
    ...

print('{0:<10} {1:<8} {2:^8}'.format('module''function''time'))
exp(Decimal(150))
exp(Decimal(400))
exp(Decimal(3000))
得到如下输出:

nbsp;python3.8 slow_program.py
module     function   time
__main__  .exp      : 0.003267502994276583
__main__  .exp      : 0.038535295985639095
__main__  .exp      : 11.728486061969306
此时我们需要考虑想要测量哪一类时间。time 库提供了 time.perf_counter 和 time.process_time 两种时间。其区别在于,perf_counter 返回绝对值,其中包括了 Python 程序并不在运行的时间,因此它可能受到机器负载的影响。而 process_time 只返回用户时间(除去了系统时间),也就是只有进程运行时间。
让程序更快
现在到了真正有趣的部分了,让 Python 程序跑得更快!我不会告诉你一些奇技淫巧或代码段来神奇地解决程序的性能问题,而更多是关于通用的想法和策略。使用这些策略,可以对程序性能产生巨大的影响,有时甚至可以带来高达 30% 的提速。
使用内置的数据类型
这一点非常明显。内置的数据类型非常快,尤其相比于树或链表等自定义类型而言。这主要是因为内置数据类型使用 C 语言实现,使用 Python 实现的代码在运行速度上和它们没法比。
使用 lru_cache 实现缓存/记忆
我在之前的博客中介绍过这一技巧,但我认为它值得用一个简单例子再次进行说明:
import functools
import time

# caching up to 12 different results
@functools.lru_cache(maxsize=12)
def slow_func(x):
    time.sleep(2)  # Simulate long computation
return x

slow_func(1)  # ... waiting for 2 sec before getting result
slow_func(1)  # already cached - result returned instantaneously!

slow_func(3)  # ... waiting for 2 sec before getting result
上面的函数使用 time.sleep 模拟了繁重的计算过程。当我们第一次使用参数 1 调用函数时,它等待了 2 秒钟后返回了结果。当再次调用时,结果已经被缓存起来,所以它跳过了函数体,直接返回结果。
使用局部变量
这和每个作用域中变量的查找速度有关。我之所以说「每个作用域」,是因为这不仅仅关乎局部变量或全局变量。事实上,就连函数中的局部变量、类级别的属性和全局导入函数这三者的查找速度都会有区别。函数中的局部变量最快,类级别属性(如 self.name)慢一些,全局导入函数(如 time.time)最慢。
你可以通过这种看似没有必要的代码组织方式来提高效率:
#  Example #1
class FastClass:

def do_stuff(self):
        temp = self.value  # this speeds up lookup in loop
for i in range(10000):
            ...  # Do something with `temp` here

#  Example #2
import random

def fast_function():
    r = random.random
for i in range(10000):
        print(r())  # calling `r()` here, is faster than global random.random()

使用函数

这也许有些反直觉,因为调用函数会让更多的东西入栈,进而在函数返回时为程序带来负担,但这其实和之前的策略相关。如果你只是把所有代码扔进一个文件而没有把它们放进函数,那么它会因为众多的全局变量而变慢。因此,你可以通过将所有代码封装在 main 函数中并调用它来实现加速,如下所示:
def main():
    ...  # All your previously global code

main()
不要访问属性
另一个可能让程序变慢的东西是用来访问对象属性的点运算符(.)。这个运算符会引起程序使用__getattribute__进行字典查找,进而为程序带来不必要的开销。那么,我们怎么避免(或者限制)使用它呢?
#  Slow:
import re

def slow_func():
for i in range(10000):
        re.findall(regex, line)  # Slow!

#  Fast:
from re import findall

def fast_func():
for i in range(10000):
        findall(regex, line)  # Faster!
当心字符串
当在循环中使用取模运算符(%s)或 .format() 时,字符串操作会变得很慢。有没有更好的选择呢?根据 Raymond Hettinger 近期发布的推文,我们只需要使用 f-string 即可,它可读性更强,代码更加紧凑,并且速度更快!基于这一观点,如下从快到慢列出了你可以使用的一系列方法:
f'{s} {t}'  # Fast!
s + '  ' + t 
' '.join((s, t))
'%s %s' % (s, t) 
'{} {}'.format(s, t)
Template('$s $t').substitute(s=s, t=t)  # Slow!
生成器本质上并不会更快,因为它们的目的是惰性计算,以节省内存而非节省时间。然而,节省的内存会让程序运行更快。为什么呢?如果你有一个大型数据集,并且你没有使用生成器(迭代器),那么数据可能造成 CPU 的 L1 缓存溢出,进而导致访存速度显著变慢。
当涉及到效率时,非常重要的一点是 CPU 会将它正在处理的数据保存得离自己越近越好,也就是保存在缓存中。读者可以看一看 Raymond Hettingers 的演讲(https://www.youtube.com/watch?v=OSGv2VnC0go&t=8m17s),其中提到了这些问题。
总结
优化的第一要义就是「不要去做」。但如果你必须要做,我希望这些小技巧可以帮助到你。然而,优化代码时一定要谨慎,因为该操作可能最终造成代码可读性变差、可维护性变差,这些弊端可能超过代码优化所带来的好处。
参考链接:https://towardsdatascience.com/making-python-programs-blazingly-fast-c1cd79bd1b32

转自:https://mp.weixin.qq.com/s/hidWQghW3Gy_ysqGlS5MRA