Chuyển đến nội dung chính

Quy trình giám sát mô hình ML đầu-cuối với NannyML trong Python

Học quy trình đầu-cuối để giám sát bất kỳ mô hình nào trong Jupyter notebook của bạn khi vận hành trong môi trường sản xuất.
· 15 phút đọc

Khám phá cùng AI

Vì sao cần giám sát mô hình ML?

Các dự án học máy là quá trình lặp đi lặp lại. Bạn không dừng lại ở một mô hình chạy tốt trong Jupyter notebook. Bạn thậm chí cũng không dừng lại sau khi mô hình đã online và mọi người có thể truy cập. Ngay cả sau khi triển khai, bạn phải liên tục “trông nom” để nó vận hành tốt như trong giai đoạn phát triển.

Bê bối của Zillow là ví dụ hoàn hảo cho việc điều gì xảy ra nếu bạn không làm vậy. Năm 2021, Zillow lỗ tới 304 triệu đô la vì mô hình học máy ước tính giá nhà. Zillow đã trả quá cao cho hơn 7000 căn nhà và buộc phải bán tháo với giá thấp hơn nhiều. Công ty bị chính mô hình của mình “lừa” và phải cắt giảm 25% nhân sự.

Những kiểu lỗi mô hình âm thầm như vậy rất phổ biến với mô hình ngoài đời thực, nên chúng cần được cập nhật liên tục trước khi hiệu năng sản xuất suy giảm. Không làm vậy sẽ làm tổn hại danh tiếng công ty, niềm tin với các bên liên quan, và cuối cùng là túi tiền của họ.

Bài viết này sẽ hướng dẫn bạn triển khai một quy trình đầu-cuối để giám sát mô hình học máy sau triển khai với NannyML.

NannyML là gì?

NannyML là thư viện mã nguồn mở đang phát triển, tập trung vào học máy sau triển khai. Thư viện cung cấp nhiều tính năng để giải quyết các vấn đề nảy sinh trong môi trường ML sản xuất. Ví dụ:

  • Phát hiện drift: Phát hiện thay đổi phân phối dữ liệu giữa dữ liệu huấn luyện và dữ liệu sản xuất.
  • Ước lượng hiệu năng: Ước lượng hiệu năng mô hình trong sản xuất khi chưa có ground truth ngay lập tức.
  • Báo cáo tự động: Tạo báo cáo về tình trạng và hiệu năng của mô hình đã triển khai.
  • Hệ thống cảnh báo: Cảnh báo về drift dữ liệu và các vấn đề hiệu năng.
  • Đánh giá công bằng mô hình: Giám sát tính công bằng để ngăn chặn thiên lệch.
  • Tương thích với các framework ML: Tích hợp với mọi framework học máy.
  • Giao diện thân thiện: Giao diện quen thuộc như scikit-learn.

Chúng ta sẽ lần lượt tìm hiểu phần kỹ thuật của các tính năng này.

Các khái niệm tiên quyết

Chúng ta sẽ học các khái niệm nền tảng của giám sát mô hình thông qua phép ẩn dụ một robot thành thạo bắn cung.

Trong phép ẩn dụ này:

  • Robot đại diện cho mô hình học máy của chúng ta.
  • Mục tiêu đại diện cho đích hay mục tiêu của mô hình.
  • Có thể coi đây là bài toán hồi quy, vì điểm số được tính dựa trên việc mũi tên bắn gần hồng tâm — chấm đỏ ở giữa — đến mức nào.
  • Đặc điểm của mũi tên và cung, cùng với thuộc tính vật lý của robot và điều kiện môi trường (như gió và thời tiết), là các đặc trưng hay biến đầu vào của mô hình.

Vậy, bắt đầu nhé.

Data drift

Hãy hình dung chúng ta đã chuẩn bị kỹ càng cung, tên và bia (tương tự chuẩn bị dữ liệu). Robot của chúng ta, được trang bị nhiều cảm biến và camera, bắn 10000 lần trong quá trình huấn luyện. Theo thời gian, nó bắt đầu bắn trúng hồng tâm với tần suất ấn tượng. Chúng ta rất hài lòng với hiệu năng và bắt đầu bán robot cùng các bản sao cho người yêu thích bắn cung (triển khai mô hình).

