网站性能检测评分
注:本网站页面html检测工具扫描网站中存在的基本问题,仅供参考。
python中与或非
一位16岁CEO教你如何在高中阶段入门人工智能 人工智能视频课程
大数据文摘作品
编译:冯琛、龙牧雪
What? 高中生也可以?
人工智能、大数据已经被纳入了我国高中“新课标”,但估计大多数高中生要是真想了解这一学科恐怕是一头雾水:高数没学过,编程也不会,老师也不教,这怎么学人工智能?
新加坡有位高中生Karan Jaisingh已经学习人工智能和机器学习一年了。不久前,他在GitHub发出了一篇长文,专门教广大高中生(以及高中老师、高中生家长、准高中生、准高中生家长……)入门人工智能。
不看不知道,他的LinkedIn显示他还是个CEO!他正在开发一个错题集和期末复习相关的App
文摘菌不禁惦记起了广大想入行的本科生、硕士生、博士生……告诉我,春节假期余额严重不足了,你计划要看的书翻开了吗?如果没有,可以参考下面这篇入门指南,它虽然是针对高中生而写,但使用的都是主流教程和工具。
高中生写给高中生
这份指南中整合的内容,是为打算在机器学习和人工智能这个新兴领域内有所建树的高中生准备的。目前在这个领域还没有适合高中生的学习路径。这份指南的特别之处在于,你不需要了解线性代数、偏导以及其他高中生没有学到的复杂数学概念。
如果你能够定期按照这个路径学习,我相信在短短三个月内你会进步飞速。接下来我们就正式开始吧。
学习Python,你需要使用它编写算法
我强烈推荐Python,不仅仅因为它超容易上手,还因为它提供了机器学习会用到的几乎所有好用的函数库。R也很好用,但是我认为Python更适合高中生。除了基础的编程,Numpy、Pandas和Matplotlib是机器学习中最有用的几个函数库。
如果你没有任何编程经验,我推荐你上一门多伦多大学的免费课程。多伦多大学是目前在机器学习和人工智能方面水平最高的大学之一。这门课耗时数周,但它值得你花费时间。你在这门课程中学到的大多数知识都能应用于任何其他的编程语言,唯一不同的只有语法。
课程链接:
https://coursera.org/learn/learn-to-program?siteID=SAyYsTvLiGQ-rs4V8qoewjp3oL7Nr.r_Fw&utm_content=10&utm_medium=partners&utm_source=linkshare&utm_campaign=SAyYsTvLiGQ#
如果你有除Python之外的编程经验,可以直接浏览以下语法教程,这最多耗时一天。
教程链接:
https://tutorialspoint/python/python_basic_syntax.htm
学习了Python的基本知识后,你需要了解Numpy、Pandas两个函数库(Matplotlib可以之后再说)。Numpy数组和Pandas用于调用和更改数据,Matplotlib用来制作图表将数据可视化。下面两个课程只需要几天时间就能完成:
Numpy: http://cs231n.github.io/python-numpy-tutorial/Pandas: https://pandas.pydata.org/pandas-docs/stable/10min.html
文摘菌备注:这篇Numpy教程是斯坦福CS231n的配套练习,想同步学可以看大数据文摘翻译的视频+笔记
http://study.163/course/courseMain.htm?courseId=1003223001
机器学习的基础知识
如果要说一门通用的机器学习课程,那非吴恩达(Andrew Ng)的课程莫属。对于高中学生来说,这门课程可能有点难度,因为它涉及到偏导数等概念(尽管这些概念不是必须的)。建议反复观看第3至5周的课程。
我鼓励每个人都学学这门课并做笔记,虽然基于Matlab的编程相关的教程和练习不是必须的,而且根据我的经验,这个课程对于高中生来说难以掌握。但不用担心,我们将用更短的时间在Python中完成相同(甚至更先进)的算法。
课程链接:https://coursera.org/learn/machine-learning
学习各种机器学习算法并了解如何实现
在没有通用数学基础的情况下想要理解机器学习算法,理论上讲是很难的。但是一个澳洲团队解决了这个问题。
来自SuperDataScience团队的Kirill Eremenko和Hadelin de Ponteves,特别擅长在现实生活中寻找实现简单算法的途径。更厉害的是,这让没有复杂数学背景的高中生可以轻松理解。
他们的课程包括Python和R,不用担心R的部分,只需要看Python的教程就可以了。如果你觉得他们的课有点慢,可以用1.25倍速播放。
他们的课在Udemy上,是付费的,但Udemy一般都给他们的课90%的折扣。在这可以找到课程,通常只要花费10美元。
课程链接:https://udemy/machinelearning/learn/v4/overview
该课程涵盖了从基本回归分析到深度卷积神经网络。如果你还想探索更深的领域,机器学习课程的最后提供了他们的深度学习课程,有90%的折扣。但是,因为第二个课程太新了,其中的概念可能有点超前并缺乏合适的分类整理。
如果你不愿意花钱学,你可以看看谷歌的免费深度学习课程,或者密西根大学的免费课程。但是这些课程都与SuperDataScience的课程相差甚远。
谷歌的免费深度学习课程:https://udacity/course/deep-learning--ud730密西根大学的免费课程: https://coursera.org/learn/python-machine-learning
对于这些课,做笔记不是必须的,网上有很多算法小抄,你一下就能看明白这些算法是怎么运作的。
小抄链接:https://analyticsvidhya/blog/2017/02/top-28-cheat-sheets-for-machine-learning-data-science-probability-sql-big-data/
探索、探索再探索
现在你掌握了广泛的机器学习概念,并且学到了大量的技能。是时候在这些基础项目上小试牛刀啦。我建议上Kaggle或者UCI机器学习库,找个你感兴趣的数据集,对它进行建模解决一些问题。尝试各种不同的算法,尝试去不断优化模型表现。
Kaggle:https://kaggle/UCI机器学习库:http://archive.ics.uci.edu/ml/datasets.html
确保你用的数据集简单明了,它们不应该需要太多的预先处理和修改。一些我能想到的简单数据集:鸢尾花数据、葡萄酒数据、威斯康星州乳腺癌数据、自闭症筛查数据、国会投票数据、MNIST手写数字数据和MNIST时尚数据。
如果你遇到障碍,Stack Overflow是你的好朋友,上面有你所有问题的答案。如果没有,发布一个问题,几个小时内就能得到解答。
Stack Overflow链接:https://stackoverflow/
寻找一个特别感兴趣的领域,深入研究
现在你已经有了对全部基础知识有了很好的广泛了解。我建议你在机器学习的范围内寻找一个感兴趣的领域,并且深入了解它。在高中阶段,你可能没有时间成为所有领域的专家,但可以尝试去征服一个或两个领域。
计算机视觉
应用一种特殊的神经网络使计算机观察并理解事物,这应该是当下机器学习及人工智能最热门的领域。斯坦福大学发布了相关在线课程,讲义、课堂笔记和作业都公开。尽管课程涉及的数学有些复杂,不要担心,试着去学习一下,该课程只是为了加深你的知识。另外,你还可以看看OpenCV,这是一个计算机视觉库,它可以为你处理很多复杂的东西。这是一个很好的教程。当你完成上述这些,就去Kaggle和UCI上找更多的高级图像数据集,或者参加Kaggle的竞赛。
斯坦福CS231n在线课程:http://cs231n.stanford.edu/OpenCV教程:https://youtube/watch?v=Z78zbnLlPUA&list=PLQVvvaa0QuDdttJXlLtAJxJetJcqmqlQq斯坦福CS231n中文字幕视频+笔记:http://study.163/course/courseMain.htm?courseId=1003223001
自然语言处理
了解计算机如何学习说话也是当下的一个突出话题。斯坦福大学又提供了一个在线课程。如果你不了解其中的一些数学概念,不要担心,只需要了解这个领域的工作原理。对于实现NLP应用,你可以学习Udemy课程。你也可以选择Siraj Raval的视频。如果你已经完成了这些,可以尝试开始做简单的众所周知的项目,比如创建聊天机器人,情感分析或为歌曲创建歌词。
斯坦福CS224n在线课程:http://web.stanford.edu/class/cs224n/Udemy课程:https://udemy/data-science-natural-language-processing-in-python/Siraj Raval的视频:https://youtube/watch?v=9zhrxE5PQgY大数据文摘经授权译制Siraj Raval多个视频,戳这里看
强化学习
该领域专注于机器如何以特定方式学习,其最受欢迎的应用程序是在电玩领域。 Siraj Raval在这方面又有了一个不错的视频集合,另外David Silver的UCL课程非常棒,虽然初学者可能会觉得有点难 。一旦你完成了这些工作,就可以开始从网上下载基础项目,并添加人工智能元素来改进他们的行为模式。
Siraj Raval:https://youtube/watch?v=i_McNBDP9Qs&list=PL2-dafEMk2A5FZ-MnPMpp3PBtZcINKwLADavid Silver的UCL课程:http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html
数据科学
这是一个萌芽的领域,有许多令人兴奋的工作机会。我建议你学习SuperDataScience的付费课程或加州大学圣地亚哥分校基于Python的免费课程。你还必须学习SQL以及Matplotlib。在学生时期学习的优势在于找工作——我有高中的朋友拿到了数据科学实习的offer,因为从他们的工作中获得的数据可以立即被公司拿去盈利。公司总是很需要数据科学家。
SuperDataScience的付费课程:https://udemy/datascience/加州大学圣地亚哥分校的免费课程:https://edx.org/course/python-data-science-uc -san-diegox-dse200xSQL:https://khanacademy.org/computing/computer-programming/sqlMatplotlib:https://youtube/watch?v=q7Bo_J8x_dw
还有像代表性学习(用于推荐系统)、Adversial Networks(AI改进AI)和遗传算法(以与自然进化类似的方式改进解决方案)等领域,但在我看来,对于大多数高中学生来说,这些是延伸学习。因为这些领域目前没有盈利空间,他们不像其他领域被学习和发掘得那么全面。如果你对其中某个领域特别感兴趣,也可以尽情去探索。
真正了解人工智能领域
如果你想要长期在这个领域中工作,了解它是什么、有什么突破性进展以及它对社会的影响至关重要。
高中生应该做如下几件事来加深对该领域的了解、增长见识:
开始阅读研究论文:它们不像你想象的那么有挑战性。即使只有高中数学水平也可以读懂很多论文。如果你读到一篇不理解的,放下它不用读了,还有很多其他的替代选择。https://kdnuggets/2017/04/top-20-papers-machine-learning.html
关注领域内的先驱:像吴恩达、Ian Goodfellow和Yann LeCunn都经常接受采访,他们给出了这一领域内专家对于人工智能课题的权威观点。https://youtube/user/Maaaarth/videos
与时俱进:Wired是科技达人的最佳平台之一。它每天发布多个与AI相关的故事。这是个方便快捷了解实时趋势的好途径。另外,订阅TechCrunch的Facebook Messenger机器人 - 它通常会每天推送与人工智能相关的有趣文章。https://wired/tag/artificial-intelligence/
了解内涵:没有比看TED更好的方式了。他们的发言人在这个领域非常权威,并且在发言中越来越强调人工智能。https://youtube/user/TEDtalksDirector/videos
了解哲学:人工智能有支持者也有反对者。然而,它背后的哲学是有趣的。推荐一些我喜欢并且适合高中生阅读的探究该领域的书籍,包括Ray Kurzweil的《如何创造心灵》和Max Tegmark的《生活3.0》。http://s3.amazonaws/arena-attachments/1446178/cffa5ebc74cee2b1edf58fa9a5bbcb1c.pdf?1511265314
做贡献:如果你喜欢从他人的经验中学习,看看脸书上的人工智能和深度学习小组。或者,如果你更喜欢对话,看一下Reddit上的人工智能相关问题。https://reddit/r/artificial/
结论
并不是每个人都要遵循这一条路径,你也可以寻找自己的学习路径。机器学习和人工智能是一个新领域,一般是研究生在学习相关课程。但这并不是说此领域晦涩难懂,只要掌握学习方法,什么时候学习都不算晚。
你觉得几岁开始学习人工智能比较合适?欢迎留言讨论~
原文链接:https://github/kjaisingh/high-school-guide-to-machine-learning/blob/master/README.md
用Python入门不明觉厉的马尔可夫链蒙特卡罗(附案例代码) 公司视频课程
大数据文摘作品
编译:Niki、张南星、Shan LIU、Aileen
这篇文章让小白也能读懂什么是人们常说的Markov Chain Monte Carlo。
在过去几个月里,我在数据科学的世界里反复遇到一个词:马尔可夫链蒙特卡洛(Markov Chain Monte Carlo , MCMC)。在我的研究室、podcast和文章里,每每遇到这个词我都会“不明觉厉”地点点头,觉得这个算法听起来很酷,但每次听人提起也只是有个模模糊糊的概念。
我屡次尝试学习MCMC和贝叶斯推论,而一拿起书,又很快就放弃了。无奈之下,我选择了学习任何新东西最佳的方法:应用到一个实际问题中。
通过使用一些我曾试图分析的睡眠数据和一本实操类的、基于应用教学的书(《写给开发者的贝叶斯方法》,我最终通过一个实际项目搞明白了MCMC。
《写给开发者的贝叶斯方法》
https://github/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers
和学习其他东西一样,当我把这些技术性的概念应用于一个实际问题中而不是单纯地通过看书去了解这些抽象概念,我更容易理解这些知识,并且更享受学习的过程。
这篇文章介绍了马尔可夫链蒙特卡洛在Python中入门级的应用操作,这个实际应用最终也使我学会使用这个强大的建模分析工具。
此项目全部的代码和数据:
https://github/WillKoehrsen/ai-projects/blob/master/bayesian/bayesian_inference.ipynb
这篇文章侧重于应用和结果,因此很多知识点只会粗浅的介绍,但对于那些想了解更多知识的读者,在文章也尝试提供了一些学习链接。
案例简介
我的智能手环在我入睡和起床时会根据心率和运动进行记录。它不是100%准确的,但现实世界中的数据永远不可能是完美的,不过我们依然可以运用正确的模型从这些噪声数据提取出有价值的信息。
典型睡眠数据
这个项目的目的在于运用睡眠数据建立一个能够确立睡眠相对于时间的后验分布模型。由于时间是个连续变量,我们无法知道后验分布的具体表达式,因此我们转向能够近似后验分布的算法,比如马尔可夫链蒙特卡洛(MCMC)。
选择一个概率分布
在我们开始MCMC之前,我们需要为睡眠的后验分布模型选择一个合适的函数。一种简单的做法是观察数据所呈现的图像。下图呈现了当我入睡时时间函数的数据分布。
睡眠数据
每个数据点用一个点来表示,点的密度展现了在固定时刻的观测个数。我的智能手表只记录我入睡的那个时刻,因此为了扩展数据,我在每分钟的两端添加了数据点。如果我的手表记录我在晚上10:05入睡,那么所有在此之前的时间点被记为0(醒着),所有在此之后的时间点记为1(睡着)。这样一来,原本大约60夜的观察量被扩展成11340个数据点。
可以看到我趋向于在10:00后几分钟入睡,但我们希望建立一个把从醒到入睡的转变用概率进行表达的模型。我们可以用一个简单的阶梯函数作为模型,在一个精确时间点从醒着(0)变到入睡(1),但这不能代表数据中的不确定性。
我不会每天在同一时间入睡,因此我们需要一个能够模拟出这个个渐变过程的函数来展现变化当中的差异性。在现有数据下最好的选择是logistic函数,在0到1之前平滑地移动。下面这个公式是睡眠状态相对时间的概率分布,也是一个logistic公式。
在这里,β (beta) 和 α (alpha) 是模型的参数,我们只能通过MCMC去模拟它们的值。下面展示了一个参数变化的logistic函数。
一个logistic函数能够很好的拟合数据,因为在logistic函数中入睡的概率在逐渐改变,捕捉了我睡眠模式的变化性。我们希望能够带入一个具体的时间t到函数中,从而得到一个在0到1之间的睡眠状态的概率分布。我们并不会直接得到我是否在10:00睡着了的准确答案,而是一个概率。创建这个模型,我们通过数据和马尔可夫链蒙特卡洛去寻找最优的alpha和beta系数估计。
马尔可夫链蒙特卡洛
马尔可夫链蒙特卡罗是一组从概率分布中抽样,从而建立最近似原分布的函数的方法。因为我们不能直接去计算logistic分布,所以我们为系数(alpha 和 beta)生成成千上万的数值-被称为样本-去建立分布的一个模拟。MCMC背后的基本思想就是当我们生成越多的样本,我们的模拟就更近似于真实的分布。
马尔可夫链蒙特卡洛由两部分组成。蒙特卡洛代表运用重复随机的样本来获取一个准确答案的一种模拟方法。蒙特卡洛可以被看做大量重复性的实验,每次更改变量的值并观察结果。通过选择随机的数值,我们可以在系数的范围空间,也就是变量可取值的范围,更大比例地探索。下图展示了在我们的问题中,一个使用高斯分布作为先验的系数空间。
能够清楚地看到我们不能在这些图中一一找出单个的点,但通过在更高概率的区域(红色)进行随机抽样,我们就能够建立最近似的模型。
马尔可夫链(Markov Chain)
马尔可夫链是一个“下个状态值只取决于当前状态”的过程。(在这里,一个状态指代当前时间系数的数值分配)。一个马尔可夫链是“健忘”的,因为如何到达当前状态并不要紧,只有当前的状态值是关键。如果这有些难以理解的话,让我们来设想一个每天都会经历的情景--天气。
如果我们希望预测明天的天气,那么仅仅使用今天的天气状况我们就能够得到一个较为合理的预测。如果今天下雪,我们可以观测有关下雪后第二天天气的历史数据去预测明天各种天气状况的可能性。马尔可夫链的定义就是我们不需要知道一个过程中的全部历史状态去预测下一节点的状态,这种近似在许多现实问题中都很有用。
把马尔可夫链(Markov Chain)和蒙特卡洛(Monte Carlo),两者放到一起,就有了MCMC。MCMC是一种基于当前值,重复为概率分布系数抽取随机数值的方法。每个样本都是随机的,但是数值的选择也受当前值和系数先验分布的影响。MCMC可以被看做是一个最终趋于真实分布的随机游走。
为了能够抽取alpha 和 beta的随机值,我们需要为每个系数假设一个先验分布。因为我们没有对于这两个系数的任何假设,我们可以使用正太分布作为先验。正太分布,也称高斯分布,是由均值(展示数据分布),和方差(展示离散性)来定义的。下图展示了多个不同均值和离散型的正态分布。
具体的MCMC算法被称作Metropolis Hastings。为了连接我们的观察数据到模型中,每次一组随机值被抽取,算法将把它们与数据进行比较。一旦它们与数据不吻合(在这里我简化了一部分内容),这些值就会被舍弃,模型将停留在当前的状态值。
如果这些随机值与数据吻合,那么这些值就被接纳为各个系数新的值,成为当前的状态值。这个过程会有一个提前设置好的迭代次数,次数越多,模型的精确度也就越高。
把上面介绍的整合到一起,就能得到在我们的问题中所需进行的最基本的MCMC步骤:
为logistic函数的系数alpha 和beta选择初始值。基于当前状态值随机分配给alpha 和beta新的值。检查新的随机值是否与观察数据吻合。如果不是,舍弃掉这个值,并回到上一状态值。如果吻合,接受这个新的值作为当前状态值。重复步骤2和3(重复次数提前设置好)。这个算法会给出所有它所生成的alpha 和beta值。我们可以用这些值的平均数作为alpha 和beta在logistic函数中可能性最大的终值。MCMC不会返回“真实”的数值,而是函数分布的近似值。睡眠状态概率分布的最终模型将会是以alph和beta均值作为系数的logistic函数。
Python实施
我再三思考模拟上面提到的细节,最终我开始用Python将它们变成现实。观察一手的结果会比阅读别人的经验贴有帮助得多。想要在Python中实施MCMC,我们需要用到PyMC3贝叶斯库,它省略了很多细节,方便我们创建模型,避免迷失在理论之中。
通过下面的这些代码可以创建完整的模型,其中包含了参数alpha 、beta、概率p以及观测值observed,step变量是指特定的算法,sleep_trace包含了模型创建的所有参数值。
with pm.Model() as sleep_model:# Create the alpha and beta parameters # Assume a normal distribution alpha = pm.Normal('alpha', mu=0.0, tau=0.05, testval=0.0) beta = pm.Normal('beta', mu=0.0, tau=0.05, testval=0.0) # The sleep probability is modeled as a logistic function p = pm.Deterministic('p', 1. / (1. + tt.exp(beta * time + alpha))) # Create the bernoulli parameter which uses observed data to inform the algorithm observed = pm.Bernoulli('obs', p, observed=sleep_obs) # Using Metropolis Hastings Sampling step = pm.Metropolis() # Draw the specified number of samples sleep_trace = pm.sample(N_SAMPLES, step=step);
为了更直观地展现代码运行的效果,我们可以看一下模型运行时alpha和beta生成的值。
这些图叫做轨迹图,可以看到每个状态都与其历史状态相关,即马尔可夫链;同时每个值剧烈波动,即蒙特卡洛抽样。
使用MCMC时,常常需要放弃轨迹图中90%的值。这个算法并不能立即展现真实的分布情况,最初生成的值往往是不准确的。随着算法的运行,后产生的参数值才是我们真正需要用来建模的值。我使用了一万个样本,放弃了前50%的值,但真正在行业中应用时,样本量可达成千上万个、甚至上百万个。
通过足够多的迭代,MCMC逐渐趋近于真实的值,但是估算收敛性并不容易。这篇文章中并不会涉及到具体的估算方法(方法之一就是计算轨迹的自我相关性),但是这是得到最准确结果的必要条件。PyMC3的函数能够评估模型的质量,包括对轨迹、自相关图的评估。
pm.traceplot(sleep_trace, ['alpha', 'beta'])pm.autocorrplot(sleep_trace, ['alpha', 'beta'])
轨迹图(左)和自相关性图(右)
睡眠模型
建模、模型运行完成后,该最终结果上场了。我们将使用最终的5000个alpha和beta值作为参数的可能值,最终创建了一个单曲线来展现事后睡眠概率:
基于5000个样本的睡眠概率分布
这个模型能够很好的代表样本数据,并且展现了我睡眠模式的内在变异性。这个模型给出的答案并不是简单的“是”或“否”,而是给我们一个概率。举个例子,我们可以通过这个模型找出我在特定时间点睡觉的概率,或是找出我睡觉概率超过50%的时间点:
9:30 PM probability of being asleep: 4.80%.10:00 PM probability of being asleep: 27.44%.10:30 PM probability of being asleep: 73.91%.The probability of sleep increases to above 50% at 10:14 PM.
虽然我希望在晚上10点入睡,但很明显大多时候并不是这样。我们可以看到,平均来看,我的就寝时刻是在晚上10:14。
这些值是基于样本数据的最有可能值,但这些概率值都有一定的不确定性,因为模型本身就是近似的。为了展现这种不确定性,我们可以使用所有的alpha、beta值来估计某个时间点的睡觉概率,而不是使用平均值,并且把这些概率值展现在图中。
晚上10:00睡觉的概率分布
这些结果能够更好地展现MCMC模型真正在做的事情,即它并不是在寻找单一的答案,而是一系列可能值。贝叶斯推论在现实世界中非常有用,因为它是对概率进行了预测。我们可以说存在一个最可能的答案,但其实更准确的回复应当是:每个预测都有一系列的可能值。
起床模型
同样我可以用我的起床数据创建类似的模型。我希望能够在闹钟的帮助下总能在早上6:00起床,但实际上并不如此。下面这张图展现了基于观测值我起床的最终模型:
基于5000个样本的起床事后概率
可以通过模型得出我在某个特定时间起床的概率,以及我最有可能起床的时间:
Probability of being awake at 5:30 AM: 14.10%. Probability of being awake at 6:00 AM: 37.94%. Probability of being awake at 6:30 AM: 69.49%.The probability of being awake passes 50% at 6:11 AM.
看来我需要一个更生猛的闹钟了….
睡眠的时间
出于好奇以及实践需求,最后我想创建的模型是我的睡眠时间模型。首先,我们需要寻找到一个描述数据分布的函数。事先,我认为应该是正态函数,但无论如何我们需要用数据来证明。
睡眠时间长短分布
正态分布的确能够解释大部分数据,但是图中右侧的异常值却无法得到解释(当我睡懒觉的时候)。我们可以用两个单独的正态分布来代表两种模式,但我要用偏态分布。偏态分布有三个参数:平均值、偏离值,以及alpha倾斜值。这三个参数的值都需要从MCMC算法中得到。下面的代码创建了模型,并且使用了Metropolis Hastings抽样。
with pm.Model() as duration_model:# Three parameters to sample alpha_skew = pm.Normal('alpha_skew', mu=0, tau=0.5, testval=3.0) mu_ = pm.Normal('mu', mu=0, tau=0.5, testval=7.4) tau_ = pm.Normal('tau', mu=0, tau=0.5, testval=1.0) # Duration is a deterministic variable duration_ = pm.SkewNormal('duration', alpha = alpha_skew, mu = mu_, ...
Python代码风格:PEP8规则 笔记 互联网视频课程
Python程序设计的代码风格应该遵循PEP8规则:
一、代码布局
1、缩进:
每级缩进4个空格(不用Tab,更不空格Tab混用)
1、续行应该与其包裹元素对齐,要么使用圆括号、方括号和花括号内的隐式行连接来垂直对齐,要么使用悬挂式缩进对齐。当使用悬挂缩进时,应该考虑到第一行不应该有参数,以及使用缩进以区分自己是续行。
2、缩进4个空格的规则对于续行是可选的。
3、当 if 语句的条件部分长到需要换行写的时候,注意可以在两个字符关键字的连接处(比如 if ),增加一个空格,再增加一个左括号来创造一个4空格缩进的多行条件。这会与 if 语句内同样使用4空格缩进的代码产生视觉冲突。PEP没有明确指明要如何区分i发的条件代码和内嵌代码。可使用的选项包括但不限于下面几种情况:
4、(可以参考下面关于是否在二进制运算符之前或之后截断的讨论)
在多行结构中的大括号/中括号/小括号的右括号可以与内容对齐单独起一行作为最后一行的第一个字符,如:
或者也可以与多行结构的第一行第一个字符对齐,如:
2、Tab还是空格?
空格是被首先推荐的缩进方式。
Tab应该只在现有代码已经使用tab进行缩进的情况下使用,以便和现有代码保持一致。
Python 3不允许再同一个代码块中Tab和空格混合使用。
混合使用制表符和空格缩进的Python2代码应该统一转成空格。
使用命令行运行Python 2时,使用-t选项,会出现非法混用tab和空格的警告。当使用-tt选项时,这些警告会变成错误。强烈推荐使用这些选项!
3、最大行长
每行最大长度79个字符。
对于连续大段的文字(比如文档字符串(docstring)或注释),每行应该被限制在72个字符长度内。
Python标准库比较传统,将行长限制在79个字符以内(文档字符串/注释为72个字符)。
一种推荐的换行方式是利用Python圆括号、方括号和花括号中的隐式续行。长行可以通过在括号内换行来分成多行。应该最好加上反斜杠来区别续行。
有时续行只能使用反斜杠才。例如,较长的多个 with 语句不能采用隐式续行,只能接受反斜杠表示换行:
另一个这样的例子是assert语句。要确保续行的缩进适当。
在二元运算符之前应该换行吗?
遵循数学的传统能产出更多可读性高的代码:
4、空行
顶层函数和类的定义,前后用两个空行隔开。
类里的方法定义用一个空行隔开。
相关的功能组可以用额外的空行(尽量少地)隔开。一堆相关的单行代码之间的空白行可以省略(例如,一组虚拟实现 dummy implementations)。
在函数中使用空行来区分逻辑段(尽量少地)。
Python接受control-L(即^L)换页符作为空格;许多工具把这些字符当作页面分隔符,所以你可以在文件中使用它们来分隔相关段落。请注意,一些编辑器和基于Web的代码阅读器可能无法识别control-L为换页,将在其位置显示另一个字形。
5、源文件编码
Python核心发布版本中的代码总是以UTF-8格式编码(或者在Python2中用ASCII编码)。
使用ASCII(Python 2)或者UTF-8(Python 3)的文件不应该添加编码声明。
在标准库中,只有用作测试目的,或者注释或文档字符串需要提及作者名字而不得不使用非ASCII字符时,才能使用非默认的编码。否则,在字符串文字中包括非ASCII数据时,推荐使用\x, \u, U或N等转义符。
对于Python 3.0及其以后的版本中,标准库遵循以下原则(参见PEP 3131):Python标准库中的所有标识符都必须只采用ASCII编码的标识符,在可行的条件下也应当使用英文词(很多情况下,使用的缩写和技术术语词都不是英文)。此外,字符串文字和注释应该只包括ASCII编码。只有两种例外:
(a) 测试情况下为了测试非ASCII编码的特性
(b) 作者名字。作者名字不是由拉丁字母组成的也必须提供一个拉丁音译名。
鼓励面向全球的开源项目都采用类似的原则。
6、导入
1、imports应该分行写,而不是都写在一行,例如:
这样写也是可以的:
导入(import)始终在文件的顶部,在模块注释和文档字符串之后,在模块全局变量和常量之前。
导入顺序如下:
imports应该按照下面的顺序分组来写:
1、标准库imports
2、相关第三方imports
3、本地应用/库的特定imports
不同组的imports之前用空格隔开。
将任何相关的 __all__ 说明(specification)放在imports之后。
推荐使用绝对(absolute)imports,因为这样通常更易读,在import系统没有正确配置的情况下,也会有更好的表现(或者至少会给出错误信息):
在绝对路径比较长的情况下,也可以使用相对导入:
Python 3中已经禁止隐式的相对导入。
导入类的方法,通常可以这样写:
如果和本地命名的拼写产生了冲突,应当使用绝对导入:
禁止使用通配符导入。
通配符导入(from import *)应该避免,因为它不清楚命名空间有哪些名称存,混淆读者和许多自动化的工具。唯一的例外是重新发布对外的API时可以考虑使用。
7、模块中前后具有双下划线的变量名
像__all__ , __author__ , __version__ 等这样的模块中的变量名(也就是名字里有两个前缀下划线和两个后缀下划线),应该放在文档字符串的后面,以及除from __future__ 之外的import表达式前面。Python要求将来在模块中的导入,必须出现在除文档字符串之外的其他代码之前。
比如:
二、字符串引号
Python中单引号字符串和双引号字符串都是相同的。注意尽量避免在字符串中的反斜杠以提高可读性。
根据PEP 257, 三个引号都使用双引号。
三、表达式和语句中的空格
在下列情况下,避免使用无关的空格:
1、紧跟在小括号,中括号或者大括号后。
2、紧贴在逗号、分号或者冒号之前。
3、然而,冒号在切片中就像二元运算符,在两边应该有相同数量的空格(把它当做优先级最低的操作符)。在扩展的切片操作中,所有的冒号必须有相同的间距。例外情况:当一个切片参数被省略时,空格就被省略了。
4、紧贴在函数参数的左括号之前。
5、紧贴索引或者切片的左括号之前。
6、为了和另一个赋值语句对齐,在赋值运算符附件加多个空格。
其他建议
1、避免在尾部添加空格。因为尾部的空格通常都看不见,会产生混乱:比如,一个反斜杠后面跟一个空格的换行符,不算续行标记。有些编辑器不会保留尾空格,并且很多项目(像CPython)在pre-commit的挂钩调用中会过滤掉尾空格。
总是在二元运算符两边加一个空格:赋值(=),增量赋值(+=,-=),比较(==,,!=,,=,in,not,in,is,is not),布尔(and, or, not)。
如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空格。有时需要通过自己来判断;但是,不要使用一个以上的空格,并且在二元运算符的两边使用相同数量的空格。
2、在指定函数 关键字参数 或者 默认参数 值的时候,不要在=附近加上空格。
3、功能型注释应该使用冒号的一般性规则,并且在使用 ->的时候要在两边加空格。(参考下面的功能注释得到能够多信息)
4、当给有类型备注的参数赋值的时候,在=两边添加空格(仅针对那种有类型备注和默认值的参数)。
5、复合语句(同一行中的多个语句)通常是不允许的。
6、虽然有时候将小的代码块和 if/for/while 放在同一行没什么问题,多行语句块的情况不要这样用,同样也要避免代码行太长!
四、注释
与代码自相矛盾的注释比没注释更差。修改代码时要优先更新注释!
注释是完整的句子。如果注释是断句,首字母应该大写,除非它是小写字母开头的标识符(永远不要修改标识符的大小写)。
如果注释很短,可以省略末尾的句号。注释块通常由一个或多个段落组成。段落由完整的句子构成且每个句子应该以点号(后面要有两个空格)结束,并注意断词和空格。
非英语国家的程序员请用英语书写你的注释,除非你120%确信代码永远不会被不懂你的语言的人阅读。
1、注释块
注释块通常应用在代码前,并和这些代码有同样的缩进。每行以 '# '(除非它是注释内的缩进文本,注意#后面有空格)。
注释块内的段落用仅包含单个 '#' 的行分割。
2、行内注释
慎用行内注释(Inline Comments) 节俭使用行内注释。 行内注释是和语句在同一行,至少用两个空格和语句分开。行内注释不是必需的,重复罗嗦会使人分心。
不推荐:
但是有时,很有必要:
加了以后对理解代码很有帮助的情况下,关键处才加。
3、文档字符串
文档字符串的标准参见:PEP 257。
为所有公共模块、函数、类和方法书写文档字符串。非公开方法不一定有文档字符串,建议有注释(出现在 def 行之后)来描述这个方法做什么。
更多参考:PEP 257 文档字符串约定。注意结尾的 """ 应该单独成行,例如:
单行的文档字符串,结尾的 """ 在同一行。
4、版本标签
如果你必须在源文件中包含git、Subversion、CVS或RCS crud信息,放置在模块的文档字符串之后,任何其他代码之前,上下各用一个空行:
五、命名规范
Python库的命名约定有点混乱,不可能完全一致。但依然有些普遍推荐的命名规范的。新的模块和包 (包括第三方的框架) 应该遵循这些标准。对不同风格的已有的库,建议保持内部的一致性。
1、最重要的原则
用户可见的API命名应遵循使用约定而不是实现。
2、命名风格
以下是常见的命名方式:
b(单个小写字母)
B(单个大写字母)
lowercase (小写字母)
lower_case_with_underscores (使用下划线分隔的小写字母)
UPPERCASE( 大写字母)
UPPER_CASE_WITH_UNDERSCORES (使用下划线分隔的大写字母)
CapitalizedWords(首字母大写的单词串或驼峰缩写)
注意: 使用大写缩写时,缩写使用大写字母更好。故 HTTPServerError 比 HttpServerError 更好。
mixedCase(不同于首字母大写,第一个单词的首字母小写)
Capitalized_Words_With_Underscores(带下划线,首字母大写,巨丑无比)
还有一种风格使用短前缀分组名字。这在Python中不常用, 但出于完整性提一下。例如,os.stat()返回的元组有st_mode, st_size, st_mtime等等这样的名字(与POSIX系统调用结构体一致)。
X11库的所有公开函数以X开头, Python中通常认为是不必要的,因为属性和方法名有对象作前缀,而函数名有模块名为前缀。
下面讲述首尾有下划线的情况:
_single_leading_underscore:(单前置下划线): 弱内部使用标志。 例如"from M import " 不会导入以下划线开头的对象。
single_trailing_underscore_(单后置下划线): 用于避免与 Python关键词的冲突。 例如:
__double_leading_underscore(双前置下划线): 当用于命名类属性,会触发名字重整。 (在类FooBar中,__boo变成 _FooBar__boo)。
__double_leading_and_trailing_underscore__(双前后下划线):用户名字空间的魔法对象或属性。例如:__init__ , __import__ or __file__,不要自己发明这样的名字。
3、命名约定规范
避免采用的名字:
决不要用字符'l'(小写字母el),'O'(大写字母oh),或 'I'(大写字母eye) 作为单个字符的变量名。一些字体中,这些字符不能与数字1和0区别。用'L' 代替'l'时。
包和模块名:
模块名要简短,全部用小写字母,可使用下划线以提高可读性。包名和模块名类似,但不推荐使用下划线。
模块名对应到文件名,有些文件系统不区分大小写且截短长名字,在 Unix上不是问题,但当把代码迁移到 Mac、Windows 或 DOS 上时,就可能是个问题。当然随着系统的演进,这个问题已经不是经常出现。
另外有些模块底层用C或C++ 书写,并有对应的高层Python模块,C/C++模块名有一个前置下划线 (如:_socket)。
类名:
遵循CapWord。
接口需要文档化并且可以调用时,可能使用函数的命名规则。
注意大部分内置的名字是单个单词(或两个),CapWord只适用于异常名称和内置的常量。
异常名:
如果确实是错误,需要在类名添加后缀 "Error"。
全局变量名:
变量尽量只用于模块内部,约定类似函数。
对设计为通过 "from M import " 来使用的模块,应采用 __all__ 机制来防止导入全局变量;或者为全局变量加一个前置下划线。
函数名:
函数名应该为小写,必要时可用下划线分隔单词以增加可读性。 mixedCase(混合大小写)仅被允许用于兼容性考虑(如: threading.py)。
函数和方法的参数:
实例方法第一个参数是 'self'。
类方法第一个参数是 'cls'。
如果函数的参数名与保留关键字冲突,通常在参数名后加一个下划线。
方法名和实例变量:
同函数命名规则。
非公开方法和实例变量增加一个前置下划线。
为避免与子类命名冲突,采用两个前置下划线来触发重整。类Foo属性名为__a, 不能以 Foo.__a访问。(执著的用户还是可以通过Foo._Foo__a。) 通常双前置下划线仅被用来避免与基类的属性发生命名冲突。
常量:
<...