关于人工智能:视觉搜索看似神奇亲自试试其实没那么难

3次阅读

共计 8473 个字符,预计需要花费 22 分钟才能阅读完成。

天天混迹互联网的你,必定已经用过,或者至多见过四周人应用上面这样的利用:

  • 逛街看到后面的路人穿的衣服挺丑陋,拍张照就能在电商利用中搜到同款
  • 路边小花开的正艳,拍张照搜寻一下,学名、门纲目科属种,甚至拉丁名,各种信息高深莫测
  • 后面那人貌似是个明星,可是叫啥忘了,拍照搜寻,个别都能很快失去答案

的确!一些状况下,咱们可能很难找到适合的词汇来形容本人想要寻找的货色。而正如俗语所言:「一图抵千言」,一般来说,展现实在示例或者图像,对于指标的表白成果的确要比纯文字描述好上不少。这一点,在应用搜索引擎查找所需内容时显得尤其突出。

相似的能力在很多利用中都有,不过你是否想过本人该如何实现?本文咱们将用大概一个小时的演练,从零开始构建一款视觉图像搜寻应用程序,其中蕴含用于提供视觉搜寻后果的全栈 Web 应用程序。

视觉搜寻可能进步客户在批发业务与电子商务中的参与度,这种性能对于时尚及家庭装饰零售商而言尤其重要。视觉搜寻容许零售商向购物者举荐与主题或特定造型相干的商品,这是传统纯文本查问所无奈做到的。依据 Gartner 的报告,「到 2021 年,从新设计网站以反对视觉及语音搜寻的晚期采纳者品牌,将推动数字商务支出增长 30%」。

视觉搜寻的高级示例

Amazon SageMaker 是一项全托管服务,可为每位开发人员及数据科学家提供疾速构建、训练以及部署机器学习(ML)模型的能力。Amazon Elasticsearch Service(Amazon ES)同样为全托管服务,可帮忙咱们轻松以合乎老本效益的形式大规模部署、爱护并运行 Elasticsearch。Amazon ES 还提供 k 最近邻(KNN)搜寻,可能在相似性用例中加强搜寻能力,适用范围涵盖产品举荐、欺诈检测以及图像、视频与语义文档检索。KNN 应用轻量化且效率极高的非度量空间库(NMSLIB)构建而成,可在数千个维度上对数十亿个文档进行大规模、低提早最近邻搜寻,且实现难度与惯例 Elasticsearch 查问完全一致。

下图所示,为这套视觉搜寻架构的根本模式。

解决方案概述

视觉搜寻架构的实现分为两个阶段:

  • 通过示例图像数据集在 Amazon ES 上构建参考 KNN 索引。
  • 向 Amazon SageMaker 端点提交一份新图像,并由 Amazon ES 返回类似图像。

创立 KNN 推理索引

在此步骤中,托管在 Amazon SageMaker 当中、且通过事后训练的 Resnet50 模型将从每幅图像中提取 2048 个特征向量。每个向量都被存储在 Amazon ES 域的 KNN 索引当中。在本用例中,咱们将应用来自 FEIDEGGER 的图像——FEIDEGGER 是一套 Zalando 钻研数据集,其中蕴含 8732 张高分辨率时尚图像。以下截屏所示,为 KNN 索引的创立工作流程。

整个流程蕴含以下操作步骤:

  • 用户与 Amazon SageMaker Noteoobk 实例上的 Jupyter notebook 进行交互。
  • 从 Keras 处下载通过事后训练的 Resnet50 深层神经网络,删除最初一个分类器层,并对新的模型工件进行序列化,而后存储在 Amazon Simple Storage Service(Amazon S3)当中。该模型负责在 Amazon SageMaker 实时端点上启动 TensorFlow Serving API。
  • 将时尚图像推送至端点,端点通过神经网络运行图像以提取其中的特色(或称嵌入)。
  • Notebook 代码将图像嵌入写入至 Amazon ES 域中的 KNN 索引。

通过查问图像进行视觉搜寻

在此步骤中,咱们提供来自应用程序的查问图像,该图像通过 Amazon SageMaker 托管模型进行传递,并在期间提取 2048 项特色。咱们能够应用这些特色来查问 Amazon ES 中的 KNN 索引。Amazon ES 的 KNN 将帮忙咱们在向量空间中搜寻各点,并依据欧几里德间隔或余弦类似度(默认值为欧几里德间隔)找到这些点的「最近邻」。在找到给定图像的最近邻向量(例如 k = 3 最近邻)时,它会将与之关联的 Amazon S3 图像返回至应用程序。下图所示,为视觉搜寻全栈应用程序的根本架构。

