使用 Amazon SageMaker 與 Amazon ES 構建一款視覺搜索應用程序

Original URL:https://aws.amazon.com/cn/blogs/machine-learning/building-a-visual-search-application-with-amazon-sagemaker-and-amazon-es/

有時候,我們可能很難找到合適的詞彙來描述自己想要尋找的東西。正如俗語所言,“一圖抵千言。”一般來說,展示真實示例或者圖像,對於目標的表達效果確實要比純文字描述好上不少。這一點,在使用搜索引擎查找所需內容時顯得尤其突出。

在本文中,我們將在一個小時的演練中從零開始構建一款視覺圖像搜索應用程序,其中包含用於提供視覺搜索結果的全棧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 GatewayAWS Lambda,並在Lambda函數中重新編碼爲字節形式。
    • 在該函數中,公開可讀的圖像URL以字符串形式傳遞,並可下載爲字節形式。
    • 各字節作爲載荷被髮送至Amazon SageMaker實時端點,而後由模型返回圖像嵌入的向量。
    • 該函數將搜索查詢中的圖像嵌入向量傳遞至Amazon ES域內索引中的k近鄰,而後返回一份包含k相似圖像及其對應Amazon S3 URI的列表。
    • 該函數生成經過預簽名的Amazon S3 URL並返回至客戶端Web應用程序,此URL用於在瀏覽器中顯示相似圖像。

    相關AWS服務

    要構建這樣一款端到端應用程序,大家需要使用以下AWS服務:

    • AWS AmplifyAWS Amplify 是一套面向前端與移動開發人員的JavaScript庫,用於構建雲應用程序。關於更多詳細信息,請參閱GitHub repo
    • Amazon API Gateway – 一項全託管服務,用於以任意規模創建、發佈、維護、監控以及保護API。
    • AWS CloudFormationAWS CloudFormation 爲開發人員及企業提供一種簡便易行的方法,藉此創建各AWS與相關第三方資源的集合,並以有序且可預測的方式進行配置。
    • Amazon ES – 一項託管服務,能夠幫助用戶以任意規模輕鬆部署、運營以及擴展Elasticsearch集羣。
    • AWS IAM – AWS身份與訪問管理(AWS Identity and Access Management,簡稱IAM) 幫助用戶安全地管理指向各AWS服務與資源的訪問操作。
    • AWS Lambda – 一套事件驅動型、無服務器計算平臺,可運行代碼以響應事件,並自動管理代碼所需的各項計算資源。
    • Amazon SageMaker – 一套全託管端到端機器學習平臺,用於以任意規模構建、訓練、調優以及部署機器學習模型。
    • AWS SAMAWS 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中的一套超集,詳見以下代碼:

    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
    knn_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-apivis-search棧。

    總結

    在本文中,我們介紹瞭如何使用Amazon SageMaker與Amazon ES KNN索引創建基於機器學習的視覺搜索應用程序。我們還使用到在ImageNet數據集上經過預訓練的ResNet50模型。當然,大家也可以使用其他預訓練模型,例如VGG、Inception以及MobileNet等,並使用自己的數據集進行調優。

    對於大部分深度學習類用例,我們建議您使用GPU實例。在GPU實例上訓練新模型,將帶來遠超CPU實例的訓練速度。如果您擁有多個GPU實例,或者需要在多個GPU實例之間使用分佈式訓練,則可以進行次線性擴展。本用例中僅使用CPU實例,因此您可以在AWS Free Tier中通過免費資源完成演練。

    關於本文所使用代碼示例的更多詳細信息,請參閱GitHub repo。關於Amazon ES的更多詳細信息,請參考以下擴展資源:

    作者介紹

    Amit Mukherjee

    AWS公司高級合作伙伴解決方案架構師。他爲各合作伙伴提供架構指導以幫助其在雲端獲得業務成功。他對AI及機器學習領域抱有濃厚興趣。在業餘時間,他喜歡與家人共度美好時光。

    Laith Al-Saadoon

    AWS公司數據分析方向高級解決方案架構師。他長期專注於幫助客戶設計規模化大數據處理架構。在業餘時間,他一直在關注機器學習與人工智能技術的最新動向。

    本文轉載自亞馬遜AWS官方博客

    原文鏈接

    使用 Amazon SageMaker 與 Amazon ES 構建一款視覺搜索應用程序

  • 發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章