File size: 7,335 Bytes
77fa523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix, classification_report, roc_curve, auc, precision_score, f1_score, recall_score
import pandas as pd
from tensorflow.keras.models import load_model
import argparse

def plot_confusion_matrix(y_true, y_pred, classes):
    """

    Vẽ ma trận nhầm lẫn

    """
    cm = confusion_matrix(y_true, y_pred)
    plt.figure(figsize=(10, 8))
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
                xticklabels=classes, yticklabels=classes)
    plt.title('Ma trận nhầm lẫn')
    plt.ylabel('Nhãn thực tế')
    plt.xlabel('Nhãn dự đoán')
    plt.savefig('confusion_matrix.png')
    plt.close()

def plot_roc_curve(y_true, y_pred_proba, classes):
    """

    Vẽ đường cong ROC

    """
    plt.figure(figsize=(10, 8))
    for i, class_name in enumerate(classes):
        fpr, tpr, _ = roc_curve(y_true == i, y_pred_proba[:, i])
        roc_auc = auc(fpr, tpr)
        plt.plot(fpr, tpr, label=f'{class_name} (AUC = {roc_auc:.2f})')
    
    plt.plot([0, 1], [0, 1], 'k--')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.xlabel('Tỷ lệ dương tính giả')
    plt.ylabel('Tỷ lệ dương tính thật')
    plt.title('Đường cong ROC')
    plt.legend(loc="lower right")
    plt.savefig('roc_curve.png')
    plt.close()

def plot_training_history(history):
    """

    Vẽ đồ thị quá trình huấn luyện

    """
    plt.figure(figsize=(12, 4))
    
    # Vẽ đồ thị loss
    plt.subplot(1, 2, 1)
    plt.plot(history.history['loss'], label='Training Loss')
    plt.plot(history.history['val_loss'], label='Validation Loss')
    plt.title('Loss trong quá trình huấn luyện')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend()
    
    # Vẽ đồ thị accuracy
    plt.subplot(1, 2, 2)
    plt.plot(history.history['accuracy'], label='Training Accuracy')
    plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
    plt.title('Accuracy trong quá trình huấn luyện')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend()
    
    plt.tight_layout()
    plt.savefig('training_history.png')
    plt.close()

def plot_metrics_bar(y_true, y_pred, classes):
    """

    Vẽ biểu đồ cột cho các chỉ số Precision, Recall và F1-score

    """
    precision = precision_score(y_true, y_pred, average=None)
    recall = recall_score(y_true, y_pred, average=None)
    f1 = f1_score(y_true, y_pred, average=None)
    
    metrics = np.vstack((precision, recall, f1))
    
    plt.figure(figsize=(12, 6))
    x = np.arange(len(classes))
    width = 0.25
    
    plt.bar(x - width, precision, width, label='Precision')
    plt.bar(x, recall, width, label='Recall')
    plt.bar(x + width, f1, width, label='F1-score')
    
    plt.xlabel('Classes')
    plt.ylabel('Scores')
    plt.title('Precision, Recall và F1-score cho từng lớp')
    plt.xticks(x, classes, rotation=45)
    plt.legend()
    plt.tight_layout()
    plt.savefig('metrics_bar.png')
    plt.close()

def evaluate_model(model, X_test, y_test, classes, history=None):
    """

    Đánh giá mô hình và vẽ các sơ đồ

    """
    # Dự đoán
    y_pred = model.predict(X_test)
    y_pred_classes = np.argmax(y_pred, axis=1)
    y_true = np.argmax(y_test, axis=1)
    
    # In báo cáo phân loại
    print("\nBáo cáo phân loại:")
    print(classification_report(y_true, y_pred_classes, target_names=classes))
    
    # Tính toán các chỉ số
    precision = precision_score(y_true, y_pred_classes, average=None)
    recall = recall_score(y_true, y_pred_classes, average=None)
    f1 = f1_score(y_true, y_pred_classes, average=None)
    
    # In các chỉ số chi tiết
    print("\nChi tiết các chỉ số cho từng lớp:")
    for i, class_name in enumerate(classes):
        print(f"\n{class_name}:")
        print(f"Precision: {precision[i]:.4f}")
        print(f"Recall: {recall[i]:.4f}")
        print(f"F1-score: {f1[i]:.4f}")
    
    # Vẽ ma trận nhầm lẫn
    plot_confusion_matrix(y_true, y_pred_classes, classes)
    
    # Vẽ đường cong ROC
    plot_roc_curve(y_true, y_pred, classes)
    
    # Vẽ biểu đồ các chỉ số
    plot_metrics_bar(y_true, y_pred_classes, classes)
    
    # Vẽ đồ thị quá trình huấn luyện nếu có
    if history is not None:
        plot_training_history(history)
    
    # Tính toán và in các metric
    accuracy = np.mean(y_pred_classes == y_true)
    print(f"\nĐộ chính xác tổng thể: {accuracy:.4f}")
    
    # Lưu kết quả vào file
    results = {
        'accuracy': accuracy,
        'precision': precision,
        'recall': recall,
        'f1_score': f1,
        'classification_report': classification_report(y_true, y_pred_classes, target_names=classes, output_dict=True)
    }
    
    # Chuyển đổi kết quả thành DataFrame và lưu
    metrics_df = pd.DataFrame({
        'Class': classes,
        'Precision': precision,
        'Recall': recall,
        'F1-score': f1
    })
    metrics_df.to_csv('detailed_metrics.csv', index=False)
    
    results_df = pd.DataFrame(results['classification_report']).transpose()
    results_df.to_csv('model_evaluation_results.csv')
    
    return results 

if __name__ == "__main__":
    # Tạo parser để nhận tham số từ command line
    parser = argparse.ArgumentParser(description='Đánh giá mô hình phân loại khối u não')
    parser.add_argument('--model_path', type=str, required=True, help='Đường dẫn đến file model (.keras)')
    parser.add_argument('--test_data', type=str, required=True, help='Đường dẫn đến file dữ liệu test (.npy)')
    parser.add_argument('--test_labels', type=str, required=True, help='Đường dẫn đến file nhãn test (.npy)')
    parser.add_argument('--history', type=str, help='Đường dẫn đến file lịch sử huấn luyện (.npy)')
    
    args = parser.parse_args()
    
    # Load model
    print(f"Đang tải model từ {args.model_path}...")
    model = load_model(args.model_path)
    
    # Load dữ liệu test
    print(f"Đang tải dữ liệu test từ {args.test_data}...")
    X_test = np.load(args.test_data)
    y_test = np.load(args.test_labels)
    
    # Load lịch sử huấn luyện nếu có
    history = None
    if args.history:
        print(f"Đang tải lịch sử huấn luyện từ {args.history}...")
        history = np.load(args.history, allow_pickle=True).item()
    
    # Đánh giá mô hình
    print("Bắt đầu đánh giá mô hình...")
    results = evaluate_model(
        model=model,
        X_test=X_test,
        y_test=y_test,
        classes=['glioma', 'meningioma', 'notumor', 'pituitary'],
        history=history
    )
    
    print("\nĐánh giá hoàn tất! Các kết quả đã được lưu vào:")
    print("- confusion_matrix.png")
    print("- roc_curve.png")
    print("- metrics_bar.png")
    print("- detailed_metrics.csv")
    print("- model_evaluation_results.csv")