程式碼研究室簡介
1. 總覽
在本研究室中,您將瞭解如何透過 Vertex AI Workbench 進行資料探索及訓練模型。
課程內容
學習重點:
- 建立及設定 Vertex AI Workbench 執行個體
- 使用 Vertex AI Workbench BigQuery 連接器
- 在 Vertex AI Workbench 核心上訓練模型
在 Google Cloud 中執行這個研究室的總費用約為 $1 美元。
2. Vertex AI 簡介
這個實驗室使用 Google Cloud 最新推出的 AI 產品服務。Vertex AI 整合了 Google Cloud 中的機器學習產品,提供流暢的開發體驗。先前使用 AutoML 訓練的模型和自訂模型,都能透過不同的服務存取。這項新產品會與其他新產品一起合併為一個 API。您也可以將現有專案遷移至 Vertex AI。
Vertex AI 包含許多不同產品,可支援端對端機器學習工作流程。本實驗室將著重於 Vertex AI Workbench。
Vertex AI Workbench 可與資料服務 (例如 Dataproc、Dataflow、BigQuery 和 Dataplex) 及 Vertex AI 深度整合,協助使用者快速建立以筆記本為基礎的端對端工作流程。這項服務可讓數據資料科學家連線至 GCP 資料服務、分析資料集、實驗不同的建模技術、將訓練完成的模型部署至實際環境,以及在模型生命週期中管理機器學習運作。
3. 用途簡介
在本研究室中,您將探索 London Bicycles Hire 資料集。這項資料包含自 2011 年以來,倫敦公共自行車共用計畫的自行車行程資訊。您可以透過 Vertex AI Workbench BigQuery 連接器,在 BigQuery 中探索這份資料集。然後,您會使用 pandas 將資料載入 Jupyter 筆記本,並訓練 TensorFlow 模型,根據行程發生時間及這個人騎車距離,預測循環行程的持續時間。
本實驗室課程會使用 Keras 預先處理層,轉換及準備模型訓練的輸入資料。這個 API 可讓您直接在 TensorFlow 模型圖中建構預先處理作業,確保訓練資料和提供資料進行相同的轉換,藉此降低訓練/提供偏差的風險。請注意,自 TensorFlow 2.6 起,這個 API 已穩定。如果您使用的是舊版 TensorFlow,則需要匯入實驗符號。
4. 設定環境
您需要已啟用計費功能的 Google Cloud Platform 專案,才能執行這個程式碼研究室。如要建立專案,請按照這篇文章中的操作說明進行。
步驟 1:啟用 Compute Engine API
前往「Compute Engine」,並選取「啟用」 (如果尚未啟用)。
步驟 2:啟用 Vertex AI API
前往 Cloud 控制台的 Vertex AI 專區,然後點選「啟用 Vertex AI API」。
步驟 3:建立 Vertex AI Workbench 執行個體
在 Cloud 控制台的 Vertex AI 專區中,按一下「Workbench」:
啟用 Notebooks API (如果尚未啟用)。
啟用後,按一下「MANAGED NOTEBOOKS」:
然後選取「新增筆記本」。
為筆記本命名,然後在「權限」下方選取「服務帳戶」
選取「進階設定」。
在「安全性」下方,選取「啟用終端機」(如果尚未啟用)。
您可以保留其他進階設定。
接著,按一下「建立」。
建立執行個體後,請選取「OPEN JUPYTERLAB」。
5. 在 BigQuery 中探索資料集
在 Vertex AI Workbench 執行個體中,前往左側並點選「筆記本中的 BigQuery」連接器。
BigQuery 連接器可讓您輕鬆探索及查詢 BigQuery 資料集。除了專案中的任何資料集外,點選「新增專案」按鈕即可探索其他專案中的資料集。
在本實驗室中,您將使用 BigQuery 公開資料集的資料。向下捲動,找到「london_bicycles」london_bicycles資料集。您會發現這個資料集有 cycle_hire 和 cycle_stations 兩個資料表。以下逐一介紹
首先,請按兩下 cycle_hire 資料表。您會看到資料表以新分頁的形式開啟,其中包含資料表的結構定義,以及資料列數和大小等中繼資料。
按一下「Preview」分頁標籤,即可查看資料樣本。讓我們執行一個簡單的查詢,看看熱門歷程。首先,請按一下「查詢表格」按鈕。
接著,請將以下內容貼到 SQL 編輯器中,然後點選「Submit Query」。
SELECT
start_station_name,
end_station_name,
IF(start_station_name = end_station_name,
TRUE,
FALSE) same_station,
AVG(duration) AS avg_duration,
COUNT(*) AS total_rides
FROM
`bigquery-public-data.london_bicycles.cycle_hire`
GROUP BY
start_station_name,
end_station_name,
same_station
ORDER BY
total_rides DESC
從查詢結果中,您會發現往返海德公園角站的單車行程最受歡迎。
接著,請雙擊 cycle_stations 資料表,這裡提供每個站點的相關資訊。
我們要彙整 cycle_hire 和 cycle_stations 資料表。cycle_stations 資料表包含每個站點的經緯度。您將使用這項資訊,計算起點與終點站之間的距離,估算每趟單車行程行經的距離。
如要執行這項計算,您必須使用 BigQuery 地理位置函式。具體來說,您會將每個 lat/lon 字串轉換為 ST_GEOGPOINT,然後使用 ST_DISTANCE 函式,以公尺為單位計算兩個點之間的直線距離。您將使用這個值做為每趟單車行程中移動距離的 Proxy。
將下列查詢複製到 SQL 編輯器,然後點選「Submit Query」(提交查詢)。請注意,JOIN 條件中有三個資料表,因為我們需要兩次彙整車站資料表,才能取得週期起點和終點車站的 lat/lon。
WITH staging AS (
SELECT
STRUCT(
start_stn.name,
ST_GEOGPOINT(start_stn.longitude, start_stn.latitude) AS POINT,
start_stn.docks_count,
start_stn.install_date
) AS starting,
STRUCT(
end_stn.name,
ST_GEOGPOINT(end_stn.longitude, end_stn.latitude) AS point,
end_stn.docks_count,
end_stn.install_date
) AS ending,
STRUCT(
rental_id,
bike_id,
duration, --seconds
ST_DISTANCE(
ST_GEOGPOINT(start_stn.longitude, start_stn.latitude),
ST_GEOGPOINT(end_stn.longitude, end_stn.latitude)
) AS distance, --meters
start_date,
end_date
) AS bike
FROM `bigquery-public-data.london_bicycles.cycle_stations` AS start_stn
LEFT JOIN `bigquery-public-data.london_bicycles.cycle_hire` as b
ON start_stn.id = b.start_station_id
LEFT JOIN `bigquery-public-data.london_bicycles.cycle_stations` AS end_stn
ON end_stn.id = b.end_station_id
LIMIT 700000)
SELECT * from STAGING
6. 在 TensorFlow 核心上訓練機器學習模型
Vertex AI Workbench 提供運算相容性層,可讓您從單一筆記本執行個體啟動 TensorFlow、PySpark、R 等核心。在本實驗室中,您將使用 TensorFlow 核心建立筆記本。
建立 DataFrame
查詢執行完畢後,請按一下「複製 DataFrame 程式碼」。這樣您就能將 Python 程式碼貼到與 BigQuery 用戶端連線的筆記本中,擷取此資料做為 pandas DataFrame。
接下來,請返回啟動器,並建立 TensorFlow 2 筆記本。
在筆記本的第一個儲存格中,貼上從查詢編輯器複製的程式碼。應如下所示:
# The following two lines are only necessary to run once.
# Comment out otherwise for speed-up.
from google.cloud.bigquery import Client, QueryJobConfig
client = Client()
query = """WITH staging AS (
SELECT
STRUCT(
start_stn.name,
ST_GEOGPOINT(start_stn.longitude, start_stn.latitude) AS POINT,
start_stn.docks_count,
start_stn.install_date
) AS starting,
STRUCT(
end_stn.name,
ST_GEOGPOINT(end_stn.longitude, end_stn.latitude) AS point,
end_stn.docks_count,
end_stn.install_date
) AS ending,
STRUCT(
rental_id,
bike_id,
duration, --seconds
ST_DISTANCE(
ST_GEOGPOINT(start_stn.longitude, start_stn.latitude),
ST_GEOGPOINT(end_stn.longitude, end_stn.latitude)
) AS distance, --meters
start_date,
end_date
) AS bike
FROM `bigquery-public-data.london_bicycles.cycle_stations` AS start_stn
LEFT JOIN `bigquery-public-data.london_bicycles.cycle_hire` as b
ON start_stn.id = b.start_station_id
LEFT JOIN `bigquery-public-data.london_bicycles.cycle_stations` AS end_stn
ON end_stn.id = b.end_station_id
LIMIT 700000)
SELECT * from STAGING"""
job = client.query(query)
df = job.to_dataframe()
為了達成本實驗室的目標,我們將資料集限制在 700000 筆,以縮短訓練時間。不過,您可以自行修改查詢,並嘗試使用整個資料集。
接著,匯入必要的程式庫。
from datetime import datetime
import pandas as pd
import tensorflow as tf
執行下列程式碼,建立精簡版 DataFrame,只包含本練習 ML 部分所需的資料欄。
values = df['bike'].values
duration = list(map(lambda a: a['duration'], values))
distance = list(map(lambda a: a['distance'], values))
dates = list(map(lambda a: a['start_date'], values))
data = pd.DataFrame(data={'duration': duration, 'distance': distance, 'start_date':dates})
data = data.dropna()
start_date 欄是 Python datetime
。您不必在模型中直接使用這個 datetime
,您會建立兩個新功能,以指出單車行程發生在星期幾和一天中的哪些時段。
data['weekday'] = data['start_date'].apply(lambda a: a.weekday())
data['hour'] = data['start_date'].apply(lambda a: a.time().hour)
data = data.drop(columns=['start_date'])
最後,將時間長度欄從秒數轉換為分鐘,方便閱讀
data['duration'] = data['duration'].apply(lambda x:float(x / 60))
查看格式化的 DataFrame 的前幾列。現在,您可以取得每趟單車行程在星期幾和當時每小時的資料,以及行程的移動距離。您將根據這些資訊,嘗試預測行程所需的時間。
data.head()
您必須先將資料分割成訓練和驗證集,才能建立及訓練模型。
# Use 80/20 train/eval split
train_size = int(len(data) * .8)
print ("Train size: %d" % train_size)
print ("Evaluation size: %d" % (len(data) - train_size))
# Split data into train and test sets
train_data = data[:train_size]
val_data = data[train_size:]
建立 TensorFlow 模型
您將使用 Keras Functional API 建立 TensorFlow 模型。如要預先處理輸入資料,您將使用 Keras 預處理層 API。
下列公用程式函式會從 pandas Dataframe 建立 tf.data.Dataset
。
def df_to_dataset(dataframe, label, shuffle=True, batch_size=32):
dataframe = dataframe.copy()
labels = dataframe.pop(label)
ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))
if shuffle:
ds = ds.shuffle(buffer_size=len(dataframe))
ds = ds.batch(batch_size)
ds = ds.prefetch(batch_size)
return ds
使用上述函式建立兩個 tf.data.Dataset
,一個用於訓練,另一個用於驗證。您可能會看到一些警告,但可以放心忽略。
train_dataset = df_to_dataset(train_data, 'duration')
validation_dataset = df_to_dataset(val_data, 'duration')
您將在模型中使用下列預先處理層:
- Normalization layer:針對輸入特徵執行特徵層級的正規化。
- IntegerLookup 圖層:將整數類別值轉換為整數索引。
- CategoryEncoding 層:將整數類別特徵轉換為 onehot、多樣本或 TF-IDF 密集表示法。
請注意,這些圖層「無法」訓練。您可以改為透過 adapt()
方法,將預先處理層暴露給訓練資料,藉此設定預先處理層的狀態。
下列函式會建立可用於距離地圖項目的規格化圖層。您可以在訓練資料上使用 adapt()
方法,在擬合模型前設定狀態。這會計算用於標準化的平均值和變異值。稍後,當您將驗證資料集傳遞至模型時,系統會使用在訓練資料上計算的相同平均值和變異數來調整驗證資料。
def get_normalization_layer(name, dataset):
# Create a Normalization layer for our feature.
normalizer = tf.keras.layers.Normalization(axis=None)
# Prepare a Dataset that only yields our feature.
feature_ds = dataset.map(lambda x, y: x[name])
# Learn the statistics of the data.
normalizer.adapt(feature_ds)
return normalizer
同樣地,下列函式會建立您將用於小時和星期幾特徵的類別編碼。
def get_category_encoding_layer(name, dataset, dtype, max_tokens=None):
index = tf.keras.layers.IntegerLookup(max_tokens=max_tokens)
# Prepare a Dataset that only yields our feature
feature_ds = dataset.map(lambda x, y: x[name])
# Learn the set of possible values and assign them a fixed integer index.
index.adapt(feature_ds)
# Create a Discretization for our integer indices.
encoder = tf.keras.layers.CategoryEncoding(num_tokens=index.vocabulary_size())
# Apply one-hot encoding to our indices. The lambda function captures the
# layer so we can use them, or include them in the functional model later.
return lambda feature: encoder(index(feature))
接下來,請建立模型的預先處理部分。首先,為每個地圖項目建立 tf.keras.Input
圖層。
# Create a Keras input layer for each feature
numeric_col = tf.keras.Input(shape=(1,), name='distance')
hour_col = tf.keras.Input(shape=(1,), name='hour', dtype='int64')
weekday_col = tf.keras.Input(shape=(1,), name='weekday', dtype='int64')
接著建立標準化和類別編碼層,並將這些層儲存在清單中。
all_inputs = []
encoded_features = []
# Pass 'distance' input to normalization layer
normalization_layer = get_normalization_layer('distance', train_dataset)
encoded_numeric_col = normalization_layer(numeric_col)
all_inputs.append(numeric_col)
encoded_features.append(encoded_numeric_col)
# Pass 'hour' input to category encoding layer
encoding_layer = get_category_encoding_layer('hour', train_dataset, dtype='int64')
encoded_hour_col = encoding_layer(hour_col)
all_inputs.append(hour_col)
encoded_features.append(encoded_hour_col)
# Pass 'weekday' input to category encoding layer
encoding_layer = get_category_encoding_layer('weekday', train_dataset, dtype='int64')
encoded_weekday_col = encoding_layer(weekday_col)
all_inputs.append(weekday_col)
encoded_features.append(encoded_weekday_col)
定義預先處理層後,您可以定義模型的其餘部分。您將串連所有輸入元素,並傳遞至稠密層。由於這是迴歸問題,因此輸出層是單個單位。
all_features = tf.keras.layers.concatenate(encoded_features)
x = tf.keras.layers.Dense(64, activation="relu")(all_features)
output = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(all_inputs, output)
最後,請編譯模型。
model.compile(optimizer = tf.keras.optimizers.Adam(0.001),
loss='mean_squared_logarithmic_error')
定義了模型後
tf.keras.utils.plot_model(model, show_shapes=True, rankdir="LR")
請注意,就這個簡單的資料集而言,這個模型相當複雜。這項資訊僅供示範之用。
我們再訓練 1 個週期,藉此確認程式碼可以執行。
model.fit(train_dataset, validation_data = validation_dataset, epochs = 1)
使用 GPU 訓練模型
接下來,您將延長模型的訓練時間,並使用硬體切換器加快訓練速度。有了 Vertex AI Workbench,您無須關閉執行個體就能變更硬體。您只需在需要時新增 GPU,就能降低成本。
如要變更硬體設定檔,請按一下右上角的機器類型,然後選取「修改硬體」
選取「Attach GPUs」(連結 GPU),然後選取 NVIDIA T4 Tensor Core GPU。
硬體設定大約需要五分鐘。程序完成後,我們再訓練模型一會兒。您會發現每個訓練週期現在所需的時間較短。
model.fit(train_dataset, validation_data = validation_dataset, epochs = 5)
🎉 恭喜!🎉
您已瞭解如何使用 Vertex AI Workbench 執行下列操作:
- 探索 BigQuery 中的資料
- 使用 BigQuery 用戶端將資料載入 Python
- 使用 Keras 預處理層和 GPU 訓練 TensorFlow 模型
如要進一步瞭解 Vertex AI 的其他部分,請參閱說明文件。
7. 清除所用資源
由於我們已將 Notebook 設為在閒置 60 分鐘後逾時,因此不必擔心關閉執行個體。如果您想手動關閉執行個體,請按一下控制台 Vertex AI Workbench 專區中的「停止」按鈕。如要完全刪除筆記本,請按一下「刪除」按鈕。