首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >大模型应用:大模型时代的XGBoost:传统梯度提升树与大模型的协同应用.103

大模型应用:大模型时代的XGBoost:传统梯度提升树与大模型的协同应用.103

原创
作者头像
未闻花名
发布2026-05-11 07:57:48
发布2026-05-11 07:57:48
530
举报
文章被收录于专栏:大模型应用大模型应用

一、前言

在人工智能技术体系中,XGBoost作为经典的梯度提升树模型,凭借高效的特征学习能力和优秀的结构化数据处理性能,长期占据机器学习应用的核心地位;而大模型则以其强大的语义理解、上下文建模和通用推理能力,成为自然语言处理、多模态分析等领域的颠覆性技术。将XGBoost与大模型结合,既能发挥XGBoost在结构化数据建模上的精准性和可解释性,又能借助大模型处理非结构化数据(文本、语音、图像)的优势,构建更全面、更强大的 AI 系统,今天我们由浅入深拆解 XGBoost 与大模型融合的全链路知识,深度了解其核心原理和应用实践。

二、基础知识

1. XGBoost 核心概念

1.1 梯度提升树(GBT)基础

梯度提升树是集成学习的核心分支,其核心思想是“逐步修正错误”:通过串行训练多个弱分类器,通常是决策树,每个新的弱分类器都专注于修正前一轮模型的预测误差,最终将所有弱分类器的预测结果加权求和,得到强分类器。

举个通俗的例子,假设我们要预测一个商品的销量:

  • 第一个决策树根据“价格”特征预测销量为1000件,但实际销量是1200件,误差为200 件;
  • 第二个决策树则专门学习“价格 + 促销活动”特征来修正这200件的误差,预测补充值为180件;
  • 第三个决策树再学习“价格 + 促销 + 季节”特征修正剩余20件误差,最终三个树的结果相加得到精准预测。

1.2 XGBoost 的核心优势

XGBoost是梯度提升树的优化版本,相比传统 GBT,其核心优势体现在:

  • 1. 正则化优化:在损失函数中加入 L1(Lasso)和 L2(Ridge)正则项,有效防止过拟合;
  • 2. 并行化训练:在构建决策树时,对特征的分裂点选择进行并行计算,大幅提升训练速度;
  • 3. 缺失值处理:自动学习缺失值的最优分裂方向,无需手动填充;
  • 4. 预排序与直方图优化:支持预排序和直方图两种分裂策略,平衡精度与效率;
  • 5. 剪枝策略:采用 “贪心 + 正则” 的剪枝方式,从叶子节点向上剪枝,保留最优树结构。

1.3 XGBoost 的关键参数

掌握以下核心参数是使用 XGBoost 的基础:

  • n_estimators:弱学习器数量,常用值100-1000
  • max_depth:决策树最大深度,常用值3-10
  • learning_rate:学习率,即步长,常用值0.01-0.3
  • subsample:样本采样比例,常用值0.7-1.0
  • colsample_bytree:特征采样比例,常用值0.7-1.0
  • reg_alpha:L1 正则化系数,常用值0-10
  • reg_lambda:L2 正则化系数,常用值1-10
  • objective:目标函数,常用值的分类函数:binary:logistic/multi:softmax;回归函数:reg:squarederror

2. XGBoost 与大模型结合

2.1 大模型的核心痛点

尽管大模型能力强大,但在实际应用中存在明显短板:

  • 1. 结构化数据处理能力弱:大模型擅长处理文本类非结构化数据,但对表格、数值型结构化数据的建模能力远不如XGBoost;
  • 2. 计算成本高:训练和推理大模型需要昂贵的GPU/TPU资源,单条推理成本远高于传统机器学习模型;
  • 3. 可解释性差:大模型的黑箱特性导致其预测结果难以解释,无法满足金融、医疗等领域的合规要求;
  • 4. 过拟合特定模式:在小样本、强规律的结构化数据任务中,大模型的泛化能力不如XGBoost;
  • 5. 数值计算精度低:大模型对数值的精准计算能力弱,无法替代传统模型完成高精度的回归、分类任务。

2.2 结合的核心逻辑

将 XGBoost 与大模型结合,本质是扬长避短、优势互补:

  • 大模型负责处理非结构化数据,如用户评论、商品描述、文档内容,将其转化为高质量的语义特征(Embedding);
  • XGBoost负责处理结构化数据(如用户年龄、商品价格、交易金额)+ 大模型输出的语义特征,完成精准的预测或分类任务;
  • 同时,XGBoost 的可解释性可以弥补大模型黑箱的缺陷,大模型的语义理解能力可以拓展 XGBoost 的特征维度。

举个实际场景:电商平台的用户购买预测;

  • 大模型将用户的历史评论、商品标题、客服对话转化为语义 Embedding;
  • XGBoost 结合用户的消费金额、购买频次、商品类别等结构化数据,以及大模型输出的 Embedding 特征;最终预测用户是否会购买某商品。
  • 这种融合方案的准确率远高于单独使用 XGBoost,缺少语义特征,也高于单独使用大模型,因为大模型的数值建模能力弱。

三、融合的核心原理

1. 特征融合原理

