【组队学习·打卡】项目实践:广告-信息流跨域CTR预估(待更新)

0 任务概述

任务1:报名并理解赛题任务(9.12~9.13,2天)

任务2:配置环境(9.14,1天)

任务3:baseline实践(9.15,1天)

任务4:数据处理、算法应用等技能学习(9.16~9.17,2天)

任务5:相关知识参考学习(9.18,1天)

大作业:结合学习任务完成一篇学习笔记

1 报名并理解赛题任务

1.1 学习准备任务

    学习准备任务主要包括:

①Datawhale报名(完成)

②平台注册:在【华为赛事官网注册网址】 已完成注册

③比赛报名:在【华为赛事官网报名地址】已完成报名

④数据下载:在相应的赛题连接中完成数据的下载

1.2 赛题理解

1.2.1背景

        为什么要做CTR预测?——若能准确预测CTR,可丰富用户的行为特征。

1.2.2赛题数据

        目标域数据:广告行为本身,即收集广告任务产生的历史数据(收集的数据,质量不好保证,可能数据会很稀疏 → 受数据收集手段的影响)

        源域数据:用户另外渠道收获到的数据,用户浏览信息流里的数据,即在其他领域的行为数据

        应该将上述两种数据有效结合起来:可通过用户的【u_userid】这个特征,将两种数据结合形成一个更大的数据集

1.2.3 赛题任务   

        基于用户的行为历史特征,预测该用户是否会产生点击这个行为。

        输入:用户的行为历史特征数据

        输出:用户是否会产生【点击】这个行为(0:不点击;1:点击)

        模型:初步判断,任务的问题可抽象成一个二分类的问题。

1.2.4 评价指标

    AUC和GAUC的加权求和。

2 环境配置

2.1 本地配置

①参考教程:https://blog.csdn.net/fan18317517352/article/details/123035625

②配置结果,如下图所示:

2.2 线上配置

    按照本期Datawhale组队学习贡献者的建议,对于推荐任务,使用百度飞桨AI Studio即可。

    在完成百度飞桨AI Studio账号注册和登录后,可参照其官方提供的新手教程进行新建项目、baseline实践等操作。

    部分操作的截图如下图所示。

①找到“项目”选项标签,单击【创建项目】,效果如下图所示;

 ②按照上图所示,选择【Notebook】,单击【下一步】后,如下图所示

 ③按照上图所示,完成【配置环境】后,单击【下一步】后界面如下图

 ④在上图中,填写项目信息后,单击【创建】按钮,会提示【项目创建成功】,进入如下图所示的界面

⑤点击上图中的【启动环境】,即可完成云端环境的配置。 

3 baseline实践

3.1 解决机器学习问题的流程

(1)问题分析

        根据赛题的描述,可将赛题的问题抽象成二分类问题。

(2)数据探索

        数据有两个部分:训练集和测试集,每个包含两个数据文件:一类是广告相关的数据(ads),另外一个是用户的习惯数据(feeds)。

(3)特征工程

        ①可以去除一些无关的特征

        ②将一些非数值类型的特征转换为数值型特征

        ③为了节省内存空间,可将数据类型进行压缩

(4)模型训练

        对于二分类问题,可以考虑使用:逻辑回归、决策树、XGBoost等算法进行模型构建。

(5)模型验证:若结果不理想,返回(3),否则进入(6)

(6)结果输出

3.2 代码实现

# ---------------------------------------------------
# 导入库
import pandas as pd

# ----------------数据探索----------------
# 只使用目标域用户行为数据
train_ads = pd.read_csv('./train/train_data_ads.csv',
                        usecols=['log_id', 'label', 'user_id', 'age', 'gender', 'residence', 'device_name',
                                 'device_size', 'net_type', 'task_id', 'adv_id', 'creat_type_cd'])

test_ads = pd.read_csv('./test/test_data_ads.csv',
                       usecols=['log_id', 'user_id', 'age', 'gender', 'residence', 'device_name',
                                'device_size', 'net_type', 'task_id', 'adv_id', 'creat_type_cd'])

