使用 Google Cloud 的 ABAP SDK 在 SAP 中讀取 BigQuery ML 預測結果

1. 簡介

在本程式碼研究室中,您將在 BigQuery 中建立機器學習 (ML) 模型,並使用 Google Cloud 專用 ABAP SDK 從該模型取得預測結果。

您將運用下列 Google Cloud 服務:

  • BigQuery
  • Cloud Shell

建構項目

您將建立下列項目:

  • BigQuery 機器學習 (ML) 模型。
  • 具備 BigQuery 工作使用者角色的服務帳戶,可呼叫 BigQuery API。
  • 一個 ABAP 程式,可呼叫 BigQuery API 並取得機器學習模型的預測結果。

2. 需求條件

  • ChromeFirefox 等瀏覽器。
  • 已啟用計費功能的 Google Cloud 專案,或為 Google Cloud Platform 建立 90 天免費試用帳戶
  • 系統中安裝了 SAP GUI (Windows 或 Java)。如果筆電上已安裝 SAP GUI,請使用 VM 外部 IP 位址做為應用程式伺服器 IP,連線至 SAP。如果您使用 Mac,也可以安裝 這個連結中的 SAP GUI for Java。

3. 事前準備

6757b2fb50ddcc2d.png

  • 在 Cloud Shell 中執行下列指令,為帳戶進行驗證,並將預設專案設為 abap-sdk-poc。以區域 us-west4-b 為例。如有需要,請根據偏好變更下列指令中的專案和區域。
gcloud auth login
gcloud config set project abap-sdk-poc
gcloud config set compute/zone us-west4-b
  • 您必須能存取已安裝 Google Cloud 專用 ABAP SDK 的 SAP 系統。
  • 您必須先完成 Codelab 1 (在 Google Cloud Platform 上安裝 ABAP 平台試用版 1909,並安裝 Google Cloud 專用的 ABAP SDK) 和 Codelab 2 (使用憑證設定 Compute Engine VM 上託管的 SAP 認證),才能繼續進行本 Codelab。
  • 如果您已完成程式碼研究室 1 和程式碼研究室 2,Google Cloud 上就會為您佈建 ABAP 平台試用版 1909 系統,並完成驗證和連線功能的必要設定。
  • 如果您尚未完成程式碼研究室 1 和程式碼研究室 2,就無法取得執行本程式碼研究室中提供步驟所需的所有基礎架構和連線。因此,您必須先完成程式碼研究室 1 和程式碼研究室 2,才能繼續進行本程式碼研究室。

4. 在 Google Cloud 專案中啟用 BigQuery API 2.0

  1. 在 Cloud 控制台中,按一下右上角的「啟用 Cloud Shell」

6757b2fb50ddcc2d.png

  1. 在 Cloud Shell 中執行下列指令,啟用 BigQuery API:
gcloud services enable bigquery.googleapis.com

執行成功後,您應該會看到如下所示的訊息

b5f52859df2c2f56.png

你現在應該已在 Google Cloud 專案中啟用 BigQuery API。

5. 建立服務帳戶,以便安全存取 BigQuery

如要安全地從 BigQuery ML 模型取得機器學習預測結果,您必須建立具有 BigQuery 作业使用者BigQuery 資料檢視者角色的服務帳戶,讓您的程式可在專案中執行查詢 (做為作业),並從資料表讀取資料。這個角色只會授予建立工作和讀取資料的必要權限,盡可能降低安全性風險。

建立服務帳戶

如要建立具備必要角色的服務帳戶,請執行下列步驟:

  1. 在 Cloud Shell 終端機中執行下列指令:
gcloud iam service-accounts create abap-sdk-bigquery-jobuser --display-name="Service Account for BigQuery Job user"
  1. 接著,請將必要角色新增至先前步驟中建立的服務帳戶:
gcloud projects add-iam-policy-binding abap-sdk-poc --member='serviceAccount:abap-sdk-bigquery-jobuser@abap-sdk-poc.iam.gserviceaccount.com' --role='roles/bigquery.jobUser'

gcloud projects add-iam-policy-binding abap-sdk-poc --member='serviceAccount:abap-sdk-bigquery-jobuser@abap-sdk-poc.iam.gserviceaccount.com' --role='roles/bigquery.dataViewer'

上述指令會使用 abap-sdk-poc 做為 Google Cloud 專案的預留位置。將 abap-sdk-poc 替換為您的專案 ID。

  1. 如要確認是否已新增角色,請前往 IAM 頁面。您建立的服務帳戶應會列出,並顯示已指派給該帳戶的角色。

