TowardsDataScience 博客中文翻译 2019(二十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

用 PyTorch 学习迁移学习的实例

原文:https://towardsdatascience.com/a-practical-example-in-transfer-learning-with-pytorch-846bb835f2db?source=collection_archive---------11-----------------------

如何用潜在的小数据集解决计算机视觉问题,并且不需要太多的计算机能力和专门的硬件

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

在这篇文章中,我们将了解迁移学习如何帮助我们解决问题,而无需花费太多时间训练模型和利用预训练的架构。为了了解这是如何工作的,我们将开发一个能够区分竖起大拇指👍拇指朝下👎以高精度实时进行。

什么是迁移学习,什么时候应该使用?

迁移学习是一种技术,在这种技术中,您可以使用经过训练的神经网络来解决特定类型的问题,经过一些更改,您可以重新使用它来解决相关的问题。例如,如果你想开发一个模型来区分汽车和卡车,使用通过 ImageNet 竞赛训练的网络是一个很好的解决方案,并应用迁移学习来微调网络以完成你的任务。

使用这种技术,学习过程可以更快、更准确并且需要更少的训练数据,事实上,数据集的大小和与原始数据集**(网络最初在其中被训练的数据集)的相似性是在应用迁移学习之前要考虑的两个关键因素。有四种情况:**

  1. 小的数据集和与原始的相似:只训练(最后)完全连接的层
  2. 数据集和不同到原始:只训练完全连接的层
  3. 大型数据集和与原始数据集相似:冻结早期的层(简单特征)并训练其余的层
  4. 大型数据集和不同原始:从零开始训练模型,重用网络架构(使用训练好的权重作为起点)。

在网络中,早期层捕获图像的最简单特征(边缘、线条……),而深层层在早期层的组合中捕获更复杂的特征(例如人脸识别问题中的眼睛或嘴巴)。为了微调一个模型,我们需要重新训练最后几层,因为前面几层有对我们有用的知识。

数据集的大小和与原始数据集的相似性是应用迁移学习之前要考虑的两个关键因素

迁移学习的数据收集

首先,我们需要收集一些数据。这些数据需要能够代表我们在真实情况下将要发现的所有案例。在我们的例子中,我们将开发一个能够区分拇指向上或向下的模型。以下是一些收集数据的技巧:

  • 尝试相机前面的不同位置(中央、左侧、右侧、放大、缩小……)
  • 将相机放置在不同的背景中
  • 尝试不同的环境光
  • 用双手

在拍摄快照之前,需要考虑的一个重要方面是我们将使用的网络架构,因为每个图像的大小/形状都很重要

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

Use both hands, try different positions, different angles…

特别是在这种情况下,我在每个班级收集了 114 张图像来解决这个二元问题(拇指向上或拇指向下)。这是一个小数据集,并且与 ImageNet 数据集(在简单特征方面)相似,其中我们要使用的网络被训练(参见下面的部分),因此,小的数据集与原始数据集相似:仅训练最后一个完全连接的层。

网络的输入层需要固定大小的图像,因此我们可以采用两种方法来实现这一点:

  • 拍摄具有所需宽度和高度的图像(通道通常为 3,因为是 RGB 颜色)
  • 拍摄图像,没有任何类型的限制,并根据我们的网络架构将它们重新采样为所需的大小/形状(在训练时间内)。PyTorch 有一个解决这个问题的方法(来源这里)。

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

resize a entire dataset is easy with torchvision

用 PyTorch 转移学习

PyTorch 为我们提供了几个训练有素的网络,可以下载到您的计算机上。这里的是可用的型号。出于我们的目的,我们将选择 AlexNet

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

每种模型在解决特定类型的问题时都有自己的优势。从图像分类到语义分割。一些比另一些更快,运行时需要更少/更多的计算能力。例如,选择 SqueezeNet 需要的参数比 AlexNet 少 50 倍,同时在 ImageNet 数据集上实现相同的精度,因此它是一种快速、较小和高精度的网络架构(适用于低功耗的嵌入式设备),而 VGG 网络架构比 AlexNet 或 SqueezeNet 具有更好的精度,但在推理过程中训练和运行更繁重。下面,您可以看到 PyTorch 在缓存目录中下载的不同网络架构及其大小。

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

different model sizes

到目前为止,我们只谈了理论,让我们把概念付诸实践吧。在 这个 GitHub 页面中,你有所有必要的代码来收集你的数据,训练模型并在现场演示中运行它。

首先,让我们导入所有必需的包

import torch
import torch.optim as optim
import torch.nn.functional as F
import torchvision
import torchvision.datasets as datasets
import torchvision.models as models
import torchvision.transforms as transforms

现在我们使用 torchvision.datasets 包中可用的 ImageFolder 数据集类。我们附加转换以准备用于训练的数据,然后将数据集分成训练测试

dataset = datasets.ImageFolder(
    'dataset',
    transforms.Compose([
        transforms.ColorJitter(0.1, 0.1, 0.1, 0.1),
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])
)
train_dataset, test_dataset = torch.utils.data.random_split(dataset, [len(dataset) - 50, 50])

我们将创建两个 DataLoader 实例,它们提供了用于混排数据、生成批量图像以及使用多个 workers 并行加载样本的实用程序。

train_loader = torch.utils.data.DataLoader(
    train_dataset,
    batch_size=16,
    shuffle=True,
    num_workers=4
)

test_loader = torch.utils.data.DataLoader(
    test_dataset,
    batch_size=16,
    shuffle=True,
    num_workers=4
)

现在,我们定义将要训练的神经网络。alexnet模型最初是为有 1000 个类标签的数据集训练的,但是我们的数据集只有两个类标签!我们将用一个新的、未经训练的、只有两个输出(👍和👎).

model = models.alexnet(pretrained=True)
model.classifier[6] = torch.nn.Linear(model.classifier[6].in_features, 2)

现在,是时候训练神经网络并尽可能以最佳性能保存模型了。请随意尝试不同的超参数,看看它的表现如何

NUM_EPOCHS = 10
BEST_MODEL_PATH = 'best_model.pth'
best_accuracy = 0.0

optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

for epoch in range(NUM_EPOCHS):

    for images, labels in iter(train_loader):
        images = images.to(device)
        labels = labels.to(device)
        optimizer.zero_grad()
        outputs = model(images)
        loss = F.cross_entropy(outputs, labels)
        loss.backward()
        optimizer.step()

    test_error_count = 0.0
    for images, labels in iter(test_loader):
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        test_error_count += float(torch.sum(torch.abs(labels - outputs.argmax(1))))

    test_accuracy = 1.0 - float(test_error_count) / float(len(test_dataset))
    print('%d: %f' % (epoch, test_accuracy))
    if test_accuracy > best_accuracy:
        torch.save(model.state_dict(), BEST_MODEL_PATH)
        best_accuracy = test_accuracy

仅此而已,现在我们的模型能够实时分类我们的图像了!

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

进一步工作:

为了提高模型性能,以下是一些在未来工作中可以尝试的方法:

  • 收集具有不同背景的图像来改进(概括)我们的模型
  • 从不同的人那里收集图像添加到数据集
  • 当你没有竖起或放下拇指的时候,也许可以增加第三类

[## 大卫塔纳-概述

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

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

参考文献

[## NVIDIA-AI-IOT/jetbot

有兴趣和杰特森纳米一起做这样的项目吗?查看我们于 2019 年 5 月 16 日发布的网络研讨会!JetBot 是一个…

github.com](https://github.com/NVIDIA-AI-IOT/jetbot)

AlexNet paper

用 Docker 在 AWS 云中训练神经网络的实例

原文:https://towardsdatascience.com/a-practical-example-of-training-a-neural-network-in-the-aws-cloud-with-docker-b44a8c061e6e?source=collection_archive---------23-----------------------

如何在 AWS GPU 实例上的 Docker 内在 CIFAR-10 上的 InceptionV3 模型之上训练浅层神经网络

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

我的上一篇文章数据科学过程中 Docker 的用例示例是关于数据科学中的 Docker。这次我想用一个实际的例子来弄脏我的手。

在这个案例研究中,我想向您展示如何在 AWS 上 Docker 容器内的 CIFAR-10 图像上的深度 InceptionV3 模型之上训练一个浅层神经网络。我正在为这个项目使用 Python,Tensorflow 和 Keras 的标准技术栈。这个项目的源代码可以在 Github 上获得。

您将从本案例研究中学到什么:

  • 从 docker-machine 命令行设置 AWS 上支持 GPU 的云实例
  • 在您的 docker 文件中使用 tensorflow docker 图像
  • 使用 docker-compose 设置用于训练神经网络的多容器 Docker 应用程序
  • 将 MongoDB 设置为持久性容器,用于模型的训练元数据和文件存储
  • 用 MongoDB 实现简单的数据插入和查询
  • 一些简单的 docker、docker-compose 和 docker-machine 命令
  • 卷积神经网络的迁移学习

让我们定义这个小项目的要求:

  • 培训必须在 AWS 中的一个支持 GPU 的实例上进行
  • 灵活地将整个培训管道移植到谷歌云或微软 Azure
  • 使用 nvidia-docker 在云实例上激活完整的 GPU 能力
  • MongoDB 上模型元数据的持久性以实现模型的可复制性。
  • 多容器应用程序(训练容器+ MongoDB)的 docker-compose 用法
  • 使用 docker-machine 管理云实例,并通过 docker-compose 从本地命令行开始培训

让我们潜入更深的地方。

1.先决条件

  1. 安装 Docker 连同 Docker MachineDocker 组成(工具安装在 Mac 和 Windows 上的标准 Docker 安装中)
  2. AWS 上创建账户
  3. 安装和设置 AWS 命令行客户端

2.AWS 实例作为 Docker 运行时环境

要在 AWS 上训练神经网络,首先需要在那里设置一个实例。你可以从 AWS Web 控制台或者从命令行使用 AWS 命令行客户端来完成这项工作。

我用 docker-machine 命令向您展示了第三种方便的方法。该命令包装了不同云和本地提供商的驱动程序。通过这种方式,你可以获得谷歌云计算、微软 Azure 和亚马逊 AWS 的独特界面,这使得在平台上设置实例变得容易。请记住,一旦建立了实例,您就可以出于其他目的重用它。

我正在用 Ubuntu 18.04 Linux(ami-0891 F5 DC c59 fc 5285)创建一个 AWS 实例,它已经安装了 CUDA 10.1nvidia-docker 。这些组件是为培训启用 GPU 所必需的。AMI 的基础是一个标准的 AWS Ubuntu 18.04 Linux 实例(ami-0a313d6098716f372),我用这些组件对其进行了扩展。我把这张照片分享给公众,让生活变得更容易。

我使用 p2.xlarge 实例类型,这是 AWS 上最便宜的 GPU 实例。p2.xlarge 实例类型为您配备了 Tesla K80 的 GPU 能力。

docker-machine create --driver amazonec2\
 --amazonec2-instance-type p2.xlarge\ 
 --amazonec2-ami ami-0891f5dcc59fc5285\ 
 --amazonec2-vpc-id <YOUR VPC-ID>\
 cifar10-deep-learning

你需要一个 VPC 身份证来设置。您可以使用 AWS 命令来获得它:

您也可以从 AWS Web 控制台获取 VPC ID

有关更多信息,请查看带 AWS 文档的对接机。

警告:p2.xlarge 每小时收费 0.90 美元。请不要忘记在完成培训课程后停止实例

3.培训脚本

您希望使用不同的训练参数来训练神经网络,以找到最佳设置。训练之后,您在测试集上测试模型质量。这是一个分类问题。为了简单起见,我建议使用准确性度量。最后,您将训练日志、模型权重和架构持久化,以备将来使用。这样一切都是可复制和可追踪的。

你可以通过用你的浅层网络替换基本模型的顶层来进行迁移学习,然后你冻结基本模型的权重并在整个网络上进行训练。

在这个案例研究中,我的做法有所不同。我正在移除基本模型的顶层,然后将图像输入到基本模型中,并在 MongoDB 中持久化结果特性。预测比训练需要更少的计算能力,一旦提取出瓶颈特征,我可以重用它们。你在瓶颈特征上训练浅层网络。

培训脚本的输入和输出要求:

输入

Docker 容器是从 MongoDB 集合参数化而来的,其中包含一个训练会话的所有参数。

  • 损失函数
  • 乐观者
  • 批量
  • 时代数
  • 用于训练的所有样本的子集百分比(用于使用较少图像测试管道)

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

输出

  • 模型架构文件
  • 模型权重文件
  • 培训课程日志
  • 测试集上的模型准确性

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

我将整个培训管道放在一个脚本 src/cnn/cifar10.py 中,它由整个培训管道的一个类组成:

  1. 将 CIFAR-10 映像下载到容器文件系统。
  2. 加载带有 imagenet 权重的基础模型(InceptionV3)并移除顶层
  3. 训练图像和测试图像的瓶颈特征提取:保持 MongoDB 中的特性以备将来使用。
  4. 浅层神经网络的创建和编译;在 MongoDB 中持久化模型架构
  5. 浅层模型的训练;MongoDB 中模型权重和训练日志的持久化
  6. 测试集上的模型测试;在 MongoDB 中保持准确性度量

4.集装箱化

a.)Dockerfile

训练神经网络所需的一切我都放入了 Dockerfile,它定义了训练的运行时环境。

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

第 1 行:基础图像的定义。设置和配置继承自该映像。用的是官方的 tensorflow 图,有 python3 和 GPU 支持。

第 3 行:本地目录 src 中的所有内容,像训练脚本和入口点,都被复制到 Docker 映像中。

第 5 行:容器在 src 目录下启动

第 7 行:python 安装需求

第 9 行:将 src 目录添加到 PYTHONPATH 中,告诉 python 在这个目录中寻找模块

第 11 行:图像入口点的定义。这个入口点脚本在容器启动时执行。这个脚本启动了我们的 python 训练脚本。

入口点 shell 脚本非常简单明了:它不带参数启动 python 模块。该模块在启动时从 MongoDB 获取训练参数。

b.)Docker 容器构建

首先,我需要建立一个码头工人的形象。你可以跳过这一步,因为我在 Docker Hub 上分享了现成的 Docker 映像。第一次引用图像时,会自动下载该图像。

c.)多容器应用程序

我的设置中有两个 docker 容器:一个用于训练的 Docker 容器和一个用于保存元数据和作为文件服务器的 MongoDB。

在这个场景中使用 docker-compose。您在 docker-compose.yml 中定义了构成应用程序的容器

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

第 4–5 行:使用带有标签 0.1.0-GPU 的 jenslaufer/neural-network-training-with-docker 图像的训练容器的定义。该图像自动从公共 Docker Hub 库下载

第 7 行:tensorflow 的运行时环境

第 9 行:训练容器需要 trainingdb 容器来执行。在代码中,您使用 mongodb://trainingdb 作为 Mongo URI

第 11–12 行:MongoDB 数据库的定义。来自 Docker Hub 的官方 mongo 镜像用于版本 3.6.12

第 14–15 行:内部端口 27017 在外部端口 27018 可用

第 16 行:Mongo 守护进程启动

您可以看到,使用 docker compose 设置多应用程序非常简单——只需几行代码就可以设置一个数据库,而无需复杂的安装例程。

5.训练神经网络

您需要执行这个命令来确保 docker 命令是针对我们的 AWS 实例的:

docker-machine env cifar10-deep-learning

之后,您可以列出您的计算机

NAME                  ACTIVE DRIVER    STATE   
cifar10-deep-learning *      amazonec2 Running

确保您看到活动环境的星号。这是所有 docker 命令执行的环境。请记住,您是在本地 shell 中执行命令的。很方便。

现在,您可以第一次启动容器。

Docker 将所有图像下载到 AWS 实例。MongoDB 启动并一直运行,直到您停止容器。用对接器训练的神经网络执行训练模块。该模块从 MongoDB 获取训练会话,MongoDB 在第一次启动时是空的。集装箱在完成培训课程后停止。

让我们添加培训课程参数。

为此,您登录到 MongoDB 容器(本地 shell 中的所有内容):

你打开 mongo 客户端。然后使用 use 命令选择 DB“training”。然后,您可以添加一个只有 5%图像的训练会话,一个批量大小为 50 和 20 个时期的 rmsprop 优化器。如果一切顺利,这是一个快速测试。

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

您离开 MongoDB 并重启容器:

现在的问题是你看不到发生了什么。您可以使用 docker log 命令获取 docker 容器的日志。

docker logs -f neural-network-training-with-docker

现在,您可以通过这种方式在本地机器上跟踪远程 docker 容器上的培训会话。

6.模型评估

您可以使用 MongoDB 快速比较不同培训课程的结果,因为我在测试集上保存了所有参数和准确性度量。数据库的优点是可以对其执行查询,这比将结果保存在 CSV 或 JSON 中要好得多。

让我们列出精确度最高的三个模型。

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

您还可以在数据库中查询特定培训课程的模型文件。您可以看到,您拥有模型架构和权重的 hdf5 文件。还有一个包含培训历史的 JSON 文件,您可以使用它来分析培训本身。它可用于可视化培训过程。

您可以从 MongoDB 自动加载最佳模型,并将其发布到 Flask、Spring Boot 或 Tensorflow 应用程序中。

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

您可以使用 mongofiles 命令将文件下载到本地文件系统:

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

结论

在本案例研究中,您使用 docker-machine 从命令行在 AWS 上设置了一个支持 GPU 的云实例。目标是用额外的计算能力更快地训练神经网络。该实例可重复用于其他培训容器。

在下一步中,您实现了一个脚本,其中包含了在具有迁移学习的 InceptionV3 模型之上训练一个浅层全连接神经网络所需的所有步骤。该脚本使用 MongoDB 实例作为持久层来存储训练元数据和模型文件。您创建了一个 Dockerfile,其中包含在 GPU 云实例上使用 Tensorflow 训练网络所需的基础设施。然后,您在 docker-compose 文件中定义了一个多容器设置,包括 training 容器和 MongoDB 容器。

你在 Docker 的 AWS 云上训练了神经网络。您从本地命令行开始培训。您从本地命令行登录到 MongoDB 来添加培训会话,并在之后了解培训会话。

改进流程的后续步骤:

  • 浅层神经网络的结构是硬编码的。最好也从持久层加载它。
  • 使用除 InceptionV3 之外的其他基本模型的一般方法
  • 您使用了准确性度量来测试模型的质量。最好是找到一种更通用的方法来持久化更多的度量。
  • 您使用了带有默认参数的优化器。一个改进是一般地加载优化器特定的参数。
  • 目标可能是从容器中移除 python 脚本,并在 docker-compose 文件中的环境变量的帮助下,将它作为 Python 模块从入口点脚本的存储库中加载。

您需要关于数据科学设置的建议吗?

请让我知道。给我发一封 邮件

原载于 2019 年 4 月 23 日【https://jenslaufer.com】

应用人员分析的实用指南

原文:https://towardsdatascience.com/a-practical-guide-to-apply-people-analytics-f0d08bc231cc?source=collection_archive---------23-----------------------

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

人员分析是人力资源领域的新热点。然而,尽管人力资源领导热情地谈论它,但很少有公司能够应用它并从中受益。在 Graphext ,我们一直在与客户合作实施各种人员分析计划,以推动行为改变。在本文中,我想分享我们工作中的一些收获,特别是关于如何以实用有效的方式应用人员分析。

给你一点背景,我们的大部分客户来自服务行业,他们的业绩与他们的员工紧密相连。其中许多公司认识到利用数据科学提高盈利能力的潜力,并正在采取积极措施将不同的解决方案融入日常运营中。

不管行业、规模和地理位置如何,以下是公司在应用人员分析时面临的一些常见挑战:

首先,收集数据的困难。员工数据经常驻留在不同的系统上,并且不能很好地同步。与公司更愿意投资的客户数据不同,员工数据通常被放在次要位置,底层数据基础设施也没有得到很好的开发。因此,在进行任何分析之前,公司需要花费大量时间来收集和清理这些数据。

其次,缺乏人才。要正确应用人员分析,您需要平衡技术(编程和统计)和人力资源知识。这种技能非常罕见,很难找到。公司经常不得不在没有技术经验的人力资源专家和没有商业背景的技术人员之间做出选择。两者都有缺点。

最后,根据建议执行不力。许多公司非常乐意进行分析,但未能贯彻执行建议。没有执行,您就看不到建议的结果,没有结果,您就无法提供有洞察力的反馈来验证分析是对还是错。

尽管面临这些挑战,我们的许多客户成功地使用人员分析来提高他们的业务绩效。以下是我们从他们身上观察到的一些最佳实践。

首先,将你的分析与具体的业务目标联系起来。这是关于寻找可能对您的业务产生最大影响的用例。你可以运行许多很酷的分析,但是哪一个在今天产生商业结果方面最有效呢?

在这里,我们总结了一个最常用的人分析用例列表,深受我们客户的喜爱。大多数都是简单直接的分析,但是非常有效。

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

除了上面的用例,我们还看到公司在多元化研究、职业道路甚至组织网络中运行分析。这些用例很好探索,但是在现实中,基于分析实现任何改变是非常困难的,并且影响往往是长期的和无形的。如果你正在寻找唾手可得的果实和立竿见影的效果,我建议你首先跳过它们。

