之前在某乎上看见有人说银行信贷审批的职业是越老越值钱,本文基于客户过往信贷数据角度进行机器学习训练,来探讨该职位未来是否还可能存在,欢迎吐槽我没有考虑信审人员懂产品、懂客户、懂市场,懂流程、懂风险,只是从机器学习角度来考虑,基于信贷数据进行用户信贷分类,使用Logistic算法和KNN算法模构建型。
一、相关理论
1.1 机器学习知识点:
- KNN:K近领算法,训练集中每一个样本都可以用其周围样本来代表。
- KNN三大要素:K值的选择、邻近距离度量、分类规则决策
- KNN代码公式:KNeighborsClassifier(n_neighbors=5,weights=’uniform’,algorithm=’kd_tree’,leaf_size=30,p=2,metric=’minkowski’)分别表示(邻近数目=默认5,样本权重=等权重,计算方式=kd树,叶子数量=默认30,样本距离=闵可夫斯基)
- Logistic:二分类算法
- LR代码:LogisticRegression()
1.2 环境配置
- python3.6
- 安装包:pandas、numpy、matplotlib、sklearn。
二、相关代码
2.1数据来源
Credit Approval Data Set(伟大的UCI机器学习数据库,顺带了解下常用的数据来源网站?)
2.2信息描述
从信息描述来看属性有分类、整数、实数,还有缺失值。总共包含690行数据,15列特征.
2.3 数据获取及划分
### 加载数据并对数据进行预处理
# 1. 加载数据
path = "datas/crx.data"
names = ['A1','A2','A3','A4','A5','A6','A7','A8',
'A9','A10','A11','A12','A13','A14','A15','A16']
df = pd.read_csv(path, header=None, names=names)
print ("数据条数:", len(df))
# 2. 异常数据过滤
df = df.replace("?", np.nan).dropna(how='any')
print ("过滤后数据条数:", len(df))
df.head(5)
# 1. 加载数据
path = "datas/crx.data"
names = ['A1','A2','A3','A4','A5','A6','A7','A8',
'A9','A10','A11','A12','A13','A14','A15','A16']
df = pd.read_csv(path, header=None, names=names)
print ("数据条数:", len(df))
# 2. 异常数据过滤
df = df.replace("?", np.nan).dropna(how='any')
print ("过滤后数据条数:", len(df))
df.head(5)
一共16列,前15列是特征,哭晕,只有4列是数值型数据, 其余全部需要进行特征工程。
2.4 特征工程
离散特征处理:
one-hot_encoding:将类别数据编码成为对应的数值表示并扩维,如['A','B','C']转换成[[1,0,0],[0,1,0],[0,0,1]],函数parse()
(LabelEncoder(另外一种类别数据编码顺带了解下?))
# 自定义的一个哑编码实现方式:将v变量转换成为一个向量/list集合的形式
def parse(v, l):
# v是一个字符串,需要进行转换的数据
# l是一个类别信息,其中v是其中的一个值
return [1 if i == v else 0 for i in l]
def parseRecord(record):
result = []
## 格式化数据,将离线数据转换为连续数据
a1 = record['A1']
for i in parse(a1, ('a', 'b')):
result.append(i)
result.append(float(record['A2']))
result.append(float(record['A3']))
# 将A4的信息转换为哑编码的形式; 对于DataFrame中,原来一列的数据现在需要四列来进行表示
a4 = record['A4']
for i in parse(a4, ('u', 'y', 'l', 't')):
result.append(i)
a5 = record['A5']
for i in parse(a5, ('g', 'p', 'gg')):
result.append(i)
a6 = record['A6']
for i in parse(a6, ('c', 'd', 'cc', 'i', 'j', 'k', 'm', 'r', 'q', 'w', 'x', 'e', 'aa', 'ff')):
result.append(i)
a7 = record['A7']
for i in parse(a7, ('v', 'h', 'bb', 'j', 'n', 'z', 'dd', 'ff', 'o')):
result.append(i)
result.append(float(record['A8']))
a9 = record['A9']
for i in parse(a9, ('t', 'f')):
result.append(i)
a10 = record['A10']
for i in parse(a10, ('t', 'f')):
result.append(i)
result.append(float(record['A11']))
a12 = record['A12']
for i in parse(a12, ('t', 'f')):
result.append(i)
a13 = record['A13']
for i in parse(a13, ('g', 'p', 's')):
result.append(i)
result.append(float(record['A14']))
result.append(float(record['A15']))
a16 = record['A16']
if a16 == '+':
result.append(1)
else:
result.append(0)
return result
def parse(v, l):
# v是一个字符串,需要进行转换的数据
# l是一个类别信息,其中v是其中的一个值
return [1 if i == v else 0 for i in l]
def parseRecord(record):
result = []
## 格式化数据,将离线数据转换为连续数据
a1 = record['A1']
for i in parse(a1, ('a', 'b')):
result.append(i)
result.append(float(record['A2']))
result.append(float(record['A3']))
# 将A4的信息转换为哑编码的形式; 对于DataFrame中,原来一列的数据现在需要四列来进行表示
a4 = record['A4']
for i in parse(a4, ('u', 'y', 'l', 't')):
result.append(i)
a5 = record['A5']
for i in parse(a5, ('g', 'p', 'gg')):
result.append(i)
a6 = record['A6']
for i in parse(a6, ('c', 'd', 'cc', 'i', 'j', 'k', 'm', 'r', 'q', 'w', 'x', 'e', 'aa', 'ff')):
result.append(i)
a7 = record['A7']
for i in parse(a7, ('v', 'h', 'bb', 'j', 'n', 'z', 'dd', 'ff', 'o')):
result.append(i)
result.append(float(record['A8']))
a9 = record['A9']
for i in parse(a9, ('t', 'f')):
result.append(i)
a10 = record['A10']
for i in parse(a10, ('t', 'f')):
result.append(i)
result.append(float(record['A11']))
a12 = record['A12']
for i in parse(a12, ('t', 'f')):
result.append(i)
a13 = record['A13']
for i in parse(a13, ('g', 'p', 's')):
result.append(i)
result.append(float(record['A14']))
result.append(float(record['A15']))
a16 = record['A16']
if a16 == '+':
result.append(1)
else:
result.append(0)
return result
将parse()函数应用到A1-A16中类别数据,看一下处理后的数据:
没错,从16列变成48列了,不知道为啥。了解下one_hot俗称亚编码的工作原理?
2.5 建立模型
先建立logistic模型,python中建模就是几行代码,顺带看一下预测结果,使用score也就是准确率来表示的。
KNN算法建立模型
2.6 数据可视化
x_len = range(len(X_test))
plt.figure(figsize=(14,7), facecolor='w')
plt.ylim(-0.1,1.1)
plt.plot(x_len, Y_test, 'bo',markersize = 6, zorder=3, label=u'真实值')
plt.plot(x_len, lr_y_predict, 'ro', markersize = 10, zorder=2, label=u'Logis算法预测值,$R^2$=%.3f' % lr.score(X_test, Y_test))
plt.plot(x_len, knn_y_predict, 'yo', markersize = 16, zorder=1, label=u'KNN算法预测值,$R^2$=%.3f' % knn.score(X_test, Y_test))
plt.legend(loc = 'center right')
plt.xlabel(u'数据编号', fontsize=18)
plt.ylabel(u'是否审批(0表示通过,1表示通过)', fontsize=18)
plt.title(u'Logistic回归算法和KNN算法对数据进行分类比较', fontsize=20)
plt.show()
2.7 总结分析
关键的部分在与特征工程的提取。提起特征工程又是一个很大的话题了。持续学习中。关于开头提出的问题,信贷审批人员在未来会不会被取代,用历史数据加KNN算法训练的模型效果来看,都能达到100%预测准确,虽然过拟合了,但我相信通过迭代,预测的准确性会在一个合理的范围内。这让我有理由相信计算机在未来回取代信审人员的部分工作。