Nhưng chẳng bao lâu, chúng ta nhận được một loạt phàn nàn. Một số người dùng báo cáo robot bắn trượt bia hoàn toàn. Ngạc nhiên, chúng ta tập hợp đội ngũ để bàn bạc nguyên nhân.

Những gì phát hiện được là một trường hợp kinh điển của data drift. Môi trường hoạt động của robot đã thay đổi — mẫu gió khác, độ ẩm thay đổi, thậm chí cả các đặc tính vật lý của mũi tên (trọng lượng, cân bằng) và cung cũng thay đổi.

Sự thay đổi thực tế này ở các biến đầu vào đã làm sai lệch độ chính xác của robot, tương tự cách một mô hình học máy có thể kém hiệu quả khi dữ liệu đầu vào, đặc biệt là mối quan hệ giữa các đặc trưng, thay đổi theo thời gian.

Concept drift

Sau khi xử lý các vấn đề này, chúng ta tung ra lô robot mới. Thế nhưng, vài tuần sau, các phàn nàn tương tự lại xuất hiện. Hoang mang, chúng ta tìm hiểu sâu hơn và phát hiện người dùng thường xuyên thay bia.

Những bia mới có kích thước khác nhau và đặt ở các khoảng cách khác nhau. Sự thay đổi này đòi hỏi cách tiếp cận khác cho kỹ thuật bắn của robot — một ví dụ điển hình về concept drift.

Trong học máy, concept drift xảy ra khi mối quan hệ giữa các biến đầu vào và kết quả mục tiêu thay đổi. Với robot của chúng ta, các loại bia mới khiến chúng phải thích nghi cách bắn khác đi, cũng như một mô hình học máy cần điều chỉnh khi động lực của dữ liệu huấn luyện thay đổi đáng kể.

Nhiều ví dụ thực tế hơn về concept và data drift

Để khắc sâu ý tưởng, hãy khám phá vài ví dụ thực tế về cách data và concept drift xảy ra.

Ví dụ về data drift

  1. Mô hình chấm điểm tín dụng: Biến động kinh tế làm thay đổi thói quen chi tiêu và tín dụng của người dân. Nếu mô hình chấm điểm tín dụng không thích ứng, nó có thể dẫn đến từ chối không chính đáng hoặc chấp thuận rủi ro.
  2. Hệ thống theo dõi sức khỏe: Trong y tế, thay đổi nhân khẩu học người dùng hoặc hiệu chuẩn cảm biến có thể khiến các mô hình theo dõi sinh hiệu cho đánh giá sai.
  3. Dự báo nhu cầu bán lẻ: Trong bán lẻ, dịch chuyển hành vi và xu hướng người tiêu dùng có thể khiến các mô hình dựa trên dữ liệu bán hàng quá khứ trở nên kém hiệu quả khi dự đoán nhu cầu hiện tại.

Ví dụ về concept drift

  1. Kiểm duyệt nội dung mạng xã hội: Mô hình kiểm duyệt phải liên tục thích nghi với ngôn ngữ và hiện tượng văn hóa đang phát triển, nếu không sẽ dễ phân loại sai nội dung không phù hợp.
  2. Xe tự hành: Mô hình trong ô tô tự lái cần được cập nhật theo luật lệ và điều kiện giao thông theo vùng để đạt hiệu năng tốt nhất.
  3. Mô hình phát hiện gian lận: Khi chiến thuật gian lận tiến hóa, mô hình phát hiện gian lận cần được cập nhật để nhận diện các mẫu mới nổi.

Giờ hãy cùng xem một quy trình giám sát ML đầu-cuối.

Quy trình giám sát mô hình ML đầu-cuối trông như thế nào?

Giám sát mô hình gồm ba bước chính mà kỹ sư ML nên lặp lại theo chu kỳ.

1. Giám sát hiệu năng

Bước đầu tiên dĩ nhiên là theo dõi sát sao hiệu năng mô hình trong triển khai. Nhưng nói thì dễ hơn làm.

Khi ground truth có ngay lập tức cho một mô hình đang chạy trong sản xuất, việc phát hiện thay đổi hành vi của mô hình là dễ. Ví dụ, người dùng có thể lập tức chỉ ra sai sót trong phép ẩn dụ robot/bắn cung của chúng ta vì họ nhìn vào bia và nói robot bắn trượt — ground truth tức thời.