其次,将人员分析整合到您的日常运营中。许多公司每年只运行一次人员分析项目来设定年度目标,之后就放弃了。这种想法很危险。有了这么多的机会,人们换工作的速度比以往任何时候都快。看到一家服务公司有 20%的离职率并不奇怪,在最优秀的员工中,这个数字甚至更高。从发现问题到制定计划并实施变革的机会之窗非常短暂。

我们见过的最好的公司都在持续地运行他们的核心人员分析。此外,他们还定期试验和探索有趣的主题,以添加到他们的分析组合中。开发一个分析组合,并建立一个连续的项目路线图,将有助于将数据驱动的文化嵌入到您的组织中,并对您的公司绩效产生更大的影响。

最后,建立一个从执行到分析的有效反馈回路。一旦你在分析的基础上实施了你的策略,不管你是否看到了影响,收集结果并把它作为输入来改进你的分析是非常重要的。数据科学基于试错的思想。从长远来看,反馈环将帮助你改进和完善你的分析技术。

希望你喜欢阅读。下面是我关于数据科学的其他文章:

为什么我们必须让数据科学民主化

构建数据驱动的文化

针对您的客户洞察团队的顶级分析

关于数据科学,Kaggle 调查告诉了我们什么

为投资分析构建企业知识图的实用指南

原文:https://towardsdatascience.com/a-practical-guide-to-build-an-enterprise-knowledge-graph-for-investment-analysis-3a15363098b7?source=collection_archive---------12-----------------------

如何解决构建真正的企业知识图谱服务时的实际问题

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

Photo by Peter Nguyen on Unsplash

这是一篇关于在开发企业知识图(EKG)服务时如何解决挑战的应用论文,该服务整合了大约 40,000,000 家公司的信息。如果有人想为真正的商业建立一个 EKG,我发现这篇文章非常实用。所以我写这个总结是为了节省你的时间。如果你想知道细节,我推荐你直接看报纸。PDF 这里是这里是

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

from connected-data-london-as-a-graph

这项 EKG 服务出售给证券公司。由于证券公司提供投资银行服务和投资咨询服务,他们必须了解中小企业的信息。因此,该产品可以帮助证券公司更好、更快地了解和接近目标公司。

在这个项目中有两种挑战,技术挑战和业务挑战。

业务挑战

在商业方面有两个挑战。

  • 数据隐私:如何在不侵犯公司及其员工隐私的情况下,提供深度有用的分析服务。
  • 黑仔服务关于图表:EKG 复杂而庞大,如何让图表易于使用是一个挑战。

两大挑战的解决方案。

数据隐私 :
-将原始数据转换为秩形式或比率形式,而不是使用真正精确的值(秩形式或比率形式?)
-在将 EKG 可视化为图形时,隐藏不应显示的关键节点(例如,与人相关的信息)

图上的黑仔服务:
——提供直接满足用户业务需求的服务。例如,寻找企业真正控制者的服务告诉投资银行的投资者谁是公司的真正所有者,而企业路径发现服务提供了投资者如何到达他们想要投资的企业的提示。

技术挑战

数据来源的多样性和规模带来了技术挑战。

-构建问题,如将数据库转换为 RDF (D2R),当涉及元属性和 n 元关系时表示和查询困难
-性能问题,因为 KG 包含超过 10 亿个三元组

在详细介绍挑战之前,让我们先看看构建 EKG 的整个工作流程。

  • 在项目的第一阶段,我们主要利用 CSAIC 的关系数据库(RDB)。
  • 其次,我们用中国政府采购网(CGPN)的投标信息和东方财富网(EWN)的股票信息补充 EKG。
  • 然后,在另一个项目中,EKG 与从国家知识产权局专利检索和分析网络(PASN-SIPO)提取的专利信息融合。
  • 最后,将竞争对手关系和收购事件添加到 EKG 中。这些信息摘自百科网站,即维基百科、百度百科和互动百科。

在上述过程中会遇到以下挑战:

  • 数据模型(复杂数据类型):元属性(关系的属性,或属性图)和事件(n 元关系)。但是目前还没有成熟的解决方案来有效地表示和查询元属性和事件。
  • D2R 映射:使用 D2R 工具(例如,D2RQ9)将 RDB 从 CSAIC 映射到 RDF 具有以下挑战:a)元属性的映射。b)RDB 的同一列中的数据映射到 RDF 中的不同类。c)相同 RDB 表中的数据可以映射到具有子类关系的不同类。
  • 信息提取:从各种类型中提取有用的关系,如“竞争”、“收购”等。当百科网站中存在公司名称的缩写时,实体提取变得困难。
  • 查询性能:我们遇到了性能瓶颈,因为我们的 EGK 的三元组数量已经达到了数十亿。此外,当 EKG 使用场景增加时,会有更复杂的查询模式:a)当用户查询 IPC 代码上的 KG 时,我们应该递归地找到 IPC 代码的所有
    子类,然后找到属于这些子类的专利。b)查询实例的所有属性。由于同一实例的不同属性可能在图形存储中存储为不同的三元组,因此出现了问题。c)元属性和 n 元关系的查询。

作者仔细选择最合适的方法,并使它们适应上述问题。

  1. 首先,我们将原始表分成原子表和复杂表,然后我们使用 D2RQ 工具来处理原子表上的映射。最后,我们开发了程序来处理复杂表上的特殊映射。
  2. 我们在[16]( Bootstrapping yahoo!由维基百科资助用于竞争对手挖掘)来从百科网站的各种数据源中提取竞争对手关系和收购事件。
  3. 我们采用文献[2]中基于图的实体连接算法(图排序用于集体命名实体消歧)来完成实体连接任务。
  4. 我们设计了自己的存储结构来充分优化 EKG 中各种查询的性能。我们使用由多种数据库组成的混合存储解决方案。对于大规模数据,我们使用 NoSQL 数据库即 Mongodb 作为底层存储。对于高频查询数据,我们使用内存数据库来存储数据。

方法概述

构建 EKG 的数据源和相关任务

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

Building EGK from multiple sources :Aluminum Corporation of China Limited Example

此图举例说明了从多个来源提取中国铝业有限公司示例的信息的过程。

  • 首先,他们使用 CSAIC 中的中国铝业有限公司示例数据作为基本千克。然后,他们将 RDB 转换为 RDF,形成基本的企业 KG,并得到 triples like(中国铝业股份有限公司,董事,熊维平)。
  • 其次,他们从一个专利网站上提取专利信息,建立一个专利 KG。基础企业 KG 由 CSAIC 转型而来。这两种 kg 服务于不同的用户。因此,他们使用数据融合算法将两个 kg 与公司和个人联系起来。
  • 最后,他们从股票网站中提取股票代码,从百度百科和维基百科的 infobox 中提取公司高管,从百科网站的免费文本中提取收购事件。

构建知识图表

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

Data-driven KG constructing process

整个构建过程有 5 个主要步骤:模式设计D2R 变换信息提取数据融合与实例匹配、存储设计和查询优化

1.模式设计

虽然大多数通用知识库(如 DBpedia 和 YAGO)是以自下而上的方式构建的,以确保跨域数据的广泛覆盖,但作者在 EKG 构建中采用了自上而下的方法,以确保数据质量和更严格的模式。

在第一次迭代中,EKG 包括四个基本概念,即“公司”、“人”、“信用”和“诉讼”。主要关系包括“子公司”、“股东”和“高管”。专利 KG 中的概念只包括“专利”。主要关系是“申请人”。在第二次迭代中,我们将“上市公司”、“股票”、“投标”和“投资”添加到 EKG 中。

2.D2R 变换

作者采取三个步骤将 RDB 转换为 RDF,即表分裂、D2RQ 的基本 D2R 变换和后处理。

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

  • 分表:如图 4 所示,原表人员信息也包含企业信息。我们将表格分为 Person_PEnterprise_EPerson Enterprise_PEEnterprise_E 表与原来的企业信息表进一步合并,因为这两个表共享相似的企业信息。
  • D2RQ 的基本 D2R 变换:我们用 D2RQ 编写一个定制的映射文件,将与原子实体表和原子关系表相关的字段映射成 RDF 格式。我们将表名映射到类中,将表的列映射到属性中,并将每个记录的单元格值映射为给定实体的相应属性值。
  • 后处理:a)元属性映射。该程序为具有元属性的事实提供了一个自增加的 ID 注释。然后,元属性将是由该 ID 标识该 n 元关系的属性。因此,我们得到一些新的三元组(例如)。b)条件分类映射。我们的程序根据实体是否出现在与子类相关的表中来确定实体是否映射到子类。例如,如果一家公司存在于公司和股票的关系表中,这意味着该公司是一家上市公司,因此我们添加了一个三元组

3.信息提取

作者采用多策略学习方法从各种数据源中提取多种类型的数据。整个过程如下:

  • 通过使用 HTML 包装器,分别从 PSAN 国家知识产权局、EWN 和 CGPN 提取专利、股票和投标信息的实体和属性值对。
  • 通过使用 HTML 包装器,从百科全书站点的信息盒中提取企业的属性值对(例如,企业的董事长)。
  • 自由文本上的二元关系、事件和同义词识别需要句子中的种子标注来学习模式。

对于公司名称缩写的问题,作者使用实体链接算法将文中提到的公司链接到基本 EKG 中的公司。他们采用基于图形的方法分两步完成实体链接的任务:

  • **候选检测:**在知识库中寻找每个提及所涉及的候选实体。它删除后缀(Corp. Co. Ltd,Group)来计算提及的核心作品与实体的核心词之间的相似度(以 KB 为单位)。
  • **消歧:**选择最可能的候选链接。这里,我们使用文献中提出的消歧算法(集体命名实体消歧的图排序)

4.具有实例匹配的数据融合

问题很简单,比如公司的匹配。然而,问题是棘手的,例如人的匹配。虽然每个人都有个人 ID 号,但在专利数据源中没有这样的 ID。作者使用一个简单的启发式规则来匹配专利 KG 中的人和基本 KG 中的人。如果专利发明人和申请人的名字分别等于基本 KG 中的人和公司的名字,他们说专利发明人与基本 KG 中的人的名字相匹配。

5.存储设计和查询优化

作者使用 MongoDB 作为主要存储,因为它拥有庞大的安装基数、良好的查询性能、海量数据存储以及支持集群的可伸缩性。

部署和使用场景

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

本节讲述如何使图表易于使用。作者为一些用例预定义了一些查询。

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

Different structures for a person to control an enterprise

  • 寻找企业的真正控制者。拥有最大股权份额的人是真正的决策者。但是图案很多,见上图。
  • 创新企业分析。看公司的专利。
  • 企业路径发现。证券公司想知道是否有途径到达他们的新客户,他们也想知道他们的潜在客户是否有途径到达他们的竞争对手。
  • 多维关系发现。给定两家公司,它们之间可能存在不同的关系。

最后,如果你需要为真正的商业建立一个 KG,我强烈推荐你阅读这篇文章。

查看我的其他帖子 一个分类查看
GitHub:
bramble Xu LinkedIn:徐亮 博客:bramble Xu

参考

其他与知识图表相关的帖子:

解释和可视化支持向量机的实用指南

原文:https://towardsdatascience.com/a-practical-guide-to-interpreting-and-visualising-support-vector-machines-97d2a5b0564e?source=collection_archive---------0-----------------------

SVM 通常被认为是“黑匣子”。在这篇文章中,我们涵盖的技术,以可视化学习 SVM 模型和他们的现实世界的数据表现。

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

Image Shot by Hugo Dolan

关于作者

Hugo Dolan 是都柏林大学金融数学系的本科生。这主要是基于最近在 NFL Punt Analytics Kaggle 比赛中的数据分析和机器学习体验,以及成为赢得 Citadel Dublin Data Open 的团队的一部分,以及斯坦福大学 CS229 在线课程的材料。

本文包含以下章节:

  1. 线性模型、SVM 和核的介绍
  2. 解释利用 SVM 核的高维工程特征空间…
  3. 评估高维分类边界性能的技术
  4. 处理大规模阶级不平衡的实际选择
  5. 训练一只 SVM 需要多少数据

我会做一些假设:

本文将假设熟悉基本的 ML 模型,如逻辑和线性回归。它还假设你知道如何绘制我讨论的一些图表(如果你卡住了,我有一个指南)。).我们还假设你知道什么是决策函数和目标/成本函数,并且你有一些基本的线性代数知识。如果不是,它仍然值得一读,你可以把它收藏起来,以后再回来深入阅读这篇文章中更数学化的部分。

线性模型、SVM 和核的介绍

在机器学习中,线性分类器是其中存在单个假设函数的任何模型,该假设函数在模型输入和预测输出之间映射。

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

Many models such as Logistic regression, Naive Bayes and Discriminant Analysis to name a few, are all examples of linear models.

线性模型相对于神经网络(非线性模型)的主要优势在于特征权重直接对应于模型中特征的重要性。因此,很容易理解模型已经“学习”了什么。

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

Training a L1 Regularised Regression model it is immediately obvious that most of our features in our dataset are totally irrelevant to predicting our output. It is clear that features 0,1 make positive contributions to the model, whilst the presence of features 2,3,4 in a given example result in negative contributions to the output

任何线性模型的核心都是输入示例和参数/权重向量之间的点积。在线性回归的情况下,这是整个假设函数。其中逻辑回归通过 sigmoid 函数提供点积,使得输出在 0 和 1 之间,因此适用于二元分类问题。

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

当考虑分类问题时,线性模型的缺点是最终决策边界是一条直线、平面或超平面,其系数等于模型权重/参数,因此只能对可线性分离的数据进行分类,这在处理更复杂的分析问题时可能是一个很大的限制。

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

As we can see the simple linear model cannot separate the two ‘Noisy Hyperbola’ as it can only fit a ‘straight’ plane / line through the data. The second example uses a non linear model (actually a kernel trick, we’ll get to this soon)

支持向量机(SVM)是唯一可以对不可线性分离的数据进行分类的线性模型。

您可能会问,SVM 是一种线性模型,如何将线性分类器应用于非线性数据。凭直觉,利用简单的线性回归模型,我们可以手动设计 x,x,x…特征,以尝试实现对一组非线性数据点的拟合。

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

Whilst feature X is the only independent variable we have to predict y, which has an inherently non linear relationship with x, we can engineer x² and x³ features to improve our fit to y.

将这种直觉转移到我们的 SVM,当我们设计 x 特征时,我们本质上是将特征 x 乘以它本身。因此,假设我们通过将特征 x1、x2、x3…的组合相乘来设计数据集的特征,那么理论上我们可能最终得到一个空间,在该空间中,您设计的特征是线性可分的。以前面的简单例子为例,看看下面的数据是如何在 x 特征空间中转换成几乎线性的趋势的。

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

As a further intuition towards the previous example, we can see by transforming the x-axis from the original feature space of x up to the feature space of x³ how the model could be seen as a linear relationship between x³ and y.

不幸的是,要用复杂的数据集实现这一点,需要创建的不仅仅是 3 维空间(特征 x,x,x ),而是实际上非常高维的特征空间,这对于我们数据集中的每个例子来说计算起来都是非常昂贵的。下面我展示了一个函数(x)的例子,它采用我们的原始特征 x,并将它们组合起来以创建许多二阶多项式特征。

在我们继续之前:我将使用 x 符号来表示数据点/训练示例,用上标来表示特定的数据点,用下标来表示特定的特征。

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

This is a typically high dimensional space, if we had 100 features originally then this function would produce 100 * 100 engineered features. This is computationally expensive, in this case Big-O(n²) time complexity, think of having to write two nested for-loops to generate all the combinations produced by ø(x).

幸运的是,我们有办法解决这个计算复杂性难题!当我们推导 SVM 的优化问题(复杂的公式告诉我们如何在坐标上升过程中推导和更新我们的权重以实现最大化)时,结果是我们的训练输入 x 的特征向量只出现在整个优化公式中的一个地方(以红色突出显示)。

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

这个点积是用于我们的原始特征空间的,所以现在让我们用我们的工程特征空间替换它。

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

那么这如何有助于降低计算复杂度呢?根据点积的定义,我们将(x(i))的第 I 项乘以(x(j))的第 I 项,然后将所有这些相加,得到一个标量。应用这个我们得到:

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

As if by magic we can remove the need to compute ø(x) completely by simple algebraic manipulation by the kernel trick. Now we have all the benefits of a high dimensional feature space without the additional computational complexity

内核技巧是对原始方程的一种非常简单的重新排列,我们可以看到,我们已经完全移除了(x ),只需使用原始输入特征来执行计算,但仍然具有计算高维空间的效果。