XGBoost 与大模型的融合本质是特征级融合,核心步骤为:

  • 1. 特征提取:
    • 结构化数据:直接提取数值型 / 类别型特征(如年龄、性别、价格),类别型特征需进行编码(One-Hot/Label Encoding);
    • 非结构化数据:通过大模型提取 Sentence Embedding,转化为固定维度的数值向量(如 768 维)。
  • 2. 特征拼接:将结构化特征向量与大模型输出的 Embedding 向量拼接,形成融合特征矩阵;
  • 3. 特征训练:将融合特征矩阵输入 XGBoost,利用 XGBoost 的梯度提升机制进行训练,得到最终模型。

这种融合方式的优势在于:

  • 保留了结构化数据的精准数值信息;
  • 融入了非结构化数据的语义信息;
  • XGBoost 能够自动学习不同特征的重要性,权重高的特征会被优先分裂。

2. 模型互补原理

XGBoost 与大模型的互补性体现在多个维度:

维度

XGBoost

大模型

融合优势

数据类型

擅长结构化数据

擅长非结构化数据

同时处理两类数据

可解释性

高(特征重要性、决策路径)

低(黑箱)

用 XGBoost 提升整体可解释性

计算成本

低(CPU 即可训练)

高(需 GPU)

仅用大模型做 Embedding 提取,降低整体成本

数值精度

高(精准拟合数值规律)

低(数值计算误差大)

用 XGBoost 保证预测精度

语义理解

无(无法处理文本语义)

高(强语义建模)

用大模型拓展特征维度

3. 数据一致性处理

在实际融合过程中,会遇到一些数据匹配度的问题,以下提供了一些常规的解决方案:

3.1特征维度匹配

  • 大模型输出的 Embedding 维度通常较高,如768维,而结构化特征维度较低,如几十维,可能导致特征分布不均衡。
  • 解决方案:对 Embedding 进行降维(PCA/TSNE)或特征选择(如基于方差的筛选);

3.2 特征尺度差异

  • 结构化特征(如年龄:0-100)与 Embedding 特征(如 - 1~1 之间的浮点数)尺度差异大,可能影响 XGBoost 的分裂决策。
  • 解决方案:对所有特征进行标准化、归一化;

3.3 过拟合风险

  • 高维度的 Embedding 特征可能导致XGBoost过拟合。
  • 解决方案:增加 XGBoost 的正则化参数(reg_alpha/reg_lambda)、降低树深度(max_depth)、使用早停(early stopping);

3.4. Embedding 一致性

  • 不同批次的文本输入大模型,可能输出分布略有差异的 Embedding,导致 XGBoost 模型泛化能力下降。
  • 解决方案:对大模型的 Embedding 进行归一化(L2 归一化),保证向量长度一致。

四、融合的执行流程

1. 执行流程

XGBoost 与大模型融合的完整执行流程可分为 6 个核心步骤:

2. 分步详解

步骤 1:数据收集

数据收集是融合模型的基础,需要同时收集两类数据:

2.1 结构化数据:

  • 数值型:如用户年龄、消费金额、商品价格、交易次数、评分等;
  • 类别型:如用户性别、商品类别、地区、支付方式等;
  • 时间型:如购买时间、注册时间、活动时间等(需转化为数值特征,如时间差、小时 / 天 / 月等)。

示例结构化数据集(电商用户购买预测):

用户 ID

年龄

性别

消费金额

购买频次

商品类别

评分

是否购买(标签)

1001

25

500

10

电子产品

4.5

1

1002

32

1200

25

美妆

4.8

1

1003

45

800

5

服装

3.2

0

2. 非结构化数据:

  • 文本型:如用户评论(“这款手机续航太差了”)、商品标题(“2024 新款华为 Mate60 Pro 12GB+512GB”)、客服对话、用户画像描述等;
  • 其他类型:如商品图片,可通过视觉大模型转化为 Embedding、用户语音,可通过语音大模型转化为文本再提取 Embedding。

示例非结构化数据(对应上述结构化数据):

用户 ID

用户评论

商品标题

1001

这款手机性能很好,值得购买

2024 新款华为 Mate60 Pro 12GB+512GB

1002

这款粉底液遮瑕效果超棒,推荐!

兰蔻持妆粉底液 PO-01 30ml

1003

这件衣服尺码偏小,材质一般

优衣库男士纯棉 T 恤 458762

步骤 2:数据预处理

预处理的目标是将原始数据转化为模型可处理的格式,分为两部分:

1. 结构化数据预处理:

  • 缺失值处理:数值型特征用均值、中位数、众数填充,类别型特征用“未知”填充或基于业务逻辑填充;
  • 类别特征编码:二分类特征(如性别)用Label Encoding(0/1),多分类特征(如商品类别)用 One-Hot Encoding或Target Encoding;
  • 数值特征归一化:对数值型特征进行标准化(Z-Score)或归一化(Min-Max),使特征尺度统一;
  • 时间特征转化:将时间戳转化为小时、天、周、月、季度等特征,或计算时间差。

2. 非结构化数据预处理:

  • 文本清洗:去除特殊字符、标点、多余空格,统一大小写,纠正错别字;
  • 分词:将文本拆分为单词、中文分词,如使用Jieba分词;
  • 去停用词:去除无意义的词汇,如“的”、“了”、“a”、“the”;
  • 文本长度统一:对过长、过短的文本进行截断、补全,保证输入大模型的文本长度一致。

