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")