演练:训练和验证逻辑回归模型

任务目标

  • 构建逻辑回归模型并对数据样本进行预测
  • 理解和掌握逻辑回归模型性能的评价指标和方法
  • 理解过拟合的产生以及通过惩罚项进行抑制的方法

任务描述

【dataset/titanic_train.csv】文件包含了泰坦尼克号乘客信息及其是否幸存的记录,各个字段含义如下:

  • PassengerId:乘客ID
  • Survive:标签,标记乘客是否生还
  • Pclass:乘客等级(1/2/3等舱位)
  • Name:乘客姓名
  • Sex:性别
  • Age:年龄
  • SibSp:兄弟姐妹的个数
  • Parch:父母与小孩个数
  • Ticket:船票信息
  • Fare:票价
  • Cabin:客舱
  • Embarked:登船港口

要求完成下列任务项:

  • 数据探查:查看各个字段的数据分布及与标签结果之间的关系
  • 数据清洗和特征处理:缺失值处理,删除无用特征,合并相关特征并进行分箱处理
  • 构建基础模型并评估性能:训练一个逻辑回归模型,根据特征预测其是否生还;计算二分类的性能指标
  • 非线性可分处理(拓展):通过高阶函数来处理非线性问题,并通过惩罚项抑制过拟合
  • 多分类处理(拓展):使用逻辑回归对手写数字图片分类

工具和方法

  • sklearn.linear_model模块:LogisticRegression
  • sklearn.metrics模块:precision_score, recall_score, f1_score, confusion_matrix, classification_report

【任务0】 准备工作

本演练准备工作包括:

  • 预设随机数种子以使结果可重现

    • 设置各随机数的种子为固定值(100),以便产生的随机序列可以重现
    • 后续代码中如果涉及到随机种子的设置,应统一设置为random_state
  • 装载数据集并查看样例数据
import random
import numpy as np
import pandas as pdrandom_state = 100
random.seed(random_state)
np.random.seed(random_state)data_file = 'dataset/titanic_train.csv'
df = pd.read_csv(data_file)
print(df.head())
print("=" * 100)
print("训练样本维度:", df.shape)
   PassengerId  Survived  Pclass  \
0            1         0       3
1            2         1       1
2            3         1       3
3            4         1       1
4            5         0       3   Name     Sex   Age  SibSp  \
0                            Braund, Mr. Owen Harris    male  22.0      1
1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1
2                             Heikkinen, Miss. Laina  female  26.0      0
3       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1
4                           Allen, Mr. William Henry    male  35.0      0   Parch            Ticket     Fare Cabin Embarked
0      0         A/5 21171   7.2500   NaN        S
1      0          PC 17599  71.2833   C85        C
2      0  STON/O2. 3101282   7.9250   NaN        S
3      0            113803  53.1000  C123        S
4      0            373450   8.0500   NaN        S
====================================================================================================
训练样本维度: (891, 12)

【任务1】 数据探查

【子任务项1.1】 统计字段类型和缺失情况

检查数据集每个字段的类型(文本/数值),查看字段的的缺失值数量

print(df.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):#   Column       Non-Null Count  Dtype
---  ------       --------------  -----  0   PassengerId  891 non-null    int64  1   Survived     891 non-null    int64  2   Pclass       891 non-null    int64  3   Name         891 non-null    object 4   Sex          891 non-null    object 5   Age          714 non-null    float646   SibSp        891 non-null    int64  7   Parch        891 non-null    int64  8   Ticket       891 non-null    object 9   Fare         891 non-null    float6410  Cabin        204 non-null    object 11  Embarked     889 non-null    object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None

说明

  • Name、Sex、Ticket、Cabin、Embarked 5个字段为字符串类型
  • 样本中,Age、Cabin和Embarked字段均有缺失值,且Cabin大量缺失,后续要注意处理

【子任务项1.2】 考查【仓位】与生还结果之间的关系

统计并使用堆叠柱状图显示不同仓位(Pclass)的生还(Survived)结果

import matplotlib.pyplot as plt
%matplotlib inline# 统计未幸存的乘客中每种Pclass的数量
no_survived = df['Pclass'][df['Survived'] == 0].value_counts()
# 统计幸存的乘客中每种Pclass的数量
survived = df['Pclass'][df['Survived'] == 1].value_counts()
# 构建用于作图的数据集
df_temp = pd.DataFrame({'Survived':survived,'Died':no_survived})
# 绘制堆叠柱状图
df_temp.plot(kind='bar',stacked = True)plt.xlabel('Class')
plt.ylabel('Sum')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s8L6eMJx-1626015050075)(output_7_0.png)]

说明
  • 就生还率而言,一等舱明显最高,而三等舱显然最低。因此可以推测舱位的高低与生还情况成正相关
  • 可以尝试查看其它特征与分类结果之间的样本数量关系

【任务2】 数据清洗和特征处理

【子任务项2.1】 初步筛选合适的特征

  • 在原始的各个字段中,PassengerID和Name显然与分类结果没有任何关联,无需使用
  • Ticket字段描述的船票信息既非数值,也不是有限取值的文本,因此在此处也不作为特征
  • Cabin特征样本缺失数量巨大,因此可以考虑将该特征删除
  • 最终经过初筛,特征字段为:Pclass,Sex,Age,SibSp,Parch,Fare,Embarked。

下面的代码从数据集中删除无关字段,仅保留特征字段和标签。

df.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'],  axis=1, inplace=True)
print(df.columns)
Index(['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare','Embarked'],dtype='object')
说明

上述结果输出,已经去除了无关字段。

【子任务项2.2】 拆分训练集和测试集

将数据按照7:3拆分成训练数据集和测试数据集
注意,Survived字段是标签(下标索引为0),其余字段是特征

from sklearn.model_selection import train_test_splitX_train,X_test,y_train,y_test = train_test_split(df.iloc[:, 1:], df.iloc[:, 0], test_size=0.3, random_state=random_state)
print("训练集特征维度:", X_train.shape, ",标签维度:", y_train.shape)
print("测试集特征维度:", X_test.shape, ",标签维度:", y_test.shape)
训练集特征维度: (623, 7) ,标签维度: (623,)
测试集特征维度: (268, 7) ,标签维度: (268,)
说明

训练样本623个,测试样本268个。这些样本都要保留下来,但是部分字段存在缺失值,需要以恰当的方式填充这些缺失值

