AI+数据分析

41 阅读21分钟

AI+数据分析 是什么?

首先,我们思考两个问题

人工智能是什么?

数据分析是什么?

我们都知道人工智能是用机器用来处理一些执行通常需要人类智能的任务; 数据分析是分为数据收集、数据清洗、数据探索、数据建模、结果解释的这样一个流程。

那么显然数据分析中用到了人类智能,那么使用ai是否可以得到快速的建立这样一个流程的过程呢?答案显然是可以的,今天就为大家带来一期用ai工具进行将数据分析的流程。

工具

小浣熊家族 Raccoon - AI 智能助手 - 商汤科技是商汤科技旗下的 AI 生产力平台(小浣熊家族 Raccoon)

image.png

实例

示例一,贷款风险分析

数据来源:该数据集源自Kaggle的“Playground Series - Season 4, Episode 10”竞赛,是通过在贷款批准预测数据集上训练的深度学习模型生成的数据,旨在使用借款人信息预测贷款批准结果,它通过模拟真实贷款审批场景,帮助金融机构评估借款人风险。

AI+数据总览

你现在是一名专业的信贷数据分析师,请帮我对以下信贷数据集进行**基础统计总览分析**,要求如下:
1.  数据说明:
    字段含义:
    - id:唯一标识
    - person_age:申请人年龄(数值型)
    - person_income:申请人收入(数值型)
    - person_home_ownership:申请人住房产权类型(分类型:RENT/OWN/MORTGAGE等)
    - person_emp_length:申请人就业年限(数值型)
    - loan_intent:贷款用途(分类型)
    - loan_grade:贷款等级(分类型)
    - loan_amnt:贷款金额(数值型)
    - loan_int_rate:贷款利率(数值型)
    - loan_percent_income:贷款金额占收入比例(数值型)
    - cb_person_default_on_file:征信违约记录(分类型:Y=有,N=无)
    - cb_person_cred_hist_length:申请人信用记录年限(数值型)
    - loan_status:贷款状态(分类型:0=正常,1=违约)

2.  分析任务:
    (1)  生成**数值型字段的描述性统计总览表**:包含字段名、样本量、均值、中位数、最小值、最大值、标准差
    (2)  生成**分类型字段的占比分布表**:每个字段的不同类别对应的数量和百分比(比如 住房产权类型中 RENT占比XX%、OWN占比XX%)
    (3)  重点输出**核心业务指标的百分比**:
        - 贷款违约率(loan_status=1的占比)
        - 有违约记录的申请人占比(cb_person_default_on_file=Y的占比)
        - 各贷款用途的占比排名

3.  输出格式要求:
    - 用markdown表格呈现,分“数值型字段统计总览”“分类型字段占比分布”“核心业务指标百分比”三个模块
    - 百分比保留2位小数,统计结果清晰标注单位
    - 最后附加1句关键结论总结(比如“本次分析样本中贷款违约率为XX%,租房申请人占比最高达XX%”)

可以看到我们最后要求ai帮我们生成了三个任务 当然这三个任务的意义各不相同

  1. 第一条任务的意义是:帮你看那些带数字的字段(比如年龄、收入、贷款金额)的整体情况,避免拿着有问题的数据瞎分析。
  • 比如算 “申请人平均收入”,你就知道这批借钱的人大概多有钱;算 “年龄最大 / 最小”,能快速发现离谱数据(比如年龄写个 1000 岁,明显是填错了,得删掉);
  • 算 “标准差” 就是看数据波动大不大:比如大家收入都在 3 万 - 5 万,波动就小;有人收入 1 万,有人收入 100 万,波动就大 —— 波动大的话,后续就得分开分析 “低收入人群” 和 “高收入人群” 的借钱习惯。
  1. 第二条任务的意义是:分析那些分好类的字段(比如租房 / 自有住房、贷款用来上学 / 买房),统计每类人有多少、占比多少。
  • 比如住房类型里,租房的占 60%,自有住房的占 30%,那你就知道:租房的人是咱们的主力客户,后续可以专门给租房人群设计还款方案(比如房租季付月还);
  • 再比如贷款等级里,A 级客户占 50%,说明咱们现在主要借钱给信用好的人,放贷策略偏保守。

