8.3 KiB
8.3 KiB
In [ ]:
from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
DATA_PATH = Path("data/malware_features.csv")
if not DATA_PATH.exists():
raise FileNotFoundError(
"Missing data/malware_features.csv. Follow data/README.md, place the three "
"official UCI CSV files under data/raw/, and run: python data/prepare_dataset.py"
)
from sklearn.dummy import DummyClassifier
from sklearn.impute import SimpleImputer
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score, accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.tree import export_text
def security_metrics(y_true, y_pred):
tn, fp, fn, tp = confusion_matrix(y_true, y_pred, labels=[0, 1]).ravel()
return {
"accuracy": accuracy_score(y_true, y_pred),
"malware_precision": precision_score(y_true, y_pred, zero_division=0),
"malware_recall": recall_score(y_true, y_pred, zero_division=0),
"malware_f1": f1_score(y_true, y_pred, zero_division=0),
"false_positives": int(fp),
"false_negatives": int(fn),
"false_positive_rate": fp / (fp + tn) if fp + tn else 0.0,
}
OUTPUT_DIR = Path("output")
OUTPUT_DIR.mkdir(exist_ok=True)In [ ]:
# TODO 1: load the dataset, exclude source/label from X, and create an
# 80/20 stratified split that also retains source_test for error auditing.
df = None
feature_cols = None
X = None
y = None
X_train, X_test, y_train, y_test, source_train, source_test = (None,) * 6
print("Train/test rows:", None, None)In [ ]:
# TODO 2: define Dummy, ExplainableTree, DeepTree, and RandomForest.
# Keep ExplainableTree at max_depth=4 and min_samples_leaf=10.
models = None
# TODO 3: fit every model, save predictions/probabilities, and build a
# metrics table with security_metrics.
metric_rows = None
predictions = None
probabilities = None
metrics_table = None
display(metrics_table)In [ ]:
# TODO 4: implement the documented selection rule.
eligible_metrics = None
best_recall = None
best_fpr = None
explainable_ok = None
selected_name = None
selected_model = None
selected_predictions = None
print("Selected model:", selected_name)In [ ]:
# TODO 5: create error_table with source, true label, prediction,
# malware probability, and error_type. Keep mistakes in errors_only.
error_table = None
errors_only = None
display(errors_only["error_type"].value_counts())
# TODO 6: plot and save the selected model's confusion matrix.In [ ]:
# TODO 7: export the ExplainableTree rules even if another model was selected.
tree_rules = None
# TODO 8: write an English analyst summary covering the recommendation,
# metrics, FP/FN costs, data limitations, and deployment safeguards.
analyst_summary = None
# TODO 9: save the metrics, errors, rules, and analyst summary.
print(analyst_summary)In [ ]:
expected_files = {
"capstone_metrics.csv",
"capstone_errors.csv",
"capstone_tree_rules.txt",
"capstone_confusion_matrix.png",
"capstone_analyst_summary.md",
}
assert set(models) == {"Dummy", "ExplainableTree", "DeepTree", "RandomForest"}
assert selected_name in set(models) - {"Dummy"}
assert len(error_table) == len(y_test)
assert set(errors_only["error_type"].unique()).issubset({"false_negative", "false_positive"})
assert isinstance(tree_rules, str) and "class:" in tree_rules
assert expected_files.issubset({path.name for path in OUTPUT_DIR.iterdir()})
print("✓ Lab 6 completed")