整个流程蕴含以下操作步骤:

  • 终端用户通过本人的浏览器或挪动设施拜访 Web 应用程序。
  • 用户上传的图像以 Base64 编码字符串的模式被发送至 Amazon API Gateway 与 AWS Lambda,并在 Lambda 函数中从新编码为字节模式。
  • 在该函数中,公开可读的图像 URL 以字符串模式传递,并可下载为字节模式。
  • 各字节作为载荷被发送至 Amazon SageMaker 实时端点,而后由模型返回图像嵌入的向量。
  • 该函数将搜寻查问中的图像嵌入向量传递至 Amazon ES 域内索引中的 k 近邻,而后返回一份蕴含 k 类似图像及其对应 Amazon S3 URI 的列表。
  • 该函数生成通过预签名的 Amazon S3 URL 并返回至客户端 Web 应用程序,此 URL 用于在浏览器中显示类似图像。

相干 AWS 服务

要构建这样一款端到端应用程序,须要应用以下 AWS 服务:
*AWS Amplify:AWS Amplify 是一套面向前端与挪动开发人员的 JavaScript 库,用于构建云应用程序。对于更多详细信息,请参阅 GitHub repo。

  • Amazon API Gateway:一项全托管服务,用于以任意规模创立、公布、保护、监控以及爱护 API。
  • AWS CloudFormation:AWS CloudFormation 为开发人员及企业提供一种简便易行的办法,借此创立各 AWS 与相干第三方资源的汇合,并以有序且可预测的形式进行配置。
  • Amazon ES:一项托管服务,可能帮忙用户以任意规模轻松部署、经营以及扩大 Elasticsearch 集群。
  • AWS IAM:AWS 身份与拜访治理(AWS Identity and Access Management,简称 IAM)帮忙用户平安地治理指向各 AWS 服务与资源的拜访操作。
  • AWS Lambda:一套事件驱动型、无服务器计算平台,可运行代码以响应事件,并主动治理代码所需的各项计算资源。
  • Amazon SageMaker:一套全托管端到端机器学习平台,用于以任意规模构建、训练、调优以及部署机器学习模型。
  • AWS SAM:AWS Serverless Application Model(AWS SAM)是一套开源框架,用于构建无服务器应用程序。
  • Amazon S3:一项对象存储服务,可提供具备极高持久性、可用性、老本极低且可有限扩大的数据存储基础设施。

先决条件

在本次演练中,咱们须要筹备一个具备适当 IAM 权限的 AWS 账户,用于启动 CloudFormation 模板。

部署解决方案

在解决方案的部署方面,咱们须要应用 CloudFormation 栈。请筹备栈创立所波及的所有必要资源,具体包含:

  • 一个 Amazon SageMaker notebook 实例,用于在 Jupyter notebook 中运行 Python 代码。
  • 一个与该 Notebook 实例相关联的 IAM 角色。
  • 一个 Amazon ES 域,用于将图像嵌入向量存储在 KNN 索引内并进行检索。
  • 两个 S3 存储桶:其一用于存储源时尚图像,其二用于托管动态网站。

在 Jupyter notebook 中,咱们还须要部署以下几项:

  • Amazon SageMaker 端点,用于实时获取图像特征向量与嵌入。
  • 一套 AWS SAM 模板,用于通过 API Gateway 与 Lambda 建设一套无服务器后端。
  • 一个托管在 S3 存储桶上的动态前端网站,用于出现端到端机器学习应用程序的应用界面。前端代码应用 ReactJS 与 Amplify JavaScript 库。

首先,请实现以下操作步骤:

  • 应用 IAM 用户名与明码登录至 Amazon 治理控制台。
  • 抉择 Launch Stack 并在新选项卡中将其关上:

  • 在 Quick create stack 页面中,勾选复选框以确认创立 IAM 资源。
  • 抉择 Create stack。

  • 期待栈执行实现。

咱们能够在 Events 选项卡中的栈创立进度中查看各种事件。栈创立实现之后,将看到状态转为 CREATE_COMPLETE。
在 CloudFormation 模板创立实现后,能够在 Resources 选项卡中看到所有资源。

  • 在 Outputs 选项卡中,抉择 SageMakerNotebookURL 值。