步骤 3:大模型 Embedding 提取

这是融合的核心步骤,目标是将文本转化为语义Embedding:

1. 选择合适的大模型:

  • 开源模型:LLaMA2、ChatGLM、Qwen等,适合本地部署;
  • 闭源 API:OpenAI Embedding、混元大模型、通义Embedding 等,适合快速开发。
  • 推荐使用开源的 BERT-base 模型,中文的为bert-base-chinese,参数量小(110M),部署成本低,Embedding效果好。

2. Embedding 提取流程:

  • 加载预训练大模型和 Tokenizer;
  • 将预处理后的文本输入 Tokenizer,转化为模型可识别的 token;
  • 将 token 输入大模型,获取输出的 Hidden States;
  • 对 Hidden States 进行池化,如均值池化、最大值池化、[CLS] token等,得到 Sentence Embedding;
  • 对 Embedding 进行 L2 归一化,保证向量长度为 1,提升稳定性。

3. Embedding 降维:

  • 如果 Embedding 维度过高,如768维,可使用 PCA 进行降维,保留 95% 以上的方差,减少特征维度,提升 XGBoost 训练速度。

步骤 4:特征融合

特征融合的目标是将结构化特征与 Embedding 特征结合:

  • 1. 特征拼接:将预处理后的结构化特征矩阵(n_samples × n_structured_features)与 Embedding 特征矩阵(n_samples × n_embedding_features)按列拼接,得到融合特征矩阵(n_samples × (n_structured_features + n_embedding_features));
  • 2. 特征选择:
    • 方差筛选:去除方差过小的特征,如全部为0的特征;
    • 相关性筛选:计算特征与标签的相关性,去除相关性极低的特征;
    • 递归特征消除(RFE):使用 XGBoost 的特征重要性,递归去除不重要的特征;
  • 3. 特征验证:检查融合后的特征是否存在缺失值、异常值,确保数据质量。

步骤 5:XGBoost 模型训练

这一步是传统 XGBoost 的训练流程,但需要针对融合特征进行参数调优:

  • 1. 数据集划分:将融合特征矩阵按 7:2:1 的比例划分为训练集、验证集、测试集;
  • 2. 参数初始化:设置 XGBoost 的基础参数,如n_estimators=100、max_depth=5、learning_rate=0.1;
  • 3. 模型训练:使用训练集训练模型,验证集监控过拟合,通过早停策略:当验证集损失连续 n 轮不下降时停止训练;
  • 4. 参数调优:使用网格搜索、随机搜索、贝叶斯优化调优核心参数,如max_depth、learning_rate、reg_alpha、reg_lambda,提升模型性能;
  • 5. 模型保存:将训练好的 XGBoost 模型保存为文件,如 JSON/PMML 格式,方便后续部署。

步骤 6:模型评估与部署

1. 模型评估:

  • 分类任务:计算准确率(ACC)、精确率(Precision)、召回率(Recall)、F1 值、AUC-ROC 等指标;
  • 回归任务:计算均方误差(MSE)、平均绝对误差(MAE)、R² 等指标;
  • 可解释性分析:输出 XGBoost 的特征重要性,分析哪些特征对预测结果影响最大,包括结构化特征和 Embedding 特征;
  • 对比实验:与单独使用 XGBoost(无 Embedding)、单独使用大模型直接预测的结果对比,验证融合方案的优势。

2. 模型部署:

  • 离线部署:将模型集成到批处理系统中,处理离线数据;
  • 在线部署:搭建 API 服务,如 FastAPI/Flask,接收结构化特征和文本数据,实时提取 Embedding 并调用 XGBoost 模型预测;
  • 性能优化:对 Embedding 提取过程进行缓存,对 XGBoost 模型进行量化,提升在线推理速度。

流程简化总结:

五、完整实例实现

步骤 1:导入库

代码语言:python
复制
import os
import re
import numpy as np
import pandas as pd
import jieba
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.metrics import accuracy_score, classification_report, roc_auc_score, confusion_matrix
from sklearn.feature_selection import VarianceThreshold
import xgboost as xgb
from xgboost import callback as xgb_callback
from transformers import BertTokenizer, BertModel
import torch
import warnings
warnings.filterwarnings('ignore')

# 设置中文字体(解决matplotlib中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 设置设备(优先使用GPU)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"使用设备:{device}")

输出结果:

使用设备:cpu

步骤 2:数据准备与预处理