【子任务项2.3】 使用随机森林模型插补Age字段的缺失值

  • Age字段的缺失值有100多个,可以考虑通过其它字段来推算其可能的值。此处使用随机森林模型预测Age值。
  • 选择训练集中的’Fare’, ‘Parch’, ‘SibSp’, 'Pclass’四个字段作为特征,'Age’字段作为结果,训练随机森林模型
  • 使用模型预测缺失的Age值,并写回到训练集和测试集中
from sklearn.ensemble import RandomForestRegressor# 使用数据集中的'Age','Fare', 'Parch', 'SibSp', 'Pclass'
age = X_train[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]
known_age = age[age.Age.notnull()].values    # Age未缺失的样本
unknown_age = age[age.Age.isnull()].values    # Age缺失的样本X = known_age[:,1:]    # 后4个字段为特征矩阵X
y = known_age[:,0]    # 第1个字段为标签结果# 训练模型
rf = RandomForestRegressor(random_state=random_state, n_estimators=200)
rf.fit(X, y)# 计算Age缺失的样本中的预测值
predicts = rf.predict(unknown_age[:, 1:])
# 将Age值更新到df_train中
X_train.loc[(X_train.Age.isnull()), 'Age' ] = predicts # 将Age值更新到df_test中
age_test = X_test[['Fare', 'Parch', 'SibSp', 'Pclass']][X_test.Age.isnull()]
predicts = rf.predict(age_test)
X_test.loc[(X_test.Age.isnull()), 'Age' ] = predicts print("测试数据中插补的Age值:", predicts)
print("=" * 100)
print(X_train.info())
print("=" * 100)
print(X_test.info())
测试数据中插补的Age值: [ 4.9025846  27.01755548 29.26959254 11.22093849 29.146325   28.8532124926.396      11.22093849 26.41578589 23.26333333 25.06640712 32.7373645239.30680952 22.71342866 27.01546825 26.41578589 39.05960516 29.4431720827.01755548 29.26959254 32.73736452 32.73736452 29.44317208 16.0058333332.73736452 32.73736452 27.84292626 27.84292626 27.01755548 22.7134286627.84292626 23.34266667 32.43666667 25.62333333 32.73736452 38.0693333332.51466667 25.41690476 33.41228986 23.02333333 22.90907184 27.0175554836.85508479 30.35875    27.01755548 39.58833333 52.01260387 25.639761936.85508479]
====================================================================================================
<class 'pandas.core.frame.DataFrame'>
Int64Index: 623 entries, 69 to 520
Data columns (total 7 columns):#   Column    Non-Null Count  Dtype
---  ------    --------------  -----  0   Pclass    623 non-null    int64  1   Sex       623 non-null    object 2   Age       623 non-null    float643   SibSp     623 non-null    int64  4   Parch     623 non-null    int64  5   Fare      623 non-null    float646   Embarked  622 non-null    object
dtypes: float64(2), int64(3), object(2)
memory usage: 38.9+ KB
None
====================================================================================================
<class 'pandas.core.frame.DataFrame'>
Int64Index: 268 entries, 205 to 277
Data columns (total 7 columns):#   Column    Non-Null Count  Dtype
---  ------    --------------  -----  0   Pclass    268 non-null    int64  1   Sex       268 non-null    object 2   Age       268 non-null    float643   SibSp     268 non-null    int64  4   Parch     268 non-null    int64  5   Fare      268 non-null    float646   Embarked  267 non-null    object
dtypes: float64(2), int64(3), object(2)
memory usage: 16.8+ KB
None
说明

可以看到测试数据集中预测的Age值,同时观察到,训练集中Age的缺失值已经为0

【子任务项2.4】 使用众数填充Embarked字段的缺失值

  • Embarked字段只有2个缺失样本,因此直接采用众数填充
  • 在填充测试数据中缺失的Embarked字段时,也应采用训练集的众数填充
embarked_mode = X_train['Embarked'].mode().values[0]
print("Embarked字段的众数值:", embarked_mode)X_train.loc[X_train.Embarked.isnull(), 'Embarked'] = embarked_mode
X_test.loc[X_test.Embarked.isnull(), 'Embarked'] = embarked_modeprint(X_train.info())
print("=" * 100)
print(X_test.info())
Embarked字段的众数值: S
<class 'pandas.core.frame.DataFrame'>
Int64Index: 623 entries, 69 to 520
Data columns (total 7 columns):#   Column    Non-Null Count  Dtype
---  ------    --------------  -----  0   Pclass    623 non-null    int64  1   Sex       623 non-null    object 2   Age       623 non-null    float643   SibSp     623 non-null    int64  4   Parch     623 non-null    int64  5   Fare      623 non-null    float646   Embarked  623 non-null    object
dtypes: float64(2), int64(3), object(2)
memory usage: 38.9+ KB
None
====================================================================================================
<class 'pandas.core.frame.DataFrame'>
Int64Index: 268 entries, 205 to 277
Data columns (total 7 columns):#   Column    Non-Null Count  Dtype
---  ------    --------------  -----  0   Pclass    268 non-null    int64  1   Sex       268 non-null    object 2   Age       268 non-null    float643   SibSp     268 non-null    int64  4   Parch     268 non-null    int64  5   Fare      268 non-null    float646   Embarked  268 non-null    object
dtypes: float64(2), int64(3), object(2)
memory usage: 16.8+ KB
None
说明

可见,Embarked字段已经没有缺失值

【子任务项2.5】 Sex字段转换成数值1和0

将female取值转换成0,male取值转换成1

X_train.loc[X_train.Sex=='male', 'Sex'] = 1
X_train.loc[X_train.Sex=='female', 'Sex'] = 0
X_test.loc[X_test.Sex=='male', 'Sex'] = 1
X_test.loc[X_test.Sex=='female', 'Sex'] = 0print(X_train.head())
print("=" * 100)
print(X_test.head())
     Pclass Sex       Age  SibSp  Parch     Fare Embarked
69        3   1  26.00000      2      0   8.6625        S
85        3   0  33.00000      3      0  15.8500        S
794       3   1  25.00000      0      0   7.8958        S
161       2   0  40.00000      0      0  15.7500        S
815       1   1  39.30681      0      0   0.0000        S
====================================================================================================Pclass Sex   Age  SibSp  Parch     Fare Embarked
205       3   0   2.0      0      1  10.4625        S
44        3   0  19.0      0      0   7.8792        Q
821       3   1  27.0      0      0   8.6625        S
458       2   0  50.0      0      0  10.5000        S
795       2   1  39.0      0      0  13.0000        S
说明

可见,Sex字段值已经转换成0、1数值

