你最喜欢的文本编辑器揭示了你的个性
给我看你的编辑,我会告诉你你是谁。
你怎么写就是你是谁。米卡·博斯韦尔在 Unsplash 上的照片
D*isclaimer:*作者是一个狂热的 Vim 用户,因此这个故事可能不公正。此外,性别不明确的语言被用于显而易见的原因。这并不意味着这个故事是免费的刻板印象!
括号:雅皮士
雅皮士这个词什么时候不流行了?这是一种耻辱,因为它完全符合使用括号的人的类型:就是那个戴着角质框架眼镜、穿着粗花呢裤子、留着齐胸长、精心修剪过的胡子、痴迷于街角咖啡馆里的浓缩咖啡的孩子。
为什么?因为他们可以让任何网站看起来令人惊叹,括号是他们的首选工具。另外,出于无人理解的原因,这种布局让他们想起了他们最喜欢的胡须洗发水的包装…
WebStorm:JavaScript 世界的狂热爱好者
那种很聪明但是不怎么开口的人。那种有着无人知晓的狂野梦想的人。那种希望自己的名字出现在程序员名人堂,但对此保持沉默的人。
或者换句话说,普通的 JavaScript 开发人员。这是使用 WebStorm 的类型:与其他编辑器不同,这是为 JavaScript 量身定制的,它是为从事 JavaScript 世界的人设计的,没有其他用途。
行动要小,梦想要大。使用网络风暴。 Joe Ciciarelli 在 Unsplash 上拍摄的照片
Coda:网络开发者
仅仅是为了 OS X,结尾是为了隔壁那个总是带着闪亮的新 MacBook 到处跑,为网络创造难以捉摸的图形的人。
他们通常是城市流浪者,从不在一个地方呆上几个月以上。他们试着在农场工作,但注意到当他们试图编码时,鸡让他们发疯。
人们不禁会觉得,这个人在他们商务休闲装的背后隐藏着价值一千本书的生活经验。但他们擅长向外界隐藏自己的内心秘密,无论是线上还是线下。
记事本++:孩子
哦,那些仍然没有抛弃窗户的忠实的人们!欢迎来到这个头发凌乱,戴着厚厚的有色眼镜,穿着海军蓝毛衣的世界,这些毛衣看起来就像是从附近的旧货店买来的,在披萨面团中沐浴,然后清洗,直到它们足够干净,不会失去披萨服装。
或者,换句话说,欢迎来到 Notepad++ 的世界:一个用于 MS Windows 的轻量级工具,它承诺通过让你的计算机不那么忙来拯救环境。这是真的,Notepad++的用户关心他们的 CPU 空间就像关心环境一样!只有一件事他们更关心,那就是——你猜对了——披萨。
崇高的文本:梅西
他们不知道把哪个文件放在哪里,也不知道在代码的前 50 行他们把那个变量叫做什么。出于无人理解的原因,他们希望他们的文本编辑器处理所有的混乱。
欢迎来到崇高的文本——这个文本编辑器可以处理所有的混乱。有如此多的弹出窗口,甚至可以在修改和未保存的文件之间即时切换,这是那些认为他们的混乱不仅在他们的头脑中有效,而且在他们的项目中有效的人使用的编辑器。
如果你的桌子是这样的,用 Sublime。 Wonderlane 在 Unsplash 上拍照
Atom:合作者
典型的 Atom 用户是地球上最友好的人。总是穿着浅色毛衣,给整个办公室的人带早餐,有什么不喜欢的呢?
当需要帮助时,他们总是在那里,但他们从不要求表扬。总是自我牺牲,如果他们有所成就,他们会让别人去拿奖金。但是每个人都知道,没有他们什么都不会起作用。他们是每个团队的粘合剂,每本书的关节。欢迎普通的 Atom 用户。
Visual Studio 代码:完美主义者
他们的鞋子干干净净,头发梳理得整整齐齐,桌子上没有一点灰尘。他们并不是不友好,但他们是比别人先发现汤里头发的人。一切都需要完美;他们的生活中没有多余的垃圾。
他们的编码风格也是如此。绝不——我再说一遍,绝不!—他们会把自己的名字写在一段包含哪怕是最微小错误的代码下面吗?这是 Visual Studio 代码的用户:调试变得如此简单,你甚至不再需要编译器。每个厌恶 bug 的程序员的必备工具。
NetBeans:咖啡店
绿豆,咖啡豆,网豆。神圣三和弦!
普通 NetBeans 用户对代码和 beans 非常着迷。尤其是豆子。一天的开始离不开他们最喜欢的咖啡店里的圣咖啡豆。在那之后,他们会呆上一整天,疯狂地敲击键盘。
他们是焦虑型的。总是害怕失去。穿着略低于休闲(那些牛仔裤真的需要洗一洗),总是有点神经过敏,注意力不集中,他们真的不需要咖啡来唤醒他们。*他们需要咖啡来平静自己。*当然还有代码。
自动机
有些人是天生的工程师。做一次任务?无聊。做两次?自动化!
这是你对 TextMate 的普通用户:OS X 的一名工程师(因为这是它运行的唯一系统)。办公室角落里那个安静的人。那些似乎从不努力工作的人,他们的结果却是惊人的。在会议上话不多,但问出精彩问题的人。不怎么社交,但总能帮你解决问题的人。
唯一的缺点是?他们的工作经常不被人注意。他们可能需要几年时间才能得到认可。那是你的 TextMate 的普通用户。
IntelliJ:优化器
在你的朋友群中,总有那么一个人对每一个新的生产力黑客技术着迷。IntelliJ 的普通用户就是这样的朋友。
他们是几年前在咖啡里放黄油的人,练习最极端形式的间歇禁食,在凌晨 4 点喝蛋白奶昔的人。如果你给他们一块蛋糕,他们会欣然接受——但只能在五个小时内吃完,也就是斋戒结束后。
他们的着装风格首先是功能性的,他们的发型也是如此。品味并不差,只是没有其他服装所具有的 X 因素。
但是,尽管所有的焦点都集中在生产力上,他们并不总是产出最高的那一个…
如果你只说不做,那么 Dreamweaver 就适合你。格雷戈里·海斯在 Unsplash 上的照片
Dreamweaver:自我
他们的头发是光滑的,他们的衬衫是新熨的,他们的西装值一个月的工资。他们看起来很好,但不太好说话——因为除了他们自己,他们不知道任何其他话题。他们认为自己很聪明,但他们的技术能力稍显不足。他们认为他们在学习,但实际上他们只是在吹牛。
欢迎你的普通用户使用 Dreamweaver :完整的可视化界面,这是一个用于炫耀的编辑器。暗地里,他们不喜欢编码。他们不喜欢命令行界面的吸引力,也不了解自动化的力量。他们宁愿用那个时髦的新网站模板给同事留下深刻印象。为什么不呢?这让他们在职业生涯中走得更远。
维姆:极客中的极客
最近三年没有理发,最近五个月没有刷牙的人。那个还穿着妈妈的毛衣去上班的人。鞋子快散架了却拒绝买新鞋的人(“85%的材料还完好无损!”).
欢迎你成为 Vim 的普通用户:没有比这更令人讨厌的了。
二分之一的编辑战,Vim 是为那些严格按照系统类别思考并且不需要太多个性化的人准备的。Vim 是为那些喜欢学习一个结构,然后永远不要放弃它的人准备的。Vim 是为极客中的极客准备的。
Emacs:优柔寡断
Emacs 是所有尚未达到极客状态的书呆子的首选编辑器。这就是那种对图形用户界面略有反感,但又离不开的书呆子。那种喜欢编码,但仍然希望他们的文本编辑器不仅仅能够编码的书呆子。
角落里那个总是喝桃红葡萄酒的书呆子。当被问及一个非黑即白的问题时,会用一个精心设计的灰色来回答的人。上午 11 点起床的人,不是因为他们之前在睡觉,而是因为他们太忙于思考起床的最佳时间。
你不擅长做决定?使用 Emacs。
告诉我你的编辑,我就能知道你是不是一个极客。玛丽亚·卡斯泰利在 Unsplash 上的照片
SpaceMacs:和平缔造者
你的普通 SpaceMacs 用户是学术界的教师。优雅地穿着破旧的衣服。带着新鲜的仙人掌在难闻的办公室里。带着疲惫眼神的灿烂笑容。一种既怪异又有感染力的笑声。
他们是想退出编辑战的人。一个不像 Emacs 用户那样优柔寡断的人,但也不像 Vimmer 那样绝对古怪。一个永远不想站在舞台中央的人。依赖和谐的人。通常带有紫色终端背景。
欢迎来到传统而平凡的太空中心。
弗罗斯特:文学先知
能写剧谁还需要代码?戴着厚厚的眼镜穿着粗花呢夹克的书呆子才会这么说。你知道,就是那个每天晚上坐在酒吧角落里啜饮白兰地,认为这样会显得更聪明的人。
他们说,代码只是一种趋势。莎士比亚、歌德、柏拉图、佛陀等都将留下来。他们打开他们的 Frost 编辑器,选择一个令人惊叹的内置音乐主题,然后开始破解。编码员会说这个书呆子的写作是莎士比亚式的。文学天才们说他们的作品看起来更像计算机代码。
CodeLobster:如果你能让它变得复杂,为什么会变得简单?
你典型的 CodeLobster 程序员不相信简单事物中的快乐。相反,他们会尽可能地把事情复杂化。非常复杂。
如果他们制作鸡尾酒,它需要包含至少 18 种成分。如果他们使用浏览器,那么只有一个至少有 27 个插件。如果他们使用的是文本编辑器,那么就应该是一个兼容所有内容、能够处理所有事情的编辑器。嗯,几乎所有的事情。你明白了。
你就是你编码的东西
…或者你如何编码。
你选择你的文本编辑器是基于你是谁吗?还是你的文本编辑器把你塑造成了今天的你?你决定吧。
2020 年 3 月 5 日编辑:正如 Tylor Borgeson 所指出的,IntelliJ 在这篇文章发表时失踪了。现在包含了!
还有,在Edmund munday的评论 Java-World 更名为 JavaScript-World——以澄清 JavaScript 与 Java 有很大不同。
编辑,2020 年 3 月 21 日:我在 NetBeans 上添加了一个全新的部分,专门针对 麸皮老林 !
编辑,2020 年 10 月 6 日:我已经收录了 曼西达克辛格 的 霜降 编辑!没有赞助的内容,只是很酷的东西。
你的终端颜色揭示了你的个性
让我看看你的终端,我会告诉你你的感受
你的终端颜色比你想象的要多。史蒂夫·哈拉马在 Unsplash 上拍摄的照片
编码是一门艺术。所以颜色总是交易的一部分!
正确使用时,颜色可以提高速度和可读性。但最重要的是,它们是程序员个性的一面镜子。
有些人比其他人更多地通过颜色来表达自己——这已经充分说明了他们的自我。一些人选择自定义他们的背景,另一些人喜欢让文本看起来像一堆 M&M。其他人两样都做。
每个方面都讲述了一个关于你是一个程序员的故事,以及你在日常生活中的感受。
背景颜色
你如何给背景上色揭示了你的舒适区。你的终端背景就是你每天看的东西,不管你是不是在编码。因此,你如何保持你的背景说明了你每天的感受。
黑色优雅
优雅来自黑色。你悠闲、时尚,而且你有那种确定的精神,不管你是否在编码。
你的同事认为你是个超额完成任务的人。他们认为你几乎是个名人,尽管你在 Twitter 上只有区区 30 个粉丝。你既不是名人,也不是成功者,但你知道如何推销自己。
你说话的时候,声音很大。毕竟,如果没人听到你说话,为什么要说话呢?
你是一个充分享受生活的人。
你活着。你爱。你放纵。但绝不会堕落到如此地步。
你是一个在纪律和放纵之间走钢丝的艺术家。你的终端正好反映了这一点。
又白又乱
你不认为自己没有组织能力。你只是钦佩别人的组织水平。
当你醒来时,你不知道明天会发生什么。你讨厌计划,因为那会打乱你的节奏。
你办公室的每一面都堆满了文件夹、笔记和一些去年圣诞节的礼物。你忘记了你最喜欢的咖啡杯去了哪里;它可能藏在几本书后面的某个地方。
说到咖啡——啊,咖啡因!你的圣杯和你生产力的唯一秘密。不管这让你更加紧张不安。来喝杯咖啡,开始编码吧!
灰色的老鼠
这是为每一个灰色阴影的用户。你无法决定非黑即白。你不会想要一种颜色,因为那会太分散注意力。
你喜欢保持东西的功能性:你选择了浅灰色,因为白色对你来说太亮了。或者你选择了深灰色,因为黑色对你来说太黑了。
你优柔寡断,但并不低效。你完成了工作,但不要大声说出来。开会时,你通常坐在角落里,除非被要求,否则从不发言。
你喜欢把私人的事情保持为私人的,把商业的事情保持为职业的。你不喜欢大声说话,因为那样会浪费精力。你没有任何政治观点,因为那会引起争议。最重要的是,你不喜欢引起别人的注意。
你有灰色终端?你完全是一只灰色的老鼠。
你用颜色来表达自己。由edu·劳顿在 Unsplash 上拍摄的照片
单色古怪
你厌倦了黑色、白色和灰色。你希望你的终端是你最喜欢的颜色,或者至少是一种能引起你注意的颜色。
你喜欢用各种方式表达自己。你代码中的变量名是独一无二的,你的服装风格无疑就是你。你喜欢艺术、音乐和喜剧。
你是程序员中的异类。你总是鹤立鸡群。你很享受。
你用你的终端颜色来表达你是谁。
你的终端是红色的?你是个了不起的爱人。
绿色?你永远不会停止学习。
黄色?你就像一缕阳光。
蓝色?你喜欢技术性的东西,天空和大海…
紫色?你是个伪装的怪人。人们甚至没有意识到你脑子里所有疯狂的想法!
海报男孩
你尝试过单色背景,但是你很快就厌倦了。你更喜欢用你最喜欢的星系的照片,或者你的第一只泰迪熊的照片,或者你妈妈的照片…
人们说你古怪,但实际上你只是个大孩子。好奇心是你前进的动力。编程是你的职业,因为它总是关于学习新的东西。
你对一切甜美多彩的事物都有着巨大的、无法控制的吸引力。你的注意力持续时间相当于一个三岁的孩子;每一次分心都会让你迷失方向。
尽管如此,你在工作中始终如一。你源源不断的想法弥补了你注意力的不足。
标准的终端外观只是白底黑字。苹果包括了一些不错的预置…
osxdaily.com](https://osxdaily.com/2013/02/05/improve-terminal-appearance-mac-os-x/) [## 如何改变你的 Linux 终端的颜色
您可以使用特殊的 ANSI 编码设置为您的 Linux 终端添加颜色,或者在终端命令中动态地添加颜色…
opensource.com](https://opensource.com/article/19/9/linux-terminal-colors)
文本颜色
文字激发行动。它是在你的屏幕上来来去去的东西。你使用的文本颜色反映了你的动机。
这反过来也说明了你是谁。
单色提交
你不喜欢你的文本看起来像一袋 M&M 巧克力豆。你宁愿选择传统的黑色、白色或灰色。那只是你有多爱你的手艺。
你对一切都很投入。那个永远准时,永远付出 150%,永远有有用的话要说的人——那就是你。你的输出是一致的,而且是高水平的。当你说好的时候,你是认真的。
有些人可能会说你傲慢。你总是带着灿烂的笑容走进办公室,对某人正在做的事情发表一些评论。通常情况下,这可能是一种侮辱——因为你的想法是错误的,脱离了上下文。你有强烈的倾向向你认识的每个人展示你更好。
但你不知道更好。你只是热爱你的工作。
承诺是单色者的关键。照片由 @plqml // felipe pelaquim 在 Unsplash 上拍摄
违约灵活性
大多数系统都有默认的配色方案。尽管在过去十年左右的时间里你一直在编码,但你并没有改变那个模式。千万不要碰正在运行的系统!
你可以和任何东西一起工作。灵活性是你的第二个名字。
十分钟后有个自发会议?赶紧塞几张幻灯片。必须使用完全不同的软件?哦,是的,你喜欢变化!你的猫生病了?没问题,你今天做家庭办公室。
不利的一面是,人们认为你有点不可靠。你不是那种每天都在同一时间出现在办公室的人——有时候,你的猫生病了。人们永远不知道当你交付结果时会有什么期望——这取决于它是在什么样的环境中编写的,对吗?
古怪的定制
您已经尝试使用默认的配色方案,但是您发现它既笨拙又低效。所以你花了半天左右的时间来为你的文字寻找完美的颜色。
走过你的笔记本电脑的人会发现你的设计非常吸引眼球。但是他们不知道每种颜色的真正含义。只有你知道。
你的颜色只属于你。同理,你的生命只属于你。你非常保守,把事情藏在心里。你学到了很多,却懒得和别人分享你的知识。你不喜欢在会议上发言——但当你这样做时,你的投入非常出色。
你非常聪明,但有时你最好分享你的智慧。是的,甚至你的配色方案!
你是个书呆子——你定制一切。奥比·奥尼耶德在 Unsplash 上拍摄的照片
一致且高效
当然,您已经在终端中定制了颜色。毕竟,人们应该如何处理那些蹩脚的默认颜色呢?
你大脑的容量是你最宝贵的资源。你不喜欢在不同环境下不同颜色的使用上浪费任何心思。这就是为什么您不仅定制了您的 shell,还以同样的方式定制了您的文本编辑器!
你在工作中始终如一,总是能取得高水平的成果。你认为这是因为你不会在颜色这样的小事上浪费时间。
这就是你提高效率的方法:清除杂物,剩下的事情自然就好了。而且显然很管用!
[## 具有 16 种 ANSI 颜色 Vim 主题的一致终端颜色
不是分别为 Vim 和终端的其余部分配置颜色,而是将 Vim 的配色方案限制为 16…
jeffkreeftmeijer.com](https://jeffkreeftmeijer.com/vim-16-color/)
你是一致的还是矛盾的?
一致性是关键,个性也是如此——但矛盾更有趣!
在这个故事中,我们已经回顾了五种背景颜色和四种文本。如果我们允许每种组合,我们会得到二十种不同类型的终端颜色。
背景中揭示的一些个性特征也可能在文本中得到反映。其他的可能是完全矛盾的。
而人类不都是行走矛盾吗?虽然一致的类型确实出现得更频繁,但有趣的是矛盾的类型。
详细阐述每一个矛盾的类型会扩大这个故事的范围。但也许你自己也是矛盾型的?你如何解释你的一致性和矛盾性?
你的 WhatsApp 信息告诉你什么是快乐,5 个简单的 Python 步骤
WhatsApp 聊天情感分析入门指南
齐比克在 Unsplash 上的照片
在过去的几年里,情感分析和其他形式的自然语言处理变得越来越流行,尤其是 Python。虽然我已经在其他平台上运行情感分析和其他文本分析很多年了,但我想扩大我的学习范围,探索用 Python 来运行它,这是一种我还不太熟悉的语言。
希望这可以作为对情感分析相对陌生的人的指南。
5 个步骤
有时有人向我指出,我是一个相当消极的人。不是否定,但我强烈反对。
所以我想我应该测试一下,在我的 WhatsApp 群组对话中进行情绪分析,看看我和朋友/家人在快乐方面相比如何。如果你想“找到自己的幸福”,下面是我采取的步骤:
1.提取您的 WhatsApp 对话
这出奇的容易。单击组名并点击导出(如下所示)。它会下载一个 Zip 文件,解压后会给你一个. txt 文件。
2.打开 Python 并将 Flair 导入 Python 包
Flair 是由 Zalando Research 开发和开源的自然语言处理(NLP)库。我不会在这里详细介绍,只是说我选择使用它的原因是因为它简单易用,包括随时可用的情感分析。关于为什么它是一个很好的博客,有很多其他的博客。
!pip3 install flair
import flair
import pandas as pd
3.带上。txt 文件转换成 Python 并做一些基本的清理工作
的。txt 文件需要快速解析成单独的列。我只是在这里提取“日期”、“人”和“消息”:
***# bring in data and give it header 'text'***
data = pd.read_table('YourPathHere/_chat.txt', names=['text'], header=None)***#get rid of top 2 rows (e.g. "this chat is encrypted" etc.)***
data = data.iloc[3:]
data.head()***# parse the data into the columns 'date', 'person', and 'message'***
data[['date','remaining']] = data['text'].str.split(']',expand=True, n=1)
data[['person','message']] = data['remaining'].str.split(':', n=1, expand=True)data.drop(['text', 'remaining'], axis=1, inplace=True)
data
在进行任何情感分析之前,我们都希望去掉任何我们不想向下游传递情感的行。这可能包括任何空值,也可能包括任何简短的响应消息(例如“Ok”、“Lol”或“Thanks”)。此外,为了进行任何时间序列分析,将我们的日期字段转换为实际的日期数据类型是有意义的:
***# get rid of all the "image omitted"***
data = data[~data["message"].str.contains("omitted", na=False)]***# remove null rows***
data.dropna(inplace=True)***# remove any small messages***
data = data[data['message'].map(len) > 10]***# sort of the date into a proper date column***
data['date'] = data['date'].map(lambda x: x.replace(',',''))
data['date'] = data['date'].map(lambda x: x.strip('['))
data['date'] = pd.to_datetime(data['date'], format="%d/%m/%Y %H:%M:%S", errors='coerce')
data.head()
4.运行情绪分析
我使用 flair _ perspective . predict()来提供标签,这些标签将告诉我们值是正还是负,以及预测的置信度的 0 到 1 分。
sentiment = []
def run_sentiment(a):
b = flair.data.Sentence(a)
flair_sentiment.predict(b)
sentiment.append(b.labels)data['message'].apply(lambda x: run_sentiment(x))
data['sentiment'] = sentiment
5.想象并理解你的结果
是时候快速看到结果了。你现在可以直接在 Python 中运行可视化,或者像我下面这样进入 Tableau。
开心了吗?
显然我不是最消极的。我很激动。
为了方便截图,我在这里“匿名”了一些人的名字,但我个人最喜欢的是分散图左下角的人:他们很少说话,但当他们说话时,这是这个群体收到的最负面的东西。感谢您的参与。
同样明显的是,实际上我们当中没有人特别积极,这并不令人惊讶。唯一真正的例外是在 5 月,可能是因为这是宣布体育运动再次开始的时候(这是这个小组讨论最多的话题)。
最后的想法
我选择分享这个,因为我在 Python 中找不到太多简单的情绪分析例子。希望它对其他不熟悉 Python 的人也有用。
同样,我绝对欢迎任何反馈或提示,以改善这里列出的任何东西。
你买的不是人工智能:如何区分事实和虚构
“人工智能”这个时髦词被频繁使用。这可能意味着简单的自动化,甚至 excel 公式。你是怎么发现的?
当涉及到人工智能(AI)的产品时,越来越难区分真假。事实上,这很难,约会应用程序现在用假脸来增加他们的数量,广告商甚至用它们来增加广告的多样性。围绕人工智能的这种模糊性范围很广,并且在我们许多人不知道的情况下,进一步蔓延到我们的日常生活中。
对这种生成性媒体的使用既有非法的,也有良性的。
根据处方制作的人造脸——库存照片的商业替代品(来源:生成的照片
这些是人工智能在现实世界中帮助伪造的例子。但是,技术提供商一开始试图伪造人工智能解决方案怎么办?
在商界,“人工智能”这个时髦词经常被提起。即使是对技术有基本了解的人也经常把它与简单的自动化、统计测试甚至 excel 公式混为一谈。
研究发现,40%的欧洲人工智能初创公司实际上并不使用人工智能,其中许多公司没有纠正第三方分析网站因围绕该技术的炒作而做出的错误分类。公司秘密使用人类来做人工智能机器人的工作并不罕见。
在这种情况下,当您的组织准备好开始人工智能之旅时,您如何评估技术解决方案?有一些你应该问的标准问题,以确保你得到你所支付的东西。这些准则适用于评估任何“智能”机器学习解决方案,包括人工智能等先进技术。
真的还是假的 AI?要问的首要问题
所以,你决定扩展你的能力,投资人工智能。问这六个问题可以很好地了解你得到了什么,以及它实际上有多先进。
1.它是如何工作的?
首先问一个供应商他们的解决方案到底是如何工作的,为什么它是人工智能的一个例子。很好地理解它如何做它声称要做的事情,并质疑为什么自动化或更简单的技术不够。一家销售人工智能技术的公司应该能够以一种易于理解的方式解释对人工智能的需求以及他们使用的方法。不要担心在这里听起来很幼稚。
有了这个,你就可以开始区分人工智能算法和出色的营销了。例如,一个向客户推荐产品的系统可以建立在简单的商业启发之上,也可以由人工智能驱动。提出试探性的问题必须是你揭开真相的第一步。
2.解决方案是否基于数据?
任何人工智能解决方案都需要大量数据。数据使人工智能变得聪明,所以找出哪些数据被用来训练人工智能。例如,Open AI 的 GPT 2 模型具有撰写新闻文章的能力,并在数百万篇维基百科文章上接受了训练,从而赋予它智能。
询问供应商你必须提供什么数据来保持人工智能在使用中的智能。如果没有对数据的强烈需求,这是一个潜在的危险信号。
美国宇航局在 Unsplash 拍摄的照片
3.数据是如何标注的?
对于今天的许多人工智能来说,数据需要以某种格式标记,以便人工智能理解。为了训练人工智能阅读图像并识别属性,获得高质量的图像是不够的。它们必须被仔细标记,以便人工智能从中学习。在面部识别的情况下,人类需要在每个人的脸上画出方框,以首先教会人工智能人脸是什么样子的。
询问 AI 厂商他们如何标记他们的数据,以及当你部署它时,这种标记是否需要继续——这是 AI 是否真正从数据中学习的另一个标志。
来源: mc.ai
4.有没有一个学习的过程?
传统的技术解决方案会以第一次运行程序的方式运行第一百万次。当涉及到人工智能时,解决方案可能会在每次运行数据时进行学习,并根据每次反馈进行调整。
提出问题以了解学习过程和你必须提供的反馈类型。例如,当你在 Gmail 中将一封电子邮件标记为重要时,人工智能会从中学习,以改善未来所有电子邮件的分类。这是一个智能应用程序简单、持续学习的例子。一个不接受这种明确反馈的系统可能终究不是“智能”的。
5.应用程序需要什么样的维护?
像人类一样,任何人工智能都需要处于不断改进的状态,才能保持相关性。一个非人工智能的标准技术应用程序将提供预期的功能,几乎不需要维护。然而,真正的人工智能需要学习新数据,并定期调整内部智能。
如果你看不到一个明确的路线图,让智能保持最新或随着时间的推移而改进,那就是一个危险信号。例如,一个准确预测员工流失的人工智能在几个月后就不会那么好了。它需要重新学习员工动态、业务场景和市场条件的变化。
JESHOOTS.COM在 Unsplash 上拍照
6.我能看一下我公司的现场演示吗?
大多数人工智能演示在精心策划的场景中工作,并作为试点。任何高质量人工智能解决方案的供应商都应该提供他们产品的现场演示,而不仅仅是营销视频。如果他们能拿着你的数据用 AI 解决方案兜一圈就更好了。
例如,一个能够识别选定领域法律文档风险的人工智能解决方案,应该能够证明它能够识别你上传的类似文档的风险。在现场演示解决方案时犹豫不决可能是问题的早期迹象。
由于许多公司继续“驾驭人工智能的浪潮”,而没有实际提供人工智能解决方案,因此业务团队自学如何识别真假非常重要。从上面列出的问题开始讲区别,继续加深你对 AI 在实践中是什么样子的认识,以避免落入陷阱。
这篇文章最初是在 Entrepreneur.com**发表的 。增加了插图。标题照片由 埃里克·克鲁尔 上的Unsplash。
对数据科学感兴趣但不确定从哪里开始?查看我关于 的文章,了解何时以及如何组建您的数据科学团队 。
什么是容器,我为什么要关心?
消除容器的神秘和困惑,以及为什么今天应该使用它们
托德·克雷文在 Unsplash 上的照片
啊,集装箱,科技界的勒布朗·詹姆斯。如果你以任何身份关注美国体育,你可能对勒布朗·詹姆斯有足够的了解,可以和别人就他进行一次有意义的谈话。然而,如果你不关注任何体育运动,鉴于他在娱乐和新闻媒体上无处不在的形象,你可能至少还知道他的名字,但可能会发现自己处于一种尴尬的境地,有人提到“国王”,并希望你简单地跳进去,知道最近发生了什么以及他昨晚掉了多少分。
技术世界中的容器也是如此。无论我们在哪里看到,都有人在编写另一个关于容器化他们的小发明的故事,或者容器编排对您的业务至关重要,或者您需要转向为您部署和维护容器的云提供商。如果您已经对容器有所了解,那么这些文章很有价值,可以帮助您了解如何进一步利用该技术来获得更多价值。然而,如果你不属于这一类,你可能知道的关于容器的唯一事情就是你应该知道更多关于容器的事情。这篇文章旨在回答一些关于什么是容器以及在工作中应该如何和为什么使用容器的基本问题。我将使用一个愚蠢的类比从基础开始,最终进展到容器实际如何工作的更多技术描述。
容器和纸杯蛋糕有什么共同点?照片由雷伊·戈德曼在 Unsplash 拍摄
集装箱纸杯蛋糕
在我深入研究这项技术之前,让我们先用一个简单的类比来解释容器的用途以及它们为什么有用。举个例子,假设我拥有一家个人纸杯蛋糕公司,在家里烘焙并出售纸杯蛋糕。我知道厨房里的所有东西都在哪里,我知道如何使用我的烤箱和搅拌器,我有我需要的烤盘,知道糖在我当地杂货店的哪个通道,哪个品牌的蛋糕适合我的完美蛋糕。每样东西都完全符合我的需求,我能够做出完全一样的美味纸杯蛋糕,并且可以在家里轻松出售。
现在,假设我的纸杯蛋糕在中欧迅速走红,潜在顾客会求我在阿尔卑斯山开店。什么会出错?有明显的需求,而且我是做纸杯蛋糕的专家,所以为什么不开一家新店来增加我的收入呢?在搬到瑞士并为我的生意租了一个新的面包店后,我很快遇到了一些问题。杂货店在哪里,我用什么牌子的糖?为什么我找不到和我习惯的尺寸差不多的烤盘?为什么烤箱的测量单位是摄氏度,我如何打开计时器?我习惯的每次都能持续搅拌面糊的电动搅拌器在哪里?我甚至不得不担心在不同的海拔和温度下烹饪会改变食物的烘烤方式。最重要的是,我不会说瑞士德语,无法寻求帮助。
在努力做好我的第一批蛋糕后,蛋糕沉了下去,尝起来又苦又有点焦。我的失望是无法估量的,我的一天就这样毁了。哪里出了问题,怎么会更好?进入神奇的集装箱。
让我们从头开始,但是这次做一些改变。让我们想象一下,我把一个神奇的海运集装箱放在我家前面的草坪上,并在那里工作,而不是直接在我家外面经营我最初的生意。现在,我提到这是一个神奇的集装箱,因为我可以将我需要的一切无限量地放入这个结构中,并且它有足够的内部空间。我完全按照我喜欢的方式设计容器,有我最喜欢的烤箱、搅拌器和平底锅,足够的柜台空间,以及我制作美味纸杯蛋糕所需的所有配料。我甚至把容器设置到完美的温度、压力和湿度,这样一切都是一样的。由于我的配料永远不会用完,我可以专门在这个容器中工作,并通过我在单元前面制作的窗口出售纸杯蛋糕(我也没有其他爱好、义务或其他人类需求来将我从工作中抽离)。
当这一次纸杯蛋糕像病毒一样传播开来时,我没有放下一切,试图在瑞士重新开始,而是把我的神奇海运集装箱送到海外,在山里重新打开。这一次,我的容器里的所有东西都是我想要的样子。我有我需要的所有材料,并且可以复制我的纸杯蛋糕,所以它们看起来和尝起来都和在家里一样,尽管在一个完全不同的环境中。
有了这个容器,当我的纸杯蛋糕毫无疑问地在北京、约翰内斯堡、里约热内卢,甚至在月球上变得受欢迎时,我可以移动我的容器,或者更好的是,简单地创建一个副本,并立即开始与当地的客户分享我的精彩纸杯蛋糕。多亏了我的神奇容器,我再也不用担心我将要工作的底层环境,而是可以愉快地专注于手头的任务。
Giu Vicente 在 Unsplash 上拍摄的照片
回到现实
尽管我们都爱纸杯蛋糕和神奇的海运集装箱,但让我们跳回现实,看看这与现实世界有何关联,以及是什么让集装箱变得有用。
很有可能,你在生活中的某个时候听过或说过“奇怪,它对我有用”这句话。如果你像世界上绝大多数人一样(包括我自己),你讨厌听到这句话,但是当你是说这句话的人时,把它当作一个安全网。在技术世界中,这种小情况发生得比大多数人愿意承认的要多,因为硬件、网络、软件环境,甚至文档实践都因人而异,因机器而异,将过多的随机变量扔进混合物中,阻止应用程序或用例被可靠地复制。
即使依赖项、设置和其他工具都被精确地记录下来,复制一个工作设置也需要很长时间,并且仍然有可能其中一个步骤执行不正确。回到纸杯蛋糕的比喻,即使我知道如何找到我的纸杯蛋糕所需的所有工具和配料,我也要花很长时间才能在一个新的地方得到我需要的一切,而不是把我的容器带到我已经拥有一切的地方。有了我的集装箱,我可以立即开始烘烤,而不是浪费几天、几周甚至几个月来准备一切。
由于有了容器,可以消除许多随机性和浪费的时间,因为可以创建一个只包含必要的包、设置和实用程序的标准化映像,以确保一个通用的操作环境,而不管应用程序在哪里运行。也就是说,到底什么是容器,它是如何工作的?
集装箱仅供参考
对容器的标准描述通常是称其为“轻量级虚拟机(VM)”或“名称空间隔离器”虽然这些都是准确的描述,但它们并不是所有用户都能完全理解的,也不能可靠地解释它们做什么和如何工作。为了更好地理解,让我们进一步分解它们。
对于那些不知道的人来说,顾名思义,虚拟机是在主机上运行的虚拟化计算机。换句话说,它是一个共享物理资源(内存、CPU、存储等)的仿真计算机系统。)与运行 VM 的机器。虚拟机允许您在物理设备上运行不同的操作系统(OS ),而无需双重引导至不同的 OS。虚拟机被称为“来宾”,每个虚拟机都在所谓的虚拟机管理程序(我们不会在这里讨论)之上运行唯一的来宾操作系统。随着单台机器上虚拟机数量的增加,运行所有来宾操作系统所需的空间和资源也会随之增加,主机可能会因为所有的限制而陷入困境。
相反,容器运行在主机操作系统之上,不需要第二个客户操作系统来运行。每个容器共享主机的内核,并有可能在必要时共享库和二进制文件。因为这些容器不需要它们自己的独立资源,所以它们最终比基于 VM 的容器小得多,因此被称为“轻量级 VM”任何特定的虚拟机都可能有几千兆字节大小,启动需要几分钟,而几乎相同的容器占用几兆字节,可以在几秒钟内启动。
唯一主机和容器命名空间的可视化表示
名称空间隔离
Linux 有一个被称为名称空间的特殊特性,它是在不同资源之间划分或“隔离”的一种方式。这些名称空间包括用户列表、进程 id 和网络资源。任何使用与宿主不同的命名空间的进程都与宿主的资源隔离。例如,具有不同用户名称空间的应用程序将拥有一组唯一的用户 ID,所有用户 ID 都拥有特定应用程序所需的权限。如果您希望某个特定用户拥有某个应用程序的特权,而不是更大的主机的特权,这是很有用的。
隔离名称空间的过程是容器的基础,因为默认情况下,除了主机之外,所有容器都使用自己唯一的名称空间。这允许对容器内运行的所有应用程序进行更好的控制和更具体的控制。
共享网络和 IPC 命名空间的容器和主机的可视化表示
然而,请注意,容器不需要与它们的主机完全隔离。上图显示了一个与主机共享 IPC 和网络名称空间的容器,允许容器使用与主机相同的网络接口以及共享内存。共享命名空间只有在应用程序需要时才有用,例如在为 web 应用程序共享网络命名空间时,使用与主机相同的主机名、网络接口和 IP 地址。
为什么所有这些都很重要?给定这些名称空间的划分,容器变得可复制,并且更能避免各种依赖性、配置或资源问题,这些问题会阻止应用程序在不同的机器上可靠地运行。因此,容器可以很容易地在完全不同的系统上复制,并按预期运行,因为没有其他进程、包和设置妨碍。这还有一个额外的好处,即更复杂的操作可以在容器内完成,而不会干扰主机。
尼克·吉奥在 Unsplash 上的照片
最终蜂鸣器
现在,您有望对什么是容器以及一些关键原则有一个相当好的理解。利用容器是证明您的应用程序是快速、轻量级的,最重要的是,是可再现的一个很好的实践。即使在容器中运行简单的应用程序也能给软件的开发和部署带来巨大的好处。
虽然您可能仍然不知道“国王”下一个追逐的记录是什么,但您现在已经准备好成为您工作的容器的国王或女王,并了解它们如何在实现您的软件梦想中发挥关键作用。请继续关注未来关于如何在实践中构建、运行和部署容器的文章,这样您就可以真正开始统治您的容器王国了。
对数是什么?
Joel&Jasmin fr estbird 在 Unsplash 上拍摄的照片
我们为什么需要它们?
你可能在高中数学课上学到了它们,然后就再也没想过它们。我承认,直到今天,对数(简称 log)都不是我最好的朋友。它们并不那么直观。但它们真的很有用,所以我学会了勉强接受它们。
定义
对数是这样一个问题的答案:我需要将什么样的次方 x 应用于以 b 为底的才能获得数字 y :
log_b(y) = xis another way of specifying the relationship:b^x = y
让我们插入一些数字来使这一点更清楚。我们以 10 为基数,所以 b=10。
log_10(100) = 2The base-10 logarithm of 100 is 2 because:10^2 = 100
基本上就是问我需要多少个 b 相乘才能得到 y,要得到 100,我只需要把两个 10相乘。
这实际上是处理乘法序列的一个很好的方法。
Assume something is growing at a changing rate denoted by rn. Over 3 years, its total growth rate is:**(1+r1)*(1+r2)*(1+r3)**In log-scale, we would just take the log of the entire thing:
*(I will use log to denote log_10 to simplify notation)*One rule of logs is that *log(A*B*C) = log(A) + log(B) + log(C) so:***log{(1+r1)*(1+r2)*(1+r3)}
= log(1+r1) + log(1+r2) + log(1+r3)**Now let's think about log(1+r1) - it's asking what power do I need to apply to 10 so that it equals (1+r1):
**10^z1 = 1+r1, so log(1+r1) = z1
10^z2 = 1+r2, so log(1+r2) = z2
10^z3 = 1+r3, so log(1+r3) = z3**This allows us to rewrite each term, and the previous equation simplifies to:
**log(1+r1) + log(1+r2) + log(1+r3)
= z1 + z2 + z3****Thus, in log-space, a multiplicative sequence becomes an additive one:
log{(1+r1)*(1+r2)*(1+r3)} = z1 + z2 + z3**
一个例子
普通的非数学爱好者最有可能在以对数标度绘制的图表上遇到对数。例如,以下是美国新冠肺炎病例总数的对数比例(基数为 10)图:
美国新冠肺炎病例总数的十进制对数
当我看到对数尺度的图表时,我总是要花一秒钟来确定自己的方向。y 轴上的数字是什么意思?当剧情开始变平,趋于平稳,意味着什么?
让我们来看看美国案例总数的原始未记录数据。所以我们可以更容易地进行比较,我在上面的图表中绘制了未记录的数据,在下面的图表中绘制了记录的版本(与前面的图相同)。
原始美国案例总数及其基数为 10 的日志
除了病例在短短 200 多天内从 0 迅速增加到近 600 万以外,我们从顶部副曲线(未记录的数据)中没有收集到太多信息。但我们真正想知道的是感染率是否在下降,使用未记录的数据是不可能知道的。事实上,由于缩放比例(以及开始时未记录的数据的明显平坦性),一个没有经验的分析师在查看该图表时可能会错误地得出结论,感染率在突然加速之前的前 50 天非常低。
那将与现实完全相反。对数标度的救援。我马上会解释它是如何工作的,但是现在请相信我:
- 对数刻度线斜率的增加意味着感染率在增加。
- 恒定的斜率意味着感染率没有变化。
- 斜率的降低意味着感染率在下降。
- y 轴是基数的幂。在这种情况下,因为 y 轴是以 10 为底,1 表示 10,2 表示 10,依此类推。
回到我们的图,我们可以看到对数标度图讲述了一个完全不同的故事。在减速前的头 75 天左右,感染率实际上非常高。所以对数可以很快告诉我们某个东西的变化率是在增加(比如汽车加速),保持不变,还是在减少(逐渐踩下刹车)。让我们再举一个例子,看看对数如何帮助我们更好地观察数据的增长趋势。假设我们的数据以下列高速度增长,但持续下降:
rates = [1.5, 1.4, 1.3, 1.2, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3]
从未记录的图(左)来看,我真的不知道增长率是否在下降。但是从对数坐标图(右)来看,增长正在放缓是显而易见的。
日志帮助我们更好地看到增长率的变化
我们为什么关心?
对我来说,当我学习数学的时候,我经常缺少的是知道为什么我应该关心一个特定的概念。所以从实际意义上来说,为什么日志很重要呢?
答案是(还有其他的,但这是最实际的一个)日志让我们在处理呈指数增长的事物时有更大的灵活性。与普遍的看法相反,指数增长并不总是像一棵树长到天上一样,它仅仅意味着数据以合理的恒定速率复合(或衰减)。指数增长的一些例子有:
- 储蓄账户。这些天可能没什么回报,但它仍在不断复利。一个年利率为 2%的储蓄账户会在 35 年后让你的钱翻倍(1.02 ⁵ = 2)。这是指数增长,因为为了得到总增长率,我们用 1 加上增长率,再乘以 N 的幂,其中 N 是年数。
- 通货膨胀。相反,每年我们的购买力都会下降 2%(商品和服务价格上涨 2%)。我们的钱,如果不投资,35 年后会贬值 50%(0.98⁵= 0.5)。
- 一个明显的例子是像我们现在这样的疫情。在今年 2 月和 3 月的早期,感染以平均每天 20%的速度增长。因此,有一段时间,我们基本上每 4 天就有一倍的新冠肺炎病例(1.2⁴ = 2.07)!这也是为什么仔细追踪和降低感染率是如此重要的部分原因。
- 大学费用每年增长约 8%。这对于每 9 年翻一番(1.08⁹ = 2)来说是好事。
- 摩尔定律表明,微芯片上的晶体管数量大约每两年翻一番,这意味着年增长率为 41%。
作为一个普普通通的规则,如果我们可以说某样东西每 N 年大约翻一番(或减半),那么我们就有了指数或复合增长。
为了好玩,让我们先正常地绘制所有这些(除了新冠肺炎,因为它会在图表上爆炸),然后用对数标度。以下是未记录绘图的代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as pltyrs = 30
rates = [0.02, -0.02, 0.08, 0.41]
labels = ['Savings Account', 'Real Value of Cash',
'Cost of College', 'Transistors on Chip']
values = []for r in rates:
temp_list = []
for y in range(yrs+1):
temp_list.append((1+r)**y)
values.append(np.array(temp_list).reshape(-1,1))
ax = pd.DataFrame(np.concatenate(values, axis=1),
columns=labels).plot(figsize=(10,6));
ax.set_ylabel('Growth factor with starting value of 1')
ax.set_xlabel('Years')
plt.tight_layout()
剧情不是很有意思。晶体管的生长速度如此之快,以至于其他所有东西看起来都像一条扁平的线。
原始未记录值
让我们看看能否更好地了解对数标度图的情况。要获得 y 轴上的对数标度,我们只需切换 Pandas 绘图方法中的 logy 选项(以对数标度绘制 y 轴):
ax = pd.DataFrame(np.concatenate(values, axis=1), columns=labels).plot(figsize=(10,6), logy=True);
ax.set_ylabel('Growth factor with starting value of 1 (log base 10 scale)')
ax.set_xlabel('Years')
plt.tight_layout()
对数标度图是四条直线。为什么会这样?简而言之,它们都是直线,因为它们都在以恒定的速度增加(或者在现金实际价值的情况下减少)。
数值的对数标度图
让我们利用摩尔定律更深入地了解一下,该定律指出,晶体管数量应该以每年 41%的速度增长:
Unlogged log_10
Year 0: 1 transistor **0** <- 10^**0** = 1
Year 1: 1.41 **0.15** <- 10^**0.15** = 1.41
Year 2: 1.98 **0.30** <- 10^**0.30** = 1.98
Year 3: 2.80 **0.45** <- 10^**0.45** = 2.80
Year 4: 3.95 **0.60** <- 10^**0.60** = 3.95**Explanation:**We get year 3’s value of 2.80 as 1.41^3.Because 10^0.15 = 1.41, we can reframe this as:**1.41^3 = (10^0.15)*((10^0.15)*(10^0.15)**Now let's take the log of both sides using the rule that:
*log(A*B*C) = log(A) + log(B) + log(C)*We get:
*(I will use log to denote log_10 to simplify notation)* **log(1.41^3) = log{(10^0.15)*((10^0.15)*(10^0.15)}
log(1.41^3) = log(10^0.15) + log(10^0.15) + log(10^0.15)**Recall log(10^0.15) asks what power do I need to apply to 10 in order to get the value in the parentheses, 10^0.15? Obviously the answer is 0.15.So the previous equation simplifies to:
**log(1.41^3) = 0.15 + 0.15 + 0.15
log(1.41^3) = 0.45**Thus, something growing 41% a year, would in log-scale (with a base of 10), would grow by adding 0.15 a year like so:**0, 0.15, 0.30, 0.45, 0.60**And to get the actual unlogged values, you just apply these values as powers to the base:**10^0, 10^0.15, 10^0.30, 10^0.45, 10^0.60**
对数使指数数据线性化
对数允许我们将乘法(也称为复合)序列转换成加法序列。除了使指数数据的图表更容易解释之外,这还有另一个真正有用的应用——线性回归。线性回归的要求之一是因变量和自变量之间的关系必须是线性的。让我们制作一些假数据来形象化地说明这一点:
rates = [0.3, 0.8, 0.2, 0.1, 0.4, 0.7, 0.5, 1.2, 0.3, 0.1, 0.4, 0.9]
x = [i for i in range(len(rates))]
y = (np.array(rates)+1).cumprod()
fig, (ax1, ax2) = plt.subplots(1,2,figsize=(14,6), sharex='all')
ax1.scatter(x, y);
ax1.set_xlabel('X');
ax1.set_ylabel('Y');
ax1.set_title('Raw Values');
ax2.scatter(x, np.log10(y));
ax2.set_xlabel('X');
ax2.set_ylabel('Y');
ax2.set_title('Log-Scale Values');
plt.tight_layout()
我们的 y 变量以非常高的速度增长。尽管比率不同,但似乎 x 越大,y 的增加速度越快。因为左侧曲线的斜率在变化(并且在增加),所以 y 和 x 不具有线性关系。所以线性回归是行不通的。
原始值与记录值
但是一旦我们应用对数(以 10 为底),我们就得到右边的图。对我来说这看起来很线性。指数数据是指数数据,因为对于每个时间步长(假设时间序列),当前值会乘以某个值:
At time step 1, y is: x^1At time step 2, y is: x^2At time step 3, y is: x^3
所以在 y 和 x 之间有一个指数关系。但是注意在 y 和应用于 x 的指数之间有一个线性关系。取对数(让我们作弊,使用基数 x)得到指数:
At time step 1: log(x^1) = 1At time step 2: log(x^2) = 2At time step 3: log(x^3) = 3
现在我们有了 log(y)和 x 之间的线性关系,这是线性回归所需要的。
结论
这就是所有的人。日志是数学不可或缺的一部分,这篇文章仅仅触及了它们有用的表面。但希望读完这篇文章后,你不再觉得它们可怕,并鼓励你在日常工作中使用它们!干杯!
什么是张量?
打开通用数据科学结构的包装
从 Adobe Stock 获得许可的图像
张量的概念是由两位意大利数学家 Tullio Levi-Civita 和 Gregorio Ricci-Curbastro 在 1900 年创立的,并且,正如通常所见,他们是建立在其他数学家的工作基础上的。维基百科关于“张量”的页面是这样开始的:
对于非数学家来说,要解开的东西太多了!
幸运的是,在实际意义上掌握张量是什么以及我们如何在数据科学中操纵它们要容易得多。
我发现把张量想象成嵌套的数字“列表”很有帮助,可以有任意数量的“层次”另一种形象化的方法是想象 Excel 电子表格中的每个单元格都包含另一个完整电子表格中的所有内容。然后,在第二个电子表格中,每个单元格都链接到另一个完整的电子表格,依此类推。每个电子表格都可以被视为一个额外的“维度”
“一阶”张量只有一维。在计算机科学中,这将被称为“向量”,一个有序的数字列表。“二阶”张量是一个矩阵,像 Excel 电子表格一样,有两个维度。随着维度的增加,我们可以将这些信息想象成嵌套在数组中的向量、矩阵或数组,具有任意数量的维度( n 维)。
三阶张量可能是这样表示的:
可视化三阶张量
三组“顶级”值中的每一组都用不同的颜色表示。在本例中,每个值的数字对应于该值在整个数据结构中的特定位置。每个值最右边的数字对应于它所属的顶级组。所有红色的值都在顶级组 1 中,绿色的值在组 2 中,红色的值在组 3 中。
每个顶级组中都有一个矩阵(二维)。每个值最左边的数字对应于它所在的“行”,中间的数字对应于它所在的“列”通过这种方式,所有值的顺序得以保持,并允许我们使用其他向量、矩阵或数组对整个结构执行计算。
这是相同的结构,用不同的信息可视化:
三阶张量
每个字母代表结构中的一个独特位置,使用相同的颜色编码来区分顶级矩阵。
使用三维立方体可以实现更复杂的可视化。立方体的每个垂直层将包含来自这些“顶级”组之一的数据,创建一个具有 27 个唯一“位置”的 3x3x3 立方体但是一旦我们超越了三维,我们用图形来形象化张量的能力就失效了。
由于这一限制,让我们来看看如何使用计算机软件对相同的数据进行编码。使用 Python 和 Numpy,我们可以用第一个例子中的数字数据创建一个数组:
from numpy import arrayT = array([[[111,121,131], [211,221,231], [311,321,331]],[[112,122,132], [212,222,232], [312,322,332]],[[113,123,133], [213,223,233], [313,323,333]],])
以这种方式对数据进行编码使得拥有任意数量的维度成为可能,这在我们拥有大量复杂数据时具有巨大的价值!
我希望这有助于解释为什么,至少在数据科学中,张量可以被认为是“嵌套”数组。
在以后的文章中,我将讨论“基于元素的”加法、减法、乘法、除法等。以及“Hadamard 积”和“张量积”之间的区别——一个需要相同维数的张量,一个不需要。
互联网上有很多关于数据科学教育的资源。以下是我更喜欢的一些资源:
- 杰森·布朗利的《机器学习大师》
- 免费神经网络入门课程,由 3Blue1Brown 提供
- 熨斗学校(付费项目)
我乐观地认为,人工智能将越来越多地被用来让我们所有人的生活变得更好。您是否面临数据科学问题/挑战?我很乐意帮忙;我们连线吧!
感谢阅读!
一个简单的 SQL 查询背后是什么?
简要回顾一下当应用程序/开发人员运行 SQL 查询从 PostgresDB 数据库获取数据时会发生什么。
肉从哪里来?照片由弗拉德·chețan从佩克斯拍摄
就像现在大多数孩子似乎不知道他们的肉来自哪里(提示:不是长在树上,而是可能来自实验室)或者为什么天空是蓝色的(提示:蓝光的波长更短、更小),数量惊人的开发人员不(真的)知道他们的数据来自哪里以及如何处理和存储。这篇文章应该是工程师理解其工作原理的起点。不管营销人员试图教给你什么样的框架和无代码平台,这都是一件非常好的事情。尤其是如果数据真的是新的石油(显然这已经持续了几年),看看数据库是如何工作的可能会有回报。
免责声明:这不是 SQL 教程
简单的 SQL 语句直接从名为 users 的数据库中获取所有用户:
免责声明 2:重点不在于编写花哨的 SQL 语句,而是展示一旦您这样做了会发生什么
SELECT * FROM users;
那么,有多少人真正知道在 psql 终端中按下 enter 键和返回结果之间发生了什么?
基本原则
为了理解这一点,我们必须从头开始——PostgresDB 的架构。
归根结底,它是一个用 C++编写的客户机/服务器应用程序。客户是任何访问数据库的人,比如你的 psql 终端,你的 Lambda 函数,JDBC 驱动等等。服务器是 PGDB 后端,它接受你的请求,存储数据等等。
下面是 PostgresDB 的基本架构概述,整篇文章都会详细介绍:
这是一种老派,但仍然有效:)来源:幻灯片分享
查询的路径
在 PostgresDB 官方文档中有一个关于“查询路径”的很好的概述。以下是你应该知道的:
1。建立连接,发送查询&等待结果
PGDB 可以同时处理多个连接(通过“postmaster”,参见架构),并且对于每个连接,它派生一个新的进程(“postgres”,参见架构)来处理该连接的请求(例如 SQL 语句)。换句话说,这是一个简单的“每个用户一个进程”的客户机/服务器模型。邮局主管处理初始连接和身份验证,然后将该连接移交给新的 postgres 进程。这些进程通过共享内存和信号量相互通信,以确保即使在并发连接的情况下整体数据的完整性(还记得 ACID 吗?)
2。解析查询
这包括两个阶段:
- 解析:PGDB 解析器利用 UNIX 工具 bison 和 flex 作为解析器和 lexer 来验证传入的查询字符串(ASCII 文本)是否是有效的 SQL 查询。这只能通过关于 SQL 语法的固定规则来完成,而不需要了解查询字符串的底层语义。输出是一个解析树:
SELECT 语句的解析树示例。来源: interdb.jp
- 转换:使用解析器树构建查询树,查询树包含查询的语义解释,例如引用了哪些表、数据类型、运算符和函数。查询树的根是这里定义的查询数据结构。输出:
同样的例子,查询树作为输出。来源: interdb.jp
深入查询:
- targetList:保存查询的输出及其数据类型,在本例中是列 id 和 data,它们都是整数
- rtable:保存对表的引用
- jointree:保存 FROM 和 WHERE 操作符
- sortClause:保存数据应该如何排序
直接来自官方文件的重要说明:
将原始解析与语义分析分开的原因是系统目录查找只能在事务中完成,我们不希望在收到查询字符串时立即启动事务。原始解析阶段足以识别事务控制命令(BEGIN、ROLLBACK 等),然后这些命令可以被正确执行,而无需任何进一步的分析。一旦我们知道我们正在处理一个实际的查询(比如 SELECT 或 UPDATE),如果我们还没有在一个事务中,就可以开始一个事务。只有这样才能调用转换过程。
3。重写
PGDB 的重写系统使用查询树作为输入,并基于存储在其系统目录中的规则执行转换,这些规则可以应用于查询树。输出也是一个查询树。一个很好的例子是视图(虚拟表)的实现,其中重写系统重写用户查询以访问视图定义中的原始表,而不是视图的别名。
关于规则系统如何为视图工作的综合例子可以在这里找到。
4。查询计划
计划器/优化器使用上一步重写的查询树为查询创建最佳/最便宜(=最快/最有效)的执行计划——查询计划。优化器会寻找所有可能的路径来执行查询。除非该语句有大量超过 geqo_treshold 的连接,在这种情况下查看所有可能性在计算上是不可行的。在这种情况下,使用通用查询优化器来代替。
查询计划/计划树的示例相同。来源: interdb.jp
上图中的例子显示了一个简单的例子,其中执行器必须对表 tbl_a 进行顺序扫描,然后进行排序。
您可以通过在查询前键入 EXPLAIN 来检查您的查询计划:
EXPLAIN SELECT (...)
5。遗嘱执行人
官方文件尽可能清楚地解释了这一点:
执行器递归地遍历计划树,并以计划表示的方式检索行。执行器在扫描关系时使用存储系统,执行排序和连接,评估资格,最后返回派生的行。
执行器用于评估所有 4 种基本 SQL 查询类型选择、插入、删除和更新。您可以在这里找到每个查询类型的执行者步骤的更多细节。
奖励:GPU 加速
实际上有类似 PG Strom 的工具用于 GPU 加速,特别是针对查询优化器和执行器,如下图所示:
又是那种老派,但是有什么不喜欢的呢?:)来源: SlideShare
这篇文章没有测试过这一点,但它可能会启发你去看看有什么,因为这似乎是一项非常酷的技术。
记忆
好的。现在您知道了(1)当您连接到 PGDB 实例时会发生什么,以及(SQL 查询是如何被解析、优化和执行的。唯一缺少的是数据如何存储,以涵盖现代数据库如何工作的(非常)基础。
*鉴于 PostgresDB 的历史,你可以对“现代”持保留态度,但它仍然被广泛使用,是当今使用的主要关系数据库之一。
这个题目这里有很大的解释,所以下面只是简单总结一下。
PostgresDB 内存架构的(非常)高级概述。来源:severalnines.com
有两种类型的内存:
1。本地存储器
它由每个 postgres 后端进程使用。该内存由每个进程分配,用于查询处理,包括:
- temp_buffers:由执行器存储临时表
- work_mem:由执行程序用于连接等。
- maintenance_work_mem:像 REINDEX 这样的维护操作
2。共享内存
它是在 PGDB 服务器启动时分配的,所有后端进程都使用它来确保数据完整性(还记得文章的开头吗?)这也是后端进程与之接口的内存—它通常不直接与持久性存储接口。该共享存储器包括:
- 共享缓冲池:表和索引中的页面被加载到的地方
- WAL buffer: Postgres 有一个预写日志,即事务性日志,确保不会因为服务器故障而丢失数据。WAL 数据在传输到持久存储之前存储在 WAL 缓冲区中。
- 提交日志:保存所有事务状态,作为并发控制机制的一部分
您可以调整这些值以及分配给它们的内存量,以提高数据库的性能。关于存储器各部分实用程序的更多信息可在这里找到。
整合/持久存储怎么样?
最后会怎么样?数据是如何持久化的?执行器可以通过缓冲区管理器读取/写入数据库中的表和索引,缓冲区管理器可以通过将数据添加到共享缓冲池来访问持久存储中的数据。
摘要
到目前为止,您应该对最流行的数据库之一的内部工作原理有了基本的了解!在一天结束的时候,你只是在和一个非常智能的 C++应用程序交互——这多酷啊?希望这能消除一些“数据库很复杂”的污名。也许它甚至会启发你更深入地挖掘,并了解如何通过更好地理解如何存储数据来优化应用程序——这是现代软件工程中最大的瓶颈之一。
来源:
- 2020 年 8 月 5 日,https://www.postgresql.org/docs/9.1
- 2020 年 8 月 5 日,http://www.interdb.jp/pg/pgsql08.html
- 2020 年 8 月 5 日,http://www.interdb.jp/pg/pgsql03.html
- 2020 年 8 月 5 日,https://www.slideshare.net/oddbjorn/Get-to-know-PostgreSQL
- https://www . slide share . net/kaigai/gpussd-accelerates-PostgreSQL-challenge-forward-query-processing-throughput-10g bs,05.08.2020
76 人的客场之旅背后是什么?
NBA 历史上最糟糕的主场比赛背后的理论分析。
76 人有望成为 NBA 历史上唯一一支至少赢得 90%主场比赛,输掉超过 2/3 客场比赛的球队。没人知道为什么。本·西蒙斯(CC BY-SA 2.0)BYKA 体育照片
费城 76 人队在主场度过了一个伟大的赛季。NBA 球队在费城南部比赛时的战绩是 28 胜 2 负,胜率为 93%,而在客场比赛时的战绩是 9 胜 23 负,胜率仅为 30%。这 63 个百分点的主客场差距使他们成为 NBA 历史上唯一一支至少赢得 90%主场比赛而输掉超过 2/3 客场比赛的球队。
如何解释这种差异?有据可查,NBA 的主场优势效应是美国四大职业体育联盟常规赛中最大的,在胜率约 60% 。本赛季 60 场比赛后,76 人 93%的主场胜率显然是一个异常值,但他们糟糕的客场表现引发了一个问题:为什么他们在客场表现如此糟糕?
在过去一周的体育分析播客的一集中,统计学和营销学教授凯德·梅西、谢恩·詹森、阿迪·韦纳和埃里克·布拉德洛讨论了 76 人队主场大比分失利的潜在理论(从 17:35 开始):
阿迪·韦纳(AW): 这是有史以来最大的差距之一……【他们的主场优势】难以置信的不同!…超过四个标准误差,太荒谬了!…我不知道这实际上是不是史无前例的,但就概率而言,我没想到会发生这种事,也许以前有过一次?…
凯德·梅西(CM): 那么,这说明了车队的什么?
AW: 这就是其中的奥秘!
CM: 当情况如此严峻时,不可能…我们不可能没有洞察力…
肖恩·詹森(SJ): 他们显然是在偷标语,伙计们!…
我会猜测,这只是一个完整的,没有受过教育的,但可能是正确的猜测,它与谁在玩以及他们实际上是如何玩的结构有关。我认为篮球是最容易受努力影响的运动…在三巨头中…在篮球中,我们可以看到当明星们想上场时,他们就变成了不同的球员!…
SJ: 几周前在《运动》杂志上写了一篇非常有趣的关于负荷管理的文章,当然在篮球领域,我们只是把它作为常规赛的一部分,因为负荷管理是一个巨大的战略…
AW: 我猜负荷管理在某种程度上与 76 人的主场优势有关,因为他们的球星在主场比赛,而我打赌他们不会在客场比赛…
SJ:这是一个至少可以很容易分析的问题,他们是不是在做一种极端版本的负载管理,他们只是在家里不成比例地发挥他们的明星…
很想知道比赛的时间是多少,主客场平分……
AW: 还要努力!…
SJ:……负载管理促使我们让更好的球员在主场比赛,而不是在客场比赛……
总而言之,主持人提出了三种理论:
- 76 人的明星球员在客场的上场时间更少。
- 76 人的球员在客场花费的精力更少。
- 六代移民在作弊。
在这篇文章的剩余部分,我将评估前两个理论,使用来自 NBA.com/stats 的数据来看看这些理论是否有效。显然,最后一个理论是对最近发生的休斯顿太空人队偷牌丑闻的半开玩笑的引用,现在我将让其他人根据需要进行评估!
相反,我将评估我自己的第三个不同的理论:
3.76 人在客场的对手比他们在主场遇到的对手要强大得多。
用于以下分析的数据是从 3 月 1 日周日中午的 NBA.com/stats 收集的,当时 76 人的总战绩为 37 胜 23 负,主场 28 胜 2 负,客场 9 胜 23 负。
分别从Basketball-Reference.com和五三八同时收集历史进度和强度进度数据。
理论 1:76 人的明星球员在客场的上场时间更少
为了确定 76 人队是否正在部署一个极端版本的负荷管理,让他们的明星球员在路上休息,但在主场比赛,我首先看了看主场和客场比赛时间的差异:
比较每个 76 人球员主客场上场时间,按上场时间排序。数据。
在总共出场超过 1000 分钟的 76 人队中,只有两名球员,乔尔·恩比德和马蒂斯·蒂布尔,在主场的出场时间明显多于客场。他们都有大约 55%的时间是在主场而不是在客场。
其他关键球员,像本·西蒙斯和约什·理查德森,实际上更多的时间是在客场,分别只有 48.6%和 46.7%的时间在主场比赛。
平均来说,76 人是不是主场打球星多,客场打球星少?为了确定主场-客场比赛时间差对特定球队的整体影响,我计算了每支球队的分数,对主场比赛多于客场比赛的球员,这一分数会向上调整总得分。如果团队为他们的明星部署这种形式的极端负载管理,我们会在他们调整后的幻想点中看到差异。
举个例子:相对于球队 49.92%的主场率,乔尔·恩比德 55.07%的时间都在主场比赛。*因此,恩比德在主场的表现比预期高出 5.15 个百分点。为了权衡他的主场比赛时间不平衡的影响,我根据他在主场比赛的额外时间调整了他今年的 1,963.2 分。1963.2 *(1+5.15%)=调整后分数 2064.3。为了确定这种加权的绝对效果,我从他调整后的幻想总点数(2,064.3)中减去他的实际幻想总点数(1,963.2),得到 101.1 点的差值。
*注:76 人实际上有 50%的时间在主场比赛,但由于某种原因, 总的球员主场出场时间 不等于 总的客场出场时间 。为了说明这种差异,当比较球员主客场分钟和球队主客场分钟时,我将同一球队球员的分钟相加,而不是使用 报告的球队统计数据 。
恩比德的幻想总得分和他调整后的幻想总得分之间的差异,我称之为他的**“主场偏差得分”**,在现实中没有任何意义,但确实给了我们一种感觉,如果我们怀疑一支球队在客场让明星球员休息,他在主场比赛的不平衡应该给予多少权重。
对于每个本赛季在 76 人队打球的球员来说,我们可以看到让那个球员在客场休息的效果。恩比德是客场休息的最大受益者,但在某种程度上被其他首发西蒙斯、哈里斯和理查德森抵消了,他们在主场的比赛比客场少:
根据主场得分给每个球员排名。数据。
通过合计所有球员的得分,我们看到 76 人只是略微倾向于让他们的球星更多地在主场比赛,在其他球队中排名中间:
排名每支球队在主场和客场让他们更好的球员上场的次数。数据。
在所有球队中,看起来休斯顿火箭队和波特兰开拓者队最有可能为他们最好的球员部署一种负荷管理形式,让他们在路上休息,尽管差异仍然小到足以成为巧合。
对休斯顿来说,先发球员詹姆斯·哈登和拉塞尔·维斯特布鲁克都有 52%的时间是在主场,而不是在客场:
休斯顿火箭队球员的主客场分钟分裂和主场偏向得分。数据。
由于哈登和威斯布鲁克都在幻想积分所有球员的前 15 名,所以显著扭曲了球队的主场偏差得分。
波特兰的五名先发球员中有四名在主场比赛的时间(49-60%)比球队整体(48%)多:
波特兰开拓者球员的主客场分钟分裂和主场偏向得分。数据。
帕特里克·贝弗利、乔尔·恩比德和詹姆斯·哈登在主场优势得分上领先所有球员,这表明他们可能在客场很轻松。以下是主场优势得分最高的 30 名球员:
根据主场优势得分排名的前 30 名球员,计算为他们的总得分,以他们在主场比赛的分钟数与他们球队主场比赛的分钟数之间的百分比差异加权。数据。
如果你很好奇,以下是前 35 名幻想得分者如何分配他们的主场和客场时间,以及他们最终的主场偏差得分:
前 35 名球员的总幻想点,他们的主客场比赛时间分裂,和他们的计算主场优势得分。数据。
当比较一支球队的主客场胜利百分比差异和他们的主场优势得分时,我们发现实际上没有相关性:
主客场胜率%与主场优势分数的差异。76 人是图表顶部中间的点,他们的主场胜利和主场偏差得分之间有 63 个百分点的差距。
**理论#1 结论:**总的来说,76 人似乎没有比其他球队更多地在客场休息他们的天赋,这足以解释他们主场胜率的差异。恩比德拥有所有球员中第二高的主场偏向得分,当然是一个潜在的异数,但他在客场的相对休息在很大程度上被其他球星在客场比主场打得更多所抵消。总的来说,球队在主场和客场使用顶尖人才似乎与球队在主场和客场的胜率差异没有太大关联。
理论 2:76 人的球员在客场花费更少的精力
为了衡量 76 人是否在客场“尝试更少”,我们不得不求助于一组更主观的统计数据。
回到 2016 年,NBA 开始发布“hustle”统计。这些包括屏幕辅助,偏转,回收球,收费和有争议的投篮。此外,他们已经公布了关于禁区、距离和速度的数据。这些数据是用来衡量一个球队或球员在一场比赛中所付出的努力。
对于上述每个类别,我收集了每支球队每场比赛的主场和客场数据。然后,我把在家时的每场比赛数据和在旅途中的每场比赛数据相除,得出一个比率分数;一支在客场和主场付出同样多努力的球队会得到 1.00 的中性分数。
例如,76 人每场主场比赛平均投篮 54.8 次,而每场客场比赛平均投篮 53.9 次。54.8/53.9 = 1.02 的分数,这表明球队在主场比赛中比在客场比赛中付出更多努力的可能性(尽管更可能是巧合)。
然而,与客场比赛(8.4 分)相比,他们每场主场比赛(8.3 分)回收的松散球略少,得分为 0.99:
按球队选择的每场比赛的主场优势率。比率为 1.00 表示每场比赛球队的主场和客场表现没有差异。高于 1.00 的比率表明在家比在路上花费的精力可能增加(反之亦然)。数据。
当比较所有球队的主场和客场时,76 人并不突出;对于这些统计数据中的大多数,他们排在中间位置:
对所有 30 支球队的主场优势进行排名。数据。
此外,我查看了球队在禁区、距离和速度方面的平均水平,比较了每场比赛主客场的平均水平。这些可能不太能代表努力程度(例如,速度可能是团队和对手比赛风格/节奏的一个属性),但可能表明努力程度存在一些差异。
在这里,76 人再一次相对于其他球队排名中游甚至垫底:
根据 30 支球队的主场优势、球场行进距离和球场速度对他们进行排名。数据。
**理论#2 结论:**根据屏幕助攻、偏转、回收的松散球、冲锋、有争议的投篮、禁区、行进的距离或速度来衡量,相对于其他球队,76 人在主场比赛时似乎没有花费更多的努力。
理论 3:76 人的客场比主场更难对付
为什么 76 人在主场表现更好的第三个可能的解释是,他们只是打弱队,而在客场打强队。
为了验证这个理论,我收集了每个队相对于对手在赛季中每场比赛的预期获胜概率的数据。我使用了 FiveThirtyEight 基于猛禽玩家评级的游戏预测。
由于 NBA 球队众所周知的主场优势,所有球队在客场比赛的平均对手获胜概率都高于主场比赛。但一些球队在客场比在主场与对手的胜算差距更大,这表明赛程更加艰难。按照这个标准,76 人在客场面对的最强对手方面排名中等,30 个中有 14 个:
根据对手主场与客场比赛的平均获胜概率的差异对所有 30 支球队进行排名。数据。
你可能想知道这些数据是否受到球队主场优势差异的影响;例如,丹佛掘金队(和其他丹佛职业运动队)因其比赛地的高海拔而在主场拥有更大的优势,这可能解释了他们在上图中相对较高的排名。然而,FiveThirtyEight 的概率考虑了一般的主场优势、疲劳、旅行和海拔,可能会减少这些影响。举个例子:犹他州也因海拔高而被认为是一个潜在的困难之地,排名仅次于 76 人,这表明在客场比赛时,固有的主场优势可能不是比赛程更重要的因素。
令人惊讶的是,当将一支球队的客场胜率差异与其客场对手的相对实力进行比较时,我们发现没有相关性:
比较一支球队在主场和客场比赛中主客场胜率的差异与对手平均胜率的差异(76 人是最大的点,分别为-25%和 65%)。数据。
我会认为,至少在主场和客场的胜率之间的一些差异是由于对手在主场和客场比赛前的平均获胜概率的差异。
**理论#3 结论:**相对于主场的对手,76 人在客场还没有遇到过不成比例的强劲对手。
那么 76 人的客场之旅背后是什么呢?
这一分析表明:
- 平均而言,当考虑明星球员时,76 人的球员在客场比赛的时间更少。
- 当通过屏幕辅助,偏转,回收的松散球,冲锋,有争议的投篮,出界,行进距离或速度来衡量时,76 人的球员在路上花费的精力确实而不是少。
- 相对于主场的对手,76 人在客场面对的对手更强大。
因此,我们可能需要转向更“模糊”的理论来解释 76 人在客场的挣扎。
二月初,艾尔·霍福德对道路上的模糊“注意力不集中”发表了评论:
我们的更衣室里发生了一些事情,我们会保密的。我们都知道我们需要变得更好。我们需要加快步伐,明天是一个很好的机会。
我们不够专注,尤其是在路上。我们在上半场很专注(对抗热火),然后下半场他们有一点点跑动,出于某种原因我们没能恢复。作为一个团队,我们需要更加专注。我们在客场做得好一点,但我们又回到了糟糕的状态。
蔻驰布雷特·布朗不太相信一个原因:
你看看我们在路上的记录,就像是,‘这怎么可能?’你家里有这个,路上有这个,这是两种不同的性格。…我们有过糟糕的枪战吗?我们有过不好的做法吗?这个团体的精神被污染了,以至于我们不能浏览所有的东西吗?事实并非如此。
(我们的道路斗争)有点神秘…我做这个已经够久了,足以生活在现实世界中。我不能指出任何[理论]是“哦哦。”
那么如何解释 76 人的客场之旅呢?不幸的是,目前答案并不令人满意:这是一个谜。
在你走之前…
如果你喜欢这篇文章,你可能也会喜欢我关于体育和数据的其他文章——给我一个关注,当我发布更多内容时会通知我:
- 填写三月疯狂的最终指南
- 我如何正确预测比利亚诺瓦赢得 2018 年 NCAA 男篮锦标赛
- 我是如何智胜一个 538 预测算法的
- 我如何使用 200 名专家和 Reddit 的评论排名算法赢得我的 Office NFL Pick’em Pool
- 2020 梦幻足球拍卖守门员策略综合指南
在煮什么!—用自然语言处理对菜肴进行分类
学习用于食谱分类的 word2vec 和单词嵌入
兴奋地想去旅行,但在疫情却被困在家里?想尝试世界各地的美食却被困在家里?嗯,这是给你的项目!作为一名美食家,这是一个有趣的数据集,了解每种美食的不同特色食材。“什么是烹饪”数据集是来自 20 种不同菜系的食谱列表,任务是为不同的食谱建立一个分类器。在本文中,我将比较理解这个数据集的两种不同方法。
维度的诅咒
在将数据输入机器学习模型之前,第一步是将数据转换成机器学习模型能够使用的定量形式。最简单的方法是使用一键编码,这种技术根据条目是否存在,将列表转换为 1 和 0 的向量。
在这个包含 7137 种成分的数据集中,如果没有额外的处理,事情可能会很快失控。维度过多将使执行操作在计算上更加困难,这将大大延长训练模型所需的时间。这个问题是一个常见的问题,被称为维数灾难。
为了解决这个问题,我们必须将数据投影到一个更低的维度上,这样我们更容易处理。这些低维向量被称为单词向量或单词嵌入,它们本质上是单词含义的数字表示。然后可以将这些单词向量组合起来创建句子向量,或者在这种情况下,创建菜谱向量。为了获得这些配方向量,我们看两种方法,第一种方法是主成分分析,或者使用被称为连续单词包的自然语言模型。
主成分分析
PCA 是一种统计技术,用于将数据集压缩到更低的维度。这是通过找到最高方差的方向,然后将数据投影到这些轴上来实现的。这背后的想法是,方差最大的轴能够保留数据集中的大部分信息,从而最大限度地减少变换到较小维度时的信息损失。
在这个问题的背景下,PCA 可以直接应用于配方向量,而无需学习每种成分的嵌入。原始的大小矩阵被压缩成 32 维,作为配方的嵌入。
自然语言处理方法
自然语言处理领域的一个巨大突破是 word2vec 的出现,这是一种可以将单词的意思转换为计算机可以理解的数字向量表示的系统方法。著名的等式“女王-女人+男人=国王”向我们展示了精确的单词向量如何能够有效地捕捉单词的语义。
word2vec 的单词类比
用于生成该单词向量的一种常见模型是连续单词袋(CBOW)模型,该模型使用相邻单词(上下文单词)来学习不同单词之间的关联。
CBOW 模型架构。谷歌图片
在第一部分中,该模型通过编码器传递上下文单词的独热向量,以将其转换到较低的维度。然后将这些向量相加,得到我们正在寻找的 32-D 嵌入向量。然后,模型的下一部分将尝试将该低维嵌入向量转换回目标单词的独热码编码向量。正如所预期的,从嵌入向量重建一位热码向量将不是完美的,并且两个向量之间的误差将通过模型反向传播。在连续的学习时期之后,该模型将能够将一次性向量转换为嵌入向量,同时保留尽可能多的信息。
如果你有兴趣了解更多,你可以看看这篇解释其他模型的文章这里或者对于那些想深入研究数学的人来说,这里的注释相当不错。
然而,与句子不同的是,配方中的配料本质上是无序的,不是采用配方中的相邻配料,而是从整个配料列表中随机抽取上下文配料。训练数据集也每 5 个时期重新采样,以学习尽可能多的关联。
def sample(recipe,ingredient,samples):
recipe = recipe[:]
recipe.remove(ingredient)
if len(recipe) < CONTEXT_SIZE+1:
context = random.choices(recipe, k=samples)
else:
context = random.sample(recipe, k=samples)
return context
在找到模型训练的最佳学习速率后,CBOW 模型被训练 60 个时期,其中数据每 5 个时期被混洗一次。这导致损失函数每 5 个时期增加,因为模型必须适应新的混洗数据,这将有希望允许它更好地概括。
一旦我们使用这种技术获得了单词嵌入,我们就可以对它们做一些初步的评估。观察这些向量的定量方法是找出我们期望相似的向量之间的相似性。比如酱油和鸡肉的相似度要明显高于酱油和牛奶。这可以使用余弦相似性来评估,余弦相似性测量两个向量之间的角度的余弦。指向相似方向的向量将具有接近 1 的余弦相似性,而不同的向量应该具有接近-1 的相似性。
估价
回到手头的任务,我们更感兴趣的是分类食谱,而不是成分向量。对配方中的所有成分进行平均将得到配方向量,然后我们可以将该向量与从 PCA 获得的配方向量进行比较。评估这两个模型的定性方法是将它们在二维空间中可视化。然后,我们可以观察不同菜系的食谱之间的区别,以评估算法的有效性。
我们可以做到这一点的方法是使用 t-SNE 一种流形降维工具,它对于绘制高维空间非常有用。根据从两种技术获得的 32-D 向量,对两者执行 t-SNE 以获得 2-D 图。
NLP 模型(左)和 PCA 模型(右)的比较
显然,我们看到从我们的 NLP 模型获得的图比预期的 PCA 模型表现得好得多。与 PCA 相比,CBOW 模型等神经网络可以学习更多的高维特征,我们可以从图中更好的分离看出这一点。同时,这些情节可以为不同的美食提供有价值的见解。从图中我们可以看出,墨西哥菜和印度菜形成了一个非常独特的群体,而希腊菜和美国南方菜则更加分散,这表明它们融合了更多种类的食材。从每个集群之间的距离,我们也可以比较不同美食的相似之处。正如所料,日本,中国和泰国聚集在一起,而希腊,意大利和法国美食形成另一个相反的一端集群。看看你还能从这些数据中获得什么见解!
Github 链接:https://github.com/reoneo97/Whats_Cooking
在 LinkedIn 上联系我:【https://www.linkedin.com/in/reo-neo/
过去一个月,数据科学就业市场发生了什么变化
据 Recode 报道,美国招聘信息发布在。
我在的一家公司工作,免费指导数据科学家,直到他们被聘用。因为我们只有在我们的数据科学家被雇用时才能赚钱,所以我们可以非常详细地了解北美数据科学就业市场及其实时发展情况。我们知道谁在哪里被雇佣,他们的工资是多少,雇佣谈判过程的细节,以及许多其他数据。
在这篇文章中,我将分析过去一个月我们在数据科学就业市场上看到的情况。我最初在上周的 tweetstorm 上发布了一些信息,但我会在这篇文章中更详细地介绍。
以下所有统计数据均基于我们导师计划的内部数据。我们密切跟踪我们的学员在哪里、何时以及由谁聘用。对更广泛的数据科学就业市场的推断不会完美,但基于我们的规模和地理范围,应该非常接近。
招聘放缓📉
三月份,数据科学家的招聘普遍放缓,降幅约为 60-70%。实际上,我们预计招聘会暂时降为零,但事实并非如此——至少目前还没有。
这次经济放缓的影响非常不均衡。依赖客流量的公司(如时装零售商)受到了沉重的打击,他们正在冻结招聘,进行裁员或休假。像 Twilio 和 Airtable 这样的 B2B 软件公司基本上都在正常招聘。像 Slack 和 Zoom 这样的远程工作使能器正在加速招聘。
到目前为止,我们已经看到,与三月份同期相比,四月份有更多的学员被录用。但现在还是月初,事情变化很快。
工作机会被撤回📃
三月份,我们看到几份最终确定的工作邀请在没有通知的情况下被撤回。这意味着实际的、签署的协议——来自公司的承诺,比如“你的工资是 x 万美元,你从周一开始工作。”。欢迎登机!”——被拉了回来。这是前所未有的:在 3 月份之前的 18 个月里,这种情况为零。
一些撤回报价的公司是初创公司;其他的是你肯定听说过的大公司。我们不可能预测谁会撤回提议,谁不会。小心这个。
到目前为止,在 4 月份,我们还没有看到更多这样的撤资。我们怀疑大多数公司现在已经调整了他们的招聘计划,所以这种事情会越来越少。
解雇😬
裁员还没有打击太多的数据科学家。到目前为止,只有 3%的校友受到了影响。这既包括临时休假,也包括不算裁员的减薪。
裁员的时候,大部分公司早裁,一次裁,深裁。这有助于减少留下来的员工的不确定性和风险。如果你的公司使用这种策略,并且你熬过了第一轮裁员,你的工作在中期内更有可能是稳定的。
如果你担心被解雇,你的第一道防线就是让成为不可或缺的。想办法为公司省钱并增加价值,即使这超出了你的工作范围——不被要求就去做。大多数公司都不希望裁员。你带来的价值越多,你就越有可能留下来。
(**公司:**如果你需要削减工资,请考虑临时休假,而不是直接解雇员工。这将给你的员工一个仍然拥有工作的机会,加上寻找新工作的灵活性。这样做是对的。)
工作申请📨
你现在看到的几个职位都是无用的。许多公司因为 COVID 取消了内部职位,但还没有删除他们的职位。通过求职公告板申请从来都不是一个好策略,但是现在因为这些无用的职位而变得更加困难。
由于显而易见的原因,面对面的交流也是不可能的。
效果更好的是冷邮件和 LinkedIn 外联。要真正做好这些,需要很多细节,但简单来说就是:1)对公司做研究;2)发送一条深思熟虑、精心制作的信息;3)谈论你已经建立或完成的具体事情。
有趣的是,一个人是否会回复你冰冷的电子邮件或 LinkedIn 信息的一个重要因素是这个人是否有孩子。没有孩子的人通常在家很无聊,更有可能回答;有孩子的人正忙着照顾他们,因为日托也不在考虑范围内了。
在线聚会也可能是一个很好的社交渠道。我们对此还不确定,现在说还为时过早。但我们的一些学员正在积极尝试。
视频采访👨💻
如果你得到了面试机会,你很可能会在 Zoom 上接受面试。Zoom 是一个非常稳定的视频平台,但仍然要确保你的互联网连接是牢固的。如果你没有很好的关系,在面试开始时提到这一点也没关系。大多数面试官会理解你,放你一马。
(Zoom 曾经有一个设置,告诉会议组织者你在屏幕上看的是什么,这在求职面试中是一个短暂的因素。幸运的是,他们最近移除了它。)
到处都很偏僻🌎
好消息是:**几乎所有的工作都突然变得遥远了。**地理障碍一夜之间消失了。你现在可以申请比以前多得多的公司。这对农村地区的人们来说尤其重要,它在很多方面都是公平的。
这就是我们目前所看到的,但我们仍处于这个疫情的早期。很难预测未来几个月会发生什么,但目前,获得一份数据科学的工作很难,但并非不可能。诀窍是找到那些没有被锁定打击太大的公司。
如果你想得到如何在 DS 就业市场导航的建议——特别是在北美——请在 Twitter 上关注我,我会尽力帮助你。
祝大家好运。❤️
一句话里有什么?
入门指南
为什么 tf-idf 有时不能准确捕捉单词的重要性,我们可以用什么来代替
TL;DR:Term Frequency-Inverse Document Frequency(TD-IDF)是一个强大而有用的工具,但它有一些缺点,导致它对相对重要的词赋予较低的值,在大范围内过于敏感,在密集范围内过于抗拒。一个更纯粹的比例方法改善了这些问题。
目录
- TF-IDF 简介
- 弊端
- 比例重要性
- 进行珠宝案例研究
- 结论
TF-IDF 简介
正如我向任何对文本分析感兴趣的人推荐的那样,我最近在通读朱莉娅·西尔格和大卫·罗宾逊的优秀著作《与 R 一起进行文本挖掘》。在那本书中,他们有一章讲述了如何使用一种叫做“词频-逆文档频率”(tf-idf)的统计方法来量化给定文档中哪些词相对重要。在阅读那一章之前,我当然看过甚至使用过 tf-idf,但是说实话,我从来没有真正质疑过它。我知道这是一个简单而强大的工具,可用于各种应用程序,所以我只是简单地继续使用它,没有想太多。
然而,读完那一章,更仔细地考虑它是如何计算的,我开始意识到,也许有比我以前认为的更多的理由来质疑它。事实上,我注意到了两个相当重要的缺点,正如我将要展示的,它们可以有意义地改变一个分析。
但是在讨论这些缺点之前,我应该简单解释一下 tf-idf 的实际目标是测量什么以及如何计算。
tf-idf 的目标是量化一个感兴趣的单词对于文档集合中的一个给定文档有多重要。
它这样做的方式很简单。它将给定单词在给定文档中出现的频率(术语频率)乘以该单词在其他文档中出现的次数(逆文档频率)。经常在文档 A 中出现并且在很少或没有其他文档中出现的单词将为该文档获得高值,而在文档 A 中不常见和/或在许多其他文档中出现的单词将为文档 A 获得低值
在数学上,这是通过将术语频率(给定文档中由感兴趣的单词组成的单词的比例)乘以逆文档频率(分析中文档数量的自然对数除以感兴趣的单词出现的文档数量)来完成的。
正如我上面提到的,这是一个简单而强大的工具,通常可以很好地估计语料库中哪些词定义了文档。然而,它有两个具体问题。
缺点
paweczerwi ski 在 Unsplash 上的照片
首先,我称之为“零价值问题”,它源于逆文档频率计算。通过构造,如果感兴趣的单词出现在所有文档中,则 tf-idf 值将为零;分析中的文档数与该单词出现的文档数之比为 1,1 的自然对数为零。这意味着这个词对于任何给定的文档都不是唯一重要的。
在许多情况下,这可能是合理的:如果一个词出现在任何地方,它在任何地方都不是唯一的,这一想法似乎是一个可靠的启发。然而,在有些情况下,这给分析带来了有意义的挑战,在我看来,分配的重要性是不正确的低。
要了解这是如何造成问题的,请考虑下面的场景。假设我们有三个文档:A、B 和 c。假设我们想获得文档 A 中单词“apple”的 tf-idf 值,并假设 apple 构成了该文档中整整 75%的单词。如果苹果只在文档 B 中出现过一次,而在文档 C 中根本没有出现,那么 tf-idf 值就应该很高。然而,如果苹果只在的文档 B 和 C 中出现一次,tf-idf 就会一路跌到零。尽管唯一的变化是 apple 现在再次出现在文档 A 之外,尽管文档 A 几乎完全由单词 apple 组成,但是 tf-idf 统计数据从相对较高的值骤降到零。这是一个不受欢迎的衡量标准,因为它表明这两个案例远比实际情况不同,也因为它表明苹果对 A 并不是唯一重要的,尽管它显然是重要的。
第二个缺点与第一个相似,我称之为“广泛的保证金问题”。这是因为 tf-idf 的逆文档频率部分没有考虑一个单词在其他文档中出现的频率(密集边距),而只是考虑它是否出现(广泛边距)。这导致它在广泛边际上有变化时过度敏感,而在密集边际上有变化时过度抵制变化,尽管后者可能更重要。
要了解这一点,请考虑上面的相同设置,这一次 apple 占了文档 a 中 10%的单词,如果 apple 根本没有出现在文档 B 中,tf-idf 值会相对较高。然而,如果它只在 B 中出现一次,值就会急剧下降(尽管只要它不在 C 中出现,就不会降到零)。尽管这两个场景几乎相同,唯一的变化是苹果的外观增加了一个,但价值发生了巨大的变化,这都是因为这种变化是在广泛的范围内发生的(即苹果从没有外部文档变为有外部文档)。当然,在实践中,apple 这个词在文档 a 之外只出现一次或者根本不出现没有什么区别。但是 tf-idf 认为这两种情况是完全不同的。
另一方面,如果苹果从只在文档 B 中出现一次,变成几乎 100%地使用文档中的文字,tf-idf 也不会有任何改变。也就是说,这个词在文档 B 中出现多少次并不重要,因为 tf-idf 忽略了密集边距。重要的是它是否出现。然而,如果我们的目标是获得一个指示相对重要性的度量,那么区分这些场景是非常关键的。在前者中,与 B 相比,苹果对文档 A 相对重要(只在 B 中出现一次),而在后者中,相对于它对文档 B 的重要性(100%的单词),苹果对文档 A 根本不是唯一重要的(10%的单词)。然而,tf-idf 认为没有什么不同。
概括一下:零值问题意味着如果感兴趣的词出现在所有外部文档中,即使它只在每个文档中出现一次,tf-idf 也会突然降到零。大范围裕度问题意味着,当大范围裕度上有较小的和相对不重要的变化时,tf-idf 会有显著的不同,但当大范围裕度上有变化时,即使是实质性的变化,TF-IDF 也不会有任何不同。
我们能做些什么呢?
比例重要性
输入:比例重要性。
比例重要性是我试图提出的一种方法,它同样能告诉我们一个给定的单词对于一个给定的文档是否既重要又独特,而没有 tf-idf 的缺点。我将指出,这是可能的,甚至可能类似或相同的事情以前已经做过。我没有亲眼见过,但尽管如此,我并不声称自己是第一个想到这种方法的人。记住这一点,让我来解释这个方法。
背后的想法很简单。为了计算给定文档中给定单词的比例重要性,我只需查看该文档中由感兴趣的单词组成的总单词的比例,并减去由感兴趣的单词组成的该文档之外的单词的比例。
这有点拗口,所以让我们看一个例子。使用与上面相同的场景,我的测量将采用文档 A 中由苹果公司创造的单词的比例,并从中减去 B 和 C 中由苹果公司创造的单词的比例。因此,如果文档 A 中有 50%的单词是苹果,而 B 和 C 中有 20%的单词是苹果,那么苹果在文档 A 中的重要性比例就是 0.3(30%)。请注意,与 tf-idf 不同,此度量可能会变为负值。负值只是表示该单词在给定文档外部比在文档内部更常见。
这种简单的方法既解决了零值问题,也解决了广泛的利润问题。对于零值问题,如果苹果占文档 A 的 50%,并且只在 B 和 C 中出现一次,那么比例重要性将正确地保持苹果在文档 A 中的高值,而 tf-idf 统计的值将为零。
对于扩展边距问题,如果我们保持文档 A 中由 apple 构成的单词比例不变,那么在 apple 构成文档 B 中 1%的单词的情况下,与 apple 构成文档 B 中 0%的单词的情况相比,比例重要性将相差很小。它会将这两种情况视为相似,忽略扩展边距上的微小变化。另一方面,同样假设苹果在文档中的流行度为常数,比例重要性将在苹果占文档 B 中 1%的单词的情况下与苹果占文档 B 中 50%的单词的情况下有很大不同。考虑到密集边界的变化,比例重要性将把这两种情况视为完全不同。
运行珠宝案例研究
这在理论上似乎是合理的,但我想看到它的行动。为了做到这一点,我看了一下由黑仔·迈克和埃尔-P 组成的嘻哈二人组“奔跑吧珠宝”的唱片目录。这对组合已经发行了四张专辑:奔跑吧珠宝、奔跑吧珠宝 2、奔跑吧珠宝 3 和奔跑吧珠宝 4。我把每个都缩短为“RTJ”和数字。
为了获得用于分析的数据,我在 r 中使用了{Rspotify}、{genius}和{geniusr}包,然后使用{tidytext}包将这些原始数据转换成可供分析的“整洁”形式。最后,在开始实际分析之前,我使用 SMART、snowball 和 onix 词典删除了所谓的“停用词”,比如“the”和“for”。
准备好数据后,我开始使用{tidytext}包计算每个单词-相册对的 tf-idf 值。下图显示了 tf-idf 测量的专辑中最重要的前十个单词(由于平局,一些专辑有超过 10 个单词)。
歌迷们会意识到,许多歌词是由专辑中特别独特的歌曲驱动的(这一点我希望在未来的帖子中再次提到)。例如,《奔跑吧珠宝》中的歌曲 Sea Legs 不出所料地包含了 Sea 和 Legs 这两个词,这两个词在其他任何专辑中都没有出现过。因此,这两个词在该专辑中都获得了较高的 tf-idf 分数。类似的模式也出现在《RTJ 2》中的单词 steal 和 check(来自歌曲 Lie Cheat Steal)和《RTJ 3》中的单词 garden(来自歌曲 Call Ticketron,在这首歌中,他们唱的是在麦迪逊广场花园表演)。
一个独立但同样有趣的模式是,与以前的专辑相比,像“是”、“是”和“哦”这样的表达在他们最近的专辑《RTJ 4》中尤为重要。
记住这些有趣的模式后,下一步是用我的衡量标准,比例重要性,来看看哪些单词被列为重要的。请注意,我将该图的度量从比例转换为百分比。
一些相似之处是显而易见的,《RTJ》中出现了《海与腿》(尽管重要性降低了),而《RTJ 3》中出现了《花园》。然而,有 21 个词没有被 tf-idf 列为重要的词,我的衡量标准表明它们实际上是专辑中最重要的十个词之一。
其中一些差异相对较小。RTJ2 中的“偷”和“骗”以及 RTJ 3 中的“布迈耶”没有出现在排行榜上,因为虽然它们确实是专辑中独有的,但实际上它们对他们来说并不那么重要,每个都被使用了 8 到 9 次。鉴于这种缺乏内在重要性的情况,我的衡量标准没有考虑它们。
更有意思的是度量之间的主要变化,这表明了相对重要性如何在 tf-idf 上得到提高。
一个很大的变化立即引起了我的注意,虽然 kill 根本没有出现在 tf-idf 的《RTJ 3》最重要的十个单词中,但它实际上按照重要性比例被列为专辑中最重要的单词。这确实是一个巨大的差异。然而,只要看一看基础数据,就能立即弄清楚为什么会出现这种情况。
Kill 在《RTJ 3》中出现了 97 次,几乎占了专辑中所有不间断单词的 3%。它不仅在专辑中很重要,而且相对来说也是独一无二的,在《RTJ 3》中比在专辑中多出现了整整 6 次,它出现的频率位居第二(《RTJ 2》)。因此,它的比例重要性值很高。
然而,正如我们在表中看到的,tf-idf 值实际上是零,这表明这个词对专辑来说一点也不独特或重要。怎么回事?归结起来就是零值问题。因为 kill 在所有四个专辑中至少出现一次,所以逆文档频率为零,因此 tf-idf 分数本身为零。尽管这个词在《RTJ 3》中既重要又相对独特,但还是出现了这种情况。
在 tf-idf 中,RTJ 的“嘿”和 RTJ 2 中的“跑”也会出现同样的问题。和“kill”一样,这两个词都没有被 tf-idf 列为重要词,但它们都被列为专辑中最重要的词。就像“kill”一样,这种差异是有棱有角的,因为这两个词在所有专辑中都至少出现过一次。因此,尽管这两个词在他们给定的专辑中很常见并且相对独特,但他们在 tf-idf 中的得分为零。
事实上,对于比例重要性和 tf-idf 不一致的超过一半的单词(11 ),原因是 tf-idf 测量的零值问题。这证明我的方法确实改善了 tf-idf 面临的零值问题。
广泛的保证金问题呢?RTJ 4 中的“奴隶”一词显示了我的措施是如何应对这一挑战的。虽然比跑或杀更微妙,奴隶同样没有出现在《RTJ 4》中关于 tf-idf 的前十个词中,但却有相应的重要性。同样,原始数据有助于解释为什么会这样。
Slave 在《RTJ 4》中出现得有点频繁(虽然不是压倒性的),在其他地方很少出现。事实上,大约 90%的“奴隶”出现在《RTJ 4》中,只有两次在专辑外提到它(一次在《RTJ 2》,一次在《RTJ 3》)。因此,我的衡量标准认为它对 RTJ 协议 4 非常重要。另一方面,对于 tf-idf,由于它在 4 张专辑中的 3 张专辑中至少出现一次(即使只是一次),所以该值较低(0.002)。
为了显示 tf-idf 处理这种情况的脆弱性,考虑一下当我简单地删除 RTJ 4 之外的 slave 的两个实例并重新计算时会发生什么。tf-idf 统计不仅翻了三倍达到 0.008,而且成为《RTJ 4》中任何单词的第三高分数。换句话说,这个词从甚至不在最重要的十个词之列变成了第三名。尽管奴隶出现在 RTJ 4 之外两次和没有出现两次之间几乎没有实际差别,这种情况还是发生了。这是 tf-idf 在大范围内过度敏感的一个很好的例子。
另一方面,如果你增加奴隶出现在 RTJ 4 之外的次数,比如 400 次,tf-idf 的统计数据不会改变,仍然是 0.002!尽管这个词在第一种情况下对 RTJ 4 来说有些重要和独特,但在第二种情况下却一点也不独特,tf-idf 的统计数据并没有改变。这证明了我上面所讨论的:tf-idf 不仅在广泛的边界变化时过度敏感(该词出现在外部相册中的数量从零到一个或两个),而且在密集的边界变化时过度抵制变化(当外部提及的总数从两个到数百个)。
我的比例重要性度量更好地处理了这种情况。它承认 slave 确实对 RTJ 4 非常重要,但没有赋予过高的价值,因为它也承认虽然独特,但对专辑并不特别重要(只占总字数的 0.5%)。此外,当 slave 出现在 RTJ 4 之外的次数从 2 到 0 时,它正确地指出这是一个小变化。另一方面,当外部出现的数量急剧增加时,它变得非常消极,正确地表明奴隶对于 RTJ 4 已经变得相对不重要。
这些发现同样适用于其他单词,比如《RTJ 2》中的“holding”。事实上,tf-idf 对这个词的大范围变化比对 slave 更敏感。简单地除去《RTJ 2》之外的两次出现,tf-idf 的统计数据从甚至不在前十名变成专辑中任何词的最高*。也就是说,仅仅通过删除这个词的两个外部实例,tf-idf 就从在《RTJ 2》中说持有基本上不重要变成了字面上最重要的词。同样,我的措施以一种更有分寸的方式处理这种情况。它给它一个中等的值,因为它认识到虽然这个词对《RTJ 2》非常重要(在这张专辑中出现的次数是其他专辑的 19 倍),但它对整个专辑并不特别重要(只占单词总数的 0.7%)。*
最终,这个案例研究证明了比例重要性确实实现了我为它设定的目标。在许多方面,它反映了 tf-idf,捕捉了许多相同的单词,并将它们列为重要单词。然而,它避免了 tf-idf 的主要缺点:它不会突然逐步下降到零,它不会对广泛边际的变化过于敏感,它不会忽略密集边际的变化。
结论
这一切给我们带来了什么?当然,这并不是说 tf-idf 是无用的,应该被完全抛弃。这不会发生,也不应该发生。一般来说,这是一个有用的统计数据,我发现的问题通常只发生在边缘情况下。
相反,我写这篇文章只是为了建议分析师和研究人员在使用这种方法时应该谨慎行事,承认它的缺点以及它们可能如何和何时改变分析。就在上面的小案例研究中,当我切换到比例重要性时,最重要的词的组成发生了一些戏剧性的变化,并且以一种提出关于 tf-idf 的问题的方式这样做。事实上,这种转变肯定大到足以改变分析的结论。
就比例重要性而言,我写这篇文章也不是暗示它将取代 tf-idf。我强烈怀疑它不会,这没关系。也就是说,我真的希望我已经让你相信它是一个强大的工具,反映了 tf-idf 的优点并减轻了它的缺点,我很乐意分享我用来计算它的代码(代码仍在开发中。它完成了工作,但是还没有优化速度。
当我等待成百上千的关于比例重要性的消息涌入时,我会简单地说祝你文本挖掘愉快!
数据里面有什么!
预处理、EDA 和特征工程
弗兰基·查马基在 Unsplash 上拍摄的照片
信不信由你,这部分占了整个 ML 工作的 60-70 %!我不会在这里谈论代码,因为我相信如果你知道逻辑,找到一个代码并不是超级困难的,只是到那里会因人而异。获得代码的地方有 StackOverflow、Kaggle、Github 或 Google 上任何有助于实现这种逻辑的地方!
相反,让我们谈谈作为数据科学家在进行初始分析时要记住的一般逻辑/概念。这将包括整理数据,理解背后不同的模式,等等。
可以去翻翻我的上一篇了解一下**“我从哪里开始学 ML”**,适合初学者或者任何不同背景想学 ML 的人。
整理数据
数据清理或数据清理是从记录集、表或数据库中检测并纠正(或删除)损坏或不准确的记录的过程,是指识别数据中不完整、不正确、不准确或不相关的部分,然后替换、修改或删除脏的或粗糙的数据。——(来源——维基百科)。
为什么我们需要清理数据?让我们看看下面的例子:
来源: Pablo Sanchez 通过quandare
在这个“脏数据”的小例子中有许多问题。
- ID 列(应该是主键)应该有唯一的值,但是有个重复记录。
- 日期列有不同的日期格式,这使得后面在一个层次上的分析变得困难。
- 在某些列中有个缺失记录
- 相同的名字有不同的拼写或打字错误。
这些只是数据如何变脏的几个例子。也可能有其他东西会弄乱数据,应该被删除。所以在分析数据之前,清理数据是非常重要的一部分。
现在,你知道数据是混乱的,那么你如何修复它呢?
- 最好的情况→与消息来源谈谈,看他们能否帮你清理数据。
- 如果那是不可能的,那么你必须自己做。数据中不同类型的错误可以基于用例和数据集类型以多种方式修复。
- 重复行可以在某些级别(例如在学生级别、城市级别或教师级别)进行聚合,以创建唯一的记录。
- 不同格式日期、数字、收入、分数等。应采用相同的格式,以适用者为准。
- 如果有人填写作为数据来源的表格,打字错误是不可避免的。但是,从长远来看,使这种数据输入系统自动化有助于更好地获取数据。
- 缺失记录——根据缺失项目值和用例的列,有多种填写方式。
a.你可以用一个普通的值来填充(比如 0 或者 9999 或者“:”),
b.使用整个列的平均值/中值
c.使用先进的方法,如 KNN(k-最近邻)或,
d.如果没什么区别,就让它保持原样。
一旦所有不同的数据集都清理干净,你需要**把它们放在一起。**因为对于机器学习来说,如果我们有一个大文件,就更容易输入到模型中。
一旦数据清理到一定程度,我们就可以进入下一步了。
理解背后的模式
一旦我们清理了数据,我们就可以开始分析它了。分析是可以从数据中收集到的任何有用的发现/见解。例如,如果你可以将你的整个人生放入数据中(从你出生的第一天到你今天午餐吃了什么),我们从中选取一个随机样本,你可以获得的一些见解可能是:
来源:作者
- 你今年吃了多少汉堡?其中,你吃了多少薯条?
- 你和朋友一起吃过几次饭?
- 当你和你的朋友在一起的时候,你吃了多少次汉堡?诸如此类的事情。
为什么分析是必要的?它帮助我们理解**“我们有足够的样本/特征来解决最终问题吗”**?
我们可以了解数据中的不同模式,或者多个列如何相互关联,或者不同级别的发现—就像在这个示例中,我们可以在天/月级别、食物类型、使用的交通工具等方面获取数据。它还可以帮助我们删除对我们的查找不必要的列。我将在下一篇博客中详细解释这个步骤,并附上代码和示例。
特征工程
特征属性列==维度
特征工程是指操纵/改变特征以创造新的特征。为什么这很重要?因为这有助于我们展现数据的不同属性。
例如-地址包含:伦敦贝克街 221b 号。我们可以溶解这个列以带出更多的值 —城市、街道、公寓#。类似地,生日“1994 年 1 月 21 日”可以分解成日期、月份、年份、一年中的某一天、一年中的某一周等。这些新栏目比原来的功能更有意义。
另一个例子,如果整个数据集是伦敦的,我们可以删除新创建的城市列,因为它**不会增加任何附加值。**类似地,如果我们有一个年龄列,并且添加了与出生日期列相同的值,我们可以删除其中的一个。
以上两种方法都是特征工程的例子。还有其他方法来创建新的功能,你可以添加滞后,做一个总收入/累计总收入,列的平均值/中值,不同类别的计数等。因此,通过这种方式,我们可以创建许多功能来帮助模型很好地理解和预测数据。
但是,有一个东西是我在读硕士期间碰到的——**“维度的诅咒”。**这暗示了拥有大量维度实际上并不好。那我们该怎么办?嗯,曾经有一件简单的事情要做:
a .没有给数据增加任何价值的列应该被删除。
b .应删除暗示相同细节的多列。
除此之外,我们还有其他方法可以自动为模型选择最佳列,如特征重要性、SHAP 等。但是我们将在创建模型的阶段讨论它们!:)在此之前,享受预处理数据,并让我知道你的反馈!
ICLR 2020 大会上的变形金刚有什么新内容?
变形金刚是一种基于注意力的神经架构,它在推出后将 NLP 领域推向了新的高度。国际学习代表会议有大量的相关出版物,所以这里有一个相关出版物的精选集,可以帮助你浏览它们。
学习表示国际会议(ICLR)是机器学习社区最受欢迎的舞台之一。如今,该领域的会议通常作为高质量的商标,并成为已经存在于预印服务器中的出版物的焦点。尽管如此,呈现的工作量越来越大,这使得它很难跟上。
在 Zeta Alpha ,我们密切关注自然语言处理(NLP)和信息检索(IR)研究的前沿。本着这种精神,在我们的语义搜索引擎的帮助下,我们从 40 多篇论文中精选了 9 篇!—从三个主要角度与亮相 ICLR 2020 的变形金刚有关:建筑修改、培训创新和衍生应用。尽情享受吧!
🏛建筑修订
了解最新的变形金刚模型。
1. ALBERT:用于语言表达自我监督学习的 Lite BERT|ICLR 会议
变压器在很大程度上变得过度参数化,因为这是在几个 NLP 任务中实现最先进水平的成功秘诀。或者,ALBERT 是一个已经很有影响力的例子,说明了如何在保持让 BERT 出名的令人印象深刻的性能的同时,减少它对资源的消耗。
这些优化包括:
- 因式分解嵌入参数化:通过使用不同于文字块嵌入尺寸的隐藏尺寸,嵌入参数化可以因式分解,将其尺寸从 O(Vocab × Hidden)减小到 O(Vocab × Emb + Emb × Hidden),如果隐藏≫ Emb,这可能是实质性的。
- 跨层参数化共享:为不同的变换块重用参数,如 FFN 和/或注意力权重。
- 句子排序目标:作者认为从原始 BERT 中预测下一个句子不够有挑战性,引入了这个新的句子级自我监督目标。
结果如何?与 BERT-large 相比,参数少 18 倍,性能相当,推理速度略快。
2.改革者:高效的变压器 | ICLR 会议
早期转换器的一个限制是注意力机制的计算复杂度与序列长度成二次方关系。这项工作引入了一些技巧,以允许更有效的计算,这使得对更长的序列(从 512 到 64k!).为此,该模型的主干包括:
- 允许在整个模型中仅存储激活的单个副本的可逆层。
- 使用位置敏感散列法(LSH) 通过快速最近邻居来近似注意力计算。这就用 O(L log L)代替了注意层中的 O(L)因子。
来源:重整器:高效变压器
3.Lite Transformer with Long-Short Range Attention(LSRA)|ICLR 时段
这里有另一个提议,通过强加他们所谓的“移动约束”来克服变压器中的长距离依赖性和高资源需求。这一次,他们对短期依赖使用卷积,对长期依赖使用选择性注意力,创造了一个新的更有效的变压器 LSRA 积木。
虽然结果无法与其他成熟的旗舰变形金刚相提并论,但其有原则的架构设计和深思熟虑的动机使其值得一提。
🧠关于学习
模特如何学习和模特看起来如何一样重要,所以这里有一些令人耳目一新的出版物,推动了变形金刚如何学习的界限。
1.伊莱克特拉:预先训练文本编码器作为鉴别器而不是生成器 | ICLR 会议
自引入 BERT 以来,掩蔽语言建模(MLM)一直是模型预训练目标的学习基础。本文提出了一种更便宜、更快速的替代方案:替代令牌检测。
主要想法非常简单:不是让模型猜测屏蔽的令牌,而是需要区分哪些令牌被一个小型生成器网络所取代,该网络提出了看似合理但错误的令牌。作者声称,这个目标比 MLM 更有样本效率,因为任务是在所有序列上定义的,而不仅仅是屏蔽的标记。如果这些结果证明自己很容易重现,这项任务有可能成为无监督预训练的新标准。
来源: ELECTRA:预训练文本编码器作为鉴别器而不是生成器
2. TabFact:用于基于表的事实验证的大规模数据集 | ICLR 会议
随着现代变压器缩小与人类性能的差距,许多经典的 NLP 数据集正在变得过时,这意味着需要创建新的更具挑战性的基准来刺激进步。在这种情况下,提出了一种新的数据集来解决对用自然语言表达的基于事实的信息进行建模的问题。
它由来自维基百科的 16k 个表格和 18k 个人类陈述组成,带有引用事实数据的ENTAILMENT
或REFUTED
标签。基线的性能仍然一般,所以这是一个激动人心的创新解决这个任务的时刻!
3.预训练百科:弱监督知识-预训练语言模型 | ICLR 会议
这项工作没有采用传统的 MLM 目标,而是从稍微更加结构化的数据中探索自我监督训练的力量:维基百科及其实体。它们用其他相似类型的实体替换文本中的实体( a la ELECTRA),模型学习通过上下文辨别被替换的实例。使用这种方法,模型被迫学习关于真实世界实体及其关系的信息。
当在预训练中将该任务与经典 MLM 相结合时,它导致零射击事实完成的性能的显著提高,以及以实体为中心的任务(如问题回答和实体打字)的性能的改善。
优秀奖: 一种语言表征学习的互信息最大化视角;用频谱控制改善神经语言生成;深度学习大批量优化:76 分钟训练 BERT。
🤖分拆用途
变形金刚不仅仅是语言建模。以下是一些作品,巧妙地利用这些模型的力量来解决相关问题。
1. BERTScore:使用 BERT 评估文本生成 | ICLR 会议
在松散定义的环境下客观地测量质量(即生成连贯的文本)本质上是具有挑战性的。在语言中,BLUE score 被广泛用作文本相似性的代理,它与人类对文本生成任务(如翻译或问答)的判断有很好的相关性,但它仍然远非完美。
这项工作解决了这个问题,并展示了如何为序列对设计一个基于 Bert 的评分函数,用于文本生成,使与人类判断更好地关联。该过程非常简单,不涉及任何微调:只有预先训练的上下文嵌入,余弦相似性和基于频率的重要性加权。
尽管失去了一些可解释性,这种学习得分能成为新的标准吗?只有时间能证明一切。
基于 BERT 的评分函数之一的示例。来源: BERTScore:用 BERT 评估文本生成
2.基于嵌入的大规模检索预训练任务 | ICLR 会议
鉴于 BM25 这样的简单基线是如此强大和难以超越,信息检索领域已经晚于神经革命。目前,大多数神经增强的 SOTA 方法需要两个主要步骤:第一个快速过滤整个文档集——基于 BM25 类算法— ,以及重新排序步骤,其中通过神经网络处理查询和一小部分文档。这种方法存在许多局限性,因为在第一步中错过的任何文档都不会被进一步处理,并且在推理时完全处理查询和文档对的计算成本严重限制了现实世界的适用性。
相反,这项工作探索了受约束的问题,其中推理只能通过预先计算的文档表示的嵌入相似性得分来完成,从而实现大规模的端到端基于转换器的检索。
要得出的关键见解是,使用段落级自我监督任务进行预训练是必不可少的,而标记级屏蔽语言建模对这一特定任务的影响可以忽略不计。在结果部分,他们展示了即使在相对缺乏监督训练数据的情况下,BM25 如何能够在问答任务中被击败。
3.VL-伯特:通用视觉语言表征的预训练 | ICLR 会议
如何利用预训练和微调框架来共同学习通用语言和视觉表示?这里我们找到了一个很好的例子:视觉语言 BERT 将 Transformer 架构和 R-CNN 一起作为主干。虽然这不是同类中的第一个,但它是对现有模型的一个令人耳目一新的改进,并且为视觉常识推理 (VCR)基准设定了一个新的最先进水平(嗯,在出版时)。预培训程序依赖于两个主要目标:
- **具有视觉线索的掩蔽语言建模:**类似于原始的 MLM 任务,但是增加了被加字幕的图像区域的表示。
- **利用语言线索的掩蔽的感兴趣区域分类:**以一定的概率,图像的区域被掩蔽,并且目标是在给定语言信息的情况下预测该区域的类别。
🎉奖金:关于自我关注和卷积层的关系 | ICLR 会议
这篇非传统的论文对注意力机制和卷积可能存在的共同点进行了令人信服的分析。有趣的是,他们发现的重叠比人们事先预期的要多:正如他们的证据所表明的那样,注意力层经常学会像 CNN 一样注意“像素网格模式”。
使用计算机视觉作为案例研究,以及详细的数学推导,他们得出结论,变压器架构可能是 CNN 的概括,因为它们经常学习等效的模式,甚至可能由于同时学习局部和全局信息的能力而呈现优势。
优秀奖: 符号数学深度学习;[逻辑和 2-单纯变压器](http://LOGIC AND THE 2-SIMPLICIAL TRANSFORMER)(用于深度 RL)。
今年的 ICLR 完美地反映了机器学习的一个充满活力的活跃分支是如何成熟的:模型、训练技术、数据集和应用变得更加完善,围绕它们的理解也更加深入。我们这篇文章的变压器之旅到此结束,但会议还有很多内容需要探索。我和我的团队将密切关注相关的会谈和研讨会,并通过我们公司的 twitter feed 在 @zetavector 上实时报道有趣的见解,所以如果你不想错过任何事情,请收听我们的节目!
谷歌新推出的人工智能“哼歌搜索”功能可以搜索歌曲
人工智能搜索你最喜欢的歌曲
来源: Unsplash
借助人工智能的力量,我们可以想象的一切现在都有可能实现。你有没有想象过,如果你能在某个地方找到你听过的那首歌,而你的脑海里只有音乐?你可能这样问过你最好的朋友。
像这样“哼哼哼哼哼哼”的那首歌叫什么来着但是你的朋友(一个人类)也没有告诉你歌名。
人工智能已经证明,它现在可以读取你在想什么,但人类不能。有了大量的数据、机器学习算法和高处理能力的机器,这一切都是可能的。
这种哼唱的主要特点是,即使你在嘈杂的背景下,这种功能也能很好地准确工作。要使用这种功能,你不需要成为一名歌手,你可以哼唱,谷歌将使用其人工智能算法和高端计算能力来完成剩下的工作。
该功能目前支持 20 种语言。这意味着我们可以哼唱,谷歌将找到 20 种不同语言的歌曲。现在还不知道这二十种语言是什么。我已经在印度语和英语歌曲中测试过了,它运行得相当快和准确。
谷歌是如何做到的
我对幕后的技术很好奇,我发现它使用了谷歌的下一代音乐识别功能。它使用深度学习算法,可以通过大量数据来训练我们的模型。此前,谷歌在 Pixel 2 手机中推出了类似的功能,可以在另一台设备上播放歌曲,Pixel 的手机可以通过音乐和歌词识别歌曲。我们现在可以在谷歌搜索功能中使用我们的声音,即使没有歌词,也可以通过哼唱找到这首歌。
如何有效地使用“哼声搜索”功能
由作者添加
你可以说,“好吧,谷歌,这首歌是什么?”或者你可以从谷歌小工具中添加快捷方式。你需要哼唱大约 10-15 秒,接下来,你会发现这首歌在你的脑海中回响。
你觉得这个功能怎么样?
照片由 Ehimetalor Akhere Unuabona 在 Unsplash 上拍摄
这一新的人工智能搜索功能上周刚刚推出。更新您的 Google 应用程序后,您可以更有效地使用该功能。对于 Siri 中的 IOS 用户,该功能目前不可用。但作为一个突破性的功能,Siri 可能很快就会有这个功能。这个功能对我们许多人来说是一种祝福,因为我们可以哼唱并找到歌曲;我们不需要去问别人,也不需要靠猜歌词去四处搜索。
车床 0.1.2 有什么新功能?
车床 0.1.2 中一些最激动人心的特性的回顾。
L 距离 0 . 1 . 2“butter ball”被合并到 master 并取代之前的车床 0.1.1 只有几个提交之遥。在车床 0.1.2 中已经呈现了许多令人兴奋和有趣的东西,并且有许多有趣的新东西需要实验——既有已实现的,也有计划中的。所以事不宜迟,我们来看看车床 0.1.2 有什么新功能!
宏指令
车床现在有一系列易于访问和利用的宏,用于车床内部的最基本操作。这还附带了一系列非常酷的实验性宏,你可能没有想到它们会被实现,这很可能会使机器学习在车床上变得更加容易。
首先,stats.jl 已经获得了执行统计测试的宏。正如您所预料的,这可以使统计测试更快。新宏的一些示例包括:
@t -> Independent T-test
@f -> F-test
@- -> Signs test
以及一些为方便起见而添加的基本统计宏:
@mu -> Mean
@r -> Correlation Coefficient
@sigma -> Standard Deviation
除此之外,还有一个非常酷的新精度宏,叫做@acc。这在某种程度上是未来努力的模板,但是@acc 宏的目标是能够在同一个函数中保持连续和绝对的准确性。不要再问 r2、广义分类准确度或平均绝对误差,很快一个机器学习模型就会为你做这些!在未来,我很乐意进一步扩展它,以包含一个更强大的模型和更受欢迎的验证方法,比如混淆矩阵。
Powerlogging —有进一步实施的计划
Powerlogging 是一个非常酷的概念,已经在 STATA 软件中使用了一段时间。它允许统计学家用数学方法计算模型功效的适当样本量。如果您想了解更多关于 powerlogging 本身的知识,我已经写了另一篇文章,深入讨论了它是如何工作的,它做了什么,以及如何从头开始编写代码。
将权力投入到您的物流决策中。
towardsdatascience.com](/power-analysis-the-coolest-thing-that-youve-never-heard-of-476d35c18161)
虽然这本身很酷,但我有很多想法,谁可以将它进一步实现到模型中,甚至可能是预处理。这可以通过使用不同的训练样本大小来实现,也可以通过同时测试不同的样本来获得更准确的结果。所有这些都可能等同于更高的后勤准确性,这绝对是非常酷的!
分割
我最终得到的印象是车床包装太大了。因此,它们被分开并包含在内。虽然这不会对最终用户产生影响,但对于贡献者来说,这无疑是一个显著的增加。这将使在车床上操作特定组件比以前容易得多,并允许像宏、模型和公式这样的东西驻留在它们自己的位置上。
证明文件
虽然 http://lathe.ai 服务器目前正在进行维护,但 lathe 终于有了一个自动更新文档的网站!这当然会使使用文本文件时使用车床比使用 REPL 更容易。在这个新的文档站点发布之前,关于车床的文档只能通过 Julia?()方法。虽然我当然认为在大多数情况下这仍然是处理文档的一个更好的方法,但是我当然能够理解能够滚动浏览网站的吸引力。此外,能够在谷歌上找到你的答案总是一件很棒的事情!
在新网站的顶部,车床的文档已被修改,以包括更多的信息,并彻底解释如何在车床类型使用。当然,由于车床仍然处于开发的早期,这只会随着开发的深入而改进,这是令人兴奋的!
结论
这一次,车床增加了一些令人兴奋的新功能,但是这个软件的未来肯定是非常光明的。未来的车床更新将提出进一步的统计库,增加更多的模型,并增加更多的预处理功能。虽然有很多工作要做,但我仍然对车床自诞生以来的发展感到高兴。
Matplotlib 3 的新特性
第 3 代中最重要的更新概述
如果说可视化在数据中无处不在,无论大小,那么 Matplotlib 在 python 中同样无处不在。
Matplotlib 是 python 中使用最广泛的绘图库。**句号。**自 2003 年首次发布以来,它已经经历了四代开发,最新版本是最近发布的 3 . 2 . 2(2020 年 6 月 17 日)。最新一代的 Matplotlib 3 只与 Python 3 兼容,是近两年前推出的。
Matplotlib 开发的历史时间表(未按比例绘制)
为了保持这篇文章的简短,我将关注从 Matplotlib 3.0 开始的最有趣的特性(在我看来),然后转移到 3.1 和 3.2 版本。如果你对学习 python 绘图的基础感兴趣,请阅读我最近在《走向数据科学》中的文章,如果你想了解最新的 Matplotlib 3.3 中的特性,请阅读我的第二篇文章这里。
生存下来的不是最强壮的物种,也不是最聪明的物种,而是对变化最敏感的物种——查尔斯·达尔文
所以准备好在 Matplotlib 3 上更新自己吧
Matplotlib 3.0 中的新功能
- 轴的可缩放性 如果您想按给定的数量级缩放轴的值,您可以指定相同的值作为上限和下限。例如,下面的代码片段将 y 轴缩放 1000 倍。
import numpy as np
import matplotlib.pyplot as pltfig, ax = plt.subplots()x = np.linspace(0, 2*np.pi, 1000)ax.plot(x, np.sin(x**2), 'orange', label=r'sin($x^2$)')
ax.legend(title='Legend Title', fontsize=14, title_fontsize=18)ax.ticklabel_format(style='sci', scilimits=(3, 3), axis='y')
sin(x)函数的重新缩放 y 轴。注意左上角的乘法因子 1e3。
2.自由选择图例标题的字体大小
您现在可以分别设置图例标题和图例标签的字体大小。这已经在代码片段和上图中显示出来了。如果你正在使用rcParams
,你也可以使用rcParams["legend.title_fontsize"]
和rcParams["legend.fontsize"]
分别指定两者
plt.rcParams["legend.title_fontsize"] = 18
plt.rcParams["legend.fontsize"] = 14
3.饼图现在默认为圆形
与 Matplotlib 2 不同,饼状图现在默认总是圆形的,你不需要手动设置纵横比"equal"
。在早期版本中,您需要指定ax.set_aspect("equal")
或plt.axis("equal")
来制作圆形饼图。如果您不喜欢这个默认行为,您可以使用ax.set_aspect("auto")
或plt.axis("auto").
来覆盖它**
4.轴标题和x-轴之间不再重叠
如果图的顶部有x-轴(或双y-轴),图标题 将不再与顶部 x 轴标签和刻度标签 重叠。以前,您必须手动重新定位图形标题。
捕捉 : 默认y*-标题值为 1.0。即使您手动指定默认位置为ax.title.set_position(0.5, 1.0)
、,这是多余的,因为它已经默认了,底层算法仍然会重新定位标题并防止重叠。如果你不想重新定位,并且你是一个混乱和喜欢重叠的人,你可以使用一个不等于 1 的值 y 来防止它,例如ax.title.set_position(0.5, 1.005)
*
5. GridSpec 现在更方便了
以前,要添加子情节网格,您必须使用需要导入gridspec
的gridspec.GridSpec()
和gridspec.GridSpecFromSubplotSpec()
方法。现在这两个都换成了add_gridpec()
和SubplotSpec.subgridspec()
。这移除了显式需要来导入gridspec
,如下面的官方示例所示
*fig = plt.figure()
gs = fig.add_gridspec(3, 1)ax1 = fig.add_subplot(gs[0])
ax2 = fig.add_subplot(gs[1])
sub_gs = gs[2].subgridspec(1, 4)for i in range(4):
fig.add_subplot(sub_gs[0, i])*
Matplotlib 3 中“add_gridspec”和“subgridspec”的演示
Matplotlib 3.1 中的新功能
- 创建辅助 x-y 轴的新方法
假设您正在用欧元计算股票价格,但是您的老板要求您也在同一数字中显示相应的美元价格,那么 副轴 就是您所需要的。你现在可以简单地使用ax.secondary_xaxis()
和ax.secondary_yaxis()
。您必须定义两个转换函数,例如下面的eur2dol()
和dol2eur()
,它们将定义主轴和副轴之间的关系,如这个官方示例所示。
***def** eur2dol(x):
**return** x * 1.14 # Taking 1 Eur = 1.14 US Dollar as Rate
**def** dol2eur(x):
**return** x / 1.14
secax = ax.secondary_xaxis('top', functions=(eur2dol, dol2eur))*
2.整洁简洁的日期格式器
如果你正在处理日期,你会喜欢这个功能的!新的日期格式器,被称为ConciseDateFormatter()
,属于matplotlib.dates
,与默认的格式器相比,它可以简洁明了地显示刻度标签。
3.轻松创建散点图的图例
以前,在为标记绘制不同颜色和大小的散点图时,需要一种变通方法,要么用单个标签条目绘制多个散点图,要么使用代理美工手动添加它们。Matplotlib 3.1 通过引入返回唯一句柄和标签的legend_elements()
简化了这一过程,这些句柄和标签可用于生成图例。此处提供了一个官方示例。
4.反转轴的新方法
现在,您可以使用set_inverted()
反转轴,使用get_inverted()
检查轴之前是否被反转过。后者将返回 Matplotlib 2 中的True
或False.
,等效方法为invert_xaxis()
和invert_yaxis()
用于反转,xaxis_inverted()
和yaxis_inverted()
用于检查轴是否已反转。
*fig, ax = plt.subplots()x = np.linspace(0, 0.5, 100)ax.plot(x, np.sin(x**2), 'orange')
ax.xaxis.set_inverted(True) # <-- Takes Boolean as argumentax.xaxis.get_inverted()
>>> True*
x 轴倒置的图形
5.滑块控件终于俯身直起
现在可以有一个垂直的小部件滑块。您需要传递一个可选参数orientation
,它可以是'horizontal'
或'vertical'
。
Matplotlib 3.2 中的新功能(最新版本是 3.2.2)
- 控制轴的标题位置和颜色
在定制您的rcParams
文件/设置时,您现在还可以传递图形标题的位置及其颜色。标题的位置可以是以下任意一个:"left", "center", "right"
。标题的颜色可以是"auto"
或任何指定的颜色,如"red"
、"mediumseagreen",
等。这里列出了和。
*plt.rcParams["axes.titlelocation"] = "left"
plt.rcParams["axes.titlecolor"] = "red"*
2.3d 条的阴影
你现在可以用bar3d().
从不同的角度投射光线来制作漂亮的 3d 条,这可以用[lightsource](https://matplotlib.org/3.2.0/api/_as_gen/matplotlib.colors.LightSource.html#matplotlib.colors.LightSource)
参数来配置,它有两个角度:方位角和高度。阴影参数需要是True
来调用这个效果。
3.选择显示哪些误差线
有时您可能希望在数据点上显示误差线。然而,如果您有大量的数据点,您不希望在每个点上添加误差线。到目前为止,您只能选择在每个 n 数据点后放置误差线。现在,您还可以指定误差线的起点。下面的第一个代码将在x[::5], y[::5]
点放置误差线,而第二个代码将在x[2::5], y[2::5]
放置误差线,即从第二个点开始每隔第五个点放置误差线。[::5]
是 NumPy 的切片符号,它返回每第 5 个元素。
*# Before matplotlib 3.2
plt.errorbar(x, y, yerr, errorevery=5)# matplotlib 3.2 onwards
plt.errorbar(x, y, yerr, errorevery=(2, 5))*
这就是我的帖子的结尾。恭喜你!现在,您已经更新了 Matplotlib 3 的一些最新特性。下一个候选版本是 3.3.0 。当这种情况发生时,我会更新这个帖子。
您可以在以下超链接中找到 Matplotlib 3 中新增功能的完整列表: 3.0 、 3.1 和 3.2 。如果你对学习 python 绘图的基础感兴趣,请阅读我在《走向数据科学》中的文章。
Matplotlib-ing 快乐!
熊猫 1.0 和 TensorFlow 2.0 的新增功能
关于用于数据分析和机器学习的流行 python 包的大版本,需要记住一些事情。
本文假设读者对这些库有一定的了解。如果你需要一个快速介绍,这里有一些关于熊猫和 TensorFlow 的很棒的媒体文章。
熊猫 1.0.0
来源:熊猫用户指南
(2020 年 1 月 29 日发布)
pandas(Panel Data 的缩写)是一个用于数据分析和操作的 Python 包,早在 2008 年就从 AQR Capital Management 开源了。它的主要特性是 DataFrame 对象,该对象为 Python 用户提供了一种简单且标准化的方式来与表格数据进行交互。当我开始使用它时,我觉得很奇怪,这样一个突出和广泛使用的软件还没有 1.0 版本。
从 0.25.3 →1.0.0 变化不多。尽管如此,以下是主要的主题。
新数据框列类型
这是熊猫在 1.0 版本之前处理数据类型的方式:
来源:https://pbpython.com/pandas_dtypes.html
现在我们可以在列表中再添加两个:pd.StringDtype()
和pd.BooleanDtype()
。
**字符串类型:**在添加string
数据类型之前,Pandas 字符串列被编码为 NumPy object
数组。这太笼统了,因为任何东西都可以存储在熊猫对象列中。很难区分哪些列是只有字符串的,哪些列包含混合的对象类型。
现在有了 Pandas 中的pd.StringDtype()
列,你应该可以在字符串列上运行所有的 python 字符串方法,比如.lower()
、.upper()
、.replace()
等等。
**布尔类型:**在新的熊猫布尔类型之前,布尔列被编码为bool
类型的 NumPy 数组。唯一的问题是这些数组不能包含缺失值。新的pd.BooleanDtype()
解决了这个问题。
说到缺失值…
三种不同的数据类型表示熊猫对象的“缺失”:np.NaN
表示浮点类型,np.NaT
表示日期时间类型,None
表示其他对象类型。一些人(包括我)认为这很烦人,很困惑。
引入pd.NA
,新的捕捉所有缺失数据的熊猫类型。那么它是如何工作的呢?
用于算术运算;任何被加、减、连、乘、除等的东西。将返回pd.NA
。
In[1]: pd.NA + 72
Out[1]: <NA>In[2]: pd.NA * "abc"
Out[2]: <NA>
除了少数特殊情况,比如pd.NA
所代表的数值与结果无关。
In[3]: 1 ** pd.NA
Out[3]: 1In[3]: pd.NA ** 0
Out[3]: 1
为了便于比较,pd.NA
的行为就像您所期望的那样,通过操作进行传播。
In[4]: pd.NA == 2.75
Out[4]: <NA>In[5]: pd.NA < 65
Out[5]: <NA>In[6]: pd.NA == pd.NA
Out[6]: <NA>
要测试缺失数据:
In[7]: pd.NA is pd.NA
Out[7]: TrueIn[7]: pd.isna(pd.NA)
Out[7]: True
对于布尔运算,pd.NA
跟在三值逻辑 ( 又名 Kleen 逻辑)之后,类似于 SQL、R、Julia。
In[8]: True | pd.NA
Out[8]: TrueIn[9]: False | pd.NA
Out[9]: <NA>In[10]: True & pd.NA
Out[10]: <NA>In[11]: False & pd.NA
Out[11]: False
如果pd.NA
的值可以改变结果,那么操作返回<NA>
,但是如果pd.NA
的值对结果没有可能的影响,就像在True | pd.NA
和False & pd.NA
中那样,那么它将返回正确的值。
挑战问题:这也能评价什么?(答案在最后。)
In[12]: ((True | pd.NA) & True) | (False & (pd.NA | False))
Out[12]: ???
注意:该pd.NA
值是实验性的,并且行为可能会在没有警告的情况下改变。有关更多信息,请查看文档中的 处理缺失数据 部分。
速度和动力
来源: Numba 文档
C 运行速度比 Python 快主要原因是 C 得到编译而 Python 得到直接解释*(注:* 稍微多一点 ) 。Pandas 和 NumPy 使用 Cython 将 Python 代码转换成 C 语言并获得性能提升。
但是在 Python 社区中,另一个编译器 Numba 正在迅速获得关注。Numba 允许你编译 Python 代码到几乎达到 C 和 FORTRAN 的速度;没有任何额外编译步骤或安装 C/C++编译器的复杂工作。只需导入numba
库,用@numba.jit()
修饰你的函数。
举例:
@numba.jit(nopython=True, parallel=True)
def my_function():
...
# Some really long and computationally intense task
return(the_result)
Pandas 在apply()
函数中添加了一个engine=’numba’
关键字,用 Numba 运行你的数据操作。我认为我们将开始在 Python 数据科学生态系统中看到更多这种功能。
可视化原始数据
眼见为实。甚至在用数据制作图表之前,当人们将数据放入 DataFrame 对象时,他们做的第一件事就是运行.head()
方法来了解数据的样子。
您现在有 2 个选项来轻松查看您的数据。
# Create a DataFrame to print out
df = pd.DataFrame({
'some_numbers': [5.12, 8.66, 1.09],
'some_colors': ['blue', 'orange', 'maroon'],
'some_bools': [True, True, False],
'more_numbers': [2,5,8],
})
漂亮的 JSON:.to_json()
方法现在有了一个indent=
参数,它将以更易于阅读的方式打印出您的数据。
而不是像这样得到输出的文本转储:
print(df.to_json(orient='records'))[{"some_numbers":5.12,"some_colors":"blue","some_bools":true,"more_numbers":2},{"some_numbers":8.66,"some_colors":"orange","some_bools":true,"more_numbers":5},{"some_numbers":1.09,"some_colors":"maroon","some_bools":false,"more_numbers":8}]
你可以这样美化 JSON:
print(df.to_json(orient='records',indent=2))[
{
"some_numbers":5.12,
"some_colors":"blue",
"some_bools":true,
"more_numbers":2
},
{
"some_numbers":8.66,
"some_colors":"orange",
"some_bools":true,
"more_numbers":5
},
{
"some_numbers":1.09,
"some_colors":"maroon",
"some_bools":false,
"more_numbers":8
}
]
这只是将表格打印到控制台的另一种方式。这产生了一种更容易复制和粘贴到 markdown 文档中的格式。仅供参考,你需要安装tabulate
包才能工作。
print(df.to_markdown())| | some_numbers | some_colors | some_bools | more_numbers |
|---:|-------------:|:------------|:------------|-------------:|
| 0 | 5.12 | blue | True | 2 |
| 1 | 8.66 | orange | True | 5 |
| 2 | 1.09 | maroon | False | 8 |
有趣的事实
您过去可以从 Pandas 包中访问 NumPy 和 datetime 名称空间。像这样:
import pandas as pdx = pd.np.array([1, 2, 3])current_date = pd.datetime.date.today()
但是你不应该这样做。这使得代码变得混乱。自己导入库。
from datetime import date
import numpy as np
import pandas as pdx = np.array([1,2,3])
current_date = date.today()
这种名称空间攻击最终被否决了。点击查看公关讨论。
张量流 2.0
来源:发行说明
(2019 年 9 月 30 日发布)
TensorFlow 是一个深度学习的 Python 包,已经被整个行业广泛采用。它最初是谷歌 DeepMind 的一个内部项目,但在 2015 年 11 月 9 日向公众发布。1.0 版本2017 年 2 月问世。现在我们已经到了 2.0。
TensorFlow 因其可移植性和易于将模型部署到生产级软件中而在工业用例中广受欢迎。但对于研究用例,许多人发现,与 PyTorch 等其他框架相比,它缺乏创建和运行机器学习实验的便利性(阅读更多)。
不管你喜欢还是讨厌 TensorFlow 1。x,以下是你需要知道的。
更多关注热切的执行
在 TensorFlow 1。x 您通常会构建出想要执行的操作的整个控制流,然后通过运行一个会话来一次执行所有的操作。
这不是很 Pythonic 化。Python 用户喜欢能够交互式地运行数据并与数据交互。TensorFlow v1.7 中发布了急切执行,现在在 2.0 中将成为处理计算的主要方式。这里有一个例子。
没有急切的执行。
In[1]: x = tf.constant([[1,0,0],[0,1,0],[0,0,1]], dtype=float)In[2]: print(x)
Out[2]: Tensor("Const:0", shape=(3, 3), dtype=float32)
急切地执行。
In[1]: x = tf.constant([[1,0,0],[0,1,0],[0,0,1]], dtype=float)In[2]: print(x)
Out[2]: Tensor([[1,0,0]
[0,1,0]
[0,0,1]], shape=(3, 3), dtype=float32)
当您可以实际看到您正在处理的数字时,理解和调试正在发生的事情会容易多少?这使得 TensorFlow 与原生 Python 控制流更加兼容,因此更容易创建和理解。(阅读更多)
功能强大,但仍便于携带
行业背景下的 ML 从业者较早采用 TensorFlow 的部分原因是它的可移植性。您可以用 Python 构建逻辑(或执行图),导出它,然后用 C、JavaScript 等无缝运行它。
TensorFlow 听到了人们的呼声,即让接口更加 Python 化,但仍然保持了使用@tf.function
decorator 将代码移植到其他执行环境的便利性。这个装饰器使用 AutoGraph 自动将您的 python 函数翻译成 TensorFlow 执行图。
来自文件:
for
/while
->-[tf.while_loop](https://www.tensorflow.org/api_docs/python/tf/while_loop)
(支持break
、continue
)if
->-for _ in dataset
- >dataset.reduce
# TensorFlow 1.X
outputs = session.run(f(placeholder),
feed_dict={placeholder: input})
# TensorFlow 2.0
outputs = f(input)
Keras 的本地支持
Keras 最初是作为一种更高级别的深度学习 API 开发的,它包装了 TensorFlow、Theano 或 CNTK。从首页:
“它的开发重点是支持快速实验。能够以尽可能少的延迟从想法到结果是做好研究的关键。”
TensorFlow 决定在tf
名称空间内原生支持 Keras API。这为用户提供了模型实验的模块化方法,并解决了“ TensorFlow 不适合研究”的问题。
Keras 仍然作为一个独立的库存在,但建议使用 TensorFlow 后端的用户切换到tf.Keras
。所以现在当人们说他们在用“Keras”时,我不知道它是tf.Keras
还是原来的Keras
…哦,好吧。
API 重构
从 v1 手动升级您的旧代码。x 到 v2。x 并不容易。但是 TensorFlow 开发人员通过创建一个脚本来自动重新排序参数、更改默认参数和切换模块名称空间,从而减少了这种痛苦。
来自指南:
很多 API 在 TF 2.0 中要么没有了,要么移动了。一些主要的变化包括移除
*tf.app*
、*tf.flags*
和*tf.logging*
以支持现在开源的 absl-py,重新组织存在于*tf.contrib*
中的项目,以及通过将较少使用的函数移动到类似*tf.math*
的子包中来清理主*tf.**
名称空间。一些 API 已经被替换为它们的 2.0 等效版本-*tf.summary*
、*tf.keras.metrics*
和*tf.keras.optimizers*
。自动应用这些重命名的最简单方法是使用 v2 升级脚本。
结论
Pandas 反对在其名称空间中使用 NumPy 和 datetime,并建议用户直接导入它们。但是 TensorFlow 建议使用 Tensorflow 内部的 Keras,而不是直接导入它。🤷♂️
我希望你觉得这很有用。如果有你认为应该包含的大功能,请告诉我。
感谢阅读!
挑战问题的答案:
In[12]: ((True | pd.NA) & True) | (False & (pd.NA | False))
Out[12]: True
熊猫 1.0 有什么新功能?🐼
你需要知道的比普通熊聪明的一切
熊猫开发团队刚刚在 2020 年 1 月 29 日正式发布了熊猫 1.0.0 版本。在本文中,我将回答您的迫切问题,讨论主要的变化,并向您展示如何从今天开始使用新版本。😀
请注意,这篇文章已经更新,以反映官方发布。🎉
普通的熊
熊猫
Pandas 是最流行的用于清理、探索和操作数据的 Python 库。它将命名的行和列添加到 NumPy 的 ndarray 数据结构中。它还增加了许多方便的方法,使处理数据变得更加容易。Pandas 是 Python 成为数据科学家和数据工程师主导语言的重要原因。
我们走吧!🚀
我们说的是 1.0。这是一件有很多重大变化的大事吗?
不完全是。1.0 的标签并不意味着与 0.25.3 有很大的不同,0 . 25 . 3 是截至 2020 年 1 月 22 日(本文最初撰写时)的稳定版本。你会看到,没有那么多大的变化。
1.0 版本也并不意味着这种语言已经达到了一个成熟点。Pandas 是一个相当稳定的库,已经在生产代码中使用了多年。韦斯·麦金尼从 2008 年开始在图书馆工作。 GitHub 显示在撰写本文时,它已经在大约 170,000 个 GitHub 仓库中使用。👍
1.0 中的变化可能会在短期内引入更多的复杂性,但从长远来看,它们为语言打下了更好的基础。
良好的基础是一份礼物
有什么新鲜事?
除了通常的错误修复和小的 API 清理,熊猫 1.0.0 引入了一些主要功能。
警察。钠
在 pandas 0.25 中,一个数据帧可以有三个不同的值——T0、T1 或 T2——来表示缺失的数据,这取决于列的数据类型。如果你想知道细节,请看我的关于熊猫中丢失数据值的文章。
许多人面临的缺失值的最大问题是,一个缺失值的整数列会自动转换为 float。呀。🙀
这种现状很大程度上是由于底层 NumPy 库的能力。为了改善这种情况,pandas 开发团队创建了一个新值来表示几个 dtypes 的缺失数据。如 1.0 文档所述:
从 pandas 1.0 开始,可以使用一个实验性的
pd.NA
值(singleton)来表示标量缺失值。此时,它被用于可空的整数,布尔和专用字符串数据类型中作为缺失值指示器。
pd.NA
的目标是【提供】一个“缺失”指示器,可以在所有数据类型中一致使用(而不是根据数据类型使用np.nan
、None
或pd.NaT
)。
从长远来看,缺失数据的单个值和避免将缺失数据的整数列自动转换为浮点数听起来很棒!👏从短期来看,它创造了更多需要学习和记忆的东西。
新的pd.NA
的一个问题是,你不能直接将其与布尔条件中的值进行比较。所以没有带pd.NA
的==
。相反,您可以使用df.isna()
返回数据帧中缺失值的布尔掩码。
我们来看看能装pd.NA
的三种 dtypes。
可空整数数据类型
如果您想使用新的pd.NA
并避免将 int 类型转换为 float,现在您必须指定特殊的可空整数 dtypeInt64
——注意大写的 I 。这个 dtype 和你所了解和喜爱的标准int64
NumPy dtype 不一样。❤️
下面是用整数 dtype 列创建数据帧的老方法(熊猫和 NumPy 以它们通常的别名导入):
pd.DataFrame([1, 2, np.nan])
这导致了:
请注意,自动类型转换为浮点型。
下面是创建可以处理pd.NA
的列的方法。
pd.DataFrame([1, 2, np.nan], dtype="Int64")
只需在创建系列或数据帧时指定dtype=”Int64"
,就可以得到可空的整数数据类型。请注意不同之处:
该列仍有整数!还有新的 *<娜>。*👍
关于int64
和Int64
的微妙之处 pandas 版本只有一个大写的 I 而现有 NumPy 版本只有一个小写的 i 看起来可能会引起一些混乱。☹️
迷茫?
布尔数据类型
如果引入了缺失值,一个bool
dtype 列将被转换为一个object
dtype。如果想要一个缺少pd.NA
值的布尔整数列,那么用 dtypeboolean
指定该列。
你可以这样做:
pd.DataFrame([True, False, np.nan], dtype=”boolean”)
同样,这很酷,但是boolean
dtype 似乎很可能与现有的bool
dtype 混淆。
让我们看看新的string
数据类型。
新字符串
字符串数据类型
一种新的、更直观的文本数据类型对我来说是个好主意,至少乍一看是这样。object
dtype 是文本数据和任何不属于另一个类别的杂项数据的默认集合。
string
dtype 使用pd.NA
来表示缺失值,节省内存,并告知您只需要一列中的文本值。现在,你需要指定你想要它。你可以这样做:
pd.DataFrame(['a', 'b'], dtype='string')
这些变化的短期负面影响是,缺失值和数据类型现在有了更多的细微差别。☹️
为了使转换更容易一些,现在有了一个 pandas DataFrame 方法convert_dtypes()
。
转换类型
在数据帧或系列上调用convert_dtypes()
,pandas 将尝试将每一列转换成支持pd.NA
的 dtype。(这些是上面讨论的新数据类型)。在新奇的新文件中了解更多信息!
感谢凯文·马卡姆给我指出了这个方法。
因此,尽管可能有更多的细微差别需要学习,但新数据类型的好处是 pandas 在更直观地处理整个 API 中的缺失值方面迈出了一大步。对我来说,这似乎是一种必要的成长的痛苦。😀
其他值得注意的变化
- 这些文档有一个漂亮的新外观和一个关于扩展到大数据集的新部分。
- 熊猫团队将开始使用语义版本化的松散变体来管理弃用、API 兼容性和版本编号。
- 您可以使用
to_markdown()
将数据帧输出为降价表。 - 像
df.info()
这样的函数的输出现在组织得更好了。 pandas.util.testing
模块已被弃用。我喜欢它,因为它可以快速制作各种数据类型的数据框架。然而,您可以通过其他几种方式创建这样的数据帧,但它似乎没有得到广泛使用。从好的方面来说,这是一个少学的东西,我可以把它从我即将出版的熊猫书里删掉。📘- 熊猫 1.0.0 支持 Python 3.6.1 及以上版本。😉
变化
我如何安装新版本?(截至 2020 年 1 月 29 日更新)
点
以下是如何用 pip 安装熊猫 1.0:
pip install pandas
就是这样!😀建议你用 Python 内置的 venv 创建一个虚拟环境。因此,要使用 Python 3.8 创建虚拟环境,您需要:
python3.8 -m venv my_env
source my_env/bin/activate
如果您已经安装了 pandas,您可以通过以下方式升级到 1.0:
pip install pandas --upgrade
康达
以下是如何用 Python 3.8 和 pandas 1.0 创建一个新的 conda 环境:
conda create -n my_conda_env pandas
或者你可以更新你当前活动的 conda 环境,如果它有熊猫的话
conda update pandas
向那些一直致力于改善熊猫的人们大声呼喊!谢谢大家!🎉
建议
熊猫 1.0 来了。现在正是开始使用的好时机!👍
如果你一直在关注最近的熊猫发布,并对那些弹出的警告做了些什么,更新到 1.0 应该不会太难。然而,你在以前版本的 pandas 中看到的许多警告现在会出错,所以要小心。😀
如果你想学习熊猫,我已经起草了一本关于熊猫的书。订阅我的邮件列表,确保你不会错过发布。
如果你还不知道香草 Python,先看看我的书,难忘的 Python 。
如果你想要一份关于 conda 命令的便签,我为你我制作了这个要点。😀
包装
希望你觉得这个熊猫 1.0 的指南有用。如果你有,请在你最喜欢的社交媒体上分享,这样其他人也可以找到它。👍
我撰写关于数据科学、 Docker 、 SQL 和其他技术主题的文章。如果你对此感兴趣,请关注 me ,点击阅读更多。
熊猫快乐!🐼
Python 2020 的新特性—第 1 部分
Python 过去(3.7)、现在(3.8)、未来(3.9)的幽灵正在 2020 年拜访你。
克里斯里德在 Unsplash 上的照片
自从很久以前切换到 Python 3(咳咳 —我希望那是很久以前的事了!),语言层面的特性变化相对较小。然而,在每个版本中,从事 Python 工作的天才们都在不断添加我不能缺少的东西。
随着 Python 3.8 于 2019 年 10 月发布,我发现自己在使用该语言的一些功能,当我第一次读到它们时,让我说“随便吧”。
- 3.5-类型注释
- 3.6 — asyncio
- 3.7 —数据类
- 3.8 —赋值表达式又名海象运算符
在 3.9 中,字典联合操作符和泛型类型提示。尽量减少感叹号,但这是令人兴奋的事情!
以上所述,我一直在专业地使用代码库,并在我的项目中寻找乐趣。
快速演讲:如果您还在使用旧版本的 Python 工作或项目,不要害怕升级!您的旧代码仍然可以工作,而且您将获得 Python 新特性的好处!
声明:如果你还在使用 Python 2.7,这是不正确的。但在这种情况下,你不是那种会接受好建议的人。😎
下面我将(快速)回顾一些我最喜欢的特性,希望你会发现它们每天都在你的编码中使用。
它们是:类型注释、数据类、字典联合操作符、walrus 操作符。
在这一部分:输入注释,walrus 操作符。
打字— 3.5 以上
从 Python 3 开始,打字就已经成为一项功能。因为我们是开发者,而不是历史学家,所以现在(2020 年)将会有类型注释和类型提示。
Python 不需要给变量赋值类型。这可能是我如此热爱这门语言的部分原因。清晰易读的语法。用 24 种不同的方法中的一种来编码解决方案并仍然得到相同结果的能力。
但是后来…应用程序增长了。或者你得看看你几个月或几年没碰过的代码。或者,最糟糕的是,你还得理解别人写的代码!战栗
然后你意识到输入变量对解释器没有好处。这是给你的。
键入有助于您在编写代码时以及以后理解代码。TypeScript 如此受欢迎是有原因的,即使 JavaScript 完全能够编译成没有类型的工作代码。
from typing import List
def print_cats(cats: List[str]) -> None:
for cat in cats:
print(f"{cat} has a name with {len(cat)} letters.")
class Cat(object):
def __init__(self, name: str, age: int, **attrs):
self.cattributes = {
"name": name,
"age": age,
**attrs
}
cats = "this still works w/o type annotation!"
cats: List[str] = ["Meowie", "Fluffy", "Deathspawn"]
# not a list of strings, but Python will not check
cats2: List[str] = [Cat("Meowie", 2), Cat("Deathspawn", 8)]
print_cats(cats) # succeeds
print_cats(cats2) # fails
这将返回:
Meowie has a name with 6 letters.
Fluffy has a name with 6 letters.
Deathspawn has a name with 10 letters.
--------------------------------------------
...
TypeError: object of type 'Cat' has no len()
在这里,类型注释并没有拯救我们,那么为什么要使用它们呢?因为当创建变量cats
并用List[str]
键入它时,显而易见,分配的数据应该与该结构匹配。所以当一个函数稍后消耗cats
时,它变得(更加)明显,你传递的数据正是它所期望的。
我认为,对于具有复杂类型的可维护代码来说,这变得更加有用——必要。
from typing import List
class Cat(object):
def __init__(self, name: str, age: int, **attrs):
self.cattributes = {
"name": name,
"age": age,
**attrs
}
# creating a type variable
Cats: type = List[Cat]
def print_cats(cats: Cats) -> None:
for cat in cats:
name: str = cat.cattributes.get("name")
print(f"{name} has a name with {len(name)} letters.")
cats = [Cat("Meowie", 2), Cat("Deathspawn", 8)]
print_cats(cats)
输出:
Meowie has a name with 6 letters.
Deathspawn has a name with 10 letters.
在函数/方法的定义中输入参数被称为类型提示。类型甚至不必是 Python 数据类型或来自typing
模块。一个简单的,虽然有点尴尬的文本提示是完全合法的:
import pandas as pd
cols = ["name", "age", "gender"]
data = [["Meowie", 2, "female"],
["Fluffy", 5, "male"],
["Deathspawn", 8, "rather not say"]]
df: pd.DataFrame = pd.DataFrame() # not very descriptive
df: "name (string), age (integer), gender (string)" = \
pd.DataFrame(data, columns=cols)
类似这样的东西在包含大量复杂类型变量的数据处理管道中可能会很有用,并且您的脑袋开始发晕,试图让它们保持直线。在变量 mouseover 上有类型提示的 ide 也会显示那个提示,而不是pandas.DataFrame
,如果它有 Python 支持的话。
**奖励:**在 Python 4 中,前向引用将被允许开箱即用。这意味着您可以注释尚未定义的类型。我们现在仍然可以通过将from __future__ import annotations
放在文件的顶部来利用这一优点,然后做如下事情:
from __future__ import annotations
class Food:
""" Look at the type hint. Food is legal even without the
class defined yet.
"""
def __init__(self, ingred_1: Food, ingred_2: Food) -> None:
self.ingred_1 = ingred_1
self.ingred_2 = ingred_2
原生类型注释— 3.9(很快将成为我的最爱)
这将是真正的快速,因为我把打字部分拖了出来。
内置的泛型类型将是 3.9 中的东西,所以从typing
导入来添加参数到泛型数据类型将不再是必要的。从 3.7 开始,from __futures__ import annotations
就提供了这一功能,但这是因为它阻止了类型引用在运行时被求值。
这让我对从 3.8 升级感到兴奋。现在我将typing
导入到每个模块中,或者从我保存在代码旁边的类型定义模块中导入。
示例(信用: PEP 585 ):
>>> l = list[str]()
[]
>>> list is list[str]
False
>>> list == list[str]
False
>>> list[str] == list[str]
True
>>> list[str] == list[int]
False
>>> isinstance([1, 2, 3], list[str])
TypeError: isinstance() arg 2 cannot be a parameterized generic
>>> issubclass(list, list[str])
TypeError: issubclass() arg 2 cannot be a parameterized generic
>>> isinstance(list[str], types.GenericAlias)
Truedef find(haystack: dict[str, list[int]]) -> int:
...
海象运营商——3.8(我的最爱)
海象有眼睛:
然后是长牙=
。
:=
是一个赋值表达式,在 Python 3.8 中新增。
complicated = {
"data": {
"list": [1,2,3],
"other": "stuff"
}
}
if (nums := complicated.get('data').get('list')):
print(nums)
结果:
1
2
3
如果没有海象,这将是更多的代码行。
...
nums = complicated.get('data').get('list')
if nums:
print(nums)
这不是世界末日,但是因为控制流语句在编程中经常被使用,一旦你开始使用 walrus 操作符,你就不会停止。
来自 PEP 572 :
这种命名表达式的值与合并表达式的值是相同的,但有一个额外的副作用,即目标被赋予该值
换句话说,用一个表达式杀死两个语句。
当我复制/粘贴 PEP 指南时,这里有几个我认为很好的例子。迫不及待地想在列表理解中尝试一下 walrus 运算符。
# Handle a matched regex
if (match := pattern.search(data)) is not None:
# Do something with match
# A loop that can't be trivially rewritten using 2-arg iter()
while chunk := file.read(8192):
process(chunk)
# Reuse a value that's expensive to compute
[y := f(x), y**2, y**3]
# Share a subexpression between a comprehension filter clause and its output
filtered_data = [y for x in data if (y := f(x)) is not None]
结论
最近对 Python 语言的补充提供了一些相当不错的特性供练习。我希望我对打字和海象操作符的看法对你有用。
在第 2 部分中,我们将看看内置库的数据类,同时也看看需要考虑的一些原因pydantic
。我们还将介绍 dictionary union 操作符,这是 Python 3.9 语法中的一项新内容。