代码语言:python
复制
# ====================== 1. 生成示例数据(电商用户购买预测) ======================
def generate_sample_data():
    """生成示例结构化数据和文本数据"""
    # 结构化数据
    structured_data = pd.DataFrame({
        'user_id': range(1000, 1500),
        'age': np.random.randint(18, 60, size=500),
        'gender': np.random.choice(['男', '女'], size=500, p=[0.5, 0.5]),
        'consumption_amount': np.random.normal(1000, 300, size=500).round(2),
        'purchase_frequency': np.random.randint(1, 30, size=500),
        'product_category': np.random.choice(['电子产品', '美妆', '服装', '食品', '家居'], size=500),
        'rating': np.random.uniform(1, 5, size=500).round(1),
        'is_purchase': np.random.choice([0, 1], size=500, p=[0.4, 0.6])
    })
    
    # 文本数据(用户评论 + 商品标题)
    comments = [
        "这款产品性能很好,值得购买",
        "质量一般,价格偏高",
        "使用体验很棒,推荐!",
        "物流很慢,包装破损",
        "性价比超高,会回购",
        "尺寸不合适,材质差",
        "比预期的好,满意",
        "售后服务差,不推荐"
    ]
    
    product_titles = [
        "2024新款华为Mate60 Pro 12GB+512GB",
        "兰蔻持妆粉底液PO-01 30ml",
        "优衣库男士纯棉T恤458762",
        "三只松鼠坚果大礼包1500g",
        "小米空气净化器4 Pro",
        "美的电饭煲5L大容量",
        "苹果AirPods Pro 2代",
        "Nike Air Max 270运动鞋"
    ]
    
    text_data = pd.DataFrame({
        'user_id': range(1000, 1500),
        'user_comment': np.random.choice(comments, size=500),
        'product_title': np.random.choice(product_titles, size=500)
    })
    
    # 合并文本数据(将评论和标题拼接)
    text_data['combined_text'] = text_data['user_comment'] + " " + text_data['product_title']
    
    # 合并结构化数据和文本数据
    data = pd.merge(structured_data, text_data, on='user_id')
    
    return data

# 生成数据
data = generate_sample_data()
print("数据基本信息:")
print(data.info())
print("\n数据前5行:")
print(data.head())

输出结果:

数据基本信息: <class 'pandas.DataFrame'> RangeIndex: 500 entries, 0 to 499 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 500 non-null int64 1 age 500 non-null int32 2 gender 500 non-null str 3 consumption_amount 500 non-null float64 4 purchase_frequency 500 non-null int32 5 product_category 500 non-null str 6 rating 500 non-null float64 7 is_purchase 500 non-null int64 8 user_comment 500 non-null str 9 product_title 500 non-null str 10 combined_text 500 non-null str dtypes: float64(2), int32(2), int64(2), str(5) memory usage: 100.2 KB None 数据前5行: user_id age gender consumption_amount ... is_purchase user_comment product_title combined_text 0 1000 36 男 1508.83 ... 1 物流很慢,包装破损 Nike Air Max 270运动鞋 物流很慢,包装破损 Nike Air Max 270运动鞋 1 1001 50 女 370.92 ... 1 售后服务差,不推荐 Nike Air Max 270运动鞋 售后服务差,不推荐 Nike Air Max 270运动鞋 2 1002 22 男 451.52 ... 0 尺寸不合适,材质差 苹果AirPods Pro 2代 尺寸不合适,材质差 苹果AirPods Pro 2代 3 1003 55 女 716.35 ... 0 质量一般,价格偏高 小米空气净化器4 Pro 质量一般,价格偏高 小米空气净化器4 Pro 4 1004 53 男 1442.72 ... 0 尺寸不合适,材质差 三只松鼠坚果大礼包1500g 尺寸不合适,材质差 三只松鼠坚果大礼包1500g [5 rows x 11 columns]

步骤 3:大模型 Embedding 提取

代码语言:python
复制
# ====================== 2. 结构化数据预处理 ======================
print("====================== 2. 结构化数据预处理 ======================")
def preprocess_structured_data(data):
    """预处理结构化数据"""
    # 分离特征和标签
    X_structured = data[['age', 'gender', 'consumption_amount', 'purchase_frequency', 'product_category', 'rating']]
    y = data['is_purchase']
    
    # 定义数值特征和类别特征
    numeric_features = ['age', 'consumption_amount', 'purchase_frequency', 'rating']
    categorical_features = ['gender', 'product_category']
    
    # 数值特征处理管道:缺失值填充 + 标准化
    numeric_transformer = Pipeline(steps=[
        ('imputer', SimpleImputer(strategy='median')),  # 中位数填充缺失值
        ('scaler', StandardScaler())  # 标准化
    ])
    
    # 类别特征处理管道:缺失值填充 + One-Hot编码
    categorical_transformer = Pipeline(steps=[
        ('imputer', SimpleImputer(strategy='most_frequent')),  # 众数填充缺失值
        ('onehot', OneHotEncoder(handle_unknown='ignore'))  # One-Hot编码,忽略未知类别
    ])
    
    # 组合预处理管道
    preprocessor = ColumnTransformer(
        transformers=[
            ('num', numeric_transformer, numeric_features),
            ('cat', categorical_transformer, categorical_features)
        ])
    
    # 执行预处理
    X_structured_processed = preprocessor.fit_transform(X_structured)

    # 转换为DataFrame(方便后续拼接)
    # 获取特征名称
    num_feature_names = numeric_features
    cat_feature_names = preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names_out(categorical_features)
    feature_names = list(num_feature_names) + list(cat_feature_names)

    # 根据输出类型选择合适的转换方式
    if hasattr(X_structured_processed, 'toarray'):
        X_structured_df = pd.DataFrame(X_structured_processed.toarray(), columns=feature_names)
    else:
        X_structured_df = pd.DataFrame(X_structured_processed, columns=feature_names)
    
    return X_structured_df, y, preprocessor

