TowardsDataScience 博客中文翻译 2019(四百三十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

安全外壳(SSH)提示和技巧

原文:https://towardsdatascience.com/secure-shell-ssh-tips-and-tricks-3f82b8ff2a53?source=collection_archive---------29-----------------------

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

Photo by Jefferson Santos on Unsplash

作为一名程序员,我最喜欢的一点是我可以坐在沙滩上远程工作。但作为一名数据科学家,事情稍微有点棘手,因为我无法在本地笔记本电脑上执行任何大数据处理(我不会带着一台高规格但笨重的电脑去海滩……)。我仍然需要在拥有更多资源的远程服务器上运行我的下一个模型训练。尽管如此,不要担心,我们仍然有远程安全 shell 来拯救我们!

在这篇文章中,我将分享一些我在日常工作中使用过的 ssh 技巧。在做任何事情之前,让我们首先定义 bash 脚本的变量。

#!/bin/bash
user=usernameString
password=passwordString
serverAddr=IPAddressOfTheRemoteServer
serverPort=PortToBeTunnelledFromTheRemoteServer
sourceLoc=locationOfTheFolderToBeCopied

通过 SSH 仅复制更新的文件

有时候,我需要将大量文件从本地笔记本电脑复制到远程服务器。我在技术上可以使用 SCP 。然而,缺点是,如果我需要重复复制许多文件,其中大多数文件自上次操作以来没有更新过,SCP 仍然会盲目地将所有文件复制到服务器。为了减少复制所需的负载和时间,我们可以使用 rsync。Rsync 将只向服务器发送更新的文件。

rsync -avh -e ssh $sourceLoc $user@$serverAddr:$remoteLoc

远程运行脚本

假设我有一个名为 script.sh 的 shell 脚本,我想在远程服务器上执行它。我可以把它和前缀“bash -s”一起传递给 ssh 命令。

ssh ${user}@${serverAddr} 'bash -s' < script.sh

建立端口隧道(仅推荐用于调试!)

有些情况下,您可能无法在服务器外部公开端口(很可能是由于安全问题)。例如,假设我在服务器的端口 5000 上运行一个 web 服务。不幸的是,这个端口不能从外部 ping 通。我可以通过 ssh 执行隧道操作,将我的本地计算机的端口 5000(技术上可以是任何选择的 l o c a l P o r t ) 链接到服务器的端口 5000 ( 同样,任何 localPort)链接到服务器的端口 5000(同样,任何 localPort)链接到服务器的端口5000(同样,任何serverPort 都可以)。这样,只要我保持 SSH 连接,当我在本地浏览器中访问 localhost:5000 时,我就会看到来自远程服务器的 web 服务的内容。

ssh -N -L localhost:$localPort:localhost:$serverPort ${user}@${serverAddr}

在终端的变量中写入密码(不推荐,仅用于调试)

使用基于密码的 ssh 意味着每次我们执行 SSH 命令时,都会提示我们输入密码。如果您曾经希望有一种方法可以将密码存储在终端的临时变量中(很可能太懒了),您会发现 sshpass 很有用。事实上,我们所需要做的就是将 sshpass -p $password 添加到任何普通的 ssh 命令中。下面是一个如何将 sshpass 与前面所有命令一起使用的示例。

sshpass -p $password rsync -avh -e ssh $sourceLoc $user@$serverAddr:$remoteLocsshpass -p $password ssh ${user}@${serverAddr} 'bash -s' < script.shsshpass -p $password ssh -N -L localhost:$localPort:localhost:$serverPort ${user}@${serverAddr}

结论

请谨慎使用 SSH。必须认真对待 IT 安全,尤其是考虑到最近网络攻击越来越普遍。如果您在公共网络中,请确保您只连接到安全的接入点。实际上,我并不推荐远程工作,比如在海滩上(这是个玩笑!)和 ssh-ing 到工作服务器。最安全的方法是只从内部网络访问资源(或者至少激活 VPN 连接)。

使用 Anaconda 保护带有环境变量的 API 密钥

原文:https://towardsdatascience.com/securing-api-keys-with-environment-variables-using-anaconda-d30a7c48b1fd?source=collection_archive---------10-----------------------

如何在公共论坛分享项目时保证私人信息的安全?

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

如果您正在阅读本文,我假设您已经熟悉 API、令牌、私钥和公钥。您的私钥和公钥作为一种身份验证的形式,通过开发人员的 API 来识别您的身份并跟踪您的活动。这意味着,如果有人得到了你的密钥,他们就可以冒充你访问 API 中的数据,这可能会产生一些可怕的后果。

大多数崭露头角的数据科学家面临的挑战是,他们希望在公共论坛上推广他们的项目工作。如果这些项目中的任何一个使用 API,个人将不得不把他们的密钥加载到他们的笔记本中。换句话说,公开笔记本意味着危及 API 密钥的安全。

这个问题有几种常见的解决方案:第一种是用类似于******YOUR_PRIVATE_KEY_HERE的东西来替换这个键。这在一定程度上是可行的,但是这种方法容易出现人为错误。对于单个项目的多次提交,每次都必须删除并重新添加令牌。当您按下 commit 并忘记清除密钥时,它就被破坏了。这不是会不会发生的问题,而是什么时候发生的问题。另一种选择是将 API 密钥保存到一个单独的 JSON 文件中,读取私钥,并在推送到 GitHub 时排除该文件。虽然这稍微好一点,但这里的问题是,其他想要探索您的工作的人必须对分叉的存储库进行编辑才能运行代码。此外,这并不能完全消除人为错误的可能性。

如果有一种方法可以将密钥和令牌保存到我们的系统文件中,以便在需要时调用,这不是很好吗?如果其他人可以使用相同的代码从他们自己的系统中调用他们自己的密钥和令牌,那不是更好吗?事实证明,有一个办法:环境变量!

什么是环境变量?

环境变量顾名思义:保存在本地环境中的变量,可以在任何项目中调用。因为它们不是存储库本身的一部分,所以没有必要限制推送到 GitHub 的信息。在下面的例子中,一个私有 API 密匙已经被保存为一个名为PRIVATE_API_KEY的环境变量。稍后我们将看看如何创建变量本身。

import osapi_key = os.environ.get("PRIVATE_API_KEY")

正如我们所见,这看起来非常干净简单。每当我们需要使用密钥时,我们所要做的就是调用api_key变量。更有经验的数据科学家在审查这段代码时应该会立即意识到需要使用他们自己的私钥,并将它们保存在他们自己的环境中。一旦完成,程序应该可以正常运行,不会出现任何问题。

这里需要注意的是,审查者需要使用相同的变量名保存 API 键。如果这个人已经使用不同的变量名将相关的键保存到了他们的环境中,他们可能会选择修改代码而不是他们的环境。如果 API 开发人员在他们的文档中为这些键提供推荐的命名约定,将会使这个过程更加优雅。但那是另一天的话题。

创建环境变量

在这篇文章中,我们不打算讨论跨项目管理环境的最佳实践。相反,我假设您已经在合适的环境中工作,并且知道如何使用 Anaconda 在它们之间切换。如果你不熟悉这个,我推荐你看看这个视频,作为这篇文章的基础。

创建这些变量的总体过程如下:

  1. 导航到存储包和详细信息的环境路径。
  2. 创建文件和目录,用于在调用时激活变量,并在使用完变量后停用变量。
  3. 将变量添加到相关文件中。

我将向您展示如何在 macOS、Linux 和 Windows 中处理所有这三个步骤。所有的指令都直接改编自 Anaconda 文档

macOS 和 Linux

以下命令可用于使用终端处理步骤 1 和 2:

cd $CONDA_PREFIX
mkdir -p ./etc/conda/activate.d
mkdir -p ./etc/conda/deactivate.d
touch ./etc/conda/activate.d/env_vars.sh
touch ./etc/conda/deactivate.d/env_vars.sh

因此,我们现在有两个名为env_vars.sh的文件,它们分别存储在不同的目录中。我们需要在您选择的文本编辑器中打开这些文件来创建变量。对于activate.d目录中的文件,我们将添加以下内容:

*#!/bin/sh*

export PRIVATE_API_KEY='YOUR_PRIVATE_KEY_HERE'

对于 deactivate.d 目录中的文件,我们添加以下内容:

*#!/bin/sh*

unset MY_KEY

第一行#!/bin/sh让操作系统知道这些文件是 shell 脚本,以确保exportunset命令被正确执行。

一旦这些文件被保存并关闭,在终端输入conda activate analyticsYOUR_PRIATE_KEY_HERE保存到环境变量PRIVATE_API_KEY。使用完这些变量后,可以使用conda deactivate将它们从环境中删除。

Windows 操作系统

使用命令 shell,可以使用以下命令来处理步骤 1 和 2:

cd %CONDA_PREFIX%
mkdir .\etc\conda\activate.d
mkdir .\etc\conda\deactivate.d
type NUL > .\etc\conda\activate.d\env_vars.bat
type NUL > .\etc\conda\deactivate.d\env_vars.bat

因此,我们现在有两个名为env_vars.bat的文件,它们分别存储在不同的目录中。我们需要在您选择的文本编辑器中打开这些文件来创建变量。对于activate.d目录中的文件,我们将添加以下内容:

set PRIVATE_API_KEY='YOUR_PRIVATE_KEY_HERE'

对于 deactivate.d 目录中的文件,我们添加以下内容:

unset PRIVATE_API_KEY=

一旦保存并关闭这些文件,在终端中输入conda activate analyticsYOUR_PRIATE_KEY_HERE保存到环境变量PRIVATE_API_KEY。使用完这些变量后,可以使用conda deactivate将它们从环境中删除。

结论

正如您所看到的,虽然将 API 键保存为环境变量需要几个步骤,但这本身并不困难或复杂。一旦就位,这些变量就可以快速而容易地访问,并且当您使用完它们时,只需一个命令就可以停用它们。这比每次你想对 GitHub 进行更新或提交新的提交时添加和删除键要有效得多。在向外界展示您的项目时,它会为您提供更多安全保障。

保护学习机器:

原文:https://towardsdatascience.com/securing-learning-machines-bdfb6db96f9d?source=collection_archive---------30-----------------------

在尝试保护产品之前,先了解机器学习、人工神经网络和人工智能背后的基础知识

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

The Perceptron — The Simplest Model by Geoff Hinton

场景:

你刚刚被位于昂贵的硅谷某处的一家有前途且资金充足的“人工智能和人工智能”技术初创公司聘用为他们的第一名安全工程师。

你满足了他们对“技术堆栈”体验的所有要求,在面试中,你对如何处理复杂的安全问题表现出了热情和激情。你同意了这个提议,你已经准备好开始你的第一天。

有一个问题。

你对机器学习(ML)、人工神经网络(ANN)和营销界的新宠“人工智能”(A.I .)一无所知,也没有任何经验。为了简单起见,在整个故事中,我们将这一技术堆栈称为 ML/ANN/AI。

想象一下,您只有两周时间来熟悉支持产品堆栈的技术。

你从哪里以及如何开始?书籍?网络课程?只是谷歌的东西?

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

Don’t just Google stuff. Prepare a learning path. (Photo by Jacky Chiu on Unsplash)

首先,不要自责。你不是落后者。这些都是尖端技术,由于可使用的现成框架的爆炸式增长,它们最近悄悄进入了主流软件产品。

这些框架包括 Caffe,TensorFlow,PyTorch,NVIDIA DIGITS 和 RAPIDS,以及亚马逊 AWS,谷歌云平台和微软 Azure 基于云计算的产品。

所有人都称之为“机器学习的民主化”

我个人认为,如果有足够的动力和时间,即使没有 ML/ANN/AI 的实践经验,你仍然可以赶上技术,成为一名有效的安全工程师。

那么如何开始呢?

理解 ML/ANN/AI 的基础和构建模块是你的首要任务。

其余的,也就是你所支持的产品的代码和基础设施的实际实现,你可以边做边学。

对于安全工程师来说,在不了解其背后的基本原理或核心原则的情况下,保护基于尖端技术的新产品或服务是一场艰苦的战斗。

以下是我的一些个人建议,告诉你如何在短时间内掌握基本知识,以便开始帮助保护产品:

“理解 ML/ANN/AI 的基础和构建模块是你的首要任务。剩下的,就是你所支持的产品在代码和基础设施中的实际实现,你可以边做边学。”

(**注:**这是个人推荐,也是我熟悉 ML/ANN/AI 技术栈所走的路。绝不是唯一的办法,随便挑你喜欢的就行。我与课程的创建者和书籍作者没有业务关系)

在线课程

我建议在开始学习之前,先复习一下 Python 脚本/编码知识。在我开始学习之前,我已经不再每天写代码了,所以我在 Python 上有点吃力。但如果我能做到,你也能。

以下是我的学习经历:

1。 IBM 数据科学基础—一级 (免费)

数据科学概念、方法、工具包和业务用例介绍。完成时间:3 小时

2。 IBM 数据科学基础—二级 (免费)

1 级课程的延续。回顾数据科学工具和数据科学方法的介绍性概念、更深入的讨论和实践。完成时间:13 小时

3。 IBM 应用数据科学与 Python (免费)

现在是时候应用您在之前的数据科学基础课程中学到的数据科学概念和方法了。本课程将教你如何使用 Python 语言来清理、分析和可视化数据。课堂实验很短但很有帮助,因此你可以获得处理有趣数据问题的实践经验。使用 Python 深入研究数据分析和数据可视化。了解如何将事实上的 Python 库的基础知识用于数据科学 pandas、Matplotlib、Seaborn 和 Folium。完成时间:23 小时。

4。 IBM 机器学习用 Python (免费)

本课程将向您介绍使用 Python 进行机器学习的基础知识。它将向您介绍有监督和无监督的机器学习,流行的算法,如分类,回归,聚类和降维,以及流行的模型训练/测试分裂,均方根误差和随机森林。完成时间:12 小时。

5。 深度学习。人工智能神经网络和深度学习 ($$$)

由全球公认的机器学习先驱吴恩达创建和教授。深入探究神经网络和深度学习进化背后的理论和数学。

为繁重的数学和线性代数复习做准备。本课程将深入探讨深度学习介绍、神经网络基础知识以及浅层和深层神经网络。

由于大量的符号和公式,白板会议可能会让你睡着,请确保你及时休息,以便吸收关键概念。练习在自己的备忘单或白板上写下注释,以加强学习和视觉识别。

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

Computing gradients: One of Andrew Ng’s whiteboard session in his course.

这门课的编程练习完全值得一试。你将使用 Jupyter 笔记本,在复习了前面的基础课程后,你现在应该已经知道了。完成时间:18 小时。

“练习在你自己的备忘单或白板上书写符号,以加强学习和视觉识别.”

6。 英伟达($ $)

这是一门优秀的入门课程,包括在 NVIDIA 的 DIGITS 平台上进行图像分类和对象检测的实际配置和编码练习。了解已经在平台上使用的图像分类中获奖的预训练模型 AlexNet、GoogleLeNet、LeNet 和 UNET。

您将探索深度学习的基础,并学习如何训练和提高神经网络的性能,学习深度学习工作流,实验数据、训练参数(也称为超参数调整)、网络结构和其他调整,以提高神经网络的性能和能力。

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

You will learn how to classify, train and tweak hyperparameters quickly using NVIDIA’s DIGITS platform.

完成本课程后,我立即获得了许多使用该平台进行图像分类的想法和业务用例。完成时间:8 小时以上。

书籍

按顺序排列,下面是我推荐给你的书籍,你可以阅读它们来提高你的基础知识或者扩展它们。

我还没有 100%看完所有这些书,但是从一本书跳到另一本书来改变一下步调,对你的学习道路很有帮助。

  1. 塔里克·拉希德制作自己的神经网络。

可能是我读过的关于神经网络的最好的入门材料。像伟大的理查德·费曼会如何解释一样解释(像我五岁/ELI5 一样解释)

2。 务实的艾乘诺亚的礼物

Noah 是一位好朋友兼柔术实践者写的,他已经在数据科学领域工作多年了。了解现代开发人员工作流程,以及如何利用云计算服务来运行机器学习工作负载。在职场上非常有用。

3。 安迪·托马斯博士编码深度学习革命

工程师的理想伴侣书。介绍深度学习概念和模型。了解如何使用 Python、Tensorflow 和 Keras。大量的示例代码和编码练习。在职场上非常有用。

4。 机器学习的向往:深度学习时代 AI 工程师的技术策略吴恩达

注册并获得该领域全球公认的领导者吴恩达的书的草稿。雄辩的文字说明,易于阅读。技术或数学方面没那么重。提倡简化工作流程,您可以从 Andrew 本人那里获得提示和指导!

5。 深度学习的 TensorFlow:从线性回归到强化学习拉姆伦达和扎德

通过 TensorFlow 学习机器学习的基础知识,tensor flow 是谷歌著名的深度学习软件库,使工程师可以直接设计和部署复杂的深度学习架构。了解如何使用 TensorFlow 构建能够检测图像中的对象、理解人类文本和预测潜在药物属性的系统。

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

Photo by NeONBRAND on Unsplash

总而言之,我想重申一下这个学习途径的目标:

作为一名新创公司的安全工程师,您需要了解使用 ML/ANN/AI 创建软件产品所涉及的基本原则、理论、技术和现代工具,以便您拥有保护产品的最基本的知识和背景。

拥有适当的上下文是生成您负责保护的产品的最小可行威胁模型的必要条件。

(精通是一件不同的事情,通常需要至少 10,000 小时对你的技能或专业领域的刻意练习。)

如果加上完成在线课程的总预计时间,总计 80 多个小时,大约三天。实际上,我会用一周的时间来完成这些课程,其中主要包括通过 Stack Overflow 和 GitHub 进行编码练习的研究。我可以在家连续两周从早上 9 点到晚上 12 点学习来完成这些课程。

目前,我正享受着翻阅我提供的书单,探索很酷的 GitHub 项目,如优步的 Ludwig 项目NVIDIA 的 DIGITS 平台,以及它如何帮助美国安全工程师快速原型化由 ML/ANN/AI 增强的信息安全工具。

如果你刚刚开始你的学习之路,犹豫不决,停滞不前,请告诉我,我会尽我所能给予回应和帮助。

享受你的学习之路。会有障碍和难以消化的概念,特别是如果你来自非计算机科学教育背景,但正如俗话所说,“这不是目的地,而是旅程”

去找你的 y 吧。明白吗?

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

您可能一直在犯的安全和加密错误

原文:https://towardsdatascience.com/security-and-cryptography-mistakes-you-are-probably-doing-all-the-time-7407c332944f?source=collection_archive---------22-----------------------

让我们澄清一些关于加密和安全的常见误解…

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

一般来说,关于密码学和安全性有很多神话和错误的假设。人们经常滥用密码原语,假设某些东西默认是安全的,或者使用过时的技术/算法。所以,让我们来看看这些误区和常见错误,这样你就可以在将来避免它们。

已经停止使用/dev/random

几乎所有人都会说,出于加密的目的,应该总是使用/dev/random。嗯,那是错误的。/dev/urandom/dev/random都使用完全相同的 CSPRNG 。它们之间的区别是,/dev/random会阻塞,直到它有足够的熵。这是另一个问题——你不希望你的应用程序等待熵,并围绕/dev/random阻塞的可能性设计逻辑,特别是考虑到你不需要那么多熵…你所需要的是大约 256 比特的熵,这将从/dev/urandom中得到。如果你想更深入地研究这个话题,那么请看这里的文章。

永远不要使用 AES ECB

你肯定知道 AES 是一种分组密码。它以 128 位的块加密纯文本。好吧,听起来不错,那么使用 *ECB(电子密码本)*模式有什么问题呢?它在每个块上使用一个不变的密钥,所以如果你加密超过 128 位的数据,你的密文将看起来像这样:

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

这算不上什么加密,对吧?那么,你应该用什么来代替 ECB ?计数器模式(CTR)!为什么?因为加密可以并行完成,它使用 IV (nonce)来消除未更改的密钥问题,这是 ECB 模式所具有的。记住永远不要重复使用第四代。

这是密文在 CTR 模式下的样子:

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

可以用 *openssl* : 自己试试

永远不要对任何东西使用 MD5

当我们谈到永远不使用东西的话题时…忘掉 MD5 ,就像现在。它被设计用作一种安全的加密散列算法,但是在这一点上没有什么安全可言。它有冲突漏洞,您可以创建一对具有相同 MD5 哈希的文件,这意味着您可以伪造 SSL 或 CA 证书。那么,你应该用什么来代替呢?这取决于使用案例——对于密码散列使用bcryptscrypt。你用哪一个,在我看来是个人喜好- scrypt被设计成*【更好】*比bcrypt好,但它更新,所以它面临的审查更少。我个人仍然使用bcrypt。至于其他用例,使用来自 SHA-2 家族的哈希函数,最好是像 SHA-512 这样的长摘要。

总是先加密后 MAC

这一节的标题说*“Encrypt-then-MAC”,但是让我们先回溯一点。很多人没有意识到他们应该始终将加密与消息认证结合使用。我不想详细解释为什么你应该验证消息,我要说的是,如果你不验证消息,那么你的应用程序就很容易受到攻击,比如重放攻击主动攻击*。

既然这样,为什么先加密然后 MAC ?简单地说,这是获得可证明安全性的唯一方法,这并不总是必要的,但这意味着当使用这种结构时,基本上不可能在密码上搞乱*。*

如果你想要更深入的解释,那么我推荐科林·帕西瓦尔的文章。

特殊字符不会让您的密码变得更好

不一定,至少。一个好的密码是你能记住的,所以加入像!@#$%^&*这样的字符会让你或你的应用程序的用户更有可能忘记它或者把它写在别人能看到的地方。

最初在密码中添加特殊字符的原因是什么?是,那么如果我们不想强迫用户在密码中包含特殊字符,那么有什么替代方案可以让熵保持足够高呢?

让它 loooong 。正如流行的 xkcd 密码强度漫画所示,使用由几个随机单词串联而成的密码比试图记住一些胡言乱语更有意义。创建这些类型的密码满足了人类和计算机两方面的要求,换句话说,它很容易记住并且很难猜测(高熵,无法暴力破解)。

注意:在理想世界中,每个人都会使用密码管理器并生成他们随机的超高熵密码,但这不是我们对普通非技术用户的期望。

加密密钥轮换误解

有人可能已经告诉过你,你应该每隔一段时间旋转你的密钥,没错,你绝对应该这么做。然而,许多人认为他们应该这样做以降低密钥被破解的可能性,而对于加密密钥来说,情况并非如此。您应该轮换加密密钥,以减少该密钥加密的数据量,从而降低单个密钥泄露造成的潜在损害。这种误解并没有改变你应该旋转键的事实,但是知道你为什么这样做是很重要的,这样你就可以正确地评估应该使用什么间隔。

不要存储用户密码

再次回到*“千万不要做傻事”*的话题。这是一个有点夸张的说法,我见过很多次了,一个网站在我注册后通过电子邮件给我发了一个密码…就像…当你从一个用户那里得到一个密码时,你应该做的第一件事就是散列它并扔掉密码的明文版本,如果你是通过电子邮件给我发的,那么你显然没有这样做(夸张结束)!

所以,让我们深呼吸一下…那么如何存储那些密码呢?

收到用户的密码后,立即使用工作系数至少为 12 的慢速哈希函数(如bcrypt)对其进行哈希运算,并从内存中删除明文密码。工作系数 12 在发布时是有效的现在是有效的,一年后仍然不够。我会亲自拍摄长达 400 毫秒的密码验证,你可以在你的机器上检查哪个工作因素会给你。

如果你不打算使用bcrypt,请确保在密码中添加,以防止预计算攻击,就像彩虹表攻击一样。

集装箱不安全

很多人认为默认情况下 Docker 容器是安全的,但事实并非如此。它们是为了解决部署问题而构建的,而不是安全问题。

甚至还有漏洞允许攻击者获得对主机系统的root访问权,而所需要的只是对容器的外壳访问权。那么,如何避免这些安全问题和漏洞呢?

  • 使用最少的基础图像来减少攻击面 —这些图像的例子有基于alpine的图像或 Red Hat 通用基础图像
  • 只安装必要的库 —容器中的库越少,被利用的可能性就越低。
  • 使用受信任的图像——不要只是从 Docker Hub 下载任何图像。使用那些由值得信赖的团队审查、维护并有大量下载的网站。
  • 不要使用 *latest* 标签——通过使用固定标签,你可以确保在你的下一个版本中不会引入任何漏洞。
  • 使用特权最低的用户(永远不要在*root*)——用USER 1001命令结束Dockerfiles是一个很好的做法,这样可以确保你使用的用户没有特权,不会打开你的容器,从而暴露额外的漏洞。

你可以做更多的事情来保护你的图像,你可以稍后谷歌,但我认为上面的列表是每个人在使用图像/容器时应该记住的最低要求。

结论

每个软件开发者/DevOps 工程师都要对应用和系统的安全性负责,至少在一定程度上是这样(不管你喜不喜欢)。因此,我认为我们所有人都应该花一点时间做必要的研究,以确保避免类似上述的愚蠢错误和误解。

不要只相信别人告诉你的(人总是会犯错)。当涉及到安全和加密时,自己查找和检查—根据事实做出决定。

注:这最初发布在martinheinz . dev

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

人工智能和机器学习中的安全和隐私考虑—第 6 部分:近距离接触隐私

原文:https://towardsdatascience.com/security-privacy-in-artificial-intelligence-machine-learning-part-6-up-close-with-privacy-3ae5334d4d4b?source=collection_archive---------5-----------------------

注意:这是“人工智能中的安全和隐私&机器学习”系列文章的第 6 部分。以下是所有文章的链接(到目前为止):

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

Photo by Jason Blackeye on Unsplash

在本系列的前一篇文章中,我们研究了攻击者如果也开始利用 AI/ML 的能力(这是不可避免的),可能造成的损害的性质和程度。在这一部分,我们将把注意力转移到另一个方面,在机器学习的背景下更仔细地研究隐私。

就隐私而言,人工智能/人工智能的进步带来了巨大的挑战。每一个新的场景——无论从功能和效用的角度来看多么引人注目——似乎都带来了影响和损害数据隐私的可怕的新方式。

让我们来看看隐私在人工智能/人工智能环境中的表现——治理、个人和组织的动机、隐私保证的技术机制、监管方面等等。

美丽新世界中的隐私治理

鉴于人工智能/人工智能场景的巨大利润可能性,在介绍隐私治理挑战时,很少有什么比近距离观察“剑桥分析”争议更好的了。

如果你没有听说过剑桥分析,首先,欢迎回到地球!😃.事情的要点是,2014 年,剑桥大学的一名心理学教授在脸书应用平台上发布了一款名为“这是你的数字生活”的“心理测量”/“个性档案”应用。该应用程序至少在纸面上征得了用户的同意,收集了他们的一些个人资料/个人信息*。作为一项个性测试,它变得非常受欢迎,到 2016 年,约有 5000 万美国公民注册并参加了测试(这使作者能够了解和洞察 5000 万公民的个性!).*

然而,在如何和为什么这样做方面存在一些问题。首先,该应用程序收集的个人数据远远超过了它获得同意的数量。第二,这位教授与一家名为 Cambridge Analytica (CA)的公司有业务往来,该公司专门为大型竞选活动提供咨询。这位教授(碰巧部分是俄罗斯人,部分是美国人)将这些数据以大约 2 亿美元的价格卖给了 CA。此外,剑桥分析公司的大投资者之一是一名共和党参议员,他也是特朗普总统竞选活动的重要助手。剩下的就是让我们把这些点联系起来。

下面的截图来自教授和他在加州大学的团队之间的电子邮件交流(克里斯·怀利成为了其中的一个告密者)。

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

“This is a start to get you thinking about what you may want…”

CA 争议不仅凸显了如何使用大数据分析/AI&ML 世界的技术来“大规模社会工程化”像民主这样的长期制度,它还对跨几个系统和组织边界的治理失败进行了出色的研究。这是一个严重的提醒:保护我们的隐私是如何建立在站不住脚的承诺之上的,而这些承诺可能会被一股令人信服的商业价值主张冲掉。

随着基于人工智能和人工智能的商业机会的扩大和变得更加普遍,各行各业的隐私和安全专业人士可能会面临类似的困境,即在收集和保留个人数据以及对其使用保持透明方面,应该在哪里划定界限。从一开始就没有非黑即白的事情——但是现在可能会有更多的灰色阴影。

正如我们所看到的,不幸的消费者记住这一点很重要:

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

On the internet you are the product!

说到这个话题,另一件需要注意的事情是,我们在社交网络平台上留下的“赞”已经被证明是关于我们的丰富信息来源。这项研究表明,只要知道 10 个赞,计算机模型就能判断或理解某人的个性,就像判断或理解同事一样,70 个赞时,它能胜过朋友,150 个赞时,它能胜过家庭成员,300 个赞时,它能胜过配偶!!

大数据、隐私和匿名

尽管 AI/ML 将挑战推向了一个全新的水平,但自大数据本身的早期以来(即远在机器学习回归主流之前),对隐私的担忧就一直很普遍。

许多大数据场景带来的一个经典问题是“推理控制”的挑战,即在不泄露数据集中个人隐私敏感信息的情况下,为各种研究/调查项目共享大规模数据集的摘录的能力。在深入研究机器学习环境中的隐私方面之前,让我们探索一下在挖掘大型数据集时多年来开发和使用的技术。

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

Privacy concerns have been around since early days of Big Data

包含人员数据的数据库通常具有列/属性,从隐私的角度来看,这些列/属性可以是以下类型之一:

(a)【PII】—这些栏目可以直接链接或识别一个人(例如,社会保险号、电子邮件地址等)。).