6. 建立 BigQuery 機器學習模型

在本程式碼研究室中,我們將建立 k-means 模型,將倫敦自行車租用資料集分群。您可以套用 k-means 演算法,將資料分組成各個叢集。與監督式機器學習 (預測性分析) 不同,非監督式學習著重在描述性分析,也就是瞭解您的資料,好讓您能做出資料導向的決策。

建立資料集

如要建立 BigQuery 資料集來儲存機器學習模型,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「BigQuery」頁面。前往「BigQuery」頁面
  2. 在「Explorer」窗格中,按一下專案名稱。
  3. 依序按一下 5cf3b742649f1e2c.png「View actions」(查看動作) >「Create dataset」(建立資料集)

3fbc072041bfa313.png

  1. 在「Create dataset」頁面上執行下列操作:
  • 在「Dataset ID」(資料集 ID) 中輸入 bqml_tutorial
  • 在「位置類型」部分,選取「多區域」,然後選取「歐盟 (多個歐盟地區)」。倫敦自行車租用公開資料集儲存在 EU 多地區。資料集必須位於相同位置。
  • 保留其餘預設設定,然後按一下「Create dataset」(建立資料集)「建立資料集」頁面。

建立 k-means 模型

資料集設定完成後,下一步就是使用資料建立 k-means 模型。您可以使用 CREATE MODEL 陳述式搭配 model_type=kmeans 選項,建立及訓練 k-means 模型。

如要執行查詢並建立 k-means 模型,請執行下列步驟:

  1. 前往「BigQuery」BigQuery頁面。前往 BigQuery
  2. 在編輯器窗格中執行下列 SQL 陳述式:
CREATE OR REPLACE MODEL `bqml_tutorial.london_station_clusters`
  OPTIONS(model_type='kmeans', num_clusters=4) AS
WITH
  hs AS (
  SELECT
    h.start_station_name AS station_name,
  IF
    (EXTRACT(DAYOFWEEK
      FROM
        h.start_date) = 1
      OR EXTRACT(DAYOFWEEK
      FROM
        h.start_date) = 7,
      "weekend",
      "weekday") AS isweekday,
    h.duration,
    ST_DISTANCE(ST_GEOGPOINT(s.longitude,
        s.latitude),
      ST_GEOGPOINT(-0.1,
        51.5))/1000 AS distance_from_city_center
  FROM
    `bigquery-public-data.london_bicycles.cycle_hire` AS h
  JOIN
    `bigquery-public-data.london_bicycles.cycle_stations` AS s
  ON
    h.start_station_id = s.id
  WHERE
    h.start_date BETWEEN CAST('2015-01-01 00:00:00' AS TIMESTAMP)
    AND CAST('2016-01-01 00:00:00' AS TIMESTAMP) ),
  stationstats AS (
  SELECT
    station_name,
    isweekday,
    AVG(duration) AS duration,
    COUNT(duration) AS num_trips,
    MAX(distance_from_city_center) AS distance_from_city_center
  FROM
    hs
  GROUP BY
    station_name, isweekday)
SELECT
  * EXCEPT(station_name, isweekday)
FROM
  stationstats
  1. 在導覽面板的「Resources」(資源) 部分,展開專案名稱,然後依序按一下「bqml_tutorial」和「london_station_clusters」
  2. 按一下 [Schema] (結構定義) 分頁標籤。模型結構定義會列出 BigQuery ML 用來執行分群作業的 3 個車站屬性。結構定義應如下所示:

5f1feb313bd0f6a5.png

  1. 按一下 [Evaluation] (評估) 分頁標籤。這個分頁會顯示 k-means 模型所識別的群組圖表。在「數值特徵」下方,長條圖會顯示每個群集最重要的數值特徵值 (最多 10 個)。您可以從下拉式選單中選取要視覺化的地圖項目。

8f9b53971e33dc08.png

7. 使用 Google Cloud 的 ABAP SDK 取得 BigQuery ML 預測結果

在 Google Cloud 端完成必要設定後,您就可以在 SAP 系統中完成步驟,使用 Google Cloud 專用的 ABAP SDK 從 ML 模型取得預測結果。

建立用戶端金鑰設定

針對驗證和連線相關設定,Google Cloud 專用的 ABAP SDK 會使用 /GOOG/CLIENT_KEY/GOOG/SERVIC_MAP. 資料表