【子任务项2.6】 Embarked字段转换成OneHot编码

  • Embarked字段有3个取值,OneHot编码之后,将产生三个字段(字段取名为Embarked_x),每个字段的取值为0或1
  • 删除原有的Embarked字段
from sklearn.preprocessing import OneHotEncoderencoder = OneHotEncoder()
encoder.fit(X_train.loc[:, ['Embarked']])    # 即使只有1个列,也必须将列名写在[]中# 分别针对训练集和测试集进行OneHot编码
train_onehot = encoder.transform(X_train.loc[:, ['Embarked']]).toarray()    # 使用toarray获得转换以后的OneHot编码数组
test_onehot = encoder.transform(X_test.loc[:, ['Embarked']]).toarray()    # 使用toarray获得转换以后的OneHot编码数组# 新增编码后的字段
index = 0
for index in range(train_onehot.shape[1]):category_name = encoder.categories_[0][index]    # 获取OneHot编码后对应的第index个类别名称X_train['Embarked_' + category_name] = train_onehot[:, index]    # 将对应类别(字段)的编码数值增加到df中X_test['Embarked_' + category_name] = test_onehot[:, index]# 删除原有Embarked字段
X_train.drop(['Embarked'], axis=1, inplace=True)
X_test.drop(['Embarked'], axis=1, inplace=True)# 打印前5行数据
print(X_train.head())
print("=" * 100)
print(X_test.head())
     Pclass Sex       Age  SibSp  Parch     Fare  Embarked_C  Embarked_Q  \
69        3   1  26.00000      2      0   8.6625         0.0         0.0
85        3   0  33.00000      3      0  15.8500         0.0         0.0
794       3   1  25.00000      0      0   7.8958         0.0         0.0
161       2   0  40.00000      0      0  15.7500         0.0         0.0
815       1   1  39.30681      0      0   0.0000         0.0         0.0   Embarked_S
69          1.0
85          1.0
794         1.0
161         1.0
815         1.0
====================================================================================================Pclass Sex   Age  SibSp  Parch     Fare  Embarked_C  Embarked_Q  \
205       3   0   2.0      0      1  10.4625         0.0         0.0
44        3   0  19.0      0      0   7.8792         0.0         1.0
821       3   1  27.0      0      0   8.6625         0.0         0.0
458       2   0  50.0      0      0  10.5000         0.0         0.0
795       2   1  39.0      0      0  13.0000         0.0         0.0   Embarked_S
205         1.0
44          0.0
821         1.0
458         1.0
795         1.0
说明
  • 已经删除了原有的Embarked字段,并且增加了Embarked_C、Embarked_Q和Embarked_S三个OneHot编码字段
  • Age字段和Fare字段的值域范围较大,因此可以考虑给它们做标准化或归一化处理

【子任务项2.7】数据标准化处理

如上所述,Age和Fare字段需要进行标准化和归一化处理。此处采用标准化处理方式。
注意测试数据集也要使用训练集的参数进行标准化处理

from sklearn.preprocessing import StandardScalerscaler = StandardScaler()
X_train[['Age', 'Fare']] = scaler.fit_transform(X_train[['Age', 'Fare']])
X_test[['Age', 'Fare']] = scaler.transform(X_test[['Age', 'Fare']])print(X_test.head())
     Pclass Sex       Age  SibSp  Parch      Fare  Embarked_C  Embarked_Q  \
205       3   0 -2.076413      0      1 -0.427985         0.0         0.0
44        3   0 -0.815021      0      0 -0.477484         0.0         1.0
821       3   1 -0.221425      0      0 -0.462475         0.0         0.0
458       2   0  1.485164      0      0 -0.427266         0.0         0.0
795       2   1  0.668970      0      0 -0.379363         0.0         0.0   Embarked_S
205         1.0
44          0.0
821         1.0
458         1.0
795         1.0
说明

经过归一化处理之后,Age和Fare字段的值域范围进行了缩放

【任务3】 构建基础模型并评估性能

【子任务项3.1】 训练逻辑回归模型

  • Survived字段作为标签(列下标索引为0),其余字段作为特征,训练LogisticRegression模型
  • 使用predict函数,直接预测每个样本的分类结果(0或1)
  • 使用predict_proba函数,获得预测的每个样本的分类概率(0~1)。该函数针对每个样本分别计算其属于分类0和分类1的概率(两个概率之和为1)
from sklearn.linear_model import LogisticRegression# 训练模型
model = LogisticRegression()
model.fit(X_train, y_train)# 从测试数据中取出前10条数据,预测其分类结果
number = 10
predicts = model.predict(X_test.iloc[:number, :])# 预测每个样本的分类概率
predicts_prob =model.predict_proba(X_test.iloc[:number, :])# 将预测样本的特征和结果合并显示
results = X_test.iloc[:number, :].copy()
results['Survived'] = y_test[:number]
results['Predicted'] = predicts
results['Predicts_prob_0'] = predicts_prob[:, 0]    # 获取分类结果为1(生还)的预测概率
results['Predicts_prob_1'] = predicts_prob[:, 1]    # 获取分类结果为1(生还)的预测概率
print(results)
     Pclass Sex       Age  SibSp  Parch      Fare  Embarked_C  Embarked_Q  \
205       3   0 -2.076413      0      1 -0.427985         0.0         0.0
44        3   0 -0.815021      0      0 -0.477484         0.0         1.0
821       3   1 -0.221425      0      0 -0.462475         0.0         0.0
458       2   0  1.485164      0      0 -0.427266         0.0         0.0
795       2   1  0.668970      0      0 -0.379363         0.0         0.0
118       1   1 -0.444023      0      1  4.114350         1.0         0.0
424       3   1 -0.889220      1      1 -0.241162         0.0         0.0
678       3   0  0.965768      1      6  0.270204         0.0         0.0
269       1   0  0.372172      0      0  1.970445         0.0         0.0
229       3   0 -1.861042      3      1 -0.140485         0.0         0.0   Embarked_S  Survived  Predicted  Predicts_prob_0  Predicts_prob_1
205         1.0         0          1         0.229934         0.770066
44          0.0         1          1         0.290268         0.709732
821         1.0         1          0         0.900322         0.099678
458         1.0         1          1         0.323410         0.676590
795         1.0         0          0         0.826048         0.173952
118         0.0         0          1         0.300159         0.699841
424         1.0         0          0         0.913576         0.086424
678         1.0         0          0         0.830145         0.169855
269         1.0         1          1         0.063346         0.936654
229         1.0         0          1         0.439897         0.560103
说明
  • 前10个测试样本中,只有6个样本被正确的预测
  • 可以看到,默认情况下,概率阈值以0.5为界,来确定其最终的分类结果

