如何做数据竞赛·优秀案例学习(DC01)

2019年腾讯广告算法大赛冠军思路、代码(PART 1)

方案地址:https://zhuanlan.zhihu.com/p/73062485
代码地址:https://github.com/guoday/Tencent2019_Preliminary_Rank1st
数据地址:https://algo.qq.com/application/home/home/review.html


官方题目描述:

在这里插入图片描述

通俗题目描述:

利用历史曝光信息,广告信息,用户信息来预测一个广告的日曝光量。

数据描述:

  • 历史曝光日志数据文件
    • 广告请求 id:唯一标识每次请求(每个请求对应一个用户某一时刻,可能多个广告位)。
    • 广告请求时间:该字段为时间戳,即 1970 纪元后经过的浮点秒数。
    • 广告位 id:加密后无业务含义,只区分不同广告位,每个广告位只能曝光特定素材尺寸的广告。
    • 用户 id(即看广告的人):加密后无业务含义,只区分不同用户,可和后面的用户特征数据中 id 相关联。
    • 曝光广告 id:加密后无业务含义,只区分不同广告,可以和广告特征文件中的广告 id 关联。
    • 曝光广告素材尺寸:枚举型取值,不同广告位对素材的尺寸要求不同,同一个广告位可能适配多个不同尺寸的素材。
    • 曝光广告出价 bid:这里只记录 cpc 出价,非 cpc 广告此处记录折算后的 cpc价格。
    • 曝光广告 pctr:预估的 pctr,和 bid 相乘得到 basic_ecpm。
    • 曝光广告 quality_ecpm:将广告质量和用户体验等因素折算成 ecpm 的分数,主要影响因素有 pctr/pcvr/窄定向等。
    • 曝光广告 totalEcpm:广告排序的分数依据,由 basic_ecpm 和 quality_ecpm相加得到。
      在这里插入图片描述

  • 广告静态数据
    • 广告 id:和曝光日志中的广告 id 相关联。
    • 创建时间:广告创建时的时间戳。
    • 广告账户 id:广告所在账户的唯一标识,账户结构分为四级:账户——推广计划——广告——素材。
    • 商品 id:广告推广目标的唯一标识,若推广目标是落地页,则该字段为空。
    • 商品类型:广告推广目标的类型,枚举型。
    • 广告行业 id:广告所属的行业类别标识。
    • 素材尺寸:不同广告位对素材的尺寸要求不同,同一个广告可能有多个不同尺寸的素材,用逗号分隔。
      在这里插入图片描述

  • 广告操作数据
    • 广告 id(同上)。
    • 创建/修改时间: 即广告创建或者修改设置的时间。
    • 操作类型:1-修改,2-新建。
    • 修改字段:1-广告状态,2-出价,3-人群定向,4-广告时段设置。
    • 操作后的字段值:
      • 广告状态取值:1- 正常,0-失效。
      • 出价:整数(单位分)。
      • 投放时段:字符串。包含 7 个 64 位无符号整型数字(逗号分隔),每个整数分别代表周一到周日的投放时段。该整数转为 2 进制后从低到高 48 位bit 代表全天各时段(半小时为一时间窗口)是否投放,1-投放,0-不投。举例说明17179865088= 1111111111111111111111000000000000,代表投放时段为 6:00-17:00,281474976710655=111111111111111111111111111111111111111111111111,代表全天投放。
      • 人群定向:字符串。格式如下:
        feature_name1:feature_value1,feature_value2|feature_name2:feature_value3,feature_value4|… 此处 feature_name 取值同用户属性文件中的各列属性名,feature_value 取值 id 同用户属性文件中的定义,不同feature 用“|”分隔,不同 feature 取值用逗号分隔。广告通过人群定向的设置来召回对应的用户请求,对应的人群规则:不同 feature_name 是求 交 集 , 同 一 featurename 下 不 同 的 value 求并集 , 未 定 义 的feature_name 则表示 该维度 不 限 。 举 例 如:定向 设 置 为age:51,62,73,84|gender:1|area:1,3,5 ; 则表示该广告能被“(年龄 id 为51 或 62 或 73 或 84) 且 (性别取值为 1) 且 (地域取值为 1 或 3或 5)”的用户召回(即在这些用户上有曝光机会)。
        在这里插入图片描述

  • 用户特征属性文件
    • 用户 id:此处和上面曝光日志文件中的用户 id 关联。
    • 年龄(Age):每个取值随机映射为[1-N]的唯一 id。
    • 性别(Gender):男/女。
    • 地域(area):每个省/市用唯一 id 标识,可能多标签,使用逗号分隔不同 id。
    • 婚恋状态(Status):单身/已婚等状态,可能去多值,使用逗号分隔。
    • 学历(Education):博士/硕士/本科/高中/初中/小学。
    • 消费能力(ConsuptionAbility):高/低。
    • 设备(device):IOS/Android, 不区分版本号。
    • 工作状态(work):在校大学生/商旅人士/政府公职人员/科研教育者/ IT 互联网工作者/医护工作者, 可能取多值,逗号分隔。
    • 连接类型(ConnectionType):无线/2G/3G/4G。
    • 行为兴趣(behavior):每个兴趣点一个 id,可多值,逗号分隔。
      在这里插入图片描述