Ngược lại, xét ví dụ mô hình dự đoán vỡ nợ khoản vay. Các mô hình này mỗi tháng dự đoán liệu người dùng có vỡ nợ khoản thanh toán tiếp theo hay không. Để kiểm chứng dự đoán, mô hình phải đợi đến ngày thanh toán thực tế. Đây là ví dụ về ground truth bị trễ, rất phổ biến trong hệ thống học máy thực tế.

Trong những trường hợp như vậy, chờ ground truth để biết mô hình hoạt động tốt hay không là quá tốn kém. Vì vậy, kỹ sư ML cần các phương pháp ước lượng hiệu năng mô hình mà không cần ground truth. Đây là lúc các thuật toán như CBPE hay DLE phát huy (sẽ nói sau).

Giám sát mô hình cũng có thể thực hiện bằng cách đo tác động kinh doanh trực tiếp, tức giám sát KPI (chỉ số hiệu suất chính). Trong trường hợp Zillow, một hệ thống giám sát phù hợp có thể đã phát hiện sụt giảm lợi nhuận và cảnh báo kỹ sư (giả định).

2. Phân tích nguyên nhân gốc rễ

Nếu hệ thống giám sát phát hiện sụt giảm hiệu năng, bất kể hệ thống phân tích hiệu năng ghi nhận (có ground truth) hay ước lượng (không có ground truth), kỹ sư ML phải xác định nguyên nhân phía sau sự sụt giảm.

Thường sẽ kiểm tra từng đặc trưng hoặc kết hợp đặc trưng để tìm data (feature drift) và xem xét mục tiêu để phát hiện concept drift.

Dựa trên phát hiện, họ áp dụng các kỹ thuật xử lý vấn đề khác nhau.

3. Xử lý vấn đề

Dưới đây là danh sách không đầy đủ các kỹ thuật giảm thiểu thiệt hại do suy giảm hiệu năng sau triển khai:

  1. Cân bằng lại dữ liệu: Nếu sụt giảm hiệu năng do data drift, điều chỉnh tập huấn luyện để phản ánh điều kiện hiện tại là lựa chọn tốt.
  2. Kỹ thuật đặc trưng: Cập nhật hoặc tạo đặc trưng mới có thể cải thiện hiệu năng. Cách này phù hợp với concept drift, khi quan hệ giữa đầu vào và đầu ra đã thay đổi.
  3. Huấn luyện lại mô hình: Một phương án tốn kém hơn là huấn luyện lại mô hình với dữ liệu mới để đảm bảo độ chính xác. Cách này hiệu quả với cả data và concept drift.
  4. Fine-tune mô hình: Thay vì huấn luyện lại từ đầu, một số mô hình có thể fine-tune trên tập dữ liệu gần đây. Rất phù hợp với mô hình học sâu và sinh sinh (generative).
  5. Phát hiện bất thường: Dùng các phương pháp phát hiện bất thường (novelty) có thể nhận diện sớm các mẫu lạ trong dữ liệu sản xuất.
  6. Tham vấn chuyên gia miền: Mời chuyên gia miền có thể mang lại insight sâu về lý do mô hình kém hiệu quả.

Mỗi phương pháp có bối cảnh áp dụng riêng, và thường bạn sẽ triển khai kết hợp.

NannyML xử lý hai bước đầu của quy trình lặp này. Vậy hãy bắt tay vào làm.

Bước 1: Chuẩn bị dữ liệu cho NannyML

Ngoài tập huấn luyện và tập validation, NannyML cần thêm hai tập gọi là reference và analysis với định dạng cụ thể để bắt đầu giám sát. Phần này hướng dẫn bạn cách tạo chúng từ bất kỳ dữ liệu nào.

Đầu tiên, chúng ta cần một mô hình đã được huấn luyện và sẵn sàng triển khai vào sản xuất để giám sát. Cho mục đích này, chúng ta sẽ dùng bộ dữ liệu diamonds và huấn luyện một bộ hồi quy XGBoost.

Nạp dữ liệu, định nghĩa đặc trưng và mục tiêu

import warnings

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder

warnings.filterwarnings("ignore")

