1. 程式人生 > >AWS機器學習初探(1):Comprehend

AWS機器學習初探(1):Comprehend

1. Comprehend 服務簡介

1.1 功能

Amazon Comprehend 服務利用自然語言處理(NLP)來分析文字。其使用非常簡單。

  • 輸入:任意 UTF-8 格式的文字
  • 輸出:Comprehend 輸出一組實體(Entity)、若干關鍵詞(Key phrase)、哪種語言(Language)、什麼情緒(Sentiment,包括 positive,negative,neutual,mixed等幾種)和針對每個單詞的語法分析(Syntax)
  • 形式:支援同步的單文件返回,非同步的多文件處理和批處理
  • 支援的語言:語言判斷API支援上百種語言,其餘API 只支援英語和西班牙語。
  • 是否需要預處理:不需要。AWS 自己會持續訓練處理模型,來不斷提高處理精度,這對使用者來說是透明的。

典型的非同步批處理過程:

  1. 將文件儲存在 AWS S3 中
  2. 開啟一個或者多個 Comprehend job 來處理這些文件
  3. 監控這些 job 的狀態
  4. 從另一個 S3 bucket 中獲取分析結果

1.2 示例

該圖中,左側為一段作為輸入的文字,右側為Comprehend API 的輸出,分別是實體、關鍵詞、情緒和語言。

在介面上做測試的例子:

在 Comprehend 介面上輸入美國總統川普最新的一條推特訊息,它認為其是負面的:

利用CLI 做測試的例子:

aws comprehend detect-dominant-language --region us-east-1 --text "hello world"
{
    "Languages": [
        {
            "LanguageCode": "en",
            "Score": 0.9750663042068481
        }
    ]
}

2. 一個示例應用場景

2.1 應用場景說明

部署架構圖:

架構說明:

  • 在某個 AWS 區域,利用該區域中的 Comprehend API
  • 有一個該區域中的 VPC,它有兩個 Public Subnet,其中一箇中有一個EC2 例項,安裝了 phpmyadmin,用於連線和管理私有子網中的 Aurora 例項
  • 有一個私有子網,其中建立了一個 Aurora 例項,它只能在 VPC 範圍內被訪問
  • VPC 中有一個 Lambda 函式。因為該函式需要直接訪問 Aurora 例項,因此它必須在 VPC 之中。
  • 因為 Lambda 函式需要訪問 Comprehen API ,而 AWS 目前未提供內部訪問該 API 的端點,因此需要有一個 NAT 閘道器。 Lambda 函式通過該閘道器訪問 Comprehend API。

操作過程:

  1. 使用者通過 phpmyadmin 來使用 Aurora 資料庫。資料庫中有一個名為 ReviewInfo 的表,每行代表一個文字資訊,三列分別儲存了文字資訊的 ReviewID,message,sentiment,分別是記錄的ID,訊息內容和情緒。
  2. 每當使用者插入一條訊息(圖中的1和2),Lambda 函式會自動被觸發(圖中的3),它呼叫 Comprehend API(圖中的4),獲取該資訊的 sentiment,然後寫回 Aurora 中的該條記錄的 sentiment 欄位(圖中的5)。
  3. 使用者從 phpmyadmin 中查詢該條記錄的 sentiment。

2.2 實現

(1)按照部署圖,建立所需的各個AWS 服務例項,包括EC2 例項、NAT 例項、VPC、安裝phpmyadmin 等。過程省略。在VPC 中建立一個 Aurora 例項,配置 phpmyadmin 指向該例項。在 VPC 中建立一個 python 2.7 Lambda 函式。函式內容如下:

import pymysql
import json
import boto3
import os

def lambda_handler(event, context):
    comprehend = boto3.client(service_name='comprehend')
    jsonresponse= json.dumps(comprehend.detect_sentiment(Text=event['ReviewText'], LanguageCode='en'), sort_keys=True, indent=4)
    json_object = json.loads(jsonresponse)
    sentiment=json_object["Sentiment"]
 
    db = pymysql.connect(host=os.environ['host'],user=os.environ['user'],passwd=os.environ['password'],db=os.environ['db'], autocommit=True)
    add_order = ("UPDATE ReviewInfo SET Sentiment=%s WHERE ReviewId=%s;")
    db.cursor().execute(add_order, (sentiment,event['ReviewId']))
    db.commit()
    db.close()