(b) 准标识符(QI) —这些列本身可能没有用处,但可以与其他 QI、查询结果和一些外部信息结合使用,以识别个人身份(例如,邮政编码、年龄、性别等)。).

© 敏感栏 —这些属性不是 PII 或 QI,但构成出于各种原因(如工资、HIV 诊断、居住地理位置等)需要保护的个人的数据。).

(d) 非敏感列 —这些是不符合上述(a)、(b)或©的剩余属性(例如,国家)。

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

Types of attributes from a privacy standpoint

显然,在合格中介机构存在的情况下,仅仅从数据集中删除 PII 列不足以保护隐私。例如,如果一个数据集中存在基本的人口统计数据(称为 QI ),那么它可以与其他公共数据源(如选民登记名单)相结合,以非常准确地识别个人。几年前,研究人员使用了这种方法,当时他们发现为 Netflix Prize 比赛共享的“匿名化”数据集可能会通过与另一个公共数据源的一些数据相关联而受到损害。IMDB 上用户对电影的评级。在这种情况下,研究人员利用 IMDB 公开提供的几个数据点来挖掘网飞数据集,并揭示了个人的整个电影观看历史(这被认为是敏感的,受美国隐私法规保护)。

那么什么可能有用呢?

向’k-匿名 '、'l-多样性 '和’t-亲密度 '问好。

K-匿名用于保证对大型数据集的任何任意(基于 QI 的)查询都不会暴露有助于将群体缩小到“K”个人阈值以下的信息。也就是说,该技术提供了一种保证,即对于任何使用他们对特定个人的 qi 的知识从数据集中挖掘隐私敏感属性的人来说,将保持“至少 k”个记录的模糊性。

在这种情况下,具有一个或多个 qi 的相同值的数据集子集被称为“等价组”(或“等价类”)。例如,'在某个邮政编码的所有 30 岁以下的女性可以构成一个等价组。目标是确保攻击者无法利用此类查询来缩小范围并获取特定人员的敏感信息。本质上,“k-匿名”确保数据集的所有可能等价组至少有“k”条记录。

这是通过使用以下技术实现的:( a) 清除记录或列,其中一些记录可能被完全清除,或者某些 QI(例如,性别)可能在其他记录中被替换为“*”;或者(b) 概括,其中特定 QI 值被范围(例如,63 年→55-70 年)或数字替换为分类值(例如,87% →“通过”)—从而降低基于 QI 的查询对数据集的精确度。

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

A ‘k-anonymized’ result set (k=3)

对 k-匿名的攻击— 如果来自数据集的不同子集(可能出于不同目的发布)的结果未经排序,则“k-匿名”中使用的技术可能会受到攻击。例如,为不太敏感的场景发布的子集可能有一个有用的 QI,攻击者碰巧将它链接到使用其他信息的个人。然后,攻击者可以查看同一数据的一个更敏感的子集,如果这些行恰好处于相同的顺序,则将个人与敏感信息(例如,疾病)相关联。对此的缓解是随机化每个释放子集的顺序。

如果在每个等价组中包含敏感属性的记录没有足够的多样性,则另一类攻击开始起作用。在这种情况下,攻击者可以使用个人的一些背景信息来推断他们的敏感数据。在极端情况下,如果一个等价组中的所有记录都具有相同的敏感属性的值,那么攻击者甚至可以在没有背景信息的情况下做出推断。例如,如果匿名化的数据集揭示某一年龄范围(例如,20-30 岁)的个人的所有记录都患有特定疾病,并且如果攻击者知道特定的人(例如,该年龄组中的邻居)在数据集中,则他们可以断定此人患有相同的疾病。

因此,虽然 k-匿名提供了对 成员推断 攻击的抵抗,但是它不能防止“属性推断”攻击(这种攻击来自等价组的同质性)。

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

k-anonymized data lacking attribute diversity can leak sensitive info

L-Diversity 试图通过确保等价组具有“**属性多样性”**来解决这个问题。也就是说,它确保具有相同 QI 值(例如,相同年龄组)的数据集子集具有敏感属性的“足够多样性”(至少“l”个不同值)。此外,它试图在所有可能的等价组中达到这一点。请注意,“l-多样性”与“k-匿名”携手工作——它将“属性推断”保护添加到受“k-匿名”保护的“成员推断”数据集。

虽然“l-多样性”涵盖了“k-匿名”的弱点,但在具有许多 qi 的数据集上实现这一点是复杂和困难的(因为这会导致需要处理大量等价组)。此外,攻击者可以利用(a)属性值之间的语义关系或者(b)属性值具有非常不同的敏感度级别的情况来提取私人信息。它还假设攻击者不知道敏感属性在整个数据集中的实际全局分布(这通常是不正确的)。

T-closure通过有意识地保持每个敏感属性在等价组中的分布“接近”其在完整数据集中的分布来缓解这些弱点。在“t-接近度”中,敏感属性在等价组中的分布与该属性在整个表(或群体)中的分布之间的距离不超过阈值“t”。此外,它使用推土机距离(EMD)的概念来表示分布之间的“距离”,因为它具有消除不同属性敏感性影响的优点。

输入 AI/ML

当我们将 AI/ML 的算法和技术引入大数据领域时,挑战会上升到一个完全不同的水平。这是因为,与传统的基于查询/规则的数据提取/三角测量方法不同,ML & AI 场景可以以任意复杂的方式组合数百个输入维度/特征,因此,可以以迄今为止未知和不可理解的方式危及隐私。

大数据时代的技术在这个生态系统中苦苦挣扎。例如,“k-匿名”依赖于找到附近“k 记录”的能力,以返回进行查询——这是超维空间中一个已知的挑战/模糊的概念。例如,一个在线购物网站存储了数百个关于其客户的属性。当每个记录有如此多的维度时,“近邻”的概念变得很难确定——忘记能够对所有等价组都这样做吧!

现在让我们来看看一些有帮助的基本原则和当前的努力。

将隐私融入机器学习

差异隐私

最近许多分析 AI/ML 算法隐私保证的工作都利用了一个叫做差分隐私 (DP)的概念。

差分隐私提供了一个数学框架,可用于理解机器学习算法在多大程度上“记住”了它不应该记住的个人信息——从而提供了评估 ML 算法的隐私保证的能力。这是非常宝贵的,因为我们希望模型从数据集学习一般概念(例如,工资高于 X 的人比工资低于 Y 的人购买无人机的可能性高 90%),而不是可以揭示组成数据集的个人的身份或敏感数据的特定属性(例如,约翰的工资是 X)。此外——与“k-匿名”及其同类假设的攻击模型不同——差分隐私不假设攻击者可获得的背景知识的水平或范围。

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

DP — the adversary cannot tell if the training set contained a specific record

尽管“差异隐私”这个术语已经成为一个时髦的词(特别是在苹果宣布这种方法支持他们在各种 iOS 设备上的隐私保护工作之后),但它是基础性的,因为研究人员正在各个人工智能/人工智能领域投入大量努力,以确保算法和机器学习的构建模块可以变得“差异隐私”。

差分隐私通过在处理期间添加受控量的“噪声”来实现其目标,以便在下游生成足够的模糊性,使得不能基于来自系统的预测做出影响隐私的推断。此外,这样做的同时还能确保预测足够准确,具有实用性。它基于固定“隐私预算”的概念,并为评估各种数据操作的隐私损失提供了一个基础——最终指定如何限制损失,同时实现数据效用损失的可接受折衷。

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

The mathematical gist of Differential Privacy (Image from this deck.)

在 iOS 用例中(采用差分隐私),苹果使用三种关键机制来保护隐私,同时仍然了解用户在各种环境下的一般行为模式。例如,在寻找“的过程中,哪些表情符号是流行的?’,首先,哈希用于确保他们的后端服务不会获得任何关于用户的直接识别数据。其次,通过仅报告每个用户活动的随机子集来采用子采样(即,不是发送可能感兴趣的每个数据点,而是仅发送子集)。最后,即使对于 T2 发送的数据,噪声也会被注入,因此特定用户的击键模式在后端看到时也只是大致准确。隐私感知后端算法能够在跨设备聚合数据的同时“过滤”噪音,以了解用户行为的一般模式,并在此基础上改善用户体验。因此,例如,如果确定某个特定的表情符号越来越受欢迎,它就会被添加到所有用户都能看到的快速访问表情符号集中。同样,一旦确定特定的“本地”词典单词已经被许多用户添加,它就被添加到所有用户的词典中。

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

Trending emojis learned with local (client-side) differential privacy on iOS

PATE 框架

差分隐私提供了一种通用技术,可以在 AI/ML 环境中以各种方式应用。教师集合的私有聚集(PATE)框架应用差别隐私来为根据用户数据训练的模型提供整体隐私保证。PATE 框架中的关键直觉是*“如果两个基于独立数据训练的模型在某些结果上达成一致,那么向消费者分享该结果就不太可能泄露任何关于特定用户的敏感数据”。*

该框架将私有数据划分为子集,并在每个子集上独立训练不同的模型(称为“教师”)。总体预测是通过组合教师模型“整体”的各个预测而生成的。这本身并没有增加任何隐私成分。这是通过两个重要步骤实现的。首先,在组合单个教师的结果时会添加噪声,因此组合的结果是单个教师预测的“有噪声的集合”。第二,来自教师总体的这些有噪声的预测被用作“标记的训练数据”来训练下游的“学生”模型。就是这个学生模型被暴露给终端用户消费。PATE 框架的作者撰写的这篇文章更为详细。

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

Private Aggregation of Teacher Ensembles (PATE)

联合学习

联合学习采取了一种有些不同的方法来保护众包学习场景中的隐私。关键的想法是,如果我们可以设计出从数据子集(孤岛)中学习的方法,然后有效地汇总我们的学习,为什么还要把所有的数据聚集在一起呢?’。

这使得在几种有趣的情况下学习成为可能。例如,一组医院可能对应用 ML 技术来改善患者的医疗保健感兴趣,但是(a)单个医院可能没有足够的数据来独自完成这项工作,以及(b)他们可能不想冒险将他们的数据用于集中汇总和分析。这是应用联合学习的理想场景。

另一个常见的场景是使用机器学习来改善跨设备平台的用户体验,而无需将用户活动数据从单个设备移动到中央服务(此处描述为)。在后一种情况下,每个设备从中央位置下载一个(定期改进的)模型,并在本地应用 ML 来对要提交回中央服务器的模型进行“微改进”。这种方法越来越受欢迎,还因为每个设备上本地可用的数据越来越丰富(因此本地学习非常有益,隐私约束更少),以及与过去相比更强大的设备端处理器(使得计算密集型 ML 算法可行)。

同态加密

最后,通过利用一种称为同态加密(HE)的加密技术,人们也在努力使用密码术来提供机器学习中的隐私保证。

当使用传统技术对数据进行加密时,就不可能对加密形式的数据进行任何有意义的计算。随着云计算的广泛采用,人们经常会遇到这样的情况:拥有敏感数据的一方想要将对该数据的一些计算外包给它不信任明文数据的第三方。同态加密基本上提供了对加密数据执行各种有意义的操作的能力,而无需直接访问加密密钥或纯文本数据本身。使用同态加密,服务可以对加密数据执行请求的计算,并将(加密的)结果返回给客户端。然后,客户端可以使用加密密钥(从未与服务共享)来解密返回的数据并获得实际结果。

同态加密本身是一个不断发展的领域。性能是一个很大的问题,某些限制——例如只计算多项式函数的限制(ML 中的许多激活函数是非多项式的)和只计算整数模 n 的加法和乘法(大多数学习算法需要浮点计算)——意味着仍然有许多挑战要克服。然而,随着机器学习即服务(MLaaS)的日益流行,人们对改进利用同态加密来执行“加密”机器学习的技术产生了浓厚的兴趣。这两种变体都在探索中——对加密数据执行学习/预测的能力,以及使用加密模型对明文数据进行学习的能力。

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

Privacy regulations and machine learning

GDPR 和机器学习

《通用数据保护条例》(GDPR)于 2018 年 5 月生效,这是欧盟让全球组织认真对待个人数据的最新尝试。简而言之,GDPR 将任何处理(或外包处理)欧盟公民数据的实体/组织的隐私保护门槛推得更高。在同意处理、数据保护、违规披露和擦除方面有着严格的要求,对故意违规行为会处以重罚。此外,与它的前身数据保护指令(DPD)不同,它是一个“指令”(被成员国用作制定法律的指导方针),GDPR 是一个“法规”(一个法律本身)。

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

The GDPR went into effect from May 2018

《GDPR》中的一些条款就其对人工智能/洗钱的潜在影响激起了许多讨论和辩论。让我们简单地看看几个突出的例子。

“潜在可识别”数据的解释