# 数据集采样
train_ads = pd.concat([
    train_ads[train_ads['label'] == 0].sample(70000),
    train_ads[train_ads['label'] == 1].sample(10000),
])

# ----------------模型训练----------------
# 加载训练逻辑回归模型
from sklearn.linear_model import LogisticRegression

clf = LogisticRegression()
clf.fit(
    train_ads.drop(['log_id', 'label', 'user_id'], axis=1),
    train_ads['label']
)

# ----------------结果输出----------------
# 模型预测与生成结果文件
test_ads['pctr'] = clf.predict_proba(
    test_ads.drop(['log_id', 'user_id'], axis=1),
)[:, 0]
test_ads[['log_id', 'pctr']].to_csv('submission.csv', index=None)

3.3 运行结果输出

    运行结果的部分截图如下

3.4 模型优化

    解决机器学习问题的流程,以代码的形式展现如下:

(1)导入库

#导入库
# ——————————————————————————————————————————————————————

# ---------- 数据探索 ---------- #
import pandas as pd
import numpy as np
import os
import gc
import matplotlib.pyplot as plt
import tqdm import *
#----------------核心模型----------------
from catboost import CatBoostClassifier
from sklearn.linear_model import SGDRegressor, LinearRegression, Ridge
#----------------交叉验证----------------
from sklearn.model_selection import StratifiedKFold, KFold
#----------------评估指标----------------
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score, log_loss
#----------------忽略报警----------------
import warnings
warnings.filterwarnings('ignore')

(2)数据预处理

# 数据预处理
# ——————————————————————————————————————————————————————

# ---------- 读取训练数据和测试数据 ----------
train_data_ads = pd.read_csv('./train/train_data_ads.csv')
train_data_feeds = pd.read_csv('./train/train_data_feeds.csv')

test_data_ads = pd.read_csv('./test/test_data_ads.csv')
test_data_feeds = pd.read_csv('./test/test_data_feeds.csv')


# ---------- 合并数据 ----------
# 为数据添加新列istest,便于区分数据
train_data_ads['istest'] = 0
test_data_ads['istest'] = 1
data_ads = pd.concat([train_data_ads, test_data_ads], axis=0, ignore_index=True)

train_data_feeds['istest'] = 0
test_data_feeds['istest'] = 1
data_feeds = pd.concat([train_data_feeds, test_data_feeds], axis=0, ignore_index=True)

# 清除变量、内存
del train_data_ads, test_data_ads, train_data_feeds, test_data_feeds
gc.collect()

# # 删除无意义的特征
# data_ads = data_ads.drop(columns=['log_id'])

(3)特征工程

    本项目中的特征工程主要包括:自然数编码、特征提取、内存压缩

# 特征工程:自然数编码、特征提取、内存压缩
# ——————————————————————————————————————————————————————

# 1/3 自然数编码
def label_encode(series, series2):
    unique = list(series.unique())
    return series2.map(dict(zip(
        unique, range(series.nunique())
    )))

for col in ['ad_click_list_v001','ad_click_list_v002','ad_click_list_v003','ad_close_list_v001','ad_close_list_v002','ad_close_list_v003','u_newsCatInterestsST']:
    data_ads[col] = label_encode(data_ads[col], data_ads[col])

# 2/3 特征提取
# 特征构建部分,均使用训练集数据进行构建,避免测试集使用未来数据
train_feeds = data_feeds[data_feeds.istest==0]
cols = [f for f in train_feeds.columns if f not in ['label','istest','u_userId']]
for col in tqdm(cols):
    tmp = train_feeds.groupby(['u_userId'])[col].nunique().reset_index()
    tmp.columns = ['user_id', col+'_feeds_nuni']
    data_ads = data_ads.merge(tmp, on='user_id', how='left')

