返回文章列表

Databricks AWS 整合與 SpaCy 模型佈署

本文介紹如何將 Databricks 與 AWS 整合,設定 S3 儲存桶存取許可權,使用 Instance Profiles 管理許可權,並在 Databricks 上佈署 SpaCy 模型進行命名實體識別(NER)任務。文章涵蓋 Databricks 成本結構、方案選擇、AWS 存取許可權設定、S3

雲端運算 機器學習

Databricks 作為一個雲端原生資料科學與機器學習平台,與 AWS 的整合至關重要。透過設定 AWS 存取許可權和 S3 儲存桶,可以讓 Databricks 存取和管理資料。Instance Profiles 提供更精細的許可權控制,確保安全性。在 Databricks 上佈署 SpaCy 模型需要設定 Libraries 和叢集,並使用 init 指令碼安裝必要的套件。透過實作範例,可以瞭解如何在 Databricks 上進行 NER 任務,並評估其效能。最後,與 Google Colab 的效能比較能提供更全面的評估,幫助選擇合適的平台。

Databricks 設定與 AWS 整合

瞭解 Databricks 的成本結構

使用 Databricks 時,需要支付雲端運算例項(compute instances)以及 Databricks 平台本身的費用。Azure 和 AWS 以及 Databricks 都按照小時收費,而每小時的成本取決於所使用的叢集大小。

選擇 Databricks 方案

在完成電子郵件驗證和密碼設定後,使用者將看到一個類別似於圖 11-4 的頁面。在此頁面中,需要選擇 Databricks 的方案型別。有關詳細資訊,可以參考 Databricks 在 AWS 上的定價頁面。此處選擇了 Standard Plan,並注意到相關的收費標準:$0.40/DBU 用於 all-purpose compute,$0.07/DBU 用於 jobs compute。

什麼是 DBU?

一個 DBU(Databricks Unit)大約相當於在標準雲端運算例項上執行一小時(例如,在 AWS 上的 EC2 例項)。換句話說,如果在標準雲端運算例項上使用 Databricks 一小時,將消耗一個 DBU。

  • All-purpose compute:與在互動式環境(如 notebook)中執行的程式碼相關的運算。
  • Jobs compute:由自動化資料或機器學習管道消耗的運算。

通常,資料科學家在 notebook 環境中的大多數編碼工作將被歸類別為 all-purpose compute,而由資料和 ML 工程師佈署的管道將被歸類別為 jobs compute。

設定 AWS 存取許可權

為了組態 Databricks 對 AWS 的存取,需要擁有一個 AWS 帳戶。如果沒有,可以透過 AWS 帳戶建立頁面建立一個新的帳戶。作為新使用者,將有 12 個月的免費存取基本服務(如運算和儲存)的許可權。

完成 AWS 帳戶設定後,需要將 Databricks 與 AWS 連結起來。有關詳細的逐步說明,可以參考 Databricks 上的官方 AWS 組態頁面。

設定 S3 儲存桶存取許可權

為了讓 Databricks 能夠讀取和寫入 AWS 上的雲端儲存(稱為 S3 儲存桶),需要設定儲存存取許可權。這個存取許可權允許 Databricks 將帳戶範圍內的 Databricks 資產(如函式庫、日誌、已註冊模型等)讀寫到單個 S3 儲存桶中。

設定 S3 儲存桶的步驟

  1. 登入 AWS 帳戶並導航到 S3 管理控制檯。
  2. 點選“建立儲存桶”按鈕並輸入儲存桶名稱,選擇區域,然後點選“建立儲存桶”。
  3. 在新建立的儲存桶中,建立一個名為 ag_dataset 的資料夾,並上傳 AG News Dataset 的訓練資料。
  4. 建立一個名為 models 的資料夾,並上傳所需的模型套件。

使用 Instance Profiles 設定 S3 存取許可權