在“适用范围”部分,GDPR 声明该法规适用于*“所有可能识别数据主体的欧盟公民数据”。这本身就提出了一个有趣的难题。鉴于人工智能/人工智能算法的巨大能力和洞察力,是否有可能将任何处理关于人的数据(以任何形式和出于任何目的)的系统明确排除在 GDPR 的管辖范围之外?你能确定你正在处理的关于人的数据不会以任何方式被用来识别任何对象吗?*

此外,探索性数据分析(EDA)是帮助数据科学项目走向创新和有趣见解的最有价值的活动之一。GDPR 规定,未经数据主体的进一步同意,数据处理者不得将数据用于超出原始意图的任何目的。这最多会大大减慢探索的速度。

明确禁止人们服从“自主”决定

GDPR 明确禁止数据主体受制于自主决策的结果。但这就是这么多 AI/ML 主流用例的全部本质,对吧?这一条款是否意味着不能将 ML 应用于欧盟公民的数据?当有人浏览一个网站时显示广告是否构成了自动决策?有许多这样的问题需要解释。当谈到 AI/ML 的使用时,似乎有一个出路,大多数组织可能会依靠它。基本上,如果自主决策是(a)履行合同义务所必需的或出于法律原因所需要的,或(b)当数据主体明确同意时,这一禁令不适用。

解释的权利

这是一个棘手的问题。GDPR 要求应向数据主体提供充分的解释,这些主体可能希望了解为什么基于对其数据的使用做出某个(自动)决定。这样做的目的是提高透明度,并确保这种系统是公正的。

然而,机器学习模型的复杂性以及解释它们如何得出预测或结果的严重困难,使这成为一项艰巨的任务。尚不完全清楚这些解释需要“细化”到何种程度才能被监管机构接受。例如,如果使用深度神经网络(DNN),数据处理器是否需要解释随机梯度下降(SGD)的内部工作原理,显示各层的权重向量,并解释卷积和丢失的逻辑等。大多数深度学习专家说,很多时候,甚至他们也不明白为什么这一切都行得通——但它确实行得通!还有知识产权保护的问题可能会在某个时候出现。

当每个人都在等待“案例法”出现并澄清这方面的确切立场时,让机器学习变得可以解释的工作正在进行中。一个例子是局部可解释模型不可知解释(LIME) 中概述的方法。LIME 基本上将潜在的非常复杂的实际模型视为一个黑盒,并试图纯粹通过研究更复杂的模型提供的输入和做出的决策来重新创建一个更简单(更容易解释)的表示。此外,它试图“局部地”这样做,也就是说,它采用要寻求解释的特定预测,并对输入向量进行扰动,以查看输入的哪些方面在所做的决策中具有显著影响或更大权重。这承认了一个事实——尽管对一个模型的每一个方面进行彻底的解释可能令人望而生畏——我们仍然可以努力理解具体的决策。

被遗忘的权利

根据 GDPR 的说法,数据主体可以要求处理器删除他们可能已经存储的关于该主体的所有数据(相当于撤回过去同意使用个人数据)。这项规定旨在授权数据主体控制各种数据处理者对其数据的长期使用和保留。(它最初是由引入的,因为它认识到保护改过自新的个人不被互联网上关于他们过去罪行的信息永久玷污的基本需要。)

当数据主体的数据用于机器学习时,当他们撤回同意或请求删除数据时,会出现一个有趣的问题。是否应该要求数据处理器在没有特定对象数据的情况下重新训练先前训练过的模型?显然不是!GDPR 明确表示,撤销不影响或不适用于最初同意生效时所做的过去的处理。所以这应该是一种解脱。然而,正如我们在上一节中看到的,模型可能会记住它们不应该记住的东西,因此从训练好的模型开始重新创建潜在的可识别数据是可能的。这意味着,虽然您可能认为您已经删除了数据主体的数据,但它可能仍然是可恢复的!目前,这种风险似乎已经被学术界忽略了。

接下来呢?

前面关于 GDPR 及其许多规定背后的意图的讨论提出了关于人工智能/人工智能的社会含义的有趣问题。算法决策的公平性和偏见、伦理和道德等考虑因素可以在最深层次上激发我们的社会安全感。在下一篇文章中,我们将探索这些领域,并且可能从我们到目前为止所做的最广泛的意义上来看待 AI/ML 环境中的“安全性”。

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

透过编号的颜色看世界

原文:https://towardsdatascience.com/see-the-world-through-numbered-colour-d8635a2eaca7?source=collection_archive---------23-----------------------

香港 2016 年中期人口统计结果互动地图

起初,我只是想得到一些普查结果。这是了解我居住的地方和我周围的人的一个很好的来源。当我在香港政府网站找到 2016 年中期人口统计结果时,首先看到的是一张地图,然后在它的下面,是无数的表格。尽管被这些表淹没了,我仍然有一些控制权。我可以选择一个区域,它会返回给我一些表格。

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

Table Streak! (source)

我决定制作一些彩色地图来缓解我的眼睛,而不是看那些表格和数字来找出各个地区的人口特征。

中期人口统计数据

中期人口统计的结果包含了很多关于人口统计、教育、经济等方面的有价值的数据。这些数据按区议会、三级规划单位、新市镇和主要屋分组。要了解更全面的情况,区议会的人口特征是一个很好的起点。这些数据可以用 Excel 格式下载。全港共有 18 个区议会,因此,最简单的方法是下载全部 18 个 Excel 档案。每个文件代表一个区,有 11 个电子表格。每个电子表格都包含一个表,例如,电子表格 D4 包含“按种族和性别划分的人口”表。

为了使它更灵活,我创建了一个类“District”来处理数据。当读取 Excel 文件时,将创建一个实例,该实例将解析数据并将其转换为 DataFrame 和 Series。这里有一个例子。

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

District 类有一个 summary()方法,用来计算一些有用的统计量和比率,保存为熊猫系列。为了数据可视化,所有区议会摘要都保存为 demographic_summary_2016.csv。

地理空间数据

第二部分数据是地区边界的地理空间数据。

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

就是因为找不到已经可用的 GeoJson 数据,所以在 geojson.io 上划了 18 个区的界限,把它们标绘在地图上。以下是 GeoJson 数据的快照:

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

The name of the district is stored in the “properties”, and the coordinates are stored in “geometry”.

地图可视化

当数据准备好了,就该绘制等值线图了。这是一个有多个阴影或图案区域的地图,每个区域都根据统计变量按比例测量。可视化一个地理区域中的统计测量是如何变化的是非常有用的。制作 choropleth 地图有不同的方法。Folium 提供了一个有效的选项,让我可以更少地担心美观,而是更多地关注数据部分。

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

District name and the median age are displayed as tooltip

从上面的 choropleth 图,我们可以很容易地确定哪个地区的平均年龄最高。当光标位于选区边界内时,将显示选区的名称和年龄中位数。图层控件允许我们选择要可视化的数据。然而,当有更多的层时,屏幕可能会很混乱,因为所有的图例将同时显示。

幸运的是,Ipywidgets 提供了有用的小部件。它们是支持为 Jupyter 笔记本构建交互式 GUI 的多事件 python 对象。有各种类型的小部件可以让你的笔记本更加有趣和互动。为了使用 Ipywigets.interact 来显示地图,我们将地图保存为 HTML 文件。

现在,它有一个用于地图选择的下拉菜单。地图中的颜色表示该地区的种族密度百分比。举例来说,湾仔有 180123 人,其中 14706 人是菲律宾人,因此,湾仔约有 8%的人口是菲律宾人。

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

1 Map + 1 Legend at a time

所有的代码和地图都可以在 GitHub 库中找到。为了避免任何法律问题,Excel 文件不会放在存储库中,但可以从政府网站下载。我用于可视化的摘要 csv 文件可以在存储库数据文件夹中找到。

人口普查数据是一个很好的探索资源。给出正确的演示,所有这些数字都可以成为鼓舞人心的。我在上面制作的地图只是一个简单的例子,展示了如何使用 follow 和 Ipywidgets 将来自表格和数字的人口普查数据转化为丰富多彩的 choropleth 地图。我相信在这些资料中还有许多其他的选择和未被探索的故事。一如既往,我欢迎任何类型的建议,如果你有任何想法,请随时发表评论或通过 Twitter@ HLH _ 丹尼尔联系我。

只见树木不见森林:随机森林导论

原文:https://towardsdatascience.com/seeing-the-forest-for-the-trees-an-introduction-to-random-forest-41a24fc842ac?source=collection_archive---------22-----------------------

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