3.第三条任务的意义是:直接关系到业务赚不赚钱、会不会亏钱

  • 贷款违约率:就是 “借了钱不还的人占多少”。如果只有 3%,说明风险小,放贷策略没问题;如果有 20%,那就要慌了 —— 得赶紧查原因,是不是给信用差的人借太多了?
  • 有违约记录的申请人占比:就是 “以前借过钱不还,现在又来借的人有多少”。如果这批人现在违约率很高,那以后就尽量别借给他;如果这批人现在都按时还钱了,那可以适当放宽条件。
  • 贷款用途占比排名:就是 “大家借钱最常干啥”。比如上学占第一,那咱们就重点推广教育贷款,优化这个产品的额度和利率,把这块业务做大。

效果:

信贷数据集基础统计总览分析报告
数据概况

本次分析基于58,645个信贷样本,包含13个关键字段,数据质量良好,无缺失值和重复记录。

一、数值型字段描述性统计总览表
字段名样本量均值中位数最小值最大值标准差
person_age58,64527.5526201236.03
person_income58,64564,046.258,0004,2001,900,00037,931.1
person_emp_length58,6454.7401233.96
loan_amnt58,6459,217.568,00050035,0005,563.81
loan_int_rate58,64510.6810.755.4223.223.03
loan_percent_income58,6450.160.1400.830.09
cb_person_cred_hist_length58,6455.8142304.03
二、分类型字段占比分布表
住房产权类型分布
类别数量百分比(%)
RENT30,59452.17%
MORTGAGE24,82442.33%
OWN3,1385.35%
OTHER890.15%
贷款用途分布
类别数量百分比(%)
EDUCATION12,27120.92%
MEDICAL10,93418.64%
PERSONAL10,01617.08%
VENTURE10,01117.07%
DEBTCONSOLIDATION9,13315.57%
HOMEIMPROVEMENT6,28010.71%
贷款等级分布
类别数量百分比(%)
A20,98435.78%
B20,40034.79%
C11,03618.82%
D5,0348.58%
E1,0091.72%
F1490.25%
G330.06%
征信违约记录分布
类别数量百分比(%)
N49,94385.16%
Y8,70214.84%
贷款状态分布
类别数量百分比(%)
正常(0)50,29585.76%
违约(1)8,35014.24%
三、核心业务指标百分比
指标名称数值
贷款违约率14.24%
有违约记录申请人占比14.84%

各贷款用途占比排名:

  1. 教育用途(EDUCATION): 20.92%
  2. 医疗用途(MEDICAL): 18.64%
  3. 个人用途(PERSONAL): 17.08%
  4. 创业用途(VENTURE): 17.07%
  5. 债务整合(DEBTCONSOLIDATION): 15.57%
  6. 房屋改善(HOMEIMPROVEMENT): 10.71%
关键结论总结

本次信贷数据分析基于58,645个样本,关键发现如下: • 贷款违约率为14.24%,略高于行业平均水平 • 征信有违约记录的申请人占比为14.84% • 租房申请人占比最高,达52.17% • 教育用途贷款占比最高(20.92%),其次是医疗用途(18.64%) • 平均申请人年龄为27.6岁,平均收入为64,046元 • 平均贷款金额为9,218元,平均利率为10.68%

AI+数据清洗

提示词

plaintext

你现在是一名专业的信贷数据清洗工程师,请帮我清洗以下信贷数据集,要求如下:
1.  数据说明:
    字段含义:
    - id:唯一标识;person_age:申请人年龄;person_income:申请人收入
    - person_home_ownership:住房产权类型(RENT/OWN/MORTGAGE);person_emp_length:就业年限
    - loan_intent:贷款用途;loan_grade:贷款等级;loan_amnt:贷款金额
    - loan_int_rate:贷款利率;loan_percent_income:贷款占收入比例
    - cb_person_default_on_file:征信违约记录(Y/N);cb_person_cred_hist_length:信用记录年限
    - loan_status:贷款状态(0=正常,1=违约)

2.  清洗任务(按优先级排序):
    (1)  去重:删除id重复的行(id是唯一标识,重复即无效)
    (2)  处理缺失值:
        - 数值型字段(person_age/income/emp_length等):用中位数填充
        - 分类型字段(home_ownership/loan_intent等):用最常见类别填充
        - loan_status、cb_person_default_on_file缺失的行,直接删除(这俩是核心字段)
    (3)  处理异常值(重点!):
        - person_age:保留18-80岁,剔除之外的行
        - person_emp_length:保留0-40年,剔除之外的行
        - loan_amnt/loan_int_rate:剔除≤0的值
        - loan_percent_income:剔除>0.5的值(贷款占收入超50%大概率不合理,可根据你的数据调整)
        - cb_person_cred_hist_length:保留1-50年,剔除之外的行
    (4)  格式标准化:
        - 分类型字段全大写(比如把“rent”改成“RENT”,“y”改成“Y”)
        - loan_int_rate、loan_percent_income保留2位小数
    (5)  逻辑校验:
        - 贷款占收入比例(loan_percent_income)>1的行,直接删除
        - 信用记录年限(cb_person_cred_hist_length)>年龄的行,标注后删除(不可能信用记录比年龄还长)

