没学过编程?不懂统计学?别担心!跟着我,用最简单的方式搭建你的第一个风控模型。
前言:从“技术恐惧”到“风控自信”
3个月后,小张独立搭建的评分卡模型成功上线,将审批效率提升了40%。今天,我就把小张的“零基础逆袭秘籍”完整分享给你。
记住:风控的核心是业务思维,代码只是工具。
一、准备工作:像安装手机APP一样简单
1.1 安装Python环境(5分钟搞定)
别被“环境配置”吓到,跟着我做:
- 1. 下载Anaconda(就像下载微信一样简单)
- • 打开浏览器,访问:https://www.anaconda.com/download
- • 点击下载(Windows用户选Windows,Mac用户选MacOS)
- 2. 打开Jupyter Notebook(我们的“代码记事本”)
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: 今天学的是核心思路。实际工作中:
Q3:如何提高模型准确率?
A: 新手建议:
- 2. 创造更好的特征(如:收入稳定性、社交关系等)
Q4:模型上线需要什么?
A: 简单部署可以用Flask(网页API),复杂系统需要:
八、学习路径建议
第一阶段(1-2周):夯实基础
第二阶段(1个月):项目实战
- • 找真实数据练习(推荐Kaggle的"Give Me Some Credit"数据集)
第三阶段(3个月):成为能手
- • 学习更复杂模型(XGBoost、LightGBM)