# 预处理结构化数据
X_structured, y, structured_preprocessor = preprocess_structured_data(data)
print("\n预处理后的结构化特征:")
print(X_structured.head())
print(f"\n结构化特征形状:{X_structured.shape}")

# ====================== 3. 文本数据预处理 ======================
def preprocess_text(text):
    """预处理单条文本"""
    # 去除特殊字符
    text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\s]', '', text)
    # 分词
    words = jieba.lcut(text)
    # 去停用词(简单停用词表)
    stopwords = ['的', '了', '是', '我', '你', '他', '她', '它', '在', '有', '就', '都', '和', '与', '及', 'a', 'an', 'the']
    words = [word for word in words if word not in stopwords and len(word) > 0]
    # 拼接为字符串
    processed_text = ' '.join(words)
    return processed_text

# 预处理所有文本
data['processed_text'] = data['combined_text'].apply(preprocess_text)
print("\n预处理后的文本示例:")
print(data[['combined_text', 'processed_text']].head())

输出结果:

预处理后的结构化特征: age consumption_amount purchase_frequency ... product_category_电子产品 product_category_美妆 product_category_食品 0 -0.198386 1.565593 0.142051 ... 1.0 0.0 0.0 1 0.968590 -2.000561 0.866802 ... 0.0 1.0 0.0 2 -1.365362 -1.747964 -0.945075 ... 0.0 0.0 0.0 3 1.385368 -0.918000 1.591552 ... 0.0 0.0 1.0 4 1.218657 1.358407 -0.945075 ... 0.0 0.0 0.0 [5 rows x 11 columns] 结构化特征形状:(500, 11) Building prefix dict from the default dictionary ... Loading model from cache C:\Users\Admin\AppData\Local\Temp\jieba.cache Loading model cost 0.387 seconds. Prefix dict has been built successfully. 预处理后的文本示例: combined_text processed_text 0 物流很慢,包装破损 Nike Air Max 270运动鞋 物流 很 慢 包装 破损 Nike Air Max 270 运动鞋 1 售后服务差,不推荐 Nike Air Max 270运动鞋 售后服务 差 不 推荐 Nike Air Max 270 运动鞋 2 尺寸不合适,材质差 苹果AirPods Pro 2代 尺寸 不 合适 材质 差 苹果 AirPods Pro 2 代 3 质量一般,价格偏高 小米空气净化器4 Pro 质量 一般 价格 偏高 小米 空气 净化器 4 Pro 4 尺寸不合适,材质差 三只松鼠坚果大礼包1500g 尺寸 不 合适 材质 差 三只 松鼠 坚果 大礼包 1500g

步骤 4:XGBoost 模型训练与评估

代码语言:python
复制
class BertEmbeddingExtractor:
    """BERT Embedding提取器"""
    def __init__(self, model_name='bert-base-chinese'):
        self.tokenizer = BertTokenizer.from_pretrained(model_name)
        self.model = BertModel.from_pretrained(model_name).to(device)
        self.model.eval()  # 设置为评估模式
    
    def get_embedding(self, text, max_length=32):
        """提取单条文本的Embedding"""
        # 编码文本
        inputs = self.tokenizer(
            text,
            max_length=max_length,
            padding='max_length',
            truncation=True,
            return_tensors='pt'
        ).to(device)
        
        # 前向传播(不计算梯度)
        with torch.no_grad():
            outputs = self.model(**inputs)
        
        # 获取最后一层的Hidden States
        last_hidden_state = outputs.last_hidden_state  # [1, max_length, 768]
        
        # 均值池化得到句子Embedding
        embedding = torch.mean(last_hidden_state, dim=1).squeeze(0)  # [768]
        
        # L2归一化
        embedding = torch.nn.functional.normalize(embedding, p=2, dim=0)
        
        return embedding.cpu().numpy()
    
    def batch_get_embedding(self, texts, batch_size=32):
        """批量提取Embedding"""
        embeddings = []
        for i in range(0, len(texts), batch_size):
            batch_texts = texts[i:i+batch_size]
            
            # 批量编码
            inputs = self.tokenizer(
                batch_texts,
                max_length=32,
                padding='max_length',
                truncation=True,
                return_tensors='pt'
            ).to(device)
            
            # 前向传播
            with torch.no_grad():
                outputs = self.model(**inputs)
            
            # 均值池化
            batch_embeddings = torch.mean(outputs.last_hidden_state, dim=1)  # [batch_size, 768]
            # L2归一化
            batch_embeddings = torch.nn.functional.normalize(batch_embeddings, p=2, dim=1)
            
            embeddings.extend(batch_embeddings.cpu().numpy())
        
        return np.array(embeddings)

# 初始化Embedding提取器
embedding_extractor = BertEmbeddingExtractor()

# 提取文本Embedding
print("\n开始提取文本Embedding...")
texts = data['processed_text'].tolist()
X_embedding = embedding_extractor.batch_get_embedding(texts)

# Embedding降维(PCA)
print(f"\n原始Embedding形状:{X_embedding.shape}")
pca = PCA(n_components=0.95)  # 保留95%的方差
X_embedding_pca = pca.fit_transform(X_embedding)
print(f"降维后的Embedding形状:{X_embedding_pca.shape}")

