上一章:機器學習實操項目03——Scikit-learn介紹及簡單分類案例
下一章:
機器學習核心知識點目錄:機器學習核心知識點目錄
機器學習實戰項目目錄:【從 0 到 1 落地】機器學習實操項目目錄:覆蓋入門到進階,大學生就業 / 競賽必備
文章目錄
- 客戶信用評估模型開發全流程
- 任務總覽
- 1. 數據加載與預處理
- 2. 劃分訓練集和驗證集
- 3. 特征預處理
- 4. 模型訓練與評估
- 5. 最佳模型選擇與評估
- 6. 混淆矩陣分析
- 7. 業務解讀
- 8. 測試集預測與提交
- 總結
- 完整代碼及中間結果
客戶信用評估模型開發全流程
任務總覽
本項目旨在開發一個客戶信用評估模型,通過分析客戶的基本信息、賬戶特征等數據,預測客戶是否為"好客戶"(Target=1)或"壞客戶"(Target=0)。這一模型可幫助金融機構在信貸審批過程中做出更合理的決策,平衡風險控制與業務發展。
整個流程包括:數據加載與預處理、數據集劃分、特征工程、模型訓練與評估、模型選擇與解讀、以及最終預測等關鍵步驟。
通過網盤分享的文件:用戶信用評分數據集
鏈接: https://pan.baidu.com/s/1F2R0rOLuw4_ntaKMPL8otg?pwd=1x27 提取碼: 1x27
1. 數據加載與預處理
功能說明
這一步驟的主要目的是加載原始數據并進行初步處理,為后續建模做準備。包括處理缺失值、分離特征與目標變量等。
# 讀取訓練數據和測試數據
train = pd.read_csv('train.csv') # 加載訓練數據集(包含目標變量)
test = pd.read_csv('test.csv') # 加載測試數據集(不包含目標變量,用于最終預測)
pd.read_csv():pandas庫的函數,用于從CSV文件中讀取數據并轉換為DataFrame格式,方便后續的數據處理和分析。
# 處理缺失值 - 只對分類特征進行簡單填充
# 將Credit_Product列的缺失值填充為'Unknown'
train['Credit_Product'] = train['Credit_Product'].fillna('Unknown')
test['Credit_Product'] = test['Credit_Product'].fillna('Unknown')
fillna():pandas的DataFrame方法,用于填充缺失值。這里將缺失的信用產品信息標記為’Unknown’,而不是簡單刪除,以保留更多數據信息。
# 分離特征和目標變量
X = train.drop(['ID', 'Target'], axis=1) # 特征數據:刪除ID(無預測價值)和Target(目標變量)
y = train['Target'] # 目標變量:客戶是否為好客戶(1表示好客戶,0表示壞客戶)
drop():pandas的DataFrame方法,用于刪除指定列(axis=1表示刪除列)。這里移除ID列(僅作為標識)和Target列(需要預測的目標)。
2. 劃分訓練集和驗證集
功能說明
將訓練數據進一步劃分為訓練集(用于模型訓練)和驗證集(用于模型評估),避免模型過擬合并客觀評估模型性能。
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, # 驗證集比例20%stratify=y, # 按目標變量分層抽樣random_state=42 # 設置隨機種子確保結果可復現
)
train_test_split():sklearn庫的函數,用于將數據集隨機劃分為訓練集和驗證集。
- test_size=0.2:指定驗證集占總數據的20%
- stratify=y:按目標變量y的分布進行分層抽樣,確保訓練集和驗證集中目標變量的比例一致
- random_state=42:設置隨機種子,保證每次運行代碼得到相同的劃分結果,便于結果復現
3. 特征預處理
功能說明
對不同類型的特征進行預處理,使特征滿足模型輸入要求,同時提升模型性能。主要包括對分類特征進行獨熱編碼,對數值特征進行標準化。
# 定義分類特征和數值特征
cat_cols = ['Gender', 'Region_Code', 'Occupation', 'Channel_Code', 'Credit_Product', 'Is_Active']
num_cols = ['Age', 'Vintage', 'Avg_Account_Balance']
特征分為兩類:
- 分類特征(cat_cols):非數值型特征,如性別、職業等
- 數值特征(num_cols):可直接進行數值計算的特征,如年齡、賬戶余額等
# 對分類變量進行獨熱編碼
encoder = OneHotEncoder(handle_unknown='ignore') # 創建獨熱編碼器
X_train_encoded = encoder.fit_transform(X_train[cat_cols]) # 擬合并轉換訓練集
X_val_encoded = encoder.transform(X_val[cat_cols]) # 轉換驗證集
X_test_encoded = encoder.transform(test[cat_cols]) # 轉換測試集
OneHotEncoder():sklearn的預處理類,用于將分類特征轉換為獨熱編碼形式。
- handle_unknown=‘ignore’:遇到訓練集中未出現的類別時忽略,避免錯誤
- fit_transform():先根據訓練數據擬合編碼器(學習類別信息),再進行轉換
- transform():使用已擬合的編碼器對新數據(驗證集/測試集)進行轉換,保證編碼方式一致
# 數值特征標準化(Z-score標準化)
scaler = StandardScaler() # 創建標準化器
X_train_num = scaler.fit_transform(X_train[num_cols]) # 擬合并轉換訓練集
X_val_num = scaler.transform(X_val[num_cols]) # 轉換驗證集
X_test_num = scaler.transform(test[num_cols]) # 轉換測試集
StandardScaler():sklearn的預處理類,用于對數值特征進行標準化(Z-score轉換),使特征均值為0,標準差為1。
- 標準化可以消除不同特征間的量綱影響,使模型更易收斂
# 合并處理后的特征
X_train_final = np.hstack([X_train_num, X_train_encoded.toarray()])
X_val_final = np.hstack([X_val_num, X_val_encoded.toarray()])
X_test_final = np.hstack([X_test_num, X_test_encoded.toarray()])
np.hstack():numpy庫的函數,用于水平堆疊數組。這里將處理后的數值特征和編碼后的分類特征合并,形成最終的特征矩陣。
4. 模型訓練與評估
功能說明
訓練多種分類模型,并使用驗證集評估模型性能,選擇最優模型。采用AUC(ROC曲線下面積)作為主要評估指標,適用于二分類問題且對不平衡數據較為穩健。
# 定義要比較的模型
models = [("Logistic Regression", LogisticRegression(max_iter=1000, random_state=42)),("Decision Tree", DecisionTreeClassifier(max_depth=5, random_state=42)),("Random Forest", RandomForestClassifier(n_estimators=100, random_state=42)),("KNN", KNeighborsClassifier(n_neighbors=30)),("Naive Bayes", GaussianNB())
]
選擇了5種常見的分類算法進行比較:
- 邏輯回歸:線性模型,可解釋性強
- 決策樹:非線性模型,可捕捉特征間的交互關系
- 隨機森林:集成模型,通常性能更優
- K近鄰:基于實例的學習,簡單直觀
- 樸素貝葉斯:基于概率的簡單模型
# 評估每個模型
for name, model in models:model.fit(X_train_final, y_train) # 訓練模型# 獲取預測概率if hasattr(model, "predict_proba"):val_proba = model.predict_proba(X_val_final)[:, 1] # 預測為1的概率else:val_proba = model.decision_function(X_val_final)val_proba = (val_proba - val_proba.min()) / (val_proba.max() - val_proba.min()) # 歸一化val_auc = roc_auc_score(y_val, val_proba) # 計算AUCprint(f"{name}: AUC = {val_auc:.4f}")
model.fit():模型訓練方法,根據輸入的特征矩陣和目標變量學習模型參數。
predict_proba():多數分類模型提供的方法,返回每個樣本屬于各個類別的概率。[:, 1]表示取樣本屬于類別1(好客戶)的概率。
roc_auc_score():計算ROC曲線下面積(AUC)的函數。AUC取值范圍為0-1,越接近1表示模型區分正負樣本的能力越強。
5. 最佳模型選擇與評估
功能說明
基于驗證集的AUC值選擇性能最優的模型,并進行更詳細的評估,包括分類報告和混淆矩陣分析。
# 選擇最佳模型
best_model_name, best_auc, best_model = max(results, key=lambda x: x[1])
通過比較各模型的AUC值,選擇性能最優的模型(此處為決策樹,AUC=0.8595)。
# 詳細評估最佳模型
val_pred = best_model.predict(X_val_final) # 預測類別
print(classification_report(y_val, val_pred)) # 生成分類報告
predict():模型預測方法,返回樣本的預測類別(0或1)。
classification_report():生成包含精確率(precision)、召回率(recall)、F1分數等指標的分類報告:
- 精確率:預測為正的樣本中實際為正的比例
- 召回率:實際為正的樣本中被正確預測的比例
- F1分數:精確率和召回率的調和平均
6. 混淆矩陣分析
功能說明
通過混淆矩陣更直觀地分析模型的預測結果,了解模型在不同類別上的表現。
cm = confusion_matrix(y_val, val_pred)
tn, fp, fn, tp = cm.ravel()
confusion_matrix():計算混淆矩陣的函數,矩陣元素含義:
- TP(True Positive):真正例,實際為好客戶且被正確預測
- FP(False Positive):假正例,實際為壞客戶但被錯誤預測為好客戶
- FN(False Negative):假反例,實際為好客戶但被錯誤預測為壞客戶
- TN(True Negative):真反例,實際為壞客戶且被正確預測
7. 業務解讀
功能說明
將模型的技術指標轉化為業務指標,從業務角度解讀模型表現,評估模型對實際業務的影響。
accuracy = (tp + tn) / (tp + tn + fp + fn) # 總體準確率
good_recall = tp / (tp + fn) # 好客戶識別率(召回率)
bad_recall = tn / (tn + fp) # 壞客戶識別率
從業務角度看:
- 假陽性(FP):將壞客戶誤判為好客戶,可能導致壞賬損失
- 假陰性(FN):將好客戶誤判為壞客戶,會損失潛在收益
- 模型需要在兩者之間找到平衡,根據業務策略調整閾值
8. 測試集預測與提交
功能說明
使用最佳模型對測試集進行預測,生成符合要求的提交文件,用于模型部署或競賽提交。
# 測試集預測
test_proba = best_model.predict_proba(X_test_final)[:, 1]# 生成提交文件
submission = pd.DataFrame({'ID': test['ID'],'Target': test_proba
})
submission.to_csv('submission.csv', index=False)
生成包含客戶ID和對應好客戶概率的提交文件,概率值可用于業務決策(如設定閾值來確定是否批準信貸)。
總結
本項目通過完整的機器學習流程,從數據預處理到模型評估,最終構建了一個客戶信用評估模型。決策樹模型在本數據集上表現最佳,AUC達到0.8595,能夠較好地區分好客戶和壞客戶。模型的業務解讀幫助將技術結果轉化為實際業務價值,為信貸決策提供數據支持。
完整代碼及中間結果
# 導入必要的數據處理和機器學習庫
import pandas as pd # 用于數據處理和分析
import numpy as np # 用于數值計算
import matplotlib.pyplot as plt # 用于數據可視化
from sklearn.model_selection import train_test_split # 用于劃分訓練集和驗證集
from sklearn.preprocessing import StandardScaler, OneHotEncoder # 用于特征預處理
from sklearn.metrics import roc_auc_score, confusion_matrix, classification_report # 用于模型評估
# 1. 數據加載與預處理
# 讀取訓練數據和測試數據
train = pd.read_csv('train.csv') # 加載訓練數據集
test = pd.read_csv('test.csv') # 加載測試數據集# 處理缺失值 - 只對分類特征進行簡單填充
# 將Credit_Product列的缺失值填充為'Unknown'
train['Credit_Product'] = train['Credit_Product'].fillna('Unknown')
test['Credit_Product'] = test['Credit_Product'].fillna('Unknown')# 分離特征和目標變量
# 訓練數據中刪除ID列和Target列作為特征
X = train.drop(['ID', 'Target'], axis=1)
# 提取目標變量(客戶是否為好客戶)
y = train['Target']
# 2. 劃分訓練集和驗證集
# 將數據分為訓練集和驗證集,驗證集占20%
# 使用分層抽樣確保訓練集和驗證集的目標變量分布一致
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, # 驗證集比例20%stratify=y, # 按目標變量分層抽樣random_state=42 # 設置隨機種子確保結果可復現
)
print(X)
輸出結果:
Gender | Age | Region_Code | Occupation | Channel_Code | Vintage | Credit_Product | Avg_Account_Balance | Is_Active | |
---|---|---|---|---|---|---|---|---|---|
0 | Male | 58 | RG264 | Self_Employed | X2 | 19 | No | 552449 | Yes |
1 | Female | 45 | RG271 | Self_Employed | X3 | 104 | Yes | 525206 | No |
2 | Female | 30 | RG278 | Other | X1 | 25 | No | 724718 | No |
3 | Female | 52 | RG283 | Self_Employed | X1 | 43 | Yes | 1452453 | No |
4 | Female | 76 | RG254 | Other | X1 | 57 | No | 1895762 | No |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
195720 | Female | 39 | RG279 | Self_Employed | X2 | 19 | Unknown | 1595992 | No |
195721 | Female | 46 | RG283 | Self_Employed | X2 | 27 | Yes | 1220029 | No |
195722 | Male | 68 | RG268 | Other | X3 | 104 | Yes | 1789781 | No |
195723 | Male | 30 | RG277 | Self_Employed | X2 | 15 | No | 722822 | Yes |
195724 | Female | 60 | RG268 | Self_Employed | X3 | 98 | Yes | 1837992 | Yes |
195725 rows × 9 columns
# 3. 特征預處理
# 定義分類特征和數值特征
# 分類特征列表
cat_cols = ['Gender', 'Region_Code', 'Occupation', 'Channel_Code', 'Credit_Product', 'Is_Active']
# 數值特征列表
num_cols = ['Age', 'Vintage', 'Avg_Account_Balance']# 對分類變量進行獨熱編碼
# 創建獨熱編碼器,忽略未知類別
encoder = OneHotEncoder(handle_unknown='ignore')
# 在訓練集上擬合并轉換分類特征
X_train_encoded = encoder.fit_transform(X_train[cat_cols])
# 在驗證集上轉換分類特征(使用訓練集擬合的編碼器)
X_val_encoded = encoder.transform(X_val[cat_cols])
# 在測試集上轉換分類特征
X_test_encoded = encoder.transform(test[cat_cols])# 數值特征標準化(Z-score標準化)
# 創建標準化器
scaler = StandardScaler()
# 在訓練集上擬合并轉換數值特征
X_train_num = scaler.fit_transform(X_train[num_cols])
# 在驗證集上轉換數值特征(使用訓練集擬合的標準化器)
X_val_num = scaler.transform(X_val[num_cols])
# 在測試集上轉換數值特征
X_test_num = scaler.transform(test[num_cols])# 合并處理后的特征
# 水平堆疊數值特征和編碼后的分類特征
X_train_final = np.hstack([X_train_num, X_train_encoded.toarray()])
X_val_final = np.hstack([X_val_num, X_val_encoded.toarray()])
X_test_final = np.hstack([X_test_num, X_test_encoded.toarray()])
# 打印形狀檢查
print(f"訓練集形狀: {X_train_final.shape}")
print(f"驗證集形狀: {X_val_final.shape}")
print(f"測試集形狀: {X_test_final.shape}")
輸出結果:
訓練集形狀: (156580, 53)
驗證集形狀: (39145, 53)
測試集形狀: (50000, 53)
# 4. 模型訓練與評估
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB# 定義要比較的模型
models = [("Logistic Regression", LogisticRegression(max_iter=1000, random_state=42)),("Decision Tree", DecisionTreeClassifier(max_depth=5, random_state=42)),("Random Forest", RandomForestClassifier(n_estimators=100, random_state=42)),("KNN", KNeighborsClassifier(n_neighbors=30)),("Naive Bayes", GaussianNB())
]# 評估每個模型
results = []
for name, model in models:# 訓練模型model.fit(X_train_final, y_train)# 在驗證集上預測概率# 對于不支持predict_proba的模型,使用decision_functionif hasattr(model, "predict_proba"):val_proba = model.predict_proba(X_val_final)[:, 1]else:# 對于SVM等模型,使用decision_functionval_proba = model.decision_function(X_val_final)# 將決策函數值縮放到0-1范圍val_proba = (val_proba - val_proba.min()) / (val_proba.max() - val_proba.min())# 計算AUCval_auc = roc_auc_score(y_val, val_proba)# 保存結果results.append((name, val_auc, model))print(f"{name}: AUC = {val_auc:.4f}")
輸出結果:
Logistic Regression: AUC = 0.8540
Decision Tree: AUC = 0.8595
Random Forest: AUC = 0.8477
KNN: AUC = 0.8509
Naive Bayes: AUC = 0.7988
# 5. 選擇最佳模型
best_model_name, best_auc, best_model = max(results, key=lambda x: x[1])
print(f"\n最佳模型: {best_model_name}, AUC: {best_auc:.4f}")# 在驗證集上詳細評估最佳模型
val_pred = best_model.predict(X_val_final)# 對于支持概率預測的模型,獲取概率
if hasattr(best_model, "predict_proba"):val_proba = best_model.predict_proba(X_val_final)[:, 1]
else:val_proba = best_model.decision_function(X_val_final)val_proba = (val_proba - val_proba.min()) / (val_proba.max() - val_proba.min())print("\n分類報告:")
print(classification_report(y_val, val_pred))
輸出結果:
最佳模型: Decision Tree, AUC: 0.8595分類報告:precision recall f1-score support0 0.85 0.98 0.91 298401 0.85 0.47 0.60 9305accuracy 0.85 39145macro avg 0.85 0.72 0.76 39145
weighted avg 0.85 0.85 0.84 39145
# 6. 混淆矩陣分析
cm = confusion_matrix(y_val, val_pred)
tn, fp, fn, tp = cm.ravel()print("\n混淆矩陣:")
print(f"真正例(TP): {tp} - 實際好客戶被正確識別為好客戶")
print(f"假正例(FP): {fp} - 實際壞客戶被錯誤識別為好客戶")
print(f"假反例(FN): {fn} - 實際好客戶被錯誤識別為壞客戶")
print(f"真反例(TN): {tn} - 實際壞客戶被正確識別為壞客戶")
輸出結果:
混淆矩陣:
真正例(TP): 4328 - 實際好客戶被正確識別為好客戶
假正例(FP): 737 - 實際壞客戶被錯誤識別為好客戶
假反例(FN): 4977 - 實際好客戶被錯誤識別為壞客戶
真反例(TN): 29103 - 實際壞客戶被正確識別為壞客戶
confusion_matrix(y_val, val_pred)
輸出結果:
array([[29103, 737],[ 4977, 4328]], dtype=int64)
# 7. 業務解讀
accuracy = (tp + tn) / (tp + tn + fp + fn)
good_recall = tp / (tp + fn)
bad_recall = tn / (tn + fp)print("\n業務解讀:")
print(f"- 假陽性(FP): {fp} 個實際壞客戶被錯誤分類為好客戶,可能導致壞賬損失")
print(f"- 假陰性(FN): {fn} 個實際好客戶被錯誤分類為壞客戶,損失潛在收益")
print(f"- 模型準確率: {accuracy:.2%}")
print(f"- 好客戶識別率: {good_recall:.2%} (正確識別好客戶的能力)")
print(f"- 壞客戶識別率: {bad_recall:.2%} (正確識別壞客戶的能力)")
輸出結果:
業務解讀:
- 假陽性(FP): 737 個實際壞客戶被錯誤分類為好客戶,可能導致壞賬損失
- 假陰性(FN): 4977 個實際好客戶被錯誤分類為壞客戶,損失潛在收益
- 模型準確率: 85.40%
- 好客戶識別率: 46.51% (正確識別好客戶的能力)
- 壞客戶識別率: 97.53% (正確識別壞客戶的能力)
# 8. 測試集預測與提交
# 在測試集上預測
if hasattr(best_model, "predict_proba"):test_proba = best_model.predict_proba(X_test_final)[:, 1]
else:test_proba = best_model.decision_function(X_test_final)test_proba = (test_proba - test_proba.min()) / (test_proba.max() - test_proba.min())# 生成提交文件
submission = pd.DataFrame({'ID': test['ID'],'Target': test_proba
})
# submission.to_csv('submission.csv', index=False)
print("\n提交文件已生成: submission.csv")
輸出結果:
提交文件已生成: submission.csv
上一章:機器學習實操項目03——Scikit-learn介紹及簡單分類案例
下一章:
機器學習核心知識點目錄:機器學習核心知識點目錄
機器學習實戰項目目錄:【從 0 到 1 落地】機器學習實操項目目錄:覆蓋入門到進階,大學生就業 / 競賽必備