TowardsDataScience 2023 博客中文翻译(一百四十二)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

从见面会到辅导:如何作为数据科学家进行网络交流

原文:towardsdatascience.com/from-meetups-to-mentoring-how-to-network-as-a-data-scientist-ecab8a95ab35

有志、初级和资深数据科学家的五条建议

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Eirik Berge, PhD

·发表于 Towards Data Science ·15 分钟阅读·2023 年 8 月 3 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源于 NikUnsplash

概述

  1. 介绍

  2. 有志数据科学家的建议

  3. 初级数据科学家的建议

  4. 资深数据科学家的建议

  5. 总结

介绍

网络交流。我们经常听到类似 “我听说网络交流很有用,为什么不试试呢?” 这样的短语。这些鼓励是出于好意,但效果不大。大多数人都明白网络交流的价值。许多数据科学家不是通过正式的招聘信息而是通过推荐和人脉获得职位的。

理解如何有效地进行网络交流可能很棘手。一些建议已经过时,有些不适用于数据科学家,有些则完全错误。回顾你职业生涯中的前一步,理解什么实际上有效会更容易。这是因为你可以看到你周围成功人士的共同点 ✨

在这篇博客文章中,我想给你一些关于如何作为数据科学家进行网络交流的建议。下面我将这些建议分为有志数据科学家初级数据科学家资深数据科学家的类别。我自己是资深数据科学家,因此对这些步骤有经验。我还与许多专业招聘人员交谈过,也曾在数据科学家的招聘面试中参与过。尽管如此,请将我说的所有内容都看作参考。我在这个话题上并没有比其他人更具权威,这些只是我自己的思考。

在我们开始之前,你应该知道,我认为将网络视为优化问题是根本错误的。拥有 1000 个 LinkedIn 联系人或 5000 个关于 LLMs 的帖子点赞并不是目标。网络的真正目标是建立与你志同道合的其他人之间的真实连接。这些连接会为你提供一个你可以帮助和在需要时联系的网络。

矛盾的是,将网络视为一个优化问题会使你在网络中表现不佳。这会让你关注指标而非人际关系。遇到一个仅仅为了“炫耀”而与你交谈的人是令人厌恶的。这种方法也会造成心理上的伤害。你开始把人们视为实现某些任意指标的工具。这既不有趣也不有效 😔

因此,在阅读以下提示时,不要忘记网络连接本质上是关于人的。我敢肯定,这听起来可能有点老生常谈。但它也可以令人意外地平静。你不需要在网络中表现得像销售员。你不需要穿西装、对新认识的人做出手指枪的姿势。你对数据科学的热情已经足够了。

对未来数据科学家的建议

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Tim Bogdanov 提供,来自 Unsplash

我很高兴你对追求数据科学职业感兴趣。我假设你目前还不是数据科学家,但希望未来成为。你可能在大学或类似的机构学习。在你职业生涯的这个阶段,我建议你关注以下五个网络建议:

提示 1:参加相关课程以结识志同道合的人

我相信考古学或环境法课程很有趣。然而,如果你想成为一名数据科学家,你可能不会在这些课程中遇到很多未来的同事。如果你参加数据科学、统计学或信息学课程,那么遇到未来同事的机会就会大大增加。参加相关课程的主要原因当然是获得知识,但也不要低估建立坚实网络的价值。

在参加相关课程时,尽量与不同的人交谈,了解他们一点。即使你不想过于社交,也不必过于担心,但一点点努力会大有成效。与每门相关课程中的 5-10 个人建立联系,很快就会积累起来。

提示 2:如果可能的话,申请一个(有薪的!)相关的暑期工作

如果你能够找到一个数据科学家的暑期工作,那么这对获得人脉极其有用。有些人利用这个机会进入公司,并在完成学业后常常能在公司获得工作。即使你没有这样做,拥有以前的数据科学专业经验在任何简历上都是一个很大的加分项。

在网络建设方面,做一个暑期工作会让你接触到导师和同事,你可以与他们建立联系。人们会拥有真实的数据科学知识,这通常与学术版的有所不同。在这里建立网络对你未来的职业生涯至关重要。

在暑期工作中,尽量了解你所在的圈子之外的人。与设计师一起吃午餐,与产品负责人闲聊。暑期工作意味着大多数人会非常愿意接受你的提问和交流。这使得网络建设变得容易多了 😃

提示 3: 参加职业日活动并与代表交谈

大学通常会组织职业日活动,企业会来做演讲。这是一个与公司代表交流并了解他们的绝佳机会。你甚至可能会找到一些免费食物,这对学生来说总是个额外的好处。

我知道从经验中参加职业日活动会有些尴尬。它半正式但又放松。不要担心。公司的代表们通常也会有相似的感觉。在参加职业日活动时,确保充分利用这个机会。

提示 4: 参加指导计划

大学通常有指导/校友计划。学生可以通过这些计划与行业内的专业人士联系,以了解职业的日常工作。这是一个很好的机会,通常是免费的,会让你接触到在职的专业人士。

导师可以给你提供技术方面的建议,还能指导你如何/何时申请职位或哪些职位比较好。像这样的专业人士通常因为热爱自己的职业而担任导师,并且对这个领域了如指掌。如果你决定参与这样的项目,请确保做好准备。准备好你想要问的问题,并且尊重导师的时间 🙏

不要害怕与导师保持联系。导师通常喜欢听到你进展的情况,如果你有疑问,他们可以提供更多建议。在你的职业生涯后期,如果你愿意,可以“回馈”并成为别人的导师。

提示 5: 至少保持最基本的在线存在

你应该注册你所在国家最常用的数据科学在线网络工具。对大多数人来说,这将是 LinkedIn,所以我接下来只会提到 LinkedIn。从与招聘人员的交谈中,我知道完全没有 LinkedIn 个人资料会被看作有些不受欢迎。虽然我个人不一定认同,但这几乎无关紧要。

添加你通过课程、聚会和暑期工作认识的人到 LinkedIn 上。这是一种便捷的保持联系的方式。你还可以利用 LinkedIn 在找工作时做宣传。我许多朋友就是这样找到工作的。

记住,你不需要在网上发布任何让你不舒服的内容。事实上,我真的认为你在职业生涯的这个阶段并不需要发布任何内容。只需创建一个账户,添加相关信息,并与遇到的人保持联系。就是这么简单!

初级数据科学家的建议

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片来自Microsoft EdgeUnsplash

我看到你是一名初级数据科学家。恭喜你!这是一个令人兴奋的领域,我很高兴你加入了我们。你在技术方面有很多要学习,但关注网络建设也是有益的。在你职业生涯的这个阶段,我建议你专注于以下五个网络建设的技巧:

技巧 1:与同事培养良好关系

这一点几乎太明显了。你很可能会在职业生涯中与其他数据科学家、数据工程师、数据分析师和机器学习工程师合作。确保你与他们保持良好的关系并建立联系。尽管可以谈论数据科学和相关学科,但也不要回避谈论其他话题。通常,了解一些关于他们个人的简单信息会使建立关系变得更容易。

我建议你也去认识其他部门的人。当你换工作时,你可能会发现之前沟通过的人现在也在那儿工作。即使他们可能不能对你的数据科学技能做太多评价,他们也可以根据你的性格给出推荐。与不同领域的人交流也是一种很好的避免完全隔绝的方式。我认识的一些最优秀的数据科学家对邻近领域的知识了解甚少。

如果你在远程工作,这将会困难得多。我自己也有远程工作的经验,所以我并不是在一般情况下反对远程工作。我只是想对你选择这种职位时的现实情况保持诚实。如果你选择了远程职位,那么你可以把更多的精力投入到接下来的建议中💪

技巧 2:参加聚会、研讨会和会议

在你的工作之外,会有机会认识其他数据科学家。这通常以聚会、研讨会和会议的形式出现。这些活动偶尔参加一下是很好的,有助于建立网络。如果活动质量高,你可能还会学到很多东西。虽然聚会和研讨会通常是免费的,但会议通常需要相当昂贵的费用。你可以要求公司承担这些费用

我建议你只有在真正感兴趣的情况下才参加这些活动。如果你对前端开发不感兴趣,去参加 React 研讨会是没有意义的。找到真正让你感兴趣的东西——否则,你只会感到疲惫

最后,如果你发现了一个你喜欢的聚会,并且参加了几次,不要害怕主动申请演讲。组织聚会的人常常会为找到演讲者而苦恼。你不需要是高级数据科学家才能做出精彩的演讲。实际上,我见过的一些最好的演讲来自经验较少的人。

提示 3:不要害怕指导他人

你可能认为自己还没有达到可以指导他人的水平。但这并不真实。即使只有 6 个月的工作经验的人,也可以在某些方面指导新毕业生。回想一下你开始工作时的情况。有什么是你当时希望知道的?也许是像某些信息的位置这样平凡的事情。或者在组织中数据科学的部署是如何运作的?这现在对你来说可能很简单,但一开始可能很有挑战。

通过指导他人,你会与他们建立联系。他们可以向你提出问题,而你将尽力协助他们。许多新员工认为他们的导师(前提是导师确实在做这份工作)是他们最了解的人,这并不令人惊讶。所以尽快问问你的经理是否可以成为新员工的导师 🔥

提示 4:撰写博客或教授技术课程

你现在处于一个可以教导他人的位置。虽然上面提到的指导是一种非常个性化的方式,但也不要害怕通过博客或课程来实现。如果你撰写了一篇关于缺乏良好文档的技术库的博客文章,那么许多人会感激你。只需确保选择一个你熟悉的主题即可。

我的建议是从小处做起。你公司里的人是否抱怨新毕业生不知道像 Git 这样的版本控制软件?提供一个 1 小时的课程。你的同事们是否抱怨在数据处理时难以理解何时使用 Pandas、Polars 还是 Spark?为此创建一个博客文章,花时间调查这些差异。这既可以是有价值的,又是很好的实践。

提示 5:提升你的在线形象

我认为在你职业生涯的这个阶段,提升一下你的在线形象是有益的。不必担心,你不需要成为一个有观点的数据科学家影响者。但投入更多精力到你的个人资料和互动中可能是件好事。

对于你的个人资料,添加更详细的职位描述、技能、证书等。如果你想成为一名高级数据科学家,那么模仿这样的个人资料。清晰的图像和一个吸引人且专业的自我介绍部分。写这部分内容不应该花费你很多时间,但许多招聘人员对此非常看重。你可以做得比用猫的照片作为个人头像和一段“我做那数据 stuff”的描述要好。

如果你想发布内容,可以发布关于有趣的技术、有趣的讲座或博客,或者任何真正让你感兴趣的东西。你不需要发布有关数据科学的当前炒作趋势的帖子,也不需要发布类似“SQL 已死!”的标题点击诱饵帖子。它并没有死,希望你现在已经知道这一点 😅

高级数据科学家的提示

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 bruce mars 提供,来源于 Unsplash

祝贺你成为高级数据科学家!我相信你为此付出了很多努力。这一职位的变化也大大改变了你的网络联系方式。简而言之,主要的变化是你需要以各种方式“展示自己”。在这个职业阶段,我建议你关注以下五个网络联系的提示:

提示 1:在会议、聚会、网络研讨会、研讨会等场合进行演讲。

在职业生涯的早期阶段,你主要是参加活动。虽然这仍然是一个有价值的网络联系方式,但它相较于演讲黯然失色。在各种场合演讲时,你间接展示了你的知识。如果你表现良好,人们会主动找上你。这会反转你的网络效应——你现在拥有了吸引力。只需知道,良好的演讲需要大量时间:

  • 首先,对于大多数人来说,成为一个优秀的演讲者需要多年时间。尽早开始。职业生涯越早,人们对表现平庸的演讲接受度越高。作为初级数据科学家,即使你的演讲技巧需要改进,人们也会对你的投入印象深刻。在职业生涯的某个阶段,演讲表现糟糕会受到更多的轻视。

  • 其次,即使你已经很擅长演讲,准备演讲仍然需要大量的工作。因此,你应该仔细选择何时在活动中演讲。比起每年演讲 50 次表现平庸,每年演讲 5 次表现出色要更好。优先考虑质量而非数量

提示 2:提高你的写作能力

你会发现你的工作中有很多写作。不论是文档、备忘录、说明、演示、总结、观点、博客文章、电子邮件,还是完全不同的东西,这并不重要。重点是写作已经成为你日常的一部分。你突然被期望能做到这一点。

事实上,你会因写作被评判。因此,这可能会严重影响在高级别的网络联系。对于某些人来说,仅凭写作来评判别人似乎非常肤浅。但写作往往是接收者能评判或理解的唯一输出。大多数利益相关者无法理解你的巧妙超参数搜索或复杂的数据管道。如果你不能用简单的术语解释一个项目为何应该继续,那么当它被取消时不要感到惊讶 😲

清晰的书面沟通在建立网络时变得越来越重要。你会通过聊天、电子邮件和类似的接口与许多人交流。如果你写得不好,这可能会影响你给人的印象。

对许多人来说,英语不是我们的母语。因此,我们通常需要用两种(或更多!)语言进行清晰沟通。这听起来很令人生畏。幸运的是,清晰的写作在很大程度上是语言无关的。开始在你建立网络时最常用的语言上进行练习。你会很快发现你其他语言的清晰度也会同步提升

提示 3:构建有价值的东西

你可以通过建立有价值的东西来证明自己的技能。无论这是一个实现了新机器学习算法的 Python 库,还是一个展示了酷炫用例的 GitHub 仓库,都完全取决于你。这也可以是你组织中的一个内部工具。

我想强调的是,构建具有很高原创性的东西并不是总是必要的。也许你的组织使用了不佳的数据管道编排流程。承担责任并解决这一问题带来价值,即便这是在其他组织中已经做过 1000 次的事情。尝试创建一些真正能够帮助他人的东西。

如果你制作内部工具,这将赢得你在组织中他人的尊重。如果你制作开源工具,这将帮助更广泛的受众。这两种选择都是建立网络的好方法。如果人们已经对你有了良好的印象,那么建立网络会变得简单很多

提示 4:成为某一领域的专家

当你刚开始成为数据科学家时,你会想要了解各种各样的知识。这包括从自然语言处理到云平台。作为一名高级数据科学家,你应该对广泛的主题有一定了解。但你也应该成为某一领域的专家。这可以是像异常检测这样的技术领域,也可以是更侧重软技能的内容,比如如何成功地在数据科学中实施敏捷方法。

通过成为专家,你会因为你的专业知识而受到追捧。这为建立网络打开了许多大门,因为你将被邀请讲述和撰写关于你的专业知识的内容。选择一个专业话题可能很困难。我最好的建议是深入研究你真正关心的领域。如果这个话题在广泛的环境中适用,这也是一个加分项。

在建立网络时,你可以利用你的专业知识来脱颖而出。几乎每个数据科学家都对深度学习有一定了解。但你认识的有多少数据科学家是集成方法的专家?或者是将长期组织战略与数据项目结合的专家?这确实很突出 😍

提示 5:建立强大的在线存在感

作为一名高级数据科学家,你应该力求拥有强大的在线存在感。这包括更多地与他人互动,花更多时间展示你的想法和观点。实现这一点的方式有很多种,你可以自己决定。格式可以是 LinkedIn 帖子、视频教程等。专注于制作高质量的内容,真正吸引和阐明话题。再次提醒,质量胜于数量。

人们常常谈论建立你自己的品牌。这个词有点负担,我更喜欢谈论发展你自己的声音。当你写作和讲话时,你需要做出一些选择。你会采用友好和帮助的语气,还是更权威的语气?语气的选择应该与你想要达成的目标相匹配:

  • 假设你想为你开始领导的团队招聘更多初级数据科学家。那么,在线上使用“滚出我的草坪”那种反应性语气可能不是一个好主意。

  • 假设你想说服世界 Rust 是数据科学的未来。那么,采用友好和可接受的语气可能也不合适。你绝不要选择攻击性的语气,但有时略带一些被压抑的消极攻击性可能会令人感到有趣😤

总结

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由Spencer Bergen提供,来源于Unsplash

在这篇博客文章中,我给出了在数据科学家各个阶段的网络交流技巧。我不希望你把这些当作圣经,而是作为你可以工作的参考点。

如果你对数据科学感兴趣,欢迎在LinkedIn上关注我。不过,为了让这次连接更有意义,请在网络交流时告诉我你的个人看法。我很想听听你的观点😃

喜欢我的写作? 查看我的其他文章,获取更多内容:

  • 数据科学家成功所需的软技能

  • 作为数据科学家如何编写高质量的 Python 代码

  • 用优雅的类型提示现代化你的罪恶 Python 代码

  • 在 Python 中可视化缺失值是惊人的简单

  • 在 Python 中使用 PyOD 介绍异常/离群值检测 🔥

从数据到行动:让数据为公司服务

原文:towardsdatascience.com/from-numbers-to-actions-making-data-work-for-companies-162183c13998

什么数据是失败的,什么数据是有效的?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Michal Szudejko

·发表于 Towards Data Science ·阅读时间 14 分钟·2023 年 8 月 14 日

如今,组织和个人都被数据淹没了。 每天全球产生 329 万亿字节的数据,每年积累达到惊人的 120 泽字节 [1]。

但这在具体的术语中是什么意思呢?考虑一下存储空间为 128GB 的 iPhone。让我们想象一下,如果每天的数据等于三十亿部 iPhone 的容量*。听起来很令人印象深刻?让我们深入探讨一下。这个每日数据量换算成年数据量的话,就是理论上有 1.08 万亿部 iPhone 被数据充斥。鉴于当前全球人口约为 78 亿,这意味着每个人需要拥有近 139 部 iPhone [2]。荒谬,对吧?

数据的巨大体量令人震惊,但增长速度同样惊人。就在 13 年前,也就是 2010 年,年度数据创作量还只是相对温和的两泽字节……

这只是冰山一角。想想那些没有在线的数据——直接存储在我们设备上的文件,或是纸上写的笔记和文档(是的,这种方式还在存在!)。估算一下这些数据的体积?

我甚至不敢猜测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

没有 iPhone 能够处理这些数据。来源:作者提供的图片,由 DALL-E 2 生成

所以,外面有大量的数据。

但这对企业来说意味着什么?

我最近审查了最新的数据和人工智能领导力执行调查 [3]。结果显示,97%的公司已经投资于数据及相关基础设施。92%投入了大数据和人工智能。你可能会认为这意味着他们正在看到这些投资的回报。实际上,并非如此。只有 40%的受访者表示他们将数据视为“产生收入”的资产。

