2023百度商业AI技术创新大赛-赛道1【非官方baseline】

本文围绕广告高价值转化行为预测赛题展开,介绍了背景、数据、评分标准及解题思路。赛题要求构建转化率预估模型,提供了含用户及广告信息的脱敏数据。解题思路包括数据处理为一维向量、搭建DeepFM网络,还给出相关代码,最终按auc和pcoc指标评判。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

2023百度商业ai技术创新大赛-赛道1【非官方baseline】 - 创想鸟

赛道一 广告高价值转化行为预测

(非官方baseline)

背景

随着互联网的发展,数字营销已成为企业获取潜在客户、用户获取目标商品和服务的主要渠道之一。 转化率预估技术可以在数字营销场景提高企业广告投放精准度、减少无效信息对用户的干扰,为用户带来更好的信息服务体验。 本任务提供了一个的 baseline模型,旨在帮助参赛者快速入手提高模型性能和效果。

PS : 本人也是第一次尝试完成推荐系统相关的数据处理以及demo实现,若有什么问题请评论区留言交流,或加微信沟通(同昵称)

本次比赛提供N天广告日志抽样数据(数据已脱敏):

训练集:前N-1天数据,供参赛者训练/调试模型测试集:第N天数据,非公开

赛题介绍

本次任务提供百度广告投放场景的海量真实数据,希望参赛者通过采用机器学习方式,构建转化率预估模型, 根据给定用户及广告信息,预估转化概率,即 pcvr = p(cv=1 | user, ad)。

数据说明

数据格式 每一行数据为一次广告点击,共计5个域,各域间 t 分隔:

字段 说明

log_id样本idt1转化类型1t2转化类型2t3转化类型3特征包含用户及广告信息

样本示例:(1)logid t 1 t - t - t 特征字段,属于第一个转化类型,是正样本(2)logid t - t 1 t - t 特征字段,属于第二个转化类型,是正样本(3)logid t - t - t 1 t 特征字段,属于第三个转化类型,是正样本(4)logid t 0 t - t - t 特征字段,属于第一个转化类型,是负样本(5)logid t - t 0 t - t 特征字段,属于第二个转化类型,是负样本(6)logid t - t - t 0 t 特征字段,属于第三个转化类型,是负样本

       

example:3601136181 - - 0 704:1 227:2 4630318:3 4630319:4 5:5 6:6 319:7 8:8 75:9 1715101:10 63328:10 412248:10 263656:10 4630320:10 150154:10 412250:10 63336:10 465:11 21:13 22:14 29442:15 24:16 630457:17 4630321:17 776254:17 4630322:17 325042:17 4630323:17 238029:17 325041:17 1690121:17 4630324:17 31148:18 3462866:18 174535:18 174536:18 675808 :18 675809:18 131969:18 36517:18 4259795:18 616316:18 2085787:19 30093:20 31406:20 31407:20 63351:20 46:21 4630325:22 4630326:22 4630327:22 4630328:22 4285695:22 4630329:22 4630330:22 4630331:22 4630332:22 4630333:22 2431996:22 4630334:22 1037304:22 4630335:22 1984706:22 4630336:22 2645081:22 816199:22 4630337:22 4630338:22 2085788:23 3161:24 3742:25 150:26 601:26 182:26 62:26 184:26 185:26 345:26 155:26 156:26 1258:26 158:26 70:26

       

特征类型

特征字段中包含26个不同的特征,各特征的信息类别如下:

字段号 说明

标号1~13用户基础信息标号14~16场景信息标号17~24广告信息标号25~26用户多值信息

注:本次比赛分为初赛和复赛,初赛的测试集随本项目进行发布,复赛数据集,将在复赛开始时间进行发布

所有样本已按时间先后排序,用户及广告信息已转为id进行脱敏。
使用组合特征及多目标建模有助于提高模型效果。
比赛最终根据所有转化类型样本整体auc排名。
       

评分标准

0.90 =< pcoc <= 1.10方可进入榜单排序。 主排序指标为auc,auc相同情况下按照 abs(pcoc – 1)升序。 指标说明:

auc(Area under curve):ROC曲线下的面积,越接近于1越好

pcoc(predict cv over cv) :预估转化率 / 真实转化率,越接近于1越好

解题思路

嫌弃啰嗦可以直接看第三步,一行完成项目训练!

数据处理: 数据解析(我这里就简单粗暴的将特征全部拼在一起,多特征的取均值处理)网络搭建: 采用深度网络分类deepfm(自己写的非官方,若有问题欢迎评论探讨)训练验证

1 数据处理

In [ ]

# 45-50 s 只需运行一次!unzip /home/aistudio/data/data213105/train_test.zip -d ./

   