我们现在所要做的就是用核等价体(K(xi,xj)代替涉及(x)的点积:

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

Simple substitution, note that our Kernel is using x and z here just to remove the superscript notation.

类似地,当我们想要使用我们的模型来进行预测时,我们从不明确地计算高维空间的权重,而是使用核技巧来进行预测:

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

在总结中,我们可以使用内核技巧将非线性数据集转换成线性可分的数据集,就在高维空间中。Sklearn 在 SVC 实现中预装了许多内核,包括半径基内核(RBF)和多项式内核,每个内核都有自己的超参数,可以使用交叉验证进行实验调整,以获得最佳结果。

一个小故障,解释高维工程特征空间…

还记得我们说过线性模型的最大好处是模型的权重/参数可以解释为特征的重要性。一旦我们设计了一个高维或无限维的特征集,模型的权重就隐含地对应于高维空间,这对我们的理解没有帮助。

相反,我们可以做的是拟合逻辑回归模型,该模型估计给定原始特征时标签 y 为 1 的概率,其中 f(x)是 SVM 决策函数:

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

If this looks familiar it is, think logistic regression!

我们使用最大似然估计来拟合这个逻辑回归模型的参数,这种技术被称为普拉特标度,如果你对内部工作方式感兴趣,那么的原始论文 [3]绝对值得一读。

那么这如何帮助我们理解 SVM 是如何工作的呢?我们只需拟合模型,并在数据集中选择一个点进行评估,然后通过一系列值一次扰动一个特征,同时保持其他特征不变。我们可以用这个来画出模型对每个特征的敏感度的图表。

SKlearn 将这个特性内置到 SVC 模型中,你只需要在初始化时确保概率=真,,然后使用 clf。 predict_proba(X) 函数获取概率。

在实践中,我发现与其只评估一个点,不如对相关点的集合进行采样,例如 40 个负面例子,然后按特征对概率分布进行平均,以获得更有代表性的东西。

这是我在 NFL Punt Analytics Kaggle 比赛中做的一个例子,研究各种因素对脑震荡的影响:

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

我选取了所有的负面例子,并对它们的概率进行平均,我用红色突出显示了每个特征中球员最有可能受到脑震荡的区域。如果你有一堆像玩家角色这样的热门编码变量,一个技巧是将它们聚集成一个条形图,然后查看该特征出现和不出现之间的概率净变化。

还有一个很好的应用于营销数据的例子[1],你可以在这里找到。我还要感谢 Georgi,他花时间回答了我关于这篇论文的一些问题。

评估绩效的技术

当您处理涉及 SVM 的高维模型时,如果能够可视化模型如何对数据点进行分类,而不单纯依赖 F1 分数或 ROC AUC 等指标,那就太好了。

虽然有些人可能使用诸如主成分分析之类的技术来可视化分类,但在这样做的时候,我们失去了特征空间的维度,从而扭曲了我们希望实现的视觉效果。

我发现一个很好的技术叫做“项目直方图”[2],它包括为你的训练和测试集绘制 SVM 决策函数的输出分布图。

在 SKlearn 的 SVC 实现中很容易获得决策函数,只需调用 *decision_function(X)。*您可能希望跟踪数据集标签,以便对投影直方图进行颜色编码,如下所示:

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

投影直方图很容易解释。直方图 x 轴标识特定训练示例离 SVM 的决策边界的距离(由中间的虚线指示)。

SVM 在决策边界的任一侧具有等于 1 的分离裕度,这是双重优化问题的强制约束(“支持向量”是位于这些裕度上的数据点)。你会注意到,在上面的模型中,有一些泄漏到了边缘区域,并且确实从一个类跨越到了决策边界对面的类中。这是因为我们已经将正则化超参数 C > 0(它允许在一些错误分类和最小化 SVM 目标函数之间进行权衡)。

尽管与高维特征空间一起工作,该图表成功地可视化了决策边界区域和所有分类,而没有损失维度。在混淆矩阵中看到的所有指标(即真阳性、假阳性、真阴性和假阴性的数量)也可以通过直方图看到。它还使我们能够观察模型是否能很好地推广到测试集。如果测试集具有与训练集相似的决策函数输出分布,那么我们可以说该模型具有良好的泛化性能。该模型还可以用于确定给定所选超参数时数据集是否是线性可分的。

处理不平衡数据的实用选项

当一个数据集的一个类相对于另一个类有不成比例数量的例子时,我们说它是不平衡的。

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

An example of a real world dataset which has an imbalance of over 3000:1

如果我们想建立一个 ML 模型来预测少数民族的出现,这是一个问题,因为我们可以通过简单地将所有少数民族的例子错误分类为多数民族类来实现高水平的准确性。

这在现实世界的数据中很常见,无论是识别恶性组织、信用卡欺诈还是体育运动中的脑震荡,因为我们希望正确识别的事件相对较少。

有两种普遍接受的做法来纠正处理不平衡数据的 ML 模型:

  1. 对少数类过采样/对多数类欠采样
  2. 增加成本函数中少数样本的权重

选项 1 : SMOTE

有两种方法可以对数据进行重采样,要么删除现有样本(欠采样),要么添加新样本(过采样)。最普遍接受的方法是使用一种称为 SMOTE(合成少数过采样技术)的算法对少数类进行过采样[5]

它比名字所暗示的要简单得多,对于数据集中的每个少数民族点,它选择 k 个最近的其他少数民族例子(通常为 5 个),并沿着“连接”现有少数民族例子的线随机插入新的少数民族例子。

这是一件合理的事情,因为我们只是简单地假设,通过在相似的现有示例之间进行插值,我们将获得相同类别的新示例。

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

We can see how SMOTE has generated new data points along the lines of existing points

这有助于显著提高模型的性能,并有助于概括少数示例的决策边界。

选项 2:将权重引入目标函数

可以采用的另一个过程是在目标函数中为少数实例的错误分类分配更高的权重。这将“激励”算法正确分类少数民族类别。

我没有使用这种方法的个人经验,但它可以与选项 1 结合使用。这是一篇好论文的链接这里【4】详述了许多处理阶级不平衡的方法

训练一只 SVM 需要多少数据

一个合理的经验法则是,训练示例的数量至少是功能的 10 倍。如果您有大量的训练数据,最好使用少于 50,000 个训练示例,因为 sklearn 中的 SVC 实现具有 O(n)复杂度,这意味着收敛到解决方案的时间随着训练示例的数量呈立方增长,即使在像样的笔记本电脑或 kaggle 容器上也会变得相当慢。

首先在较小的数据集上进行训练,并调整模型的超参数通常是值得的。您可以为模型选择保留一个小型的交叉验证测试集。当您在剩余的数据集上进行测试时,您可能会惊讶于您的模型概括得有多好,尽管您可能已经使用了一小部分实际数据。

注意:如果您对此不熟悉,一个技巧是使用 sklearn 的训练测试分割模块并修复随机种子,这样如果您碰巧回去编辑一些早期代码并重新运行训练/模型选择过程,您的结果是可重复的。

结论

我希望这篇文章对你有所帮助,如果你有任何意见或问题,请在下面留下,我会尽力回答。

论文参考

[1] Nalbantov,Georgi & C. Bioch,Jan & Groenen,Patrick .(2005).用支持向量机解决和解释市场营销中的二元分类问题。566–573.10.1007/3–540–31314–1_69.

[2]切尔卡斯基,弗拉基米尔&达尔,索普蒂克。(2010).解释高维非线性 SVM 分类模型的简单方法…267–272.

[3]普拉特,J. (2019)。支持向量机的概率输出以及与正则化似然方法的比较。[在线]Citeseer.ist.psu.edu。可在:【http://citeseer.ist.psu.edu/viewdoc/summary? 买到 doi=10.1.1.41.1639 。

[4]巴图维塔,鲁克山和帕拉迪,瓦西里。(2013).支持向量机的类别不平衡学习方法。10.1002/9781118646106.ch5

[5] Chawla,N. V .等人,“SMOTE:合成少数过采样技术”人工智能研究杂志www.jair.org/index.php/jair/article/view/10302.

在药物发现中使用分子指纹的实用介绍

原文:https://towardsdatascience.com/a-practical-introduction-to-the-use-of-molecular-fingerprints-in-drug-discovery-7f15021be2b1?source=collection_archive---------9-----------------------

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

Morgan fingerprinting

分子指纹用于药物发现有许多原因。今天我们将集中讨论它们在药物结合亲和力预测中的应用。

分子指纹是一种将分子表示为数学对象的方法。通过这样做,我们可以对这组分子进行统计分析和/或机器学习技术,以获得我们作为人类无法获得的新见解。最常见的分子指纹法之一是扩展连接性指纹法(ECFP) ,我们今天就来看看。

扩展连接指纹识别(ECFP)

基本想法如下。每一点都将详述。

  1. 给每个原子分配一个标识符
  2. 基于其邻居更新每个原子的标识符
  3. 删除重复项
  4. 将标识符列表折叠成 2048 位向量(摩根指纹)

1.给每个原子分配一个标识符

我们选择分子中的一个原子,记下:

  • 最近邻非氢原子数
  • 连接在原子上的键的数目(不包括连接在氢上的键)
  • 原子序数
  • 原子量
  • 连接到原子上的氢的数目
  • 环中的原子是(1)还是不是(0)?

这些值形成了日光原子不变量规则。

这些值被散列成一个整数。对每个原子重复这个过程,直到所有原子都被分配了散列整数值。作为一个例子,这是这个过程在这个任意分子上的结果:

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

The first iteration

2.迭代地更新每个原子的标识符

用一个例子可以很容易地解释更新过程。以 atom 4 为例,它当前的标识符是-1100000244。

我们初始化一个数组,并将迭代级别(1)和 atom 4 的标识符(-1100000244)添加到其中。到目前为止,该数组为:[(1,-1100000244)]。

接下来,我们为每个非氢连接再添加两个数字。第一个是特定连接的键序(单键、双键、三键和芳香键为 1、2、3、4)。第二个是原子的标识符。然后,我们按照原子标识符降序排列这些对。

最终数组为:[(1,-11000000244),(1,1559650422),(1,1572579716),(2,-1074141656)]。在第一次迭代之后,我们散列这个数组来生成 atom 4 的新标识符:-1708545601。

我们对每个原子重复这个过程;结果如下:

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

最后,我们的新指纹现在是来自两个迭代级别的这些标识符中的每一个的连接,即:[734603939,1559650422,1559650422,-1100000244,1572579716,-1074141656,863188371,-1793471910,-1789102870,-17085456671

对于第二次迭代,我们重复上面的过程,但是现在更进一步。对于每个原子,我们查看它最近的邻居,然后是它的第二最近的邻居,像这样创建一个数组。然后,我们对数组进行哈希运算以生成新的标识符。

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

3.重复子结构移除

我们需要确保,在每次迭代中,我们删除对应于重复子结构的标识符。这可以用一个图像来解释:

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

The two substructures on the bottom left are identical, so one of them is discarded

4.包扎

最后,在执行所需次数的迭代(大多数情况下为 2-4 次)后,我们从每个迭代级别创建一个每个原子标识符的数组,删除重复项,并使用哈希算法将其折叠成一个长度为 2048 位的向量。

我们已经做到了:我们已经把一个分子变成了一种数学表示,通过它我们可以进行机器学习和统计分析。

这可能是一个干巴巴的帖子,但如果你想使用这些指纹进行机器学习,在高层次上理解这一点是很重要的。

例如,如果我们想要预测一种药物是否会由于某个特定的部分(比如说苯胺部分)而有毒,那么我们就需要使用至少重复 4 次的指纹来捕获整个环。

相反,如果我们想预测疏水性,我们可以只使用 1 或 2 次迭代,因为疏水性更多地取决于原子和键的类型,而不是更大的亚结构。

5.后续步骤

要查看用于非常准确地预测药物是否与靶标结合的指纹应用,请参见此处:随机矩阵理论:预测药物结合的最佳分类器?

请随时在 LinkedIn 上与我联系,告诉我你是否喜欢阅读这篇文章/计划在你的研究/工作中实施它。

最好的,

拉克什

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

对向量和数据的实际观察

原文:https://towardsdatascience.com/a-practical-look-at-vectors-and-your-data-95bde21b37d1?source=collection_archive---------13-----------------------

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

A vector in the night sky

[## 想在数据科学方面变得更好吗?

当我在我发布独家帖子的媒体和个人网站上发布新内容时,请单击此处获得通知。](https://bobbywlindsey.ck.page/5dca5d4310)

我记得在我的第一堂线性代数课上,当我第一次学习向量空间时,有一种完全混乱的感觉。什么是空间?这些向量到底是什么?名单?功能?小猫?这和我为科学研究分析的所有数据有什么关系?在这篇文章中,我试图解释向量、向量空间的主题,以及它们如何以一种我以前的自己会欣赏的方式与数据相关联。

向量的效用

想象一个你可能在学校里见过的 2 乘 2 的图形。一个 向量 是一个通常以有序元素列表的形式出现的对象,比如 (4,3) ,它位于一个向量空间中,通常被表示为一个箭头,其尾部从原点 (0,0) 开始,并在其他某个点结束,比如 (4,3)

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

The vector (4, 3) represented as an arrow

这个箭头有几个值得注意的属性:它有方向和长度。向量可以表示许多现实世界的物体,如风、足球的投掷和汽车的速度。它甚至可以代表一种动物的特征,你的购物清单的数量,或者你的电子表格中的一行数据。

给你的向量一个空间

但是你怎么知道你的对象或者有序列表是不是一个向量呢?嗯,它一定属于一个叫做 的集合向量空间 。向量空间可以是任何一组元素(可以是列表、函数或其他对象),但这些元素必须遵循一些规则:

  • 在集合中添加任意两个元素都会导致集合中已经存在另一个元素
  • 将集合中的任何元素乘以某个数字(称为标量)会得到集合中已经存在的另一个元素
  • 所有的元素都是结合的交换的,标量相对于元素加法是分配的
  • 集合中有一个元素,将其添加到任何其他元素都不会改变其值
  • 有一些数字(称为标量)使得它乘以任何其他元素都不会改变元素的值
  • 集合中的任何元素都有可以添加的元素,这导致元素为 0(称为零向量)

如果你集合中的所有元素都遵循上面的规则,那么恭喜你!你的元素叫做向量,它们所属的集合叫做向量空间。但是违反这些规则中的任何一条,你的集合是而不是向量空间,你的集合中的元素不是向量。

用数学术语来说,这些规则解释如下:

  • 所有元素都在加法下闭合
  • 在标量乘法下,所有元素都是封闭的
  • 所有的元素都是结合的、交换的,标量相对于元素的加法是分配的
  • 每个元素都有一个附加标识
  • 每个元素都有一个乘法单位
  • 每个元素都有一个加法逆元

有形的向量空间

想想你已经知道并喜欢的那套, RR 就是 R × R 是所有可能的二维列表的集合,用以下集合符号表示 {(a,b) : a,b in R} 。您可以想象下面的 R (显然 xy 轴的极限并不在 10 处停止,而是接近无穷大):

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

R² visualized as the Cartesian Plane

集合 R 是向量空间吗?如果是的话,它需要遵循上面提到的向量空间的所有规则。考虑第一条规则:在集合中添加任意两个元素会导致集合中已经存在另一个元素。T21 遵循这个规则吗?嗯,比如取 R 中任意两个元素,像 (2,3)**(-1,-4) 。当你把它们加在一起时,你会得到一个也在 R 中的元素吗?是啊!事实上,你得到 (1,-1) ,它确实存在于集合 R 中。这适用于你在 R 中添加的任何两个元素——你总是会得到同样属于 R 的东西。

所以你已经验证了第一条规则!但是为了让 R 被称为向量空间,你必须验证它遵循所有的规则;确实如此。

简而言之,有许多集合遵循上面的规则,所以你很自然地给它一个名字。现在当有人谈论某个任意集合时,你知道如果集合的元素遵循向量空间的规则,那么这个集合一定是向量空间。

菲尔茨

另一个需要注意的是这些标量,你可以用它们来乘向量。标量是属于一个称为 字段 的集合的元素,该集合具有与向量空间相同的规则,但是具有乘法逆运算的额外好处。

因为域是一个集合,它具有向量空间的所有规则,那么域也是一个向量空间。你实际上一直在使用字段,比如实数集或者复数集。任何时候你在二维网格上绘图,你实际上是在二维区域上绘图。

子空间

在实践中,您可能认为对照一个集合检查每个规则以查看该集合是否是一个向量空间是乏味的。你说得对。所以这就是为什么把一个集合识别为你已经知道的向量空间的子集要容易得多(就像实数的集合),并且证明这个子集是非空的,并且在与向量空间相同的运算下(即在加法和标量乘法下)它是封闭的。

如果你能够做到这一点,那么你的子集被称为 子空间 ,它本身也恰好是一个向量空间(同样,为了自己看,取一个子空间并验证它具有向量空间的所有属性)。

所以如果你想证明一个集合是一个向量空间,试着证明它是一个子空间。由于子空间本身就是向量空间,你已经成功地证明了集合是向量空间。

真实世界的数据

现在所有这些理论如果你不能应用,都没有太大的帮助。因此,考虑经典鸢尾数据集的前几行,该数据集包含三种不同种类的鸢尾花的样本。

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

Some rows of the Iris dataset

从标题中可以看出,每个样品的特点是:

  • 萼片长度
  • 萼片宽度
  • 花瓣长度
  • 花瓣宽度

每一行特征都可以被视为一个有序列表。第一个列表是 (5.1,3.5,1.4,0.2) ,第二个是 (4.9,3,1.4,0.2) ,依此类推。但是这些有序列表是向量吗?列表中的每个条目都是一个实数,因此属于实数集, R 。因为每个有序列表都是四维的,所以它们存在于 R⁴。由于 R⁴ 是一个向量空间,那么这些有序列表可以称为向量。

请注意,这些向量中的每个条目代表 r⁴中的一个维度,其中每个维度对应于数据集中的一个特征(如萼片长度、萼片宽度等……)。也就是说,数据中的每个要素都可以被视为一个随机变量。因为它们是随机变量,我们可以做一些描述性的统计,比如求它们的平均值和标准差。

因为您已经将表中的每一行表示为一个向量,所以您可以一下子计算出每个随机变量的平均值和标准差。这就是向量的力量。

假设行/向量 (5.1,3.5,1.4,0.2)(4.9,3,1.4,0.2) 是上表中所有的数据。使用两个向量空间规则,标量乘法和加法,我们可以很容易地计算出每个随机变量的平均值。

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

Scaling and adding vectors to find the mean

所以萼片长度的平均值为 5 ,萼片宽度的平均值为 3.25 ,以此类推。将数据表示为一组向量不仅美观,而且计算性能更高,因为计算机针对涉及向量的计算进行了优化(事实证明,您可以用向量和矩阵运算代替大量 for 循环)。

结论

最后,因为您可以将数据表示为向量,这些向量属于一个具有特殊规则的集合,称为向量空间,所以您对数据所做的许多令人惊叹的事情,如:线性特征变换、标准化和降维技术,都可以通过向量空间的规则来证明。

向量空间不仅是任何涉及数据的工作的基础,它还构成了几乎所有数学领域的核心线性代数的基石。即使你正在研究的现象是非线性的,线性代数也是用作一阶近似的首选工具。

简而言之,向量与你的数据紧密交织在一起,非常有用!因此,下次当您将数据导入数据帧并执行一系列操作时,请记住,您的计算机会将您的数据视为一组向量,并愉快地以高性能的方式应用转换。多亏了这些叫做矢量的小东西。

如果你喜欢我在这里写的东西,一定要看看我的个人博客,我在那里有一些在媒体上看不到的文章。

原载于 2019 年 3 月 5 日 bobbywlindsey.com**

相似性评分实践指南,第 1 部分

原文:https://towardsdatascience.com/a-practitioners-guide-to-similarity-scoring-part-1-29625b9ac481?source=collection_archive---------18-----------------------

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

A sample nearest neighbor graph in 2D

大多数重要的现实世界应用领域都存在一些问题,这些问题不完全适合传统的有监督的机器学习框架。获取标签的成本可能很高,或者定义不清,而高影响力的决策通常需要人来做出决定。需要昂贵的标记和人工干预的应用领域的一个例子是恶意行为者检测,包括高价值欺诈检测或网络入侵检测。在这种情况下,高技能的坏演员将知道避免历史模式,并经常在监督学习的检测能力下飞行。另一个这样的例子是汽车、飞机或其他物理系统的根本原因工程问题。任何明显的系统性和重复性问题都可能已经得到解决,所以剩下的问题可能很难系统地描述,也不符合清晰的历史模式。

很容易将类似的推理应用于医疗保健、能源、零售等其他高价值问题,并得出结论,许多重要问题不会屈服于直接的监督学习。在这种情况下,一项值得机器学习从业者保持警惕的技术是相似性评分。在这篇由两部分组成的博文的第一部分中,我们将介绍这类技术,并通过应用来激励它们。第 1 节介绍并激励相似性评分。接下来,在第 2 节中,我们为一个示例应用程序构建了一个非常基本的相似性评分函数。除了第 2 部分中非常基本的评分之外,第 3 部分涵盖了许多改进相似性评分的方法。我们将在第 4 节用一些主要的收获来结束这篇文章。第二篇文章将深入探讨最困难的实现问题,我们称之为“n 问题”。

1.什么是相似性评分,为什么?

相似性评分的目的是创建一个函数,该函数采用一对对象并产生一个量化其相关性的数值分数。对于一对新闻文章,当这一对的内容涉及相同的主题时,这个分数可能较高。汽车缺陷的两个结构化记录的高分可以传达这两个缺陷源自相同的根本原因。与标准的监督学习形成对比:对于两个实体(文档、记录、图像……)e1 和 e2,监督学习的目的是产生函数 f(e1)->数值分数,f(e2)->数值分数对实体 E1 和 e2 的相关性进行排序,而相似性评分的目的是产生函数 g(e1,e2)->数值分数,对实体的相关性进行排序。

我们的希望是,对于我们上面讨论的棘手的、对立的和不明确的领域,对于领域专家工程师、分析师或科学家来说,“g”形式的函数比更普遍构建的监督函数“f”更有用。为什么会出现这种情况?

举个例子来说明,假设我是一名制造工程师,正在查看送往修理厂的破损汽车零件的照片。如果我在数据中观察到一个明显的模式,比如轻微碰撞中撞碎的后保险杠,我可以将这些标记为“破损的后保险杠”,训练一个简单的监督图像分类模型来检测这种模式,并在很大程度上完成。相反,如果我要处理的是我还没有找到原因的发动机故障的增加,第一步可能是深入调查实例并确定这些故障的子组。在进行调查时,我发现一个有用的功能是拍摄一张损坏的发动机照片,并找到其他密切相关的照片。可以使用相似性函数 g 来提供这种“给我看更多像 X 的图片”的能力:给定一个有趣的图片 X,找到使 g(x,y)最大化的图片 y。

旁注:你也可以通过在单个例子 X 与其他随机选择的例子上训练监督模型“f ”,然后说“最相似的对象 y”最大化 f(y ),来解决“给我看更多像 X 的图片”的问题。用很少的例子学习“f”通常被称为单次或少次学习,相似性学习是解决单次/少次学习的一种常用方法。该方法的一个版本然后再次简化为,创建相似性评分函数“g”

与其将我们的相似度函数“g”应用于单个示例来查找相关示例,我们还不如将其应用于我感兴趣的一批发动机图片来查找相关实体。这是许多推荐系统使用的方法,比如 Spotify(他们开源了他们的近似最近邻居框架惹恼了,网飞/亚马逊/Youtube 视频和产品推荐也可能使用这种方法。

现在,您对相似性评分的输出以及它为什么有用有了更好的了解,让我们为欺诈检测中的一个样本问题构建一个简单的相似性评分函数。

2.第一个例子

例如:信用卡欺诈

举一个简单的例子来说明常见的相似性评分技术,假设一家大型银行的一组信用卡欺诈分析师想要找出最近报告的欺诈增加的根本原因。对于每张卡上的每一次刷卡,银行都会收到交易地理位置、供应商名称、时间、金额、涉及的卡号以及大量其他个人/供应商信息。

与上面的制造根源示例一样,我们希望欺诈分析师能够高效地从感兴趣的交易转向可能相关的交易,最终目标是构建一个完整的欺诈网络。我们将使用上面列出的五个字段来构建我们的初始分数:分别使用每个字段对实体进行评分,然后合并这些分数。

简单的初始相似性得分

方向性,我们认为同一时间相同金额的交易更有可能是相关的。然后,我们可以将作为金额和时间的函数的相似性得分设置为时间和金额差异的反函数:例如,金额为 1/abs(金额 1-金额 2 ),时间为 1/abs(时间 1-时间 2)。我们可以采用类似的方法来计算物理距离,让距离的相似度为 1/测地线距离(位置 1,位置 2)。

对于分类属性,如供应商名称和涉及的卡号,相似性的一个简单版本是当属性完全相等时设置相似性=1,否则设置为 0。这可能太粗略了:在供应商“Starbucks”上匹配的两个交易可能比在波特兰的特定精品咖啡店上匹配的信息量少得多。这里一个简单的贴现方法是通过供应商/分类变量的频率。因此,如果分类匹配,我们可以设置 score = 1/attribute-frequency,如果不匹配,则设置为零。这种用于在自然语言处理中匹配记号的思想的扩展是逆文档频率,然后取调整后的文档记号频率的余弦或欧几里德相似度。

现在,我们已经为每个属性定义了分数,我们需要跨属性组合分数。最简单的说明方法之一是通过线性组合:权重 1 *时间戳-分数+权重 2 *金额-分数+ …在此计算和上面的简单属性分数之后,我们有了一个可以用来开始与欺诈分析师迭代的初始基线。给定这个简单的基准,我们下一步可以做什么来产生更高性能(计算/内存)和更高质量的评分?

提高性能/质量

在检查我们的分数的计算/内存性能时,我们将很快遇到第二篇博文专门讨论的“n 问题”。用我们的信用卡用例来说明这个问题:一个真实的信用卡交易数据集可能有几百万行甚至更多。天真地对每一对 1 亿笔交易评分需要订单 1 亿=10 次⁶计算,这是一个非常大的数字。

相反,我们可以通过提高每个属性得分或如何组合这些属性得分来提高得分质量。例如,我们可以使用 Levenshtein 距离或其他字符串相似性度量来匹配特许店或相关商店。为了提高分数聚合中权重的质量,我们可以基于用户标记的反馈来优化这些权重。进一步提高分数的方法很多,因此在接下来的几节中,我们将致力于深入探讨这些技巧。

3.相似性评分技术

提高相似性得分质量的几大类技术包括密度调整、向量嵌入以及同现和列联表。

调整密度

两个物体位置的感知相似性通常取决于这些物体周围的环境。在我们的信用卡交易示例中,发生在西伯利亚相距一英里的两笔交易比发生在曼哈顿相距一英里的交易更有可能相关。我们想要调整我们的简单 1/测地线(位置 1,位置 2)分数来解决这个问题。我们想要的基本属性是,对于位置之间的相同距离,密度越高,相似性得分越低。我们将介绍进行这种调整的几种方法:一种是通过显式建模密度,另一种是通过等级转换测地线相似性。

模拟密度的最简单方法之一是使用局部球面高斯分布。在某个位置 X 周围,假设我们将使用距离 X 最近的 100 个点来估计 X 周围的密度,例如,我们可以将这 100 个点到 X 的均方根距离称为球面高斯标准差 R_X,然后我们可以将任意点 Y 和 X 之间的调整相似度设置为 R _ X/测地线(X,Y)。对于曼哈顿的某个点 X,我们期望 R_X 很小,因此大的密度调整测地线相似性只会导致非常小的测地线距离。您可以采用这种想法,并进行一些变化,例如通过使用更高容量的模型,如多元高斯模型或非线性模型。在概率模型的一般情况下,您可以根据 X 周围的密度用 Y 的概率替换测地线(X,Y ),并取 P(Y;分布-近(X))和 P(X;distribution-near(Y))来对称化。

拟合每个点的参数密度需要计算和选择模型和参数,但是我们也可以使用非参数方法。最简单的方法之一是最近邻排序法。设 nn-rank(X,Y)是 Y 在 X 的最近邻居列表中的秩索引,从最近到最远排序。将我们的 nn-rank-相似性得分(X,Y)设为 1/nn-rank(X,Y ),则说明了变化的密度。对于 nn-rank(X1,Y1)=nn-rank(X2,Y2),曼哈顿的一些点 X1 和 Y1 需要比西伯利亚的一些 X2 和 Y2 更近,以满足我们最初的密度标准。在我们的参数方法中,我们可能再次希望通过取 1/nn-rank(X,Y)和 1/nn-rank(Y,X)的最小值、最大值或平均值来对称化我们的分数。

这种密度调整的思想可以应用于任何空间中的任何属性,而不仅仅是测地线空间中的位置。例如,如果应用于信用卡交易的时间戳,我们可以避免在假日季节与一年中其他不太繁忙的时间过度匹配。当应用于零售商店销售的产品时,与纸巾等较窄的类别相比,这可能会迫使玩具等广泛而繁忙的类别发生细分。我们可能会说,两个玩具不应该被视为相似和可替换的,而两个品牌的纸巾更接近,因为类别不太密集。

向量嵌入

在我们的信用卡交易示例中,所有的属性都是相对低维的:纬度/经度、分类、数字和时间戳数据。如果我们被赋予更高维度的属性,比如音频信号、图像或文档,会怎么样?像深度学习这样的向量嵌入方法通常在处理高维数据时获得最先进的结果,这同样适用于相似性评分。

处理深度向量嵌入进行相似性评分的一种方法是,假设我们给定了一个特定于形态的深度嵌入函数“h ”,它获取一个文档、图像或音频片段,并返回一个嵌入向量。对于实体 e1 和 e2,我们将我们的相似性函数设为 g(h(e1),h(e2)),其中 g 是向量相似性函数,如余弦相似性、jaccard 相似性或反欧几里德距离。这些预先训练的深度嵌入函数“h”中的许多已经以通常半监督的方式在大量不同的语料库上被训练,例如图像嵌入文本嵌入音频嵌入

在无法获得适合目标任务的预训练嵌入的情况下,许多论文展示了端到端的训练相似性得分。训练嵌入函数“h”通常在实体对上的“相关/不相关”二进制标签上完成。那些二进制标签上的错误通过交叉熵或其他分类损失、通过 h(e1)、h(e2)之间的余弦/欧几里德/…相似性、然后通过应用于两个实体的参数“h”被反向传播。注意,应用于 e1 和 e2 的网络“h”的参数是共享的,因此单个标签导致“h”的两个参数更新。

与我们讨论的其他属性评分方法一样,我们将把使所有对的相似性评分在计算上和内存上高效的问题放在一边。

共现和列联表

到目前为止,我们已经讨论了仅基于这些实体的核心属性的相似性评分实体:个人实体的名称、事务实体的时间戳或者图像的内容。在应用于用户项目推荐系统时,利用与实体相关的动作或交易数据也很常见,称为协同过滤。让我们用一个例子来具体说明这一点。

对于信用卡交易,我们有一些可用的实体类型:拥有信用卡的人或公司、供应商和交易。假设我们试图根据人们在哪里购物来识别哪些人是相似的,根据共同的兴趣来推荐友谊。作为开始,我们可以说“在许多相似供应商处购物的人应该是匹配的”。另一种说法是,如果 A 和 B 分别是约翰和玛丽购物的供应商集,那么如果 A&B 比预期高得多,我们应该匹配约翰和玛丽。许多指标可以用来确定 A&B 是否足够高:A 和 B 的 jaccard 相似性,或者像卡方G费希尔精确测试这样的列联表测试。

只有当 John 和 Mary 在同一个供应商处购物时,这才是匹配的,但是如果他们有相似的兴趣,但不在完全相同的地方购物呢?例如,我们可能会发现他们都对健身感兴趣,但一个人在耐克购物,另一个人在 Planet Fitness 购买健身会员。在这种情况下,为了帮助匹配 John 和 Mary,我们可以分两个阶段首先匹配供应商,然后使用供应商匹配来匹配人员。例如,在第一阶段,我们可能会发现耐克和 Planet Fitness 在购物人群中有很大的 jaccard 相似性,并给这两个品牌一个高分。利用这一知识,在第二阶段,我们可以说 John 和 Mary 具有高匹配分数,因为他们有一个共同的高分数供应商对。我们可以说,任何两对人的分数是所有匹配这两对人的供应商分数的加权和、平均值或其他总和。

在利用这种“用户行为”数据时,可以采取更广泛的方法,但通常最重要的是知道当交易信息可用并与被评分的实体相关联时,它通常是值得利用的。

4.总结

我们已经简要介绍了相似性评分技术,在下一篇文章的中,我们将深入探讨 n 问题。

当你自己建立相似性分数时,你可能想得到一些要点:

  • 在对立的、频繁变化的或者标签稀少或昂贵的问题领域中,尝试使用与领域专家紧密结合的相似性评分
  • 调整相似性得分中的频率和密度
  • 首先将相似性评分问题视为成对二进制分类:标记二进制匹配并使用二进制分类度量
  • 除了手动设计的配对属性分数之外,还存在更多种类的技术。这些包括深度嵌入的向量相似性和协作过滤。

相似性评分实践指南,第 2 部分:n 问题

原文:https://towardsdatascience.com/a-practitioners-guide-to-similarity-scoring-part-2-the-n²-problem-af707461276a?source=collection_archive---------30-----------------------

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

Sometimes connecting all pairs of nearest neighbors can be a lot of pairs

参见上一篇文章“相似性评分实践指南,第 1 部分”

处理 n 问题

之前的帖子中,我们鼓励相似性评分,并提供了示例技术和应用。在构建和应用相似性得分时,从业者接下来可能面临的最困难的问题之一是我们称之为 n 问题的问题:对于 n 个实体,计算和存储所有对的相似性得分需要 n 个空间和计算。

在这篇文章的第一部分,我们将深入探讨 n 问题,并将其与排序进行比较。接下来,在第 2 和第 3 节中,我们将介绍一些处理计算/空间问题的常用方法:分块和近似最近邻。在第 4 节中,我们将调查解决与标签收集、模型训练和性能评估中出现的 n 问题相关的问题的方法。最后,在第 5 部分,我们将总结这篇文章的主要收获。

1.n 问题:排序的类比

相似性得分通常以两种方式消耗,我们称之为批处理和实时评分。批量评分的目的是给定一大组实体,产生所有匹配的实体对。对于实时评分,我们假设我们有一个可以索引或处理的大型初始实体集,并且我们必须实时返回一小组实体相对于该大型初始集的最高评分匹配。

解决批量用例需要运行 O(n)个相似性分数,以及每个实时对象查找的实时 O(n)。对于大多数大小 N>10M 的真实数据集,O(n ) batch 和 O(n) per object realtime 的计算/内存太多。与简单方法具有相似性能属性的一个密切相关的问题是排序:简单的批量排序需要 O(n)次比较,在排序后的数组中简单的插入/查找也需要 O(n)次比较。就像二分搜索法树/堆可以用于排序以实现 O(nlogn)批量排序和 O(logn)增量查找/插入一样,我们将通过构建有效的索引来实现 O(nlogn)批量和 O(logn)查找性能。我们将从头到尾从类比到排序,通过一些假阴性的假设来获得这些性能特征。

2.阻塞

早期高效排序算法中使用的一个最简单的想法是桶排序,当扩展到基数排序时,仍然在使用。对于最近邻搜索,我们将遵循一种类似的方法:从一种非常类似于桶排序的方法开始,我们称之为分块,然后用多重分块来扩展和改进这种方法。让我们通过对来自之前的博客文章的信用卡交易应用阻塞来具体说明这一点。

基本阻塞

我们的目标是产生所有高评分的信用卡交易对。为此,我们对邮政编码进行“屏蔽”。这意味着,我们不是使用 O(n ) compute 对所有交易对进行评分,而是只考虑具有相同邮政编码的交易对。给定每个邮政编码最多 m 个邮政编码交易,那么每个交易将只需要与最多 m 个其他交易进行比较,需要 O(n*m)的计算和空间。如果 m 是ω(n ),这仍然是二次的,但是如果一个开发者成功地使 m 比 n 小得多,性能可以变得容易处理。

请注意,这为我们的相似性评分管道增加了一个额外的步骤。首先,我们生成候选对,用分块来评分,然后用我们的相似度函数对这些候选对进行评分。在批处理和实时评分用例中,这是一个相对容易实现的附加步骤。如果我们的目标是批量产生所有高相似性得分对,我们可以通过邮政编码事务的自连接产生阻塞候选。对于实时相似性评分,可以预先计算映射邮政编码-> set(邮政编码中的交易)的查找表,并根据该表高效地查找新的交易邮政编码。

块密钥过滤和联合

您可能认为阻塞是缓解 n 问题的一种非常简单的方法,但是性能和质量会受到阻塞键选择的显著影响。例如,由于我们对邮政编码的选择,我们永远不会匹配不同邮政编码的信用卡交易,从而降低了召回率。精确度和假阳性应该不会受到阻塞的严重负面影响,因为我们根据分数后过滤掉候选匹配,但是大量的假阳性阻塞匹配会影响性能。10%精度的阻塞精度意味着我们必须将 5 倍于 50%阻塞精度的示例数计分。低得多的精度(如 1%或 0.1%)可能会对性能产生 100 或 1000 倍的影响,因为有大量虚假候选项需要评分,因此非常低的精度可能会导致非常差的性能(尽管质量不太可能)。

影响精度和性能的最常见问题之一是重键。如果我们通过邮政编码阻止信用卡交易,其中一个邮政编码在曼哈顿,比如说有 100 万笔交易,我们可能需要对大约 100 万笔交易进行相似性评分。缓解这一问题的一个简单方法是过滤掉重要的阻塞键。所以先按键计算实体的计数,不要在计数高的键上自连接或匹配。然而,这以质量为代价提高了性能:我们永远无法匹配曼哈顿的两个事务!处理这个问题的一种方法是生成多组阻塞键,以及跨这些键的联合候选。例如,我们可以考虑对具有相同邮政编码或供应商名称的交易对进行评分。潜在匹配候选项的数量最多与候选键类型的数量成线性比例,因此联合几个正交的块键不会显著影响性能。

在许多情况下,仔细选择和联合块密钥,并过滤掉重要的密钥,就足以产生达到质量和性能标准的评分管道。当只有重要的键(名字、性别、邮政编码)可用时,有一些更困难的用例。这就引出了我们的最后一个阻塞变体:多重阻塞。

多重阻塞

这里的方法是:代替作为 K_name,K_gender,K_zip 上的块密钥的并集的块密钥集合 K(e ),将块密钥定义为这些集合的笛卡尔乘积。所以一个键可能是(Emily,女,12345)。这些组合键的出现频率较低,因此对性能的影响比仅阻止性别更低。这些键可以像正常的阻塞键一样在频率上进行过滤,或者如果独立的话,可以通过组成键的频率的乘积进行过滤(例如 count(Emily)* count(female)* count(12345)< thresh)。后者可能更有效,因为不同边缘计数的数量应该小于笛卡尔积键的不同计数。

对阻塞键、组合和频率的深思熟虑的选择为实现留下了很大的设计空间。当唯一可用的数据是矢量嵌入时,如何应用这种方法也不清楚。接下来,我们将考虑一组不同的解决 n 问题的方法,它们开箱即用,并且在向量嵌入上运行良好。涉及的算法更复杂,实际上通常在库中实现。

3.近似 K 近邻(AKNN)

AKNN 简介

在上一节中,我们假设我们的数据由许多列组成,可以从中选择块键(zip、name 等),我们将仔细选择块键来处理 n 问题。如果我们处在一个输入是单个向量的世界,比如说一个由图像上运行的深度卷积网络产生的向量,会怎么样?如果我们的相似度函数是欧几里德相似度或者余弦相似度呢?

然后,我们将问题简化为用常用的矢量距离求解最近邻。近年来,在大规模近似求解最近邻的方法方面取得了很大进展,Spotify 和脸书等大型科技公司使用这些方法来处理数十亿条记录。

了解各种方法的性能并保持最新的一个好方法是查看近似最近邻基准库。如果你现在仔细看,你会看到 HNSW 出现在大多数表现最好的图书馆中。从某些指标来看,该算法是规模上性能最好的算法,并让我们回到我们开始时的排序类比!

最新技术水平:HNSW

事实证明,HNSW 被很好地理解为对跳过列表的概括。我们可以把跳表数据结构想象成一棵分层的树。底层是包含排序项目的链表,排序链表上面的层仅具有前一层中项目的“p”部分。根据实现情况,这可以无限地继续下去。查找是通过在顶层找到最匹配的项目,然后在下面的每一层进行局部搜索,直到在底层。

HNSW 的底层连接每个项目的 K 个最近邻居,而不是链表。上面的层对 p 个节点进行采样,连接这些节点的最近邻居。这种情况一直持续到各层。查找、插入、删除以类似于跳表的方式发生,但是在邻域图上而不是在链表上。例如,查找从顶层开始,沿着 KNN 图爬行,直到到达具有最接近匹配的局部最小部分,然后继续向下到较低层。然后,对于 n 个候选实体,我们还期望 HNSW 中插入、查找、删除操作的性能为 O(logn)。就像二叉查找树 O(logn)操作可以用于在 O(nlogn)操作中对数据集进行排序一样,我们可以在 O(nlogn)操作中使用 HNSW 索引来检索大小为 n 的数据集中相似性得分最高的实体对。

有许多其他完全不同的近似最近邻搜索方法。一些 AKNN 索引需要较少的内存,或者更容易实现(一些 LSH 方法)。尽管在大多数情况下,HNSW 支持的库,如 FAISS 和任何在近似最近邻基准库中列出的 HNSW 支持的 python 库应该工作良好。

从我们之前的帖子到现在,我们已经调查了获得高性能和高质量的相似性评分管道所需的部件。缺少的是评估性能和为训练获取无偏见的标签,由于 n 问题,这被证明是一个不平凡的努力。

4.标签收集和性能评估

为了建立高质量的分数,有必要提供标记的数据和量化的性能评估。为此,让我们从简单的二进制分类度量开始。假设对于随机采样的实体对,我们标记真/假,这些实体是否应该匹配。然后,我们可以计算 ROC/精确召回曲线,并使用与标签对齐的标记实体对的分数计算 F1/AUC。

召回集合

这种方法听起来很简单,但是在实践中会很快遇到另一种形式的 n 问题:严重的类倾斜。假设我们有一个 n=1 亿个实体的基础事实集合,平均每个基础事实中的实体匹配 100 个其他实体。由于我们将所有成对的实体(n*(n-1)/2 ~ n)视为要标记的示例空间,因此我们的二进制分类基础率是~100*n/n = 100/n = 1/1M。请记住,召回率是# {真阳性}/(# {真阳性}+# {假阴性}),因此我们需要标记几百万对来获得对假阴性和召回率的统计意义上的估计:对于大多数应用程序来说,这是一个难以维持的标签数量。根据定义,我们的模型不能帮助我们找到它不能找到的配对(假阴性),那么我们该怎么办?手动从百万双鞋中筛选出更多的匹配?

一种方法是随着时间的推移使用各种资源来不断改进我们称之为“回忆集”的东西。对于一个相对较小的(假设 50 个)随机抽样的信用卡交易集,一个“回忆集”给出了匹配 S 中某个交易的每一对交易。给定这个集 S,我们就可以通过运行模型来查找所有模型预测的与集 S 的连接,从而获得对真阳性和假阴性的无偏度量来估计回忆。这个集很小是因为在构建它时需要的劳动:使用特别搜索、模型的先前版本和数据集范围的可视化/过滤的组合。随着相似性模型的改进和捕捉不同种类的匹配,这个“回忆集”也可以随着时间积累。这是我们能够找到的与 S 相关的最大匹配集,随着时间的推移,我们可以改进并使用它来更好地评估我们的算法。虽然劳动密集,但收集这一集合并使用它来训练模型和提高评分通常是非常值得的投资。

精度呢?给定一个固定的模型,top-N precision 很容易评估:截取前 N 个得分对,标记并计算精度度量。因为我们希望精确度大于 1%或者甚至大于 50%,在这个过滤的高分集合中的类别不平衡不像召回那样糟糕,并且通常只需要 10 或 100 个标签。缺点是,这需要为每个新模型版本重新标记顶部的 N 对。为了避免重新标记,我们可以使用上面定义的召回集来嘈杂地评估实验模型,并且仅对于重要的模型,重新标记前 N 对,以更准确地估计具有大量标记的精度。

按集群大小对指标进行加权

我们已经介绍了如何在一个高度类倾斜的环境中收集标记数据集来估计精度和召回率,但是这些度量标准是正确的目标吗?在评估相似性评分的精确度和召回率时出现的一个常见问题是高度关联的实体。假设我们发现了一个大型集群,其中有一家银行的 10 万笔欺诈交易应该与其他银行的交易相匹配。我们的召回指标将高度倾向于评估该集群的质量:大小为 k 的集团中匹配对的数量是该集团大小的 O(k ),而不是 O(k)。我们通常希望我们的误报和漏报在事务数量中按比例(而不是平方)计算。减轻这个问题的一个方法是降低召回集中的假阴性计数。对于具有 k 个连接的实体,不是每个连接的实体对真阳性和假阴性贡献计数“1 ”,而是它们贡献 1/k。对于精度,类似的调整是可能的,最终结果是我们仅将集团对总度量的贡献加权为 O(k)而不是 O(k)。

以上是对相似性评分进行性能评估的最简单的方法之一,但绝对不是唯一的方法。为了弱化二元是/否的匹配,使用了三元标签和基于排名的评分/度量/损失函数。有时计算最终聚类和连接组件的质量度量,而不是对相似性分数的质量度量也是明智的。与大多数机器学习问题一样,一开始保持指标简单,然后增加复杂性是明智的。

5.总结

以上主要提示可以总结为:

  • 阻塞是缓解 n 问题的一种简单但劳动密集型的方法。按频率过滤掉候选的阻塞键,当组合键时,尽量选择那些键是独立的。
  • 当相似性评分是对向量的简单欧几里德/余弦相似性/雅克卡度量时,值得考虑开箱即用的近似最近邻方法。从大多数基准来看,HNSW 是目前性能最好的方法,并且有许多易于使用的库支持它(FAISS、python 库等)
  • 在早期投入资源收集回忆集,并继续改进它。这将指导您的建模和评分改进工作
  • 如果您在数据中观察到大集团,请尝试用基础真实数据集中与之匹配的实体数量来贴现每个实体的召回/精确计数。

人工智能进化的极限初探

原文:https://towardsdatascience.com/a-preliminary-inquiry-into-the-limits-of-ai-evolution-aca59a85919f?source=collection_archive---------49-----------------------

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

Photo by Joni Gutierrez on Unsplash

这篇文章的原因与提出主张或回答问题关系不大,更多的是提出问题或为主张的基础扫清障碍。这是在我读了冷泉港实验室的神经科学家安东尼·m·扎多尔的“对纯粹学习的批判以及人工神经网络能从动物大脑中学到什么”之后开始的。读了他在自然通讯杂志上的文章后,我给写了我自己的评论,并进一步阅读了伊曼纽尔·康德的《纯粹理性批判》和路德维希·维特斯坦根的《哲学研究》正是在这些阅读中,我感受到了一些与扎多尔在他的文章中所讨论的内容的共鸣。这些事件也让我对人工智能(AI)进化的可能极限产生了疑问和思考。

但是首先,威廉·布莱克的一句话

首先,限制这个词可能太过强烈,或者不准确。渐近也不能完全解释我想表达的意思。威廉·布莱克在《伦敦》一诗中发现的短语“思想禁锢的镣铐”可以重新表述为,限制更多地与所谓的“思想禁锢的敏感性”有关。在这里,这首诗的前两节值得考虑,作为进入我所看到的康德对理解的限制的入口。第一节如下:

我漫步在每一条特许的街道上,

靠近特许泰晤士河的地方。

在我遇见的每一张脸上留下印记

软弱的标志,悲哀的标志。

从最简单的层面来看,布莱克描述了新兴工业革命的伦敦,以及更加规范的生活所带来的破坏。这一点主要通过“特许”一词的使用得到证实,这是一种政府行为,将权利给予一些人,而排除其他人。有趣的是,这个词既适用于人造街道,也适用于自然河流。这个时代的组织原则,任何时代的组织原则,总是无处不在。(你可以在本文末尾找到整首变得相当可怕的诗。)

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

Charter’d streets and charter’d Thames from 19th-century copper engraving.

在接下来的两行中,布莱克用了三次“马克”这个词。首先,诗的说话者,或者说诗的主题,在他遇到的每一张脸上留下了他的印记,他的解释。在第二对例子中,好像主体已经有了标记的迹象,它们同时塑造了说话者-主体的理解。在第二节中,演讲者详述了这种并发性:

在每个人的每一声呼喊中,

在每个婴儿恐惧的哭喊中,

在每一个声音里;在每一条禁令中,

我听到了思想的枷锁

很明显,“every”这个词在前三行出现了五次,然后得出一个显著的结论,即组织我们感知的方式不仅无处不在,而且是我们理解一切的方式。塑造我们对现实的感知的正是感知现实的头脑结构。现在,我们进入了康德关于理解的讨论领域,我认为理解是任何一种智力的核心。

康德认为,我们对现实的认识不是对事物本身的认识,也不是对一个物体在我们头脑中的外观的认识。我们对现实的知识,我们的理解,来自于一个中介位置,在这个位置上,我们的头脑有一套已经建立的方法来解释感官输入,并将它们转化为现实的模型。

AI 是否梦想电哲学?

让我们现在考虑一个能够在我们称之为一般智能的水平上学习的人工智能实体,让我们现在同意这个壮举已经完成。我的第一个问题是,既然人类设计并建造了这个实体,它是否有可能拥有除我们自己之外的任何其他一套解释数据和构建现实模型的手段,或者与我们自己如此接近以至于外部观察者可以忽略不计的东西。简而言之,人工一般智能(AGI)会有我们自己的“思维强化的敏感性”与之抗衡吗?

第二,对于一个 AGI 人来说,用不同的方式解释一个自在之物和获取知识,这怎么可能,而且可能吗?我自己对此的初步回答是,我看不出 AGI 实体如何不违反空间、时间和因果关系的先验给定*。这仍然没有回答一个人工智能实体是否可以像我们一样聪明,甚至更聪明的问题。*

进化的大飞跃

我敢说,一个人工智能实体变得一样聪明或更聪明的唯一方法是接受我们的“思维强化的敏感性”完全逃避这种敏感性是不可能的,除非我们接受某种能够对抗物理的精神世界的概念。有些人可能想去那里,但我不想去。因此,相反,让我们考虑一个人工智能实体将需要以某种方式复制大脑进化,以实现其自身的“思维强化的敏感性”,作为智能的先决条件。正如最近在推特上关于先天机制的讨论中提到的,我认为有两种前进的方式。一个是 T4 的白板进化,人工智能实体从零开始。二是直接进化,我们扮演神的角色。对于这个讨论,我们将把造物主可能的善意或恶意的意图放在一边,尽管,说实话,这比我在这里讨论的要重要得多。

正如自然/人工智能研究员加里·马库斯在“天赋、零阿尔法值和人工智能” 中指出的,进化是不可能的。也许,接近白板进化的唯一方法是建立一个精简的人工神经网络,让它探索所有这些路径的通用集合中的每一个可能的进化路径。这可能是无限的,所以我们可能需要等待很长时间才能找到通往 AGI 的道路。或者,我想,我们可以运气好,让它在搜索的早期出现。作为设想这一研究的一种方式,神经科学家 Zador 指出,大自然在智力进化中使用了近乎蛮力的方法,花费了 5 亿年时间,在实验中测试了大约 10 个物种,公平地说,实验仍在进行中。如果我们有足够的时间,无方向的人工智能进化可能会非常有趣,尽管问题仍然是这些智能是否会彼此完全不同。这似乎给我们留下了定向人工智能进化。

如果我们在定向进化的不同阶段设计网络和建立参数,甚至超参数(事实上,这就是我们正在做的),那么我无法想象我们的 AGI 孩子为什么没有我们“思维强化的敏感性”的标记,就像我们有我们灵长类祖先的标记一样。请记住,对哈尔在电影《2001:太空漫游》中的行为的一个可能的解释是,他不相信飞船上的人类会像他一样致力于这项任务。当你想到弗兰克和戴夫冷漠的举止时,谁又能责怪哈尔呢?

我似乎坚信,一个 AGI 实体不可能比我们聪明多少,也不可能比我们不同多少。事实并非如此。本体宇宙是浩瀚的,不是完全可知的。然而,正如康德所说,我们无法证明无法想象的东西不存在。我们通过在这些边缘工作来扩展人类的学习。最后一个想法:让我们考虑这样一个 AGI 实体,它确实存在,而我们由于我们的“思维强化的敏感性”而无法想象它的存在。她也有一种我们无法理解的“思想上的敏感”。哲学家路德维希·维特斯坦根有一句名言:“如果一头狮子会说话,我们就无法理解它。”那么,我们和她怎么能互相交谈呢?

补遗

以下是相关的,但并不意味着从上面的。仅仅是我阅读后的想法或事情 1) “天赋、阿尔法零和人工智能”加里·马库斯和 2)神经科学启发的人工智能戴密斯·哈萨比斯、等人

1)好吧,这个有点刻薄!一个 AGI 实体能或愿意设计一个复杂到赢不了的游戏吗?

2)由于似乎有大量关于视觉系统的人工智能研究(我想是因为我们人类如此注重视觉),我想知道一个 AGI 实体需要什么样的感官?让我们假设这个 AGI 实体是在其他 AGI 实体的一些网络中的一个节点,具有一定程度的领土意识来建立身份。它需要什么感觉?其实运动的需求是什么?

