路過了學校花店
荒野到海邊
有一種浪漫的愛
是浪費時間
徘徊到繁華世界
才發現你背影
平凡得特別
繞過了城外邊界
還是沒告別
愛錯過了太久
反而錯得完美無缺
幸福兜了一個圈
?????????????????????🎵 林宥嘉《兜圈》
import pandas as pd
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression# 示例數據
data = {'feature1': np.random.rand(1000),'feature2': np.random.rand(1000),'feature3': np.random.rand(1000),'target': np.random.randint(0, 2, 1000)
}
df = pd.DataFrame(data)# 自動選擇最佳分箱數量的函數
def find_best_bins(df, feature, target, max_bins=10):best_bins = 2best_score = -np.inffor bins in range(2, max_bins + 1):df['bin'] = pd.cut(df[feature], bins=bins, labels=False)model = LogisticRegression()# 使用分箱后的特征進行交叉驗證評分scores = cross_val_score(model, df[['bin']], df[target], scoring='roc_auc', cv=5)mean_score = scores.mean()if mean_score > best_score:best_score = mean_scorebest_bins = binsreturn best_bins# 計算 WoE 和 IV 的函數
def calculate_woe_iv(df, feature, target, bins):epsilon = 1e-6 # 平滑處理,避免除零df['bin'] = pd.cut(df[feature], bins=bins)# 計算每個箱的總數、正樣本數和負樣本數binned = df.groupby('bin')[target].agg(['count', 'sum'])binned.columns = ['total', 'positive']binned['negative'] = binned['total'] - binned['positive']# 計算每個箱或類別的正負樣本比例binned['positive_ratio'] = (binned['positive'] + epsilon) / (binned['positive'].sum() + epsilon)binned['negative_ratio'] = (binned['negative'] + epsilon) / (binned['negative'].sum() + epsilon)# 計算 WoE 和 IVbinned['woe'] = np.log(binned['positive_ratio'] / binned['negative_ratio'])binned['iv'] = (binned['positive_ratio'] - binned['negative_ratio']) * binned['woe']# 計算總 IViv = binned['iv'].sum()return iv# 對 DataFrame 中每個特征列進行分箱,并選擇最佳分箱數量
def binning_dataframe(df, target, max_bins=10):binned_df = df.copy()bin_info = {}iv_info = {}for feature in df.columns:if feature != target:best_bins = find_best_bins(df, feature, target, max_bins)bin_info[feature] = best_binsbinned_df[feature] = pd.cut(df[feature], bins=best_bins, labels=False)# 計算 IV 值iv = calculate_woe_iv(df, feature, target, best_bins)iv_info[feature] = ivreturn binned_df, bin_info, iv_info# 進行分箱并選擇最佳分箱數量
binned_df, bin_info, iv_info = binning_dataframe(df, 'target', max_bins=10)print("分箱信息:")
print(bin_info)
print("\nIV 信息:")
print(iv_info)
print("\n分箱后的 DataFrame:")
print(binned_df.head())