3.  输出要求:
    (1)  输出清洗步骤报告(含每步处理的数据量)
    (2)  输出清洗前后的核心字段对比表
    (3)  输出清洗后的最终数据(markdown表格)
  • 去重(删重复 id 行)意义:避免 “一个人被算成两个人”

    id 是每个人的唯一标识,重复的行就相当于同一个申请人的信息被录了 2 遍。如果不删,后续算 “申请人总数”“违约率” 都会虚高 —— 比如本来 1000 个人,重复了 50 行,你会误以为有 1050 人,分析结果从根上就错了。

  • 处理缺失值意义:补全 “空着的坑”,或者扔掉 “坑太大” 的没用数据

    • 数值型字段(年龄、收入)用中位数填:比如有人年龄空着,总不能瞎写个数字,用大家的中间年龄填,最接近真实情况;
    • 分类型字段(住房类型)用最常见的填:比如大部分人是租房,空着的就填 “租房”,比瞎猜靠谱;
    • 核心字段(贷款状态、违约记录)缺失直接删:这俩是分析风险的关键,没这俩数据的行,留着也没法分析,不如直接扔掉,免得添乱。
  • **处理异常值(重点!)**意义:扔掉那些 “明显瞎写” 的离谱数据比如年龄填个 1000 岁、贷款金额填个负数、就业年限填 50 年,这些数据在现实中根本不可能存在。如果不删,会严重误导分析 —— 比如算平均年龄时,一个 1000 岁的 “异常值” 会把整体平均年龄拉高几十岁,得出 “申请人平均年龄 80 岁” 的荒唐结论。

  • 格式标准化意义:让数据 “规矩统一”,AI 和人都能看懂算对

    • 比如住房类型有的写 “rent”、有的写 “RENT”、有的写 “租房”,AI 会误以为是 3 种不同类型,统计占比就全错了;统一改成大写 “RENT”,就不会乱;
    • 利率有的留 1 位小数、有的留 3 位,统一成 2 位,对比起来更直观。
  • 逻辑校验意义:揪出那些 “自相矛盾” 的离谱数据

    • 贷款占收入比例大于 1:就是借的钱比一年赚的还多,现实中这种情况极少,大概率是填错了;
    • 信用记录年限比年龄还长:比如 20 岁的人,信用记录填了 25 年,这根本不可能,纯属数据错误。这些矛盾数据不删,后续分析 “贷款占比和违约率的关系”“信用年限和还款能力的关系”,都会得出错误结论。

image.png

AI+数据探索

你现在是一名资深信贷数据分析师兼可视化专家,请基于我清洗后的信贷数据集,帮我完成**探索性数据分析可视化**,要求如下:

1.  数据基础信息
    清洗后的数据字段及含义:
    - id:唯一标识;person_age:申请人年龄;person_income:申请人收入
    - person_home_ownership:住房产权类型(RENT/OWN/MORTGAGE);person_emp_length:就业年限
    - loan_intent:贷款用途;loan_grade:贷款等级;loan_amnt:贷款金额
    - loan_int_rate:贷款利率;loan_percent_income:贷款占收入比例
    - cb_person_default_on_file:征信违约记录(Y/N);cb_person_cred_hist_length:信用记录年限
    - loan_status:贷款状态(0=正常,1=违约)
    

