如何在pandas中展示多项逻辑回归公式并实现无pickle部署
多项逻辑回归无pickle部署+公式展示实现方案
核心思路
- 摆脱pickle依赖的核心逻辑是不保存训练框架的模型对象,只提取训练完成后的核心参数(特征列表、类别映射、权重矩阵、偏置项),这类参数全是基础数值/字符串/列表结构,可以直接存为JSON,推理时手动实现多项逻辑回归的线性计算+softmax逻辑即可,不需要依赖sklearn等训练库,也不存在pickle的版本兼容、恶意代码风险。
- 剪枝直接用L1正则训练即可,L1会自动把无区分度的特征权重压到0,训练后剔除全类别权重都接近0的特征,就能大幅压缩部署时的参数量。
- 模型公式可以把每个类别的线性计算式整理成结构化表格,用pandas DataFrame直接渲染,方便查看和业务解释。
完整实现代码
import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import LabelEncoder import json # ---------------------- 1. 加载输入数据 ---------------------- # 特征矩阵 X = pd.DataFrame( data=[ [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 1] ], columns=['2853', '1864', '2658', '11187', '2874'] ) # 分类标签 y = pd.Series(['>50', '15-20', '35-50'], name='a.age') # 标签编码 le = LabelEncoder() y_enc = le.fit_transform(y) class_names = le.classes_.tolist() feature_names = X.columns.tolist() # ---------------------- 2. 模型训练 ---------------------- # 带L1正则的剪枝版配置:penalty='l1'、C越小正则越强剪枝力度越大 # 如果需要标准版无剪枝多项逻辑回归,把penalty改为'l2'、C设为1.0即可 model = LogisticRegression( penalty='l1', solver='saga', multi_class='multinomial', C=0.5, random_state=42 ) model.fit(X, y_enc) # ---------------------- 3. 提取可独立部署的参数 ---------------------- deploy_params = { "features": feature_names, "classes": class_names, "intercepts": model.intercept_.tolist(), "weights": model.coef_.tolist() # 形状:[类别数, 特征数] } # 剪枝逻辑:剔除所有类别上权重都接近0的特征 pruned_feat_idx = [] for feat_idx in range(len(feature_names)): feat_weights = [w[feat_idx] for w in deploy_params["weights"]] if not np.allclose(feat_weights, 0, atol=1e-6): pruned_feat_idx.append(feat_idx) deploy_params["features"] = [feature_names[i] for i in pruned_feat_idx] deploy_params["weights"] = [[w[i] for i in pruned_feat_idx] for w in deploy_params["weights"]] # 可直接存为JSON文件,不需要pickle with open("lr_deploy_params.json", "w", encoding="utf-8") as f: json.dump(deploy_params, f, ensure_ascii=False, indent=2) # ---------------------- 4. pandas展示模型公式 ---------------------- formula_df = pd.DataFrame(columns=["目标分类"] + feature_names + ["偏置项", "logit计算公式"]) for class_idx, class_name in enumerate(class_names): row = {"目标分类": class_name} formula_terms = [] for feat_idx, feat_name in enumerate(feature_names): w = round(model.coef_[class_idx, feat_idx], 4) row[feat_name] = w if abs(w) > 1e-6: formula_terms.append(f"{w}*{feat_name}") b = round(model.intercept_[class_idx], 4) row["偏置项"] = b formula_terms.append(f"{b}") row["logit计算公式"] = f"logit(P(y={class_name})) = " + " + ".join(formula_terms) formula_df = pd.concat([formula_df, pd.DataFrame([row])], ignore_index=True) print("=== pandas展示的模型公式表 ===") print(formula_df.to_string(index=False)) # ---------------------- 5. 无依赖推理逻辑(部署时直接复用,不需要sklearn) ---------------------- def predict(input_row: dict, deploy_params: dict) -> str: """ input_row格式:键为特征名,值为对应特征取值,示例:{"2853":0, "1864":0, "2658":1, "11187":0, "2874":0} """ features = deploy_params["features"] classes = deploy_params["classes"] intercepts = np.array(deploy_params["intercepts"]) weights = np.array(deploy_params["weights"]) # 构造输入向量,缺失特征默认填0 x = np.array([input_row.get(f, 0) for f in features]) # 计算logit logits = weights @ x + intercepts # softmax算概率,减最大值防止数值溢出 exp_logits = np.exp(logits - logits.max()) probs = exp_logits / exp_logits.sum() return classes[np.argmax(probs)] # 推理测试 test_input = {"2853":0, "1864":0, "2658":1, "11187":0, "2874":0} print(f"\n测试输入预测结果:{predict(test_input, deploy_params)}")
部署注意事项
- 部署时只需要拷贝
predict函数和导出的JSON参数文件即可,不需要安装sklearn,也不需要加载pickle模型;如果要彻底去掉numpy依赖,把函数里的矩阵运算替换成纯Python循环实现即可做到零第三方依赖运行。 - 剪枝力度可以通过调整模型训练时的
C参数控制,C值越小,被压到0的权重越多,最终保留的特征越少,部署体积越小。 - pandas输出的公式表可以直接导出为csv、excel,方便给业务方做模型规则解释。
内容的提问来源于stack exchange,提问作者Nabih Bawazir
相关产品推荐
相关产品推荐