评价指标:

1 准确性指标

在这里插入图片描述
Ft 为预估的广告曝光值,At 为真实的曝光值。

2 单调性指标

在这里插入图片描述

3 综合指标

在这里插入图片描述
最后要将单调性指标和准确性指标综合到一起来计算最后得分。


代码 预处理(数据清洗)Preprocess.py:

import os
import pandas as pd
import numpy as np
import random
import gc
import time
from tqdm import tqdm

def parse_rawdata():
    #曝光日志
    df=pd.read_csv('data/testA/totalExposureLog.out', sep='\t',names=['id','request_timestamp','position','uid','aid','imp_ad_size','bid','pctr','quality_ecpm','totalEcpm']).sort_values(by='request_timestamp')
#使用pandas来读取曝光日志文件,分隔符为‘\t’,命名列名为['id','request_t...],同时根据列名request_timestamp对所有数据排序,默认为升序
    df[['id','request_timestamp','position','uid','aid','imp_ad_size']]=df[['id','request_timestamp','position','uid','aid','imp_ad_size']].astype(int)  
##类型转化,因为读入的有些字符可能是字符串格式的,需要统一转化为float格式
    df[['bid','pctr','quality_ecpm','totalEcpm']]=df[['bid','pctr','quality_ecpm','totalEcpm']].astype(float) 
    ##类型转化,因为读入的有些字符可能是字符串格式的,需要统一转化为int格式
    df.to_pickle('data/testA/totalExposureLog.pkl') 
    ##将dataframe格式数据转换pickle,方便下次存取
    
    del df
    gc.collect()
    #这两行的作用是删除df变量在内存中的占用,同时用gc.collect()来清理内存
    ##############################################################################
    #静态广告
    df =pd.read_csv('data/testA/ad_static_feature.out', sep='\t', names=['aid','create_timestamp','advertiser','good_id','good_type','ad_type_id','ad_size']).sort_values(by='create_timestamp')
    ##同理,读取静态广告文件,分隔符‘\t’,按列名['aid','create_timestamp'...]命名,按列排序。
    df=df.fillna(-1)
    ## 对df中缺失值填充-1
    for f in ['aid','create_timestamp','advertiser','good_id','good_type','ad_type_id']:
        items=[]
        for item in df[f].values:
            try:
                items.append(int(item))
            except:
                items.append(-1)
        #try,except语句,当try中出现错误时执行except语句,可以保证程序都会执行下去
        df[f]=items
        df[f]=df[f].astype(int)
        ## 对于可能不是空值,但是有异常的值,某些填入字符串的值,利用遍历来转换,对这些值置为-1
    df['ad_size']=df['ad_size'].apply(lambda x:' '.join([str(int(float(y))) for y in str(x).split(',')]))    
    #因为ad_size列中可能有多个数值,不同广告大小,所以使用匿名函数,
    #将size列中的数据转化为str类型,同时去掉逗号,用空格分隔
    df.to_pickle('data/testA/ad_static_feature.pkl')
    del df
    gc.collect()
##同理,清除内存    
    ##############################################################################
    #用户信息
    df =pd.read_csv('data/testA/user_data', sep='\t', 
                  names=['uid','age','gender','area','status','education','concuptionAbility','os','work','connectionType','behavior'])
    df=df.fillna(-1)
##读取用户文件,同时命名,对缺失值填充-1
    df[['uid','age','gender','education','consuptionAbility','os','connectionType']]=df[['uid','age','gender','education','concuptionAbility','os','connectionType']].astype(int)
    ## 类型转化
    for f in ['area','status','work','behavior']:
        df[f]=df[f].apply(lambda x:' '.join(x.split(',')))
    #因为['area','status','work','behavior']中可能会有多值存在,
    #所以进行数据清洗,方便后续处理,将分割由,转换为空格
    df.to_pickle('data/testA/user_data.pkl')
    del df
    gc.collect()
