動(dòng)的互聯(lián)網(wǎng)貸款客戶聚類與風(fēng)險(xiǎn)預(yù)警實(shí)戰(zhàn))
這兩天幫一位27屆的學(xué)弟整理計(jì)算機(jī)畢設(shè)源碼題目正好是《基于多維特征融合的互聯(lián)網(wǎng)貸款客戶聚類與風(fēng)險(xiǎn)預(yù)警研究》和配套的《基于數(shù)據(jù)挖掘的互聯(lián)網(wǎng)貸款用途與風(fēng)險(xiǎn)定價(jià)可視化研究》。乍一看像是兩個(gè)題目實(shí)際是一個(gè)完整的風(fēng)控?cái)?shù)據(jù)挖掘閉環(huán)先把客戶按照多維特征聚成不同群體再做風(fēng)險(xiǎn)預(yù)警最后把貸款用途、利率、逾期率之間的關(guān)系用可視化大屏呈現(xiàn)出來。拿到這類題目容易發(fā)懵范圍太大不知道該先做什么。我把從數(shù)據(jù)清洗到出具整套源碼的全過程拆一遍包括選型思路、參數(shù)調(diào)優(yōu)、踩過的坑盡量把能直接復(fù)現(xiàn)的細(xì)節(jié)都交代清楚。做過金融風(fēng)控類畢設(shè)的人都知道這類項(xiàng)目最容易被卡住的不是模型而是“業(yè)務(wù)邏輯與數(shù)據(jù)特征對(duì)不對(duì)得上”。比如為什么要把聚類和風(fēng)險(xiǎn)預(yù)警放一起為什么貸款用途要和風(fēng)險(xiǎn)定價(jià)關(guān)聯(lián)。先把這個(gè)題目的設(shè)計(jì)思路講明白后續(xù)每一步才走得順。1. 項(xiàng)目整體設(shè)計(jì)與拆解1.1 題目到底在考什么“多維特征融合”這個(gè)詞聽起來很高端其實(shí)就是把客戶畫像里分散的信息整合起來形成一個(gè)能同時(shí)反映還款能力、還款意愿、資金需求緊急度的特征集。傳統(tǒng)做法可能只盯著收入、負(fù)債或者歷史逾期某一個(gè)字段效果往往不穩(wěn)定。一個(gè)用戶可能在單一維度上表現(xiàn)正常但把收入負(fù)債比、近3個(gè)月征信查詢次數(shù)、當(dāng)前逾期天數(shù)放在一起看風(fēng)險(xiǎn)特征立刻暴露出來??蛻艟垲惤鉀Q的是“客群分層”問題。不同客群的風(fēng)險(xiǎn)驅(qū)動(dòng)因素不一樣比如剛畢業(yè)的學(xué)生群體負(fù)債低但收入穩(wěn)定性差經(jīng)營類客群收入高但資金周轉(zhuǎn)波動(dòng)大把這些人混在一起訓(xùn)練模型預(yù)警準(zhǔn)頭會(huì)大打折扣。所以題目先要求聚類再要求預(yù)警本質(zhì)上是希望用無監(jiān)督方法先找出結(jié)構(gòu)性差異再針對(duì)不同分群搭建有監(jiān)督的風(fēng)險(xiǎn)判斷。風(fēng)險(xiǎn)定價(jià)可視化的核心邏輯也很簡單風(fēng)險(xiǎn)越高的客戶貸款利率理應(yīng)越高。但這還不夠還需要回答“貸款用途對(duì)違約風(fēng)險(xiǎn)有沒有顯著影響”這個(gè)問題。買房裝修、日常消費(fèi)、生意周轉(zhuǎn)、教育醫(yī)療不同用途背后的資金去向和真實(shí)還款來源不同定價(jià)策略也應(yīng)該有差異。把這個(gè)差異通過散點(diǎn)圖、漏斗圖、熱力圖展示出來就是可視化研究的價(jià)值。1.2 整體技術(shù)架構(gòu)與代碼組織我的技術(shù)選型以Python為主原因很簡單數(shù)據(jù)挖掘生態(tài)最成熟sklearn直接提供聚類和分類模型pandas處理表格數(shù)據(jù)非常順手可視化用ECharts做前端展示后端用Flask暴露接口。整份源碼分成四個(gè)模塊data_process/原始數(shù)據(jù)導(dǎo)入、缺失值處理、異常值截?cái)唷⑻卣鞴こ套罱K輸出標(biāo)準(zhǔn)化后的建模寬表。cluster_model/PCA降維、K-Means聚類、層次聚類輔助驗(yàn)證、輪廓系數(shù)評(píng)估、分群畫像輸出。risk_model/預(yù)警標(biāo)簽構(gòu)造、訓(xùn)練集/測(cè)試集劃分、邏輯回歸與隨機(jī)森林對(duì)比、AUC與KS指標(biāo)計(jì)算。visualization/Flask后端接口ECharts前端大屏包括聚類散點(diǎn)圖、風(fēng)險(xiǎn)漏斗圖、用途利率散點(diǎn)圖。這個(gè)組織方式不是隨便拍的而是按照“數(shù)據(jù) - 人群 - 風(fēng)險(xiǎn) - 表達(dá)”的順序來安排。每個(gè)模塊的產(chǎn)物會(huì)成為下一個(gè)模塊的輸入。比如聚類結(jié)果作為一個(gè)新字段喂給風(fēng)控模型風(fēng)控模型的輸出結(jié)果再作為可視化大屏的數(shù)據(jù)源。這樣各模塊之間耦合度低論文里也容易畫出層次清晰的架構(gòu)圖。選擇Flask而不直接用Django是因?yàn)楫呍O(shè)場(chǎng)景下不需要用戶登錄、后臺(tái)管理這些偏工程的能力Flask輕量、接口邏輯簡單前端用原生HTMLECharts就能跑。如果你已經(jīng)裝了Anaconda直接跑pip install flask pandas scikit-learn matplotlib就能把環(huán)境湊齊不需要額外折騰數(shù)據(jù)庫。數(shù)據(jù)量在十萬級(jí)以下時(shí)CSV文件配合pandas足夠支撐整個(gè)項(xiàng)目了。2. 數(shù)據(jù)預(yù)處理與多維特征融合2.1 數(shù)據(jù)來源與核心字段梳理這個(gè)題目沒有公開的標(biāo)準(zhǔn)數(shù)據(jù)集需要自己構(gòu)造或合拼。常見的做法是參考Lending Club的公開字段結(jié)構(gòu)自己構(gòu)造一份包含客戶基本信息、歷史行為、貸款字段的模擬數(shù)據(jù)。字段設(shè)計(jì)要貼合國內(nèi)互聯(lián)網(wǎng)貸款的業(yè)務(wù)習(xí)慣至少要覆蓋下面幾類特征類別代表字段用途說明客戶基本盤年齡、性別、收入、學(xué)歷、職業(yè)類型刻畫還款能力的基礎(chǔ)信息負(fù)債與需求負(fù)債總額、貸款金額、貸款期限、申請(qǐng)用途判斷資金壓力與資金去向歷史行為征信查詢次數(shù)、歷史逾期次數(shù)、當(dāng)前逾期天數(shù)、歷史貸款筆數(shù)判斷還款意愿與信用歷史行為融合特征收入負(fù)債比、近6個(gè)月平均查詢次數(shù)、額度使用率、收入穩(wěn)定性多維特征融合后的核心變量我在做數(shù)據(jù)準(zhǔn)備時(shí)特別注意“貸款用途”字段題目里專門提到用途與風(fēng)險(xiǎn)定價(jià)可視化所以這個(gè)字段必須保留而且不能只做成啞變量還要在后續(xù)聚類和預(yù)警里作為分群的特征之一。用途一般包含經(jīng)營周轉(zhuǎn)、日常消費(fèi)、裝修、教育、醫(yī)療、購車、旅游等建議統(tǒng)一編碼成類別再結(jié)合數(shù)值特征做Embedding式融合。如果你用的是自己爬來的數(shù)據(jù)格式肯定很亂。清洗的第一步是把所有字段統(tǒng)一命名、統(tǒng)一單位金額統(tǒng)一換算為元時(shí)間字段統(tǒng)一為YYYY-MM-DD。第二步是檢查取值范圍比如年齡不可能超過100歲貸款金額不能為負(fù)數(shù)征信查詢次數(shù)必須是整數(shù)這些約束都要寫進(jìn)清洗函數(shù)里而不是靠肉眼核對(duì)。2.2 清洗、標(biāo)準(zhǔn)化與特征構(gòu)造數(shù)據(jù)清洗這一塊最容易出問題是缺失值比例高的時(shí)候。貸款數(shù)據(jù)里收入字段經(jīng)常缺失直接刪除會(huì)損失大量樣本。我的做法是先用缺失比例排序低于5%的字段用中位數(shù)填充高于30%的字段直接丟棄中間的字段用“是否缺失”作為一個(gè)二值特征加入模型。這樣既保住了樣本量又把缺失信息本身變成了特征。異常值不能只靠describe()看一眼就完事。收入字段的99分位可能高達(dá)幾十萬直接參與聚類會(huì)讓K-Means的重心計(jì)算被極值帶偏。穩(wěn)妥的截?cái)喾椒ㄊ侨?%到99%分位小于下分位或大于上分位的值統(tǒng)一壓到邊界。實(shí)際操作里可以這樣寫def winsorize_series(s, lower0.01, upper0.99): q_low s.quantile(lower) q_high s.quantile(upper) return s.clip(q_low, q_high)特征工程是提高模型效果最劃算的一步。原始字段只能提供單點(diǎn)信息真正的風(fēng)險(xiǎn)信號(hào)往往藏在比值、頻次、趨勢(shì)里。我做過的項(xiàng)目中下面這幾個(gè)手工衍生特征對(duì)聚類和預(yù)警的幫助最大debt_to_income 總負(fù)債 / 年收入直接衡量還款壓力數(shù)值越高風(fēng)險(xiǎn)越大。recent_query_6m 近6個(gè)月征信查詢次數(shù)查詢次數(shù)暴增通常代表多頭借貸。overdue_ratio 歷史逾期次數(shù) / 歷史貸款筆數(shù)衡量用戶還款習(xí)慣的穩(wěn)定性。usage_rate 貸款金額 / 信用卡額度代表資金緊張程度。income_stability 近6個(gè)月收入標(biāo)準(zhǔn)差 / 平均收入收入波動(dòng)越大越可能斷供。這些衍生特征加進(jìn)去之后你會(huì)明顯感覺到客戶之間的差異性被拉出來了。后面K-Means分出來的人群不再只是“年齡大的人”和“年齡小的人”而是“高負(fù)債、高查詢、經(jīng)營周轉(zhuǎn)型”和“低負(fù)債、穩(wěn)定收入、日常消費(fèi)型”業(yè)務(wù)解釋性強(qiáng)得多。2.3 多維特征融合策略特征融合在工程上的常見做法不是把變量隨便拼在一起而是區(qū)分不同類型采用不同策略。數(shù)值特征用標(biāo)準(zhǔn)化類別特征用獨(dú)熱編碼或目標(biāo)編碼時(shí)間特征拆成年、月、是否工作日等周期項(xiàng)再把這些處理后的特征一起拼成寬表。拼接之后通常會(huì)有幾十維如果直接拿去聚類稀疏性和噪聲會(huì)干擾距離計(jì)算。這時(shí)就需要降維。最常用的方案是PCA但PCA本身是無監(jiān)督方法它只保留方差最大的方向不一定對(duì)業(yè)務(wù)解釋友好。我會(huì)同時(shí)保留兩個(gè)層面的結(jié)果聚類散點(diǎn)圖用PCA的前兩個(gè)主成分做展示建模數(shù)據(jù)用用標(biāo)準(zhǔn)化后的全量特征不強(qiáng)行壓到極低維度。這樣既照顧了可視化需求又不損失建模信息。真正意義上的多維融合我還會(huì)做一步“特征選擇”。通過隨機(jī)森林的特征重要性排序把重要性低于閾值的字段剔除只保留對(duì)風(fēng)險(xiǎn)區(qū)分度最高的二十個(gè)左右特征。這樣做的好處是防止聚類被無關(guān)變量帶偏比如“客戶姓名長度”這種字段如果存在一定會(huì)干擾距離計(jì)算但它和風(fēng)險(xiǎn)沒有關(guān)系。把所有特征無腦拼進(jìn)去是新手最常見的錯(cuò)誤。3. 客戶聚類從K值選擇到分群畫像3.1 為什么先聚類再做風(fēng)險(xiǎn)預(yù)警一個(gè)很容易被忽視的問題是既然我們已經(jīng)有監(jiān)督模型可以做預(yù)警為什么還要先花力氣聚類我的理解是互聯(lián)網(wǎng)貸款客戶天生就是異質(zhì)的不同人群的風(fēng)險(xiǎn)驅(qū)動(dòng)因素完全不同。單一模型用一個(gè)全局閾值判斷所有客戶會(huì)犧牲不同群體的差異。舉個(gè)例子一個(gè)年收入50萬的個(gè)體戶偶爾逾期5天但貸款用途是備貨周轉(zhuǎn)還款來源清晰一個(gè)剛?cè)肼氃率杖?000元的白領(lǐng)從未逾期但貸款用途是分期買手機(jī)負(fù)債率已經(jīng)超過60%。如果用全局模型打分很可能個(gè)體戶被標(biāo)記為風(fēng)險(xiǎn)更高但實(shí)際爆雷概率也許低于那個(gè)負(fù)債已經(jīng)到頂?shù)陌最I(lǐng)。聚類能幫我們先識(shí)別出這種結(jié)構(gòu)性差異再在每個(gè)客群內(nèi)部分別評(píng)估風(fēng)險(xiǎn)。同時(shí)聚類結(jié)果本身就是很好的業(yè)務(wù)標(biāo)簽。銀行和消金公司非常看重客群分層不同層級(jí)用不同營銷策略、不同利率、不同額度。畢設(shè)里能把這層意思講透評(píng)委通常會(huì)覺得你對(duì)業(yè)務(wù)有理解而不是只會(huì)調(diào)包。3.2 K-Means與層次聚類的實(shí)踐聚類算法我用的是K-Means主方案原因是它在樣本量幾萬到幾十萬時(shí)效率高結(jié)果也相對(duì)好解釋。但K-Means對(duì)初始中心敏感對(duì)離群點(diǎn)敏感所以前面提到的異常值截?cái)嗪蜆?biāo)準(zhǔn)化必須做干凈。為了避免隨機(jī)種子帶來的不穩(wěn)定性我固定了random_state42并且跑了多組K值取輪廓系數(shù)的平均值再選K。K值的選擇我同時(shí)用了兩種方法。第一種是肘部法則畫出簇內(nèi)誤差平方和SSE隨K值變化的曲線找拐點(diǎn)第二種是輪廓系數(shù)直接計(jì)算不同K下的平均輪廓系數(shù)選最高的K。兩者結(jié)論不一致時(shí)優(yōu)先參考輪廓系數(shù)因?yàn)镾SE曲線很多時(shí)候沒有明顯拐點(diǎn)。from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score scores [] for k in range(2, 9): model KMeans(n_clustersk, random_state42, n_init10) labels model.fit_predict(X_scaled) scores.append(silhouette_score(X_scaled, labels)) best_k range(2, 9)[scores.index(max(scores))]除了K-Means我還會(huì)跑一次層次聚類作為交叉驗(yàn)證。層次聚類可以畫出樹狀圖直觀看出每個(gè)簇的分裂過程特別適合在論文里展示聚類邏輯。但層次聚類的計(jì)算復(fù)雜度偏高樣本超過五萬就慢得難受所以只用它在一個(gè)小規(guī)模抽樣子集上驗(yàn)證。兩個(gè)算法得出的簇?cái)?shù)一致時(shí)結(jié)論會(huì)更有說服力。聚類散點(diǎn)圖一定是用PCA降維后畫的不然高維空間只能看兩兩組合無法呈現(xiàn)群體邊界。實(shí)操中可以先PCA降到二維再以散點(diǎn)圖著色展示聚類結(jié)果。每個(gè)簇的中心點(diǎn)可以用紅色X標(biāo)記這樣即使客戶樣本點(diǎn)重疊嚴(yán)重也能看出分群重心的大致位置。3.3 聚類結(jié)果畫像與業(yè)務(wù)解讀聚類完成后我習(xí)慣做一張“分群畫像表”把每個(gè)簇在各個(gè)特征上的均值列出來然后根據(jù)均值特征給簇起一個(gè)有業(yè)務(wù)含義的名字。這一步很關(guān)鍵論文里的分析深度全靠這里體現(xiàn)。比如做出來的結(jié)果可能是這樣分群收入均值負(fù)債率均值近6月查詢次數(shù)逾期率主要用途業(yè)務(wù)標(biāo)簽01.2萬18%2.10.8%裝修、購車優(yōu)質(zhì)穩(wěn)健型1800055%6.84.2%日常消費(fèi)、教育資金緊張型22.5萬65%9.37.5%經(jīng)營周轉(zhuǎn)高杠桿經(jīng)營型“優(yōu)質(zhì)穩(wěn)健型”客戶收入不低、負(fù)債不高逾期率極低適合推低息大額產(chǎn)品“資金緊張型”客戶收入偏低但查詢次數(shù)多存在多頭借貸跡象應(yīng)該控制額度并提高利率“高杠桿經(jīng)營型”客戶收入高但負(fù)債率也高風(fēng)險(xiǎn)缺口在于現(xiàn)金流波動(dòng)需要結(jié)合經(jīng)營流水?dāng)?shù)據(jù)做二次核驗(yàn)。這些畫像結(jié)論看起來不復(fù)雜但需要你真的去統(tǒng)計(jì)均值并觀察差異。我通常會(huì)把每個(gè)簇的特征均值做成橫向柱狀對(duì)比圖再用雷達(dá)圖展示三四個(gè)核心特征的相對(duì)水平。這些圖放在畢設(shè)里比一堆數(shù)字直觀得多評(píng)委掃一眼就知道聚類是有效的。4. 風(fēng)險(xiǎn)預(yù)警與風(fēng)險(xiǎn)定價(jià)模型4.1 預(yù)警標(biāo)簽怎么打風(fēng)險(xiǎn)預(yù)警屬于有監(jiān)督學(xué)習(xí)第一步是確定“什么是壞用戶”。公開數(shù)據(jù)不會(huì)直接給你一個(gè)違約標(biāo)簽所以需要自己根據(jù)業(yè)務(wù)含義定義。我的定義規(guī)則是當(dāng)前逾期天數(shù)30天標(biāo)記為高風(fēng)險(xiǎn)同時(shí)結(jié)合未來三個(gè)月的還款表現(xiàn)如果用戶后續(xù)逾期超過60天也標(biāo)記為壞樣本。這句話聽起來簡單但要注意標(biāo)簽泄漏。如果直接用“當(dāng)前是否逾期”作為標(biāo)簽再把“當(dāng)前逾期天數(shù)”作為特征模型會(huì)學(xué)到一個(gè)恒等映射看起來AUC接近1.0實(shí)際毫無意義。正確做法是刪除“當(dāng)前逾期天數(shù)”這個(gè)字段只保留歷史行為特征比如過去12個(gè)月的逾期次數(shù)、查詢次數(shù)、負(fù)債變化等。對(duì)于沒有未來還款表現(xiàn)的數(shù)據(jù)也可以用無監(jiān)督的異常檢測(cè)思路來輔助打標(biāo)簽。把異常分?jǐn)?shù)排名前10%的用戶視為潛在風(fēng)險(xiǎn)客戶再結(jié)合規(guī)則標(biāo)簽獲得一個(gè)半監(jiān)督訓(xùn)練集。但畢設(shè)場(chǎng)景下我更推薦直接構(gòu)造模擬壞客戶在正常客戶中隨機(jī)注入高逾期特征再標(biāo)記為高風(fēng)險(xiǎn)。這樣模型學(xué)的是特征之間的組合關(guān)系而不是某一列的復(fù)制粘貼。4.2 預(yù)警模型的選擇與訓(xùn)練我同時(shí)跑了邏輯回歸和隨機(jī)森林原因是兩者各有優(yōu)勢(shì)論文里可以做對(duì)比。邏輯回歸是風(fēng)控場(chǎng)景的基準(zhǔn)模型系數(shù)正負(fù)和大小能直接解釋為“特征每增加一個(gè)單位風(fēng)險(xiǎn)對(duì)數(shù)幾率的變化”可解釋性強(qiáng)隨機(jī)森林能自動(dòng)捕捉非線性關(guān)系A(chǔ)UC通常更高但黑盒感強(qiáng)。訓(xùn)練時(shí)要特別注意類別不平衡。正常情況下好客戶可能占90%以上壞客戶不到10%。如果直接訓(xùn)練模型會(huì)傾向于把所有樣本預(yù)測(cè)為好客戶雖然準(zhǔn)確率很高AUC卻并不一定差但壞客戶一個(gè)也撈不上來。解決思路有三個(gè)一是用class_weightbalanced讓模型自動(dòng)調(diào)整類別權(quán)重二是對(duì)訓(xùn)練集做SMOTE過采樣三是預(yù)測(cè)時(shí)把閾值從0.5下調(diào)到0.3或0.2按業(yè)務(wù)需求在召回率與精確率之間找平衡。評(píng)估指標(biāo)不要只看準(zhǔn)確率風(fēng)控場(chǎng)景看AUC、KS、混淆矩陣。KS值能刻畫模型區(qū)分好壞樣本的能力大于0.3就基本可用了AUC和KS一起看比單看準(zhǔn)確率靠譜得多。額外多說一句做特征重要性分析時(shí)隨機(jī)森林能直接輸出Gini importance邏輯回歸可以用系數(shù)絕對(duì)值排序如果兩邊的top特征高度重合那說明特征工程做得很扎實(shí)。4.3 風(fēng)險(xiǎn)定價(jià)與貸款用途的關(guān)系風(fēng)險(xiǎn)定價(jià)這塊很多人不知道怎么做量化。我的處理方式是把預(yù)警概率映射為風(fēng)險(xiǎn)溢價(jià)再與利率建立線性關(guān)系。假設(shè)基準(zhǔn)資金成本是5%客戶的違約概率是p預(yù)期損失率約等于p乘以一個(gè)固定損失回收系數(shù)那么風(fēng)險(xiǎn)定價(jià)利率可以近似為base_rate 0.05 loss_given_default 0.7 pred_prob model.predict_proba(X_test)[:, 1] risk_premium pred_prob * loss_given_default loan_rate base_rate risk_premium operation_cost這里面的loss_given_default設(shè)為0.7表示一旦違約本金損失七成這個(gè)數(shù)字可以按業(yè)務(wù)場(chǎng)景調(diào)整。最終算出的利率會(huì)自然地按預(yù)警概率高低排序高風(fēng)險(xiǎn)客戶利率更高。為了可視化我們用貸款用途分組統(tǒng)計(jì)每組客戶的平均預(yù)警概率、平均利率、實(shí)際逾期率然后畫散點(diǎn)圖和柱狀圖。從業(yè)務(wù)角度看經(jīng)營周轉(zhuǎn)類客戶的金額通常較大、期限較短但利率跨度也比較大日常消費(fèi)類客戶金額小、利率相對(duì)穩(wěn)定。如果發(fā)現(xiàn)某個(gè)用途組的實(shí)際逾期率和模型預(yù)測(cè)概率差距過大就說明該組客戶的還款行為特殊需要單獨(dú)調(diào)整定價(jià)策略。這種“用途-利率-逾期率”的三角關(guān)系正好是題目副標(biāo)題要求研究的內(nèi)容。5. 可視化大屏與數(shù)據(jù)呈現(xiàn)5.1 可視化指標(biāo)框架與頁面結(jié)構(gòu)可視化部分不是隨便扔幾張統(tǒng)計(jì)圖就完事而是要有清晰的看板邏輯。我的大屏分四個(gè)核心區(qū)域頂部放整體業(yè)務(wù)概覽包括客戶總數(shù)、貸款總額、整體風(fēng)險(xiǎn)等級(jí)占比、平均利率中間區(qū)域放聚類結(jié)果散點(diǎn)圖和每個(gè)簇的用戶畫像指標(biāo)右側(cè)放風(fēng)險(xiǎn)預(yù)警概覽包括高風(fēng)險(xiǎn)客戶占比、風(fēng)險(xiǎn)等級(jí)漏斗圖、逾期率走勢(shì)底部區(qū)域放貸款用途與利率、逾期率的關(guān)系圖。頁面結(jié)構(gòu)上我參考了現(xiàn)在的企業(yè)級(jí)數(shù)據(jù)可視化大屏風(fēng)格以深色科技風(fēng)為主用ECharts自帶的深色主題配合紅黃綠三色做風(fēng)險(xiǎn)等級(jí)提示。背景用深藍(lán)灰色卡片標(biāo)題統(tǒng)一左上角基礎(chǔ)單位統(tǒng)一顯示避免圖表數(shù)據(jù)量綱不同導(dǎo)致誤讀。也可以用現(xiàn)有的大屏框架類項(xiàng)目作為模板但自己寫HTML布局其實(shí)不復(fù)雜四張卡片加四個(gè)圖表容器就夠了。一屏放不下所有內(nèi)容就采用“總覽篩選同頁切換”的方式。頂部放一個(gè)貸款用途的下拉篩選器選擇不同用途時(shí)下面的聚類散點(diǎn)圖、風(fēng)險(xiǎn)漏斗、利率分布全部聯(lián)動(dòng)刷新。交互式分析能體現(xiàn)你做了前端聯(lián)動(dòng)方案在評(píng)審時(shí)也是加分項(xiàng)。5.2 用ECharts實(shí)現(xiàn)核心圖表ECharts的圖形渲染質(zhì)量高社區(qū)資料多出圖效果非常適合畢設(shè)。我在項(xiàng)目里用了三種核心圖PCA聚類散點(diǎn)圖、風(fēng)險(xiǎn)等級(jí)漏斗圖、用途-利率-逾期率散點(diǎn)圖。聚類散點(diǎn)圖的實(shí)現(xiàn)邏輯是把后端返回的每個(gè)樣本的x、y、cluster三個(gè)字段拿出來遍歷成ECharts的scatter數(shù)據(jù)。每個(gè)簇單獨(dú)一個(gè)series顏色用調(diào)好的色板區(qū)分symbolSize按樣本量做縮放避免太多點(diǎn)重疊成一團(tuán)糊。這樣的圖放在大屏中間一眼就能看出人群分裂的邊界。用途-利率-逾期率散點(diǎn)圖更講究一點(diǎn)橫軸是平均利率縱軸是實(shí)際逾期率點(diǎn)的大小代表貸款金額顏色代表用途類型。這張圖最直觀地回應(yīng)了“風(fēng)險(xiǎn)定價(jià)可視化研究”這個(gè)題目當(dāng)看到某一個(gè)用途的點(diǎn)在右上方說明利率高、逾期率也高定價(jià)是合理的如果某個(gè)用途的點(diǎn)在左上方說明利率不高但逾期率不低就存在定價(jià)偏低的嫌疑。前端調(diào)用后端接口時(shí)我的Flask路由統(tǒng)一返回jsonify({status: 200, data: list_dict})前端用fetch拉數(shù)據(jù)后直接setOption。需要注意ECharts實(shí)例要在數(shù)據(jù)返回后再初始化否則容器寬度還沒穩(wěn)定很容易出現(xiàn)圖表發(fā)虛的毛病。5.3 大屏的交互與部署注意交互設(shè)計(jì)方面我會(huì)給每個(gè)圖表加上tooltip提示框、legend圖例、dataZoom縮放條。尤其聚類散點(diǎn)圖樣本量大不帶縮放條的話局部細(xì)節(jié)完全看不清楚。篩選器不只是裝飾要真的綁定到后端的查詢參數(shù)上比如選擇“經(jīng)營周轉(zhuǎn)”后接口返回的數(shù)據(jù)全部按該用途過濾前端圖表刷新。部署時(shí)我把Flask服務(wù)跑在本地9100端口大屏頁面通過相對(duì)路徑訪問避免跨域問題。如果你要把項(xiàng)目打包交給老師不要給MySQL依賴最好把處理好的數(shù)據(jù)緩存在pickle或JSON文件里前端直接讀靜態(tài)JSON。這樣免去老師配數(shù)據(jù)庫的麻煩項(xiàng)目打開即用。數(shù)據(jù)口徑的一致性是可視化最容易翻車的地方。很多人在后端寫統(tǒng)計(jì)SQL時(shí)只寫了客戶總數(shù)到前端圖表又是另一個(gè)總數(shù)兩張圖對(duì)不上答辯時(shí)會(huì)被一眼看穿。我的經(jīng)驗(yàn)是全局只保留一份匯總好的JSON數(shù)據(jù)所有圖表都從這份數(shù)據(jù)里取值不再各自計(jì)算。6. 實(shí)操過程遇到的高頻坑6.1 標(biāo)簽泄漏預(yù)警模型看起來效果爆表的原因我一開始直接把“當(dāng)前逾期天數(shù)”當(dāng)作特征保留了結(jié)果邏輯回歸AUC直接沖到0.97心里還挺高興。后來用特征重要性一看排名第一的特征就是當(dāng)前逾期天數(shù)這明顯不對(duì)。因?yàn)椤爱?dāng)前逾期天數(shù)”和標(biāo)簽的定義本就是一回事模型根本不需要學(xué)習(xí)直接記住這個(gè)字段就能預(yù)測(cè)。解決辦法是把標(biāo)簽相關(guān)的字段從特征里全部剔除包括當(dāng)前逾期天數(shù)、是否逾期這些直接變量。保留的只能是與歷史行為有關(guān)的時(shí)間滯后特征比如過去6個(gè)月內(nèi)的逾期次數(shù)、過去12個(gè)月的最高逾期天數(shù)。我反復(fù)提醒自己凡是“到了今天才能知道”的信息都不能用來預(yù)測(cè)“今天是否會(huì)發(fā)生風(fēng)險(xiǎn)”。6.2 K-Means結(jié)果不穩(wěn)定換了幾次數(shù)據(jù)都不一樣K-Means對(duì)初始中心敏感換一套數(shù)據(jù)或者換一個(gè)隨機(jī)種子聚類結(jié)果可能面目全非。哪怕邏輯上沒有錯(cuò)答辯時(shí)老師讓你復(fù)現(xiàn)一遍結(jié)果對(duì)不上就很尷尬。我做了兩件事第一固定所有隨機(jī)種子包括train_test_split、KMeans、模型初始化全部傳random_state42第二增加n_init參數(shù)讓KMeans跑十次取最優(yōu)結(jié)果。再加上前面說的異常值截?cái)嗪蜆?biāo)準(zhǔn)化聚類結(jié)果基本穩(wěn)定。如果樣本量大還可以對(duì)數(shù)據(jù)做mini-batch K-Means但畢設(shè)數(shù)據(jù)量一般不大直接跑標(biāo)準(zhǔn)版就行層次聚類驗(yàn)證也夠用了。6.3 類別不平衡讓預(yù)警模型變成“全好客戶分類器”這個(gè)問題在訓(xùn)練初期折磨了我很久。當(dāng)時(shí)模型預(yù)測(cè)的結(jié)果幾乎全是“好客戶”因?yàn)楹每蛻粽剂?2%哪怕全部預(yù)測(cè)為好準(zhǔn)確率也有92%。但風(fēng)險(xiǎn)預(yù)警完全失效。后面我改用class_weightbalanced并把決策閾值下調(diào)才讓壞客戶召回率從不到10%升到65%左右。閾值調(diào)節(jié)時(shí)需要同時(shí)看混淆矩陣不能只看AUC。AUC只反映排序能力閾值決定實(shí)際判斷結(jié)果這兩個(gè)不是一回事。我還試過用SMOTE過采樣效果也不錯(cuò)但對(duì)高維稀疏數(shù)據(jù)容易生成一些離群樣本。偶爾遇到數(shù)據(jù)和模型沒問題的場(chǎng)景加上SMOTE反而不如調(diào)閾值穩(wěn)。所以我現(xiàn)在默認(rèn)先用class_weight再調(diào)閾值過采樣只是備選方案。6.4 可視化大屏圖表錯(cuò)位和數(shù)據(jù)對(duì)不上圖表容器在小屏端容易擠壓變形我是在setOption之前等容器完成布局并且在初始化時(shí)給每個(gè)圖表設(shè)置固定寬高百分比不寫死像素。數(shù)據(jù)對(duì)不上的問題核心是統(tǒng)一數(shù)據(jù)源。我的方案是后端只生成一份dashboard_data.json前端四個(gè)圖表引用同一個(gè)對(duì)象個(gè)別圖表需要聚合數(shù)據(jù)就在前端臨時(shí)計(jì)算不做兩次后端查詢。還有一個(gè)低級(jí)的坑ECharts的formatter里拼接變量時(shí)如果數(shù)值是None或者NaN整個(gè)tooltip會(huì)顯示undefined。我一度以為自己數(shù)據(jù)有問題排查半天才發(fā)現(xiàn)是字符串模板里沒做類型轉(zhuǎn)換。所有輸出數(shù)據(jù)在返給前端前我都強(qiáng)制round(..., 2)或str()避免這類玄學(xué)報(bào)錯(cuò)。7. 寫在最后的一點(diǎn)建議這套源碼做下來我最大的體會(huì)是數(shù)據(jù)分析類的畢設(shè)重點(diǎn)不全在模型調(diào)參而在于能不能把每一步?jīng)Q策背后的業(yè)務(wù)邏輯說通。為什么選K-Means而不是DBSCAN為什么把貸款用途放進(jìn)聚類特征為什么風(fēng)險(xiǎn)定價(jià)要由預(yù)警概率驅(qū)動(dòng)這些問題比AUC多0.03更能體現(xiàn)你的工作量和理解深度。源碼交付時(shí)我習(xí)慣把環(huán)境依賴寫在一個(gè)requirements.txt里附上一份“快速運(yùn)行說明”從數(shù)據(jù)生成到啟動(dòng)Flask服務(wù)三步跑通。任何工具鏈都經(jīng)不起折騰能一鍵演示的項(xiàng)目在評(píng)審時(shí)天然占優(yōu)勢(shì)。最后再分享一個(gè)小技巧如果你的時(shí)間倉促聚類部分只保留K-Means輪廓系數(shù)預(yù)警部分只保留邏輯回歸閾值調(diào)節(jié)可視化只保留聚類散點(diǎn)圖和風(fēng)險(xiǎn)漏斗圖也能形成一個(gè)完整閉環(huán)。演示時(shí)按“數(shù)據(jù)預(yù)處理 - 分群 - 預(yù)警 - 定價(jià) - 可視化”的順序講既有邏輯又有視覺沖擊比盲目堆模型靠譜得多。