為了給 Databricks 存取其他 S3 儲存桶的許可權,需要建立一個新的 IAM 角色並具有適當的 S3 許可權。Instance profiles 是包含 IAM 角色的容器,可以將其傳遞給啟動的 EC2 例項。透過設定 instance profile,可以控制 EC2 例項對 S3 的存取許可權。

在 Databricks 中新增 Libraries

在啟動 EC2 叢集之前,需要將 libraries 新增至 Databricks 工作區。具體步驟如下:

  1. 從 Databricks 首頁,點選左側欄中的“Workspace”。
  2. 瀏覽至 Workspace > Users > 您的電子郵件地址
  3. 建立一個名為 Workspace Libraries 的新資料夾,用於存放所需的 libraries。

程式碼示例與說明

# 以下是一個簡單的範例,用於展示如何在 Databricks 中讀取 S3 儲存桶中的資料
import pandas as pd

# 設定 S3 儲存桶的路徑
s3_path = "s3://nlp-demo/ag_dataset/prepared/train_prepared.csv"

# 使用 pandas 讀取 CSV 檔案
df = pd.read_csv(s3_path)

# 顯示資料的前幾行
print(df.head())

內容解密:

  1. 匯入必要的函式庫:使用 import pandas as pd 將 pandas 函式庫匯入,以便進行資料處理。
  2. 設定 S3 路徑:定義 s3_path 變數來指定 S3 儲存桶中 CSV 檔案的位置。
  3. 讀取 CSV 檔案:使用 pd.read_csv(s3_path) 將 CSV 檔案讀取到 DataFrame 中。
  4. 顯示資料:透過 print(df.head()) 輸出 DataFrame 的前幾行,以驗證資料是否正確讀取。

在 Databricks 中設定工作環境

建立工作區函式庫

要在 Databricks 中使用 spaCy,首先需要在 Workspace Libraries 資料夾中建立一個函式庫。請在 Workspace Libraries 資料夾上點選右鍵,選擇建立函式庫的選項。你將會看到一個類別似於圖 11-9 的提示視窗。

圖 11-9. 建立函式庫

為了讓 spaCy 可以在 EC2 叢集中使用,我們需要將其安裝為可用的函式庫。在 Create Library 小工具中,點選 PyPI,輸入 spacy 進行搜尋,然後點選 Create。如果成功,你將會在 Workspace 標籤下的 Workspace Libraries 中看到 “spacy”。

你可以透過同樣的小工具新增更多的函式庫。

建立叢集

現在,我們已經使用案例項設定檔建立了 S3 存取許可權,並為 Workspace 建立了函式庫。這是令人興奮的開始。讓我們現在建立一個叢集。

從 Databricks 首頁,點選左側欄的 Clusters(參見圖 11-10)。

圖 11-10. 叢集

在 Clusters 檢視中,你將看到三個標籤:All-Purpose Clusters、Job Clusters 和 Pools。我們想要建立一個叢集供筆記本使用,因此 All-Purpose Clusters(預設選擇)是正確的選擇。

點選藍色的 Create Cluster 按鈕。這裡有很多可供選擇的選項,但讓我們先介紹基本的設定。首先,輸入叢集名稱。接下來,選擇叢集模式。如果想要利用 EC2 叢集中的多台機器(例如,需要多台機器同時處理資料操作),“Standard” 叢集模式是預設選擇。對於我們的小型 AG News 訓練資料集,我們可以選擇 Single Node,但對於生產環境中的大型資料集,您將需要選擇 Standard。讓我們選擇 Standard 來示範如何處理大型資料集。