【子任务项3.2】 评估模型的性能指标

针对测试数据,检测模型的正确率、精度、召回率和F1 Score。
可以调用模型的score方法计算正确率, 使用sklearn.metrics的precision_score, recall_score, f1_score方法来计算其它指标。

from sklearn.metrics import precision_score, recall_score, f1_scoreaccuracy = model.score(X_test, y_test)# 预测测试数据的结果
predicts = model.predict(X_test)
precision = precision_score(y_test, predicts)
recall = recall_score(y_test, predicts)
f1 = f1_score(y_test, predicts)print("正确率:%.3f, 精度:%.3f, 召回率:%.3f, F1:%.3f" % (accuracy, precision, recall, f1))
正确率:0.791, 精度:0.785, 召回率:0.670, F1:0.723
说明
  • 针对所有测试数据的正确率为0.79,只能说一般。
  • 精度较高,说明把原本为0(死亡)的样本错判为1(生还)的数量较少
  • 召回率较低,说明把原本为1(生还)的样本漏判为0(死亡)的数量较多
  • 可以尝试降低概率阈值,从而使得更多的样本被判别为1,从而减少漏判,提高召回率

【子任务项3.3】 查看混淆矩阵并手动计算前述指标

sklearn.metrics.confusion_matrix可根据真实分类结果和预测结果,统计TP/FP/TN/FN的数量值

from sklearn.metrics import confusion_matrixpredicts = model.predict(X_test)
confusion_matrix_model = confusion_matrix(y_test, predicts)
print(confusion_matrix_model)
[[139  20][ 36  73]]
说明
  • 返回的2x2混淆矩阵中:

    • 索引为0的行代表实际结果为0(死亡),索引为1的行代表实际结果为1(生还)
    • 索引为0的列代表预测结果为0,索引为1的列代表预测结果为1
  • 因此:
    • 行列索引[0,0]的元素是139,代表有139个样本预测为死亡(0),而且实际结果也是死亡(0)。(正确查出了分类为0的样本,TN)
    • 行列索引[0,1]的元素是20,代表有20个样本预测为生还(1),但实际结果为死亡(0)。(预测错误,相当于误报,FP)
    • 行列索引[1,0]的元素为36,代表有36个样本预测为死亡(0),但实际结果为生还(1)。(预测错误,相当于漏报,FN)
    • 行列索引[1,1]的元素为73,代表有73个样本预测为生还(1),而且实际结果也是生还(1)。(正确查出了分类为1的样本,TP)
  • 根据上述结果可手动计算:
    • $ Precision= \frac{#TP}{#TP+#FP} = \frac{73}{73+20}=0.785$
    • $ Recall= \frac{#TP}{#TP+#FN} = \frac{73}{73+36}=0.669$
    • 这些结果与前述计算一致

【子任务项3.4】 自动生成指标报表

sklearn.metrics.classification_report可针对逻辑回归模型自动生成综合性能指标报表

from sklearn.metrics import classification_reportpredicts = model.predict(X_test)
print(classification_report(y_test, predicts))
              precision    recall  f1-score   support0       0.79      0.87      0.83       1591       0.78      0.67      0.72       109accuracy                           0.79       268macro avg       0.79      0.77      0.78       268
weighted avg       0.79      0.79      0.79       268
说明
  • (除标题外)第一行:统计分类标签为0的预测结果性能。

    • support=159,是指真实结果为0的样本数为159个
    • precision=0.79,是指所有预测结果为0的样本中,有79%的样本是正确的
    • recall=0.87,是指所有真实结果为0的样本中,有87%的样本被正确的预测出来了
    • f1-score=(20.790.87)/(0.79+0.87)=0.83
  • 第二行:统计分类标签为1的预测结果性能
    • support=109,是指真实结果为1的样本数为109个
    • precision=0.78,是指所有预测结果为1的样本中,有78%的样本是正确的
    • recall=0.67,是指所有真实结果为1的样本中,有67%的样本是正确的
    • f1-score=(20.780.67)/(0.78+0.67)=0.0.72
  • accuracy:统计所有预测正确的样本占总样本的比率(与Score方法计算结果一致)
  • macro avg和weight avg在此处不做分析

【子任务项3.5】 调整分类阈值并观察对结果的影响

  • 计算样本分类结果的概率值
  • 指定分类阈值K(此处设为0.4,而不是默认的0.5)
  • 对于每一个样本的预测概率,如果分类1的概率大于K,那么其分类结果就为1,否则为0
predicts_prob = model.predict_proba(X_test)
K = 0.4
# 对于每一个样本的预测概率,如果分类1的概率大于K,那么其分类结果就为1,否则为0
predicts = [1 if prob[1] > K else 0 for prob in predicts_prob]# 手动计算正确率
corrects = np.sum(predicts == y_test)
accuracy = corrects / len(y_test)precision = precision_score(y_test, predicts)
recall = recall_score(y_test, predicts)
f1 = f1_score(y_test, predicts)print("正确率:%.2f, 精度:%.2f, 召回率:%.2f, F1:%.2f" % (accuracy, precision, recall, f1))
正确率:0.81, 精度:0.78, 召回率:0.73, F1:0.75
说明
  • 将域值调整为0.4后,发现召回率有所提升。这意味着,一个样本只要有40%的概率被分类为1(存活),那么其预测的分类结果就为1。这就使得更多原本被预测为0的样本转向预测为1,从而提高了漏判。
  • 可以尝试其它的K值,观察各个指标的效果。事实上,应该根据实际的业务含义,合理调整阈值K
拓展说明

关于泰坦尼克号乘客生还预测的实验到此结束。【dataset/titanic_test.csv】中另外存放了一批乘客信息(不包含标签Survived字段)。可尝试使用上述模型对这些信息进行预测,并将预测结果提交到Kaggle平台来检查正确率。详情请看链接https://www.kaggle.com/c/titanic

【任务4】 非线性可分处理(拓展)

【子任务项4.1】 线性可分的二分类及决策边界线

【dataset/exam_score.csv】文件存放了一系列学生成绩数据,每个样本包括两个特征字段:exam1_score(分数1)、exam2_score(分数2)和1个标签passed(总成绩是否通过)。要求:

  • 建立一个逻辑回归模型,根据两个分数预测是否通过
  • 绘制决策边界线

分析

  • 数据可视化:对于只有2个特征的模型而言,可以用X和Y两个坐标分别代表特征,用不同颜色的点代表分类
  • 不同分类的数据点之间,可以通过平面上的一条曲线来分割,该曲线实际上是使得逻辑回归判别式值等于0.5的曲线。但是如果有更多维度,则不容易绘制决策边界线。

(1)查看数据样本分布情况

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inlinetrainData = np.loadtxt(open('dataset/exam_score.csv', 'r'), delimiter=",", skiprows=1)
x1 = trainData[:,0]         # 第一个特征
x2 = trainData[:,1]         # 第二个特征
y = trainData[:,2]          # 标签结果def initPlot():plt.figure()plt.title('Data for ')plt.xlabel('Feature 1')plt.ylabel('Feature 2')return pltplt = initPlot()
score1ForPassed = trainData[trainData[:,2] == 1, 0]    # 标签结果为1(通过)的样本点的第一特征值(exam1_score)
score2ForPassed = trainData[trainData[:,2] == 1, 1]    # 标签结果为1(通过)的样本点的第一特征值(exam1_score)
score1ForUnpassed = trainData[trainData[:,2] == 0, 0]
score2ForUnpassed = trainData[trainData[:,2] == 0, 1]
plt.plot(score1ForPassed,score2ForPassed,'r+')
plt.plot(score1ForUnpassed,score2ForUnpassed,'ko')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hH52B8NJ-1626015050077)(output_48_0.png)]

