当前位置:首页>python>零基础Python评分卡模型搭建

零基础Python评分卡模型搭建

  • 2026-09-06 04:32:03
零基础Python评分卡模型搭建

没学过编程?不懂统计学?别担心!跟着我,用最简单的方式搭建你的第一个风控模型。

前言:从“技术恐惧”到“风控自信”

3个月后,小张独立搭建的评分卡模型成功上线,将审批效率提升了40%。今天,我就把小张的“零基础逆袭秘籍”完整分享给你。

记住:风控的核心是业务思维,代码只是工具。

一、准备工作:像安装手机APP一样简单

1.1 安装Python环境(5分钟搞定)

别被“环境配置”吓到,跟着我做:

  1. 1. 下载Anaconda(就像下载微信一样简单)
    • • 打开浏览器,访问:https://www.anaconda.com/download
    • • 点击下载(Windows用户选Windows,Mac用户选MacOS)
    • • 双击安装包,全部点“下一步”直到完成
  2. 2. 打开Jupyter Notebook(我们的“代码记事本”)
    • • 在开始菜单找到“Anaconda3”
    • • 点击“Jupyter Notebook”
    • • 浏览器会自动打开一个新页面
  3. 3. 新建文件(创建你的第一个模型文件)
    • • 点击右上角“New”
    • • 选择“Python 3”
    • • 看到代码输入框了吗?恭喜,环境配置完成!

1.2 安装必要工具包(复制粘贴就行)

在代码输入框里,复制粘贴下面这段代码,然后按 Shift + Enter:

# 安装必要的包!pip install pandas numpy matplotlib scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple# 检查是否安装成功import pandas as pdimport numpy as npprint("安装成功!可以开始建模了。")

看到“安装成功”了吗?就这么简单!

二、第一步:准备数据 - 不用Excel,更简单

2.1 创建虚拟数据(就像填表格)

假设我们是某消费金融公司的风控专员,需要分析客户数据。我们先创建一个简单的数据集:

# 创建100个虚拟客户数据import pandas as pdimport numpy as np# 设置随机种子,确保每次结果一样np.random.seed(123)# 创建数据字典 - 就像填Excel表格data = {'客户ID': range(1, 101),  # 1到100号客户'年龄': np.random.randint(22, 55, 100),  # 22-55岁'月收入': np.random.randint(5000, 30000, 100),  # 5000-30000元'工作年限': np.random.randint(1, 20, 100),  # 1-20年'信用卡数量': np.random.randint(0, 5, 100),  # 0-4张'历史逾期': np.random.randint(0, 3, 100),  # 逾期0-2次'是否违约': np.random.choice([0, 1], 100, p=[0.85, 0.15])  # 85%好客户,15%坏客户}# 创建数据框(可以理解为智能Excel表格)df = pd.DataFrame(data)# 查看数据print("客户数据表:")print(df.head(10))  # 显示前10行print(f"\n共有{len(df)}个客户")print(f"其中{df['是否违约'].sum()}人违约,违约率{df['是否违约'].mean():.1%}")

运行后你会看到:

   客户ID  年龄  月收入  工作年限  信用卡数量  历史逾期  是否违约0      1  45  23456       8         2        0        01      2  38  12345      12         1        1        02      3  29  28765       3         3        0        1...共有100个客户其中15人违约,违约率15.0%

看!你已经有了100个客户的数据,包括年龄、收入、信用记录等。这比Excel简单多了,不是吗?

2.2 数据可视化 - 一图胜千言

让我们用图表更直观地看数据:

import matplotlib.pyplot as plt# 设置中文字体plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False# 创建画布fig, axes = plt.subplots(2, 2, figsize=(12, 10))# 1. 年龄分布axes[0, 0].hist(df['年龄'], bins=15, color='skyblue', edgecolor='black')axes[0, 0].set_xlabel('年龄')axes[0, 0].set_ylabel('人数')axes[0, 0].set_title('客户年龄分布')axes[0, 0].grid(True, alpha=0.3)# 2. 收入分布axes[0, 1].hist(df['月收入'], bins=15, color='lightgreen', edgecolor='black')axes[0, 1].set_xlabel('月收入(元)')axes[0, 1].set_ylabel('人数')axes[0, 1].set_title('客户收入分布')axes[0, 1].grid(True, alpha=0.3)# 3. 好坏客户比例bad_count = df['是否违约'].sum()good_count = len(df) - bad_countaxes[1, 0].pie([good_count, bad_count],                labels=['好客户', '坏客户'],               autopct='%1.1f%%',               colors=['lightblue', 'lightcoral'],               startangle=90)axes[1, 0].set_title('好坏客户比例')# 4. 各年龄段违约率# 将年龄分组df['年龄段'] = pd.cut(df['年龄'],                      bins=[20, 30, 40, 50, 60],                     labels=['20-30', '30-40', '40-50', '50-60'])default_by_age = df.groupby('年龄段')['是否违约'].mean()axes[1, 1].bar(default_by_age.index.astype(str),                default_by_age.values,               color='orange')axes[1, 1].set_xlabel('年龄段')axes[1, 1].set_ylabel('违约率')axes[1, 1].set_title('各年龄段违约率')axes[1, 1].grid(True, alpha=0.3)plt.tight_layout()plt.show()

