Python 中计时代码的一种简单方法
使用装饰器来计时你的函数
布拉德·尼瑟里在 Unsplash 上拍摄的照片
介绍
我们的目标是在 Python 中创建一种简单的函数计时方法。我们通过用 Python 的库functools
和time
编写装饰器来实现这一点。然后,这个装饰器将被应用到我们感兴趣的运行时的函数中。
计时装饰:@timefunc
下面的代码代表了一个通用的装饰模式,它具有可重用和灵活的结构。注意functool.wraps
的位置。这是我们关闭的装饰。这个装饰器保存了传递给闭包的func
的元数据。
timer.py
Functools 在第 16 行变得很重要,我们在打印语句中访问了func.__name__
。如果我们不使用functools.wraps
来修饰我们的闭包,将会返回错误的名称。
这个装饰器返回传递给timefunc()
的函数的运行时。在第 13 行,start
开始计时。然后,第 14 行的result
存储func(*args, **kwargs).
的值,之后计算time_elapsed
。打印语句报告func
的名称和执行时间。
使用@符号应用 timefunc
在 Python 中,decorators 可以很容易地用@
符号来应用。并非所有装饰者的应用都使用这种语法,但是所有的@
符号都是装饰者的应用。
我们用符号@
用timefunc
来修饰single_thread
。
用@timefunc 装饰函数
现在single_thread
被修饰了,当它在第 13 行被调用时,我们将看到它的func.__name__
和运行时。
timefunc 修饰的 single_thread 的输出
如果你想知道这是如何工作的,下面我们将更深入地讨论为什么以及如何为时间函数编写装饰器。
为什么一个人可以计时一个函数
原因相对简单。更快的功能是更好的功能。
时间就是金钱,朋友。—加斯洛维
时序装饰器向我们展示了一个函数的运行时。我们可以将装饰器应用于一个函数的几个版本,对它们进行基准测试,并选择最快的一个。此外,在测试代码时,知道执行需要多长时间也很有用。提前五分钟运行?这是一个很好的起床、活动双腿和倒满咖啡的窗口!
为了用 Python 编写装饰函数,我们依赖于functools
和对作用域的认识。我们来回顾一下范围和装饰。
装饰、关闭和范围
修饰是 Python 中的一种设计模式,允许您修改函数的行为。装饰器是一个函数,它接受一个函数并返回一个修改过的函数。
当编写闭包和装饰器时,必须记住每个函数的作用域。在 Python 中,函数定义范围。闭包可以访问返回它们的函数的范围;装饰者的范围。
在将修饰函数传递给闭包时,保留它的元数据是很重要的。了解我们的作用域让我们可以用functools.wraps
恰当地修饰我们的闭包。
要了解这些概念的更多信息,请阅读这篇三分钟的文章。
这个装饰器的可重用性
注意func
被当作第 7 行的一个参数。然后在第 11 行,我们传递*args, **kwargs
,进入我们的闭包。这些*args, **kwargs
用于计算第 10 行func(*args, **kwargs)
的result
。
timer.py
*args
和**kwargs
的灵活性使得timefunc
可以处理几乎任何功能。我们闭包的 print 语句被设计用来访问函数__name__
、args
、kwargs
和result
,为func
创建一个有用的定时输出。
结论
装饰是增强功能行为的有力工具。通过编写一个装饰器来为函数计时,您可以获得一个优雅的、可重用的模式来跟踪函数的运行时。
请随意将timefunc
复制到您的代码库中,或者您可以尝试编写自己的时序装饰器!
用 Python 追踪代码的简单方法
使用装饰器来跟踪你的函数
Maksym Kaharlytskyi 在 Unsplash 上拍摄的照片
介绍
我们的目标是创建一种可重用的方法来跟踪 Python 中的函数。我们通过用 Python 的functools
库编写装饰器来实现这一点。然后,这个装饰器将被应用到我们感兴趣的运行时的函数中。
跟踪装饰者:@tracefunc
下面的代码代表了一个通用的装饰模式,它具有可重用和灵活的结构。注意functool.wraps
的位置。这是我们关闭的装饰。这个装饰器保存了传递给闭包的func
的元数据。
tracer.py
如果我们没有在第 7 行使用functools.wraps
来修饰我们的闭包,那么在第 11 行打印func.__name__
时将会返回错误的名字。
这个装饰器打印出传递给tracefunc()
的函数的轨迹。在第 10 行,result
,存储func(*args, **kwargs).
的值,之后生成一个打印语句。该语句报告了func.__name__
、args、kwargs 和result
。
因此,我们用tracefunc
修饰的函数将生成关于它们执行的附加信息。
使用@符号应用 tracefunc
在 Python 中,decorators 可以很容易地用@
符号来应用。并非所有装饰者的应用都使用这种语法,但是所有的@
符号都是装饰者的应用。
我们用符号@
用tracefunc
来修饰show_args_and_kwargs
。
@tracefunc 的应用
现在show_args_and_kwargs
被修饰了,当它在第 8–10 行被调用时,我们将看到它的func.__name__
、args、kwargs 和 result。
跟踪输出
下面我们将更深入地探讨为什么以及如何编写一个装饰器来跟踪函数。
为什么人们会追踪一个函数
跟踪是模拟程序的执行,一行一行地遍历程序,显示变量是如何变化的。有经验的程序员使用跟踪来调试程序,通常作为调试器的替代品。描摹对于正在学习语言的初学者来说也是非常有用的。
“干杯,爱!骑兵来了!”—示踪剂
为了用 Python 编写装饰函数,我们依赖于functools
和对作用域的认识。我们来回顾一下范围和装饰。
装饰、关闭和范围
修饰是 Python 中的一种设计模式,允许您修改函数的行为。装饰器是一个函数,它接受一个函数并返回一个修改过的函数。
当编写闭包和装饰器时,必须记住每个函数的作用域。在 Python 中,函数定义范围。闭包可以访问返回它们的函数的范围;装饰者的范围。
在将修饰函数传递给闭包时,保留它的元数据是很重要的。了解我们的作用域让我们可以用functools.wraps
恰当地修饰我们的闭包。
要了解这些概念的更多信息,请阅读这篇三分钟的文章。
这个装饰器的可重用性
注意func
被当作第 4 行的一个参数。然后在第 8 行,我们通过*args, **kwargs
,进入我们的闭包。这些*args, **kwargs
用于计算第 10 行func(*args, **kwargs)
的result
。
tracer.py
*args
和**kwargs
的灵活性允许tracefunc
处理几乎任何函数,不管它是使用 args、kwargs,还是两者都不使用。我们的闭包的 print 语句被设计用来访问函数__name__
、args
、kwargs
和result
,从而为func
创建一个有用的跟踪输出。
结论
装饰是增强功能行为的有力工具。通过编写一个装饰器来跟踪您的函数,您获得了一个优雅的、可重用的模式来跟踪函数的行为。
请随意将tracefunc
复制到您的代码库中,或者您可以尝试编写自己的跟踪装饰器!
从客户购物篮分析用例理解关联规则的简单方法
本文是对 的全面概述 的关联规则和不同的度量标准
a)导言
本文的目标是解释应用于客户购物篮分析用例的关联规则。我们将经历定义什么是关联规则的步骤,识别测量它的主要方法,并且也提及它的优点和缺点。
b)关联规则的定义
关联规则是一种基于 规则的机器学习方法 ,用于部署模式识别,以识别不同但相关的项目之间的关系。自 20 世纪 90 年代以来,它一直用于零售业,以帮助分析客户同时购买的产品。这可以帮助商店经理找到更好的产品布局、产品折扣、库存管理等策略。当然,其他行业也可以从这项技术中受益。
c)展示我们的使用案例
比方说,咖啡和糖经常一起购买。有了这些信息,您可以通过以下方式增加销售额:
- 将咖啡和糖放在一起,这样购买一种产品的顾客就不会步行去买另一种产品。
- 向购买咖啡或牛奶的人做广告,以增加此人购买配对的其他产品的倾向。
- 如果顾客一次购买牛奶和咖啡,则提供折扣。
d)将关联规则应用于我们的用例
首先,需要注意的是,一个关联规则有两部分: 一个前因(if) 和 一个后果(then) 。前提是在数据中找到的项目。结果项是与先行项结合在一起的项。
通过将关联规则应用到我们之前的用例中,我们可以用咖啡和牛奶的例子得到下面的表达式。
- " 如果购买了 项咖啡, 则 项购买糖的可能性是 __"
可以表示为: - {咖啡}→{糖}
e)测量关联规则的三种主要方法
测量联想的三种主要方式是: 支持度、信心度、升力度。
让我们用咖啡和糖的类比来突出这些概念。想象以下场景,其中:
- 店内总交易笔数为 3000
- 咖啡©的购买数量是 800 次交易
- 糖的购买数量为 500 笔交易
- 一起购买的咖啡和糖(C → S)的数量是 400 个交易
1)支持
这是给定数据集中某项的相对频率(所有事务)。它代表了商品的受欢迎程度,也是由它在总销售额中所占的比例来定义的。
c 是的先行词。s 是的后件
基于我们的案例,我们可以将咖啡的支持计算为:
2)信心
这对应于在数据中看到结果项的概率,假设数据也包含先行项。换句话说,它告诉 在购买了一件商品的情况下,购买另一件商品的可能性有多大。
c 是的先行词。s 是的结果
咖啡是 T21 的前身。糖是的后件
这个分数意味着,如果购买咖啡,有 50%的几率会购买糖。
3)电梯
这衡量了前因和后果一起发生的频率比它们独立发生的频率高多少。
c 是先行词。s 是的结果
- 如果 Lift 得分< 1,则表示如果购买 C 不太可能购买 S 。
- 如果 Lift 得分> 1,说明 C 与 S 关联度高。换句话说,如果购买了 C ,很可能会购买 S 。
- 如果 Lift score = 1,则表示 C 和 S. 之间没有关联
咖啡是先行词。糖是的后件
- 从结果中,我们可以看到 lift 得分> 1,这意味着如果购买了咖啡,很可能也会购买糖。
f)关联规则的优点和缺点
1)优势
- 这个技术是最具描述性的,一旦我们修正了 结果,它就可以成为预测。
- 它是有效的,对所分析的离散数据的性质没有任何理论限制。
- 它提供了广泛的可能性;例如,我们可以添加时态、个人数据等。
- 由此产生的规则非常容易理解。
F.2)缺点
- 处理大量数据(大量交易或/和项目)非常耗时。
- 它不适合处理连续变量。
- 这种技术仅提供局部规则,而不是给出现象的全局视野,强调主要因素和因素之间的相互作用。
g)文章结尾
我希望您喜欢这篇文章。如果您有任何问题或意见,我将很高兴欢迎进一步讨论。
如需进一步阅读,请随时查阅以下链接:
https://searchbusinessanalytics . techtarget . com/definition/association-rules-in-data-mining
https://searchbusinessanalytics . techtarget . com/definition/association-rules-in-data-mining
【https://en.wikipedia.org/wiki/Rule-based_machine_learning
再见🏃🏾
一个简单而有效的掌握数据可视化的 5 步框架
让我们用一个例子来慢慢分解框架,并创建可视化效果。包括截图。
图片由 Freepik 上的 Freepik 提供
将数据可视化一直令我着迷。用视觉图像呈现我的想法和发现,并讲述一个故事一直是我的强项。
我们都知道数据可视化在大数据时代的重要性。
你的教授喜欢精心设计的课堂演示。你的老板喜欢你通过可视化揭示模式、趋势和商业洞察力。你已经在新的 iPhone 发布会上看到了这些可视化的画面,是吗?
当人们通过可视化的方式讲述一个引人入胜的故事时,你可能会感到敬畏,但请相信我;这不是火箭科学。我可以坚持这样做,因为随着时间的推移,我已经开发了自己的 5 步框架,并且每次都依靠这个过程来做好。
关键是要反复进行框架实践,直到你自然而然地创造出“魔法”
我不会把它放在那里,而是用一个例子带你浏览这个框架。
我挑选的是美国超市数据集,它由一个电子商务平台从 2014 年到 2018 年的交易列表组成,可在 Kaggle 上获得。去吧,下载数据(你需要的只是一个免费的 Kaggle 账户)*,*然后照着例子做。
1.明确目的
这是很多人一开始就忽略的,包括我。甚至在弄清楚你要想象什么之前,你就开始浏览数据。你花了几个小时去理解数据,后来才意识到;这种努力没有什么价值。
作为第一步,让我们明确目的。
- 你想回答什么问题?
- 你想通过想象传达什么?
- 你的视觉化将如何帮助观众?
- 你试图用视觉化来完成什么?
这些简单的问题将有助于你在接下来的阶段提高工作效率。
将此应用于示例:
在我们的例子中,美国超市数据集,一些你可能想要解决的问题。
- 各州之间的销售额有何不同?
- 每个产品的利润是多少?
- 哪个产品类别产生高利润?
- 每种产品对利润贡献的百分比?
这些只是问题的几个例子,还可以有更多。接下来,我们将使用第一个问题,即各州之间的销售额如何变化,作为示例。
2.了解您的数据
现在你清楚了你要回答的目的或问题,你应该理解呈现给你的数据。
你需要非常了解数据集。数据集可能有数百列,一眼看去可能会让人不知所措。但是要花时间让自己熟悉变量,每个变量代表什么,以及变量在数据集中的意义。
现在你已经有了一个清晰的目标(来自第一步的*)*,并且已经理解了每个变量所代表的含义,你将能够过滤出你可视化所需要的列。
了解数据集还将澄清您是否可以按原样使用数据,或者是否应该执行任何修改。
将此应用于示例:
在检查数据时,为了更好地理解,您可能会问这些问题。
- 数据集中的每个变量代表什么?
- 回答问题需要哪些变量?
- 解决问题需要哪些修改?
- 你需要绘制哪些变量?
现在你已经有了明确的目的和对数据的理解,让我们进入下一步。我们走吧。
3.定义你的受众
理解你的观众是至关重要的,因为它给你的视觉化的想法,你应该拿出来。
例如,如果你的读者是数据科学家,你可以使用 matplotlib 作为你的可视化工具。但是让我们假设你被要求把它展示给一个业务分析师或销售人员;用 matplotlib 创建可视化将是一个错误。你可以使用 MS Excel 或者一些高级工具,比如 Tableau 和 PowerBI。
如果您向客户推销您的数据,您可能希望它尽可能有吸引力。在这种情况下,您可能不想使用 MS Excel,而是选择使用 Tableau 或 PowerBI。
了解你的受众不仅仅是选择你使用的工具,还包括你使用的标题和说明。
将此应用于示例:
为了更好地了解你的听众,你可以问自己几个问题
- 你的目标受众是谁?(或者你在为谁创造可视化?)
- 你的目标受众是技术人员吗?
- 他们在解释数据方面有什么能力?
- 他们希望可视化是什么形式?(例如,在线仪表板、MS Excel 表格、演示文稿)
在我们的例子中,让我们假设销售人员是我们的目标受众。我们可以选择创建 Tableau 仪表板来显示美国不同州之间的销售差异。
4.发展你的想象力
前三个步骤会给你一个清晰的你将要创建的可视化的图像。现在是时候动手开发可视化了。
可视化类型
选择正确的可视化类型至关重要。如果你在视觉化的类型上没有做出正确的选择,你到目前为止所付出的所有努力都会以失败告终。
我大概可以写一整篇文章来讨论如何在不同的可视化类型之间进行选择,但是在这篇文章中我将保持简单。
- **条形图:**当您想要对数据进行比较时,可以使用条形图。
- **折线图:**这些图表可以用来可视化数据随时间变化的趋势。例如,一种产品在一年中的价格,一年中每天产生的利润。
- **饼状图:**这些是用来展示构图的。来解释整体的百分比。比如每个产品贡献利润的百分比。
- **地图:**你可以选择使用地图来可视化基于地理位置的数据。这将使最终用户更好地了解位置。
- **甘特图:**这是一种广泛使用的图表类型,用于可视化一段时间内的项目进度或活动。
可视化的类型不限于以上五种。为了简单起见,我只提到了上面五个。一旦你选择了正确的图表类型,注意颜色和比例的选择。
将此应用于示例:
在我们看到的例子中,我们可以创建一个类似下图的条形图。
作者创造的形象
5.测试和改进
在这个阶段,您测试您的实现以进行改进。人类在开发时做出假设是很常见的。为了减少这种偏见,你应该总是期待同事的反馈。
将此应用于示例:
在我们的示例中,我们可以将上一步中创建的条形图改进为地图。(我在上一个步骤中特意创建了条形图,以显示反馈可能带来的改进)。
作者创造的形象
让我们重温一下,永远记住它
简单的五步指南可以节省你创建可视化的时间。
- 明确目的:把自己要解决的问题说清楚。
- 理解你的数据:检查数据,清楚每个变量代表什么。根据问题过滤掉变量。
- 定义你的受众:了解你的受众将有助于你决定在开发阶段使用的工具和短语。
- 发展你的视觉化:现在,你确切地知道要创造什么。为数据集选择正确的可视化类型,并开始创建。
- 测试和改进:获得对开发的可视化的反馈,并对其进行改进。最后,与利益相关者分享。
好了,你知道了。这不是魔法。很简单。当你把它付诸实践时,你就会知道它有多有效。万事如意!
非常感谢你读到这里。我希望你喜欢阅读,这篇文章给你增加了一些价值。我希望听到您对我如何改进的反馈。期待看到你的恒星可视化!
为您的数据科学项目创建 CLI 的简化指南
CLI 是一种与机器学习模型交互的强大而直接的方式
迈克尔·泽兹奇在 Unsplash 上的照片
这是一个可怕的假设。我以为一旦部署,就结束了。但是,部署只是大多数数据科学项目的开始。
我们经常需要重新训练和更新模型。通常使用新数据,有时使用不同的配置,偶尔使用完全独特的体系结构。
更糟糕的是,有时,你把它交给另一个团队或没有技术能力的客户去做。如果不是,无论是谁在做这些维护工作,都可能对架构有不同的理解。
在这种情况下,我们建立一个门户网站来支持善后处理。我们将应用程序链接到数据存储库,让用户通过 web 表单进行配置,并运行算法。
构建一个 web 应用程序来与您的机器学习模型进行交互是一个不错的主意。特别是,Streamlit 等工具允许数据科学家创建 web 应用程序,而无需任何 HTML、CSS 或 JavaScript 代码。
然而,网络应用并不适合一些人。假设你对托管 web 应用程序有所顾虑。不用担心;不是死路一条。我们有一个后备方案,这确实是一个解决问题的可靠方案。
您可以创建命令行界面(CLI)来产品化和交付您的机器学习项目。
你能用 CLI 为你的机器学习模型做什么?
CLI 允许您在命令提示符下运行编程指令,而无需与代码库交互。CLI 可以有许多命令,每个命令都有不同的参数。例如,下面启动一个 web 服务器,您可以选择使用哪个端口。
python -m "http.server" 8080
您也可以创建像这样有用的 CLI 来与您的 ML 模型交互。如果您的客户想要用不同的数据重新训练模型,他们可以用一个像下面这样的命令来完成。
manage retrain /<path>/new_data.csv
您还可以为您的 CLI 创建帮助页面,在训练(或任何其他任务)时显示进度,并在终端窗口中有意义地设计日志和错误。
创建您的第一个 CLI。
我们将使用一个名为 Typer 的 python 库来创建 CLI。Typer 是创建 CLI 命令、打印时尚输出和显示进度的最小框架。
您仍然可以使用 Typer 为您的非 Python 程序创建 CLI。您必须使用 Python 子流程,或者通过 HTTP 或消息代理与非 Python 代码通信。这里就不讨论了。但是,这可能是未来文章的主题。
安装 Typer 很简单。您可以使用 PyPI:
pip install typer
安装完成后,您可以尝试这个 Hello World 应用程序,了解一下 Typer 是如何工作的。
在您的项目目录中创建一个名为 app.js 的文件(您可以选择不同的名称)和以下内容。
作者的代码片段。
运行上面的命令将在终端上打印一条彩色的 Hello World 消息。
作者截图。
当然,上面的练习不仅仅是简单的 Hello World。您可以更改文本颜色和字体颜色。如果您使用的是带有 IntelliSense 的编辑器,如 VSCode,找到它们就很容易了。如果没有,你可以在 Typer 的文档上找到它们,无论如何都值得一查。
作者截图。
在继续之前,让我们看看如何向您的 CLI 添加多个命令。它需要对代码库稍加修改。
我们创建一个类型的实例,并在“main”方法中调用它。它需要对代码库稍加修改。我们可以在函数上使用“command”修饰符,将每个函数转换成一个 CLI 命令。
代码片段由作者提供。
通过这种新的安排,您可以在同一个 CLI 下使用多个命令。您可以在文件名后面加上函数,告诉 CLI 要执行哪个函数。
这不是已经很棒了吗?现在我们已经安装并测试了 Typer,让我们继续集成一个 ML 算法。
为 K-Means 算法创建 CLI。
我将使用 K-Means 算法,我在以前的帖子中讨论过。K-Means 是一种简单而强大的数据点聚类技术。
这是我们的应用程序的修改版本。我们创建了两个命令:一个用于训练和保存 K 均值模型,另一个用于加载和在预测中使用。注意,train 函数定义有一个参数 file_path。Typer 会将其转换为命令行参数。
代码片段由作者提供。
使用文件路径运行我们的应用程序 CLI 的“train”命令就可以做到这一点。您可以通过实现 predict 命令来练习一下。
作者截图。
显示进度条
对于消耗任务,你必须显示一个进度条,这样用户就不用拔头发了。Typer API 可以帮助你创建进度条,而不用拖动你的进度条。
让我们使用另一个命令,使用 elbow 方法找出集群的最佳数量。该方法将对不同数量的组运行 K-Means 多次。理想的数字应该是具有低惯性的数字。在大型应用程序中,这可能是一个运行几个小时的任务。
下面是完成这项工作的代码片段。注意,这一次,我们添加了两个参数,其中一个有默认值。Typer 会把它当做一个选项,而不是一个论点。您可以选择留空。
代码片段由作者提供。
现在尝试运行python app.py elbow voters_demo_sample.csv
。
作者截图。
这段代码目前没有进度条。运行这个命令将使终端在几秒钟内没有任何输出,并立即打印出来。
让我们放一个进度条来帮助我们的用户。这是更新后的脚本。请注意 for 循环中的细微变化。
代码片段由作者提供。
下面是现在运行它的样子:
作者截图。
为 CLI 创建手册页。
手册页是帮助用户的文档。Typer 很聪明地将您的函数及其输入转换成详细的手册页。它将列出所有可用的命令、参数和选项。
您可以使用后缀- -help 来访问 Typer 生成的手册页。
python app.py --help
作者截图。
您也可以访问特定命令的手册页:
python app.py elbow --help
作者截图。
如果你需要给用户更多的信息,你可以在函数的开头使用多行注释。Typer 将在帮助页面上显示它们。
代码片段由作者提供。
结论
在本文中,我们创建了一个 CLI 来帮助与机器学习模型进行交互。您可以将这些技术扩展到数据科学项目之外。CLI 可以处理任何用户交互。
虽然我们使用 Python 来生成 CLI,但是您也可以使用它来运行其他程序。在这种情况下,您可能必须使用子流程、HTTP 或消息代理。
CLI 是解决关键问题的快速方法。如果不适合开发门户网站或其他解决方案,您可以构建一个。此外,您不必担心服务器停机等不可预见的事件。这使得 CLIs 成为值得考虑的可靠替代方案。
通过 Typer,一个极简的 Python 库,我们创建了
- 与 K-Means 算法交互的 CLI 命令;
- 终端窗口上的彩色消息;
- 一个进度条,让用户随时了解情况;
- 指导用户的命令行文档。
感谢阅读,朋友!看来你和我有许多共同的兴趣。我很乐意通过 LinkedIn、T2、Twitter 和 Medium 与你联系
还不是中等会员?请使用此链接 成为 会员。你可以享受成千上万的有见地的文章,并支持我,因为我赚了一点佣金介绍你。
用于评估对象检测模型的单个数字度量
F1 分数以及它们如何帮助评估模特的表现
尼古拉斯·卡佩罗在 Unsplash 上拍摄的照片
介绍
使用精度和召回率来评估对象检测模型可以提供对模型在各种置信度值下如何执行的有价值的洞察。类似地,F1 分数尤其有助于确定平衡给定模型的精度和召回值的最佳置信度;然而,该值跨越了从 0 到 1 的置信值的范围。单值评估度量可以从给定模型的 F1 分数集合中导出,其可以是整体模型性能的良好指标。
背景
F1 分数、精确度和召回率可使用以下等式进行评估:
F1 分数、精确度和回忆方程式,作者图片
当在各种置信值下评估模型时,这些指标可以很好地协同工作,从而根据设计规范提供关于模型如何执行以及哪些值可以优化模型性能的有价值的见解。通常,随着置信度阈值的增加,精确度会上升,召回率会下降,如下面显示的自定义 yolo v5 模型的结果所示:
自定义 yolo v5 对象检测模型的单一类别精度分数,图片由作者提供
自定义 yolo v5 对象检测模型的单一类别召回分数,图片由作者提供
使用 F1 得分曲线,可以看到精确度和召回率之间的平衡,并且可以使用下面的图表确定设计点:
自定义 yolo v5 对象检测模型的 F1 得分曲线,图片由作者提供
从 F1 曲线来看,优化精度和召回率的置信度值是 0.352。在许多情况下,更高的置信度值是可取的。在该模型的情况下,选择置信度 0.6 可能是最佳的,因为 F1 值看起来大约为 0.75,这与最大值 0.81 相差不远。观察置信度为 0.6 的精度和召回值也证实了这可能是一个合适的设计点。从 0.6 左右开始,召回值开始吃亏,精度值还是大致在最大值。
理论
现在,通过提供具有相应置信度的最大值,可以用 F1 分数中的单个数字来评估模型;然而,这可能不能准确地代表模型的整体。从 F1 得分中得出的一个建议的单个数字指标如下所示:
建议度量的基本积分形式,作者提供的图像
该值通过对 F1 得分曲线进行积分来确定,积分的指数因子称为 gamma。如果 F1 曲线的方程是已知的,可以使用这种形式。在大多数情况下,F1 得分曲线由使用评估或测试数据集评估的值生成。在这种情况下,可以使用更一般形式的方程:
建议指标的求和符号,作者提供的图像
当应用矩形积分时,可以使用具有中点规则的公式的详细形式:
中点规则应用于矩形块,按作者排序的图像
p 是给定索引处的精度值,R 是给定索引处的召回值。指数γ1/c 已被给定指数的平均置信度值所取代。
在这个新的符号中,将计算每个数据点的 F1 得分曲线下的面积,并将其添加到累计总数中。指数因子 gamma 可用于惩罚和奖励 F1 曲线的各个区域。例如,对于 gamma 的标准值,置信值较低的 1/c: F1 分数由于被驱动到 0 而受到严重惩罚,并且对整体度量几乎没有贡献。类似地,对于高置信度值的 F1 分数,指数因子最低限度地惩罚总分数。此指标可获得的最大值为 1,最小值为 0。yolo v5 模型 F1 得分曲线各点的建议指标值如下所示:
衍生 F1 评分曲线与处罚,图片由作者
蓝线表示等式 7 在每个数据点的计算值。请注意,随着数据点数量的增加,该值会越来越小。浅橙色条代表所有计算的单个数据点得分的累计总数。
由于伽马因子,在置信度为 0.1 或更低时评估的大多数 F1 分数点被驱为零,并且 F1 分数贡献被抑制直到置信度为 0.4。F1 分数值的惩罚程度可以使用 gamma 因子来控制。例如,如果需要更高的惩罚,将伽马因子中的分子从 1/c 增加到 10/c。这将使置信度为 0.4 之前的所有值比以前受到更严重的惩罚,但不会改变惩罚开始改变的置信度值。
类似地,如果想要更少的惩罚,减少分子或者甚至移除伽马指数将会有所帮助。用于评估度量标准的一种形式的方程,该度量标准考虑了控制惩罚程度和惩罚点的变量,可描述为:
带有惩罚因子的度量评估,由作者提供的图像
其中 f 用于控制上面讨论的惩罚量(默认值 1)。请注意,将 f 增加到大于 1 的值将显著影响分数。
比较
我们来比较三个模型:前面提到的基础模型,一个比基础模型差的模型,一个比基础模型好的模型。这些模型被指定为优于或劣于基本模型的方式可以总结为:
- F1 曲线、积分面积、罚积分面积
- 推理结果的人工评估
- 通过较少的训练数据、不同的配置参数以及时期和批次变化,专门训练得更好或更差
各种模型的 F1 曲线、非惩罚积分值和惩罚积分值曲线如下所示:
各种度量得分曲线,图片由作者提供
非惩罚曲线将遵循 F1 曲线的相同轮廓,因为它们是线性相关的。请注意,F1 曲线和非惩罚积分曲线之间的幅度是不同的。这是由于等式 9 中的δ置信项。任何积分分数的最大可能值是用于积分 F1 曲线的增量。在这种情况下,使用 0.05 的增量,因此非惩罚和惩罚积分的最大值是 0.05。当置信度接近约 0.4 时,惩罚曲线的低置信度部分随着衰落严重程度而明显降低。所有被罚曲线都是在 f 值为 1 的情况下计算的。
上述曲线的最终得分总结如下:
分数摘要,按作者分类的图像
最后一行是处罚分数与非处罚分数的比率。它代表综合 F1 分数中位于较高置信区域的部分。如果期望更高的置信度,当确定多少非惩罚分数实际上是相关的时,这可能是一个很好的指标。
一个 GitHub 知识库已经公开,可以很容易地计算出被罚和未被罚的综合分数。可以在以下位置找到它:
https://github.com/plebbyd/integrated-F1
此外,对于任何给定的置信度和 F1 分数值的输入,该存储库中的函数返回惩罚与非惩罚的比率。
结论
惩罚的和非惩罚的综合 F1 分数可以是用于评估对象检测模型的良好的单个数字度量。如果在多个模型的研究或训练过程中无法对 F1 曲线进行手动检查,那么评估这些新指标可能会有所帮助。
参考
[1]戴维·m·w·鲍尔斯(2011 年)。“评价:从精度、召回率、F-Measure 到 ROC、信息量、标记性&相关性”。机器学习技术杂志。2(1):37–63。
[2] Yolo v5 (2021)。In: GitHub。https://github.com/ultralytics/yolov5。访问时间是 2021 年 5 月 31 日。
模拟森林火灾、流行病和经济的单一技术
探索 Python 中的交互代理建模
流行病,森林大火和经济危机。不仅是去年的菜单,还有一小部分现象可以在基于主体的建模(ABM)框架下进行建模。
图片来自 Unsplash
ABM 非常适合于理解复杂行为是如何在基于系统个体参与者之间简单交互的系统中出现的。abm 在解释一般观察结果方面表现出特别的优势,这些观察结果被称为“程式化事实”,例如观察到的中子散射模式或资产回报的分布。这些代理可以是任何东西,从人或公司到生态系统中的动物或气体中的原子。这种建模方法是自下而上的方法,其中系统的行为完全由对参与者个体行为的假设驱动,而不是自上而下的方法,该方法假设参与者将如何一起行为。
一个简单的例子是野火建模,每个代理代表一小片土地。每块土地的规则可能非常简单:如果土地着火,将顺风的相邻土地点燃,直到该土地上的所有燃料都烧完。尽管有这些简单的规则,wildfire 系统的整体行为表现出复杂的行为。此外,探索改变假设的影响,如使火灾蔓延概率化或引入燃料再生,只需要改变地块之间相互作用的规则,而不改变模型框架。这有助于快速实验和假设测试。
有两个点火点的野火反弹道导弹。原始图形
快速实验并不是 ABM 优于自顶向下方法的唯一优势。考虑被建模的个体中的变化会在自上而下的模型中引入显著的复杂性,而在基于代理的方法中是微小的变化,因为这种异质性可以被变化的个体代理捕获。这可用于捕捉差异,如野火模拟中不同的燃料水平,或创建模仿流行病模型的人口普查数据的代理群体。
ABMs 不局限于在模拟物理空间中交互的代理,模型框架扩展到代理交互的非物理限制,例如限制代理只与他们“知道”的其他代理交互。这允许引入社会异质性,许多代理人属于封闭的社会圈子,而较少的高度社会化的代理人连接这些圈子。
这是在下面的简单流行病模型中通过将代理的社会联系表示为具有小世界属性的网络来实现的。
具有小世界相互作用的简单 ABM 流行病模型。原始图形
这也让我们能够探索限制社会交往如何影响流行病的持续时间和强度的程式化事实。在该模型中,这是通过减少网络中的平均连接来实现的,这类似于个人减少与他们最亲密的朋友和家人的物理接触。
与上面相同的流行病模型,但是社会联系减少了 40%。原始图形
ABM 的另一个关键优势是潜在假设的可解释性,这可以为结果提供信心,并使发现更容易沟通。例如,对收入不平等和税收影响的自上而下的分析通常是高度数学化的,并且对个人非常抽象,这使得政策决策的沟通成为一个持续的挑战。
各种税收制度下的收入平等——基尼系数越高,不平等程度越高。原始图形
另一方面,自下而上的 ABM 方法允许模型减少到只有三个步骤,每个周期由代理重复:1)与他们有社会联系的代理随机交易,如在流行病模型中;2)缴纳交易所得税,如果财富低于最低水平,则领取福利金;3)产生固定的生活费用,并获得储蓄利息。注意到这些假设没有提到每个代理人的工作道德或生产力,模型的程式化事实仍然模仿自上而下模型中发现的事实,特别是统一税导致比累进税更高的财富不平等(以基尼系数衡量),以及需要福利支付以防止固定生活成本使大部分代理人破产。
不幸的是,通常缺乏关于这些基本假设和输入的知识,因为有关系统的相关数据通常是在总体水平上而不是在单个水平上获取的。此外,模型输出通常对所使用的输入敏感,这可能极大地限制预测中的使用并削弱信心。
一种解决方案是将假设捕捉为一组参数,然后优化参数以拟合历史数据,针对各种参数组合运行模型,直到模型输出与观察到的数据相匹配。然后,来自该调整模型的参数被用于正在进行的预测或建模练习。这种实践增加了对所产生的洞察力的信心,并在模拟世界和现实世界之间提供了更强的联系。
虽然 ABM 技术并没有取代传统的自上而下的方法,但它们确实提供了一种替代的视角,并且在某些情况下提供了一种方法来处理那些太复杂而无法以自上而下的方式定义的问题,或者代理表现出大量异质性的问题。虽然编写和测试 abm 需要一定水平的技术技能,但由于模型框架的可重用性和开源库(如 Mesa for Python)的存在,这种学习曲线变平了,Mesa for Python 为代理、代理交互和数据捕获提供了通用框架。最后,通过易于沟通的假设和方法,增加了对模型结果的信心。通过将模型输入建立在已知真实世界数据的基础上并优化参数以适应历史观察,这将得到进一步的测试和改进。
这个故事是基于代理的建模系列的第一篇,是基于我自己对构建 abm 的研究和实验。如果你想跟进,请考虑关注我的个人资料或这份出版物。
一些来源如下:
https://www . science direct . com/science/article/pii/s 1755436517300221
关于如何维护人工智能/人工智能模型的六点框架
行业笔记
随着疫情在我们的世界上发生了巨大的变化,我们不能总是依赖我们用来训练和构建我们的第一个模型版本的历史数据。我们都知道——或者我们现在应该意识到——这些最初的版本会以某种方式崩溃。这只是时间问题。在我们去年 12 月的第一篇文章中,我们讨论了为什么你需要在你的 AI/ML 模型上进行模型监控。让我们通过考虑一个整体框架来维护我们的模型,来拓宽我们的讨论和视野。这一点至关重要,因为模型是活生生的功能性工具,支持我们的业务决策、推动收入、降低成本,并代表着公司的重大投资。简单地监控模型是一个好的开始,但是还不够,特别是当您想要扩展到生产中的少数模型之外的时候。
一个整体的框架应该确保你的模型没有偏见(我们都记得亚马逊的招聘模型,它只使用大部分男性进行培训)。它应该包含可解释性。它应该涵盖我们在重新培训时完全再现性所需的所有内容。我们将其分为以下六个要点。
1.一个有据可查的目的是第一步。我们的模型应该与我们的商业目标和目的一致,否则它们会变得陈旧和失去效力。这似乎是显而易见的,但经常被忽视,因为有时建模者为了他们的研究或满足他们的求知欲而更多地参与构建它们。正如我的同事大卫·布洛赫在他的博客中所说,“挑战的一部分是评估一个好决策的价值的困难。”有时,可以使用模型来阐明这些决策,并更紧密地映射和量化它们对业务的价值。有了这个目的,并了解实际的业务目标,就可以将模型从数据科学项目中转移出来,并使其成为业务的一个合法部分。有目的的方法的一部分是考虑您的目标、KPI 和其他指标,以评估 ROI 并填写有关目标最终用户和交付机制的详细信息。另一部分是理解一个模型在满足特定业务标准之前和之后将如何被使用。
2.**数据血统详情。**每个模型都有一些内置的底层数据。诀窍是捕捉这些细节,以及如何准备足够详细的数据,以确保模型可以重现和可信。这在审计时也很有用,所以我们不必试图追踪模型的数据来源,也不必从头开始。
正如我在之前的文章中提到的,即使是最好的模型也会进化,因为底层数据和关系会随着时间而变化。拥有这种数据谱系是跟踪并有望防止概念漂移的关键,概念漂移是指世界在变化,但模型没有反映这些变化。这种偏差可能是由数据分布、测量值或潜在用户群的变化引起的,而这些变化可能会被您的模型忽略。如何记录这些变化至关重要。
3.**全生命周期跟踪系统。**与软件开发生命周期一样,这是一个将模型运行与特定数据版本联系起来的过程,也是记录对模型元素所做的各种更改的另一种方式,这些更改是实验性构建过程的一部分。想想 GitHub 在跟踪程序代码版本方面做了什么,Docker 在跟踪系统定义和组件方面做了什么,Kubernetes 在跟踪和编排计算版本方面做了什么。当我们完成各种模型运行时,我们需要记录这些元素,这样我们可以注释我们的进展,并显示我们如何修复模型的各种问题。我们的模型的演变几乎比实际模型本身更重要,因为我们可以更好地理解我们正在建模什么,以及为什么我们不仅选择首先构建它们,而且还要调整它们的数据输入和假设。
4.一个模型注册中心,链接到上面提到的生命周期跟踪系统。注册表还可用于跟踪模型版本历史,其中每个版本都可以完全重现,其元素与我们在更改数据、代码、软件和硬件平台方面的实验相同。理想的情况是拥有一个带有汇总仪表板的中央注册表,您可以在其中浏览模型版本并深入了解每个版本的历史。
5.验证例程记录代码审查,报告关于道德和偏见检查的各种解释,并获得用户的批准。这也是报告其服务水平协议和我们所做的其他功能测试以及评论其总体生产准备情况的好地方。我见过很多建模者跳过这一步。验证是确保模型确实如您所愿的关键。这也是在模型的使用寿命即将结束,需要淘汰或重建时做出决策的关键。
6.最后一点是有一个开放式模型监控系统。这就是我在 12 月的帖子中讨论的内容,应该用于捕获数据漂移、单一接地真相、测量精度等项目,并提供深入分析信号故障的功能。监控系统还应该能够检测异常情况,并在超过特定阈值时自动向利益相关者发出警报。
随着您扩大在数据科学和建模方面的投资,您将需要管理和维护您的业务日常所依赖的不断增加的模型集合。这里有两种方法可以开始。首先,根据这里提到的六个目标中的每一个目标,检查您当前的模型维护计划。第二,为这项工作建立一个特别工作组,或者考虑寻求外部帮助。这将需要时间和资源的前期投资,但您最终会得到更好的模型,它们寿命更长、更安全,并在指导您的业务决策方面发挥更大的作用。在未来几年中,在模型护理方面领先的企业将在竞争优势方面处于有利地位。把这种资源看作是一种为你的企业设想和指导一个坚实的未来的方式。
如何在 Python 中分割序列
了解如何在 Python 中分割列表和字符串
格伦·卡斯滕斯-彼得斯在 Unsplash 上拍摄的照片
能够有效地分割 Python 中的序列(比如列表、字符串和元组)是编程时最重要的技能之一。幸运的是,python 提供了索引语法,极大地方便了切片过程,并使其更加直观。
在本教程中,我们将首先回顾如何索引一个序列,然后继续切片序列,特别是列表和字符串。此外,我们将涵盖切片列表和切片字符串之间的一些重要差异。然后,我们将查看列表中的片分配。最后,我们将看看在 Python 中使用索引语法时到底发生了什么。
索引序列
在我们开始切片之前,让我们简单回顾一下如何在一个序列(特别是一个列表)中索引元素。
请记住,我们可以通过使用方括号中的索引来访问列表中的单个元素。让我们看看下面的数字列表:
num_list = [0,5,10,15,20,25,30,35,40]
0,1, 2, 3, 4, 5, 6, 7, 8
-9,-8,-7,-6,-5,-4,-3,-2,-1
序列中元素的索引是它在序列中的位置。在上面的例子中,我们有一个数字列表, num_list ,列表下面的数字代表相应元素的索引。我们可能还记得,我们可以从开始处(从左侧开始)对序列进行索引,从索引 0 开始进行正索引,或者从序列的结尾处(从右侧开始)进行负索引,从索引-1 开始。
换句话说,如果我们想从 num_list 中检索数字 10(或第三个元素),我们可以使用它的正索引 2,也可以使用负索引-7:
num_list[2]
#10or num_list[-7]
#10
如果我们想获得列表中的最后一个数字 40,我们可以使用索引 8 或-1:
num_list[8]
#40ornum_list[-1]
#40
或者我们可以使用 len()函数,如下所示:
num_list[len(num_list)-1]
#40
如果我们使用一个不在列表中或超出范围的索引值,我们将收到一个 IndexError:
num_list[12]
#IndexError: list index out of rangenum_list[-12]
#IndexError: list index out of range
既然我们已经回顾了如何使用正索引和负索引来索引一个序列,让我们来看看切片。
分割序列
我们刚刚看到了如何使用索引从列表中检索单个元素。另一方面,切片允许我们从序列中获取一部分,比如一个列表或字符串。
有时,为了理解切片,想象索引指向元素之间,而不是指向元素本身是很有用的。尽管这仅在步长值为正值时有用,也就是说当我们从左向右切片时。稍后将详细介绍步长值。
num_list = [0,5,10,15,20,25,30,35,40] +---+---+----+----+----+----+----+----+----+
| 0 | 5 | 10 | 15 | 20 | 25 | 30 | 35 | 40 |
+---+---+----+----+----+----+----+----+----+
0 1 2 3 4 5 6 7 8 9
-9 -8 -7 -6 -5 -4 -3 -2 -1
对序列进行切片的语法如下:
变量[开始:停止:步进]
为了分割一个序列,我们需要在方括号中使用冒号。换句话说,下标符号[方括号]中的冒号(:)构成切片符号。尽管我们可以在括号中提供三个可能的值(开始值、停止值和步/步幅值),但我们实际上不必提供所有三个值,除非我们需要,正如我们将在下面看到的。
让我们看一些例子。
指定开始和停止值
我们分割一个序列(比如一个列表)的一种方法是指定起始值和终止值。换句话说,如果我们想要列表中两个特定点之间的所有元素,我们可以使用以下格式:
变量[开始:停止]
variable[start:stop]返回以位置 start 开始的变量部分,直到但不包括位置 stop。
例如,如果我们想获得从索引 2 到索引 6 的所有元素,我们可以这样做:
num_list = [0,5,10,15,20,25,30,35,40]num_list[2:7]
#[10,15,20,25,30]
注意开始值是如何包含的,但是停止值是如何排除的。因此,我们从索引 2(即数字 10)开始,一直到但不包括索引 7(即索引 6 处的数字 30)。如果我们将索引想象为元素之间的索引(如上所示),那么将进一步说明这一点,因为索引 7 在数字 35 之前。由于我们没有提供步长值,的默认步长值是 1 。因此,我们从索引 2 开始,然后向索引 3 前进 1 步,再向索引 4 前进 1 步,依此类推。换句话说,因为步长值是正的,所以在对列表进行切片时,我们将索引增加 1(向右移动)。
仅指定起始值
如果我们想从一个特定的数字开始并遍历整个列表,那么我们只需要提供起始值。
变量[开始:]
variable[start:]返回从位置 start 开始到序列结尾的变量部分。
例如,如果我们想从整个列表的第二个索引中检索所有元素,我们可以使用下面的代码:
num_list = [0,5,10,15,20,25,30,35,40]num_list[2:]
#[10,15,20,25,30,35,40]
正如我们所看到的,如果我们只在冒号前提供一个索引,那么这将是我们的开始索引,我们将获得列表中的其余元素(因为步长值仍然是 1)。
仅指定停止值
如果我们想从列表的开头开始,一直到一个特定的索引,那么我们只需要提供停止值。
变量[:停止]
variable[:stop]返回从序列开始处开始的变量部分,直到但不包括位置 stop。
例如,如果我们想要检索从列表开始到索引 7(包括索引 7)的所有元素,我们可以这样做:
num_list = [0,5,10,15,20,25,30,35,40]num_list[:8]ornum_list[:-1]#[0,5,10,15,20,25,30,35]
因此,如果没有为起始值提供数字,那么它假设我们希望从索引 0 开始。由于我们想要检索索引 7 之前的所有元素,我们将使用停止值 8,因为它是排他的。我们也可以使用-1 作为停止值。
使用正指数和负指数
我们也可以混合搭配正负指数。例如,如果我们想要检索索引 2 到索引 7 之间的所有元素,我们可以这样做:
num_list = [0,5,10,15,20,25,30,35,40]num_list[2:8]or num_list[2:-1]ornum_list[-7:-1]ornum_list[-7:8]#[10,15,20,25,30,35]
注意,在所有情况下,停止值都在起始值的右边,因为我们使用的是正的步长值。换句话说,相对于起始值,停止值必须在步长值的方向上。如果步长值为正,则停止值必须在起始值的右侧。如果步长值为负,则停止值必须位于起始值的左侧。稍后会详细介绍。
检索整个列表
我们还可以通过使用不带开始或结束值的冒号来检索整个列表。
变量[:]
变量[:]返回整个序列。
num_list = [0,5,10,15,20,25,30,35,40]num_list[:]or num_list[::]#[0,5,10,15,20,25,30,35,40]
步幅值
到目前为止,我们只指定了开始和/或停止值,我们从开始值开始,在停止值之前结束(因为它是唯一的)。但是如果我们不想要这两点之间的所有元素呢?如果我们想要所有其他元素呢?这就是步长值的来源。
假设我们需要列表中的所有其他值,从索引 0 开始。或者我们只需要偶数索引的元素。我们可以使用步长值来实现:
变量[::步长]
num_list = [0,5,10,15,20,25,30,35,40]num_list[::2]#[0,10,20,30,40]
因为我们没有指定开始或停止值,所以它假设我们想要从序列的开始处开始并遍历整个列表。所以它从索引 0 开始,然后到索引 2(因为步长是 2),然后到索引 4,依此类推。
**之前我们提到过,相对于起始值,停止值必须与步长值方向相同。**换句话说,如果步长值为正,这意味着我们向右移动,停止值必须在起始值的右边。如果步长值为负,则停止值必须位于起始值的左侧。否则,将返回一个空列表:
num_list = [0,5,10,15,20,25,30,35,40]num_list[8:5]
#[]num_list[8:5:-1]
#[40,35,30]
正如我们所看到的,在两个例子中,开始值是 8,停止值是 5,所以停止值在开始值的左边。在第一个示例中,步长值为+1。因为停止值在开始值的左边,而我们的步长值是正的,所以返回一个空列表,因为我们不能向停止值的方向移动。然而,在第二个示例中,我们将步长值更改为-1。因此,我们从索引 8(40)开始,向负方向或左方向移动 1 个索引到索引 7(35),然后到索引 6(30)。我们不去索引 5,因为停止值是唯一的。
颠倒顺序
也许步长值最重要的实际应用是反转一个序列。例如,如果我们想以相反的顺序检索整个列表,我们可以使用-1 作为步长值:
num_list[::-1]#[40,35,30,25,20,15,10,5,0]
因为我们没有指定开始或停止值,所以将检索整个序列。但是,因为我们的步长值是-1,所以它以相反的顺序获取元素。
如果我们的止损值大于序列中可用的最高指数,该怎么办?或者我们的开始和/或停止值是否超出范围?换句话说,如果我们要求的东西比现有的多,会发生什么?
例如,如果我们尝试以下方法:
num_list = [0,5,10,15,20,25,30,35,40]num_list[2:12]
#[10,15,20,25,30,35,40]
正如我们所看到的,即使我们请求的条目比序列中的多,它也只是返回所有存在的元素,而不会给我们一个错误。相比之下,如果我们试图索引一个超出范围的元素(而不是切片),那么我们会得到一个 IndexError,就像我们前面看到的那样。
num_list[12]
#IndexError
分割字符串
索引和切片对于字符串也是同样的工作方式。同样,如果我们使用如下的正步长值,我们可以想象字符之间的索引:
word = 'Python' +---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
因此,为了通过切片获得子串“yt ”,我们可以这样做:
word[1:3]#'yt'
要反转一个字符串,我们可以使用步长值-1:
word[::-1]#'nohtyP'
回文示例
让我们用我们所学的知识来解决一个非常常见的 python 编码问题。我们想写一个函数,接受一个字符串,并返回这个字符串是否是一个回文。如果一个字符串的倒数与原字符串相同,则该字符串为回文。例如,“civic”是回文,但“radio”不是,因为“radio”的反义词是“oidar”,而“civic”的反义词是“civic”。
我们刚刚学习了如何通过使用步长值-1 来反转序列。因此,我们可以很容易地编写一个函数来实现这一点,如下所示:
isPalindrome(word):
return word == word[::-1]
就是这样!表达式 word == word[::-1] 的计算结果为真或假。如果我们传入的字符串等于它的倒数,那么表达式的计算结果为 True,返回 True。如果我们传入的字符串不等于它的倒数,那么表达式的计算结果为 False,并且返回 False。
isPalindrome('civic')
# TrueisPalindrome('radio')
# False
切片分配
如果我们记得,列表是 python 中的可变对象。换句话说,它们能够变异或改变。因此,我们可以使用片分配操作来适当地改变或编辑列表。
代替
num_list = [0,5,10,15,20,25,30,35,40]num_list[2:5] = [1,2,3]num_list
#[0,5,1,2,3,25,30,35,40]num_list[2:5] = [1,2,3,4,5,6]num_list
#[0,5,1,2,3,4,5,6,25,30,35,40]
注意我们如何用更多或更少的元素替换列表的一部分。
删除
我们还可以使用 del 关键字删除列表的一部分或片段:
num_list = [0,5,10,15,20,25,30,35,40]del num_list[2:5]num_list
#[0,5,25,30,35,40]
注意:字符串和元组是不可变的。因此我们不能像对列表那样编辑或改变它们。
分割字符串与列表
分割列表将返回该列表的副本,而不是对原始列表的引用。
我们可以在这里看到这一点:如果我们将我们的列表片分配给另一个列表,因为列表片返回一个副本,而不是对原始列表的引用,我们可以修改新列表(因为列表是可变的)而不影响原始列表:
num_list = [0,5,10,15,20,25,30,35,40]# assign a slice of num_list to new_list
new_list = num_list[2:5]new_list
#[10,15,20]# replace the third element of new_list with 3
new_list[2] = 3# new_list changes
new_list
#[10,15,3]# num_list remains the same
num_list
#[0,5,10,15,20,25,30,35,40]
相比之下,当我们分割一个字符串时,返回的是对原始字符串对象的引用,而不是副本。记住,字符串在 Python 中是不可变的。
我们可以使用 Python 的标识操作符(is)和等式操作符(==)来确认对列表进行切片会返回一个副本或不同于原始列表的对象,但是对字符串进行切片会返回对原始字符串对象的引用:
**Lists:**num_list = [0,5,10,15,20,25,30,35,40]num_list == num_list[:]
#Truenum_list is num_list[:]
#False**Strings:**word = 'Python'word == word[:]
#Trueword is word[:]
#True
相等运算符(==)检查值是否相等。identity 运算符(is)检查这两个变量是否指向内存中的同一个对象。
https://levelup.gitconnected.com/the-ultimate-guide-to-sorting-in-python-d07349fb96d5
切片函数
当我们在 python 中使用索引语法时,包括在方括号中使用冒号,内置的 slice 函数实际上被用来创建一个 slice 对象。
切片(停止)
切片(开始,停止[,步进])
slice 函数可以以两种不同的方式创建 slice 对象(类似于创建 range 对象的 range 函数)。如果我们给 slice 函数传递一个参数,那么这就是停止值。如果我们向 slice 函数传递三个参数,那么它们将具有开始、停止和步进值。换句话说,起始和步长参数将默认为无。
以下是一些示例,显示了使用索引语法对列表进行切片时使用的切片对象:
num_list[:8] is equivalent to num_list[slice(8)]num_list[2:8] is equivalent to num_list[slice(2,8,None)]num_list[2:] is equivalent to num_list[slice(2,None,None)]
如果我们想要保存一个特定的 slice 对象并多次使用它,使用 slice 函数创建一个 slice 对象会很有用。我们可以这样做,首先实例化一个 slice 对象并将其赋给一个变量,然后在方括号中使用该变量。
evens = slice(None,None,2)num_list[evens]
#[0,10,20,30,40]odds = slice(1,None,2)num_list[odds]
#[5,15,25,35]
如果你喜欢阅读这样的故事,并想支持我成为一名作家,考虑注册成为一名媒体会员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你用我的 链接 注册,我会赚一小笔佣金。
https://lmatalka90.medium.com/membership
结论
在本教程中,我们首先回顾了索引序列意味着通过使用方括号中的正或负索引来提取单个元素。然后,我们比较了索引序列和切片序列,后者可以检索序列的一部分。我们学习了如何用方括号和冒号分割序列,包括指定我们想要检索的部分的不同方法。由于 Python 中的列表是可变的,我们看到了如何使用片赋值来改变列表的一部分。然后我们看到了分割一个列表和分割一个字符串之间的区别,因为分割一个列表会返回该列表的一个副本,但是分割一个字符串会返回一个对原始字符串对象的引用。最后,我们看到了在 Python 中使用切片符号时切片对象是如何被实际使用的。
一篇关于居住和沉思的演讲
机器学习和就职演说
1 月 20 日,按照宪法治理的正常流程,拜登总统宣誓就职。总统用演讲来纪念这一时刻——通常具有特别的说服力。在他们关于就职演说的经典方法中,Karlyn Kohrs Campbell 和 Kathleen Hall Jamison 认为就职演说通常是由他们的条件所决定的,这些演说重新组成了“人”,论证了总统职位的可能性和局限性,并且在邀请沉思中是永恒的。最好的就职演说会提出一些深刻的论点,它们不像威尔逊式的国情咨文,读起来像是一系列政策建议。里根的第一次就职颁布了跨领域的统一复兴幻想。奥巴马的第一次就职解散二进制,建立新的国家统一。坎贝尔和贾米森总结了就职演说的作用:
就职典礼必须复述过去的公共价值观,阐明指导新政府的政治原则,并证明总统能够恰当地扮演总统角色。
这是有道理的,在大多数情况下,这些地址会有非常相似的签名,因为它们可能会说许多相同的事情。在这篇文章中,我不是在阅读演讲的语义内容。我以前用情绪分析做过这个,在这一点上,这位即将离任的高管的风格是众所周知的——高度多变、情绪化、粗暴和好斗。
就职的签名
情感分析是一个有用的工具,但是经常被过度使用。在我们今天看到的背景下,知道使用普通词汇是有用的。拜登今天的情绪比他的前任更消极,但变化较小。这对于具有简单连接的词汇的情感分析来说是一个问题:高价值单词的混乱可以产生非常正常的和或平均情感得分,这只能通过偏差来揭示。深刻负面的文本很容易得到正面的分数。
我没有为了感悟而阅读,而是把拜登的就职演说加入了一个更大的可以追溯到 JFK 的就职文集。使用 Mallet for LDA,一种机器学习方法,我们可以使用停用词的一般选择来读取三十个主题的语料库。
我们三十个话题的标签
主题之间的关系如下:
请注意,话题 11 和 24 是在底部结合在一起的——这些话题在很大程度上与总统之间的共同价值观有关。12 和 23 这一组讲述了关于阿灵顿国家公墓的讨论和不断变化的对话。而在第 19 题的第一个休息处,我们可以找到每一位总统列举的人物的开头段落,比如众议院议长。在我做过的 LDA 驱动的项目中,这是在主题层面上最连贯的。机器学习的远距离阅读过程增强了近距离阅读的修辞阅读维度,作为一名研究总统沟通的研究人员,我可以以我坐在几十页纸上永远无法做到的方式快速查看和判断案件。
重要的是就职演说有多少,它们是如何进行的,以及总统们是如何选择一些话题的。每位总统都会留下一个特别的签名。
为了这个图形的目的,只有超过 0 . 4 的值被包括在内,毕竟每个段落都有 30 分,我们不需要图形的底部完全拥挤。你可以在第二届就职典礼上看到紧缩,因为与上届政府没有什么不同。为了量化这种转变,我们需要查看平均赋值值、赋值总数和每个单词的赋值。
主题 11 是最常见的作业。这里的特殊异常值包括尼克松关于越南战争结束的言论被框定为和平(29),除了特朗普咄咄逼人的一段。话题 30 是对美国的祝福和忠诚,这是拜登的一个中心主题,一个典型的总统可能会说一两个。
第二次就职典礼往往有更高的平均分配值和更高的最大值(奥巴马是一个例外),这将再次表明第二次演讲更集中。从这个意义上来说,拜登读起来更像是第二次就职演说,尽管他的最高分出现在主题 11、16 和 30,其中拜登的标志性主题“献身美国”非常明显。JFK 使用话题 11,然后是话题 26,这是一个被许多人使用的外交政策话题,但在乔治·w·布什的作品中只出现过一次。这是有道理的,因为他的第一次演讲是在 9/11 之前,但他关于外交政策的最有力的陈述是在主题 8 中——因为它们是用莱茵霍尔德·尼布尔的语言表达的,古典现实主义——它们是灵魂的问题。这也证实了另一件事:除了议题 26 中的合作语言,没有外交政策驱动的就职演说,外交政策问题隐藏在美国公民宗教中。
我们可以用这种方法确认,奥巴马的第一个是关于主题 11,然后是主题 21——一个关于克服二进制的旅程的主题。60%的 topic 21 位置来自奥巴马的第一个,Nixon1 使用了两次,Reagan2 和克林顿 1 使用了单个段落。里根的用法特别有趣,因为这是一个关于历史终结的混合隐喻:“这首歌永远回荡在未知的空气中。”
最后,考虑主题被检测到的速率是很重要的。
拜登的演讲相当长,话题比平均水平多,话题发现率接近平均水平。除了奥巴马,每第二次演讲都比前一次详细。当然,有一个引人注目的异常值,我们已经确定它与其他异常值在性质上是不同的。
结论
拜登总统就职演说的修辞信号在主题选择和变化上都符合预期。主题建模过程进一步表明,除了被检测为主题 11 的标准框架(国家的未来承诺),拜登的演讲通过对美国和民主的主题关注为语料库贡献了独特的签名。虽然读数完全有可能会发生变化,但在这种最初的机器学习驱动的方法和对这些结果的修辞性阅读的背景下,很明显,拜登总统发表了一个非常符合就职典礼形式的演讲,并且非常适合这个时刻。最后,我们可以清楚地看到支持就职演说研究的悠久历史的证据。
影响公民幸福感的社会因素的统计分析
使用线性回归对不同因素进行深入的统计分析
图片由 Ricardo Moura 在 Unsplash 上拍摄
摘要
本文旨在探索可能影响全球公民幸福的各种社会、城市和国家因素。报告的布局包括对用于分析数据的方法的描述,包括数据集选择、数据清理和预处理、探索性数据分析和数据建模(使用多元线性回归),然后是对每个阶段的调查结果的详细分析。该分析集中于确定对幸福分数的预测和我们的拟合模型的质量有贡献的各种因素的重要性。在我们进行的过程中,每个阶段都会回答多个子问题。然而,最重要和最有趣的分析结果在最后进行了总结,并提出了可行的建议。
介绍
随着 COVID 的出现,一种绝望和不确定感笼罩了整个世界。全世界人民的福祉和精神健康受到严重影响。这暗示了这样一个想法:随着世界一天天进步,我们的注意力更多地转向永无止境的进步,而不是真正重要的事情。我们忽略的一件事就是幸福。了解幸福的决定因素以及它们如何影响个人的福祉非常重要,这样我们作为一个社会可以共同努力改善它们,以形成一个更幸福的环境。因此,在本报告中,我们开始着眼于更大的图景,并确定以下研究问题的答案:
“公民的幸福如何取决于各种社会、城市和国家因素?”
数据集
《世界幸福报告》是一项具有里程碑意义的全球幸福状况调查。这项调查是 2012 年发起的同类调查之一,自那以来每年在 155 个国家进行。它衡量了几个社会、城市、国家和个人因素,这些因素可能会以这样或那样的方式影响幸福。幸福指数较高的国家被认为更幸福,更有利于公民的福祉,而幸福指数较低的国家则被鼓励实施以公民为中心的政策。总的来说,该报告因其完整性和在跨学科研究中的实用性而获得了巨大的全球认可。
我们将使用的数据集是 2015 年至 2019 年的世界幸福报告。它基于五个 CSV 文件,即每年一个文件,这些文件合并在一起形成一个整合的数据集。我们打算确定这些年来国内生产总值、家庭、健康和预期寿命、自由、无腐败和慷慨对公民福祉的贡献程度【1】。关于本次调查数据收集过程的背景研究显示,受访者被要求参加盖洛普世界民意测验。他们必须对上述每个因素对他们生活的影响进行评分,满分为 10 分,最低分为 0 分(即该因素不会带来幸福),最高分为 10 分(即该因素对他们的幸福贡献很大)。
方法
为了系统地找到我们的研究问题的答案,我们将我们的方法分为三个阶段,即数据清理(和预处理)、探索性数据分析(EDA)和最后的回归分析。
数据清理
在开始分析之前,理解和预处理数据是很重要的。我们首先导入我们需要用于分析的相关库。接下来,我们读取数据集并检查它们的维度,以了解我们正在处理的行数和列数。
图 1:数据集维度的 R-输出
正如我们所见,每个数据集中的列(要素)数量各不相同。我们选择了所有数据中共同的数据,以形成一个更大的数据集,并去掉不同的数据。然后,我们分别清理每个数据集。他们每个人都遵循相似的模式。我们首先检查每个数据帧中的空值,并相应地处理它们。幸运的是,我们在数据帧中几乎没有发现空值。如果我们有,我们适当地估算他们。然后,我们对列进行了标准化,即为了便于访问而对它们进行了重命名,将名称转换为小写,并检查了适当的数据类型。为了确认数据清理是否成功,我们从每个数据集中抽取了 10 行样本,并检查我们所做的更改是否成功应用。
在分别清理数据帧后,我们将它们合并成一个名为 *df 的数据帧。*它由 782 行和 10 列组成,如下面的 R 输出所示:
R-组合数据集的维度和列的输出
然后我们检查数据集是否有空值,我们在 corruption 列中发现了一个空值。我们有两个选择,要么删除行,要么填充空值。我们决定采用后者,并用腐败列的平均值来估算缺失值。
R-清洗前后的空值输出
上面 R 输出中的 False 表示现在数据集中没有空值或缺失值。
最后,我们检查每一列的数据类型是否合适,或者我们是否需要改变什么。让我们来看看:
R-列数据类型的输出
除了 country 之外的所有列都具有数值或整数数据类型。事实上,这些就是我们分析中将要用到的列(或前面提到的起作用的因素)。因此,列的当前数据类型对于我们的后续分析来说是很好的,因此不需要标记或编码。这使我们进入方法的第二阶段,即探索性数据分析(EDA)。
探索性数据分析
对于一个 782 行 10 列的数据集,重要的是从分析数据在正式建模、回归分析和其他测试之外能够揭示什么开始。因此,我们进行了探索性数据分析,以可视化数据并总结其特征。我们还想看看是否有任何明显的趋势,以便我们可以相应地构建我们的研究问题。
分析的特征
现在,我们知道我们有 10 个特征。其中之一是幸福得分,这是因变量。我们使用的数据源和其他网站的背景研究使我们能够找出自变量的确切含义和目的。其中每一项的详细情况如下:
数据集中特征(列)的描述
相互关系
既然我们知道了每个特性代表什么,我们想看看这些特性是如何相互关联的。我们以相关矩阵的形式计算不同特征之间的皮尔逊相关®。我们检查了每一个变量,看它们是正线性相关,负线性相关还是没有。
皮尔森特征间的相关性
为了便于解释,我们随后在彩色编码的热图中绘制了相关性,并附有一个参考尺度来理解它。产生的图如下:
关联热图®
从右边的刻度可以明显看出,特征之间较暗的图表示强线性相关性(r 更接近+1)。蓝色代表正线性相关(r > 0),而红色代表负线性相关(r < 0)。显然,特征与其自身的相关性是 1,即完全相关。令人惊讶的是,没有一个特征与另一个负相关。这暗示了一个事实,因为所有的预测变量都以一种形式衡量幸福,增加其中一个并不会导致另一个因素的减少。分数,我们的反应变量,与其余特征有最强的正相关。GDP、家庭和健康与其余变量也有中等程度的相关性,但慷慨度与其他变量的相关性最弱甚至没有相关性。
由于我们的主要目标是预测幸福分数和影响幸福分数的因素,我们决定更深入地研究每个可能的因素与幸福分数(因变量)的相关性,以了解哪些因素更有可能强烈影响幸福分数。这一次,我们打算查看皮尔逊相关的确切值,以做出尽可能准确的判断:
特征与分数的皮尔逊相关性
幸福得分与所有考虑的因素呈线性正相关。它与 GDP 的相关性最强,其次是健康和家庭。它与自由有适度的相关性,与腐败和慷慨有微弱的正相关性。
幸福分数
在探索性数据分析的前两个步骤中,我们非常重视我们的响应变量——得分。让我们更深入地了解它,以了解它在数据集中的分布。这将使我们对回归建模结果的解释更加容易。如前所述,幸福指数是人们在调查时对自己幸福程度的评价。可能的最高分是 10 分(这意味着回答者是他/她所能得到的最快乐的人),最低分是 0 分(这意味着回答者一点也不快乐)。
幸福指数的五位数汇总显示,幸福指数在 2.693 到 7.769 之间。平均幸福指数为 5.379,平均幸福指数为 5.322。最低和最高分数足够合理,即它们既不太低也不太高。由于没有异常值(如下面的方框图所示),很明显没有需要考虑的幸福指数特别高或特别低的国家。
同样,下面的幸福得分分布也表明,甚至没有一个国家的幸福得分是完美的。事实上,所有国家的幸福指数都低于 8。大多数国家的幸福指数在 5 到 6 之间(包括平均值和中间值)。所以总体来说,幸福得分的分布是对称的。
乡村幸福指数
虽然对幸福分数的国别分析超出了我们研究问题的范围,但注意到不同国家幸福分数的差异还是很有趣的。因此,我们决定鸟瞰各国的幸福指数。
下面的世界地图(以 R 绘制)显示了我们数据集中 156 个国家的彩色幸福指数。光谱左侧的颜色(即蓝色阴影)不太快乐,而光谱右侧的颜色(即红色和黄色阴影)更快乐。看看这张地图,像巴西、俄罗斯、美国和加拿大这样的发达国家显然比不发达国家更幸福。
世界范围内相关量表的幸福得分
为了有一个更具体的图片,前 20 个最幸福的国家和他们的分数被绘制如下:
回归分析
在使用预测变量和反应变量的可视化和总结彻底理解数据后,我们继续通过一个模型来理解所选预测变量对幸福得分的影响。
我们使用对幸福得分起作用的因素的多元线性回归,假设我们的预测变量与响应变量有线性关系(根据之前计算的皮尔逊相关值推断)。
该模型的基本思想是找到 GDP、家庭、健康、自由、腐败和慷慨程度的线性组合,这种组合最能预测幸福得分。我们确定了显著变量(用回归模型汇总表的 p 值< 0.05) in the prediction of score. Important diagnostics for the model included determining coefficient of determination (R-squared and Adjusted R-squared) and making and analyzing ANOVA table. We also visualized our model and the residuals using Residual Plots and Q-Q plots the interpretations of which are discussed in the latter part of the report. Lastly, to make sure our model was not faulty (i.e., it neither underfitted nor overfitted), we also employed several measures — tested multicollinearity, data distribution and then drew final conclusions from the results.
Analysis
Multiple Linear Regression
As mentioned earlier, we employed Multiple Linear Regression to model the dependence of response variable (happiness score) on a set of predictor variables (GDP, family, health, freedom, corruption, and generosity). The relevant R code for this is shown in the excerpt below alongside the summary table of the regression model as the output.
R 输出
回归方程式
根据上面的 R 输出,我们构建了以下回归方程来预测幸福得分:
得分= βo + gdpβ1 +家庭β2 +健康β3 +自由β4 +腐败β5 +慷慨β6
**得分= 2.17749+1.14675 * GDP+0.64109 *家庭+1.00394 *健康+1.47913 *自由+0.85366 腐败+0.59359 慷慨
上述方程的这些系数被解释为当一个变量改变 1 个单位而所有其他变量保持不变时幸福得分的边际增加。
βo :在所有其他预测因素都不在模型中的情况下,幸福得分将为 2.17749
gdp :如果所有其他特征保持不变,那么 gdp 每增加一个单位,幸福指数就会增加 1.14675 个单位。
家庭:如果其他所有特征保持不变,那么家庭(社会支持)水平每增加一个单位,幸福得分就会增加 0.64109 个单位。
健康:如果所有其他特征保持不变,那么健康(预期寿命)每增加一个单位,幸福指数就会增加 1.00394 个单位。
自由度:如果其他所有特征保持不变,那么自由度每增加一个单位,幸福得分就会增加 1.47913 个单位。
腐败:如果所有其他特征保持不变,那么腐败(在我们的上下文中,是对政府的信任)增加一个单位将导致幸福指数增加 0.85366 个单位。
慷慨度:如果所有其他特征保持不变,那么慷慨度增加一个单位将导致幸福得分增加 0.59359 个单位。
特征显著性(p 值)
通过分析回归模型汇总表中 Pr(>|t|)列中给出的 p 值,我们可以衡量每个预测变量在解释响应变量时的重要性。p 值是对观察到的差异可能只是随机发生的概率的度量,也可以称为对零假设的证据强度的度量。对于我们的模型,零假设(Ho)表明幸福得分和相应的预测变量之间没有关系。如果预测变量的 p 值小于 0.05(标准阈值),我们将认为它在估计响应变量中具有重要意义。
从汇总表中可以看出,Pr(>|t|)列中的所有值都小于 0.05。这表明了这样一个事实,即 Bo、gdp、家庭、健康、自由、腐败和慷慨中的所有特征在估计幸福分数时都起着重要作用。我们的回归模型的总体 p 值也小于 0.05,因此,它具有统计学意义,可以用于从给定的预测变量预测幸福得分。
下表总结了每个预测变量的 p 值及其显著性:
由各自的 p 值指示的特征(列)的重要性
决定系数
r 平方是一种统计度量,表示回归模型中自变量解释的因变量方差的比例。在这种情况下,多个 R 平方值代表了幸福分数的可变性,这可以用 6 个特征来解释。然而,在多变量回归设置中,多重 R 平方不是一个可靠的度量,因为随着我们向模型添加更多的特征,它会不断增加,即使这些特征中的一个或多个变量可能不重要(这会导致模型过度拟合)。这可能导致对我们模型预测能力的不准确估计。
因此,在这种回归模型中,采用调整的 R 平方,并确保在向模型中添加非显著变量时其值降低。在这种情况下,调整后的 R 平方的值为 0.7622 或 76.22%,这表明模型使用 gdp、家庭、健康、自由、腐败和慷慨度等特征估计了大约 76% 的幸福得分可变性。
诊断学
回归模型基于一组假设,在得出关于响应变量与预测变量之间关系的结论之前,必须检查这些假设。一是初步模型拟合;为此可以采用不同的技术。
残差与回归模型拟合图
上图显示了 y 轴上的残差值(未知误差的预测值)和 x 轴上的拟合值。理想情况下,该图应该看起来像一个随机散点图,线残差= 0,方差恒定,因为残差的总和为 0。从上面的散点图中可以看出,这些点是随机分布的,没有明显的模式会违反回归模型的一个或多个假设。在该图中,编号为 457、616 和 774 的点被表示为异常值,因为它们远离残差= 0 线,但与我们拥有的数据量相比,该数字并不显著。
回归模型的分位数图
上图显示了标准化残差和理论分位数之间的正态分位数-分位数图。它用于评估残差呈正态分布的回归假设。如果数据来自正态分布,则这些点位于图上的一条直对角线上。因此,为了使正态假设成立,这些点应该位于 y = x 线上或靠近 y = x 线。该曲线尾部的曲率表明数据中存在异常值。例如,编号为 457、616 和 774 的点在该图中被表示为异常值(就像残差图一样),因为它们远离 y = x 线。尽管与 y = x 线有一些偏差,但绝大多数数据点位于 y = x 线上,因此,保持正态假设有效。
回归模型残差直方图
为了重申残差正态分布的概念,我们还绘制了它们的直方图,以展示正态假设事实上是有效的。上面的图还描绘了平均值以 0 为中心,这是正态分布数据的情况。
我们还测试了模型的偏斜度,如上面的代码片段所示,模型只是稍微向左偏斜了–0.286,这并不多,可以忽略不计。因此,我们得出结论,我们的模型包含了需要在回归中考虑的一组假设。
方差分析
接下来,我们继续进行回归的一个组成部分,即 ANOVA 分析。以下是我们构建的方差分析表的 R 输出:
ANOVA(方差分析)测试允许同时对两个以上的组进行比较,以确定它们之间是否有任何关系。我们将逐一查看输出的主要结果:
我们的数据的自由度被计算为 N-(P+1)= 782-(6+1)= 775。这些是数据集中可以自由变化的数据值的数量。自由度将多次用于计算统计测量值,如 F 值,如下所示。
方差分析公式的结果 F 统计量(也称为方差分析系数)可以计算为
F =回归均方/残差均方。
F 统计允许对多组数据进行分析,以分析和确定样本间和样本内的变异性。如果两组之间不存在真正的差异,即两组之间没有明显的差异,则 F 统计量接近 1。然而,在我们的模型中,高 F 值表明每个预测变量在预测幸福得分中起着重要作用。p 值的计算也表明了这一点,但是 F 值证实了我们先前的主张。因此,如上面的 ANOVA 表所示,平均值之间的所有差异都具有统计学意义,这使我们得出结论,我们拟合的回归模型作为预测变量的集合,具有高度显著性。
预测变量分析
在本节中,我们将逐一分析每个预测变量,以便更好地理解模型的结果。它包括它的分布、相关性和对幸福分数的影响,以及合理的原因。
国内生产总值
最低人均国内生产总值为 0.000,最高人均国内生产总值为 2.096,差距为 2.096。人均国内生产总值的四分位数间距为 0.6297。
如相关图所示,人均 GDP 与幸福指数有很强的正相关关系。
正如我们的回归模型所确定的,人均国内生产总值的单位增长也会导致幸福指数单位的最高增长。
直觉上,经济状况较好的国家通货膨胀率较低,国民生活更轻松。这里的一个例子是任何发达国家和发展中国家之间的比较。经济较好的国家有较高的生活水平,这可能会导致公民的幸福。
家庭的
个人以家庭、朋友和亲戚形式获得的最低社会支助水平为 0.000,最高为 1.6440,范围为 1.6440。家庭/社会支持的四分位数范围是 0.4579。
如相关图所示,个人获得的社会支持水平与幸福指数有很强的正相关关系。
正如我们的回归模型所确定的,家庭(社会支持)单位的增加也会导致幸福指数单位的增加。
从逻辑上讲,人们需要从亲戚朋友那里获得一定程度的社会支持才能快乐,这是有道理的,这两者之间的关系根植于社会环境中。很多人依靠他们的支持系统来获得幸福。因此,家庭(社会支持)是预测幸福的一个似是而非的衡量标准。
健康
健康预期寿命的最低水平是 0.000,最高水平是 1.1410,范围是 1.1410。健康预期寿命的四分位距是 0.3678。
如相关图所示,健康预期寿命与幸福指数有很强的正相关关系。
正如我们的回归模型所确定的,健康预期寿命增加一个单位也会导致幸福指数增加一个单位。
直觉上,反过来也是有道理的,因为更快乐会提高生活质量,从而带来更健康的预期寿命。在这个前所未有的疫情时代,健康生活、高免疫力和更长的预期寿命的需求凸显出来,我们的幸福建立在我们的健康和我们周围人的健康之上。
自由
做出生活选择的最低自由度为 0.000,最高自由度为 0.7240,范围为 0.7240。自由度的四分位数范围是 0.2212。
如相关图所示,做出生活选择的自由与幸福指数呈正相关。
正如我们的回归模型所确定的,自由增加一个单位也会导致幸福分数增加一个单位。
这又一次有了直觉,因为对许多人来说,以自我为中心的自主和选择是影响幸福的重要因素。
腐败
腐败认知的最低水平为 0.000,最高水平为 0.55191,范围为 0.55191。对腐败的看法的四分位数范围是 0.10161。
如相关图所示,特定国家的低腐败水平和对政府的信任度的增加与幸福指数之间的正相关性相当弱。
正如我们的回归模型所确定的那样,腐败感(在我们的案例中是对政府的信任感)每增加一个单位,幸福指数就会增加一个单位,但这种增加不如人均平均绩点或健康预期寿命等预测变量的影响深远。
如柱状图所示,对腐败的看法是正确的,这意味着这些国家对腐败的看法很高,也就是说,有腐败问题的国家越多。
慷慨
最低慷慨度为 0.000,最高慷慨度为 0.8381,范围为 0.55191。慷慨的四分位数范围是 0.1488。
正如相关图所示,慷慨与幸福指数也有微弱的正相关。
正如我们的回归模型所确定的,慷慨度单位的增加会导致幸福指数单位的增加,但这种增加不如人均平均绩点或健康预期寿命等预测变量的影响深远。
多重共线性分析
多重共线性是多元回归模型中两个或多个独立变量之间存在高度相关性的一种现象,它会导致扭曲和误导的结果,并使回归模型估计值不可靠和不稳定。虽然我们在开始分析之前检查了变量之间的相关性,但我们再次进行了交叉检查,以便(这次从多重共线性的角度)检查模型中使用的变量是否很少或没有多重共线性。
多重共线性的可视化(如果有)
上图展示了每个独立变量和其他预测值的散点图,以直观地寻找多重共线性。对角线代表 gdp、家庭、健康、自由、腐败和慷慨的密度图。从图中可以看出,只有健康和国内生产总值高度相关,而家庭-国内生产总值和健康-家庭中度相关。总的来说,可以得出结论,在自变量的总体集合中存在非常轻微的多重共线性,这不会影响我们的统计推断的可靠性。
我们通过使用下面的方差膨胀因子(VIF)模型进一步证实了这一观点。
预测变量的 VIF 分数
此处使用的测量方法 VIF 量化了多元回归设置(即我们使用的回归技术)中一组独立变量内的多重共线性的数量。从数值上来说,它是整个模型的方差和各个独立变量的方差的比例。因此,较大的 VIF 值表明一个独立变量与其他多元回归变量高度共线性,应进行调整。
在我们的回归模型中,没有一个独立变量的 VIF 值超过 3(即 VIF <= 3),如上面的水平条形图所示。一般来说,高于 10 的 VIF 表示高相关性。因为我们的预测变量的值小于阈值,所以几乎没有可能使模型不可靠的多重共线性。总体而言,无需对多重共线性进行进一步调整。
结果和结论
除了在分析的每个阶段回答的多个子问题之外,以下是可以从上述统计数字的广泛分析、可视化和阐述中得出的关键结果:
GDP、家庭、健康、自由、腐败和慷慨等因素在决定幸福得分方面发挥着重要作用。增加这些特征中的任何一个,保持其他特征不变,都会导致幸福感的增加(正如回归方程及其解释所解释的那样)。在所有因素中,自由对幸福得分的影响最大,其次是人均 GDP 和公民的健康(预期寿命)。
所有起作用的因素的 p 值< 0.05(即,我们拒绝零假设的阈值)。因此,它们对预测幸福得分都有统计学意义。然而,p 值本身不足以证实我们的发现。因此,方差分析表和 F-统计量的计算使我们得出结论,我们拟合的回归模型作为预测变量的集合,确实非常显著。
在探索性数据分析中,我们发现很少或没有异常值,并且整个数据中的偏斜度非常小,这使得数据建模和解释相关统计数据更加容易。多元线性回归足以有效地模拟和描述我们的数据。
总的来说,数据选择、数据整合、数据清理、特征选择、探索性数据分析、回归建模和后续分析使我们能够找到一开始提出的研究问题的答案,即各种社会、城市和国家因素确实有助于决定公民的幸福。
前进的道路
从我们的分析中得出了如此有趣的结果和结论,我们希望随后的幸福报告和幸福测量可以有效地用于评估国家的进步和幸福。我们的分析涵盖了 2015 年至 2019 年的幸福报告。然而,在新冠肺炎之后,幸福报告的重点需要从典型的预测稍微转移到理解疫情对主观幸福感的影响,反之亦然。
全世界已有 200 多万人死亡,变异的威胁和关于如何应对的不均衡政策决定给未来带来了不确定性。尽管如此,当务之急是通过理解个人的福祉并采取必要的措施,让彼此的事情变得更容易。这就是幸福报告及其分析发挥作用的地方。即使未来几年的报告中的影响因素保持不变,重要的是要评估在疫情的背景下,哪些因素对个人和国家的幸福影响更大。这不仅使政府能够更好地制定以公民为中心的政策,而且也使我们作为个人能够为彼此创造一个更幸福的环境。
参考
[1]网络,可持续发展解决方案。《世界幸福报告》卡格尔,2019 年 11 月 27 日,【www.kaggle.com/unsdsn/world-happiness】T2。(数据集)
[2]《世界幸福报告》。首页,可持续发展解决方案网,worldhappiness.report
[3]“起重机和生物导体上的 R 封装。”文档,数据营,www.rdocumentation.org
查看完整 R 码 此处 。
超级碗 LV 的统计分析
酋长海盗队比赛的讨论要点
罗伯特·埃尔南德斯·维拉塔摄于佩克斯
22 周后,NFL 赛季终于结束了,我们可以坐下来回顾一下我们刚刚目睹的一切。作为联盟的惯例,汤姆·布拉迪赢得了他的第 7 枚戒指,这次是在海盗队。这是双方真正的统治性表现,海盗队自始至终赢得了这场比赛。这篇文章将呈现一个游戏的统计摘要,回顾谈话要点并呈现支持它的分析。
关键术语
- YAC——接球后码数
- xYAC —接球后的预期码数
- EPA —每场比赛的预期加分
- WPA —每次游戏增加的获胜百分比
- EP —预期点数(可作为 EPA 的总和计算)
- 移动棒——获得第一次击倒的动作
如果最后的分数没有告诉你足够的信息,这些数字可以证明这是一场多么没有争议的比赛。
作者图片
31-9 的最终比分很好地向我们展示了这场比赛是如何进行的。酋长队在前三节每节都得了 3 分,第四节一分未得,而海盗队继续疯狂得分,上半场得了 21 分,下半场得了 10 分。当我们查看 Bucs 的胜率时,在上图中用四分之一进行了颜色编码,这一事实得到了进一步强调,因为 Bucs 在上半场结束前就超过了 90%的水平。很明显,海盗队在第二节给这场比赛打上了印记。在前 15 分钟,他们设法将胜率提高了大约 5%,但在第二季度,这一数字从 60%上升到 90%。自 2014 年海鹰队和野马队之间的总决赛以来,我们还没有见过这种统治地位。在那场比赛中,海鹰队也有类似的统计表现,在第二节达到了 90%的分数,尽管西雅图队在上半场的时间超过了 3 分钟,而上周末的比赛只有 30 秒。
酋长的防守使他们输掉了比赛
作者图片
图表显示了排名前 20 的 WPA 比赛。WPA 是赢球百分比的总和,它本质上代表了一场比赛对一支球队赢得比赛的贡献。这是使用每场比赛的一系列情况输入来计算的,例如获得的码数、剩余时间、第一次进攻所需的码数、新的场地位置等。WPA 的计算方式是这样设计的,即在游戏快结束时,重要的玩法比游戏开始时的相同玩法对 WPA 的影响更大。在对方半场跑 20 码也会比在自己半场跑 20 码得到更高的 WPA。WPA 被设计来调整所有这些情境因素,因此在分析剧本时是一个相当可靠的方法。
在上图中,海盗队在 WPA 排名前 20 的比赛中占据了 14 席。橙色突出显示的是比赛中涉及点球的那些,正如我们所看到的,所有这四个点球都是针对酋长队的。合计 18.82%的罚款成本非常高,尤其是考虑到它们发生的关键时刻。4 个点球中的 3 个发生在触地得分,第一个在第 4 和第 5 次投篮尝试中,给了海盗队第一次得分,最终导致 7 分而不是 3 分。从本质上来说,在 WPA 中奖励一支球队 18%的得分和 2 次触地得分在这里是不能低估的,因为我们可以清楚地看到这对决定比赛的胜负有多大的贡献。
首席执行官们没有给帕特里克·马霍斯提供任何东西
作者图片
当看简单的盒子分数时,泰瑞克希尔和特拉维斯凯尔斯有合理的外出。酋长队的两个主力队员的码数比整个 Bucs 接收队加起来还多,但这并不能说明他们的情况表现。整个游戏过程中,酋长们都在丢弃捕获量,EPA 的统计数据让我们更好地了解了这种影响。希尔在比赛中有 73 码,但他不完整的传球和多次移动球棍的失败导致了环保局更具破坏性的表现,而不是积极的表现。例如,凯尔斯的统计数据和伦纳德·福内特的统计数据之间的比较,突出了简单统计数据中没有显示的推论。Fournette 有 1/3 的 Kelce 的接收码,也有 0 次触地得分,但总 EPA 略好。这背后的很大一部分原因可能是因为凯尔斯的不完整传球有多么重要。第三次下降时的多次下降或失误将导致环保局受到更大的处罚,因为局长们将被迫放弃。
作者图片
xYAC EPA 表示进位后从预期码增加的预期点数。持球后的预期码是另一个情境统计,根据球员接球时的位置、接球时的速度和最近的防守队员的距离计算得出。这个统计数据也是为不完整传球计算的,它代表了接球者在接球后的预期跑动距离。酋长的总 xYAC EPA 为 29.98。这告诉我们一些事情。直接的翻译是,马霍斯把他的接球手放在一个很好的位置,因为他们有持续的机会在接球后把球带到更远的地方。这也是对海盗队后场或任何在覆盖范围内打球的人的轻微指控,因为他们确实在太空中留下了接球手。这不一定是一件坏事,托德·鲍尔斯的防守一直优先向 QBs 施压,他的防守计划在周日完美地发挥了作用,但它确实给了我们一些关于海盗如何防守传球的洞察力。
完成的 YAC EPA 是 xYAC EPA 的一半,告诉我们接收器在周日完全丢失。我们不得不称赞海盗队的防守,因为他们预测传球和追截接球手的速度非常快,但这是一种无能为力的真实反映。对酋长队来说,在空中和空中得到 60 分,但实际上只得到 9 分是另一个重大的失败。
优化生活的统计法则:呼唤效应
在一个信息太多的世界里,你如何从噪音中分辨出信号?
有时候,我一觉醒来,会着急打开手机。浏览所有的社交媒体新闻,浏览《纽约时报》的应用程序,希望在 Youtube 上看到一些新的上传,这需要 很多时间 。
每天淹没我的信息洪流产生的痛苦大于收获。每一点信息都被优化得“看起来紧急/重要”,以至于我们不得不不断地选择要处理什么,而我们知道其中很少(如果没有的话)会在接下来的 24 小时内保持相关?
如果存在一种规则来识别哪种类型的新闻或信息在未来很长一段时间内仍然相关,那会怎样?
如果有一个指南,你可以用来从其他的噪音中过滤出值得知道的知识,那会怎么样?
有——这叫做林迪效应。
呼唤效应——或作为质量评判标准的时间价值
呼唤效应是这样一个观察结果:
一件藏物存在的时间越长,它可能存在的时间就越长。
纳西姆·尼古拉斯·塔勒布在他的书https://www.amazon.com/dp/B0083DJWGO/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1中,把这个概念解释得相当干净:“如果一本书已经印了四十年,我可以预计它还会印四十年。但是,[……],如果它能再生存十年,那么它就有望再出 50 年。”
这个想法是,像一本书/技术/智力产品等一些不易腐烂的东西的未来预期寿命与它们当前的年龄成正比;每多存活一段时间意味着更长的预期寿命。
数学动机:
呼唤效应始于一个想法,即一些智力人工制品的寿命遵循帕累托分布:一个带有沉重的、“缓慢衰减”尾部的偏斜分布(即大部分数据在尾部)。
帕累托图的一个例子。左边是占主导地位的少数,右边是包含大量数据的长尾。图片来自维基百科——公共领域。
你可能听说过帕累托分布,即著名的 80/20 法则:有几个项目非常普遍,对分布的“头部”贡献很大,例如,20%的高收入者占全国财富的 80%;顶级足球队在英国联赛中只占一小部分,但他们却占据了电视版税的大头。
通过帕累托分布对工件的生命周期建模意味着大多数项目将只持续很短的一段时间,但是有一个长尾巴的项目可以持续更长的时间。大量的经济研究已经证实了智能人工制品的这一特性。
我们可以将这种工件的寿命概率分布函数——PDF(t)写成帕累托形式:
其中 t_m (比例参数)是 t 的最小可能值, α 是形状参数,也称为尾部指数。注意 t_m 必然是正数,即工件的寿命必须为> 0。
现在,我们要找到预期寿命 E(t) ,条件是它已经持续了一段时间 t_0 。换句话说,我们要找到 E(t|t > t_0)。
因此,在 t_0 或E(t-t _ 0 | t>t _ 0)之后的预期额外寿命为:
虽然数学看起来令人生畏,但结果却出人意料地清晰。有条件的预期额外寿命简单地是已经过去的时间()乘以比例常数【α-1】。
- α 越接近 1,比例常数越大,我们对工件的预期额外寿命就越大。如果 α = 2,则比例常数为 1。即 预期额外寿命等于目前所见寿命。
- 例如,当 α = 2 时,一旦到达 t_0,我们期望的未来寿命也是 t _ 0;如果达到该点使得总寿命到目前为止为 2t_0,则新的预期未来寿命是 2t _ 0;诸如此类。
模拟
我知道不是每个人都喜欢数学证明,所以我会试着用一个小模拟来说服你。
让我们假设 2021 年是你最喜欢的书的 20 周年纪念,你想知道这本书在完全被遗忘之前还有多少年。
我们要做的是从 P(t-t_0|t > 20,α) 到 α, 的不同值,模拟生命周期的许多许多场景,并观察分布如何表现 。
现在,实际执行这种模拟需要一种称为逆随机采样的技术。它的细节超出了本帖的范围,但是如果你感兴趣,我写了 一个小说明 解释技巧。
条件抽样和绘图的样本代码
您可以看到,随着 α 值的增加,头部周围的条件分布变得“更重”,从而导致剩余年数的条件预期更小。一本已经印了 20 年的书,如果 α=1.5 ,20 如果如果 α=2 ,10 如果 α=3 ,预计还能再印 40 年。
一个有趣的结果是比较了剩余寿命的条件预期在呼唤人和人之间的差异。
通过一些快速的研究,我发现美国男性的寿命分布遵循平均寿命为 70 岁的威布尔分布。有了这些信息,我们就可以做一些模拟,看看一个人庆祝完 20 岁生日后剩余寿命的条件概率是多少:
**左图:前 20 年过去后呼唤氏好(Pareto withα= 2)和人类(Weibull with mean = 70)的条件概率分布函数——虚线代表各自分布的均值。右图:作为已过去年数的函数的预期剩余年数。
我们了解到技术和人类有不同的生存模式。
- 考虑到最初的 20 年,呼唤的预期剩余寿命是 20 年,而我们预计美国男性的平均寿命是 50 年(加起来是 70 岁)。
- 然而,一个人越老,他剩下的预期年数就越少。这是因为人类的寿命遵循细尾分布——比帕累托分布的尾部细得多。帕累托分布的重尾是为什么一项技术存活的时间越长,我们就能期待它存活的时间越长。用塔勒布的话来说,技术 “反过来老化。”
运用呼唤效应优化你的生活:
本质上,呼唤效应教给我们一个简单的原则:如果你无法决定,那么就让时间成为内容的自然过滤器:
- 我已经卸载了手机上所有的新闻应用,同时订阅了每周新闻简报。如果一个事件是重要的和有新闻价值的,那么它应该在最初的 24 小时之外保持如此。
- 书籍:不知道在比尔·盖茨的读书笔记和 NPR 的书《礼宾》中选择哪本书?读经典。《圣经》、马基雅维利的《君主论》、马可·奥勒留的《沉思录》,这些书的真知灼见经受住了时间的考验,它们很可能比今年 NYT 的大多数畅销书都要长寿。
- ML 算法:根据 2016 年 Kdnuggets 的一项调查,高斯在 19 世纪发明的通过最小平方估计的线性回归仍然是迄今为止数据科学家中最受欢迎的机器学习技术。如果我必须在最小平方线性回归和深度神经网络之间打赌,并选择哪种算法在 2200 年仍将被使用,我的赌注肯定是前者。
一些警告:
正如我们已经看到的,呼唤效应是非常整齐的概率陈述。但它们确实是概率陈述,你不应该把它看得太重:
- 我们并不确定哪一项展现了呼唤效应。申请的条件相当严格。并非一切都遵循帕累托分布:人类的寿命当然不会,原子衰变也不会。最重要的是,即使一个工件的寿命以帕累托方式分布,我们已经看到,如果我们只是稍微移动一下形状参数,额外的寿命预期会有很大的不同。
- 注意,我计算的是E(t | t>t _ 0),也就是说,它只以知道 t > t_0 为条件。如果你有额外的信息,比如有证据表明某项技术正在衰落,那么你就需要以这些信息为条件。
因此,林迪效应是一种微不足道的启发法,随着你获得更多的相关信息,它的有用性会降低。
但是你知道,要过滤阅读的书籍和新闻,也许琐碎的试探法就足够了。
如果你喜欢这篇文章,你可能也会喜欢我的另一篇关于有趣的统计事实和经验法则的文章
对于其他深潜分析:
这个项目的完整代码可以在我的 Github 中找到。
图像聚类的分步指南
用于图像簇的检测和探索。了解如何仔细预处理图像,利用众所周知的特征提取方法,并评估聚类的良好性。理论背景,然后是实践教程。
许多计算机视觉任务依赖于(深度)神经网络,旨在预测“图像上有什么”。然而,并不是所有的任务都需要监督方法或神经网络。通过无监督的方法,我们可以确定图像的自然组或簇,而不局限于固定数量的(学习的)类别。在这篇博客中,我将总结无监督聚类的概念,然后是一个关于如何预处理图像、提取特征(PCA、HOG)以及考虑到聚类的良好性对具有高相似性的图像进行分组的实践教程。我将演示对***【MNIST】数据集 、 101 对象数据集 、 花数据集 的聚类,最后使用*【Olivetti】数据集*** 对 面孔 的聚类。所有结果都是使用 Python 库clustimage导出的。***
如果你觉得这篇文章很有帮助,可以使用我的 推荐链接 继续无限制学习,并注册成为中级会员。另外, 关注我 关注我的最新内容!
重要的事情先来。
图像识别是一项计算机视觉任务,其识别部分可以分为有监督的和无监督的方法。在监督任务的情况下,目标可以是对图像或图像上的对象进行分类。现在有各种各样的预学习模型用于分类任务。共同的主题是,所有监督模型都需要一个学习步骤,其中使用基础事实标签来学习模型的对象。一些模型可以容易地识别数百个对象,并且这个数字在稳步增加,但是大多数特定领域的对象在预先学习的模型中可能仍然是未知的。在这种情况下,向无监督聚类方法的过渡似乎是不可避免的。构建高质量的标注数据集是一项艰巨的任务,因此倾向于使用聚类方法。
一般来说,无监督机器学习的任务是从“未标记”的数据中推断出一个描述隐藏结构的函数。
非监督任务不仅仅是聚类,还可以用于各种其他任务,如数据探索、离群点检测和特征提取。在这篇博客中,我将关注 无监督聚类方法及其在图像识别中的应用 。然而,图像的聚类需要多个步骤,每个步骤都会影响最终的聚类结果。让我们从一个示意图开始,然后进入兔子洞。
图像聚类的示意图。
图像的聚类是一个多步骤的过程,其步骤是 预处理图像提取特征根据相似性对图像 进行聚类, 使用优度来评估聚类的最佳数目 。另请参见图 1 中的示意图。所有这些步骤都很容易在 python 包clustimage中实现,该包只需要 路径位置 或 原始像素值 作为输入。
图一。图像无监督聚类的 clustimage 中所采取步骤的示意图。图片来自作者。
我将在接下来的章节中描述这些步骤,但是让我们先简单介绍一下无监督聚类的背景和一些术语。
无监督聚类。
*对于无监督聚类,我们的目标是在不使用关于标签或类别的先验知识的情况下,确定数据中的“自然的或“数据驱动的”组。使用不同的无监督聚类方法的挑战在于,它将导致样本的不同划分,从而导致不同的分组,因为每种方法都隐含地对数据施加了结构。因此问题出现了;*什么是“好的”集群?*图 2A 描绘了二维空间中的一串样本。直观上,我们可以将它描述为一组杂乱的样本(也称为图像)。我会声明有两个不使用任何标签信息的聚类。*为什么?因为点与点之间的距离,以及杂乱样本之间相对较大的“间隙”。
图二。聚类示例。图片来自作者。
考虑到这一点,我们可以将我们对“簇”的直觉转换成一个数学陈述,例如;所谓的类内样本的方差应该较小( 内方差【σW】,红蓝* ),同时类间方差应该较大( 间方差,【σB】),如图 2B 所示。样本之间的距离(或内在关系)可以用 一个距离度量 (例如欧几里德距离)来测量,并存储在所谓的相异度矩阵中。然后可以使用 链接类型 计算样本组之间的距离(用于层次聚类)。*
距离度量
最广为人知的距离度量是欧几里德距离*。尽管在许多方法中它被设置为默认度量,但它并不总是最佳选择。*
理解指标的数学属性,使其符合数据的统计属性,并与研究问题保持一致。
各种距离度量的示意图如图 3 所示[1]。在图像相似的情况下,当使用主成分分析(PCA)【2】或梯度方向直方图(HOG)* 提取特征时,推荐使用欧几里德距离。*
图 3:最流行的距离度量的示意图。图片作者:马腾·格鲁特·奥斯特[1]。由作者编辑。
链接类型
**分级聚类的过程包括将样本分组到更大的聚类中的方法。在此过程中,需要计算两个子集群之间的距离,不同类型的链接描述了集群之间的连接方式(图 4)。
图 4:链接类型。图片由作者提供。
简单来说,两个聚类之间的 单连锁 就是它们最接近的两个样本之间的接近程度。它产生一个长链,因此非常适合聚类球形数据,也适合异常值检测。 完全连锁 两个星团之间的距离就是它们两个最远样本之间的接近度。直观上,两个相距最远的样本不可能比其他完全不同的样本对更不相似。它迫使星系团呈球形,其边界通常具有“紧凑的”轮廓,但内部不一定是紧凑的。 两个集群之间的平均链接 是一侧的一个对象与另一侧的另一个对象之间的所有邻近度的算术平均值。 形心连锁是簇的几何形心之间的接近度。谨慎选择度量和链接类型*,因为它直接影响最终的聚类结果。考虑到这一点,我们可以开始预处理图像。*
图像预处理。
在我们从图像中提取特征之前,我们需要执行一些预处理步骤,以确保图像在图像大小 中与 相当。预处理步骤利用了open-cv和流水线中的clustimage。******
- 色阶: 将图像转换成例如灰度(二维)或彩色(三维)。
- scale: 归一化最小和最大范围[0,255]之间的所有像素值。
- dim: 调整每个图像的大小,确保特征的数量相同。
**pip install clustimage**
图像预处理示例,包括颜色缩放、数值缩放、大小调整和矢量化。
图像特征提取。
在对图像进行预处理之后,我们可以开始使用像素值信息从图像中提取特征。有许多方法来提取特征,但我将集中于 PCA 和 HOG 特征,因为这些是公认的技术,可以很好地概括不同类型的对象。我将简要回顾 PCA 和 HOG,但更多细节我建议阅读其他文章和博客。
主成分分析
使用主成分分析,我们可以降低维数,并提取主要成分(PC ),其中大部分方差可见。非常重要的是,所有图像必须具有相同的宽度和高度,并且进行类似的预处理,因为像素值将形成特征空间。假设我们有 100 张 128×128 像素的灰度 2D 图像。每个图像将被展平并形成大小为 16384 的向量。现在可以将向量堆叠起来,形成一个新的 NxM 阵列,其中 N 是 100 个样本,M 是 16384 个特征。特征提取将在 NxM 阵列上进行。在在后一种情况下,将自动确定电脑的数量。
方向梯度直方图(HOG)
HOG 是一个特征描述符,用于从图像数据中提取与边缘的方向和方位相关的特征。一般来说,它是图像的简化表示,仅包含最重要的信息,例如图像的局部部分中梯度方向的出现次数。总结如下:
- HOG 描述符侧重于对象的结构或形状。HOG 特征包含边缘和方向信息。
- 完整的图像被分解成更小的区域(局部部分),并且对于每个区域,计算梯度方向。
- 最后,HOG 会为这些区域分别生成一个直方图。直方图是使用像素值的梯度方向创建的,因此称为梯度方向直方图。
使用 HOG 功能时,并非所有应用程序都有用,因为它“仅”提供图像的轮廓。例如,如果用例是对不同的通用对象进行分组,HOG 特征可以做得很好,但是对象内更深层次的相似性可能很困难,因为细节可能会丢失。然而,如果需要增加 HOG 特征,可以减少每个像元的像素(例如 4,4)。
从花中提取 HOG 特征的例子。
图 5。HOG 特征描述符。左:输入图像。右图:猪的特征。图片由作者提供。
集群评价。
在这一点上,我们预处理图像,提取特征,并且在我们心中有了目标,我们选择链接类型并且能够开始聚类图像以基于距离度量找到相似的组。然而,聚类方法不 而不 提供关于聚类的可分性、良好性或最佳数量的信息。为了评估聚类,有各种方法,其中最著名的方法是Silhouette score和Davies–Bouldin(DB)。每种都有其属性,其摘要如下:
- 戴维斯–波尔丁指数(dbindex) :直观上可以描述为簇内距离和簇间距离的度量。分数有界在[0,1]之间, 越低越好 。请注意,由于它测量聚类质心之间的距离,因此仅限于使用欧几里德距离。
- 剪影得分 :剪影值是一个样本与其聚类(内聚)相比与其他聚类(分离)相似程度的度量。分数限制在[-1,1]之间,其中高值指示对象与其聚类匹配良好,而与相邻聚类匹配较差。因而 分数越高越好 。与 DBindex 相反,剪影得分是一种样本方式的测量,即测量一个聚类内的样本的平均相似性以及它们与其他聚类中的其他对象的距离。轮廓分数可以与任何距离度量结合使用。
对于聚类的评价,clusteval库在clustimage中使用,包含三种评价方法: 剪影 、 DBindex ,以及 衍生 方法。评估方法应与聚类方法结合使用,如agglomerate、k-means 或 dbscan ,这些方法也包含在 clustimage 中。同样,理解这些方法的数学属性很重要,这样它才能与(预期的)聚类的统计属性相匹配。例如, DBscan 结合剪影评估可以检测具有不同密度和形状的聚类,而 k-means 假设聚类是凸形的。**
请注意,聚类评估方法很容易被欺骗,因为分数会随着聚类数量的增加而逐渐提高。
明智的做法是设置聚类数量的搜索范围,以找到局部最小值/最大值。
MNIST 数据集。
*MNIST 是一个著名的手写数字数据集,它非常适合于检查和展示方法的性能。让我们加载数据集并运行clustimage来检测集群。在这种情况下,我将使用 PCA 提取特征,并将所有其他参数保留为默认值。默认设置如下:对于 预处理 ,将灰度设置为假(将其设置为真不会改变结果,因为图像很容易被灰度化),如果需要,图像尺寸减少到 128,128 。PCA 用于 特征提取 ,其中选择覆盖 95%方差的主成分数。使用具有欧几里德距离度量和沃德链接的凝聚方法来检测聚类。使用*剪影得分评估聚类和最佳聚类数。聚类数的搜索范围在[3,25]之间。为了可视化的目的,执行 tSNE 以减少高维空间并分散相对于彼此的样本。
正如您可能注意到的,在clustimage中,有许多参数的所有功能都很容易流水线化,以对图像进行聚类并确定最佳聚类数。输出存储在 结果 和对象本身中。让我们看看结果。维数减少到 29 个特征(图 6)并存储在 feat 键中。可用cl.pca.plot()
绘制解释的差异。嵌入的坐标存储在 xycoord、 中,聚类标签可以在 标签 中找到。为了更直观地了解性能,我们可以绘制各种图表,例如聚类的良好程度、每个聚类中相似检测样本的一致性,以及散点图。
图 6。解释差异。图片作者。
集群评价。
我们使用检测到 10 个最佳聚类的轮廓分数(图 7A 中的最高相对分数)来评估分级聚类。数据集也包含 10 个数字[0 到 9],但我们需要检查聚类是否也表示这些数字。在图 7B 中,我们可以看到每个样本的系数值。许多样本具有较高的值,这意味着聚类配置是适当的。如果有许多点具有低值或负值,则聚类配置可能具有太多或太少的聚类。因此,总的来说,两个图都表明样本的良好聚类。
cl.clusteval.plot()
cl.clusteval.scatter()
图 7。基于轮廓得分的聚类评价结果。a .聚类数与轮廓分数的关系。b .每个样本的轮廓系数值。图片由作者提供。
为了研究样本在聚类中的分布,我们可以用cl.plot_dendrogram()
绘制树状图。树状图提供了样本在 10 个聚类中的分布情况,聚类之间的距离似乎或多或少是均匀分布的,没有强烈的异常值或其他可能干扰聚类结果的影响。
使用功能cl.plot_unique()
,我们可以绘制每个聚类的质心图像。此外,还可以通过设置以下参数对每个聚类的所有图像进行平均:cl.plot_unique(img_mean=True)
。后一个选项有助于更直观地了解每个聚类的图像是否相似。例如,如果我们看图 9 中的聚类 7,聚类的质心似乎是数字 3,而平均图像似乎更像 9?这表明群集可能看到不完全相同的图像。
图 9。绘制每个集群的独特图像。a .每个聚类的最质心图像。b .每个聚类的平均图像。图片由作者提供。
基于 t 分布随机邻居嵌入的散点图
使用散点图功能cl.scatter(zoom=5)
,我们可以将样本分散在嵌入的 2D tSNE 空间中,并直观了解样本相对于彼此的分布情况。注意,样本(数字图像)在高维空间中确定的聚类标签上是有颜色的。在这种情况下,2D tSNE 嵌入仅用于可视化目的。对于每个聚类,在 2D 空间中确定质心,并绘制最接近质心的图像。总的来说,我们看到一些数字可能需要进一步检查的聚类的清晰分离,例如聚类 4 和 5。为了查看集群标签,我们可以将zoom
参数设置为 None,cl.scatter(zoom=None)
。
图 10。tSNE 嵌入的散点图。图片作者。
为了更深入地检查集群中的图像,我们可以使用绘图功能cl.plot(cmap=’binary’, labels=[4,5])
。这里我们只画出感兴趣的聚类,比如聚类 4 和 5。簇 4 似乎包含数字 1 和 9,簇 5 包含数字 1、4 和 9。
图 11。为指定的集群绘制图像。a .群组 4 中的图像。b .第 5 组中的图像。图片作者。
猪的特征。
使用clustimage,也可以通过将方法设置为 hog,使用方向梯度直方图提取特征。** 因为 MNIST 的图像尺寸很小,所以也需要减少每个像元的像素数来计算 hog 特征。让我们再次聚类 MNIST 数据集,但现在使用 HOG 特征。**
使用pixels_per_cell:(2,2)
可以获得以下结果。
图 12。使用 HOG 特征检测聚类。a .聚类数与轮廓分数的关系。使用 HOG 特征的 tSNE 嵌入的散点图。图片作者。
基于最大剪影 分数检测十四个聚类。注意,第二个局部最优值是 10 个集群。当我们将聚类结果(图 12B)与使用 PCA 的聚类结果(图 10)进行比较时,基于视觉检查,使用 HOG 特征的聚类显得不太明显。当使用最接近质心的图像和每个聚类的平均图像绘制每个聚类的独特图像时,我们可以更深入地检查聚类。尽管如此,结果似乎是合理的。
图 13。绘制每个集群的独特图像。a .每个聚类的最质心图像。b .每个聚类的平均图像。图片由作者提供。
聚类 101 对象和花数据集的示例。
对 MNIST 数据集进行聚类很有趣,但现在我们将对两个真实世界的数据集进行聚类。第一个数据集包含大量不同的对象,第二个数据集相对较小,但包含不同的花的子类型。
加州理工 101 对象数据集。
**包含 101 个对象的大型数据集是 Caltech101 数据集。该数据集包含属于 101 个类别的 9144 幅真实世界图像。大约 40 至 800 每类图像。每张图片的大小大约为 300 x 200 像素,可以在加州理工学院的网站上下载。作为对clustimage的输入,我们可以简单地提供存储所有图像的路径位置。子目录中的所有图像将被递归收集。
检测到最佳的 63 个聚类(图 14A ),其中聚类的质心图像在图 14C 中示出,这少于 101 个已知输入对象。尽管如此,一些聚类还是很好地从整体中分离出来(图 14B),并且包含具有高相似性的图像(图 14D)。由于 tSNE 算法的性质,在 2-D 空间中更居中的聚类可能不像图 14D 所示的那样纯。总的来说,一些对象倾向于很好地聚类,而其他对象可能需要进一步微调模型参数,或者甚至可能需要不同的特征提取方法。
图 14。Caltech101 数据集。a .轮廓分数在 63 个聚类处检测到最佳值。b .使用检测到的聚类标签对样本进行着色的 tSNE 嵌入。c .每个聚类的质心图像。d .在群集 13 中检测到的图像。图片由作者提供。
花卉数据集
花卉数据集包含 210 幅图像,并使用 HOG 方法进行聚类。在花数据集的情况下,与使用基于视觉检查的 PCA 特征相比,HOG 特征似乎产生更好的结果(结果未示出),即使颜色在特征提取方法期间丢失。如果图像数量变大,也可以将方法设置为pca-hog
,对 HOG 特征执行 PCA,从而显著减少特征数量,节省内存并保留结果。
检测到最佳的 6 个聚类(图 15A ),这些聚类的质心图像在图 15B 和 c 中示出。质心图像的 HOG 特征在图 15D 中示出。
图 15。花卉数据集。a .轮廓分数在 6 个集群处检测到最佳值。b .使用检测到的聚类标签对样本进行着色的 tSNE 嵌入。c .每个聚类的质心图像。提取的猪特征。图片由作者提供。
图。检测到的聚类 1 和聚类 4 中的样本。图片由作者提供。
聚类人脸。
使用 clustimage 库也可以进行人脸聚类。然而,这可能需要额外的步骤,即从图像中提取脸部的。可以使用 cl.extract_faces()功能从图像中提取人脸,该功能反过来使用 openCV 的 haar 级联,更具体地说,是 Haar cascade _ frontal face _ default . XML。在本例中,我们将加载具有 400 张人脸图像的著名的 Olivetti faces 数据集。对于这个数据集,不需要提取人脸,因为人脸很容易被裁剪。**
当我们运行 clustimage 时,检测到 18 个簇的最优值(图 16A),嵌入了簇标签的 tSNE 如图 16B 所示。我们确实看到了一些集群的分离,现在可以使用cl.plot()
功能检查每个集群。
图 16。人脸数据集。a .轮廓分数在 18 个聚类处检测到最佳值。b .使用检测到的聚类标签对样本进行着色的 tSNE 嵌入。c .每个聚类的质心图像。d .聚类 15 中的图像示例。图片由作者提供。
找到相似的图像。
除了聚类功能外,clustimage**库也包含了搜索图片的功能。使用find
功能,可以提供输入图像,并将返回类似的图像。实现了两种方法:
- 基于 k 近邻。
- 基于概率密度拟合后的显著性。
对于这两种方法,使用指定的距离度量(默认欧几里德)跨所有图像计算邻接矩阵。在 k-最近邻方法的情况下,选择 k-最近邻,并且逻辑上它将总是导致命中。在密度拟合的情况下,邻接矩阵用于估计测试分布 [‘norm ‘,’ expon ‘,’ uniform ‘,’ gamma ‘,’ t’] 中 loc/scale/arg 参数的最佳拟合。拟合的分布形成样本的相似性分布*。对于每个新的看不见的输入图像,跨所有图像计算相似性的概率,并且返回在分布的下限中为P<α的图像。这种方法只会返回重要的命中结果。在指定了 k 和α两个参数的情况下,取检测样本的并集。让我们使用 flower-dataset,使用来自路径位置的输入图像来查找相似的图像。***
在上面的例子中,我们的目标是检测两幅输入图像的相似图像。出于演示目的,这些图像也在 fit_transform 功能本身中。或者换句话说,我们至少应该能够检测到相同的图像。图 17 展示了相似性显著且 P < 0.05 的图像。请注意,由于拟合分布中的随机成分,结果可能会略有变化。
图 17。输入图像用红色矩形表示。a .检测到一幅输入图像。b .检测到 34 个相似性显著的图像。图片由作者提供。
最后的话。
我提到了无监督聚类的概念,以及如何从原始输入图像到高度相似图像的聚类。图像的聚类需要多个步骤和各种方法。采取不同的步骤和/或方法将产生不同的分组,因为它隐含地对数据施加了结构,从而对样本进行了划分。 clustimage 包可以帮助使用众所周知的特征提取、评估和聚类方法。通过各种绘图功能可以很容易地研究结果。此外,它还可以用于检测新的看不见的图像的非常相似的图像。如果你的目标是找到(几乎)相同的图像(照片),我推荐阅读这个博客,它是关于使用 可撤销库 使用图像哈希函数检测重复图像的。这已经成为一篇冗长的文章,但是底线是总是确保方法的数学属性与数据的统计属性相匹配。
注意安全。保持冷静。
干杯 E.
如果你觉得这篇文章很有帮助,可以使用我的 推荐链接 继续无限制学习,并注册成为中级会员。另外, 关注我 保持我的最新内容!
软件
我们连线吧!
参考
- Maarten Grootendorst 、、数据科学中的 9 个距离测度、走向数据科学,2021 年 2 月。
- Kimberly L. Elmore 等人、、欧氏距离作为主成分分析的相似性度量、、 AMS,2001 年 3 月 1 日
- Sergei Evgenievich Ivanov 等,基于修正距离度量的物体识别与分类,Procedia Computer Science 136(2018)
使用贝叶斯定理设计知识驱动模型的分步指南。
实践教程
万一你没有数据但是有专家知识。将知识转化为计算机辅助模型的入门指南。
照片由: 基兰木 ,Unsplash
数据是模型的燃料,但是您可能已经目睹了没有数据,只有一个领域专家可以很好地描述甚至预测给定环境下的情况的情况。我将从 贝叶斯概率 的角度总结 知识驱动 模型的概念,接下来是一个动手教程,演示将专家的知识转化为贝叶斯模型的步骤,目标是做出推论。我将使用 S prinkler 系统从概念上解释从知识到模型的过程中的步骤。最后,我将讨论复杂知识驱动模型的挑战,以及由于提问和提取知识而可能出现的系统性错误。所有的例子都是使用 python 库 bnlearn 创建的。
如果你觉得这篇文章很有帮助,可以使用我的 推荐链接 继续无限制学习,并注册成为中级会员。另外, 关注我 关注我的最新内容!
我们能把专家的知识融入模型吗?
当我们谈论知识时,它不仅仅是描述性的知识,如事实。知识也是对某人或某事的熟悉、觉察或了解,程序性知识(技能),或熟人知识[ 1 ]。
无论你有什么知识,或者想使用什么知识,如果你想建立一个计算机辅助知识模型,它都需要以计算机可解释的方式呈现。
这意味着你需要设计一个建立在一系列流程阶段上的系统。或者换句话说,一个序列从一个过程的输出进入下一个过程的输入。多个简单的序列可以组合成一个复杂的系统。我们可以把这样一个系统表示成一个有节点和边的图。每个节点对应一个变量,每条边代表变量对之间的条件依赖关系。通过这种方式,我们可以根据专家的知识定义一个模型,最好的方法是使用贝叶斯模型。要回答这个问题,我们能把专家的知识转化为模型吗? ’ 嗯,这要看你把知识用图形表示出来有多准确,用概率定理又叫贝叶斯图形模型把它粘在一起有多精确。尽管如此,还是有一些限制。
贝叶斯图形模型是创建知识驱动模型的理想选择。
机器学习技术的使用已经成为在许多领域获得有用见解和做出预测的标准工具包。然而,许多模型是数据驱动的,这意味着需要数据来学习模型。将专家的知识整合到数据驱动的模型中是不可能的,也不容易做到。然而,机器学习的一个分支是 贝叶斯图形模型 (又名贝叶斯网络、贝叶斯信念网络、贝叶斯网、因果概率网络和影响图),可以用来将专家知识纳入模型并进行推理。下面是一些贝叶斯图形模型的优点,我将在本文中强调。
- 将领域/专家知识纳入图表的可能性。
- 它有模块化的概念。
- 复杂的系统是由简单的部分组合而成的。
- 图论直观地提供了高度交互的变量集。
- 概率论提供了结合各部分的粘合剂。
要制作贝叶斯图形模型,您需要两个要素:1 .有向无环图和 2。条件概率表。只有一起才能形成专家知识的表示。
第 1 部分:贝叶斯图是有向无环图(DAG)
至此,你知道知识可以表示为一个系统化的过程,可以看做一个图形。在贝叶斯模型的情况下,一个图需要被表示为一个 DAG 。 但达格到底是什么? 首先,它代表 D 有向 A 循环 G 图,是一个具有有向的节点(变量)和边的网络(或图)。图 1 描绘了三个独特的 图案,可以用三个变量(X,Y,Z)来制作。节点对应于变量 X、Y、Z,有向边(箭头)表示依赖关系或条件分布。网络是无环的 T21,这意味着不允许有反馈回路。
使用 DAG,可以通过组合(较简单的)部分来创建复杂的系统。
图 1:三节点 DAG 的三种独特模式(图片由作者提供)。
所有 Dag(大型或小型)都是根据以下 3 条规则构建的:
- 边是条件依赖。
- 边缘是有方向的。
- 不允许反馈循环。
这些规则很重要,因为如果您删除方向性(或箭头),三个 Dag 将变得相同。或者换句话说,有了方向性,我们可以使 DAG 可识别[2]。有许多博客、文章和维基百科页面描述了 Dag 背后的统计数据和因果关系。您需要理解的是,每个贝叶斯网络都可以通过这三种独特的模式来设计,并且应该代表您想要建模的过程。设计 DAG 是创建知识驱动模型的第一部分。 第二部分是定义条件概率表 ,用(条件)概率描述每个节点的关系强度。
第 2 部分:定义条件概率表来描述节点关系的强度。
概率论(又名贝叶斯定理或贝叶斯规则)构成了贝叶斯网络的基础。查看这篇关于 贝叶斯结构学习3的中型文章,阅读更多关于贝叶斯定理的具体部分。虽然这个定理在这里也适用,但还是有一些不同。首先,在知识驱动的模型中,CPT 不是从数据中学习的(因为没有数据)。相反,概率需要通过提问从专家那里获得,并随后存储在所谓的条件概率表(CPT)(也称为条件概率分布,CPD)中。在本文中,我将交替使用 CPT 和 CPD。**
CPTs 用条件概率或先验来描述每个节点的关系强度。
然后,CPT 与 Bayes 规则一起使用,以更新允许做出推断的模型信息。在下一节中,我将通过洒水车用例来演示如何用专业知识准确地填写 CPT。但是首先,将专家的知识转化为概率存在挑战。
将专家知识转化为概率
当我们想要建立一个知识驱动的模型时,从专家那里提取正确的信息是至关重要的。领域专家将告知成功流程的可能性和副作用的风险。将信息理解为旨在最大限度地降低沟通失误的风险,这一点非常重要。当与专家交谈时,许多估计的概率是口头传达的,用诸如“很可能之类的术语,而不是确切的百分比。
确保发送方和接收方的口头概率短语在概率或百分比方面是相同的。
在某些领域中,有一些指导原则将诸如’ common ‘这样的术语描述在一定的范围内,比如说 1-10%。但是如果没有该领域的背景知识,单词’ common '很容易被解释为不同的数字[ 4 ]。此外,概率短语的解释会受到其上下文[ 4 ]的影响。例如,比较您在下面两个语句中的数字解释:
- 明年六月,曼彻斯特(英格兰)可能会下雨。**
- 明年六月的 巴塞罗纳 (西班牙)可能会下雨。
很可能,你对第一句话中的“可能”的数值解释高于第二句话。小心上下文曲解,因为它也可能导致系统性错误,从而导致不正确的模型。概率短语的概观图如图 2 所示。
“不可能”似乎并不总是不可能的!
图 2:概率短语的解释。资料来源:Sanne Willems 等人,JCOM [ 4 ]
bnlearn 图书馆。
关于用于本文所有分析的 bnlearn 库的一些话。bnlearn 库旨在应对一些挑战,例如:
- 结构学习 :给定数据:估计一个捕捉变量间依赖关系的 DAG。
- 参数学习 :给定数据和 DAG:估计个体变量的(条件)概率分布。
- 推理 :给定学习过的模型:为你的查询确定准确的概率值。
bnlearn相比其他贝叶斯分析实现有什么好处?
建立一个基于专家知识的喷水灭火系统。
让我们从一个简单直观的例子开始,展示如何基于专家的知识构建真实世界的模型。在这个用例中,我将扮演自动喷水灭火系统领域专家的角色。
假设我的后院有一个自动喷水灭火系统,在过去的 1000 天里,我亲眼目睹了它是如何以及何时工作的。我没有收集任何数据,但我创造了一种关于工作的直觉。姑且称之为专家观点或领域知识。注意,洒水系统是贝叶斯网络中一个众所周知的例子。**
从我的专家的角度来看,我知道一些关于这个系统的事实;它有时开有时关(是不是很棒)。我经常看到--如果自动喷水系统在上,那么草可能会---湿。然而,我也知道下雨--几乎肯定 -也会导致湿草,并且喷水系统在大多数时间 - 关闭。我知道云在开始下雨之前经常出现。最后,我注意到在洒水器和多云之间有一个微弱的互动,但我不完全确定。****
从这一点开始,你需要将专家的知识转化为模型。这可以通过首先创建 图 然后定义连接图中节点的CPT来系统地完成。
喷水灭火系统由四个节点组成,每个节点有两种状态。
在喷水灭火系统中有四个节点,您可以从专家的视图中提取。每个节点有两种工作状态:下雨:是或否,多云:是或否,喷水系统:开或关,湿草:真或假。
定义简单的一对一关系。
复杂的系统是由简单的部分组合而成的。这意味着你 不需要 立刻创建或设计整个系统,而是首先定义较简单的部分。更简单的部分是一对一的关系。在这一步,我们将把专家的观点转换成关系。我们从专家那里得知:雨取决于多云状态,湿草取决于雨状态,但是湿草也取决于 s prinkler 状态。最后我们知道洒水靠多云。我们可以建立以下四种有向的一对一关系。
- 多云 → 下雨
- 雨 → 湿草
- 洒水器 → 湿草
- 多云 → 洒水器
重要的是要认识到,一对一部分之间的关系强度存在差异,需要使用 CPT 来定义。但是在进入 CPTs 之前,让我们先使用 bnlearn 制作 DAG。
DAG 基于一对一的关系。
这四个有向关系现在可以用来构建带有节点和边的图。每个节点对应一个变量,每个边代表变量对之间的条件依赖关系。在 bnlearn 中,我们可以赋值并图形化表示变量之间的关系。
pip install bnlearn
根据一对一的关系设计喷水灭火系统的 DAG。
在图 3 中是生成的 DAG。我们称之为因果 DAG* ,因为我们已经假设我们编码的边代表我们对喷水系统的因果假设。*
图 3:喷水灭火系统的 DAG。它编码了以下逻辑:湿草依赖于洒水器和雨水。洒水车依多云,雨依多云(图片作者)。
此时,DAG 拥有 没有 关于底层依赖关系的知识。我们可以用bn.print(DAG)
检查 CPT,这将导致消息“没有 CPD 可以打印”。我们需要用所谓的条件概率表和向 DAG 添加知识,我们将依靠专家的知识来填充条件概率表。**
可以用条件概率表(CPT)将知识添加到 DAG 中。
建立条件概率表。
洒水系统是一个简单的贝叶斯网络,其中湿草(子节点)受到两个父节点(雨和洒水器)的影响(见图 1)。节点洒水和下雨受单个节点影响;多云。多云节点不受任何其他节点的影响。
我们需要将每个节点与一个概率函数相关联,该函数将该节点的父变量的一组特定值作为输入,并给出(作为输出)该节点所表示的变量的概率。让我们为四个节点做这件事。
CPT:多云
多云节点有两种状态(是或否)并且没有依赖关系。当处理单个随机变量时,计算概率相对简单。从我专家的角度来看,在过去的 1000 天里,我有 70%的时间亲眼目睹了多云的天气(不过我没有抱怨,只是失望)。由于概率加起来应该是 1, 不是 多云的时间应该是 30%。CPT 看起来如下:
定义节点的 CPT:多云。
CPT:下雨
雨节点有两种状态,受多云制约,多云也有两种状态。总的来说,我们需要指定 4 个条件概率,即在给定一个事件发生的情况下,另一个事件发生的概率。在我们的情况下;假定多云,事件下雨发生的概率。 证据 因此多云而变量是雨。从我的专家的角度来看,我可以告诉你,当下雨的时候,80%的时间都是多云。我也确实看到下雨 20%的时间看不到云 ( 真的吗?是的。真实故事)。**
定义节点的 CPT:Rain。
CPT:洒水喷头
洒水器节点有两种状态,并受多云两种状态的制约。总的来说,我们需要指定 4 个条件概率。这里我们需要定义喷头出现多云的概率。 证据 因此多云而变量是雨。我可以说当洒水器关闭时,90%的时间都是多云。因此,对于洒水器为真和多云为真的对应情况是 10%。其他的概率我不太清楚,所以我会设置为 50%的几率。**
定义节点的 CPT:喷水装置。
CPT:湿草
湿草节点有两种状态,受两个双亲节点制约;下雨和洒水。这里我们需要定义湿草的概率,给定雨和洒水车的发生。总之,我们必须指定 8 个条件概率(2 个状态^ 3 个节点)。**
- 作为一个专家,我可以肯定,比如说 99%,在下雨或者洒水器开了之后看到湿草😛(湿草=1 |雨=1,洒水器=1) = 0.99。因此对应的是 P(湿草=0|雨=1,洒水器= 1)= 1–0.99 = 0.01
- 作为一个专家,我完全确定当不下雨或者洒水器没有打开的时候,没有湿草😛(湿草=0 |雨=0,洒水器=0) = 1。相应的是:P(湿草=1 |雨=0,洒水器= 0)= 1–1 = 0**
- 作为专家,我知道湿草几乎都发生在下雨和洒水器关闭的时候(90%)。p(湿草=1 |雨=1,洒水车=0) = 0.9。对应的就是:P(湿草=0 |雨=1,洒水车= 0)= 1–0.9 = 0.1。
- 作为专家,我知道湿草几乎总是发生在不下雨并且洒水器开着(90%)的时候。p(湿草=1 |雨=0,洒水车=1) = 0.9。对应的就是:P(湿草=0 |雨=0,洒水车= 1)= 1–0.9 = 0.1。
定义节点的 CPT:湿草地
就是这个!此时,我们定义了 DAG 与 CPT 之间的关系强度。现在我们需要连接 DAG 和 CPT。
使用 CPT 更新 DAG:
所有 CPT 都已创建,现在我们可以将它们与 DAG 连接起来。作为健全性检查,可以使用 print_DAG 功能检查 CPT。
用 CPT 更新喷水灭火系统的 DAG。
带有 CPT 的 DAG 现在将如图 4 所示。
图 4:喷水灭火系统的因果 DAG 与连接的 CPT(图片由作者提供)。
对因果模型进行推论。
干得好!至此,您已经创建了一个描述数据结构的模型,以及定量描述每个节点及其父节点之间的统计关系的 CPT。让我们对我们的模型提几个问题,举一反三!
****How probable is having wet grass given the sprinkler is off?*** *P(Wet_grass=1 | Sprinkler=0) = 0.6162****How probable is a rainy day given sprinkler is off and it is cloudy?***
*P(Rain=1 | Sprinkler=0, Cloudy=1) = 0.8**
对因果喷水灭火系统做出推论。
讨论
贝叶斯网络的一个优点是,对于人类来说,直观上更容易理解直接相关性和局部分布,而不是完全的联合分布。要制作知识驱动的模型,我们需要两种成分;DAG 和条件概率表(CPT)。两者都来源于专家的提问。DAG 描述数据的结构,需要 CPT 来定量描述每个节点与其父节点之间的统计关系。虽然这种方法似乎是合理的,但是您应该意识到通过向专家提问可能会出现系统错误,以及在构建复杂模型时的局限性。
我如何知道我的因果模型是正确的?
在喷头的例子中,我们通过个人经验提取领域专家的知识。虽然我们创建了因果图,但是很难完全验证因果图的有效性和完整性。例如,你可能对概率和图表有不同的观点,你也可能是对的。作为一个例子,我描述道:“我也确实在 20%的时间里没有看到云的情况下看到了雨”。对这样的说法进行争论可能是有道理的。相反,也可能在同时存在多个真知识模型。在这种情况下,你可能需要综合各种可能性,或者决定谁是对的。
所使用的知识和专家的经验一样丰富,和专家的偏见一样丰富多彩。
或者换句话说,我们通过向专家提问提取的概率是 主观概率【5】。在洒水喷头的例子中,接受这个概率的概念是个人的就足够了,它反映了特定的人在特定的时间特定的地点的信仰程度。这样质疑自己;如果专家生活在英国相比于西班牙,喷头型号会有变化吗?
如果你想使用这样的程序来设计一个知识驱动的模型,理解人们(专家)如何得出概率估计是很重要的。在文献中描述了当对不确定事件进行推理时,人们很少遵循概率原则,而是用有限数量的试探法[ 6 ,7]代替概率法则,例如代表性*、可用性和*来自锚的调整。请注意,这可能会导致系统误差和不正确的模型。此外,确保发送方和接收方的口头概率短语在确切的概率或百分比方面是相同的。
复杂性是一个主要的限制。
所提出的喷水灭火系统只有几个节点,但是贝叶斯网络可以包含更多具有多级父子依赖关系的节点。在贝叶斯网络中填充条件概率表(CPT)所需的概率分布的数量随着与该表相关联的父节点的数量呈指数增长。如果要通过从领域专家那里获得的知识来填充表格,那么任务的巨大规模会形成相当大的认知障碍[ 8 ]。
过多的父子依赖会对领域专家形成相当大的认知障碍。
例如,如果 m 父节点表示布尔变量,那么概率函数由一个具有条目的表来表示,每个条目对应一个可能的父组合。不要创建大图(超过 10-15 个节点),因为父子依赖的数量会对领域专家形成相当大的认知障碍。如果您有想要建模的系统的数据,也可以使用结构学习[3] 来学习结构(DAG)和/或其参数(CPTs) 。**
我们能把专家的知识变成模型吗?
我再重复一遍我之前的说法:“嗯,这取决于你用图形表示知识的准确度,以及你用概率定理把它粘在一起的准确度。”
最后的话
这就是了。创建一个知识驱动的模型并不容易。这不仅是关于数据建模,也是关于人类心理。确保你为专家面试做好准备。多次短面试比一次长面试好。系统地问你的问题。首先设计有节点和边的图,然后进入 CPTs。讨论概率时要谨慎。理解专家如何得出他的概率,并在需要时进行标准化。检查时间和地点是否会影响结果。建立模型后进行健全性检查。偶尔微笑。
注意安全。保持冷静。
欢呼,E.
如果你觉得这篇文章很有帮助,可以使用我的 推荐链接 继续无限制学习,并注册成为中级会员。另外, 关注我 保持我的最新内容!
软件
我们连线吧!
参考
- 维基百科,知识
2.朱迪亚·珀尔(2000 年)。因果关系:模型、推理和推论。剑桥大学出版社。ISBN 978–0–521–77362–1。OCLC 42291253。
3.E.Taskesen,使用 Python 中的贝叶斯结构学习检测因果关系的逐步指南,Medium,2021
4.Sanne Willems 等人,荷兰新闻文章中概率短语解释的可变性——误传的风险,JCOM,2020 年 3 月 24 日
5.R. Jeffrey,主观概率:真实的事物,剑桥大学出版社,剑桥,英国,2004 年。
6.A. Tversky 和 D. Kahneman,不确定性下的判断:启发和偏见,《科学》,1974 年
7.特沃斯基和 d .卡内曼,“不确定性下的判断:试探法和偏见”,载于《不确定性下的判断:试探法和偏见》,d .卡内曼、p .斯洛维奇和 a .特沃斯基编辑。,剑桥大学出版社,剑桥,1982 年,第 3-2 页
8.Balaram Das,生成贝叶斯网络的条件概率:缓解知识获取问题。Arxiv
使用 Python 中的贝叶斯结构学习检测因果关系的分步指南
实践教程
有效确定变量间因果关系的入门指南。
确定变量之间的因果关系可能是一个具有挑战性的步骤,但它对于战略行动非常重要。我将从 贝叶斯概率 方面总结 因果模型 的概念,后面是一个动手教程,利用贝叶斯结构学习检测因果关系。我将使用喷洒器数据集从概念上解释如何使用 Python 库 bnlearn 学习结构。
如果你觉得这篇文章很有帮助,可以使用我的 推荐链接 继续无限制学习,并注册成为中级会员。另外, 关注我 关注我的最新内容!
背景
在疾病预测、推荐系统、自然语言处理等许多领域,机器学习技术的使用已经成为获得有用见解和进行预测的标准工具包。虽然可以实现良好的性能,但提取与目标变量的因果关系并不简单。换句话说:哪些变量对目标变量有直接的因果作用?这些洞察对于确定得出结论的驱动因素非常重要,因此可以采取战略行动。机器学习的一个分支是贝叶斯概率图形模型,也称为贝叶斯网络(BN),可用于确定这些因果因素。
在我们进入因果模型的技术细节之前,让我们重温一些术语。术语“相关性”和“关联性”经常互换使用。但我们都知道,相关或关联并不是因果关系。或者换句话说,观察到的两个变量之间的关系并不一定意味着一个导致另一个。从技术上讲,相关性指的是两个变量之间的线性关系,而关联性指的是两个(或更多)变量之间的任何关系。另一方面,因果关系意味着一个变量(通常称为预测变量或自变量)引起另一个变量(通常称为结果变量或因变量)[1]。在接下来的两节中,我将通过示例简要描述关联和关联。
相互关系
皮尔逊相关是最常用的相关系数。这是如此普遍,它经常被用作相关的同义词。强度由 r 表示,并在从-1 到 1 的标准化范围内测量样本中线性关系的强度。使用关联时有三种可能的结果:
- 正相关:两个变量之间的关系,其中两个变量的运动方向相同
- 负相关:两个变量之间的关系,其中一个变量的增加与另一个变量的减少相关
- 无相关性:两个变量之间没有关系。
图 1 展示了一个正相关的例子,在图 1中,我们看到了巧克力消费量与每个国家诺贝尔奖获得者人数之间的关系【2】。
图 1:巧克力消费与诺贝尔奖得主之间的相关性
该图显示,巧克力消费可能意味着诺贝尔奖获得者的增加。或者反过来说,诺贝尔奖获得者的增加同样可能导致巧克力消费量的增加。尽管相关性很强,但更有可能的是,社会经济地位或教育系统质量等未被观察到的变量可能会导致巧克力消费量和诺贝尔奖获得者人数的增加。或者换句话说,这种关系是否是因果关系还是个未知数[2]。这并不意味着相关性本身是无用的,它只是有一个不同的目的[3]。相关性本身并不意味着因果关系,因为统计关系并不唯一地约束因果关系。
联想。
当我们谈到关联时,我们的意思是一个变量的某些值往往与另一个变量的某些值同时出现。从统计学的角度来看,有许多关联的测量方法(如卡方检验、Fisher 精确检验、超几何检验等),通常用于一个或两个变量为序数或名义变量的情况。应该注意的是,相关性是一个技术术语,而术语关联不是,因此,在统计学上并不总是有一致的含义。这意味着陈述你正在使用的术语的含义总是一个好习惯。关于关联的更多信息可以在这个博客[4]中找到,并且阅读这个关于如何通过一个重要关联的网络 [5】探索和理解你的数据的博客。
为了举例,我将使用超几何测试来演示两个变量是否与使用 Titanic 数据集的相关联。泰坦尼克号数据集在许多机器学习例子中使用,众所周知,性别状态(女性)是存活率的良好预测器。我来演示一下如何计算幸存和女性之间的关联*。*
首先安装bnlearn库,只加载泰坦尼克数据集。
*pip install bnlearn*
问:雌性存活的概率有多大?
存活与雌性之间的超几何检验
无效假设:存活者与女性没有关系。
超几何检验使用超几何分布来衡量离散概率分布的统计显著性。在本例中, N 是总体大小(891), K 是总体中成功状态的数量(342), n 是样本大小/抽签数(314), x 是成功的数量
等式 1:使用超几何检验来检验存活者和雌性之间的关联。
我们可以在α= 0.05 的情况下拒绝零假设,因此,我们可以谈论幸存者和女性之间的统计显著关联。* 重要的是,联想本身并不意味着因果关系。 我们需要区分 边际 关联和 条件 关联。后者是因果推理的关键组成部分。*
因果关系。
因果关系是指一个(独立)变量引起另一个(因变量),由赖兴巴赫(1956)* 表述如下:*
如果两个随机变量 x 和 y 在统计上是相关的(X/Y),那么要么(a) X 导致 y,(b) Y 导致 x,要么©存在第三个变量 z 导致 x 和 y。此外,给定 z,即 X⊥Y∣Z.,x 和 y 变得独立
这个定义包含在贝叶斯图形模型中(又称贝叶斯网络、贝叶斯信念网络、贝叶斯网、因果概率网络和影响图)。同一个技术有很多名字。为了确定因果关系,我们可以使用贝叶斯网络(BN)。让我们从图表开始,可视化由赖兴巴赫* (X,Y,Z)描述的三个变量之间的统计相关性(见图 2)。节点对应于变量(X,Y,Z ),有向边(箭头)表示依赖关系或条件分布。*
图 2:Dag 编码条件独立性。(a,b,c)是等价类。(a,b) 级联,©、【d】是具有 V 型结构的特殊类。**
可以创建四个图形;*【a,b】Cascade、【c】*Common parent 和(d)V-结构、这些图构成了贝叶斯网络的基础。
但是我们怎么能知道什么导致什么呢?
确定因果关系的方向,从而确定哪个节点影响哪个节点的概念思想是通过保持一个节点不变,然后观察效果。举个例子,让我们看一下图 2 中的 DAG (a ),它描述了 Z 是由 X 引起的,Y 是由 Z 引起的,如果我们现在保持 Z 不变,如果这个模型是真的,Y 应该不会有变化。每一个贝叶斯网络都可以用这四个图来描述,用(见下一节)我们可以把各个部分粘在一起。**
贝叶斯网络是概率论和图论的完美结合。
应该注意,贝叶斯网络是一个有向无环图 (DAG),DAG 是因果的。这意味着图中的边是指向的,并且没有(反馈)循环(非循环)。**
概率论
概率论,或更具体的贝叶斯定理或贝叶斯规则,形成了贝叶斯网络的基础。贝叶斯规则用于更新模型信息,在数学上表述为以下等式:
等式 2:贝叶斯法则。
该方程由四部分组成; 后验概率 是给定 x 时 Z 发生的概率 条件概率 或可能性是假设为真时证据出现的概率。这可以从数据中推导出来。我们的 先验 信念是在观察证据之前假设的概率。这也可以从数据或领域知识中获得。最后, 边际 概率描述了新证据在所有可能假设下需要计算的概率。如果你想阅读更多关于(因式分解)概率分布或贝叶斯网络联合分布的细节,试试这个博客[6]。
贝叶斯结构学习估计 DAG。
通过结构学习,我们希望确定能够最好地捕捉数据集中变量之间的因果依赖关系的图的结构。换句话说:
最符合数据的 DAG 是什么?
寻找最佳 DAG 的一种简单的方法是创建图的所有可能的组合,即,通过制作几十个、几百个、甚至几千个不同的 DAG,直到所有的组合都用尽。然后,可以根据数据的拟合度对每个 DAG 进行评分。最后,返回得分最高的 DAG。在变量 X,Y,Z 的情况下,我们可以做出如图 2 所示的图形以及更多的图形,因为它不仅是 X>Z>Y(图 2a),还可以是 Z>X>Y,等等。变量 X,Y,Z 可以是布尔值(真或假),但也可以有多种状态。Dag 的搜索空间在使分数最大化的变量数量上变成所谓的超指数。这意味着对于大量节点,穷举搜索实际上是不可行的,因此,已经提出了各种贪婪策略来浏览 DAG 空间。使用基于优化的搜索方法,可以浏览更大的 DAG 空间。这种方法需要一个核函数和一个搜索策略。一个常见的评分函数是给定训练数据的结构的后验概率,如 BIC 或 BDeu。
大型 Dag 的结构学习需要评分函数和搜索策略。
在我们进入示例之前,理解何时使用哪种技术总是好的。有两种广泛的方法来搜索整个 DAG 空间并找到数据的最佳拟合图。
- 基于分数的结构学习
- 基于约束的结构学习
注意,局部搜索策略进行了旨在提高结构得分的增量改变。像马尔可夫链蒙特卡罗这样的全局搜索算法可以避免陷入局部极小值,但我不会在这里讨论。
基于分数的结构学习
基于分数的方法有两个主要组成部分:
- 在所有可能 Dag 的搜索空间中进行优化的搜索算法;如穷举搜索*、 Hillclimbsearch 、 Chow-Liu 。***
- 评分函数表示贝叶斯网络与数据的吻合程度。常用的评分函数有贝叶斯狄利克雷得分如 BDeu 或 K2 和贝叶斯信息准则* ( BIC ,也叫 MDL)。***
下面描述了四种常见的基于评分的方法,但是关于贝叶斯评分方法的更多细节可以在这里找到[9]。
- **穷举搜索 ,顾名思义,对每个可能的 DAG 进行评分,并返回得分最高的 DAG。这种搜索方法只对非常小的网络有吸引力,并且阻止有效的局部优化算法总是找到最佳结构。因此,确定理想的结构通常是不容易的。然而,如果只涉及几个节点(例如:少于 5 个左右),启发式搜索策略通常会产生好的结果。
- Hillclimbsearch是一种启发式搜索方法,如果使用更多的节点,可以使用这种方法。 HillClimbSearch 执行贪婪的局部搜索,从 DAG“start”(默认:断开的 DAG)开始,通过迭代执行单边操作来最大限度地增加分数。一旦找到局部最大值,搜索就终止。
- Chow-Liu 算法是一种特定类型的基于树的方法。Chow-Liu 算法找到最大似然树结构,其中每个节点最多有一个父节点。可以通过限制树形结构来限制复杂度。
- 树增强朴素贝叶斯(TAN) 算法也是一种基于树的方法,可用于对在其各种相互依赖的特征集之间涉及大量不确定性的巨大数据集进行建模[6]。
基于约束的结构学习
- 卡方检验。 一种不同但相当直接的方法,通过使用假设检验(如 chi2 检验统计量)识别数据集中的独立性来构建 DAG。这种方法依赖于统计测试和条件假设来学习模型中变量之间的独立性。chi2 检验的 P 值是观察到计算出的 chi2 统计值的概率,给定零假设,即 X 和 Y 是独立的,给定 z。这可用于在给定的显著性水平上做出独立的判断。基于约束的方法的一个例子是 PC 算法,该算法从一个完整的全连通图开始,并且如果节点是独立的,则基于测试结果移除边,直到达到停止标准。
bnlearn 图书馆
关于本文中用于所有分析的 bnlearn 库,说几句话。 bnlearn 库旨在应对一些挑战,例如:
- 结构学习 :给定数据:估计一个捕捉变量间依赖关系的 DAG。
- 参数学习 :给定数据和 DAG:估计个体变量的(条件)概率分布。
- 推论 :给定学习过的模型:为你的查询确定准确的概率值。
bnlearn相比其他贝叶斯分析实现有什么好处?
喷头数据集中的结构学习。
让我们用一个简单直观的例子来演示结构学习的工作原理。假设你的后院有一个喷水系统*,在过去的 1000 天里,你测量了四个变量,每个变量有两种状态:雨(是或否)多云(是或否)喷水系统(开或关),以及湿草(对或错)。基于这四个变量和你对现实世界的概念,你可能会有一个图形应该是什么样子的直觉。对吗?对吗?如果没有,你最好读一下这篇文章,因为通过结构学习你会发现!***
用bn learn只用几行代码就很容易确定因果关系。
在下面的例子中,我们将导入 bnlearn 库,加载洒水喷头数据集,并确定哪个 DAG 最适合该数据。请注意,洒水喷头数据集很容易清理,不会丢失值,并且所有值都具有状态 1 或 0。
图 3:喷水灭火系统的最佳 DAG 示例。它编码了以下逻辑:草地潮湿的概率取决于洒水器和雨水。洒水喷头开启的概率取决于多云天气。下雨的可能性取决于多云天气。
就是这样!我们已经学习了如图 3 所示的结构。检测到的 DAG 由通过边连接的四个节点组成,每个边指示一个因果关系。湿草的状态取决于两个节点,下雨和洒水。下雨的状态受多云的制约,另外洒水器的状态也受多云的制约。这个 DAG 表示(分解的)概率分布,其中 S 是洒水喷头的随机变量, R 表示下雨, G 表示湿草地, C 表示多云。****
通过检查图表,您很快就会看到模型中唯一的独立变量是 C 。其他变量取决于多云、下雨和/或洒水的概率。通常,贝叶斯网络的联合分布是给定其父节点的每个节点的条件概率的乘积:
在 bnlearn 中对于结构学习的默认设置是 hillclimbsearch 方法和 BIC 评分。值得注意的是,可以指定不同的方法和评分类型。请参见指定搜索和评分类型的示例:
bnlearn 中各种结构学习方法和评分类型的示例。
尽管检测到的洒水喷头数据集的 DAG 很有见地,并显示了数据集中变量的因果相关性,但它不允许您询问所有类型的问题,例如:
- 洒水装置关闭时,草地潮湿的可能性有多大?
- 在洒水装置关闭且多云的情况下,下雨的可能性有多大?
在洒水喷头数据集中,根据您对世界的了解和逻辑思维,结果可能很明显。但是一旦你有了更大、更复杂的图表,它可能就不再那么明显了。有了所谓的 推论, 我们就可以回答“假设我们做了什么”类型的问题,这些问题通常需要受控实验和明确的干预来回答。
如何进行推论?
为了做出推论,我们需要两个因素: DAG 和 条件概率表(CPTs) 。此时,我们将数据存储在数据帧( df )中,并且我们很容易计算出描述数据结构的 DAG 。需要 CPT 来定量描述每个节点与其父节点之间的统计关系。CPT 可以使用 参数学习 来计算,所以让我们先跳到参数学习,然后我们再回到做出推论。
参数学习
参数学习的任务是估计条件概率表的值。 bnlearn 库支持离散节点的参数学习:**
- 最大似然估计 是利用变量状态发生的相对频率进行的自然估计。当估计贝叶斯网络的参数时,缺少数据是一个常见的问题,并且 ML 估计器具有过拟合数据的问题。换句话说,如果观察到的数据对于基础分布不具有代表性(或者太小),那么最大似然估计可能会非常遥远。例如,如果一个变量有 3 个父变量,每个父变量有 10 个状态,那么对于 10 = 1000 个父变量的配置,将分别进行状态计数。这可能使 MLE 对于学习贝叶斯网络参数非常脆弱。减轻 MLE 过拟合的一种方法是贝叶斯参数估计。
- 贝叶斯估计 从容易存在的先验 CPT 开始,这些 CPT 表达了我们在数据被观察到之前对变量的信念。然后使用来自观测数据的状态计数来更新那些“先验”。人们可以认为先验存在于伪状态计数中,其在归一化之前被添加到实际计数中。一个非常简单的先验是所谓的 K2 先验,它简单地将“1”加到每个单个状态的计数上。更明智的先验选择是 BDeu (贝叶斯狄利克雷等价均匀先验)。****
喷头数据集上的参数学习。
我将继续使用洒水喷头数据集来学习其参数,从而检测到条件概率表(CPT)。为了学习参数,我们需要一个有向无环图(DAG)* 和一个具有完全相同变量的数据集。想法是将数据集与 DAG 连接起来。在前面的例子中,我们很容易计算 DAG(图 3)。您可以在这个示例中使用它,或者,您可以基于您对世界的了解创建自己的 DAG!在示例中,我将演示如何创建您自己的 DAG,它可以基于专家/领域知识。***
使用喷头数据集进行参数学习的示例。
如果您达到了这一点,那么您已经使用最大似然估计(MLE) 基于 DAG 和输入数据集 df 计算出了 CPTs (图 4)。注意,为了清楚起见,图 4 中包括了 CPT。**
图 4:CPT 是使用最大似然估计通过参数学习得出的。**
使用 MLE 计算 CPT 很简单,让我通过手动计算节点多云和下雨的 CPT 来举例说明。**
为多云和下雨的节点手动计算最大似然的例子。
请注意,条件依赖可以基于有限的数据点。作为一个例子, P(Rain=1|Cloudy=0) 是基于 91 个观测值。如果 Rain 有两个以上的状态和/或更多的依赖项,这个数字会更低。 是更多数据的解决方案? 也许吧。也许不是。请记住,即使总样本量非常大,每个父配置的状态计数都是有条件的,这一事实也会导致碎片。查看 CPT 与 MLE 方法的区别。
关于洒水喷头数据集的推论。
为了进行推理,它要求贝叶斯网络有两个主要组件:描述数据结构的有向无环图(DAG) 和描述每个节点及其父节点之间的统计关系的条件概率表(CPT)* 。此时,您有了数据集,使用结构学习计算了 DAG,使用参数学习估计了 CPT。你现在可以做推论了!***
通过推理,我们在一个叫做变量消除的过程中边缘化变量。变量消去法是一种精确的推理算法。它还可以用于计算出网络的状态,通过简单地交换最大函数的和,具有最大概率。它的缺点是,对于大型 bn,它可能在计算上很难处理。在这些情况下,可以使用近似推理算法,如吉布斯采样或拒绝采样。
用 bnlearn 我们可以做出如下推论:
现在我们有了问题的答案:
******How probable is it to have wet grass given the sprinkler is off?*** *P(Wet_grass=1 | Sprinkler=0) = 0.51* ***How probable is it have a rainy day given sprinkler is off and it is cloudy?*** *P(Rain=1 | Sprinkler=0, Cloudy=1) = 0.663****
我如何知道我的因果模型是正确的?
如果你仅仅使用数据来计算因果图,很难完全验证你的因果图的有效性和完整性。然而,一些解决方案有助于在因果图中获得更多信任。例如,有可能根据经验测试变量集之间的某些条件独立性或依赖性关系。如果它们不在数据中,则表明因果模型的正确性[8]。或者,可以添加先前的专家知识,例如 DAG 或 CPTs,以在进行推断时获得对模型的更多信任。
讨论
在本文中,我谈到了一些概念,关于为什么相关性或关联性不是因果关系,以及如何使用结构学习从数据走向因果模型。贝叶斯技术的优势总结如下:
- 后验概率分布的结果或图形允许用户对模型预测做出判断,而不是将单个值作为结果。
- 在 DAG 中整合领域/专家知识的可能性,以及不完整信息和缺失数据的推理。这是可能的,因为贝叶斯定理是建立在用证据更新先验项的基础上的。
- 它有模块化的概念。
- 复杂的系统是由简单的部分组合而成的。
- 图论直观地提供了高度交互的变量集。
- 概率论提供了结合各部分的粘合剂。
贝叶斯网络的另一方面的弱点是寻找最优 DAG 在计算上是昂贵的,因为必须对所有可能的结构进行穷举搜索。穷举搜索的节点限制可能已经是大约 15 个节点,但是也取决于状态的数量。如果您有更多的节点,则需要具有评分功能和搜索算法的替代方法。然而,为了处理具有数百甚至数千个变量的问题,有必要采用不同的方法,例如基于树或基于约束的方法,并使用变量的黑名单/白名单。这种方法首先确定顺序,然后找到该顺序的最佳 BN 结构。这意味着在可能排序的搜索空间上工作,这是方便的,因为它小于网络结构的空间。
确定因果关系可能是一项具有挑战性的任务,但 bnlearn 库旨在应对一些挑战,如 结构学习、参数学习、 和 推理 。但是它也可以导出(整个)图的拓扑排序,或者比较两个图。文档可在此处找到,其中还包含了报警、安第斯、亚洲、探路者、萨克斯车型的示例。****
注意安全。保持冷静。
欢呼,E.
如果您觉得这篇文章很有帮助,请使用我的 推荐链接 继续无限制学习,并注册成为中级会员。另外, 关注我 关注我的最新内容!
软件
我们连线吧!
- 让我们在 LinkedIn 上联系
- 在 Github 上关注我
- 在媒体上跟我来
参考
- 麦克劳德,S. A,相关定义,例题&释义 。单纯心理学 2018 年 1 月 14 日
- F.达布兰德,因果推理导论,心理学方法系,阿姆斯特丹大学,https://psyarxiv.com/b3fkw
- 布列塔尼·戴维斯,当相关性优于因果关系,中等,2021
- 保罗·金里奇措施协会。第 766–795 页
- Taskesen,E,通过一个重要关联网络探索和理解您的数据。2021 年 8 月,中等
- 布拉尼斯拉夫·霍兰德,概率图形模型介绍,中型,2020 年
- Harini Padmanaban,朴素贝叶斯和 Tes 的朴素分析与树增强朴素增强朴素贝叶斯模型的比较分析,圣何塞州立大学,2014 年
- 胡萨尔。曲线拟合之外的 ML:因果推理和微积分简介
- E.巴黎水等人,给定超结构寻找最优贝叶斯网络,《机器学习研究杂志》9(2008)2251–2286。