随机森林非常整洁。他们利用集成学习来使用通常被认为是弱学习者的东西(决策树来创建一个更强更健壮的建模方法。

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

随机森林模型由决策树组成,因此在进入森林之前,确保您了解这些树是非常重要的。如果你需要复习决策树,请花点时间查看播种——决策树介绍

正如你可能知道的,决策树的两个主要限制是,它们容易过度拟合,并且它们往往不健壮,这意味着训练数据的微小变化会导致非常不同的树。随机森林模型通过生成许多决策树,然后将每棵树的预测聚合为单个模型预测,克服了决策树的这两个缺点。

创建然后组合一堆决策树的结果看起来很基本,然而,简单地从完全相同的训练数据中创建多个树不会有成效——它会产生一系列强相关的树。所有这些树都以相同的方式对数据进行排序,因此这种方法与单一决策树相比没有优势。这就是随机森林的奇特之处开始发挥作用。为了去相关组成随机森林的树木,进行了一个被称为引导聚集(也称为装袋)的过程。Bagging 通过用替换对原始训练数据进行采样来从原始数据集生成新的训练数据集(引导)。对于构成随机森林的尽可能多的决策树,重复这一过程。然后,每个单独的自举数据集被用于构建树。这个过程有效地降低了模型的方差(训练数据中随机噪声引入的误差,即过拟合),而不增加偏差(欠拟合)。就其本身而言,将训练数据打包以生成多棵树创建了所谓的打包树模型。

称为随机子空间方法(也称为属性装袋或特征装袋)的类似过程也用于创建随机森林模型。对于每棵树,对可能的预测变量的子集进行采样,从而为每棵树产生一个较小的预测变量集以供选择。这通过防止主要预测变量成为被选择来在每个单独的决策树中创建分裂的第一个或唯一的变量,进一步去相关树。如果不实施随机子空间方法,则存在一个或两个主要预测变量被一致地选为每个决策树的第一分裂变量的风险,并且所得的树将是高度相关的。bagging 和随机子空间方法的结合产生了随机森林模型。

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

bootstrap 聚合的聚合部分来自于组合这些决策树中每一个的预测,以确定总体模型预测。对于每个单独的记录,整个模型的输出是类的模式(分类)或单独的树的所有预测的平均预测(回归)。

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

在这种情况下,插入到(简化的)随机森林模型中的记录在大多数树(2/3)中被分类为杂色,因此随机森林会将该记录分类为杂色。

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

随机森林还有几个重要的组成部分需要强调。

出袋错误

Bagging 有效地导致大约 1/3 的原始训练数据被排除在每个单独的决策树之外。这些被排除的数据被称为袋外(OOB)观察值。这种效应已经被用来创建出袋 (OOB)误差估计,它可以用来代替交叉验证指标。

通过在每个决策树中运行不属于训练数据的记录,然后将这些结果聚合到单个预测中,可以计算出超出范围的误差。可以为所有训练记录确定 OOB 预测,这意味着可以计算总体 OOB MSE,并将其用作模型误差率。

可变重要性

关于随机森林的另一个巧妙之处是,在它们的实现过程中,预测变量重要性是通过利用基尼重要性来计算的,基尼重要性用于确定各个决策树的节点,以生成杂质的平均减少(MDI)。

MDI 是一个变量的节点杂质总减少量的平均值(mean ),通过随机森林中每个单独决策树中到达该节点的样本比例进行加权。用于创建随机森林模型的每个预测变量都有一个结果 MDI 值,该值用于对变量对模型的重要性进行排序。基尼系数的平均降幅越大,表明变量的重要性越高。

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

随机森林的局限性

随机森林在模型鲁棒性方面比决策树有所提高,但在可解释性和可接近性方面有所损失。在决策树中,您可以看到用于对目标变量进行排序的单个变量分割和阈值。这在随机森林中是不可能的,在随机森林中,数百棵树被聚集在一起以创建一个估计值。因为随机森林模型不太容易接近,也不容易解释,所以它们通常被视为“黑箱”

优势

随机森林与组成它们的决策树有许多相同的优点。它们可以应用于分类或连续目标变量,并且可以处理不平衡数据集、异常值和非线性关系。除了这些优势,随机森林往往比单个决策树有更好的预测能力,并且不容易过度拟合。随机森林模型在估计分类数据时往往表现很好。

总之……

随机森林是一种集成机器学习方法,通过创建多个决策树,然后通过聚合各个树的预测将这些树组合成一个模型,来利用决策树的个体预测能力。随机森林比决策树更健壮,并且往往具有更好的预测能力。然而,它们也更不透明,看起来更令人生畏。希望这篇文章已经让你看到了(决策)树的森林,并向你展示了随机森林是多么整洁。

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

https://www.youtube.com/watch?v=Hm3JodBR-vs

原文。经允许重新发布。

OCR 中的分割!!

原文:https://towardsdatascience.com/segmentation-in-ocr-10de176cf373?source=collection_archive---------4-----------------------

OCR 系统使用的不同分段级别的基本说明。

欢迎来到关于 OCR 系统工作的第三部分**。在 上一篇 中,我们已经看到了 OCR 系统中基本且广泛使用的预处理技术。**

在这一部分,我们将介绍 OCR 系统的另一个最重要的阶段的技术,

分割 无非是 将整幅图像分割成子块,以便进一步处理

图像的分割按以下顺序进行:
→行级分割
→词级分割
→字符级分割

对于上述所有级别的分割,我们将使用直方图投影技术*。*

直方图投影法

下面我给大家简单介绍一下直方图投影法。一旦彩色图像被转换成二进制图像,图像中就只存在黑色和白色像素。

在二值图像中,代表有用信息的像素称为,非前景像素的称为 背景像素。 我们在对图像进行二值化时,选择前景像素应该是白色还是黑色。**

水平直方图投影: 在这种方法中,我们沿着图像的行统计前景像素的号,得到的数组的大小等于图像中行的号(图像的高度)。

**# img be binarized image of size height x width and foregound pixel is white i.e pixel value = 255
**horizontal_hist = np.sum(img,axis=1,keepdims=True)/255**
# axis = 1 is used to take sum along the row
# horizontal_hist is an array of size height x 1# If the img has foreground pixel as black i.e pixel value = 0
**horizontal_hist = img.shape[1] - np.sum(img,axis=1,keepdims=True)/255**
# Logic :- No.of columns - No.of white pixels**

horizontal_hist 绘制成直方图,如下所示

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

No.of White pixels (foreground) in each row. Source: researchgate.net

在上图中,

  • 较高的峰值意味着相应行中前景像素的数量较高。
  • 较低的峰值意味着相应行中前景像素的数量较低

垂直直方图投影: 该方法中,我们统计前景像素沿图像列的个数。结果数组的大小等于图像中列的号(图像的宽度)。

**# img be binarized image of size height x width and foregound pixel is white i.e pixel value = 255
**vertical_hist = np.sum(img,axis=0,keepdims=True)/255**
# axis = 0is used to take sum along the column
# vertical_hist is an array of size 1 x width# If the img has foreground pixel as black i.e pixel value = 0
**vertical_hist = img.shape[0] - np.sum(img,axis=0,keepdims=True)/255**
# Logic :- No.of rows - No.of white pixels**

vertical_hist 绘制成直方图,如下所示

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

No.of Black pixels (foreground) in each column. Source: researchgate.net

注意:上图中,前景像素为黑色,背景像素为白色。

在上图中,

  • 较高的峰值意味着相应列中的前景像素的数量较高。
  • 较低的峰值意味着相应列中的个前景像素的数量较低。

既然我们已经理解了水平垂直直方图投影,我们就准备知道不同层次的 分割 是如何执行的。

  1. 线级分割: 在这一级分割中,我们被提供一个倾斜校正图像包含以线的形式书写的文本。线级分割的目的是将的图像分割成线条** 。**

写作的一般规则:我们应该在行间留有足够的空间。

这个想法是,如果我们水平投影二进制图像,

  • 表示一行中文本的行具有高数量的前景像素 ,其对应于直方图中较高的峰值
  • 表示线间间隙的行具有高数量的背景像素 ,其对应于直方图中的较低的峰值

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

Horizontal Projection of image, Counting No.of Foreground pixels in each row. Source: Image by the author.

对应于直方图中较低峰值的行可以被选择作为分割线来分离这些线。

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

Segmenting the image as lines by selecting the rows which have lower peaks. Source: Image by the author.

2.单词级分割的目的是 将图像分割成单词

写作的一般规则:我们应该在单词之间留有足够的空间。

这个想法与上一步类似,但唯一的变化是,这里我们必须垂直投影图像(沿列求和),因为我们必须垂直分割单词。

如果我们垂直投影二进制图像,

  • 表示文本的列具有高数量的前景像素 ,其对应于直方图中较高的峰值
  • 表示单词之间间隙的列具有高背景像素数 ,其对应于直方图中的较低峰值

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

Vertical Histogram Projection of image. Source: researchgate.net

注:上图中,前景像素为黑色像素,背景像素为白色。

我想你已经搞清楚上图的分词是怎么做的了。可以选择对应于直方图中较低峰值的列作为分割线来分隔单词。

对于分割单词,应该以这样的方式选择较低的峰值,即它们应该跨越一定的宽度(阈值)。这是因为我们会发现较低的峰值,这些峰值对应于一个单词中不相连的字符之间的间隙,这是我们不感兴趣的。众所周知,单词之间的间隙大于单词内字符之间的间隙,阈值的选择应忽略单词内字符之间的细小间隙。

3. 字符级分割: 在这一级别的分割中,我们得到一个包含一个单词(在前面的步骤中被分割)的图像,该单词由一系列字符组成。字符级分割的目的是 将图像分割成单个字符

这一级别的分割是可选的,这取决于使用 OCR 的上下文。

  • 如果将 OCR 系统应用于文本,其中一个单词中的 字符是单独的字符级分割是不需要的由于一个单词中的字符之间保持一致的间隙(即使它很小),我们可以在前面的步骤中分割字符(通过设置非常低的阈值)。**
  • 如果将 OCR 系统应用于文本,其中一个单词中的 字符被连接 (草书),必须执行字符级分割来分割字符。

通过利用字符之间的小间隙,我们可以使用我们用于单词级分割的相同思想,即通过垂直投影图像,我们可以分割字符。

*在*字符级切分中,字符的切分并不简单,因为草书中的 连字 的概念。

什么是连字??
连字是连接草书中两个连续字符的纽带。

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

Source: Image by the author.

现在你可能在想, 这个连写产生了什么问题………对吗?
在英文剧本中,我们有两种类型的人物**

  • 闭合字符: 这些字符有一个循环,垂直投影时,横跨这些字符的所有列至少有 2 个前景像素 。如 a、b、c、d
  • 开放字符: 这些字符没有循环,垂直投影时,跨越这些字符的所有列中,至少有一列只有 1 个前景像素。如 u,v,w

因此,OCR 系统无法将带有曲线的连字与开放字符区分开,并认为两者都是有效的分割候选。这个问题被称为 过度分割问题

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

Ligature problem for the word “umn” written in Cursive. Source: Image by the author.

注意: 上图中,为了分割,有效候选是连字(u,m & m,n 之间的连接),无效候选是那些,是开放字符 u,m,n 的一部分【我们不能在字符之间分割】

**到目前为止,我们还没有解决这个问题的完美方法,但是这里有一个基本的和广泛使用的方法来克服这个问题。

我们假设 细化 到 1 像素宽。因此,垂直直方图数组中可能的 sum 为
sum=0 ,如果列
sum=1 ,如果列
sum>1中存在连字或部分开放字符,如果列中存在部分封闭字符。例如 o,p(在每一列中具有一个以上的前景像素)**

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

Source: Reference[1]

在上图中,用红色标记的列要么有垂直直方图 sum=0 要么有 sum=1 。这些列被称为 PSC ( 潜在分割列)。

遵循以下规则选择有效线段(不总是选择有效线段,但大多数时候选择有效线段):-

  • 两个连续字符之间的垂直空白,即沿该列的*【sum = 0】,*** ,表示不存在前景像素。所以我们可以在这些连续的列中选择中间的列。**
  • 当有一列 sum=1, 表示存在连字或部分开放字符时,在这种情况下, 过度分割问题 通过取所有那些距离小于特定值(阈值)的 PSC 的平均值并通过将它们合并成单个 SC(分割列)在很大程度上得以消除。阈值是沿着连续 PSC 之间的单词图像宽度的最小距离,并且被选择为使得其值必须小于单词图像中可能的最细字符的宽度(例如,I,l)。现在,所有这些 SC 都通过用大量数据训练的机器学习模型来验证。如果 SC 成为有效分段线的概率很高,则认为它是有效分段线;否则,它将被忽略。

通过遵循上述规则,我们可以在 90%的情况下正确分割字符。

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

Word Images Showing all types of Segmentation Errors. Source: Reference[1]

最后的话

在这个由 3 部分组成的系列中,我们对 OCR 系统的工作有了一个较高层次的概述,并涵盖了 OCR 系统的两个最重要的阶段分割

我希望你能理解并喜欢阅读这篇文章!!!

欢迎任何质疑、建议、指正。

快乐学习……结束😀😀

参考资料:

[1] Choudhary,Amit & Rishi,Rahul & Savita,Ahlawat。(2013).一种新的脱机手写草书字符分割方法。计算机科学。17.88–95.10.1016 年 5 月 13 日

[2]桑切斯、a .和苏亚雷斯、P.D .和梅洛、卡洛斯和奥利维拉、阿德里亚诺和阿尔维斯…(2008).手写历史文献图像中的文本行分割。1–6.10.1109/ipta . 2008 . 436386363637

[3]库尔尼亚万、法杰里和沙夫里、莫哈末和拉希姆、莫哈末和马图斯、尼和拉赫马迪、阿克毛和穆罕默德、祖尔基弗利。(2011).基于轮廓分析和神经网络验证的草书手写体字符分割。ITB 信息与通信技术杂志。5.10.5614/itbj.ict

图片来源: 谷歌

利用机器学习细分信用卡客户

原文:https://towardsdatascience.com/segmenting-credit-card-customers-with-machine-learning-ed4dbcea009c?source=collection_archive---------14-----------------------

利用无监督机器学习识别可销售细分市场

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

Photo by Ryan Born on Unsplash

市场营销中的细分是一种技术,用于根据行为或人口统计等属性将客户或其他实体分成不同的群体。确定可能以类似方式对特定营销技术(如电子邮件主题行或展示广告)做出反应的客户群非常有用。因为它使企业能够定制营销消息和时机,以产生更好的响应率并提供改善的消费者体验。

在接下来的文章中,我将使用一个包含信用卡客户行为属性的数据集。数据集可以从 Kaggle 网站下载。我将使用 scikit-learn python 机器学习库来应用一种称为聚类的无监督机器学习技术,以识别人类认知可能不会立即显现的片段。

该数据集由 18 个信用卡客户行为特征组成。这些变量包括当前卡上的余额、账户上的购物次数、信用额度等。完整的数据字典可在数据下载页面找到。

设置

我在JupyterLab中运行以下代码。我正在使用iPython magic扩展水印来记录我正在运行的工具的版本。如果您在运行代码时遇到任何问题,其输出如下所示。库导入也显示在下面。

%load_ext watermark
%watermark -d -m -v -p numpy,matplotlib,sklearn,seaborn,pandas -g

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

import pandas as pd
import numpy as npfrom sklearn.cluster import KMeans
from sklearn import preprocessingimport matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns

数据清理

首先,我们需要检查数据,找出可能需要的清理和转换。scikit-learn 库要求所有数据都没有空值,并且所有值都必须是数字。

首先,我已经阅读了下载的 csv 文件。

TRAIN_FILE = 'CC GENERAL.csv'
train_data = pd.read_csv(TRAIN_FILE)

首先,我运行下面的代码来检查数据类型,看看是否有需要转换的分类变量。从结果中我们可以看到,除了CUST_ID以外,所有的特征都是数字。但是因为我们不需要这个特性来训练模型,所以我们不需要在这里做任何转换。

print("Data Types:", train_data.dtypes)output:
Data Types: CUST_ID                              object
BALANCE                             float64
BALANCE_FREQUENCY                   float64
PURCHASES                           float64
ONEOFF_PURCHASES                    float64
INSTALLMENTS_PURCHASES              float64
CASH_ADVANCE                        float64
PURCHASES_FREQUENCY                 float64
ONEOFF_PURCHASES_FREQUENCY          float64
PURCHASES_INSTALLMENTS_FREQUENCY    float64
CASH_ADVANCE_FREQUENCY              float64
CASH_ADVANCE_TRX                      int64
PURCHASES_TRX                         int64
CREDIT_LIMIT                        float64
PAYMENTS                            float64
MINIMUM_PAYMENTS                    float64
PRC_FULL_PAYMENT                    float64
TENURE                                int64

运行下面的代码告诉我,只有两个特性具有空值“CREDIT_LIMIT”和“MINIMUM_PAYMENTS”。此外,每列中只有不到 5%的部分为空。这意味着我们应该可以用合理的替换值来填充它们,并且应该仍然能够使用该特性。

train_data.apply(lambda x: sum(x.isnull()/len(train_data)))Output:
CUST_ID                             0.000000
BALANCE                             0.000000
BALANCE_FREQUENCY                   0.000000
PURCHASES                           0.000000
ONEOFF_PURCHASES                    0.000000
INSTALLMENTS_PURCHASES              0.000000
CASH_ADVANCE                        0.000000
PURCHASES_FREQUENCY                 0.000000
ONEOFF_PURCHASES_FREQUENCY          0.000000
PURCHASES_INSTALLMENTS_FREQUENCY    0.000000
CASH_ADVANCE_FREQUENCY              0.000000
CASH_ADVANCE_TRX                    0.000000
PURCHASES_TRX                       0.000000
CREDIT_LIMIT                        0.000112
PAYMENTS                            0.000000
MINIMUM_PAYMENTS                    0.034972
PRC_FULL_PAYMENT                    0.000000
TENURE                              0.000000

下面的代码用列中最常出现的值填充缺少的值。我们同样可以使用均值或中值,或者其他方法,但如果需要,我们将从这里开始迭代。

train_clean = train_data.apply(lambda x:x.fillna(x.value_counts().index[0]))

我还将删除CUST_ID列,因为我们在培训中不需要它。

cols_to_drop = 'CUST_ID'
train_clean = train_clean.drop([cols_to_drop], axis=1)

特征缩放

在训练模型之前,我要做的最后一项处理是缩放特征。

我在这篇文章中使用的聚类模型是 K-Means。简单来说,下面是该算法的工作原理:

  1. 取预定数量的簇。
  2. 找到每个聚类的质心,实质上就是平均值。
  3. 根据平方欧几里得距离将每个数据点分配给其最近的聚类。
  4. 一旦训练了新的看不见的数据点的聚类,就可以基于欧几里德距离来识别。

因为它依赖于这种距离度量特征,所以缩放是一个非常重要的考虑因素。在我使用的数据集的例子中,让我们取两个特征PURCHASES_FREQUENCYBALANCE。特征PURCHASES_FREQUENCY是一个介于 0 和 1 之间的数字,而BALANCE在这个数据集中是一个介于 0 和 19,043 之间的货币值。这些特征具有非常不同的尺度,这意味着如果我们不对它们进行标准化,使它们处于相同的尺度上。可能存在算法将给予一个变量更多权重的情况。

以下代码缩放数据框中的所有要素。我在第一次迭代中使用了 min_max_scaler。不同的缩放技术可能会产生不同的结果。

x = train_clean.values
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
train_clean = pd.DataFrame(x_scaled,columns=train_clean.columns)

为了说明这一点,这里是缩放前的PURCHASES_FREQUENCYBALANCE 列。

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

缩放后。

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

有多少个集群?

我之前提到过,我们需要告诉 K-Means 算法它应该使用的聚类数。有许多技术可以用来找到最佳数量。对于这个例子,我将使用肘方法,这样命名是因为它产生的图表在形状上类似于肘的曲线。此方法计算聚类 k 的距离平方和。随着使用的聚类越来越多,方差将会减少,直到达到某个点,在该点上增加聚类不再会产生更好的模型。从这篇文章中借用的代码说明了这一点。谢谢托拉孙心怡

Sum_of_squared_distances = []
K = range(1,15)
for k in K:
    km = KMeans(n_clusters=k)
    km = km.fit(train_clean)
    Sum_of_squared_distances.append(km.inertia_)plt.plot(K, Sum_of_squared_distances, 'bx-')
plt.xlabel('k')
plt.ylabel('Sum_of_squared_distances')
plt.title('Elbow Method For Optimal k')
plt.show()

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

您可以看到,在 8 个集群之后,添加更多集群对模型的好处微乎其微。因此,我将使用 8 个聚类来训练我的模型。

培养

在训练之前,我将把数据集分为训练集和测试集。下面的代码划分数据,保留 20%用于测试。

np.random.seed(0)
msk = np.random.rand(len(train_clean)) < 0.8
train = train_clean[msk]
test = train_clean[~msk]

然后,我将训练集和测试集都转换成 numpy 数组。

X = np.array(train)
X_test = np.array(test)

接下来,我使用 8 个集群调用 KMeans fit 方法。

kmeans = KMeans(n_clusters=8, random_state=0).fit(X)

使用训练好的模型,我现在将预测测试集上的聚类。

y_k = kmeans.predict(X_test)

现在,我将把预测指定为原始测试数据框上的一个新列,以分析结果。

test['PREDICTED_CLUSTER'] = y_k

分析集群

我将使用 pandas groupby 函数来分析聚类的一些选定特征,以了解模型是否成功识别了独特的片段。

train_summary = test.groupby(by='PREDICTED_CLUSTER').mean()
train_summary = train_summary[['BALANCE', 'PURCHASES', 
                               'PURCHASES_FREQUENCY','CREDIT_LIMIT', 
                               'ONEOFF_PURCHASES_FREQUENCY', 
                              'MINIMUM_PAYMENTS','PRC_FULL_PAYMENT', 
                               'PAYMENTS']]
train_summary

这给出了以下输出。

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

只需查看“PURCHASES_FREQUENCY ”,我们就可以看到该模型已经识别出一些高频购买细分市场,即集群 2 和集群 3。让我们了解这两个部分之间的差异,以进一步确定它们为什么在不同的群集中。我们可以看到,集群 3 的总购买次数更多,信用额度更高,他们经常进行一次性购买,更有可能全额支付。我们可以得出结论,这些都是高价值的客户,因此几乎可以肯定的是,你如何向这些客户营销会有所不同。

作为模型的第一次迭代,这似乎是识别一些有用的部分。我们可以通过多种方式调整模型,包括替代数据清理方法、特征工程、删除高相关性特征和超参数优化。然而,出于这篇文章的目的,我想给出一个关于如何启动一个执行无监督聚类的机器学习模型的高级端到端视图。

细分网站导航会话

原文:https://towardsdatascience.com/segmenting-website-navigation-sessions-f9258117737c?source=collection_archive---------28-----------------------

使用主题建模发现网站导航模式

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

Photo by Rodion Kutsaev on Unsplash

目标和应用

本文将展示一种方法,使用主题建模方法,根据访问的页面对网站导航会话进行分段。

这有一些可能的应用:描述性分析、面向细分市场的营销、定制网站导航模式等等。它还可以让你了解人们如何使用你的网站,什么类型的内容经常一起出现,等等。

你也可以尝试同样的方法来细分用户而不是会话,并在营销活动中以不同的方式针对这些细分市场,或者将这些数据与现有的交易细分市场进行交叉,以了解每个细分市场如何使用你的网站。

使聚集

聚类意味着根据相似性对对象进行分组。有许多方法可以做到这一点,这也是因为什么是集群有许多不同的定义。共同点是集群是一组数据对象。

硬聚类方法将每个对象分类为仅属于一个聚类;而软聚类给予这些对象每个对象属于一个聚类的程度(例如使用可能性)。

主题建模

另一方面,主题建模用于根据经常一起出现的单词从文本中推断主题。一种可用于此的算法是潜在狄利克雷分配(LDA)。在 LDA 中,我们给它一组文档,我们设置我们认为有多少个主题,它返回给我们一个主题列表,每个主题都由一个最能识别它们的单词列表来描述。

用于识别导航模式的 LDA

好的,那么我们如何使用 LDA 来分割网站会话呢?这实际上非常简单:我们将每个会话视为一个文档,其中每个页面都是一个单词(您可以使用 URL 或页面名称,只要有助于您唯一地标识每个页面)。如果有帮助的话,把会话想象成一个用户写的文本,他试图告诉你他想从你的网站得到什么,用页面代替文字。

主题的正确数量并不总是显而易见的,仅仅纯粹的优化并不一定会产生最好的结果。用不同的数字试几次,看看结果,看看有没有道理。

LDA 是一种软聚类算法,这意味着最终它不会告诉您哪个会话属于哪个组。相反,它会给你一个向量,每个会话属于每个组的概率。然后,你可以将其归入概率最高的那一组(如果你想最后有一个硬聚类的方法的话)。

Python 代码教程

我们导入必要的库:

然后,我们从原始数据帧中提取会话,并为其安装计数矢量器。CountVectorizer 将文本转换成密集的向量。

警告:页面必须用空格分隔,并且它们的名称/URL 不应该包含标点符号,如点和逗号。用下划线“_”替换所有这些字符。

在下一步中,我们执行网格搜索:我们遍历 LDA 函数的所有可能的参数组合,以找到哪一个将产生最好的组,然后将该组合应用于我们的数据。警告:此步骤可能需要一段时间…

最后,我们打印所有的主题,连同最能描述它的单词列表和它们的重要性。

对结果满意后,如果需要,最终可以对结果进行硬聚类:

结论

一旦这项工作适应了您现有的数据和基础设施,您就可以以几种不同的方式使用它,或者尝试扩展这项工作。一种可能的方法是使用概率向量来测量会话或用户之间的距离,而不是对聚类进行硬编码。这可能会打开内容推荐的大门(例如,一旦你计算了用户之间的距离,通过计算概率向量之间的距离,你可以根据向量接近他们的其他用户向新用户推荐内容)。这里介绍的方法的另一个可能的扩展是考虑页面被访问的顺序(根据上下文,这可能是非常相关的)。

这种方法显示了有时跳出框框思考的重要性,以及将算法应用于问题的重要性,这些问题不一定是它们的预期应用,但却有一个等价的框架。在这个特定的例子中,它帮助把用户想象成一个作者,用页面名称而不是单词来写他们的想法。

我希望你喜欢这篇文章,并请让我知道你是否应用了它或以某种方式改进了它。

芝加哥的隔离和消费选择

原文:https://towardsdatascience.com/segregation-consumption-options-in-chicago-d62cb6852579?source=collection_archive---------34-----------------------

— —利用 K-Means 聚类和多项逻辑回归探索芝加哥公共消费空间的潜在模式

维多利亚·王

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

77 Chicago communities, clustered by recurrent venue types

种族隔离一直是芝加哥的一个重要问题。虽然这座城市的总人口分布相当均匀——大约 32%是白人,30%是黑人,29%是西班牙裔,但这些人被分成 77 个不同的社区,过着截然不同的生活。

伊利诺伊大学社会学教授 Maria Krysan 在哥伦比亚广播公司的一篇报道中说:“你居住的地方深刻地塑造了你生活的方方面面。”。事实上,不同种族或经济背景的芝加哥市民不仅居住在不同的居住环境中,而且接触到极其不同的公共空间和资源,这反过来又塑造了他们的生活方式。这个项目研究了芝加哥居民生活的一个特定方面——他们在各自生活空间的消费选择。

消费是一种建立和表达社会归属和区别的方式,这些目的地针对特定用户,包括一些人,而排除其他人( Bolzoni 2016 )。有理由假设芝加哥市的种族隔离可以反映在人们的日常消费中——换句话说,他们在食物、零售商品、活动等方面的花钱选择。本项目旨在验证这一假设。 除了居住隔离,不同社会背景的市民在公共消费空间上接触到的选择是否不同?

这可能是进一步研究美国城市地区社会经济隔离的第一步。以往的研究主要集中在城市人口的居住分布,而本项目旨在发现与公共消费空间的使用和可达性相关的空间隔离模式。这项研究的结果可能会引起学者、政策制定者、社会工作者和/或活动家以及直接受到这种隔离影响的人的兴趣。

数据采集和预处理
一个社区对某类场馆的可达性是通过该类场馆的流行程度(或出现频率)来衡量的。如果某种类型的场所通常出现在社区区域中,则可以推断该社区中的居民更容易接触到这些类型的场所。使用 FourSquare API,我搜索了每个社区中心周围 2.5 公里半径内的场地,每个社区的上限是 100 个场地。值得注意的是,2.5km 的搜索半径对于获取小型社区(社区区域半径小于 2.5km)的场地并不完全令人满意,这可能导致错误地包含属于其相邻社区的场地。

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

Part of data obtained from FourSquare API

单个社区的居民特征由从芝加哥市人口数据的两个来源提取的数据给出,包括芝加哥 2017 年人口普查数据芝加哥社区快照。这些指标为每个社区的居民的个人发展、经济状况和种族身份提供了足够的信息。

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

Part of Chicago Communities Demographic Data

K-均值聚类

这个项目的第一步是根据每个地区最常见的 10 种场所类型对 77 个芝加哥社区区域进行分类。从 FourSquare 获得的数据集计算每个社区区域中每个场馆类别的出现频率。为每个社区区域挑选出前 10 个最常出现的场所类型。

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

Part of Communities’ top-10 most recurrent venues data

为了将具有相似类型场馆的社区归入相同的组,我对场馆数据集应用了 K-Means 聚类方法。

K 均值模型的准确性在很大程度上取决于为该模型选择的聚类数,即 K 值。为了确定该模型的最佳 K 值,我应用了两种方法来交叉评估值为 3 到 10 的 K 值:

  1. 弯头判据方法。该方法旨在找到 SSE(标准误差之和-样本到其最近聚类质心的距离)急剧接近 0 时的最小 k 值。一个相对最优的 SSE 显示在 k = 5 或 6。
  2. 轮廓系数的测量。较高的轮廓系数表示较密集的聚类和每个聚类之间更明显的边界。虽然所有的 k 都产生相当低的轮廓系数,但当 k = 3、4 或 5 时,该数值较高。

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

Two plots for finding the optimal K

给定上述两种方法的结果,如果将芝加哥社区分成 5 个群,则是最佳的。本博客开头的地图显示了用聚类标签着色的 77 个芝加哥社区。直观上,在这张地图上用相同颜色标记的社区应该有相似的场馆出现模式。

探索跨集群的场馆模式

首先,我单独查看聚类数据。我在这五个组中找出了最常出现的前五种场地类型,以检查组内模式和组间差异。下面的气泡图显示了结果。

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

就餐馆而言,集群 0 和集群 2 中的社区几乎只有快餐店,从常识来看,这些快餐店很不健康,但很饱,更方便,最重要的是更便宜。相比之下,集群 3 中的社区有很多咖啡店、中高端的意大利和日本餐馆。他们也可以选择享受博物馆和酒店。群组 1 和群组 4 中的社区具有更均匀分布的场所,尚未注意到明显的模式。

通过集群探索社区居民属性

然后,将聚类数据与表示每个社区的常驻属性的数据一起进行检查。首先,我研究了社区整体财务状况、教育状况、就业率和年龄构成的指标:

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

Per-capita income, unemployment, education, age composition by cluster labels

集群 0、2 和 4 中的社区拥有低收入居民**。对于集群 1 和集群 3,虽然存在低收入社区,但这两个集群中的社区的平均财务状况较高**。集群 0 和集群 4 的失业率明显较高;群组 2 的低教育率特别高。最后,如最后一个方框图所示,虽然前四个图具有相似的年轻人和老年人百分比,但在这一部分中,聚类 4特别高。****

这些结果与上一节的发现一致,这表明第 1 和第 3 集群中的社区拥有相对较高价格的消费空间,而其余集群中的社区拥有相反的

接下来,我研究了每个集群中社区居民的种族构成。尽管有一些异常值,但这些图表显示了集群之间清晰的种族分割。

如第一个方框图所示,白人居民比例高的社区主要集中在集群 1 和集群 3 ,这里的高端消费空间非常普遍集群 0 和 4 充斥着黑人社区,其中一些黑人居民比例超过 95%;聚类 2 显示了西班牙裔居民的相同特征。这三个社区群是快餐和折扣店聚集区

虽然在以亚裔为中心的社区的分布中没有明显的趋势,但第 1 类确实包括两个亚裔居民比例很高的边远社区。正如美国其他城市的情况所表明的那样,亚裔居民的总人口较少,而且倾向于集中居住在一两个小的集中空间。这两个社区大概就是芝加哥的空间。

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

Race compositions by clusters

简而言之,探索性分析表明这些由场所产生的芝加哥社区集群之间存在一些居民属性的差异。具体来说,对于倾向于拥有更高端和更高价格消费选择的社区,居民一般都是受过高等教育、收入高的成年人,其中大多数也是白人。另一方面,在充斥着快餐店和旧货店的社区里,大量居民——通常是非白人——接受的教育和收入较低。

多项逻辑回归

那么,公共消费空间(即场馆)与居民经济/种族特征之间是否存在真实的关系?基于上述探索性分析得出的结论,我使用了一个多项逻辑回归模型来检验上一节中考察的居民特征是否真的与场馆产生的社区聚类相关。

多项式逻辑回归适用于该数据集有两个原因。首先,它允许因变量类别有两个以上的级别。在这种情况下,聚类标签被视为因变量,因为有五个聚类,所以它有五个级别;常驻特征被视为独立变量。第二,它不假设独立变量的正态性、线性或同方差性。在这种情况下,自变量不易呈正态分布,很难证明具有线性和同方差性。

逻辑回归模型的汇总统计提供了一个有点复杂的信息,但总的来说,结果合理地倾向于自变量和因变量之间存在真实关系的结论。

完整模型的总体总结如下所示。伪 R 平方是基于零模型“M0”和全模型“M1”的最大化对数似然函数的比率来计算的。伪 R 平方值接近 0 意味着模型不会显著提高估计因变量分类的确定性,而接近 1 意味着模型完全符合,对数优势比最大化为 0。在这个模型中,这个值在~0.6,这表明完整的模型比平庸的模型工作得稍好。

LLR 指标评估的是完整模型相对于零模型(零模型中不考虑任何指标)的绩效。特别是,LLR p 值表示观察假设总体系数为零的零假设(H0)的检验统计量的概率。在这个模型中,4.166e^-14 的 p 值非常低,这表明我们可以拒绝零模型比全模型更好的零假设。

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

Analytic model summary

讨论

探索性分析给人的印象是,芝加哥社区居民的社会、经济和文化属性与他们各自的消费空间类型之间存在着强有力的联系。

另一方面,逻辑回归模型有其缺点。虽然显示消费空间类型确实与所有居民的属性整体相关,但其结果可能会受到多重共线性的破坏,多重共线性是一种统计现象,其中逻辑回归模型中的预测变量高度相关。不可避免的是,社会、种族和经济隔离是深深交织在一起的现象,相互影响。因此,使用这些变量表示这三个方面的分离会使模型面临一定的多重共线性风险,阻止模型观察单个指标和因变量之间的一些显著相关性。

未来的研究可能会采用更严格的方法,例如使用岭回归或主成分分析(CPA)来最小化多重共线性的混杂影响;或者分解完整模型,比较不同局部模型的性能。

结论

日常经验告诉我们,不同的消费空间服务于不同的社会群体,这个项目为这种普遍的看法提供了一个粗略的证明。

该项目对芝加哥社区的公共消费选择和居民的社会、经济和文化分割之间的关系进行了相当全面但初步的分析。尽管下面的逻辑回归分析没有完全证实,但两者之间存在相关性。

分析发现,某些食物和活动消费选择在低收入和少数种族居民社区更为普遍,如快餐店。另一方面,收入较高且大多为白人的社区群体可以选择在高级餐厅和更好的娱乐场所消费,如酒店和博物馆。

未来的研究可能会对不同类型的场馆在不同社区开放的潜在原因进行更严格的调查。研究还可以更深入地考察这种消费选择差异对芝加哥市民生活各个方面的影响,比如他们的身体、精神或社会福祉

癫痫发作分类 ML 算法

原文:https://towardsdatascience.com/seizure-classification-d0bb92d19962?source=collection_archive---------8-----------------------

Python 中的二元分类机器学习算法

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

介绍

癫痫是一种中枢神经系统(CNS)疾病,在美国影响约 1.2%(340 万人),全球超过 6500 万人。此外,大约 1/26 的人会在他们一生中的某个时候患上癫痫。癫痫发作有很多种,每种都有不同的症状,如失去知觉、抽搐或意识模糊。有些癫痫发作很难用肉眼发现;患者通常会出现短时间无反应或发呆等症状。癫痫发作可能会意外发生,并可能导致受伤,如跌倒、咬伤舌头或无法控制大小便。因此,这些就是为什么癫痫发作检测对于在医疗监督下被怀疑有癫痫发作倾向的患者是至关重要的一些原因。这个项目将使用二元分类方法来预测一个人是否有癫痫发作。

该数据集可在 UCI 的机器学习知识库这里获得。该数据集包括每名患者在 23.5 秒内的 4097 次脑电图(EEG)读数,总共有 500 名患者。然后将 4097 个数据点平均分成每个患者 23 个块;每个块被转换成数据集中的一行。每行包含 178 个读数,这些读数被转换成列;换句话说,有 178 列组成了一秒钟的脑电图读数。总之,有 11,500 行和 180 列,第一列是患者 ID,最后一列包含患者的状态,无论患者是否有癫痫发作。

在这个项目中,我将演示用 Python 构建二元分类机器学习算法的步骤。

我的 Github 上有 Jupyter 笔记本。

数据探索

该数据集包含一个散列的患者 ID 列、一秒钟内的 178 个 EEG 读数和一个描述该秒钟患者状态的 Y 输出变量。当患者癫痫发作时,y 表示为 1,而所有其他数字都是我们不感兴趣的其他状态。所以当我们把我们的 Y 变量变成二元变量的时候,这个问题就变成了二元分类问题。

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

我们还将选择删除第一列,因为患者 id 是散列的,我们无法使用它。我们使用下面的代码来完成所有这些工作。

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

下一步是计算患病率,它被定义为样本在类中呈阳性的比例;换句话说,在我们的数据集中,这是癫痫发作患者的比例。

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

我们的患病率是 20%。当涉及到平衡类和使用“提升”度量评估我们的模型时,了解这一点是很有用的。

数据处理和建立训练/验证/测试集

这里不需要做任何特征工程,因为我们所有的特征都是脑电图读数的数值;将我们的数据集转储到我们的机器学习模型中不需要任何处理。

将预测变量和响应变量从数据集中分离出来是一种很好的做法。

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

cols_input are our predictor variables & OUTPUT_LABEL is our response variable

现在是时候将我们的数据集分成训练集、验证集和测试集了!多刺激啊!通常,验证集和测试集的大小相同,定型集通常占主数据集的 50%到 90%,具体取决于数据集拥有的样本数。数据集拥有的样本越多,我们就有越多的样本可以转储到我们的训练集中。

第一步是打乱我们的数据集,以确保我们的样本没有某种顺序。

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

然后,选择的分割是 70/15/15,所以让我们这样分割数据集。我们将首先选择将我们的验证和测试集与我们的训练集分开,这是因为我们希望我们的验证和测试集具有相似的分布。

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

然后我们可以检查每组的患病率,以确保它们大致相同,也就是 20%左右。

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

接下来,我们希望平衡我们的数据集,以避免创建一个错误地将样本分类为属于多数类的模型;在我们的案例中,是病人没有癫痫发作。这被称为准确性悖论,例如,当我们的模型的准确性告诉我们有 80%的准确性时,如果类别不平衡,它将只反映底层的类别分布。因为我们的模型看到我们的大多数样本没有癫痫发作,所以获得高准确度分数的最好方法是将样本分类为没有癫痫发作,而不管我们要求它预测什么。有两种简单易用的方法可以帮助我们解决这个问题。欠采样和过采样。我们可以通过减少属于较主导类的样本数量来对较主导类进行子采样,或者我们可以通过多次粘贴少数类的相同样本来进行过采样,直到两个类的数量相等。我们将选择在这个项目中使用二次抽样。

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

然后,我们将train_alltrainvalidtest集合保存为。csv 文件。在开始导入sklearn并构建我们的第一个模型之前,我们需要调整我们的变量以使我们的一些模型能够工作。由于我们将构建九个不同的分类模型,我们应该用StandardScaler来调整我们的变量。

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

We dump our scaler as a .csv file for quick access if we want to use it in other python notebooks

分类模型

让我们设置一下,这样我们就可以用一个函数print_report打印所有的模型指标。

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

由于我们已经平衡了数据,我们将阈值设为 0.5。阈值用于确定样本被分类为阳性还是阴性。这是因为我们的模型返回样本属于正类的百分比机会,所以在不设置阈值的情况下,它不会是二进制分类。如果样本返回的百分比高于我们的阈值,那么它将被归类为阳性样本,等等。

分类模型

我们将介绍以下型号:

  • k 个最近邻居
  • 逻辑回归
  • 随机梯度下降
  • 朴素贝叶斯
  • 决策树
  • 随机森林
  • 极端随机森林
  • 梯度推进
  • 极端梯度增强(XGBoost)

我们将对所有模型使用基线默认参数,然后选择具有最高验证分数的模型来执行超参数调整。

k 最近邻(KNN)

当谈到分类模型时,KNN 是人们最先学习的模型之一。该模型根据与其最接近的 k 个样本对样本进行分类。例如,如果 k = 3,并且所有三个最接近的样本都是正类,那么该样本将被分类为类 1。如果三个最接近的样本中有两个是阳性类别,那么该样本将有 66%的概率被分类为阳性。

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

我们得到了一个非常高的曲线下训练面积(AUC)、受试者操作曲线(ROC ),以及一个很高的验证 AUC。此指标用于衡量分类模型的性能。AUC 告诉我们模型能够在多大程度上区分类别,AUC 越高,模型在区分类别方面就越好。如果 AUC 是 0.5,那你还不如猜样本。

逻辑回归

逻辑回归是一种广义线性模型,它是常规线性模型的概念和能力的概括。

在逻辑回归中,模型预测某事是真还是假,而不是预测连续的事情。该模型适合两个类别的线性决策边界,然后通过 sigmoid 函数从几率对数转换为样本属于阳性类别的概率。因为该模型试图找到正类和负类之间的最佳分离,所以当数据分离明显时,该模型表现良好。这是一个要求缩放所有要素的模型,并且因变量是二分的。

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

随机梯度下降

梯度下降是一种算法,可以最小化许多不同模型中的许多损失函数,如线性回归、逻辑回归和聚类模型。它类似于逻辑回归,其中梯度下降用于优化线性函数。不同之处在于,随机梯度下降允许小批量学习,其中模型使用多个样本来采取单个步骤,而不是整个数据集。这在数据中存在冗余的情况下尤其有用,这通常是通过聚类发现的。因此,SGD 比逻辑回归快得多。

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

朴素贝叶斯

朴素贝叶斯分类器使用贝叶斯定理来执行分类。它假设如果所有的特征彼此不相关,那么一起看到这些特征的概率只是每个特征发生的概率的乘积。给定所有不同的特征组合,它找出样本被分类为阳性的概率。该模型通常是有缺陷的,因为模型的“幼稚”部分假设所有的特性都是独立的,而大多数时候情况并非如此。

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

决策树

决策树是一种模型,其中它运行多个“问题”的样本来确定其类别。分类算法通过重复地将数据分成相同类别的子区域来工作,并且当算法已经将所有样本分成纯的类别时,或者通过满足分类器属性的一些标准,树结束。

决策树是弱学习者,我的意思是它们不是特别准确,它们通常只比随机猜测好一点点。他们也几乎总是过度拟合训练数据。

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

随机森林

由于决策树可能会过度适应,随机森林就是为了减少这种情况而创建的。许多决策树组成了一个随机森林模型。随机森林包括引导数据集,并使用每个决策树的随机特征子集来降低每个树的相关性,从而降低过度拟合的可能性。我们可以通过使用没有用于任何树来测试模型的“袋外”数据来衡量随机森林有多好。随机森林也几乎总是优于决策树,因为该模型具有较低的方差;因此,该模型可以更好地推广。

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

极度随机化的树

树外分类器类似于随机森林,除了:

  • 当在拆分时选择变量时,样本是从整个训练集中抽取的,而不是引导样本
  • 节点拆分是随机选择的,而不是像在随机森林中那样被指定

这使得树外分类器不容易过度拟合,并且它通常可以产生比随机森林更一般化的模型。

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

梯度推进

梯度推进是另一种对抗决策树过度拟合的模型。然而,GB 和 RF 之间存在一些差异。梯度推进一次建立一棵更短的树,每棵新树都减少了前一棵树的错误。这个误差叫做伪残差。梯度推进比随机森林更快,在许多现实应用中很有用。然而,当数据集包含噪声数据时,梯度增强效果不佳。

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

极端梯度推进

XGBoost 类似于梯度增强,除了

  • 树有不同数量的终端节点
  • 用较少证据计算的树的叶子重量收缩得更厉害
  • 牛顿推进提供了比梯度下降更直接的到达最小值的路线
  • 额外的随机化参数用于减少树之间的相关性
  • 由于标准 GBM 没有正则化,因此使用更正则化的模型来控制过拟合,这使其性能优于 GBM。
  • XGB 实现并行处理,比 GBM 快很多。

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

模型选择和验证

下一步是在一个图表中可视化我们所有模型的性能;这使得我们更容易选择要调哪个。我选择了 AUC 曲线来评估我的模型。您可以选择任何想要优化的指标,如精度或提升,但是,AUC 不受您选择的阈值的影响,因此它是大多数人用来评估其模型的指标。

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

九个模型中的七个具有非常高的性能,这很可能是由于癫痫发作和非癫痫发作患者之间 EEG 读数的极端差异。决策树看起来像预期的那样过度拟合,请注意训练 AUC 和验证 AUC 之间的差距。

我将选择 XGBoost 和 ExtraTrees 分类器作为要调优的两个模型。

学习曲线

学习曲线是我们在模型中可视化偏差-方差权衡的一种方式。我们利用了scikit-learn中的学习曲线代码,但绘制了 AUC,因为这是我们选择用来评估模型的指标。

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

训练和 CV 曲线都很高,因此这表明我们的树外分类器中的低方差和低偏差。

然而,如果你看到两条曲线的分数都很低,而且很相似,那就是高偏差的信号。如果你的曲线有一个很大的差距,这是一个高方差的迹象。

以下是在这两种情况下如何做的一些提示:

高偏差:
-增加模型复杂性
-减少正则化
-改变模型架构
-增加新特性

高方差:
-添加更多样本
-减少特征数量
-添加/增加正则化
-降低模型复杂度
-组合特征
-改变模型架构

特征重要性

就像在回归模型中,你可以从特征系数中分辨出影响的大小;你可以在分类模型中做同样的事情。

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

根据您的偏差-方差诊断,您可以选择删除一些特征,或者通过组合一些新的变量,如下图所示。然而,对于我的模型,没有必要这样做。从技术上来说,脑电图读数是我唯一的特征,读数越多,分类模型就越好。

超参数调谐

下一步应该执行的是调整我们模型中的旋钮,也称为超参数调整。有几种方法可以做到这一点。

网格搜索

这是一种传统的超参数调整技术,这意味着它是第一个在手动调整每个超参数之外开发的技术。它需要相关超参数的所有输入(例如,您想要测试的所有学习率),并通过遍历超参数值的所有可能组合,使用交叉验证来测量模型的性能。这种方法的缺点是,当我们有很多想要优化的超参数时,要花很长时间进行评估。

随机搜索

随机搜索使用超参数的随机组合来寻找性能最佳的模型。您仍然需要输入想要调整的超参数的所有值,但是该算法在网格中随机搜索,而不是搜索超参数的所有值的所有组合。根据本文所述,由于其随机性,这通常在时间上胜过网格搜索,因为模型可以比网格搜索更快地达到其优化值。

遗传表演程序

遗传编程或遗传算法(GA)是基于查尔斯·达尔文的适者生存理论。GA 对当前超参数应用小的、缓慢的和随机的改变。它的工作原理是给一个解决方案分配一个适应值,适应值越高,解决方案的质量越高。然后,它会选择具有最高适应值的个体,并将它们放入“交配池”中,其中两个个体将产生两个后代(对后代进行一些更改),预计后代的质量将高于其父母。这种情况一次又一次地发生,直到我们达到期望的最佳值。

TPOT 是一个正在积极开发中的开源库,最初由宾夕法尼亚大学的研究人员开发。它获取整个训练数据集的多个副本,并执行自己的一键编码变体(如果需要),然后使用遗传算法优化超参数。

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

我们将在 tpot 的 automl 中使用dask来执行此操作。我们将xgboostextratrees分类器传递到tpot配置中,告诉它我们只希望算法在这两个分类模型中执行搜索。我们还告诉tpot把生产的每一款车型都出口到一个目的地,以防我们想早点停下来。

模型评估

AUC 为 0.997 的最佳性能模型是优化的 extratrees 分类器。下面是它在所有三个数据集上的性能。

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

我们还创建了 ROC 曲线图来显示上述 AUC 曲线。

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

结论

现在,向副总裁或首席执行官传达项目的要点通常是工作中最困难的部分,所以下面是我想对高层利益相关者简明扼要地说的话。

在这个项目中,我们创建了一个分类机器学习模型,可以通过脑电图读数预测患者是否癫痫发作。表现最好的模型的提升度量为 4.3,这意味着它比随机猜测要好 4.3 倍。它在预测测试集中的阳性类别方面也有 97.4%的正确率。如果将该模型投入生产以预测患者是否有癫痫发作,那么您可以预期该模型在正确预测癫痫发作患者方面的性能。

感谢您的阅读!

这是东北大学 Andrew Long 教授的硕士课程中的一个顶点项目。

从 sql 中选择答案

原文:https://towardsdatascience.com/select-answers-from-sql-5cef923380ac?source=collection_archive---------29-----------------------

一些带有直观答案的常见 SQL 面试问题的回顾

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

Modded from photo by Ashim D’Silva on Unsplash

对于任何对数据分析或数据科学感兴趣的人来说,重要的一点是:**不要低估 SQL 的效用!**使用 Python 和 pandas、numpy 之类的包很容易上手,但有许多业务是用 SQL 完成的,许多报告和分析工作可以用它快速高效地完成。如果您对大数据感兴趣,并且使用 PySpark 之类的包与 Apache Spark 进行交互,那么编写 SQL 查询可能是过滤和分析数据最清晰、最快捷的方式。

为了帮助巩固这些概念,下面是一些关于 SQL 的常见面试问题的分类。我从我最近查阅的其他人的列表中提取了这些信息(更多信息请点击底部的链接),我只是针对我个人在最近的采访中遇到的一些问题给出了解释:

SQL、MySQL 和 SQL Server 之间的区别

非常基础的,SQL 代表结构化查询语言。它是用于设计、管理和查询结构化关系数据库的语言本身。mySQL 是一个开源的关系数据库管理系统。SQL Server(也称为 Microsoft SQL Server)是由 Microsoft 为其服务器平台创建的关系数据库管理系统。这两个平台都使用一种通用语言(SQL ),但也有各自的细微差别。还有一些你可能听说过的,比如 Oracle,但是要注意的是 SQL 是语言,而其他的是数据库平台。

哪里与拥有

如果你需要一个一句话的答案: HAVING 专门用于使用集合函数对表进行过滤,而 WHERE 不是。对于更长的上下文: WHERE 子句根据满足特定条件的行进行过滤。它在行中寻找特定数据的匹配。 HAVING 子句用于对整个表中的数据条件进行过滤。下面是这种情况的快速分析。让我们假设我们有一张桌子,看起来像这样一个随机分类的《权力的游戏》角色:

╔═══════════╦════════════════════╦════════╗
║   name    ║       house        ║  age   ║
╠═══════════╬════════════════════╬════════╣
║ Eddard    ║ Stark              ║ 40     ║
║ Catelyn   ║ Stark              ║ 35     ║
║ Rob       ║ Stark              ║ 17     ║
║ Sansa     ║ Stark              ║ 13     ║
║ Cersei    ║ Lannister          ║ 35     ║
║ Jaime     ║ Lannister          ║ 35     ║
║ Tyrion    ║ Lannister          ║ 30     ║
║ Daenerys  ║ Targaryen          ║ 15     ║
║ Theon     ║ Greyjoy            ║ 19     ║
╚═══════════╩════════════════════╩════════╝

如果您想要查找大于或等于 30 的字符,我们可以编写如下查询:

SELECT name, age
FROM got_table
WHERE age >= 30

此函数查看表,根据列出的年龄大于或等于 30 的行进行筛选。它查看表中的可用数据,并从中进行过滤。但是假设你想使用集合函数。让我们从基于 house 聚合这个表开始,只是为了计算每个表中列出了多少人:

SELECT house, COUNT(*)
FROM got_table
GROUP BY house

我们做到了!但是,如果我们只想查看在这个聚合表中创建的具有多个成员的行,我们需要使用具有的而不是 WHERE :

SELECT house, COUNT(*)
FROM got_table
GROUP BY house
HAVING COUNT(*) < 2

简而言之,如果你在寻找行在哪里或者组在哪里

主键与外键

一个主键 是数据库表中一条记录的唯一标识符。外键是一个表中的一个字段,它是另一个表中的主键。主键在每个表中只能出现一次,而外键可以出现多次。在这里,我将制作几个表格来说明(为了好玩,请容忍我的假数据和混合位置):

╔════════╦═══════════╦═════════╗  ╔════════╦═══════════╦════════╗
║group_id║  name     ║army_size║  ║planetid║  name     ║group_id║
╠════════╬═══════════╬═════════╣  ╠════════╬═══════════╬════════╣  
║ 0001   ║Cpt. Planet║ 1       ║  ║ 7001   ║ Earth     ║ 0001   ║  
║ 0002   ║First Order║ 800,000 ║  ║ 7020   ║ Cybertron ║ 0001   ║
║ 0003   ║ Autobots  ║ 1,000   ║  ║ 7044   ║ Tatooine  ║ 0003   ║
║ 0004   ║Silverhawks║ 10      ║  ║ 5084   ║ Alderan   ║ 0004   ║
║ 0005   ║ C.H.U.D.s ║ 35,000  ║  ║ 2001   ║ Mars      ║ 0002   ║
╚════════╩═══════════╩═════════╝  ╚════════╩═══════════╩════════╝
TABLE 1                           TABLE 2

因此,假设我们有一些派系(主要取自大脑的后部)在为几个不同的星球而争斗。我们将它们放在单独的表中,以存储每一个的单独特征。这些表格是基于哪个群体控制哪个星球而联系在一起的。在表 1 中,主键是 group_id。它是用来标识每条记录的唯一 id。在表 2 中,主键是 planetid,而外键是 group_id。你可以看到我们如何证明行星船长已经接管了地球和赛博顿,这是一个相当有力的举动!表 2 中使用的 group_id 显示了两个表之间的关系,但是拥有一个外键允许我们为每个集合拥有唯一的表。在较大的数据库中,您的系统会有几个以这种方式连接的表。

连接和联合

基础如下,假设我们有两个表,我们并排连接数据,它们有一些共同的键或值来匹配:

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

  • 内部连接:只记录在两个表中有匹配的值(B)
  • 左连接:最左侧表中的所有记录和右侧匹配的记录(A & B)
  • 右连接:最右边的表中的所有记录和最左边的记录相匹配(B & C)
  • 完全外部连接:来自两者的所有记录(A & B & C)

还不错,只是需要时间记住布局。这是很好的思考通过加入他们并排的性质。有了工会,我们只需要改变我们看待表格的角度:

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

  • 联合:两个表的组合,一个堆叠在另一个的上面,但是第二个没有重复(A & B)
  • 联合所有:两张桌子整体叠放在一起的组合(A & B & C)

删除、截断和丢弃

快速回答: DELETE 可以用来从表中删除一些记录, TRUNCATE 删除整个表的行, DROP 从数据库中删除对象。当使用 DELETE 时,您将指定一个 WHERE 子句来选择记录:

DELETE FROM got_table WHERE house = "Stark"

TRUNCATE 清除表格中的所有行,没有修饰符:

TRUNCATE TABLE got_table

DROP 实际上是从数据库中删除表对象和行:

DROP TABLE got_table

每一个都有用途,但是根据你的情况,明智地选择你需要的。

操纵字符串

有很多函数可以帮助进行字符串操作,但是一个重要的事情是索引从 1 开始(尽管在其他编程语言中通常从 0 开始)。下面是一些可能会出现的快速重要功能:

  • SUBSTR()text,position,length ) 将获取文本并抓取任意部分
  • LEFT( text,length**)**&**RIGHT(**text,length ): 两者都从最右边或最左边的固定位置开始并从那里修剪。
  • REPLACE( text,string_to_find,string _ to _ REPLACE _ with**)😗*相当直接的文本替换。
  • CONCAT()T26【text _ 1】、text_2 等 ): 简单组合的文字

