Spaces:
Sleeping
Sleeping
| import json | |
| import torch | |
| import torch.nn as nn | |
| import torch.optim as optim | |
| from models.gnn import PhishingGNN_Model | |
| from pipeline.graph_engine import TopologicalGraphEngine | |
| from config import * | |
| def run_training_pipeline(): | |
| print("[*] Launching Production Defender V5 Training Run...") | |
| # 1. Try to load real data, fallback to mock if missing | |
| try: | |
| with open("network_telemetry.json", "r") as f: | |
| dataset = json.load(f) | |
| print(f"[+] Loaded {len(dataset)} real telemetry logs.") | |
| except FileNotFoundError: | |
| print("[-] network_telemetry.json not found. Falling back to simulated context.") | |
| dataset = [ | |
| {'ip': '185.220.101.5', 'domain': 'shadow-dns-bypass.net', 'asn': 44050, 'is_malicious': 1.0}, | |
| {'ip': '193.56.28.14', 'asn': 57099, 'is_malicious': 1.0}, | |
| {'ip': '8.8.8.8', 'domain': 'dns.google', 'asn': 15169, 'is_malicious': 0.0} | |
| ] | |
| # 2. Extract logs and structure target threat labels | |
| engine = TopologicalGraphEngine() | |
| x_dict, edge_index_dict = engine.extract_and_build(dataset) | |
| labels_list = [] | |
| for ip_str in engine.ip_map.keys(): | |
| matching_logs = [log for log in dataset if log.get('ip') == ip_str] | |
| label = matching_logs[0].get('is_malicious', 0.0) if matching_logs else 0.0 | |
| labels_list.append([label]) | |
| labels = torch.tensor(labels_list, dtype=torch.float32) | |
| # 3. Model setup | |
| in_channels_dict = {'ip': 16, 'domain': 32, 'asn': 8, 'cert': 16} | |
| model = PhishingGNN_Model( | |
| metadata=GRAPH_METADATA, | |
| in_channels_dict=in_channels_dict, | |
| hidden_channels=HIDDEN_CHANNELS, | |
| num_heads=NUM_HEADS, | |
| num_layers=NUM_LAYERS, | |
| dropout_rate=DROPOUT_RATE | |
| ) | |
| optimizer = optim.AdamW(model.parameters(), lr=0.0005, weight_decay=1e-3) | |
| criterion = nn.BCELoss() | |
| # 4. Optimization Loop | |
| model.train() | |
| for epoch in range(100): | |
| optimizer.zero_grad() | |
| predictions = model(x_dict, edge_index_dict) | |
| # Only calculate loss on the nodes we have labels for | |
| valid_preds = predictions[:len(labels)] | |
| loss = criterion(valid_preds, labels) | |
| loss.backward() | |
| optimizer.step() | |
| if (epoch + 1) % 20 == 0: | |
| print(f"Epoch {epoch+1:03d}/100 | Topological Loss: {loss.item():.5f}") | |
| model.safe_save(MODEL_SAVE_PATH) | |
| print(f"[+] Operational weights successfully frozen at: {MODEL_SAVE_PATH}") | |
| if __name__ == "__main__": | |
| run_training_pipeline() |