新闻中心

飞桨常规赛:点击反欺诈预测-10月第2名方案

2025-07-30
浏览次数:
返回列表
本文围绕广告欺诈预测这一二分类任务展开,流程涵盖数据分析、特征工程等。对类别特征用Embedding处理,连续特征标准化;模型维持baseline结构,含embedding、concat等层,采用RMSProp优化器与交叉熵损失。还指出可从特征工程、模型结构等方面改进。

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

飞桨常规赛:点击反欺诈预测-10月第2名方案 -

1 赛题背景

广告欺诈是数字营销需要面临的重要挑战之一,点击会欺诈浪费广告主大量金钱,同时对点击数据会产生误导作用。本次比赛提供了约50万次点击数据。特别注意:我们对数据进行了模拟生成,对某些特征含义进行了隐藏,并进行了脱敏处理。

请预测用户的点击行为是否为正常点击,还是作弊行为。点击欺诈预测适用于各种信息流广告投放,banner广告投放,以及百度网盟平台,帮助商家鉴别点击欺诈,锁定精准真实用户。

2 任务分析

根据赛题设置,本任务为二分类任务; 根据数据挖掘与机器学习的一般任务流程,将按照下述流程完成该任务:

  1. 数据分析
  2. 特征工程
  3. 模型构建
  4. 模型训练
  5. 模型调优
  6. 模型推理

其中,模型调优部分同时涉及数据的再处理(比如选用新的特征工程方案)以及模型结构、优化方法、损失函数等方面的优化

3 解决方案

基于比赛提供的baseline实现,按照以下思路进行:

  1. 对于结构化数据中的各字段,进行稠密向量嵌入式表示;并将嵌入维度作为超参数进行调优;
  2. 维持baseline模型的基本结构不变,调整优化器及其学习率等训练超参数;

4 数据分析

在本赛题中,由于数据形式为结构化数据,为了对数据进行更好的表示以便神经网络模型能够充分挖掘数据背后的模式与规律,参照自然语言处理(NLP)中的字词方法,对数据的各字段进行稠密向量的嵌入式表示,即embedding方法。

简单而言,Embedding方法就是用一个低维的向量表示一个物体,可以是一个词,一个商品,或是一部电影等。这个向量能使距离相近的向量对应的物体有相近的含义,比如“复仇者联盟”对应的向量和“钢铁侠”对应的向量之间的距离(欧几里得距离,汉明距离等)就会很小,但 “复仇者联盟”对应的向量和“乱世佳人”对应的向量之间的距离就会大一些。 此外,Embedding形式的表示使得其背后所代表的“物体”具有数学运算关系,比如:Embedding(马德里)-Embedding(西班牙)+Embedding(法国)≈Embedding(巴黎)。

Embedding能够用低维向量对物体进行编码还能保留其含义的特点非常适合深度学习。在传统机器学习模型构建过程中,经常使用onehot编码对离散特征、特别是id类特征进行编码,但由于onehot编码的维度等于物体的类别总数,这样的编码方式对于类别型变量来说是极端稀疏的,而深度学习的特点使其不利于对稀疏特征向量的处理。

Motiff妙多 Motiff妙多

Motiff妙多是一款AI驱动的界面设计工具,定位为“AI时代设计工具”

Motiff妙多 334 查看详情 Motiff妙多

因此,在本任务中,先对数据集中的类别型变量进行嵌入式表示(连续性变量进行标准化),将处理之后的字段输入到神经网络模型中用以分类。

5 模型分析

本任务中,模型结构维持baseline提供的模型结构基本不变,其主要由embedding层、concat层以及dense层组成,embedding层用于获取每个输入字段值的嵌入式表示向量,concat层用于拼接所有字段的表示向量成为一个总的样本特征向量,dense层用于转换数据大小,其中模型最后一层的输出维度为2(类别数目),激活函数使用softmax函数。

关于模型的优化器与损失函数,优化器使用RMSProp,损失函数使用分类任务常设的交叉熵损失函数。

6 总结改进

根据赛题重点,合理有效地处理数据集的各类特征是完成分类任务的关键之处。 本项目只是使用较为初级的多层感知机网络执行分类任务,项目可改进的地方包含但不限于:

进一步细化特征处理办法,深化特征工程有关工作,Embedding处理只是其中一个方法; 改进或换用预测模型结构,可以尝试使用现代深度学习框架内更为先进的神经网络模型; 更换任务思路,采用传统机器学习项目中的相关思路与模型解决该问题,如适用于结构化数据的TabNet网络。

7 飞桨使用

在使用paddlepaddle进行深度学习时,注重理论课程与实践应用的合理结合; 一方面,强调通过资料与视频课程领会框架的基本使用; 另一方面,需要结合具体应用(如参加飞桨的各类竞赛)熟练掌握数据预处理、模型构建、模型训练、模型调优与应用等深度学习各阶段操作

8 参考资料

  1. 本次竞赛的baseline代码
  2. 深入浅出Word2Vec原理解析
  3. Embedding从入门到专家必读的十篇论文

feature_process

In [ ]
import osimport pandas as pdimport numpy as npfrom paddle.io import Datasetfrom baseline_tools import *

DATA_RATIO = 0.9  # 训练集和验证集比例TAGS = {'android_id': None,        'apptype': "emb",        'carrier': "emb",        'dev_height': "emb",        'dev_ppi': "emb",        'dev_width': "emb",        'lan': "emb",        'media_id': "emb",        'ntt': "emb",        'os': "emb",        'osv': None,        'package': "emb",        'sid': None,        'timestamp': "norm",        'version': "emb",        'fea_hash': None,        'location': "emb",        'fea1_hash': None,        'cus_type': None}# 归一化权重设置NORM_WEIGHT = {'timestamp': 6.40986e-12}
In [ ]
TRAIN_PATH = "train.csv"S*E_PATH = "emb_dicts"df = pd.read_csv(TRAIN_PATH, index_col=0)

pack = dict()for tag, tag_method in TAGS.items():    if tag_method != "emb":        continue
    data = df.loc[:, tag]
    dict_size = make_dict_file(data, S*E_PATH, dict_name=tag)
    pack[tag] = dict_size + 1  # +1是为了增加字典中不存在的情况,提供一个默认值with open(os.path.join(S*E_PATH, "size.dict"), "w", encoding="utf-8") as f:
    f.write(str(pack))print("全部生成完毕")

data_loading

In [ ]
def get_size_dict(dict_path="./emb_dicts/size.dict"):
    """
    获取Embedding推荐大小
    :param dict_path: 由run_make_emb_dict.py生成的size.dict
    :return: 推荐大小字典{key: num}
    """
    with open(dict_path, "r", encoding="utf-8") as f:        try:
            size_dict = eval(f.read())        except Exception as e:            print("size_dict打开失败,请检查", dict_path, "文件是否正常,报错信息如下:\n", e)        return size_dictclass Reader(Dataset):
    def __init__(self,
                 is_infer: bool = False,
                 is_val: bool = False,
                 use_mini_train: bool = False,
                 emb_dict_path="./emb_dicts"):

        """
        数据读取类
        :param is_infer: 是否为预测Reader
        :param is_val: 是否为验证Reader
        :param use_mini_train:使用Mini数据集
        :param emb_dict_path: emb字典路径
        """
        super().__init__()        # 选择文件名
        train_name = "mini_train" if use_mini_train else "train"
        file_name = "test" if is_infer else train_name        # 根据文件名读取对应csv文件
        df = pd.read_csv(file_name + ".csv")        # 划分数据集
        if is_infer:
            self.df = df.reset_index()        else:
            start_index = 0 if not is_val else int(len(df) * DATA_RATIO)
            end_index = int(len(df) * DATA_RATIO) if not is_val else len(df)
            self.df = df.loc[start_index:end_index].reset_index()        # 数据预处理
        self.cols = [tag for tag, tag_method in TAGS.items() if tag_method is not None]
        self.methods = dict()        for col in self.cols:            # ===== 预处理方法注册 =====
            if TAGS[col] == "emb":
                self.methods[col] = Data2IdEmb(dict_path=emb_dict_path, dict_name=col).get_method()            elif TAGS[col] == "norm":
                self.methods[col] = Data2IdNorm(norm_weight=NORM_WEIGHT[col]).get_method()            else:                raise Exception(str(TAGS) + "是未知的预处理方案,请选手在此位置使用elif注册")        # 设置FLAG负责控制__getitem__的pack是否包含label
        self.add_label = not is_infer        # 设置FLAG负责控制数据集划分情况
        self.is_val = is_val    def __getitem__(self, index):
        """
        获取sample
        :param index: sample_id
        :return: sample
        """
        # 因为本次数据集的字段非常多,这里就使用一个列表来"收纳"这些数据
        pack = []        # 遍历指定数量的字段
        for col in self.cols:
            sample = self.df.loc[index, col]
            sample = self.methods[col](sample)
            pack.append(sample)        # 如果不是预测,则添加标签数据
        if self.add_label:
            tag_data = self.df.loc[index, "label"]
            tag_data = np.array(tag_data).astype("int64")
            pack.append(tag_data)            return pack        else:            return pack    def __len__(self):
        return len(self.df)# 获取训练集和测试集数据读取器USE_MINI_DATA = Falsetrain_reader = Reader(use_mini_train=USE_MINI_DATA)