说明
  • 横坐标为exam1_score的值,纵坐标为exam2_score的值
  • 左下部分黑色点表示分类为0(不通过)的数据点,右上部分红色点表示分类为1(通过)的数据点。大致来看,可以用一条左上到右下的直线来分割不同分类的样本,也就是说这些样本点是【线性可分的】
  • 该分割线(决策边界线)只需要两个样本点就可以确定(一条直线)。

(2)数据预处理及构建逻辑回归模型

  • 特征标准化处理
  • 训练LogisticRegression模型
  • 用模型预测几个测试样本
# 准备数据
X_train = trainData[:,[0,1]]
y_train = trainData[:,2]model = LogisticRegression()
model.fit(X_train, y_train)
# 给定4个用于测试的样本的特征
newScores = np.array([[58, 67],[90, 90],[35, 38],[55, 56]])print("预测结果:")
print(model.predict(newScores))
预测结果:
[1. 1. 0. 0.]
说明

4个样本,前2个预测结果为1(通过),后两个预测结果为0(不通过)

(3)绘制决策边界线

  • 首先获得已训练好的模型的权重参数(w0,w1,w2w_0, w_1, w_2w0​,w1​,w2​)
  • 决策边界线上的点,实际上就是【最不能确定分类结果】的点,或者说其分类概率为0.5,此时相当于: g(w0+w1x1+w2x2)=0.5g(w_0 + w_1 x_1 + w_2 x_2)=0.5g(w0​+w1​x1​+w2​x2​)=0.5,也即:w0+w1x1+w2x2=0w_0 + w_1 x_1 + w_2 x_2=0w0​+w1​x1​+w2​x2​=0
  • 应为采用线性分割,只需要任意给定2个点的横坐标(x1x_1x1​),代入上式即可求出对那个的纵坐标(x2x_2x2​),最后绘制通过这两个点的直线
# 获取权重参数w0,w1和w2
W = np.array([model.intercept_[0], model.coef_[0,0], model.coef_[0,1]])plt = initPlot()
score1ForPassed = trainData[trainData[:,2] == 1, 0]
score2ForPassed = trainData[trainData[:,2] == 1, 1]
score1ForUnpassed = trainData[trainData[:,2] == 0, 0]
score2ForUnpassed = trainData[trainData[:,2] == 0, 1]
plt.plot(score1ForPassed,score2ForPassed,'r+')
plt.plot(score1ForUnpassed,score2ForUnpassed,'ko')# 绘制决策边界线
boundaryX = np.array([30, 100])                 # 给定任意两个样本点的横坐标
boundaryY = -(W[1] * boundaryX + W[0]) / W[2]   # 计算对应的纵坐标
plt.plot(boundaryX, boundaryY, 'b-')    # 连接边界线上的两个点plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X64cpATW-1626015050078)(output_54_0.png)]

说明
  • 蓝色决策边界线,较好的(注意不是完全的)将不同分类的样本点隔开
  • 边界线右上的样本点,将被划入类别1;左下的样本点,将被划入类别0

【子任务项4.2】 线性不可分数据的处理

【dataset/non_linear.csv.csv】文件包括两个特征字段和1个分类结果。要求:

  • 建立一个逻辑回归模型能够较好的分割不同类别的样本
  • 绘制决策边界线

(1)查看数据样本分布情况

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inlinetrainData = np.loadtxt(open('dataset/non_linear.csv', 'r'), delimiter=",", skiprows=0)
x1 = trainData[:,0]         # 第一个变量
x2 = trainData[:,1]         # 第二个变量
y = trainData[:,2]          # 因变量def initPlot():plt.figure()plt.title('Data for ')plt.xlabel('Feature 1')plt.ylabel('Feature 2')return pltplt = initPlot()
score1ForPassed = trainData[trainData[:,2] == 1, 0]
score2ForPassed = trainData[trainData[:,2] == 1, 1]
score1ForUnpassed = trainData[trainData[:,2] == 0, 0]
score2ForUnpassed = trainData[trainData[:,2] == 0, 1]
plt.plot(score1ForPassed,score2ForPassed,'r+')
plt.plot(score1ForUnpassed,score2ForUnpassed,'ko')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BEHZWj2Z-1626015050080)(output_58_0.png)]

说明

可见,上述样本是线性不可分的,无法使用一条直线来较好的分割不同类别的样本点

(2)构建高阶/多维特征

  • 既然线性计算无法满足要求,则可考虑高阶计算,把原始的2个特征,扩展称为多个高阶字段。本例采用最高6阶的计算式:
    $ \begin{aligned}
    & w_0 + w_1 x_1+ w_2 x_2+ w_3 x_1^2+ w_4 x_1 x_2 + w_5 x_2^2+ w_6 x_1^3+ w_7 x_1^2 x_2 + w_8 x_1 x_2^2+ w_9 x_2^3+ \cdots \+ & w_{21} x_1^6+w_{22} x_1^5 x_2 + w_{23} x_1^4 x_2^2+ w_{24} x_1^3 x_2^3+ w_{25} x_1^2 x_2^4+ w_{26} x_1 x_2^5+ w_{27} x_2^6
    \end{aligned} $
    将x1x_1x1​和x2x_2x2​两个自变量的值,按照上述多项式的各个项进行乘方、乘积运算,得到有28项的一个高阶表达式
  • 虽然变成了高阶数据,但根据【高阶变多维】的思想,可视为均为一阶的28维特征,从而仍然可以使用逻辑回归
    下面的代码生成了6阶的特征数组(28个维度):