如要維護 /GOOG/CLIENT_KEY 資料表中的設定,請執行下列步驟:

  1. 在 SAP GUI 中輸入交易代碼 SPRO
  2. 按一下「SAP Reference IMG」
  3. 依序點選「ABAP SDK for Google Cloud」>「基本設定」>「設定用戶端金鑰」

25871e639293b9ee.png

  1. 請將下列值填入對應欄位,其他欄位則全部保留空白:

欄位

Google Cloud 金鑰名稱

BIGQUERY_ML

Google Cloud 服務帳戶名稱

abap-sdk-bigquery-jobuser@abap-sdk-poc.iam.gserviceaccount.com

Google Cloud 範圍

https://www.googleapis.com/auth/cloud-platform

專案 ID

abap-sdk-poc

授權類別

/GOOG/CL_AUTH_GOOGLE

建立 ABAP 報表,從 BigQuery ML 模型取得預測結果

如要建構 ABAP 報表,請執行下列步驟:

  1. 在 SAP GUI 中,前往交易代碼 SE38,然後建立名為 ZDEMO_BIGQUERY_ML_PREDICT. 的報表程式
  2. 在隨即開啟的彈出式視窗中,提供詳細資料,如下圖所示:

4cb32d50427df294.png

  1. 在下一個彈出式視窗中,選取「Local Object」或提供適當的套件名稱。
  2. 在 ABAP 編輯器中新增下列程式碼:
REPORT zdemo_bigquery_ml_predict.

types:
  begin of lty_query_result,
    centroid_id     type i,
    station_name    type string,
    isweekday       type string,
    num_trips       type i,
    distance_from_city type string,
  end of lty_query_result,
  ltt_query_result type standard table of lty_query_result.

DATA:
  lv_project_id TYPE string,
  ls_input      TYPE /goog/cl_bigquery_v2=>ty_103,
  ls_output     TYPE lty_query_result,
  lt_output     TYPE ltt_query_result.

CONSTANTS:
  lc_newline TYPE c VALUE cl_abap_char_utilities=>newline.