Bước đầu tiên sau khi nhập các mô-đun là nạp bộ dữ liệu Diamonds từ Seaborn. Tuy nhiên, chúng ta sẽ dùng một phiên bản đặc biệt của bộ dữ liệu mà tôi chuẩn bị riêng cho bài viết này để minh họa việc giám sát trông như thế nào. Bạn có thể nạp bộ dữ liệu vào môi trường của mình bằng đoạn mã dưới đây:

dataset_link = "https://raw.githubusercontent.com/BexTuychiev/medium_stories/master/2024/1_january/4_intro_to_nannyml/diamonds_special.csv"

diamonds_special = pd.read_csv(dataset_link)
diamonds_special.head()

image8.png

Phiên bản đặc biệt này có một cột tên “set”, chúng ta sẽ bàn ngay sau đây.

Hiện tại, chúng ta sẽ trích xuất tên tất cả đặc trưng, tên đặc trưng phân loại và tên mục tiêu:

# Extract all feature names
all_feature_names = diamonds_special.drop(["price", "set"], axis=1).columns.tolist()

# Extract the columns and cast into category
cats = diamonds_special.select_dtypes(exclude=np.number).columns

# Define the target column
target = "price"

Nhiệm vụ là hồi quy — chúng ta sẽ dự đoán giá kim cương dựa trên thuộc tính vật lý của chúng.

Bộ dữ liệu diamonds khá sạch. Vì vậy, bước tiền xử lý duy nhất là ép các đặc trưng văn bản sang kiểu dữ liệu category của Pandas. Đây là yêu cầu để kích hoạt tiền xử lý dữ liệu phân loại tự động của XGBoost.

for col in cats:
   diamonds_special[col] = diamonds_special[col].astype("category")

Hãy chuyển sang bước chia dữ liệu.

Chia dữ liệu thành bốn tập

Đúng vậy, bạn không nghe nhầm. Chúng ta sẽ chia dữ liệu thành bốn tập. Thông thường, bạn có thể chỉ chia thành ba:

  • Tập huấn luyện để mô hình học mẫu
  • Tập validation để tinh chỉnh siêu tham số
  • Tập kiểm tra để đánh giá cuối cùng trước triển khai

Quy trình giám sát mô hình cần thêm một tập nữa để mô phỏng dữ liệu sản xuất. Mục tiêu là đảm bảo hệ thống phát hiện đúng sụt giảm hiệu năng bằng các thuật toán phù hợp và báo cáo vấn đề.

Vì mục đích này, tôi đã gán nhãn các hàng của Diamonds Special với bốn loại trong cột set:

diamonds_special.set.unique()
['train', 'val', 'test', 'prod']
Categories (4, object): ['prod', 'test', 'train', 'val']

Tập huấn luyện chiếm 70%, phần còn lại mỗi tập là 10% tổng dữ liệu. Hãy chia dữ liệu:

tr = diamonds_special[diamonds_special.set == "train"].drop("set", axis=1)
val = diamonds_special[diamonds_special.set == "validation"].drop("set", axis=1)
test = diamonds_special[diamonds_special.set == "test"].drop("set", axis=1)
prod = diamonds_special[diamonds_special.set == "prod"].drop("set", axis=1)

tr.shape
(37758, 10)

Nhưng dữ liệu thực tế không đi kèm nhãn tập dựng sẵn, nên bạn phải tự chia thủ công thành bốn tập. Đây là một hàm thực hiện nhiệm vụ đó bằng train_test_split từ sklearn:

def split_into_four(df, train_size=0.7):
   """
   A function to split a dataset into four sets:
   - Training
   - Validation
   - Testing
   - Production
   train_size is set by the user.
   The remaining data will be equally divided between the three sets.
   """
   # Do the splits
   training, the_rest = train_test_split(df, train_size=train_size)
   validation, the_rest = train_test_split(the_rest, train_size=1 / 3)
   testing, production = train_test_split(the_rest, train_size=0.5)

   # Reset the indices
   sets = (training, validation, testing, production)
   for set in sets:
       set.reset_index(inplace=True, drop=True)

   return sets


tr, val, test, prod = split_into_four(your_dataset)

Lưu ý: Dùng nút “Explain code” để nhận giải thích từng dòng cho hàm.

Giờ hãy chuyển sang huấn luyện mô hình.

Huấn luyện mô hình

Trước khi huấn luyện mô hình XGBoost, chúng ta cần chuyển các tập dữ liệu thành DMatrix. Mã như sau:

dtrain = xgb.DMatrix(tr[all_feature_names], label=tr[target], enable_categorical=True)
dval = xgb.DMatrix(val[all_feature_names], label=val[target], enable_categorical=True)

dtest = xgb.DMatrix(
   test[all_feature_names], label=test[target], enable_categorical=True
)
dprod = xgb.DMatrix(
   prod[all_feature_names], label=prod[target], enable_categorical=True
)

Sau đây là mã huấn luyện bộ hồi quy với siêu tham số đã tinh chỉnh:

# Define optimized parameters
params = {
   "n_estimators": 10000,
   "learning_rate": 0.1,
   "tree_method": "gpu_hist",
   "max_depth": 6,
   "min_child_weight": 1,
   "gamma": 0,
   "subsample": 0.8,
   "colsample_bytree": 0.8,
   "objective": "reg:squarederror",
   "reg_alpha": 0.01,
   "reg_lambda": 1,
}

# Training with early stopping
regressor = xgb.train(
   params,
   dtrain,
   num_boost_round=10000,
   evals=[(dtrain, "train"), (dval, "eval")],
   early_stopping_rounds=50,
   verbose_eval=500,
)
[0]	train-rmse:3638.77217	eval-rmse:0.00000
[49]	train-rmse:502.61376	eval-rmse:0.00000

Tuyệt — chúng ta có mô hình đạt RMSE 503$ trên tập validation. Hãy đánh giá lần cuối trên tập test:

from sklearn.metrics import mean_squared_error

# Predict on the test set
y_test_pred = regressor.predict(dtest)

# Evaluate
mean_squared_error(test[target], y_test_pred, squared=False)
551.2763827068798

Hiệu năng kiểm tra là 551$. Khá ổn.

Tạo tập reference

Đến đây mọi thứ khá đơn giản. Giờ đến phần chính — tạo các tập reference và analysis.

Tập reference là tên khác của tập test trong ngữ cảnh giám sát mô hình. NannyML dùng hiệu năng của mô hình trên tập test làm chuẩn so sánh cho hiệu năng sản xuất. Tập reference phải có hai cột ngoài các đặc trưng:

  • Chính cột mục tiêu — ground truth — giá kim cương
  • Dự đoán trên tập kiểm tra — chúng ta đã tạo trong y_test_pred

Hiện tại, tập test có các đặc trưng và mục tiêu nhưng thiếu y_test_pred:

test.columns  # Ignore the `set` column
Index(['carat', 'cut', 'color', 'clarity', 'depth', 'table', 'price', 'x', 'y',
      'z'],
     dtype='object')

Hãy thêm vào:

test["y_pred"] = y_test_pred

Giờ chúng ta sẽ đổi tên tập test thành reference:

reference = test.copy(deep=True)

reference.columns
Index(['carat', 'cut', 'color', 'clarity', 'depth', 'table', 'price', 'x', 'y',
      'z', 'y_pred'],
     dtype='object')

Tạo tập analysis

Tại thời điểm này, hãy tưởng tượng bộ hồi quy của chúng ta đã được triển khai lên cloud. Tưởng tượng đơn giản hơn triển khai thật, điều này vượt ngoài phạm vi bài viết.

Sau khi triển khai mô hình định giá kim cương, chúng ta nhận tin một lô kim cương lớn sắp về. Trước khi hàng đến, các số đo vật lý của kim cương được gửi cho chúng ta dưới dạng prod (vẫn đang tưởng tượng) để chúng ta tạo giá và bắt đầu quảng bá trên website. Vậy hãy sinh giá.

# Generate prices for production data
y_prod_pred = regressor.predict(dprod)

Trước khi kim cương thực tế đến và chuyên gia xác minh giá do mô hình tạo, chúng ta phải kiểm tra mô hình có hoạt động tốt không. Chúng ta không muốn niêm yết kim cương với giá không chính xác trên website.

Để làm điều này, chúng ta cần đo hiệu năng của mô hình bằng cách so sánh y_prod_pred với giá thực của lô kim cương mới, tức ground truth. Nhưng chúng ta sẽ không có ground truth trước khi giá được xác minh. Vì vậy, chúng ta cần ước lượng hiệu năng của mô hình mà không có ground truth.