运行代码后,你会看到4张图表。发现了什么?

  • • 哪个年龄段的客户最多?
  • • 收入主要集中在什么范围?
  • • 哪个年龄段的违约率最高?

这就是数据分析的魅力:用眼睛看数据,而不是凭感觉!

三、第二步:特征工程 - 创造“聪明”的特征

3.1 创建业务特征

原始数据有时不够用,我们需要创造更有意义的特征:

# 1. 创建负债收入比(重要指标!)# 假设每张信用卡平均负债5000元df['信用卡总负债'] = df['信用卡数量'] * 5000df['负债收入比'] = df['信用卡总负债'] / df['月收入']print("添加新特征后的数据:")print(df[['客户ID', '月收入', '信用卡数量', '信用卡总负债', '负债收入比']].head())# 2. 创建工作稳定性指标df['工作稳定性'] = df['工作年限'] / (df['年龄'] - 22)  # 假设22岁开始工作df['工作稳定性'] = df['工作稳定性'].fillna(0)  # 处理除零错误# 3. 查看新特征的分布fig, axes = plt.subplots(1, 2, figsize=(12, 4))axes[0].hist(df['负债收入比'], bins=20, color='purple', edgecolor='black', alpha=0.7)axes[0].set_xlabel('负债收入比')axes[0].set_ylabel('人数')axes[0].set_title('负债收入比分布')axes[0].grid(True, alpha=0.3)axes[1].hist(df['工作稳定性'], bins=20, color='teal', edgecolor='black', alpha=0.7)axes[1].set_xlabel('工作稳定性')axes[1].set_ylabel('人数')axes[1].set_title('工作稳定性分布')axes[1].grid(True, alpha=0.3)plt.tight_layout()plt.show()

3.2 特征与违约率的关系分析

让我们看看哪些特征与违约相关:

# 分析特征与违约率的关系print("特征与违约率的关系分析:")print("="*50)features_to_analyze = ['年龄', '月收入', '工作年限', '信用卡数量', '历史逾期', '负债收入比', '工作稳定性']for feature in features_to_analyze:# 将特征分成4组    df[f'{feature}_分组'] = pd.qcut(df[feature], 4, duplicates='drop')# 计算每组的违约率    default_rate = df.groupby(f'{feature}_分组')['是否违约'].mean()print(f"\n{feature}与违约率关系:")for group, rate in default_rate.items():print(f"  {group}: 违约率={rate:.1%}")# 可视化    plt.figure(figsize=(8, 4))    plt.bar(range(len(default_rate)), default_rate.values, color='steelblue')    plt.xticks(range(len(default_rate)),                [str(x) for x in default_rate.index], rotation=45)    plt.xlabel(f'{feature}分组')    plt.ylabel('违约率')    plt.title(f'{feature}与违约率关系')    plt.grid(True, alpha=0.3)    plt.tight_layout()    plt.show()

关键发现:

  • • 负债收入比越高,违约率越___?
  • • 收入越高,违约率越___?
  • • 历史逾期次数越多,违约率越___?

四、第三步:建立模型 - 三行代码搞定

4.1 准备建模数据

# 选择用于建模的特征selected_features = ['年龄', '月收入', '工作年限', '信用卡数量', '历史逾期', '负债收入比', '工作稳定性']X = df[selected_features]  # 特征数据y = df['是否违约']         # 目标变量(是否违约)print("特征数据形状:", X.shape)print("目标变量形状:", y.shape)print("\n前5个样本的特征数据:")print(X.head())

4.2 训练第一个模型(超级简单!)

from sklearn.model_selection import train_test_splitfrom sklearn.linear_model import LogisticRegression# 1. 分割数据(80%训练,20%测试)X_train, X_test, y_train, y_test = train_test_split(    X, y, test_size=0.2, random_state=42, stratify=y)print(f"训练集:{len(X_train)}个样本")print(f"测试集:{len(X_test)}个样本")print(f"训练集违约率:{y_train.mean():.1%}")print(f"测试集违约率:{y_test.mean():.1%}")# 2. 训练逻辑回归模型(就三行代码!)model = LogisticRegression(max_iter=1000, random_state=42)model.fit(X_train, y_train)print("\n🎉 模型训练完成!")print(f"模型参数数量:{len(model.coef_[0])}")print(f"模型截距:{model.intercept_[0]:.4f}")

