首页 / 资讯中心 / 文章详情

淘宝用户行为分析:从数据清洗到购买预测的完整机器学习实践

淘宝用户行为分析:从数据清洗到购买预测的完整机器学习实践 ★ FEATURED ARTICLE
简介面向Python机器学习课程设计与期末大作业场景这份源码与实验报告围绕淘宝用户行为数据展开完整分析流程适合需要快速完成高分项目的学生参考。资源共包含3个文件1个SQL数据文件用于还原原始数据集1个Python分析脚本承载数据预处理、特征工程与建模可视化逻辑1份PDF实验报告整理项目过程、关键代码与结论整体压缩包约1012KB轻量简单下载后稍加部署即可运行。代码附有清晰注释从数据导入、清洗到用户行为漏斗分析、转化率对比均有覆盖报告同步展示分析思路与可视化结果功能完善且界面友好新手也能轻松看懂。目前已有980人学习下载这一被验证的高分项目尤其适合课程设计、期末答辩也可作为电商行为数据分析的入门范本。1. 淘宝用户行为分析这个机器学习大作业到底要做什么选期末大作业题最怕两件事一是题目太简单答辩时没什么可讲二是题太大一两周搭不出主线。“淘宝用户行为分析”恰好是个折中选题它需要的数据量不大常见的是几十万到几百万行行为日志技术栈用 Python 的 pandas、sklearn 就能完整跑通又以“用户是否购买”这个二分类标签收敛到一个很明确的机器学习目标上。我做这个项目时最大的感受是它把机器学习从“调用库”变成了“理解业务”为什么要构造特征、怎么做用户分群、预测结果如何和转化漏斗相互印证这些在别的题目里很难一次覆盖全。所以如果你正为机器学习课程设计或期末大作业发愁手头拿到的是用户行为记录类的数据集那么这份源码加实验报告的搭配是值得直接下载并照着复现一轮的。它解决的痛点很具体给你一套「数据清洗 → 特征工程 → 模型训练 → 实验报告」的完整可跑链路而不是零散代码片段。2. 数据清洗与行为漏斗从原始日志到可用训练集2.1 先看懂数据集四类行为和两个容易踩的字段淘宝用户行为数据集虽然字段不算多但最容易出问题的地方恰恰在“行为类型”和“时间戳”这两列。常见的字段设计是用户 ID、商品 ID、商品类目 ID、行为类型、时间戳。行为类型通常有四种状态浏览pv、收藏fav、加购物车cart、购买buy。这里的一个关键认知是四级行为并不是严格的线性漏斗用户可能先加购再浏览也可能只购买从不收藏所以不能按“上一级发生了才能进入下一级”来筛选样本。我在写数据读取脚本时第一版就翻过车直接读进来后发现用户 ID 和商品 ID 是字符串行为列里有大小写不一致的情况。规范的读入做法是import pandas as pd df pd.read_csv( user_behavior.csv, sep,, names[user_id, item_id, cat_id, behavior, timestamp] ) # 原始数据通常没有列头names 必须按实际列顺序对应 df[user_id] df[user_id].astype(int) df[item_id] df[item_id].astype(int) df[timestamp] pd.to_datetime(df[timestamp], units) # Unix 秒级时间戳 # 行为映射成数字后续做序列分析更方便 behavior_map {pv: 1, fav: 2, cart: 3, buy: 4} df[behavior_num] df[behavior].map(behavior_map) print(df.dtypes) print(df.isnull().sum())这段代码里几个动作的含义要搞清楚。user_id 和 item_id 转成整型一是减少内存占用二是避免字符串比较带来的额外开销当数据量到几百万行时这个优化能明显缩短后续 groupby 的时间。timestamp 用units解析的前提是原始数据给的是 Unix 秒级时间戳如果源文件里给的是毫秒级或日期字符串解析方式完全不一样这一点后面避坑章节还会细说。behavior_num 的映射为的是按时间顺序还原用户路径排序时用数值型字段比字符串快得多。2.2 数据清洗四步去重、去异常、筛噪声、按用户排序第二步要把原始日志整理成“每个用户一条行为序列”。我一般固定走四步先按用户、商品、行为、时间戳完全去重再剔除行为数为空的记录然后剔除行为总量过多或过少的用户最后按用户和时间排序重进行为索引。# 1. 完全去重四个字段一起判断 df df.drop_duplicates(subset[user_id, item_id, timestamp, behavior]) # 2. 统计每个用户的行为总量剔除两端极值阈值按数据分布取 user_stats df.groupby(user_id).size() low, high user_stats.quantile(0.01), user_stats.quantile(0.99) valid_users user_stats[(user_stats low) (user_stats high)].index df df[df[user_id].isin(valid_users)] # 3. 按用户和时间排序重建索引 df df.sort_values([user_id, timestamp]).reset_index(dropTrue) # 4. 按用户聚合行为序列它是后续标签构造的基础 user_seq df.groupby(user_id)[behavior].apply(list).reset_index() print(user_seq.head())这段的要点在第一步去重时四个字段必须一起判断只按用户和商品去重会把同一用户对同一商品的多次浏览误删成一个行为漏斗比例会整体失真。第二步用 1% 和 99% 分位数做阈值而不是拍脑袋写“小于 100 条就删”因为不同数据集的分布差异很大。行为总数在 99 分位数以上的用户大概率是爬虫或脚本产生的噪声留着会让特征工程阶段出现一批“超人用户”严重拉偏特征分布。2.3 转化漏斗与基础指标先把业务数字算明白再定义模型标签整理完原始数据先别急着建模。我会先算一遍四级行为的转化漏斗既给实验报告的业务分析章节准备素材也用来验证数据处理没写错。常见做法是算整体漏斗和按小时漏斗两张表funnel {} for action in [pv, fav, cart, buy]: funnel[action] df[df[behavior] action][user_id].nunique() funnel_df pd.DataFrame([funnel]).T.rename(columns{0: uv}) funnel_df[ratio] funnel_df[uv] / funnel_df[uv].max() print(funnel_df) # 按小时统计浏览人数看时间维度的行为规律 df[hour] df[timestamp].dt.hour hour_uv df[df[behavior] pv].groupby(hour)[user_id].nunique()逻辑说明这里统计的是独立用户数不是行为次数因为漏斗关心的是“有多少人走到这一步”同一人反复点击只算一次。整体漏斗第一版跑出来通常是 100% → 20% 左右 → 8%10% → 2%3%。如果出现收藏人数比加购还多先别急着分析业务很可能是数据处理阶段把映射关系写错了。按小时统计能清楚看到深夜低谷和晚上八点到十点的高峰这个规律在后面构造时间特征时能直接用上。这些数字写进实验报告的“业务背景”部分是答辩现场证明你真的跑过数据的最好证据。3. 特征工程与模型评估预测购买行为的完整管线3.1 特征体系怎么搭行为宽度、行为深度、行为节奏建模目标是预测用户在未来一段时间内会不会购买所以训练集不是用全部数据而是“用时间点 T 之前的行为预测 T 之后是否有购买”。特征我习惯分三类宽度特征即用户在多少个商品上有过交互反映探索范围深度特征即浏览、收藏、加购、购买各自发生的次数反映行为强度节奏特征即两次行为的时间间隔、深夜行为占比反映行为习惯。宽度和深度特征先构造user_feat pd.DataFrame(indexdf[user_id].unique()) user_feat[item_cnt] df.groupby(user_id)[item_id].nunique() user_feat[cat_cnt] df.groupby(user_id)[cat_id].nunique() user_feat[pv_cnt] df[df[behavior] pv].groupby(user_id).size() user_feat[fav_cnt] df[df[behavior] fav].groupby(user_id).size() user_feat[cart_cnt] df[df[behavior] cart].groupby(user_id).size() user_feat[buy_cnt] df[df[behavior] buy].groupby(user_id).size()参数说明item_cnt 是用户接触过的商品去重数反映广度cat_cnt 是用户覆盖的类目数反映兴趣面宽不宽pv_cnt 到 buy_cnt 分别是四类行为的总次数这里不去重保留行为频率信息。这个特征组合在逻辑回归上的表现往往已经能接近一个中等效果的 XGBoost 模型因为购物车和收藏行为本身高度指示购买意愿。节奏特征单独构造df df.sort_values([user_id, timestamp]) df[prev_time] df.groupby(user_id)[timestamp].shift() df[gap_seconds] (df[timestamp] - df[prev_time]).dt.total_seconds() # 每个用户的平均行为间隔小时 gap_mean df.groupby(user_id)[gap_seconds].mean() / 3600 user_feat[avg_gap_hours] gap_mean # 深夜行为占比23点到次日6点算深夜 df[hour] df[timestamp].dt.hour df[is_night] ((df[hour] 23) | (df[hour] 6)).astype(int) night_ratio df.groupby(user_id)[is_night].mean() user_feat[night_ratio] night_ratioshift()是往上取前一行按 user_id 分组后做 shift刚好得到同一用户上一次行为的时间。行为间隔均值反映用户的活跃密度间隔短的用户可能是在短时间内集中比价这类用户购买转化率往往更高深夜行为占比反映用户是否在非主流时段逛淘宝这个特征在部分数据集上对购买预测有正向贡献。需要留意的是gap_seconds会为每个用户的第一条记录生成 NaN计算均值时会自动跳过这是预期行为。3.2 标签构建与训练集划分按时间切而不是随机切这是整个项目里最重要的一步。很多新手在这里翻车对全量数据直接随机划分训练集和测试集结果训练集里混入了未来的行为信息。正确的做法是选一个时间点 t0t0 之前作为特征窗口t0 之后作为标签窗口。t0 pd.Timestamp(2017-12-03) feature_start pd.Timestamp(2017-11-25) label_end t0 pd.Timedelta(days7) # 特征窗口t0 之前的 7 天 df_feature df[(df[timestamp] feature_start) (df[timestamp] t0)] # 标签窗口t0 之后 7 天内是否有购买行为 df_label df[(df[timestamp] t0) (df[timestamp] label_end)] buy_users set(df_label[df_label[behavior] buy][user_id].unique()) # 在特征改造的基础上打标签 X user_feat.loc[df_feature[user_id].unique()].copy() X[label] X.index.isin(buy_users).astype(int) print(X[label].value_counts())这里为什么是 7 天加 7 天特征窗口 7 天能保留足够的交互频次标签窗口 7 天则保证“购买事件”有足够的时间发生窗口太短会导致正样本过少太长会让“预测”失去实时性。用户如果同时出现在特征窗口和标签窗口里这是正常的因为我们用的是他在 t0 之前的行为去预测未来。真正的问题是特征窗口内的行为被放到了训练集然后又把它在标签窗口内的购买行为也放进了训练集这就是泄漏。我每次写完这段都会检查一下测试集用户和训练集用户是否有时间窗口重叠。3.3 模型选择逻辑回归打底XGBoost 提升对课程作业来说我的建议是跑双模型对比逻辑回归作为基线XGBoost 作为提升模型。逻辑回归最容易被答辩导师认可因为能说清楚每个特征对购买概率的影响方向和大小。XGBoost 的优势是精度更高能自动捕捉特征间的非线性关系但解释性弱一些。from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report, roc_auc_score import xgboost as xgb y X[label] X_feat X.drop(columns[label]) # 此时已经是时间切分train_test_split 只做随机打乱不跨时间 X_train, X_test, y_train, y_test train_test_split( X_feat, y, test_size0.3, stratifyy, random_state42 ) # 逻辑回归基线 lr LogisticRegression(class_weightbalanced, max_iter200, random_state42) lr.fit(X_train, y_train) y_pred_lr lr.predict(X_test) print(LR AUC:, roc_auc_score(y_test, lr.predict_proba(X_test)[:, 1])) print(classification_report(y_test, y_pred_lr)) # XGBoost 对比 xgb_model xgb.XGBClassifier( n_estimators200, max_depth4, learning_rate0.1, scale_pos_weighty_train.value_counts()[0] / y_train.value_counts()[1], random_state42 ) xgb_model.fit(X_train, y_train) y_pred_xgb xgb_model.predict(X_test) print(XGB AUC:, roc_auc_score(y_test, xgb_model.predict_proba(X_test)[:, 1])) print(classification_report(y_test, y_pred_xgb))class_weightbalanced 在逻辑回归中自动给少数类加权应对购买行为占比过低的问题XGBoost 里的 scale_pos_weight 是同样的作用数值取负类与正类的数量比。max_depth 设 4 就够了这类表格型数据深度太大容易过拟合训练集 AUC 很高但测试集 AUC 反而下降。第一版跑通时不要急着调参我见过太多同学在网格搜索上调了半天最后发现是标签泄漏导致 AUC 虚高。4. 常见问题与排查五个让作业翻车的坑4.1 时间戳单位搞错图表全部错位现象画出来的小时分布图出现凌晨四点高峰、白天反而低谷的诡异曲线。原因原始时间戳是毫秒级代码里却用了 units 解析等于把时间放大了一千倍解析出来的是未来时间。解决读入后先做范围校验把解析后时间的最小值和最大值打出来对照数据集描述里的时间范围毫秒级就改用unitms。我在每次读数据后都会打印一行 min/max 时间戳成本极低但能拦住这类最隐蔽的错误。4.2 随机划分训练测试集造成特征泄漏现象模型 AUC 高达 0.98答辩时导师问“测试集时间范围是什么”答不上来。换到新一批数据上预测效果一塌糊涂。原因直接对整个数据集随机切分同一个用户的早期行为随进了测试集而他的后期行为出现在训练集里模型相当于“看过答案再考试”。解决固定一个时间点 t0特征窗口和标签窗口完全按时间切分训练集和测试集的用户可以有重合但时间窗口绝对不重合。4.3 类别极不平衡准确率虚高到 97%现象打印 classification_report 时准确率很高但 F1 分数只有 0.1。原因购买占比通常只有 1%~3%模型把全部样本预测为“不购买”就有 97% 的准确率准确率彻底失去参考意义。解决评估指标换用精确率、召回率、F1 和 AUC训练时对少数类加权逻辑回归用 class_weightbalancedXGBoost 用 scale_pos_weight或者对正类做简单过采样。4.4 漏斗比例错乱收藏人数比浏览还多现象业务漏斗表算出来收藏人数比浏览多明显不合逻辑。原因大多不是业务问题而是行为映射写错比如把 view 和 pv 当成两种行为处理或者去重时把浏览记录误删了一部分。解决先别分析模型回退到原始数据按行为类型做 groupby 统计次数和人数对照源文件里的枚举值逐一核验映射表单独写成常量不要散落在代码里。4.5 内存溢出或特征工程跑一小时没结果现象读几百万行数据直接内存溢出或者特征构造阶段长时间无响。原因数据没去重就做 groupby或者对字符串列反复做分组聚合内存和 CPU 都被浪费在无用计算上。解决最开始的阶段把 user_id、item_id 转成整数类型先用 1% 用户抽样把全流程跑通确认每个阶段的输出结构正确后再放大到全量数据。另一个实用技巧是尽早做完全去重行为日志里重复记录的比例经常超乎想象。5. 实验报告与答辩技巧把结果写成高分项目的细节报告结构按“业务理解、数据处理、特征工程、模型对比、结论启示”五段式走真正拉开分数差距的是细节。第一个技巧图和表要成对出现。整体转化漏斗旁边放一张按小时切分的漏斗图导师一眼就能看到你理解了时间维度对用户行为的影响这个细节比十段文字描述都有说服力。第二个技巧特征重要性图不要直接贴 XGBoost 默认的 feature importance 输出把特征名改成业务含义按贡献度从高到低排列下面配一段解释比如“cart_cnt 贡献度最高因为用户只有真正有意向才会把商品放进购物车”。第三个技巧结论部分不要写“准确率达到多少”而要写业务价值比如“按照模型预测的购买概率排序取前 1000 个用户做定向推送能覆盖真实购买用户中约 25% 的比例”这种写法在答辩现场明显比单纯报一个数字更有说服力。第四个技巧是参数表。在报告附录里放一张关键参数说明表列清楚参数名、取值、选择理由这是答辩时最不容易被问倒的地方。比如逻辑回归的 max_iter 为什么设 200、XGBoost 的 max_depth 为什么设 4每个都能说得出来就不会出现“默认参数”这类让导师皱眉的回答。第五个技巧时间切分的代码块要单独放一页并配上时间轴示意图让导师一眼看到数据没有泄漏。我自己做这类项目有个挺笨但很有效的习惯永远先跑完一轮全流程再动笔写报告报告里出现的每个数字都来自代码的输出绝不手填。这个习惯帮我躲过好几次“报告写得漂亮、代码跑不通”的尴尬局面。如果你拿到的是这份源码加实验报告的资源建议也按这个顺序走一遍先跑通数据清洗和漏斗再构造特征和模型最后对照报告里的结果表逐项核对自己的输出。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站