劃與分支定界算法在金融風控信用評分卡優(yōu)化中的應用)
1. 項目概述當數(shù)學建模遇上金融風控去年帶學生打MathorCupA題“信用評分卡優(yōu)化”一出來我們團隊就意識到這絕不是一個簡單的套模型題。它本質(zhì)上是一個典型的、在強約束下的資源分配與決策優(yōu)化問題。題目要求我們基于給定的客戶數(shù)據(jù)構(gòu)建并優(yōu)化信用評分卡核心目標是最大化銀行的利潤或最小化風險損失同時必須滿足一系列現(xiàn)實業(yè)務(wù)規(guī)則比如通過率、壞賬率、風險敞口等限制。這聽起來像是機器學習問題但當你真正開始構(gòu)建目標函數(shù)和約束條件時你會發(fā)現(xiàn)它的最優(yōu)解往往藏在線性規(guī)劃Linear Programming, LP及其擴展形式如混合整數(shù)線性規(guī)劃MILP的求解器里。為什么是線性規(guī)劃因為評分卡的“優(yōu)化”動作無論是調(diào)整評分閾值、決定授信額度還是組合不同的風控策略其決策變量如是否給某個分數(shù)段的客戶放款與最終的目標利潤和約束通過率之間在題目設(shè)定的框架下通常可以表達為線性關(guān)系。你的目標函數(shù)總利潤是各客戶群利潤的線性加權(quán)和你的約束總通過人數(shù)、總壞賬金額也是線性不等式。這就把一個復雜的金融風控問題轉(zhuǎn)化成了一個標準的、可求解的數(shù)學優(yōu)化問題。網(wǎng)絡(luò)上熱詞里提到的“分支定界/分支切割算法求解MILP”正是我們當時求解核心模型的關(guān)鍵。因為有些決策變量必須是整數(shù)比如選擇哪幾張評分卡或者某個策略是否啟用這就構(gòu)成了混合整數(shù)線性規(guī)劃。直接求解MILP是NP-Hard問題而分支定界Branch-and-Bound框架是求解它的主流精確算法。簡單來說它通過不斷“分支”將問題分解為更小的子問題并“定界”快速排除那些不可能包含最優(yōu)解的分支從而在可接受的時間內(nèi)找到全局最優(yōu)解或近似最優(yōu)解。所以這個項目的核心路徑非常清晰將信用評分卡的業(yè)務(wù)優(yōu)化問題嚴謹?shù)亟3梢粋€線性規(guī)劃或混合整數(shù)線性規(guī)劃模型然后利用高效的優(yōu)化求解器如Gurobi, CPLEX或開源的OR-Tools、SCIP進行計算最終得到一整套可執(zhí)行的、最優(yōu)的信貸決策方案。下面我就把這個從業(yè)務(wù)理解到模型求解的完整鏈條拆開結(jié)合我們踩過的坑和實戰(zhàn)心得給大家捋清楚。2. 問題拆解從風控業(yè)務(wù)到數(shù)學模型拿到題目和數(shù)據(jù)千萬別急著套代碼。第一步也是最關(guān)鍵的一步是把模糊的業(yè)務(wù)需求翻譯成精確的數(shù)學語言。這決定了你的模型是否合理求解是否可行。2.1 核心決策變量定義決策變量是你的“操作手柄”。在信用評分卡優(yōu)化中通常有兩種定義方式對應不同的優(yōu)化粒度方式一基于客戶分箱的決策這是最直觀的方式。信用評分卡通常會將客戶根據(jù)分數(shù)劃分為若干個風險等級例如A、B、C、D、F五個等級。那么你的決策變量可以是x_A, x_B, ..., x_F連續(xù)變量表示對每個分數(shù)段客戶的通過率0到1之間。例如x_A 0.95表示A級客戶95%通過審批?;蛘遹_A, y_B, ..., y_F整數(shù)變量0或1表示是否對某個分數(shù)段采取“通過”策略。這常用于策略組合優(yōu)化。方式二基于評分卡閾值的決策更精細的優(yōu)化是直接調(diào)整評分卡的審批閾值Cut-off Score。例如原閾值是600分高于600的通過。優(yōu)化后可能變?yōu)?10分。這時決策變量可以是閾值S本身。但這樣目標函數(shù)和約束關(guān)于S通常是非線性的因為客戶分布是離散的需要做一些線性化處理或?qū)⑵滢D(zhuǎn)化為第一種方式。在我們的解題中采用了第一種方式因為它能更自然地與線性規(guī)劃結(jié)合。我們將客戶按初始評分分成了20個組bin決策變量x_i表示第i組客戶的放款比例。2.2 目標函數(shù)構(gòu)建利潤最大化銀行的最終目的是盈利。因此目標函數(shù)通常是期望利潤最大化。對于每一組客戶i我們需要計算單客期望收入貸款利息收入。假設(shè)貸款額度為L_i利率為r則收入為L_i * r。單客期望損失即壞賬損失。這需要用到題目提供的違約概率PD和違約損失率LGD。期望損失 L_i * PD_i * LGD_i。單客期望利潤利潤_i L_i * r - L_i * PD_i * LGD_i - 運營成本。其中運營成本可能是一個固定值或比例。那么對于該組所有客戶總期望利潤就是總利潤 Σ (客戶數(shù)_i * x_i * 利潤_i)。 這個Σ (客戶數(shù)_i * x_i * 利潤_i)就是一個關(guān)于決策變量x_i的線性函數(shù)完美符合線性規(guī)劃的要求。注意這里的PD_i和LGD_i需要從題目數(shù)據(jù)中估計。通常同一分數(shù)段內(nèi)的客戶具有相似的PD。我們可以用該分數(shù)段歷史違約客戶的占比來估算PDLGD有時題目會直接給出或假設(shè)一個固定值如45%。這是建模的第一個關(guān)鍵假設(shè)需要明確說明。2.3 約束條件梳理業(yè)務(wù)的緊箍咒光追求利潤不行銀行經(jīng)營有嚴格的風險控制和合規(guī)要求。這些就構(gòu)成了模型的約束條件同樣是線性的??傮w通過率約束銀行可能希望控制整體業(yè)務(wù)規(guī)?;蛲ㄟ^率在一個范圍內(nèi)??傮w通過客戶數(shù) Σ (客戶數(shù)_i * x_i)約束可能為總體通過率下限 (總體通過客戶數(shù) / 總客戶數(shù)) 總體通過率上限壞賬率約束控制整體風險水平。總壞賬金額 Σ (客戶數(shù)_i * x_i * L_i * PD_i * LGD_i)總放貸金額 Σ (客戶數(shù)_i * x_i * L_i)約束為(總壞賬金額 / 總放貸金額) 壞賬率上限。注意這是一個比值約束但可以通過變形轉(zhuǎn)化為線性約束總壞賬金額 壞賬率上限 * 總放貸金額。高風險客戶限制對評分最低的幾組客戶如F級可能嚴格限制其通過率甚至禁止通過。x_F 0.05或x_F 0預算或資本約束總放貸金額不能超過可用資金總額B。Σ (客戶數(shù)_i * x_i * L_i) B決策變量自身約束0 x_i 1對于某些需要整數(shù)決策的則y_i ∈ {0, 1}。將這些目標函數(shù)和約束條件用數(shù)學公式寫出來一個完整的信用評分卡優(yōu)化線性規(guī)劃模型就誕生了。它看起來就像這樣Maximize: Σ_i (N_i * x_i * P_i) Subject to: Σ_i (N_i * x_i) / N_total P_min Σ_i (N_i * x_i * L_i * PD_i * LGD_i) LR_max * Σ_i (N_i * x_i * L_i) Σ_i (N_i * x_i * L_i) B 0 x_i 1, for all i (可能還有 x_j C_j 對于特定高風險組j)其中N_i是i組客戶數(shù)P_i是單客利潤。3. 模型求解算法選擇與實現(xiàn)細節(jié)模型建好了怎么解對于純線性規(guī)劃LP有成熟的單純形法Simplex和內(nèi)點法Interior-Point可以高效求解全局最優(yōu)解。但我們的模型往往包含整數(shù)變量比如必須選擇3張評分卡中的2張這就變成了MILP需要更專門的算法。3.1 求解器你的計算引擎不要試圖自己從頭實現(xiàn)單純形法或分支定界算法那是科研人員的工作。我們應該站在巨人的肩膀上使用成熟的優(yōu)化求解器商業(yè)求解器性能最強Gurobi學術(shù)界和工業(yè)界公認的標桿對學術(shù)免費速度和穩(wěn)定性極佳。MathorCup這類比賽通常允許使用。CPLEXIBM的老牌產(chǎn)品同樣非常強大。它們都提供了Python、Java、C等接口集成非常方便。開源求解器免費可選OR-Tools (Google)谷歌推出的優(yōu)化工具套件內(nèi)置了多個求解器對MILP支持良好文檔豐富是比賽中的熱門選擇。SCIP目前最強大的非商業(yè)開源混合整數(shù)規(guī)劃求解器之一。PuLP (Python)一個建模庫可以調(diào)用多種后端求解器包括CBC、GLPK等。我們的選擇是Python PuLP Gurobi。PuLP提供了非常直觀的建模語法而Gurobi作為后端求解器保證了求解效率。對于無法獲得Gurobi許可的情況PuLP默認的CBC求解器也能應付中小規(guī)模問題。3.2 求解過程與代碼框架下面是一個高度簡化的、基于PuLP的核心代碼框架展示了如何將上述數(shù)學模型“翻譯”成代碼import pulp import pandas as pd # 1. 讀取和處理數(shù)據(jù) data pd.read_csv(customer_data.csv) # 假設(shè)數(shù)據(jù)已按評分分組并計算好所需字段 # data 中包含列bin, customer_count, avg_loan, pd, lgd, interest_rate, operation_cost # 2. 創(chuàng)建問題實例 # 最大化問題 prob pulp.LpProblem(Credit_Scorecard_Optimization, pulp.LpMaximize) # 3. 定義決策變量 # 為每個分箱創(chuàng)建一個連續(xù)變量代表放款比例范圍在[0, 1] x pulp.LpVariable.dicts(x, data[bin].tolist(), lowBound0, upBound1) # 4. 構(gòu)建目標函數(shù) # 計算每個分箱的單客期望利潤 data[profit_per_customer] data[avg_loan] * data[interest_rate] - \ data[avg_loan] * data[pd] * data[lgd] - \ data[operation_cost] # 總利潤 sum(客戶數(shù) * 放款比例 * 單客利潤) prob pulp.lpSum([data.loc[i, customer_count] * x[data.loc[i, bin]] * data.loc[i, profit_per_customer] for i in data.index]) # 5. 添加約束條件 # 5.1 總體通過率約束 (例如不低于30%) total_customers data[customer_count].sum() prob pulp.lpSum([data.loc[i, customer_count] * x[data.loc[i, bin]] for i in data.index]) 0.3 * total_customers # 5.2 壞賬率約束 (例如不超過5%) # 總壞賬金額 total_bad_debt pulp.lpSum([data.loc[i, customer_count] * x[data.loc[i, bin]] * \ data.loc[i, avg_loan] * data.loc[i, pd] * data.loc[i, lgd] for i in data.index]) # 總放貸金額 total_loan pulp.lpSum([data.loc[i, customer_count] * x[data.loc[i, bin]] * data.loc[i, avg_loan] for i in data.index]) prob total_bad_debt 0.05 * total_loan # 5.3 高風險組約束 (例如最低分箱通過率不超過1%) lowest_bin data[bin].min() # 假設(shè)bin是數(shù)值或可排序 prob x[lowest_bin] 0.01 # 6. 求解問題 # 使用CBC求解器開源如果安裝了Gurobi可以替換為 pulp.GUROBI() prob.solve(pulp.PULP_CBC_CMD(msgFalse)) # 7. 輸出結(jié)果 print(f求解狀態(tài): {pulp.LpStatus[prob.status]}) print(f最大化總利潤: {pulp.value(prob.objective):.2f}) for b in data[bin]: if x[b].varValue 1e-5: # 忽略接近零的值 print(f分箱 : 建議放款比例 {x[b].varValue:.3f})這段代碼清晰地展示了從建模到求解的流水線。關(guān)鍵在于第4步和第5步如何正確地將業(yè)務(wù)邏輯轉(zhuǎn)化為線性表達式。3.3 關(guān)于“分支定界”算法當我們引入整數(shù)變量時例如y_i ∈ {0,1}表示是否對第i組客戶采用高利率策略PuLP和Gurobi在調(diào)用prob.solve()時會自動啟用分支定界算法來求解這個MILP問題。你不需要手動實現(xiàn)它但理解其原理對調(diào)試和解釋結(jié)果很有幫助松弛首先忽略整數(shù)約束求解對應的線性規(guī)劃松弛問題LP Relaxation。這會得到一個目標值上界對于最大化問題。分支如果松弛解中某個整數(shù)變量y_i的值是小數(shù)比如0.7就創(chuàng)建兩個新的子問題一個強制y_i 0另一個強制y_i 1。這就像一棵樹的分叉。定界與剪枝求解每個子問題的松弛解。如果某個子問題的解比當前已知的整數(shù)解還差或者它的松弛解都無法超過當前最優(yōu)整數(shù)解那么這個分支就可以被“剪掉”不再探索因為它不可能產(chǎn)生更好的整數(shù)解。迭代不斷分支、求解、定界、剪枝直到找到滿足整數(shù)要求的、且被證明是最優(yōu)或接近最優(yōu)的解。在求解日志中你可能會看到“Gap”在逐漸縮小這個Gap就是當前最優(yōu)整數(shù)解與全局上界之間的差距是衡量求解進度和精度的關(guān)鍵指標。4. 方案優(yōu)化與策略分析得到一組最優(yōu)的x_i放款比例只是第一步。更重要的是如何解讀這個結(jié)果并形成可執(zhí)行的業(yè)務(wù)策略。4.1 結(jié)果解讀與策略生成求解器輸出的x_i可能是一些小數(shù)如x_A0.95, x_B0.8, x_C0.3, x_D0.01, x_F0.0。這直接翻譯成業(yè)務(wù)策略A級客戶優(yōu)質(zhì)客戶給予95%的通過率幾乎全部放行。B級客戶次優(yōu)客戶通過率80%可以適當收緊。C級客戶中等風險客戶通過率30%需要嚴格篩選。D級客戶高風險客戶僅1%通過近乎拒絕。F級客戶極高風險客戶完全拒絕?;诖丝梢灾贫ú町惢瘜徟呗宰詣油ㄟ^評分高于A閾值的系統(tǒng)自動通過。人工復審評分在B和C區(qū)間的轉(zhuǎn)入人工審批流程結(jié)合其他信息綜合判斷。自動拒絕評分低于D閾值的系統(tǒng)自動拒絕。4.2 敏感性分析與“What-If”場景線性規(guī)劃的一個巨大優(yōu)勢是便于進行敏感性分析Sensitivity Analysis。這能回答業(yè)務(wù)非常關(guān)心的問題“如果某個條件變化了我的最優(yōu)策略和最大利潤會怎樣變”約束右端值變化的影響例如如果監(jiān)管要求的壞賬率上限從5%收緊到4%我的最大利潤會下降多少這個信息在求解報告中稱為“影子價格Shadow Price”或“對偶價格Dual Price”。它量化了放松或收緊一單位約束所帶來的邊際利潤變化。這對于資源分配和談判極具價值。目標函數(shù)系數(shù)變化的影響如果某個客戶群的利率r或違約率PD預估發(fā)生了變化當前的最優(yōu)解是否依然最優(yōu)求解器提供的“目標系數(shù)允許增減范圍”可以告訴你答案。在比賽中進行深入的敏感性分析并據(jù)此提出動態(tài)策略調(diào)整建議是論文的重要加分項。例如你可以指出“在當前市場環(huán)境下壞賬率約束是限制利潤的主要瓶頸其影子價格為X。這意味著如果銀行能通過提升催收能力將壞賬損失降低1個百分點理論上可增加Y百萬元利潤。”4.3 模型擴展多評分卡與策略組合原題可能更復雜比如提供多張基礎(chǔ)評分卡如“收益優(yōu)先型”、“風險規(guī)避型”要求你從中選擇幾張進行組合并對不同客戶群體應用不同的評分卡。這就引入了0-1整數(shù)變量。定義變量z_k ∈ {0,1}是否選用第k張評分卡。定義變量y_{i,k} ∈ {0,1}是否對第i組客戶使用第k張評分卡。需要添加約束Σ_k z_k K最多選K張卡且y_{i,k} z_k只有被選中的卡才能被使用。目標函數(shù)變?yōu)镸ax Σ_i Σ_k (客戶數(shù)_i * y_{i,k} * 利潤_{i,k})。這個模型明顯更復雜變量更多求解時間更長。但建模思路一脈相承只是約束條件更豐富了。這時求解器的性能差異就會體現(xiàn)出來。5. 實戰(zhàn)心得與避坑指南最后分享一些在實戰(zhàn)中總結(jié)出來的、教科書上不會寫的經(jīng)驗。5.1 數(shù)據(jù)預處理是地基模型再漂亮數(shù)據(jù)不準全白搭。缺失值處理對于關(guān)鍵的PD、LGD字段如果缺失不能簡單刪除或填0。需要根據(jù)業(yè)務(wù)邏輯用同組均值、中位數(shù)或通過簡單模型如基于其他特征的回歸進行插補并說明處理方法。異常值處理對于明顯不符合邏輯的極端值如貸款額度為負要查明原因是數(shù)據(jù)錯誤還是特殊業(yè)務(wù)如沖正交易。通常需要與業(yè)務(wù)方確認或采用蓋帽法Capping進行處理。變量轉(zhuǎn)換線性規(guī)劃要求線性關(guān)系。如果原始變量與目標之間可能存在非線性可以考慮分段線性化或引入輔助變量。但在信用評分中經(jīng)過分箱處理后組內(nèi)用線性近似通常是可接受的。5.2 模型假設(shè)必須清晰所有模型都是對現(xiàn)實的簡化必須明確你的假設(shè)。獨立性假設(shè)我們假設(shè)不同客戶之間的違約是獨立的。現(xiàn)實中可能存在系統(tǒng)性風險導致違約相關(guān)但題目數(shù)據(jù)通常不包含這類信息。參數(shù)穩(wěn)定性假設(shè)我們使用歷史數(shù)據(jù)估計的PD、LGD來預測未來假設(shè)這些參數(shù)在未來一段時間內(nèi)是穩(wěn)定的。明確寫下這些假設(shè)并在論文的“模型評價與推廣”部分討論這些假設(shè)不成立時的影響這體現(xiàn)了建模的嚴謹性。5.3 求解效率與規(guī)模平衡問題規(guī)模客戶分箱數(shù)決策變量數(shù)不宜過多也不宜過少。過多如超過1000個可能導致求解變慢過少如少于10個則策略過于粗糙失去優(yōu)化意義。通常20-50個分箱是一個合理的范圍。整數(shù)變量帶來的計算挑戰(zhàn)MILP的求解時間隨整數(shù)變量數(shù)量指數(shù)級增長。如果模型中有大量0-1變量求解可能非常耗時。可以嘗試先求解LP松弛問題觀察哪些變量在松弛解中已經(jīng)是0或1將其固定。設(shè)置合理的求解時間限制Time Limit和最優(yōu)間隙MIP Gap。比如設(shè)置“在1小時內(nèi)找到Gap小于1%的解即可”這在商業(yè)應用中很常見。使用啟發(fā)式方法如貪心算法先找到一個較好的可行解作為求解器的初始解Warm Start可以大幅加速求解過程。5.4 結(jié)果驗證與業(yè)務(wù)合理性檢查求解器給出的“數(shù)學最優(yōu)解”未必是“業(yè)務(wù)可行解”。檢查極端值是否出現(xiàn)了某個分箱通過率為99.9%而相鄰分箱為0%這種跳躍過大的情況這可能在數(shù)學上最優(yōu)但業(yè)務(wù)上難以解釋風險是連續(xù)的??梢钥紤]添加平滑性約束如|x_i - x_{i1}| δ。進行壓力測試用另一份驗證集Out-of-Sample數(shù)據(jù)按照優(yōu)化后的策略模擬運行計算實際的關(guān)鍵指標利潤、壞賬率看是否與模型預測相符。這是檢驗模型泛化能力的金標準。與基準策略對比一定要設(shè)置一個基準策略例如“所有分數(shù)高于600的客戶全部通過”。清晰地展示你的優(yōu)化策略相比基準策略在利潤、風險等指標上提升了多少百分比用數(shù)據(jù)說話。信用評分卡優(yōu)化是一個完美的交叉領(lǐng)域課題它要求你既懂金融風控的業(yè)務(wù)邏輯又能熟練運用運籌優(yōu)化的數(shù)學工具。通過線性規(guī)劃建模我們可以將復雜的業(yè)務(wù)決策問題轉(zhuǎn)化為清晰的計算問題從而找到在既定規(guī)則下的“最優(yōu)解”。這個過程本身就是數(shù)據(jù)驅(qū)動決策的核心體現(xiàn)。希望這份從實戰(zhàn)中總結(jié)的指南能幫你下次面對類似問題時思路更清晰下手更有力。記住建模的關(guān)鍵不在于用了多復雜的算法而在于你是否準確地把業(yè)務(wù)問題“翻譯”成了數(shù)學語言。