只有 27%的公司认为自己是以数据驱动的组织。

什么?为什么?

主要问题有两个方面。虽然一些问题来源于技术,但**高达 92%**的问题源于人为因素,如组织文化、人员和流程。即使是技术问题,通常也归结为人为错误。

这可能会让一些人感到惊讶。我曾经看到一个声明错误地说“决策驱动的数据”而不是“数据驱动的决策”。这是一个简单的打字错误吗?也许。弗洛伊德可能对此有一两个理论,我很乐意参与讨论。 虽然这看起来像是一个失误,但我的研究表明情况并非如此。我越深入探究,发现越多的理由解释这种奇特的对比。

在一篇简短的文章中,无法涵盖每一个细节,但我已经突出了几个要点,以向亲爱的读者展示复杂性。

数据沼泽

从一个常见的误区开始:许多人认为问题出在数据、分析或工具上,而不是人。

随着时间的推移,数据供应机制已经发生了变化。第一代系统,数据仓库,将数据从操作系统转移到商业智能平台,简化了查询,但处理复杂流程和多样数据时存在困难。第二代系统,数据湖,以原始形式保存数据,便利了机器学习,但也带来了数据质量问题和来源映射问题等挑战。第三代系统,基于云的数据湖,在云中融合了前两代系统的特点,提供了实时数据访问,但依然复杂,并且在将数据转化为见解时可能较慢。第四代系统,数据网格,是一种去中心化的数据架构和组织结构,推动了分布式数据产品的领域导向所有权[4]。

然而,企业往往从数据仓库、数据湖或数据网格开始,但最终却陷入同样的困境:数据沼泽。可以把它看作是一个杂乱的数据储藏室。

如果没有明确的指南,数据可能会变得无序和混乱,就像没有规则的游戏或一个充满未标记箱子的衣橱一样。公司经常存储未经检查的数据,使得其有用性和准确性受到质疑。没有策略地上传数据进一步加剧了混乱,就像随意把衣服扔进衣橱一样。而且,如果不定期维护,数据湖就像被忽视的花园一样,会变成沼泽。

简而言之,要拥有一个有用的数据湖,你需要将其组织得井井有条,就像保持房间的整洁一样。如果不这样做,很容易陷入…

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据沼泽:小心鳄鱼。图像由作者在 DALL-E 2 中生成。

我的见解在哪里?

让我分享一个我在公司生活中的经历。在一次例行的月度财务审查中,我发现了一个显著的差异,比如说是一百万美元。当我向一位分析师询问差异时,我收到的分解是:

  • 10 万美元:具体原因

  • 5 万美元:另一个原因

  • 剩余的金额?简单标记为‘各种’。

我的脸色一定变得苍白,尤其是因为我有一个即将召开的会议要与管理委员会讨论这些差异。我措手不及,没什么实质性的内容可以呈现。

这突显了数据洞见中的一个常见问题:它们往往停留在表面,通常只是陈述已经显而易见的内容。 我们可以轻松地使用像 ChatGPT 这样的工具来获取这种表面层次的信息。然而,尽管像 LLMs 这样的先进模型很强大,我们仍然期望人类对数据进行深入分析和解读。我们希望他们得出有意义的结论,并将其转化为可操作的步骤。这些洞见应该提供价值并建议具体行动,而不仅仅是传达那些人们自己很容易找到的信息。

鱼从头部开始腐烂

Brent Dykes 在 LinkedIn 的帖子中引用了丰臣秀吉及其 1592-1598 年失败的朝鲜入侵的故事。

这位领导因其残酷的本性而臭名昭著。带给他坏消息可能会导致信使的死亡。因此,他的将领们犹豫不决,不敢告知他战役的真实状态,这远未成功。他们表现得如此出色,以至于秀吉在他最后的呼吸之前仍然幻想着成功。一旦他去世,日本迅速撤回了这次征服。

这个故事突显了基于坚实数据的客观洞见与某些管理方法之间的冲突。在这种情况下,驱动因素是恐惧。这并非唯一的可能情境。考虑在会议上提出一个让部分与会者不安的见解。即使信息根植于硬事实,大多数人(根据我的观察)仍会捍卫自己的立场。这突显了将我们的分析基于客观和经过验证的数据的重要性。此外,如果存在潜在的不适感,与可能感到被针对的人对齐,确保观众更加接纳,是明智之举。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

丰臣秀吉,来源:维基百科

证明明显的事情有多困难?

首先,让我们观看一段著名的罗温·艾金森爵士的视频采访。

来源:YouTube

罗温·艾金森爵士确实是喜剧传奇。 想到有人可能不认识他是标志性角色 Mr. Bean 的幕后天才,真是有趣。然而,有时候,我们越是试图说服别人一个明显的真相,它就变得越不可信。

我们中的许多人都经历过类似的情况。我记得个人尝试向销售代表解释权责发生制会计的复杂性时的经历。那是一个非常“特殊”的时刻。 有时候,专业知识与理解之间的差距显得非常大,再多的解释也无法弥补。这提醒我们,沟通不仅仅是我们说了什么,更在于我们的受众如何接收和理解这些信息。

哦,传达复杂话题的乐趣和挑战!对于数据科学社区的人来说,这是一种熟悉的情景。你深入分析,使用你发现非常有趣的高级技术。然而,当你展示你的发现时,却遇到了空洞的凝视或礼貌的点头。就好像你在讲外语一样。

他们真的理解了吗?还是只是点头附和,努力不让自己看起来迷茫?通常,问题的缺乏就是一个明显的信号。当然,除非你已经提前让观众准备好给你抛一个软球问题。顺便说一下,这确实是个好主意。

这突显了不仅要掌握自己领域的技术方面,还要能够将这些知识转化为适合不同受众的洞察的关键重要性。这是在展示专业知识与确保可接触性之间的微妙平衡。

有效的沟通依赖于了解你的受众。如果没有这种理解,即使是最深刻的见解也可能会失去效果。虽然专业知识至关重要,但同样重要的是以可接触的方式呈现这些知识。毕竟,这不仅仅是简化我们的工作,而是关于清晰和连接。如果我们不付出这种努力,为什么我们的受众要参与呢?

匿名的诅咒

这个故事还有另一面。你是否见过类似下面的图片?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者提供的图片,部分基于此图片

当然,我们中的许多人都有过这种经历。我也曾经在那个位置上,脸出现在左上角。我的记录?在我主持的一个漫长而坦白说有些乏味的培训中,连续八小时。其他参与者?他们的摄像头只是短暂地亮起——开头时快速“打招呼”,结束时,像往常一样,“道别”。

从那次经历中,我知道这一点:

如果你把他们当作墙壁,他们就会像墙壁一样表现。

如果没有吸引受众或者编织一个有趣的故事,我们不能指望得到互动。通常,他们只有在感到烦恼时才会参与。这突显了基于数据的讲故事的力量。我是这种方法的坚定支持者。鉴于 AI 和 LLMs 的迅速发展,我坚信它应该融入所有以商业为重点的课程中,尤其是财务课程。

过度复杂化的威力

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者提供的图片

上面的图片展示了华沙普拉加区一栋公寓楼的入口。这栋建筑经过改造,以适应残疾人士,从而创建了这个独特的坡道。我经过几次,每次都会让我思考:

为什么会有这样的设计?难道不能更简单或者稍微陡一点?那会导致进出困难吗?从开始到门口需要花费多少时间?人们使用它吗?是否更有意义的是购买并安装一个电梯而不是建造这个坡道?如此多的问题,却没有答案……

最初,没有扶手,使其看起来不那么麻烦。但现在,这确实是一个引人注目的景象。

而且,请请请:不要误解我的意思。我对任何能让残疾人士生活更轻松的举措持 200%的支持态度。我只是见过一些解决方案,在我看来,可以帮助人们按照他们想要的方式运作,并且不像照片中的那东西那么麻烦。但我算什么呢?

不管怎样,数据或分析的问题往往在于它们真的可能令人不知所措。它们可能充满了复杂的细节,这些细节看似重要,但在实际决策时却是多余的。这些不必要的复杂性可能会使我们偏离正轨,风险类似于照片中的坡道。

那又如何?

让我再讲一个故事。这次是关于一个来自白俄罗斯的机智汽车修理工。他在职业生涯中积累了大量废弃汽车零件。他没有让这些零件生锈,而是创造性地将它们重新利用成一个 3.5 米高的矮人。你可以在这里看到它。这是一种相当创新的“废物”使用方式,不是吗?

这难道不是很有意思吗? 一个由废弃汽车零件组成的 3.5 米高的矮人。但对我们来说,有什么收获?坦白说,不多。 除非,也许,我们发现一个我们认识的零件,因为它来自我们的车。

但在商业中情况并非如此。

考虑一下仪表板。我们是否都遇到过那些数据过载却提供很少实际见解的管理仪表板?或者,也许有价值的信息被深埋其中,就像试图在一个 3.5 米高的金属小矮人中找到一个旧化油器一样。正如我在最近的一篇文章中强调的那样,情况不必如此。仪表板确实可以成为强大的讲故事工具[5]。

为何要这样做?

这是我在办公室拍的一张照片。纸上的便条用波兰语写道:“请清洗您的碗盘或将其放入洗碗机中。不这样做会使水槽无法供他人使用”。

然而,你看到的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:作者提供的图片

在应对日常企业挑战时,我已承诺一个:即使水槽里满是碗碟,我也要洗我的杯子。确实,有几次因为忙碌的日子而跳过了。确实,上面的快照展示了水槽中约 30-40%的最满状态。

有趣的是,当我停下来拍这张照片时,两位同事拿着脏杯子走进了厨房。令我感到好笑的是,他们也感到了洗杯子的冲动。这只是巧合吗?我有些难以相信。

有效的行动号召的力量不仅在于说明需要做什么,更在于确定谁来做。通过指定这个人或团队并进行后续跟进,我们可以避免浪费时间和金钱的无尽会议。此外,最后,我们应该利用我们的数据!

从上述讨论中,得出了哪些见解?最重要的是,公司如何有效地过渡到数据驱动型?

如何清理数据沼泽?

好吧,最好的策略是避免一个。精简的数据湖和混乱的数据沼泽之间的界限可能很薄。但只要有正确的策略,你可以将数据沼泽转变回一个有序且高效的数据湖。

要有效地恢复你的数据湖,首先要进行彻底的数据审计,以评估数据的相关性和结构。引入强有力的数据治理,强调协议和数据管理。提升元数据管理,以提高数据的可发现性,并实施能够通过验证检查和自动清理确保数据质量的工具。定期审计、数据保留政策以及关注数据安全都是必不可少的。如机器学习和人工智能用于异常检测和数据优化

在这次重振过程中,同样重要的是建立一个知识丰富的团队。提供持续的培训,推动强调数据素养的文化。这种将战略和技术结合的整体方法,确保你的数据湖保持有序且对组织来说是宝贵的资产。

如何让见解更具深度呢?

既然我们已成功脱离数据沼泽,是时候深入探讨了。

要从数据中获得真正有价值的见解,我们必须从正确的问题开始[6]。仅仅随意地转向数据不会得到我们想要的结果。要确定正确的问题,我们需要熟悉业务世界的人来指导我们的数据使用。把业务看作一台复杂的机器,不仅有精密的内部运作,还有与外部世界如客户、供应商、竞争者以及经济环境的互动。

这就是财务业务伙伴角色变得至关重要的地方。 他们充当桥梁,将财务数据与实际业务操作连接起来。他们指导数据团队,提供关于哪些见解可能有益的方向。一个设计良好的仪表板可以成为他们的强大工具[5]。他们可能会先在较小的规模上使用这样的仪表板测试一些想法。当他们在数据中发现值得注意的东西时,他们是确保其重要性和有效性的人。

鱼多少钱?

所以,我们已经汇集了我们的见解。但是如果这些见解让人不安怎么办?如果它们暴露了脆弱性呢?

领导者在塑造数据驱动文化中发挥着关键作用。 他们倡导一种探究的环境,将数据视为解决紧迫问题的方案。通过庆祝基于数据的胜利和强调持续教育,他们将数据融入组织的 DNA 中。

领导以身作则,做出突显数据重要性的选择。他们基于数据建立基准,确保可衡量的结果,并在团队中创造责任感。他们的适应能力和对数据驱动方法的承诺成为灯塔,激励整个组织采用类似的方法。

证明显而易见的事情……

当你已确保数据、获得管理层的支持,并讲述了基于事实的故事时,如果有人表达怀疑,尤其是其他人站在怀疑者一边,这可能会让人感到泄气。那么,你应该如何应对呢?

首先,认真倾听他们的保留意见,以把握他们疑虑的性质。尊重并认可他们的观点。展示你愿意进行开放对话的态度。通过提问深入探讨,以更好地理解他们的担忧。在澄清复杂问题时,依靠简单的解释和直观的类比。保持冷静,确保讨论保持富有成效。

如果怀疑仍然存在,建议额外安排会议或研讨会以进行更彻底的探索。通过建议延长参与时间,你强调了对相互清晰度的承诺。合作更佳。团队合作可以帮助我们更好地理解并建立彼此的信任。

匿名的诅咒

哦,还有问题吗?到现在为止,每个人都应该已经达成一致了。如果存在脱节,现在正是利用数据讲故事的力量的时候。数据驱动的叙述,配以引人注目的视觉效果,为数据科学家和业务团队之间提供了无缝的桥梁。与其深入复杂的电子表格,不如用简洁的视觉效果来简化数据。这确保了核心见解立刻显现,帮助所有人做出更明智的决策[7]。

保持简单明了

数据讲故事有助于将复杂的事物简化。通过将数据转化为清晰的故事,我们突出了主要观点,省略了令人困惑的部分。使用图片或图表可以使理解变得更加容易。这样,每个人都能迅速获取主要思想,而不会迷失在过多的细节中。简而言之,数据讲故事保持了事物的简单明了。

谁在做笔记?

最后,让我们解决激发本文的燃眉之问:我们如何有效利用洞察力和数据?

秘密在于准备。一个引人注目的行动号召建立在一个基于数据的精心编排的故事基础上。 这个行动号召应该在故事的高潮时刻揭示,那是所有目光集中在你(或你的幻灯片)上时,观众渴望听到下一步的时刻。但这种势头是短暂的。无论你的信息多么有影响力,确立责任都是至关重要的。谁将采取下一步?接下来将做什么?

理想情况下,观众中会有人记录下来(你需要事先请求)。演讲结束后,发送一封总结邮件,详细说明主要决策。定期检查进展情况,确保工作持续进行。

结论

每一个伟大的旅程都始于一个脚步。即使是小事也能带来巨大变化。使用数据对现代企业很重要,但并不总是容易。没有一种正确的方法,但开始这段旅程是值得的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 History in HD 提供,来源于 Unsplash

关注我在 medium.com 上的动态。

在 LinkedIn 上与我联系。

访问我的博客(波兰语).

访问我的 YouTube(波兰语,提供英文字幕的影片)。

在扣除 iOS 和系统文件使用的内存后。

参考资料:

[1] Duarte, Fabio, 每日生成的数据量(2023),2023 年 4 月 3 日

[2] 我引用了这篇文章来进行上述计算:Zero Agency, 计算泽字节,2015 年 10 月 21 日

[3] NewVantage Partners, 数据和人工智能领导力执行调查,2022 年 1 月

[4] Silva Santos, Diogo, 数据架构的过去、现在和未来,2023 年 3 月 9 日

[5] 苏德杰科,米哈伊,利用管理仪表板讲故事:一种可行的途径,2023 年 8 月 3 日

[6] 拉马克里希南,拉马,我有数据。我需要洞察。我该从哪里开始?,2017 年 7 月 2 日。

[7] 纳斯鲍默·克纳夫利克,科尔数据讲故事,Wiley,2015 年。

从纸张到像素:评估数字化手写文本的最佳技术

原文:towardsdatascience.com/from-paper-to-pixel-evaluating-the-best-techniques-for-digitising-handwritten-texts-9cc39e7a457d?source=collection_archive---------2-----------------------#2023-09-14

对 OCR、变换器模型和基于提示工程的集成技术的比较分析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Sohrab Sani

·

关注 发表在 Towards Data Science ·16 分钟阅读·2023 年 9 月 14 日

作者: Sohrab SaniDiego Capozzi

组织长期以来一直在处理数字化历史手写文档这一繁琐且昂贵的任务。之前,光学字符识别(OCR)技术,如 AWS Textract (TT) [1] 和 Azure 表单识别器 (FR) [2],在这方面领先。虽然这些选项可能广泛可用,但它们有许多缺点:价格高、需要长时间的数据处理/清洗,并且准确性可能不尽如人意。最近,利用 Transformer 架构的深度学习进展在图像分割和自然语言处理领域,使得 OCR 自由的技术得以发展,例如 Document Understanding Transformer (Donut)[3] 模型。

在这项研究中,我们将使用自定义数据集比较 OCR 和基于 Transformer 的技术,该数据集由一系列手写表单创建。对这一相对简单任务的基准测试旨在引导向更复杂的应用,特别是在更长的手写文档上。为了提高准确性,我们还探索了利用提示工程结合 gpt-3.5-turbo 大型语言模型(LLM)的集成方法,以结合 TT 和微调的 Donut 模型的输出。

这项工作的代码可以在这个 GitHub 仓库中查看。数据集可以在我们的 Hugging Face 仓库这里获得。

目录:

· 数据集创建

· 方法

∘ Azure 表单识别器 (FR)

∘ AWS Textract (TT)

∘ Donut

∘ 集成方法:TT、Donut、GPT

· 模型性能测量

∘ FLA

∘ CBA

∘ 覆盖范围

∘ 成本

· 结果

· 其他考虑因素

∘ Donut 模型训练

∘ 提示工程的变异性

· 结论

· 下一步

· 参考文献

· 致谢

数据集创建

本研究从 NIST 特殊数据库 19 数据集[4]的 2100 张手写表单图像中创建了一个自定义数据集。图 1 提供了这些表单之一的样本图像。最终的集合包括 2099 张表单。为了整理这个数据集,我们裁剪了每个 NIST 表单的顶部部分,目标是红框中高亮的 DATE、CITY、STATE 和 ZIP CODE(现在称为“ZIP”)键[图 1]。这种方法启动了基准测试过程,进行了一项相对简单的文本提取任务,使我们能够快速选择和手动标记数据集。在撰写时,我们不知道有任何公开的带标记的手写表单图像数据集可以用于 JSON 键字段文本提取。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1. 来自 NIST 特殊数据库 19 数据集的示例表单。红框标识了裁剪过程,该过程仅选择此表单中的 DATE、CITY、STATE 和 ZIP 字段。(作者提供的图像)

