『壹』 如何在python中實現數據的最優分箱
Monotonic Binning with Python
Monotonic binning is a data preparation technique widely used in scorecard development and is usually implemented with SAS. Below is an attempt to do the monotonic binning with python.
Python Code:
# import packages
import pandas as pd
import numpy as np
import scipy.stats.stats as stats
# import data
data = pd.read_csv("/home/liuwensui/Documents/data/accepts.csv", sep = ","念顫滾, header = 0)
# define a binning function
def mono_bin(Y, X, n = 20):
# fill missings with median
X2 = X.fillna(np.median(X))
r = 0
while np.abs(r) < 1:
d1 = pd.DataFrame({"X": X2, "Y": Y, "Bucket": pd.qcut(X2, n)})
d2 = d1.groupby('Bucket', as_index = True)
r, p = stats.spearmanr(d2.mean().X, d2.mean().Y)
n = n - 1
d3 = pd.DataFrame(d2.min().X, columns = ['min_' + X.name])
d3['max_' + X.name] = d2.max().X
d3[Y.name] = d2.sum().Y
d3['total'] = d2.count().Y
d3[Y.name + '仔余_rate'] = d2.mean().Y
d4 = (d3.sort_index(by = '洞銷min_' + X.name)).reset_index(drop = True)
print "=" * 60
print d4
mono_bin(data.bad, data.ltv)
mono_bin(data.bad, data.bureau_score)
mono_bin(data.bad, data.age_oldest_tr)
mono_bin(data.bad, data.tot_tr)
mono_bin(data.bad, data.tot_income)
Output:
============================================================
min_ltv max_ltv bad total bad_rate
0 0 83 88 884 0.099548
1 84 92 137 905 0.151381
2 93 98 175 851 0.205640
3 99 102 173 814 0.212531
4 103 108 194 821 0.236297
5 109 116 194 769 0.252276
6 117 176 235 793 0.296343
============================================================
min_bureau_score max_bureau_score bad total bad_rate
0 443 630 325 747 0.435074
1 631 655 242 721 0.335645
2 656 676 173 721 0.239945
3 677 698 245 1059 0.231350
4 699 709 64 427 0.149883
5 710 732 73 712 0.102528
6 733 763 53 731 0.072503
7 764 848 21 719 0.029207
============================================================
min_age_oldest_tr max_age_oldest_tr bad total bad_rate
0 1 59 319 987 0.323202
1 60 108 235 975 0.26
2 109 142 282 1199 0.235196
3 143 171 142 730 0.194521
4 172 250 125 976 0.128074
5 251 588 93 970 0.095876
============================================================
min_tot_tr max_tot_tr bad total bad_rate
0 0 8 378 1351 0.279793
1 9 13 247 1025 0.240976
2 14 18 240 1185 0.202532
3 19 25 165 1126 0.146536
4 26 77 166 1150 0.144348
============================================================
min_tot_income max_tot_income bad total bad_rate
0 0.00 2000.00 323 1217 0.265407
1 2002.00 2916.67 259 1153 0.224631
2 2919.00 4000.00 226 1150 0.196522
3 4001.00 5833.33 231 1186 0.194772
4 5833.34 8147166.66 157 1131 0.138815
『貳』 特徵穩定性
part1:特徵穩定性
特徵穩定性,就磨納是關注該特徵的取值隨著瞎運沒時間的推移會不會發生大的波動,
對特徵穩定性的關注,一定要在建模之前完成,從一開始就避免將那些本身不太穩定的特徵選入模型。一旦發現有特徵穩定性不滿足要求,則需要對其進行剔除後重新建模,避免不必要的重復性勞動。
通常採用PSI(PopulationStability Index,群體穩定性指數)指標評估特徵穩定性。
part2:常用方法:
PSI反映了驗證樣本在各分數段的分布與建模樣本分布的穩定性,穩定性是有參照的,因此需要有兩個分布—— 實際分布 (actual)和 預期分布 (expected)。其中,在建模時通常以訓練樣本(In the Sample, INS)作為預期分布,而驗證樣本通常作為實際分布
<pre>PSI = sum((實際佔比-預期佔比)* ln(實際佔比/預期佔比))</pre>
比如訓練一個logistic回歸模型,預測時候會有個概率輸出 p
測試集上的輸出設定為p1,將它從小到大排序後10等分,如:
<pre>0.0-0.1
0.1-0.2
0.2-0.3... </pre>
現在用這個模型去對新的樣本進行預測,預測結果叫p2,按p1的區間也劃分為10等分。
<pre>實際佔比 = p2上在各區間的用戶佔比
預期佔比 = p1上各區間的用戶佔比</pre>
意義就是如果模型更穩定,那麼p1和p2上各區間的用戶應該是相近的,佔比不會變動很大,也就是預測出來的概率不會差距很大。
PS:除了按概率值大小等距十等分外,還可以對概率排序後按數量十等分,兩種方法計算得到的psi可能有所區別但數值相差不大
一般認為:
<pre>PSI<0.1 :模型穩定性很高
0.1-0.25:一般,繼續監控後續變化
PSI>0.25: 模型穩定性差,建議重做</pre>
step1: 將變數預期分布(excepted)進行分箱(binning)離散化,統計各個分箱里的樣本佔比 注意: 1. 分箱可以是等頻、等距或其他方式,分箱方式不同,將導致計算結果略微有差異; 2. 對於連續型變數(特徵變數、模型分數等),分箱數需要設置合理,一般設為10或20;對於離散型變數,如果分箱太多可以提前考慮合並小分箱;分箱數太多,可能會導致每個分箱內的樣本量太少而失去統計意義;分箱數太少,又會導致計算結果精度降低
step2: 按相同分箱區間,對實際分布(actual)統計各分箱內的樣本佔比
step3: 計 算各分箱內的A - E和Ln(A / E),
計算index = (實際佔比 - 預期佔比)* ln(實際佔比 / 預期佔比)
step4: 將各分箱的index進行求和,即得到最終的PSI
[圖片上傳失敗...(image-fc79b3-1637314904243)]
相對熵(relative entropy),又被稱為Kullback-Leibler散度(Kullback-Leibler divergence)或信息散度(information divergence),是兩個概率分布間差異的非對稱性度量。
劃重點——KL散度不滿足對稱性。
相對熵可以衡量兩個隨機分布之間的"距離「。
相對熵和PSI的概念非常相近:當兩個隨機分布完全一樣時,PSI = 0;反之,差異越大,PSI越大。
相對熵的公式:
在信息理論中,相對熵等價於兩個概率分布的悄畢信息熵(Shannon entropy)的差值:
[圖片上傳失敗...(image-7a9318-1637314904243)]
其中,P(x)表示數據的真實分布,而Q(x)表示數據的觀察分布。上式可以理解為:
[圖片上傳失敗...(image-57d277-1637314904243)]
KL散度具有非對稱性
相對熵與PSI之間的關系:
[圖片上傳失敗...(image-76a049-1637314904243)]
將PSI計算公式變形後可以分解為2項:
因此,PSI本質上是實際分布(A)與預期分布(E)的KL散度的一個對稱化操作。其雙向計算相對熵,並把兩部分相對熵相加,從而更為全面地描述兩個分布的差異。
在業務上,一般以訓練集(INS)的樣本分布作為預期分布,進而跨時間窗按月/周來計算PSI,得到Monthly PSI Report,進而剔除不穩定的變數。同理,在模型上線部署後,也將通過PSI曲線報表來觀察模型的穩定性。
參考:
(17條消息) PSI群體穩定指數-Python實現_u010654299的博客-CSDN博客_psi python
https://zhuanlan.hu.com/p/79682292
『叄』 12個銷售價格記錄如下怎麼寫python
1、假設12個銷售價格記錄組已經排序如下:5, 10, 11, 13, 15, 35, 50, 55, 72, 92, 204, 215 使用如下每種方法將它們劃分成四個箱。等頻(等深)劃分時,15在第幾個宴渣箱子內? (2 )
等寬劃分晌旁悄:將整個區域啟畢劃分成N個相同大小的間隔
等頻劃分:將整個區域劃分為N個間隔,各個間隔中包含的樣本數目大致相同
舉個例子: 假定由年齡組合:{0,4,12,16,18,24,26,28}
按照等寬的話,子區間寬度相同,取寬度為10,則:{0,4},{12,16,16,18},{24,26,28}
等頻的話,子集元素個數相同,則 {0,4,12},{16,16,18},{24,26,28} 回歸到這個題:分成四個箱子,一個箱子裝3個,{5,10,11},{13,15,35}{...}{...}很明顯在第二個箱子中
『肆』 python用卡方檢驗,自動分箱,結果是否可靠有待驗證
def calc_chiSquare(sampleSet, feature, target):
'''
計算某個特徵每種屬性值的卡方統計量
params:
sampleSet: 樣本集
feature: 目標特徵
target: 目標Y值 (0或1) Y值為二分類變數
return:
卡方統計量dataframe
feature: 特徵名稱
act_target_cnt: 實際壞樣本數
expected_target_cnt:期望壞樣本數
chi_square:卡方統計量
'''
# 計算樣本期望頻率
target_cnt = sampleSet[target].sum()
sample_cnt = len(sampleSet[target])
expected_ratio = target_cnt * 1.0/sample_cnt
# 對變數按屬性值從大到小排序
df = sampleSet[[feature, target]]
col_value = list(set(df[feature]))
# 計算每一個屬性值對應的卡方統計量等信息
chi_list = []; target_list = []; expected_target_list = []
for value in col_value:
df_target_cnt = df.loc[df[feature] == value, target].sum()
df_cnt = len(df.loc[df[feature] == value, target])
expected_target_cnt = df_cnt * expected_ratio
chi_square = (df_target_cnt - expected_target_cnt)**2 / expected_target_cnt
chi_list.append(chi_square)
target_list.append(df_target_cnt)
expected_target_list.append(expected_target_cnt)
# 結果輸出到dataframe, 對應欄位為特徵屬性值, 卡方統計量, 實際壞樣本量塌拆, 期望壞樣本量
chi_stats = pd.DataFrame({feature:col_value, 'chi_square':chi_list,
'act_target_cnt':target_list, 'expected_target_cnt':expected_target_list})
return chi_stats[[feature, 'act_target_cnt', 'expected_target_cnt', 'chi_square']]
def chiMerge_maxInterval(chi_stats, feature, maxInterval=5):
'''
卡方分箱合並--最大區間限製法
params:
chi_stats: 卡方統計量dataframe
feature: 目標特徵
maxInterval:最大分箱數閾值
return:
卡方合並結果dataframe, 特徵分割敏老split_list
'''
橋衫升 group_cnt = len(chi_stats)
split_list = [chi_stats[feature].min()]
# 如果變數區間超過最大分箱限制,則根據合並原則進行合並
while(group_cnt > maxInterval):
min_index = chi_stats[chi_stats['chi_square']==chi_stats['chi_square'].min()].index.tolist()[0]
# 如果分箱區間在最前,則向下合並
if min_index == 0:
chi_stats = merge_chiSquare(chi_stats, min_index+1, min_index)
# 如果分箱區間在最後,則向上合並
elif min_index == group_cnt-1:
chi_stats = merge_chiSquare(chi_stats, min_index-1, min_index)
# 如果分箱區間在中間,則判斷與其相鄰的最小卡方的區間,然後進行合並
else:
if chi_stats.loc[min_index-1, 'chi_square'] > chi_stats.loc[min_index+1, 'chi_square']:
chi_stats = merge_chiSquare(chi_stats, min_index, min_index+1)
else:
chi_stats = merge_chiSquare(chi_stats, min_index-1, min_index)
group_cnt = len(chi_stats)
chiMerge_result = chi_stats
split_list.extend(chiMerge_result[feature].tolist())
return chiMerge_result, split_list
def chiMerge_minChiSquare(chi_stats, feature, dfree=4, cf=0.1, maxInterval=5):
'''
卡方分箱合並--卡方閾值法
params:
chi_stats: 卡方統計量dataframe
feature: 目標特徵
maxInterval: 最大分箱數閾值, default 5
dfree: 自由度, 最大分箱數-1, default 4
cf: 顯著性水平, default 10%
return:
卡方合並結果dataframe, 特徵分割split_list
'''
threshold = get_chiSquare_distuibution(dfree, cf)
min_chiSquare = chi_stats['chi_square'].min()
group_cnt = len(chi_stats)
split_list = [chi_stats[feature].min()]
# 如果變數區間的最小卡方值小於閾值,則繼續合並直到最小值大於等於閾值
while(min_chiSquare < threshold and group_cnt > maxInterval):
min_index = chi_stats[chi_stats['chi_square']==chi_stats['chi_square'].min()].index.tolist()[0]
# 如果分箱區間在最前,則向下合並
if min_index == 0:
chi_stats = merge_chiSquare(chi_stats, min_index+1, min_index)
# 如果分箱區間在最後,則向上合並
elif min_index == group_cnt-1:
chi_stats = merge_chiSquare(chi_stats, min_index-1, min_index)
# 如果分箱區間在中間,則判斷與其相鄰的最小卡方的區間,然後進行合並
else:
if chi_stats.loc[min_index-1, 'chi_square'] > chi_stats.loc[min_index+1, 'chi_square']:
chi_stats = merge_chiSquare(chi_stats, min_index, min_index+1)
else:
chi_stats = merge_chiSquare(chi_stats, min_index-1, min_index)
min_chiSquare = chi_stats['chi_square'].min()
group_cnt = len(chi_stats)
chiMerge_result = chi_stats
split_list.extend(chiMerge_result[feature].tolist())
return chiMerge_result, split_list
def get_chiSquare_distuibution(dfree=4, cf=0.1):
'''
根據自由度和置信度得到卡方分布和閾值
params:
dfree: 自由度, 最大分箱數-1, default 4
cf: 顯著性水平, default 10%
return:
卡方閾值
'''
percents = [0.95, 0.90, 0.5, 0.1, 0.05, 0.025, 0.01, 0.005]
df = pd.DataFrame(np.array([chi2.isf(percents, df=i) for i in range(1, 30)]))
df.columns = percents
df.index = df.index+1
# 顯示小數點後面數字
pd.set_option('precision', 3)
return df.loc[dfree, cf]
def merge_chiSquare(chi_result, index, mergeIndex, a = 'expected_target_cnt',
b = 'act_target_cnt', c = 'chi_square'):
'''
params:
chi_result: 待合並卡方數據集
index: 合並後的序列號
mergeIndex: 需合並的區間序號
a, b, c: 指定合並欄位
return:
分箱合並後的卡方dataframe
'''
chi_result.loc[mergeIndex, a] = chi_result.loc[mergeIndex, a] + chi_result.loc[index, a]
chi_result.loc[mergeIndex, b] = chi_result.loc[mergeIndex, b] + chi_result.loc[index, b]
chi_result.loc[mergeIndex, c] = (chi_result.loc[mergeIndex, b] - chi_result.loc[mergeIndex, a])**2 /chi_result.loc[mergeIndex, a]
chi_result = chi_result.drop([index])
chi_result = chi_result.reset_index(drop=True)
return chi_result
for col in bin_col:
chi_stats = calc_chiSquare(exp_f_data_label_dr, col, 'label')
chiMerge_result, split_list = chiMerge_maxInterval(chi_stats, col, maxInterval=5)
print(col, 'feature maybe split like this:', split_list)
『伍』 如何在python中實現數據的最優分箱
其實任何開發工弊和核具只是把演算法變成代碼,根本上是你要想清楚如何棚吵分箱。
你所需要的最優分箱應該是從所有分箱的可能中找到具有最小方差的方案,分箱的數量通常按照等頻或者等寬劃分,還是要預設或者通過最優化計算得到。
然後,對應每種分箱方法計算其方差,你找到找到相應的函數,把這租掘個方差的計算方法實現代碼。
對Python完全不熟,幫不了你。你可以搜一些代碼,自己調試和驗證一下
『陸』 python 對toad裡面的toad.metrics.KS_bucket函數改寫成自定義分段
toad函數裡面有個 類似於woe 統計各段的好壞,好壞比, 累計好壞比,KS的一個數為
toad.metrics.KS_bucket
此函數中有兩個參數,可以 是等頻分,也可以 是等距分箱滾雹,但此分箱均是以分數的最大培帆大最小值 為基礎劃分的。
我想把整成0~1區間的,中槐所以對原函數進行了修改。
『柒』 python最優分箱中woe計算(求大聖)
>>> list =[None,None,None,None,"a","b","c",None,"d",12,None,2,4,5,4]>>> list = list[4:]>>> len(list)11>>州虛> list['a', 'b', 'c', None, 'd', 12, None, 2, 4, 5, 4]>>>#如果你的冊拍燃list 格式是相同的 比如前面4個都是None,這賀扒個格式是固定的,那麼切片很容易解決
『捌』 利用分箱光滑技術可以進行什麼
給定一個數據集waitakere.txt,該數據集中含有大量的噪音數據。具體操作要求:1)該數據集的偶數位均為噪音數據,判斷偶數位是否為0,若為0,利用1替換。2)對轉換後的數據集進行排序,利用分閉茄箱技術來光滑數據。假設有10個桶,實現「用箱均值光滑」、 「用箱中位數光滑」、「用箱邊界光滑」三種技術。
waitakere.txt:
這只是一部分數據,只是為了示例噪音數據
1 0 3 2 0 3
4 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 7 0
0 8 9 0 9 0
0 6 0 5 0 3
6 0 7 0 1 0
......
登錄後侍態局復制
解題思路:首先讀入數據到列表裡,然後對數據進行排序,將數據劃分到10個箱中。對於箱均值光滑,箱中每一個值都被替換為箱中的均值。對於箱中位數光滑,箱中每一個值都被替換為箱中的中位數。對於箱邊界光滑,箱中每一個值都被替換為最近的邊界值。
以下為python代碼實現老讓部分:
import numpy as np
def binning(filename,box_num):
my_list=[]
my_list1=[]
noise_data = open(filename)
for line in noise_data.readlines():
dataline=line.strip()
my_list.append(dataline)
for i in range(0,len(my_list)):
my_list[i]=int(my_list[i])
if (i+1) % 2==0 and my_list[i]==0:
my_list[i]=1
my_list1=sorted(my_list)
#print my_list1
box_list=[]
len_box=int(np.ceil(len(my_list1)/float(box_num)))
for i in range(0,10):
each_box=my_list1[i*len_box:(i+1)*len_box]
box_list.append(each_box)
return box_list
def box_mean_smooth(box_list):
for i in range(0,len(box_list)):
box_avg=int(np.average(box_list[i]))
for j in range(0,len(box_list[i])):
box_list[i][j]=box_avg
return box_list
def box_mid_smooth(box_list):
for i in range(0,len(box_list)):
box_mid=int(np.median(box_list[i]))
for j in range(0,len(box_list[i])):
box_list[i][j]=box_mid
return box_list
def box_boundary_smooth(box_list):
for i in range(0,len(box_list)):
left_bdy=box_list[i][0]
right_bdy=box_list[i][-1]
for j in range(0,len(box_list[i])):
if abs(box_list[i][j]-left_bdy)<abs(box_list[i][j]-right_bdy):
box_list[i][j]=left_bdy
else:
box_list[i][j]=right_bdy
return box_list
filename='waitakere.txt'
box_list=binning(filename,10)
print box_list
print box_mean_smooth(box_list)
print box_mid_smooth(box_list)
print box_boundary_smooth(box_list)
登錄後復制
下圖為實驗結果截圖:
由於數據較多,截圖只是一部分
python
數據
銀川旅遊景點攻略,這個地方驢友必去之一!良心推薦
精選推薦
廣告
python 等深分箱法(均值平滑技術、邊界值平滑技術)
1.3W閱讀·6評論·24點贊
2020年12月10日
數據挖掘概念與技術(第三版)課後答案——第三章
2.2W閱讀·201評論·119點贊
2020年7月3日
python S-G (Savitzky–Golay filter) 平滑濾波和kalman濾波濾掉雜訊實現實例,有可視化結果
357閱讀·0評論·0點贊
2022年11月10日
R語言數據挖掘(2) 數據預處理
2292閱讀·0評論·1點贊
2017年10月10日
數據認知與數據預處理--數據預處理
348閱讀·0評論·0點贊
2022年6月23日
數據挖掘復習
815閱讀·0評論·0點贊
2021年12月20日
美人魚公主參加聚會裝扮美人魚游戲
精選推薦
廣告
python 數據、曲線平滑處理
9904閱讀·0評論·16點贊
2022年4月21日
數據挖掘如何分箱以及如何對每個箱子中的數據進行平滑處理
2.0W閱讀·2評論·38點贊
2019年6月24日
數據挖掘概念與技術(原書第三版)范明 孟小峰譯-----第三章課後習題答案
2.6W閱讀·13評論·21點贊
2017年5月21日
python 數據可視化 -- 真實數據的雜訊平滑處理
2779閱讀·0評論·2點贊
2019年2月11日
【6】python生成數據曲線平滑處理——(Savitzky-Golay 濾波器、convolve滑動平均濾波)方法介紹,推薦玩強化學習的小夥伴收藏
2612閱讀·2評論·3點贊
2021年8月12日
數據挖掘理論與演算法筆記
368閱讀·0評論·0點贊
2021年6月10日
《數據挖掘概念與技術》學習筆記-第三章
3957閱讀·0評論·6點贊
2020年2月14日
這個神奇的庫,可以將數據平滑化並找到異常點
135閱讀·0評論·0點贊
2022年6月9日
python數據平滑處理,numpy之數據平滑處理
3253閱讀·0評論·0點贊
2021年4月27日
python 數據平滑_數據平滑方法的原理和應用
1394閱讀·0評論·0點贊
2020年12月9日
python使曲線變得平滑_如何在Python中平滑數據?
3234閱讀·0評論·1點贊
2020年12月4日
numpy模塊的使用(二)
257閱讀·0評論·2點贊
2020年10月3日
去首頁
看看更多熱門內容
評論1
扣尼奇哇
贊
寫得好