21.8. 特征丰富的推荐系统¶ 在 SageMaker Studio Lab 中打开 Notebook
交互数据是反映用户偏好和兴趣的最基本指标,在之前介绍的模型中起着至关重要的作用。然而,交互数据通常极其稀疏,有时还可能包含噪声。为了解决这个问题,我们可以将辅助信息(如物品的特征、用户的个人资料,甚至交互发生的上下文)整合到推荐模型中。利用这些特征有助于进行推荐,因为这些特征可以有效预测用户的兴趣,尤其是在缺乏交互数据的情况下。因此,推荐模型必须具备处理这些特征的能力,并赋予模型一定的内容/上下文感知能力。为了展示这类推荐模型,我们引入了另一个关于在线广告推荐的点击率(CTR)预测任务 (McMahan et al., 2013),并提供一个匿名的广告数据集。定向广告服务已引起广泛关注,并通常被视为推荐引擎。推荐符合用户个人品味和兴趣的广告对于提高点击率至关重要。
数字营销人员利用在线广告向客户展示广告。点击率是衡量广告商的广告获得的点击次数与展示次数之比的指标,它以百分比表示,计算公式为
点击率是衡量预测算法有效性的重要信号。点击率预测任务是预测网站上某个内容被点击的可能性。点击率预测模型不仅可以用于定向广告系统,还可以用于一般的物品(如电影、新闻、产品)推荐系统、电子邮件营销,甚至搜索引擎。它还与用户满意度、转化率密切相关,并且有助于设定营销活动目标,因为它可以帮助广告商设定切合实际的期望。
import os
from collections import defaultdict
from mxnet import gluon, np
from d2l import mxnet as d2l
21.8.1. 在线广告数据集¶
随着互联网和移动技术的巨大进步,在线广告已成为重要的收入来源,并为互联网行业创造了绝大部分的收入。展示相关的广告或能激发用户兴趣的广告非常重要,这样可以将普通访客转化为付费客户。我们介绍的数据集是一个在线广告数据集。它包含34个字段,第一列是目标变量,表示广告是否被点击(1表示点击,0表示未点击)。所有其他列都是类别特征。这些列可能代表广告ID、网站或应用ID、设备ID、时间、用户画像等。由于匿名化和隐私问题,这些特征的真实含义并未公开。
以下代码从我们的服务器下载数据集并将其保存到本地数据文件夹中。
#@save
d2l.DATA_HUB['ctr'] = (d2l.DATA_URL + 'ctr.zip',
'e18327c48c8e8e5c23da714dd614e390d369843f')
data_dir = d2l.download_extract('ctr')
Downloading ../data/ctr.zip from http://d2l-data.s3-accelerate.amazonaws.com/ctr.zip...
数据集包含一个训练集和一个测试集,分别由15000和3000个样本/行组成。
21.8.2. 数据集包装器¶
为了方便数据加载,我们实现了一个CTRDataset
类,它从CSV文件中加载广告数据集,并可供DataLoader
使用。
#@save
class CTRDataset(gluon.data.Dataset):
def __init__(self, data_path, feat_mapper=None, defaults=None,
min_threshold=4, num_feat=34):
self.NUM_FEATS, self.count, self.data = num_feat, 0, {}
feat_cnts = defaultdict(lambda: defaultdict(int))
self.feat_mapper, self.defaults = feat_mapper, defaults
self.field_dims = np.zeros(self.NUM_FEATS, dtype=np.int64)
with open(data_path) as f:
for line in f:
instance = {}
values = line.rstrip('\n').split('\t')
if len(values) != self.NUM_FEATS + 1:
continue
label = np.float32([0, 0])
label[int(values[0])] = 1
instance['y'] = [np.float32(values[0])]
for i in range(1, self.NUM_FEATS + 1):
feat_cnts[i][values[i]] += 1
instance.setdefault('x', []).append(values[i])
self.data[self.count] = instance
self.count = self.count + 1
if self.feat_mapper is None and self.defaults is None:
feat_mapper = {i: {feat for feat, c in cnt.items() if c >=
min_threshold} for i, cnt in feat_cnts.items()}
self.feat_mapper = {i: {feat_v: idx for idx, feat_v in enumerate(feat_values)}
for i, feat_values in feat_mapper.items()}
self.defaults = {i: len(feat_values) for i, feat_values in feat_mapper.items()}
for i, fm in self.feat_mapper.items():
self.field_dims[i - 1] = len(fm) + 1
self.offsets = np.array((0, *np.cumsum(self.field_dims).asnumpy()
[:-1]))
def __len__(self):
return self.count
def __getitem__(self, idx):
feat = np.array([self.feat_mapper[i + 1].get(v, self.defaults[i + 1])
for i, v in enumerate(self.data[idx]['x'])])
return feat + self.offsets, self.data[idx]['y']
以下示例加载训练数据并打印出第一条记录。
train_data = CTRDataset(os.path.join(data_dir, 'train.csv'))
train_data[0]
[21:49:38] ../src/storage/storage.cc:196: Using Pooled (Naive) StorageManager for CPU
(array([ 143., 144., 227., 232., 957., 1250., 1471., 1566., 1624.,
1662., 2008., 2061., 2229., 2304., 2305., 2360., 2745., 2746.,
2747., 2748., 2892., 2988., 3165., 3167., 3194., 3195., 3258.,
3683., 3687., 3689., 3732., 3761., 3765., 3803.]),
[1.0])
可以看到,所有34个字段都是类别特征。每个值代表相应条目的独热编码索引。标签 \(0\) 表示未被点击。这个CTRDataset
也可以用于加载其他数据集,例如Criteo展示广告挑战赛数据集和Avazu点击率预测数据集。
21.8.3. 小结¶
点击率是衡量广告系统和推荐系统有效性的重要指标。
点击率预测通常被转化为一个二分类问题。其目标是根据给定的特征预测一个广告/物品是否会被点击。