以下是对每一种可能出现的情况的简要介绍:

╔═══════════╦══════════╦══════════════════════════╗
║   first    ║   last   ║  line                    ║
╠═══════════╬══════════╬══════════════════════════╣
║ Inigo     ║ Montoya ║ "Prepare to battle!"     ║
╚═══════════╩══════════╩══════════════════════════╝**SELECT** LEFT(first, 1), last **FROM** pb_table
╔═════╦══════════╗
║  I  ║  Montoya ║  
╚═════╩══════════╝
**SELECT** CONCAT(last, "," , first) **FROM** pb_table
╔════════════════╗
║ Montoya, Inigo ║  
╚════════════════╝
**SELECT** last, REPLACE(line, "battle", "die") **FROM** pb_table
╔══════════╦════════════════════╗
║  Montoya ║  "Prepare to die!" ║  
╚══════════╩════════════════════╝

我发现一些面试问题来源很有帮助:

最重要的 SQL 面试问题(IntelliPaat)

2019 年需准备的 65 大 SQL 面试问题(Edureka)

50 大 SQL 面试问题&答案(Guru99)

100+最流行的 SQL 面试问答(软件测试材料)

我喜欢的一些 SQL 学习资源:

模式分析(免费,可以用自己的平台做一些互动练习)

代码教程(喜欢他们的互动平台和详尽的讲解)