我们手动从文档中提取每个键的值,并仔细检查其准确性。总共丢弃了 68 个表单,因为它们包含至少一个无法辨认的字符。表单中的字符被记录为实际出现的样子,无论拼写错误或格式不一致。

为了对 Donut 模型进行微调以处理缺失数据,我们添加了 67 个空表单,以便为这些空字段进行训练。表单中的缺失值在 JSON 输出中表示为“None”字符串。

图 2a 显示了我们数据集中的一个样本表单,而图 2b 则展示了与该表单相关的 JSON。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2。 (a) 数据集中的示例图像;(b) JSON 格式的提取数据。(图像由作者提供)

表 1 提供了数据集中每个键的变异性分解。从最具变异性到最少的顺序是 ZIP、CITY、DATE 和 STATE。所有日期均在 1989 年,这可能降低了整体 DATE 的变异性。此外,尽管美国只有 50 个州,但由于不同的首字母缩略词或大小写敏感的拼写,STATE 的变异性有所增加。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 1。 数据集的总结统计。(图像由作者提供)

表 2 总结了我们数据集中各种属性的字符长度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 2。 字符长度和分布的总结。(图像由作者提供)

上述数据表明,CITY 条目的字符长度最长,而 STATE 条目的字符长度最短。每个条目的中位数值紧随其各自的均值,表明各类别的字符长度围绕平均值的分布相对均匀。

数据标注后,我们将其分为三个子集:训练集、验证集和测试集,样本量分别为 1400、199 和 500。这里是一个链接,用于此笔记本。

方法

我们将详细阐述每种测试方法,并将其与包含更多细节的相关 Python 代码关联起来。方法的应用首先单独描述,即 FR、TT 和 Donut,然后是 TT+GPT+Donut 集成方法。

Azure Form Recognizer (FR)

图 3 展示了使用 Azure FR 从表单图像中提取手写文本的工作流程。

  1. 存储图像: 可以存储在本地驱动器或其他解决方案中,如 S3 桶或 Azure Blob 存储。

  2. Azure SDK:用于从存储中加载每个图像并通过 Azure SDK 将其传输到 FR API 的 Python 脚本。

  3. 后处理:使用现成的方法意味着最终输出通常需要精细调整。以下是 21 个需要进一步处理的提取键:

    [ ‘DATE’, ‘CITY’, ‘STATE’, ‘’DATE’, ‘ZIP’, ‘NAME’, ‘E ZIP’,’·DATE’, ‘.DATE’, ‘NAMR’, ‘DATE®’, ‘NAMA’, ‘_ZIP’, ‘.ZIP’, ‘print the following shopsataca i’, ‘-DATE’, ‘DATE.’, ‘No.’, ‘NAMN’, ‘STATE\nZIP’]

    一些键有额外的点或下划线,需要去除。由于文本在表单中的位置非常接近,提取的值有许多实例被错误地关联到不正确的键。这些问题随后会得到合理程度的解决。

  4. 保存结果:将结果以 pickle 格式保存到存储空间中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3. Azure FR 工作流的可视化。(作者提供的图片)

AWS Textract (TT)

图 4 描述了使用 AWS TT 从表单图像中提取手写文本的工作流:

  1. 存储图像: 图像存储在 S3 桶中。

  2. SageMaker Notebook:Notebook 实例帮助与 TT API 进行交互,执行脚本的后处理清理,并保存结果。

  3. TT API: 这是由 AWS 提供的现成的基于 OCR 的文本提取 API。

  4. 后处理: 使用现成的方法意味着最终输出通常需要进行精细调整。TT 产生了一个包含 68 列的数据集,而 FR 方法只有 21 列。这主要是由于检测到图像中额外的文本,这些文本被认为是字段。在基于规则的后处理中会解决这些问题。

  5. 保存结果:经过处理的数据会使用 pickle 格式存储在 S3 桶中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4. TT 工作流的可视化。(作者提供的图片)

Donut

与不能通过自定义字段和/或模型再训练适应特定数据输入的现成基于 OCR 的方法相比,本节深入探讨了使用基于 Transformer 模型架构的 Donut 模型来改进无 OCR 方法。