##清除内存    
    ##############################################################################
    #测试数据
    df=pd.read_csv('data/testA/test_sample.dat', sep='\t', names=['id','aid','create_timestamp','ad_size','ad_type_id','good_type','good_id','advertiser','delivery_periods','crowd_direction','bid'])
    df=df.fillna(-1)
    ## 读取测试数据,缺失值填充-1
    df[['id','aid','create_timestamp','ad_size','ad_type_id','good_type','good_id','advertiser']]=df[['id','aid','create_timestamp','ad_size','ad_type_id','good_type','good_id','advertiser']].astype(int)
    ## 类型转化
    df['bid']=df['bid'].astype(float)
    df.to_pickle('data/testA/test_sample.pkl')
    del df
    gc.collect()
## 保存pickle格式,清除内存。


def construct_log():
    #构造曝光日志,分别有验证集的log和测试集的log
    train_df=pd.read_pickle('data/testA/totalExposureLog.pkl')
    ##读取之前存储的pickle格式文件
    train_df['request_day']=train_df['request_timestamp']//(3600*24)
    ##将时间戳粗略转化为‘天’为单位的计量值
    wday=[]
    hour=[]
    minute=[]
    for x in tqdm(train_df['request_timestamp'].values,total=len(train_df)):
    ##tqdm是python里面进度条的封装函数,通过封装一些处理语句,可以让程序有反馈,方便程序员操作
        localtime=time.localtime(x)
        ## time.localtime作用是格式化时间戳为本地的时间,通过打印可返回一个结构体
        #time.struct_time(tm_year=2016, tm_mon=11, tm_mday=27, tm_hour=10, tm_min=26, tm_sec=5, tm_wday=6, tm_yday=332, tm_isdst=0)
        wday.append(localtime[6])#对应tm_wday
        hour.append(localtime[3])#对应tm_hour
        minute.append(localtime[4])#对应tm_min
    train_df['wday']=wday
    train_df['hour']=hour
    train_df['minute']=minute
    train_df['period_id']=train_df['hour']*2+train_df['minute']//30
    #将时间粒度以半小时为单位作为一个特征
    dev_df=train_df[train_df['request_day']==17974]
    #构造验证集
    del dev_df['period_id']
    del dev_df['minute']
    del dev_df['hour']
    #删除验证集中period_id,minute,hour列
    log=train_df
    #备份训练集,这种赋值方法是对象指向型的,也就是说改变任何变量里的数据,另一个变量都会随之改变。
    tmp = pd.DataFrame(train_df.groupby(['aid','request_day']).size()).reset_index()
    #按照'aid','request_day'分组来构造曝光量,同一个aid,同一天的出现次数作为曝光量,同时reset_index()增加新的索引列index,从0开始
    tmp.columns=['aid','request_day','imp']
    #重新命名dataframe的列名
    log=log.merge(tmp,on=['aid','request_day'],how='left')
    #merge函数,方式为左连接,及左边的dataframe(log)在['aid','request_day']列上全取,右边的根据与之合并。
    #构造出最后的训练集,最后由train_df返回
    #与之前备份的训练集数据合并,相当于为训练集中的所有数据增加了标签列
    log[log['request_day']<17973].to_pickle('data/user_log_dev.pkl')
    #将小于17973号数据存为pickle格式数据
    log.to_pickle('data/user_log_test.pkl')
    #训练集构造保存为pickle格式,方便下次读取
    del log
    del tmp
    gc.collect()
    #清除内存变量
    del train_df['period_id']
    del train_df['minute']
    del train_df['hour']  
    #删除训练集中的某些列  
    return train_df,dev_df
    #返回训练集和验证集
def extract_setting():
    aids=[]
    with open('data/testA/ad_operation.dat','r') as f:
    #以只读方式‘r’打开广告操作文件
        for line in f:
        #对文件中的按行遍历
            line=line.strip().split('\t')
    #Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列,
    #同时split('\t'),用‘\t’分割数据,形成列表
            try:
                if line[1]=='20190230000000':
                    line[1]='20190301000000'
                    #对出现2月30号的数据视为异常,将其强制转变为3月1号数据
                if line[1]!='0':
                    request_day=time.mktime(time.strptime(line[1], '%Y%m%d%H%M%S'))//(3600*24)
                    #time.strptime函数根据指定的格式把一个时间字符串解析为时间元组。返回一个时间结构体
                    #mktime()用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0秒算起至今的UTC时间所经过的秒数。
                    #从而同步与训练集的时间戳数据
                else:
                    request_day=0
                    #对于line[1]==0的数据,也就是update==0的,request_day也为0,可以视为异常数据
            except:
                print(line[1])
                #如果上述发生错误语句,则打印这行的遍历结果


