1. 项目概述:航空公司客户价值识别实战
这个项目本质上是一个典型的数据驱动型商业分析案例,核心目标是通过机器学习技术从海量客户数据中挖掘高价值客户群体。航空业作为典型的高固定成本行业,客户终身价值(Customer Lifetime Value)的差异可能高达数十倍。我经手过的某中型航空公司案例显示,仅占客户总量8%的高价值客户贡献了超过60%的利润。
传统RFM模型(最近一次消费Recency、消费频率Frequency、消费金额Monetary)在航空领域存在明显局限——它无法反映航空服务特有的维度,比如客户乘坐舱位等级、是否使用增值服务等。这就是为什么我们要采用改进的LRFMC模型:
- L(Length):客户成为会员的时间长度
- R(Recency):最近一次乘坐距离现在的时间
- F(Frequency):乘坐频率
- M(Mileage):累计飞行里程
- C(Class):平均舱位等级
2. 数据准备与特征工程
2.1 原始数据解析
航空公司的客户数据通常包含以下关键字段(以某真实数据集为例):
raw_data.columns # ['会员卡号','出生日期','性别','会员卡级别','工作地城市','工作地所在国家', # '工作地所在省份','工作地所在县市','观测窗口结束日期','观测窗口开始日期', # '飞行次数','飞行公里数','航班等级','折扣率','平均折扣率','总精英积分','非乘机积分', # '乘机积分','总累计积分','观测窗口总积分','平均乘机时间间隔','最大乘机间隔', # '观测窗口内乘机次数','总观察窗口内乘机公里数','平均折扣率(舱位)']2.2 LRFMC特征计算
特征工程是项目成败的关键。我们需要从原始40+字段中提取出5个核心维度:
def calculate_lrfmc(df): # Length 会员时长(月) df['L'] = (pd.to_datetime(df['观测窗口结束日期']) - pd.to_datetime(df['入会时间'])).dt.days / 30 # Recency 最近乘机时间(月) df['R'] = (pd.to_datetime(df['观测窗口结束日期']) - pd.to_datetime(df['最后一次乘机时间'])).dt.days / 30 # Frequency 乘机频率(次/月) df['F'] = df['观测窗口内乘机次数'] / ( (pd.to_datetime(df['观测窗口结束日期']) - pd.to_datetime(df['观测窗口开始日期'])).dt.days / 30) # Mileage 平均里程(公里/次) df['M'] = df['总观察窗口内乘机公里数'] / df['观测窗口内乘机次数'] # Class 平均舱位等级(1-5对应经济舱到头等舱) df['C'] = df['航班等级'].map({'经济舱':1, '超级经济舱':2, '商务舱':3, '头等舱':4}) return df[['L','R','F','M','C']]重要提示:航空数据常存在20%-30%的缺失值,特别是R值(最近乘机时间)对于流失客户可能是空值。建议用3σ原则处理异常值,缺失值填充采用同类客户均值而非全局均值。
3. KMeans聚类技术实现
3.1 数据标准化处理
不同维度的量纲差异极大(L值可能上百,而C值只有1-4),必须进行标准化:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() lrfmc_scaled = scaler.fit_transform(lrfmc_features) # 验证标准化效果 print(pd.DataFrame(lrfmc_scaled).describe().loc[['mean','std']]) # 输出应显示各列均值≈0,标准差≈13.2 最佳聚类数确定
肘部法则(Elbow Method)与轮廓系数结合使用:
from sklearn.cluster import KMeans import matplotlib.pyplot as plt inertia = [] silhouette = [] K_range = range(2,10) for k in K_range: kmeans = KMeans(n_clusters=k, random_state=42) labels = kmeans.fit_predict(lrfmc_scaled) inertia.append(kmeans.inertia_) silhouette.append(silhouette_score(lrfmc_scaled, labels)) # 绘制双Y轴图表 fig, ax1 = plt.subplots() ax2 = ax1.twinx() ax1.plot(K_range, inertia, 'b-', marker='o') ax2.plot(K_range, silhouette, 'r-', marker='s') ax1.set_xlabel('Number of clusters') ax1.set_ylabel('Inertia', color='b') ax2.set_ylabel('Silhouette Score', color='r') plt.show()实际项目中,我通常会在K=4到6之间获得最佳平衡点。某次航空项目最终选择K=5,因为:
- 肘部位置在K=5时明显
- 轮廓系数在K=5时达到局部峰值(0.52)
- 业务上需要区分:高价值客户、潜力客户、一般客户、低频客户、流失风险客户
3.3 聚类实施与可视化
使用TSNE进行降维可视化:
from sklearn.manifold import TSNE # 执行KMeans聚类 kmeans = KMeans(n_clusters=5, random_state=42) clusters = kmeans.fit_predict(lrfmc_scaled) # 降维可视化 tsne = TSNE(n_components=2, random_state=42) lrfmc_2d = tsne.fit_transform(lrfmc_scaled) plt.figure(figsize=(10,6)) scatter = plt.scatter(lrfmc_2d[:,0], lrfmc_2d[:,1], c=clusters, cmap='viridis') plt.colorbar(scatter) plt.title('TSNE Visualization of Customer Clusters') plt.show()4. 客户价值分析与业务应用
4.1 聚类中心解析
通过反标准化查看各类别特征:
# 将聚类中心反标准化 cluster_centers = scaler.inverse_transform(kmeans.cluster_centers_) lrfmc_centers = pd.DataFrame(cluster_centers, columns=['L','R','F','M','C']) # 添加业务标签 lrfmc_centers['客户类型'] = ['高价值常旅客', '新晋贵宾客户', '普通经济舱客户', '低频次客户', '流失风险客户'] print(lrfmc_centers)典型分析结果示例:
| 客户类型 | L(月) | R(月) | F(次/月) | M(公里/次) | C(等级) |
|---|---|---|---|---|---|
| 高价值常旅客 | 48.2 | 0.8 | 2.1 | 3200 | 3.5 |
| 新晋贵宾客户 | 6.5 | 1.2 | 1.8 | 2800 | 3.2 |
| 普通经济舱客户 | 24.7 | 3.4 | 0.7 | 1500 | 1.8 |
| 低频次客户 | 18.3 | 8.6 | 0.3 | 1200 | 1.5 |
| 流失风险客户 | 36.4 | 15.2 | 0.1 | 800 | 1.2 |
4.2 业务策略建议
基于某航空公司的实战经验,针对不同群体可制定策略:
高价值常旅客(占比约7%)
- 提供免费升舱机会
- 专属客服通道
- 提前值机/选座特权
新晋贵宾客户(占比约12%)
- 定向发送贵宾休息室体验券
- 推荐联程机票优惠
- 里程加速计划
流失风险客户(占比约25%)
- 触发预警机制
- 发送个性化召回优惠(如"我们想念您"活动)
- 调查流失原因
关键发现:在某项目中,我们发现R值(最近乘机时间)是预测流失的最敏感指标。当R > 6个月时,客户二次激活成本飙升300%。
5. 工程化与性能优化
5.1 大数据量处理技巧
当数据量超过100万条时,需要特殊处理:
# 使用MiniBatchKMeans from sklearn.cluster import MiniBatchKMeans mbk = MiniBatchKMeans(n_clusters=5, batch_size=1000, random_state=42) mbk.fit(lrfmc_scaled) # 使用PCA预降维 from sklearn.decomposition import PCA pca = PCA(n_components=0.95) # 保留95%方差 lrfmc_pca = pca.fit_transform(lrfmc_scaled)5.2 模型更新策略
客户价值动态变化,推荐更新频率:
- 高价值客户群:每月更新
- 普通客户群:季度更新
- 全量数据:半年更新
建立自动化流水线示例:
import airflow from airflow.operators.python_operator import PythonOperator def update_clusters(): # 实现数据获取->清洗->聚类->报告全流程 pass dag = airflow.DAG('customer_segmentation', schedule_interval='@monthly') task = PythonOperator(task_id='cluster_update', python_callable=update_clusters, dag=dag)6. 常见问题与解决方案
6.1 聚类结果不稳定
现象:每次运行得到不同的分类结果解决方案:
- 设置固定random_state
- 增加n_init参数(默认10次初始化)
- 数据标准化前去除极端异常值
kmeans = KMeans(n_clusters=5, random_state=42, n_init=20)6.2 业务部门不理解结果
现象:聚类结果无法直接对应已知客户类型解决方案:
- 制作雷达图直观展示各类别特征
- 为每个类别提取典型客户案例
- 组织跨部门工作坊共同解读
# 绘制雷达图示例 angles = np.linspace(0, 2*np.pi, 5, endpoint=False) stats = cluster_centers.mean(axis=0) stats = np.concatenate((stats,[stats[0]])) angles = np.concatenate((angles,[angles[0]])) fig = plt.figure(figsize=(8,8)) ax = fig.add_subplot(111, polar=True) ax.plot(angles, stats, 'o-', linewidth=2) ax.fill(angles, stats, alpha=0.25) ax.set_thetagrids(angles * 180/np.pi, ['L','R','F','M','C'])6.3 模型效果随时间下降
现象:半年后聚类质量指标下降20%+解决方案:
- 建立监控看板跟踪轮廓系数等指标
- 引入增量学习机制
- 定期评估是否需要调整聚类数
# 监控指标计算 monitor_metrics = { 'silhouette': silhouette_score(current_data, current_labels), 'inertia': kmeans.inertia_, 'cluster_size_var': np.var(np.bincount(current_labels)) }在真实航空项目中,我建议先用6-12个月的历史数据建立基线模型,之后每次更新时保留10%的旧数据作为对照样本,确保模型变化不会导致客户分类标准剧烈波动。