def mapFeatures(x1, x2):            # 生成6阶双变量的多项式拟合特征值矩阵rowCount = len(x1)colIndex = 1                    # 第0列为Intercept Item,无需进行计算features = np.ones((rowCount, FEATURE_COUNT))for i in np.arange(1, DEGREE + 1):        # 1,2,3....DEGREEfor j in np.arange(0, i + 1):         # 0,1,2...ifeatures[:, colIndex] = (x1 ** (i - j)) * (x2 ** j)      # 每个循环计算1列FeaturecolIndex = colIndex + 1return features# 定义全局变量
DEGREE = 6                  # 最高为6阶
FEATURE_COUNT = 28          # 两个变量,6阶公式,共28个Feature(含Intercept Item)
ROW_COUNT = len(trainData)  # 总行数
features = mapFeatures(x1, x2)      # 获得一个ROW_COUNT x FEATURE_COUNT维度的特征值数组
print("高阶特征矩阵的维度:", features.shape)    # 每个样本都拥有28个维度
高阶特征矩阵的维度: (118, 28)

(3)建立逻辑回归模型(不带惩罚项)

  • 设置penalty=‘none’(不带惩罚项)
  • 观察各个权重参数的取值
X_train = features
y_train = trainData[:,2]model = LogisticRegression(penalty='none', max_iter=2000)
model.fit(X_train, y_train)
print("截距项:", model.intercept_[0])
print("权重参数:", model.coef_[0])
截距项: 13.805214927591399
权重参数: [   13.80521493    41.32782962    40.70132754  -280.85788491-152.60128169  -130.58982339  -299.39921416  -464.90952213-328.27047934  -144.13859136   944.5933964   1006.565355141300.86067248   619.81271183   249.08387005   501.859086811084.70837594  1402.01857905  1175.93373061   564.27758173159.45797961 -1047.61826184 -1743.79125559 -2795.08309536-2483.86639601 -2035.87732905  -854.59244568  -213.22468803]c:\users\iahuo\appdata\local\programs\python\python38\lib\site-packages\sklearn\linear_model\_logistic.py:763: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.Increase the number of iterations (max_iter) or scale the data as shown in:https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:https://scikit-learn.org/stable/modules/linear_model.html#logistic-regressionn_iter_i = _check_optimize_result(
说明
  • 即使在2000次迭代运算情况下,仍没有收敛
  • 此时获得的权重参数量级都较大

(4)绘制边界线

此时边界线不再是直线,因此在绘制时,必须给定大量点的横坐标和纵坐标,然后代入到判别式中计算出其对应的分类结果(0或1),最后使用等高线图显示高度值为0.5(决策阈值)的等高线

plt = initPlot()
score1ForPassed = trainData[trainData[:,2] == 1, 0]
score2ForPassed = trainData[trainData[:,2] == 1, 1]
score1ForUnpassed = trainData[trainData[:,2] == 0, 0]
score2ForUnpassed = trainData[trainData[:,2] == 0, 1]
plt.plot(score1ForPassed,score2ForPassed,'r+')
plt.plot(score1ForUnpassed,score2ForUnpassed,'ko')# 生成若干个样本点
plotX1 = np.linspace(-1, 1.5, 50)
plotX2 = np.linspace(-1, 1.5, 50)
Z = np.zeros((len(plotX1), len(plotX2)))
for i in np.arange(0, len(plotX1)):                         # 每次预测一列点a1 = [plotX1[i] for _ in np.arange(0, len(plotX2))]plotFeatures = mapFeatures(a1, plotX2)Z[i,:] = model.predict(plotFeatures)
plt.contour(plotX1, plotX2, Z, levels=[0.5])    # 取Z=0.5作为决策边界plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2xW3ng7-1626015050081)(output_66_0.png)]

说明

很显然,虽然分割的效果不错,但是已经产生了过拟合

【子任务项4.4】 使用惩罚项解决过拟合问题

  • 设置L2惩罚项,并提供不同的惩罚系数
  • 查看每种惩罚系数对应的边界线效果

(1)λ=10\lambda=10λ=10,对应C=0.1C=0.1C=0.1

model = LogisticRegression(C=0.1)
model.fit(X_train, y_train)
print("截距项:", model.intercept_[0])
print("权重参数:", model.coef_[0])plt = initPlot()
score1ForPassed = trainData[trainData[:,2] == 1, 0]
score2ForPassed = trainData[trainData[:,2] == 1, 1]
score1ForUnpassed = trainData[trainData[:,2] == 0, 0]
score2ForUnpassed = trainData[trainData[:,2] == 0, 1]
plt.plot(score1ForPassed,score2ForPassed,'r+')
plt.plot(score1ForUnpassed,score2ForUnpassed,'ko')# 生成若干个样本点
plotX1 = np.linspace(-1, 1.5, 50)
plotX2 = np.linspace(-1, 1.5, 50)
Z = np.zeros((len(plotX1), len(plotX2)))
for i in np.arange(0, len(plotX1)):                         # 每次预测一列点a1 = [plotX1[i] for _ in np.arange(0, len(plotX2))]plotFeatures = mapFeatures(a1, plotX2)Z[i,:] = model.predict(plotFeatures)
plt.contour(plotX1, plotX2, Z, levels=[0.5])    # 取Z=0.5作为决策边界plt.show()
截距项: 0.3261743348125194
权重参数: [ 4.80060874e-06 -8.15346950e-03  1.65795385e-01 -4.46717768e-01-1.11773868e-01 -2.78919687e-01 -7.14543762e-02 -5.78891579e-02-6.50971508e-02 -1.06370649e-01 -3.36728581e-01 -1.29717223e-02-1.16707334e-01 -2.80967442e-02 -2.86026426e-01 -1.16148883e-01-3.70447251e-02 -2.24215126e-02 -4.88657219e-02 -4.16295811e-02-1.86754269e-01 -2.53337925e-01 -2.91085963e-03 -5.79667693e-02-5.28007020e-04 -6.35287458e-02 -1.20640539e-02 -2.71483918e-01]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k3id7uQD-1626015050082)(output_70_1.png)]

