机器学习基础课程-6-课程实验

目录

[6.1 实验介绍](#6.1 实验介绍)

实验准备

贷款审批结果预测

[6.2 数据读取](#6.2 数据读取)

[6.3 数据处理](#6.3 数据处理)

[6.4 特征处理](#6.4 特征处理)

有序型特征处理

类别型特征处理

数值型特征归一化

[6.5 建立机器学习模型](#6.5 建立机器学习模型)

建立测试模型

结果可视化


6.1 实验介绍

贷款审批结果预测

银行的放贷审批,核心要素为风险控制。因此,对于申请人的审查关注的要点为违约可能性。而违约可能性通常由申请人收入情况、稳定性、贷款数额及偿还年限等因素来衡量。该项目根据申请人条件,进一步细化得到各个变量对于违约评估的影响,从而预测银行是否会批准贷款申请。在项目实现过程中使用了经典的机器学习算法,对申请贷款客户进行科学归类,从而帮助金融机构提高对贷款信用风险的控制能力。

6.2 数据读取

数据读取
import pandas as pd

file = './data/loan_records.csv'

loan_df = pd.read_csv(file)
数据预览
print('数据集一共有{}行,{}列'.format(loan_df.shape[0], loan_df.shape[1]))

数据集一共有614行,13列

loan_df.head()

从贷款数据样本中,可以观察得到数据的特征

  • Loan_ID:样本标号
  • 性别:贷款人性别
  • 已婚:是否结婚 (Y/N)
  • 家属:供养人数
  • 教育: 受教育程度(研究生/非研究生)
  • Self_Employed:是否自雇 (Y/N)
  • 申请人收入:申请人收入
  • 共同申请人收入:联合申请人收入
  • 贷款金额:贷款金额(单位:千)
  • Loan_Amount_Term:贷款期限(单位:月)
  • Credit_History:历史信用是否达标(0/1)
  • Property_Area:居住地区(城市/半城市/农村)
  • Loan_Status:是否批准(Y/N)
    在我们即将构建的机器学习模型当中,Loan_Status 将是模型训练的目标列

数据统计信息
loan_df.describe()

观察数据情况可以得知:

  • LoanAmount、Loan_Amount_Term、Credit_History有明显的缺失值,需要进行空值处理

6.3 数据处理

重复值处理
if loan_df[loan_df['Loan_ID'].duplicated()].shape[0] > 0:

print('数据集存在重复样本')

else:

print('数据集不存在重复样本')

数据集不存在重复样本
缺失值处理
cols = loan_df.columns.tolist()

for col in cols:

empty_count = loan_df[col].isnull().sum()

print('{} 空记录数为:{}'.format(col, empty_count))

Loan_ID 空记录数为:0

Gender 空记录数为:13

Married 空记录数为:3

Dependents 空记录数为:15

Education 空记录数为:0

Self_Employed 空记录数为:32

ApplicantIncome 空记录数为:0

CoapplicantIncome 空记录数为:0

LoanAmount 空记录数为:22

Loan_Amount_Term 空记录数为:14

Credit_History 空记录数为:50

Property_Area 空记录数为:0

Loan_Status 空记录数为:0

将存在空值的样本删除

clean_loan_df = loan_df.dropna()

print('原始样本数为{},清理后的样本数为{}'.format(loan_df.shape[0], clean_loan_df.shape[0]))

原始样本数为614,清理后的样本数为480
特殊值处理

数值列Dependents包含3+,将其全部转换为3

可忽略SettingWithCopyWarning

clean_loan_df.loc[clean_loan_df['Dependents'] == '3+', 'Dependents'] = 3
特征数据和标签数据提取

在该数据集中,共有以下三种特征列

  1. 数值型特征列
    • 家属:供养人数
    • 申请人收入:申请人收入
    • 共同申请人收入:联合申请人收入
    • 贷款金额:贷款金额(单位:千)
  • Loan_Amount_Term:贷款期限(单位:月)
  1. 有序型特征
    • 教育: 受教育程度(研究生/非研究生)
  • Credit_History:历史信用是否达标(0/1)
  1. 类别型特征
    • 性别:贷款人性别
    • 已婚:是否结婚 (Y/N)
    • Self_Employed:是否自雇 (Y/N)
  • Property_Area:居住地区(城市/半城市/农村)

按数据类型指定特征列

1. 数值型特征列

num_cols = ['Dependents', 'ApplicantIncome', 'CoapplicantIncome', 'LoanAmount', 'Loan_Amount_Term']

2. 有序型特征

ord_cols = ['Education', 'Credit_History']

3. 类别型特征

cat_cols = ['Gender', 'Married', 'Self_Employed', 'Property_Area']

feat_cols = num_cols + ord_cols + cat_cols

特征数据

feat_df = clean_loan_df[feat_cols]

#################################################################

TODO

将标签Y转换为1,标签N转换为0

并将结果保存至labels变量中

labels = clean_loan_df['Loan_Status'].copy()

labels.loc[clean_loan_df['Loan_Status'] == 'Y'] = 1

labels.loc[clean_loan_df['Loan_Status'] == 'N'] = 0

#################################################################
现在我们需要划分数据集为训练集和测试集
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(feat_df, labels, random_state=10, test_size=1/4)

print('训练集有{}条记录,测试集有{}条记录'.format(X_train.shape[0], X_test.shape[0]))

训练集有360条记录,测试集有120条记录

6.4 特征处理

有序型特征处理

有序型特征中Credit_History已经是数值,只需要转换教育列就即可:将Graduate转为1,Not Graduate转为0

复制代码
# 可忽略SettingWithCopyWarning
复制代码
# 在训练集上做处理
复制代码
X_train.loc[X_train['Education'] == 'Graduate', 'Education'] = 1
复制代码
X_train.loc[X_train['Education'] == 'Not Graduate', 'Education'] = 0
复制代码
复制代码
# 在测试集上做处理
复制代码
X_test.loc[X_test['Education'] == 'Graduate', 'Education'] = 1
复制代码
X_test.loc[X_test['Education'] == 'Not Graduate', 'Education'] = 0
复制代码
复制代码
# 获取有序型特征处理结果
复制代码
train_ord_feats = X_train[ord_cols].values
复制代码
test_ord_feats = X_test[ord_cols].values
类别型特征处理
复制代码
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
复制代码
import numpy as np
复制代码
复制代码
def encode_cat_feats(train_df, test_df, col_name):
复制代码
    """
复制代码
`        `对某列类别型数据进行编码
复制代码
    """
复制代码
    # 类别型数据
复制代码
    train_cat_feat = X_train[col_name].values
复制代码
    test_cat_feat = X_test[col_name].values
复制代码
`    `
复制代码
    label_enc = LabelEncoder()
复制代码
    onehot_enc = OneHotEncoder(sparse=False)
复制代码
复制代码
    # 在训练集上处理
复制代码
    proc_train_cat_feat = label_enc.fit_transform(train_cat_feat).reshape(-1, 1)
复制代码
    proc_train_cat_feat = onehot_enc.fit_transform(proc_train_cat_feat)
复制代码
复制代码
    # 在测试集上处理
复制代码
    proc_test_cat_feat = label_enc.transform(test_cat_feat).reshape(-1, 1)
复制代码
    proc_test_cat_feat = onehot_enc.transform(proc_test_cat_feat)
复制代码
`    `
复制代码
    return proc_train_cat_feat, proc_test_cat_feat
复制代码
复制代码
# 初始化编码处理后的特征
复制代码
enc_train_cat_feats = None
复制代码
enc_test_cat_feats = None
复制代码
复制代码
# 对每个类别型特征进行编码处理
复制代码
for cat_col in cat_cols:
复制代码
    enc_train_cat_feat, enc_test_cat_feat = encode_cat_feats(X_train, X_test, cat_col)
复制代码
    # 在训练数据上合并特征
复制代码
    if enc_train_cat_feats is None:
复制代码
        enc_train_cat_feats = enc_train_cat_feat
复制代码
    else:
复制代码
        enc_train_cat_feats = np.hstack((enc_train_cat_feats, enc_train_cat_feat))
复制代码
`        `
复制代码
    # 在测试数据上合并特征
复制代码
    if enc_test_cat_feats is None:
复制代码
        enc_test_cat_feats = enc_test_cat_feat
复制代码
    else:
复制代码
        enc_test_cat_feats = np.hstack((enc_test_cat_feats, enc_test_cat_feat))
数值型特征归一化

将所有特征进行合并,然后进行范围归一化。

复制代码
from sklearn.preprocessing import MinMaxScaler
复制代码
复制代码
# 获取数值型特征
复制代码
train_num_feats = X_train[num_cols].values
复制代码
test_num_feats = X_test[num_cols].values
复制代码
复制代码
# 合并序列型特征、类别型特征、数值型特征
复制代码
all_train_feats = np.hstack((train_ord_feats, enc_train_cat_feats, train_num_feats))
复制代码
all_test_feats = np.hstack((test_ord_feats, enc_test_cat_feats, test_num_feats))
复制代码
复制代码
#################################################################
复制代码
# TODO
复制代码
# 数值归一化到0-1
复制代码
# 将处理后的训练特征保存到变量all_proc_train_feats中
复制代码
# 将处理后的测试特征保存到变量all_proc_test_feats中
复制代码
scaler = MinMaxScaler(feature_range=(0, 1))
复制代码
all_proc_train_feats = scaler.fit_transform(all_train_feats)
复制代码
all_proc_test_feats = scaler.transform(all_test_feats)
复制代码
#################################################################
复制代码
复制代码
print('处理后的特征维度为', all_proc_train_feats.shape[1])
复制代码
处理后的特征维度为 16

6.5 建立机器学习模型

建立测试模型

使用网格搜索(GridSearchCV)来调整模型的重要参数

复制代码
from sklearn.linear_model import LogisticRegression
复制代码
from sklearn.neighbors import KNeighborsClassifier
复制代码
from sklearn.tree import DecisionTreeClassifier
复制代码
from sklearn.svm import SVC
复制代码
from sklearn.model_selection import GridSearchCV
复制代码
import time
复制代码
复制代码
def train_test_model(X_train, y_train, X_test, y_test, model_name, model, param_range):
复制代码
    """
复制代码
`        `训练并测试模型
复制代码
        model_name:
复制代码
            kNN         kNN模型,对应参数为 n_neighbors
复制代码
            LR          逻辑回归模型,对应参数为 C
复制代码
            SVM         支持向量机,对应参数为 C
复制代码
            DT          决策树,对应参数为 max_depth
复制代码
            Stacking    将kNN, SVM, DT集成的Stacking模型, meta分类器为LR
复制代码
            AdaBoost    AdaBoost模型,对应参数为 n_estimators
复制代码
            GBDT        GBDT模型,对应参数为 learning_rate
复制代码
            RF          随机森林模型,对应参数为 n_estimators
复制代码
复制代码
`        `根据给定的参数训练模型,并返回
复制代码
        1. 最优模型
复制代码
        2. 平均训练耗时
复制代码
        3. 准确率
复制代码
    """
复制代码
    print('训练{}...'.format(model_name))
复制代码
`    `
复制代码
    #################################################################
复制代码
    # TODO
复制代码
    # 初始化网格搜索方法进行模型训练,使用5折交叉验证,保存到变量clf中
复制代码
    clf = GridSearchCV(estimator=model,
复制代码
                       param_grid=param_range,
复制代码
                       cv=5,
复制代码
                       scoring='accuracy',
复制代码
                       refit=True)
复制代码
    start = time.time()
复制代码
    clf.fit(X_train, y_train)
复制代码
    #################################################################
复制代码
`    `
复制代码
    start = time.time()
复制代码
    clf.fit(X_train, y_train)
复制代码
    # 计时
复制代码
    end = time.time()
复制代码
    duration = end - start
复制代码
    print('耗时{:.4f}s'.format(duration))
复制代码
复制代码
    # 验证模型
复制代码
    train_score = clf.score(X_train, y_train)
复制代码
    print('训练准确率:{:.3f}%'.format(train_score * 100))
复制代码
复制代码
    test_score = clf.score(X_test, y_test)
复制代码
    print('测试准确率:{:.3f}%'.format(test_score * 100))
复制代码
    print('训练模型耗时: {:.4f}s'.format(duration))
复制代码
复制代码
    y_pred = clf.predict(X_test)
复制代码
复制代码
    return clf, test_score, duration
复制代码
#################################################################
复制代码
# TODO
复制代码
# 在model_name_param_dict中添加逻辑回归和SVM分类器,并指定相应的超参数及搜索范围
复制代码
model_name_param_dict = {'kNN': (KNeighborsClassifier(),
复制代码
                                 {'n_neighbors': [1, 5, 15]}),
复制代码
                         'DT': (DecisionTreeClassifier(),
复制代码
                                {'max_depth': [10, 50, 100]}),
复制代码
                         'SVM': (SVC(kernel='linear'),
复制代码
                                 {'C': [0.01, 1, 100]}),
复制代码
                         'DT': (DecisionTreeClassifier(),
复制代码
                                {'max_depth': [10, 50, 100]})
复制代码
                         }
复制代码
#################################################################
复制代码
复制代码
# 比较结果的DataFrame
复制代码
results_df = pd.DataFrame(columns=['Accuracy (%)', 'Time (s)'],
复制代码
                          index=list(model_name_param_dict.keys()))
复制代码
results_df.index.name = 'Model'
复制代码
for model_name, (model, param_range) in model_name_param_dict.items():
复制代码
    _, best_acc, mean_duration = train_test_model(all_proc_train_feats, y_train.astype('int'), all_proc_test_feats, y_test.astype('int'), model_name, model, param_range)
复制代码
    results_df.loc[model_name, 'Accuracy (%)'] = best_acc * 100
复制代码
    results_df.loc[model_name, 'Time (s)'] = mean_duration
复制代码
训练kNN...
复制代码
耗时0.0661s
复制代码
训练准确率:80.556%
复制代码
测试准确率:76.667%
复制代码
训练模型耗时: 0.0661s
复制代码
训练DT...
复制代码
耗时0.0442s
复制代码
训练准确率:91.111%
复制代码
测试准确率:76.667%
复制代码
训练模型耗时: 0.0442s
复制代码
训练SVM...
复制代码
耗时0.1124s
复制代码
训练准确率:80.556%
复制代码
测试准确率:81.667%
复制代码
训练模型耗时: 0.1124s
结果可视化

现在对比一下各个模型的效率和他们的准确率吧!

复制代码
# 结果可视化import matplotlib.pyplot as plt%matplotlib inlineplt.figure(figsize=(10, 4))ax1 = plt.subplot(1, 2, 1)results_df.plot(y=['Accuracy (%)'], kind='bar', ylim=[60, 100], ax=ax1, title='Accuracy(%)', legend=False)ax2 = plt.subplot(1, 2, 2)results_df.plot(y=['Time (s)'], kind='bar', ax=ax2, title='Time(s)', legend=False)plt.tight_layout()plt.show()
相关推荐
FL16238631291 小时前
荔枝成熟度分割数据集labelme格式2263张3类别
人工智能·深度学习
一点.点1 小时前
DRIVEGPT4: 通过大语言模型实现可解释的端到端自动驾驶
人工智能·语言模型·自然语言处理·自动驾驶
天涯海风2 小时前
介绍一下什么是 AI、 AGI、 ASI
人工智能·agi
zzc9212 小时前
Tensorflow 2.X Debug中的Tensor.numpy问题 @tf.function
人工智能·tensorflow·numpy
我是你们的星光2 小时前
基于深度学习的高效图像失真校正框架总结
人工智能·深度学习·计算机视觉·3d
追逐☞3 小时前
机器学习(11)——xgboost
人工智能·机器学习
未来可期叶4 小时前
如何用Python批量解压ZIP文件?快速解决方案
python
张槊哲4 小时前
ROS2架构介绍
python·架构
智驱力人工智能4 小时前
AI移动监测:仓储环境安全的“全天候守护者”
人工智能·算法·安全·边缘计算·行为识别·移动监测·动物检测
斯普信专业组4 小时前
Apidog MCP服务器,连接API规范和AI编码助手的桥梁
运维·服务器·人工智能