2.  可视化任务(分优先级,先看单字段分布,再看字段间关联)
    ## 第一类:单字段分布可视化(看数据整体特征)
    (1)  数值型字段分布(用直方图/箱线图)
        - 申请人年龄分布:看主力申请人群的年龄区间,标题标注“清洗后申请人年龄分布”
        - 申请人收入分布:看收入分层情况,标题标注“清洗后申请人收入分布”
        - 贷款金额分布:看主流放贷额度,标题标注“清洗后贷款金额分布”
    (2)  分类型字段占比(用饼图/条形图)
        - 住房产权类型占比:标题标注“申请人住房类型占比”,显示各类别百分比
        - 贷款用途占比排名:条形图按占比从高到低排序,标题标注“贷款用途占比TOP5”
        - 贷款违约率占比:饼图显示正常(0)和违约(1)的比例,标题标注“整体贷款违约率分布”

    ## 第二类:双字段关联可视化(看特征与风险的关系,核心业务视角)
    (1)  不同特征 vs 违约率(分组条形图)
        - 住房类型与违约率:对比RENT/OWN/MORTGAGE三类人群的违约率,看哪种住房类型风险高
        - 贷款等级与违约率:对比A/B/C等不同等级的违约率,看等级和风险的关联
        - 历史违约记录 vs 当前违约率:对比Y(有记录)和N(无记录)人群的当前违约率
    (2)  数值型特征关联(散点图/折线图)
        - 收入 vs 贷款金额:看收入越高的人,贷款金额是否越高
        - 贷款占收入比例 vs 违约率:看比例越高,违约率是否越高(重点风险指标)

3.  输出要求(根据你用的AI工具二选一)
    ### 若用「支持直接生成图表的AI」(如Tableau Copilot、Power BI Copilot)
    (1)  直接生成上述所有图表,图表风格简洁清晰,标注坐标轴、单位、百分比
    (2)  每个图表下方配1句**业务解读**(比如“年龄分布显示25-40岁是主力申请人群,占比60%”)
    (3)  最后汇总1份「可视化核心结论清单」

    ### 若用「普通大语言模型」(如ChatGPT、文心一言)
    (1)  输出**详细制图方案**:每个图表对应“工具(Excel/Python)+ 数据维度 + 操作步骤”
        - 示例:“年龄分布直方图(Excel版):选中person_age列 → 插入 → 直方图 → 调整区间为5岁一组 → 添加标题”
    (2)  输出**图表预期解读**:假设图表做好了,能得出什么结论(比如“若租房人群违约率高于自有住房,说明租房人群风险更高”)
    (3)  标注**核心关注图表**:哪3张图对信贷风控最有价值(比如贷款占收入比例vs违约率、贷款等级vs违约率)

效果图太多,我随便粘几张

image.png

image.png

image.png

AI+数据建模

提示词

你现在是一名AI+资深信贷风控建模专家,同时具备业务落地思维,请基于我清洗后的信贷数据集,完成**贷款违约风险预测模型**的构建工作,具体要求如下:

1.  数据基础信息
    清洗后的数据字段及含义:
    - 特征变量(用于预测的输入):
      数值型:person_age(年龄)、person_income(收入)、person_emp_length(就业年限)、loan_amnt(贷款金额)、loan_int_rate(利率)、loan_percent_income(贷款占收入比)、cb_person_cred_hist_length(信用记录年限)
      分类型:person_home_ownership(住房类型)、loan_intent(贷款用途)、loan_grade(贷款等级)、cb_person_default_on_file(历史违约记录Y/N)
    - 目标变量(需要预测的输出):loan_status(贷款状态,0=正常,1=违约)
    清洗后数据量:【填写清洗后的总行数,如5000行】
    建模目标:通过申请人的特征,预测其贷款违约的概率,辅助信贷风控决策

