浙大疏锦行
===================== 导入所需库 =====================
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import warnings
warnings.filterwarnings(‘ignore’)
===================== 1. 读取数据 =====================
file_path = r"C:\Python Study\Python60DaysChallenge-main\data.csv"
df = pd.read_csv(file_path)
===================== 2. 数据预处理 =====================
---- 2.1 特殊异常值修正(数据集特有问题) ----
Current Loan Amount 中 99999999 是缺失值占位符,替换为NaN
df[‘Current Loan Amount’] = df[‘Current Loan Amount’].replace(99999999, np.nan)
信用分正常范围300~850,大于1000的属于输入错误(多打1位),除以10修正
df[‘Credit Score’] = df[‘Credit Score’].apply(lambda x: x/10 if x > 1000 else x)
---- 2.2 缺失值填充 ----
分离数值型、分类型特征,以及标签列
label_col = df.columns[-1] # 最后一列是违约标签:0=未违约,1=违约
num_cols = df.select_dtypes(include=[‘int64’, ‘float64’]).columns.tolist()
cat_cols = df.select_dtypes(include=[‘object’]).columns.tolist()
num_cols.remove(label_col)
num_cols.remove(‘ID’) # ID是样本标识,不作为建模特征
数值型用中位数填充,分类型用众数填充
for col in num_cols:
df[col] = df[col].fillna(df[col].median())
for col in cat_cols:
df[col] = df[col].fillna(df[col].mode()[0])
---- 2.3 异常值处理:箱线图IQR法 + 迭代思想(知识点1) ----
原理:小于 Q1-1.5IQR 或 大于 Q3+1.5IQR 判定为异常值
迭代思想:去除一次异常值后数据分布变化,需重新计算分位数,直到无新异常值
def remove_outliers_iqr(data, cols, max_iter=3):
for i in range(max_iter):
before_size = len(data)
for col in cols:
Q1 = data[col].quantile(0.25)
Q3 = data[col].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 保留非异常值样本
data = data[(data[col] >= lower_bound) & (data[col] <= upper_bound)]
after_size = len(data)
print(f"第{i+1}次迭代去异常值:样本量从 {before_size} → {after_size}")
if before_size == after_size: # 无新异常值,停止迭代
break
return data
df_clean = remove_outliers_iqr(df, num_cols, max_iter=3)
print(f"异常值处理完成,剩余样本数:{len(df_clean)}\n")
---- 2.4 分类变量独热编码 ----
df_encoded = pd.get_dummies(df_clean, columns=cat_cols, drop_first=True)
分离特征矩阵X和标签y
X = df_encoded.drop([‘ID’, label_col], axis=1)
y = df_encoded[label_col]
===================== 3. 数据集划分(知识点2) =====================
按7:3划分训练集和测试集,stratify=y保证正负样本比例和原数据一致
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
print(f"训练集样本数:{X_train.shape[0]}“)
print(f"测试集样本数:{X_test.shape[0]}\n”)
===================== 4. 数据标准化(知识点3:避免数据泄露) =====================
关键原则:先划分数据集,再做归一化
仅用训练集拟合标准化器,测试集只做转换,防止测试集的统计信息泄露到训练中
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 训练集:拟合+转换
X_test_scaled = scaler.transform(X_test) # 测试集:仅转换
===================== 5. 模型训练(知识点4:三行代码建模) =====================
第1行:实例化逻辑回归模型(二分类任务经典模型)
model = LogisticRegression(random_state=42, max_iter=1000)
第2行:用训练集训练模型
model.fit(X_train_scaled, y_train)
第3行:输出测试集预测结果
y_pred = model.predict(X_test_scaled)
===================== 6. 模型评估(知识点5+6) =====================
---- 6.1 准确率 ----
acc = accuracy_score(y_test, y_pred)
print(f"模型整体准确率:{acc:.4f}\n")
---- 6.2 混淆矩阵 ----
cm = confusion_matrix(y_test, y_pred)
print(“混淆矩阵:”)
print(cm)
print(f"真阴性(TN):{cm[0][0]} | 实际未违约,预测未违约")
print(f"假阳性(FP):{cm[0][1]} | 实际未违约,预测违约")
print(f"假阴性(FN):{cm[1][0]} | 实际违约,预测未违约")
print(f"真阳性(TP):{cm[1][1]} | 实际违约,预测违约\n")
---- 6.3 分类报告(知识点6:分类报告解读) ----
print(“=”*50)
print(“分类报告:”)
print(classification_report(y_test, y_pred))
print(“=”*50)
print(“分类报告指标说明:”)
print(“1. precision(精确率):预测为违约的样本里,真实违约的比例,代表预测的"准度”“)
print(“2. recall(召回率):真实违约的样本里,被正确预测的比例,代表对违约用户的"查全度””)
print(“3. f1-score:精确率和召回率的调和平均数,综合衡量模型性能”)
print(“4. support:对应类别在真实标签中的样本数量”)
print(“5. accuracy:整体准确率,所有预测正确的样本占总样本的比例”)
print(“6. macro avg:宏平均,不考虑样本量,对两类指标直接取平均”)
print(“7. weighted avg:加权平均,按样本量占比加权,适合样本不平衡场景”)