首先,我们使用我们的数据对 Donut 模型进行了微调,然后将模型应用于我们的测试图像,以 JSON 格式提取手写文本。为了高效地重新训练模型并防止潜在的过拟合,我们使用了 PyTorch Lightning 的 EarlyStopping 模块。批量大小为 2,训练在 14 个周期后结束。以下是 Donut 模型微调过程的更多细节:

  • 我们分配了 1,400 张图像用于训练,199 张用于验证,其余 500 张用于测试。

  • 我们使用了一个 naver-clova-ix/donut-base 作为基础模型,它可以在 Hugging Face 上访问。

  • 然后使用 24GB 内存的 Quadro P6000 GPU 对模型进行了微调。

  • 整个训练时间大约为 3.5 小时。

  • 有关更复杂的配置细节,请参考仓库中的 [train_nist.yaml](https://github.com/srsani/hvdu/blob/main/src/config/train_nist.yaml)

该模型也可以从我们的 Hugging Face 空间 代码库 下载。

集成方法:TT、Donut、GPT

探索了各种集成方法,其中 TT、Donut 和 GPT 的组合表现最佳,具体解释如下。

一旦通过单独应用 TT 和 Donut 获得 JSON 输出,这些输出被用作输入,随后传递给 GPT。目的是利用 GPT 将这些 JSON 输入中的信息与上下文 GPT 信息结合,创建一个新的/更清晰的 JSON 输出,以提高内容的可靠性和准确性 [表 3]。图 5 提供了这一集成方法的视觉概述。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5. 结合 TT、Donut 和 GPT 的集成方法的视觉描述。(图片由作者提供)

为此任务创建适当的 GPT 提示是一个迭代过程,并需要引入临时规则。根据附加考虑部分的说明,为此任务 — 以及可能的数据集 — 定制 GPT 提示是本研究需要探索的一个方面。

模型性能测量

本研究主要通过使用两种不同的准确度测量来评估模型性能:

  • 字段级准确率(FLA)

  • 基于字符的准确度(CBA)

还测量了其他数量,如覆盖率成本,以提供相关的背景信息。所有指标如下所述。

FLA

这是一个二元测量:如果预测的 JSON 中所有键的字符与参考 JSON 中的字符匹配,则 FLA 为 1;如果有一个字符不匹配,则 FLA 为 0。

请考虑以下示例:

JSON1 = {'DATE': '8/28/89', 'CITY': 'Murray', 'STATE': 'KY', 'ZIP': '42171'}
JSON2 = {'DATE': '8/28/89', 'CITY': 'Murray', 'STATE': 'KY', 'ZIP': '42071'}

使用 FLA 比较 JSON1 和 JSON2 由于 ZIP 不匹配得分为 0。然而,将 JSON1 与自身比较则提供 FLA 得分为 1。

CBA

该准确度测量的计算方法如下:

  1. 确定每对对应值的 Levenshtein 编辑距离。

  2. 通过将所有距离相加并除以每个值的总组合字符串长度来获得标准化得分。

  3. 将此得分转换为百分比。

两个字符串之间的 Levenshtein 编辑距离是将一个字符串转换为另一个字符串所需的更改次数。这包括计数替换、插入或删除。例如,将“marry”转换为“Murray”需要两个替换和一个插入,共计三个更改。这些修改可以以各种顺序进行,但至少需要三次操作。对于此计算,我们使用了 NLTK 库中的 edit_distance 函数。

下面是一个代码片段,展示了所描述算法的实现。此函数接受两个 JSON 输入,并返回一个准确度百分比。

def dict_distance (dict1:dict,
                  dict2:dict) -> float:

   distance_list = []
   character_length = []

   for key, value in dict1.items():
       distance_list.append(edit_distance(dict1[key].strip(),
                                          dict2[key].strip()))

       if len(dict1[key]) > len(dict2[key]):
           character_length.append((len(dict1[key])))

       else:              
           character_length.append((len(dict2[key])))

   accuracy = 100 - sum(distance_list)/(sum(character_length))*100

   return accuracy

为了更好地理解该函数,让我们看看它在以下示例中的表现:

JSON1 = {'DATE': '8/28/89', 'CITY': 'Murray', 'STATE': 'KY', 'ZIP': '42171'}
JSON2 = {'DATE': 'None', 'CITY': 'None', 'STATE': 'None', 'ZIP': 'None'}
JSON3 = {'DATE': '8/28/89', 'CITY': 'Murray', 'STATE': 'None', 'ZIP': 'None'}
  1. dict_distance(JSON1, JSON1): 100% JSON1 和 JSON1 之间没有差异,因此我们获得了 100% 的完美得分。

  2. dict_distance(JSON1, JSON2): 0% JSON2 中的每个字符都需要修改才能匹配 JSON1,从而得出 0% 的得分。

  3. dict_distance(JSON1, JSON3): 59% JSON3 中的 STATE 和 ZIP 键的每个字符都必须更改以匹配 JSON1,从而得到 59% 的准确性得分。

我们现在将重点关注分析图像样本的 CBA 平均值。这些准确性测量非常严格,因为它们衡量了检查字符串中的所有字符及字符大小写是否匹配。由于 FLA 的二元特性,使其在处理部分正确的情况时表现得特别保守。尽管 CBA 比 FLA 更不保守,但仍被认为是有些保守的。此外,CBA 能够识别部分正确的实例,但它也考虑了文本大小写(大写与小写),这可能根据是否关注于恢复文本的适当内容或保留书写内容的准确形式而具有不同的重要性。总体而言,我们决定使用这些严格的测量方法,以便采取更保守的方法,因为我们优先考虑文本提取的正确性而非文本语义。

覆盖率

这个量度定义为字段已全部从输出 JSON 中提取的表单图像的比例。这有助于监测从表单中提取所有字段的整体能力,而不考虑其正确性。如果 Coverage 非常低,则表示某些字段系统性地被遗漏在提取过程中。

成本

这是对将每种方法应用于整个测试数据集所产生的成本的简单估算。我们没有计算微调 Donut 模型的 GPU 成本。

结果

我们评估了所有方法在测试数据集上的表现,该数据集包含 500 个样本。这一过程的结果汇总在表 3 中。

使用 FLA 时,我们观察到传统的基于 OCR 的方法 FR 和 TT 表现相似,准确率相对较低(FLA~37%)。虽然不理想,但这可能是由于 FLA 的严格要求。作为替代,当使用 CBA Total,即考虑所有 JSON 键的平均 CBA 值时,TT 和 FR 的表现远远更可接受,值大于 77%。特别是,TT(CBA Total = 89.34%)比 FR 高出约 15%。这种行为在关注单个表单字段的 CBA 值时也得以保持,尤其是在 DATE 和 CITY 类别 [表 3] 中,并且在测量整个样本 2099 张图像的 FLA 和 CBA Totals 时(TT: FLA = 40.06%;CBA Total = 86.64%;FR: FLA = 35.64%;CBA Total = 78.57%)。虽然应用这两种模型的 Cost 值相同,但 TT 更有利于提取所有表单字段,其 Coverage 值比 FR 高出约 9%。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 3. 性能指标值是根据测试数据集计算的。CBA 总体和 CBA 关键(key= 日期、城市、州、邮政编码)分别是样本平均值和 JSON 键的总值和单独值。(图片由作者提供)

量化这些更传统的基于 OCR 的模型的性能为我们提供了一个基准,我们用这个基准来评估使用纯 Donut 方法与将 Donut 与 TT 和 GPT 结合使用的优缺点。我们从使用 TT 作为基准开始。

采用这种方法的好处体现在微调的 Donut 模型上,该模型在 1400 张图像及其对应的 JSON 上进行了微调。与 TT 结果相比,该模型的全球 FLA 为 54%,CBA 总体为 95.23%,分别提高了 38% 和 6%。最显著的提高体现在 FLA 上,显示出该模型能够准确检索超过一半测试样本中的所有表单字段。

CBA 的提高是显著的,因为用于微调模型的图像数量有限。Donut 模型显示出其优势,表现在 Coverage 和基于关键的 CBA 指标的总体值有所改善,增加幅度在 2% 到 24% 之间。Coverage 达到 100%,表明该模型可以从所有表单字段中提取文本,从而减少了将这种模型投入生产所需的后处理工作。

基于此任务和数据集,这些结果表明,使用经过微调的 Donut 模型产生的结果优于 OCR 模型。最后,还探索了集成方法,以评估是否可以继续进行额外的改进。

由 gpt-3.5-turbo 支持的 TT 和经过微调的 Donut 的集成性能表明,如果选择特定的指标(如 FLA),是有可能实现改进的。与我们经过微调的 Donut 模型相比,该模型的所有指标(不包括 CBA 状态和 Coverage)都有所增加,增加幅度在 ~0.2% 到 ~10% 之间。唯一的性能下降体现在 CBA 状态上,与我们经过微调的 Donut 模型测得的值相比,下降了 ~3%。这可能归因于使用的 GPT 提示,进一步微调可能会改善这一指标。最后,Coverage 值保持在 100% 不变。

与其他单独字段相比,日期提取(见 CBA 日期)效率更高。这可能是由于日期字段的变异性有限,因为所有日期都来源于 1989 年。

如果性能要求非常保守,那么 FLA 的 10%提升是显著的,并可能值得构建和维护更复杂的基础设施的更高成本。这也应考虑到 LLM 提示词修改引入的变异来源,如附加考虑部分所述。然而,如果性能要求不那么严格,那么该集成方法所带来的 CBA 指标改进可能不值得额外的成本和努力。

总体而言,我们的研究表明,虽然基于 OCR 的个别方法——即 FR 和 TT——各有其优点,但仅在 1400 个样本上微调的甜甜圈模型轻松超越了它们的准确性基准。此外,通过 gpt-3.5-turbo 提示词对 TT 和微调后的甜甜圈模型进行集成,进一步提高了通过 FLA 指标测量的准确性。附加考虑也必须考虑甜甜圈模型和 GPT 提示词的微调过程,接下来将进行探讨。

附加考虑

甜甜圈模型训练

为了提高甜甜圈模型的准确性,我们尝试了三种训练方法,每种方法都旨在提高推理准确性,同时防止过拟合训练数据。表 4 展示了我们结果的总结。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 4. 甜甜圈模型微调的总结。(作者提供的图像)

1. 30-周期训练:我们使用甜甜圈 GitHub 仓库提供的配置训练了 30 个周期的甜甜圈模型。该训练过程持续了约 7 小时,结果显示 FLA 为 50.0%。不同类别的 CBA 值有所不同,CITY 达到 90.55%,ZIP 达到 98.01%。然而,当我们检查 val_metric 时注意到模型在第 19 周期后开始过拟合。

2. 19-周期训练:根据初步训练获得的见解,我们将模型微调了 19 个周期。我们的结果显示 FLA 显著提高,达到 55.8%。整体 CBA 以及基于关键的 CBAs 显示了准确性值的改善。尽管这些指标很有前景,但我们检测到了过拟合的迹象,如 val_metric 所示。

3. 14-周期训练:为了进一步完善我们的模型并抑制潜在的过拟合,我们使用了 PyTorch Lightning 的 EarlyStopping 模块。这种方法在 14 个周期后终止了训练。结果显示 FLA 为 54.0%,CBAs 与 19 周期训练相比相当,甚至更好。

比较这三次训练的输出时,尽管 19 周期训练的 FLA 略有改善,但 14 周期训练的 CBA 指标整体上更优。此外,val_metric 强化了我们对 19 周期训练的担忧,表明略有过拟合的倾向。

总结来说,我们推断出,经过 14 个周期使用 EarlyStopping 微调的模型是最强健且最具成本效益的。

提示工程的变化

我们研究了两种提示工程方法(ver1 和 ver2),通过将微调的 Donut 模型与 TT 结果进行集成,以提高数据提取效率。在训练模型 14 个周期后,Prompt ver1 取得了更好的结果,其 FLA 为 59.6%,并且所有键的 CBA 指标均较高[表 5]。相比之下,Prompt ver2 出现了下降,其 FLA 降至 54.4%。详细查看 CBA 指标显示,ver2 中每个类别的准确度评分略低于 ver1,突显了这一变化的显著差异。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 5。结果总结:从表单中提取手写文本。(图片由作者提供)

在对数据集进行手动标注过程中,我们利用了 TT 和 FR 的结果,并在对表单文本进行标注时开发了 Prompt ver1。尽管 Prompt ver2 在本质上与其前身相同,但经过了轻微修改。我们的主要目标是通过去除 Prompt ver1 中的空行和冗余空格来改进提示。

总之,我们的实验突显了看似微小调整的细微影响。尽管 Prompt ver1 展示了更高的准确性,但将其精炼和简化为 Prompt ver2 的过程,悖论地导致了所有指标上的性能下降。这凸显了提示工程的复杂性以及在最终确定提示之前进行细致测试的必要性。

Prompt ver1 可在这个 Notebook中找到,Prompt ver2 的代码可以在这里查看。

结论

我们创建了一个基准数据集,用于从包含四个字段(DATE、CITY、STATE 和 ZIP)的手写表单图像中提取文本。这些表单被手动标注为 JSON 格式。我们使用此数据集评估了基于 OCR 的模型(FR 和 TT)和一个 Donut 模型,该模型随后使用我们的数据集进行了微调。最后,我们采用了一个通过提示工程构建的集成模型,该模型利用了 LLM(gpt-3.5-turbo)与 TT 和我们微调的 Donut 模型输出。

我们发现 TT 的表现优于 FR,并以此作为基准来评估 Donut 模型在单独使用或与 TT 和 GPT 组合使用(即集成方法)时可能产生的改进。正如模型性能指标所显示的那样,这种微调的 Donut 模型显示出明显的准确性提升,这证明了其优于基于 OCR 的模型。集成模型显著提高了 FLA,但成本较高,因此可以在要求更严格的性能要求的情况下考虑使用。尽管使用了相同的基础模型 gpt-3.5-turbo,但我们观察到当提示中进行微小更改时,输出 JSON 表单存在显著差异。这种不可预测性是使用现成 LLM 的一个重大缺陷。我们目前正在开发基于开源 LLM 的更紧凑的清理流程来解决这个问题。

下一步

  • 表 2 中的价格列显示,OpenAI API 调用是本研究中最昂贵的认知服务。因此,为了减少成本,我们正在通过利用完全微调、提示微调[5] 和 QLORA [6] 等方法来微调 LLM 以进行 seq2seq 任务。

  • 由于隐私原因,数据集中图像上的名称框被黑色矩形覆盖。我们正在通过向数据集中添加随机的名字和姓氏来更新这一点,这将使数据提取字段从四个增加到五个。

  • 未来,我们计划通过将这项研究扩展到包括整个表单或其他更大文档的文本提取任务,从而增加文本提取任务的复杂性。

  • 调查 Donut 模型超参数优化。

参考文献

  1. Amazon Textract,AWS Textract

  2. 表单识别器,表单识别器(现为文档智能)

  3. Kim, Geewook 和 Hong, Teakgyu 和 Yim, Moonbin 和 Nam, JeongYeon 和 Park, Jinyoung 和 Yim, Jinyeong 和 Hwang, Wonseok 和 Yun, Sangdoo 和 Han, Dongyoon 和 Park, Seunghyun,无 OCR 文档理解转换器 (2022),欧洲计算机视觉会议 (ECCV)

  4. Grother, P. 和 Hanaoka, K. (2016) NIST 手写表单和字符数据库 (NIST 特殊数据库 19)。DOI: doi.org/10.18434/T4H01C

  5. Brian Lester, Rami Al-Rfou, Noah Constant,规模化的参数高效提示微调的力量 (2021),arXiv:2104.08691

  6. Tim Dettmers, Artidoro Pagnoni, Ari Holtzman, Luke Zettlemoyer,QLoRA: 高效的量化 LLM 微调 (2023),arxiv.org/abs/2305.14314

致谢

我们要感谢我们的同事大卫·罗德里格斯博士,他对这个项目的持续支持和讨论。我们还要感谢Kainos的支持。

从 Powerpoints 到 PDFs 再到 CSV 文件:用于读取主要文件类型的 Python 类

原文:towardsdatascience.com/from-powerpoints-to-pdfs-to-csv-files-python-classes-for-reading-major-file-types-14eac058ecb5

在下一个数据科学项目中能够从多种不同的文件类型中提取和比较信息!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 本杰明·麦克洛斯基

·发表于 Towards Data Science ·阅读时间 6 分钟·2023 年 1 月 6 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源于 Glen CarrieUnsplash

介绍

数据科学家可能需要读取多种不同类型的文件以完成他们的项目。虽然在 Python 中读取 文本 文件特别容易,但其他文件类型可能需要来自不同 Python API 的额外支持,以确保它们在 Python 中可读和可用。今天的代码提供了多种 Python 类,可用于读取许多不同的文件类型。每个类的输出是一个文本字符串,数据科学家可以利用这些字符串进行信息提取以及各种文档的相似性分析。

PDF 文件

我在过去多次讨论了 PDF 文件的重要性及其在 Python 中的处理方法。

## PDF 解析仪表板与 Plotly Dash

介绍如何在下一个仪表板中读取和展示 PDF 文件。

towardsdatascience.com ## 自然语言处理:用于获取概述的 PDF 处理功能

今天用于自然语言处理 (NLP) 的许多文档都是 .pdf 格式的。读取 pdf 文件到…

[towardsdatascience.com

我想包括下面的类,因为我无法强调在下一个项目中使用 PDF 文件的重要性。今天,许多人使用 PDF 执行各种任务,里面的信息太多,不应轻易丢弃。pdfReader 类有两个功能:一个是使 PDF 可以被 Python 读取,另一个是将 PDF 转换为 Python 中的一个文本字符串。注意:最近 PyPDF2 有了新的更新,所以在使用未更新的旧教程时要小心。PyPDF2 3.0.0 中许多方法名称已被更改。

!pip install PyPDF2
import PyPDF2
import re
class pdfReader:

    def __init__(self, file_path: str) -> None:
        self.file_path = file_path

    def pdf_reader(self) -> None:
            """A function that can read .pdf formatted files 
                and returns a python readable pdf.

                Returns:
                read_pdf: A python readable .pdf file.
            """
            opener = open(self.file_path,'rb')
            read_pdf = PyPDF2.PdfReader(opener)
            return read_pdf

    def PDF_one_pager(self) -> str:
        """A function that returns a one line string of the 
            pdf.

            Returns:
            one_page_pdf (str): A one line string of the pdf.

        """
        p = pdfReader(self.file_path)
        pdf = p.pdf_reader()
        content= ''
        num_pages = len(pdf.pages)

        for i in range(0, num_pages):
            content += pdf.pages[i].extract_text() + "\n"
        content = " ".join(content.replace(u"\xa0", " ").strip().split())
        page_number_removal = r"\d{1,3} of \d{1,3}"
        page_number_removal_pattern = re.compile(page_number_removal, re.IGNORECASE)
        content = re.sub(page_number_removal_pattern, '',content)
        return content

Microsoft Powerpoint 文件

有趣的事实:有一种方法可以将 Microsoft Powerpoint 文件读入 Python 并查看它们包含的信息。下面的 pptReader 类将从你 Powerpoint 演示文稿中的每一张幻灯片读取文本,并将其添加到一个文本字符串中。不要担心 Powerpoint 中的图片,ppt_text() 函数会处理这些内容!

class pptReader:

    def __init__(self, file_path: str) -> None:
        self.file_path = file_path

    def ppt_text(self) -> str:
    """A function that returns a string of text from all 
       of the slides in a pptReader object.

      Returns:
      text (str): A single string containing the text 
      within each slide of the pptReader object.
   """
      prs = Presentation(self.file_path)
      text = str()

      for slide in prs.slides:
        for shape in slide.shapes:
          if not shape.has_text_frame:
              continue
          for paragraph in shape.text_frame.paragraphs:
            for run in paragraph.runs:
              text += ' ' + run.text
      return text

Microsoft Excel 文件

出乎意料的是,Excel 文件比我最初预期的更难以读入 Python。我必须使用 openpyxl 库首先将 Excel 文件读入 Python。我没有得到想要的输出,于是将读入的文件保存为标准的 csv 文件,然后继续处理。这个技巧有效!

 class xlsxReader:

    def __init__(self, file_path: str) -> None:
        self.file_path = file_path

    def xlsx_text(self) -> str:
      """A function that will return a string of text from 
         the information contained within an xlsxReader object.

         Returns:
         text (str): A string of text containing the information
         within the xlsxReader object.
     """
      inputExcelFile = self.file_path
      text = str()
      wb = openpyxl.load_workbook(inputExcelFile)
      for ws in wb.worksheets:
        for val in ws.values:
          print(val)

      for sn in wb.sheetnames:
        print(sn)
        excelFile = pd.read_excel(inputExcelFile, engine = 'openpyxl', sheet_name = sn)
        excelFile.to_csv("ResultCsvFile.csv", index = None, header=True)

        with open("ResultCsvFile.csv", "r") as csvFile: 
          lines = csvFile.read().split(",") # "\r\n" if needed
          for val in lines:
            if val != '':
              text += val + ' '
          text = text.replace('\ufeff', '')
          text = text.replace('\n', ' ')
      return text

CSV 文件

你可能会想知道为什么我没有使用 Pandas 库来读取我的 CSV 文件。我使用传统的 open() 方法,因为我想要获取给定 csv 文件中的所有信息,而且许多 csv 文件的格式不同。此外,我倾向于使用标准 Python 库,而不是导入外部 API,当内置函数与 API 同样有效或可以快速完成我的任务时

class csvReader:

    def __init__(self, file_path: str) -> str:
        self.file_path = file_path

    def csv_text(self):
    """A function that returns a string of text containing
       the information within a csvReader object.

      Returns:
      text (str): A string of text containing information
      within a csvReader object.
     """ 
      text = str()
      with open(self.file_path, "r") as csvFile: 
        lines = csvFile.read().split(",") # "\r\n" if needed

        for val in lines:
          text += val + ' '
        text = text.replace('\ufeff', '')
        text = text.replace('\n', ' ')
      return text

额外:自然语言预处理类

在一个项目中处理所有上述类时,通过将每个类的输出格式化为文本字符串来进行归一化处理。我最近在处理各种文档时,还需要对每个字符串进行预处理,以增加更多的归一化以及移除不必要的信息。在将所有文件读入 Python 后,使用 data processor 类清理每个字符串,并在所有样本中标准化它们。

class dataprocessor:

  def __init__(self):
    return

  @staticmethod
  def get_wordnet_pos(text: str) -> str:
    """Map POS tag to first character lemmatize() accepts.

       Parameters:
       text (str): A string of text

       Returns:
       tag: The tag of the word
    """
    tag = nltk.pos_tag([text])[0][1][0].upper()
    tag_dict = {"J": wordnet.ADJ,
                "N": wordnet.NOUN,
                "V": wordnet.VERB,
                "R": wordnet.ADV}
    return tag_dict.get(tag, wordnet.NOUN)

  @staticmethod
  def preprocess(input_text: str):
    """A function that accepts a string of text and conducts various
       NLP preprocessing steps on said text including puncation removal, 
      stopword removal and lemmanization.

       Parameters:
       input_text (str): A string of text

       Returns:
       output_text (str): A processed string of text.
    """
    #lowercase
    input_text = input_text.lower()

    #punctuation removal
    input_text = "".join([i for i in input_text if i not in string.punctuation])

    #Stopword removal
    stopwords = nltk.corpus.stopwords.words('english')
    custom_stopwords = ['\n','\n\n', '&', ' ', '.', '-', '$', '@']
    stopwords.extend(custom_stopwords)
    input_text = [i for i in input_text if i not in stopwords]
    input_text = ' '.join(word for word in input_text)

    #lemmanization
    lm = WordNetLemmatizer()
    input_text = [lm.lemmatize(word, dataprocessor.get_wordnet_pos(word)) for word in input_text.split(' ')]
    text = ' '.join(word for word in input_text)

    output_text = re.sub(' +', ' ',input_text)

    return output_text

结论

今天我们讨论了数据科学家在下一个项目中可以使用的不同 Python 类,以便读取各种文件类型。虽然还有其他可以读取到 Python 中的文件类型,但今天讨论的这些种类非常重要,有时可能会被忽视。使用今天介绍的文件读取类和最终的数据清理类,你可以比较和对比完全不同文件类型中的信息。例如,也许你想使用自然语言处理来查看不同的研究文献,找出哪些相似,然后推荐给学生作为当前课程的学习资料。这只是从今天提供的类中可以创建的众多不同项目之一,祝你享受!

如果你喜欢今天的阅读内容,请给我关注,并告诉我是否有其他话题你希望我探索!如果你没有 Medium 账户,可以通过我的链接 这里注册!另外,欢迎添加我的 LinkedIn,或者随时联系我!感谢阅读!

从穿孔卡到 ChatGPT

原文:towardsdatascience.com/from-punch-cards-to-chatgpt-42c2a09ac01a?source=collection_archive---------1-----------------------#2023-11-01

我祖父的生成式人工智能一瞥

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Ty Stephens

·

关注 发布在Towards Data Science ·9 分钟阅读·2023 年 11 月 1 日

我的母亲的父亲,Skip,在我眼中一直是一名农夫。不幸的是,我母亲在 1988 年我的出生后仅一个月就因白血病去世。作为家庭中的第一个孙子,我和 Skip 非常亲密。小时候,我常常坐在拖拉机和联合收割机的扶手上度过我的一天,后来成为青少年时,我也在农场做了一个夏季工作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在夏季小麦收割期间,从空中俯瞰一台约翰迪尔联合收割机。在 20 世纪 90 年代末/21 世纪初,我和我的祖父在我们自己的小麦收割季节中使用了两台这样的机器。那是我的第一份“工作”。照片由Scott Goodwill拍摄,来源于Unsplash

然而,Skip 早期的生活与我认识的农业世界大相径庭。在我进入这个场景之前,他已经深入学术领域,1972 年完成了德州农工大学(Texas A&M, College Station)的统计学博士课程。不久之后,他接受了马里兰大学的教授职位,并于 1974 年完成了他的论文。他开创性的研究旨在预测和定位工业环境中的安全和材料风险。这项艰巨的任务需要数年的努力。他不得不手动从不同公司收集十年的事故报告,手工处理统计数据,然后将这些见解转换为大学计算机系统的打孔卡指令。获取计算机使用时间并非立即可得;这需要提前几周甚至几个月预约。一个编码错误可能意味着从头开始,可能会使他的研究延迟几个月。

他在 1980 年代离开了那种生活,回到东德州接管家族农场,并开始了创业生涯。但在他作为农民的所有工作中,运用统计推断的愿望始终存在——只是我小时候并没有意识到。对我孩子的理解来说,Skip 在做他所称的“办公室工作”——但实际上他是在利用 IT 来预测和确保融资以应对运营开支,优化化肥中的化学成分以提高作物产量,通过在芝加哥商品交易所交易期货来降低现金流的不确定性,这些都是在他用 16 KB RAM 的Radio Shack 购买的 TRS 80上完成的,连接了一台点阵打印机。农业可以是一个利润微薄的行业——而 Skip 的赌注是他可以利用统计数据稍微拉平竞争环境。

多年来,这个农场没有经受住时间的考验。事实证明,当代际农业被迫跳过一代时,其效果并不好——而且今天的投入成本比以往任何时候都更为严苛——规模经济成为了唯一可以盈利竞争的方式——因此,Skip 一代的大多数中小型农场被收购和整合——但这是一种逐步发生的过程——一点一点地(至少我们是这样经历的)。

我当然逐渐欣赏到统计学与农业之间的紧密联系。我仍然记得来自美国农业部的年度访问,他们详细采样作物产量(包括我们的农场),作为他们国家农业统计服务的一部分。在我看来,这是历史上一个伟大的未被充分重视的持续数据项目——帮助一代代农民做出“数据驱动”的决策——在那个词还未成为流行词之前。但我对 Skip 几十年来所做的一切有了更深的理解,因为我开始了自己的分析与数据科学事业——这是我在 20 多岁和 30 多岁时作为美国陆军军官服务和环球旅行后的第二幕。我经常通过电话与他联系,询问他们如何进行回归分析或模拟,或他们如何在“那时候”控制随机抽样。然后偶尔告诉他现在的做法,以评估他对我描述机器学习、深度学习、强化学习等概念的兴奋——对他来说,这有些像科幻小说——但他喜欢听这些——即使这在他晚年并不完全真实

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我看到约翰·迪尔在 2023 年 1 月 CES 上进行的主题演讲——展示了新设备,例如上图所示的喷雾器,它使用 36 台相机、计算机视觉和神经网络实时检测杂草与作物,并最小化除草剂的使用。图像由作者提供。

实验开始了。

我决定在周末做出一个展示而不是讲述的决定。我希望 Skip 亲自体验新技术,而不仅仅是听我谈论它。如果我们能在不到 40 分钟内制定一个启动虚拟新农场的商业计划呢?我可以使用启用了高级数据分析的 ChatGPT 4,通过屏幕分享给他的 iPhone——我们一起合作完成它。

我们简要讨论了我们的假设:

  1. 我们在东德克萨斯州有 1000 英亩的农田。

  2. 我们有 100 万美元的启动资金用于购买设备。

  3. 我们需要从银行获得一笔信用额度,以支付第一年的运营费用以启动项目。

  4. 我们有兴趣种植小麦和大豆(Skip 曾经种植的作物)。

我们从简单开始:

提示 1: “为我写一个商业计划大纲,以启动东德克萨斯州的新农场,种植小麦和大豆”。

Skip 立刻对详细结果留下了深刻的印象。但等等,我们才刚刚开始……

提示 2: “给我一个我需要开始的设备清单”

提示 3: “将其放入表格中,并根据最紧急的到最不紧急的按数字优先级排序”。

提示 4: “现在创建一个新的预算分配列,假设我将使用租赁和购买的组合,创建一个额外的列来推荐租赁与购买,假设我有 100 万美元的启动资金。”

(时间耗时 4 分钟)

结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据由 GPT-4 生成,图片由作者提供。

提示 5: “我应该留出多少资金来申请一条用于变动成本(种子、肥料、劳动力等)的信用额度,假设为 1000 英亩。创建一个新的表格。”

结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据由 ChatGPT 4 生成,图片由作者提供

到了这个时候,我感觉 Skip 就像是再次目睹了阿波罗 11 号。他几乎抑制不住他的兴奋。但我们还没完成……

提示 6: “给我写一个 Monte Carlo 模拟,我可以调整输入假设并测试我的预算结果”

结果:

import numpy as np
import matplotlib.pyplot as plt

# Define number of simulations
n_simulations = 10000

# Assumptions with [mean, std deviation]
wheat_seed_cost = [20, 2]  # Cost per acre
soybean_seed_cost = [50, 5]
fertilizer_wheat_cost = [50, 5]
fertilizer_soybean_cost = [40, 4]
labor_cost = [25, 3]
pesticide_cost = [30, 3]
fuel_maintenance_cost = [15, 2]
miscellaneous_cost = [10, 1]

def simulate_farm_costs():
    wheat_seed = np.random.normal(wheat_seed_cost[0], wheat_seed_cost[1])
    soybean_seed = np.random.normal(soybean_seed_cost[0], soybean_seed_cost[1])
    fertilizer_wheat = np.random.normal(fertilizer_wheat_cost[0], fertilizer_wheat_cost[1])
    fertilizer_soybean = np.random.normal(fertilizer_soybean_cost[0], fertilizer_soybean_cost[1])
    labor = np.random.normal(labor_cost[0], labor_cost[1])
    pesticide = np.random.normal(pesticide_cost[0], pesticide_cost[1])
    fuel_maintenance = np.random.normal(fuel_maintenance_cost[0], fuel_maintenance_cost[1])
    miscellaneous = np.random.normal(miscellaneous_cost[0], miscellaneous_cost[1])

    total_cost = (wheat_seed + soybean_seed + fertilizer_wheat + fertilizer_soybean + 
                  labor + pesticide + fuel_maintenance + miscellaneous) * 1000  # for 1000 acres

    return total_cost

results = [simulate_farm_costs() for _ in range(n_simulations)]

# Visualization
plt.hist(results, bins=50, edgecolor='black', alpha=0.7)
plt.title('Distribution of Total Farm Costs')
plt.xlabel('Total Cost')
plt.ylabel('Frequency')
plt.grid(True, alpha=0.2)
plt.show()

现在是关键时刻——代码会运行吗?我们跳到 Jupyter notebook 运行代码。第一次尝试就成功了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据由 ChatGPT 4 生成,图片由 Python 生成,图片由作者提供

到了这个时候,我们仅用了 10-15 分钟。还有一些时间……我们可以使它具有互动性吗?

我们需要创建一个参数列表,允许用户在滑块上动态调整假设。我们再次向 ChatGPT 寻求一些关于这些参数的建议,基于我们之前构建的 Monte Carlo 模拟:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据由 GPT 4 生成,图片由作者提供

一旦我们建立了参数列表,我们在 Power BI 中创建了一个“度量”表,连接到 16 个切片器视觉效果,允许用户手动选择他们的输入并动态更新 Monte Carlo 模拟。为此,我们在 Power BI 中创建了一个“Python 视觉”,将所有度量拖入其中,然后更新代码如下:

# The following code to create a dataframe and remove duplicated rows is always executed and acts as a preamble for your script: 

# dataset = pandas.DataFrame(fertilizer_soybean_cost_avg Value, fertilizer_soybean_cost_std Value, fertilizer_wheat_cost_avg Value, fertilizer_wheat_cost_std Value, fuel_maintenance_cost_avg Value, fuel_maintenance_cost_std Value, labor_cost_avg Value, labor_cost_std Value, miscellaneous_cost_avg Value, miscellaneous_cost_std Value, pesticide_cost_avg Value, pesticide_cost_std Value, soybean_seed_cost_avg Value, wheat_seed_cost_avg Value, wheat_seed_cost_std Value)
# dataset = dataset.drop_duplicates()

# Paste or type your script code here:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Assuming the data from Power BI is passed as 'dataset'
df = dataset

# Fetch values from the dataset
wheat_seed_cost_avg = df['wheat_seed_cost_avg Value'].iloc[0]
wheat_seed_cost_std = df['wheat_seed_cost_std Value'].iloc[0]
soybean_seed_cost_avg = df['soybean_seed_cost_avg Value'].iloc[0]
soybean_seed_cost_std = df['soybean_seed_cost_std Value'].iloc[0]
fertilizer_wheat_cost_avg = df['fertilizer_wheat_cost_avg Value'].iloc[0]
fertilizer_wheat_cost_std = df['fertilizer_wheat_cost_std Value'].iloc[0]
fertilizer_soybean_cost_avg = df['fertilizer_soybean_cost_avg Value'].iloc[0]
fertilizer_soybean_cost_std = df['fertilizer_soybean_cost_std Value'].iloc[0]
labor_cost_avg = df['labor_cost_avg Value'].iloc[0]
labor_cost_std = df['labor_cost_std Value'].iloc[0]
pesticide_cost_avg = df['pesticide_cost_avg Value'].iloc[0]
pesticide_cost_std = df['pesticide_cost_std Value'].iloc[0]
fuel_maintenance_cost_avg = df['fuel_maintenance_cost_avg Value'].iloc[0]
fuel_maintenance_cost_std = df['fuel_maintenance_cost_std Value'].iloc[0]
miscellaneous_cost_avg = df['miscellaneous_cost_avg Value'].iloc[0]
miscellaneous_cost_std = df['miscellaneous_cost_std Value'].iloc[0]

# Define number of simulations
n_simulations = 10000

# Assumptions with [mean, std deviation]
wheat_seed_cost = [wheat_seed_cost_avg, wheat_seed_cost_std]
soybean_seed_cost = [soybean_seed_cost_avg, soybean_seed_cost_std]
fertilizer_wheat_cost = [fertilizer_wheat_cost_avg, fertilizer_wheat_cost_std]
fertilizer_soybean_cost = [fertilizer_soybean_cost_avg, fertilizer_soybean_cost_std]
labor_cost = [labor_cost_avg, labor_cost_std]
pesticide_cost = [pesticide_cost_avg, pesticide_cost_std]
fuel_maintenance_cost = [fuel_maintenance_cost_avg, fuel_maintenance_cost_std]
miscellaneous_cost = [miscellaneous_cost_avg, miscellaneous_cost_std]

def simulate_farm_costs():
    wheat_seed = np.random.normal(wheat_seed_cost[0], wheat_seed_cost[1])
    soybean_seed = np.random.normal(soybean_seed_cost[0], soybean_seed_cost[1])
    fertilizer_wheat = np.random.normal(fertilizer_wheat_cost[0], fertilizer_wheat_cost[1])
    fertilizer_soybean = np.random.normal(fertilizer_soybean_cost[0], fertilizer_soybean_cost[1])
    labor = np.random.normal(labor_cost[0], labor_cost[1])
    pesticide = np.random.normal(pesticide_cost[0], pesticide_cost[1])
    fuel_maintenance = np.random.normal(fuel_maintenance_cost[0], fuel_maintenance_cost[1])
    miscellaneous = np.random.normal(miscellaneous_cost[0], miscellaneous_cost[1])

    total_cost = (wheat_seed + soybean_seed + fertilizer_wheat + fertilizer_soybean +
                  labor + pesticide + fuel_maintenance + miscellaneous) * 1000  # for 1000 acres

    return total_cost

results = [simulate_farm_costs() for _ in range(n_simulations)]

# Convert results into a dataframe
df_simulated_results = pd.DataFrame(results, columns=['Total Cost'])

# Calculate the Interquartile Range (IQR)
Q1 = df_simulated_results['Total Cost'].quantile(0.25)
Q3 = df_simulated_results['Total Cost'].quantile(0.75)

# Plotting the histogram
plt.figure(figsize=(10, 6))
n, bins, patches = plt.hist(df_simulated_results['Total Cost'], bins=50, color='blue', edgecolor='black', alpha=0.7)
plt.title('Distribution of Year 1 Variable Farm Costs from Simulation')
plt.xlabel('Year 1 Variable Cost')
plt.ylabel('Frequency')
plt.grid(True, which='both', linestyle='--', linewidth=0.5)

# Shade the IQR
for i in range(len(bins)):
    if bins[i] > Q1 and bins[i] < Q3:
        patches[i].set_facecolor('green')

plt.axvline(Q1, color='red', linestyle='dashed', linewidth=1)
plt.axvline(Q3, color='red', linestyle='dashed', linewidth=1)
plt.tight_layout()
plt.savefig('simulated_costs_histogram.png')  # This will save the figure as an image file
plt.show()

只是为了好玩,我们提示 ChatGPT 定义四分位距(IQR)并将其着色为不同的颜色,我们还手动更新了图表标签和 x 轴。其余的只是稍微清理一下 Power BI 中的视觉效果,使其更用户友好。最终结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据由用户选择的参数输入生成的 Monte Carlo 模拟,Python 代码由 ChatGPT 4 生成,仪表板在 MS PowerBI 中构建,图片由作者提供

现在我们有了一个动态的 Monte Carlo 模拟,可以用来测试不同的输入成本假设并预测我们启动农业运营所需的变动运营费用。借助 ChatGPT 4,我们几乎没有编写代码,只是稍微调整了一下,大部分工作通过屏幕共享在 iPhone 上完成,最后一部分在 Power BI desktop 中构建,并通过 Power BI iPhone 应用程序屏幕共享。总共花费了大约 30-40 分钟。

我祖父的评判?“我们在 40 分钟内完成了他自己‘过去’需要 2 年才能完成的工作。” 是的,我意识到我们还有很多*可以做的——*而且“模拟”远非完美。(例如,我们没有区分投入大豆与小麦的作物百分比。)但 40 分钟呢?即使是我也感到印象深刻。这就是生成 AI 的承诺——使数据科学民主化,鼓励实验,并加快在你手掌之间开发的能力。让祖父和孙子有机会通过一些统计数据重新建立联系,并以新的、出乎意料的方式利用技术。

从 Python 到 Julia:基本数据操作和探索性数据分析

原文:towardsdatascience.com/from-python-to-julia-basic-data-manipulation-and-eda-51171b34f685

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 王晟昊

·发表于 Towards Data Science ·阅读时间 7 分钟·2023 年 6 月 20 日

作为统计计算领域的一种新兴编程语言,Julia 近年来获得了越来越多的关注。Julia 有两个特性使其优于其他编程语言。

  • Julia 是一种像 Python 一样的高级语言。因此,它易于学习和使用。

  • Julia 是一种编译语言,设计目标是与 C/C++ 一样快速。

当我第一次了解 Julia 时,我被它的计算速度吸引了。所以我决定尝试一下 Julia,看看我是否可以在日常工作中实际使用它。

作为一名数据科学从业者,我使用 Python 开发各种用途的原型 ML 模型。为了快速学习 Julia,我将模拟我在 Python 和 Julia 中构建简单 ML 模型的常规过程。通过将 Python 和 Julia 代码并排比较,我可以轻松捕捉这两种语言的语法差异。这就是本博客将按以下章节安排的原因。

设置

在开始之前,我们需要先在工作站上安装 Julia。Julia 的安装分为以下 2 步骤。

  • 官方网站 下载安装程序文件。

  • 解压安装程序文件并创建指向 Julia 二进制文件的符号链接。

以下博客提供了安装 Julia 的详细指南。

[## 在 Ubuntu 上安装 Julia

关于如何在 Ubuntu 上安装 Julia 并将内核添加到 Jupyter 的快速教程

medium.com](https://medium.com/coffee-in-a-klein-bottle/install-julia-1-5-on-ubuntu-bb8be4b2571d?source=post_page-----51171b34f685--------------------------------)

数据集

我将使用从 Kaggle 获得的信用卡欺诈检测数据集。该数据集包含 492 个欺诈交易,出现在 284,807 个交易中。共有 30 个特征,包括交易时间、金额,以及通过 PCA 获得的 28 个主成分。交易的“Class”是待预测的目标变量,表示交易是否为欺诈。

类似于 Python,Julia 社区开发了各种包以支持 Julia 用户的需求。这些包可以通过 Julia 的包管理器 Pkg 安装,相当于 Python 的 pip

我使用的欺诈检测数据采用典型的 .csv 格式。要在 Julia 中将 csv 数据加载为数据框,需要导入 CSVDataFrame 包。DataFrame 包可以视为 Julia 中 Pandas 的等价物。

将结构化数据加载为数据框 — Julia 实现

下面是导入的数据的样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

在 Jupyter 中,加载的数据集可以如上图所示。如果您希望查看更多列,一种快速的解决方案是指定环境变量 ENV["COLUMNS"]。否则,最多只会显示不到 10 列。

相应的 Python 实现如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将结构化数据加载为数据框 — Python 实现(作者提供的图片)

探索性数据分析(EDA)

探索性分析允许我们检查数据质量并发现特征之间的模式,这对特征工程和训练 ML 模型非常有用。

基本统计

我们可以从计算特征的一些简单统计数据开始,例如均值、标准差。类似于 Python 中的 Pandas,Julia 的 DataFrame 包提供了 describe 函数来实现这一目的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Julia 中的 describe 函数生成基本统计数据(作者提供的图片)

describe 函数允许我们生成 12 种基本统计数据。我们可以通过更改 :all 参数来选择生成哪一种,例如 describe(df, :mean, :std)。令人有些烦恼的是,如果不指定 :all,即使设置了显示列的上限,describe 函数也会不断遗漏统计数据的显示。这是 Julia 社区未来可以改进的地方。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Julia 遗漏了指定统计数据的打印 😕(作者提供的图片)

类别平衡

欺诈检测数据集通常存在极端的类别不平衡问题。因此,我们希望了解两个类别之间的数据分布。在 Julia 中,这可以通过应用“split-apply-combine”函数来实现,这等同于 Python 中 Pandas 的“groupby-aggregate”函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检查类别分布——Julia 实现(图像由作者提供)

在 Python 中,我们可以使用value_counts()函数实现相同的目的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检查类别分布——Python 实现(图像由作者提供)

单变量分析

接下来,让我们通过直方图深入了解特征的分布。特别是,我们以交易金额和时间为例,因为它们是数据集中唯一可解释的特征。

在 Julia 中,有一个名为StatsPlots的实用库,允许我们绘制各种常用的统计图表,包括直方图、条形图、箱形图等。

以下代码在两个子图中绘制了交易金额和时间的直方图。可以观察到交易金额高度偏斜。对于大多数交易,交易金额低于 100。交易时间遵循双峰分布。

绘制交易时间和交易金额的分布图——Julia 实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绘制交易时间和交易金额的分布图——Julia 实现(图像由作者提供)

在 Python 中,我们可以使用 matplotlib 和 seaborn 创建相同的图表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绘制交易时间和交易金额的分布图——Python 实现(图像由作者提供)

双变量分析

虽然上述单变量分析展示了交易金额和时间的一般模式,但它并未告诉我们这些与待预测的欺诈标志如何相关。为了快速了解特征与目标变量之间的关系,我们可以创建一个相关矩阵并通过热图进行可视化。

在创建相关矩阵之前,我们需要注意到数据高度不平衡。为了更好地捕捉相关性,需要对数据进行下采样,以避免特征的影响因数据不平衡而被“稀释”。这个过程需要数据框的切片和连接。以下代码演示了 Julia 中下采样的实现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Julia 中的数据下采样(图像由作者提供)

上述代码统计了欺诈交易的数量,并将这些欺诈交易与相同数量的非欺诈交易结合起来。接下来,我们可以创建热图来可视化相关矩阵。

绘制热图以可视化相关矩阵——Julia 实现

结果热图如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由 Julia 绘制的特征相关性热图(图像由作者提供)

这里是 Python 中的下采样和热图绘制的等效实现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下采样和绘制相关性热图 — Python 实现(图片由作者提供)

在对特征相关性进行概述后,我们希望深入研究与目标变量(在本例中为“Class”)显著相关的特征。从热图中可以观察到,以下经过 PCA 转换的特征与“Class”具有正相关关系:V2、V4、V11、V19,而具有负相关关系的特征包括 V10、V12、V14、V17。我们可以使用箱线图来检查这些突出特征对目标变量的影响。

在 Julia 中,可以使用上述的 StatsPlots 包来创建箱线图。在这里,我使用与“Class”正相关的 4 个特征作为示例来说明如何创建箱线图。

创建箱线图以可视化特征对“Class”的影响 — Julia 实现

@df 作为宏,用于表示在目标数据集上创建箱线图,即 balanced_df。结果图如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特征与“Class”之间的正相关箱线图(图片由作者提供)

以下代码可以用来在 Python 中创建相同的箱线图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建箱线图以可视化特征对“Class”的影响 — Python 实现(图片由作者提供)

插曲

在此,我将暂停,并简要评论一下我迄今为止使用 Julia 的“用户体验”。就语言语法而言,Julia 似乎介于 Python 和 R 之间。Julia 包提供了对数据处理和探索性数据分析(EDA)各种需求的全面支持。然而,由于 Julia 的发展仍处于早期阶段,这种编程语言仍然缺乏资源和社区支持。寻找某些数据处理练习的 Julia 实现,如 展开类似列表的数据框列,可能需要花费很多时间。此外,Julia 的语法远未稳定,如 Python 3。此时,我不会说 Julia 是大型企业和企业的良好编程语言选择。

我们还未完成构建欺诈检测模型的工作。我将在下一篇博客中继续,敬请关注!

Jupyter notebook 可以在 Github 上找到。

参考文献

从 Python 到 Julia:特征工程与机器学习

原文:towardsdatascience.com/from-python-to-julia-feature-engineering-and-ml-d55e8321f888?source=collection_archive---------11-----------------------#2023-06-26

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 CardMapr.nl 提供,Unsplash 上的

基于 Julia 的欺诈检测模型构建方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 王胜浩

·

关注 发表在 Towards Data Science ·6 分钟阅读·2023 年 6 月 26 日

这是我关于如何使用 Julia 进行应用数据科学的两部分系列中的第二部分。在 第一篇文章 中,我们回顾了几个简单的数据操作示例以及使用 Julia 进行的探索性数据分析。在本博客中,我们将继续构建一个欺诈检测模型以识别欺诈性交易。

简要回顾,我们使用了从 Kaggle 获取的 信用卡欺诈检测数据集。该数据集包含 30 个特征,包括交易时间、金额和 28 个通过 PCA 获得的主成分特征。下面是数据集前 5 个实例的截图,以数据框的形式加载到 Julia 中。请注意,交易时间特征记录了当前交易与数据集中第一笔交易之间的经过时间(以秒为单位)。

特征工程

在训练欺诈检测模型之前,让我们准备好供模型使用的数据。由于本博客的主要目的是介绍 Julia,因此我们不会在此进行特征选择或特征合成。

数据划分

在训练分类模型时,数据通常以分层的方式进行训练和测试划分。主要目的是在训练数据和测试数据中保持数据相对于目标类变量的分布。这在处理极度不平衡的数据集时尤其必要。MLDataUtils 包在 Julia 中提供了一系列预处理函数,包括数据划分、标签编码和特征归一化。以下代码展示了如何使用 MLDataUtilsstratifiedobs 函数进行分层抽样。可以设置随机种子以便重现相同的数据划分。

数据划分用于训练和测试 — Julia 实现

stratifiedobs 函数的使用与 Python 中 sklearn 库的 train_test_split 函数非常相似。请注意,输入特征 X 需要经过两次转置以恢复数据集的原始维度。这对于像我这样的 Julia 新手来说可能会令人困惑。我不确定 MLDataUtils 的作者为何这样开发这个函数。

等效的 Python sklearn 实现如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据划分用于训练和测试 — Python 实现(图片来源于作者)

特征缩放

作为机器学习中的推荐实践,特征缩放将特征调整到相同或类似的值范围或分布。特征缩放有助于提高训练神经网络时的收敛速度,并且避免了在训练过程中某个特征的主导地位。

尽管我们在这项工作中没有训练神经网络模型,但我仍然想了解如何在 Julia 中进行特征缩放。不幸的是,我找不到一个同时提供缩放器拟合和特征变换功能的 Julia 库。特征归一化函数由 MLDataUtils 包提供,允许用户推导特征的均值和标准差,但不能方便地应用于训练/测试数据集以进行特征变换。由于特征的均值和标准差可以在 Julia 中轻松计算,我们可以手动实现标准缩放过程。

以下代码创建了 X_train 和 X_test 的副本,并在循环中计算每个特征的均值和标准差。

标准化特征 — Julia 实现

变换后的特征和原始特征如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

缩放后的特征与原始特征 — Julia 实现(图像作者提供)

在 Python 中,sklearn 提供了多种特征缩放选项,包括归一化和标准化。通过声明一个特征缩放器,可以用两行代码完成缩放。以下代码展示了如何使用一个RobustScaler的示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对特征进行鲁棒缩放 — Python 实现(图像作者提供)

过采样(通过 PyCall)

欺诈检测数据集通常严重不平衡。例如,我们的数据集中负样本与正样本的比例超过了 500:1。由于无法获取更多的数据点,欠采样将导致多数类数据点的大量丢失,在这种情况下,过采样成为最佳选择。在这里,我使用了流行的 SMOTE 方法来为正类创建合成样本。

目前,没有可用的 Julia 库提供 SMOTE 的实现。ClassImbalance 包已经有两年未维护,无法与最近的 Julia 版本兼容。幸运的是,Julia 允许我们使用一个名为PyCall的包装库来调用现成的 Python 包。

要将 Python 库导入 Julia,我们需要安装 PyCall 并将 PYTHONPATH 指定为环境变量。我尝试创建一个 Python 虚拟环境,但没有成功。由于某种原因,Julia 无法识别虚拟环境的 Python 路径。因此,我不得不指定系统默认的 Python 路径。之后,我们可以导入由imbalanced-learn库提供的 Python 实现的 SMOTE。PyCall 提供的 pyimport 函数可以用于在 Julia 中导入 Python 库。以下代码展示了如何在 Julia 内核中激活 PyCall 并寻求 Python 的帮助。

使用 SMOTE 进行上采样训练数据 — Julia 实现

相应的 Python 实现如下。我们可以看到,fit_resample 函数在 Julia 中的用法是相同的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 SMOTE 进行上采样训练数据 — Python 实现(图片由作者提供)

模型训练

现在我们进入模型训练阶段。我们将训练一个二分类器,这可以通过多种机器学习算法完成,包括逻辑回归、决策树和神经网络。目前,Julia 中的机器学习资源分布在多个 Julia 库中。让我列出几个最受欢迎的选项及其专业化的模型。

在这里,我选择了XGBoost,考虑到它的简洁性和在传统回归及分类问题上的卓越表现。训练 XGBoost 模型的过程在 Julia 中与 Python 相同,尽管语法上有一些小的差异。

使用 XGBoost 训练欺诈检测模型 — Julia 实现

相应的 Python 实现如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 XGBoost 训练欺诈检测模型 — Python 实现(图片由作者提供)

模型评估

最后,让我们通过查看在测试数据上获得的精度、召回率,以及训练模型所花费的时间来评估模型的表现。在 Julia 中,精度、召回率指标可以通过EvalMetrics库计算。另一个可以实现相同目的的包是MLJBase

进行预测和计算指标 — Julia 实现

在 Python 中,我们可以使用 sklearn 来计算指标。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进行预测和计算指标 — Python 实现(图片由作者提供)

那么 Julia 和 Python 哪个是赢家?为了公平比较,两种模型都使用默认超参数进行训练,学习率 = 0.1,估算器数量 = 1000。性能指标总结在下面的表格中。

可以观察到,Julia 模型在训练时间稍长的情况下,达到了更好的精确度和召回率。由于用于训练 Python 模型的 XGBoost 库底层是用 C++ 编写的,而 Julia XGBoost 库完全用 Julia 编写,Julia 的运行速度确实与 C++ 一样快,就像它所声称的那样!

用于上述测试的硬件:第 11 代 Intel® Core™ i7–1165G7 @ 2.80GHz — 4 核心。

Jupyter notebook 可以在 Github 找到。

收获

我想以对不同数据科学任务的 Julia 库的总结结束这一系列内容。

由于缺乏社区支持,目前 Julia 的可用性无法与 Python 相比。然而,鉴于其优越的性能,Julia 仍然在未来具有很大的潜力。

参考文献

从 RAG 到财富

原文:towardsdatascience.com/from-rags-to-riches-53ba89087966?source=collection_archive---------4-----------------------#2023-10-25

向量搜索在深入理解您的数据和模型中的 10 种应用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Jacob Marks, Ph.D.

·

关注 发表在 Towards Data Science ·10 min read·2023 年 10 月 25 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

向量搜索用于数据探索的艺术效果图。图像由 DALLE-3 生成。

随着大型语言模型(LLMs)席卷全球,向量搜索引擎也随之而来。向量数据库构成了 LLMs 长期记忆系统的基础。

通过高效地查找相关信息并将其作为上下文输入到语言模型中,向量搜索引擎可以提供超出训练截止日期的最新信息,并在不进行微调的情况下提高模型输出的质量。这个过程,通常称为检索增强生成(RAG),将曾经晦涩的近似最近邻(ANN)搜索算法挑战推向了聚光灯下!

在所有的喧嚣中,人们可能会误以为向量搜索引擎与大型语言模型不可分割。但事实远不止于此。向量搜索有许多强大的应用,远远超出了改善 RAG 对 LLMs 的应用!

在这篇文章中,我将展示我最喜欢的十种向量搜索的应用,用于数据理解、数据探索、模型解释等。

以下是我们将涵盖的应用,按复杂度大致递增的顺序:

  • 图像相似性搜索

  • 反向图像搜索

  • 对象相似性搜索

  • 强健的 OCR 文档搜索

  • 语义搜索

  • 跨模态检索

  • 探测感知相似性

  • 比较模型表示

  • 概念插值

  • 概念空间遍历

图像相似性搜索

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对来自 Oxford-IIIT Pet 数据集的图像进行相似性搜索 (LICENSE). 图片由作者提供。

也许最简单的起点是图像相似性搜索。在这个任务中,你有一个由图像组成的数据集——这可以是个人照片集,也可以是数以亿计的图像仓库,这些图像由数千个分布式相机拍摄,历时多年。

设置很简单:计算数据集中每张图像的嵌入向量,并从这些嵌入向量生成一个向量索引。在这初始批次计算之后,不需要进一步的推断。探索数据集结构的一个好方法是选择数据集中的一张图像,并查询向量索引获取 k 个最近邻——最相似的图像。这可以直观地了解查询图像周围图像空间的密度。

欲了解更多信息和示例代码,请见 这里

反向图像搜索

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对来自 Unsplash 的图像进行反向图像搜索 (图片由 Mladen Šćekić 提供),与* Oxford-IIIT Pet 数据集进行对比。图片由作者提供。

类似地,图像相似性搜索的自然延伸是找到数据集中与外部图像最相似的图像。这可以是来自本地文件系统的图像,也可以是来自互联网的图像!

要执行反向图像搜索,你需要像图像相似性搜索示例那样创建数据集的向量索引。不同之处在于运行时,你计算查询图像的嵌入向量,然后用这个向量查询向量数据库。

欲了解更多信息和示例代码,请参见 这里

对象相似性搜索

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

COCO-2017 数据集的验证分割中进行羊的对象相似性搜索 (LICENSE)。图片由作者提供。

如果你想深入研究图像中的内容,那么对象或“补丁”相似性搜索可能正是你所追求的。例如,人物再识别就是其中之一,在这种情况下,你有一张包含目标人物的单一图像,你想在数据集中找到所有该人的实例。

人物可能只占据每张图像的小部分,因此这些图像中包含的整个图像的嵌入可能会强烈依赖于这些图像中的其他内容。例如,图像中可能有多个人。

更好的解决方案是将每个对象检测补丁视为一个独立的实体,并为每个补丁计算嵌入。然后,使用这些补丁嵌入创建一个向量索引,并针对你想要重新识别的人的补丁进行相似性搜索。作为起点,你可能想尝试使用 ResNet 模型。

这里有两个细微之处:

  1. 在向量索引中,你需要存储元数据,将每个补丁映射回数据集中的相应图像。

  2. 你需要运行一个对象检测模型来生成这些检测补丁,然后再实例化索引。你可能还想仅为某些对象类别(如person)计算补丁嵌入,而不是其他类别——chairtable等。

欲了解更多信息和示例代码,请参见 这里

强大的 OCR 文档搜索

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过 Tesseract OCR 引擎生成的博士论文页面上的文本块进行模糊/语义搜索。使用 GTE-base 模型计算的嵌入。图片由作者提供。

光学字符识别(OCR)是一种允许你数字化文档的技术,如手写笔记、旧期刊文章、医疗记录以及那些藏在你衣柜里的情书。像 TesseractPaddleOCR 这样的 OCR 引擎通过识别图像中的单个字符和符号并创建连续的“文本块”来工作——想象成段落。

一旦你有了这些文本,你可以对预测的文本块进行传统的自然语言关键词搜索,如这里所示。然而,这种搜索方法容易受到单字符错误的影响。如果 OCR 引擎错误地将“l”识别为“1”,那么对“control”的关键词搜索将失败(这真是有趣!)。

我们可以通过使用向量搜索来克服这个挑战!使用像GTE-base这样的文本嵌入模型将文本块嵌入,并创建一个向量索引。然后,我们可以通过嵌入搜索文本并查询该索引,对我们的数字化文档进行模糊和/或语义搜索。从高层次来看,这些文档中的文本块类似于目标相似性搜索中的目标检测补丁!

欲了解更多信息和示例代码,请见这里

语义搜索

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用自然语言在 COCO 2017 验证数据集上进行语义图像搜索。图像由作者提供。

使用多模态模型,我们可以将语义搜索的概念从文本扩展到图像。像CLIPOpenCLIPMetaCLIP这样的模型被训练以找到图像及其标题的共同表示,因此一张狗的图像的嵌入向量将与“狗的照片”这一文本提示的嵌入向量非常相似。

这意味着创建一个由 CLIP 嵌入生成的图像向量索引,并使用该向量数据库进行向量搜索是合理的(即我们“被允许”这样做),其中查询向量是文本提示的 CLIP 嵌入。

💡通过将视频中的每一帧视作图像,并将每帧的嵌入添加到向量索引中,你还可以对视频进行语义搜索

欲了解更多信息和示例代码,请见这里

跨模态检索

跨模态检索与输入音频文件匹配的图像。使用 ImageBind 和 Qdrant 向量索引实现,基于 COCO 2017 验证数据集。视频由作者提供。

从某种意义上说,对图像数据集进行语义搜索是一种跨模态检索。一个概念化的方法是我们正在检索与文本查询对应的图像。使用像ImageBind这样的模型,我们可以更进一步!

ImageBind 将来自六种不同模态的数据嵌入到同一嵌入空间中:图像、文本、音频、深度、热成像和惯性测量单元(IMU)。这意味着我们可以为任何这些模态的数据生成一个向量索引,并用这些模态中的任何其他样本来查询该索引。例如,我们可以用一段汽车鸣笛的音频片段来检索所有汽车的图像!

欲了解更多信息和工作代码,请查看这里

探测感知相似性

在向量搜索故事中,我们迄今为止只略微提及了一个非常重要的部分,那就是模型。我们向量索引中的元素是来自模型的嵌入。这些嵌入可以是定制嵌入模型的最终输出,也可以是从另一个任务(如分类)训练的模型中提取的隐藏或潜在表示。

无论如何,我们用来嵌入样本的模型可以对哪些样本被认为是最相似的样本产生重大影响。CLIP 模型捕捉语义概念,但在表示图像中的结构信息方面存在困难。另一方面,ResNet 模型非常擅长表示结构和布局的相似性,操作在像素和补丁的层面上。然后,还有像DreamSim这样的嵌入模型,旨在弥合差距,捕捉中级相似性 — 将模型的相似性概念与人类的感知对齐。

向量搜索为我们提供了一种探测模型如何“看待”世界的方法。通过为每个我们感兴趣的模型(在相同数据上)创建一个单独的向量索引,我们可以迅速培养对不同模型如何在背后表示数据的直觉。

下面是一个示例,展示了在 NIGHTS 数据集中,使用 CLIP、ResNet 和 DreamSim 模型嵌入进行相似性搜索的情况:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 ResNet50 嵌入进行图像相似性搜索,在NIGHTS 数据集中(图像由 Stable Diffusion 生成 — MIT RAIL LICENSE)。ResNet 模型在像素和补丁的层面上操作。因此,检索到的图像在结构上类似于查询图像,但在语义上不一定相似。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 CLIP 嵌入进行相似性搜索,基于相同的查询图像。CLIP 模型尊重图像的基本语义,但不关注其布局。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 DreamSim 嵌入进行相似性搜索,基于相同的查询图像。DreamSim 弥合了语义和结构特征之间的差距,寻找最佳的中级相似性折衷。

欲了解更多信息和工作代码,请查看这里

比较模型表示

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对比 ResNet50 和 CLIP 模型在 NIGHTS 数据集上的表示。ResNet 嵌入通过 UMAP 降维到 2D。选择嵌入图中的一个点并突出显示附近的样本,我们可以看到 ResNet 如何捕捉组成和色彩相似性,而不是语义相似性。对选定样本使用 CLIP 嵌入进行向量搜索,我们可以看到根据 CLIP 的结果,大多数样本在 ResNet 中并没有局部化。

我们可以通过结合向量搜索和降维技术,如均匀流形逼近 (UMAP),获得对两个模型差异的新见解。操作方法如下:

每个模型的嵌入包含了模型如何表示数据的信息。使用 UMAP(或 t-SNE 或 PCA),我们可以生成来自 model1 的低维(2D 或 3D)表示。这样做虽然牺牲了一些细节,但希望保留了样本之间的相似性信息。我们获得的是可视化这些数据的能力。

以 model1 的嵌入可视化为背景,我们可以在这个图中选择一个点,并对该样本执行一个针对 model2 嵌入的向量搜索查询。然后你可以看到检索到的点在 2D 可视化中的位置!

上述示例使用了与上一节相同的 NIGHTS 数据集,视觉化 ResNet 嵌入,捕捉更多的组成和结构相似性,并用 CLIP(语义)嵌入进行相似性搜索。

概念插值

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 CLIP 嵌入在 Oxford-IIIT 宠物数据集上进行“哈士奇”和“吉娃娃”概念的插值

我们接近这十个应用的尾声,但幸运的是,我把一些最佳的留到了最后。到目前为止,我们处理的唯一向量是嵌入—向量索引中填充了嵌入,查询向量也是嵌入。但有时在嵌入的空间中还有额外的结构,我们可以利用这些结构以更动态的方式与数据互动。

这种动态交互的一个例子是我喜欢称之为“概念插值”。操作方法如下:拿一个图像数据集,使用多模态模型(文本和图像)生成一个向量索引。选择两个文本提示词,比如“晴天”和“雨天”,这两个词代表了不同的概念,并设置一个在 [0,1] 范围内的值 alpha。我们可以为每个文本概念生成嵌入向量,并将这些向量按照 alpha 指定的线性组合方式相加。然后我们对这个向量进行归一化,并将其作为查询向量用于我们的图像嵌入向量索引。

因为我们在对两个文本提示(概念)的嵌入向量进行线性插值,从很大程度上说,我们在插值这些概念本身!我们可以动态改变alpha并在每次交互时查询我们的向量数据库。

💡这种概念插值的想法是实验性的(即:并不总是明确的操作)。我发现当文本提示在概念上相关且数据集足够多样化,以便在插值范围内产生不同结果时,它效果最佳。

欲了解更多信息和示例代码,请参见 这里

概念空间遍历

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过其嵌入在“概念”空间中移动,以各种文本提示的方向进行遍历,示例为 COCO 2017 数据集的测试拆分。图像和文本由 CLIP 模型嵌入。图像由作者提供。

最后但同样重要的是,我喜欢称之为“概念空间遍历”。与概念插值类似,首先用像 CLIP 这样的多模态模型生成图像的嵌入。接着,从数据集中选择一张图像。这张图像将作为你的起点,你将“遍历”概念空间。

从那里,你可以通过提供一个文本字符串作为概念的替代来定义你想要移动的方向。设置你想在该方向上迈出的“步长”,并将该文本字符串的嵌入向量(带有乘法系数)加到初始图像的嵌入向量上。将使用“目标”向量来查询向量数据库。你可以添加任意数量的概念,并实时查看检索到的图像集的更新。

与“概念插值”一样,这并不总是一个严格定义的过程。然而,我发现它很迷人,当应用于文本嵌入的系数足够高时,它表现得相当好。

欲了解更多信息和示例代码,请参见 这里

结论

向量搜索引擎是极其强大的工具。当然,它们是RAG时代最佳演出的明星。但向量数据库远比这更为多功能。它们使我们对数据有更深刻的理解,提供有关模型如何表示这些数据的见解,并为我们与数据互动提供了新的途径。

向量数据库并不局限于 LLMs。只要涉及到嵌入,向量数据库就会显得非常有用,而嵌入恰好位于模型数据的交汇处。我们对嵌入空间结构的理解越深入,我们的向量搜索驱动的数据和模型交互就会变得越动态和普遍。

如果你觉得这篇文章有趣,你可能还想看看这些由向量搜索驱动的文章:

  • 🔗 如何将我的公司文档转化为可搜索的数据库与 OpenAI

  • 🔗 如何将 ChatGPT 转变为类似 SQL 的图像和视频数据集翻译器

  • 🔗 我在推动 Prompt Engineering 极限中学到的东西

从 SQL 到 Julia:数据科学的其他编程语言

原文:towardsdatascience.com/from-sql-to-julia-data-sciences-other-programming-languages-ff11ae2f0c20?source=collection_archive---------3-----------------------#2023-07-27

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 TDS Editors

·

关注 发表在 Towards Data Science · 发送为 新闻通讯 · 3 分钟阅读 · 2023 年 7 月 27 日

Python 可能是数据科学家和机器学习从业者的主流编程语言,但成为编程多语种高手的好处越来越明显。数据团队所做的项目跨越多个平台和架构,能够切换到不那么常见但有时更高效的语言,可以成为一个强大的优势。

本周的重点文章涵盖了广泛的内容:它们关注多种语言、项目和工作流程。这些帖子邀请你卷起袖子,开始尝试一些代码——它们可能会激发你进一步扩展知识。

  • 数据库查询语言 SQL 并不陌生;它已经存在了几十年,并且仍然是许多数据工作者进入编码的常见途径。伊法特·马利克·戈尔 对窗口函数的概述是SQL 词汇的核心元素的极佳介绍(或复习)

  • 如果你的工作涉及大量统计数据,你可能已经在实际工作中遇到过 R。尽管 R 的使用场景可能比你想象的更为广泛,珍娜·伊格尔森 通过一个有用的实操教程,展示了如何使用 R来解决人力分析中的常见挑战。

  • Python 库在数据可视化领域占据主导地位,以至于你可能会忘记其他语言也能创建精美的图表。马哈茂德·哈穆赫Rust 的可视化选项进行了深入探讨,重点关注 Plotters 库及其强大的功能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 马克斯·斯皮斯基 提供,来源于 Unsplash

  • 无论你使用什么编程语言,准备数据以便于分析或建模项目都是至关重要的步骤。艾玛·布德罗 带我们了解了在 Julia 中进行数据筛选的过程——一种在近年来数据科学家中爆炸性增长的相对小众语言

  • 版本控制是任何软件开发过程中的重要组成部分,而 Git 尽管不是编程语言本身,却是处理和协作代码的首选系统。如果您还处于编码旅程的早期阶段,阅读 Khuyen Tran数据科学家的全面 Git 使用指南 是一个明智的下一步。

为了拓宽您的视野,我们很高兴分享我们近期的几篇亮点文章:

  • 初创企业生态系统如何应对 AI 快速增长的影响?Viggy Balagopalakrishnan 提供了基于最新 Y Combinator 批次的 敏锐洞察。

  • Lambert T Leong 博士 展示了 在医疗保健与深度学习交汇处的最新研究,旨在基于体成分成像预测全因死亡率。

  • 如果您听说过 Code Interpreter 这个 ChatGPT 插件,且 想看看所有的热议内容,Natassha Selvaraj 的项目演示是必看的。

  • 如需了解 大数法则的清晰、透彻且引人入胜的解释 及其工作原理,不要错过 Sachin Date 的新深度解析。

  • 如果每天有数十亿人使用生成 AI 工具,会带来 什么样的环境影响?Kasper Groes Albin Ludvigsen 探讨了一个棘手、及时且重要的问题。

感谢您支持我们的作者!如果您喜欢在 TDS 阅读的文章,可以考虑 成为 Medium 会员 —— 这将解锁我们的所有档案(以及 Medium 上的其他所有文章)。

我们希望许多人也在 计划参加 Medium Day,在 8 月 12 日庆祝社区及其使之特别的故事——注册(免费)现已开放

直到下次 Variable,

TDS 编辑部

从感知机到 Adaline

原文:towardsdatascience.com/from-the-perceptron-to-adaline-1730e33d41c5?source=collection_archive---------6-----------------------#2023-11-28

奠定基础

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Pan Cretan

·

关注 发表在 Towards Data Science ·11 min read·Nov 28, 2023

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Einar Storsul 提供,来源于 Unsplash

介绍

在上一篇文章中,我尝试解释了可能存在的最基本的二元分类器,Rosenblatt 的感知机。理解这个算法具有教育价值,可以作为初级机器学习课程的良好介绍。这是一个可以在一个下午从零开始编写的算法,并且能够激发兴趣、成就感和深入研究更复杂主题的动力。然而,作为一个算法,它仍然有很多不足,因为只有在类是线性可分的情况下才能保证收敛,这种情况往往不会发生。

在本文中,我们将继续掌握分类概念的旅程。从 Rosenblatt 的感知机自然演变而来的就是自适应 线性 神经分类器,俗称 adaline。从感知机到 adaline 的过渡并不是一个大的飞跃。我们只需将阶跃激活函数更改为线性激活函数。这一小的变化导致了一个连续的损失函数,可以被稳健地最小化。这使我们能够引入机器学习中的许多有用概念,如向量化和优化方法。

在未来的文章中,我们还将讨论激活函数和损失函数的进一步细微变化,这将使我们从 adaline 过渡到逻辑回归,这已经是日常实践中的有用算法。上述所有算法本质上都是单层神经网络,并且可以很容易地扩展到多层神经网络。在这方面,本文将读者带到了这次进化的下一步,并为处理更高级的概念奠定基础。

我们需要一些公式。我使用了在线的LaTeX 方程编辑器来开发方程的 LaTeX 代码,然后使用 Chrome 插件数学方程随处可用将方程渲染成图片。这种方法的唯一缺点是 LaTeX 代码不会被存储,以备将来需要再次渲染时使用。为此,我在本文末尾提供了方程列表。如果你对 LaTex 不熟悉,这可能有其自身的教育价值。正确的符号表示是机器学习旅程的一部分。

自适应线性神经分类器(adaline)

那么 adaline 算法是什么呢?Adaline 是一个像感知机一样的二元分类器。通过使用一组特征[x₁, … , xₘ]的输入值来进行预测,其中 m 是特征的数量。输入值与权重[w₁, … , wₘ]相乘,并加上偏置,以得到净输入 z = w₁x₁ + … + wₘxₘ + b。净输入通过线性激活函数σ(z),然后使用阶跃函数进行预测,与感知机类似:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

与感知器的一个关键区别在于,线性激活函数用于学习权重,而阶跃函数仅用于最终的预测。这听起来是件小事,但它具有重要意义。线性激活函数是可微分的,而阶跃函数则不是!上面的阈值 0.5 并非一成不变。通过调整阈值,我们可以根据我们的使用案例调整精确度和召回率,即根据假阳性和假阴性的成本。

在 adaline 的情况下,线性激活函数就是恒等函数,即 σ(z) = z。需要在训练过程中最小化的目标函数(也称为损失函数)是

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 w 是权重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并且 b 是偏置。求和是在训练集中的所有示例上进行的。在一些实现中,损失函数还包括 1/2 系数以便于计算。这个系数在我们对损失函数关于权重和偏置的梯度进行求导时会被抵消,并且正如我们下面将看到的,它除了将学习率缩放两倍外没有其他影响。在本文中,我们不使用 1/2 系数。

对于每个示例,我们计算计算结果与真实类标签之间的平方差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

以及真实类标签。注意,输入向量被理解为形状为 (1, m) 的矩阵,即正如我们稍后将看到的,是我们的特征矩阵x的一行,其形状为 (n, m)。

训练不过是一个优化问题。我们需要调整权重和偏置,使损失函数最小化。与任何最小化问题一样,我们需要计算目标函数对独立变量的梯度,在我们的情况下,这些变量将是权重和偏置。损失函数关于权重 wⱼ 的偏导数是

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后一行引入了重要的矩阵符号。特征矩阵 x 的形状为 (n, m),我们对其第 j 列取转置,即形状为 (1, n) 的矩阵。真实类标签 y 是一个形状为 (n, 1) 的矩阵。所有样本的净输出 z 也是一个形状为 (n, 1) 的矩阵,激活应用于其每个元素后不会改变。上述公式的最终结果是一个标量。你能猜出我们如何使用矩阵符号表示所有权重的梯度吗?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特征矩阵的转置形状为 (m, n)。此操作的最终结果是一个形状为 (m, 1) 的矩阵。这种表示法非常重要。我们将使用 numpy 进行这种矩阵乘法,而不是使用循环。在神经网络和 GPU 时代,应用向量化的能力至关重要!

那么损失函数关于偏差的梯度如何呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中横线表示向量的均值。再次强调,使用 numpy 计算均值是一个向量化操作,即求和不需要使用循环实现。

一旦我们得到梯度,就可以使用梯度下降优化方法来最小化损失。权重和偏差项会使用以下公式迭代更新

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 η 是合适选择的学习率。值过小可能会延迟收敛,而值过高则可能完全阻止收敛。需要进行一些实验,这通常是机器学习算法参数调整的一部分。

在上述实现中,我们假设权重和偏差是基于所有样本一起更新的。这被称为全批量梯度下降,是一种极端情况。另一种极端情况是每处理一个训练样本后更新权重和偏差,这被称为随机梯度下降(SGD)。实际上,还有一些中间情况,称为小批量梯度下降,其中权重和偏差是基于样本的子集进行更新的。通常,这种方法收敛速度更快,即我们不需要对整个训练集进行过多的迭代,同时向量化仍然(至少部分地)是可能的。如果训练集非常大(或者模型非常复杂,如现在 NLP 中的变换器),全批量梯度下降可能根本不可行。

替代的公式化和闭式解

在我们继续用 Python 实现 adaline 之前,我们将稍作岔开。我们可以将偏差 b 吸收到权重向量中,如下所示

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这种情况下,训练集中所有样本的净输出变为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这意味着特征矩阵前面加了一列全是 1,从而导致形状为 (n, m+1)。关于组合权重集的梯度变为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

原则上,我们可以推导出一个闭式解,因为在最小值时所有梯度都将为零

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实际上,上述方程中的矩阵的逆可能不存在,可能是因为奇异性,或者无法足够准确地计算。因此,这种封闭形式的解决方案在实践中不被使用,无论是在机器学习中还是在数值方法中。然而,了解 adeline 类似于线性回归,并且具有封闭形式的解决方案仍然很有用。

在 Python 中实现 adeline

我们的实现将使用小批量梯度下降。然而,该实现具有灵活性,可以使用随机梯度下降和全批量梯度下降这两个极端来优化损失函数。我们将通过改变批量大小来检查收敛行为。

我们使用一个类来实现 adeline,该类在通常的scikit-learn API 样式中暴露了 fit 和 predict 函数。

在初始化时,adeline 分类器设置了小批量梯度下降的批量大小。如果批量大小设置为 None,则使用整个训练集(全批量梯度下降);否则,训练集将分批使用(小批量梯度下降)。如果批量大小为 1,我们实际上回到了随机梯度下降。在每次训练集遍历之前,训练集会被打乱,以避免重复周期,但这仅在使用小批量梯度下降时才会产生效果。算法的核心在于_update_weights_bias函数,该函数完成对训练集的完整遍历,并返回相应的损失。此函数应用了梯度下降法,使用先前章节中的导数计算的梯度。注意使用 numpy 的matmuldot函数,避免了显式循环。如果批量大小设置为 None,则完全没有循环,且实现完全矢量化。

实践中使用 adeline

我们进行必要的导入,并创建一个合成数据集,如之前感知器的文章中所示。

这产生了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

合成数据集中两个类别的散点图。作者提供的图像。

与早期文章的唯一区别是我们调整了高斯均值和协方差,使得类别不是线性可分的,因为我们希望 adeline 能够克服这一点。此外,两个独立变量故意具有不同的尺度,以讨论特征缩放的重要性。

让我们尝试拟合第一个模型并可视化收敛情况。在拟合之前,我们对特征进行归一化,使其均值为零且标准差为单位。

这产生了收敛图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Adaline 收敛。作者提供的图像。

Adaline 缓慢收敛,但损失函数不会变为零。为了验证训练的成功,我们使用与早期文章相同的方法可视化决策边界。

产生

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

拟合的 Adaline 模型的决策边界。图片由作者提供。

由于训练集中的两个类别不可线性分开且我们使用了线性决策边界,因此存在一些分类错误的点。尽管如此,算法还是良好地收敛了。该解决方案是确定性的。通过足够多的训练集轮次,我们可以获得数值上相等的权重和偏置,无论它们的初始值如何。

迷你批量与全批量梯度下降

上述数值实验使用了全批量梯度下降,这部分解释了缓慢收敛的原因。我们将使用与之前相同的数据集和随机状态,但这次我们将使用不同的批量大小来拟合 Adaline 分类器,范围从 20 到 400,即我们训练集中的样本数量。

产生

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

批量大小对收敛的影响(使用 0.001 学习率)。图片由作者提供。

我们可以清楚地看到,批量大小越小,收敛越快,但也会有一些震荡。这些震荡可能会在较大的学习率下使收敛不稳定。如果将学习率加倍到 0.002,这一点就会变得明显。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

批量大小对收敛的影响(使用 0.002 学习率)。图片由作者提供。

进一步增加学习率最终会阻止较小批量大小的收敛。即使使用更大的学习率,即使是全批量梯度下降也会因为超越全局最小值而无法收敛。

结论

Adaline 相比于感知机有了显著的改进。权重和偏置通过最小化一个连续的损失函数来获得,该函数是凸的(因此没有局部极小值)。使用足够小的学习率,即使类别不能线性分开,算法也会收敛。当使用梯度下降及其任何变体时,特征的缩放会影响收敛速度。在这篇文章中,我们使用了简单的标准化,将每个特征的均值调整为零,同时将方差调整为单位方差。通过这种方式,可以选择一个对所有权重和偏置都适用的学习率,这意味着可以在更少的轮次中获得全局最小值。

在深入研究更复杂的主题,如支持向量机和多层神经网络之前,理解如何利用向量化构建二分类器是关键。在日常实践中,可以使用 scikit-learn,它提供了先进的分类算法,允许非线性决策边界,并支持高效和系统的超参数调整及交叉验证。然而,从零开始构建简单的二分类器能够提供深入的理解、增强自信并带来掌控感。虽然从头开始构建所有内容显然是不现实的,但深入理解简单算法能提供必要的技能和洞察力,使得从现成库中包含的更高级算法显得不那么神秘。

文章中使用的方程的 LaTeX 代码

文章中使用的方程可以在下面的 gist 中找到,以便你可以再次渲染它们。

MLE、MAP 和贝叶斯推断的全面解释

原文:towardsdatascience.com/full-explanation-of-mle-map-and-bayesian-inference-1db9a7fb1d2b

介绍最大似然估计、最大后验估计和贝叶斯推断

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Oliver S

·发布于 Towards Data Science ·阅读时间 13 分钟·2023 年 3 月 6 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源于 fabioUnsplash

在这篇文章中,我们将介绍 MLE(最大似然估计)MAP(最大后验估计)贝叶斯推断——这些概念对统计学、数据科学和机器学习等领域至关重要。我们将使用一个不公平的硬币抛掷的例子来解释每种方法,分析并数字推导(对于贝叶斯推断),并展示它们之间的差异。

我们将了解到 MLE 最大化了似然——即选择最大化观察数据似然的参数。MAP 添加了先验,引入了对参数的先验知识——从而弥合了从纯粹的频率派概念到贝叶斯概念的差距 (link). 贝叶斯推断最终给我们提供了最完整的信息,但也是最难执行的:它涉及建模给定数据的参数的完整后验分布——而之前的方法只是给出点估计。

让我们通过正式化这些描述来设定背景:本质上,对于任何类型的学习问题,我们都希望找到一个模型/参数,以尽可能好地描述观察到的数据。我们可以通过找到从观察数据到参数的映射/分布来完全描述和解决这个问题:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通常,这些术语被称为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

给定数据的参数的条件分布称为后验分布——这是我们关注的术语。似然函数是给定特定参数值的数据的条件分布。这——正如其名称所示——描述了在给定选择的参数值下观察到数据的可能性。先验分布描述了我们对参数的信念——即我们在观察到数据之前对它们的预期。最后,证据是一个归一化常数,使得后验分布成为一个“真实”的概率分布。它完全描述了给定的数据,并且通常很难计算或甚至不可计算——这是贝叶斯推断常常困难的主要原因之一。

利用这些见解和公式/符号,我们将介绍最大似然估计(MLE)、最大后验估计(MAP)和贝叶斯推断。但首先,让我们介绍一个我们将在整个演示中使用的问题。

玩具问题:估计不公平硬币的参数

为了展示这些概念,我们将使用抛掷不公平硬币的例子:假设,我们给定一枚硬币,其正面出现的概率为θ,反面出现的概率为1 — θθ对我们来说是未知的,我们希望在实验后估计它。也就是说,我们假设我们拥有或收集了一个抛币的数据集,然后希望使用 MLE、MAP 和贝叶斯推断来为θ找到一个估计值。

在继续之前,让我们描述一个我们在所有后续部分中需要的量:似然函数。抛掷硬币遵循伯努利分布。假设我们抛掷硬币N次,则用Nₕ表示正面的次数,用Nₜ表示反面的次数。

对于此(以及接下来的内容)的一个核心假设是独立性:我们假设,所有的抛币结果是相互独立且同分布的(i.i.d)——这使我们能够将似然函数表示为各个独立似然函数的乘积。特别地,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代入伯努利分布得出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里,我们用一个值为 1 的二元变量表示单次事件(抛硬币)的正面,值为 0 表示反面。

由于对数函数是单调的,并且处理求和往往更为简便,我们应用这一点并重新公式化:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据集

在继续之前,让我们定义一个我们通过抛掷这枚不公平硬币观察到的样本数据集——我们将在接下来的部分中使用它来展示不同方法的结果。

我们将假设我们抛掷了一枚不公平的硬币,真实的θ = 0.3进行了 100 次实验,并观察到 36 次正面和 64 次反面。

最大似然估计(MLE)

现在,让我们来看看我们的第一个感兴趣的概念:MLE。在这里,我们要找到使观察数据的似然最大化的参数集。为此,我们形成似然函数,对参数求导并解根。注意,即使你以前可能不知道这个名称,你很可能已经应用过这个概念——这实际上是大多数机器学习算法的核心。想象一个神经网络来解决回归或分类问题:L2 损失或交叉熵可以被解释为似然,而梯度下降则找到最优解。

因此——让我们取上述似然公式,并找到使其最大化的θ——即求导并将其设为 0:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解 0 和一些较小的重构给出了θ的 MLE 估计:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这也应该从直观上讲得通:参数θ,即硬币正面朝上的概率,在没有其他先验信息或约束的情况下,应该等于观察到的正面结果与总投掷次数的比例。

让我们将此应用于上述介绍的数据集。我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最大后验估计(MAP)

MLE 代表最大化似然——找到解释数据最好的参数值集合,而无需任何先验信息或进一步的约束。现在,我们转向 MAP——这涉及引入一个参数的先验——实际上等同于寻找后验分布的最大值。

MLE 和 MAP 是频率派与贝叶斯概念之间讨论的良好示例。频率派认为概率只是观察随机、可重复事件的结果——而贝叶斯观点则将一切,包括参数,建模为随机变量——这些变量可以根据新证据进行更新。虽然贝叶斯概念(在我看来)通常提供更强大的解决方案,但一个核心的频率派批评是其对先验的需求——这些先验必须来自某处,并且可能是错误的。

进一步说明,将正则化添加到机器学习模型中实际上可以被证明等同于最大后验估计(MAP)(除了上述声明,即没有正则化的模型代表最大似然估计(MLE)概念)。但这一有趣的认识在这里过于深入,我们将专门在未来的文章中讨论。

让我们重新审视引言公式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由于p(x)是一个常数,并且独立于θ,在对θ求导并解 0 时,它会消失。因此,MAP 确实给出了最大化后验分布的θ点估计。我们需要的只是一个先验。我们选择一个贝塔分布,其给定θ的概率密度函数由以下特征描述:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们选择 beta 分布的原因将在下一节讨论(提示:共轭先验)。

为简化起见,我们再次应用对数运算,得到以下问题:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,在形成导数并解出 0 时,我们可以分别考虑每个加数——左侧的我们已经在上面计算过:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在让我们来看右侧的图像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

形成导数得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们现在可以将这两个项结合起来,并解出 0:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一些重构返回 θ 的映射估计:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要应用这个公式,我们首先必须制定我们的先验。假设我们模糊地听说(例如来自硬币制造商)真实的正面概率应该在 0.3 左右,但我们并不确定。

为了建模这个信念,让我们选择一个 α = 4β = 10 的 beta 分布。我们可以通过以下方式绘制这个分布:

import matplotlib.pyplot as plt
from scipy.stats import beta

x = np.linspace(0, 1, 100)
plt.plot(x, beta.pdf(x, 4, 10))
plt.show()

得到以下图形:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的图像

使用这个先验,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

贝叶斯推断

现在,让我们来进行完全的贝叶斯推断,求解完整的后验分布,而不是参数的点估计:也就是说,我们将获得一个以观察数据为条件的参数的概率分布。

首先我们来检查分子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

插入之前介绍的分布和结果,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这引出了之前提到的共轭先验的概念:如果结果分布与先验分布属于同一家族,那么这个先验被称为对似然的共轭先验——这也意味着后验分布也属于同一家族,我们稍后将看到。

现在让我们来看看证据,即分母。这通常是棘手的部分,且往往是不可解的,因为它涉及到对所有可能的参数值进行边际化:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个积分通常很难计算,甚至不可解——这是(精确)贝叶斯推断困难或不可解的主要原因之一。然而,正如我们稍后将看到的,通常我们不会尝试解析解,而是 resort to 各种近似技术,这些技术也能产生令人满意的结果。

在我们的案例中,虽然存在一个解析的闭式解。观察积分,我们发现其内部与上述计算是相同的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

根据我们之前巧妙忽略的Beta 函数的定义,我们观察到这实际上是 Beta 函数在Nₕ+α-1N-Nₕ-1的值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们可以将分子和分母放在一起,得到后验的闭式解:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们看看这个分布的样子,保持我们之前的 beta 先验α = 4β = 10

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像由作者生成

利用关于Beta 分布的现有知识,一个遵循 beta 分布的随机变量X的均值由参数αβ给出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在我们的情况下,这计算结果与 MAP 得到的结果相同,即 0.348。

对于方差,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结果讨论

在本节中,我们将讨论并比较前几节中获得的结果。

MLE估计θ,即硬币正面朝上的概率为 0.36——这正是观察到的正面投掷的相对频率(36 / 100)。这很有道理。在没有其他信息、先验知识的情况下……最能解释数据的参数应为那个反映数据的参数——在我们的案例中为 0.36。

我们的MAP估计为 0.348,这更接近真实值 0.3,并且更接近于先验的模式。这里的最后一点就是造成这种情况的原因:由于我们的先验围绕 0.3 中心,且方差相对较小,这在最终结果中得到了反映。

为了观察这种效果,考虑一个方差更大的先验,例如由α = 2β = 3给出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像由作者生成

在这种情况下,我们的 MAP 估计变为 0.359——这更接近 MLE 值,因为它受到先验的影响较小。

贝叶斯推断返回了完整的后验分布。其模式为 0.348,即与 MAP 估计相同。这是预期之中的,因为 MAP 只是后验分布的点估计解。然而,拥有完整的后验分布能让我们对问题有更多的洞察——我们将在接下来的两节中深入探讨。

后验分布的数值近似

对于这个例子,我们成功找到后验的闭式解,从而分析性地解决了贝叶斯推断问题。然而,正如之前所述,这通常很困难甚至不可行。幸运的是,在实际中,我们不需要,也通常不会尝试分析性地解决这个问题——而是 resort to 一些近似方法。

这里有几种可能性,我们使用了使用 MCMC 方法的数值近似。在链接的文章中,我详细介绍了这一点,因此我在此建议参考更多细节。在这里,我们只是简要总结核心概念:MCMC 方法通过定义一个相对简单的马尔可夫链来工作,从中采样的目标分布是其平稳分布。然后我们跟随这个马尔可夫链,生成N个相关的数据样本——由于平稳特性,这等同于从目标分布中采样。

这里我们现在想应用这个原则,特别是 Metropolis-Hastings 算法,来近似我们之前解析得到的后验分布。

我们可以使用以下代码片段来完成:

import matplotlib.pyplot as plt
import numpy as np
import scipy.stats

THETA_TRUE = 0.3  # True probability for landing heads
# Parameters defining the beta prior distribution
ALPHA_PRIOR = 4
BETA_PRIOR = 10
NUM_SAMPLES = 100000  # Number of MCMC steps

# Fake a dataset which equals the one assumed in the previous sections
D = np.asarray([1] * 36 + [0] * 64)

# Define prior distribution
prior = scipy.stats.beta(ALPHA_PRIOR, BETA_PRIOR)

def likelihood_ratio(theta_1, theta_2):
    return (theta_1 / theta_2) ** np.sum(D == 1) * (
        (1 - theta_1) / (1 - theta_2)
    ) ** np.sum(D == 0)

def norm_ratio(theta_1, theta_2):
    return prior.pdf(theta_1) / prior.pdf(theta_2)

# Step 1
x = np.random.uniform(0, 1)

# Proposal distribution
q = scipy.stats.norm(0, 0.1)

samples = []

for i in range(NUM_SAMPLES):
    # Step 2
    y = x + q.rvs()
    # Step 3
    ratio = likelihood_ratio(y, x) * norm_ratio(y, x)
    p = min(ratio * q.pdf(x - y) / q.pdf(y - x), 1)
    # Step 4
    u = np.random.uniform(0, 1)
    # Step 5
    x = y if u <= p and 0 <= y <= 1 else x
    samples.append(x)

# Plot the sampled posterior distribution
plt.hist(samples, density=True, bins=100)
# Plot the posterior distribution obtained by the analytical solution
x_values = np.linspace(0, 1, 100)
plt.plot(x_values, scipy.stats.beta.pdf(x_values, 36 + ALPHA_PRIOR, 100 - 36 + BETA_PRIOR))

plt.show()

最后两行绘制了采样后验分布(直方图)与计算后验(线)——我们观察到预期的重叠:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者生成的图像

为什么要做贝叶斯推断?

到目前为止,你可能会问这样一个问题:所有展示的方法都给我相同(或非常相似)的后验分布模式——导致我最终总是选择相同的参数。那么为什么还要做这种复杂的贝叶斯推断呢?

在最后一节中,我们将回答这个问题。我们首先解释这带来了什么好处,然后用一个实际的例子来展示这一点。

首先:做贝叶斯推断给了我们更多的信息。我们不仅获得了后验分布的模式,还获得了完整的分布。因此,我们可以检查它,计算其他矩(例如方差),并总体上更好地理解问题。特别是,通过这点我们能够感知不确定性,还可以决定是否拒绝我们解释数据的假设。让我们通过一个例子来演示这一点。

假设我们把硬币分析变成一个“游戏”:我们有两个硬币,必须选择那个公平的,即出现 50:50 的硬币。

游戏节目主持人给你呈现了两个硬币:

  • 硬币 1 被抛掷了 8 次,其中 4 次出现了正面。

  • 硬币 2 被抛掷了 100 次,其中 50 次出现了正面。

初看之下,两者似乎都有大约 50%的概率出现正面。然而,直观上大多数人肯定会选择硬币 2——因为这里我们有一个更大的样本量。聪明的你迅速在脑海中应用了最大后验法。你选择了一个α = β = 2的贝塔分布,为你提供了一个在[0, 1]区间上对称分布,模式为 0.5。

让我们做数学计算并计算θ的 MAP 估计:

  • θ₁ = (4+2-1)/(8+2+2–2)=0.5

  • θ₂= (50+2–1)/(100+2+2–2)=0.5

因此,根据 MAP 方法,两枚硬币的结果完全相同!

让我们绘制贝叶斯推断上得到的两个硬币的完整后验分布:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的图片

现在,根据我们的预期,硬币 2 的后验方差要低得多——这证明我们应该选择它!

结论

在这篇文章中,我们介绍了 MLE(最大似然估计)、MAP(最大后验估计)和贝叶斯推断。我们用一个不公平的硬币作为例子进行演示。

MLE 寻找优化似然的参数。MAP 引入了参数的先验分布,返回最大化完整后验的参数。因此,MLE 和 MAP 都返回点估计。相比之下,贝叶斯推断对完整后验分布进行建模。这通常是一个复杂的任务——但也更强大,因为我们可以深入了解这个分布,例如方差。

本文到此结束。感谢阅读!

备注:

  • 所有图片,除非另有说明,均由作者生成。

  • 本文中的计算示例部分受到这个很棒的教程的启发。

统计学基础:所有数据科学家和分析师应知——带代码——第一部分

原文:towardsdatascience.com/fundamentals-of-statistics-all-data-scientists-analysts-should-know-with-code-part-1-d6ac0f4b99b5

本文是对数据科学家和数据分析师统计学基础的全面概述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Zoumana Keita

·发表于 Towards Data Science ·阅读时间 8 分钟·2023 年 1 月 31 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:Clay BanksUnsplash

动机

构建机器学习模型对于做出预测很酷。然而,当涉及到更好地理解业务问题时,它们并不适用,这需要在统计建模中投入最多的时间。

本文将首先帮助你建立统计学基础的理解,这对数据科学家和数据分析师的日常活动是有益的,以帮助业务做出可操作的决策。它还将指导你通过实际操作,使用 Python 练习这些统计概念。

如果你喜欢视频而不是阅读文章,那么这适合你 👇🏽

总体和样本之间有什么区别?

在开始处理数据之前,让我们首先了解总体和样本的概念。

→ 一个总体是你感兴趣的所有项目的集合(事件、人物、物体等)。在下面的图片中,总体由七个人组成。

→ 一个样本则是总体的一个子集。图片中的样本包含两个人。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

样本和总体的示意图(图片来源:作者)

在现实生活中,很难找到和观察总体。然而,收集样本的时间更少,成本更低。这些是我们更喜欢处理样本的主要原因,大多数统计测试也设计为处理不完整的数据,即样本。

样本需要满足以下两个标准以确保有效性:(1) 随机(2) 代表性

随机样本意味着样本中的每个元素都是从总体中严格随机选择的。

→ 当样本准确地反映总体时,它是代表性的。例如,当总体包括男性和女性时,样本不应仅包含男性。

数据有哪些不同类型?

现实生活中的数据由不同类型组成。了解它们很重要,因为不同类型的数据具有不同的特征,并且以不同的方式收集和分析。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据的不同类型(作者提供的图片)

中心趋势的主要度量有哪些?

中心趋势的主要度量有三个:均值中位数众数。在探索数据时,应同时应用这三种度量,以便得出更好的结论。然而,仅使用其中一个可能会导致对数据提供不准确的信息。

本节重点定义它们的每一个,包括其优缺点。

均值

也称为平均值 (µ 对于总体,x 带有上标对于样本)。它对应于有限数字集的中心。均值通过将所有数字除以元素的总数来计算。考虑一个数字集合 *x1, x2, …, xn*,均值定义如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

维基百科中的均值公式

  • *x*带有上标表示样本均值。

  • *n*表示样本集中的观察总数。

以下是 Python 中的实现。

# Import the mean function from statistics module
from statistics import mean

# Define the set of numbers
data = [5, 53, 4, 8, 6, 9, 1]

# Compute the mean
mean_value = mean(data)

print(f"The mean of {data} is {mean_value} ")

之前的代码应生成以下结果:

The mean of [5, 53, 4, 8, 6, 9, 1] is 12.28

尽管均值主要被使用,但它确实存在一个问题,就是容易受到异常值的影响,因此可能不是得出相关结论的最佳选择。

中位数

中位数表示数据在按升序或降序排列后的中间值,公式如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

维基百科中的中位数公式

与均值相对,中位数不受异常值的影响,因此可以是更好的中心趋势度量。然而,中位数和均值仅适用于数值数据。

使用上述相同的数据,我们可以如下计算中位数:

# Import the median function from statistics module
from statistics import median

# Compute the median
median_value = median(data)

print(f"The median of {data} is {median_value} ")

执行结果如下:

 The median of [5, 53, 4, 8, 6, 9, 1] is 6 

让我们详细分析数据的中位数计算过程。

  • 第 1 步:将数据按升序排列:[1, 4, 5, 6, 8, 9, 53]

  • 第 2 步:在我们的例子中,n = 7是奇数。

  • 第 3 步:中间值是 (n + 1)/2 项,即 (7+1)/2 = 4,因此为 6。

众数

它对应于数据中出现频率最高的值,可以应用于数值和分类变量。

类似于中位数,模式对异常值不敏感。然而,当数据中的所有值出现的次数相同时,模式不存在。大多数情况下,我们在数据中最多可以观察到三种模式。

让我们使用一个不同的数据集来说明模式的使用。

# Define the data
data = [5, 9, 4, 9, 7, 9, 1]

# Compute the mode
mode_value = mode(data)

print(f"The mode of {data} is {mode_value} ")

数据中所有值只出现一次,除了 9 出现了三次。由于模式对应于出现次数最多的值,上述代码的结果如下:

The mode of [5, 9, 4, 9, 7, 9, 1] is 9

形状的度量指标是什么?

SkewnessKurtosis是可以更好地描述给定数据集形状的两种主要技术。本节将详细介绍每一种技术,包括使用 Python 的示例。

在深入解释每个概念之前,让我们导入必要的 Python 库。

  • Numpy用于处理数组。

  • scipy模块用于统计分析。

  • 为了可视化,我们使用matplotlib库。

import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
from scipy.stats import beta, kurtosis

偏斜度

当数据的概率分布在均值周围不对称时,数据被称为偏斜。根据偏斜度的值,可以出现三种主要情况。

以下辅助函数用于示例和绘制每种情况。

# Use the seed to get the same results for randomization
np.random.seed(2023)

def plot_skewness(data, label):

    plt.hist(data, density=True, color='orange', alpha=0.7, label=label)
    plt.axvline(data.mean(), color='green', linestyle='dashed', linewidth=2, label='Mean')
    plt.axvline(np.median(data), color='blue', linestyle='dashed', linewidth=2, label='Median')
    plt.legend()
    plt.show()
  • 当数据符合正态分布时,偏斜度是对称的。在这种情况下,Mean = Median = Mode.
# Normal distribution
normal_data = np.random.normal(0, 1, 1000)
label = 'Normal: Symetric Skewness'
plot_skewness(normal_data, label)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正态分布或对称偏斜(图像来源于作者)

  • 当值大于零时,存在正偏斜或右偏。这意味着均值右侧的值较多,均值位于中位数的右侧。在这种情况下,我们有Mean > Median > Mode.
# Exponential distribution
exp_data = np.random.exponential(1, 1000)
label = 'Exponential: Positive Skewness'
plot_skewness(exp_data, label)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正偏斜的示意图(图像来源于作者)

  • 当值小于零时,存在负偏斜或左偏。在这种情况下,左侧的值较多,我们通常发现均值位于中位数的左侧。在这种情况下,Mean < Median < Mode.
# Beta 
beta_data = beta.rvs(5, 2, size=10000)
label = 'Beta: Negative Skewness'
plot_skewness(beta_data, label)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

负偏斜的示意图(图像来源于作者)

峰度

峰度度量量化了分布尾部的权重与分布其余部分的比例。它告诉我们数据是分散还是集中在均值附近。

具有较高均值集中度的分布被称为具有高峰度。低峰度与更平坦的分布相关,该分布中较少的数据集中在均值附近。

此外,峰度用于检查数据是否符合正态分布,也用于检测数据中的异常值。

数据可以展示三种主要类型的峰度:(1) Mesokurtic(2) Leptokurtic(3) Platykurtic。除了说明每个概念外,还将展示如何计算每一种类型的 Python 代码。

**(1) Mesokurtic**在这种情况下,kurtosis=3。这意味着峰度类似于正态分布,主要用作与现有分布的基准。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Mesokurtic 分布的插图(图像作者提供)

**(2) Leptokurtic**,也称为正峰度,其kurtosis>3。通常被称为“尖峰”分布,Leptokurtic在均值周围的数据集中的浓度高于正态分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Leptokurtic 分布的插图(图像作者提供)

**(3) Platykurtic**,也称为负峰度,其kurtosis<3。通常被称为“平坦”分布,Leptokurtic在均值周围的数据集中度低于Platykurtic峰度,且尾部较短。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Platykurtic 分布的插图(图像作者提供)

以下代码来自scipy的官方文档,完美演示了如何计算峰度。

x = np.linspace(-5, 5, 100)
ax = plt.subplot()
distnames = ['laplace', 'norm', 'uniform']

for distname in distnames:
    if distname == 'uniform':
        dist = getattr(stats, distname)(loc=-2, scale=4)
    else:
        dist = getattr(stats, distname)
    data = dist.rvs(size=1000)
    kur = kurtosis(data, fisher=True)
    y = dist.pdf(x)
    ax.plot(x, y, label="{}, {}".format(distname, round(kur, 3)))
    ax.legend()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三种主要峰度及其值的插图(图像来自代码)

  • 拉普拉斯分布具有Leptokurtic峰度的特性。它的尾部比正态分布的尾部更为明显。

  • 均匀分布由于其负峰度(Platykurtic)具有最不明显的尾部。

结论

本系列的第一部分涵盖了不同类型的数据、样本与总体之间的差异、主要的集中趋势度量以及最终的偏度度量。

敬请关注下一部分,我们将讨论更多主题,帮助你获得相关的统计技能。

如果你喜欢阅读我的故事并希望支持我的写作,考虑成为 Medium 会员。每月$5 的承诺,你将解锁 Medium 上无限制访问故事的权限。

想请我喝咖啡☕️吗?→ 点击这里!

随时在MediumTwitterYouTube上关注我,或者在LinkedIn上打招呼!讨论 AI、ML、数据科学、NLP 和 MLOps 总是令人愉快的!

源代码可在GitHub上获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值