2.  建模核心任务(分步骤执行)
    ## 步骤1:特征工程(建模的关键前提)
    (1)  特征筛选:剔除无意义特征(如id),保留与违约相关的核心特征;删除高度相关的冗余特征(比如“贷款金额”和“贷款占收入比”若强相关,可保留其一)
    (2)  特征处理:
        - 分类型特征:进行编码处理(比如独热编码:把住房类型RENT/OWN/MORTGAGE转换成0/1格式,方便模型计算)
        - 数值型特征:进行标准化/归一化处理(比如把年龄、收入缩放到同一区间,避免数值大的特征主导模型)
        - 可选优化:对核心风险特征(如贷款占收入比)进行分箱处理(比如0-0.2、0.2-0.5两个区间),提升模型稳定性
    (3)  数据划分:将数据集按7:3的比例拆分为**训练集**(70%,用于训练模型)和**测试集**(30%,用于验证模型效果)

    ## 步骤2:模型选择与训练(新手友好+业务实用优先)
    选择3类适合二分类任务的模型,从简单到复杂依次训练,方便对比效果:
    (1)  基础模型:逻辑回归(解释性强,适合风控场景,方便向业务方解释“哪些因素影响违约”)
    (2)  树模型:决策树(容易理解,能输出决策规则,比如“贷款占收入比>0.4且无自有住房→违约概率高”)
    (3)  集成模型:随机森林(提升预测准确率,降低过拟合风险,适合实际业务落地)
    要求:设置基础模型参数(不用太复杂,新手默认参数即可)

    ## 步骤3:模型评估(判断模型好不好用)
    用测试集验证模型效果,输出**分类模型核心评估指标**:
    (1)  基础指标:准确率(模型预测正确的比例)、精确率(预测为违约的样本中实际违约的比例)、召回率(实际违约的样本中被预测出来的比例)
    (2)  风控核心指标:AUC值(衡量模型区分“正常”和“违约”样本的能力,AUC越接近1越好)
    (3)  模型对比:列出3个模型的指标对比表,选出最优模型(比如随机森林AUC最高,作为最终模型)

    ## 步骤4:模型解释与业务落地(重点!贴合实际需求)
    (1)  特征重要性分析:输出影响违约的TOP5核心特征(比如“贷款占收入比”>“历史违约记录”>“贷款等级”)
    (2)  业务规则提取:从最优模型中提炼可落地的风控规则(比如“贷款占收入比超过0.5时,违约概率提升至60%,建议拒绝放贷”)
    (3)  模型局限性说明:比如“模型对年龄>60岁的样本预测准确率低,因为该群体样本量少”

3.  输出要求(根据你使用的AI工具二选一)
    ### 若用「普通大语言模型」(如ChatGPT、文心一言)
    (1)  输出**完整建模方案文档**:包含特征工程步骤、模型参数设置、评估指标计算逻辑、特征重要性排序
    (2)  输出**Python代码模板**:基于Scikit-learn库,实现上述建模流程(代码带注释,新手能看懂)
    (3)  输出**业务决策建议**:基于模型结论,给出具体的放贷策略调整建议

    ### 若用「支持自动建模的AI工具」(如AutoML、阿里云PAI、腾讯TI-ONE)
    (1)  直接生成**最优模型**:指定模型类型为随机森林(或逻辑回归),输出模型文件
    (2)  输出**模型评估报告**:可视化展示各指标、特征重要性柱状图
    (3)  输出**模型部署建议**:比如如何将模型嵌入信贷审批流程

4.  额外要求
    - 建模过程要兼顾**准确性和可解释性**,优先选择业务方容易理解的模型(比如逻辑回归比深度学习更适合风控场景)
    - 避免过度拟合(比如决策树设置最大深度,随机森林增加树的数量)

image.png

python代码

"""
信贷违约风险预测模型 - 测试集预测完整代码
基于随机森林算法,包含数据预处理、模型训练和测试集预测的完整流程
"""

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score
import matplotlib.pyplot as plt
import seaborn as sns

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

def load_data(train_path, test_path):
    """加载训练数据和测试数据"""
    train_df = pd.read_csv(train_path)
    test_df = pd.read_csv(test_path)
    return train_df, test_df

def preprocess_data(train_df, test_df):
    """数据预处理和特征工程"""
    # 定义特征变量
    numeric_features = ['person_age', 'person_income', 'person_emp_length', 'loan_amnt', 'loan_int_rate', 'loan_percent_income', 'cb_person_cred_hist_length']
    categorical_features = ['person_home_ownership', 'loan_intent', 'loan_grade', 'cb_person_default_on_file']
    
    # 分离特征和目标变量
    X_train = train_df.drop(['id', 'loan_status'], axis=1)
    y_train = train_df['loan_status']
    X_test = test_df.drop(['id'], axis=1)
    
    # 创建预处理管道
    numeric_transformer = Pipeline(steps=[
        ('scaler', StandardScaler())])
    
    categorical_transformer = Pipeline(steps=[
        ('onehot', OneHotEncoder(handle_unknown='ignore'))])
    
    preprocessor = ColumnTransformer(
        transformers=[
            ('num', numeric_transformer, numeric_features),
            ('cat', categorical_transformer, categorical_features)])
    
    return X_train, y_train, X_test, preprocessor