val_reader = Reader(use_mini_train=USE_MINI_DATA, is_val=True)

model_define

In [ ]
import osimport numpy as npimport pandas as pdimport paddleimport paddle.nn as nnimport paddle.tensor as tensorfrom paddle.static import InputSpecfrom paddle.metric import Accuracy# 模型保存与加载文件夹S*E_DIR = "./output/"# 部分训练超参数EMB_SIZE = 256  # Embedding特征大小EMB_LINEAR_SIZE = 32  # Embedding后接Linear层神经元数量LINEAR_LAYERS_NUM = 2  # 归一化方案的Linear层数量# 组网class SampleNet(paddle.nn.Layer):
    def __init__(self, tag_dict: dict, size_dict: dict):
        super().__init__()        # 新建一个隐藏层列表,用于存储各字段隐藏层对象
        self.hidden_layers_list = []        # 定义一个用于记录输出层的输入大小变量,经过一个emb的网络结构就增加该结构的output_dim,以此类推
        out_layer_input_size = 0

        # 遍历每个字段以及其处理方式
        for tag, tag_method in tag_dict.items():            # Embedding方法注册
            if tag_method == "emb":
                hidden_layer = nn.LayerList([nn.Embedding(num_embeddings=size_dict[tag],
                                                          embedding_dim=EMB_SIZE),
                                             nn.Linear(in_features=EMB_SIZE, out_features=EMB_LINEAR_SIZE)])
                out_layer_input_size += EMB_LINEAR_SIZE            # 归一化方法注册
            elif tag_method == "norm":
                hidden_layer = nn.LayerList(
                    [nn.Linear(in_features=1, out_features=1) for _ in range(LINEAR_LAYERS_NUM)])
                out_layer_input_size += 1
            # 如果对应方法为None,那么跳过该字段
            elif tag_method is None:                continue
            # 若出现没有注册的方法,提示报错
            else:                raise Exception(str(tag_method) + "为未知的处理方案,请在SampleNet类中用elif注册处理流程")
            self.hidden_layers_list.append(hidden_layer)
        
        self.out_layers = nn.Linear(in_features=out_layer_input_size,out_features=2)    # 前向推理部分 `*input_data`的`*`表示传入任一数量的变量
    def forward(self, *input_data):
        layer_list = []  # 用于存储各字段特征结果
        for sample_data, hidden_layers in zip(input_data, self.hidden_layers_list):
            tmp = sample_data            for hidden_layer in hidden_layers:
                tmp = hidden_layer(tmp)
            layer_list.append(tensor.flatten(tmp, start_axis=1))  # flatten是因为原始shape为[batch size, 1 , *n], 需要变换为[bs, n]
        # 对所有字段的特征合并
        layers = tensor.concat(layer_list, axis=1)        # 把特征放入用于输出层的网络
        result = self.out_layers(layers)
        result = paddle.nn.functional.softmax(result)        
        # 返回分类结果
        return result
In [ ]
# 定义网络输入inputs = []for tag_name, tag_m in TAGS.items():
    d_type = "float32"
    if tag_m == "emb":
        d_type = "int64"
    if tag_m is None:        continue
    inputs.append(InputSpec(shape=[-1, 1], dtype=d_type, name=tag_name))# 定义Labellabels = [InputSpec([-1, 1], 'int64', name='label')]# 实例化SampleNetmodel = paddle.Model(SampleNet(TAGS, get_size_dict()), inputs=inputs, labels=labels)

