-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpreprocessing_cicids.py
More file actions
109 lines (86 loc) · 4.02 KB
/
Copy pathpreprocessing_cicids.py
File metadata and controls
109 lines (86 loc) · 4.02 KB
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
import os
import pandas as pd
import numpy as np
import json
from sklearn.utils import resample
RAW_DIR = "data/cicids" # Folder with raw CSVs
PROCESSED_DIR = "data/processed" # Where output will go
os.makedirs(PROCESSED_DIR, exist_ok=True)
# ===== CONFIG =====
PER_CLASS_MAX = 50_000 # Max rows per class after downsampling (tune as needed)
def preprocess():
print("📂 Loading CICIDS raw data...")
csv_files = [f for f in os.listdir(RAW_DIR) if f.endswith(".csv")]
if not csv_files:
print(f"❌ No CSV files found in '{RAW_DIR}'. Exiting.")
return
# --- 1. Global Label Mapping ---
print("🗺️ Scanning all files to create a consistent label map...")
all_labels = set()
for file in csv_files:
file_path = os.path.join(RAW_DIR, file)
try:
df_labels = pd.read_csv(file_path, usecols=[" Label"], engine="python", encoding="ISO-8859-1")
df_labels.columns = [col.strip() for col in df_labels.columns]
all_labels.update(df_labels["Label"].astype(str).str.strip().unique())
except Exception as e:
print(f"⚠️ Could not read labels from {file}: {e}")
continue
# Stable sorted mapping
global_label_map = {label: idx for idx, label in enumerate(sorted(all_labels))}
print(f"✅ Found {len(global_label_map)} unique labels across all files.")
# --- 2. Load, Clean, Encode, Downsample ---
all_dfs = []
for file in csv_files:
file_path = os.path.join(RAW_DIR, file)
print(f" -> Processing {file}...")
try:
# Try utf-8, fallback
try:
df = pd.read_csv(file_path, engine="python")
except UnicodeDecodeError:
df = pd.read_csv(file_path, engine="python", encoding="ISO-8859-1")
# Strip cols
df.columns = [col.strip() for col in df.columns]
if "Label" not in df.columns:
print(f"⚠️ Skipping {file}: no 'Label' column.")
continue
df["Label"] = df["Label"].astype(str).str.strip()
df["LabelMapped"] = df["Label"].map(global_label_map)
# Fill missing values
for col in df.columns:
if df[col].dtype == "object":
df[col] = df[col].fillna("missing").astype(str)
else:
df[col] = df[col].fillna(0)
# --- Downsampling ---
dfs_down = []
for label, group in df.groupby("LabelMapped"):
if len(group) > PER_CLASS_MAX:
group = resample(group, replace=False, n_samples=PER_CLASS_MAX, random_state=42)
dfs_down.append(group)
df_balanced = pd.concat(dfs_down)
# Save parquet per file
out_file = os.path.join(PROCESSED_DIR, f"processed_{os.path.splitext(file)[0]}.parquet")
df_balanced.to_parquet(out_file, index=False)
print(f"✅ {file} → {out_file} (rows: {len(df_balanced)}, classes: {df_balanced['LabelMapped'].nunique()})")
all_dfs.append(df_balanced)
except Exception as e:
print(f"⚠️ Skipping {file}: {e}")
continue
# --- 3. Combined Dataset ---
if all_dfs:
full_df = pd.concat(all_dfs, ignore_index=True)
# Re-check object cols
for col in full_df.select_dtypes(include=["object"]).columns:
full_df[col] = full_df[col].fillna("missing").astype(str)
combined_file = os.path.join(PROCESSED_DIR, "cicids_full.parquet")
full_df.to_parquet(combined_file, index=False)
print(f"✅ Combined dataset saved → {combined_file} ({len(full_df)} rows, {full_df['LabelMapped'].nunique()} classes)")
# Save global label mapping
with open(os.path.join(PROCESSED_DIR, "label_map.json"), "w") as f:
json.dump(global_label_map, f, indent=2)
print("📝 Label mapping saved → label_map.json")
print("📌 Preprocessing complete.")
if __name__ == "__main__":
preprocess()