4.3 模型评估 - 看看模型表现如何

from sklearn.metrics import accuracy_score, confusion_matrix# 1. 在测试集上预测y_pred = model.predict(X_test)y_pred_prob = model.predict_proba(X_test)[:, 1]  # 预测为违约的概率# 2. 计算准确率accuracy = accuracy_score(y_test, y_pred)print(f"模型准确率:{accuracy:.1%}")# 3. 计算AUC(风控核心指标)from sklearn.metrics import roc_auc_scoreauc = roc_auc_score(y_test, y_pred_prob)print(f"AUC值:{auc:.4f}")# AUC解释:0.5=瞎猜,0.7=不错,0.8=很好,1.0=完美if auc < 0.6:print("模型表现:需要改进")elif auc < 0.7:print("模型表现:一般")elif auc < 0.8:print("模型表现:良好")elif auc < 0.9:print("模型表现:优秀")else:print("模型表现:完美!")# 4. 混淆矩阵cm = confusion_matrix(y_test, y_pred)print(f"\n混淆矩阵:")print(f"预测为好且实际好:{cm[0, 0]}人")print(f"预测为好但实际坏:{cm[0, 1]}人(风险!)")print(f"预测为坏但实际好:{cm[1, 0]}人(损失客户)")print(f"预测为坏且实际坏:{cm[1, 1]}人")

4.4 模型解释 - 为什么这个客户被拒绝?

# 查看模型学到的规律print("模型学到的规律(特征重要性):")print("="*50)feature_importance = pd.DataFrame({'特征': selected_features,'系数': model.coef_[0],'系数绝对值': np.abs(model.coef_[0])}).sort_values('系数绝对值', ascending=False)print(feature_importance)print("\n📊 业务解读:")print("正系数表示增加违约概率,负系数表示减少违约概率")for _, row in feature_importance.iterrows():    effect = "增加违约风险"if row['系数'] > 0else"降低违约风险"print(f"{row['特征']}: {effect} (影响程度:{abs(row['系数']):.4f})")

五、第四步:评分卡转换 - 把概率变成分数

5.1 创建评分卡函数

defcreate_scorecard(prob, base_score=600, pdo=50, base_odds=30):"""    将违约概率转换为信用分数    参数:    prob: 违约概率(0-1之间)    base_score: 基准分数(当好坏比为base_odds:1时的分数)    pdo: 好坏比翻倍所需的分数变化    base_odds: 基准好坏比    公式:分数 = base_score + pdo * log2(好坏比/基准好坏比)    """    odds = (1 - prob) / (prob + 1e-10)  # 计算好坏比    score = base_score + pdo * np.log2(odds / base_odds)return np.clip(score, 300, 850)  # 限制在300-850分之间# 为所有客户计算分数df['违约概率'] = model.predict_proba(X)[:, 1]df['信用分数'] = df['违约概率'].apply(create_scorecard)print("客户的信用分数:")print(df[['客户ID', '违约概率', '信用分数']].head(10))

5.2 分析分数分布

# 分析分数分布plt.figure(figsize=(15, 5))# 1. 分数分布plt.subplot(1, 3, 1)plt.hist(df['信用分数'], bins=20, color='skyblue', edgecolor='black', alpha=0.7)plt.xlabel('信用分数')plt.ylabel('人数')plt.title('信用分数分布')plt.grid(True, alpha=0.3)# 2. 分数与违约率关系plt.subplot(1, 3, 2)df['分数段'] = pd.cut(df['信用分数'], bins=10)score_default_rate = df.groupby('分数段')['是否违约'].mean()plt.bar(range(len(score_default_rate)), score_default_rate.values,         color='lightcoral', alpha=0.7)plt.xticks(range(len(score_default_rate)),            [f"{x.left:.0f}-{x.right:.0f}"for x in score_default_rate.index],           rotation=45)plt.xlabel('分数段')plt.ylabel('违约率')plt.title('不同分数段的违约率')plt.grid(True, alpha=0.3)# 3. 好坏客户分数对比plt.subplot(1, 3, 3)good_scores = df[df['是否违约'] == 0]['信用分数']bad_scores = df[df['是否违约'] == 1]['信用分数']plt.boxplot([good_scores, bad_scores],             labels=['好客户', '坏客户'],            patch_artist=True,            boxprops=dict(facecolor='lightblue'))plt.ylabel('信用分数')plt.title('好坏客户分数对比')plt.grid(True, alpha=0.3)plt.tight_layout()plt.show()

5.3 制定审批策略

