Tạo một mô hình học máy dựa vào dữ liệu
Disclaimer
Đào tạo một mô hình học máy hiệu quả là công việc khó khăn. Bản thân mình mặc dù học tập khá là chăm chỉ, nhưng chưa thể tạo được một mô hình học máy hoàn chỉnh. Bài viết này không đề cập tới việc sử dụng các ứng dụng hỗ trợ training và model experiment tracking, do hầu hết chúng mặc dù có thể sử dụng miễn phí, cũng có một giới hạn nhất định. Việc sử dụng công cụ sẽ giúp tiết kiệm nhiều thời gian, nhưng theo mình sẽ giống như nghiện thuốc, dần dần phụ thuộc vào chúng. Bài viêt này được tạo ra với mục đích thuần túy là một báo cáo môn học, không phải một hướng dẫn hay trình tự cần có. Sử dụng nó với đúng nhu cầu, tìm kiếm và kết luận đâu là phương pháp tốt nhất cho chính dự án của bạn.
Cài đặt môi trường để chạy trên local.
Cài đặt python notebook
- Cài đặt python theo hướng dẫn: https://www.python.org/downloads/
- Cài đặt venv (nếu version chưa có)
- Cài đặt jupyter notebook kernel
- Tạo một venv tại thư mục dự án: setting venv
- Cài đặt jupyter notebook
- Tại giao diện notebook, phía trên bên phải, chọn kelnel vừa tạo.
Cài đặt Experiments Tracking tool MLflow
Để thuận tiện, ta sử dụng Docker
docker-compose.yml | |
---|---|
Khởi tạo container, sau đó truy cập vào địa chỉ web http://localhost:5000/
để vào giao diện web.
Dữ liệu sử dụng
Trong bài này, mình đã chuẩn bị một bộ dữ liệu mô phỏng. Download và sử dụng tại đây.
Huấn luyện mô hình
Xem đầy đủ file notebook tại đây
Xử lý dữ liệu
Đọc dữ liệu từ file csv và kiểm tra một số thông tin của dữ liệu
Kết quả cho thấy thông tin các cột, loại dữ liệu của từng cột, số giá trị null của các cột, cuối cùng là một phần dữ liệu.
- Dữ liệu dạng time series: bài toán forecast
- Dữ liệu dạng nhãn: bài toán phân loại.
Ta có thể dễ dàng nhận ra rằng cột cuối cùng của dữ liệu là Label
. Vậy đối với dữ liệu này, bài toán ta cần giải thuộc trường hợp thứ hai.
Phương pháp xử lý dữ liệu thô sơ nhất, là ta xử lý các trường hợp null của các cột. Ở ví dụ này, mình chỉ đơn giản điền các trường null thành -1
Cuối cùng, ta chia dataset thành các tập train, test.
data_sample = data_n_null.sample(frac=0.3) # We just use 30% of dataset to check, which model compatible.
X = data_sample.drop(columns=['Label'])
y = data_sample['Label']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 42)
Đào tạo với mô hình cơ bản
Với bài toán phân loại, có rất nhiều mô hình có thể thực hiện tốt. Với hiểu biết hạn hẹp, ở đây mình chỉ giới thiệu một vài mô hình cơ bản
Ta tiến hành đào tạo và lấy thông số F1, lưu lại các feature có đóng góp quan trọng với mô hình.
model = DecisionTreeClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
f1 = f1_score(y_test, y_pred, average='weighted')
print(f"F1 score: {f1}")
feature_scores = pd.Series(model.feature_importances_, index=X_train.columns).sort_values(ascending=False)
plt.figure(figsize=(20, 20))
sns.barplot(x=feature_scores, y=feature_scores.index)
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
feature_importance_plot = "feature_importance.png"
plt.savefig(feature_importance_plot, bbox_inches='tight')
Tương tự với Random Forest
model = RandomForestClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
f1 = f1_score(y_test, y_pred, average='weighted')
print(f"F1 score: {f1}")
feature_scores = pd.Series(model.feature_importances_, index=X_train.columns).sort_values(ascending=False)
plt.figure(figsize=(20, 20))
sns.barplot(x=feature_scores, y=feature_scores.index)
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
feature_importance_plot = "feature_importance.png"
plt.savefig(feature_importance_plot, bbox_inches='tight')
Cuối cùng là XGBoost
model = XGBClassifier()
label_encoder = LabelEncoder()
y_train_num = label_encoder.fit_transform(y_train)
y_test_num = label_encoder.fit_transform(y_test)
model.fit(X_train, y_train_num)
y_pred = model.predict(X_test)
f1 = f1_score(y_test_num, y_pred, average='weighted')
print(f"F1 score: {f1}")
feature_important = model.get_booster().get_score(importance_type='weight')
keys = list(feature_important.keys())
values = list(feature_important.values())
data = pd.DataFrame(data=values, index=keys, columns=['score']).sort_values(by = 'score', ascending=True)
data.nlargest(40, columns="score").plot(kind='barh', figsize = (20,20))
Ta lần lượt có được thời gian training, thông số F1 cùng hình ảnh minh họa mức độ quan trọng của các cột (feature) trong dataset với mô hình. Hình dưới là kết quả của mô hình Decision Tree
Sử dụng MLflow để tracking các chỉ số của model
Sử dụng MLflow rất đơn giản. Nhiều model có hỗ trợ. Ta chỉ cần gọi một lệnh.
# Setting mlflow information
ML_TRACKING_URL = "http://localhost:5000"
mlflow.set_tracking_uri(ML_TRACKING_URL)
mlflow.set_experiment("decision_tree")
mlflow.sklearn.autolog()
# Star training model
model = DecisionTreeClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
f1 = f1_score(y_test, y_pred, average='weighted')
# Log f1 metric to model metrics
mlflow.log_metric("f1_score", f1)
feature_scores = pd.Series(model.feature_importances_, index=X_train.columns).sort_values(ascending=False)
plt.figure(figsize=(20, 20))
sns.barplot(x=feature_scores, y=feature_scores.index)
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
feature_importance_plot = "feature_importance.png"
plt.savefig(feature_importance_plot, bbox_inches='tight')
# Save figure to model artifact and remove it from local
mlflow.log_artifact(feature_importance_plot)
os.remove(feature_importance_plot)
Sau khi thực thi xong, các thông số được ghi vào MLflow. Thực thi nhiều lần sẽ được ghi nhiều lần. Ta có thể xem nhiều thông số bằng cách nhấn vào từng experiment.
Sử dụng optuna để hyper parameter turning
Có nhiều thuật toán và thư viện để thực hiện nhiệm vụ này. Bản thân mình đã thử nghiệm GridSearchCV và RandomizedSearchCV của sklearn nhưng chúng quá nặng, chạy chậm. Vì vậy không phù hợp với điều kiện hiện tại.
Optunal sử dụng các study
và trial
để định nghĩa quá trình hyper param. Một study bao gồm nhiều trial.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
|
Tổng quát, ta sử dụng optuna để suggest giá trị của các parameter trong một range do ta quy định. Nó chạy tối đa bao nhiêu lần trong tối đa bao nhiêu thời gian để tìm parameter tốt nhất, cho giá trị F1 cao nhất.
Sau khi chạy hoàn tất một study với rất nhiều trial, ta thu thập được nhiều thông số của các lần chạy. Ta tiến hành so sánh các mối tương quan của chúng để điều chỉnh khoảng tham số.
Hình trên cho thấy mức liên quan giữa các parameter tới việc chỉ số F1 của mô hình cao hay thấp. Từ đó quyết định mở rộng, thu hẹp, dịch chuyển khoảng tham số mà ta sẽ cung cấp cho optuna để dò tìm.
Info
Sẽ cố gắng cập nhật theo kiến thức mới của mình.