计算模型稳定性评估指标 PSI
一、基本概念
PSI反映了验证样本在各分数段的分布与建模样本分布的稳定性,在建模中,我们常用来筛选特征变量、评估模型稳定性
稳定性是有参照的,因此需要有两个分布——实际分布(actual)和预期分布(expected),在建模时通常以训练样本(In the Sample, INS)作为预期分布,而验证样本通常作为实际分布。
把两个分布重叠放在一起,以下为相关解释:
训练数据中的标签列即y列 表示实际数据
训练数据用于模型训练 得到一个模型
用该模型进行数据预测 预测出来的y列即预期数据
将实际数据和预期数据进行同样的分段
每一段内分别计算数据分布 然后比较
用来反映模型的稳定性
将变量预期分布(excepted)进行分箱(binning)离散化
统计各个分箱里的样本占比
PSI 源码
https://gitee.com/pingfanrenbiji/population-stability-index-argo/blob/master/psi.py
import numpy as np
def calculate_psi(expected, actual, buckettype='bins', buckets=10, axis=0):
'''Calculate the PSI (population stability index) across all variables
Args:
expected: numpy matrix of original values
actual: numpy matrix of new values, same size as expected
buckettype: type of strategy for creating buckets, bins splits into even splits, quantiles splits into quantile buckets
buckets: number of quantiles to use in bucketing variables
axis: axis by which variables are defined, 0 for vertical, 1 for horizontal
Returns:
psi_values: ndarray of psi values for each variable
Author:
Matthew Burke
github.com/mwburke
worksofchart.com
'''
def psi(expected_array, actual_array, buckets):
'''Calculate the PSI for a single variable
Args:
expected_array: numpy array of original values
actual_array: numpy array of new values, same size as expected
buckets: number of percentile ranges to bucket the values into
Returns:
psi_value: calculated PSI value
'''
def scale_range (input, min, max):
input += -(np.min(input))
input /= np.max(input) / (max - min)
input += min
return input
breakpoints = np.arange(0, buckets + 1) / (buckets) * 100
if buckettype == 'bins':
breakpoints = scale_range(breakpoints, np.min(expected_array), np.max(expected_array))
elif buckettype == 'quantiles':
breakpoints = np.stack([np.percentile(expected_array, b) for b in breakpoints])
expected_percents = np.histogram(expected_array, breakpoints)[0] / len(expected_array)
actual_percents = np.histogram(actual_array, breakpoints)[0] / len(actual_array)
def sub_psi(e_perc, a_perc):
'''Calculate the actual PSI value from comparing the values.
Update the actual value to a very small number if equal to zero
'''
if a_perc == 0:
a_perc = 0.0001
if e_perc == 0:
e_perc = 0.0001
value = (e_perc - a_perc) * np.log(e_perc / a_perc)
return(value)
psi_value = np.sum(sub_psi(expected_percents[i], actual_percents[i]) for i in range(0, len(expected_percents)))
return(psi_value)
if len(expected.shape) == 1:
psi_values = np.empty(len(expected.shape))
else:
psi_values = np.empty(expected.shape[axis])
for i in range(0, len(psi_values)):
if len(psi_values) == 1:
psi_values = psi(expected, actual, buckets)
elif axis == 0:
psi_values[i] = psi(expected[:,i], actual[:,i], buckets)
elif axis == 1:
psi_values[i] = psi(expected[i,:], actual[i,:], buckets)
return(psi_values)
结合具体业务实现需求
经过上面的学习 咱们已经知道了PSI是个什么玩意了
而且还有了实现好的算法源码
该算法需要2方面的数据
一个是实际数据(训练数据)
实际数据即是训练数据集中的标签列
比如贷款数据样本
标签列为是否按时还款
另一个是预期数据(预测数据根据模型得到的预测结果)
预期样本是
根据训练出来的模型
对于即将要贷款的用户进行预测是否会还款
接下来就要结合自己公司的业务来得到这块数据调用算法就可以了
相关文章:
计算模型稳定性评估指标PSI
Github|population-stability-index
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)