TRY.
    "Initialize Bigquery object, pass the client key name that you have configured in /GOOG/CLIENT_KEY table
    DATA(lo_bq) = NEW /goog/cl_bigquery_v2( iv_key_name = 'BIGQUERY_ML' ).

    "Populate relevant parameters
    lv_project_id = lo_bq->gv_project_id.

    ls_input-default_dataset-project_id = 'abap-sdk-poc'.
    ls_input-default_dataset-dataset_id = 'bqml_tutorial'.

    "This query gets predictions from
    ls_input-query =
                | WITH | && lc_newline &&
                | hs AS ( | && lc_newline &&
                | SELECT | && lc_newline &&
                | h.start_station_name AS station_name, | && lc_newline &&
                | IF | && lc_newline &&
                | (EXTRACT(DAYOFWEEK | && lc_newline &&
                | FROM | && lc_newline &&
                | h.start_date) = 1 | && lc_newline &&
                | OR EXTRACT(DAYOFWEEK | && lc_newline &&
                | FROM | && lc_newline &&
                | h.start_date) = 7, | && lc_newline &&
                | "weekend", | && lc_newline &&
                | "weekday") AS isweekday, | && lc_newline &&
                | h.duration, | && lc_newline &&
                | ST_DISTANCE(ST_GEOGPOINT(s.longitude, | && lc_newline &&
                | s.latitude), | && lc_newline &&
                | ST_GEOGPOINT(-0.1, | && lc_newline &&
                | 51.5))/1000 AS distance_from_city_center | && lc_newline &&
                | FROM | && lc_newline &&
                | `bigquery-public-data.london_bicycles.cycle_hire` AS h | && lc_newline &&
                | JOIN | && lc_newline &&
                | `bigquery-public-data.london_bicycles.cycle_stations` AS s | && lc_newline &&
                | ON | && lc_newline &&
                | h.start_station_id = s.id | && lc_newline &&
                | WHERE | && lc_newline &&
                | h.start_date BETWEEN CAST('2015-01-01 00:00:00' AS TIMESTAMP) | && lc_newline &&
                | AND CAST('2016-01-01 00:00:00' AS TIMESTAMP) ), | && lc_newline &&
                | stationstats AS ( | && lc_newline &&
                | SELECT | && lc_newline &&
                | station_name, | && lc_newline &&
                | isweekday, | && lc_newline &&
                | AVG(duration) AS duration, | && lc_newline &&
                | COUNT(duration) AS num_trips, | && lc_newline &&
                | MAX(distance_from_city_center) AS distance_from_city_center | && lc_newline &&
                | FROM | && lc_newline &&
                | hs | && lc_newline &&
                | GROUP BY | && lc_newline &&
                | station_name, isweekday ) | && lc_newline &&
                | SELECT | && lc_newline &&
                | * EXCEPT(nearest_centroids_distance) | && lc_newline &&
                | FROM | && lc_newline &&
                | ML.PREDICT( MODEL `bqml_tutorial.london_station_clusters`, | && lc_newline &&
                | ( | && lc_newline &&
                | SELECT | && lc_newline &&
                | * | && lc_newline &&
                | FROM | && lc_newline &&
                | stationstats | && lc_newline &&
                | WHERE | && lc_newline &&
                | REGEXP_CONTAINS(station_name, 'Kennington'))) |.

    "Call API method: bigquery.jobs.query
    CALL METHOD lo_bq->query_jobs
      EXPORTING
        iv_p_project_id = lv_project_id
        is_input        = ls_input
      IMPORTING
        es_output       = DATA(ls_response)
        ev_ret_code     = DATA(lv_ret_code)
        ev_err_text     = DATA(lv_err_text)
        es_err_resp     = DATA(ls_err_resp).

    IF lo_bq->is_success( lv_ret_code ).
      "API Call successful, loop through the data & display the result
      IF ls_response-job_complete = abap_true.
        LOOP AT ls_response-rows ASSIGNING FIELD-SYMBOL(<ls_row>).
          LOOP AT <ls_row>-f ASSIGNING FIELD-SYMBOL(<ls_value>).
            ASSIGN <ls_value>-v->* TO FIELD-SYMBOL(<ls_field_value>).
            CASE sy-tabix.
              WHEN 1.
                ls_output-centroid_id = <ls_field_value>.
              WHEN 2.
                ls_output-station_name = <ls_field_value>.
              WHEN 3.
                ls_output-isweekday = <ls_field_value>.
              WHEN 4.
                ls_output-num_trips = <ls_field_value>.
              WHEN 5.
                ls_output-distance_from_city = <ls_field_value>.
            ENDCASE.
          ENDLOOP.
          APPEND ls_output TO lt_output.
          CLEAR ls_output.
        ENDLOOP.
        IF lt_output IS NOT INITIAL.
          cl_demo_output=>new( )->begin_section( 'ML.Predict Query Details'
                               )->write_text( ls_input-query
                               )->write_text( 'Dataset: bigquery-public-data.london_bicycles'
                               )->end_section(
                               )->begin_section( 'ML.Predict Query Results'
                               )->write_data( lt_output
                               )->end_section(
                               )->display( ).
        ENDIF.
      ENDIF.
    ELSE.
      "Display error message in case the API call fails
      MESSAGE lv_err_text TYPE 'E'.
    ENDIF.

    "Close HTTP Connection
    lo_bq->close( ).

  CATCH /goog/cx_sdk INTO DATA(lo_exception).
    MESSAGE lo_exception->get_text( ) TYPE 'E'.
ENDTRY.
  1. 儲存並啟用報表。
  2. 執行報表 (F8)。

執行成功後,您應該會看到如下所示的報表輸出內容:

739e5685511fc9fc.png

6405542a597ed09f.png

8. 恭喜

您已順利完成「使用 ABAP SDK for Google Cloud 從 BigQuery 機器學習 (ML) 模型取得預測結果」程式講堂,真是太棒了!

您已成功從 SAP 系統中擷取 BigQuery 機器學習模型的預測結果!您已成功將 ABAP 與 Google Cloud 服務整合。透過其他精彩的 ABAP SDK for Google Cloud 程式碼研究室,拓展您的視野:

  • 搭配 Google Cloud ABAP SDK 使用 Translation API
  • 使用分割功能將大型物件上傳至 Cloud Storage 值區
  • 使用 ABAP SDK for Google Cloud 從 Secret Manager 擷取憑證/密鑰
  • 從 ABAP 呼叫 Vertex AI test-bison

9. 清理

如果您不想繼續進行與 Google Cloud 適用的 ABAP SDK 相關的其他程式碼研究室,請繼續進行清理作業。

刪除專案

  • 刪除 Google Cloud 專案:
gcloud projects delete abap-sdk-poc

刪除個別資源

  1. 刪除運算執行個體:
gcloud compute instances delete abap-trial-docker
  1. 刪除防火牆規則:
gcloud compute firewall-rules delete sapmachine
  1. 刪除服務帳戶:
gcloud iam service-accounts delete \
    abap-sdk-bigquery-jobuser@abap-sdk-poc.iam.gserviceaccount.com