Để làm việc này, NannyML yêu cầu một tập analysis — dữ liệu chứa dữ liệu sản xuất kèm dự đoán do mô hình tạo.

Tạo tập analysis tương tự như tạo reference:

# Add the predictions of new diamonds to prod
prod["y_pred"] = y_prod_pred

analysis = prod.copy(deep=True)
analysis.columns
Index(['carat', 'cut', 'color', 'clarity', 'depth', 'table', 'price', 'x', 'y',
      'z', 'y_pred'],
     dtype='object')

Giờ chúng ta sẵn sàng ước lượng hiệu năng của regressor.

Bước 2: Ước lượng hiệu năng trong NannyML

NannyML cung cấp hai thuật toán chính để ước lượng hiệu năng cho mô hình hồi quy và phân loại:

  • Direct Loss Estimation (DLE) cho hồi quy
  • Confidence-Based Performance Estimation (CBPE) cho phân loại

Chúng ta sẽ dùng thuật toán DLE cho nhiệm vụ này. DLE có thể đo hiệu năng mô hình trong sản xuất mà không cần ground truth và báo cáo nhiều pseudo-metrics cho hồi quy như RMSE, RMSLE, MAE, v.v.

Để dùng DLE, trước tiên chúng ta cần fit nó với reference để thiết lập hiệu năng nền.

Ước lượng hiệu năng bằng DLE trong NannyML

import nannyml  # pip install nannyml

estimator = nannyml.DLE(
   feature_column_names=all_feature_names,
   y_true=target,
   y_pred="y_pred",
   metrics=["rmse"],
   chunk_size=250,
)

Khởi tạo DLE cần ba tham số — tên các đặc trưng đầu vào, tên cột chứa ground truth cho kiểm tra và tên cột chứa dự đoán kiểm tra.

Thêm vào đó, chúng ta truyền RMSE làm metric và kích thước chunk là 250. Hãy fit estimator lên reference và ước lượng hiệu năng trên analysis:

# Fit to the reference set
estimator.fit(reference)

# Estimate on the analysis set
estimated_results = estimator.estimate(analysis)
estimated_results
<nannyml.performance_estimation.direct_loss_estimation.result.Result at 0x7f3954af1c90>

Chúng ta có một đối tượng Result của NannyML có thể vẽ biểu đồ. Hãy xem nó hiển thị gì:

estimated_results.plot().show()

image1.png

Hãy diễn giải biểu đồ — nó có hai phần hiển thị hiệu năng trên tập reference và analysis. Nếu RMSE ước lượng của sản xuất vượt ngưỡng, NannyML đánh dấu cảnh báo.

Như ta thấy, có vài cảnh báo cho dữ liệu sản xuất, gợi ý có gì đó “không ổn” ở những lô cuối.

Bước 3: Hiệu năng ước lượng vs. hiệu năng thực tế trong giám sát

Hệ thống giám sát cho biết hiệu năng mô hình giảm khoảng một nửa trong sản xuất. Nhưng đó chỉ là ước lượng — chúng ta chưa thể khẳng định chắc chắn.

Trong lúc chúng ta đang vẽ biểu đồ hiệu năng ước lượng, lô hàng đã đến và chuyên gia kim cương đã tính giá thực tế. Chúng ta đã lưu chúng là price trong prod.

Giờ chúng ta có thể so sánh hiệu năng thực tế (realized) của mô hình với hiệu năng ước lượng để xem hệ thống giám sát hoạt động tốt không.

NannyML cung cấp lớp PerformanceCalculator để làm việc này:

calculator = nannyml.PerformanceCalculator(
   problem_type="regression",
   y_true=target,
   y_pred="y_pred",
   metrics=["rmse"],
   chunk_size=250,
)

calculator.fit(reference)
realized_results = calculator.calculate(analysis)

Lớp này cần bốn tham số:

  • problem_type: Nhiệm vụ là gì?
  • y_true: Nhãn là gì?
  • y_pred: Tìm dự đoán ở đâu?
  • metrics: Dùng metric nào để tính hiệu năng?

Sau khi truyền các tham số và fit calculator với reference, chúng ta calculate trên tập analysis.

Để so sánh realized_results với estimated_results, chúng ta lại dùng biểu đồ:

estimated_results.compare(realized_results).plot().show()

image5.png