def build_and_train_model(X_train, y_train, preprocessor):
    """构建和训练随机森林模型"""
    rf_model = Pipeline([
        ('preprocessor', preprocessor),
        ('classifier', RandomForestClassifier(
            random_state=42,
            n_estimators=100,
            max_depth=15,
            min_samples_split=20,
            min_samples_leaf=10,
            n_jobs=-1
        ))
    ])
    
    # 训练模型
    rf_model.fit(X_train, y_train)
    
    # 在训练集上评估
    y_train_pred = rf_model.predict(X_train)
    y_train_proba = rf_model.predict_proba(X_train)[:, 1]
    
    train_accuracy = accuracy_score(y_train, y_train_pred)
    train_auc = roc_auc_score(y_train, y_train_proba)
    
    print(f"模型训练完成!")
    print(f"训练集准确率: {train_accuracy:.4f}")
    print(f"训练集AUC值: {train_auc:.4f}")
    
    return rf_model

def predict_on_test_set(rf_model, X_test, test_df):
    """在测试集上进行预测"""
    # 预测类别和概率
    y_test_pred = rf_model.predict(X_test)
    y_test_proba = rf_model.predict_proba(X_test)[:, 1]
    
    # 创建预测结果DataFrame
    prediction_results = pd.DataFrame({
        'id': test_df['id'],
        'predicted_default': y_test_pred,
        'default_probability': y_test_proba
    })
    
    # 添加风险等级分类
    bins = [0, 0.1, 0.2, 0.3, 0.5, 1.0]
    labels = ['极低风险(0-10%)', '低风险(10-20%)', '中等风险(20-30%)', 
              '高风险(30-50%)', '极高风险(>50%)']
    prediction_results['risk_level'] = pd.cut(
        prediction_results['default_probability'], 
        bins=bins, labels=labels, include_lowest=True)
    
    return prediction_results

def analyze_feature_importance(rf_model, preprocessor, numeric_features, categorical_features):
    """分析特征重要性"""
    feature_importance = rf_model.named_steps['classifier'].feature_importances_
    
    # 获取特征名称
    all_feature_names = numeric_features.copy()
    ohe_categories = preprocessor.named_transformers_['cat'].named_steps['onehot'].categories_
    for i, cat_name in enumerate(categorical_features):
        for category in ohe_categories[i]:
            all_feature_names.append(f"{cat_name}_{category}")
    
    importance_df = pd.DataFrame({
        'feature': all_feature_names,
        'importance': feature_importance
    }).sort_values('importance', ascending=False)
    
    return importance_df

def main():
    """主函数:执行完整的建模和预测流程"""
    # 文件路径(根据实际情况修改)
    train_path = '/mnt/data/train.csv'
    test_path = '/mnt/data/test.csv'
    output_path = '/mnt/data/测试集违约风险预测结果.csv'
    
    print("=== 信贷违约风险预测模型 - 测试集预测 ===")
    
    # 1. 加载数据
    print("\n步骤1:加载数据...")
    train_df, test_df = load_data(train_path, test_path)
    print(f"训练数据维度:{train_df.shape}")
    print(f"测试数据维度:{test_df.shape}")
    
    # 2. 数据预处理
    print("\n步骤2:数据预处理...")
    X_train, y_train, X_test, preprocessor = preprocess_data(train_df, test_df)
    print(f"特征工程完成,包含{len(numeric_features + categorical_features)}个特征")
    
    # 3. 模型训练
    print("\n步骤3:模型训练...")
    rf_model = build_and_train_model(X_train, y_train, preprocessor)
    
    # 4. 测试集预测
    print("\n步骤4:测试集预测...")
    prediction_results = predict_on_test_set(rf_model, X_test, test_df)
    
    # 5. 结果统计
    print("\n步骤5:预测结果统计...")
    print(f"测试样本总数:{len(prediction_results):,}")
    print(f"预测违约样本数:{prediction_results['predicted_default'].sum():,}")
    print(f"预测违约率:{prediction_results['predicted_default'].mean()*100:.2f}%")
    
    # 6. 特征重要性分析
    print("\n步骤6:特征重要性分析...")
    importance_df = analyze_feature_importance(rf_model, preprocessor, numeric_features, categorical_features)
    print("TOP 10 最重要的风险特征:")
    for i, (idx, row) in enumerate(importance_df.head(10).iterrows(), 1):
        print(f"{i:2d}. {row['feature']:35s} : {row['importance']:.4f}")
    
    # 7. 保存结果
    print("\n步骤7:保存预测结果...")
    prediction_results.to_csv(output_path, index=False)
    print(f"✅ 预测结果已保存到: {output_path}")
    
    print("\n🎉 测试集预测任务完成!")
    return prediction_results, rf_model, importance_df

if __name__ == "__main__":
    prediction_results, rf_model, importance_df = main()

``