##根据operation文件里的特性,我们发现,广告按其id已经分好组了,判断是否重复
#只需要和最后一个比较就可以。下面的操作可以理解为一种填充,因为只有一个广告在
#operation里才会有曝光量,所以下面的语句是为了填充,如果某个广告只在操作表中
#出现过一次,那么我们则将其扩充到所有日期,如果某个广告在操作表中出现2次及以上
#,如果请求时间相同则不处理,如果请求时间不同,则扩充两次请求时间内全部为第一次出现操作。
            if len(aids)==0:
                aids.append([int(line[0]),0,"NaN","NaN"])
                #line[0]为aid,存入的list为['aid','request_day','crowd_direction','delivery_periods']
            elif aids[-1][0]!=int(line[0]):
                for i in range(max(17930,aids[-1][1]+1),17975):
                #需要注意的是在这个循环里,(aids[-1][1]+1)是一个一开始就确定的数
                #将只出现一次的广告扩充所有日期原操作
                    aids.append(aids[-1].copy())
                    aids[-1][1]=i
                aids.append([int(line[0]),0,"NaN","NaN"])               
            elif request_day!=aids[-1][1]:
            #将出现2次及以上的广告在request间隔内扩充
                for i in range(max(17930,aids[-1][1]+1),int(request_day)):
                    aids.append(aids[-1].copy())
                    aids[-1][1]=i                
                aids.append(aids[-1].copy())
                aids[-1][1]=int(request_day)
            if line[3]=='3':
                aids[-1][2]=line[4]
                #对'crowd_direction'赋值操作
            if line[3]=='4':
                aids[-1][3]=line[4]
                #对'delivery_periods'赋值操作
    ad_df=pd.DataFrame(aids)
    #将列表生成dataframe
    ad_df.columns=['aid','request_day','crowd_direction','delivery_periods']
    #对dataframe格式数据重新命名列名
    return ad_df
    #返回广告操作数据以dataframe格式
    
def construct_train_data(train_df):
    #构造训练集
    #算出广告当天平均出价和曝光量
    tmp = pd.DataFrame(train_df.groupby(['aid','request_day'])['bid'].nunique()).reset_index()
    #对训练数据按['aid','request_day']进行分组操作之后提取bid属性,
    #nunique()用这个函数可以查看数据有多少个不同值,重新建立索引
    tmp.columns=['aid','request_day','bid_unique']
    #对生成的新dataframe重新命名
    train_df=train_df.merge(tmp,on=['aid','request_day'],how='left')
    #为每一个广告,和请求时间加上bid数量属性,表明同一个广告,在同一个请求时间下,存在多少次不同出价
    tmp = pd.DataFrame(train_df.groupby(['aid','request_day']).size()).reset_index()
    #对训练数据按照['aid','request_day']分组,并求每组有多少个,重新设置索引
    tmp_1 = pd.DataFrame(train_df.groupby(['aid','request_day'])['bid'].mean()).reset_index()
    ##提取每个分组的出价平均值
    tmp.columns=['aid','request_day','imp']
    #构造曝光量,将曝光近似为同一天有多少个请求
    del train_df['bid']
    #删除训练集中的bid列
    tmp_1.columns=['aid','request_day','bid']
    #构造平均出价作为同一广告,同一刻请求的出价
    train_df=train_df.drop_duplicates(['aid','request_day'])
    # 去重aid和request_day一样的数据
    train_df=train_df.merge(tmp,on=['aid','request_day'],how='left')
    #tmp文件里有曝光量的属性,与之合并
    train_df=train_df.merge(tmp_1,on=['aid','request_day'],how='left')
    #tep1里有平均出价的属性,与训练集合并
    del tmp
    del tmp_1
    gc.collect()
    #清空内存
    train_df=train_df.drop_duplicates(['aid','request_day'])
    del train_df['request_timestamp']
    del train_df['uid']
    #删除训练集中的['request_timestamp']和['uid']属性,删除无关属性,可以在训练中提高效率


    #以下操作过滤未出现在广告操作文件的广告
    ad_df=extract_setting()#调用之前写的extract_setting()函数,返回的是广告操作数据
    ad_df=ad_df.drop_duplicates(['aid','request_day'],keep='last')
    #操作数据去重,按照aid','request_day,保留最后一项
    ad_df['request_day']+=1
    #对操作数据的所有请求时间加一天,我的理解是这么做可以和训练数据出现的请求时间上是同步的,因为操作之后是后一天才计算曝光量的
    train_df=train_df.merge(ad_df,on=['aid','request_day'],how='left')
    #和训练数据合并,此时训练数据属性包括改广告曝光量,出价,以及对应的操作
    train_df['is']=train_df['crowd_direction'].apply(lambda x:type(x)==str)
    #生成训练数据新列,表示是否有定向人群的属性,如果该字段是字符串,则标记为true
    train_df=train_df[train_df['is']==True]
    #提取有is列是true的数据,相当于筛选
    train_df=train_df[train_df['crowd_direction']!="NaN"]
    #除去定向人群是NAN格式的数据,表示空值
    train_df=train_df[train_df['delivery_periods']!="NaN"]
    #在之前基础上,除去投送时期是空的数据



    #以下操作过滤出价和曝光过高的广告
    train_df=train_df[train_df['imp']<=3000]
    #除去曝光量大于3000的数据,因为经过分析,大于3000的只有很少,我们可以把他们作为异常值处理,这样可以保证模型准确性
    train_df=train_df[train_df['bid']<=1000]
    #除去出价大于1000的,原因同上
    train_dev_df=train_df[train_df['request_day']<17973]
    #将请求日期小于17973的数据作为训练验证数据集
    print(train_df.shape,train_dev_df.shape)
    #输出训练数据的规模大小,以及验证数据集的
    print(train_df['imp'].mean(),train_df['bid'].mean())
   #输出训练数据集中曝光量的平均值,以及出价的平均值
    return train_df,train_dev_df
   #返回训练数据集和训练验证数据集