此超链接将在咱们的 Amazon SageMaker notebook 实例上关上 Jupyter notebook,用于实现选项卡中的其余部分。

这时,咱们应该曾经处于 Jupyter notebook 的登录页面中。

  • 抉择 Visual-image-search.ipynb。

在 Amazon ES 上构建 KNN 索引

在此步骤中,咱们应该在 Notebook 结尾的 Visual image search 题目地位。遵循 notebook 中的步骤并按秩序运行各单元。

这里,咱们应用托管在 Amazon SageMaker 端点上的预训练 Resnet50 模型生成图像特征向量(嵌入)。嵌入将被保留在 CloudFormation 栈所创立的 Amazon ES 域中。对于更多详细信息,请参阅 notebook 中的 markdown 单元。

找到 notebook 当中的 Deploying a full-stack visual search application 单元。

该 notebook 中蕴含多个重要单元。

要加载预训练 ResNet50 模型,同时剔除最终 CNN 分类器层,请应用以下代码(此模型仅作为图像特征提取器应用):

#Import Resnet50 model
model = tf.keras.applications.ResNet50(weights='imagenet', include_top=False,input_shape=(3, 224, 224),pooling='avg')

咱们将模型另存为 TensorFlow SavedModel 格局,其中蕴含残缺的 TensorFlow 程序,包含权重与计算。详见以下代码:

#Save the model in SavedModel format
model.save('./export/Servo/1/', save_format='tf')

将模型工件(model.tar.gz)上传至 Amazon S3,具体代码如下:

#Upload the model to S3
sagemaker_session = sagemaker.Session()
inputs = sagemaker_session.upload_data(path='model.tar.gz', key_prefix='model')
inputs

咱们能够应用 Amazon SageMaker Python SDK 将模型部署至基于 Amazon SageMaker TensorFlow Serving 的服务器当中。此服务器负责提供 TensorFlow Serving REST API 中的一套超集,详见以下代码:

# define a function to extract image features
from time import sleep
sm_client = boto3.client('sagemaker-runtime')
ENDPOINT_NAME = predictor.endpoint
def get_predictions(payload):
 return sm_client.invoke_endpoint(EndpointName=ENDPOINT_NAME,
 ContentType='application/x-image',
 Body=payload)
def extract_features(s3_uri):
 key = s3_uri.replace(f's3://{bucket}/', '')
 payload = s3.get_object(Bucket=bucket,Key=key)['Body'].read()
 try:
 response = get_predictions(payload)
 except:
 sleep(0.1)
 response = get_predictions(payload)
 del payload
 response_body = json.loads((response['Body'].read()))
 feature_lst = response_body['predictions'][0]
 return s3_uri, feature_lst
predictor = sagemaker_model.deploy(initial_instance_count=3, instance_type='ml.m5.xlarge')

应用以下代码从 Amazon SageMaker 端点处提取参考图像特色:

# define a function to extract image features
from time import sleep
sm_client = boto3.client('sagemaker-runtime')
ENDPOINT_NAME = predictor.endpoint
def get_predictions(payload):
 return sm_client.invoke_endpoint(EndpointName=ENDPOINT_NAME,
 ContentType='application/x-image',
 Body=payload)
def extract_features(s3_uri):
 key = s3_uri.replace(f's3://{bucket}/', '')
 payload = s3.get_object(Bucket=bucket,Key=key)['Body'].read()
 try:
 response = get_predictions(payload)
 except:
 sleep(0.1)
 response = get_predictions(payload)
 del payload
 response_body = json.loads((response['Body'].read()))
 feature_lst = response_body['predictions'][0]
 return s3_uri, feature_lst

应用以下代码定义 Amazon ES KNN 索引映射:

#Define KNN Elasticsearch index mapping
kn_index = {
 "settings": {"index.knn": True},
 "mappings": {
 "properties": {
 "zalando_img_vector": {
 "type": "knn_vector",
 "dimension": 2048
 }
 }
 }
}

应用以下代码将图像特征向量与关联的 Amazon S3 图像 URI 导入至 Amazon ES KNN 索引:

# defining a function to import the feature vectors corrosponds to each S3 URI into Elasticsearch KNN index
# This process will take around ~3 min.
def es_import(i):
 es.index(index='idx_zalando',
 body={"zalando_img_vector": i[1],
 "image": i[0]}
 )
process_map(es_import, result, max_workers=workers)