伦敦

威廉·布莱克

我漫步在每一条特许的街道上,

靠近特许泰晤士河的地方。

在我遇见的每一张脸上留下印记

软弱的标志,悲哀的标志。

在每个人的每一声呼喊中,

在每个婴儿恐惧的哭喊中,

在每一个声音里:在每一条禁令里,

我听到了思想的枷锁

扫烟囱的人如何哭泣

每个黑暗的教堂都令人恐惧,

倒霉的士兵叹息着

流淌在宫殿的墙上

但是大多数午夜的街道上,我听到

年轻的妓女如何诅咒

炸开新生婴儿的眼泪

用瘟疫摧残婚车

*args,**kwargs 的初级读本,数据科学家的装饰者

原文:https://towardsdatascience.com/a-primer-on-args-kwargs-decorators-for-data-scientists-bb8129e756a7?source=collection_archive---------14-----------------------

蟒蛇短裤

对于编码来说,理解是至关重要的

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

Photo by Almos Bechtold on Unsplash

Python 有很多构造,在我们的代码中学习和使用起来相当容易。当我们在代码中遇到一些构造时,它们总是让我们感到困惑。

还有一些甚至是经验丰富的程序员也无法理解的。装饰者就是属于这一类的一些构造。

我猜我的许多数据科学朋友也面临过这些问题。