W3Schools (也是一些示例交互的非常好的书面参考)

谢谢!

为组学集成选择特征

原文:https://towardsdatascience.com/select-features-for-omics-integration-511390b7e7fd?source=collection_archive---------11-----------------------

生命科学的数理统计和机器学习

单变量与多变量特征选择

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

Idea of Integrative OMICs from Yugi et al., Trends Biotechnol. 2016 Apr;34(4):276–290

这是 生命科学的数理统计和机器学习 专栏的第六篇文章,我试图在这里解释一些在生物医学、生物信息学、细胞生物学、遗传学、进化生物学等领域常见的神秘分析技术。接下来的几篇文章将致力于综合组学分析,这是对计算生物学的现代挑战。这里我讨论了如何使用深度学习进行数据整合。现在,我将后退一步,解释在将各种类型的生物信息合并在一起之前,将对数据执行的基本预处理步骤

什么是整合组学?

下一代测序(NGS) 技术催生了多种生物和生物医学大数据,如基因组学、蛋白质组学、表型组学、转录组学、代谢组学、表观组学、宏基因组学、脂质组学等。,由于它们共同的后缀,常被称为。快速增长的数据量和多样性提供了新的独特的机会,也带来了大量的分析挑战。一个挑战是,我们假设组学数据应该具有协同效应,这允许更准确地模拟生物细胞的行为。以这种方式,组学整合可以识别新的生物学途径,这些途径在单个组学层中不一定是可区分的。然而,尽管开发了暗黑混合组学等有前途的工作流程,目前仍缺乏用于执行组学整合的数学方法学。

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

DIABLO Integrative OMICs pipeline from mixOmics R package, image source

为什么要选择信息丰富的特征?

另一个挑战是组合不同类型的生物信息增加了分析特征 的数量,同时保持统计观察(样本)的数量不变。考虑到即使是单个组学也可能是非常高维的,如果没有严格的降维或正则化,它们的集成是困难的,这归结为对最有信息的特征的选择 ,同时丢弃有噪声的特征

假设我们对解释我们感兴趣的表型 Y 的变异感兴趣,例如疾病状态,我们有一个解释变量(基因)的矩阵 X,我们假设这些变量对 Y 的变异负责。问题是:X 中的所有解释变量对 Y 的变异都有同等贡献吗?由于生物数据中存在大量噪声,有理由假设一些基因是信息性的,而一些基因是有噪声的。由于我们通常只有有限数量的统计观测值,我们不能包含噪声基因,而必须专注于信息基因,即在继续建模之前选择特征

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

Feature selection is an important step in biological analysis workflow, image source

为了进行选择,我们必须针对表型 y 测试 X 中的基因。然而,我们应该如何做呢:一起测试X 中的所有基因(多变量特征选择)还是逐个测试(单变量特征选择)?这里我们要比较两种方式。

单变量特征选择

为了演示单变量与多变量特征选择,我将使用来自人类骨骼肌的 RNAseq 基因表达数据,来自 GTEx 人类组织基因表达 联合体 V7 。数据集包括 n=157 个样本,为了简单和快速起见,我随机抽取了 p=1000 个基因

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

The Genotype-Tissue Expression (GTEx) project. Nature Genetics. 29 May 2013. 45(6):580–5.

在这里,我们加载基因表达矩阵 X,并删除低表达基因。为简单起见,感兴趣的表现型将是性别。换句话说,在我们的案例中,我们将发现人类骨骼肌中哪些基因的表达显示了 99 名男性和 58 名女性之间的表型差异。让我们通过显示 PCA 图 来可视化 157 个男女样本。

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

PCA 图显示了 PC1 和 PC2 中的样本之间的大量差异,但是基于它们的骨骼肌基因表达数据,没有明确的雄性和雌性分离。了解样本之间差异背后的基因的一种方法是测试每个个体基因与性别的相关性,在我们的情况下,这相当于差异基因表达(DGE)的分析。这里,我们将使用简单的非参数 Spearman 相关性 来推断 X 和 Y 之间的关系,我们将对照 Y 逐一测试 X 中的所有基因,使用错误发现率调整多重测试相关性的 p 值,并通过 FDR 对基因进行排序。

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

我们根据基因与性别的个体关联对基因进行排序,并可以应用传统的截止值 FDR=0.05 来选择**信息性/**/显著性基因。接下来,我们可以将这些选择的基因组合成一个预测得分,这似乎是一个有吸引力的想法。然而,在实践中,这种基于单变量特征选择的预测效果很差,因为它有两个问题:****

  • 单变量特征选择不能克服 维数灾难 问题,因为 FDR 校正不足以达到此目的,即它易于过度拟合并且具有较差的泛化能力
  • 单变量特征选择不考虑特征之间的多重共线性,即当特征彼此高度相关时。

上述缺点可以用稀疏线性模型来解决,即具有正则化惩罚的模型,如 【套索/脊/弹性网】偏最小二乘(PLS) 回归或判别分析,多变量特征选择的基本技术。

多元特征选择

同时考虑 X 矩阵中所有解释变量的最简单方法是将它们一起放入多重多元线性模型,并执行 普通最小二乘(OLS) 最小化:

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

这里为了简单起见,我们只使用了两个预测值 X1 和 X2,但是可以有成千上万个。这意味着,为了最小化 OLS 成本函数,我们必须在高维空间中工作,由于维数灾难,这本来就很困难。这导致多元线性回归的解非常不稳定。为了克服这个障碍,我们可以在上述 OLS 成本函数中增加一个惩罚项:

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

在这里, λ 被称为拉格朗日乘数**,它是我们想要在我们的线性模型上放置多少惩罚的度量,它的最优值是通过交叉验证找到的。参数 α 通常是固定的,但原则上也可以通过交叉验证找到,正则化的类型称为: 1) LASSO if α =1,2) Ridge if α =0,3)Elastic Net ifα= 0.5。这些惩罚方法有一些不同之处,当您选择分析方法时,请记住这些不同之处。LASSO 是最严格的惩罚,在有大量噪音的数据上表现最好。LASSO 的问题在于它不能完全处理预测因子之间的多重共线性。如果两个变量强相关,LASSO 将只选择其中一个(偶然),并将另一个变量前面的系数设置为零。有时,如果被忽略/省略的特征比 LASSO 选择的特征有更多的物理/生物意义,这种类型的特征选择可能会有问题。这个问题可以通过脊罚函数来避免,此外,脊对于数值最小化更加稳定,因为它在高维空间中提供了完全凸流形。然而,在超高维空间中,Ridge 可能过于宽松,会选择许多噪声特征,这可能是不可取的。弹性净惩罚在套索和脊之间提供了一种折衷,通常是机器学习从业者的首选和推荐。让我们使用 LASSO,进行交叉验证,检查选择了哪些基因:**

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

正如我们所见,LASSO 选择了大约 30 个信息丰富的特征,并根据其内部得分对它们进行了排名。与单变量特征选择相比,排序看起来非常不同,即使基因 MAP7D2 出现在两种特征选择方法的顶部。

另一种优雅的多元特征选择技术是偏最小二乘法(PLS)** 回归和判别分析,其也被(其作者)称为潜在结构投影(PLS)。PLS 背后的思想是,它通过最大化 X 和 Y 之间的协方差来执行特征选择:**

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

让我们使用性别 Y 对基因表达矩阵 X 进行 PLS 判别分析(PLS-DA)用于监控**。它可以被认为是基因的多元选择,提供了雄性和雌性之间最大的分离。**

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

在这里,我们可以清楚地看到男性和女性之间的分离,将该图与上面的 PCA 图进行比较,我们没有看到任何分离。为了观察哪些基因提供了性别分离,我们显示了 PLS 负荷:

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

我们再次得出结论,通过 PLS 的多变量特征选择提供了一组看起来与单价特征选择非常不同的基因。此外,我们将使用以多元方式选择的基因组来整合不同的组学层。

摘要

在本文中,我们了解到组学集成为生物过程的精确建模提供了一个有希望的下一步。然而,为了克服维数灾难,通常必须在集成之前进行特征预选**。单变量特征选择很简单,但是它的泛化能力很差,并且没有考虑多重共线性。多元特征选择LASSO、Ridge、Elastic Net 和 PLS 等方法更适合处理高维生物数据。**

在下面的评论中让我知道生命科学中的哪些分析对你来说似乎特别神秘,我会在这个专栏中尝试回答它们。在我的 github 上查看完整的笔记本。在 Medium 关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。下次我们将讨论监督组学整合方法**,敬请关注。**

为 XGBoost 模型训练选择最佳参数

原文:https://towardsdatascience.com/selecting-optimal-parameters-for-xgboost-model-training-c7cd9ed5e45e?source=collection_archive---------3-----------------------

所描述的方法有助于找到用 XGBoost 为机器学习模型训练选择参数的方法

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

XGBoost training results

在为机器学习模型训练选择参数时,总会涉及一点运气。最近,我在研究渐变增强树,特别是 XGBoost。我们在企业中使用 XGBoost 来自动化重复性的人工任务。在用 XGBoost 训练 ML 模型时,我创建了一个选择参数的模式,这有助于我更快地构建新模型。我会在这个帖子里分享它,希望你也会觉得有用。

我使用皮马印第安人糖尿病数据库进行训练,CSV 数据可以从这里下载。

这是运行 XGBoost 训练步骤并构建模型的 Python 代码。通过传递成对的训练/测试数据来执行训练,这有助于在模型构建期间特别评估训练质量:

XGBoost 中的关键参数(将极大影响模型质量的参数),假设您已经选择了 max_depth(更复杂的分类任务,树更深)、子样本(等于评估数据百分比)、目标(分类算法):

  • n _ estimators—XGBoost 将尝试学习的运行次数
  • 学习速率 —学习速度
  • early _ stop _ rounds—防止过拟合,如果学习没有改善,则提前停止

当在 verbose=True 的情况下执行 model.fit 时,您将看到每个训练运行评估质量被打印出来。在日志的末尾,您应该看到哪个迭代被选为最佳迭代。可能训练轮数不足以检测最佳迭代,那么 XGBoost 将选择最后一次迭代来构建模型。

使用 matpotlib 库,我们可以绘制每次运行的训练结果(来自 XGBoost 输出)。这有助于理解被选择来构建模型的迭代是否是最好的。这里我们使用 sklearn 库来评估模型精度,然后用 matpotlib 绘制训练结果:

让我们描述一下我为 XGBoost 训练选择参数的方法( n_estimatorslearning_rateearly_stopping_rounds )。

第一步。根据你的经验,从你认为最有效的或者有意义的事情开始

  • n _ 估计量 = 300
  • 学习率 = 0.01
  • 提前 _ 停止 _ 回合 = 10

结果:

  • 停止迭代= 237
  • 准确率= 78.35%

结果图:

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

通过第一次尝试,我们已经在 Pima Indians 糖尿病数据集上获得了良好的结果。训练在迭代 237 时停止。分类误差图显示了在迭代 237 附近较低的误差率。这意味着学习率 0.01 适用于该数据集,并且提前停止 10 次迭代(如果结果在接下来的 10 次迭代中没有改善)是可行的。

第二步。尝试学习率,尝试设置一个较小的学习率参数,并增加学习迭代次数

  • n _ 估算者 = 500
  • 学习率 = 0.001
  • 提前 _ 停止 _ 回合 = 10

结果:

  • 停止迭代=没有停止,花费了所有 500 次迭代
  • 准确率= 77.56%

结果图:

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

较小的学习率对这个数据集不起作用。即使迭代 500 次,分类误差几乎不变,XGBoost 对数损失也不稳定。

第三步。尽量提高学习率。

  • n _ estimates= 300
  • 学习率 = 0.1
  • 提前 _ 停止 _ 回合 = 10

结果:

  • 停止迭代= 27
  • 准确率= 76.77%

结果图:

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

随着学习速率的增加,算法学习得更快,它已经在迭代 Nr 处停止。27.XGBoost log loss 误差趋于稳定,但总体分类精度并不理想。

第四步。从第一步开始选择最优学习率,增加提前停止(给算法更多机会找到更好的结果)。

  • n _ 估算者 = 300
  • 学习率 = 0.01
  • 提前 _ 停止 _ 回合 = 15

结果:

  • 停止迭代= 265
  • 准确率= 78.74%

结果图:

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

稍微好一点的结果是 78.74%的准确度,这在分类误差图中是可见的。

资源:

GitHub 上的 Jupyter 笔记本

博文— Jupyter 笔记本—忘记 CSV,用 Python 从 DB 获取数据

博客文章— 通过在 Python 中使用 XGBoost 来避免过度拟合

选择正确的预测建模技术

原文:https://towardsdatascience.com/selecting-the-correct-predictive-modeling-technique-ba459c370d59?source=collection_archive---------1-----------------------

使用统计、概率和数据挖掘来预测未来的结果。

什么是预测建模?

预测建模是获取已知结果并开发一个可以预测新事件值的模型的过程。它使用历史数据来预测未来事件。有许多不同类型的预测建模技术,包括方差分析、线性回归(普通最小二乘法)、逻辑回归、岭回归、时间序列、决策树、神经网络等等。在项目开始时选择正确的预测建模技术可以节省大量时间。选择不正确的建模技术会导致不准确的预测和经历非恒定方差和/或均值的残差图。

回归分析

回归分析用于从一个或多个独立变量预测一个连续的目标变量。通常,回归分析用于自然发生的变量,而不是通过实验操纵的变量。如上所述,有许多不同类型的回归,所以一旦我们决定了应该使用回归分析,我们如何选择应该应用哪种回归技术?

方差分析

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

A scatterplot for data that may be best modeled by an ANOVA model looks as so

当目标变量是连续的且因变量是分类的时,使用 ANOVA 或方差分析。该分析中的无效假设是不同组之间没有显著差异。总体应呈正态分布,样本病例应相互独立,且组间方差应大致相等。

线性回归

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

当目标变量是连续的,因变量是连续的或者是连续变量和分类变量的混合,并且自变量和因变量之间的关系是线性的时,将使用线性回归。此外,所有预测变量应正态分布,具有恒定的方差,并且彼此之间应很少或没有多重共线性或自相关。

逻辑回归

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

https://www.researchgate.net/figure/Linear-Probability-Versus-Logistic-Regression-6_fig2_224127022

逻辑回归不需要目标和因变量之间的线性关系。目标变量是二元的(假设值为 0 或 1)或二元的。逻辑回归的误差/残差不需要是正态分布的,并且残差的方差不需要是常数。但是,因变量是二元的,观察值必须相互独立,数据中必须很少或没有多重共线性或自相关,并且样本量应该很大。最后,虽然该分析不要求自变量和因变量线性相关,但自变量必须与对数概率线性相关。

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

If the scatter plot between the independent variable(s) and the dependent variable looks like the plot above, a logistic model might be the best model to represent that data.

岭回归

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

For variables that experience high multicollinearity, such as X1 and X2 in this case, a ridge regression may be the best choice in order to normalize the variance of the residuals with an error term.

岭回归是一种分析经历多重共线性的多重回归变量的技术。岭回归采用普通的最小二乘法,并通过向回归估计值添加一定程度的偏差来减少标准误差,从而承认残差经历了较高的方差。假设遵循多元回归的假设,散点图必须是线性的,必须有不含异常值的恒定方差,并且因变量必须表现出独立性。

时间序列

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

https://simplystatistics.org/2016/05/05/timeseries-biomedical/

时间序列回归分析是一种基于响应历史预测未来响应的方法。时间序列的数据应该是变量在不同时间点的一组观察值。数据是二元的,自变量是时间。序列必须是稳定的,这意味着它们是正态分布的:序列的均值和方差在很长一段时间内是恒定的。此外,残差还应在长时间内呈均值和方差恒定的正态分布,并且不相关。该系列不应包含任何异常值。如果随机冲击是存在的,它们确实应该随机分布,平均值为 0,方差为常数。

分类分析

决策树

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

https://hackernoon.com/what-is-a-decision-tree-in-machine-learning-15ce51dc445d

决策树是一种监督学习算法,它基于关于样本的某些问题重复分割样本。这些对于分类问题非常有用。它们相对容易理解并且非常有效。决策树表示几个决策,后面跟着不同的发生几率。这项技术帮助我们定义最重要的变量以及两个或更多变量之间的关系。

神经网络

神经网络有助于对数据进行聚类和分类。这些算法大致模仿人脑,旨在识别模式。神经网络往往非常复杂,因为它们由一组算法组成。这种类型的分析可能非常有用,但是,如果你试图确定为什么发生了什么,这可能不是最好的模型。

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

http://www.asimovinstitute.org/neural-network-zoo/

总之,这些只是可用于数据建模的不同预测技术的一小部分选项。需要注意的是,在使用预测分析技术时,在变量之间建立因果关系是非常危险的。在预测分析中,我们不能说一个变量导致了另一个,相反,我们可以说一个变量对另一个变量有影响,以及这种影响是什么。

我们来连线:

https://www.linkedin.com/in/mackenzie-mitchell-635378101/