说明
  • 权重参数的量级大为减小
  • 从边界线来看,大量样本点分错,产生欠拟合

(2)λ=0.1\lambda=0.1λ=0.1,对应C=10C=10C=10

model = LogisticRegression(C=10)
model.fit(X_train, y_train)plt = initPlot()
score1ForPassed = trainData[trainData[:,2] == 1, 0]
score2ForPassed = trainData[trainData[:,2] == 1, 1]
score1ForUnpassed = trainData[trainData[:,2] == 0, 0]
score2ForUnpassed = trainData[trainData[:,2] == 0, 1]
plt.plot(score1ForPassed,score2ForPassed,'r+')
plt.plot(score1ForUnpassed,score2ForUnpassed,'ko')# 生成若干个样本点
plotX1 = np.linspace(-1, 1.5, 50)
plotX2 = np.linspace(-1, 1.5, 50)
Z = np.zeros((len(plotX1), len(plotX2)))
for i in np.arange(0, len(plotX1)):                         # 每次预测一列点a1 = [plotX1[i] for _ in np.arange(0, len(plotX2))]plotFeatures = mapFeatures(a1, plotX2)Z[i,:] = model.predict(plotFeatures)
plt.contour(plotX1, plotX2, Z, levels=[0.5])    # 取Z=0.5作为决策边界plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0VjK9ZbZ-1626015050083)(output_73_0.png)]

说明

此种情况较好,基本能反映样本点的分类情况

(3)λ=0.001\lambda=0.001λ=0.001,对应C=1000C=1000C=1000

model = LogisticRegression(C=1000)
model.fit(X_train, y_train)plt = initPlot()
score1ForPassed = trainData[trainData[:,2] == 1, 0]
score2ForPassed = trainData[trainData[:,2] == 1, 1]
score1ForUnpassed = trainData[trainData[:,2] == 0, 0]
score2ForUnpassed = trainData[trainData[:,2] == 0, 1]
plt.plot(score1ForPassed,score2ForPassed,'r+')
plt.plot(score1ForUnpassed,score2ForUnpassed,'ko')# 生成若干个样本点
plotX1 = np.linspace(-1, 1.5, 50)
plotX2 = np.linspace(-1, 1.5, 50)
Z = np.zeros((len(plotX1), len(plotX2)))
for i in np.arange(0, len(plotX1)):                         # 每次预测一列点a1 = [plotX1[i] for _ in np.arange(0, len(plotX2))]plotFeatures = mapFeatures(a1, plotX2)Z[i,:] = model.predict(plotFeatures)
plt.contour(plotX1, plotX2, Z, levels=[0.5])    # 取Z=0.5作为决策边界plt.show()
c:\users\iahuo\appdata\local\programs\python\python38\lib\site-packages\sklearn\linear_model\_logistic.py:763: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.Increase the number of iterations (max_iter) or scale the data as shown in:https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:https://scikit-learn.org/stable/modules/linear_model.html#logistic-regressionn_iter_i = _check_optimize_result(

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IMuWYCVU-1626015050084)(output_76_1.png)]

说明

此时有过拟合之嫌。可以进一步推算,如果继续增加C的值,将逐渐相当于没有惩罚项(严重过拟合)

【任务5】 多分类处理(拓展)

前述介绍的逻辑回归能够较好的判断结果是1或0的情形(两种类别)。但是现实中,结果往往有多种类别。例如,判断某个手写出来的阿拉伯数字是0-9中的哪一个,这就有10个类别。
【dataset/digits_training.csv】存放了5000张手写数字图片的像素信息,每行代表一张图片,每列代表一个像素值(二维像素数组展开成一维数组)。
【dataset/digits_testing.csv】存放了500个用于测试的数据。
要求:训练逻辑回归模型,是之能够根据像素数组识别出对应的0~9数字分类

分析

  • 准备训练数据
    为了使机器学习具有一定的准确性,需要提供足量的训练数据。本例中,我们准备提供0~9这10个数字的手写图片总共5000张(另有500张测试图片),并且:

    • 每张图片都已经标记好其对应的数字值(称为“分类标签”或Label)
    • 为了便于计算机统一处理,每张图片都是28x28像素
    • 每张图片都是灰度图(即:每个像素的取值从0~255,0为白色,255为黑色),这样就省去了处理RGB彩色的负担
    • 上述所有训练样本数据已经存放在【digits_training.csv】中,测试样本数据都存放在【digits_testing.csv】中
  • 准备好训练数据的特征值矩阵

    • 对于一张图片,我们准备一个一维数组,将该图片对应的数字(Label)放在数组的第一个元素;然后将图片中每个像素点的值,按行依次连续存放在数组后面的元素中。最终该数组的共有1+28x28=785个元素
    • 将这5000张图片的数据放置在一个二维数组中,容量是:5000x785。这样就构成了一个训练矩阵。
    • 因为像素值在0~255之间,跨度较大,因此必须对训练数据进行归一化(Normalization)。考虑到灰度图每个像素的最大值就是255,因此本例直接使用$ X=\dfrac{x_i-\bar{x_i}}{255},这样每个特征值都在,这样每个特征值都在,这样每个特征值都在[-1,1]$之间
    • 在本例中,我们直接从灰度图像素中提取特征值,这是最简单的提取方法
  • 使用逻辑回归进行分类

    • 有了特征值和Lable矩阵,就可以使用某种机器学习算法进行训练了。
    • 逻辑回归能够较好的进行分类。但是上一章讲的逻辑回归只能分成两个类别。因此需要考虑如何将2-Classes的分类扩展到N-Classes的分类
  • 使用得到的假设公式进行预测

    • 训练完成后,就得到了假设公式
    • 将待预测的图片(也必须是28x28的灰度图),读取到一个一维数组中(784个元素,没有Label)。然后就可以代入到假设公式中进行预测。预测的结果应该能告知是0~9中的哪个数
  • 使用测试数据进行验证

    • 为了判断该假设公式的有效性,需要另外找一批图片(本例中500张)进行验证。
    • 测试数据也需要先进行归一化处理
    • 本例仅统计出预测正确的图片数量占总图片数量的比重(正确率)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