将每条数据处理为简单粗暴的一维向量

具体逻辑详见:

queuedataset_reader.py
dataset.py

In [ ]

# queuedataset_reader.pyimport paddle.distributed.fleet as fleetclass Reader(fleet.MultiSlotDataGenerator):    def __init__(self):        padding = 0        # 无稠密特征        sparse_slots = "log_key click 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26"        self.sparse_slots = sparse_slots.strip().split(" ")        self.slots = self.sparse_slots        self.slot2index = {}        self.visit = {}        for i in range(len(self.slots)):            self.slot2index[self.slots[i]] = i            self.visit[self.slots[i]] = False        self.padding = padding    def line_process(self, line):        items = line.strip("n").split("t")        log_key = int(items[0])        conv1 = items[1]        conv2 = items[2]        conv3 = items[3]        conv = 0         if conv1 == "1" or conv2 == "1" or conv3 == "1":            conv = 1        else:            conv = 0        output = [(i, []) for i in self.slots]        feasigns = items[4].split(" ")        for i in feasigns:            slot_feasign = i.split(":")            slot = slot_feasign[1]            if slot not in self.slots:                continue            if slot in self.sparse_slots:                feasign = int(slot_feasign[0])            else:                feasign = float(slot_feasign[0])            output[self.slot2index[slot]][1].append(feasign)            self.visit[slot] = True        output[0][1].append(log_key)        self.visit['log_key'] = True        output[1][1].append(conv)        self.visit['click'] = True        for i in self.visit:            slot = i            if not self.visit[slot]:                output[self.slot2index[i]][1].extend([self.padding])            else:                self.visit[slot] = False                        new_output = []        for i in range(len(output)):            if len(output[i][1]) > 1:                new_output.append(int(sum(output[i][1])/len(output[i][1])))            else:                new_output.append(output[i][1][0])                        return new_output            def generate_sample(self, line):        r"Dataset Generator"        def reader():            output_dict = self.line_process(line)            yield output_dict        return reader    if __name__ == '__main__':    reader = Reader()    with open('train_data_small/file_01.txt') as f:        for line in f:            print(reader.line_process(line))            break

   In [ ]

# dataset.pyimport collectionsimport paddleimport queuedataset_reader as readerimport randomfrom tqdm import tqdmclass MyDataset(paddle.io.Dataset):    def __init__(self, file_paths, train_ratio=0.8):        super(MyDataset, self).__init__()        self.file_paths = file_paths                self.reader = reader.Reader()        self.total_samples = 0        self.train_data = []        self.val_data = []        self.train_ratio = train_ratio        self._load_data()    def _load_data(self):        for file_path in tqdm(self.file_paths, desc='load file and data',ncols=100):            samples = self._load_file(file_path)            self.total_samples += len(samples)            self.train_data.extend(samples)        self._split_dataset()    def _load_file(self, file_path):        samples = []        with open(file_path) as f:            for line in f:                sample = self.reader.line_process(line)                feature = sample[2:]                label = sample[1]                samples.append((feature, label))        return samples            def _split_dataset(self):        num_train = int(self.total_samples * self.train_ratio)        random.shuffle(self.train_data)                # 均分数据集类别,防止训练集和验证集中类别不均衡        class_samples = collections.defaultdict(list)        for feature, label in self.train_data:            class_samples[label].append((feature, label))        num_classes = len(class_samples)        num_samples_per_class = num_train // num_classes        train_samples = []        val_samples = []        for class_label, samples in class_samples.items():            num_samples = len(samples)            num_train_samples = min(num_samples_per_class, num_samples)            num_val_samples = num_samples - num_train_samples            train_samples.extend(random.sample(samples, num_train_samples))            val_samples.extend(samples[num_train_samples:])        random.shuffle(train_samples)        random.shuffle(val_samples)        self.train_data, self.val_data = train_samples, val_samples[:num_train - len(train_samples)]    def __getitem__(self, idx):        if idx < len(self.train_data):            sample = self.train_data[idx]        else:            sample = self.val_data[idx - len(self.train_data)]        return sample[0], sample[1]    def __len__(self):        return self.total_samplesif __name__ == '__main__':        file_paths = ['train_data/file_01.txt', 'train_data/file_02.txt']    dataset = MyDataset(file_paths, train_ratio=0.8)    print(len(dataset.train_data))    print(len(dataset.val_data))    train_loader = paddle.io.DataLoader(dataset.train_data, batch_size=32, shuffle=True, num_workers=0)    val_loader = paddle.io.DataLoader(dataset.val_data, batch_size=32, shuffle=False, num_workers=0)    for epoch in range(1):        for batch_id, data in enumerate(train_loader()):            x = data[0]            y = data[1]            #  32 转换为 32*1 然后拼接为 32*26            for i in range(len(x)):                x[i] = paddle.unsqueeze(x[i], axis=1)            x = paddle.concat(x, axis=1)                        print(x.shape)            # 将 32 转换为 32*1            y = paddle.unsqueeze(y, axis=1)            print(y.shape)                        print(x)            print(y)                        break

   