# 转换为DataFrame
embedding_feature_names = [f'embedding_{i}' for i in range(X_embedding_pca.shape[1])]
X_embedding_df = pd.DataFrame(X_embedding_pca, columns=embedding_feature_names)

# ====================== 4. 特征融合 ======================
# 拼接结构化特征和Embedding特征
X_combined = pd.concat([X_structured.reset_index(drop=True), X_embedding_df.reset_index(drop=True)], axis=1)

# 特征选择:去除方差过小的特征
variance_selector = VarianceThreshold(threshold=0.01)
X_combined_selected = variance_selector.fit_transform(X_combined)

# 获取选择后的特征名称
selected_feature_indices = variance_selector.get_support(indices=True)
selected_feature_names = [X_combined.columns[i] for i in selected_feature_indices]

print(f"\n融合后的特征形状(原始):{X_combined.shape}")
print(f"融合后的特征形状(特征选择后):{X_combined_selected.shape}")
print(f"选择后的特征数量:{len(selected_feature_names)}")

# 转换为DataFrame
X_combined_df = pd.DataFrame(X_combined_selected, columns=selected_feature_names)

输出结果:

Loading weights: 100%|████████████████████████████████| 199/199 [00:00<00:00, 4484.75it/s, Materializing param=pooler.dense.weight] BertModel LOAD REPORT from: bert-base-chinese Key | Status | | -------------------------------------------+------------+--+- cls.predictions.transform.LayerNorm.bias | UNEXPECTED | | cls.seq_relationship.bias | UNEXPECTED | | cls.seq_relationship.weight | UNEXPECTED | | cls.predictions.transform.dense.weight | UNEXPECTED | | cls.predictions.transform.dense.bias | UNEXPECTED | | cls.predictions.transform.LayerNorm.weight | UNEXPECTED | | cls.predictions.bias | UNEXPECTED | | Notes: - UNEXPECTED :can be ignored when loading from different task/architecture; not ok if you expect identical arch. 开始提取文本Embedding... 原始Embedding形状:(500, 768) 降维后的Embedding形状:(500, 16) 融合后的特征形状(原始):(500, 27) 融合后的特征形状(特征选择后):(500, 16) 选择后的特征数量:16

步骤 5:在线推理示例

代码语言:python
复制
# ====================== 1. 划分数据集 ======================
X_train, X_test, y_train, y_test = train_test_split(
    X_combined_df, y, test_size=0.2, random_state=42, stratify=y
)
X_train, X_val, y_train, y_val = train_test_split(
    X_train, y_train, test_size=0.25, random_state=42, stratify=y_train
)

print(f"\n训练集形状:{X_train.shape}")
print(f"验证集形状:{X_val.shape}")
print(f"测试集形状:{X_test.shape}")

# ====================== 2. 定义XGBoost模型 ======================
# 设置参数
xgb_params = {
    'objective': 'binary:logistic',  # 二分类任务
    'max_depth': 5,                  # 树最大深度
    'learning_rate': 0.1,            # 学习率
    'n_estimators': 200,             # 树的数量
    'subsample': 0.8,                # 样本采样比例
    'colsample_bytree': 0.8,         # 特征采样比例
    'reg_alpha': 0.1,                # L1正则化
    'reg_lambda': 1,                 # L2正则化
    'eval_metric': 'auc',            # 评估指标
    'seed': 42,                      # 随机种子
    'verbosity': 1                   # 输出日志级别
}

# 初始化模型
model = xgb.XGBClassifier(**xgb_params)

# ====================== 3. 训练模型 ======================
print("\n开始训练XGBoost模型...")
model.fit(X_train, y_train, verbose=True)

# ====================== 4. 模型评估 ======================
# 预测
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]

# 计算评估指标
accuracy = accuracy_score(y_test, y_pred)
auc = roc_auc_score(y_test, y_pred_proba)
classification_rep = classification_report(y_test, y_pred)

print("\n====================== 模型评估结果 ======================")
print(f"准确率(ACC):{accuracy:.4f}")
print(f"AUC-ROC:{auc:.4f}")
print("\n分类报告:")
print(classification_rep)

# ====================== 5. 特征重要性分析 ======================
# 获取特征重要性
feature_importance = model.get_booster().get_score(importance_type='weight')
# 转换为DataFrame
feature_importance_df = pd.DataFrame({
    'feature': list(feature_importance.keys()),
    'importance': list(feature_importance.values())
})
# 按重要性排序
feature_importance_df = feature_importance_df.sort_values('importance', ascending=False).head(20)

# 绘制特征重要性图
plt.figure(figsize=(12, 8))
sns.barplot(x='importance', y='feature', data=feature_importance_df)
plt.title('XGBoost特征重要性(Top 20)', fontsize=14)
plt.xlabel('重要性得分', fontsize=12)
plt.ylabel('特征名称', fontsize=12)
plt.tight_layout()
plt.savefig('feature_importance.png', dpi=300)
plt.show()

# ====================== 6. 混淆矩阵 ======================
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['未购买', '购买'], 
            yticklabels=['未购买', '购买'])