叢集組態詳解

  1. 選擇 Databricks Runtime 版本:這些版本不斷更新,但讓我們選擇截至 2021 年 1 月的最新 ML 版本(7.5 ML)。

  2. 啟用自動擴充套件:在 Autopilot Options 部分,啟用自動擴充套件、自動擴充套件本地儲存,並設定終止時間(如果叢集在一段時間內處於非活動狀態,它將自動關閉,以節省閒置機器的不必要成本)。

  3. 選擇 Worker 和 Driver 型別:Driver 是主要節點,它向 Worker 節點傳送指令以執行命令。我們可以擴充套件 Worker 的數量以加快資料操作的處理速度,這是分散式計算的魔力,也是 Spark 非常適合大規模生產環境中機器學習的原因。

    • Worker Type:選擇 m4.large
    • Driver Type:與 Worker Type 相同。

    這種機器有 8 GB 的記憶體和 2 個核心,每小時消耗 0.4 個 DBU。每個 EC2 例項的成本為 0.4 DBU × 每 DBU $0.40(每小時 $0.16)。

    如果我們想要有 1 個 Driver 和 8 個 Worker,我們需要啟動 9 個 EC2 例項(每個例項有 2 個核心),這將花費 9 個例項 × 0.4 DBU × 每 DBU $0.40(每小時 $1.44),這是相當合理的。

你的新叢集組態現在應該類別似於圖 11-11 所示的組態。

圖 11-11. 叢集組態

接下來,讓我們在 Advanced Options 下為叢集設定例項策略。預設值為 None。從下拉式選單中,選擇您建立的例項設定檔。在我們的例子中,它被命名為 databricks-nlp-demo(參見圖 11-12)。

圖 11-12. 例項設定檔

現在,我們已經準備好啟動叢集。請點選頂部的藍色 Create Cluster 按鈕。

你的叢集需要幾分鐘時間來啟動。在它啟動的同時,讓我們安裝 spaCy 函式庫。從 Clusters 檢視中,導航到 Libraries 標籤,點選 Install New,選擇 Workspace,導航到您儲存的 spaCy 函式庫,然後點選 Install。你的導航窗格應該類別似於圖 11-13 所示。

圖 11-13. 安裝函式庫

如果成功,你很快就會看到 spaCy 在叢集上安裝(參見圖 11-14)。

圖 11-14. 安裝成功

建立筆記本

現在,讓我們建立第一個 Databricks 筆記本。我們的筆記本將建立一個 init 指令碼,用於 pip 安裝我們將使用的 spaCy 函式庫,然後將指令碼載入 Databricks File System(DBFS)。我們將把這個 init 指令碼新增到我們的叢集組態中,以便每次啟動叢集時都會執行該指令碼。換句話說,叢集將執行 init 指令碼(pip 安裝我們需要的 spaCy 函式庫),然後我們就可以載入 spaCy 函式庫進行 NLP 工作。

在 DBFS 中建立目錄並複製模型檔案

首先,在 DBFS 中建立一個目錄來存放模型:

# 在 DBFS 中建立目錄
dbutils.fs.mkdirs("dbfs:/databricks/models/spacy")

接下來,將上傳到 S3 的模型套件複製到剛剛在 DBFS 上建立的目錄:

# 將檔案從 S3 複製到 DBFS
dbutils.fs.cp("s3a://nlp-demo/models/spacy/", "dbfs:/databricks/models/spacy/", True)

你可以使用以下命令確認檔案是否成功複製到 DBFS:

# 確認 DBFS 中的檔案
display(dbutils.fs.ls("dbfs:/databricks/models/spacy/"))

如果成功,你將看到類別似於圖 11-16 的輸出結果。

圖 11-16. 成功複製檔案

詳細解說:

  1. dbutils.fs.mkdirs("dbfs:/databricks/models/spacy"):此命令在DBFS中建立一個新的目錄,用於存放我們的spaCy模型。這是必要的,因為Databricks需要一個地方來儲存和存取我們的模型檔案。

  2. dbutils.fs.cp("s3a://nlp-demo/models/spacy/", "dbfs:/databricks/models/spacy/", True):此命令將S3儲存桶中的spaCy模型複製到剛剛建立的DBFS目錄中。引數True表示遞迴複製,即複製源目錄中的所有檔案和子目錄。

  3. display(dbutils.fs.ls("dbfs:/databricks/models/spacy/")):此命令列出指定DBFS目錄中的所有檔案,以確認模型是否成功複製。透過使用display函式,我們可以在Databricks筆記本中以表格形式檢視結果,使其更容易檢查和驗證檔案的存在。

