TowardsDataScience-博客中文翻译-2021-七十八-

TowardsDataScience 博客中文翻译 2021(七十八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

为 PyTorch 模型提供 TorchServe

原文:https://towardsdatascience.com/serving-pytorch-models-with-torchserve-6b8e8cbdb632?source=collection_archive---------8-----------------------

这是关于如何使用 TorchServe 在生产中创建和部署您自己的 PyTorch 模型的详细指南

来源:https://pix abay . com/photos/银河系-星空-夜空-星空-2695569/

TorchServe 是 PyTorch 开发的 ML 模型服务框架。

📖介绍

目前,随着 MLOps 的发展,有许多不同的解决方案为生产中的 ML 模型提供服务,这是当今在 ML 模型的整个生命周期中使用 ML 模型的标准程序。也许最受欢迎的是 TensorFlow 开发的 TensorFlow Serving ,以便在生产环境中服务他们的模型,因此 TorchServe 是在它之后创建的,以便让 PyTorch 用户也可以轻松地服务他们的模型。

在这篇文章中,介绍了使用 ResNet 作为主干来训练和部署迁移学习 CNN 模型的过程,该模型对从一个名为 Food101 的众所周知的食品数据集中检索到的图像进行分类。

为了服务于经过培训的迁移学习模型,我们将使用 TorchServe,并解释使用此框架服务模型之前和之后的所有细节和注意事项。

为了更好地理解本文中介绍的所有过程,作为个人建议,您应该在查看资源库中可用资源的同时阅读本文,并尝试使用相同或不同的 PyTorch 模型再现它,因为“熟能生巧”。

https://github.com/alvarobartt/serving-pytorch-models

警告 : TorchServe 是实验性的,可能会有变化。

🔨要求

首先,你需要确保你已经安装了 Java JDK 11 ,因为这是 torchserve 在部署模型时所需要的,因为它使用 Java 来公开 API。

sudo apt install --no-install-recommends -y openjdk-11-jre-headless

然后您可以继续安装培训和服务模型所需的 PyTorch Python 包。

pip install torch==1.7.0 torchvision==0.8.1 -f [https://download.pytorch.org/whl/torch_stable.html](https://download.pytorch.org/whl/torch_stable.html)pip install torchserve==0.2.0 torch-model-archiver==0.2.0

或者您也可以从资源库中的 requirements.txt 文件安装它们,如下所示:

pip install -r requirements.txt

如果您有任何关于 PyTorch 安装的问题,请访问 PyTorch —本地入门

📂资料组

将要用于训练图像分类模型的数据集是 Food101 ,但不是它的完整版本,只是 10 个类的切片,这或多或少是数据集的 10%。

原始的 Food101 数据集由 101 个食物类别组成,包含 101,000 张图片。对于每个类别,提供 250 幅人工审阅的测试图像以及 750 幅训练图像。有意地,训练图像没有被清理,因此仍然包含一定量的噪声。这主要表现在强烈的颜色和有时错误的标签上。所有图像的最大边长都调整为 512 像素。

来源:来自 TensorFlow 的 Food101 数据集的 10%切片的每个类别的 10 个随机图像

🤖系统模型化

我们将使用 ResNet 作为其主干,并在 ImageNet 上训练一组预训练的权重,来进行迁移学习方法,因为这是图像分类问题的最新技术。

在这种情况下,由于我们想要提供 PyTorch 模型,我们将使用 PyTorch 的 ResNet 实现,更具体地说,是 ResNet18 ,其中 18 代表它包含的层数。

由于我们将从预训练的 PyTorch 模型中使用迁移学习,我们将加载 ResNet18 模型,并使用以下代码冻结其权重:

加载后,我们需要更新 fc 层,它代表完全连接,是模型的最后一层,在这一层之上,将计算权重以优化数据集的网络。在这种具体情况下,我们包括以下连续层:

然后,我们将使用包含 750 幅图像的训练数据集来训练该模型,该训练数据集已被分成 80%-20%分别用于训练和验证。并在包含 2500 幅图像的测试数据集上进行测试。

:关于模型训练过程的更多细节,请随时查看资源库中的notebooks/transfer-learning . ipynb

训练完模型后,你只需要将 state_dict 转储到一个中。pth 文件,包含预训练的权重集,代码如下:

一旦从预训练的模型中生成了 state_dict ,您需要确保它可以被正确加载。但是,在检查之前,您需要将模型的架构定义为 Python 类,以便将预先训练的权重集加载到该架构中,这意味着模型和权重之间的键应该匹配。

由于我们使用了来自预训练模型的迁移学习,并且我们刚刚修改了最后一个全连接层(fc),因此我们需要修改原始的 ResNet18 类。您可以在torch vision/models/segmentation找到该模型的原始类,并在torch vision/models找到 PyTorch 预训练模型的剩余类。

ResNet18 模型的代码如下所示:

这转化为我们的定制模型的架构,它应该是这样的:

如你所见,我们正在创建一个名为image classifier的新类,它继承了该文件中定义的基类 ResNet 。然后,我们需要用我们的架构初始化该类,在这种情况下,该架构与 ResNet18 的架构相同,包括 基本块 ,指定 ResNet18 层【2,2,2】,然后我们修改类的数量,在我们的案例中,如我们之前提到的,该数量为 10。

最后,为了使 state_dict 与 model 类匹配,我们需要覆盖 self.fc 层,这是网络的最后一层。由于我们在训练模型时使用了该顺序层,最终权重已针对该层上的数据集进行了优化,因此只要覆盖它,我们就可以通过修改获得模型的架构。

然后,为了检查模型是否可以加载到image classifier类中,您应该只需要使用下面这段代码定义该类并加载权重:

其预期输出应为“ <所有键匹配成功>”

你可以在 PyTorch 图像分类模型找到更多的图像分类预训练 PyTorch 模型。

:该模型已经在使用 CUDA 11 的 NVIDIA GeForce GTX 1070 8GB GPU 上进行了训练。如果你想得到你的 GPU 规格,只需在你的控制台上使用 nvidia-smi 命令,但要确保你已经正确安装了 nvidia 驱动程序。为了检查 PyTorch 是否正在使用 GPU,您可以使用下面这段代码,它会告诉您是否有一个(或多个)可用的 GPU,如果有,它是该设备的名称,取决于它的 ID(如果有多个 GPU)。

🚀部署

为了部署该模型,在安装了上一节中描述的所有需求之后,您需要重复以下步骤。

1.生成标记文件

首先,您需要生成 MAR 文件,这是用torch-model-archiver 生成的模型的“准备好服务”归档文件,以此类推,为此,您需要使用以下命令:

*torch-model-archiver --model-name foodnet_resnet18 \
                     --version 1.0 \
                     --model-file model/model.py \
                     --serialized-file model/foodnet_resnet18.pth \
                     --handler model/handler.py \
                     --extra-files model/index_to_name.json*

因此火炬模型归档器使用的标志代表:

  • 型号名称 :生成的 MAR“准备就绪”文件的名称。
  • —版本 :它是可选的,尽管包含模型的版本以便对它们进行适当的跟踪是一个好的做法。
  • —模型文件 :定义模型架构的文件。
  • —序列化文件 :已训练模型权重的转储 state_dict
  • — handler :定义数据预处理、推理和后处理的 Python 文件。

注意:你可以定义自定义的处理程序,但是你不需要这样做,因为 TorchServe 已经为每个可能的问题定义了一些默认的处理程序,并且可以通过一个简单的字符串访问。当前可能的
默认处理程序有:图像 _ 分类器图像 _ 分割器对象 _ 检测器文本 _ 分类器。你可以在 TorchServe 默认处理程序找到更多信息。

生成后,您需要将 MAR 文件放入 部署/模型存储 目录,如下所示:

***mv foodnet_resnet18.mar deployment/model-store/***

更多关于火炬模型归档器的信息可从火炬服务器的火炬模型归档器获得。**

2。部署火炬服务器

一旦您创建了 MAR“随时可用”模型,您只需为其提供服务。作为 MAR 文件的预训练 PyTorch 模型的服务过程从 TorchServe REST APIs 的部署开始。

这些 API 是推理 API、管理 API 和度量 API,默认情况下分别部署在端口 8080、8081 和 8082 中的本地主机上。**

在部署 TorchServe 时,您还可以指定存储 MAR 文件的目录,以便在启动时在 API 中部署它们。

使用存储在deployment/model-store/下的当前 MAR 模型部署 TorchServe 的命令如下:

***torchserve --start \
           --ncs \
           --ts-config deployment/config.properties \
           --model-store deployment/model-store \
           --models foodnet=foodnet_resnet18.mar***

所以火炬服务使用的旗帜代表:**

  • — start :表示要启动 TorchServe 服务(部署 API)。
  • — ncs :表示您想要禁用快照功能(可选)。
  • — ts-config :包含配置文件,也是可选的。
  • — model-store :存储 MAR 文件的目录。
  • — models :是将在启动时服务的模型的名称,包括将作为该具体模型的 API 端点的别名和该模型的文件名,格式为endpoint = model _ name . mar

注意:另一个过程可以是首先部署 TorchServe(不指定模型),然后使用管理 API 注册一个(或多个)模型,并缩放工作线程的数量(如果需要)。

***torchserve --start \
           --ncs \
           --ts-config deployment/config.properties \
           --model-store deployment/model-storecurl -X POST "http://localhost:8081/models?initial_workers=1&synchronous=true&url=foodnet_resnet18.mar"curl -X PUT "http://localhost:8081/models/foodnet?min_worker=3"***

有关火炬服务的 CLI 的更多信息,请访问 火炬服务 CLI**

3。检查其状态

为了检查部署的 TorchServe API 的可用性,您可以只向默认部署在 8080 端口的推理 API 发送一个 HTTP GET 请求,但是您应该检查 config.properties 文件,该文件指定了包含端口的“推理 _ 地址”**

***curl http://localhost:8080/ping***

如果一切按预期进行,它应该输出以下响应:

注意:如果健康检查请求的状态是“不健康,您应该从运行 TorchServe 部署的控制台或者从在部署 TorchServe 时自动创建的 logs/ 目录中检查日志。

4。停止火炬 Serve

完成后,您不再需要 TorchServe,您可以使用以下命令优雅地关闭它:

***torchserve --stop***

那么下次您部署 TorchServe 时,如果要作为服务器的模型已经注册/加载,它将比第一次花费更少的时间,因为 TorchServe 将它们缓存在 /tmp 目录下,所以如果名称和版本都没有改变,它就不需要再次加载它们。另一方面,如果你注册了一个新的模型,TorchServe 将不得不加载它,这可能需要更多的时间,这取决于你的机器规格。

🐋码头工人

为了在一个 Ubuntu Docker 映像中重现 TorchServe 部署,您应该只使用下面的一组命令:

***docker build -t ubuntu-torchserve:latest deployment/docker run --rm --name torchserve_docker \
           -p8080:8080 -p8081:8081 -p8082:8082 \
           ubuntu-torchserve:latest \
           torchserve --model-store /home/model-server/model-store/ --models foodnet=foodnet_resnet18.mar***

有关 docker 部署的更多信息,您应该查看 TorchServe 在py torch/serve/Docker上的解释和注释,因为它还解释了如何使用他们的 Docker 映像(而不是清晰的 Ubuntu 映像)以及一些关于使用 TorchServe 的模型的生产部署的提示。

🧙‍♂️用法

一旦您完成了上面的所有步骤,您就可以向部署的模型发送一个示例请求,以便查看它的性能并做出推断。在这种情况下,由于我们面临的问题是一个图像分类问题,我们将使用下面提供的示例图像,然后将它作为 HTTP 请求正文中的文件发送,如下所示:

***wget [https://raw.githubusercontent.com/alvarobartt/pytorch-model-serving/master/images/sample.jpg](https://raw.githubusercontent.com/alvarobartt/pytorch-model-serving/master/images/sample.jpg)curl -X POST http://localhost:8080/predictions/foodnet -T sample.jpg***

它应该会输出类似如下的内容:

记住:原始推理的输出是带有每个类的标识符的字典,而不是类名,在这种情况下,我们在创建 MAR 时将 index_to_name.json 作为一个额外文件,TorchServe 会自动分配带有类名的标识符,这样预测就更加清晰。

上面的命令翻译成 Python 代码后看起来像:

注意:要执行上面的示例代码,您将需要比需求部分中指定的更多的需求,所以只需运行下面的命令来安装它们:

***pip install opencv-python pillow requests --upgrade***

📕结论

总而言之,TorchServe 是 PyTorch 开发的一个强大的框架,以一种简单但一致的方式服务于他们的模型。因此,当希望在生产环境中为基于 PyTorch 的 ML 模型提供服务时,建议使用 TorchServe,因为它与 PyTorch 完全集成。

因此,在 MLOps 生命周期中,当将模型投入生产时,您不需要创建完整的 API 来公开端点以使用您的模型,因为这已经通过 TorchServe 自动完成了。

除了推理 API。这可能是最常见的一个,您还将能够访问 Metrics API 和 Management API,这两个 API 允许您定期收集系统级指标和自定义指标,并分别管理您的服务器以及您所公开的模型和分配给每个模型的服务器资源。

这使得 TorchServe 成为一个真正一致的模型服务框架,因此从保存训练好的模型到服务它的周期可以在一些简单的步骤中完成,使得 PyTorch 的 MLOps 比以往任何时候都更容易。

💻信用

数据集切片的功劳归于丹尼尔·伯克,因为他通过 Twitter DM 很好地向
我提供了信息。关于如何使用 TorchServe 为 PyTorch 迁移学习模型提供服务的提示的学分归 Prashant Sail 所有,正如他在本评论中正确解释的那样。

📑联系信息

你可以通过https://twitter.com/alvarobarttTwitter 或者https://github.com/alvarobartt.GitHub 联系我,或者直接去https://allmylinks.com/alvarobartt你可以找到我所有的链接。

***https://github.com/alvarobartt

🌟我非常感谢所有的关注者和善意的评论!🌟***

使用张量流服务的服务张量流模型📙

原文:https://towardsdatascience.com/serving-tensorflow-models-with-tensorflow-serving-9f1058ac7140?source=collection_archive---------14-----------------------

实践教程

这是关于如何创建 TensorFlow 模型,然后使用 TensorFlow 服务部署它们的详细指南

来源:https://www . stock free images . com/109904469/Photo-of-Space-rocket . html

TensorFlow Serving 是一个灵活、高性能的机器学习模型服务系统,专为生产环境而设计。TensorFlow 服务可以轻松部署新的算法和实验,同时保持相同的服务器架构和 API。TensorFlow 服务提供了与 TensorFlow 模型的现成集成,但可以轻松扩展为服务于其他类型的模型和数据。

📖介绍

目前,随着 MLOps 的发展,有许多不同的解决方案为生产中的 ML 模型提供服务,这是当今在 ML 模型的整个生命周期中使用 ML 模型的标准程序。也许最流行的是 TensorFlow 开发的 TensorFlow Serving ,以便在生产环境中服务他们的模型。

这篇文章是关于如何在生产环境中训练、保存、服务和使用 TensorFlow ML 模型的指南。通过链接到本帖的 GitHub 库,我们将准备和训练一个定制的 CNN 模型,用于对辛普森一家的人物数据集进行图像分类,稍后将使用 TensorFlow 服务进行部署。

为了更好地理解这篇文章中介绍的所有过程,作为个人建议,您应该在检查资源库中可用资源的同时阅读这篇文章,并尝试使用相同或不同的 TensorFlow 模型再现它,因为“熟能生巧”。

https://github.com/alvarobartt/serving-tensorflow-models

🔨要求

首先,你需要确保你已经安装了所有的需求,但是在继续之前,你需要知道 TF-Serving 只适用于 Ubuntu,这意味着,为了使用它,你要么需要一个 Ubuntu VM,要么只需要在你的操作系统中安装 Docker,以便运行部署 TF-Serving 的 Docker 容器。

警告! ⚠️ 如果你没有 Ubuntu,但仍然想通过 Docker 部署 TF-Serving,你不需要安装 APT-GET,因为你将无法安装,你只需要运行 Dockerfile(转到章节 Docker )。

所以,从你的 Ubuntu VM 你需要安装tensorflow-model-server,但是在能够安装它之前你需要添加 TF-Serving 发行版 URI 作为一个包源,如下所示:

echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | sudo tee /etc/apt/sources.list.d/tensorflow-serving.list && \
curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | sudo apt-key add -

然后您将能够使用 APT-GET 安装tensorflow-model-server,如下所示:

apt-get update && apt-get install tensorflow-model-server

最后,对于客户端,您需要安装 Python 包tensorflow-serving-api,这对使用 gRPC API 很有用;还有,tensorflow。注意,两个包的版本应该匹配。

pip install tensorflow-serving-api==2.4.1
pip install tensorflow==2.4.1

如果您对 TensorFlow 安装有任何问题,请访问安装| TensorFlow

📂资料组

将用于训练图像分类模型的数据集是“ 《辛普森一家》人物数据 ”,这是一个大的 Kaggle 数据集,包含一些主要辛普森人物的 RGB 图像,包括荷马、玛吉、巴特、丽莎、玛吉、巴尼等等。

原始数据集包含 42 个 Simpsons 角色类,每个类的样本数量不*衡,总共有 20,935 个训练图像和 990 个 JPG 格式的测试图像,图像大小不同,但由于它们都很小,我们将在训练模型时将其大小调整为 64x64px。

无论如何,我们将创建原始数据集的自定义切片,仅保留训练集,并使用随机 80/20 训练测试分割,删除少于 50 幅图像的类。依此类推,我们将有 32 个类,13,210 个训练图像,3,286 个验证图像和 4,142 个测试图像。

来源:辛普森一家人物数据集中 10 个最常见类别的随机图像

🤖系统模型化

一旦研究了数据,我们将继续定义 ML 模型,在这种情况下,这将是一个 CNN(卷积神经网络),因为我们面临着图像分类问题。

所创建的模型架构由初始的Conv2D层(也表示网络的input_shape)组成,它是一个 2D 卷积层,产生 16 个滤波器作为 3×3 卷积的窗口的输出,之后是一个MaxPooling2D,以便对前一个卷积层产生的张量进行下采样。通常,您会在两次连续卷积后找到该层,但为了简单起见,我们将在每次卷积后对数据进行下采样,因为这是一个简单的 CNN,数据集相对较小(少于 20k 张图像)。

然后,我们将包括Conv2DMaxPooling2D层的另一种组合,因为增加卷积滤波器的数量意味着我们将向 CNN 提供更多的数据,因为它正在从输入图像张量中捕捉更多的像素值组合。

在应用卷积运算后,我们将包括一个Flatten层,以便将图像张量转换为 1D 张量,该张量准备通过 CNN 的数据,以便包括其后的几个完全连接的层。

最后,我们将包括一些Dense完全连接的层,以分配网络的最终权重,以及一些Dropout层,以避免在训练阶段过度拟合。您还需要考虑到最新的Dense层包含的单元与要预测的标签总数一样多,在这种情况下,这是训练集中可用的 Simpsons 角色的数量。

经过训练的模型已被命名为 SimpsonsNet (稍后将使用该名称作为模型的标识符),其架构如下所示:

最后,一旦完成训练,我们将需要以SavedModel格式转储模型,这是 TensorFlow 模型的通用序列化格式。这种格式提供了一种语言中立的格式来保存 ML 模型,这种格式是可恢复的和密封的。它使更高级别的系统和工具能够生产、消费和转换张量流模型。

最终模型的目录应该大致如下所示:

assets/
assets.extra/
variables/
    variables.data-?????-of-?????
    variables.index
saved_model.pb

有关SavedModel格式的更多信息,请访问 TensorFlow SavedModel

最后,作为个人建议,您应该检查/关注以下课程:

🚀部署

一旦使用SavedModel格式保存了模型,如果安装成功的话,让 TF-Serving 工作就非常简单了。与 TorchServe 不同,在 TF-Serving 中提供 ML 模型更简单,因为您只需要安装tensorflow-model-server和指定格式的 ML 模型。

tensorflow_model_server --port=8500 --rest_api_port=8501 \
                        --model_name=simpsonsnet \
                        --model_base_path=/home/saved_models/simpsonsnet

现在,尽管该命令很清楚,不言自明,但还是给出了对所用标志的更详细的解释:

  • —端口:这是 gRPC API 监听的端口,默认值为 8500;但是通常的做法是仍然定义这个标志的值,以便总是知道所部署的 TF 服务服务器的配置。
  • — rest_api_port :这是 REST API 端口,默认设置为零,意味着除非你手动设置端口,否则 REST API 不会被部署/暴露。没有默认值,只是需要与 gRPC 端口不同,所以我们将它设置为 8501(下一个端口)。
  • — model_name :这是要服务的 ML 模型的名称,它将在端点中公开。
  • — model_base_path :这是将要服务的 ML 模型所在的基本路径。注意,his 是绝对路径,不要使用相对路径。

有关 TF-Serving CLI 的更多信息,请访问Train and serve a tensor flow model with tensor flow Serving,您也可以查看tensorflow_model_server --help

一旦 TF-Serving 被成功部署,您就可以向HTTP://localhost:8501/v1/models/Simpsons net上的模型状态REST API 发送一个示例 HTTP GET 请求;它返回所服务的 ML 模型的基本信息。

curl [http://localhost:8501/v1/models/simpsonsnet](http://localhost:8501/v1/models/simpsonsnet)

如果一切顺利,应该会输出类似下面的 JSON 响应:

注意:本期所述,没有一种方法可以正常关闭服务器。

要关闭服务器,您有两种选择:

  • 获取tensorflow_model_server的 PID 并终止该进程:
ps aux | grep -i "tensorflow_model_server"
kill -9 PID
  • 获取正在运行的 Docker 容器 ID 并停止/终止它:
docker ps # Retrieve the CONTAINER_ID
docker kill CONTAINER_ID

这些都不是关闭服务器的推荐方式,因为你应该有一个合适的方式来关闭它,但是,目前这些都是可能的。如果你有更多关于这个问题的信息或者更干净的方法,请告诉我!

🐋码头工人

为了在 Ubuntu Docker 映像中重现 TF-Serving 部署,您可以使用以下命令集:

docker build -t ubuntu-tfserving:latest deployment/docker run --rm --name tfserving_docker -p8500:8500 -p8501:8501 -d ubuntu-tfserving:latest

注意:确保使用docker run中的-d标志,这样容器在后台运行,不会阻塞你的终端。

有关 Docker 部署的更多信息,您应该查看 TensorFlow 在 Docker 的 TF-Serving 中提供的解释和注释,因为它还解释了如何使用 Docker 映像(而不是清晰的 Ubuntu 映像)以及一些关于使用 TF-Serving 的模型的生产部署的提示。

🧙‍♂️用法

在这一节中,我们将看到如何通过 Python 与部署的 API(REST 和 gRPC)进行交互,以便发送样本请求来对来自 Simpsons 角色的图像进行分类。

来源:Reddit—r/the Simpsons

使用请求 Python 模块的 REST API 请求

关于对已部署的 TF 服务预测 API 的 REST 请求,您需要安装如下要求:

pip install tensorflow==2.4.1
pip install requests==2.25.1

然后使用以下脚本,该脚本将发送一个 Simpsons 图像样本,并使用部署的模型对其进行分类:

使用tensorflow-serving-api的 gRPC API 请求

现在,关于 gRPC 对已部署的 TF 服务预测 API 的请求,您需要安装如下要求:

pip install tensorflow==2.4.1
pip install tensorflow-serving-api==2.4.1
pip install grpcio==1.35.0

然后使用以下脚本,该脚本将发送一个 Simpsons 图像样本,并使用部署的模型对其进行分类:

📕结论

总之,由于 TensorFlow ML 模型被转储的 Keras SavedModel格式,用 TensorFlow 服务模型非常容易。TF-Serving 由 TensorFlow 积极维护,这意味着建议将其用于他们提供的 LTS(长期支持)。

ML 模型的一致性和部署的便利性使得 TF-Serving 成为在生产环境中服务 TensorFlow 模型的一个值得考虑的工具。由于模型部署是 MLOps 生命周期中的关键部分,如果您使用主要的深度学习框架(TensorFlow 和 PyTorch ),当前的 ML 服务解决方案是必不可少的,因为它们的服务解决方案 TensorFlow Serving 和 TorchServe 分别使 ML 模型服务变得简单和可扩展。

因此,当您在生产环境中为您的 ML 模型服务时,您非常重视这一点!⚡

💻信用

《辛普森一家人物数据集》归功于的亚历山大·阿提亚创建了它,以及的 Kaggle 社区使之成为可能,因为他们在原始数据集中包含了许多图像(从 20 个人物到 42 个,但我们只用了 32 个)。

📑联系信息

你可以通过Twitter或者 GitHub 联系我。或者直接去 AllMyLinks 那里可以找到我所有的链接。

🌟另外,你可以在 GitHub 上关注我,支持我,让我继续开发开源内容!🌟

**https://github.com/alvarobartt **

尺度等变 CNN

原文:https://towardsdatascience.com/sesn-cec766026179?source=collection_archive---------20-----------------------

如何设计规模均衡的网络

注意:因为不可能有内嵌的公式,我们用一种杂乱的方式制作了这些公式。然而,我们注意到在一些设备上渲染失败。如果“a ⁻、 a ⁻、 a ⁰、 aa**的指数不是从-2 到 2,那么我们推荐查看我们的 草案 ,乳胶制作。

卷积神经网络(CNN)已经被证明是计算机视觉任务中的主导力量,并且具有广泛的应用,例如在图像和视频识别、图像分类、图像分割等方面。CNN 旨在通过使用多个构建块(如卷积层、汇集层和全连接层)通过反向传播自动和自适应地学习要素的空间层次。CNN 的一个有趣的性质是,通过设计,CNN 是翻译等变的,即输入特征的翻译导致输出的等效翻译。作为这意味着什么的直观例子,如果 CNN 已经被训练来检测图像中猫的存在,由于其*移等方差属性,它将能够识别猫,而不管猫出现在图像中的什么位置。这是通过卷积层中神经元感受野的权重共享来实现的。因此,在下图中,如果猫的图像被移动,CNN 仍然能够检测到猫。

细胞神经网络的翻译等变性质的例子;识别猫的能力,不管图像如何移动。【我作者法师(安东尼奥·格拉万提的猫——Shutterstock.com)

现在,当同样的物体以不同的比例出现在图像中会发生什么?比如猫会以不同的尺度出现会怎么样?普通的 CNN 还能认出这些猫吗?不幸的是,尽管细胞神经网络具有非常强大和有趣的特性,但它们并没有被设计成对输入的旋转和尺度变化都是等变的。这就成了一个问题,对吗?因为在现实生活应用中,这种类型的输入转换一直在发生,例如,想象一下由自动车辆处理的图像,所以无论行人可能出现的比例如何,都需要检测行人。

缩放对象的示例;CNN 并不是天生被设计成在不同的尺度上识别相同的物体。【我作者法师(安东尼奥·格拉万提的猫——Shutterstock.com)

那么……如何解决这个问题呢?2019 年,Ivan Sosnovik、michaszmaja 和 Arnold Smeulders 提出了一个非常有趣的解决方案。他们的团队发表了一篇名为“尺度等变可控网络”的论文,解决了这个问题。他们不仅解决了这个问题,还设法提供了一个计算成本相当高的“普通”CNN 解决方案,获得了 MNIST 和 STL-10 数据集的最新结果。因此,由于我们发现这篇论文非常有趣&激动人心,在接下来的章节中,我们分析了他们的贡献,提供了他们方法背后的一些直觉,最后但同样重要的是,展示了我们复制他们结果的尝试。

什么是尺度等方差?

如前所述,CNN 在计算机视觉任务中表现出色的一个最重要的原因是卷积层是*移等变的。这意味着,如果我们将输入图像移动( x ', y ')个像素,该层的输出也会移动。

图 CNNs 翻译等方差属性的例子;识别猫的能力,不管图像如何移动。[图片由作者提供,灵感来自来源,猫来自 STL-10 ]

等方差的一个特例是不变性。不变性意味着无论我们如何变换输入,输出都保持不变。CNN 中从等方差到不变性的转变发生在池层。例如,如果一个 3x3 池块中的最大值在中心,输入移位 1 不会改变该块的输出。然而,一个重要的注意事项必须作出,池只是准不变的,等方差是有限的边缘效应在细胞神经网络。现在,让我们想象一下缩放图像也是如此。如果输入图像被放大/缩小,输出也应该被放大/缩小。如前所述,我们知道,默认情况下,卷积层没有这个属性。为了解决这个问题,必须定义等尺度变化层。等尺度变化层将能够以与常规卷积层响应输入偏移相同的方式响应尺度差异。规模等方差来源于一个数学概念:组等方差。粗略地说,组等变变换意味着如果层的输入由 g 变换,则输出也由 g 变换。而 g 可以是任意同态,例如:*移、旋转缩放,或者这些的组合。通过设计G-等变层,我们可以以一种有意义的方式进一步增加重量分担。

我们应该如何处理这个问题?

数学细节

读一次论文,我们看到 GitHub 库是公开的,我们很高兴我们可以窃取(我的意思是,重用)代码,并有一个免费的午餐…好吧,在这样做之前,让我们了解在数学和算法层面上发生了什么。
论文作者为 1 维信号定义了一切,随后是臭名昭著的“推广到更高维情况是直截了当的”。我们认为直观的解释不一定是一维的,但我们承诺保持低维数。

首先,让我们理解什么是方向可调滤波器:方向可调滤波器是一种内核,内核的尺度可以通过一个参数很容易地改变。论文给出的数学定义是:

内部的 σ ⁻是缩放滤波器,而外部的 σ ⁻是归一化滤波器。这样,我们可以通过参数 σ 来重新调整任意的 ψ ( x )滤波器。下图提供了一些直观的图像:

同样的 ψ (x,y)高斯 2D 滤波器,左边的= 0.5,右边的= 1。【我*法师作者】***

我们要了解的第二件事是规模翻译组。该组由 H 表示,并被定义为缩放操作后跟随*移操作。它由两个子组组成,即 ST

缩放组由 S 表示。群组运算是缩放,其表示为乘以 s ,元素 s 的逆是 s ⁻ =1/s。单位元素是 s * 1/s = 1
然而, s 被定义为离散的缩放群组(在哈尔积分中在数学上更易于管理),由元素[a⁻、 a ⁻、1 在那种情况下, ⁿ的逆就是 ⁻ⁿ.

*移组由 T 表示。分组操作明显是翻译,表现为添加 tt 的元素的逆是- t 。单位元素是 t +(- t )=0。*移组保持连续,而不是被离散化为 1 个像素的倍数,因为 T 上的连续卷积在数学上被很好地定义(并且可以随后缩放)。

为了执行分组操作(即缩放或加法),我们必须通过分组操作将分组元素应用于输入函数的变量(即分别乘以或加到 x )。这两组的一个很好的性质是它们的半直积很容易定义。直积是笛卡儿积的群论等价物;半直积只是直积的推广。这个操作可以想象成两个向量的外积。形式上的定义是 H ={( st ) ∣ sStT },意思是变换 h 是缩放 s 后跟*移 t 。分组操作是( s ₂, t ₂)⋅( s ₁,t₁)=(ss₁,st₁+t。变换方程( s ₂, t ₂)⁻ ⋅( s ₁,t₁)=(s₂⁻s₁,s₂⁻(t₁-t833))我们可以求出逆元素,即(s833)单位元素是(1,0)。

通过定义群 H ,我们将寻找尺度等变卷积的问题转化为寻找群等变卷积的问题。我们把这个问题从一个具体问题转化为一个一般问题,希望能找到解决的办法。幸运的是,我们按照论文的引文找到了群等变卷积的定义:

数学细节高得惊人,因为多维微积分和群论是了解正在发生的事情的最低要求。因此,我们不建议查找它们,但是,如果你选择这样做,我们发现这个这个这个是一个很好的额外来源。
在组等变卷积f(g’)中,表示我们的输入信号,其对应于图像,或后面层的尺度等变输入。
lᵍ[ψ](g '),(或ψ(gg ')变换后)为滤波器, μ ( g ')表示哈尔测度。经过一系列的数学变换,我们得出:

我们还没有谈到的一件事是渠道。常规卷积层对输入通道求和,每个输入-输出通道对有不同的滤波器。然后,让我们的公式做完全相同的事情。在下面的等式中, C ᵢₙ和 C ₒᵤₜ分别是输入和输出通道的数量。

算法

前面提到的等式不能直接用代码实现。首先,在滤波器 ψ 中,S-群是无限的;这需要进一步限制。设 N ₛ(后来也表示为 S )为这个极限,那么组 S 就变成了【a,a⁻₁,…,a^ N ₛ].其次,因为输入图像是在ℤ而不是在ℝ上定义的,所以组 T 必须被离散化。

按照作者的选择,不是将内核中的每个像素定义为一个权重,而是将每个滤波器组成为一个完整基的线性组合。当以这种方式构造函数时,基的维数通常是无限的(例如泰勒级数或傅立叶级数)。因此,我们将算法限制为具有 Nb 维度基础。这样,我们可以将网络的权重设置为线性组合的系数。数学上来说:ψ=∑ᵢ wᵢ ψᵢ,其中 wᵢ是一个重量,ψᵢ是一个基本向量。在这个技巧之后,我们可以实现神奇的等变卷积。

注 1 :根据该论文,具有 2D 高斯包络的 2D 埃尔米特多项式的基足够好
注 2: 这样,特别是在较大的滤波器尺寸下,加强了权重共享。例如,具有 4 阶 hermite 多项式的 7×7 卷积核只需要 10 个参数,而不是常规的 49 个。虽然我们无法从逻辑上推理这种重量共享是否有意义,但我们的直觉告诉我们,它有意义;这种额外的重量分担可能是与等比例变化层一起增加精度的另一个来源。

现在,讨论实现,对于每个滤波器,我们有一个长度为 Nb (线性组合的系数)的权重向量,以及形状为[ NbSVV ]的预缩放滤波器基,其中 Nb 是基数, S 是缩放数, V

当我们有每一个 C ₒᵤₜ — C ᵢₙ对时,如果权重张量的形状为[ C ₒᵤₜ、 C ᵢₙ、 Nb ],乘以形状的预先计算的基[ NbSVV ,这可以有效地实现。对于乘法,我们在 Nb 维度上求和。例如,通过使用以下函数:

**torch.einsum(‘ijk, klmn -> ijlmn’), weights, bases)**

对于该操作的输出,我们将具有形状为
cₒᵤₜ、 C ᵢₙ、 SVV 的滤波器,记为κ。下图显示了这一点:

单个 C ₒᵤₜ→ C ᵢₙ通道的滤波器基础的可视化。[图片改编自论文

使用尺度*移不变卷积的方程,我们可以定义两种情况。我们试图遵循作者的注释:当层的输入具有 1 的尺度维度(也称为“图像”)并且过滤器具有多个尺度维度时,我们称为 TH ,并且当层的输入和过滤器都具有多个尺度维度时,我们称为 HH

TH 的情况下,提到了“S 个简并子上的求和”。我们觉得这条线有点太模糊,因此,我们提供了另一种解释:对于尺度维度中的每个 s ,我们在κ[:,:, s ,:,:]和输入图像之间执行常规卷积。卷积的结果存储为图像阵列,从而产生从组 TH 的操作。为了利用已经优化的 PyTorch 库,可以用以下形式实现 TH

**convTH(f, w, ψ) = squeeze(conv2d(f, expand(w × ψ)))**

在这种情况下,输入κ滤波器从[ C ₒᵤₜ、 C ᵢₙ、 SVV ]$的形状扩展为[ C ₒᵤₜ SC ᵢₙ、 VV 。此后,将扩展的滤波器基与输入图像(具有[ C ᵢₙ, UU ]的形状,其中 U 是图像的大小)进行卷积。这个卷积的输出产生了一个形状为[ C ₒᵤₜ SUU ]的张量,它压缩了维度[ C ₒᵤₜ, SUU ]。虽然我们已经从头实现了这一层,但是我们还没有使用它;由于时间限制,我们被迫选择另一种方法,以满足项目的最后期限。

注 1 :对于展开κ的形状,文中定义了尺寸
[ C ₒᵤₜ, C ᵢₙ SVV 而不是 C ₒᵤₜ SC 我们认为作者在这里犯了一个相当痛苦的错别字。
注 2 :输入图像的大小为[ UU ],因为用于基准测试的数据集使用的是正方形图像。没有任何东西限制它具有[ U ₁, U ₂]的形状,但是我们决定遵循作者的符号。
注 3 :应用卷积时,输出并不总是具有[ UU ]的大小,它以正常方式通过填充、内核大小和步幅进行修改。

卷积的可视化 TH 。为了简单起见,隐藏了空间组件。[图片改编自论文

HH 的情况可以想象成在 xys 方向做卷积,其中方向 s 指的是尺度间相互作用。然而,由于这将进一步扩展数学表述,我们愿意认为我们已经为 TH 提供了足够的直觉,以便人们能够自己理解 HH

数据预处理和扩充

关于手传实验,我们必须处理和扩充两个数据集的数据,即 MNIST 和 STL-10。对于每一个,正如本文中提到的,我们都遵循了特定的步骤。

MNIST

我们使用 0.3-1 之间的均匀采样因子重新缩放了 MNIST 图像,并用零填充图像以保持初始图像的分辨率。

重新缩放 MNIST 图像的示例。【我法师作者】

此外,我们生成了该数据集的 6 个实现。培训 10.000,测评 2.000,测试 48.000。

STL-10

类似地,对于 STL-10 数据集,我们按照论文的说明为实验准备数据。我们将图像归一化,减去每个通道的*均值,除以每个通道的标准偏差,通过应用 12 像素零填充和随机裁剪回 96x96px 尺寸来增强。此外,我们使用了水*随机翻转(50%的概率)和 32 像素的 1 孔剪切。

STL-10 图象的数据处理。【我法师作者】

运行代码,我们能够为 MNIST 数据集复制实验。虽然 STL-10 的代码是可用的,但我们无法复制结果,因为我们没有足够的计算资源来进行实验。在复制了修改后的 MNIST 数据集(在上一节中介绍)后,我们能够重现结果。这些有点类似,差别不大。

对于 MNIST 数据集,我们在以下模型上运行了实验:
mnist _ ses _ scalar _ 28
mnist _ ses _ scalar _ 56
mnist _ ses _ vector _ 28
mnist _ ses _ vector _ 56
mnist _ ses _ scalar _ 28p
mnist _ ses _ scalar _ 56p
mnist _ ses _ vector _ 28p
mnist _ ses _ vector _ 56p

复制修改后的 MNIST 数据集后,我们能够重现结果。对于上一节底部提到的每个模型,进行了两个实验:一个实验的比例因子设置为 1,另一个实验的比例因子设置为 0.5。因此,对于每个模型,我们获得了 12 个结果(每个实现 6 个)。结果存储在“results.yml”中,并使用我们编写的 python 脚本进行进一步处理。我们复制了与作者相似的结果。结果显示在下表中。

MNIST 数据集的重复结果。“+”表示缩放数据扩充。

作者定义的 STL10 模型有 11M 个参数。我们试图以更小的批量运行这些模型(以适应我们 12GB 的 GPU 限制),但是为了重现有意义的结果,模型训练得太慢了。后来,这些没有包括在内。

结论

通过阅读本文,我们希望你现在能更好地理解什么是等尺度方差,以及为什么设计等尺度方差 CNN 是有价值的。虽然乍一看,这篇论文看起来真的“数学化”,但我们可以说,在花了无数时间在维基百科的文章上试图扩展我们在群论方面的知识后,我们有点理解作者的意图了。我们认为G–等变卷积(如 scale–等变)是细胞神经网络的一个有前途的方向,因为它们的适用性是不可否认的。总之,对于这个项目,我们重现了数据扩充步骤,重新运行了 MNIST 实验,并产生了准等效的结果。我们试图运行 STL–10 实验,但是计算资源的缺乏战胜了我们。我们试图实现这些层本身,尽管我们无法测试它,我们相信我们已经成功地实现了 T→H 层,但是剩下的时间不够了。

感谢

这个博客是在代尔夫特大学 CS4240 深度学习课程的背景下创建的,作为一个小组项目。
我们要感谢讷计斯·托曼和托马什·莫蒂卡的建议和有益的见解。

有用链接:
链接到原创论文
链接到这个项目的网站
链接到我们的 GitHub 资源库

作者: 马克·卢卡奇 吉图布 斯蒂芬·彼得雷斯库 吉图布

如果你喜欢这篇文章,别忘了分享!

Streamlit 的会话状态

原文:https://towardsdatascience.com/session-state-for-streamlit-dc9ea1685ea?source=collection_archive---------20-----------------------

现在,您可以在应用程序交互和重新运行之间存储信息

(图片由作者提供)

在 2019 年推出 Streamlit 后不久,社区就开始寻求为他们的应用程序添加状态的方法。针对会话状态的黑客攻击自 2019 年 10 月就已经出现,但我们希望建立一个优雅的解决方案,你可以用几行代码直观地将其编入应用程序。今天我们很高兴发布它!

现在,您可以使用会话状态来跨重新运行存储变量,在输入小部件上创建事件,并使用回调函数来处理事件。这一强大的功能有助于创建能够:

  • 执行数据/图像注释
  • 支持分页
  • 添加依赖于其他小部件的小部件
  • 构建简单的有状态游戏,如战舰,井字游戏等。
  • 更多——所有这一切都是通过编写 Python 脚本的应用程序来实现的!

💡如果你想直接进入,请查看我们的演示来看看上面的一些应用程序的运行情况,或者前往文档获取更多关于开始的详细信息。

向您的应用程序添加状态

在 Streamlit 中,与小部件交互会触发一次重新运行,代码中定义的变量会在每次重新运行后重新初始化。但是有了会话状态,当你不希望你的变量被重新初始化的时候,有可能在那些实例的重新运行中保持值。

例如,这里有一个简单的计数器,它在多次按下增量按钮时保持一个计数值。每次按下按钮都会触发一次重新运行,但在重新运行过程中,计数值会保留并递增(或递减):

(图片由作者提供)

💡为了继续构建这个例子,请跟随我们的主题指南:向您的应用程序添加状态🤓

上面展示了一个基本的例子,说明了值是如何在重新运行时保持不变的,但是让我们继续看一些更复杂的东西!

回调函数和会话状态 API

作为此次发布的一部分,我们将在 Streamlit 中启动回调。回调可以使用on_change参数作为参数传递给像st.buttonst.slider这样的小部件。

💡好奇什么是回调?维基百科说得好:“回调,也称为“call-after”函数,是作为参数传递给其他代码的任何可执行代码;其他代码应该在给定的时间回调(执行)参数。如果你想了解更多,这里有一个链接。

使用会话状态,与小部件更改相关联的事件或与按钮按压相关联的单击事件可以由回调函数来处理。记住以下执行顺序很重要:

(图片由作者提供)

执行顺序:如果一个回调函数与一个窗口小部件相关联,那么窗口小部件中的一个变化触发以下顺序:首先执行回调函数,然后应用程序从上到下执行。

这里有一个例子:

(图片由作者提供)

在上面,我们展示了回调和会话状态的使用。我们还展示了一个高级概念,其中会话状态可以使用key参数与小部件状态相关联。

要了解更多信息,请查看会话状态文档中的高级概念部分,要详细查看 API,请访问状态 API 文档

包扎

这就是对会话状态的介绍,但我们希望这不是对话的结束!我们很高兴看到您将如何使用这些新功能,并且 state 将为社区解锁所有新功能。

要开始使用,请升级到最新版本,以便在您的应用中使用st.session_statecallbacks:

pip install --upgrade streamlit

如果你对这些有任何疑问(或者对 Streamlit 有任何疑问),请在下面的评论中或者在论坛上告诉我们。一定要来论坛或推特分享你做的所有酷的东西!🎈

资源

原载于 2021 年 7 月 1 日https://blog . streamlit . io

如何启动 R/Python 代码让同事心存感激

原文:https://towardsdatascience.com/set-path-automatically-r-python-4dbc4963321e?source=collection_archive---------25-----------------------

设置路径和创建输出文件夹的自动化方式

作者图片

在学术界,我的代码曾经是我的。我们讨论了实验和数据分析的方法。试图理解其背后的结果和现象花了我们很长时间。但是我不需要分享我的代码。当我进入金融市场时,事情发生了变化。

编写无论保存在哪里都可以运行的代码变得至关重要。共享驱动器或文件夹名称的映射可能会有所不同,但代码应该仍然可以正常运行。它节省时间和挫折。幸运的是,很少几行代码可以做到这一点!

在本文中,我们将浏览代码的两个方便的部分(对于 R 和 Python*):

  1. 如何自动设置工作目录?无论您或您的同事将文件保存在哪里,它都能运行代码。
  2. 如何直接从代码中创建输出文件夹?您不必在代码之外搜索文件夹。

*我使用 RStudio 和 Jupyter 笔记本。

我们走吧!

1。设置您的工作目录并运行代码,无论您将它保存在哪里

代码要求在开头设置路径。但是您很忙,有许多打开的项目,并且不记得在哪里保存了代码。因此,让您的代码为您检查路径,并将其用作工作目录。下面几行代码将帮助你做到这一点。

R 代码

r 总是指计算机上的一个目录。为了读取当前工作目录,我们使用两个主要函数:

  • setwd (dir) =设置工作目录。您可以使用特定的路径,例如 C:/Users/Aga/R。这意味着当您想要更改文件夹时,需要手动更新路径。自动化会更容易。可以用下面的代码来实现:setwd(dirname(rstudioapi::getSourceEditorContext()$ path))。请注意,您必须先保存 R 代码。
  • getwd () =获取工作目录。这个函数读取当前目录。它没有参数,所以使用之前在 setwd()函数中指定的路径。

看看它在代码中的样子:

r:将当前路径设置为工作目录

如果要将父文件夹设置为路径,可以使用 setwd( " . " ):

r:将父文件夹路径设置为工作目录

Python 代码

Python 允许读取文件的目录,并将其设置为工作目录。我们需要 os 库来做这件事,所以我们在下面的第一行中导入它。

在第二行中,我们使用了 os.getcwd() 函数,意思是“获取当前工作目录”。这个函数没有参数,它只是检查当前路径。我们将这个目录分配给变量 dir_code 。因此,我们可以在第三行打印路径,以检查我们是否在我们希望的地方。

Python:将当前路径设置为工作目录

如果我们想将父文件夹设置为工作目录,我们可以使用 os.chdir( )。)、这相当于的 setwd (“.”)在 r。

Python:将父文件夹路径设置为工作目录

无论您如何映射您的驱动器,代码都已准备好运行!如此简单,如此省时,对你的同事如此有帮助。

2。创建一个新文件夹来保存结果,并轻松地保持您的输出有序

直接从代码创建新文件夹比手动检查文件夹更容易。下面,你可以看到它是如何工作的。

R 代码

首先,我们必须为输出文件夹指定一个新路径。我们可以通过使用paste()函数来实现。这是一个有用的函数,它将我们想要连接的术语和分隔符作为参数:

然后,我们可以使用 dir.create() 函数创建输出路径:

r:在您的路径目录中创建输出文件夹

这些都在这里了!我们继续学习 Python。

Python 代码

与 R 不同,Python 不需要任何特定的函数来连接先前指定的路径和新的文件夹名。如第一行所示,加号很好地完成了这项工作。

然后,我们使用 os.path.exists()检查我们的新文件夹是否已经存在。如果不是,使用 os.makedirs() 创建它。您可以查看下面的代码:

Python:创建输出路径(如果尚不存在)

现在,我们已经准备好开始编码并分享它,没有任何路径问题!

感谢阅读!

我们讨论了用 R 和 Python 启动代码的简单但有用的方法。我希望你在日常工作中找到一些有趣的东西。

我很想在下面的评论区看到你最喜欢的简单函数!如果你喜欢直接联系我,请随时通过 akujawska@yahoo.com 的 LinkedIn 联系我。不久后见!

您可能还喜欢:

在几分钟内设置好 AWS 上的气流环境

原文:https://towardsdatascience.com/set-up-an-airflow-environment-on-aws-in-minutes-f934cf10ec54?source=collection_archive---------10-----------------------

Amazon Managed Apache Airflow 入门

Apache Airflow 是一个强大的*台,用于调度和监控数据管道、机器学习工作流和 DevOps 部署。在这篇文章中,我们将介绍如何在 AWS 上建立一个气流环境,并开始在云端调度工作流。

Ashkan ForouzaniUnsplash 上拍摄

这是调度机器学习工作流系列的第一部分。 Airflow 允许您安排数据提取,并提供工程管道、模型培训、模型部署等功能。本教程中的内容适用于任何想要学习如何在亚马逊气流环境中创建、调度和监控他们的生产工作流程的人——不仅仅是机器学习工程师。

  1. 在 AWS 上设置一个气流环境(这篇文章)
  2. 更多即将推出……

动机

无论你是有志于从事工程或数据科学职业,编程处理数据和构建系统以在下游消费数据(例如机器学习模型)的技能组合可能对你的成功至关重要。这些技能如此抢手是有原因的。

为什么是气流?

Airflow 是编排 ETL 作业、机器学习管道和 DevOps 部署最常用的工具之一。

当我第一次开始机器学习时,我对工作流的(不)管理让我今天畏缩不前。在我自己的环境中,我在一台大型本地计算机上使用 cron 安排了作业。当我的作业失败时,没有警报,也没有 UI 来监控进度—我必须每天手动检查日志!当我在度假的时候,我的同事就经历了这种残酷的过程。

气流使您的工作流程更加透明。您可以在 UI 中跟踪作业进度,并在出现故障时轻松配置警报。团队可以轻松共享一个气流环境,因此您不需要总是随叫随到。

亚马逊为什么要管理气流?

直到最*,创造和维持一个气流环境还是相当复杂的,即使对于有经验的工程师来说也是如此。Airflow *台包括一个前端 web 服务器、一个调度服务、执行器和一个后端数据库——所有这些都必须进行配置。最重要的是,气流必须与其他服务连接,如亚马逊 EMR 和 S3,以便在你的管道中利用它们。

当我第一次开始使用 Airflow 时,我天真地试图支持我自己的实现(这是一场灾难)。我很快意识到,控制气流才是出路。

在亚马逊推出 Apache Airflow 托管工作流之前,该领域还有其他一些选择。然而,有了 Amazon,您可以将工作流管理解决方案与 AWS 上的其他资源无缝集成。此外,AWS 不会很快消失,所以你不必担心你的管道管理系统的稳定性取决于另一家公司是否继续运营。如果你有兴趣学习如何建立一个气流环境来帮助你找到工作,对我来说,AWS 是开始的地方。使用 AWS 的公司比任何其他云提供商都多。

亚马逊帮助你保持你的气流版本最新。次要版本更新和修补程序会自动处理,并允许您计划主要更新。

我们开始吧

警告:创造一个可控的气流环境需要资金。如果您只是为了自己的教育而这样做,我建议您设置环境,加载并运行您的 Dag,然后删除您的资源。查看更多关于定价 此处

步伐

  • AWS 帐户设置。
  • 创建一个测试 DAG 并将其上传到 S3。
  • 编写一个 requirements.txt 文件,在您的环境中包含开源包。
  • 在 AWS 控制台中创建一个气流环境。
  • 访问气流用户界面。

AWS 帐户设置

首先,如果你还没有 AWS 账户,你需要一个。完成本教程中的第一步和第四步,使用 IAM 管理员用户和 S3 桶设置您的帐户。

创建测试 DAG

让我们创建一个简单的气流 DAG,在我们即将创建的环境中进行测试。

# test_dag.py# This code borrows heavily from [https://airflow.apache.org/docs/apache-airflow/stable/tutorial.html](https://airflow.apache.org/docs/apache-airflow/stable/tutorial.html)from datetime import timedelta
import loggingfrom airflow import DAG
from airflow.operators.python_operator import PythonOperator
from airflow.utils.dates import days_agodefault_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'email': ['[brent@brentlemieux.com](mailto:brent@brentlemieux.com)'],
    'email_on_failure': True,
    'email_on_retry': False,
    'retries': 1,
    'retry_delay': timedelta(minutes=5),
}dag = DAG(
    'simple_demo',
    default_args=default_args,
    description='A simple DAG with a few Python tasks.',
    schedule_interval=timedelta(days=1),
    start_date=days_ago(2),
    tags=['example'],
)### PYTHON FUNCTIONS
def log_context(**kwargs):
    for key, value in kwargs.items():
        logging.info(f"Context key {key} = {value}")def compute_product(a=None, b=None):
    logging.info(f"Inputs: a={a}, b={b}")
    if a == None or b == None:
        return None
    return a * b### OPERATORS
t1 = PythonOperator(
    task_id="task1",
    python_callable=log_context,
    dag=dag
)t2 = PythonOperator(
    task_id="task2",
    python_callable=compute_product,
    op_kwargs={'a': 3, 'b': 5},
    dag=dag
)t1 >> t2

我们需要上传这个 DAG 到我们的 S3 桶。这在 AWS 控制台中很容易做到——只需在控制台中搜索 S3,导航到您想要上传的文件夹,然后单击Upload。或者,您可以使用 AWS CLI 上传您的 DAG。

让我们在我们的 bucket 中创建这个路径,并将我们的测试 DAG 上传到这里:s3://<your-bucket>/airflow/dags/<your-dag.py>

为气流环境配置开源包

接下来,我们将创建一个requirements.txt文件,其中我们将指定我们希望安装在我们的环境中的开源包。

# requirements.txt example
apache-airflow[amazon]==1.10.12
boto3==1.17.44

将您的需求文件上传到您的 S3 存储桶,位置如下:s3://<your-bucket>/airflow/requirements.txt

创造气流环境

现在我们准备好创建我们的环境了!

  1. 导航到 AWS 控制台中的Managed Apache Airflow,点击Create environment

2.命名您的环境并选择您的 Airflow 版本(我建议您选择最新版本)。

3.添加您的 S3 桶、DAGs 路径和 requirements.txt 路径,然后单击Next

4.将网络服务器访问设置为Public network并检查Create new security group。接下来,点击Create MWAA VPC

5.在 CloudFormation 模板中,保留默认值并单击Create stack

6.您需要等待几分钟来创建您的 VPC,然后选择您的新 VPC。

7.选择您的环境类别。我建议选择mw1.small,如果需要的话,从那里开始扩展。

8.配置您的监控、加密和气流配置选项—如果您不知道该选择什么,请暂时保留默认值。

9.除非您知道您需要什么权限,否则选择选项Create a new role,AWS 将为您创建一个具有必要权限的角色。

10.点击Next,检查您的选择,然后点击Create environment!启动您的环境需要 20–30 分钟。

访问气流用户界面

一旦您的环境准备就绪,只需点击Open Airflow UI即可开始运行!

下一个

现在您已经知道如何设置气流集群,尝试在创建更多气流 Dag并在您的环境中测试它们。在不久的将来,我将创建更多的气流教程,涵盖的主题有在亚马逊 EMR 中运行 Spark 作业。

取得联系

感谢您的阅读!请让我知道你是否喜欢这篇文章,或者你是否有任何批评。如果你觉得这个指南有用,一定要关注我,这样你就不会错过我以后的文章。

如果你在一个数据项目上需要帮助或者想打声招呼, LinkedIn 上联系我。干杯!

用 Python 为您的应用程序设置 Heroku PostgreSQL

原文:https://towardsdatascience.com/set-up-heroku-postgresql-for-your-app-in-python-7dad9ceb0f92?source=collection_archive---------7-----------------------

实践教程

托拜厄斯·菲舍尔在 Unsplash 拍摄的照片

所以我的问题是。我有大量的数据,我需要这些数据能够动态地在我的仪表盘上运行应用程序。听起来熟悉吗?更具体地说,我运行哲学数据项目,这是一个实现数据驱动工具的网站,帮助人们探索哲学史。所以我有大约 330,000 句哲学句子,并且我一直在增加,我需要所有这些都可以动态地供人们通过我网站上的应用程序轻松搜索。

我不能把一个巨大的电子表格扔进 Heroku 这将打破段塞的大小,而且会慢得令人难以置信。幸运的是,Heroku 非常乐于助人,他们将为您提供一个免费的 Heroku Postgres 服务器来存放您的数据并使其可以访问。

很好,但事实证明,实际设置并不那么简单,虽然肯定有一些人在网上有很好的教程,但没有一个人真正从头到尾指导我们。这就是我要做的。

主要有三个步骤:
1。设置 Heroku Postgres 并将其连接到您的应用程序。
2。向服务器添加数据。
3。在应用程序中调用数据并运行查询。

让我们一次看一个。首先,你只需要一个现有的 Heroku 应用程序。

1。设置 HEROKU POSTGRES

有两种方法可以做到这一点。首先是通过 Heroku 网站界面。登录并转到您的应用程序。然后,在 resources 选项卡下,从 addons 菜单中搜索 Postgres。点击标题为“Heroku Postgres”的选项

看起来我的朋友特雷弗实际上是个英雄?有意思……

系统会提示您选择一个层;选择最符合您需求的(有一个免费的,但它限制您为 10,000 行)。

很好,现在点击插件,你将被带到你的 Postgres 仪表板。

哇,这么顺从

太好了,你可以走了!请注意,所有关于您的密码和网址的信息都在“设置”标签下。Heroku 会自动填充您的相关配置变量,但是如果您将来需要它,您可以在那里找到它。

如果您喜欢使用命令行,您可以遵循以下步骤。首先,打开一个终端,导航到你的应用程序。然后使用命令heroku addons检查你当前安装了什么插件。

现在您可以使用heroku addons:create heroku-postgresql:hobby-dev添加 Postgres 数据库。当然,如果你想要一个不同的计划,用那个代替hobby-dev

好了,你可以走了。请注意,无论采用哪种方式,您现在都将在 Heroku 环境中拥有一个新的DATABASE_URL配置变量;这个变量存储了——您猜对了——数据库 url。

2.向您的服务器添加数据

好的,现在你有一台服务器了。但是你没有任何数据。所以你需要添加它。大概有一百万种方法可以做到这一点,但是这里有一个简单的方法,你可以只用 Python 从 Jupyter 笔记本上运行。

首先,将您的数据设置为您想要的熊猫数据框架。

现在,使用下面的代码。

#import the relevant sql library from sqlalchemy import create_engine# link to your databaseengine = create_engine(<YOUR DATABASE URL>, echo = False)# attach the data frame (df) to the database with a name of the 
# table; the name can be whatever you likedf.to_sql(‘phil_nlp’, con = engine, if_exists='append')# run a quick test 
print(engine.execute(“SELECT * FROM phil_nlp”).fetchone())

这段代码基于它的 url 连接到你的数据库,然后全部上传。

这段代码可以填充一个空数据库,或者向现有数据库追加新值。要改变它插入值的方式,请更改if_exists参数。

3.使用应用程序中的数据

酷,现在你已经有了一个数据库,你已经为你所有珍贵的小数据建立了一个美丽的家。然而,如果您没有正确地查询它们,您的数据婴儿肯定会因疏忽而死亡。

但是你如何从你的应用程序中查询它们呢?它们都在那边的数据库里,这不可能吧?

一点也不,我的朋友,事实上这很容易。我使用 Dash 在 Python 中构建了我的应用程序,但同样的原则应该适用于任何其他 Python 应用程序。

要连接到数据库,你需要psycopg2库。像这样建立连接:

import psycopg2DATABASE_URL = os.environ.get(‘DATABASE_URL’)con = psycopg2.connect(DATABASE_URL)cur = con.cursor()

这段代码从环境变量中读取数据库 url,并使用它来建立到服务器的连接。

注意,如果不通过 Heroku local 在本地机器上运行 app,app 就不起作用;url 保存在您的 Heroku 环境中,除非您自己指定,否则通常无法在您的本地环境中使用。

很好,那么让我们把它们放在一起——这是一个应用程序的例子,它让用户在数据库中搜索给定单词的每一次出现。

现在你知道了!希望这是有帮助的。如果您有任何问题,请随时通过 LinkedIn 或[电子邮件](mailto: kcalizadeh@gmail.com)与我联系,并查看搜索应用程序 repo 中的PhilosophyData.com的实例。谢谢!

使用 PyTorch 在几分钟内设置强大的深度学习基线

原文:https://towardsdatascience.com/setting-a-strong-deep-learning-baseline-in-minutes-with-pytorch-c0dfe41f7d7?source=collection_archive---------16-----------------------

从基线到定制模型不断迭代,以更快地交付产品或更快地发布您的研究。

借助闪存,在几分钟内构建 PyTorch 基准

无论你是数据科学家、研究工程师、人工智能研究员还是机器学习工程师,基线是不可协商的。在建立良好的基础之前,不要构建一个花哨的 GAN 或尝试一个复杂的想法。

在本教程中,我们将使用 Flash 在几分钟内构建两个 PyTorch 基线。之后,我们将使用 Lightning 迭代该基线,以获得针对您的特定环境定制的实现,并从您的模型中获取更多性能。

基线与最终模型

为了快速获得价值,分阶段从基线迭代到最终模型。

大多数时候,我们希望通过深度学习尽快找到最佳解决方案。但这可能需要几个月的研究和书面实施。在这个过程中,您可以使用一些技巧,从一个强大的基线开始,迭代地获得最佳模型。

请记住,基线的目标是将您的想法呈现在用户面前,或者获得您正在处理的数据集的基准。一旦你建立了基线,你就可以继续进行你需要做的所有复杂的深度学习工程,知道你是从一个强大的基础开始的。

基线 1:蚂蚁对蜜蜂

为了说明关键的想法,假设你在一家家庭保险公司工作,你开发了一个摄像头,业主安装它来跟踪他们房子里的虫子类型。你的保险是基于摄像机捕捉到的蚂蚁和蜜蜂的数量。作为该系统的一部分,您决定构建一个分类器来确定什么是蚂蚁或蜜蜂。

首先,让我们安装闪光灯

pip install lightning-flash

现在我们需要做的是找到一个强大的预训练模型,并对你的数据进行微调。这里,我们使用在 Imagenet 上预先训练的模型,并使用“冻结 _ 解冻”方案调整权重。

在短短几行中,你已经设法为你的工作建立了一个基线。运行它,你会发现它有 80%的预测准确率。如果这对您来说足够好,您可以在同一天内部署该模型。

基线 2:爱好者基线

另一个简单的方法是改变你基线的主干,使用来自脸书人工智能(Swav) 的最新自我监督模型。有了 Flash,这很简单:

把主干从‘resnet 34’改成‘swav-imagenet’就行了。

ImageClassifier(backbone='swav-imagenet')

现在,如果你幸运的话,你的模型可以获得另外 5%的准确性。同一天内,你重复了两次你的工作!

最终模型

但是现在有趣的部分和实际的工作开始了。

在这里,你将刷掉所有那些布满灰尘的数学书籍,找到一份深度学习论文的列表,并开始尝试深度学习方面的最新和最棒的东西。

假设您有一些其他数据想要集成到您的模型中,并且您想要使用一种奇特的调度技术,该技术使用一种奇特的 GAN 正则项来做一些超级独特的事情,这些事情只能为您提供特定的数据集。

由于 Flash 是 Lightning 的伴侣,您可以简单地将您的基线重写到 LightningModule 中,并做您想要的所有花哨的技巧。

请注意,您能够从基线实现到超级定制实现,而无需引入大量样板文件。从快速的高水*基线到超级漂亮的定制实现,您还可以保持完全的控制和定制。

奖金,部署!

另外,所有照明模块都可以通过火炬脚本onnx 轻松导出。您可以使用这些来部署高性能型号

摘要

本文向您展示了如何迭代地构建深度学习模型,以尽可能快地交付价值。使用 Lightning 框架系列,您能够:

  • 在几分钟内交付基线 v1
  • 再过几分钟迭代到基线 v2
  • 在几小时/几天内迭代到最终模型(定制实现)。

快速构建和发布/发布!

访问 Flash GitHub repo 了解更多快速基线的示例!

自动设置测试中每个问题的分数

原文:https://towardsdatascience.com/setting-the-points-per-question-of-a-test-automatically-120186278e90?source=collection_archive---------14-----------------------

如何使用线性规划来选择考试的评分标准,既择优又鼓励

斯科特·格雷厄姆Unsplash 上拍照

作为一名年轻的教师,我最*不得不进行我的第一次考试,所以我必须给我的第一份论文打分,但在打分之前,我必须确定每个问题的分数。

我发现自己在反复尝试多种评分标准,试图找到一种既能激励精英管理,又能让整体成绩优秀的标准。

但后来我注意到,评级尺度是一个加权和,因此找到一个评级尺度可以被视为一个优化问题;然后,我决定设计一种方法,通过使用线性编程和 ILOG 的解算器 CPLEX 来自动化这种缩放。

问题陈述

我要做的第一件事是在没有评分表的情况下批改试卷。为此,我创建了一个 CSV 文件,其中每个学生和每个问题都有一个介于 0 和 1 之间的浮点数,表示我判断它回答问题的程度。

之后,我用熊猫得到了每个问题和每个学生的分数,矩阵如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as pltdf = pd.read_csv("TME_Grades.csv")
N = df.values.T #I Transpose because initially i Had a table with     #the students in the rows and the exercices in the columns.

考虑我们有 n 个问题和 m 个学生,让 N(n,m) 矩阵,它给我们一个学生在一个问题中的“相对分数”。

问题可能是找到一组大小为 n 的权重 W ,使得 W.N 给出学生的分数

让我们从如何创建模型和变量开始。

from docplex.mp.model import Modelmodel = Model("Exam_Scoring")
exercices_vars = model.continuous_var_list(keys = np.arange(N.shape[0]), name= lambda k:"E_"+str(k))

函数“continuous_var_list”给出了一个键列表;在我们的例子中,它是 0 和问题数减 1 之间的数。

在我们创建了所需的变量之后,让我们考虑一下我们想要实现的约束,我们想要拥有的一些约束是直观的;权重集是一组实数,它们的总和是一个固定的数(比如说 20),每个权重必须是严格正的。

在定义其他约束和目标之前,我们需要在我们的问题中定义精英管理的概念,并看看我们如何实现它。

精英管理和安逸

如果我想在我的评分尺度上完全精英化,我会给每个问题一个与其难度成比例的权重。

由于任何两个问题之间的差异是回答每个问题的学生数量,我可以认为,如果回答正确的学生较少,一个问题会比另一个问题更复杂。

因此,精英分级标准会给每个问题一个与以下因素成比例的权重:

其中 nᵢ 是没有回答问题的学生人数

让我们试试这个评分表,看看我的学生的成绩,如果我完全任人唯贤的话。

not_ans = N.shape[1] - N.sum(axis=1)
m = 20*(not_ans /not_ans.sum())

这会给我们以下的成绩。

我们可以看到,他们非常粗略,没有人得到 20 分,*均值约为 4.50,这是意料之中的,因为该量表是为了奖励没有人回答的问题而计算的。

我们如何改变评分标准,在保持精英管理的同时提高分数的*均值?

为此,我们必须确保新的砝码组满足两个条件:

1-学生的排名不得改变。新等级必须大于或等于精英等级。

给定一组权重,学生的分数可以很容易地计算如下:

为了确保第一个条件得到尊重,我们将使用 argsort 函数根据学生在精英管理系统中的分数对他们进行排序,并规定排名不会改变,因为对于每个学生来说,其分数必须保持高于在前一顺序中低于他的学生的分数。

for i in range(len(sorted_students)-1):
    gap = min(grades[i]-grades[i+1], 0.001) 
    cst = sum(N[:, sorted_students[i]]*exercices_vars) >=                                   sum(N[:,sorted_students[i+1]]*exercices_vars) + gap
    model.add_constraint(cst)

由于我们不能使用线性规划中的严格比较,我们使用较大的一个变量来表示我们希望两个学生之间的差距,如果他们的成绩相同,差距将等于 0,在其他情况下,它将是一个微小的浮动(这里是 0.001)。

间隙变量起着另一个重要的作用;它规定了我们所要求的“精英管理的程度”;差距等于 0 意味着一个在精英评分表中领先于另一个学生的学生现在可以和他有相同的分数。

差距为-1 意味着我们部分解除了精英约束,我们允许分数比其他学生高的学生比他低,但不超过 1 分。

从另一个角度来说,设置一个至少和初始差距一样大的差距会给我们相同的排名。

以下约束确保了另一个条件:

for i,grade in enumerate(grades):
    if(grade==0):
        continue
    cst = (sum(N[:,i]*exercices_vars)) >= grade
    model.add_constraint(cst) 
model.add_constraint(sum(exercices_vars) == 20)
for var in exercices_vars:
    model.add_constraint(var >= 0)

现在我们知道了如何限制评分标准,使他对每个人都公*,让我们看看我们可以使用什么目标来强制执行特定的评分标准。

功利主义和*等主义

作为一名教师,第一个直观的目标是最大化整个班级的*均水*;这可以通过将新等级的总和设置为最大化目标来实现。

model.maximize(sum(exercices_vars@N)/ N.shape[1])

在我们的示例中,标记将发生如下变化:

我们可以看到排名没有变化。总分增加,*均分为 6.10 分。

这个目标被称为功利目标,但是正如我们所看到的,分数并没有以同样的比例增加。

相反,我们可以考虑最大化最小非零分数,以促进分数的*均增长;这是通过以下方式实现的:

model.maximize(model.min([i for i in (exercices_vars@N) if str(i) != "0"]))

给了我们:

成绩的提高在学生中分布更加均匀,*均值在 5.10 左右。

可以设想其他目标,可以最大化录取人数,或者假设我们想要某个*均值,从而最小化班级*均值和这个期望*均值之间的距离的绝对值。

结论

如果我使用一个手工的评分量表,而不是使用这个协议,那就需要我估计一下我给出的问题的难度。

由于我不能精确地知道每个学生的每个问题的难度,有人可以利用我的估计来回答具有最佳分数/难度比的问题,从而比其他没有战略性地回答的人排名更好。

当我还是学生的时候,我认为这个策略维度是考试的一部分,因为在大多数情况下,只有通过在考试前做大量的练习,才能估计一个问题是否比另一个问题需要更多的时间。

虽然评分标准经常给出,但后来又改变了,通常是为了避免太多人得到糟糕的分数;在这种情况下,对那些足以回答复杂问题的学生和那些有足够经验回避这些问题的学生来说,都是不公*的。

有了这个框架,我们可以确保即使在改变评分标准时也能保持最初的排名,从而在提高学生成绩的同时避免糟糕的成绩。

为成功建立数据科学组织

原文:https://towardsdatascience.com/setting-up-a-data-science-org-for-success-b0203728630a?source=collection_archive---------57-----------------------

办公时间

如何组建一个有效的数据科学小组!

介绍

这是一篇关于如何建立一个有效的数据科学小组的观点文章,基于我从事编程工作> 10 年,从事数据科学工作> 5 年,以及为各个部门和公司工作。在我的文章“数据科学家的 Web 框架,以及你为什么应该关注”中,我指出像 VentureBeat、Redapt 和其他公司报告说 ~90%的机器学习项目没有进入生产。换句话说,许多数据科学团体努力提供价值。这篇文章总结了(我发现的)让数据科学团队更有效的品质。在所审查的概念中,如果仅仅缺少一个元素,就会导致交付变慢(如果有的话)。

先简单模糊的说一下什么是数据科学,数据科学团队的职责是什么。

什么是数据科学?

以其最简单和最模糊的形式,数据科学是使用数学、统计学和计算机科学来分析和处理数据的实践。如果你正在读这篇文章,你可能已经知道了。如果您还不知道这一点,本文的其余部分可能会有所帮助(但我们将假设您在很大程度上知道什么是数据科学)。

这让我们想到了下一个(可能更有见地的)问题,数据科学团队是做什么的?

数据科学团队是做什么的?

这就是事情变得有趣的地方。一些公司可能会根据他们的组织结构或观点对此进行不同的处理。本文的重点是开发一个能提供最大价值的有效的数据科学团队。有了这个框架,我们来谈谈数据科学的一些组成部分。

在强化学习中,我们有这些探索和利用的想法。探索是我们尝试新事物,希望发现我们以前不知道的东西。利用是利用我们已经拥有的信息来获取未来利益的行为。(你可以将这些概念应用于任何群体,而不仅仅是数据科学)。

由作者创建

我们可以将数据科学团队的职责分成两个类似的领域。

  • 探索

数据科学探索的另一个常用术语是数据挖掘。在这种情况下,我们希望获取数据,并尝试发现未知。有一些公司在这个领域蓬勃发展,但却很难利用任何获得的知识(,我们稍后会谈到)。一些公司发现很难理解这个想法,因为这个过程可能非常模糊(,那是因为它有点像一种艺术形式)。数据挖掘需要经验,但更重要的是开放的心态。有经验的数据科学家知道,像时间文本这样的数据字段信息非常丰富,他们知道提取实体信息的方法。经验丰富的数据挖掘者擅长数据验证、数据可视化,并且知道如何发现有趣的模式。这在结构化的教科书中很难教授。事实是,你只需要做到这一点,并保持开放的态度。

如果您的数据科学团队不花任何时间进行数据挖掘,那么您可能会错过数据科学团队一半的潜在价值!

  • 剥削

数据科学中最常见的开发类型包括描述性统计和说明性建模。我们可以获取一些我们在业务中已经知道的信息,比如“一些客户群比其他客户群更有可能转化”,我们可以通过部署一些规定的模型来进一步利用这些信息。也许我们在公司的 CRM 工具中以优先销售线索列表的形式使用预测模型来优化销售。或者,也许我们知道“经理很难理解哪些销售代表在苦苦挣扎,为什么”,所以我们可以以仪表板的形式部署一些描述性统计数据。仪表板可以告诉经理他们的哪些销售代表在努力,他们在哪里努力。(我们还可以部署一些规范的建模来告知经理们他们陷入困境的一些潜在原因)。

如果您的数据科学团队没有部署任何数据产品,那么您可能会错过数据科学团队一半的潜在价值!

现在,我们已经了解了数据科学家的工作类型,让我们来谈谈可交付成果。数据科学团队生产什么样的产品,或者更重要的是数据科学团队应该生产什么样的产品

什么是数据科学产品?

  • 报道

这通常以 BI 工具的形式出现,如 Tableau、Power BI、Apache Superset、Plotly Dash、RShiny、Microsoft Excel,甚至 Microsoft Powerpoint。

如果是一次性的报告,那么你可以将你的发现合并成一个 Powerpoint 演示文稿,然后将它们展示给利益相关者。然后,您可以将幻灯片保存到一个位置,以便风险承担者以后可以参考。

如果它是一个重复出现的报告,那么你可以使用一个 dashboarding 工具,比如 Tableau 或者 Plotly Dash。

您应该生成一次性报告和重复性报告。同样,如果您的数据科学团队没有花任何时间进行数据挖掘和报告发现,那么您可能会错过数据科学团队潜在价值的很大一部分!

  • 新系统

根据您正在构建的系统,解决方案可能会完全不同。可能是比较 2 张图片的 REST API。或者可能是一个完整的 web 应用程序,它列出了需要审查潜在欺诈的客户。一般来说,您的解决方案应该是可靠的,并且具有适当的可伸缩性。如果您的应用程序需要与其他 IT 系统配合使用,那么您需要您的 IT 部门对您的解决方案感到满意。

此外,你的新系统可能是软件 2.0 或软件 1.0。(软件 2.0 是包含机器学习的软件解决方案,其中软件 1.0 不包含机器学习)。例如,您可以实现一个模型来帮助优化引入客户的路由。或者,这可能是一个更简单的解决方案,根据一天中的时间优化客户路线。

无论是哪种情况,以下是一些常见的系统\产品:

  1. REST API——也许您的公司有一个 web 产品,当客户正在使用 web 应用程序时,您希望应用程序调用您的 REST API 并向用户返回一个结果。一般来说,如果需要的话,您会想要可伸缩的东西。一些常见的商业解决方案包括 AWS Lambda、Azure Functions App 和 Algorithmia。一些开源解决方案包括 Kubernetes、Flask、plumber 等。预期的流量将决定 REST API 的可伸缩性。
  2. 模型批量评分—假设您有一个系统来确定欺诈审查客户的优先级。也许那个系统每天都在更新,你用 ML 模型对客户进行优先排序进行审核。在这种情况下,模型需要适合您的 ETL 管道。一些常见的云解决方案包括 Databricks、Azure ML Studio Pipelines 和 Azure Batch。一些开源解决方案包括 Apache Airflow 和 Luigi。
  3. Web 应用程序—除了实际的欺诈模型之外,您可能还托管欺诈应用程序。你可以使用 Heroku 或 Azure Web Apps 这样的系统来托管这个应用。您也可以使用 Linux 服务器在本地托管它。预期的流量将决定您的 web 应用程序的可伸缩性。

同样,如果您的数据科学团队没有部署任何产品,那么您可能会错过数据科学团队的大量潜在价值!

接下来,我们需要问自己,需要什么样的工具来实现这些最终产品?

数据科学团队需要什么工具?

首先,我们需要灵活。你不想限制你的数据科学家的能力,否则,他们有什么意义。

  • 数据科学开发

我写了一篇关于这个主题的更详细的文章,题为“2020 年值得关注的数据科学*台”。不管怎样,这里有一个快速总结:

  1. 你能做的最好的事情就是获得一个云环境。这将为您的团队提供分析数据和构建模型所需的工具和规模。这将是你的最佳选择。它应该比其他选项更强大,而且很可能更便宜。如果你已经在云中,这应该是一个扣篮。如果您是本地的,那么您可以使用混合基础设施在云和本地之间传递数据。
  2. 如果你是本地的,而混合动力是不可能的你可以拿起电话,试着打电话给数据科学*台(DSP) 供应商。一些供应商将在本地部署一些东西,或者他们可以将它部署在他们管理的云环境中(在这种情况下,您仍然需要弄清楚如何连接到您的数据)。DSP 的缺点是它们往往更贵。

不言而喻,您的团队也应该实践良好的代码版本控制、文档版本控制和数据版本控制。像 GitHub 这样的系统非常适合代码版本控制。Box 和 SharePoint 是很好的文档版本控制解决方案。存在用于数据版本控制的商业和开源解决方案。

一旦你有了一个开发环境,你的数据科学家可以分析数据和建立模型,我们还没有完成!为了给我们公司创造价值,我们还有很多要考虑的!

  • 汇报

一次性报告维护成本低。像 Excel 和 Powerpoint 这样的工具是轻而易举的。

另一方面,重复出现的报告更复杂。以下是一些需要考虑的概念:

  1. 自动化 —如果有人每周都手动运行相同的报告,那么你就错过了一个窍门。分析师应该把时间花在数据挖掘或构建模型上,而不是运行手动步骤。你可能会说“嗯,我们想发送一封电子邮件,其中包含对最新报告的评论”。这很好,您仍然可以这样做,但这应该需要一个小时,而不是您的数据科学家的 30%的时间。
  2. 复杂的 ETL 管道 —你应该能够运行复杂的 ETL 管道。您应该能够快速地将来自不同来源的数据联系起来,并将这些数据存储在一个能够支持仪表板的表中。如果你还没有在你的仪表板基础设施中启用这个,忘记它,放弃吧,因为你已经错过了你仪表板价值的一大块
  3. 数据库存储 —仪表板数据处理应推送到数据库。这将使您的仪表板运行更快,并提供实时体验。缓慢的仪表板对任何人都没有用。用户应该能够与您的仪表板快速交互,这意味着要有一个合适的数据库来支持您的仪表板。
  4. 不受限制的数据可视化 —你应该只受限于你的想象力,而不是你的工具。这使得基于代码的仪表板工具,如 Plotly Dash 和 RShiny 非常受欢迎。
  5. 版本控制 —如果您的仪表板发生变化,您应该能够跟踪您的变化。这使得基于代码的仪表板工具,如 Plotly Dash 和 RShiny 非常受欢迎。

对于一个数据库,采取你的选择。对于 ETL 和自动化,有开源的选择,比如 Apache AirflowApache SparkLuigi 等。,并且有大量的商业产品。如果你在云中,你可以使用云服务,比如 Azure Data Factory 和 AWS Batch。如果您在本地,您可以使用单个服务器启动,然后您可以根据需要纵向扩展。最终,你可能需要一个通用的集群,你可以自己构建,也可以打电话给像 Cloudera 这样的公司。

  • ML & App 操作化

这与重复出现的报告非常相似,只是略有不同。

  1. 数据库 —您需要能够存储数据以支持报告和任何其他应用程序。它还有助于模型开发和建立建模、分析和部署所需的数据管道。
  2. ETL —您需要一个健壮的 ETL 工具,它可以编排复杂的数据管道,为您的应用程序提供动力,并为潜在的分析准备数据。
  3. 模型 ETL 集成 —您选择的 ETL 工具应该能够集成(并运行)模型评分管道。
  4. REST API 托管 —您需要能够托管模型和应用程序作为任何实时用例的 REST API。
  5. web 应用托管 —你的团队可能不会托管任何 Web 应用,但你应该对托管 Web 工具的可能性持开放态度。
  6. 版本控制和 DevOps —这是标准的实践,应该是显而易见的。
  7. 模型监控 —您应该监控您发布的模型的数据漂移、一般问题以及您的模型需要刷新的迹象。

很明显,数据科学团队需要大量工具,这就引出了一个问题,要实现这些最终产品,需要什么样的团队?

数据科学团队是什么样的?

数据科学组应该是 3 个子组的结合。

由作者创建

  • 数据科学

如果没有数据科学家,一个数据科学小组会是什么样子!但是这并不是全部的要求;否则,这将是一个非常短的部分。

  • 数据工程

你的数据科学小组应该有自己的数据工程师。你可能会说“我的 IT 组织已经有数据工程师来填充我们的数据集市”——我相信这是真的,但是你的团队中仍然需要数据工程师。这些人负责真正理解数据集市,并为建模和分析恰当地收集数据。如果您的团队中没有指定的数据工程师,您的团队中可能有人充当数据工程师。这些人对数据库了如指掌。每当有人需要数据集市的帮助时,这些人就像数据大师一样被对待,并被问题淹没。在某些情况下,也许团队中的每个人都是数据仓库专家,在这种情况下,您是身兼数职的分析师。短期来看,人们身兼数职并不是一件坏事,但从长期来看,这会导致重要的事情缺乏适当的关注。你的团队应该有指定的数据工程师。此外,他们应该能够访问他们自己的团队数据库,在那里他们可以存储用于分析、模型、应用程序和报告的数据。因此,您的数据工程师不仅专注于开发,他们还专注于生产应用程序!

  • DevOps &应用开发者

这些人负责单元测试,考虑 CI/CD,确保你运行的任何东西都是可靠的。他们还负责与其他 IT 团队合作,并管理任何投入生产的解决方案。如果您的解决方案有问题,谁将随叫随到来修复它?你的数据科学家?你在这方面的第一道防线应该是你的应用开发者。

  • MLOps

MLOps 实际上是所有 3 个子组共享的一个区域。MLOps 本质上是 DevOps,但侧重于 ML。所以你可以说 MLOps 属于 DevOps,但是由于 ML 给 DevOps 增加了新的复杂性,MLOps 变成了一个共享的规程。数据科学应该拥有一些单元测试,他们还应该拥有模型监控。来自数据科学家和数据工程师的所有生产代码都应该在 DevOps 下测试,但这仍然需要共同努力。一些团队雇用“机器学习工程师”,他们是数据科学家,更专注于团队内的 MLOps 工作。

机器学习系统中隐藏的技术债务

上图来自一份著名的谷歌白皮书,名为“机器学习系统中隐藏的技术债务”。该图传达了数据科学不仅仅是构建模型。黑色的小方块代表 ML 代码,其余的是从 ML 代码中获益所需的基础设施。支持数据科学需要资源、多元化的团队和企业的承诺。

在谷歌的另一篇题为“机器学习:技术债务的高息信用卡的论文中,他们指出:

学术界可能会感到惊讶的是,在许多机器学习系统中,只有极小一部分代码实际上在进行“机器学习”。当我们认识到一个成熟的系统可能最终(最多)是 5%的机器学习代码和(至少)95%的粘合代码时,重新实现而不是重用一个笨拙的 API 看起来是一个更好的策略。

我认为主要的一点是,ML 代码相对于整个系统来说,一般只是代码的一小部分。我认为这是一个惊人的观察。你应该让这个想法真正深入你的大脑。考虑到这一点,开始变得清晰的是,你需要的不仅仅是数据科学家来做数据科学。

这将我们带到下一个要点——我们已经讨论了很多关于数据科学团队、工具和产品的内容;但是,公司文化呢?实现这些最终产品需要什么样的公司文化?毫无疑问,公司文化在数据科学团队的成功中扮演着重要角色。

数据科学团队要取得成功,需要哪些社会\业务要求?

  • 与整个组织协作,特别是 MLOps\DevOps 团队需要与 IT 部门保持紧密联系。

你需要组织中其他人的合作。高层有责任认识到数据科学是公司的工作,并要求整个公司在需要时与数据科学团队合作。此外,MLOps\DevOps 团队需要与 IT 部门保持紧密联系。这将帮助您更快地将产品推向市场,因为您已经建立了关系!

  • 敏捷软件开发和项目跟踪

你的团队应该使用像吉拉这样的产品来跟踪你正在做的项目和工作。ML 产品有很多复杂性,因此敏捷框架对于 ML 项目变得越来越重要。

  • 具有适当团队 KPI 和期望的创新文化

这是什么意思?这意味着公司需要投资尝试在内部做事情偶尔拿起电话给供应商打电话是没问题的,但公司需要投入内部数据科学。公司用什么样的工具?公司总是努力走在前沿吗?一些公司渴望尝试新事物,而另一些公司则喜欢稳扎稳打。

一个数据科学组织将在一个创新的公司中茁壮成长,而在一个过于谨慎的公司中则会饿死。

公司需要对失败持开放态度。

失败应该是意料之中的,从中吸取教训,并用来改进。这就引出了我们的下一点——KPI 和期望值。

这一点非常重要,它将我带回到探索与开发的问题上。如果你没有任何信息可以利用,你需要愿意探索。在这种情况下,你的团队应该看看你每年完成/开始多少实验(或项目)。一旦你真正交付了产品,你就可以开始收集信息并利用你的知识。在这一点上,你可以过渡到衡量你已经完成了多少成功的产品(,即有多少仍在使用并交付价值)。换句话说,在利用任何知识之前,你需要投资探索。

一些团队试图在第一天就衡量投资回报率。只要你有合适的镜头,这是没问题的。如果每个人都明白你正处于探索阶段,那就没关系。如果没有这个镜头,每个人都期待你利用你还没有收集的信息,这是一个灾难的配方。

正如你所看到的,在实践中,你的模型的实际实现需要的不仅仅是训练一个模型!您将经常需要运行实验来收集更多的数据,并考虑如何将您的模型整合到您正在开发的整个系统中。— Fast.ai / FastBook

你需要尝试和学习,然后你可以微调。为了获得全面的成功,你必须接受一些失败。试图一开始就把每件事都做对是不可能的,从长远来看,你是在为自己的失败做准备。(这是许多公司使用敏捷软件开发而不是瀑布的众多原因之一)。

当你的下一个季度评估摆在你面前时,很难这样想,但你需要让人们接受一些失败,这样你才能从长远来看获得一些真正的奖励。你需要强调你学到了什么,以及你下一步要做什么。如果一次失败意味着公司的每个团队和领导都将对你的团队失去信心,那么你在开始之前就已经失败了。你需要在交付任何东西之前纠正这种想法。

(另外,请注意,只关注下一个即时奖励与贪婪算法非常相似。一个贪婪的算法寻找下一个最高的收益,不把游戏作为一个整体来考虑。正如许多数据科学家会告诉你的,下一个最高的增益很少会优化游戏的整体。)

  • 数据道德意识

最后但同样重要的是,小组建立某种数据伦理框架(或指导方针)是很重要的。其中很大一部分属于 MLOps 和针对特定基础的测试,但思考数据伦理也是整个团队(和整个公司)的责任。 Fast Book 来自 Fast.ai 有一个很好的问题列表,你可以在每次 sprint 回顾时问你的团队。在速成书第三章:伦理“分析你正在做的一个项目”一节下找。前两个问题是最好的——“我们应该这么做吗?”以及“数据中有什么偏见?”。如果你问自己,这与成功的数据科学团队有什么关系?答案是——它会让你免于制造一个让客户不快、让你的公司(和你自己)陷入丑闻的怪物。此外,不言而喻,我们都有责任创造改善社会的产品,而不是扰乱和损害社会。这将转化为积极的客户体验和代表质量的品牌。

摘要

那么一个有效的数据科学小组需要什么呢?

必备工具:

  • 团队数据库。
  • 具有自动化、调度和调用模型评分管道能力的 ETL 工具。
  • 用于 REST APIs 和批量评分的模型部署工具(即与您的 ETL 工具集成)。
  • 灵活的报告工具。
  • 代码、文档和数据的版本控制。
  • 项目管理的敏捷软件。
  • 灵活的数据科学开发环境。

关键团队成员:

  • 数据科学
  • 数据工程
  • 开发运维及应用开发

基本组织需求:

  • 与组织的其他部门保持良好的关系,尤其是在您的 DevOps 团队和您的各种其他 IT 团队之间。
  • 敏捷的工作环境。
  • 具有适当 KPI 和期望的创新文化。
  • 数据伦理意识。

结束了

就是这样!非常感谢你的阅读,希望你发现这很有见地!

巨大的行业资源

这里有一些很棒的资源和视频。Spark + AI Summit 和 TWIML AI Podcast 是观看来自脸书、LinkedIn、Comcast、Capital One 等大公司的真实 MLOps 和真实 ML 实践的惊人资源。

再次感谢阅读!

使用 Python 设置 GCP 发布/订阅集成

原文:https://towardsdatascience.com/setting-up-a-gcp-pub-sub-integration-with-python-6bf3fab111f8?source=collection_archive---------38-----------------------

使用谷歌云*台解锁 Python 应用程序数据流的指南

戴维·克洛德在 Unsplash 上的照片

Python 是当今各种数据处理的流行语言。用例范围从 web 应用和机器学习应用一直到像 RaspberryPi 这样的设备上的硬件控制。当涉及到这些事件系统和实时数据处理时,利用发布/订阅*台可以为您的解决方案增加模块化和可扩展性— 您可以在此处了解更多信息

在这里阅读我为什么在我的爱好项目中使用谷歌云*台工具

目标

在本文中,我将介绍如何设置一个 Python 应用程序来发布和使用来自 Google 的 Pub/Sub 的数据。

所需时间: 15 分钟。

先决条件

要跟进,您应该具备以下条件:

  1. 对 Python 工作原理的基本理解
  2. 你机器上安装的 Python 3.x】
  3. 一个谷歌云*台账户和一个项目

来做点编码吧!

GCP-服务帐户设置

首先,让我们在 GCP 完成所有的配置。从 Python 应用程序访问发布/订阅服务需要 GCP 服务帐户和私钥。

您的服务帐户的完整列表可在此处访问,并可使用此链接添加新的服务帐户。给你的账户一个名字和 id——两者可以相同,但是 id 必须是唯一的——我把我的命名为python-tester

作者图表

点击创建并添加Pub/Sub PublisherPub/Sub Subscriber角色,以确保该帐户可以从您的发布/订阅主题消费数据和向其发布数据。

作者图表

从这里你可以点击完成

接下来,我们需要生成一个私钥,Python 应用程序将在与 GCP 通信时使用这个私钥。找到您刚刚创建的服务帐户,并选择管理密钥选项。

作者图表

使用添加密钥按钮添加新的 JSON 密钥。

作者图表

点击创建会将私钥文件下载到您的默认下载目录。如果您打开该文件,您应该会看到类似这样的内容:

{
 *“type”*: “service_account”,
 *“project_id”*: “…”,
 *“private_key_id”*: “…”,
 *“private_key”*: “ — — -BEGIN PRIVATE KEY — — -…”,
 *“client_email”*: “python-tester@…”,
 *“client_id”*: “…”,
 *“auth_uri”*: “https://accounts.google.com/o/oauth2/auth",
 *“token_uri”*: “https://oauth2.googleapis.com/token",
 *“auth_provider_x509_cert_url”*: “…”,
 *“client_x509_cert_url”*: “…”
}

确保跟踪这个文件,因为我们的 Python 应用程序将需要它。

GCP —发布/订阅主题设置

在我们可以从发布/订阅推送/拉取数据之前,我们需要创建一个主题。你可以在这里看到你所有的活跃话题。创建一个新主题,给它一个名称,并选中默认订阅选项——我将我的主题命名为my-python-topic

作者图表

确保选中添加默认订阅选项,然后单击创建主题 —您应该会看到新主题出现在您的主题列表中。你的默认订阅将有一个带有-sub后缀的主题名称,在我的例子中,它被命名为my-python-topic-sub

python——编写生产者和消费者

在编写代码之前,你必须安装Python 3 . x以及google-api-python-clientgoogle-cloud-pubsub GCP 库。您可以使用以下命令在 pip/pip3 中安装它们:

pip3 install --upgrade google-api-python-client
pip3 install --upgrade google-cloud-pubsub

在机器上的某个地方为 Python 代码创建一个文件夹。

mkdir pub-sub-test
cd pub-sub-test

将您在 GCP —服务账户设置部分生成的私钥移到这个新文件夹中。如果您丢失了您的密钥,您可以使用相同的说明生成一个新的。

在这个目录中创建您的主要可执行 Python 文件——我调用我的code.py,并添加以下内容:

GCP 库期望一个名为GOOGLE_APPLICATION_CREDENTIALS的环境变量指向私钥。我们在第 2 行上设置该值:

os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="YYYY.json"

确保将YYYY.json替换为您的私钥文件的路径/名称。

上的 PUB_SUB_PROJECT 应该更新为您的 GCP 项目的 id,您可以在 Pub/Sub 列表页面上找到该 id。它将是项目主题之间的值— 项目/YYY/主题/my-python-topic。

作者图表

您的项目现在应该如下所示:

├── pub-sub-test
│ ├── code.py
│ ├── YYYY.json

我尽了最大努力让代码尽可能不言自明,但本质上:

process_payload: 一个回调函数,处理从发布/订阅消费的事件,任何你想应用到有效负载的逻辑都应该在这里添加。

push_payload: 获取一个有效负载(JSON)并将其推送到提供的发布/子主题/项目 id 组合。

consume_payload: 检查所提供的订阅/项目组合中的新事件,如果数据存在,将调用回调函数进行处理。超时周期作为一个中断。

剩下的代码继续推送和消耗数据,直到程序终止。您可以用python3 code.py运行代码,应该会在终端中看到类似这样的内容:

作者图表

现在你有了它,一个基本的实现,但是这应该足够让你开始使用 Python 来利用 GCP 的 Pub/Sub。

结论

Google 的 Pub/Sub *台非常适合处理大量的数据和分离你的架构的各个组件。在本文中,我向您介绍了如何在 Python 应用程序中利用 Pub/Sub。我希望你能从这篇文章中学到一些东西。

祝好运,编码快乐!

原载于 2021 年 4 月 25 日 http://www.theappliedarchitect.comhttp://www.theappliedarchitect.com/setting-up-gcp-pub-sub-integration-with-python/

建立文本摘要项目

原文:https://towardsdatascience.com/setting-up-a-text-summarisation-project-daae41a1aaa3?source=collection_archive---------8-----------------------

拥抱变形金刚深入文本摘要的实用指南

图片由 Ralf Roletschek 拍摄;根据知识共享署名 3.0 获得许可

自然语言生成新时代的到来

OpenAI 在 2020 年 7 月发布了专门研究文本生成的第三代机器学习(ML)模型时,我知道有些事情不同了。这个模型触动了前人没有触及的神经。突然,我听到朋友和同事谈论它,他们可能对技术感兴趣,但通常不太关心 AI/ML 领域的最新进展。甚至《卫报》也就此写了一篇文章。或者准确的说是模特写的文章,卫报编辑出版。不可否认,GPT 3 号改变了游戏规则。

一旦模型发布,人们立即开始为它想出潜在的应用。几周之内,大量令人印象深刻的演示被制作出来,这些演示可以在令人敬畏的 GPT-3 网站上找到。一个引起我注意的特殊应用是 文本摘要 ,即计算机阅读给定文本并总结其内容的能力。它结合了自然语言处理(NLP)领域中的两个领域,阅读理解和文本生成,并且是计算机最困难的任务之一。这就是为什么我对 GPT-3 文本摘要演示印象如此深刻。

你可以在 拥抱脸空间网站上试试。我目前最喜欢的是一个应用程序,它只需要输入文章的 URL 就可以生成新闻文章的摘要。

这个教程是关于什么的?

我工作的许多组织(慈善机构、公司、非政府组织)有大量的文本需要阅读和总结——财务报告或新闻文章、科研论文、专利申请、法律合同等。自然,这些组织对使用 NLP 技术自动完成这些任务感兴趣。因此,为了展示可能性的艺术,我经常使用文本总结演示,它们几乎总能给人留下深刻印象。

但是现在呢?

这些组织面临的挑战是,他们想要评估基于许多许多文档摘要的文本摘要模型——而不是一次一个。他们不想雇佣一个实习生,他唯一的工作就是打开应用程序,粘贴一个文档,点击“总结”按钮,等待输出,评估总结是否好,然后对数千个文档重新做一遍。

这就把我们带到了这个博客系列的目标:在这个教程中,我为组织提出了一个实用的指南,这样他们就可以评估他们领域的文本摘要模型的质量。

这个教程是(不是)给谁看的?

我是带着四周前的过去的自己写下这篇教程的,也就是说,当我开始这段旅程的时候,我希望我有这篇教程。从这个意义上说,本教程的目标读者是熟悉 AI/ML 并且以前使用过 Transformer 模型的人,但是他们才刚刚开始他们的文本总结之旅,并且想要更深入地了解它。因为它是由“初学者”为初学者写的,所以我想强调的是,本教程是实用指南,而不是实用指南。请像乔治·博克斯所说的那样对待它:**

作者图片

就本教程需要多少技术知识而言:它确实涉及一些 Python 中的编码,但大多数时候我们只是使用代码来调用 API,所以也不需要深入的编码知识。熟悉机器学习的某些概念将是有用的,例如,训练部署一个模型意味着什么,训练、验证和测试数据集的概念,等等。之前接触过变形金刚库可能会有用,因为我们将在本教程中广泛使用这个库。尽管如此,如果我没有忘记的话,我会试着为这些概念的进一步阅读加入有用的链接;)

因为这个教程是一个初学者写的,所以我不指望 NLP 专家和高级深度学习从业者能从这个教程中得到多少。至少从技术角度来看不是这样——不过,你可能仍然喜欢阅读,所以请不要离开!但是你必须对我的简化保持耐心——我试图让本教程中的所有内容尽可能简单,而不是更简单。

本教程的结构

这个系列将分为五个部分,我们将经历一个文本摘要项目的不同阶段。在第一部分中,我们将首先介绍文本摘要任务的度量标准,即允许我们评估摘要是“好”还是“坏”的性能衡量标准。我们还将介绍我们想要总结的数据集,并使用非 ML“模型”创建基线,即我们将使用简单的启发式方法从给定文本中生成摘要。创建这个基线在任何人工智能项目中都是至关重要的一步,因为它将使我们能够量化我们通过使用人工智能取得的进展,也就是说,它允许我们回答这样一个问题:“投资人工智能技术真的值得吗?”

在下一部分(第 2 部分)中,我们将使用一个已经预先训练好的模型来生成摘要。这是一种现代的称为迁移学习的方法。你可以在这篇文章中读到更多。这是另一个有用的步骤,因为我们基本上采用现成的模型,并在我们的数据集上进行测试。这允许我们创建另一个基线,这将有助于了解当我们在数据集上实际训练模型时会发生什么。这种方法被称为零镜头总结,因为该模型对我们的数据集没有任何影响。

之后,是时候使用一个预先训练好的模型,并在我们自己的数据集上训练它了(第 3 部分)。这也叫微调。它将使模型能够从我们数据的模式和特质中学习,并慢慢适应它。一旦我们训练了模型,我们将使用它来创建摘要(第 4 部分)。

所以,总结一下(看我做了什么?):

  • 第 1 部分:使用非 ML“模型”建立基线
  • 第 2 部分:使用零镜头模型生成摘要
  • 第 3 部分:训练总结模型
  • 第 4 部分:评估训练好的模型

本教程结束时,我们将取得什么成果?

恐怕现在是残酷的现实检验的时候了:在本教程结束时,我们将而不是有一个可以在生产中使用的文本总结模型。我们甚至不会有一个好的总结模型(此处插入尖叫表情符号)!

相反,我们将有一个项目下一阶段的起点,这是实验阶段。这就是数据科学中的科学的用武之地,因为现在一切都是关于用不同的模型和不同的设置进行实验,以了解是否可以用可用的训练数据训练出足够好的汇总模型。

而且,完全透明地说,很有可能得出的结论是技术还不成熟,项目不会被实现。你必须让你的商业利益相关者为这种可能性做好准备。但那是另一篇博文的内容;)

第 1 部分—创建基线

这是建立文本摘要项目教程的第一部分。关于本教程的更多背景和概述,请参考简介

在这一部分中,我们将使用一个非常简单的“模型”建立一个基线,而不实际使用机器学习(ML)。在任何 ML 项目中,这都是非常重要的一步,因为它让我们了解 ML 在项目期间增加了多少价值,以及是否值得投资。

教程的代码可以在这个 Github repo 中找到。

数据,数据,数据…

每一个 ML 项目都是从数据开始的!如果可能的话,我们应该总是使用与我们想要通过文本摘要项目实现的目标相关的数据。例如,如果我们的目标是总结专利申请,我们也应该使用专利申请来训练模型。对于一个 ML 项目,一个很大的警告是训练数据通常需要用标记。在文本摘要的上下文中,这意味着我们需要提供要摘要的文本以及摘要(“标签”)。只有提供这两者,模型才能知道“好的”摘要是什么样的。

在本教程中,我们将使用公开可用的数据集,但如果我们使用自定义/私有数据集,步骤和代码完全相同。同样,如果你对你的文本摘要模型有一个目标,并且有相应的数据,请使用你的数据来充分利用它。

我们将使用的数据是包含 arXiv 论文摘要及其标题的 arXiv 数据集。出于我们的目的,我们将使用摘要作为我们想要总结的文本,使用标题作为参考摘要。下载和数据预处理的所有步骤都可以在这个笔记本中找到。该数据集是作为这篇论文的一部分开发的,并根据知识共享 CC0 1.0 通用公共领域专用协议获得许可。

请注意,数据分为三个数据集,即训练、验证和测试数据。如果您想使用自己的数据,请确保情况也是如此。简单提醒一下,这是我们使用不同数据集的方式:

作者图片

自然,此时一个常见的问题是:我们需要多少数据?你可能已经猜到了,答案是:视情况而定。这取决于该领域的专业化程度(总结专利申请与总结新闻文章有很大不同)、该模型需要有多精确才能有用、该模型的训练成本应该是多少等等。我们将在稍后实际训练模型时回到这个问题,但不足的是,一旦我们处于项目的实验阶段,我们将不得不尝试不同的数据集大小。

什么是好的模型?

在许多 ML 项目中,度量一个模型的性能是相当简单的。这是因为模型的结果是否正确通常没有什么模糊性。数据集中的标签通常是二元的(真/假,是/否)或分类的。无论如何,在这种情况下,很容易将模型的输出与标签进行比较,并将其标记为正确或不正确。

当生成文本时,这变得更具挑战性。我们在数据集中提供的摘要(标签)只是总结文本的一种方式。但是总结一篇给定的文章有很多可能性。因此,即使模型与我们的标签 1:1 不匹配,输出可能仍然是有效和有用的摘要。那么,我们如何比较模型的总结和我们提供的总结呢?文本摘要中最常用来衡量模型质量的指标是 ROUGE score 。为了理解这个指标的机制,我推荐这篇博文。总之,胭脂分数测量模型摘要(候选摘要)和参考摘要(我们在数据集中提供的标签)之间的 n-grams (连续的 n 项序列)的重叠。但是,当然,这不是一个完美的措施,并了解其局限性,我很喜欢这篇文章

那么,我们如何计算胭脂分数呢?有相当多的 Python 包来计算这个指标,为了确保一致性,我们应该在整个项目中使用相同的方法。因为在本教程的稍后部分,我们将非常 l̶a̶z̶y̶聪明地使用变形金刚库中的训练脚本,而不是编写我们自己的脚本,所以我们可以只查看脚本的源代码并复制计算胭脂分数的代码:

通过使用这种方法来计算分数,我们可以确保在整个项目中始终进行比较。

注意,这个函数将计算几个 ROUGE 分数: rouge1rouge2rougeLrougeL sum(rougeL sum中的“总和”是指这个度量是在整个摘要上计算的,而 rougeL 是作为单个句子的*均值计算的)。那么,我们应该为我们的项目使用哪个 ROUGE 分数呢?同样,我们将不得不在试验阶段尝试不同的方法。值得一提的是,原始 ROUGE 论文称“ROUGE-2 和 ROUGE-L 在单个文档摘要任务中表现良好”,而“ROUGE-1 和 ROUGE-L 在评估简短摘要方面表现出色”。

创建基线

接下来,我们想通过使用一个简单的非 ML 模型来创建基线。那是什么意思?嗯,在文本摘要领域,许多研究使用一种非常简单的方法:他们提取文本的前 n 个句子,并将其声明为候选摘要。然后,他们将候选摘要与参考摘要进行比较,并计算 ROUGE 分数。这是一个简单而强大的方法,我们可以用几行代码实现(这部分的完整代码可以在这个笔记本中找到):

请注意,我们使用测试数据集进行评估。这是有意义的,因为一旦我们训练模型,我们也将使用相同的测试数据集进行最终评估。我们也为 n 尝试不同的数字,即我们只从第一句开始作为候选摘要,然后是前两句,最后是前三句。

这些是我们第一个“模型”的结果:

作者图片

我们可以看到,只有第一句话作为候选摘要,得分最高。这意味着使用一个以上的句子会使总结变得冗长,从而导致较低的分数。这意味着我们将使用一句话总结的分数作为基线。

值得注意的是,对于这样一个简单的方法,这些数字实际上相当不错,特别是对于 rouge1 分数。为了将这些数字放在上下文中,我们可以查看第,它显示了不同数据集的最先进模型的分数。

结论和下一步

我们已经介绍了将在整个总结项目中使用的数据集以及评估总结的指标。然后,我们用一个简单的非 ML 模型创建了以下基线:

作者图片

在下一部分中,我们将使用零镜头模型,即经过专门训练用于公共新闻文章文本摘要的模型。然而,这个模型根本不会在我们的数据集上训练(因此得名“零炮”)。

我会把它作为家庭作业留给你们,让你们猜猜这个零射击模型与我们非常简单的基线相比会有什么表现。一方面,它将是一个更加复杂的模型(实际上是一个神经网络),另一方面,它仅用于概括新闻文章,因此它可能会与 arXiv 数据集固有的模式相冲突。

第 2 部分—零起点学习

这是建立文本摘要项目教程的第二部分。关于本教程的更多内容和概述,请参考简介以及第 1 部分,在其中我们为我们的项目创建了一个基线。

在这篇博客文章中,我们将利用零距离学习 (ZSL)的概念,这意味着我们将使用一个经过训练的模型来总结文本,但尚未看到任何 arXiv 数据集的示例。这有点像当你这辈子一直在做的都是风景画的时候,试图去画一幅肖像。你知道如何绘画,但你可能不太熟悉肖像绘画的复杂性。

整个教程的代码可以在这个 Github repo 中找到。对于今天的部分,我们将特别使用这个笔记本

为什么零起点学习(ZSL)?

ZSL 在过去几年中变得流行起来,因为它允许在没有培训的情况下利用最先进的 NLP 模型。他们的表现有时相当惊人:大型科学研究工作组最*发布了他们的 T0pp(发音为“T Zero 组合+”)模型,该模型经过专门训练,用于研究零射击多任务学习。在大工作台基准测试中,它的表现经常超过 6 倍大的型号,在其他几个 NLP 基准测试中,它的表现也超过 16 倍大的 GPT-3

ZSL 的另一个好处是使用它只需要两行代码。通过尝试,我们可以创建第二个基线,一旦我们在数据集上对模型进行了微调,就可以用它来量化模型性能的提高。

建立零起点学习管道

为了利用 ZSL 模型,我们可以使用拥抱脸的 管道 API 。这个 API 使我们能够使用只有两行代码的文本摘要模型,同时它负责 NLP 模型中的主要处理步骤:

  1. 文本被预处理成模型可以理解的格式。
  2. 预处理后的输入被传递给模型。
  3. 模型的预测是后处理的,所以你可以理解它们。

它利用了已经在拥抱脸模型中心上可用的总结模型。

所以,下面是如何使用它:

就是这样,信不信由你。这段代码将下载一个汇总模型,并在您的机器上本地创建汇总。如果您想知道它使用的是哪种模型,您可以在源代码中查找或者使用以下命令:

当我们运行这个命令时,我们看到用于文本摘要的 defaukt 模型被称为sshleifer/distilbart-CNN-12-6:

作者图片

我们可以在拥抱脸网站上找到该模型的模型卡,在那里我们还可以看到该模型已经在两个数据集上进行了训练:CNN 每日邮件数据集和极端摘要(XSum)数据集。值得注意的是,该模型不熟悉 arXiv 数据集,仅用于总结与其训练过的文本相似的文本(主要是新闻文章)。型号名称中的数字 12 和 6 分别指编码器层数和解码器层数。解释这些是什么超出了本教程的范围,但是你可以在 Sam Shleifer 的博客文章中读到更多关于它的内容,他创建了这个模型。

我们将继续使用默认模型,但我鼓励您尝试不同的预培训模型。所有适合总结的模型都可以在这里找到。要使用不同的模型,您可以在调用管道 API 时指定模型名称:

侧边栏:提取与抽象总结

我们还没有谈到两种可能但不同的文本摘要方法:提取抽象。摘要概括是将从文本中提取的内容连接成一个摘要的策略,而抽象概括包括用新句子解释语料库。大多数摘要模型都是基于生成小说文本的模型(它们是自然语言生成模型,例如,【GPT-3】)。这意味着总结模型也会产生新的文本,这使得它们成为抽象的总结模型。

生成零镜头摘要

现在我们知道了如何使用它,我们想在我们的测试数据集上使用它,与我们在第 1 部分中用来创建基线的数据集完全相同。我们可以用这个循环来实现:

注意,我们有最小长度最大长度参数来控制模型生成的摘要。在本例中,我们将 min_length 设置为 5,因为我们希望标题至少有 5 个单词长。通过查看参考摘要(即研究论文的实际标题),看起来 20 可能是 max_length 的合理值。但同样,这只是第一次尝试,一旦项目进入实验阶段,这两个参数可以而且应该改变,以查看模型性能是否发生变化。

侧边栏:波束搜索、采样等。

如果您已经熟悉文本生成,您可能知道还有许多参数会影响模型生成的文本,如光束搜索、采样和温度。这些参数使您能够更好地控制正在生成的文本,例如,使文本更加流畅,减少重复等。这些技术在管道 API 中是不可用的——你可以在源代码中看到最小长度最大长度是唯一会被考虑的参数。然而,一旦我们训练并部署了我们自己的模型,我们就可以访问那些参数了。在本系列的第 4 部分中会有更多的介绍。

模型评估

一旦我们生成了零镜头摘要,我们可以再次使用我们的 ROUGE 函数来比较候选摘要和参考摘要:

对使用 ZSL 模型生成的摘要运行此计算,我们得到以下结果:

作者图片

当我们将这些与第一部分的基线进行比较时,我们看到这个 ZSL 模型实际上比我们简单的只取第一句话的试探法表现得更差。同样,这并不出人意料:尽管这个模型知道如何总结新闻文章,但它从未见过总结学术研究论文摘要的例子。

结论

我们现在已经创建了两条基线,一条使用简单的启发式方法,另一条使用 ZSL 模型。通过比较 ROUGE 分数,我们看到简单启发式算法目前优于深度学习模型:

作者图片

在下一部分中,我们将采用这种完全相同的深度学习模型,并尝试提高其性能。我们将通过在 arXiv 数据集上训练它来做到这一点(这一步也被称为微调):我们利用了它已经知道如何概括文本的事实。然后,我们向它展示了大量 arXiv 数据集的示例。深度学习模型一旦接受训练,就非常擅长识别数据集中的模式,因此我们确实希望该模型在这项特定任务中变得更好。

第 3 部分—培训总结模型

在这一部分中,我们将在我们的数据集上训练我们在第二部分中用于零镜头摘要的模型(ssleifer/distilbart-CNN-12-6)。这个想法是通过展示许多例子来教导模型研究论文摘要的摘要是什么样子的。随着时间的推移,该模型应该能够识别该数据集中的模式,这将允许它创建更好的摘要。

值得再次注意的是,如果您已经标记了数据,即文本和相应的摘要,您应该使用它们来训练模型。只有这样做,模型才能学习您的特定数据集的模式。

SageMaker 培训工作

因为在我的笔记本电脑上训练一个深度学习模型需要几周时间,所以我们将利用 SageMaker 的培训工作来代替。你可以在这个文档中了解所有关于培训工作的信息,但是我想简要强调一下使用这些培训工作的优势,除了它们允许我们使用 GPU 计算实例这一事实之外。

因此,让我们假设我们有一个可以使用的 GPU 实例集群。在这种情况下,我们可能希望创建一个 Docker 映像来运行培训,这样我们就可以轻松地在其他机器上复制培训环境。然后,我们将安装所需的软件包,因为我们希望使用几个实例,所以我们还需要设置分布式培训。一旦训练结束,我们希望迅速关闭这些电脑,因为它们很昂贵。

当使用培训工作时,所有这些步骤都是抽象的。事实上,我们可以通过指定训练参数,然后只调用一个方法,以与上述相同的方式训练模型。SageMaker 将负责剩下的工作,包括在培训完成后终止 GPU 实例,以便不会产生任何进一步的成本。

此外,拥抱脸和 AWS 今年早些时候宣布了一项合作伙伴关系,这使得在 SageMaker 上训练拥抱脸模特变得更加容易。我们可以在这个 Github repo 中找到很多这样做的例子。

设置培训工作

事实上,我们将使用其中一个示例作为模板,因为它几乎完成了我们的目的所需的一切:以分布式方式(即使用多个 GPU 实例)在特定数据集上训练汇总模型

然而,我们必须考虑的一件事是,这个例子使用了直接来自 HF dataset hub 的数据集。因为我们想提供我们自己的自定义数据,我们需要稍微修改笔记本。

将数据传递给培训工作

考虑到我们自带数据集,我们需要利用渠道。你可以在这个文档中找到更多关于它们的信息。

现在,我个人觉得这个术语有点令人困惑,所以当我听到频道时,在我的脑海中我总是想到映射,因为它帮助我更好地想象发生了什么。让我试着解释一下:正如我们已经了解到的,训练作业旋转了一个 EC2 实例集群,并在其上复制了一个 Docker 映像。但是,我们的数据集位于 S3,无法通过 Docker 映像访问。相反,培训作业需要将数据从 S3“本地”复制到 Docker 映像的预定义路径中。其方法是,我们告诉培训作业数据位于 S3 的哪个位置,以及数据应该拷贝到 docker 映像的哪个位置,以便培训作业可以访问它。我们用本地路径绘制S3 的位置。

我们在训练作业的超参数部分设置本地路径:

作者图片

然后,当调用启动训练的 fit() 方法时,我们告诉训练作业数据在 S3 的位置:

作者图片

请注意, /opt/ml/input/data 后面的文件夹名称与通道名称(数据集)匹配。这使培训作业能够将数据从 S3 拷贝到本地路径。

开始训练

一旦我们做到这一点,我们就可以开始培训工作。如前所述,这是通过调用 fit() 方法来完成的。培训作业将运行大约 40 分钟,您可以跟踪进度并在控制台中查看其他信息:

作者图片

模特训练的完整代码在这个笔记本里。一旦训练工作完成,就该评估我们新训练的模型了。

第 4 部分—模型评估

评估我们的训练模型与我们在第 2 部分中评估 ZSL 模型时所做的非常相似:我们将调用模型并生成候选摘要,并通过计算 ROUGE 得分将它们与参考摘要进行比较。但是现在这个模型在 model.tar.gz S3 的一个名为的文件中(要找到确切的位置,你可以在控制台中查看培训工作)。那么我们如何访问模型来生成摘要呢?

我们有两种选择:要么将模型部署到 SageMaker 端点,要么在本地下载,类似于第 2 部分中 ZSL 模型的情况。在本教程中,我选择将模型部署到 SageMaker 端点,因为这样更方便,而且通过为端点选择一个更强大的实例,我们可以显著缩短推理时间。也就是说,在 Github repo 中,您还会发现一个笔记本,它显示了如何在本地评估模型。

部署模型

在 SageMaker 上部署一个训练有素的模型通常很容易,再次参见这个例子来自拥抱脸。一旦模型训练完毕,我们只需调用 estimator.deploy() ,SageMaker 会在后台为我们完成剩下的工作。因为在我们的教程中,我们会从一个笔记本切换到下一个笔记本,所以在部署之前,我们必须首先找到培训作业和关联的模型:

作者图片

一旦我们获得了模型位置,我们就可以将它部署到 SageMaker 端点:

在 SageMaker 上的部署很简单,因为它利用了 SageMaker 拥抱面部推理工具包,这是一个开源库,用于在 Amazon SageMaker 上提供变形金刚模型。我们通常甚至不需要提供一个推理脚本,工具包会处理好的。然而,在这种情况下,工具包再次利用管道 API,正如我们在第 2 部分中讨论的,管道 API 不允许我们使用高级的文本生成技术,比如波束搜索和采样。为了避免这个限制,我们提供了我们的定制推理脚本

首次评估

对于我们新训练的模型的第一次评估,我们将使用与第 2 部分零炮模型相同的参数来生成候选摘要。这允许进行苹果之间的比较:

将由模型生成的概要与参考概要进行比较:

这是令人鼓舞的!我们在没有任何超参数调整的情况下首次尝试训练模型,显著提高了 ROUGE 分数:

作者图片

第二次评估

现在终于是时候使用一些更高级的技术了,比如波束搜索和采样来摆弄这个模型。你可以在这篇出色的博文中找到这些参数的详细解释。因此,让我们用这些参数的一组半随机值来尝试一下:

当使用这些参数运行我们的模型时,我们得到以下分数:

作者图片

所以这并不像我们希望的那样,胭脂的分数实际上略有下降。但是,不要因此而放弃尝试这些参数的不同值。事实上,这是我们完成设置阶段并过渡到项目实验阶段的地方。

最终结论和后续步骤

我们已经完成了实验阶段的设置。我们已经下载并准备了我们的数据,使用简单的启发式方法创建了第一个基线,使用零触发学习创建了另一个基线,然后训练了我们自己的模型,并看到了性能的显著提高。现在是时候对我们创建的每个部分进行修改,以便创建更好的摘要了。一些你可能想尝试的想法:

  • 适当地预处理数据,例如删除停用词、标点符号等。不要低估这一部分——在许多数据科学项目中,数据预处理是最重要的方面之一(如果不是最重要的),数据科学家通常将大部分时间花在这项任务上。
  • 尝试不同的模型。在我们的教程中,我们使用标准模型进行总结(ssleifer/distilbart-CNN-12-6),但是我们知道有更多的模型可以用于这项任务。其中一个可能更适合您的用例。
  • 超参数调谐。在训练模型时,我们使用了一组特定的超参数(学习率、时期数等)。这些参数并不是一成不变的,恰恰相反。您希望更改这些参数,以了解它们如何影响您的模型性能。
  • 文本生成的不同参数。我们已经用不同的参数进行了一轮总结,以利用波束搜索和采样。尝试不同的值和不同的参数。回头参考这篇博客和其他资源,了解它们如何影响文本的生成。

我希望你能坚持到最后,并且觉得这篇教程很有用。

建立文本摘要项目(简介)

原文:https://towardsdatascience.com/setting-up-a-text-summarisation-project-introduction-526622eea4a8?source=collection_archive---------15-----------------------

拥抱变形金刚深入文本摘要的实用指南

纳迪·博罗迪纳在 Unsplash 上拍摄的照片

更新(2021 年 12 月 14 日):该教程现已作为一篇长文发布于此

自然语言生成新时代的到来

OpenAI 在 2020 年 7 月发布了专门研究文本生成的第三代机器学习(ML)模型时,我知道有些事情不同了。这个模型触动了前人没有触及的神经。突然,我听到朋友和同事谈论它,他们可能对技术感兴趣,但通常不太关心 AI/ML 领域的最新进展。甚至《卫报》也就此写了一篇文章。或者准确的说是模特写的文章,卫报编辑出版。不可否认,GPT 3 号改变了游戏规则。

一旦模型发布,人们立即开始为它想出潜在的应用。几周之内,大量令人印象深刻的演示被制作出来,这些演示可以在棒极了的 GPT-3 网站上找到。一个引起我注意的特殊应用是 文本摘要 ,即计算机阅读给定文本并概括其内容的能力。它结合了自然语言处理(NLP)领域中的两个领域,阅读理解和文本生成,并且是计算机最困难的任务之一。这就是为什么我对 GPT-3 文本摘要演示印象如此深刻。

你可以在 拥抱脸空间网站上试试。我目前最喜欢的是一个应用程序,它只需要输入文章的 URL 就可以生成新闻文章的摘要。

这个教程是关于什么的?

我工作的许多组织(慈善机构、公司、非政府组织)有大量的文本需要阅读和总结——财务报告或新闻文章、科研论文、专利申请、法律合同等。自然,这些组织对使用 NLP 技术自动完成这些任务感兴趣。因此,为了展示可能性的艺术,我经常使用文本总结演示,它们几乎总能给人留下深刻印象。

但是现在呢?

这些组织面临的挑战是,他们想要评估基于许多许多文档摘要的文本摘要模型——而不是一次一个。他们不想雇佣一个实习生,他唯一的工作就是打开应用程序,粘贴一个文档,点击“总结”按钮,等待输出,评估总结是否好,然后对数千个文档重新做一遍。

这就把我们带到了这个博客系列的目标:在这个教程中,我为组织提出了一个实用的指南,这样他们就可以评估他们领域的文本摘要模型的质量。

这个教程是(不是)给谁看的?

我是带着四周前的过去的自己写下这篇教程的,也就是说,当我开始这段旅程的时候,我希望我有这篇教程。从这个意义上说,本教程的目标读者是熟悉 AI/ML 并且以前使用过 Transformer 模型的人,但是他们才刚刚开始他们的文本总结之旅,并且想要更深入地了解它。因为它是由“初学者”为初学者写的,所以我想强调的是,本教程是实用指南,而不是实用指南。请像乔治·博克斯所说的那样对待它:**

作者图片

就本教程需要多少技术知识而言:它确实涉及一些 Python 中的编码,但大多数时候我们只是使用代码来调用 API,所以也不需要深入的编码知识。熟悉机器学习的某些概念将是有用的,例如,训练部署一个模型意味着什么,训练、验证和测试数据集的概念,等等。之前接触过变形金刚库可能会有用,因为我们将在本教程中广泛使用这个库。尽管如此,如果我没有忘记的话,我会试着为这些概念的进一步阅读加入有用的链接;)

因为这个教程是一个初学者写的,所以我不指望 NLP 专家和高级深度学习从业者能从这个教程中得到多少。至少从技术角度来看不是这样——不过,你可能仍然喜欢阅读,所以请不要离开!但是你必须对我的简化保持耐心——我试图让本教程中的所有内容尽可能简单,而不是更简单。

本教程的结构

这个系列将分为五个部分,我们将经历一个文本摘要项目的不同阶段。在第一部分中,我们将首先介绍文本摘要任务的度量标准,即允许我们评估摘要是“好”还是“坏”的性能衡量标准。我们还将介绍我们想要总结的数据集,并使用非 ML“模型”创建基线,即我们将使用简单的启发式方法从给定文本中生成摘要。创建这个基线在任何人工智能项目中都是至关重要的一步,因为它将使我们能够量化我们通过使用人工智能取得的进展,也就是说,它允许我们回答这样一个问题:“投资人工智能技术真的值得吗?”

在下一部分(第 2 部分)中,我们将使用一个已经预先训练好的模型来生成摘要。这是一种现代的称为迁移学习的方法。你可以在这篇文章中读到更多。这是另一个有用的步骤,因为我们基本上采用现成的模型,并在我们的数据集上进行测试。这允许我们创建另一个基线,这将有助于了解当我们在数据集上实际训练模型时会发生什么。这种方法被称为零镜头总结,因为该模型对我们的数据集没有任何影响。

之后,是时候使用一个预先训练好的模型,并在我们自己的数据集上训练它了(第 3 部分)。这也叫微调。它将使模型能够从我们数据的模式和特质中学习,并慢慢适应它。一旦我们训练了模型,我们将使用它来创建摘要(第 4 部分)。

所以,总结一下(看我做了什么?):

本教程结束时,我们将取得什么成果?

恐怕现在是残酷的现实检验的时候了:在本教程结束时,我们将而不是拥有一个可以在生产中使用的文本总结模型。我们甚至不会有一个好的总结模型(此处插入尖叫表情符号)!

相反,我们将有一个项目下一阶段的起点,这是实验阶段。这就是数据科学中的科学的用武之地,因为现在一切都是关于用不同的模型和不同的设置进行实验,以了解是否可以用可用的训练数据训练出足够好的汇总模型。

而且,完全透明地说,很有可能得出的结论是技术还不成熟,项目不会被实现。你必须让你的商业利益相关者为这种可能性做好准备。但那是另一篇博文的内容;)

建立文本摘要项目(第 1 部分)

原文:https://towardsdatascience.com/setting-up-a-text-summarisation-project-part-1-45553f751e14?source=collection_archive---------16-----------------------

如何用非 ML“模型”建立基线

Alexis Fauvet 在 Unsplash 上拍摄的照片

更新(2021 年 12 月 14 日):该教程现已作为一篇长文发布于此

这是怎么回事?

这是建立文本摘要项目教程的第一部分。有关本教程的更多内容和概述,请参考简介

在这一部分中,我们将使用一个非常简单的“模型”建立一个基线,而不实际使用机器学习(ML)。在任何 ML 项目中,这都是非常重要的一步,因为它让我们了解 ML 在项目期间增加了多少价值,以及是否值得投资。

教程的代码可以在这个 Github repo 中找到。

数据,数据,数据…

每一个 ML 项目都是从数据开始的!如果可能的话,我们应该总是使用与我们想要通过文本摘要项目实现的目标相关的数据。例如,如果我们的目标是总结专利申请,我们也应该使用专利申请来训练模型。对于一个 ML 项目,一个很大的警告是训练数据通常需要用标记。在文本摘要的上下文中,这意味着我们需要提供要摘要的文本以及摘要(“标签”)。只有提供这两者,模型才能知道“好的”摘要是什么样的。

在本教程中,我们将使用公开可用的数据集,但如果我们使用自定义/私有数据集,步骤和代码完全相同。同样,如果你对你的文本摘要模型有一个目标,并且有相应的数据,请使用你的数据来充分利用它。

我们将使用的数据是包含 arXiv 论文摘要及其标题的 arXiv 数据集。出于我们的目的,我们将使用摘要作为我们想要总结的文本,使用标题作为参考摘要。下载和数据预处理的所有步骤都可以在这个笔记本中找到。该数据集是作为这篇论文的一部分开发的,并根据知识共享 CC0 1.0 通用公共领域专用协议获得许可。

请注意,数据分为三个数据集,即训练、验证和测试数据。如果您想使用自己的数据,请确保情况也是如此。简单提醒一下,这是我们使用不同数据集的方式:

作者图片

自然,此时一个常见的问题是:我们需要多少数据?你可能已经猜到了,答案是:视情况而定。这取决于该领域的专业化程度(总结专利申请与总结新闻文章有很大不同)、该模型需要有多精确才能有用、该模型的训练成本应该是多少等等。我们将在稍后实际训练模型时回到这个问题,但不足的是,一旦我们处于项目的实验阶段,我们将不得不尝试不同的数据集大小。

什么是好的模型?

在许多 ML 项目中,度量一个模型的性能是相当简单的。这是因为模型的结果是否正确通常没有什么模糊性。数据集中的标签通常是二元的(真/假,是/否)或分类的。无论如何,在这种情况下,很容易将模型的输出与标签进行比较,并将其标记为正确或不正确。

当生成文本时,这变得更具挑战性。我们在数据集中提供的摘要(标签)只是总结文本的一种方式。但是总结一篇给定的文章有很多可能性。因此,即使模型与我们的标签 1:1 不匹配,输出可能仍然是有效和有用的摘要。那么,我们如何比较模型的总结和我们提供的总结呢?文本摘要中最常用来衡量模型质量的指标是 ROUGE score 。为了理解这个指标的机制,我推荐这篇博文。总之,胭脂分数测量模型摘要(候选摘要)和参考摘要(我们在数据集中提供的标签)之间的 n-grams (连续的 n 项序列)的重叠。但是,当然,这不是一个完美的措施,并了解其局限性,我很喜欢这篇文章

那么,我们如何计算胭脂分数呢?有相当多的 Python 包来计算这个指标,为了确保一致性,我们应该在整个项目中使用相同的方法。因为在本教程的稍后部分,我们将非常 l̶a̶z̶y̶聪明地使用变形金刚库中的训练脚本,而不是编写我们自己的脚本,所以我们可以只查看脚本的源代码并复制计算胭脂分数的代码:

通过使用这种方法来计算分数,我们可以确保在整个项目中始终进行比较。

注意,这个函数将计算几个 ROUGE 分数: rouge1rouge2rougeLrougeL sum(rougeL sum中的“总和”是指这个度量是在整个摘要上计算的,而 rougeL 是作为单个句子的*均值计算的)。那么,我们应该为我们的项目使用哪个 ROUGE 分数呢?同样,我们将不得不在试验阶段尝试不同的方法。值得一提的是,原始 ROUGE 论文称“ROUGE-2 和 ROUGE-L 在单个文档摘要任务中表现良好”,而“ROUGE-1 和 ROUGE-L 在评估简短摘要方面表现出色”。

创建基线

接下来,我们想通过使用一个简单的非 ML 模型来创建基线。那是什么意思?嗯,在文本摘要领域,许多研究使用一种非常简单的方法:他们提取文本的前 n 个句子,并将其声明为候选摘要。然后,他们将候选摘要与参考摘要进行比较,并计算 ROUGE 分数。这是一个简单而强大的方法,我们可以用几行代码实现(这部分的完整代码可以在这个笔记本中找到):

请注意,我们使用测试数据集进行评估。这是有意义的,因为一旦我们训练模型,我们也将使用相同的测试数据集进行最终评估。我们也为 n 尝试不同的数字,即我们只从第一句开始作为候选摘要,然后是前两句,最后是前三句。

这些是我们第一个“模型”的结果:

作者图片

我们可以看到,只有第一句话作为候选摘要,得分最高。这意味着使用一个以上的句子会使总结变得冗长,从而导致较低的分数。这意味着我们将使用一句话总结的分数作为基线。

值得注意的是,对于这样一个简单的方法,这些数字实际上相当不错,特别是对于 rouge1 分数。为了将这些数字放在上下文中,我们可以查看第,它显示了不同数据集的最先进模型的分数。

结论和下一步

我们已经介绍了将在整个总结项目中使用的数据集以及评估总结的指标。然后,我们用一个简单的非 ML 模型创建了以下基线:

作者图片

在下一部分中,我们将使用零镜头模型,即经过专门训练用于公共新闻文章文本摘要的模型。然而,这个模型根本不会在我们的数据集上训练(因此得名“零炮”)。

我会把它作为家庭作业留给你们,让你们猜猜这个零射击模型与我们非常简单的基线相比会有什么表现。一方面,它将是一个更加复杂的模型(实际上是一个神经网络),另一方面,它仅用于概括新闻文章,因此它可能会与 arXiv 数据集固有的模式相冲突。

建立文本摘要项目(第 2 部分)

原文:https://towardsdatascience.com/setting-up-a-text-summarisation-project-part-2-a2a8c49193e2?source=collection_archive---------12-----------------------

利用拥抱脸的管道 API 利用零射击学习进行文本摘要

戴维·dvořáček 在 Unsplash 上的照片

更新(2021 年 12 月 14 日):该教程现已作为一篇长文发布于此

这是怎么回事?

这是建立文本摘要项目教程的第二部分。有关本教程的更多内容和概述,请参考简介以及第 1 部分,在其中我们为我们的项目创建了一个基线。

在这篇博文中,我们将利用零射击学习 (ZSL)的概念,这意味着我们将使用一个经过训练的模型来总结文本,但尚未看到任何 arXiv 数据集的示例。这有点像当你这辈子一直在做的都是风景画的时候,试图去画一幅肖像。你知道如何绘画,但你可能不太熟悉肖像绘画的复杂性。

整个教程的代码可以在这个 Github repo 中找到。今天我们将特别使用这个笔记本

为什么零起点学习(ZSL)?

ZSL 在过去几年中变得流行起来,因为它允许在没有培训的情况下利用最先进的 NLP 模型。他们的表现有时相当惊人:大型科学研究工作组最*发布了他们的 T0pp(发音为“T Zero 组合+”)模型,该模型经过专门训练,用于研究零射击多任务学习。在大工作台基准测试中,它经常超过 6 倍大的模型,在其他几个 NLP 基准测试中,它也超过 16 倍大的 GPT-3

ZSL 的另一个好处是使用它只需要两行代码。通过尝试,我们可以创建第二个基线,一旦我们在数据集上对模型进行了微调,就可以用它来量化模型性能的提高。

建立零起点学习管道

为了利用 ZSL 模型,我们可以使用 Hugging Face 的 管道 API 。这个 API 使我们能够使用只有两行代码的文本摘要模型,同时它负责 NLP 模型中的主要处理步骤:

  1. 文本被预处理成模型可以理解的格式。
  2. 预处理后的输入被传递给模型。
  3. 模型的预测是后处理的,所以你可以理解它们。

它利用了拥抱面部模型中枢上已经可用的总结模型。

所以,下面是如何使用它:

就是这样,信不信由你。这段代码将下载一个汇总模型,并在您的机器上本地创建汇总。如果您想知道它使用的是哪种模型,您可以在源代码中查找或者使用以下命令:

当我们运行这个命令时,我们看到用于文本摘要的 defaukt 模型被称为sshleifer/distilbart-CNN-12–6:

作者图片

我们可以在拥抱脸网站上找到该模型的模型卡,在那里我们还可以看到该模型已经在两个数据集上进行了训练: CNN Dailymail 数据集极端摘要(XSum)数据集。值得注意的是,该模型不熟悉 arXiv 数据集,仅用于总结与其训练过的文本相似的文本(主要是新闻文章)。型号名称中的数字 12 和 6 分别指编码器层数和解码器层数。解释这些是什么超出了本教程的范围,但是你可以在 Sam Shleifer 的博客文章中读到更多关于它的内容,他创建了这个模型。

我们将继续使用默认模型,但我鼓励您尝试不同的预培训模型。所有适合总结的模型都可以在这里找到。要使用不同的模型,您可以在调用管道 API 时指定模型名称:

侧边栏:提取与抽象总结

我们还没有谈到两种可能但不同的文本摘要方法:提取 vs 抽象。摘要概括是将从文本中提取的内容连接成一个摘要的策略,而抽象概括包括用新句子解释语料库。大多数摘要模型都是基于生成新文本的模型(它们是自然语言生成模型,例如, GPT-3 )。这意味着总结模型也会产生新的文本,这使得它们成为抽象的总结模型。

生成零镜头摘要

现在我们知道了如何使用它,我们想在我们的测试数据集上使用它,与我们在第 1 部分中用来创建基线的数据集完全相同。我们可以用这个循环来实现:

注意,我们有最小长度最大长度参数来控制模型生成的摘要。在这个例子中,我们将的最小长度设置为 5,因为我们希望标题至少有 5 个单词长。通过查看参考摘要(即研究论文的实际标题),看起来 20 可能是 max_length 的合理值。但同样,这只是第一次尝试,一旦项目进入实验阶段,这两个参数可以而且应该改变,以查看模型性能是否发生变化。

侧边栏:波束搜索、采样等。

如果您已经熟悉文本生成,您可能知道还有许多参数会影响模型生成的文本,如光束搜索、采样和温度。这些参数使您能够更好地控制正在生成的文本,例如,使文本更加流畅,减少重复等。这些技术在管道 API 中是不可用的——你可以在源代码中看到 min_lengthmax_length 是唯一要考虑的参数。然而,一旦我们训练并部署了我们自己的模型,我们就可以访问那些参数了。在本系列的第 4 部分中会有更多的介绍。

模型评估

一旦我们生成了零镜头摘要,我们可以再次使用我们的 ROUGE 函数来比较候选摘要和参考摘要:

对使用 ZSL 模型生成的摘要运行此计算,我们得到以下结果:

作者图片

当我们将这些与第一部分的基线进行比较时,我们看到这个 ZSL 模型实际上比我们简单的只取第一句话的试探法表现得更差。同样,这并不出人意料:尽管这个模型知道如何总结新闻文章,但它从未见过总结学术研究论文摘要的例子。

结论

我们现在已经创建了两条基线,一条使用简单的启发式方法,另一条使用 ZSL 模型。通过比较 ROUGE 分数,我们看到简单启发式算法目前优于深度学习模型:

作者图片

在下一部分中,我们将采用这种完全相同的深度学习模型,并尝试提高其性能。我们将通过在 arXiv 数据集上训练它来做到这一点(这一步也被称为微调):我们利用了它已经知道如何概括文本的事实。然后,我们向它展示了大量 arXiv 数据集的示例。深度学习模型一旦接受训练,就非常擅长识别数据集中的模式,因此我们确实希望该模型在这项特定任务中变得更好。

在 AWS 上设置气流

原文:https://towardsdatascience.com/setting-up-airflow-on-aws-eks-385667671789?source=collection_archive---------6-----------------------

亚历克斯·丘马克在 Unsplash 上的照片

介绍

Airflow 是我最喜欢的工具之一,我经常使用它来设置和管理数据科学管道。气流用户界面为我们提供了 DAGS 及其当前状态的清晰画面。我可能是错的,但是从我的经验来看,我认为单个机器上的气流是不可扩展的。因此,为了扩大气流,我们可以使用 Kubernetes。

当我试图在 AWS EKS 上部署气流时,我不得不通过多个来源,从社区获得澄清。因此,我写这篇文章是为了让在 AWS EKS 上部署气流变得尽可能容易。

本文的先决条件是安装 aws-cli、kubectl 和 helm,在 aws 中设置一个 EKS 集群。我们将使用 helm 在 EKS 自动气象站部署气流舵图表。

我发现 Helm 在设置和管理 Kubernetes 应用程序时非常有用。Artifacthub.io 中提供了许多舵图。

气流也有一个舵图表,有很好的社区支持。我得感谢气流舵图表社区,他们帮了我大忙!舵轮图可在https://github . com/air flow-helm/charts/tree/main/charts/air flow获得。

先决条件

首先,我们需要设置我们的 kubectl 配置以指向 AWS EKS 集群。它的“如何”部分可在以下链接中找到:

https://docs . AWS . Amazon . com/eks/latest/user guide/create-kube config . html

一旦 kubectl kubeconfig(本地配置)设置为与 AWS EKS 集群通信,我们就可以继续在 AWS EKS 上部署气流了!!!!

舵图和自定义默认安装

在设置了前面指定的所有先决条件之后,我们现在可以开始我们的旅程了!

首先,我们需要添加回购并更新回购。这可以使用以下代码来完成:

helm repo add airflow-stable [https://airflow-helm.github.io/charts](https://airflow-helm.github.io/charts)
helm repo update

更新 helm repo 后,我们可以在 Kubernetes 集群上安装气流。为此,您可以先在本地的 minikube 上试用,然后再在 AWS EKS 集群上使用,或者直接安装在 AWS EKS 集群上。

以下命令将在 Kubernetes 集群上安装 Airflow:

helm install RELEASE_NAME airflow-stable/airflow 
--namespace NAMESPACE \
--version CHART_VERSION

RELEASE_NAME 可以取用户给定的任何值,名称空间是我们要安装 Airflow 的 Kubernetes 名称空间。默认情况下,如果没有指定名称空间,它将安装在 kubeconfig 的默认名称空间上。图表版本是需要安装的特定图表的版本,可以从https://github.com/airflow-helm/charts/releases获得

这将在 Kubernetes 集群上安装气流,并将创建 pod。这可能需要一些时间,所以请耐心等待。成功安装后,我们可以使用 kubectl 端口转发访问 airflow UI,如下所示:

export POD_NAME=$(kubectl get pods --namespace NAMESPACE -l "component=web,app=airflow" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward --namespace NAMESPACE $POD_NAME 8080:8080

这样,您可以通过 localhost:8080 上的浏览器访问 UI。它可能会问你用户名和密码,默认的用户名和密码分别是 admin 和 admin。

自动气象站 EKS 上的气流

Kubernetes 上的 Airflow 使用 PostgreSQL 数据库、持久性卷来存储 dags 代码和日志、Redis 数据库和其他组件。更多信息请参考https://github . com/air flow-helm/charts/tree/main/charts/air flow

上述组件在 Kubernetes 集群中创建为 pod,并由气流使用。

从 AWS 的角度来看,其中一些可以用 AWS 提供的服务来替代。就像我们可以使用 AWS EFS 作为永久卷的基础来保存我们的气流日志并保留我们的气流 DAG 代码,AWS RDS PostgreSQL 而不是使用 PostgreSQL 数据库作为 pod,AWS 弹性缓存而不是 Redis 数据库(虽然我没有尝试过)。气流推荐用 PostgreSQL 代替 MySQL。

AWS 的所有这些定制都可以在 helm 安装过程中使用的 values.yml 文件中完成。利用 values.yml 覆盖默认值的方法如下:

helm install RELEASE_NAME airflow-stable/airflow 
--namespace NAMESPACE \
--version CHART_VERSION \
--values values.yml

可以在以下链接中找到示例 values.yml 文件:

https://github . com/manojbalaji 1/AWS-air flow-helm/blob/main/values . yml

假设我们有一些 AWS RDS PostgreSQL。我们可以通过编辑上面提到的 values.yml 文件的“# Database-External Database”部分,用它来替代默认的 PostgreSQL。

在此之前,我们需要将我们的 AWS RDS PostgreSQL 密码作为 kubernetes-secret。这可以通过创建一个类似于https://github . com/manojbalaji 1/AWS-air flow-helm/blob/main/airflow-db-secret.yml的 air flow-d b-secret . yml 文件来完成

该文件包含 AWS RDS PostgreSQL base64 编码的密码。在基于 Linux 的系统上,密码可以编码如下:

>$echo “password” | base64
cGFzc3dvcmQK

其中 cGFzc3dvcmQK 是字符串“password”的 base64 编码值。类似地,您可以获得各自密码的 base64 编码值。

密码的编码值存储在 airflow-db-secret.yml 中,与密钥“密码”相对应,如下所示:

apiVersion: v1
kind: Secret
metadata: 
    name: airflowdb
type: Opaque
data: 
    password: cGFzc3dvcmQK

创建秘密文件后,我们可以使用以下命令使其在 Kubernetes 集群上可用,helm 将在安装期间访问该集群,如下所示:

kubectl apply -f airflow-db-secret.yml

现在继续,如果我们希望 Airflow 使用 AWS RDS PostgreSQL,首先我们需要在 values.yml 文件的“# Database-PostgreSQL Chart”部分将 enable 设置为 false,并编辑“# Database-External Database”部分,如下所示:

###################################
# Database - External Database
# - these configs are only used when `postgresql.enabled` is false
###################################
externalDatabase:  
    ## the type of external database:{mysql,postgres}  ##  
    type: postgres   

    ## the host of the external database  ##  
    host: <aws-postgresql-url>   

    ## the port of the external database  ##  
    port: 5432       ## the database/scheme to use within the the external database##         
    database: airflow       ## the user of the external database  ##  
    user: postgres   

    ## the name of a pre-created secret containing the external                       database password  ##  
    passwordSecret: "airflowdb"   

    ## the key within `externalDatabase.passwordSecret` containing the password string  ##  
    passwordSecretKey: "password"   

    ## the connection properties for external database, e.g. "?sslmode=require"  
    properties: ""

这里,我们需要在主机部分添加 AWS RDS PostgreSQL,将用户部分编辑为创建数据库时使用的适当用户名,添加我们在上一步中创建的密码的名称,在本例中,它是 passwordSecret 部分中的“airflowdb”和包含 base64 编码密码的密钥。在 passwordSecretKey 部分。

假设有一个在 s3 中持久化日志的需求,那么我们可以做同样的事情,首先在气流配置部分中添加一个具有适当值的连接,如下所示:

connections:     
    - id: s3_conn      
      type: aws      
      description: my AWS connection      
      extra: |-        
      { 
        "aws_access_key_id": "<aws_key_id>",             
        "aws_secret_access_key": "<aws_key>",           
        "region_name":"<aws-region>"         
      }

除此之外,我们还需要在 config 部分下设置一些环境变量,如下所示:

 AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL: "30"            
AIRFLOW__LOGGING__REMOTE_LOGGING : "True"        
AIRFLOW__LOGGING__REMOTE_LOG_CONN_ID : "s3_conn"        
AIRFLOW__LOGGING__REMOTE_BASE_LOG_FOLDER : "s3://<s3-path>/"        
AIRFLOW__CORE__ENCRYPT_S3_LOGS: "False"AIRFLOW__KUBERNETES_ENVIRONMENT_VARIABLES__AIRFLOW__CORE__REMOTE_LOGGING: "True"        AIRFLOW__KUBERNETES_ENVIRONMENT_VARIABLES__AIRFLOW__CORE__REMOTE_BASE_LOG_FOLDER: "s3://<s3-path>/"        AIRFLOW__KUBERNETES_ENVIRONMENT_VARIABLES__AIRFLOW__CORE__REMOTE_LOG_CONN_ID: "s3_conn"        AIRFLOW__KUBERNETES_ENVIRONMENT_VARIABLES__AIRFLOW__CORE__ENCRYPT_S3_LOGS: "False"

除此之外,还有其他需要注意的事情,比如我们如何获取代码库中的代码库。有一个 git-sync 选项,可以将 git 存储库中的代码与持久性卷中的代码同步。对于企业来说,这可能不是一个理想的选择,因为代码库是不可公开访问的。相反,我们可以有一个 Jenkins 作业,将代码部署到 AWS EFS 的一个可以通过气流访问的位置。

我们首先可以通过如下定义 efs-pvc.yml 来设置持久卷和持久卷声明,以便使用 AWS:

kind: StorageClassapi
Version: storage.k8s.io/v1
metadata:  
    name: efs-sc
provisioner: efs.csi.aws.com 
---apiVersion: v1
kind: PersistentVolume
metadata:  
    name: efs-pvc
spec:  
    capacity:    
        storage: 10Gi  
    volumeMode: Filesystem  
    accessModes:    
        - ReadWriteMany  
    persistentVolumeReclaimPolicy: Retain  
    storageClassName: efs-sc  
    nfs:    
        server: <sub-region>.<efs-key>.efs.<region>.amazonaws.com     
        path: "/" 
---apiVersion: v1
kind: PersistentVolumeClaim
metadata:  
    name: efs-storage-claim
spec:  
    accessModes:    
        - ReadWriteMany  
    storageClassName: efs-sc  
    resources:    
        requests:      
            storage: 10Gi

在代码中,我们需要用适当的 AWS EFS 值替换服务器属性的值,如上所述。

创建这个文件后,我们可以使用下面的代码创建一个 PV 和 PVC:

kubectl apply -f efs-pvc.yml

这将在 Kubernetes 集群中创建一个 PV 和 PVC,并且可以在 values.yml 文件中使用,如下所示:

airflow:
    extraVolumeMounts:
        - name: airflow-efs-dag
          mountPath: /opt/efs/

    extraVolumes:
        - name: airflow-efs-dag
          persistentVolumeClaim:
              claimName: efs-storage-claim

在上面的代码中,我们要求 helm 使用前面定义的 PVC 名称创建一个额外的卷。然后,使用它在 extraVolumeMounts 中指定的路径上创建一个卷装载。这样,我们现在可以通过路径/opt/efs/访问 helm install 创建的 Airflow pods 上的 AWS EFS。

要将该路径用作 dags 文件夹的路径,我们需要对 values.yml 文件中的“# air flow-DAGs Configs”部分进行如下小改动:

dags:
    path: /opt/efs/dags # /opt/efs is EFS mount path specified above

使用 values.yml 文件中的上述代码,Airflow 集群将从上述路径访问 dags 文件。现在,我们可以创建一个 Jenkins 作业,将代码从 git 存储库复制到前面提到的 EFS 的 dags 文件夹路径中。

同样,如果想使用 AWS ElasticCache 而不是 Redis 数据库,他们可以编辑 values.yml 文件中的# External Redis 数据库部分,并能够使用 ElasticCache。仅供参考,如果 ElasticCache 不需要密码,您可以忽略密码部分,在前面提到的部分填写其他详细信息。

气流 AWS 连接器

最后但同样重要的是,airflow 默认不提供连接器和其他库来与 AWS 一起工作,所以我们需要安装 Airflow AWS 提供程序。这可以通过在 values.yml 文件中使用以下代码进行编辑来完成:

airflow:
    extraPipPackages: 
        - "apache-airflow-providers-amazon"
        - "awscli"

使用上面的代码,helm 将确保这些包安装在 web、worker 和 scheduler pods 上。如果有任何其他外部 pip 包需求,它们可以被添加到上面的代码中,它也将被安装。

注意:不要忘记更改 fermatkey 默认值…!!!!

结论

通过遵循上述所有步骤,我们可以在 AWS EKS 上设置一个气流集群,利用它我们可以轻松地进行纵向扩展和横向扩展。

设置气流集群的代码可在 https://github.com/manojbalaji1/aws-airflow-helm处获得

希望这是有帮助的,请让我知道你的想法!干杯……!!!

使用 Docker 设置 Apache Airflow 2

原文:https://towardsdatascience.com/setting-up-apache-airflow-2-with-docker-e5b974b37728?source=collection_archive---------1-----------------------

Mikel Parera 在 Unsplash 上的照片

使用 Docker 设置著名任务编排器新版本的分步指南

简介

一个 帕切气流 2 终于出来了。在宣布的新特性中(一个全新的调度器,稳定的 REST APIs 等等),已经发布了一个生产就绪的 Dockerfile。这使得开发人员可以使用现代云技术部署气流,而不是将其安装在裸机上。

在本文中,我们将了解如何使用 VirtualBoxvagger创建一个本地环境,安装 Docker 并部署一个生产就绪的气流容器。开始吧!

局部环境

在本节中,我们将了解如何创建一个虚拟机,安装 docker 并配置一个共享文件夹,以便轻松访问客户机中的本地文件。如果您不想在实验中使用 VM,请随意跳过这一部分。

配置虚拟机

假设您已经在本地机器上安装了 VirtualBox 和 vagger,这是代表我们想要构建的虚拟机的清单(vagger file):

流浪档案

这个清单指定了" airflow-vm" (主机名)必须是什么样子:

  • 基于 ubuntu/xenial64 图片
  • 4GB 内存
  • 使用 IP 192.168.1.200
  • /opt/airflow 下挂载共享文件夹(必须在与流浪文件相同的路径下创建)

打开一个新的终端窗口,移动到流浪文件路径,简单输入:

vagrant up
vagrant ssh

安装对接器

现在是时候在这个全新的虚拟机上安装 Docker 了。我们将通过键入以下命令来使用官方 docker-install 脚本:

curl -fsSL https://get.docker.com -o get-docker.sh\
sh get-docker.sh\

如果一切正常,我们应该能够运行以下命令:

sudo docker run hello-world

码头集装箱上的气流 2

在这一节中,我们将从官方 Docker 映像(2.0 稳定版)开始,在其上添加一个层,以自动创建一个管理帐户并轻松配置一个外部 Postgres 数据库,从而通过本地执行器实现并行。

进场

从最后说起吧(是的,诺兰和特尼特改变了我的想法)。我们的目标是创建一个由 Airflow 2 (web 服务器和调度程序可以分开部署,但是对于本文来说,一体化解决方案可能更合适)和 Postgres 数据库组成的堆栈。我们将使用下面的 docker-compose 文件:

docker-compose.yaml

这里我们定义了两个服务: postgres (我们的 db)和 server (airflow)。

我们来分解一下!

方法— Postgres 数据库

学分: PostgreSQL 网站

postgres:
  image: postgres:12-alpine
  env_file:
    - postgres.env
  volumes:
    - postgres:/data/postgres
    - ./scripts/postgres/:/docker-entrypoint-initdb.d/

Postgres(基于 alpine 的 v12)由外部环境文件初始化:

POSTGRES_USER=airflow
POSTGRES_PASSWORD=<db_pass_here>
POSTGRES_DB=airflow
PGDATA=/data/postgres

和一个 00_init.sql 文件(在一个目录 scripts/postgres 中),它只是创建一个表:

CREATE TABLE airflow__extra_conf(
  conf_name  VARCHAR (255) PRIMARY KEY,
  conf_value VARCHAR (255) NOT NULL
);

Postgres 数据通过创建一个映射到 /data/postgres 的卷来持久化。

方法—气流服务器

演职员表:阿帕奇气流网站

server:
  image: airflow2-docker:1.0.0 # build this first
  env_file:
    - airflow.env
    - airflow_db.env
  ports:
    - "8080:8080"
  volumes:
    - ./dags:/opt/airflow/dags

Airflow server 是基于官方 2.0 稳定版的自定义 docker 镜像(将在下一节介绍)。我们使用两个环境文件: airflow.env (气流配置)和 airflow_db.env (数据库配置)。

这是一个最小的 airflow.env,您可以根据自己的需要扩展它:

# -- CORE
AIRFLOW__CORE__EXECUTOR=LocalExecutor
AIRFLOW__CORE__LOAD_EXAMPLES=False# -- WEBSERVER
AIRFLOW__WEBSERVER_BASE_URL=http://192.168.1.200 # here your VM IP# -- SCHEDULER
AIRFLOW__SCHEDULER__MIN_FILE_PROCESS_INTERVAL=60# -- ADMIN
SECURITY__ADMIN_USERNAME=<admin_username>
SECURITY__ADMIN_FIRSTNAME=<admin_firstname>
SECURITY__ADMIN_LASTNAME=<admin_lastname>
SECURITY__ADMIN_EMAIL=<admin_email>
SECURITY__ADMIN_PASSWORD=<admin_password>

请注意,由于我们不想使用内部的 SQLight 数据库,我们已经将 LocalExecutor 指定为核心执行器。本地执行器也将允许我们 Dag 中的任务并行。

airflow_db.env 包含我们在上一步中设置的外部数据库信息:

# -- DB
DB__HOST=airflow_postgres #docker stack name + _postgres
DB__PORT=5432
DB__USERNAME=airflow
DB__PASSWORD=<db_pass_here>
DB__NAME=airflow

我们还将挂载一个 dags 文件夹,在那里我们将放置我们的 DAG 文件。

气流 2 Dockerfile

让我们看看自定义气流图像是什么样子的:

*FROM* apache/airflow:2.0.0-python3.7*USER* root*# INSTALL TOOLS
RUN* apt-get update \
&& apt-get -y install libaio-dev \
&& apt-get install postgresql-client*RUN* mkdir extra*USER* airflow*# COPY SQL SCRIPT
COPY* scripts/airflow/check_init.sql ./extra/check_init.sql
*COPY* scripts/airflow/set_init.sql ./extra/set_init.sql*# ENTRYPOINT SCRIPT
COPY* scripts/airflow/init.sh ./init.sh*ENTRYPOINT* ["./init.sh"]

这基本上安装了一些依赖项(我们马上会看到为什么需要 postgresql-client),添加了两个 sql 脚本并运行了一个提供的 SH 脚本。让我们看看他们从结尾开始都做了些什么(再次感谢诺兰):

初始化. sh

一旦数据库可用,脚本将检查管理员用户是否存在,如何检查?还记得 airflow__extra_conf 表吗?它用于存储一个标志,该标志决定了正确的服务器初始化。

我们来看看 check_init.sql :

SELECT count(conf_name) FROM airflow__extra_conf WHERE conf_name='IS_INITIALIZED';

如果没有一个 IS_INITIALIZED 配置,SH 脚本会创建管理员帐户,然后使用 set_init.sql 设置配置:

INSERT INTO airflow__extra_conf VALUES('IS_INITIALIZED','1');

通过这种方式,管理员用户只需创建一次,而无需依赖其他解决方案(比如将文件保存在卷中)。

最终的项目结构应该如下所示:

/-- Vagrantfile
|-- shared
   |-- dags
   |-- scripts
      |-- airflow
         -- check_init.sql
         -- set_init.sql
         -- init.sh
      |-- postgres
         -- 00_init.sql
    -- Dockerfile
    -- docker-compose.yaml
    -- airflow.env
    -- airflow_db.env
    -- postgres.env

准备部署

假设您已经通过更改 IP、db 密码和管理员凭证更改了环境变量文件,那么您已经准备好使用 Docker 来部署 Airflow 了。

cd /opt/airflow
sudo docker stack deploy -c docker-compose.yaml airflow

可以使用以下方式查看 Airflow 服务器日志:

sudo docker service logs -f airflow_server

一旦您看到消息"创建管理员用户..”和 Airflow 徽标,您可以使用 UI 登录了。

打开您的浏览器并转到 192.168.1.200:8080 。输入您的管理员凭据,瞧!

接下来是什么?

现在,您可以将 Dag 上传到Dag文件夹中,并通过 UI 运行它们。

在下一篇文章中,我们将看到如何建立一个 Docker Swarm 集群,并使用 DockerSwarmOperator 在其中分配负载。

在独立模式下设置 Apache Spark

原文:https://towardsdatascience.com/setting-up-apache-spark-in-standalone-mode-81efb78c2b52?source=collection_archive---------12-----------------------

一种完整的并行计算集群构建方法

在这篇文章中,我们将在独立集群模式下设置 Apache Spark。Apache Spark 是一个框架,用于解决大数据问题,如数据处理、特征工程、机器学习和处理流数据。Apache Spark 提供了一种方法,通过使用独立的、YARN 或 MESOS 集群管理器进行并行计算,用几个工作节点来分配您的工作负载。其中最简单的是独立集群管理器,它不需要对配置文件进行太多的修改就可以设置自己的处理集群。

在这篇文章中,我不会涉及概念上的细节,而是实际的细节。对于有多个节点的集群,我将使用两个节点,一台机器独立安装 Ubuntu,另一台机器安装 VM 并激活桥接适配器。如果桥接适配器未激活,请执行以下步骤。

为主机 IP 地址共享设置虚拟机

1。选择机器,然后转到设置(作者图片)

2。切换到网络选项卡并选择适配器 1。在此检查后,如果未选中“启用网络适配器”。从下拉框中选择“桥接适配器”。(图片由作者提供)

要检查您的 IP 地址是否正与虚拟机共享,请打开并登录到您的虚拟机,然后在终端中键入:

#If "ifconfig" not installed
$ sudo apt-get install net-tools
$ ifconfig

您应该看到您的 IP 地址与您的主机相同。

设置 Apache Spark 环境

完成基本网络配置设置后,我们需要设置 Apache Spark 环境,方法是安装二进制文件、依赖项,并将系统路径添加到 Apache Spark 目录和 python 目录,以运行 Spark 的 bin 目录中提供的 Shell 脚本来启动集群。

-----PYTHON SETUP-----
#Check if "python3" is installed
$ python3 --version#If "pyhon3" not installed, then type commands below
#This will install python 3.6.9
$ sudo apt-get install python3.6#Check if pip is installed, since we might need it in future
$ pip3 --version#If pip3 not installed, then type commands below
$ sudo apt install python3-pip#Also install some other dependencies
$sudo apt-get install python3-numpy python3-matplotlib python3-scipy-----JAVA SETUP----
#Check if JAVA is installed, this is required by Spark which works #underneath it.
$ java -version#If not installed, type the command below
#This will install JAVA-11
$ sudo apt install default-jdk#Once JAVA installed, add it to the environment path
$ sudo update-alternatives --config java#copy the path from above command and paste it to environment as #"JAVA_HOME=/path/to/JAVA"
$ sudo nano /etc/environment

我们需要使用 SSH-keygen 设置 SSH-key,以允许 Spark 通过预授权访问机器。

#Install ssh
$ sudo apt-get install openssh-server openssh-client#Edit the sshd_config file to allow certain permissions
$ sudo nano /etc/ssh/sshd_config
PermitRootLogin yes
PubkeyAuthentication yes
PasswordAuthentication yes#Restart sshd services to reflect the changes in file
$ services sshd restart

到目前为止,所有步骤都需要在所有节点上完成。我们现在需要生成公钥,并将其复制到其他节点进行无密码身份验证。

仅对要启动 Spark master 的节点执行以下步骤。

# Generate key with rsa algorithm
#This will create a .ssh directory at /home/usr
$ ssh-keygen -t rsa#Skip paraphrase and other information by pressing "ENTER"#Copy id_rsa.pub public key using scp to all other nodes' root #directories. This will ask you to enter password for root@worker_1_IP #and root@worker_2_IP first time.
$ scp .ssh/id_rsa.pub root@worker_1_IP:
$ scp .ssh/id_rsa.pub root@worker_2_IP:#Change to root directory by typing "cd ~".#Switch to root@worker_1_IP and root@worker_2_IP and copy id_rsa.pub #from root directory to home directory of user.
$ ssh root@worker_1_IP (and for worker_2 also)
$ cp id_rsa.pub /home/usr/.ssh/authorized_keys#Above step will ask you to overwrite key if already present.#Once done with above steps, check if password-less authorisation #works from your Master node.
$ ssh usr@worker_1_IP
$ ssh usr@worker_2_IPNOTE: I would advice you to keep the user name for the machines in VM same if security is not an issue because the Spark requires Master node user (in my case "rahul") to be given permission for login as usr@worker_1_IP and usr@worker_2_IP where usr has to be same (in my case "rahul").#Another alternative is to create users on salve machines with sudo permissions.

下面,我们安装 Apache Spark 并修改配置文件来设置集群。我们已经安装了所有的依赖项和网络配置,以确保 Spark 运行无误。对所有节点执行这些步骤。

#Download Apache Spark-3.0.1 with hadoop2.7 tar file
$ wget [https://downloads.apache.org/spark/spark-3.0.1/spark-3.0.1-bin-hadoop2.7](https://downloads.apache.org/spark/spark-3.0.1/spark-3.0.1-bin-hadoop2.7) tgz#Check if tar file is present
$ ls -la#Extract the tar file
$ tar xvf spark-*#Move the file to /opt/spark
$ sudo mv spark-3.0.1-bin-hadoop2.7 /opt/spark#/opt/spark is going to be your SPARK_HOME directory. Also add #python3 directory path as PYSPARK_PYTHON. These change are to be #done in .profile file
$ sudo nano .profile#Add following variables and path
export SPARK_HOME=/opt/spark
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
export PYSPARK_PYTHON=/usr/bin/python3#save and close .profile file and recompile it
$ source .profile

现在我们只编辑主节点的配置文件。不要在从属节点上执行这些步骤。

#Copy and edit spark-env.sh.template and slave.template file
$ cp $SPARK_HOME/conf/spark-env.sh.template $SPARK_HOME/conf/spark- env.sh$cp $SPARK_HOME/conf/slaves.template $SPARK_HOME/conf/slaves#Open spark-env.sh file and add JAVA_HOME and other configurations 
#like Memory or CPU core numbers
$ sudo nano $SPARK_HOME/conf/spark-env.sh#add at the end of the file
export JAVA_HOME=/path/to/JAVA or $JAVA_HOME(from /etc/environment)
export SPARK_MASTER_HOST=master_IP#Open slaves file and add IP address of slaves. Delete "localhost" #if present
worker_1_IP
worker_2_IP#Save the file above and run command below to check if all nodes #starts
$ $SPARK_HOME/sbin/start-all.sh#Go to web browser and type
http://127.0.0.1:8080/
#This will show the number of workers, their running status, their configuration and other information.#To stop the Master and workers
$ $SPARK_HOME/sbin/stop-all.sh#To start SPARK SHELL which will run SCALA programming language
#Quit it using ":q" and enter
$ $SPARK_HOME/bin/spark-shell#To start SPARK SHELL with PYTHON programming language
# Quit it using "exit()" and enter
$ $SPARK_HOME/bin/pyspark

向群集提交应用程序

我们可以通过提交申请来检查我们的集群是否正常工作。Spark 应用程序检测保存 SparkConf 对象的 SparkContext 实例,该对象指定应用程序必须在本地进程还是集群进程中运行。我们将在以后的文章中讨论这个问题,但是现在只运行下面的代码来计算圆周率的值。

#IP=MASTER node IP address
#PORT=7077 for me
#You can check your master address by opening #[https://127.0.0.1:8080/](https://217.0.0.1:8080/)
$ MASTER=spark://IP:PORT $SPARK_HOME/bin/run-example org.apache.spark.examples.SparkPi#You should get a value and bunch of warnings

您应该会在 Spark UI 上看到类似的屏幕,如下所示。

SparkUI:作业完成(作者图片)

结论

在这篇文章中,我们学习了如何在 Apache Spark 中设置自己的集群环境,以及如何向它提交一个简单的应用程序,并使用 Spark UI 导航节点的状态。在接下来的文章中,我将解释如何配置您的应用程序在集群环境中执行,并以 rdd(弹性分布式数据集)的形式保存它们的结果。

参考

[1].http://spark.apache.org/docs/latest/spark-standalone.html

为机器学习设置苹果的 M1 MacBooks

原文:https://towardsdatascience.com/setting-up-apples-new-m1-macbooks-for-machine-learning-f9c6d67d2c0f?source=collection_archive---------1-----------------------

适用于 M1 专业版、M1 Max 和普通 M1 芯片

随着定制 M1 芯片的最新迭代,M1 Pro 和 M1 Max 版本,苹果给了机器学习社区一个强大的工具。然而,在某种程度上,这种力量只有在系统设置正确的情况下才能释放出来——尽管苹果公司通常对用户友好,但这不是一项简单的任务。

杰里米·贝赞格在 Unsplash 上的照片

在之前的一篇文章中,我将做事的过程与我们天生的求知欲联系起来。这篇文章是一个后续:它展示了如何为机器学习准备 M1 macbook。

机器学习的典型设置包括 a)使用虚拟环境,b)在其中安装所有包,c)使用 python,d)分析数据,以及 e)训练模型。因此,我们从建立虚拟环境开始。

我这边的一个简短说明(2022 年 3 月):在这篇文章的初始版本发布后*半年,我仍然定期回到这里,要么更新说明,要么为自己复习一下——特别是在设置 TensorFlow 时……我希望它也能同样很好地为你服务。

设置虚拟环境

虚拟环境帮助我们保持不同(python/code)项目之间的差异。例如,任务 A 可能需要特定程序的 1.0 版本来创建奇妙的动画。现在,项目 B 也需要这个程序,但是需要从版本 2.0 起才可用的其他特性。因此,我们没有合并项目的依赖关系,而是创建单独的虚拟空间。

我们可以把它们想象成盒子,每个项目都使用自己的盒子。通过使用这种方法,我们最小化了项目之间的干扰。这反过来减少了可能出现的问题。例如,如果我们不小心将一个程序从 1.0 更新到 2.0,但一个项目仍然需要 1.0 的功能,会发生什么?另一个项目需要从 2.0 开始引入的特性?因此,通过使用虚拟空间,我们可以省去精神上的麻烦。

Anaconda 和 venv(包含在 python 中)是处理这个问题最常用的工具。在本文中,我将使用 Anaconda,或者更具体地说,conda 实用程序。我这样做是因为在 M1 macbook 上安装 TensorFlow 目前需要 conda 工具才能顺利安装。(高级用户:尝试自己编译包。)

我们将从下载一个叫做 Miniforge 的小程序开始,它是 Conda 的最小安装程序。最小化意味着它并不臃肿,只包含一些基本的特性。这对于我们的用例来说已经足够了;我们将手动安装所有需要的东西。

首先,下载最新版本。下载完成后,打开一个终端窗口(使用 spotlight 搜索,键入终端,点击回车。)和类型:

这使得下载的文件可执行,并允许下一步:

在终端中输入上面的行之后,会要求您检查许可证。点击 q 跳到最后,键入 yes 表示同意。接下来,你会被问到你想在哪里安装 Miniforge。默认情况下,这是

X 是 Miniforge 的当前版本。在撰写本文时,这是 3。

保持原样,然后按回车键。如果询问您是否想要初始化它,键入 yes 。然后,通过同时按 CMD 和 q 关闭终端,并重新打开它。

你会像往常一样受到欢迎,但是终端窗口现在显示

(基数) <your_username>@ <name_of_your_machine>~ %</name_of_your_machine></your_username>

“(基础)”部分意味着您已经成功创建并激活了您的第一个环境!然而,在本文的剩余部分,我们将使用另一个环境,我们通过键入:

当询问您是否要继续时,键入 y (表示)。

完成后,它说,除其他事项外:

要激活此环境,请使用

$ conda 激活数据-科学

我们会做到的。我们因此打字

这就把(基础)部分变成了(数据科学),这正是我们想要的。我们现在开始安装我们需要的所有软件包。

将包安装到虚拟环境中

PyTorch 和 TensorFlow 是机器学习相关的最常用的框架。除此之外,Scikit-Learn 库对于许多任务都非常方便。

安装 PyTorch

我们从更容易安装的 PyTorch 开始。我们打字

来安装它和 NumPy 包。因为 NumPy 在大多数框架中使用,我们无论如何都要安装它。要快速检查事情是否进展顺利,输入 python 。这将在终端中打开一个 python 控制台。一个接一个地复制下面的行,每一行都按下回车键:

这个程序的输出将是一个用随机数填充的 5x 3 矩阵。

安装 TensorFlow

完成这个简单的安装后,我们现在开始安装 TensorFlow。在之前的帖子中,我说过这是(现在仍然是)一个麻烦。现在您将看到为什么会这样,特别是与 PyTorch 的无缝设置相比。

首先,我们打字

如果您在此阶段遇到问题,请尝试通过以下方式手动添加 Apple 频道

第一个命令在安装 TensorFlow 之前安装我们需要的所有依赖项。如果它要求你继续,输入 y 或者直接按回车键。如果没有这样的提示也不用担心;一切都很好。

我们将输入的下一个命令是

此命令在设备上安装 TensorFlow。请注意,下载可能需要一些时间;大概 200 MB 大小。

最后,我们将在 M1 Mac 电脑上安装一个加速计算的软件包:

因为到达那里很麻烦,所以我通常会执行一个小脚本来检查 TensorFlow 是否正常工作。你可以在下面找到我从文档中摘录的代码:

复制代码,在桌面上另存为 tf_installation_test.py 。然后,在终端仍然打开的情况下,运行

别忘了用你的用户名替换 <你的用户名> 。这需要几秒钟,然后输出开始。在五个时期之后,模型被训练达到大约 99%的测试准确度。

如果您想在以后安装任何额外的软件包,只需输入

pip 安装<package_name></package_name>

在终点站。确保您之前已经激活了“数据科学”conda 环境:

如果以后你没有得到任何关于 TensorFlow/Keras 的代码完成建议,请前往本期 GitHub

安装 Scikit-学习

scikit-learn 包可以按照前面的方法安装。简单地打字

pip 安装 scikit-学习

会成功的。

在成功设置 PyTorch、TensorFlow 和 Sklearn/Scikit-Learn 之后,我们现在可以开始用 python 编码了。

设置 PyCharm

说到 python 开发,PyCharm 是我的首选。因此,我将引导您通过 PyCharm“连接”我们的“数据科学”conda 环境。

如果您还没有,请访问下载页面。社区版就够了。确保您选择了”。dmg(苹果硅)”下拉菜单中。下载完成后,像安装任何其他 macOS 应用程序一样安装它。

启动 PyCharm 后,会有一个屏幕显示您的所有项目。在顶部,单击“新建项目”:

PyCharm 欢迎屏幕。图片由作者提供。

之后,将显示一个新的屏幕。默认情况下,新项目的类型是“纯 Python”,保持不变。点击“Python 解释器”旁边的小箭头,会显示更详细的设置页面:

更详细的项目设置页面。作者图片

在此页面上,勾选“先前配置的解释器”如果您在下拉列表中找不到我们的“数据科学”环境,请单击它旁边的三个点。

这将打开另一个屏幕:

您可以在该屏幕上创建新的 python 解释器。图片由作者提供。

单击左侧的“Conda Environment ”,并导航到我们保存环境的“Interpreter”路径。这是

/Users//miniforge 3/envs/data-science/bin/python

类似地,“Conda 可执行文件”字段的默认路径是

/Users//miniforge 3/bin/conda

完成后,单击“确定”。

最后,检查您是否想要创建一个 main.py 脚本,这对于演示是有帮助的。之后,点击“创建”。

在第一个项目打开和安装额外的包之后,PyCharm 会对您的包进行索引。完成后,点击出现在第 13 行的绿色三角形。这将运行脚本并将“Hi,PyCharm”打印到控制台上。

如果您得到一个错误,没有显示 TensorFlow/Keras 的代码建议,请前往这个 GitHub 问题

摘要

有了虚拟环境设置(a),安装了必要的包(b),并且能够用 python 编码,您现在可以开始分析数据和训练模型了。因为每个人都不一样,所以我让你来创造你想要的东西。

设置 Conda 在您的苹果 M1 硅机器上运行 PyData 堆栈

原文:https://towardsdatascience.com/setting-up-conda-to-run-pydata-stack-on-your-apple-m1-silicon-machine-55e0b8320f65?source=collection_archive---------22-----------------------

使用 mambaforge 为您的 ARM64 芯片安装诸如 Dask、XGBoost 和 Coiled 等 PyData 库的分步指南

Michael Dziedzic 通过 Unsplash 拍摄的图片

TL;博士;医生

在苹果 M1 机器上运行 PyData 库需要你使用一个 ARM64 定制版本的 conda-forge。本文提供了如何在您的机器上设置它的分步指南。然后讨论了一些特定于运行 Dask、Coiled 和 XGBoost 的问题。我希望这能对遇到类似问题的人有所帮助。

M1 的 PyData

苹果 M1 硅芯片是一项了不起的创新:它低功耗、高效率、电池寿命长,而且价格便宜。但是,如果您使用默认版本运行 PyData 堆栈,您可能会遇到一些奇怪的行为。

当您安装为英特尔 CPU 架构编写的库时,代码将通过 Rosetta 仿真器运行。这通常很有效,但可能会给特定的 PyData 库带来意想不到的问题。例如,当导入一个<100MB dataset.

Since the internals of Rosetta is proprietary, there’s no way to know exactly why this is happening.

Installing PyData Libraries using Mambaforge

But fear not, there 的一种前进方式时,我个人遇到了 Dask 的内存使用爆炸。您可以通过安装 ARM64-native 版本的 PyData 库来解决这种奇怪的行为。虽然对于大多数安装,我通常会推荐 Anaconda/miniconda,但是目前, mambaforge 部署似乎拥有最*滑的 ARM 安装过程。

下面是安装这个版本的 conda 并使用它来安装您最喜欢的 PyData 库的分步指南。

1。检查您的 conda 版本

  • 要检查您的 conda 安装,请在您的终端中键入conda info并检查platform键的值。这个应该说osx-arm64.
  • 如果没有,继续删除包含您的 conda 安装的文件夹。请注意,这将删除您的软件环境,因此请确保将这些环境另存为。yml 或者。txt 文件。您可以通过在终端中键入conda list - export > env-name.txtenvironment.yml来导出活动软件环境的“配方”。

2。下载曼巴福吉安装程序

3。运行安装程序。

  • 这应该会问你是否希望它为你运行conda init。选择“是”。
  • 如果由于某种原因它没有这样做(在我的例子中就发生了),您将不得不使用/path/to/mamba forge/bin/conda init zsh 自己运行conda init。请注意,zsh只有在您使用 zsh外壳时才有效。根据需要使用其他 shell 标志。

重启终端后,你现在应该可以像往常一样使用conda了。例如,你可以从使用conda env create -f <path/to/environment.yml>重建你的软件环境开始。

运行 Dask、Coiled 和 XGBoost 时的具体问题

下面是我在 Coiled 上尝试使用 Dask 和 XGBoost 运行工作负载时遇到的一些问题的进一步说明:

import coiled 
from dask import Client 
import dask.dataframe as dd cluster = coiled.Cluster() 
client = Client(cluster) 
ddf = dd.read_parquet("<path/to/100MB/file/on/s3>") 
ddf = ddf.persist()

我遇到了三个问题,我想分享我的解决方案,因为我可以想象其他人可能也会遇到这种情况:

  1. Dask 的内存使用量在导入小(<100MB) dataset with an error like the one below:
distributed.nanny - WARNING - Worker exceeded 95% memory budget. Restarting

2. In some software environments, my kernel was crashing when calling 导入盘绕时爆炸

3.切换到 mambaforge 部署后,我无法安装 XGBoost。

以下是我想出的解决办法。

1。Dask

第一个问题通过切换到 mambaforge 并从那里安装所有需要的 PyData 库得到了解决,如上面的分步指南所述。

2。盘绕的

第二个问题是由于 python-blosc 库引起的冲突。由于某种未知的原因,当导入带有分段错误的 python-blosc (例如作为import coiled的一部分)时,苹果 M1 机器上的内核崩溃。为了避免这种情况,请确保您当前的软件环境中没有安装 python-blosc。如果是,运行conda uninstall python-blosc将其移除。

3。XGBoost

最后,如果你想在你的苹果 M1 机器上运行 XGBoost,你需要跳过一些额外的环节,因为目前 conda-forge 上没有 arm64 兼容版本的 XGBoost。这不是问题,因为 XGBoost 本身实际上可以在你的苹果 M1 机器上运行;问题在于 XGBoost 安装的依赖项,特别是 numpy、scipy 和 scikit-learn。这些依赖项需要与 arm64 兼容,我们将通过完成以下步骤来确保这一点:

1.创建一个包含 Python、numpy、scikit-learn 和 scipy 的新 conda 环境。在这里使用 conda 而不是 pip 来安装这些依赖项是至关重要的。

conda create -n xgboostconda activate xgboostconda install python=3.8.8 numpy scipy scikit-learn

2.安装必要的库来编译 XGBoost

conda install cmake llvm-openmp compilers

3.现在我们已经有了正确的依赖项,我们可以从 pip 安装 XGBoost 了。这很好,因为我们已经安装了所有合适的 arm-64 依赖项。

pip install xgboost

4.带它去兜一圈!

注意:上面的步骤是由 Fabrice Daniel这本很棒的教程中总结出来的,并在 Isuru Fernando 的帮助下进行了更新。

走向

正如任何技术突破一样,随着行业重新校准并适应苹果转向 M1 芯片所引起的连锁反应,将会有一些阵痛。看到像 Anaconda 和 QuanStack 这样的公司以及 Conda-Forge 社区继续改进对 ARM 硬件的支持是令人兴奋的,我对 PyData 的强大未来充满信心!

这一次到此为止!我希望这篇文章有助于让你的 PyData 工作流程在你的苹果 M1 机器上顺利有效地运行。如果您有任何反馈或问题,或者有更适合您的不同设置,请联系我们!

原载于 2021 年 8 月 19 日https://coiled . io

在云功能上设置持续集成

原文:https://towardsdatascience.com/setting-up-continuous-integration-on-cloud-function-c015a214c96e?source=collection_archive---------28-----------------------

使用云功能时,无需再花费时间进行集成

莎拉·马赫穆达在 Unsplash 上拍摄的照片

介绍

集成是将您的更改应用到应用程序的过程。这可以通过很多方式实现,比如直接在应用程序中修改代码并重启,或者通过一个叫做持续集成的过程。持续集成是指将集成过程自动化。可以将您的应用程序连接到您的源存储库。通过这种方式,当您与 master/main 分支合并时,您可以将您的代码设置为集成的。当使用谷歌云功能时,非常简单,它是通过谷歌源代码库实现的。

谷歌资源仓库

Cloud Source Repositories 是 google 针对代码存储、管理和跟踪的解决方案。它类似于 git hub,但由 google 创建。在 GSR 中,可以跟踪 git hub 存储库并将其集成到功能中。让我们检查一下。首先,访问 google 控制台,在侧栏上的 CI/CD 子组中,单击 source repositories。点击开始,然后点击创建库。在它之后,这个模态应该出现:

点击连接外部储存库,然后在中继续。

选择您的项目名称和 git 提供者。对我来说,这是我的第一个项目和 Git Hub。

点击连接 GitHub。将出现一个 github 页面。输入您的 GH 凭证并授权连接。

之后,点击授权谷歌云*台。现在,您应该能够在 GSR、上看到您的回购,如下图所示:

谷歌云功能

现在进入 google cloud functions ,打开或创建你的函数(如果你对创建一个云函数并测试它有任何疑问,请查看我的上一篇文章https://towardsdatascience . com/deploying-python-functions-with-Google-cloud-functions-557517865 ba7)

打开你的函数,点击 next,把源代码改成云库

  • 在 repository 中键入您的存储库的名称(请使用 google,在下一版本中为我们提供一个下拉列表)。
  • 选择分支或标签。如果是分支,输入部署分支的名称。一般来说,我们使用主分支机构来完成这项工作。
  • 在有源代码的目录下,放你的目录路径。这里,有一个提示。如果保存。包含您的入口点的 py 文件位于 foder example_folder,put /example_folder 中。

之后,选择 deploy,持续集成就完成了。开心点,把时间花在有趣的事情上,而不是手工集成代码。

结论

手工进行集成是耗时的任务。自动集成的可能性节省了时间。在谷歌云功能中做起来很容易。只需要建立云储存库(将其连接到您的 git 提供商,如 github 和 bitbucket)。使用这些工具使我们能够提交,然后集成。它使部署过程更简单,并帮助我们在更短的时间内交付我们的功能。下一篇文章再见!

参考

[1]https://cloud.google.com/source-repositories

[2]https://towards data science . com/deploying-python-functions-with-Google-cloud-functions-557517865 ba 7

在 Kubernetes 上使用 Apache Airflow 设置数据管道

原文:https://towardsdatascience.com/setting-up-data-pipelines-using-apache-airflow-on-kubernetes-4506baea3ce0?source=collection_archive---------7-----------------------

在 Kubernetes 上部署可扩展的生产就绪型气流

安德拉兹·拉济奇在 Unsplash 上的照片

介绍

Apache Airflow 是一个用于调度和监控数据管道的开源工作流编排工具。它还可以用于机器学习工作流和其他目的。Kubernetes 是一个事实上的编排工具,用于调度容器化的应用程序。气流可以利用 Kubernetes 提供的能力,根据工作负载来放大/缩小工作人员。

去年,我在 Kubernetes 上部署了 Apache Airflow。Bitnami 提供了一个 Apache 气流舵图,使我易于部署和扩展。它主要由三部分组成:webserver、scheduler 和 worker。

  1. Web 服务器:您可以浏览您的 Dag,使用 GUI 启动/停止进程
  2. 调度程序:在后台管理和调度任务
  3. 工人:执行任务的实际实例

除了这三个重要部分,Airflow 还有 Redis 和 PostgreSQL 来存储您的连接设置、变量和日志。

你可以在下面的 GitHub 库查看 Bitnami 图表的细节。

https://github.com/bitnami/charts/tree/master/bitnami/airflow

加载气流 DAG 文件

在 Airflow 中,用户创建有向无环图(DAG)文件来定义必须执行的流程和任务、它们的执行频率、流程中任务的执行顺序以及它们之间的关系和依赖性。

当 Airflow 部署在标准服务器上时,我们只需要将 DAG 文件加载到服务器上的特定目录中。但是当您的 Airflow 部署在 Kubernetes 上时,您将需要其他方式让 Airflow 加载您的 DAG 文件。

我过去加载 DAG 文件的方式是从 Git 存储库。在我的本地 Kubernetes 集群上,有一个私有的 Git 存储库 GitLab。我必须启用舵图中的 Git 部分,并指定 Airflow 将使用的存储库。

可以从他们的资源库下载 Bitnami 气流图的 values . YAML:https://github . com/Bitnami/charts/tree/master/Bitnami/air flow

在 values.yaml 的 Git 部分,有一个字段定义了 Airflow 将同步和加载所有 DAG 文件的存储库。

git:
  dags:
  ## Enable in order to download DAG files from git repositories.
    enabled: true
    repositories:
      - repository: http://<User>:<Personal-Access-Tokens>@gitlab-webservice.gitlab.svc.cluster.local:8181/airflow/airflow.git
        branch: master
        name: gitlab
        path:

之后,您可以将所有 DAG 文件放在 Git 存储库中名为 dags 的文件夹中。因为我使用的是私有存储库,所以我使用如上所示的个人访问令牌来克隆 DAG 文件。

配置 Web 用户界面访问

为了让您的用户和您自己访问 Airflow 的 web UI,您需要公开 web 服务器的服务。如果您的 Kubernetes 集群中有 ingress 控制器,您可以配置 Ingress 资源,并允许自己通过 Ingress 访问 Airflow 服务器。您只需要启用入口,并将主机修改为您在 Helm 图表的 values.yaml 中的主机名。

ingress:
## Set to true to enable ingress record generation
  enabled: true
  hosts:
    name: airflow.yourdomain.com
    path: /

在我们部署气流之前,我们需要考虑舵图的更多值。因为我们将来需要升级我们的版本,所以必须提供数据库 PostgreSQL 和 Redis 的密码。您可以在 PostgreSQL 和 Redis 图表配置中设置它们。

此外,我们需要提供用户的密码和 fernetKey 进行身份验证。访问 web UI 的usernamepassword可以在 values.yaml 中的auth部分进行修改。记住还要将forcePassword设置为 true,这是将来升级正常工作所必需的。

要生成新的 fernet 密钥,可以使用 Airflow 官方文档提供的以下代码片段。一些随机的文本(例如2r3EPAQ-Fzc-rAexn5ltRsnaUP9QjoVi7Z36I3AcyZ4=)会被打印出来。只需将其复制到auth部分的fernetKey字段即可。

from cryptography.fernet import Fernet
fernet_key= Fernet.generate_key()
print(fernet_key.decode()) # your fernet_key, keep it in secured place!

使用头盔展开

一旦我们完成了舵图的修改,你就可以使用三个命令在 Kubernetes 上部署气流了!

首先,创建一个名为 airflow 的名称空间:

kubectl create ns airflow

其次,将 Bitnami 图表存储库添加到 Helm:

helm repo add bitnami [https://charts.bitnami.com/bitnami](https://charts.bitnami.com/bitnami)

最后,你用头盔安装气流。轻松点。当然,您可以将“my-release”更改为任何您喜欢的名称。

helm install –n airflow my-release bitnami/airflow -f values.yaml

气流展开!您应该会看到类似这样的内容:

NAME: my-release
LAST DEPLOYED: Thu Mar 11 01:27:30 2021
NAMESPACE: airflow
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1\. Get the Airflow URL by running:echo URL : [http://127.0.0.1:8080](http://127.0.0.1:8080)2\. Get your Airflow login credentials by running:
 export AIRFLOW_PASSWORD=$(kubectl get secret — namespace airflow my-release-airflow -o jsonpath=”{.data.airflow-password}” | base64 — decode)
 echo User: user
 echo Password: $AIRFLOW_PASSWORD

您可以按照上面的说明获取您的 Airflow 登录凭据。您还可以通过 values.yaml 中指定的 URL 访问您的 web UI(在本例中是 airflow.yourdomain.com)

过一会儿,通过命令kubectl get pod -n airflow,您应该看到所有的 pod 都在名称空间 airflow 中运行。

# kubectl get pod -n airflow
NAME READY STATUS RESTARTS AGE
airflow-postgresql-0 1/1 Running 0 3m53s
airflow-redis-master-0 1/1 Running 0 3m53s
airflow-redis-slave-0 1/1 Running 0 3m53s
airflow-redis-slave-1 1/1 Running 0 3m53s
airflow-scheduler-5f8cc4fd5f-jf4s9 2/2 Running 0 3m53s
airflow-web-859dd77944-sfgw4 2/2 Running 0 3m53s
airflow-worker-0 2/2 Running 0 3m53s
airflow-worker-1 2/2 Running 0 3m53s
airflow-worker-2 2/2 Running 0 3m53s

安装额外的 Python 包

有时,您可能需要原始图像不包含的额外 Python 包。Bitnami 的图表允许您挂载自己的 requirements.txt 来安装所需的包。您需要将您的卷安装到/bitnami/python/requirements.txt。当容器启动时,它将执行pip install -r /bitnami/python/requirements.txt

在 worker 组件中,需要通过提供卷的name和容器实例的mountPath来修改extraVolumeMounts。还需要加上你的extraVolumes。我使用 ConfigMap 将 requirements.txt 添加到容器中,因为我可以更容易地添加更多额外的 python 包。

extraVolumeMounts:
  - name: requirements
    mountPath: /bitnami/python/## Add extra volumes
extraVolumes:
  - name: requirements
    configMap:
# Provide the name of the ConfigMap containing the files you want
# to add to the container
      name: requirements

为了创建我们需要的配置图,首先,我们准备 requirements.txt 文件。然后,我们通过以下命令创建配置映射:

kubectl create -n airflow configmap requirements --from-file=requirements.txt

在我们创建了 ConfigMap 并修改了 values.yaml 之后,我们需要升级我们的气流。只需一个简单的命令:

helm upgrade –n airflow my-release bitnami/airflow -f values.yaml

结论

在本文中,我向您展示了如何在 Kubernetes 上部署气流的基础知识。Bitnami 提供了一个组织良好的舵图,让我们可以轻松地在 Kubernetes 上部署气流。基于 Bitnami 的掌舵图,仍然有一些小参数,如数据库用户名和密码,auth fernet 密钥,额外的 python 包等,我们需要调整。虽然 Bitnami 已经帮我们省去了很多辛苦,但是在建立“正确”的设置之前,我还是经历了很多试错的过程。希望这个指南能帮你节省一些时间!如果你对 Kubernetes 上的气流架构有什么想法,请告诉我。我想听听你对 Kubernetes 更好、更可扩展的气流的看法。

如果你想了解更多关于气流的用例,可以看看我之前的文章。在那篇文章中,我展示了如何使用 Airflow 构建一个用于移动网络性能监控的自动报告系统。

如果您想了解如何使用 Kubespray 构建本地 Kubernetes,请访问本文:

如果您想了解更多关于 Apache Airflow 的知识,Udemy 上有一个很好的课程,可以教授 Airflow 的基础知识,还可以动手构建数据管道。如有兴趣,请参考以下附属链接:

https://click.linksynergy.com/deeplink?id=0wsuN4lypZM&mid=39197&murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fthe-complete-hands-on-course-to-master-apache-airflow%2F https://click.linksynergy.com/link?id=0wsuN4lypZM&offerid=916798.19111388448&type=2&murl=https%3A%2F%2Fwww.coursera.org%2Flearn%2Fetl-and-data-pipelines-shell-airflow-kafka

如何以最简单的方式配置 Github 动作?

原文:https://towardsdatascience.com/setting-up-python-environment-using-github-actions-9a81936be5c9?source=collection_archive---------21-----------------------

本文旨在自动化 GitHub 上托管的 ML 项目,并减少通过拉请求的代码破坏。

https://github.com/features/actions

介绍

在我的上一篇文章中,我一步一步地引导您在本地机器上使用 pyenv 正确设置 python3 环境。然而,在某些情况下,由于使用不同 python 版本甚至缺少模块的 pull 请求所导致的一些冲突,可能会出现一些问题。

本教程将演示为任何使用 Github actions 插件的项目建立标准工作流程的步骤。在项目 CI 文件夹中配置 Github 操作将保护不符合关于代码格式、语法错误和版本冲突的代码标准的代码库 pull 请求。所以,让我们开始吧!

先决条件:

  1. Github 账户。
  2. 代码编辑器— IDE,我更喜欢 vscode
  3. YML 语法基础知识— 这里快速回顾
  4. 安装在本地机器上的 python 3—遵循这里的步骤

GitHub 有哪些动作?

Github actions 是自动化和管理项目工作流完整开发生命周期的插件。在功能上类似 Circleci、Travis、Gitlab 但是,如果项目存储库是公共的,那么它是免费的。

什么是工作流?

Github 动作的工作流程是一系列写在 yml 文件中的步骤或指示,每次你推送到 GitHub 上的特定分支时都会运行。

为什么为每个项目建立工作流程很重要?

从长远来看,设置工作流可以节省时间,在推送/合并代码的过程中,您可以安心。可以定制工作流来检查 yml 文件中描述为步骤的不同测试。这些检查可能是使用编码语言的正确版本、安装依赖,甚至是检查代码格式和语法错误。通过这种方式,您可以保证不那么担心将代码合并到主分支中——至少不会出现任何问题!

https://developer . sales force . com/blogs/2020/01/using-sales force-dx-with-github-actions . html

您可能有多个工作流,每个工作流可能有多个作业。工作流每次都被触发,推送到一个特定的分支

设置 yml 文件以使用特定版本的 python

在本指南中,我将使用以下内容:

  1. pyenv-action 由 Gabriel Falco 开发,用于选择正确的 python 版本。
  2. 将 Postgres 配置为数据库的 Postgress docker 映像。
  3. Flak8 检查语法错误
  4. Pylint 来检查代码格式。

首先:初始化 GitHub 项目 repos

Github 操作可以在现有的回购协议上配置,也可以从头创建一个。为了简单起见,我会从头开始一个新的;导航到 GitHub,新建一个 repo 并命名;我将它命名为github_actions。然后将 repo 克隆到您的本地机器上,并在.github/workflows/main.yml上创建一个 GitHub 工作流操作文件——这是定义步骤的地方。

您可以使用 github workflows 模板,方法是转到 action tap 并触发 yml 文件。

Github repo 上的操作选项卡—作者图片

第二:定义项目需求;

您可以通过在终端中运行以下命令来包含 requirements.txt 文件:

$ pip freeze > requirements.txt

第三:定义操作作业 python 版本:

每个工作流可能有一组作业,每个作业包含几个要执行的步骤。

我用的是 Gabrial 开发的 pyenv-action 动作。该操作将执行以下操作:

  • 安装 pyenv 1.2.21
  • 导出 PYENV_ROOT 环境变量。
  • 在路径中注入$PYENV_ROOT/bin
  • 在路径中注入 pyenv 垫片
  • 预安装指定的 python 版本。
  • 设置默认 python 版本(通过pyenv local)。— pyenv-action

打开main.yml文件,开始配置 pyenv 并选择正确的 python 版本。以下代码片段使用 pyenv-action 版本 7 安装 pyenv,然后在选择版本 3.8.6 后升级 pip 并将其设置为默认版本。接下来,使用默认版本创建一个虚拟环境,并安装项目依赖项。

成功构建—作者的图像

获得成功构建的健康绿色检查—图片由作者提供

它有一个成功的构建,并且会出现一个与提交 id 相关联的绿色健康检查,如上所示。

四:配置 Postgres 服务

与上一步相同;但是,我们将使用 Postgres docker 映像在服务部分定义 Postgres 数据库连接。一些运行状况检查被配置为等待 Postgres 启动。最后,端口 5432 从服务容器映射到主机。

db_service 服务容器已经成功构建😏。

五—可选:配置 pylint

利用 pylint 可以检查每个推送到主分支的代码片段是否有错误,并强制执行编码标准。

Pylint 是一个检查 Python 代码中错误的工具,试图执行一个编码标准并寻找代码气味。它还可以查找特定的类型错误,它可以推荐关于如何重构特定块的建议,并且可以提供关于代码复杂性的细节。— 皮林特 2 . 6 . 1-开发 1

我们可以在安装完需求后安装 pylint,并运行pylint作为下一步

- name: Install dependencies run: pip install -r requirements.txt --upgrade pip pip install pylint- name: Analysing the code with pylint run: | pylint `ls -R|grep .py$|xargs`

最终的 main.yml 文件可能如下所示:

测试:将代码推送到 Github repo

现在是时候添加一些代码,并尝试将其推送到 GitHub 库了。我首先创建了一个演示文件,并开发了一种从不同元素和大小的输入数组中生成随机采样的方法。所有子集的可能性应该相等。

下一步是使用 pull 请求或直接 push to master 提交和推送 Github 存储库变更。一旦对遥控器进行了更改,在将更改合并到 master 之前,将针对这些更改运行不同的测试。

不成功的构建—作者的图像

如上图所示,根据 pylint 包,由于不适当的格式化,产生了一个错误;有些错误是因为我没有遵循 snake_case 命名约定。如您所见,推送代码的比率为 4.29/10。

如果您想忽略 pylint 对 docstring 的检查,您可以创建一个名为.pylint的新文件,并在其中添加以下代码片段来忽略 docstring 模块。

【MASTER】
disable =
c 0114,# missing-module-docstring

现在,在创建 pylint 文件之后,提交并推送 Github 存储库更改,构建应该会成功,并且在 repo 附*会出现一个健康的绿色复选标记😎。

成功构建—作者的图像

结论和要点

Github action 是一个强大的插件,它使机器学习开发周期自动化。您可以向工作流添加更多的步骤和工作,包括部署到不同的*台,如 Iaas、Paas、Saas 和现场。此外,它允许您使用 docker 容器以及 Kubernetes。有很多 GitHub-actions 是由社区的市场构建的;如果你有编程背景或者遵循文档,你甚至可以创建你的 定制动作

帮助我配置此工作流的一些参考资料是:

  1. Github 动作的工作流语法
  2. Postgresql Github 动作Harmon
  3. Github 动作文档—环境变量
  4. 学习 Github 动作
  5. Pyenv-行动加布里埃尔·法尔科
  6. 皮林特文件

最后,我希望这为利用 GitHub 动作自动化机器学习项目提供了全面的指导。如果你有任何问题或建议,请发表在下面的评论区;我非常乐意帮忙。感谢阅读和快乐学习👍

编码面试的七(7)个基本数据结构和相关的常见问题

原文:https://towardsdatascience.com/seven-7-essential-data-structures-for-a-coding-interview-and-associated-common-questions-72ceb644290?source=collection_archive---------1-----------------------

作者图片

用动画可视化的重要数据结构

编码面试是各种软件工程、机器学习和数据科学工作的重要组成部分。大多数候选人擅长使用编程来解决他们的日常研究问题。但是当进行编码面试时,人们需要温习不同数据结构的基础知识,因为大多数问题都围绕着为给定的问题选择正确的数据结构。

本文将详细介绍对编码面试很重要的七种基本数据结构,它们的时间复杂性,以及常见的编码问题。

1.数组/列表

List 包含一系列有序的值,这些值在内存中相邻放置。列表由第一个元素的地址来标识。由于列表元素在内存中的放置顺序与它们被定义的顺序相同(在下面的例子中,由于 2 在 12 之后,所以 12 在内存中的位置紧接在 2 之后),所以列表中的每个元素都可以通过将第一个元素的地址增加正确的索引量来访问。因此,无论元素在列表中的位置如何,访问列表中的任何元素都需要恒定的时间。

时间复杂度:

Access-O(1):访问列表中的元素需要用索引对其进行寻址。

Search-O(n):搜索列表中是否存在元素需要(在最坏的情况下)逐个遍历每个索引

插入/删除— O(n) :从列表中插入(删除)一个元素首先需要找到它,也就是 O(n)

常见问题:

  1. 反转链表
  2. 查找链表的中间元素
  3. 查找链表是否循环

2.链表

与列表/数组相反,链表的顺序不是由它们在内存中的物理位置定义的。链表的连续元素在内存中不是彼此相邻放置的。相反,每个链表元素包含值和指向下一个链表元素的地址(指针)。因此,链表只能一次顺序遍历每个元素。这也意味着链表的长度只有在完全遍历完一个元素之后才能知道。链表的最后一个元素以 None/Null 作为指针。链表由指向第一个元素的指针定义。

时间复杂度:

Access — O(n): 访问链表中的一个元素需要(在最坏的情况下)逐个遍历每个元素。

Search-O(n):搜索一个元素是否存在于一个链表中需要(在最坏的情况下)逐个遍历每个元素

插入/删除— O(1) :插入(删除)一个给定指针的元素到需要插入(删除)的地方只需要重新排列指针。然而,在末尾插入(删除)一个元素需要遍历整个链表,因此是 O(n)

常见问题:

  1. 反转链表
  2. 查找链表的中间元素
  3. 查找链表是否循环

3.哈希表

散列表可以被认为是列表的一般形式。在列表中,我们将索引映射到可以在常量时间内访问的值。哈希表试图映射一种数据类型(整数、浮点、字符串等。)转换为另一种数据类型,从而创建成对的赋值(键映射到值),这样就可以在常量时间内访问这些对

对于每个 (key,value) 对,通过哈希函数传递密钥,试图为要存储在内存中的值创建唯一的物理地址。大多数情况下,哈希函数可以跨键值创建唯一的物理地址。有时候,散列函数最终会为不同的键(比如 key_1、key_2)生成相同的物理地址。这被称为碰撞。哈希表通过创建一个键和值都很强的链表来处理冲突。然后遍历链表以匹配< 键> ,返回 <值> 对。

当必须在代码算法中执行多个搜索操作时,哈希表会很有用。

时间复杂度:

Search-O(1):搜索一个关键字是否存在于一个哈希表中需要(*均来说)恒定的时间量。

插入/删除— O(1) :从哈希表中插入(删除)一个 <键、值> 对需要一个恒定的时间量,而与字典的大小无关

常见问题:

  1. 判断列表中的两个元素的总和是否为目标值
  2. 分组字谜
  3. 没有重复字符的最长子串

4.长队

队列是一种顺序数据结构,当元素被插入队列时,它保持元素的顺序。它保持先入先出( FIFO )的顺序,这意味着元素只能以与它们被插入队列时相同的顺序被访问。将 元素先插入 ,将 第一个从队列中移除

对队列执行的两个最常见的操作是 Enqueue()和 Dequeue()。 Enqueue() 将一个元素添加到队列中,而 Dequeue() 从队列中移除一个元素。在给定阶段,由出列移除的元素取决于队列的初始状态和 Enqueue()操作的顺序。

为了理解队列是如何工作的,让我们考虑队列中的两个位置(水*放置,以便更好地理解)——前端 和末端 。每当添加一个元素(Enqueue())时,它都被添加到队列的末尾。另一方面,元素移除(Dequeue())是从队列的前面完成的。现实生活中的一个例子是杂货店的结账队伍。顾客进入队列,等待轮到自己。只有当他/她前面的所有客户都已被处理(从队列中删除)时,才能处理(从队列中删除)。

时间复杂度(*均):

Access-O(n):访问队列中的一个元素需要(在最坏的情况下)逐个使每个元素出列()。

Search-O(n):搜索一个元素是否存在于队列中需要(在最坏的情况下)将每个元素出列()并与目标进行比较。

插入/删除-O(1):从队列中插入(删除)一个元素,将该元素添加到(从)队列的末端(前端)。这总是可以在恒定的时间内完成。

常见问题:

  1. 二叉树右侧视图
  2. 任务调度器
  3. 总和至少为 K 的最短子阵列

5.堆

堆栈也是一种顺序数据结构(类似于队列),它维护元素插入时的顺序。然而,与队列不同,堆栈保持后进先出( LIFO )的顺序,这意味着元素只能以插入堆栈时的 逆序 访问。最后插入 的元素, 将把的第一个从堆栈中删除* 。*

对堆栈执行的两个最常见的操作是 push()和 pop()。 Push() (类似 Enqueue())将一个元素添加到堆栈中,而 pop() (就像 Dequeue())将一个元素从中移除。在给定阶段,pop()移除的元素取决于堆栈的初始状态或最后一次 push()操作

为了理解堆栈如何工作,让我们考虑堆栈中的两个位置( 垂直 放置以便更好地理解)——头和尾。每当添加或删除一个元素时(push()或 pop()),总是在头部位置完成。堆叠的真实例子是一堆厨房盘子。最后一个被添加到盘子堆中的盘子将是第一个被使用的(虽然您可以访问最上面的盘子下面的盘子,但是人们很少这样做)

时间复杂度(*均):

Access — O(n): 访问堆栈中的一个元素需要(在最坏的情况下)逐个 pop()每个元素。

Search — O(n): 搜索一个元素是否存在于一个栈中,需要(在最坏的情况下)pop()每个元素,并与目标进行比较。

Insert/Delete — O(1) :向堆栈中插入(删除)一个元素,在堆栈顶部添加(删除)该元素。这总是可以在恒定的时间内完成。

常见问题:

  1. 有效括号
  2. 收集雨水
  3. 功能独占时间

6.树(二进制)

树是一种数据结构,它维护其元素之间的层次关系。每个元素都有一个前任和多个继任者,分别称为 。在这一节,我们将考虑一个二叉树。在二叉树中,每个节点最多可以有两个子节点(左子节点,右子节点)。以下是与二叉树相关的一些基本定义

  • 树由指向其根节点的指针定义。
  • 父节点——任何至少有一个子节点的节点称为父节点。
  • 子节点—父节点的后继节点称为子节点。节点既可以是父节点,也可以是子节点。根永远不是子节点。
  • 叶节点——没有任何子节点的节点称为叶节点。
  • 子树——原始树的有效子集。
  • 路径——沿着树的边缘的节点序列被称为路径。
  • 遍历——以一定的顺序遍历节点,如广度优先遍历、深度优先遍历等。

基于条件层次结构,我们可以有多种类型的树。最常用的一种是二叉查找树。二叉查找树(BST)是一种有序或排序的二叉树,其中左侧子节点的值小于父节点的值,右侧子节点的值大于父节点的值。

常见问题:

  1. 验证二叉查找树
  2. 二叉树层次顺序遍历
  3. 二叉树的最低共同祖先

7.图表

图由节点或顶点和连接一对节点的边组成。从形式上讲,一个图 G 是一对集合 (V,E) ,其中 V 是所有顶点的集合, E 是所有边的集合。如果所有顶点都通过一条边与一个节点或顶点相连,则称该节点或顶点为邻居。与树相反,图可以是循环的,这意味着从一个节点开始,沿着边,可以在同一个节点结束。

常见问题:

  1. 克隆图形
  2. 图是二分的吗?
  3. 外星人字典

重要资源:

您可能还会发现下面的文章很有用

* *

如果这篇文章对你有帮助,或者你想了解更多关于机器学习和数据科学的知识,请关注我Aqeel an war,或者联系我LinkedIn**

七种 Jupyter 笔记本电脑设置,提高可读性

原文:https://towardsdatascience.com/seven-jupyter-notebook-setups-to-improve-readability-a9b681b05dec?source=collection_archive---------11-----------------------

一个实现你可能会用到的七个 Jupyter 笔记本增强/修改的教程

Jupyter 笔记本

使用单独执行的编码块或单元——尽管它们可能有顺序依赖性——对于数据模型开发非常有用。Jupyter 笔记本界面简单易学。一旦你精通了基础知识,请允许我分享七个增加这些笔记本可读性的设置修改或增强。

增加可读性的七种 Jupyter 笔记本设置:

  1. 黑暗主题
  2. 执行时间
  3. 便条簿
  4. 拆分单元
  5. 代码折叠
  6. 可折叠标题
  7. 目录(2)

安装 Nbextensions

Nbextensions 选项适用于设置 2–7(除了黑暗主题之外的所有选项)。

这七个设置中的大多数都包括来自jupyter _ contrib _ nb extensions的选项。请参见安装步骤中的阅读文档。例如,使用画中画:

pip install jupyter_contrib_nbextensions

或者

pip install https://github.com/ipython-contrib/jupyter_contrib_nbextensions/tarball/master

安装完成后,当您启动 Jupyter 笔记本电脑时,您会在顶部看到 Nbextensions 选项。

Juptyer 笔记本推出 Nbextensions(图片由作者提供)

点击 Nbextensions,你会看到下面的许多选项。

Nbextensions 选项(图片由作者提供)

当您单击某个选项时,该选项的描述将出现在列表下方(在 Jupyter 笔记本中向下滚动)。虽然下面对拆分单元格笔记本的描述很简短,但一些扩展有更详细的描述。

1.黑暗主题

安全第一。深色主题通常是我对软件默认设置的第一个修改。深色主题通过限制默认情况下更常见的明亮白光来减少眼睛疲劳。如果我忘记设置一个黑暗的主题,用不了多久我就会注意到生产力的下降,并考虑调整默认值。

要安装 Jupyter 主题:

pip install jupyterthemes

要查看可用的主题选项,请键入 jt -l:

jt -l

输出:

Available Themes: 
 chesterish
 grade3
 gruvboxd
 gruvboxl
 monokai
 oceans16
 onedork
 solarizedd
 solarizedl

事实上,并非所有的主题都是黑暗主题。这些主题的例子可以在 dunovank 的 GitHub 上找到。如果你想定制你自己的主题,也可以在 GitHub 主页上找到。

我更喜欢切斯特风格的主题。为了在更改主题后在 Jupyter 环境中看到工具栏、名称和内核,您需要分别在命令中添加-T -N 和-kl。

jt -t chesterish -T -N -kl

重启 Jupyter 内核,重新打开你的笔记本,瞧!您现在拥有了与本文中的屏幕截图相同的主题。

但是,图和其他图像可能不会像在白色背景上那样显示。对于 seaborn 地块,以下命令可以解决这个问题。

import seaborn as sns
sns.set_theme(style=”whitegrid”)

2.执行时间

执行时间选项允许您查看每个单元需要多长时间来完成。任何使用需要几分钟以上时间来执行的模型的人都可以体会到这种时间记录的便利性,但是这在开发新模型时比较单元的不同选项时也很有帮助。

启用 Nbextensions 中的 ExecuteTime 选项,可以看到执行代码块下面共享的执行时间。在这种情况下,细胞在 203ms 内执行。

3.便条簿

Scratchpad 选项允许您测试代码,而无需临时创建然后删除单元块。

启用 Nbextensions 中的草稿栏选项。

便签簿按钮出现在笔记本的右下角。

便签簿按钮出现在笔记本的右下角(图片由作者提供)

点击草稿栏按钮打开草稿栏。暂存区是一个空的单元块,可以利用已经在笔记本内核上运行的内容。但是便笺式存储器可以在不修改任何笔记本单元的情况下被修改和运行。

我发现这是一个查找帮助细节、打印变量或尝试新事物而不改变现有笔记本单元格的方便地方。

打开草稿栏查找帮助文件(作者图片)

4.拆分单元

拆分单元格选项有助于改善笔记本的外观和可读性。

启用 Nbextensions 中的分割单元格笔记本选项。

按← →按钮调整单元格的半宽,然后在单元格的上方或下方移动到上一个或下一个单元格,再次按下按钮将之前水*分隔的单元格移动到新的垂直分隔。

这对于在可视化旁边显示数据框尤其有用。这样,就不需要向下滚动来查看数据框或可视化效果。

使用切换分割按钮移动数据框并垂直分割绘图(按作者分类的图像)

5.代码折叠

Codefolding 选项启用了用于隐藏缩进代码的扩展箭头,增强了笔记本的可读性和外观。

启用 Nbextensions 中的代码折叠选项。

单击显示隐藏缩进代码选项的箭头。

折叠缩进代码前后的代码折叠(作者图片)

6.可折叠标题

可折叠标题选项也有助于笔记本的外观和可读性。

启用 Nbextensions 中的可折叠标题选项。

使用标题旁边生成的箭头,折叠和展开标题。

1.1(显示在 #5 分割单元格中)现在折叠,而 1.2 未折叠(图片由作者提供)

7.目录(2)

目录(2) 选项是快速浏览冗长笔记本的另一个好方法。

启用 Nbextensions 中的目录(2)* 选项。*

点击启用后出现的目录图标。带有超链接的表格将加载到笔记本的左上角,在工具栏图标下。向下拖动到一个舒适的位置,如下图所示。

带超链接的目录(图片由作者提供)

当不再需要快速导航或阅读该部分的概述时,可以通过再次按下其按钮从笔记本空间中移除目录。

摘要

这些是相对快速的 Jupyter 设置,我发现对可读性非常有用。但是还有许多更好的软件包可以和 Jupyter 一起使用。我想分享三个在某些情况下很棒的荣誉奖,虽然不是每个笔记本都需要。

荣誉奖:

在你的项目中引入人工智能之前要问的七个问题

原文:https://towardsdatascience.com/seven-questions-to-ask-before-introducing-ai-to-your-project-b969d591c98b?source=collection_archive---------15-----------------------

又名机器学习第一法则?不要用机器学习。

作者图片

随着机器学习在寻找新药和为无人驾驶汽车提供动力方面取得成功,人们的期望是它是可用的,而且非常实惠。如果它能解决那些大问题,那么它一定很容易应用于更小的问题。

我还记得我在大学期间第一次了解 CNN 时的兴奋。在年轻活跃的头脑中,所有的问题都有一个解决方案,这个解决方案就是深度神经网络。经验告诉我,如果使用不当,机器学习算法本身就会成为一个问题。

在写这篇文章的时候,我偶然发现了 LinkedIn 的这篇文章,它描述了两个机器学习团队在处理同一个问题时的区别——一个团队不惜一切代价带来一个机器学习解决方案,另一个团队花时间去理解问题。我更喜欢第二种方法。

这篇文章总结了我在决定是否继续使用机器学习解决方案时关注的领域。说了这么多,让我们开始吧!

问题

这个问题适合机器学习吗?

机器学习可以从多个角度来看,在一个简化的世界中,它是一种从训练数据中学习模式的工具,用于对看不见的测试示例进行预测。

自然,数据中的模式可能非常简单,可以通过一组规则或分析解决方案来破解。例如,预测下一次日出时间可以很容易地通过一套物理规则指导的分析解决方案来完成。在这些情况下,机器学习解决方案将是一种矫枉过正的做法。

同时,模式对于当前的模型来说可能过于复杂。这是一个机器翻译问题,要超越简单的字典映射并达到人类水*的性能,需要将关于世界的大量信息纳入模型。

最佳点问题是一个非常具体的任务,有一组固定的输出选项和明确的目标,其中有一个可以学习的明确模式——图像或文本分类、图像增强、语音到文本映射。

数据

有足够的数据吗?数据质量是否合理?

也许开发高质量解决方案的主要障碍是缺乏足够数量的高质量数据。对于许多问题来说,数据需要被挖掘——这为数据挖掘工具创造了一个市场,比如 Amazon Mechanical Turk。理想情况下,数据需要是*衡的、通用的、异构的和标记良好的。

如果数据集包含 1000 张猫的图像和 10 张狗的图像,那么简单模型很可能无法捕捉到狗的分布。在这种情况下,通常使用可以根据不*衡数据训练的模型。数据需要有一个很好的猫和狗品种的选择,以便模型学习共同的特征。被误标为猫的狗很可能会混淆模型。

费用

开发和维护成本能否持续?

开发成本

开发机器学习解决方案有几个方面成本非常高——团队、硬件、数据。

正如许多问题一样,人是成功的关键。顶级机器学习工程师拥有高水*的学位,他们的技能需求很高,这意味着他们的成本会非常高。在英国,一名 ML 工程师的*均工资是 6 万英镑。

人不是唯一的费用——机器学习模型需要在专门的硬件上进行训练。初创公司经常从科技巨头那里获得数十万的信用额度,用于硬件。然而,对于老牌企业来说,这种情况很少发生,这意味着它们需要自己支付费用。

最后,数据…如果我们无法获得免费数据,就需要挖掘这些数据。在亚马逊土耳其机械上,一个简单的点击标签的简单任务,只需花费 0.05 美元。为了得到一个有 1,000,000 张图片的标签良好的数据集,我们必须支付 50,000 美元。这是一个非常简单的点击式任务。对于更复杂的问题,成本很容易超过 10 万美元。

维修费用

机器学习模型需要维护,以确保驱动您决策的模型与当前数据分布保持同步。这意味着理想情况下你需要一个工程师来维护它。顶级产品通常停留在迭代反馈周期。

部署模型的硬件(例如云)也需要付费。随着业务规模的扩大,成本会直线上升。工作负载分配可能是一个挑战——没有足够的机器意味着处理请求的延迟。机器太多,成本会上升。

程序调试时间

你能拿出至少半年的时间来解决一个问题吗?

如果解决方案不是现成可用的,比如 Google/Amazon/Microsoft 提供的服务,那么开发和部署时间可能会相当长。对于长期解决方案,您需要建立数据、培训和测试渠道。

开发是一个迭代的过程。根据我的个人经验,建立一个非常简单的模型需要一个月的时间。并行执行的数据收集和清理将花费大致相同的时间。简单的培训和部署也需要大约一个月的时间。

复杂性通常是迭代增加的——随着模型的每一步,数据管道变得越来越复杂,因此需要积极地维护。根据应用的不同,在实际得到解决方案之前,可能会有几十次迭代。

可解释性

了解算法如何得出解决方案对于应用程序是否至关重要?

尽管对于许多非生命关键的应用程序来说并不那么重要,但是理解 ML 算法如何得出结论可能是有用的。例如,药物发现将极大地受益于可解释性,因为我们将获得指导成功发现的模式的提示。

在生命危急的情况下,可解释性是必不可少的——在用机器学习模型诊断疾病时,必须知道模型如何以及为什么得出结论,以确保患者没有受到虐待。理解自动驾驶汽车如何做出决策也很重要,以确保不会学到可能导致道路事故的虚假相关性。

伦理学

你的模型决策会歧视最终用户吗?

臭名昭著的推特机器人在一瞬间变成了一个种族主义者,这是一个很好的例子,但可能很少是一个模特如何走错方向的明显例子。实践中使用的许多模型都有潜在的偏差,这种偏差通常很难识别。

在某些情况下,这种偏见可能没什么大不了的——例如,一个聊天机器人在下午学会了变得更友好(也许是在带有时间戳的数据集上训练的——人们确实倾向于在午餐后变得稍微友好一些)。然而,一个对女性比男性更友好的聊天机器人会很令人担忧,但很难诊断问题。偏差通常指向训练数据中的严重问题。

处理时间

应用需要实时运行吗?

由于其复杂性,许多机器学习算法将难以达到某些应用所要求的时间性能。在准确性方面表现良好的重模型将需要大量的计算和内存。

机器学习很难实现的两个例子是高频交易和计算机图形学。在这两种情况下,速度非常重要,因此通常采用简单的试探法。

手机是另一个例子,由于资源相当稀缺,实现机器学习解决方案可能具有挑战性。这就是为什么现在许多手机都引入了神经处理单元(NPUs)——使模型能够放在移动设备上。

结论

本科生在最后一年不被鼓励做机器学习项目是有原因的——这简直太冒险了。大学已经经历了所有的陷阱,才知道它使项目暴露在明显的风险中。

从机器学习工程师那里听到这种说法,听起来可能像是我是一名保险代理人,劝说你不要购买他的服务。但在这种情况下,诚实是最好的策略。毕竟,这是非常容易的烧钱吨,而以下炒作,实际上并没有更糟。

对于那些有足够勇气开始一个人工智能项目的人来说,看看我最*写的关于管理人工智能项目特别有用的工具的文章。

如果你喜欢这篇文章,请与朋友分享!要阅读更多关于机器学习和图像处理的主题,请点击订阅!

进一步阅读

我是 Cassie Kozyrkov 关于 ML 用例的一系列文章的忠实粉丝。这些是我最喜欢的:

你的项目真的需要机器学习吗?寻找 AI 用例的建议

在开始一个人工智能项目之前要考虑的一个更详细的问题清单: 你的人工智能项目是一个没有希望的项目吗?

一个关于如何在开始一个人工智能项目之前进行健全性检查的更详细的指南,以及在开始一个项目之前要寻找什么的广泛的指导: 人工智能入门?从这里开始!

你可能还想看看 谷歌 ML 工程师指南

喜欢作者?保持联系!

我错过了什么吗?不要犹豫,直接在 LinkedInTwitter 上给我留言、评论或发消息吧!

产生数据科学项目想法的七种策略

原文:https://towardsdatascience.com/seven-steps-to-generate-data-science-project-ideas-8fb69400634d?source=collection_archive---------36-----------------------

用这七个策略寻找数据科学组合项目创意

佛罗伦萨——作者的形象

个人项目是数据科学最棒的事情之一。大多数项目需要大型团队&昂贵的软件——尝试作为一名孤独的土木工程师,只用一台笔记本电脑和互联网连接来建造一座桥梁!

数据科学社区在数据、工具和教育方面的开放性意味着您可以自己取得进步。

在公司之外完成的工作可以为你的个人作品集做出贡献——这是展示你的技术能力和创造内容供他人使用和学习的一种方式。这也是对家庭测试和专业数据科学工作的实践。

投资组合项目伴随着一个挑战——提出一个想法。这就是这篇文章的内容——产生数据科学项目想法的七个策略:

  1. 一场纸牌游戏比赛,
  2. 解决你关心的问题,
  3. 从一个环境开始,做控制,
  4. 重新实现一篇机器学习论文,
  5. 用机器学习改进现有工作,
  6. 管理一个数据集,
  7. 打造一个工具。

开始之前

在我们开始之前,我们有两件事要讲。

首先是在公司之外做项目的挑战之一——商业环境挑战

商业环境挑战

在公司之外做项目的挑战之一是缺乏商业背景。

业务环境允许数据科学家做出技术决策。了解业务需求有助于数据科学家理解要做出的技术决策。

如果业务需要一个可以解释的模型,这就缩小了数据科学家可以考虑的模型的选择范围。如果模型需要在嵌入式硬件上运行,深度学习可能不是一个好的选择。

缺乏商业背景意味着你要做出选择——这些选择通常是由你工作的企业决定的。这取决于你是否能填补你缺乏商业背景留下的空白——一种方法是用你自己的激励目标。

明确你的动机和目标

动机和目标可以用来填补个人项目中的业务背景空白。

你可以根据自己做项目的理由做出技术决策,而不是考虑雇主的需求。你需要明确两件事——你的动机和目标。

你的动机是关于为什么——为什么你想做一个项目

数据科学家从事新项目的原因有很多。对于那些闯入数据科学的人来说,一个项目给了他们展示能力和技能的机会。对于成熟的数据科学家来说,项目提供了学习和持续改进的机会,或者为他们关心的问题做出贡献的机会。

常见的动机包括:

  • 建立你的投资组合,
  • 向雇主展示特定的能力,
  • 学习一门新的语言(比如 Javascript 或者 Haskell),
  • 学习一项新技术(如计算机视觉或概率编程),
  • 学习新库(学习 Tensorflow 或 PyTorch),
  • 学习一个新工具(比如 Docker),
  • 有助于解决现实世界的问题,
  • 对科学文献有所贡献,
  • 通过赢得比赛赚钱。

保守你的动机——只选择一个。虽然同时朝着多个动机努力是可能的,但也有可能陷入困境。在学习一门新语言的同时试图给雇主留下深刻印象,最终可能看起来不那么令人印象深刻!

你的目标是关于什么——你想从项目中获得什么。

目标是具体的,应该是你可以触摸、展示或下载的东西,例如:

  • 成功的求职申请
  • 一个记录良好的 Github 库
  • 一篇博文
  • 可下载的数据集
  • 可用的工具
  • Kaggle 比赛名次

与你的动机不同,你应该有多个优先的目标。例如,如果你的主要目标是一篇博客文章,那么努力创建一个有良好文档记录的 Github 库仍然很重要。

别忘了享受你的项目!并不是项目的每个时刻都是难以想象的幸福(尤其是当你必须安装 CUDA 的时候)——但是应该有你喜欢的时刻,比如看到一个模型第一次学习,你的代码质量提高,或者乐于修复一个 bug。

现在我们已经了解了您的动机和目标,我们可以看看产生数据科学项目想法的七个策略,大致按照难度增加的顺序排列。

1.纸牌游戏比赛

从卫星图像中了解云

Kaggle 是一个举办数据科学竞赛的网站——公司提出他们的商业问题,并为最佳解决方案提供现金奖励。

Kaggle 竞赛的伟大之处在于它们伴随着商业背景。

竞赛通常包括以下所有内容:

  • 数据集 —通常是表格数据、图像或文本,
  • 预定义的测试集
  • 目标 —要预测的列,如图像类、
  • 一种度量 —判断性能,如均方误差、
  • 别人代码的笔记本(或内核),
  • 比较表现的排行榜。

所有这些都是有用的——这就是为什么 Kaggle 竞赛是一个更容易的项目。典型的 Kaggle 竞争比数据科学家在行业中获得的商业背景更多!例如,选择指标通常是由数据科学家做出的选择,而不是由业务部门做出的选择。

尽管 Kaggle 比赛有商业背景,但这并不意味着 Kaggle 比赛很容易获胜。Kaggle 竞赛通常是通过巧妙的特征工程、外部数据、数据泄漏和梯度增强决策树的大规模集成(如 XGBoost 或 LightGBM)的组合来赢得的。

主导 Kaggle 竞赛的大规模合奏在行业中并不常见,训练、维护和部署它们的额外工程工作不值得增加性能改进。然而,在每 0.01%都很重要的 Kaggle 竞争中,它们确实有意义。

竞争会持续一段时间,然后变得不活跃。如果你的动机是获得更高的名次,你就只能参加积极的比赛。然而,如果你的动机是学习,你也应该考虑不活跃的竞争。

开展 Kaggle 竞赛的最佳方式是借鉴他人的成果。从一台性能良好的公共笔记本开始,可以为您的工作打下坚实的基础。

在 Kaggle 上也有可能有创意。你可以对一个数据集采取不同的方法,甚至可以合并不同比赛的数据集。

如果你正在寻找一个比赛开始,我们建议如下:

2.解决你关心的问题

Kaggle 竞赛的问题在于,你无法控制竞赛在解决什么问题。如果你的任务是解决一个特定的问题,或者有你想要使用的领域专业知识,Kaggle 上可能没有与你的动机相符的合适竞争。

如果你有一个你关心的具体问题,在你开始考虑数据集之前,你需要问— 数据科学如何帮助解决这个问题?数据科学家帮助企业的最常见方式之一是通过预测——这通常意味着某种形式的监督机器学习。

如果你的洞察力不能促成新的行动或改进现有的行动,它就没有多大价值

Russell Jurney,敏捷数据科学

当考虑监督学习是否可以解决你的问题时,你需要回答这个问题— 改进的预测如何帮助解决我的问题?这个问题的另一种表达方式是问在预测做出后将会采取什么行动。仔细考虑如何在现实世界中使用预测是很重要的。

一旦您理解了预测如何推动行动,您接下来的步骤是:

  • 找到一个数据集,
  • 选择要预测的目标,
  • 选择一个衡量性能的标准,
  • 研究其他人对类似问题的解决方案。

你会注意到,这些步骤与一家公司在 Kaggle 竞争中提供的内容一致——这是你需要定义的缺失的业务环境。

有很多地方可以找到数据集—一些受欢迎的地方是(你可以在这里找到一个更大的列表:

考虑数据集时,您应该问:

  • 我有多少数据?多少行&列?
  • 功能有用吗?
  • 什么是目标
  • 目标是如何分布的——不*衡吗?
  • 目标和特征的测量误差有多大?
  • 数据取样是否有任何偏差?
  • 有季节效应吗?

选择指标至关重要。在业务中,理想的度量是那些与业务目标一致的度量。如果没有这种背景,度量标准的选择应该与解决您所关心的问题相一致。

3.从环境入手,做控制

开 AI 健身房

前两种策略用于监督学习项目——使用一些特征来预测目标。控制是不同的——控制是让系统按照你想要的方式运行。采用一个复杂的系统并设计一个算法来控制它是监督学习的一个进步。

一个流行的控制算法家族是强化学习(其他包括最优控制和进化算法)。

强化学习可以被视为三个任务的交集:

难怪控制比监督学习更难,在监督学习中,数据和标签都是免费的!

进行控制项目的两个常见动机——一个是通过实现控制算法来了解它,另一个是控制一个真实的系统。

动机——学习控制算法

如果你的动机是想了解一个特定的算法是如何工作的,那么实现它是一个很好的开始。如果你是初学者,我们建议选择一个简单的算法,而不是从复杂的开始。

不幸的是,这并不像选择旧方法那么简单——在控制方面,进步往往是通过简化实现的。比如最*的 PPO 就比 TRPO 简单。

如果你不知道从哪里开始,我们建议如下:

  • 价值函数方法——普通 Q 学习,
  • 政策梯度方法——用基线加强,
  • 进化算法-1-λES。

一旦你选择了一个算法,你需要一个环境来控制。当你进行开发和调试时,使用经过实战检验的环境是很重要的——最好是你熟悉的环境。这种熟悉意味着您知道代理应该多快开始学习,以及良好的表现是什么样子的。也意味着你不会在环境有 bug 的时候追着尾巴调试你的代理!

用于调试和调优的良好环境经过了良好的测试,并且模拟起来很便宜——我们推荐以下内容(均来自 Open AI 的健身房):

动机——控制一个真实的动态系统

如果你有兴趣控制一个真实的动态系统(真实世界或模拟),你的任务是不同的。您需要回答的一些问题是:

  • 我可以模拟我的环境吗?
  • 我的观察包括足够的信息来做决定吗?
  • 我的奖励信号是什么?

没有这些对于学习如何控制会是一个很大的问题。对于任何控制问题,你应该先了解特定领域的解决方案,然后再考虑通用的学习方法。通用的学习方法是强大的,因为它们可以推广到许多不同的问题——专用的解决方案之所以有效,是因为它们适合于单一的任务。

4.重新实现一篇机器学习论文

这个策略来自吴恩达的演讲关于应用深度学习的细节

Ng 建议阅读和复制机器学习论文,这是专门针对机器学习研究人员的——他认为这最终会导致你自己的新想法(在大约 20-50 篇论文之后!).

即使你的目标不是机器学习研究,重新实现论文也是学习机器学习的最好方法之一。

数据科学和机器学习的一大挑战是有多少不同的技术可以用来解决问题。通过重新实现其他人的工作,你可以看到哪些技术经常被使用,以及它们是否真的有效

这种策略的一个重要步骤是访问原始数据集—这可能需要与论文作者进行交流(可能需要几周时间)。如果他们还能提供他们使用的任何代码,那就更好了——这对于检查原作者采取了什么步骤很有用。有时候重要的细节不会出现在报纸上!

你可能认为拥有代码库使这个项目变得容易——事实上,研究代码库通常是混乱的,并且包括许多研究人员用来尝试不同东西的代码,这些代码从未出现在论文中。

重新实现并不意味着你需要做和原始代码完全一样的事情。您可以构建不同的代码库,使用不同的数据或不同的库,例如在 Tensorflow 中完成工作,然后在 Pytorch 中重新实现。

你也可以考虑扩展这篇论文——在超参数上进行网格搜索或者尝试不同的架构。

重新实现机器学习论文的基本过程是:

  • 获得对原始数据集(或类似数据集)的访问权
  • 审查原始文件和代码库
  • 查看您能找到的其他重新实现
  • 决定绩效的目标水*

不要害怕与纸张的性能不完全匹配。研究人员经常可以使用免费计算,但对您来说可能不是这样!你想要展示的是良好的性能——如果你真的缩放了模型,它将与原始作品相匹配。

5.利用机器学习改进现有工作

离子年龄

之前的策略是利用现有的机器学习工作并重新实现它。这一战略是关于利用现有的工作并应用新技术——使用机器学习代替特定领域的方法,或者使用现代机器学习(如深度学习)代替经典的机器学习方法。

这不是简单的拿一篇机器学习论文,通过超参数调整来改进它——这里我们谈论的是做一些原始论文的作者从未考虑过的事情。

这种策略的步骤类似于重新实现一篇机器学习论文:

  • 获得对原始数据集(或类似数据集)的访问权
  • 审查原始作品(最好是学术论文和代码库)
  • 审查对原始作品的潜在新颖改进
  • 尝试改进

尽管作者会在论文中报告他们的解决方案的性能,但是您会希望重新实现他们的解决方案作为您的基线。这是为了能够将它与您的改进进行比较,并重现它们的结果。不要依赖于将你的结果与他们的打印结果进行比较。

这方面的一个很好的例子是所做的工作改善电池寿命的预测,其中汉尼斯·克诺布洛赫、阿德姆·弗伦克和温迪·张将深度学习应用于预测电池可以持续多少次循环的问题。他们还有一个优秀的 Github 库——非常值得一试。

6.管理数据集

影像网

机器学习的进步是由数据集&基准推动的。MNIST 和 ImageNet 与计算机视觉的进步同时出现并非巧合。这些数据集是研究人员比较算法和模型改进的基准,在 Scikit-Learn 或 TensorFlow 等框架中轻松访问它们的能力使他们的工作变得毫不费力。

贡献数据集是研究人员能做的最高尚的事情之一。这也很有挑战性,因为您需要考虑真实数据世界带来的所有混乱:

  • 在哪里得到它
  • 如何存储(CSV、JSON、SQLite)
  • 如何分享(S3)
  • 标签有多吵
  • 抽样有多大偏差
  • 数据集是静态的吗?如果不是,您将如何更新它

数据集管理的一个关键问题是从哪里获得来自的原始数据。你可能会在这里使用某种形式的网络抓取。您可能还需要一些领域知识来了解原始数据在哪里,以及它如何有助于解决问题。

另一个有趣的问题是要清理多少数据。像转换日期时间 it ISO 8601 这样的基本数据清理将受到欢迎,但填充缺失值可能会引入研究人员想要自己处理的噪声。最佳实践是包含原始数据和干净数据,这样用户就可以自己做出决定。

7.制造工具

工具形状研究方向

Yann LeCun

我们所有策略中最具挑战性的是建立一个工具。为什么构建一个工具很难?改进一个工具需要来自用户的反馈——人们实际上必须使用它来让你理解它是否解决了他们的问题。

另一个挑战是需要额外的技能,例如提供 REST API、命令行工具或 Python 包——这些技能通常在传统的数据科学工作流中不是核心的。然而,这些技能在数据科学中很有价值——即使你只是用它们来改进你自己的工作流程,你也不会后悔学习它们。

构建工具的好处有很多。除了扩展您的软件工程技能,它们还允许您更好地理解您使用的框架和库。

为现有的开源包做贡献

如果你想让你的工作产生影响,从头开始构建一个工具可能不是最好的选择。更有可能的是,贡献一个开源工具对这个世界更有用。这些贡献包括添加文档、编写测试、修复错误、重构或添加新功能。

为一个现有的开源工具做贡献是一个很好的回报方式。这也是了解这些工具如何在幕后工作的绝佳方式。最后,它可以在你的简历上看起来很棒。

您还将改进自己的代码。阅读他人的代码让你有机会探索你以前没有使用过的语言的特性,并看到不同的编码风格。看看优秀的读码了解更多读码的好处。

那么问题就变成了——你也应该贡献什么工具?在这里,我们建议与你的一个依赖者和解。经常用熊猫?去看看他们 Github 上的问题,看看他们需要做什么。

从头开始构建工具

虽然为现有的开源工具做贡献是做有用工作的最好方式,但这并不意味着你不应该从头开始编写自己的工具。构建自己的工具对学习很有帮助,因为你可以接触到项目的每个部分。

仅仅因为你不太可能建立新的 Keras,这并不意味着你不应该建立自己的深度学习库。除了被广泛使用之外,构建工具还有许多好处。

使用别人的工具意味着你不能从一开始就设计项目——意味着你不能实现程序的接口或核心逻辑。

如果您计划从头开始构建一个项目,首先从查看类似项目的源代码开始。坚持己见——复制你喜欢的,改变你不喜欢的。

摘要

这就是我们产生数据科学组合项目想法的七个步骤:

  1. 一场纸牌游戏比赛,
  2. 解决你关心的问题,
  3. 从一个环境开始,做控制,
  4. 重新实现一篇机器学习论文,
  5. 用机器学习改进现有工作,
  6. 管理一个数据集,
  7. 打造一个工具。

享受构建你的下一个项目——感谢阅读!

如果你喜欢这篇文章,请随时在媒体上关注我,或者在 LinkedIn 上与我联系。

如果你喜欢这篇文章,一定要看看:

https://betterprogramming.pub/should-you-be-using-pathlib-6f3a0fddec7e https://betterprogramming.pub/should-you-be-using-pathlib-6f3a0fddec7e

最初发表于https://www.datasciencesouth.com

根据欧盟值得信赖的人工智能蓝图,帮助您减少算法偏差的七个步骤

原文:https://towardsdatascience.com/seven-steps-to-help-you-reduce-bias-in-algorithms-in-light-of-the-eus-trustworthy-ai-blueprint-b348dc3cf2ae?source=collection_archive---------25-----------------------

偏见。每个人都有。每个公民都不想要那么多。每个算法都容易受到它的影响。以下是如何在您的数据科学项目中减少它。

作者图片

“BIAS 不是来自人工智能算法,而是来自人类,”Cassie Kozyrkov 在她的迈向数据科学文章什么是偏见?那么,如果我们是人工智能偏见和风险的来源,我们如何减少它?

不容易。认知科学研究表明,人类无法识别自己的偏见。由于人类创造了算法,偏见盲点将会成倍增加,除非我们创造系统来照亮、衡量风险并系统地消除它们。

欧盟指派了一个人工智能专业人员团队来定义一个框架,以帮助描述人工智能风险和偏见。欧盟人工智能法案( EU AIA )旨在为人工智能的人工代理和监督制定蓝图,包括鲁棒性、隐私、透明度、多样性、福祉和问责制的指导方针。

他们的建议是什么,对你的业务有什么好处?技术如何帮助人工智能的应用增加动力?他们推荐的七个步骤,以及如何实现它们的具体行动,是一个很好的起点。但首先,让我们回顾一下他们的“算法风险三角形”,它从最小到不可接受的范围来描述风险。

什么样的偏见是可以接受的?

正如 Lori Witzel 在 5 关于即将到来的欧盟人工智能法规你现在必须知道的事情中解释的那样,欧盟人工智能法案(EU AIA)根据其对社会的潜在危害定义了四个风险级别,因此必须加以解决。例如,在视频游戏和电子邮件垃圾过滤器中使用人工智能的风险与其在社交评分、面部识别和黑暗模式人工智能中的使用相比就相形见绌了。

来源: 制定关于人工智能的统一规则(《人工智能法》)并修正某些联盟法案

他们的框架有助于理解,但并没有规定对此做什么。该团队确实提出了人工智能可信度的七个关键原则,本文将其用作算法偏差缓解行动计划的指南:

原则#1:人员代理和监督。欧盟 AIA 团队表示,“人工智能系统应该赋予人类权力,让他们做出明智的决定,并促进他们的基本权利。与此同时,通过人在回路、人在回路和人在指挥的方法,需要适当的监督机制。”

他们没有规定怎么做。

Gartner 称之为模型操作化(Model Operationalization,简称 ModelOps)的技术为人在回路系统提供了便利。模型操作工具就像算法的操作系统。他们管理帮助算法运行最后一英里以供企业使用的流程。

ModelOps 工具提供了人类指挥工具,以确保人类能够代理和监督算法如何执行、它们的历史性能以及它们的潜在偏差。

算法分析帮助人类窥视算法的判断、决策和预测。通过分析算法元数据(关于人工智能数据的数据),人类观察者可以实时看到算法正在做什么。

下面的仪表板比较了两种算法的操作以及它们对评估贷款风险的银行算法的预测中涉及的因素。“冠军”模型的算法元数据是紫色的,而提议的“挑战者”模型是红色的。

在左上角,我们看到挑战者模型“更准确”但是代价是什么呢?

对模型元数据的分析有助于将人类置于循环中,对人工智能进行代理和监督。

右下角的横条显示了这两种算法是如何做出决定的。我们一眼就可以看出,生产算法比挑战者更重视以前的贷款拖欠和支付历史。我们还看到,挑战者模型更多地考虑贷款的规模,申请人有多少储蓄,以及信用历史。

来源:www.tibco.com

这是一个公*和*衡的风险评估吗?账户余额的衡量标准是否偏向经济上处于优势的借款人?在挑战者模型中,年龄是一个不太重要的因素;这样好吗?像这样的分析给了人类自己提问和回答这些问题的权力和监督。

原则#2:技术稳健性和安全性:欧盟 AIA 团队解释道,“人工智能系统需要具有弹性和安全性。它们需要安全,在出现问题时有后备计划,并且可靠和可复制。这是确保尽量减少和防止意外伤害的唯一途径。”

AI 有多种部署形式,每种部署都应该包括最新的安全性、身份验证、代码签名和可扩展功能,这些功能是任何企业级技术通常都包括的。这些包括但不限于双因素登录、安全模型和健壮的 DevOps 部署范例。

作者图片

所需的安全类型取决于部署地点。例如,部署到可穿戴设备的算法本身必须是安全的,以便该算法同样安全。有效的人工智能部署计划应用所有这些技术及其管理。

原则#3:隐私和数据管理。欧盟人工智能小组警告说,“人工智能系统还必须确保足够的数据治理机制,考虑数据的质量和完整性,并确保对数据的合法访问。”

敏捷数据结构提供对任何公司筒仓中的数据的安全访问,以保护数据并评估由 AI 模型采取或推荐的行动的结果。此数据结构必须符合法规中的隐私和数据保护标准,如欧盟的《一般数据保护条例》( GDPR)和加利福尼亚州的《加州消费者隐私法》( CCPA ),以及软件供应商的最佳实践软件开发 ISO 标准。

一个 gile 数据结构有助于确保算法提供可信的观察。

现代数据管理、数据质量和数据治理工具有助于促进这些需求,并且在考虑您的 AI 蓝图实施时必须加以整合。有关敏捷数据架构发展的更多信息,请阅读 techno-sapien.com 上的您的下一个企业数据架构

原则#4:透明:欧盟人工智能团队建议数据、系统和人工智能商业模式应该透明,可追溯性机制有助于实现这一点。此外,人工智能系统及其决策应该以适合相关利益相关者的方式进行解释。最后,欧盟人工智能建议人类意识到他们正在与人工智能系统进行交互,并且必须了解它的能力和局限性。

作者图片

透明度是适当的披露、文档和技术的结合。从技术上来说,数据结构和模型操作化工具通过变更日志和历史记录来跟踪和暴露数据透明度,以跟踪和回放 AI 模型的动作。这种数据和模型可追溯性,结合适当的披露和文档,有助于使所使用的数据、所做的决策以及这些决策的含义在整个组织中以及对客户和合作伙伴更加透明。

原则#5:多样性、不歧视和公*:必须避免不公*的偏见,因为它可能产生多种负面影响,从弱势群体的边缘化到偏见和歧视的加剧。欧盟人工智能团队建议,为了促进多样性,人工智能系统应该对所有人开放,无论是否有残疾,并让相关利益相关者参与他们的整个生命周期。

偏差缓解是一个强大的研究领域。正如诺贝尔奖得主心理学家和经济学家丹尼尔·卡内曼在 噪音 中解释的那样,减少偏见是很难的。但是解决方法就藏在人们的视线中,甚至在一些电视游戏节目中:问一个朋友。就是让别人给你鉴定!卡尼曼称这些人为“朋友”决策观察者。系统、过程和文化思维在算法偏差缓解这个话题上是至关重要的。

消除偏见很难。一个方便的方法是询问其他人。在 的喧嚣 中,丹尼尔·卡内曼称这些人为决策观察者。

敏捷数据结构和人工智能模型操作化工具的协作方面有助于提供围绕人工智能偏差分析、协作和缓解的团队合作,因此是实施人工智能欧盟蓝图时需要考虑的重要工具。

原则#6:社会和环境福祉:人工智能系统应该造福全人类,包括子孙后代。使用人工智能的公司应该考虑环境,包括其他生物,以及它们的社会和社会影响。采用欧盟人工智能的原则有助于形成一种经过深思熟虑的人工智能文化,这是追求这种福祉的重要一步。

原则 7:责任:啊哦!规定来了!也许吧。欧盟提供指导方针和原则的方法是一种建设性的替代方案,可以替代美国等国家经常采用的高压监管。欧盟人工智能团队提出了自我导向机制,以确保人工智能系统及其结果的责任和问责。

人工智能伦理的监管、监督和问责是一个庞大的课题。现代数据结构和模型操作化工具是新的人工智能文化的技术基础。他们承诺提高对算法风险和偏见的认识,并通过这样做,提高问责标准。

保险业的算法风险和偏差缓解

爱尔兰汽车协会专门从事房屋、汽车和旅行保险,并为人们在家中和路上提供紧急救援,每年处理超过 140,000 起汽车故障,其中 80%是现场修复的。

AA Ireland 开发算法来“识别欺诈和嵌入客户价值,然后在真实环境中更新这些模型。”

该仪表板显示了模型性能和对重定基准的诊断评估:对业务感兴趣的特定变量的预测。

来源:闭环持续学习案例研究:动态在线定价

AA Ireland 的首席分析官 Colm Carey 解释说:“保险业一直都有预测模型,但我们会建立一些东西,并在三个月内更新它。数据无中断地无缝进出模型,基本上提供了实时可预测性。与其说是预测,不如说是‘如果我提高或降低折扣,销量和盈利能力会有什么提升?’

这些原则帮助企业能够问:我应该做什么不同?我的算法应该如何改变?

“你可以了解市场中的全部机会和风险,并做出明智的决策。然后,你可以问:我应该做什么不同?我的定价应该如何变化?我应该如何在呼叫中心促进这一点?你可以理解这一切,再加上细分,欺诈建模,和保险商利润。我们将使用它来长期预测呼叫中心的容量和 CRM 建模、活动和投资回报,以及如何为产品定价。”

这个系统的结果恰恰创造了欧盟人工智能团队所建议的东西:人类指挥工具、实时评估和调整算法行为。

该系统通过吸收历史数据、佣金和参考数据(左上)来工作。数据和模型在 analytics / ModelOps 服务器(右上)上运行,以便根据客户的报价请求进行实时评分(左下)。

来源:闭环持续学习案例研究:动态在线定价

有关应用程序架构和更多可视化的详细案例研究,请在此阅读 AA Ireland 案例研究

人工智能信托蓝图:帮助人工智能造福所有人

欧盟集团的雄心是帮助 AI 造福全人类,包括后代。但是,和任何技术一样,它的使用需要仔细考虑和文化变革。欧盟蓝图和这些行动可以有所帮助。结合起来,它们为我们的算法风帆增加了风力,并确保我们与人工智能一起朝着公正和公*的方向前进。

资源

制作优秀数据科学简历的七个技巧

原文:https://towardsdatascience.com/seven-tips-for-crafting-a-great-data-science-resume-82281296f842?source=collection_archive---------15-----------------------

帮助您为下一份数据科学工作制作一份优秀、简短的简历

你好,朋友们!如果您关注了数据科学行业最*的发展,您可能会注意到最*就业发生了很大变化。随着许多公司在后 COVID 时代走向完全虚拟化,许多人正在重新评估他们目前的就业,以寻求更优惠的机会。(我不太愿意用“更好”这个词,因为“更好”是相对的。)

虽然我自己不在就业市场,但我想我会为所有考虑改变数据科学就业的人写这篇文章。在我看来,大多数简历都不是很好,因为它们倾向于遵循过时的“最佳实践”技术的发展已经改变了一些事情,像 LinkedIn 这样的地方允许一个人“吐槽”他们的整个工作经历,这意味着这在简历中已经没有必要了。

此外,我认为旧的简历提示根本没有抓住这一事实:人类是高度不理性的。至少在生活的某些方面,我们都是非理性的。虽然在为一个职位选择理想的候选人时,我们愿意认为自己是不理智的,但不理智的因素往往会下意识地渗透进来。正因为如此,许多这样的建议被写来解释这些不合理的因素。老实说,这里至少有一个我个人认为完全荒谬的提示。你一会儿就知道是哪一个了。

在我们开始学习这些技巧之前,我更新了我自己的个人简历,用一个具体的例子来说明如何采用这些技巧。除了是一名机器学习工程师,我还兼职做一些*面设计,并用 Affinity Designer 来制作我的简历。Affinity Designer 很棒,但就像它更臭名昭著的对手 Adobe Illustrator 一样,它是一个为更专业的图形设计用途而设计的工具。我个人认为这是值得考虑的,你可以考虑使用这个软件来创建基本的*面设计作品,非常非常方便。(例如,我所有的博客标题卡都是在 Affinity Designer 中创建的。)但如果你想让事情变得简单,我可能会推荐像 Canva 或 EnhanCV 这样的*台。

好了,让我们开始学习技巧吧!

由作者创建

1.把所有的东西都放在一页上。

回想一下之前关于技术如何改变人们的雇佣方式的评论,对于数据科学的候选人来说尤其如此。如果你今天申请一个职位,除了提交一份 PDF 格式的简历之外,很有可能会有一个类似表格的申请流程或从你的 LinkedIn 个人资料中抓取信息。此外,雇主很可能会通过编码练习之类的方式来评估你的技能,所以没有必要再在简历中确保你的技能和经验的每一个细节。雇主可能正在筛选一大堆这样的简历,所以你希望事情尽可能简单。你的简历没有理由超过一页。如果你像我一样安排事情,你可以在一页上得到很多信息!

2.让你的简历设计脱颖而出。

想想传统的普通简历。大多数传统的简历只是在白纸上写上黑色的文字。现在想象一下,如果你把所有申请人的传统简历挂在墙上,并在其中随机加入一份像我设计的简历。站在 30 英尺外,你能挑出哪份简历是我的吗?答案当然是肯定的!在 30 英尺外,你不可能阅读任何人简历上的任何文字(除非你有鹰一样的视力),但你可以大致了解一个人的设计。这就是我们开始看到人类非理性蔓延的地方。如果你给招聘经理或招聘人员一叠简历,他们会倾向于快速浏览简单、老式的简历,即使他们代表的是非常合格的候选人。他们更倾向于停留在一份特别设计的简历上,仅仅是因为…嗯,它看起来不错。再说一次,这是不理智的,但是因为我想看到你成功,如果我不提这件事,我会对你不利。说到不理智…

3.考虑不包括头像。

记得我在介绍中说过,这里有一个我认为很可笑的提示吗?这正是我所说的小费。再次指出非理性因素,人们不公*地根据外表来判断人。你会注意到我确实包括了我自己的自画像,那只是因为我认为我的摄影师朋友在我的头像上做了一个绝对完美的工作。一般来说,我不会认为自己是一个“传统上有吸引力”的人,所以如果我只是用智能手机自拍,我不确定我会把它包括在内。此外,我很幸运,因为我是一个年轻的人,即使这是完全非法的,我敢肯定,有一些雇主会掩盖一个人的简历,如果他们看起来更老。再说一次,这甚至是一个问题的事实让我沮丧不已,但我无法改变招聘人的想法。我只能帮助你,朋友们,在我们这个非理性的世界里精心制作你的简历。

4.确保清楚人们可以去哪里了解你的工作。

正如我们前面提到的,简历实际上只是雇主评估潜在候选人时要看的一整套东西中的一部分。在类似表格的申请中,雇主可能会要求你提供 LinkedIn 个人资料的链接,但以防万一,雇主不会确保这一点在你的简历中得到反映。特别是对于数据科学从业者,我会确保包括以下内容:

  • 你的 GitHub 简介:大多数技术型雇主都熟悉 GitHub,以及它能为应聘者提供的以代码形式展示工作的价值。我不打算在这篇文章中讨论这个问题,但是请确保你的 GitHub 简介是以这样一种方式组织的,即你的作品集清楚地反映了你希望雇主看到的东西。
  • 个人网站:老实说,我对这个有点警惕。我个人认为,只要你有扎实的 GitHub 和 LinkedIn 个人资料,那么就不需要个人网站。然而,我建议你获得自己的域名,至少让它指向类似链接树的东西。这需要最少的努力,并允许雇主无缝导航到你想让他们看到的任何内容。
  • 其他数据科学方面的事情:我在这里想的是像 Kaggle 竞赛或发表关于数据科学的文章之类的事情。作为一个有面试一家财富 50 强公司的机器学习工程师候选人经验的人,我可以告诉你,我个人从来没有面试过展示这些额外东西的人,这没关系。我不一定期望看到这些,但我可以告诉你,他们肯定会锦上添花!

5.如果你缺乏经验,突出一两个个人项目。

对于那些刚刚进入数据科学领域的人来说,这是一个超级重要的提示。作为一名数据科学编码训练营的导师,我目睹了从那里出来的学生如何努力想知道在简历上写下什么经历。我认为在简历上至少写上一两个以前的职位是很重要的,这只是为了显示你有工作经验,但是如果你过去的 8 份工作都是在餐馆之类的地方,我不会把它们都列出来,这样可以节省简历的空间。如果你的简历上有多余的空间,我会强调一两个个人数据科学项目。当您描述该项目时,请确保包括以下内容:

  • 项目简介:关于项目总体目标的两三句话
  • 项目是如何成功的:对于我的数据科学训练营学员来说,他们的项目通常会寻求对世界产生某种积极的影响,无论是直接对公司还是以更加“开源”的方式。我绝对鼓励强调项目的成功,因为这有助于雇主理解该项目在数据科学领域是值得追求的。
  • 用于支持项目的技术:这可以是你使用的东西的简单列表,包括 Python 库、开源工具、云*台等等。例如,您可以简单地列出这样的内容:“使用的技术:Pandas、Scikit-Learn、FastAPI、AWS SageMaker”

6.确保你的简历符合招聘公司的目标。

这一点尤其重要,因为数据科学职位可能相当模糊。一些职位更接*于普通数据分析师,这些职位更侧重于数据收集和数据清理。其他职位可能更侧重于建立预测模型。其他人,比如我自己的机器学习工程师职位,可能会更多地寻找软件工程背景。无论是哪种情况,你都可能需要稍微修改一下你的简历,以更好地适应公司的需要。以下是我可能会针对不同类别的数据科学职位强调的一些技能和属性:

  • 数据分析师/数据工程师 : SQL、Pandas、特征工程、Spark (PySpark)、Hadoop、NoSQL 数据库
  • 数据科学家:应用统计学、预测建模、Pandas、Scikit-Learn、PyTorch、Tensorflow、Jupyter
  • 机器学习工程师 : CI/CD(如 GitLab、Jenkins)、FastAPI / Flask、Docker、Kubernetes、AWS、Terraform

7.不要害怕分享一点你的个性。

大多数数据科学职位在招聘潜在申请人时都有一个多步骤的流程。这些步骤通常包括某种编码练习、一次或多次电话面试,并且通常以“面对面”面试告终。(“亲自”在引号中,因为大多数最终面试现在已经虚拟化了,尤其是在新冠肺炎之后。)如果一名候选人进入了最后一轮面试,他们通常与其他进入最后一轮的候选人一样合格。换句话说,雇主雇佣任何进入最后一轮的候选人通常都不会错。

这就是非理性再次发挥作用的地方。如果两个人条件相当,你如何确定你想雇佣谁?如果你听说过“机场规则”,这条规则基本上是这样的:如果你不得不和某人一起被困在机场很长一段时间,你更愿意和谁一起度过这段时间?这就是为什么我认为分享个性很重要,因为对于这最后一轮面试来说,这真的是让你得到这份工作的区别因素。再说一次,这并不完全合理,但这是这个世界的运行方式。我对这张照片不像对大头照那样沮丧,因为性格可以显示一个人在团队中的表现,这确实是一个重要的因素。

我们的提示到此结束!你会给这个列表添加什么?我很想听听你是如何在求职中获得成功的。祝你在追求下一个数据科学职位时一切顺利!

在数据科学世界中保持有序的七个技巧

原文:https://towardsdatascience.com/seven-tips-for-staying-organized-in-the-data-science-world-f616c40b25ab?source=collection_archive---------34-----------------------

办公时间

通过组织日常实践,帮助您优化工作流程

在我作为机器学习工程师(MLE)的日常工作中,我玩了很多球。我支持生产中的几个模型,积极参与许多新的建模工作,作为管理员参加我们区域的定期“技能团队会议”,并担任我的 MLE 团队的 scrum master。我总是对任何请求说“是”的人,并且非常乐意帮助遇到困难的队友。

可能让你吃惊的是,我并不认为自己是一个非常忙碌的人。

别误会,我一直都很忙。(如果我的经理正在读这封信,我并不是在为工作而难过!😂)我只是从来没有忙到“撕头发”的地步。如果你不知道我的背景,我在数据科学世界里有点反常。在成为机器学习工程师之前,我从事纯粹的商业工作。我的硕士学位是组织领导,我拥有几个领导/管理头衔。

也就是说,我已经能够延续我在以前的生活中采用的思维模式,帮助我在目前的 MLE 角色中取得成功。说真的,如果不把这些都记在心里,我就无法保持目前的工作*衡。知道数据科学家和 mle 经常保持繁重的工作量,我希望你发现这一套技巧很有价值!

1.把你的饭桶收拾好。

为组织创建系统是我喜欢在生活的方方面面做的事情,我发现这对于组织我的代码非常有益。我所有的回复都是以同样的方式概述的,所以如果我从一项工作转到另一项工作,我确切地知道在哪里可以找到某些信息。如果您想得到额外的乐趣,您甚至可以提出一个 Cookie Cutter 模板来在初始化时自动化您的 Git 存储库的结构。一般来说,我用以下目录组织我的回购:

  • 数据:这包含了我工作所需的数据(如果不在共享位置的话)。
  • 模型:顾名思义,这里面包含了我保存的模型文件。
  • 依赖关系(Dependencies):这包含像 Python 需求文件和其他支持我在生产环境中工作所需的东西。
  • 测试:这个目录存放了我用于测试目的的脚本,从单元测试到集成测试。它还包含一些测试 JSON 文件,以防我需要在生产环境中测试实时 API。
  • 我在 Docker 容器中做了很多工作(我鼓励你也这样做),所以这个目录包含了所有需要的工作文件,以支持我在 Docker 映像中需要做的任何事情。例如,这个目录将包含启用类似 Flask API 的文件。
  • 笔记本:如果我需要在 Jupyter 笔记本上做与发现相关的工作或“概念验证”工作,我会把它们都放在同一个目录下。
  • K8s / Terraform :根据我是在 Kubernetes 还是 AWS 中工作,我创建了一个目录来存放适当的文件,这些文件构建了我在各个环境中需要的资源。

2.集成适当级别的日志/警报。

这对于生产中的事情来说更是如此,但是如果您在预测模型中建立适当的日志记录或警报,您可以使您的生活变得更加轻松。业务伙伴经常问我关于传递到特定模型的输入数据的问题。对于正在进行的模型验证,您应该这样做,但是我通过创建更适合这种情况的单独日志来更进一步。例如,如果一个模型接受 100 多个特征作为输入,那么保存一个不同的日志文件可能是有意义的,该文件只包含 10 个经常被质疑的特征。以后解析起来会容易得多!

说到警报,我想到的是您可以集成的主动措施,而不是被动措施。例如,您可能有一个仪表板或被动地告诉您模型如何执行的东西,但我喜欢集成电子邮件警报,它会告诉我某些东西是否真的出了问题。这样,我就不必总是记得检查那些被动的东西,因为重要的东西都是通过电子邮件发给我的。说到电子邮件…

3.采用“零收件箱”理念。

这是你以前可能听说过的东西,我发现它在我作为机器学习工程师的角色中特别有价值。简而言之,这个想法就是让你的收件箱尽可能的干净。一旦你读了一封电子邮件,你应该把它放在一个合适的文件夹里。由于每个现代电子邮件提供商都提供“搜索”功能,我把我的电子邮件分类到相当高的“桶”中我不能分享我的工作包括什么,但我会告诉你,我只定期在 5 个文件夹中归档东西。通过保持收件箱的整洁,你保证了你将会看到所有的东西,并且能够及时地处理它们。

4.将您的代码编写到适当的水*。

虽然有些人可能主张创建类和相关方法总是最佳实践,但我实际上不同意。我认为通过只采用你的项目所需要的元素来“调整”你的代码是更合适的。例如,如果你有一个对象或动作将被一遍又一遍地重复使用,那么无论如何都要为它创建一个类或函数。但是如果你做的事情只会被使用一次,那么我认为创建一个类/函数会引入不必要的复杂性。相信我,如果你总是试图做“正确的”事情,它会很快变得令人困惑。

5.总是注释你的作品。

一个伟大的程序员在仔细检查代码时总是知道代码在做什么,但在第一次阅读时并不总是很清楚。为了帮助别人以及健忘的我,我总是用代码注释来注释我的工作,以便确切地知道我的代码在做什么。它还有助于更快地提高代码的可读性。例如,您可能有 5-10 行代码在进行特定的数据转换。您可以编写一个简单的带注释的注释来通知您这一点,稍后当您想要引用某个内容时,您可以快速浏览大量代码来找到您想要的内容。

6.写下你需要在一周内完成的事情。

每周一,我都会花 30 分钟来分析我需要做些什么来完成给定的一周,以此开始我的一周。我用一块实体白板来做这件事,每完成一项,我就核对一下。我建议每周只做一次,不要每天做,因为每天做有点麻烦,而且你通常对一周的开始有一个很好的想法。

7.了解你的优先事项。

这应该是另一个显而易见的问题,但是我仍然很惊讶我经常看到这种情况发生。人们经常忙到“抓狂”的地步,因为他们没有按照适当的顺序处理事情,并且有东西偷偷靠*咬他们。通过了解你的优先事项,你将能够以适当的方式组织你的工作日(或工作周),以确保每件事都按时完成。

这篇文章到此结束!希望您发现这对于在这个有趣的数据科学世界中组织您的生活很有价值。你还有什么要补充的吗?我一直在寻求优化我的工作流程,所以我很想听听你的分享!

2021 年将探索 Python 中七个未被充分利用的数据科学包

原文:https://towardsdatascience.com/seven-underutilized-data-science-packages-python-2021-81b2d85bcaef?source=collection_archive---------17-----------------------

有用的 python 包,在数据科学和数据清理领域不太流行。

介绍

Python 有大量的包。它包括从普通任务到高级任务。不知不觉中,我们经常在应用程序中使用大量的包。本文讨论了一些用于数据清理、应用程序开发和调试的未被充分利用的数据科学包。

https://xkcd.com—来源

骗子

生产环境通常有实时数据。让它进入测试环境并不容易。我们必须将来自生产环境的数据标记到测试环境中。这通常会将数据转换成胡言乱语。

此外,在欺诈行业,我们需要找出欺诈身份。为了生成一个假的 PII(个人身份信息),我使用了一个名为 Faker 的包。这是一个很酷的软件包,可以让你用地址、姓名等创建一个假的 PII。

作者图片

以上是一些假数据的例子。假数据与甘假图像可以给一个像真的人。

假数据—表格甘

如果您想要生成类似的实时生产数据,那么您可能需要使用 GAN。查看下面关于表格 GAN 的文章。

https://medium.com/make-money-with-code/generating-synthetic-tabular-data-using-conditional-tabular-gan-on-an-imbalanced-dataset-smote-f4f921e9c716

Pywebio

我绝不是前端开发者。Flask 适用于 Python 端的表单、UI 和 Rest API。然而,如果我想要一个简单的表单,这就有点过分了。简单的东西不学前端。

这就是 Pywebio 前来救援的地方。它为次要任务创建了一个简单、干净的用户界面。所有代码都是用普通 python 写的。所以不需要学习任何新的东西!

输出—按作者分类的图像

在几秒钟内,它转换成一个前端 UI 网页。我们还可以编写一些会话,处理输入和输出。查看他们的文档获取详细信息。

气流

我最喜欢的包之一是气流。Airflow 是一种工作流管理工具,在 MLOPS 中经常被低估和较少使用。它还可以用于特定的执行间隔、重新训练模型、批处理、抓取网站、投资组合跟踪、自定义新闻提要等。

谈到工作流程,选项是无限的。它还可以连接到特定服务的云提供商。代码可以用 python 写,执行可以在 UI 看到,很棒。还可以按特定的时间间隔安排工作流。

查看我关于如何使用气流的文章。

洛格鲁

我讨厌但不得不使用的一件东西是一个记录器。Logger 是调试应用程序的最佳方式之一。但是,原木里面的印子太多了,我很讨厌。洛格鲁在某种程度上是来救援的。它不能解决所有的挑战,但是,添加日志语句和更多的调试是很容易的。

from loguru import logger

logger.debug("That's it, beautiful and simple logging!")

它还有助于分割文件和执行清理,所以我们不需要进入所有的历史日志。

logger.add("file_1.log", rotation="500 MB")    # Automatically rotate too big filelogger.add("file_2.log", rotation="12:00")     # New file is created each day at noonlogger.add("file_3.log", rotation="1 week")    # Once the file is too old, it's rotated

logger.add("file_X.log", retention="10 days")  # Cleanup after some time

logger.add("file_Y.log", compression="zip")    # Save some loved space

您还可以使用参数回溯来回溯执行。

简而言之,在生产环境中拥有这个包来调试您的应用程序或 AI 模型训练是值得的。

皮达什

经常在数据清洗或处理中,我们要处理大量的数据清洗。这些是一些较小的项目,需要时间。例如,如何将列表的列表扁*化?是的,你可以写一个清单理解。如果有快捷的功能来执行这些呢?

这就是 Pydash 的闪光点。它成为了我的快速转到库,包含了一系列 python 实用程序。

我的常用-作者图片

以上只是一个小例子;它包含了很多功能。我肯定会推荐查看文档

权重和偏差

WANDB 是跟踪和可视化机器学习管道所有部分的最有用的包之一。我最喜欢的部分是他们的中央仪表盘。它类似于一个记录器,可以做更多的事情。

启动运行-按作者排序的图像

执行后的图表—作者提供的图像

它易于使用,并与最流行的库(如 Tensorflow、PyTorch、fastai、huggingface 等)集成。但是,在业务领域使用它时,您会受到一些限制,并且您必须切换到付费订阅。除此之外,这是一个非常好的库。

PyCaret

我最喜欢的 R 包之一是 caret 包。看到 PyCaret 包的时候很激动。当你想快速做某事时,它简化了许多编码。该软件包有大量的默认参数选项,可以运行不同度量点的各种模型。

不同的模型-作者的图像

最后的想法

正如文章中所讨论的,我们已经看到了应用程序开发或数据分析中使用的不同的包。这绝不是一份详尽的清单。我会继续添加更多的包。如果您使用任何其他经常未被充分利用的包,请在评论中告诉我。

加入 200+人 上我的 简讯 获取工作代码等更新的文章和书籍。

Python 中的几种模型验证技术

原文:https://towardsdatascience.com/several-model-validation-techniques-in-python-1cab3b75e7f1?source=collection_archive---------17-----------------------

四种流行的交叉验证技术的综合指南

karlyukav 创作的男子照片—www.freepik.com

我想写这篇文章,因为我认为很多人倾向于忽略机器学习的验证和测试阶段。类似于实验设计,花足够的时间和使用正确的技术来验证你的 ML 模型是很重要的。模型验证远远不止 train_test_split(),如果你继续读下去很快就会发现!

但是首先,什么是模型验证?

模型验证是一种检查模型的预测与现实有多接*的方法。同样,模型验证意味着计算您正在训练的模型的准确性(或评估的度量)。

有几种不同的方法可以用来验证您的 ML 模型,我们将在下面深入探讨:

1.使用 Gradio 进行模型验证

虽然这不一定是一种技术,但我认为这是一个额外的收获,因为它可以作为几乎任何您创建的 ML 模型的额外的验证步骤。

大约一个月前,我遇到了 Gradio,我一直是它的大力支持者,这是理所当然的。它非常有用,原因有很多,包括能够用您自己的输入来验证和测试您的模型。

我发现 Gradio 在验证我的模型时非常有用,原因如下:

  1. 它允许我交互式地测试模型的不同输入。
  2. 它允许我从领域用户和领域专家(他们可能不是编码人员)那里得到反馈
  3. 它需要 3 行代码来实现,并且可以通过公共链接轻松分发。

这种类型的“验证”是我经常在以下验证技术之上做的事情…

2.培训/验证/测试分割

这种方法是模型验证中最常用的。这里,模型的数据集分为训练、验证和测试样本。所有这些集合定义如下:

训练集:模型训练的数据集。所有的学习都发生在这组数据上。

验证集:该数据集用于调整从数据集训练的模型。这里,这也是选择最终模型来使用测试集进行测试的时候。

测试集:根据测试集测试模型的概化能力。这是评估的最后阶段,因为它给出了模型是否准备好用于实际应用的信号。

该方法的目标是检查新数据的模型行为。数据集被分成不同的百分比,这主要取决于您的项目和您拥有的资源数量。

下图清楚地展示了这个例子。

作者创建的图像

以下 python 代码实现了此方法。训练验证测试集合将分别占总数据集的 60%、20%和 20%;

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=1)X_train, X_val, y_train, y_val = train_test_split( X_train, y_train, test_size=0.25, random_state=1)

这种方法并不适用于每种情况,它有优点也有缺点。

优点:

  • 实现起来非常简单。
  • 与其他方法相比,执行速度相对较快。

缺点:

  • 对于小数据集的模型,如果每个数据集中没有足够的数据点,这种方法会降低精度。
  • 对于准确的评估指标,分割应该是随机的,否则会变得不准确。
  • 它会导致模型过度适应验证集。

3.k-折叠交叉验证

K-fold 交叉验证解决了训练/测试分离的所有问题。使用 K 折叠交叉验证,数据集被分成 K 个折叠或部分,每个折叠被用作某个位置的测试集。

例如,假设有一个 4 重交叉验证集-有四重,模型将被测试四次,其中每个重用作测试集,其他重用作训练集。然后,模型的最终评价就是简单的所有 k 次测试的*均值。下图清晰地展示了这一过程。

作者创建的图像

下面是如何用 Python 实现大小为 5 的折叠:

from sklearn.datasets import load_iris
import pandas as pd
from sklearn.model_selection import KFold
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_scoredata = load_iris(as_frame = True)
df = data.frame
X = df.iloc[:,:-1]
y = df.iloc[:,-1]kf = KFold(n_splits=5, random_state=None)
model = LogisticRegression(solver= ‘liblinear’)acc_score = []for train_index , test_index in kf.split(X):
   X_train , X_test = X.iloc[train_index,:],X.iloc[test_index,:]
   y_train , y_test = y[train_index] , y[test_index] model.fit(X_train,y_train)
   pred_values = model.predict(X_test) acc = accuracy_score(pred_values , y_test)
   acc_score.append(acc)avg_acc_score = sum(acc_score)/kprint(‘accuracy of each fold — {}’.format(acc_score))
print(‘Avg accuracy : {}’.format(avg_acc_score))

这种方法有以下优点和缺点:

优点:

  • 这种方法生成的评估指标更加真实。
  • 很大程度上解决了过拟合问题。
  • 这导致偏差减小。

缺点:

  • 因为需要做更多的计算,所以需要大量的计算能力。
  • 同样,所需的时间也更长。

4.留一交叉验证

留一法是 K 折叠验证的一种特殊情况,在这种情况下,训练集将所有实例减去数据集的一个数据点,而测试集将剩余的观察结果留在外面。假设我们有一个 M 个实例的数据集,训练集是 M-1,测试集是 1。

这解释了这种方法的名称。在 LOOCV,K=N,其中为数据集中的每个实例创建并评估一个模型。由于每一个瞬间都被用于该过程,这消除了对数据采样的需要。

它的 python 实现如下所示:

from sklearn.datasets import make_blobs
from sklearn.model_selection import LeaveOneOut
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score**# create dataset**
X, y = make_blobs(n_samples=100, random_state=1)**# create loocv procedure**
cv = LeaveOneOut()**# enumerate splits**
y_true, y_pred = list(), list()
for train_ix, test_ix in cv.split(X):
 **# split data** X_train, X_test = X[train_ix, :], X[test_ix, :]
   y_train, y_test = y[train_ix], y[test_ix]
   **# fit model** model = RandomForestClassifier(random_state=1)
   model.fit(X_train, y_train)
   **# evaluate model** yhat = model.predict(X_test)
   **# store** y_true.append(y_test[0]) 
   y_pred.append(yhat[0])**# calculate accuracy**
acc = accuracy_score(y_true, y_pred)
print('Accuracy: %.3f' % acc)

优点:

  • 通过省去一个交叉验证,可以生成高度准确和无偏的模型。
  • 我们不必把数据分成随机样本。
  • 它非常适合较小的数据集。

缺点:

  • 这是 k-folds 交叉验证计算量最大的版本,因为模型需要拟合 M 次。
  • 它不适合较大的数据集。
  • 均方差会因测试数据的单一瞬间而变化,这会导致更高的可变性(高方差)

4.分层 K 倍交叉验证

分层 k-fold 方法是主要用于分类问题的简单 k-交叉验证的扩展。这种方法中的分裂不像 k 交叉验证那样是随机的。分层确保每个折叠都代表数据的所有层次,具体来说,它旨在确保每个测试折叠中每个类都得到同等的代表。

让我们以一个简单的分类问题为例,其中我们的机器学习模型从图像中识别出一只猫或一只狗。如果我们有一个数据集,其中 70%的图片是猫,另外 30%是狗,在分层的 k 折叠中,我们将为每个折叠保持 70/30 的比例。

当我们有较小的数据集并且我们必须保持类比率时,这种技术是理想的。有时,数据会过采样或欠采样,以符合要求的标准。

python 实现的工作方式如下。Sklearn 为我们提供了 StratifiedKFold 函数。

import numpy as np
from sklearn.model_selection import StratifiedKFoldX = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([0, 0, 1, 1])skf = StratifiedKFold(n_splits=2)
skf.get_n_splits(X, y)print(skf)for train_index, test_index in skf.split(X, y):
   print(“TRAIN:”, train_index, “TEST:”, test_index)
   X_train, X_test = X[train_index], X[test_index]
   y_train, y_test = y[train_index], y[test_index]

这种方法的利弊如下:

优点:

  • 它适用于具有少量训练样本和不*衡数据的数据集。
  • 阶级比例保持不变。

缺点:

  • 这不是回归问题的理想方法。
  • 它努力处理更大的数据集以获得最佳结果。

感谢阅读!

在本文中,我们看到了不同的模型验证技术,每种技术都服务于不同的目的,并且最适合不同的场景。在使用这些验证技术之前,请始终考虑您的计算资源、时间限制和您试图解决的问题类型。

一如既往,我祝你学习一切顺利!😃

不确定接下来要读什么?我为你挑选了另一篇文章:

又一个!

特伦斯·申

  • 如果你喜欢这个, 跟我上媒 了解更多
  • 有兴趣合作吗?让我们连线上LinkedIn
  • 报名我的邮箱列表 这里

性、毒品和有机主题建模

原文:https://towardsdatascience.com/sex-and-drugs-and-organic-topic-modeling-91a9776d32e6?source=collection_archive---------18-----------------------

用 GPT J 分析摇滚歌曲的歌词

性、毒品和有机主题建模,作者提供的图表

问题:摇滚歌词中最常见的话题是哪个?

回答:甲壳虫乐队在他们的歌中总结道,“你所需要的只是爱。”

作为主题建模的实验,我使用最新的人工智能系统分析了 50 个摇滚乐队的 12,000 首歌曲。本文将介绍我使用的过程,并解释所有的组件,包括运行在 Google Colab 的 TPU GPT j 上的 GPT 3 的免费版本。请注意,您可以使用这些技术来查找和分析任何文本数据集中的主题。

RockTopics 概述

这是这个实验的高级图表,我称之为 RockTopics。在简要讨论了主要组件之后,我将在下面的小节中更详细地解释处理步骤。

RockTopics 组件,作者图解

我从我在 Kaggle 上找到的 128K 歌词数据库开始,我通过找到它与滚石杂志上 100 个最伟大的摇滚乐队列表的交集来过滤歌曲的数量。这产生了来自 50 个乐队的 13K 首歌曲。

该系统的核心是开源的 GPT-J 转换器,它是使用 Pile 上的网格转换器 JAX 训练的,Pile 是一个大型英语文本语料库。我把每首歌的歌词一行一行输入 GPT J,用几个简短的提示找到每一行的主题。

我使用谷歌通用句子编码器将每个发现的主题转换成一个 512 个数字的数组。然后,我结合使用 TSNE 降维和 k-means 聚类来分析主题,并使用 matplotlib 生成图表。

根据分析,以下是最常见的话题。注意,相似的主题聚集在一起,圆圈的大小代表歌词中出现的次数。

摇滚话题,作者图片

系统组件

以下部分详细描述了我使用的组件和过程。

歌词数据库

对于歌词,我找到了一个不错的数据集,作者是巴西的人工智能研究员安德森·尼斯(Anderson Neisse)。该数据集包含来自 6 个流派的 2940 个乐队的 128083 首歌曲。他在数据库内容许可下发布了数据集。

正如我上面提到的,我用《滚石》杂志的 100 位最伟大的录音艺术家名单过滤了歌曲列表。结果列表有来自 50 个乐队的 11,959 首歌曲,包括披头士、鲍勃·迪伦、猫王、滚石、查克·贝里和吉米·亨德里克斯。总共有 185003 行歌词。

GPT J

GPT-J 是一个人工智能模型,用于分析和生成使用网格转换器 JAX 训练的文本,这是一个使用并行处理训练大型模型的可扩展系统。该模型在一个名为 Pile 的大型文本语料库上进行训练,这是一个 825 千兆字节的英语文本数据集,旨在训练大规模的语言模型[1]。

GPT-J 是由 EleutherAI 创建的,这是一个致力于开源人工智能研究的草根研究人员集体。该系统模仿 OpenAI 的 GPT-3,但 GTP-J 在 Apache 2.0 开源许可下可以免费使用。

你可以在这里免费试用 GPT J,https://6b.eleuther.ai/

EleutherAI 的 GPT J,作者图片

如你所见,它已经知道了摇滚歌曲中的头号话题。接下来,我会告诉你如何找到歌词中每一行的主题。

在歌词中寻找主题

与其他大型 transformer 模型类似,GPG-J 的工作方式是传入一个提示,结果系统会生成连续的文本。我使用下面的提示从歌曲的每一行获取主题。请注意,这被称为“少量”推理,因为给出了几个例子。

**Determine the topic for these lyrics.****Line**: Ah, look at all the lonely people!
**Topic**: Loneliness**Line**: Wiping the dirt from his hands as he walks from the grave.
**Topic**: Death**Line**: Little darling, the smiles returning to the faces.
**Topic**: Happiness**Line**: Every breath you take.
**Topic**:

第一行是对查询的一般描述,后面是三个示例行和主题。该系统将使用这些信息来获取所提问题的要点,并为最后一行“你的每一次呼吸”指定主题多次运行该查询将得到主题“呼吸”、“健康”、“生命”等。

以下是警察的《你的每一次呼吸》前五行的题目。

**Line                     Topic**
Every breath you take    Breathing
Every move you make      Movement
Every bond you break     Leaving
Every step you take      Walking
I'll be watching you     Watching

这个系统似乎做得很好,为台词找到了主题。注意,不仅仅是拉关键词。它总是以名词的形式陈述主题,有时会概括该行的意思来找到主题,就像它对离开和行走所做的那样。

请注意,我发现对每个查询使用相同的示例有时会将示例主题“孤独”、“死亡”和“幸福”泄漏到结果中,从而增加它们的数量。为了最大限度地减少泄漏,我从中间结果中挑选了一个包含 300 个示例的列表,并编写了一些代码来为每个查询从大量的列表中随机选择三个示例。这似乎已经将渗漏减少(或分散)到统计上不显著的水*。

我发现,使用 OpenAI 的 GPT-3 达芬奇-指导-贝塔模型,使用“零射击”查询,意味着没有提供示例,可以完全避免泄漏问题。下面是提示。

**Determine the topic for this line of lyrics.
Line**: Every breath you take.
**Topic**:

结果类似于 GPT J,没有任何泄漏,因为没有例子。这种方法是首选的,但它是有代价的。虽然使用 GPT-3 的付费版本运行这个查询只需要 0.0017 美元,但在 185,000 条线路上运行它需要 300 多美元。

张量处理单元

张量处理单元,图片来源:谷歌博客

在过去的 18 个月里,我一直在使用 Google Colab 来运行我的人工智能实验。我一直在使用两种类型的处理器,中央处理器(CPU)和图形处理器(GPU)。CPU 是自 20 世纪 60 年代以来就存在的通用计算机。GPU 是在 20 世纪 80 年代为图形密集型操作开发的,并从 2010 年开始用于人工智能和 ML。

2016 年,谷歌推出了他们的张量处理单元 (TPU),专门为训练和运行人工智能模型的实例而设计。自 2020 年以来,它们已经可以在谷歌 Colab 上使用。王禹带领一个来自哈佛的团队在 GPU 和 TPU 上测试人工智能模型的速度。他们发现,在运行大型模型时,TPU 的性能比 GPU 高出 3 到 7 倍[2]。

我用于运行 GPT-J 主题建模的 RockTopics Colab 是基于来自王贲 EleutherAI 的 TPU Colab 。每一行花了大约 1.4 秒,运行了大约三天来获得所有 185,000 行歌词的主题。

通用句子编码器

在我收集了主题之后,我使用 Google 的通用句子编码器将每个主题短语转换成嵌入的 512 个浮点数的数组。这里有一些示例代码来展示它是如何工作的。

import tensorflow_hub as hub
embed = hub.Module("https://tfhub.dev/google/universal-sentence-encoder-large/5")
embedding = embed(["love loss"])
print(embedding)

结果在这里。

tf.Tensor( [[-2.79744454e-02 -6.52119750e-03 1.32698761e-02
4.50092048e-04 9.81796882e-04 3.18628997e-02 2.73146853e-02
-1.10505158e-02 -2.71893758e-02 -5.06720766e-02 -3.20894904e-02
...
-1.08678043e-02 7.85474479e-03 -6.44846493e-03 -3.88006195e-02]], shape=(1, 512), dtype=float32)

虽然这些数字对人类来说没有任何意义,但它们代表了编码器多维空间中“失恋”的概念。在接下来的部分中,我将向您展示我是如何使用统计学来理解这些主题的。

降维

在每个嵌入中都有大量的信息。然而,我使用的第一步是降维(DR)来图形化地显示主题嵌入。这将通过将每个主题的维度数量从 512 个减少到两个来创建二维图表,从而帮助可视化数据。

DR 的两种标准方法是主成分分析(PCA)和 T 分布随机邻居嵌入(TSNE)。每种方法都试图保留数据的要点,同时减少维数。

PCA 获取数据,将其转换为矩阵,使用一些复杂的数学运算来找出最显著的方差,然后将其转换回数据集。TSNE 的工作原理是,在将输入数据点和表示相同数据点的数据点转换成低维表示后,迭代地最小化它们之间的差异。你可以在 Luuk Derksen 的文章中阅读更多关于 PCA 和 TSNE 方法的内容。

当使用主成分分析和 TSNE 从 512 个维度减少到两个维度时,前 100 个主题看起来像这样。每个圆圈的大小代表该主题在一行歌词中被发现的次数。你可以点击图片查看大图。

PCA 和 TSNE 降维后的摇滚话题,作者图片

你可以看到主成分分析减少了更紧密的集群,而 TSNE 减少了更多的主题。虽然 PCA 简化有一个更有趣的整体分组,但它使阅读主题标签变得困难,因为它们经常堆叠在另一个之上。总的来说,我觉得 TSNE 的简化更容易阅读。

确定图表的方向

在看图表时,你可能会问为什么主题在它们的空间位置上?虽然相对位置有意义,但整体空间方向是任意的。通用句子编码器在 512 维空间中指定短语含义的位置。尽管 DR 算法试图保持空间的一致性,但并不能保证任何特定的主题会落在任何特定的地方。

为了使图形的方向更加可预测,我任意选择主题时间来确定 X 轴的方向,主题音乐来确定 Y 轴的方向。下面是运行方向代码前后的图形。

摇滚主题定位,作者图解

图形定向后,时间话题现在在三点钟位置,音乐话题大致在 12 点钟位置。图定向的源代码是这里的。

k 均值聚类

你可能已经注意到有些主题是同义词。比如可以看到等。,作为单独的主题。

为了组合相似的主题,我使用了一种叫做 k-means 聚类的算法。该算法旨在将 n 个样本分成 k 个聚类,其中每个样本属于具有最*均值的聚类。

下面是使用 k-means 将数据减少到 50 个聚类后主题的样子。

摇滚话题群,作者图片

你可以看到相似的主题被有效地分组在一起,像主题如何合并成合并成等等。

这里有一张图表,显示了按歌词主题*均值排列的乐队。圆圈的大小代表他们的歌曲目录中的行数。

按乐队分类的主题,按作者分类的图片

看到你最喜欢的乐队登陆是相当有趣的。有些分组是有道理的,比如看到布鲁斯·斯普林斯汀挨着埃尔维斯·考斯特罗。但不知何故,沙滩男孩夹在电台司令和涅磐之间。我没想到会这样。

讨论和后续步骤

使用大型 transformer 模型进行有机主题建模似乎可以很好地处理大型数据集。在 Google Colab 上运行 GPT-J 是一种经济高效的分析方法。我可以尝试的下一件事是微调 GPT-J,在不指定例子的情况下找到主题,消除例子泄漏的问题。

另一个项目是观察这种主题建模技术与其他方法相比有多好。例如,我可以在 20 个新闻组数据集上运行它,看看它与最先进的系统双向对抗训练(BAT)[4]相比如何。虽然 BAT 方法使用一个较小的模型来执行主题建模的特定任务,但是我使用大型 transformer 模型的方法可以利用一般知识来产生更好的结果。

源代码和 Colabs

这个项目的所有源代码都可以在 GitHub 上找到。我在 CC BY-SA 许可下发布了源代码。

归属共享

感谢

我要感谢詹尼弗·林和奥利弗·斯特瑞普对这个项目的帮助。

参考

[1] L. Gao 等, The Pile:一个用于语言建模的 800GB 多样化文本数据集 (2020)

[2] Y. Wang 等人,深度学习的、GPU 和 CPU *台的基准测试 (2019)

[3] D. Cer 等人,通用语句编码器 (2018)

[4] R.Wang 等,双向对抗训练的神经主题建模 (2020)

为了无限制地访问 Medium 上的所有文章,成为会员,每月支付 5 美元。非会员每月只能看三个锁定的故事。

莎士比亚和阿姆——谁是更好的作词人?

原文:https://towardsdatascience.com/shakespeare-versus-eminem-1de54e479279?source=collection_archive---------8-----------------------

许多人认为他是有史以来最好的作家。他以他的歌谣、诗歌、奏鸣曲以及关于生活、爱情和人类状况的作品而闻名。像这样的人如何能与莎士比亚相提并论?

马克斯·穆塞尔曼Unsplash 上拍摄的照片

数据科学已经渗透到现代生活中每一个可以想象的角落。苹果在你的手机中使用一个专用芯片来通知 Siri 向你建议什么。甚至杂货店的标签也能实时更新产品价格。但与此同时,生活的真正问题仍然没有答案;我们无法回答生命的意义是什么,如何获得真正的幸福,或者莎士比亚是否比阿姆更适合作词。

(免责声明:此分析严重偏向于表明 b 兔是更好的作词人。我不会采取任何措施来解释这种偏见。事实上,我会尽我所能证明这一点。因为这是应该做的事情。" 如果我只能用这种力量行善,我不会,即使我能 。")

称重

抱歉,如果我说得太直白了
但是我像一尊雕像一样僵硬,你坐在架子上
我觉得我像个半身像,也许我只是超越了自己——阿姆

这两个人都因擅长文字游戏而出名。莎士比亚发明了我们现在使用的 1700 多个单词。他创作了 37 部戏剧和一些诗歌。他最长的作品是《哈姆雷特》,有 4042 行(说唱术语中的“酒吧”),他的全集包含 884647 个单词。

我们在莎翁分析中的数据包含了 36 部作品和 857,648 个单词。

与普遍的看法相反,莎士比亚在他的一生中并不引人注目,他当然很受欢迎,但其他剧作家更受欢迎。他的成名要等到他死后很久。死后 100 年,在 1730 年,莎士比亚女士俱乐部开始通过当地剧院宣传他的作品,这使他成为人们关注的焦点,并赢得了他现在享有的声誉。

另一方面,自从马歇尔·马瑟斯(M&M:外行人的阿姆)一炮走红,他就成了一个传奇。迄今为止,他已经制作了 12 张录音室专辑。

阿姆有许多以他的名字命名的唱片。他经常受到称赞的《说唱之神》(Rap God)保持着一首热门歌曲中最多单词的吉尼斯纪录——1,560 个——而且,当它问世时,是以一定数量的音节最快的速度——16.3 秒 157 个音节,每秒 9.6 秒的舌头扭曲音节——他在《威严》(Maurice)上以每秒多 0.7 个音节的速度打破了这一纪录然后,在 2018 年,他凭借《哥斯拉》再次打破了他自己的记录,但现在“也许我只是超越了自己。

哦,还有阿姆拿了奥斯卡

他也是唯一一个在同一周内拥有冠军歌曲、专辑和电影的人!

我们选择的阿姆作品包含 17 张不同的专辑204 首歌曲和总计 167,080 字(还不包括他的许多单曲或混音带、自由风格、合作带,或他抢尽风头的’特色)。

斯利姆·谢迪并不回避挑战,在 Jay-Z 的叛徒中,他直截了当地喊出了莎士比亚。莎士比亚对阿姆做过这样的事吗?我觉得不是!

节奏和诗歌

我能否把你比做夏季的一天?
当你在永恒的诗行中与时间同长:
只要人们还能呼吸,眼睛还能看得见,
只要这诗行长存,这诗行赋予你生命。—莎士比亚

Christian Rudder 在他的书 Dataclysm中指出,在 Twitter 上使用词语比在书本中发现的更有水准,即使是那些我们认为“伟大”的人。他认为,原因是 Twitter 的 140 个字符的限制迫使用户对我们使用的词语进行长时间的思考。Twitterers 用户会选择更重的词,在有限的空间里传达更多的意思。

文本“成熟度”有许多不同的指标,比如戴尔·查尔的可读性测试。这样的测试不能捕捉到我们皇家韵律的全部光辉,但它会做到的。让我们看看,如果我们的主角和对手在拳击比赛中针锋相对,会发生什么。

第一回合开始。叮叮。

第一轮:*均水*,在(他的)最佳状态下摇摆不定…

"*均值是你隐藏真相的地方."这种智慧在这里同样适用。*均水*很少提到我们英雄的绝对抒情素养和丰富词汇。

在某些方面,Em 和 Shaky 的作品有很大的不同;比如它们的长度。阿姆*均每首歌有 827 个单词,*均每首歌有 110 个小节,而莎翁每首歌有令人印象深刻的 23823 个单词,*均每首歌有 3949 行。

Em 和晃动在这一点上都不占优势。他们在社会中的地位略有不同。因此,这一轮有点*淡无奇。我们的传奇故事都没有真正的出彩,但话说回来"你必须是钻石才能爬上拳击台"

阿姆作品中出现频率最高的词。

莎士比亚作品中出现频率最高的词。

第 2 轮:标准化*均值…

这是战斗变得更有趣的地方。这就是我们看到谁在言语攻击中出拳过重的地方。阿姆没有被分阶段:“只要努力,做绳索 a-dope 阿里洗牌,在他的对手周围跳舞。

对于这一点,我们想看看谁用的词更复杂。我们已经使用了 3000 个简单单词的列表。这些词用在日常用语中,应该避免使用,因为它们主要是填充语。

阿姆和莎士比亚不相上下。两人的作品中*均都有 20%左右的“硬话”。老实说,这种差别并不大,但优势在于莎士比亚。

然而,当谈到每部作品的独特词汇时,阿姆胜过莎翁。*均而言,Em 的作品有 42%的独特词汇,而莎士比亚只有大约 15%的独特词汇。这并不奇怪——莎士比亚需要大量的填充词来填充他的长篇作品。

****阿姆罗的难比易词。

****莎士比亚笔下的难易词之比。

阿姆用力挥棒,莎士比亚躲闪。那家伙的“连电池都没充过电。婊子,他什么也没插。

第 3 轮:你自己更差的殿下……

阿姆经常说自己是更大的敌人。他已经证明了自己是一名出色的射手。“他的说唱之神是一个异数,即使以他自己的标准来看(见下图,右上角)。如前所述,这首歌有多达 1547 个词,其中 617 个词是独一无二的。

一首被严重低估的歌曲是同名专辑中的歌曲 shadyxv 。这首歌只有 1158 个单词,但是 T8 有多达 611 个单词(几乎和说唱之神一样多)。

关于我们分析中歌曲的完整分类,请参见下面的气泡图。将鼠标悬停在上面以查看正在考虑的工作。

****阿姆的抒情天才作品集,将鼠标悬停在泡泡上,看看是哪首歌…

第四轮:莎士比亚引领对话……****

莎士比亚也想插话。尽管他的作品冗长乏味,但他作品中的变化却少得多。自己看看,下面:

****莎士比亚的无聊戏剧作品集,将鼠标悬停在泡泡上,看看是哪部戏剧…

第五轮:双关语

两位作者都有玩弄语言的倾向。他们在适当的位置弯曲单词,语言在他们手中变得几乎是流动的。在《第十二夜》中,莎士比亚展示了他顽皮的一面:

我的生活,这是我的夫人的手:这些是她的 C,
她的 U,(读:‘N’)她的 T;从而使她成为伟大的诗人——莎士比亚

然而,在沼泽上阿姆用他的三重(?)双关语:

我胸前的“s ”(超人)好像是复数——阿姆

在我的胸前;在 chest 上加一个 s 会使它变成复数。然而,胸膜也是胸部包裹肺部的区域。所有的乐趣和游戏,而且,复数“s”(读作:S.S .)是 Slim Shady 的缩写。

或者,考虑这首歌超越:

一二三,咔嚓咔嚓,一二三
咔嚓咔嚓,一二三——阿姆

上,我亲爱的,1+2+3,1+2+3,1+2+3 = 666,恶魔的符号——这首歌里他可以说是在和谁战斗。但他在 1:23 分的时候把这些小节带入了这首歌。这里列举的太多了,值得去看看天才网站看看你到底错过了多少。

第六轮:口才的要素

他的脚步仍然轻盈。阿姆动作很快。莎士比亚看起来又老又累。

马克·福赛思(Mark Forsyth)写了他的书《口才要素》(Elements of 口才)用文字赞美莎士比亚的方式,没有人比山羊做得更好(对于那些不知道山羊是什么的人来说,它意味着有史以来最伟大的,我认为他就是其中之一。”)。

马克给了我们很多可以研究的东西(39 章,阿姆本可以胜过莎士比亚)。在他的第一章和第二十五章中,他谈到了 头韵(或押韵),即具有相似字母或音的快速递进的单词,这满足了听众对押韵的“需求”。

马克给了我们莎士比亚的《仲夏夜之梦》:

于是,他用剑,用该死的剑,勇敢地剖开他滚烫的血淋淋的胸膛;

但我很高兴在清理我的衣柜时抚养他阿姆:

花一点时间听听,在你认为这张唱片令人不快之前
但是把你自己放在我的位置上,试着想象一下
目睹你妈妈在厨房里吃处方药
抱怨有人总是翻钱包,丢东西

第 7 轮:多音节押韵方案

或者考虑我们的英雄的押韵方案;莎士比亚的《暴风雨》中写道:

满揣五个令尊的谎言
他的骨头是珊瑚
制成的;那些珍珠是他的眼睛。
凡是不褪色的、
没有一样东西,而是经历了一场海——

为丰富的东西和
奇怪的东西——莎士比亚

莎士比亚的押韵方案是简单的 A;b;a;b;c;c(其中“;”表示一个句子的结束。将此与阿姆的完全清醒诗句相比:

但是他们看不到我能看到的,我的肚子里有一个空缺
它让我玩捉迷藏,就像杰森一样我太饿了
她是裸体的,看,没有隐私但是我能看到她想要我
那么有耐心,看,我试着去做但是哎呀,为什么她嘲笑我?
(等。)—阿姆

这里的押韵方案是 ABCDABCDABCDABCD 接下来的 14 小节等等!

很明显,莎士比亚可能已经开始了,Em 肯定是来完成它的。

第 8 轮:最快的诗句

这里有五段经文值得思考。他们都快得不可思议。

  1. 哥斯拉——音乐将在 30 秒内被
    339 个音节谋杀(
    每秒 11.3 个音节)
  2. 女王陛下(妮琪·米娜)
    12 秒 123 个音节
    每秒 10.2 个音节****
  3. 被冒犯——复兴
    13 秒 130 个音节,(
    每秒 10.2 个音节)
  4. 说唱之神——马歇尔·马瑟斯 LP2
    仅用 16.3 秒就唱出 157 个音节(
    每秒 9.6 个音节)

现在,试着跟着这些诗句一起说唱,你会发现你所看到的是一个天才在工作。《T4》《哥斯拉》顺带一提,这是阿姆连续第三次打破他自己的最快韵文记录。

第九轮:T.K.O

好吧,TKO 是 JT 的歌,我的错。)

莎士比亚几乎站不住脚。最后一个钉在棺材里,阿姆罗用音乐的方式。很明显,“我一拔出笔,纸就是手榴弹”

在恢复的惊人(奖金)轨道上无标题,他在 3/4 拍内敲击 4/4 拍号。结果是良性的“摇头晃脑”酒吧在迷人的*滑华尔兹流。

最后一张漂亮的图片是阿姆的作品,带有他们独特的词,专辑中的 dale-challs。

他在围绳上。他荡秋千。他击中了。莎士比亚倒下了…他是有史以来最伟大的:阿姆。尽管莎士比亚进行了令人生畏的斗争,但重要的是他显然不是马歇尔·马瑟斯的对手。

这样的人对莎士比亚有什么看法?一切。

余波

那么,我们的英雄在哪里?在事后(懂了吗?)只剩下一个站着:黑幕。

尽管'5-0 开始向他逼*'我也不再是孩子了。我猜当 Em 说:“某个地方某个孩子在对着镜子假唱的时候,他在做这个,那是我为谁做的,其他的我真的不在乎”——我就是那个孩子。****

完整的分析和数据集可以在我的 GitHub 页面找到, 这里

对于纤细黑幕的歌词,我已经用了数据库上的az lyrics**

对于莎士比亚的作品,我用的是《全集》第 2 版(1905 年,牛津大学出版社)。

感谢 伊莉莎白 为她精心设计的可视化嵌入媒介, 这里

你必须知道的机器学习工具

原文:https://towardsdatascience.com/shame-on-you-if-you-dont-know-these-machine-learning-tools-2c0f6cb09524?source=collection_archive---------23-----------------------

2021 年机器学习从业者的所有必备工具

图片由作者创建,背景许可证由作者通过 Envato 持有

今天,我们将探讨成为一名高效的机器学习专家或数据科学家的最重要的方面之一。也就是说,作为机器学习实践者,最好的工具、框架和软件包。尤其是在不断发展的机器学习世界中,事情发展得如此之快,以至于不断学习新工具至关重要。

此外,我们还将介绍简化您生活的子工具和小助手,这里和那里,还有一些代码行,以确保这些工具也能在美学上说服您。

像往常一样,确保留在社区流中,并在评论区评论您最喜欢的工具,这样我们都可以了解您对什么感兴趣。说到心流,我知道这不是秘密,但 TensorFlow 必须出现在每个列表中。

张量流

是一个完整的端到端开源机器学习生态系统,熊猫和蟒蛇等可爱的小动物在这里有宾至如归的感觉。从构建到培训、评估和可视化过程中的各个步骤,TensorFlow 已经俘获了世界各地 ML 开发人员的心,并被许多世界上最大的公司使用,如可口可乐、英特尔、优步和 Twitter。它可以被安全地称为业界的最爱。

使用 Tensorflow 的公司

它由谷歌在 2015 年首次发布,是首批真正帮助将机器学习应用到全球数十亿人的设备上的神经网络编程框架之一。通过这个位置,他们也建立了优势。也就是说,你可以很容易地在网上找到大量预先训练好的模型和代码。另一个主要优势是,他们的框架 TensorflowLite 可以轻松集成到移动应用程序和物联网设备中,如果你不打算在服务器上运行一切,这是关键。

如前所述,Tensorlfow 是一个完整的生态系统,他们的 Tensorboard 是评估和监控模型性能的重要工具。Colab 是另一个组件。它是云中的一个类似 Jupyter 的笔记本,你可以用它来运行机器学习项目并与其他人合作。我记得在我学习期间,许多人用它来免费安装所有的软件包。此外,如果您想让代码对互联网上的其他人可用,这也是一个不错的选择。

张量流子系统,截图来自张量流

提到 Tensorflow 而不提到 Keras 是一种可判死刑的罪过,让我们避免这种信念,并给出一个简短的例子,说明 Keras/Tensorflow 中的 python 模型看起来有多简单

单元格 3 中所述的实际模型定义非常简单,对于顺序模型,可以简单到:

model = keras.Sequential(
    [
        keras.Input(shape=input_shape),
        layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
        layers.MaxPooling2D(pool_size=(2, 2)),
        layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
        layers.MaxPooling2D(pool_size=(2, 2)),
        layers.Flatten(),
        layers.Dropout(0.5),
        layers.Dense(num_classes, activation="softmax"),
    ]
)

Pytorch

TensorFlow 在很长一段时间内都是王者,但现在有了一个新成员,实际上几乎和他一样大…我真的不知道我要去哪里。无论如何,脸书开发的 PyTorch 在 2016 年开始时有点受欢迎,但现在与 Tensorflow 并驾齐驱,同样受欢迎。

截图来自 Google Trends,Blu: PyTorch Red: Tensorflow

到目前为止,您可以在两个框架中做几乎相同的事情。我个人的感觉是,自然语言社区更接* PyTorch,基于图像/视频的模型更倾向于 Tensorflow。但最终,最重要的是你更了解什么,或者有合适的预训练模型或代码。

其中,PyTorch 用于特斯拉的自动驾驶仪和 Pyro 等库。与 Tensorflow 相比,PyTorch 在我看来更容易开发和修改。这表现在他们在研究和探索项目中的强势地位。虽然 Pytorch 有移动支持,但它不像 Tensorflow 那样成熟,而且相当新,但如果你试图在移动上使用 PyTorch 模型,它肯定是正确的选择。

为了向大家展示当我们使用强大的 PyTorch Lightning 软件包时它看起来有多漂亮,我制作了一个完整的视频,让我们展示一个最小的例子。

与上面的 Keras 例子相反,模型定义是“存储”在一个类中的

**class** **MNISTModel**(LightningModule):

其中我们简单地从模块继承,然后可以继续重写各种函数,例如测试/训练/验证集上的损失计算。就我个人而言,我觉得这种方法更加 pythonic 化,也是我的首选武器。

如果你想开始使用最快的快速原型库,一定要看看我的教程,让你开始使用你需要的所有代码。

SageMaker

SageMaker 是一个机器学习环境,它通过提供超快速模型构建和部署的工具来简化任何 ML 开发人员的工作。

2021 年,亚马逊推出了第一个用于机器学习的集成 IDEsage maker Studio。它提供了一个网络界面来监控 ML 模型生命周期的所有可能方面。除了紧密集成到 AWS 云中,它还提供数据标签软件和许多其他功能。

虽然谷歌和 Azure 有类似的服务,但我觉得这是最成熟、最大胆的服务,我会很快开始使用。但众所周知,在单一云上的锁定效应是如此舒适,所以我会坚持使用谷歌笔记本电脑 AI,这对你们谷歌云的人来说也是一个很酷的选择。请在评论中让我们知道你最常用的是哪种云,以及你对他们的 ML 服务的爱憎。

MXNet

另一个开源框架旨在训练和部署深度神经网络,重点关注可扩展性。与两个主要框架相比,MXNet 是 Apache 基金会的孩子,可能是最好的真正开源框架。起步较晚,已经可以用多种语言访问,不仅仅是 Python。

它并不流行,但是仍然被所有主流云所支持,并且有可能加速你的计算。

ONNX

ONNX 是一种表示机器学习模型的格式。这里的目标是未来的开发人员不再被迫选择在他们特定的框架中训练过的模型。而是可以,不管他们开始使用他们选择的工具、编译器和框架是什么。分别试验新的,没有太多的移植工作。

他们通过指定一组通用的操作符来实现这一目标,基本上就是发生在不同层和通用文件格式之间的数学运算。它得到了几乎所有大型人工智能玩家的支持,并且肯定会对 ML 开发的未来产生巨大的影响。除了谷歌,所有的科技巨头都是这个项目的合作伙伴。

ONNX 社区的合作伙伴,截图来自 ONNX

Sklearn

到目前为止,我们已经研究了围绕神经网络的强大工具。然而,我倾向于使用最多的一个机器学习库仍然是官方称为 Scikit-learn 的 Sklearn。自 2007 年以来,它已经成为每个机器学习者工具带的核心部分,无论你是想处理异常值还是评估模型的不同方面。Sklearn 拥有所有可用的简单算法,并且是在一个熟悉的、有良好文档记录的代码库中构建的。

从集成方法、聚类、评估、数据集构建,以及几乎所有你想用数据做的事情,sklearn 至少有一些易于使用的功能,可以让你更有效率。

自动 ML 工具

总而言之,让我们面对现实吧,如果我们内心深处不懒惰,我们就不会成为自动化专家。或者就像比尔·盖茨说的,那个曾经很受欢迎的有钱人“我选择一个懒惰的人去做一件艰难的工作。因为一个懒惰的人会找到一个简单的方法去做。”

这正是我们的领域提出 auto ML 的原因,所以事实上,学习正确的算法和数据转换,从训练数据到预测。虽然从我的个人经验来看,这些工具不能取代数据科学家,但它们将提供很多帮助,并在未来几年加速新工具的开发和部署

自动对焦

让我们从一个不需要云基础设施就能让你去任何地方的开始。AutoKeras 是一个基于 Keras 的 AutoML 系统。它是由德克萨斯 A 大学的 T2 数据实验室开发的。AutoKeras 的目标是让每个人都可以使用机器学习。

Autokeras 基于神经结构搜索的思想。使用贝叶斯优化,他们指导搜索和形态。这里,态射意味着改变各种超参数,并决定使用哪个模型。

在我继续让你厌烦之前,让我们看一个简短的例子。

与上面的其他两个模型定义相比,我们在这里只看到一个调用

clf = ImageClassifier(num_classes=9)

像模型和超参数调整这样的其他事情都由库来处理。

谷歌云汽车

AutoML 使具有有限机器学习专业知识的开发人员能够训练针对其业务需求的高质量模型。分分钟建立自己的定制机器学习模型是他们的口号。

我最后一次尝试时,它在像图像分类这样的样板任务上表现得非常好。但是整个特征工程和潜在的合并多个模型的输出以提高准确性仍然超出了这个实现的范围

无与伦比的优势是投入到这样一个项目中的开发工作量,假设它是可行的,那么与您必须自己维护的经典 ML 管道相比,它是非常小的。缺点是价格,因为它似乎成本高昂,但你又节省了工作时间。其他类似的工具是 IBM Watson,非常适合关注数据隐私、Azure 机器学习和数据机器人的公司。

H20 的无人驾驶 AI

另一个可能拥有最佳用户体验的竞争对手。我的意思是 GUI,我的意思是仪表板,字面上看起来像直接从犯罪现场调查迈阿密。换句话说,这是任何试图拍摄邪恶 AI 开发者场景的电影导演的正确工具。

他们的功能工程特别好,他们的合作伙伴包括一些主要的参与者,如 IBM、NVIDIA 和三大云提供商。除了科技巨头,他们的产品是小公司中最有趣的选择,被 Gartner 称为有远见者是有充分理由的。

亚马逊的 Lex

Amazon Lex 是一项为任何使用语音和文本的应用程序构建对话界面的服务。如果你正在寻找建立人工智能聊天机器人或评估文本,这项服务肯定是一个很好的起点。

我对它进行了一些修改,必须说这确实是一个很好的体验,而且表现得非常好,至少在处理英语数据时是这样。这项服务背后的技术毕竟和家庭助手 Alexa 是一样的。

10,000 个文本请求和 5,000 个语音请求在 AWS 免费层是免费的,因此试用一段时间对于新开发人员来说也是一个很好的选择。最后,您可以肯定的是,无论您投入多少流量,这项服务都可以很好地扩展。

结论

我们又一次了解到,有比你所能看到的更多的工具,许多相当诚实地填补了类似的目的,并且他们的交互经常就好像没有比特定的工具更重要。

很高兴向您介绍它们,不要忘记在评论中告诉我们“这个列表中肯定缺少什么工具?”

如果你喜欢这篇文章,我会很高兴在 Twitter 或 LinkedIn 上联系你。

一定要看看我的 YouTube 频道,我每周都会在那里发布新视频。

SHAP:用 Python 解释任何机器学习模型

原文:https://towardsdatascience.com/shap-explain-any-machine-learning-model-in-python-24207127cad7?source=collection_archive---------0-----------------------

入门

SHAP 和沙普利价值观综合指南

动机

想象一下,你正在试图训练一个机器学习模型来预测一个广告是否被特定的人点击。在收到一个人的一些信息后,模型预测一个人不会点击某个广告。

作者图片

但是为什么这个模型预测到了这一点呢?每个特征对预测的贡献有多大?如果您能看到一个如下图所示的曲线图,显示每个要素对预测的贡献大小,那不是很好吗?

作者图片

这就是 Shapley 值派上用场的时候。

什么是沙普利值?

Shapley 值是博弈论中使用的一种方法,它涉及到将收益和成本公*地分配给联盟中的参与者。

由于每个参与者对联盟的贡献不同,沙普利值确保每个参与者根据他们贡献的多少得到公*的份额。

作者图片

简单的例子

Shapley 值广泛用于质疑一个组中每个工作者/特征的贡献的问题。为了理解 Shapley value 是如何工作的,让我们想象一下你的公司刚刚进行了 A/B 测试,他们测试了不同的广告策略组合。

每个策略在特定月份的收入如下:

  • 没有广告:150 美元
  • 社交媒体:300 美元
  • 谷歌广告:200 美元
  • 电子邮件营销:350 美元
  • 社交媒体和谷歌广告 320 美元
  • 社交媒体和电子邮件营销:400 美元
  • 谷歌广告和电子邮件营销:350 美元
  • 电子邮件营销、谷歌广告和社交媒体:450 美元

作者图片

使用三个广告和不使用广告的收入相差 300 美元。每个广告对这种差异的贡献有多大?

作者图片

我们可以通过计算每种广告的 Shapley 值来找出答案。这篇文章提供了一个计算 Shap 值的好方法。我在这里总结一下。

我们首先计算谷歌广告对公司收入的总贡献。谷歌广告的总贡献可以通过以下公式计算:

作者图片

让我们找出谷歌广告的边际贡献和权重。

寻找谷歌广告的边际贡献

首先,我们会发现谷歌广告对以下群体的边际贡献:

  • 没有广告
  • 谷歌广告+社交媒体
  • 谷歌广告+电子邮件营销
  • 谷歌广告+电子邮件营销+社交媒体

作者图片

谷歌广告对无广告的边际贡献是:

作者图片

谷歌广告对谷歌广告和社交媒体集团的边际贡献是:

作者图片

谷歌广告对谷歌广告和电子邮件营销集团的边际贡献是:

作者图片

谷歌广告对谷歌广告、电子邮件营销和社交媒体集团的边际贡献是:

作者图片

寻找重量

为了找到权重,我们将把不同广告策略的组合组织成多个层次,如下所示。每个级别对应于每个组合中广告策略的数量。

然后,我们将根据每个级别中的边数来分配权重。我们看到:

  • 第一层包含 3 条边,因此每条边的权重将是的 1/3
  • 第二层包含 6 条边,因此每条边的权重为 1/6
  • 第三层包含 3 条边,因此每条边的权重将为 1/3

作者图片

找出谷歌广告的总贡献

现在我们已经准备好根据之前找到的权重和边际贡献来找到谷歌广告的总贡献了!

作者图片

作者图片

酷!因此,谷歌广告为使用 3 种广告策略和不使用广告之间的总收入差异贡献了 36.67 美元。36.67 是谷歌广告的 Shapey 值。

对另外两种广告策略重复上述步骤,我们可以看到:

  • 电子邮件营销贡献了 151.67 美元
  • 社交媒体贡献了 111.67 美元
  • 谷歌广告贡献 36.67 美元

作者图片

他们共同贡献了 300 美元来区别使用 3 种不同类型的广告和不使用广告!很酷,不是吗?

现在我们已经了解了 Shapley 值,让我们看看如何使用它来解释机器学习模型。

SHAP——用 Python 解释任何机器学习模型

SHAP 是一个 Python 库,它使用 Shapley 值来解释任何机器学习模型的输出。

要安装 SHAP,请键入:

pip install shap

训练模特

为了理解 SHAP 是如何工作的,我们将使用一个广告数据集进行实验:

我们将建立一个机器学习模型,根据用户的一些信息来预测用户是否点击了广告。

我们将使用 Patsy 将数据帧转换成一个特性数组和一个目标值数组:

将数据分为训练集和测试集:

接下来,我们将使用 XGBoost 构建模型并进行预测:

为了了解模型的表现,我们将使用 F1 分数:

0.9619047619047619

相当不错!

解释模型

该模型在预测用户是否点击广告方面做得很好。但它是如何得出这样的预测的呢?每个特征对最终预测和*均预测之间的差异有多大贡献?

请注意,这个问题与我们在文章开头提到的问题非常相似。

这就是为什么找到每个特征的 Shapley 值可以帮助我们确定它们的贡献。获得特征 I 的重要性的步骤,其中 I 是特征的索引,与前面类似:

  • 获取不包含特征 I 的所有子集
  • 找出特征 I 对每个子集的边际贡献
  • 合计所有边际贡献以计算特征 I 的贡献

要使用 SHAP 找到 Shapley 值,只需将训练好的模型插入shap.Explainer:

SHAP 瀑布图

想象第一个预言的解释:

作者图片

啊哈!现在我们知道了每个特征对第一次预测的贡献。对上图的解释:

作者图片

  • 蓝色条显示特定特征降低预测值的程度。
  • 红色条显示了特定特征对预测值的增加程度。
  • 负值意味着该人点击广告的概率小于 0.5

对于这些子集中的每一个,SHAP 不会删除一个特征,然后重新训练模型,而是用该特征的*均值替换该特征,然后生成预测。

我们应该期望总贡献等于预测值和*均预测值之差。让我们检查一下:

作者图片

酷!他们是*等的。

想象第二个预言的解释:

作者图片

SHAP 汇总图

我们不需要查看每个单独的实例,而是可以使用 SHAP 汇总图直观显示这些功能对多个实例的总体影响:

作者图片

SHAP 汇总图告诉我们最重要的要素及其对数据集的影响范围。

从上面的图中,我们可以对模型的预测获得一些有趣的见解:

  • 用户的日常互联网使用对该用户是否点击广告有最大的影响。
  • 随着日常互联网使用 的增加,用户点击广告的可能性降低。****
  • 随着每天花在网站上的时间增加,用户点击广告的可能性降低
  • 随着地区收入的增加,用户点击广告的可能性降低。
  • 随着年龄的增加,用户更有可能点击广告。
  • 如果用户是男性,那么这个用户不太可能点击广告

SHAP 条形图

我们还可以使用 SHAP 条形图来绘制全局特征重要性图。

作者图片

SHAP 相关散点图

我们可以使用 SHAP 相关散点图观察单个特征对模型做出的所有预测的影响。

日常互联网使用

日常互联网使用功能散点图:

作者图片

从上面的图中,我们可以看到,随着每日互联网使用量的增加,每日互联网使用量的 SHAP 值减少。这证实了我们在早期情节中看到的。

我们还可以通过添加color=shap_values来观察日常互联网使用功能与同一情节中其他功能之间的交互。

散点图将试图挑选出与日常互联网使用(即每天花在网站上的时间)互动最强的功能栏。

作者图片

酷!从上面的情节中,我们可以看到,一个每天使用互联网 150 分钟,并且每天在网站上花费少量时间的人更有可能点击广告。

让我们看看其他一些特征的散点图:

每天在现场花费的时间

作者图片

地区收入

作者图片

年龄

作者图片

性别

作者图片

SHAP 相互作用图

您还可以通过 SHAP 交互值汇总图观察功能之间的交互矩阵。在该图中,主要效应在对角线上,交互效应在对角线外。

作者图片

相当酷!

结论

恭喜你!您刚刚学习了 Shapey 值以及如何使用它来解释机器学习模型。希望这篇文章能给你必要的知识,让你用 Python 解读自己的机器学习模型。

我推荐查看 SHAP 的文档来了解更多关于 SHAP 的其他应用。

您可以随意使用这个交互式笔记本中的源代码,或者转到我的存储库:

https://github.com/khuyentran1401/Data-science/blob/master/data_science_tools/shapey_values/shapey_values.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

参考

南马赞蒂(2021 年 4 月 21 日)。 SHAP 解释道,我希望有人能给我解释一下。中等。检索于 2021 年 9 月 23 日,来自https://towards data science . com/shap-explained-the-way-I-wish-someone-explained-it-to-me-ab 81 cc 69 ef 30。

用于特征选择和超参数调整的 SHAP

原文:https://towardsdatascience.com/shap-for-feature-selection-and-hyperparameter-tuning-a330ec0ea104?source=collection_archive---------8-----------------------

调整参数时,使用 SHAP 进行最佳特征选择

蓝菊·福托雷菲在 Unsplash 上拍摄的照片

特征选择和超参数调整是每个机器学习任务中的两个重要步骤。大多数情况下,它们有助于提高性能,但缺点是耗费时间。参数组合越多,或者选择过程越精确,持续时间就越长。这是一个实际上我们无法克服的物理极限。我们能做的是利用我们管道中的最佳资源。我们面临不同的可能性,最方便的两种是:

  • 结合调音和选择功能
  • 采用 SHAP(SHapley Additive explaints)使整个过程更具概括性和准确性。

将调整过程与特征的最佳选择相结合可能是每个基于排序的选择算法的需要。排序选择包括迭代地丢弃不太重要的特征,同时重新训练模型,直到达到收敛。用于特征选择的模型可能(在参数配置或类型上)不同于用于最终拟合和预测的模型。这可能导致次优性能。这是例如 RFE(递归特征消除)或 Boruta 的情况,其中由算法通过可变重要性选择的特征被另一个算法用于最终拟合。

当我们使用基于排名的算法进行特征选择时,SHAP 会有所帮助。我们不使用梯度增强生成的默认变量重要性,而是选择最佳特征,如具有最高 shapley 值的特征。使用 SHAP 的好处显而易见,因为基于原生树的特征重要性存在偏差。标准方法倾向于高估连续或高基数分类变量的重要性。这使得在特征转移或类别数量变化的情况下计算的重要性不可信。

为了克服这些不足,我们开发了shap-hype tune:一个 python 包,用于同时进行超参数调整和特性选择。它允许将超参数调整和特征选择结合到一个具有梯度增强模型的管道中。它支持网格搜索、随机搜索或贝叶斯搜索,并提供分级特征选择算法,如递归特征消除(RFE)、递归特征添加(RFA)或 Boruta。额外的提升包括提供使用 SHAP 重要性进行特征选择的可能性。

在本帖中,我们展示了在执行监督预测任务时采用 shap-hypetune 的实用程序。我们尝试搜索最佳参数配置,同时选择具有(和不具有)SHAP 的最佳特征集。我们的实验分为三次试验。给定分类场景中的数据集,首先我们简单地通过优化参数来拟合 LightGBM。然后,我们尝试在优化参数的同时,使用默认的基于树的特征重要性来操作标准 RFE。最后,我们做同样的事情,但选择 SHAP 的功能。为了让事情更有趣,我们使用了一个不*衡的二进制目标和一些高基数的分类特征。

参数调谐

在第一部分中,我们计算训练集的拟合,只搜索最佳参数组合。最好的模型达到了高于 0.9 的精度,但是在我们的测试数据上具有低召回率。

测试数据上的性能(图片由作者提供)

让我们看看是否能做得更好。

参数调整+功能选择

通常,引入特征选择是为了从原始数据集中去除有噪声的预测值。在搜索最佳参数集时,我们使用递归特征消除(RFE)。换句话说,对于每个参数配置,我们在初始训练数据上迭代 RFE。可以通过配置适当的拟合参数来加速该过程,例如提前停止,或者在删除较差特征的同时设置较大的步长。存储在验证集上具有最佳分数的管道,并准备在推断时使用。

测试数据上的性能(图片由作者提供)

在这种情况下,我们总体上有所提高,但召回率和 F1 得分仍然较低。

SHAP 参数调整+功能选择

最后,我们重新提出和以前一样的程序,但是用 SHAP 代替 RFE。当与基于树的模型结合使用时,SHAP 非常有效。它使用一种树路径方法来跟踪这些树,并提取沿着每片叶子向下的训练样本的数量,以提供背景计算。它也不容易过于自信,因为我们可以在验证集而不是在训练数据上计算重要性(像经典的基于树的重要性)。

测试数据上的性能(图片由作者提供)

我们在召回率和 F1 分数方面取得了巨大进步。SHAP 能够排出低质量的分类特征,只保留最佳预测值。

测试数据上的性能对比(图片由作者提供)

摘要

在这篇文章中,我们介绍了 shap-hypetune ,作为一个有用的框架,用于对梯度增强模型进行参数调整和最佳特征搜索。我们展示了一个应用程序,其中我们使用了网格搜索和递归特征消除,但随机搜索和 Boruta 也是其他可用的选项。我们还看到了在经典特征重要性方法缺乏性能的情况下,如何使用 SHAP 幂来改进选择过程。

如果你对题目感兴趣,我建议:

查看我的 GITHUB 回购

保持联系: Linkedin

SHAP:沙普利加法解释

原文:https://towardsdatascience.com/shap-shapley-additive-explanations-5a2a271ed9c3?source=collection_archive---------2-----------------------

一步一步的指导理解 SHAP 如何工作,以及如何通过使用 SHAP 图书馆解释 ML 模型

图一。SHAP |作者图片|自由选择的图标

在过去的十年里,我们见证了人工智能时代的爆发,由学术界推动,并被业界接受。人工智能已经融入日常生活,甚至商业模式也围绕着人工智能模式。

人工智能在自然语言处理、计算机视觉等领域已经显示出令人印象深刻的成果。今天,只需要几行代码就可以实现最先进的人工智能模型,这太令人着迷了。然而,作为人类,我们该如何解读 AI 模型做出的预测呢?我们如何衡量模型赋予待推断数据的重要性?嗯,在这个博客中我们将谈论这个有争议的话题:人工智能模型的可解释性

人工智能模型的可解释性是一个活跃的研究领域。*年来已经提出了几种替代方案,在这篇博客中,我们将特别关注其中一个:SHAP(Shapley Additive explaints)。

在这个博客中,我们将看到 SHAP 方法的 ML 模型的可解释性,我们将看到 SHAP 是如何工作的,以及它的主要组成部分:Shapley 值。因此,本博客将分为以下几个部分:

  • 什么是沙普利值?
  • 什么是 SHAP?
  • SHAP 在行动:一个分类问题
  • 结论

我建议你去喝杯咖啡,放松一下,☕️!

什么是匀称的价值观?

Shapley 值是合作博弈论领域的一个概念,其目的是衡量每个玩家对游戏的贡献。获得 Shapley 值的方法是由 Lloyd Shapley [ 1 ]在 1953 年提出的。Shapley 值产生于这样的背景,其中" n "玩家集体参与并获得奖励" p ",该奖励旨在根据个人贡献公*地分配给每个" n "玩家,这样的贡献是 Shapley 值。

简而言之,Shapley 值是一个特性实例在所有可能组合中的*均边际贡献。*均边际贡献?所有可能的联盟?我们来详细看看这一切指的是什么。

比方说,一群朋友(ABCD)正在一起合作获取利润P。公*分配利润,意在衡量每个成员的贡献,即每个朋友的沙普利值。为了计算给定成员的 Shapley 值,计算当该成员存在时产生的利润与当该成员不存在时产生的利润之间的差(这种差是给定成员对当前联盟的边际贡献),这是针对当你期望为其计算贡献的成员存在时可以产生的所有子组(或联盟)进行的。获得的差值的*均值(*均边际贡献)是 Shapley 值。

在下图中,我们看到了朋友A对由朋友BCD组成的校对的边际贡献的计算表示。

图二。成员“A”对成员 B、C、d 联盟的边际贡献|作者图片|自由选择的图标

例如,为了计算朋友A的 Shapley 值,我们将需要构建朋友A出现的所有排序,对于每个排序,将计算边际贡献(成员在场时获得的利润与成员不在场时获得的利润之间的差异),并且给定所有边际贡献,将计算*均边际贡献,即 Shapley 值。简单吧?

图 3 显示了朋友A的 Shapley 值的计算。

图 3。成员“A”的 Shapely 值计算|作者的图像|自由选择的图标

到目前为止,我们已经知道什么是 Shapley 值,它是如何计算的,以及它的解释是什么。然而,Shapley 值与 ML 模型的可解释性有什么关系?让我们看看这是如何发生的。

在一个 ML 模型的背景下,我们假设我们例子中的每个朋友都是一个特性,游戏是生成预测的函数,利润就是预测。

然而,ML 模型通常具有大量的特征,其中每个特征是离散或连续的变量,这导致计算每个特征的每个实例的 Shapley 值在计算上非常复杂,事实上,这是一个 NP-hard 问题。

正是在这一点上,SHAP 成了主角。在下一节中,我们将看到什么是 SHAP 以及它对 ML 模型的可解释性的方法。

也许是时候重新装满咖啡杯了,☕️!

什么是 SHAP?

Shapley Additive Explanations(SHAP),是 Lundberg 和 Lee 在 2017 年[ 2 推出的一种通过 Shapely 值解释 ML 模型预测的方法。SHAP 的主要思想是为要解释的样本的每个特征计算 Shapley 值,其中每个 Shapley 值代表与其关联的特征在预测中产生的影响。

SHAP 背后的直觉很容易理解,每个特征都有一个相关的沙普利值。然而,SHAP 是如何工作的呢?在上一节中,我们看到 Shapley 值的计算对于许多特征来说可能变得难以处理。为了避免这种情况,作者引入了 Kernel Shap,这是一种从线性时间[ 3 ]扩展和改编的方法,用于计算 Shapley 值。

核 Shap 是一种允许用少得多的联合样本计算 Shapley 值的方法。内核 Shap 基于加权线性回归,其中解的系数是 Shapley 值。为了建立加权线性模型,采用样本联盟,对于每个联盟,获得预测,并使用核形状计算权重。最后,拟合加权线性模型,得到的系数是 Shapley 值。

有点复杂,对吧?我们来详细看看。

假设我们想要解释实例x,它由特征f1f2f3f4组成。该过程从获取一组联合样本开始。例如,联合(1,0,1,0)指的是特征f1f3的存在,以及特征f2f4的不存在。由于 ML 模型不能省略特征来进行推断,所以特征f2f4的值被取自训练集的值所替换。然后,对于联合(1,0,1,0),特征f1f3的值取自实例x,特征f2f4的值来自训练集,这样可以正确地进行预测。因此,对于每个联合样本,利用等式 1 中描述的核形状来获得预测并计算权重。求解线性模型,得到的系数就是 Shapley 值。

等式 1。内核形状

一切都清楚了吧?没有什么比一张图片更能说明整个过程了。在图 4 中,我们看到了给定实例X的 Shapley 值计算的描述过程。

图 4。SHAP 从 ML 模型中获取 Shapley 值的描述过程|图片由作者提供

从上图可以看出,通过核 Shap 从 ML 模型中获取 Shapley 值的过程并不复杂,但却很费力。主要成分是联盟、预测和权重。

值得注意的是,试图计算所有的联盟会使问题变得棘手。这就是采取联盟样本的原因,样本越大,不确定性越低。

最后,很重要的一点是,对于 Shapley 值的计算,Kernel Shap 是唯一与模型无关的方法,也就是说,Kernel Shap 可以解释任何 ML 模型,而不管其性质如何。另一方面,作者还提出了基于不同类型的模型(如树 SHAP、深 SHAP、低阶 SHAP、线性 SHAP 和最大 SHAP)来获得沙普利值的其他变型。

好了,是时候看看 SHAP 的行动了。在下一节中,我们将看到如何使用shap库从 ML 模型中获取 Shapley 值。我想是时候重新装满咖啡杯了,☕️!

SHAP 在行动:一个分类问题

SHAP 及其变体被集成到 python 库shap中,该库除了提供计算 Shapely 值的不同方法外,还集成了多种结果可视化和解释方法。

本节的目标是展示如何使用shap库来计算、绘制和解释分类问题中的 Shapley 值。所以,让我们努力吧!

完整的项目,以及本文中显示的例子,可以在下面找到:https://github . com/FernandoLpz/SHAP-分类-回归

数据集

对于这个例子,我们将使用乳腺癌威斯康星(诊断)数据集[ 4 ],其特征描述了肿瘤的特征,并且目标是预测肿瘤是良性还是恶性。数据集包含 100 个样本,8 个独立特征(radiustextureperimeterareasmoothnesscompactnesssymmetryfractal_dimension)和一个从属特征(diagnosis_result,目标特征)。

目标特征包含两个类别M = MalignB = Benign。出于实用目的,我们将类别编码如下:0 = Malign1 = Benign

模型

针对这个问题,我们实现并优化了一个基于随机森林的模型,在测试集中获得了92%的准确率。下面的代码片段显示了分类器的实现。

代码片段 1。随机森林分类器的训练和优化

在上面的代码片段中,我们实现了一个基于随机森林的分类器,它已经使用Optuna库进行了优化。从这一点上来说,我们已经有了一个能做出预测的模型,我们打算用 SHAP 来解释它,所以让我们来看看我们是怎么做的吧!

释义:沙普利价值观

假设我们有两个想要解释的样本,一个样本属于类别1 ( Benign),另一个样本属于类别0 ( Malign),分别如图 5 和图 6 所示。

图 5。阳性样本|类别=良性

图 6。负样本| Class = Malign

由于我们的 ML 模型是基于决策树的,为了获得 Shapley 值,我们将使用 TreeShap。因此,我们首先需要导入库,并通过将我们的分类器作为参数传递来初始化解释器,如下面的代码片段所示:

代码片段 2。TreeExplainer 初始化

接下来,我们需要计算 Shapley 值的样本。在这种情况下,我从训练数据集中提取分别对应于图 5 和图 6 中所示的样本(重要的是要提到,出于解释的目的,我一次使用一个样本,但是也可以使用整个数据集)。

代码片段 3。阳性和阴性样本

只是为了检查,每个样本的预测是:

代码片段 4。阳性和阴性样本的预测

为了计算 Shapley 值,我们使用从 explainer 扩展而来的shap_values方法。它接收到的参数就是我们想要解释的样本:

代码片段 5。获取阳性和阴性样本的 Shapley 值

这就是我们的沙普利值!但是等一下,我们如何解读这些价值观呢?为什么从索引[1]打印出来?好吧,我们来详细看看这个。

首先,变量shap_values_positiveshap_values_negative包含对应于正类和负类的每个特征的 Shapley 值,因此,shap_values_positive[0]包含每个特征相对于类0(或Malign)的 Shapley 值,shap_values_positive[1]包含每个特征相对于类1(或Benign)的 Shapley 值,这同样适用于shap_values_negative。为了实用,我们使用关于类1的结果。

然后,对于positivenegative样本,我们获得 8 个值的列表,它们对应于每个特征的 Shapley 值。在下图中,我们可以更清楚地看到每个样本及其各自的 Shapley 值:

图 7。每个阳性和阴性样本的每个特征的 Shapley 值

你还记得第一部分中解释的 Shapley 值的本质吗?这里发生了完全相同的事情,具有高 Shapley 值的要素影响较大,具有低 Shapley 值的要素对预测的影响较小。我们也可以将 Shapley 值解释为,具有高 shap 值的特征推向一个类,而具有低 shap 值的特征推向另一个类。

从正面样本中,我们看到 Shapley 值最高的特征是perimetercompactnessarea。从负样本来看,Shapley 值最低的特征是perimeterareacompactness

正如我们提到的,shap库也提供了生成图的工具。让我们看看如何为阳性和阴性样本绘制一个名为force_plot的图:

代码片段 6。绘制阳性和阴性样本

每个样品的结果图如下:

图 8。阳性样本的强制绘图| Class =良性|作者提供的图像

图 9。负样本的强制绘图| Class = Malign |作者的图像

正如我们从两个图中看到的,每个特性的影响对应于图 7 中描述的 Shapely 值。在红色中我们看到高 Shapley 值,即它们向类1(或Benign)推进,在蓝色中我们看到低 Shapley 值,即它们向类0(或Malign)推进。force_plot是一个很好的可视化工具,可以用来理解每个特性对给定预测的特定样本的影响。

force_plot()是理解每个特性对特定样本的影响的一个很好的可视化工具,同样shap库提供了各种类型的可视化工具来帮助解释 Shapley 值。例如,summary_plot()方法通过改变每个特性的值来提供关于特性重要性以及 Shapley 值影响的信息。

对于本例,summary_plot()由下式给出:

代码片段 7。汇总图

生成以下图:

图 10。汇总图

在左侧,我们观察根据重要性排序的每个特性。perimeter特征最重要,而texture特征最不重要。颜色代表每个要素可以采用的值,红色代表高值,蓝色代表低值。因此,对于特性perimeter,如果值较高(红色),则 Shapley 值将较低,因此将推向等级0(或Malign),否则,当值较低(蓝色)时,Shapley 值将较高,因此将推向等级1(或Benign)。这可以分别用图 8 和图 9 所示的结果来验证。

另一个重要的观察结果是,perimetercompactnessarea特征是在给定其相关 Shapely 值的情况下对预测产生最大影响的特征,也就是说,它们的 Shapley 值非常高或非常低。另一方面,其余的特征不会产生太大的影响,因为它们的相关 Shapley 值更接*于零。

summary_plot()的一个变体,以条形图的形式显示了每个特性的影响,这样的图可以通过以下方式获得:

代码片段 8。汇总图,条形图

生成以下图:

图 11。汇总图,条形图

如图 10 所示,在图 11 中,我们可以看到每个特性根据其相关 Shapley 值的影响进行排序。同样,我们观察到特征perimetercompactnessarea是对模型影响最大的特征。

完整的项目,以及本文中显示的例子,可以在下面找到:https://github . com/FernandoLpz/SHAP-分类-回归

喝了几杯咖啡后,现在我们已经到了终点!

结论

在这篇博客中,我们看到了什么是 SHAP。

在第一节中,我们谈到了从 Shapely 价值观的起源和解释。在第二部分中,我们学习了什么是 SHAP,它是如何工作的,以及它对 ML 模型可解释性的基于石灰和 Shapely 值的支持。最后,在第三部分中,我们看到了如何使用shap库,并展示了一个示例来解释 shap 库返回的结果。

shap库提供了大量可视化和解释 ML 模型的工具。在这篇博客中,我们只看到了几个例子。建议看一下文档,以便从这个伟大的库获得最大的好处。

“阅读、学习、写作、分享。重复“T1”——费尔南多·洛佩斯·维拉斯科。

参考

[1]n 人游戏的一个数值。L.S .沙普利。1953 年

[2] 解释模型预测的统一方法

【3】“我为什么要相信你?”解释任何分类器的预测

[4] 乳腺癌威斯康星(诊断)

模型解释的 SHAP 值

原文:https://towardsdatascience.com/shap-values-for-model-interpretation-268680a25012?source=collection_archive---------30-----------------------

用博弈论的概念解释一个模型

来源( Unsplash )

在越来越多的领域,机器学习模型已经开始被赋予更高的标准。模型预测已经不够了。现在,公司可以对其模型产生的任何虚假预测负责。随着这一转变,模型的可解释性可以说已经优先于预测能力。准确性和 R2 分数等指标已经退居二线,而能够解释模型预测已经变得越来越重要。我们已经研究了几种方法来解释您的模型,并更好地理解它们是如何工作的。在这里,我们将研究 SHAP 值,这是一种解释来自机器学习模型的预测的强大方法。

SHapley 意思是 SHapley 附加解释是一种解释来自机器学习模型的个体预测的方法。这超出了另一篇文章中讨论的依赖系数进行模型解释的常用方法。

它们是如何工作的?

SHAP 是基于沙普利价值观,一个来自博弈论 的概念,由经济学家劳埃德·沙普利发展而来。该方法通过让我们看到每个特征对模型预测的贡献大小来帮助我们解释模型。我们模型中的每个特征将代表一个“玩家”,而“游戏”将是模型的预测。实际上,我们将试图了解每个玩家对游戏的贡献。

这样做的过程包括计算具有特征的模型和没有特征的模型的预测。通过获得这两个预测之间的差异,我们可以看到该特征对模型预测的贡献有多大。这是特性的边际贡献。我们对特征的每个子集都这样做,并取这些贡献的*均值来获得特征的 Shapley 值。

计算边际分布

每个特征子集的可视化表示

对于我们的例子,假设我们有一个预测房价的模型。上图以图表的形式展示了这一点。我们将有三个特性:RoomsAgeLocation。总的来说,我们将有 8 个不同的功能子集。图中的每个节点将代表一个单独的模型,因此我们也将有 8 个不同的模型。我们将在相应的子集上训练每个模型,并预测同一行数据。

每个特征子集的预测

我们图中的每个节点都通过有向边与另一个节点相连。节点 1 将没有任何功能,这意味着它将只预测在我们的训练数据中看到的*均值(100k $)。沿着通向节点 2 的蓝色边,我们看到具有单个特征Rooms的模型预测较低的值为 85k $。这意味着Rooms对以Rooms为唯一特征的模型的边际贡献是 -15k $ (85k $ - 100k $)。我们已经为一个型号这样做了,但是有几个型号的Rooms是一个特性。我们将对添加了Rooms功能的每个型号进行计算。

计算边际贡献

上图突出显示了添加了Rooms特征的每条边,还显示了该特征在每个模型中的边际贡献。接下来我们要做的是取这些边际贡献的*均值。唯一的问题是我们将如何在我们的*均值中权衡它们。你可能会认为我们可以*等地权衡它们,但事实并非如此。功能越少的模型意味着每个功能的边际贡献越大。因此,具有相同数量特征的模型应该具有相同的权重。

按要素数量对节点进行分组

我们可以像上面看到的那样把图表分成几行。每一行都有包含不同数量特征的模型。在*均我们的边际贡献时,我们希望每一行都有相等的权重。因为我们有 3 行,每一行的权重是 1/3。对于我们有两个特征模型的行,我们有两个具有特征Rooms的模型,所以每个模型的权重应该是 1/6。我们对每种“类型”模型的重量细分如下:

  • 1 特征模型:1/3
  • 2 个特征模型:1/6
  • 3 个特征模型:1/3

我们的最终计算结果如下:

因此,我们对于Rooms特性的 SHAP 值将是-10.5 千美元。然后,我们可以对模型中的每个特性重复这个过程,以找到所有特性的值。这种特殊方法的好处在于,我们可以看到特征如何影响单个预测,而不仅仅是对数据集中所有示例的*均影响。

实施

从头开始实现这一切看起来很痛苦,对吗?幸运的是,与 Python 中的大多数数据科学任务一样,我们可以使用一个名为 shap 的库来完成这项任务。根据上面的示例,我们将使用来自 Kaggle 的房地产数据集。我将检查代码,以便能够做到这一点。

为模型定型并获取单行数据的 SHAP 值

单行数据的 SHAP 值图

上面的图表向我们展示了几条重要的信息。这栋房子的价值预计为 15.42 英镑。在图的右侧,我们看到了 23.16 的基础值。我们还看到两组不同的特征,分别是红色和蓝色。以红色突出显示的要素有助于提高预测,而以蓝色突出显示的要素有助于降低预测。每个要素在图中所占的大小显示了它对预测的影响程度。我们看到特征LSTAT(较低的人口状况百分比)对降低预测值贡献最大,而特征CRIM(按城镇划分的人均犯罪率)对提高预测值贡献最大。

你可能已经注意到的另一件事是,我使用了一个名为TreeExplainer的类。这是因为我们在这个例子中使用了基于树的模型(随机森林)。shap 库中有几个‘解释器’。适用于非基于树的模型的更通用的解释器是 KernelExplainer 。或者,你也可以使用深度学习模型的深度解释器

我们可以通过上面的决策图来观察这个个体预测。我们在基础值 23.16 处看到一条黑色的垂直线。从底部开始,沿着图向上移动,我们看到我们遇到的每个特征如何影响我们模型的预测,直到我们到达顶部,这是我们对这一特定数据行的最终预测。还有许多其他方法可以将模型中的 SHAP 值可视化;这些例子只是让你开始。

结论

我们研究了 SHAP 值,这是一种解释机器学习模型预测的方法。通过这种方法,我们可以查看单个预测,并了解每个特征如何影响结果。我们通过查看一个决定房屋价格的模型,逐步完成了 SHAP 值的示例计算。我们还研究了 Python 中的 shap 库,以便能够快速计算和可视化 SHAP 值。特别是,我们讨论了可视化 SHAP 值的力图和决策图。

感谢您的阅读!

消息来源

您可以通过以下渠道与我联系:

Shapash 1.3.2,宣布了更多可审计人工智能的新功能

原文:https://towardsdatascience.com/shapash-1-3-2-announcing-new-features-for-more-auditable-ai-64a6db71c919?source=collection_archive---------37-----------------------

AMIT·马哈托Unsplash 上拍摄的照片

Shapash 版本 1.3.2 现已发布,该库增加了一个新特性:Shapash 报告,一个帮助你的模型可审计的 HTML 文档!

Shapash是由 MAIF 数据团队于 2021 年 1 月发布的一个 Python 库,旨在让机器学习模型能够被所有人理解。

沙帕什 允许:

  • 数据科学家能够轻松地分析他的模型,与客户分享并验证他的方法
  • 最终用户理解来自 ML 模型的推荐/预测,这要归功于引导它的标准的适应总结。

Shapash当前正在使用一个 Shap 后端来计算本地贡献。Shapash提供了易读的可视化和一个 web app 。它以适当的措辞显示结果(预处理反向、后处理等)****

你会在这篇文章里找到 Shapash 的大概介绍。

版本 1.3.2 现已推出,https://github.com/MAIF/shapash****允许数据科学家记录他发布到生产中的每个模型。在几行代码内,他可以在一个 HTML 报告中包含关于他的模型(及其相关性能)、他使用的数据、他的学习策略……该报告旨在与数据保护官员、内部审计部门、风险控制部门、合规部门或任何想要了解他的工作的人轻松共享。****

语境

人工智能很吓人:“个人数据有什么用途?AI 是为了什么目的而开发的?对就业有什么影响?我们的自由吗?…"

如此多的问题往往没有答案,并留下了猜测的空间。这是一个非常热门的话题,许多玩家都在讨论。

首先,公共当局:在法国,ACPR 在 2020 年发表了一份关于人工智能算法治理的讨论文件。欧盟已经与 GDPR 建立了第一个框架,该框架可能很快会通过一项关于人工智能的法规来完成,该法规将主要解决治理、可审计性和控制等问题。**

在法律框架之外,各组织都在致力于建立一种负责任、值得信赖的数据科学。例如,subra Foundation共享了一个评估工具,允许每个公司独立评估其数据科学实践,并确定需要改进的领域。****

最后,一些私营公司是其组织内值得信赖的人工智能的参与者。一些法国公司已经建立了人工智能道德的治理机制。在这个问题上,Impact IA 智库在 2020 年底发布了一份指南,介绍了建立可信人工智能治理的具体案例。最后,其他玩家已经实现了最佳实践指南并正在分享它们。

在这个新版本 1.3.2 中,MAIF 的 Shapash 通过使用模板促进这些模型的系统化文档化,对模型可审计性的主要问题做出了更进一步的贡献。

沙帕什报告:

Shapash Report是一个“独立的”HTML 文档,由数据科学家在将他的模型部署到生产中时用一行代码生成。它允许他记录他的项目,并且将与他的模型的训练和上游步骤(数据准备、范围界定等)相关的所有信息冻结在“当前快照”中。**

这份报告通过详细记录每个部署的算法,有助于改善人工智能治理。它允许组织中的每个人理解为什么、如何、用什么数据以及为了什么目的而构建模型。

我们希望它将成为模型审计和更好的人工智能治理的一个有价值的工具!

一个开放的工具:每个组织都可以修改其 Shapash 报告的内容。

在等待为该文档指定标准内容的法规时,提供一个开放的解决方案对我们来说很重要。因此,每个公司都可以调整该工具,并定义自己的“标准”,每个数据科学家都将在自己的项目中实施该标准。

关于模板的建议

Shapash 1.3.2 提出了一个每个人都能适应的模板。你会在该项目的 Github repo 上找到一个教程,展示如何实现这个模板,以及如何按照你的意愿修改它。在我们提出的示例中,您会发现以下信息:

  • 一般信息:项目名称、描述、目的、模板开发人员、时间…

**************

  • Dataprep:数据从哪里来,哪里可以找到数据准备程序,…
  • 特征工程和培训策略:实施的策略是什么,与该部分相关的计划是什么。
  • 关于模型的信息:什么类型的模型?使用了哪些超参数?
  • 训练和测试数据集的分析:模型中引入的所有特征的描述和相关性分析。
  • 整体模型可解释性:模型的主要特征是什么?每个特征对推荐/预测有什么影响?
  • 模型的性能:恢复与模型相关的度量,测试数据集上预测的分布。

这份报告的内容非常完整。此外,为了便于导航, Shapash Report 提供了“目录”部分以及不同的菜单按钮。

Shapash 报告 受益于所有的 Shapash 数据措辞功能:与每个特性相关联的功能标签都呈现在这个 HTML 文档中,以便所有人都能理解共享的内容,尤其是那些没有参与模型构建的人。

如何创建此报告?

例如,让我们在一个具体的数据集上一起测试 Shapash 并创建这个报告。同样,我们建议您使用我们喜爱的著名 Kaggle House 数据集:“房价数据集。我们来拟合一个预测房价的回归变量吧!首先加载数据集:

***import pandas as pd
from shapash.data.data_loader import data_loading
house_df, house_dict = data_loading('house_prices')
y_df=house_df['SalePrice'].to_frame()
X_df=house_df[house_df.columns.difference(['SalePrice'])]house_df.head(3)***

对分类特征进行编码:

***from category_encoders import OrdinalEncodercategorical_features = [col for col in X_df.columns if X_df[col].dtype == ‘object’]
encoder = OrdinalEncoder(cols=categorical_features).fit(X_df)
X_df=encoder.transform(X_df)***

训练、测试分割和模型拟合。

***Xtrain, Xtest, ytrain, ytest = train_test_split(X_df, y_df, train_size=0.75)
regressor = RandomForestRegressor(n_estimators=50).fit(Xtrain, ytrain)***

干得好,你有一个模型可以投入生产了!但在此之前,让我们记录我们的项目!

填写您的项目信息

****第一步:创建一个包含项目信息的 YML 文件。
您可以在这里使用可用的示例文件。

欢迎您将此文件用作自己报告的模板。

现在,您已经指定了想要显示的所有信息,您可以使用 Shapash 来创建报告。

第二步:声明并编译 SmartExplainer 对象

*****from** **shapash.explainer.smart_explainer** **import** SmartExplainer

xpl = SmartExplainer(features_dict=house_dict) *#Optional: Labels* xpl.compile(
    x=Xtest,
    model=regressor,
    preprocessing=encoder, *# Optional: Apply inverse_transform* 
)***

在这一步,您可以使用任何方法来探索和理解您的模型。但让我们保持专注,创建我们的 Shapash 报告。

您需要传递x_trainy_trainy_test参数,以便探索训练模型时使用的数据。您还将指定要在报告中显示的指标。

***xpl.generate_report(
 output_file=’output/report.html’, 
 project_info_file=’utils/project_info.yml’,
 x_train=Xtrain,
 y_train=ytrain,
 y_test=ytest,
 title_story=”House prices report”,
 title_description=”””This document is a data science report of the kaggle house prices tutorial project. 
 It was generated using the Shapash library.”””,
 metrics=[
 {
 ‘path’: ‘sklearn.metrics.mean_absolute_error’,
 ‘name’: ‘Mean absolute error’, 
 },
 {
 ‘path’: ‘sklearn.metrics.mean_squared_error’,
 ‘name’: ‘Mean squared error’,
 }
 ]
)***

搞定了!你创建了这个报告

定制您自己的报告!

你可以更进一步!让我们通过添加一些新的部分来自定义你的报告。

更多详情请点击查看

💡分享你的想法!

请随意访问 Shapash GitHub:你会找到关于这个新特性的详尽文档。您也可以在那里留下您的消息(讨论选项卡),并通过共享您的模板或任何其他想法来为解决方案做出贡献。愿 Shapash 为开发一个值得信赖的 AI 做出贡献!

Shapley 值辅助材料配方设计

原文:https://towardsdatascience.com/shapley-value-aided-recipe-for-materials-design-d122fb851cef?source=collection_archive---------9-----------------------

追求新材料时解码特征的重要性

杰瑞米·托马斯Unsplash 上拍照

“数据只是成千上万个故事的总结——讲几个这样的故事来帮助数据变得有意义。”—丹·希斯

简介

在我之前的文章 " 使用 Matminer 和 Pymatgen 揭示材料数据的潜力"中,我展示了材料数据挖掘工具的应用,以从材料数据集中提取基本信息,并使用它们来表征数据集。

现在所有的特征都可用了,是时候确定它们在机器学习(ML)模型中的相关性了。因此,在本文中,我将重点关注“特征重要性”这一方面,并展示它如何在寻找具有改进性能的材料中发挥至关重要的作用。

约翰·麦克阿瑟在 Unsplash 上的照片

数据集可能包含大量与目标变量相关的要素或预测值。现在,所有这些功能可能对实现目标的贡献并不相等。一些可能比另一些对 ML 模型的结果有更大的影响。这些特征基于它们的重要性被分级。

让我们以设计飞机机身的轻质(低密度)材料为例。这是一个多目标优化问题,其中设计要求结合低密度、高强度、抗冲击性和耐腐蚀性。飞行器主体主要是铝(Al)合金,其中具有低原子量和低密度的元素 Al 是主要成分。这种合金还含有其他元素,如铜、镁和硅。特征“Al”在密度特征重要性列表中占据最高位置。与此同时,其他因素的重要性也不容忽视。例如,当目标变量是强度时,铜排在首位。

因此,特征的相关性在很大程度上取决于目标属性。这就像烹饪一道特殊的菜肴,菜谱要求不同的配料(相当于 ML 中的“特征】)(与“特征重要性”相关)以获得最佳的味道。

因此,从海量数据中提取重要特征的艺术为技术进步铺*了道路。然而,通过部署可解释的人工智能(XAI)算法,这项回收和重用数据的庞大任务变得更加顺利。可解释性因素又由描述符的特征重要性决定。有鉴于此,Shapley 值算法被发现在产生决策洞察数据方面非常有效。

沙普利值概述

Andrey Metelev 在 Unsplash 上拍摄的照片

Shapley 值源于博弈论的概念,最早由 L . S Shapley 提出。该值是从事件结果中涉及的不同因素或参数的所有可能排列所获得的边际贡献的*均总和计算出来的。让我用一个例子来解释一下。三个朋友 A、B 和 C 一起购买了价值 100 美元的食物。现在,我们将做出以下假设:

1.如果他们单独购买食物,A、B 和 C 将分别花费 60 美元、45 美元和 15 美元。

2.A 和 B 一起将花费 70 美元,A 和 C 一起将支付 65 美元,而 B 和 C 一起将花费 80 美元。

3.如果 A、B 和 C 合作一起购买食物,那么按照他们参与的顺序,六种可能的排列是可能的:(A、B、C);(甲、丙、乙);(乙、丙、甲);(B,A,C);(C,A,B)和(C,B,A)。

4.请注意,所有这些排列的总和应为 100 美元。

在这样的合作场景中,每个参与者的边际贡献取决于他们贡献的顺序。根据 A、B 和 C 的边际贡献,可以计算每个玩家的预期边际贡献或 Shapley 值。这些列表如下:

同样的概念被应用于解释和诠释机器学习预测,否则,机器学习预测将被视为黑盒。Shapley 值已被证明在具有一致性和准确性的分类(基于概率的)和回归模型中有效地解释了个体特征在最终预测中的作用。

李和斯隆伯格开发的 SHAP ( 沙普利附加解释 ) API 足够灵活,可以应用于任何基于树和非树的 ML 以及深度学习系统。TreeExplainer()和 KernelExplainer()函数分别与基于树的 ML 和基于非树的 ML 相关联,用于获得最终预测中涉及的每个特征的贡献。

现在,让我从几种成分的可用实验数据库开始,展示 SHAP 值在设计高性能热电材料蓝图的策略中的有用性。我已经用 Google Colab 运行了全部代码。

基于 SHAP 的系统化方法,用于发现具有所需功能的材料

导入相关库,加载数据集,预处理

在运行任何机器学习算法之前,一个重要的基本规则是导入所有需要的库。在这种情况下,除了导入标准 Python 库,如 NumPy、Pandas 和 Matplotlib,还安装了其他基于材质的 Python 包,如 Matminer、Pymatgen 和 SHAP。

我收集了 204 种成分/材料的数据集(显示在公式栏中),以及它们的室温特性(PF 和 kappa)。按照我上一篇文章中提到的步骤对数据集进行预处理。下面显示了准备用于训练的细化数据集的片段。

可工作数据集的输出片段

*注意,在用于材料勘探的真实世界数据集中,包含过程变量是优化的必要条件。

定义 X(特征/描述符)和 y(响应/目标)

这里,有 49 个特征/描述符被指定为 X,并且这些是构成公式的单独元素。有趣的是,该数据集涉及两个响应/目标——PF(目标 A)和 kappa(目标 B ),指定为 y。目标变量——PF 和 kappa,一次考虑一个用于训练。因此,y 分支为 y_pf 和 y _κ,分别为 pf 和κ。对于两种训练,X 保持不变。

X = ds_RT.iloc[:, 1: 50]
print(X)

显示预处理数据集的输出片段

y_pf = ds_RT.iloc[:, -1]
print(y_pf)y_kappa = ds_RT.iloc[:, -2]
print(y_kappa)

证明多个目标的合理性

你可能想知道选择 PF 和 kappa 这两个目标背后的基本原理是什么。

因此,在详述代码之前,我想解释一下与数据集相关的科学术语,以便恰当地捕捉材料设计方面的数据分析的重要性。

该数据集整理了材料及其两个重要的室温特性——PF(功率因数)和 kappa,κ(热导率)。这些材料是热电材料,通过热量发电,反之亦然,被认为是绿色能源。由于这类材料涉及热和电,因此它们的κ和电导率(σ)参数与计算性能指标(ZT 或品质因数)密切相关。此外,对于 ZT 计算,还有一个关键参数,称为塞贝克系数(S),这是一个控制热能和电能转换的转换系数。在绝对温度 T 下,ZT 与所有这三个参数 S、σ和κ的关系为:

S 与σ的*方之积称为功率因数(PF)。从该关系式可以清楚地看出,潜在的热电材料应该具有高的 PF 和低的κ。

我的代码旨在建立一个机器学习模型,以识别元素的可能组合,形成具有高 PF 和低κ理想特性的新型热电材料。因此,选择这两个参数作为目标是合理的。在这里,我将展示各种元素与 PF 和 kappa 的独立相关性,然后计算它们的 SHAP 值,这将最终有助于设计新的组成。

目标为 A (PF)的培训 1

将数据集拆分成训练和测试批次

预处理的数据集按照 80:20 的比例分为训练和测试批次,如下面的代码片段所示。

from sklearn.model_selection import train_test_splitX_train_p, X_test_p, y_train_p, y_test_p = train_test_split(X, y_pf, test_size = 0.2, random_state = 0)

拟合成机器学习算法

训练批次 X_train 和 y_train_p 用随机森林回归器算法拟合。

from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor(n_estimators = 50, random_state = 0)
rf.fit(X_train_p, y_train_p)

计算 SHAP 值来评估每个特征的贡献

使用 TreeExplainer()获得影响 PF 的元素的 SHAP 值。与随机森林算法的特征重要性等级相比,这种分析更加可靠。后一类不区分密切相关的变量,只突出一个变量的重要性,而忽略另一个变量。这个缺点被 SHAP 方法克服了,该方法努力地预测每个变量的贡献。此外,强调每个特征对目标的影响方向,包括正面和负面的,赋予这种方法独特性。

import shap
explainer = shap.TreeExplainer(rf)
shap_values_pf = explainer.shap_values(X_train_p)
shap.summary_plot(shap_values_pf, X_train_p)

使用 SHAP 值解释模型结果

SHAP 值表示目标上每个特征的强贡献和弱贡献,分别用红色和蓝色进行颜色编码。这在《SHAP 概要》情节中刻画得很漂亮。

显示元素对 PF 影响的 SHAP 汇总图

SHAP 图如何在材料设计中发挥作用?

X 轴为 SHAP 值,Y 轴代表变量,该图生动地描述了直接提高 PF 的积极贡献。图上的每个点表示数据集中的一行。快速浏览 SHAP 汇总图,可发现可能的元素,如锡、锑、镁、铋、钴、硅、锌,这些元素可用于获得理想的高 PF 值。

然而,要设计一种新颖的热电材料,我们还需要找到有助于降低 kappa 的元素。因此,我们的策略是确定同时满足具有高 PF 和低 kappa 的要求的组合物。这促使了以 kappa 为目标变量的第二次训练。

目标为 B(κ)的训练 2

现在,我们使用相同的回归变量训练数据集,但将 kappa(热导率)作为目标变量。SHAP 汇总图的获取方式与训练 1 中的相似。在这种情况下,我们感兴趣的是那些显示出对 kappa 高度负贡献的元素。这是因为最终的成分(材料)应该是不良的热导体。如图所示,只有少数元素如锑、锗、铪和钙有这种影响。

设计策略和现实世界的例子

在获得两个 SHAP 概要图之后,我现在可以进入本文的核心和最有趣的部分:材料设计。

让我们仔细观察这两张相邻放置的图,以选择能够导致潜在热电成分的组成元素的排列。

SHAP 汇总图

需要具有高的正 SHAP 值 PF 和高的负 SHAP 值 kappa 的元素组合来实现该任务。从图中可以明显看出,Sn、Mg、Bi 和 Zn 对 PF 具有大的正 SHAP 值,而 Sb 是唯一同时分别对 PF 和κ表现出高的正和高的负 SHAP 值的元素。维恩图很好地说明了 Sb 的相交面积,表明它具有增加 PF 和降低热导率的双重作用。

维恩图

因此,在我们寻找一种有效的新组合物时,Sb 可以被选作组成元素之一。并且新材料的其他成分可以明智地从分别有利于和不利于 PF 和 kappa 的元素范围中选择。

我做了一些研究来验证从生成的 SHAP 图中得到的结果与现实的接*程度。瞧啊。!文献中确实报道了具有从上述 SHAP 总结图中识别的元素的混合和匹配的预期成分。

最*研究的一种这样的合成物是 Sb)₂的 Mg₃(Bi,它在室温下表现出相当高的品质因数。这一直接证据证明了 SHAP 价值观的有用性和适用性。

结束语

巴德·海利森Unsplash 上的照片

这篇文章的核心是从长期收集的大量数据中指出 Shapley 值在编织新的高效材料中的重要性。ML 的兴奋围绕着建立一个合适的、可解释的模型,这正是 SHAP 所做的。这种改变游戏规则的技术背后的哲学是透明性,这使得任何 ML 模型都是可解释的和有生产力的。

我希望这篇文章激励越来越多的材料工程师和科学家探索 Shapley 技术,努力协调元素的相关属性,以获得适合应用的新成分。

在结束之前,这里的是整个代码的链接。

如果您觉得此工具有用,请分享您的意见和反馈。

感谢阅读!

围绕一个定制的网络

原文:https://towardsdatascience.com/shapling-around-a-custom-network-636b97b40628?source=collection_archive---------32-----------------------

博弈论能扭转局面吗?

Rbm托马斯 G.本杰明拉鲁斯

这是一项研究的第二部分,在这项研究中,将莱姆和 SHAP 应用于神经网络,以预测一个人的购买概率。关于网络架构的细节,连同应用 LIME 的结果我们参考 前面的文章

在可解释性领域,仅次于莱姆的另一个头条新闻是 SHAP(SHapley Additive exPlanations 的缩写)。

比如 LIME,SHAP 是一个模型不可知的解释者,他的目标是提供对模型输出的局部洞察。与 LIME 的主要区别是解释器的严格的数学基础:它允许为可解释性定义一个通用框架,该框架包括几个已经存在的算法(包括 LIME)。

接下来的部分简要介绍了 SHAP 及其在我们用例中的应用结果。

SHAP 或合作的艺术

远不止是一个新的解释者,SHAP 结合了不同的已经开发的方法,从而强调了某些共同的特征,并提供了一个共享的背景,允许将它们归入同一保护伞下,并确保一个坚实的数学基础。

根据我们的用例,介绍集中在方法内核 SHAP,这是一个石灰和沙普利值的组合。关于其他方法的更多信息和对 SHAP 的更深入理解,我们参考最初的论文。为简单起见,在下面几节中,我们将“内核 SHAP”写成“SHAP”。

比如莱姆,SHAP 旨在用拟合附*的线性模型对实例进行解释。LIME 和 SHAP 之间的第一个区别是用于拟合线性模型的训练数据的生成方式。

LIME 基于模型的训练集的特征(或者基于训练集本身,如果可用的话)生成一组扰动数据。SHAP 生成从实例中保留或删除的特征的联盟以进行解释(想象它是在实例上应用“0/1”的掩码,其中“0 =删除特征”和“1=保留特征”),并用一些“代表”值替换要丢弃的特征。这些值可以基于训练数据,也可以是特定的。

例如在 LIME 中,然后将扰动的集合传递给原始模型,以便生成相应的标签。

为 SHAP 生成输入数据和标签的方案。(图片作者提供)

一旦产生了扰动的数据,就通过最小化加权 RMSE 来训练可解释的模型,就像在 LIME 中一样。

那么有什么好大惊小怪的呢?到目前为止,用不同的微扰方法,SHAP 似乎与石灰相同。然而,SHAP 为加权函数和复杂性度量提供了具体的选择:这些是解释者满足局部准确性、遗漏性和一致性的唯一有效选择。

为什么我们想要这些财产?

这些属性确保我们在评估特征贡献时获得每个特征的 Shapley 值(或 Shapley 值的估计值)。

Shapley 值是合作游戏的一种可能的解决方案,即,它是将游戏的输出“公*地”分配给每个玩家的唯一解决方案。它评估一个玩家在所有可能的排列上的*均边际贡献,这代表了该玩家与其他人的联盟。

在我们的场景中,游戏是模型的输出,玩家是对输出有贡献的特性。

我们知道这个概念对读者来说可能并不十分清楚;解释了这么几行之后,事情就不清楚了。核心思想是,在 SHAP,加权函数和复杂性度量的选择有一个坚实的理论背景,这是缺乏在石灰在这些条款是可定制的参数。

将两块拼图拼在一起

因为 SHAP 只是一个对参数有不同选择的 LIME 解释者(请回忆一下,我们正在含蓄地谈论“KernelSHAP”),我们认为我们可以很容易地将其应用到我们的定制模型中(关于模型架构的细节,我们可以参考以前的文章)。我们当然错了😅。

LIME 中出现的一些问题也会在 SHAP 中出现,例如处理一次性编码或相关的要素。这些问题可以通过我们为石灰构建的相同的预处理/后处理步骤来解决。

我们无法在 SHAP 执行的转换是将输入数据从原始模型所需的形状重新整形为 SHAP(和石灰)所需的 2D 形状。当然,困难并不在于实际的整形行动(我们很清楚 Numpy 的存在),而在于手术在 SHAP 会产生的后果。

在时间上,这种转换涉及到 2D 阵列中 LSTM 细胞输入的整形;第二维的大小为 n_f*n_s,其中 n_f 是特征的数量,n_s 是实例的序列的数量。因为我们想对不同的实例使用相同的解释器,所以序列的数量必须是所有实例中序列的最大数量。

从模型输入到石灰输入的转换。(图片作者提供)

让我们想象同样的数据转换方法应用于 SHAP。

因为 SHAP 评估沙普利值,准确的评估需要生成大量扰动数据,这些数据能够探索对模型输出有贡献的所有特征的所有可能排列。

当应用与 LIME,2^(n_f*max(n_s)中相同的变换方法时,得到置换,这对于我们的模型是难以处理的。减少如此大量的扰动数据将会降低最终 Shapley 值的准确性。

而且,层序数量的分布向低位层序倾斜;因此,大部分数据将由填充值组成,不必要地过度计算。

基于这些考虑,我们修改了 SHAP 在石灰方面的应用。我们不是将原始输入转换为单个 2D 阵列,而是递归地将 SHAP 应用于实例的每个序列步骤以进行解释,从而仅针对每次迭代中的最后一个序列生成扰动数据。这减少了对 n_s*2^n_f.最优扰动的数量

从模型输入到 SHAP 输入的转换。(图片作者提供)

跳进水里之前先感受一下水

所有这些工作完成后,我们可以开始看有趣的事情:获得的实际解释。

SHAP 的一大特点是可以通过汇总不同实例的解释来收集大量信息。这也可以用石灰来完成;然而,在 SHAP,由于使用 Shapley 值而不是权重来衡量影响,由此产生的综合解释有一个更坚实的背景。

虽然这是一个很好的属性,但在顺序输入的特定情况下(如在我们的模型中),正确地组合 Shapley 值以获得对模型的洞察可能是困难的。

最常见的 SHAP 应用涉及二维输入(例如,观察值和特征),因此解释以可理解的方式呈现了不同实例中 Shapley 值和特征值之间的关系(我们基本上是在处理三维集合)。

在我们的例子中,还依赖于事件序列中的位置;在进行解释时,必须考虑这个额外的方面。为游戏中所有不同玩家之间的关系提供有意义的见解可能是一项艰巨的任务。

我们将在下一节中解决这个问题。

让我们从简单地解释一个事件序列的最后一步开始。

为了建立与之前关于 LIME 的工作的连续性,下图用与上一篇文章相似的布局(针对同一用户)给出了解释。我们在解释中明确省略了与产品评级相关的两个特征,因为我们在之前的研究中发现数据可能缺失。

使用 SHAP 解释单个实例的最后一步。(图片作者提供)

从解释中清楚地显现出两个方面:首先,不活动时间(即,在该用户的最后动作和预测日期之间经过的时间)是最重要的特征;第二,所有的功能都有助于增加购买的概率。

第一个见解与我们用石灰获得的相同。然而,尽管 SHAP 对的不活动时间赋予了正面影响,但莱姆赋予了负面影响,即的不活动时间降低了预测的购买概率。

这两个结果哪个是正确的?

其实两个结果都是对的。这种差异是由于莱姆和 SHAP 提供了不同的解释。

SHAP 定义了相对于从训练数据获得的预测的基值的特征影响。具有积极影响的不活动 _ 时间意味着该用户的不活动 _ 时间的值相对于模型的基础值增加了购买的可能性。

下图中 SHAP 图书馆的 force_plot 可视化方法清晰地呈现了这种解释。

使用基本 SHAP force_plot 函数解释单个实例的最后一步。(图片作者提供)

从训练数据获得的基值低于该用户的预测值;此外,所有特性都有助于将购买概率从基准值转移到预测值(注意:基准值低于预测值并不一定意味着所有特性都有积极影响;我们可以让具有负面影响的功能与具有更强正面影响的其他功能相*衡

其他功能的影响比不活动时间小得多,彼此之间只有细微的差别。

请记住,此解释指的是该用户的一系列事件的最后一步。因为利用 SHAP 的当前实现,我们可以在每个步骤中获得一个解释(而不是对所有步骤的一个解释,例如在 LIME 中),所以所评估的影响应该被认为如下:作为特征 X 相对于序列的最后一步中的基值对预测的贡献。

到目前为止,SHAP 和莱姆提供的见解是相似的。它们都强调了不活动时间相对于其他特征的优势。然而,在解释这两种情况下的结果时应该保持谨慎。

本节考虑了对序列最后一步中的单个实例的解释。这个用户的其他步骤呢?这个例子的结论也是全局有效的吗?

使用在 SHAP 评估的 Shapley 值,我们可以为沿路特征的影响以及它们对单个用户的整体影响建立一个有趣的解释。开始了。

沿着小路漫步

SHAP 的有效性和受欢迎程度与其坚实的基础、计算效率以及通过结合不同实例的本地解释而提供的全局洞察力有关。

用同样的潜力来为单个用户产生一个对整个事件序列的解释怎么样?

我们确实可以将每个步骤的 Shapley 值聚合到序列中,以了解某个功能的影响演变、整个功能对序列的影响,甚至某个步骤相对于其他步骤的重要性。可能性很多。

首先,在序列中的不同事件期间是否发生了一些有趣的事情?

直觉的回答是“是的”。例如,一些特征在用户交互开始时可能具有更大的影响。下图展示了这一想法。

使用 SHAP 力图函数解释序列的第一、中间和最后步骤中的单个实例。(图片作者提供)

该特征的影响确实可以在不同的步骤中改变,这也是由于不同步骤中不同的基值和不同的预测概率(因为 SHAP 解释器在序列的每个步骤中被训练,所以我们在每个步骤中都有基值和预测概率)

前面的数字似乎证实了我们最初的假设(序列中的位置对最终预测也有影响)。

对中间步骤和最后步骤的解释显示了一些相似之处:inactive _ time具有正面影响的主要角色,其他功能紧随其后。

相比之下,对第一步的解释是不同的。

首先,在这种情况下,只有几个特征对预测有影响。

不活动时间不再是最重要的功能;它已经被替换为 delta_time (即,在用户的先前交互之后经过的时间)。

这个观察很奇怪。初始步骤中的 delta_time 被设置为零,因为没有先前的步骤。该特征在事件开始时的重要性可能表明 delta_time 越短,购买概率越大(这是合理的直觉)。或者,它可以简单地强调第一步的重要性,作为购买途径的初始步骤。

在第一步中,我们可以看到对预测概率有负面影响的特征;值得注意的是,它们是与产品相关的特性。

仅根据这三个数字,可以建立关于特征在购买预测中的作用的一些假设:

  • 初始步骤是基于他/她的交互(根据序列开始时的 delta_time 的影响)来预测用户的购买概率的基础;
  • 用户看到的第一个产品可能会对购买概率产生显著的负面影响;
  • 用户交互越多(从而增加序列长度),个别功能的影响就越小,除了不活动时间。

我们记得我们正在查看单个用户的解释;因此,我们还不能将这些假设推断为一个全球性的解释。我们会到达那里。

这些都是有趣的(但多少有限的)见解;我们应该通过观察所有特征对所有序列步骤的影响来验证它们。

在这个方向上,下图显示了四个特征的 Shapley 值的演变。

作为序列步长函数的四个特征的 Shapley 值的演化。(图片作者提供)

不活动时间始终优于其他功能;它保持了一种*似恒定的积极影响。

除了 delta_time 的影响外,其他特征的影响相当弱;所有的特征在序列结束时都趋向于接*零的影响。此外,直到大约第五步,特征的影响才表现出明显的差异。

这个假设应该被其他特征所证实,并获得这个实例的所有特征的进化的更一般的概述。

为了实现这一目标,以下两个图显示了每个特征的 Shapley 值及其在每个序列步骤中的等级的热图。

第一个图证实了之前获得的结论:在第五步之后,特征的总体低影响进一步降低(除了不活动时间)。

第二张图显示了根据 Shapley 值的绝对值确定的特征等级的演变。虽然该图显示了某种程度上更丰富的行为,但所有功能的影响之间的实际差异相当小。

热图显示 1)每个序列步骤中每个特征的 Shapley 值;2)每个特征和每个序列步骤的排序。(图片作者提供)

通过堆叠每个序列步骤的结果,我们可以用包中的 force_plot 函数可视化;这种情况类似于多个实例的情况,只是在这种情况下,不同的实例是不同的序列步骤。

下图分别比较了根据原始顺序对序列进行排序的堆叠表示,以及它们基于 Shapley 值的相似性。

使用内置函数 force_plot 对不同序列步骤的堆叠说明:1)对原始序列顺序的堆叠说明;2)具有按相似性排序的序列的堆叠解释。(图片作者提供)

序列已被重新排列;因此,一些不一定彼此接*的步骤表现出相似性。因为每一步的 base_value 都不同,所以在这种情况下考虑所有序列的*均值。

到目前为止,我们还没有考虑一个特性的价值和它对 Shapley 值的影响是否相关。对这种相关性的深入了解通常可以通过 SHAP 现有的内置汇总图获得。因此,下面两个图展示了重新创建的蜂群图;在这种情况下,每个点代表同一实例的一个序列步骤,而不是实例本身。

第一个是 SHAP 软件包中绘图程序的复制品;Shapley 值和特征分别呈现在 x 轴和 y 轴上,并根据所有序列的 Shapley 值总和的绝对值排序。颜色代表特征值。

第二个图形与第一个几乎相同;但是,点的颜色代表序列中的位置。

根据这两个图,所有的特征通过将输出从基础值推至预测值,大多具有积极的影响。

第一个数字没有显示出 Shapley 值和特征值之间的任何显著关系。

Shapley 值和序列步长之间似乎有一种更有趣的关系:最大的负面影响发生在序列的第一步,并且总是在路径的最开始获得 delta_time 的极值。

蜂群图具有根据沿序列的 Shapley 值的绝对值之和排列的特征。1)点的颜色代表特征值;2)点的颜色代表顺序步骤。(图片作者提供)

我们可以公*地说,对于这个用户来说,事件序列中的位置对预测的购买概率有很大的影响,并且初始步骤是至关重要的。

从本地到全球

一个简单的例子已经为我们提供了许多关于特征对预测的影响的信息。此外,我们对序列步骤的作用获得了有趣的见解。

如果我们将 SHAP 应用于几个实例,会发生什么?

因此,我们试图通过结合对几个用户的解释来了解这些特性对模型结果的整体影响。

如前所述,为了获得关于特性影响的信息,我们准备了下图,为三个不同的用户在他们的路径的最后一步提供一个单一的解释。

使用 SHAP 解释最后一步中的三个不同实例。(图片作者提供)

这三种解释互不相同。在其中的两个例子中,不活动时间具有负面影响,这与前一个例子形成对比,并恢复了我们使用 LIME 找到的解释(请回忆一下两个解释的不同含义)。

在最后一个中,不活动时间不再是最具影响力的功能。

如果我们想要获得一些全球的洞察力,这个观察必须被更彻底地调查。

我们可以从再次查看内置的 force_plot 开始,它在各自的最后一个序列步骤中堆叠了不同的实例。下图显示了两个实例家族的存在:在一个家族中, inactivity_time 对最终预测有积极的影响(左),而在另一个家族中,它表现出相反的趋势(右)。

使用 SHAP 内置函数 force_plot 对最后一个序列步骤中的不同实例进行堆叠解释。(图片作者提供)

我们能获得更多的定量信息吗?序列的其他步骤会发生什么?

不活动时间真的是唯一有趣的特性吗?

这些都是有趣的问题。在这种情况下,由于额外的维度(我们应该在每个步骤和每个实例中呈现每个特性的影响,包括特性值对其影响的效果),很难提供结果的正确表示;相当多的信息要压缩在单个数字中)。

获得额外洞察力的简单方法是对实例的 Shapley 值进行*均;其结果是类似于上一节中呈现的那些表示;然而,这种表示指的是所有用户之间的*均影响。

下图显示了在序列的最后一步中特性的影响(实例的*均值)。

序列最后一步中特征的*均影响。(图片作者提供)

显然,*均行为与上一节中介绍的单个实例有很大不同;不活动时间增量时间是影响最小的特征。

当然,作为一个*均值,对不同实例具有负面和正面影响的特性的净影响可能低于对每个用户具有较小影响但符号相同的特性的净影响。

通过查看*均绝对值,可以更深入地了解特性的重要性。

序列最后一步中特征影响的*均绝对值。(图片作者提供)

根据上图,不活动时间仍然是最重要的特性,其他特性在事件序列的最后一步也有类似的影响。

让我们试着从最后一个步骤开始,更深入地了解整个过程。我们可以用概要图再做一次。

下图显示了所有序列步骤中所有实例的所有特征;颜色代表标准化的特征值。

蜂群图,其特征根据用户和序列的 Shapley 值的绝对值之和进行排序。这些点代表每个序列步骤中的每个实例。点的颜色代表归一化的特征值。(图片作者提供)

虽然大多数特性在 Shapley 值和特性值之间没有表现出明显的关系,但是对于 inactivity_time 却不是这样:显然,值越高,影响越负面。

我们发现不活动时间和预测购买概率之间的直观关系:用户的最后一次交互越老,对购买预测的负面影响越大。

如前一节所述,我们可以通过明确考虑事件序列中的位置来呈现结果。

蜂群图,其特征根据用户和序列的 Shapley 值的绝对值之和进行排序。这些点代表每个序列步骤中的每个实例。点的颜色表示沿序列的位置。(图片作者提供)

在这种情况下,除了 inactivity_time 之外,大多数特征都呈现出清晰的模式。这些结果似乎证实了上一节的结果:这些特征在序列开始时具有负的 Shapley 值,然后在序列的发展过程中向正的影响转变。

到目前为止,我们已经关注了不同步骤和不同输入值的特性和影响。让我们考虑一下顺序本身。有影响吗?(答案是“是”:我们已经看到了序列中初始步骤和最后步骤之间的显著差异)。

为了进一步了解序列中各个位置的影响,我们准备了下图。我们总结了每一步中不同特征的 Shapley 值。结果图显示了不同实例之间的分布情况;这些序列是根据重要性排序的。

Box_plot,根据特征上 Shapley 值的绝对值之和对序列进行排序。(图片作者提供)

同样,我们在序列中走得越远,积极的影响就越大;就 Shapley 值的绝对值而言,最显著的影响是在最后的步骤中。

我们已经深入研究了 SHAP 在现实世界应用中的潜力,包括递归神经网络的使用。

当将解释器应用于这种神经网络时,我们发现了与应用石灰类似的困难。此外,我们发现需要修改预处理流水线,以便更好地适应 SHAP。

这远非简单明了,但努力是值得的。

SHAP 的解释能力令人印象深刻。

它可能不如 LIME 直观,而且对于 KernelExplainer 来说,计算量仍然很大;然而,Shapley 值的组成特性允许建立丰富多样的解释。

为递归神经网络的三维情况建立深刻的解释可能具有挑战性;然而,沙普利价值观为实现这一目标提供了基础。其余方面取决于最终用户的需求和他/她的创造力。

这项工作已经在 easyence 数据实验室内完成。

具有 Azure 数据块和 Synapse 火花池的共享外部配置单元 Metastore

原文:https://towardsdatascience.com/shared-external-hive-metastore-with-azure-databricks-and-synapse-spark-pools-8d611c677688?source=collection_archive---------2-----------------------

了解如何设置共享的外部配置单元 metastore,以便在多个数据块工作区和 Synapse Spark 池中使用(预览)

图片由 Tumis u 在 Pixelbay

1 背景

为了帮助构建数据湖中的数据,您可以在 Hive metastore 中以表格的形式注册和共享数据。Hive metastore 是一个数据库,它保存关于我们数据的元数据,例如数据湖中数据的路径和数据的格式(parquet、delta、CSV 等)。

图片作者。

Azure Databricks 中的每个工作区都带有一个托管的内置 metastore。过一会儿,您会有新的团队或项目创建多个 Databricks 工作区,并开始注册它们的表。其他 spark 用户可能会使用 Synapse Spark Pools。然后,您意识到您想要共享来自不同工作区的表,但是每个元存储都是独立的,并且只能从每个工作区内访问。

您可能还想使用 metastore 在业务中共享表,将 Databricks SQL 与 metastore 结合起来为 BI 用户服务。

一种解决方案是创建一个共享的 metastore,以便不同的工作空间可以将其数据注册到一个共享的 metastore 中。

2 个共享外部 metastore

我们希望创建一个共享的外部 metastore。一个好的开始通常是查看文档:外部 Apache Hive metastore—Azure data bricks | Microsoft Docs

文档中有很多信息。你必须选择:

  • Hive metastore 版本
  • metastore 的数据库

我们需要 Databricks 运行时、为外部 metastore 保存元数据的数据库以及使其工作的 Hive 版本的正确组合。

2.1 数据块 spark 配置设置和外部 metastore

在我们进入匹配配置单元版本和后端数据库的细节之前,我们先看看如何告诉 Databricks 集群使用哪个 metastore。我们在集群的 spark 配置中提供我们的设置:

图片作者。

图片作者。

我们需要提供:

  • 要使用的配置单元架构的版本
spark.sql.hive.metastore.version X.Y.Z
  • 作为 metastore 后端的数据库的驱动程序和 URI。下面的例子使用 MySql 的“org.mariadb.jdbc.Driver”。
javax.jdo.option.ConnectionDriverName org.mariadb.jdbc.Driver
javax.jdo.option.ConnectionURL jdbc:mysql://mysqlserveruri.mysql.database.azure.com:3306/myextmetadb013?useSSL=true&requireSSL=false
  • 连接到数据库的凭据
javax.jdo.option.ConnectionPassword {{secrets/databricks/databricksmetastorepass}}
javax.jdo.option.ConnectionUserName {{secrets/databricks/databricksmetastoreuser}}

请注意,我们使用占位符来表示存储在 Azure KeyVault 中的凭据。你可以在 spark 配置中直接引用 Azure KeyVault 中的秘密。语法是:

{{secrets/scope/secretname}}

其中 scope 是您注册的作用域名称,secretname 是 Azure KeyVault 中的机密名称。如果你忘记了或者还没有向密钥库注册一个作用域,你可以在这里查看:https://docs . Microsoft . com/en-us/azure/databricks/security/secrets/secret-scopes了解如何注册。

如果您忘记了作用域名称和秘密,您总是可以使用 dbutils 来查看:

dbutils.secrets.listScopes()
dbutils.secrets.list(scope="myscopename")

确保为低于 2 的配置单元版本创建配置单元架构(第一次):

datanucleus.autoCreateSchema true
datanucleus.schema.autoCreateTables true

注意:模式的自动创建不适用于配置单元版本 2 和更高版本

  • 我们需要的任何罐子(0.13 不需要)
  • 其他一些可选设置不验证模式(第一次),因为我们创建了模式,但无法验证它。
datanucleus.fixedDatastore false
hive.metastore.schema.verification.record.version false hive.metastore.schema.verification false

当您为 metastore 创建了模式后,您可以设置回该属性:

datanucleus.fixedDatastore true

这可以防止对 metastore 数据库进行任何意外的结构更改。

2.2 选择 Hive 版本和学习

根据您选择的配置单元版本,配置单元的行为会有所不同。一些区别是:

  • 并非所有数据库都支持作为后端
  • 配置单元可以/不能自己创建架构。
  • 一些错误修复和功能。在这里查看所有版本和变更日志:【apache.org 下载

用蜂巢学习 0.13

我第一次尝试用的是 Hive 0.13(工作区默认内置版本)。使用 0.13 有一些好处。0.13 版可以通过设置属性“data nucleus . autocreateschema true”来为 metastore 生成模式。此外,所需的 jar 由 databricks 提供。

不要将 Hive 0.13 用于 Azure SQL DB。在我的测试中,由于在删除 metastore 中注册的表时 Datanucleus 中的一个错误,这种组合不起作用。虽然文档说它应该可以工作,但是它没有。

Azure MySql DB 5.7 与 Hive 0.13 配合良好,但请确保您设置了服务器参数将 lower_case_table_names 更改为 2。在为 metastore 创建数据库和表之前,请执行此操作。

这可以在 Azure 门户中完成:

图片作者。

然后在 MySql 服务器中创建一个数据库。在用 JDBC 连接字符串将数据块连接到数据库之前,我们需要创建数据库。

使用您喜欢的工具登录 MySQL 服务器,并使用您选择的名称为 metastore 创建一个数据库。示例:

CREATE DATABASE extmetadb013;

将以下内容添加到要使用的 Databricks 集群的 Spark 配置中,替换:

xxxscope, xxxsecretname, xxxserverurl, xxxdatabasename, xxxuser

使用您的数据库 URL 和凭据:

spark.sql.hive.metastore.version 0.13javax.jdo.option.ConnectionDriverName org.mariadb.jdbc.Driver
javax.jdo.option.ConnectionURL jdbc:mysql://xxxserverurl.mysql.database.azure.com:3306/xxxdatabasename?useSSL=true&requireSSL=false
javax.jdo.option.ConnectionUserName xxxuser
javax.jdo.option.ConnectionPassword {{secrets/xxxscope/xxxsecretname}}
datanucleus.fixedDatastore false
hive.metastore.schema.verification false
datanucleus.schema.autoCreateTables truehive.metastore.schema.verification.record.version false
datanucleus.autoCreateSchema true

在数据块中重新启动集群,以在 metastore 存储数据库中创建表。

在此之后,您应该能够看到新的数据库和创建的模式。

学习 Hive 2.3.7

Hive 2.3.7 使用 Azure SQL DB 作为后端。

突触

如果您想要在数据块和 Synapse Spark 池之间共享相同的外部 metastore,您可以使用数据块和 Synapse Spark 都支持的 Hive 2 . 3 . 7 版。在 manage 选项卡下链接 metastore 数据库,然后设置一个 spark 属性:

spark.hadoop.hive.synapse.externalmetastore.linkedservice.name HIVEMetaStoreLinkedName

请注意,这仍处于预览阶段(在我的测试中有点不稳定),因此还不适合生产工作负载。请参阅:将外部配置单元 Metastore 用于 Synapse Spark Pool(预览)以获得逐步指南。

数据砖块

Hive 版本 2.3.7 要求您在 Databricks 的 spark.config 中设置一个属性,告诉 spark 使用什么 jar:

spark.sql.hive.metastore.jars builtin

jar 是提供的/内置的,所以您不必自己下载 jar。注意:对于 Hive 1.x 和 3.x,您必须提供一个包含 jar 的文件夹,或者您可以在集群启动时使用 Maven 下载 jar,但是 jar 的下载需要相当长的时间,因此如果您以前下载过一次 jar,将会缩短启动时间。

手动创建 metastore 表

Hive 版本 2.3.7(版本 2.x 和更高版本)不会为您创建 metastore 表,并且文档没有清楚地告诉您如何创建表。我尝试了两种有效的方法:

  • 使用配置单元模式工具
  • 使用配置单元 SQL 脚本

使用 Hive schematool 创建 metastore 表

要使用 Hive schematool 二进制文件(/Apache-Hive-2 . 3 . 9-bin/bin/schema tool),您需要下载 Hive 和,下载 Hadoop Core,并在 hive-site.xml 中设置连接属性(您可以使用 proto-hive-site.xml 作为模板)。然后运行 schematool,它将连接到您的数据库并创建表。即使它确实有效,我也不会在这里详细讨论。我建议使用下面描述的 SQL 脚本。

使用 Hive SQL 脚本创建 metastore 表

有一种更简单的方法来为特定的 Hive 版本创建表/模式。您可以下载并运行 SQL 脚本。

从这里下载并解压最新的 2.3.x HIVE 版本:https://hive.apache.org/downloads.html

您将看到一个文件夹,其中包含不同配置单元版本和不同数据库的脚本:

图片作者。

例如,如果我们选择 mssql 文件夹(如果我们使用该数据库,则选择您的数据库),我们将找到不同模式版本的脚本:

图片作者。

在我们的例子中,我们将运行 Hive 2.3.7,并希望创建模式版本 2.3.0。在您喜欢的 SQL 编辑器中运行或粘贴脚本:

hive-schema-2.3.0.mssql.sql

来创建表格。

我们需要为集群设置 spark 配置,以使用 Hive 2.3.7 和我们的 Azure SqlDB:

在 Spark 配置中,用您的值替换:XXXDNSXXX、XXXDATABASEXXX、XXXUSERXXX 和 XXXPASSORDXXX,最好使用如上所述的 Azure KeyVault,以避免明文机密。

spark.sql.hive.metastore.jars builtin
javax.jdo.option.ConnectionURL jdbc:sqlserver://XXXDNSXXX.database.windows.net:1433;database=XXXDATABASEXXX;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
javax.jdo.option.ConnectionUserName XXXUSERXXX
javax.jdo.option.ConnectionPassword XXXPASSORDXXX
javax.jdo.option.ConnectionDriverName com.microsoft.sqlserver.jdbc.SQLServerDriver
hive.metastore.schema.verification.record.version true
hive.metastore.schema.verification true
spark.sql.hive.metastore.version 2.3.7

如果您愿意,可以将 metastore 的 spark 配置设置移动到一个共享的 init 脚本中,这样它就可以被许多集群使用。

3 通过共享 metastore 访问数据

现在我们有了一个共享的 metastore,可以用来从表名读取数据湖中的数据。

使用 metastore 查询数据块中的表:

使用相同的 metastore 查询 Synapse Spark 池中的相同表:

图片作者。

这要求不同的工作区和集群拥有对数据的读取权限。当使用共享 metastore 时,我们应该使用对数据湖的直接访问,即不使用装载来访问数据,因为装载可能因工作空间而异。如果我们查询关于在 metastore 中注册的表的信息,我们可以查看表后面的数据位置(直接访问 URL):

图片作者。

作者图片

我们可以看到,Databricks 和 Synapse 都使用在 metastore 中注册的直接访问 URL。

位置必须被所有读者理解。如果位置是直接 URL,它将跨用于读取数据的所有技术工作(只要读取器有访问权)。在数据湖中挂载文件夹是行不通的,因为这会要求读者在工作空间中拥有完全相同的挂载点。此外,其他工具,如 Synapse Spark Pools,可能希望使用 metastore,但可能无法挂载数据。

4 始终创建外部表

在数据块中创建表格时,使用:

df.write.saveAsTable("MyManagedTableName")

默认位置是将数据存储在本地 DBFS 文件夹下:

/dbfs/user/hive/warehouse/MyManagedTableName 

在 Databricks 工作区。

DBFS 属于工作空间,而不是您的数据湖。此外,一般建议是不要向 DBFS 写入任何敏感数据。我们应该通过在创建表时给出数据的位置来确保只创建外部的表。我们应该使用直接的 URL 到数据表,而不是挂载路径。下面是一个简单的例子,给出了在数据湖中的现有数据(增量格式)之上创建表时数据的位置:

图片作者。

我们必须说出数据的格式(上例中的 delta ),并指向数据所在的文件夹,以便在现有数据的基础上创建我们的表。

如果您想了解更多关于托管表和非托管表的信息,这里还有另一篇文章: 3 种使用 Apache Spark 创建表的方法|作者 AnBento |介绍了不同的选项。另外,官方文档在这里:数据库和表格——Azure Databricks |微软文档

5 允许集群直接访问数据

您可能已经注意到,我们还没有讨论如何直接访问数据湖中我们需要的数据。这可以在 spark 配置中使用 Azure KeyVault 来存储秘密。如何使用密钥或服务主体访问数据湖是另一个故事,但这里有文档的链接:
使用 OAuth 2.0 和 Azure 服务主体
访问 Azure 数据湖存储 Gen2,具体来说,您不想挂载,而是使用直接访问:
直接访问 ADLS gen 2

在 synapse workspace 中,您可以在“管理”选项卡下链接存储帐户,方法是使用密钥、服务主体、托管身份或用户分配的托管身份(预览)将存储帐户添加为链接的服务。

6 下一步是什么

一如既往,在这篇文章中,我想分享一些关于设置共享外部元商店的学习,例如在 Azure Databricks 和 Synapse Spark Pools 中使用。我希望您在开发下一个外部 metastore 的过程中获得了一些新的见解。

通过这个真实世界的房地产市场聚类分析来提高你的机器学习技能

原文:https://towardsdatascience.com/sharpen-your-machine-learning-skills-with-this-real-world-housing-market-cluster-analysis-f0e6b06f6ba0?source=collection_archive---------17-----------------------

这是一个实践项目,结合了主成分分析、层次聚类和 K-means 来提供最佳的聚类解决方案

来自 Pexels杰西卡·布莱恩特的照片

无论您是一名经验丰富的数据科学家,还是一名刚刚开始分析之旅的人,请相信我,在您职业生涯的某个阶段,您一定遇到过或将要遇到至少一个涉及细分/聚类分析的项目。作为一名数据科学家,这可能是最受欢迎和最重要的机器学习技能之一。

在本教程中,我将带您浏览我最*做的聚类分析,这完全是由我作为一名数据科学家对北卡罗来纳州住房市场见解的好奇心所驱使的(为什么是北卡罗来纳州?嗯,那是我住的地方,它是*年来蓬勃发展的地区,房地产市场势头强劲😉).

在这个动手项目中,您将分析从北卡罗来纳州 162 个社区收集的住房市场数据,并使用无监督的 ML 模型,根据这些社区在一些关键指标上的相似性和差异来识别这些社区的聚类。原始数据来自 Redfin 数据中心,可以免费下载。

你准备好了吗?我们走吧!

聚类分析简介

在我们开始编码之前,让我们先回顾一下关于聚类分析的知识。聚类分析是一种非常流行的机器学习技术,广泛用于许多应用,例如客户细分、图像处理、推荐系统等。

一般来说,聚类分析属于无监督机器学习模型的范畴。顾名思义,无监督 ML 模型不是使用训练数据集进行监督的。换句话说,该算法没有为训练数据提供任何预先分配的标签(例如,聚类标签)。相反,模型从给定的数据本身中发现隐藏的模式和见解。因此,它在本质上非常具有探索性和‘好奇性’。

聚类分析实例(图片来源:维基百科)

存在不同类型的聚类方法,例如基于连接的方法、基于质心的方法、基于密度的方法、基于分布的方法等等,每种方法都有其自身的优点和缺点,并且适合于不同的目的和使用情况。

在我们的项目中,我们主要关注使用上面提到的两种聚类技术:层次聚类(基于连通性)和 k-means(基于质心)。这两种无监督的 ML 技术都基于邻*性(使用距离度量)。它们很简单,但在许多集群任务中非常有效和强大。

下载、读取和准备数据

首先,让我们去 Redfin 的数据中心,向下滚动到“它如何工作”部分,并下载“邻居”级别的区域数据。这是一个开放的数据集(。gz 文件),可以免费下载和使用。

来源:Redfin 住房市场数据(【https://www.redfin.com/news/data-center/】T2)

接下来,让我们打开 Jupyter 笔记本,导入所有必需的库,并读入数据。这是一个相当大的邻域级数据集,所以读入 python 可能需要一些时间。

这是一个庞大的数据集,因此为了简化分析和便于演示,我们只关注最* 3 个月(2021 年 7 月至 9 月)在北卡罗来纳州出售的“独栋住宅”房产。我们还会过滤掉在此期间出售少于 20 处房产的社区。

原始数据如下表所示,共有 58 列。列“区域”是邻域名称。

图片由作者提供

图片由作者提供

对于我们的聚类分析,我们不需要所有这些列。我们将基于五个要素创建聚类,因此我们使用以下代码仅保留数据框中感兴趣的字段。

具有五个特征的聚类分析数据框(图片由作者提供)

数据清理(缺失值、异常值等。)

在进行分析之前,让我们快速检查一下是否有任何缺失值或异常值需要处理。

图片由作者提供

数据看起来已经相当不错了。所有列都没有缺失值。看起来特征“median_dom”和“homes_sold_yoy”可能具有潜在的较大异常值,但其余特征似乎在相当合理的范围内。

使用箱线图检查异常值(图片由作者提供)

让我们通过使用以下代码将最大值限制在 99%来处理‘median _ DOM’和‘homes _ sold _ yoy’的异常值。

异常值处理后的数据框(图片由作者提供)

执行 PCA(主成分分析)

在我们将我们的特征输入聚类算法之前,我总是建议您首先对您的数据执行 PCA。PCA 是一种降维技术,允许您只关注能够代表数据中大部分信息和差异的几个主要成分。

在聚类分析的背景下,特别是在我们没有大量特征的情况下,执行 PCA 的主要优势实际上更多的是可视化。执行 PCA 将帮助我们识别前 2 或 3 个主成分,以便我们可以在 2 或 3 维图表中可视化我们的聚类。

为了进行 PCA,让我们首先将我们所有的特征归一化到相同的尺度,因为 PCA 和基于距离的聚类方法对异常值和不同的尺度/单位很敏感。

接下来,让我们执行 PCA 分析,并使用下面的代码显示解释数据中大部分差异的主要成分。

您可以看到,前 3 个主成分加在一起解释了数据中约 80%的方差。因此,我们可以只使用前 3 个主成分进行聚类,而不是使用我们模型的所有 5 个特征。

图片由作者提供

最后,让我们看看每个原始变量在这些主成分上的权重,以便我们可以很好地了解哪些变量对哪些主成分影响最大,或者换句话说,我们可以推导出这些主成分的一些意义。

图片由作者提供

这个看着挺有意思的!PC1 在很大程度上受“median_dom”(市场中值天数)的影响,因此这个主成分代表了一个社区的房产销售速度。我们可以称之为“销售速度”。

PC2 在很大程度上受“new_listings_yoy”(与去年同期相比,新上市数量的增加)的影响,因此这一项代表库存数量或新上市数量的同比变化。我们可以称之为“供应/需求/新上市”。

PC3 在很大程度上受“avg_sale_to_list”(销售价格除以标价的比率)和“median_sale_price_yoy”(销售价格中值的年变化)的影响,这两者都与价格有关。我们可以给 PC3 贴上“销售价格变化”的标签。

执行分层聚类

我们已经准备好将数据输入到聚类算法中了!首先,我们将尝试分层聚类。分层集群最棒的一点是,它允许您构建一个集群树(称为“树状图”)来可视化集群步骤。然后,您可以水*分割树,根据树结构选择最有意义的集群数量。

图片由作者提供

在上面的树状图中,我们可以看到,根据您放置水*线的位置,您会得到不同数量的聚类。看起来 4 集群或 5 集群都是合理的解决方案。让我们用散点图绘制 4 集群解决方案,看看它是什么样子。

图片由作者提供

这并不坏,它让我们对这个数据中可能存在多少个可能的聚类以及这些聚类在散点图中的样子有了一个基本的了解。然而,层次聚类的结果似乎并不理想,因为我们可以看到,有一些“有问题”的数据点可能被分配到错误的聚类中。

分层聚类虽然在通过树结构可视化聚类过程方面非常有帮助,但也有一些缺点。例如,分层聚类只对数据进行一次遍历。这意味着在流程早期错误分配或指派的记录不能在随后重新指派。

因此,我们很少使用层次聚类解决方案来停止分析,而是使用它来“直观地”了解聚类可能的样子,然后使用迭代方法(例如,k-means)来改进和完善聚类解决方案。

执行 K 均值聚类

K-means 是一种非常流行的聚类方法,通过该方法,我们指定所需的聚类数 k,并将每个记录分配给 k 个聚类中的一个,以便最小化聚类内的离差度量。

这是一个迭代过程,它分配和重新分配数据点,以最小化每个记录到其分类质心的距离。在每次迭代结束时,都会实现一些改进,并重复该步骤,直到改进非常小。

要执行 k-means 聚类,我们需要首先指定 k(聚类数)。我们可以通过几种方式做到这一点:

  1. 使用我们的领域知识或过去的经验指定 k
  2. 执行层次聚类,以初步了解可以尝试多少个聚类
  3. 用“肘”法确定 k

从上一步的树状图中,我们已经知道 k=4(或 k=5)似乎工作得很好。我们还可以用‘肘’的方法再检查一遍。下面的代码绘制了“肘”图,告诉我们最佳集群数量的转折点在哪里。

图片由作者提供

看起来结果与我们从树状图中得到的非常一致:4 和 5 都是合理的聚类数目,所以让我们尝试 k=5。下面的代码生成 5 个聚类的三维散点图。

图片由作者提供

描述集群并获得洞察力

现在我们有了我们的聚类,让我们将聚类标签添加回我们的原始数据框(df_NC ),将其导出到一个. csv 文件并从中获得见解。

我使用我最喜欢的仪表板工具 Tableau 来可视化这些集群的特征、相似性和差异。我在二维散点图中绘制聚类,就像我们在 Python 中所做的一样。

x 轴是我们称为“销售速度”的第一个主成分。y 轴是我们标记为“供应/新上市”的第二个主成分。圆圈的大小代表第三个主要成分,即“价格变化/销售额与价目表比率”。在这个控制面板中,您还可以将鼠标悬停在每个圆圈上,查看哪些是热门市场区域,工具提示中会提供更多详细信息。

图片由作者提供

祝贺您跟随教程,并通过这个动手项目提升您的机器学习技能!我希望你喜欢这篇文章。快乐学习!

你可以通过这个推荐链接报名 Medium 支持我。通过这个链接注册,我将收到你的会员介绍费的一部分。谢谢大家!

Python 中数据科学的 Shell 脚本

原文:https://towardsdatascience.com/shell-scripts-for-data-science-in-python-c004c9c6a4c5?source=collection_archive---------19-----------------------

学习 Bash 中命令行参数的基础知识,以便作为数据科学家在工作中充分利用 shell 脚本。

Jethro CarulloUnsplash 上拍摄的照片

让我们学习一点 shell 脚本,因为这将极大地提高您为 Python 脚本提供和解析命令行参数(CLA)的能力。

shell 脚本是一种计算机程序,设计用于运行 Unix shell,一种命令行解释程序。shell 脚本执行的典型操作包括文件操作和程序执行,这正是作为一名数据科学家学习基础知识的原因。

  • 为什么使用 shell 脚本?
  • shell 脚本中带有getopts的单划线 CLA
  • shell 脚本中的双破折号 CLA
  • Python 的内置argparse
  • argparse布尔值的教训:boolstore_true
  • 把所有的放在一起

为什么使用 shell 脚本?

Shell 脚本使您能够在单个脚本中自动执行一组命令行操作,一行一行地执行它们。您的项目已经为这些自动化步骤做好了准备,学习 shell 越早越好。

我在作为数据科学家的工作中使用它的几个例子:虚拟环境管理、PySpark 表的实例化、Python linters 的执行、静态文档网站的更新和构建、带有特定参数的生产管道的执行等。

shell 脚本中带有getopts的单划线 CLA

Bash 脚本有一个内置选项getopts来处理布尔标志和有可选参数的标志。getopts只能对付单杠 CLA,比如-a。它读取 while 语句中的:ab:如下

  • :第一个冒号启用静默错误报告模式 : getopts不会产生任何关于缺少选项参数或无效选项的诊断消息。通过抑制自动错误消息,您可以使用自定义消息来处理错误。
  • a case 代表一个布尔类-a
  • b: case 代表可选参数 CLA -b some_value

在 while 循环中,我们可以用<character>)语法捕获命令行参数;然后我们可以将 CLA 赋给一个变量,比如first_variable。有两种特殊情况

  • :上述案例抓住了缺失的论证错误。这仅在所有参数都是强制的情况下才有意义。
  • /?案例代表任何无效选项错误。注意,?需要被转义或加引号来匹配文字?,否则它会像正则表达式一样匹配任何单个字符。

我们可以用下面的命令行参数调用我们的脚本

**$** sh run.sh -a -b hello

shell 脚本中的双破折号 CLA

双破折号参数比看起来要困难得多,因为没有处理双破折号的内置方法:我们必须迭代每个 CLA 并匹配参数。这对于像--help这样的布尔参数来说相当简单。

我们对在$@中捕获的所有命令行参数使用 for 循环迭代。If-elif-else 语句以fi结束。这个特定的函数为每个参数寻找在双管|| OR 语句中捕获的两个字符串比较:--help-h

我使用 bash 支持的双括号[[ ... ]],但是您也可以使用单括号。点击阅读更多关于这两个的区别。

如果我们想要提供可选的参数,比如--arg1 some_var,这将变得更加复杂,我会参考 bash 中定制的 arg 解析器的文档。

同样值得一提的是,在大多数 Bash 内置命令和许多其他命令中,使用一个单双破折号--来表示命令选项的结束,之后只接受位置参数,比如**$** sh run.sh -a one -b two -- three four

Python 的内置argparse

现在进入更熟悉的领域:Python 脚本及其内置的argparse。使用这个内置的参数解析器增加了许多现成的功能。argparse使用所有数据类型,支持就地转换,默认值,并定义单和双—-破折号 CLA。我们的 Python 脚本run.py如下所示。

参数通过命令parser.parse_args()存储在一个对象中,我们通过每个参数的名称来检索这个对象,比如args.ageargs.debug。如果我们在不提供任何参数的情况下打印args,我们将得到以下具有默认值的对象:

Namespace(name='', age=1, date='20210709', debug=False, alive=False)

Argparse布尔值的教训

我得到的一个教训是,布尔值可以通过两种方式提供,要么通过使用type=bool的参数,要么通过使用action="store_true"的参数。无论你选择哪种方式,它的行为都会大不相同。我们来看下面两个案例:

**$** python3 run.py --name Louis --age 27 --alive --debug
>>> Namespace(name='Louis', age=27, date='20210709', debug=**None**, alive=True)**$** python3 run.py --name Louis --age 27 --alive --debug **True**
>>> Namespace(name='Louis', age=27, date='20210709', debug=**True**, alive=True)

如果你提供了type=bool,你需要添加一个标志True或者False使参数不是None。您只能通过在没有提供值的情况下添加默认值来避免这种情况。毫无疑问,如果您只提供标志--debug而不提供布尔值,它将导致None

另一方面,如果您应用action=store_true,您不需要提供任何布尔标志:提供参数--alive将它存储为True,不提供它将它存储为False。用action=store_false反之亦然。在 Python 的 argparse 文档中有更多关于这个的信息,请点击

把所有的放在一起

让我们测试一下我们的知识,创建一个 shell 脚本run.sh,它为我们的run.py提供命令行参数。我在我们的 shell 脚本中添加了一些有用的功能来解释它的用法和帮助功能,并避免误用参数。

如果变量是null ( None),则-z ${var_name}语法返回True${var_name}是如何在 Bash 或 shell 中调用变量,在字符串中调用"var_name = $var_name”。如果我们运行run.sh并打印run.py中的参数,我们将看到以下用法:

**$** sh run.sh -n Elvis -b 19350108 -a 42
>>> Namespace(name='Elvis', age=42, date='19350108', debug=False, alive=False)**$** sh run.sh -n Ringo -b 19400707 -a 81 -d False -l
>>> Namespace(name='Ringo', age=81, date='19400707', debug=False, alive=True)

我希望你喜欢这个故事和快乐的编码!

</7-tell-tale-signs-that-you-need-to-level-up-your-python-ed2e41d0d2eb>

幕府将军:一个被低估的 Python 机器学习包

原文:https://towardsdatascience.com/shogun-an-underrated-python-machine-learning-package-d306ac07b0e0?source=collection_archive---------36-----------------------

看看 Python 的幕府包,以及为什么它是 Python 中机器学习的一个很少使用的库

(src =https://pixabay.com/images/id-1556912/

介绍

在 Python 这个奇妙的世界中,有许多选项可以用来完成机器学习的任务。流行的例子通常包括使用 SkLearn 和 Tensorflow 这样的模块。SkLearn 是一个有用的模块,因为它可以用来解决预建机器学习模型的许多问题,这些模型试图通过使用一致的超参数来避免黑箱问题。然而,在这方面,SkLearn 肯定不是以这种方式有效解决问题的唯一解决方案。

虽然我们经常认为这是理所当然的,但是 Pythonic 包生态系统绝对是巨大的。当我们想以一种新的方式处理模型,或者只是从一个不同的 API 处理模型时,这就很方便了。我遇到的 SkLearn 包的最酷的替代品之一是一个叫做幕府将军的模块。幕府将军是一个基于 C++的库,使用与 SkLearn 相同的预构建概念。

为什么用幕府?

当然,由于幕府的用户群和维护者列表较小,使用这个包会有一些主要的缺点。文档就是一个很好的例子。没有文档,有效地使用任何用于机器学习的软件都是非常困难的,不管是不是最先进的。在幕府文档中已经投入了大量的工作,但是这将永远无法达到技术写作和组织的水*,像 SkLearn 这样一个得到良好支持的库已经工作了十多年了。由于缺乏文档和更大的用户群,另一个问题是缺乏支持。幕府将军类中可能会有抛出返回不等于零的东西,而没有关于为什么会发生异常的详细信息。当在 SkLearn 这样的包中发生这种情况时,可以很容易地搜索 throw 并找出您的代码到底有什么问题。另一方面,对于幕府将军来说,情况往往不是这样。

使用幕府将军而不是 SkLearn 的一个优点是,该库在语言方面更加成熟,这使得跨*台和在通常不能使用 SkLearn 的不同应用程序中更容易访问。Python、Javascript、C++、R、Ruby、C# mono 等语言都有实现,这使得幕府将军这个包更有可能被移植到任何其他可能需要使用的语言中。另一方面,SkLearn 主要是专门为 Python 用 C 编写的。当然,这意味着在大多数 C 衍生语言中都有通向该语言的桥梁,例如 C++或 C#,但它也不能与幕府将军在这方面的能力所提供的可访问性相提并论。考虑到这一点,可能需要注意的是,SkLearn 主要是为 Pythonic 数据科学家服务的,并且可能是他们个人的最佳选择。也就是说,我仍然认为交替使用两个包和它们的代码库是有好处的。

使用幕府将军

为了使用幕府包,我们当然需要安装 PIP。我使用的是 Ubuntu,以下是我个人的安装过程。我首先需要添加幕府工具 PPA:

sudo add-apt-repository ppa:shogun-toolbox/stable
sudo apt-get update

之后我分别装了 lib 幕府 18,然后 python-幕府。

sudo apt-get install libshogun18
sudo apt-get install python-shogun

关于机器学习对幕府的实际使用,首先要注意的是幕府是非常基于类型的,比 SkLearn 更是如此,例如,在 SkLearn 中,通常使用已经包含在其他模块(如 NumPy 或 Pandas)中的类型。这是一个重要的区别,很可能源于幕府将军在 C++中的独创性。此外,我认为这肯定有助于从如此多的不同 API 使用幕府将军,因为它真的不需要担心从许多不同的语言促进类型,而是更担心与自己的泛型类型工作。

对于今天的例子,我真的想展示一些我们在 Python 中使用的其他机器学习包并不普遍可用的东西。很可能大多数 SkLearn 用户都熟悉决策树和随机森林分类器的概念,它们使用 gini 杂质来计算模型的下一次分裂。幕府包中的一个非常酷的替代品是 CHAID,或者卡方自动交互检测器,tree。CHAID 树没有使用基尼指数,而是使用卡方检验来计算每一个分裂。这就是为什么我选择这个模型来进行讨论,因为它是不同的,它显示了你可以用幕府将军做很多用 SkLearn 做不到的事情。当然,为了开始这个项目,我们将在 Python 中引入科学计算的动态二重奏:

import pandas as pd
import numpy as np

我还将使用 SkLearn 中的 train-test-split 方法和 Ordinal Encoder 类,以便准备我的数据用于这些类型和这个模型。

from sklearn.preprocessing import OrdinalEncoder
from sklearn.model_selection import train_test_split

现在是时候准备我的数据,把它放入新的幕府类型,然后把它传递到我的模型。我不打算过多地描述我用于处理数据的代码,但是您可以随意检查我做了什么:

df = pd.read_csv("LatheBooks/atlcrime.csv")
df.head()
df = df.dropna()
target = "neighborhood"
feature = "feat"
encoder = OrdinalEncoder()
df["feat"] = encoder.fit_transform(np.array(df["npu"]).reshape(-1, 1))
train, test = train_test_split(df)
trainX = train[feature]
trainy = train[target]
testX = test[feature]
testy = test[target]

现在我们需要将这些数据放入新的特征类型中,然后我们就可以最终拟合我们的 Chi 树了!

features_train = RealFeatures(f_feats_train)
features_test = RealFeatures(f_feats_test)
labels_train = MulticlassLabels(f_labels_train)
labels_test = MulticlassLabels(f_labels_test)

接下来,我们需要设置我们的特征类型。这方面有三种选择:

  • 0 —标称值
  • 1-序数
  • 2-连续

如果我们要处理多个特性,我们将需要设置许多特性类型,但是因为我们只处理一个顺序编码的特性,我们可以只提供一个顺序为 1 的迭代列表。

ft = [1]

现在我们可以初始化新的 CHAID 树了:

classifier = CHAIDTree(0, ft, 10)
classifier.set_labels(labels_train)

然后训练和预测:

classifier.train(features_train)
labels_predict = classifier.apply_multiclass(features_test)

结论

幕府将军是一个非常棒的 Python 机器学习包。也就是说,我当然可以理解为什么与 Python 中的许多主流解决方案相比,它很少被使用。不管怎样,我很高兴能把这个包中的知识带回 C++中,并从这个包中得到一点乐趣。值得添加到您的 Python 安装中吗?有一些很酷的模型,我认为很难在其他地方找到,我认为可能对某些事情有好处。许可证也是 GPL3,它可能会阻止这个包在某些情况下被使用。话虽如此,我认为这是一个很酷的包检查出来!非常感谢您的阅读,我希望这篇文章影响了更多的探索!

Python 中的商店订单分析

原文:https://towardsdatascience.com/shop-order-analysis-in-python-ff13615404e0?source=collection_archive---------15-----------------------

用 Apriori 算法进行产品分析

照片由杰玛Unsplash 上拍摄

Apriori 算法用于数据挖掘,以识别数据集中的频繁项和关联规则学习。本文将关注一个实用且常见的用例,商店订单分析。例如,订购哪些产品比其他产品更频繁,以及订购哪些不相关的产品是订购另一种产品的结果。换句话说,也许购物者在买牙刷的时候会买牙膏,或者买面包的时候会买黄油。他们没有直接的联系,但是在两者之间找到联系并不是没有道理的。Apriori 算法有助于识别这些关联规则。

本文将提供一个非数学的演练,演示它如何使用 Python mlxtend 库工作。对于进一步的阅读,我推荐彼得·哈灵顿的《机器学习在行动 》中的第 11 章

https://www.manning.com/books/machine-learning-in-action

准备

我将使用一个 Jupyter 笔记本 来演示这一点。如果你的本地系统上没有安装 Jupyter 笔记本 你也可以使用 Google Colab ,它有免费的云版本。

我将使用用于 Python 的"mlx tend" Apriori 库。如果你没有安装它,你可以通过命令行或通过 Jupiter 笔记本直接安装。

# from the command line
$ **python3 -m pip install pandas mlxtend ploty matplotlib networkx**# or, from Jupyter notebooks
**!python3 -m pip install pandas mlxtend ploty matplotlib networkx**

像往常一样,Jupyter 笔记本的第一步是加载所需的库。

import pandas as pdimport networkx as nx
import plotly.express as px
import matplotlib.pyplot as plt
plt.style.use('default')from mlxtend.frequent_patterns import apriori
from mlxtend.frequent_patterns import association_rules

数据收集

出于本演练的目的,我将使用我在 Kaggle 上找到的一个数据集,名为“购物篮优化”。该数据集在订单中有一个很好的产品组合,但不是以一种清晰的方式呈现的。我不得不进行一些预处理以使其可行。

df_orders = pd.read_csv('Market_Basket_Optimisation.csv')
df_orders.shape
**(7500, 20)**

我们的数据集有 7500 行和 20 个特征。

作者图片

我不太确定为什么数据集的作者会这样展示数据。

第一步是创建一个求反的正则表达式。用下划线替换所有非字母数字字符和换行符。

df_orders = df_orders.replace(r'[^A-z0-9\n]+','_', regex=True)

然后,我们需要创建一个名为“ combined 的新特性,它的每一行都有一个 CSV 格式的列。

x = df_orders.to_string(header=False, index=False, index_names=False).split('\n')
vals = [','.join(e.split()) for e in x]
df_orders['combined'] = [','.join(e.split()) for e in x]

现在的问题是 NaN 词条也是这样收录的:
汉堡,肉丸,鸡蛋,NaN,NaN,NaN 等。

我们删除这些条目的方法是使用正则表达式。

df_orders_tmp = df_orders[['combined']].replace(to_replace=r',NaN.*$', value='', regex=True)

因此,第一行的“组合功能现在看起来像:
汉堡、肉丸、鸡蛋

我还想包括一个订单号功能,它只是复制索引号。

df_orders_tmp['orderId'] = df_orders_tmp.index

我们现在用逗号将每个订单分成单独的行。

df_orders_tmp = df_orders_tmp.assign(combined=df_orders_tmp.combined.str.split(',')).explode('combined').reset_index(drop=True)

我们现在想用空格替换上面的临时下划线。

df_orders_tmp = df_orders_tmp.replace(r'_',' ', regex=True)

如果您想知道为什么要这样做,数据集中的一些意外字符会导致“内爆过程出现问题。解决方案是将它们全部替换为下划线,执行拆分,并将空格放回原处。

我们需要订单中购买的每个项目的数量。这看起来很简单,因为每一列都是购买的一件商品,所以我将对每一行反映 1。

df_orders_tmp['itemQuantity'] = 1

用我们需要的有意义的名称的列来完成我们的新数据框架。

df = df_orders_tmp[['orderId','combined','itemQuantity']]
df.columns = ['orderId','itemDescription','itemQuantity']

让我们来看看…

df

作者图片

(英)可视化(= visualization)

df_table = df.copy()
df_table['all'] = 'all'fig = px.treemap(df_table.head(30), path=['all', "itemDescription"], values='itemQuantity', color=df_table["itemQuantity"].head(30), hover_data=['itemDescription'], color_continuous_scale='Blues')fig.show()

作者图片

df.value_counts()

作者图片

另一个非常好的可视化是一个网络图,显示订单中的前 15 个产品。

df_network = df.copy()
df_network_first = df_network.groupby("itemDescription").sum().sort_values("itemQuantity", ascending=False).reset_index()
df_network_first["itemType"] = "groceries"
df_network_first = df_network_first.truncate(before=-1, after=15) # top 15plt.rcParams['figure.figsize']=(20,20)
first_choice = nx.from_pandas_edgelist(df_network_first, source='itemType', target="itemDescription", edge_attr=True)
pos = nx.spring_layout(first_choice)
nx.draw_networkx_nodes(first_choice, pos, node_size=12500, node_color="lavender")
nx.draw_networkx_edges(first_choice, pos, width=3, alpha=0.6, edge_color='black')
nx.draw_networkx_labels(first_choice, pos, font_size=18, font_family='sans-serif')
plt.axis('off')
plt.grid()
plt.title('Top 15 Products', fontsize=25)
plt.show()

作者图片

为了继续,我们需要汇总同一订单中的多个产品。

df_grouped = df.groupby(['orderId','itemDescription']).sum()['itemQuantity']

作者图片

现在,我们需要拆分已分组的数据帧。

df_basket = df_grouped.unstack().reset_index().fillna(0).set_index('orderId')

作者图片

现在需要将矩阵中的值编码为 1 和 0。我们的方法是,如果值小于或等于 0,则将值设置为 0,如果值大于或等于 1,则将值设置为 1。

def encode_units(x):
    if x <= 0:
        return 0
    if x >= 1:
        return 1basket_sets = df_basket.applymap(encode_units)
basket_sets.head()

作者图片

Apriori 算法

我们将使用函数" apriori ",从" mlxtend "库打开," basket_sets "创建一个数据框架,"frequency _ items sets",并支持每一项。我们将把参数设置为“先验”到“最小支持= 0.05 ”和“使用列名=真”。

重要术语

  • 前件 ( if )是 Apriori 算法的第一部分。将在数据集中找到该商品或产品。我们说“如果”是因为“如果”存在,那么很可能“的结果也将存在,“然后”。
  • 后件 ( then )是 Apriori 算法的第二部分。结合“先行词”找到的商品或产品。
  • 关联规则是从由两个或更多项目组成的数据集(例如商店订单)中计算出来的。
  • 支持度表示该商品在数据集中出现的频率,例如某产品在商店中的受欢迎程度
  • 置信度表示该规则被发现为正确的频率。它表明该规则有多可靠。有人在购买牙刷时会购买牙膏的可能性有多大
  • Lift 是一种度量标准,用于测量产品在统计上独立的情况下同时出现的置信比率。例如,当购买一个产品时购买另一个产品的可能性有多大,同时控制另一个产品有多受欢迎。提升分数接* 1 表示前提和结果是独立的,前提的出现对结果的出现没有影响。提升分数大于 1 表明前因和后果相互依赖,且前因的出现对后果的出现有积极影响。提升分数小于 1 表明前因和后果是相互替代的,这意味着前因的存在对后果有负面影响,反之亦然。
  • 信念从统计独立性来衡量规则的隐含强度。信念得分是一个比率,它是一种产品在没有另一种产品的情况下出现的概率与一种产品在没有另一种产品的情况下存在的实际概率之间的比率。例如,如果(橙子)→(苹果)关联的信念得分为 1.5;如果两者之间的关联是完全独立的,则该规则错误的几率会增加 1.5 倍(增加 50%)。
frequent_itemsets = apriori(basket_sets, min_support=0.05, use_colnames=True).sort_values(by=['support'], ascending=False)
frequent_itemsets.head()

作者图片

这是在告诉我们“矿泉水”、“鸡蛋”、“意大利面”是这家店最受欢迎的商品。“ min_support ”参数需要根据数据集进行微调。0.05 在这里工作得很好,但如果你尝试其他数据集,你可能需要在某些情况下将其降低到 0.01。

使用函数," association_rules " from," mlxtend "创建 dataframe from,"frequency _ items ets"使用参数度量," lift "。

rules = association_rules(frequent_itemsets, metric="lift")
rules.head()

作者图片

重申一下,“前因是正在购买的产品,“后果是经常购买的产品,以及它们相关的可能性。

理想情况下,我们寻找提升和信心都很高的参赛作品。类似于" lift "大于等于 6,以及" confidence "大于等于 0.8。简单重述一下,“ lift ”是“实际置信度”和“预测置信度”之间的比值。大于 1.0 的升力比意味着两个产品之间的关系比如果两个集合是独立的所预期的更重要。升力比越大,关联越显著。“置信度”是规则被发现为正确的频率。换句话说,这个规则作为百分比有多可靠。

我们寻找的是“提升”和“信心”最高的规则。这在熊猫身上很容易过滤。至少我们希望"升力"大于 1,但尽可能高。对于“置信度”我将规则设置为等于或高于 25%。

rules[ (rules['lift'] > 1) & (rules['confidence'] >= 0.25) ]

作者图片

这告诉我们,在这家商店,如果有人买了“意大利面”,他们也有 34%的可能会买“矿泉水”。

最后

Apriori 算法在数据挖掘中非常有用。最常见的使用案例是零售市场、推荐系统、营销活动、用户行为分析等。

迈克尔·惠特尔

短文本主题建模:LDA 与 GSM

原文:https://towardsdatascience.com/short-text-topic-modelling-lda-vs-gsdmm-20f1db742e14?source=collection_archive---------2-----------------------

使用阿拉伯推特数据对短文本文档的两种自然语言处理主题建模方法的比较分析

通过 iStock 向作者许可的图像

在本文中,我对应用于短文本文档的两种主题建模方法进行了比较分析,例如推特:潜在狄利克雷分配 (LDA)和 Gibbs 抽样狄利克雷多项式混合(GSM)。我解释了算法中的主要差异,提供了它们如何在幕后操作的直观性,解释了每种算法的预处理要求,并评估了它们在聚类不同数量的短文本文档时的比较性能。

这篇文章是 一个更大的项目 的副产品,在这个项目中,我使用了主题建模和聚类来从 3600 万条阿拉伯语推特中识别政治错误信息内容。

在领英上跟我来获取常规数据科学内容。

差异

很可能您在登录本页之前就已经听说过 LDA 了。这是目前最流行的主题建模算法。然而,GSM 并不享有同样的地位。这是一种鲜为人知的主题建模算法,因此也没有得到广泛的实施。有点像贾斯汀比伯和他同母异父的兄弟杰克森。

图像通过giphy.com

撇开流行明星评级不谈,这两种方法的主要区别在于,LDA 假设每个文档(在我们的案例中是推特)都由多个主题组成,并计算每个主题对文档的贡献。另一方面,GSM 专门针对检测较小文档中的主题,并假设每个文档只有一个主题。这就是为什么有人认为更适合推特这样的微博内容的话题建模。

这两种方法之间的另一个区别是,LDA 要求预先设置主题的数量,而 GSM 只要求一个上限(max。主题的数量)并将从那里工作以从数据推断主题的数量。

LDA 是如何工作的

直觉

这篇文章提供了一个关于 LDA 如何在幕后工作的很好的介绍性解释(如果你愿意的话,还会探究这一切背后的数学)。简而言之,LDA 假设每个文档由主题分布组成,每个主题又由单词分布组成。既然我们已经有了我们的文档(tweets)和我们的文字,那么 LDA 算法的任务就是构建连接两者的隐藏(“潜在”)层:主题。

因为 LDA 假设每个文档有多个主题,所以模型将返回每个主题对文档的百分比贡献的概率分布,例如 **0.3 主题 _1,0.7 主题 _2 。这意味着 30%的文档包含属于主题 1 的单词,剩余的 70%包含属于主题 2 的单词。反过来,主题被定义为单词簇,这些单词簇也具有百分比贡献。所以 Topic_1 可能由 0.3 *面粉、0.2 *黄油、0.2 *奶油、0.1 *苹果、0.1 *樱桃、0.1 *黑莓组成……这意味着 Topic_1 很可能是不同种类的水果派食谱的集合。

图片由瑞切尔·亨特通过giphy.com拍摄

一旦建立了 LDA 模型,您就可以选择提取最主要的主题(即,具有最大百分比贡献的主题)或者将您的文档建模为主题的分布,这取决于您的用例。

为 LD 惊人的成功设置您的数据

下面是使用 gensim python 库建立 LDA 模型所需的预处理的分步脚本。请注意,我过滤掉了字典中的一些极端情况(经常出现或很少出现的单词,因此可能会扭曲数据),并且我使用 LDA 的多核实现来允许本地并行处理,以加快模型构建。

在我的机器上,当对 615 万条推文建模时,每个 LDA 实例需要大约 1 小时来完成。这意味着,根据数据的大小,可以相对容易地运行 LDA 模型的多个实例,以查看哪些数量的主题和其他超参数在捕获数据中的一致主题方面做得最好。

为了让您了解默认情况下和 LDA 模型的输出,下面是我的 Jupyter 笔记本的截图:

正如你所看到的,每个主题都被打印成单词和它们对主题的贡献百分比的“等式”。这让我们对每个主题的内容有了很好的第一印象。

想象你惊人的结果

使用流行库的好处之一是,肯定会有一些很酷的其他库与您创建的输出很好地融合在一起。一个例子是 pyLDAvis 库,它出色地完成了 LDA 的粗略输出(见上图),并将其融入到 magic sauce 中,以创建输出的交互式 HTML 可视化报告。

正如你在下面的 quick-n-dirty 截屏中看到的,pyLDAvis 报告在左侧的主题间距离图上绘制了主题(在我们的例子中是 5 个,参见上面脚本中的 num_topics )。在右侧,报告列出了与每个主题最相关的前 30 个单词。你会发现一旦你选择了右边的一个单词,左边的圆圈就会移动。选择一个单词将显示该单词出现在哪个主题(一个或多个)中。圆圈将根据所选单词对特定主题的贡献百分比而增大。这确实有助于我们理解潜在主题层的内容和架构。

GSDMM 的工作原理

直觉

虽然 LDA 在较大的文本(> 50 个单词左右)上表现很好,但在尝试对较短文本的主题进行建模时,它的性能往往会下降,原因很明显,一个简短的文本(如一条推文或一个论坛问题的标题)可能只涉及一个主题。

进入 GSDMM:一个替代的主题建模算法,正是从这个假设出发。

图片来自 giphy.com

为了理解 GSDMM 是如何工作的,理解一个类似的概率过程是有帮助的,这个过程通常被称为电影组过程。我将从 Matyas Amrouche *的这篇文章中复制一个简单的叙述式解释:

“想象一下,一群学生在一家餐馆里,随机坐在 K 张桌子旁。他们都被要求在纸上写下他们最喜欢的电影(但必须是一个简短的名单)。目标是以这样一种方式将他们聚集在一起,使得同一组中的学生分享相同的电影兴趣。为此,学生必须根据以下两条规则逐一选择新的桌子:

规则一:选择学生多的桌子。这个规则提高了完整性,所有对同一部电影感兴趣的学生都被分配到同一个桌子上。

规则 2:选择一张桌子,让学生分享相似电影的兴趣。这条规则旨在增加同质性,我们只希望成员们在同一张桌子上分享对同一部电影的兴趣。

重复这个过程后,我们预计一些表格会消失,另一些会变得更大,最终会有一群学生符合他们对电影的兴趣。这就是 GSDMM 算法所做的事情!"

为 gsdm 的巨大成功设置您的数据

正如我前面提到的,GSDMM 在 Python 库中的实现远不如它流行的表亲 LDA。在尝试了一些不同的实现之后,我选定了这个 Python 包(T0 ),您可以使用以下命令直接从 Github repo 安装它:

pip 安装 git+https://github . com/rwalk/GSD mm . git

下面是一个将数据预处理成所需格式的脚本:

注意,GSDMM 只需要两个输入变量:numpy 数组形式的文档和字典/词汇表的长度。我们还创建了一个 bow_corpus ,因为稍后计算主题连贯性时它会派上用场。

拟合模型将生成如下所示的输出;您的模型在第一次迭代中被初始化为您指定的最大主题数( K )。然后,它总共运行 n_iters 次迭代,并试图将文档混洗到少于 K 个簇中。

在我的机器上,只用了 17 分钟就完成了 10 万条推文的子集(来自原始的 615 万条数据集)。

现在我们有了我们的 GSDMM 模型,我们可以使用下面的代码片段检查主题,该代码片段改编自 this Kaggle notebook

这将生成一个集群总数的列表,其中包含前 20 个(在本例中)最常出现的单词,以及前 20 个单词在主题中出现的次数。

据我所知,不幸的是,没有办法像显示 LDA 输出那样显示 GSDMM 输出。相反,我所做的是使用主题中的单词及其计数,格式化为 python 字典,为每个主题生成一个单词云。请参见下面的示例代码和输出。

我的 GSDMM 主题群之一的输出示例

比较性能

现在我们知道了如何设置两种算法来输出我们的文档作为主题,是时候看看比伯兄弟中谁真的“比其他人漂亮得多”。

为了比较这两种主题建模方法的性能,我选择关注 3 个关键参数:

  • 运行时间
  • 建模主题的连贯性和一致性
  • 话题连贯性得分

关于评估主题模型的一个注记

主题建模不是一门精确的科学。语境——就我而言,还有翻译——构成了一个可能含义的复杂网络,人眼通常比计算机更容易梳理出来(至少在经过适当训练之前)。这就是为什么我主要依靠对主题模型的视觉检查来评估每个模型的质量。

我们将使用主题连贯性的客观测量作为额外的检查来验证这些目测检查。虽然主题连贯性可以给你的评估表现带来一种(诱人的)客观性错觉,但我发现用Stack Overflow thread的一些发人深省的怀疑来*衡这一点很有帮助:

  • 0.3 是不好的
  • 0.4 很低
  • 0.55 没问题
  • 0.65 可能是最好的结果了
  • 0.7 就不错了
  • 0.8 不太可能
  • 0.9 很可能是错的

运行时间

您可能已经注意到,在上面对 GSDMM 的描述中,我在一个 100K 文档的子集上运行了这个模型(大约是我的总数据集的 1.67%)。如果你一直在阅读,脑海里不停地萦绕着一个问题,关于我为什么要那样做……答案就在这里!

GSDMM 无法处理我总共 615 万条推文的数据集。至少在 48 小时的运行时间内没有。).

图片来自 giphy.com

这意味着,就运行时间而言,LDA 远远优于 GSDMM(它在大约 1 小时内处理了完整的 6M 数据集)。不仅如此,出于所有实际目的,我们可以说 GSDMM 不能处理非常大的数据集,至少不能一次处理完。

这对 LDA 来说是一次重大胜利。

注意:截至 2021 年 6 月,GSDMM 还不能被并行化,尽管 本文 似乎暗示有一个正在开发的版本可以。

主题建模质量:目视检查

然而,实际考虑和可行性只是故事的一面。因为当我们在短文本文档上查看主题建模输出的质量时,我毫不怀疑 GSDMM 比 LDA 做得更好。在我构建的所有 9 次迭代中,GSDMM 能够从我的项目的其余部分中一致地提取政治推文,而 LDA 的输出在每次迭代中变化很大,总体上更加混乱。

GSDMM 大获全胜。

1–1.

主题建模质量:连贯性得分

话题连贯得分是一个客观的衡量标准,它植根于语言学的分布假设:意思相似的词往往出现在相似的语境中。如果所有或大部分单词密切相关,则认为主题是连贯的。更多细节见这篇科学文章

我们可以使用 gensim 库中的 CoherenceModel 实例轻松计算主题一致性分数。对 LDA 来说,很简单:

GSDMM 的实现需要多做一点工作,因为我们首先必须将主题中的单词作为列表列表(变量主题)获取,然后将其输入 gensim CoherenceModel。注意,这是我们使用之前创建的 bow_corpus 变量的地方。

在我的例子中,计算主题连贯性分数证实了我的眼球观察所观察到的:就其输出主题的连贯性和一致性而言,GSDMM 远远优于 LDA。

最终裁决

那么…哪个比伯兄弟今晚会和我们一起回家?

嗯,在数据科学和机器学习的世界里,这完全取决于你的醉酒程度,我指的是你的用例。你想要一个速度快、对最终结果不那么模糊的比伯,还是一个愿意花时间(而不是以一种友好、自由的方式)一次处理一小部分数据的比伯?

总结一下,这里有一个表格,列出了每种方法的利与弊:

如果你和我一样,你当然会想要两个世界最好的东西。两个比一个好,是我的人生格言。具体来说,对于我的项目,我想要由 GSDMM 提供的细粒度、连贯的主题输出,但是我有一个最后期限,真的没有时间等 48 个小时以上。

所以我建了一个变通办法。我将 615 万条推文的完整数据集输入 LDA 模型,作为对数据的第一次粗略传递。然后,我删除了那些被分配到我绝对确定与我感兴趣的话题(政治内容)无关的话题的推文。这使得推文数量减少到 35 万条(约 17%)。然后,我将这个粗略过滤的子集输入到一个 GSDMM 模型中,得到了我正在寻找的高质量主题建模输出。

关于我如何做到这一点的完整实现代码,请点击这里查看我的项目的 Jupyter 笔记本。

所以也许根本不用选。

谢谢你能走到这一步!为了表达我的感激之情,我将留给你最后一个令人痛心的流行参考:

点击它…我谅你也不敢!

感谢您的阅读!在 LinkedIn 上关注我,了解常规的数据科学和 NLP 更新和技巧。

请考虑成为支持写作社区的媒体成员:

https://richardpelgrim.medium.com/membership

最短路径算法在 OSM 街道网中的应用

原文:https://towardsdatascience.com/shortest-path-algorithm-used-in-osm-street-network-33e0f864f34b?source=collection_archive---------9-----------------------

针对汽车、自行车和行人的最短路径分析的 GIS 自动化提示

图片由作者提供。赫尔辛基骑行 OSM 网络

今年秋天,我有机会作为 T2 的研究助理,参加了赫尔辛基大学的自动化 GIS 课程。本课程旨在使用 Python 实现地理空间分析的自动化,并提供大量使用 geopandas、shapely、mapclassify、folium、OSMnx 等库以及 GIS 中其他常用库的精彩材料。我在研讨会上与学生分享了我的一些编码技巧,看到地理学家如何用 Python 接管 GIS 自动化,我获得了灵感。

在上次与 OSMnx 相关的研讨会中,我刚刚回忆了 OSM 数据在城市地区最短路径算法应用中的用法是多么有趣。我发现令人感兴趣的是,如何将汽车、自行车和行人等网络类型归结为最短路径。您还可以使用不同的权重变量,如最短距离或最短时间。最短路径算法的使用直接返回与汽车、自行车或行人网络重叠的 LineString 对象。

那么,我所说的 GIS 自动化是什么呢?

Python 是地理空间分析中非常有用的编码语言,尤其是在使用函数时。在本文中,我想分享我在多个起点和终点之间创建最短路径的技巧,使用网络类型(汽车、自行车或行人)并按最短距离加权。准备好加载了 OSMnx 库的 python GIS 环境,让我们开始编码练习。

这里有代码库:带 OSM 的最短路径

OSM 数据许可证

GIS 自动化

众所周知。让我们开始导入所需的库。

**import** pandas **as** pd
**import** geopandas **as** gpd
**from** shapely.geometry **import** LineString, Point
**import** osmnx  **as** ox
**import** networkx **as** nx
**import** matplotlib.pyplot **as** plt

正如我所建议的那样,从简单的函数开始,然后继续努力总是好的。从你所拥有的简单开始,在你的函数中返回最新的一步,继续下去,直到你可以返回你正在寻找的东西。

在这种情况下,我只是创建两个点。我选择 Kamppi 购物中心作为起点,Kumpula 校园的 Physicum 大楼作为终点。这两个点都位于赫尔辛基。我要为自动化创建的函数必须与多个起点和终点一起工作,这就是自动化 GIS 过程的要点。

**# Kamppi shopping center as Origin**
origin = gpd.GeoDataFrame(columns = [‘name’, ‘geometry’], crs = 4326, geometry = ‘geometry’)
origin.at[0, ‘geometry’] = Point(24.933260, 60.169111)
origin.at[0, ‘name’] = ‘Kamppi’**# Physicum**
destination = gpd.GeoDataFrame(columns = [‘name’, ‘geometry’], crs = 4326, geometry = ‘geometry’)
destination.at[0, ‘geometry’] = Point(24.962608, 60.205301)
destination.at[0, ‘name’] = ‘Physicum’

请注意,在 CRS 4326 中使用起点和终点作为时,这种自动化实践是可行的。

OSM 数据提取

运行最短路径算法之前的第一部分是在提取的 OSM 数据上可视化起点和终点。默认情况下,该函数用于行驶网络类型,但您可以将其更改为自行车或步行。

def **osm_network**(origin, destination, network = ‘drive’):
 '''
**origin and destination <geodataframe>, 
network <str> drive, bike, walk
RETURN OSM network as <GeoDataFrame>**
 '''

 **# creating a boundary for fetching OSM data**
    combined = origin.append(destination)

    convex = combined.unary_union.convex_hull

    graph_extent = convex.buffer(0.02) **# fetching graph**
    graph = ox.graph_from_polygon(graph_extent, network_type= network) **# Get the edges/network as GeoDataFrame**
    edges = ox.graph_to_gdfs(graph, nodes=False)    

    **return** edges

然后,使用函数就简单了。让我们用不同的网络类型做一些测试,然后画出来。

**osm_network(origin, destination)**

图片由作者提供。OSM 驾驶网络上的起点和终点图

**osm_network(origin, destination, ‘bike’)**

图片由作者提供。OSM 自行车网络的起点和终点

使用 OSM 数据的最短路径

下一步是扩展包含最短路径算法之前创建的函数。该功能还将像以前一样包括网络类型。所以这种自动化可以用来分析汽车、自行车或行人的最短路径。

def **shortest_path**(origin, destination, network = ‘drive’):
 ‘’’
**origin and destination <GeoDataFrame> crs 4326, network <str> drive, bike, walk
RETURN shortest path <GeoDataFrame>**
 ‘’’

 **# creating a frame for fetching OSM data**
 combined = origin.append(destination)

 convex = combined.unary_union.convex_hull

 graph_extent = convex.buffer(0.02)

 **# fetching graph**
 graph = ox.graph_from_polygon(graph_extent, network_type= network)

 **# Reproject the graph**
 graph_proj = ox.project_graph(graph)

 **# Get the edges as GeoDataFrame**
 edges = ox.graph_to_gdfs(graph_proj, nodes=False)

 **# Get CRS info UTM**
 CRS = edges.crs

 **# Reproject all data**
 origin_proj = origin.to_crs(crs=CRS)
 destination_proj = destination.to_crs(crs=CRS)

 **# routes of shortest path**
 routes = gpd.GeoDataFrame()

 **# Get nodes from the graph**
 nodes = ox.graph_to_gdfs(graph_proj, edges=False)

 **# Iterate over origins and destinations**
 for oidx, orig in origin_proj.iterrows():

   **# Find closest node from the graph → point = (latitude, longitude)**
   closest_origin_node = ox.get_nearest_node(G=graph_proj, point=(orig.geometry.y, orig.geometry.x), method=’euclidean’)

 **# Iterate over targets**    for tidx, target in destination_proj.iterrows():
      **# Find closest node from the graph → point = (latitude, longitude)**
      closest_target_node = ox.get_nearest_node(graph_proj, point=(target.geometry.y, target.geometry.x), method=’euclidean’) **# Check if origin and target nodes are the same → if they are → skip**
      if closest_origin_node == closest_target_node:
          print(“Same origin and destination node. Skipping ..”)
          continue

 **# Find the shortest path between the points**       route = nx.shortest_path(graph_proj, 
 source=closest_origin_node, 
 target=closest_target_node, weight=’length’)

 **# Extract the nodes of the route**       route_nodes = nodes.loc[route]

 **# Create a LineString out of the route**       path = LineString(list(route_nodes.geometry.values))

 **# Append the result into the GeoDataFrame**       routes = routes.append([[path]], ignore_index=True) **# Add a column name** routes.columns = [‘geometry’]

 **# Set coordinate reference system** routes.crs = nodes.crs **# Set geometry** routes = routes.set_geometry(‘geometry’)

 **return** routes

该函数将返回路径最短的地理数据框。您可以使用像这样简单的函数并绘制结果。

**shortest_path**(origin, destination)

图片由作者提供。OSM 驾驶网络最短路径图

**shortest_path**(origin, destination, 'bike')

图片由作者提供。OSM 自行车网络最短路径图

**shortest_path**(origin, destination, 'walk')

图片由作者提供。OSM 步行网络的最短路径图

建议

创建的函数可用于两个目的:1)第一部分可以帮助根据您使用的起点和终点按网络类型获取 OSM 数据。如果您只处理位置,您可以操作该函数来正确获取 OSM 网络。2)第二部分直接给出起点和终点之间的最短路径(多于 2 条)。最短路径分析可用于城市分析和移动性。这种算法有助于回答这样的问题:哪条路线是上学/工作的最佳路线?骑自行车去短还是走路去短?

我希望你能从这些功能的使用中获得灵感,继续解决城市的移动性问题。

所有的 AI 研究都应该发表吗?

原文:https://towardsdatascience.com/should-all-ai-research-be-published-5226ad5145b4?source=collection_archive---------32-----------------------

播客

罗西·坎贝尔论人工智能中负责任的研究和出版规范

苹果 | 谷歌 | SPOTIFY | 其他

编者按:这一集是我们关于数据科学和机器学习新兴问题的播客系列的一部分由 Jeremie Harris 主持。除了主持播客,Jeremie 还帮助运营一家名为sharpes minds的数据科学导师初创公司。

当 OpenAI 在 2019 年初开发其 GPT-2 语言模型时,他们最初选择不发布该算法,因为担心它可能被恶意使用,以及人工智能行业需要试验新的、更负责任的发布实践,这些实践反映了现代人工智能系统日益增长的力量。

这个决定是有争议的,甚至今天在某种程度上仍然如此:人工智能研究人员历来享有开放出版的文化,并默认分享他们的结果和算法。但无论你对 GPT-2 等算法的立场是什么,很明显,在某个时候,如果人工智能变得任意灵活和强大,那么在某些情况下,限制发布对公共安全将是重要的。

人工智能中的出版规范问题很复杂,这就是为什么它是一个值得与既有研究经验又有政策专家经验的人一起探索的话题——就像今天的《走向数据科学》播客嘉宾罗西·坎贝尔一样。罗西是 AI Partnership on AI(PAI)的安全关键人工智能负责人,这是一个非营利组织,汇集了非营利组织、民间社会组织、学术机构、初创公司和谷歌、脸书、微软和亚马逊等大型科技公司,以塑造最佳实践、研究和关于人工智能对人类和社会的好处的公共对话。Rosie 与 PAI 的同事一起,最*完成了对白皮书的整理,该白皮书探讨了当前关于人工智能研究出版规范的激烈辩论,并为参与人工智能研究的研究人员、期刊和机构提出了建议。

以下是我在对话中最喜欢的一些观点:

  • 最佳实践和推荐的出版规范只有在研究人员愿意并且能够实施的情况下才有用。因此,Rosie 强调了推荐出版规范的重要性,这些规范对研究过程的干扰最小,并且要求研究人员尽可能少的开销。例如,虽然她建议研究人员在发表的作品中包括一些关于他们贡献的潜在影响和使用案例的声明,但他们在这方面投入的时间应该与每次贡献的大小成比例。对于代表渐进进展的项目(这是绝大多数 ML 研究),研究人员应该花更少的时间去思考他们工作的潜在危害和影响。
  • 建立负责任的出版规范的最大挑战之一是,不同意给定出版框架的单个组织或研究团队可以简单地拒绝实施它,从而破坏其他所有人的努力。事实上,这已经发生了:2019 年,在 OpenAI 宣布他们将推迟发布完整的 GPT-2 模型后不久,一个独立的研究团队开始复制它,理由是限制对领先人工智能系统的访问将阻止人工智能安全研究人员进行跟上人工智能能力所需的前沿研究。这就是为什么努力在研究人员中达成共识是如此重要,这是一套每个人都愿意遵守的负责任的最低出版标准。
  • 为了能够预测他们工作的影响或潜在危害,期望忙碌的人工智能研究人员成为未来学家和政策专家是不合理的。这就是为什么随着人工智能技术的发展,与社会科学家和伦理学家的合作将变得越来越重要。罗西提倡这些学科之间更多的混合,作为支持人工智能研究人员开发更强大的影响评估的一种手段。

你可以在这里的 Twitter 上关注罗西,或者在这里的 Twitter 上关注我

播客中引用的链接:

  • 你可以在艾的网站上找到合作伙伴
  • PAI 关于出版规范的白皮书在这里。

章节:

  • 0:00 介绍
  • 2:05 罗西的背景
  • 5:40 高级人工智能的风险
  • 8:15 围绕出版规范的活动
  • 12:40 偏离默认模型的参数
  • 15:10 语言建模的有害后果
  • 23:00 作为一个团体进行协调
  • 28:04 默认发布规范
  • 研究人员的责任
  • 34:30 政府在这一领域的作用
  • 40:20 激励企业人工智能研究
  • 44:30 审计公司算法
  • 46:20 PAI 和国际参与
  • 50:00 行动呼吁
  • 51:55 总结

工程师应该学 R 还是 Python?

原文:https://towardsdatascience.com/should-an-engineer-learn-r-or-python-c91b36215a91?source=collection_archive---------29-----------------------

诚实且可行的审查

作者图片

学习数据科学最困难的部分是决定你想先学习哪种语言。太多时候,寻求扩展他们的数据分析工具箱的专业人员被这个决定所麻痹,以至于他们从来没有取得任何进展。这是一场我希望避免的悲剧。到本文结束,你就知道最适合你的选择了。

你马上知道没有错误的答案,这对你的健康很重要。这两种语言都是图灵完备的(这意味着它们都能够解决任何计算问题),都被广泛使用,并且都很容易学习。事实上,在您的数据科学之旅的某个阶段,您很有可能会同时使用这两种语言(我就是这样做的),并且已经做了大量的工作来使您能够在一个分析中同时使用这两种语言。(R 的 Reticulate 包可以在 R 代码中运行 Python 代码,甚至可以将结果从一种数据类型转换成另一种数据类型!)

不过,如果你打算开始学习,你需要选择一个开始。所以,让我们言归正传。

背景

r 是专门为数据科学而构建的,围绕它的社区全心全意地接受这一事实。这个社区是由教育家组成的,他们从教人们如何编码中找到巨大的乐趣。这个社区的领导者是 RStudio,他的“tidyverse”包集合非常强大和直观,并且附带了优秀的文档。#rstats 社区的名人之一是 Hadley Wickham(来自 RStudio),他有几本书可以带你从零经验一路走到真正的高级程序员。他还有一篇重要的论文《整洁的数据》,这是任何数据科学家都应该阅读的,不管你使用的是什么软件。

Python 是软件工程师为软件工程师开发的语言。数据科学家通过构建一系列包(熊猫、numpy 等)渗透到语言中。)使 Python 能够与 R 竞争数据科学语言的声誉。由于这个性质,Python 社区有点冷,更精英化。Python 程序员倾向于从软件工程师的角度看待自己,而不是统计学家,他们可能看不起没有使用“真正的”编程语言的 R 用户。社区并不欢迎初学编程的数据科学家,但一旦你知道如何用 Python 编程,你往往会更容易在部署“生产代码”(在实际应用中使用的代码,如无人驾驶汽车或推荐服务)的公司找到工作。)

易决策者

首先,你应该考虑任何潜在的合作者,并尝试采用他们使用的相同语言。如果你的队友都用同一种语言写作,生活会更容易。“队友”不一定只是工作上的同事;它也可能是您想要贡献或在自己的代码中使用的开源包。

如果你在考虑协作之后仍然有灵活性,你应该考虑你想要结束在哪里。如果你的目标是在一家将“大数据”融入其产品的软件公司工作,你可能需要学习 Python。如果您不想编写部署在应用程序中的代码,而是想编写完成分析和得出统计推断的代码,那么您可能最终会与使用 r。

重要因素

如果你的目标是把一套新的工具带到你目前正在做的工作中,希望说服你团队的其他人跟随你的领导,那么你就有机会选择你团队的其他人将会跟随的道路。在这种情况下,有几点需要考虑:

学习曲线

虽然这两种语言都相对容易掌握,但是有几个因素使学习 R 变得更加愉快。如前所述,语言本身、社区和资源的设计都是为编程初学者量身定制的。然而,具有更传统编程背景的人会更习惯使用 Python。假设你和你的团队没有编程经验,R 赢在这里。

集成开发环境

IDE 是你编写所有代码的地方。对于数据科学家来说,这非常重要,因为一个好的 IDE 将允许您有效地探索您的数据。迄今为止,R 凭借 RStudio 统治了这个部门。方便的是,RStudio 已经扩展为 Python 的 IDE。虽然我不推荐将它作为主要的 Python 编辑器,但是它非常适合将两种语言结合到一个分析中。虽然仍然不如 RStudio 好,但新的 Python IDE JupyterLab 最终给了 Python 数据科学家一个有价值的 IDE。不过,Jupyter 笔记本也可以用 R 写。所以,我会给 R 这个类别的胜利。

包管理(琐碎的计算机工作)

当您第一次学习时,在计算机上安装正确运行分析所需的所有文件可能会非常痛苦,尤其是对于 Windows 用户。RStudio 通过为您处理一些具体的问题,很好地减轻了这种痛苦。在 Windows 上使用 python 可能会导致您浪费整个晚上来排除与您试图运行的数据分析完全无关的问题。然而,这场对话中的另一个新成员,Anaconda 包分发软件,使这种情况大大减轻了。如果你使用 Anaconda,这部分是*局。否则,我会说 R/RStudio 用户会比 Python 编码人员有更好的体验。

可视化

两种语言都有出色的可视化包,尽管 R 的 ggplot2 包被认为是最好的选择。除了单一的可视化,构建仪表板的能力是这些语言的另一个可取的方面。在这里,R 再一次凭借闪亮的套件占据了上风。然而,plotly 的 dash 已经成为 Python 用户的一个很好的选择,因为它是用 React 构建的,所以比 shiny 更容易进入前端软件工程师的代码库。如果您试图使用 React 框架构建一个生产应用程序,那么 dash / Python 显然是您的最佳选择。然而,对于大多数用户来说,R / 闪亮 / ggplot2 将是首选。

速度、语言能力、软件包生态系统

到目前为止,Python 编码语言的有效性一直是它的主要卖点,声称它可以比 r 运行得快得多。它还有更广泛的开发人员为它制作软件包,并且是一种更通用的编码语言,允许您轻松地自动化计算机任务。这些主张不再像以前那样极端。r 开发人员已经在所有这些问题上缩小了差距。然而,纯软件工程师绝不会选择 R 而不是 Python,因为它有一些奇怪的约定(同样的约定使得它对纯数据分析师来说稍微好一点)。这一节基本是*局,但 Python 应该算是赢家。

行业用途

Python 往往更常用于“生产环境”,在这种环境中,代码是作为正在运行的应用程序的一部分编写的。与此同时,R 在学术领域占据主导地位,更多地用于分析和可视化。大型科技公司拥有使用两种语言的团队是很常见的;r 用于分析本身,Python 用于实现生产模型。然而,根据我的经验,如果你选择 Python 作为你的语言,会更容易找到工作。除非你在学术界,否则 Python 会在这里胜出。

外卖

如果你想以最简单的方式从电子表格中摆脱出来,你应该学习 r。如果你想建立部署在自动驾驶汽车上的机器学习模型,你应该学习 Python。不管你如何开始,你将很容易学会另一种语言,并可能很快发现自己(就像我一样)在相同的数据分析中用两种语言写作。最后,协作是最重要的因素,无论你的合作者使用什么语言(甚至是电子表格),你都需要能够有效地工作。令人欣慰的是,为了使这种协作尽可能无缝,已经做了很多工作(即使是电子表格)。

最后的话

如果你仍然犹豫不决,那么这是我最后的建议。下载 RStudio,阅读“R for Data Science”一书,阅读 Hadley Wickham 的“整理数据”论文。这是做好事最简单的途径。用你学到的知识解决你自己的问题。然后,使用 RStudio 或 JupyterLab 作为您的 IDE,通过“Python 进行数据分析”,重新解决您在 r 中解决的相同问题。您现在将形成一种语言偏好(但要精通两种语言),并成为一名相当熟练的数据分析师。从这一点出发,你想要成长的机会会让你的前进道路变得清晰。

数据科学家应该关心新的 M1 Pro 和 M1 Max MacBook Pro 吗?

原文:https://towardsdatascience.com/should-data-scientists-care-about-the-new-m1-pro-and-m1-max-macbook-pro-cb28988725a9?source=collection_archive---------2-----------------------

苹果发布了新款 Macbook Pro。这是它对数据科学的意义。

韦斯·希克斯在 Unsplash 上的照片

你可能知道,苹果发布了新的 MacBook Pro,有 M1 Pro 和 M1 Max。它们应该比最初的 M1 更快更强大,但这对数据科学家来说意味着什么呢?

我很高兴拥有一台配有原版 M1 的 Mac 电脑,我不得不说它的能力令人印象深刻——我甚至无法想象如果有一台配有 M1 Pro 或 M1 Max 的新 MacBook Pro 会有多好。

也就是说,如果您经常使用数据科学中的工具,那么在购买最新的计算机、迁移甚至更新您的操作系统时,您应该三思而行(在更新到 macOS Catalina 并突然失去 Anaconda 之后,我得到了这个惨痛的教训)

让我们看看是否值得购买新的 MacBook。

数据科学的当前和(可能的)未来优势

M1 Pro 和 Max 芯片的一些优势是高单线程性能。M1 Max 的分数显示单线程分数在 1,700 到 1,800 之间,多线程分数在 11,000 到 12,000 之间(这比最快的英特尔笔记本电脑高出 15%)。此外,配备 M1 Pro 和 Max 的 MacBooks 电池续航时间也非常出色。

也就是说,这些并不是数据科学的独有优势。事实是,最初的 M1 MAC 没有提供任何特别有利于数据科学家的东西,新的 M1 Pro 和 M1 Max 芯片也没有太大变化(我们将在下一节检查技术规格)。

幸运的是,据 Anaconda 网站报道,未来可能会有一些即将到来的好处。

最令人兴奋的发展将是机器学习库可以开始利用苹果硅上的新 GPU 和苹果神经引擎核心。苹果提供了像 Metal 和 ML Compute 这样的 API,可以加速机器学习任务,但它们在 Python 生态系统中没有得到广泛应用。苹果有一个 TensorFlow 的 alpha 端口,它使用 ML Compute,也许未来几年其他项目也能利用苹果的硬件加速。
——斯坦利·塞伯特(Anaconda)

数据科学 M1 的利与弊

M1 Pro 和 Max 的资源使用效率很高,但它适合数据科学活动吗?

  • 高性能内核:新的 M1 Pro 和 M1 Max 支持八个高性能和两个低功耗内核。TensorFlow 和 PyTorch 等数据科学库受益于更多的 CPU 核心,因此从原来 M1 的 4 个高性能 CPU 核心升级到新 M1 Pro/Max 的 8 个,对于执行数据科学任务来说肯定是好的。
  • ARM64 包可用性:目前,在新 MAC 上运行 Python 的最佳选择是通过 Rosetta 2。然而,这个选项无助于在 M1 MAC 电脑上运行 Python。谁知道 PyData 生态系统需要多少时间才能赶上苹果芯片。(请记住与原生 ARM64 相比,使用 Rosetta2 运行 x86–64 程序时,人们会看到 20–30%的性能损失)
  • 内存:配备 M1 Pro 的 MacBook Pro 配备 16GB 内存,而配备 M1 Pro Max 的 MacBook Pro 配备 32GB 内存。自然,当处理大型数据集时,更多的内存总是有帮助的,所以如果你已经有一台支持 8-16GB 内存的原始 M1 的 Mac,它可能值得升级到 M1 Pro Max。

我作为 M1 Mac 所有者的经历

目前,我有一台 Mac mini (M1,2020),它对我来说很好。使用 Rosetta2 运行 x86–64 程序时,我不介意 20–30%的性能损失;不过,如果我能原生运行 Python 就更好了。

不过,我不得不说,在新的 Mac 机型上设置带有数据科学和非数据科学包的 Python 简直是一场噩梦。然而,当涉及到数据科学时,有两个简单的解决方案来设置 Python——使用 anaconda 或 miniforge。

如果你是那些已经购买或打算购买配备 M1 Pro 和 M1 Max 的新 MacBook 的幸运儿之一,查看本指南轻松设置 Python(或观看下面的视频)。

与 3k 以上的人一起加入我的电子邮件列表,获取我在所有教程中使用的 Python for Data Science 备忘单(免费 PDF)

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。每月 5 美元,让您可以无限制地访问数以千计的 Python 指南和数据科学文章。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。

https://frank-andrade.medium.com/membership

你应该已经在学习量子计算了吧?

原文:https://towardsdatascience.com/should-i-already-learn-quantum-computing-953813797d71?source=collection_archive---------8-----------------------

这并不像看起来那么复杂

图片由 Pexels 提供

1.介绍

当谈到量子计算时,太多的人想象着遥远的未来,比如去火星旅行。然而,许多组织和科学家现在正致力于使量子力学更接*于解决日常问题。我决定对现有的各种生态系统进行一次考察,并对其中的一个或多个进行测试,首先看看它们的复杂程度,其次看看各种生态系统及其适用性,第三看看去解决“经典”问题是否有意义。

我学到的是,你需要一些量子力学的概念来理解为什么你做某些步骤。此外,需要复杂的代数来理解你如何做这些步骤,以及一些计算机科学家的技能来知道在哪里应用它。好消息是,你不需要理解所有的量子物理或极其复杂的代数。要处理它,你必须熟悉一些最初可能看起来违反直觉的公理和过程。

2.量子计算的最新进展

C 的未来仍处于猜测阶段。第二次量子数字革命的前景让人既害怕又兴奋。许多企业已经对其运营进行了数年的数字化。但是现在我们听说量子计算将再次改变一切(我们不知道什么时候)。随着量子控制的新进展,“量子怀疑论”也在增长。推特账号“量子狗屁探测器”( @BullshitQuantum )已经开始在设定量子技术的今天和未来的极限方面做了一件很好的工作。他们验证科技新闻报道或一个虚构的宇宙,在那里“量子比特”将解决我们可以想象的每一个问题,或一个镜像宇宙出现问题。科学界声称( F. Arute 等人 Nature 574,505–510;2019 )关于量子至上这个术语的使用,煽动用'优势'这个词代替'至上'来避免既有错误的错觉又有误解。斯科特·阿伦森(Scott Aaronson)指出,如果我们能够将自己从物理(这令人费解且违反直觉)和“炒作”中分离出来,量子处理器的应用为 ML 和其他数字技术开辟了一个“真正”可能性的新世界。我们不知道它会到达哪里,但我们现在可以看到一些非常接*我们的有趣的发展。

3.行业领导者做什么?

“今天,在任何关于任何计算问题的讨论中,提出量子计算的概率接* 1。”

克里斯·雷特福德,谷歌数据工程师

谷歌、亚马逊、脸书、IBM 和微软早在十年前就开始投资这一领域。按照他们自己的话说,他们要到 2030 年才能开发出误差低、能力足够的可靠量子处理器。迄今为止已知最大的成功测试的量子处理器是谷歌的 Sycamore,它有 54 个量子位。然而,这种处理器仍然来自“非默认容忍”一代,这也称为“小规模”或“*期”,以表明它仍处于早期阶段。物理学家将当前的技术状态正式定义为 NISQ ( 噪音中等规模量子技术),以强调当前技术问题的来源:噪音。读者可能会奇怪,54 个量子位是有限的,但我们不得不认为,在量子世界中,计算能力随着量子位的数量呈指数增长。然而,连接的量子位越多,在设备运行时就越难保持它们的脆弱状态,误差也就越大。物理学家认为,在量子计算机能够无误差(无噪声)地运行高级算法之前,还有很多工作要做。

尽管量子计算机远离主流实际应用,但谷歌、亚马逊、IBM 或微软等科技巨头已经调整其服务*台,提供量子计算服务。他们专注于解决简单的问题,在这些问题上,IBM Q 量子处理器优于 CPU、GPU 和 TFU。例如, IBM 也在 50 量子位的范围内,并提供特定的 SDK Quiskit 来与其量子处理器一起运行。他们开发了一系列特定的算法来解决金融或化学问题。他们已经说服 JP 摩根(JP Morgan)和巴克莱(Barclays)等公司研究其算法在预测金融期权的风险或价值方面如何优于传统的 ML 算法。测试是成功的,金融行业对其潜在的应用充满热情。他们还帮助 Mitshubishi Chemicals 等制造商模拟其电池中的 LiO2 反应机制,以改进这项技术。CERN 使用 IBM Q 来改进其当前的分类算法,以寻求基本粒子之间的相互作用。这是其 SDK 早期采用者的简短列表。

谷歌正在集中资源进行硬件开发。约翰·马丁尼(John Martinis)是谷歌量子硬件的首席科学家,他领导的团队正试图回答一些关于理解和控制量子宇宙的基本问题,以便在通往“量子优势的竞赛中领先。它的方法与 IBM 的不同之处在于,目前它不太强调现实世界的应用。

微软推出了微软全球计划,该计划与 IBM 的方法非常接*,但与 Honeywell 或 ION-Q 等重要公司合作。 Azure Quantum *台提供了解决当今量子处理器问题所需的所有层。它的方法很好地展示了整个生态系统,提供了非常以客户为中心的解决方案(在特定问题中)。

2019 年在加州理工学院校园推出的亚马逊 AWS 量子计算中心是一项旨在改善未来量子计算系统的倡议。该中心通过提供完全托管的服务( Amazon Braket )提供了与微软类似的方法,允许用户在一个地方开始试验来自多个量子硬件提供商的计算机。这个地方仍然是一个实验*台,亚马逊已经开始建立它的完全管理的愿景。

4.量子 ML

"一旦你抛开物理学,量子计算就会变得简单得多."

斯科特·阿伦森,德克萨斯大学奥斯汀分校

量子处理器专注于三种量子力学现象[4]:

  • 离散化
  • 叠加,
  • 纠缠

离散化意味着一些物理变量只能有一组可能的可用值。例如,原子内部的电子显示了这种性质。

量子力学是研究系统的物理状态,也就是关于这些系统的所有可用信息。根据量子力学,在一个系统中,有些量级对是不能同时测量或定义的。这仅发生在一些星等对中,特别是那些不互换的星等对。假设我们在寻找一个特定粒子的位置。量子力学告诉我们,比如某个粒子 x 可以同时处于两个不同的位置,并假设粒子 x 态可以同时定义在两个位置。这被称为叠加。如果一个粒子被定义在两个位置,那么到底在哪个位置呢?我们不知道它是在两个位置还是在其中任何一个位置。在我们真正“测量”它之前,我们没有任何概念。而当我们测量时,我们会发现粒子只处于一个位置(也称为一个量子态)。量子力学假设,如果我们重复这个测量足够的次数,粒子有可能处于第一态 p ,也有可能处于第二态p’。量子力学是概率性和预测性的。

在量子力学中,我们可以有两个明显不同的状态。但是,如果这两种状态是在一定的条件下产生的,那么我们就不能独立地描述它们中的任何一个。我们可以看到粒子在空间中分离,但它的量子描述是全局的,因为它的量子态是纠缠的。唯一的条件是,这两个粒子不能与宇宙中的任何东西发生相互作用或者纠缠丢失。

应用于量子计算,我们可以按以下方式操作这一现象:

  • 离散化允许我们选择在物理量级上只有两种可用状态(0 和 1)的系统。
  • 我们可以处于状态 0 或状态 1(经典计算),但也可以处于状态 0 和状态 1 的叠加状态。这就是我们所说的量子比特,它具有将两个经典比特(2^1 比特)的信息集中起来的特性。例如,如果我有一组具有两个量子态的一千个离子,如果这些离子处于叠加态,我将得到一千个量子比特,这就是 2^1000 经典比特。
  • 如果这一千个离子是纠缠在一起的,我就可以操作所有的离子。我可以同时操纵所有这些离子。纠缠态的存在是一个物理事实,它对量子计算和一般的量子信息处理有重要的影响。事实上,如果没有这种状态的存在,量子计算机不会比经典处理器更强大。

量子计算机我们输入信息,我们有一个处理步骤,我们得到一个输出。主要的区别是这个中间过程与经典计算机有很大的不同,因为它使用了上面描述的三种特殊现象。利用这些现象,我们可以做传统处理器做不到的事情。

图一。一个量子位的表示。作者图片

量子机器学习通过操纵量子系统中的状态来运行。我们可以将量子算法表示为电路图(图 2-a)。这是一个来自电子电路的类比,我们有一个输入和一个输出。电路有不同的元件,如电阻、晶体管或二极管,每个元件执行一种操作。量子电路的工作原理相似:有一个输入和一个输出,有几个组件,每个组件执行一个操作。这种量子运算是基于上述公理的。

任何量子系统的状态总是由复向量空间中的一个向量来表示(图 1)。这被称为希尔伯特空间。同样,任何量子系统的状态都是一个归一化的向量。电路使我们能够在这个向量空间上进行变换。量子处理器的第一步总是加载“经典”数据。例如,在这个实验中,我将使用以电路为中心的方法[1][2],其中数据被编码成叠加量子位状态的振幅(图 1)。这种方法被称为振幅编码量子机器学习变分算法 (VQA) [2]是量子机器学习的另一种流行方法,它使用经典优化器来训练参数化的量子电路,目标是逼*给定问题的答案。在[3]描述的实验中,我将结合两种方法。这种组合利用了振幅编码的优势,但它是基于一种变分方法[5],并且它是专门为小规模量子器件设计的。[3]包含了完整的理论背景。还有额外的资源可以帮助你更深入地理解理论问题[6]。

5.基本的分类任务

“如果小型量子信息处理器可以创建经典计算机难以计算的统计模式,它们也可以识别经典无法识别的模式,”

有了这个想法,我想做一个实验,利用现有的量子技术来执行一个简单的分类任务。然后与经典机器学习算法进行比较。我们的数据集是一个多类案例,其中目标值是几个要素的非线性组合。我选择这里描述的以电路为中心的方法[3]有两个原因:

  • 可用的 q 处理器的现有技术水*限制了可用量子位的数量,
  • 并且该方法专用于执行具有少量 qbits 的经典机器学习任务。

这种方法通常被称为低深度量子态制备(LDQST)【7】。LDQST 通过引入概率量子态制备算法来减少电路深度(时间)。

图 2-a 显示了以电路为中心的量子分类器概念。量子处理单元使用模型 f(x,θ) = y 进行推理

图 2a .量子电路和变分量子电路。我们更新函数以获得 y 和 f 之间的最小差值,即最小化成本函数。作者图片

它由一个将输入 x 编码成量子系统振幅的状态准备电路 S_x ,一个模型电路 U_θ 和一个单量子位测量组成。该计算检索模型预测 0 或 1 的可能性,由此可以推导出二元预测。分类电路参数 θ 可以学习和训练。

图 2-b .本试验中使用的变分电路方法[3]。图片由[3]

以电路为中心的量子分类器的推理包括四个步骤(图 2-b)。
以回路为中心的量子分类器的推理涉及四个步骤。步骤 1 通过运行从输入空间到特征空间的特征映射,将输入向量编码到 n 量子位系统中。在步骤 2 中,量子电路将酉变换应用于特征向量,这类似于神经网络的一个线性层。

为了从量子系统中提取信息,我们需要进行“测量”。一个量子系统有无限多的可能状态,但是当我们进行基本测量时,我们只能提取有限的信息。结果的数量等于量子系统的维度。

在执行量子电路之后,在步骤 3 中,我们测量第一个量子位的统计数据。通过添加一个可学习的偏置项,该度量被解释为分类器的连续输出,以产生模型的连续输出(步骤 4 )。

5.1 实施

为了实现,我选择了开源的 IBM Q iskit 库。Qiskit 可以看作是一个用于量子电路执行的 Python 库。要在真实的量子计算机上运行实验,首先需要设置您的 IBM 帐户。你也可以在量子模拟器中运行它(不是真正的量子处理器)。在我们的实验中,我们使用了一个具有两个量子位的量子模拟器qsm-simulator,并且我们还使用一个真实的量子处理器检查了差异。

import **numpy** as np
import **seaborn** as sns
from **qiskit** import *
from **qiskit.tools.jupyter** import *
import **matplotlib.pyplot** as plt
import **pylatexenc**
from **scipy.optimize** import minimize
from s**klearn.preprocessing** import Normalizer, normalize, binarize, Binarizer
from **sklearn.model_selection** import train_test_split
from **sklearn.preprocessing** import StandardScaler, MinMaxScaler
from **sklearn.decomposition** import PCA, KernelPCA, LatentDirichletAllocation
import **pandas** as pd

backend = BasicAer.get_backend('qasm_simulator') ***# for using a quantum simulator***

对于使用真正的量子处理器:

***# Using a real quantum processors from IBM*** IBMQIBMQ.save_account('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
provider = IBMQ.load_account()
***# You can check in IBM site the cues in different backend processors # and choose the ones with lower cues to speed up your work.*** 
backend = provider.backends.ibmq_london

我们将在具有 N=19 个特征(包括目标特征)的数据集中执行分类任务。作为准备步骤,我们将使用 PCA 对 N=2 个分量进行降维,因为我们想要使用 2 个量子位模拟器。数据准备和降维是用 Scikitlearn 库完成的。完整的代码可以在这里找到

第一步。编码数据

只有数量为 n 个量子位的多项式量子算法可以对 2n 个振幅进行计算。

纠缠使得创建一个完整的 2n 维复向量空间成为可能,我们可以在这个空间中进行计算,只需要使用 n 个物理量子位。

如果使用这些 2n 振幅对数据进行编码,则可以在多对数时间内处理数据输入。纠缠使得我们有可能创建一个完整的 2n 维复向量空间来进行计算,只需要使用 n 个物理量子位。因此,给定一个四维酉向量,我们用函数get_angles提取五个角度。这些角度将作为在 quantum a 电路中对我们的数据进行编码的参数(在图 3 中, R 指的是 Y 中的旋转角度)。

**# Arguments to encoding quantum circuit**
def get_angles(x):
    beta0 = 2 * np.arcsin(np.sqrt(x[1]) ** 2 / np.sqrt(x[0] ** 2 + x[1] ** 2 + 1e-12))
    beta1 = 2 * np.arcsin(np.sqrt(x[3]) ** 2 / np.sqrt(x[2] ** 2 + x[3] ** 2 + 1e-12))
    beta2 = 2 * np.arcsin(
        np.sqrt(x[2] ** 2 + x[3] ** 2) / np.sqrt(x[0] ** 2 + x[1] ** 2 + x[2] ** 2 + x[3] ** 2)
    )
    return np.array([beta2, -beta1 / 2, beta1 / 2, -beta0 / 2, beta0 / 2])

获得的角度:

First features sample:[ 0.81034968, -0., 0., -1.22809981, .22809981]

包括角度在内的准备电路。

**# State preparation circuit**
def statepreparation(a, circuit, target):   **# a:angle**
    a = 2*a
    circuit.ry(a[0], target[0])         **# rotation angle on y**
    circuit.cx(target[0], target[1])    **# CNOT gate**
    circuit.ry(a[1], target[1])         **# rotation angle on y**
    circuit.cx(target[0], target[1])    **# CNOT gate**
    circuit.ry(a[2], target[1])         **# rotation angle on y**
    circuit.x(target[0])                **# x value**
    circuit.cx(target[0], target[1])    **# CNOT gate**
    circuit.ry(a[3], target[1])         **# rotation angle on y**
    circuit.cx(target[0], target[1])    **# CNOT gate**
    circuit.ry(a[4], target[1])         **# rotation angle on y**
    circuit.x(target[0])                **# x value**
    return circuit

x = X_norm[0]
ang = get_angles(x)
q = QuantumRegister(2)
c = ClassicalRegister(1)
circuit = QuantumCircuit(q, c)
circuit = statepreparation(ang, circuit, [0,1])
circuit.draw(output=*'*mpl*'*)  **#for plotting the circuit draw**

我们的状态准备电路将如下所示:

图 3。实验中状态准备电路 Sx。作者图片

其中 X-gate 由 2x2 矩阵表示。两个 X 门都在一个 0 量子位上。 R 为旋转角度(共五个),连接器为 CNOT 门(图 4)。

第二步。模型电路。

该电路有几个堆叠的块,可以称为层,以此与神经网络进行类比。一层由应用于两个量子位的通用参数化幺正门组成。下面我们可以看到最终电路包括状态准备,模型电路和测量。

图 4。状态准备、模型电路和测量与训练。作者图片

我们将操作符应用于特征状态 U(theta) ,其中( theta_i) 是可训练参数(见图 4)。以下代码执行模型电路:

def execute_circuit(params, angles=None, x=None, use_angles=True, bias=0, shots=1000):
    if not use_angles:
        angles = get_angles(x)  
    q = QuantumRegister(2)
    c = ClassicalRegister(1)
    circuit = QuantumCircuit(q,c)
    circuit = statepreparation(angles, circuit, [0,1])
    circuit = create_circuit(params, circuit, [0,1])
    circuit.measure(0,c)
    result = execute(circuit, backend, shots=shots).result()

    counts = result.get_counts(circuit)
    result=np.zeros(2)
    for key in counts:
        result[int(key,2)]=counts[key]
    result/=shots
    return result[1] + bias

execute_circuit(params, ang, bias=0.02)

第三步。训练模型

我们必须找到一个预测器 f 来估计 y 给定一个新的值x。我们将通过找到使损失最小化的参数θl (图 4) 用训练输入训练一个模型。在我们的例子中 f 将返回被标记为 l 的概率。

第四步。测量和结果

执行测量后,我们得到了以下结果(图 5)。

图 5。应用图 4 电路后的测量结果。作者图片

5.2 结果和基准

我们使用交叉熵损失或对数损失来计算我们的模型的准确性,该模型测量分类模型的性能,其输出是 0 到 1 之间的概率值。随着预测概率偏离当前标签,交叉熵损失增加。图 5 描述了最终结果。此外,我们使用各种标准的 Scikitlearn 算法执行了相同的分类任务(图 6)。

图 6。标准 Scikitlearn 算法的分类问题。作者图片

正如我们所看到的,我们的结果比用 Scikitlearn(最*邻)得到的最好结果稍好。在任何情况下,模型猜测为正确类别的概率低于 0.8。读者可能认为使用量子算法的努力太高了。我个人是这么认为的。但是我必须考虑整个过程,在这个过程中,我用标准的 ML 算法降低了数据集的维数,以便只使用 2 个 qbits。想法是使用低深度量子态制备方法。尽管结果仍然很有希望。

结论

“一旦你熟悉了量子力学的公理,叠加或纠缠在你看来就是一件自然而然的事情。”

J.I Cirac,马克斯·普朗克量子光学研究所

是的,你必须了解并熟悉量子力学的一些基本公理。否则,你可能会陷入开发量子算法所需的步骤中。然而,为了能够编写这些算法,需要一些复代数知识。与神经网络不同,这里的困难在于理解你为什么做你所做的事情。神经网络的困难在于确定它们做了什么。综上所述,进步是显著的。不仅仅是量子比特的数量;而是认识到量子算法的结果可以为模式识别提供一个新的视角。

忽略速度和计算能力等问题,量子计算今天可能会很有趣,尽管它有局限性。

参考

[1]御手洗幸助,内乡诚,北川正弘,藤井圭介(2018) ' 量子电路学习',Phys. Rev. A 98,032309。

[2]雅各布·比亚蒙特,彼得·魏特克,尼古拉·潘科蒂,帕特里克·雷本特罗斯特,内森·维贝,塞斯·劳埃德(2017),'量子机器学习',Nature 549,195–202。

[3]玛利亚·舒尔德,亚历克斯·鲍恰洛夫,克里斯塔·斯沃雷,内森·维贝,(2020) ' 以电路为中心的量子分类器',物理评论 A 101,032308。

[4]米勒-柯尔斯顿,H. J. W. (2006 年)。量子力学导论:薛定谔方程和路径积分。美国:世界科学。第 14 页。国际标准书号 978-981-2566911。

[5]马卡卢索 A .,克里萨 l .,罗提 s .,萨托利 C. (2020)量子神经网络的变分算法。载于:Krzhizhanovskaya V .等人(编辑)的《计算科学——2020 年的 ICCS》。ICCS 2020。计算机科学讲义,第 12142 卷。斯普林格,查姆。https://doi.org/10.1007/978-3-030-50433-5_45

[6]朱利亚诺·贝宁蒂、朱利奥·卡萨蒂和朱利亚诺·斯特里尼(2004 年)。量子计算与信息原理,默认丛书。

[7]肖,,容曼红,,(2021) ' 低深度量子态制备', arXiv:2102.07533

更多基础知识:

  • IBM 的 Qisqit:https://qiskit.org/textbook/what-is-quantum.html
  • 量子算法初学者实现, abhijith j . and adetokumbo Adedoyin and John Ambrosiano and Petr Anisimov and Andreas brtschi and William Casper and Gopinath Chennupati and Carleton coff rin and Hristo Djidjev and David Gunter and Satish Karra and Nathan Lemons and Shizeng Lin and Alexander Malyzhenkov and David Mascarenas and Susan Mniszewski and 巴鲁 Nadiga and Daniel 和 Diane Oyen and Scott Pakin and laksh man Prasad and Randy Roberts and Phillip Romero and Nandakishore Santhi and 温德尔伯格和 Boram Yoon 和 Richard Zamora 和朱未和 Stephan Eidenbenz 和 Patrick J. Coles 和 Marc Vuffray 和 Andrey Y. Lokhov。 2020,1804.03719,arXivcs。东部时间

之前的版本最初发布于https://www.linkedin.com

我应该为每个客户训练一个模型,还是为我的所有客户使用一个模型?

原文:https://towardsdatascience.com/should-i-train-a-model-for-each-customer-or-use-one-model-for-all-of-my-customers-f9e8734d991?source=collection_archive---------14-----------------------

几乎每一个在软件即服务公司工作的数据科学家,最后都会来到题目中的问题:我应该为每个客户训练一个模型,还是为我的所有客户使用一个模型?

pch.vector 创建的人向量—【www.freepik.com

我是 BigPanda 的高级数据科学家,这是一家向企业销售软件的 SaaS 公司。这意味着我们的任何机器学习功能都应该为许多不同的客户正常工作,他们每个人都有非常不同的数据分布,我们的模型也应该尽快为我们的新客户工作,这些客户有望保持指数增长。

这一挑战不仅仅是我们的,我从我的许多朋友那里听说过,他们从事不同领域的数据科学,如欺诈检测、电子商务、销售预测、广告推荐等。在这篇文章中,我将分享 4 种不同的策略来处理机器学习中的多租户问题,并强调这些策略的优缺点。我也将分享我在 BigPanda 的经验,关于我在生产 ML 模型中尝试的方法。

每个客户的型号

这可能是多客户场景中最常见的方法,我们有不同的客户,他们的数据分布各不相同,因此,为客户指定的模型可能会工作得最好。这就带来了更多的问题,即该模型对客户来说有多具体。我们是否对每个客户使用相同的模型,并根据他们的数据进行训练?我们需要为每个客户进行超参数调谐吗?我们要做特征选择吗?型号选择?

对这些问题中的每一个都回答“是”可能会增加模型的准确性,并增加模型的产品化和维护的复杂性。

缺点

  • 生产复杂性- 为每个客户培训和优化一个模型需要模型培训、部署和监控方面的大量自动化,以确保您的系统可以扩展到 10 个以上的客户。
  • 较小的数据- 您的一些客户可能没有大量数据,他们的模型可能也不太准确。
  • 冷启动- 当新客户想要使用你的模型时,他必须等待模型有足够的数据来生成准确的预测。在不同的用例中,这可能需要几周甚至几个月的时间,并且会显著影响客户实现产品价值的时间。

优点

  • 该模型非常适合客户- 学习不相关的数据会严重损害您的 ML 模型的准确性。通过只对客户数据进行训练,您可以确保所有训练数据都是相关的,并有助于您的模型。
  • 有时这是唯一可能的选择- 在许多场景中,由于客户之间不同的特征分布,对多个客户进行训练会损害您的模型(例如,如果您的每个客户都在不同的国家或不同的行业),因此为每个客户训练一个模型是唯一可能的方法。

有什么要注意的?

  • 模型验证- 在研究阶段,你需要确保你的模型设计对各种各样的客户都起作用,尝试在不同的客户身上验证模型,并确保模型对大多数客户都是准确的,并分析你建模的弱点是什么。
  • 自动化- 为每个客户培训一个模型时,您最终可能会有数百甚至数千个模型,为了达到这一规模,您必须在生产服务中实现大量自动化,以进行模型培训、优化、部署和监控。
  • 冷启动- 你必须分析如何为新客户添加型号。你需要多少数据?需要做哪些优化?对新客户上线的验收测试是什么?

我的外卖

在 BigPanda 的 ML 特性中,我们为每个客户提供一个模型。我们这样做是因为我们客户的数据非常不同,每个客户都有不同的属性、不同的数据规模、不同的用例以及不同的内部术语。在研究和实施该解决方案的过程中,我们通过研究何时可以为新客户训练模型,并自动完成大部分模型训练和优化,将模型扩展到新客户。

全球模型

全局模型是最简单的方法,我们将忽略数据中有不同的客户,并根据我们拥有的所有数据训练一个 ML 模型。使用这种方法无疑避免了每个客户模型的大多数缺点,但是它引入了新的问题。

缺点

  • 数据分布的差异- 根据不相关的数据训练模型通常会降低模型的准确性。很多时候,不同客户的数据差异很大,会影响模型的准确性。
  • 监控隐藏的问题- 虽然监控模型的整体准确性很有吸引力,但是模型中的问题可能只针对一部分客户,这些问题不会影响模型的 KPI,但肯定会影响客户满意度。在全球模型中找到并解决这些问题可能非常困难。

优势

  • 工程工作- 只训练和优化一个模型比许多模型容易得多,并且可以大大减少产品化和维护方面的工程工作。
  • 冷启动- 通过全球模型方法,我们可以在有新客户时立即做出预测,这确实可以提高客户满意度。
  • 更大的数据集- 通常在混合来自几个客户的数据后,你会有一个大的数据集,你可以用它来训练复杂而强大的模型。

需要注意什么?

  • 模型验证- 在研究阶段,您需要确保您的模型能够在模型训练中没有数据的新客户身上发挥作用,这可以通过分组交叉验证来实现,您可以在几个客户身上训练您的模型,并在其他客户身上进行测试。
  • 模型弱点- 模型对某些客户的准确性可能较低。识别哪些客户具有较低的准确性以及造成这种情况的原因对于算法的改进非常有益。
  • 跨客户的特性标准化- 通常,您的模型的特性在不同的客户身上会有不同的分布。这可能会导致某些客户的模型精度降低,并使其他客户过度拟合。通过标准化每个客户的数据,我们可以减少这些差异,并建立一个更好的模型。

我的外卖

在 BigPanda 的另一个 ML 特性中,我们为所有客户提供了一个全球模型。我们决定使用全球模型,因为新客户能够立即使用这一模型对我们来说非常重要。在研究该模型时,我们重点确保在培训和测试中不使用相同的组织来验证该模型,并尝试设计跨客户通用的功能,以便该模型可以推广到每个新客户。

客户细分

下一个策略是一种介于每个客户模型和全球模型之间的中间策略。这种方法首先将我们的客户分成几个部分,然后为每个部分训练一个模型。在这种方法中,我们可以享受全局模型的一些优势(可扩展性和冷启动),同时使用更多相关数据,并有望产生更准确的模型。

缺点

  • 如何细分? -细分客户的方法有很多,我们可以按语言、国家、行业甚至更多,甚至使用一些聚类或嵌入模型来做细分。在拥有许多客户(数据差异太大)和很少客户(我们将拥有许多不同的模型)的细分市场之间也存在权衡,找到最佳的细分市场是一个困难的研究问题。
  • 仍然有其他策略的缺点- 在客户细分后,您的模型将比客户少,但您可能仍然有几十个模型,这些模型也很难部署和维护,需要自动化和工程工作。

优势

  • 权衡控制- 分段的数量通常控制模型精度(在或多或少相似的数据上训练)和操作复杂度(模型数量)之间的权衡,在这种方法中你可以选择最适合你的点。
  • 两全其美?- 在某些用例中,客户细分可以让您两全其美,通过维护几个模型而不是数百个模型,为冷启动客户提供相关数据和模型的大型数据集,而不需要非常大的工程工作量。

需要注意什么?

  • 细分方法- 您对客户进行细分的方法可能是模型中最重要的部分之一,这将极大地影响模型的准确性。确保测试和迭代不同的分割方法,并找到产生最佳模型的方法。
  • 工程工作- 虽然使用客户细分比使用每用户模型简单得多,但仍然需要一些自动化、部署和培训方面的工程工作。

我的外卖

我还没有在我们的任何用例中尝试过这种方法,但我确实从业内的大学那里听说他们使用客户细分。他们大多表示,找到细分客户的最佳方式是一个难题,数据科学家必须对此投入大量精力。

迁移学习

使用迁移学习是 4 种方法中最先进的方法。在这种方法中,我们将首先使用大量数据对我们的所有数据训练一个全局模型,然后根据特定客户的数据对模型进行微调。这种方法将主要与可以在网络之间转移知识的深度学习模型一起工作。

缺点

  • 主要用于深度学习 -迁移学习主要用于深度神经网络,但对于许多应用程序(尤其是表格数据),像 XGboost 这样的基于树的模型更准确,更易于解释,也更轻量级。因此,有时你将无法使用迁移学习与你选择的模式。
  • 需要非同寻常的协调- 根据你的所有数据训练一个大型模型,然后对每个客户进行微调,这不是一个简单的过程,可能需要为每个模型的再训练建立一个复杂的管道。

优点

  • 可以非常准确- 通过使用迁移学习,我们可以在预训练阶段自动利用数据中的共性,并在微调部分丢弃不相关的信息,这可能会导致非常准确的模型。BERT、GPT3 和 SimCLR 等模型证明了迁移学习的潜力。
  • 冷启动- 在迁移学习场景中,我们不能像在全球模型中那样立即开始给出预测,但我们可以为只有数百或数千个数据点的新客户训练一个非常准确的模型。

有什么要注意的?

  • 如何迁移知识- 迁移学习有很多方法。我们可以微调网络,提取嵌入或使用知识提炼。这些方法中的每一种都可能导致更好或更差的模型,这取决于用例。
  • 新客户- 在预培训阶段无法获得的客户身上验证模型,并评估新客户培训好模型所需的数据量,这一点很重要。

我的外卖

我没有使用迁移学习来学习多个客户,但我在一些不同的用例中使用了迁移学习,它在提高模型性能方面表现出了极大的有效性。我相信这是一个很好的解决方案,在这种情况下,拥有一个带有少量标记数据的精确模型是很重要的。

结论

在这篇文章中,我回顾了 4 种不同的多客户场景建模方法,并试图强调每种方法的优缺点。标题中问题的答案是,这取决于您项目的业务和技术需求。模型应该有多精确?你愿意付出多少工程努力?新客户冷启动有多重要?不同客户的数据差异有多大?更多的问题将帮助你为你的问题选择正确的解决方案。

你如何用机器学习对抗气候变化

原文:https://towardsdatascience.com/should-machine-learning-experts-respond-to-climate-change-call-to-action-1ffeb4ba008b?source=collection_archive---------35-----------------------

帮助解决这一紧急情况,并使之有所不同!

来源: Flickr

我们星球的正常运转和生存依赖于动物、植物和微生物物种的巨大异质性的微妙*衡,这些物种有助于在地球上建立生态系统。

来源: StockSnap

在所有的生物中,有一种对地球产生了巨大的影响,以至于它能够打破地球的*衡,导致整个生态系统消失,并威胁到它的生存:人类

密集捕鱼等活动破坏了海洋、畜牧业和我们对肉类的巨大需求,大大增加了向大气中排放的二氧化碳,并促使人们更加肆无忌惮地使用杀虫剂和压力大的技术进行耕作,从而破坏了半个世界的土壤,加速了荒漠化现象。

来源: Flickr

这使我们走到了今天,我们的社会刚刚开始从我们历史上最大的灾难之一----新冠肺炎疫情----中恢复过来,而且不可避免地要准备面对更大、更重要的挑战。

这个疫情无疑教会了我们很多东西。它告诉我们,预防胜于治疗,如果我们不提前为问题做准备,它将不可避免地压倒我们。它告诉我们,我们的*衡是脆弱的,尽管社会似乎在无情地、不可阻挡地向前发展,但只要一点点就可以使一切停止,并造成巨大的社会和经济损失。最后,它告诉我们,尽管政府的反应和长期计划总是稍慢一些,但科学界并非一无所知,他们在问题发生前的工作是至关重要的。

例如,疫苗发展的速度也是科学家们在疫情之前进行的研究的结果,他们的专业知识对于解决我们历史上的这一黑暗篇章是不可或缺的。

来源: Flickr

但是,不仅仅是医学专家在改变我们的世界;相反,机器学习已经被证明是一门强大的学科,因为它能够影响社会的每个部门。

当我们听到呼吁采取行动应对气候变化时,我们许多人认为这只是针对政府的,但如果没有技术专家的支持和承诺,政府永远无法解决如此重大的问题。这就是这篇文章的来源,鼓励机器学习这一令人着迷的革命性学科的专家对这个问题感兴趣,并理解当你在你的手中有这样一个强大的工具时,即使是一个人也可以有所作为。

整篇文章的灵感来自于 David Rolnick 等人在“ 用机器学习解决气候变化 ”中的工作,该工作对应对气候变化的可能 ML 解决方案进行了非常广泛的分析。我真的建议你读一读,以加深对这个话题的理解。

然而,研究中关注的一些领域是大多数人无法接触到的,需要的资源和知识也不是每个人都能接触到的。因此,我将在下面列出一些可能的领域和问题,这些领域和问题可以由机器学习来处理,即使不是大公司或特定领域中最重要的专家,也有可能为之工作。但是,众所周知,要获得一个好的模型,我们需要好的数据,幸运的是,*年来,许多有趣的数据集已经发表,我们可以使用和组合它们来获得重要的结果。

对于本文的每个主题,我收集了一个有用的数据集列表,这可能是您的项目的一个好的起点。在某些情况下,它们可能只是你的部分起点,但千里之行始于足下,今天在有限数据集上创建的简单模型和开发过程中遇到的问题可能对明天的研究有用。

能量消耗监控

来源: Unsplash

虽然不是全球变暖的唯一原因,但当谈论这个问题时,能源生产的排放肯定是首先想到的事情之一。长期以来,我们一直依赖于化石燃料的使用,并且不明智地使用能源,但这正是机器学习可以帮助我们的地方。

机器学习已经在一些良性环境中成功应用,以优化能源消耗。然而,到目前为止,这些技术还不是特别普遍,但它们仍然可以减少能源需求,从而减少二氧化碳向空气中的排放。

使用机器学习减少电力系统 GHG 排放的机会(来源:[1])

在这个领域,机器学习也可以用于越来越准确的能源消耗预测,并使电力生产和分配越来越具有战略意义。

你可以从哪里开始?

城市和交通

资料来源: Unsplash

当开始讨论气候变化时,人们立即关注汽车排放,随着时间的推移,人们采取了许多措施来改善汽车的机械性能,使它们更加环保,减少它们的使用,今天我们正试图越来越多地推动电动汽车的发展。

我们还试图鼓励人们使用公共交通工具,以减少道路上的车辆数量。然而,这需要仔细和复杂的规划,以了解使用哪种交通工具以及如何组织它们,并预测人口的需求。

使用机器学习减少交通运输中 GHG 排放的策略(来源:[1])

同样的优化工作也可以用于建筑物的建造,以便它们可以以减少环境影响和所需旅行量的方式建造,但机器学习也可以用于提高它们的能源效率。例如,基于强化学习的方法已被用于这一目的,并取得了可喜的成果。

使用机器学习减少建筑物和城市 GHG 排放的选定策略(来源:[1])

你可以从哪里开始?

工业和废物

来源: Unsplash

可持续工业生产是建设环境友好型社会的关键,机器学习可以发挥作用的领域之一是优化生产和供应链。这些优化得越多,这些活动对环境的影响就会减少得越多。

不仅如此,工业和社会生产的资源消耗也可以变得更有效率。据估计,在发展中国家,40%的粮食生产在收获、加工或零售过程中被浪费掉了。而在工业化国家,40%的浪费发生在供应链的末端,商店、餐馆和消费者家中。

来源: Unsplash

在预测性维护方面也取得了长足的进步,预测性维护用于预测工厂何时需要维修并进行快速干预。行业本身对这一领域也很感兴趣,他们也看到了经济优势。

你能从哪里开始?

气象预报

来源: Unsplash

很有可能,我们已经在经历这种情况,无论我们如何迅速地扭转这种趋势,我们都将遭受过去几年我们所做的一些后果,当这种情况发生时,必须准备好做出反应。

我们已经看到飓风、火灾和洪水等破坏性自然现象的加剧,能够正确识别可能导致这些事件的天气条件可以拯救成千上万人的生命。

来源: Unsplash

幸运的是,地球轨道上许多卫星的存在为我们提供了大量数据,可以用来建立预测模型,这些模型可能已经对今天的社会产生了重大影响,而且肯定会在不久的将来产生影响。

在最极端的情况下,洪水和干旱可能会使一些地方变得不适宜居住,迫使人口迁移,产生前所未有的移民潮。在这里,对过去数据的创造性使用可以为未来的世界产生有用的模型。

你能从哪里开始?

育种和农业

来源: Unsplash

畜牧业现在是污染和土地开发的主要原因。当今发达国家为满足对肉类的巨大需求而存在的集约化畜牧场是非常昂贵的,需要生产大量的食物和消耗大量的水。事实上,据估计,世界上生产的 40%的谷物用于喂养农场动物。

为了满足这种需求,越来越多的土地被用于耕作,而且耕作方式越来越密集,而且往往不顾及他人。这种方法已被证明是不可持续的。犁耕和杀虫剂的使用使土壤贫瘠,对土壤的破坏越来越严重,从而加剧了荒漠化。

来源: Unsplash

因此,预测作物对土地的影响是机器学习可以发挥作用的另一个领域,此外还可以使用新的农业工具,改善作物组织和畜群管理。

困扰农业的另一个现象是微生物和疾病,它们最终会毁坏整个作物,造成经济和社会损失,并浪费大量资源。因此,患病植物的早期分类对对抗这种现象非常有帮助。

使用机器学习减少土地使用的 GHG 排放的策略(来源:[1])

此外,森林火灾管理、估计植被吸收二氧化碳的能力、改善畜群管理和精准农业都是机器学习的一些可能应用。这个领域的可能性是无限的,机器学习可以真正成为游戏规则的改变者,是更可持续的农业和耕作的关键。

可以从哪里入手?

海洋和渔业

来源: Unsplash

受人类活动影响最大的生态系统之一当然是海洋生态系统。海洋变暖了,虽然这只是几度的变化,但已经足以杀死很大一部分珊瑚礁,破坏整个海洋生态系统。好像这还不够,大量的废物最终流入海洋,包括大量的渔网,其污染已经毁灭了数量惊人的海洋物种。

来源: Unsplash

这可能是应用机器学习最复杂的领域之一,缺乏好的数据肯定没有帮助。然而,人们可以想到一些模型来帮助鱼类更加健康,而不会给生态系统带来过度压力,或者一些模型可以识别人类活动导致海洋破坏的最初迹象。

你能从哪里开始?

机器学习碳排放

来源: Unsplash

是的,像许多其他人类活动一样,机器学习,特别是深度学习,对环境有影响。据麻省大学的研究人员估计,训练一个大型深度学习模型会产生 626,000 磅导致地球变暖的二氧化碳,相当于五辆汽车一生的排放量。

幸运的是,似乎有许多解决方案,许多研究人员正在努力使这一学科更加可持续发展。例如,正在开发新的基于光子学的硬件来创建光子神经网络,这种网络在更节能的硬件上训练更快。

结论

气候紧急情况是一个现实,当我们等待世界各国政府采取行动时,任何人都可以有所作为。本文试图为在不久的将来会有用的机器学习应用程序提供一些想法和起点,但可能的创新实际上是无限的。结合、操作和分析这些以及来自在线来源的其他数据,并利用它们进行高级建模,最终可能会为即将到来的紧急情况带来一些至关重要的东西。

参考资料和见解

[1]《大卫·罗尔尼克等人》。用机器学习应对气候变化

[2]《斯里尼瓦桑·艾扬格等人》。" WattScale:数据驱动的建筑能效分析方法 "

[3]“solo plan”,机器学习和人工智能如何彻底改变你的交通规划

[4]《阿米尔雷扎·法拉哈尼等人》。在线多式联运规划采用深度强化学习

[5]《雍怡然等人》。预知维修综述:系统、目的和方法

[6]《安德烈亚斯·卡米拉里斯等人》。 农业深度学习:一项调查

[7]《naz neen N Sultana 等人》。" 供应链中多产品多节点库存管理的强化学习 "

[8]《苏维扬等人》。"利用遥感数据和机器学习预测森林火灾"

[9]《皮尤什·贾因等人》。机器学习在野火科学与管理中的应用综述

[10]《亚历山大·拉科斯特等人》。 量化碳排放的机器学习

[11]《洛伦佐·德·马里尼斯等人》。 光子神经网络综述

高等教育中应该教 R 吗?

原文:https://towardsdatascience.com/should-r-be-taught-in-higher-ed-bd34118a443b?source=collection_archive---------19-----------------------

也许吧——但不是像今天这样。

我的圈子里有人正在学习 R 课程中的统计学,作为他们硕士学位的必修部分。在听到他们和他们的同伴抱怨他们没有学到任何东西几个星期后,我打开了电视。我吓坏了。

明确一点,我充其量是个中级 R 用户。我很容易被归类为初学者,但很明显,这位教授甚至连基本概念都没有掌握。而且这远远不是我第一次听说有人有这种经历。

我完全支持在学习新技能时把自己放在外面。我们都在以某种方式学习。但是当在高等教育中教授一门必修课的时候——特别是在有如此多的免费资源的地方——我们需要提高标准。

我不怪教授。完全有可能是他们抽到了短签,根本不想教这门课。也许没有其他人更有资格。也许系主任(或者任何负责课程分配的人)没有足够的 R 知识来评估是否有教授够资格

毫无疑问,最大的问题是学术界在适应学生应该具备的技能方面行动迟缓。我很想看到使用和教授 SPSS 的教授的百分比与他们的学生在毕业后的第一份工作中使用 SPSS 的百分比的比较。我的蜘蛛感官告诉我,前者会很高,后者会很低。如果我们想要完全相反的结果,我们可以询问 R 的用法和可用性。如果我是一个打赌的女人,我敢打赌很少有教授使用 R,几乎所有的学生都可以使用 R。随着 R 被免费(并且开源可复制),何乐而不为呢?

现在,故事的重点是我们承认不是所有的教授。毫无疑问,有一些杰出的教授在使用和教授 R 语言方面取得了巨大的成功(我想到了理查德·兰德斯和安德鲁·海斯)。但我担心他们是例外,而不是常态。

当学生花大价钱学习新东西时,我们希望他们在将来使用这个工具时,会比其他任何时候得到更多的指导和支持。训练营可以非常有效,因为他们帮助引导新用户通过 r 等工具的生态系统。他们帮助新用户获得 T2 的整体理解,而不是在独立学习中经常出现的零敲碎打的方法。他们通常还有机会就可能遇到的问题获得一对一的支持。这有助于树立新用户的信心,让他们相信自己能够独立解决问题。

相比之下,许多(我知道,不是“所有”,见上面的免责声明)接受高等教育的学生的经历是,教授没有足够的基础知识来帮助他们看透沼泽。这些学生感到沮丧和气馁。如果他们在学习过程的“指导和支持”部分没有得到,你认为他们在继续自己的学习时会有多少信心?你认为有多少学生因为[失败的]正规教育经历而更加不愿使用 R?**

照片由 ahmad gunnaiviUnsplash 上拍摄

当学生问一些基本问题,而教授“向教室里的其他初学者开放”时,他们应该学些什么?当课堂包括观看教授键入的杂乱无章的代码示例时,学生应该如何理解如何从原始数据文件到完成的报告?

有些东西必须放弃。如果高等教育迫使学生通过他们的项目学习 R 课程,那么课程的质量(和教师)需要达到或超过以低得多的成本广泛提供的训练营。这意味着教授需要提高技能,或者需要聘请外部讲师。如果高等教育项目还没有做好投资的准备,那么在要求学生投资你不愿意投资的项目之前,也许是时候考虑将免费和开源课程纳入课程了。

照片由内森·杜姆劳Unsplash 上拍摄

詹娜·伊格尔森我的背景是工业组织心理学,我在人物分析中找到了自己的家。数据使我的作品变得生动。我主要使用 Power BI,但偶尔也会使用 Tableau 和其他工具。我很想听到更多关于你的旅程!通过在此评论或在TwitterLinkedin联系我。**

OpenAI 推出 GitHub Copilot:专注于代码生成的 AI。我们现在应该担心吗?

原文:https://towardsdatascience.com/should-we-be-worried-now-that-github-copilot-is-out-12f59551cd95?source=collection_archive---------2-----------------------

它是做什么的,它是如何工作的,它有什么缺陷,作为一名数据科学家,你应该担心吗…

副驾驶主页截图

10 亿美元的投资能买到什么?

本周二,OpenAI 和 GitHub 通过一款新的人工智能工具——GitHub Copilot的预览大胆地回答了这个问题。它可以编写用户兼容的代码,并且在这项任务上比它的前辈 GPT 3 号要好得多。

Copilot 自动完成代码片段,建议新的代码行,甚至可以根据提供的描述编写整个功能。根据 GitHub 博客的说法,这个工具不仅仅是一个基于用户输入的语言生成算法——它是一个虚拟的对程序员

它学习并适应用户的编码习惯,分析可用的代码库,并生成由数十亿行公共代码支持的建议。

这是微软向 OpenAI 投资10 亿美元的第一次尝试,open ai 是一家专注于 AGI(人工通用智能)的研发公司。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

它是如何工作的?

在其核心部分,GitHub Copilot 使用了一种新的语言生成算法,该算法由 OpenAI 开发,称为 Codex。OpenAI 首席执行官 Greg Brockman 将其描述为 GPT-3 的后代,但只专注于代码生成。

Codex 算法已经在从 GitHub 和精选的英语语言中提取的万亿字节的公共代码上进行了训练。这使得该工具能够以前所未有的准确性编写基于上下文的代码。

目前是 Visual Studio 代码扩展,技术预览版的位置有限。

在引擎盖下,扩展将您的代码和评论发送到 GitHub Copilot 服务,该服务使用 Codex 算法来合成和创建建议。

Copilot 主页部分截图

它几乎可以说任何编程语言,但最适合与 Python、JavaScript、TypeScript、Ruby 和 Go 一起使用。

根据用户的选择,该工具可以为一个建议生成多达 10 个备选方案。该算法通过记录每个建议是否被接受而不断改进。

有多好?

GitHub 的开发人员进行了一项实验来测量该工具的准确性。它在一组 Python 函数上进行了测试,这些函数在开源存储库中具有良好的测试收敛性。

所有的函数体都被删除了,唯一提供的上下文是函数名和文档字符串。Copilot 能够在 43%的时间内正确填写,在 10 次尝试后,准确率增加到 57%。

这确实是一个了不起的成就,因为该工具生成了您可以在项目中使用的工作代码。一旦上市,将有数百万人使用它,这将大大加快开发速度。

为了充分利用它,建议将代码分成小函数,提供有意义的函数名、参数和文档字符串。

换句话说,它真的是你的搭档程序员——它让你遵循软件工程的最佳实践,作为回报,它从你的代码中学习改进它的建议。

生成的代码质量如何?

尽管 Copilot 几乎有一半的时间是正确的,但创造者表示,应该对其输出进行监控:

GitHub Copilot 试图理解您的意图,并尽可能生成最佳代码,但它建议的代码可能并不总是有效,甚至没有意义。

建议的质量也取决于现有的代码。Copilot 只能使用当前文件作为上下文。它不能测试自己的代码,这意味着它甚至不能运行或编译。

此外,FAQ 说你使用这个工具要自担风险,因为它可能会建议你使用旧的或者废弃的版本的库和框架。

也有人担心 Copilot 的训练集包含数百万人编写的代码。

显而易见的问题是,“它会重复训练数据中的代码吗?”答案是。据观察,该工具有 0.1%的机会从训练集中泄漏代码。

副驾驶背诵蟒蛇禅

将这种可能性用百分比来表示可能不会显示更大的图景。考虑到每个建议会有多达 10 个选项,1000 分之一的可能性实际上更严重。

然而,关于这个问题的深入案例研究显示,这些情况只发生在没有足够的背景可供学习的时候。特别是,当当前文件很短或为空时,算法更容易犯这些错误。

作为一名数据科学家,你应该担心吗?

考虑到它的优点和缺点,值得问一下 GitHub Copilot 是否会影响未来的开发者工作。

当 GPT-3 发布的时候,这个问题的答案是一个试探性的,微弱的。然而,现在 Copilot 已经上市,并将成为一种商业产品,集成到全球广泛使用的 ide 中,我们应该重新考虑我们的答案。

创造者声称,该工具只会提高生产率,将开发人员从手工任务中解放出来,并帮助他们专注于更有趣的工作。这也有可能降低新手进入软件行业的门槛。

就我个人而言,我坚信人工智能,无论多么先进,都不会很快取代人类。我完全不同意有一天,人工智能会超越所有编程学科,能够独自解决任何独特、复杂的问题。

对于数据科学领域来说尤其如此。不管 GitHub Copilot 有多好,我觉得它连最简单的 Auto-ML 库都打不过。

数据科学不仅仅是写好代码,它是领域知识、理解数据和漂亮数学的集合。

然而,我不会否认,像这样一个基于人工智能的工具,一个由数十亿公司支持的技术,将在未来数百万程序员的日常工作流程中发挥至关重要的作用。

我们应该协调预测以调整供应链吗?

原文:https://towardsdatascience.com/should-we-reconcile-forecasts-to-align-supply-chain-b8b241fcbf36?source=collection_archive---------24-----------------------

供应链管理是关于决策的。我们应该使用“一个数字预测”还是“一个数字思维”来调整团队?

请求预报

不同的团队和流程使用供应链的需求预测。正如(Vandeput,2021 年)和(Clarke,2019 年)所讨论的,不同的利益相关方对预测材料和时间粒度有其他要求。物流经理可能会使用预测来决定未来几天在哪些商店装运货物。工厂经理必须计划好接下来几周的生产。战略家和营销人员将使用同样的预测来评估在接下来的六到九个月里要推出什么新产品。财务经理将根据下一季度的收入预测与投资者沟通。

供应链管理是关于决策的。我们如何确保所有这些团队在进行预测(以及由此产生的决策/计划)时保持一致?

一号预测?

为了协调所有这些利益相关者,许多从业者——如(Clarke,2019 年)和(Bowman,2013 年)中所讨论的那样——倡导一个数字预测(即供应链中所有人共享的统一预测);希望共享一个统一的预测将迫使利益相关者一致。由于当前的预测软件,跨不同的时间和材料粒度机械地调整预测是容易的。

尽管如此,它仍将伴随着挑战。

  • 效率。首先,你将面临一个单调乏味的周期性调整过程:你能想象在未来 18 个月内每月调整数千个 SKU 的每周预测吗?
  • 最优。第二,在一个材料/时间粒度级别的最佳预测(或模型)在另一个粒度级别将不是最佳的(我们将在下一节讨论这种影响)。一种尺寸不能适合所有人。
  • 对齐。最后,正如(Bowman,2013 年)所解释的,拥有“一个数字预测”并不能保证供应中的所有团队都是一致的。(Bowman,2013)讨论了雀巢美国公司在 S & OP 流程中就单一数字预测达成一致的例子。然而,每个部门仍然在执行一些内部烹饪。
    再举一个简单的例子。你可以在销售会议上同意需求预测是 100。然而,供应经理将生产 120 个单位,销售经理将假设销售目标为 90,财务经理的收入为 105。一个统一的预测,却有许多不同的计划。

不同的粒度…不同的最佳预测

使用统一预测的一个主要问题是,单一预测(或模型)不可能对所有物料和时间汇总级别都是最佳的。

计划者经常惊讶地发现,在 SKU 水*上做出的预测与在家庭水*上做出的预测是不同的。这很正常,令人沮丧。预测者很清楚,对总和的预测并不是预测的总和。

除了数学之外,让我们来讨论这一效应背后的两个业务驱动因素:

现货销售&清仓处理

一个产品系列的销售在总体水*上可以相当稳定。然而,在 SKU,你会看到许多现货销售,由于闪电促销,剩余库存清理,特定的一次性销售,或合同。SKU 不可能准确预测这些现货交易:预测模型使用历史需求来预测未来的销售。他们如何预测长期未售出的 SKU 的清仓情况?

自上而下的预测【1】可以包括一些现货销售,但不能将它们分配到特定的库存单位。例如,如果你知道你将为一个产品系列进行清货,你并不知道你的客户将会购买哪一款SKU。

此外,需求计划者应该密切注意而不是将历史库存清理纳入未来预测。否则,他们将面临触发新的库存补充的风险。

产品生命周期

(新)产品随着时间的推移来来去去。由于预测引擎使用历史需求来预测未来的销售,您不能指望预测引擎预测新 SKU 的未来推出。另一方面,预测引擎将发现产品接*其寿命终点时的任何下降趋势。这种双重效应往往会使长期自下而上的预测产生偏差。另一方面,自上而下的预测——如果家庭投资组合稳定——不会受到这种影响。

总之,即使你可以很容易地得出一个家庭级别的 18 个月预测,将其转化为 SKU 级别也不是最佳的:你不知道哪个 SKU 将构成这个家庭的总销售额(即使你可以预测主要产品)。

[1] 自上而下的预测:在家庭层进行的预测,根据历史值传播到 SKU。

示例

作为需求计划员,你负责预测水果。水果主要由苹果和香蕉组成,加上一百种其他不太知名的水果(通常不卖)。你知道你每个月销售大约 10.000 种水果(大部分是苹果和香蕉,还有一些不太知名的水果)。

如果您预测 SKU 级别的水果销售,您的统计引擎预测每月需求为 9.500 个水果(苹果和香蕉)。如果您在汇总级别预测您的水果销售,则引擎显示 10.000 单位的预期需求。如果以水果总量来衡量,这第二个综合预测可能是最准确的。然而,在 SKU 水*上,将 9.500 个苹果和香蕉的预测扩展到 10.000 个单位(如表 1 所示),可能不会带来任何改进,甚至会降低价值!

表 1 SKU 预报与比例预报。

SKU 预测(9500 单位)和家庭预测(10000 单位)之间的差异是由于通常不会销售的水果的意外销售。

结论

将苹果和香蕉的预测提高到 10.000 单位将会摧毁 SKU 水*的价值。事实上,在 SKU 的层面上,你根本无法知道下个月会有哪些“不太知名”的水果出售。

调和概率预测

在许多情况下,使用概率预测无法解决这个调和问题。这会让事情变得更糟。对不同物品的需求是而不是独立的。(一些需求驱动因素会推动所有需求上升或下降,一些客户可能会选择购买一种产品或另一种产品,等等。)以使较高聚合级别的概率分布不会是较低级别需求分布的总和(参见表 2 中的示例)。

表 2 概率预测协调示例

另一方面,点预测——因为它预测的是*均需求——在任何汇总级别都是可调节的,不会出现问题:在粒度级别的总例外需求应该与全局级别的*均预期需求相同。

这种效应为预测者所熟知:M5 国际预测竞赛要求对每个聚合级别进行不同的需求分布,但只有一个点——最细级别的预测。【1】

【1】参见(商务部,2020)。

一号思维定势!

一号预测的概念旁边,出现了一个新的想法:一号思维定势。这一构想建议所有利益相关者(计划者、财务、市场营销)以单一的心态来结盟,而不是强迫每个人都以单一的数字来结盟。正如(Bowman,2013 年)和(Wilson,2019 年)所建议的那样,这种想法是为了共享假设、数据和对未来的清晰愿景,而不是强迫每个人都遵循每个 SKU 预测(并在一个预测流程中满足所有要求和团队)。每个团队都应该了解任何可能影响需求的信息,如定价、营销活动、产品介绍、竞争对手的行动等。

实际上:

  • 应该要求每个团队使用相同的调和需求、定价和主数据(以及任何其他相关的信息源)。供应链不允许两个团队使用不同的历史数据来填充预测。
  • 应该建立一个正式的流程来共享影响需求的事件的信息(如价格变化、营销事件、产品介绍、竞争对手的行动……)。S&OP 流程可以成为团队间信息共享的渠道。
  • 最后,由不同团队完成的预测应该很容易被其他团队访问。为了防止彼此之间出现任何重大偏差,所有预测可能需要在一个特定(狭窄)的范围内波动。如前所述,小的差异是可以接受的,也是正常的,但是任何大的差异(全球范围内任何高于 5%的差异)都会导致利益相关者之间缺乏一致性。

有了这种一致的心态和共享的数据,尽管使用不同的预测流程(具有不同的汇总级别)和略有不同的数字,但每个功能都将保持一致。

由于单一的思维模式而协调团队将允许每个利益相关者在其所需的预测粒度上工作,同时实现主要需求驱动因素(新产品介绍、价格变化、特殊事件等)的协调。这将为每个团队留出更多的空间来使用最合适的预测模型定义自己的预测过程,最终提高整体预测质量。正如(Clarke,2019)所解释的,团队现在将有更多的时间来讨论规划,而不是相互影响以实现单个数字预测,因为他们避免了协调过载。

例如,供应链可以有一个基于国家 x 月粒度的 S&OP 流程。然而,为了优化从全球生产工厂到本地仓库的每周交付,可以在仓库 x 周粒度上进行另一个预测。这两种预测都将使用相同的历史需求数据集生成,但使用不同的模型和审查流程。此外,短期预测将由需求计划人员进行审核,以确保与 S&OP 预测相比,短期预测保持在合理的范围内。否则,规划者可以根据 S&OP 数字轻松调整短期预测。最后,在主要 S&OP 会议中讨论的任何重大事件(如价格变化或特殊销售)都应该用于微调短期预测。

👉我们在 LinkedIn 上连线吧!

承认

福蒂斯·彼得罗保罗斯迈克尔·吉利兰卡尔-埃里克·德沃

文献学

需求预测没有神奇的数字。供应链大脑 2013。https://www . supply chainbrain . com/blogs/1-think-tank/post/15929-需求预测中没有神奇的数字。

克拉克西蒙一位数预测。氩& Co 2019。https://www . argon andco . com/us/news-insights/articles/one-number-forecasting-sandy-springs-Atlanta-ga/。

商务部主办 2020 年 M5 奥运会。https://mofc.unic.ac.cy/m5-competition/.

Vandeput Nicolas 的四维预测框架。迈向数据科学 2021。https://towards data science . com/the-4-dimensions-forecasting-framework-f 7884 EC 1472。

你应该成为一家数字预测公司吗?需求规划 2019。https://demand-planning . com/2019/05/20/should-you-be-a-one-number-forecasting-company/。

关于作者

icolas Vandeput 是一名供应链数据科学家,擅长需求预测和库存优化。他在 2016 年创立了自己的咨询公司 SupChains ,并在 2018 年共同创立了 SKU 科学——一个快速、简单、实惠的需求预测*台。尼古拉斯对教育充满热情,他既是一个狂热的学习者,也喜欢在大学教学:自 2014 年以来,他一直在比利时布鲁塞尔为硕士学生教授预测和库存优化。自 2020 年以来,他还在法国巴黎的 CentraleSupelec 教授这两门课程。他于 2018 年出版了 供应链预测的数据科学(2021 年第 2 版)和 2020 年出版了 库存优化:模型与模拟

2021 年该不该成为数据工程师?

原文:https://towardsdatascience.com/should-you-become-a-data-engineer-in-2021-4db57b6cce35?source=collection_archive---------2-----------------------

数据工程是新的数据科学

UnsplashMagnet.me 拍照

我们都听说过这个头衔—
数据科学家,21 世纪最性感的工作。 但真的是这样吗?

对于许多刚接触数据行业的人来说,数据科学将是他们听到的第一件事,而且这个名称也不会过时。突然间,每个人要么已经是数据科学家,要么渴望成为数据科学家。

然而,这并不是业内唯一的职称。

作者图片

与数据相关的职称还有很多。
数据科学家已经在数据前沿工作了很长时间,现在是数据工程师和其他数据相关角色出现的时候了。

看看 2020 年的数据,这已经在发生了。
数据科学可能正在减速。

根据 interviewquery.com 的 2021 数据科学采访报告,该报告收集了超过 10,000 次数据科学采访经验,数据科学采访增长了 10% ,相比之下数据工程采访在 2020 年增长了 40%

作者截图

关于就业增长,数据来自 450 多家科技公司。对于数据科学家这一角色,2020 年的就业增长实际上比 2019 年下降了 15%。商业分析师和数据工程师等其他数据相关职位的增长抵消了这一下降。

因此,停止传播数据科学家仍然是最性感的工作的消息。
现在在数据领域有一些“更热门的”角色,数据工程师就是其中之一。

就业前景

保罗·斯科鲁普斯卡斯在 Unsplash 上拍摄的照片

我们来谈谈就业增长和对数据工程师的需求。
根据 DICE 的 2020 年科技岗位报告 ,数据工程师是 2019 年增长最快的岗位,同比增长 50%。数据科学家也榜上有名,同比增长 32%。

作者图片

但这还不是全部,其他薪酬研究也发现了关于数据工程师角色的类似结果——T33

作为数据从业者,我们明白数据不会说谎。
数据表明,数据工程是*年来增长最快的工作之一,甚至超过了数据科学的角色。

为什么会这样?

更高的支出

Photo by 金 运 on Unsplash

根据从 551 家大型科技买家收集数据的 IDG 云调查截至今天(2020 年),他们的全部 IT 环境中只有 38%在云上。

在 18 个月内,这些 IT 环境预计将有 59%在云上。同样的技术买家也将 32%的 IT 预算分配给云计算,相当于每家技术公司 7380 万美元(比 2018 年增长 59%)。

在大量数据科学家涌入之后,公司意识到他们需要适当的数据基础设施来对数据执行任何有意义的分析。公司已经开始花钱购买合适的云基础设施、数据架构,并雇佣新的数据工程人才。

更高的需求

作者图片

对数据工程师需求的一个有力证明是大数据的增长。
如果你一直生活在岩石下,
数据就是新的石油

每天都有新的数据产生,而且只会继续增长。随着数据量的疯狂增长,对工程师处理数据的需求将会增加。

另一个例子是咨询公司提供的大数据工程服务的增长,如埃森哲 和其他科技公司,如 Cognizant 。随着数据的增加,适当的数据工程服务也在增加。数据工程服务市场正经历着 18%的年增长率,预计到 2025 年将达到 31%的年增长率

支付

Mufid MajnunUnsplash 拍摄的照片

数据工程师工资很高。在很多情况下甚至比数据科学家的还要高。许多薪酬研究(总结如下)表明,数据工程师是薪酬最高的人才之一,他们的薪酬不会很快下降。

根据 聘请的 2019 年软件工程师状况报告 ,数据工程师的*均工资在纽约州增长了 7%,在湾区增长了 6%,而其他美国人的*均工资为 3.5%。

这是关于数据工程师的工资研究—

作者图片

从数据中可以看出,数据工程师的收入远远高于 110,000 美元,这对大多数人来说是一个可观的数字。此外,由于数据工程师的供应短缺,工资预计会增加。

申请人竞争

作者图片

根据 Ori Rafael(up solver 的首席执行官)所做的一项研究,LinkedIn 上列出的每个职位大约有 2.5 名候选人申请数据工程师职位,而其他职位的申请人要多得多。

这个数字表明数据工程师的供应短缺。因此,求职者更有可能在招聘过程中为自己争取更高的薪资范围。

不言而喻,每个人的招聘过程都是不同的,谈判范围取决于多种因素。这些因素包括但不限于—

  • 多年的经验
  • 技能
  • 以前的成就
  • 公司所在地
  • 工业

从经验上讲,我个人看到过那些非常重视自己数据的公司提供比其他公司更高的薪水。这些公司的一个很好的例子是提供某种数据产品的公司,以及对其数据有某种目标的公司。

责任

布鲁克·卡吉尔Unsplash 拍摄

那么,数据工程师是做什么的呢?
好吧,我已经在我之前的帖子中写了这些。

**

从本质上讲,数据工程师管理着公司数据在数据仓库中如何组织的核心基础。任务范围从设计表结构到构建 ETL/ELT 管道以确保可扩展的高性能基础设施满足公司的所有数据需求。

他们还处理几乎所有与数据自动化有关的事情。我之前做过的一个例子是我创建的 Gmail 数据管道

数据工程师能够回答这样的问题—

  • 当站点上发生事件时,主数据库中会发生什么?
  • 为什么数据仓库中的表是这样构造的?
  • 为什么我们每天而不是每小时提取数据?

更高级的数据工程师也致力于将数据实时接收到数据接收器的流数据管道。这对于机器学习产品来说非常有用,这些产品可以实时接收数据并执行一些操作。

技能

图片来自 Shutterstock

成为一名数据工程师需要广泛的技能。除了掌握编程语言,数据工程师需要了解数据库如何工作,以及如何正确设计管道将数据加载到数据库中。为了让你更容易理解,我将它总结为 5 个主要能力—

  • 编程语言— Python 和 SQL
  • SQL 和 NoSQL 数据库
  • ETL/ELT 技术— Apache Airflow、Hadoop
  • 流式传输—阿帕奇波束
  • 基础架构—云基础架构

这些技能完美地结合在一起,就形成了一个数据工程师。要真正了解如何构建管道,请看一看我写的关于如何使用 Apache Airflow 构建您的第一个管道的指南。

摘要

Tachina LeeUnsplash 上拍摄的照片

如果你已经做到了这一步,你一定对数据工程非常感兴趣。

有什么不喜欢的?

这是增长最快的行业中增长最快的工作之一,同时也是世界上*均工资最高的行业之一。这听起来好得令人难以置信。在本文中,我们讨论了以下立场—

- Job Outlook
- Pay
- Responsibilies
- Skills

像往常一样,我引用一句话作为结束。

你可以有没有信息的数据,但你不能有没有数据的信息——丹尼尔·凯斯·莫兰

订阅我的时事通讯,保持联系。

也可以通过 我的链接 注册一个中等会员来支持我。你将能够从我和其他不可思议的作家那里读到无限量的故事!

我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,你可以随时查看我的其他 文章 来暂时填补你对数据的渴望。

感谢 的阅读!如果你想和我联系,请随时通过 nickmydata@gmail.com 联系我或者我的 LinkedIn 个人资料 。你也可以在我的Github中查看之前写的代码。**

你应该建立在歌手的基础上吗?

原文:https://towardsdatascience.com/should-you-build-on-singer-taps-16bb1e45ef09?source=collection_archive---------31-----------------------

关于开源 Singer taps 可行性的争论越来越多

Singer 是一个开源标准,用于编写脚本,将 T2 Stitch 的人构建的数据转移到 T3。Stitch 引入了开源项目,以使创建数据集成“连接器”的过程更加标准化和简单——这对开发人员来说是一个很大的吸引力。

来源: unDraw

事实上,像 hotglue 这样的闭源项目和像 Meltano 这样的开源项目都在构建 Singer taps 来提供*台,使得开发人员创建数据集成管道的过程更加容易。

然而,关于在 Singer taps 上建立数据管道的可行性存在越来越多的争论。为什么?

YCombinator 公司 Airbyte 是开源社区中对 Singer 最直言不讳的批评者之一,它专注于构建一个 OSS 解决方案,使您的数据可以轻松地转移到数据仓库中。他们发表了一系列关于歌手问题的文章,以及他们打算做得更好的地方。

让我们来看看利弊:

赞成的意见

1.核心歌手规格不错

歌手规格是有据可查的,有几个维护良好,有据可查的水龙头。使用 JSON 在 tap 和目标之间移动数据的核心设计避免了不兼容的输出格式,交替使用不同 tap 的想法是一个巨大的优势。

2.已经有很多歌手了!

目前有 150–200 个基于 Singer 规范的连接器,构建新的连接器相对容易。这些连接器大部分来自想要特定数据源的开发人员,他们构建了 tap,并提交给 Singer 进行审查。这意味着你不必担心自己要用的每一个水龙头。

骗局

1.龙头之间缺乏标准化

每个歌手 tap 都是一个独特的项目——它们被组织为歌手组织下的开源 repos。这是为了鼓励开发者创建他们自己的 tap,并为整个社区做出贡献。这绝对有效——有很多开源的歌手 tap,其中许多已经被 Singer 接受为“官方”tap。

但是,这也造成了 Singer 最大的一个问题。因为每个项目都是独一无二的,所以 tap 支持的特性和用例之间往往缺乏连续性。许多贡献者只从 tap 构建他们需要的东西,然后留给开源社区。

这使得人们很难对歌手拍子的质量有信心,许多组织最终维护他们自己的拍子叉或定制垫片。

2.缺乏维护

在 Stitch 被 Talend 收购后,歌手项目基本上被搁置了。这可能会产生真正的问题,因为 API 有突破性的变化,而组织仍然停留在不推荐的歌手 tap 上。

除此之外,这些 tap 的依赖关系经常相互冲突,并且在版本控制中没有真正的一致性。一起运行多个 tap 通常需要将独立的 Singer tap 二进制文件放入容器化的应用程序中,或者进行虚拟环境训练以避免冲突。

结论

Singer 无疑为开发者创造了巨大的价值,并且在开始标准化构建 tap 的过程方面做了很多。现在,数据比以往任何时候都更加分散,解决跨组织数据集成的需求也更加迫切。

虽然 Singer 提供了大量的 taps,但我个人认为 Airbyte 解决 Singer 缺陷并为开发者创造更好体验的使命是一个很好的替代方案。我认为 Airbyte 绝对值得尝试,你应该警惕完全依赖 Singer。

感谢阅读!让我知道你在评论中的想法,或者你有什么问题。

创建线形图时使用什么纵横比

原文:https://towardsdatascience.com/should-you-care-about-the-aspect-ratio-when-creating-line-plots-ed423a5dceb3?source=collection_archive---------16-----------------------

了解如何创建更好的图表,并使用适当的宽高比在时间序列中找到隐藏的见解。

卢德·洛伦兹Unsplash 拍摄的照片

创建图表最容易被忽视的一个方面是使用不正确的纵横比。即使在摄影中,改变长宽比也会使照片看起来失真。在这里,很容易纠正长宽比。但是创建图表就那么容易吗?

让我们比较三个情节,并尝试回答以下问题:

  • 你能看出这两个情节之间的区别吗,还是一点区别也没有?
  • 哪个地块更陡或更*?你能猜到吗?

作者图片

如果我说三个情节都一样。生成的图用于线方程y = x,您对上述问题的回答会改变还是保持不变。

最左边的曲线斜率最大,最右边的曲线较*缓。所以,你可以猜测使用不正确的纵横比会发送错误的信息。

现在让我们看看另一种类型的线形图,时间序列,以使情况更强有力。下图是 1700 年到 1988 年间观察到的太阳黑子。当考虑下面的图表时,循环行为具有几乎相同的陡度,我们不能得出太多关于太阳黑子出现的变化率的结论。

作者图片

现在,如果我们看下面长宽比为 0.045 的同一幅图,我们可以看到陡度变化很大,在 1800 年至 1850 年之间很明显。这也揭示了一个事实,即变化率每年也有很大变化。因此,很明显,在创建线条图时,纵横比起着重要的作用。

作者图片

现在剩下的问题是如何确定长宽比。大多数绘图软件使用的纵横比要么是 1:1,要么取决于监视器的显示大小,可以在 4:3、5:4 和 16:9 之间变化。我们通过取宽高比来计算长宽比。

计算纵横比:

计算长宽比的想法起源于确保查看者获得图表的正确视觉感知。改变纵横比会改变我们对图表感知信息的感知,从而改变对测量量变化率或相邻数据点之间斜率的解释。为了使呈现的信息和感知的信息一致,他们引入了 45 度倾斜的概念。这是为了确保图表中线段的方向尽可能接* 45 度的斜率。

有很多方法可以计算*均加权纵横比。查看文章末尾的参考资料,了解更多细节。在目前的工作中,使用了 中值绝对斜率倾斜 方法来计算太阳黑子图的纵横比。***ggthemes***包提供了一个名为* ***bank_slopes()*** 的函数来计算绘图的长宽比。 它以 xy 值作为两个参数。默认方法是中间绝对坡度坡,但也可以使用*均绝对坡度坡计算纵横比。*

最佳实践:

如果您不在乎为图形选择正确的纵横比,那么您至少应该看看以下情况:

  • **在单个图表上绘制多条线图进行比较:在这种情况下,只有当您不打算比较两个不同的图时,默认纵横比才起作用。如下图所示,改变图表的纵横比并不能改变红线比黑线更陡,绿线更*的事实。

作者图片

  • 比较不同图表的不同折线图 :在这种情况下,确保每个图的长宽比保持不变。否则,视觉解释会有偏差。让我们看两个案例:

1.使用不正确或默认的长宽比:在这种情况下,我们选择长宽比,使图形最终为方形。这种方法的问题是,在比较三个图时,看起来好像它们都有相同的斜率。这是不正确的,因为根据直线方程,三条线的斜率分别为 3、1 和 0.5。所以在选择图的长宽比时要小心。

作者图片

2.计算每个图的纵横比:比较图的最佳方法是计算每个图的纵横比。这对于图具有相同 x 极限的情况非常适用。下图表明红线是最陡的,而绿线基本上是*坦的。线斜率也与图的视觉解释一致。我使用默认设置的bank_slopes()功能计算了长宽比。

作者图片

时间序列 :计算纵横比是明智的,因为当使用正确的纵横比绘制时,一些隐藏的信息会更加明显。

结论

以上示例显示了创建折线图时长宽比的重要性。使用错误的长宽比会向观众传递不正确的信息,有时会隐藏显而易见的信息,如时间序列数据所示。和往常一样,最好的可行方法是使用文献中提到的不同技术来计算长宽比,或者尝试使用不同的长宽比,看看哪个长宽比值最有助于表示您的图表。

如果你喜欢阅读我写的文章,那么你可以通过使用下面的推荐链接订阅媒体来支持我。

*https://abhinav-malasi.medium.com/membership

要了解最新情况,您可以订阅我发布文章时的电子邮件通知。

https://abhinav-malasi.medium.com/subscribe

参考资料:

  • J.赫尔和 m .阿格拉瓦拉,“45 岁以上的多尺度银行”,IEEE 可视化和计算机图形学汇刊(2006),12(5)
  • D.赫里斯托多洛“在双变量线图中选择最佳纵横比的启发式标准”,Stata Journal (2017),17(2),279–313
  • W.S. Cleveland,M. E. McGill 和 R. McGill,“双变量图的形状参数”,美国统计协会杂志(1988),83(402),289-300
  • 数据来源:布鲁塞尔比利时皇家天文台 WDC-SILSO

我撰写的其他与数据可视化相关的文章:

可以在 LinkedIn Twitter*上与我连线,跟随我的数据科学和数据可视化之旅。或者您可以在 Medium 上关注我,了解有关 R 和 ggplot2 包的数据可视化的最新文章。**

2021 年该考虑做数据科学家吗?

原文:https://towardsdatascience.com/should-you-consider-being-a-data-scientist-in-2021-f8670a44fb2e?source=collection_archive---------26-----------------------

数据科学职业的利弊是什么?

UnsplashMagnet.me 拍照

这是新的一年的开始,新的冒险,新的事件,还有也许是一份新的职业?

现在是 2021 年。你可能坐在那里,对目前的职业不满意,想改变它;你可能对你一直在做的工作不满意,对目前工作的财务方面不满意,或者只是觉得挑战不够。或者,你可能是一名学生,正试图决定你的未来,或者你可能是两者之一。

不管你为什么或如何来到这里,你在这里,你正在考虑职业改变或职业开始。你在网上寻找薪水高、有智力挑战和满足感的工作。你会遇到不同的工作,数据科学工作角色看起来很吸引人,似乎很有前途。

</7-tips-for-data-science-newbies-d95d979add54>

根据 LinkedIn 和美国消费者新闻与商业频道的调查,在过去的几年里,数据科学一直是最有前途和最受欢迎的工作之一。随着我们对数据的依赖与日俱增,我不认为数据科学的工作角色会很快出现在任何地方。

但是,

选择职业是一个非常复杂的决定;这不是一个容易做的。所以我想帮你做这个决定。本文并不打算推动数据科学职业发展或让你远离它们,而是为你提供做决定所需的事实。毕竟你最了解你自己。

让我们开始吧…

从事数据科学工作的优势

好吧,让我们从选择数据科学职业的好处开始。

№1:不需要学位

对我来说,这可能是最重要的优点之一。许多高薪工作需要一些大学或同等学历,这需要很长时间和很多钱。然而,与许多人认为的相反,数据科学不需要大学学位。

想要在数据科学领域有一个职业生涯,你需要学习一些核心概念,并尽可能多地构建项目来展示你的能力。这意味着你可以在相对较短的时间内成为一名数据科学家,与大学学费相比,你的钱更少。

№2:这是一个高薪领域

钱很重要,我会争论很多。当你付出努力时,你期望你的努力会得到同样有价值的回报。金钱是市场评估工作角色的方式之一。

与其他工作相比,数据科学和许多 IT 角色的工资相对较高。据威斯康星大学报道,2020 年,入门级数据科学职位的*均工资可高达 95000 美元/年。

№3:它有多种用途

数据科学是一个跨许多行业应用的领域,包括医学、电子商务、营销等。由于这种广泛的应用,该领域的需求在不久的将来不会减少。

此外,该领域的不断进步只会进一步扩大其应用范围。我必须说,数据科学在各个领域的应用不仅仅是数量众多;它对其他领域的连续性也是非常重要和关键的。

№4:这是性别比例很高的领域之一

作为一名技术领域的女性,数据科学的优势之一是它比其他计算和工程领域的性别差距更小。2019 年,数据科学家的男女比例为 7 比 3,这并不算大,但仍优于其他工作领域。

由于需要多样化并让更多的妇女进入这一领域,我只能希望这一比例在未来几年将变得更加*衡,特别是随着更多有能力的妇女加入这一领域。

№5:可以远程完成

当 COVID 去年给我们带来沉重打击时,我们开始重视可以远程完成的工作角色。不管你身在何处,这都同样有效。这样的工作为国际合作打开了更多的大门,并带来了有趣的结果。

像大多数计算领域一样,数据科学可能可以远程完成,这是一个巨大的优势,尤其是考虑到我们生活的环境。我们可以和我们爱的人在一起,而不需要牺牲我们的职业前景。

№6:这是一个充满挑战的领域

我希望,我们都喜欢接受智力挑战。特别是如果你进入像数据科学这样的领域,数据科学可能相当具有挑战性;它需要一个不断自我发展和不断学习的阶段,才能被认为是该领域的佼佼者。

您还需要研究其他领域的各个方面,以便能够正确地完成您的工作,这对数据科学家来说是另一个学习机会。

数据科学职业的劣势

公*地说,我们还需要考虑选择数据科学职业的一些不利因素。

</10-different-data-science-job-titles-and-what-they-mean-d385fc3c58ae>

№1:大多数工作角色都很模糊

数据科学是你可能遇到的最模糊的术语之一。数据科学家的工作职责没有固定不变的定义。他们会因公司或项目而改变,有时也会因人而变。

由于这种模糊性,在申请数据科学职位或开始进入该领域时,知道自己将进入什么领域可能会非常具有挑战性,这导致我们进入下一个问题。

№2:找工作不容易

虽然对数据科学家的需求不低,而且就业机会前景看好。大多数新的数据科学家发现获得数据科学职位很有挑战性!

为什么?这个术语的模糊性给招聘公司和求职者都带来了问题。大多数公司都不知道自己在找什么。因此,他们提供虚假的工作要求。这导致人们申请错误的职位。

№3:你需要获得跨领域的专业知识

数据科学是一个非常跨学科的领域。要成为一名数据科学家,你需要获得数学、编程、统计、科学传播、市场营销和商业方面的知识。基于特定的项目,你可能需要更多的知识。

虽然这提供了一个智力挑战,但有时,需要在短时间内获得所有这些知识并不总是容易做到的,可能会变得相当有压力。

№4:不可能掌握

掌握像数据科学这样一个非常活跃的领域的诀窍是,你需要不断了解最新的算法、研究和发现。那会很快变得势不可挡。

数据科学是一个正在发展的领域,这意味着它永远不会结束。只要我们有数据,我们就会找到更好的方法来阅读、收集和分析数据。所以,掌握这个领域是相当不可能的。

№5:数据隐私的伦理问题

数据科学就是关于数据的。这是一个用数字和信息讲述的故事。就像任何其他涉及收集和处理数据的领域一样,你必须处理数据隐私的道德问题。

所有数据科学项目都是数据驱动的。数据科学家接受培训,根据提供给他们的数据做出决策;在此过程中,有时他们会查看用户不允许查看的数据。这将导致隐私问题,通常很难解决。

做决定

因此,我向您展示了选择数据科学作为职业的一些利弊。你现在应该做什么决定?

每个职业选择都有好有坏;这就是生活。应该由我们来评估自己容忍坏事变好事的能力。对我来说,成为数据科学家的优势超过了劣势,这就是我如何做出决定的。这就是你应该如何对待你的生活。

外卖食品

数据科学是目前最有魅力的工作前景之一。不只是现在,现在已经有一段时间了,在可预见的未来还会继续。因此,对于许多考虑转行的人来说,数据科学似乎是一个有前途且有趣的选择。

随着新年的到来,你会考虑从事数据科学吗?做出决定的最佳方式是同时考虑选择数据科学的好的方面和坏的方面,然后,根据你的价值观、目标和个性,你可以做出决定。

在本文中,我向您介绍了数据科学职业的一些优势和劣势。希望我给了你足够的材料让你的决策过程更容易。

祝你好运。

作为一名数据科学家,你应该加入大公司还是小公司?

原文:https://towardsdatascience.com/should-you-join-a-big-corporation-or-a-small-startup-as-a-data-scientist-1b7f4d83f5c6?source=collection_archive---------11-----------------------

凯勒·琼斯在 Unsplash 上拍摄的照片

你怎么知道哪一个适合你,又能从每一个中得到什么呢

年底了!这意味着现在是假期,是奖金和晋升的季节;这也是很多人想换工作的时候。不管你是在找你有史以来的第一份工作,还是职业生涯中的第十次转换,你都会一直想知道你想为什么样的公司工作。谈到这一点,我个人经历了不同偏好的阶段。以前的我只想为世界上大多数人都知道的公司工作;然而,在为几家大公司工作后,我现在痴迷于创业世界。谁知道几年后我是否会再次改变主意,但在为大公司和小公司工作后,我知道的是它们之间的差异,所以下次我想做出改变时,我会更好地了解和精通我的决策标准。

如果你正在寻找下一份工作,并且很难决定你想为哪种类型的公司工作,我希望分享一些我在这两个领域工作的经验,帮助你更容易做出决定。

这不是钱的问题(或者是?)

来自 GIPHY 的 GIF

我们加入公司都是为了使命,为了改变世界的终极目标,对吗?但我们不要粉饰太*,薪酬是一个很大的决定因素。对于大多数人来说,大公司比小公司有更多的招聘预算并不奇怪。我说“大体上”是因为这绝对不是 100%的情况。

有很好的网站可以比较不同公司的薪酬待遇,比如水*实际上等等。但不要只关注整体薪酬,注意现金-奖金-股权的细分也很重要。通常,你可以期待初创公司以股权形式提供更低的基本工资和更大的总薪酬份额;因此,接受初创公司的报价意味着更高的风险(因为初创公司可能会失败,你的股权变得一文不值),但潜在的高回报(如果公司以高估值退出)。除了初创公司股权的波动性之外,请记住,你可能需要几年时间才能真正卖掉它,而你通常可以在获得股权后不久就卖掉你在一家大型上市公司的股权。

如果你考虑加入一家初创公司,而不是大公司,你应该相信初创公司的使命和产品;你的工作保障和薪酬与它的成功直接相关。

你会长期呆在这里(或者你会吗?)

让我们面对现实吧,没有人能确定他们会在同一个公司直到退休(相反,大多数人能确定相反)。因此,当你决定加入一家公司时,考虑长期和潜在的退出策略是很重要的。

一般来说,更大、更有名的公司在招聘者眼中是一种认可。这意味着,一旦你加入了一家品牌公司,你将从 LinkedIn 和其他*台上的招聘人员那里获得更多机会。

但是这种认可的重要性实际上取决于你目前的简历和你已经工作过的地方。积累品牌名称具有递减的边际效益——如果你的简历上已经有一两个可识别的品牌,你的下一步行动几乎无关紧要。

但如果你是一名应届毕业生,或者过去只在小公司工作过,简历上的大名肯定会帮助你吸引招聘人员对你下一步行动的更多关注。如果你正在进行职业转型,无论是从一个行业到另一个行业,还是从一个不同的领域进入数据科学,拥有一个知名雇主也会有所帮助。比方说,你正在从科技行业的金融转向数据科学;在高盛(Goldman Sachs)做一名定量分析师,会比在科技招聘人员不熟悉的小型精品银行做一名定量分析师得到更多回应。

公司文化

公司文化对我来说是一个重要的考虑因素,因为糟糕的文化不仅会打击士气,还会影响生产力。

就文化而言,对我来说,最大的障碍之一是办公室政治。我充分意识到,只要有人,就有政治,这是不可避免的。但是,由于政治通过创造许多类型的我最不喜欢的人——帝国建设者、权力收集者和盗窃者——来减缓公司的发展,我想尽可能地避免它。

在已经经历了成长的痛苦并达到稳定状态的大公司中,通常会有更多的政治因素,这仅仅是因为人们有时间。在规模较小的创业公司,人们忙于奔波,没有时间浪费在政治上。

小公司的等级制度也较少,因为..良好的..你根本没有足够的人手来做这件事。你如何用 11 个人建立一个 10 层的组织结构?

等级制度的另一面是结构。在已经发展了很长时间的大公司里,你通常可以找到更好定义的范围、更清晰的团队任务和泳道。如果你不喜欢模棱两可,创业可能不适合你;虽然有些人(包括我在内)发现拥有完成事情的自主权是一种解放,但缺乏明确的指导和既定的流程可能会让其他人感到害怕。

尽管公司规模和我所发现的“不良文化”的数量之间有很强的相关性,但肯定有异常值。因此,在做出选择之前,尽可能多地了解一家公司的文化是很重要的;记住,面试是双向的,你应该利用面试来了解团队。

增长和影响

根据以往的经验,我发现小公司有更多的发展机会。这种巨大的增长空间可以归因于几个因素。

  • 小公司缺乏组织结构和等级制度,这意味着无论你的任期有多长,你都有更大的发挥主动性的空间。也更容易承担更多责任,获得更多曝光。
  • 正在经历成长烦恼的公司通常资源紧张,每个人都需要身兼数职,承担不属于他们直接职责范围的任务。你通常需要成为数据工程师、数据科学家和数据分析师的组合,甚至可能是数据产品经理,而不是数据科学家。
  • 与成熟的公司相比,小公司通常没有现成的框架和剧本。因此,你将有机会用新颖的方法解决你遇到的问题。

也就是说,更成熟的公司通常已经开发了许多最佳实践,你可以作为一个早期的终身雇员来学习;更不用说在大公司里你有更多的人可以学习。

最后,因为在小公司有更多的机会承担大项目和责任,而且通常参与的人更少,所以更容易想象自己的影响并感受到影响,而在大公司,更容易感觉自己像公司巨轮上的一个小齿轮。

工作与生活的*衡

一个众所周知的现象是,大多数创业公司都有一种 hustle 文化。初创公司正在为市场份额甚至生存而战,人们通常非常注重结果,如果这是完成工作的必要条件,他们不会回避周末工作和加班。这也部分是由于泳道不太清晰,团队之间的界限模糊,所以如果你想承担更多的责任,就更容易。

相反,更成熟的公司有更长的时间来弄清楚角色的清晰性和范围,他们的业务处于更稳定的状态;因此,按照正常的工作时间来安排工作更容易。更大的公司通常也有更多的员工来分担工作量;因此,与小公司相比,大公司的工作生活*衡通常更好。

关键要点

在决定为哪种公司工作时,有许多不同的因素要考虑。知道一般的比较肯定是有帮助的,但你应该总是尽可能多地了解你正在考虑的特定公司,以便做出更好的判断,因为总趋势中有异常值。

你也可能在职业生涯的不同阶段想要不同的东西,所以人们在不同类型的公司之间转换并不罕见;不要害怕做出错误的选择,你总是可以尝试一些事情,并在不成功的时候做出改变。

想了解更多关于数据科学的信息吗?你可能会对这些文章感兴趣:

https://medium.com/geekculture/avoid-these-five-behaviors-that-make-you-look-like-a-data-novice-40f01158ae00 </5-mistakes-i-wish-i-had-avoided-in-my-data-science-career-6c22a44304a1>

2021 年数据科学该不该学 JavaScript?

原文:https://towardsdatascience.com/should-you-learn-javascript-for-data-science-in-2021-458ced8fb5d4?source=collection_archive---------15-----------------------

Javascript 是不是会永远改变 DS/ML 的语言?

(src =https://pixabay.com/images/id-4523100/

介绍

早在 2018 年,Tensorflow 就在其支持的语言列表中引入了 JavaScript 接口。我认为这对于许多数据科学社区来说是一个相当大的惊喜,但是这个决定肯定是有意义的。JavaScript 是一种非常流行的编程语言,使用它进行开发的人肯定希望利用 Tensorflow 库所提供的优势。当然,机器学习根本不是 JavaScript 的应用,所以有一个问题是为什么会出现这种实现。

JavaScript 在机器学习生态系统中的位置是什么?在接下来的几年里,我们有可能发现自己在 Python 上编写 JavaScript 吗?这些只是我想在这篇文章中触及并试图展开对话的一些问题。在数据科学中,了解该领域的最新技术总是很重要的,即使看起来不像,JavaScript 也不例外。所以我想讨论使用 JavaScript 进行机器学习的一些缺点,并讨论它对整个数据科学的潜在影响。

JavaScript 的潜力

JavaScript 在 web 开发方面的能力是众所周知的,但是这些能力如何应用到数据科学中呢?首先,我们应该考虑到 JavaScript 不是一种统计编程语言。这种语言很大程度上是为 web 开发而创建的,而这正是这种语言所擅长的。这意味着从典型统计学家的角度来看,JavaScript 可能有点难以理解。然而,Python 过去也是这种情况。Python 本身从未打算在机器学习领域引领世界,但由于它总体上是一门伟大的语言,所以占据了这个位置。JavaScript 有可能占据这个位置吗?

JavaScript 当然有潜力,但在我们认为它是机器学习领域的亚军之前,有一些关键的事情需要考虑。第一件事是 JavaScript 有一个很好的网络开发生态系统。虽然 Python 有很多处理数据、线性代数和机器学习的优秀包,但 JavaScript 却不是这样。在这方面,JavaScript 需要很长时间才能赶上。

另一个要考虑的是 JavaScript 很慢。像 Python 一样,JavaScript 是一种解释型编程语言,但也有一些缺点。然而,当谈到可以使用 C 编写大部分后端代码的语言时,我们发现它们的速度往往不如在其他语言中那样重要。记住,虽然从 Python 到 JavaScript 可能会降低速度,但在 Tensorflow 的例子中,最终可能会运行完全相同的代码。

缩小差距

Tensorflow.js 真正酷的地方在于,它显示了某种弥合我们和 web 开发团队之间差距的主动性。大多数利用机器学习的全栈应用程序通常向外部 API 发出请求,该 API 从用其他语言(如 Python)编写的模型中返回预测。这意味着 web 开发团队通常依赖端点来查询,以便为他们的全栈应用程序获取输入数据。

如果能看到一个内部利用 Tensorflow 的全栈 web 应用程序,那就太棒了。当然,即使在全栈的世界中,前端和后端之间通常也是分离的,但是如果能看到这一切都在 JavaScript 中完成,那就太酷了。我认为这肯定是一个很酷的概念,将所有东西整合到一种编程语言中。这当然有利于数据的传输,因为在某些情况下,用 JSON 数据正确地传递数据类型是非常困难的。当我们考虑 JavaScript 的类型和其他语言的类型时,这一点更是如此。

科学程序员和 JavaScript

JavaScript 是否会在机器学习领域扮演重要角色的问题是采用。科学程序员对 JavaScript 感兴趣吗?有几个原因让我不太喜欢实际使用 JavaScript,尽管我很喜欢这种语言本身和它所取得的成就。当然,这些都是主观的,根据程序员的不同,这些特性中的一些可能是使用这种语言的好处,而不是坏处。

我对 JavaScript 最大的问题是它的类型。JavaScript 具有非常弱的类型,这是由设计隐含的。我认为,在某些方面,这可以使语言变得非常容易使用,但也使类型有时可以做编译器想做的任何事情。我并不认为这是科学计算的最佳选择,尽管我可以肯定地看到在某些情况下这个特性肯定是有用的。然而,我的主观偏好是显式类型——我更喜欢告诉我的编译器做什么。此外,如果您想了解更多关于显式和隐式类型的知识,我不久前写了一篇文章,您可以在这里阅读,这篇文章更详细地介绍了这些概念:

我认为 JavaScipt 有一些非常酷的处理数据的方法。我当然指的是 JavaScript 的数据数组,它可以被视为包含命名数据的对象,就像字典一样。我认为这些应用于科学计算会很棒。在很多方面,它们就像是数据类的基础实现版本,更接*语言本身。我最*也写了一篇关于 Python 的数据类的文章,我认为值得一读,你可以在这里查看:

[## Python 的数据类被低估了

towardsdatascience.com](/pythons-data-classes-are-underrated-cc6047671a30)

结论

总的来说,我认为 Tensorflow 的 JavaScript 实现是 Tensorflow 家族中一个受欢迎的新成员。事实上,我非常期待 JavaScript 在机器学习领域的发展。我认为数据科学家了解 JavaScript 是相当普遍的,这种语言本身很像 Python。也就是说,我很好奇有多少数据科学家会将这种语言用于数据科学。当然也有一些缺点。最主要的担忧当然是缺乏生态系统工具来处理数据,以及语言的速度。我认为这两个问题都有解决方案,但可能需要几年时间才能有结果。

现在让我们来回答这个问题。数据科学该不该学 JavaScript?如果你碰巧知道 Python,我会说试试吧。一般来说,这两种语言非常相似,学会一种语言会使另一种语言更容易掌握。也就是说,如果你想做的只是数据科学,当然有一些理由先学习 Python。Python 速度更快,有更多的行业标准工具,这些工具历史悠久,使用良好,记录完善,可以让你找到工作,更重要的是,可以让你用半信半疑的方法实践事情。如果你熟悉 Python,并考虑将 JavaScript 作为你机器学习的下一门语言,我也建议你先尝试一些其他语言。

当然,还有许多其他优秀编程语言的例子可以用于统计分析和机器学习。一个这样的例子是 R,我认为它在分析甚至可视化方面有优势。此外,shiny 只是一个很棒的包,可以构建一些非常酷的仪表板,RStudio 只是一个很好的工作环境。另一种你可以考虑的语言是 Julia。虽然 Julia 仍然是我在本文中尚未提到的最小的语言,但它在过去几年中发展迅速。当然,我仍然会首先推荐 Python,因为它是最用户友好的,通过像 StackOverflow 这样的网站提供最多的在线支持。请查看这个比较不同语言提问的可视化图片:

https://insights.stackoverflow.com/survey/2020#most-popular-technologies

我认为任何可用的工具都值得学习,如果你有时间的话。当然,在数据科学的世界里,可能有更重要的东西需要学习,因为每时每刻都有太多的东西需要学习。但我认为 JavaScript 是一种可以应用于如此多不同应用程序的技能,它肯定会派上用场。如果你是那种最终与 web 开发人员一起工作的数据科学家,当他们问问题时,知道他们在谈论什么也是很方便的,所以出于许多不同的原因,它肯定是一种很有价值的语言。感谢您的阅读,我希望这篇文章提供了一些重要的信息和一些关于 JavaScript 的好建议。我真的对 JavaScript 在机器学习领域的未来感到兴奋,因为我认为它有潜力,而且肯定会是一种很酷的语言!

2021 年数据科学该不该学 Scala?

原文:https://towardsdatascience.com/should-you-learn-scala-for-data-science-in-2021-cf7810be7bfc?source=collection_archive---------10-----------------------

Scala 编程语言在发布 17 年后真的值得学习吗?

(img src =https://pixabay.com/images/id-5076887/)

介绍

在今天奢华、功能齐全的生态系统和编程语言出现之前,数据科学之类的东西曾经非常不同。Scala 是一种在过去被大量使用并且今天仍在使用的语言。说到数据科学,Scala 有着与 R 编程语言有些相似的故事,只是它要年轻得多。考虑到这一点,如果我们想真正理解 Scala 在行业中的位置,我们可能需要从头开始。

斯卡拉的过去

Scala 是一种编程语言,最初发布于 2004 年;17 年前。这种语言的诞生是为了减轻对 Java 编程语言的一些批评。如果你熟悉 Java,你可能会意识到 2004 年是这种语言绝对的爆发期。我们仍然能感受到当时 Java 繁荣的影响。我认为这是有充分理由的,Java 是一个超级酷的*台,相当新,但仍然相当古老。

虽然 Java 确实是一种令人敬畏的语言,但这种语言确实存在一些问题。就我个人而言,这种语言最大的问题在于 JVM 本身和浮点设计。也就是说,并不是每个人都像我一样为了好玩而处理荒谬的复数。不要像我一样。我跑题了,一个大问题是范式相当严格地面向对象,并没有真正地有许多多范式方面。*行主义和奇怪的宣言式语言也增加了这种语言的一些设计选择的混乱。此外,如果您想了解

Scala 开始创建一种新的基于 JVM 的语言,它可以避免几乎所有这些问题。这种语言允许程序员在面向对象和函数式编程中工作。Scala 中的 Scala 实际上应该是可伸缩语言的简称。这也是 Scala 在很多方面的特点。有相当明显的科学计算和统计计算的灵感也进入了语言的创造。

Scala 今日

现在我们至少知道了 Scala 是什么,让我们来讨论一下这种语言在 2021 年的状态。尽管 Scala 在某种程度上正在衰落,但这种语言仍然非常受欢迎,是许多雇主非常需要的技能。Scala 实际上仍然经常被使用,而且它很可能不会在短期内突然消失。也就是说,那些学习 Scala 进行数据科学的人可能也想学习另一种语言。

这是因为通常包含 Scala 的工作不仅仅是 Scala 工作,他们只是数据科学家,有些工作是在 Scala 中进行的,而通常是在更像 Python 的东西中工作。这是现代 Scala 的典型用法,更多的是作为大数据的机器。Scala 甚至将 Spark 和 Hadoop 与 Python 结合起来,为一台漂亮的小型大数据计算机器创建了一个非常棒的系统。

结论

2021 年数据科学该不该学 Scala?我认为这个问题的答案取决于给定的工程师在他们的数据科学旅程中处于什么位置。一些数据科学家可能毫无问题地学会了这种语言,只是顺其自然,而一些人可能会遇到麻烦。此外,很多时候你可能有更好的事情可以做。也就是说,如果你以任何一种方式学会了这门语言,在可见的未来很可能会有它的工作。也就是说,我仍然不会向一个有抱负的数据科学家推荐学习数据科学,当然不会。

那些在 2021 年将 Scala 作为数据科学的一个选项的人,至少应该非常擅长编写 Python……当然,这只是我的主观看法,但 Python 更有可能让你找到工作,会有更好的文档,并且更容易学习。真正损害 Scala 受欢迎程度的是 Python 的受欢迎程度,但真正有趣的是,Julia 真的已经成为业界的一名杰出人物。我很想知道这是否会对 Scala 的流行产生影响。很久以前,我写了一篇关于这个话题的文章,如果你对这个话题感兴趣,你可以在这里阅读:

两年前的这个月初,哇——我怎么记得我写了这个?

不管 Scala 在数据科学生态系统中的不确定未来,我认为它仍然是一门值得学习的伟大语言。无论是否计划将这种语言用于数据科学,情况都是如此。感谢您阅读我的文章,祝您有愉快的一天!

2021 年数据科学该不该拿起 Linux 技能?

原文:https://towardsdatascience.com/should-you-pick-up-linux-skills-for-data-science-in-2021-9458736d156a?source=collection_archive---------22-----------------------

Unix 技能是数据科学家必须掌握的吗?

(图片由作者提供)

介绍

数据科学的一个独特而具有挑战性的方面是该学科通常需要多种多样的技能。虽然一个普通的科学家可能需要阅读一些基本的统计和假设测试的科学或研究数据,但数据科学家也做同样的事情

  • 机器学习
  • 编程;编排
  • 企业管理

今天讨论的主题是,

  • 管道和 API 构建。

我认为这些是在从事数据科学职业时需要考虑的关键数据。对数据科学的大量介绍使它在许多方面看起来像它不是的东西。有许多不同的组件组合在一起,可以创建一个数据科学家,它可能会或可能不会受到某种方式的限制。如果您想阅读我一年前写的一篇文章中有关数据科学软技能的更多内容(哇!)您可以在这里查看这篇文章:

现实数据科学

考虑到我上面提到的技能集,这在数据科学技能和软技能的大计划中只是一个小提,很容易理解为什么许多人可能不知道从数据科学职业中可以期待什么。不同的工作之间也有许多技术方面和差异,这使得量化数据科学家完成特定职业目标所需的一切变得更加困难。

在这方面,最大的期望粉碎通常是数据科学家在大部分时间里实际做的事情。乍一看,似乎大部分工作是拟合高精度模型并将它们部署到生产中,就像人们在数据科学学校所做的那样。然而,我认为在考虑某个特定领域可能吸引你的想法时,仔细考虑这份工作中还有什么是很重要的。“数据科学家”这个名字的很大一部分是数据部分。

考虑到数据部分多于科学家部分,许多数据科学实际上是处理、准备、移动和返回数据。当然,一般来说,这是编程的一个重要部分,但是通常由整个团队工作的大型模型将需要一个额外的数据后端。此外,对于模型的部署来说也是如此,因为部署通常依赖于外部请求,对于 API 来说更是如此。

我觉得对数据科学最大的误解恰恰是这个。我知道,我很惊讶有多少数据科学只是停留在部署东西的技术困难后面,以及在部署之前对如何部署它们有一个坚实的理解。最大的挑战之一是当所有的工作都完成了,而部署解决方案没有按预期的那样工作。

部署管道并处理返回和请求的数据是数据科学的一项绝对重要的技能。管道部署的很大一部分将是为端点配置实际的服务器。这是一项也可以量化为开发-运营工作的任务,我当然认为这是对数据科学技能组合的一项好处。如果您想了解更多关于开发运营技能在数据科学中的好处,您可以查看我不久前写的这篇文章。所有这些倒退都让我很开心:

Linux 在哪里倒下

随着这些技术需求的消失,我认为现在重要的是谈论 Linux 在这个行业中的位置。Linux 在服务器领域占有 98%的市场份额。也就是说,如果你正在设置一个服务器,它很可能运行 Linux。这是因为 Linux 内核不仅更稳定,而且可以更多地访问各种命令以及它们各自的参数和参数。

因为大多数服务器运行在 Linux 上,所以我们的大多数终端也是由 Linux 驱动的。也就是说,我认为在准备部署之前彻底理解部署主题是至关重要的。我在本文中提出的问题是,这些技能作为一种技术技能,是否会成为数据科学家的一大卖点,这个问题的答案是肯定的。

往往这不仅是暗示,也是乔布斯要求的。数据科学家经常需要部署一个模型,我所在的团队部署计划很快就失败了。幸运的是,在大多数情况下,我拥有服务器管理方面的技术知识,可以有效地继续我们的工作,并让模型以我们可能需要的任何方式工作。

有许多非常酷的工具可以从 Linux 命令行访问以实现自动化,我认为这是任何数据科学家都应该感兴趣的事情。在我看来,自动化模型的后端非常棒,当你想做一些复杂的事情时,它真的很方便。像 Crontab 和 Supervisord 这样的工具在这方面非常有效,如果部署是最优的,整个系统通常可以压缩到最小的计算量。

也就是说,除了自动化和部署模型之外,这些技能还可以派上用场。对于典型的数据科学家来说,这些技能每天都会派上用场。Bash 不仅是处理虚拟环境最常用的系统,而且对于快速处理文件和运行服务器也很方便。完全没有头脑地进行数据科学是完全可能的,我认为,随着我们的笔记本和 Anaconda navigator 的出现,数据科学的这一方面已经完全丧失了。这些都是很棒的工具,而且要说明的是,我并不是在讨论“没有 DS 的 GUI ”,我只是认为这些无头终端工具在我的日常生活中对我很有用。此外,我认为这些技能提高了我使用计算机的能力。

结论—您的下一步行动。

T 这篇文章的目的是提供一个很好的理解,为什么这种特定的技能可能是你在数据科学发展中需要掌握的。我认为 Linux 和通用 Unix 管理和 Bash 技能对于任何想从事数据科学工作的人来说都是绝对必要的。虽然我不认为软件工程师也是如此,但我确实认为软件工程师也可以从教育和技能中受益。

几乎所有从事计算机技术工作的人都应该知道如何使用 Linux。我认为它已经成为这样一个行业标准工具,这意味着找到工作和找不到工作之间的差别,它绝对值得捡起来。考虑到这一点,如果你在船上,你首先应该做什么?幸运的是,我有一些关于基本配置和服务器工作的资源,您可以使用它们来开始了解一些概念。我认为一个好的方向是看一看我用 Crontab 构建的自我训练模型。

https://medium.com/chifi-media/build-a-beautiful-model-that-trains-itself-the-easy-way-a0d31b611cee

既然这样,我认为这项技能当然值得学习。这些技能不仅对找工作、处理模型和部署那些模型有益,而且在日常计算中理解幕后实际发生的事情也很有帮助。这种属性甚至可以渗透到对网络浏览的更深层次的理解中,所以这只是显示了这些技能在多大程度上融入了技术,以及它们有多有价值。感谢您的阅读,祝您白天(或晚上)休息愉快!)

真的应该像瘟疫一样避免递归吗?

原文:https://towardsdatascience.com/should-you-really-avoid-recursion-like-the-plague-d239aa50a16?source=collection_archive---------22-----------------------

忘记你的计算机科学教授告诉你的——这里是递归的真相

(src =https://pixabay.com/images/id-6635502/

介绍

在有时精彩,有时令人畏惧的计算机编程世界中,有许多可怕的词汇,对于一个新手,有时甚至是一个有经验的程序员来说都是可怕的。在许多情况下,令程序员感到害怕的一个词是递归。这是因为递归的关联通常被发现应该永远不要使用。也就是说,这绝对是一个反对这种技术的基于观点的论点,我个人认为看一看递归在软件中的什么地方被使用以及为什么在那里被使用可能是有意义的,以更好地理解这种关联到底来自于什么。

当然,没有一种技术是完美的。其他循环技术也总是存在问题,比如 while 循环和迭代循环。也就是说,从机器码的角度来看,有一些非常合乎逻辑的原因使得递归在许多场景中显然不是一个好的选择。然而,对于“是否应该使用递归?”实际上是一个相当复杂的问题,因为实际上在某些情况下,可能需要使用递归。

什么是递归?

在我们深入探讨为什么递归既是一件好事又是一件坏事之前,让我们首先描述并回顾一下递归到底是什么。对于下面的例子,我将使用 Julia 代码——因为它对那些不编程的人来说也是非常可读的,而且它也是我最喜欢的语言。也就是说,我还将提供一个笔记本,其中包含本文中使用的示例代码:

让我们考虑下面这个递归的例子:

function add_rec(x) if x < 30000 x += 1 add_rec(x) else return(x) endend

在这个例子中,函数 add_rec()首先检查 x 是否小于 30,000。这在递归应用程序中很常见,在递归应用程序中,如果完成了检查,就进行检查以中断循环。现在让我们考虑迭代的例子,它尽最大能力写成与递归例子相同:

function add_iter(x)for i in x:30000 if x < 30000 x += 1 else return(x) endendend

仍然很简单,但是这次计算机也知道一个停止点。计算机会知道这个循环需要运行的确切次数。递归不是这种情况,现在让我们计算一下这两个函数的时间,看看结果:

@time add_rec(1)0.000094 seconds@time add_iter(1)0.000000 seconds

嗯,我们在这个测试中确实遇到了一个问题…

朱莉娅太快了。

尽管 Julia 很快,而且在这里可能很难看出显著的性能差异,但我们可以清楚地看到递归示例确实较慢。考虑到这一点,为了更好地展示这一点,我决定用 python 重写代码

(图片由作者提供)

对…

通过这两个例子,你可能已经开始弄清楚什么是递归了。递归是我们调用整个方法定义的地方,而不是在函数内部实例化一个循环。因此,性能会受到很大的影响。这有几个原因。第一点很简单,方法调用比典型的 for 循环需要更多的计算。

发生这种情况的下一个原因是因为 while 循环本质上是为编译器设计的。当我们调用一个迭代循环时,编译器知道更多关于我们将要创建的循环的定义。有始有终。有些值是在编译器已经准备好的 for 循环范围内声明的。这就完美地引出了递归既迷人又对性能有害的最大原因——嵌套。嵌套是指同时使用多个作用域层。关于嵌套要记住的一件重要事情是,每次创建一个嵌套,编译器都要做大量的工作。声明了新的成员变量,在这个例子中是 x,声明了一个新的作用域层,这意味着所有这些值对于这个特定的方法调用都是私有的,而不是像 while 或迭代循环中的单个定义。

换句话说,每当我们打电话

for i in x:1000

我们只需要初始化一个变量,计算机已经知道它的类型是我们提供的 iterable 中的任何类型。在本例中,这是一个范围生成器,因此返回的类型将是一个整数。然而,每当我们打电话

add_rec(x)

这将重新创建该方法调用。这是这两个元素之间非常明确的根本区别——方法不是循环,循环也不是方法。使用递归,我们实际上是强迫一个方法成为一个循环。

从硬件看递归

既然我们已经理解了递归,以及为什么它会对硬件造成损害,那么让我们考虑一下递归在硬件上是什么样子的。为此,我当然会写一些汇编来演示。请继续关注我,因为我认为这很可能会改变你看待计算中递归的方式。我将编写一个读取、求值、打印循环——这当然是递归循环的一个例子——至少在汇编时是这样。另外,如果你想学习更多关于编写汇编的知识,我有一篇文章,我认为可以用“Hello World!”所有人都可以在这里读到:

总之,这是我的。数据部分,它只是提供一个保存在堆栈中的提示,我们可以用它让用户输入一行。然后,我将添加一个. bss 部分,这只是允许我用一个别名保留一些内存。在这个例子中,我们只需要一个字节,因为我只是将整数存储在这里:

section .data
repl_prompt: db "Heya> "
section .bss
inp resb 1section .text  
global _start

我还添加了我的。文本部分,它包含了我的处理器要解释的所有代码。global _start 在这里的原因是因为这个函数将被用作一个入口点,因此我们希望汇编器知道当我们到达这里时该去哪里。现在,让我们最终开始编写 _start 函数,它将读取、计算并打印:

_start:; Check for exit code set to 1:mov rdi, 1cmp rdi, inpje _exitmov rdi, 0je _retzer; Readcall _promptcall _repl_input; Evaluatemov rsi, inpmov rax, 1mov rdi, 1mov rdx, 2syscallmov rsi, 10mov rax, 1mov rdi, 1mov rdx, 2syscall; Loopjmp _start

正如您所看到的,在 _start 过程的末尾,我们返回到 _start。假设这是一个函数,下面有几个不同的单独调用。这本质上看起来像是递归的应用,这是一件有趣的事情——因为从非常低级的硬件角度来看,这通常是软件的工作方式。每个应用程序的文本被调用,有时作为子程序,但通常作为主要的循环过程。

众所周知,循环是计算机计算方式不可或缺的一部分。当涉及到低级别时,与代码的处理器实现交谈——避免这种循环的唯一方法是调用. loop。当然,在汇编中也经常这样做,但前者也这样做仍然有效。我在这里想说明的是,在低端机器上使用了多少递归。

此外,编译和加载它,我们看到这个应用程序是一个 REPL,它本身经常是这样写的。这意味着我们用来处理和调试代码的 REPLs 通常本质上是递归的。此外,您可以在我的“随机代码库”中查看我为这个示例编写的所有程序集:

https://github.com/emmettgb/Random_Code/tree/main/assembly_repl

高级编程中递归的实现

好了,现在我们已经看到了在低级操作中使用递归的例子,我们是数据科学家,通常不在那个级别上操作,所以让我们看一些在高级意义上使用递归的例子。虽然递归当然不会像迭代那样被广泛使用,甚至不会像传统的 while 循环一样被广泛使用,但是仍然有一些使用递归的例子。我通常认为统计分析和数据科学中最重要的是阶乘的计算。

阶乘很难计算。当计算与它结合时,这种情况更加有效。阶乘对于许多语言来说都是一个非常大的问题,实际上我很久以前就写过一篇文章,讲述我最喜欢的语言 Julia 是如何处理阶乘的。他们使用查找表,而不是计算阶乘,这意味着阶乘被缓存。如果这只是针对低于表所达到的计数的阶乘,那就好了,但事实并非如此。另外,你可以在这里阅读我写的关于这个话题的文章:

这表明,即使是像 Julia 这样非常数学化的语言,也会有阶乘的严重问题。总之,典型地,递归阶乘实现是这样写的:

function fact(n) if n == 1 return(1) else return n * fact(n-1) endend

如果不使用递归,真的没有什么好的方法来计算这个。当然,在现有软件的整个范围内,有很多这样的例子。

应该使用递归吗?

所以问题来了,你应该避免递归吗?答案比简单的是或不是要复杂一点。尽管许多计算机科学家和教授可能会坚持,递归的使用肯定有一些有效的方面。这在高层次的意义上和非常非常低层次的意义上都是正确的。正如我们在汇编示例中看到的,在许多情况下,汇编代码中没有使用子例程,这可能使递归成为这种情况下最有效的选择。

我想我会推荐一篇关于如何运用这种判断力的好文章,作者是费思·齐克威。本文详细介绍了何时应该使用常规循环,通常是迭代循环,而不是递归实现。如果你想更多地了解他们在这个问题上的主张,你可以在这里看到一篇很好的文章:

https://betterprogramming.pub/when-to-loop-when-to-recurse-b786ad8977de

结论

到总结,虽然递归肯定不是没有问题,但是拥有这样一个工具也有一些非常重要的好处。没有理由完全忽略和不使用任何编程技术,甚至递归。非常感谢您的阅读,我真的希望这篇文章对这种经常被认为是不可用的技术提供了一些反思。祝您愉快!

是否应该停止使用 Else?

原文:https://towardsdatascience.com/should-you-stop-using-else-cd1820b00c02?source=collection_archive---------37-----------------------

else 关键字不好吗?您应该将它完全从代码中删除吗?

(src =https://pixabay.com/images/id-634941/

介绍

在编程中,为了从一系列的参数中得到想要的回报,程序员常用的技巧有很多。为了在高级编程语言中调用这些技术,我们经常使用关键字。程序员经常为此使用条件和循环,尽可能有效地使用这两者是编程的组成部分。

也就是说,处理问题和使用这些技巧来解决问题,总有一个错误的方法和一个正确的方法。在这方面,一个有争议的话题是 else 关键字。许多程序员已经把 else 这个关键词完全从他们的编程团队中删除了。这是因为使用 else 会带来一些问题,尽管在某些情况下 else 对解决问题很有价值。但是是什么让 else 语句如此糟糕呢?真的有办法可以完全避免使用 else 吗,或者这只是程序员为了恐吓他人而使用的另一种说法?今天,我想回顾一下我对 else 关键字使用不当的主观体验,并回顾一下我对这种无 else 方法的看法。希望所提供的信息可以阐明您自己代码的一些潜在问题,或者对您以某种方式构造条件的方式产生影响。

笔记本

嵌套

为了理解 else 块的问题,我们需要首先理解嵌套。在很多方面,我们可以把嵌套看作给定代码块的层。关于嵌套要记住的重要事情是,它本身就是一个循环,不管这个循环是否重复。任何嵌套的东西都可能有自己的作用域,这意味着在其作用域中声明的值不会是全局的。

此外,一个简单的方法是直接在全局范围下嵌套一层。在模块的例子中,我们可以有一个从全局到模块的嵌套层,然后是模块内的方法,然后是方法内的迭代循环。让我们看一个迭代循环来进一步演示这一点。

for iteration in range(1, 5):
    z = 5
    print(z)

在这个循环中,我们定义了一个新变量 z,它保存整数 5。每当我们试图在这个 for 循环的范围内使用这个值时,我们可以看到这个值被打印了四次,在 1:5 的范围内每次迭代打印一次。我们可以通过编写所谓的嵌套 for 循环来给这个函数添加另一层嵌套。这本质上是一个循环中的循环。现在我们正在一个循环中运行一个循环,事情变得非常复杂,因为为了现在使用 z,我们需要考虑在此之前已经使用过的所有循环。

for iteration in range(1, 5):
    z = 5
    for i in range(1, z):
        print("iteration")
    print(z)

这对于可读性来说是个很大的问题,因为这意味着任何阅读我们代码的人都必须参考我们之前的代码才能理解我们正在处理的变量。无妨的是,一系列 for 循环同时工作可能会相当混乱。我们也可以对条件句做同样的事情,并创建嵌套的条件句。很容易理解为什么过度使用嵌套会很快使您的项目显得复杂,让任何试图阅读您的代码的人感到困惑。但是这和其他有什么关系呢?

其他

既然我们理解了嵌套,else 在可读性方面的重要问题很快就变得非常明显了。else 关键字严重依赖于写在它前面的代码。如果不先写一个 if 块,我们就不能使用 else 块。例如,以下代码不是有效的语法:

else:
    print("hi")

这意味着每次我们添加一个 else 语句,我们也在它后面添加了各种各样的嵌套,甚至没有意识到这一点。考虑以下函数:

def else_test(x):
    if x == 5:
        print("five")
    elif x == 4:
        print("four")
    elif x == 3:
        print("three")
    elif x == 2:
        print("two")
    else:
        print("one")

为了让这段代码打印出 1,x 不能等于 5、4、3 或 2。这些条件中的每一个都是程序员在分析代码时需要考虑的。此外,这段代码中的 elifs 遵循相同的功能。因此,这段代码中的每个连续条件语句都有另一层嵌套。

重组条件句

考虑到我上面写的函数,现在让我们只用 ifs 来重构它,然后我会谈到你是否真的应该这样做。为了修改这段代码,我们只需要将所有的 elifs 改为 if,将 else 改为新的 if 语句。

def else_test(x):
    if x == 5:
        print("five")
    if x == 4:
        print("four")
    if x == 3:
        print("three")
    if x == 2:
        print("two")
    if x == 1:
        print("one")

当然,这个新代码有一些优点和缺点。首先,如果我们输入数字 6,这个函数没有任何返回。其次,代码更容易阅读,因为我们可以单独读取每个嵌套的块。在这个例子中可能看起来不是这样,但是在大多数真实的编程情况下,这最终会变得更容易阅读。这是因为一旦到了第五个阶段,我们就不需要再回头去回顾前四个阶段发生的事情了。

现在,如果我要写这个函数,我会写什么代码呢?当然,答案是第一个例子。我认为有一个地方和时间可以用两种方式来写条件句,诚实地说,避免混淆是一个很难驾驭的斜坡。在你自己写完代码之后,你不可能第一次分析你的代码。可读性归结为试图像阅读英语一样阅读自己的代码。您应该能够逐行查看您的代码,并说出每一行的作用。导致代码缺乏可读性的原因有很多,虽然我认为一些 else 语句肯定不好,但我不认为使用关键字本身是一种罪过。

结论

嵌套是计算机编程中的一个重要组成部分。它允许我们让简单得多的代码变得更加强大。然而,伴随着强大的能力而来的是巨大的责任,如果不小心的话,嵌套会完全破坏代码的可读性。以我的主观看法,我认为使用 else 关键字是完全可以接受的。然而,就像生活中的任何东西包括水和食物一样,它的使用必须总是适度的。

在我关于代码重构的文章中,过度使用条件句是一种不好的编程实践。如果您还没有机会阅读那篇文章,可以在这里找到,我认为它确实值得一读:

</5-fabulous-refactoring-methods-for-prettier-code-e3bc3447c0b2> [## 更漂亮的代码的 5 个惊人的重构方法

towardsdatascience.com](/5-fabulous-refactoring-methods-for-prettier-code-e3bc3447c0b2)

条件句的过度使用也适用于 else 的过度使用。用的时候应该是有意识的决定。您还应该考虑它上面的每个条件的开销,并注意只有当所有这些条件都丢失时才会命中 else。换句话说,任何使用你的软件的程序员都需要弄清楚如何调用它,如果它嵌套在数百个条件之下,那就相当困难了。我不认为有必要把它完全从你的编程团队中删除,但是我认为应该负责任地使用它!感谢您阅读我的文章,我希望它能让您对 else 和嵌套有更多的思考!

你应该使用。包括或。过滤器检查数组是否包含一个项目?

原文:https://towardsdatascience.com/should-you-use-includes-or-filter-to-check-if-an-array-contains-an-item-1a8365dfc363?source=collection_archive---------2-----------------------

WEB 性能

两种方法都可以。Array.prototype.filter()Array.prototype.includes()强大得多,而.includes()方法更容易阅读,性能也更好。

照片由 Athena LamUnsplash 上拍摄

如果你需要知道一个 JavaScript 数组是否包含一个条目,除了写一个[for](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) 循环之外,你还有几个选择。

最明显的选择是[Array.prototype.includes()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes),但是使用[Array.prototype.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)可能会节省你未来的重构。

**includes()**方法确定数组的条目中是否包含某个值,根据情况返回truefalse
MDN 文档

如果您需要返回第一个匹配的条目,您应该使用[Array.prototype.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)而不是.includes()

更强大的.filter()方法让您用任意标准测试整个数组,它返回所有匹配项的新数组。换句话说,.filter()给出了一个过滤后的数组。

如果以后您需要处理匹配的项目,或者将包含条件更改为任意条件,您将需要使用.filter()。比.includes()厉害多了。

"**filter()**方法创建一个新数组,其中所有通过测试的元素都由提供的函数实现。"
MDN 文档

如果您检查由.filter()返回的数组是否有一个[.length](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length) > 0,您将知道数组是否包含至少一个匹配的值。这将模拟.includes()的行为。

还有相关的[Array.prototype.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)法,基本是在.includes().filter()中间。

**some()**方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。它返回一个布尔值。
MDN 文档

.some()方法允许一个任意的条件,比如.filter(),但是不返回匹配项的数组——只有[true](https://medium.com/coding-in-simple-english/what-are-truthy-values-in-javascript-e037bdfa76f8)[false](https://medium.com/coding-at-dawn/what-are-falsy-values-in-javascript-ca0faa34feb4)

因此,如果您需要测试数组中的任何一项是否匹配任意条件,.some()无需创建额外的数组。(这类似于[.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)[.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)的区别。)

你可能会认为.filter()会比.some()慢一点,因为多了一步。后来,我验证了这个假设。

看看这个 JavaScript 代码示例,它演示了判断数组是否有给定值的四种方法:

将原始代码视为 GitHub 要点

查看原始代码作为 GitHub 要点

哪个 JavaScript 数组方法最快?

C 众所周知,某些 ES6 函数在大型数据集中被认为比老式for循环更慢。具体来说,[for](https://hackernoon.com/3-javascript-performance-mistakes-you-should-stop-doing-ebf84b9de951) 循环比 [.forEach](https://hackernoon.com/3-javascript-performance-mistakes-you-should-stop-doing-ebf84b9de951) 循环慢,尽管我更喜欢更简单的版本

当然,对于小数据集来说,这没什么大不了的——担心它将是“过早优化的严重情况。”

为了可读性,我们同意.includes()是最明确命名的方法,表明你想知道一个数组是否包含一个项。但是哪个是最快的?includes().filter().some(),还是一个for循环?

我知道你需要速度,所以我运行了这些 JSBench.me 测试用例来测试上面代码示例的微性能:

查看原始数据作为 GitHub 的依据

在 Visme 查看图表将数据作为谷歌表单

我们在图表中可以清楚的看到.includes()以 10 项明显胜出,在 1000 项中独占鳌头。

当我们到达 100,000 个项目时,.includes()变慢了:它的性能是for循环的 53%(慢了 47%)。结果与 1,000,000 个项目几乎相同。

这些测试测试的是*均案例性能(列表中的中间项)。为了完整起见,我包括了.find(),因为我发现另一个数据集使用了.find()而不是.includes()

结果会因您的测试环境而异。我在 Windows 10 上用的是最新的谷歌 Chrome(88 版,64 位)。然而,在我将我的结果与其他数据进行比较之前,我们先来讨论一下在 JavaScript 开发人员的现实生活中什么时候使用for循环。

性能差那么多吗?

你的数据需要多大才能让你为了性能而牺牲代码的可读性?

可能比你想象的要大。

要点如下:使用.includes()查看数组是否包含项目,除非您的数组包含超过 100,000 个项目。在这种情况下,使用for循环代替,因为它的速度是.includes()的两倍。

"从长远来看,通过清晰和可重用的编码,你将获得更好的性能."

Reddit 上的约书亚·库迪斯

根据上面的结果,你需要数组中有几十万个元素才能切换到一个更难阅读的for循环。

在这一点上,你可能肯定想切换到for,但在此之前.includes()不仅更容易阅读,它实际上更快。默认情况下,当您需要检查数组是否包含项目时,请使用.includes()。对于小型数据集来说,这是一个三赢的局面。

让我们保持真实。在实际处理数组中成千上万的项之前,不需要过早地优化代码。在这一点上,考虑切换到一个for循环。

Riccardo Polacci 在他写给《值得关注》杂志博客的一篇文章中出色地讨论了 ES6 函数的可读性和性能之间的权衡:

https://blog.usejournal.com/performance-vs-readability-2e9332730790

我试图找到其他研究来支持我的性能结果,Deepak Gupta 在 2018 年的hacker noon**和forward Data Science(完整结果在 GitHub 上)发表了大量的for循环测试数据

截图来自迪帕克·古普塔GitHub 知识库的德里克·奥斯丁·🥳博士,对第 1 条 & 第 2 条的补充

Deepak 发现,直到你在一个数组中找到 100,000 个元素,for循环并不比像[.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)[.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)这样的原生 JavaScript 函数慢多少。当数组中有 500,000 个或者特别是 1,000,000 个元素时,这种差异对于使用for循环来说变得更加明显。他将for循环比作.find(),这几乎就像.includes()

德里克·奥斯丁·🥳博士截图迪帕克·古普塔GitHub 知识库,对第 1 条 & 第 2 条的补充

Deepak 的数据显示,对于中等大小的数据,.find()for循环更快,我用.includes()也得到了同样的结果。然而,对于小数据集,我们的结果有所不同:他发现for循环几乎是即时的,而.includes()稍慢一些(0.10 秒)。

在我的测试中,我发现对于小数据集来说,.includes()击败了for循环——但这可能是因为.includes().find()之间的根本区别。后者使用一个回调函数,这意味着您可以使用.find()中的任意代码。

换句话说,.find()就像.filter():它们都很强大,但是很慢,因为它们采用了回调函数。同时,.includes()是快速的“是或否”搜索特性,它返回一个布尔值。(作为最后的测试,我还尝试用 JSBench.me 的缓存回调函数,但是这样做并没有改变我的结果。)

Chrome V8 几乎肯定使用了性能优化,比如内联缓存,这使得小数据的处理速度大大提高。我敢肯定,当内存成为更大的问题时,性能提升消失是有技术原因的。

一个包含百万条目的数组在 Chrome 中占据大约 10MB ,这可能大于 CPU 的 L2 缓存,后者通常为 256KB-8MB。这意味着阵列在物理上远离 CPU,并且数据必须从 L2 缓存传输到微小的 L1 缓存才能被处理。这是我对结果的最佳猜测。

一个数组包含一个项吗?使用.includes()

W 说唱起来,我们发现 JavaScript 的内置.includes()方法是检查 JavaScript 数组是否包含项目的最快方法,除非你有一个包含很多项目的数组。

在大多数情况下,.includes()for更可读,更快,所以一定要用.includes()。最后,让我们讨论一下其他更慢的选项,看看数组是否包含元素。

我的大脑喜欢通过使用.filter()寻找匹配项来解决确定一个数组是否包含一个项的问题。过滤数组有一些有趣和直观的东西。

通过检查该数组的大小,我知道该数组是否包含该项,但我也可以灵活地轻松更改包含标准。当然,从内存使用和处理速度的角度来看,如果我以后从来没有真正使用过这个数组,那会造成很大的浪费。

寻找数组中是否至少有一项(即一些项)匹配任意标准的“最佳”工具是.some()。但是我的蜥蜴脑喜欢我可能使用那些过滤的项目的想法,所以我倾向于只依赖.filter()而不是.some()

当然,如果我需要做的只是检查数组是否包含特定的项。正如我们看到的,filter()是多余的。当你有小数据集时,**.includes()** 快得惊人。数据集越大,**for** 胜于,但数据需要大,像“大数据”一样大。

根据你的项目,你可能会发现.filter().includes() 更好——你也可以考虑使用.some().find()。每一个都有稍微不同的目的,但是最好记住可能会有性能差异。

你绝对应该使用.includes() …除非你正在处理一个有几十万个条目的数组,在这种情况下,你绝对应该使用一个 [for](https://www.freecodecamp.org/news/how-to-optimize-your-javascript-apps-using-loops-d5eade9ba89f/) 循环来提高性能

编码快乐!🐚🌞🕶🌻🌴

照片由 Caleb DowUnsplash 上拍摄

德里克·奥斯汀博士是《职业规划:如何在 6 个月内成为一名成功的 6 位数程序员 一书的作者,该书现已在亚马逊上架。

你应该使用现成的还是开发一个定制的机器学习模型?

原文:https://towardsdatascience.com/should-you-use-off-the-shelf-or-develop-a-bespoke-machine-learning-model-6cf826ecd179?source=collection_archive---------23-----------------------

支持和反对使用预先构建的现成模型的论点。

Unsplash 上由 Jaredd Craig 拍照

作为一名数据科学家,我喜欢探索新的领域来应用我的技能。找出适合问题领域的模型,并思考一些可以描述预期结果的特征,这些都是我喜欢的挑战。随着现成(OTS)模型的兴起,这一领域的自动化程度越来越高,这就提出了一个问题:你是否应该费心构建一个定制模型来解决问题。这并不意味着 OTS 模式正在接管,没有定制模式的空间,它们都是工具,都有需要它们的情况。作为澄清,我将不涉及 AutoML 或 MLops *台,尽管它们是现成的系统,但它们不是特定的模型,这两个*台都是后续文章的主题。在这篇文章中,我将探讨 OTS 和定制机器学习(ML)模型的利弊,并讨论何时应该考虑使用 OTS,何时应该继续开发定制的东西。

首先,让我们来定义一下什么是 OTS 模式:OTS 通常指的是一种立即可用的产品,不需要为适应特定目的而特别制造[https://dictionary . Cambridge . org/dictionary/English/off-the-shelf]。在 ML 和 AI 中,这通常意味着为特定任务预先构建、预先训练和预先优化的模型或 API(背后有一个模型)。这些模型的数据输入是已定义的,您必须符合所提供的模式,并且数据输出通常是固定的,这是因为 OTS 模型是为了解决特定的任务而构建的。这并不总是与你试图解决的问题完全一致。

云中的 OTS 模式的例子有 Azure Cognitive services[https://Azure . Microsoft . com/en-GB/services/Cognitive-services],以及 Amazon Rekognition、Amazon understand 和 Amazon SageMaker JumpStart(仅举几个 AWS 的例子,它们没有一个统称)[https://aws.amazon.com/sagemaker/features

使用现成产品的优势。

首先是积极的一面,与定制车型相比,OTS 的成本可能较低。这主要是因为工程时间是昂贵的,使用 OTS 模型可以大大减少你的开发时间,从而降低开发成本。仍然有一些费用是服务提供商收取的订阅费或处理费,这是为您的使用付费。

另一个主要优势是准确性,尽管这在很大程度上取决于您的用例。如果 OTS 模型完全符合您的用例,并且已经过预训练和预优化,那么您将很难创建一个有竞争力的定制模型。这主要是因为服务提供商通常拥有大型团队来处理这些模型,并且能够访问来自服务的所有用户的大量数据。因此,如果您的用例符合服务的用例,那么利用它可能是一个好主意。

OTS 模型对于绿地或概念验证(POC)项目(一个没有先前工作强加的约束的项目)非常有用。它们允许你快速开始并在很短的时间内产生结果,尤其是当你缺乏自己的数据时。

当一个系统投入生产时,维护该系统可能是一个挑战。如果你在系统中有一个定制的模型需要生产,就更是如此。使用 OTS 解决方案将允许您进入生产环境,并利用许多 OTS 服务的生产就绪特性,限制您维护模型的需求,因此您只需担心与服务提供商的 API 的连接。

使用现成产品的缺点。

经常出现的问题是,您的用例略有不同,或者没有被 OTS 服务覆盖。如果您的用例稍有不同,POC 项目调整需求,或者对数据执行一些后处理或预处理以使其适合可能是有意义的。这将影响你的准确性,并可能意味着你在未来考虑定制模型。如果 OTS 服务不能覆盖你的用例,那么你别无选择,只能创建一个定制的模型。由于大多数 ML 系统由多个阶段和模型组成,您可能会将 OTS 服务用于您的部分管道。有必要对你的系统进行分解,看看 OTS 模型是否适合某个阶段的需求,尤其是在项目的早期。

使用定制的优势。

准确性经常被吹捧为使用定制模型的原因,但正如上文所讨论的,如果您的用例适合,OTS 模型可以胜过定制模型。通常,OTS 并不适合,必须换鞋,这对于概念验证来说是可以的,但定制模型在这种情况下会很快表现出色。

借助定制模式,您可以更加灵活地应用任何尖端技术,这可能比等待您的服务提供商实施任何新技术要快得多。这种灵活性也带来了试验和尝试不同方法来解决具体问题的能力。

使用定制模型,您可以更好地控制模型的隐私,因为数据不会通过您的服务提供商系统传递,因此您不需要担心他们对隐私的态度。

使用定制的缺点。

构建真正定制的机器学习模型可能很难,非常难。尤其是当涉及到功能工程、优化和生产时,需要考虑很多因素。大多数机器学习系统需要一个主题专家和一个机器学习专家,就像所有跨学科活动一样,它带来了独特的挑战。

模型投入生产后,另一个需要考虑的问题是基础设施和维护。使用适当的基础设施与您的客户、最终用户或*台开发团队合作可能是一项挑战,因为您不能只是将 jupyter 笔记本电脑投入生产。如果你的模型成功了,你就需要想出如何扩展它。从一开始就将可伸缩性规划到模型中需要预先规划,并且没有范围漂移。通常,项目会在某个时候导致模型重建,以允许以后的可伸缩性。

结论

题目的答案是,“你应该使用现成的还是开发一个定制的机器学习模型?”很大程度上取决于你在做什么,你工作的公司,以及你可以利用的资源。

如果这是一个绿地项目,如果你能找到一个足够适合你的用例,你可能想使用 OTS 服务开发*台。如果你有一个现有的*台,你想尝试一个机器学习模型来自动化一些东西,那么首先尝试现成的。一个新项目开发定制产品的唯一原因是,如果你找不到现成的服务来作为概念验证,或者你没有截止日期和大量的可用资源。

如果你为一家初创公司工作,OTS 服务可以削减成本,并在早期提供概念证明,以引起客户和投资者的兴趣,如果你缺乏任何数据来训练你的模型,这一点尤其如此。然后,您可以获得资源和数据来定制模型。如果你在一家企业公司工作,你可能有时间、资源、现有的数据集,并在内部购买,直接跳到一个定制的模型,你可以花一些时间来开发。

如果您正在开发一个真正新颖的模型,并且不能利用任何现有的现成服务,那么您将希望跳转到定制模型的主要情况。这里的一个警告是,这假设了一个非常二元的问题观点,并且有许多支持创建机器学习系统的服务,如 AutoML 和 ML Ops,没有被考虑在内。

作为最后一点,我鼓励你评估任何即将到来的项目,看看你是否可以通过 OTS 模式的首次推出来加快速度,特别是如果它让你的经理满意,从而有不间断的时间来研究新的定制模式。

浓缩咖啡淋浴屏

原文:https://towardsdatascience.com/shower-screens-for-espresso-e56357f083b6?source=collection_archive---------23-----------------------

咖啡数据科学

升级淋浴屏幕

淋浴帘可以影响水流入圆盘,就像过滤篮影响水流出圆盘一样。一般来说,较新的机器有很好的淋浴屏幕,经过一些维护,它们工作得非常好。旧机器是一个不同的故事。在精密篮子出现之前,它们的质量和规格就值得怀疑。

我已经在 Kim Express 上将库存的淋浴屏升级到 IMS 淋浴屏两次了。然而,直到现在,我也没有像我希望的那样很好地记录这个变化。

设备/技术

浓缩咖啡机:金特快

咖啡研磨机:韩国

咖啡: La Prima Miscela 酒吧

预输注:15 秒

输液:压力脉动

过滤篮:Pesado 精密篮

其他设备:Atago TDS 测量仪,Acaia Pyxis 秤

金快线淋浴屏

这个淋浴帘至少有 40 年历史了,非常干净。然而,水点显示了它没有完全覆盖的地方。

检查后,它似乎比我用过的其他机器干净得多。

为了取下它,我用了一个小螺丝,小心翼翼地把弹簧弹出来。弹簧很容易折断,所以要小心,因为我以前折断过一个。然后我把新的放进去,它在孔的数量和排列方面有更好的设置。

左:原金淋浴屏幕。右图:IMS 淋浴屏幕。

发射

原始淋浴屏幕是最上面一行,IMS 淋浴屏幕是最下面的 5 秒、10 秒和 15 秒。最上面一排最初的篮子在边缘很快褪色,需要一点时间来覆盖过滤器。然而,IMS 淋浴屏幕示例更快地覆盖篮子,并且在圆盘上具有更均匀的颜色。

预灌注从左到右:开始、中间、结束;上图:原始淋浴屏幕,下图:IMS 淋浴屏幕

在输液过程中,原始的淋浴屏幕拍摄甜甜圈,并不像 IMS 屏幕那样完全融合在一起,IMS 屏幕保持更深的颜色更长时间,融合得很好。

输液从左到右:开始、中间、结束;上图:原始淋浴屏幕,下图:IMS 淋浴屏幕

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。

最终得分 是评分卡上 7 个指标(辛辣、浓郁、糖浆、甜味、酸味、苦味和回味)的*均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水*。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

使用折射仪测量总溶解固体量(TDS),这个数字结合咖啡的输出重量和输入重量用于确定提取到杯中的咖啡的百分比,称为提取率(EY)** 。**

表演

味道和提取效果有着直接的区别,考虑到这两张照片的样子,我并不感到惊讶。更均匀的镜头味道会更好。

****

最后的拍摄时间非常相似,但 IMS 淋浴屏幕花了很长时间才流入杯子。

升级设备时我总是很紧张,因为我害怕以新的方式损坏机器。或者,我担心某个部分,虽然以某种方式破碎了,却给了我的咖啡某种独特的味道,我会怀念它,再也回不来了。这两件事都没有发生。

如果可以的话,我绝对鼓励对旧机器进行升级。我一直在另外两台机器上使用这种屏幕,可能是因为它的成分,它是一个更干净的屏幕。

如果你愿意,可以在推特和 YouTube上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。也可以在 LinkedIn 上找到我。你也可以关注我的媒体订阅

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事首页

摄影启动页面

使用图像处理测量咖啡研磨颗粒分布

改善浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡滤纸

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维修

咖啡评论和想法

咖啡实验

作为数据分析师展示增值

原文:https://towardsdatascience.com/showing-value-add-as-a-data-analyst-a4d5ac97313c?source=collection_archive---------28-----------------------

办公时间

开放数据集:它们不仅仅是为了可视化和模型

Sharon McCutcheon 通过 Unsplash 拍摄的照片

我将解释作为一名数据分析师,你如何在不实际“分析”数据的情况下,为你当前/未来的潜在雇主增加价值!

嘣!—你的思想,因为它刚刚被吹爆了

这是什么疯话?!?

获取、准备和探索是数据管道的三个早期阶段。“好吧,但这对我有什么帮助,”,你可能会问。你是分析师,不是工程师。你所需要的是可用形式的数据,你可以把各种各样的表格放在一起,制作一些可爱的 viz。对吗?

“我们会……”我,正要告诉你一些坏消息

什么是可用数据?

在一个超级棒的数据科学训练营 Codeup 期间,我学到了一个非常有价值的人生信条:“这取决于应用。”可用数据取决于其用途。任何人都可以从他们可以访问的任何表格中“选择*”或获取同事使用的 Excel 文件,并开始制作各种条形图和线图。这有可能引发许多不必要的消防演习。

接下来的这一部分将着重于您能够探索您的数据,并能够理解是否有任何事情看起来不对劲。在这里,你可以展示你属于善用数据的世界。如果您正在处理的数据中存在大问题,那么世界上所有的可视化和深入分析都毫无意义。分析型领导者会同意这种说法。

旁注:这是你听说过的数据科学中不好玩的部分。这也是数据科学中非常重要的一部分,你应该集中注意力。

让我们把它变得不那么抽象

接下来的几段可能会有点无聊,但是对于上下文来说非常必要。

我将向您展示 Kaggle 的“酒店预订需求”数据集中的几个数据示例。这个数据集由两家酒店的行/观察值组成,一家城市酒店和一家度假酒店。每行代表一个预订。示例栏允许您查看客人的到达/入住日期、客人数量(成人、儿童、婴儿)、ADR(*均每日房价)以及预订的是两家酒店中的哪一家。

为此,我将重点关注一个布尔值列,该列指示客人之前是否在酒店住过(0 是新客人,1 是回头客)。还有另外两列给出了客人取消的先前预订数和客人未取消的预订数。

逻辑告诉我们,新来的客人以前不会住在酒店。此外,作为回头客的客人会有先前的访问。我们看到的行不是这样。

作者照片

作者照片

在现实世界中,你可能会去找一个工程师或者提供数据的人来检查代码的逻辑。在这个例子中,你不能。

垃圾进,垃圾出。—一大堆数据

作为一名分析师,很大一部分工作是确保你使用的数据已经通过了健全性检查。这里的棘手之处在于,出于业务目的,可能有无数种不同的方式来查看数据。您和您的团队很可能在构建表格时无法想到要检查的所有项目。一旦你开始有目的地使用数据,事情就会变得更加明显。

现在,我们专注于可视化数据

下一部分更关注利益相关者在这类数据集中会发现什么是重要的。还有一个重点是创造力和将数据转换成数据集来回答你的特定问题的能力。

我们有两家酒店,我们可以很容易地看到每个酒店每个月有多少入住。数据集由两年多的观察数据组成。

如果你是一名区域经理,你会如何关注两家不同酒店的入住人数?

为什么我不在乎入住的次数:

  1. 两家酒店很可能有不同数量的房间。
  2. 如果一家酒店是更短暂(短期住宿)的酒店,而另一家酒店是长期住宿的酒店,那么入住总数将真正突出某个特定的酒店。

可视化签到不是苹果对苹果的方法。

我可以想象,担任这一角色的人会更关心每家酒店的入住率、入住房间数/可用房间数。我们来看看入住率和入住率的区别。

作者照片

作者照片

这两个酒店之间的结果在这些图像中非常不同。基本上,城市酒店确实有更多的预计房间,也有预订时间较短的客人。正因为如此,它让入住登记的第一张图片中的度假酒店相形见绌。

看一看 Kaggle 笔记本以获得关于执行的数据清理和转换的更多细节,以获得允许这些可视化的数据集。

为了进一步了解数据分析世界,这篇文章关注的不仅仅是作为一名优秀的数据分析师你应该知道的标准工具。了解一些较少讨论的特征,这些特征将对你有长期的帮助。一如既往,继续学习!

在熊猫数据帧中重排行

原文:https://towardsdatascience.com/shuffling-rows-in-pandas-dataframes-eda052275635?source=collection_archive---------15-----------------------

讨论如何重排熊猫数据帧的行

瑞安·昆塔尔在 Unsplash 上拍摄的照片

介绍

数据混洗是一项常见任务,通常在模型训练之前执行,以便创建更具代表性的训练和测试集。例如,假设您的原始数据集是基于特定列排序的。

如果分割数据,那么得到的集合将不会代表数据集的真实分布。因此,我们必须调整原始数据集,以最小化差异,并确保模型能够很好地推广到新的、看不见的数据点。

在今天的简短指南中,我们将讨论如何以各种方式重排熊猫数据帧的行。具体来说,我们将探索如何使用

  • pandas中的sample()方法
  • scikit-learn中的shuffle()方法
  • numpy中的random.permutation()方法

首先,让我们创建一个示例 pandas DataFrame,我们将在本文中引用它来演示如何以多种不同的方式重排行。

import pandas as pd df = pd.DataFrame({
    'colA': [10, 20, 30, 40, 50, 60],
    'colB': ['a', 'b', 'c', 'd', 'e', 'f'],
    'colC': [True, False, False, True, False, True],
    'colD': [0.5, 1.2, 2.4, 3.3, 5.5, 8.9],
})print(df)
 *colA colB   colC  colD
0    10    a   True   0.5
1    20    b  False   1.2
2    30    c  False   2.4
3    40    d   True   3.3
4    50    e  False   5.5
5    60    f   True   8.9*

在熊猫中使用 sample()方法

对 pandas 数据帧进行混排的第一个选择是[panads.DataFrame.sample](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sample.html)方法,它返回一个随机的项目样本。在这种方法中,您可以指定想要采样的记录的确切数量或部分。因为我们想要打乱整个数据帧,所以我们将使用frac=1来返回所有记录。

**df = df.sample(frac=1)**print(df)
 *colA colB   colC  colD
4    50    e  False   5.5
0    10    a   True   0.5
2    30    c  False   2.4
1    20    b  False   1.2
5    60    f   True   8.9
3    40    d   True   3.3*

如果你想让洗牌在重现,那么也要确保为** **random_state** 参数指定一个有效值。此外,有时您可能希望重置返回的数据帧的索引。在这种情况下,以下方法应该可以解决问题:**

df = df.sample(frac=1).reset_index(drop=True)

使用 scikit-learn 的 shuffle()方法

另一个可以用来混洗数据帧的函数是如下所示的[sklearn.utils.shuffle()](https://scikit-learn.org/stable/modules/generated/sklearn.utils.shuffle.html):

**from sklearn.utils import shuffle****df = shuffle(df)**print(df)
 *colA colB   colC  colD
4    50    e  False   5.5
5    60    f   True   8.9
1    20    b  False   1.2
2    30    c  False   2.4
0    10    a   True   0.5
3    40    d   True   3.3*

同样,如果您希望结果是可重复的,请确保配置random_state参数。

在 numpy 中使用 random.permutations()

我们的另一个选择是随机排列序列的[numpy.random.permutation](https://numpy.org/doc/stable/reference/random/generated/numpy.random.permutation.html)方法。

import numpy as np**df = df.iloc[np.random.permutation(len(df))]**print(df)
 *colA colB   colC  colD
3    40    d   True   3.3
0    10    a   True   0.5
5    60    f   True   8.9
1    20    b  False   1.2
2    30    c  False   2.4
4    50    e  False   5.5*

同样,如果你希望结果是可重复的,你必须设置numpy的随机种子。举个例子,

np.random.seed(100)

最后的想法

在今天的简短指南中,我们讨论了数据洗牌在机器学习模型环境中的重要性。此外,我们还探索了如何使用sample()方法、sklearn中的shuffle()方法和numpy中的random.permutations()方法来洗牌。

如果你想了解更多关于如何将数据分成训练集、测试集和验证集的信息,那么请务必阅读下面的文章。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。

你可能也会喜欢

https://medium.com/geekculture/use-performance-visualization-to-monitor-your-python-code-f6470592a1cb

暹罗网络介绍和实施

原文:https://towardsdatascience.com/siamese-networks-introduction-and-implementation-2140e3443dee?source=collection_archive---------1-----------------------

了解如何在每个类别只有少量样本且类别分布不均衡的情况下,在分类任务中获得良好的准确性

来源

简介

现在有几个深度学习模型,如 BERT、GANs 和 U-Nets,正在实现图像识别、图像分割和语言建模等任务的最先进性能。几乎没有一天机器学习没有新的创新。谷歌、微软和亚马逊等科技巨头正在开发复杂的深度学习架构,实现类似人类的性能。但是这些模型的一个问题是它们需要大量的标记数据。有时,对于特定的任务,很多数据是不可用的。更少的数据意味着深度学习模型将无法正确地对不同的类进行建模,并且性能很差。这就是暹罗网络前来救援的地方。它有助于在每类样本较少且类分布不*衡的情况下建立具有良好准确性的模型。

什么是暹罗网络?

暹罗网络基本结构

连体网络是一类包含一个或多个相同网络的神经网络。我们向这些网络提供一对输入。每个网络计算一个输入的要素。然后,使用特征的差或点积来计算特征的相似性。对于相同的类输入对,目标输出是 1,而对于不同的类输入对,输出是 0。

记住,两个网络有相同的参数和权重。如果不是,那他们就不是暹罗人。

通过这样做,我们已经将分类问题转化为相似性问题。我们正在训练网络,使同一类的样本之间的距离最小,并增加类间距离。有多种相似性函数,通过这些函数可以训练暹罗网络,如对比损失、三联损失和圆损失。

  1. 对比损失:在对比损失中,拍摄成对的图像。对于相同的类对,它们之间的距离较小。对于不同的对,距离更多。尽管二进制交叉熵似乎是我们问题的完美损失函数,对比损失在区分图像对方面做得更好。对比损失,l=y * d^2+(1-y) max(margin—d,0)^2*

D 是图像特征之间的距离。边距是一个帮助我们区分不同类别的参数。

对比损失:上半部分显示同类图像,下半部分显示不同图像

2.三重丢失:三重丢失是 Google 在 2015 年推出的人脸识别。这里,模型有三个输入——锚、积极和消极。锚点是一个参考输入。实际输入与锚输入属于同一类别。负输入属于锚类之外的随机类。

三重损耗实现

三联体损失函数背后的思想是,我们最小化锚和阳性样本之间的距离,同时也最大化锚和阴性样本之间的距离。

我们来看看三重态损耗的数学公式。

这里 d 表示距离度量。锚点和正锚点之间的距离应小于负锚点和正锚点之间的距离。所以, d(a,p) — d(a,n) < 0 。为了保持正,我们可以这样修改:LOSSL =max(d(a,n) — d(a,p),0)

为了进一步增加正负之间的分离,引入了参数'裕量'。

现在, L = max(d(a,n) — d(a,p) + margin,0)

利弊

在开始实现之前,让我们先来谈谈这种方法的一些优点和缺点。

优点:

1.需要更少的数据样本。

2.可以处理高度不*衡的数据。

缺点:

1.因为有这么多对类,所以训练数据量很大。

2.不能一概而论。为一项任务训练的模型不能用于另一项任务。

3.对输入中的一些变化敏感。

实施

问题陈述:这是一个非常简单的演示概念的问题。我们有一个不同形状(三角形,圆形和矩形)的数据库,有 3 种不同的颜色(红色,绿色和蓝色)。这些形状大小不同,位置不同,旋转角度也不同。

我们希望通过学习图像的颜色编码,根据图像的颜色对图像进行分类。每种颜色我们有 20 个样品。这里有一个包含这个数据集的 GitHub 存储库。

https://github.com/AdityaDutt/MultiColor-Shapes-Database

还有几个其他数据集也可以尝试,如著名的 Omniglot 数据集,MNIST 等。

第一部分 :准备数据

阅读图像,并产生积极和消极的一对。有两个 NumPy 数组包含一对大小为 Nx28x28x3 的图像。如果颜色相同,目标标签为 1,如果颜色不同,目标标签为 0。例如:

输入 : 红色_ 三角形, 红色_ 正方形(同色物体)

输出 : 1

输入 : 红色_ 三角形, 蓝色_ 三角形(不同颜色的物体)

输出 : 0

第二部分: 创建模型

从第2132行,我们已经为一个单独的图像创建了模型。首先,我们有输入层。然后, Conv2DMaxPool 层。之后,我们将其压*,并添加一个密集层。我们在那之后已经标准化了密集层,因为这些将作为我们图像的特征。特征的长度为 16。稍后,当我们连接这两个模型时,我们采用这些特性的点积。由于我们已经对这些特征进行了规范化,它们将介于 0 和 1 之间。因此,我们可以很容易地将它们与我们的目标标签进行比较。

在第 3637 行中,我们创建了同一个模型的两个实例,并将输入传递给它们。在第 45 行,我们获取两个模型的输出,并对它们应用点积。点积将显示两幅图像的相似性。

这是一个简单的例子,所以我们得到了高达 99%的准确率。对于复杂的图像和任务来说,它并不是那么好。但是,本文的目标是使用一个简单的例子来演示暹罗网络。

以下是暹罗网络中单个编码器的示意图:

编码器型号

这是完整的暹罗模型的样子:

连体模型

第 3 部分 : 测试模型

加载模型并在看不见的图像上测试它。我们可以做以下事情来检查类之间的准确性和分离性-

a)首先,我们可以使用单个编码器模型对图像进行编码,以获得要绘制的特征。我们可以画出这些特征的散点图,看看它们的分离程度如何。(特征长度为 16)

b)其次,我们可以用连体网络输出(1 到 0 之间)做一个混淆矩阵。

两者如下所示。

这是前三个特征的三维可视化

16 个特征向量中前 3 个特征的散点图

张量板特征的 PCA 可视化

TensorBoard 球化后特征的 PCA 可视化

测试图像的混淆矩阵。所有图像都是三角形,但颜色不同。但是,对于相同颜色的图像,相似性很高。

以下是完整资源库的链接:

https://github.com/AdityaDutt/Siamese-Networks-Tutorial

结论

  1. 当可用数据较少且类别不*衡时,此模型非常有用。
  2. 它具有像图像分类、对象检测、文本分类、声音分类,
  3. 连体网络也可用于对特定要素进行编码。可以创建类似的模型来对不同的形状进行分类。
  4. 一次性学习也使用连体网络。它通过使用每个类中的一个样本进一步扩展了这一思想。零炮学习也差不多。它在完全看不到任何输入的情况下训练模型。这是一个相当新的话题,已经引起了很多关注。

未来项目构想

在暹罗模型被训练之后,最终的层可以被丢弃,并且特征可以与变分自动编码器一起使用来重构输入。这样,您还可以通过使用其他图像的一些特征来重建原始图像,从而更改图像的样式和其他特征。例如,转换图像的形状或颜色。

接下来,我将写使用暹罗网络和使用 VAE 与暹罗网络的语音分类。

感谢阅读!希望对理解底层逻辑有帮助。

如果你喜欢这篇文章,请推荐并分享。

参考

  1. https://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf
  2. https://en.wikipedia.org/wiki/Siamese_neural_network

暹罗 NN 食谱与 Keras

原文:https://towardsdatascience.com/siamese-nn-recipes-with-keras-72f6a26deb64?source=collection_archive---------10-----------------------

用于语义相似性任务的具有 Keras 和 BERT 的实用暹罗神经网络配方

我已经享受了一段时间在我的工作不同的 NLU 任务的暹罗网络。在本文中,我将与 Keras 分享一些快速的方法,将 Glove vectors 或 BERT 作为文本矢量器。我们将关注语义相似度计算。语义相似性基本上是确定一组文本是否相关的任务。语义相似度通常是在一对文本段之间计算的。在这篇文章中,我将举例说明如何比较两个文本。

连体网络是具有两个或更多输入的神经网络(通常输入的数量是两个,否则必须定义三向距离函数)。我们对输入文本进行编码,然后将编码后的向量提供给距离层。最后,我们在距离层上运行一个分类层。距离可以是余弦距离、L1 距离、指数负曼哈顿距离和任何其他距离函数。这是一个作为黑盒的连体网络:

更高层次的暹罗 NN。如果 2 个输入和 NN 个输出在语义上相关,我们就给它们

可以通过 LSTM、通用编码器或 BERT 对输入文本进行编码。根据带有单词嵌入的文本编码,该体系结构如下图所示:

详细的暹罗建筑。我们首先用 LSTM/伯特对输入句子进行编码,然后将编码后的向量对送入距离层。

这是带有 LSTM 和预训练嵌入层的 Keras 配方:

from keras import backend as Kfirst_sent_in = Input(shape=(MAX_LEN,))
second_sent_in = Input(shape=(MAX_LEN,))embedding_layer =  Embedding(input_dim=n_words+1, output_dim=embed_size, embeddings_initializer=Constant(embedding_matrix), input_length=MAX_LEN, trainable=True, mask_zero=True)first_sent_embedding = embedding_layer(first_sent_in)
second_sent_embedding = embedding_layer(second_sent_in)lstm =  Bidirectional(LSTM(units=256, return_sequences=False))first_sent_encoded = lstm(first_sent_embedding)
second_sent_encoded = lstm(second_sent_embedding)l1_norm = lambda x: 1 - K.abs(x[0] - x[1])merged = Lambda(function=l1_norm, output_shape=lambda x: x[0], name='L1_distance')([first_sent_encoded, second_sent_encoded])predictions = Dense(1, activation='sigmoid', name='classification_layer')(merged)model = Model([first_sent_in, second_sent_in], predictions)
model.compile(loss = 'binary_crossentropy', optimizer = "adam", metrics=["accuracy"])
print(model.summary())model.fit([fsents, ssents], labels, validation_split=0.1, epochs = 20,shuffle=True, batch_size = 256)

模型摘要应该是这样的:

Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 200)]        0                                            
__________________________________________________________________________________________________
input_2 (InputLayer)            [(None, 200)]        0                                            
__________________________________________________________________________________________________
embedding (Embedding)           (None, 200, 100)     1633800     input_1[0][0]                    
                                                                 input_2[0][0]                    
__________________________________________________________________________________________________
bidirectional (Bidirectional)   (None, 512)          731136      embedding[0][0]                  
                                                                 embedding[1][0]                  
__________________________________________________________________________________________________
L1_distance (Lambda)            (None, 512)          0           bidirectional[0][0]              
                                                                 bidirectional[1][0]              
__________________________________________________________________________________________________
classification_layer (Dense)    (None, 1)            1026        L1_distance[0][0]                
==================================================================================================
Total params: 2,365,962
Trainable params: 2,365,962
Non-trainable params: 0
______________________________

两个输入层输入要比较的两个文本。然后,我们将输入单词馈送到嵌入层,以获得每个输入单词的单词嵌入。之后,我们分别将第一句话的嵌入向量馈送到 LSTM 层,将第二句话的嵌入向量馈送到 LSTM 层,并获得第一文本和第二文本的密集表示(用变量 first_sent_encodedsecond_sent_encoded 表示)。现在是棘手的部分,合并层。合并层输入第一个文本和第二个文本的密集表示,并计算它们之间的距离。如果你查看模型摘要的第四层,你会看到L1 _ 距离(λ)(这一层在技术上是一个 Keras 层),接受两个输入,它们都是 LSTM 层的输出。结果是一个 512 维的向量,我们将这个向量提供给分类器。结果是一个一维向量,它是 0 或 1,因为我在做相似或不相似的二元分类。在分类层,我用 sigmoid 压缩了 512 维距离向量(因为我很喜欢这个激活函数:),我还用 binary_crossentory 编译了模型,因为这也是一个二进制分类任务。

在这个配方中,使用了L1-距离来计算编码向量之间的距离。您可以使用余弦距离或任何其他距离。我特别喜欢 l1 距离,因为它的不像函数那么*滑。这同样适用于 sigmoid 函数,它为提供了语言神经网络所需的非线性

伯特的食谱有点不同。我们去掉了嵌入+ LSTM 层,取而代之的是伯特层(因为伯特向量包含了足够多的顺序性!):

fsent_inputs = Input(shape=(MAX_L,), dtype="int32")                       fsent_encoded = bert_model(fsent_inputs)                       fsent_encoded = fsent_encoded[1] ssent_inputs = Input(shape=(150,), dtype="int32")                       ssent_encoded = bert_model(ssent_inputs)                       ssent_encoded = ssent_encoded[1] merged =concatenate([fsent_encoded, ssent_encoded])                                               predictions = Dense(1, activation='sigmoid', name='classification_layer')(merged) model = Model([fsent_inputs, ssent_inputs], predictions)                                               adam = keras.optimizers.Adam(learning_rate=2e-6,epsilon=1e-08) model.compile(loss="binary_crossentropy", metrics=["accuracy"], optimizer="adam")

这里,我们再次分别向 BERT 层提供一对文本输入,并获得它们的编码 fsent-encodedssent_encoded 。我们使用【CLS】标记的嵌入,它捕获句子的*均表示。(BERT 层有 2 个输出,第一个是 CLS 令牌的向量,第二个是 (MAX_LEN,768) 的向量。第二个输出为输入句子的每个标记提供了一个向量。我们通过调用fsent _ encoded = fsent _ encoded[1]ssent _ encoded = ssent _ encoded[1]来使用第一个输入。优化器也是 Adam,但学习率略有不同(我们降低 lr 以防止 BERT 表现过激和过度拟合。如果我们不加以阻止,伯特很快就会过度适应)。损失也是二元交叉熵,因为我们在做二元分类任务。基本上我用 BERT 层替换了嵌入层+ LSTM,其余的架构是相同的。

亲爱的读者,您已经阅读完了这篇实用文章。我的目的是提供一个快速的工作解决方案,以及解释如何暹罗网络的工作。如果你愿意,你可以把辍学层放在几个地方,自己做实验。玩暹罗网络很令人兴奋,就我个人而言,它们可能是我最喜欢的架构。我希望你喜欢暹罗 NN,并在你的工作中使用。在新架构会议之前,感谢您的关注,敬请关注!

《权力的游戏》中的兄弟竞争与共整合

原文:https://towardsdatascience.com/sibling-rivalry-and-cointegration-in-the-game-of-thrones-8642466fa2f2?source=collection_archive---------15-----------------------

实践教程

提利昂和瑟曦·兰尼斯特之间的因果关系。在 Python 中。没有龙。

时间序列协整、格兰杰因果关系、*稳性(ADF 和 KPSS)和白噪声残差的检验。在向量自回归的快速帮助下。

流程步骤:

0.《权力的游戏》和格兰杰因果关系——这是关于什么的?

一个普遍公认的事实是,一个拥有有点书呆子气的头脑的数据科学家肯定想要一个幻想世界,供她或他在下班后沉浸其中。

十年来,《权力的游戏》( GoT)一直是我们许多人消磨时间的选择。数据科学爱好者和 GoT 爱好者之间肯定有大量的重叠。然而,与 GoT 相关的定量分析的缺乏表明,这种差距需要弥补。

然而,如果你不是一个 GoT 爱好者,并想知道这是怎么回事,这里的纲要:

《权力的游戏》

GoT 是一个以维斯特洛和埃索斯大陆为背景的中世纪奇幻世界;乔治·R·R·马丁在 20 世纪 90 年代开始写的系列丛书;自 2010 年以来,它还作为 HBO 系列播出。

GoT 正在暂存:

  • 龙(活着的、死了的或不确定的)和它们的骑手;
  • 大摇大摆卖剑;
  • 不死的白行者(与 AMC 系列无关),他们不受钢刃的伤害,但被黑曜石触碰时会碎成冰柱;
  • 喝醉的国王,诡计多端的朝臣,名字如小指头;
  • 头发花白的学院派学士们,如果他们不必花那么多时间打扫他们雇来作为加强版信鸽的乌鸦的笼子,他们无疑会渴望尝试数据科学;
  • 狡猾的太监间谍头子和身经百战的太监士兵;
  • 乱伦倾向和其他家族并发症;
  • 一个不死怪物骑士,在被驱逐的弗兰肯斯坦学士的帮助下,将他残暴的个性带到了不太真实的来世;
  • 一个红头发的火女祭司,不知什么原因,每当她念咒语时,她必须在屏幕上露出胸部;
  • 这是一场皇家红色婚宴,让任何其他醉酒的家庭庆典和争吵都相形见绌。

你知道要点了。

提利昂和瑟曦是这个重塑的黑暗时代的主角。

  • 提利昂是双胞胎瑟曦和杰米的弟弟,这对双胞胎从十几岁开始就陷入乱伦关系。天生矮人的提利昂,用他非凡的智慧反击瑟曦煽动的嘲笑和羞辱。
  • 瑟曦责怪提利昂,他们的母亲在生提利昂时死在产床上。瑟曦在帮助她永远泡在水里的丈夫劳勃·拜拉席恩国王进入一个早期皇家墓穴后成为摄政王。对于这对皇室夫妇,肯定有一些格兰杰因果关系需要分析,但我们没有足够的数据说明罗伯特国王在斩首开始前迅速离开舞台左侧。瑟曦控制欲强,权力欲强,报复心强。她认为自己在政治上很精明,但却追求短视的野心。龙或不死行尸只是她寻求力量的麻烦。她的弟弟提利昂成了她仇恨的磁石。
  • 《权力的游戏:screenrant.com》中瑟曦·兰尼斯特做过的 10 件最无耻的事

好了,你已经有了一分钟的概要。

现在,我们将把这个戏剧性的织锦的一小部分输入到一些选定的 Python 算法中,看看我们能从中提取出哪些确凿的事实。

格兰杰因果关系

g-因果关系是一种概率性的(相对于确定性的)方法来定义和研究因果关系。

如果 X 的过去值包含的信息有助于预测 Y,而不仅仅是 Y 的过去值中包含的信息,则称变量 X 是目标变量 Y 的 Granger 原因

GC 检验的无效假设是 X 的滞后值而非有助于解释目标变量 Y 的变化。X 中没有信号,从中可以推导出 Y 在未来期间的预测。如果我们拒绝低 p 值的零假设,我们可以得出结论,X 可以贡献一些预测值:X G ranger-causes Y 通过帮助预测 Y。

因此,G-因果关系并不能证明一个真正的因果链。

在一个滞后范围内,格兰杰因果关系可能不是单向的(X 格兰杰原因 Y),而是双向的。

1。预处理和数据争论

我们下载了从 2011 年到 2020 年的关键字“提利昂”和“瑟曦”的全球谷歌趋势时间序列。

https://trends.google.com/trends/explore?date=today 5-y 问=提利昂,瑟曦

请注意,Google Trends 提供了长达 5 年的每周关键词数据。超过 5 年后,频率变为每月。要获得 2011–2020 年的每周数据,我们需要从 5 年前开始重新运行自定义日期范围的搜索。csv 文件,然后将时间序列合并到一个文件中。

谷歌关键词趋势表达了当姐妹俩在屏幕上实施他们的阴谋时,公众对瑟曦和提利昂生活的兴趣有增无减。我们将这种趋势作为衡量其名气或恶名的标准,并询问一个兄弟姐妹受欢迎程度的起伏是否是格兰杰原因——导致另一个兄弟姐妹在观众心目中出现的高峰和低谷。

我们创建一个 Jupyter 笔记本并导入所需的包。然后我们加载 Google 趋势源数据文件‘got _ Cersei _ Tyrion . CSV’

将字符串对象转换为数字和日期后,我们可以绘制提利昂和瑟曦的数据。

2011 年至 2020 年间,关于提利昂和瑟曦的新闻集中在特定的几周和几个月:每当 HBO 播出新一季的。该时间表并不完全表现出固定的周期。

我们必须假设提利昂和瑟曦的手足之争包含了*静的时期,在几个月的时间里不断积累紧张,然后在极端戏剧性的时刻爆发,通过餐桌上的下流言论、斩首或解决家庭内部纠纷的类似方法来释放紧张。

提利昂和瑟曦的关联有多强?

就其本身而言,提利昂和瑟曦的高度关联并不能证实格兰杰因果关系。低相关性也不会否定协整或格兰杰因果关系。

  • 相关性不一定随时间保持稳定,例如,如果序列遵循具有不同上升或下降速率的趋势曲线。
  • 具有完全对齐的峰的两个系列可以表现出 1.0 的相关性。但是,如果其中一个序列在时间轴上经历了小的移动,使得其峰值现在与另一个序列的谷值对齐,则该序列将相互抵消,并且它们的相关性可能下降到 0。

2。测试前诊断

2.1 协整:格兰杰因果关系的首次暗示

如果两个数列中的每一个都是非*稳的,那么它们就是协整的,但是存在一个*稳的线性组合。

这两个序列不一定完全同步(每个周期中的峰值和谷值不精确匹配),但它们之间的*均距离随着时间的推移保持相对恒定:序列将返回到*衡状态。如果我们着眼于长期关系,协整取代了相关性。

如果两个序列是协整的,那么它们之间必然存在格兰杰因果关系。

2.2 *稳性检验和差分

格兰杰因果关系要求时间序列是*稳的。

扩展的迪基-富勒(ADF)和科维亚特科夫斯基-菲利普斯-施密特-申(KPSS)检验是研究时间序列*稳性的常用选择。但是,它们可能会返回相互冲突的结果。我们将不得不反复核对它们,以决定是否需要对时间序列进行区分。

可能的冲突:

  • 如果 ADF 确定了一个单位根,但是 KPSS 发现这个序列在一个确定的趋势附*是*稳的,那么这个序列只是趋势*稳的。区别它(或者尝试通过其他转换去趋势化它)。
  • 如果 ADF 没有找到单位根,但 KPSS 通过了非*稳性的判断,则该序列只是差分*稳的。区别它。

我们将运行 ADF 和 KPSS 测试,审查它们的结果,并确定适当的差异顺序。

定义测试后,我们检查 Tyrion 的稳定性。

综合测试的结果是推荐区分 Tyrion 的系列——之后我们将测试差异数据的*稳性。

经过一次一阶差分后,提利昂是一个*稳过程。

接下来,我们区别瑟曦。

经过一阶差分后,瑟曦是一个*稳过程。

让我们总结一下提利昂和瑟曦的系列,区分前后:

3。合理数量的滞后

如果我们为格兰杰因果关系检验选择了太多的滞后,我们将倾向于接受假阴性,并在没有因果关系的地方发现明显的因果关系。我们将通过执行大量测试来实施 p-hacking 或数据挖掘,直到我们在其中一个外围滞后处找到因果关系。

另一方面,如果我们选择的滞后时间太少,测试结果可能会因为截止期以外的自相关而出现偏差。

因此,我们将对长达 52 周的滞后运行向量自回归模型(VAR ),并选择导致最低 Akaike 信息标准的滞后。

我们将遵循 Dave Giles 的指导:在风险值模型中,我们将在差异之前使用源数据https://Dave giles . blogspot . com/2011/04/testing-for-Granger-causality . html

3.1 差异前的风险值模型

让我们通过使用德班-沃森检验来确认,残差是否表明 VAR 模型在时间序列中没有发现显著的信号。

3.2 差异后的风险值模型

我们再次运行风险值模型,这一次是对差分序列,并将差分顺序添加到 AIC 最小化之前风险值模型返回的滞后。

让我们再次使用德班-沃森测试来确认残差是否可以被解释为白噪声。

3.3 确认协整

我们重复进行协整检验,这次使用的是 VAR 模型推荐的合理的滞后数。

如果时间序列“是协整的,那么它们之间一定存在格兰杰因果关系——要么是单向的,要么是双向的。”(戴夫·贾尔斯,2011 年)

如果不存在协整,该序列仍可能呈现格兰杰因果关系。

https://Dave giles . blogspot . com/2011/04/testing-for-Granger-causality . html

4。格兰杰因果检验

4.1 瑟曦作为致病因子

我们从数组的第一列中的提利昂开始;瑟曦,在第二列。因此,瑟曦将被视为致病因子。我们将测试瑟曦的恶名是否有助于预测几周后提利昂的受欢迎程度。

我们使用 VAR1 模型推荐的 AIC 最小化滞后的数量。

  • 无效假设:瑟曦的恶名不会而不是成为提利昂受欢迎的原因。
  • 替代假设:瑟曦的突出确实是提利昂的格兰杰原因。
  • 输出:该方法在选定的滞后期应用了 4 个可选择的检验:F、卡方、似然比和参数-F。
  • f 检验:仅适用于序列协整的情况。

我们将关注 f 检验。

我们观察到瑟曦的 p 值仍然远低于 0.05,并得出结论,她确实是提利昂共整合突出的格兰杰原因。

让我们回头来研究格兰杰因果关系是否是双向的。

4.2 作为致病因子的提利昂

他的高 p 值表明——除了滞后三周的短暂时间窗口——提利昂并不是瑟曦声名狼藉的原因。瑟曦忠于她邪恶女王的角色,必须被视为她自己的毁灭代理人,而不需要她弟弟星光大道上任何之前的起伏来推一把。

4.3 出轨:因果关系的扩展滞后曲线

我们现在做了一些统计学家不会赞同的事情。我们将在比我们的 VAR 模型推荐的 Akaike 信息标准更多的滞后上运行因果关系测试。

如果选择了太多的滞后,我们可能会被虚假的回归结果引入歧途,并在没有因果关系的地方接受明显的因果关系。然而,最小 AIC 并不是一个硬性的规则,而只是一个寻找合理的滞后次数的启发式规则。

减轻处罚的情节:我们已经观察到瑟曦在很少的滞后时间里有可靠的格兰杰因果关系。我们不想在后期寻找虚假的因果关系,而是相反:瑟曦对提利昂的影响是否会在后期开始减弱?

在提利昂的案例中,我们只看到了轻微的因果关系,如果有的话。我们将观察这种模式是否会在晚些时候改变,但我们不会接受提利昂的格兰杰因果关系在 15 或 18 周的时间滞后后突然发生。在一季的最后一集播出后,观众不再收到瑟曦和提利昂出轨的每周更新,这种褪色的模式更有可能。因此,考虑到原始数据的性质,格兰杰因果关系在 15 或 20 周后出现将无法通过气味测试。

我们选择了一个“难以置信”的最大数字:长达 20 周的滞后。

越来越滞后的高 p 值表明提利昂只是间歇性地让瑟曦的名声或恶名指数短暂波动。

相比之下,瑟曦的低 p 值持续存在。她似乎是格兰杰的原因,因为她给她的弟弟带来了太多的悲伤,这使得提利昂受到的公众关注有了明显的变化。

Python 中字符串的并排比较

原文:https://towardsdatascience.com/side-by-side-comparison-of-strings-in-python-b9491ac858?source=collection_archive---------5-----------------------

实施一个工具,用 Python 并排比较文本,以便更好地了解差异

瓦妮莎·贾科尼的照片(图片来源: Unsplash

目前我正在为 Python 中的文本制作一个隐私过滤器。在开发过程中,我遇到了一个经常遇到的问题;如何快速比较两个字符串并轻松评估差异?这一次,是时候解决这个问题了。

difflib 库

一些互联网研究很快揭示了 difflib 模块的存在。这个默认的模块包含几个比较序列的助手,比如数组和字符串。所有比较序列的算法都可以用几行代码实现。有那么一小会儿,实现我自己的算法的想法掠过我的脑海,但很快就消失了。

difflib 模块的基础是类 SequenceMatcher 。这个类实现了比较序列的算法。它首先在两个输入序列中找到最大的公共序列,并在其他部分递归地执行这个任务,直到没有序列剩下。由于它的递归性质,执行时间可以变成二次的,这取决于序列中的差异量。对于我们的目标来说,这种表现是可以接受的。它不会被用来比较书籍的文本,但只有几行一次。

查找匹配序列

为了匹配序列,我们首先必须创建一个 SequenceMatcher 类的实例。构造器将两个序列匹配作为参数 ab 。不使用垃圾邮件检测的参数。当将字符串作为参数传递时,字符串被视为一系列字符。匹配器将寻找匹配的字符序列。

SequenceMatcher 类有几种返回匹配结果的方法,比如找到最长的匹配,返回将 a 转换为 b 的操作,以及返回所有找到的匹配。我们将使用后者:

get_matching_blocks()方法返回所有匹配项的可迭代列表,从序列的开始按出现的顺序排序。每个匹配由序列中匹配的位置 a ,序列中匹配的位置 b 和匹配的长度组成。在示例中,找到了三个匹配;“是”,“温暖。是”,“呃。”。第四个返回的匹配是序列的结尾。

所以我们在字符串中找到了所有匹配的序列。但是为了比较文本,最后一个匹配“呃”只匹配单词的一部分。我喜欢只匹配整个单词。因为匹配器接受序列(字符串是 Python 中的字符序列),所以我们应该向匹配器添加单词。因此,让我们看看如果在执行匹配器之前对字符串进行标记会发生什么:

tokenize 方法是一个非常简单、粗糙的实现,它通过在空格(“”)处分割字符串来实现。结果是有希望的,只有序列“它是”和“温暖”。“是被退回来了。不再找到部分匹配的单词。测试几行文本很快就指出了只在空格处进行拆分的有限的标记化。它在换行符和制表符处失败,所以为了加快游戏进度, split() 被替换为一个正则表达式,该表达式在所有空格处拆分文本:

这与前面的实现结果相同,但是对于其他白色空间比空间本身更健壮。

*衡琴弦

匹配器告诉我们哪些序列匹配,哪些不匹配。有了这个信息,就有可能使两个序列相等,把第一个序列的缺失部分加到第二个序列上,反之亦然。

看上面的例子,我们看到第一个匹配序列从位置 0 开始,长度为 2。第二个匹配序列从序列 a 的位置 2 开始,从序列 b 的位置 3 开始。因此序列 b 包含不在序列 a 中的部分。我们需要向序列 a 中添加一个元素,其长度与序列 b 中的元素长度相同。

为了确定匹配序列中是否缺少元素,我们查看匹配的起始位置,加上匹配序列的长度,并确定下一个序列是否从两者之和开始。在下面的示例中,两个序列的第二个匹配从位置 0 + 3 开始,第一个序列的第二个匹配从位置 4 开始,第二个序列的第二个匹配从位置 3 开始。由于 0 + 3 等于 3,匹配序列在第二个序列中相互“接触”,第一个序列在两个匹配序列之间包含一个附加元素。这意味着,第二个序列中必须增加一个附加元素。

作者图片

有三种可能性:第一个序列包含一个或多个附加元素,第二个字符串包含附加元素,或者两个字符串都包含附加元素。在后一种情况下,序列不匹配,例如,在我们的第一个例子中,单词“summer”和“winter”。

我们将通过在其他序列具有不匹配元素的地方添加附加元素来均衡该序列。这些附加元素将被赋予与不匹配元素相同的长度,并将由下划线组成:

该方法遍历找到的匹配项(第 15 行),并检查每个匹配项是否与前一个匹配项相邻。如果不是这种情况,元素被添加到另一个序列中以创建一个匹配(第 16–23 行)。添加缺失的元素后,用匹配的序列扩展两个序列。在返回值之前,它们是未标记的。

不在第一个字符串中的单词“not”作为下划线添加到第一个字符串中。不同的词“夏天”和“冬天”都添加到另一个字符串中。看到上面的结果已经很好地概括了两个字符串之间的区别。

视觉化差异

所以现在我们有了均衡的字符串,我们需要一个方便的方式来可视化的比较。对于单句,将它们一个接一个地打印出来是一个很好的解决方案。对于较长的文本,并排比较更方便。

为了进行并排比较,我们需要将字符串分成有限的块,例如 40 个字符。我们希望在单词中间断开,因此添加了一个可接受的窗口,例如 10 个字符,这意味着我们将开始搜索 40 个字符后的空格(第 5 行),并最多返回 10 个字符,以找到小于并最接* 40 个字符的第一个空格(第 7–8 行):

该函数返回一个字符串列表,长度不超过 40。因为均衡字符串使它们长度相等,所以我们可以使用这种方法将两个字符串都断开,并且这些字符串将总是在同一行包含相同的单词。它们很容易比较。我们可以打印包含下划线的字符串,但删除了下划线。通过在 breaking then text up 之后删除下划线,我们可以保证两个文本中的相同单词出现在同一行中:

comparison() 函数将两个要比较的文本作为参数,后跟可选的并排显示宽度、从该宽度中寻找空间的窗口以及是否并排或上下显示文本。

完整代码:

使用所有可能的可视化运行示例:

希望这种并排比较法对你的帮助和对我的帮助一样大。通过这种比较,找到文本中的差异要容易得多,因为左右相同的文本出现在同一行确实很有帮助。对于我的隐私过滤器来说,当相同的文本部分之间显示多行时,长度差异变得相当大,使得比较变得很尴尬。

我希望你喜欢这篇文章。要获得灵感,请查看我的其他文章:

免责声明:本文包含的观点和看法仅归作者所有。

Python 中的并行 OCR 与 Google Vision 和 Tesseract

原文:https://towardsdatascience.com/side-by-side-ocr-in-python-with-google-vision-and-tesseract-66021d5702a0?source=collection_archive---------9-----------------------

关于如何使用一些流行的引擎在 Python 中执行 OCR 以及它们的特点和技巧的简短说明

作者图片

现代光学字符识别系统

OCR(光学字符识别)系统将包含有价值信息(假定为文本格式)的图像转换为机器可读数据。在大多数情况下,通过一些可用的方法执行 OCR 是从纸质或基于扫描的 PDF 文档中提取数据的第一步。

然而,在网上进行短暂的搜索后,你可以找到大量各种开源和商业工具的链接,谷歌视觉宇宙魔方作为 OCR 引擎已经比他们的竞争对手领先了很长时间,尤其是在最*几年。

Tesseract 是一个离线和开源的文本识别引擎,具有全功能的 API,可以通过 Python 的一些包装器模块轻松实现到任何业务项目中, pytesseract 就是一个例子。

相反,Google Vision 并不在本地运行,而是在远程 Google 的服务器上运行。要开始在您的项目中使用 Google Vision API,您必须进行一些设置步骤,包括根据官方指南提供有效凭证。此外,如谷歌的定价政策所述,你可以为超出免费限制的文本识别请求付费。

尽管这两种工具在用法和选项设置上存在根本差异,但从谷歌趋势来看,它们对网络用户的兴趣几乎是一样的:

接下来,我们将尝试使用两个引擎在 Python 中执行 OCR,顺便比较它们在真实图像上的性能(由作者重新创建或扫描以模仿不同初始质量的文档)。

OCR 比较方法综述

为了获得尽可能可比的结果,我们将执行“反转”方法。这意味着,我们将首先对文本图像执行 OCR,而不进行任何预处理,尝试从同一图像中反复应用不同的降级过滤器来机器读取字符。在每一步中,我们将评估 OCR 性能,将正确读取的字符数与两种工具在初始步骤中成功读取的字符数进行比较。

但是作为一个起点,我们将尝试在使用 Google Vision 和 Tesseract 在 Python 中执行 OCR 时,您应该注意的每个工具的一些奇怪之处。

宇宙魔方:连接你可能期望分裂的东西

当您将 Tesseract 的 image_to_data 方法应用于足够高质量的图像(即足够硬和清晰)时,事情可能看起来很自然。但是对于模糊的图像,这个工具试图不正确地确定文本边界框。这就是实际情况。

更具体地说(注意一些边界框是如何相互重叠的):

为了检索这种奇怪的行为,我们必须手动迭代边界框,找到那些具有显著水*相交区域的边界框,并纠正它们的右边界。在绝大多数情况下,它会使边界框的宽度精确匹配所包含的字符串的长度。这个算法已经包含在 Demoocr 类的 get_tes_ocr_data 方法中,允许我们在对修改后的图像执行 OCR 的每个步骤中获取调整后的数据。

Google Vision:拆分你可能期望加入的内容

与 Tesseract 相反,Google Vision 为已识别的文本实体提供了更加分散的边界框。请注意,它将作为标点符号阅读的字符从前面的单词中分离出来是多么有用和隐含。但是在某些情况下,这可能会被认为是不受欢迎的行为!在我们的特殊情况下,从后续数字的边界框中取出一个货币单位,这使得很难直接比较 OCR 引擎在给定区域内字符数量方面的性能。

OCR 比较方法:更精细的点

由此可见,我们不仅要考虑在每一步图像修改中识别的字符数量,还要考虑它们的正确位置,即在初始步骤中确定的边界框。由于 OCR 引擎的输出有很大的不同,我们需要手动校正边界框,这次是通过以下方式合并所有重叠的多边形。

接下来,我们将在这些基线边界内精确计算识别字符的数量。为了便于说明,正确读取的字符数将显示在图像上相应区域的不透明彩色横条上。堆叠的条越短,相应的 OCR 引擎在给定区域内成功读取的字符数量就越少。

把所有的放在一起

通过比较两种工具在使用不同强度的过滤器修改图像的每一步的 OCR 结果,我们有望获得谷歌视觉和宇宙魔方特定功能的感觉。下面是一个中间步骤的示例,以及这两种工具的 OCR 结果。

下面是我们的比较方法:

作者图片

另一个例子是:

作者图片

还有一个。

作者图片

最后一个了。

作者图片

带回家的笔记

如上所述,Google Vision 和 Tesseract 都是成熟的工具,并且历史上已经在许多商业项目中找到了它们的方法。即使没有经过预处理,它们也能对质量尚可的文本图像进行充分的 OCR。虽然这样的预处理用OpenCV 似乎能显著提高对宇宙立方体的 OCR 结果。此外,您应该已经注意到,这两种工具对带有文本背景的图像的处理是多么不稳定。我们分析的这一发现与另一个比较中的见解有着特定的对应关系,但这也绝非详尽无遗。总而言之,这两个引擎都应该被认为是易于设置和使用的 OCR 工具,您的项目的正确选择在很大程度上取决于外部需求和预算。

Github 上查看完整的代码,其中包含一系列方便的 OCR 和图像预处理方法。

Python 中的信号链分析

原文:https://towardsdatascience.com/signal-chain-analysis-in-python-84513fcf7db2?source=collection_archive---------28-----------------------

行业笔记

硬件工程师案例研究

信号链在硬件电子产品中很常见。通常情况下,物理信号(温度、位置、压力……)会通过一系列操作在整个链条中进行转换。考虑到实际的硬件限制,这种转换会引入一些误差。预测存在错误时的整体性能需要数学分析,Python 非常适合这种分析。这篇教程文章提供了一个完整的可重现性分析作为说明性案例研究。案例研究是一个跨越多个领域(机械、磁性、模拟硬件和数字信号处理)的传感器读出链。本文展示了 Python 作为一流工程设计工具的能力。它是介绍编码模式的前一篇文章[1]的延续。这里的分析使用这种编码模式,并集中在工程方面。

介绍

温度、压力、位置等真实信号通常由硬件信号链处理。典型的链由模拟电子设备、数字数据转换和进一步的数字处理操作组成。实际硬件的非理想性,如噪声和有限的位数,会降低信号质量。为了量化性能,需要一个忠实捕捉误差的链的数学模型。Python 拥有丰富的数学和工程库生态系统,非常适合编写这样的模型。此外,Jupyter 笔记本混合了计算、绘图和叙述故事,为与同事、利益相关者甚至全世界分享工程分析报告提供了理想的格式。这种分析可以用最少的基础设施再现:只需一个浏览器。此外,这个生态系统的开源性质不仅有利于钱包,而且促进了学习和合作。

尽管有这些优势,没有软件背景的工程师经常发现很难开始使用 Python 建模和分析。因此,这些工程师倾向于回到电子表格来进行系统建模。Excel 仍然是最常用的建模语言[2]——严重限制了建模能力。

在本文中,我们将展示 Python 支持完整信号链分析的能力。我们采用教程方法,涵盖端到端的分析。我们从链框图开始,讨论每个块的建模代码。我们解释了一般的分析流程,并在与利益相关者共享的出版物质量的交互式仪表板中总结了我们的结果。

作为一个具体的用例,我们将该方法应用于一个智能传感器读出链。这个例子的灵感来自作者的职业经历[3]。然而,设计和参数是虚构的。虽然建模和分析技术是通用的。这个示例性链的优点在于,它足够通用,可以涵盖各种信号链。它包括非线性运算和在实际硬件实现中发现的非*凡误差。

完整的代码以 Jupyter 笔记本的形式提供。这个笔记本是完全可执行的在那里。鼓励读者在笔记本上玩耍,复制下面讨论的情节和仪表板。

传感器读出链的例子

作为一个实际例子,我们考虑智能磁位置传感器的信号链。传感器的目的是测量旋转磁铁的角位置。这种传感器在现代汽车和无数其他工业和机器人应用中无处不在。

该链如下所示,涵盖多个工程领域。从左到右,磁铁产生磁场。磁体的机械旋转调制由传感器感测的磁信号。传感器沿着正交传感轴转换磁场分量。这两个电压被标准模拟电子设备放大并转换成数字位。通过对两个数字分量进行反正切运算(由 CORDIC 算法实现)来计算角度。

硬件信号链(图片作者提供)。

如果该链是理想的,那么可以进行分析,或者在简单的电子表格中进行模拟。实际上,这个链条受到非理想性的困扰。它们以非*凡的方式破坏信号,使得除了最简单的情况之外,分析在电子表格中难以管理。

另一方面,使用 Python,我们可以将链分解成模块化的功能块。此外,对于复杂的数学运算,我们可以依赖一个丰富的生态系统,该系统由成熟的开源高级库组成。从而保持对工程方面的关注。

误差模型考虑

考虑以下误差源(在上图中以红色突出显示和编号)。

(1)机械错位。传感器没有完全对准磁铁旋转轴。想象有一个偏心率和一个倾斜角。这使得数学变得具有挑战性:简单的教科书公式不再适用于磁体对称轴上的磁场。相反,该模型需要考虑 3-D 中的矢量场,如[4]中的等式所示。此外,在传感器的框架中表达该场需要使用旋转。开源库 Magpy [5]很好地解决了第一个挑战,它为各种磁体几何形状提供了磁场。关于旋转,标准的 scipy.spatial.transform 包中提供了各种格式(欧拉角、角轴、矩阵……)的基本旋转操作。

②电子噪音。感应信号在毫伏范围内,因此被电子噪声破坏。我们假设噪声源可以建模为闪烁噪声,也称为“粉红噪声”。这种噪声在电子产品中很常见。与纯粹随机的“白噪声”不同,相邻样本在某种程度上是相关的,就像在随机漂移或扩散过程中一样。再次,产生具有这种性质的噪声序列的算法被发展。有多个现成的开源 Python 库可以用一行代码生成如此嘈杂的波形。一个例子是[6]。

(3)量化误差。数字运算受到二进制运算精度的限制。例如,模数转换器(ADC)的位数有限。这很容易被建模为舍入运算。对在硬件中实现的有限精度的三角函数进行建模是更加进化的。考虑 CORDIC 算法:它将反正切运算分解为一系列角度递减的旋转。产生的角度误差再次取决于位数,但也取决于迭代次数。还有现成的开源 Python 库,如[7]提供了这种操作的高级模型。

以上三个误差的累积效应是,测得的输出角 θo 仅约等于磁体的输入角 θi 。角度误差由随机波动和非线性失真组成。基于快速傅立叶变换 (FFT)的频谱分析可以区分这些贡献,从而提供工程洞察力。标准scipy封装中也提供 FFT 功能。

总的来说,Python 生态系统为我们提供了建模链、其误差和数学信号分析的高级库。按照我们在上一篇文章[1]中介绍的编码模式,该模型将由一系列模块块组成,从而密切模仿框图的结构。对于每个模块,我们将定义一个函数 y=f(x) 来捕捉从输入到输出的转换。

块函数通常在代码行方面很小,尽管由于高级库而捕获了复杂的数学。代码将保持精简,在精神上接*工程图。

请注意,编码模式仅限于没有反馈回路和动态的链。需要一个扩展来涵盖这些情况。这将在后续文章中讨论。

建模

鉴于完整的代码可在配套的 Jupyter 笔记本中获得,我们在这里不深入研究所有细节。相反,我们专注于工程方面和整体方法。我们首先列出所有表征链条的工程参数及其误差源。

首先考虑磁铁。其特征在于它的维度(一个 3 元素列表)、它的磁化矢量(另一个 3 元素列表)和它的位置(另一个 3 元素列表)。对于传感器,我们有位置、倾斜角、灵敏度和噪声均方根(RMS)幅度。对于 ADC,我们有舍入步长和位数。对于 CORDIC 算法,我们有迭代次数。

就像我们以前的文章[1]中推荐的那样,为了方便起见,我们将所有固定的参数分组到一个数据字典中。我们使用一个 Box 数据结构,而不是普通的字典:这样就可以用dd.block.parameter简洁地调用参数。

将参数分组在单个数据结构中为给定模拟运行的参数集提供了单点真实性。这简化了参数研究期间多个模拟运行的管理。

为了简化计算,通常还需要几个额外的导出参数。这里,传感器和磁体边缘之间的气隙以及传感器旋转矩阵被用于中间计算。因为两者都是直接从主要的参数集派生出来的,所以为了方便起见,我们将它们集成到数据字典中。为了模块化,我们将数据字典定义和派生参数的计算包装在支持函数中。我们获得下面的代码。

*#----------------------*
*# Parameters*
*#----------------------*

**def** load_dd():
  **return** Box({
    'magnet'  : {
      'dim'   : [10,10,10],  *# magnet dimension Lx, Ly, Lz [mm]*
      'mag'   : [-1,0,0],    *# magnetization vector Br [Tesla]* 
      'pos'   : [0,0,15] },  *# magnet center [mm]* 
    'sensor'  : {
      'pos'   : [0,1,0],     *# sensor center [mm]*
      'tilt'  : 3,           *# sensor tilt [°]*
      'S'     : 1.0,         *# sensor sensitivity [Volt/Telsa]*
      'noise' : 0.2 },       *# sensor input-referred noise [Tesla]*
    'adc': {
       'lsb'  : 0.1,         *# ADC LSB size rounding step*
       'n'    : 12 },        *# ADC number of bits* 
    'cordic'  : {
      'n'     : 12, }        *# CORDIC number of iterations* 
  })

**def** calc_derived(dd):
  dd.sensor.airgap =dd.magnet.pos[2] - dd.magnet.dim[2]
  dd.sensor.rot=R.from_euler('y', dd.sensor.tilt, degrees=**True**)

建模磁性和机械方面

我们现在将注意力转向机械和磁方面的建模。根据我们的功能框图,磁体和传感器被组合成一个单独的模块。相应的函数将输入角度 θi 转换为传感器位置的磁场矢量,以传感器的框架表示。让我们将这个函数分解成基本的 Python 语句。

  • 我们用数据字典中的参数创建一个条形磁铁的实例:magnet = Bar_magnet(*dd.magnet)
  • 我们将磁铁旋转输入角度:magnet.rotate(...)
  • 我们计算参考系B=magnet.getB(...)中传感器中心的磁场;
  • 我们将磁铁返回到初始位置(避免记忆状态):magnet.angle=0
  • 我们通过乘以旋转矩阵来表达传感器框架中的矢量,以说明倾斜:dd.sensor.rot.apply(B)
  • 我们使用显式变量标签返回向量分量,以符合我们的编码模式:return {'Bx': B[0], ...}

我们获得了下面的代码(与电子表格中的暴力实现形成对比)。

**from** **magpylib.source.magnet** **import** Box **as** Bar_magnet
magnet=Bar_magnet(**dd.magnet)

**@apply_func_df**
**def** calc_B(X, dd, magnet):
  'Calculate the field vector in mT as a function of rotation'
  magnet.rotate(angle=X.theta_i, axis=[0,0,1])
  B = magnet.getB(np.array(dd.sensor.pos))/1e-3
  magnet.angle=0
  B=dd.sensor.rot.apply(B)
  **return** {'Bx': B[0], 'By': B[1], 'Bz': B[2]}

请注意,magnet 实例只为函数外部的所有对象创建一次,并作为参数传递,以避免在每个函数调用中产生开销。像我们以前的文章[1]中一样,该函数用@apply_fun_df包装,以使其与数据帧兼容。这样,该函数直接在一个表格数据集上操作,该数据集代表一次全角度扫描,而无需显式循环。有了这些代码,我们可以对这个功能块进行实验,例如,绘制一个完整旋转的字段的 BxBy 分量:

df = pd.DataFrame({'theta_i': np.linspace(0,360,2**10, endpoint=False)})
df.hvplot(x='theta_i', y=['Bx', 'By', 'B magn.'],
          xlabel='θi [°]', ylabel='Field [mT]')

完整旋转的字段组件(图片由作者提供)。

噪声建模

为了模拟噪声,我们将两个粉红噪声序列注入到两个感测的场分量中。这两个噪声序列是来自同一统计模型的两种不同实现。实际上,这相当于两个分量被两个独立的链放大的情况,每个链都有自己的噪声源。在功能上,这被表示为从一对无噪声分量 (Bx,By) 到有噪声分量(Bx’,By’)的变换。该功能可以分解如下:

  • 我们使用库 colorednoise 生成两个独立的粉红噪声序列(与刺激长度相同)。默认情况下,它们的归一化均方根幅度为 1;
  • 我们通过期望的 RMS 幅度(来自数据字典的参数)来缩放两个序列;
  • 我们将它们添加到无噪声信号中。

下面是相应的代码。请注意,为了方便起见,转换是就地完成的(无噪声组件被覆盖)。

**import** **colorednoise** **as** **cn****def** apply_noise(df, dd):
  noise=pd.DataFrame([pd.Series(cn.powerlaw_psd_gaussian(1, len(df))) **for** k **in** (0,1)]).T
  noise*=noise*dd['sensor']['noise']
  df[['Bx', 'By']] +=noise.values
  **return** df

完整链

对于链的其余部分,我们以类似的方式进行。表示为 G_k 的两个模块仅代表缩放增益系数,在此忽略不计( G_k =1)。ADC 函数只是一个舍入运算。我们只剩下使用 CORDIC 算法的角度计算。我们通过 n 次迭代(数据字典中的参数)重用库[7]中的算法,特别是在单个象限中工作的arctan_cordic函数。为了推广到四个象限,我们使用维基百科中的公式,使用sign函数从arctan计算arctan2。我们获得:

**@apply_func_df**
**def** calc_angle(X, dd):
  x,y = X.Qx, X.Qy *# convenient alias*
  angle = cordic.arctan_cordic(x, y, n=dd.cordic.n)
  *# 4-quadrant extension*
  **return** {'theta_o': np.degrees(np.sign(x)**2 * angle + (1-np.sign(x))/2*(1+np.sign(y)-np.sign(y)**2)*np.pi)}

除了分析模块之外,完整的链现在被建模。为了模块化,我们将完整的模拟运行封装到一个virtual_experiment函数中。该功能执行端到端实验(设置参数,按顺序运行所有模块,并测量角度误差)。它将数据框中的角度扫描和对数据字典的潜在更改作为参数。它返回包含所有中间信号和自然输出角度的填充数据帧。该功能如下进行:

  • 我们首先构建默认的数据字典;
  • 我们合并作为参数传递的更改;
  • 我们将使用的块函数链接成一个流水线,依次调用每个函数,丰富了信号的数据帧;
  • 我们执行快速计算以提取角度非线性误差(为便于解释,该误差包裹在 180°内),并针对*均值进行了校正(这不会导致非线性)。

下面是相应的代码。并注意与框图的对应关系。

**def** virtual_experiment(theta_i=np.arange(0,360,0.1), dd={}):
  dd=merge(load_dd(), dd)
  calc_derived(dd)
  magnet=Bar_magnet(**dd.magnet)

  df = pd.DataFrame({'theta_i': theta_i})
  df=(df.pipe(calc_B, dd=dd, magnet=magnet)
      .pipe(transduce,dd=dd)
      .pipe(apply_noise, dd=dd)
      .pipe(quantize, dd=dd)
      .pipe(calc_angle, dd=dd))
  df['theta_err'] = deg_180(df.theta_o - df.theta_i)
  df['theta_err'] -= df['theta_err'].mean()
  **return** df

分析

量化动态误差并给出令人信服的解释的一个性能指标是有效位数(ENOB)。确切定义见【8】和 [<#enob-2> 9]。顾名思义,该指标提供了从模拟输入到数字输出的整体转换的有效位数。例如,ENOB=10b 表示误差与理想 10 位转换的幅度相同。

根据定义,该指标需要满量程幅度的正弦波激励: θi = 180 sin(2π ft )。调整频率 f 以覆盖 2ᴺ样本中的整数个周期。然后通过 FFT 分析数字输出 θo 波形。工程解释是 FFT 的系数(所谓的频谱)对应于每个频率仓中的信号功率。自然,在输入频率上有一个功率峰值:这是目标信号的功率 S 。总功率为 D 的失真出现在谐波频率上。剩余的功率 N 是随机噪声,它广泛地填充了其他频率仓,建立了“噪声基底”。在 Python 中,这种分析通过以下方式简洁地调用:

f,P = signal.periodogram(df.theta_o, scaling='spectrum')
idx_max=np.argmax(P)
S   = P[idx_max]    
D   = sum(P[2*idx_max:11*idx_max:idx_max]) *# sum of harmonic components up to order 10*
N   = sum(P) - S - D

再次注意拥有高级库的便利,比如提供periodogram分析功能的scipy

像往常一样,为了模块化,我们将上述内容和最终的 ENOB 计算封装在一个函数ENOB()中。然后通过连续调用虚拟实验和 ENOB 函数来调用完整的分析。

分析仪表板

该分析返回最终指标,如 ENOB(位数)以及失真和噪声的均方根功率。在分享我们的分析之前,我们应该用几个有见地的情节来说明。这里我们简单地画出输入激励、输出误差和频谱。我们使用另一个库面板将这些图和一个汇总表组合在一个交互式仪表板中。

互动仪表盘截图(图片由作者提供)。

分享分析

在区域工程分析中,人们当然会分析这些结果,并提出设计改进建议。这超出了本文的范围,我们将通过发布分析来结束本文。

分析是在 Jupyter 笔记本中进行的:分析代码、情节和叙述是一个整体:一个可复制的报告。自然,报告可以导出为标准的静态格式,如 HTML 或 PDF。然而,共享报告的“实时”实例确实有好处。这样,计算可以被复制。除了再现之外,还可以试验一组新的参数,并且报告可以即时更新。这促进了协作学习。完整的代码笔记本可以在那里找到,还有一个可执行版本的链接。

结论

我们用 Python 演示了硬件信号链的分析。从框图和误差源的识别开始,我们开发了相应的 Python 模型。我们使用模块化编码模式,严格遵循框图的结构。我们展示了如何调用该模型来运行虚拟实验和执行深入的信号分析(例如失真和噪声分析)。最后,我们以出版物质量仪表板和可复制报告的形式展示了我们的结果。总的来说,这个端到端教程展示了 Python 执行硬件工程设计任务的能力。

参考

[1] G. Close,“python 中的功能建模和定量系统分析”,走向数据科学,2021 年 1 月 31 日。可用:https://towards data science . com/functional-modeling-and-quantitative-system-analysis-in-python-22 b 90 BF 0 b 9 b 5。

[2] R. Dronzek,“系统工程师的模拟建模”,INCOSE 网络研讨会,2019 年 7 月 10 日。可用:https://www . any logic . com/upload/webinars/al-webinar-simulation-modeling-for-systems-engineers . pdf .

[3] N. Dupré、Y. Bidaux、O. Dubrulle 和 G. Close,“具有 1%精度的杂散磁场免疫磁位移传感器”,IEEE Sens. J,2020 年 5 月。可用:https://doi.org/10.1109/JSEN.2020.2998289

[4] R. Ravaud 和 G. Lemarquand,“*行六面体磁铁产生的各种均匀极化的磁场”,电磁学研究进展,第 98 卷,第 207-219 页,2009 年。可用:http://dx.doi.org/10.2528/PIER09091704

[5] M. Ortner 和 L. G. Coliado Bandeira,“Magpylib:用于磁场计算的免费 Python 包”,SoftwareX,第 11 卷,第 100466 页,2020 年 1 月。可用:http://www . science direct . com/science/article/pii/s 2352711020300170

[6] F. Patzelt 和 Alex Spaeth,“colorednoise.py”,版本 1.1.1,2019 年 6 月 1 日。可用:【https://github.com/felixpatzelt/colorednoise

[7]:约翰·伯卡特,《科迪奇》,2017 年 6 月 28 日。可用:https://people . sc . FSU . edu/~ jburkardt/py _ src/cord IC/cord IC . html。[访问日期:2021 年 2 月 15 日]

[8] W. Kester,“了解 SINAD、ENOB、SNR、THD、THD + N 和 SFDR,以免迷失在噪底中”,ADI 公司,MT-003 教程,2009 年。可用:https://www . analog . com/media/en/training-seminals/tutorials/MT-003 . pdf

[9]:robustcircuitdesign.com,“理解有效位数”,2016 年 11 月 18 日。可用:https://robustcircultdesign . com/signal-chain-explorer/understanding-effective-number-of-bits/【访问时间:2021 年 2 月 15 日】

基于细胞复杂网络的细胞复合体信号处理

原文:https://towardsdatascience.com/signal-processing-on-cell-complexes-with-cell-complex-networks-cxns-fc4cebe24e42?source=collection_archive---------19-----------------------

单纯/细胞复合体及其他支持的深度学习

里卡多·戈麦斯·安吉尔在 Unsplash 上的照片

D eep 学习促进了许多新技术的发展,从自动医学图像分析到人工智能驱动的文档翻译。这些社会变革起源于计算机视觉和自然语言处理领域的快速发展,即图像和文本的处理。然而,用一个像素网格或一系列单词来表示大范围的数据并不是最好的。例如,(生物分子)形状或(社会)网络是展示局部和全局几何属性的数据类型,这些属性可能无法被现有的深度学习架构有效利用。因此,需要严格理解和扩展深度学习方法可以应用的数据类型。本文考虑将深度学习推广到称为“细胞复合体”的广义空间。这种域概括了几乎所有具有实际重要性的离散域,如图形、点云、网格和单纯复形。然而,它们保留了足够直观的结构,使它们在实际应用中很重要。我们简要介绍了这些空间,并提供了这方面的最新工作[9]。

高阶网络建模

图是用于建模实体之间关系的自然对象。然而,通常在实践中,人们可能需要对 k 个实体之间的高阶关系进行建模。图形的建模能力有限,因为它们只能对成对关系建模。如果我们想要对关系之间的关系建模呢?这就是来自代数拓扑的对象,如单纯和细胞复形来拯救[1,9,10]。

单纯复形是从称为单纯的原始对象构建的图的推广。零和一单形对应于图中的节点和边。单纯复形中的高阶关系通过面或四面体和高阶单纯来建模。下图是一个二维单纯复形的例子。这里维数为 2 的原因是这个单纯复例包含维数为 2 的单纯。

二维单纯复形。图像源[1]

单纯复形可能是最简单的一种复形,并且已经具备了许多编码高阶关系的特性:它们不仅允许顶点对之间的关系,而且允许更大的顶点集之间的关系,从而扩展了图。然而,单纯复形作为离散域的建模工具具有某些缺点。特别地,在单纯复形中,k 个实体之间的任何关系都必须从包含(k1)个实体的所有对应子集的关系中构建。因此,通过单纯复形编码空间可能需要(不必要的)大量数据和存储器。对于深度学习应用,这使得在这些领域训练神经网络相当具有挑战性。

我们能否找到这个空间的更简单的表示,它保留了单纯复形的代数结构,我们可以利用它进行深度学习应用?在这篇文章中,我们认为规则细胞复合体的理论为 SCs 肯定地回答这个问题提供了必要的概括。

什么是细胞复合体?

多边形复合体是规则细胞复合体的特例[1,9]。

在直观的层面上,单元复合体(CC)是由称为单元的基本实体构建的广义空间。虽然 SC 只允许简单的构造块,但是 CC 允许使用任意形状的单元。因此,每个单元在其边界上可以具有任意数量的低维单元。这种更灵活的复杂类型产生了一个更简单的圆环模型,见下图(右)。不是必须将环面的表面分成 18 个三角形,而是可以用 4 个节点、8 条边和 4 个面来模拟环面,描述由这些边界定的区域。除了在模拟各种域时增加的灵活性之外,当用细胞复合体代替单纯复合体时,还可以获得数值稳定性[9]。

单元复合体可用于用少得多的构件来模拟相同的底层空间。图片来源[9]

细胞复杂网络

最*,人们对将深度学习协议推广到自然模拟高阶交互的对象产生了浓厚的兴趣。细胞复合体网络是一种在常规细胞复合体上执行深度学习计算的网络。在常规细胞复合物上的这种网络的研究首先在[1]中介绍。这种网络是图形神经网络的一般化,并且它们使用直观的消息传递协议以类似的方式操作,该协议允许在细胞之间改组信号。这些网络表现出的一个关键区别是,细胞复合体上的信号可以在不同维度的细胞之间被打乱[1,9]。相关处理方法参见[2,3,4,5,6,7,8]。

例如,考虑下图中给出的例子。

消息传递方案,其中节点从 0 和 1 单元接收信号。图像源[1]

这个简单细胞复杂网络的计算图是相对于红色节点来解释的。注意这个节点是如何从 0 维和 1 维细胞接收信号的。在这种网络的计算中(通过考虑红色单元的局部邻域),维度 1 的单元接收来自维度 1 和维度 2 的单元的信号。这可以从下图中看出:

在第二层中,使用来自相邻边缘以及面的信号来更新边缘信号。图像源[1]。

请注意,蓝色边缘接收来自亮粉色边缘和暗粉色边缘的信号,因为所有这些边缘都是粉色表面的边界。也可以在小区复合体上定义其他消息传递方案。关于这些网络[13,14]的更多细节,参见 CXNs 的介绍这篇相关文章。

引入代数拓扑语言描述 CXNs

细胞复合体是拓扑空间,通常在代数拓扑的背景下研究[10]。组合上,它们可以通过一系列的边界图来描述,粗略地说,描述了(n-1)个单元与 n 个单元相邻的方式。以下是图下部给出的细胞复合体的前两个边界图。注意,这里有两个边界矩阵(因为复合体的维数是 2),第一个矩阵描述了 1 单元相对于 0 单元的邻接关系(或者更精确地说是边界关系),第二个矩阵描述了 1 单元相对于 2 单元的边界关系。

单纯复形的前两个边界图

这些矩阵序列实际上可以用来表示一个单元或一个单纯复形。在这些领域的深度学习环境中,这些图可用于在复合体的细胞之间发送信号或协同链[1,9]。

现在我们知道如何描述细胞复合体,我们上面描述的计算图可以通过熟悉的方程(类似于熟悉的 GNN 方程)在实践中计算出来[4,9,11]:

这里,H 是线性运算符,负责在尺寸为 l 的单元之间移动信号(消息传递信号),而 s_l 是在 l 单元上更新/混洗的信号。在实践中,H 只是一个矩阵,并且在单纯/细胞复合体的信号处理的上下文中[8,9,11,12],H 被选择为拉普拉斯矩阵或其一个推广的霍奇拉普拉斯矩阵[8,9,11,12]。

我们可以推广上述等式,并要求在不同维度的单元之间移动信号(由于边界/共边界运算符将信号发送到较低/较高的单元)。即,给定上链空间之间的适当线性算子的集合[8,9]:

将 I 单元格顶部定义的信号映射到 j 单元格的矩阵。

人们可以将一般的细胞复杂网络定义如下:

使用算子 Gi,可以将来自多个源的信号组合在一起,以更新目标信号 sj。

前一等式中给出的这种通用形式描述了在单元/单纯复合体上支持的深度学习模型的许多现有架构,包括[1,2,3,4,5,6,7,8]。映射 Gi 起到将信号从 I 细胞传递到 j 细胞的作用,并且可以看出,这可以容易地用矩阵来表征。有关更多详细信息,请参见[1,8,9]。

本文是与许多作者共同工作的一部分,这些作者包括 Roddenberry、T. Mitchell、Michael T. Schaub、Ghada Zamzmi、Birdal、Kyle Istvan、Xuanting Cai、Nina Miolane、Karthikeyan Natesan Ramamurthy 和 Aldo Guzman Saenz。

参考文献

[1] M. Hajij、K. Istvan 和 G. Zamzmi,“细胞复合神经网络”,NeurIPS 2020 研讨会,TDA 及以后,2020 年。

[2] M. T. Schaub,Y. Zhu,J.-B. Seby,T. M. Roddenberry 和 S. Segarra,“高阶网络上的信号处理:生活在边缘上……以及超越”,信号处理,第 187 卷,第 108149 页,2021 年。

[3] M. T. Schaub、A. R. Benson、P. Horn、G. Lippner 和 A. Jadbabaie,“单纯复形上的随机漫步和标准化的 hodge 1-laplacian”,《暹罗评论》,第 62 卷,第 2 期,第 353-391 页,2020 年。

[4] S. Ebli、M. Defferrard 和 G. Spreemann,“单纯神经网络”,NeurIPS 拓扑数据分析研讨会,2020 年。

[5] T. M. Roddenberry,N. Glaze 和 S. Segarra,“用于轨迹预测的有原则的单纯神经网络”,机器学习国际会议,第 9020-9029 页,PMLR,2021 年。

[6] E. Bunch、Q. You、G. Fung 和 V. Singh,“Simplicial 2- complex 卷积神经网络”,NeurIPS 拓扑数据分析研讨会,2020 年。

[7] M. Hajij,G. Zamzmi,和 X. Cai,“单纯复表示学习”,arXiv 预印本 arXiv:2103.04046,2021 .

[8] Hajij,Mustafa 等,“以数据为中心的人工智能需要重新思考数据概念。”NeurIPS 以数据为中心的人工智能研讨会,2021 年。

[9] Roddenberry、T. Mitchell、Michael T. Schaub 和 Mustafa Hajij。"细胞复合体的信号处理."arXiv 预印本 arXiv:2110.05614 (2021)。

[10]艾伦·哈奇,代数拓扑,2005。

11.《单纯复形上的信号处理》 arXiv 预印本 arXiv:2106.07471 (2021)。

[12]巴巴罗萨、塞尔吉奥和斯特凡尼亚·萨德利提。"单纯复形上的拓扑信号处理."IEEE 信号处理汇刊 68(2020):2992–3007。

[13] M. Hajij,单纯复表示学习,使用高阶几何消息传递方案学习整个单纯复表示。

[14] M. Hajij,一个网络统治一切:细胞复杂神经网络一个统一的数学框架,在其中可以定义和执行深度学习模型和协议。

Q-Q 图的重要性

原文:https://towardsdatascience.com/significance-of-q-q-plots-6f0c6e31c626?source=collection_archive---------13-----------------------

它会告诉我们哪些关于数据的秘密?

马特·邓肯在 Unsplash 上的照片

了解变量的分布是浏览数据集时首要完成的任务之一。一种用图形测试连续变量分布的方法是通过 Q-Q 图。就个人而言,这些图在参数检验的情况下很方便,因为它们坚持正态假设,即使它们可以用于任何基础分布。

什么是阿 q 情节?

分位数-分位数图或 Q-Q 图是通过绘制两个不同的分位数来创建的散点图。第一个分位数是测试假设的变量的分位数,第二个分位数是测试假设的实际分布。例如,如果您正在测试团队中员工的年龄分布是否为正态分布,您将比较团队成员年龄的分位数与正态分布曲线的分位数。如果从同一分布中抽取两个分位数,它们应该大致落在一条直线上。
由于这是一种直观的比较工具,结果也可能相当主观,但对理解变量的潜在分布很有用

是如何产生的?

以下是为团队成员年龄生成 Q-Q 图以测试正态性的步骤

  1. 将你感兴趣的变量(在这个场景中是团队成员的年龄)从最小值到最大值排序。假设在这个场景中有 19 个团队成员。
  2. 取一条正态曲线,分成 20 等份(n+1;其中 n = #个数据点)
  3. 计算这些点的 z 分数
  4. 根据排序后的变量绘制获得的 z 得分。通常,z 分数位于 x 轴(也称为理论分位数,因为我们将它用作比较的基础),可变分位数位于 y 轴(也称为有序值)
  5. 观察数据点是否在一条 45 度直线上紧密对齐
  6. 如果有,年龄呈正态分布。如果不是,您可能希望对照其他可能的发行版来检查它

我如何用 Python 来绘制这个?

下面是检查随机正态分布的正态性的示例代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
%matplotlib inlinenp.random.seed(100) #for reproducibility# Generate 200 random normal data points with mean=0, standard_deviation=0.1
#Documentation:https://numpy.org/doc/stable/reference/random/generated/numpy.random.normal.html
random_normal_datapoints = pd.Series(np.random.normal(0, 0.1, 200))# Lets plot the data points along with its KDE to see how it looks
fig, ax = plt.subplots()
random_normal_datapoints.plot.kde(ax=ax, legend=False, title='A random normal distrubution with mean 0 and SD 1')
random_normal_datapoints.plot.hist(density=True, ax=ax)
ax.set_ylabel('Frequency')# Plot the Q-Q plot to graphically check for the hypothesis
#https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.probplot.html
res = stats.probplot(random_normal_datapoints, plot=plt)
plt.show()

# Plot the Q-Q plot to graphically check for the hypothesis
# Documentation : https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.probplot.html
res = stats.probplot(random_normal_datapoints, plot=plt)
plt.show()

正如您所观察到的,数据点大致位于一条直线上。因此,我们可以说数据点是正态分布的(即使我们知道它是从随机正态分布中采样的)

如果你要绘制一个随机均匀分布对正态分布,你会得到下图

正如你所看到的,大多数点并不在一条直线上。表明潜在的分布是不正常的

在下面的 Github 链接中可以找到更多关于如何检查其他发行版的示例和一些其他示例:

https://github.com/SundareshPrasanna/QQPlot-Medium

我们还能用它做什么?

Q-Q 图也可用于测试 2 个不同数据集之间的分布。例如,如果数据集 1(年龄变量)有 200 条记录,而数据集 2(年龄变量)有 20 条记录,则可以比较这些数据集的分布,看它们是否确实相同。这在机器学习中特别有帮助,在机器学习中,我们将数据分成训练-验证-测试,以查看分布是否确实相同。它还用于部署后场景,以直观地识别协变量转换/数据集转换/概念转换。

摘要

总的来说,Q-Q 图可以帮助你比较手头变量的样本分布和其他可能的分布。

使用 Python 进行显著性或假设检验

原文:https://towardsdatascience.com/significance-or-hypothesis-tests-with-python-7ed35e9ac9b6?source=collection_archive---------22-----------------------

入门

用 Python 实现大学统计

介绍

在一系列的每周文章中,我将会涉及一些重要的统计学主题。

目标是使用 Python 来帮助我们获得对复杂概念的直觉,从经验上测试理论证明,或者从零开始构建算法。在本系列中,您将会看到涵盖随机变量、抽样分布、置信区间、显著性检验等主题的文章。

在每篇文章的最后,你可以找到练习来测试你的知识。解决方案将在下周的文章中分享。

迄今发表的文章:

像往常一样,代码可以在我的 GitHub 上找到。

假设检验简介

安东尼奥和 4 个朋友一起度过了 30 天的假期,他们想决定每晚谁来做饭。安东尼奥提议他们可以写下自己的名字,并把它们储存在一个碗里。然后,他会从一个碗里随机抽取一个名字,上来的名字必须是当天晚上做晚饭的。现在,假设在 4 轮随机选择名字后,安东尼奥的名字再也没有出现。剩下的朋友开始怀疑发生了什么事。让我们来计算一下这个概率。

0.80**40.4096000000000001

我们可以看到,这种情况有接* 41%的概率发生。这是一个非常重要的概率,因此朋友小组可能应该信任安东尼奥。现在,想象一下 15 轮过后,安东尼奥仍然没有被选中。

0.8**150.03518437208883203

假设这个过程是完全随机的,他连续 15 轮没被选中的概率大概是 3.5%。如果他的朋友使用通常定义的 5%的阈值,他们不会想到纯粹偶然发生的事件的概率小于 5%。然后,他们可能会拒绝这是一个真正随机过程的假设,这意味着安东尼奥在作弊。

关于总体比例的假设检验

图 1:安东尼奥和他的朋友在海滩上思考统计数据;来源

一天,在海滩上,安东尼奥在一本杂志上读到一篇文章,文章称只有 30%的人在海滩上使用防晒霜。安东尼奥认为这个数字对于他们度假的海滩地区来说太低了。他告诉了他的朋友,他们决定从附*的海滩随机抽取 35 人,他们估计当天至少有 400 人在享受海滩。这 35 人中,有 14 人使用了防晒霜。

14/350.4

让我们更正式地定义我们的假设检验:

零假设显示了预期的结果,假设只有 30%的人在海滩使用防晒霜。另一方面,另一个假设陈述了安东尼奥的怀疑:超过 30%的人实际上在使用防晒霜。

让我们进行一次模拟,看看像上面这样的样本随机发生的可能性有多大。我们模拟了 40 个样本,样本量等于 30,其中 40%的人使用了防晒霜。

from scipy.stats import bernoulli, norm, t
import matplotlib.pyplot as plt
import numpy as np
import seaborn as snsx = np.zeros((40, 35))
for i in range(40):    
    x[i] = bernoulli.rvs(p=0.3, size=35)

我们可以用柱状图来描绘我们的模拟。

sns.histplot(np.mean(x, axis=1));

图 2:样本大小等于 30 的模拟样本(40)的直方图。

p = np.mean(x, axis=1)

有了这些信息,我们就可以计算我们的 p 值。它可以定义为 p̂大于或等于 0.4 的抽样比例的概率,以 h0 为真为条件:

我们可以很容易地计算出 p 值。

p[p>=0.40].shape[0]/p.shape[0]0.125

如果安东尼奥使用α=0.05 的显著性水*,他不会拒绝 H_0。这意味着,在 p̂ = 0.4 的情况下,他们没有足够的证据来否定只有 30%的人使用防晒霜的可能性,而他们得到的 40%的统计数据只是随机的结果。

if (p[p>=0.4].shape[0]/p.shape[0]<0.05):
    print('Reject H_0')
else:
    print('Do not reject H_0')Do not reject H_0

关于比例的 Z 检验的条件

我们在以前的文章中看到了执行 z 测试的条件。这三个条件是:

  • 样本必须是随机的。
  • 正态分布可以*似样本比例的抽样分布。经验法则是,你至少需要有 10 次成功和 10 次失败。
  • 要求样本是独立的。经验法则是,如果你是在没有替换的情况下抽样,你的样本量应该少于总体量的 10%。

让我们完成前面的例子,并对每种情况进行测试。从随机抽样开始,我们被告知,朋友小组随机选择要问的人。有了这些信息,我们将假设他们的过程是真正随机的。正常情况告诉我们,预期的成功和失败次数至少需要等于 10 次。我们也能够满足该标准(参见下面的计算)。最后,我们有独立的条件。在我们的例子中,人口数量是海滩地区的人口,大约 400 人。使用的样本大小为 35,因此我们也可以满足执行 z 检验的条件。

n = 35
p = 0.3

print('np = '+ str(n*p))
print('n(1-p) = '+ str(n*(1-p)))np = 10.5
n(1-p) = 24.5

在关于比例的测试中计算 z 统计量

我们将继续使用我们的防晒霜问题。在上一节中,我们检查了推断的所有条件都得到了满足。在这种情况下,我们将执行 z 测试。

在继续之前,让我们回忆一下我们的目标。安东尼奥和他的朋友们从海滩地区的所有人口中抽取了 35 人作为样本,并计算出样本统计̂p= 40%。现在,假设零假设为真,得到一个离假设的人口比例 p=30%这么远或者更远的结果的概率是多少。

计算这种概率的一种方法是通过计算抽样比例与真实比例相差多少标准差(记住我们总是假设 h0 为真,所以我们认为是真实比例)。

p_0 = 0.3
p_hat = 0.4

Z = (0.4-0.3)/np.sqrt((0.3*(1-0.3)/n))
Z1.290994448735806

我们的 p 值可以定义为:

1-norm.cdf(Z)0.09835280122947343

将我们得到的这个概率与α=0.05 的显著性水*相比较,我们再次看到,我们不能拒绝 H_0。

关于总体均值的假设检验

一天晚上,安东尼奥正在查看他的手机,并开始想知道他和他的朋友在 WhatsApp 群聊中交换了多少条消息,他们在度假前 3 个月就建立了这个群聊。他怀疑他们*均每天会互相发送 180 条信息,但他的一个朋友认为他们交换了超过 180 条信息。他们决定检验这个理论。

让我们定义我们的显著性测试:

他们从聊天记录中随机抽取了 8 天的样本,并记录了这些天发送了多少条消息。样本数据大致对称,*均值为 215 条消息,标准偏差约为 36 条消息。他们想用 5%的显著性水*来检验他们的假设。

正如我们之前看到的,在这种情况下,我们将执行 t 检验,而不是 z 检验。原因是我们不知道样本均值的抽样分布的标准偏差

我们只能用抽样标准差来估计它

然后,我们可以将测试写成:

x = [266, 190, 161, 191, 241, 180, 240, 251]
x = np.asarray(x)
sns.histplot(x, bins=10);

图 3:随机抽样的邮件数量直方图。

print(x.mean())
print(x.std())215.0
36.29738282576307μ = 180
n = 8

t_star = (x.mean()-μ)/(x.std()/np.sqrt(n))
t_star2.7273302276728411-t.cdf(t_star, df=n-1)0.01472601649385541

我们的 p 值约为 0.015,小于我们的显著性水*。这意味着我们可以拒绝安东尼奥提出的 H_0,而接受替代假说。有足够的证据接受安东尼奥的朋友的假设,即该小组每天发送超过 180 条消息。

关于总体均值的 t 检验的条件

我们在以前的文章中看到了执行 t 检验的条件。这三个条件是:

  • 样本必须是随机的。
  • 样本均值的抽样分布可以*似为正态分布。有三种方法可以实现它:样本量大于 30(中心极限定理适用),原始分布是正态分布,或采样分布是对称的,不显示异常值。
  • 要求样本是独立的。经验法则是,如果你是在没有替换的情况下抽样,你的样本量应该少于总体量的 10%。

让我们再一次针对每一种情况测试我们之前解决的问题。这将使我们更加确信结果在某种程度上不会有偏差。我们被告知安东尼奥和他的朋友随机选择日期,这符合第一个标准。其次,我们的样本分布大致对称,可以认为正态条件也满足。最后,安东尼奥和他的朋友使用了 8 的样本量。我们被告知,他们在度假前 3 个月就已经建立了 WhatsApp 群聊。样本量少于 10%,因此可以安全地假设取样日之间的独立性,即使它们是在没有替换的情况下取样的。

第一类和第二类错误

我们已经看到,如果 p 值小于显著性水*α,我们应该拒绝 H_0。反之,如果 p 值大于α,我们就不能拒绝 H_0。当我们进行这些比较时,总有可能出错。让我们画一个表,让它更清楚。

表 1:与实际和预测结果相关的 I 型和 II 型误差。

请注意,出现 I 类错误的概率等于显著性水*。假设您定义了 5%的显著性水*。这意味着,在 5%的情况下,即使你的零假设是真的,你也会得到一个让你拒绝零假设的统计数据。

在前面给出的例子中,第一类和第二类错误是什么?让我们再次写下使用防晒霜人群比例的假设检验:

如果朋友们得出结论,使用防晒霜的人的比例不等于 0.3,而实际上是 0.3,那么就会发生第一类错误。另一方面,第二类错误是人们的比例不等于 0.3,但他们没有拒绝它。

另一个需要定义的重要概念是显著性检验的功效。它是当假设不成立时,你拒绝零假设的概率。

请注意

实际上是犯第二类错误的概率,所以你可以把显著性检验的功效看作是而不是犯第二类错误的概率。

让我们看看我们能做些什么来增强假设检验的能力:

  • 提高显著性水*(但请注意,这也将增加 I 类错误的概率)。
  • 增加样本量。
  • 数据的可变性更小。
  • 如果真参数远离零假设。

结论

在本文中,我们讨论了显著性或假设检验。这对于使用抽样数据来评估关于总体值的索赔的可能性非常有用。要测试的值可以是总体的比例或*均值。我们分别使用 z 检验和 t 检验计算了两种情况下的 p 值。

我们还解决了在执行这些测试时可能发生的错误。类型 I 错误的发生概率与定义的显著性水*相同,并转化为对实际为真的零假设的拒绝。当我们不能拒绝一个无效假设,并且它是错误的,我们就产生了第二类错误。最后,我们将显著性检验的功效定义为不犯第二类错误的概率,并找到了提高它的方法。

保持联系: LinkedIn

练习

你将在下周的文章中找到答案。

  1. 根据去年的一项大型民意调查,波尔图大约 85%的房屋都接入了高速互联网。Marco 想知道这一比例是否发生了变化,他随机抽样调查了 80 栋房子,发现其中 75 栋可以接入高速互联网。他想用这个样本数据来检验这个比例是否真的发生了变化。假设推断条件满足,考虑到 1%的显著性水*,您对拥有高速互联网的房屋比例会得出什么结论?
  2. 玛尔塔拥有一家水果店,每周都会收到西瓜。供应商声称它们应该重 1 公斤。Marta 决定对随机抽取的 100 个西瓜进行称重,发现*均重量为 850 克,标准偏差为 200 克。她想用这个样本数据来测试*均值是否小于供应商声称的*均值,如果是这样,就重新协商他们的合同。假设推断的条件满足,Marta 应该怎么做(考虑 5%的显著性水*)?

上周的答案

  1. 更改函数confidence_interval_mean_t并构建 5 个不同的实验来计算样本均值的 95%区间,其中 3 个不满足 t 区间的条件,2 个满足。对于不满足条件的 3,定义以下情况:抽样不随机,原始分布不*似正态,不满足独立性。对于满足条件的两种情况,定义一种情况下原始分布是正态分布,另一种情况下原始分布是偏斜的,但采样均值是正态分布。对于后两种情况,真正的总体均值应该包含在 95%的计算置信区间内。

提示:您可能会发现使用 *scipy* 中的 *skewnorm* 函数很有用。下面,您有一个正态分布的修改版本,由偏斜度参数、*均值和标准偏差来偏斜。

# code adapted from https://stackoverflow.com/questions/49367436/scipy-skewnorm-mean-not-matching-theory

skew = 4.0
mean = 2
stdev = 0.5

delta = skew / math.sqrt(1\. + math.pow(skew, 2.))
adjStdev = math.sqrt(math.pow(stdev, 2.) / (1\. - 2\. * math.pow(delta, 2.) / math.pi))
adjMean = mean - adjStdev * math.sqrt(2\. / math.pi) * delta

print('target mean={:.4f} actual mean={:.4f}'.format(mean, float(skewnorm.stats(skew, loc=adjMean, scale=adjStdev, moments='mvsk')[0])))
print('target stdev={:.4f} actual stdev={:.4f}'.format(stdev, math.sqrt(float(skewnorm.stats(skew, loc=adjMean, scale=adjStdev, moments='mvsk')[1]))))target mean=2.0000 actual mean=2.0000
target stdev=0.5000 actual stdev=0.5000# Original skewed distribution

plt.hist(skewnorm.rvs(a = skew, loc=adjMean, scale=adjStdev, size=2000), bins=50);

# Approximately normal distribution of the sample mean because sample 
# size is bigger than 30 (CTL applies)

plt.hist(np.mean([skewnorm.rvs(a = skew, loc=adjMean, scale=adjStdev, size=35) for _ in range(2000)], axis=1), bins=50);

def confidence_interval_mean_t(μ, σ, n, number_trials, N, ci=0.95, sample='random', dist='normal'):

    skew = 4.0
    mean = μ
    stdev = σ

    delta = skew / math.sqrt(1\. + math.pow(skew, 2.))
    adjStdev = math.sqrt(math.pow(stdev, 2.) / (1\. - 2\. * math.pow(delta, 2.) / math.pi))
    adjMean = mean - adjStdev * math.sqrt(2\. / math.pi) * delta

    if dist!='normal':
        x_ = skewnorm.rvs(a = 4, loc=adjMean, scale=adjStdev, size=N)
    else:
        x_ = norm.rvs(loc=μ, scale=σ, size=N)

    x_hat_list = []
    SE_hat_x_list = []

    if sample!='random':
        # Inducing bias on the sampling
        x_.sort()
        x_ = x_[:-int(0.2*N)]
        np.random.shuffle(x_)

    for i in range(number_trials):
        s_ = np.random.choice(x_, n, replace=False)
        x_hat = np.mean(s_)
        x_hat_list.append(x_hat)
        SE_hat_x_list.append(t.ppf(ci+(1-ci)/2, df=n-1)*np.std(s_)/np.sqrt(n))

    plt.hist(x_hat_list, bins=50)

    j=0
    _, ax = plt.subplots(1, 1, figsize=(6, 8))
    for i in range(len(x_hat_list)):
        if (μ>x_hat_list[i]-SE_hat_x_list[i]) & (μ<x_hat_list[i]+SE_hat_x_list[i]):
            # interval contains p
            if i > len(x_hat_list)-50:
                ax.errorbar(x_hat_list[i], np.arange(len(x_hat_list))[i],lolims=True, xerr=SE_hat_x_list[i], yerr=0.0, linestyle='', c='black')
            j +=1
        else:
            # interval does not contain p
            if i > len(x_hat_list)-50:    
                ax.errorbar(x_hat_list[i], np.arange(len(x_hat_list))[i],lolims=True, xerr=SE_hat_x_list[i], yerr=0.0, linestyle='', c='red')
    ax.axvline(μ, color='darkorange')
    #plt.xlim(0,1)
    plt.show()
    print(f'{j}/{number_trials}={np.round(j/number_trials,2)}')# Not random sampling
confidence_interval_mean_t(μ=2, σ=0.5, n=35, number_trials=1000, N=500, sample='not_random')

191/1000=0.19# not approximately normal dist
confidence_interval_mean_t(μ=2, σ=0.5, n=15, number_trials=1000, N=500, dist='not normal')

944/1000=0.94# not independent samples
confidence_interval_mean_t(μ=2, σ=0.5, n=150, number_trials=1000, N=600, dist='not normal')

973/1000=0.97# Not normal distribution but n >= 30, so CTL applies; all other conditions are met
confidence_interval_mean_t(μ=2, σ=0.5, n=35, number_trials=1000, N=500, dist='not normal')

947/1000=0.95# Original distribution is normal; all other conditions are met
confidence_interval_mean_t(μ=2, σ=0.5, n=35, number_trials=1000, N=500)

930/1000=0.93

虽然最讨厌,显著性测试仍然是有用的

原文:https://towardsdatascience.com/significance-testing-2e5a0e546b3a?source=collection_archive---------34-----------------------

即使在复制危机之后,统计学意义仍然是数据科学家需要理解的一个重要概念

照片由来自 PexelsPixabay 拍摄

有许多类型的统计检验 — 零假设显著性检验占主导地位。

使用这种技术,目的是针对无效假设测试观察值。你可以把零假设当成现状。它代表干预不起作用的情况。

显著性测试上升到卓越的地位,因为它是一种对从大量人口中提取的数据子集进行推断的有用方法。本文将增强您对这种有用的数据科学技术的直觉。

概观

研究者进行零假设检验的目的是评估零假设是否可以被拒绝。这需要一个称为显著性水*α(⍺)的概率阈值。该值通常设置为 0.05,代表拒绝干预无效的零假设所需的证据水*。

0.05 的显著性水*意味着如果我们运行测试 100 次,我们可以预期 100 次中有 5 次错误地拒绝零假设。换句话说,在没有实际效果的情况下,我们有 5%的时间错误地报告干预有效果。

为了使测试更加严格,研究人员只需将 alpha 值从标准的 0.05 降低到 0.01 或更低。不同的科学学科有不同的设定 alpha 的标准。在粒子物理学中,测量是非常精确的,alpha 可能被设置为 0.000001。相比之下,在社会科学中,0.05 的 alpha 值被认为是可以接受的。

拒绝零假设

假设检验导致 p 值的计算。在我定义这个术语之前,请观看一群统计学家试图这样做的视频:

https://fivethirtyeight.abcnews.go.com/video/embed/56150342

欢迎回来,心情沉重的旅行者,来到由内特·西尔弗和团队揭露的奇异之地。你仍然想要一个 p 值的定义吗?

好吧,好吧:

假设零假设是正确的,得到结果的概率至少与观察到的结果一样极端

作为研究人员斯图尔特·巴克的进一步解释:

p 值不会告诉你硬币是否公*,但它会告诉你如果硬币是公*的,你得到的人头至少和你得到的一样多的概率。

记住这些技术和功能定义,让我们继续理解 p 值如何用于显著性检验。

p 值小于或等于α表示我们可以拒绝零假设,并说结果具有统计显著性。在这种情况下,证据有利于另一种假设——尽管我们绝不会说我们接受另一种假设——️️⛔️

没有。多亏了统计学,我们陷入了笨拙的双重否定:我们 拒绝零假设

这实际上非常重要,因为在科学上,基本上不可能证明干预是有效的。回想一下你三年级的科学老师解释重力只是一个理论——不管你多少次把书从桌子上摔下来,你都无法最终证明另一个假设,即重力起作用并且总是会让你的书落下。

当我们执行零假设显著性检验时,在评估零假设时,我们可能会犯两个潜在的错误。如果无效假设被错误地拒绝(即我们认为疫苗是有效的,而事实上它不是),我们就犯了1 型错误假阳性。相反,如果我们未能拒绝零假设,而事实上我们应该拒绝(即我们认为疫苗无效,而事实上是),我们就犯了2 型错误假阴性

克里斯·阿尔邦创造了一个方便的图形来帮助我们区分这两者:

通过机器学习抽认卡

显著性测试词汇

  • 假设:基于观察数据可检验的陈述
  • 零假设:被测效应等于零的默认假设
  • 显著性水*(⍺) :研究者设置的阈值,代表当零假设为真时拒绝零假设的概率
  • p 值:在特定的统计模型下,数据的统计汇总(例如,两个比较组之间的样本均值差异)等于或大于其观察值的概率;如果 p ≤ ⍺,我们可以拒绝零假设,说结果是有统计学意义的
  • 替代假设:与原假设相反
  • 第一类错误:拒绝事实上为真的原假设;也称为假阳性
  • 第二类错误:当原假设事实上为假时,未能拒绝原假设;同样假阴性

关于显著性检验的警告

请注意,零假设显著性检验的方法受到了攻击,原因有很多:

🔥首先,众所周知,p 值很难解释。将科学方法的基本概念建立在专家们难以表达而普通大众难以理解的概念上是很棘手的。

🔥第二,正如在这篇文章的描述中提到的,p 值在 2010 年代中期动摇社会科学的复制危机中发挥了作用。术语 p-hacking 是指操纵数据或分析直到 p 值符合统计显著性所需的小于α水*的做法。心理学家 Brian Nosek 的创意项目再现性项目显示,在 100 个被评估的心理学发现中,只有 36%在重复时产生了具有统计学意义的结果。

🔥第三,存在好的替代原假设显著性检验的方法,包括:https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1473027/【置信区间】【有点精确的结果检验(SPOT)

**

摘要

最后,我引用一下安妮·杜克的话,她是扑克冠军,也是下注思考的作者:

尽管人们普遍认为我们通过积极的想象获得成功,但事实证明,融入消极的想象会让我们更有可能实现我们的目标。

在生活中,就像在数据科学中一样,从我们的模型不起作用、我们的干预不起作用、现状不会被新事件打破的假设出发是有用的。

零假设显著性测试从这个前提开始,并要求研究者找到足够的证据来拒绝现状。尽管最令人讨厌,显著性测试仍然是数据科学家需要理解的一种有用的方法。**

更多文章促进您的数据科学

** </10-python-skills-419e5e4c4d66> **

数据可视化工具使用不当的迹象

原文:https://towardsdatascience.com/signs-you-are-using-data-visualization-tools-wrong-121220696500?source=collection_archive---------7-----------------------

凯·皮尔格Unsplash 上的照片

以及取而代之做什么

随着公司每天收集和分析更多的数据以支持数据驱动的决策,更多的员工应该具备挖掘和理解数据的能力。同时,期望公司里的每个人都知道 SQL 并能够直接从数据库中提取数据是不现实的(这难道不是梦想的世界吗?).低代码或无代码的数据可视化工具来救援;随着拖放功能和圆滑的可视化,他们都是这些天的炒作。

Looker 和 Tableau 是低代码数据可视化领域的两大玩家。如果你以前用过这些工具中的任何一种,你知道它们非常容易上手;用户可以在不知道如何在 SQL 中使用“分组的情况下获得按不同维度汇总的数据,在不知道如何用代码将纬度/经度转换为地理点的情况下获得绘制在地图上的需求趋势,等等。

这些工具很棒…如果你使用正确的话。但是一次又一次,我观察到数据用户,甚至是数据科学家和数据分析师,没有充分利用这些工具所提供的功能,并因此减缓了数据的消费和分析。

  1. 您的仪表板包含相同数据聚合的无限变体(将可视化工具视为静态报告)

大多数低代码可视化工具可以做的最有用的事情之一是能够将粒度数据聚合到不同的级别——天、周、一周中的某一天,等等;从一个聚合切换到另一个聚合通常只需要点击一下。这个功能应该使不熟悉 SQL 的人能够以他们自己的方式快速浏览数据。但是我看到许多组织只将数据可视化工具用作静态报告——数据团队开发每日视图,却被要求开发每周视图、每月视图和年度视图。

不要误解我的意思,数据可视化工具肯定可以用作静态报告工具,但这不应该是它的唯一用例。对于大多数高级领导成员来说,具有多个聚合的静态报告是正确的选择。但对于公司的其他人来说,为数据用户提供他们应得的自由可以节省数据团队和其他人大量的时间和精力,并使整个公司的团队能够更快地前进。

改做什么:

如果你给一个人一条鱼,你可以喂他一天。如果你教一个人钓鱼,你就喂了他一辈子。

向非数据团队用户展示该工具的基础知识,以便他们能够自己进行过滤和汇总。这不仅在数据探索方面给用户更多的灵活性,而且有助于在公司建立数据文化。

2。你只有一小部分人在开发仪表盘

上面的第一点是这个问题的一个症状。因为公司的其他人无法使用这些数据可视化工具的基础,所以开发工作就落在了一个小型的、有能力的团队身上——通常是数据团队。这创造了关于数据和可视化的孤立的部落知识。鉴于如今的高损耗率,数据知识随时都有丢失的危险。

这也违背了在您的公司中使用低代码或无代码数据可视化工具的目的,考虑到它们的主要创新是使数据探索对具有有限先决知识的广泛用户群可用。

改做什么 : 除了上面已经提到的,向公司更多的人开放编辑权限;对于技术水*较低的团队来说,学习如何在这些工具中构建仪表板是一个很好的拓展机会。与此同时,您可能希望让数据专家随叫随到,以防该工具的新手破坏了某些东西。

3。工具中的业务逻辑太多

大多数数据可视化工具都位于数据仓库之上。

这些工具通常为定制提供大量空间,这意味着您可以进行数据操作,并在将数据仓库中的数据表转化为可视化之前在其上构建业务逻辑。

这种定制能力可以让团队保持敏捷,因为如果他们熟悉工具但不熟悉 SQL,他们不必总是等待数据团队在数据仓库的表中实现某些业务逻辑;他们可以在 Looker 里做。

但是这种灵活性是有代价的——错误的空间和同一指标的多个真实来源。

举一个具体的例子:假设数据仓库中有一个包含优步旅行信息的表,它包含旅行持续时间(以分钟为单位)和旅行距离(以英里为单位)。

一名团队成员创建一个 Looker 视图文件,该文件将“*均行程长度”定义为以分钟为单位的持续时间,而另一名团队成员在另一个文件中创建一个定制的测量“*均行程长度”作为*均行程距离。两者都开始开发显示“*均行程长度”的可视化工具;他们的数字肯定不会匹配,这势必会在使用这些仪表板的人中间造成混乱。

改做什么:

使用 Looker 测试业务逻辑或进行一次性分析。对于应该长期使用的业务逻辑,最好求助于您的数据团队,将它们嵌入到数据仓库的数据表中,以确保一致性。

这不仅将确保在涉及某些定义时有一个真实的来源,而且很可能有其他团队可以从这种实现中受益,而不必重新发明轮子。

4。您的仪表盘不会讲述一个故事

当我第一次开始使用可视化工具时,我肯定犯了这个错误。仪表板没有整体视图或设计;相反,它是不同图表的大杂烩,是随着时间的推移,利益相关者不断请求添加和更改的结果。

结果呢?识别关键信息非常困难且耗时。

一个好的仪表板讲述一个故事,充满了洞察力和评论,将用户的注意力引向重要的地方。

改做什么:

只要记住一件事——使用注释。使用注释对可视化进行分组,讲述一个故事并指出注意事项。更好的是,内置带有说明的注释,这样用户就知道如何浏览/过滤/导航仪表板,而不需要放松它的所有者。如果仪表盘因为你不断添加更多的视图而变得过于臃肿,那么值得后退一步,重新定义仪表盘的用途,减少混乱(或者将仪表盘分成多个更窄、定义更清晰的焦点)。

5。您没有详细探索工具的功能

我明白,有时即使对于熟悉编程语言的数据科学家和数据分析师来说,学习可视化工具的定制也是一件苦差事。

但是我鼓励您给它一个机会,阅读一些文档;你会发现它们有无穷无尽的功能可以探索。例如,如果你不知道如何在 Tableau 或 Looker 中做一些事情,坚持你已经知道的东西并在 R Shiny 中建立可视化会很有诱惑力。但是相信我,花时间掌握这些可视化工具将会有回报,因为它们比乍看起来更强大。

改做什么:

很简单,不要害怕学习新的东西,花一些时间阅读文档,成为该工具的专家。这一初始投资将为您节省大量时间,因为一旦您掌握了窍门,在 Looker 或 Tableau 中实现许多东西要比从头开始编码容易得多。

不知道接下来要读什么?您可能会对以下数据科学相关文章感兴趣:

</5-lessons-mckinsey-taught-me-that-will-make-you-a-better-data-scientist-66cd9cc16aba> [## 麦肯锡教给我的 5 条经验将使你成为更好的数据科学家

towardsdatascience.com](/5-lessons-mckinsey-taught-me-that-will-make-you-a-better-data-scientist-66cd9cc16aba) https://medium.com/geekculture/avoid-these-five-behaviors-that-make-you-look-like-a-data-novice-40f01158ae00

人工智能给云带来一线希望

原文:https://towardsdatascience.com/silver-lining-clouds-with-ai-ff6a234786e2?source=collection_archive---------20-----------------------

思想和理论

星云计划,通过卷积神经网络的云分割应用

作者

扬恩·伯纳利卢多维奇·钱翁凯茜·拜诺-萨姆森何塞·卡斯特罗

来自 Pexels詹姆斯·惠勒的照片

F 鱼、花、石子、糖……这绝不是随机盘点,而是云形成的命名。根据它们的形状命名,它们可能对地球气候理解有很大的兴趣。

这与这些浅云的矛盾特征有关:对地球辐射*衡的重要影响和不愿建模。早在 2019 年,马克斯·普朗克气象研究所就通过 Kaggle 比赛的方式向数据科学家社区发起了挑战。目标:在先前由一个专家小组标记的卫星图像上确定和定位上述四类云。实际的项目不是假装直接解决气候变化,尽管我们认为这有助于更好地理解气候。

美国宇航局在地球观测系统数据和信息系统(EOSDIS) 上拍摄的照片,非版权材料

下面的文章将介绍这种图像分割情况的解决方案。有关基本假设,请参见参考资料。该项目及其成果是来自数据科学研究所的数据科学家培训课程的一部分。

本文末尾给出了关于数据集的更多信息。

您可以随意探索和使用演示来查看运行中的模型:星云项目演示

分析局限性

根据专家们对许多云形成的位置和性质的分歧,我们推断类别特征可能是模糊的。探索性分析证明我们是对的。无论是云的表面,还是图像的白色比例,都无法让我们确定每一类的特征。对图像灰度的分析最终说服我们将像素亮度分开。为了定位类别,我们需要在图像中寻找模式,并因此使用更智能的计算技术:卷积神经网络(又名 CNN)。

内存限制迫使我们使用参数尽可能少的网络。通过迭代,我们选择了其中的两个:安装在 UNet 架构内的 ResNet 18 主干和安装在 LinkNet 架构内的 EfficientNet B1 主干。这两个模型分别计算 1400 万和 850 万个参数。该项目的一个核心思想是利用两种不同的模型,以建立各自的优势。在这个框架中,损失函数和模型优化器的选择与它们各自的体系结构不同。

下表总结了最终模型的主要特征。

作者图

在使用之前,所有图像都从 1400x2100 像素缩小到 320x480 像素,然后通过垂直和水*对称、10°以下旋转和伽马校正进行放大。这最后一次增强是特别选择来补偿在许多图像上明显的太阳步幅。第一个模型受益于在有限数量的时期内对噪声过滤图像的预训练阶段。这将有助于模型在主要训练期间关注低层云的特征。

这样美好的婚礼

对这两个模型的评估产生了接*的*均性能。每一个在某些职业中更强一点。因此,最终的预测来自于婚礼或共识。跨模型对每个像素属于一个类别的预测概率进行简单的算术*均。然而,似乎云模糊模式和硬件限制都需要纠正。这是通过两种后处理技术实现的:像素激活和表面滤波。

作者的预测管道图,NASA 在地球观测系统数据和信息系统(EOSDIS) 上的照片,非版权材料

照亮我的像素

像素级别的预测通过其属于当前类别的概率来识别。默认阈值为 0.5,这意味着只要概率高于 50%,像素就属于该类。现在很容易理解云的形成有不同的结构:糖类似乎比鱼更稀疏。这导致糖的激活阈值较低,或者激活区域较宽。

通过对来自训练集的 30 批 64 幅图像进行采样来识别最佳阈值。

美国宇航局在地球观测系统数据和信息系统(EOSDIS) 上拍摄的照片,非版权材料

清洁表面

从先前操作得到的掩模可以是从一个像素到整个图像的所有可能的尺寸。为了从实际的云中过滤数字伪影,详细阐述了校准操作。计算了一个简单且任意的规则,以避免在过度拟合数据时被当场抓住。基于训练集,为每个类确定第 15 个百分位数的表面大小。最后,删除所有低于阈值的预测曲面。

几个预测

考虑到一张图片胜过千言万语,我们收集了以下几个预测。第一行显示由于太小而被过滤的糖(黄色)和砾石(绿色)表面。第二行显示了 Sugar 类的轻微调整,这是由于降低了激活阈值。

美国宇航局在地球观测系统数据和信息系统(EOSDIS) 上拍摄的照片,非版权材料

评估和结果

评估是基于一个保留的 224 图像集进行的,两个模型都不知道。评估综合如下表所示。

注:如结果表中所述,所选指标是骰子系数或 f1 分数

除了 Fish 类,我们可以看到模型集和后处理都提高了原始模型的个体性能。即使改进看起来很大,我们也要记住,测试是在有限的 224 个图像集上进行的。

作为奖励,Kaggle 竞赛的迟到提交确认了我们的方法性能,授予我们虚拟的第 74 位(在 1500 名贡献者中)。公开分数是 0.66173,而私下分数是 0.66016。

我们的策略在测试和训练数据集上显示了准确的结果。对完全不同的图像进行模型推断是我们进行的最后一项测试。在这个画面中,我们扫描了世界各地的其他地点。该模型能够识别它所训练的云,结果似乎是一致的。请看下面的几个例子。

美国宇航局在地球观测系统数据和信息系统(EOSDIS) 上拍摄的照片,非版权材料

作为结论,我们提出所提出的解决方案在硬件限制方面是有效的。在目前的框架内,仍有可能进一步改进,因为仍存在许多轨道。例如,对在调整图像尺寸期间使用的图像插值方法进行彻底的分析,或者使用梯度累积技术以实现更密集的模型架构。最后,我们已经获得了强有力的证据,证明我们的模型有潜力进入上述 Kaggle 竞赛的前 10 名。

结论

从卫星图像中收集新数据,这些数据如此重要,以至于我们能够了解我们的星球,用类似人类的模式识别能力分析甚至最模糊的实体,如云,并将其应用于几乎无限量的图像…

所有这些都可以通过每个人都可以使用的深度学习技术来实现。与大数据相结合,一切都朝着卫星图像领域的重大扩展方向汇聚,这将极大地改善我们对环境的理解。

致谢

首先,我们要感谢整个 DataScientest 团队在过去几个月中提供的宝贵帮助和支持。

DataScientest.com 学院的数据科学家学位课程让我们获得了丰富多样的知识。这是在像现在这样的数据科学项目中保持自主和关键的先决条件。

我们的团队是由四个人组成的,彼此都不认识。由于地理距离和封闭,我们很少有机会见面,而且…我们还没有。在我们为期八个月的项目中,每个人的投资都是成功的关键。

成功的数据科学项目的另一个关键是数据管理。利用 Google Colab / Drive 作为主要*台,Github 作为笔记本和库的版本化工具,我们能够支持从最初的学习步骤到更复杂的最终步骤的整个项目。

我们感谢使用来自 NASA Worldview 的图像,这是 NASA 地球观测系统数据和信息系统(EOSDIS)的一部分。

最后但同样重要的是,感谢您的阅读。我们希望你和我们一样享受完成整个工作的经历。如需更多信息,请随时联系我们。

数据集

本文讨论的 Nebula 项目仅用于教育目的。

本项目使用的数据集可从 Kaggle 竞赛主页获得。

数据选自三个地区,横跨 21 度经度和 14 度纬度。更多的细节可以从 Rasp,Schulz,Bony 和 Stevens 的研究中获得,在本文的参考文献部分提到[1]。

正如 Kaggle 数据描述中提到的,组成数据集的图像是从 NASA Worldview 下载的。因此,数据受制于以下条款和条件:美国宇航局地球科学数据

参考文献

[1] Rasp,Schulz,Bony 和 Stevens,结合众包和深度学习探索浅对流的中观尺度组织 (2019)

用你的销售数据建立一个产品推荐系统

原文:https://towardsdatascience.com/similar-product-recommendations-data-to-deployment-970a085bafce?source=collection_archive---------5-----------------------

约翰·福勒在 Unsplash 上的照片

简介

这是一篇分享我从头到尾实现一个产品推荐系统的帖子。我构建的推荐系统是基于条目-条目协同过滤的。我们将通过共生矩阵构建产品的多维向量表示,并通过所有产品向量之间的余弦相似性来寻找相似的产品。

在应用方面,该系统旨在为电子商务产品提供产品推荐。例如,当客户点击某个产品时,大多数网站会显示一个产品详情页面(PDP),通常您可能会在该页面上看到更多共享的产品,标题为“您可能也喜欢““类似产品”

概念

同现矩阵

我不会深入到同现矩阵的细节,因为这是已经写了很多的东西。但是我将从概念上介绍共现矩阵是如何工作的,以及为什么我们可以使用它来创建类似产品的推荐系统。我们正在利用的数据只是客户订单数据,特别是我们感兴趣的是产品与其他产品一起购买的订单。

简化示例

在我们的简化示例中,我们在整个历史中只有两个订单:

作者图片

我们有 3 个独特的项目,两个不同颜色的牙刷都是独立购买的牙膏。利用这些信息,我们能够通过牙膏建立从蓝色牙刷到绿色牙刷的桥梁。

作者图片

现在想象一下,我们有成千上万的订单。你可能会认为两种颜色的牙刷都和牙线、漱口水等一起出现。我们可以利用这些产品的共现来构建目录中所有产品的多维向量表示。

余弦相似度

为了确定一个产品是否与另一个产品相似,我们从我们的共现矩阵中获取它们的向量表示之间的余弦相似性,并得到-1 和 1 之间的分数。分数为 1 表示向量方向相同,分数为-1 表示向量方向相反。你可以在这里找到余弦相似度的细节。

数据

如前所述,我们的数据是客户订单数据。对于大多数数据集,您可能希望将一个订单级表连接到一个订单行级表,以便可以看到特定订单 id 中出现的所有项目。

作者图片

模型代码

库依赖:

import pandas as pd
import numpy as np
import s3fs
import json
from sklearn.metrics.pairwise import cosine_similarity
import datetime

首先以上面的格式加载您的客户订单数据,作为名为 sales_df 的 pandas 数据框。

加载数据后,您需要将数据转换为每行是一个订单,每列是一个产品,值是每个订单中产品的数量。注意:pandas 会自动将 pivot 中的数据类型更改为 float64。如果你有内存方面的考虑,你可能想向下传输数据

pivot_df = pd.pivot_table(sales_df,index = 'order_id',columns = 'product_id',values = 'category',aggfunc = 'count')pivot_df.reset_index(inplace=True)
pivot_df = pivot_df.fillna(0)
pivot_df = pivot_df.drop('order_id', axis=1)

接下来,我们通过获取数据透视表及其转置的点积,将数据透视表转换为共生矩阵。

co_matrix = pivot_df.T.dot(pivot_df)
np.fill_diagonal(co_matrix.values, 0)

为了将共现矩阵转换为我们产品之间的余弦相似度矩阵,我们利用了来自 sklearn余弦相似度函数。

cos_score_df = pd.DataFrame(cosine_similarity(co_matrix))
cos_score_df.index = co_matrix.index
cos_score_df.columns = np.array(co_matrix.index)

产品 x 产品余弦相似性得分

模型验证

与大多数无监督学习模型一样,模型验证可能很棘手。对于我们的数据集,我们有一组不同的产品类别。由于我们正在创建一个推荐器来显示类似的产品,我们应该期望我们的模型返回与原始基本产品在同一类别的推荐。

针对每个产品类别:

计数(类别中每个产品的最佳推荐)/计数(类别中的产品)= %相同类别中的推荐

举例:

我们为 735 种健康产品生成了建议,根据我们对每种健康产品的最佳余弦相似度,我们有 720 种建议属于健康类别,或 98%的同类建议。有了如此高比例的同类推荐,我们可以更加自信地认为,我们的购买数据中有一个强大的信号来推动我们的模型。

下一步

从这里开始,一旦我们将模型的第一个版本推广到生产,并开始 AB 测试,模型验证将继续进行。迭代模型时的一些参数调整考虑事项将有一个余弦相似性得分阈值或样本大小阈值,以将建议限制在我们有最高置信度的范围内。

部署

我们的部署过程相当简单。我们将带有前 n 条建议的 JSON 文件输出到 S3 桶中。这个 JSON 文件然后被我们的*台工程团队提取出来,并加载到 Postgres 数据库中,该数据库将用于前端产品服务。

得分最高的五个推荐和 JSON 输出:

#Take top five scoring recs that aren't the original productproduct_recs = []
for i in cos_score_df.index:
    product_recs.append(cos_score_df[cos_score_df.index!=i][i].sort_values(ascending = False)[0:5].index)

product_recs_df = pd.DataFrame(product_recs)
product_recs_df['recs_list'] = product_recs_df.values.tolist()
product_recs_df.index = cos_score_df.index#Semi-colon delimited JSON Outputproduct_recs_df['json_out'] = product_recs_df['recs_list'].apply(lambda x: [str(element) for element in x])
product_recs_df['json_out'] = product_recs_df['json_out'].apply(lambda x: ";".join(x))
product_recs_dict = product_recs_df.to_dict()
json_out = json.dumps(product_recs_dict['json_out'],indent = 4,ensure_ascii = False).encode('UTF-8')

将 JSON 输出到 S3 桶:

ts = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M")fs = s3fs.S3FileSystem(key=s3_key, secret=s3_value)
with fs.open('s3://yourbucket/key'+ts+'.json', 'wb') as f:
    f.write(bytes(json_out))

结论

因此,我们已经为类似产品创建了一个端到端的产品推荐系统,只需使用历史销售数据。对于所有模型,模型输出的质量将取决于数据的质量。一般来说,每种产品的订单样本越大越好;因为我们期望在较大的样本量下减少来自随机产品共现的噪声。要为您的模型找到正确的样本大小阈值,您可以在不同的样本阈值下评估模型验证指标(同一类别中建议的百分比),以查看在哪个阈值下评估指标开始出现有意义的下降。

使用 dirty_cat 对脏类别进行相似性编码

原文:https://towardsdatascience.com/similarity-encoding-for-dirty-categories-using-dirty-cat-d9f0b581a552?source=collection_archive---------14-----------------------

实践教程

在对脏类别进行编码时,这是一种比一键编码更好的替代方法

作者图片

动机

假设您的任务是预测蒙哥马利县员工的工资。你的employee_position_title专栏看起来像这样:

Office Services Coordinator
Master Police Officer
Social Worker IV
Resident Supervisor II
Police Officer III
Police Aide

由于许多机器学习算法只处理数字数据,因此将employee_position_title变量转换为数字形式非常重要。

为此,一种常见的方法是使用一键编码来处理名义数据。当应用独热编码时,每个类别将被表示为 0 和 1 的数组。

例如,在下表中,Office Service Coordinator被表示为[0,1,0,0,0,0]Master Police Officer表示为[1,0,0,0,0,0]

作者图片

然而,单热编码不能捕捉脏类别之间的相似性,例如Master Police OfficerPolice Officer III

有没有一种方法,我们可以编码这些类别,同时捕捉它们之间的相似之处,如下所示?这时 dirty_cat 的相似性编码就派上用场了。

作者图片

什么是 dirty_cat?

dirty_cat 帮助对脏类别进行编码。脏分类数据可以是:

  • 拼写错误(技术人员而不是技术人员
  • 额外信息(职位和级别首席警官,而不仅仅是职位警官
  • 缩写(高级代替高级
  • 级联分层数据(国家-州-城市 vs 州-城市)

在本文中,我将向您展示如何使用 dirty_cat 对脏类别应用相似性编码。要安装 dirty_cat,请键入:

pip install dirty_cat

相似性编码

开始

首先导入 employee _ salaries 数据集,该数据集包含蒙哥马利县 9000 多名雇员的年薪信息。

请注意,employee_position_title中的一些类别如Accountant/Auditor IAccountant/Auditor II是相似的。为了捕捉脏类别之间的相似性,我们将使用 dirty_cat 的SimilarityEncoder

让我们使用SimilarityEncoderemployee_position_title列的前 10 行进行编码。

array(['Office Services Coordinator', 'Master Police Officer',
       'Social Worker IV', 'Resident Supervisor II',
       'Planning Specialist III', 'Police Officer III',
       'Accountant/Auditor II', 'Administrative Specialist II',
       'Firefighter/Rescuer III', 'Police Aide'], dtype=object)
array([[0.05882353, 0.03125   , 0.02739726, 0.19008264, 1\.        ,
        0.01351351, 0.05555556, 0.20535714, 0.08088235, 0.032     ],
       [0.008     , 0.02083333, 0.056     , 1\.        , 0.19008264,
        0.02325581, 0.23076923, 0.56      , 0.01574803, 0.02777778],
       [0.03738318, 0.07317073, 0.05405405, 0.02777778, 0.032     ,
        0.0733945 , 0\.        , 0.0625    , 0.06542056, 1\.        ],
       [0.11206897, 0.07142857, 0.09756098, 0.01574803, 0.08088235,
        0.07142857, 0.03125   , 0.08108108, 1\.        , 0.06542056],
       [0.04761905, 0.3539823 , 0.06976744, 0.02325581, 0.01351351,
        1\.        , 0.02      , 0.09821429, 0.07142857, 0.0733945 ],
       [0.0733945 , 0.05343511, 0.14953271, 0.56      , 0.20535714,
        0.09821429, 0.26086957, 1\.        , 0.08108108, 0.0625    ],
       [1\.        , 0.05      , 0.06451613, 0.008     , 0.05882353,
        0.04761905, 0.01052632, 0.0733945 , 0.11206897, 0.03738318],
       [0.05      , 1\.        , 0.03378378, 0.02083333, 0.03125   ,
        0.3539823 , 0.02631579, 0.05343511, 0.07142857, 0.07317073],
       [0.06451613, 0.03378378, 1\.        , 0.056     , 0.02739726,
        0.06976744, 0\.        , 0.14953271, 0.09756098, 0.05405405],
       [0.01052632, 0.02631579, 0\.        , 0.23076923, 0.05555556,
        0.02      , 1\.        , 0.26086957, 0.03125   , 0\.        ]])

解释

请注意,输出中有 10 行和 10 列,这表示不同类别对之间的相似性。这有点类似于一键编码,但是相似性编码采用 0 和 1 之间的值,而不是二进制值 0 或 1。

相同的字符串将具有等于 1 的相似度,非常不同的字符串将具有接* 0 的相似度。为了更好地理解这种关系,我们来形象化一下。

作者图片

从上面的矩阵中我们可以看出,

  • 相同的字符串如Office Services CoordinatorOffice Services Coordinator之间的相似度为 1
  • 有些相似的字符串如Office Services CoordinatorMaster Police Officer之间的相似度为 0.41
  • 两个非常不同的字符串如Social Worker IVPolic Aide之间的相似度是 0.028

看起来相似性编码很好地捕捉到了每一对类别之间的相似性!两个字符串的差异越大,它们的相似性得分就越小。

一次性编码与相似性编码

现在,让我们比较一次性编码和相似性编码在预测雇员工资方面的性能。

为此,我们将对employee_position_title列应用两种不同的编码方法,即一次性编码相似性编码

我们使用一键编码来编码干净的分类列,如genderdepartment_nameassignment_category,并保持数字列Year First hired不变。

源代码

然后我们使用ColumnTransformer将这些处理方法应用到每一列。

源代码

现在我们将创建两个管道,一个使用一热编码,另一个使用相似编码来编码employee_position_title列。然后用cross_val_score来评估各个管道的性能。

源代码

one-hot encoding
r2 score:  mean: **0.856**; std: 0.034

similarity encoding
r2 score:  mean: **0.915**; std: 0.012

酷!使用相似性编码的流水线的 R 分数比使用一位热码编码的流水线高 0.059。

dirty_cat 是否提供其他编码方式?

是啊!还有其他的编码方法,我不能在这里介绍,包括GapEncoderMinHashEncoderTargetEncoder。我鼓励您在 dirty_cat 的文档中阅读更多关于它们的内容。

作者图片

结论

恭喜你!您刚刚学习了如何使用 dirty_cat 的SimilarityEncoder对脏分类特征进行编码。下一次当你看到肮脏的分类列时,你就不会害怕它们,知道该怎么做了。

随意发挥,并在这里叉这篇文章的源代码:

https://github.com/khuyentran1401/Data-science/blob/master/feature_engineering/dirty_cat_example/employee_salaries.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

参考

切尔达大学、瓦洛夸大学和凯格尔大学(2018 年)。脏分类变量学习的相似性编码。机器学习,**107(8–10),1477–1494。doi:10.1007/10994–018–5724–2

服装相似性学习:从零开始构建 web 服务

原文:https://towardsdatascience.com/similarity-learning-for-clothing-building-a-web-service-from-scratch-350216830e21?source=collection_archive---------21-----------------------

涵盖从建模到部署的所有内容的简要指南

自由股票Unsplash 上的照片

动机

我曾多次想到可以找到相似衣服的神奇工具,这令人担忧。

让我们想象一种情况:你正在 Instagram 上滚动,突然看到一件惊艳的大衣。如果有一个“我想要这件外套”的按钮,Instagram 商店可以向你推荐这件外套以及一系列类似的外套,也许你会更喜欢。最重要的是,如果你能通过价格范围和品牌来筛选它们,并获得完整的网上购物体验,会怎么样?

也许我根本不用担心。有时候,当我在网上购物时,我唯一需要的就是有人或事来理解我和我的时尚需求。

如果您想获得数据科学方面的端到端经验,请阅读本文并查看 GitHub 上的项目。您将练习从神经网络建模到 docker 部署的所有内容。

什么是相似性

在我的例子中,物品或衣服的特征,比如颜色、形状、类型,可以用数值来表示,它们一起形成一个向量。因此,我们可以构建一个向量空间,其中每一项都有一个对应的向量。

对象的“相似性”将简单地由该空间中这些对象之间的距离来定义。它们之间的距离越小,它们就越相似或相关。

2D 空间中向量的简化可视化,我作者的图像

项目的理念

该项目旨在尽可能简单地实施。因此,为了构建图像向量,我会重新训练一个预先训练好的模型。为了向量存储和相似向量的搜索,我将应用向量搜索引擎。一个简单的 web 界面将建立在一个应用程序框架上,而后端将基于一个用于构建 API 的 web 框架。最后,整个项目将使用 Docker 容器部署在虚拟机上。乍一看,这可能听起来让人不知所措,然而,这并不困难,只需要一步一步地去做。

项目阶段:从想法到应用

关键阶段如下所示:

  1. 查找数据集
  2. 寻找相关的变压器型号
  3. 重新训练模型并评估它
  4. 将模型应用于所有数据并提取数据集的向量
  5. 编码前端和后端,使一个简单的网络界面
  6. 在虚拟机上部署项目。

让我们从第一阶段开始,然后进行其余的。

1 该数据集位于介质上,包含 20 类服装的 5000 张图片。从鞋子到帽子。前 10 个类每个都包含至少 150 个项目。

关于它是如何被收集的更多细节在的文章中。

前 10 个类别的每个类别中出现的项目数,按作者排序的图像

2 Vision Transformer (ViT)是一个基于 Transformer 架构的视觉模型,最初是为基于文本的任务设计的(你可能听说过 BERT)。这是一个非常新的模型,发布于 2020 年 12 月。更多细节在这里。

未经培训,通常不会使用变压器模型。从转换器中直接提取的嵌入或向量可能包含大量不同的参数,对于您正在解决的特定问题,其中一些参数可能比其他参数更重要。

因此,这种模型需要重新训练或微调。根据笔记本中介绍的方法,我想出了以下再培训方案。

再培训计划,作者形象

该模型在预训练的 ViT 模型上使用了线性层。因此,我在[CLS]令牌的最后一个隐藏状态上放置了一个线性层,它很好地表现了整个图像。此外,辍学是为了正规化而增加的。最后一层返回属于某个类别的概率。所添加的线性层的输入可以准确地用作相似性搜索中的对象向量。

模特再培训的完整脚本可在笔记本中找到。

对于模型评估,我使用了两个指标:

  • 比较训练数据集中和测试数据集中的准确性,
  • 比较了微调前后属于同一类的前 N 个邻居的百分比。

我还试验了一些图层的添加和矢量提取。

评估表,作者图片

重新训练(微调)transformer 模型增加了最接*项目的类中的“相似性”:“属于同一类的前 5 个邻居的百分比”从 56.7%提高到 83.4%。

在 ViT 顶部添加 1 个线性层的模型的类别中的“相似性”,图片由作者提供

在模型上增加一个额外的线性层并没有改善任何指标。此外,在重新训练过程中,变压器的权重以及添加层中的权重都进行了调整。由于这个事实,我可以使用添加层的输入作为“相似性”搜索中对象的向量。

在本文的其余部分,我将只提到在预训练模型之上添加了一个线性层的模型。

为了保存添加的线性层的输入,我使用了一个向前的钩子。关于如何使用它的详细指南在文章中提供。

5 为了制作一个简单的网络界面,使用了这个文档。这项工作包括在本地机器上进行的以下步骤:

  • 使用 Streamlit 创建了一个简单的界面来显示图像和维护图像选择。

  • 我已经在 docker 容器中运行了 Qdrant (矢量搜索引擎),创建了一个集合,并在那里添加了矢量。

  • 后端部分使用 FastAPI 编码,包含搜索请求。

  • 类似对象的呈现被添加到前端脚本中。

  • 前端和后端都是在没有 dockers 的情况下调试的

  • 添加了 Docker 文件和 docker-compose.yml,在后者中,我描述了所有的服务和依赖项。有 3 种服务:后端、前端和 qdrant。

  • 我确保所有东西都在本地机器上工作,然后将项目推送到 GitHub 仓库,进入下一个阶段。

6 在虚拟机上部署项目包括以下步骤:

  • 在 Amazon Web Services 上预订免费的 Linux 机器,并添加 HTTP 连接
  • 将 images 和 vectors.json 从本地机器上传到虚拟机。
  • 运行 docker for Qdrant 并使用 vector.json 中的点创建集合。但是,集合可以直接从本地机器上传。
  • 从 GitHub 克隆存储库,调整 python 脚本和 docker-compose.yml。
  • 构建和运行 docker-compose。
  • 享受网络界面。

结果

网页包括:

  • 5 件随机衣服的图片
  • 项目选择器
  • 所选项目的图像(默认情况下是第一个项目)
  • 三件最相似的衣服的图片。

当你选择了一些你喜欢的物品时,页面会显示所选择的物品以及三个最相似的物品。如果你不喜欢任何赠送的衣服,只需点击“显示其他项目”,你会看到其他 5 个项目。即使是我们当中最挑剔的人,我们也希望你不会花太多时间找到真正特别的东西!

相似衣服搜索的网络服务,Gif 作者

下一个视角

类似的衣服有些单品不好看。例如,黑色 t 恤被识别为与灰色 t 恤相似,即使数据集中还有其他灰色 t 恤。我认为背景颜色在这种情况下可能起着关键作用。

表现不好的例子,图片作者

显然,这个模型可以通过对比学习来改进。如果手动选择的“错误”对在数据中被标记,模型可以并且应该学会忽略图像上的背景。

此外,搜索类似的项目可以实现一个全新的项目!只需将模型应用于新图像,接收相应的向量,并在当前基础上运行搜索。从编码角度来看,将这一功能添加到应用服务中非常容易。

如果我有一个网上商店,我也可以实现搜索类似的服装与基本的过滤器,如价格,品牌,交货时间,等等。这就是搜索变得更加有效和精确的原因。请注意,我使用的矢量搜索引擎支持在搜索中应用过滤器。

说了这么多……我相信,通过对我们零售习惯的理解,在人工智能的支持下,网上购物的未来将会得到显著改善。

在这个项目中,我学到了什么

对我来说,这是一次非常紧张和富有成效的旅程。我第一次用变形金刚。我第一次部署了 web 服务。以下是我想与你分享的重大发现:

  1. 最好在本地计算机上调试模型训练,但是在 Google Colab 上训练一个模型。将图像上传到 Colab 需要一段时间,而在本地机器上训练模型则非常耗时。此外,我在 Colab 中对模型进行训练后下载了该模型,并将其应用于本地机器上提取向量。
  2. 微调变压器时,会修正变压器层中的权重。我认为只有增加的层被训练。但是变压器内部也在发生变化。然而,可以配置设置,不允许变压器层改变。
  3. Streamlit 框架不能用于跟踪图片的点击,这就是我使用侧边栏解决方案的原因。该框架也有一些优点,例如,它有一个不错的移动版本,没有任何编码。
  4. Docker 合成是部署中最棘手的部分。原来,从前端到后端的请求可以在 mac 机器上工作,但不能在 amazon ec2 机器上工作。所以它需要一些调整,幸运的是,Linux 的解决方案在 Mac OS 上也能工作。

自然语言处理中的相似性度量

原文:https://towardsdatascience.com/similarity-metrics-in-nlp-acc0777e234c?source=collection_archive---------13-----------------------

欧几里德距离、点积和余弦相似度

作者图片

当我们将语言转换成机器可读的格式时,标准的方法是使用密集向量。

神经网络通常生成密集向量。它们允许我们将单词和句子转换成高维向量——组织起来使得每个向量的几何位置都可以赋予意义。

众所周知的语言算术例子表明女王=国王——男人+女人

有一个特别有名的例子,我们取国王的向量,减去向量男人,加上向量女人。与合成向量最接*的匹配向量是皇后

我们也可以将同样的逻辑应用于更长的序列,比如句子或段落——我们会发现,相似的意思对应于这些向量之间的接*度/方向。

所以,相似性是很重要的——我们将在这里介绍计算相似性的三个最常用的指标。

欧几里得距离

欧几里德距离(通常称为 L2 范数)是最直观的度量。让我们定义三个向量:

三个向量示例

仅仅通过观察这些向量,我们就可以自信地说 ab 彼此更*——当我们在图表上可视化每个向量时,我们会看到这一点更加清晰:

矢量 ab 离原点很*,矢量 c 远得多

显然, ab 靠得更*,我们使用欧几里得距离计算:

欧几里德距离公式

为了将这个公式应用于我们的两个向量, ab,我们做:

计算矢量 ab 之间的欧几里德距离

并且我们得到距离 0.014 ,对 d(a,c) 返回 1.145d(b,c) 返回 1.136 进行同样的计算。显然, ab 在欧氏空间中更*。

点积

欧几里得距离的一个缺点是在计算中没有考虑方向,它仅仅基于大小。这是我们可以使用其他两个指标的地方。第一个是点积。

点积考虑方向(方位),也与矢量幅度成比例。

我们关心方向,因为相似的意思(我们经常会发现)可以用向量的方向来表示——不一定是向量的大小。

例如,我们可能会发现向量的大小与它在数据集中代表的单词的频率相关。现在,单词 hi 的意思与 hello 相同,如果我们的训练数据包含单词 hi 1000 次,而 hello 只有两次,这可能不会被表示出来。

因此,向量的方向通常被认为和距离一样重要(如果不是更重要的话)。

点积的计算公式如下:

点积公式

点积考虑向量之间的角度,其中角度为~0,公式的 cosθ 分量等于~1。如果角度接* 90 度(正交/垂直),则 cosθ 分量等于~0 度,而在 180 度时 cosθ 分量等于~-1 度。

因此, cosθ 分量增加了两个向量之间角度较小的结果。因此,更高的点积与更高的方向相关。

同样,让我们将这个公式应用于我们的两个向量, ab :

计算矢量 ab 的点积

显然,点积计算很简单(三者中最简单的),这在计算时间方面给我们带来了好处。

然而,有一个缺点。它不是归一化的,这意味着较大的矢量倾向于获得较高的点积,尽管不太相似。

例如,如果我们计算a a——我们会期望比 a c 更高的分数( aa 完全匹配)。但不幸的是,事情并非如此。

当向量大小不同时,点积就没那么大了。

因此,实际上,点积用于确定两个向量的大致方向,因为:

  • 指向相似方向的两个向量返回一个正的点积。
  • 两个垂直向量返回的点积。
  • 指向相反方向的向量返回一个负的点积。

余弦相似性

余弦相似性考虑矢量方向,与矢量大小无关。

余弦相似公式

在这个公式中,我们应该注意的第一件事是,分子实际上是点积——它同时考虑了大小方向

在分母中,我们有奇怪的双竖线——这意味着‘长度’。因此,我们将 u 的长度乘以 v 的长度。长度当然要考虑量级

当我们采用一个考虑大小方向的函数,并将其除以一个只考虑大小的函数时,这两个大小相互抵消,留给我们一个考虑方向 与大小无关的函数。

我们可以把余弦相似度看成是归一化点积!这显然是有效的。 ab 的余弦相似度接* 1 (完美):

计算向量 ab 的余弦相似度

并且使用余弦相似性的sklearn实现来比较 ac 再次给我们更好的结果:

余弦相似度通常可以提供比点积更好的结果。

这就是本文涵盖三个距离/相似性度量的全部内容——欧几里德距离、点积和余弦相似性。

了解每种方法的工作原理及其优缺点是值得的,因为它们都被大量用于机器学习,尤其是 NLP。

您可以在本笔记本中找到每个指标的 Python 实现。

我希望你喜欢这篇文章。如果您有任何问题或建议,请通过 Twitter 或在下面的评论中告诉我。如果你对更多类似的内容感兴趣,我也会在 YouTube 上发布。

感谢阅读!

来源

🤖带变压器的 NLP 课程

*所有图片均由作者提供,除非另有说明

PyTorch Lightning、MONAI 模型和 Rising augmentation 的简单 3D MRI 分类在 Kaggle 排行榜上排名铜牌

原文:https://towardsdatascience.com/simple-3d-mri-classification-ranked-bronze-on-kaggle-87edfdef018a?source=collection_archive---------11-----------------------

插图照片由安娜·施韦茨派克斯拍摄

使用 MONAI 模型和 MedicalNet 预训练权重在 3D MRI 扫描上解决图像分类任务(脑瘤识别),通过 Rising augmentation 和 Pytorch Lightning 训练获得分组,在 Kaggle 排行榜上获得铜牌基线。

这篇文章介绍了我们提交给最*的 Kaggle 竞赛:RSNA-米卡脑肿瘤放射基因组分类,旨在从 3D MRI 扫描中检测脑肿瘤。我简单描述一下比赛,提供数据。后来,我设计了一个简单的培训工作流程,它建立在几个成熟的框架之上,以产生一个健壮的基线解决方案

尽管公共排行榜得分较低,但该基线在私人排行榜上获得了铜牌!我的观点是“简单比复杂好”,过多地关注公共排行榜是不明智的。

竞争概述

RSNA-密歇根大学脑肿瘤放射基因组分类竞赛解决了一个基本的医学筛查挑战——检测大脑中的恶性肿瘤。这是一种威胁生命的疾病,中位生存期不到一年。竞赛发起人声称,肿瘤中存在一种称为 MGMT 启动子甲基化的特定遗传序列,可以用作预后因素和对化疗反应性的强预测因子。挑战在于从给定的 MRI ( 磁共振成像)扫描及其结构参数化中预测每个病例的 MGMT 值。

三轴切面,累积投影在完整 MRI 扫描的下方。

MRI 是一种用于放射学的非侵入性医学成像技术,用于获取活体组织中解剖和生理过程的图片。MRI 扫描仪依靠固体磁场来测量磁场梯度和无线电波,以产生人体或选定器官的人类可解读图像。

简单介绍一下竞赛的组织者和动机:北美放射学会(RSNA)与医学图像计算和计算机辅助介入学会(MICCAI)联手改进诊断。如果成功,你将帮助脑癌患者接受侵入性更小的诊断和治疗。

我们的投稿 Kaggle 笔记本是下面的 🧠Brain 肿瘤 Classif。~ lightning⚡monai-resnet3dT3。

https://www.kaggle.com/jirkaborovec/brain-tumor-classif-lightning-monai-resnet3d

随意分叉,进一步延伸!

探索性数据分析

训练数据集包括 585 个病例(患者研究)。每个独立的病例都有一个由五位数标识的专用文件夹,其中每个病例文件夹包含四个对应于结构多参数 MRI (mpMRI)的子文件夹。特定的 MRI 扫描以 DICOM 格式保存。

数据集中包含的 mpMRI 扫描有:

  • T1w : T1 加权预对比
  • T1Gd : T1 加权后对比
  • T2w : T2 加权
  • FLAIR :流体衰减反转恢复

简而言之:T1 加权更好地描绘了解剖,T2 加权自然地显示了病理。

流体衰减反转恢复(FLAIR) 是一种特殊的反转恢复序列,反转时间长。这将从生成的图像中去除脑脊液信号。FLAIR 图像上的脑组织看起来类似于 T2 加权图像,灰质比白质亮,但脑脊液是暗的而不是亮的。
物理学:为了消除来自流体的信号,调节 FLAIR 脉冲序列的反转时间,使得在*衡状态下没有流体的净横向磁化。
临床应用:FLAIR 序列是几乎所有脑部成像协议的一部分,尤其适用于检测大脑半球外围和靠*脑脊液的脑室周围区域的细微变化。

浏览注释

不管 mpMRI 如何,每个病例的注释都是二元分类,MGMT 为 0 或 1。在训练数据集中,正负 MGMT 观测值分布均衡,如下图所示。

二元事例间的标号分布。

一维稀疏扫描

与任何真实数据集一样,并非所有扫描都具有相同的质量。我们观察到输入扫描尺寸的差异,在一维上从 512 到 52 个像素不等。与相同扫描中的其他 X 和 Y 轴相比,高稀疏性通常出现在 Z 轴中。

由于大多数深度学习模型依赖于固定大小的输入,我们有两种选择来处理扫描:
1。将所有扫描向下采样至最低分辨率或
2。将所有扫描插入(上/下采样,取决于原始尺寸和与目标尺寸的比率)到一个共同的尺寸。

累积投影低于 MRI 扫描的三轴切面在 Z 维稀疏。

对于第一个选项,我们将丢失大量有价值的信息,对训练好的模型产生负面影响。所以我们决定把所有的扫描都插值成一个标准尺寸。虽然插值可能会在降级的扫描中引入一些噪声,但它会在其他地方保留完整的信息。

结构

我们使用 PyTorch 生态系统中的几个框架来解决深度学习过程的每个阶段:
1。将数据处理封装到由 Pytorch Lightning
2 提供的[DataModule](https://pytorch-lightning.readthedocs.io/en/latest/extensions/datamodules.html)中。通过MONAI3 创建卷积模型。从医疗网
4 加载预训练的重量。应用由上升
5 提供的基本 3D 增强。利用 Pytorch Lightning 的最佳实践无缝培训模型

所有代码快照和可视化都是这个示例库的一部分,可以作为pip install [https://borda.github.io/kaggle_vol-3D-classify](https://borda.github.io/kaggle_vol-3D-classify)/archive/refs/heads/main.zip安装。欢迎任何好的贡献!

Pytorch 闪电

PyTorch Lightning 是一个用于高性能人工智能研究的轻量级 PyTorch 包装器,允许你缩放你的模型,而不是样板文件。它还分离了数据、模型和训练逻辑,使研究人员能够专注于这些阶段中的每一个(此外,这种分离的代码更容易与您的同事共享)。此外,训练完全由 Lightning [Trainer](https://pytorch-lightning.readthedocs.io/en/stable/common/trainer.html)和自动监控一起处理。

莫奈模型

MONAI 是一个基于 PyTorch 构建的开源医疗框架,专注于医疗保健成像领域的深度学习。我们选择它作为一个丰富的模型集合,还包括这个任务所需的 3D 模型。在大多数情况下,他们还提供预先训练的重量,以改善你的训练的最初表现。

来自 MedicalNet 的预训练重量

深度学习的性能受到训练数据量的显著影响。 MedicalNet 项目聚合了具有不同模态、目标器官和病理的数据集,以促进知识转移。基于该数据集,提供了一系列 3D-ResNet 预训练模型。特别是,作者参考了 Med3D:用于 3D 医学图像分析的迁移学习

上升增强

Rising 是一个高性能的数据加载和增强库,用于 PyTorch 编写的 2D 和 3D 数据。它专注于提供与 PyTorch 生态系统的无缝集成,而不牺牲可用性或特性。一个很好的部分是,增强功能集成在DataLoader中,可以在 GPU 中应用,以显著提高训练,因为任何更高维度的变换/插值都需要计算。

数据准备和扩充

体积数据以 DICOM 格式的标准 2D 图像的有序序列提供。DICOM(医学数字成像和通信)是一种典型的医学图像格式,通常用于存储和传输医学图像,实现医学成像设备的集成。为了加载这些图像,我们使用了[pydicom](https://pypi.org/project/pydicom/) Python 包:

用于加载 DICOM 图像的样本代码

为了加载完整的卷,我们列出了特定文件夹中的所有图像,按照文件名中编码的切片索引对它们进行排序,并将它们全部连接到一个卷中:

样品代码用于装载完整的体积。

我们使用标准的最小-最大强度归一化使所有值都在范围(0,1)内,并在体积内插入一些缺失的切片,使所有轴相等。这种标准化简化了后期的增强,因此我们可以使用全方位翻转和旋转,而不会出现任何并发症。

使用 PyTorch 进行体积插值的示例代码。

数据缓存

加载过程相对较慢,并且对存储 IO 要求很高。这很快成为未来培训工作流程的瓶颈。我们引入了简单的扫描缓存来加速数据加载——每幅图像只从原始 DICOM 图像序列中加载一次,然后保存在 PyTorch 3D tensor 中。

DICOM 图像在内部使用 JPEG 压缩来减小它们的大小,相比之下,我们使用默认参数(张量使用torch.float64)进行简单的保存,结果非常占用空间。所以我们将张量保存为torch.float16,它仍然保留了所有的图像信息,但是显著减小了缓存大小(大约 4 倍),并连续改善了加载时间。

裁剪扫描

我们观察到,所有扫描都包括覆盖每个扫描的重要部分的黑色/均匀背景,这使得模型学习能力的相当一部分被浪费,或者最终对不想要的噪声敏感。

作为一项实验,我们在每个扫描轴上进行简单的裁剪,以最大化大脑占用率。我们计算一个简单 1D 投影(强度总和);从扫描边缘开始,当总强度超过给定阈值时,我们搜索第一个点。

从各个方向裁剪体积

原则上,它运行良好;设置适当的数据集范围的阈值是非常敏感的,结果显示每次扫描之间略有不同。它还取决于实际的轴和特定的大脑质量的存在。

扫描增强

有许多方法可以通过各种图像/体积扩充来提高模型的鲁棒性。主要类别是基于强度的、几何变换和结论(最后一种可能对输入样本敏感,因为我们不会移除肿瘤部分)。

用于培训的培训/验证增强

我们已经使用了简单的镜像和随机仿射变换,对于移位和旋转具有保守的参数范围。作为最后一步,我们将强度归一化为在训练数据集上计算的零*均值。

使用过的培训和验证增强

微调基线模型

我们的基线选择使用来自 MONAI 包的 ResNet 模型,该模型加载了来自 MedicalNet 的权重,并在大约 23 个不同的医学数据集上进行了预训练。

唯一复杂的是,MONAI 模型中的根模块名与 MedicalNet 中的预期模型名不兼容,因此在调用load_state_dict之前必须对其进行重命名。

简化的权重加载从 MedicalNet 到 MONAI ResNet 模型。

竞赛使用 AUROC (接收器工作特性下的面积)作为主要指标。我们用重物将 MONIA 模型包裹在 PyTorch-Lightning 模块中,并添加了几个 TorchMetrics 来监控模型性能,包括 AUROC。

对于培训,我们使用了 Grid.ai sessions 和一个基本的英伟达 T4 显卡。我们对基线模型的参数化如下:

  • ResNet18 模型架构
    *体积大小设置为 224px 各维度
    *自动混合精度训练( AMP )
    *批量大小 4

监控传输过程。

我们对微调进行了实验(所有预先训练的权重都被冻结),并将其与从头开始训练模型进行了比较。比较这两个选项,我们没有观察到任何显著的改进(通过所描述的参数化)。对于微调,我们显著增加了批量大小,同时仍然适合 16GB GPU。

推理和提交

一个简单的模型推理迭代测试数据集中的图像,并生成预测,这些预测被汇总到竞争提交中。请注意,您需要首先将模型切换到eval状态,对于预测,您不需要跟踪梯度,这大大加快了预测速度并降低了内存需求。

测试数据集上的简单模型推断

我们知道,训练数据集具有大约 52:48 的*衡标签分布比率。我们希望测试分布与训练数据集大致相似(因为模型的一部分是学习偏差)。

下面我们绘制了测试数据集预测的概率直方图,它似乎在一边形成了 0.5 左右的两个模式。

最终预测分布。

比赛期间,我在公开排行榜上排名第 757 位,后来在私人排行榜上跃升至第 134 位!公共测试分数基于总测试数据集的 1/3。

结论

这篇文章为最*的 Kaggle 竞赛提供了一个基线解决方案,旨在通过 MRI 扫描进行大脑分类。我挑选了几个方便的框架来取长补短,并从社区和学术研究中受益。

我介绍了数据集,并展示了一些如何通过缓存来增强训练的技巧。后来,我将预训练的模型权重加载到一个简单的 ResNet 模型中,并在带有 AMP 的英伟达 T4 显卡上对其进行了训练。我用这个解决方案在公共排行榜上排名居中,后来在私人排行榜上获得了铜牌。

通过交互式 Grid.ai 会议和 Github 项目查看培训,该项目包括作为简单 python 包和 iPython 笔记本提供的所有代码…

对更酷的 Pytorch 闪电集成感兴趣?
关注我,加入我们牛逼的
Slack社区!

https://devblog.pytorchlightning.ai/best-practices-to-rank-on-kaggle-competition-with-pytorch-lightning-and-grid-ai-spot-instances-54aa5248aa8e

关于作者

吉尔卡·博罗维克 拥有 CTU 大学的计算机视觉博士学位。他已经在几家 IT 创业公司和公司从事机器学习和数据科学工作几年了。他喜欢探索有趣的世界问题,用最先进的技术解决这些问题,并开发开源项目。

感谢

MRI 插图是基于提供的 Kaggle 数据集生成的,作为RSNA-ASNR-米凯布拉特挑战赛 2021
U.Baid 等人的“RSNA-ASNR-米凯布拉特 2021 脑肿瘤分割和放射基因组分类基准”, arXiv:2107.02314 ,2021。

A/B 测试设计、实施和缺陷的完整指南

原文:https://towardsdatascience.com/simple-and-complet-guide-to-a-b-testing-c34154d0ce5a?source=collection_archive---------0-----------------------

实践教程

为您的数据科学实验进行端到端的 A/B 测试,面向非技术专家和技术专家,提供示例和 Python 实现

图片来源:卡罗琳娜·格拉博斯卡

A/B 测试也称为分割测试,起源于统计学中的随机控制试验,是企业测试 UX 新功能、产品新版本或算法以决定你的企业是否应该推出新产品/功能的最受欢迎的方法之一。

《天下大 A/B 考》肖恩·埃利斯

本文面向技术和非技术受众,我将涵盖执行 A/B 测试时应该考虑和执行的以下主题:

**- What is A/B testing and when to use it?
- Questions to clarify before any A/B test
- Choice of Primary metric 
- Hypothesis of the test
- Design of the test (Power Analysis)
- Calculation of Sample Size, Test Duration 
- Statistical tests (T-test, Z-test, Chi-squared test)
- Analysing A/B test results in Python 
- Bootstrapping and Bootstrap Quantile Method for SE and CI
- Statistical Significance vs Practical Significance
- Quality of A/B test (Reliability, Validity, Potency)
- Common problems and pitfalls of A/B testing
- Ethics and privacy in A/B testing**

如果事先没有统计知识,可以简单跳过统计推导和公式。但是,如果您想学习或更新基本统计概念的知识,您可以查看本文: 数据科学家和数据分析师的统计学基础

什么是 A/B 测试,什么时候使用?

A/B 测试背后的想法是,你向一个客户样本(实验组)展示产品的变体版本,向另一个客户样本(对照组)展示产品的现有版本。然后,跟踪实验组/治疗组相对于对照组的产品性能差异,以确定产品的新版本对产品性能的影响。因此,目标是在测试期间跟踪指标,并找出产品性能中是否存在差异以及差异的类型。

该测试背后的动机是测试新产品变体,这些变体将提高现有产品的性能,并将使该产品更加成功和最佳,从而显示出积极的治疗效果。

这种测试之所以伟大,是因为企业通过向他们展示现有的和变化的产品/功能选项,从他们的实际用户那里获得了直接的反馈,这样他们可以快速测试新的想法。如果 A/B 测试表明变化的版本/方法不是有效的,至少企业可以从中学习,并决定他们是否需要改进它或需要寻找其他想法。

A/B 测试的好处

  • 允许以快速的方式了解什么有效,什么无效
  • 您直接从实际/真实的产品客户那里获得反馈
  • 由于用户不知道他们正在被测试,结果将是无偏见的

A/B 测试的缺点

  • 向不同的客户呈现不同的内容/价格/功能,尤其是在相同的地理位置,可能有潜在的危险,导致变化厌恶(我们将在后面讨论如何解决这个问题)
  • 需要大量的产品、工程和数据科学资源
  • 如果处理不当,可能会导致错误的结论

A/B 测试背后的动机是测试新产品变体,这些变体将提高现有产品的性能,并将使该产品更加成功和优化,显示出积极的治疗效果。

任何 A/B 测试前要问的问题

鉴于 A/B 测试需要大量的资源,并可能导致具有重大影响的产品决策,在开始运行测试之前,询问您自己、产品、工程团队和参与实验的其他利益相关者一些基本问题是非常重要的。

  • 样本人群是什么样的,目标产品的客户群是什么样的?
  • 我们能否使用探索性/历史数据分析(例如,使用因果分析)找到业务问题的答案?
  • 我们想要测试目标产品的单个还是多个变体?
  • 我们能否确保真正随机的对照组和实验组。两个样本都是真实用户群体的无偏见的真实代表?
  • 在整个测试过程中,我们能否确保治疗效果与对照效果的完整性?

A/B 测试的目标是在测试期间跟踪主要指标,并找出产品的性能是否存在差异以及差异的类型。

图片来源:卡罗琳娜·格拉博斯卡

为 A/B 测试选择主要指标

选择指标是 A/B 测试中最重要的部分之一,因为该指标将用于测量实验广告控制组的产品或功能的性能,并将用于确定这两组之间是否存在统计显著差异

成功指标的选择取决于这个 A/B 测试所测试的基本假设。这是 A/B 测试中最重要的部分之一,因为它决定了测试将如何设计,以及提议的想法执行得如何。选择糟糕的度量标准可能会取消大量工作的资格,或者可能导致错误的结论。

收入并不总是最终目标,因此对于 A/B 测试,我们需要将主要指标与产品的直接目标和更高层次的目标联系起来。人们的期望是,如果产品赚更多的钱,那么这表明内容是伟大的。但是在实现这个目标的过程中,我们可以优化转换漏斗,而不是提高材料和写作的整体内容。测试您为 A/B 测试选择的指标的准确性的一种方法是回到您想要解决的确切问题。你可以问自己以下问题:

度量标准有效性问题:如果这个选择的度量标准显著增加,而其他一切保持不变,我们会实现我们的目标并解决这个问题吗?

尽管您需要为您的 A/B 测试准备一个单一的主要指标,但是您仍然需要关注剩余的指标,以确保所有的指标都显示出变化,而不仅仅是目标指标。在你的 A/B 测试中有多个度量标准会导致误报,因为你会发现许多显著的差异,而没有影响,这是你想要避免的。

常见 A/B 测试指标

经常在 A/B 测试中使用的流行性能指标是点击率、点击率和转化率。

1:点击率使用方法

其中考虑了总视图或会话的数量。这个数字是查看页面(印象)然后实际点击它(点击)的人的百分比。

2:影响的点进概率(CTP)

与 CTR 不同,CTP 考虑了重复点击,这意味着如果用户出于某种原因在单个会话中出于某种原因(例如,因为不耐烦)对同一项目执行了多次点击,则该多次点击在 CTP 中被计为单次点击。

为了计算 CTP,您需要与工程师合作修改网站的 s.t .对于每个页面视图,您捕获视图/印象事件和点击事件,将每个页面视图与每个页面的所有子点击 相匹配,以确保每个独特的页面视图只计算 1 个子点击。

3:转换率

转换率,定义为以交易结束的会话比例。

所以,如果你想衡量网站的可用性,你可以使用 CTR 如果你想衡量功能的实际影响,你可以使用 CTP。CTR 不处理重复的点击,所以如果用户不耐烦地多次按下同一个按钮,这将不会被纠正为等于 1。

陈述测试的假设

A/B 测试应该总是基于一个需要测试的假设。这种假设通常是产品团队和数据科学团队的相关人员集思广益和协作的结果。这一假设背后的想法是决定如何“修复”产品中的潜在问题,这些问题的解决方案将影响感兴趣的关键性能指标(KPI)?

当你想挑选一个问题的时候,对要测试的产品问题和想法进行优先排序也是非常重要的。解决这个问题将会对产品产生最大的影响。

例如,如果产品的 KPI 是为了提高推荐系统的推荐质量,这可以通过例如添加印象折扣或者为推荐者建立重新排序模型来实现。但是,这两种解决方案对建议质量的改善程度可能会有所不同。也就是说,重新排序模型通过潜在地改变呈现给用户的推荐集来影响推荐的排序,这与印象折扣不同,印象折扣只是确保用户看不到之前向用户看过的推荐。

图片来源: 波琳娜·科瓦列娃

对于这个特定的例子,我们可以决定建立一个重新排序的模型,我们希望它能够提高目标推荐系统的质量(让我们把这个假想的推荐系统命名为 RecSys)。此外,我们还进行了研究,发现 XGBoost 可用作重新排序模型,对 RecSys 建议进行重新排序。

最后,我们进行了探索性分析/离线测试,发现推荐质量有所提高(假设使用 NDCG 作为推荐质量的性能衡量标准),并确定了显著的影响。因此,作为最后一项检查,我们希望测试 XGBoost 重排序器在 RecSys 推荐质量方面与现有推荐器版本相比的有效性。因此,我们可以陈述以下假设:

假设:在现有的 RecSys 推荐器上增加一个 XGBoost re-ranker 模型,会提高推荐的 CTR,也就是说,会提高 RecSys 推荐的质量。

不要将多个想法合并到一个假设中,也不要限制测试中引入的变量,以便您可以了解它们各自的影响。否则,在考试结束时,你会留下许多问题和很少的答案。

设计 A/B 测试

一些人认为 A/B 测试是一门艺术,其他人则认为这是一种商业调整的普通统计测试。但是边界是,为了正确地设计这个实验,你需要自律和有目的,同时记住这不是真正的测试——这是关于学习。以下是你需要采取的步骤,为你的 A/B 测试提供一个可靠的设计。

第一步:统计假设

步骤 2:电源分析

为了确保我们的结果是可重复的、稳健的,并且可以推广到整个群体,我们需要避免 p-hacking ,以确保真正的统计显著性并避免有偏见的结果,我们希望确保我们收集了“足够”数量的观察值,并且我们在最短的预定时间内运行测试。因此,在运行测试之前,我们需要确定控制组和实验组的样本量,以及我们需要运行测试多长时间。这个过程通常被称为功效分析,它包括 3 个具体步骤:确定检验的功效,确定检验的显著性水*,以及确定最小可检测效应。A/B 测试功耗分析中涉及的参数的一个常用参考符号如下:

测试的功效

统计检验的能力是正确拒绝零假设的概率。功效是当零假设为假时做出正确决定(拒绝零假设)的概率。

通常由(1-β)定义的功效等于不犯第二类错误的概率,其中第二类错误是当零假设为假时不拒绝零假设的概率。

通常的做法是选择 80%作为 A/B 测试的功效,也就是 20%的第二类误差,这意味着当存在一种效应时,我们可以不检测(不能拒绝无效)一种治疗效应。然而,该参数值的选择取决于测试的性质和业务约束。

测试的显著性水*

显著性水*也是 I 型错误的概率,是拒绝零的可能性,因此检测到治疗效果,而零是真的并且没有统计学上显著的影响。该值通常由希腊字母 alpha,α定义,是做出错误发现的概率,通常被称为假阳性率。

通常,我们使用 5%的显著性值,这表明当没有实际差异时,我们有 5%的风险得出实验和控制变量性能之间存在统计显著差异的结论。因此,100 个病例中有 5 个检测到治疗效果,而没有效果,我们就没事了。这也意味着控制组和实验组之间有显著的结果差异,有 95%的置信度

就像在测试能力的情况下,alpha 值的选择取决于测试的性质和业务约束。例如,如果运行这个 A/B 测试与高工程成本有关,那么企业可能会决定选择高 alpha,以便更容易检测处理效果。另一方面,如果生产环境中建议版本的实现成本很高,您可以选择一个较低的显著性水*,因为这个建议的功能应该确实有很大的影响来证明高实现成本的合理性,所以应该更难拒绝 null。

最小可检测效应(δ)

从业务的角度来看,业务希望看到的新版本的最小影响的统计显著性是什么,以发现该变体值得投资?

这个问题的答案是,与现有版本相比,我们的目标是在新版本的指标中观察到什么形式的变化,以便向业务部门提出建议,该功能应该在生产中推出。这个参数的估计值就是所谓的最小可检测效应,通常由希腊字母 delta、定义,这也与测试的实际意义有关。MDE 是一个与最小影响相关的代理,这种最小影响在业务实践中很重要,通常由利益相关者设定。

通常的做法是选择 80%作为 A/B 测试的功效和 5%作为显著性水*,即 20%的第二类误差和 5%的第一类误差。然而,该参数值的选择取决于测试的性质和业务约束。

步骤 3:计算最小样本量

图片来源:迈克尔·布伦斯

A/B 测试的另一个非常重要的部分是确定控制组和实验组的最小样本量,这需要使用测试的定义的功效(1-beta)显著性水*(alpha)最小可检测效应 (MED)以及两个相同大小的正态分布样本的方差来确定。样本量的计算取决于您为跟踪对照和实验版本的进展所选择的基本主要指标。这里我们区分两种情况;案例 1 中,A/B 测试的主要指标采用二元变量的形式(如点击量或无点击量),案例 2 中,测试的主要指标采用比例或*均值的形式(如*均订单量)。

案例 1:用二进制度量计算样本量

当我们处理具有两个可能值的主要性能跟踪指标时,例如点击率,其中用户可以点击(成功)或不点击(失败),如果用户对产品的响应可以被定义为“独立”事件,那么我们可以将此视为伯努利试验,其中点击事件(成功)以概率 p_con 发生在对照组的情况下,以概率 p_exp 发生在实验组的情况下。此外,在对照组的情况下,不点击事件(失败)以概率 q_con 发生,在实验组的情况下,以概率 q_exp 发生,其中:

因此,描述测试期间从用户处收到的成功(点击)次数的随机变量遵循二项式分布,其中样本大小是功能/产品给用户留下印象的次数,成功的概率分别是对照组和实验组的 p_conp_exp、****。然后,使用具有预先指定的显著性水*、功效水*和 MID 的双边检验,比较这两个二项式比例所需的样本量可计算如下:

这里我们需要使用 A/A 测试(A/B 测试,除了给两组分配相同的处理)来获得 p_bar 和 q_bar 的估计值。

案例 2:使用连续指标计算样本量

当我们处理*均形式的主要绩效跟踪指标时,如*均订货量,我们打算比较对照组和实验组的*均值 s,,然后我们可以使用中心极限定理,说明对照组和实验组的*均抽样分布都遵循正态分布。因此,两组均数差的抽样分布也服从正态分布。那就是:

因此,使用具有预先指定的显著性水*、功效水*、MID 的双边检验,比较两个正态分布样本的*均值所需的样本大小可计算如下:

在这里,我们可以运行 A/A 测试来获得样本方差σ _con 和σ _exp。

描述测试期间从用户处收到的成功(点击)次数的随机变量遵循二项式分布,其中样本大小是特性/产品给用户留下印象的次数,成功的概率分别是对照组和实验组的 p_con 和 p_exp。

步骤 4:确定 A/B 测试持续时间

如前所述,这个问题需要在你进行实验之前回答,而不是在实验过程中,当你检测到统计显著性时,尝试停止测试。要确定持续时间的基线,常用的方法是使用以下公式:

例如,如果此公式的结果为 14,则表明测试运行了 2 周。然而,在选择运行测试的时间和时长时,将许多特定于业务的方面考虑在内是非常重要的,并且要有所保留地使用这个公式。

例如,如果一个人想在 2020 年 1 月初运行一个实验,当时新冠肺炎疫情震动了世界,这对页面使用产生了影响,对于一些企业来说,这意味着页面使用的高增长,而对于一些企业来说,可用性的巨大下降,那么在不考虑这一点的情况下运行 A/B 测试将导致不准确的结果,因为活动期不会是常见页面使用的真实表示。

测试持续时间过短:新奇效果

用户倾向于对所有类型的变化做出快速而积极的反应,不管这些变化的性质如何。这种对实验版本的积极影响是完整的,因为有一个变化,不管变化是什么,被称为新奇效应,它随着时间的推移而消失,因此被认为是“虚幻的”。所以,把这种效应描述给实验版本本身,并期望它会在新鲜感消失后继续存在是错误的。

因此,当选择测试持续时间时,我们需要确保我们不要在太短的时间内运行测试,否则我们会有新奇的效果。新奇效应可能是 A/B 测试外部效度的主要威胁,因此尽可能避免它是很重要的。

测试持续时间过长:成熟效应

当计划一个 A/B 测试时,考虑一个更长的测试持续时间通常是有用的,这样可以让用户习惯新的特性或产品。通过这种方式,人们将能够观察到真正的治疗效果,这是通过给返回的用户更多的时间来从最初的积极反应或由于作为治疗的一部分而引入的改变而引起的兴趣高峰中冷却下来。这将有助于避免新奇效应,从而更好地预测测试结果。然而,测试时间越长,外部效应影响用户反应的可能性就越大,并可能污染测试结果,成熟效应。因此,运行 A/B 测试太长时间也是不推荐的,并且可以更好地避免以增加结果的可靠性。

测试时间越长,外部效应影响用户反应并可能污染测试结果的可能性就越大。

运行 A/B 测试

一旦准备工作完成,在工程的帮助下,你可以开始运行 A/B 测试。首先,工程团队需要确保控制组和实验组之间的完整性。其次,存储用户对治疗的反应的机制必须准确,并且对所有用户都相同,以避免系统偏差。您还需要避免一些事情,例如,一旦您检测到统计显著性(小 p 值),而您还没有达到开始测试前计算的最小样本量,就过早停止测试。

图片来源:Lum 3N

用 Python 分析 A/B 测试结果

在解释 A/B 测试的结果时,您应该计算一组值来测试前面陈述的统计假设(测试控制组和实验组之间是否存在统计上的显著差异)。该套件包括:

  • 选择合适的统计检验
  • 计算测试统计量(T)
  • 计算检验统计的 p 值
  • 拒绝或未能拒绝统计假设(统计显著性)
  • 计算误差幅度(实验的外部有效性)
  • 计算置信区间(实验的外部有效性和实际意义)

选择合适的统计测试

一旦收集了对照组和实验组的相互作用数据,您就可以通过选择适当的统计测试来更早地测试统计假设,这种测试通常分为参数非参数测试。测试的选择取决于以下因素:

  • 主要指标的格式(基础 pdf)
  • 样本量(适用于 CLT)
  • 统计假设的性质(表明两个组之间的关系仅仅存在或确定两个组之间的关系类型)

A/B 测试中最常用的参数测试有:

  • 2 样本 T-检验(当 N < 30 时,度量遵循 student-t 分布,你要确定对照组和实验组之间是否存在关系以及关系的类型
  • 2 样本 Z-检验(当 N > 30 时,度量遵循渐*正态分布,并且您想要识别对照组和实验组之间是否存在关系 类型的关系

A/B 测试中最常用的非参数测试有:

  • Fishers 精确检验(小 N,识别与你想要识别的对照组和实验组之间是否存在关系 )
  • 卡方检验(大 N,识别和你想要识别的对照组和实验组之间是否存在关系)
  • Wilcoxon 秩和/Mann Whitney 检验(小 N 或大 N,偏斜采样分布,检验对照组和实验组之间中位数的差异)

双样本 T 检验

如果您想测试控制组和实验组之间是否存在统计意义上的显著差异,这些差异以*均值的形式表示(例如,*均购买金额),指标遵循 student-t 分布,当样本量小于 30 时,您可以使用双样本 T 检验来测试以下假设:

其中对照组均值的抽样分布遵循自由度为 N_con-1 的 Student-t 分布。此外,实验组均值的抽样分布也遵循自由度为 N_exp-1 的 Student-t 分布。注意,N_con 和 N_exp 分别是控制组和实验组中的用户数量。

然后,两个样本的合并方差的估计值可以计算如下:

其中σ _con 和σ _exp 分别是对照组和实验组的样本方差。那么标准误差等于集合方差估计的*方根,可以定义为:

因此,带有前述假设的双样本 T 检验的检验统计量可计算如下:

为了检验样本均值间观察到的差异的统计显著性,我们需要计算检验统计量的 p 值。p 值是由于随机机会而观察到的值至少与普通值一样极端的概率。换句话说,假设零假设为真,p 值是获得至少与样本数据中的效应一样极端的效应的概率。那么检验统计的 p 值可以计算如下:

p 值的解释取决于所选的显著性水*α,该水*是在功率分析期间运行测试之前选择的。如果计算出的p-值似乎小于等于α(例如,对于 5%显著性水*为 0.05),我们可以拒绝零假设,并声明对照组和实验组的主要指标之间存在统计学显著差异。

最后,为了确定获得的结果有多准确,也为了评价获得的结果的实际意义,您可以使用以下公式计算您的测试的置信区间:

其中,t(1-alpha/2)是与具有 alpha 显著性水*的双边 t 检验相对应的检验的临界值,可以使用 t 表找到。

双样本 Z 检验

如果您想要测试控制组和实验组的指标(以*均值(例如*均购买量)或比例(例如点击率)的形式)之间是否存在统计上的显著差异,指标遵循正态分布,或者当样本大小大于 30 时,您可以使用中心极限定理(CLT)来说明控制组和实验组的抽样分布是渐*正态的,您可以使用双样本 Z 检验。这里我们将区分两种情况:一种情况是主要指标采用比例形式(例如点击率),另一种情况是主要指标采用*均值形式(例如*均购买量)。

案例 1:比较比例的 Z 检验(双边)

如果您想测试控制组和实验组之间的比例(如 CTR)指标是否存在统计学上的显著差异,以及点击事件是否独立发生,您可以使用双样本 Z 测试来测试以下假设:

其中每个点击事件可以由随机变量来描述,该随机变量可以取两个可能的值 1(成功)和 0(失败),遵循伯努利分布(点击:成功和没有点击:失败),其中 p_con 和 p_exp 分别是对照组和实验组的点击概率(成功概率)。那就是:

因此,在收集了控制用户和实验用户的交互数据后,您可以计算这两个概率的估计值,如下所示:

因为我们正在测试这些概率的差异,所以我们需要获得一个对联合成功概率的估计和一个对联合方差的估计,如下所示:

那么标准误差等于集合方差估计的*方根,可以定义为:

因此,比例差异的双样本 Z 检验的检验统计量可以计算如下:

那么这个检验统计的 p 值可以计算如下:

最后,您可以计算测试的置信区间,如下所示:

其中,Z(1-alpha/2)是与具有 alpha 显著性水*的双边 Z 测试相对应的测试临界值,可以使用 Z 表找到。这种双边 2 样本 Z 检验的拒绝区域可以通过下图来显示。

图片来源:作者

案例 2:比较*均值的 Z 检验(双边)

如果您想测试对照组和实验组的*均值(如 CTR)是否存在显著的统计学差异,您可以使用双样本 Z 检验来测试以下假设:

其中对照组均值的抽样分布服从正态分布,均值为μ_ con 和σ con/N_con,此外,实验组均值的抽样分布也服从正态分布,均值为μ exp 和σ _exp/N_exp。

然后,对照组和实验组的均值差异也遵循正态分布,均值为μ_ con-μ_ exp,方差为σ _con/N_con + σ _exp/N_exp。

因此,均值差异的双样本 Z 检验的检验统计量可计算如下:

标准误差等于混合方差估计值的*方根,可定义为:

那么这个检验统计的 p 值可以计算如下:

最后,您可以如下计算测试的置信区间:

卡方检验

如果您想测试控制组和实验组的绩效指标(例如它们的转化率)之间是否存在统计上的显著差异,并且您并不想知道这种关系的本质(哪一个更好),您可以使用卡方检验来测试以下假设:

请注意,该指标应采用二进制变量的形式(例如,转换或无转换/点击或无点击)。数据可以用下表的形式表示,其中 O 和 T 分别对应于观察值和理论值。

那么卡方检验的检验统计量可以表示如下:

其中observed对应的是观测数据 Expected 对应的是理论值,我可以取值 0(不换算)和 1(换算)。重要的是要看到这些因素中的每一个都有一个单独的分母。当只有两个组时,测试统计的公式可以表示如下:

期望值等于产品的每个版本被浏览的次数乘以导致转化的概率(或者在点击率的情况下导致点击)。

请注意,由于卡方检验不是参数检验,其标准误差和置信区间不能像在参数 Z 检验或 T 检验中那样以标准方式计算。

这种双边 2 样本 Z 检验的拒绝区域可以通过下图来显示。

图片来源:作者

非参数检验的标准误差和置信区间

在参数测试的情况下,标准误差和置信区间的计算是简单的。然而,在非参数测试的情况下,计算不再简单。为了计算旨在比较对照组和实验组的样本均值或样本中位数的非参数统计检验的标准误差和置信区间,需要使用重采样技术,如Boostrap 分位数法、 分别为

Bootstrap 所做的是,它获取原始训练样本,并通过替换从中重新采样,从而产生 B 个不同的样本。因此,自举背后的想法是用替换重新采样(相同的观察结果可以在自举数据集 ) 中出现不止一次。从两组的现有数据中,数据是在实验期间收集的,B 次这意味着你将最终得到两组的 B 个样本。然后,您需要计算对照组和实验组的样本均值/中位数 B 次,可由以下 Bx1 向量表示:**

因此,您可以计算每对对照组和实验组的样本均值差异,从而得出 B 样本均值差异。然后,您还可以在样本*均值中绘制该差异的采样分布,它可以由以下 Bx1 向量表示:

然后,如果 B 较大(例如 B = 1000),我们可以利用中心极限定理,假设对照组和实验组均值差的抽样分布服从正态分布,如下图所示。

图片来源:作者

然后,我们需要计算这 B 次的次数,*均值之差大于 0,以获得该测试的 p 值,如下所示:

如果 p 值大于所选的显著性水*,那么我们可以声明我们不能拒绝空值。因此,没有足够的证据表明对照和实验样本均值之间存在显著的统计学差异。可以对样本中位数进行相同的自举测试。**

为了计算 95%的置信区间,可以使用百分位方法,该方法使用估计值的 bootstrap 分布的 2.5 和 97.5 百分位作为区间的下限和上限。**

如果 p 值大于所选的显著性水*,那么我们可以声明我们不能拒绝空值。因此,没有足够的证据表明对照和实验样本均值之间存在显著的统计学差异。

统计意义与实际意义

在 A/B 测试的统计分析阶段,当检测到一个小的 p 值时,我们称之为统计显著性。然而,仅有统计显著性并不足以提出关于推出一项功能或产品的建议。

检测出统计显著性后,下一步就是了解是否有 的实际显著性。

确定 A/B 测试是否具有实际意义的一种方法是使用置信区间,并将其下限与 MDE(经济意义的估计值)进行比较。更具体地说,如果 CI 的下限大于 MDE(δ),那么你可以声明你有实际意义。例如,如果 CI = [5%,7.5%]和 MDE = 3%,那么您可以得出结论,因为 5% > 3%,所以具有实际意义。

请注意,您还应该查看置信区间的宽度,并确保它不要太大,因为太宽的置信区间表明您的结果的精确度很低,并且结果不能概括到整个人群(外部有效性)。

A/B 测试质量

A/B 测试是实验设计的一个例子,与任何其他类型的实验一样,也需要满足 3 个因素才能做出可靠的结论和产品决策。这些因素是:

  • 可靠性/可复制性
  • 有效期
  • 效力

可靠性和可复制性

可靠性背后的理念是,实验结果必须不仅仅是一次性的发现,而且必须具有内在的可再现性和可重复性。最*,研究行业出现了可复制性危机的现象,因为研究人员无法重现实验结果。这可能是由不同的原因造成的,例如:**

  • 当原始实验被改变或者有 p-hacking 时
  • 当原始实验中存在测量误差时
  • 当最初的实验存在系统误差时
  • 缺少用于执行实验的文档或源代码/数据

你可以做些什么来增加你的 A/B 实验的可复制性:

  • 将带有注释的源代码存储在安全的云上
  • 将带有注释的数据存储在安全的云上
  • 详细记录过程和结果
  • 检查系统误差(报告治疗反应的方式,因此你如何衡量治疗的影响)
  • 对另一个国家做同样的分析
  • 如果你使用抽样技术或模拟,使用随机种子**

所有这些步骤将使你的工作更具可复制性。

有效期

有效性包括您的实验的整个概念,并确定获得的结果是否符合随机对照试验的所有要求。就有效性而言,我们通常区分两种类型的有效性:

  • 内部有效性
  • 外部有效性

内部效度是指观察到的数据和用它得到的结果。那些结果是有效和可靠的还是不准确和有偏见的?因变量的变化仅仅是由于干预(自变量)而不是由于其他因素吗?下列问题会对你的 A/B 实验的内部效度产生负面影响:

  • 省略变量偏差(使用赫克曼两步流程)
  • 反向因果关系(使用 IV 或 2sl 方法)
  • 虚假变量(为目标变量寻找控制变量或仪器)
  • 使用不适当的替代变量(使用实际干预变量)

外部效度指的是你的实验结果对整个人群的可推广程度。它回答了这样一个问题:研究结果可以推广到更广泛的人群吗?外部效度可以通过在相似条件下重复实验来提高?下列问题会对你的 A/B 实验的外部效度产生负面影响:

  • 有偏样本(使用 实体抽样 技术随机抽取无偏样本)
  • 非代表性样本(使用高级统计抽样技术,如 加权或分层抽样 来生成一个样本,该样本不仅无偏,而且能代表您的总体)

特别是,如果你的人口被分成几个不同的亚人口,并且研究要求每个亚人口的大小相等, 分层抽样 会非常有用。这样,每个亚群中的单位被随机化,但不是整个样本。然后,实验结果被可靠地从实验单元推广到更大的单元群体。

您还可以使用 Boostrapping 来计算结果的标准误差/误差幅度以及置信区间的宽度。也就是说,如果你的 A/B 测试的 SE 很大或者 CI 很宽,那么你可以得出结论,你的结果的精度很低,并且当应用于整个人群时,你的结果不会一般化。**

效力

确保干预具有足够的效力以产生因变量的可测量变化是很重要的,否则你会错误地认为干预没有效果(II 型错误)。或者,这意味着因变量必须对治疗敏感。可以通过减少噪声(例如测量误差)来提高灵敏度,例如通过进行重复测量并对它们求*均(例如自举 )**

图片来源:卡罗琳娜·格拉博斯卡

如果您的 A/B 测试的 SE 很大或 CI 很宽,那么您可以得出结论,您的结果的精确度很低,并且您的结果在应用于整个人群时不会一般化。

A/B 测试的常见问题和陷阱

为了不使你的在线实验失败,重要的是要遵循指定的指导方针,并耐心地完成一系列应该发生的行动,以结束一个准备充分并执行良好的 A/B 实验。下面将介绍 A/B 测试中常见的问题和陷阱,以及相应的解决方法。

混杂效应

重要的是要确保所有其他已知的对因变量有影响的可能因素保持不变。因此,你需要控制尽可能多的不想要的或不*等的因素(也称为无关变量)。当无关变量与自变量和因变量都相关时,它们就很重要。当考虑到某些虚假变量时,自变量和因变量之间的关系完全改变/逆转,这是该问题的一个特殊和极端的情况,这通常被称为辛普森悖论****

需要控制这些效应的原因是,随机分配治疗单位有助于减少混淆,使治疗以外的因素产生的效应看起来像是治疗的结果。因此,混杂效应威胁到你的 A/B 实验的内在有效性。以下解决方案可以帮助您避免这个问题。

  • 混杂变量的控制
  • 可靠的仪器(IV 或 2SLS 估计)
  • 适当选择自变量和因变量
  • 随机样本的生成

选择偏差

A/B 测试的一个基本假设是,你的样本需要是无偏的,每种类型的用户都需要有相同的概率被包含在样本中。如果由于某种错误,你排除了人口中的特定部分。(例如,只对一个州的*均体重进行抽样:上次关于教育的例子)然后我们称之为选择偏差。

为了检查您的样本是否有偏差在知道真实总体分布的情况下,您从您的样本中创建 B 个 bootstrapped 样本,并绘制样本均值的分布。如果这种分布不是以真实总体*均值为中心,那么你的样本是有偏差的,你应该使用更多的 固体抽样 技术来随机抽样一个无偏样本。

系统偏差

这个问题与衡量治疗效果的方式有关(产品的新版本或功能)。你在测量它的时候有系统地犯错误吗?这种类型的误差总是以相同的量或相同的比例影响测量,假设每次以相同的方式读取读数,因此它是可预测的。与主要影响估计结果精度的随机误差不同,系统误差影响结果的精度**

提前停止或黑客入侵

A/B 实验中的一个常见错误是,在 A/B 测试的功效分析阶段预先确定显著性水*和所有其他模型参数时,一旦观察到具有统计显著性的结果(例如,较小的 p 值),就提前停止实验,并假设实验将一直运行到达到最小样本量。

P-hacking 或提前停止会影响结果的内部有效性,使结果有偏差,还会导致假阳性。

溢出或网络效应

这个问题通常发生在脸书、Instagram、抖音等社交媒体*台上进行 A/B 测试时,但也发生在其他产品中,例如,连接的实验组和控制组中的用户在同一个组或社区中,并影响彼此对实验和控制产品版本的反应。这个问题导致有偏见的结果和错误的结论,因为它违反了测试和控制效果的完整性。

为了检测网络效应,您可以执行分层抽样,然后将其分成两组。然后,您可以在一个样本上运行 A/B 测试,将聚类样本考虑在内,而另一个样本则不考虑。如果治疗效果有差异,那么就存在网络效应问题。**

变化厌恶和新奇效应

当你正在测试产品的重大变化,而用户不希望这样,起初用户可能只是出于好奇而尝试,即使该功能实际上并不比受控/当前版本更好,这被称为新奇效应,它会影响你的结果的内部有效性。此外,新功能(实验产品版本)也可能影响整体用户体验,使一些用户流失,因为他们不喜欢这个新版本。这种现象通常被称为厌恶变化**

检验新奇效果最常用的方法之一是在新老中对用户进行细分。如果老用户喜欢这个特性,但新用户不喜欢,那么很可能你遇到的是新奇感。**

样本比率不匹配

如果在您看来,控制组和实验组之间的划分看起来可疑,表明处理分配过程看起来可疑,因为分配到控制组/实验组的用户比分配到实验组/控制组的用户多,那么您可以执行卡方检验。该测试将帮助您正式检查样本比率不匹配。你可以在这里阅读更多关于这个测试的信息

测试周期选择不当

A/B 测试的另一个常见错误是测试周期的选择。如前所述,A/B 测试的一个基本假设是,每种类型的用户都需要有相同的概率被包含在样本中。然而,如果你在一个没有考虑假期、季节性、周末和任何其他相关事件的时期运行你的测试,那么不同类型的用户被选择的概率将不再相同(例如周末购物者、假日购物者等。).例如,在周日早上运行测试与在周二晚上 11 点运行相同的测试是不同的。

同时运行太多测试

当您的产品有一个以上的实验变量需要测试时,您需要同时处理两个以上的变量,这样您就不能再使用相同的显著性水*来测试统计显著性。因此,需要调整与结果进行比较的 p 值或显著性水*。

在这种情况下,可以使用 Bonferonni 校正 根据样本数 n 调整显著性水*。因此,需要在多变量测试中使用的显著性水*应为 alpha/N。例如,如果显著性水*为 5%,则新调整的显著性水*应为 0.05/n

图片来源:卡罗琳娜·格拉博斯卡

检验新奇效果最流行的方法之一是将用户分为新用户和旧用户。如果这个特性被老用户喜欢,但是没有被新用户喜欢,那么,很有可能,你正在处理新奇效应。

A/B 测试中的道德和隐私

随着 A/B 测试越来越受欢迎,A/B 测试背后的隐私和道德问题也越来越受到关注。也就是说,下面的问题就派上用场了。

  • 用户是否被告知条件和风险?
  • 数据附带了哪些用户标识符?
  • 收集什么类型的数据?(个人自愿同意)
  • 测试和收集的数据的保密和安全级别是什么,每个人都知道吗?

在进行 A/B 实验时,您要确保在向一组用户(实验)提供治疗(更好的产品/更好的功能)而不向另一组用户(对照)提供治疗时,不会剥夺用户的权利。此外,要考虑的其他问题是用户可能拥有的其他服务,以及在时间、金钱、信息等方面的转换成本。

例如,如果你正在测试一个搜索引擎的变化,参与者总是可以选择使用另一个搜索引擎。主要问题是,参与者的选择越少,围绕强制的问题就越多,参与者是否真的可以选择是否参与,以及如何*衡风险和收益。

额外资源

***https://github.com/TatevKaren

Github 库进行 A/B 测试: 这里***

如果你喜欢这篇文章,这里有一些你可能喜欢的其他文章:

***https://tatev-aslanyan.medium.com/bias-variance-trade-off-in-machine-learning-7f885355e847 https://tatev-aslanyan.medium.com/data-sampling-methods-in-python-a4400628ea1b https://medium.com/analytics-vidhya/pyspark-cheat-sheet-big-data-analytics-161a8e1f6185 https://medium.com/mlearning-ai/using-customer-and-product-features-in-recommender-systems-2734258873cf

调查:完美的数据科学课程对你来说是什么样的?

你是否也注意到,作为数据科学家,我们很难浏览多个博客和课程,即使在这种情况下,也没有一个地方涵盖所有主题。所以,我愿意为您打造这个 【一站式数据科学店】 课程。

为了为您定制本课程,我很想了解您的意见,以了解“完美的数据科学课程对您来说是什么样的?”。

因此,我想请您回答几个问题来完成这个 简短调查*,一旦课程开始,您将是第一个收到通知的人。也请* 与你认为会对此课程感兴趣的人分享

预先感谢您,非常感谢您的参与!

为调查链接: 点击此处

感谢阅读

我鼓励你 加入 Medium today 以拥有 完整访问所有跨媒体发布的伟大锁定内容,并在我的 feed 上发布关于各种数据科学、机器学习和深度学习主题的内容。

关注我 中型阅读更多关于各种数据科学和数据分析主题的文章。更多机器学习的动手应用,数学和统计概念查看我的*Github*账号。
我欢迎反馈,可以联系LinkedIn。****

快乐学习!***

简单的复制粘贴改变了计算机视觉问题的游戏规则

原文:https://towardsdatascience.com/simple-copy-paste-is-a-game-changer-for-computer-vision-5858a9445caa?source=collection_archive---------14-----------------------

理解大数据

来参加使用 Google 的复制粘贴数据增强的 SoA 计算机视觉模型之旅吧

张艺Unsplash 上拍照

如果你被要求建造一个书架,你对你需要什么的猜测应该不会太远,但是你能想象你需要什么来建造一个两层楼的房子,甚至像圣家堂这样的建筑吗?我不知道每个积木是如何设计和雕刻的,直到我参加了一个旅行团。卷积神经网络(CNN)无疑是计算机视觉模型的主要组成部分,就像圣家族教堂的石头一样;然而,仅仅分析 SoA(最先进的)模型的架构是不够的。在这篇博文中,我想邀请你参观一下计算机视觉中当前 SoA 模型的每一个构建模块(截至 2021 年 2 月 1 日)。目标是不经常跟踪 SoA 模型的人,目的是在不显示数学公式的情况下提供现代模型架构的剖析,并引导读者根据他们的背景和热情找到他们想要进一步研究的任何领域。

在计算机视觉中,SoA 模型的架构已经变得越来越复杂,该领域的进步不仅来自于模型架构的改进,还来自于数据的增加。谷歌研究和大脑团队提交了一篇应用随机复制粘贴数据增强的论文,截至 2021 年 2 月 1 日,他们在 paperswithcodes.com 的用 Yolov4-P7 的 COCO 测试开发数据集在目标检测上夺回了领先地位。

截图由作者于 2021 年 2 月 1 日在paperswithcodes.com拍摄。

该模型的名称是级联 Eff-B7 NAS-FPN,具有自我训练和复制粘贴功能。模型名称的每一项都包含了伟大研究者的贡献。为了以结构化的方式解释模型架构,我将主题分成了两个领域:模型架构和数据扩充。让我们深入了解每个构建模块。

作者创建的图表。

首先,将这个冗长命名的模型分解为 Cascade Eff-B7 NAS-FPN (上半部分)和自训练复制粘贴(下半部分)。第二,级联 Eff-B7 NAS-FPN 进一步分解为 Cacade R-CNN (2018)efficent net B7(2020)NAS-FPN (2019) 。第三,NAS-FPN 包括两个组件: NAS(神经架构搜索,2017)FPN(特征金字塔网络,2017) 。然后,让我们看看下半部分的数据扩充。自我训练复制粘贴(2020) 由两个研究贡献:自我训练(2020)复制粘贴(2018) 。我们参观这些组件的行程安排如下。

目录

一、数据扩充

  1. 复制粘贴增强
  2. 自我训练复制粘贴
  3. 什么时候我们应该应用自我训练复制粘贴?

二。模型架构

  1. 效率网
  2. FPN(特征金字塔网络)
  3. 神经结构搜索
  4. NAS-FPN
  5. 级联 R-CNN

三。关闭

数据扩充

数据扩充的目的是通过对现有图像应用合成变换来增加数据集的大小。数据扩充的传统方法是随机裁剪、旋转、缩放、水*或垂直变换的组合。其他方法是改变图像的对比度或亮度。更高级的方法可以是填充雨的效果,太阳耀斑,甚至敌对的噪音。当您组合这些转换方法时,增加的数据如下所示。由于适当的数据扩充,计算机视觉模型的性能有望变得更加稳健和准确。

来源是 Alexandra Deis 帖子中的图片。

如果您没有使用过数据扩充,Sumit Sarin 的文章是一个很好的起点,因为它展示了带有代码的介绍性示例。此外,你可以在 AgaMiko 的知识库找到各种传统和现代的图像和音频数据增强方法。

复制粘贴增强

我们终于要去访问的文件,“简单的复制粘贴是一个强大的数据增强方法,例如分割。”一些一直在跟踪这个领域的读者会认为复制粘贴方法自 2018 年就已经存在了!作者讨论了与相关作品的不同之处:1)大规模抖动(LSJ),2)自训练复制粘贴,3)不考虑图像背景的简单随机复制粘贴,以及 4)不应用几何变换(如旋转)。让我深入探讨一下前两点。如下图所示,一幅图像的裁剪实例(不是整个边界框)被粘贴到另一幅图像的随机位置上,抖动很大。通常,标准比例抖动从 0.8 到 1.25,但作者通过应用从 0.1 到 2.0 的大比例抖动获得了明显更好的模型性能,这非常有趣。

来源是图 2 的简单复制粘贴纸。

自我训练复制粘贴

复制-粘贴方法被应用于附加的未标记图像以及具有标记的监督数据。该研究使用了标记的 COCO 数据集(118K 图像)以及未标记的 COCO 数据集(120K 图像)加上 Objects 365 数据集(610K 图像)。这个过程非常简单。

  1. 在标记数据上训练具有复制粘贴增强的监督实例分割模型;
  2. 使用步骤 1 中训练的模型在未标记的数据上生成伪标签;
  3. 将地面实况实例粘贴到伪标记和监督标记的图像中,并在此新数据上训练模型。

步骤 3 中的关键是我们只粘贴来自真实情况的实例,而不是伪标签实例。你可以从 Google Brain 的论文反思预训练和自我训练中了解更多关于自我学习的内容。根据这篇论文,自我训练可以使机器学习方法在更少的数据下更好地工作。对于一些复杂的情况,通过自我训练的伪标签可以比人类更好地标注。

来源是反思培训前和自我培训论文的图 4。

请查看附录中的“自我训练中伪标签的可视化”一节,因为有更多的伪标签示例。

什么时候我们应该应用自我训练复制粘贴?

正如您可能已经意识到的,您需要注释边界框和实例,即使您的最终目标是开发一个对象检测模型。作者发现,与相应的基线模型相比,当可用的标记数据集更少时,应用带有自我训练的复制-粘贴的 Box AP 的增加更高。当仅使用标记的 COCO 数据集的 10%时,在大规模抖动之上,效率是基线模型的 4.8 盒 AP(包围盒*均精度)。因为工作量非常大,所以当数据集很小时,并且项目中有足够的资源进行标注时,使用这种方法更现实。

模型建筑

我们已经了解了在中使用的数据扩充技术。“简单的复制粘贴是一种用于实例分割的强大的数据扩充方法。”让我们继续我们的旅行,了解论文的引擎,级联 Eff-B7 NAS-FPN 。让我只关注每个组件的整体工作原理。我选择了以下主题的顺序,以便比其他主题更早地涵盖更重要的构建模块。

效率网

EfficientNet 是谷歌在 2019 年开发的一种非常强大的模型创建方法。它旨在确定与给定数据集相对应的神经网络的最佳架构。这些曾经是我们面临的常见问题。

是否应该增加神经网络的深度?是否应该增加每层的通道数量?或者说,是不是应该提高每一层的分辨率?

EfficientNet 控制深度、宽度和输入分辨率值,以有效地扩大基线神经网络。除了这些控制变量,我们还需要注意优化模型中的资源约束。例如,预算是收入优化模型的约束条件。如果我们可以忽略预算,我们应该选择更多的劳动力和更多的资本来达到更高的生产水*。在 EfficientNet 中,我们设置深度、宽度和分辨率值的乘积必须小于某个阈值。在这种资源约束下,我们可以通过限制所需的计算能力来有效地实现最佳的神经网络架构。例如,如果模型增加深度和宽度,它必须降低分辨率以满足资源约束,这样模型就不会要求超过我们所能承受的计算资源。

来源是效率网论文的图 2。模型缩放。(a)是一个基线网络示例;(b)-(d)是仅增加网络宽度、深度或分辨率的一个维度的传统缩放。(e)是 paper 提出的复合缩放方法,它以固定的比例统一缩放所有三个维度。

高效扩展的 conv net是理解高效网络概念的重要资源。

高效网-B7

你仍然会有一个问题;什么是 B7 的结尾?模型的复杂程度可以用 FLOPs(每秒浮点运算次数)来定义。FLOPs 表示每秒执行的加法或乘法次数。例如,EfficientNet-B0 进行了 3.9 亿次浮点运算,而 B7 进行了 370 亿次浮点运算。这意味着 B7 在约束中有更高的预算/资源,但是 B7 也需要更高的计算能力来从搜索空间中找到最优值。您可以记住“B”之后的较大值需要更高规格的机器,并且通常需要更大容量的数据集作为输入来微调预训练的模型。

FPN(特征金字塔网络)

检测图像中不同大小的物体一直是计算机视觉中的一个基本难题。人们过去常常使用尺度不变特征变换来解决没有神经网络的相同问题。要素金字塔用于检测不同比例的对象。FPN 致力于让系统识别照片中站在远处的小狗和坐在摄影师前面的大狗可以属于同一“狗”类别。 SSD(单次多盒探测器,2016) 是另一种通过创建不同比例的特征地图来克服这一问题的有用方法。根据 FPN (2017) 的论文,FPN 有两个优势。首先,它重用不同比例的功能图,以自下而上的方式继承 SSD 的优势。第二,FPN 合并两个编码的见解:一个具有来自自顶向下路径的语义强但粗糙的分辨率,另一个具有来自横向连接的语义弱但高的分辨率,以增强对象检测中的性能,从而提高模型性能。

来源是 FPN 论文的图 2。

NAS(神经架构搜索)

NAS (2017) 是一种使用搜索算法从所有可能的架构中自动找到最大化关键指标的最佳架构的方法。对于不熟悉现代建筑的人来说,传统的神经网络是线性连接的(下面左边的模型),但是现代的神经网络有分支和跳跃连接(下面右边的模型)。

来源是图 3.2。神经架构搜索

让我用一个 DARTS(可区分架构搜索)的优化过程来说明一个单元搜索算法的例子。下面的四个图(a)到(d)显示了运行优化的步骤。首先,(a)是优化中的初始状态。每个带数字的方框就是一个节点,节点之间通过有向边连接,这是一条单向路径。节点 0 是输入,节点 1 是输出。

来源是飞镖纸的图 1。

在运行搜索算法之前,我们不知道应该如何连接节点,包括跳过连接。跳过连接的一个例子是在节点 0 和 3 之间。跳过连接是 ResNet (2015) 中用来克服消失梯度问题的一个非常重要的概念,这是研究它的一个很好的资源。节点之间不同颜色的边代表不同类型的卷积层和最大池层。DARTS 通过以下步骤确定最佳架构。在状态(a)中,飞镖不知道边缘。在状态(b)中,它在每个边上放置候选操作的混合,并且它使用状态(c)中的候选边来解决双层优化问题。最后,它归纳出状态(d)中的最终架构。EfficientNet 的基线网络由MNAS开发。

NAS-FPN

NAS-FPN (2019) 的作者挑战优化 FPN 的架构。NAS-FPN 设计的体系结构不再像最初的 FPN 体系结构那样对称,但它仍然包含自上而下和自下而上的连接结构,以融合跨规模的功能。通过结合可扩展搜索空间和神经结构搜索(NAS)算法来实现结构优化,以克服金字塔结构搜索空间大的缺点。优化过程中的一个关键决策是两个任意特征图(具有强语义的高级特征和具有高分辨率的低级特征)是否需要通过两个二元操作中的一个来合并:求和或全局池。下面的图(a)是普通的 FPN,由 NAS 算法开发的不同 fpn 用*均精度(AP)表示,作为比较架构的检测精度。

来源是 NAS-FPN 论文的图 7。

强化学习用于优化模型架构。如何合并节点的决定由控制器递归神经网络(RNN)做出,因为构建块的顺序很重要。控制器对具有不同架构的子网络进行采样。可以想象,这些实验需要巨大的计算能力,作者在实验中使用了 100 个张量处理单元(TPU)。在保留验证集上产生的 AP 被用作更新控制器的奖励。大多数独特的架构在大约 8,000 步后就收敛了。最后,以下是在实验中 RL 训练期间所有采样架构中具有最高 AP 的架构。

来源是美国国家科学院-FPN 论文的图 6。该论文描述了“在 NAS-FPN 中发现的具有 5 个输入层(黄色)和 5 个输出特征层(蓝色)的 7-合并单元金字塔网络的架构”。GP 和 R-C-B 分别代表“全球统筹”和“conv-批处理”

级联 R-CNN(基于区域的 CNN)

级联 R-CNN 于 2018 年研发。目标检测中的一个传统问题是选择正确的交集/并集(IoU)阈值来训练模型和运行推理。如果使用低 IoU 阈值(如 0.5)训练对象检测器,它通常会产生噪声检测,并且检测性能往往会随着 IoU 阈值的增加而下降,因为较高的 IoU 往往会通过收紧框来产生假阴性。级联 R-CNN 的主要贡献是缓解这个问题,因为一系列检测器可以基于其下面的架构适应越来越高的 iou。

来源是级联 RCNN 论文的图 3。本文描述了模型的体系结构。“I”是输入图像,“conv”主干卷积,“池”区域特征提取,“H”网络头,“B”边界框,以及“C”分类。“B0”是所有架构中的建议。

级联 R-CNN 具有四个阶段,一个 RPN 和三个 rcnn,用于以越来越高的阈值进行检测。本文中的实验在这些阶段使用 0.5、0.6 和 0.7 IoU 阈值。作者通过将一个粗略的结合盒方案交给下一阶段,通过增加每个阶段的 IoU 阈值来改进它,从而克服了过度拟合。结果,定位和检测的性能将优于具有一个 IoU 阈值的模型。详细的论文综述可在阅读:级联 R-CNN——深入研究高质量物体探测(物体探测)获得。

关闭

我原本计划在 Yolo v4 成为对象检测领域的最佳模型后,写一篇关于用交叉部分网络(CSP) 扩展 Yolo v4 的博文;然而,Cascade Eff-B7 NAS-FPN 通过自我培训复制粘贴,在排行榜上压倒了其他车型。我很高兴看到它自 2020 年 12 月中旬以来一直排名第一。2020 年物体探测的竞争非常激烈,最初的模型通常每个月至少更换一次。在 CNN 模型的这些竞争之上, Vision Transformer 由谷歌推出,我预计这种基于 Transformer 的架构将在 2021 年繁荣起来。如果你对 NLP 中的 Transformer 架构感兴趣,请阅读我之前的文章。

我希望你喜欢我的旅行。尽管带有 CSP 的缩放 Yolo v4 不再是最好的模型,但我喜欢 Yolo 系列的框架来训练模型,因为它们非常用户友好。我对我们的下一次旅行有一些想法。它可能是关于使用 Scale Yolo v4 和 CSP 代码微调模型的教程,或者是关于基于 EfficientNet 的新模型(如 EfficientNet Cascades )的论文综述。我列出了我在本文中介绍的有用模型的 Github 资源库的链接,以便您可以使用它们!

GitHub 仓库

使用 RFM 分析进行简单的客户细分

原文:https://towardsdatascience.com/simple-customer-segmentation-using-rfm-analysis-1ccee2b6d8b9?source=collection_archive---------7-----------------------

Jonathan Pielmayer 在 Unsplash 上的照片

什么是 RFM 分析?

RFM 分析是一种客户行为细分技术。基于客户的历史交易,RFM 分析关注客户交易的 3 个主要方面:最*频率购买金额。了解这些行为将使企业能够将不同的客户分组。

我如何应用 RFM 分析?

数据集

这是一家商店的数据集,其客户来自世界各地。它包括发票号、发票日期、客户 id、库存代码、产品描述、购买数量和客户所在国家等信息。在本文中,我将只向您展示我进行 RFM 分析的方法,而不是清理数据集的步骤。 下图 1 & 2 是我的数据集经过编辑变换后的结果。

图 1:我的数据集可视化(df5)

图 2: df5 信息

RFM 分析

首先,我将在我的分析中澄清 RFM 的定义。

  • Recency (R) :顾客购买的时间。
  • 频率(F) :顾客购物的频率。
  • Monetary (M) :顾客为他们的购买支付了多少钱。

接下来,我将为每个客户计算这 3 个组成部分。

*因(R)

import datetime###Calculate total_amount of money for each order
df5.InvoiceDate = pd.to_datetime(df5.InvoiceDate)df5['amount'] = df5.Quantity*df5.UnitPricedf6=df5.copy()###Taking a reference date to calculate the gap between this reference date and the last purchase date of each customer.
The gap can be referred as the recency of each customerreference_date = df6.InvoiceDate.max() + datetime.timedelta(days = 1)df6['days_from_last_purchase'] = (reference_date - 
df6.InvoiceDate).astype('timedelta64[D]')lastpurchase_day = df6[['CustomerID','days_from_last_purchase']].groupby('CustomerID').min().reset_index()lastpurchase_day.rename(columns={'days_from_last_purchase':'recency'}, inplace=True)

在计算每个客户最后一次购买后的天数后,我得到如下输出:

图 3:客户的新*度

频率(F)

###Calculate number of orders purchased by each customer
freq = df6[['CustomerID','InvoiceNo']].groupby(['CustomerID','InvoiceNo']).count().reset_index().\
groupby(["CustomerID"]).count().reset_index()freq.rename(columns = {'InvoiceNo':'frequency'}, inplace = True) 

客户频率的结果如下:

图 4:客户的频率

货币(M)

###Total amount of money spent per customer
money = df6[['CustomerID','amount']].groupby('CustomerID').sum().reset_index()
money.rename(columns = {'amount':'monetary'}, inplace = True) 

输出:

图 5:客户的货币

最终,当我将这 3 个指标结合起来时,这里是每个客户的 RFM 信息。

图 6:客户的 RFM

RFM 得分

在获得每个客户的 RFM 信息后,我会根据每个买家的 RFM 数据给她/他一个 RFM 分数。我的评分基准将取决于每个指标的百分比。详细的,可以看下面的代码做更多参考:

###Calculating quantile values
quintiles = rfm[['recency', 'frequency', 'monetary']].quantile([.2, .25, .3, .35, .4, .5, .6, .7, .8, .9]).to_dict()###Benchmark to give score for recency indicator
def r_score(r):
    if r < quintiles['recency'][.2]:
        return 3 
    elif r < quintiles['recency'][.8]:
        return 2
    else: 
        return 1###Benchmark to give score for frequency & monetary indicator.   
def fm_score(f): 
    if f > quintiles['frequency'][.8]:
        return 3
    elif f > quintiles['frequency'][.2]: 
        return 2
    else: 
        return 1

将此规则应用于数据框:

rfm2 = rfm.copy()
rfm2['r_score'] = rfm2.recency.apply(lambda x: r_score(x))
rfm2['f_score'] = rfm2.frequency.apply(lambda x: fm_score(x))
rfm2['m_score'] = rfm2.monetary.apply(lambda x: fm_score(x))
rfm2['rfm'] = rfm2['r_score'].map(str)+rfm2['f_score'].map(str) + rfm2['m_score'].map(str)

每个顾客现在都有一个 RFM 分数:

图 7: RFM 分数

RFM 聚类

现在,这是我最喜欢的一步,因为我可以按照我想要的方式来分组。但是,在对客户进行分类时,考虑您的业务情况是很重要的。不同的商业目的会产生不同类型的分组,进而产生不同的策略。

在这一部分,我将把我的客户分成 7 组,每组标记如下:

###Loyal Customers, who are the champions of all the customers with highest score of RFM. 
rfm2_group1 = rfm2[rfm2['rfm']=='333']
rfm2_group1['label'] = 'champion'###Customers who have the most potential to become the Champions. They recently buy the products and they make their purchases quite frequently. Moreover, the amount they spent is quite great. rfm2_group2 = rfm2[rfm2['rfm'].str.contains('332|331|323|313')] 
rfm2_group2['label'] = 'potential1'###Customers whose frequency score and monetary score are slightly lower than potential 1 group
rfm2_group3 = rfm2[rfm2['rfm'].str.contains('321|322|311|312')] 
rfm2_group3['label'] = 'potential2'###Customers who used to pay a lot of money and come to the store frequently. They did not purchase recently. 
rfm2_group4 = rfm2[rfm2['rfm'].str.contains('233')]
rfm2_group4['label'] = 'needing_attention1'###Customers who do not come to store often and not frequently make purchases.
rfm2_group5 = rfm2[rfm2['rfm'].str.contains('223|213|212|231|232|211|221|222')]
rfm2_group5['label'] = 'needing_attention2'###Customers who haven't paid a visit to the store for a long time. However, once in a while, they do spend lot of money
rfm2_group6 = rfm2[rfm2['rfm'].str.contains('132|123|113|133')]
rfm2_group6['label'] = 'lost1'###Customers who churn
rfm2_group7 = rfm2[rfm2['rfm'].str.contains('111|112|121|122|131')]
rfm2_group7['label'] = 'lost2'

结论

以上是对 RFM 的简单分析。然而,当结合其他深层分析时,RFM 可能更有意义。我希望这篇文章能对你今后的工作有所帮助。

简单的仪表盘,只需 Jupyter

原文:https://towardsdatascience.com/simple-dashboards-just-with-jupyter-187c4ea2502d?source=collection_archive---------14-----------------------

有时候一辆小型货车就够了,你却送来一辆卡迪拉克

粘土银行Unsplash 拍摄的照片

有一种东西叫做合适的工作工具。当您或您的组织可以使用昂贵的可视化软件,如 Tableau、Power BI 或 Domo 时,每个问题看起来都像钉子,您的程序就是锤子。如果你是这样一个组织的数据分析师,你将不可避免地在其中一个仪表板上花费无数的时间,并嵌入公司高级决策者可能提出的任何问题的每一个可以想象的答案,只是为了在一周后收到一封电子邮件,其中包含一些请求,表明甚至没有人在使用仪表板的最基本功能。我不能假装知道为什么有些人(尤其是高层管理人员)不喜欢交互式 Tableau 应用程序的美妙之处,因为条形图、传单和折线图都以完美的和谐方式同步在一起,但这可能是因为整天不处理数据的人天生不知道如何导航这样的东西,也不想花费任何宝贵的时间来试图弄明白它。

与其处理所有这些麻烦,不如考虑使用 Jupyter Lab,结合基本的 Python 和 markdown 来创建简单的可视化,导出到 HTML 或 PDF 文档中,直奔主题,基本上不需要任何维护成本,并且可以在几个小时内完成。我并不认为这样的东西适合所有情况,但它可能是箭筒中的一支箭,因为无论谁需要仪表板,快速浏览数据就可以了,而不是一个完美的视觉辅助工具的马赛克。我发现许多高层可以更容易地访问如此简单的东西,并意识到只需投入很少的资源来设置和维护它。

https://github.com/mikekeith52/JupyterDashboard

安装和导入数据

蟒蛇

首先,我建议使用 Anaconda 来运行 Jupyter 实验室。有许多资源描述了如何做到这一点——我特别喜欢来自熊猫的指南。我个人在 Windows 上使用 64 位图形安装程序 Anaconda 发行版(点击这里下载)来运行我的大部分 Python 应用程序,但是我知道还有其他的方法。使用对你的情况最有意义的东西。

安装 Anaconda 之后,您应该能够通过打开 Anaconda Navigator 并在 JupyterLab 应用程序框中选择 Launch 来运行 Jupyter Lab。

作者图片

您也可以通过在 Anaconda 提示符下键入“jupyter lab”来启动它。

Nbconvert

接下来,您需要安装 Nbconvert。我推荐阅读整个文档,以防你对我的总结有疑问。要安装它,请在 Anaconda 提示符下使用以下命令:

conda install nbconvert

Pandoc

要将最终产品导出为 HTML 文档,您需要安装 Pandoc。对于 Windows,建议使用安装程序,但也有其他安装方法。你可以在这里找到所有的信息。

我更喜欢将结果导出为 HTML 格式——速度快,最终产品看起来也很棒。但是您可以探索其他导出选项,包括 PDF 和 Latex。这些工具的安装更加复杂。同样,所有这些都可以在 Nbconvert 文档中找到。

导入数据

最后,让我们导入数据。我认为这意味着为大多数用户建立一个到数据仓库的 SQL 连接(对我来说通常是这样),但这也意味着从共享驱动器、API 等导入数据。这里重要的一点是,导入要在代码中没有警告的情况下完成。警告不会阻止您的代码工作,但它们会导出到最终的 HTML 文档中,除非您手动将它们从笔记本中清除。对于您运行的每个编码块都是如此。

对于这个例子,我将使用 GitHub 上的数据中的新冠肺炎疫苗接种数据。

以下是所需进口的清单:

import datetime
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
from IPython.core.display import display, HTMLpd.options.display.max_rows = None # to print tables
pd.options.display.max_columns = None # to print tablesdata_state = pd.read_csv('us_state_vaccinations.csv')
data_manufac = pd.read_csv('vaccinations-by-manufacturer.csv')

添加视觉效果

现在我们已经安装了 Jupyter Lab 和所有必要的附加组件,并且我们已经读取了数据,我们可以开始制作数据可视化。

对于这个例子,我将构建三个图形,并在输出中包含两个表格。我还会在 Jupyter 上使用 Markdown,以便在不同部分之间轻松导航。

图 1——按日期累计接种的疫苗

对于这个图表,我使用了一个折线图,其中显示了三个统计数据:分发的疫苗总数、接种疫苗的人数以及从 2020 年 12 月 15 日到现在(2021 年 4 月 15 日)完全接种疫苗的人数。这是一个非常简单的可视化,唯一潜在的挑战是将最后一个数据点放在每一行的末尾,使用 matplotlib text()函数给出各个组的总数字。下面给出了 Python 代码。

首先,准备数据:

然后,构建图表:

输出如下所示:

作者图片

图 2——各州管理的疫苗

接下来,用一个图表来表示美国各州/地区的表现。许多人表示这些统计数据的第一个想法是活页图表,它基本上是您正在绘制的区域的区域地图,不同的区域用阴影表示不同的密度。但是,在这种情况下,这些数据可能很难生成,也不像简单的热图那样直接获得相关的比较。让我们看看热图是什么样子的。

我们可以使用为之前的图表准备的数据。创建视觉帮助的代码:

输出是:

我们还可以在表格中添加这些信息,以及每个州的疫苗接种总数。代码包含在上面 GitHub 链接的笔记本中。

图 3——由制造商管理的疫苗

最后,让我们按制造商细分数据。对于这个图表,我们可以尝试一些更高级的东西:一个叠加了阴影线的堆叠条形图,代表 7 天的滚动*均线。让条形图和折线图之间的日期对齐可能很棘手,因为底层 matplotlib 函数默认为两个图表的不同日期表示。

准备数据的代码如下所示:

进行可视化的代码:

输出:

作者图片

让我感到惊讶的一件事是,强生疫苗的使用量如此之少。考虑到这是一种单剂量疫苗,我预计它会更受欢迎。即使是简单的可视化,也可以从数据中发现有趣的见解。

导出结果

现在我们有了三个可视化效果,我们可以将笔记本导出到一个 HTML 文档中。理论上有一种方法可以通过在代码中使用“%matplotlib widget”命令来使这些图表都是交互式的,但是我还不能在我的系统上使用它。欢迎评论中的任何建议。无论如何,export 命令涉及使用 Anaconda 提示符来运行两个命令:

cd local/path/to/jupyter/notebook
jupyter nbconvert --to html --no-input dashboard.ipynb

这将把一个 HTML 文档放在与笔记本相同的本地目录中。有关本例中使用的完整代码,请参见此处的

刷新分析

要用新数据刷新分析,只需确保已经建立了数据的实时提要(在本例中,我使用了需要重新下载的*面文件)。然后,在 Jupyter 笔记本打开的情况下,在浏览器中选择“内核→重启内核并运行所有单元”就很容易了。确认您想要重新启动内核,然后在 Anaconda 提示符下重新运行上一节中给出的命令,您将获得新的输出,可以通过电子邮件发送给任何需要的人。这个过程比构建最先进的仪表板要简单得多,当您需要一些简单的东西并且您很快就需要它时,它会是一个有效的解决方案。

简单的开发人员开发的简单遗传算法(Python 语言)

原文:https://towardsdatascience.com/simple-genetic-algorithm-by-a-simple-developer-in-python-272d58ad3d19?source=collection_archive---------16-----------------------

作者的《他们在进化》;由谢尔盖·塞明、尤金·日夫奇克美国宇航局通过 Unsplash 拍摄的原始图像

在我们进一步讨论之前,尤其是在你开始评判我的代码之前,我需要做一些免责声明:

  • 我不是 python 开发者;所以如果你觉得我的 python 很烂,那么,好吧,你可能是对的,
  • 我绝不是进化算法方面的专家;接下来的代码只是我试图通过编写一个简单的实现来理解遗传算法,这是出于好奇心和多余的时间,
  • 性能不是我的主要关注点;我想要实现的是一个相当容易理解的代码,可以很容易地映射到文献中描述的概念。

我已经决定从零开始实现一切,主要基于关于该主题的两本书[1][2]。术语简单遗传算法在这里与作者在【1】中描述的上下文相同。记住这一点,如果你在实现中发现任何错误,我将感谢反馈。

到底什么是遗传算法?

遗传算法是一种找到问题解决方案的方法,它受到生物学的启发,或者更准确地说是进化的启发(如果你需要的话,这里有关于这个主题的不错的复习)。它也是更广泛的进化算法中最受欢迎的变体。基本的想法是从一组随机的解决方案开始(或者好的解决方案,如果你已经对这个领域有了相当的了解,并且知道一个好的解决方案可能是什么样子的话)。然后,对解决方案进行迭代评估,并从池中选择最佳方案,进行杂交和变异。这个过程重复固定的次数(代),或者直到找到一个完美的解决方案,随着时间的推移导致(希望)更好的答案。

要解决的问题

我们将把这些原则一步一步地应用到一个简单的、有点人为的问题上。你可能会认为用遗传算法来解决它就相当于用坦克打死一只苍蝇。你不会错的。但是,为了这篇文章,让我们假设计算器还没有被发明出来,这是计算 0-1048575(包括 0-1048575)范围内的整数的最大*方的最好方法。

鸟瞰图

在深入实施细节之前,让我们快速浏览一下该算法的高级概述:

  1. 从一堆解决方案开始,可能是随机的。
  2. 评估他们有多好。
  3. 挑选一些将被用来创造新的,理想的更好的解决方案。
  4. 从选定束创建对。每一对将产生两个新的解决方案。
  5. 以一定的概率对新创建的解决方案进行小的随机更改。
  6. 用新创建的解决方案替换以前的包。
  7. 坚持下去,直到找到一个完美的解决方案,你终于厌倦了,或者你已经到达了宇宙的热寂。

个体、群体和健康

在进化算法的背景下,每个解决方案被称为一个个体。在给定时间被认为是解决方案的一组个体被称为群体

每个个体可以通过其基因型来表征。基因型是算法直接操作的解的表示。问题领域中的实际解决方案被称为个体的表型(一个基因型总是转化为一个表型,然而一个特定的表型可能由多个不同的基因型获得)。

为了更具体一点,让我们考虑一下这在我们的问题中意味着什么。我们用来代表个体的基因型是一个二进制数。表现型是它的*方,用十进制整数表示。

为了表示我们操作的整数范围,我们需要一个长度为 20 的基因型(2 ⁰ = 1048576),这意味着基因型在 0000000000000000000(二进制 0)和 11111111111111111(二进制 1048575)之间。例如,基因型为 00000000000000000101 的个体的表型将等于 25 (5)。

适合度是衡量解决方案有多好的指标。在我们的例子中,我们可以简单地用个体的表型作为它的适应度:代表个体基因型的数字的*方越大,它的适应度越高。在上面的例子中,个体的适应度等于 25。

让我们来看看一些代码:

GenotypeDecoder类用于在基因型(这里表示为二进制数字串)和相应的表现型之间进行转换。FitnessEvaluator评估给定基因型的适合度。在我们的例子中,这直接对应于个体的表型,所以使用解码器。

一个Individual有两个属性:genotypefitnessIndividualFactory包装新的个人创作逻辑,并提供三种方法:

  • with_random_genotype创建一个具有随机基因型的个体——用于在最开始创建一个随机群体作为起点,
  • with_set_genotype创建具有提供的基因型的个体——当通过繁殖上一代的两个个体来创建新个体时使用。
  • with_minimal_fitness创建一个基因型仅由零组成的个体——用于创建一个适应度为 0 的个体群体的替代起点。

Population类持有个人的集合。它提供了一种通过get_the_fittest方法获得最适个体的方法。PopulationFactoryIndividualFactory的对应物,提供了用随机个体、给定个体和最小适应度个体创建群体的方法。

亲本选择和存活选择

创建新一代解决方案的第一步是从当前群体中选择将成为父母的个体(父母选择)。新创建的个体被称为后代。决定为下一代保留哪些个体被称为生存选择。

进行亲本选择有许多可能的方法。在我们的例子中,我们将采用适合度比例选择——个体成为父母的概率直接取决于他们的适合度。为此,我们将使用 随机通用抽样

这里的基本思想是创建一个尺度,由群体中所有个体的适应值组成,然后从随机点 p 开始,以 1/池大小的步长遍历该尺度,使得0 < p < 1/population size。例如,假设我们的交配池由适应值为 1,5,3,12,9,6 的个体组成。为了形象化标尺,想象一把标有以下数值的尺子:

[0, 1, 6, 9, 21, 30, 36]

我们从 0 开始,并在标尺上的先前标记上添加一个新的适应值,因此 0 -> 0 + 1 = 1 -> 1 + 5 = 6 -> 6 + 3 = 9 ->等等。

现在,我们选择一个步骤,我们将沿着标尺移动。总的适应度等于 36 (1+ 5 + 3 + 12 + 9 + 6),群体中有 6 个个体,所以我们准备从范围(0,36/6 = 6)中选取一个随机数作为初始偏移量。步长将等于 36/6 = 6。

假设我们的随机偏移量是 2。我们从 2 开始,并在我们的尺子上检查这对应于哪个个体——在这种情况下是指数为 1 的个体(尺子上的范围在 1 和 6 之间)——因此这个个体将被挑选到交配池。我们把步长加到当前位置,所以 2 + 6 = 8。我们重复与前面相同的过程,将第二个人添加到池中(范围在 6 和 9 之间)。我们不断重复这一过程,直到我们到达了统治者的尽头,并以产生下一代的 6 个个体的集合而结束。

被选中的个体构成了交配池在我们的例子中,它的大小等于人口的大小。然而,这并不意味着我们选择每一个人。一些体能差的人根本无法游到泳池。另一方面,高度适合的人会不止一次出现在人才库中。这样,最佳解决方案更有可能产生后代,因此,*均而言,对下一代有更大的影响。

在我们的实现中,每一代都将完全取代上一代。这一点,加上每对父母将生育两个孩子的事实,将导致人口规模不变。

育种和突变

仅仅选择最合适的父母本身不会使我们走得很远。我们需要一种方法来将使个体适应下一代的特征传递给下一代。这就是交叉,或在我们的情况下一点交叉更准确地说,进来了。

杂交是另一个直接来自生物学的术语,意思是将两个个体(父母)的基因型结合成一对新的个体。例如,如果双亲的基因型为 000001111100000111111 和 111111110000000000,首先我们选择一个大于 0 且小于基因型长度(本例中为 20)的随机交叉点,比如 7。这意味着我们在第 7 位(0 索引)将两种基因型分开:

1a) 0000011   1b) 1110000011111
2a) 1111111   2b) 1110000000000

现在,我们通过将第一基因型的第一部分(1a)与第二基因型的第二部分(2b)以及第二基因型的第一部分(2a)与第一基因型的第二部分(1b)相结合来创建一对新的基因型:

1a) 0000011   2b) 1110000000000
2a) 1111111   1b) 1110000011111

新的基因型将成为后代。

除了使用现有的解决方案作为新个体的基础之外,我们还希望在这个过程中引入一些随机性(就像生物繁殖中的情况一样)。这是通过使用突变实现的。通过交叉创建的基因型中的每个位(基因)在创建新个体的最后阶段有小概率被翻转(0 变成 1,反之亦然)。在我们的例子中,我们将对每个基因突变使用 1/基因型长度的概率,因此在这种情况下 1/20 = 0.05。

我们将这两个概念封装在Breeder类中。它的produce_offspring方法以交配池为参数。

在每次迭代中,算法:

  1. 从池中随机挑选两个人。
  2. 通过杂交所选双亲的基因型来创造两个新个体。
  3. 改变新产生的后代的基因型。
  4. 将如此创建的个体添加到后代集合中,这些个体将成为下一代。

把所有的碎片放在一起

既然我们已经准备好了遗传算法所需的所有概念组件,我们可以将它们放在Environment类中。

它负责初始化群体,每次调用update方法时,它进行父代选择,产生后代,并用新的群体替换当前群体。此外,它还提供了一种通过get_the_fittest方法从当前群体中获得最合适个体的方法。

最后,我们需要实例化所有部分,决定一些参数(例如,世代数、基因型长度等。),不断迭代,直到我们找到解决方案或者失去耐心。

我们将选择一个适中的 10000 代,人口为 50 人(如果您修改这个数字,请记住它必须是偶数)。最后,在算法完成后,我们打印出最适合的个体的基因型和它被创建时的代号,并绘制出每代中最适合的个体的适应度。

每一代中最适合的个体在 1024 代中结束。

结果

如果您有足够的勇气运行代码,并且不止一次地运行,您将会注意到找到解决方案的代在运行之间有很大的不同。这可以用算法固有的随机性来解释。

您可能希望调整算法的参数,如种群大小和突变概率(例如,增加种群大小很可能会更快地找到解决方案)。此外,您可能希望从最小适应度的群体开始,而不是从随机群体开始,并看看这如何改变几次运行所需的迭代次数(在Environment类中用self.population = self.population_factory.with_minimal_fitness_individuals(size = population_size)替换self.population = self.population_factory.with_random_individuals(size = population_size)行)。

希望这篇文章和代码能让遗传算法的一些核心概念更容易理解。该实现虽然远非完美,但应该足够模块化,并且易于通过根据需要切换算法的部分(例如,如何表示个体、适应度函数、单点交叉与 n 点交叉等)来修改。).作为一个 jupyter 笔记本,你可以在这里找到完整的代码。

参考资料:

[1] A.E .艾本,J.E .史密斯。 进化计算简介

[2]圣路加。 元启发式 要领。

我如何在 VSCode 中为小型项目使用 GitHub

原文:https://towardsdatascience.com/simple-github-integration-with-vscode-3d7a3db33047?source=collection_archive---------16-----------------------

GitHub 是一个分享代码并保证其安全的好方法——vs code 是一个很棒的编辑器,可以与 GitHub 无缝协作

照片由 Fotis FotopoulosUnsplash 上拍摄

我不需要成为 GitHub 专家。我不需要在开发团队之间共享代码,也不需要拥有最终将被合并到一个产品中的多个版本的代码,或者做任何其他你可以用 Git 和 GitHub 做的美妙事情。

我所需要的就是为我创建的小项目准备一个可以与他人共享的存储库。我希望能够从不同的计算机和/或位置轻松访问我的代码。VSCode 和 GitHub 的结合简单而容易地做到了这一点。

使用 GitHub 还意味着我可以在多台机器上工作,随心所欲地使用 Windows 和 Linux,并且仍然可以在每台机器上保持代码同步和最新。

设置完成后,只需几次点击即可完成。

我将按照我自己的简单需求来运行我使用 GitHub 的步骤,所以如果你是 GitHub 专家或者你领导着一个远程工作的开发团队,在他们之间创建和共享文档和代码,那么你现在可能想要停止阅读——这不适合你。

但是如果你处在和我相似的位置,你创建了一些小项目,你想分享,同时保持你的代码安全可靠,并且你目前没有使用 GitHub,那么继续读下去。

Git 基础

GitHub 使用版本控制系统 Git 管理代码,对该系统的支持内置于 VSCode 中。你可以从他们的网站下载 Git,一旦安装,VSCode 应该能找到它。

从根本上说,Git 会跟踪您在代码中所做的任何更改——编辑一个文件,Git 就会知道。但是为了更新一个项目,你需要提交变更。提交有两个部分,首先,您将您想要的文件添加到提交中——这被称为 staging——然后,您实际上用一条短消息提交更改(通常描述您所做的更改)。通过这种方式,Git 保存了一个代码库,其中包含最新版本的最新文件以及所做更改的历史记录。

一旦你的代码版本被提交,它就可以被推到一个像 GitHub 这样的远程仓库,并与全世界(或你的团队)共享。

相反,一个版本的代码可以从远程存储库被到本地机器上进行处理,然后当你完成后被推回到远程存储库。

这就是我在 Git 和 GitHub 中使用的全部内容,所以我就不多说了。但是你可以在他们的网站上找到关于 Git 和 T2 GitHub 的全面文档。

设置 Github 帐户

为了使用 GitHub,你需要一个帐户,而获得一个帐户是很简单的。您需要您的电子邮件地址和密码,并且您需要选择一个尚未使用的用户名。然后你必须解决一个难题,以确定你真的是一个人——这并不难。

接下来,他们会给你发送一个启动代码,你输入就可以开始了。

他们会询问你如何使用 GitHub 以及你的兴趣,并给你选择你可能感兴趣的不同账户。有些账户每月收取少量费用,但有一个免费账户可能是你想要的。你可以看看其他可用的细节,但免费的给了我所需要的一切。

创建存储库

一旦你整理好了你的账户,你会想要创建一个仓库(在 Git 圈子里也被称为“回购”)。在您的主页上,您应该会看到类似这样的内容:

在 GitHub 中创建存储库—作者图片

点击“创建存储库”将弹出一个表单,您可以在其中命名回购,对其进行描述,并决定是公开还是私有。如果你把它公开,全世界都可以看到并下载你的代码。私有存储库是…它们是私有的。

在 GitHub 中命名存储库——作者图片

然后会要求您指定一些选项。创建一个自述文件是一个好主意,您可以在其中描述回购的目的及其内容,因此选择该文件,它将自动为您创建。

我通常不关心。gitignore —这是一种指示 Git 忽略您不想包含在 repo 中的特定类型文件的方式。

最后,选择许可证。选择哪一个完全取决于你,但是 GitHub 公共回购应该是开源的。

GitHub 中存储库的设置—按作者分类的图片

一旦你创建了你的回购,它会看起来像这样。README.md 文件是以回购协议的标题及其描述创建的,您可能希望以后更改它。

你在 GitHub 的第一个知识库——作者图片

现在,您已经有了一个可以下载到本地机器上的基本回购协议。为此,我们克隆回购。单击 code 按钮并复制 url —稍后您将在 VSCode 中使用它。

在 GitHub 中克隆存储库—图片由作者提供

在 VSCode 中克隆 repo

现在你需要打开 VSCode。关闭任何打开的文件或文件夹,并选择源代码控制图标。这使您可以选择打开一个现有的 Git repo 或克隆一个新的。我们要做的是后者。

在 VSCode 中创建存储库—按作者排序的图像

所以,点击克隆库,你会被要求提供一个 URL——这是我们刚才从 GitHub 网页上复制的,所以粘贴进去吧!

在 VSCode 中克隆存储库—按作者排序的图像

不要试图复制我的回购网址,因为虽然你可以克隆它,但你不能在以后把它推回 GitHub,而且你会浪费很多时间,因为你必须从头再来一遍!

点击回车键,系统会询问你是否想打开回购——你当然想。然后它可能会问你是否信任回购协议的作者——同样,你信任(你信任自己,对吗?).

一两秒钟后,您应该会看到:

VSCode 中的一个新存储库—作者图片

这是一个新创建的报告,包含自述文件和许可证。

现在我们要创造一些新的东西。创建一个新文件并保存它。例如

VSCode 中的新 Python 程序—作者图片

请注意,源代码管理图标现在有了一个通知—这是因为发生了一些变化。再次打开源代码控制图标,您可以看到改变了列表 prog1.py 。我们现在可以通过输入提交消息并点击Ctrl+Enter来提交这个更改。

源代码管理更改了 VSCode 中的 y-按作者排序的图像

现在,由于我们还没有转移变更,VSCode 会询问您是否想要自动转移它们,以及您是否应该总是这样做(或者从不这样做)。我从不费心准备事情,因为我总是希望我的所有更改都在提交中——如果你也想这样,那么选择总是。如果您选择从不,您将不得不手动进行分段。

自动暂存—按作者分类的图像

您应该注意到通知已经消失了。

现在,我们做这一切的全部目的是将我们的代码保存在 GitHub 上,所以已经做了更改,我们现在需要将它推到那里。从菜单中选择按钮

推送回购-按作者分类的图像

GitHub 需要知道你被授权推你的回购。下一步只会在你第一次连接 GitHub 时发生,之后它会自动连接。第一步:

允许登录 GitHub —图片由作者提供

这将打开一个浏览器窗口,并要求您以通常的方式登录 GitHub,以确认 VSCode 可以使用您的帐户。

当你完成后,本地回购将被推送到 GitHub。打开它,您会看到在 GitHub 版本的 repo 中有一个新文件——即与您本地机器上的文件完全相同。

更新的远程报告—按作者排列的图像

让我们对 VSCode 中的 prog1.py 进行另一项更改:

另一个变化——作者的图像

像以前一样提交并再次推动。这一次不应该有授权。推进应该会顺利进行。

在 GitHub 中点击 prog1.py,你应该会看到这个:

修改后的程序在 GitHub repo-image by author 中

程序的修改版本现在在远程存储库中。

现在,您可以在 GitHub 中对文件进行更改,并使用 Pull 命令将其恢复到 VSCode。要编辑文件,请单击铅笔图标。

编辑 prog1.py —按作者编辑图像

进行一些更改,然后点击提交更改按钮(您可以选择添加注释)。

提交 GitHub 中的更改—作者图片

现在你可以回到 VSCode 并修改,这样你在本地就有了新修改的回购协议。

将 repo 拉至 VSCode —按作者排序的图像

嘿,很快!

VSCode 中的提取文件—按作者排序的图像

因此,我们既可以远程进行更改,然后将它们拉至本地计算机,也可以在本地进行更改,然后推至远程存储库。

通过这些方法的组合,您可以让多台机器保持代码的最新版本。只需确保您的远程回购始终是最新的,方法是在编辑会话后将它作为您做的最后一件事来推送。

我希望演示我如何使用 Git 和 GitHub 是有用的。它只是触及了使用这些工具可以做的事情的表面,所以如果您有任何更好的想法或技术(或者如果您认为我做错了什么),请在下面随意评论。

一如既往,感谢阅读。如果你想知道我什么时候发表新文章,请考虑在这里注册一个电子邮件提醒

如果你不是一个媒体订阅者,那就注册吧,这样你就可以每月花 5 美元阅读尽可能多的文章。在这里注册,我会赚一点佣金。

使用 Python 和开放街道地图实现简单的 GPS 数据可视化

原文:https://towardsdatascience.com/simple-gps-data-visualization-using-python-and-open-street-maps-50f992e9b676?source=collection_archive---------2-----------------------

有一种简单的方法可以在地图上显示 GPS 数据。

蒂莫·维林克在 Unsplash 上的照片

当使用编程语言时,GPS 数据的可视化可能具有挑战性。一些有趣的 Python 包可以用于这种目的。但是,在某些情况下很难安装和使用它们,尤其是当你只有一个简单的任务要做的时候。本文将展示使用 Python 和开放街道地图(OSM)的简单而有效的 GPS 记录可视化方法。如果你想直接跳到代码,请访问 https://github.com/tisljaricleo/GPS-visualization-Python。

目标

下图显示了这种方法的目标。需要包括三个主要因素:

  1. 地图图像—以某种图像格式显示的地图,如。png,。jpg 等。
  2. GPS 记录-由(纬度、经度)对组成的记录。
  3. 地理坐标-从像素到地理坐标的转换。

GPS 可视化方法的最终结果(图片来源:作者)

设置和数据

使用下面代码最简单的方法是安装 VS 代码或其他一些 IDE 来编辑 Python 代码。Python Jupyter 笔记本用户可能会遇到一些问题或额外的设置。最简单的方法是直接从一个 ide 中运行 main.py 脚本。

对于本文,使用了一个小型 GPS 数据集,它是用我在口袋里放了两天的 Columbus V-990 记录器收集的。数据可以在 github 库获得。

这是一个简单的(纬度、经度)数据集,包含大约 35000 条记录,如下所示:

使用的数据集(图片作者:作者)

重要提示:要成功运行代码,数据必须按照上图所示的精确方式进行格式化。否则,代码将导致错误!

方法

在这里,我们将经历这个方法工作所需的所有步骤。完整代码,请访问 github 库

1.去拿地图

地图可以从https://www.openstreetmap.org/export下载。只需点击“手动选择不同的区域”来选择您需要的地图部分在这种情况下,写下左上角和右下角的坐标(45.8357,15.9645)和(45.6806,16.1557)。

导出 OSM 地图(图片作者:作者)

然后使用右侧的“共享”按钮将其导出。不要忘记选择“设置自定义尺寸”选项,并将视图与所选区域对齐。

2.Python 代码

导入包和数据:

要在图像上绘制地理坐标,坐标必须转换为图像像素。方法scale _ to _ img(gps _ coordinate,(image_height,image_width))获取 GPS 坐标,并根据图像的宽度和高度将其转换为图像坐标(像素)。

下图显示了将地理坐标转换为影像坐标的需要:

地理坐标和图像坐标的区别(图片来源:作者)

现在,我们已经在地图上绘制了 GPS 记录!如果你看下面的图片,如果有一些其他的元素,比如网格和地理坐标,看起来会更好。

OSM GPS 坐标的可视化(图片来源:作者)

这些额外的元素将使用 matplotlib 包添加:

最后的结果在这里:

使用 Python 和 OSM 实现 GPS 记录可视化的最终结果(图片来源:作者)

结论

当使用编程语言来自动化 GPS 数据时,GPS 数据的可视化可能是具有挑战性的。有一些有趣的 Python 包可以用于这种目的。但是,在某些情况下,可能很难安装和使用它们,特别是如果您只有一个简单的任务要做。

本文提出了一种简单而有效的 GPS 数据集可视化方法。我们使用 Python 和 OSM 构建了一个框架。文章中展示了所有的步骤,但是你可以在这里找到完整的代码:【https://github.com/tisljaricleo/GPS-visualization-Python】T4

如有任何问题或建议,欢迎评论或联系我!

领英:https://www.linkedin.com/in/leo-tisljaric-28a56b123/

参考

使用监督学习模型预测时间序列数据的简单指南

原文:https://towardsdatascience.com/simple-guide-on-using-supervised-learning-model-to-forecast-for-time-series-data-a570720add84?source=collection_archive---------6-----------------------

用 XGBoost 预测时间序列数据的未来值

照片由克里斯托弗·高尔拍摄自 Unsplash

时间序列预测已经成为一个热门领域,因为许多预测问题涉及预测未来的时间,以允许更好的决策和更有效地管理资源。

在本文中,我们将发现如何使用监督学习模型 XGBoost 来预测未来的销售值,该模型使用的数据集来自谷歌大查询-爱荷华州酒类零售预测的公共数据。(资料来源:爱荷华酒精饮料部)

目录:

  • 什么是时间序列数据?
  • 监督学习简介
  • 了解我们的数据集(EDA)
  • 预处理/格式化数据集
  • 时间序列数据的特征工程
  • 拟合模型

什么是时间序列数据?

时间序列数据通常由大多数公司生成,如销售数据、库存数据、财务数据、股票价格等。时间序列通常是指在一段时间内连续产生的数据序列,基于时间的属性在时间序列数据集中起着重要的作用。

一个简单的时间序列数据如下图所示。

时间序列示例(图片由作者提供)

  • 时间戳列指示收集值的时间。
  • Sales 列是当时产生的值。

预测模型将使用历史数据的知识来预测未来不同时间段会发生什么。有许多方法可以利用时间序列数据进行预测,如 SARIMA 萨里玛(自回归综合移动*均,季节性自回归综合移动*均),指数*滑模型,神经网络模型-如 LSTM(长短期记忆),以及机器学习方法,如决策树,SVM(支持向量机),XGBoost 等。上述所有方法都是时间序列预测的常用方法。现在,让我们来理解监督学习的概念。

监督学习简介

监督学习图解(图片由作者提供)

监督学习模型的目标是学习输入数据和输出数据(目标变量)之间的关系。模型将根据与已知输出一起提供的数据进行训练,并进行多次迭代训练,直到模型能够检测到输入数据和输出数据之间的潜在模式,从而使模型能够以高精度预测未知数据

上图是预测这是什么动物的监督学习问题的简单例子。输入数据是动物的图像和细节,如大小、长度、颜色、耳朵长度等。连同输出值,以便模型可以知道兔子应该如何。

这种相同的方法可以应用于时间序列数据,方法是重新构建数据集,使其看起来像一个监督学习问题,例如时间序列数据集中以前的值将用作预测未来值的输入变量。

了解我们的数据集:

如前所述,我们将使用一组来自谷歌大查询公共数据——爱荷华州酒类销售预测的数据。

谷歌大查询公共数据—爱荷华州酒类销售预测

我们来看看数据集——“2020 _ 销售 _ 培训”

训练数据集的示例视图(作者提供的图片)

这是一个数据集,包含 2020 年爱荷华州每周批发购买的酒。如上图中训练数据的示例视图所示,我们可以注意到每周的零售额已经按县、邮政编码、城市和商店名称进行了细分。让我们执行一些简单的数据探索,以更好地了解我们在 Big Query 中的数据集。

县、城市、邮政编码和商店数量的细分(图片由作者提供)

通过对数据集的简单查询,我们可以看到共有 119 个县的 1881 家不同的商店。

按国家/地区划分的总销售额—前 10 名(按作者划分的图片)

按国家对总销售额的进一步细分显示,“波尔克”的销售额在所有县中最高,其次是“林恩”和“斯科特”。我们将通过预测每周所有商店的总销售额来简化本教程,而不是预测每个商店、城市、邮政编码或商店的总销售额。下面是用于计算每周总销售额的 SQL 查询。

With Table_A as (
SELECT date,
EXTRACT(ISOYEAR FROM date) AS isoyear,
EXTRACT(ISOWEEK FROM date) AS isoweek,
sum(sale_dollars) as Total_Sales FROM `bigquery-public-data.iowa_liquor_sales_forecasting.2020_sales_train`
group by date, EXTRACT(ISOYEAR FROM date), EXTRACT(ISOWEEK FROM date)
order by date)
select min(date) as Week_date, isoyear, isoweek, sum(Total_Sales) as Total_Sales_dollars from Table_A
group by isoyear,isoweek
order by min(date)

每周总销售额

上图显示了所有商店每周的总销售额。周值是根据 ISO 周编号从日期列中提取的。现在,让我们画出 2020 年每周的总销售量

每周总销售额(图片由作者提供)

从上面的图中,我们可以看出全年的总销售额没有任何季节性趋势,但我们也注意到销售量随着时间的推移在逐渐增加。

“季节性是在一段时间内重复的模式,具有影响时间序列信号的长期相关性。”

现在,让我们从预处理数据集开始,并确定我们可以为模型构建什么特征。由于我们使用的是监督学习模型方法,我们需要将数据框定为监督学习问题。

预处理/格式化数据集

首先,让我们进行最基本的检查,看看数据集中是否有缺失值。

print(Train_Table.isnull().sum())

空记录的数量(按作者排列的图片)

从上面的结果中,我们可以看到数据集在所有列中都没有缺失值。接下来,如果您查看所提供数据的数据类型,您会注意到我们的日期列(“Week_date”)是字符串格式的。通过将数据类型更改为“日期”来格式化此列

Train_Table['Week_date'] = pd.to_datetime(Train_Table['Week_date'], errors="coerce")

将 Week_date 列从“字符串”类型转换为“日期时间”(图片由作者提供)

日期列(“Week_Date”)是基于时间的列,需要转换为 DateTime 对象。使用正确的数据列格式,我们可以基于日期列索引数据框。

时间序列数据的特征工程

在构建模型之前,我们需要使用一组要素/输入变量(x)和输出变量(y 目标)来重新构建数据集。以下是在时间序列数据集上生成的常见特征:

  • 滞后期 : 滞后值 (如昨天、上周、上月等。)

在这个例子中,因为我们的数据集是按周的,所以数量值滞后一周。

#Python shift() function 
Train_Table['Total_Sales_Dollars_lag1'] = Train_Table['Total_Sales_dollars'].shift(1)

“Total_Sales_Dollars_lag1”功能已创建(图片由作者提供)

  • 移动*均滞后期 : 过去 X 小时/天/周的移动*均

创建移动*均特征是为了消除特定时间段内异常值和波动的值和影响。在本例中,我们创建了一个滞后 1 周的滚动 2 周*均值,以避免数据泄漏。

#Python rolling().mean() function 
Train_Table['Total_Sales_Dollar_MA2_lag1'] = Train_Table['Total_Sales_dollars'].rolling(2).mean().shift(1).reset_index(0,drop=True)

“Total_Sales_Dollar_MA2_lag1”功能已创建(图片由作者提供)

差异 : 当前小时/日/周/月值减去前一小时/日/周/月值(例如,昨天的值与上周同一天的值的差异)

计算与先前值之差的要素被视为趋势要素。在本例中,我们计算了本周与前一周的差值,相差 1 周。

#Python diff() function 
def difference(data, feature):
    # assume data is already sorted
    return data[feature] - data['Total_Sales_dollars'].shift(1)Train_Table['Total_Sales_Dollar_Difference_lag1'] = difference(Train_Table,'Total_Sales_dollars').shift(1)

“Total _ Sales _ Dollar _ Difference _ la G1”功能已创建(图片由作者提供)

除此之外,我们还可以创建计算当前值和以前值之间的百分比变化的特性。在本例中,我们将计算当前周与前一周相差 1 周的百分比变化。

def difference_in_percentage(data, feature):
    # assume data is already sorted
    lag_by_1 = data[feature].shift(1)return (data[feature] - lag_by_1)/(lag_by_1)Train_Table['Total_Sales_Dollar_Difference_in_Percent_Lag1'] = difference_in_percentage(Train_Table,'Total_Sales_dollars').shift(1)

“Total _ Sales _ Dollar _ Difference _ in _ Percent _ la G1”功能已创建(图片由作者提供)

  • 时间戳分解 : 一周中的某天、一月中的某天、一年中的某月、工作日或周末。

日期中的年、月、周和日的值也可以用作数字特征。在本例中,我们已经使用 SQL 查询提取了周和年。但是如果我们要使用 python 来执行,我们可以通过以下方法来实现:

Train_Table['week'] =Train_Table['Week_date'].dt.week
Train_Table['month'] =Train_Table['Week_date'].dt.month
Train_Table['year'] =Train_Table['Week_date'].dt.year

创建了“年”、“月”、“周”功能(图片由作者提供)

可以创建的其他特征是— 统计值,例如 昨天、上周、前两周等的最小值、最大值、*均值、标准偏差值。

到目前为止,我们应该已经生成了一组供模型使用的特性。现在让我们进入下一步——拟合模型。

拟合模型

首先,确定哪些是可以使用的特性,哪些应该被索引。在此处的示例中,我不会采用“Year”特性,因为培训数据属于同一年,并且将对“Week_date”列进行索引。

Train_Table = Train_Table [['Week_date', 'Total_Sales_dollars', 'Total_Sales_Dollars_lag1','Total_Sales_Dollar_MA2_lag1','Total_Sales_Dollar_Difference_lag1','Total_Sales_Dollar_Difference_in_Percent_Lag1', 'month','week']]Train_Table = Train_Table.fillna(0)Table = Train_Table.set_index('Week_date')

按“周日期”选择的功能和索引(图片由作者提供)

接下来,我们将根据 80:20 规则将数据分为训练集和测试集。

from sklearn.model_selection import train_test_splittraining_data, testing_data = train_test_split(Table, test_size=0.2)
print(f"No. of training examples: {training_data.shape[0]}")
print(f"No. of testing examples: {testing_data.shape[0]}")

将数据分为 x_train、y_train、x_test 和 y_test —输入(x)和输出(y)

x_train, y_train = training_data.drop("Total_Sales_dollars", axis=1), training_data['Total_Sales_dollars']
x_test, y_test   = testing_data.drop("Total_Sales_dollars", axis=1) , testing_data['Total_Sales_dollars']

将数据集分为输入(x)和输出(y)后,我们可以导入 XGBoost 模型库,并用训练集拟合模型。

import xgboost as xgb
from sklearn.metrics import mean_absolute_errormodel = xgb.XGBRegressor(n_estimators=1000)
model.fit(x_train, y_train,
        eval_set=[(x_train, y_train), (x_test, y_test)],
        early_stopping_rounds=50, #stop if 50 consequent rounds without decrease of error
        verbose=False) 

模型定型后,将模型应用于测试集并评估模型性能。这里使用的性能指标是*均绝对误差(MAE)。MAE 是基于预测误差值的*均值计算的,误差值被转换为正值。有许多不同的性能指标可供使用,如误差比、均方误差。如果你感兴趣,你可以参考这篇文章,它列出了不同的性能指标——时间序列预测的各种性能指标

preds = pd.DataFrame(model.predict(x_test))

衡量模型性能:

from sklearn.metrics import mean_absolute_percentage_errormean_absolute_percentage_error(y_test, preds)

MAE 错误率(图片由作者提供)

为了获得更好的准确性,我们可以在维持集(模型看不到的另一个测试集)上测试我们的模型。我们可以使用在同一个 Google 大查询公开数据集下已经提供和可用的数据—“2021 销售预测”。在将模型应用于测试集之前,应用相同的数据转换并创建用于训练模型的相同特征集。

在对维持数据集应用模型后,我们还可以绘制一个图表来比较实际值和预测值。

实际与预测的对比图(图片由作者提供)

正如你在上面的图中看到的,我们在 2021 年有几个星期的时间来测试模型。从图中,我们可以看到,模型预测在开始的几周并不匹配,但在接下来的几周内紧随其后,并在三月底偏离实际。模型表现不佳有几个原因,其中之一可能是由于训练数据不足,因为我们仅使用一年的数据来构建模型,并且没有足够的稳健特征供模型学习。

恭喜,我们已经理解了如何使用监督学习模型来构建时间序列预测。请注意,这只是一个简单的指南,现实生活中的示例将会更加复杂,您需要考虑创建许多不同的要素,例如用于捕捉假期/季节性趋势的 alpha 变量,从其他驾驶员的数据中生成有助于预测的要素,等等。

结论:

本文介绍了对时间序列数据特征的基本理解,以及如何将时间序列数据准备成可以应用监督机器学习模型(如 XGBoost)的预测问题。

感谢您阅读本文,希望本文对您有所帮助,能够帮助您踏上数据科学之旅的任何一步。

参考和链接:

[1]https://www.investopedia.com/terms/t/timeseries.asp

[2]https://machine learning mastery . com/xgboost-for-time-series-forecasting/

[3]https://machine learning mastery . com/time-series-forecasting-supervised-learning/

[4]https://search enterprise ai . tech target . com/definition/supervised-learning

[5]https://towards data science . com/everything-you-need-known-to-know-about-time-series-5fa 1834 d5b 18

[6]https://console . cloud . Google . com/big query(cameo:product/Iowa-department-of-commerce/Iowa-liquid-sales)

使用 Python 清理数据的简单指南

原文:https://towardsdatascience.com/simple-guide-to-data-cleaning-with-python-39203a14afeb?source=collection_archive---------6-----------------------

我们不希望看到垃圾进来,垃圾出去…

万花筒Unsplash 上拍摄的照片

在任何项目中,数据清理都是最关键的一步,如果我们处理不好,可能会得出完全不同的结论。通常,在大多数项目中,我们可能会花一半的时间清理数据。

在本文中,我将分享一些 Python 函数,它们可以帮助我们进行数据清理,尤其是在以下方面:

  • 删除未使用的列
  • 删除重复项
  • 数据映射
  • 处理空数据

入门指南

我们将在这个项目中使用熊猫,让我们安装软件包,如果我们没有它。

conda install pandas

为了演示的目的,我修改了 Kaggle 著名的泰坦尼克号数据集,你可以在这里下载数据集。

让我们导入包并读取数据集。

df.head()的结果

df.head()将显示 dataframe 的前 5 行,您可以通过使用此功能快速浏览数据集。

删除未使用的列

根据我们的观察,有一个无效/空的Unnamed: 13列是我们不需要的。我们可以使用下面的函数来删除它。

如果您希望删除多个列,需要一个数组来传入columns参数。

inplace = True将直接对数据帧本身进行操作,默认情况下,它将创建另一个副本,你必须像df = df.drop(columns="Unnamed: 13")一样再次将其分配给数据帧。

删除重复项

让我们使用这个函数来检查数据集中的重复项。

df[df.duplicated(keep=False)]

df 的结果[df.duplicated(keep=False)]

keep允许一些参数检查重复项。

  • first:除第一次出现外,将重复标记为True
  • last:除最后一次外,将重复标记为True
  • False:将所有重复标记为True

在这种情况下,我想显示所有的副本,所以将False作为参数传递。现在,我们已经看到该数据集中有重复项,我想删除它们并保留第一个重复项。下面的函数用于保存第一次出现的内容。

df = df.drop_duplicates(keep="first")

我们可以使用len(df)df[df.duplicated(keep=False)]来检查重复项是否被删除。df[df.duplicated(keep=False)]如果删除重复项,将返回 null。

数据映射

df["Sex"].uniquedf["Sex"].hist()的帮助下,我们发现该列中还有其他值,如mmF。这可能是由于来自数据源的错误输入,我们必须假设这些值是正确的,并映射到malefemale

df["Sex"] = df["Sex"].map({
    "male": "male",
    "m": "male",
    "m ": "male",
    "M": "male",
    "F": "female",
    "f": "female",
    "female": "female"
})

上述函数用于将这些值映射到malefemale

注意:请确保映射中包含默认值 *male* *female* ,否则在执行映射后将变成 *nan*

处理空数据

在该列中,有 3 个值缺失:-naNaN。熊猫不承认-na为空。在处理它们之前,我们必须用 null 替换它们。

replace()用于将-na替换为空。

如果我们在读取数据时发现了这一点,我们实际上可以通过将丢失的值传递给na_values参数来处理这个丢失的值。结果是一样的。

现在我们已经用空值替换了它们,我们将如何处理那些丢失的值呢?

  • 解决方案 1:删除观察(行)/特征(列)

如果我们确定丢失的数据没有用或者丢失的数据只是数据的一小部分,我们可以删除包含丢失值的行。

在统计学中,这种方法称为列表式删除,这是一种处理缺失数据的方法。在这种方法中,如果缺少任何单个值,将从分析中排除整个记录。

如果我们确信这个特性(列)没有提供有用的信息或者缺失值百分比很高,我们可以删除整个列。这在进行统计分析时非常有用,因为填充缺失值可能会产生意外或有偏差的结果。

  • 解决方案 2:估算缺失值

这意味着根据其他数据计算缺失值。例如,我们可以用出生日期计算年龄的缺失值。

在这种情况下,我们没有出生日期,我们可以用数据的*均值或中值(分类值的模式)替换缺失值。

注意:当数据没有倾斜时,*均值最有用,而中位数更稳健,对异常值不敏感,因此在数据倾斜时使用。

在这种情况下,让我们使用 median 来替换缺失的值。

df["Age"].median用于计算数据的中值,而fillna用于用中值替换缺失值。

现在你已经学会了如何用熊猫来清理 Python 中的数据。希望这篇文章对你有用。如果我犯了任何错误或错别字,请给我留言。

可以在我的 Github 中查看完整的 Jupyter 笔记本。干杯!

如果你喜欢读这篇文章,你可能也会喜欢这些:

你可以在 Medium 上找到我其他作品的链接,关注我 这里 。感谢阅读!

使用 FastAI.jl 进行简单的图像分类

原文:https://towardsdatascience.com/simple-image-classification-using-fastai-jl-83960d1d2ce1?source=collection_archive---------32-----------------------

Fastai 库现在在 Julia 上,Python 中也有类似的特性。在这个项目中,我们将训练 Resnet-18 模型,通过几个步骤对 ImageNet 数据集中的图像进行分类。

图片作者|元素作者 freepik

FastAI.jl 简介

FastAI.jl 库类似于 Python 中的 fast.ai 库,这是在 Julia 中试验深度学习项目的最佳方式。该库允许您使用最先进的模型,您可以通过使用几行代码来修改、训练和评估这些模型。FastAI.jl 为深度学习提供了一个完整的生态系统,其中包括计算机视觉,自然语言处理,表格数据,每个月都会添加更多的子模块 FastAI (fluxml.ai)

在这个项目中,我们将使用 fastai 库在带有 Apache License 2.0imagenette 2–160数据集上训练一个图像分类器。imagenette 2–160 数据集来自 fastai 数据集存储库,其中包含我们周围事物的较小尺寸图像,从动物到汽车。ResNet-18 模型架构在用于图像识别的深度残差学习中可用。我们不会深入数据集或模型架构如何工作,相反,我们将专注于 fastai.jl 如何使深度学习变得简单。

图片 1

Julia 中的 FastAI.jl 入门

欲了解更多详情,请访问 Quickstart (fluxml.ai) ,因为本项目中使用的代码来自 fastai 文档。

本地设置

如果您的系统中安装了 Julia,请键入:

using Pkg
Pkg.add("FastAI")
Pkg.add("CairoMakie")

如下图所示👇

作者图片

深度笔记

对于 Deepnote 环境,您必须创建一个 docker 文件并添加:

FROM gcr.io/deepnote-200602/templates/deepnote
RUN wget https://julialang-s3.julialang.org/bin/linux/x64/1.6/julia-1.6.2-linux-x86_64.tar.gz && 
    tar -xvzf julia-1.6.2-linux-x86_64.tar.gz && 
    sudo mv julia-1.6.2 /usr/lib/ && 
    sudo ln -s /usr/lib/julia-1.6.2/bin/julia /usr/bin/julia && 
    rm julia-1.6.2-linux-x86_64.tar.gz && 
    julia  -e "using Pkg;pkg"add IJulia LinearAlgebra SparseArrays Images MAT""
ENV DEFAULT_KERNEL_NAME "julia-1.6.2"

Google Colab

对于 Google Colab,你可以在 GitHub上关注我的报告,或者通过添加一个额外的单元格来创建一个 Julia 环境,如下所示。安装 Julia 软件包可能需要 15 分钟。

  1. 将运行时间更改为 GPU 以获得更快的结果。
  2. 执行下面的代码。
  3. 按 F5 重新加载此页面。
%%shell
set -e
#---------------------------------------------------#
JULIA_VERSION="1.6.2"
export JULIA_PACKAGES="CUDA IJulia CairoMakie"
JULIA_NUM_THREADS="2"
#---------------------------------------------------#
if [ -n "$COLAB_GPU" ] && [ -z `which julia` ]; then
  # Install Julia
  JULIA_VER=`cut -d '.' -f -2 <<< "$JULIA_VERSION"`
  echo "Installing Julia $JULIA_VERSION on the current Colab Runtime..."
  BASE_URL="https://julialang-s3.julialang.org/bin/linux/x64"
  URL="$BASE_URL/$JULIA_VER/julia-$JULIA_VERSION-linux-x86_64.tar.gz"
  wget -nv $URL -O /tmp/julia.tar.gz # -nv means "not verbose"
  tar -x -f /tmp/julia.tar.gz -C /usr/local --strip-components 1
  rm /tmp/julia.tar.gz
  # Install Packages
  echo "Installing Julia packages, this may take up to 15 minutes. "
  julia -e 'using Pkg; Pkg.add(["CUDA", "IJulia", "CairoMakie"]); Pkg.add(Pkg.PackageSpec(url="https://github.com/FluxML/FastAI.jl")); Pkg.precompile()' &> /dev/null
  # Install kernel and rename it to "julia"
  echo "Installing IJulia kernel..."
  julia -e 'using IJulia; IJulia.installkernel("julia", env=Dict(
      "JULIA_NUM_THREADS"=>"'"$JULIA_NUM_THREADS"'"))'
  KERNEL_DIR=`julia -e "using IJulia; print(IJulia.kerneldir())"`
  KERNEL_NAME=`ls -d "$KERNEL_DIR"/julia*`
  mv -f $KERNEL_NAME "$KERNEL_DIR"/julia  
  echo ''
  echo "Success! Please reload this page and jump to the next section."
fi

利用 FastAI.jl 实现图像分类

检查版本以确保你有一个和我相似的版本。

versioninfo()

Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Xeon(R) CPU @ 2.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, haswell)
Environment:
  JULIA_NUM_THREADS = 2

导入库

using FastAI
import CairoMakie

下载数据集

我们使用loaddataset函数从 fastai 导入本地数据集。正如你所看到的,使用一行代码就可以下载数据集,并为您提供访问所有图像位置的标签。

data, blocks = loaddataset(“imagenette2–160”, (Image, Label))

┌ Info: Downloading
│   source = https://s3.amazonaws.com/fast-ai-imageclas/imagenette2-160.tgz
│   dest = /root/.julia/datadeps/fastai-imagenette2-160/imagenette2-160.tgz
│   progress = 1.0
│   time_taken = 2.69 s
│   time_remaining = 0.0 s
│   average_speed = 35.138 MiB/s
│   downloaded = 94.417 MiB
│   remaining = 0 bytes
│   total = 94.417 MiB
└ @ HTTP /root/.julia/packages/HTTP/5e2VH/src/download.jl:128

数据包含图像的位置,包含结构和图像标签。

data

(mapobs(loadfile, ["/root/.julia/datadeps/fastai-imagenette2-160/imagenette2-160/train/n01440764/I…]), mapobs(parentname, ["/root/.julia/datadeps/fastai-imagenette2-160/imagenette2-160/train/n01440764/I…]))

blocks

(Image{2}(), Label{String}(["n01440764", "n02102040", "n02979186", "n03000684", "n03028079", "n03394916", "n03417042", "n03425413", "n03445777", "n03888257"]))

使用 FastAI.jl 探索用于图像分类的图像

通过使用 getobs,我们可以从数据中检查单个样本,并检查类。在我们的例子中,类名是 n01440764 您也可以将该类重命名为 fish ,但是为了简单起见,我们将为该类使用一个唯一的 Id。我们还可以看到样本 500 中的图像。

image, class = sample =  getobs(data, 500)
@show class
image

我们可以通过使用getobsplotsamples来检查多张带有标签的照片。

idxs = rand(1:nobs(data), 9)
samples = [getobs(data, i) for i in idxs]
plotsamples(method, samples)

图像分类功能

为了加载我们的图像数据,我们需要首先创建一个将图像转换为 128X128 的函数,并对它们进行预处理以随机放大(剪切、拉伸、旋转、翻转)。对于标签,它将使用一键编码将字符串标签转换为整数。

method = BlockMethod(

blocks,

(

ProjectiveTransforms((128, 128)),

ImagePreprocessing(),

OneHot()

)

)

您可以使用ImageClassificationSingle功能来重现相同的结果。

method = ImageClassificationSingle(blocks)

利用 FastAI.jl 建立影像分类模型

  1. 首先,我们需要使用数据加载器来加载图像链接,并使用转换方法。这将把图像和标签转换成整数数据。
  2. methodmodel采用 image loader 和 ResNet architect 的方法构建训练模型。
  3. 我们可以简单地通过在metholossfn中添加方法来创建一个损失函数。默认情况下,损失函数为CrossEntropy
  4. 通过使用Learner,我们组合了方法、数据加载器、优化器(ADAM)、损失函数和度量(在我们的例子中是准确性)。
dls = methoddataloaders(data, method)
model = methodmodel(method, Models.xresnet18())
lossfn = methodlossfn(method)
learner = Learner(model, dls, ADAM(), lossfn, ToGPU(), Metrics(accuracy))

我们可以使用如下所示的一行代码简单地完成上述所有步骤。

learner = methodlearner(method, data, Models.xresnet18(), ToGPU(), Metrics(accuracy))

图像分类模型的训练与评估

我们将以 0.002 的学习率在 10 个时期上训练我们的模型。正如我们可以看到的,我们的训练和验证损失随着每次迭代而减少,但是在第 5 个时期之后,验证损失变得稳定。

最终指标:

训练=损失:0.07313 │准确率:98.38%

验证=损失:0.59254 │准确率:83.27%

这并不坏,因为我们还没有清理数据或执行超参数调整。

fitonecycle!(learner, 10, 0.002)

Epoch 1 TrainingPhase(): 100%|██████████████████████████| Time: 0:05:50┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   1.0 │ 1.75345 │  0.43189 │
└───────────────┴───────┴─────────┴──────────┘Epoch 1 ValidationPhase(): 100%|████████████████████████| Time: 0:00:19┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   1.0 │ 1.54432 │  0.53701 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 2 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:34┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   2.0 │ 1.37105 │  0.56158 │
└───────────────┴───────┴─────────┴──────────┘Epoch 2 ValidationPhase(): 100%|████████████████████████| Time: 0:00:17┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   2.0 │ 1.23731 │  0.62673 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 3 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:32┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   3.0 │ 1.09463 │  0.65127 │
└───────────────┴───────┴─────────┴──────────┘Epoch 3 ValidationPhase(): 100%|████████████████████████| Time: 0:00:17┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   3.0 │ 1.11761 │  0.65932 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 4 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:31┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   4.0 │ 0.87518 │  0.71549 │
└───────────────┴───────┴─────────┴──────────┘Epoch 4 ValidationPhase(): 100%|████████████████████████| Time: 0:00:16┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   4.0 │ 0.95252 │   0.6995 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 5 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:29┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   5.0 │ 0.70251 │  0.77235 │
└───────────────┴───────┴─────────┴──────────┘Epoch 5 ValidationPhase(): 100%|████████████████████████| Time: 0:00:16┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   5.0 │ 0.77653 │  0.75314 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 6 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:29┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   6.0 │ 0.52883 │  0.82565 │
└───────────────┴───────┴─────────┴──────────┘Epoch 6 ValidationPhase(): 100%|████████████████████████| Time: 0:00:16┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   6.0 │ 0.76827 │   0.7698 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 7 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:28┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   7.0 │ 0.35174 │  0.88405 │
└───────────────┴───────┴─────────┴──────────┘Epoch 7 ValidationPhase(): 100%|████████████████████████| Time: 0:00:16┌─────────────────┬───────┬────────┬──────────┐
│           Phase │ Epoch │   Loss │ Accuracy │
├─────────────────┼───────┼────────┼──────────┤
│ ValidationPhase │   7.0 │ 0.7575 │  0.77955 │
└─────────────────┴───────┴────────┴──────────┘Epoch 8 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:28┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   8.0 │ 0.20262 │  0.93675 │
└───────────────┴───────┴─────────┴──────────┘Epoch 8 ValidationPhase(): 100%|████████████████████████| Time: 0:00:16┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   8.0 │ 0.63952 │  0.81444 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 9 TrainingPhase(): 100%|██████████████████████████| Time: 0:03:28┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │   9.0 │ 0.11359 │  0.96763 │
└───────────────┴───────┴─────────┴──────────┘Epoch 9 ValidationPhase(): 100%|████████████████████████| Time: 0:00:15┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │   9.0 │ 0.59102 │  0.82806 │
└─────────────────┴───────┴─────────┴──────────┘Epoch 10 TrainingPhase(): 100%|█████████████████████████| Time: 0:03:27┌───────────────┬───────┬─────────┬──────────┐
│         Phase │ Epoch │    Loss │ Accuracy │
├───────────────┼───────┼─────────┼──────────┤
│ TrainingPhase │  10.0 │ 0.07313 │  0.98377 │
└───────────────┴───────┴─────────┴──────────┘Epoch 10 ValidationPhase(): 100%|███████████████████████| Time: 0:00:16┌─────────────────┬───────┬─────────┬──────────┐
│           Phase │ Epoch │    Loss │ Accuracy │
├─────────────────┼───────┼─────────┼──────────┤
│ ValidationPhase │  10.0 │ 0.59254 │  0.83267 │
└─────────────────┴───────┴─────────┴──────────┘

评估模型预测

正如我们所看到的,所有四张照片都被正确预测了。您也可以使用“plotprediction”方法查看预测。

plotpredictions(method, learner)

结论

Julia 是数据科学的未来,如果你想成为未来的证明,你需要学习基础知识。随着 fastai.jl 的引入,对于 Julia 用户来说事情变得非常简单,因为他们只需编写几行代码来构建最先进的机器学习模型。fastai.jl 构建在 flux.jl 之上,后者完全构建在 Julia 之上,不像 Python 库集成了其他编程语言,如 C 和 Java 脚本。就连 Julia 用的 CUDA 都是用 Julia 语言搭建的,而不是 C,这就给了 Julia 在处理和安全性上的优势。正如我在之前的文章Julia for Data Science:A New Age Data Science—Analytics vid hya中所讨论的,Julia 在许多方面都优于 Python。

在这个项目中,我们使用几行代码在 ImageNet 数据中构建了一个图像分类器模型,并且我们的模型表现超出了我们的预期。我们还发现了在图像分类中完成类似任务的不同方法,以及该库在探索和预测图像方面是多么强大。总的来说,我很喜欢使用这个库,其中有很多东西我没有在本文中讨论。

我希望你用这个库做实验,并展示已经准备好生产的令人惊奇的项目。

源代码

源代码可在 GitHubDeepnote 获得。

你可以关注我在 LinkedIn 和 T21 发表的关于数据科学和机器学习的惊人文章。

图像来源

图片 1-https://www . research gate . net/publication/314646236 _ Global-Attributes _ Assisted _ Outdoor _ Scene _ Geometric _ Labeling

本文中显示的媒体不归 Analytics Vidhya 所有,由作者自行决定使用。

原载于 2021 年 9 月 9 日【https://www.analyticsvidhya.com】

减轻计算机视觉中过拟合的五种简单图像数据增强技术

原文:https://towardsdatascience.com/simple-image-data-augmentation-technics-to-mitigate-overfitting-in-computer-vision-2a6966f51af4?source=collection_archive---------12-----------------------

本文是对 的全面概述 的一些简单的图像增强技术

研究已经证明了深度卷积神经网络对于许多领域中的许多计算机视觉任务的效率,例如自主车辆、医学成像等。然而,这些网络严重依赖大质量数据,以便在现实世界的问题上表现出色。但是,一个数据能有多大才能有一个好的模型呢?关于数据,有一点很清楚:我们拥有的高质量数据越多,它就越好。为了消除任何疑虑,我们将使用一种称为 图像增强 的技术来增加我们的训练数据的数量,以便我们的模型 避免过度拟合 训练图像数据。

过度拟合是什么,什么时候发生?

在模型的训练期间,如果模型能够学习底层任务,则验证错误会减少。在某一点上,训练误差会不断减小,而测试/保留数据上的误差会增加,这种情况称为过度拟合,因为模型不断从训练数据中学习一些模式,而这些模式不会在测试数据上推广(图中所示)。

图片来自维基百科

与有限图像数据相关的问题

获取数量非常有限的高质量训练数据 是过度拟合的根本原因之一。

  • 我们拥有的高质量数据越多越好,但获取这样的数据可能非常昂贵和耗时。
  • 健壮的计算机视觉模型对于图像中的微小变化(例如旋转、*移)应该是不变的。如果一个模型能够识别左边的大象,我们可能也希望它能够识别右边的大象,不幸的是,这不一定是已知的,除非这个模型被训练成这样。

(图片由作者提供)

图像增强方法

图像扩充是使用训练集中已经存在的图像来增加训练数据大小的过程。正如我们从下图中看到的,有两种主要的图像增强方法

  • 基本的图像操作:这将是我们文章的重点。
  • 使用生成对抗网络(GAN)增强、风格转移和对抗训练的深度学习方法:这可能是另一个时间的主题。

图片由康纳缩短 & 塔希·米·科什戈夫塔尔来自斯普林格

基本图像增强技术和插图

这五种主要的图像变换技术可以用来增加数据的大小。为了更好地理解,所有这些技术后面都会有例子。

  • 几何变换
  • 色彩空间转换
  • 随机擦除
  • 内核过滤器
  • 混合图像

1.几何变换

在使用这种技术之前,重要的是要理解在保留标签方面什么样的转换对数据有意义(例如,对于数字识别,以某种方式翻转 6 可能会变成 9 )。

(图片由作者提供)

2.色彩空间转换

这种技术有很多可能性,它为图像转换提供了更多的创造性空间,但亮度和对比度可能是最常见的技术。

(图片由作者提供)

3.随机擦除

与几何变换一样,这种技术也可能不保留标签。但它很有趣,因为它迫使模型关注整个图像,而不是子集。例如,模型不能通过只看它的脸来识别大象,因为那部分可能被遮住了,这实际上迫使模型看整个上下文。该技术受 dropout 方法的启发,dropout 方法是一种正则化技术,它将神经网络层中的随机部分权重归零。它还有助于克服测试图像的遮挡或不清晰部分的问题(例如,大象的某个部分被树或其他东西隐藏)。

(图片由作者提供)

4.内核过滤器

这些技术主要用于使用滤镜锐化或模糊图像。他们在引擎盖下使用了一个 NxN 内核 ,类似于卷积神经网络(CNN)的内部工作方式。它们也非常有利于使模型对动作镜头更加鲁棒,尤其是当训练数据中的所有图像都具有相似的清晰质量时。

(图片由作者提供)

5.混合图像

像素*均(混合)和叠加裁剪(剪切混合)是混合图像的两种方式。让我们考虑把大象和右边的森林图像结合起来。

(图片由作者提供)

结论

通过前面的技术,我们能够从一个图像中获得多个图像。将这些技术应用于训练数据中的所有图像可以因此增加其大小。然而,为了应用保留标签的技术,理解数据是非常重要的。

我希望您喜欢这篇文章。如果您有任何问题或意见,我将很高兴欢迎他们进行进一步的讨论。如需进一步阅读,请随时查阅以下链接:

https://link.springer.com/article/10.1186/s40537-019-0197-0

https://github.com/albumentations-team/albumentations

再见🏃🏾

OpenAI 剪辑模型的简单实现:教程

原文:https://towardsdatascience.com/simple-implementation-of-openai-clip-model-a-tutorial-ace6ff01d9f2?source=collection_archive---------3-----------------------

摘要剪辑模型的方法,从学习可转移的视觉模型从自然语言监督论文

介绍

2021 年 1 月,OpenAI 宣布了两个新模型:DALL-E 和 CLIP,这两个多模态模型以某种方式连接文本和图像。在本文中,我们将在 PyTorch 中从头开始实现剪辑模型。OpenAI 已经开源了一些与 CLIP model 相关的代码,但我发现它令人生畏,而且它远非简单短小。我还看到了一个很好的教程,灵感来自 Keras 代码示例上的剪辑模型,我将它的一些部分翻译成 PyTorch,完全用我们心爱的 PyTorch 来构建这个教程!

我把所有的代码都作为笔记本放在了Google Colabka ggle上,也放在了我的GitHub上。

CLIP 是做什么的?为什么好玩?

从自然语言监督中学习可转移视觉模型论文中,OpenAI 介绍了他们的新模型,名为 CLIP ,用于对比语言-图像预训练。简单来说,这个模型学习一个整句和它所描述的形象之间的关系;在某种意义上,当训练模型时,给定一个输入句子,它将能够检索对应于该句子的最相关的图像。这里重要的是,它是在完整的句子上训练的,而不是像汽车、狗等单一类别。直觉是,当对整个句子进行训练时,模型可以学习更多的东西,并在图像和文本之间找到一些模式。

他们还表明,当这个模型在一个巨大的图像数据集及其相应的文本上训练时,它也可以充当分类器。我鼓励您研究这篇论文,以了解更多关于这个令人兴奋的模型及其在基准数据集上的惊人结果。仅举一个例子,用这种策略训练的剪辑模型比那些在 ImageNet 上训练的 SOTA 模型更好地分类 ImageNet,ImageNet 本身被优化用于唯一的分类任务!

作为一个引子(!),让我们看看我们将在本文中从头开始构建的最终模型有什么能力:给定一个查询,如“一个男孩用滑板跳跃”或“一个女孩从秋千上跳跃”,该模型将检索最相关的图像:

上述文本查询的最终模型输出|作者图片

敬请期待:)

入门指南

好吧。让我们直接看它的 PyTorch 实现。首先,我们需要一个包含图像和一些描述它们的文本的数据集。坦白地说,网上有很多。我们将使用 Flickr 8k 数据集(你可以使用更大的 30k 版本,最终模型的性能会更好),它主要用于图像字幕任务。但是,没有限制,我们也可以用它来训练剪辑模型。

如果你用的是我写的Kaggle 笔记本 ,你不需要下载任何东西!数据已经在那里了../输入。

但是如果你正在使用 Colab 或者你想在你的本地机器上下载它,下面的代码将下载 8k(或者 30k,如果你不注释最后几行)并解压它们。您需要在下面的指定字符串中输入您的 Kaggle 用户名和密钥(如果您还没有 Kaggle 帐户,只需创建一个即可!)

关于这个数据集需要注意的一点是,每个图像有 5 个标题。这个我以后写损失函数的时候再讲!

资料组

正如您在本文的标题图片中所看到的,我们需要对图片及其描述文本进行编码。因此,数据集需要返回图像和文本。当然,我们不会将原始文本输入到我们的文本编码器中!我们将使用来自 HuggingFace 库中的 DistilBERT 模型(它比 BERT 小,但性能几乎和 BERT 一样好)作为我们的文本编码器;因此,我们需要用 DistilBERT tokenizer 对句子(标题)进行标记,然后将标记 id(input _ ids)和注意力屏蔽提供给 DistilBERT。因此,数据集也需要考虑标记化。下面你可以看到数据集的代码。下面我将解释代码中发生的最重要的事情。

关于configCFG的一个说明:我用 python 脚本写代码,然后转换成 Jupyter 笔记本。因此,在 python 脚本的情况下,config 是一个普通的 python 文件,我将所有的超参数放在其中,而在 Jupyter Notebook 的情况下,它是一个在 Notebook 的开头定义的类,用于保存所有的超参数。查看GitHub repo或笔记本,查看所有的超参数。

init 中,我们接收一个 tokenizer 对象,它实际上是一个 HuggingFace tokinzer 运行模型时将加载此标记器。我们将字幕填充和截断到指定的 max_length。在 getitem 中,我们将首先加载一个编码的标题,这是一个带有键 input_ids 和 attention_mask 的字典,从它的值中提取张量,然后我们将加载相应的图像,转换并放大它(如果有!)然后我们把它做成张量,放在字典里,以“image”为关键字。最后,我们将带有关键字“caption”的标题的原始文本放在字典中,只是为了可视化的目的。

我没有使用额外的数据扩充,但如果你想提高模型的性能,你可以添加它们。

图像编码器

图像编码器代码非常简单。我在这里使用 PyTorch 图像模型库(timm ),它使许多不同的图像模型从 ResNets 到 EfficientNets 等等都可用。这里我们将使用一个 ResNet50 作为我们的图像编码器。如果不想安装新的库,可以很容易地使用 torchvision 库来使用 ResNets。

代码将每个图像编码为一个固定大小的矢量,该矢量具有模型输出通道的大小(在 ResNet50 的情况下,矢量大小将是 2048 )。这是 nn 之后的输出。AdaptiveAvgPool2d()层。

文本编码器

正如我之前提到的,我将使用 DistilBERT 作为文本编码器。像它的哥哥伯特一样,两个特殊的标记将被添加到实际的输入标记中: CLSSEP ,它们标记一个句子的开始和结束。为了获得一个句子的完整表示(正如相关的 BERT 和 DistilBERT 论文所指出的),我们使用 CLS 令牌的最终表示,我们希望这个表示能够捕捉到句子的整体含义(标题)。以这种方式思考,它类似于我们对图像所做的,并将它们转换成固定大小的向量。

在 DistilBERT(还有 BERT)的情况下,每个令牌的输出隐藏表示是大小为 768 的向量。因此,整个字幕将被编码在大小为 768 的 CLS 令牌表示中。

投影头

我用投影头的 Keras 代码示例实现用 PyTorch 写了以下内容。

既然我们已经将图像和文本编码成固定大小的矢量(图像 2048,文本 768)我们需要将它们(投影)到一个新的世界(!)具有相似的尺寸,以便能够对它们进行比较,并推开不相关的图像和文本,将匹配的图像和文本放在一起。因此,下面的代码将把 2048 和 768 维向量带入一个 256 (projection_dim)维的世界,在那里我们可以比较它们:

“embedding_dim”是输入向量的大小(对于图像是 2048,对于文本是 768 ),而“projection_dim”是输出向量的大小,在我们的例子中是 256。要了解这部分的细节,您可以参考回形针

剪辑模型

这部分是所有乐趣发生的地方!这里我也讲一下损失函数。为了撰写这一部分,我将 Keras 代码示例中的一些代码翻译成 PyTorch。看一下代码,然后阅读代码块下面的解释。

这里,我们将使用之前构建的模块来实现主模型。init 函数是不言自明的。在正向函数中,我们首先图像和文本分别编码成固定大小的向量(维度不同)。之后,使用独立的投影模块,我们将它们投影到我之前提到的共享世界(空间)。在这里,编码将变成类似的形状(在我们的例子中是 256)。之后,我们将计算损失。我再次建议阅读回形针,以获得更好的效果,但我会尽力解释这一部分。

线性代数中,衡量两个向量是否具有相似特征(它们彼此相似)的一个常用方法是计算它们的点积(将匹配条目相乘并取其和);如果最后的数字很大,他们是一样的,如果它很小,他们不是(相对而言)!

好吧!我刚才说的是理解这个损失函数最重要的事情。我们继续。我们讨论了两个向量,但是,这里有什么呢?我们有 image_embeddings,一个带有形状的矩阵(batch_size,256)和带有形状的 text _ embeddings(batch _ size,256)。很简单!这意味着我们有两组向量,而不是两个单独的向量。我们如何衡量两组向量(两个矩阵)彼此的相似程度?同样,使用点积(在这种情况下,PyTorch 中的@ operator 执行点积或矩阵乘法)。为了能将这两个矩阵相乘,我们转置第二个矩阵。好的,我们得到一个形状为(batch_size,batch_size)的矩阵,我们称之为 logits 。(在我们的例子中,温度等于 1.0,所以,没有区别。你可以玩玩它,看看它有什么不同。还要看看纸,看看为什么会在这里!).

希望你还和我在一起!如果没有也没关系,只需检查代码并检查它们的形状。现在我们有了逻辑,我们需要目标。我需要说的是,有一种更直接的方法可以获得目标,但是对于我们的情况,我必须这样做(我将在下一段中讨论为什么)。

让我们考虑我们希望这个模型学习什么:我们希望它学习给定图像和描述它的标题的“相似表示(向量)”。这意味着我们要么给它一个图像,要么给它描述它的文本,我们希望它为两者产生相同的 256 大小的向量。

因此,在最好的情况下,text _ embeddings 和 image_embedding 矩阵应该是相同的,因为它们描述的是相似的东西。现在让我们想想:如果发生这种情况,罗吉斯矩阵会是什么样的?我们用一个简单的例子来看!

所以 logits,在最好的情况下,将是一个矩阵,如果我们取它的 softmax,将在对角线上有 1.0(一个用花哨的词来称呼它的单位矩阵!).因为损失函数的工作是使模型的预测与目标相似(至少在大多数情况下!),我们要这样一个矩阵作为我们的目标。这就是为什么我们在上面的代码块中计算图像相似性和文本相似性矩阵的原因。

现在我们已经得到了目标矩阵,我们将使用简单的交叉熵来计算实际的损失。我写了交叉熵的完整矩阵形式作为一个函数,你可以在代码块的底部看到。好吧!我们完了!这不是很简单吗?!好吧,你可以忽略下一段,但如果你好奇,有一个重要的注意事项。

这就是为什么我没有使用更简单的方法:我必须承认在 PyTorch 中有一种更简单的方法来计算这个损失;这样做: nn。CrossEntropyLoss()(logits,torch.arange(batch_size)) 。为什么我没有在这里使用它?有两个原因。1-我们正在使用的数据集对于单个图像具有多个标题;因此,有可能一批中存在两个标题相似的相同图像(这种情况很少见,但也有可能发生)。用这种更简单的方法来承担损失将会忽略这种可能性,并且模型学会将实际上相同的两个表示(假设它们不同)分开。显然,我们不希望这种情况发生,所以我计算了整个目标矩阵,考虑到了这些边缘情况。2-按照我的方式做,让我更好地理解了这个损失函数中发生了什么;所以,我想这会给你一个更好的直觉!

火车

这里有一个方便的函数来训练我们的模型。这里没发生什么事情。只是加载批处理,将它们提供给模型,并步进优化器和 lr_scheduler。

你可以在 ColabKaggle 笔记本或者我的 GitHub repo 中找到更多的实用函数和类(比如 AvgMeter 和 get_lr)。

好吧!我们已经完成了模型的训练。现在,我们需要进行推理,在我们的例子中,将为模型提供一段文本,并希望它从一个看不见的验证(或测试)集中检索最相关的图像。

获取图像嵌入

在这个函数中,我们加载训练后保存的模型,在验证集中输入图像,并返回带有形状(valid_set_size,256)和模型本身的 image _ embeddings。

查找匹配项

这个函数完成了我们希望我们的模型能够完成的最后一项任务:它获取模型、image _ embeddings 和一个文本查询。它将显示验证集中最相关的图像!是不是很神奇?看看它到底表现如何!

来看几个例子吧!在这一点上,当我看到输出时,我高兴地尖叫起来,并震惊地发现模型实际上正在学习图像和文本之间的关系!这种感觉简直难以置信。

这是我们如何使用这个功能。Aaaannnndddd 添加结果:

作者图片

我当时就想:哇!这个模特知道点什么!当然,它并不完美,因为在一些照片中有两只狗,但考虑到小的训练集和短的训练时间,我认为它很棒!

让我们看看其他一些输出。查询写在每个图像的顶部。

作者图片

看吧!它还会数数!把这个和前一个比较一下。该模型知道“two”的含义,并带来了包含两只狗的图像,与前面的查询形成了对比!这时我从第二次震惊中尖叫了出来:)

我们从文章开始的输出:

作者图片

作者图片

对于下一个,这个模型犯了一些错误,但总体来说,它显然对文本和图像都有很好的理解。

作者图片

最后的话

我希望你喜欢这篇文章。实现这篇论文对我来说是一次非常有趣的经历。我要感谢 Khalid Salama 提供的伟大的 Keras 代码示例,它启发了我用 PyTorch 编写类似的代码。

如文中所述,所有代码和结果均可在我的GitHub repo中获得,也可作为 Jupyter 笔记本上的KaggleColab

清理逻辑回归

原文:https://towardsdatascience.com/simple-logistic-regression-a9735ed23abd?source=collection_archive---------32-----------------------

非数学家指南

Unsplash 上由 Rots Marie-Hélène 拍摄的照片

介绍

YouTube 上有很多出色的数据科学内容创作者。如果我试图理解一个算法,他们中的一个通常会一针见血并完美地描述它。

用逻辑回归,我找不到一个完美的描述。人们似乎从不同的方向接*这个算法,这让我感到困惑。也可能是因为我没有深厚的数学背景。逻辑回归是相当重的数学符号,这可能是另一个原因,为什么我发现它很难理解了很长一段时间。

本文旨在以一种易于理解的格式解释逻辑回归,从其他解释中吸取精华,并给出引入新概念的逻辑顺序。

那么它是如何工作的呢?

目录

数据集

示例数据

对于这个例子,我们将使用我臭名昭著的水果数据集。实际上,我们将忽略这里的葡萄,而专注于苹果

包含水果相关数据的示例数据集。图片作者。

如果我们对照实际的类/ 水果绘制球形度(测量水果有多圆)就会发生这种情况(1 代表苹果,0 代表)

苹果和梨的球形度与水果的关系图。图片作者。

你将如何对这些数据进行分类?

  • 我们可以在中间画一条垂直线,表示任何超过 0.7 的都是苹果。
  • 我们可以创建一个回归模型,其中球形度的增加意味着苹果的球形度的增加?这真的没有意义
  • 理想情况下,我们想说我们有多确信水果是苹果,给定关于球形度的数据,增大的球形度表示更大的可能性。

为什么我们不能对此使用线性回归

我们可以通过确定 y 轴是概率来把这个问题公式化为一个回归问题。回归输出会给我们一个概率p ,我们可以说任何低于 0.5 的都是一个,高于 0.5 的都是一个苹果

我们可以对数据拟合一条回归线,这将给出下面的回归线。记住线性回归方程是:

线性回归方程。图片作者。

一个分类问题的线性回归。图片作者。

这种做法行不通有几个原因。最明显的是我们的回归模型可以预测低于 0 和高于 1 的值。这些值实际上意味着什么?它们真的是概率吗?

如果我们得到一个形状特别奇怪的梨会怎么样?

你可以在下面看到,如果我们添加一个和一个球形度为 0.2,我们真的想表明我们 100%确定这是一个。这实际上是将回归线拉向这个例子,意味着我们靠*中心的点现在被错误分类了。

添加异常值。图片作者。

重申…

为了对数据进行分类,我们需要使用变量的线性组合来预测 0 和 1 之间的概率

那么,我们如何将结果压缩在 0 和 1 之间呢?

物流功能

逻辑或 Sigmoid 功能是一个激活功能。

机器学习中的术语激活函数现在几乎专门用于神经网络。这基本上是一个函数,我们可以用它将数字压缩到一个合理的范围内。

我们可以使用激活函数将线性回归结果压缩到我们需要的范围内。

对于逻辑回归,使用 Sigmoid 函数。这有一个等式:

乙状结肠函数。图片作者。

为了将我们的函数映射到这里,我们将 Z 定义为回归方程。

线性回归方程。图片作者。

这个等式的结果输出现在看起来像下面的曲线。值只能在 0 和 1 之间,在本例中,我们正确地对每个点进行了分类。

逻辑回归数据。图片作者。

我们现在有了一个等式,可以根据变量的线性组合对数据进行分类。然而,现阶段我们仍有许多不了解的地方:

  • 逻辑回归中的系数是什么意思?
  • 这个模型是如何计算出系数的?

为了解释这一点,我们需要再介绍几个概念。

赔率和概率

几率提供了一个特定结果的可能性的度量。它们被计算为产生结果的事件数量与不产生结果的事件数量之比。赔率常用于赌博和统计。

事件的概率是一个介于 0 和 1 之间的数字,其中,粗略地说,0 表示事件的不可能性,1 表示确定性。

使用掷骰子的例子:

图像我们有一个 6 面骰子,我们想掷出 6。

  • 滚动 a6 的概率1/6 (0.167%)。
  • 掷出 6 的赔率1:5。
  • 掷出 a 6 的赔率5:1。

我们可以将赔率概率与等式联系起来:

赔率和概率之间的转换。图片作者。

重新排列逻辑回归方程

我们将重新排列我们的等式,试图理解它的含义,这里有一个到目前为止我们所拥有的提示:

逻辑回归方程。图片作者。

其中 Z 是变量的线性组合;

线性回归方程。图片作者。

而 S(Z)是概率

逻辑回归方程。图片作者。

我们可以按照下面的步骤重新排列等式。对于这个过程,我们的目标是分离出 Z,变量的线性组合。

重新排列逻辑回归方程。图片作者。

让我们花点时间来看看结果,如果我们跳回赔率和概率,你会注意到这个等式是赔率的对数!这也被称为 logit 功能。

系数

这意味着我们方程中的系数是以对数几率表示的。

我们可以取这个的逆来得到以概率表示的系数,这允许我们量化系数在实际中的意义,例如

“特性 X 将我们的数据被归类为苹果的几率提高了 3 倍”。

对数概率

对数概率背后的直觉

对数赔率是一种考虑我们赔率的有用方法,因为赔率是如何衡量的。看看下面的例子。

考虑在普通的六面骰子上掷出 6 和 5 或 6 的几率。我们可以在一条数轴上画出赔率,并观察事件发生和事件不发生的赔率

我们可以看到,“未发生”端的值可以在 1 和无穷大之间,而“发生”端的值正好在 0 和 1 之间。

这是一个问题,因为就绝对值而言,一方有巨大的差异,另一方有非常小的差异。

数字线上不同骰子滚动的几率。图片作者。

然而,如果我们将这些转换成对数赔率,我们会得到相反赔率之间的相等距离。

对数-一条数字线上不同骰子滚动的几率。图片作者。

这在复杂得多的统计建模中使用得更广泛,但它有助于将所有这些联系在一起。

逻辑回归中的对数优势

回到模型,假设我们已经对数据进行了建模,并从模型中提取了一些系数。如果我们继续使用回归方程计算对数几率,我们会得到下面的图表。

球形度的对数优势。图片作者。

Log-odds 给了我们一个线性模型,这可以追溯到我们之前如何重新安排等式。

我们仍然需要按照概率的数据,这样我们就可以分配一个类别,但这是一个将所有事情联系在一起的有用方法。

绑在乙状结肠上

那么为什么我们不能用对数概率来模拟我们的分类问题呢?为什么我们必须使用 sigmoid 函数?

对数赔率被称为 logit 函数。如果我们画出这个函数,我们最终会得到一条在 y 轴上没有定义的曲线。我们的目标变量是 y 轴,这意味着我们需要反转这个函数来建模。 logit 函数的逆函数就是 sigmoid 函数。

最大似然估计

现在我们知道了逻辑回归背后的数学原理,但是这个模型实际上是如何计算这些系数的呢?这就是最大似然估计出现的地方。

首先,让我们重温一下我们的数据。我们有球形水果,标注1 对苹果,0 对

在逻辑回归中,我们想要预测一个数据点是一个苹果的概率。

最大似然估计的图形表示的示例数据。图片作者。

首先,我们将这些数据转换成对数几率。我已经解释了逻辑回归和对数概率之间的关系,所以希望这看起来是一件明智的事情。

然而,这里有一个问题。0 和 1 的对数几率是正负无穷大!

此时,我们还绘制了一条随机线来拟合我们的数据。然而,我们不能像线性回归那样使用残差来计算直线与数据的拟合程度,因为我们所有点都在无穷远处。

对数优势转换。1 和 0 概率最终为正负无穷大。图片作者。

所以,为了评估我们线的质量,我们把每个点都投射到它上面。从这里,我们可以读出每个点的对数概率。

从投影点读取对数优势值。图片作者。

现在我们有了每个点的对数几率,给定我们的随机线,我们可以使用我们之前计算出的重新排列的逻辑回归方程将几率转换回概率。

我们的点现在在概率轴上,我们画的线现在是一个 sigmoid。

我们可以从图中读出每个点的概率,然后用它来计算这条线的总可能性

似然一般以对数形式计算,但也可以用其他方式。

为此,我们对每个苹果点取概率的对数,对每个点取 1 — 概率的对数。将这些相加以计算该线的对数似然。

我们可以将数据转换回概率,然后计算出每个点的可能性。作者图片/

然后,我们旋转直线以找到更好的东西,重复相同的步骤来绘制我们的乙状结肠并计算它的可能性得分。

用新的一行重复上述步骤。图片作者。

更陡的直线产生更陡的 s 形曲线。我们可以不断旋转这条线,找到最大化对数似然的曲线。

更陡的线产生更陡的 s 形。图片作者。

虽然第一条线是随机的,但最大似然估计能很快找到最佳线。

旋转线的算法能够以这样的方式做到这一点,即它总是提高可能性,使得该过程非常高效。

照片由 Antoine DautryUnsplash 上拍摄

结论

逻辑回归是最简单和最广泛使用的分类算法之一。网上和教科书上有丰富的信息。我个人的经验是,我发现这个算法有各种不同的解释方式。这篇文章的目的是为数据科学家提供一个清晰有序的解释。

希望这已经按逻辑顺序理清了逻辑回归。如果你觉得有什么没有解释清楚或者需要更多的细节,请留下你的评论。我很想进一步讨论这个问题。

点击这里查看我的其他算法解释:

联系我

https://www.linkedin.com/in/adamshafi/

Python 中的简单逻辑回归

原文:https://towardsdatascience.com/simple-logistic-regression-using-python-scikit-learn-86bf984f61f1?source=collection_archive---------5-----------------------

从数据预处理到模型评估的逐步指南

逻辑回归 python cheatsheet(图片作者来自www.visual-design.net

什么是逻辑回归?

不要让逻辑回归这个名字欺骗了你,它通常属于分类算法而不是回归算法的范畴。

那么,什么是分类模型呢?简而言之,由分类模型生成的预测将是一个分类值,例如,猫或狗,是或否,真或假…相反,回归模型将预测一个连续的数值。

逻辑回归基于 Sigmoid 函数进行预测,Sigmoid 函数是一条曲线状的线,如下所示。尽管它返回概率,但最终输出将是通过将概率与阈值进行比较而分配的标签,这使它最终成为一种分类算法。

sigmoid 函数的简单说明(图片由作者提供)

在本文中,我将通过以下步骤使用 python scikit -learn 构建一个简单的逻辑回归模型:

  1. 数据预处理
  2. 特征工程和 EDA
  3. 模型结构
  4. 模型评估

数据取自 Kaggle 公共数据集“澳大利亚的雨”。目标是根据现有知识,如温度、湿度、风速等,预测二元目标变量“RainTomorrow”。在我的网站上的文章末尾,您可以随意获取完整代码。

1.数据预处理

首先,让我们加载库和数据集。

导入库和数据集(图片由作者提供)

df.head()(图片作者提供)

使用df.describe()查看原始数据。

df.describe()(图片由作者提供)

我们不能总是期望所提供的数据对于进一步的分析是完美的。事实上,这种情况很少发生。因此,数据预处理至关重要,尤其是处理缺失值是确保数据集可用性的必要步骤。我们可以使用 isnull() 函数来查看缺失数据的范围。下面的代码片段计算每列缺失值的百分比。

缺失值百分比(作者图片)

有四个字段丢失了 38%到 48%的数据。我删除了这些列,因为这些值很可能是丢失的,而不是随机丢失的。例如,我们遗漏了大量的蒸发数据,这可能会受到测量仪器容量的限制。因此,有更多极端蒸发措施的日子可能不会首先被记录下来。所以剩下的数字已经偏了为此,保留这些字段可能会污染输入数据。如果您想区分三种常见类型的缺失数据,您可能会发现这篇文章“如何处理缺失数据”很有帮助。

按列和按行删除(图片由作者提供)

在执行按列删除后,我删除了缺少标签的行,“RainTomorrow”,直到dropna().为了建立一个机器学习模型,我们需要标签来训练或测试模型,因此没有标签的行对这两个过程都没有太大帮助。但是,数据集的这一部分可以在模型实现后作为预测集分离出来。在处理缺失数据时,不可避免的是数据形状会发生变化,因此df.shape是一种方便的方法,可以让您跟踪数据的大小。在上面的数据操作之后,数据形状从 145460 行 23 列变成了 142193 行 19 列。

对于剩余的列,我分别估算了分类变量和数值变量。下面的代码将列分为分类列表和数字列表,这对后面的 EDA 过程也很有帮助。

分离数值和分类变量(图片由作者提供)

  • 数值变量:用变量的*均值估算缺失值。注意,组合df.fillna()df.mean() 将足以只转换数字变量。

解决数值缺失问题(图片由作者提供)

  • 分类变量:遍历 cat_list 并用“未知”替换缺失值

处理分类缺失值(图片由作者提供)

2.特征工程和 EDA

将这两个过程结合在一起有利于根据数据集的分布和特征选择适当的特征工程技术。

在这个例子中,我没有深入探索数据分析(EDA)过程。如果您有兴趣了解更多,请随意阅读我关于更全面的 EDA 指南的文章。

我通过 FOR 循环自动进行单变量分析。如果遇到数字变量,将生成一个直方图来可视化分布。另一方面,为分类变量创建一个条形图。

单变量分析(图片由作者提供)

1)地址异常值

现在我们有了数据分布的整体视图,发现异常值就容易多了。例如,降雨量有严重的右偏分布,表明至少有一个非常高的记录。

为了消除离群值,我使用分位数(0.9) 将数据集限制在数据集的 90%分位数内。因此,降雨量值的上限从 350 大幅降至 6。

处理异常值(图片由作者提供)

2)特征变换

日期变量被转换成月份。这是因为日期具有如此高的基数,以至于不可能产生模式。而使用 month 可以给出一年中的某些月份是否更有可能下雨的建议。

日期转换(图片由作者提供)

3)分类特征编码

逻辑回归只接受数值作为输入,因此,有必要将分类数据编码成数字。最常见的技术是一键编码和标签编码。我发现这篇文章很好地比较了这两者。

https://www.analyticsvidhya.com/blog/2020/03/one-hot-encoding-vs-label-encoding-using-scikit-learn/

RainToday 为例:

今天下雨的例子

  • 标签编码更适合基数大的序数数据

标签编码

  • 一个热编码更适合低基数和非序数数据

一个热编码

尽管这些列不是有序的,我还是选择了标签编码。这是因为大多数字段都有不少于 17 个唯一值,而一次性编码会使数据变得太大。

标签编码代码(图片由作者提供)

现在所有的变量都被转换成整数或浮点数。

df.info()(图片作者提供)

4)特征选择

如果您想了解特性选择技术的详细信息,您可能会发现这很有帮助:

在这个练习中,我使用了上面文章中提到的相关性分析。相关性分析是一种常见的多变量 EDA 方法,有助于识别高度相关的变量。

相关性分析(图片由作者提供)

例如:

  • 最小温度,最大温度,温度 9am温度 3pm
  • 降雨今日降雨
  • 压力 9am压力 3am

相关矩阵(图片由作者提供)

由于逻辑回归要求预测值之间几乎没有多重共线性,我试图在每组高度相关的变量中只保留一个变量。

特征选择(图片由作者提供)

3.模型结构

之前,我提到过这个练习的目的是预测明天的降雨。因此,首要任务是分离输入要素(自变量— X)和标注(因变量— y)。df.iloc[:, :-1]是一个方便的函数,可以抓取除最后一行以外的所有行和所有列。

自变量和因变量(图片由作者提供)

其次,特征和标签都被分解成一个子集用于训练,另一个子集用于测试。结果,返回四个部分,X_train、X_test、y_train 和 y_test。为此,我们引入了 train_test_split 函数,并指定了参数 test_size。在下面的示例中,test_size = 0.33,因此大约 2/3 的数据用于训练,1/3 用于测试。

分为训练和测试(图片由作者提供)

多亏了 scikit-learn,我们可以避免从零开始实现所有数学和算法的繁琐过程。相反,我们需要做的只是从 sklearn 库中导入 LogisticRegression,并将训练数据拟合到模型中。然而,通过指定几个参数,例如 max_iter、solver、penalty,仍然有改变模型的灵活性。更复杂的机器学习模型通常会涉及超参数调整过程,该过程搜索可能的超参数值并找到最佳组合。

对于这个初学者友好的模型,我只改变了 max_iter 参数,以使逻辑回归收敛,但同时,该数字不应该太高,以导致过度拟合。

逻辑回归模型(图片由作者提供)

4.模型评估

ROC、AUC、混淆矩阵和准确度广泛用于评价 Logistic 回归模型。所有这些指标都是基于计算模型预测的 y 值与测试集的实际 y 值之间的差异,即 y_pred 和 y_test。比较差异时,有四种可能的情况:

  1. 当预报下雨时,明天确实下雨
  2. 真否定:当预测不下雨的时候,明天不下雨
  3. 假阳性:当预报下雨时,明天不下雨
  4. 假阴性:当预测不下雨的时候却下雨了

混淆矩阵

混淆矩阵

我使用了plot_confusion_matrix()来提供一个可视化的表示,清楚地指出上面提到的四个场景的数量。如图所示,真正的否定是 33122 例,表明该模型擅长在实际上不会下雨的时候预测明天不会下雨。然而,它仍然需要提高真阳性率,从而成功地预测明天下雨(只有 2756 例)。

准确度

准确(性)

准确性计算所有正确预测的比率:(真阳性+真阴性)/(真阳性+假阳性+假阴性+假阳性)

ROC 和 AUC

ROC、AUC 插图(图片由作者提供)

ROC 绘制了不同阈值下的真阳性率和假阳性率。例如,当阈值设置为 0.7 时,该点指示真阳性率和假阳性率,因此当预测概率大于 0.7 时,RainTomorrow = Yes。随着概率阈值下降到 0.4,更多的病例将被预测为阳性(RainTomorrow = Yes),因此真阳性率和假阳性率都上升。AUC 代表曲线下面积,不同的模型具有不同的 ROC,因此 AUC 得分也不同。在这个例子中,模型 2 比模型 1 具有更大的 AUC,并且它是更好的模型。这是因为,在相同的假阳性率水*下,模型 2 具有更高的真阳性率。因此,模型 2 具有更高的 AUC 分数,这使其成为更好的模型。

三个函数用于绘制 ROC 图和计算 AUC:

  • predict_proba():为每个实例生成概率分数
  • roc_curve():返回假阳性率、真阳性率以及绘制曲线所必需的参数。
  • roc_auc_score():计算 auc 分数

ROC,AUC 代码(图片由作者提供)

带回家的信息

本文涵盖了逻辑回归模型构建过程的基本步骤:

  1. 数据预处理:重点是缺失值插补
  2. 特征工程和 EDA:单变量分析和多变量分析:处理异常值和特征转换
  3. 建模:分割数据集并拟合数据逻辑回归
  4. 模型评估:混淆矩阵、准确性、ROC 和 AUC

然而,这只是一个基本的指南,旨在让你及时掌握如何实施逻辑回归。通过引入超参数调整、特性重要性和标准化,有足够的空间来改进当前的模型。一如既往,让我们继续学习。

更多这样的文章

https://medium.com/analytics-vidhya/top-15-websites-for-data-scientists-to-follow-in-2021-67352092c54d

原载于 2021 年 3 月 30 日【https://www.visual-design.net】

简单的机器翻译:英语

原文:https://towardsdatascience.com/simple-machine-translation-yorùbá-to-english-1b958ccdc8a1?source=collection_archive---------16-----------------------

图片作者|元素作者 Freepik : pch.vector0melapicssyarifahbrit

微调赫尔辛基 NLP 多语言模型,将文本从约伯语翻译成英语。

约鲁巴语机器翻译挑战| 津迪

针对西班牙语读者:traducción automática simple:del yorba inglés

介绍

在本文中,我们将构建一个机器翻译模型,将约鲁巴语句子翻译成英语。这些句子来自各种资源,如新闻文章、社交媒体上的对话、口头记录以及纯用约鲁巴语编写的书籍。

低资源语言的机器翻译非常少见,而且由于这些语言的可用训练数据有限,很难得到准确的结果。我们有一个可用于约鲁巴语文本(JW300)的数据集,但它是用来训练宗教领域的。我们需要一个一般化的模型,可以在多个领域中使用,这就是AI4D . ai带来更多一般化数据的地方,我们所要做的就是根据这些数据训练我们的模型,并产生一个准确的结果,以确保在AI4D yorübá机器翻译挑战赛— Zindi 中的领先地位。****

在这个项目中,我们将使用赫尔辛基 NLP 模式,所以让我们把他们作为一个组织来讨论。

赫尔辛基 NLP

赫尔辛基大学的语言技术研究小组训练了赫尔辛基 NLP 模型。他们的使命是为所有人类语言提供机器翻译。他们还研究和开发处理人类语言的工具,包括自动拼写和语法检查、机器翻译和 ASR(自动语音识别)更多信息请访问语言技术。这些模型在 HuggingFace 和 GitHub 上公开发售。

导入基本库

选择选项

  • 要清理你的文本,你需要使 Clean 变量为真,因为现在我正在训练我的数据而没有清理。
  • 如果你想训练你的模型,使 训练 变量为真****

读取翻译数据

使用 pandas 阅读训练数据,对我们的数据集有初步的了解。

训练数据包括 10,054 个*行的约伯语-英语句子。我们有三列 ID :唯一标识符、约鲁巴语:包含约鲁巴语的文本和英语:文本包含约鲁巴语的英语翻译。数据看起来相当干净,没有丢失的值。****

清理数据

我们已经删除了标点符号,将文本转换为小写,并删除了文本中的数字,以使我们的模型性能更好。现在,我将关闭这个特性,但是我将在以后的实验中使用它。

正在加载标记器和模型

我们使用了机器翻译中隐藏的宝石,它被训练成多种语言,包括约鲁巴语。赫尔辛基 NLP 模型是机器语言翻译领域最好的模型之一,它们具有迁移学习功能,这意味着我们可以使用相同的模型和相同的权重,并根据我们的新数据进行微调,以获得最佳结果。我们将使用Helsinki-NLP/opus-mt-mul-en 拥抱脸模型,并在由人工智能促进发展-非洲网络(ai4d . ai*)提供的更一般化的约鲁巴语文本上对其进行微调。*******

这个模型可以在拥抱脸网站上公开获得,使用变形金刚库很容易下载和训练。我们将使用 GPU,添加.to(cuda)将激活该模型上的 GPU。

  • ****源组:多种语言
  • ****目标人群:英语
  • 作品自述 : 多英
  • ****型号:变压器

如果你有良好的互联网连接,下载和加载模型不会花太多时间

*****Downloading: 100% 1.15k/1.15k [00:00<00:00, 23.2kB/s]
Downloading: 100% 707k/707k [00:00<00:00, 1.03MB/s]
Downloading: 100% 791k/791k [00:00<00:00, 1.05MB/s]
Downloading: 100% 1.42M/1.42M [00:00<00:00, 2.00MB/s]
Downloading: 100% 44.0/44.0 [00:00<00:00, 1.56kB/s]
Downloading: 100% 310M/310M [00:27<00:00, 12.8MB/s]*****

准备培训模型

【计算机】优化程序

我们将使用 AdamW 优化器来使我们的模型快速收敛,并以 0.0001 的学习率提供更好的结果。我试验了 PyTorch 库中不同的优化器,AdamW 在这个问题上表现得更好。通过进行超参数调整,我以 0.0001 的学习率获得了最好的结果。

我使用了 ekshusingh 技术来微调赫尔辛基 NLP 模型。它训练速度快,并且只需要很少的样本就能产生更好的结果。

我做了一些超参数调整,得到了 27 个时期和 32 个批量的最终参数。****

model_train()功能首先将批次分为local_Xlocal_y。我们使用来自记号赋予器的prepare_seq2seq_batch函数将文本转换成记号,这些记号可以用作我们模型的输入。然后,我们使用梯度下降来减少损失,并打印最终损失。

培养

模型的训练花费 30 分钟,有 27 个时期,每个时期花费大约 38 秒来运行。最终损失为 0.0755,这相当不错,显然我们的模型表现良好,但我们仍需要在评估指标上检查它。

*****100% 125/125 [00:38<00:00, 3.84it/s]Loss: tensor(0.0755, device='cuda:0', grad_fn=<DivBackward0>)*****

测试模型

对测试数据集中的单一样本进行测试。

模型表现得相当好,句子有道理。我们需要删除括号和其他不必要的标点符号<pad>,以进一步清理我们的数据集。

使用字符串subreplace,我们从文本中移除了<pad>,', [,]

最终的文本看起来很干净,对于最初的评估几乎是完美的。

对测试数据集的预测

让我们从测试数据集进行预测,并检查我们的模型表现如何。我们将加载您可以从 Zindi *台访问的测试数据集。

生成预测并将张量批量解码成文本。使用.progress_apply我们已经翻译了测试数据集中的所有约鲁巴语文本,并将其移动到名为Label的新列中

清除我们预测的翻译。

你可以看到我们测试数据集的最终版本,它非常准确。为了检查我们的模型在测试数据集上的表现,我们将尝试在 Zindi *台上上传文件。

公制的

比赛使用胭脂分数指标,分数越高,你的模型表现越好。我们这款的排行榜分数是 0.3025 还不错,能让你进前 20。

作者指标| Zindi 排行榜得分

结论

利用迁移学习的能力,我们创建了一个在通用约鲁巴语文本上表现良好的模型。赫尔辛基 NLP 机器翻译多语言模型表现相当好。我在 HugginFace 和 opus-mt-mul-en 上试验了许多公开可用的模型,到目前为止,它们在我们的低资源语言上表现得最好。由于谷歌翻译,机器翻译研究已经衰落,但谷歌翻译不提供低资源语言的翻译,其中一些语言不太准确,所以微调您的机器翻译模型为您提供了使用转换器翻译任何低资源语言的自由。最后,这是我的起始代码,通过多次实验和预处理文本,我以 0.35168 的最终 Rogue 分数在比赛中获得了第 14 名。

竞赛排行榜| 津迪

你可以在kingabzpro/Helsinki-NLP-opus-yor-mul-en 拥抱脸上找到我的模特

偏差-方差误差的简单数学推导

原文:https://towardsdatascience.com/simple-mathematical-derivation-of-bias-variance-error-4ab223f28791?source=collection_archive---------18-----------------------

思想和理论

一个简单直观的图形,表示作为模型复杂性函数的预测(测试数据误差)误差。偏倚误差随着模型复杂度的增加而减小,而方差误差随着模型复杂度的增加而增加(图片来源于知识共享署名 4.0 国际许可条款下的书籍“ 【临床数据科学基础】 ”。)

1。简介

统计建模、数据科学和机器学习中最重要的概念之一是 偏差-方差误差 。这个概念非常重要,因为它有助于我们理解当我们试图拟合数据来预测和做出推断时,在我们的数学建模中出现的不同错误。然而,与这个概念相关的一个问题是,通常,从事数据科学/机器学习的学生/研究人员不太清楚如何推导偏差-方差误差关系。

主要原因与以下事实有关:在大多数学习材料和课程中,很多时候偏差-方差误差(BV 误差)概念的讲授非常肤浅。通常,术语 偏差误差 是指由于我们选择的拟合模型函数与真实模型函数之间的差异而在我们的统计建模中出现的误差。这意味着,如果我们选择一个简单的拟合函数用于我们的统计建模,而真实的函数是更复杂的,那么我们在选择拟合函数时会引入偏差。另一方面, 方差误差 被引入作为在估计对我们的建模中使用的不同样本数据集的拟合函数时的误差。这意味着,如果我们使用一个特定的数据集来拟合我们所选择的模型函数,那么如果我们使用不同的数据集,我们针对新数据集的新拟合函数可能会与之前发现的函数有很大的不同,这取决于样本数据集及其大小

上面给出的偏差和方差误差的两个简单定义在某种程度上是准确的,但没有给学生/研究者一个解释,说明这些误差是如何在统计建模中出现的。在这篇文章中,我用统计理论推导了 BV 误差关系,希望能帮助你更好地理解 BV 误差。这里我假设读者了解数学分析和统计理论。事实上,本文的目的是给出一个严格的推导,同时尽量保持数学符号的简单性。

2。符号和定义

让我首先介绍一些符号,这些符号在接下来的内容中会很有用。这里, X因变量预测器特征矩阵,自变量输出变量向量。其他重要的表示法有数据集、D=(Xy ),模型函数f(Xθ )其中 θ 是我们所选模型的参数向量。例如,在我们试图拟合线性函数的简单线性回归中,模型参数可以是最小二乘法直线的截距和斜率。下面将使用的最后一个符号是损失函数成本函数C(yf(Xθ ))这是对观察值的模型性能的度量 y. 统计/机器学习的整个目标是简单来说就是以下:给定数据集D=(Xy θ )。这是统计/机器学习最简洁、最简单的定义。在实践中,数据集被分为训练测试数据,用于模型性能,但我不会详细介绍,因为我假设读者熟悉这些概念。**

我稍后将广泛使用的另一个重要概念是通用随机变量 X.数学期望值期望值T5期望值这里的 X 是通用随机变量,以免与上述特征矩阵X .混淆。为简单起见,这里我考虑随机变量*的情况所以,让 XN 个离散值*****

那么随机变量 X 的期望值定义为

其中 P(X=x) 是随机变量 X.离散概率分布函数期望值 E 具有不同的性质如 : E(X+Y) = E(X) + E(Y),E(aX) = aE(X),E(XY)= E(X)E(Y)ifXY 【T41另一个重要的量是随机变量 X 的方差,定义为:Var(X)=E(【X-E(X)】),这里通常将 E(X) 称为 X均值。如果随机变量 X 是连续的,那么需要用一个积分代替等式(1)中的和,用一个连续的概率分布函数代替 P(X) 。下面推导的 BV 关系对离散和连续定量变量都有效。

3。 模型分解和成本函数

现在假设我们有一个给定的数据集,其中生成数据的真函数y(x)由下式给出

其中𝜖是对真函数y(x)有贡献的随机误差或随机噪声。假设误差𝜖正态分布,均值为零,标准差为𝜎,如等式(2)所示。误差变量𝜖的不同分量也被认为是不相关的。

假设我们有一个给定的数据集, D =( Xy ),我们要对离散的定量输入输出变量进行典型回归。原则上,数据集 D 可以是任何类型的数据集,例如训练数据或测试数据的数据集,但这里我对测试数据集感兴趣,因为这是统计/机器学习的主要分析目标。如统计学/机器学习中常见的,需要评估代价函数C(yf(Xθ ))对于给定的数据集

成本函数取决于所使用的距离测量方法的类型,这里我将使用典型的欧几里德距离测量(欧几里德度量),其中成本函数可以写成:

统计/机器学习的主要目标是:给定一个固定的数据集,找到使成本函数 C 或等价的 : 最小的参数向量 θ

例如,如果使用不同的数据集,成本函数C(yf(Xθ ))会不同,并且最小化成本函数的参数向量 θ 也会不同 。因此,需要记住的一件重要事情是,成本函数和参数向量值取决于数据集。

假设现在我们已经从训练数据集中“学习”了参数向量 θ ,并且想要为测试数据集 计算成本函数。 在这种情况下,通过使用等式(3)中的一般定义,测试数据集的成本函数由下式给出

可以观察到,在等式(4)中,测试数据集的成本函数明确地依赖于先前学习的参数向量【θ,其中下标 D

如果你已经注意到了所有的定义和等式(4 ),那么我必须祝贺你的耐心和毅力。然而,还有更多的要补充,因为我还没有得到 BV 误差表达式,所以,请耐心等待,继续跟进。

4。偏差-方差误差推导

为了得出 BV 误差,我必须注意它取决于特定的测试数据集和随机误差 𝜖 实例记住这些信息,现在我计算(4)中的测试成本函数期望值 E(C) ,用于可能从总体和不同错误实例中采样的不同可能测试数据集。在这种情况下,(4)中的成本函数是随机变量,因为它隐含地依赖于本身是随机变量的误差 𝜖 (由于(2)中的分解)。通过在等式(2)中使用等式(4),我得到:

作者出于教育目的明确进行的计算。

现在让我解释等式(5)中每一行的含义。在第一行中,我计算了测试数据集 D,的成本函数的期望值,在第一个等式中,我明确地写了成本函数。在第二行,在等式(5)中,我在给定的值x 处加减函数f(x),并使用等式(2),其中我在第四个等式行中写下了【𝜖= y-f .,首先我扩展了二次表达式,然后我使用了之后,我仍然使用等式(2)来计算误差 𝜖、分量的方差和均值,其中对于随机、正态分布且不相关的误差分量,其均值为零。在等式(5)的最后一行,我使用了每个误差方差分量的总和给出了【var】【𝜖】或者仅仅是 噪声 的事实。然而,仍然需要计算等式(5)中最后一行的最后一项。

如果你在方程(5)的所有步骤中设法跟随我,那么我必须再次祝贺你。现在,正如我上面提到的,仍然需要计算等式(5)中最后一行的最后一项,即:

在上面的表达式中需要注意的一件重要事情是,我在可能的不同数据集 D 和错误实例 𝜖.上取期望值事实上,正如我在推导等式(5)时提到的,这里给出的 BV 误差的计算是最通用的,因为它考虑了不同的误差实例和不同的数据集,因此它是一个广义 BV 误差。现在,我可以将等式(5)中最后一行的最后一项写为:

作者出于教育目的明确进行的计算。

在等式(6)的第一行,我增加和减去了一个和等于零的项。在(6)的第二行,我展开了二次型,然后在每一项上使用了期望值 E 的线性特性。在(6)的第三行中,第一项只是一个数,它的期望值就是数本身,并且独立于 D,第二项依赖于 D,而第三项等于零,因为一般随机变量【6】的第四行中 E(X-E(X))=E(X)-E(X)=0

现在我用等式(6)的最后一行代入等式(5)的最后一行,得到最终结果:

作者出于教育目的明确进行的计算。

5。结论和意见

等式(7)是我们旅程的最终表达式,其中测试数据集成本函数的期望值 C 等于不可约(或固有)误差总方差总方差𝜖、总偏差总偏差* 的*方和总方差之和*

既然我推导了等式(7),有人可能会问:它意味着什么?方程式(7)的解释是什么? 第一点 要注意的是,测试数据集的输出误差总是大于不可约噪声(var(【𝜖】),所以学习过程后的总噪声总是大于初始噪声。**

第二点 要注意的是(7)中偏差的定义,其中偏差考虑了在给定点的真实函数f(x)到依赖于在同一点的学习参数向量的学习函数之间的差异。如果我们善于选择学习函数的正确形式,那么它与真实模型函数的差异将是最小的并且接*于零,偏差误差也将接*于零。因此,这意味着偏差考虑了我们在选择正确的函数来建模数据时的准确性。如果我们选择一个更简单的线性函数来模拟一个给定的数据集,其中真正的函数是一个指数函数,那么我们的偏差误差将会很大,因为我们的猜测非常差。

第三点 要注意的是(7)中所学函数的方差的定义。可以观察到,在方差的定义中,在给定点的学习函数与在同一点的学习函数的期望值之间存在差异 D 然而,期望值取决于数据集及其大小。因此,学习函数的方差给出了由于在我们的模型中使用不同数据集而产生的误差,并给出了学习函数与其在不同可能数据集上计算的*均值之间的差异。

要注意的第四点和最后一点 是,等式(7)中的 BV 误差关系是通过使用测试数据集成本函数 C 的欧几里德度量获得的。如果我使用了不同的度量,例如曼哈顿距离度量,则 BV 误差关系不一定与等式(7)中获得的相同。因此,BV 误差关系取决于用于计算距离的度量。

简单的模型堆叠,解释和自动化

原文:https://towardsdatascience.com/simple-model-stacking-explained-and-automated-1b54e4357916?source=collection_archive---------6-----------------------

实践教程

在这个循序渐进的教程中,通过叠加来提高模型性能

La-Rel 复活节Unsplash 上拍摄的照片

模型堆叠概述

在模型堆叠中,我们不使用单个模型进行预测,而是使用几个不同的模型进行预测,然后使用这些预测作为更高级元模型的特征。它尤其适用于不同类型的低水*学习者,他们都对元模型有不同的贡献。模型堆栈可以用许多方法构建,使用堆栈没有一种“正确”的方法。它可以比今天的例子更复杂,有多个级别、权重、*均值等。我们今天将制作的基本模型堆栈如下所示:

具有原始训练特征的模型堆叠-图片由作者提供

在我们的堆栈中,我们将使用一系列中间模型对我们的训练数据进行非泄漏预测,然后将这些作为特征与元模型上的原始训练特征结合使用。

如果这听起来很复杂,不要被吓住。我将向您展示一种无痛的方法来自动化这个过程,包括选择最佳元模型、选择最佳堆栈模型、将所有数据放在一起,并对您的测试数据进行最终预测。

今天,我们使用位于 Kaggle 上的 King County Housing 数据集来处理一个回归问题。

起始位置

健全性检查:本文不涉及任何预处理或模型调优。您的数据集应该是干净的,随时可以使用,如果需要,您的潜在模型应该进行超参数调整。您还应该将您的数据拆分为一个训练/测试集或一个训练/验证/测试集。这篇文章还假设读者对交叉验证有基本的了解。

我们首先用任何可选的超参数实例化我们调优的潜在模型。一个有趣且成功的堆栈的关键是越多越好— 尽可能多地尝试您想要的模型!你可以节省时间,如果你事先对你所有的潜在模型进行交叉验证的抽查,以避免那些明显不能提供信息的模型。但是您可能会惊讶于一个糟糕的基本模型对一个堆栈的贡献有多大。请记住,您添加到可能性中的每个潜在模型都需要时间。但是在您的堆栈中可以尝试的模型数量没有限制,我们教程的关键是我们最终将只使用最好的模型,而不必手动选择任何模型。

对于我们的例子,我将只实例化五个潜在的模型。我们开始吧:

from sklearn.linear_model import LinearRegression, Ridge
from sklearn.svm import SVR
from sklearn.neighbors import KNeighborsRegressor
import xgboost as xgbsvr = SVR(gamma = 'scale', kernel = 'linear', C=10, epsilon=.05)ridge = Ridge(random_state = randomstate, tol=1e-3, normalize=False, solver='auto')neighbor = KNeighborsRegressor(n_neighbors = 11)linreg = LinearRegression()xgbr = xgb.XGBRegressor(n_estimators=1000, eval_metric='mae', max_depth = 7,eta = .1, min_child_weight = 5, colsample_bytree = .4, reg_lambda = 50)

接下来,我们将创建空列表来存储每个潜在的训练集预测(我们将以非泄漏的方式获得)。您需要为每个潜在模型列出一个列表,一致的命名约定将有助于保持有序。

svr_yhat, ridge_yhat, neighbor_yhat, linreg_yhat, xgbr_yhat = [], [], [], [], []

最后,我们将实例化的模型和它们的空预测列表放到一个存储字典中,我们将在各种堆栈函数中使用它。每个字典条目的格式是“标签”:[模型实例,预测列表],像这样:

models_dict = {'SVR' : [svr, svr_yhat], 
                'Ridge' : [ridge, ridge_yhat],  
                'KNN' : [neighbor, neighbor_yhat], 
                'Linear Regression' : [linreg, linreg_yhat], 
                'XGB' : [xgbr, xgbr_yhat]}

健全性检查:为以下函数准备数组格式的训练/测试集。X 要素应该是(n,m)的数组形状,其中 n 是样本数,m 是要素数,y 目标应该是(n,)的数组。如果它们是数据帧,用 np.array(df)转换它们

获得非折叠预测

有一个超出折叠或超出样本的预测意味着什么?在模型堆叠中,我们使用对训练数据本身做出的预测来训练元模型。正确包含这些预测的方法是将我们的训练数据分成多个折叠,就像交叉验证一样,并使用剩余的折叠对每个折叠进行预测。通过这种方式,我们将拥有针对我们的训练数据的全套预测,但没有任何数据泄漏,如果我们只是简单地训练,然后在同一套数据上进行预测,就会出现这种情况。

这是我们的第一个函数,用来得到我们的非折叠预测。这个函数改编自机器学习大师上的大折叠预测教程:

from sklearn.model_selection import KFolddef train_oof_predictions(x, y, models, verbose=True):
    '''Function to perform Out-Of-Fold predictions on train data
    returns re-ordered predictors x, re-ordered target y, and model dictionary with filled predictors
    Parameters:
    x: training predictors
    y: training targets
    models: dictionary of models in form of model name : [instantiated model, predictors list]
    verbose: if True, prints status update as the function works
    '''

    # instantiate a KFold with 10 splits
    kfold = KFold(n_splits=10, shuffle=True, random_state=randomstate)

    # prepare lists to hold the re-ordered x and y values
    data_x, data_y  = [], []

    # run the following block for each of the 10 kfold splits
    for train_ix, test_ix in kfold.split(x, y):

        if verbose: print("\nStarting a new fold\n")

        if verbose: print("Creating splits")
        #create this fold's training and test sets
        train_X, test_X = x[train_ix], x[test_ix] 
        train_y, test_y = y[train_ix], y[test_ix]

        if verbose: print("Adding x and y to lists\n")
        # add the data that is used in this fold to the re-ordered lists
        data_x.extend(test_X)
        data_y.extend(test_y)

        # run each model on this kfold and add the predictors to the model's running predictors list
        for item in models:

            label = item # get label for reporting purposes
            model = models[item][0] # get the model to use on the kfold

            # fit and make predictions 
            if verbose: print("Running",label,"on this fold")
            model.fit(train_X, train_y) # fit to the train set for the kfold
            predictions = model.predict(test_X) # fit on the out-of-fold set
            models[item][1].extend(predictions) # add predictions to the model's running predictors list

    return data_x, data_y, models

现在,我们已经准备好了,使用我们之前制作的模型字典,来获得非折叠预测。该函数默认为 verbose,并将提供有关其进度的状态更新。请记住,如果您的堆栈中有大量数据集或大量模型要尝试,那么获得 OOF 预测可能需要很长时间!

运行折叠外预测功能:

data_x, data_y, trained_models = train_oof_predictions(X_train, y_train, models_dict)

健全性检查:检查这个折叠函数的一致输出。字典中的所有 yhats 都应该返回普通的数字列表,没有任何数组。

我们现在有了 data_x 和 data_y,它们是与我们的 x_train 和 y_train 相同的数据,但是被重新排序以匹配势的 yhat 预测的顺序。我们返回的 trained_models 字典包含对整个训练集和每个潜在模型的预测。

运行堆栈选择器

堆栈选择器时间到了。这是我们的下一个函数。这个是基于大卫·戴尔写的特征选择向前向后选择器:

from sklearn.model_selection import cross_validatedef model_selector(X, y, meta_model, models_dict, model_label, verbose=True):

    """ 
    Perform a forward model selection based on MAE improvement
    Parameters:
        X - baseline X_train with all features
        y - baseline y_train with all targets
        meta_model - meta_model to be trained
        models_dict - dictionary of models in format of model name : [model object, out-of-fold predictions]
        label - the label for the current meta model
        verbose - whether to print the sequence of inclusions(True recommended)
    Returns: list of selected models, best MAE 
    """print("\n\nRunning model selector for ", model_label)
    included_models = []

    while True:
        changed=False

        # forward step

        if verbose: print("\nNEW ROUND - Setting up score charts")
        excluded_models = list(set(models_dict.keys())-set(included_models)) # make a list of the current excluded_models
        if verbose: print("Included models: {}".format(included_models))
        if verbose: print("Exluded models: {}".format(excluded_models))
        new_mae = pd.Series(index=excluded_models) # make a series where the index is the current excluded_models

        current_meta_x = np.array(X)

        if len(included_models) > 0:
            for included in included_models:
                included = np.array(models_dict[included][1]).reshape((len(models_dict[included][1]), 1))
                current_meta_x = np.hstack((current_meta_x, included))# score the current model
        scores = cross_validate(meta_model, current_meta_x, y, cv=5, n_jobs=-1, scoring=('neg_mean_absolute_error'))
        starting_mae = round(scores['test_score'].mean(),3)
        if verbose: print("Starting mae: {}\n".format(starting_mae))

        for excluded in excluded_models:  # for each item in the excluded_models list:

            new_yhat = np.array(models_dict[excluded][1]).reshape(-1, 1) # get the current item's predictions
            meta_x = np.hstack((current_meta_x, new_yhat)) # add the predictions to the meta set

            # score the current item
            scores = cross_validate(meta_model, meta_x, y, cv=5, n_jobs=-1, scoring=('neg_mean_absolute_error'))
            mae = round(scores['test_score'].mean(),3)
            if verbose: print("{} score: {}".format(excluded, mae))

            new_mae[excluded] = mae # append the mae to the series field

        best_mae = new_mae.max() # evaluate best mae of the excluded_models in this round
        if verbose: print("Best mae: {}\n".format(best_mae))

        if best_mae > starting_mae:  # if the best mae is better than the initial mae
            best_feature = new_mae.idxmax()  # define this as the new best feature
            included_models.append(str(best_feature)) # append this model name to the included list
            changed=True # flag that we changed it
            if verbose: print('Add  {} with mae {}\n'.format(best_feature, best_mae))
        else: changed = False

        if not changed:
            break

    print(model_label, "model optimized")
    print('resulting models:', included_models)
    print('MAE:', starting_mae)

    return included_models, starting_mae

健全性检查:我的功能是对*均绝对误差进行评分,但是您可以根据您最喜欢的评分标准进行编辑,比如 R2 或 RMSE。

我们将最终使用我们的每个潜在模型作为函数的元模型来运行这个函数。当我们运行这个函数时,我们向它发送从 out-of-fold 函数中得到的 data_x 和 data_y,还有一个实例化的模型作为元模型,以及我们的字典和所有 out-of-fold 预测。然后,该函数使用折叠外预测作为特征运行向前选择。

对于被尝试作为元模型的模型,我们在训练集上获得基线分数(使用 CV)。对于每个其他潜在模型,我们迭代地将潜在的 yhat 预测附加到特征集,并使用该附加特征对元模型重新评分。如果我们的元模型得分随着任何特征的增加而提高,那么单个最佳得分潜力的预测将被永久地附加到特征集,并且提高的得分将成为基线。然后,该函数循环,再次尝试添加尚未在堆栈中的每个潜在值,直到没有潜在值可以提高分数。然后,该函数报告这个元模型的最佳包含模型,以及获得的最佳分数。

健全性检查:编写这个模型选择器是为了使用 CV 在训练集上进行优化。如果你足够幸运有一个验证集,你可以重写并执行选择。它会快得多——但要小心过度拟合!

我们如何为这个任务选择元模型?有趣的部分来了——我们将尝试我们所有的模型作为元模型。请记住,此功能可能需要很长时间才能运行。将 verbose 设置为 True 会给出频繁的进度报告。

我们制作了一个字典来存储我们将从测试中得到的所有分数。然后,我们在每个经过训练的模型上运行堆栈选择器,将该模型用作元模型:

# Set up a scoring dictionary to hold the model stack selector results
scores = {}
scores['Model'] = []
scores['MAE'] = []
scores['Included'] = []# Run the model stack selector for each model in our trained_modelsfor model in trained_models:

    meta_model = trained_models[model][0] resulting_models, best_mae = model_selector(data_x, data_y,  meta_model, trained_models, label, verbose=True)

    scores['Model'].append(model)
    scores['MAE'].append(best_mae)
    scores['Included'].append(resulting_models)

之后,我们将得到每个模型作为元模型的表现分数,以及它最好的附加部分。我们将字典转换成数据框架,并根据分数标准对结果进行排序:

# Look at the scores of our model combinationsbest_model = pd.DataFrame(scores).reset_index(drop=True)
best_model.sort_values('MAE', ascending=False) 

现在,我们可以确切地看到哪个元模型和堆叠模型执行得最好。

作者图片

把所有的放在一起

我们快完成了!很快我们将在我们的测试集上进行预测。我们已经选择了一个元模型(可能是在堆栈选择器上表现最好的一个!)和我们将包括的堆叠模型。

在我们将元模型与堆叠数据相匹配之前,在测试集上尝试没有添加特性的模型,这样您就可以比较堆叠模型的改进了!在原始训练/测试集上拟合和预测元模型。这是我们期望用堆叠模型打破的基线。

# Check our meta model on the original train/test set only# Instantiate the chosen meta model
meta_model =  SVR(gamma = 'scale', kernel = 'linear', C=10, epsilon=.05)meta_model.fit(X_train, y_train)
predictions = meta_model.predict(X_test)pred_exp = np.exp(predictions)
actual = np.exp(y_test)print("MAE: ",int(mean_absolute_error(pred_exp, actual)))
print("RMSE:",int(np.sqrt(mean_squared_error(pred_exp, actual))))
print(("R2:",r2_score(pred_exp, actual)*100)*Output:
MAE:  53130
RMSE: 82427
R2: 86.93570728212*

后退一步,将我们将在堆栈中使用的所有模型放入我们的原始训练数据集。我们这样做是因为我们将在测试集上进行预测(与单个模型相同!)并将预测作为元模型的特征添加到我们的测试集中。

print("Fitting Models")
linreg.fit(X_train, y_train)
xgbr.fit(X_train, y_train)
knn.fit(X_train, y_train)

现在我们准备模型堆栈。首先,手动创建一个列表,只存储我们在最终堆栈中使用的模型的折叠外预测。我们从先前使用折叠外预测函数生成的“trained_models”字典中获得这些预测:

yhat_predics = [trained_models['XGB'][1], trained_models['Linear Regression'][1], trained_models['KNN'][1]]

又到了一个功能的时间了。这一个接受我们重新排序的 train data_x 和包含 yhat 预测的列表,并把它们放在一个单一的元 train 集合中。我们在一个函数中这样做,因为稍后我们将对测试数据再次这样做。

def create_meta_dataset(data_x, items):
    '''Function that takes in a data set and list of predictions, and forges into one dataset
    parameters:
    data_x - original data set
    items - list of predictions
    returns: stacked data set
    '''

    meta_x = data_x

    for z in items:
        z = np.array(z).reshape((len(z), 1))
        meta_x = np.hstack((meta_x, z))

    return meta_x

现在调用这个函数传递 data_x 和预测列表,为我们的元模型创建一个元训练集:

# create the meta data set using the oof predictions
meta_X_train = create_meta_dataset(data_x, yhat_predics)

元训练集由我们的原始预测特征以及堆叠模型的非折叠预测作为附加特征组成。

制作一个列表来保存拟合的模型实例;我们将在下一个也是最后一个函数中用到它。确保这与您为元堆栈器列出的 yhat 预测顺序相同!

final_models = [xgbr, linreg, knn]

我们最后一次活动的时间到了。该函数接受我们的测试集和拟合模型,使用拟合模型对测试集进行预测,然后将这些预测作为特征添加到测试集。它发回一个完整的 meta_x 集合,供元模型进行预测。

def stack_prediction(X_test, final_models): 
    '''takes in a test set and a list of fitted models.
    Fits each model in the list on the test set and stores it in a predictions list. Then sends the test set and the predictions to the create_meta_dataset to be combined
    Returns: combined meta test set
    Parameters:
    X_test - testing dataset
    final_models - list of fitted models
    '''
    predictions = []

    for item in final_dict:
        print(item)
        preds = item.predict(X_test).reshape(-1,1)
        predictions.append(preds)

    meta_X = create_meta_dataset(X_test, predictions)

    return meta_X

这里我们调用函数,发送测试集和拟合模型:

meta_X_test = stack_prediction(X_test, final_models)

最终模型评估

关键时刻终于来了。使用堆叠模型进行预测的时间到了!

# fit the meta model to the Train meta dataset
# There is no data leakage in the meta dataset since we did all of our predictions out-of-sample!
meta_model.fit(meta_X_train, data_y)# predict on the meta test set
predictions = meta_model.predict(meta_X_test)pred_exp = np.exp(predictions)
actual = np.exp(y_test)print("MAE: ",int(mean_absolute_error(pred_exp, actual)))
print("RMSE:",int(np.sqrt(mean_squared_error(pred_exp, actual))))
print(("R2:",r2_score(pred_exp, actual)*100)*Output:
MAE:  47205
RMSE: 73973
R2: 90.03816032670765*

在我们的堆栈示例中,我们将测试集上的 MAE 从 53130 减少到 47205,提高了 11.15%。

我希望你能看到你的模型分数的提高,并能看到尝试堆叠模型的效用!我相信您已经学到了一些有价值的工具,可以添加到自动化模型选择和堆叠的工具包中。

参考资料:

  1. 如何在机器学习中使用非折叠预测

2.大卫·戴尔的前向-后向特征选择

使用 K-最*邻机器学习算法的 NBA 位置的简单建模

原文:https://towardsdatascience.com/simple-modeling-of-nba-positions-using-the-k-nearest-neighbors-machine-learning-algorithm-223b8addb08f?source=collection_archive---------20-----------------------

NBA 赛季再次升温,这意味着世界各地的篮球迷们正准备观看他们最喜爱的球员以远距离三分,海报扣篮和以往任何时候都不尊重的脚踝交叉球征服世界。

本着展示绝对统治地位的精神,我想分享一下计算机是如何利用机器学习在篮球知识上统治一般球迷(比如我自己)的。

在这篇博客中,我将向你展示如何创建一个机器学习模型(用 Python 编写),它可以让只从职业生涯得分、助攻、篮板、盖帽和抢断中学习 NBA 位置和打球风格

看看这里的配套视频:https://www.youtube.com/watch?v=Va5X6zcNsPw

照片由 JC GellidonUnsplash

基本面

任何观看现代 NBA 篮球的人都知道,联盟是最丰富的数据资源之一。NBA 收集了大量关于球队、球员和比赛的数据。这些数据凸显了 NBA 引以为豪的一些声望和精英人才。以下是一些例子:

  • 勒布朗·詹姆斯已经在 NBA 打了 18 个赛季。NBA 常规赛长达 82 场。常规赛结束后,16 支优秀的球队将在 NBA 季后赛中争夺总冠军的机会。迄今为止,勒布朗·詹姆斯已经打了 266 场 NBA 季后赛。这意味着勒布朗也有效地打了三个多赛季的比赛,仅仅是季后赛的出场。
  • 丹尼斯·罗德曼连续 7 年在篮板上领先联盟,但是他直到 30 岁才第一次领先。
  • 在 1961-1962 赛季,威尔特·张伯伦*均每场比赛上场 48.5 分钟。起初,这听起来像是一个适度的统计线,直到你意识到一场常规的 NBA 比赛在 48 分钟结束。他是怎么做到的?他在每场比赛中尽可能地打好每一分钟,包括几场进入加时赛的比赛。这在 NBA 的任何时代都是罕见的。

在这篇博客中,我们将引用一些更频繁引用的数据点。即:得分,助攻,篮板,盖帽,抢断。这些数据通常在讨论玩家在任何游戏中的表现时被提及。我想到了一些特别的表演:

  • 在 NBA 历史上,一个球员在整个赛季中*均只有五次达到三双(在上面提到的五次统计中有三次达到两位数)。其中四次是由拉塞尔·威斯布鲁克提供的。
  • 勒布朗·詹姆斯是第一个也是唯一一个在 NBA 总决赛场均三双的球员
  • 德雷蒙德·格林是第一个也是唯一一个没有得到两位数分数就获得三双的球员

到现在为止,你应该已经看到了这项运动的伟大之处。

回到基础——有组织的篮球比赛有五个位置:

  • 控球后卫
  • 得分后卫
  • 小前锋
  • 大前锋
  • 中心

这就把我们带到了这个博客的目标——让一台计算机只使用得分、助攻、篮板、盖帽和抢断来学习这些位置。为了简单起见,我们将组合两个后卫位置和两个前锋位置,总共三个位置。

机器学习

为此,我们将使用 K *邻(KNN)分类算法。KNN 通常被视为最简单的机器学习模型之一。如果你刚刚开始学习机器学习,下面是你需要知道的要点(如果你已经知道 KNN 是如何工作的,请随意跳到下图):

k-最*邻是一种监督机器学习技术。这意味着我们的训练数据由数据点的特征(即沿 x 轴和 y 轴的值)以及数据点所属的(即数据点的颜色)组成。

该算法或模型首先通过绘制训练数据点来工作。接下来,绘制新的数据点(实际上,我们称之为测试数据),其特征是已知的,但其类别是未知的。测量测试数据点和 N 个最*邻点(下图中 N=3)之间的距离。

从这里开始,这是一个多数规则过程,例如,如果大多数邻居是红色类的成员,则测试数据点被标记为红色数据点。就是这样!

三个最*邻的预测

在这个 KNN 的例子中,我们模型的特征将是职业生涯得分、助攻、篮板、盖帽和抢断。我们的班级将是三个篮球位置:后卫,前锋和中锋。

让我们进入代码。

从我们的导入开始,我们将使用科学计算包 numpy、数据操作和分析包 pandas、绘图和可视化包 matplotlib,以及来自 sklearn 包的 KNN 分类器。最后,我们将使用 PyPi 的 basketball_reference_scraper 包(如果需要的话可以在这里 pip 安装它)。basketball_reference_scraper 包从 https://www.basketball-reference.com/的获取数据和统计数据。来自篮球 _ 参考 _ 铲运机。我们需要 players.get_stats 函数来检索职业统计数据,如场均得分或场均篮板。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
from sklearn.neighbors import KNeighborsClassifier
from basketball_reference_scraper.players import get_stats

接下来是训练数据。同样,这是我们的特性和类已知的数据。这意味着我们需要从每个位置选择一些 NBA 球员。我选择了一些目前的球员,但是你可以选择任何在联盟中有一些重要经验的人(并且在他们的位置上是/曾经是特别好的!).

POSITION_TYPES = ['CENTER', 'GUARD', 'FORWARD']# Centers
centers=[
    'nikola jokic',
    'joel embiid',
    'anthony davis',
    'andre drummond',
    'bam adebayo'
]# Guards
guards=[
    'damian lillard',
    'stephen curry',
    'luka doncic',
    'jamal murray',
    'james harden'
]# Forwards
forwards=[
    'giannis antetokounmpo',
    'draymond green',
    'pascal siakam',
    'zion williamson',
    'blake griffin'
]

接下来,我们收集所有这些玩家的数据:

def fetch_player_career(player):
    career = get_stats(player, stat_type='PER_GAME', playoffs=False, career=False, ask_matches=False)

    # Drop rows containing 'Did Not Play' by only returning rows with digits in the "Games Played" field
    career_stats = career[career['G'].apply(lambda x: str(x).replace('.','').isdigit())]

    return career_statscareers = []
nba_players = centers + guards + forwards
for player in nba_players:
    print(player)
    careers.append(fetch_player_career(player))

现在我们准备好准备我们的训练数据。要做到这一点,我们需要每个赛季的*均数据。我们将求和,然后除以赛季。这会给我们每场比赛的*均值。我们使用每场比赛的*均水*,因为它将职业生涯长度纳入了模型。换句话说,如果一名球员在职业生涯中获得了 2000 次助攻,那么这名球员是在 7 年内还是在联盟中的 15 年内完成的都很重要,因为这将显示出他们在各自位置上的效率。

例如,如果一个球员在第一个赛季场均 15 分,第二个赛季场均 20 分,我们将 15 和 20 相加得到 35,然后除以 2 个赛季得到职业生涯场均 17.5 分。

还要注意的是,y_train 所发生的一切是,我声明了一个大小为(15)的数组,该数组保存的位置值经过编码,以匹配我们的训练数据中使用的 15 名球员:

  • 中心= 0
  • 防护= 1
  • 向前= 2
def extract_stats(career_stats):
    '''
    extract_stats() takes a player's stats and returns a numpy array of [PTS, AST, TRB, STL, BLK]
    '''
    total_seasons = len(career_stats)

    career_ppg = (sum(career_stats['PTS'].astype(float)) / total_seasons)
    career_ast = (sum(career_stats['AST'].astype(float)) / total_seasons)
    career_trb = (sum(career_stats['TRB'].astype(float)) / total_seasons)
    career_stl = (sum(career_stats['STL'].astype(float)) / total_seasons)
    career_blk = (sum(career_stats['BLK'].astype(float)) / total_seasons)

    return np.array([career_ppg, career_ast, career_trb, career_stl, career_blk])X_train = np.zeros((15,5))
for i in range(len(careers)):
    X_train[i] = extract_stats(careers[i])

y_train = np.array([0]*5 + [1]*5 + [2]*5)

我们准备好训练我们的模型了!继续实例化一个 KNN 分类器的实例,并调用它的。对训练数据使用 fit()函数:

clf = KNeighborsClassifier()
clf.fit(X_train, y_train)

现在我们有了分类器,我将编写一个“预测”函数。该函数将采用我们的分类器,以及任何球员的统计数据(extract_stats()函数的返回值),并尝试基于我们之前查看的相同职业统计数据来预测该球员的位置。

def predict_position(stats, clf):    
    position_id = clf.predict(stats)[0]
    position = POSITION_TYPES[position_id]
    return position

让我们看看分类器在一些明星球员身上的表现如何…

more_players = [
    'michael jordan', # 1
    'magic johnson',  # 1
    'chris paul',  # 1
    'marc gasol',  # 0
    'dikembe mutombo',  # 0
    'russell westbrook',  # 1
    'kevin durant',  # 2
    'larry bird',  # 2
    'john stockton',  # 1
    'derrick rose',  # 1
    'charles barkley',  # 2
    'demarcus cousins',  # 0
    'kyrie irving',  # 1
    'rudy gobert',  # 0
    'kawhi leonard',  # 2
    'devin booker',  # 1
    'steve nash',  # 1
    'tim duncan',  # 0
    'dirk nowitzki',  # 2
    'carmelo anthony',  # 2
    'paul george',  # 2
    'lebron james'  # 2
]X_test = np.zeros((len(more_players),5))for i in range(len(more_players)):
    all_career_stats = fetch_player_career(more_players[i])
    stats = extract_stats(all_career_stats).reshape(1,-1)
    X_test[i] = (stats)y_test = [1, 1, 1, 0, 0, 1, 2, 2, 1, 1, 2, 0, 1, 0, 2, 1, 1, 0, 2, 2, 2, 2]correct_pred = 0for p in range(len(X_test)):
    predicted_position = predict_position(X_test[p].reshape(1,-1), clf)
    actual_position = POSITION_TYPES[y_test[p]]if predicted_position == actual_position:
        correct_pred += 1print(f'I think {more_players[p]} is a {predicted_position}. He played {actual_position} in his career')I think michael jordan is a GUARD. He played GUARD in his career
I think magic johnson is a GUARD. He played GUARD in his career
I think chris paul is a GUARD. He played GUARD in his career
I think marc gasol is a FORWARD. He played CENTER in his career
I think dikembe mutombo is a CENTER. He played CENTER in his career
I think russell westbrook is a GUARD. He played GUARD in his career
I think kevin durant is a GUARD. He played FORWARD in his career
I think larry bird is a CENTER. He played FORWARD in his career
I think john stockton is a FORWARD. He played GUARD in his career
I think derrick rose is a CENTER. He played GUARD in his career
I think charles barkley is a CENTER. He played FORWARD in his career
I think demarcus cousins is a CENTER. He played CENTER in his career
I think kyrie irving is a GUARD. He played GUARD in his career
I think rudy gobert is a CENTER. He played CENTER in his career
I think kawhi leonard is a FORWARD. He played FORWARD in his career
I think devin booker is a GUARD. He played GUARD in his career
I think steve nash is a FORWARD. He played GUARD in his career
I think tim duncan is a CENTER. He played CENTER in his career
I think dirk nowitzki is a FORWARD. He played FORWARD in his career
I think carmelo anthony is a FORWARD. He played FORWARD in his career
I think paul george is a FORWARD. He played FORWARD in his career
I think lebron james is a GUARD. He played FORWARD in his career

20 个位置中有 14 个预测正确。还不错!这是 70%的准确率。让我们花一点时间了解我们的缺点,并找出需要改进的地方。

I think larry bird is a CENTER. He played FORWARD in his career
I think charles barkley is a CENTER. He played FORWARD in his career
I think derrick rose is a CENTER. He played GUARD in his career
I think steve nash is a FORWARD. He played GUARD in his career
I think john stockton is a FORWARD. He played GUARD in his career
I think lebron james is a GUARD. He played FORWARD in his career

如果我们的错误预测是我们的模型预测的中心位置,则为 50%。这意味着模型可能会过度拟合到中心位置。这有助于从机器学习上下文以及篮球上下文中理解这一点。出现这种情况的几个原因可能是

  • 众所周知,NBA 中锋比普通球员获得更多的篮板和盖帽,所以任何出色的,高大的,或高于*均水*的后卫前锋都可能获得盖帽和篮板,欺骗模型认为他们是中锋。
  • 眼尖的人可能会注意到,在写这篇博客的时候,用于我们训练的 NBA 中锋的*均年龄是 20 多岁,这意味着这个模型并不完全理解中锋的位置是如何在职业生涯中发挥作用的。这将有助于包括一些已经打满职业生涯的中锋球员,如卡里姆·阿布杜尔·贾巴尔、哈基姆·奥拉朱旺或德怀特·霍华德。
  • 我们也可以包括每个球员更多的数据点。当谈到 NBA 中锋时,抢断和助攻这样的统计数据往往不是亮点的一部分,所以模型不会从他们身上学到很多东西。一些好的候选人包括防守篮板,三分球尝试,投篮命中率
  • 即使是我们的模型也不得不承认它的伟大。像勒布朗·詹姆斯这样真正杰出的球员在他们的职业生涯中打过好几个位置。在选择球员时,我们应该谨慎选择那些在最适合他们的位置上表现出色的球员——比如中锋沙克或者控卫达米恩·利拉德。

最重要的是,有了从 NBA 创建的所有数据,我们最大的收获可能来自于使用更多的训练数据来创建我们的模型。15 名球员是一个好的开始,但我们的模型可以通过训练 50 到 100 名球员来减少失误,其中更多的是 NBA 老将。

最后,下面是 NBA 球员测试集的一个剧情。因为这五个属性很难在二维空间中可视化,我们将把这些属性分为基于得分的属性和非基于得分的属性。你将开始看到某些职位是如何与他们的统计数据相关联的。然而,像迈克尔·乔丹或勒布朗·詹姆斯这样的特殊球员有足够的技术出现在他们“预期”的区域之外。要不是这样的人才,我们的数据早就线性可分了!

恭喜你!如果你做到了这一步,你就有了将机器学习应用于 NBA 数据分析的能力。如果你想要这个项目的完整源代码,请查看这个 Github repo:Christophe brown/KNN _ NBA _ positions(github.com)

使用 VPython 的简单物理动画

原文:https://towardsdatascience.com/simple-physics-animations-using-vpython-1fce0284606?source=collection_archive---------11-----------------------

实践教程

使用 Python 和 GlowScript 创建 3D 物理模拟,以模拟带电粒子在磁场中的螺旋运动

摄影:飞:DUnsplash

在现实生活中,进行物理实验可能具有挑战性,通常涉及昂贵而又嘈杂的设备。随着今天的实验变得越来越复杂,模拟和建模已经成为产生和解释数据的一个有吸引力的新领域。本文旨在让您开始使用 VPython——一种用于模拟的 3D Python 环境——对物理系统建模。

模拟带电粒子在磁场中的运动

今天,我们要看看带电粒子是如何在磁场中运动的。电磁学是对电场和磁场如何相互作用的研究。当带电粒子以垂直于外部磁场的速度运动时,它执行圆周运动,因为恒定垂直于速度的磁力充当圆周运动的向心力。

如果速度不完全垂直于磁场呢?这意味着垂直于磁场的速度分量将继续为带电粒子做圆周运动提供向心的力。另一方面,*行于磁场的速度分量既不会经历任何向心加速度,也不会经历任何方向变化。因此,我们将观察到如下所示的螺旋路径。

带电粒子在磁场中的螺旋运动(图片由作者提供)

VPython 简介

我们将使用 VPython 来重现这一物理现象。VPython 允许我们对这一现象进行 3D 可视化。我们将使用 GlowScript,这是一个用于 VPython 的在线代码编辑器。您可以在此处访问它:

https://glowscript.org/

点击链接后,点击“登录”并使用您的 Google 帐户登录。然后在 GlowScript 页面点击“此处”按钮,再点击“创建新程序”即可开始!或者,您可能希望在本地运行 VPython,在这种情况下,您必须导入 VPython 模块。完整的 VPython / Glowscript 文档可以在这里找到。

创造环境

在我们开始处理任何运动的粒子之前,我们首先要定义我们的工作空间。下面的代码展示了我们如何通过定义画布的大小在 VPython 中创建场景。

scene = display(width=1500, height=600)

首先,我们要开始定义我们实验的边界。我们将在一个封闭的容器中进行实验,这个容器由一个立方体的各个侧面组成。换句话说,我们将绘制自己的容器。

xlen, ylen , zlen = 100, 100, 100
boundaries = [
    box(pos = vector(0,-ylen/2,0), size = vector(xlen, .2, zlen)),
    box(pos = vector(0,ylen/2,0), size = vector(xlen, .2, zlen)),
    box(pos = vector(-xlen/2,0,0), size = vector(.2, ylen, zlen)),
    box(pos = vector(xlen/2,0,0), size = vector(.2, ylen, zlen)),
    box(pos = vector(0,0,-zlen/2), size = vector(xlen, ylen, .2))
    ]

这里,我们将立方体容器的长度标准化为 100 个单位。我们还定义了一系列盒子(即长方体)来构成我们的容器的侧面。让我们来看看“盒子”中的每个参数是做什么的:

  • pos 参数接受一个向量,它表示盒子中心的位置向量。
  • 大小参数接受另一个向量,它接受 3 个值,分别是盒子在 x、y 和 z 轴上的长度。请注意,对于每个盒子,其中一个轴的边长为 0.2 个单位,这表示我们容器的厚度。

万岁!现在我们有了一个容器来进行实验。在我们开始实际创建对象之前,让我们定义几个物理常数。这些常量背后的含义将在后面的章节中详细阐述,但是在这一点上对这些值的作用有一个粗略的概念就足够了。

dt = .001 #time step
Bfield = 5 #strength of magnetic field
v_mag = 20 # magnitude of velocity of proton
Q = 0.5 #charge of proton in arbitrary units
theta = pi/4 #angle of launch of proton
v = vector(v_mag*cos(theta), v_mag*sin(theta), 0) #velocity vector
B = vector(0,-Bfield,0) #vector of magnetic field
starting_point = vector(0,-ylen/2 + 1,0) #starting position vector of proton 

使用 Python 类定义对象

在下一部分,我们将使用 Python 类来表示质子在磁场中的运动。

class create_proton:
    def __init__(self, v): #v is a vector representing velocity
        self.v = v
        self.proton = sphere(pos = starting_point, color = color.red, radius = 1, make_trail=True, trail_type="curve")
        self.a = vector(0,0,0)

    def move(self): #moves proton by small step
        self.a = Q * cross(self.v, B) # F = ma = q v x B
        self.v += self.a * dt #a = dv/dt
        self.proton.pos += self.v * dt #v = dx/dt

    def reset_proton(self): #resets proton position and path
        self.proton.pos = starting_point 
        self.v = v
        self.proton.clear_trail()
        self.a = vector(0,0,0)

    def check_collision(self): #checks for boundaries
        if self.proton.pos.y < ylen / 2 and self.proton.pos.x < xlen/2 and self.proton.pos.y > -ylen/2 and self.proton.pos.x > -xlen/2 and self.proton.pos.z > -zlen/2 and self.proton.pos.z < zlen/2:
            return True
        else:
            return Falseproton = create_proton(v) #creates the variable 'proton'

在上面的 create_proton 类中有 4 个函数。以下是它们的功能:

  • init

这个函数将在创建类时被调用。这将质子的默认速度向量设置为 self.v。我们还创建了质子,它在 VPython 中建模为球体。我们定义了质子的半径,并打开了在质子路径后面绘制轨迹的设置。

  • 移动

这个函数在特定的时间点以小的增量移动质子。加速度(self.a)是根据洛伦兹力定律计算出来的,该定律表述为F=Q(vxB)。因此,我们使用矢量 vB 的叉积来计算合成加速度及其方向。不需要分解速度的单个分量。这也是我们的时间步长发挥作用的地方,因为我们每次移动质子一小步,我们逐渐更新速度和位移。因此,我们将小时间步长 dt 乘以质子的位移和速度。

基于上面定义的矢量 B ,假设磁场指向下方。初速度 v 也由之前定义的角度θ(θ)决定。

  • 复位 _ 质子

该函数重置所有参数,以便我们可以在以后多次运行该实验。

  • 检查 _ 碰撞

如果与容器壁没有碰撞,函数返回 True。如果不是,则返回 False,程序终止。

此时,如果您点击“运行此程序”,您将看到以下布局:

底部有红色球体质子的 3D 盒子(图片由作者提供)

你可以按住鼠标右键拖动盒子。

启动功能

下面我们定义主启动函数,它执行我们实验的一个实例。首先,我们重置系统中的所有变量,当质子不与容器的任何壁碰撞时,我们在等待每个小的时间步长 dt 后移动质子。时间步长的设置是为了提高算法的效率。

def launch():
    proton.reset_proton()
    while proton.check_collision():
        rate(1/dt) #basically a delay function
        proton.move()

之后,我们创建一个启动按钮,这样我们就可以按下它来开始实验。该按钮的代码如下:

button(text="Launch!", bind=launch) #link the button and function

使用滑块调整参数

在任何实验中,当我们这样做时,我们希望能够改变我们的参数来观察趋势。滑块在实现这一功能时非常有用。比如下面是调整磁场强度的代码( B )。

scene.append_to_caption("\n\n") #newlines for aesthetics
def adjustBfield():
    global Bfield #to update global value
    Bfield = BfieldSlider.value
    B = (0,-Bfield,0) #B directed downwards
    BfieldSliderReadout.text = BfieldSlider.value + " Tesla"BfieldSlider = slider(min=0, max=10, step=.5, value=5,
bind=adjustBfield)
scene.append_to_caption(" B-field Strength = ")
BfieldSliderReadout = wtext(text="5 Tesla")

该函数接收滑块的输入,并更新代码中的磁场强度值。当滑块被调整时,函数adjust field将被调用,代码中的所有值将被更新。屏幕上显示的 B 的值也会更新。创建滑块时,还可以指定滑块的范围和间隔。如果你想改变这些参数,你可以参考滑块的文档:https://www.glowscript.org/docs/VPythonDocs/controls.html

类似的滑块可以用于充电量( Q )和发射角度( θ ),下面已经提供了相关的代码。

#Adjust charge Q
scene.append_to_caption("\n\n")
def adjustQ():
    global Q
    Q = QSlider.value
    QSliderReadout.text = QSlider.value + " Coulumbs"QSlider = slider(min=0, max=1, step=.1, value=.5,
bind=adjustQ)
scene.append_to_caption(" Q = ")
QSliderReadout = wtext(text="0.5 Coulumbs")#Adjust angle theta
scene.append_to_caption("\n\n")
def adjustAngle():
    global theta
    theta = angleSlider.value * pi / 180 #degree - radian conversion
    angleSliderReadout.text = angleSlider.value + " degrees"
    proton.v = vector(v_mag*cos(theta), v_mag*sin(theta), 0)

angleSlider = slider(min=0, max=90, step=1, value=45,
bind=adjustAngle)
scene.append_to_caption(" Angle = ")
angleSliderReadout = wtext(text="45 degrees")

构建滑块后,它们应该出现在画布下方,如下所示:

启动按钮和滑块来调整实验参数(图片由作者提供)

您可以拖动滑块来修改参数,以改变质子的路径。

运行模拟

现在,你可以发射质子了!单击“运行该程序”,然后单击您创建的启动按钮。你会注意到质子以螺旋路径运行,就像我们之前学过的一样!

质子的螺旋路径(图片由作者提供)

您甚至可以使用滑块试验不同的值,并创建不同半径和螺距的螺旋!要尝试模拟,点击这里

左图:大螺距大半径螺旋路径;右图:螺距和半径较小的螺旋路径(图片由作者提供)

结论

暂时就这样吧!VPython 的 3D 界面允许我们做各种很酷的实验和动画,并广泛用于物理模拟。VPython 有许多令人兴奋的应用,这只是其中之一。

接下来,你可以阅读更多关于如何使用 VPython(【https://www.glowscript.org/docs/VPythonDocs/graph.html】)绘制图表的内容,这对生成数据和观察实验趋势非常有用。

Python 中简单的抄袭检测

原文:https://towardsdatascience.com/simple-plagiarism-detection-in-python-2314ac3aee88?source=collection_archive---------7-----------------------

实践教程

使用语言模型(代码、解释和可视化)捕捉骗子

斯科特·格雷厄姆Unsplash 上拍照

作为一名教师,我理解那些努力向学生传授知识和有意义的反馈的教育工作者的沮丧,只是为了一小部分作弊的人通过假冒抄袭的作品作为自己的作品来规避制度。多亏了互联网,现在作弊比以往任何时候都更容易,也更有诱惑力。对老师来说幸运的是,有自动检测作弊的方法。当然,有些服务是收费的,但我想用 Python 创建一个剽窃检测系统,看看这些系统是如何工作的。如果你已经熟悉语言模型是如何工作的,请随意跳到最后的代码和可视化。

语言建模

语言模型是一种统计模型,它捕获了在其上进行训练的语料库的相关语言特征。在基本水*上,它应该捕获字母和单词的频率分布。一个更高级的语言模型应该捕获句法和语法依赖性,例如一致性和变形,以及语义属性,例如哪些单词可能出现在给定的上下文中。语言模型通常用于两个主要任务:评分生成。在评分中,语言模型对在给定上下文中出现的某个单词给出概率分数。给定上下文machine learning is ____,它应该有希望给完成fun比给完成octopus更高的分数,假设它是在英语文本的代表性样本上训练的。在生成中,模型从学习到的分布中采样,以生成虚假但听起来似乎可信的文本。克劳德·香农在他 1948 年的开创性论文中讨论了语言模型,给一系列单词分配概率的能力是信息论的一大成就。

要将语言建模应用于剽窃检测,您可以在一堆您认为人们可能会抄袭的文本上训练一个语言模型。假设你目前正在化学课上讲授金箔实验。你可以取几篇相关的维基百科文章,谷歌搜索“金箔实验”的前 10 名结果,也许还有过去几年的学生提交的文章(如果你担心传下来的论文),然后把它们放在一个文本文件中。这个聚集的数据集将是我们的训练数据,我们使用它来建立语言模型,该模型捕获文本的统计特征。一旦我们有了这个语言模型,我们就可以通过语言模型运行学生作业来分配分数。较高的分数意味着工作从训练数据中更可预测,并代表抄袭的可能性较高。

在之前的文章中,我讨论了两种不同的语言建模方法——N-gram 模型和 RNNs。在那篇文章中,目标是生成某种样式的假文本。其中一种方法,N-gram 模型,被证明是一种简单而有效的剽窃检测方法。

n 元语言模型

N-gram 语言模型基于前一个上下文窗口对单词评分。虽然 N-gram 模型不是非常复杂,并且无法处理长期依赖和抽象语义信息,但我们实际上可以将这视为这项任务的一个功能,而不是一个错误。其他语言模型,如基于递归神经网络或转换器的语言模型,更擅长捕捉长期依赖和更高层次的抽象。然而,对于剽窃来说,重点是复制的单词序列,而不是抽象层面的相似性。转述不应该引起警觉,但直接复制应该引起警觉。我发现 4 的 N-gram 窗口工作得很好,它也符合许多老师的建议,即不要在一个来源中连续使用三个以上的单词。

为了用 Python 实现 N 元语言模型,我们可以使用 NLTK 库(众多选项中的一个)。训练语言模型的基本步骤如下:

  • 读入并预处理培训数据文件(例如,删除标点符号、大小写和格式)。我们会剩下类似this is an example sentence的东西
  • 将训练数据标记化(即分成单个单词)并在开头添加填充。这将留给我们['<s>', '<s>', 'this', 'is', 'an', 'example', 'sentence']
  • 使用nltk.ngramsnltk.everygrams方法从训练数据中生成 N-gram。对于大小为 3 的 N-gram,这将给我们类似于[('<s>', '<s>', 'this'), ('<s>', 'this', 'is'), ('this', 'is', 'an'), ('is', 'an', 'example'), ('an', 'example', 'sentence')]的东西。注意,除了三元模型,每个二元模型还会给我们一元模型和二元模型。
  • 用这些 N-gram 拟合一个模型。NLTK 有各种模型可以使用,从基本的 MLE(最大似然估计器)到更高级的模型,如使用插值来处理看不见的 N-gram 的WittenBellInterpolated

一旦我们有了训练好的模型,它就支持各种操作,比如给定上下文给一个单词打分,或者从学习到的概率分布中生成一个单词。现在是时候评价一些“学生作业”了。

  • 在预处理中读入测试数据(“学生作业”)。
  • 将测试数据符号化。
  • 对于文本中的每个单词,调用该单词上的model.score(),将前面的N-1单词作为上下文参数。

这给了我们一个 0 到 1 之间的分数列表,每个单词一个,分数越大代表给定单词被剽窃的可能性越高。

形象化

如果我们能一目了然地看到一篇文章是否以及有多少是抄袭的,这不是很好吗?为此,我们可以将学生提交的内容表示为热图图像,其中每个像素对应一个单词的分数。这让我们可以快速判断是否有抄袭的可能,以及文本的哪些部分最有可能被抄袭。以这种方式可视化信息比查看一组数字分数或所有分数的汇总统计更有用。

我尝试了各种可视化这些数据的方法,我想到了下面的方法:

  • 每行显示 K 个字(我用的是 K=8)。这是以像素为单位的热图宽度。然后计算高度(测试数据字数除以 K )。
  • 由于数据集的规模较小和插值的挑战,分配的分数存在一些不确定性,所以我对分数应用了高斯*滑。
  • 将分数数组整形为一个由 K 列和行组成的矩形。这需要添加零填充以确保数组大小正确。
  • 使用 Plotly 热图显示使用您选择的色阶的图像。
  • 将文本的 K 个单词显示为热图相应行旁边的 y 轴刻度标签,以便于并排比较。调整悬停数据,使每个像素在悬停时显示其对应的单词。

为了测试这种方法,我在盖格尔-马斯登实验(也称为金箔实验)的维基百科文章上训练了抄袭检测模型。对于“学生作品”,我比较了两个提交的作品,一个是从维基百科复制的,略有改动,另一个来自完全不同的来源,谈论相同的主题。

非抄袭的例子,其中的文本不是来自维基百科的文章。注意对应卢瑟福名言的黑色区域,这句话也出现在维基百科的文章中。如果你看到这样的东西,你可以检查一下,以确保它被正确引用,否则它可能是剽窃的证据。图片作者。

抄袭的例子,其中的文本取自维基百科,并不时替换一些单词。较浅颜色的像素对应于被修改的单词。这种方法更容易辨别出文章的哪些部分是抄袭的。图片作者。

代码

这是我用来训练、评估和可视化剽窃检测的完整代码。

结论

这是一个简单的剽窃检测实现。当然,还可以添加许多其他功能,例如处理引用、自动收集训练数据、比较不同学生提交的内容,或者对其进行调整以适用于剽窃的代码而不是文本。然而,该计划阐明了语言模型背后的一些关键思想和信息论对现实世界问题的适用性。如果你喜欢这个,你可能会喜欢我关于信息论的文章:

参考

[1]克劳德·香农。1948.《交流的数学理论》。http://people . math . Harvard . edu/~ CTM/home/text/others/Shannon/entropy/entropy . pdf

[2]自然语言工具包。【https://www.nltk.org/

[3]维基百科。“盖革-马斯登实验”。https://en . Wikipedia . org/wiki/Geiger % E2 % 80% 93 marsden _ experiment

[4]大英百科全书。“卢瑟福模型”。https://www.britannica.com/science/Rutherford-model

简单的情节教程

原文:https://towardsdatascience.com/simple-plotly-tutorials-868bd0890b8b?source=collection_archive---------9-----------------------

第 1 部分:创建漂亮的动画地图

作者图片

动画地图是可视化和交流具有地理属性的数据的有效方式。在本教程中,您将学习如何在 Python 中部署 Plotly Express 包,以快速制作具有交互式功能的精美地图。

Plotly 是数据科学家可用的增长最快的可视化库之一,证明了它的易用性和它可以生成的漂亮的图形。这是展示日益复杂的 Plotly 功能的 3 个系列教程中的第一个。本期将向您展示如何使用 Plotly Express 快速制作动画地图。随后的教程将依次关注进一步定制 Plotly 图形,并在 Dash 应用程序中可视化它们。

温哥华犯罪数据集

在本教程中,我们将使用 Kaggle 数据集,它提供了加拿大温哥华市不同类型犯罪的数据。

在开始编码之前,您需要在 Python 中安装以下包。只需在您的终端或 Jupyter 笔记本中运行以下 pip 安装程序:

  • pip 安装计划
  • pip 安装 geopandas

让我们加载所需的包和数据集。我们可以在读取 CSV 文件时使用 parse_dates 参数创建一个Date列。在这里,我选择使用MONTHYEAR列来创建Date列,但是如果您愿意,也可以包含HOURMINUTE列。

温哥华犯罪数据集的前 5 行。作者图片

在开始分析之前绘制数据是一个很好的做法,以便发现任何不寻常的情况。当查看LatitudeLongitude特征的分布时,我注意到几个 0 值扰乱了数据的绘制方式——点显示在世界的另一端,使得无法在温哥华可视化数据!

为了本教程的目的,让我们去掉它们,使用一个 2000 行的样本。

绘制温哥华地图

1.散点图

“静态”视图

在我用 Plotly 这样的库做任何“花哨”的工作之前,我总是喜欢看我的地图的简单版本,以便对事物应该是什么样子有一种感觉。通常,这涉及到查找 shapefile 或 geojson,温哥华市的开放数据门户[就有这些工具。](# https://opendata.vancouver.ca/explore/dataset/local-area-boundary/export/?location=6,47.9237,-119.82788)因为我们将需要 geojson 文件来绘制 choropleth 多边形,所以让我们下载它。我们加载带有 Geopandas 库的 geojson,并在其上绘制数据集中的所有事件。

温哥华犯罪类型的分布。作者图片

这看起来很不错,但地图看起来很拥挤,很难获得洞察力。让我们来看看如何使用 Plotly Express 向我们的观众展示犯罪如何随着时间的推移而演变。

“动态”视图

map box 是一种在地图上显示散点数据的服务。因为这是第三方服务,所以您需要为自己生成一个访问令牌,以便显示他们的地图。这可以通过遵循此处的说明轻松完成。你需要做的就是用 Mapbox 创建一个帐户,然后你就可以访问你的令牌了——整个过程是免费的。一旦有了令牌,只需用自己的替换下面代码块中的“your_token”字符串。

px.set_mapbox_access_token("your_token")

您现在可以开始了!

通过将特征设置为animation_frame,可以快速实现具有 Plotly Express 功能的动画,它将使用特征的值来子集化和显示您的数据。例如,将time_col设置为“年”将允许您可视化数据集中所有年份的犯罪,“月”表示所有月份,依此类推。

我们可以通过设置一个“color”参数来指定散点图的颜色,与海运的“hue”参数的工作方式相同。默认情况下,传递给“animate_frame”参数(它决定了地图动画的顺序)的值是不排序的,所以我们添加了一个“category_orders”参数:一个包含要迭代的值的排序列表。

瞧啊。我们有一个很好的互动地图。如果您想显示数据在几个月(或几个小时等)内的变化。)相反,只需更改上面函数中的time_col参数。

温哥华犯罪数据的动画散点图。作者 Gif

注意事项:

  • 因为 Plotly 散点图依赖于 Mapbox 服务,使用它们的一个很好的优势是,它们会根据您提供的坐标自动显示地图——无需提供地理文件!但是,在显示 choropleth 地图时,您需要提供一个 geojson 文件,如下一节所示。
  • 如 gif 所示,你可以点击Type变量中的类别来过滤图上显示的数据点!这提供了很好的初始互动性,可以帮助你引导你如何传达你的见解。

2。Choropleth 地图

“静态”视图

绘制犯罪数据的另一个很好的方法是使用 choropleth 地图可视化每个街区的事件数量,然后显示这些数字如何随时间演变。当显示 choropleth 地图时,我们根据想要可视化的基础值给多边形(每个多边形对应一个邻域)着色。在下面的示例中,我们将根据每个面内发生的犯罪事件的数量对其进行着色,较深的着色代表较高的犯罪事件数量,较浅的着色代表较低的犯罪数量。

在我们绘制任何东西之前,数据集需要一些额外的操作。首先,我注意到 geojson 和 crime 数据之间的一些命名差异,所以我重命名了一些街区,以确保它们的名称一致。我还删除了斯坦利公园附*的观测数据,不幸的是,geojson 文件中没有这些数据。

我们现在可以绘制重新格式化的数据。

温哥华社区累积犯罪事件的 Choropleth 地图。作者图片

正如我们所见,温哥华的每个街区都由一个多边形表示,其颜色强度与街区内发生的犯罪事件数量成正比。城市北部的街区往往比南部的街区有更高的犯罪率,CBD(中央商务区)街区在整个样本中的犯罪率最高,白色阴影区的街区犯罪率最低。

“动态”视图

让我们制作上图的动画。对于每个时间戳,我们希望可视化温哥华不同社区中累积事件的分布。

在处理最终的数据帧之前,我们需要完成几个额外的步骤,该数据帧将包含数据中每个时间戳每个邻域所有事件的累积总和。

滚动计数数据帧的前 5 行。作者图片

现在这里有一个稍微棘手的部分。如果您查看我们刚刚生成的counts_rolling数据帧,您会注意到并非所有的邻域都有每个时间戳的值。这是因为某些街区在特定日期没有任何犯罪记录,因此我们需要使用向前填充来填充那些“缺失”的值。

最终犯罪累计金额数据框架预览。作者图片

现在,我们有了一个完整的数据帧,其中包含每个时间戳/邻域组合的值。我们终于可以绘制图表了!

为了使用 Plotly 的 choropleth_mapbox 函数,我们必须确保包含犯罪数量的数据帧和用于绘制地图的 geojson 具有相同的标识符,以便映射函数可以正确地将每个面与其犯罪数量相关联。这里,我利用featureidkey参数告诉映射函数多边形标识符位于 geojson 文件的“properties.name”位置。这些标识符与犯罪数据帧中包含的邻居名称相同。

温哥华犯罪统计动画地图。作者 Gif

后续步骤

正如我们刚刚看到的,用 Plotly 制作动画图形是一件轻松快捷的事情。在接下来的教程中,我将展示如何进一步定制 Plotly Express 图形。例如,我们可能希望选择一个特定的年份,并可视化犯罪在这一年的几个月中的演变。或者,我们可能希望有一个选项来按犯罪类型过滤数据,并可视化其随时间的演变。幸运的是,Plotly 使我们可以轻松地在 Plotly Express 图形的基础上构建,一步一步地添加定制层。在后面的教程中,我们将会看到如何将所有的东西包装成一个漂亮的 Dash 应用程序!

我想对我在数据科学和人工智能精英团队的同事们大声欢呼,感谢他们激励我写这篇博文。特别感谢 Andre ViolanteRakshith Dasenahalli linga raju的意见和建议,以及 Robert Uleman极其彻底的校对和代码改进!

人工智能伦理中做出正确决定的简单提示

原文:https://towardsdatascience.com/simple-prompts-to-make-the-right-decisions-in-ai-ethics-e0475bda8f41?source=collection_archive---------48-----------------------

变更数据

Paul Skorupskas 在 Unsplash 上拍摄的照片

随着最*结束的 FAccT 2021 会议,我们享受到了许多论文和研讨会,这些论文和研讨会讨论了统计技术、交叉讨论、跨学科想法以及将负责任的人工智能付诸实践的许多不同尝试。Twitter 上有许多有趣的讨论,有助于从会谈、小组讨论和演示中挖掘出更多的见解,这无疑帮助我提升了自己对人工智能伦理的理解,我鼓励每个人都去看看。

但是,在一切结束的时候,仍然有一些东西是缺少的。

我经常被这样一个问题困扰:“如果我们能让在人工智能伦理中做出正确的决定变得更容易,会怎么样?”

在与一些 HCI 专家和从业者交谈时,我提出了以下 3 步方法,我认为这将有助于我们解决上述问题提出的核心问题。我的目标是让做从人工智能伦理的角度来看是正确的事情成为默认和更容易的选择。

为什么

从组织的文化角度来看,使命应该清晰地表达出来,并融入员工的日常工作中。这不仅仅是将使命宣言写在海报或宣传材料上,而是员工在日常工作中可以在内心深处产生共鸣的东西。

拥有这些将为每个从事这项工作的人提供一个强有力的“为什么”,这将帮助他们(当然有正确的个人道德指南针)每次都选择正确的事情去做,而不必通过审计、审查、委员会和其他治理框架被迫这样做。

这是令人向往的,但希望这些机制成为我们很少需要依赖的东西,因为每个人都是一致的,并被激励去做正确的事情。

怎么做

从纯组织和运营的角度来看,我发现当有人努力将这些想法带给他们的同事,以消除摩擦的方式(嗯,至少尽可能地)时,这是很了不起的。

我经常提到微软的包容性设计实践,这使得包括可访问的设计元素(比如隐藏式字幕)变得非常容易,因为它们在所有员工的工作流程中以一种良好集成和可访问的方式呈现。从 HCI 的角度来看,这也需要深思熟虑的努力和理解,以使包含可访问性元素成为一种默认,从而提高它们的接受度。

您也可以开始考虑在员工的工作流程中使用简单的提示,例如在采购周期中(比如,在您的内部工具中列出供应商名单时),第三方数据会要求采购人员停下来,考虑他们是否已经与领域专家交谈过,以了解他们正在采购的数据的局限性。或者,考虑一个简单的提示,询问你的 UX 设计师在提交草稿时是否考虑了残疾人的需求。

简单的提示有巨大的力量,以一种低摩擦的方式,将组织内的行为推向更道德的姿态。

什么

这涉及到实际的工具考虑。想想这些提示的位置,它们有多持久,它们有多突出,它们什么时候显示,它们显示的背景是什么,等等。,这是 HCI 从业者在开发这些提示时的常规考虑。

我的建议是从小处着手。如果您无法控制所使用的工具,并且无法改变核心功能,那么总会有创造性的方法来解决这个问题。想象一下,您可以构建一个 Slackbot,它在您的组织的设计频道中读取消息,并在读取“准备提交的草稿”或其他短语时,向团队成员发送消息,要求他们考虑他们是否已将残疾需求纳入他们的设计中。这些小步骤是一个很好的开始方式,然后随着时间的推移在整个组织中规范实践。

我们一直不知道什么是正确的事情…

我同意!这一点并不总是为人所知,但是如果我们坚持上面的三个步骤,我们就能到达一个地方,在那里我们有能力走出去寻找正确的事情而不会受到影响。希望有一种足够热情和友好的文化,能够包容相互矛盾的思想和观点,通过仔细的思考,共同帮助达成正确的事情。

如果你已经尝试过类似的东西,并且有什么样的结果,我很乐意在评论区听到你关于如何应用它的想法。

在这里注册以获得关于可操作人工智能伦理书的更新!你可以在这里了解更多关于我的作品

你可以通过订阅人工智能伦理简报蒙特利尔人工智能伦理研究所了解更多这样的见解!

让您成为更高效的数据科学家的简单解决方案

原文:https://towardsdatascience.com/simple-solutions-to-make-you-a-more-productive-data-scientist-9e9ad3bd0bd9?source=collection_archive---------31-----------------------

或者更有成效的事情

丹·巴瑞特在 Unsplash 上拍摄的照片

没有比新年更好的时机来解决数据科学家面临的最大问题之一:生产力。

数据科学家有很多工作要做,要求很高的工作描述和不断自我教育的需求。难怪数据科学家会感到筋疲力尽。但是,有一种方法可以看到数据末尾的亮光(或者如果您愿意,也可以是隧道)。

通过实施一些生产力解决方案和工具,数据科学家可以努力缓解似乎永远不会停止的工作压力。你可能以前见过一些这样的建议,但是有时候提醒你所拥有的一切来帮助你变得更有效率并没有坏处。为什么不在新的一年里尝试一下,看看什么对你有用?

如何提高工作效率?

自动化繁琐的任务。

数据科学家花费高达 70%的时间在低级任务上,比如收集、清理和组织数据。

当你想到 80/20 法则时,你会发现 80%的成果来自于 20%的努力,在低级任务上花费这么多时间似乎并不那么有效。再者,不是曾经有一句名言建议你应该聪明地工作而不是努力工作吗?

收集、清理和组织数据所涉及的许多过程都是极其重复的,并且没有很好地利用您的时间。因此,与其把时间浪费在常规任务上,不如让代码为你工作,把单调的东西自动化。

查看这些关于自动化数据科学任务的文章,开始您的工作:

如果你在远程工作,利用你最有效率的时候安排你的工作日。

根据你工作的公司,这可能是一个不可能的解决方案。然而,如果你是在一家更自由流动的公司工作,或者你自己是一名自由职业者,为什么不把你的工作时间安排在你效率最高的时候呢?

随着疫情结束后在家工作运动的兴起,许多数据科学家将被允许在他们想去的任何地方工作。不仅如此,随着凌晨 3 点给同事发邮件变得可以接受,工作时间也变得更加灵活。

所以,如果你在早上效率最高,那就把你的工作日安排在早上。或者,如果你是一个夜猫子,晚上工作到很晚。你可能会惊讶于你的生产力、总体幸福感和生活满意度是如何同步提高的。

使用适合您的 IDE,而不是大多数人所说的让您“更有效率”的 IDE。

仅仅因为一个 IDE 使一个数据科学家更有效率,并不意味着它会使你更有效率。

首先,当选择一个 IDE 时,选择一个你最熟悉的。如果你不停地摆弄那些你不熟悉的小插件或功能,你就不会有成效。

幸运的是,如果你还没有选择你的唯一,你有几个 ide 可以选择。Spyder、Pycharm IDE、Jupyter Notebooks、R Studio 和 Visual Studio Code 只是可供选择的几个 IDE。

从个人经验来看,Visual Studio Code 和 Jupyter 笔记本是我最喜欢使用的 ide,因为它们的布局简洁,易于使用的生产力增强插件,以及对我的计算机大小的要求不高。

拍摄你自己的工作。

我知道这是个奇怪的建议。但是听我说完。

看着人们工作或编码的时间流逝,有种奇怪的满足感。只要在 Youtube 上看一看,你就会发现数以千计的人们正是这样做的视频。

你不仅在一天结束时得到了一个很酷的视频,而且在拍摄期间你也变得有动力去工作。此外,你还可以看到你大部分时间都花在哪里了。如果您发现您花了四分之三的时间编写特性代码,但是认为花更多的时间来选择和调整您的模型会更好,那么您可以在将来进行调整以提高您的生产率。

让任务批处理为你工作。

数据科学是那些期望你完美地完成许多不同任务的学科之一。然而,很难从一项任务跳到另一项任务,因为每项任务都需要完全不同的技能或工作类型。这也适用于在不同的项目中工作时必须进行的思维转变。

这个问题的解决方案是让任务批处理为你工作。任务批处理是一个生产力主题,你可以留出时间来处理相同类型的任务,并且只处理那些类型的任务。

例如,如果您使用任务批处理来计划您的工作日,您的日程可能如下所示:

  • 上午 8 点到 9 点——查看电子邮件。
  • 上午 9:00-11:30—项目 x 的数据清理
  • 上午 11:30-下午 12:30—午餐
  • 下午 12:30-2:30—关于项目 x 的会议
  • 下午 2:30-5:00-对项目 x 的数据进行初步分析并开发模型。

这些任务不仅按类型分批,还按重点分批。例如,你可能在一个给定的时间从事多个项目。对于一些人来说,一整天从一个项目切换到另一个项目是很困难的。为了让自己轻松一点(如果这对你的工作环境/流程有用的话),试着把你的一整天都集中在一个给定的项目上,以避免不得不在一天的中途把你的思维转移到一个不同的项目上。从那里,你可以将特定于项目的任务进行批处理,这样你就可以将所有的注意力集中在完成一个给定的任务上,而不是试图同时处理多项任务而什么也没完成。

使用像 Trello 这样的生产力工具来跟踪你的项目进度。

当我在做我的顶点项目时,像 Trello 这样的生产力工具是我的救命稻草。它不仅允许多个团队成员更新他们的进度,而且给你一个简单的方法来可视化你的团队在过程中的位置。

简单的生产力工具可以让你追踪你的项目进度,但在创造生产力环境方面却没有得到应有的认可。无论你首选的跟踪进度的方法是白板、日志还是生产力工具,跟踪你的进度都是一个确保按时完成和减少压力的方法。

根据您的风格和项目需求,您可能需要升级您的生产力工具。以下是一些我最喜欢的和其他经过验证的跟踪生产力的方法,你可以在下一个项目中实施:

如何通过自我教育提高工作效率?

自我教育是那些必要的罪恶之一,它会让你感到筋疲力尽,没有动力去做你真正有报酬的工作。随着数据科学作为一门学科不断发展,自我教育是雇主期望你做的工作合同中未言明的部分之一。问题是,工作日结束后,几乎没有精力去做个人项目或完成一堂新技术课。为了提高你的自学效率,充分利用你的学习时间,甚至给你自己一些额外的时间,试试这些提高效率的技巧和解决方案。

创建个性化的学习课程来学习一项新技能或技术。

虽然许多概念可以通过一个 Youtube 视频学习,但其他概念需要更多的努力。例如,如果你的工作需要你学习如何创建一个特定的机器学习模型,那么很难在一个视频中学习你需要的一切。这可能需要一些更深入的东西,比如学习课程。

创建自己的个性化学习课程不仅是在自学过程中保持积极性的好方法,也是学习困难概念的理想方法,而不必为在线课程支付过高的费用。

对于这个例子,首先列出你需要知道的所有概念来建立一个机器学习模型。然后,添加任何额外的概念,这些概念可能更具体地针对您需要为工作创建的机器学习模型的确切类型。从那里,你可以在网上搜索免费课程、原始文档、博客文章和视频教程,这些都可以满足你需要学习的每一个概念。我最喜欢的一些在线学习内容来源是 freeCodeCamp、Coursera、Udacity、edX、Youtube 和媒体上的 TowardsDataScience 出版物。

在你投入时间对课程进行个性化设置后,你不仅会更倾向于将课程进行到底,而且课程已经为你安排好了,每天只需要少量时间,你就可以深刻理解如何创建一个可以在工作中实施的机器学习模型。

将学习概念分成小块,这样可以在一个小时内学会。

不是每个人每天都有八个小时来钻研学习一个新概念或新技术。很少有人有一个小时可以用来学习。正因为如此,如果你觉得你需要学习一些新的东西,但是没有时间去学,你的工作效率会受到影响。

相反,把学习看作是在更短的时间内完成的事情。每个人都有二三十分钟可以用来学习。通过把学习分成更小的部分,你会更容易养成一个只占用你一天一小部分时间的学习习惯。

此外,想到要学习一个完整的概念可能会令人生畏,但是当它被分解成只需要很少时间就能完成的逻辑片段时,这个任务看起来就容易管理得多了。

通过打破你的学习观念,你不仅会养成一个容易保持的习惯,而且你会惊讶于每天花几分钟时间学习会有多快。

在努力学习的时候,把工作的想法抛在脑后。

当你试图学习一个新概念时,工作是你能想到的最分散注意力的事情之一。

在担心你是否完成了你需要做的一切,或者你是否正在进行你老板信任你的大项目,或者你发给同事的电子邮件是否有点冒犯,因为你太晚意识到一个笑话可能不是正确的,或者如果办公室的流言是真的,那么太多本可以更好地用于学习的时间将被浪费,因为你的思想正徘徊在你实际上被支付工资要做的事情上。

当你坐在一个无聊的微积分讲座前时,你的思维会自动导航,走神,这是很自然的。

因此,为了在学习的同时提高效率,你需要关掉所有其他的东西,只专注于学习。

这可能意味着早上五点醒来,只是为了了解世界是寂静的,你的工作日还没有开始。或者,这可能意味着在学会放慢你的思维,让你更加集中注意力,专注于手头的任务之前,先进行冥想。或者你可以戴上那些大的降噪耳机来消除任何干扰。

不管是什么诀窍,确保它让你专注于学习,而不是让你每五分钟检查一次邮件。当你把注意力集中在眼前的事情上时,你会惊讶地发现你能学到多少东西。

意识到你什么时候会筋疲力尽。

有时候,生活可以很多。在工作、家庭、个人需求和你已经做出的其他承诺之间,有一个优先事项会把你推到边缘。

使用一些过度使用但高度相关的类比:你的盘子只能有这么满,你只能从一个满杯子倒酒。

换句话说,如果一想到要再上一堂新技术课,你就想辞掉工作,卖掉一切,搬到远离电网的荒野中的一个偏僻小屋,在那里你未来四十年都不会接触技术,那么你需要停下来。当你的大脑明显需要休息时,停止强迫自己学习新的东西。

作为一名数据科学家,在精神上已经够累的了,有时候,在一天工作八小时处理数据、清理数据和调试代码之后,你的大脑需要休息一下。

偶尔听听自己的大脑,让自己从学习中解脱出来。除非你的老板是机器人,否则他们可能也经历过同样的事情。技术领域的每个人都曾在某个时候遇到过。给自己足够的时间远离学习,这样你就能兴奋地再次学习。它会回来的,相信我。当学习的激情回来时,你会比以前更有效率。

最后的想法。

随着数据科学家头衔带来的一切,人们很容易感到不知所措。然而,如果有一件事可以提高效率,那就是让自己变得有效率。这听起来似乎是显而易见的,但更多的时候,生活发生了,你的生产力解决方案飞出窗外,以补偿任何突如其来的事情。

虽然你可能已经知道我在这篇文章中提到的解决方案,但温和地提醒一下其他可能进一步刺激你的生产力的解决方案也无妨。因为归根结底,数据科学家需要尽可能多的生产力。

用 Python 创建自定义色彩映射表的简单步骤

原文:https://towardsdatascience.com/simple-steps-to-create-custom-colormaps-in-python-f21482778aa2?source=collection_archive---------5-----------------------

随心所欲地创造任何色彩

Pawel Czerwinski 在 Unsplash 上的照片

假设您发现了一个其他人在出版物中使用的漂亮的色彩映射表,并且您也想在您的结果中使用它。然而,遗憾的是,它并不是 matplotlib 中内置的 colormap。周围有解决的办法吗?

所以今天我将向你展示我通常是如何通过创建基于任何图像的自定义色彩映射表来解决这个问题的。

包装器函数的 Github 存储库可以在:https://Github . com/frank ligy/sc triangulate/blob/main/image/colors _ module/readme . MD找到

我在这张细胞纸中遇到了一个好看的色彩图,在他们的图 4,面板 K 中,有一个彩虹般的色彩图,它显示了很大的对比度,在视觉上也很有吸引力。我们需要做的第一步是截取这个色图的截图,如下所示:

我们想要创建的示例色彩映射表(图片由作者提供)

正如你所看到的,它似乎有 5 个不同的颜色补丁,每个补丁内也有一个梯度。为了用 python 再现这个色彩映射表,我们首先需要知道一些锚点的颜色,我们提供的锚点越多,我们的色彩映射表看起来就越接*原始色彩映射表。为了提取锚点的颜色,我们使用了免费的 web 应用程序 adobe 颜色渐变

上传截图后,我们提取了 6 个锚点的 RGB 值(图片由作者提供)

该应用程序要求我们上传截图,然后您可以提取任意数量锚点的 RGB 颜色(用 0-255 之间的值表示)。这里我们选择 6,因为我们假设有 5 个不同的颜色补丁。

我在红框中突出显示的 RGB 值将帮助我们在接下来的步骤中创建自定义色彩映射表。

乍一看,在 matplotlib 中构建自定义色彩映射表的逻辑有点混乱,它要求我们首先创建一个包含redgreenblue通道动态变化规范的cdict字典。用一个更简单的例子来解释语法:

理解 cdict 的语法(图片由作者提供)

和上面的例子一样,我们指导程序如何在从 0 到 1 的连续统上线性插值 R、G 和 B 通道。关键的概念是选择断点,在断点处我们表达颜色通道的强度。另一个令人困惑的地方是我们需要输入两个值,一个是断点左边的强度,另一个是右边的强度。在一个简单的情况下,比如我刚才展示的例子,对左右两边使用相同的亮度是完全没问题的。对于更详细的操作,我们可以让他们不同的理想效果。记住这一点,我们终于可以开始我们的旅程了!

第一步是安装和加载必要的软件包:

from matplotlib import colors
import numpy as np
import os
import matplotlib.pyplot as plt
from matplotlib import cm

我们首先构建如上所示的cdict,这里我们定义一个函数inter_from_256() 来将 Adobe 输出值(0–255)转换为 range (0,1)。

def inter_from_256(x):
    return np.interp(x=x,xp=[0,255],fp=[0,1])

现在可以实例化自定义色彩映射表对象了:

new_cmap = colors.LinearSegmentedColormap('new_cmap',segmentdata=cdict)

我们可以通过使用自定义颜色图生成颜色条来测试它:

fig,ax = plt.subplots()
fig.colorbar(cm.ScalarMappable(norm=colors.Normalize(),cmap=new_cmap),ax=ax)

我们的自定义彩色地图(图片由作者提供)

全程一行代码?

当我几个月前第一次遇到这个问题时,我发现为新的色彩映射表重复这个过程几次是很痛苦的。所以我开始在我开发的一个名为 scTriangulate 的 python 包中编写一个名为“colors”的模块。让我们使用颜色模块中非常方便的函数build_custom_continuous_cmap将整个过程简化为一行代码:

如您所见,我们只需将 adobe web 应用程序中的所有 RGB 值传递给该函数,不再需要担心底层流程。

现在我们再测试一次:

fig,ax = plt.subplots()
fig.colorbar(cm.ScalarMappable(norm=colors.Normalize(),cmap=new_cmap),ax=ax)

可以得到同样的结果(图片由作者提供)

结论

结束了,我希望这个简短的教程对你的情况有所帮助。此外,我想向您推荐 scTriangulate.colors 模块,以获得更方便的 python 可视化功能。我写这篇教程的部分原因也是为了获得您的宝贵反馈,了解您希望在 python 中简化哪些繁琐的绘图过程?如果您有任何功能要求,请让我知道,以便我可以实现它们并将其添加到 scTriangulate.colors 模块中,以使其他用户受益。

差不多就是这样!我希望你觉得这篇文章有趣和有用,感谢阅读!如果你喜欢这篇文章,请在 medium 上关注我,非常感谢你的支持。在我的 TwitterLinkedIn 上联系我,也请让我知道你是否有任何问题或你希望在未来看到什么样的教程!

简单奇异值分解算法

原文:https://towardsdatascience.com/simple-svd-algorithms-13291ad2eef2?source=collection_archive---------3-----------------------

计算奇异值分解的简单方法

来源

介绍

这篇文章的目的是展示一些简单而有教育意义的例子,如何使用简单的方法计算奇异值分解。如果你对行业力量的实现感兴趣,你可能会发现这个很有用。

德拉贡诺夫狙击步枪(Snayperskaya Vinyovka Dragunov 的缩写)

奇异值分解(SVD)是一种矩阵分解方法,将方阵(n×n)的特征分解推广到任意矩阵(n×m)(来源)。

如果你不知道什么是特征分解或者特征向量/特征值,你可以谷歌一下或者看看这篇帖子。这篇文章假设你熟悉这些概念。

SVD 类似于主成分分析(PCA),但更一般。PCA 假设输入方阵,SVD 没有这个假设。奇异值分解的一般公式是:

m=uσvᵗ,其中:

  • M 是我们想要分解的原始矩阵
  • U-是左奇异矩阵(列是左奇异向量)。 U 列包含矩阵的特征向量 MM
  • σ-是包含奇异(本征)值的对角矩阵
  • V-是右奇异矩阵(列是右奇异向量)。 V 列包含矩阵的特征向量 MM

奇异值分解矩阵(来源)

奇异值分解比主成分分析更通用。从上图中我们看到,SVD 可以处理不同列数和行数的矩阵。奇异值分解类似于主成分分析。PCA 公式为m=𝑄𝚲𝑄ᵗ,将矩阵分解为正交矩阵 𝑄 和对角矩阵𝚲.简单地说,这可以解释为:

  • 将基准从标准基准变更为基准 𝑄 (使用 𝑄 ᵗ)
  • 应用变换矩阵𝚲,它改变长度而不是方向,因为这是对角矩阵
  • 将基准从基准 𝑄 变更为标准基准(使用 𝑄

SVD 做类似的事情,但是它没有回到我们开始转换的基础上。它不能这样做,因为我们的原始矩阵 M 不是方阵。下图显示了与奇异值分解相关的基的变化和变换。

奇异值分解变换和基变换。(来源)

从图中我们可以看到,SVD 执行以下步骤:

  • 将基准从标准基准变更为基准 V (使用 V ᵗ).请注意,在图表中,这显示为简单旋转
  • 应用矩阵σ描述的变换。这在基础 V 上缩放了我们的向量
  • 基从 V 变为基 U. 因为我们的原始矩阵 M 不是正方形的,所以矩阵 U 不能具有与 V 相同的维数,并且我们不能返回到我们的原始标准基(参见图片“SVD 矩阵”)

SVD 有许多变体和计算 SVD 的方法。我将展示一些计算它的方法。

计算奇异值分解的方法

如果你想尝试自己编写例子,可以使用这本笔记本,里面有这篇文章中用到的所有例子。

幂迭代

幂迭代从可能是随机向量的 b ₀开始。在每次迭代中,使用以下规则更新该向量:

来源

首先我们用原始矩阵 A ( Abₖ )乘以 b ₀,然后用范数除结果(|| Abₖ ||)。我们将继续,直到结果收敛(更新少于阈值)。

幂法有几个假设:

  • b初始化 b ₀随机最小化这个假设不成立的可能性
  • 矩阵 A 具有主特征值,该主特征值的幅值严格大于其他特征值的幅值(来源)。

这些假设保证了算法收敛到合理的结果。主特征值和第二特征值之间的差异越小,收敛所需的时间可能越长。

非常简单的幂法例子可以在这里找到。我做了一个例子,也能找到特征值。如你所见,这个函数的核心是幂迭代。

举个简单的例子,我们使用啤酒数据集(可以从这里的获得)。我们将构建协方差矩阵,并尝试确定数据集的主要奇异值。数据处理的完整示例可在笔记本中找到。

#construct data 
df=pd.read_csv('data/beer_dataset.csv')
X = np.array([df['Temperatura Maxima (C)'],
              df['Consumo de cerveja (litros)']]).T
C = np.cov(X, rowvar=False)eigen_value, eigen_vec = svd_power_iteration(C)

我们可以用原始数据绘制主特征向量。

啤酒数据的主导主成分/特征向量

从图中可以看出,这种方法确实找到了主导奇异值/特征向量。看起来它正在工作。您可以使用 notebook 来查看结果,结果与numpy提供的 svd 实现的结果非常接*。接下来,我们将看到如何获得不仅仅是第一优势奇异值。

n 个奇异值的幂迭代

为了从矩阵中得到更多主要奇异值,我们仍然可以使用幂迭代。我们将实现一个新函数,它使用我们之前的svd_power_iteration函数。寻找第一主奇异值很容易。我们可以使用前面提到的函数。但是如何求第二奇异值呢?

我们应该从矩阵中移除主要方向,并重复寻找最主要的奇异值()。为此,我们可以从原始矩阵中减去先前的特征向量分量(使用我们已经计算过的奇异值和左右奇异向量):

下一站= A-(singular_value₁)(u₁)(v₁)ᵗ

下面是计算多个特征值/特征向量的示例代码(这里借用了这里是,做了小的修改)。

当我们应用到我们的啤酒数据集时,我们得到两个特征值和特征向量。

啤酒数据主成分/特征向量

注意,这个例子也适用于列多于行或者行多于列的矩阵。结果可与numpy svd 实现相媲美。这里有一个例子:

mat = np.array([[1,2,3],
                [4,5,6]])
u, s, v = np.linalg.svd(mat, full_matrices=False)
values, left_s, rigth_s = svd(mat)np.allclose(np.absolute(u), np.absolute(left_s))
#True
np.allclose(np.absolute(s), np.absolute(values))
#True
np.allclose(np.absolute(v), np.absolute(rigth_s))
#True

为了将我们的定制解决方案结果与numpy svd 实施进行比较,我们采用绝对值,因为矩阵中的符号可能相反。这意味着向量指向相反的方向,但仍然在同一直线上,因此仍然是特征向量。

既然我们已经找到了计算多个奇异值/奇异向量的方法,我们可能会问,我们能更有效地做吗?

幂法的块版本

这个版本也有名字,如同时幂迭代或正交迭代。这个版本背后的想法非常简单(来源):

  • 其他特征向量与主导向量正交
  • 我们可以用幂法,强迫第二个向量与第一个向量正交
  • 算法收敛到两个不同的特征向量
  • 对许多向量这样做,而不只是其中的两个

每一步,我们不只是将 A 乘以一个向量,而是乘以多个向量,我们将这些向量放入矩阵 q 中,在每一步,我们将使用 QR 分解来归一化这些向量。 QR 分解将矩阵分解成以下部分:

A=QR,其中

  • 我们要分解的原始矩阵
  • q 正交矩阵
  • r-上三角矩阵

如果算法收敛,那么 Q 将是特征向量和 R 个特征值。以下是示例代码:

从代码中我们可以看到,计算奇异向量和值只是代码的一小部分。大部分代码致力于处理不同形状的矩阵。

如果我们将这个函数应用于啤酒数据集,我们应该得到与之前方法相似的结果。

来自 svd _ 联立 _ 幂 _ 迭代的啤酒数据主成分/特征向量

与以前的版本相比,特征向量指向相反的方向,但是它们在同一条线上(有一些小误差),因此是相同的特征向量。在笔记本中,我举例比较了输出与numpy svd 实现。

结论

计算主奇异值和奇异向量可以从幂迭代法开始。该方法可以被调整用于计算 n-主导奇异值和向量。对于同时奇异值分解,我们可以使用幂迭代的块版本。这些方法不是最快最稳定的方法,但却是很好的学习资源。

参考

啤酒消费——圣保罗,卡格尔

特征值和特征向量,Risto Hinno

如何计算奇异值分解

幂迭代,ML Wiki

幂迭代,维基百科

QR 分解,维基百科

奇异值分解,维基百科

奇异值分解第二部分:定理、证明、算法,杰里米·昆

面向数据从业者的简单时间管理技巧

原文:https://towardsdatascience.com/simple-time-management-tips-for-data-practitioners-434c1dbbaa7f?source=collection_archive---------28-----------------------

获得更多关注并提高您的工作效率

Eduardo Olszewski 在 Unsplash 上的照片

你是否曾经因为有太多的任务需要完成而感到超负荷?你有没有因为满脑子都是它而感到不知所措?我知道。在现实世界的数据科学工作中,我们不得不面对如此多的特别报告或分析请求,这些报告或分析请求都是在已经计划好的报告或分析请求之外的(不规则性变成了规则性)。

作为数据科学家或数据分析师,您可能会面临以下一些情况:

  • 一系列会议
  • 多任务处理
  • 当你还在处理某个问题的时候,请求会不断的出现
  • 更多

严重的是,如果你不好好管理它们,它可能会产生负面影响。请注意,我使用 word " manage "因为这是现实世界数据科学工作的本质,我们无法消除它们(至少目前是这样)。每个组织也可能有不同的成熟度数据驱动的文化,这使得它更具挑战性。

简单提示

正如我所承诺的,我的建议非常简单,你可以马上尝试。

1.设定你今天想做的事情

为今天,为每一天设定一个简单的目标。简单地告诉自己今天你想完成什么。根据你认为自己的能力,可能只有 1-2 项任务或更多。

别忘了设置一些缓冲(剧透:期待意想不到的任务到来)

在我看来,完成一些任务的感觉是非常令人耳目一新和有收获的,而不是做了很多任务却什么也没完成。它可以让你的大脑在接下来的一天更加放松,因为“一件事做完了,还有四件事要做”。

2.早点开始

只是…早点开始…

是的,非常简单,但是我发现这个很难做到(或者至少需要时间)。通过尽早开始,你将避免那些来自你的利益相关者的请求,没有会议,只是没有什么会打扰你。

您可以利用这个机会(不限于):

  • 更多地了解交给你的任务
  • 更深入地了解您的数据和业务流程(这是提高您业务敏锐度的黄金活动)
  • 让自己做好准备(演示、会议等)
  • 甚至更多

此外,它还会提高你的注意力、意志力和减少拖延。可以看看这篇关于早工作的好文章。

https://medium.com/personal-growth-lab/the-key-to-better-focus-and-higher-productivity-work-early-in-the-morning-4-reasons-why-c6ab13f47ef3

3.一次专注于一项任务

如果可能的话。

随着时间的推移,当你完成了许多任务,你会对哪些任务能很快完成,哪些不能很快完成有更好的认识。您可以通过首先切换到这些类型的任务来减轻上下文切换的沉重负担。

通过完成比待办事项更多的任务,可以给你的大脑空间休息,清晰地思考解决你正在处理的问题。

4.划分你每天的时间段

这是我最喜欢的,划分你一天的时间段。这是什么意思?

你可以清楚地划分出你想在哪些时间段内完成一些常规任务,例如:

8–9:探索数据

9–11:协作、会议、回答聊天

11-12:忙碌时间(屏蔽任何东西,不回复聊天和邮件,避免开会)

12–13:休息

13-15:又是忙碌的时候了

15–17:协作、会议、再次回复聊天

一天的剩余时间:探索数据、结果,并回顾你今天做了什么

这可能是非常个人化的,在每种工作环境中每个人都不一样,但我希望你能明白。要记住的一件主要事情是努力保持一致。当你在一个确定的时间段内,例如,与他人合作,不要让你的大脑并行处理你的任务(反之亦然)。

此外,一定要与你的队友和利益相关者交流你的时间段,这一点非常重要,因为你不想让他们因为你忽略了他们的聊天而生气,对吗?😀

结束语

这些技巧基于我作为数据从业者在日常活动中管理时间的经验。我发现它们很有帮助,让我获得了更多的注意力、更高的效率和更广泛的知识来解决更多的问题。

最后一点,由于每个组织工作环境的多样性,这些建议可能并不适用于所有人,但我希望其中一些会有所帮助。至少,先试一试👌。

一如既往,快乐学习!!!🚀🚀

在 Python 中使用相对路径的简单技巧

原文:https://towardsdatascience.com/simple-trick-to-work-with-relative-paths-in-python-c072cdc9acb9?source=collection_archive---------0-----------------------

轻松计算运行时的文件路径

让我们计算目标文件的路径(图片由 Tobias RademacherUnsplash 上提供)

这篇文章的目标是计算一个文件在你的项目的文件夹中的路径。我们计算这个路径的原因是,无论代码安装在哪里,您都可以引用正确的位置。当你与同事分享你的代码或者在网络服务器上部署你的代码时,就是这种情况

您不能硬编码文件的(预期)位置,因为在您的机器或我们要部署到的服务器上不存在C:/users/mike/myproject/config/.env。理想情况下,我们希望指定相对于项目根文件夹的路径

在本文中,我们将检验一个简单的 Python 技巧,它允许我们以一种非常简单的方式引用与项目文件夹相关的文件。我们来编码吧!

TL/DR;查看下面的“诀窍”!

用例

两个简单例子可以说明这个技巧的用处:

  • /config/.env加载环境文件
  • 我们有一个接收文件的 API 例如,文件应该总是保存在data/received_audio_files

准备

在本文中,我们将像这样设置我们的项目结构:

relative_path 
- data 
-- mydata.json 
- processes
-- load_data.py

我们所有的代码都包含在一个名为relative_path的文件夹中。这是我们项目的根,意味着它保存了我们所有的代码。如你所见,我们有两个文件夹:包含目标 json 文件的 data 文件夹,以及包含load_data.py的 processes 文件夹;代码将加载mydata.json

加载数据

在这一部分中,我们将从加载 mydata.json 的最明显的方式开始,看看它的缺陷。然后我们会慢慢改进,以一个相对加载它的方法结束。然后我们将把这些知识汇编成一个简单的技巧,这对我们未来的所有项目都有帮助。

1.绝对路径

最直接的方法是在代码中使用绝对路径。

import json
f = open(r’C:\projects\relative_path\data\mydata.json’)
data = json.load(f)

虽然这在我的笔记本电脑上运行得很好,但是如果我们将代码部署在服务器上,如果我们将代码放在另一个文件夹中,这可能会失败。Linux 甚至没有 c 盘,所以服务器上肯定没有C:\project\relative_path folder

2.使用 file

我们可以计算运行时文件的绝对路径:

print(__file__)# Results in
# C:\projects\relative_path\processes\load_data.py

上面的代码将打印出我们当前正在执行的文件
的位置,在我们的例子中是C:\projects\relative_path\processes\load_data.py。我们可以在那里工作。

3.正在计算 file 的目录名

获取我们正在执行的文件的文件夹路径使我们更接*了:

import os
print(os.path.dirname(__file__))# Results in
# C:\projects\relative_path\processes

4.导航文件夹

我们必须转到一个文件夹,转到我们的根路径,然后转到data文件夹,以便获得我们的 json 数据的位置:

这里我们取我们的目录路径,并使用 os.path.join 来导航:

  1. 首先,我们将使用“..”上移一个文件夹(这与在端子中相同)。这将把我们导航到父文件夹,在本例中是根文件夹。
  2. 然后我们加入“数据”来导航到数据目录。
  3. 最后我们加入文件名

此外,我们调用 os.path.realpath 来“计算”‘..’-命令,因此它将产生我们的绝对路径。

导航故障

不错!我们已经在运行时计算了正确的路径。然而,问题是我们必须导航很多次。假设我们正在这个位置的文件中工作:\some_folder\some_process\datacollection\thing_one.py。如果我们想从这个文件加载' mydata.json '文件,我们必须运行:

从文件中我们必须向上移动三次。这有点复杂。我们也不能移动文件,因为它计算了我们的数据相对于我们正在执行的文件的路径。让我们在下一部分清理一下。

一条非常清晰和笔直的前进路线(图像由弹出&斑马上的无刷产生)

诀窍是

诀窍是定义一个变量来计算文件中根目录的绝对路径,然后从项目中的任何地方导入这个变量。它是这样工作的:

在我们的项目根目录下创建一个名为config的文件夹,其中包含一个名为definitions.py的文件。我们将把下面的代码放在里面:

这一小段代码将始终计算出我们项目根目录的正确路径。我们知道文件在项目中的位置,只需向上移动一个位置。然后,在其他文件中,我们可以导入 ROOT_DIR 变量。

我们可以做以下事情来代替前一部分中冗长而复杂的代码:

这种方法不仅可读性更好,而且不会将处理文件的位置绑定到数据文件的位置:我们计算数据文件相对于项目根的位置。您可以将带有 definition.py 文件的 config 目录添加到任何项目中,这样您就有了一个非常好的处理相对路径的通用解决方案。

如此美丽的小路(图片由莉莉·波普Unsplash 上拍摄)

结论

使用包含单个变量的单个文件,我们可以大大简化路径计算!此外,这个技巧非常简单,可以很容易地复制到每个项目中。使用定义文件,我们可以轻松地将环境变量加载到 python 程序中。更多关于这些在 这篇 中。

如果你有建议/澄清,请评论,以便我可以改进这篇文章。同时,看看我的其他关于各种编程相关主题的文章,比如:

编码快乐!

—迈克

又及:喜欢我正在做的事吗?跟着我

https://mikehuls.medium.com/membership

流畅的生物信息学工作流程的简单用户界面

原文:https://towardsdatascience.com/simple-user-interfaces-for-slick-bioinformatics-workflows-f765a37109b1?source=collection_archive---------34-----------------------

螺旋艺术,braňo @ 3d 天堂 Unsplash 许可下免费使用

最*,我开始将我所有的生物信息学脚本和工作流程打包到一个简单的基于文本的用户界面中。不是为了我的利益,而是为了我的生命科学同事的利益,他们倾向于避免可怕的命令行。因此,我花在运行作业或解决工作流程问题上的时间大大减少了,而他们运行自己的分析的信心却大大增加了。在这里,我们将把一个示例分析管道打包到一个基于文本的用户界面中,同时还有一些用户提示,以确保正确的文件得到处理。

那么他们为什么这么喜欢界面呢?因为这让他们感到安全,而且使用起来也容易得多,不需要跳到可怕的脚本中。

还有为什么我们这么喜欢界面?因为当我们不在办公室时,它更容易确保他们以正确的顺序运行正确的工作流,让我们有更多的时间来编写错误的代码。

这是针对什么受众的?

我开始将我的生物信息学工作流和脚本放入一个复古的基于文本的用户界面(TUI)中的原因是,实验室中不太熟悉 Linux 和 shell 脚本的人可以自己执行我定期运行的分析。它面向的是那些更倾向于湿实验室的同事或实验室伙伴,当你外出徒步旅行、划独木舟或滑雪时,他们仍然需要运行偶尔的分析管道(这对创造性思维空间是必不可少的)。

他们的反馈如何?

非常积极。他们不再需要考虑对某些样品进行何种类型的分析,但这也减少了错误设置参数或文件名的情况。当然,这一切都可以通过一系列彻底的检查和文档来完成,但是用户界面看起来很光滑,感觉很好,并且易于使用。

那么用户界面会是什么样子呢?

简单的界面,图片由作者提供

我们将使用 ncurses Dialog 和 shell 脚本来构建我们的界面,使用您通常使用的任何 yum/apt-get/conda 方法来安装 Dialog,并做一些修改,它看起来很容易让人想起某部科幻电影第 4 集的重启。这将比默认的蓝色和红色的配色方案少得多,我强烈建议改变它,以避免头痛。要更改我们的界面颜色,将我们的 profile.rc 文件复制到我们将要运行 TUI.sh 的同一个目录中。忽略后果自负。

制作启动屏幕

为了欢迎您的同事使用他们的新工具,我们可以显示一个闪屏,其中包括一些 ASCII 格式的欢迎说明或徽标。对话框有这个简洁的功能,你可以指向一个要在界面中显示的文本文件。为了正确显示,界面尺寸必须与文本文件的字符尺寸相匹配。我喜欢蜥蜴,所以我的欢迎屏幕将是一张使用https://many tools . org/hacker-tools/convert-images-to-ASCII-art/转换成 ASCII 的 groovy 蜥蜴的图片,其尺寸与界面尺寸相匹配。我发现 60 x40 的效果很好。我们将把它保存为文本文件 welcomemsg.txt

然后,可以使用以下命令在 TUI 中显示该文本文件。

export NCURSES_NO_UTF8_ACS=1welcomemsg () {
 dialog — title “Bioinformatics Analysis Wizard” — ok-button “next” — msgbox “$(cat welcomemsg.txt)” 40 60
}

添加菜单

一个很棒的功能是内置了交互式菜单,这些菜单(和可能的子菜单)可以引导用户进行特定类型的分析,例如 DNA 或 RNA。我们将为菜单创建三个选项,以代表通常分析的主要分子类别(RNA、DNA 和蛋白质)。

mainoption() {
 MAINOPTION=$(dialog — title “Bioinformatics Analysis Wizard” — menu “Please choose from the following\
 analysis options” 20 60 3 \
 “1” “Start DNA analysis” \
 “2” “Start RNA analysis” \
 “3” “Start Protein analysis” \
 3>&1 1>&2 2>&3)

 if [ $MAINOPTION = 1 ]; then
 DNA_analysis
 elif [ $MAINOPTION = 2 ]; then
 RNA_analysis
 elif [ $MAINOPTION = 3 ]; then
 Prot_analysis
 fi
}

菜单选项

一旦用户选择了他们的分析选项,在我们开始潜在的冗长分析之前,显示正在处理的文件和通过的工作流总是一个好主意,只是为了确认已经上传了正确的数据集。为了显示输入文件的名称,我们将在 DNA 分析工作流程的描述旁边使用内置函数的对话框。这与我们显示闪屏的方式类似。

这里值得注意的是,进一步的子菜单可以放置在菜单选项中,以增加您的生物信息学工作流程的复杂性。

现在,用户已经手动验证了将要分析的文件以及如何分析它们,我们终于可以运行分析了。当分析正在运行时,我们通过显示“运行”屏幕让用户知道他们的分析正在运行。

DNA_analysis() {
 #Displays files listed in analysis folder
 if (dialog — title “Bioinformatics Analysis Wizard” — yesno \
 “Are these the samples you are expecting? \n\n$(ls [Your_Input_Directory.*])” 20 60)
 then
 #while the script is running display and information box
 $(yes | bash [YOUR_DNA_ANALYSIS_SCRIPT_HERE] 2>&1 out.log) | dialog — title “Bioinformatics Analysis Wizard” \
 — infobox “Performing DNA analysis, please wait” 8 60
 else
 mainoption
 fi
}

退出消息

为了表明分析已经完成,我们可以显示最后的庆祝屏幕。

exitmsg () {
 dialog — title “Bioinformatics Analysis Wizard” — ok-button “exit” — msgbox “$(cat exitmsg.txt)” 20 60
}

为此,您可以选择尺寸为 60x40 的 ASCII 文件形式的个人风格。为了从图像中生成 ASCII 艺术,我使用了https://many tools . org/hacker-tools/convert-images-to-ASCII-art/

现在都在一起

export NCURSES_NO_UTF8_ACS=1welcomemsg () {
 dialog — title “Bioinformatics Analysis Wizard” — ok-button “next” — msgbox “$(cat welcome.txt)” 20 60
}mainoption() {
 MAINOPTION=$(dialog — title “Bioinformatics Analysis Wizard” — menu “Please choose from the following\
 analysis options” 20 60 3 \
 “1” “Start DNA analysis” \
 “2” “Start RNA analysis” \
 “3” “Start Protein analysis” \
 3>&1 1>&2 2>&3)

 if [ $MAINOPTION = 1 ]; then
 DNA_analysis
 elif [ $MAINOPTION = 2 ]; then
 RNA_analysis
 elif [ $MAINOPTION = 3 ]; then
 Prot_analysis
 fi
}DNA_analysis() {
 #Displays files listed in analysis folder
 if (dialog — title “Bioinformatics Analysis Wizard” — yesno \
 “Are these the samples you are expecting? \n\n$(ls [Your_Input_Directory.*])” 20 60)
 then
 $(yes | bash [YOUR_DNA_ANALYSIS_SCRIPT_HERE] 2>&1 out.log) | dialog — title “Bioinformatics Analysis Wizard” \
 — infobox “Performing DNA analysis, please wait” 8 60
 else
 mainoption
 fi
}exitmsg () {
 dialog — title “Bioinformatics Analysis Wizard” — ok-button “exit” — msgbox “$(cat exitmsg.txt)” 20 60
}welcomemsg
mainoption
exitmsg

重述

总之,我们制作了一个基于文本的用户界面(TUI)来帮助指导我们潜在的不太自信的 Linux 同事运行常见的生物信息学工作流程。我们这样做的原因是通过限制可用的选项和命令,确保分析完成。添加了一个闪屏来欢迎用户,然后显示一个菜单来进一步指导用户执行他们想要的分析类型。然后在他们选择的分析运行时通知他们。一旦分析完成,就会显示完成通知。

通过以这种方式打包生物信息学脚本,您可以让同事们更加独立地执行常规分析流程。

如果不熟悉终端,它可能是一个可怕的地方,许多生物学家强烈地认为它是“非编码者”。将复杂的分析管道包装在安全舒适的 TUI 中可以弥补这一差距,并使我的一些同事能够更多地了解潜伏在终端矩阵阴影中的龙…

在 Python 中应用 Lambda 函数的简单方法

原文:https://towardsdatascience.com/simple-ways-to-apply-lambda-function-in-python-7382276403a4?source=collection_archive---------7-----------------------

开始使用高度通用的功能

Yannis Papanastasopoulos 在 Unsplash 上拍摄的照片

什么是λ函数

匿名函数是没有名字的函数。在 Python 中,使用lambda关键字来确定匿名函数。这是因为 lambda 函数在定义时不需要名字,不像常规函数。我们使用lambda关键字来构造函数,而不是使用def关键字。这就是匿名函数也被称为 lambda 函数的原因。

lambda 函数可以有几个参数,但只有一个表达式。以下语法用于声明 lambda 函数:

lambda argument(s): expression

何时使用 Lambda 函数

有成千上万个使用 lambda 函数的用例。然而,当需要函数对象时,它们最常被应用。

此外,lambda 定义中没有“return”语句;相反,它总是包含一个返回的表达式。所以,为了简单起见,可以考虑使用lambda函数。

此外,当函数表达式很小时,最好使用 lambda 函数来提高可读性。换句话说,lambda 只能有一个表达式,因此如果你的函数不能用一行代码来描述,就不要使用 lambda 函数。

稍后,我们将探索几个使用 lambda 函数的例子,以便更好地理解它的用例。

如何使用 Lambda 函数

λ和应用

我将通过将 lambda 函数应用于不同的例子来解释它的用法。首先,让我们创建一个简单的数据框进行操作。

grade = {'Class':['A1', 'A2', 'A3', 'A4','A5'],
        'MathScore':[3.2, 3.3, 2.1, 2.9, 3.6],
        'ChemistryScore': [3.2, 3.6,3.3,2.1,4.6]}grade = pd.DataFrame(grade)

该数据集显示了从 A1 到 A5 的五个班级的数学和化学*均分数。

图 1:数据集—按作者分类的图像

例如,我想根据一个特殊的公式来评估每个班级的数学能力,该公式是将数学分数乘以数学分数本身的幂,然后将结果除以 2。下面是我如何使用lambda函数计算的。

grade['evaluate']=grade['MathScore'].apply(lambda x: round((x**x)/2,2))

apply方法调用lambda函数,并将计算应用于数据帧的每一行。此外,apply还可以对数据框中的每一列进行修改。在这种情况下,在apply函数中再指定一个参数作为axis = 0。我计算后的结果存储在“evaluate”列,如下图所示。

输出:

图 2: Lambda +应用——作者图片

在我们的数据框架的另一个例子中(图 1 ),我想根据他们在数学和化学上的表现对班级进行分类。我们可以使用lambda很容易地解决这个问题。

grade['group']=grade['MathScore'].apply(lambda x: 'Excellent' if x>=3.0 else 'Average')

输出:

图 3:使用 Apply、Lambda 和条件语句

λ和子列表

假设我有一个如下的列表:

list = [[5,6],[12,32,43],[3,43,42]]

为了找到具有最大值的子列表,我可以如下应用lambda函数和max:

max(list, key=lambda x: sum(x))

因此,[3,43,42]是三个子列表中总值最高的子列表。

Lambda 和 if-else

万一我想做一个值之间的比较,得到一个更大值的结果。让我们看看如何用lambdaif-else.来实现它

Greater = lambda x, y : x if(x > y) else y
Greater(0.002, 0.5897)

结果是 0.5897。简单吧?

λ和过滤器

继续使用图 1 中的示例数据框,我将找出有多少数学成绩大于*均分。filter方法可以通过对序列应用 lambda 函数来过滤数据。事情是这样的:

mean = mean(grade['MathScore'])
list(filter(lambda x: x> mean,grade['MathScore']))

输出是一个大于*均值的数学分数列表:[3.2,3.3,3.6]

在另一种情况下,我想用filter方法找到嵌套列表的交集。看看我在下面的两个列表中有什么:

group1 = [1, 2,3,43,23,42,8,3,7]
group2 = [[3, 34, 23, 32, 42], [6, 11, 9], [1, 3,9,7,2,8]]

现在,通过应用下面的代码,我可以找出一个列表,其中组 2 中的值也存在于组 1 中:

[list(filter(lambda x: x in group1, sublist)) for sublist in group2]

输出: [[3,23,42],[],[1,3,7,2,8]]

简单地说,filter 方法检查每个子列表的项目,以确定它是否包含在组 1 中。列表理解应用于组 2 中的每个子列表。

结论

以上是一些简单的lambda.例子,希望你觉得有用。如果你有什么有趣的应用,不要犹豫,与我分享。

单纯复表示学习

原文:https://towardsdatascience.com/simplicial-complex-representation-learning-a04ccf2d2578?source=collection_archive---------15-----------------------

思想和理论

使用高阶几何消息传递方案学习整个单纯复表示

罗南古田Unsplash 上的照片

O 对象表示学习旨在学习一种映射,该映射将该对象的基本组件嵌入到某个欧几里得空间中,同时保留该对象的结构信息。最*,这种方法获得了很大的势头,特别是图形表示学习。具体来说,后者在过去几年里吸引了相当大的流行,在节点级表示学习上都取得了成功。这种图表示的应用是多种多样的,因为它们可以用于诸如图分类或图相似性等领域的几乎任何下游机器学习任务。

本文的目的是将图形表示学习推广到称为单纯复形【2】的几何/组合对象。单纯复形是图的一般化,它们可用于存储超出通常用图的边来建模的成对关系的关系。下图给出了单纯复形的例子。

单纯复形的例子

在上图中,左侧 SC 包含两个面。这些面中的每一个都可以被认为是它所包围的三个边中的一个关系,或者一个高维度的“边”。从这个角度来看,很自然地可以将图[3]上常见的信息传递推广到单纯复形 T11。也就是说,高阶面可以用于在它们所绑定的低维面之间发送消息。我们接下来考虑这个。

几何消息传递方案

例如,考虑下面的例子:

图 1:在单纯复形上传递消息的例子[1]

我们试图通过从图[3]中概括熟悉的消息传递思想来定义单纯复形上的深度学习协议。我们将针对图 1 中给出的红色节点来说明计算图。这个红色节点分别通过边 e1、e3 和 e2 与 v2、v3 和 v3 相邻。我们定义了一个计算图,将这些节点和边考虑在内。这应该与图[3]上的消息传递方案很相似。现在来考虑边缘之间的高阶消息传递协议,我们看一下面[1,7]。

图 2:深入消息传递[1]

我们从图中观察到,蓝色边缘与亮粉色边缘和暗粉色边缘相邻,从某种意义上说,它们都限定了相同的粉色面。为此,计算图如图 2 所示。其他边缘也是如此。注意,图 2 中给出的计算图包含从节点、边和面获得的信号。如下图所示,这种消息传递协议以放射状方式有效地从顶点的邻域收集信息:

图 3:图 2 中解释的消息传递以放射状方式收集本地信息。如图所示,每次深入网络,我们都会收集更多的信息。

三种消息传递方案

上述消息传递方案被称为 邻接消息传递方案(AMPS) ,因为它考虑了给定单纯复形的邻接关系。如果我们想写一个等式来描述这个方案,它将是这样的:

邻接消息传递方案等式[7]

这里的 H 是表示单形嵌入的向量。下标 m 是单纯形的维数,上标代表计算阶段。θ是训练参数。注意,在前面的等式中,更新考虑了从 mm+1 尺寸获得的信号。这与上面的图 1、2 和 3 是一致的。此外,上述等式概括了常见的图形神经网络消息传递协议:

图的通用消息传递方程[7]

注意,当 m=0 时,基本上等式是相同的。

然而,单纯复形的情况要有趣得多,并且可以定义其他自然消息传递协议。

共邻接消息传递方案(CMPS) 是一种消息传递方案,从较高的面开始,对较低维度的面进行计算,如下图所示:

图 4:相邻消息传递方案[1]

这里的信息流通过以下方式给出:

图 CMPS 中的信息流

观察到信息从高阶面孔流向低阶面孔,与前一种情况相反。例如,如果一个人需要对一个给定的单纯复形的面进行分类,这种方案是有用的。

上述方案的等式给出如下:

请注意,它非常类似于 AMPS 方程,唯一的区别是此处的更新考虑了较低的相邻面,而不是较高的相邻面。

我们在这里介绍的第三个消息传递代理是一个考虑了边界和联合边界关系的代理。看一个例子是最容易的。我们考虑关于粉红色边缘的情况。这条边的边界是红色和绿色节点,共同边界面是蓝色和粉色面。这解释了下图(a)中的计算图

图 6:边界/联合边界消息传递方案(BCMPS)

深入研究上面的网络,我们可以得到上面图(b)中给出的计算图。下图给出了这里的信息流:

图 7:图 6 中给出的 BCMPS 中的信息流。

上述三种消息传递协议最早出现在[1,7]中。

单纯复数自动编码器

我们现在看看如何使用上述方案之一(AMPS)来定义一个单纯复数自动编码器。给定一个单纯复形 x,单纯复形自动编码器[1,7]由三部分组成:

(1)编码器-解码器系统,自动编码器的可训练组件。

具体来说,编码器和解码器是以下形式的函数

单纯复形上的编码器和解码器功能

(2)感兴趣对象的相似性度量,它是用户定义的相似性函数,表示对象之间相似性的概念,

单纯复形上的相似性度量可以是,比如说,它的邻接矩阵。

我们希望上面指定的编码器-解码器系统学习单纯形的嵌入表示,使得:

这里 z_a 表示单形 a 在欧几里德空间内的嵌入。为了满足上面的等式,我们定义了一个损失函数来强制这些关系。

(3)损失函数,它是用户定义的函数,用于根据相似性度量来优化编码器-解码器系统。

上面的定义有效地定义了单纯复形上的自动编码器。相关处理方法参见[4]、[5]和[6]。

学习完全单纯复表示

假设我们已经训练了一个编码器解码器系统,就像我们在上一节中描述的那样。我们寻求学习单形复级嵌入的形式:

这里 U_X 表示由经过训练的编码器编码器( enc,dec)(详见【7】)导出的 X 的单形嵌入,以及

是嵌入 z_m 的单纯形的权重。这些权重可以通过(例如)学习:

最后,嵌入 hX 的整个单纯复形可以用多种方法学习。例如,给定一个单纯复形{Xi}的集合,可以通过最小化目标来学习复形到复形的邻*嵌入:

在哪里

是单纯复形{Xi}上适当选择的距离矩阵。

参考文献

[1] Mustafa Hajij、Kyle Istvan 和 Ghada Zamzmi。细胞复杂神经网络。2020 年 NeurIPS 拓扑数据分析研讨会。

[2]艾伦·哈奇,代数拓扑,2005。

[3] Gilmer,j .,Schoenholz,S. S .,Riley,P. F .,Vinyal,o .和 Dahl,G. E,《量子化学传递神经信息》。《2017 年国际机器学习会议论文集》

[4]雅各布·查尔斯·赖特·比林斯、米尔科·胡、朱利亚·勒达、阿列克谢·梅德韦杰夫、弗朗切斯科·莫特斯、阿德里安·奥尼卡斯、安德里亚·桑托罗和乔瓦尼·佩特里。用于单纯复形中社区检测的简单 x2vec 嵌入。

[5]迈克尔·T·绍布、奥斯汀·R·本森、保罗·霍恩、加博尔·利普纳和阿里·贾德巴贝。单纯复形上的随机游动和归一化的 Hodge 1-拉普拉斯算子。暹罗评论,62(2):353–391,2020。

[6]西莉亚·哈克。k-simplex 2 vec:node 2 vec 的单纯扩展。NeurIPS 拓扑数据分析研讨会,2020 年

[7]穆斯塔法·哈吉、加达·扎姆兹米和蔡轩亭,单纯复表示学习,arXiv 预印本 arXiv:2103.04046 (2021)

用脸书预言家简化预测

原文:https://towardsdatascience.com/simplified-forecasting-with-facebook-prophet-d5789d32acdf?source=collection_archive---------21-----------------------

fbprophet 库快速预测入门

照片由德鲁·比默Unsplash 上拍摄

为什么是脸书先知?

时间序列预测的挑战

时间序列预测是一种复杂的艺术形式。许多模型对趋势、周期(称为“季节”)和不断变化的波动幅度非常敏感,而是需要静态数据,而这些数据缺乏这些特征。

非*稳数据的一个很好的例子是 2020 年新冠肺炎在美国的累积扩散。在这个项目中,我将使用冠状病毒政府反应跟踪器的数据,该跟踪器提供每个国家的每日更新数据,包括政府干预。如果您希望通过包含外生变量(建模数据之外的变量,可能会对其产生影响)来进一步进行预测,您可以在该数据集中找到许多相关变量。然而,对于这个例子,我们将只使用美国的累计报告感染。

从上面可以看到,不仅有上升趋势,而且趋势还在不断变化。从累积数据来看,季节性并不明显,但当我们进行一阶差分将累积病例转换为每日新病例时,我们会看到季节性出现。

作者图片

每周的季节性可能是因为:

  1. 人们往往在周末接受检测,他们的结果往往在周三回来,造成报告病例的高峰在周三,低谷在其他日子。或者,
  2. 实验室在特定的日子报告大量病例。

请注意 12 月 7 日、12 月 14 日、12 月 21 日等的下跌。12-25 日和 01-01 日也有大幅下跌。我想圣诞节和元旦期间没有多少实验室工作人员在工作,所以报告数量有所下降。

我们必须记住,数据不是事实,图表中的病例实际上是报告的病例,而不是实际的感染。报告模式造成了数据的季节性。

阿玛系列模特

ARMA 模型是自回归模型和移动*均模型的组合,是预测*稳时间序列数据的重要工具。我不会在这里详细解释,因为这篇文章是关于一种不同的技术,但是你可以在这里阅读。

ARMA 模型的扩展,如 ARIMA 可以解释趋势,s ARIMA 可以考虑数据的季节性。然而,这些模型的准确性需要仔细调整几个超参数,以确定过去的数据如何以及在何种程度上影响未来。数据科学家通常会对数据进行一系列转换,例如减去移动*均值或标准偏差,或者对其进行对数缩放以获得良好的预测。通过足够的努力和专业知识,这些都是强大的模型。

通过努力和彻底的数据探索,我调整了我的数据库,以 99%的准确率预测 1 月前 18 天的病例。你可以通过我的 Github repo 预测 COVID 病例率来体验我在 SARIMA 建模方面的冒险。

使用 SARIMA 模型预测 2021 年 1 月的累计新冠肺炎病例,该模型仅根据 2020 年的数据进行训练,并与同期的实际累计病例进行比较。作者图片

用脸书预言家做一个简单的预测

R 和 Python 脸书先知库为您做了大量的工作。它允许快速和简单的时间序列预测,但也为经验丰富的预测者提供了调整内部设置的选项。它可以检测并调整残差中的季节性、趋势和移动标准偏差。然而,它是关于你如何实现它的。让我们看看如何开始。

加载 fbprophet 并准备数据

我们可以用!pip install fbprophet轻松地将 Prophet 安装到 Google Colab 笔记本中。

在我运行 Anaconda 包管理器的本地 Windows 机器上,我用 bash 终端安装了它,脸书在这里有更多关于安装的指南。

作者要点

您可能会注意到,最后一行将“日期”列重命名为“ds”,将“累计案例”列重命名为“y”。这是脸书要求的,以便使用数据框架进行建模。许多有经验的 Pandas 用户可能会尝试将 datetime 列作为索引,但是对于 Prophet,不要这样做。

用 Prophet 预测

我们的数据框架已经可以建模了。创建和训练开箱即用的模型非常简单:

m = Prophet() m.fit(df)

但是,这是棘手的部分。你必须准备一个特殊的数据帧来存储实际的预测。幸运的是,这个模型提供了一个方便的方法来帮你做这件事。

future = m.make_future_dataframe(periods=length_of_desired_forecast)

最后,要进行预测,只需将future数据帧作为模型的.predict()方法的参数,如下所示:

forecast = m.predict(future)

我喜欢脸书的人们创造的变量名惯例,其中模型预测未来以做出预测。对我来说,这是令人满意的,也是恰到好处的。

以下是对未来 30 天的新冠肺炎病例进行预测的完整代码。作者图片

forecast将是一个包含您的预测的数据帧,位于您的future数据帧中“ds”列的末尾。它包括置信区间和模型用于每一步预测的所有参数。这允许对模型的内部工作进行一些有趣的检查,并有机会用置信带做一些有趣的图表。

作者图片

从上面可以看到,这个开箱即用的预言家模型做了一个非常基本的线性回归作为预测。模型的进一步调整将提高精确度。如果您运行该代码,您将看到警告,表明 Prophet 已经自动识别数据中的每周季节性,但您可以手动告诉它寻找每月或每年的季节性。你可以尝试一些其他的调整和改进,包括添加额外的(外生的)变量,比如假期或我们使用的数据集中提供的政府干预。

Greg Rafferty 的这篇精彩的文章提供了更全面的指导。但是,以上应该让你离开地面,给你一些东西开始。

如果你想看我在尝试预测 Xprize 比赛的新冠肺炎案例方面的全部工作,你可以在这里查看:
(剧透,我最终选择了更准确的萨里玛模型)

参考文献:

脸书先知快速入门指南

用 Python 预测脸书预言家Greg raff erty

数据:

冠状病毒政府响应跟踪系统
感谢 Blavatnic 政府学院和牛津大学

神经网络背后的简化数学

原文:https://towardsdatascience.com/simplified-mathematics-behind-neural-networks-f2b7298f86a4?source=collection_archive---------16-----------------------

图片由 阿丽娜

神经网络是将数据映射到信息的通用*似器。这是什么意思?神经网络能解决任何问题吗?神经网络是逐场景/逐帧分析、股票价格预测、零售和许多其他目的的成熟解决方案。我们很多人都在企业级使用它,但是有多少人真正理解它呢?

为了回答这个问题,‘神经网络能解决任何问题吗?’,还是从基础说起吧。一个 NeuralNet 由称为层的垂直堆叠组件组成:输入、隐藏、输出。每一层都由一定数量的神经元组成。输入图层具有数据集的属性(要素)。基于问题陈述,可以有具有多个神经元的多个隐藏层,并且输出层可以具有多个神经元。

理解感知器和激活函数

感知器(或神经元)是神经网络的基本粒子。它的工作原理是阈值化。f(x) 为阈值为 40 的求和函数。

图一。神经元的放电(图片由作者提供)

在这两种情况下,定义的函数都返回两个输入的和, x₁,x₂.在第一种情况下,函数返回小于阈值的 30。在第二种情况下,函数返回大于阈值的 50,神经元将被激活。这个函数比这个复杂。典型神经网络的神经元接收乘以其权重并加上偏差的输入值之和,并且该函数也称为激活函数阶跃函数帮助做出决策。

图二。感知器(作者图片)

激活函数将来自节点的输出转换成二进制输出;如果加权输入超过阈值,则为 1,否则为 0(取决于激活函数)。有三种最常见的激活功能:

乙状结肠的

Sigmoid 是一种广泛使用的激活函数,有助于捕捉非线性关系。

图三。s 形曲线(来源)

对于 z 的任何值,函数φ(z)将总是返回二进制(0/1)输出。正因为如此,在概率型题中被广泛使用。

正切双曲线

它或多或少类似于 Sigmoid 函数,但是 tanh 的范围是从-1 到 1,这使得它适合于分类问题。它是非线性的。

图 4。tanh 曲线(图片由作者提供)

整流线性单位

它是深度学习中使用最多的激活函数,因为它没有其他激活函数复杂。 f(x) 返回 0 或者 x

图五。ReLu 曲线(图片由作者提供)

这使得计算变得容易,因为 ReLu 函数的导数返回 0 或 1。

神经网络

为了理解神经网络的黑盒,让我们考虑一个具有 3 层的基本结构;输入层、密集/隐藏层(连接在神经元的两侧)和输出层。

图六。简单的神经网络(图片由作者提供)

权重和偏差是随机初始化的。神经网络输出的准确性在于通过不断更新来找到权重偏差的最佳值。让我们考虑一个等式, y = wx ,其中“w”是权重参数,“x”是输入特征。简单来说, weight 定义了赋予特定输入属性(特征)的权重。现在,方程 y = wx 的解总会经过原点。因此,增加了一个截距来提供自由度,以适应被称为偏差的完美拟合,等式变为 ŷ = wx + b ,我们都熟悉因此,偏差允许激活函数的曲线上下调整轴。

现在让我们看看神经网络可以变得多么复杂。对于我们的网络,输入层有两个神经元,密集层有四个,输出层有一个。每个输入值都与其权重和偏差相关联。输入特征与权重和偏差的组合通过密集层,在密集层中,网络在激活函数的帮助下学习该特征,它具有自己的权重和偏差,并最终进行预测(输出)。这就是正向传播。那么,我们的网络总共有多少个参数?

图 7。神经网络的总参数计算(图片由作者提供)

对于这样一个简单的网络,总共有 17 个参数需要优化,以便得到最优解。随着隐藏层数量和其中神经元数量的增加,网络获得了更多的能力(直到某一点),但我们有指数数量的参数要优化,这可能会占用大量的计算资源。所以,有一个权衡。

更新网络

在前向传播的单次迭代之后,通过取实际输出和预测输出之间的(*方)差来计算误差。在网络中,输入和激活函数是固定的。因此,我们可以改变权重和偏差来最小化误差。可以通过注意两件事来最小化误差:通过少量改变权重来改变误差,以及改变的方向。

价值函数

一个简单的神经网络基于线性关系预测值, ŷ = wx + b,其中 ŷ(预测)y(实际)的*似值。现在,可以有几条直线来拟合 ŷ.为了选择最佳拟合线,我们定义了成本函数。

ŷ = θ₀ + xθ₁.我们需要找到 θ₀θ₁ 的值,使得 ŷ 尽可能靠* y 。为此,我们需要找到 θ₀θ₁ 的值,使得以下定义的误差最小。

(图片由作者提供)

误差, E = 实际值与预测值之差的*方,即= (ŷ - y)

因此, 成本=(1/2n)(θ₀+xθ₁-y)其中 n 是用于计算均方差的点的总数,并且除以 2 以减少数学计算。因此,我们需要最小化这个成本函数。

梯度下降

该算法通过最小化成本函数来帮助找到 θ₀θ₁ 的最佳值。我知道c =(1/2n)(θ₀+xθ₁—y)对于解析解,我们取 C 关于变量的偏导数(**),称为梯度**

****

这些梯度代表斜率。现在,原来的成本函数是二次的。所以,图表看起来像这样:

图 8。梯度下降曲线(图片由作者提供)

更新 θ 的公式为:

如果我们在点 P1 ,斜率为负,这使得梯度为负,整个方程为正。因此,该点正向下移动,直到达到最小值。类似地,如果我们在点 P2 ,斜率为正,这使得梯度为正,并且整个方程向负方向移动 P2 ,直到它达到最小值。这里, η 是一个点向最小值移动的速率,称为学习速率。所有的θ’同时更新(对于某些时期)并计算误差。

顺便提一下

照此下去,我们可能会遇到两个潜在的问题:1 .在更新 θ,的值时,您可能会陷入局部最小值。一种可能的解决方案是使用具有动量的随机梯度下降(SGD ),这有助于越过局部最小值;第二。如果 η 太小,收敛时间太长。或者,如果 η 太大(甚至中等偏高),它会继续在最小值附*振荡,永远不会收敛。因此,我们不能对所有参数使用相同的学习率。为了处理这个问题,我们可以安排一个例程,在梯度向最小值移动时(例如余弦衰减),调整 η 的值。

反向传播

通过使用梯度下降算法优化和更新权重偏差的一系列操作。让我们考虑一个简单的神经网络(图 2。)具有输入、单个隐藏层和输出。

设, x 为输入, h 为隐含层, σ 为 sigmoid 激活, w 权重, b 为偏置, wᵢ 为输入权重, wₒ 为输出权重, bᵢ 为输入偏置, bₒ 为输出偏置, O

现在,我们通过堆叠从输入到输出的一系列操作来创建图 2 的计算图。

图九。计算图(图片由作者提供)

这里, E 依赖 OO 依赖 μ₂μ₂ 依赖 bₒwₒ & hh 依赖 μ₁μ₁ 依赖 x ,我们需要计算权重和偏差的中间变化(依赖性)。因为只有一个隐藏层,所以存在输入和输出权重和偏差。所以,我们可以把它分成两种不同的情况。

案例 1: w.r.t .输出权重和偏差

图 10。案例 1 的计算图(图片由作者提供)

因此,通过将导数的值放入上述两个误差变化方程中,我们得到梯度如下

我们可以通过以下等式更新权重和偏差:

这个计算是针对隐藏层和输出的。同样,对于输入和隐藏层如下。

案例 2: w.r.t .输入权重和偏差

图 11。情况 2 的计算图。(图片由作者提供)

我们可以使用以下方法更新这些梯度:

两种情况同时发生,计算误差,直到称为时期的重复次数。神经网络有监督。在它运行了一定数量的历元后,我们为数据集的选定要素提供了一组优化的权重和偏差。当在这个优化的网络中引入新的输入时,它们用权重和偏差的优化值来计算,以实现最大的精度。

神经网络能解决任何问题吗?

如前所述,神经网络是通用逼*器。理论上,它们能够表示任何函数,因此可以解决任何问题。随着网络的增长(更多的隐藏层),它获得了更多的能力,但是有指数数量的参数需要优化,这需要大量的资源。

实现可以在这里找到。

简化的学生 t 分布

原文:https://towardsdatascience.com/simplified-students-t-distribution-8ce0e4b950a4?source=collection_archive---------29-----------------------

统计学中的分布序列

图片来自 Unsplash

简介

数据无处不在。我们需要的是通过处理数据来找到数据的核心,并通过提取隐藏在内部的东西来让数据为我们服务。数据分析师、科学家和工程师是实现这一目标的一线人员。当我们谈论数据时,数据点的分布非常重要。它让我们快速了解了数据的*均值和标准差。此外,数据的正态性检验非常重要,因为各种统计测量都是基于正态分布的。在这里,我将讨论 t 分布,它是正态分布和二项式分布的一个家族,对可能出现两种结果的事件的决策非常有影响。

T 分布

t 分布类似于正态分布,只是它的尾部更粗更长。正态分布具有正态形状,这意味着它在偏离中心几个标准偏差后下降到 0,而 t 分布是一族几乎正态形状的曲线,这些曲线因采样数不同而不同。我们来澄清一下说法。中心极限定理指出,当我们随机抽样且抽样次数足够多时,样本均值的分布将遵循正态曲线。让我们试着实现它。

我们有 30000 个测量值,我们想取 5000 个样本,替换 1000 次。然后,我们将计算每个样本的*均值,并绘制样本*均值。

全体人口(图片由作者提供)

一旦获得样本*均值,它们的分布将类似于下图。这证明了虽然总体是非正态的,但样本均值的分布类似正态分布曲线。样本均值也非常接*总体均值。这就是中心极限定理的精髓。当样本容量越来越大时,样本均值的分布接*正态分布。

样本大小= 500 的样本均值分布(图片由作者提供)

如果样本大小是 50 而不是 500,分布变得更宽。

样本大小= 50 的样本均值分布(图片由作者提供)

很明显,样本大小在分布曲线中很重要。样本量越小,分布就成为 t 分布的一部分,尾部越厚越长。当两个图形重叠时,视觉上可以理解。

绿色(样本量= 500)和红色(样本量= 50)(图片由作者提供)

标准化测试统计

在现实世界中,我们不处理正态分布的数据,因为大部分时间人口参数是未知的。在这些情况下,样本提供了一种通过估计获得总体参数的方法。如前所述,不同的样本量提供不同的 t 分布,我们需要一个检验统计量来衡量我们感兴趣的效果。在这种情况下,我们感兴趣的是样本数据的正态性。我们可以利用 t 值并将其作为检验统计量来区分 t 分布。

我有另一篇关于 t 检验的文章,读者可能会发现它与这个讨论有关。

t 作为检验统计量

当我们用 5 的小样本量绘制 t-统计量的分布时,我们得到了一个具有较长尾部的分布。样本号是自由度的去定义器。一般来说,如果样本大小为 N,自由度为 N-1。

样本量= 5 的 t 统计分布(图片由作者提供)

我们可以证明自由度也是 t 分布族中的区别因素。样本量为 10 和 50 时,我们得到以下分布。

样本量= 10 的 t 统计分布(图片由作者提供)

样本量= 50 的 t 统计分布(图片由作者提供)

当一起绘制时,它将在视觉上具有吸引力。理论上当自由度为无穷大时,情节变得正常。

黄色(样本量= 5)、蓝色(样本量= 10)和绿色(样本量= 50)(图片由作者提供)

seaborn 软件包的 kdeplot 提供了一种可视化观察分布的方法,这种方法类似于直方图,但它不是绘制频率,而是绘制连续的概率密度。当使用时,它也揭示了 t 分布的长尾。

KDE(核密度估计)图

结论

对于数据科学家和统计学家来说,正态分布的数据听起来像是奢侈品。真实世界的数据有时类似于正态分布,但本质上,它遵循一族 t 分布。这篇文章展示了对 t 分布族以及正态分布的清晰解释。在处理样本时,利益相关者应该意识到样本大小对关键决策估计的影响。

我的 Github 页面

使用道格拉斯·普克算法简化折线

原文:https://towardsdatascience.com/simplify-polylines-with-the-douglas-peucker-algorithm-ac8ed487a4a1?source=collection_archive---------7-----------------------

一种减少折线中数据点数量的算法

作者图片

一.动机

在开发路径跟踪应用和文档扫描应用时,我惊讶地发现这两个应用都需要某种折线简化算法。第一种方法需要算法来减少要保存到数据库中的路线点(纬度、经度)的数量,而后者使用该算法来拟合分割掩模中白色像素周围的四点多边形。虽然这两个应用程序是在两个不同的框架(Flutter 和 Android Native)中编写的,但在这两个实例中,我最终都使用了道格拉斯·普克算法的实现。因此,在这篇文章中,我想把重点放在这个有趣而简单的算法上,并提供该算法在 Python 中的一个“从头开始”的实现。

对于那些好奇的人,我使用的 Flutter 实现是由 darwin-morocho 提供的,Android 原生实现是由 OpenCV 在其 approxPolyDP 函数中提供的。

二。道格拉斯·普克算法

该算法也被称为 Ramer-Douglas-Peucker 算法,因为早在一年前的 1972 年,Urs Ramer 在其题为“*面曲线多边形*似的迭代程序”(Ramer,1972)的论文中重复了类似的思想。

1973 年,David H. Douglas 和 Thomas K. Peucker 发表了一篇题为“减少表示数字化线或其漫画所需点数的算法”的论文(Douglas & Peucker,1973)。其中他们引入了两种算法。其中一种算法已经被广泛实施,通常被称为道格拉斯·普克算法。该算法的目的是产生一个简化的折线,它比原始折线具有更少的点,但仍然保持原始折线的特征/形状。为了理解算法是如何工作的,我们可以一步一步地看看它是如何在图 1 中的四点折线上运行的。

图 1:原始折线。作者图片

第一步

图 2:B 和 C 到 AD 线的距离。作者图片

该算法从识别折线的起点和终点开始。在他们的论文中,Douglas & Peucker (1972)将这两个点分别称为锚点和浮点。在我们的例子中,这些点是 A (开始)和 D (结束)。对于折线中既不是起点也不是终点的其他点( BC ,它计算从该点到起点和终点形成的直线的“垂直距离”。这就给了我们 d(B,AD) = 1d(C,AD) = 0.3

第二步

图 3: B 离 AD 线最远。作者图片

然后该算法选择最远的点。在我们例子中,点是 b。我们称这个点为最大值。然后,它将 d(B,AD) 与 epsilon ( ε )值进行比较(在我们的示例中为 0.5)。由于 d(B,AD) > ε ,该算法将折线分为两个子线段。一段由最大值* ( AB )左侧的所有点组成,另一段由最大值 ( BC 、和 D )右侧的所有点组成。*

图 4:原始折线被分成两段。作者图片

第三步

图 5:第一部分。作者图片

该算法然后在第一段上再次执行步骤 1。它将起点和终点分别标识为 AB 。然而,与之前的迭代不同的是,在这个片段中只有两个点。在这种情况下,该算法不能进一步减少点数,因为直线是任何折线的最简单*似。因此, AB 被保留。

图 6:从第一个片段中选择的点。作者图片

第四步

图 7:第二部分。作者图片

类似地,对于第二段,算法执行步骤 1 以将 BD 识别为起点和终点,并计算所有剩余点(在我们的示例中只有 C )与由 BD 形成的直线之间的垂直距离。

图 8:从 C 到 BD 线的距离。作者图片

由于除了 BD 之外剩下的唯一一个点就是 C ,所以它是距离最远的点。因此,该算法将 d(C,AB)ε 进行比较。与第一次迭代不同, d(C,AB) < ε 。因此,该段可以去掉点 C ,只保留 BD

图 8:从第二段中选择的点。作者图片

第五步

图 9:算法的结果。作者图片

在第一段和第二段上完成所有迭代后,该算法将所有结果组合在一起,以创建原始折线的简化版本。

三。代码

图 10:示例代码的输出

下面的代码是我实现的最简单形式的道格拉斯普克算法。我的实现基于这个主题的维基百科页面提供的伪代码。我确信还有更有效实现。然而,我相信下面的代码足以理解算法的基本思想。

四。结论

在这篇文章中,我们学习了一个有用而简单的算法来减少折线中的点数。除了我在这篇文章的介绍中给出的例子,这种算法可以应用于更多真实世界的应用,从加速地图渲染,改善物联网设备之间的通信等。我希望这篇文章能帮助你理解这个算法,并把它应用到更多有用的应用中。

喜欢这篇文章,想表示你的支持?关注我或者给我买咖啡

参考

道格拉斯,D. H .,&普克,T. K. (1973)。减少表示数字化线或其漫画所需点数的算法。制图:国际地理信息和地理可视化杂志,10 (2),112–122。doi:10.3138/fm57–6770-u75u-7727

拉默,U. (1972)。*面曲线多边形逼*的迭代程序。计算机图形与图像处理, 1 (3),244–256。doi:10.1016/s 0146–664 x(72)80017–0

编码列车。(2019 年 10 月 24 日)。编码挑战#152 : RDP 线简化算法【视频】。YouTube。https://www.youtube.com/watch?v=nSYw9GrakjY

使用 Functools 的部分和单一分派简化您的功能

原文:https://towardsdatascience.com/simplify-your-functions-with-functools-partial-and-singledispatch-b7071f7543bb?source=collection_archive---------5-----------------------

处理具有许多参数和数据类型的函数

动机

你有没有遇到过像下面这样有很多参数的函数,

…或者一个带有不同数据类型参数的函数?

作者图片

在本文中,您将了解上面的函数可能出错的地方以及如何简化它们。

functools.partial

为了理解functools.partial是如何有用的,让我们从一个例子开始。假设您有一个如下所示的数据集:

您可能决定创建一个函数来获取每列中超过特定阈值的行数:

然后调用上面的函数,对每个参数使用不同的值:

以这种方式创建函数没有任何问题。然而,如果我们想试验不同的thresholdcolumn值,df就变得多余了。

有没有一种方法可以让我们用参数 **df** 固定来创建另一个类似于原始函数的函数?是的,那可以用functools.partial来完成。

现在函数get_acount_above_threshold_per_col只需要两个参数thresholdcolumn

相当酷!如果我们想为列magnesium试验不同的阈值,我们可以再次使用方法partial来进一步简化函数。

让我们来玩玩我们的新功能。

酷!

functools.singledispatch

假设您的函数接受两种类型的数据,一种是字典,一种是列表。

在函数中使用 if-else 语句调用另一个函数:

  • 如果数据类型为 dictionary,您将调用函数process_dict
  • 如果数据是列表类型,您将调用函数process_list

这很好,但是随着数据类型的增加,函数变得更加复杂。有没有一种方法可以不使用 if-else 语句来处理不同的数据类型?这时候functools.singledispatch就派上用场了。

singledispatch将根据当前函数第一个参数的类型选择正确的函数。

要使用singledispatch,只需:

  • 将装饰器@singledispatch添加到函数process_data
  • 将装饰者@process_data.register添加到process_dictprocess_list中。

让我们试试这些新功能,看看它们是否工作正常。当第一个输入是类型dict时,应该调用函数process_dict

当第一个输入是类型list时,应该调用函数process_list

当第一个输入是类型str时,将调用函数process_data,因为没有为该数据类型实现函数。

很酷,不是吗?

结论

恭喜你!你刚刚学会了如何使用functools.partialfunctools.dispatch来简化你的功能。我希望这篇文章能给你动力,让你当前的代码更具可读性。

随意发挥,并在这里叉这篇文章的源代码:

https://github.com/khuyentran1401/Data-science/blob/master/python/functools example.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的数据科学工具。你可以在 LinkedInTwitter 上联系我。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

💔-python-tricks-to-read-create-and-run-multiple-files-automatically-5221ebaad2ba> [## 使用 SimPy 在 Python 中模拟真实事件

towardsdatascience.com](/simulate-real-life-events-in-python-using-simpy-e6d9152a102f)

使用此框架简化您的 GA4 跟踪和分析—以 Spotify 应用程序为例。

原文:https://towardsdatascience.com/simplify-your-ga4-tracking-analysis-with-this-framework-spotify-app-as-an-example-6fb5327201b0?source=collection_archive---------35-----------------------

为您的数字产品制定一个组织良好的测量计划的 4 步框架。

凯利·西克玛在 Unsplash 上的照片

在这篇文章中,我将分享一个我已经使用了一段时间的跟踪框架。事实证明,这非常有助于简化 GA4/Firebase 数据的测量思路、报告和分析。这个框架可以和任何其他的产品分析工具一起使用,比如 Mixpanel,Amplified 等等。

这个框架应该可以帮助您回答如下问题:

我们的用户使用产品功能/流程吗?有哪些热门流量/功能?我们的哪部分用户使用哪些功能,使用频率如何?

我们的用户成功地完成了流程吗?每个流量的成功率是多少?我们是否有一个用户因为技术原因而难以完成的流程?

每个流程的完成率是多少?用户掉哪里最多?

该框架有四个主要步骤,您应该遵循这些步骤来为您的数字产品制定跟踪计划。虽然我不在 Spotify 工作,但我将举一个 Spotify 应用程序的例子来说明这个想法。

夹具在 Unsplash

第一步——列出你希望你的用户实现的数字产品(网络或应用)的所有流程。以 Spotify 为例,下面是一些可能被跟踪的流量。

第 1/4 步:GA4 分析跟踪框架——列出你的应用或网站中的所有流量。

第 2 步——对于每个流程,列出您希望您的应用程序用户执行的所有事件。在我们的 Spotify 示例中,下面是一些可能被跟踪的事件。

第 2/4 步:GA4 分析跟踪框架——列出你的应用或网站中的所有事件。

第 3 步——对于每个事件,列出与之一起发送的所有参数。与开发团队讨论对这一步很有帮助,这样您就知道每个事件有哪些数据可用。在 Spotify 的简化示例中,以下是一些可能随跟踪事件一起发送的参数。

步骤 3/4 : GA4 分析跟踪框架—列出事件的所有参数。

步骤 4-列出描述您的用户的所有用户属性。在这个阶段,与开发团队的协调会很有帮助,因为你的开发人员更了解应用的 API 框架。以 Spotify 为例,下面是一些可以追踪的用户属性。

步骤 4/4 : GA4 分析跟踪框架—列出您的用户的所有用户属性。

您可以通过以下链接下载带有 Spotify 示例的 GA4 分析框架:

https://docs.google.com/spreadsheets/d/1kH_BbETEQDGwIOk4UX84l7yAvC6NWcTLBoHieYmeJm8/edit?usp=sharing

最后的想法:

在这篇文章中,我试图分享一个分析框架,你可以用它来简化和组织你对数字产品测量的思考。这个框架的输出是一个度量文档,您可以使用它与开发人员、股东进行交流,并在后期的分析中使用参考。这个文档应该是一个动态文档,当有新的特性/流程添加到您的产品中时,它会得到更新。

最后,您是否从事产品分析工作,如果是的话,我很想听听您在为您的产品创建测量计划方面的想法和经验:-)

使用 ColumnTransformer 和管道简化机器学习模型开发

原文:https://towardsdatascience.com/simplifying-machine-learning-model-development-with-columntransformer-pipeline-f09ffb04ca6b?source=collection_archive---------24-----------------------

本文解释了 Scikit-Learn 的 ColumnTransformer 和 Pipeline 类的用法,以简化开发和部署机器学习模型的过程。

图片由克里斯里德Unsplash 上拍摄

列变压器简介

ColumnTransformer 使我们能够转换一组指定的列。它帮助我们用一个 fit()或 fit_transform()语句将多个转换应用于多个列。例如,我们可以用一个 fit()或 fit_transform()语句对数据帧的第一列进行估算,对第二列进行热编码。ColumnTransformer 类可以从' sklearn.compose '模块导入,如下所示。

让我们通过一个例子来深入研究 ColumnTransformer。考虑下面的数据帧,其中我们必须进行一次热编码“列 1”和顺序编码“列 2”。

作者图片

按照惯例,我们创建 OneHotEncoder 类的一个实例,并使其适合数据框,然后对其进行转换,如下所示。

作者图片

上面的步骤对数据帧的两列都进行了热编码,这不是我们想要做的。使用 ColumnTransformer 可以解决这个问题。让我们创建一个数据框,并使用 ColumnTransformer 转换它的列。

作者图片

作者图片

如上所述,我们可以用一个 fit_transform()语句在多个列上执行多个转换。如果没有 ColumnTransformer,这个操作会很复杂。在上面的例子中,我们创建了一个 ColumnTransformer 类的实例,并传递了一个名为“transformers”的参数,这是我们想要执行的转换的列表/元组。

变换列表/元组中的每个变换都有三个部分:

  1. 转换的名称,可以是任何名称,但是转换列表中的每个转换都必须有唯一的名称。
  2. 转变本身。
  3. 要转换到的列的列表。它应该是一个列表,即使您必须将它应用于一个单独的列。

让我们看另一个例子。考虑下面的数据帧,我们必须对“列 1”进行热编码,并保持“列 2”不变。

作者图片

作者图片

输出中的‘col 2’在哪里?

ColumnTransformer 只返回它已转换的列。在前面的例子中,我们已经转换了两个列,因此,它们都被返回。但是在当前示例中,我们只转换了一个列(“col1”),所以只返回转换后的“col1”。为了避免这种情况,我们需要传递一个参数' remainder=passthrough ',如下所示,这个参数的默认值是' drop ',它将删除其他列。

作者图片

作者图片

ColumnTransformer 的局限性

下面将讨论 ColumnTransformer 的一些限制。

  1. 即使我们输入了 DataFrame 对象,ColumnTransformer 也会输出一个数组,这使得跟踪列变得很困难。
  2. 在 ColumnTransformer 中,我们不能对单个列应用多个转换,如下所示。

考虑下面的数据框,其中我们必须输入模式和一个热编码“列 1”和中值输入“列 2”。这里我们试图对一个列(' col1 ')应用多个转换。

作者图片

作者图片

我们收到一条错误消息,称“输入包含 NaN”。为什么在上述 ColumnTransformer 的第一步中输入了“col1”之后,“NaN”仍然存在?

这是因为 ColumnTransformer 在每一步中都直接从输入数据帧/数组中提取列。一个步骤的输出不是下一个步骤的输入。因此,热编码的第二步是从输入数据帧中提取“col1 ”,而不是从第一步中提取。让我们看另一个例子。在下面的数据框中,我们将尝试顺序编码和最小-最大比例“列 1”和中位数估算“列 2”。

作者图片

作者图片

即使在步骤 1 中添加了一个顺序编码器,仍然会出现错误消息“无法将 string 转换为 float:‘a’”。为了解决这个问题,让我们了解一下管道。

管道介绍

管道是一系列的操作,其中一个步骤的输出成为下一个步骤的输入。管道类可以从 sklearn.pipeline 模块导入,如下图所示。

在下面的示例中,我们将首先对数据框的列进行中值估算,然后使用 Pipeline 对其进行最小-最大缩放。

作者图片

作者图片

如上所述,我们可以用一个 fit()或 fit_transform()语句执行多个转换。与 ColumnTransformer 不同,管道遵循一个连续的过程,前一步的输出成为下一步的输入。与 ColumnTransformer 类似,管道接受步骤输入,这些步骤可以是分类器、转换等。管道中的每一步都有两个部分:

  1. 步骤的名称。
  2. 手术本身。

如果不使用流水线,上述操作将使用如下所示的传统过程来执行。

作者图片

作者图片

传统的过程需要两个 fit_transform()语句来转换列,而 Pipeline 只需要一个。

管道的局限性

  1. 与 ColumnTransformer 类似,Pipeline 也输出数组。
  2. 与 ColumnTransformer 一样,我们不能指定要转换的列。

将 ColumnTransformer 与管道结合使用

正如在前面的一个例子中看到的,我们不能使用 ColumnTransformer 对一个列应用多个转换。我们在尝试时出错。让我们再次讨论这个例子。考虑下面的数据帧,其中我们必须输入模式和一个热编码“列 1”和中值输入“列 2”。这里我们试图对一个列(' col1 ')应用两个转换。

作者图片

作者图片

上面发生了什么?

如上所述,在流水线(‘col 1 _ pipe’)中,第一步(‘mode _ col 1’)的输出变成了第二步(‘one _ hot _ encode’)的输入。然后,我们将管道作为输入传递给 column transformer(' col _ transform '),其中这些步骤序列应用于' col1 ',中值转换应用于' col2 '。

因此,将 ColumnTransformer 与 Pipeline 结合使用简化了模型开发和部署过程,还减少了代码的大小。

简化 MATLAB 中强化学习的工作流程

原文:https://towardsdatascience.com/simplifying-reinforcement-learning-workflow-in-matlab-32b5aa5287b8?source=collection_archive---------20-----------------------

在 MATLAB 中求解 OpenAI 环境

假设你对使用强化学习解决某个问题感兴趣。您已经在您的环境中编写了代码,并编译了一系列强化学习(RL)算法来尝试。从头开始自己实现算法是棘手和耗时的,因为它需要大量的试验,并且包含许多实现技巧。那你是做什么的?

最好的答案是使用 RL 框架。RL 框架包含 RL 算法的*似最优实现。算法的实现被卸载到框架中,用户只需要担心演员和评论家模型的神经架构。有很多基于 TensorFlow 和 PyTorch 的框架。然而,与 MATLAB 2021a 一起发布的强化学习设计器应用程序在这一类别中也是一个强有力的竞争者,本文就是关于这一点的。

典型的 RL 环路(图片来自 mathworks.com)

RL Designer app 是强化学习工具箱的一部分。它基本上是 RL 工具箱功能的前端。设计器的点击功能使管理 RL 工作流变得极其简单,在这篇文章中,我将描述如何使用该应用程序解决一个简单的 OpenAI 环境。我创建了一个 youtube 系列,深入研究 MATLAB 中强化学习的细节。这篇文章的视频版本在这里:

RL 设计器应用程序看起来有点类似于深度网络设计器应用程序。在左侧窗格中,您可以找到代理、环境、结果和环境详细信息。您可以在应用程序内部执行整个 RL 工作流程。因为我们想让事情有点挑战性,我们将首先演示如何加载到外部环境中,并使用我们的自定义网络在其上训练 DQN。

强化学习设计器

您需要 Python 和 OpenAI-gym 包才能在环境中加载。我们开始吧,

装载环境

MATLAB R2021a 附带了一些预构建的环境,可以通过单击环境选项卡位置中的“新建”按钮来加载它们。在本文中,我们将尝试加载我们的自定义环境,它基本上是 OpenAI 的 mountain-Car-v 0 环境的包装器。在下面的代码中,我们为体育馆环境定义了包装器。“步骤”函数在健身房环境中执行步骤,并以 MATLAB 友好的格式返回详细信息。

开放式包装

这个类的对象需要在工作空间中创建,然后环境就可以导入 RL Designer 应用程序了。

选择代理和型号

就像选择环境一样,也可以通过选择代理选项卡区域中的“新建”按钮来选择代理。该应用程序给出了可供选择的算法列表。我们将选择 DQN 来完成这项任务。

代理选择屏幕

一旦我们选择了一个代理,MATLAB 就会创建一个默认的演员/评论家神经网络,该网络具有完全连接的层。我们想对此进行修改,并使用我们自己的定制神经网络。这可以通过选择代理并从工作区导入我们的自定义评论家网络来完成。我们使用以下脚本创建一个简单的线性网络,并将其加载到工作空间中。

DQN 客户网络

我们首先将网络加载到我们的 MATLAB 工作区,然后通过从代理选项卡中选择“导入”选项,最终将其加载到 RL designer 应用程序中。

我们还可以使用 Deep Network designer 应用程序来分析和编辑网络。网络架构可以是任意的。对神经网络的唯一限制是输入和输出应该与算法和环境修复相匹配。我们还直接在主窗口中指定超参数。我们也可以直接从这个屏幕设置目标网络的行为。该应用程序会自动处理所有这些小细节。

设置代理的超参数

培训代理人

单击主菜单栏上的“训练”按钮,即可开始训练。在开始这个过程之前,我们需要指定剧集细节和*均细节。训练统计如下所示:

训练步骤

这是一个非常标准的代理培训窗口。培训完成后,您可以保存代理和网络。保存的代理可以被重新训练或用于模拟性能。

验证

我们可以在应用程序中直接模拟我们训练有素的代理的结果。可以在“模拟”选项卡中设置模拟剧集的数量。您还可以加载预先训练的代理并模拟它们,以比较不同的代理。请记住,模拟步骤只记录任何给定环境的最终分数。如果需要可视化,您需要使用脚本手动模拟环境。

遗言

我们讨论了 MATLAB 中完整的 RL 工作流程。改变代理算法是非常无缝的,这是这个应用程序的主要卖点。我想强调的是,可以在 RL 工具箱(使用脚本)中找到额外的功能,但对于大多数用户来说,应用程序中的功能应该足够了。这个应用程序和框架的最大优势是它抽象出了所有的实现细节,以提供无缝的体验。如果你已经进入了 MATLAB 生态系统,试一试吧。干杯!

参考文献

  1. 本文代码: GitHub 链接
  2. RL 播放列表: Youtube 链接
  3. 强化学习工具箱文档

简单来说,就是云中的 Python

原文:https://towardsdatascience.com/simply-just-python-in-the-cloud-78274389ab00?source=collection_archive---------27-----------------------

所以你只想大规模运行 python?

作者图片

TL;博士

这是一个关于在 Azure 中运行代码的“精益”教程。随着你的数据驻留在云中虚拟机旁边的存储中,无需探索 Azure 迷宫般的复杂性,并使用新发布的 VS-Code“Azure 机器学习-远程”扩展,在虚拟机上编程就像在本地机器上开发代码一样简单,但具有云的扩展优势。这是利用云计算和 Azure 机器学习(AML)的第一步。

响亮的服务提供了许多选择,Azure 比其他服务更多;但是由于种类繁多,很难知道从哪里开始。让我们假设你已经订阅了 Azure ,并且已经开始了解 Azure 的网络门户portal.azure.com,——它是用于设置和管理网络资源的通用图形界面。云组件、服务和产品的通用管理术语是“资源”如果你对此不熟悉,可以在 Azure Fundamentals 中搜索一门在线课程,内容包括订阅、资源组、区域等。哈佛的 DS intro 让你觉得使用 Azure 门户网站很舒服。请记住,大多数在线培训都是针对企业用户的,比您需要了解的更多。假设您对以合理的成本快速获得结果感兴趣,并且企业用户最关心的问题还包括可用性、可靠性和其他“能力”,这些都不是您最关心的问题——您最终会实现的。在本教程中,您将在 Azure 门户中交互创建一些 Azure ML 资源,然后通过 VS-Code 或命令行工具的组合进行开发。我假设你很容易编程和在命令行工作。根据我的经验,我将特别针对我们的任务,将您的 Python 应用程序迁移到云中运行,这是我强烈的个人偏见,以避免常见的陷阱。

为什么要将代码转移到云中的机器上呢?为了规模。Azure 有一些巨大的机器,巨大的网络带宽,和几乎无限的内存。令人惊讶的是,计算量大的应用程序在单台机器上可能比在集群上更快,并且更容易设置。当然,如果你的目标是运行数十亿字节的数据,或者训练十亿节点的神经网络,有合适的虚拟机集群解决方案。无论是通过集群还是大型虚拟机,它对于任何大规模问题都是一个巨大的福音,不仅是传统的机器学习应用程序,而且对于那些大规模的 MCMC 任务或 GPU 上的培训。

云资源

云服务本质上由三种资源组成:计算、存储和网络。您的应用程序资源集合被指定为一个“资源组”——一个用于创建、跟踪和拆除云应用程序的逻辑结构。你的资源组需要包括一个机器学习工作区,一个方便的资源集合,它本身就是一种资源。在 Azure 的图形界面中找到它。

作者图片

继续创建一个。门户提示非常友好,可以为其存储帐户和其他帐户创建新的资源组和新的组件资源。采用默认值,继续创建新的组件资源。只需记住工作区名称,并对您在应用程序中创建的其他资源使用相同的资源组名称。如果你犯了一个错误,很容易删除整个资源组并重新开始。

计算

简而言之,计算由虚拟机(VM)组成,从微小的 VM 映像到具有巨大 RAM 和 GPU 的 VM,比您桌面上的任何东西都大。工作区不附带任何默认计算资源,因为它允许您选择创建单个虚拟机、虚拟机计算集群或使用现有计算资源。对于本教程,您需要通过选择满足您需求的大小来创建一个“计算实例”——单个虚拟机。这些在 Azure Machine Learning Studio (AML)中创建的 Ubuntu 虚拟机是受管理的虚拟机——已经安装了几乎所有需要的软件,并为您管理了更新。这减轻了您设置和配置虚拟机的负担。或者,Azure 仍然提供遗留的“数据科学虚拟机”,这些虚拟机带有大量预安装的 ML 工具,但除了一些特殊目的,(如运行 Windows OS) AML 计算实例可以取代它们。

储存;储备

存储也可以规模化。但与桌面不同的是,主存储不是运行在虚拟机本地磁盘上的文件系统,而是具有访问 API 的独立组件。一个原因是存储是永久的,但虚拟机来来去去;当你需要完成工作的时候启动它们,然后为了省钱把它们拆掉。存储由“blobs”组成,具有持久性和冗余性的强保证。本教程的重点是演示如何集成现有的 Azure 存储,这些存储可能已经加载了您的数据。

建立工作关系网

网络服务连接计算存储。此外,云中的网络由软件定义的虚拟网络组成,这些网络连接到您的本地“内部”设备和云资源。借助云资源,网络将组件与本地子网、安全服务(防火墙)和面向公众的 IP 地址结合在一起。对于连接了存储的虚拟机的简单情况,关联的网络看起来像您的家庭网络,具有公共 IP 地址和子网中的 NAT 地址。您不需要了解太多,因为它已经在您创建 VM 时为您设置好了。我们会谈到这一点。但是应该从存储开始,并将数据存储在存储上。

设置您的开发环境

在云中运行代码所需的工具有:

  • VS-Code——微软的开源 IDE
  • git:开源版本控制

和两个 Azure 资源:

  • Azure 存储
  • 包含计算实例的 AML 工作区。

标题插图显示了这些是如何拼凑在一起的。AML 工作区汇集了一组集成的资源:您只需要两个:受管虚拟机和存储代码的附加存储。此外,你将设置一个 Azure 存储帐户,或使用现有的数据帐户。这不是真正必要的,但学习管理存储是很好的体验。资源设置和管理可以完全在门户中完成。至于代码,你用git把它移动到 AML 版本。然后运行编辑-运行-调试循环,并在本地运行 VS 代码的两个副本。神奇的是,AML 计算实例附加了一个副本,看起来就像是另一个本地实例。

我的重点是使用 VS-Code 进行代码开发,以及它的两个扩展,Azure ML 扩展和 Azure ML-Remote 扩展。安装来自 VS-Code“活动栏”的扩展,可以在最左边的一列中找到,如下所示:

作者图片

使用扩展图标安装两个 VS-Code 扩展。

Azure 图标将用于启动远程会话。

作为一个开源项目,改进和扩展 VS-Code 的势头值得注意,正如其专用博客所说。核心 Python 开发人员可能更喜欢其他专用的 Python 工具,如 PyCharmSpyder ,但是在本教程中,我使用微软的 VS-Code 来实现优雅的项目管理、符号调试和扩展,它们与 Azure 完美集成。由于这些原因,我更喜欢它,而不是微软遗留的 Visual Studio IDE 工具。

所以,如果你还没有 VS-Code,就安装它。

除了你的 Azure 订阅、git和 VS-Code 之外,你还需要az命令行包,称为 Azure 命令行界面(Azure CLI) ,以及它对 Azure 机器学习的扩展,它可以在 Windows 或 Unix shells 上等效地工作。网页上有它的安装程序。

az包管理着每一个 Azure 资源,它的 az 参考页是 Azure 的完整目录。它被实现为 Azure 的 RESTful 管理 API 的包装器。你很少需要直接引用它,因为 VS-Code Extensions 会为你调用az,并在它丢失时提供安装。并且门户公开相同的功能。但是每一个都是命令行工具的语法糖,你应该知道这两个。

从长远来看,了解az的另一个原因是为了编写自动化管理步骤的脚本。每当您在门户中创建一个资源时,它都会为您提供下载“模板”的选项。模板只是你创建的资源在 JSON 中的描述。使用az你可以调用 ARM(Azure 资源管理器)来自动创建它。ARM 是一种用于资源管理的声明性语言,它将资源创建简化为一个命令。详细信息请查看az deployment group create...命令。

az 扩展中特定于 Azure Machine Learning (AML)的命令需要单独安装。第一次使用az mlaz会提示您这样做。

不要把 az CLI 和具有重叠功能的 Azure python SDK 混淆。下面是一个使用 SDK 以编程方式读取存储的示例。您可以用 az CLI 做的大多数事情也在 python azureml包中作为 SDK 公开。

最后,为了检查az是否正常工作,请尝试验证您的本地机器和您的云订阅。当你跑步的时候跟着指示走

$ az login 

你在开始的时候做一次。后续的az命令将不需要认证。

应用程序

好了,您已经得到了代码和数据,并安装了工具。我们开始吧!假设您已经创建了一个新的反洗钱工作区,步骤如下

  1. 设置存储,
  2. 准备你的代码,
  3. 创建 AML 计算实例,并
  4. 启动远程 VS-Code 会话。

当你完成你的代码时,一个选择是通过将它包装在一个“RESTful”API 调用中作为一个 Azure Function 应用程序来部署它。这将您的应用程序公开为一个“端点”,可以从 Web 上调用。构建 Azure 函数可能是另一个教程的主题。

第一件事——准备你的资料。把你的数据保存在云中是值得的。 存储,比如 Azure blob 存储便宜,速度快,容量看似无限;每月每千兆字节的费用约为 2 美分,移动数据也有少量费用。出于成本和网络带宽的原因,您最好将数据一次性转移到云中,而不是在云中针对本地存储的数据运行代码。简而言之,您将创建一个存储帐户,然后创建一个“Azure Data Lake Generation 2”(ADL 2)blob 存储的容器——相当于一个分层文件系统。blob 存储有许多替代方案,甚至有更多的高级选项可以在 Azure 上运行几乎任何你可以想象的数据库软件,但是对于你打算运行的批处理计算,应该从 ADL2 blob 存储开始。

Blob 存储显示为以分层目录结构组织的文件。顾名思义,它将数据视为字节块,与文件格式无关。如果你愿意的话,可以使用csv文件,但是我建议你使用像parquet这样的二进制格式,因为它的压缩、速度和对定义的数据类型的理解。

也许你的数据已经在云端了。如果创建存储的最简单方法不是使用门户—“创建资源”,那么请按照提示进行操作。它不需要与您的工作区在同一个资源组中,选择权在您。您需要做出的一个关键选择是选择“第二代数据湖存储”:

作者图片

本质上,这是一种 blob 存储,它取代了构建在*面文件系统上的原始 blob 存储。注意“Azure Data Lake Gen 1”存储是而不是 blob 存储,原因不值得深入讨论,我将忽略它。

您可以使用此门户页面以交互方式上传数据。这里有一个名为“data-od”的容器的例子从顶级存储帐户页面单击几下,即可导航到存储容器和路径。它包含文件和目录操作命令,很像桌面的“文件浏览器”

作者图片

稍后我将展示如何以编程方式读写存储数据。

在本教程的精益风格中,我只包括了构成 Azure ML 的拜占庭式的特性集合的绝对最小值。Azure ML 有自己的数据存储,或者更准确地说,将现有的 Azure 存储组件包装为“数据集”,向你的表添加元数据,并为你验证存储,这很好。但是,如果您仔细观察,底层存储资源是可以访问的。本教程——围绕这些高级特性的最终运行——即使只做一次,也是理解 Azure ML 存储是如何构成的良好实践。

准备你的代码

与常识相反,我建议你一旦通过了最初的探索性分析,就应该将笔记本代码转换成 Python 模块。如果你坚持使用笔记本,虚拟机就很好:Azure ML 工作空间和 Spark clusters 都允许你运行笔记本,但是你在管理、调试、测试和部署代码方面会受到限制。笔记本电脑非常适合探索您的数据,但是当开发代码供后续使用时,人们会厌倦它们的局限性:

  • 他们和git玩的不好。如果版本之间存在合并冲突,区分它们并编辑冲突是一件非常头疼的事情。
  • 他们得到巨大的曾经填满的数据和图形。要么在提交之前去掉它们的输出,使它们易于管理。或者将它们转换成 html,作为一个可共享的、自文档化的文档。
  • 随着代码的增长,模块化、可调试的面向对象代码的所有优点都消失了。老实说,VS-Code 中的符号调试器值得进行转换,更不用说在单独的模块中按功能组织代码的可管理性了。
  • Python 模块鼓励你构建测试,这是可靠扩展、重用、共享和生产代码的必要实践。

因此,将笔记本电脑归入运行一次的实验,并将代码块升级为易于测试和调试的独立文件。

Jupyter 通过命令行从笔记本中为您生成一个.py文件

$ jupyter nbconvert --to-py <your notebook>.ipynb

依靠 ***git***

值得真正的敬意。随着你的项目规模的扩大和你与他人的合作——使你对你的组织有价值的东西—git是你工作的舒适之家。任何一个软件工程师都知道,如果你“破坏了构建”,只需几个命令就能恢复到工作状态,这是从你的同事的愤怒中得到的最大安慰和喘息。拥有一段有记载的历史也是你给后代的礼物。可以说,git的复杂性让层次文件系统的复杂性相形见绌,但是每次走出git舒适区时,依赖堆栈溢出并不可耻。相信我,有一个git指挥部可以完成任何可以想象的任务。

假设您的代码在您选择的git库中。git将成为您在云与本地文件系统之间来回移动代码的工具。

设置云资源 Azure 机器学习(AML)工作区

我假设您已经创建了一个 AML 工作区。导航到工作区后,有一个按钮可以启动网络版:

作者图片

巡视工作区

Workspace 在一个地方收集了大量与机器学习相关的功能。我将只涉及本教程使用的几个。然而,使用 VS-Code 的好处是你不需要到这里来:你需要在 Studio 中做的一切都可以从 Azure Remote 扩展中完成。

  • 计算实例进入工作区窗格后,在其左侧菜单上有一个“计算”菜单项,它会将您带到一个面板,用于创建新的计算实例。创建一个。您有多种尺寸可供选择,比如 64 核和 128G 内存?还是用 4 NVIDA Teslas?否则,接受默认值也没关系。当实例不被使用时,您可以启动和停止实例以节省资金。
  • 代码编辑在“笔记本”(一个误称)下面,有一个附加到工作区的文件系统视图。它实际上是一个基于 web 的 IDE,用于在必要时编辑和运行代码。它可以包括笔记本、普通 python 文件、本地 git 存储库等等。该文件系统隐藏在工作区的关联 AML 存储中,因此即使删除了计算实例,该文件系统仍然存在。您创建的任何新计算实例都将共享该文件系统。
  • AML 存储Studio 不会透露其连接的 AML 存储帐户,因此可以将其视为存储远程文件系统和其他工件的黑匣子。现在使用外部 Azure 存储——为什么?所以你看到了如何通过存储与其他 Azure 服务集成。你们中最勇敢的人可以使用门户来浏览工作区附带的默认存储。可以通过名称找到存储帐户,名称以工作区名称的任意版本开头,后跟一个随机字符串。

请记住,好的一面是,您需要的所有工作区功能都通过 VS-Code 扩展暴露在您的桌面上。

开发周期

让我们进入有趣的部分——这些组件如何协同工作并提供更好的体验。值得注意的是,当远程使用云资源时,VS-Code 的本地编辑-运行-调试循环几乎是不可区分的。此外,本地和远程 VS-Code 实例同时在您的桌面上运行,这比运行远程桌面服务器(“rdp”)或尝试完全在浏览器中远程工作要流畅得多。多酷啊!

让我们来看一下这些步骤。

本地运行

对云的认证由 VS-Code 的 Azure ML 扩展管理;一旦您启动并运行并连接到您的工作区,您将无需再次进行身份验证。

  • 在 VS-Code 的.vscode文件夹所在的git存储库中的本地目录中启动 VS-Code。(那里的launch.json文件为每个文件配置运行调试会话。学会给它添加配置。)
  • 一旦您对代码在本地运行感到满意,就使用git提交并推送它。如果您提交笔记本,最好先“清理”它们的输出,以保持它们可管理的大小。
  • 从 Azure ML 扩展启动 Azure ML 计算实例。首先使用 VS-Code Activity 菜单中的 Azure 图标(见上文)连接到您的工作区。您可以从隐藏良好的右键菜单项“连接到计算实例”中的本地 VS-Code 实例生成一个远程附加的 VS-Code 实例:

作者图片

这将启动 VM,并在您的桌面上生成第二个 VS-Code 实例,连接到您的远程工作区文件系统!

远程运行

请注意,出现在远程连接 VS-Code 终端窗口中的终端实例正在您的虚拟机上运行!不需要为“putty”或ssh设置一个公钥来打开一个远程 shell。类似地,VS-Code 中可见的文件系统是工作区文件系统。多酷啊!

  • 第一件事当然是通过使用git获取您最*的更改,使工作空间文件系统中的存储库保持最新。然后就像*常一样编辑-运行-调试,但是所有的计算和文件访问都在云中。
  • 当两个 VS-Code 实例都在本地机器上运行时,您可以同时在本地和远程版本之间来回工作,用git传输代码变更。
  • 在远程实例中,Azure ML 扩展菜单自然会被禁用。把一个“远程”衍生到一个“远程”是没有意义的。
  • 完成后,关闭虚拟机以节省资金。您的远程文件系统保存在存储中,无需您做任何事情。

如果您不愿意用git移动文件(您忘记了什么,或者您需要移动一个机密文件),请注意 VS-Code 的远程附加实例可以查看云或本地文件系统,使其成为在它们之间移动文件的“后门”。特意使用git来保持两个文件系统中代码的一致性,所以要谨慎使用这个后门。

或者,可以在门户中调用远程会话。尝试从 AML Studio 笔记本窗格打开本地机器上的远程 VS-Code 会话。

作者图片

如果您的计算实例正在运行,您可以启动 VS-Code 的一个本地实例,该实例远程连接到工作区的文件系统(不仅仅是在门户编辑器中打开的文件)和一个运行在计算实例上的 shell。但是我想你会发现直接从你的本地 VS-Code 实例产生你的远程会话要比在门户的 Azure ML 页面中的 Studio 窗格中启动它更容易。

编程 adl2 文件访问

在云中运行代码需要做的一个改变是替换本地文件 IO。对代码的主要修改是将本地文件系统 IO 调用替换为对用于 Blob 存储的 python SDK 的调用。这既适用于代码在本地运行的情况,也适用于当您将应用程序切换到云中处理数据时在 VM 中运行的情况。

有几种方法可以访问虚拟机的文件。这里有一种使用 Azure python SDK 的方法,它只需要很少的依赖就可以工作,尽管要写很多代码。将这些打包成一个模块,然后将你的努力投入到手边的计算任务中。python SDK 在不同的包中定义了许多类。这个类DataLakeServiceClient是特定于 adl2 blob 存储的。在本地你需要得到这些包裹,

pip install azure-storage-file-datalake 
pip install pyarrow

熊猫需要“pyarrow”。Apache project“arrow”是一种内存数据格式,支持多种语言。

在这个代码片段中,第一个函数返回一个到存储的连接。第二个函数定位文件,以字节字符串的形式检索文件内容,然后将其转换为可以作为 Pandas 数据帧读取的 file 对象。无论您引用您创建的 Azure ML workspace 附带的默认存储,还是 Azure cloud 其他部分中的一些预先存在的存储,这种方法都是一样的。详情见https://docs . Microsoft . com/en-us/azure/storage/blobs/data-lake-storage-directory-file-ACL-python

您可以使用__name__ == '__main__'部分来嵌入测试代码。当您导入文件时,它不会运行。但是当您开发使用这个文件的其他脚本时,您可以用一个已知 blob 的路径来调用这个文件,以测试它没有被破坏。

在存储帐户“访问密钥”窗格中,DataLakeServiceClient使用从门户中恢复的“帐户密钥”字符串对 Azure 存储进行身份验证。帐户密钥是 88 个字符的随机字符串,用作您的存储帐户的“密码”。从该窗格复制它:

作者图片

因为它是机密的,所以它不应该嵌入到代码中,而是隐藏在另一个文件 secrets.py 中,该文件位于只包含全局变量赋值的本地目录中,在本例中是AZURE_STORAGE_ACCOUNTSTORAGE_ACCOUNT_KEYCONTAINER

将文件名放在您的.gitignore文件中,因为这是您不想共享的内容。这是一种加强安全性的简单方法,还有几种更好但更复杂的替代方法。你可以将秘密保存在环境变量中,或者更好地使用 Azure“密钥库”来存储秘密,或者将秘密管理留给 Azure ML。如果您在单独开发代码时小心地管理它们,那么授予帐户密钥是一个简单的解决方案,但是在为企业系统构建代码时,您可能希望使用按钮式身份验证。

类似地,有更多的“代码精简”方法来检索 blobs。如前所述,Azure ML 有自己的瘦包装器和一个为工作区创建的默认存储帐户,在那里可以存储数据。但正如我所说,你会想知道如何连接到任何 Azure 数据,而不仅仅是 AML 管理的数据。客气地说,AML“简化”数据科学基础云服务的倾向并不总是让事情变得更简单,而且当“简单”的服务不符合您的要求时,它可能会隐藏导致混乱的事实。

其他服务、修饰和后续步骤

对于受益于更多处理能力的计算任务,云为分布式计算提供了集群。但是,在跳到分布式处理解决方案的集群(例如 dask )之前,请考虑 python 的多处理模块,它提供了一种利用多核机器的简单方法,并避开了 python 的单线程架构。对于令人尴尬的并行任务,使用模块在多个数据集上运行相同的代码,这样每个任务都在自己的进程中运行,并返回父进程接收的结果。模块导入是

from multiprocessing import Process, Manager

Process类为每个实例生成一个新的操作系统进程,Manager类收集实例的结果。

至于超越一台机器,没有限制。Apache Spark clusters 无缝集成了 Python、R、SQL 和 Scala 中的编码,通过为数据科学量身定制的工具,与庞大的数据集交互工作。Azure 上的 Spark 有几种风格,包括第三方数据块,以及 Spark 和 MSSQL 集群的以数据库为中心的集成,名为“Synapse”。

更多机器学习功能

本文的重点是 Azure ML 中可用的扩展机会,但是我提到 Azure ML 的 ML 特性了吗?除了将开发升级到一定规模的乐趣之外,你已经开始学习使用 Azure 的数据科学工具。为了跟踪和比较多次运行的结果,AzureML 集成了MLFlow。见这篇文章。为了管理数据,AML“数据集”用元数据修饰数据文件。甚至还有一个类似于 python SDK 的 R 的 SDK。有用于实验、运行、环境和模型管理的对象。“AutoML”自动监督学习模型的选择和调整。这只是 Azure ML 如何将服务重新包装为机器学习任务的“一站式”商店的几个例子。

Azure 功能部署及其他

Azure 不仅可以用于大规模运行实验,还可以围绕你的代码构建应用。云应用由运行在独立虚拟机上的网络服务集合组成。为了方便起见,我们避免在“基础架构”级别工作,而转向“托管服务”,在这种情况下,虚拟机不公开,只公开接口,就像我们对托管计算实例所做的那样。通过将代码作为 RESTful http 端点发布到云中,您可以对代码做同样的事情。对于您的客户端来说,它看起来像一个 URL,只是它返回的不是一个网页,而是您的计算结果。构建这个的一个基本方法是将你的代码封装在一个 Azure 函数中。一个 Azure 函数通常在几秒钟内运行,并且不会从一个调用到下一个调用保存状态。(保存状态是 blob 存储的用武之地,记得吗?)实现 http 端点有几种更有特色的替代方案,例如基于 Docker 容器,当然有些可以从 Azure ML Workspace 获得,但都作为托管服务工作,使实现独立于它所构建的*台“基础设施”。如何使用 AFs 值得一个单独的教程,但为了让你开始,加载 Azure 函数扩展到 VS-Code 并浏览它的特性。还记得我说过所有事情的本地管理都带有az吗?我没有告诉你全部真相。对于 AF,你需要为以az func开头的命令单独安装 Azure Functions 核心工具。当你安装 VS-Code Azure Functions 扩展时,VS-Code 会提示你进行安装。

既然你不会因为写代码而放弃,你可以继续与云服务的所有部分集成:数据库、虚拟主机、高级人工智能和安全性——就像你最喜欢的在线零售网站在构建企业 Azure 应用程序时可能已经做的那样。

VS-Code 远程扩展源代码

https://github.com/microsoft/vscode-tools-for-ai
https://github . com/Microsoft docs/azure-docs/blob/master/articles/machine-learning/how-to-management-resources-vs code . MD

Python SDK 参考

https://azuresdkdocs . blob . core . windows . net/$ web/python/azure-storage-file-data lake/12 . 0 . 0 B7/azure . storage . file data lake . html?highlight = datalakefileclient # azure . storage . filedatalake . datalakefileclient

最初发布于https://tech community . Microsoft . com/T5/ai-customer-engineering-team/simple-just-python-in-the-cloud/ba-p/2591940

简单线性和多项式回归

原文:https://towardsdatascience.com/simply-linear-and-polynomial-regression-9c9624774f5a?source=collection_archive---------8-----------------------

使用 Statsmodels、Polyfit、线性回归和多项式特征

图片来自 Unsplash

介绍

回归是预测分析和商业预测中最基本的课题之一。它可以通过线性方式和使用高阶多项式来实现。存在使用多元线性回归生成模型的实例,但是许多真实世界的情况在因变量和自变量之间具有非线性相关性。这就是为什么需要多项式回归。使用样条进行回归也有助于最小化多项式回归的缺点,例如不必要的波动。

用 Python 实现

使用统计模型

为了用 python 实现,我将使用来自这个链接的数据。这是按年龄与鱼长相关的数据。

作者图片

我们希望使用线性和多项式回归来拟合这些数据。使用 statsmodels,可以部署普通最小二乘法(OLS)来拟合数据。我们可以看看拟合的结果。

作者图片

R *方值决定拟合的好坏。最佳实践是绘制残差图来检查异方差,但这里我们将范围限制为仅检查 R *方值。R *方值为 0.735 表示拟合良好,但不是很强。调整后的 R *方值试图抵消添加更多因变量的影响。这里显示了因变量的系数和截距。

作者图片

为了合并高阶项 aka 多项式回归,我们需要实现以下模块。

作者图片

多项式回归的 R *方值为 0.801,比线性回归好。

作者图片

使用 Polyfit

使用 numpy 的 polyfit 类可以实现相同的回归。这种情况下的 R *方值也是 0.801。

作者图片

使用线性回归和多项式特征

使用 sklearn 的基本功能,可以实现线性和多项式回归。

作者图片

这种情况下的 R *方值为 0.735,与之前的方法(使用 statsmodels)相同。对于高阶回归(非线性回归),可以使用下面的代码块。

作者图片

在这种情况下,R *方值也是 0.801。

结论

我们已经尝试了三种不同的方法来实现多项式回归,在所有情况下,我们都得到了相同的 R *方值。对于 python 中的回归分析,所有这些方法都是相似的。对每次执行持续时间的简单测试表明,numpy 的 polyfit 是最快的实现。因此,在处理大数据时,与其他实现相比,polyfit 可能是更好的方法。

简单样条回归:节点间的多项式

原文:https://towardsdatascience.com/simply-spline-regression-polynomials-between-knots-3d007523ad99?source=collection_archive---------21-----------------------

使用 python 的 statsmodels 库

图片来自 Unsplash

简介

线性和多项式回归有一些很大的优点,也有一些缺点。线性回归非常简单且易于实施,而多项式回归则需要更高阶的多项式来拟合数据。多项式回归有一个基本的局限性,它导致一些数据拟合向样条拟合发展。样条回归比多项式回归更复杂,但是这里我将使用 statsmodels 库演示 python 中的样条回归实现。

多项式回归可能在局部数据中过度拟合,因此,如果过度拟合,在预测未来趋势时会产生误导。此外,多项式回归线由样本中的每个数据点全局控制。一个单独的数据点可以剧烈地移动多项式曲线。异常值会改变曲线,因此在进行多项式拟合之前从数据中移除异常值非常重要。我还有一篇关于如何去除异常值的文章。

花键

样条只是整个多项式线的一部分。线被分成几个结,其中每两个结由用户确定的多项式线连接。这基本上消除了单个数据点对全局多项式曲线的影响。

python 实现

在这个简单的代码中,我将展示样条曲线是如何形成的,以及如何控制这些曲线来获得用户定义的输出。让我们用正弦波创建一个虚拟数据集,如下所示。我将用多条样条曲线来拟合这些数据,而不是单一的多项式曲线。

我将把这些数据放在一个 panda dataframe 中,这样我就可以在模型中使用它们作为列。

作者图片

我将使用下面的块实现 statsmodels 样条回归。

这里,基函数采用用户定义的自由度和节点间多项式的次数。然后,将公式输入到模型中。

拟合的 R *方值显示了遵循趋势的样条的强度。R *方值越高,模型拟合越好。显然还有一些其他的因素,比如同质性,但这超出了本文的范围。下面的文章就是为了讨论这个话题而写的。

如果 df = 1,degree = 1,本质上将是一个线性回归模型。

df = 1,度数= 1

将 df 更改为 2 将导致以下拟合。很明显,有两条线有三个结。连接线的顺序仍然是 1,因此,在结之间仍然是线性的。

df = 2,度数= 1

将 df 保持在 2,并将 degree 改为 2 将导致这种情况。

df = 2,度数= 2

现在我们有所收获了。曲线变得更加多项式化,但它离正弦波的良好拟合还差得很远。让我们把 df 增加到 3,degree 增加到 3。每当阶数为 3 时,回归就变成三次样条回归,这是许多分析的默认设置。通常需要 25、50 和 75 个百分点来拟合数据。

df = 3,度数= 3

我们正在到达那里。该曲线有 4 个节点(包括端点),在这些节点之间拟合了三次多项式。如果我们将 degree 放回 1(线性),这一点会更加明显,如下所示。

df = 3,度数= 1

当 df =8 和 degree = 3 时,它变得更符合实际。

df = 8,度数= 3

结论

样条回归不像多项式回归那样具有单个数据点的全局影响的缺点。样条回归中的基本数学更为复杂,其中的结由三次样条或用户定义的结确定。它还消除了由于过度拟合而从多项式回归中产生的不期望的摆动。

参考 : github 功能

Github 页面

posted @ 2024-10-17 11:35  绝不原创的飞龙  阅读(259)  评论(0)    收藏  举报