Có vẻ RMSE ước lượng (màu tím) khá sát với hiệu năng thực tế (RMSE thực, màu xanh).

Điều này cho chúng ta thấy một điều — hệ thống giám sát hoạt động tốt, nhưng mô hình thì không, thể hiện qua mất mát tăng. Vậy lý do là gì?

Chúng ta sẽ đi sâu vào ngay bây giờ.

Bước 4: Các phương pháp phát hiện drift

Như đã đề cập ở phần mở đầu, một trong những lý do phổ biến khiến mô hình thất bại trong sản xuất là drift. Ở phần này, chúng ta tập trung vào phát hiện drift dữ liệu (đặc trưng).

Phát hiện drift là một phần của bước phân tích nguyên nhân gốc rễ trong quy trình giám sát mô hình. Thông thường, nó bắt đầu bằng phát hiện drift đa biến.

Phát hiện drift đa biến

Một trong những phương pháp phát hiện drift đa biến tốt là tính lỗi tái tạo dữ liệu bằng PCA. Phương pháp này hoạt động rất tốt và có thể bắt được cả những drift nhỏ nhất trong phân phối đặc trưng. Dưới đây là tổng quan mức cao của phương pháp:

1. PCA fit trên reference và nén nó xuống không gian thấp hơn - reference_lower.

  • Ở bước này, một phần thông tin của bộ dữ liệu gốc bị mất do bản chất của PCA.

2. reference_lower sau đó được giải nén về số chiều ban đầu - reference_reconstructed.

  • Vì thông tin đã mất ở bước 1, dữ liệu tái tạo sẽ không giống hoàn toàn reference.

3. Hiệu giữa reference và reference_reconstructed được tính và gọi là lỗi tái tạo dữ liệu - reconstruct_error.

  • reconstruct_error đóng vai trò chuẩn để so sánh lỗi tái tạo của dữ liệu sản xuất

4. Áp dụng cùng quy trình nén/giải nén cho các lô dữ liệu sản xuất.

  • Nếu lỗi tái tạo của dữ liệu sản xuất cao hơn chuẩn, ta nói các đặc trưng đã drift.
  • Hệ thống gửi cảnh báo thúc giục chúng ta điều tra dữ liệu sản xuất kỹ hơn

Bốn bước này được hiện thực trong lớp DataReconstructionDriftCalculator của NannyML. Cách dùng như sau:

# Initialize
multivariate_calc = nannyml.DataReconstructionDriftCalculator(
   column_names=all_feature_names,
   chunk_size=250,
)

# Fit
multivariate_calc.fit(reference)
# Calculate error
multivariate_results = multivariate_calc.calculate(analysis)

Khi đã có lỗi cho mỗi chunk dữ liệu (mỗi chunk 250 dòng), chúng ta có thể vẽ biểu đồ:

multivariate_results.plot().show()

image3.png

Như thấy, lỗi tái tạo rất cao, cho thấy có drift ở các đặc trưng. Chúng ta cũng có thể so sánh lỗi với hiệu năng thực tế:

multivariate_results.compare(realized_results).plot().show(config={"staticPlot": True})

image7.png

Như thấy, mọi đỉnh tăng của mất mát đều tương ứng với các cảnh báo về lỗi tái tạo.

Phát hiện drift đơn biến

Lỗi tái tạo dữ liệu là một con số đơn để đo drift cho tất cả đặc trưng. Nhưng còn drift của từng đặc trưng riêng lẻ thì sao? Nếu bộ dữ liệu có hàng trăm đặc trưng, làm sao tìm ra những đặc trưng drift nhiều nhất và có biện pháp phù hợp?

Đó là lúc dùng các phương pháp phát hiện drift đơn biến. NannyML cung cấp nhiều phương pháp tùy loại đặc trưng:

  • Đặc trưng phân loại: L-infinity, Chi2
  • Đặc trưng liên tục: Wasserstein, kiểm định Kolmogorov–Smirnov
  • Cả hai: Jensen–Shannon distance, Hellinger distance

Tất cả phương pháp này so sánh phân phối của từng đặc trưng trong reference với phân phối trong tập analysis. Chúng ta có thể dùng một số (hoặc tất cả) trong lớp UnivariateDriftCalculator:

