机器学习实验笔记-基于信用卡数据建立行为评分模型的机器学习方法
基于信用卡数据建立行为评分模型的机器学习方法
很久之前的一个答疑, 应该不会再影响评分了, 记录以供复习. 数据集与代码放在CSDN下载区域, 也可以留言索要.
https://download.csdn.net/download/lagoon_lala/87636214
目录
数据预处理
读取数据
数据概况
缺失值分析
缺失值填充
类别型变量处理
异常值处理
划分数据/标签
划分训练集测试集
数据标准化
归一化和标准化
标签不平衡
变量筛选
过滤式特征选择
包裹式特征选择
嵌入式特征选择
性能评估
模型选择
算法选择
最佳模型参数选择
法二: 使用手动划分的数据集选择
模型表现
使用最佳模型进行预测
作图展示模型表现
数据预处理
读取数据
我们使用pandas库读取数据文件, 可以看到其中包括目标变量共有262个变量, 148077个样本.
data = pd.read_csv('data/data_model.csv') print("读入数据的样本与变量个数:",data.shape)#(148077, 262) |
import pandas as pd data = pd.read_csv('data/data_model.csv') # print(data.shape)#(148077, 262) data |
总样本数量:148077 总变量数量:262 (148077, 262)
数据概况
本文用到的数据为银行真实业务场景下的脱敏数据,在这个数据集上进行数据处理及建模。其中包括261项脱敏的特征,以及是否是逾期的标签项,共148077条数据。
特征类型包含:
客户基本信息, 账户信息, 开卡, 总体交易行为, 分期行为, 取现行为, 还款行为, 消费行为.
缺失值分析
根据数据介绍,在数据样本中,变量的缺失值统一以特殊数值表示。特征变量缺失率表明某个特征缺失是否严重。缺失率高,说明这些特征缺失严重,可能会对预测模型带来干扰。一般来说,对于高维数据和普通模型,通过删除缺失率较高的特征,可以减少噪音特征对模型的干扰。
统计缺失率高的特征
missing_rate = pd.read_csv('data/missing_rate.csv', index_col=0) high_missing_features=missing_rate[missing_rate['missing_rate'] > 0.7] high_missing_features |
缺失率高的特征为
xaccount_phonechange |
最近一次号码变更距观察点时长 |
xaccount_addrchange |
最近一次地址变更距观察点时长 |
xaccount_empchange |
最近一次单位名称修改时长 |
xaccount_autopaytime |
持卡人首次关联自扣时长 |
tran_cyclenum_STMT3roi |
近三期账单循环交易笔数环比增长率 |
tran_cyclenum_STMT6roi |
近六期账单循环交易笔数环比增长率 |
tran_cyclenum_STMT12roi |
近十二期账单循环交易笔数环比增长率 |
由于存在信息的样本太少, 难以训练, 直接删除
(若不删除, 也可前4个特征的缺失原因为未修改, 缺失值可以定义为99999
后3个特征无缺失原因, 前n期账单交易金额为0, 可以定义为99999)
删除缺失率高的特征
data_cleaned = data.drop(high_missing_features.index, axis=1) data_cleaned |
得到的数据特征数已经减少:
148077 rows × 255 columns
法二 根据特征名删除
由变量说明表可得, 以下特征缺失率较高(缺失率 > 70%):
xaccount_phonechange
xaccount_addrchange
xaccount_empchange
xaccount_autopaytime
tran_cyclenum_STMT3roi
tran_cyclenum_STMT6roi
tran_cyclenum_STMT12roi
# 删除缺失率高的特征 high_missing_features=['xaccount_phonechange','xaccount_addrchange','xaccount_empchange','xaccount_autopaytime','tran_cyclenum_STMT3roi','tran_cyclenum_STMT6roi','tran_cyclenum_STMT12roi'] data_cleaned = data.drop(high_missing_features, axis=1) print("删除缺失率高的特征:",data_cleaned.shape) |
缺失值填充
其中, 一些缺失值的填充有意义, 无需修改, 如:
xaccount_credlimitnum |
额度调整次数 |
xaccount_credlimitrenum |
额度降低次数 |
各类占比的缺失值均因为金额为0, 原为-1, 改设为0
data_cleaned = data_cleaned.replace(-1, 0) |
可以看到其中为-1的值已设为0
对这些特征的缺失值进行填充为0:
TRAN_NOW_NUMMONRIO |
近一期月交易笔数环比增长率 |
||
TRAN_STMT3_NUMMONRIO |
近三期月均交易笔数环比增长率 |
||
TRAN_STMT6_NUMMONRIO |
近六期月均交易笔数环比增长率 |
||
TRAN_STMT12_NUMMONRIO |
近十二期月均交易笔数环比增长率 |
||
TRAN_NOW_AMTMONRIO |
近一期交易金额环比增长率 |
||
TRAN_STMT3_AMTMONRIO |
近三期月均交易金额环比增长率 |
||
TRAN_STMT6_AMTMONRIO |
近六期月均交易金额环比增长率 |
||
TRAN_STMT12_AMTMONRIO |
近十二期月均交易金额环比增长率 |
||
tran_num_STMT1roi |
近一期账单交易笔数环比增长率 |
||
tran_num_STMT3roi |
近三期账单交易笔数环比增长率 |
||
tran_num_STMT6roi |
近六期账单交易笔数环比增长率 |
||
tran_num_STMT12roi |
近十二期账单交易笔数环比增长率 |
||
tran_amt_STMT1roi |
近一期账单交易金额环比增长率 |
||
tran_amt_STMT3roi |
近三期账单交易金额环比增长率 |
||
tran_amt_STMT6roi |
近六期账单交易金额环比增长率 |
||
tran_amt_STMT12roi |
近十二期账单交易金额环比增长率 |
||
tran_mpamortize_num_STMT1roi |
近一期账单大额交易笔数环比增长率 |
||
tran_mpamortize_num_STMT3roi |
近三期账单大额交易笔数环比增长率 |
||
tran_mpamortize_num_STMT6roi |
近六期账单大额交易笔数环比增长率 |
||
tran_mpamortize_num_STMT12roi |
近十二期账单大额交易笔数环比增长率 |
||
bill_num_STMT1roi |
当月消费笔数环比增长率 |
||
bill_num_STMT3roi |
近三期月均消费 笔数环比增长率 |
||
bill_num_STMT6roi |
近六期月均消费 笔数环比增长率 |
||
bill_num_STMT12roi |
近十二期月均消费 笔数环比增长率 |
||
bill_amt_STMT1roi |
当月消费金额环比增长率 |
||
bill_amt_STMT3roi |
近三期月均消费金额环比增长率 |
||
bill_amt_STMT6roi |
近六期月均消费金额环比增长率 |
||
bill_amt_STMT12roi |
近十二期月均消费金额环比增长率 |
||
设为0(或利用随机森林等方法对缺失值进行预测).
features_resetNA=['TRAN_NOW_NUMMONRIO','TRAN_STMT3_NUMMONRIO','TRAN_STMT6_NUMMONRIO','TRAN_STMT12_NUMMONRIO','TRAN_NOW_AMTMONRIO','TRAN_STMT3_AMTMONRIO','TRAN_STMT6_AMTMONRIO','TRAN_STMT12_AMTMONRIO','tran_num_STMT1roi','tran_num_STMT3roi','tran_num_STMT6roi','tran_num_STMT12roi','tran_amt_STMT1roi','tran_amt_STMT3roi','tran_amt_STMT6roi','tran_amt_STMT12roi','tran_mpamortize_num_STMT1roi','tran_mpamortize_num_STMT3roi','tran_mpamortize_num_STMT6roi','tran_mpamortize_num_STMT12roi','bill_num_STMT1roi','bill_num_STMT3roi','bill_num_STMT6roi','bill_num_STMT12roi','bill_amt_STMT1roi','bill_amt_STMT3roi','bill_amt_STMT6roi','bill_amt_STMT12roi'] data_cleaned[features_resetNA] = data_cleaned[features_resetNA].replace(9999, 0) # data_cleaned[features_resetNA].replace(9999, 0,inplace=True) data_cleaned |
为避免部分特征值过大, 将剩余的定义为9999的缺失值修改为999
data_cleaned = data_cleaned.replace(9999, 999) |
类别型变量处理
特征中变量类型为字符的可以处理为类别型变量. 将变量类型为字符的特征转换为类别型变量.
# 使用get_dummies()函数将变量类型为字符的特征转换为类别型变量 data_dummies = pd.get_dummies(data) data_dummies |
异常值处理
所用特征皆为正数才有意义, 若出现负数则设为相反数
data_cleaned = data_dummies.mask(data_dummies < 0, -data_dummies) (data_cleaned< 0).sum() |
划分数据/标签
首先, 从data_cleaned中提取'target'变量, 并将其保存为y
然后, 从data_cleaned中提取所有其他变量, 并将其保存为X:
y = data_cleaned['target'] X = data_cleaned.drop('target', axis=1) X,y |
划分训练集测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) print("划分训练集测试集:",X_train.shape,X_test.shape) |
数据标准化
归一化和标准化
归一化将数据缩放到[0,1]范围内,公式为:
$$x_{norm} = \frac{x - \min(x)}{\max(x) - \min(x)}$$
标准化将数据转化为均值为0,标准差为1的正态分布,公式为:
$$x_{std} = \frac{x - \mu}{\sigma}$$
其中,$\mu$为均值,$\sigma$为标准差。
原始数据特征的数据密度分布不均匀,而归一化和标准化能够尽可能地消除这种情况下由特殊数据带来的影响。
归一化和标准化的适用场景
(1)数据的分布本身就服从正态分布,使用Z-Score。
(2)有离群值的情况:使用Z-Score。
Min-Max对于离群值十分敏感,因为离群值的出现,会影响数据中max或min值,从而使Min-Max的效果很差。相比之下,虽然使用Z-Score计算方差和均值的时候仍然会受到离群值的影响,但是相比于Min-Max法,影响会小一点。
(3)如果对输出结果范围有要求,用归一化。
(4)如果数据较为稳定,不存在极端的最大最小值,用归一化。
(5)如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响。
此处考虑到数据存在离群值, 故使用标准化.
import numpy as np # 标准化 def standardize(X): X_mean = np.mean(X, axis=0) X_std = np.std(X, axis=0) X_std = np.where(X_std==0, 1, X_std) X_std = X_std.reshape(1, -1) X_std = np.repeat(X_std, X.shape[0], axis=0) X_std = (X - X_mean) / X_std return X_std |
# 数据标准化 X_train_std = standardize(X_train) X_test_std = standardize(X_test) |
作图展示归一化和标准化的效果
为了展示归一化和标准化的效果,我们可以通过绘制直方图或者箱线图来比较原始数据和预处理后的数据的分布情况。
将原始数据、归一化后的数据和标准化后的数据的直方图和箱线图绘制在了同一张图中,方便对比效果。可以看出,归一化后的数据在每个特征维度上都被缩放到了[0, 1]的范围内,而标准化后的数据在每个特征维度上呈现出了均值为0,标准差为1的正态分布。
import matplotlib.pyplot as plt # 绘制直方图 fig, axs = plt.subplots(1, 2, figsize=(12, 4)) axs[0].hist(X_train.iloc[:, 0], bins=50) axs[0].set_xlabel('Feature 1') axs[0].set_ylabel('Frequency') axs[0].set_title('Original Data') # axs[1].hist(X_norm[:, 0], bins=50) # axs[1].set_xlabel('Feature 1') # axs[1].set_ylabel('Frequency') # axs[1].set_title('Normalized Data') axs[1].hist(X_train_std.iloc[:, 0], bins=50) axs[1].set_xlabel('Feature 1') axs[1].set_ylabel('Frequency') axs[1].set_title('Standardized Data') plt.show() # 绘制箱线图 fig, axs = plt.subplots(1, 2, figsize=(12, 4)) axs[0].boxplot(X_train) axs[0].set_xticklabels(['Feature 1', 'Feature 2', 'Feature 3', 'Feature 4']) axs[0].set_ylabel('Value') axs[0].set_title('Original Data') # axs[1].boxplot(X_norm) # axs[1].set_xticklabels(['Feature 1', 'Feature 2', 'Feature 3', 'Feature 4']) # axs[1].set_ylabel('Value') # axs[1].set_title('Normalized Data') axs[1].boxplot(X_train_std) axs[1].set_xticklabels(['Feature 1', 'Feature 2', 'Feature 3', 'Feature 4']) axs[1].set_ylabel('Value') axs[1].set_title('Standardized Data') plt.show() |
标准化后的直方图与箱线图如下
可以看出标准化后的数据分布更加均匀了.
方法二:
在实际应用中,归一化和标准化通常是根据具体情况选择一种或者同时进行的。如果需要同时进行归一化和标准化,首先进行归一化,然后计算归一化后数据的均值和标准差,最后根据归一化后数据的均值和标准差进行标准化。
# 归一化和标准化 def normalize_and_standardize(X): X_min = np.min(X, axis=0) X_max = np.max(X, axis=0) X_norm = (X - X_min) / (X_max - X_min) X_mean = np.mean(X_norm, axis=0) X_std = np.std(X_norm, axis=0) X_std = np.where(X_std==0, 1, X_std) X_std = X_std.reshape(1, -1) X_std = np.repeat(X_std, X.shape[0], axis=0) X_std = (X_norm - X_mean) / X_std return X_norm, X_std |
方法三:
首先, 使用sklearn库中的MinMaxScaler函数对数据进行归一化. 这将所有数据缩放到0-1之间. 然后, 使用sklearn库中的StandardScaler函数对数据进行标准化. 这将所有数据缩放到均值为0, 标准差为1的范围内.
from sklearn.preprocessing import MinMaxScaler, StandardScaler scaler_minmax = MinMaxScaler() scaler_standard = StandardScaler() X_minmax = scaler_minmax.fit_transform(X) X_standard = scaler_standard.fit_transform(X) |
然后, 使用matplotlib绘制归一化和标准化的效果:
plt.figure(figsize=(12, 6)) plt.subplot(1, 2, 1) plt.hist(X_minmax) plt.title('MinMaxScaler') plt.subplot(1, 2, 2) plt.hist(X_standard) plt.title('StandardScaler') plt.show() |
归一化和标准化的效果如图
对数值进行归一化和标准化主要是为了保证模型对异常数据的鲁棒性,使其更加稳定,降低过拟合风险。
标签不平衡
样本不均衡情况
0代表未逾期用户,1代表逾期用户。
在总共148077条数据中,有144012条属于未逾期用户,4065条属于逾期用户,比例达到35.4:1,样本极其不均衡。
# 统计标签类别的不平衡情况 target_counts = data['target'].value_counts() # 可视化标签类别的分布情况 import matplotlib.pyplot as plt plt.bar(target_counts.index, target_counts.values) plt.xlabel('Target') plt.ylabel('Counts') plt.title('Target Distribution') plt.show() target_counts |
上采样缓解不平衡情况
使用sklearn中的SMOTE类对数据集进行上采样:
from imblearn.over_sampling import SMOTE sm = SMOTE(random_state=42) X_res, y_res = sm.fit_resample(X, y) |
查看上采样后的标签类别分布:
pd.Series(y_res).value_counts() |
变量筛选
对过滤式, 包裹式, 嵌入式三种特征选择算法, 利用标准化后的特征进行特征选择. 并比较三种特征选择算法的性能.
使用了SelectKBest进行过滤式特征选择,使用了RFE进行包裹式特征选择,使用了SelectFromModel进行嵌入式特征选择。在嵌入式特征选择中,使用了带L1正则化的逻辑回归模型,并设置max_features参数为50,表示要选择的特征数为50。
过滤式特征选择
过滤式特征选择中单变量特征选择, 分别单独的计算每个变量的统计指标,根据该指标来判断哪些特征重要,剔除那些不重要的特征。
SelectKBest 移除得分前 k 名以外的所有特征(取top k).
selector_filter = SelectKBest(f_classif, k=5) X_train_filter = selector_filter.fit_transform(X_train_std, y_train) X_test_filter = selector_filter.transform(X_test_std) |
包裹式特征选择
包裹式特征选择中递归特征消除 (Recursive Feature Elimination)使用一个基模型来进行多轮训练,每轮训练后,移除若干权值系数的特征,再基于新的特征集进行下一轮训练。
对特征含有权重的预测模型(例如,线性模型对应参数coefficients),RFE通过递归减少考察的特征集规模来选择特征。首先,预测模型在原始特征上训练,每个特征指定一个权重。之后,那些拥有最小绝对值权重的特征被踢出特征集。如此往复递归,直至剩余的特征数量达到所需的特征数量。
clf_wrapper = RandomForestClassifier(n_estimators=10, random_state=42) selector_wrapper = RFE(clf_wrapper, n_features_to_select=5, step=1) X_train_wrapper = selector_wrapper.fit_transform(X_train_std, y_train) X_test_wrapper = selector_wrapper.transform(X_test_std) |
嵌入式特征选择
嵌入式特征选择是将特征选择过程与模型训练过程融合在一起,通过优化模型的目标函数来进行特征选择。嵌入式特征选择基于机器学习模型的方法。有些机器学习方法本身就具有对特征进行打分的机制,或者很容易将其运用到特征选择任务中,例如回归模型,SVM,决策树,随机森林等等。
使用L1范数作为惩罚项的线性模型(Linear models)会得到稀疏解:大部分特征对应的系数为0。当希望减少特征的维度以用于其它分类器时,可以通过 feature_selection.SelectFromModel 来选择不为0的系数。特别指出,常用于此目的的稀疏预测模型有 linear_model.Lasso(lasso回归), linear_model.LogisticRegression(逻辑回归)和 svm.LinearSVC(SVM支持向量机)
对于SVM和逻辑回归,参数C控制稀疏性:C越小,被选中的特征越少。对于Lasso,参数alpha越大,被选中的特征越少。
本文使用了带L1正则化的逻辑回归模型进行嵌入式特征选择。
使用逻辑回归模型对标准化后的训练数据进行拟合,然后使用SelectFromModel类选择特征。SelectFromModel类是一个元变换器(meta-transformer),它可以将任何带有coef_或feature_importances_属性的基本估计器转换为特征选择器。本文将拟合后的逻辑回归模型作为基本估计器,并将prefit参数设置为True,表示已经在训练数据上拟合好了模型。然后,将max_features参数设置为50,表示要选择的特征数为50。
在选择特征的过程中,SelectFromModel类会使用逻辑回归模型的coef_属性(也就是系数)来衡量每个特征的重要性。具体来说,如果某个特征的系数绝对值小于一个阈值(这里是1e-5),则认为该特征不重要,将其舍弃。最后使用transform方法将选择后的特征应用到训练数据和测试数据中。
clf_embedded = LogisticRegression(penalty='l1', solver='liblinear') clf_embedded.fit(X_train, y_train) selector_embedded = SelectFromModel(clf_embedded, prefit=True, max_features=5) X_train_embedded = selector_embedded.transform(X_train_std) X_test_embedded = selector_embedded.transform(X_test_std) |
性能评估
回归模型对三种特征选择后的数据进行训练,并计算了测试准确率。
clf = LogisticRegression() clf.fit(X_train_filter, y_train) score_filter = clf.score(X_test_filter, y_test) clf.fit(X_train_wrapper, y_train) score_wrapper = clf.score(X_test_wrapper, y_test) clf.fit(X_train_embedded, y_train) score_embedded = clf.score(X_test_embedded, y_test) print('过滤式特征选择的测试准确率:', score_filter) print('包裹式特征选择的测试准确率:', score_wrapper) print('嵌入式特征选择的测试准确率:', score_embedded) |
可以看出, 过滤式特征选择在本文使用的信用数据集的效果最好.
故使用过滤式特征选择得到的特征.
X_train=X_train_filter X_test=X_test_filter |
只使用单一特征选择算法的版本:
使用scikit-learn库中的特征选择算法SelectKBest类进行特征选择. 以确定哪些变量可以被排除,以减少模型的复杂性.
from sklearn.feature_selection import SelectKBest selector = SelectKBest(k=50) X_new = selector.fit_transform(X_res, y_res) # 查看选择的特征: selected_features = X_res.columns[selector.get_support()] X_new=X_res[selected_features] X_new |
计算特征的重要度
使用sklearn中的ExtraTreesClassifier类计算特征的重要度
from sklearn.ensemble import ExtraTreesClassifier import numpy as np model = ExtraTreesClassifier() model.fit(X_new, y_res) importances = model.feature_importances_ |
作图展示特征的重要度排序
对特征的重要度从大到小排序:
indices = np.argsort(importances)[::-1] |
然后, 使用matplotlib绘制特征的重要度排序:
plt.figure(figsize=(12, 6)) plt.bar(X_new.columns[indices], importances[indices]) plt.xticks(rotation=90) plt.title('Feature Importance') plt.show() |
绘制热力图展示变量间的相关度
import seaborn as sns # 绘制热力图 # sns.heatmap(X_new.corr(), annot=True) sns.heatmap(X_new.corr()) plt.show() |
我们用热力图来表示不同变量之间的关系,单元格颜色越浅,代表该单元格交叉的两个变量相关性越强。注意, 只能表示线性相关程度
模型选择
算法选择
对3种性能分类模型进行模型选择.
使用sklearn中的KNeighborsClassifier, DecisionTreeClassifier和LogisticRegression类进行模型选择.
使用K折交叉验证来评估模型性能, 使用模型对训练集和测试集进行预测.
使用sklearn中的accuracy_score函数来评估模型性能.
from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.linear_model import LogisticRegression from sklearn import svm from sklearn.model_selection import KFold from sklearn.metrics import accuracy_score knn = KNeighborsClassifier() dt = DecisionTreeClassifier() lr = LogisticRegression() svc = svm.SVC() for model in models: model.fit(X_train, y_train) y_pred = model.predict(X_test) # print(model.score(X_new, y_res)) accuracy = accuracy_score(y_test, y_pred) print(type(model).__name__,':', accuracy) kf = KFold(n_splits=3) for train_index, test_index in kf.split(X_new): X_train, X_test = X_new[train_index], X_new[test_index] y_train, y_test = y_res[train_index], y_res[test_index] for model in models: model.fit(X_train, y_train) y_pred = model.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(type(model).__name__,':', accuracy) |
得到几个模型评分分别为
KNeighborsClassifier : 0.9123860775974307
DecisionTreeClassifier : 0.9699678847322281
LogisticRegression : 0.7200937418626855
可以看出决策树的模型效果最好, 准确率达到了0.9699678847322281
最佳模型参数选择
使用sklearn中的GridSearchCV类进行模型选择:
# 导入GridSearchCV from sklearn.model_selection import GridSearchCV # 定义参数网格 param_grid = {'max_depth': [3, 5, 7], 'min_samples_split': [2, 4, 6], 'min_samples_leaf': [1, 3, 5]} clf = DecisionTreeClassifier() # 创建GridSearchCV实例 grid_search = GridSearchCV(clf, param_grid, cv=5) # 训练模型 grid_search.fit(X_train, y_train) # 获取最佳模型参数 best_params = grid_search.best_params_ best_params |
最佳模型参数
经过实验,最终确定了一组可以使所构建的模型性能优异的参数,如下所示:
max_depth参数表示决策树的最大深度28,
min_samples_split参数表示分裂内部节点所需的最小样本数3,
min_samples_leaf参数表示叶子节点所需的最小样本数1。
法二: 使用手动划分的数据集选择
不使用交叉验证及网格搜索
通过计算模型表现的召回率,准确率,F1值, 根据模型表现对模型进行选择.
knn = KNeighborsClassifier() dt = DecisionTreeClassifier() knn.fit(X_train, y_train) y_pred = knn.predict(X_test) accuracy = accuracy_score(y_test, y_pred) recall = recall_score(y_test, y_pred) f1 = f1_score(y_test, y_pred) print('knn \naccuracy:', accuracy, '\n recall:',recall, '\n f1_score:',f1) dt.fit(X_train, y_train) y_pred = dt.predict(X_test) accuracy = accuracy_score(y_test, y_pred) recall = recall_score(y_test, y_pred) f1 = f1_score(y_test, y_pred) print('dt \naccuracy:', accuracy, '\n recall:',recall, '\n f1_score:',f1) |
根据召回率,准确率,F1值可以看出KNN的表现较好. 故选择其作为最终模型.
其模型表现为:
模型表现
使用最佳模型进行预测
划分数据集
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X_new, y_res, test_size=0.1) |
训练模型
使用最佳模型参数来实例化svm模型:
dt = DecisionTreeClassifier(max_depth=best_params['max_depth'],min_samples_split=best_params['min_samples_split'],min_samples_leaf=best_params['min_samples_leaf']) |
训练模型并预测
dt.fit(X_train, y_train) y_pred = dt.predict(X_test) |
作图展示模型表现
作图展示ROC曲线,KS曲线, 以展示模型表现.
使用sklearn中的roc_curve函数来计算ROC曲线:
from sklearn.metrics import roc_curve fpr, tpr, thresholds = roc_curve(y_test, y_pred) |
使用matplotlib中的plot函数来绘制ROC曲线:
plt.plot(fpr, tpr) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('ROC Curve') plt.show() |
使用sklearn中的ks_2samp函数来计算KS曲线:
def ks(df, y_true, y_pre, num=10, good=0, bad=1): # 1.将数据从小到大平均分成num组 df_ks = df.sort_values(y_pre).reset_index(drop=True) df_ks['rank'] = np.floor((df_ks.index / len(df_ks) * num) + 1) df_ks['set_1'] = 1 # 2.统计结果 result_ks = pd.DataFrame() result_ks['group_sum'] = df_ks.groupby('rank')['set_1'].sum() result_ks['group_min'] = df_ks.groupby('rank')[y_pre].min() result_ks['group_max'] = df_ks.groupby('rank')[y_pre].max() result_ks['group_mean'] = df_ks.groupby('rank')[y_pre].mean() # 3.最后一行添加total汇总数据 result_ks.loc['total', 'group_sum'] = df_ks['set_1'].sum() result_ks.loc['total', 'group_min'] = df_ks[y_pre].min() result_ks.loc['total', 'group_max'] = df_ks[y_pre].max() result_ks.loc['total', 'group_mean'] = df_ks[y_pre].mean() # 4.好用户统计 result_ks['good_sum'] = df_ks[df_ks[y_true] == good].groupby('rank')['set_1'].sum() result_ks.good_sum.replace(np.nan, 0, inplace=True) result_ks.loc['total', 'good_sum'] = result_ks['good_sum'].sum() result_ks['good_percent'] = result_ks['good_sum'] / result_ks.loc['total', 'good_sum'] result_ks['good_percent_cum'] = result_ks['good_sum'].cumsum() / result_ks.loc['total', 'good_sum'] # 5.坏用户统计 result_ks['bad_sum'] = df_ks[df_ks[y_true] == bad].groupby('rank')['set_1'].sum() result_ks.bad_sum.replace(np.nan, 0, inplace=True) result_ks.loc['total', 'bad_sum'] = result_ks['bad_sum'].sum() result_ks['bad_percent'] = result_ks['bad_sum'] / result_ks.loc['total', 'bad_sum'] result_ks['bad_percent_cum'] = result_ks['bad_sum'].cumsum() / result_ks.loc['total', 'bad_sum'] # 6.计算ks值 # result_ks['diff'] = result_ks['bad_percent_cum'] - result_ks['good_percent_cum'] result_ks['diff'] = abs(result_ks['bad_percent_cum'] - result_ks['good_percent_cum']) # 7.更新最后一行total的数据 result_ks.loc['total', 'bad_percent_cum'] = np.nan result_ks.loc['total', 'good_percent_cum'] = np.nan result_ks.loc['total', 'diff'] = result_ks['diff'].max() result_ks = result_ks.reset_index() return result_ks |
使用matplotlib中的plot函数来绘制KS曲线:
def ks_curve(df, num=10): ks_value = df['diff'].max() # 获取绘制曲线所需要的数据 x_curve = range(num + 1) y_curve1 = [0] + list(df['bad_percent_cum'].values[:-1]) y_curve2 = [0] + list(df['good_percent_cum'].values[:-1]) y_curve3 = [0] + list(df['diff'].values[:-1]) # 获取绘制ks点所需要的数据 df_ks_max = df[df['diff'] == ks_value] x_point = [df_ks_max['rank'].values[0], df_ks_max['rank'].values[0]] y_point = [df_ks_max['bad_percent_cum'].values[0], df_ks_max['good_percent_cum'].values[0]] # 绘制曲线 plt.plot(x_curve, y_curve1, label='bad', linewidth=2) plt.plot(x_curve, y_curve2, label='good', linewidth=2) plt.plot(x_curve, y_curve3, label='diff', linewidth=2) # 标记ks plt.plot(x_point, y_point, label='ks - {:.2f}'.format(ks_value), color='r', marker='o', markerfacecolor='r', markersize=5) plt.scatter(x_point, y_point, color='r') plt.legend() plt.show() return ks_value sns.set() y_pred_test = pd.DataFrame(data = {'y_pred': y_pred, 'y_test': y_test}) result_ks = ks(y_pred_test, 'y_pred', 'y_test') ks_curve(result_ks) |
bad, good这两条曲线的最大差值就是的KS统计量. 这个差值越大,说明模型对这个正负样本的区别能力越强. KS统计量大于0.6, 说明模型的可信度较高.
机器学习实验笔记-基于信用卡数据建立行为评分模型的机器学习方法相关推荐
- bgp基础配置实验(基于环回口建立peer关系)
实验需求:全网互通 拓扑: 步骤:1.接口ip配置 R1(config)#interface f0/0 R1(config-if)#ip address 12.12.12.1 255.255.255. ...
- 机器学习实践笔记(三)时间序列数据预测
时间序列模型 1.拿到数据咱们开始分析 2.Arima 硬性基础知识 Arima模型 AR MA ARMA ARIMA 如何选择p值和q值 自相关函数ACF 建立Arima模型 数据的确定 模型预测 ...
- 机器学习笔记 - 基于Torch Hub的深度估计模型MiDaS
1.MiDaS 图像的深度估计从 2D 图像本身预测对象的顺序(如果图像以 3D 格式扩展).这无疑是一项艰巨的任务,因为获取专门用于该领域的注释数据和数据集本身就是一项艰巨的任务.深度估计的使用范围 ...
- 《Spark机器学习》笔记——基于MovieLens数据集使用Spark进行电影数据分析
1.数据集下载 https://grouplens.org/datasets/movielens 2.数据集下文件格式 u.user用户属性文件 包含user.id用户ID gender性别 ...
- 跳出数据计算拯救人工智能之打败机器学习方法详解
首先人脑智能分为三种 一是逻辑 二是创造 三是建立关系存储 关系存储 就是建立每个最小信息与已经存起来的信息之间的关系 也就是说新的信息是靠已经存储的信息记录下来的 就像人类通过语言的描述记录环境 这 ...
- 跳出数据计算拯救人工智能之打败机器学习方法详解二
上回分析的够透彻了吧 计算方面就使用填字数据结构计算 存储方面使用数据库表的方式存储 为了方便就都使用 填字的方式进行试验 首先要知道采取上回说到的65535个二进制位进行代表人类的文字信息的话 那么 ...
- 跳出数据计算拯救人工智能之打败机器学习方法
时间过去这么久了,还是选择挑战一下权威 建立一个简单的逻辑思维 实际上每个细胞都是智能的整体所以智能是同样逻辑的堆叠 不是随机的模拟规律 机器学习是表面的模仿并未达到本质 智能的本质是 自然法则 自然 ...
- 基于深度学习的信用评分模型实现
目录 1.引言 2.数据准备 2.1 数据收集和清洗 2.2 特征工程 2.3 数据划分
- 基于大数据方法的经济研究:前沿进展与研究综述 | 特别推荐
基于大数据方法的经济研究:前沿进展与研究综述 李华杰 史丹 马丽梅 摘要: 随着数据挖掘和分析技术的不断提高,基于大数据方法对经济的研究日益增多,大数据对经济研究和应用具有重要的现实意义.本文梳理了近 ...
最新文章
- 【重建】从FJOI2016一试谈起
- linux 内核 struct file_operations中 ioctl 变为 unlocked_ioctl
- 形象标识 新松机器人_东莞市81个乡村振兴重点项目集中启用,树立统一标识牌302块...
- CSS布局之float浮动
- python引用传递产生的问题_python关于lambda、引用传递等易犯的错误
- mysql如何加快备份和恢复速度_加速mysql备份和恢复
- 游戏筑基开发之学生管理系统数据结构及数据结构解析图(C语言)
- Android 强升逻辑和实现
- Linux平台搭建Discuz
- WDSR:Wide Activation for Efficient and Accurate Image Super-Resolution
- 圆形矢量场field driven strength效果
- 市场营销人员如何用BI工具进行多维度数据分析?仅需7步
- H3C HCL模拟器配置vlan划分案例
- Qt 6.2的下载和安装
- 计算机班级学生分析,【本班学生学业成绩状况】_本班学生情况分析报告
- 国瀚实业|怎么才能做好互联网投资理财
- java.io.IOException Failed to replace a bad datanode
- Lanczos插值滤波器
- STM32 IAP 在线升级详解
- Windows修改3389端口