plt.title('混淆矩阵', fontsize=14)
plt.xlabel('预测标签', fontsize=12)
plt.ylabel('真实标签', fontsize=12)
plt.tight_layout()
plt.savefig('confusion_matrix.png', dpi=300)
plt.show()

# ====================== 7. 对比实验(仅使用结构化特征) ======================
print("\n====================== 对比实验:仅使用结构化特征 ======================")
# 仅使用结构化特征训练XGBoost
X_train_struct = X_train[X_structured.columns] if set(X_structured.columns).issubset(X_train.columns) else X_train.iloc[:, :len(X_structured.columns)]
X_test_struct = X_test[X_structured.columns] if set(X_structured.columns).issubset(X_test.columns) else X_test.iloc[:, :len(X_structured.columns)]

# 训练模型
model_struct = xgb.XGBClassifier(**xgb_params)
model_struct.fit(X_train_struct, y_train, verbose=False)

# 评估
y_pred_struct = model_struct.predict(X_test_struct)
y_pred_proba_struct = model_struct.predict_proba(X_test_struct)[:, 1]
accuracy_struct = accuracy_score(y_test, y_pred_struct)
auc_struct = roc_auc_score(y_test, y_pred_proba_struct)

print(f"仅结构化特征 - 准确率(ACC):{accuracy_struct:.4f}")
print(f"仅结构化特征 - AUC-ROC:{auc_struct:.4f}")
print(f"\n融合模型 vs 仅结构化特征:")
print(f"准确率提升:{(accuracy - accuracy_struct)*100:.2f}%")
print(f"AUC提升:{(auc - auc_struct)*100:.2f}%")

# ====================== 8. 保存模型 ======================
# 保存XGBoost模型
model.save_model('xgboost_llm_fusion.model')
print("\n模型已保存为:xgboost_llm_fusion.model")

# 保存特征名称
with open('feature_names.txt', 'w', encoding='utf-8') as f:
    for name in selected_feature_names:
        f.write(f"{name}\n")


class XGBoostLLMFusionInference:
    """XGBoost+大模型融合推理类"""
    def __init__(self, model_path, feature_names_path, embedding_extractor, structured_preprocessor):
        # 加载模型
        self.model = xgb.XGBClassifier()
        self.model.load_model(model_path)
        
        # 加载特征名称
        with open(feature_names_path, 'r', encoding='utf-8') as f:
            self.feature_names = [line.strip() for line in f.readlines()]
        
        # Embedding提取器
        self.embedding_extractor = embedding_extractor
        
        # 结构化数据预处理器
        self.structured_preprocessor = structured_preprocessor
        
        # PCA模型(这里简化,实际应保存训练好的PCA模型)
        self.pca = pca
    
    def preprocess_input(self, structured_data, text):
        """预处理输入数据"""
        # 1. 预处理结构化数据
        structured_df = pd.DataFrame([structured_data])
        structured_processed = self.structured_preprocessor.transform(structured_df)

        # 根据输出类型选择合适的转换方式
        if hasattr(structured_processed, 'toarray'):
            structured_df_processed = pd.DataFrame(structured_processed.toarray(),
                                                  columns=self.structured_preprocessor.get_feature_names_out())
        else:
            structured_df_processed = pd.DataFrame(structured_processed,
                                                  columns=self.structured_preprocessor.get_feature_names_out())

        # 2. 预处理文本并提取Embedding
        processed_text = preprocess_text(text)
        embedding = self.embedding_extractor.get_embedding(processed_text)
        embedding_pca = self.pca.transform([embedding])

        # 3. 特征融合
        embedding_df = pd.DataFrame(embedding_pca, columns=[f'embedding_{i}' for i in range(embedding_pca.shape[1])])
        combined_df = pd.concat([structured_df_processed, embedding_df], axis=1)

        # 4. 确保所有需要的特征都存在,缺失的填充为0
        for col in self.feature_names:
            if col not in combined_df.columns:
                combined_df[col] = 0

        # 5. 选择模型训练时的特征
        combined_df = combined_df[self.feature_names]

        return combined_df
    
    def predict(self, structured_data, text):
        """预测"""
        # 预处理输入
        input_data = self.preprocess_input(structured_data, text)
        
        # 预测
        pred_proba = self.model.predict_proba(input_data)[0]
        pred_label = self.model.predict(input_data)[0]
        
        return {
            'pred_label': int(pred_label),
            'pred_prob': float(pred_proba[1]),
            'label_name': '购买' if pred_label == 1 else '未购买'
        }

# 初始化推理类
inference = XGBoostLLMFusionInference(
    model_path='xgboost_llm_fusion.model',
    feature_names_path='feature_names.txt',
    embedding_extractor=embedding_extractor,
    structured_preprocessor=structured_preprocessor
)

# 示例推理
sample_structured_data = {
    'age': 28,
    'gender': '女',
    'consumption_amount': 1500.0,
    'purchase_frequency': 20,
    'product_category': '美妆',
    'rating': 4.8
}

sample_text = "这款粉底液遮瑕效果超棒,持妆久,推荐! 兰蔻持妆粉底液PO-01 30ml"

