当今以互联网、移动终端等为代表的技术力量正深刻地影响着金融支付市场,信息化、网络化、无线终端等技术的应用,使金融机构特别是银行业的经营发生了天翻地覆的变化,传统的银行柜台和网点业务,正渐渐被电子化交易所替代,电子银行以其便利性和增值服务各方面的优势,已经成为银行业保持活力和竞争力的主要发展动力。
围绕电子渠道信息泄露、资金被盗、诈骗等威胁与日俱增,欺诈信息、木马病毒、仿制克隆卡等欺诈手段层出不穷,让各家银行头疼不已。
一、欺诈行为分类
1、身份欺诈,即利用虚假的身份信息向金融机构申请贷款。身份造假有以下几种类型:
(1)盗用或冒用他人身份信息,利用账户资金进行非法消费、转账或提现等操作。
(2)盗用银行卡,或者通过复制银行卡,提取银行卡内资金。
(3)虚假注册,利用虚假注册的非本人账户进行骗贷或洗钱。
(4)电信诈骗,即通过网络、电话等诈骗方式,诱使客户主动将资金转移到欺诈分子账户。
2、信息隐瞒或造假,即刻意隐藏不良信息。
3、隐形的欺诈意图,正常信贷需求的人可能出现未能正确评估自身还款能力或丧失还款意愿的情况。
4、商户欺诈,商户与借款人形成套现、套利的勾结关系,骗取金融机构对于特定消费场景的补贴等。
二、金融反欺诈模型
金融反欺诈模型是通过数据采集手段,对风险行为或可疑行为监测与分析,根据不同风险事件或可疑行为的风险计量标准和规则模型,分别实施预警或干预等措施,从而有效减少金融欺诈的发生。一套完整的流程化的规则模型,系统有几个必备的要素:规则库、规则标的、规则评价、风险计量。
1、规则库模型最基本、最核心的系统架构便是规则库,它是整个系统运作的核心机制,商业银行针对欺诈行为特点,提炼欺诈行为的关键和核心要素。
将这些要素整合并参数化、逻辑化、可定制化,当客户行为触发规则库中的某一条规则或多条规则时,系统根据触发的规则的风险程度大小,计算相应的风险分值,并根据风险分值大小采取不同的干预、事后核实等处理手段。
要实施一套反欺诈系统,最重要的一项工作即是在充分搜集、获取渠道欺诈行为特点的基础上,进行风险规则模型库的建立,也就是说,风险规则模型即是对客户欺诈行为的模拟,与实际欺诈行为模拟的越相近,就越能充分发挥系统本身的作用。
2、规则标的模型的本质是客户行为达到启动模型暴露风险的条件,这里的启动条件要素,即是模型要涉及的规则标的,它是指通过模型工具捕捉到的客户行为要素,要素包含在银行系统所记录的客户行为日志中。
规则标的要素,涵盖了模型对欺诈行为精度、准确度和说服力的标准和要求。一般规则要素的多少,决定了一条规则的运作和复杂程度。一个成熟的规则模型,应该实现规则标的的任意搭配和调试,以适应复杂程度不断更新和变化的欺诈行为。
目前最广泛的规则标的要素主要有以下几个方面:
1、客户基本属性(包含客户基本信息,如家庭、职业、住址、资产情况等)
2、交易账户属性(包含登入、交易使用账户情况)
3、交易时间、地点、金额、交易频率、使用终端标识
4、交易收付对象
5、异常行为
3、模型评价评价一个模型的优劣,要看投入使用和运营的成果,对真正欺诈行为的暴露的准确性和完整性。衡量欺诈行为暴露的准确性和完整性指针有规则命中率、规则误报率及欺诈客户命中率。
4、风险计量模型建立风险评分机制对违反规则的客户行为进行风险评估。每个规则或组合规则(场景)都有一个规则风险分,当一个交易触发了多个规则报警,这个交易最终有一个0-100之间的交易风险分。模型通过风险分值的大小(0-100)来衡量客户可疑行为的风险程度,风险分值大小则由客户交易行为所触发的规则参数阀值来衡量和计算。一套反欺诈系统成功与否,在于是否能准确的暴露风险,即存在欺诈行为时,系统能准确的捕捉并预警,并根据风险程度大小进行干预或展现。
三、代码实现
1、导入数据,并查看数据信息
# 导入数据文件
df = pd.read_csv('F:\Python\data\LoanStats_2016Q3.csv', skiprows=1, low_memory=False)
df.info() # 查看文件属性
2、对数据进行预处理,将相关度不大的属性列删除
# drop id and member_id
df.drop('id',1,inplace=True)
df.drop('member_id',1,inplace=True)
# drop nan rows
df.dropna(axis=0,how='all',inplace=True)
df.info()
# emp_title is too many to ignore
df.drop('emp_title',1,inplace=True)
3、查看数据类别,将缺失值较大的属性列删除
# drop hige missing_pct
df.drop('desc',1,inplace=True)
df.drop('verification_status_joint',1,inplace=True)
# drop unnecessary object
df.drop('term',1,inplace=True)
df.drop('issue_d',1,inplace=True)
df.drop('purpose',1,inplace=True)
df.drop('title',1,inplace=True)
df.drop('zip_code',1,inplace=True)
df.drop('addr_state',1,inplace=True)
df.drop('earliest_cr_line',1,inplace=True)
df.drop('revol_util',1,inplace=True)
# drop after loan
df.drop(['out_prncp','out_prncp_inv','total_pymnt','total_pymnt_inv','total_rec_prncp', 'grade', 'sub_grade'] ,1, inplace=True)
df.drop(['total_rec_int','total_rec_late_fee','recoveries','collection_recovery_fee','collection_recovery_fee'],1, inplace=True)
df.drop(['last_pymnt_d','last_pymnt_amnt','next_pymnt_d','last_credit_pull_d'],1, inplace=True)
df.drop(['policy_code'],1, inplace=True)
4.整理数据列,关注loan_status属性列,并计算与该属性列相关系数,相关系数高的可以删除
# focus on loan_status
df.loan_status.value_counts()
# Current and Fully Paid regard as excellent 1, late regard as bad loan 0, others regard ass nan
df.loan_status.replace('Current',int(1),inplace=True)
df.loan_status.replace('Fully Paid',int(1),inplace=True)
df.loan_status.replace('Charged Off',np.nan,inplace=True)
df.loan_status.replace('In Grace Period',np.nan,inplace=True)
df.loan_status.replace('Default',np.nan,inplace=True)
df.loan_status.replace('Late (31-120 days)',int(0),inplace=True)
df.loan_status.replace('Late (16-30 days)',int(0),inplace=True)
# find highly corr Data
cor = df.corr()
cor.loc[:,:] = np.tril(cor,k=-1)
cor = cor.stack()
cor[abs(cor) > 0.5]
# drop the columns highly correlated with loan_status
df.drop(['funded_amnt','funded_amnt_inv','installment'],1,inplace=True)
5.对已处理好的数据进行建模训练,测试集为0.2
Y = df.loan_status
df.drop('loan_status',1,inplace=True)
X = df
# train_data and test_data
x_train, x_test, y_train, y_test = train_test_split(X,Y,test_size=0.2,random_state=1)
6.使用GBRT对数据进行建模训练
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn import ensemble
from sklearn.preprocessing import OneHotEncoder
param_grid = {'learning_rate': [0.1],
'max_depth': [2],
'min_samples_split': [50,100],
'n_estimators': [100,200]
}
est = GridSearchCV(ensemble.GradientBoostingRegressor(),
param_grid, n_jobs=4, refit=True)
est.fit(x_train, y_train)
best_params = est.best_params_
print(best_params)
%%time
est = ensemble.GradientBoostingRegressor(min_samples_split=50,n_estimators=300,
learning_rate=0.1,max_depth=1,random_state=0,
loss='ls').fit(x_train,y_train)
est.score(x_test,y_test)
7、测试模型,找出10个最重要属性
def computer_ks(data):
sorted_list = data.sort_values(['predict'],ascending=True)
total_bad = sorted_list['label'].sum(axis=None,skipna=None,level=None,numeric_only=None)/3
total_good = sorted_list.shape[0] - total_bad
max_ks = 0.0
good_count = 0.0
bad_count = 0.0
for index, row in sorted_list.iterrows():
if row['label'] == 3:
bad_count += 1.0
else:
good_count += 1.0
val = bad_count/total_bad - good_count/total_good
max_ks = max(max_ks,val)
return max_ks
feature_importance = est.feature_importances_
feature_importance = 100.0 * (feature_importance / feature_importance.max())
indices = np.argsort(feature_importance)[-10:]
plt.barh(np.arange(10),feature_importance[indices],color='green',alpha=0.4)
plt.yticks(np.arange(10+0.25),np.array(X.columns)[indices])
_ = plt.xlabel('Relative importance'), plt.title('Top Ten Important Variables')
8、最终结果