天天混迹互联网的你,必定已经用过,或者至多见过四周人应用上面这样的利用:
- 逛街看到后面的路人穿的衣服挺丑陋,拍张照就能在电商利用中搜到同款
- 路边小花开的正艳,拍张照搜寻一下,学名、门纲目科属种,甚至拉丁名,各种信息高深莫测
- 后面那人貌似是个明星,可是叫啥忘了,拍照搜寻,个别都能很快失去答案
的确!一些状况下,咱们可能很难找到适合的词汇来形容本人想要寻找的货色。而正如俗语所言:「一图抵千言」,一般来说,展现实在示例或者图像,对于指标的表白成果的确要比纯文字描述好上不少。这一点,在应用搜索引擎查找所需内容时显得尤其突出。
相似的能力在很多利用中都有,不过你是否想过本人该如何实现?本文咱们将用大概一个小时的演练,从零开始构建一款视觉图像搜寻应用程序,其中蕴含用于提供视觉搜寻后果的全栈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'¶m_BucketName={outputs["s3BucketTraining"]}' f'¶m_DomainName={outputs["esDomainName"]}' f'¶m_ElasticSearchURL={outputs["esHostName"]}' f'¶m_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域的应用老本