def construct_dev_data(dev_df):
    #构造验证集,主要用来确定网络结构或者控制模型复杂程度的参数
    #过滤掉当天操作的广告,和未出现在操作日志的广告
    aids=set()
    #set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
    exit_aids=set()
    
    with open('data/testA/ad_operation.dat','r') as f:
    #打开广告操作文件
        for line in f:
        #按行遍历
            line=line.strip().split('\t')
            #除去每行开头结尾的空格,同时按字符'\t'分割
            if line[1]=='20190230000000':
                line[1]='20190301000000'
                #对出现2月30号的数据视为异常,将其强制转变为3月1号数据
            if line[1]!='0':
                request_day=time.mktime(time.strptime(line[1], '%Y%m%d%H%M%S'))//(3600*24)
                 #time.strptime函数根据指定的格式把一个时间字符串解析为时间元组。返回一个时间结构体
                    #mktime()用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0秒算起至今的UTC时间所经过的秒数。
                    #从而同步与训练集的时间戳数据
            else:
                request_day=0
                #对于line[1]==0的数据,也就是update==0的,request_day也为0,可以视为异常数据
            if request_day==17974:
                aids.add(int(line[0]))
                #最后一天的所有广告操作,其广告id加入aids中
            exit_aids.add(int(line[0]))
            #所有的广告操作中广告id集合
    dev_df['is']=dev_df['aid'].apply(lambda x: x in aids)
	#apply函数将dataframe中每个数据调用后面的匿名函数
    dev_df=dev_df[dev_df['is']==False]
    #将验证集中的广告id如果出现在最后一天则除去
    dev_df['is']=dev_df['aid'].apply(lambda x: x in exit_aids)
    dev_df=dev_df[dev_df['is']==True]
    #除去验证集中没有广告操作的数据
    
    #过滤当天出价不唯一的广告
    tmp = pd.DataFrame(dev_df.groupby('aid')['bid'].nunique()).reset_index()
    #按照广告id统计出价个数,并且重新设置索引
    tmp.columns=['aid','bid_unique']
    dev_df=dev_df.merge(tmp,on='aid',how='left')
    #在验证集上增加新列,每个广告id下的出价个数
    dev_df=dev_df[dev_df['bid_unique']==1]
    #保留出价个数为1次的广告id
    
    #统计广告当天的曝光量
    tmp = pd.DataFrame(dev_df.groupby('aid').size()).reset_index()
    tmp.columns=['aid','imp']
    #统计验证集上广告当天的曝光量,并重新命名列名
    dev_df=dev_df.merge(tmp,on='aid',how='left')
    #为验证集增加新列,以左连接方式在aid属性上合并数据,增加曝光量属性
    dev_df=dev_df.drop_duplicates('aid')
    #过滤广告ID重复数据
    
    #过滤未出现在广告操作文件的广告
    ad_df=extract_setting()
    #返回扩充过的广告操作数据
    ad_df=ad_df.drop_duplicates(['aid'],keep='last')
    #过滤aid重复数据,保留最后一次
    dev_df=dev_df.merge(ad_df,on='aid',how='left')
    #验证集和操作数据合并
    dev_df=dev_df[dev_df['crowd_direction']!="NaN"]
    #过滤验证集中没有人群定向的数据
    dev_df=dev_df[dev_df['delivery_periods']!="NaN"].reset_index()
    #过滤验证集中没有投放时段的数据
    del dev_df['index']
    del dev_df['request_timestamp']
    del dev_df['is']
    del dev_df['uid']
    #删除验证集中对应的列
    
    #构建虚假广告,测试单调性
    items=[]
    #创建一个空列表
    for item in dev_df[['aid','bid','crowd_direction', 'delivery_periods','imp']].values:
    #产生一个遍历,item是一个对应numpy的数组,每次循环对应一行dev_df中'aid','bid','crowd_direction', 'delivery_periods','imp'属性列的值。
        item=list(item)
        #将numpy格式的item转换为列表格式
        items.append(item+[1])
        #为为列表增加新的元素1,作用是标记其为真是数据,同时将整个列表加入到items中,作为一个数据
        for i in range(10):
        #i从0-9产生一个遍历
            while True:
                t=random.randint(0,2*item[1])
                #在python中的random.randint(a,b)用于生成一个指定范围内的整数。这里将产生一个0到2*bid的之间的一个随机整数
                if t!=item[1]:
                #如果产生的数不等于bid值
                    items.append(item[:1]+[t]+item[2:]+[0])
                    #构造一个广告id等于之前id,出价为t,'crowd_direction', 'delivery_periods'都与之前一样的新数据,同时在数据最后加0元素作为标记,标记其为构造的虚假数据
                    break
                    #直到产生一个虚假数据为止,跳出一个循环
                else:
                    continue
                    #继续内层循环


	#每一个真是数据,产生了10个由其产生的虚假数据,这些数据仅仅是出价不同
    dev_df=pd.DataFrame(items)
    #将items转换为dataframe结构
    dev_df.columns=['aid', 'bid', 'crowd_direction', 'delivery_periods','imp','gold'] 
    #重新命名列
    del items
    #删除内存中的items
    gc.collect()
    #内存清理
    print(dev_df.shape)
    #输出验证集大小
    print(dev_df['imp'].mean(),dev_df['bid'].mean())
    #输出验证集的曝光量平均,和出价平均
    return dev_df
    #返回验证集