# 推理
result = inference.predict(sample_structured_data, sample_text)
print("\n====================== 在线推理示例 ======================")
print(f"输入结构化数据:{sample_structured_data}")
print(f"输入文本:{sample_text}")
print(f"预测结果:{result['label_name']}")
print(f"  - 购买概率:{result['pred_prob']:.4f} ({result['pred_prob']*100:.2f}%)")
print(f"  - 未购买概率:{1-result['pred_prob']:.4f} ({(1-result['pred_prob'])*100:.2f}%)")

# 测试多个样本
print("\n====================== 多样本对比测试 ======================")
test_cases = [
    {
        'structured': {'age': 35, 'gender': '女', 'consumption_amount': 2000.0, 'purchase_frequency': 25, 'product_category': '美妆', 'rating': 4.9},
        'text': "产品非常棒,会继续购买! 兰蔻持妆粉底液PO-01 30ml"
    },
    {
        'structured': {'age': 22, 'gender': '男', 'consumption_amount': 500.0, 'purchase_frequency': 2, 'product_category': '服装', 'rating': 2.5},
        'text': "质量太差,不建议购买 优衣库男士纯棉T恤458762"
    },
    {
        'structured': {'age': 45, 'gender': '女', 'consumption_amount': 3000.0, 'purchase_frequency': 15, 'product_category': '电子产品', 'rating': 4.5},
        'text': "性能出色,推荐购买 2024新款华为Mate60 Pro 12GB+512GB"
    }
]

for i, test_case in enumerate(test_cases, 1):
    pred = inference.predict(test_case['structured'], test_case['text'])
    print(f"\n样本{i}:")
    print(f"  预测: {pred['label_name']} (购买概率: {pred['pred_prob']:.4f})")
    print(f"  评论: {test_case['text']}")

输出结果:

训练集形状:(300, 16) 验证集形状:(100, 16) 测试集形状:(100, 16) 开始训练XGBoost模型... ====================== 模型评估结果 ====================== 准确率(ACC):0.6500 AUC-ROC:0.6419 分类报告: precision recall f1-score support 0 0.56 0.46 0.51 39 1 0.69 0.77 0.73 61 accuracy 0.65 100 macro avg 0.63 0.62 0.62 100 weighted avg 0.64 0.65 0.64 100

====================== 对比实验:仅使用结构化特征 ====================== 仅结构化特征 - 准确率(ACC):0.5400 仅结构化特征 - AUC-ROC:0.5254 融合模型 vs 仅结构化特征: 准确率提升:11.00% AUC提升:11.64% 模型已保存为:xgboost_llm_fusion.model

====================== 在线推理示例 ====================== 输入结构化数据:{'age': 28, 'gender': '女', 'consumption_amount': 1500.0, 'purchase_frequency': 20, 'product_category': '美妆', 'rating': 4.8} 输入文本:这款粉底液遮瑕效果超棒,持妆久,推荐! 兰蔻持妆粉底液PO-01 30ml 预测结果:购买 - 购买概率:0.9326 (93.26%) - 未购买概率:0.0674 (6.74%) 样本1: 预测: 购买 (购买概率: 0.8819) 评论: 产品非常棒,会继续购买! 兰蔻持妆粉底液PO-01 30ml 样本2: 预测: 未购买 (购买概率: 0.3257) 评论: 质量太差,不建议购买 优衣库男士纯棉T恤458762 样本3: 预测: 购买 (购买概率: 0.9219) 评论: 性能出色,推荐购买 2024新款华为Mate60 Pro 12GB+512GB

六、总结

XGBoost 结合大模型核心就是两者优势互补,大模型搞定文本这类非结构化数据,提取语义特征,XGBoost 擅长结构化数据建模,把两者的特征结合起来,既解决了大模型处理数值差、成本高的问题,又弥补了 XGBoost 不懂语义的短板。传统模型和大模型不是替代关系,而是协同关系。以前总觉得大模型很高大上,传统模型过时了,现在才明白,能落地、能解决实际问题的组合才是最好的。整个学习过程不用死磕复杂公式,从原理到代码一步步来,就能慢慢理解。不管是学 XGBoost 还是大模型,打好基础、注重实战,比盲目追求高大上的技术更重要。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、基础知识
    • 1. XGBoost 核心概念
      • 1.1 梯度提升树(GBT)基础
      • 1.2 XGBoost 的核心优势
      • 1.3 XGBoost 的关键参数
    • 2. XGBoost 与大模型结合
      • 2.1 大模型的核心痛点
      • 2.2 结合的核心逻辑
  • 三、融合的核心原理
    • 1. 特征融合原理
    • 2. 模型互补原理
    • 3. 数据一致性处理
  • 四、融合的执行流程
    • 1. 执行流程
    • 2. 分步详解
      • 步骤 1:数据收集
      • 步骤 2:数据预处理
      • 步骤 3:大模型 Embedding 提取
      • 步骤 4:特征融合
      • 步骤 5:XGBoost 模型训练
      • 步骤 6:模型评估与部署
  • 五、完整实例实现
    • 步骤 1:导入库
    • 步骤 2:数据准备与预处理
    • 步骤 3:大模型 Embedding 提取
    • 步骤 4:XGBoost 模型训练与评估
    • 步骤 5:在线推理示例
  • 六、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档