univariate_calc = nannyml.UnivariateDriftCalculator(
   column_names=all_feature_names,
   continuous_methods=["wasserstein"],
   categorical_methods=["jensen_shannon"],
   chunk_size=250,
)

univariate_calc.fit(reference)
univariate_results = univariate_calc.calculate(analysis)

Tham số bắt buộc duy nhất là column_names, phần còn lại có thể dùng mặc định của NannyML. Nhưng để đơn giản, chúng ta dùng wasserstein và jensen_shannon cho đặc trưng liên tục và phân loại.

Hiện chúng ta có 11 đặc trưng, nên gọi plot().show() có thể không tối ưu. Thay vào đó, ta dùng alert count ranker để trả về các đặc trưng tạo ra nhiều cảnh báo nhất (khi xét tất cả chunk). Mã như sau:

# Initialize the ranker
alert_count_ranker = nannyml.AlertCountRanker()

# Filter the univariate results for only columns containing the metrics
filtered_univariate = univariate_results.filter(
   continuous_methods=["wasserstein"],
   categorical_methods=["jensen_shannon"],
   only_drifting=False,
)

# Rank the alerts
ranker_results = alert_count_ranker.rank(filtered_univariate)

Khi đã có kết quả xếp hạng, chúng ta có thể in phần đầu vì nó là một Pandas DataFrame:

ranker_results.head(10)

image4.png

Ta thấy các đặc trưng gây vấn đề nhiều nhất là color và depth. Điều này không làm tôi ngạc nhiên vì chính tôi đã cố ý tạo drift cho chúng trước khi viết bài.

Nhưng nếu là tình huống thực tế, bạn sẽ muốn dành thời gian xử lý vấn đề cho các đặc trưng này.

Kết luận

Tôi thấy giám sát mô hình rất thú vị vì nó phá vỡ ảo tưởng rằng học máy kết thúc khi bạn có một mô hình tốt. Khi Trái Đất quay và hành vi người dùng thay đổi, không mô hình nào giữ nguyên giá trị lâu dài. Điều này khiến giám sát mô hình trở thành kỹ năng thiết yếu của mọi kỹ sư ML.

Hôm nay, chúng ta đã đi qua một quy trình giám sát mô hình cơ bản. Chúng ta bắt đầu với các khái niệm nền tảng về giám sát. Sau đó, đi thẳng vào mã: chuẩn hóa dữ liệu theo định dạng tương thích với NannyML; tạo biểu đồ đầu tiên cho hiệu năng ước lượng của mô hình, và biểu đồ khác để so sánh với hiệu năng thực tế; nhận vài cảnh báo rằng hiệu năng đang giảm; kiểm tra bằng phát hiện drift đa biến; phát hiện drift đặc trưng nghiêm trọng; kiểm tra chéo bằng phát hiện drift từng đặc trưng; xác định đặc trưng đang drift.

Đáng tiếc, chúng ta dừng lại ngay trước bước xử lý vấn đề. Bước cuối trong quy trình giám sát vượt ngoài phạm vi bài viết này. Tuy nhiên, tôi có vài gợi ý tuyệt vời bao quát phần đó và nhiều nội dung về giám sát mô hình:

Cả hai khóa học đều được tạo bởi người giỏi nhất mà bạn có thể hy vọng — CEO và nhà sáng lập NannyML. Trong các khóa, có rất nhiều “viên ngọc” thông tin bạn không thể bỏ lỡ.

Tôi cũng khuyến nghị đọc tài liệu Nanny ML để có các hướng dẫn thực hành.

Bexruz (Bex) Tuychiev

Tác giả

Bexruz (Bex) Tuychiev

Tôi là người sáng tạo nội dung về khoa học dữ liệu với hơn 2 năm kinh nghiệm và là một trong những tài khoản có lượng người theo dõi lớn nhất trên Medium. Tôi thích viết các bài chuyên sâu về AI và ML với chút giọng điệu mỉa mai, vì bạn cũng phải làm gì đó để chúng bớt khô khan. Tôi đã xuất bản hơn 130 bài viết và một khóa học trên DataCamp, cùng với một khóa nữa đang được thực hiện. Nội dung của tôi đã được hơn 5 triệu lượt xem, trong đó 20 nghìn người đã trở thành người theo dõi trên cả Medium và LinkedIn. 

Chủ đề

Liên quan