該函式非常簡單。簡單說明如下:

  1. 通過環境變數傳入 host,user,password,db 等資料庫連線資訊。
  2. 首選通過 boto3 庫建立一個 comprehend 客戶端
  3. 從傳入的 event 中獲取訊息內容
  4. 呼叫 comprehend 服務的 detect_sentiment 函式,獲取該訊息的sentiment
  5. 通過 pymysql 庫連結到資料庫
  6. 更新該訊息對應的記錄的 Sentiment 列

(2)通過 phpmyadmin 在 Aurora 例項中建立一個數據庫  comprehend_demo。

(3)在 phpmyadmin 中執行下面的 SQL 語句在該資料庫中建立一個數據表 ReviewInfo。它有三個欄位。

CREATE TABLE comprehend_demo.ReviewInfo(
    ReviewId NUMERIC PRIMARY KEY ,
    ReviewText TEXT NOT NULL ,
    sentiment VARCHAR( 30 ) NOT NULL)

(4)在 phpmyadmin 中執行下面的 SQL 語句在資料庫comprehend_demo中建立一個名為Aurora_To_Lambda的儲存過程。注意需將其中的 COMPREHEND_LAMBDA_ARN 替換為步驟(1)中建立的Lambda 函式的 ARN。該儲存過程會呼叫由 arn 指定的 Lambda 函式,並且傳入 ReviewID 和 ReviewText 引數值。

DROP PROCEDURE IF EXISTS comprehend_demo.Aurora_To_Lambda;
DELIMITER ;;
CREATE PROCEDURE comprehend_demo.Aurora_To_Lambda (IN ReviewId NUMERIC, IN ReviewText TEXT) LANGUAGE SQL 
BEGIN CALL mysql.lambda_async('<COMPREHEND_LAMBDA_ARN>', CONCAT('{ "ReviewId" : "', ReviewId, '", "ReviewText" : "', ReviewText,'"}') );
END;;
DELIMITER ;

結果:

(5)在 phpmyadmin 中執行下面的 SQL 語句在該資料庫中建立一個觸發器。每當 ReviewInfo 表中有新行被插入時,該觸發器會被呼叫。它會獲取該行的 ReviewID 和 ReviewText 欄位,然後呼叫第(4)步中建立的觸發器,觸發器會呼叫 Lambda 函式。

CREATE TRIGGER `TR_Lambda` AFTER INSERT ON `ReviewInfo`
 FOR EACH ROW BEGIN
  SELECT  NEW.ReviewId , NEW.ReviewText INTO @ReviewId , @ReviewText;
  CALL  comprehend_demo.Aurora_To_Lambda(@ReviewId , @ReviewText);    
END

(6)因為Aurora 需要呼叫 Lambda 函式,因此需要配置 Aurora 的 IAM Role,使之具有呼叫 Lambda 函式的許可權。

首先在 IAM 介面上,建立一個 IAM Policy,它包含 InvokeFunction 許可權。

再建立一個 IAM Role,包含該 policy。

在 Aurora 介面上,建立一個新的 DB Cluster parameter group:

修改其  aws_default_lambda_role 為前面建立的 IAM role 的 arn,比如:

將 group2 設定為 Aurora 例項的group。此時需要重啟例項,使得修改得以生效。

然後在下面介面中設定 Aurora 的 IAM role 為上述 role:

 (7)做個簡單測試,插入一條資料,如果出現下面的錯誤,則意味著 Aurora 成功地呼叫了 Lambda 函式,但是 Lambda 函式無法連線到 Comprhend 服務。此時需要檢查從 Lambda 函式經過 NAT 閘道器訪問 Comprehend API 的路徑,主要是 VPC 的路由表。

(8)在網路路徑確認無誤後,如果出現下面的錯誤,則表示 Lambda 函式還無權呼叫 Comprehend API。

(9)配置 Lambda 函式呼叫 Comprehend API 的許可權。

首先需要在 IAM 建立一條 policy,它有 Comprhend API 的完全許可權。當然,可以只授予 sentiment API 許可權。

然後建立一個 IAM role,關聯該 policy。再將該 role 配置給 Lambda 函式,作為其 Execution Role。

(11)到現在為止,整個路徑才算全部打通了。當你在 phpmyadmin 中通過 SQL 語句向 ReveiwInfo 表中插入一行時,Lambda 函式會自動在改行內更新 sentiment 欄位。 

參考文件:

歡迎大家關注我的個人公眾號: