电商用户购买意向预测

2,399 阅读8分钟

背景:

京东作为中国最大的自营式电商,在保持高速发展的同时,沉淀了数亿的忠实用户,积累了海量的真实数据。如何从历史数据中找出规律,去预测用户未来的购买需求,让最合适的商品遇见最需要的人,是大数据应用在精准营销中的关键问题,也是所有电商平台在做智能化升级时所需要的核心技术。 以京东商城真实的用户、商品和行为数据(脱敏后)为基础,通过数据挖掘的技术和机器学习的算法,构建用户购买商品的预测模型,输出高潜用户和目标商品的匹配结果,为精准营销提供高质量的目标群体。

目标:使用京东多个品类下商品的历史销售数据,构建算法模型,预测用户在未来5天内,对某个目标品类下商品的购买意向。

数据集:

  • 这里涉及到的数据集是京东最新的数据集:
  • JData_User.csv 用户数据集 105,321个用户
  • JData_Comment.csv 商品评论 558,552条记录
  • JData_Product.csv 预测商品集合 24,187条记录
  • JData_Action_201602.csv 2月份行为交互记录 11,485,424条记录
  • JData_Action_201603.csv 3月份行为交互记录 25,916,378条记录
  • JData_Action_201604.csv 4月份行为交互记录 13,199,934条记录
  • 用户数据
user_id 用户ID 脱敏
age 年龄段 -1表示未知
sex 性别 0表示男,1表示女,2表示保密
user_lv_cd 用户等级 有顺序的级别枚举,越高级别数字越大
user_reg_tm 用户注册日期 粒度到天
  • 商品数据
sku_id 商品编号 脱敏
a1 属性1 枚举,-1表示未知
a2 属性2 枚举,-1表示未知
a3 属性3 枚举,-1表示未知
cate 品类ID 脱敏
brand 品牌ID 脱敏
  • 评论数据
dt 截止到时间 粒度到天
sku_id 商品编号 脱敏
comment_num 累计评论数分段 0表示无评论,1表示有1条评论, 2表示有2-10条评论,3表示有11-50条评论,4表示大于50条评论
has_bad_comment 是否有差评 0表示无,1表示有
bad_comment_rate 差评率 差评数占总评论数的比重
  • 行为数据
user_id 用户编号 脱敏
sku_id 商品编号 脱敏
time 行为时间
model_id 点击模块编号,如果是点击 脱敏
type 1.浏览(指浏览商品详情页);2.加入购物车;3.购物车删除;4.下单;5.关注;6.点击
cate 品牌ID 脱敏
brand 品牌ID 脱敏

数据挖掘流程:

  • 数据探索
    1. 数据预览,查看数据集的整体面貌
    2. 数据集中是否存在缺失值
    3. 数据集是否存在异常值(有值,但是非常规值范围)
    4. 数据集完整性、一致性验证
  • 数据清洗
    1. 数据集字段的理解与处理
    2. 过滤掉无行为交互的商品和用户
    3. 筛选出行为数据中cate==8的数据
    4. 将有价值数据信息做成新的数据源
  • 数据理解与分析
    1. 可视化发现分析
    2. 用户的购买意向与时间因素的关系
    3. 用户的购买意向与好评/差评的关系
  • 特征工程
    1. 特征过滤
    2. 特征组合
  • 模型建立
    1. 数据集切分?
    2. 使用机器学习算法进行预测
    3. 参数设置与调节

用户行为

用户评论

用户属性

产品信息

预览小结

  • users/用户:ID,年龄,性别,用户等级,用户注册日期
    • 用户的age存在未知的情况,标记为-1
    • 用户的sex存在保密情况,标记为2
  • products/商品:商品编号,属性1,属性2,属性3,品类ID,品牌ID
  • comments/评价:商品编号,累计评论数(分段),是否有差评,差评率
  • act/行为:用户编号,商品编号,行为时间,点击模块编号,类型(浏览,加入购物车,购物车删除,下单,关注,点击),品类ID,品牌ID

1.2 缺失值异常值探索

待处理问题

  • 用户行为数据
    • user_id 为float型,需转换成int或str
    • time 为object型,需转换成time
  • 用户数据
    • age数据为object,需要处理转换成int
    • sex数据为float,需要转换成int
    • user_reg_tm数据为object,需要转换成time
  • 评论数据
    • dt数据为object,需要转换成time

User的总数据有105321条,age的缺失条数为:3,缺失率为:0.0028%

User的总数据有105321条,sex的缺失条数为:3,缺失率为:0.0028%

User的总数据有105321条,user_reg_tm的缺失条数为:3,缺失率为:0.0028%

Action 2的总数据有11485424条,model_id的缺失条数为:4959617,缺失率为:43.1818%

Action 3的总数据有25916378条,model_id的缺失条数为:10553261,缺失率为:40.7204%

Action 4的总数据有13199934条,model_id的缺失条数为:5143018,缺失率为:38.9625%

缺失值小结

上面简单的输出了下存在空值的文件中具体哪些列存在空值,结果如下:

  • 行为数据

    • model_id
  • 用户数据

    • age
    • sex
    • user_reg_tm

1.3 各数据集中的未知值情况:

年龄特征的未知值有14415个, 所占比例是:13.69%

性别特征的未知值有54738个, 所占比例是:51.97%

Product中a1特征的未知值个数有:1701 percent: 7.03%

Product中a2特征的未知值个数有:4050 percent: 16.74%

Product中a3特征的未知值个数有:3815 percent: 15.77%

未知值小结

  • 空值部分对3条用户的sex,age填充为未知值,注册时间不作处理,此外行为数据部分model_id待定: 43.2%,40.7%,39.0%
  • 未知值部分,用户age存在部分未知值: 13.7%,sex存在大量保密情况(超过一半) 52.0%
  • 商品中各个属性存在部分未知的情况,a1<a3<a2,分别为: 7.0%, 15.8%, 16.7%

1.4 数据一致性检测

  • 检测用户行为数据和用户数据是否出自同一分布,即用户和用户行为数据集的描述主体是否一致
    • 如果用户数据中出现A, B, C用户,行为数据中的数据是A, B, D用户行为,需要视情况做出取舍
  • 检测数据是否来矛盾,比如用户注册时间,用户行为时间晚于数据集生成时间

一致性检测结论

  • 用户注册时间中存在超过数据截取时间的数据
  • 用户操作数据中不存在超越本月及以后各月的数据
  • 不对用户注册异常数据过滤

Part_2 数据清洗

  • 数据集字段的理解与处理
  • 筛选出行为数据中cate==8的数据(比赛要求)
  • 筛选出有购买行为的数据
  • 将有价值数据信息做成新的数据源

上一节中待处理问题

  • 用户行为数据
    • user_id 为float型,需转换成int
    • time 为object型,需转换成time
  • 用户数据
    • age数据为object,需要处理转换成int
    • sex数据为float,需要转换成int
    • user_reg_tm数据为object,需要转换成time
  • 评论数据
    • dt数据为object,需要转换成time

由于数据量比较大,处理的数据如果都装载到内存里会爆掉,处理好待用的特征后序列化到本地

特征工程

特征

用户基本特征:

  • 获取基本的用户特征,基于用户本身属性多为类别特征的特点,对age,sex,usr_lv_cd进行独热编码操作,对于用户注册时间暂时不处理

商品基本特征:

  • 根据商品文件获取基本的特征
  • 针对属性a1,a2,a3进行独热编码
  • 商品类别和品牌直接作为特征

评论特征:

  • 分时间段,
  • 对评论数进行独热编码

行为特征:

  • 分时间段
  • 对行为类别进行独热编码
  • 分别按照用户-类别行为分组和用户-类别-商品行为分组统计,然后计算
  • 用户对同类别下其他商品的行为计数
  • 不同时间累积的行为计数(3,5,7,10,15,21,30)

累积用户特征:

  • 分时间段
  • 用户不同行为的
  • 购买转化率
  • 均值

用户近期行为特征:

  • 在上面针对用户进行累积特征提取的基础上,分别提取用户近一个月、近三天的特征,然后提取一个月内用户除去最近三天的行为占据一个月的行为的比重

用户对同类别下各种商品的行为:

  • 用户对各个类别的各项行为操作统计
  • 用户对各个类别操作行为统计占对所有类别操作行为统计的比重

累积商品特征:

  • 分时间段
  • 针对商品的不同行为的
  • 购买转化率
  • 均值

类别特征

  • 分时间段下各个商品类别的
  • 购买转化率
  • 均值
parameters = {
              'max_depth': [5, 10, 15, 20, 25],
              'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],
              'min_child_weight': [0, 2, 5, 10, 20],
              'colsample_bytree': [0.5, 0.6, 0.7, 0.8, 0.9],
              'scale_pos_weight': [0.2, 0.4, 0.6, 0.8, 1,10]
}
gsearch = GridSearchCV(xgb_model, param_grid=parameters, scoring='roc_auc', cv=3, verbose=10)
gsearch.fit(x_train, y_train.values.ravel())

print("Best score: %0.3f" % gsearch.best_score_)
print("Best parameters set:")
best_parameters = gsearch.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
    print("\t%s: %r" % (param_name, best_parameters[param_name]))

cv_result = pd.DataFrame.from_dict(gsearch.cv_results_)

xgb_auc=roc_auc_score(y_test,test_probs)
print(xgb_auc)
xgb_score=accuracy_score(y_test,test_probs)
print(xgb_score)