model_config

In [ ]
from paddle.optimizer import RMSProp# 定义优化器optimizer = RMSProp(learning_rate=0.01, parameters=model.parameters())# 模型训练配置model.prepare(optimizer, paddle.nn.loss.CrossEntropyLoss(), Accuracy())

model_training

In [7]
# 开始训练model.fit(train_data=train_reader,  # 训练集数据
            eval_data=val_reader,  # 验证集数据
            batch_size=128,  # Batch size大小
            epochs=10,  # 训练轮数
            log_freq=1000,  # 日志打印间隔
            s*e_dir=S*E_DIR)  # checkpoint保存路径

model_reasoning

In [ ]
# 推理部分CHECK_POINT_ID = "final"  TEST_BATCH_SIZE = 128  # 实例化SampleNetmodel = paddle.Model(SampleNet(TAGS, get_size_dict()), inputs=inputs)# 获取推理Reader并读取参数进行推理infer_reader = Reader(is_infer=True)
model.load(os.path.join(S*E_DIR, CHECK_POINT_ID))
In [ ]
# 开始推理model.prepare()
infer_output = model.predict(infer_reader, TEST_BATCH_SIZE)# 获取原始表中的字段并添加推理结果result_df = infer_reader.df.loc[:, "sid"]
pack = []for batch_out in infer_output[0]:    for sample in batch_out:
        pack.append(np.argmax(sample))# 保存csv文件RESULT_FILE = "./result1.csv"  result_df = pd.DataFrame({"sid": np.array(result_df, dtype="int64"), "label": pack})
result_df.to_csv(RESULT_FILE, index=False)print("结果文件保存至:", RESULT_FILE)
In [ ]
<br/>

以上就是飞桨常规赛:点击反欺诈预测-10月第2名方案的详细内容,更多请关注其它相关文章!


# 百度  # 系列产品  # 中文网  # 等方面  # 适用于  # 遍历  # 结构化  # 进行了  # type  # fig  # latte  # red  # csv文件  # ai  # 就会  # 顾轩SEO  # 宁波优化网站建设推广  # 潍坊网站优化简历工作室  # 邯郸正规网站seo优化报价  # 什么叫养老营销推广  # 平定网站推广怎么样赚钱  # 唐山模板网站建设价格  # seo秘教程博客  # 恩施郊区民宿网站推广  # 营销推广公司爱  # 首款  # 报错 


相关栏目: 【 行业资讯67740 】 【 技术百科0 】 【 网络运营39195


相关推荐: hen是什么意思  如何激活固态硬盘  juice是什么意思  5g手机4g卡怎么没有网络  typescript怎么判断单选按钮  j*a数组怎么新增值  输入命令如何换行  linux如何跳回命令行界面  焊机上power灯闪是什么意思  typescript在浏览器里怎么用  access 如何输入命令  typescript中如何引入本地js  命令行如何启动应用程序  春运抢票需要抢几天  笔记本电脑多少钱  typescript什么意思  苹果16系统多了哪些  单片机.lib文件怎么打开  cmd如何定时执行命令  东芝固态硬盘如何保修  单片机怎么控制内功率  win10系统如何打开cmd命令  win10如何开启命令行  固态硬盘如何接主机  360n7lite怎么设置动态壁纸  typescript中文怎么读  安卓手机怎么打开5g  春运抢票哪个平台好抢  typescript属性只读如何修改  跑步机power键是什么意思  如何通过命令行启动tomcat  苹果16最近玩法有哪些  iPhone无法打开YouTube原因分析与解决方案  如何用命令提示符显示隐藏分区  苹果16关闭哪些功能好  征信不好如何快速恢复 征信不好快速恢复的方法  单片机显存怎么设置最佳  春运抢票要用抢票软件吗  react怎么用typescript  广东春运几点抢票  如何查看固态硬盘分区  苹果16将会带来哪些升级  阿里云手机云盘怎么用_阿里云盘苹果手机怎么用教程  夸克po什么意思  市盈率底下 18A 19E 是什么意思  如何以管理员身份打开cmd命令行窗口  电动车power灯亮是什么意思  使用typescript对团队有什么要求  夸克投屏为什么那么卡  python 如何执行linux命令 

搜索