%matplotlib inline# 使用简单的归一化处理
def normalizeData(X, col_avg):return (X - col_avg) / 255trainData = np.loadtxt(open('dataset/digits_training.csv', 'r'), delimiter=",",skiprows=1)
MTrain, NTrain = np.shape(trainData)
xTrain = trainData[:,1:NTrain]
xTrain_col_avg = np.mean(xTrain, axis=0)
xTrain = normalizeData(xTrain, xTrain_col_avg)
yTrain = trainData[:,0]
print("装载训练数据:", MTrain, "条,训练中......")model = LogisticRegression(solver='lbfgs', multi_class='multinomial', max_iter=500)
model.fit(xTrain, yTrain)print("训练完毕")
testData = np.loadtxt(open('dataset/digits_testing.csv', 'r'), delimiter=",",skiprows=1)
MTest,NTest = np.shape(testData)
xTest = testData[:,1:NTest]
xTest = normalizeData(xTest, xTrain_col_avg)    # 使用训练数据的列均值进行处理
yTest = testData[:,0]
print("装载测试数据:", MTest, "条,预测中......")yPredict = model.predict(xTest)
errors = np.count_nonzero(yTest - yPredict)
print("预测完毕。错误:", errors, "条")
print("测试数据正确率:", (MTest - errors) / MTest)
装载训练数据: 5000 条,训练中......
训练完毕
装载测试数据: 500 条,预测中......
预测完毕。错误: 54 条
测试数据正确率: 0.892
说明

针对测试数据的预测正确率约为89.2%,对于手写数字图像识别而言,这实际上是一个很差的效果。使用深度学习和卷积神经网络,一般可达99%以上的正确率。这也在一定程度上说明了,简单的机器学习可能并不太适合处理图像问题。

信用评分卡DAY8-9相关推荐

  1. 信用评分卡模型的理论准备

    目录 0 前言 1 构建评分卡的整个流程图 2 信息值 IV(Information Value)和 证据权重 WOE(Weight of Evidence) 2.1 WOE 定义 2.2 IV 定义 ...

  2. 基于R的信用评分卡模型解析

    信用评分流程 1.数据获取 我使用的信贷数据共有3000条数据,每条数据11个特征. rm(list=ls()) setwd("D:\\case") library(xlsx) d ...

  3. r k-means 分类结果_R语言信用评分卡:数据分箱(binning)

    作者:黄天元,复旦大学博士在读,热爱数据科学与R,热衷推广R在工业界与学术界的应用.邮箱:huang.tian-yuan@qq.com.欢迎合作交流 library(knitr) opts_chunk ...

  4. 信用评分python_信用评分卡(python)

    目录 导入数据 缺失值和异常值处理 特征可视化 特征选择 模型训练 模型评估 模型结果转评分 计算用户总分 一.导入数据 #导入模块 importpandas as pdimportnumpy as ...

  5. python信用评分卡_基于Python的信用评分卡模型分析(二)

    上一篇文章基于Python的信用评分卡模型分析(一)已经介绍了信用评分卡模型的数据预处理.探索性数据分析.变量分箱和变量选择等.接下来我们将继续讨论信用评分卡的模型实现和分析,信用评分的方法和自动评分 ...

  6. 数据挖掘项目:银行信用评分卡建模分析(上篇)

    kaggle上的Give Me Some Credit一个8年前的老项目,网上的分析说明有很多,但本人通过阅读后,也发现了很多的问题.比如正常随着月薪越高,违约率会下降.但对于过低的月薪,违约率却为0 ...

  7. 数据挖掘项目:银行信用评分卡建模分析(下篇)

    以下是银行信用评分卡建模分析下篇的内容,包括特征工程,构建模型,模型评估,评分卡建立这四部分.其中如果有一些地方分析的不正确,希望大家多多指正,感谢! 上篇文章的链接:数据挖掘项目:银行信用评分卡建模 ...

  8. [机器学习] 信用评分卡中的应用 | 干货

    背景介绍与评分卡模型的基本概念 如今在银行.消费金融公司等各种贷款业务机构,普遍使用信用评分,对客户实行打分制,以期对客户有一个优质与否的评判.交易对手未能履行约定契约中的义务而造成经济损失的风险,即 ...

  9. 基于Python的信用评分卡建模分析

    1.背景介绍 信用评分技术是一种应用统计模型,其作用是对贷款申请人(信用卡申请人)做风险评估分值的方法.信用评分卡模型是一种成熟的预测方法,尤其在信用风险评估以及金融风险控制领域更是得到了比较广泛的使 ...

  10. 3分钟搞明白信用评分卡模型模型验证

    2019独角兽企业重金招聘Python工程师标准>>> 信用评分卡模型在国外是一种成熟的预测方法,尤其在信用风险评估以及金融风险控制领域更是得到了比较广泛的使用,其原理是将模型变量W ...

最新文章

  1. linux网卡设置adsl上网,Linux下设置ADSL自动拨号上网
  2. 总结2021面试中的常见14种算法套路
  3. Java BigDecimal常用方法
  4. 【C++】 二叉树的基本知识及其遍历
  5. SSM中怎样使用JUnit4+spring-test编写单元测试
  6. A - Promotions
  7. scrapy去重原理,scrapy_redis去重原理和布隆过滤器的使用
  8. 工厂模式 构建者模式_实践中的构建者模式
  9. C++ 11 深度学习(四)结构、权限修饰符
  10. 新代数控系统参数说明书_台湾新代宏程序编程书
  11. mac 不显示 外接屏幕_Mac外接屏幕亮度调整
  12. 企业IT构建核心基础架构解决方案
  13. apache hbase的region 分割与合并
  14. 阿里云数据森林人才计划起航
  15. DEDECMS 另类***
  16. 计算机文言,中国最具有概括性的文言文文字?本人学计算机编程的
  17. 计算机专业理论试题答案最新,2017年计算机一级考试题库及答案
  18. 如何用excel制作饼图
  19. 归纳法证明汉诺塔解析式思路
  20. 华南师范大学计算机学院男生宿舍,最全!广东68所本科高校宿舍汇总!你的宿舍豪华还是简陋?...

热门文章

  1. 使用JavaScript克隆元素
  2. python 二维列表_python二维列表
  3. 修改人人商城支付后报错“服务器暂时无法处理您的请求,请稍后重试“
  4. win10更新并关机怎么取消
  5. 【python爬虫】学习笔记1-爬取某网站妹子图片
  6. python如何计算平均分_python脚本如何输入成绩求平均分?
  7. python去掉最高分和最低分求平均飞_Excel里去掉最高分最低分再求平均分教程
  8. 制作京东快递查询 css制作三角形
  9. 【编译原理】语言认知之Java、Python、C++快速排序三者运行效率与开发效率比较
  10. Python使用Google多语言翻译Excel文档