7.0 KiB
7.0 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
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,
}In [ ]:
df = pd.read_csv(DATA_PATH, low_memory=False)
feature_cols = [column for column in df.columns if column not in {"source", "label"}]
X = df[feature_cols].apply(pd.to_numeric, errors="coerce")
y = df["label"].astype(int)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.20, stratify=y, random_state=42
)
print("Train shape:", X_train.shape, "Test shape:", X_test.shape)
print("Malware rate — train/test:", y_train.mean().round(4), y_test.mean().round(4))In [ ]:
dummy = DummyClassifier(strategy="most_frequent")
dummy.fit(X_train, y_train)
dummy_predictions = dummy.predict(X_test)
dummy_metrics = security_metrics(y_test, dummy_predictions)
pd.Series(dummy_metrics, name="dummy")In [ ]:
tree_pipeline = Pipeline([
("imputer", SimpleImputer(strategy="median", add_indicator=True)),
("tree", DecisionTreeClassifier(
max_depth=4,
min_samples_leaf=10,
random_state=42,
)),
])
tree_pipeline.fit(X_train, y_train)
tree_predictions = tree_pipeline.predict(X_test)
tree_metrics = security_metrics(y_test, tree_predictions)
comparison = pd.DataFrame([dummy_metrics, tree_metrics], index=["Dummy", "Decision Tree"])
display(comparison.round(4))
display(pd.DataFrame(
confusion_matrix(y_test, tree_predictions, labels=[0, 1]),
index=["Actual benign", "Actual malware"],
columns=["Predicted benign", "Predicted malware"],
))In [ ]:
assert X_train.shape[0] + X_test.shape[0] == len(df)
assert abs(y_train.mean() - y_test.mean()) < 0.01
assert set(tree_predictions).issubset({0, 1})
assert tree_pipeline.named_steps["tree"].get_depth() <= 4
assert set(comparison.index) == {"Dummy", "Decision Tree"}
assert comparison.loc["Decision Tree", "malware_f1"] >= comparison.loc["Dummy", "malware_f1"]
print("✓ Lab 3 completed")