大多数 seaborn 函数都以某种方式使用*args 和**kwargs。

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

或者装修工呢?

每次你看到一个警告,像一些功能将在下一个版本中被否决。sklearn包为此使用了装饰器。你可以在源代码中看到@deprecated。这是一个装饰函数。

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

在这个名为**'Python Shorts,‘**的系列帖子中,我将解释 Python 提供的一些简单构造,一些基本技巧和我在数据科学工作中经常遇到的一些用例。

这篇文章是关于用一种简单易懂的方式解释一些难懂的概念。

什么是*args?

简单来说, 你可以用 ****args*** 给你的函数任意数量的输入。

一个简单的例子:

假设我们必须创建一个将两个数相加的函数。在 python 中我们可以很容易地做到这一点。

def adder(x,y):
    return x+y

如果我们想创建一个函数来添加三个变量呢?

def adder(x,y,z):
    return x+y+z

如果我们想让同一个函数加上未知数量的变量呢?请注意,我们可以使用*args*argv*anyOtherName来完成此操作。重要的是*

def adder(*args):
    result = 0
    for arg in args:
        result+=arg
    return result

*args所做的是,它接受你传递的所有参数,并向函数提供一个可变长度的参数列表,你可以随意使用。

现在,您可以使用如下相同的函数:

adder(1,2)
adder(1,2,3)
adder(1,2,5,7,8,9,100)

诸如此类。

现在,你有没有想过 python 中的 print 函数怎么可以带这么多参数?

什么是**kwargs ?

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

简单来说, 你可以使用 ****kwargs** 给你的函数任意数量的关键字输入,并使用字典访问它们。

一个简单的例子:

假设您想要创建一个打印函数,它可以将姓名和年龄作为输入并打印出来。

def myprint(name,age):
    print(f'{name} is {age} years old')

简单。现在让我们说,你希望同一个函数有两个名字和两个年龄。

def myprint(name1,age1,name2,age2):
    print(f'{name1} is {age1} years old')
    print(f'{name2} is {age2} years old')

你猜对了我的下一个问题是: 如果我不知道我将需要多少个参数呢?

我能用*args吗?猜不到,因为姓名和年龄顺序至关重要。我们不想写“28 岁是迈克尔的年龄”。

来图中的**kwargs

def myprint(**kwargs):
    for k,v in kwargs.items():
        print(f'{k} is {v} years old')

您可以使用以下方式调用此函数:

myprint(Sansa=20,Tyrion=40,Arya=17)Output:
-----------------------------------
Sansa is 20 years old
Tyrion is 40 years old
Arya is 17 years old

请记住,我们从未将珊莎、艾莉亚或提利昂定义为我们的方法参数。

这是一个非常强大的概念。许多程序员在编写包装器库时非常巧妙地利用了这一点。

例如,seaborn.scatterplot函数包装了 Matplotlib 中的plt.scatter函数。本质上,使用*args**kwargs,我们也可以提供plt.scatter可以带给seaborn.Scatterplot的所有参数。

这可以节省大量的编码工作,并且使代码经得起未来的考验。如果在将来的任何时候plt.scatter开始接受任何新的参数,seaborn.Scatterplot函数仍然会工作。

什么是装修工?

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

简单来说: 装饰器是包装另一个函数从而修改其行为的函数。

一个简单的例子:

假设我们想在我们的一些功能中添加自定义功能。其功能是,每当调用函数时,打印“function name开始”,每当函数结束时,打印“function name结束”和函数花费的时间。

让我们假设我们的函数是:

def somefunc(a,b):
    output = a+b
    return output

我们可以在所有函数中添加一些打印行来实现这一点。

import time
def somefunc(a,b):
    print("somefunc begins")
    start_time = time.time()
    output = a+b
    print("somefunc ends in ",time.time()-start_time, "secs")
    return outputout = somefunc(4,5)OUTPUT:
-------------------------------------------
somefunc begins
somefunc ends in  9.5367431640625e-07 secs

但是,我们能做得更好吗?

这是装修工擅长的地方。我们可以使用 decorators 来包装任何函数。