print("parsing raw data ....")
parse_rawdata() 
#调用函数parse_rawdata() ,生成测试数据,用户属性数据,广告静态数据等等对应的dataframe格式

print("construct log ....")
train_df,dev_df=construct_log()
#构建训练数据和验证数据集

print("construct train data ....")
train_df,train_dev_df=construct_train_data(train_df)
#构建训练数据集和训练验证数据集
print("construct dev data ....")
dev_df=construct_dev_data(dev_df)
#构建验证数据集

print("load test data ....")
test_df=pd.read_pickle('data/testA/test_sample.pkl')
#构建测试数据集
print("combine advertise features ....")
ad_df =pd.read_pickle('data/testA/ad_static_feature.pkl')
train_df=train_df.merge(ad_df,on='aid',how='left')
train_dev_df=train_dev_df.merge(ad_df,on='aid',how='left')
dev_df=dev_df.merge(ad_df,on='aid',how='left')
#合并广告训练数据和静态文件数据集
print("save preprocess data ....")
train_dev_df.to_pickle('data/train_dev.pkl')
train_df.to_pickle('data/train.pkl')
dev_df.to_pickle('data/dev.pkl')
test_df.to_pickle('data/test.pkl')
#将上述数据集存成对应的pickle格式,方便下次读取
print(train_dev_df.shape,dev_df.shape)
print(train_df.shape,test_df.shape)

train_dev_df 是17973号以前(不含17973)的数据,train_df是包含17973所有的数据,dev是17974号的数据。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值