print("📋 基于评分的审批策略建议:")print("="*60)# 定义审批阈值thresholds = [    (700, "自动批准"),    (650, "快速审核"),    (600, "标准审核"),    (550, "严格审核"),    (0, "自动拒绝")]previous_threshold = 850for threshold, decision in thresholds:    mask = df['信用分数'] >= threshold    count = mask.sum()    default_rate = df[mask]['是否违约'].mean() if count > 0else0print(f"\n分数 ≥ {threshold}分 ({decision}):")print(f"  客户数量:{count}人 ({count/len(df):.1%})")print(f"  平均分数:{df[mask]['信用分数'].mean():.1f}分")print(f"  违约率:{default_rate:.1%}")    previous_threshold = threshold# 推荐策略print("\n🎯 推荐审批策略:")print("1. 分数≥700分:自动批准(低风险)")print("2. 600-699分:快速审核(中低风险)")print("3. 550-599分:人工审核(中风险)")print("4. <550分:自动拒绝(高风险)")

六、第五步:模型应用 - 新客户预测

6.1 创建预测函数

defpredict_new_customer(customer_data):"""    预测新客户的信用分数和审批建议    参数:    customer_data: 字典,包含客户特征    返回:预测结果    """# 转换为DataFrame    customer_df = pd.DataFrame([customer_data])# 确保特征顺序一致for feature in selected_features:if feature notin customer_df.columns:print(f"警告:缺少特征 {feature}")returnNone# 预测概率    X_customer = customer_df[selected_features]    prob = model.predict_proba(X_customer)[0, 1]    score = create_scorecard(prob)# 生成建议if score >= 700:        decision = "✅ 自动批准"        reason = "信用优秀,风险很低"elif score >= 600:        decision = "⚠️ 快速审核"        reason = "信用良好,风险较低"elif score >= 550:        decision = "⚠️ 人工审核"        reason = "信用一般,中等风险"else:        decision = "❌ 自动拒绝"        reason = "信用较差,高风险"# 特征贡献分析    contributions = {}    coef = model.coef_[0]    intercept = model.intercept_[0]for i, feature inenumerate(selected_features):        value = customer_data[feature]        contribution = coef[i] * value        contributions[feature] = {'值': value,'贡献': contribution,'影响': "加分"if contribution < 0else"减分"# 负系数降低违约概率        }return {'违约概率': f"{prob:.1%}",'信用分数': f"{score:.0f}分",'审批建议': decision,'建议原因': reason,'特征贡献': contributions    }# 测试新客户预测new_customer = {'年龄': 35,'月收入': 25000,'工作年限': 8,'信用卡数量': 2,'历史逾期': 0,'负债收入比': 0.3,'工作稳定性': 0.6}result = predict_new_customer(new_customer)print("新客户预测结果:")print("="*50)for key, value in result.items():if key != '特征贡献':print(f"{key}: {value}")print("\n特征贡献分析:")for feature, info in result['特征贡献'].items():print(f"  {feature}: 值={info['值']}, {info['影响']} ({info['贡献']:.4f})")

七、常见问题解答

Q1:我没有编程基础,真的能学会吗?

A: 绝对能!今天的内容只需要复制粘贴和按Shift+Enter。我带的实习生小张也是零基础起步,现在已经是团队骨干。

Q2:实际业务数据更复杂怎么办?

A: 今天学的是核心思路。实际工作中:

  1. 1. 数据清洗会更细致
  2. 2. 特征工程会更丰富
  3. 3. 模型会更复杂但基本原理完全一样

Q3:如何提高模型准确率?

A: 新手建议:

  1. 1. 增加更多数据
  2. 2. 创造更好的特征(如:收入稳定性、社交关系等)
  3. 3. 调整模型参数
  4. 4. 尝试其他模型(学完基础后)

Q4:模型上线需要什么?

A: 简单部署可以用Flask(网页API),复杂系统需要:

  1. 1. 模型版本管理
  2. 2. 监控报警
  3. 3. A/B测试但这些都有现成的工具包

八、学习路径建议

第一阶段(1-2周):夯实基础

  • • 每天花1小时练习今天的内容
  • • 尝试修改参数,观察结果变化
  • • 用不同数据测试模型

第二阶段(1个月):项目实战

  • • 找真实数据练习(推荐Kaggle的"Give Me Some Credit"数据集)
  • • 学习特征工程进阶技巧
  • • 掌握模型评估方法

第三阶段(3个月):成为能手

  • • 学习更复杂模型(XGBoost、LightGBM)
  • • 掌握模型部署
  • • 参与实际业务项目

欢迎添加:

公众号:消费金融风控联盟,ID:xiaojinfengkong
公众号:天天学风控,ID:xuefengkong
商务合作:13716986572 
欢迎加入联盟粉丝通讯录:免费加入+免费发布信息,Vivian:13911850028回复通讯录
欢迎加入风控干货知识星球:详情可添加管理Vivian:13911850028回复知识星球

最新文章

随机文章