2 模型搭建

我这里只是一个可以跑通的demo展示,所以对模型不再深入研究,跑通即可。

当然,这里不做效果的评价,只是作为一个baseline的编写,带领大家能够迅速的拉通整个项目。

模型的优化还是交给大家!毕竟那么多奖金呢!

模型详见文件:

deepfm.py

In [ ]

# deepfm.pyimport mathimport paddleimport paddle.nn as nnclass FM(nn.Layer):    def __init__(self, sparse_feature_number, sparse_feature_dim):        super(FM, self).__init__()        self.sparse_feature_number = sparse_feature_number        self.sparse_feature_dim = sparse_feature_dim        self.init_value_ = 0.1        self.embedding = paddle.nn.Embedding(            self.sparse_feature_number,            self.sparse_feature_dim,            sparse=True,            weight_attr=paddle.ParamAttr(                name="SparseFmFeatFactors",                initializer=paddle.nn.initializer.TruncatedNormal(                    mean=0.0,                    std=self.init_value_ /                    math.sqrt(float(self.sparse_feature_dim)))))                self.bias = paddle.create_parameter(            shape=[1],            dtype='float32',            default_initializer=paddle.nn.initializer.TruncatedNormal(                mean=0.0,                std=self.init_value_ /                math.sqrt(float(self.sparse_feature_dim))))    def forward(self, sparse_inputs):        emb = self.embedding(sparse_inputs.astype('int64'))        square_of_sum = paddle.square(paddle.sum(emb, axis=1))        sum_of_square = paddle.sum(paddle.square(emb), axis=1)        fm = 0.5 * paddle.sum(square_of_sum - sum_of_square, axis=1, keepdim=True)        fm = fm + self.bias        return fmclass DNN(nn.Layer):    def __init__(self, num_field, layer_sizes, sparse_feature_number, sparse_feature_dim):        super(DNN, self).__init__()        self.num_field = num_field        self.layer_sizes = layer_sizes        self.sparse_feature_dim = sparse_feature_dim        self.sparse_feature_number = sparse_feature_number        self.init_value_ = 0.1                self.embedding = paddle.nn.Embedding(            self.sparse_feature_number,            self.sparse_feature_dim,            sparse=True,            weight_attr=paddle.ParamAttr(                name="SparseDnnFeatFactors",                initializer=paddle.nn.initializer.TruncatedNormal(                    mean=0.0,                    std=self.init_value_ /                    math.sqrt(float(self.sparse_feature_dim)))))        sizes = [self.num_field * self.sparse_feature_dim] + self.layer_sizes        acts = ["relu" for _ in range(len(self.layer_sizes))] + [None]        self._mlp_layers = []        for i in range(len(layer_sizes)):            linear = paddle.nn.Linear(                in_features=sizes[i],                out_features=sizes[i + 1],                weight_attr=paddle.ParamAttr(                    initializer=paddle.nn.initializer.Normal(                        std=1.0 / math.sqrt(sizes[i]))))            self.add_sublayer('linear_%d' % i, linear)            self._mlp_layers.append(linear)            if acts[i] == 'relu':                act = paddle.nn.ReLU()                self.add_sublayer('act_%d' % i, act)                self._mlp_layers.append(act)    def forward(self, sparse_inputs):        emb = self.embedding(sparse_inputs.astype('int64'))        y_dnn = paddle.reshape(emb, shape=[-1, self.num_field * self.sparse_feature_dim])        for n_layer in self._mlp_layers:            y_dnn = n_layer(y_dnn)        return y_dnnclass DeepFM(nn.Layer):    def __init__(self, num_field, layer_sizes, sparse_feature_number=88000000, sparse_feature_dim=8):        super(DeepFM, self).__init__()        self.num_field = num_field        self.layer_sizes = layer_sizes        self.sparse_feature_number = sparse_feature_number        self.sparse_feature_dim = sparse_feature_dim        self.fm = FM(self.sparse_feature_number, self.sparse_feature_dim)        self.dnn = DNN(self.num_field, self.layer_sizes, self.sparse_feature_number, self.sparse_feature_dim)        self.fc = paddle.nn.Linear(            in_features=1 + self.layer_sizes[-1],            out_features=1,            weight_attr=paddle.ParamAttr(                initializer=paddle.nn.initializer.Normal(std=1.0 / math.sqrt(1 + self.layer_sizes[-1]))))        self.add_sublayer('fc', self.fc)    def forward(self, sparse_inputs):                fm_out = self.fm(sparse_inputs)        dnn_out = self.dnn(sparse_inputs)        concat_out = paddle.concat([fm_out, dnn_out], axis=1)        y = self.fc(concat_out)                pred = paddle.nn.functional.sigmoid(y)                return pred            if __name__ == '__main__':        model = DeepFM(26, [512, 256, 128,32],sparse_feature_dim=9)        paddle.summary(model, (100, 26))        # data = [[159, 259, 4630199, 4630200, 163, 164, 165, 650, 167, 79129, 3135, 0, 652361, 169, 714906, 24, 0, 1520746, 1000438, 17249, 298, 0, 1000441, 3251, 1686, 181]]    # data = paddle.to_tensor(data)        # print(model(data))

   

3 训练

训练脚本,我这里采用的是MLP模型进行的训练,大家可以自己改进更换。

(推荐使用TeslaA100 32G 版本) 否则可能会有读取数据内存溢出,这一点是可以优化的,但是在平台上有32的选择,就无须纠结了。

train.py

In [ ]

# 训练一次需要很久,请根据自己的情况去调整epoch!python train.py

   

以上就是2023百度商业AI技术创新大赛-赛道1【非官方baseline】的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/52560.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月9日 05:01:16
下一篇 2025年11月9日 05:11:59

相关推荐

  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 如何用 CSS 实现微信输入法进度条按钮效果?

    如何在 css 中呈现微信输入法的进度条按钮效果? 问题:微信输入法中的进度条按钮具有独特的外观。如何使用 css 来实现这种效果? 答案:要实现微信输入法的进度条按钮效果,可以使用以下 css 属性的组合: linear-gradient:创建渐变效果。background-position:控制…

    2025年12月24日
    300
  • 微信小程序文本省略后如何避免背景色溢出?

    去掉单行文本溢出多余背景色 在编写微信小程序时,如果希望文本超出宽度后省略显示并在末尾显示省略号,但同时还需要文本带有背景色,可能会遇到如下问题:文本末尾出现多余的背景色块。这是因为文本本身超出部分被省略并用省略号代替,但其背景色依然存在。 要解决这个问题,可以采用以下方法: 给 text 元素添加…

    2025年12月24日
    000
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000
  • 如何用前端实现 Windows 10 设置界面的鼠标移动探照灯效果?

    如何在前端实现 Windows 10 设置界面中的鼠标移动探照灯效果 想要在前端开发中实现 Windows 10 设置界面中类似的鼠标移动探照灯效果,可以通过以下途径: CSS 解决方案 DEMO 1: Windows 10 网格悬停效果:https://codepen.io/tr4553r7/pe…

    2025年12月24日
    000
  • 使用CSS mask属性指定图片URL时,为什么浏览器无法加载图片?

    css mask属性未能加载图片的解决方法 使用css mask属性指定图片url时,如示例中所示: mask: url(“https://api.iconify.design/mdi:apple-icloud.svg”) center / contain no-repeat; 但是,在网络面板中却…

    2025年12月24日
    000
  • 如何用CSS Paint API为网页元素添加时尚的斑马线边框?

    为元素添加时尚的斑马线边框 在网页设计中,有时我们需要添加时尚的边框来提升元素的视觉效果。其中,斑马线边框是一种既醒目又别致的设计元素。 实现斜向斑马线边框 要实现斜向斑马线间隔圆环,我们可以使用css paint api。该api提供了强大的功能,可以让我们在元素上绘制复杂的图形。 立即学习“前端…

    2025年12月24日
    000
  • 为什么自定义样式表在 Safari 中访问百度时无效?

    自定义样式表在 Safari 中无效的问题 你在 Safari 偏好设置中自定义的样式表无法在某些网站(例如百度)上生效,这是为什么呢? 原因在于,你创建的样式表应用于本地文件路径,而百度是一个远程网站,位于互联网上。 在访问本地项目时,文件协议(file://)会允许你访问本地计算机上的文件。所以…

    2025年12月24日
    300
  • 图片如何不撑高父容器?

    如何让图片不撑高父容器? 当父容器包含不同高度的子元素时,父容器的高度通常会被最高元素撑开。如果你希望父容器的高度由文本内容撑开,避免图片对其产生影响,可以通过以下 css 解决方法: 绝对定位元素: .child-image { position: absolute; top: 0; left: …

    2025年12月24日
    000

发表回复

登录后才能评论
关注微信