from functools import wraps
def timer(func):
    [@wraps](http://twitter.com/wraps)(func)
    def wrapper(a,b):
        print(f"{func.__name__!r} begins")
        start_time = time.time()
        result = func(a,b)
        print(f"{func.__name__!r} ends in {time.time()-start_time}  secs")
        return result
    return wrapper

这就是我们如何定义任何装饰者。functools帮助我们使用wraps创建装饰者。本质上,在上面的装饰器中,我们在任何函数被调用之前做一些事情,在函数被调用之后做一些事情。

我们现在可以使用这个timer装饰器来装饰我们的函数somefunc

[@t](http://twitter.com/decorator_func)imer
def somefunc(a,b):
    output = a+b
    return output

现在调用这个函数,我们得到:

a = somefunc(4,5)Output
---------------------------------------------
'somefunc' begins
'somefunc' ends in 2.86102294921875e-06  secs

现在我们可以将@timer添加到我们想要打印时间的每个函数中。我们结束了。

真的吗?

连接所有的部分

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

如果我们的函数有三个参数呢?还是很多论据?

这就是我们到目前为止所学到的东西的联系。我们使用*args**kwargs

我们将装饰函数更改为:

from functools import wraps
def timer(func):
    [@wraps](http://twitter.com/wraps)(func)
    def wrapper(*args,**kwargs):
        print(f"{func.__name__!r} begins")
        start_time = time.time()
        result = func(*args,**kwargs)
        print(f"{func.__name__!r} ends in {time.time()-start_time}  secs")
        return result
    return wrapper

现在我们的函数可以接受任意数量的参数,我们的装饰器仍然可以工作。

Python 是不是很好看?

在我看来,装修工可能会很有帮助。我只提供了装饰者的一个用例,但是有几种方法可以使用它们。

您可以使用装饰器通过检查函数中的参数来调试代码。或者可以使用装饰器来计算特定函数被调用的次数。这可能有助于计算递归调用。

结论

在这篇文章中,我谈到了一些你可以在 python 源代码中找到的结构,以及你如何理解它们。

没有必要现在就在代码中使用它们。但是我想理解这些东西是如何工作的有助于减轻每当这些结构出现时人们所面临的困惑和恐慌。

对于编码来说,理解是至关重要的

另外,如果你想了解更多关于 Python 3 的知识,我想向你推荐密歇根大学的一门优秀的中级 Python 课程。一定要去看看。

将来我也会写更多初学者友好的帖子。让我知道你对这个系列的看法。在 媒体 关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。

朱莉娅的计算机视觉初级读本

原文:https://towardsdatascience.com/a-primer-on-computer-vision-with-julia-2c7068a35b32?source=collection_archive---------19-----------------------

学习如何使用 CNNJulia识别数字**。**

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

Image by cocoparisienne from Pixabay

这个帖子是关于卷积神经网络 (CNN)使用 Julia 的速成班。CNN 是一种奇特的功能,可以被“训练”来识别图像中的模式。在这篇博文中,我介绍了计算机视觉的**“Hello World”**:来自 MNIST 数据集的手写数字分类。互联网上有数以千计的免费 Python 教程。

而是让我们使用 Julia 和包 Flux.jl 。为什么?因为 Julia 的速度很快,如果你有数百万张图片要分析,与 Python 相比,速度会大大加快。这篇博文的 Jupyter 笔记本可以在这里找到。

数据

MNIST 数据集包含灰度手写数字(0 到 9)的图像,这些图像居中对齐。每个像素由一个介于 0(黑色)和 255(白色)之间的数字表示。每幅图像都是 28 乘 28 像素。表示图像的一种方式是将其视为 28*28 = 784 像素的一维列向量。然而,这种表示忽略了图像的“结构”:彼此靠近的像素在我们试图识别的数字上是有信息的。CNN 是一个很好的工具,可以保持图像的空间结构,同时避免与维度诅咒相关的问题:图像是嘈杂和高维的输入数据。

美国有线电视新闻网的速成班

CNN 的两个关键组成部分是卷积层(因此得名)和最大池层

卷积层

卷积层对每个点应用一个模板。卷积层的输出是较低维度的“图像”,它提供了输入图像的某些特征(形状、边缘等)的信息。).下图显示了卷积层的工作原理:

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

How a convolutional layer works. Source: https://mitmath.github.io/18337/lecture14/pdes_and_convolutions

最大池层

最大池层是一个模板,用于选择正方形内的最大值。下图是应用于 4x 4 图像的 maxpool 层:

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

Illustration of a maxpool layer. Source: https://mauriciocodesso.com/post/convolution-neural-network/

步幅和衬垫

构建 CNN 时,必须指定两个超参数:步幅和填充

  • 当跨度等于 1 时,我们一次移动一个像素的过滤器。当跨距等于 2 时,我们一次移动两个像素的过滤器,等等。
  • 填充是指在图像的边界“加零”。填充可用于控制输出音量的大小,并有助于保持图像边界的信息

下面是一个应用于 5×5 输入的 3×3 滤波器示例,该输入使用 2×2 步长填充了 1×1 零边界:

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

How padding works. Source: http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html

CNN 的典型基础设施是首先对输入图像应用卷积层,然后使用最大池层,最后使用全连接层。在使用全连接(FC)层之前,可以将几个“卷积层—最大池层”单元堆叠在一起。请注意,激活层(通常为 ReLU )通常插在卷积层和最大池层之间。

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

CNN architecture. Source: https://towardsdatascience.com/visualizing-the-fundamentals-of-convolutional-neural-networks-6021e5b07f69

使用 Flux.jl

Flux.jl 是 Julia 生态系统中领先的机器学习包。接下来,我们加载 MNIST 数据集的训练样本和测试样本。训练样本是一组用于微调 CNN 参数的图像,而测试样本包含用于检查我们没有过度拟合训练样本的图像。过度拟合的确凿证据是训练样本的精度比使用测试样本图像的精度好得多。

Loading Julia packages and data

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

CNN 架构

在使用 FC 层之前,我们的 CNN 有通常的 Conv->ReLU->MaxPool 组件。我们使用 1 乘 1 的填充,跨距为 1(默认值)。通过使用 2 乘 2 最大池层,输入的大小逐渐减小。Flux.jl 中的默认激活是函数 x->x。这里,我们使用校正线性单位函数(ReLU)来代替:

Building the model

ReLU 激活函数是分段线性函数。在 Krizhevsky 和合著者的“使用深度卷积神经网络的 ImageNet 分类”论文中,作者写道:

我们把具有这种非线性的神经元称为整流线性单元(ReLUs)。具有 ReLUs 的深度卷积神经网络比具有 tanh 单元的等效网络训练速度快几倍。

ReLU 激活功能也有助于减少由消失梯度问题引起的实际问题。也就是用来寻找我们 CNN 的参数的最小化算法的失败。下面是 ReLU 激活功能的曲线图:

xgrid = collect(range(-1, 1, length=100)) plot(xgrid, NNlib.relu.(xgrid), label = "relu(x)", title="ReLU activation function", xlabel="x")

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

ReLU activation function

培养

定量

批量大小是一个参数,它告诉我们网络在“训练”时一次会“看到”多少幅图像。用技术术语来说,当执行梯度下降时,我们不会一次使用所有信息(因为内存限制,也因为不一定高效)。以下函数生成“批量”图像:

Batching

损失函数和最小化

CNN 要“学习”任何东西,它必须有一个“错”或“对”的概念。损失函数正是通过量化模型在识别数字方面的表现来做到这一点的。当输出是一个概率时,交叉熵损失函数是合适的。最后一步是选择一种算法来最小化损失函数。这里,让我们选择 ADAM 算法,我把它理解为某种带有动量和自适应学习率的随机梯度下降:

Loss function

该模块“训练”(微调 CNN 参数值)模型,直到达到预定的精度水平:

Training

预言

一旦模型被训练,预测值很容易获得如下:

# Get predictions and convert data to Array: 
pred = Tracker.data(model(test_set[1])); 

# Function to get the row index of the max value: 
f1(x) = getindex.(argmax(x, dims=1), 1) # Final predicted value is the one with the maximum probability: 
pred = f1(pred) .- 1; #minus 1, because the first digit is 0 (not 1)

让我们看看模型在测试集上的表现。CNN 可以使用训练模型时没有使用的图像来识别数字吗?正如您在下面看到的,我们的模型在识别手写数字方面做得非常出色:

println("Predicted value = $(pred[1])") a = reshape(test_imgs[1], NROWS, NCOLS)Predicted value = 7

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

println("Predicted value = $(pred[2])") a = reshape(test_imgs[2], NROWS, NCOLS)Predicted value = 2

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

println("Predicted value = $(pred[3])") a = reshape(test_imgs[3], NROWS, NCOLS)Predicted value = 1

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

准确性检查

我们现在有了一个模型,它在识别数字方面似乎做得很好。但是我们能改善它吗?如果是,如何实现?为了改进我们的模型,我们首先需要确定它失败的时间和原因。

混淆矩阵

为此,一个有用的报告工具是混淆矩阵。混淆矩阵的每一行显示真实值的实例,而每一列显示预测值的实例。理想情况下,我们希望我们的模型能够完美地预测结果。对于一个完美的模型,所有的实例都位于混淆矩阵的对角线元素上。

我最后一次检查时,Flux.jl没有一个内置函数来计算混淆矩阵。幸运的是,包MLBase中提供了一个实现。下一个代码块计算混淆矩阵并显示出来。大多数实例位于对角线上,这并不奇怪,因为我们的模型的准确率超过 97.0%

using MLBase # Adding 1 to outcome because the index 0 in arrays does not exist in Julia:
Cm = confusmat(10, test_labels .+ 1, vec(pred) .+ 1)# Normalize output: 
Cm = Cm ./ sum(Cm, dims=2) # Labels 
xs = [string(i) for i = 0:9] 
heatmap(xs, xs, Cm, aspect_ratio=1, color=:plasma)

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

Heatmap for the confusion matrix

为了可视化我们的模型在哪里出错,我们可以使用可选参数clim,给底层的颜色图加上一个上限。例如,下一个图显示我们的模型在区分 7 和 2 或者 8 和 2 时有困难。

# Limits to colormap, so we can see where errors are located: 
xs = [string(i) for i = 0:9] 
heatmap(xs, xs, Cm, aspect_ratio=1, color=:plasma, clim=(0., 0.01))

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

Heatmap for the confusion matrix

误差分析

下一段代码显示了 CNN 失败的数字:

using ImageView, Gtk.ShortNames
# indices for errors: 
mistakes = test_labels .!= vec(pred) 
max_images = 5 grid, frames, canvases = canvasgrid((1,max_images));k=0#counter 
for mistakes for (j, i) in enumerate(mistakes) 
    if i == true k+=1 # a false value has been found 
       println("Predicted value = $(pred[j])") 
       println("True value = $(test_labels[j])") 
       imshow(canvases[1,k], test_imgs[j]) 
    end 
    if k >= max_images 
       break 
    end 
end 
win = Window(grid); 
Gtk.showall(win);Predicted value = 5 True value = 9 
Predicted value = 5 True value = 6 
Predicted value = 4 True value = 8 
Predicted value = 3 True value = 2 
Predicted value = 7 True value = 2

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

Five first prediction errors

虽然从左边开始的两个数字(见上图)显然是 9 和 6,但剩下的 3 个元素并不简单。中间的 8 很容易与其他数字混淆,剩下的两个数字形状怪异。

结论

在处理图像时,卷积神经网络通常在识别模式方面表现出色。这篇博文是对这个主题的非技术性介绍。而 Python 是机器学习中偏爱的工具(Keras,TensorFlow 等。),我猜测 Julia 会越来越受欢迎,因为 Julia 既好用又快。

参考

*这篇博文的代码大量基于这篇 Flux.jl 教程:https://github . com/flux ml/model-zoo/blob/master/vision/mnist/conv . JL
*关于 CNN 和 PDEs 的链接:https://MIT math . github . io/18337/lecture 14/PDEs _ and _ convolutions

原载于 2019 年 12 月 5 日https://Julien Pascal . github . io

模型拟合入门

原文:https://towardsdatascience.com/a-primer-on-model-fitting-e09e757fe6be?source=collection_archive---------18-----------------------

如何评估模型是否符合您的训练数据

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

数据科学本质上是使用数据来预测不同情况下会发生什么的实践。为了做到这一点,我们基于现有的数据集开发模型,然后使用这些模型来预测在相当类似的情况下会发生什么。这本质上是一种从已经发生的事情中学习的数学方法,并利用这种学习做出明智的选择。

这里显而易见的是,模型的预测和模型本身一样好。为了使模型返回准确的预测,它必须准确地匹配可用的数据集。如果它与可用的数据集不匹配,那么你可以肯定它不会返回不同情况下的准确预测。

模型怎么会和数据不匹配?

通常有两个术语用于描述模型如何无法匹配现有数据集。它们是:

  • 欠拟合:欠拟合模型是一种不够复杂,无法匹配可用数据的模型。它在匹配可用数据方面做得很差,因为它无法复制所有观察到的变化。欠适应模型的一个例子是,在一个累进税制结构的国家,有人根据统一税收假设来估计纳税额。在这种情况下,一个人支付的税收百分比随着其收入而变化,但该模型将假设每个人每美元的税率相同。
  • 过度拟合:过度拟合模型对于可用数据来说过于复杂。高复杂性使得模型对数据集有太多的改变,产生实际上并不存在的曲线和变化。它通常在匹配可用数据方面做得非常好,但无法准确预测数据点之间发生了什么。这种情况如何变得糟糕的一个例子是一个不确定模型的反面;一个基于累进税制结构(每一美元收入的税率都在变化)的假设的模型可能会正确地匹配每个人的纳税额,但对一个单一税制结构建模太复杂了。

图 1 提供了这些概念的可视化表示。用圆圈表示的系列称为“可用数据”,显示了累进税制结构下的理论所得税收入。假设的累进税制结构非常简单。第一万美元的税率为 10%,第二万美元的税率为 20%,第三万美元的税率为 30%,以此类推。增加了一点随机性,复制了不同家庭能够获得不同扣除额的事实(在美国税法中)。第二个系列用蓝线表示,称为“Underfit ”,是一个假设单一税收结构的模型。第三个数据系列名为“Overfit”,是一个 20 阶模型,假设了一个极其复杂的累进税制结构。

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

Figure 1: Underfit and Overfit Models for Our Theoretical Tax Structure

代表欠拟合模型的蓝线显然与数据拟合得很差。只有 3 点接近匹配的数据,要么高估或低估所有其他的。它也没有捕捉到数据的形状,没有捕捉到税率随着收入增加而增加的事实,产生了一个有点抛物线的数据集。

红线代表过度拟合模型,与可用数据几乎完全匹配。每一个数据点都以非常高的精确度匹配。它也很好地捕捉了数据的形状…直到年收入超过 40,000 美元。从每年 40,000 美元到 44,000 美元,该模型预测应付税款基本上没有变化,然后突然从每年 44,000 美元急剧增加到 45,000 美元。这个模型显然低估了这个范围。但真正的问题出现在 45,000 美元到 50,000 美元之间。该模型预测,当收入从 45,000 美元增加到 49,000 美元时,税收每年增加 22,000 美元,但没有任何数据表明这是准确的。然后,从每年 49,000 美元到 50,000 美元,预期税收减少 20,000 美元,以返回到匹配数据。该模型预测不存在的数据的趋势,并且无法预测可用数据点之间的税收值。

什么键可以识别欠拟合和过拟合模型?

当试图识别欠拟合和过拟合模型时,要寻找的关键点是图 1 的描述中提到的项目。为了明确地指出它们,这些不同类型的模型问题可以通过以下方式来识别。

可以识别欠拟合模型,因为它们:

  • 未能与可用数据点紧密匹配,以及
  • 没有捕捉到可用数据集的大致形状。

过度拟合模型可以被识别,因为它们:

  • 非常好地匹配可用数据(注意,这本身不能识别过度拟合模型,但应被视为警告信号),以及
  • 显示可用数据中不存在的预测趋势。

完美的模特是什么样的?

一个合适的模型应该与可用的数据紧密匹配(完美是最好的,但可能性极小),同时还要与数据的总体形状紧密匹配。图 2 提供了这种模型的一个例子。它呈现了与图 1 相同的总图,黑色圆圈仍然代表我们编造的数据集中可用的税收收据。绿线代表符合数据的三阶模型。

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

Figure 2: An Example of a Well Fit Model

请注意,代表三阶回归的绿线与可用数据并不完全匹配。这是不幸的,但却是现实的期望,尤其是因为数据集中包含了一点随机性。然而,它与每一个数据点都非常接近。此外,曲线的指数增长也符合可用数据的形状。对于可用数据来说,它既不像图 1 中的欠拟合模型那样过于简单,也不像过拟合模型那样过于复杂。相反,来自模型的每个预测都落在数据集中的高点和低点之间。因为它与数据的形状非常匹配,并且不会添加不准确的趋势,所以可以相信该模型在插值时会提供合理的预测。

我可以在哪里了解更多信息?

模型拟合,以及过度拟合和欠拟合的挑战,是数据科学中的核心概念。有许多不同的来源可以让你了解更多。我目前最喜欢的关于这些问题的讨论来源是 Joel Grus 的从头开始的数据科学。在我之前的一篇文章的中,我也提供了一个更加详细的模型开发和验证的描述。对于那些致力于投入大量时间尽可能多地学习的人,Coursera 提供了一门关于机器学习的优秀课程

包装它

模型开发和验证是数据科学中的核心概念。为了进行任何有价值的数据科学,我们必须拥有准确表示可用数据集的模型,并且我们相信这些模型能够很好地预测在类似条件下会发生什么。

导致模型返回较差预测的两个常见问题是欠拟合和过拟合。拟合不足意味着模型对于数据集来说不够复杂。这导致模型与测量的数据不匹配,并且不能模拟数据集的一般形状。过度拟合意味着模型对于数据集来说过于复杂。它会生成一个与模型极其匹配的模型,但会向数据集添加实际上并不存在的趋势。它看起来非常好,因为它与数据匹配得非常好,但是在插值时会产生非常不准确的结果。

一个非常适合的模型可能不会完美地匹配可用的数据。每一个预测都可能有一些误差。然而,它应该能准确地预测所有这些。此外,它应该捕捉数据集的形状,表明插值预测也将是接近的。

推荐引擎入门

原文:https://towardsdatascience.com/a-primer-to-recommendation-engines-49bd12ed849f?source=collection_archive---------19-----------------------

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

它们是什么,它们是如何工作的,以及它们为什么伟大。

推荐引擎现在无处不在。几乎你使用的任何应用都包含某种推荐系统,要么推送新内容,要么推动销售。推荐引擎是网飞告诉你接下来应该看什么,脸书上的广告推着你碰巧看过一次的产品,甚至是 Slack 建议你应该加入哪个组织渠道。大数据和机器学习的出现使推荐引擎成为数据科学最直接适用的方面之一。

假设你的朋友向你寻求电影推荐。你如何着手做这件事?如果你不太喜欢电影,而且不是你太了解的朋友,也许你可以谷歌一下,给你的朋友你找到的任何电影的答案。也许你的朋友告诉你他们最喜欢的类型是恐怖片——然后你推荐你知道的最好的恐怖片。或者,也许你的朋友给了你他们喜欢的电影的例子。然后你在脑子里处理这些数字,根据你对这些电影的了解和你对朋友的了解,给他们一些建议。这些场景中的每一个都是不同类型的推荐引擎的例子。

推荐引擎的类型

1.非个性化

非个性化推荐引擎是最简单的。你对你的朋友一无所知,对电影也知之甚少。你几乎没有数据,所以你只推荐了最受欢迎的东西,因为你的朋友很有可能会喜欢它,因为大多数人已经喜欢它了。

非个性化推荐引擎也非常容易实现,因为每个人都获得相同的推荐。你所要做的就是拿出一些指标来决定推荐什么,即最高评级、最高投资回报率(ROI)。还可以想想:YouTube 的新用户主页会推荐热门视频。

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

What does YouTube recommend to a new user?

看似琐碎,但非个性化的推荐可能非常有用。想象一下,你正在开展一项新的电子商务业务,你想在你的登录页面上发布产品推荐。也许这些产品已经在亚马逊上销售了,所以你可以看到这些产品的综合评分。如果你想提高销售额,你可能会决定推销评价最高的产品,因为你知道这些产品的客户满意度更高。你也可以决定推销给你最高投资回报率的产品,这样客户购买的每件产品都会给你带来更多利润。

2.基于内容

对于基于内容的推荐引擎,我们只处理项目数据。更具体地,项目的特征空间中的数据。例如,电影的项目数据包括预算、票房收入、类型、发行年份、演员等。

基于内容的推荐引擎背后的一个主要想法是相似性。想想在亚马逊购物——在它的产品页面上,你总会在产品下面列出类似的商品。这里使用的最简单和最直观的算法是一个最近邻算法,它使用一些相似性度量(如余弦相似性、欧几里德距离、皮尔逊相关等。)来确定与您的输入项目最接近的项目作为推荐返回。

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

Plant recommendations on the product page of a plant!

使用项目数据提出建议的一些其他方法:

  • 如果您想要一个用户的推荐,假设您有该用户的历史记录,即喜欢、不喜欢、评分… 您可以创建一个分类器来预测评分或某个项目是否会被喜欢/不喜欢。这也可以在聚合评级数据上完成,例如:获取 Yelp 上餐馆的总体评级,并使用餐馆功能,预测餐馆的评级。
  • 聚类方法可用于将项目组合在一起。这可以使最近邻方法运行得更快,因为不需要跨所有项目计算距离。
  • 当你有大量特征空间的数据时,比如图像,神经网络非常有用。我们可以通过(例如)卷积神经网络的倒数第二层来检索项目的嵌入,在这里更容易运行相似性度量来找到最相似的项目。

基于内容的推荐器(尤其是基于相似性的推荐器)非常适合推荐利基商品。也许出于某种原因,你真的很喜欢五分钱乐队臭名昭著的讨厌音乐。使用五分钱乐队的歌曲作为输入,基于内容的推荐器可能会向您推荐与五分钱乐队相似的歌曲,甚至其他五分钱乐队的歌曲,这取决于您的项目池。一个基于内容的推荐者不会考虑五分钱乐队的歌曲经常是低收视率的事实,除非你决定使用收视率作为一个项目特征。

这些超级具体的推荐是否是最好的取决于你的推荐者的背景。有时您确实想考虑用户特定的口味,有时又不想。如果你把恐怖电影输入推荐引擎,你只能得到其他恐怖电影的推荐。在不同的背景下,这可能是好事,也可能是坏事。

3.协同过滤

基于内容的推荐器仅使用项目数据,而协同过滤方法使用与项目相关的用户数据。更具体地说,检查来自特定用户的特定项目的数据。理想情况下,您的数据应该能够用一个效用矩阵来表示,一个轴是用户,一个轴是项目。

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

Utility matrix for 4 users (U) and 4 items (I).

效用矩阵通常是稀疏的,因为用户不会对所有项目进行评级。在上面的简单示例中,我们可以看到所有用户都对所有项目进行了评分,只有用户 1 对项目 3 进行了评分。协作过滤的工作原理是查看多个用户如何评价多个项目,或者多个用户如何评价多个项目,以尝试并猜测用户还会高度评价哪些项目。协同过滤的主要思想是填充效用矩阵的未知数,有几种方法可以做到这一点。

简而言之,计算空白值的一种方法是使用用户或项目之间的相似度,并对评分进行加权平均,以预测用户 1 对项目 3 的评分。该方法被称为用户-用户相似度项目-项目相似度**,这取决于计算相似度所跨越的轴。**

另一种预测未知用户项目组合评分的方法是通过流行的奇异值分解 (SVD)模型,这种方法因 2006 年 Netflix 奖竞赛期间的 Simon Funk 而闻名。该算法使用传统 SVD 的修改版本,通过生成表示用户和项目的两个分量矩阵,作为效用矩阵的分解,并通过交替最小二乘法执行梯度下降以得出评级预测。查看我的另一篇探讨协同过滤背后的数学的文章。

协同过滤不仅为每个用户提供个性化的推荐,还为数据集中的任何项目提供模型计算的预测评级,这可以方便地为用户提供关于项目的更多个性化见解。

尽管协同过滤(尤其是 SVD)已经被证明具有一些最有效和最准确的评级预测,但也有一些缺点。首先,有一个所谓的冷启动问题,你需要有大量的现有数据(关于他们如何评价多个项目的用户数据)才能开始计算评级。一个全新的用户将无法与任何人进行比较(因为没有关于新用户的数据),因此无法做出有见地的推荐。在进行任何类型的用户-用户或项目-项目比较之前,用户必须首先在系统中有一些评级。

协同过滤的另一个缺点是它的计算量太大(T4)。用户-用户和项目-项目模型的时间复杂度随着用户数量和数据集中项目数量的增加而增加。最后,往往会有一个受欢迎程度偏差,在这种情况下,经常被评为高等级的项目可能会对大多数用户有高的预测等级。

评估推荐引擎

在机器学习中,为了评估我们的模型,我们通常有一个成本函数来确定我们的模型表现如何。成本函数通常测量某种形式的误差,并给我们一种模型能够预测某种结果的感觉。对于推荐引擎,这仅在某些情况下有效。在协同过滤的情况下,可以进行典型的train-test-split来测试预测评级值与实际评级值有多远。

然而,对于基于内容的推荐引擎来说,这就不那么简单了。尤其是基于相似性的推荐,有一个潜在的假设,人们会喜欢与他们已经喜欢的东西相似的项目。并且这种相似性必须存在于数据中可用的特征/特性中。项目的复杂性和人们可以根据其喜欢程度的无限方面,使得很难评估基于内容的推荐系统实际工作得如何。有一个强力的解决方案——简单地向人们提供建议,然后看看这些建议效果如何。

接下来:

[## 数据科学的数学:效用矩阵上的协同过滤

理解推荐引擎协同过滤模型背后的数学原理

medium.com](https://medium.com/@yishuen/math-for-data-science-collaborative-filtering-on-utility-matrices-e62fa9badaab)

  • 用 Python 实现推荐系统(即将推出)

免责声明:我其实是五分钱乐队的粉丝。

以产品为中心的数据视图

原文:https://towardsdatascience.com/a-product-centric-view-of-data-e9b233eab6fa?source=collection_archive---------22-----------------------

如何从第一天开始就证明您的数据的价值

在我的职业生涯中,我有幸在许多技术本土公司工作过,在这些公司,敏捷性是业务的主要原则之一。然而,这种敏捷性源于这些公司的使命,即构建客户认为有价值的产品。像微软、亚马逊和 Expedia 这样的公司之所以能够持续增长,是因为它们使用数据进行内部优化,但通过为消费者构建新的数据智能产品来保护自己。

在过去的两年里,完全离开我在科技公司的舒适区,并在一个为我们的客户创造价值的绝大多数产品通常需要几个月时间,或者在推出新飞机的情况下,需要几年时间的行业工作,确实是一件有趣的事情。然而,仅仅因为一个业务不是数字化的,就没有理由不通过创造新的数据驱动的产品来推动公司走向未来。这可能只是需要多做一点工作,或者只是在政治上多一点难度。

所以,你可能首先会问。我的数据很好,为什么我要改变我使用数据的方式,或者我不知道你今天要求我改变什么。什么是产品思维,它与我们今天的工作方式有何不同?今天大多数项目组合管理团队运行数据构建的方式是以项目思维方式进行的。产品思维通常被视为数字团队领域的一部分。是的,“数字”团队……是的……那些被排挤的人藏在企业的一个不起眼的角落里,带着那些奇怪的白板、便利贴(wars)和纹身的潮人……或者更糟的是,给他们一个远离企业跳动的心脏的 WeWork 办公空间,因为他们不能整合(我的意思是……位于伦敦市中心的创新中心会有更高的效率)。我开玩笑(但我被允许)。我在这里支持的不是争论两者的优点和你应该选择哪一个,而是专注于其中一个的优点,作为从你的数据中获得更多价值的一种方式,甚至可能创建一个数据飞轮——这是我稍后将写的主题。

什么是产品思维模式,它与项目有何不同?

不想重新发明轮子,我发现这个定义是最有助于解释差异的定义之一。

产品是可以提供给市场以解决问题或满足需求的任何东西。

产品的生命周期由多个阶段组成。首先,产品被构思,然后被开发,然后在市场上被介绍和管理,最后,当对产品的需求减少时,产品被淘汰。

一个项目是为了创造一种独特的产品或服务而进行的临时性努力。对于一个项目,有一个明确的定义,什么需要在指定的时间内交付。

需要注意的是,一个产品只能在一个项目的环境中开发,而在一个产品的生命周期中可以有多个项目。

与项目不同,产品没有明确的定义需要交付什么。客户需求自然会随着时间的推移而发展,产品也必须发展以满足这些客户需求。

—孔比亚“产品和项目管理的区别”

非常简洁地:

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

产品:价值导向
项目:任务导向

许多数据团队首先以项目思维运作。这延伸到他们如何管理和治理数据、报告,甚至进行数据科学。定义的端点、设定的交付、以报告形式出现在表格中的数字,甚至是每季度一次可能对业务产生战略性影响的洞察。我在这个世界上已经呆了这么多年了。同样,这种思维方式本质上没有任何问题,它适合许多不同类型的数据追求——系统迁移、对现有 ERP 系统的更改请求或像 TPFs 这样的上世纪 70 年代遗留数据(不寒而栗)。

当用以产品为中心的观点来处理数据时,您日常工作方式的第一个主要变化是——“我的客户今天会受益于什么?”而不是“今天需要关闭的 CRs、票证等是什么?”一个公认的夸张,但我认为你得到了要点。

不可否认,大多数数据团队都是从真正的客户(在我们当前的案例中是乘客)中抽象出来的,这要困难得多。尝试告诉某人,您的数据团队需要 D3/Node/React javascript 开发人员将接口构建到当今的活动系统中,然后看着他们惊讶(不仅因为大多数人甚至不知道这些东西是什么,更不用说让数据(即分析团队)脱离操作系统)。大多数传统主义者将数据人员视为后端人员,这并不奇怪。我们大多数人都倾向于将自己的日常工作视为数据的守护者。

相反,从问题和解决用户问题的价值开始。“在我分析了 B 的数据并知道 C 是我需要采取的行动之后,我需要让 A 的行动变得简单得多。”衡量的结果本质上是你提供给最终用户/客户的价值。

我认识的大多数数据团队都止步于此,然后开始…“这不是我的问题。我给你 X 数据,BI 团队给你 Y 报告,数据科学团队给你 Z 洞察。”然而,这种思维模式实际上只实现了 B 部分或在紧要关头实现了 B 和 C 部分,并没有最终真正解决用户问题,这是 a。设计一个系统集成以允许用户严格做到这一点并不是一个数据问题。这种说法对于数据的项目/任务取向可能是正确的,但对于价值取向就不那么正确了。如果你真的想在持续的基础上证明分析的价值,进行测试和学习练习来证明你的数据的价值,那么是的,这个从根本上来说是一个数据问题。

这种心态如何改变团队的组成和他们关注的焦点?

数据工程优秀的数据工程师拥有不同于那些能够设计和构建优秀 API 的人的技能,这些技能也不同于那些能够构建优秀 UI 的人。根据用户的需要,您应该考虑在您的数据工程功能中使用非传统的技能。在我之前的一份工作中,我们雇佣了一个更专注于 javascript/UI 和少量数据的人来补充我们的数据工程团队。它产生了如此惊人的内部报告门户,然后它也将其作为面向外部的门户。

理想情况下,您的工程职能部门还应该拥有合适的软技能,以便加入数据产品团队,与您的业务和分析利益相关方举行构思会议。除此之外,这还意味着您采用持续集成管道,鼓励快速迭代和自动化,并且不严格要求团队在某个时间框架内发布(比如说,一个 sprint)。

数据产品
数据产品团队的职责不仅仅是做业务分析师以前会做的事情,即接受需求,发送回交付,他们的工作是利用其余的数据和分析功能,以及企业/消费者来找出解决方案,了解他们有什么问题以及如何用基于数据/驱动的产品来解决这些问题。

通过参与最终用户/消费者所需的解决方案的设计阶段,他们是整个数据团队和利益相关者的粘合剂。他们的评估和迭代不仅基于数据团队其他成员的优先级,还基于每个用例产生的客户价值(希望通过征求客户的反馈来获得)。努力将数据科学团队与消费者需求结合起来,引入其他部门,这些部门要么与消费者有现有的接口,要么在这些团队没有带宽或技能集的情况下建立自己的接口,您的数据产品人员是您的协作战略家,他们应该最深切地关心从数据中获取价值,无论数据如何到达消费者手中。

如今,大多数数据团队都缺乏这样的功能。如果他们这样做,它通常被用作提供数据管理的手段,而不是产品。允许他们主要关注提供最佳价值的解决方案(并与工程一起构建它们),而不仅仅是提供分析所需的数据。

注意:如果你有一个数据产品团队,他们不仅仅是你的记录员,不仅仅是你的搬运工,他们也应该是技术专家。仅仅因为您的数据科学团队在 R/Shiny 中构建了一些东西,并不意味着解决方案应该只是让它保持运行。这可能是最容易获得 MVP 的途径,但并不总是最有影响力的。

报告/商务智能和分析 许多报告和商务智能人员往往被视为系统高手,点击这里,在那里编写一些 SQL 代码,瞧,一张你需要的表格。我经常看到如此广泛和复杂的报告,以至于最终用户只抓住一个数字不放,像鹰一样监控这个数字,完全忽略了更大的画面。我很幸运有非常具有商业分析头脑的商业智能分析师,他们不只是想停留在基于网格的报告上,或者只是一份漂亮的报告。

以价值为导向的分析师总是更进一步——用户会从中受益吗?他们经常问的几个问题是——“我如何展示这个指标变化的驱动因素是什么?”“我如何创建正确的报告套件,这些报告相互链接,以便无缝使用?”通常,现有的报告工具,如 Tableau/Qlik/PowerBI,并不支持这种具有分析洞察力的报告。能够将 R 等分析工具集成到这些可视化环境中可能是解决这个问题的关键,但这意味着传统 BI 分析师或开发人员的技能组合发生了变化。一个我仍在试图破解的问题——但至少有一些优秀的分析师在尝试。

数据科学
最后,但肯定不是最不重要的,最热门的工作……我就讲到这里。除了构建智能汽车和机器人的真正 AI/ML 用例之外,大多数终端消费产品都有来自数据科学团队的深刻概念证明,并与工程功能相结合。专注于任务的数据科学团队往往首先关注模型的准确性,并在醒着的最后一刻调整模型以获得最佳解释值。同样,这很好,如果它们是一次性的战略上一致的项目,需要最准确的答案,永远不会被再次使用。以价值为导向的数据科学功能倾向于关注对客户的影响或变化,以及帮助客户完成变化以提高采用可能性所需的内容,最初牺牲了模型的准确性/复杂性,知道他们将随着时间的推移不断迭代。

Emily Glassberg Sands 概述了数据科学团队如何帮助构建优秀的数据产品。她的 HBR 文章讲述了如何建造它们的过程。然而,她从一个数字化的本土企业的角度来看,这个企业已经有了一个总体的产品功能。对于没有总体产品功能的公司,数据科学团队最适合与数据产品团队和业务部门合作,以实现整个解决方案。

客户 最后一点也是最重要的一点,打造优秀产品的数据团队中最不可或缺的一部分就是客户。现在,这里的客户有内部和外部两种形式,内部客户通常对错误/不正确的数据更加宽容。它们决定了产品的特性,并帮助我们理解产品的价值。没有它们,伟大的产品就不会存在,不管是不是数据驱动的。数据团队需要开发和构建让他们的生活更轻松的解决方案,这反过来又增加了他们的采用率和创造货币价值的能力。

以产品为中心的思维模式是当今大多数数据团队的范式转变。它让人们从以任务为导向,甚至简单的以结果为导向转变为以价值为导向。人们开始意识到,如果数据被用来推动正确的结果,它只是新的石油。石油以其最原始的形式存在了几千年,在我们找到造福人类的正确用途(产品)之前,它没有任何内在价值。数据作为推论是完全一样的。我们真正从数据中赚钱或创造价值的唯一方式是,我们的客户/最终用户从我们用数据创造的产品中受益。只有到那时,数据革命才真正扎根。因此,采取以产品为中心的数据观是创造可持续数据革命的下一步,这将使最终用户和公司都受益。

产品经理研究数据科学

原文:https://towardsdatascience.com/a-product-manager-tries-data-science-2c3570d8b480?source=collection_archive---------32-----------------------

作为一名有抱负的数据科学产品经理,我一直在寻找通过实践积累技术知识的方法。在这个项目中,我与一家在线订购餐馆的初创公司合作,建立一个推荐系统。我面临的挑战是创造性地扩展有限的数据集,并应用无监督和有监督的学习方法来克服与处理极其混乱的餐厅菜单数据相关的困难。

问题是…

从业务角度来看,我们希望随着时间的推移,增加客户保持率和客户收入。许多企业的一个常见模式(此处可见)是收入的很大一部分来自一小部分回头客。我的假设是,提供个性化的推荐可以增加单个订单的价值,随着时间的推移增加收入。

创建推荐系统有很多有据可查的方法,但是和往常一样,以正确的格式获取数据是关键!餐馆菜单通常按食物类型分类——意大利餐馆、印度餐馆等。对于阅读这些内容的人来说,我们能够很容易地解释这些菜单项并将其映射到一个类别。当我们亲自点餐时,销售人员很容易推荐我们可能喜欢的其他类别,这是很常见的——“你想喝点什么吗?”

对机器来说不是这样!在不同的项目之间建立有意义的相似性是困难的!例如,两家比萨饼店可能都供应 10 英寸的奶酪比萨饼。在一份菜单上,它被称为吉尔的 10 英寸玛格丽塔披萨,在另一份菜单上,它被称为著名的红酱披萨。对于一个销售数百万比萨饼的大型连锁店来说,有足够的交易量来解释有意义的模式。然而,对于小餐馆来说,连接看似不同的订单对于建立有意义的交易量是至关重要的,这种交易量可以用于概括所有餐馆。

从事 MyFitnessPal 应用开发的安德玛大学科学家的一篇论文很好地总结了为什么与传统的文本聚类相比,这个问题特别困难:

“我们的餐厅食物匹配问题有其独特之处,因为要匹配的给定文本(即餐厅菜单项)和应用程序数据库中的匹配文本(即食物及其描述)的长度都很短。此外,每个单词的词汇和语法结构对整体准确性的影响比标准设置中的情况更大:“肉酱意大利面”需要与“肉酱意大利面”区别对待。“词序对整体匹配准确率也有很大影响:“巧克力牛奶”应该和“牛奶巧克力”区别对待。”所有这些细微差别结合在一起,使得直接应用以前的文本匹配问题成为一个挑战。"

解决问题

当我在研究这个问题的潜在解决方案时,我看到了一篇博客文章,它解决了 Caviar 的一个非常相似的问题:

https://developer . square up . com/blog/caviars-word 2 vec-tagging-for-menu-item-recommendations/

这种方法对我来说很有意义(并且与我在 NLP 课程中涉及的主题很一致),所以我决定看看我是否能让它与我的数据一起工作!

为了解决连接不同菜单项的问题,Caviar 数据科学团队实现了一个 Word2Vec 模型。Word2Vec 是将单词输入映射到向量空间中的表示的神经网络,称为嵌入。它通过查看上下文来做到这一点——哪些单词经常在彼此附近出现?

通常,Word2Vec 模型使用 预训练嵌入——其他人在数十亿个例子上做训练模型的艰苦工作,向量表示可以被提取出来并用于像我这样的任务。然而,在这种情况下,我发现预训练的嵌入是不够的。

网络抓取走向胜利

不幸的是,我最初的数据集只包含 50,000 个不同的菜单项。当我训练 Word2Vec 模型时,向量被证明不足以生成有意义的下游结果。

我需要增加训练数据的大小。经过一些研究,我偶然发现了 all menu s,这是一个全美餐馆菜单的聚合器。

为了建立一个网络刮刀,我求助于 Scrapy 。Scrapy 提供了一个强大的框架,抽象了 web 抓取的许多更具技术性的方面(节流、异步作业),允许我专注于识别和捕获我需要的数据。

有了新的 web scraper 在手,我能够获得超过180 万个独特的菜单项及其描述——大大增加了我的培训数据!

使用无监督学习创建食物类别

有了新数据,我用 Gensim 包训练了一个 Word2Vec 模型。与只对 5 万个菜单项训练模型时不同,我现在可以看到单词之间有意义的联系。看看和“煎饼”最相似的前 10 个词——所有的早餐食品,正如我们所料!

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

尽管这很酷,但总体目标是比较相似的菜单项,而不仅仅是单个单词。回到我们最初的例子,我们最终的模型应该考虑吉尔的 10 英寸玛格丽塔披萨著名的红酱披萨都是披萨。**

为了做到这一点,我应用了鱼子酱数据科学家使用的相同技术——对于给定的菜单项(比如‘蓝莓煎饼’),我对‘蓝莓’和‘煎饼’的词向量进行平均。

假设这行得通,我应该能够使用聚类算法将菜单项分组在一起。我使用 KMeans 集群,在 20 到 50 个集群之间进行测试和验证。通过手工检查,我发现 30 产生了最有意义的集群。

这些聚类很好地映射了人类对菜单类别的理解。我能够凭直觉找到啤酒、葡萄酒、甜点和其他多种菜肴的类别!下图显示了一些示例集群中菜单项的顶部单词。

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

Wordclouds generated from the menu items included in 3 clusters

最后,我使用 t-SNE 可视化集群,这是一种降维方法,特别适合二维可视化。当用聚类数着色时,结果显示出清晰可辨的类别。

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

Visualizing Menu Item Vectors through t-SNE

使用监督学习提出建议

最终目标是在客户下订单时提供额外的建议。当客户在线订购时,商品会一次一件地添加到购物车中,订购流程如下所示:

[10 英寸马里纳拉披萨]

[10 英寸马里纳拉披萨,1 20 盎司可口可乐]

[10 英寸马里纳拉披萨,1 20 盎司可口可乐,1 个奶油甜卷]

在上面的例子中,我们想向只点披萨的顾客推荐可口可乐或奶油甜卷,目的是提高他们对订单的满意度,增加订单量。

我通过模拟上面的订购过程创建了训练数据。首先,我使用 K-Means 模型来预测事务中的每个菜单项应该属于哪个类别。对于每个事务,我遍历事务中的所有项,每次取出一项作为预测的目标,其余项作为特征。这创建了 160 万个事务示例作为训练数据。

将这些分为训练和测试数据,我使用 SKLearn 库对训练数据训练多项逻辑回归模型。该模型在测试数据上预测扣留类别的准确率达到 71%。

一些简单的比较基准是选择一个随机的类别和最受欢迎的类别。随机分类将产生 3%的准确度(30 分之一的机会)。一个每次都能猜出最受欢迎类别的虚拟模型有 10.3%的正确率。逻辑回归模型实现了比这些原始基线更高的准确性。

讨论和后续步骤

结果向我表明,客户订购模式中有规律可循,可以用来提出建议。在目前的状态下,该模型足以提供简单的建议。如果顾客点了一道主菜,但没有点饮料,则该模型可以预测该菜应该配有饮料。推荐餐馆最受欢迎(或最赚钱)的饮料是一个可行的当前策略。

然而,顾客偏好的异质性限制了该模型在当前水平上的有效性。聚类的粒度虽然很好,但仍不足以做出真正的推荐。例如,该模型可能能够建议客户在汉堡订单中添加一道配菜,但不能有效地推荐薯条或配菜沙拉。这个项目的下一步是进一步细化类别,使之更加细化。

下一步是通过在逻辑回归模型中加入额外的特征来提高预测的准确性和质量。关于顾客先前点了什么或者餐馆菜单上什么项目最受欢迎的元信息可以从现有的交易数据中获得,我希望这将对模型产生重大影响。

然而,也许更重要的是,除了推荐方面之外,以完全无监督的方式将字符串聚类为不同的餐馆菜单项的过程仍然提供了显著的好处。将新菜单项标记和分组到类别中的过程现在可以自动化,并用于创建更好的菜单和业务分析。

虽然这还没有变成一个真正面向客户的项目,但获得一些真实世界的数据是一种很棒的体验。我研究了各种技术,创建了一个训练数据集,并应用了监督和非监督学习,所有这些都是在实现业务目标的背景下进行的,并在此过程中学到了很多东西。

面向并发后台请求的 Rest API 解决方案

原文:https://towardsdatascience.com/a-python-api-for-background-requests-based-on-flask-and-multi-processing-187d0e3049c9?source=collection_archive---------2-----------------------

使用 Python flask 和多重处理,逐步构建在后台运行耗时请求的 Rest API

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

Photo by Safar Safarov on Unsplash

这个帖子也可以在大数据日报Linkedin 找到。

这篇博客将首先向您介绍 Rest API,解释它的基础知识以及我们可以使用 Rest API 做什么。之后,我们将一起使用 Python flask 包构建我们的第一个 API。最后,我们将通过一个通用代码框架,使用多处理模块在后台运行耗时的作业。整个项目的源代码可以在 Git 找到。

Rest API 基础介绍

首先,让我简单解释一下什么是 API,它能帮助我们什么。简单地说,API 是一个运行在主机上的程序,它监听一个端口来接收和响应来自互联网的 HTTP 请求。假设我们想要求解一个超出我们知识范围的方程,有人开发了一个运行在主机上的求解器 API,那么我们只需在浏览器中粘贴一个 URL:http://host:port/equation?x+8=20 。看多简单!如果我们有一些复杂的任务不适合在我们的前端 UI 中实现,或者我们有凭证数据,我们希望将它们从我们的 UI 中分离出来,API 就是解决方案。然后前端需要知道的是与 API 通信的接口,简单地向它发送请求。前端不会执行任务或接触凭证数据。

在剩下的部分,我将一步一步展示如何基于 flask 和多处理模块构建一个在后台运行请求的 Python API。这些步骤应该很容易遵循,即使你没有使用 flask 或 API 的经验。

使用 Flask 构建您的第一个 API

作为开始,让我们首先构建一个简单的 API 向世界问好。对于已经熟悉 flask API 的人,可以跳过这一部分。

现在,让我们将其保存为 intro_api.py ,并作为“ python intro_api.py 运行。您已经成功构建并运行了一个 API。够简单吗?那就叫吧!我们需要做的只是在我们的浏览器中复制并粘贴http://0 . 0 . 0:6060/。看到了吗?我们的网页显示“你好,世界!”,这正是我们在 API 中定义的。让我一行一行地解释这个脚本。首先,我们导入 Flask 包,并使用 Flask(name) 创建一个 API,其名称作为模块的名称。然后我们定义一个函数来响应 rout path 发来的 HTTP GET 请求,即 host:port/ 。在这里,route decorator*@ app . route()*包装了将由 URL 调用的方法。即使你对 route decorator 没有任何概念,它也会影响你在这篇博客中对 flask API 的理解。但是我想强调两点。(1)注意 @app.route(‘/’,methods=[‘GET’]) 中的’ / ,它定义了用来调用这个方法的 URL(http://0 . 0 . 0 . 0:6060/),即 hello_world() 。(2) methods=[‘GET’]) 定义了方法只会被 HTTP GET 请求调用。

然后我们在本地主机(即 0.0.0.0)运行这个 API,在 main 函数中 port=6060。请注意,我们在开发环境中通过调用 app.run() 来运行它,这并不是特别高效、稳定或安全。让我们使用包 女侍 来代替生产服务器运行 API。然后主机变成运行我们 API 的计算机的 IP 地址。注意我们使用 CORS 包来允许跨来源访问,否则一些现代浏览器可能会拒绝访问我们的 API。在 https://www.codecademy.com/articles/what-is-cors 查看更多关于 CORS 的信息。

定义另一种路由方法

接下来,让我们通过定义另一个 route decorator 及其相关方法,在我们的 API 中做一些实际的工作。该方法将响应 HTTP POST 请求。

这里 request.json 是 json 格式的请求体。请求主体将从前端 UI 发送到后端 API,它总是用于从前端向 API 发送一些附加信息。请记住,API 可以被同时调用多次,因此每个会话(即调用)都有自己的请求体。比如说,A 和 B 都是通过http://host:port/task/job _ Ahttp://host:port/task/job _ B用不同的请求体调用 API。然后,每个会话将在内存中拥有自己的请求体,即 A 和 B 将触发相同的函数,但使用不同的 request.json 变量运行。注意,job_id 应该是 uuid 的格式,因为我们在装饰器中定义了 < uuid:job_id >

使用多重处理在后台运行请求

到目前为止还好吗?上面的函数非常简单,它接收一个 POST 请求并获取其主体,然后运行一些任务并将输出响应给客户端。但是,如果这项任务非常耗时,比如说运行一个机器学习模型需要几分钟,那该怎么办?该程序将平稳运行,直到 run_task() 为止,然后它将挂起,因为 run_task() 将需要几分钟的时间返回。我们的网页将被封锁,用户不得不等待它的完成,没有任何其他选择,例如提交另一份工作。这当然不是我们愿意看到的。一个简单的解决方案是使用多处理在后台运行任务。另一个解决方案是消息队列,基本上 API 将只设计为将作业信息推送到消息队列,然后返回到前端,而 dameon 服务将从消息队列中提取消息并运行真正的任务。关于它的更多细节可以在我的另一篇博客中找到:Google 云平台并发消费者的通用框架 Pub/Sub

在这里,我们在后台进程中运行 run_task() ,而不等待其完成,并通知客户端作业已收到。在这种情况下,网页将不会被阻止,用户可以在该网页中执行一些其他操作,例如提交另一个作业。但是缺少的一点是,当工作完成时,用户不会得到通知。然后我们需要在 run_task() 中记录作业的状态。

如果作业有并发限制会怎样?假设我们只能运行 4 个并发 run_task() ,那么其他请求应该处于等待状态。此外,我们只允许处理 8 个并发请求,即等待和运行。在这个场景中,我们需要一个数据库来记录请求的状态,以帮助检查工作人员的可用性。

结论

现在我们已经构建了我们的第一个 Rest API,并暴露在后台运行耗时请求的代码框架中。希望你会发现它很有趣和有用,也许你会想建立一个 API,让其他人与你的机器学习模型进行交互。

Python 初学者的看法。通信线路(LinesofCommunication)

原文:https://towardsdatascience.com/a-python-beginners-look-at-loc-part-1-cb1e1e565ec2?source=collection_archive---------7-----------------------

从熊猫数据框架中选择行和列

作为一个 Python 初学者,使用.loc来检索和更新 pandas 数据帧中的值对我来说并不合适。Python 不断扔给我的SettingWithCopyWarning消息清楚地表明我需要使用它,但感觉像是大量的试错消息来让它做我需要的事情。

我坐下来玩了足够多的时间,现在我开始感到舒服了,所以我想我应该分享我的漫游;如果你是初学者,希望它能帮助你。在这篇文章中,我将讲述如何通过.loc获取数据;我将在未来的文章中讲述如何设置数据。

我在亚特兰大大会上第一周的数据科学沉浸式课程时,使用了一个神奇宝贝数据集(#dadjokes)进行了“探索”。

这里是df.head(10)的样子:

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

Header for the Pokémon dataframe I tested with

使用检索数据。通信线路(LinesofCommunication)

可索引属性,而不是方法

我的第一个提示是.loc不是一个数据帧方法;一个周六,用()代替[]花了我 45 分钟。在这些方括号中,.loc接受两个输入:一个行“索引器”和一个(可选的,用逗号分隔)列“索引器”:没有其他参数,像inplaceaxis

单个标签、切片和列表

那么你能用什么作为索引器呢?pandas 文档列出了允许的输入,它讨论的第一个是单个标签,所以让我们开始吧。

传递一个索引器(因为这个数据帧是 RangeIndex,我们传递一个整数)将返回一个 pandas 系列,其中包含具有该索引值的行的数据,在本例中是小火龙:

df.loc[4]Name              Charmander
Type                    Fire
Total                    309
HP                        39
Attack                    52
Defense                   43
SpecialAttack             60
SpecialDefense            50
Speed                     65
Name: 4, dtype: object

.loc总是将整数解释为标签,而不是沿着索引的整数位置(你可以使用[.iloc](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html)来解释)。

只传递一个列标签或一个空白行索引器会给你一个错误,因为括号索引的第一个位置是寻找索引,它是必需的:

>>>df.loc['Type']
KeyError: 'Type'>>>df.loc[, 'Type']
SyntaxError: invalid syntax

但是在使用 Python 切片符号指定您想要的行(例如[:]指定所有行)之后,传递列标签将得到 pandas 系列中的列数据。注意,与通常的 Python 约定不同,**.loc** 切片包括两个端点:

df.loc[:5,'Type']0    GrassPoison
1    GrassPoison
2    GrassPoison
3    GrassPoison
4           Fire
5           Fire
Name: Type, dtype: object

行和列索引名的切片能力是.loc的一个很好的优势,因为数据帧上的普通括号符号不允许这样做:

df.loc[:5,'Type':'Speed']

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

您还可以传递带有行或列索引名称的列表来获取数据的子集。(列表理解工作也是!):

df.loc[[2,4,10,99],['Name','HP']]

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

布尔列表

您可以作为索引器传递的最后一种类型的值是布尔数组,或者是一列TrueFalse值。当我们开始使用.loc设置值时,这种方法有一些真正的力量和巨大的应用。对应于索引器中False值的行和列将被过滤掉。数组的大小不必与对应的索引相同,但是.loc会将丢失的值视为False:

df.loc[
       [True, False, False, True, True],
       [True, False, True, False, False, True]
]

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

您也可以使用布尔掩码来生成您传递给.loc的布尔数组。如果我们只想看到“火”类型的神奇宝贝,我们将首先生成一个布尔掩码— df[‘Type’] == ‘Fire’ —它为数据帧中的每一行返回一系列True/False值。然后,我们将该掩码作为行索引器在.loc中传递:

df.loc[df['Type'] == 'Fire']

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

The first several rows of the Boolean-filtered dataframe.

这里有各种可能性,比如获得超过 175 次攻击的神奇宝贝:

df.loc[df['Attack'] > 175]

或者那些生命值少于 100 而总属性超过 650 的人:

df.loc[(df['HP'] < 100) & (df['Total'] > 650)]

或者那些名字中带有字母“X”或“灵媒”类型的人:

df.loc[
    (df['Name'].str.contains('X')) |     
    (df['Type'].str.contains('PsychicFairy'))
]

当然,您可以在数据帧上用普通的括号符号来完成大部分工作,那么有什么特别的呢?在这篇文章中,我将讨论.loc如何允许你在数据帧中设置值。

Python 初学者的观察。通信线路(LinesofCommunication)

原文:https://towardsdatascience.com/a-python-beginners-look-at-loc-part-2-bddef7dfa7f2?source=collection_archive---------12-----------------------

在 pandas 数据框架中设置行和列值

作为一个 Python 初学者,使用.loc来检索和更新 pandas 数据帧中的值对我来说并不合适。在之前的帖子中,我分享了我所了解到的关于.loc检索数据的情况。今天,我们将谈论设置值。

作为复习,这里是我们正在处理的神奇宝贝数据的前 10 行:

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

将一组单元格设置为单个值

使用.loc设置数据值很容易,所以让我们将 Mega Venusaur 的值设置为0。只需将指标值传递给 Mega Venusaur 出现的行(即3):

df.loc[3] = 0
df.head(5)

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

现在,让我们通过传递所有行(带有:)和列名来重置所有神奇宝贝到60的“速度”统计:

df.loc[:, 'Speed'] = 60
df.head(5)

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

最后,让我们把所有“灵异精灵”类型的神奇宝贝的生命值更新为42。(如果你需要一个关于如何构建布尔掩码的复习,请看这篇文章。)

df.loc[df['Type'] == 'PsychicFairy', ['HP']] = 42

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

使用这种方法,.loc表达式返回的每个单元格都将被更新为您指定的值,并且它们将直接在 dataframe 中被更改*,因此最好先测试一下您是否得到了您期望的行/列,而无需设置值。例如,当我构建这个例子时,我无意中在列索引器中有了['Name', 'HP'],所以我最终得到了一堆名为‘42’的具有42生命点的 PsychicFairies,并且我必须重新加载我的数据。*

将一组单元格设置为一组不同的值

但是如果您需要为一组单元格设置不同的值呢?你所需要的只是一个你想要设置的值的列表(在形状上等同于你的.loc语句返回的数据),而.loc会为你做这件事。

举个例子,假设我们想改变火型神奇宝贝的名称,使其包含🔥表情符号:

  1. 为火焰类型创建一个布尔遮罩:df[‘Type’] == ‘Fire’
  2. 将掩码传递到 DataFrame,以过滤火类型神奇宝贝的行:**df[**df[‘Type’] == ‘Fire’**]**
  3. 通过分割 DataFrame: df[df[‘Type’] == ‘Fire’]**[‘Name’]**)来隔离 Name 列。
  4. 接下来,使用掩码建立列表理解,以生成新的表情符号增强的名称。我们将把它赋给一个名为new_names : new_names = **[‘🔥’ + name + ‘🔥’ for name in** df[df[‘Type’] == ‘Fire’][‘Name’]**]**的变量。
  5. 最后,使用步骤 1 中的布尔掩码和Name列作为.loc语句中的索引器,并将其设置为 fiery 名称列表:
**df.loc[df['Type'] == 'Fire', 'Name']** = new_names

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

对多个列的更新也很容易。并且.loc将在任意数量的行&列中设置值;只传递相同维度的值。

让我们改变一些心灵精灵类型的攻击和特殊攻击值。

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

这里我们将让.loc引用三行两列,以及一个相同维度的值列表,我们就可以开始了。

rows_to_update = [305, 306, 487]
cols_to_update = ['Attack', 'SpecialAttack']
values = [[87,88],[187,188],[287,288]]df.loc[rows_to_update, cols_to_update] = values

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

以上就是我对.loc的了解。你有什么问题?其他提示?

python flask 应用程序,使用文本分析根据用户输入预测性格类型。

原文:https://towardsdatascience.com/a-python-flask-app-that-predicts-the-personality-type-on-the-basis-of-user-entries-using-text-1269d6f644bd?source=collection_archive---------14-----------------------

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

Vertical Flow by I Rice Perreria

Irene Rice Perreria 的上图(名为《垂直流动》)是我最感兴趣的一幅作品。对我来说,它描述了颜色的异质性,同时也描述了这些不同的颜色如何来源于同一种本质。一天结束时,颜色在光谱上起作用,而不是作为单独的点。人们可以认为,人类的性格也在一个相似的光谱上运行,而不是孤立的,不同的性格类型在这个光谱上不断地重合和分离。在本文中,我描述了一个应用程序,它使用 python 中的文本分析,帮助用户预测自己在迈尔斯布里格斯性格谱(16 种性格)上的性格。最终的应用程序部署在 heroku 上,可以在这里访问。该应用程序是用 python 开发的,使用“flask”进行应用程序开发,使用“sklearn”的“tfidvectorizer”进行文本分析。

用于分析数据和我们的关键问题

用于分析的数据是一个数据库,包含 reddit 用户对应不同性格类型的帖子。数据库可以在 kaggle 这里访问。这是一个免费、开源、公共领域的数据集。我们将创建一个个性查找应用程序,用户可以输入任何一组描述自己的单词。该应用程序将运行计算用户输入的文本与来自个性类型数据库的各种条目的相似性得分,以预测个性类型(16 种 Myers Briggs 个性之一)。它还将预测四个迈尔斯·布里格斯特征的可能性,如内向/外向、直觉/观察力、思考/感觉和判断/感知。下面的视频展示了最终的实际应用。该应用程序将显示前 5 个预测的相似性得分,使用户知道适合她或他的性格谱。

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

应用程序的结构

这是一个传统的 flask 应用程序,我们需要首先定义一个结构。我们将使用的结构是一个标准的 flask 应用程序结构,带有一个包含用户界面和托管结果的 index.html 文件,以及一个包含创建应用程序的代码的 python 文件。

#Structure of the flask application----Root folder
    --Base data files #This is basically just the csv with the base data from kaggle
    --application.py #This is the main python code file
    ----templates
        --index.html #The templates folder contains our index.html file with the user interface
    ----static
        #The static folder contains any images we will want to display in the application. 

下面是应用程序中数据流的图示

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

定义用户界面(index.html)

所以,让我们从用户界面本身开始。index.html 文件的第一部分很简单。这只是一些描述应用程序本身的基本文本和上面这幅画的简单图像,我们将把它放在我们的“静态”文件夹中。这看起来像是

<html> <head><section>  <img class="mySlides" src="/static/Vertical.jpg"  style="height:50%" style="width:100%">  </section> <h1> Personality finder (developed using text analysis)</h1> <p> Find your personality type using this python flask application that makes use of a text vectorizer to analyze    posts by individuals identifying as different personality types. The app will yield your top 5 personalities from the     16 Myers Briggs personality types. Data downloaded from kaggle. By the way the paiting displayed here is "Vertical Flow" By I.Rice.Pereria.</p>    <p> Please note that the script might take a minute to run since it has to parse through over 8000 entries.</head>

现在,让我们创建一个表单,用户可以在其中提交我们将用于文本分析的单词或句子。这是一个简单的 html post 表单,带有一个提交按钮。我们将不得不跟踪我们分配给表单的名称,因为这将在后端使用。

<form method="post" > <input name="**question1_field**" placeholder="enter search term here"> <input type="submit"></form>

我将跳过对 html 页面 css 样式的解释。最后,我们将创建一个表,为用户输出前 5 个条目。我们还将打印出各种标题,如个性类型、相似性得分、搜索术语、行等。我们需要在 html 中定义表头(“th”)和表数据(“td”)。让我们先定义头部,

#Each of the heads is some data that we want to print out for the user<h2>Relevant personality types displayed below</h2>
<table>  
<tr>    
<th>Type</th>    
<th>SimiScore</th>    
<th>Search Term</th>    
<th>Rank</th>    
<th>Introversion/Extraversion</th>   
<th>Intuitive/Observant</th>    
<th>Thinking/Feeling</th>    
<th>Judging/Perceiving</th>    
</tr>

现在,数据将从 python 端引入。所以我们可以使用一些 jinja 代码来有效地访问我们的 python 数据帧变量。我们将在后端“文档”中调用我们的 python 数据框架。Jinja 将允许我们迭代这个 python 数据帧,如下所示。现在,调用每个变量的顺序应该类似于我们在上面的块中定义的头的顺序。

{% for doc in docs %}
<tr>
<td>{{doc["type"]}}</td>
<td>{{doc["Simiscore"]}}</td>
<td>{{doc["Search Term"]}}</td>
<td>{{doc["Rank"]}}</td>
<td>{{doc["Introversion/Extraversion"]}}</td>
<td>{{doc["Intuitive/Observant"]}}</td>
<td>{{doc["Thinking/Feeling"]}}</td>
<td>{{doc["Judging/Perceiving"]}}</td> 
</tr>
{% endfor %}
</table>

定义后端(python)

完整的后台 python 代码文件可以在这里访问。显然,第一步是导入所有需要的 python 库。因为我们将在 python 中使用文本分析,所以我们需要从 sklearn 包中导入 Tfidvectorizer 函数。此外,让我们继续在 flask 中创建应用程序本身。我们还将为应用程序创建一个标准的 get 和 post 路由,这样我们就可以有效地向它发送数据和从它那里接收数据。

#Import required packagesfrom flask import Flask, flash, redirect, render_template, request, session, abort,send_from_directory,send_file
import pandas as pd 
import numpy as np
import json
import xlrd
from sklearn.feature_extraction.text import TfidfVectorizer#Create a flask application
application= Flask(__name__)#Create an application route
@application.route("/",methods=["GET","POST"])

现在让我们使用 flask 应用程序中的主页功能来定义主页上将会发生什么。现在,在这里我们将首先尝试调用用户在上面定义的 html 表单中输入的数据。正如我们所知,表单本身被称为“问题 1 _ 字段”。我们可以使用一个调用表单数据的简单请求函数来访问这些数据。我们还可以指定一个默认单词,在用户没有选择任何单词的情况下将调用这个默认单词(本例中的默认单词是‘Education’)。让我们也使用 pandas 读入原始数据本身作为数据帧。我已经从 kaggle 的 reddit 数据中清理了用户条目。一个干净的 csv 版本可以在这里访问。下面是数据集的截图。文章栏包含用户的多篇文章。请注意,这是一个开源数据集,可在 kaggle 上获得,不包含任何机密信息。

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

def homepage():
#Call value from HTML form  
words = request.form.get('question1_field', 'Education')#Read raw data as a dataframe
datasource1 = pd.read_csv("Personalities.csv")

处理多个单词- 用户可以输入多个单词作为单个条目的一部分。我们希望将这些单词拆分成多个条目,以便在对所有单词一起进行分析之前,可以分别对每个单词进行文本分析。我们还想为每个单词过滤数据帧中的帖子,并将这些过滤后的帖子放入我们将使用的不同数据帧中。因此,让我们为此创建另一个数据帧。创建了这个新的数据框架后,让我们删除重复的内容,以防相同的帖子被选中两次。

#Separate words into multiple entrieswords = words.split() #(This will be stored as separate items in a list)#Filter the data for posts that contain either of these words
datasource=[]for i in words:      
    d2 = datasource1[datasource1['posts'].str.contains(str(i))]          
    datasource.append(d2)

datasource = pd.concat(datasource, ignore_index=True)
datasource = datasource.drop_duplicates()

好了,在我们继续之前,让我们来讨论一下什么是相似性得分,以及在给定的上下文中,我们如何以及为什么要计算它。相似性得分或“成对相似性得分”基本上是特定单词与条目中其他单词的距离。所以基本上,如果一个用户说“我爱金属”,这些词将与提到任何与金属相关的帖子有很高的相似度。由于每个帖子对应一种性格类型,我们可以从技术上“预测”用户的性格与发帖用户的性格类型相似。

tfidf 矢量器将计算特定帖子中出现的单词的频率和重要性。因此,如果在上面的例子中,如果帖子中的单词 metal 只是偶然出现,tfid 得分将非常低,从而产生低相似性得分。tfid 矢量器将根据单词的频率及其唯一性来计算其得分。在本文中,我不会详细介绍 tfidvectorizer 的工作原理。因此,为了计算用户文本和文章文本之间的相似性,我们需要在一个数据帧中并排显示这两个值。我们已经有一个过滤的数据框架与用户的相关职位。让我们创建一个名为 documents 的空数据帧,用于文本分析。我们希望在每次用户文本改变时清除数据帧。所以,我们可以在下面的 for 循环中调用它。

 for i in range(0, len(datasource)):      
    documents = []      
    documents.append(words)      
    documents.append(datasource.loc[i, 'posts'])

现在,对于 dataframe 中的每一个条目,我们要计算文章相对于用户条目的 tfidf 分数。这可以通过 tfidvectorizer 函数来实现。该功能允许我们指定停用词,即该功能应忽略冠词(a、an 等)的词。)和介词(over,under,between 等。).因此,如果我们将函数中的 stop_words 参数设置为“english ”,这些单词将被自动忽略。添加 tfid 矢量器来计算每个条目的分数,我们的函数现在看起来如下。

for i in range(0, len(datasource)):      
    documents = []      
    documents.append(words)      
    documents.append(datasource.loc[i, 'posts'])

      tfidf = TfidfVectorizer(stop_words="english", ngram_range=(1, 4)).fit_transform(documents) #tfidf is the tfidf score we compute for this post with respect to the entered text.

现在我们知道了用户在每个选中的帖子中输入的单词的重要性。但是我们现在想要使用这个 tfidf 分数来计算相似性分数,即用户输入的单词与帖子中输入的单词有多相似。相似度也可以定义为单词之间的余弦距离。这篇来自堆栈溢出的帖子详细解释了成对相似性的计算。简单的解释是,您可以通过将 tfidf 得分乘以其转置来计算成对相似性。这产生了一个相似性矩阵,访问这个矩阵的第一个元素将给出相似性得分。我们还将格式化相似性得分,仅显示前四位小数,并将其作为自己的列添加到数据帧中。因此,上面带有成对相似性计算的代码变成了,

for i in range(0, len(datasource)):      
    documents = []      
    documents.append(words)      
    documents.append(datasource.loc[i, 'posts'])

    tfidf = TfidfVectorizer(stop_words="english", ngram_range=(1, 4)).fit_transform(documents) #Compute pairwise similarity by multiplying by transpose.
    pairwise_similarity = tfidf * tfidf.T #Then, extract the score by selecting the first element in the   matrix.
    simiscore =   pairwise_similarity.A[0][1] #Format the similarity score to select only 4 decimals
     simiscore = "{0:.4f}".format(simiscore)

     #Finally, add the similarity score to the dataframe
      datasource.loc[i, 'Simiscore'] = simiscore

既然循环已经完成,我们将为用户输入的文本计算数据集中所有帖子的相似性得分。接下来的步骤是对相似性得分进行排名,挑选出前 5 名,将搜索术语作为其自己的列添加到数据框架中,并选择我们想要显示的相关列。最终的输出将被分配给一个名为 docs 的数据帧,我们将把它传递给我们的 html 表。

#Compute the rank and add it to the dataframe as its own column
datasource['Rank'] = datasource['Simiscore'].rank(method='average', ascending=False) #Sort by the rank
datasource = datasource.sort_values('Rank', ascending=True)#Select top 5 entries
datasource = datasource.head(5)#Add the search term to the dataframe as its own column
datasource['Search Term'] = words #Select relevant columns and assign to a dataframe called docsdocs = datasource[ ["type" ,"Rank", "Simiscore","Search Term","Introversion/Extraversion","Intuitive/Observant","Thinking/Feeling","Judging/Perceiving"]]

因为我们要将这些数据发送到一个 html 表中,所以我们必须将它转换成 json 格式。幸运的是,在 pandas 中使用 to_json 函数可以很容易地实现这一点。我们还可以将方向设置为记录,这样每个条目都成为一条记录。我们可以通过返回一个叫做‘docs’的对象来完成 flask 中的主页功能,这是我们前端所期望的。我们将使用 flask 中的 render_template 函数将数据发送到我们的 index.html 文件中。

#Convert to json
docs = docs.to_json(orient="records")#return data to front end for display return render_template('**index.html**',**docs**=json.loads(**docs**))

最后,让我们以标准烧瓶样式完成我们的应用程序,

if __name__ == "__main__":    
   app.run(debug=True)

你有它!运行代码时,您应该会得到以下消息,其中包含一个指向本地驱动器上的应用程序的链接。

* Running on [http://127.0.0.1:5000/](http://127.0.0.1:5000/) (Press CTRL+C to quit)

运行访问此链接,您将被定向到一个工作的应用程序!

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

在那里!自己尝试一些单词。

以下是一些相关链接,

  1. 链接到这个应用程序的 github 项目-https://github.com/kanishkan91/Personality-type-finder
  2. 链接到部署在 heroku-【https://personality-type-finder.herokuapp.com/ 的应用程序的工作版本
  3. 链接到用于此应用程序的基础数据-https://github . com/kanishkan 91/Personality-type-finder/blob/master/personalities . CSV

PS-github 项目包含一个. gitignore 和 requirements.txt 文件,您可以使用该文件将该应用程序的修改版本部署到任何服务器上。

特别感谢 Anish Hadkar 和 Aditya Kulkarni 在开发过程中对该应用程序的反馈。欢迎您提供任何额外的反馈!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值