构建一款全栈视觉搜寻应用程序

当初,咱们曾经领有了一个可能失常工作的 Amazon SageMaker 端点,并能够在 Amazon ES 上提取图像特色与 KNN 索引,接下来应该构建一款理论可用的全栈 ML 反对型 Web 应用程序了。咱们应用 AWS SAM 模板通过 API Gateway 与 Lambda 部署无服务器 REST API。该 REST API 负责接管新图像、生成嵌入,并将失去的类似图像返回至客户端。接下来,咱们将与新 REST API 交互的前端网站上传至 Amazon S3。前端代码应用 Amplify 与咱们的 REST API 相集成。

在以下单元中,预填充一套 CloudFormation 模板。此模板负责为全栈应用程序创立 API Gateway 与 Lambda 等必要资源:

s3_resource.Object(bucket, 'backend/template.yaml').upload_file('./backend/template.yaml', ExtraArgs={'ACL':'public-read'})
sam_template_url = f'https://{bucket}.s3.amazonaws.com/backend/template.yaml'
# Generate the CloudFormation Quick Create Link
print("Click the URL below to create the backend API for visual search:n")
print((
 'https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/create/review'
 f'?templateURL={sam_template_url}'
 '&stackName=vis-search-api'
 f'&param_BucketName={outputs["s3BucketTraining"]}'
 f'&param_DomainName={outputs["esDomainName"]}'
 f'&param_ElasticSearchURL={outputs["esHostName"]}'
 f'&param_SagemakerEndpoint={predictor.endpoint}'
))

以下截屏所示,为预生成的 CloudFormation 模板链接。

  • 抉择该链接。

这时咱们会跳转至 Quick create stack 页面。

  • 抉择复选框以确认创立 IAM 资源、各 IAM 资源自定义名称以及 CAPABILITY_AUTO_EXPAND。
  • 抉择 Create stack。


栈创立实现之后,咱们会看到状态转为 CREATE_COMPLETE。咱们能够在 Resources 选项卡中查看 CloudFormation 模板创立实现的全副资源。

  • 在栈创立实现之后,持续按后续单元执行。

以下单元显示,咱们的全栈应用程序(包含前端与后端代码)曾经胜利部署:

print('Click the URL below:n')
print(outputs['S3BucketSecureURL'] + '/index.html')

以下截屏所示,为 URL 的输入后果。

  • 抉择该链接。

这时咱们将跳转至应用程序页面,并能够在这里上传服饰图像服饰 URL 链接,借此获取类似服饰举荐。

在实现对视觉搜寻应用程序的测试与试验之后,请运行 notebook 下方的最初两个单元:

# Delete the endpoint
predictor.delete_endpoint()
# Empty S3 Contents
training_bucket_resource = s3_resource.Bucket(bucket)
training_bucket_resource.objects.all().delete()
hosting_bucket_resource = s3_resource.Bucket(outputs['s3BucketHostingBucketName'])
hosting_bucket_resource.objects.all().delete()

这些单元会终止咱们的 Amazon SageMaker 端点并清空 S3 存储桶,为资源清理步骤做好筹备。

资源清理

要删除其余 AWS 资源,请转至 AWS CloudFormation 控制台并删除其中的 vis-search-api 与 vis-search 栈。

总结

在本文中,咱们介绍了如何应用 Amazon SageMaker 与 Amazon ES KNN 索引创立基于机器学习的视觉搜寻应用程序。咱们还应用到在 ImageNet 数据集上通过预训练的 ResNet50 模型。当然,大家也能够应用其余预训练模型,例如 VGG、Inception 以及 MobileNet 等,并应用本人的数据集进行调优。

对于大部分深度学习类用例,咱们倡议应用 GPU 实例。在 GPU 实例上训练新模型,将带来远超 CPU 实例的训练速度。如果领有多个 GPU 实例,或者须要在多个 GPU 实例之间应用分布式训练,则能够进行次线性扩大。本用例中仅应用 CPU 实例,因而咱们能够在 AWS Free Tier 中通过免费资源实现演练。

对于本文所应用代码示例的更多详细信息,请参阅 GitHub repo。对于 Amazon ES 的更多详细信息,请参考以下扩大资源:

  • 如何进步 Elasticsearch 集群上的索引性能?
  • Amazon Elasticseach Service 最佳实际
  • 升高小型 Amazon Elasticsearch Service 域的应用老本

正文完
 0