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

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

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

相似的能力在很多利用中都有,不过你是否想过本人该如何实现?本文咱们将用大概一个小时的演练,从零开始构建一款视觉图像搜寻应用程序,其中蕴含用于提供视觉搜寻后果的全栈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 modelmodel = tf.keras.applications.ResNet50(weights='imagenet', include_top=False,input_shape=(3, 224, 224),pooling='avg')

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

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

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

#Upload the model to S3sagemaker_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 featuresfrom time import sleepsm_client = boto3.client('sagemaker-runtime')ENDPOINT_NAME = predictor.endpointdef 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_lstpredictor = sagemaker_model.deploy(initial_instance_count=3, instance_type='ml.m5.xlarge')

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

# define a function to extract image featuresfrom time import sleepsm_client = boto3.client('sagemaker-runtime')ENDPOINT_NAME = predictor.endpointdef 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 mappingkn_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 Linkprint("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 endpointpredictor.delete_endpoint()# Empty S3 Contentstraining_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域的应用老本