透過這些步驟,我們成功地在Databricks環境中設定了所需的spaCy模型,為後續的NLP任務做好了準備。

在Databricks上進行SpaCy模型佈署與效能測試

佈署SpaCy模型至Databricks

首先,我們需要在Databricks檔案系統(DBFS)上建立一個目錄來存放初始化指令碼(init script):

dbutils.fs.mkdirs("dbfs:/databricks/scripts/")

接著,建立一個init指令碼來安裝我們上傳的SpaCy套件:

dbutils.fs.put("dbfs:/databricks/scripts/spacy_with_models.sh", \
"""pip install /dbfs/databricks/models/spacy/en_core_web_lg-2.3.1.tar.gz \
pip install /dbfs/databricks/models/spacy/en_ner_base_V3-0.0.0.tar.gz \
pip install /dbfs/databricks/models/spacy/en_textcat_prodigy_V3_base_full-0.0.0.tar.gz""", True)

內容解密:

  • dbutils.fs.mkdirs:用於在DBFS上建立目錄。
  • dbutils.fs.put:用於將指令碼上傳到DBFS。
  • 指令碼內容為安裝三個SpaCy模型套件。

確認init指令碼是否成功上傳:

display(dbutils.fs.ls("dbfs:/databricks/scripts/spacy_with_models.sh"))

啟用Init指令碼並重新啟動叢集

  1. 前往叢集設定頁面。
  2. 在「Advanced Options」下找到「Init Scripts」。
  3. 將剛才上傳的init指令碼路徑加入叢集設定中。
  4. 重新啟動叢集,使init指令碼生效。

內容解密:

  • init指令碼會在叢集啟動時執行,安裝必要的SpaCy模型。
  • 重新啟動叢集是為了讓init指令碼生效。

使用SpaCy進行命名實體識別(NER)的效能測試

載入必要函式庫

import spacy
import numpy as np
import pandas as pd
from pyspark.sql.functions import udf
from pyspark.sql.types import *

載入資料至PySpark DataFrame

inputPath = "s3a://nlp-demo/ag_dataset/prepared/train_prepared.csv"
df = spark.read.format('csv').options(header='true', inferSchema='true', quote="\"", escape="\"").load(inputPath)
df.cache()
print((df.count(), len(df.columns)))

內容解密:

  • spark.read.format('csv'):讀取CSV檔案。
  • df.cache():將DataFrame快取於記憶體中,加速運算。

定義輸出結構描述(Schema)

schema = ArrayType(StructType([
    StructField("text", StringType(), False),
    StructField("start_char", IntegerType(), False),
    StructField("end_char", IntegerType(), False),
    StructField("label", StringType(), False)
]))

定義函式以擷取實體

def get_entities(text):
    global nlp
    try:
        doc = nlp(str(text))
    except:
        nlp = spacy.load('en_core_web_lg')
        doc = nlp(str(text))
    return [[e.text, e.start_char, e.end_char, e.label_] for e in doc.ents]

get_entities_udf = udf(get_entities, schema)
documents_df = df.withColumn('entities', get_entities_udf('description'))

內容解密:

  • get_entities函式使用SpaCy模型對文字進行實體識別。
  • udf將Python函式轉換為Spark的使用者自定義函式。

執行推論並寫入Parquet檔案

documents_df.write.parquet("s3a://nlp-demo/ag_dataset/prepared/write_test.parquet", mode="overwrite")

內容解密:

  • 由於Spark的懶惰執行,此步驟會觸發實際的推論運算。
  • 將結果寫入Parquet檔案以衡量推論時間。

與Google Colab的效能比較

在Google Colab中進行相同的推論測試,以比較效能差異:

import spacy
import numpy as np
import pandas as pd
import time

start_time = time.time()
# 載入資料及執行推論
end_time = time.time()
print(f"Inference time: {end_time - start_time} seconds")

內容解密:

  • 記錄推論開始及結束時間,以計算總耗時。
  • 可比較在Databricks與Google Colab上的效能差異。