简介:一份以南京市为例,应用机器学习技术分析旅游方式偏好的学术论文,适合旅游管理、数据挖掘方向的研究者与高校学生用作参考文献或专业指导。该研究将旅游方式界定为团队旅游与自助旅游两类,基于人口统计特征与个人价值观设计问卷,并采用C4.5 Rule Induction Algorithm进行两次学习建模:先用神经网络集成生成虚拟样本,再扩充数据集并归纳出可读的决策规则,从而建立从游客特征到旅游方式偏好的非线性映射。文档为PDF格式,单文件约474KB,便于检索与收藏。目前已有125人学习,研究结论显示南京市居民偏好集中于团队旅游与自助旅游,所得到的决策规则和算法流程对后续同类偏好预测、旅游产品设计及机器学习方法应用均有参考价值。
1. 把南京市旅游偏好做成机器学习项目:先想清楚预测目标
当拿到"基于机器学习技术的旅游方式偏好研究——以南京市为例"这个题目时,大多数人第一反应是找数据集、跑算法。但在我做过的几个偏好类项目里,翻车往往不是模型不行,而是预测目标没定义清楚。这个题目的本质是:用机器学习模型,从南京游客的问卷、订单、轨迹或点评数据中,学习出"什么人在什么场景下更偏好哪种旅游方式"。它解决的是文旅场景里最实在的几个决策问题——给游客做行程推荐、给景区做客群定位、给营销活动做人群圈选。适合做这件事的人有两类:一类是手里握着南京文旅数据、想把统计分析报告升级成可预测模型的从业者,另一类是拿它做机器学习课程设计选题或毕业论文、需要一套能完整落地技术流程的学生。无论哪类人,第一步都不是选算法,而是把"偏好"翻译成可训练的标签。
2. 数据与特征工程:三条数据路线和一组能直接复用的清洗代码
旅游偏好研究和常见的点击率预测有个关键区别:标签不是现成的。点击率有明确的正负样本,而旅游方式偏好通常要自己整理。以南京市为例,能走的数据路线主要有三条,我一般会根据手里已有的数据源选一条或两条组合。
| 数据路线 | 典型来源 | 能提取的偏好信号 | 主要成本 |
|---|---|---|---|
| 问卷路线 | 景区游客问卷、线上调研 | 主观偏好、出行目的、同行人结构 | 样本量小,需要清洗量表 |
| 行为路线 | OTA订单、票务系统、酒店预订 | 实际消费内容、频次、客单价 | 特征稀疏,冷启动难 |
| 位置路线 | POI数据、轨迹数据 | 游览顺序、停留时长、活动半径 | 涉及地理编码,噪声大 |
实践里最稳妥的组合是"问卷定标签、行为补特征":问卷给你真实的主观偏好,行为数据给你客观的消费证据。这两者结合,模型的预测结果才不至于停留在自说自话。下面我会用一份模拟的南京问卷数据结构来讲清洗流程,代码同样适用于你手里真实的数据。
2.1 问卷数据清洗:把"想去哪玩"变成可训练的多标签
问卷里最常见的题型是"您对以下哪些旅游方式感兴趣"这类多选题,选项包括文化历史、自然风光、都市休闲、亲子娱乐等。原始数据通常是逗号或分号分隔的字符串,不能直接进模型。第一步是把这些字符串拆开,转成标准的多标签格式。
import pandas as pd # 原始问卷:pref列存的是"文化历史;自然风光"这样的分隔字符串 df = pd.read_csv('nanjing_survey.csv') df['pref_list'] = df['pref'].apply( lambda x: x.split(';') if isinstance(x, str) else [] ) # 候选偏好集合,按南京常见玩法定义,别漏掉"其他" categories = [ '文化历史', '自然风光', '都市休闲', '亲子娱乐', '美食体验', '户外运动' ] # 生成多标签列:游客勾选了就在对应列上置1 for cat in categories: df[f'label_{cat}'] = df['pref_list'].apply( lambda x: 1 if cat in x else 0 ) # 如果做单标签分类,取第一个勾选项为主标签 df['main_label'] = df.apply( lambda x: next( (c for c in categories if c in x['pref_list']), '其他' ), axis=1 ) print(df[['user_id', 'pref', 'main_label'] + [f'label_{c}' for c in categories]].head())这段代码的逻辑分三层:先用apply把字符串拆成列表,再遍历候选集合生成独立的 0/1 列,最后按需求聚合出主标签。转换完成后,每一行问卷就变成了一个标准的监督学习样本。
参数上需要注意两点。第一,categories的顺序会影响主标签的取值,如果游客同时勾了"文化历史"和"自然风光",next会把排在前面的类目设为主标签。我的习惯是把这个顺序和实际业务优先级对齐,而不是随便排列。第二,对"其他"这类兜底类别要单独处理,不能让主标签里混入大量未定义值,否则后面训练分类器时类别会失衡。清洗完成后建议立刻检查每个label_*列的分布,正常情况应该是几类偏好各占 10% 到 30%,如果某一类占比超过一半,说明问卷设计本身就存在引导性。
2.2 特征工程:人口属性之外还要加入行程时间特征
标签有了,接下来是特征。很多初学者在这里只会用性别、年龄、收入这类人口属性,结果模型训练出来跟不同城市的通用模型没有区别。旅游偏好的核心变量其实在"行程场景"里——同样是南京,一个周末周边游的游客和一个专程飞来的游客,偏好模式截然不同。所以我在做这个项目时,会额外构造一组行程特征。
import numpy as np # 用已有的出发地和游玩天数构造行程距离与时长特征 df['travel_distance_km'] = df.apply( lambda r: haversine_distance(r['origin_city'], '南京') if r['origin_city'] else -1, axis=1 ) df['stay_days'] = df['departure_date'] - df['arrival_date'] df['stay_days'] = df['stay_days'].apply(lambda x: max(x.days, 1)) # 时间特征:周末和非周末的偏好差异很大 df['is_weekend'] = (df['arrival_date'].dt.weekday >= 5).astype(int) # 同行人特征:家庭出行和独行游客选的旅游方式完全不一样 df['has_children'] = df['companion_type'].apply( lambda x: 1 if '儿童' in str(x) else 0 ) # 核弹级特征:人均预算 df['budget_per_person'] = df['total_budget'] / df['group_size'].clip(lower=1) feature_cols = [ 'age', 'gender', 'income_level', 'travel_distance_km', 'stay_days', 'is_weekend', 'has_children', 'budget_per_person', 'visit_freq_per_year', 'source_channel' ]这些特征的构造逻辑是围绕"游客决策场景"展开的。travel_distance_km用出发地与南京的球面距离近似代替交通成本,虽然比真实路网距离粗糙,但相关性足够;stay_days直接反映行程深度,深度游和一日游对旅游方式的偏好差异非常显著;budget_per_person是客单价信号,能区分高端定制和大众观光。
需要提醒的是距离计算函数haversine_distance要自己实现,用经纬度坐标算球面距离,网上有现成的公式。数据里如果出发地字段是缺失的,我建议统一填 -1 而不是 0,因为 0 在距离特征里有真实含义,会让模型误解为同城游客。另外,日期字段一定要先pd.to_datetime统一格式,否则dt.weekday会直接报错。这些特征之间还藏着一组强交互,比如"长途+多日+高预算"几乎直接指向深度文化游,树模型能自动学交互,但如果你转到逻辑回归,就要手动构造交叉项。
2.3 按游客分组划分数据集,别把同一个人切进训练和测试
这个坑我踩过,而且是在项目中期才发现的。如果一份数据里有同一个游客的多条旅游记录,直接train_test_split随机划分,就会把同一个人一部分记录放进训练集、另一部分放进测试集。模型在测试集上表现极好,但一上线就崩,因为模型其实在"记忆"这个人本身的偏好,而不是学到泛化的规律。
from sklearn.model_selection import GroupShuffleSplit # 以user_id为分组单位切分数据 gss = GroupShuffleSplit(n_splits=1, test_size=0.2, random_state=42) train_idx, test_idx = next(gss.split(X, y, groups=df['user_id'])) X_train, X_test = X.iloc[train_idx], X.iloc[test_idx] y_train, y_test = y.iloc[train_idx], y.iloc[test_idx] # 验证分组正确:两个集合的user_id不能有交集 assert set(df['user_id'].iloc[train_idx]).isdisjoint(df['user_id'].iloc[test_idx])GroupShuffleSplit的作用是保证同一个user_id的所有样本只会出现在训练集或测试集的一侧。最后那个assert是保险丝,我每次划分完都会跑一遍。如果你的数据是纯问卷、每人只有一行,那就无所谓分组,但只要有重复游客,这条就是硬规矩。
分组划分还会连带影响交叉验证的方式。后面做调参时,不能用普通的KFold,要用GroupKFold,否则你在验证集上看到的精度依然是被污染的。这一点很多机器学习实战教程不会特意强调,但在游客偏好这种强个体差异的场景里,不按个体分组就是给模型作弊。
3. 模型选型与训练:从 LightGBM 跑通基线到 K-Means 做分群
数据准备妥当后,模型选型反而是我比较放心的环节。旅游偏好预测是典型的表格数据多分类任务,类别在 5 到 8 个之间,特征以分类变量和连续变量混合为主。这类问题的首选不是神经网络,而是梯度提升树——样本量几千到几万时,LightGBM 和 XGBoost 的稳健性明显好过深度学习。
3.1 样本量决定模型路线:表格数据优先试树模型
我见过很多把旅游偏好建模直接搬 BERT 或 Wide&Deep 的方案,结果数据只有几千行,神经网络还没收敛就过拟合了。表格数据的规律是:样本量低于 10 万时,树模型通常能以更少调参成本拿到更好的结果;只有当你拿到百万级订单数据时才值得考虑深度模型。所以在南京这个题目里,我的路线很清晰:先跑 LightGBM 做基线,再用聚类做无监督分群,两者互为补充。
LightGBM 在这个场景里有三个不可替代的优势。第一,原生支持类别特征,像source_channel这种渠道字段不需要做独热编码,直接传categorical_feature参数就行。第二,训练速度快,几千行数据几十秒出结果,迭代特征时不用干等。第三,特征重要性可以直接输出,方便向业务方解释哪些变量在驱动偏好判断。
3.2 用 LightGBM 跑通第一版偏好预测:参数与调优
第一版模型不建议一上来就调参,先把流程跑通最重要。我习惯用默认参数加少量调整,目标是尽快得到一个可评估的性能基准。
import lightgbm as lgb from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, f1_score # 特征与标签已经过上一章清洗,y是main_label编码后的整数 X = df[feature_cols] y = df['main_label'].astype('category').cat.codes X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42 ) model = lgb.LGBMClassifier( n_estimators=500, learning_rate=0.05, num_leaves=31, max_depth=6, min_child_samples=20, class_weight='balanced', random_state=42, verbose=-1 ) model.fit( X_train, y_train, eval_set=[(X_test, y_test)], eval_metric='multi_logloss' ) y_pred = model.predict(X_test) print('acc:', accuracy_score(y_test, y_pred)) print('macro-f1:', f1_score(y_test, y_pred, average='macro')) # 输出特征重要性,确认没有奇怪的字段排在最前 importance = pd.Series(model.feature_importances_, index=feature_cols) print(importance.sort_values(ascending=False))这里几个参数说清楚。n_estimators=500给足迭代次数,靠learning_rate=0.05控制步长防止过拟合,我一般先固定这两个再谈别的。num_leaves=31是 LightGBM 最敏感的参数,太大会学过头,太小欠拟合,31 对应默认配置的合理起点。class_weight='balanced'是因为旅游偏好类别天然不平衡,比如"美食体验"类可能只有"自然风光"类的三分之一,不加权重模型会往大类偏。
stratify=y是分类问题划分数据集时的重点参数,"按类别比例抽样"——确保训练集和测试集里各类别的占比和全量数据一致。诊断时我优先看macro-f1而不是accuracy,因为准确率在大类占比高时很有欺骗性:如果"自然风光"占 40%,模型全预测它也有 40% 的准确率,但宏平均 F1 能暴露出小类别全被忽略的问题。
第一版跑完后,调参顺序我会按num_leaves → min_child_samples → feature_fraction → learning_rate走。先用RandomizedSearchCV配合GroupKFold搜一组 200 步的参数,再人工微调。不要一上来就跑网格搜索,那个时间成本在你反复改特征时是巨大浪费。
3.3 用 K-Means 给南京游客分群:轮廓系数与聚类数选择
监督学习的偏好预测解决"给已知偏好的人预测方式"的问题,但业务方经常还会问"南京游客到底能分成几类"。这个问题适合用无监督聚类回答。我在实际项目中会用 K-Means 在标准化后的特征上做分群,然后把每一群的特征均值拿出来标注人群标签。
from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler from sklearn.metrics import silhouette_score cluster_features = [ 'age', 'budget_per_person', 'travel_distance_km', 'stay_days', 'visit_freq_per_year' ] X_cluster = df[cluster_features].fillna(-1) X_scaled = StandardScaler().fit_transform(X_cluster) # 对K=3到K=6做轮廓系数对比,同时记录各簇样本量 for k in range(3, 7): km = KMeans(n_clusters=k, n_init=10, random_state=42) labels = km.fit_predict(X_scaled) score = silhouette_score(X_scaled, labels) print(f'K={k}, silhouette={score:.3f}', 'cluster sizes:', np.bincount(labels))StandardScaler是必须的——budget_per_person量纲是几百到几千,stay_days是 1 到 10,不清洗就会让预算在距离计算里一票否决其他特征。n_init=10是新版 sklearn 推荐的默认值,它让 K-Means 从 10 个不同初始中心出发选最优结果,避免陷入局部最优。
轮廓系数是最常用的选 K 参考,但它是玄学,不是真理。我在南京项目里遇到的实际情况是 K=4 时轮廓系数只有 0.28,K=5 反而掉到 0.23,但结合业务看,K=5 的分群结果明显更有解释力——多出来的那一组是"亲子家庭游",特征上has_children=1占比极高。所以不要只盯着 silhouette 数值,要把聚类结果输出成一张各特征均值表,让业务方看到每一组的画像差异是否成立。
4. 旅游偏好建模避坑指南:五个最常见的翻车点
这部分写的是我真实踩过的坑和从其他项目里学来的教训。每一条都按现象、原因、解决三段来写,方便你对照排查自己的数据流程。
4.1 现象:模型 AUC 和 F1 都很高,实际推荐却不准
我在南京一个景区合作项目里,模型在测试集上 macro-F1 做到 0.78,业务方高高兴兴上线做推荐,结果用户实际到访率没有显著提升。排查后发现采样偏差在作祟——训练数据里 80% 的问卷是在钟山风景区门口发的,样本天然偏向喜欢自然风光和历史文化的游客。测试集也来自同一个采样池,AUC 当然好看,但它并不能代表南京市全域游客的偏好分布。
原因本质是样本选择偏差。景区门口发问卷,等于把"不来这个景区的人"全部排除在样本之外,模型学到的其实是"在钟山景区受访者中谁会选哪种方式"。解决方法是回到数据源头,用分层抽样重新构造训练集:按南京各区的游客到访比例、淡旺季分布分别配额采样,至少要保证各主要景区和商圈都有覆盖。条件允许时,把线上问卷的投放范围从景区扩大到酒店、高铁站和本地生活 App,让样本池更接近真实游客流。
4.2 现象:问卷里选"文化历史"的游客,实际消费全在美食店铺
这是自我报告偏好和真实行为偏好的系统性偏差。游客填问卷时会选择"更体面"或"更符合自我期待"的选项,但实际掏钱订票、排队吃饭时行为很诚实。终端表现为问卷标签和订单特征高度不匹配,模型训练时特征和标签互相矛盾,学出来的决策边界一塌糊涂。
解决思路有两个方向。第一是标签清洗:如果数据里同时有问卷和消费记录,用消费行为修正问卷标签,比如问卷选了"文化历史"但连续三条订单都是餐饮类,就把主标签改成"美食体验"。第二是特征加权:在训练集里把问卷来源的样本权重降低,把行为来源的样本权重提高。我个人的习惯是构建一个标签可信度分数,用行为一致率给每条样本打折,然后把这个分数作为sample_weight传入 LightGBM 的fit。
4.3 现象:时间泄漏让模型"看到未来",验证指标虚高
时间泄漏是这类项目里最隐蔽的问题。具体现象是模型对 2023 年的数据预测非常准,但上线后对当前游客完全不灵。我的排查经历指向一个字段——"是否重游"特征里包含了游客完成本次旅行之后的信息,或者干脆把训练集和验证集按时间混着切分,让模型提前看到了后几个月的热门趋势变化。
归类起来是两类错误:特征泄漏和切分泄漏。特征泄漏的解法是把所有特征的构造时间对齐到预测时间点之前,比如用游客历史上一次南京出行的偏好来预测本次,绝不能用本次结束后的评价数据。切分泄漏的解法是改用时间序列切分,用 2023 年 1 月到 8 月的数据训练,用 9 月到 12 月的数据验证,完全按时间顺序来。GroupShuffleSplit 解决的是个体交叉问题,时间切分解决的是趋势穿越问题,两个都要做。
4.4 现象:新景区没有历史数据,模型直接推荐失败
做南京市全域旅游推荐时遇到一个典型问题——新开发的文旅街区(比如刚落地的艺术园区)没有任何订单数据和用户标签,模型遇到这种"冷启动"样本时只能按平均水平预测,推荐结果跟随机差不多。原因是模型依赖历史行为特征,而冷启动样本的这些特征全部是缺失值或默认值。
解决思路是切换到内容特征的相似性匹配。先把新景区的 POI 数据变成特征集,包括景区类型、消费均价、亲子设施、位处哪个区、地铁可达性,然后用这些内容特征计算它和已有景区画像的余弦相似度,找到最相近的 3 个成熟景区,再用这些景区的历史偏好分布做加权平均。比如新街区在"艺术展览"这个维度上和老门东相似,就参考老门东的游客偏好向量来做首轮推荐。这会损失一点精度,但至少不是随机瞎猜。
4.5 现象:偏好类别不平衡,模型只会预测"周边游"
我第一次训练南京偏好模型时,发现"周边游"占比超过一半,导致模型把所有样本都猜成周边游,F1 依然有 0.5 左右。分类器为了最大化整体准确率,会主动牺牲小类别的正确率,这对业务是毁灭性的——运营方最想触达的恰恰是利润更高的深度游和定制游。
解决分三步。第一步在数据层面做类别重采样,对"文化历史""户外运动"这类小类别使用过采样,对"周边游"大类欠采样,让训练集的类别分布接近均匀。第二步在算法层面加class_weight='balanced',让损失函数对小类别的错判施加更高惩罚。第三步在评估层面必须用 macro-F1 或类别加权 F1 替代准确率。如果重采样后依然有小类学不动,要进一步检查是不是该类别下的样本特征本身就混乱,必要时合并类别,比如把"户外运动"和"自然风光"合并成"户外自然"。
5. 把模型结论解释给业务方:SHAP 值、南京市分区画像与重训节奏
模型训练完成不等于项目交付。旅游文旅项目的业务方往往不是算法工程师,他们不会因为 LightGBM 跑赢逻辑回归就认可你,他们要看到的是"为什么给中年人推荐文化深度游""为什么雨花台区的游客和建邺区的游客偏好差异这么大"。这一章讲怎么把模型结果翻译成业务语言。
5.1 SHAP 值定位关键变量:别再只给业务方看特征重要性
LightGBM 自带feature_importances_,但它只告诉你特征被分裂的频率,不告诉你特征对预测结果起正作用还是负作用。业务方问"预算到底怎么影响偏好的",频率图回答不了。这时候上 SHAP 值。
import shap # SHAP需要原始特征,且对多分类模型要指定class_index explainer = shap.TreeExplainer(model) # 注意:多分类时shap_values返回列表,每个元素对应一个类别 shap_values = explainer.shap_values(X_test) # 只看主标签对应的类别 class_names = df['main_label'].astype('category').cat.categories label_index = list(class_names).index('文化历史') shap.summary_plot( shap_values[label_index], X_test, feature_names=feature_cols, plot_type='bar' )这段代码里shap_values[label_index]是关键,多分类模型的 SHAP 值是一个列表,不指定索引就会报错或者画出不可读的图。summary_plot的bar模式给出全局重要性排序,如果要看每个特征对"文化历史"偏好的正负影响方向,把plot_type去掉,画默认的小提琴图,能看到travel_distance_km越大、越倾向于选择文化历史类旅游,这个结论直接可以写进业务报告。
我给文旅项目做交付时,通常会产出一张关键变量与偏好方向的对照表。比如"预算越高越倾向文化深度游""有儿童同行的游客显著偏向亲子娱乐""省外游客更偏好都市休闲内的夫子庙秦淮河一线"。这些结论从 SHAP 图里可以直接抓取,而且比回归系数更容易向领导解释。
5.2 南京市分区画像:把预测结果转成地图上看得懂的人群标签
业务方最爱看的东西是画像和地图。我在这个项目里会做一件事——把模型预测结果按南京市行政区聚合,输出一张"各区游客偏好结构表"。具体做法是:对每个区的游客样本,统计模型预测概率的平均值或用多数投票得到该区主流偏好,再叠加该区样本的特征均值做交叉解释。
| 区域 | 主流偏好 | 核心特征驱动 | 建议投放内容 |
|---|---|---|---|
| 玄武区 | 文化历史 | 长途、高预算 | 明孝陵深度讲解套餐 |
| 秦淮区 | 美食体验 | 年轻、短途 | 老门东夜宵路线 |
| 江宁区 | 亲子娱乐 | 有儿童、周末 | 牛首山亲子票 |
| 建邺区 | 都市休闲 | 商务出行、快节奏 | 河西 CBD 购物线路 |
这张表的产出流程是写一段分组聚合的 pandas 操作,但我建议不要只输出表面概率,一定要回看特征均值来印证,否则会出现"建邺区被预测成亲子娱乐但该区样本里根本没几个带儿童游客"这种矛盾画像。聚合后再接地理可视化,把主流偏好渲染成南京市分区地图,这是项目汇报时最容易打动业务方的交付物。
5.3 重训节奏:按月重训与按季度重训的取舍
偏好模型和搜索推荐模型不同,游客的偏好结构不会每个月剧烈变化,频繁重训只会引入无关噪声。我的默认节奏是按季度重训主模型,按月度只更新特征统计量。
理由有三层:第一,旅游偏好受季节和节假日影响明显——清明、五一、国庆三个高峰期之后,偏好分布会发生变化,季度重训能自然吸收这些变化;第二,问卷数据的收集周期本身需要时间,第一季度发出去的问卷,往往要到季度末才能收齐足够数量,数据时间窗决定了重训频率的物理上限;第三,频繁重训会带来评估成本翻倍,每次重训都要重新跑一组时间序列验证,这个人力消耗往往被低估。
月度更新的特征是那些短期变化快的变量,比如景区热度指数、地铁新线路开通带来的可达性变化。我会把这两类更新拆成两个流水线,特征流水线每月跑一次,模型流水线每季度跑一次,中间相差一个月的数据刚好用于验证上一版模型是否需要退役。
6. 模型上线前的最小验证方案:A/B 测试与回访问卷
最后一个落地步骤,也是最容易被技术团队跳过的一步——上线验证。很多项目做到模型评估就停了,把测试集表现当成最终结论交付给业务方,但测试集只是在历史数据上的回放,场景稍一变,结论可能完全失效。我在南京这类文旅项目里,模型上线前会做一个最小成本的真实验证组合,规模不大但能回答两个关键问题:模型推荐是否真的高于原有做法,用户对推荐内容的接受度到底如何。
最小方案分两支。第一支是线上 A/B 测试,在已有的门票或行程推荐入口,把流量按 7:3 分给旧规则和新模型,旧规则可以是"热门排序"或"按景区运营方人工推荐",新模型输出偏好预测结果。指标看两个就够了:推荐内容的点击率或购买转化率,以及人均停留时长变化。不要同时改多个变量,否则分不清提升来自模型还是新上线的内容素材。测试周期建议不要少于 14 天,覆盖至少一个完整周末,因为南京这类旅游城市的周中和周末游客结构差异太大,只看工作日结果会被严重误导。
第二支是回访问卷,A/B 测试能告诉你"新模型转化率更高",但不能告诉你"游客觉得推荐对不对"。我会在游客完成行程后触发一份三五题的小问卷,问三个与模型相关的核心问题:推荐内容是否符合预期、本次成行偏好是否与你原本计划一致、哪些因素导致你最终改变了选择。回访数据样本不需要大,300 到 500 份即可,但每一条都要关联到模型预测的记录,便于做"预测是否命中真实决策"的交叉分析。如果回访问卷里 60% 以上的人认为推荐"基本符合预期",同时 A/B 测试转化率有 3 个点以上的提升,这个模型就可以放心交给业务方长期使用。
最后说一个我自己吃过亏的教训:在跑这个项目时,我先急着优化模型精度,把 A/B 测试平台和回访问卷模板推迟了一个月才启动。结果模型调了四版,每一版在离线指标上都有提升,但上线后用户反馈数据跟不上,根本说不清哪一版真正有效。现在我惯用的收尾顺序是先搭好验证链路,再回头调模型——验证先行,调参就自然有方向。希望这个流程能帮你少走一段我走过的弯路。
本文还有配套的精品资源,点击获取