处理多个 Python 文件时的常见错误
Python 中的“模块”概念
照片由 Daniela Holzer 在 Unsplash 上拍摄
在最简单的情况下,我们在单个 Python 文件中编写代码(文件名以。py)。我们运行它,一切都像预期的那样工作,我们很高兴。然而,当您必须将代码分成多个 Python 文件时,事情会变得有点复杂,通常是为了更容易的代码管理和可读性。在这篇文章中,我将带你走过我陷入的一些常见错误,我希望你不要犯和我一样的错误。
在 Python 中,每个 Python 文件实际上都有一个称为“模块”的特定术语,当您使用著名的import
语法时,您正在几个不同的 Python 模块之间建立连接,以在您的上下文中完成复杂的任务。在此,我将阐述以下主题:
- 每个文件都有自己的全局变量
- 该函数总是记得它是在哪里创建的
- Python 是“按引用传递”的
- 使用一个单独的文件来保存跨多个 Python 文件的全局变量
如果你想进一步了解它们,请继续阅读!
每个模块/文件都有自己的全局变量
当您在 Python 文件中创建一个变量(不在函数中)时,您将这个变量挂载到当前模块的名称空间中。这个 Python 文件中的每个命令都可以访问、读取和修改变量的值,也就是说,它变成了一个全局变量。你也可以通过声明一个变量global.
来明确地在函数中定义一个全局变量
将局部变量设为全局变量(图片由作者提供)
然而,全局变量不能在不同的 Python 文件之间共享。为了说明这一点,让我们看下面的例子:
全局变量对于每个模块都是唯一的(图片由作者提供)
逻辑非常清晰,我在sub_module.py
中定义了一个函数,并尝试在main.py
文件中调用它。好像我在main.py
文件中定义了变量num=5
,但结果是函数不能访问它,原因是sub_module.py
不能访问其他 Python 模块中的全局变量,所以num=5
对程序是不可见的。怎么修?在正确的文件中定义num
即可。
在 sub_module.py(作者图片)中定义一个变量
Python 函数总是记得它被创建的位置
我不确定你是否对上面的例子感到困惑?当我第一次看到这个例子时,我确实这么做了,因为我将sub_module.py
中的test_func1
显式地导入到了main.py
中,很自然地认为该函数已经在当前作用域中了,不是吗?
但是 Python 函数总是知道它是在哪里创建的。尽管看起来test_func1
在main.py
中,但当被执行时,它仍然属于sub_module.py
,因为这是它被创建的地方。现在来看另一个有用的实用技巧:
记得在子模块中导入必要的包!
忘记在子模块中导入数字(图片由作者提供)
在上面的例子中,由于我们忘记在sub_module.py
中导入 NumPy 包,即使我们在main.py
中导入了它,它仍然不能被test_func1
访问。现在让我们来解决它:
在子模块中导入 Numpy 包(图片由作者提供)
通过引用传递与通过值传递
第一个例子是可行的,但是看起来很奇怪,不是吗?通常,我们将只在子模块中定义函数和类,而不是放入单个变量num=5
。解决这个问题的常见方法实际上是在test_func1
中添加num
作为参数,并且在main.py
文件中调用函数时也将num=5
传递给该函数。
将变量作为参数传递(图片由作者提供)
现在的问题是,这样做如何能让sub_module.py
识别出num
在哪里?是因为 Python 总是传引用而不是**传值。**为了说明这一点,让我们来看看调用该函数时实际发生了什么:
通过引用传递与通过值传递(图片由作者提供)
当你在main.py
中键入num=5
时,你基本上创建了一个驻留在一块物理内存中的整数类型的PyObject
,你用名字num
指向这块物理内存。既然 Python 总是通过引用传递,那么你可以想到test_func1
就会知道num
这个名字指向哪里。因此,它可以访问value
5,因为它知道这个值在哪里。
我可以在不同的文件中共享一个全局变量吗?
正如我们所讨论的,全局变量对于它自己的模块是唯一的。但有时我们真的希望有一个全局变量,可以被目录中的每个 Python 文件访问和修改。实现这一点的规范方法是用全局变量创建另一个文件。
保存全局变量的独立文件(图片由作者提供)
我故意把这个例子弄得有点复杂;这里我们有一个包含num=10
的gloabl_.py
python 文件。但是在main.py
文件中,我也创建了一个num=5
。虽然它们都被命名为num
,但是它们在不同的范围内,所以它可以告诉你它们的区别。在main.py
中,我们通过增加 1 来修改这个全局变量,这个变化也将反映在sub_module.py
中。注意这里我必须在 **test_func2**
函数中导入 **global_**
,因为如果我把导入语法放在开头,那么导入的num
将是在global_.num += 1
行执行之前的那个。记住, **sub_module.py**
在 **from sub_module import ***
行中被执行,我们可以在下面的例子中测试它:
导入语法的顺序很重要(图片由作者提供)
如你所见,现在即使全局变量num
增加了 1,它也没有反映在sub_module.py
中,因为它们导入的变量来自操作之前。导入的时候,Python 会自动为你做一个拷贝,这样旧的global_.num
和新的global_.num
就生活在完全不同的物理内存中了。
结论
以下是处理多个 Python 文件时的一些最佳实践:
- 将变量作为参数传递,因为 Python“通过引用传递”,这保证了你的子模块可以访问你传递的变量。
- 不要忘记在子模块中导入必要的包,因为函数总是记得它是在哪里创建的。
- 使用一个单独的文件来保存 Python 模块中的全局变量,但是要记住导入全局变量将会复制原始变量,所以要经常检查你是否在程序中引用了正确的变量。
差不多就是这样!我希望你觉得这篇文章有趣和有用,感谢阅读!如果你喜欢这篇文章,请在 medium 上关注我,非常感谢你的支持。在我的 Twitter 或 LinkedIn 上联系我,也请让我知道你是否有任何问题或你希望在未来看到什么样的教程!
常见电话面试问题—第一部分
一些公司会进行一轮电话面试,他们会从你的简历中问你一些问题以及一些简单的技术问题。我试着列出了这些问题。如果你是技术新手或者想复习一些概念,这也会对你有所帮助。
马库斯·斯皮斯克在 Unsplash 上的照片
1。线程与进程。
进程是程序的实例,线程是进程的子集。进程和线程都是独立的执行序列。
- (同一进程的)线程运行在共享内存空间,而进程运行在独立的内存空间。因此,线程有自己的堆栈(局部变量),但共享同一个堆。进程有独立的堆栈和堆。
- 线程可以通过共享内存高效地进行通信。它们可以使用存储在堆中的对象进行通信,其中每个线程都可以访问相同内存位置的相同对象。进程使用进程间通信(IPC ),操作系统必须参与其中。
- 线程比进程花费更少的时间来创建和终止,因为它们消耗更少的资源。
- 在单处理器系统上,应用线程调度算法,并且调度处理器一次运行一个线程。因此,线程是并发的,而不是每个处理器并行的。
来源:https://www.tutorialspoint.com/
2.数据竞争:
当多个线程运行同一个程序,并且两个或多个线程同时访问同一个共享变量时,就会发生数据竞争。它会导致不可预测的输出,有时当结果不理想时会引起问题。
一个例子是:
理想场景:我们希望将初始值为 0 的变量的值递增 1,递增两次,有两个线程为我们做这件事。最终的结果应该是变量的值变成了 2。
来源:https://en.wikipedia.org/wiki/Race_condition
如果两个线程都读取原始值,然后重写它,最终结果将是错误的,这可能是我们程序中的一个主要错误。
资料来源:https://en.wikipedia.org/wiki/Race_condition
可以通过引入锁来防止数据竞争。这样,当一个线程访问变量以更新其值时,变量的访问将被锁定,直到该线程完成其操作。因此,在第一个线程完成更新之前,另一个线程将不得不“等待”,并且不能访问、读取或更改变量值。
但是,如果不小心使用锁,它们会导致死锁。
3.死锁:
这是一种两个或多个线程因为相互等待而被永久阻塞的情况。它会导致线程挂起,并有可能导致整个进程挂起。
4.面向对象编程的四大支柱:
馅饼:抽象、多态、继承、封装
抽象:抽象类和方法
- 你可以记住“抽象”这个词是什么意思,它是抽象这个词的一部分。
- 用于向用户隐藏复杂的细节,使用户能够使用程序或在上面实现更复杂的代码,而不用担心/知道当前程序所涉及的复杂性。
- 它是通过使用抽象类和方法来实现的。
- 抽象类是我们可以声明抽象方法的类。抽象方法是没有主体的方法,只有名字,没有实现。
- 一个经典的例子是具有抽象区域方法的抽象形状类。这个类的孩子(圆、三角形等)将有不同的方法来实现这个面积方法。
多态:重写和重载
- 你可以通过“poly”这个词来记住它,在希腊语中它的意思是很多。通过使用覆盖和重载,同一个方法在不同的子类中可以有“许多”形式。
I:继承:扩展,父类和子类
- 你可以记住这一点,记住你继承了你父母的特征,如头发和眼睛的颜色等。类似地,继承是子类接收或继承其父类的属性的过程。
- “extends”关键字用于由子类(子类)继承任何超类(父类)的属性。这有助于提高可重用性,减少代码长度,并防止用户重复编写相同的代码。
e:封装:Getters 和 Setters
- 您可以通过将单词 encapsulation 与“封装”相关联或者将方法和变量包装在一起从而隐藏数据来记住这一点。
- 当您将变量声明为私有变量并使用 getters 和 setters 来提供对它们的访问时,就会出现这种情况。
- 这有助于控制在我们的类的字段中存储什么,有限制以及使某些元素只读或只写。
5.为什么我们需要 OOPS(面向对象编程系统)?
面向对象的编程语言是那些在编程中使用“对象”概念的语言。要回答这个问题,你可以先说“哎呀”,这有助于有效和容易解决问题。它们使复杂的代码更容易理解和维护。然后,您可以谈论以下概念:
- 对象:代表现实生活中的实体的任何东西
- 类:对象的蓝图
- 方法:几行代码聚集在一起执行一些任务,它们可能接受也可能不接受输入并提供期望的输出。
然后讨论上面提到的四个支柱及其好处。
这应该足以表明你对面向对象编程有透彻的理解。
这就是第 1 部分的内容!如果您觉得它有帮助,请告诉我,如果有问题或博客主题建议,请在我的社交网站上与我联系。感谢您的阅读!
编辑:你可以和我建立一对一的职业辅导,我可以通过分享我的精确策略、修改你的简历、求职信或 Linkedin 简介来帮助你获得实习机会。你可以去 anjaliviramgama.com 看评论和安排时间
安贾利·维拉加马
脸书软件工程实习生,即将成为微软软件工程师
SQL 中的 cte:数据科学家编写更好 SQL 的 5 个技巧
从 SQL Server 到 Google BigQuery:了解我为什么喜欢常用表表达式。
授权给作者的图像
这是我从事 SQL 工作的第 20 个年头(eek!).为了纪念这个里程碑,我最近写了一篇关于我所遵循的 10 个 SQL 命名标准的文章,我觉得这些标准可以产生易于阅读、调试和维护的 SQL。
</10-sql-standards-to-make-your-code-more-readable-in-2021-4410dc50b909>
按照这个主题,我想我应该探索一下 SQL 语言的其他元素,帮助区分出色的 SQL 和简单的函数式 SQL。
我列表中最重要的一个元素是通用表表达式,简称 CTE。cte 于 2000 年首次推出,现在广泛应用于大多数现代数据库平台,包括 MS SQL Server、Postgres、MySQL 和 Google BigQuery。
我在示例中使用了 Google BigQuery,但是 cte 的语法与您可能使用的其他数据库平台非常相似。我使用了桑坦德循环雇佣计划数据集,这是谷歌公开数据集的一部分。
给 BigQuery 用户一个快速提示——如果你想知道为什么我的 BigQuery UI 看起来和你的不一样,我使用的是 2021 年的更新 UI,刚刚在预览版中发布。如果你想知道我对新特性的看法,可以看看我几天前发表的文章。
</5-great-features-in-bigquerys-new-ui-for-2021-yes-it-has-tabs-c4bac66d66b>
有哪些常见的表格表达式?
对于那些不熟悉 CTE 的人,或者刚刚开始数据科学职业生涯的人,CTE 是 SQL 查询的临时结果集,您可以在更广泛的 SQL 查询的其他部分引用它,就好像它是数据库中的永久表一样。CTE 是临时的,只在更广泛的查询执行期间存在。您可以为 cte 起别名(命名),类似于为表或列起别名,并且每个查询可以有多个 cte。
下面是基本语法:
with **employee_cte** as (select first_name, last_name from employee)select e.first_name,
e.last_name,
h.hire_date
from **employee_cte** e
inner join employee_hire h
on h.employee_id = e.employee_id
遵循我的 5 个建议,希望到最后,你会有一些好的最佳实践来开始自己探索它们。
所以,不分先后,我们开始吧。
#1 避免重复的列转换
在此查询中,我想查找伦敦市中心 500 米范围内的所有自行车站点,并返回站点名称和到中心的距离:
select name as station_name,
**st_distance
(
st_geogpoint( longitude, latitude),
st_geogpoint(-0.118092, 51.509865)
)** as distance_from_city_centre_mfrom `bigquery-public-data.london_bicycles.cycle_stations`
where **st_distance
(
st_geogpoint( longitude, latitude),
st_geogpoint(-0.118092, 51.509865)
)** <= 500
order by distance_from_city_centre_m
虽然这是完美的功能,并返回正确的结果(下面,如果你好奇!),您会注意到以粗体显示的用于计算距离的逻辑是重复的。这是我们想要避免的;逻辑应该被定义一次**,如果需要的话,使它更容易阅读和修改。**
这就是 CTE 来拯救我们的地方:
**with stations**
as
(
select name as station_name,
st_distance
(
st_geogpoint( longitude, latitude),
st_geogpoint(-0.118092, 51.509865)
) as distance_from_city_centre_m
from `bigquery-public-data.london_bicycles.cycle_stations`
)select station_name,
distance_from_city_centre_m
from **stations**
where distance_from_city_centre_m <= 500
order by distance_from_city_centre_m
不再有重复的逻辑。而且,我认为这也比第一个查询更容易阅读——你认为呢?
因为我的 CTE 站是临时的,我不需要用任何物化的(永久的)表格或视图来填充我的数据库。
自行车租赁站,距离伦敦中心 500 米以内
#2 简化复杂的 SQL (KISS)
就像在编程的其他领域以及生活中一样,如果你尽可能地保持简单,这真的会有所帮助。我们可以在 SQL 代码中使用 cte 来实现这一点的一种方法是使用 cte 作为一种将复杂的 SQL 查询分解成个更小的小块的方式。这会产生 SQL,它是:
- 更容易阅读和理解
- 更容易调试;您分阶段构建 SQL,在继续下一步之前测试每个 CTE 的输出。
- 更容易维护;改变逻辑现在可以在一个地方以一种更加模块化的方式完成。
在本例中,我想进一步探索距离市中心 500 米以内的车站,并挑选出在过去 12 个月中旅程最多的车站。然后,我想提取所有比这多的其他车站,并分析它们与市中心的距离。
实现这一点的一种方法(没有 cte)如下:
select s.name as station_name,
st_distance
**(
st_geogpoint( s.longitude, s.latitude),
st_geogpoint(-0.118092, 51.509865)
)** as distance_from_city_centre_m,
count(j.rental_id) as journey_count
from `bigquery-public-data.london_bicycles.cycle_stations` s
inner join `bigquery-public-data.london_bicycles.cycle_hire` j
on j.end_station_id = s.id
and cast(j.end_date as date) >= date_sub('2017-1-1', interval 1 year)
group by station_name, s.longitude, s.latitude
having count(j.rental_id) >
(
select journey_count
from
(
select dense_rank()
over (order by count(j.rental_id) desc) as rank,
s.id as station_id,
count(j.rental_id) as journey_count
from `bigquery-public-data.london_bicycles.cycle_stations` s
inner join `bigquery-public-data.london_bicycles.cycle_hire` j
on j.end_station_id = s.id
and cast(j.end_date as date) >= date_sub('2017-1-1', interval 1 year)
where j.end_station_id in
(
select s.id as station_id
from `bigquery-public-data.london_bicycles.cycle_stations` s
where **st_distance(
st_geogpoint( s.longitude, s.latitude),
st_geogpoint(-0.118092, 51.509865)
)** <= 500
)
group by station_id
)
where rank = 1
)
order by journey_count desc
再说一遍,这是完美的功能代码。然而,有重复的逻辑(粗体),我觉得这很难阅读。此外,如果我必须调试它,这将是很困难的——例如,验证最繁忙的工作站,因为一切都是交织在一起的。
应用 cte,我们可以大大改进这一点(cte 以粗体显示):
**with station_proximity**
as
(
select id as station_id,
name as station_name,
st_distance(
st_geogpoint( longitude, latitude),
st_geogpoint(-0.118092, 51.509865)
) as distance_from_city_centre_m from `bigquery-public-data.london_bicycles.cycle_stations`
),**station_journeys**
as
(
select s.station_id,
s.station_name,
s.distance_from_city_centre_m,
count(1) as journey_count
from **station_proximity** s
inner join `bigquery-public-data.london_bicycles.cycle_hire` j
on j.end_station_id = s.station_id
and cast(j.end_date as date) >= date_sub('2017-1-1', interval 1 year)
group by s.station_id, s.station_name, s.distance_from_city_centre_m
),**stations_near_centre**
as
(
select sp.station_id,
sj.journey_count,
dense_rank()
over (order by sj.journey_count desc) journey_rank,
from **station_proximity** sp
inner join **station_journeys** sj
on sj.station_id = sp.station_id
where sp.distance_from_city_centre_m <= 500
)select station_name,
distance_from_city_centre_m,
journey_count
from **station_journeys**
where journey_count >
(
select journey_count
from **stations_near_centre** s
where s.journey_rank = 1
)
order by journey_count desc
我觉得这个更好读。如果我想对此进行调试,我可以很容易地将最终选择改为从每个 CTE 中依次选择,在进入下一个之前进行验证。
(如果你感兴趣,下面是结果。正如你所料,这些车站大多数都靠近铁路干线)
#3 命名很重要
我的第三个建议是在给你的 cte 命名时要小心。
在我前面的例子中,我注意用有意义的名称来命名我的 cte:
**with station_proximity**
as
( --- ),**station_journeys,**
as
( -- ),**stations_near_centre**
as
( -- )
我经常看到这种情况,如果可能的话,我会尽量避免:
**with cte1**
as
( --- ),**cte2,**
as
( -- ),**cte3**
as
( -- )
#4 非常适合 SQL 联合
在处理数据时,我们经常需要将不同来源的数据整合到一个符合的表中。
cte 非常适合这个用例。
假设我们在两个系统 A 和 b 中进行循环旅程。我们可以在编写代码时有效地使用 cte 来填充单个旅程表,如下所示:
**with system_a_journeys**
as
( some data wrangling of system a ),**system_b_journeys,**
as
( some data wrangling of system b),**all_journeys**
as
(
select *
from **system_a_journeys** union allselect *
from **system_b_journeys** )
**注意我从不提倡使用 select (显式列出列)。
#5 使用 cte 显示依赖性
cte 的另一个可以提高 SQL 可维护性的新用途是,使用它们可以很容易地看到 SQL 引用了哪些表/视图。这对于复杂的查询特别有用,它跨越许多行,并引用许多表/视图。
为此,在 SQL 语句的开头,为您选择的所有表/视图创建 CTE“包装器”。您还可以将列限制为您实际使用的列,这不仅有助于识别您正在使用的列,还可以提高性能。
因此,在我的技巧 2 的例子中,我将从以下内容开始查询:
with cycle_stations as
(
select id as station_id,
name as station_name,
longitude,
latitude
from `bigquery-public-data.london_bicycles.cycle_stations`
),cycle_journeys as
(
select station_id,
end_date
from `bigquery-public-data.london_bicycles.cycle_hire`
)
结论
希望通过阅读本文,您现在已经了解了常见的表表达式,以及如何使用它们来真正提高您的 SQL 写作。
cte 是我个人日常使用的工具,也是 SQL 工具箱中帮助可读性和可维护性的最佳工具之一。它们还使得编写 SQL 更加实用,因此是一种愉快的体验。
希望你同意:)
后续步骤
1.了解更多关于安科瑞斯数据,分析&人工智能
一个永远改变了我编写查询方式的技巧
利用通用表表达式来简化复杂查询的编写和故障排除
Jan Antonin Kolar 在 Unsplash 上拍摄的照片
什么是常见的表表达式
当编写复杂的查询时,为了可读性和调试,将它们分成更小的块通常是有用的。通用表表达式(cte)提供了这种能力,我发现它们是我的 SQL 工具箱中最有用的工具之一。
cte 实现起来非常简单。他们以一个简单的WITH
陈述开始,你要去的新 CTE 的名字SELECT
。他们是这样开始的:
WITH
cte_name AS (
SELECT
...
)
美妙之处在于,您可以将多个 cte 链接在一起,数量不限。让我们看看他们中的一些人会是什么样子。
WITH
cte_name AS (
SELECT
...
),
another_cte AS (
SELECT * FROM foo
JOIN cte_name ON cte_name.id = foo.id
)
SELECT * FROM another_cte
LIMIT 10
这很好地说明了这个概念。第一个 CTE 运行第一个查询并将其存储在名为cte_name
的内存中,第二个 CTE 将cte_name
表连接到第二个 CTE 中的foo
表。您可以以多种方式使用这种模式,但是它通过将复杂的查询分解成逻辑部分来简化构造。
**注意:**需要注意的一件小事是在第一个 CTE 分隔每张表之后,
在哪里。
最后,通过在生成的 CTE 上运行一个独立的SELECT
语句来完成这个过程。
当然,强大的功能是运行复杂得多的逻辑。每个 CTE 可以包含许多SELECT
语句、JOIN
语句、WHERE
子句等。为了可读性和可理解性,使用它们来组织您的查询。
**提示:**为了方便调试或构建您的查询,您可以通过简单地注释掉剩余的代码并在每个 cte 之后运行 select 来测试每个 cte。像这样。
WITH
cte_name AS (
SELECT
...
) --, Make sure to comment out the comma
SELECT * FROM cte_name
LIMIT 10
-- another_cte AS (
-- SELECT * FROM foo
-- JOIN cte_name ON cte_name.id = foo.id
-- )
-- SELECT * FROM another_cte
-- LIMIT 10
现实生活中的例子
我为在雪花中创建的视图编写了一个查询。如果没有 cte,这将会变得更加困难。
WITH DAILY as (
SELECT ID
FROM "LOGS_DAILY"),
MAP AS (
SELECT SOURCE_ID AS ID, ANY_VALUE(UUID) AS UUID
FROM "CONTACT_MAP"
WHERE SOURCE_ID_NAME = 'ID'
AND DT = (SELECT MAX(DT) FROM "CONTACT_MAP")
GROUP BY SOURCE_ID),
CONTACT AS (
SELECT CONTACT_UUID, SITE_UUID
FROM "CONTACT_MASTER"
WHERE DT = (SELECT MAX(DT) FROM "CONTACT_MASTER")),
ACCOUNT AS (
SELECT *
FROM "ACCOUNT"
WHERE SITE_STATUS = 'Active')
SELECT DISTINCT *
FROM DAILY
LEFT JOIN MAP ON MAP.ID = DAILY.ID
LEFT JOIN CONTACT ON CONTACT.CONTACT_UUID = MAP.CONTACT_UUID
LEFT JOIN ACCOUNT ON ACCOUNT.SITE_UUID = CONTACT.SITE_UUID
LIMIT 100
结论
公共表表达式(cte)是查询工具箱中的一个强大工具,它允许您获取复杂的、分层的 SELECT 语句,将它们分解成更易于管理的块,然后最终将它们组合在一起。如果你今天没有使用它们,试一试,我相信它们会成为你经常去的地方!
如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。一个月 5 美元,让你可以无限制地访问成千上万篇文章。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。
数据科学中的常用词
定义数据科学术语
莫里茨·金德勒在 Unsplash 上拍摄的照片
在浏览在线和中级数据科学的文章和教程时,我注意到大多数文章和教程更适合中级开发人员以及更高级的开发人员。即使有一些初学者友好的教程,也有一系列使用的术语,不是每个人都知道。因此,今天这篇文章的目标是回顾术语,为数据科学的广阔世界增加一些清晰度。
这不会是一个完全全面的列表。我们可以研究的术语太多了。但它会有一些重要的,只是不是所有的,因为信息量太大。但是如果有任何你认为应该包含的重要词汇,请随意在评论中添加。
数据科学
先解释一下我们在这里的全部原因是合适的。数据科学是对数据的分析,通常是大量的数据。目标是为这些信息提供意义,以解决问题或做出决策。它包括数据的实际研究、数据本身、可视化、预测、决策过程等等。
大数据
我将大数据包括在列表中的原因是,“大数据”听起来像任何大量的数据。那么大数据到底有多大?大数据是指任何大到无法存储在单台计算机上的数据。这意味着它对于 SQL 或 Excel 之类的东西来说也太大了。从数据中获取有意义的信息需要更多的努力,因为单个查询的处理速度很慢,可能需要数周时间。这就是为什么通常它对于 SQL 来说太大了。
但不仅仅是数据的大小。这也是数据生成的速度。大数据遵循摩尔定律,即计算能力每两年翻一番。
数据挖掘
面对如此庞大的数据,一定有办法从中获取有意义的信息。这就是数据挖掘的用武之地。数据挖掘是指在给定一组数据的情况下,确定变量及其结果之间的关系。通常,这是由机器大规模完成的。它还涉及数据的清理和组织。理想情况下,它可以用那些太大而无法排序和描述的数据来帮助决策。这样的任务包括回归和分类,我们稍后会讲到。
在寻找数据中的意义时,数据挖掘可以搜索频繁模式、相关性、聚类、关联或任何可以进行的预测分析。
数据仓库
数据仓库是数据的存储库,无论是当前数据还是历史数据。这是数据挖掘或决策支持发生的环境。这是一个可以快速分析数据的系统。
数据建模
当您进行预测和分析数据时,您需要某种方式来可视化这些数据。数据建模是以书面或文档格式将数据可视化。换句话说,您创建了一个基于数据的模型。这些模型有助于解释过程的结果。
数据可视化
数据建模讲的是创建模型。数据可视化符合并详细描述了该模型。例如,数据可视化可以是以条形图、饼图、直方图等形式查看数据。甚至基于用例的漫画也可以被认为是数据可视化。它包含所有形式的可视化数据。
数据治理
当您处理如此多的数据时,必须有一些规则来确保完整性和安全性。因此,数据治理是存在的。听起来,数据治理就是管理或治理数据。这包括规则、法规、政策,甚至是围绕数据设置的有助于以某种方式管理数据的操作。这些规则必须符合法律和公司政策。
数据治理的规则有助于保护数据,确保数据的完整性,甚至保持数据的相关性。
数据角力
快速整理大数据听起来是个好主意。然而,数据怎么能如此容易地通过预测和分类呢?如果制定了某种组织系统,您需要确保数据可以通过该系统进行处理。这就是你需要争论或控制你的数据的地方。简单地说,数据争论就是“驯服”或格式化原始数据。该过程有助于数据适应工作流,以便从中获取有意义的信息。
数据管道
上学期从“数据”开始。所以,在某些时候,你需要把数据从一个地方转移到另一个地方。例如,您可能将数据导入到一个数据库中,但是在另一个数据库中发现您需要它。传递数据的一系列函数甚至脚本被认为是数据管道。
样本与总体
这可能只是一个提醒,或者也许你已经知道这个。就像数学课一样。当您考虑数据的子集或整体数据的一小部分时,这被认为是一个样本。样本大小通常是预先确定的,以帮助总结剩余的数据,或者使用监督学习方法提供给机器。我们一会儿会简单讨论一下。
如果你在看整个数据集,也就是你拥有的每一条信息,你会看到整个人口。
算法
另一个更数学化的定义,但我们下学期会用到。算法是以处理数据为目标的可重复的指令步骤。就我们的目的而言,它指的是机器用来完成任务的步骤。
机器学习
机器学习是机器使用算法分析数据的过程,该算法有助于对数据的结果进行预测。但这不仅仅是关于预测。它还涉及到分类、归类、聚类或分组,或者至少获得对数据的更多理解。当然,这是一个非常简短的简化,但是如果你特别想阅读更多关于机器学习的内容,有许多文章专门解释机器学习。
监督学习
机器学习要使用算法,必须先挑选一种学习方法。我们要讲的第一个是监督学习。使用监督学习,您需要来自数据的样本集。此样本用于获得对类别或模式的相似性的总体理解,以预测结果。这种训练方法要求数据集在处理整个数据集之前了解数据的类型。
无监督学习
下一个学习方法是无监督学习。与监督学习不同,非监督学习不使用样本数据集。相反,它只是处理全部数据,并随着数据的发展了解更多信息。这使得学习方法更能适应数据中的新情况,因此当发现新数据时,它可以重新安排它的算法或过程。
强化学习
我们要复习的机器学习的最后一种学习方法是强化学习方法。如果你养过狗,你知道有两种方法可以教它辨别是非。积极的强化是在最后提供一些东西,比如给你的狗一个奖励。负强化不会给你带来好处。消极意味着拿走一些东西。在机器学习的情况下,这就像消除导致错误结果的条件。
如果你想更深入地了解监督学习、非监督学习和强化学习,我写了一篇文章,你可以看看。
非结构化数据
听起来,非结构化数据不适合预先确定的模型。取而代之的是任何可能难以分类的数据。
结构化数据
结构化数据与非结构化数据相反。它适合数据库模型或任何其他已预定义的数据模型。
分类
分类是监督学习中的一种方法。这是一种根据数据与其他数据点的相似程度对数据进行分类的方法。该学习方法比较共同的特征,以将这些数据点“分类”为彼此更相似。然后,该类别可以用于任何具有相似特征的新数据。
回归
另一个监督学习方法的例子是回归。此方法确定跟踪值如何影响数据集中其他字段的值。一个例子是房子的面积如何影响价格。这些变量通常是连续的,这意味着它们具有数学上的“较低”和“较高”值。在这个例子中,房屋的面积会增加或减少,相关的价格也会增加或减少。
集群
我们已经研究了监督学习类型,但是非监督学习类型呢?聚类是一种无监督的学习方法,将数据与其相似程度进行比较。如果相似,可以将它们分组。越相似,数据点就越接近。如果数据点不相似,它们将被放置在更远的地方。这非常适合新数据,但如果添加更多功能,也会增加复杂性。
关联
相关性指的是价值之间的相互关系,通常是同向或反向运动。这意味着,如果一个值增加,另一个值也增加正相关。一个例子是花在学习上的时间与考试成绩相关,或者直接与考试成绩相关。在负相关中,当一个值增加时,另一个值减少。例如,如果你决定和一群人平均分摊酒店费用,那么人数越多,房间费用就越低。
神经网络
松散地基于大脑中的神经连接,神经网络是一种机器学习方法,是一种分层但通过节点连接的系统。它接受输入,给出输出,并且有一个隐藏层,大部分决策都是在这个层中做出的。
深度学习
深度学习是一种使用神经网络的机器学习方法。它的目标是更接近人脑。它做出明智的决定,并试图从每一个决定中学习。尽管一开始它必须解决简单的问题或模式,但随着时间的推移,它会学到更多,并可以转向更复杂的问题。随着复杂性的增加,它也试图提高准确性。在人工智能方面(我们也会对其进行简要描述),深度学习用于语音识别、图像识别、翻译等等。
决策树
决策树是机器学习的一部分,它允许你可视化决策。根据所做的决定,从它的分支有不同的路径。通常,它们是分割数据的是或否结果。最终,当你向下钻取时,你将到达一片叶子,它代表了结果。然而,决策树往往会过度拟合数据,这意味着答案可能不总是最准确的。
反向传播
反向传播在总结中更难定义。在神经网络中,预测输出与实际输出进行比较。在反向传播中,如果误差较大,则更新偏差和权重,以最小化数据损失,并尝试提高准确度。
ETL
ETL 代表提取、转换、加载。它是数据仓库用来使原始数据可用的工具。它指的是从数据源中提取数据,将数据转换成模型,同时保证数据的质量,并将数据加载到适当的可视化格式中。这是数据科学的一个主要部分,因为 ETL 过程不仅用于机器学习和大数据,还用于商业。
网页抓取
Web 抓取是从网站的源代码中提取数据,然后您可以从该网站中收集或过滤您正在寻找的信息。通常,您必须编写代码来从网站上收集文本,然后您可以创建一个脚本来整理您需要的内容或简单地打印您找到的结果。
商业智能
商业智能(BI)是一种分析业务指标的描述性方法。尽管它与业务相关,但它仍然更具技术性。它包括生成报告或发现重要趋势。在描述数据时,使用数据可视化。
人工智能
我们会对此保持一点模糊。人工智能是在工作时使用机器学习来适应学习的机器。例如,聊天机器人被认为是人工智能,使用得越多,它们就学习得越多。但人工智能也可以用来解决问题或进行预测。这是一个包含各种机器类型的大领域,例如不可玩的视频游戏角色在老板打架时学习如何玩,甚至无人驾驶汽车。
增强现实
同样,这将有点模糊,但如果你想了解更多,可以有专门描述 AR 的文章。增强现实基本上是增强你生活的现实。我的意思是,你给你生活的世界添加了嵌入信息。比如我想造一个智能镜子。当我早上刷牙时,智能镜子会显示天气甚至新闻标题。AR 只需一瞥就能提供更多信息,从而改善日常生活。
结论
涵盖了很多术语。其中有几个是比较常见的流行语,还有几个不太常用。我试图涵盖至少几个重要的问题。希望您可以随时查看这个列表,并且希望这些定义有助于更容易地解释数据科学术语的含义。同样,这不是一个完整的列表。我可能错过了很多。但这至少是一个让你起步的好地方。如果你认为我错过了任何重要的术语,请在评论中随意添加。下次见,干杯!
用我的 每周简讯 免费阅读我的所有文章,谢谢!
想阅读介质上的所有文章?成为中等 成员 今天!
看看我最近的一些文章:
https://medium.com/codex/something-i-learned-this-week-entity-framework-is-picky-about-primary-keys-b5d7642c9ab7 https://python.plainenglish.io/making-python-read-my-emails-9e3b3a48887c https://medium.com/codex/a-simpler-introduction-to-oauth-3533e53a4589
参考资料:
https://www.analyticsvidhya.com/glossary-of-common-statistics-and-machine-learning-terms/ https://www.dataquest.io/blog/data-science-glossary/ https://www.springboard.com/blog/data-science/data-science-terms/ https://bernardmarr.com/data-science-terminology-26-key-definitions-everyone-should-understand/ https://www.analyticsinsight.net/introducing-the-concept-of-augmented-reality-ar-based-ground-zero-analytics-data-visualization-in-real-environments/
社区检测算法
入门
作者图片
你们很多人都熟悉网络,对吧?你可能会使用社交媒体网站,如脸书、Instagram、Twitter 等。他们是社交网络。你可能在和股票交易所打交道。你可能会买入新股票,卖出现有股票,等等。他们是网络。不仅在技术领域,而且在我们的日常社会生活中,我们处理许多网络。**社区是许多网络的属性,在这些网络中,一个特定的网络可以具有多个社区,使得一个社区内的节点密集连接。**多个社区中的节点可以重叠。想想你的脸书或 Instagram 账户,想想你每天和谁互动。你可能会和你的朋友、同事、家庭成员以及生活中其他一些重要的人频繁互动。他们在你的社交网络中形成了一个非常密集的社区。
米(meter 的缩写))格文和 M. E. J .纽曼是社区检测领域的两位著名研究者。在他们的一项研究中,他们利用社会网络和生物网络突出了社区结构-属性。根据他们的说法,网络节点在社区内紧密地连接在一起,而在社区之间松散地连接。
为什么要社区检测?
在分析不同的网络时,发现网络内部的社区可能很重要。社区检测技术有助于社交媒体算法发现具有共同兴趣的人,并使他们保持紧密联系。在机器学习中可以使用社区检测来检测具有相似属性的群体,并提取各种原因的群体。例如,这种技术可以用来发现社交网络或股票市场中的操纵集团。
社区检测与聚类
人们可以认为社区检测类似于聚类。聚类是一种机器学习技术,其中相似的数据点基于它们的属性被分组到相同的聚类中。尽管聚类可以应用于网络,但它是处理多种属性类型的无监督机器学习中的一个更广泛的领域。另一方面,社区检测是专门为网络分析定制的,网络分析依赖于被称为边的单属性类型。此外,聚类算法倾向于将单个外围节点与其所属的社区分开。然而,聚类和社区检测技术都可以应用于许多网络分析问题,并且可能根据域的不同而产生不同的利弊。
社区检测技术
社区检测方法可以大致分为两种类型;聚合法和分法。在凝聚法中,边被一条一条地添加到一个只包含节点的图中。边从较强的边添加到较弱的边。分裂方法与凝聚方法相反。在那里,边被从一个完整的图中一个接一个地移除。
在给定的网络中可以有任意数量的社区,并且它们可以具有不同的大小。这些特征使得社区的检测过程非常困难。然而,在社区检测领域提出了许多不同的技术。下面解释四种流行的社区检测算法。所有这些列出的算法都可以在 python cdlib 库中找到。
1.鲁汶社区检测
Louvain 社区检测算法最初于 2008 年提出,作为大型网络的快速社区展开方法。这种方法是基于模块化的**,它试图最大化社区中的实际边数和社区中的预期边数之间的差异。然而优化网络中的模块化是 NP-hard,因此必须使用启发式。Louvain 算法分为迭代重复两个阶段;**
- 节点的局部移动
- 网络的聚合
该算法从 N 个节点的加权网络开始。在第一阶段,该算法为网络的每个节点分配不同的社区。然后,对于每个节点,它考虑邻居,并通过从当前社区中删除特定节点并将其放入邻居的社区来评估模块化的收益。如果增益为正且最大化,节点将被放置在邻居的社区中。如果没有正增益,节点将保持在相同的社区中。对所有节点重复应用该过程,直到没有进一步的改进。当获得模块性的局部最大值时,Louvain 算法的第一阶段停止。在第二阶段,该算法建立一个新的网络,将第一阶段发现的社区视为节点。一旦第二阶段完成,该算法会将第一阶段重新应用于最终网络。重复这些步骤,直到网络没有变化,并获得最大的模块化。
Louvain 社区检测算法在此过程中发现社区的社区。这是非常受欢迎的,因为易于实施,也是算法的速度。然而,该算法的一个主要限制是主存储器中网络存储的使用。
下面给出了使用 python cdlib 库的 Louvain 社区检测算法的使用。
从 cdlib 导入算法
导入 networkx 为 nx
G = nx .空手道 _ 俱乐部 _ 图形()
coms = algorithms.louvain(G,weight='weight ',resolution=1。随机化=假)
2.惊喜社区检测
由于模块性的限制,一种基于经典概率的被称为惊奇的测量被引入来评估网络到社区的划分的质量。该算法几乎类似于 Louvain 社区检测算法,除了它使用惊喜而不是模块化。节点从一个社区移动到另一个社区,这样惊喜被贪婪地改善。这种方法考虑了链接位于社区内的概率。惊喜的使用在许多小 社区的限制下效果很好,模块化的使用在少数大社区的限制下效果很好。
下面给出了使用 python cdlib 库的惊奇社区检测算法的使用。
从 cdlib 导入算法
导入 networkx 为 nx
G = nx .空手道俱乐部图形()
coms =算法.惊喜社区(G)
3.莱顿社区检测
在后来的研究(2019)中,V.A. Traag 等人表明 Louvain 社区检测倾向于发现内部断开的社区(连接不良的社区)。在 Louvain 算法中,将充当社区中两个组件之间的桥梁的节点移动到新社区可能会断开旧社区。如果旧社区被进一步分裂,这就不是问题了。但根据 Traag 等人的说法,情况不会是这样的。旧社区中的其他节点由于它们的强连接而允许它保持为单个社区。另外,根据他们的说法, Louvain 倾向于发现每周都有联系的社区。因此,他们提出了更快的莱顿算法,该算法保证了社区之间的良好连接。
图片改编自[4]
除了在 Louvain 算法中使用的阶段之外, Leiden 还使用了一个阶段,该阶段试图改进发现的分区。莱顿算法的三个阶段是,
- 节点的局部移动
- 分区的细化
- 基于精细划分的网络聚合
在细化阶段,该算法试图从第一阶段提出的分区中识别出细化的分区。第一阶段提出的社区可能在第二阶段进一步分裂成多个分区。细化阶段不遵循贪婪方法,并且可以将节点与随机选择的社区合并,这增加了质量函数。这种随机性允许更广泛地发现分区空间。同样在第一阶段,莱顿对鲁汶采取了不同的方法。在对所有节点的第一次访问完成后,Leiden 不再访问网络中的所有节点,而是只访问那些其邻居已经改变的节点。
下面给出了使用 python cdlib 库的 Leiden 社区检测算法的使用。
从 cdlib 导入算法
导入 networkx 为 nx
G = nx .空手道 _ 俱乐部 _ 图形()
coms =算法.莱顿(G)
4.Walktrap 社区检测
Walktrap 是基于随机行走的另一种社区检测方法**,其中通过网络中的随机行走来测量顶点之间的距离。Walktrap 是一种有效的算法,在最坏的情况下,它的时间复杂度和空间复杂度都是 O(mn)。但在大多数现实场景中,walktrap 运行的时间复杂度为 O((n ) log n),空间复杂度为 O(n)。该算法的基本直觉是,图/网络上的随机行走倾向于陷入对应于社区的密集连接部分。Walktrap 使用随机行走的结果,以自底向上的方式合并独立的社区。可以使用任何可用的质量标准来评估分区的质量。它既可以是模块性的,如在鲁汶社区检测中,也可以是任何其他措施。**
下面给出了使用 python cdlib 库的 Walktrap 社区检测算法的用法。
从 cdlib 导入算法
导入 networkx 为 nx
G = nx .空手道俱乐部图形()
coms =算法. walktrap(G)
结论
社区发现非常适用于理解和评估大型复杂网络的结构。这种方法使用图或网络中的边的属性,因此比聚类方法更适合于网络分析。聚类算法倾向于将单个外围节点与其所属的社区分开。许多不同的算法已经被提出并实现用于网络社区检测。根据网络的性质和应用的问题领域,每种方法都有不同的优缺点。
参考
[1]格文,米歇尔&纽曼,马克。(2001).《社会和生物网络中的社区结构》,美国国家科学院院刊。99.7821–7826.
[2]布隆德尔,v .,纪尧姆,j .,兰比奥特,r .和列斐伏尔,e .,2008 年。大型网络中社区的快速展开。IOPscience。
[3] Traag,v .,Aldecoa,r .和 Delvenne,j .,2015。使用渐近惊奇检测社区。物理复习。
[4] V. A. Traag,L. Waltman 和 N. J. van Eck,“从卢万到莱顿:保证良好连接的社区”,Sci。Rep .,vol. 9,no. 1,PP . 1–12,2019,doi:10.1038/s 41598–019–41695-z .
[5]Pons,p .和 Latapy,m .,n.d .使用随机行走的大型网络中的计算社区。
香港 280 万工人的通勤模式,可视化
就地点而言,起点-终点矩阵告诉我们就业供应的什么趋势?
(图片由作者提供)
TL;速度三角形定位法(dead reckoning)
香港有固定工作地点的工人超过 280 万人。想象一下,从他们的家到工作地点的整体旅行模式是什么样的?工作地点和工人的居住地点揭示了香港新市镇的职住失衡问题。
从家到工作场所
这里有一个 O-D 矩阵,显示了 2016 年按居住和工作地点分组的工人数量。每个单元格代表在那个行中生活的工人和在那个列中工作的工人数量。比方说,左上角的数字48647表示有 48647 名工人在中西区居住和工作。旁边的 12,938 表示有 12,938 名工人居住在中西区,而在湾仔工作。另一方面,下面的 19,244 表示有 19,244 名工人在湾仔居住,而在中西区工作。****
O-D 矩阵(作者图片)
人口普查中用于划分工人居住和工作地点的界限也如下所示。
(图片由作者提供)
(图片由作者提供)
但这张表不能不带来一些快速的见解。人们不得不手动查找并逐一比较这些数字。我们如何做得更好?
从表格到热图
下图称为热图。纵轴列出了工人居住的地区,横轴列出了按地区分类的工作地点。图中每个方格表示在该行中生活的工人和在该列中工作的工人数量。正方形的颜色越深,越多的工人属于那个生活/工作地点组。****
(图片由作者提供)
换句话说,这个图表和上面的 O-D 矩阵表没什么不同,除了 1。单元格现在用渐变的颜色方案和 2。数字被去掉了。
但是为什么要涂上颜色呢?因为我们对颜色比一些数字更敏感。更重要的是,趋势用渐变配色方案更容易看出来。可以有多种方式来解释这个图表。我总结了三个主要趋势,并列在下面。
趋势一:大部分工人在他们居住的同一地区工作
(图片由作者提供)
你可以看到的一个主要趋势是热图的对角线颜色最深。这意味着大部分工人在同一个地区生活和工作。住在中西区的人都在附近工作。屯门居民大多在屯门新市镇工作。这是意料之中的事——如果可能的话,工人们会在住处附近找工作,以尽量减少通勤时间。
西贡区和离岛是两个例外。在西贡,大部分居民都在观塘工作。由于将军澳区属于西贡区,我们可以预计大部分“在西贡居住,在观塘工作”的工人会居住在将军澳新市镇(而非西贡市及其他乡郊地区)。在离岛方面,由于机场被列为新界的其他地区,所有在东涌的航空公司的地面客舱均属于该网格。机场是近 80,000 人的工作场所(当然是在 COVID 之前)。
趋势二:工作仍然在核心城区
(图片由作者提供)
工作地点属于香港岛和九龙(图表的左边),一般来说比属于新界的要暗得多。颜色越深意味着工人越多,我们知道大部分工作仍然位于香港岛和九龙。
趋势三:新界→市区流量远大于市区→新界流量
(图片由作者提供)
这在某种程度上是趋势二的“延伸”趋势。随着更多的工作位于城市核心区,工人更容易在那里找到工作。因此,相当大比例的新市镇人口在核心市区工作,使得热图的左下角(居住在新界并在香港岛或九龙工作的人口)相当暗。
另一方面,居住在核心城区的人不太可能在新城镇工作。很难想象那 30 个离群索居的人在天水围新市镇工作,却住在南区。
这就是“职住失衡”/职住错配现象,这个问题从上世纪 80 年代就存在了。新城镇最初的发展方式是让居住在新城镇的居民也在那里工作。从屯门新市镇的总纲发展蓝图来看,屯门河的东面是住宅区,西面则是工业楼宇。这个轻工业被认为是居民就业的主要来源。
然而,经济结构的变化使得就业机会集中在维多利亚港两岸。数以百万计的新城居民需要早起,从他们的家到中央商务区需要一个小时的路程。
有兴趣了解更多吗?
我创建了一个网页(用 shiny 开发),允许用户使用本文中使用的 O-D 矩阵数据创建特定于他们感兴趣的领域的自定义图表。该网页如下所示。
https://kenneth-12.shinyapps.io/place-of-work-od/
如果可能的话,我还打算写一篇关于网页的补充说明。
【3 月 31 日更新:补充说明有 此处】
(图片由作者提供)
(图片由作者提供)
【 1 注意,不包括无固定工作场所或在家工作的劳动者。
Bins 方法和卷积神经网络在疟疾检测中的对比分析
基于 CNN 和图像处理的疟原虫分步检测
这是我的第一个媒体博客。希望你能像我写这篇文章一样开心
照片由егоркамелев在 Unsplash 上拍摄
目录:
- 介绍
- 动机
- 确定的挑战
- 问题定义
- 先决条件
- 演示
- 关于数据集的信息
- 系统的工作流程
- 带有实现细节的算法视图
- 图像使用者界面
- 绩效评估参数
- 结果
- 结论
- 未来范围
- 参考
1.介绍
alaria 仍然是全球卫生系统的一个重大负担,由于缺乏设备和医疗专业知识,它是许多发展中国家的主要死亡原因。因此,专业技术被证明是解决这一问题的关键。机器学习(ML)是人工智能的一个子集,它处理并帮助在大型数据集中找到模式。医疗保健领域的机器学习最近成为头条新闻。机器学习、预测分析和健康信息学的结合为改善医疗保健流程提供了机会,这有助于改善患者的结果。机器学习方法在基于图像的分析和诊断中是成功的。机器学习可以通过算法过程提高治疗方案和医疗保健结果的准确性。
2.动机
我们首先要明白这个问题在现实世界中有多重要。疟疾在世界上的一些地方是一种真正的地方病,这意味着这种疾病在该地区是常见的。全球每年约有 32 亿人面临疟疾风险。世界卫生组织(世卫组织)发布了关于疟疾的重要事实,你可以在这里查看https://www.who.int/features/factfiles/malaria/en/。延误治疗可能会导致几个并发症,甚至在某些情况下死亡。因此,疟疾的早期测试和检测对于拯救生命是必要的。这给了我们快速有效地诊断疟疾的动力。
3.确定的挑战
- 对于疟疾诊断,RDT 和显微镜诊断是两种广泛使用的方法。
- RDT 是一种有效的工具,可在 15 分钟内提供结果。它不需要任何训练有素的专业人员在场。然而,根据世卫组织的说法,RDT 有一些缺点,如与光学显微镜相比成本更高,并且容易受到热和湿度的损害。
- 显微镜诊断系统没有这些缺点,但它需要受过训练的显微镜专家在场。
4。问题定义
该系统的目标是通过使用 ML 和图像处理自动化疟疾检测过程来解决现有系统中的挑战和问题。
这里我们将应用两个众所周知的技术:
1 .Bins 算法
2。卷积神经网络
这些技术的结果将为我们提供一个具体的证据,证明机器学习和人工智能在疟疾检测方面的潜力。
5.先决条件
这篇文章假设读者熟悉 Python 库、数据结构、Tkinter、图像处理、线性代数、概率、统计、随机森林算法、SVM、卷积神经网络等。
6.这是一个应用程序的短片
来源:https://www.youtube.com/watch?v=pE8fv9BBQ2Q
请参考我的 GitHub 库这里的代码。
7.关于数据集的信息
在我们深入构建应用程序之前,让我们简单地看一下数据集。有许多数据集可用于疟疾检测。但为了这个项目的目的,我使用了由“美国国立卫生研究院”提供的数据集,其中包括 27558 个 RGB 细胞图像。png 格式,你可以从这里下载。
图 1:来自数据集的样本图像
数据集包含两个文件夹:分别带有训练和测试图像的训练文件夹和测试文件夹。此外,还有 2 个文件夹——带有疟疾感染细胞图像的寄生文件夹和带有正常细胞图像的未感染文件夹。
图 2:疟疾数据集
这些图像分为以下两部分:
- 寄生- 13779 图像
- 未感染- 13779 个图像
因为我们有一个平均分布的图像,所以我们不必处理不平衡数据的问题,它有更少的机会偏向某个特定的类。
8.系统的工作流程
图 3:系统的工作流程
- 输入的 RGB 单元图像首先被处理以从图像中去除噪声
- 然后对预处理后的图像进行分割,提取感兴趣区域,得到分割后的图像
- 特征提取阶段的输入是分割图像,输出是特征向量
- 下一阶段是分类阶段,其中输入将是特征向量,输出是寄生和非寄生的分类标签。
9.带有实现细节的算法视图
方法 1:使用箱柜方法
在这种方法中,我们将使用图像处理技术和最大似然分类算法。步骤如下:
步骤 1:图像预处理
- 在原始图像上训练模型可能会导致较差的分类性能。
- 预处理的主要目的是清洁图像
- 它确保图像中的信息易于访问。
*kernel = np.ones((9,9),np.uint8)
clean = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)*
图 4:预处理的图像
步骤 2:图像分割
执行分割过程以从图像中获得感兴趣区域(ROI)。以下技术用于分段:
- Otsu 分割
它用于执行自动图像阈值处理。它返回一个单一的强度阈值,将像素分为两类-背景和前景。自动全局阈值算法通常具有以下步骤:
步骤 1:处理输入图像
步骤 2:获取图像直方图(像素分布)
步骤 3:计算阈值
步骤 4:将图像中饱和度大于的区域替换为白色,反之则替换为黑色。
图 5:大津的门槛
2。分水岭分割
- 它将图像分割成几个汇水区或区域。
- 任何灰度图像都可以解释为 3D 拓扑表面。
- 图像可以被分割成概念上雨水会流入同一湖泊区域。
- 所以我们识别图像中的各种局部最小值(像素强度低)。从局部最小值淹没景观,并防止不同最小值的水合并。
- 这导致将图像分割成集水盆地和分水岭线。
图 6:分水岭分割图像
步骤 3:特征提取
这个阶段的输入将是分割的图像,输出将是特征向量。这里我们将提取以下特征:
- 统计特征
- 颜色特征
- 纹理特征
提取统计特征(均值,标准差。偏差等。)使用颜色矩:
均值等统计特征为我们提供了数据点的平均值,标准差提供了关于均值周围数据分布的信息,而偏度值为我们提供了分布不对称的度量。以下是提取统计特征的步骤:
步骤 1:读取图像文件
第二步:求平均值
第三步:找出标准偏差
步骤 4:找出偏斜度值
步骤 6:最后将平均值、标准偏差和偏斜度值存储在 1D 数组中,并对数据库中的每幅图像重复步骤 1-4。
使用面元法提取颜色特征:
- 在面元方法中,我们形成面元,使得图像的颜色细节将被适当地分离
- 使用二进制方法,我们着重于使用图像直方图来提取图像特征,并试图减少特征向量的大小。
以下是使用箱方法提取颜色特征的步骤:
步骤 1:将 RGB 细胞图像分成 3 个平面- R,G 和 B 平面。
图 7:分割的图像
步骤 2:获得每个平面的直方图。
图 8:3 个平面的直方图
步骤 3:通过计算重心(CG)将 R、G 和 B 直方图分成两部分。
第四步:处理每个像素 Pi (ri,gi,bi)。将它的 r、g 和 b 值与三个平面的相应 CG 值进行比较,并且基于它所在的相应直方图的划分,给每个像素分配一个标志(或者“0”或者“1”)。例如- Pi (1,1,0)-为像素 Pi- is 分配的标志(110-5 号箱)。这导致为每个像素(000 到 111)生成 8-Bin 地址。
步骤 5:箱中像素的计数:所有图像像素将根据其 r、g、b 强度被分成 8 个箱。
图 9:样品细胞结合值
该过程提取图像的所有颜色内容,并将每个细胞图像表示为仅 8 个分量的面元特征向量。
使用灰度共生矩阵提取纹理特征:
- 灰度共生矩阵用于提取图像的二阶统计纹理特征
- 它也被称为灰度级空间相关性矩阵
以下是使用灰度共生矩阵提取纹理特征的步骤:
步骤 1:计算共生矩阵
图 10:图像及其共生矩阵
步骤 2:一旦计算出这个共生矩阵,我们必须使这个共生矩阵对称。
图 11:计算对称 GLCM
步骤 3:这个对称的 GLCM 矩阵必须被归一化
图 12:归一化的 GLCM
共生矩阵捕获纹理的属性,如熵、相关性、对比度、方差、角二阶矩等。
第四步:分类
这个阶段的输入将是特征向量,输出是分类标签。通过应用像随机森林算法和 SVM 这样的最大似然算法对图像进行分类。
支持向量机:
图 13: SVM
- 在该算法中,我们首先在 n 维空间中绘制出数据项,其中 n 是特征的数量。
- 有许多超平面将正点和负点分开,因此将正点和负点分开尽可能远的超平面将是优选的。这个超平面称为边缘最大化超平面。
- 如果我们平行于超平面并接触一个正的点,我们得到正的超平面,如果我们平行于超平面并接触一个负的点,我们得到负的超平面。
- 正超平面或负超平面经过的点称为支持向量。
- 正超平面和负超平面之间的距离称为边缘。
- 这个算法找到了一个使边界最大化的超平面。
图 14: SVM(凸包)
- 另一种方法是分别为正负点构建一个凸包。
- 找出连接这些船体的最短的线。
- 把这条线一分为二。
- 平分该直线的平面是超平面。
随机森林算法:
图 15:随机森林
- 决策树是一个嵌套的 if-else 分类器。
- 在每一个非叶节点,我们做决定,在每一个叶节点,我们有类标签。
- 对应于每一个决策,我们都有一个超平面。
- 决策树是一组轴平行的超平面,划分你的整个区域。
- 随机森林算法由许多单独的决策树组成,这些决策树作为一个组进行操作。每棵树都给出了一个类别预测。
- 森林中的树木数量越多,预测就越稳健,准确度就越高。
- 得票最多的班级就是我们模型的预测。
输出
图 16:系统的输出
分类阶段的输出将是这样的图像,对于疟疾感染细胞图像,其分类标签为寄生,而对于正常细胞图像,其分类标签为未感染。
方法 2:使用 CNN
- CNN 帮助寻找图像中的模式。它是一个设计用于处理图像等数据阵列的模型。
- 这里,数据集中的输入图像具有不同的维度。由于 CNN 不能训练不同大小的图像,所以第一步将是调整所有图像的大小。
- 为此,我们将绘制直方图,计算两个维度(宽度、高度)的平均值,并调整所有图像的大小。
图 17:数据集中图像的连接图
- 从连接图上,我们可以看到从 50 x 60 到 200 x 200 的各种尺寸。计算两个维度的平均值,我们将图像形状设置为(130,130)。因此,我们将处理大小为 130 x 130 x 3= 50700 个数据点的图像。
- 我们不能一次输入所有的内容,相反,我们必须为我们的图像选择批次。
- 我们希望模型能够克服的另一个想法是,它应该足够健壮,能够处理与以前看到的图像完全不同的图像。当我们可以做到这一点,是通过操纵和执行对我们的图像的变换,如旋转,调整大小和缩放。
- 我们只有不到 30,000 张图像,现在我们可以使用随机变换并加倍数据集。因此,我们将通过 keras 使用数据增强。它变换图像,如翻转,移动,缩放等。其中(图像)发生变化,而易(目标类)保持不变。
*image_gen = ImageDataGenerator(rotation_range=20,
width_shift_range=0.10,
height_shift_range=0.10,
rescale=1/255,
shear_range=0.1,
zoom_range=0.1,
horizontal_flip=**True**,
fill_mode='nearest'
)plt.imshow(image_gen.random_transform(para_img))*
构建我们的第一个基线模型
图 18:为我们的基线模型声明模型架构
- 顺序模型在这里适用于简单的层堆栈。
- 在卷积层,我们将把过滤器矩阵放在图像矩阵的顶部,并计算单元格的值。然后我们将做 1 的跨步跳跃。这将提取边缘及其位置等特征。下面是一个示例,显示了一个卷积层的操作,其内核大小为 3,跨距为 1。
图 19:卷积层
- 如果有时滤波器不能完全适合输入图像,我们也可以使用填充。所以我们用零(零填充)填充图片,这样它就合适了。操作如下所示:
图 20:填充
- 对每个字段(单元格)应用 Relu 激活函数。整流线性单元(ReLU)是一个线性函数,如果它是正的,它将输出输入,否则它将输出零。
ReLU(x)=max(0,x)
- 接下来是最大池,它选择最大元素,从而提取最显著的特征。内核大小为 2、跨距为 1 的 maxpool 层操作示例如下:
图 21:最大池化
这样我们就可以堆叠任意数量的卷积运算。
图 22: CNN
- 最后是全连接层。全连接层的输入将是最大池层的输出,并被展平,转换为 1D 数组,然后馈入全连接层。
- 脱落层用于减少过拟合。
- 损失函数评估了该模型对我们的疟疾数据集的建模效果。由于我们的问题是二进制类别分类(2 个类别-寄生和非寄生),我们将使用二进制交叉熵作为我们的损失函数,它将每个预测概率与实际类别输出(0 或 1)进行比较。
- 现在,为了训练模型,我们必须选择批量大小,这里批量大小是一次 16 个图像。它首先接受一批数据集,然后对其执行反向传播,然后更新我们模型中的权重。对于指定的历元数(在我们的例子中是 20),重复该过程。
图 23:用于预测的代码
- predict_generator 函数为来自数据生成器的输入样本生成预测。它返回概率的 Numpy 数组。
- 然后,我们可以设置阈值,如如果概率> 0.5,则检测到寄生虫,否则未检测到。用这种方法我们可以做出预测。
*my_image = image.load_img(para_cell,target_size=image_shape) *#input*
my_image = image.img_to_array(my_image)
my_image = np.expand_dims(my_image, axis=0)*
- 对于单个图像,加载图像并将其传递给模型。
- 使用 img_to_array 将特定的图像对象转换为数组。
- model.predict 函数将为输入样本生成输出预测。
*s=model.predict(my_image)
**if**(s==[[1.]]):
self.label.configure(text="non parasitic")
**else**:
self.label.configure(text="parasitic")*
图 24:系统的输出
10.图形用户界面
疟疾检测系统的图形用户界面是使用 Tkinter 库创建的,为此我们首先必须安装 Tkinter 库:
*sudo apt-get install python3-tk*
现在导入所需的库,并开始创建窗口,我们将在其中添加我们的元素,如标签,按钮等,以获得一个良好的 GUI。
*from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from PIL import Image, ImageTk
import tkinter.font as font
class Root(Tk):
def __init__(self):
super(Root, self).__init__()
self.title(“Python Tkinter Dialog Widget”)
self.minsize(640, 400)
self.labelFrame = ttk.LabelFrame(self, text = “Open File”)
self.labelFrame.grid(column = 0, row = 1, padx = 20, pady = 20)
self.button()
self.button1()
def button(self):
self.button = ttk.Button(self.labelFrame, text = “Browse A File”,command = self.fileDialog)
self.button.grid(column = 1, row = 1)
def fileDialog(self):
self.filename = filedialog.askopenfilename(initialdir = “/PROJECT/test samples”, title = “Select A File”, filetype =
((“png files”,”*.png”),(“all files”,”*.*”)) )
self.label = ttk.Label(self.labelFrame, text = “”)
self.label.grid(column = 1, row = 2)
self.label.configure(text = self.filename)
img = Image.open(self.filename)
photo = ImageTk.PhotoImage(img)self.label2 = Label(image=photo)
self.label2.image = photo
self.label2.grid(column=1, row=5)
def button1(self):
self.button = ttk.Button(self.labelFrame, text = “Submit”, command = self.get_prediction)
self.button.grid(column = 1, row = 20)
def get_prediction(self):
s=model.predict(my_image)
if(s==[[1.]]):
#self.label.configure(text=”Non Parasitic”)
text = Label(self, text=”Non Parasitic”, font=(“Helvetica”, 17))
text.place(x=50,y=200)
else:
#self.label.configure(text=”Parasitic”)
text = Label(self, text=”Parasitic”, font=(“Helvetica”, 17))
text.place(x=70,y=200)
root = Root()
root.mainloop()*
图 25:系统的图形用户界面
11。性能评估参数
使用准确度、精确度、召回率和 F1 分数等参数来评估性能。
图 26:CNN 的分类报告和混淆矩阵
12.结果
表 CNN 和 Bins 方法获得的结果
- 在分类过程中,SVM 与箱柜方法配合得相当好。
- 上表还显示了具有箱的随机森林是该方法的最佳分类器,因为它达到了 96.3%的准确度,这比其他方法好得多。
- 而且,CNN 的准确率最低,为 94%;然而,由于其缺点,它具有相对更高的精确度。虽然 CNN 模型取得了很好的准确性,但也有一些缺点。CNN 需要更多的时间来训练模型。此外,加载模型和执行必要的操作会更加昂贵。
13.结论
- 到目前为止,我们得到的最好的模型在未知数据上达到了 96.3%的准确率
- 在 CNN 方法中使用数据扩充减少了过度拟合的机会和假阴性的数量。
- 在 CNN 中使用退出被证明是好的,因为它帮助我们减少了模型的过度拟合。
- bin 技术被证明是一种有效的技术,它处理实际的彩色图像内容并以紧凑的特征形式表示它们
- 随机森林的 Bins 方法比 CNN 产生更好的结果
- 由于特征向量是 8 分量的,Bins 方法也在很大程度上降低了复杂度。
- 在比较了所有方法的性能后,可以得出结论,bin 方法在特征提取中起着重要的作用
- 疟疾分类系统被证明比传统技术更快。该系统界面友好,易于使用。
14.未来范围
- 作为未来工作的范围,我们可以准备一个融合特征向量,该向量将箱的特征、颜色矩和 GLCM 参数组合在一个特征数据集中,并且还可以使用递归特征消除(RFE)进行特征选择。
- 我也希望试验更多的机器学习算法,如 KNN,AdaBoost 等。
15.参考
[1] Olugboja,和 Z. Wang,“使用不同的机器学习分类器进行疟原虫检测”,2017 年机器学习和控制论国际会议(ICMLC),宁波,2017 年,第 246–250 页。
[2] H. B. Kekre,Kavita Sonawane,“使用基于直方图的像素计数和强度平均值的图像检索”(第 74–79 页,(IJCSIS)《国际计算机科学与信息安全杂志》,第 10 卷,第 1 期,2012 年
[3] K. Silamut,N.H. Phu,C. Whitty 等人,“用于检测疟疾的图像分析和机器学习”,Am J Pathol,155 (2017),第 395-410 页
[4] Vinayak K. Bairagi 和 Kshipra C. Charpe,“用于疟原虫生命阶段分类的纹理特征比较”,国际生物医学成像杂志,2016 年第 1 卷,文章 ID 7214156,9 页,2016 年。
[5] X. Liu,T. Kawanishi,X. Wu 和 K. Kashino,“高性能 CNN 分类器和高效单词推理的场景文本识别”,2016 IEEE 声学、语音和信号处理国际会议(ICASSP),上海,2016,第 1322–1326 页,doi:10.1109/ICA ssp . 2016 . 471891 .
[6] Zulpe,Nitish & Pawar,V. (2012 年)。用于脑肿瘤分类的灰度共生矩阵纹理特征。IJ 犯罪现场调查员。9.354–359
希望你喜欢阅读这篇博客,感谢你的阅读!
关注我获取更多关于数据科学不同现实世界问题的文章!
你也可以在LinkedIn上和我联系。**
比较多个频率分布以从数据集中提取有价值的信息(Stat-06)
如何比较多个频率分布并获得重要信息
频率分布是一种图形或表格表示,显示给定间隔内的观察次数。条形图、饼图和直方图用于可视化单个变量的频率分布。如果我们需要一次比较多个频率分布表。简单的条形图、饼图等。不适用于比较多个频率表。别担心,可能有其他方法可以做到这一点。本文将涵盖完成我们工作的所有技术。你所需要的就是把这篇文章读完。
路线图………
- 为什么我们需要比较频率分布?
- 分组条形图
- 核密度估计图
- 带状图
- 箱线图
我们的旅程从这里开始
熟悉数据集
在本文中,我们使用的是[**wnba.csv**](https://dsserver-prod-resources-1.s3.amazonaws.com/283/wnba.csv?versionId=IRtAhA_HXkTG.u7ly_AYF8_iv61yieDK)
数据集。全国女子篮球协会是美国的职业篮球联盟。它目前由 12 个小组组成。在我们的数据集中,我们有 2016-2017 赛季所有比赛的统计数据。数据集有 143 行和 32 列。数据集概述如下。
频率分布和可视化的先验知识
为了更好地理解比较频率分布的必要性,您需要先了解频率分布及其可视化。如果你对此没有任何想法,你可以阅读我以前关于频率分布和可视化的文章。
为什么我们需要比较频率分布?
为了更好地解释,我们将使用wnba.csv
数据集,以便您可以通过真实世界的示例进行学习。
首先,我们尝试将experience
列表示为Exper_ordianl
列,变量按顺序度量。在下表中,我们试图根据以下标记惯例来描述玩家的经验水平:
作者照片
现在,我们非常想知道‘Pos’(Player position)
变量在experience
水平上的分布。例如,我们希望在有经验、非常有经验和经验丰富的球员的位置之间进行比较。
我们使用了下面的代码来根据上面的标签惯例转换玩家的体验。
输出:
现在我们尝试根据经验水平对数据集进行分段。然后,我们为数据集的每个片段生成频率分布。最后,我们尝试对频率分布进行对比分析。
输出:
这个例子表明,比较多个变量的分布有点棘手。有时,您会在非技术人员面前展示数据。对于非技术观众来说,理解上述场景是如此困难。图形表示是向非技术观众展示我们发现的最佳方式。在本文中,我们将讨论三种图表来比较不同变量的频率。下面的图表将帮助我们完成工作—
(一)分组条形图
(二)核密度图
(三)方框图
分组条形图
分组条形图(也称为簇状条形图、多序列条形图)扩展了条形图,绘制两个或更多分类变量的数值,而不是一个。条形图根据一个分类变量的级别位置进行分组,颜色表示每组中的二级分类级别。
作者照片
- 如何生成分组条形图
来自[seaborn](https://seaborn.pydata.org/index.html)
模块的[*seaborn.countplot()*](https://seaborn.pydata.org/generated/seaborn.countplot.html)
函数,用于生成分组条形图。为了生成分组条形图,我们将使用以下参数
(i) *x*
—以字符串形式指定 x 轴上所需列的名称。
(ii) *hue*
—以字符串形式指定要为其生成条形图的列的名称。
(iii) *data*
—指定存储数据集的变量的名称。
*import seaborn as sns* sns.countplot(x = ‘Exper_ordianl’, hue = ‘Pos’, data = wnba)
输出:
这里,我们用Exper_ordianl
列来表示 x 轴。这里,我们为Pos
列生成条形图。我们将数据存储在一个名为wnba
的变量中。
- 如何自定义分组条形图
[seaborn](https://seaborn.pydata.org/index.html)
模块中的[seaborn.countplot()](https://seaborn.pydata.org/generated/seaborn.countplot.html)
https://seaborn.pydata.org/generated/seaborn.countplot.html函数有多个参数。通过改变这些参数,我们可以根据自己的需求定制图形。我们也可以按升序设置x-axis
值的顺序,并使用hue_order
参数更改色调顺序。
import seaborn as snssns.countplot(x = ‘Exper_ordianl’, hue = ‘Pos’, data = wnba,
order = [‘Rookie’, ‘Little experience’, ‘Experienced’, ‘Very experienced’, ‘Veteran’],hue_order = [‘C’, ‘F’, ‘F/C’, ‘G’, ‘G/F’])
输出:
作者照片
轮到你稍微思考一下,找到问题的答案。
锻炼问题: 年纪大的球员打球少吗?用提到的数据集和上面的知识来回答问题。
核密度估计图
核密度估计(KDE)图是一种可视化数据集中观察值分布的方法,类似于直方图。KDE 使用一维或多维的连续概率密度曲线来表示数据。
作者照片
上面的每个平滑直方图被称为核密度估计图,或简称为核密度图。与直方图不同,核密度图在 y 轴上显示密度,而不是频率。
- 为什么使用核密度估计图?
核密度估计图(KDE 图)主要用于比较直方图。现在我们试着理解 KDE 情节的必要性。
比较两个直方图最简单的方法是将一个直方图叠加在另一个直方图之上。我们可以通过熊猫可视化方法任务来做到这一点。
import matplotlib.pyplot as pltwnba[wnba.Age >= 27][‘MIN’].plot.hist(histtype = ‘step’, label = ‘Old’, legend = True)wnba[wnba.Age < 27][‘MIN’].plot.hist(histtype = ‘step’, label = ‘Young’, legend = True)
输出:
在上面,我们想要比较两个不同的场景。一个给 27 岁以上的球员,另一个给 27 岁以下的球员。我们把两个直方图一个接一个地画出来,这样我们就可以很容易地比较它们。我们可以很容易地比较两个直方图。如果直方图的数量多于两个。比较这些直方图容易吗?KDE 情节的必要性就是针对这种情况的。
- 如何生成 KDE 图?
[Series.plot.kde()](https://seaborn.pydata.org/generated/seaborn.kdeplot.html#:~:text=A%20kernel%20density%20estimate%20(KDE,further%20in%20the%20user%20guide.)
方法用于生成 kde 图。
wnba[wnba.Age >= 27][‘MIN’].plot.kde(label = ‘Old’, legend = True)wnba[wnba.Age < 27][‘MIN’].plot.kde(label = ‘Young’, legend = True)
输出:
这里,我们使用 KDE 图执行相同的过程。
带状图
带状图是一种用于总结单变量数据集的图形数据分析技术。带状图包括:
横轴=响应变量的值;
纵轴=所有值都设置为 1。
事实上,带状图实际上是散点图。
作者照片
当其中一个变量是名义变量或顺序变量时,散点图通常采用一系列窄条的形式。
- 如何生成带状图
[sns.stripplot()](https://seaborn.pydata.org/generated/seaborn.stripplot.html)
功能用于生成带状图。
sns.stripplot(x = ‘Pos’, y = ‘Height’, data = wnba)
输出:
我们把Pos
变量放在 x 轴上,高度变量放在 y 轴上。我们可以在图表中看到,大多数矮个子球员踢守门员位置,大多数高个子球员踢中后卫位置。你也可以试试权重变量。窄条的数量与名义变量或序数变量中唯一值的数量相同。
箱线图
箱线图是一种基于五个数字汇总显示数据分布的标准化方法(“最小值”、“第一个四分位数”(Q1)、中值、第三个四分位数(第三季度)和“最大值”)。
作者照片
上图显示了箱线图。箱线图是一种图表,可以很好地显示数据中的值是如何分布的。
中位数(Q2 或第 50 百分位): 表示数据集的中间值。
第一个四分位数(Q1 或第 25 个百分位数): 它代表数据集的最小值和中值之间的中间值。
第三个四分位数(Q3 或第 75 个百分位数): 表示数据集最高值和中值之间的中间值。
四分位数范围(IQR): 表示第 25 和第 75 百分位之间的值
触须: 触须是延伸到最高和最低观测值的 方框外的两条线 。在上图中,左边的一条线和右边的其他线代表胡须。
离群值: 位于盒状图的触须之外的数据点。在上图中,绿点代表异常值。
- 如何生成盒状图
[sns.boxplot()](https://seaborn.pydata.org/generated/seaborn.boxplot.html)
功能用于生成箱线图。
sns.boxplot(x = ‘Pos’, y = ‘Height’, data = wnba)
输出:
使用sns.boxplot()
,生成一系列箱线图,检查作为球员位置函数的球员身高分布。将Pos
变量放在 x 轴上,重量变量放在 y 轴上。
离群点表示—
- 如果点大于上四分位数 1.5 倍于上四分位数和下四分位数之差(该差也称为四分位数间距)。
- 如果点数低于下四分位数 1.5 倍于上四分位数与下四分位数之差(该差也称为四分位数间距)。
我们也可以使用whis
参数将系数从 1.5 更改为自定义值。
sns.boxplot(x = ‘Pos’, y = ‘Height’, data = wnba, whis=4)
输出:
克里斯蒂娜·安妮·科斯特洛在 Unsplash 上拍摄的照片
结论
在本文中,我们试图学习如何使用图表来比较频率分布。分组条形图用于比较名义变量或顺序变量的频率分布。如果变量是以区间或比率尺度测量的,我们可以使用核密度图和带状图或盒状图来更好地理解。
如果你是数据科学爱好者,请与我保持联系。我很快会带着另一篇有趣的文章回来。
关于数据科学统计学的完整系列文章
- 少即是多;采样的‘艺术’(Stat-01)
- 熟悉数据科学最重要的武器~变量(Stat-02)
- 要增加数据分析能力,你必须知道频率分布(Stat-03)
- 通过可视化频率分布找到数据集的模式(Stat-04)
- 比较多个频率分布,从数据集中提取有价值的信息(Stat-05)
- 通过简短的讨论消除你对均值的误解(Stat-06)
- 通过规范化提高您的数据科学模型效率(Stat-07)
- 数据科学的基本概率概念(Stat-08)
- 从朴素贝叶斯定理到朴素贝叶斯分类器的路线图(Stat-09)
- 数据科学爱好者关于假设检验需要知道的一切(Stat-10)
- 用 ANOVA (Stat-11) 进行多组间统计比较
- 用卡方检验比较分类变量的相关性(Stat-12)
在 10 个表格游戏竞赛中比较流行的 AutoML 框架
你是否曾经在晚上忙于应付不同的机器学习算法和软件包,切换超参数值和尝试不同的预处理方法?建立一个好的机器学习管道需要大量的试错工作。因此,这非常耗时,而且会让人精疲力尽。
自动机器学习(AutoML)框架旨在提供帮助。
开始
2016 年开始做 AutoML 系统。我是一名博士生,从事不同领域的许多 ML 项目:高能物理、医学和生物信息学。我需要优雅的软件,我可以用它来交换我的代码,进行大量的调整和验证循环。这就是我如何开始着手我称之为 MLJAR 的项目。名字来源于 ML + JAR,但这里的 JAR 有第二层意思(我当时在波兰华沙读书):
JAR 是对华沙外来居民的非正式称呼。这个词来源于许多学生和工人在周末拜访父母时用来从父母家拿食物的罐子。
你可以在这篇文章中阅读更多关于 JARs 的内容。它有相当负面的意义。我想我会用它来命名我的新项目。我会让项目成功,以表明对新人不好是一个错误。
开源 AutoML
MLJAR AutoML 引擎是开源的,其代码可从 GitHub 获得:https://github.com/mljar/mljar-supervised
MLJAR AutoML 使用表格数据集。
常见的机器学习任务:二进制、多类分类和回归。(图片由作者妻子提供)
MLJAR AutoML 最大的优点是它的透明性。这里面没有黑箱魔法。您可以查看 AutoML 培训的每个步骤的详细信息。所有关于已训练模型的信息都保存在硬盘中(自动保存功能始终开启)。每个型号都有自己的README.md
文件。因此你可以很容易地检查细节(例如在 GitHub、VS Code 或 Jupyter Notebook 中)。下面是来自模型培训的降价README.md
报告示例:
来自模型训练的范例报告。
自动模式:解释、竞争、执行
过去,AutoML 仅用于超参数优化。这是 ML 管道中可以自动化的最简单的事情。今天,AutoML 可以服务于许多目的。MLJAR AutoML 可以在三种模式下工作:
- 它很快。只需要几分钟。应该用来让你熟悉一个新的数据集。它做探索性的数据分析。它只训练几个具有默认超参数的模型(没有调优!).对于每一个模型,都有完整的解释:特性重要性、SHAP 依赖图、决策图、学习曲线等等。
Compete
—高度调谐的 ML 流水线。应该用于构建高精度模型。培训可能需要很长时间,很容易超过 4 个小时(取决于数据集)。它使用先进的特征工程、集成和堆叠。Perform
—用于训练生产就绪的 ML 模型的模式。训练速度和最终准确性之间的平衡。
MLJAR AutoML 以三种模式工作:解释、竞争、执行。(图片由作者妻子提供)
训练模式的选择与参数设置一样简单:
# initialization of AutoML with Compete mode
# mode can be: Explain, Compete, Performautoml = AutoML(mode="Compete")
特征工程
特征工程对于机器学习流水线的性能非常重要。MLJAR AutoML 提供了先进的特征工程方法。它可以用 K-Means 或黄金特征搜索生成新特征。还有一个特征选择程序,可以与任何机器学习算法一起工作。
黄金特征生成
用于 MLJAR AutoML 的黄金特征生成。(图片由作者提供)
k-均值特征生成
基于 K-均值的特征生成。(图片由作者提供)
任何 ML 算法的特征选择
特征选择程序。(图片由作者提供)
比较 Kaggle 上的 AutoML 框架
让我们在最具挑战性的数据集上检查 AutoML 性能。 Kaggle 平台以现实生活中的数据问题举办数据科学竞赛。我使用了 Kaggle 的 10 个表格数据集,它们代表了各种机器学习任务:
- 二元分类
- 多类分类
- 回归
比较中使用的数据集描述。
数据集的选择与文章中的相同: N. Erickson,et al .:autoglon-Tabular:Robust and Accurate AutoML for Structured Data(除了房价 Adv. Regression,因为文章中没有来自私人排行榜的结果,竞争仍在进行中)。
评估了以下框架:
- AutoWeka
- 自动 Sklearn
- TPOT
- H2O
- 谷歌云自动表
- 自动增长
- MLJAR
结果
这些框架在 m5.24xlarge EC2 机器(96CPU,384 GB RAM)上进行训练。培训时间设定为 4 小时。(GCP 表除外,它使用自己的机器类型)
下面给出的最终结果是私人排行榜中的百分比排名(由 Kaggle 内部评估)。**数值越高越好。**ka ggle 竞赛中的第一名将获得与1.0
相同的百分位排名。竞赛中解决方案的最后一名将给予0
值。除 MLJAR 外,AutoMLs 的结果来自 AutoGluon paper。
表格数据中 10 个 Kaggle 竞赛的百分位数排名。最佳解决方案用黄色标出。
表格数据中 10 个 Kaggle 竞赛的百分位数排名。数值越高越好。
你可以看到一些 AutoML 框架跳到了竞争的前 10%(没有任何人工帮助)!没有任何人工干预的 MLJAR AutoML 在 10 场 Kaggle 比赛中有 5 次进入前 25%。更重要的是,它有 3 次排在前 10%。
摘要
现在 AutoML 是一个多用途的工具。可用于:
- 软件工程师需要在应用程序中应用 ML,但不知道如何调整 ML 算法的细节
- 公民数据科学家在低代码环境中构建 ML 管道
- 数据科学家和工程师加快工作速度
我希望许多人能从我的 AutoML 系统中受益。我为此付出了很多努力。我对您对 MLJAR AutoML 以及整个 AutoML 的意见和反馈非常感兴趣。
你可以在 GitHub 找到 MLJAR AutoML:https://github.com/mljar/mljar-supervised
https://github.com/mljar/mljar-supervised
基于颗粒比较 PySpark 数据帧
基于粒度比较 Pyspark 数据帧并使用数据样本生成报告的简单方法
米利安·耶西耶在 Unsplash 上拍摄的照片
比较两个数据集并生成准确而有意义的见解是大数据世界中一项常见而重要的任务。通过在 Pyspark 中运行并行作业,我们可以基于 粒度.) 高效地比较庞大的数据集,并生成高效的报告来查明每一列级别的差异。
要求:
我们从 Salesforce 获取了大量数据集。该数据集有 600 多列和大约 2000 万行。必须对开发和验证数据集进行比较,以生成一个报告,该报告可以基于 粒度.) 查明列级别的差异。
下面是与包含粒度列的数据样本一起生成的洞察,可用于进一步查询和分析。
- 重复记录。
- 缺失记录。
- 捕获开发和验证数据集中的列值之间的差异。
方法:
我们可以使用数据框的 subtract 方法减去两个数据框,这将生成不匹配的记录,但是很难确定 600 列中的哪一列实际上发生了变化以及实际值有所不同。下面是解决这个问题的一个简单方法。
从这里开始,我将验证数据集称为源数据框架(src_df),将开发数据集称为目标数据框架(tar_df)。由于相同的两个数据帧被一次又一次地用于不同的分析查询,因此我们可以将这两个数据帧保存在内存中,以便进行更快的分析。
在下面的方法中,假设两个数据框具有相同的模式,即两个数据框具有相同的列数、相同的列名以及所有列的相同数据类型。
识别重复和缺失的谷物记录:
为了识别重复记录,我们可以使用 Pyspark 函数通过查询编写一个小组。grainDuplicateCheck()函数也是如此。
为了识别丢失的颗粒,我们可以从两个数据帧中选择颗粒列并直接减去它们。
需要注意的是,我们需要执行 src_df - tar_df 来获取有效的缺失颗粒,还需要执行 tar_df - src_df 来获取无效的额外记录颗粒。
比较列值:
现在,我们必须比较数据帧之间的列值,并逐列生成报告,同时找到特定粒度的预期值和无效值。
由于我们已经确定了丢失的记录,现在我们将连接粒度列上的两个数据框,并比较在两个数据框中具有匹配粒度的所有记录的列值。
值得注意的是
- 颗粒列可以有空值,我们必须执行空安全连接,否则,那些记录不会被连接,记录将被跳过。为此,我使用了 eqNullSafe() 内置的 Pyspark 函数。
- 包含双精度值(如 amount)的列不会完全匹配,因为不同的计算可能会生成小数精度略有差异的值。因此,对于这些类型的列,我们必须减去这些值,并标记那些差异≥阈值的记录。
在下面的 compareDf()函数中,使用连接的数据框,我们选择要验证的粒度和特定列,并对它们进行比较。
通过运行并行作业比较列值:
上述函数的局限性在于,我们是按顺序逐列比较两个数据帧,遍历数据帧的每一列。
现在让我们来看一些统计数据。有 600 多列和大约 2000 万行,比较每列需要 15 秒。对于所有 600 列,大约需要 150 分钟(约 2.5 小时)。
列比较任务彼此独立,因此我们可以并行化它们。如果我们平行比较 8 根柱子,那么所用的时间大约是 19 分钟。这是一个巨大的差异,因为它快了 8 倍。
在下面的函数 compareDfParallel()中,我使用多处理内置 python 包创建了一个指定大小的线程池。使用*parallel _ thread _ count =*8,将并行比较 8 列。compareDFColumn()是将由每个线程为特定列执行的实际比较函数。
必须根据集群中节点的容量来选择并行线程数。我们可以使用 spark-submit 中指定的驱动核心数作为并行线程数。
假设 pyspark_utils.py 文件中存在上述所有函数,下面是示例数据的用法示例。
compareDfParallel()的输出将具有前缀为 _src 的列,用于引用源数据帧的列值,以及前缀为 _tar 的列,用于引用目标数据帧的列值。
在上面的示例中, billing_amount_src 是 1100,这是源数据帧中 billing_amount 的值,而 billing_amount_tar 是 1000,这是目标数据帧中 billing_amount 的值。
脚本的输出可以通过管道传输到一个文件,以获得一个合并的报告。可以修改该函数来生成 HTML 报告,而不是文本文件报告。
这是基于粒度有效比较 Pyspark 数据帧并使用数据样本生成报告的简单方法之一。
数据仓库快乐!
在 Excel 上比较 AWS understand 和 Azure ML
不同的机器学习算法表现如何相似?
在我的模块“开发有意义的指标”中,一位同学(Nicole)使用Azure Machine Learning on Excel对 4000 多条与辉瑞相关的推文进行情感分析,以确定大多数人对疫苗的感受。
她发现推特上的情绪分布相当均匀,“负面”比“正面”略有增加。这意味着 Twitter 用户的意见相对复杂,对辉瑞疫苗的正面和负面意见都很健康。这可以从她发布的下图中看出。
图片来自作者的同学妮可
巧合的是,我之前也使用过AWS understand对一堆 Reddit 评论进行情感分析。事实上,我在这里记录了那个过程。这实际上让我问, “哪个人工智能模型更准确?”作为一名计算机专业的学生,我对技术世界有一些信心,我最初的假设是,这两者将会有一些共同的趋势。换句话说,一般来说,一个人工智能的情感等级较低的推文对另一个人工智能来说也相对较低,反之亦然。
技术部分
我回答这个问题的第一步是使用 AWS understand 运行我自己的情感分析。对于那些没有看过我以前的帖子的人,我使用了一个现有的 AWS 教育帐户,在那里我有免费的信用来使用 AWS 提供的服务。写的第一个函数是从我以前的项目复制的,它连接到 AWS 服务器,并发送一段文本进行情感分析。然后处理并保存响应。这个功能实际上是由 AWS 文档指导的。
## script for sentiment analysisdef get_sentiment(text):
comprehend = boto3.client(service_name='comprehend', region_name='us-east-1')
response = comprehend.detect_sentiment(Text=text, LanguageCode='en')
response = dict(response) result = {}
result["sentiment"] = response["Sentiment"]
result["positive"] = response["SentimentScore"]["Positive"]
result["negative"] = response["SentimentScore"]["Negative"]
result["neutral"] = response["SentimentScore"]["Neutral"]
result["mixed"] = response["SentimentScore"]["Mixed"]
result["sentiment_score"] = (result["positive"] - result["negative"]) / 2 return result
其次,编写代码来处理 CSV 文件中的数据,并将结果写入另一个 CSV 文件。
## get sentiment resultstry:
result = get_sentiment(body)except botocore.exceptions.ClientError as e:
print(e)
result = 'no-go'
while (result != "ok" and result != 'skip'):
print("type 'ok' or 'skip' to continue")
result = input()
if (result == 'skip'):
skipped += 1
print("error occurred with sentiment analysis, skipping row")
continue
result = get_sentiment(body)except:
skipped += 1
print("error occurred with sentiment analysis, skipping row")
continue ## write to csvrow = ['0','1','2','3','4','5','6',result["sentiment"], result["positive"], result["negative"], result["neutral"], result["mixed"], result["sentiment_score"]]
print(row)
writer.writerow(row)
print("scanned and accessed data index", count)
在这个过程中,我遇到的一个巨大的绊脚石是“不干净数据”的存在。我认为 CSV 数据集是直接从 Twitter 上刮下来的。然而,这意味着存在大量无用字符,以及 AWS 和 Python 都无法正确处理的字符。从下面的截图可以看出,有很多垃圾字符影响了 Python 脚本。
突出显示导致错误的不良字符(图片来自作者)
经过一番搜索,我学会了如何从这个链接中检查合法字符,并实现了一个功能来帮助在发送数据进行处理之前清理数据。
帮助清理数据的代码(图片来自作者)
最后,代码工作了,成功地分析了所有的推文。我将结果复制并粘贴到一个合并的 CSV 文件中,然后开始分析结果。
可视化位
总之,我制作了两张我认为有意义的图。首先,我重新制作了 Nicole 制作的图表,但现在是基于 AWS Comprehend 的结果。下面是两张并排的图表。
比较 Azure 和 AWS(图片来自作者)
这里有许多不同之处可以挑选出来。首先,AWS 产生了一种复杂的情绪,而 Azure 没有。AWS 产生的混合和中性的区别在于,中性的情绪是指评论中没有正面和负面的词语,而混合的情绪是指评论中混合了正面和负面的评论。这是一个纯粹的算法问题,因为这就是人工智能的设计方式。虽然它可能会产生一些关于算法创建得有多好的见解,但我不认为它值得考虑,因为“混合”分数相对来说是最小的。
第二,也是更明显的一点,与 Azure 相比,AWS 的中性情绪明显较高。这也是由于算法的问题。我的理论是,Excel 情绪分析仅仅是一个插件,准确性可能没有 AWS 高。AWS understand 运行在亚马逊服务器上,亚马逊服务器有能力处理和管理更大、更复杂的机器学习算法。
对比几条评论也能看出这一点。例如,从下面的图片中,有一些评论,我认为 AWS 比 Azure 的评分更准确。第 11 行的评论只是一个标签,被 Azure 标记为负面(单元格 F11),但(我相信)被 AWS 更好地归类为中性,置信度为 99%(单元格 K11)。
样本推文及其各自的情感得分(图片来自作者)
我创建的第二个图表试图证明/反驳我之前的假设,即两个人工智能之间存在某种协议。我首先计算了情绪得分,将其与-1 到 1 的量表进行比较,其中-1 分表示负面情绪,0 分表示中性情绪,1 分表示正面情绪。然后,我在散点图上绘制了 AWS 情绪得分和 Azure 情绪得分,并希望观察到某种趋势。图表如下所示。
AWS 情绪得分与 Azure 情绪得分(图片来自作者)
正如所见,两者之间绝对没有任何趋势,这让我很惊讶,因为这完全违背了我的假设。事实上,情节的巨大分散表明两个人工智能在大多数推文中意见不一。
考虑到这一点,这可能是因为自然语言处理在技术世界中仍然是一个非常新的事物,即使是最好的情感分析机器学习算法也无法提供 95%的准确率。最终,这种行为可能是意料之中的,毕竟不是太不寻常。
结论
想一想这是如何有意义的,我相信这样的信息对于人工智能爱好者来说是有趣和独特的,他们可以比较各种技术并寻求改进这些技术。这个发现的第一部分是承认和意识到我们在人工智能游戏中仍然远远落后于完美。不是说这个领域很容易,但是大多数外行人会相信情感分析确实是最准确的算法之一。这个简单的数据图表表明我们还有很长的路要走。
然而,我希望这将有助于激励更多的人(和我自己)意识到人工智能有如此大的创新和改进空间。我们必须展望未来,改进这项技术,使其能够发挥最大潜力。在一个技术进步如此迅速的现代世界,我怀疑另一个像这样的图表看起来与我现在拥有的截然不同只是时间问题。
巴西和葡萄牙宪法的数据驱动比较
从巴西和葡萄牙宪法的文本挖掘看它们的异同
在 Unsplash 上由 Dmitrij Paskevic 拍照
这是对当前巴西和葡萄牙宪法的一些特征的快速且主要是视觉上的比较,旨在利用一些文本挖掘概念并查看宪法的一些相似性和差异。
您将在这里看到:
- 文本挖掘
- 最常用的词
- 单词云
- TF-IDF
方法
对于这个分析,我使用了 R 中的文本挖掘概念和包,简单来说步骤如下:
- 引入宪法文本
- 去除停用词,也就是像冠词和介词这样的对文本没有太大价值的词
- 标记化,即将短语缩减为单词
之后,我们会得到一个类似这样的数据帧:
用于分析的符号化数据框架-按作者分类的图像
现在我们准备为每个文档构建一些基本的情节。
1988 年巴西宪法
在一个经历了多年军事独裁、领导层更迭并因最近的直接选举运动“Diretas Já”而有所改观的国家,显然需要一部不那么专制的宪法,一部至少在纸面上将权力还给人民的宪法。
这正是 1988 年巴西宪法试图实现的目标。尽管被批评为冗长和过度分析,目前的联邦宪法是在 1988 年颁布的,它无疑是该国民主历史上的一个里程碑。
删除停用词后,我们剩下:
总字数 : 25042
总独特字数 : 4700
%
巴西宪法中最常见的 10 个词是:
巴西宪法中最常见的词汇——作者图片
一些快速注释:
- “联邦”、“国家”和“工会”代表联邦政府等级中的上层职位。
- “estados”和“municipios”代表政府的另外两个分支,即州和市。
- 有趣的是,葡萄牙语的价值观和概念,如社会、公正、资源和人,直到第 12 位才出现。
在 worcloud2 软件包的帮助下,我们在巴西国旗的美丽色彩下构建了一个单词云,并带有巴西地图的轮廓:
巴西宪法的文字云—作者图片
正如在任何词云中一样,越大的词越常见。这种情况下的颜色是随机的。
1976 年葡萄牙宪法
在 1976 年的一场左派政变之后,葡萄牙人民也需要一部新宪法,而之前的那部宪法已经有 40 多年的历史了。虽然葡萄牙在政府和政治方面几乎总是更稳定,但 1976 年的文件进行了几项创新,如议会、总理、政党和选举的明确定义,以及独立的司法系统。
就文本而言,葡萄牙宪法也相当罗嗦,尽管不太像当前的巴西宪法:
总字数 : 15111
总绝字 : 3107
%的独特词 : 20.56
葡萄牙现行宪法中最常见的 10 个词是:
葡萄牙宪法中最常见的词语—作者图片
注意事项:
- 可以理解的是,“雷”是最常见的词,
- 换句话说,至少与巴西宪法相比,他们更关心共同利益。“assembleia”、“direito/direitos”、“cidados”等词非常突出,位列前 10。
看看葡萄牙宪法中的常用词“云”这个词,不按比例。
葡萄牙宪法的文字云—作者图片
TF-IDF 和独立条款
TF-IDF 是一种旨在显示一个单词在文档集合中的重要性的度量,在这种情况下,是两种结构的组合。它清楚地显示了某个文档独有的单词,或者在某个文档中比该组中的其他单词出现频率更高的单词。更多关于 TF-IDF 的信息,请点击这里。
下图显示了在一个文档中出现频率较高,而在另一个文档中出现频率较低或根本不出现的单词。左边的术语,如“联邦”、“国会”和“补充者”只在巴西宪法中使用,而“议会”、“自治”和“经济”只在葡萄牙文件中出现。
每部宪法的专有词汇—作者图片
Obs:有些词,如“económico”和“sector ”,在巴西和葡萄牙的写法不同,因此有必要进行后续研究,以使这两种葡萄牙语“正常化”。这可能很快就会成为一项独立的研究,敬请关注。
最后的想法
- 文本挖掘是一项分析文本的伟大技术,它使我们能够比较像国家宪法这样重要的文件。
- 巴西宪法比葡萄牙宪法更加冗长。
- 至少就大多数常用词而言,葡萄牙《宪法》更侧重于公共利益,并且有许多与葡萄牙语相对应的词,如“社会”、“权利”和“公民”。
- “联邦”、“国会"和"补充者"等词几乎只在巴西宪法中使用,而"议会”、"自治"和"经济"只在葡萄牙宪法中使用。
这篇文章中使用的全部代码和文本,请到我的 GitHub 页面查看我最近的一些作品这里。
比较云 MLOps 平台,来自前 AWS SageMaker PM
对于 ML 平台工具,两大云今天如何比较?重要的特征是什么?
在组织中应用机器学习(ML)的公司有一系列工具放在一起作为他们的 ML 平台。当组织扩展时,每个 ML 工程师、ML 架构师和 CIO 团队都应该重新评估他们的架构,尤其是在大牌云供应商发布年度公告的时候。作为前亚马逊 SageMaker 高级产品经理,我将概述当前 GCP Vertex 与 SageMaker 的情况,以及我对不同工具的看法。
MLOps 很少是单一的整体系统。相反,它由许多较小的工具阶段组成,我称之为“MLOps 八大阶段”:数据收集、数据处理、特征工程、数据标记、模型设计、模型训练、模型优化以及模型部署和监控。
图片作者。开源基金会的“大八步”,社会公益技术。
ML 平台方法介绍
大型云供应商已经构建了“端到端”的 ML 平台。使用 Amazon SageMaker 的数据科学家可以从他们的数据仓库中提取数据,创建算法模型代码,并部署到生产中,而无需离开工具套件。虽然云供应商是人们谈论最多的入门产品,但也有一些初创公司旨在应对来自 Dataiku、Datarobot、C3.ai 和 H20.ai 的相同挑战。
端到端的替代方案是成为“同类最佳”工具,这要求供应商专注于成为某个领域的思想领袖产品。虽然 GCP 顶点和塞尔顿都有模型服务能力,但一个熟练的 ML 工程师会发现塞尔顿的产品具有许多客户用例所需的功能,如推理图和原生 Kubernetes 部署。端到端 ML 平台通常需要 15-36 个月才能赶上功能对等,但产品将在此之前推出,以创造思想领先地位并获得产品反馈。
在这一点上,与主要的云供应商平台有大量的重叠。事实上,谷歌 I/O 2021 的许多新公告都是 SageMaker 在 re:Invent 2020 上推出的功能。谷歌的战略与其他云供应商的区别在于,他们有许多源自谷歌大脑的开源 MLOps 项目,GCP 现在以托管服务的形式提供这些项目。Vertex AI pipelines 是一个托管的 Kubeflow Pipelines 服务,Vertex 元数据 API 几乎与 MLMD 相同,Vertex 也有用于托管 tensorboard 训练工件的 API。这种构建产品的方法意味着客户具有可移植性,相同的工具在开源中可供他们在 AWS 或内部运行。
亚马逊 SageMaker 与 GCP Vertex 的比较
每隔几个月,我都会花时间重新评估我的 18 个月 MLOps 行业路线图。这个路线图是我认为应该覆盖 90%的企业培训和服务模型所需的关键特性。它是由我在与 ML 工程师、CIO 和其他项目经理的交谈中得到的产品功能需求的金块,以及我在工作经验中观察到的东西组合而成的。我将这些特性放在一个列表中,并描述当前的 ML 产品。
GCP Vertex 与 SageMaker 在常见要求和同类最佳特性方面的比较。
ML 平台有两类特性。需要“牌桌赌注”和“同类最佳”功能。
同类最佳产品以粗体突出显示。新加入 ML 的团队使用 table stakes 特性就足够了,因此他们可以快速部署模型。GCP 顶点和亚马逊 SageMaker 都已经投入了足够的资金来清除这个最小的障碍。
然而,仅仅这些特征还不足以在生产中形成大规模的模型。同类最佳的特性,例如推理图,对于组织中已经有许多模型的 ML 团队来说非常重要。八大巨头的每个阶段都有自己的一套最佳特性需要考虑。
云平台仍在不断完善其同类最佳的功能,即使它们现在已经有了一个公共产品。虽然 GCP 更诚实,称 Vertex Metadata 和其他同类最佳工具为预 GA,但它们真的不能大规模使用(还不能)。我在 Twitter 上强调过顶点元数据(实验跟踪)没有 Python SDK 。SageMaker 也有类似的不足。一个例子是在他们的特征库中,该特征库缺少实体模型来组织保存的特征。需要更深入的测试来发现仍然存在的技术债务。
需要高级特性的企业团队应该准备好构建他们自己的解决方案来解决他们的特定用例,或者编写“粘合”代码来替代(开源工具或其他供应商)。这种粘合剂是我听到投资者称之为 ML orchestration 的一个概念,它是将出现的一类新的 MLOps 工具。
外卖食品
进行这样的评估显示了首席信息官/工程副总裁为解决当前挑战而需要构建的东西与他们根本没有 MLOps 平台团队时可以购买的东西之间的差距。需求列表总是在增长,足够的特性列表不仅仅来自端到端的 ML 平台。对于拥有高级用户的更复杂的企业来说,这一练习清楚地表明了他们的 ML 平台在传统构建与购买中的未来。对于初创公司和较小的公司来说,拥有 MLOps 平台工程并不划算,而使用 SageMaker 或 Vertex 将符合要求。
离开 AWS 后,我创办了一个名为 Social Good Tech 的非营利性 MLOps 软件基金会,以解决工具的互操作性问题。我计划写更多关于如何通过架构 ML 平台来思考的文章。请继续关注我对 MLOps 行业的分析和市场中的争论。
咖啡渣与 LBP 和 K-means 聚类的比较
咖啡数据科学
对旧数据的回顾
在使用 LBP+K-means 聚类来帮助理解 Rok 和小生境 grinder之间的差异之后,我决定看看以前使用这种技术的一些数据,看看我能看到什么。技术使用线性二进制地图(LBP)作为 K-means 聚类的特征,以帮助根据粒子在图像中的外观进行分组。
研磨机比较
之前我看了一下几台研磨机的几个研磨设置。对于相同的研磨机和不同的设置,差异更小并不令人惊讶。这是一种比较研磨机的奇怪方式。有一点似乎很突出,那就是 Rok 3(设定 3)似乎与大多数其他版本都不相似。我怀疑这是一个测量误差。哈里欧 3 号也一样。
这些颗粒可以被更细的颗粒(<400um in diameter) and coarser particles (>直径 400 微米)分解。两者显示了相似的模式,但是对于 Rok 3,没有太多的差异。可能是原始数据中有太多的细颗粒聚集在一起或其他问题。
研磨设置
我查看了生态位上的多个研磨设置,以帮助理解它们之间的线性关系。通常,重点是在研磨设置拨号,但由于这可以大大不同于其他变量,我想扩大搜索。
总的来说,大多数彼此接近的研磨物彼此相似,这是有道理的。
当我们按颗粒大小分解时,一些有趣的模式出现了。首先,对于 100um 的颗粒,在 S30 附近存在明显的分裂,其中 S0 至 S25 更相似,然后 S30 至 S50 最相似。
对于 500um 的颗粒,出现了另一种趋势,其中 S20 至 S50 非常相似,但彼此之间不一定相似。对于 400um,从 S0 到 S40 非常相似,但它们与 S45 和 S50 非常不同。
再次研磨
作为研究重新研磨咖啡豆的效果的努力的一部分,我比较了一些较粗的研磨设置和一些较细的。其他设置看起来并不像它们应该的那样相似,但是当比较时,不清楚为什么。
100um 是特别有趣的,因为底部的 5 个研磨设置都非常相似,甚至与再研磨非常相似,但它们都不同于较粗的研磨,如 S50。
通过粒子和研磨设置的比较,重新研磨咖啡并没有使它从一开始就非常类似于只是在那个设置下研磨(在这种情况下是 S15 再研磨改变了基本的颗粒形状。
辛辣研磨
在研磨之前加热咖啡豆显示出分布的变化,但是这些结果显示出随着颗粒的变化,特别是对于 74C 对 51C 或 20C 的颗粒来说,变化要大得多。
潜入更深的细粒(<400um) and coarse (400um) particles, there are some interesting differences especially for 74C. The coarse particles from the 74C are very different from the rest.
The Source of Fines
I have 之前讨论过理论,细粒来自更脆的咖啡豆内部。因此,回顾这些数据,我们发现根据模式识别,来自粗磨 S50 的细粒与来自 S13 的细粒非常匹配。
将这些数据分成更细和更粗的数据,更细的数据(<400um) from S50 are what match so well with S13.
Looking closer at just the S13 and S50 <800um across multiple particle sizes shows that 100um is really where those fines get similar between the two.
I really enjoy applying pattern recognition to coffee because I think we’re in the infancy of the application of data and imaging techniques to coffee.
LBP and K-means are the more basic types of functions, and maybe something more complex like PCA or LDA would do a better job. I hope one day, these techniques can help with dialing in beans and distinguishing with more granularity, the quality of coffee grinders.
If you like, follow me on Twitter 和 YouTube ,我在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以在中关注我,在订阅。
我的进一步阅读:
比较咖啡质量分级员
咖啡数据科学
希望了解如何衡量 Q 评分的客观性
几个月前,我联系了新兴城市咖啡烘焙商。他们分享了他们的 Q 分数数据,我想他们可能有更多的数据让我看。他们友好地与我分享了 200 多种咖啡的 400 多个 Q 分。最有趣的是每杯咖啡有两个等级。所以我做了一些分析,试图了解他们的分数之间的相关性。
我假设评分者在评分时不会分享太多关于他们分数的信息。在 Q 分级中,目的是让不同的分级员对不同的咖啡进行相同的分级。所以这是一个有趣的测试来了解这个结果有多真实。
新兴城市数据
他们使用 Cropster 来记录和存储关于烤肉和他们个人等级的信息。一半的咖啡由迪安和克里斯或者迪安和萨凡纳分级,但是只有一批咖啡由这三个人分级。有些咖啡有多个条目,但不是很多。
作者的所有图片
q 分数
Q 分数是在咖啡杯过程中记录的 10 个因素的顶点。我从我对 SCA 杯协议的理解中总结了每个指标。他们定义了如何准备咖啡样品,如何品尝,以及如何评分。我相信网上有很多资源可以帮助你通过快速搜索了解如何拔火罐。
由于补丁中的缺陷豆,最终分数也可能会丢分,因为允许有多少缺陷是有标准的。
相似性度量
在模式识别中,特征向量用于比较两个项目,通常是两个信号或图像。计算向量之间的分数,以确定它们彼此之间有多相似或不相似。
为了计算两杯咖啡的相似性得分,使用均方根将每个子指标向量与所有其他向量进行比较:
然而,在下面的细目分类中,我将每个图表调整到 0%到 100%之间。100%不代表完全匹配,0%也不代表不匹配。它相对于每个图表中的数据,其中 100%是最大相似度(最相似),0%是最小相似度(最不相似)。
我们可以查看各个地区的得分差异。对克里斯来说,他在亚洲咖啡上的分数和其他人的分数相关性最小。否则,他们的大部分分数彼此具有高度的相似性,这表明 Q-分级训练做得很好并且是客观的,或者这表明通过他们一起给咖啡分级,他们已经将他们的分数调整为彼此同步。
我们可以把重点放在同一个地区的咖啡和分类上。萨凡纳和迪恩除了在南美豆上有最大的共同点,但除此之外,萨凡纳与迪恩的匹配度比克里斯与迪恩或萨凡纳的匹配度更高。
相互关系
相关性是衡量两个变量彼此相似程度的指标。高相关性并不意味着一个变量会引起另一个变量,而是当情况发生变化时,两个变量的涨跌幅度相同。我从一开始就假设一些分级变量会有很高的相关性,因为它们是从不同的时间点来看味道的。
就相关性而言,两者略有不同。
地区和评分者之间的相关性有一些奇怪的结果。理论上,你应该与自己最相关,但在这里似乎并不总是如此。然而,我认为相关性的微小变化在统计学上是显著的。
原始差异
我们可以查看原始差异,并将克里斯和萨凡纳与迪安的分数进行比较,因为迪安对几乎所有的咖啡进行了评级。
查看数据的另一种方式是所有子指标的平均差异,以查看原始数字中的差异。有两种方法可以查看:平均值和仅包含差异不为零的样本的平均值。
我们可以将这些分为地区差异,这是查看分数的另一种有趣方式。
Dean vs Chris 没有不适用的数据
这两个指标最终都告诉我们,两者之间没有太大的区别。
这是一个独特的数据集,因为对于多个评分者来说,相同的品尝会议的数据集并不多。事实上,我怀疑这是有史以来最大的数据集,只是因为 coffee 中使用的数据太新了。好消息是,即使子指标之间的差异加起来在最终得分上有一些差异,但这种差异并不是很大。任何子矩阵的差异也不存在。
这给了我们两个事情中的一个很高的信心:所有这三个 Q 级评分者都受过良好的训练来客观地评分,或者他们的得分通过生活在相似的地区、喝相似的咖啡和一起评分而标准化。我希望这有助于鼓励其他分级者分享他们的数据,以帮助研究 Q 分级作为咖啡客观衡量标准的有效性。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。
我的进一步阅读:
家庭烘焙咖啡的经济学
如何评价 Sweet Maria 的咖啡杯度量标准,以便更好地进行比较
比较 Python 中显示分类数据的不同方式
传统与不常见的方法以及何时使用它们
来自 Unsplash
虽然表示分类数据的最流行的方式是使用条形图,但还有一些其他的可视化类型适合于此目的。它们都有各自的优点和缺点,以及适用性的限制。
在本文中,我们将比较显示相同数据的图表:按区域划分的大陆。数据从维基百科获得,用 mln km2 表示,以避免不必要的精确。
import pandas as pd
dct = {'Oceania': 8.5, 'Europe': 10, 'Antarctica': 14.2, 'South America': 17.8,
'North America': 24.2, 'Africa': 30.4, 'Asia': 44.6}
continents = list(dct.keys())
populations = list(dct.values())
1.条形图
让我们从显示分类数据的最经典的方式开始:一个甚至不需要介绍的条形图。
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,4))
plt.barh(continents, populations, color='slateblue')
plt.title('Continents by area', fontsize=27)
plt.xlabel('Area, mln km2', fontsize=19)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.tick_params(left=False)
sns.despine(left=True)
plt.show()
作者图片
从上面的图表中,我们可以清楚地看到各大洲在数量和质量上的等级划分。难怪:酒吧地块几乎没有任何缺点。它们是多用途的、高度可定制的、视觉上引人注目的、易于解释的、广泛受众熟悉的,并且可以用任何 dataviz 库来创建。在生成它们时,我们唯一要记住的是遵循良好的实践:数据排序、选择合适的颜色、条方向、添加注释、标签、整理等。
2.茎图
stem 图非常类似于条形图,甚至比后者更有优势,因为它的特点是最大化的数据-墨水比率,看起来不那么杂乱。要创建 stem 图,我们只需要 matplotlib 库。对于水平茎图(具有水平基线和垂直茎的图),我们可以将vlines()
与plot()
结合使用,或者直接使用stem()
函数。在第一种情况下,vlines()
创建词干,plot()
创建结束点。对于垂直茎图(具有垂直基线和水平茎的图),我们不能再使用stem()
功能,而是使用hlines()
和plot()
的组合。
让我们为我们的数据创建一个垂直茎图:
plt.figure(figsize=(10,4))
plt.hlines(y=continents, xmin=0, xmax=populations, color='slateblue')
plt.plot(populations, continents, 'o', color='slateblue')
plt.title('Continents by area', fontsize=27)
plt.xlabel('Area, mln km2', fontsize=19)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.xlim(0, None)
plt.tick_params(left=False)
sns.despine(left=True)
plt.show()
作者图片
与第一个图表相比,我们只增加了一行代码,在水平茎图的情况下,如果直接使用stem()
函数,甚至没有必要。结果图显示了相同的信息,但看起来比传统的条形图更清晰、更优雅。当有许多类别需要可视化或者它们的值具有可比性时,这就变得特别有价值。
3.圆形分格统计图表
饼图或其版本圆环图(具有空核心部分的饼图)是另一种众所周知的可视化类型,广泛用于显示整体中单个组件的比例。它可以用许多 dataviz 库创建和轻松定制。尽管如此受欢迎,它也是最受批评的情节类型之一。其主要原因是:
- 饼图是基于角度而不是长度,这使得它更难被清楚地解释。
- 在有许多类别或者它们的比例相似的情况下(这是创建柱状图的理想选择),饼图实际上对于计算出比例的顺序或者甚至找到最大/最小值是没有用的。
让我们看看饼状图在我们的例子中是否适用:
plt.figure(figsize=(7,7))
plt.pie(populations, labels=continents, startangle=90, autopct='%1.0f%%',
textprops={'fontsize': 15})
plt.text(x=-1.15, y=1.5, s='Continents by area, in %', fontsize=27)
plt.show()
作者图片
由于我们的数据仅由 7 个类别组成,其值最初是有序的,并且彼此之间差异很大,还因为我们添加了每个大洲占总土地的百分比,所以生成的图表看起来信息量大,易于理解,并且不会遇到上述两个问题。
饼图相对于条形图和柱状图的一个不太明显的弱点是颜色丰富。另一种方法是用图案填充楔形,但在这两种情况下,都会导致较低的数据-油墨比率。然而,这是所有“多彩”情节的典型问题,我们很快就会看到。
另一件值得强调的事情是,这种类型的图表比前两种图表的功能更有限。事实上,它只能用于可视化整个中组件的比例,而对于条形和茎图,条形/茎不应构成整体。例如,我们可以按人口数量制作前 10 个国家的柱状图。为这些数据创建一个饼状图,在技术上是可能的,但会有一点错误,因为真实的整体,在这种情况下,包括更多的元素(所有其他国家)。
4.树形图
要创建一个树形图,我们必须安装并导入 squarify 库(pip install squarify
)。这种类型的图类似于饼图,因为它也显示整体中单个组件的比例。它不使用楔形,而是使用一组矩形,矩形的面积与相应类别的值成比例。这很重要,实际上也是一个优势:对区域的心理比较肯定比对角度的心理比较容易得多。此外,与饼图不同,当我们有很多类别要比较时,它仍然可以很好地工作。下面是树状图和饼状图共有的弱点和限制:
- 当类别的比例相似时,效果不好。
- 它没有轴,所以我们必须依赖于矩形的视觉比较,或者在每个矩形上添加值。
- 这意味着使用大量的颜色,这可能会使结果图看起来有点势不可挡。
- 树形图的组成部分应该构成整体。
此外,还有一个纯粹的树图特有的缺点:
- 定制这种可视化的方式相当有限,并且不总是用户友好的。例如,要调整标签文本属性(如字体颜色或大小),我们不能直接传入相应的参数,而只能通过
text_kwargs
字典。另外,在矩形之间添加间隙的pad
参数只能取值True
或False
,没有任何调整间隙宽度的可能性。
让我们来看看我们各大洲的树形图:
import squarify
import matplotlib
plt.figure(figsize=(12,7))
squarify.plot(sizes=populations, label=continents, value=populations,
color=[matplotlib.cm.Set2(i) for i in range(7)],
text_kwargs={'fontsize': 17})
plt.title('Continents by area, mln km2', fontsize=27)
plt.axis('off')
plt.show()
作者图片
我们的树形图看起来很吸引人,也很有洞察力,我们可以清楚地从最大到最小的各大洲跟踪矩形和值。同样,这部分是由于我们只有 7 个类别、各种各样的值和初始排序。或许,我们可以考虑用百分比而不是绝对值来表示这些值。
树形图唯一必要的参数是sizes
,所有其他参数(包括label
)都是可选的。
5.华夫饼图表
要创建华夫饼图表,我们需要一个基于 matplotlib 的 PyWaffle 库:pip install pywaffle
,然后导入 PyWaffle 和 matplotlib。这种类型的图类似于饼图和树形图,因为它也说明了整体中单个组件的比例,其优点是它还显示了每个组件的单位数。根据上下文,“单位”可以指 1、10、100 等。每个类别的元素(实际上,对于我们的下一个可视化,我们将使用 100 万平方公里的单位)。每个子集(类别)由一个充满方块的华夫饼干图上的一个区域表示。与树形图一样,网格上每个类别的面积与其值成正比。
当我们有一组相对较小的离散数据,并且对其组成部分的内部结构感兴趣时,华夫格图效果最好。但是,记住这种类型的图表的局限性是很重要的。与华夫格图完全相关的缺点是,每个类别中的单位数量应该相当少。其他一些限制与已经提到的可视化类型是相同的:
带有饼图和树形图:
- 当类别的比例相似时,效果不好。
- 它没有轴,所以我们必须依赖区域的视觉比较,或者在每个区域上添加相应的注释。
- 它有同样的问题,不可避免的丰富的颜色。
- 华夫饼图表的组成部分应该构成整体。
- 对用作输入的数据进行排序是非常明智的。
带饼状图:
- 当有许多类别需要比较时,华夫格图就变得低效了。
带树形图:
- 华夫格图的定制方式并不总是简单易懂的。
让我们看看使用华夫饼图表对我们的数据来说是否是一个好主意:
from pywaffle import Waffle
fig = plt.figure(FigureClass=Waffle, figsize=(12,7), values=dct, columns=15,
block_arranging_style='snake',
legend={'bbox_to_anchor': (1.3, 1), 'fontsize':14, 'frameon': False})
plt.title('Continents by area', fontsize=33)
plt.show()
作者图片
上图看起来完全定制化,并以正确的方式揭示了模式。然而,我们不得不承认,在这里,华夫格图并不是正确的选择:即使我们的类别很少,并且每个类别都由相对较少的单元组成,我们也不需要关于每个子集内部结构的如此详细的信息。还有,我们的“单位”看起来有点诡异:100 万 km2!😮我们甚至不能称之为离散值。因此,我们的数据不适合这种可视化。
华夫饼图的必要参数是FigureClass
、values
和columns
(或rows
)。
华夫格图的一个特殊变体是使用图标而不是方块的象形图图。通常,这样的图标应该是简单但对每个类别都有意义的东西,例如,显示不同领域进展的星星符号。当我们希望以更有影响力和更吸引人的方式展示见解时,象形图可以更有效地显示分类数据。华夫格图和象形图在显示统计数据、评级、进度状态等方面都特别有用。
6.词云
最后,显示分类数据的最奇特且几乎出乎意料的方式是创建一个单词云。为此,我们需要 wordcloud 库(pip install wordcloud
)。它的传统用法是将文本数据可视化,每个单词的大小表示它的频率,这样我们就可以辨别文本中最重要的单词。然而,词云还有一个鲜为人知的应用:将数据的某个属性值分配给每个类别,我们可以创建一个词云,不是基于词频,而是基于该属性(在我们的例子中,是每个大洲的区域)。此外,以这种方式使用词云,我们很容易避免许多与其相关的典型已知问题。事实上,与“正常”的单词云不同:
- 不需要预先准备数据、删除停用词等。
- 没有缺乏上下文的问题。
- 由于类别的数量通常相对较少,我们可以确保抑制任何垂直单词(将 1 赋给
prefer_horizontal
参数)以提高图形的可读性。另外,在这种情况下,我们肯定不需要使用面具。
与各种文字云相关的一些其他缺点仍然存在:
- 单词云不允许对单词进行直接清晰的排序。
- 单词云缺乏定量方法:不可能将字体大小转化为感兴趣的属性的精确值。而且,在这种情况下,我们甚至不能直接在图上把值相加。
- 有一种错觉,即较长的类别名称(尤其是多词的类别名称),或带有上升符号(如 k 、 b 、 l )或下降符号(如 j 、 q 、 g )的类别名称看起来更大,因此比具有相同或可比值但没有这些特征的类别名称更重要。
- 如果我们对我们的词云使用连续的 matplotlib 颜色图(岩浆、春天等)。),我们应该记住,每个类别的颜色将从其中随机选择,没有任何颜色的渐变性作为类别排名的潜在附加指标。
另一个缺点是饼状图、树形图和华夫饼干图共有的:当类别的比例相似时,单词云是无效的。然而,单词云在这些类型的可视化方面有一些优势:
- 丰富的颜色是一个可以解决的问题:可以分配一个颜色函数,甚至可以让所有的单词都是同一种颜色。
- 类别不必构成整体。
- 不需要事先对数据进行排序。
- 单词云对于显示更多类别仍然有用(与饼图和华夫饼图相比)。
- 词云是高度可定制的。
让我们为我们的大陆创建一个单词云,看看它的优点和缺点:
from wordcloud import WordCloud
plt.figure(figsize=(12,8))
wordcloud = WordCloud(background_color='white',
prefer_horizontal=1).generate_from_frequencies(dct)
plt.text(x=120, y=-25, s='Continents by area, mln km2', fontsize=27)
plt.imshow(wordcloud)
plt.axis('off')
plt.show()
作者图片
我们已经准备好一个词云不特别适合心理分类排名或定量分析。此外,我们看不到多少上行或下行。然而,这里真正分散注意力的是双词类别的存在:北美和南美。因此,我们可以得出结论,最好只在只有一个单词的类别中使用这种方法。
从技术上讲,虽然在我们的例子中,WordCloud()
的所有参数都是可选的,但是使用传入字典或序列的generate_from_frequencies()
是必不可少的。有趣的是,许多与“正常”词云相关的参数对于基于属性的词云变得无用,例如collocations
、stopwords
、min_word_length
和max_words
。
结论
在本文中,我们比较了显示分类数据的各种可视化类型。每一种都有其使用范围、优点和缺点。这些类型的图表中有些是经典和流行的(条形图),有些非常具体,看起来几乎很怪异(单词云)。
在我们的例子中,为了根据陆地面积比较各大洲,最有效的可视化类型是条形图、柱状图、饼状图和树形图。另外两种类型,华夫饼图表和单词云,结果不太适合,这并不意味着它们对任何其他数据都是如此。选择一个合适的图表总是取决于一种情况,以及我们到底想用我们的发现展示什么。一个正确的,适当定制的可视化可以帮助我们与我们的观众分享宝贵的见解。
感谢阅读!
你会发现这些文章也很有趣:
https://medium.com/geekculture/creating-a-waterfall-chart-in-python-dc7bcddecb45 https://medium.com/geekculture/creating-toyplots-in-python-49de0bb27ec1 https://levelup.gitconnected.com/python-can-be-lots-of-fun-999552d69d21