随机森林算法

什么是中转航班?

1.中转旅客:在旅行过程中,需要在某个或多个中转站点暂时停留,换乘其他交通工具的旅客。
2.中转航班:指旅客需要换乘其他航班才能到达目的地的过程。
3.中转站:指在运输过程中,用于暂时停留和换乘的站点。

a. 比如张三,假期在吉祥航空买了从北京飞往上海的票,但是发现没有直达上海的票,需要先到武汉再到上海,在票面上来看虽然本次旅程到了武汉,但是票号只会出现一次,也就是票A,对应的航段为 北京-武汉-上海。我们成为中转旅客。
b. 再比如张三,假期在买了从北京到上海的往返票,但是票号却是一个,虽然往返票的起飞日期不一样,但这次旅程仍然属于中转航程。
c. 中转的站不限制次数,可以无限制的累积比如张三的票是A-B-C-D-E等等,可以无限中转换站。

如何赋能中转?

先看一篇文章,聚焦智慧民航 | 智慧赋能中转衔接:时间短一点,速度快一点|旅客|机场|值机|航季航班计划_网易订阅 (163.com)

好了,到底和算法和这玩意啥关系?💁

简单一点,就是利用算法的分析预测来辅助决策。

痛点

  1. 目前中转旅客的等待决策较为一刀切,主要以中转旅客人数作为一个判断依据,决策维度较为单一不够全面(扩充一些纬度)
  2. 总值班人数较多,每个人都有自己的价值取向,决策的价值标准比较难以统一,没有一个相对参考

数据导入

  1. 由业务部门提供尽可能全面的决策评估维度
  2. 建立多决策维度下的决策案例库,供模型搭建
  3. 通过模型计算和分析不同的决策结果,为决策者提供出中转旅客是否等待的决策建议

决策状态

  1. 已搁置:给出决策建议但忽略延后处理
  2. 已经忽略:给出决策建议但忽略
  3. 待处理:给出决策建议但等待处理
  4. 无需处理:给出决策建议
  5. 已处理:给出决策建议已处理

决策算法

# -*- coding: utf-8 -*-  
# @Time    : 2024/5/24 3:31 下午  
# @Author  : Hoey  
import json  
import os  
import pickle  
import sys  
  
import numpy as np  
import pandas as pd  
from sklearn.ensemble import RandomForestClassifier  
from sklearn.metrics import accuracy_score  
from sklearn.model_selection import train_test_split, GridSearchCV  
from sklearn.preprocessing import StandardScaler  
from argparse import ArgumentParser  
  
  
  
def parse_arguments():  
    parser = ArgumentParser()  
    parser.add_argument('json_str', help='json字符串')  
    return parser.parse_args()  
  
  
def save_model(model_path, model):  
    with open(model_path, 'wb') as file:  
        pickle.dump(model, file)  
  
  
def get_model(model_path):  
    loaded_model = None  
    if os.path.exists(model_path):  
        with open(model_path, 'rb') as file:  
            loaded_model = pickle.load(file)  
    return loaded_model  
  
  
def read_excel_data_by_pd(file_path: str, sheet_name: str):  
    return pd.read_excel(file_path, sheet_name=sheet_name, header=0, engine='xlrd')  
  
  
def model(model_path):  
    if os.path.exists(model_path):  
        print("模型已存在")  
        return get_model(model_path)  
    else:  
        print("模型不存在,开始初始化模型..")  
        return RandomForestClassifierWrapper(model_path = model_path, random_state=100)  
  
  
class RandomForestClassifierWrapper:  
  
    def __init__(self, model_path:str, random_state: int = 100):  
  
        self.base_train_data = './assert/决策样本数据.xls'  
        # 定义参数网格  
        self.param_grid = {  
            'n_estimators': [50, 100, 200],  
            'max_depth': [5, 10, 15, 20, None],  
            'min_samples_split': [2, 5, 10],  
            'min_samples_leaf': [1, 2, 4]  
        }  
  
        self.rf_clf = RandomForestClassifier(random_state=random_state)  
        self.best_rf_clf = None  
        self.scaler = StandardScaler()  
        self.init(model_path)  
  
    def init(self, model_path):  
        x, y = self.load_training_data()  
        x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=300)  
        self.train(x_train, y_train, self.param_grid)  
        # 在测试集上评估模型性能  
        score = accuracy_score(y_test, self.predict(x_test))  
        print("模型在测试集上的评分:", score)  
        if score > 0.9:  
            save_model(model_path, self)  
  
    def load_training_data(self):  
        df = read_excel_data_by_pd(self.base_train_data, sheet_name='Sheet1')  
        x = df.iloc[:, 0:7]  
        y = df.iloc[:, -1]  
        return x, y  
  
    def train(self, x_train, y_train, param_grid):  
        X_train_scaled = self.scaler.fit_transform(x_train)  
  
        grid_search = GridSearchCV(estimator=self.rf_clf, param_grid=param_grid, cv=5)  
        grid_search.fit(X_train_scaled, y_train)  
  
        self.best_rf_clf = grid_search.best_estimator_  
  
    def predict(self, x):  
        x_scaled = self.scaler.transform(x)  
        return self.best_rf_clf.predict(x_scaled)  
  
    def predict_proba(self, x):  
        x_scaled = self.scaler.transform(x)  
        return self.best_rf_clf.predict_proba(x_scaled)  
  
  
def __test():  
    rf_model = model()  
    x_np = np.array([[35, 294000, 7000, 65, 5, 3, 423]])  
    predict_realdata_dis = rf_model.predict_proba(x_np)  
    print("预测样本为某个标签的概率:\n", predict_realdata_dis)  
    predict_realdata = rf_model.predict(x_np)  
    print("预测样本为某个标签的概率:\n", predict_realdata)  
  
  
if __name__ == '__main__':  
    try:  
        # pkl_file = sys.argv[1]  
        model_path = "./rf.pkl"  
        # json_str = sys.argv[2]  
        json_str = """  
[{  
"transferNumber": 35,  
"transferIncome": 294000,  
"transferCost": 7000,  
"estimateDelayTime": 65,  
"delayFlightNumber": 5,  
"flightType": 3,  
"waitAffectsNumber": 423  
}]"""
        print(json_str)  
        if not json_str:  
            raise Exception('无效的json_str')  
  
    except Exception as e:  
        print("请输入json_str")  
        exit(1)  
  
  
    json_data = json.loads(json_str)  
    data_list = [list(item.values()) for item in json_data]  
    x_np = np.array(data_list)  
    rf_model = model(model_path)  
    predict_realdata_dis = rf_model.predict_proba(x_np)  
    print("预测样本为某个标签的概率:\n", predict_realdata_dis)  
    predict_realdata = rf_model.predict(x_np)  
    print("预测样本为某个标签的概率:\n", predict_realdata)