数据科学工作流程的 HDFS 简单 Docker 安装指南
使用 Docker 映像,在您的系统上轻松逐步安装和使用 HDFS。
卢克·切瑟在 Unsplash 上的照片
在这篇小文章中,我们将讨论如何在你的计算机上设置基于 Docker 的 Hadoop 分布式文件系统,并将讨论一个简单的例子来演示这个用例。此外,一旦安装准备就绪,您就可以开始构建自己的 map-reduce 作业来使用 Hadoop DFS。
从克隆 HDFS 项目开始
首先,你需要克隆下面的 Git 库 到你系统中你想要的目录。我更喜欢把它克隆到家里,以便演示和方便使用。
git clone [https://github.com/big-data-europe/docker-hadoop](https://github.com/big-data-europe/docker-hadoop)
然后使用更改目录命令进入项目库:
cd docker-hadoop
现在执行一个" ls -l "命令,您可以看到这个存储库中的所有文件,如下所示。
命令“ ls -l 的输出
获取 Docker 图像并创建容器
之后,您需要启动在您的系统上设置 HDFS 所需的容器。为此,项目目录中有一个 docker-compose.yml 文件,您需要使用" docker-compose up "命令从 Docker hub 下载并安装所需的映像,并基于 docker-compose.yml 文件配置容器。“ -d ”标志以分离模式运行容器。如果在本地找不到图像,Docker 会从 DockerHub 下载它们,但是如果您想要手动下载它们,您可以使用“ docker-compose pull ”。
注意:如果出现权限错误,请使用“ sudo ”作为这些命令的前缀。
# download images required for setting up HDFS and spin up necessary # containers.
docker-compose up -d
命令" sudo docker-compose up -d 的输出
上面的命令将从 docker hub 下载设置 HDFS 容器所需的所有 Docker 映像。根据您的网速,下载图像可能需要一点时间。
现在,要查看当前正在运行的 Docker 容器,使用命令列出所有活动的容器。
# List all the available running docker containers.
docker container ls
命令" sudo docker 容器 ls "的输出
与 namenode 连接
一旦您将所有文件复制到 Hadoop 集群中的一个目录中(注意:在本例中,我已经将文件复制到了 /tmp ),现在您可以在 bash 模式下的交互式终端模式中使用以下命令进入 namenode 中。
# Enter inside namenode and open its bash
docker exec -it namenode /bin/bash
例:sudo docker CP my _ input . txt NameNode:/tmp/
复制必要的 JAR 和输入文件
现在我们需要复制包含我们的 map-reduce 作业的 jar 文件,并使用以下 Docker 命令将它们复制到 HDFS 的 namenode(将运行您的作业)中:
docker cp <file_name> namenode:/<path>
与 namenode 交互
在交互式终端中输入名称节点后,使用以下 HDFS 命令与名称节点进行交互。
# HDFS list commands to show all the directories in root "/"
hdfs dfs -ls /# Create a new directory inside HDFS using mkdir tag.
hdfs dfs -mkdir -p /user/root# Copy the files to the input path in HDFS.
hdfs dfs -put <file_name> <path># Have a look at the content of your input file.
hdfs dfs -cat <input_file>
上述命令的输出
运行 Hadoop Map Reduce 作业
现在,您可以使用以下命令运行地图缩减作业:
# Run map reduce job from the path where you have the jar file.
hadoop jar <jar_file_name> <class_name> input output
例:Hadoop jar word _ counter . jar org . Apache . Hadoop . examples . word count 输入输出
一旦该命令成功运行**,您会注意到 map-reduce 作业完成了它的执行,并在控制台上显示了关于该进程的一些信息。**
检查你的输出
作业成功执行后,您可以在 HDFS 使用 cat 命令检查输出:
# Check the content of the output file after running the job
hdfs dfs -cat <output_file>
**命令"**HDFS DFS-cat output _ file/*的输出
您将看到您的单词计数器作业的词频应该打印在控制台上。
恭喜!您已经成功配置并创建了您的第一个 Hadoop HDFS map-reduce 作业!
额外小费
您可以在本地主机的端口 9870 上访问 HDFS namenode 的 UI 仪表板。使用以下链接:
http://:9870
NameNode UI:http://:9870
结论:
因此,基本上 HDFS 的设置对于简单的数据科学工作流来说很简单,并且您在阅读本文后已经了解到,设置一个基于本地 Docker 的 HDFS 设置并开始编写自己的 map-reduce 作业来执行各种任务是多么简单。如果你不是很熟悉地图减少工作,所以我附上了一些有用的链接。尽情享受吧!
- https://en.wikipedia.org/wiki/MapReduce
- https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html
- https://hadoop.apache.org/docs/r1.2.1/hdfs_user_guide.html
希望这篇文章对你有帮助!
谢谢!
使用 Python 进行头部姿态估计
您所需要的只是 OpenCV 和 Mediapipe 库。
玛利亚·特内娃在 Unsplash 上拍摄的照片
介绍
头部姿态估计是现有的计算机视觉任务之一。在这个任务中,我们想从物体的平移和旋转中知道物体的姿态。
这项任务有很多应用。例如,我们可以检测驾驶员是否在注意道路。第二个例子是,我们可以检查学生是否从学习中分心。我们可以用它做很多应用。
如你所知,我们只有二维图像。如何依靠图像本身来估计物体的姿态?我们可以使用一种称为 n 点透视(PnP)的解决方案。
PnP 问题方程看起来像这样:
从这个方程,我们可以检索旋转和平移矩阵。但是在我们得到这些矩阵之前,这个方程需要三个输入,例如:
- 图像空间中的 2D 坐标
- 世界空间中的 3D 坐标
- 相机参数,如焦点、中心坐标和倾斜参数
从这个等式中,我们得到两个主要问题:
- 我们如何获得这些输入?
- 我们如何根据这些输入来估计物体的姿态呢?
这篇文章将告诉你如何做。在本文中,我们将使用 Python 作为编程语言。此外,我们使用 mediapipe 库来检测面部关键点,使用 OpenCV 库来估计头部的姿态。
这是我们将创建的预览:
图片由作者捕捉。
没有别的了,让我们开始吧!
履行
安装库
在我们开始实现之前,第一步是安装库。在这种情况下,我们将使用 pip 安装 OpenCV 和 Mediapipe 库。在您的终端上,请编写以下命令:
**pip install opencv-python
pip install mediapipe**
加载库
安装完库之后,下一步是将库加载到我们的代码中。我们将导入 NumPy、OpenCV 和 Mediapipe 库。请添加这行代码:
初始化对象
加载完库之后,下一步是初始化几个对象。我们初始化了两个对象。它们是:
- Mediapipe 库中的 FaceMesh 对象。该对象将检测人脸,也检测一个或多个人脸的关键点。
- OpenCV 库中的 VideoCapture 对象。该对象将用于从网络摄像机中检索图像。我们将对象的参数设置为 0,用于从网络摄像头中检索图像。
请添加这几行代码:
捕捉图像
现在我们已经初始化了对象。下一步是从网络摄像头捕捉图像。为此,请添加以下代码行:
处理图像
在我们捕获图像之后,下一步是处理图像。供您参考,OpenCV 和 Mediapipe 库读取它们的图像是不同的。
在 OpenCV 库上,图像在 BGR 颜色空间中。同时,mediapipe 库需要一个具有 RGB 颜色空间的图像。
因此,我们需要首先将颜色空间转换为 RGB,应用人脸标志检测,然后将其转换回 BGR 颜色空间。
请添加以下代码行(注意缩进):
检索 2D 和三维坐标
处理完图像后,下一步是检索关键点坐标。供您参考,mediapipe 的面部标志检测算法可以从面部捕捉大约 468 个关键点。每个关键点都在三维坐标上。
对于头部姿态估计,我们不必使用所有的关键点。相反,我们选择至少能代表一张脸的 6 个点。这些点在眼睛的边缘,鼻子,下巴和嘴巴的边缘。
要访问这些点,我们可以参考 BlazeFace 模型中使用的索引。我已经标记了索引。这是它的照片:
这张图片是从 TensorFlow 的 GitHub 库中检索出来的,并由作者进行了编辑。
现在让我们提取这些关键点。对于 2D 坐标,我们将只取 x 和 y 轴坐标。对于三维坐标,我们检索所有的轴。
但是在我们提取这些关键点之前,我们必须用图像的宽度乘以 x 轴。此外,我们将 y 轴乘以图像的高度。
此外,我们将获得机头坐标。我们这样做是为了显示我们鼻子在图像空间的投影。
现在让我们添加这几行代码,注意缩进:
获取摄像机矩阵
现在我们有了面部关键点的 2D 和 3D 坐标。下一步是得到相机矩阵。让我们再次回忆一下相机矩阵。
正如你从上面看到的,我们需要几个参数。第一个是重点。我们可以通过获取图像的宽度来获得焦点(fx 和 fy)。
我们将采用的第二个参数是偏斜参数。该参数的符号为 gamma。对于这个参数,我们将值设置为 0。
第三个参数是我们图像的中心坐标。我们将用图像的宽度设置 u0,用图像的高度设置 v0。
现在让我们通过生成一个 NumPy 数组来创建矩阵。现在让我们添加这几行代码:
应用 PnP 问题
在应用 PnP 问题之前,我们需要添加另一个矩阵。这是一个距离矩阵。这个矩阵只包含零,它的形状是 4x1。现在,让我们通过添加这行代码来创建矩阵:
我们有所有的输入,从 2D 坐标,三维坐标,相机参数矩阵,和空距离矩阵。让我们通过添加这行代码将 PnP 应用于我们的问题:
将旋转向量转换成矩阵
从这个过程中,我们得到了平移向量和旋转向量。等等,旋转部分不是矩阵格式的。我们不能用它来恢复旋转角度。
别担心。我们可以用 cv2 把向量转换成矩阵。罗德里格斯函数。
现在让我们添加这行代码:
获取角度
现在我们有了旋转矩阵。现在让我们检索每个轴上的旋转角度。为此,我们可以使用 cv2。RQDecomp3x3 函数用于提取角度。
现在让我们添加这行代码:
捕捉头部的方向并显示结果
我们现在要做的最后一步是确定我们的方向。我们显示方向并创建一条线来查看我们的鼻子在图像空间上的投影。
现在让我们添加这几行代码:
通过组合所有这些代码行,结果将如下所示:
GIF 是作者捕获的。
结束语
干得好!我们已经使用 Python 实现了头部姿态估计。我希望它能帮助你建立你的计算机视觉解决方案,尤其是头部姿态估计问题。
如果你对我的文章感兴趣,可以在 Medium 上关注我。如果有任何问题,可以在 LinkedIn 上联系我。
如果您在编写代码时遇到了困惑,您可以在这里查看完整的代码来帮助您:
感谢您阅读我的文章!
参考
[1]https://medium . com/analytics-vid hya/real-time-head-pose-estimation-with-opencv-and-dlib-e8dc 10d 62078
【2】https://learnopencv . com/head-pose-estimation-using-opencv-and-dlib/
健康数据投资可能被浪费?
我们如何才能更好地实现投资数字健康研究和解决方案的潜力?
[图像信用](https://www.freepik.com/vectors/people’>People vector created by katemangostar - www.freepik.com)
在新冠肺炎疫情的推动下,的数字医疗采用速度加快了三年。从 2019 年到 2020 年,企业融资增加了 103%,仅在美国就达到 219 亿美元。那么,为什么参与度指标——尤其是关于健康行为改变的指标——仍然如此令人失望呢?
资源的涌入为数字健康研究和商业创造了大量的机会,但也暴露了其功效的局限性。
通过智能手表、手机和大量其他设备,我们似乎可以为一个人提供他们可能需要的所有测量,以全面了解他们当前的健康状况和未来的健康风险。但是当我们设计数字健康产品时,我们希望人们不仅仅是参与其中。我们还希望人们能够改变自己的行为,过上更幸福、更健康的生活。
许多数字健康和医疗保健数据科学文化基于这样一种假设,即个性化健康数据本身可以通知和激励或“推动”数字健康用户做出更健康的生活方式选择。然而,我们可能会经历一点点“发光物体综合症”,寄希望于个性化的健康数据带来现实生活中的行为改变。事实上,我们经常被低采用率和低参与率所困扰。只有一小部分的数字健康产品被用户以任何方式实现,给他们足够的输入来成功地改变行为。
事实上,在 2020 年疫情来袭之前,数字医疗的采用率实际上已经下降,从前一年的 48%下降到 35%。这似乎部分是由于用户所认为的“低质量的数字体验”。要改变人们的健康行为,我们必须首先让他们充分参与。让他们充分参与进来,采用数字健康工具。然后让他们更多地继续使用它以获得长期利益。
[形象信用](https://www.freepik.com/vectors/people’>People vector created by katemangostar - www.freepik.com)
数据够吗?
问题是,为什么数字健康创造者和用户可以获得的所有健康数据分析没有有效地吸引足够多的人?
答案可能在于我们经常对人类行为做出的另一个假设。
行为科学是从心理学和经济学发展而来的一门学科,致力于预测和解释人类行为。人们如何行动通常被认为是由他们是“理性”还是“非理性”决定的。例如,你可能听说过“系统 1 和系统 2”,这是诺贝尔奖获得者丹尼尔·卡内曼在他的开创性文章“思考的快慢”中带给我们的自动和有意识的思维过程?
健康的生活方式被认为是合理的,不健康的被认为是不合理的。几乎可以说,当人们不知何故失去了对自己和决策的控制时,就会做出不健康的选择。理性选择被视为明智的决策,最有可能基于可靠的数据。
如果我们应用这一行为科学框架,那么健康数据必然会帮助人们变得更加理性,从而做出更加健康的决定。还有什么比更多的数据更能提高理性,让理性的决策建立在更多的数据基础上呢?
但数字医疗解决方案的低采用率和参与率表明,这并不是全部情况。
房间里的情绪大象
准确和个性化健康数据的存在甚至承诺不足以让人们做出并保持健康的选择。对访问数字健康数据的人类行为的准确预测需要将该行为的更深层次的决定因素构建到我们的预测分析中。
比起认知问题的解决,情感更经常是人类行为的主导因素。情绪也是我们如何经历生活的特征,是我们生活故事中不可或缺的一部分。此外,情绪通常在人类功能的潜意识或无意识层面运作,并在我们没有意识到的情况下指导我们的行动、决定和行为模式。
也许我们在数字健康中的预测数据模型中缺少的是情感指标,这可能有助于我们解释更大比例的人类行为驱动因素,更有效地预测行为,并更可持续地让用户参与数字健康体验。
所以,让我们把情绪写进我们的预测模型。这是怎么回事?
情绪的度量
将情绪整合到我们的健康行为预测模型中可能会让我们更接近实现数字健康的潜力,但我们如何测量情绪并大规模进行大数据分析呢?
在数字健康中,情绪大多被概念化,并以面部表情来衡量。这源于发展心理学的通用面部表情理论,从中我们可以推断出其他人的感受。这种情绪指标的伟大用例是像临床决策支持系统这样的工具,在这些工具中,健康专家可以根据患者的面部表情更准确地识别他们的感受。有时,我们觉得我们不能安全地表达情感,有时我们可能不知道自己的感受,尤其是当我们处于病人这一脆弱的角色时。
然而,旨在帮助人们改变健康行为模式的数字健康技术,不会从其用户识别他人情绪的过程中获得同样多的价值。将情绪融入数字健康工具的一种通用方法是尝试预测人们使用该工具时的情绪反应。有助于个人层面行为改变的是将自己的情绪带入有意识的意识中。
在数字健康产品中创造隐含的积极情感体验会更好,我们可以通过以用户为中心的技术设计中的深度情感设计,借鉴品牌创建和用户参与中的客户忠诚度构建技术来做到这一点。
谷歌心脏框架
[图像信用](https://www.freepik.com/vectors/clouds’>Clouds vector created by vectorjuice - www.freepik.com)
如果你正在考虑在预测人类行为变化的数字健康数据模型中包含情绪,你可能想使用谷歌心脏框架作为起点。
开发该框架是为了增加用户对基于网络的产品的参与,它也可以适用于其他类型的技术。HEART 框架构建了我们对用户参与度的思考,将用户“快乐”放在首位。首字母缩写代表:快乐、参与、采纳、保持和任务成功。
对于每个度量类别,该框架还要求您确定与该度量一致的目标、信号和度量。
当考虑如何将情绪纳入预测模型时,使用框架中的快乐类别,但扩展用户满意度的定义,超出通常的 5 点李克特量表问题“您对该功能/产品的满意度如何?”。
相反,确定你的用户认同的价值观,他们信任的信息类型,并以此为基础建立你的幸福指数。
你已经离增加用户参与度更近了一步,创造积极的情感体验和对你产品的忠诚度,这将帮助人们实现长期健康行为的改变。
[形象信用](https://www.freepik.com/vectors/business’>Business vector created by jcomp - www.freepik.com)
推荐
你不需要知道所有的答案。
这可能是一个难以接受的说法。作为科学家、数据分析师或技术设计师,我们很好奇,我们想要答案。
我们写这篇文章是为了帮助数据科学家创建更有效的人类行为模型,并帮助他们提高新数据驱动技术的采用潜力。但是我们也没有所有的答案。我们确实相信,通过提出正确的问题,我们可以让事情变得更好。
我们建议您从问自己以下问题开始:
- 你的模型的预测是否依赖于人们做出严格理性的——合乎逻辑的、明智的、理性的——决定?(如果是这样,你目前还没有一个准确的行为模型。你需要带着整个模型回到绘图板)
- 在实践中,您的模型的采用或实现是否依赖于人们做出严格理性的——合乎逻辑的、明智的、理性的——决策?(如果是这样的话,你目前还没有一个有潜力改变任何事情或帮助人们的模型。您需要带着您的采纳和实施计划回到绘图板。)
- 你的用户/研究人群经历了什么样的情感体验,你如何在数据中表达出来?
- 哪些同事,也许是跨学科和国际合作者,可能能够帮助你进一步将情感体验整合到你的模型中?
- 在你的下一次资金申请中,你将如何展示你对情感体验在决定行为中的重要性的理解?
- 在您的资助申请中,您如何强调用户/参与者的参与,以强调功效/效果潜力?
不管你现在是否能肯定地回答这些问题,这都可以成为你改善情绪在数据科学中的作用的框架。
鉴于疫情所创造的势头,对数字健康工具的学术和商业研发的投资可能会以前所未有的速度持续增长。个性化健康数据分析和健康行为改变仍然是数字革命的重要目标。如果我们想避免浪费投资的失望,现在是时候更多地关注情绪在参与和行为改变中的作用了。
医疗保健人工智能的公平问题
公平和偏见
为什么数据公平不仅仅是公平
我们目前正处于一些人所说的人工智能的“狂野西部”之中。尽管医疗保健是监管最严格的部门之一,但这一领域的人工智能监管仍处于初级阶段。规则被写成我们说。我们正在迎头赶上,学习如何获得这些技术带来的好处,同时在这些技术已经部署后最大限度地减少任何潜在的危害。
医疗保健中的人工智能系统加剧了现有的不平等。我们已经看到了现实世界的后果,从美国司法系统的种族偏见、信用评分、简历筛选和性别偏见。旨在为我们的系统带来机器“客观性”和易用性的程序最终会复制和支持偏见,却没有任何责任。
算法本身很少是问题。值得关注的往往是用于技术编程的数据。但这远不止是道德和公平的问题。构建考虑医疗保健全貌的人工智能工具是创建有效解决方案的基础。
算法和数据一样好
从我们人类系统的本质来看,数据集几乎总是不公正的,很少是公平的。正如 Linda Nordling 在《自然》杂志的一篇文章中评论的那样,人工智能在医疗保健中更公平的前进方式,“这场革命取决于这些工具可以学习的数据,这些数据反映了我们今天看到的不平等的医疗系统。”
以调查结果为例,美国急诊室的黑人接受止痛药的可能性比白人低 40%,西班牙裔病人低 25%。现在,想象一下这些发现所基于的数据集被用来训练一个人工智能工具的算法,该工具将被用来帮助护士确定他们是否应该服用止痛药物。这些种族差异将会重现,而支持这些差异的隐性偏见将不会受到质疑,甚至变得自动化。
我们可以尝试通过删除我们认为导致训练偏差的数据来改善这些偏差,但仍然会有隐藏的模式与人口统计数据相关联。一个算法不能考虑到全局的细微差别。它只能从提供给它的数据模式中学习。
偏差蠕变
数据偏见以意想不到的方式蔓延到医疗保健领域。考虑到世界各地实验室中用于发现和测试新止痛药的动物模型几乎全部是雄性。因此,包括止痛药在内的许多药物都不适合女性。因此,即使像布洛芬和萘普生这样的普通止痛药也被证明对男性比女性更有效,而且女性比男性更容易遭受止痛药带来的副作用。
事实上,雄性啮齿动物也不是完美的测试对象。研究还表明,雌性和雄性啮齿动物对疼痛程度的反应因在场人类研究人员的性别而异。啮齿动物对一名男性研究人员的嗅觉引起的压力反应足以改变它们对疼痛的反应。
虽然这个例子看起来似乎偏离了人工智能,但事实上它有着深刻的联系——在治疗进入临床试验之前,我们目前可以获得的治疗选择隐含着偏见。人工智能公平的挑战不是一个纯粹的技术问题,而是一个非常人性化的问题,始于我们作为科学家做出的选择。
不平等的数据导致不平等的利益
为了让全社会享受人工智能系统可以给医疗保健带来的诸多好处,全社会必须在用于训练这些系统的数据中得到平等的代表。虽然这听起来很简单,但这是一个很难完成的任务。
来自某些人群的数据并不总是能够进入训练数据集。发生这种情况的原因有很多。由于现有的系统性挑战,如缺乏获取数字技术的途径或仅仅被认为不重要,一些数据可能无法获取,甚至根本无法收集。预测模型是通过以有意义的方式对数据进行分类而创建的。但是因为一般来说数据较少,“少数”数据往往是数据集中的异常值,为了创建一个更清晰的模型,经常被当作虚假数据剔除。
数据源很重要,因为这个细节无疑会影响医疗保健模型的结果和解释。在撒哈拉以南非洲,年轻女性被诊断出患有乳腺癌的比率要高得多。这揭示了为这一人口群体量身定制的人工智能工具和医疗保健模型的需求,而不是用于检测乳腺癌的人工智能工具,这些工具只在全球北方的乳房 x 光片上进行训练。同样,越来越多的工作表明,用于检测皮肤癌的算法对于黑人患者来说往往不太准确,因为它们主要是在浅色皮肤患者的图像上进行训练的。这样的例子不胜枚举。
我们正在创造有可能彻底改变医疗保健行业的工具和系统,但这些发展的好处只会惠及数据中显示的那些人。
那么,有什么办法呢?
消除数据偏见的部分挑战是,大量、多样和有代表性的数据集不容易访问。公开可用的训练数据集往往非常狭窄、数量少且同质——它们只捕捉到社会的一部分。与此同时,许多医疗机构每天都要捕获大量不同的健康数据*,但数据隐私法使得访问这些更庞大、更多样的数据集变得困难。*
数据保护当然至关重要。在负责任地使用数据方面,大型科技公司和政府没有最好的记录。然而,如果医疗数据共享的透明度、教育和同意得到更有目的的监管,更加多样化和高容量的数据集可能有助于在人工智能系统中实现更公平的表示,并为人工智能驱动的医疗工具带来更好、更准确的结果。
但是数据共享和访问并不能完全解决医疗保健的人工智能问题。通过人工智能实现更好的个性化医疗保健仍然是一个极具挑战性的问题,需要一大批科学家和工程师。我们希望教会我们的算法做出好的选择,但我们仍然在弄清楚好的选择对我们自己来说应该是什么样的。
人工智能为医疗保健带来了更大的个性化机会,但它也带来了巩固现有不平等的风险。我们面前有机会采取一种经过深思熟虑的方法来收集、监管和使用数据,这将提供一个更全面、更公平的画面,并实现人工智能在医疗保健中的下一步。
医疗保健价格?Fuhgeddaboudit!
纽约市公立医院系统价目表的启示
想象一下,你打算买一部新的 iPhone。首先你上网去www.apple.com。可以看到最新的 iPhone 型号,但是没有列出价格。你知道相机好的那台可能比相机差的那台贵,大的那台可能比小的那台贵,但你不知道价格到底有多大差别。于是,你打电话给苹果的客服专线,询问你最喜欢的 iPhone 的价格是多少。他们说,这取决于你去哪家苹果商店。这也取决于你有什么手机计划。如果你参加的是威瑞森家庭计划,手机将是一个价格,如果你参加的是 Sprint 个人计划,手机将是另一个价格,以此类推。即使我们知道你的手机计划和你要去的商店,我们可能也不会告诉你手机的价格,除非你已经买了。
这听起来完全就是个骗局!但是这就是美国人每天购买医疗保健的方式——而且我们都对此没什么意见。
思考医疗保健价格,比如…
来源:https://knowyourmeme.com/memes/math-lady-confused-lady
幸运的是,联邦政府已经采取了一些小措施,试图给这个错综复杂的市场带来更多的透明度和清晰度。有一项法律于 2021 年 1 月在 T21 生效,该法律要求医院以机器可读的格式公布他们手术的价格。这(理论上)包括所有程序的标价、现金折扣价格(即未投保者支付的价格)和保险公司协商的价格。在这项法律之前,医院和保险公司可以对他们协商的费率保密。这些都应该是公开的信息。
这个新法太棒了!理论上。实际上,每家医院每天的违规费用仅为 300 美元。这个费用实在太低,不足以激励大多数医院系统遵守。我住在纽约市,所以我一直对纽约市的大多数医院是否会很快遵守这一规定特别感兴趣。不幸的是,答案是…不!在 Gothamist 查看这篇关于它的文章(可悲的是,自从 1/18/21 发表文章以来,情况并没有太大变化)。
一个已经公布了非常有用的数据的医院系统是纽约市公立医院系统: 纽约市健康+医院 。有了这些数据,我对价格差异做了一个非常简单的分析:
- 按每个程序的标价、现金价格和协商价格(在同一家医院内)
- 纽约市公立医院系统内不同医院相同手术的价目表价格和现金价格
这是一个非常高层次的数据,进一步的分析应该深入到程序级别的结果。这种粒度分析的例子可以在《华尔街日报》对加州萨特医疗系统剖腹产价格的深入调查中找到。SparkNotes:根据你的保险计划,价格从 6k 美元到 60k 美元不等。
数据准备
这个项目中使用的所有数据都可以在纽约市健康+医院设施收费页面上找到(尽管我是使用 pandas read_csv 函数自动获取数据的)。我将医院名称添加到每个医院的价格表中,合并数据集,并根据程序代码将每个程序标记为“住院”或“门诊”程序。我排除了所有标价为 1 美元的程序,因为我注意到它们似乎主要是奇怪的医疗保险专用代码,只是扭曲了数据。
接下来,如果现金价格不为空,并且低于价目表价格,则使用现金价格导出“调整后的现金价格”,否则使用价目表价格。现金价格高于标价对我来说没有意义。从数据来看,现金价格的设定似乎没有标价那么细致。例如,与某个高级医疗代码相关的每个程序可能有 500 美元的现金价格,即使属于同一医疗代码的单个程序有 25 美元的标价。对于这个 25 美元的程序,我将调整后的现金价格设为 25 美元,而不是 500 美元。你可能认为这是一个糟糕的假设,但是,唉…我做到了。
只需一个快速喊出: np.where()震撼我的世界 。 为了区分住院/门诊程序,并为了计算调整后的现金价格,我想创建一个新列,其值取决于几个标准。我在熊猫上尝试了很多方法,但是 np.where()是最简单和最快的。
仅 np.where()共鸣
接下来,对于我的数据框架中的每一行,我计算协商价格与标价、现金价格与标价以及协商价格与现金价格之间的百分比差异。在这些计算中,我假设如果协商价格为空,我应该使用价目表价格来代替(因为保险计划没有为该程序协商价格)。
作为最后的数据清理步骤,对于我在分析的第 1 部分中使用的数据框架,如果它们在每个医院的每个保险计划中没有至少出现一次,我就放弃所有的程序。我想确保如果我在比较不同保险计划的数据,我是在比较不同的程序。对于我在分析的第二部分中使用的数据框架,我再次放弃了不是每个医院都提供的所有程序。同样,我希望我的比较是苹果与苹果之间的比较。
第 1 部分:清单、现金和议价
现在我的数据已经准备好了,我可以通过保险计划计算所有程序中的平均和中间协商价格与现金价格、现金价格与标价以及协商价格与现金价格。然后,我只对那些保险计划已经协商了费率的程序/计划组合执行相同的计算(以防他们没有为不常见的程序进行协商,这可能只是扭曲了更有意义的结果)。我还计算了每个计划协商了费率的程序的百分比。我将所有这些结果合并到一个数据框架中,并对住院病人和门诊病人的程序进行重复。结果如下所示。
住院结果
住院保险计划(&现金)议定费率差异
上图显示了不同保险计划在住院患者数据集中的协商价格以及调整后的现金价格。
- **协商价格与价目表平均值/中值:**我们可以看到,平均而言,Metroplus Medicaid 和 UHC 社区计划协商了与价目表价格相对应的最佳价格,其次是调整后的现金价格,然后是第一保健全面保护和医疗保险 AB。然而,当我们看中位数时,只有 Metroplus Medicaid 的表现优于调整后的现金价格。
- **协商与现金平均值/中值:**当进行面对面比较时,平均而言,只有 Metroplus 优于调整后的现金价格,而当我们查看中值差异时,Metroplus 和 UHC(略微)优于调整后的现金价格。
- %
住院患者直方图:标价、现金和议价
上面,我们深入研究了数据的分布,看看我们的均值/中位数是否掩盖了任何有趣的趋势。对于每个类别,我们显示完整的直方图,然后显示一个仅集中在-100%到+100%范围内的直方图,以忽略可能的异常值。
- **协商价格与标价(蓝色图表)😗*虽然有时协商价格高于标价,但最常见的差异是 0%(未协商)。在谈判价格中,大部分价格似乎在-80%到-50%之间。
- **调整后的现金价格与清单(绿色图表)😗*大多数程序要么有 0%的折扣,要么有~-60%的折扣。
- **协商价格与调整后现金价格(橙色图表)😗*有相当数量的程序,其协商价格是调整后现金价格的倍数(> +100%)。然而,大多数似乎都在-100%和 100%之间。我们看到另一个 0%的峰值,可能是因为某些程序的现金价格等于标价,没有协商的价格。在那种情况下,它们都是同样的价格。
住院病人,所有程序:保险计划费率与现金相比如何
我想总结每个保险计划与调整后的现金价格相比的表现,所以我创建了上表。最终,Metroplus Medicaid(如预期)的协议价格优于调整后现金价格的程序比例最高(73%),而 Medicare AB 的比例最低(19%)。
住院病人,仅协商程序:保险计划费率与现金相比如何
我们知道,不是所有的程序都有一个协商好的价格,这可能是因为它们可能非常不常见,因此只是噪音。因此,我检查了每个计划在调整后的现金价格下的表现,只检查了那些他们协商了价格的程序。使用这一指标,保险计划确实看起来更好,Metroplus Medicaid 现在 89%的时间优于现金,而 Medicare AB 现在 29%的时间优于现金。
门诊结果
下面的图表与上面住院病人部分的图表相同,只是我们现在使用的是门诊病人数据集(其中包括一些额外的保险计划)。
门诊保险计划(&现金)议定费率差异
上图显示了不同保险计划在门诊数据集中的协商价格以及调整后的现金价格。请注意,FFS 联邦医疗保险计划和 UHC 社区计划对门诊程序没有任何议价。因此,他们的大米完全符合标价。
- **协商价格与价目表平均值/中值:**我们可以看到,平均而言,Aetna 协商了最佳费率与价目表价格,其次是调整后的现金价格,然后是 1199SEIU 福利基金、Metroplus Medicaid、第一保健全面保护和 Medicare AB。然而,当我们看中位数时,只有 Metroplus Medicaid 的表现优于调整后的现金价格。
- **协商价格与现金平均值/中值:**当进行面对面比较时,所有计划的协商价格平均都高于(低于)调整后的现金价格,尽管当我们查看中值差异时,Metroplus Medicaid 明显优于调整后的现金价格。当我们查看中间值差异时,Aetna 和 1199SEIU 福利基金也优于调整后的现金价格。
- %
门诊直方图:标价、现金和议价
上面,我们深入研究了数据的分布,看看我们的均值/中位数是否掩盖了任何有趣的趋势。对于每个类别,我们显示完整的直方图,然后显示一个仅集中在-100%到+100%范围内的直方图,以消除可能的异常值。
- **协商价格与价目表价格(蓝色图表)😗*虽然协商价格很少高于价目表价格(第一个直方图范围从-1 到+140),但最常见的差异是 0%(未协商)。在协商价格中,它们相当均匀地分布在-10%和-100%之间(我不确定为什么在数据集中有相当数量的协商价格为$0 的过程;这是来自医院系统的值,我不确定它是否是有意的)。
- **调整后的现金价格与清单(绿色图表)😗*大多数手术要么有 0%的折扣,要么有-60%的折扣(与住院手术相同)。
- **协商价格与调整后现金价格(橙色图表)😗*有少数程序的协商价格是调整后现金价格的倍数(> +100%)。然而,大多数人似乎在-100%和 100%之间。我们在 0%处看到了另一个峰值(原因与之前相同),但是其余的峰值相当均匀地分布在-100%和+100%之间,在-20%处有一个小峰值。
门诊病人,所有程序:保险计划费率与现金相比如何
我想总结每个保险计划与调整后的现金价格相比的表现,所以我创建了上表。最终,Metroplus Medicaid(如预期)的协商价格优于调整后现金价格的程序比例最高(80%),而 Medicare AB 的比例最低(10%),除了 UHC 社区计划/FFS Medicaid 没有协商价格。
门诊病人,仅协商程序:保险计划费率与现金相比如何
同样,我们知道不是所有的程序都有协商好的价格,这可能是因为它们可能非常不常见,因此只是噪音。因此,我们可以根据调整后的现金价格检查每个计划的执行情况,只检查那些他们协商了费率的程序。使用这一指标,一些保险计划看起来确实更好,如 Medicare AB 和第一保健完全保护(这两个保险计划的< 25% of procedures) shooting up from ~10% to ~70% of the time better than Cash. The stats remain steady for 1199SEIU Benefit Fund, Aetna, and Metroplus Medicaid — which makes sense because they negotiated nearly every procedure.
Part 2: List & Cash Prices Across Hospitals
We now turn to the List Prices and Adjusted Cash Prices across the NYC Public Hospital System. We calculate the mean and median List and Cash Prices for each procedure across all eleven hospitals. We then calculate the difference between these means/medians and the List/Cash Price for each procedure at each hospital, to see how the hospital’s price stacks up against the competition. Since this is all data about the same hospital system, we wouldn’t expect to see massive differences across hospitals.
INPATIENT RESULTS
Inpatient: Mean Variation in Prices by Hospital
In the chart above, we plot the 谈判价格意味着住院手术的医院价格差异。
- **标价与平均值/中值:**各个医院的住院病人标价没有太大差异。
- **现金价格对比均值/中值:**这个比较有意思。看起来 11 家医院中有 4 家医院的现金价格比其他医院高得多。平均而言,康尼岛、艾姆赫斯特、哈莱姆和雅各比的现金价格都比整个医院系统的现金价格中值高出 140%以上。然而,当我查看这些医院的原始数据集时,我可以看到它们没有列出任何折扣现金价格。只需列出价格和协商价格。不确定这是为什么——可能只是没有报告他们的现金价格?
住院病人:各医院价格的中位数变化
在上面的图表中,我们绘制了医院的中值价格差异,用于住院治疗。
- **标价与平均值/中值:**同样,各个医院的住院病人标价没有太大差异。
- **现金价格与均值/中值:**康尼岛、埃尔姆赫斯特、哈莱姆和雅各比的现金价格都远高于整个医院系统的现金价格中值。在这种情况下,所有四家医院的中位数差异约为 150%。(同样,这可能只是一个数据报告问题)。
住院患者直方图:纽约市公立医院每项手术的现金价格与中间价格
为了更好地了解不同医院之间每项手术的现金价格差异,我们为每家医院创建了一个直方图,显示其现金价格与医院系统中值现金价格的分布。我们的四家昂贵的医院呈现出相似的分布,与其他七家有很大的不同。
门诊结果
下面的图表与上面住院病人部分的图表相同,只是我们现在使用的是门诊病人数据集。
门诊病人:医院价格的平均变化
在上图中,我们绘制了医院门诊手术的平均价格差异。
- **标价与平均值/中值:**不同医院的门诊标价没有太大差异。
- **现金价格与平均值/中位数:**不同医院的门诊现金价格也没有太大差异。(貌似所有医院都在提供门诊打折现金价格)。
门诊病人:医院价格的中位数变化
在上图中,我们绘制了医院门诊流程的中值价格差异。由于变化非常有限,所有医院所有这些指标的中值差异为零,因此该图表为空白。
结论
最终,这是一个有趣的练习,但我最大的收获是这仅仅是开始。首先,这个数据集似乎缺少纽约许多著名商业保险计划的协商费率:帝国蓝十字蓝盾、信诺、徽健、联合医疗保健等。此外,这只是一个城市中的一个医院系统。这可能是这个城市最便宜的系统之一,因此也可能是最没意思的。我们需要全国所有医院系统(公立和私立)的相同信息,并且我们需要一种易于比较的格式。
现在我不再是黛比·唐纳了,我们从这个不完美但仍然有用的数据集中学到了什么?
住院亮点
- 迄今为止费率最高的计划是 Metroplus Medicaid。除此之外,其他计划并不比现金价格好太多!
- 由于协商的价格往往比现金价格更差…对于任何一个每年有很高免赔额的人来说,他们认为他们不会满足,当你最好支付现金时,每月保费的意义是什么?
- 纵观纽约市系统的 11 家医院,康尼岛、埃尔姆赫斯特、哈莱姆和雅各比医院的现金价格由于某种原因比其他医院高得多(因为它们没有现金价格!).然而,这可能只是一个数据报告问题。
门诊亮点
- Metroplus Medicaid 费率最优惠。1199SEIU 福利基金和 Aetna 比现金稍好,其余的计划要么相当于,要么比调整后的现金价格差。
- 同样,对于某些程序,免赔额非常高的患者考虑现金价格与保险计划的协商价格似乎很重要。
- 纵观纽约市系统的 11 家医院,清单和现金价格基本相同(不出所料!).
感谢阅读,现在让我们向更多的医院系统施加压力,公布他们的费率!
医疗保健的人工智能未来——与和费的对话
与两位领先的人工智能专家在数据科学和医疗保健的交叉领域进行炉边交谈,获得了四个关键收获
卡米洛·希门尼斯在 Unsplash 上拍摄的照片
深度学习。AI 和斯坦福海最近组织了一次与两位世界上最杰出的计算机科学家和费的虚拟炉边聊天。
在对医疗保健的 社会使命和对人类的重要性的强烈信念的驱动下,他们近年来将努力和专业知识集中在医疗保健行业。
这篇文章从人工智能和医疗保健交叉的角度和观点来看四个关键要点。
关于扬声器
费-李非 是斯坦福大学计算机科学系的首任红杉教授,也是斯坦福大学以人为中心的人工智能研究所的联合主任。她在 2013 年至 2018 年担任斯坦福大学人工智能实验室的主任。
Andrew NG是 deeplearning.ai 的创始人,Coursera 的联合创始人,目前是斯坦福大学的兼职教授。他也是百度公司的首席科学家和谷歌大脑项目的创始人。
四个关键的信息
(1)在医疗保健领域采用人工智能的最大障碍
尽管医疗保健领域对人工智能进行了大肆宣传,但这种人工智能解决方案的现实实施比预期要慢得多,只有少数孤立的成功。
Andrew 认为,技术和非技术方面的变革管理仍然是一个严峻的挑战。从技术角度来看,团队需要学习如何更好地管理机器学习项目的整个生命周期**。**
飞飞强调,医疗保健领域的人工智能仍然缺乏“人类胜利”,无法创造行业的分水岭时刻。她提到,仍然缺乏经过验证的故事和产品来展示人工智能解决方案如何给患者或医疗保健提供商带来根本性的变化。
(2)最重要的未解决的医疗保健问题
数据科学的目标是利用数据和高级技术来解决业务问题。因此,听听小组成员认为哪些是值得应对的重大挑战会很有意思。
飞飞分享了一个惊人的统计数据,吸引了观众的注意力——据估计,美国每年有 25 万人死于医疗事故。
虽然医疗创新为开发新药和程序以更有效地治疗患者铺平了道路,但人为错误、疲劳和系统资源不足等问题仍然是医疗保健系统中伤亡事故的重要原因。
Andrew 强调了这一点,他提到虽然医疗保健中的人工智能通常与诊断和治疗相关联,但对运营方面的关注和研究相对较少**。**
他认为,在医疗保健的运营优化方面,有一些被忽视的重大问题,如为有限的资源(如核磁共振成像设备)安排患者和医疗保健人员的配备。
Alex Mecl 在 Unsplash 上拍摄的照片
(3)同理心和协作的重要性
数据科学是一项团队运动,需要紧密的合作和一致的目标才能取得成功。
飞飞认为,数据科学家(技术成员)和医疗从业者(非技术成员)都必须培养一种理解对方语言的移情意愿。
例如,飞飞会让她的学生在医院跟随斯坦福医生几天,通过见证病人和医疗服务提供者的脆弱、同情和尊严来了解医疗保健领域的人性。
Andrew 分享了他在构建姑息护理推荐系统方面的经验。他很好奇这个系统是如何激励更多的提供者开始对话推荐某些患者进行姑息咨询,而在其他情况下可能不会讨论。
这种机器学习应用程序打开了以前的层级结构,为医院中的一种方法铺平了道路,这种方法更具多利益主体、互动性和同理心**。**
(4)避免偏见的永久化
近年来,偏见进入人工智能系统并导致有害结果的问题受到了关注。
Andrew 建议多学科团队应该聚在一起集思广益,找出机器学习应用中可能出错的所有事情**,并围绕它们设计指标以实现透明监控。**
此外,数据应相应地 切片以分析机器学习模型对不同组的影响,作为系统审计的一部分。
飞飞强调,在编写任何代码之前,伦理应该是设计人工智能解决方案的核心考虑因素。在她管理的团队中,她让伦理学家、法律专业人士、患者和医疗保健提供者参与讨论这些潜在的偏见,作为解决方案设计过程的一部分。
机器学习系统中包含的偏见是最终成为** 人类的责任。因此,认识到我们人类对任何形式的系统偏差都负有责任是至关重要的,我们需要设置护栏来尽可能减轻偏差。**
完整的对话
你可以在这里观看整个对话的视频:
在你走之前
欢迎您加入我的数据科学学习之旅!点击此媒体页面,查看我的 GitHub ,了解更多精彩的数据科学内容。同时,尽情探索医疗保健和数据科学的交集吧!
美国最健康的城市:第一部分,食物
美国城市有多健康?
在 Unsplash 上由 Haseeb Jamil 拍照
我一直在思考在城市分析的背景下使用数据科学和统计学,特别是关于美国城市有多健康的问题。在这些由多个部分组成的故事中,我们将使用数据科学来分析这个问题。此刻,我打算这样划分故事:美食、休闲空间、工作生活平衡。在第一部分,我们将关注食物:即快餐连锁店在美国各城市有多普遍,以及美国人民在杂货店购买食物有多容易。让我们开始吧:
数据:
工具:
- Jupyter 笔记本
- 熊猫(一个数据帧处理包)
- Stats (Python 统计分析库)
- Seaborn 和 Matplotlib(可视化库)
1.方便食品
让我们首先尝试围绕数据收集一些基本事实:
-
有多少独特的城镇:
-
结果: 2764 个独特的城镇
-
对于每个快餐条目,数据集包含哪些列/数据?
-
**结果:**索引(['id ‘,’ dateAdded ‘,’ dateUpdated ‘,’ address ‘,’ categories ‘,
,’ country ‘,’ keys ‘,’ latitude ‘,‘经度’,’ name ‘,’ postalCode ‘,【T21 ‘,‘省’,’ sourceURLs ‘,’ websites’],
dtype='object ') -
最常见的品牌是哪个?
-
**结果:**麦当劳(1898 家餐厅),塔可钟(1032 家),汉堡王(833 家),赛百味(776 家),Arby’s (663 家)。
-
有多少快餐?
-
结果:10000
计算美国最健康城市的一个主要问题是每个城市有多少家快餐店。要回答这个问题,我们可以使用熊猫按城市名称对数据进行分组,然后按每个城市的快餐数量对数据框进行排序,如下所示:
不足为奇的是,像休斯顿和拉斯维加斯这样的大城市拥有最多的快餐店,因为它们规模庞大。因此,简单地使用餐馆数量是不够的:我们需要一个变量来量化基于人口的数量。为了做到这一点,让我们设计一个新的指标,快餐数量除以每个城市的人口。如果一个城市有许多快餐,但人口很少,这个变量将有一个高值,反之亦然,为低值。将该指标添加到数据帧的代码如下:
以下是我们设计的指标值最高的前 20 个城镇:
你可以看到像恩西诺(加利福尼亚)、吉尔福德(北卡罗来纳)和王国城(密苏里)这样的城镇在列表的顶部。有趣的是,所有这些城市/城镇似乎在规模和人口上都更小,这意味着最大的城市有更少的快餐服务更多的顾客,按照我们的标准,使他们更健康。我们来看看实际情况是否如此。首先,这是数据集中所有城市的人口数量和相应的快餐数量的散点图:
虽然对于 250,000 人以下的城镇来说,人口和快餐数量之间的关系似乎是线性的,但随着人口的增加,这种关系似乎不那么明显了。这是人口与我们设计的指标的散点图:
在这种情况下,实际上看起来这种关系有点负面:随着人口的增长,人们可以吃的快餐越来越少。
为了真正了解人口较少的城市和人口较多的城市在快餐店方面是否存在实际差异,我们可以对这两种人群进行一些统计分析。对于这个故事,我们将定义两种不同的城市规模:小于或等于 25,000 和大于 25,000。在我们测试这两个群体的差异之前,我们需要决定我们将使用的测试。为此,首先我们必须看看人口是否正态分布。这可以通过使用 QQ 图和夏皮罗-维尔克正态性检验来实现:
qqplot
QQ 图是一个散点图,绘制两组分位数之间的关系。如果两组分位数来自相同的分布,我们应该看到这些点形成一条大致笔直的线。下面的代码将数据集分成两个预定义的城市大小。
这是较大(超过 25,000 人)城市的 qqplot:
这是较小城镇的 QQ 图:
正如你所看到的,这两个群体都不符合直线,这使我们倾向于说群体不是正态分布的。
夏皮罗-维尔克
检验正态性的夏皮罗-维尔克检验通过设定两个假设来工作:
- 零假设:数据呈正态分布。
- 替代假设:数据不是正态分布的。
以下是针对较大城镇的夏皮罗-维尔克测试结果:
这是针对小城镇的夏皮罗-维尔克测试结果:
曼-惠特尼试验
既然我们已经确定数据不是正态分布的,那么一个合适的测试就是曼-惠特尼测试来确定我们两个群体之间的差异。对于这个检验,我们还应该陈述一个无效假设和另一个假设:
- 零假设:两个群体来自同一个基础群体。
- 替代假设:两个群体不来自同一个潜在群体。
该测试的代码如下:
曼·惠特尼测试告诉我们,小城镇和大城镇的快餐数量确实存在差异,这对于根据美国人居住的城市来理解他们可获得的食物类型是很有趣的。
2.食品杂货通道
对于这个故事的第二部分,我们将看看美国哪些县最容易获得食品杂货。数据取自经济研究署的食品环境图集(https://www . ers . USDA . gov/data-products/Food-Environment-Atlas/)。
如您所见,数据集包含了县一级的各种指标的信息。我们将使用的是“LACCESS_POP10”,它指的是 2010 年每个县获得食品杂货的人数。让我们首先过滤数据集,并查看每个州的这一指标的平均值:
“值”列包含获得食品杂货的平均人数,最高值属于马萨诸塞州,其次是康涅狄格州和新泽西州,这可能有点令人惊讶,因为它们都是拥有大片城区的州。就像我们对快餐所做的那样,我们应该将这些数字换算成该州的人口数,并用一个比率来表示,所以让我们使用下面的变量:很少接触食品杂货的人数除以该州的人口数。代码如下:
为了解释这些结果,该变量的大值意味着每个州拥有低访问权限的人口比例较高,而小值意味着拥有低访问权限的人口较少。以下是按变量降序排列的前 10 个州:
倒数 10 个州是:
得克萨斯州是食品杂货收入低的人口比例最小的州,而特拉华州是最高的,其次是罗德岛州和夏威夷。这些结果让你感到惊讶吗?它们对我来说有点小,因为我原本预计美国中部农村人口较多的州会在列表中占主导地位,因为杂货店可能在这些州很少。然而,有趣的是,似乎事实并非如此。
希望你喜欢这个小故事,如果你想看完整的代码,可以在这里找到:https://github . com/DeaBardhoshi/Data-Science-Projects/blob/main/_ Urban % 20 health % 20 analysis % 20 part % 201% 20-% 20 food . ipynb
感谢阅读!
听我说完:我发现了一个更好的估计中位数的方法
人们经常使用百分位数来汇总数据。中位数是第 50 个百分位数,众所周知,它对数据中的异常值非常稳健(与平均值相反)。此外,它代表了一个“典型样本”,平均值并不一定如此。有时,人们觉得他们需要追求分布的极端,并开始使用高百分位数(如第 95 和第 99)。与较低的百分位数相比,这些具有一些不期望的特性。此外,人们从一组数据中计算百分位数的简单方法并不完美,如果我们愿意增加一点复杂性,还可以改进。关于这个主题有一篇 arxiv 论文,在结论部分有很多数学内容。
I)中间值和其他百分位数
照片由 Josh Harper 在 Flickr 上拍摄
中位数是一个非常简单的概念。将数据集或分布从中间分开的值。分布的一半概率质量(或数据中的一半样本)低于中位数,一半高于中位数。这个可以一概而论。我们也可以问一个点,30%的数据在它下面。一般来说,数据中 x%的数据低于它的点被称为第 x 百分位(因此第 50 百分位是中间值)。
II)有限样本和形式理论
形式的理论是一个来自柏拉图的想法,柏拉图认为物质世界不像永恒的、绝对的、不变的想法或形式那样真实或真实。我们在物质世界中看到的任何东西都不过是对这些形式的不完美的模仿。在统计学中,这些形式是潜在的概率分布,永远无法触及。我们能看到的只是这些分布产生的数据。我们从有限的真实世界样本中推断出的任何东西都只是对产生样本的分布的真实性质的估计。
分布有许多特性,百分位数是其中的一部分。我们如何估计分布的百分位数(或其他属性)?从分布中抽取一个样本(我们假设这是可能的),并将其压缩成一个单一的描述性统计。描述性统计是将观察样本转换成单个数字的函数(详细处理见此处)。百分位数就是一个例子;样本均值是另一个。那么,什么样的描述性统计对于百分位数是最好的呢?
II-A)估算百分位数
先说中位数。同样,它是这样一个点,一半分布在它的下面,一半在它的上面。如果我们知道分布,它就是在 0.5 计算的反 CDF。这是因为分布的 CDF(或累积分布函数)将该分布可以接受的任何值作为输入,并返回该分布低于该值的概率质量。所以,这个函数的反函数将把概率质量作为输入,把我们得到的低于它的概率质量作为输出。在 0.5 处的反向 CDF 将是分布的点,使得一半的概率质量低于它,或中值。
但这是在我们知道分布的反向 CDF,或者可以得到分布本身的情况下。实际上,我们只是从分布(比如说x1,x2,…,xn)中得到几个样本(比如说 n )。为了估计样本的 x 百分位数,一个合理的做法是找到一个点,使得其中的 x %在该点以下,其余的在该点以上。
为此,我们可以对样本进行分类。
- 这个排序列表中的第一个样本(称之为 X_(1) )或者是 X_1,X_2,… 的最小值,没有比它更小的了。因此,它应该是第 0 百分位或最小值的一个很好的估计器。
- 排序列表中的第二个样本(称之为 X_(2) )恰好具有比它小的( n-1) 个样本中的一个。换句话说, 100/(n-1) 百分比的样本低于它,因此它应该对第 100/(n-1) 百分位数进行很好的估计。
- 第三个样本的 200/(n-1) 百分比低于它,依此类推。
- 第 i 个样本( X_(i) )具有其下样本的(I-1) 100/(n-1)*%。
脚注-1:如果你真的在乎效率,可以避免排序,使用快速选择算法在 O(log(n)) 时间内找到所需的订单统计。
X_(1),X_(2),…X_(n) 被称为顺序统计量,它们都是一种描述性统计量(因为它们取整个样本并给出一个数字)。
它们代表的顺序统计量和百分位数。
问题是,这些顺序统计量将只给出( *i-1)100/(n-1) 形式的百分位数。如果 n=11 例如, X_(1) 是第 0 百分位, X_(2) 是第 10 百分位, X_(3) 是第 20 百分位,以此类推。所以我们只能得到 10 的倍数的百分点。如果我们想要 75%呢?我们知道 X_(8) 是第 70 百分位, X_(9) 是第 80 百分位。用他们的中点来估计 75 度是有道理的。
我们在这里做的是在已知的两个百分点之间进行线性插值。这是 python-numpy 中的 percentile 等所有库方法对不能很好地映射到顺序统计数据的百分点所做的事情(大多数情况下都是这样)。
一般来说,这种线性插值用于计算q-百分点(比如说*u;*此处 q 是 0 和 1 之间的分数,而不是百分比)结果在下面的公式(1)中。这里我们用 x 的小数部分来表示 {x} (所以 {1.2}=0.2 , {2.9}=0.9 等等)。这一点的证明(很容易理解)在附录 A 中给出。
等式(1-a):当我们进行线性插值时,q 百分位的一般表达式。
其中:
等式(1-b):等式 1-a 中 I 的定义。
让我们考虑一些简单的例子来看看这个公式的作用。当 q=.5 时,我们要中值。现在,如果 n 是奇数, {q(n-1)} 将为零,因为 q(n-1) 将变成整数。因此,只有等式(1)中的*X(I)*项将保留。对于 n=3 ,并且 q=.5 ,我们得到:
和
代入等式 1-a,得出:
这是有意义的,因为在一个由三个元素组成的有序数组中,第二个元素将是中间的一个元素,前后各有一个元素,将数组一分为二。
类似地,对于 n=4 和 q=0.5 ,我们将得到:
II-B)用指数模型研究偏差
我们在等式(1)中描述的是从某个分布的有限样本中计算q-百分点的方法。这是我们真实世界的描述性统计数据。当计算任何有限样本量时,这个描述性统计量本身具有某种分布, n 。也就是说如果我们做多次抽取 n 个样本并计算的实验,每次都会得到不同的答案。这个描述性统计的分布会有一些平均值,一些中位数等等。然后是我们从中抽取的 n 个样本的基础分布中值的实际值。描述性统计分布的平均值(此处为样本百分位数)和实际百分位数之间的差异被定义为描述性统计的偏差。在其他条件相同的情况下,我们希望这个偏差为 0 。不幸的是,对于大多数百分位数来说,情况并非如此。
让我们用一个简单的分布来演示这一点。因为百分位数通常用于延迟之类的东西,所以让我们使用一个只能取正值的分布。最简单的这种分布是指数分布。它只有一个参数(rate 参数),但是让我们通过将它设置为 1 (标准指数分布)来进一步简化事情。
事实上,我们有一个很好的表达式来描述它的顺序统计量。在维基百科关于顺序统计的文章中,我们得到了 Renyi 提供的关于指数分布的第 i 次顺序统计的公式(来自于 n 的样本量):
在这里, Z_j 是独立同分布指数本身,速率为 *1。*取两边的期望值,当基础分布为指数分布时,我们得到基于 n 个样本的顺序统计量的分布的期望值。
等式(2)指数分布的顺序统计量的期望值。
使用这个和等式(1),我们可以找到任何顺序统计量的分布的期望值,从而找到任何百分位。
为了找到q-百分位数,首先将等式 1-b 中的 i 代入等式(2)中,得到我们需要的两个有序统计量:
并且根据等式 1-a 将它们组合,除了 E(X_(i+1)) 中的最后一项不常见,意味着它仍然存在之外, {q(n-1)} 因子抵消了两者的所有常见项。
现在,我们可以用百分位数的真实值减去它,我们也知道标准指数分布的真实值:
并通过以下方式获得指数分布的 q 百分位中的偏差( b_q )(当使用线性插值策略时):
等式(3)当使用大多数软件包中使用的流行线性插值策略时,指数分布的 q 百分位偏差。
当抽取等式(3)中描述的大小为 n 的样本时,指数分布的 q 百分点的偏差在以下 python 函数中实现:
代码片段(1)测量指数分布的百分比偏差
除了测量偏差,上面的代码片段还可以帮助我们比较从有限样本中估计百分位数的各种策略的偏差。
例如,我们甚至需要线性插值吗?如果我们不做呢?当我们的q-百分位数落在 X_(i) 和 X_(i+1) 顺序统计量之间时,简单地使用 X_(i) 作为例子。它会不会对大样本量不再有影响?让我们绘制偏差作为线性插值和无插值策略的样本大小的函数,用于各种百分位数( q )和样本大小( n=15 )。
图 1:指数分布的不同百分位数的偏差
图 1 中的关键要点:
- 偏差在低百分位开始为负,逐渐增加到 0 (在中位数仍然为负)。在大约第 67 百分位时,它变为零。从那里开始,它急剧增加,在最右边大约为 1.5 (第 99 百分位)。请注意,指数分布的第 100 个百分位数(最大值)的偏差总是∞。这表明我们应该避免高百分位数,因为那里有很大的偏差。
- 对于线性插值策略,存在偏差变为零的百分点。这不是第 50 个百分位数(或中位数),那里仍然有一些负面的偏见。非常接近 66.67 百分位。
- 除了在不需要线性插值的百分点处,无插值策略比线性插值策略具有更差的偏差。
现在,让我们研究样本大小( n )增长时的行为,如下图 2 所示。
图 2:与图 1 相同,但是我们改变了样本大小(n)。
从图 2 的电影情节中可以得到的关键信息:
- 随着样本量的增加,两种策略的偏差都减小。然而,线性插值策略总是比无插值策略有优势。
- 随着样本量 n 的增加,偏差达到零的百分位数向 66.66%(或三分之二)收敛。但是即使对于小样本量,它也非常接近这个值。
- 随着样本大小的增加,线性插值和无插值策略之间的偏差差异存在周期性。不知道是什么引起的。如果你有想法,也许可以留下评论?
从上面两张图可以清楚地看出,线性插值策略总是比无插值策略好。但是,在减少偏见方面,有没有其他更好的策略呢?事实上,至少对于指数分布来说,有一个完美的策略。
线性插值的替代方法
注意线性插值没有什么特别的,只是简单直观而已。我们可以同样容易地在 X_(i) 和 X_(i+1) 之间进行另一种插值。
我们可以使用等式(3)来提出消除偏差的策略,而不是简单地测量偏差。负责线性插值的项是 {q(n-1)}。让我们用其他的因子来代替它,然后,我们可以明确地选择 f,以消除指数分布任何百分位的偏差。
等式(4)插值因子 f,用于消除指数分布任何百分位的偏差。
这个想法在下面的 python 方法中实现,该方法给出了给定百分位、 q 和样本大小、 n 的插值因子 f :
代码片段(2):实现“低偏差插值”策略。这是流行的线性插值策略的竞争对手。
让我们称这个策略为“低偏差插值”策略。在图 1 和图 2 的曲线图中描绘这种策略并没有多大意义,因为根据其定义,它只是紧挨着 x 轴。
只有当我们从指数分布中抽取样本时,这个零偏差结论才是正确的,但如果该分布是其他分布,则不是正确的(因为在推导它时使用的所有数学都假设了指数分布)。然后将这种“低偏差插值策略”与针对其他底层分布的无处不在的标准“线性插值策略”进行比较将会很有趣(我们可以放弃“无插值策略”,因为它明显不如标准线性插值策略)。
我们将在下一节中这样做,但我们没有其他分布的顺序统计的封闭形式(指数分布是少数存在封闭形式的分布之一)。所以,我们不得不求助于模拟。
III)代码和视觉模拟
詹姆斯·哈里逊在 Unsplash 上拍摄的照片
III-A)平行宇宙的无限矩阵
从有限的样本量(比如说 n )进行估计的问题是,你的估计是有噪声的。如果你重复这个实验,你会得到不同的估计。这是一个问题,因为科学的基本租户是,结论应该是可重复实验验证的。
处理不确定性的方法是研究与不确定性相关的基本分布。我们可以想象平行宇宙,其中生成底层数据的过程完全相同,并且基于 n 个样本(独立且同分布)的实验在每个宇宙中进行。所有的数据都存储在一个巨大的矩阵中。来自第一个宇宙的数据位于矩阵第一行的数组中,来自第二个宇宙的数据位于第二行的数组中,依此类推,如下图所示。
然后,我们可以计算每个宇宙中的百分位数或其他描述性统计数据,并沿着列折叠矩阵。我们将留下一个由 m 个数据点组成的数组,代表我们的汇总统计在宇宙中的分布。我们可以让 m 尽可能大,这样我们就可以研究从小样本( n )计算的汇总统计分布的行为。例如,我们从 100,000 个平行宇宙中的各种样本大小中找到 Lomax 分布的估计中值( m ),并将这些中值绘制在下图 3 的直方图中。我们还有一条黄线,描绘了这个洛马克斯分布的中间值的真实值。我们可以看到跨越平行宇宙的估计值的平均值远离真实的中值(但是随着我们增加 n 而变得更接近),但是跨越中间值的平行宇宙的中值总是在实际中值的正上方。稍后我们将对此进行更深入的探讨。
图 3:不同样本量的 Lomax 分布的计算中间值分布。
对于一些汇总统计数据,某些结论是显而易见的。例如,考虑样本均值。首先对每一列取平均值,然后对得到的数组的行取平均值,这与对所有的 m×n 条目取平均值是一样的。由于 m→∞ ,我们可以调用大数定律,该定律认为这个平均值将与所有这些数字产生的分布的真实平均值相同。因为这正是无偏的定义,我们已经证明了样本均值总是无偏的,无论基础分布如何(只要分布的均值存在)。
对于百分位数,事情并不那么明显。例如,与样本均值不同,如果我们首先取每个 m 数组的中值,然后取所有 m 结果条目的中值或均值,这与一次取所有 m×n 数的中值是不同的。所以,是时候使用核选项了,模拟。我们将模拟本节中描述的 m×n 数(其中 m 非常大),然后通过图表得出关于百分点的各种结论。
III-B)模拟矩阵
马库斯·斯皮斯克在 Unsplash 上拍摄的照片
我在下面提供了 python 模拟器的基本版本(以及详细的注释),以演示我们描述的模拟是如何工作的。
代码片段(3)模拟一个非常大的平行宇宙矩阵。
在第二节中,我们得到了广泛使用的线性插值策略下指数分布的偏差的封闭形式。为了热身,让我们从指数模拟,看看我们的模拟器是否工作。
但是为什么仅仅停留在偏差上,我们还可以绘制一系列其他的度量标准。我们将为每个百分点(以及各种基本分布)绘制图表:
- 两种策略的偏差。
- 标准偏差:了解我们的估计在平行宇宙中有多大差异。我们不希望这个价格太高。
- 中位数的差异:我们描述了样本均值是真实均值的无偏估计量(根据大数定律)。另一方面,样本中位数是真实中位数的有偏估计量。也就是说,如果我们取平行宇宙的中间值的平均值,我们会得到与真实中间值不同的结果。有人会说这对中间值不公平。为什么要取平行宇宙的平均值?为什么不是中间值呢?当我们这样做的时候,中位数(在平行宇宙中)就变成了真正的中位数。我们将为中位数证实这一点,但也为其他百分位数看看它。我们称这种差异为“DelMedian”。
- 均方差:在偏差和方差之间经常有一个权衡,一个策略可能有较高的偏差,但方差较小。一个流行的做法是将它们合并成一个称为均方误差的单一指标。我们也会策划这个。
在下面的图 3 中,我们展示了这四个指数分布图。
图 4:从指数分布生成数据时,线性插值策略和低偏置策略的比较。
图 4 中的关键要点:
- 两种插值策略的偏差在顶部图中。当数据从指数分布生成时,低偏差策略具有零偏差,因为这正是它的设计目的。因此,黄线环绕 x 轴。另一方面,线性插值策略的偏差仅在第 66 百分位附近为零,并且对于高百分位来说非常高(我们在下图中上升到第 95 百分位)。
- 在第二个图中,我们取平行宇宙中计算出的百分位数的中间值,并取该百分位数真实值的差值。该图的行为类似于偏差图(是平行宇宙平均值的差异,而不是中值)。除了第 50 百分位附近的窄带(用两条红线标记)之外,低偏差策略的性能优于线性插值策略。
- 第三个图显示了两种策略的标准偏差。对于高百分位数(大约从第 85 位开始),低偏差策略的标准偏差高于线性插值策略的标准偏差。在此之前,两者颇为相似。
- 第四个也是最后一个图比较了两种策略的均方误差(MSE)。对于高百分位数(80+),这是由方差决定的,因此看起来非常像标准差图(第二个)。对于从低值到大约 60 的百分位数,MSE 由偏倚决定。因此,在这个指标上,低偏差策略比标准线性插值策略稍好。
这都是针对指数分布的,但这对于线性插值策略是不公平的,因为低偏差策略是在此基础上训练的。现在让我们为不同的分布绘制相同的图。我选择了对数正态分布,因为它也模拟了从 0 到 ∞ 的延迟。它比指数分布有更重的尾部。大多数结论仍然有效,并继续适用于各种其他分布(我没有包括这里的所有实验),包括均值爆炸的重尾分布(例如:Lomax 分布)。你可以自己玩代码。具有所有附加功能的完整版本是这里(首先查看代码片段-3 以了解发生了什么)。
图 5:与图 3 相同,但是分布从指数分布切换到对数正态分布。
图 5 中的关键要点:
- “低偏差策略”的偏差现在对于所有百分位数(尤其是高百分位数)都不为零。然而,就偏差而言,对于大多数百分位数,它仍然比标准线性插值策略好得多。因此,低偏置策略名副其实。另一个观察结果是低偏置策略的偏置与线性插值策略的偏置具有相反的符号。
- 正如指数分布一样,对于高百分位数(也是 80+),低偏差策略比线性插值策略具有更高的方差。
对于标准差和 MSE,其行为与我们对指数分布的行为非常相似。
总之,“低偏差策略”具有更好的特性(偏差、MSE 等。)对于我测试的所有分布,只要你计算的百分位数低于 60(包括最常用的中位数)。对于更高的百分位数,它继续是更好的偏差标准。
在所有这些模拟中观察到,第二个图显示了中位数的跨宇宙的中位数始终是真实的中位数(对于线性插值策略,第二个图似乎总是通过 (0,0) ,也参见图 3)。这是普遍适用的吗?关于这一利用测试版的优雅证明,见本帖(Stats stack exchange;“大量中位数的中位数是否总是等于真中位数”)。
四)结论
这篇文章的要点是:
- 对于取正值的分布(如延迟、收入等。)避免使用高百分位数(90+)。它们有很大的方差和很大的偏差,这使得它们几乎没有用,除非你有一个非常大的样本量。
- 就像均值取决于真均值一样,中值取决于真中值。因此,虽然样本中值是真实中值的有偏估计,那只是因为我们取了平均值(根据偏差的定义)。
- 用于估计不适合顺序统计的百分位数的线性插值策略不一定是我们能做到的最好的。在本文中,我们提出了一个替代策略,消除了指数分布简单情况下的偏差。在偏差和均方误差方面,对于各种百分位数和分布,所得到的插值策略优于线性插值策略。当你计算第 60 个或更低的百分位数时,尤其如此。
下面是一篇有更多细节的论文:【2201.01421】用指数模型(arxiv.org)减少分位数估计中的偏差和方差。
如果你喜欢这个故事,成为推荐会员:)
https://medium.com/@rohitpandey576/membership
附录
a)对精确的百分位数估计进行线性插值
在大小为 n 的样本中,q-百分位是顺序统计量 X_(i) ,如果:
如果我们幸运的话, q(n-1) 将是一个整数,那么 q- 百分位将很好地位于顺序统计量( X_(i) )上,并且等式成立。但是一般来说,我们总是可以选择两边的发言权,这将允许我们为任何 q 找到一个 i 。
但是,对应于 i 的顺序统计量不会对应于我们想要的精确百分位数。不过没关系,我们知道百分位数 X_(i) 对应的和 X_(i+1) 对应的比高 1/(n-1)。
我们现在可以通过使斜率相等来进行线性插值(如果百分位数 q 是 T30 u T31):
重新排列术语,
如果我们用 x 的小数部分来表示 {x} (所以 {1.2}=0.2 , {2.9}=0.9 等等),并注意到:
我们可以写:
这与等式(1)相同。
心脏病分类—第二部分
分类加上使用集成方法实现约 92%的总体准确度得分
作为我上一篇文章的后续(在这里找到),我将在这里展示我使用 UCI 的心脏病数据集建立分类模型的步骤,以及利用集成方法实现更好的准确性评分。
通过创建能够更准确地对心脏病进行分类的合适的机器学习算法,将对卫生组织以及患者非常有益。
我们开始吧!
首先,我导入必要的库,并读入清理过的库。csv 文件:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from collections import Counter
from sklearn.preprocessing import StandardScaler
# data splitting
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
# data modeling
from sklearn.metrics import confusion_matrix,accuracy_score,roc_curve,roc_auc_score,classification_report,f1_score
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from xgboost import XGBClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
#ensembling
from mlxtend.classifier import StackingCVClassifier
import xgboost as xgb
import itertools
from sklearn.dummy import DummyClassifier
from sklearn import metricsdf=pd.read_csv('Data/cleaned_df.csv',index_col=0)
接下来,我执行了训练测试分割,并对我们的数据进行了缩放。回顾一下,我们必须训练-测试-分割我们的数据,以评估我们的模型,缩放我们的数据使我们的自变量的值的范围正常化。
y = df["target"]
X = df.drop('target',axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state = 0)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
然后,我使用 sklearn 的 DummyClassifier 来确定我们的基线准确性——即使只是猜测,也应该达到的成功率。
dummy_clf = DummyClassifier(strategy="stratified")
dummy_clf.fit(X_train, y_train)
DummyClassifier(strategy='stratified')
dummy_clf.predict(X_test)
dummy_clf.score(X_test, y_test)
这给了我们 49.18%的准确性,这是一个有用的衡量比较我们的模型。
接下来,我采用了不同的机器学习模型,以找出哪种算法的准确度最高。
- 逻辑回归
- k-最近邻
- 朴素贝叶斯
- 随机森林分类器
- 极端梯度增强
- 决策图表
- 支持向量分类器
逻辑回归
#INSTANTIATE LOGISTIC REGRESSION
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
y_pred_log = logreg.predict(X_test)
lr_acc_score=metrics.accuracy_score(y_test, y_pred_log)
lr_f1_score=metrics.f1_score(y_test, y_pred_log)
lr_conf_matrix = confusion_matrix(y_test, y_pred_log)
# checking accuracy
print('Test Accuracy score: ', lr_acc_score)
print('Test F1 score: ', lr_f1_score)
print("confusion matrix")
print(lr_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_log))
作者图片
k-最近邻
#INSTANTIATE KNN MODEL
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
# make class predictions for the testing set
y_pred_knn = knn.predict(X_test)
knn_acc_score=metrics.accuracy_score(y_test, y_pred_knn)
knn_f1_score=metrics.f1_score(y_test, y_pred_knn)
knn_conf_matrix = confusion_matrix(y_test, y_pred_knn)
# checking accuracy
print('Test Accuracy score: ', knn_acc_score)
print('Test F1 score: ',knn_f1_score )
print("confusion matrix")
print(knn_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_knn))
作者图片
决策图表
# INSATNTIATE DECISION TREE MODEL
tree = DecisionTreeClassifier()
tree.fit(X_train, y_train)
y_pred_tree = tree.predict(X_test)
tree_acc_score=metrics.accuracy_score(y_test, y_pred_tree)
tree_f1_score=metrics.f1_score(y_test, y_pred_tree)
tree_conf_matrix=confusion_matrix(y_test,y_pred_tree)
# checking accuracy
print('Test Accuracy score: ', tree_acc_score)
print('Test F1 score: ', tree_f1_score)
print("confusion matrix")
print(tree_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_tree))
作者图片
随机森林
#INSTANTIATE RANDOM FOREST MODEL
rfc = RandomForestClassifier()
rfc.fit(X_train, y_train)
y_pred_forest = rfc.predict(X_test)
rfc_acc_score=metrics.accuracy_score(y_test, y_pred_forest)
rfc_f1_score = metrics.f1_score(y_test, y_pred_forest)
rfc_conf_matrix=confusion_matrix(y_test,y_pred_forest)
# checking accuracy
print('Test Accuracy score: ', rfc_acc_score)
print('Test F1 score: ', rfc_f1_score)
print("confusion matrix")
print(rfc_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_forest))
作者图片
极端梯度推进
# Instantiate the XGBClassifier: xg_cl
xg_cl = xgb.XGBClassifier(learning_rate=0.01, n_estimators=10, seed=25)
# Fit the classifier to the training set
xg_cl.fit(X_train,y_train)
# Predict the labels of the test set: preds
y_pred_xgb = xg_cl.predict(X_test)
xgb_acc_score=metrics.accuracy_score(y_test, y_pred_xgb)
xgb_f1_score = metrics.f1_score(y_test, y_pred_xgb)
xgb_conf_matrix=confusion_matrix(y_test,y_pred_xgb)
# Compute the accuracy: accuracy
# checking accuracy
print('Test Accuracy score: ',xgb_acc_score)
print('Test F1 score: ', xgb_f1_score)
print("confusion matrix")
print(xgb_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_xgb))
作者图片
朴素贝叶斯
nb = GaussianNB()
nb.fit(X_train,y_train)
y_pred_nb = nb.predict(X_test)
nb_conf_matrix = confusion_matrix(y_test,y_pred_nb)
nb_acc_score = metrics.accuracy_score(y_test, y_pred_nb)
nb_f1_score=metrics.f1_score(y_test, y_pred_nb)
print('Test Accuracy score: ',nb_acc_score)
print('Test F1 score: ', nb_f1_score)
print("confusion matrix")
print(nb_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_nb))
作者图片
支持向量分类器
svc = SVC(kernel='rbf', C=2)
svc.fit(X_train, y_train)
y_pred_svc = svc.predict(X_test)
svc_conf_matrix = confusion_matrix(y_test, y_pred_svc)
svc_acc_score = metrics.accuracy_score(y_test, y_pred_svc)
svc_f1_score = metrics.f1_score(y_test, y_pred_svc)
print('Test Accuracy score: ',svc_acc_score)
print('Test F1 score: ', svc_f1_score)
print("confusion matrix")
print(svc_conf_matrix)
print("\n")
print("Accuracy of Support Vector Classifier:",svc_acc_score,'\n')
print(classification_report(y_test,y_pred_svc))
作者图片
正如你在上面看到的,我打印了每个模型的准确度分数和 F1 分数。这是因为我不确定哪个指标最适合我的业务案例。在阅读了 Purva 的这篇伟大的文章后,我决定使用准确性作为我的分类标准,因为在类别分布上没有很大的差异,并且因为在确定谁有或没有心脏病时,真正的积极和真正的消极很重要。
此外,我们看到上面的准确度分数在 70-80 之间,我们如何提高这个准确度分数?我们可以用合奏法!集成方法是创建多个模型并组合它们以产生改进结果的技术。与单一模型相比,集成方法通常表现更好。有不同类型的集合方法可以被利用,关于集合方法的更多信息请参见这篇文章。
对于当前的项目,我使用了一个堆叠 cv 分类器,它通过一个元分类器组合了多个分类模型,并使用交叉验证来为二级分类器准备输入数据。对于分类器,我检查了每个模型的准确度分数:
model_ev = pd.DataFrame({'Model': ['Logistic Regression','Random Forest','Extreme Gradient Boost',
'K-Nearest Neighbour','Decision Tree','Naive Bayes', 'Support Vector Classifier'], 'Accuracy': [lr_acc_score,
rfc_acc_score,xgb_acc_score,knn_acc_score,tree_acc_score,nb_acc_score, svc_acc_score]})
model_ev
作者图片
然后,我选择了表现最好的 3 个模型,并将它们输入到堆叠 cv 分类器中:
scv=StackingCVClassifier(classifiers=[logreg,nb,svc],meta_classifier=nb,random_state=22)
scv.fit(X_train,y_train)
scv_predicted = scv.predict(X_test)
scv_conf_matrix = confusion_matrix(y_test, scv_predicted)
scv_acc_score = accuracy_score(y_test, scv_predicted)
scv_f1_score = f1_score(y_test, scv_predicted)print("confusion matrix")
print(scv_conf_matrix)
print("\n")
print("Accuracy of StackingCVClassifier:",scv_acc_score*100,'\n')
print(classification_report(y_test,scv_predicted))
作者图片
如上所述,我们使用堆叠 cv 分类器获得了大约 92%的准确率。
让我们对系综模型的混淆矩阵有一个更好的了解
作者图片
正如我们所看到的,集合模型稍微超出了非主导类的预测。
接下来,让我们绘制所有模型的 ROC 曲线。
# Generate ROC curve values: fpr, tpr, thresholds
fpr_log, tpr_log, thresholds_log = roc_curve(y_test, y_pred_log)
fpr_knn, tpr_knn, thresholds_knn = roc_curve(y_test, y_pred_knn)
fpr_tree, tpr_tree, thresholds_tree = roc_curve(y_test, y_pred_tree)
fpr_rfc, tpr_rfc, thresholds_rfc = roc_curve(y_test, y_pred_forest)
fpr_xgb, tpr_xgb, thresholds_log = roc_curve(y_test, y_pred_xgb)
fpr_nb, tpr_nb, thresholds_log = roc_curve(y_test, y_pred_nb)
fpr_svc, tpr_svc, thresholds_log = roc_curve(y_test, y_pred_svc)
fpr_ens, tpr_ens, thresholds_ens = roc_curve(y_test, scv_predicted)# Plot ROC curve
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_log, tpr_log,label = 'Logistic')
plt.plot(fpr_knn, tpr_knn,label = 'KNN')
plt.plot(fpr_tree, tpr_tree,label = 'Decision Tree')
plt.plot(fpr_rfc, tpr_rfc,label = 'Random Forest')
plt.plot(fpr_xgb,tpr_xgb,label= 'XGB')
plt.plot(fpr_nb,tpr_nb,label= 'Naive Bayes')
plt.plot(fpr_svc,tpr_svc,label= 'Support Vector Classifier')
plt.plot(fpr_ens, tpr_ens,label = 'Ensemble')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.title('ROC Curve no GridSearch')
plt.show()
作者图片
从我们的可视化中,我们可以清楚地看到集合模型在我们测试的所有模型中表现最好。
最后,我计算了特征重要性,这是根据独立变量在预测目标变量时的有用程度给它们打分。
feature_importance = abs(logreg.coef_[0])
feature_importance = 100.0 * (feature_importance / feature_importance.max())
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + .5featfig = plt.figure()
featax = featfig.add_subplot(1, 1, 1)
featax.barh(pos, feature_importance[sorted_idx], align='center')
featax.set_yticks(pos)
featax.set_yticklabels(np.array(X.columns)[sorted_idx], fontsize=10)
featax.set_xlabel('Relative Feature Importance')plt.tight_layout()
plt.show()
作者图片
从上图可以看出,变量 ca 对预测一个人是否患有心脏病最有影响。变量 ca 指荧光镜着色的主要血管数(0-3)。主要血管的数量越少,流向心脏的血液量就越少,增加了心脏病的发病率。
摘要
从这个分类项目中,我们可以看到,与使用单独的分类模型相比,使用堆叠 cv 分类器提高了整体准确性。我们的基本模型表现为大约 49%,而我们的集合模型表现为大约 92%的准确性。我还试图使用网格搜索方法来改进单个模型,并使用堆叠 cv 分类器,但只能达到与当前集成模型相同的精度。
感谢您的阅读:)所有代码都在我的 GitHub 上!
心脏病分类项目—第一部分
对 UCI 心脏病数据集的探索性数据分析
比尔·牛津在 Unsplash 上的照片
在美国,心血管疾病或心脏病是女性和男性以及大多数种族/民族的主要死亡原因。心脏病描述了一系列影响心脏的情况。心脏病范围内的疾病包括血管疾病,如冠状动脉疾病。根据疾病预防控制中心的数据,每年大约有四分之一的死亡是由于心脏病。世卫组织指出,人类的生活方式是这种心脏问题背后的主要原因。除此之外,还有许多关键因素提醒人们,这个人可能有患心脏病的机会,也可能没有。
我们将使用在这里发现的 UCI 心脏病数据集进行探索性数据分析(EDA),在第二部分中,我们将构建分类模型,并使用集成方法来产生高度精确的模型。在目前的数据集中,这项研究的出版物包括 303 名患者,并从 76 个与预测心脏病相关的特征中选择了 14 个。
变量描述
- 年龄:以年为单位的年龄
- 性别:性别(1 =男性;0 =女性)
- cp:胸痛类型—值 1:典型心绞痛,值 2:非典型心绞痛,值 3:非心绞痛性疼痛,值 4:无症状
- trestbps:静息血压(入院时单位为毫米汞柱)
- chol:血清胆固醇,单位为毫克/分升
- fbs:(空腹血糖> 120 mg/dl) (1 =真;0 =假)
- restecg:静息心电图结果-值 0:正常,值 1:ST-T 波异常(T 波倒置和/或 ST 抬高或压低> 0.05 mV),值 2:根据 Estes 标准显示可能或明确的左心室肥大
- thalach:达到最大心率
- exang:运动诱发的心绞痛(1 =是;0 =否)
- oldpeak =运动相对于休息诱发的 ST 段压低
- 斜率:峰值运动 ST 段的斜率-值 1:上坡,值 2:平,值 3:下坡
- ca:荧光镜染色的主要血管数(0-3)
- thal: 3 =正常;6 =修复缺陷;7 =可逆转缺陷
- 目标:1 =疾病,0 =无疾病
变量类型
- 连续-年龄,trestbps,chol,thalach,oldpeak
- 二进制—性别、fbs、exang、目标
- 分类— cp、restecg、斜率、ca、thal
让我们从 EDA 开始吧!
首先,我们导入必要的库并读入数据集
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.graph_objects as go # To Generate Graphs
import plotly.express as px # To Generate box plot for statistical representation
%matplotlib inline
import plotly.express as pxdf=pd.read_csv('heart.csv')
df.head()
作者图片
上面提供了变量的描述,只是为了重申,目标是我们的因变量,其中 0 =无心脏病,1 =心脏病。
让我们检查是否有任何错误数据值,以便分类变量具有正确的类别数,如上所述。检查完所有变量后,我们发现 thal 和 ca 各有一个额外的类别。我们将用 NaN 值替换这些值,然后用中值替换这些值
df.thal.value_counts()
#3 = normal; 6 = fixed defect; 7 = reversable defect# OUTPUT
2 166
3 117
1 18
0 2
Name: thal, dtype: int64# Replace 0 with NaN
df.loc[df['thal']==0, 'thal'] = np.NaNdf.ca.value_counts()
# number of major vessels (0-3) colored by flourosopy# OUTPUT
0 175
1 65
2 38
3 20
4 5
Name: ca, dtype: int64# Replace 4 with NaN
df.loc[df['ca']==4, 'ca'] = np.NaN# Replace NaN with median values
df=df.fillna(df.median())
接下来,让我们通过可视化箱线图来检查异常值
作者图片
从这个图像中我们可以看到, chol 有一个极值,我们将用它的中值来代替。
现在,我们将使用 plotly 创建更多的可视化来更好地理解数据。首先让我们看看我们的目标变量的分布:
y=df.target.value_counts()
x=['Disease','No Disease']fig=go.Figure(
data=[go.Bar(x=x,y=y,text=y, textposition='auto',)],
layout=go.Layout(title=go.layout.Title(text='Target Variable (Heart Disease) Distribution')))
fig.update_xaxes(title_text='Target')
fig.update_yaxes(title_text='Number of Individuals')
fig.show()
作者图片
存在轻微的类不平衡,但没有严重到需要上采样/下采样方法。
让我们看看数据集中年龄的分布:
fig = px.histogram(df, x='age',color_discrete_sequence=['coral'])
fig.update_xaxes(title_text='Age')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Age')fig.show()
作者图片
从上图中,我们可以看到当前数据集中的大多数患者年龄在 50-60 岁之间。
让我们看看性别在目标变量中的分布:
female=df.loc[df['sex']==0]
female_values=female.target.value_counts()
male=df.loc[df['sex']==1]
male_values=male.target.value_counts()
target=['No Disease','Disease']fig = go.Figure(data=[
go.Bar(name='female', x=female_values.index, y=female_values, text=female_values, textposition='auto'),
go.Bar(name='male', x=male_values.index, y=male_values, text=male_values, textposition='auto'),
])
fig.update_xaxes(title_text='Target')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Sex According to Target Variable')
fig.update_layout(barmode='group')
fig.show()
作者图片
从上图我们可以看出,在心脏病组(1)中,男性患者多于女性患者。
接下来,让我们看看胸痛或心绞痛( cps )在我们的目标变量中是如何变化的。当心肌没有获得足够的富氧血液时,就会发生心绞痛,导致胸部不适,通常还会蔓延到肩部、手臂和颈部。
cp=['Typical Angina','Atypical Angina','Non-Anginal Pain','Asymptomatic']
y1=df.loc[df['target']==0].cp.value_counts()
y2=df.loc[df['target']==1].cp.value_counts()fig = go.Figure(data=[
go.Bar(name='Disease', x=cp, y=y2),
go.Bar(name='No Disease', x=cp, y=y1)
])
fig.update_layout(barmode='group')
fig.update_xaxes(title_text='Chest Pain Type')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Target Variable According to Chest Pain Type')fig.show()
作者图片
从上图中可以看出,大多数非疾病患者经历了典型的心绞痛,与疾病患者相比,心绞痛被描述为胸闷。在经历过非典型心绞痛和非心绞痛的患者中,似乎也有一种平衡。
现在让我们看看空腹血糖( fbs )在目标变量中是如何变化的。空腹血糖是一项糖尿病指标,空腹血糖> 120 毫克/天被视为糖尿病(正确):
dis=df.loc[df['target']==1]
dis_values=dis.fbs.value_counts()
nodis=df.loc[df['target']==0]
nodis_values=nodis.fbs.value_counts()
target=['No Disease','Disease']
d=['False','True']fig = go.Figure(data=[
go.Bar(name='Disease', x=d, y=dis_values, text=dis_values, textposition='auto'),
go.Bar(name='No Disease', x=d, y=nodis_values, text=nodis_values, textposition='auto'),
])
fig.update_layout(barmode='group')
fig.update_xaxes(title_text='Fasting Blood Sugar (fbs)')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Target Variable According to Fasting Blood Sugar')fig.show()
作者图片
在这里,我们看到,与类 false 相比,类 true 的数量更低。这表明 fbs 可能不是区分心脏病患者和非疾病患者的强有力特征。
摘要
在本文中,我们展示了一些 EDA 技术,可以在 UCI 的心脏病数据集上进行,为建立分类模型做准备。我们还创建了一些可视化工具来进一步理解数据,并确定哪些变量可能对区分疾病和非疾病患者有影响。在第二部分,我将建立一个分类模型,并使用集成方法来创建一个更准确的模型。
感谢阅读:)所有代码都在我的 Github 上提供。
PyTorch 中使用变压器的心脏病分类
心脏病是一个重要的问题,深度学习可以解决问题。变形金刚是未来:当我们把一切结合起来会发生什么?
在本文中,将实现并讨论使用心电图(ECG/ EKG)数据的心房颤动(AF)分类系统。分类系统将是二元的(正常窦性心律,AF ),并将基于使用 PyTorch 框架的变压器网络。本文的结构如下:首先,将介绍手头的问题以及所用的数据;其次,将介绍网络的技术细节;第三,将介绍网络的实施和培训;最后,将介绍结果和讨论。这个项目的资源库可以在这里找到:https://github.com/bh1995/AF-classification。
心房颤动分类问题
心脏病是全球死亡的主要原因之一[1]。心脏病通常会导致心脏行为的不规则,称为心律不齐。在所有类型的心律失常中,心房纤维性颤动(AF)是最常见的心律失常,估计其在 2%至 4%的人群中流行;随着人口平均年龄的增加,预计将来流行率将线性增加。根据目前的统计数据,任何一个欧洲血统的人一生中患房颤的概率约为 37%[2]。标准的心脏监测技术是心电图(ECG/ EKG),它监测心脏中的电信号,因此对于临床医生诊断心律失常非常有用。这个项目的目的是利用真实的、公开可用的、已经被临床医生标记的心电图数据来训练深度学习模型。
本项目中使用的数据来自多个来源,即 2018 年中国生理信号挑战赛(CPSC2018)[3]、圣彼得堡英卡特 12 导联心律失常数据库[4]、佐治亚州 12 导联心电图挑战赛数据库(CinC2020)[5]、2017 年心脏病挑战赛生理网络计算(CinC2017)数据集[5]、背景心律失常数据库(CACHET-CADB)[6]。
所使用的数据源以不同的采样率收集他们的 ECG 数据,并且使用不同的设备(有些使用 Holter 监护仪,有些使用医院级 12 导联 ECG),这导致每个数据源的性质略有不同。为了增加深度学习模型的学习能力,明智的做法是以规范化的方式处理所有数据。在这个项目中,所有信号都使用了带通滤波器(FIR 滤波器),因此只保留了[0.5,40]范围内的频率。信号还以 300 Hz 的速率被重新采样,并被分成长度为 10 秒的单个片段(因此模型的每个输入是长度为 3000 个数据点的一维数组)。然后对每 10 秒的片段进行归一化,使得所有值都在 0 和 1 之间。下图显示了两个原始(raw)信号(一个 AF 和一个 normal)以及预处理后的两个相同信号。
显示房颤(左)和健康正常窦性心律(右)原始信号的图。
显示房颤(左)和健康正常窦性心律(右)的预处理信号的图。
第一幅图像中的信号图显示了标准、清晰的 10 秒长 ECG 记录。图中的 y 轴代表电压差,x 轴代表采样速率,本例中为 300 Hz。从图中可以看出,一个人的心脏电压与另一个人的不同。对于我们人类来说,显然是在 x 轴上寻找一种模式,而不是在 y 轴上看振幅。然而,深度学习模型以无偏见的方式计算特征,因此会天真地使用所有给定的信息(即使幅度通常与心律失常分类无关)。这就是为什么将数据标准化到给定的时间间隔(例如[-1,1]或[0,1])。上图显示了一个房颤的例子,这可以从一些心跳之间的不规则间隔中看出。这种情况是一个“简单”的例子,因为即使是业余爱好者也能清楚地看到 AF 信号的异常。
本项目使用的完整数据集可通过 链接 下载。数据全部经过预处理,以数组的形式保存在 .h5 文件格式中。下面的代码片段显示了如何加载数据集的示例。
为此项目加载数据集。
型号描述
本项目测试了两个模型,它们都遵循相同的基本架构,但使用不同的输入。第一种模型使用预处理的 ECG 信号作为其唯一的输入,而第二种模型使用预处理的 ECG 信号以及该信号的所谓 RRI (RR-interval)。RRI 是一个心跳和连续心跳之间的估计时间,以秒为单位。通过使用泛汤普金斯算法[10]估计信号中的 R 峰(每个心跳的中间位置),然后使用以下等式来计算 RRI。
其中 Rn 为给定峰值, fs 为频率(采样率)。为了保持模型的输入 RRI 序列的固定长度,使用总 RRI 的前 10 个,并且如果发现少于 10 个,则补零。
项目中使用的模型受到了[8]工作的启发。该模型由以下模块组成:1)由一系列卷积层组成的嵌入网络,2)变换器编码器层的堆叠,3)由一系列全连接层组成的分类头。模型架构和模型训练的代码可以在这里找到。
嵌入:嵌入网络将一维卷积应用于原始 ECG 信号,这导致一系列嵌入表示( x[0],…,x[n] )。这些嵌入的表示与位置编码( p[0],…,p[n] )相加,以表示每个序列的顺序,如原始 transformer 论文中所做的那样[7]。结果是位置编码嵌入, e = ( x[0]+p[0],…,x[n]+p[n] ),然后用作堆叠变换器编码器层模块的输入。
**转换器编码器层:**转换器模块由堆叠的转换器编码器层组成,其中每个编码器由多头自关注机制子层组成,经过反复试验,发现四个编码器层和头产生了良好的结果。同样,经过反复试验,编码器内的嵌入维数被选择为 64 ,编码器层内的前馈网络的维数被选择为 512 。转换器模块的输出是具有形状、[序列长度、批量大小、嵌入]的注意力权重的张量。必须以某种方式转换输出,以便将其输入分类头模块,即需要将其转换为形状[批量大小,嵌入]。尝试了两种方法,第一种是简单地取序列维度上张量的平均值,第二种是使用自我注意力集中层,如[9]的工作中所建议的。两种方法都表现出良好的性能,然而,利用自我注意池层产生了最好的结果。自我注意力集中层被应用于变换器模块的输出,该变换器模块产生嵌入,该嵌入是编码器序列中特征的学习平均。
**分类头:**自我注意力池的输出被用作最终分类头的输入,以产生用于预测的逻辑。最终的分类头是两个完全连接的层,中间有一个分离层。
培养
使用二进制交叉熵作为损失函数,AdamW 算法作为优化器来训练该模型( β1=0.9,β2=0.98,ε=10^(-9) )。10^(-3 的初始学习速率),并且使用学习调度器来在前 30 个时期之后开始每五个时期将学习速率降低 5%。该数据集总共有 52 370 个 10 秒长的 ECG 信号,其中正常与房颤标记的比例大致相等。随机选择数据集的 85% (44 514)用于训练,剩余的 15% (7 855)用于测试。使用的批量大小为 10,并且在云计算环境中使用特斯拉 P100 GPU 进行训练。
结果
两种模型的结果将在下面给出,首先是仅使用原始 ECG 信号的模型,然后是使用原始 ECG 信号以及该信号的 RRI 的模型。
使用原始 ECG 信号:
如下图所示,该模型显示了各时期的一致学习,没有任何相当大的过度拟合。测试准确度也持续增长。由于这项任务是对疾病的二元分类,敏感性和特异性可以说是一个更好的性能指标。训练结束时测试数据上的灵敏度和特异性分别为 85.6 和 92.7 。训练时间大约是每个时期 178 秒。
各时期的训练(橙色)和测试(蓝色)数据的损失曲线。
跨时期测试数据模型的准确性。
使用原始 ECG 信号和 RRI:
当在训练/推断期间使用 RRI 特征时,模型性能提高。下图显示,模型显示出明显的过度拟合迹象,但是,这种过度拟合不会对各时期测试数据的模型准确性产生负面影响。训练结束时测试数据的灵敏度和特异性分别为, 96.9 和 95.6 。训练时间大约是每个纪元 1550 秒。
各时期的训练(橙色)和测试(蓝色)数据的损失曲线。
跨时期测试数据模型的准确性。
结论
从结果可以清楚地看出,基于变换器编码器的网络在对 10 秒长的 ECG 信号中的 AF 进行分类方面工作良好。同样清楚的是,使用 RRI 特征以训练和推理时间增加近九倍为代价,提供了模型性能的巨大改进。这种时间增加归因于用于执行 R 峰检测的泛汤普金斯算法很慢的事实。
参考
[1]心脏病和中风统计 2018 年更新:来自美国心脏协会的报告。美国心脏协会,1,2018。
[2]与欧洲心胸外科协会(EACTS)合作制定的 2020 年欧洲心脏病学会房颤诊断和管理指南:欧洲心脏病学会(ESC)房颤诊断和管理特别工作组在 ESC 欧洲心律协会(EHRA)的特殊贡献下制定。欧洲心脏杂志,2020 年 8 月。ehaa612。
[3]刘芳芳、刘春燕、赵良英、张晓燕、吴晓林、徐晓燕、刘延林、马春燕、魏胜生、何志清、李俊卿和郭念英。一个用于评估心电图节律和形态学异常检测算法的开放式数据库。医学影像与健康信息学杂志,2018,8(7):1368–1373。
[4] Goldberger,a .,Amaral,l .,Glass,l .,Hausdorff,j .,Ivanov,P. C .,Mark,r .,& Stanley,H. E. (2000 年)。生理银行、生理工具包和生理网:复杂生理信号新研究资源的组成部分。循环[在线]。101 (23),第 e215–e220 页。
[5]佩雷斯·阿尔代·埃、古·阿、沙阿·阿吉、罗比肖·阿吉、黄艾、刘·阿吉、刘·阿吉、拉德·阿吉、埃罗拉·阿吉、塞耶迪·阿吉、李 q、沙尔马·阿吉、克利福德 GD 、雷纳·马。12 导联心电图的分类:2020 年心脏病学挑战中的生理网络/计算。生理测量。41 (2020).
[6] Devender Kumar、Sadasivan Puthusserypady 和 Jakob Eyvind Bardram。CADB 纪念印。2021 年 5 月 5 日。https://doi.org/10.11583/dtu . 14547264 . v1
[7]瓦斯瓦尼,a .,布雷恩,g .,沙泽尔,n .,帕尔马,n .,乌兹科雷特,j .,琼斯,l .,戈麦斯,A. N .,凯泽,l .,&波洛苏欣,I .注意力是你所需要的一切,。arXiv:1706.03762v5。
[8] A .纳塔拉扬,等…用于 12 导联心电图分类的宽深度变压器神经网络。 2020 年心脏病学计算,2020 年,第 1–4 页,doi: 10.22489/CinC.2020.107
[9]萨法里出版社,印度,m .,&赫尔南多,J…说话人识别的自我注意编码和汇集。arXiv:2008.01077v1
10 潘杰和汤普金斯。一种实时 QRS 检测算法。IEEE 生物医学工程汇刊,BME-32 卷,第 3 期,第 230-236 页,1985 年 3 月,doi: 10.1109/TBME.1985.325532
激烈的讨论:使用气候数据预测冲突强度
变更数据
使用一个世纪的气候变化数据建立一个机器学习模型来预测冲突的强度
图片来自 iStock,授权给 Richard Pelgrim
这个故事是追踪我第一个独立数据科学项目进展的系列报道的一部分。找到上一篇 这里 和 Jupyter 笔记本 这里 。
TL;博士;医生
一些研究人员推测,气候变化正在导致政治紧张局势加剧,因此正在推动世界各地武装冲突的增加。该项目试图建立一个机器学习模型,根据周围地区的可用降水和温度数据预测印度的冲突强度(以每天死亡人数衡量)(< 300km). The project concludes that 使用当地气候数据不可能准确预测冲突强度)。尽管如此,它还是偶然发现了一些有趣的信息。
问题是
气候变化越来越多地导致全球极端天气模式。这些极端天气情况,如高温、干旱、洪水等。在世界的一些地方,正导致大规模的人口流动和对土地和其他自然资源的竞争加剧。这种竞争可能导致政治紧张,并可能以武装冲突的形式出现。
这一领域的现有研究暗示了气候变化和武装冲突增加之间的可能关系;比如这里的和这里的。然而,大多数专家指出,这种关系在很大程度上仍然是推测性的,很难证明,因为还有许多其他因素推动冲突,如地缘政治和/或社会经济因素。
在这种背景下,我决定使用我的第一个顶点项目(作为跳板数据科学职业跟踪的一部分完成)来研究是否可以在气候测量和冲突强度测量之间建立直接关系。建立这种关系对以下方面很有价值:
- 说明了另一个尽快努力减缓气候变化原因,
- 预期人道主义援助和/或军事干预,以应对预期的冲突事态发展。
数据
该项目结合了来自两个独立数据集的数据:
- 乌普萨拉冲突数据计划全球武装冲突数据集,包含 1989 年至 2019 年间 220,000 多起冲突事件的信息,以及
- 全球历史气候网络数据集包含 1889 年至 2020 年间全球 115,000 多个站点的天气测量数据。
仅仅是绘制冲突事件和气象站就已经构成了一幅迷人的地图:
作者生成的图像
很明显,总的来说,**有很多冲突事件的国家只有很少的气象站,**除了像印度、南非和土耳其这样的少数国家。
浑身脏兮兮的
现在我们进入了项目中真正有肉和最令人满意的部分(记住:我喜欢肉丸——尤其是当它们出现在正确的地方时)。我在项目的探索性数据分析阶段花了 70 多个小时;掌握大型数据集,掌握用于处理空间数据的 geopandas 包,并找出哪些肉丸真正值得关注。指数学习曲线。
我将分享项目这一部分的三个很酷(也很重要)的发现:
肉丸# 1——气候数据的可用性
这是一个难以接受的事实,但对接下来的事情非常重要:不是所有的气象站都有全年的气候数据。一个气象站可能只记录了 20 年的降雨量,然后只记录了几年的平均温度,然后一段时间什么都没有…你明白了。
特别是 1950 年之前和 2012 年之后的几年显示覆盖面很差,这将影响我们能够对 1989 年至 2019 年之间发生的冲突事件进行的比较。
作者生成的图像
肉丸# 2——季节性高峰
第二个肉丸更有趣:绘制整个观察期(1989 年至 2019 年)内每月武装冲突事件的数量显示:
- 冲突事件数量的总体增加——这可能是由于实际冲突的增加或(更有可能)报道和记录的增加,以及
- 持续的季节性高峰
季节性天气模式会增加冲突事件的可能性吗?
作者生成的图像
肉丸# 3——地图的力量
这最后的肉丸特别给力。下面的地图显示了所有的冲突事件,按照事件发生的年份进行着色,标记的大小根据事件的总死亡人数而增加。图像中心巨大的紫色斑点是构成卢旺达种族灭绝事件的叠加。其他暴行,如斯雷布雷尼察大屠杀和 911 袭击也跳了出来。
作者生成的图像
我必须承认,当这个情节在凌晨 2 点出现在我的屏幕上时,我真的哽咽了。这尖锐地提醒我们地图传达信息的力量 和 事实上,我们用来指我们电脑上的大量信息的非个人化、枯燥的四个字母的单词总是与实际的人类生活(或死亡)联系在一起——换句话说:它很重要。
Hocus Pocus by Focus(歌唱印度)
如果你没有得到那个史诗般的亚文化参考,那么请暂停一下,进入这个链接,欣赏 6 分 42 秒改变人生的音乐插曲。
你回来了?
不用谢我。
当然,所有这些全球模式都很迷人,但在项目的这一点上,我被大量的意大利面条和可能的路线所困扰(事实证明,并非所有的意大利面条都通向罗马)。所以我决定将项目范围缩小到一个国家和一个焦点。是时候去印度了。
我选择印度作为案例研究,因为它有冲突和气候数据的必要重叠:15000 多起冲突事件和 3800 多个气象站。巨大的潜力……
….不是!事实证明,在 3800 多个气象站中,只有 25 个有足够的冲突事件发生年份的气候数据。幸运的是,这 25 个监测站均匀分布在全国各地,在每个可识别的冲突事件群附近至少有一个监测站。
作者生成的图像
我运行了一个 CkdTree 分类器 将每个冲突事件与这 25 个气象站中最近的气象站进行匹配。然后,我可以计算出一系列新的气候特征,让我们了解每个冲突事件周围地区的气候变化模式。
我们来关联一下。
需要另一个插曲吗?我明白你的意思,嘘——你知道三角形也是我最喜欢的形状。
深入研究我们的原始功能和新功能之间的关联揭示了三件重要的事情:
- 总死亡人数和任何气候特征(新的或旧的)之间没有明显的关联**。这意味着很难建立一个预测模型…**
- 在冲突事件的总死亡人数和持续时间(以天为单位)之间有一些关联**。这是有道理的——更长的冲突更有可能导致更多的死亡。**
- 气候特征几乎都是高度相关的。
作者生成的图像
死亡总数和持续天数都可以作为冲突强度的指标,这也是我们试图预测的。为了将这两者合并成一个变量,同时考虑到它们之间的相关性,我决定将我们的目标特征重新表述为死亡率:冲突事件每天的死亡人数。
我们的最终数据框架有 14364 个观察值和 33 个特征(1 个目标,32 个预测值)。
超级名模
我们现在准备开始构建我们的预测模型。我构建了 6 个不同的模型来比较性能:
- 一个虚拟回归变量,简单地预测每个冲突事件的平均死亡率——这将是我们用来比较实际模型性能的基线模型,
- 现成的线性回归模型
- 使用选择最佳特征优化的线性回归模型
- 现成的随机森林回归模型
- 使用超参数调谐优化的 RF 回归模型,以及
- 使用超参数调整优化的 Lasso 回归模型。
下图包含了一大串数字,基本上告诉我们,我还不如在第一步就停止了。出于所有实际目的,5 个机器学习模型中没有一个比基线模型做得更好,基线模型基本上只是一个有根据的猜测。
因此,该项目的结论是
使用选定的气候特征不可能准确预测印度的冲突强度。
关键要点
令人失望?一点点。出乎意料?不完全是。该领域的现有研究已经警告我们,这种关系将很难确定,在项目的 EDA 阶段生成的相关性热图基本上已经证实了这一点。
所以…浪费时间?肯定不是。这个项目给我们留下了一些重要的收获:
首先,气候数据本身可能不足以预测冲突强度,但可能证明是包含其他特征(社会经济、政治等)的冲突预测模型的有用补充。).与基线模型相比,预测能力略有提高;
其次,我认为最重要的发现之一是在这篇文章的顶部,在气象站和冲突事件的地图上。显而易见的是,武装冲突发生的地方和气候数据主要收集的地方不匹配。这是主张在世界上持续经历武装冲突的地区开展更多研究工作的有力理由。
下一步是什么?
当然,工作永远不会结束。
图片来自 https://giphy.com/memecandy/
我要说的是,这种当前模式有三种主要的改进方式:
首先是扩大项目的范围,不仅将印度的案例研究扩展到其他国家,也不仅仅使用气候数据来包括社会经济和政治因素。其他国家的模式可能更强,包括除气候数据之外的数据肯定会提高性能。
第二是获取额外的气候数据。我们看到,在印度的例子中,虽然我们一开始有近 4000 个气象站,但其中只有 25 个有我们感兴趣的年份的足够的气候记录。额外的数据将使气候模式的模型更加精细,这将大大提高模型的预测能力。
最后,重新构建分析并将有冲突的区域与没有冲突的区域进行比较将会很有趣。在目前的模型中,我们将冲突事件相互比较,但很可能在发生武装冲突的地区和没有发生武装冲突的地区之间存在更明显的差异。这意味着将我们的观察单位从“冲突事件”改为“国家”或其他单位区域。然后我们可以建立一个模型来预测每单位面积的事故数量。这将允许我们调查我们上面呈现的季节性峰值(如肉丸#1),这些峰值在 冲突事件计数 中,而不在死亡计数中。我的直觉是,如果我们以这种方式重新构建问题,可能会有更强的信号。
伙计们,就这样吧。如果您有任何问题或反馈,请联系我们,尤其是如果您是一位对该主题充满热情的数据科学家(或一般的研究人员),我很乐意与您联系!
下面是一个链接,链接到我对这个项目的介绍,请随时与任何人分享,它可能是有用的或有启发性的。
最后但同样重要的是,我要大声感谢我的导师盖伊·马斯卡尔一路走来给予我的宝贵支持和积极反馈!
你好,“Covid”世界:Python Dash 和 R Shiny 对比
比较 Dash 和 Shiny 在最简单但交互的仪表板实现中的差异
在数据科学领域,项目的最终目标通常是以某种仪表板或 web 应用程序来可视化您的结果。Python 和 R 这两种广泛使用的数据科学语言都有自己的包来解决这个问题。
r 有一个名为 Shiny 的主包,它使得直接从 r 构建交互式 web 应用程序变得容易。另一方面,Python 有几个根据项目强度而广泛使用的包。
Python web 应用程序的三个主要包是 Django、Flask 和 Dash。Django 是一个高级 Python Web 框架,它鼓励快速开发和干净、实用的设计。Flask 是一个轻量级的 web 应用程序框架。它旨在快速轻松地开始使用,并能够扩展到复杂的应用程序。
根据 Dash 网站的介绍:
Dash 基于 Flask、Plotly.js 和 React.js 编写,非常适合用纯 Python 构建具有高度自定义用户界面的数据可视化应用程序。它特别适合任何使用 Python 处理数据的人。
通过几个简单的模式,Dash 抽象出了构建基于 web 的交互式应用程序所需的所有技术和协议。Dash 非常简单,您可以在一个下午的时间里围绕您的 Python 代码绑定一个用户界面。
Shiny 和 Dash 都有一个共同的目标,那就是用最少甚至不需要像 JavaScript 这样的 web 开发技能来制作一个 web 应用仪表板。尽管两者都允许使用 JavaScript、HTML、CSS 栈进行更好的定制。
正如许多开发人员所知,每当你开始学习一门新的编程语言或工具时,你要做的第一件事就是尝试编写一个“Hello,World”程序。这只是简单地展示了语法的最简单形式和新语言的内部工作方式。
本文通过 Python Dash 和 R Shiny 之间的比较来比较这种想法,比较两种语言中非常简单的 dashboard web 应用程序。当然,它也是以新冠肺炎数据为中心的,就像过去一年世界其他地区一样。
免责声明:我对 Python 和 R 都有经验,但是我想在我相对公正地学习 Dash 和 Shiny 的同时写这篇文章,以便进行公平的比较。
Dash 和 Shiny 的交互式应用程序的准系统
Dash 和 Shiny 使用类似的结构,首先在组件的层次树中定义整体界面和页面布局。接下来是根据动作改变布局的函数。
我选择展示最基本的交互应用程序,因为没有交互就很难描述结构。
破折号
这是一个几乎一行一行找到的例子这里。值得注意的是,Dash 在该网站上发现了惊人的文档。
在这个例子中,我们可以看到第一步是如何声明app.layout
的,其中 HTML 部分是按照 web 应用程序从上到下的顺序定义的。有一个破折号核心组件(dcc
)接收文本,然后最后的html.Div
是输出文本。为了将这两者联系在一起,有一个@app.callback
,这就是 Dash 如何创建一个动作和反应。回调将组件 ID 和属性/值作为输入,并将其传递给函数,然后将结果返回给已定义的html.Div
组件。
发光的
这是一个同样简单,互动闪亮的应用程序。我们马上注意到一些相似之处。首先,如前所述,这两个程序都继承了相似的结构,首先定义 UI,然后定义反应性元素。一个不同之处是,对于这个闪亮的应用程序,所有输入都被传递给通用函数,每个输入都由input$input_value
调用。
作为一个快速的比较,我们可以看到 Shiny 可以用更少的代码和更简单的代码交付相同的功能。部分原因是 Dash 是在 Flask 上构建的,Flask 是无终结的,这意味着它更加开放,并且没有标准的构建方式,因为这是开发人员的决定。此外,从上面的例子可以看出,Dash 集成了更多的 HTML。
让我们通过添加一些数据来显示常用的元素,如图表、下拉菜单、地图和滑块,从而进一步深入这种比较。
元素比较
所有的代码都可以在我的 GitHub 这里 中找到,但是为了节省本文的篇幅,我将主要关注这些元素的具体代码。
条形图和下拉菜单
Dash 附带了一个核心组件库,允许轻松声明常见的 HTML 组件,如Dropdowns
或Graphs
。由于 Plotly 和 Dash 非常紧密地交织在一起,几乎所有的图表和图形都是用 Plotly 的graph_objects
完成的。因此,一旦选择了一个下拉值,数据集就会变成一个条形图,将阳性新冠肺炎病例叠加到测试总量上,以显示两者在 2020 年底之前如何随时间变化。
Plotly 的graph_objects
与 Dash 连接的一个便利之处是,你无需额外代码就能自动获得 Plotly 的特性。这包括缩放,悬停功能,悬停比较,下载选项等。
这个代码块描述了如何实例化一个下拉菜单,并使用 Python 和 Dash 显示一个条形图。
此代码生成下面的条形图,该条形图由下拉菜单值决定,用于描述单个特定状态或所有状态的合计。
仪表板下拉菜单和条形图仪表板示例
Shiny 也有一个简单的 UI 元素声明,但是在使用输入时,你必须将它存储在一个新的变量中,以便能够与其他元素进行比较。这是因为输入是电抗元素,不能与非电抗变量(如字符串)进行比较。
Shiny 的好处是大多数用 R 编写代码的人已经使用了ggplot2
包进行所有的绘图,所以很容易在 Shiny 应用程序中实现相同的绘图。
下面是一个类似程序的 R 实现,用于下拉菜单和条形图。
这段代码生成了闪亮的下拉菜单和条形图,以显示一段时间内的总数和阳性病例。
闪亮的下拉菜单和条形图仪表板示例
总的来说,下拉菜单在外观和功能上几乎是一样的。另一方面,我不得不给 Dash 一个现成的条形图,因为它附带了很多 Plotly 的有吸引力的特性。
旁白:有一个 Plotly R 库,但它不像 Dash 和 Plotly 那样自然地交织在一起。
地图和滑块
在本节中,我们将创建一个滑块,显示从新冠肺炎首次出现到 12 月 31 日的 2020 年的日期。然后,一旦选择了日期,我们将在美国地图上显示总病例汇总数据。Plotly 再次将 choropleth 地图作为其 graph objects 包的一部分。
滑块是另一个标准的dcc
元素,但是一个巨大的抱怨和不便是它不允许输入日期。因此,我们必须有点创意,将滑块用作从 0 开始的数字输入。然后,使用选择的值和datetime
Python 包,我们将这些天数添加到开始日期。也就是说,需要花更多的时间来确定哪些标记代表新的一个月的开始。
此代码块描述了如何实例化一个滑块,并使用 Dash 在选定的日期显示地图。
这将生成下面的图,该图显示了 choropleth US 图中按滑块选择的日期显示的所有测试用例。
Shiny 也有类似的实现,但是我找不到任何超级简单的方法来绘制美国地图。有几个不同的例子,他们使用了传单,但这似乎比我想要的简单地图有更多的定制。因此,我使用了来自城市研究所名为 urbnmapr 的 GitHub 包。
对于这个用例,我更喜欢 Shiny 的 slider,而不是 Dash 的,特别是因为它允许将日期作为值传入。因此,将选择的值传递给映射不需要预处理。此外,有一个动画选项,使地图可以逐步改变一天。
这个代码块描述了如何实例化一个滑块,并在选定的日期用 Shiny 显示一幅地图。
这将生成以下地图,该地图按滑块选择的日期显示 choropleth US 地图中各州的阳性病例总数。
结论
总的来说,我希望作为读者的你已经大致了解了如何为 Python Dash 和 R Shiny 制作简单的组件和反应式 web 应用程序。这是我的第一个正式项目,所以对我来说也是一个学习的过程。对于我最初的想法,我看到了两者在数据科学领域是如何有用的,并且从我目前的观点来看,它们可以互换,足以选择您喜欢的。也就是说,如果你更习惯使用 R,坚持使用它,Python 也是一样。我认为学习这两门课程会很有用。
也就是说,如果我必须选择一个继续,我可能会选择 Dash,原因如下。贯穿本文的第一个原因是,与 Plotly 交织在一起有很多优点,比如缩放、平移、悬停等。其次,Python 仍然是一种更受欢迎的语言,因此对于项目生命周期来说,用同一种语言继续仪表板阶段可能更容易。最后,Dash 是建立在 Flask 之上的,所以如果你想进一步扩展你的 web 应用来解决一个更大、更复杂的问题,你不必重启。
感谢大家的阅读!如果有什么让你惊讶或感兴趣的,请随时在评论中告诉我。😃
你好!我是 PAMI
面向数据科学的新模式挖掘 Python 库
图 1:跨越人工智能、数据挖掘、机器学习和深度学习的学习算法的广泛分类
大数据分析代表了一套发现隐藏在大型数据库中的知识的技术。这些技术可以大致分为四种类型:
- 模式挖掘—旨在发现数据中隐藏的模式
- 聚类—旨在对数据进行分组,使得组内的对象具有高的类内相似性和低的类间相似性。
- 分类——旨在从学习的模型中为测试实例找到合适的类别标签
- 预测—旨在从学习的模型中预测测试实例的值
如图 1 所示,模式挖掘和聚类是无监督学习技术,而分类和预测是监督学习技术。
一些 Python 库(例如,Sklearn、PyTorch、TensorFlow 和 Keras)已在文献中描述用于执行大数据分析。这些库主要关注聚类、分类和预测。据我们所知,不存在旨在发现隐藏在数据中的模式的 Python 库。有了这个动机,我们开发了一个新的 Python 库,叫做 PAMI。在这篇博客中,我们涵盖了以下主题:
- 什么是 PAMI?它的执照是什么?以及如何安装?
- PAMI 的组织结构是怎样的?
- 如何利用 PAMI 来发现频繁模式?
- 位置了解更多信息。
什么是 PAMI?它的执照是什么?如何安装?
PAMI 代表模式挖掘。这个库包含几个模式挖掘算法来发现隐藏在大量数据集中的知识。目前,PAMI 有 50 多种算法来寻找不同类型的基于用户兴趣的模式。示例包括频繁模式、相关模式、周期模式、频繁邻域模式和模糊周期模式。
PAMI 目前是在 GNU V3 许可下提供的。这个库的源代码可以在GitHub【3】获得。通过发出以下命令,可以从 PyPI 存储库直接安装 PAMI 库:
pip install -y pami
PAMI 的组织结构是怎样的?
PAMI 的算法是以分层的方式组织的。这个层次结构的格式是,
pami . pattern mining model . type of pattern . algorithm
- patternMiningModel —表示需要发现的模式类型,如频繁模式、相关模式、模糊频繁模式等。
- typeOfPattern 表示模式的分类。目前,PAMI 实施四种模式。(I)基本-查找数据中的所有模式,(ii)封闭-仅查找数据中的封闭模式,(iii)最大-仅查找数据中的最大模式,以及(iv)topK-查找数据中的前 k 个模式。
- 算法—表示用于发现模式的技术。
一个例子是
PAMI.frequentPattern.basic.FPGrowth
其中frequency pattern是模型, basic 是模式类型, FPGrowth 是挖掘算法。
如何利用 PAMI 来发现频繁模式?
频繁模式挖掘是大数据分析中一种重要的知识发现技术。它包括识别数据中频繁出现的所有项目集(或模式)。一个典型的应用是购物篮分析。它包括识别客户经常购买的项目集。频繁模式的一个例子是:
{Beer, Cheese} [support=10%]
上面的模式表明,10%的客户一起购买了商品“啤酒”和“奶酪”。这种信息对于用户放置产品和库存管理非常有用。关于频繁模式挖掘的更多信息可以在[5,6]找到。
我们现在使用 PAMI 图书馆和 Jupyter 笔记本一步一步地进行频繁模式挖掘。
- 点击此处【7】下载交易零售数据集。
- FP-growth 是一种著名的频繁模式挖掘算法。让我们首先通过在 Jupyter 中执行以下命令来导入这个算法:
from PAMI.frequentPattern.basic import FPGrowth as alg
3.通过提供文件、最小支持(minSup)和分隔符作为输入参数来初始化 FP-growth 算法。
obj = alg.FPGrowth('[transactional_retail.csv',100,'\t'](https://www.u-aizu.ac.jp/~udayrage/datasets/transactionalDatabases/transactional_retail.csv',100,'\t'))# '[transactional_retail.csv'](https://www.u-aizu.ac.jp/~udayrage/datasets/transactionalDatabases/transactional_retail.csv',100,'\t') is the input file downloaded from the URL
#100 is the minimum support count.
#\t is the separetor that exist between the items in a transaction
4.开始采矿过程
obj.startMine()
5.通过执行以下代码将模式保存在文件中:
obj.savePatterns('frequentPatters_100.txt')
# 100 is the minSup count
在输出文件中,比如 frequentPatters_100.txt,第一列是模式,第二列是支持。
6.用户可以通过执行以下代码将发现的模式作为数据帧读取:
df = obj.getPatternsAsDataFrame()
7.挖掘算法的运行时和内存要求可以通过执行以下代码得出:
print('Runtime: ' + str(obj.getRuntime()))
print('Memory: ' + str(obj.getMemoryRSS()))
上述步骤的完整代码如下所示:
from PAMI.frequentPattern.basic import FPGrowth as algobj = alg.FPGrowth('[transactional_retail.csv',100,'\t'](https://www.u-aizu.ac.jp/~udayrage/datasets/transactionalDatabases/transactional_retail.csv',100,'\t'))
obj.startMine()obj.savePatterns('frequentPatters_100.txt')
df = obj.getPatternsAsDataFrame()print('Runtime: ' + str(obj.getRuntime()))
print('Memory: ' + str(obj.getMemoryRSS()))
我在哪里可以找到更多关于 PAMI 的信息?
访问 https://udayrage.github.io/PAMI/index.html了解更多信息。
结论
在这篇博客中,我们讨论了不同类型的学习算法,并讨论了现有的 python 库如何无法为用户提供发现数据中隐藏模式的工具。接下来,我们介绍了我们的 PAMI Python 库,它旨在填补现有库留下的空白。接下来,我们讨论了 PAMI 算法的组织结构。最后,我们展示了如何利用 PAMI 发现隐藏在零售数据中的频繁模式。
参考文献:
[1]https://plato.stanford.edu/entries/logic-ai/
[2]人工智能中的逻辑:https://www . researchgate . net/publication/46666490 _ Logic _ in _ AI
[3]https://github.com/udayRage/PAMI 源代码:PAMI
[4]https://udayrage.github.io/PAMI/index.htmlPAMI 用户手册
[5]频繁模式挖掘:当前状况和未来方向,作者 J. Han、H. Cheng、D. Xin 和 X. Yan,2007 年数据挖掘和知识发现档案,第 15 卷第 1 期,第 55-86 页,2007 年
[6]频繁模式挖掘,编辑。Charu Aggarwal 和 Jiawei Han,Springer,2014 年。
使用 Python 自动执行会计任务
构建解决方案来自动化财务审计的重复性任务,并与您的财务同事分享,以提高他们的工作效率
Excel 自动化—(图片由作者提供)
如果你是数据分析师,想要访问大量的非结构化数据,你有影响的愿望,并且你痴迷于自动化重复的任务:去你的财务部门。
我将在本文中分享一个解决方案,它基于我从非常不结构化的 Excel 文件中提取数据来执行运营和财务审计的经验。
💌新文章直接免费放入您的收件箱:时事通讯
1.如何用 python 实现会计任务的自动化?
问题陈述
你是一家大型物流公司的数据分析师,你的财务团队同事请求你帮助建立一个模型来预测仓库运营的损益。
2017 年 5 月月度成本报告示例—(图片由作者提供)
您需要从会计团队构建的月度报告中提取信息,这些报告按类别列出了所有详细的成本
- 您的研究中包含的 20 个仓库
- 最近 36 个月的审计
- 共 720 个 Excel 文件
- 60 项费用跟踪
- 3 类成本:投资、租赁、采购
目标
您的目标是构建一个工具,自动从这 720 个 Excel 文件中提取数据,对其进行格式化,并将所有内容合并到一个报告中。
审计报告示例—(图片由作者提供)
财务部门将使用此报告来分析过去 3 年的成本,并了解趋势。您的工具将有助于在单个报告中获得可见性,而无需使用额外的资源来手动执行。
2.你的解决方案
您将设计一个简单的 python 脚本,该脚本将执行:
- 打开文件夹中的每个 Excel 报表
- 处理和清理数据
- 按照上述格式建立月度报告
- 将月度报告与全球数据框合并
- 将最终结果保存在 Excel 文件中
导入每月 Excel 报告并处理数据
这里有几个要点:
- 表头熊猫的参数只取第 5 位(对 excel 文件非常有用)
- 用 0 填充 nan以对数值进行计算
- **修剪列名称:**在人们进行手工输入的情况下非常有用(‘单位成本’和‘单位成本’对用户来说看起来是一样的)
格式化列并执行计算
这部分和我处理的报表非常链接,我在这里分享代码供参考(链接)。
3.共享此工具
关注我,了解更多与供应链数据科学相关的见解。
现在您已经构建了工具,您想与财务团队分享它。供您参考,在我以前的公司,花了 2 周的时间(1 人)来完成这些任务。
如果您能实现这个简单的工具,您能想象会有什么影响吗?
如果你感兴趣,我写了一篇关于如何分享你的 python 脚本的文章,供没有任何 Python 经验的同事使用。
https://www.samirsaci.com/build-excel-automation-tools-with-python/
如果您遵循本文中解释的不同步骤,您将获得一个可执行文件(。exe)准备好与将运行该脚本的同事共享(即使他们没有安装 python)。
超越:自动化数据提取
在开始构建报告之前,您需要从 ERP 中收集数据。如果您正在使用 SAP,您可能会对这一系列关于 ERP 自动化的文章感兴趣
https://www.samirsaci.com/sap-automation-of-orders-creation-for-retail/ https://www.samirsaci.com/sap-automation-of-product-listing-for-retail/ https://www.samirsaci.com/sap-automation-for-retail/
关于我
让我们在 Linkedin 和 Twitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运作和降低成本。
如果你对数据分析和供应链感兴趣,可以看看我的网站
利用深度学习帮助非洲农民提高产量
利用迁移学习识别木薯叶部病害
一棵健康的木薯,由 malmanxx 在 Unsplash 上拍摄
如果你和我一样,那么大部分时间你都记不起自己做了什么梦。今天早上,我想起了一切。我梦见我收到一封电子邮件,宣布我赢得了木薯叶疾病比赛。除此之外,我在 Kaggle 网站上的状态显示我已经成为了 Kaggle 大师。
Kaggle 是一个由数据科学家和机器学习实践者组成的在线社区。根据你赢得的比赛数量,Kaggle 会给你分配一定的排名。
当我醒来时,仍然有点困惑,我登录了 Kaggle 网站。我还是一个卡格尔新手。我在木薯叶疾病竞赛的公共排行榜上的排名是 2343。到目前为止,梦想成真…
在我通过了开发者认证考试后,我才开始参加木薯叶病竞赛。我想看看我是否可以通过参加这个比赛来提高我的深度学习技能。
在之前的文章中,我使用迁移学习为狗和猫的比赛创建了一个模型。建立这个模型很有趣,但是它在现实世界中没有直接的用途。
和我参加的这个 Kaggle 比赛不一样。Kaggle 将这场比赛命名为木薯叶疾病分类。目标是从图像中识别木薯叶上的疾病类型。
木薯是非洲的主要食物,由小农种植。他们种植木薯是因为它能承受恶劣的环境。但是病毒性疾病是低产的主要原因。
为了对抗这些疾病,农民需要昂贵的农业专家的帮助。这些专家首先诊断病情。然后他们和农民一起制定了一个控制疾病的计划。
我们可以通过创造一种可以检测疾病的解决方案来帮助农民。例如,使用用他们的移动照相机拍摄的照片。该解决方案应该能够处理低质量图像和低带宽。
使用图像识别和深度学习的解决方案将是理想的候选方案。
在本文中,我们将使用 TensorFlow 2.4.1 和 Python 3.8 开发一个模型。我们将从一个卷积神经网络开始,让我们登上排行榜。然后,我们将使用 DenseNet201 和 EfficientNetB3 预训练模型来改进我们的模型。最后,我们将使用测试时间增加 (TTA)来改进我们的预测。
如果你对代码感兴趣,请看这个 Github 库。
培训用数据
训练数据由 21.397 张木薯叶的 jpeg 图像组成。专家们在乌干达进行定期调查时收集了这些照片。这种格式真实地表现了农民在现实生活中需要诊断的内容。
来自比赛的图像分为以下五类。
- 0 → 一片显示木薯白叶枯病的叶子(CBB)
- 1 → 一片显示木薯褐条病的叶子(CBSD)
- 2 → 一片呈现木薯绿色斑点(CGM)的叶子
- 3 → 一片显示木薯花叶病(CMD)的叶子
- 4 → 一片健康的叶子
从左至右, CBB 、 CBSD 、 CGM 、 CMD 和一片健康的叶子。训练图像,由 Kaggle 提供
组织培训数据
Kaggle 将所有训练数据存储在一个文件夹中。每个图像的名称代表它的 id。id 和标签之间的映射存储在单独的 CSV 中。下面你可以看到一个 CSV 文件的例子。
train.csv 包含图像和标签之间的映射
我们需要重组图像,因为我想使用ImageDataGenerator
类。我们还需要保留一部分训练图像进行验证。你可以在下面看到ImageDataGenerator
需要的文件夹结构。
适用于 ImageDataGenerator 的文件夹结构
我们必须读取 CSV 文件,并将图像复制到正确的文件夹中。此外,我们必须在训练集和验证集之间划分图片。函数distribute_images
接受单个参数。该参数定义了训练图像和验证图像之间的比率。值 0.7 选择 70%的图像用于训练,30%用于验证。
函数来重新组织适合 ImageDataGenerator 的图像
我们读取第 4 行的 CSV,然后使用train_df
数据帧的unique()
方法遍历标签。
创建和训练模型
我们将从一个小的卷积神经网络开始,而不是像我们在猫对狗比赛中那样使用迁移学习。虽然 TL 可能会让我们在排行榜上排名更高,但让我们在排行榜上获得第一个分数,以确保一切正常。
创建图像数据生成器
ImageDataGenerators 用于将训练和验证图像发送到深度学习管道。用于提供训练数据的 ImageDataGenerator 使用图像增强来增加图像的多样性。验证数据的 ImageDataGenerator 仅重新缩放图像。
创建 ImageDataGenerator
猫和狗竞争的区别在于 class_mode 是绝对的,因为我们有两个以上的输出标签。
构建和编译 CNN 模型
我们要训练的第一个模型是一个小型卷积神经网络。该模型使用四个卷积层、一个下降层和一个 512 个单元的隐藏密集层。
CNN 的定义
为了能够预测五个不同的类,输出层有五个单元。
训练模型
我们设定训练 50 个纪元,尽管使用的回调可能会更早停止。
训练模型
你看到我们使用create_callbacks()
方法设置回调参数了吗?create_callbacks()
方法返回三个不同回调的数组。见下文。在每个时期之后,TensorFlow 都会调用这些回调。
TensorFlow 在每个时期后调用三个回调
如果验证精度不再提高,则EarlyStopping
回调停止训练。当 TensorFlow 看不到任何进展时,我们耐心地设置停止之前等待的纪元数。
ReduceLROnPlateau
回调如果看不到任何提升,会自动降低学习率。
ModelCheckpoint
如果验证损失小于前一个时期,则在一个时期后自动保存模型。有时,训练结束时的模型不如一个或两个时期前的模型准确。如果你使用这个回调,它将总是保存最好的一个。
可视化培训结果
在我的机器上,这个模型实现了 0.71 的最大验证精度和 0.79 的验证损失。
模型上的 fit 方法返回一个历史对象。TensorFlow 将每个历元的结果保存在这个历史对象中。我们可以使用 Matplotlib 库来可视化训练。
我们看到,训练和验证的准确性是相辅相成的。验证精度有一点波动,但是没关系。
训练和验证的准确性与我们的 CNN 时代,由作者的图像
训练和验证损失也是如此。一个优秀的第一基线,我们可以提交给竞争。
训练和验证损失 vs 我们 CNN 的时代,图片由作者提供
提交模型以获得分数
这就是这次比赛与以往不同的地方。你没有提交你的预测,而是提交了一个笔记本。
这个笔记本应该创建和训练您的模型,并创建预测。然后 Kaggle 在一个隔离的环境中运行笔记本。在这种环境下,笔记本可以访问所有的测试图像。
额外的限制是笔记本不能上网。此外,笔记本必须在不到 9 个小时内完成训练和预测。
创建和保存预测
在训练过程中,我们使用ModelCheckPoint
来保存表现最好的模型。为了创建预测,我们使用load_model
加载这个模型。然后,为了向模型提供图像,我们使用 ImageDataGenerator。我们只调整图像的大小。
计算预测
最后一步是使用熊猫将预测保存到一个名为submission.csv
的文件中。这个文件的格式由 Kaggle 规定。Kaggle 将阅读该文件,并使用它来评分您的提交。
使用 pandas 保存 submission.csv 文件
我在让 Kaggle 拿起提交文件时遇到了一些麻烦。我发现我把文件放错了文件夹。
结果
提交笔记本一小时后,Kaggle 显示了分数,果然是 0.703。
笔记本的结果,图片由作者提供
这个分数让我在公共排行榜上名列第 2996 位——这是我们第一次尝试的良好开端。
放置在 Kaggle 排行榜上,图片由作者提供
如果你想知道公共排行榜的第一名是什么?这时是 0.911 ,所以我们还有很长的路要走:)
一个木薯根,由安妮·斯普拉特在Unsplash上拍摄
使用迁移学习改进我们的模型
之前,在猫和狗的比赛中,我们使用迁移学习改进了我们的模型。我们将尝试在这里做同样的事情。
然而,还有一个额外的复杂性。如果您使用默认的 Keras 应用程序,它会从互联网下载权重文件。在这个比赛中,我们的笔记本不能上网,所以那不行。稍后我们将看到如何解决这个限制。让我们首先尝试增加我们模型的准确性。
我们唯一要改变的是模型的架构。create_cnn_model
函数看起来是这样的。
使用预训练的 DenseNet201 模型来改进我们的模型
我们创建了一个DenseNet201
的实例,并将其作为模型的第一部分。然后我们Flatten
结果,添加一个有 512 个单位的Dense
层。输出层仍然是同一个有五个单元的Dense
层。每个类别一个。
当我们训练模型时,精确度增加了 23 个时期。训练和验证准确性很好地相互跟随,这显示了一个健康的模型。训练和验证损失也是如此。验证准确度攀升至约 0.76,而验证损失在 0.70 处变平。
使用 DenseNet201 训练和验证我们的 TL 模型的准确度与时间,图片由作者提供
使用 DenseNet201 的 TL 模型的训练和验证损失与时期,图片由作者提供
当我们将这个模型提交给 Kaggle 时,它的得分是 0.772,这使我们在公共排行榜上上升到 2927 名。向上的一大步。
投稿结果,图片由作者提供
排行榜上的位置,作者图片
将模型提交给 Kaggle
当你想提交一个使用迁移学习的笔记本时,你必须拆分你的笔记本。第一部分训练并保存模型。这个笔记本可以上网检索重量。这样做的结果是保存的模型。使用此模型创建 Kaggle 数据集。
第二部分是你提交的笔记本。该笔记本从 Kaggle 数据集中加载保存的模型。然后,该模型用于创建预测。
使用不同的预训练模型 EfficientNet 进行优化
目前,表现最好的模型之一是 EfficientNet。EfficientNet,顾名思义,是最高效的模型之一。它需要最少的计算能力来进行推理。下图显示了 EfficientNet 与其他预训练模型的比较。
EfficientNet:反思卷积神经网络的模型缩放(Tan 等人,2019 年)
从 B0 到 B7,EfficientNet 有八种不同的变体。每个变体都更精确,使用更多的参数,见上图。
我们使用 EfficientB3 模型,这是精度和参数数量之间的一个很好的平衡。
我们创建了一个EfficientNetB3
的实例,并将其作为模型的第一部分。然后我们使用一个GlobalAveragePooling2D
层来调整结果的大小,并添加一个有 256 个单元的Dense
层。一个Dropout
层防止过度拟合。输出层仍然是同一个Dense
层,有五个单元——每个类别一个。
使用 EfficientNetB3 创建模型
我们改进模型的另一件事是增加输入图像的尺寸。以前我们使用 150x150,但对于 EffientNet,我们使用 512x512。
当我们训练模型时,精确度增加了 25 个时期。训练和验证准确性很好地相互跟随,这显示了一个健康的模型。训练和验证损失也是如此。验证准确度攀升至约 0.87,而验证损失在 0.33 处变平。
使用 EfficientNetB3(图片由作者提供)训练和验证我们的 TL 模型的准确度与时间
使用 EfficientNetB3 的 TL 模型的训练和验证损失与时期,图片由作者提供
提交该模型后,我们将 2343 放在了公共排行榜上。又向前迈进了一大步。
投稿结果,图片由作者提供
我在排行榜上的位置,图片由作者提供
使用测试时间增加进行优化(TTA)
我们在训练过程中用来将图像输入网络的ImageDataGenerator
随机转换照片,以增加训练图像的数量和变化。当我们创建预测时,我们也使用一个ImageDataGenerator
,但是不增加图像。如果我们改变这个会发生什么?
测试时间增加(TTA)是一种提高预测准确性的技术。我们不再直接使用测试图像。首先,我们对图片进行不同的变换,如旋转裁剪、翻转、增强对比度等。然后我们得到了每一个被改变的图像的预测。
测试时间增加解释,图片由作者提供
然后我们对预测进行平均。这将为我们提供图像的预测。大多数情况下,这将提高你预测的准确性。
在我们的笔记本中实现 TTA
因为我们已经在使用 ImageDataGenerator 向模型提供测试图像以进行预测,所以我们只需向生成器添加增强选项,并通过测试集进行多次迭代。
在我们的笔记本上实现测试时间增加
从第十六行开始,我们在所有测试图像中迭代十次并保存预测。我们计算第 33 行预测的平均值。
我重用了评分 0.880 的模型。通过使用 TTA,预测的准确度达到了 0.889,如下图所示。
将 TTA 加入我们的笔记本的结果,图片由作者提供
使用 TTA 后我在排行榜上的位置,图片由作者提供
结论和进一步优化
我们从一个简单的卷积网络开始,这个网络的准确率为 71%。在我们改用使用 DenseNet201 和 EfficientNet 的迁移学习后,准确率提高到了 88%。通过使用测试时间增加,我们几乎将它提高了一个百分点,达到 88.9%。源代码可以在这个 Github 资源库中找到。
如果把我们的分数和排行榜的第一名 91.1%相比,还是有 2.2%的差距。通过阅读 Kaggle 社区共享的笔记本,我看到了一些提高准确性的附加技术。下面我就提一下,简单解释一下。
使用更大、更准确的预训练模型,如 EfficientNetB7 。更大意味着你将需要更大的 GPU 或更大内存的 TPU,训练将需要更长的时间。
使用 K 倍交叉验证。这是将你的数据拆分成训练集和验证集的不同方法。您将图像集合分成 K 个大小相等的部分。然后训练 K 个模型,每次都使用不同的训练和验证集。若要创建预测,请组合每个模型的预测。
使用 CutMix 进行图像放大。这是一种在训练图像之间剪切和粘贴随机补丁的新策略。它还调整图片的标签。通过这种方式,它迫使模型关注木薯叶中不太容易区分的部分。
使用 Mixup 进行图像放大。使用 Mixup,您可以使用线性插值来组合两个图像及其标签。研究表明,Mixup 提高了神经网络架构的泛化能力。
多模型预测或集合模型结合来自多个模型的预测,以提高整体性能。
这些东西大部分对我来说都是新的。但是由于我喜欢学习,我将尝试这些技术来提高我的模型的准确性。我将在下一篇文章中告诉你进展如何。
感谢你的阅读,记住永远不要停止学习!
已用资源
谭明星和郭诉乐。EfficientNet:反思卷积神经网络的模型缩放。《机器学习国际会议论文集》(ICML),2019 年。
黄高、刘庄和基利安·q·温伯格。密集连接的卷积网络。arXiv 预印本 arXiv:1608.06993,2016a。
克里热夫斯基、苏茨基弗和辛顿。用深度卷积神经网络进行 Imagenet 分类。在 NIPS,2012 年