cols = [f for f in train_feeds.columns if f not in ['istest','u_userId','u_newsCatInterests','u_newsCatDislike','u_newsCatInterestsST','u_click_ca2_news','i_docId','i_s_sourceId','i_entities']]
for col in tqdm(cols):
    tmp = train_feeds.groupby(['u_userId'])[col].mean().reset_index()
    tmp.columns = ['user_id', col+'_feeds_mean']
    data_ads = data_ads.merge(tmp, on='user_id', how='left')
    
# 3/3 内存压缩
def reduce_mem_usage(df, verbose=True):
    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
    start_mem = df.memory_usage().sum() / 1024**2    
    for col in df.columns:
        col_type = df[col].dtypes
        if col_type in numerics:
            c_min = df[col].min()
            c_max = df[col].max()
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)  
            else:
                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                    df[col] = df[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)    
    end_mem = df.memory_usage().sum() / 1024**2
    if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))
    return df
    
# 压缩使用内存
data_ads = reduce_mem_usage(data_ads)
# Mem. usage decreased to 2351.47 Mb (69.3% reduction)

(4)训练集和测试集划分

# 训练集和测试集划分
# ——————————————————————————————————————————————————————

# ---------- 划分训练集和测试集 ----------

# 将数据按照时间戳排序
data_ads = data_ads.sort_values('pt_d')

cols = [f for f in data_ads.columns if f not in ['label','istest']]
x_train = data_ads[data_ads.istest==0][cols]
x_test = data_ads[data_ads.istest==1][cols]

y_train = data_ads[data_ads.istest==0]['label']


# 重置index
for df in [x_train, x_test, y_train]:
    df.index = range(0, df.shape[0])

del data_ads, data_feeds
gc.collect()

(5)模型训练

# 训练模型
# ——————————————————————————————————————————————————————

trn_x, val_x, trn_y, val_y = train_test_split(x_train, y_train, test_size=0.33, shuffle=False)


params = {'iterations': 20000, 'learning_rate': 0.3, 'depth': 5, 'l2_leaf_reg': 10, 'bootstrap_type': 'Bernoulli',
                  'od_type': 'Iter', 'od_wait': 50, 'random_seed': 11, 'allow_writing_files': False}
model = CatBoostClassifier(**params, eval_metric='AUC',task_type="GPU")
model.fit(trn_x, trn_y, eval_set=(val_x, val_y),
          cat_features=[],
          use_best_model=True,
          verbose=1)

(6)结果保存

# 结果保存
# ——————————————————————————————————————————————————————

test_pred = model.predict_proba(x_test)[:, 1]
test_pred
x_test['pctr'] = test_pred
x_test[['log_id','pctr']].to_csv('submission.csv', index=False)

(7)效果输出

    第一次模型训练的结果如下:

bestTest = 0.8001283705
bestIteration = 356
Shrink model to first 357 iterations.

    代码改动如下:

①添加了处理特征穿越的代码:训练集和测试集的数据在“时间戳”这个特征上有重合

# 处理特征穿越,避免使用未来的数据
minDate = min(test_data_ads.pt_d.min(), test_data_feeds.e_et.min())
train_data_ads = train_data_ads[train_data_ads.pt_d < minDate]
train_data_feeds = train_data_feeds[train_data_feeds.e_et < minDate]

②将数据按照时间戳排序

data_ads = data_ads.sort_values('pt_d')

    第二次模型训练的结果如下:

bestTest = 0.7939100862
bestIteration = 363
Shrink model to first 364 iterations.

    第二次模型训练的结果文件submission.csv已经提交,观察分数是否提升。

    计划后期多了解一些广告业务CTR方面的信息,并在特征构建、模型训练(多尝试几个模型)上下功夫提升赛事的得分。

未完待续~~

参考资料

 https://xj15uxcopw.feishu.cn/docx/doxcnw5LGZfH5n1WSwcNV59VxTg

https://datawhale.feishu.cn/docx/doxcn7BjORolb95KWXNBwH1nmhd

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值