Decision_Tree_Ud_Tieu_Duong (Notebook)
Ngày đăng: 2026-03-17
Chương 1: TỔNG QUAN VỀ ĐỀ TÀI VÀ KHAI BÁO THƯ VIỆN¶
1.1. Giới thiệu Machine Learning và bài toán nghiên cứu¶
Machine Learning (Học máy) là một lĩnh vực thuộc Trí tuệ nhân tạo (Artificial Intelligence – AI), tập trung vào việc xây dựng các mô hình cho phép máy tính tự động học từ dữ liệu và đưa ra dự đoán hoặc quyết định mà không cần lập trình tường minh cho từng trường hợp cụ thể.
Các thuật toán Machine Learning thường được chia thành ba nhóm chính: học có giám sát, học không giám sát và học tăng cường. Trong đó, học có giám sát là phương pháp phổ biến nhất và được sử dụng rộng rãi trong các bài toán phân loại và hồi quy.
Trong đề tài này, nhóm tập trung vào bài toán học có giám sát, cụ thể là bài toán phân loại nhị phân (binary classification), nhằm dự đoán khả năng mắc bệnh tiểu đường của bệnh nhân dựa trên các chỉ số y tế thu thập được. Thuật toán được lựa chọn là Decision Tree (Cây quyết định), do tính trực quan và khả năng giải thích rõ ràng quá trình ra quyết định.
1.2. Ngôn ngữ lập trình và các thư viện sử dụng¶
Đề tài được thực hiện bằng ngôn ngữ lập trình Python, một ngôn ngữ phổ biến trong lĩnh vực khoa học dữ liệu và học máy nhờ cú pháp đơn giản, dễ đọc và hệ sinh thái thư viện phong phú.
Các thư viện chính được sử dụng trong bài gồm:
- Pandas: cung cấp các cấu trúc dữ liệu dạng bảng như Series và DataFrame, hỗ trợ hiệu quả cho việc xử lý và phân tích dữ liệu.
- NumPy: hỗ trợ các phép toán số học và xử lý mảng đa chiều với hiệu suất cao.
- Scikit-learn (sklearn): thư viện mã nguồn mở quan trọng cho Machine Learning, cung cấp các thuật toán học máy, công cụ chia dữ liệu và đánh giá mô hình.
- Matplotlib và Seaborn: các thư viện trực quan hóa dữ liệu, giúp biểu diễn dữ liệu và kết quả mô hình dưới dạng biểu đồ trực quan.
1.3. Khai báo thư viện¶
# Khai báo thư viện
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
# Cấu hình hiển thị biểu đồ
sns.set_style("whitegrid")
plt.rcParams['figure.figsize'] = (12, 6)
CHƯƠNG 2: DỮ LIỆU VÀ TIỀN XỬ Lݶ
2.1. Tải và khám phá dữ liệu¶
Đề tài sử dụng bộ dữ liệu Pima Indians Diabetes, do National Institute of Diabetes and Digestive and Kidney Diseases cung cấp. Đây là bộ dữ liệu chuẩn mực, thường được sử dụng trong các nghiên cứu và bài toán học máy liên quan đến y tế.
Tập dữ liệu được tải từ Github qua đường link sau: https://raw.githubusercontent.com/npradaschnor/Pima-Indians-Diabetes-Dataset/master/diabetes.csv
# Tải dữ liệu từ GitHub
url = "https://raw.githubusercontent.com/npradaschnor/Pima-Indians-Diabetes-Dataset/master/diabetes.csv"
df = pd.read_csv(url)
print("🔹 5 dòng đầu của dữ liệu:")
display(df.head())
print("\n🔹 Thông tin tổng quan dữ liệu:")
df.info()
🔹 5 dòng đầu của dữ liệu:
| Pregnancies | Glucose | BloodPressure | SkinThickness | Insulin | BMI | DiabetesPedigreeFunction | Age | Outcome | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 6 | 148 | 72 | 35 | 0 | 33.6 | 0.627 | 50 | 1 |
| 1 | 1 | 85 | 66 | 29 | 0 | 26.6 | 0.351 | 31 | 0 |
| 2 | 8 | 183 | 64 | 0 | 0 | 23.3 | 0.672 | 32 | 1 |
| 3 | 1 | 89 | 66 | 23 | 94 | 28.1 | 0.167 | 21 | 0 |
| 4 | 0 | 137 | 40 | 35 | 168 | 43.1 | 2.288 | 33 | 1 |
🔹 Thông tin tổng quan dữ liệu: <class 'pandas.core.frame.DataFrame'> RangeIndex: 768 entries, 0 to 767 Data columns (total 9 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Pregnancies 768 non-null int64 1 Glucose 768 non-null int64 2 BloodPressure 768 non-null int64 3 SkinThickness 768 non-null int64 4 Insulin 768 non-null int64 5 BMI 768 non-null float64 6 DiabetesPedigreeFunction 768 non-null float64 7 Age 768 non-null int64 8 Outcome 768 non-null int64 dtypes: float64(2), int64(7) memory usage: 54.1 KB
2.2. Mô tả bộ dữ liệu¶
Bộ dữ liệu được sử dụng trong đề tài là Pima Indians Diabetes, do National Institute of Diabetes and Digestive and Kidney Diseases cung cấp. Đây là bộ dữ liệu tiêu chuẩn, thường được sử dụng trong các nghiên cứu và bài toán học máy liên quan đến lĩnh vực y tế.
Bộ dữ liệu gồm 768 mẫu quan sát, với 8 thuộc tính đầu vào (features) và 1 biến mục tiêu (target). Các thuộc tính đầu vào phản ánh những chỉ số y tế quan trọng của bệnh nhân, trong khi biến mục tiêu Outcome cho biết tình trạng mắc bệnh tiểu đường (có bệnh hoặc không bệnh).
| Thuộc tính | Ý nghĩa |
|---|---|
| Pregnancies | Số lần mang thai |
| Glucose | Nồng độ glucose trong máu |
| BloodPressure | Huyết áp tâm trương |
| SkinThickness | Độ dày nếp gấp da |
| Insulin | Nồng độ insulin |
| BMI | Chỉ số khối cơ thể |
| DiabetesPedigreeFunction | Chỉ số di truyền bệnh tiểu đường |
| Age | Tuổi |
| Outcome | Nhãn kết quả (0: Không bệnh, 1: Có bệnh) |
Bài toán đặt ra là dự đoán biến Outcome dựa trên các chỉ số y tế của bệnh nhân.
Cần lưu ý rằng trong bộ dữ liệu tồn tại một số giá trị bằng 0 ở các thuộc tính như Glucose, BMI hoặc BloodPressure, trong khi các giá trị này không có ý nghĩa về mặt y học. Trong phạm vi bài tập lớn, nhóm giữ nguyên dữ liệu gốc nhằm tập trung vào việc minh họa và đánh giá thuật toán Decision Tree.
2.3. Phân tích tương quan giữa các đặc trưng¶
Biểu đồ nhiệt (Heatmap) dưới đây thể hiện mức độ tương quan giữa các biến. Các giá trị càng gần 1 hoặc -1 cho thấy mối liên hệ càng mạnh.
# Tính ma trận tương quan
correlation = df.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation, annot=True, cmap='coolwarm', fmt=".2f")
plt.title("Ma trận tương quan giữa các biến", fontsize=14)
plt.show()
2.4. Phân bố nhãn (Outcome)¶
Biểu đồ tròn thể hiện tỷ lệ bệnh nhân có bệnh và không có bệnh trong tập dữ liệu, giúp đánh giá mức độ cân bằng của dữ liệu.
# Đếm số lượng từng nhãn
outcome_counts = df['Outcome'].value_counts()
plt.figure(figsize=(6, 6))
plt.pie(
outcome_counts,
labels=['Không bệnh (0)', 'Có bệnh (1)'],
autopct='%1.1f%%',
startangle=90
)
plt.title("Tỉ lệ phân bố bệnh nhân")
plt.show()
2.5. Kết luận phân tích dữ liệu¶
- Bộ dữ liệu có kích thước vừa phải và không bị thiếu dữ liệu
- Biến Glucose có mức tương quan cao nhất với khả năng mắc bệnh
- Dữ liệu không quá mất cân bằng, phù hợp cho bài toán phân loại
2.6 Phân chia dữ liệu huấn luyện và kiểm tra¶
Trong học máy, việc phân chia dữ liệu thành tập huấn luyện và tập kiểm tra là bước cần thiết để đánh giá khả năng tổng quát hóa của mô hình trên dữ liệu mới.
Trong đề tài này, dữ liệu được chia theo tỷ lệ 80% cho tập huấn luyện và 20% cho tập kiểm tra. Tập huấn luyện được sử dụng để xây dựng mô hình, trong khi tập kiểm tra dùng để đánh giá hiệu quả dự đoán của mô hình sau khi huấn luyện.
# 1. Tách đặc trưng (X) và nhãn (y)
X = df.drop("Outcome", axis=1)
y = df["Outcome"]
# 2. Chia tập dữ liệu
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
CHƯƠNG 3: XÂY DỰNG MÔ HÌNH DECISION TREE¶
3.1. Cơ sở lý thuyết của Decision Tree¶
Decision Tree (Cây quyết định) là một thuật toán học có giám sát, mô phỏng quá trình ra quyết định của con người thông qua chuỗi các câu hỏi dạng điều kiện.
Cấu trúc của cây quyết định bao gồm:
- Nút gốc (Root Node): Nút bắt đầu, đại diện cho thuộc tính quan trọng nhất.
- Nút quyết định (Decision Node): Các nút trung gian dùng để chia dữ liệu.
- Nút lá (Leaf Node): Nút cuối cùng, đưa ra kết quả phân loại.
Thuật toán Decision Tree sử dụng các thước đo độ vẩn đục (impurity) như Gini Index hoặc Entropy để lựa chọn cách phân chia dữ liệu tối ưu tại mỗi nút.
Một ưu điểm lớn của Decision Tree là khả năng giải thích trực quan, đặc biệt phù hợp trong các lĩnh vực như y tế, nơi tính minh bạch của mô hình là yếu tố quan trọng.
3.2. Cấu hình và huấn luyện mô hình¶
Trong đề tài này, mô hình Decision Tree được xây dựng bằng lớp DecisionTreeClassifier trong thư viện scikit-learn.
Mô hình sử dụng chỉ số Gini để đo độ vẩn đục và được giới hạn độ sâu tối đa của cây nhằm giảm hiện tượng overfitting, tức là mô hình học quá chi tiết trên dữ liệu huấn luyện nhưng dự đoán kém trên dữ liệu mới.
- criterion='gini': Sử dụng chỉ số Gini để đo độ vẩn đục.
- max_depth=3: Giới hạn độ sâu của cây nhằm giảm hiện tượng overfitting.
# Huấn luyện mô hình
# max_depth=3 để cây không quá phức tạp, dễ nhìn
dt_model = DecisionTreeClassifier(criterion='gini', max_depth=3, random_state=42)
dt_model.fit(X_train, y_train)
print("Đã huấn luyện xong mô hình Decision Tree!")
Đã huấn luyện xong mô hình Decision Tree!
Chương 4: TRỰC QUAN VÀ ĐÁNH GIÁ MÔ HÌNH¶
4.1. Đánh giá hiệu quả mô hình¶
# Dự đoán
y_pred_dt = dt_model.predict(X_test)
# Đánh giá
rp_dt = classification_report(y_test, y_pred_dt, output_dict=True)
print(classification_report(y_test, y_pred_dt))
print(f"Độ chính xác của Decision Tree: {rp_dt['accuracy']*100:.2f}%")
precision recall f1-score support
0 0.80 0.84 0.82 99
1 0.68 0.62 0.65 55
accuracy 0.76 154
macro avg 0.74 0.73 0.73 154
weighted avg 0.76 0.76 0.76 154
Độ chính xác của Decision Tree: 75.97%
Sau khi huấn luyện, mô hình được sử dụng để dự đoán trên tập dữ liệu kiểm tra. Hiệu quả của mô hình được đánh giá thông qua các chỉ số như Accuracy, Precision, Recall và F1-score, cùng với ma trận nhầm lẫn (Confusion Matrix).
Mặc dù mô hình đạt độ chính xác khoảng 76%, chỉ số này chưa phản ánh đầy đủ hiệu quả trong bối cảnh y tế. Cụ thể, chỉ số Recall của lớp “Có bệnh” đóng vai trò quan trọng hơn, do việc dự đoán sai một bệnh nhân mắc bệnh (còn gọi là False Negative) có thể gây ra hậu quả nghiêm trọng so với việc dự đoán nhầm một người khỏe mạnh là có bệnh.
4.2. Trực quan hóa kết quả¶
Ma trận nhầm lẫn được sử dụng để đánh giá chi tiết số lượng dự đoán đúng và sai của mô hình đối với từng lớp. Bên cạnh đó, sơ đồ cây quyết định giúp trực quan hóa quá trình ra quyết định của mô hình, cho phép quan sát các thuộc tính được ưu tiên trong việc phân loại bệnh nhân.
# Vẽ Confusion Matrix
plt.figure(figsize=(6,5))
sns.heatmap(confusion_matrix(y_test, y_pred_dt), annot=True, fmt='d', cmap='Blues')
plt.xlabel('Dự đoán')
plt.ylabel('Thực tế')
plt.title('Confusion Matrix - Decision Tree')
plt.show()
print()
# Vẽ cây quyết định
plt.figure(figsize=(20,10))
plot_tree(dt_model, filled=True, feature_names=X.columns, class_names=['No', 'Yes'], rounded=True)
plt.title("Mô hình Cây Quyết Định (Decision Tree Visualization)")
plt.show()
4.3. Đề xuất cải tiến và So sánh mô hình¶
Mặc dù Decision Tree (Cây quyết định) rất trực quan và dễ hiểu, nhưng nó có một nhược điểm chí tử là Overfitting (Quá khớp/Học vẹt). Khi dữ liệu thay đổi nhỏ, cấu trúc cây có thể thay đổi hoàn toàn.
Để khắc phục điều này, nhóm đề xuất thử nghiệm mô hình Random Forest (Rừng ngẫu nhiên). Đây là một kỹ thuật Ensemble Learning (Học máy kết hợp) hoạt động dựa trên nguyên lý:
- Thay vì chỉ tin vào 1 cây quyết định, ta xây dựng một "khu rừng" gồm hàng trăm cây khác nhau.
- Kết quả cuối cùng là sự "biểu quyết" (Voting) của tất cả các cây này.
- Giúp giảm thiểu rủi ro sai sót của từng cây đơn lẻ và tăng tính ổn định cho mô hình.
# Huấn luyện Random Forest
rf_model = RandomForestClassifier(n_estimators=100,random_state=42)
rf_model.fit(X_train, y_train)
# Dự đoán
y_pred_rf = rf_model.predict(X_test)
acc_rf = accuracy_score(y_test, y_pred_rf)
# Lấy acc_dt từ rp_dt
acc_dt = rp_dt['accuracy']
print(f"Độ chính xác của Decision Tree: {acc_dt*100:.2f}%")
print(f"Độ chính xác của Random Forest: {acc_rf*100:.2f}%")
if acc_rf > acc_dt:
print("=> Kết luận: Random Forest cho kết quả tốt hơn!")
else:
print("=> Kết luận: Hai mô hình tương đương hoặc cần tinh chỉnh thêm.")
Độ chính xác của Decision Tree: 75.97% Độ chính xác của Random Forest: 72.08% => Kết luận: Hai mô hình tương đương hoặc cần tinh chỉnh thêm.
4.3.1. Phân tích kết quả thực nghiệm¶
Trong bài toán này, nhóm nhận thấy một hiện tượng đặc biệt: Độ chính xác của Random Forest lại thấp hơn Decision Tree đơn lẻ. Nhóm đưa ra các giả thuyết sau:
- Kích thước dữ liệu: Bộ dữ liệu Pima khá nhỏ (768 dòng). Khi dữ liệu ít, các mô hình phức tạp như Random Forest dễ bị nhiễu hơn là một cây quyết định được giới hạn độ sâu (max_depth=3).
- Cấu trúc dữ liệu: Các quy tắc chẩn đoán tiểu đường (như chỉ số Glucose) trong bộ dữ liệu này có thể rất rõ ràng, khiến một cây đơn giản đã đủ sức bao quát hết quy luật mà không cần đến sự phức tạp của cả một khu rừng.
- Tham số mặc định: Random Forest cần được tinh chỉnh (Tuning) kỹ lưỡng hơn về số lượng cây và độ sâu để đạt hiệu quả tối ưu.
4.3.2. Đánh giá và Nhận xét:¶
Trong thực nghiệm này, một kết quả bất ngờ đã xảy ra khi Decision Tree (75.97%) đạt độ chính xác cao hơn Random Forest (72.08%). Qua phân tích, nhóm nhận thấy bộ dữ liệu Pima có kích thước nhỏ, việc sử dụng Decision Tree với độ sâu giới hạn (max_depth=3) giúp mô hình đạt được sự cân bằng tốt giữa lý thuyết và thực tế. Ngược lại, Random Forest dù mạnh mẽ hơn nhưng với các tham số mặc định, nó có xu hướng trở nên quá phức tạp so với bài toán hiện tại. Điều này minh chứng cho một nguyên tắc quan trọng trong Machine Learning: Không phải mô hình phức tạp nhất luôn là mô hình tốt nhất, mà là mô hình phù hợp nhất với đặc điểm dữ liệu.
Chương 5: KẾT LUẬN TỔNG KẾT VÀ HƯỚNG PHÁT TRIỂN¶
5.1. Kết quả đạt được¶
Sau quá trình thực hiện đồ án, nhóm đã hoàn thành các mục tiêu đề ra ban đầu:
- Về dữ liệu: Đã khám phá và trực quan hóa thành công bộ dữ liệu Pima Indians Diabetes. Nhận diện được Glucose là biến có tác động mạnh nhất đến khả năng mắc bệnh tiểu đường thông qua Ma trận tương quan (Heatmap).
- Về mô hình: Xây dựng thành công mô hình Decision Tree với độ chính xác đạt 75.97%. Cây quyết định được trực quan hóa rõ ràng, giúp hiểu được logic phân loại bệnh nhân dựa trên các chỉ số y tế.
- Về cải tiến: Đã triển khai mô hình Random Forest để so sánh. Mặc dù kết quả thực nghiệm cho thấy Random Forest (72.08%) thấp hơn Decision Tree trong trường hợp này, nhưng nhóm đã phân tích được nguyên nhân cốt lõi là do quy mô dữ liệu nhỏ và các tham số chưa được tối ưu hóa (Hyperparameter Tuning).
5.2. Đánh giá ưu và nhược điểm¶
Ưu điểm:
Mô hình Decision Tree rất trực quan, các quy tắc chẩn đoán (nút gốc, nút lá) giúp bác sĩ dễ dàng giải thích kết quả cho bệnh nhân.
Tốc độ huấn luyện nhanh, không yêu cầu chuẩn hóa dữ liệu phức tạp.
Nhược điểm:
Độ chính xác dừng lại ở mức ~76%, vẫn còn sai sót trong việc dự báo (như thể hiện trong Confusion Matrix).
Mô hình dễ bị ảnh hưởng bởi nhiễu nếu cây quá sâu (Overfitting).
5.3. Bài học rút ra và Hướng phát triển¶
- Bài học: Qua đồ án, nhóm hiểu rằng không phải thuật toán phức tạp hơn luôn mang lại kết quả tốt hơn. Sự phù hợp giữa thuật toán và đặc điểm dữ liệu (quy mô, tính chất biến số) là yếu tố quan trọng nhất.
- Hướng phát triển:
- Áp dụng kỹ thuật Grid Search để tìm bộ tham số tối ưu (max_depth, n_estimators) cho Random Forest nhằm lật ngược kết quả.
- Thử nghiệm thêm các thuật toán mạnh mẽ khác như XGBoost hoặc SVM để cải thiện độ chính xác.
- Thu thập thêm nhiều mẫu dữ liệu hơn để mô hình học được nhiều quy luật tổng quát hơn.
from google.colab import drive
drive.mount('/content/drive')
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
%%shell
jupyter nbconvert '/content/drive/MyDrive/Colab Notebooks/bao_cao_bai_tap_lon_python.ipynb' --to html
[NbConvertApp] Converting notebook /content/drive/MyDrive/Colab Notebooks/bao_cao_bai_tap_lon_python.ipynb to html [NbConvertApp] WARNING | Alternative text is missing on 4 image(s). [NbConvertApp] Writing 749219 bytes to /content/drive/MyDrive/Colab Notebooks/bao_cao_bai_tap_lon_python.html
← Quay lại trang chủ