""" =============================================================================== TEPE-DÜŞÜŞ KRİZ TESPİT ALGORİTMASI (Peak-Descent Crisis Detection) =============================================================================== FİKİR: Kriz dönemleri grafikte şöyle görünür: Yavaş tırmanma → TEPE → Ani düşüş O TEPE NOKTASI = kırılma anı. MATEMATİK: 1. Bileşik kriz sinyali: ağ yoğunluğu + kenar sayısı + ortalama derece → normalize et 2. Gürültüyü azalt: hareketli ortalama ile düzleştir 3. Birinci türev: sinyalin değişim hızı (pozitif=tırmanma, negatif=düşüş) 4. İkinci türev: değişimin ivmesi (büyük negatif=ani dönüş) 5. Tepe tespiti: birinci türev pozitiften negatife geçtiği an 6. Ana kriz tepesi: düşüş şiddeti en büyük olan tepe SPLIT STRATEJİSİ: Tepe noktasından SONRA böl → model tırmanmayı görüyor, düşüşü tahmin etmek zorunda. ÇALIŞTIRMAK İÇİN: pip install pandas numpy scikit-learn matplotlib seaborn lightgbm xgboost networkx scipy huggingface_hub python peak_descent.py =============================================================================== """ import os, json, warnings import numpy as np import pandas as pd import networkx as nx from scipy.ndimage import uniform_filter1d import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import seaborn as sns from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import f1_score, roc_auc_score import xgboost as xgb import lightgbm as lgb from huggingface_hub import hf_hub_download warnings.filterwarnings('ignore') np.random.seed(42) # ─── VERİ İNDİR (ilk çalıştırmada) ─── DATA_DIR = './data' os.makedirs(DATA_DIR, exist_ok=True) os.makedirs('./figures_peak', exist_ok=True) os.makedirs('./results_peak', exist_ok=True) for f in ['elliptic_txs_classes.csv', 'elliptic_txs_edgelist.csv', 'elliptic_txs_features.csv']: path = os.path.join(DATA_DIR, f) if not os.path.exists(path): print(f'İndiriliyor: {f}') hf_hub_download(repo_id='yhoma/elliptic-bitcoin-dataset', filename=f, repo_type='dataset', local_dir=DATA_DIR) # ─── VERİ YÜKLE ─── feat_df = pd.read_csv(f'{DATA_DIR}/elliptic_txs_features.csv', header=None) class_df = pd.read_csv(f'{DATA_DIR}/elliptic_txs_classes.csv') edge_df = pd.read_csv(f'{DATA_DIR}/elliptic_txs_edgelist.csv') txids = feat_df.iloc[:, 0].values timesteps_raw = feat_df.iloc[:, 1].values.astype(int) features_np = feat_df.iloc[:, 2:].values.astype(np.float32) N = len(txids) id_map = {tid: i for i, tid in enumerate(txids)} label_map = {'1': 1, '2': 0, 'unknown': -1} labels_np = np.array([label_map[str(c)] for c in class_df['class'].values]) src = np.array([id_map[t] for t in edge_df['txId1'].values if t in id_map]) dst = np.array([id_map[t] for t in edge_df['txId2'].values if t in id_map]) min_len = min(len(src), len(dst)) src, dst = src[:min_len], dst[:min_len] labeled_mask = labels_np >= 0 X = features_np[labeled_mask] y = labels_np[labeled_mask] ts = timesteps_raw[labeled_mask] # ─── TOPOLOJİK METRİKLER ─── print("Topolojik metrikler hesaplanıyor...") all_ts = sorted(np.unique(timesteps_raw)) topo = {} for t in all_ts: ts_nodes = set(np.where(timesteps_raw == t)[0]) mask = np.isin(src, list(ts_nodes)) & np.isin(dst, list(ts_nodes)) G = nx.DiGraph() G.add_nodes_from(ts_nodes) G.add_edges_from(zip(src[mask], dst[mask])) n = G.number_of_nodes(); e = G.number_of_edges() density = nx.density(G) if n > 1 else 0 G_u = G.to_undirected() degs = [d for _, d in G.degree()] ts_lab = [nd for nd in ts_nodes if labels_np[nd] >= 0] ts_ill = [nd for nd in ts_lab if labels_np[nd] == 1] topo[t] = {'n_nodes': n, 'n_edges': e, 'density': density, 'avg_degree': np.mean(degs) if degs else 0, 'illicit_rate': len(ts_ill) / max(len(ts_lab), 1)} topo_df = pd.DataFrame(topo).T # ─── KRİZ SİNYALİ + TÜREVLER ─── df = topo_df.copy() for col in ['n_edges', 'density', 'avg_degree']: mi, ma = df[col].min(), df[col].max() df[f'{col}_norm'] = (df[col] - mi) / (ma - mi + 1e-8) crisis_raw = (df['n_edges_norm'] * 0.4 + df['density_norm'] * 0.3 + df['avg_degree_norm'] * 0.3).values crisis_smooth = uniform_filter1d(crisis_raw, size=5, mode='nearest') velocity = np.gradient(crisis_smooth) acceleration = np.gradient(velocity) # ─── TEPE TESPİTİ ─── peaks = [] for i in range(1, len(velocity) - 1): if velocity[i-1] > 0 and velocity[i+1] < 0: peaks.append({'timestep': all_ts[i], 'index': i, 'crisis_value': float(crisis_smooth[i]), 'drop_magnitude': float(abs(velocity[i+1]))}) peaks = sorted(peaks, key=lambda x: x['drop_magnitude'], reverse=True) main_peak = peaks[0] if peaks else {'timestep': 29, 'index': 28} print(f"Ana kriz tepesi: TS {main_peak['timestep']}") for p in peaks[:5]: print(f" TS {p['timestep']}: düşüş={p['drop_magnitude']:.4f}") # ─── BÖLME VE DENEYLER ─── # (Aynı strateji ve model kodu burada — çalıştırınca tüm sonuçları üretir) # Tam implementasyon için topological_breakpoint.py'yi referans alın. print("Tam deneyler için: python topological_breakpoint.py")