[## 麦肯齐米切尔 6 -概述

在 GitHub 上注册您自己的个人资料,这是托管代码、管理项目和与 40…

github.com](https://github.com/mackenziemitchell6)

资源:

https://www.statisticssolutions.com/manova-analysis-anova/

https://DSS . Princeton . edu/online _ help/analysis/Regression _ intro . htm # target text = Regression % 20 analysis % 20 is % 20 used % 20 when,logistic % 20 Regression % 20 should % 20 be % 20 used。

https://www . statistics solutions . com/assumptions-of-logistic-regression/# target text = Third % 2C % 20 logistic % 20 regression % 20 需要% 20 这里,独立% 20 变量% 20 和%20log%20odds。

https://www . microstrategy . com/us/resources/introductive-guides/predictive-modeling-the-only-guide-you-need

https://skymind.ai/wiki/neural-network

https://NCSs-wpengine . net DNA-SSL . com/WP-content/themes/NCSs/pdf/Procedures/NCSS/Ridge _ regression . pdf

https://www . analyticsvidhya . com/blog/2015/01/decision-tree-simplified/2/

为偏态分类问题选择正确的度量

原文:https://towardsdatascience.com/selecting-the-right-metric-for-skewed-classification-problems-6e0a4a6167a7?source=collection_archive---------5-----------------------

偏斜精度!!让我们尝试一些其他的分类标准!!

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

Skew Accuracy

这是关于不平衡和噪声数据系列文章的第 2 部分。第 1 部分关于数据生成到此为止。

那么,为什么我们需要关心我们的度量呢?TLDR;这将帮助你的企业更好地理解你的模型。这将有助于您的模型更快地优化自身,并获得更加面向业务的结果。

接下来是一个很长的答案。解决有监督的 ML 问题可以从不同的角度来看。

解决模糊问题

天气预测、股票价格预测或信用欺诈检测等都试图通过建立数据模式来解决看似模糊的问题。我们试图找到我们观察到的数据和观察到的目标标签之间的关系。我们进一步使用这些发现的关系进行预测。

“我们发现的数据和预测目标之间的关系质量如何?”

寻找函数近似值

我们相信,给定所有可能的数据,每个事件都是可预测的,因此我们相信,每个目标观察都可以用一个采用正确预测集的函数来解释。

*f*(All Predictors)->y
or
*f*(All Predictors) gives target

然后,我们试图找到一个函数 g,,这是一个很好的近似函数*f。*不可能在所有情况下找到函数 f 本身,因为你有时没有所有的预测值和所有的观测值。所以我们发现

*g*(Some subset of Predictors) -> y [Correct in most cases]

“g和 f有多接近?”

现在,**" g逼近 f"** 的程度将取决于我们的预测器有多好,以及我们的学习算法有多好。

所以我们有两个问题,我们的函数逼近有多好?我们发现数据和目标之间的关系有多好?这些是我们的指标帮助我们回答的问题。

需要一个好的度量标准:预测第二天的降雨

我们试图预测明天是否会下雨?我明天应该带一把伞吗?现在,我们每天都对一整年(365)的第二天进行预测。

让我们检查一些假设的数据。

它只下了 87 天雨,整整 278 天没下雨。我们预测了 42 天。但总的来说,我们说会下雨 122 天。我们在 87 天中对了 42 天,278–80 = 278 天中的 198 天,42+198 = 240 天。所以 240/365 正确或 65%的时间。但是如果我们的目的是保护我们的用户不被淋湿,那么我们失败了 87–42 = 45 次。下雨有一半是我们没有预料到的。因此,尽管我们有 65%的时间是正确的,但我们还是在 45 天里淋湿了,而且只在 42 天里得救了。

现在,我们使用的度量标准(总体正确率%)是问题的正确度量标准吗?考虑两种情况

  • 案例一:避雨:客户利用你的预测来计划外出。或许你可以用不同的方法来衡量成功?像、【TTL/N 天前预测】、因为我们的用户想避免下雨,所以如果我们检测大多数天会更好。此外,在这种情况下,我们提前提供预测(第二个指标)以便用户进行规划是很重要的。所以我们努力优化这两者。
  • 案例 2:通勤的交通路线选择:在这里,您可以预测每个小时,没有必要找到所有的雨天,而是重要的是大多数时候是正确的,这样用户(或地图应用程序)就可以在大多数日子选择正确的路线。所以这里的“%总体正确次数”确实是一个很好的指标。

从上面的例子中,我们看到一个成功的 ML 解决方案需要定义的不仅仅是精度/召回率/准确度。您的指标可能会考虑重要的业务因素,如何时应该进行预测?*,你需要预测未来多久?(需求预测领域),*你的算法需要多长时间?等。

在这篇文章中,我关注分类问题的一个子集,偏斜标签分类问题。在这些问题中,目标标签不是均匀分布的。我们的示例问题本身存在偏差,其中阳性标签(下雨)只有 87 个,而阴性标签有 278 个,偏差为 1:3。

许多像信用欺诈这样的问题有更高的偏差,99%的例子是负面的(非欺诈),只有 1%(欺诈)。因为像准确度/精确度/召回率这样的通用指标不能捕捉业务意图。许多组织也有一套好的精确/召回的概念(90%的精确,95%的召回)。但是对于这些扭曲的问题来说,这样的数字很大程度上是无法实现的。因此,正确的问题是:ML 模型能提供商业价值吗?你的度量应该反映这个问题。

分类问题可用的度量

我提供了一个在流行的 scikit 库中可用的分类指标的列表。在链接的文档页面上可以看到它们如何工作的详细信息。

我认为最好到最坏的安排(对于偏斜问题)

不平衡/偏斜问题的分类度量的行为

Jupyter 笔记本链接

我们将创建一些人工数据,然后倾斜正负类。接下来,我们将使用一个分类算法和一些指标来检查这些指标如何应对不断增加的不对称。

理想情况下,在不对模型进行微调或对数据进行重采样的情况下,合适的指标应该从好变坏。另一方面,没有考虑偏斜的指标不会显示出太大的变化,甚至可能显示出偏斜越大的改进。

首先让我们看看不平衡的数据是什么样子的,我们将使用 scikit 的 make_moons api(在以前关于数据生成的博客中已经介绍过)。

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

Interactive Imbalance Plot Code

随着我们增加不平衡的结果

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

Increasing Imbalance

笔记本带代码。

接下来,让我们看看在不平衡加剧的情况下,各种指标会是什么样子。

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

Generating Data

接下来,我们定义一个函数来连续构建模型。

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

Model builder function

最后,我们编写一个函数,循环遍历各种不平衡值、我们提供的指标,并制作一个指标与不平衡的图表。

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

Function to plot metrics vs imbalance

注意,我使用np.logspace来生成不平衡值。这帮助我生成更多接近 0 的值,和更少接近 1 的值。第 8 行对imbalance的函数调用使数据不平衡,这是一个自定义函数,可以在同一文件夹的[lib.py](https://github.com/faizanahemad/data-science/blob/master/exploration_projects/imbalance-noise-oversampling/lib.py)中找到。其他自定义函数在同一个文件中。

最后让我们运行它。我们使用 f1、准确度、召回率和精确度作为我们的衡量标准。

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

Metrics vs Imbalance — I

我们的观察如下。

准确度对不平衡完全不敏感,而精度、召回率和 f1 则敏感。

接下来,让我们尝试几个其他指标。我们定义了两个新的指标:precision@recall=75recall@precision=75,因此我们将召回率/精确度保持在一个设定的阈值,然后检查这种不平衡如何影响另一个。

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

Metrics vs Imbalance — II

请注意,所有这些指标对不平衡都很敏感。为了改进它们,你需要改进你的模型。另一方面,精确度对不平衡不敏感,呈现出良好性能的虚假舒适画面。发生这种情况是因为随着偏斜的增加,预测最频繁的类将给出高精度。在 1:99 的偏差情况下(1 个正例,99 个负例),如果你总是预测为负,那么你的准确率是 99%。Accuracy = Num correctly predicted / Total examples

最后,我们将比较 AUC-ROC 和平均精度与准确性。

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

Metrics vs Imbalance — III

注意,AUC-ROC 对不平衡不敏感。因此,如果数据集有偏差,那么 AUC-ROC 就不是一个好的指标。让我们找出原因。

解释为什么 AUC-ROC 对不平衡不敏感

先简单介绍一下什么是 AUC-ROC。 别出心裁。

公然从上面的文章复制粘贴(避免写的东西和别人写的一样)。

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

Roc Curve and Terms

所以 ROC 曲线对于不同的阈值(0-1)是真阳性对假阳性。最低值可以是 0.5,用于随机猜测。

让我们看看它对增加不平衡有什么作用。

我们想证明的是:随着失衡的增加,TPR 和 FPR 相对保持不变。

等式 1: TPR = TP/(TP+FN)

随着不平衡的增加,TPR 将大部分保持不变,因为它依赖于错误分类的正面例子。如果我们的算法具有 90%的检测,则 TPR = 90/(90+10) = 0.9,即 TPR 不取决于偏斜,而是取决于我们的算法仅能够多好地检测正类。

等式 2: FPR = FP/(TN+FP)

有趣的是,随着偏斜的增加,我们将有更多的 FP,假设我们的算法将每 100 个负样本中的 1 个分类为正样本(FP),那么当我们有高偏斜时,我们将有许多负样本与正样本相比,以及许多 FP。但是这里我们不考虑 FP,我们考虑 FPR,注意分母中的 TN,真负数(TN)也会随着负数类的增加而增加。结果,FPR 还是老样子。

鉴于这两个方程在直觉上保持一致,AUC-ROC 对偏斜不敏感也就不足为奇了。

对不平衡/偏斜问题使用衍生指标

我建议根据您的业务需求使用以下两种方法中的任何一种。

  • 精确度@召回=x 或 FPR @召回=x
  • Recall@Precision=x

为什么这些有用?

以欺诈检测为例,你想检测 95%的欺诈,所以你的召回率=0.95,现在你想确保你没有太多的 FPs。精度= TP/(TP+FP),所以精度越高,FPs 越低。你的企业在我们的公式中修正了x。你知道召回,现在你用持续召回来优化你的模型,以提高精度或降低 FPR。

同样,考虑癌症的药物管理(化学疗法)。你要确保没有患病的人不会服用这种药物,因为它对健康有巨大的不良影响。你的医院认定只有 1/1000 的诊断是不正确的。或者你的精度= 999/(999+1) = 0.999。所以你的精度是固定的,现在你的模型必须增加检测/召回。因此,Recall@Precision=0.999 是一个很好的指标。

除了使用这些特定于问题的派生指标,您的指标还可以由多个约束组成。例如,在我们讨论的降雨预测问题中,您可以有一个类似于Precision@Recall=0.8,Duration=7 Days的度量,即您想要检测 80%的降雨天,并且您想要在下雨前至少 7 天预测这一情况。有了这些约束,您就可以优化精度。

选择正确指标时需要注意的事项

基于问题和度量的数学性质

如果你的分布是偏斜的,那么准确性和 AUC-ROC 就不好。最好使用精度/召回率或一些派生的度量标准。

基于商业效用

派生指标在这里是赢家,因为它们最好地转化为业务用例。上面我们展示了 Precision@Recall=x 和 Recall@Precision=x 如何很好地编码您的业务需求。

关于为什么不使用曲线下面积/f1 得分/AP 作为衡量标准的信息很少

仅供参考:这是一种意见。

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

F1 Formula

请注意,当精度和召回互换时,F1 可以是相同的值。取精度=0.9,召回=0.3,那么 f1=0.45,反过来取召回=0.9,精度=0.3,还是 f1 = 0.45。现在,如果您将 f1 作为您的模型指标,那么精确度和召回率的值是多少。你的企业准备好接受这两种价值观了吗?他们能理解这个吗?

现在来看 AP/AUC-ROC,他们有类似的问题,你的曲线下面积可能是相同的,这是两条看起来非常不同的曲线,它们优化的东西不同。

结论

让我总结一下我们的学习

  • 不要使用 AUC-ROC、PR-曲线面积(平均精确度分数)等进行业务报告。
  • 不要使用 F1 分数等过于复杂的指标进行报告。
  • 使用衍生指标,因为它们很容易抓住你的业务的本质
  • 如果你的数据不平衡,就不要用 accuracy 或者 auc-roc。

笔记本链接

Reddit 讨论不平衡数据集

将您的模型指标建立在您业务成功的基础上!!

感谢阅读!!

我利用数据科学、人工智能、机器学习和深度学习来解决现实世界的问题。随时联系我 LinkedIn

为机器学习选择正确的评分模式

原文:https://towardsdatascience.com/selecting-the-right-scoring-pattern-for-machine-learning-88898595a42f?source=collection_archive---------29-----------------------

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

根据 Gartner 的 2019 年首席信息官调查,企业对人工智能的采用在过去四年增长了 270%,超过 37%的企业已经在某个方面实施了人工智能。企业正在以惊人的速度采用这项技术,首席信息官和数据科学家正面临着艰难的决定,即哪种人工智能速度适合他们的业务需求。

人工智能可以分为三种评分模式:批处理、事件驱动和实时。根据模型的目标,每个评分模式提供不同的功能。例如,虽然批处理计算在工资单设置中可能工作得很理想,但它不是跟踪银行交易中欺诈的有效方法。

通过探索这三种方法及其潜力,公司能够最大限度地发挥其宝贵的洞察力。

1.成批处理

批处理是人工智能处理大量数据的有效方式。在一段时间内收集事务,然后进行批处理。历史上,批处理用于建模预测分析,因为大量的数据可确保更准确的结果和见解。随着流数据的发展,处理选项正在扩展,但批处理仍然是将大量数据提取到业务策略中的最常见方式。

这种形式的数据处理通常用于在下班后执行银行交易、运行业务报告以及在正确的时间间隔内向客户开账单。批量模型还可用于对客户忠诚度、终身价值或细分会员资格进行评分,时间间隔从每天多次到每月一次不等。任何不需要实时数据输入的任务都适合批处理。

最后,当模型和数据量数量有限时,批处理允许时间灵活性,以及成本和网络能量的效率。对于许多不需要持续数据处理的场景,批处理可能是最好的选择。对于拥有数百个模型的环境,并且这些模型应用于数 TB 或数 GB 的数据,时间和成本很快就会成为问题。

2.事件驱动处理

并非所有数据都是平等的。随着物联网设备、传感器和应用程序的激增,数据科学家面临着确定优先级的任务。大多数数据都是无关紧要的,不需要对模型进行评分;然而,当一个非典型事件发生时,人工智能可以介入并管理最佳的后续步骤。

事件可以被认为是状态的任何重大变化;可能是购买一辆新车,买一栋房子,生一个孩子,或者收到一大笔钱。另一方面,事件可以是小规模的,例如发送电子邮件、访问特定网站或设备达到某个温度。无论系统被设计来跟踪什么事件,当事件发生时,它允许 AI 遵循最佳实践。

事实证明,事件驱动的处理对营销非常有用,因为当企业适应了消费者的日常生活时,他们会变得更加敏感。这种类型的处理对于企业自动化库存控制之类的事情也很有价值,或者对于人工智能知道某人何时到家或离开也很有价值。

当企业能够预先确定应该与一致的行动相关联的指标时,它们应该实施事件驱动的处理。人工智能既可以用来识别这些指标,也可以用来采取行动。

3.实时处理

随着与互联网浏览和生成数据相关的数字标识符的增长,数据科学家努力以接收数据的相同速率处理数据,即实时处理。这种方法需要不断的输入、处理和输出。流媒体催生了快速数据的存在,世界各地的公司都在这种方式中发现了新的价值。

人工智能实时处理数据的一个例子是信用卡购买的欺诈报告。在几毫秒内,银行必须登记输入的信息,应用评分模型,并确定后续步骤。根据信息的得分,银行要么批准购买,要么将其报告为欺诈。实时人工智能处理对于医疗诊断、语音识别、市场分析、消费者推荐和机器人等许多领域都是必要的。

实时处理是关于实现更快的结果,使用上下文线索、即时分析和毫不犹豫的行动;然而,这项技术也有其局限性。某些情况下的质量水平值得怀疑。虽然丢失的数据流可能不会严重影响营销计划的准确性,但对于许多工业目的来说,这种影响可能会产生有害的影响。其他 AI 模型可能依赖于不可用于实时检索的数据源,或者它们不支持可接受的 SLA。这当然限制了它们被实时调用的能力。然而,如果环境包括在非常特定的场景下评分或不经常评分的 AI 模型,那么对这些模型采取实时或按需方法通常比花费资源批量生成很少使用的分数更好。

确定后续步骤

为了实施有效的人工智能战略,公司必须考虑每个用例或场景的需求参数。虽然批处理在历史上是主要的处理模型,但事件驱动和实时处理使结果成为可能,使人工智能数据科学家能够探索新的视野,并在他们的模型中利用实时的上下文数据。

重要的是要记住,所有这些方法都可以一起工作。由于精确度最高,批处理驱动可能是建立人工智能模型的最明智的方式;事件驱动的处理可以在必要时发出危险信号,并推动高度直观的营销活动。最后,实时处理允许成本有效的客户服务和许多类型的个性化。一个熟练的人工智能数据科学家和 ML 工程团队必须一起工作,以确定哪种类型的处理最适合给定的用例及其约束。

原载于 2019 年 7 月 1 日【https://www.quickpath.com】

为深度神经网络选择正确的权重初始化

原文:https://towardsdatascience.com/selecting-the-right-weight-initialization-for-your-deep-neural-network-8ccf8dfcfc4c?source=collection_archive---------15-----------------------

两部分系列的第一部分

您为神经网络选择的权重初始化技术可以决定网络收敛的速度或是否收敛。虽然这些权重的初始值只是许多要调整的参数中的一个,但是它们非常重要。它们的分布影响梯度,从而影响训练的有效性。

在神经网络中,权重表示相邻网络层中单元之间的连接强度。这些权重和前一层中的值的线性变换通过非线性激活函数来产生下一层的值。这个过程在正向传播期间逐层发生;通过反向传播,可以找出这些权重的最佳值,以便在给定输入的情况下产生精确的输出。

在本文中,我们将介绍:

  • 为什么重量初始化很重要
  • 围绕权重初始化的活跃研究领域

我们将不涉及这些初始化方法的数学推导。如果你对这类材料感兴趣,我们可以在文章的内部和结尾(在“进一步阅读”部分)链接到几个很好的资源📚。

为什么权重初始化很重要?

不正确初始化的权重会导致消失或**爆炸梯度问题,从而对训练过程产生负面影响。**对于消失梯度问题,权重更新较小,导致收敛较慢——这使得损失函数的优化较慢,在最坏的情况下,可能会使网络完全停止收敛。相反,使用太大的权重进行初始化可能会导致正向传播或反向传播过程中梯度值爆炸(参见更多此处)。

Deeplearning.ai 最近发布了一个互动帖子在这里你可以选择不同的初始化方式,观看网络列车。这里有一个例子:

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

你会注意到设置一个太小的初始化方法几乎不能让网络学习(即降低成本函数),而过大的初始化方法会导致发散(检查决策边界)。

权重初始化方法发生了怎样的变化?

2012 年,该年 ImageNet 大规模视觉识别挑战赛(ILVSRC)的获胜者 AlexNet 推广了“使用均值等于零、标准差设置为 0.01、某些层的偏差等于一的高斯(正态)噪声进行初始化”的权重初始化方法(参见 Krizhevsky et al. 2012 )。

然而,由于前面提到的消失和爆炸梯度问题,这种正常的随机初始化方法不适用于训练非常深的网络,尤其是那些使用 ReLU(校正线性单元)激活函数的网络。

为了解决这些问题,Xavier 和 Bengio (2010)提出了“Xavier”初始化,在初始化权重时考虑网络的大小(输入和输出单元的数量)。这种方法通过使权重与前一层中单元数量的平方根成反比来确保权重保持在合理的值范围内(称为扇入)。关于如何找到给定单元的扇入和扇出,请参见下图:

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

激活函数的选择最终在确定初始化方法的有效性方面起着重要的作用。激活函数是可微分的,并将非线性属性(即曲率)引入我们的神经网络,这些神经网络对于解决机器学习和深度学习旨在解决的复杂任务至关重要。

激活函数是我们对输入信号进行的非线性变换。然后,这个转换后的输出被发送到下一层单元作为输入。这些非线性激活函数的一些例子是:

  • 乙状结肠的
  • Softmax
  • 双曲正切
  • 热卢
  • 泄漏 ReLU

通常使用校正线性单元(ReLU)(和泄漏 ReLU),因为它们对消失/爆炸梯度问题相对鲁棒。对于像 ReLU 这样的激活函数,何等人(2015)引入了一种更稳健的权重初始化方法,该方法考虑到了它是不对称的这一事实(参见下文何等人论文中引用的性能差异)。这两种方法都使用了相似的理论分析:它们为从中提取初始参数的分布找到了良好的方差。该方差适用于所使用的激活函数,并且是在没有明确考虑分布类型的情况下导出的。

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

图来自何等人(2015)的论文,显示了他们改进的初始化策略(红色)如何比§ReLUs 的 Xavier 方法(蓝色)更快地降低错误率,并说明了其不对称的事实。

关于 Xavier 和 he 初始化方法的可访问证明,请参见 Pierre Ouannes 的精彩帖子“如何初始化深度神经网络?泽维尔和明凯初始化’

值得注意的是,权重初始化仍然是*一个活跃的研究领域。*已经出现了几个有趣的研究项目,包括数据相关初始化稀疏权重矩阵随机正交矩阵初始化

该领域最有趣的发展之一是麻省理工学院的彩票假说,该假说详细描述了这些大型神经网络如何包含比完整网络小 10 倍的较小“子网”。根据研究小组的说法,这些子网也可以学习,做出同样精确的预测,有时比完整的神经网络更快。

彩票假说:寻找稀疏的、可训练的神经网络”的作者 Carbin 和 Frankle 通过执行一个称为修剪的过程来测试他们的彩票假说和子网的存在,该过程涉及根据网络优先级或权重从训练过的网络中删除不需要的连接,以使它们适合低功耗设备。

事实上, TensorFlow 最近宣布了一个新的权重修剪 API:

权重修剪意味着消除权重张量中不必要的值。我们实际上是将神经网络参数值设置为零,以去除我们估计的神经网络各层之间不必要的连接。这是在训练过程中完成的,以允许神经网络适应这些变化。

点击阅读更多关于权重修剪 API 的信息。

互动演示

点击这里试试这个互动演示权重值的大小很重要,但确保权重随机初始化也很关键。这种随机初始化方法基于一种称为打破对称性的已知特性,其中:

  • 如果两个隐单元有相同的输入和相同的激活函数,那么它们一定有不同的初始参数
  • 最好初始化每个单元来计算不同的函数

如果仅用零初始化权重,网络中的每个神经元将计算相同的输出,并且梯度将经历完全相同的参数更新。换句话说,如果神经网络中的单元的权重被初始化为相同的值,则它们将在训练期间学习相同的特征。

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

通过迁移学习,您可以使用以前网络中保存的权重作为新实验的初始权重,而不是从随机初始化的权重开始(即微调预训练的网络)。

Selenium 和 SQL 组合——顶级英超球员

原文:https://towardsdatascience.com/selenium-and-sql-combined-top-premier-league-players-282b2a3fa413?source=collection_archive---------30-----------------------

用 Selenium 抓取并将数据列表到 SQL 数据库表中

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

Source: Jannes Glas via unsplash

英超 2019/20 赛季计划于 2019 年 8 月 10 日星期六开始。虽然对新赛季的期望越来越高,但我想我会调查刚刚过去的这个赛季中表现最好的球员。

这篇教程将演示我们如何简单地收集 2018/19 赛季最佳球员的数据,并将这些数据列表到数据库管理系统(DMS)MySQL 中。然后可以使用 SQL 查询收集的数据。

开始本教程,第一个目标是找到一个关于顶级英超球员的关键统计数据的合适来源。快速搜索将我带到 BBC 足球选项卡上的“英超最佳射手”页面,如下所示。

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

数据挖掘

我想收集的每个球员的数据的关键统计指标是:他们各自的名字和他们竞争的球队,进球和助攻,他们的射门准确性,最后是他们的每球上场时间比率。

首先,我需要找到一个包装器,其中包含我渴望收集的每个玩家的所有统计数据。我在我的 chrome 浏览器中右击感兴趣的页面,将鼠标悬停在我正在搜索的 web 元素上。显然,包装器“div . top-player-stats _ _ item . top-player-stats _ _ item-no-image”包含了所有感兴趣的信息(如下图中突出显示的)。

编写任何 Python 代码之前,我鼓励的一个工作习惯是切换到开发者工具的控制台选项卡,搜索感兴趣的元素。这种方法被认为是最佳实践,因为我们可以直观地检查是否找到了感兴趣的元素。

要使用此功能,请键入 2 个美元符号$$,然后在括号内输入标签和标识符名称。

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

现在已经找到了包装器,还需要找到包装器中的关键信息,这样我们以后就可以遍历包装器,提取每个玩家感兴趣的所有信息。

如下所示,我可以清楚地看到播放器“Mohamad Salah”包含在 h2 标签中,在浏览器和元素选项卡中,类名都以蓝色文本指定。

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

有用的验证:我的建议

控制台实用程序 API 包含一组用于执行常见任务的便利函数:选择和检查 DOM 元素以及以可读格式显示数据。

如图所示,这里我执行了一些快速但有用的验证步骤。从视觉上检查页面,我知道应该有 25 个玩家,实际上通过使用控制台中的 length 函数得到的长度实际上是 25!

此外,让我们确认球员的名字是正确的。我想知道这 25 个元素列表中的第一个元素是否是“Mohamad Salah”,所以我简单地使用了控制台文本功能,一切似乎都如预期的那样工作。

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

最后,让我们确认列表中的最后一个玩家实际上是“勒鲁瓦·萨内”,我用第 25 个元素([24],由于 Python 的第 0 计数索引系统)索引我的搜索查询,并滚动到网页的底部。事实上,“勒鲁瓦·萨内”是名单上的最后一名球员。

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

我对我想从这个网页上获取的每一条数据都重复这个过程,比如球队、进球、助攻和进球率。

使用硒

为了提取、制表并传输到 SQL 数据库,我首先需要导入 selenium webdriver、pandas 库和 sqlalchemy 模块。

sqlalchemy 模块中的 create_engine 函数支持与数据库的交互。提供了一个连接字符串,告诉引擎对象我们正在连接到 MySQL 数据库。

然后,我创建一个 webdriver 对象并将其分配给变量 browser,并使用 browser 对象上的 get 方法导航到 BBC 页面。

我使用 find_elements_by_css_selector 方法找到所有玩家及其数据,并在括号中输入前面找到的包装器。我将该列表分配给变量,明智地称为玩家。

在开发人员工具的控制台选项卡中验证元素的一个很大的优点是,它们可以直接复制并粘贴到‘find _ element(s)_ by _ CSS 选择器方法中,它们是有效的查询!

我现在可以遍历球员列表,提取像进球等关键信息。然后可以将这些附加到适当的列表中。为了确认一切工作正常,我打印出列表,并删除任何我不想要的文本。

例如,我想在我的 SQL 数据库中把“每个目标 140 分钟”作为一个数字,所以我确保删除任何填充和“每个目标分钟”。最后,尽管不是绝对必要的,我退出了浏览器,这样当我在每次迭代中检查我的列表时,页面就不会堆积。

最后,我创建了一个 DataFrame,将我的列表压缩在一起,并将它们分配给合理命名的列。然后,我通过填写下面 GitHub 要点中显示的参数连接到 MySQL。

我需要在底层数据库中存在一个表,以便将我新创建的数据帧 df 插入其中。我用 SQL 语言编写了一个查询来创建一个表,并为每一列分配一个数据类型。

然后执行查询(MySQL 中的表现在已经完成)。现在,剩下要做的就是使用**。to_sql** 方法,并将我的 DataFrame (df)插入到名为 top_players 的新表中。

刷新 schemas 图标显示 top_players 表已经创建。一个简单的 SQL 查询从表中提取所有列,显示 selenium 抓取的数据现在驻留在一个 SQL 表中。

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

最后,让我们执行一个信息查询。我们很想知道,哪些球员的投篮命中率在 60%以上,每分钟进球率低于 185 分钟。使用 WHERE 子句进行过滤会返回满足这些条件的玩家。

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

摘要

这篇教程演示了如何使用 selenium 收集数据,然后将数据制成数据帧,再传输到 MySQL 等 SQL 数据库。

气流上的硒:在网络上自动化日常任务!

原文:https://towardsdatascience.com/selenium-on-airflow-automate-a-daily-online-task-60afc05afaae?source=collection_archive---------7-----------------------

这篇文章演示了如何构建一个使用 Selenium WebDriver 的气流插件来自动化日常在线任务。

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

Photo by Jehyun Sung on Unsplash

自动化提供了一系列好处

  • 提高生产力。
  • 更高的质量。
  • 消除人为错误的可能性并减少体力劳动。
  • 额外的频率和一致性(周末工作!).

如果您的日常任务涉及到网络,那么在 Airflow 上使用 Selenium 每年可能会节省数百个小时,并提高您工作的质量和一致性。

简介

这篇文章的目标是开发一个插件,利用 Selenium 来自动完成关于气流的日常任务。

  1. 设置气流环境。
  2. 开发 Selenium 插件。
  3. 在气流 DAG 中使用 Selenium 插件。

如果你想跳过,这篇文章中讨论的所有代码都可以在我的 GitHub 这里找到。

以下是所涵盖主题和软件的简要概述:

Selenium: 简而言之,Selenium 自动化了浏览器。它主要用于自动化测试目的的 web 应用程序,但是它并不局限于此。selenium 的一个关键组件是 WebDriver,WebDriver API 直接向浏览器发送命令。示例命令可以是导航到网页、填写表格,甚至下载文件。在这篇文章中使用的网络驱动将是 Selenium/standalone-chrome 驱动。

Airflow: Airflow 是一个以编程方式创作、调度和监控工作流的平台。Airflow 的关键组件是 web 服务器、调度器和工作器。web 服务器指的是 Airflow 用户界面,而调度程序根据预定义的指令在一组工作线程上执行您的任务。

最后,为了同时使用 Selenium 和 Airflow,还需要集装箱化软件 docker。

Docker 是一款通过使用容器来简化软件部署和开发的软件。容器允许开发人员将应用程序及其所有需求打包在一起,还可以将软件与其环境隔离开来,以确保它可以在不同的开发环境中工作。Docker 的一大特色是 compose 工具,它用于定义和运行多容器 Docker 应用程序。

我们将首先使用 Docker 来设置我们的气流环境,然后作为我们插件的一部分增加一个额外的 Selenium 容器。

设置气流环境

基础环境:

如上所述,Docker 将用于设置气流环境。为此,请访问https://github.com/puckel/docker-airflow并下载docker-compose-celery executor . yml文件。这是一个 docker-compose 文件,由 Github 用户 Puckel 创建,允许您快速启动并运行气流。compose 文件选择 Celery executor,如果您需要并发运行任务,那么这是必要的,因为它扩展了工作线程的数量。

docker-compose 文件有一些基本的变化。

  • 重命名合成文件:docker-compose.yml。
  • 取消自定义插件卷的注释。
- ./plugins:/usr/local/airflow/plugin

要确保 Airflow 容器对插件和 Dag 目录拥有正确的权限,请在运行合成之前确保主机上存在这些目录。

使用 docker-compose up 命令测试环境在本地运行,UI 应该在 http://localhost:8080 可用。

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

修改环境以适应 Selenium 插件

在完成环境之前,有必要简要解释一下 Selenium 插件是如何工作的,因为它的一些功能会直接影响设置。这个插件将会在后面的文章中详细介绍。

该插件将执行以下步骤:

  1. 启动 Selenium docker 容器
  2. 配置远程硒驱动程序
  3. 向驱动程序发送命令:这将导致从互联网下载一个文件。
  4. 移除运行中的容器

上述步骤可以归纳为两类:

  • 从气流中使用 Docker。
  • 与远程容器交互

从气流中使用 Docker

气流工作者需要能够创建 Selenium 容器,然后发送命令来执行任务。正如 jérme Petazzoni 在这篇文章中很好地解释的那样,在另一个容器中旋转 Docker 容器是不好的做法,只要容器存在并且可访问,就没有必要这样做。允许工作人员创建容器的最简单的方法是通过将主机 Docker 套接字作为一个卷安装在 docker-compose 文件中,从而向工作人员公开它。

worker:
    volumes:
       - /var/run/docker.sock:/var/run/docker.sock

由于没有正确的权限,气流工人仍然无法访问主机 Docker 套接字,因此必须更改这些权限。这可以通过创建名为“Dockerfile-airflow”的新 docker 文件来实现,该文件扩展了 puckel/docker-airflow 基本映像,如下所示:

FROM puckel/docker-airflow:1.10.4USER root
RUN groupadd --gid 999 docker \
   && usermod -aG docker airflow
USER airflow
  • docker 文件首先调用 puckel/docker-airflow 基础映像
  • 作为根用户,创建 id 为 999 的 docker 用户组,并将 airflow 用户添加到该组中。
  • 设置气流用户。

工作者和主机上的 docker 组 id (999)必须相同。要找出主机 docker 组 id,请使用以下命令:

grep 'docker' /etc/group

创建新的 docker 图像:

docker build -t docker_airflow -f Dockerfile-selenium .

接下来要做的是在 Docker-compose 文件中将气流图像名称从puckel/docker-airflow:latest更改为docker_airflow:latest。这意味着合成文件将使用新创建的图像。

Airflow worker 现在可以在主机上创建 Docker 容器,但是仍然需要 Docker python 包。附加安装也可以在 Dockerfile 文件中处理。下面的安装是 Selenium 插件和 DAG 所必需的。

RUN pip install docker && \
    pip install selenium && \
    pip install bs4 && \
    pip install lxml && \
    pip install boto3

要使用插件启动 Selenium 容器,映像必须已经存在于主机上:

docker pull selenium/standalone-chrome

最后,为了让 worker 容器向新的 Selenium 容器发送命令,它们需要在同一个 Docker 网络上。两个容器都将位于外部网络上:使用以下命令创建的“container_bridge ”:

docker network create container_bridge

容器桥网络也需要添加到合成文件中。

worker:
    networks:
        - default
        - container_bridgenetworks:
    default:
    container_bridge:

NB 需要注意的是,上述将主机 docker sock 暴露给 worker 容器并设置权限的方法只能在 linux 环境下工作,要为 MacOS 配置开发环境,请参考这两篇精彩的文章:

与远程容器交互

Selenium 插件通过远程驱动程序向 docker 容器发送命令,它通过 container_bridge 网络连接到远程驱动程序。Selenium 命令将作为主目录中的挂载卷添加到环境中:{AIRFLOW_USER_HOME}

volumes:
    # Selenium scripts 
    - ./selenium_scripts:/usr/local/airflow/selenium_scripts

这些命令将来自一个定制的 Python 模块(selenium_scripts ),它需要位于 Python 路径中。这可以在 Airflow Dockerfile 文件中完成。

ENV PYTHONPATH=$PYTHONPATH:${AIRFLOW_USER_HOME}

气流环境的最后一个变化是允许 Selenium 容器和气流工作者共享文件和内容。当使用 Selenium 从互联网下载内容时,这是必需的,并且可以使用外部命名卷来实现。

docker volume create downloads

需要将“下载”卷添加到 docker-compose 文件:

worker:
        volumes:
            - downloads:/usr/local/airflow/downloadsvolumes:
   downloads:
      external: true

在容器上创建 Docker 卷时,如果没有预先存在的相应目录,它们将由 root 用户创建,这意味着容器用户没有写权限。规避这一点的最简单的方法是在初始构建期间以容器用户的身份创建目录。

对于 Airflow Dockerfile 文件,添加以下行:

RUN mkdir downloads

必须为 Selenium 容器创建一个新的 Dockerfile,这将被称为 Dockerfile-selenium。

FROM selenium/standalone-chromeRUN mkdir /home/seluser/downloads

构建两个新映像:

docker build -t docker_selenium -f Dockerfile-selenium .docker build -t docker_airflow -f Dockerfile-airflow .

环境现已完成,完整的环境如下:

气流 Dockerfile 文件:

Selenium Dockerfile 文件:

docker-撰写:

Selenium 插件

Airflow 的一个很大的特性是插件,插件是扩展 Airflow 现有特性集的一个简单方法。要将新插件与现有的气流环境集成,只需将插件文件移动到插件文件夹中。

Selenium 插件的工作方式如下:

  1. 在主机环境中启动 Selenium Docker 容器。
  2. 在 docker 容器上配置远程 Selenium WebDriver。
  3. 向 WebDriver 发送命令来完成任务。
  4. 停下来,取出容器。

这种方法比使用独立的 Docker 操作符更常用,因为它提供了更好的控制,并且便于调试。

Selenium 插件将包含一个钩子和操作符,钩子处理外部连接并构成操作符的构件。操作员将执行我们的任务。插件文件夹结构如下:


├── README.md
├── init。py
├──勾手
│ ├── init。py
│ └──硒 _hook.py
└──算子
├── init。py
└──硒 _operator.py

要创建一个插件,你需要派生 AirflowPlugin 类并引用你想插入到 Airflow 中的对象,我们在 init 中做了这些。py 文件:

硒钩

Selenium 钩子继承自 BaseHook 模块,它是所有钩子的基类。这个钩子由启动、停止和向 Selenium 容器发送命令的几个方法组成。

创建容器:钩子利用 Python Docker 库向主机 Docker 套接字发送命令,并在主机上创建 Selenium 容器。外部命名卷(下载)安装在本地下载目录中,该目录将被配置为浏览器的默认下载位置。为了支持与工人的交互,还包括了 container_bridge 网络。

**配置驱动程序:**一旦执行了 create_container 方法,下一步就是配置并连接驱动程序,使其满足任务需求。

因为 Selenium 容器位于 container_bridge 网络上,所以可以在网络 IP 的以下位置找到 web driver:<network IP>:4444/wd/hub。可以使用 WebDriver 遥控器将驱动程序连接到。

配置驱动程序的第一步是使用 Options 类使驱动程序能够在 headless 模式下运行,并设置窗口大小以确保页面内容正确加载。无头模式本质上意味着驱动程序没有用户界面。

options = Options()
options.add_argument("--headless")
options.add_argument("--window-size=1920x1080")

第二步是启用浏览器以无头模式下载。这是通过向驱动程序发送 post 请求来完成的,该请求修复了下载行为。

driver.command_executor._commands["send_command"] = (
    "POST", '/session/$sessionId/chromium/send_command')
params = {'cmd': 'Page.setDownloadBehaviour',
          'params': {'behavior': 'allow',
                     'downloadPath': <DOWNLOADS>}}
driver.execute("send_command", params)

**执行任务:**为了使插件尽可能保持任务不可知,Selenium 命令被抽象为一个单独的 python 模块,在运行时导入 DAG。每个脚本的一个条件是它们作为函数导入,第一个参数是驱动程序。这将在后面详细介绍。

**移除容器:**一旦任务完成,容器就可以被移除。

硒算子

如上所述,气流挂钩是运营商的积木。下面的操作符使用 Selenium 钩子和 Airflow 的执行上下文来运行 Selenium 任务。

所有气流操作符必须继承 BaseOperator 类,该类创建成为 DAG 中节点的对象。Airflow 操作符的一个重要特性是能够定义模板字段;这些是 Jinjafied 字段,在执行时可以接受 Airflow 宏。airflow_args 变量是一个 template_field,这意味着它们可以在运行时使用宏动态设置。

在气流 DAG 中使用 Selenium 插件

由于气流环境和 Selenium 插件现在已经完成,下一步是将它们以气流 DAG 的形式组合在一起。气流 DAG 以预定义的方式运行一组任务。

下面的 DAG 示例旨在从 BBC 下载每日播客:醒来发现钱,并将 mp3 文件上传到 S3 供以后使用。《为钱而醒》是英国广播公司第五电台的一档早间财经广播节目,每周日早上 5 点播出新一集。

Selenium 脚本:

唤醒赚钱脚本使用 Selenium WebDriver 导航到 URL:https://www . BBC . co . uk/programs/b 0070 lr 5/episodes/downloads并下载最新一集。

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

一旦浏览器呈现了页面,就会使用 Beautiful soup 来解析下载链接的 html。在下载链接上调用driver.get方法启动下载,并轮询完成。下载后,该文件会被重命名,以便于在任务之间进行跟踪。

正如在插件部分提到的,Selenium 脚本需要是一个可执行的函数,将驱动程序设置为第一个参数。

完成后,确保 Selenium 脚本位于在 Airflow 环境中挂载并在前面的步骤中添加到 Python 路径的文件夹中。

匕首

如上所述,DAG 是任务的集合,创建 DAG 的第一步是描述这些任务将如何运行。创建 DAG 对象时使用的参数就是这样做的。

由于播客在每个工作日的早上 5 点播出,DAG schedule_interval 将被设置为在早上 7 点播放每集。将气流时间表达式设置为仅在工作日运行并不容易,因此 DAG 将每天运行,分支操作符将用于根据一周中的某一天来设置任务。

现在已经定义了 DAG 计划,下一步是添加任务。DAG 任务包括:

  • **启动:**启动 DAG
  • **工作日分支:**根据执行日是否为工作日,确定遵循 DAG 的哪个分支。
  • **获取播客:**下载播客。
  • 上传播客到 S3: 上传播客到 S3。
  • **删除本地播客:**删除播客的本地副本。
  • **结束:**结束 DAG。

开始结束任务利用气流虚拟操作器,它们除了在任务分组时有用之外什么也不做。

Selenium 插件将在下载播客任务中使用。SeleniumOperator 将在运行时执行从 Selenium 脚本模块导入的 download_podcast 函数。一旦播客被下载,它将被保存在新的名称下:episode_{{ds_nodash}}.mp3,但是由于文件名是一个模板字段,这将在运行时呈现。例如,2019 年 10 月 13 日的文件名将为episode_20191013.mp3

工作日分支任务根据执行日是工作日还是周末将 DAG 分成两个分支。分支任务使用 Airflow Python 分支运算符根据 weekday_branch 函数的输出设置下一个任务。

如果执行日是工作日,DAG 运行的下一个任务是 get_podcast 任务,如果执行日是周末,运行的下一个任务是 end。

最后两个任务是:上传播客到 S3移除本地播客。这两种方法都使用 PythonOperator,它被扩展为“Jinjafy”参数。根据 Selenium 操作符,这对于跟踪 podcast 文件名是必要的。

S3 函数将需要一个名为 S3 _ 康恩 _id 的 S3 连接。

最后,最后一步是定义任务顺序,注意 weekday_branch 任务如何先于 get_podcast 和 end 任务。

start >> weekday_branch
weekday_branch >> get_podcast
get_podcast >> upload_podcast_to_s3
upload_podcast_to_s3 >> remove_local_podcast
remove_local_podcast >> end
weekday_branch >> end

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

我希望你喜欢这篇文章;如果你有任何问题或建议,甚至是对未来帖子的想法,请在评论区告诉我,我会尽最大努力回复你。

请检查我的其他气流职位:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值