器學(xué)習(xí)的航班登機(jī)口分配:特征工程與LightGBM實(shí)踐)
簡(jiǎn)介基于機(jī)器學(xué)習(xí)的航班登機(jī)口分配完整項(xiàng)目面向航空運(yùn)營(yíng)管理、數(shù)據(jù)建模與運(yùn)籌優(yōu)化學(xué)習(xí)者聚焦登機(jī)口資源調(diào)度這一機(jī)場(chǎng)核心問(wèn)題。資源包共20個(gè)文件以電子表格、Python腳本和可視化圖表為主體壓縮后僅1.6MB其中7份數(shù)據(jù)表涵蓋航班、旅客、轉(zhuǎn)機(jī)、登機(jī)口資源及關(guān)聯(lián)矩陣3個(gè)py腳本分別對(duì)應(yīng)主程序、遺傳算法參數(shù)配置和數(shù)據(jù)合并6張png圖表直觀(guān)呈現(xiàn)旅客換乘時(shí)間分布、登機(jī)口使用率以及寬窄體機(jī)分配數(shù)量等結(jié)果。項(xiàng)目從數(shù)據(jù)預(yù)處理、特征工程到模型訓(xùn)練與遺傳算法尋優(yōu)形成可復(fù)現(xiàn)的優(yōu)化閉環(huán)配套說(shuō)明文檔交代背景、數(shù)據(jù)來(lái)源與執(zhí)行思路輸出目錄存放最終分配方案和性能指標(biāo)讀者可調(diào)整遺傳算法的參數(shù)腳本對(duì)比不同調(diào)度策略下的使用均衡度與旅客體驗(yàn)。目前已有124人學(xué)習(xí)既適合復(fù)現(xiàn)競(jìng)賽級(jí)求解方案也可作為航空調(diào)度課題、畢業(yè)設(shè)計(jì)或機(jī)器學(xué)習(xí)項(xiàng)目實(shí)踐的參考。1. 從一張航顯屏說(shuō)起為什么登機(jī)口分配值得做機(jī)器學(xué)習(xí)航班登機(jī)口分配是每個(gè)樞紐機(jī)場(chǎng)每天都要面對(duì)的高頻決策。幾百架次航班落在幾十個(gè)登機(jī)口上遠(yuǎn)機(jī)位擺渡車(chē)、近機(jī)位廊橋、中轉(zhuǎn)旅客的步行距離、停機(jī)坪的機(jī)位沖突全部壓在一張動(dòng)態(tài)更新的排班表里。調(diào)度員憑經(jīng)驗(yàn)排兩個(gè)小時(shí)好不容易排完一個(gè)航班延誤就能讓整張表連鎖崩盤(pán)。這份標(biāo)題里的“基于機(jī)器學(xué)習(xí)的航班登機(jī)口分配”方案就是把“人工經(jīng)驗(yàn)”變成“可復(fù)用模型”的完整交付物——壓縮包里既有數(shù)據(jù)集也有方案報(bào)告意味著它不是一篇停留在設(shè)想層面的論文而是一份拿來(lái)就能跑、跑完能對(duì)照檢查的實(shí)踐資料。對(duì)運(yùn)控值班、數(shù)據(jù)算法崗、以及做運(yùn)籌優(yōu)化落地的工程師來(lái)說(shuō)這個(gè)方向解決的不是“排得對(duì)不對(duì)”的學(xué)術(shù)問(wèn)題而是“航顯屏上有沒(méi)有航班被分到遠(yuǎn)機(jī)位、廊橋資源是否被白白空置”的業(yè)務(wù)問(wèn)題。它適合兩類(lèi)人一類(lèi)是想把規(guī)則引擎升級(jí)成預(yù)測(cè)模型的機(jī)場(chǎng)運(yùn)控團(tuán)隊(duì)另一類(lèi)是剛接觸資源調(diào)度類(lèi)機(jī)器學(xué)習(xí)項(xiàng)目、需要一個(gè)完整數(shù)據(jù)集練手的數(shù)據(jù)從業(yè)者。讀完這份方案你至少能回答三個(gè)問(wèn)題登機(jī)口分配為什么能做成機(jī)器學(xué)習(xí)問(wèn)題、訓(xùn)練數(shù)據(jù)從哪里來(lái)、模型輸出之后怎么落地成一張不沖突的排班表。2. 把登機(jī)口分配定義成機(jī)器學(xué)習(xí)問(wèn)題特征、標(biāo)簽與方案選型在動(dòng)手寫(xiě)代碼之前先把問(wèn)題本身掰開(kāi)揉碎。登機(jī)口分配本質(zhì)上是給每一個(gè)航班選一個(gè)停機(jī)位這個(gè)選擇受航班時(shí)刻、飛機(jī)機(jī)型、廊橋適配性、中轉(zhuǎn)旅客數(shù)量、相鄰航班沖突等多重因素約束。傳統(tǒng)做法是把約束寫(xiě)進(jìn)整數(shù)規(guī)劃模型讓求解器去算最優(yōu)解。但實(shí)際運(yùn)行中目標(biāo)函數(shù)很難定義——是優(yōu)先減少遠(yuǎn)機(jī)位還是優(yōu)先減少中轉(zhuǎn)步行距離是優(yōu)先保證準(zhǔn)點(diǎn)還是優(yōu)先減少拖車(chē)調(diào)度不同機(jī)場(chǎng)的回答完全不同。機(jī)器學(xué)習(xí)方案的優(yōu)勢(shì)在于不再顯式定義優(yōu)先級(jí)而是從歷史分配記錄里把調(diào)度員的“決策習(xí)慣”學(xué)出來(lái)用概率來(lái)替代規(guī)則優(yōu)先級(jí)。2.1 特征體系怎么搭航班動(dòng)態(tài)、旅客中轉(zhuǎn)與停機(jī)位屬性特征決定了模型的上限這個(gè)在登機(jī)口分配項(xiàng)目里表現(xiàn)得尤其明顯。我一般把特征拆成三組。第一組是航班自身屬性機(jī)型編碼、計(jì)劃/預(yù)計(jì)進(jìn)出港時(shí)間、航班號(hào)前綴判斷是干線(xiàn)還是支線(xiàn)、出發(fā)/到達(dá)標(biāo)識(shí)、是否國(guó)際航班。第二組是停機(jī)位屬性廊橋還是遠(yuǎn)機(jī)位、機(jī)位類(lèi)型是否匹配機(jī)型、步行到行李轉(zhuǎn)盤(pán)的距離、是否靠近國(guó)際到達(dá)區(qū)。第三組是組合特征也是最有區(qū)分度的部分——某個(gè)航班落地前后半小時(shí)內(nèi)同一停機(jī)位上的前序航班是否已經(jīng)清艙離港、相鄰?fù)C(jī)位是否被占用。組合特征的重要性在于它能直接捕捉“沖突”這個(gè)概念。舉個(gè)例子兩個(gè)寬體機(jī)間隔只有四十分鐘分到同一個(gè)廊橋位必然造成前一班推出晚點(diǎn)但如果兩個(gè)窄體機(jī)間隔四十分鐘調(diào)度員可能覺(jué)得問(wèn)題不大。這種“容量”的判斷單純給模型喂原始字段是學(xué)不出來(lái)的需要顯式構(gòu)造。特征工程階段可以關(guān)注運(yùn)行事件的時(shí)間差、機(jī)型對(duì)機(jī)位的匹配矩陣、航班密度統(tǒng)計(jì)量。做推薦也好做排序也罷特征匱乏時(shí)再怎么調(diào)參也是白費(fèi)工夫。2.2 三類(lèi)建模思路對(duì)比分類(lèi)、排序與強(qiáng)化學(xué)習(xí)怎么選將登機(jī)口分配歸為機(jī)器學(xué)習(xí)問(wèn)題后常見(jiàn)有三種建模路線(xiàn)。第一種是“分桶分類(lèi)”把每一個(gè)候選停機(jī)位看成類(lèi)別通過(guò)多分類(lèi)模型輸出機(jī)位概率。這個(gè)方法的問(wèn)題在于類(lèi)別數(shù)太多——樞紐機(jī)場(chǎng)光近機(jī)位就有幾十個(gè)多分類(lèi)的類(lèi)別不平衡會(huì)非常嚴(yán)重。第二種是“成對(duì)排序”把航班?停機(jī)位構(gòu)造成樣本對(duì)模型學(xué)習(xí)“這個(gè)機(jī)位比那個(gè)機(jī)位更合適”的偏好最后用 ListNet 或 lambdarank 思路做排序。這是我在類(lèi)似項(xiàng)目中比較常用的一種方式能兼容冷啟動(dòng)機(jī)位。第三種是用強(qiáng)化學(xué)習(xí)建模序列決策把每個(gè)航班到達(dá)看成一步智能體按順序給航班分配機(jī)位環(huán)境反饋沖突和資源利用率作為獎(jiǎng)勵(lì)信號(hào)。強(qiáng)化學(xué)習(xí)適合動(dòng)態(tài)調(diào)度但訓(xùn)練不穩(wěn)定、落地周期長(zhǎng)沒(méi)有充足的數(shù)據(jù)積累不建議一上來(lái)就上。方案報(bào)告里的核心結(jié)論大概率也是這個(gè)傾向——先做排序模型留好特征接口等樣本量足夠再升級(jí) RL。如果你的目標(biāo)是在短時(shí)間內(nèi)拿到一份可解釋的分配結(jié)果排序模型是最穩(wěn)妥的起點(diǎn)。2.3 方案報(bào)告里最先要寫(xiě)清的三件事這份 zip 里的方案報(bào)告是給誰(shuí)看的直接決定了它的寫(xiě)法。如果給運(yùn)控部門(mén)看最先要寫(xiě)清楚的不是模型結(jié)構(gòu)而是三個(gè)業(yè)務(wù)口徑。第一標(biāo)簽是怎么定義的——?dú)v史數(shù)據(jù)里調(diào)度員最終實(shí)際分配的機(jī)位就是金標(biāo)準(zhǔn)嗎不見(jiàn)得因?yàn)橛械姆峙涫桥R時(shí)應(yīng)急下的產(chǎn)物可能在最優(yōu)解和沖突解之間搖擺標(biāo)簽需要清洗。第二評(píng)估指標(biāo)與業(yè)務(wù)成本掛鉤——模型面試用 AUC落地要看遠(yuǎn)機(jī)位占比和旅客步行距離報(bào)告里要把這兩個(gè)指標(biāo)的前后變化列出來(lái)。第三模型輸出的是概率還是方案——如果只是給每個(gè)機(jī)位打分還需要人工做最后一層確認(rèn)報(bào)告應(yīng)當(dāng)明確這個(gè)邊界否則驗(yàn)收方會(huì)誤以為模型直接生成最終排班表。寫(xiě)清楚這三件事比堆十頁(yè)算法推導(dǎo)都管用。方案報(bào)告是項(xiàng)目交付的門(mén)面也是你后續(xù)跟業(yè)務(wù)方對(duì)齊預(yù)期的主要依據(jù)能早寫(xiě)就早寫(xiě)不要等項(xiàng)目做完再來(lái)補(bǔ)。3. 構(gòu)造登機(jī)口分配數(shù)據(jù)集從航班日志到可訓(xùn)練樣本鏈路開(kāi)始之前先明確一個(gè)問(wèn)題公開(kāi)可用的登機(jī)口分配數(shù)據(jù)很少因?yàn)楹桨嘤?jì)劃和機(jī)位使用屬于機(jī)場(chǎng)運(yùn)行核心數(shù)據(jù)大部分不會(huì)公開(kāi)。但作為案例我們可以在自己的數(shù)據(jù)環(huán)境中模擬出足夠的訓(xùn)練樣本——只要保留航班計(jì)劃、機(jī)位占用時(shí)間片這兩類(lèi)核心信息就能把特征工程跑通。真實(shí)項(xiàng)目里數(shù)據(jù)源的接入周期通常是兩個(gè)月起步先把樣例數(shù)據(jù)和 schema 定義好再談?dòng)?xùn)練才能落地。3.1 原始數(shù)據(jù)長(zhǎng)什么樣航段表、停機(jī)位表與旅客中轉(zhuǎn)表原始數(shù)據(jù)一般至少包含三張表。航段表是最基礎(chǔ)的一張記錄每個(gè)航班的唯一標(biāo)識(shí)、起降城市、計(jì)劃起飛/到達(dá)時(shí)間、實(shí)際起飛/到達(dá)時(shí)間、機(jī)型、航班狀態(tài)停機(jī)位表記錄每個(gè)機(jī)位的編號(hào)、是否廊橋、可承載的最大機(jī)型級(jí)別、所屬區(qū)域有些機(jī)場(chǎng)還會(huì)額外記錄該機(jī)位離行李轉(zhuǎn)盤(pán)的距離如果要考慮中轉(zhuǎn)效率還需要旅客中轉(zhuǎn)表含每個(gè)旅客在兩段航班之間的銜接時(shí)間。這三張表通過(guò)航班號(hào)和時(shí)間戳關(guān)聯(lián)就能覆蓋絕大多數(shù)特征。建表時(shí)我會(huì)先把時(shí)間字段標(biāo)準(zhǔn)化為統(tǒng)一的時(shí)區(qū)把機(jī)型字段映射為等級(jí)編碼把航班狀態(tài)轉(zhuǎn)成枚舉值。這一步看起來(lái)枯燥但撿漏的價(jià)值很大——比如同一個(gè)機(jī)場(chǎng)既有“計(jì)劃到達(dá)時(shí)間”又有“預(yù)計(jì)到達(dá)時(shí)間”很多新手只取其一等模型上線(xiàn)才發(fā)現(xiàn)兩者差距能到 40 分鐘直接讓訓(xùn)練集和推理集的分布不一致。標(biāo)準(zhǔn)化的同時(shí)把原始日志的 zip 備份留存后續(xù)要查特征計(jì)算口徑時(shí)能倒回去對(duì)照。3.2 特征工程代碼示例把航段原始字段變成模型輸入下面這段代碼完成從航段原始記錄到特征向量的轉(zhuǎn)換是我在類(lèi)似項(xiàng)目里的常見(jiàn)起步寫(xiě)法。假設(shè) feed 是航班記錄 DataFramegate_info 是機(jī)位表output 是按航班和機(jī)位展開(kāi)的樣本集。import pandas as pd import numpy as np def build_flight_gate_features(flights, gates): flights: 包含航班號(hào)、起降時(shí)間、機(jī)型、狀態(tài) gates: 包含機(jī)位編號(hào)、是否廊橋、最大機(jī)型等級(jí) # 標(biāo)準(zhǔn)化時(shí)間字段 for col in [sched_arr, est_arr, sched_dep, est_dep]: flights[col] pd.to_datetime(flights[col]) # 機(jī)位-航班匹配合法性過(guò)濾機(jī)型等級(jí)不能超過(guò)機(jī)位等級(jí) df flights.merge(gates, howcross) df df[df[flight_level] df[gate_level]] # 組合特征前序航班離港時(shí)間差 # 對(duì)每個(gè)機(jī)位按預(yù)計(jì)到達(dá)時(shí)間排序計(jì)算與上一航班的間隔 df[time_gap_prev] ( df.groupby(gate_id)[est_arr].diff().dt.total_seconds() / 60 ) # 組合特征同一機(jī)位前一航班是否延誤 # 如果前序起飛晚點(diǎn)超過(guò) 30 分鐘該機(jī)位更可能處于占用狀態(tài) df[prev_dep_delay] df.groupby(gate_id)[dep_delay].shift(1) # 稀疏類(lèi)目編碼航班前綴干線(xiàn)/支線(xiàn)/國(guó)際保留高基數(shù)的航班號(hào)前綴 df[flight_prefix] df[flight_no].str[:2] df pd.get_dummies(df, columns[flight_prefix]) return df這段代碼的第一個(gè)關(guān)鍵參數(shù)是howcross它生成每一個(gè)航班與所有合法機(jī)位的笛卡爾積這也是構(gòu)造排序樣本的基礎(chǔ)——一條樣本代表“這個(gè)航班停這個(gè)機(jī)位”是否合理。time_gap_prev和prev_dep_delay兩個(gè)組合特征是最容易出效果的兩列前者刻畫(huà)機(jī)位周轉(zhuǎn)壓力后者把“前序延誤導(dǎo)致這個(gè)機(jī)位不可用”變成了模型可感知的信號(hào)。flight_prefix的 one?hot 不是必須的如果后續(xù)用樹(shù)模型保留原始字符串作為類(lèi)別特征效果更好這里只是演示一種通用做法。3.3 用滑動(dòng)時(shí)間窗切出訓(xùn)練樣本一份直接能跑的劃分腳本訓(xùn)練樣本的切法決定了模型會(huì)不會(huì)“看到未來(lái)”。登機(jī)口分配天然是時(shí)間序列數(shù)據(jù)按天隨機(jī) shuffle 會(huì)引入數(shù)據(jù)泄漏——昨天的樣本和目標(biāo)之間存在極強(qiáng)的相同時(shí)段相關(guān)性。我常用的做法是分段留出法把數(shù)據(jù)按時(shí)間先后排序前 70% 做訓(xùn)練后 30% 做驗(yàn)證并在驗(yàn)證集里特意選連續(xù)的幾天模擬真實(shí)上線(xiàn)后的“未知未來(lái)”。def temporal_split(df, date_col, train_ratio0.7): 按時(shí)間順序切分防止同一航班在訓(xùn)練與驗(yàn)證中重復(fù)出現(xiàn) df df.sort_values(date_col).reset_index(dropTrue) split_idx int(len(df) * train_ratio) train df.iloc[:split_idx].copy() valid df.iloc[split_idx:].copy() # 移除與訓(xùn)練集時(shí)間窗口重疊的樣本防止前序特征跨切分邊界 valid valid[valid[date_col] train[date_col].max() pd.Timedelta(minutes30)] return train, valid切分之后還要做一步“防串?dāng)_”過(guò)濾。因?yàn)閠ime_gap_prev這類(lèi)特征取的是前序航班信息如果驗(yàn)證集第一天的最早航班引用了訓(xùn)練集最后一天的航班數(shù)據(jù)會(huì)人為抬升驗(yàn)證集指標(biāo)。加一個(gè) 30 分鐘的空窗期是成本最低的規(guī)避方式。后面模型評(píng)估如果發(fā)現(xiàn)驗(yàn)證集分?jǐn)?shù)明顯好于訓(xùn)練集先回來(lái)查切分邊界而不是急著加正則化。4. 訓(xùn)練與評(píng)估用 LightGBM 解決小樣本分配登機(jī)口分配的數(shù)據(jù)量通常是十萬(wàn)級(jí)到百萬(wàn)級(jí)的樣本量等航班數(shù)乘機(jī)位數(shù)這個(gè)量級(jí)下深度學(xué)習(xí)不是首選。LightGBM 能處理類(lèi)別特征、對(duì)缺失值不敏感、訓(xùn)練開(kāi)銷(xiāo)小而且特征重要性天然可解釋方便回頭給業(yè)務(wù)方講“模型到底看了什么”。方案報(bào)告里的模型部分如果用的是梯度提升樹(shù)那么在業(yè)務(wù)上完全說(shuō)得通。4.1 模型比較為什么先上 LightGBM 而不是神經(jīng)網(wǎng)絡(luò)很多剛接觸這個(gè)方向的同行會(huì)問(wèn)機(jī)器學(xué)習(xí)都這么成熟了為什么不用深度神經(jīng)網(wǎng)絡(luò)原因在于樣本量。一個(gè)樞紐機(jī)場(chǎng)一天的航班量約 800~1200 班就算每個(gè)航班對(duì)比 30 個(gè)候選機(jī)位一天也只有兩三萬(wàn)條樣本去掉節(jié)假日波動(dòng)一個(gè)月的有效數(shù)據(jù)不到百萬(wàn)。DNN 在這個(gè)量級(jí)容易過(guò)擬合而且特征中的時(shí)間差、機(jī)位間距是用連續(xù)值刻畫(huà)的沒(méi)有好的 embedding 設(shè)計(jì)很難學(xué)出“周轉(zhuǎn)緊張”這類(lèi)高階模式。梯度提升樹(shù)的最大優(yōu)勢(shì)是對(duì)特征尺度不敏感能直接吸收數(shù)值型和類(lèi)別型混合的特征配合早停和弱正則在千級(jí)到十萬(wàn)級(jí)樣本上都能給出穩(wěn)健的 baseline。如果后續(xù)想提高上限可以在樹(shù)模型基礎(chǔ)上疊加一層冷啟動(dòng)規(guī)則——比如夜間到港的國(guó)際航班永遠(yuǎn)只分給固定幾個(gè)機(jī)位這類(lèi)規(guī)則不進(jìn)模型而是作為后處理過(guò)濾。深度學(xué)習(xí)留到樣本量穩(wěn)定突破千萬(wàn)、且你積累了足夠的序列特征之后再說(shuō)。4.2 訓(xùn)練腳本與參數(shù)說(shuō)明早停、類(lèi)別特征與目標(biāo)函數(shù)這里給出一個(gè) LightGBM 的訓(xùn)練骨架目標(biāo)是判斷“該機(jī)位分配給該航班的合適程度”。標(biāo)簽是 0/11 代表該航班歷史上實(shí)際使用該機(jī)位0 代表未使用。采樣時(shí)保證每個(gè)航班的正負(fù)樣本比例約為 1:5負(fù)樣本過(guò)多會(huì)造成模型只學(xué)會(huì)輸出低概率。import lightgbm as lgb from sklearn.model_selection import train_test_split # 假設(shè) features 是特征列名列表 feature_cols [ time_gap_prev, prev_dep_delay, gate_is_bridge, flight_level, arr_hour, dep_delay, is_international ] categorical_cols [flight_level, is_international] # 構(gòu)造 lgb Dataset直接聲明類(lèi)別特征 train_data lgb.Dataset( train[feature_cols], labeltrain[label], categorical_featurecategorical_cols ) valid_data lgb.Dataset( valid[feature_cols], labelvalid[label], referencetrain_data ) params { objective: binary, metric: auc, learning_rate: 0.05, num_leaves: 31, max_depth: 6, min_data_in_leaf: 50, feature_fraction: 0.8, bagging_fraction: 0.8, bagging_freq: 1, verbose: -1, } model lgb.train( params, train_data, num_boost_round500, valid_sets[valid_data], callbacks[ lgb.early_stopping(stopping_rounds50), lgb.log_evaluation(period50) ] )learning_rate0.05配num_leaves31是通用起步參數(shù)登機(jī)口分配這類(lèi)任務(wù)特征維度不高不需要特別深的樹(shù)。min_data_in_leaf50是防過(guò)擬合的關(guān)鍵閥門(mén)——機(jī)位樣本很不平衡如果葉子節(jié)點(diǎn)里樣本太少模型容易記住個(gè)別航班的“偶然分配”而不是學(xué)到普遍規(guī)律。feature_fraction0.8增加特征層面的隨機(jī)性對(duì)樹(shù)模型穩(wěn)定性的提升立竿見(jiàn)影。類(lèi)別特征不要自己 one?hot直接通過(guò)categorical_feature聲明LGB 內(nèi)部會(huì)用類(lèi)別直方圖的方式處理既省內(nèi)存又避免稀疏維度。4.3 評(píng)估與模擬回測(cè)用 AUC 和分配沖突率兩個(gè)指標(biāo)把關(guān)訓(xùn)練階段用 AUC 選模型但交付階段只看 AUC 是不夠的。AUC 衡量的是排序質(zhì)量也就是“正樣本是否排在負(fù)樣本前面”可業(yè)務(wù)方想知道的是“按這個(gè)概率分配實(shí)際會(huì)發(fā)生幾次機(jī)位沖突”。我在項(xiàng)目里會(huì)額外寫(xiě)一個(gè)回測(cè)腳本取驗(yàn)證集的每個(gè)航班把模型輸出的概率按機(jī)位降序排列逐個(gè)嘗試分配同時(shí)檢查該機(jī)位時(shí)間片是否已被占用若沖突則順延到下一個(gè)候選機(jī)位最后統(tǒng)計(jì)沖突率和遠(yuǎn)機(jī)位占比。這個(gè)腳本的價(jià)值在于驗(yàn)證模型排序與硬約束之間的匹配度是模型能否真正交到運(yùn)控手里的試金石。def simulate_assignment(df_scores, gates): df_scores: 每個(gè)航班在每個(gè)機(jī)位上的預(yù)測(cè)概率 返回每天的沖突率與遠(yuǎn)機(jī)位占比 assigned {} conflicts 0 far_gates 0 total 0 for flight_id, group in df_scores.groupby(flight_id): total 1 # 按概率降序依次嘗試分配 sorted_cands group.sort_values(score, ascendingFalse) chosen None for _, row in sorted_cands.iterrows(): gate row[gate_id] if gate not in assigned or assigned[gate] row[est_arr]: chosen gate assigned[gate] row[est_dep] break if chosen is None: conflicts 1 elif not gates.loc[chosen, is_bridge]: far_gates 1 return { conflict_rate: conflicts / total, far_gate_ratio: far_gates / total }回測(cè)邏輯里有一個(gè)隱性假設(shè)——assigned[gate] row[est_arr]判斷的是機(jī)位釋放時(shí)間是否早于新航班到達(dá)時(shí)間。真實(shí)運(yùn)行中還要考慮前序航班清艙和旅客下機(jī)的時(shí)間緩沖這個(gè)緩沖走廊應(yīng)該在字段est_dep構(gòu)造時(shí)就提前預(yù)留。如果不預(yù)留回測(cè)出來(lái)的沖突率會(huì)比真實(shí)值低很多現(xiàn)場(chǎng)一跑就露餡。一般在特征工程階段我會(huì)把est_dep加上 20 分鐘的緩沖時(shí)間再寫(xiě)進(jìn)時(shí)間片表。5. 登機(jī)口分配項(xiàng)目的避坑清單五個(gè)讓模型翻車(chē)的真實(shí)原因做了幾個(gè)資源調(diào)度類(lèi)項(xiàng)目之后我發(fā)現(xiàn)最容易拖垮進(jìn)度的不是模型調(diào)參而是數(shù)據(jù)和工程上的隱性坑。下面按踩坑頻率從高到低列五條每條都按現(xiàn)象到原因再到解決方案的順序?qū)?。坑一特征里混入未?lái)信息模型指標(biāo)虛高現(xiàn)象驗(yàn)證 AUC 高達(dá) 0.98但實(shí)際試運(yùn)行表現(xiàn)遠(yuǎn)不如預(yù)期。原因特征構(gòu)造時(shí)把“最終實(shí)際到達(dá)時(shí)間”當(dāng)成輸入而推理階段只有“預(yù)計(jì)到達(dá)時(shí)間”兩者之差直接抬高了排序效果。解決把數(shù)據(jù)表拆成“計(jì)劃快照”和“實(shí)際運(yùn)行”兩套制定嚴(yán)格的字段白名單凡是推理時(shí)點(diǎn)拿不到的字段一律不放進(jìn)特征列表。這條坑的隱蔽性在于它不是報(bào)錯(cuò)而是悄悄吃掉你的可信度??佣桨嗯咳∠麑?dǎo)致訓(xùn)練集和推理集分布不一致現(xiàn)象模型上線(xiàn)第一周遇到雷雨天氣大面積延誤模型輸出的機(jī)位分配連續(xù)三天返工。原因訓(xùn)練集里正常天氣樣本占絕對(duì)主導(dǎo)模型沒(méi)見(jiàn)過(guò)“大量航班延誤導(dǎo)致機(jī)位周轉(zhuǎn)時(shí)間整體拉長(zhǎng)”的情況。解決在特征中加入“航班密度”“當(dāng)前機(jī)位占用率”這類(lèi)時(shí)間窗口統(tǒng)計(jì)量并在訓(xùn)練集中保留一定比例的高延誤日數(shù)據(jù)。如果歷史數(shù)據(jù)里沒(méi)有這類(lèi)天就做基于規(guī)則的模擬樣本擴(kuò)充??尤齴ip 壓縮包里的數(shù)據(jù)版本與方案報(bào)告對(duì)不上現(xiàn)象打開(kāi)壓縮包后按報(bào)告中的字段名跑特征工程提示KeyError。原因方案報(bào)告基于某一次清洗后的數(shù)據(jù)撰寫(xiě)但壓縮包里的數(shù)據(jù)集版本更老字段名尚未統(tǒng)一。解決拿到數(shù)據(jù)后先做字段清單核對(duì)把所有 schema 差異先列出來(lái)再?zèng)Q定是更新報(bào)告還是更新數(shù)據(jù)。這也是為什么我會(huì)在項(xiàng)目交付時(shí)額外附一個(gè)字段說(shuō)明文件的原因——少一個(gè)字段對(duì)照表后續(xù)要花多倍時(shí)間猜。坑四正負(fù)樣本比例失衡模型不敢預(yù)測(cè)“遠(yuǎn)機(jī)位”現(xiàn)象模型輸出的機(jī)位概率普遍集中在幾個(gè)近機(jī)位遠(yuǎn)機(jī)位幾乎沒(méi)有高分。原因歷史數(shù)據(jù)中遠(yuǎn)機(jī)位使用占比大概只有 20%~30%模型學(xué)到了“輸出保守的分配”能降低損失。解決訓(xùn)練時(shí)對(duì)負(fù)樣本做下采樣把正負(fù)樣本比例控制在 1:5 以?xún)?nèi)同時(shí)評(píng)估指標(biāo)加上對(duì)遠(yuǎn)機(jī)位類(lèi)別的單獨(dú)召回。不要過(guò)度糾結(jié)于讓模型在遠(yuǎn)機(jī)位上也輸出高概率那不符合業(yè)務(wù)規(guī)律關(guān)鍵是排序靠前的候選中不要漏掉合理的遠(yuǎn)機(jī)位選項(xiàng)。坑五沒(méi)有可視化的分配結(jié)果審查工具模型效果無(wú)法驗(yàn)收現(xiàn)象模型訓(xùn)練完效果指標(biāo)都達(dá)標(biāo)但業(yè)務(wù)方堅(jiān)持不看報(bào)表只盯著航顯屏上的排班結(jié)果。原因模型輸出和人工排班表的格式完全不同缺少一個(gè)能直觀(guān)對(duì)比“模型分配”和“實(shí)際分配”的界面。解決抽出最少量的時(shí)間用streamlit寫(xiě)一個(gè)簡(jiǎn)單的對(duì)比工具左邊顯示模型結(jié)果右邊顯示實(shí)際結(jié)果一眼能看出差異航班。這一步對(duì)項(xiàng)目通過(guò)驗(yàn)收的作用甚至比調(diào)模型還大因?yàn)樾湃问强靠吹玫降臇|西建立的。6. 驗(yàn)證與進(jìn)階把概率變成一張運(yùn)控能用的排班表模型輸出的“概率”不是終點(diǎn)。常見(jiàn)做法是拿模型概率作為初排信號(hào)再疊加一層貪心修復(fù)來(lái)滿(mǎn)足硬約束。在模擬回測(cè)腳本里我們已經(jīng)實(shí)現(xiàn)了順序分配但那是驗(yàn)證用的真正交付時(shí)還要做三步第一步把模型輸出的概率列按航班分組生成 Top?3 候選機(jī)位清單第二步按清單順序嘗試分配并在嘗試時(shí)檢查機(jī)位的“釋放時(shí)間 緩沖時(shí)間”是否滿(mǎn)足本航班到達(dá)時(shí)間第三步對(duì)最終無(wú)法分配的少數(shù)航班單獨(dú)進(jìn)入人工處理通道由調(diào)度員手動(dòng)指定機(jī)位。這樣設(shè)計(jì)既不剝奪人工決策權(quán)又能把 90% 以上的常規(guī)航班自動(dòng)化掉運(yùn)控團(tuán)隊(duì)接受度最高。進(jìn)階方向上有兩個(gè)低成本高收益的做法值得試。一個(gè)是把前序航班的實(shí)際離港時(shí)間作為實(shí)時(shí)特征接入模型——訓(xùn)練時(shí)用歷史數(shù)據(jù)里的實(shí)際值推理時(shí)用當(dāng)前更新的預(yù)達(dá)時(shí)間能讓模型適應(yīng)動(dòng)態(tài)延誤場(chǎng)景。另一個(gè)是對(duì)模型結(jié)果做“隱含沖突率”的監(jiān)控——每天計(jì)算模型分配結(jié)果中被人工調(diào)整的比例連續(xù)多天超過(guò)閾值就觸發(fā)重新訓(xùn)練。前一個(gè)提升模型上限后一個(gè)守住落地底線(xiàn)。我的習(xí)慣是每次做這類(lèi)資源分配模型都會(huì)預(yù)留一個(gè)“策略開(kāi)關(guān)”先用純模型結(jié)果試探一周再逐步加入規(guī)則約束兩邊對(duì)比運(yùn)行數(shù)據(jù)之后再定正式策略——這個(gè)習(xí)慣幫我避免了好幾次因?yàn)槟P图みM(jìn)或保守導(dǎo)致的排班返工。希望這份從數(shù)據(jù)集到評(píng)估回測(cè)的完整鏈路能讓你在自己的登機(jī)口分配項(xiàng)目里少走幾步彎路。本文還有配套的精品資源點(diǎn)擊獲取