Spaces:
Runtime error
Runtime error
| import pandas as pd, numpy as np, gradio as gr | |
| from sklearn.model_selection import train_test_split, GridSearchCV | |
| from sklearn.preprocessing import MinMaxScaler, LabelEncoder | |
| from sklearn.metrics import accuracy_score | |
| from concrete.ml.sklearn import XGBClassifier as ConcreteXGBClassifier | |
| from concrete.ml.deployment import FHEModelDev, FHEModelClient, FHEModelServer | |
| import os | |
| # Örnek dosyalar | |
| SAMPLE_DIR = "Sample Inputs (Excel)" | |
| EXAMPLE_XLSX = [ | |
| f"{SAMPLE_DIR}/ROYAL_2019.xlsx", | |
| f"{SAMPLE_DIR}/MARKA_2016.xlsx", | |
| f"{SAMPLE_DIR}/THYAO_2023.xlsx", | |
| f"{SAMPLE_DIR}/TTRAK_2024.xlsx" | |
| ] | |
| # Global değişkenler | |
| client = None | |
| server = None | |
| encrypted_input = None | |
| encrypted_output = None | |
| fhe_prediction_ready = False | |
| simulate_prediction = [] | |
| fhe_dir = "fhe_model_artifacts" | |
| key_dir = "client_keys" | |
| def safe_div(a: pd.Series, b: pd.Series) -> pd.Series: | |
| return (a / b.replace(0, np.nan)).fillna(0) | |
| def compute_ratios(df: pd.DataFrame) -> pd.DataFrame: | |
| for col in [c for c in df.columns if c != "Periyot"]: | |
| df[col] = pd.to_numeric(df[col], errors="coerce").fillna(0) | |
| ta = df["Dönen Varlıklar"] + df["Duran Varlıklar"] | |
| tl = df["Kısa Vadeli Yükümlülükler"] + df["Uzun Vadeli Yükümlülükler"] | |
| df["Dönen Varlıklar / Aktif (%)"] = 100 * safe_div(df["Dönen Varlıklar"], df["Dönen Varlıklar"] + df["Duran Varlıklar"]) | |
| df["Cari Oran"] = safe_div(df["Dönen Varlıklar"], df["Kısa Vadeli Yükümlülükler"]) | |
| df["Asit Test Oranı"] = safe_div( | |
| df["Dönen Varlıklar"] - df["Stoklar"] - df["Diğer Dönen Varlıklar"], | |
| df["Kısa Vadeli Yükümlülükler"] | |
| ) | |
| df["Nakit Oranı"] = safe_div(df["Nakit ve Nakit Benzerleri"], df["Kısa Vadeli Yükümlülükler"]) | |
| df["Aktif Karlılık (%)"] = safe_div(df["Dönem Net Kar/Zararı"] * 100, ta) | |
| df["Faaliyet Kar Marjı"] = safe_div(df["FAALİYET KARI (ZARARI)"] * 100, df["Satış Gelirleri"]) | |
| df["Esas Faaliyet Kar Marjı"] = safe_div(df["Net Faaliyet Kar/Zararı"] * 100, df["Satış Gelirleri"]) | |
| df["Brüt Kar Marjı (%)"] = safe_div(df["Ticari Faaliyetlerden Brüt Kar (Zarar)"] * 100, df["Satış Gelirleri"]) | |
| df["FAVÖK Marjı (%)"] = safe_div(df["FAALİYET KARI (ZARARI)"] * 100, df["Satış Gelirleri"]) | |
| df["Net Kar Marjı"] = safe_div(df["Dönem Net Kar/Zararı"] * 100, df["Satış Gelirleri"]) | |
| df["Özsermaye Karlılığı (%)"] = safe_div(df["Dönem Net Kar/Zararı"] * 100, df["Özkaynaklar"]) | |
| df["VAFÖK Marjı"] = safe_div(df["FAALİYET KARI (ZARARI)"] * 100, df["Satış Gelirleri"]) | |
| df["ROCE Oranı"] = safe_div(df["FAALİYET KARI (ZARARI)"] * 100, ta) | |
| df["Finansman Gider / Net Satış"] = safe_div(df["Finansman Giderleri"], df["Satış Gelirleri"]) | |
| df["Borç Kaynak Oranı"] = safe_div(tl * 100, df["Özkaynaklar"]) | |
| df["Duran Varlıklar / Aktif "] = safe_div(df["Duran Varlıklar"] * 100, ta) | |
| df["Duran Varlıklar / Maddi Özkaynak"] = safe_div(df["Duran Varlıklar"], df["Özkaynaklar"] - df["Maddi Olmayan Duran Varlıklar"]) | |
| df["Esas Faaliyet Karı / Kısa Vadeli Borç"] = safe_div(df["Net Faaliyet Kar/Zararı"], df["Kısa Vadeli Yükümlülükler"]) | |
| df["FAVÖK / Kısa Vade Borç"] = safe_div(df["FAALİYET KARI (ZARARI)"], df["Kısa Vadeli Yükümlülükler"]) | |
| df["Net Borç / FAVÖK"] = safe_div(tl, df["FAALİYET KARI (ZARARI)"]) | |
| df["Kısa Vade Borç / Aktif"] = safe_div(df["Kısa Vadeli Yükümlülükler"], ta) | |
| df["Kısa Vade Borç / Dönen Varlık"] = safe_div(df["Kısa Vadeli Yükümlülükler"], df["Dönen Varlıklar"]) | |
| df["Kısa Vade Borç / Özsermaye"] = safe_div(df["Kısa Vadeli Yükümlülükler"], df["Özkaynaklar"]) | |
| df["Kısa Vade Borç / Toplam Borç"] = safe_div(df["Kısa Vadeli Yükümlülükler"], tl) | |
| df["Net Satışlar / Kısa Vade Borç"] = safe_div(df["Satış Gelirleri"], df["Kısa Vadeli Yükümlülükler"]) | |
| df["Özsermaye / Aktif"] = safe_div(df["Özkaynaklar"], ta) | |
| df["Özsermaye / Maddi Duran Varlıklar"] = safe_div(df["Özkaynaklar"], df["Maddi Duran Varlıklar"]) | |
| df["Toplam Borç / Özsermaye"] = safe_div(tl, df["Özkaynaklar"]) | |
| df["Aktif Devir Hızı"] = safe_div(df["Satış Gelirleri"], ta) | |
| df["Alacak Devir Hızı"] = safe_div(df["Satış Gelirleri"], df["Ticari Alacaklar"]) | |
| df["Dönen Varlıklar Devir Hızı"] = safe_div(df["Dönen Varlıklar"], df["Satış Gelirleri"]) | |
| df["Ticari Borçlar Devir Hızı"] = -safe_div(df["Satışların Maliyeti (-)"], df["Ticari Borçlar"]) | |
| df["Finansal Kaldıraç"] = safe_div(tl * 100, ta) | |
| df["Stok Devir Hızı"] = -safe_div(df["Satışların Maliyeti (-)"], df["Stoklar"]) | |
| # Altman Z-Score | |
| X1 = safe_div(df["Dönen Varlıklar"] - df["Kısa Vadeli Yükümlülükler"], ta) | |
| X2 = safe_div(df["Geçmiş Yıllar Kar/Zararları"] + df["Dönem Net Kar/Zararı"], ta) | |
| X3 = safe_div(df["SÜRDÜRÜLEN FAALİYETLER VERGİ ÖNCESİ KARI (ZARARI)"], ta) | |
| X4 = safe_div(df["Özkaynaklar"], tl) | |
| X5 = safe_div(df["Satış Gelirleri"], ta) | |
| df["Altman Z-Skoru"] = 1.2 * X1 + 1.4 * X2 + 3.3 * X3 + 0.6 * X4 + X5 | |
| # Springate | |
| S3 = safe_div(df["SÜRDÜRÜLEN FAALİYETLER VERGİ ÖNCESİ KARI (ZARARI)"], df["Kısa Vadeli Yükümlülükler"]) | |
| df["Springate Skoru"] = 1.03 * X1 + 3.07 * X3 + 0.66 * S3 + 0.4 * X5 | |
| # Zmijewski | |
| Z1 = safe_div(df["Dönem Net Kar/Zararı"], ta) | |
| Z2 = safe_div(tl, ta) | |
| Z3 = safe_div(df["Dönen Varlıklar"], df["Kısa Vadeli Yükümlülükler"]) | |
| df["Zmijewski Skoru"] = -4.3 - 4.5 * Z1 + 5.7 * Z2 - 0.004 * Z3 | |
| #L Model Score | |
| L1 = X1 | |
| L2 = X2 | |
| L3 = X3 | |
| L4 = X4 | |
| L5 = X5 | |
| L6_num = safe_div(df["Nakit ve Nakit Benzerleri"], df["Kısa Vadeli Yükümlülükler"]) | |
| L6 = safe_div(L6_num, df["Kısa Vadeli Yükümlülükler"] + df["Uzun Vadeli Yükümlülükler"]) | |
| L7 = safe_div(df["Kısa Vadeli Yükümlülükler"] + df["Uzun Vadeli Yükümlülükler"], df["Dönen Varlıklar"] + df["Duran Varlıklar"]) | |
| df["L Model Skoru"] = -0.113*L1 + 0.238*L2 - 0.052* L3 - 0.051* L4 + 0.011* L5 + 0.729*L6 - 0.639*L7 | |
| return df | |
| # ------------------------ MODEL EĞİTİMİ ------------------------ | |
| df = pd.read_csv("refined_data.csv") | |
| df["Görüs Tipi"] = df["Görüs Tipi"].apply(lambda x: "Olumlu" if "olumlu" in str(x).lower() else x) | |
| DROP = ["Şirket Adı", "Şirketin Kodu", "Periyot", "Yıl", "Dönen Varlıklar", "Duran Varlıklar", | |
| "Toplam Varlıklar", "Kısa Vadeli Yükümlülükler", "Uzun Vadeli Yükümlülükler", | |
| "Toplam Yükümlülükler", "Toplam Özkaynaklar", "Ana Ortaklığa Ait Özkaynaklar", | |
| "Kontrol Gücü Olmayan Kaynaklar", "Toplam Kaynaklar"] | |
| df = df.drop(columns=DROP) | |
| df = df.dropna(subset=["Görüs Tipi"]) | |
| X = df.drop(columns=["Görüs Tipi"]) | |
| y = df["Görüs Tipi"] | |
| X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42) | |
| scaler_full = MinMaxScaler().fit(X_tr) | |
| Xtr_s = scaler_full.transform(X_tr) | |
| Xte_s = scaler_full.transform(X_te) | |
| encoder = LabelEncoder() | |
| ytr_e = encoder.fit_transform(y_tr) | |
| yte_e = encoder.transform(y_te) | |
| # Grid Search | |
| grid = GridSearchCV( | |
| ConcreteXGBClassifier(n_bits=8, random_state=42), | |
| {"n_estimators": [20, 30, 50], "max_depth": [3, 4, 5], "learning_rate": [0.1, 0.2]}, | |
| cv=3, scoring="accuracy", verbose=0 | |
| ) | |
| grid.fit(Xtr_s, ytr_e) | |
| best_params = grid.best_params_ | |
| # Özellik seçimi | |
| full_plain = ConcreteXGBClassifier(n_bits=8, **best_params, random_state=42) | |
| full_plain.fit(Xtr_s, ytr_e) | |
| imp_df = pd.DataFrame({"col": X.columns, "imp": full_plain.feature_importances_}) | |
| imp_df = imp_df.sort_values("imp", ascending=False).reset_index(drop=True) | |
| imp_df["cum"] = imp_df["imp"].cumsum() | |
| COLS = imp_df.loc[imp_df["cum"] <= 0.95, "col"].tolist() | |
| # Final model | |
| scaler_sel = MinMaxScaler().fit(X_tr[COLS]) | |
| Xtr_sel = scaler_sel.transform(X_tr[COLS]) | |
| if os.path.exists(fhe_dir): | |
| shutil.rmtree(fhe_dir) | |
| final_model = ConcreteXGBClassifier(n_bits=8, **best_params, random_state=42) | |
| final_model.fit(Xtr_sel, ytr_e) | |
| final_model.compile(Xtr_sel) | |
| dev = FHEModelDev(path_dir=fhe_dir, model=final_model) | |
| dev.save() | |
| print("\n🔍 Seçilen Özellikler (%95 etkili):") | |
| for i, col in enumerate(COLS, 1): | |
| print(f"{i:>2}. {col}") | |
| # ------------------------ FONKSİYONLAR ------------------------ | |
| import shutil | |
| def generate_keys(): | |
| global client | |
| # Klasörleri temizle | |
| if os.path.exists(key_dir): | |
| shutil.rmtree(key_dir) | |
| os.makedirs(key_dir, exist_ok=True) | |
| client = FHEModelClient(path_dir=fhe_dir, key_dir=key_dir) | |
| # force yeni key yaratması için: eski key'leri sildik zaten | |
| serialized_eval_keys = client.get_serialized_evaluation_keys() | |
| return str(serialized_eval_keys[:120]) + "..." | |
| def encrypt_excel(file): | |
| if file is None: | |
| raise gr.Error("Lütfen önce bir Excel dosyası yükleyin.") | |
| global encrypted_input, encrypted_output, fhe_prediction_ready, simulate_prediction | |
| if client is None: | |
| raise gr.Error("Lütfen önce 'Anahtar Oluştur'a tıklayın.") | |
| # Yeni yükleme geldiğinde önceki tahminleri sıfırla | |
| encrypted_output = None | |
| fhe_prediction_ready = False | |
| simulate_prediction = [] | |
| df = pd.read_excel(file.name, header=None).set_index(0).T.reset_index(drop=True) | |
| # Temizlik işlemleri | |
| df.columns = df.columns.str.strip() | |
| df = df.loc[:, ~df.columns.duplicated()] | |
| df.rename(columns={"Desc": "Periyot"}, inplace=True) | |
| if "Periyot" in df.columns: | |
| df["Periyot"] = df["Periyot"].astype(str).str.replace(r"\s+", " ", regex=True).str.strip() | |
| enriched = compute_ratios(df) | |
| X_input = enriched[COLS].dropna().head(1) | |
| print(" Şifreleme öncesi shape:", X_input.shape) | |
| scaled = scaler_sel.transform(X_input) | |
| # Her satırı ayrı ayrı şifrele | |
| encrypted_list = [] | |
| for row in scaled: | |
| row = row.reshape(1, -1) | |
| encrypted = client.quantize_encrypt_serialize(row) | |
| encrypted_list.append(encrypted) | |
| encrypted_input = encrypted_list | |
| return f"{len(encrypted_input)} adet satır şifrelendi." | |
| def run_fhe(): | |
| global server, encrypted_output, fhe_prediction_ready | |
| if client is None: | |
| raise gr.Error("Lütfen önce 'Anahtar Oluştur'a tıklayın.") | |
| if encrypted_input is None: | |
| raise gr.Error("Veri şifrelenmemiş.") | |
| server = FHEModelServer(path_dir=fhe_dir) | |
| server.load() | |
| eval_keys = client.get_serialized_evaluation_keys() | |
| encrypted_result = [] | |
| for enc in encrypted_input: | |
| result = server.run(enc, eval_keys) | |
| encrypted_result.append(result) | |
| encrypted_output = encrypted_result | |
| fhe_prediction_ready = True | |
| return "Gerçek tahmin tamamlandı." | |
| def run_simulate_direct(file): | |
| global simulate_prediction | |
| simulate_prediction = [] | |
| if file is None: | |
| raise gr.Error("Lütfen bir Excel dosyası yükleyin.") | |
| df = pd.read_excel(file.name, header=None).set_index(0).T.reset_index(drop=True) | |
| df.columns = df.columns.str.strip() | |
| df = df.loc[:, ~df.columns.duplicated()] | |
| df.rename(columns={"Desc": "Periyot"}, inplace=True) | |
| enriched = compute_ratios(df) | |
| X_input = enriched[COLS].dropna().head(1) | |
| if X_input.empty: | |
| raise gr.Error("Geçerli veri bulunamadı. Excel dosyasını kontrol edin.") | |
| scaled = scaler_sel.transform(X_input) | |
| y_pred = final_model.predict(scaled, fhe="simulate") | |
| label = encoder.inverse_transform([int(y_pred[0])])[0] | |
| simulate_prediction = [label] | |
| return "Simülasyon tahmini tamamlandı." | |
| def show_simulate_result(): | |
| if not simulate_prediction or not isinstance(simulate_prediction, list): | |
| raise gr.Error("Henüz simülasyon tahmini yapılmadı.") | |
| if not all(isinstance(label, str) for label in simulate_prediction): | |
| raise gr.Error("Geçerli bir tahmin sonucu bulunamadı.") | |
| return "\n".join(f"{i+1}. {label}" for i, label in enumerate(simulate_prediction)) | |
| def decrypt_result(): | |
| global fhe_prediction_ready, encrypted_output | |
| if not fhe_prediction_ready: | |
| raise gr.Error("Henüz gerçek tahmin tamamlanmadı. Lütfen önce 'Gerçek Tahmini Başlat' butonuna basın.") | |
| if encrypted_output is None or len(encrypted_output) == 0: | |
| raise gr.Error("Şifreli tahmin sonucu bulunamadı.") | |
| predictions = [] | |
| for i, enc in enumerate(encrypted_output): | |
| pred = client.deserialize_decrypt_dequantize(enc) | |
| raw = pred.flatten() | |
| print(f"\n🔍 [Tahmin {i+1}]") | |
| print(f"📈 Decrypted output (vektör?): {raw}") | |
| print(f"🎯 Sınıf listesi: {list(encoder.classes_)}") | |
| if len(raw) > 1: | |
| # Çok sınıflı olasılık çıktısı | |
| label_idx = int(np.argmax(raw)) | |
| print(f"🔢 argmax sonucu: {label_idx}") | |
| else: | |
| # Tek değer → doğrudan sınıf indexi olabilir | |
| label_idx = int(round(raw[0])) | |
| print(f"🔢 Yuvarlanmış değer: {raw[0]} → {label_idx}") | |
| if label_idx >= len(encoder.classes_): | |
| label = f"⚠️ Geçersiz sınıf indexi: {label_idx}" | |
| else: | |
| label = encoder.inverse_transform([label_idx])[0] | |
| predictions.append(label) | |
| return "\n".join(f"{i+1}. {label}" for i, label in enumerate(predictions)) | |
| # -------------------- Gradio UI -------------------- # | |
| def fhe_start_message(): | |
| return "Tahmin başlatıldı, lütfen bekleyin..." | |
| def sim_start_message(): | |
| return "Simülasyon başlatıldı, lütfen bekleyin..." | |
| # -------------------- Gradio UI -------------------- # | |
| with gr.Blocks(theme=gr.themes.Default(primary_hue="blue")) as demo: | |
| gr.Markdown("# Denetçi Görüşü Tahmin Uygulaması (FHE)") | |
| gr.Markdown("## 1. Anahtar Oluştur") | |
| key_btn = gr.Button("🔑 Anahtar Oluştur") | |
| key_out = gr.Textbox(label="Evaluation Key") | |
| key_btn.click(generate_keys, outputs=key_out) | |
| gr.Markdown("## 2. Excel Yükle") | |
| file_in = gr.File(file_types=[".xlsx"], label="Excel Dosyası") | |
| encrypt_btn = gr.Button("🔐 Veriyi Şifrele") | |
| enc_out = gr.Textbox(label="Şifreli Veri") | |
| encrypt_btn.click(encrypt_excel, inputs=file_in, outputs=enc_out) | |
| gr.Markdown("## 3. Tahmini Gerçekleştir") | |
| with gr.Row(): | |
| run_real_btn = gr.Button("🔐 Gerçek Tahmini Başlat (FHE)") | |
| run_sim_btn = gr.Button("🧪 Simülasyon Tahminini Başlat") | |
| status_real = gr.Textbox(label="Durum (Gerçek Tahmin)") | |
| status_sim = gr.Textbox(label="Durum (Simülasyon)") | |
| run_real_btn.click(fhe_start_message, outputs=status_real).then(run_fhe, outputs=status_real) | |
| run_sim_btn.click(sim_start_message, outputs=status_sim).then(run_simulate_direct, inputs=[file_in], outputs=status_sim) | |
| gr.Markdown("## 4. Sonucu Deşifre Et") | |
| with gr.Row(): | |
| decrypt_btn = gr.Button("🔓 Gerçek Tahmini Göster (FHE)") | |
| decrypt_sim_btn = gr.Button("🧪 Simülasyon Sonucunu Göster") | |
| result_real = gr.Textbox(label="Gerçek Tahmin Sonucu") | |
| result_sim = gr.Textbox(label="Simülasyon Tahmin Sonucu") | |
| decrypt_btn.click(decrypt_result, outputs=result_real) | |
| decrypt_sim_btn.click(show_simulate_result, outputs=result_sim) | |
| gr.Markdown("## 📂 Örnek Dosyalar") | |
| gr.Examples(examples=EXAMPLE_XLSX, inputs=file_in, label="Örnek Excel Seç", cache_examples=False) | |
| if __name__ == "__main__": | |
| print("✅ Gradio app is launching...") | |
| fhe_prediction_ready = False | |
| simulate_prediction = [] | |
| encrypted_output = None | |
| demo.launch() |