天池- IJCAI-18 阿里妈妈搜索广告转化预测新手入门经历(一:数据预处理、特征工程)
第一次正式参加数据挖掘类的比赛,投入了三个星期。结果没有进入复赛,但是学到了许多经验。感谢技术圈和github的大佬们提供的baseline,让我少走了很多弯路。
第一次写博客,其一为了防止以后忘记,其二如果萌新能帮到萌新新们也是很开心啦。
思路:全文按照数据预处理、特征工程和模型融合讲解,并附有代码。
数据预处理
1 导入库和读取数据
1.1导入库:
import pandas as pd
import numpy as np
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss
from sklearn import preprocessing
import warnings
from sklearn.grid_search import GridSearchCV
warnings.filterwarnings("ignore")
from sklearn.model_selection import StratifiedKFold
import time
from itertools import product
import copy
import itertools
import seaborn as sns
1.2读取测试集和训练集:
train是训练数据,test是需要预测的测试集(这里用的是B榜的test_b)。
分析数据时会发现训练集中有少量样本'instance_id'字段重复,但在比赛B榜的test_b中也有重复样本,所以不进行去重(被注释的那一行是去重操作)。
train = pd.read_csv(r'C:\Users\Lee\Desktop\round\origin_data\round1_ijcai_18_train_20180301.txt', sep="\s+")
test = pd.read_csv(r'C:\Users\Lee\Desktop\round\origin_data\round1_ijcai_18_test_b_20180418.txt', sep="\s+")
data = pd.concat([train, test])
#data = data.drop_duplicates(subset='instance_id')
data = data.reset_index(drop = True)
2 数据预处理
2.1文本类特征处理
数据有3个文本类型特征item_category_list、item_property_list和predict_category_property,使用split分割。
item_category_list特征有3个字段,第一个字段所有数据一样,所以取range(1,3)
item_property_list特征有100个字段,各字段之间无从属关系,由于后面字段缺失值太多,所以取range(19)
predict_category_property特征有14个字段,有从属关系,同样是后面字段缺失值太多取range(5)
缺失值如果过多,样本不足,在对该特征做进一步的统计时,很容易造成误判,例如在52万条样本中该字段只有100条样本,里面有取值为'A'的3条样本全部点击了广告。那么在预测时就很有可能直接判定取值为'A'的广告会被点击。
并使用LabelEncoding进行编码。
lbl = preprocessing.LabelEncoder()for i in range(1, 3):data['item_category_list' + str(i)] = lbl.fit_transform(data['item_category_list'].map(lambda x: str(str(x).split(';')[i]) if len(str(x).split(';')) > i else '')) # item_category_list的第0列全部都一样for i in range(19):data['item_property_list' + str(i)] = lbl.fit_transform(data['item_property_list'].map(lambda x: str(str(x).split(';')[i]) if len(str(x).split(';')) > i else '')) for i in range(7):data['predict_category_property' + str(i)] = lbl.fit_transform(data['predict_category_property'].map(lambda x: str(str(x).split(';')[i]) if len(str(x).split(';')) > i else ''))
2.2时间戳处理
数据中的时间是以时间戳(context_timestamp)形式存在,进行如下处理提取日期和时间
data['realtime'] = data['context_timestamp'].apply(lambda x:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(x)))data['realtime'] = pd.to_datetime(data['realtime'])data['day'] = data['realtime'].dt.daydata['hour'] = data['realtime'].dt.hour
3特征工程
3.1长度特征
每条样本的3个文本特征的长度不一样,其中也许包含了一些信息。例如商品的属性列表很详细,可能是比较精细的产品,例如电脑和显卡两种商品,电脑参数包括CPU/显卡/内存等多项信息,显然比显卡复杂,那么电脑的属性长度可能为50,而显卡只有10,50和10就可以反映商品的一些信息。
因此长度特征可以描述商品的种类。
data['len_item_category'] = data['item_category_list'].map(lambda x: len(str(x).split(';')))data['len_item_property'] = data['item_property_list'].map(lambda x: len(str(x).split(';')))data['len_predict_category_property'] = data['predict_category_property'].map(lambda x: len(str(x).split(';')))
3.2基于商店质量的shop分段特征
shop中有4个连续型特征:shop_score_description、shop_score_delivery、
shop_score_service、shop_review_positive_rate
以shop_score_description为例,一条样本的取值是0.9632654,我们期望得知这个取值在总体样本中得分是处于什么样的一个水平。就需要进行分段,代码中0,1,2代表较差、一般、优秀3个等级,这里0.9632654被划分为较差,对应取值为0。
分段还有一个好处就是可以和其他特征进行组合,后面会提到。
data['shop_score_description0'] = data['shop_score_description'].apply(lambda x: 2 if x > 0.984 else x)data['shop_score_description0'] = data['shop_score_description0'].apply(lambda x: 1 if 0.984 >= x > 0.97 else x)data['shop_score_description0'] = data['shop_score_description0'].apply(lambda x: 0 if x <= 0.97 else x)data['shop_score_delivery0'] = data['shop_score_delivery'].apply(lambda x: 2 if x > 0.979 else x)data['shop_score_delivery0'] = data['shop_score_delivery0'].apply(lambda x: 1 if 0.979 >= x > 0.966 else x)data['shop_score_delivery0'] = data['shop_score_delivery0'].apply(lambda x: 0 if x <= 0.966 else x)data['shop_score_service0'] = data['shop_score_service'].apply(lambda x: 2 if x > 0.979 else x)data['shop_score_service0'] = data['shop_score_service0'].apply(lambda x: 1 if 0.979 >= x > 0.967 else x)data['shop_score_service0'] = data['shop_score_service0'].apply(lambda x: 0 if x <= 0.967 else x)data['shop_review_positive_rate0'] = data['shop_review_positive_rate'].apply(lambda x: 2 if x == 1 else x)data['shop_review_positive_rate0'] = data['shop_review_positive_rate0'].apply(lambda x: 1 if 1 > x > 0.98 else x)data['shop_review_positive_rate0'] = data['shop_review_positive_rate0'].apply(lambda x: 0 if x <= 0.98 else x)
3.3基于历史点击率的分段特征
以user_age_level为例,我们观察该特征和是否点击is_trade的图:
sns.pointplot(x='user_age_level', y='is_trade', data=data)
可以看到点击率随着用户年龄上升而上升。这说明年龄在1005的用户最容易点击广告,可以脑补一下:1005应该对应的年龄是40-50岁之间,这个阶段的用户有经济实力,工作比较稳定(上班比较悠闲),有较强的点击广告的动机。
user_age_level这个特征区分度很高,很好地反映了年纪越大点击率越高这一信息,就可以不用做分段。
再看店铺评价数量等级shop_review_num_level和is_trade的关系:
就不如用户年龄那样呈明显的线性关系了,这个时候就可以进行分段。
def review_num(x):if (x==1)|(x==22)|(x==25):return 1elif ((x>=3)&(x<=5))|(x==23):return 2else:return 3
data['shop_review_num_level'] = data['shop_review_num_level'].apply(review_num)
现在我们可以看看分段后的效果
sns.pointplot(x='shop_review_num_level', y='is_trade', data=data)
可以发现这一特征对'is_trade'的区分度提高了。即shop_review_num_level为3的点击概率很大,这一信息相比分段前能够更好地帮助模型做判断。
但是要注意这种特征本质上是带有穿越性的,我统计的是整个数据集中shop_review_num_level的点击率。data包括7月18-25用户是否点击广告的所有样本,而在判断单条7月20日的样本是否点击广告的时候,是无法知道20日后面的用户的行为的。
所以说,这种带有穿越性的特征十分容易导致过拟合,相当于拿着试卷答案在做试卷。在后面的统计特征中更要注意这一点。
3.4基于点击率的特征
如果我们能够知道某件商品以前的点击率。极端点说,如果有一个特征item_brand_id中为'豪牛'的牛奶品牌的广告,以前推送了100条广告,没有一个用户点击,点击率就为0。而另一个为'大草原'的牛奶品牌推送了50条广告,有25名用户点击,点击率为0.5。
那么在后面的预测中可以推断'豪牛'的广告大概率不会被点击,'大草原'的广告有50%的几率会被点击。并且两个品牌的点击率的可信度也是不一致的,'豪牛'样本量大,可信度自然会高。
所以应该统计两个信息:该广告的历史推送条数、该广告的历史点击率
def get_cnt(data,col_name):''' Descr:输入:带有日期特征的数据集data,特征名称col_name输出:带有两个新特征的data:该特征的历史推送次数:col_name+'_cnt'该特征的历史点击率:col_name+'_cntrate11''''user_cnt = data.groupby(by=[col_name,'day'])['is_trade'].agg({col_name+'_cnt': 'count'})user_cnt = user_cnt.unstack()user_cnt.fillna(0,inplace=True)user_cnt = user_cnt.reindex_axis(sorted(user_cnt.columns), axis=1)user_cnt = user_cnt.cumsum(axis=1)user_cnt = user_cnt.stack()user_cnt = user_cnt.reset_index()user_cnt['day'] = user_cnt['day'].map(lambda x: x+1)user_cnt1 = data.groupby(by=[col_name,'day','is_trade']).agg( 'size')user_cnt1 = user_cnt1.unstack(level=['is_trade','day'])user_cnt1 = user_cnt1[:][1]user_cnt1.fillna(0,inplace=True)day_list = user_cnt1.columns.tolist()user_cnt1 = user_cnt1.reindex_axis(sorted(day_list), axis=1)user_cnt1 = user_cnt1.cumsum(axis=1)user_cnt1 = user_cnt1.stack()user_cnt1 = user_cnt1.reset_index()user_cnt1.columns = [col_name,'day',col_name+'_cntrate11']user_cnt1['day'] = user_cnt1['day'].map(lambda x: x+1)data = pd.merge(data,user_cnt,on=[col_name,'day'],how='left')data = pd.merge(data,user_cnt1,on=[col_name,'day'],how='left')data[col_name+'_cntrate11'] = data[col_name+'_cntrate11']/data[col_name+'_cnt']
# del data[col_name+'_cnt']return data
def get_all_cnt(data):''' Descr:输入:数据data,统计函数get_cnt(data,col_name)需要统计的特征列表(此处函数内部已定义)输出:包含每个特征的历史点击率、历史推送次数的data'''item_name = ['item_sales_level', 'item_price_level', 'item_collected_level','item_pv_level','item_brand_id','item_city_id']user_name = ['user_gender_id','user_age_level','user_occupation_id','user_star_level']shop_name = ['shop_review_num_level','shop_star_level',]id_name = ['user_id','item_id','shop_id','context_page_id']all_name = item_name+id_name+user_name+shop_name+['hour']for col_name in all_name:print('------>正在统计单一特征:'+col_name)data = get_cnt(data,col_name)return data
调用:
data = get_all_cnt(data)
3.5基于组合特征的点击率特征
该特征统计的是两个特征组合起来的历史点击率和推送次数。
例如:'item_brand_id'为'大草原'品牌和‘user_age_level’为'1005'时的点击率为0.01,
'item_brand_id'为'大草原'品牌和‘user_age_level’为'1007'时的点击率为0.8
两条样本对比来看,包含了'大草原'品牌可能主打老年奶粉,许多老年人(user_age_level’=1007)的用户会点击这条广告这一信息。
def get_cross_cnt2(data,col_name,base_name):''' Descr:输入:数据data,需要组合的特征名col_name,base_name,无先后顺序输出:含有该组合特征的历史推送次数col_name+'_'+base_name+'_cnt'历史点击率col_name+'_'+base_name+'_cross_cntrate11'example:col_name = 'item_brand_id'base_name = 'item_id''''cnt = data.groupby(by = [col_name,base_name,'day'])['is_trade'].agg({col_name+'_'+base_name+'_cnt':'count'})cnt = cnt.unstack()cnt.fillna(0,inplace=True)cnt = cnt.reindex_axis(sorted(cnt.columns),axis = 1)cnt = cnt.cumsum(axis = 1)cnt = cnt.stack()cnt = cnt.reset_index()cnt['day'] = cnt['day'].map(lambda x : x+1)cnt1 = data.groupby(by=[col_name,base_name,'day','is_trade']).agg('size')cnt1 = cnt1.unstack(level=['is_trade','day'])cnt1 = cnt1[:][1]cnt1.fillna(0,inplace=True)cnt1 = cnt1.reindex_axis(sorted(cnt1.columns.tolist()),axis = 1)cnt1 = cnt1.cumsum(axis = 1)cnt1 = cnt1.stack()cnt1 = cnt1.reset_index()cnt1.columns = [col_name,base_name,'day',col_name+'_'+base_name+'_cross_cntrate11']cnt1['day'] = cnt1['day'].map(lambda x:x+1)data = pd.merge(data,cnt,on=[col_name,base_name,'day'],how='left')data = pd.merge(data,cnt1,on=[col_name,base_name,'day'],how='left')data[col_name+'_'+base_name+'_cross_cntrate11'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[col_name+'_'+base_name+'_cnt']
# del data[col_name+'_'+base_name+'_cnt']return data
这里有两个小问题
第一,组合特征的方式
特征可以分为三大类user,shop,item
那么组合特征有两种方式:
1、按照大类的特征进行组合(大类属性内部不进行组合,不会出现user_age_level_user_gender_level这样的组合特征):
user_xxx_item_xxx
user_xxx_shop_xxx
item_xxx_shop_xxx
2、不按照大类属性,所有特征两两组合:
相比第一种会多出:
item_xxx_item_xxx
user_xxx_user_xxx
shop_xxx_shop_xxx
在使用lgb输出importance时可以发现第二种组合更优秀。
第二,统计组合特征时还可以统计的一些信息
对于两个特征col和base,有如下6个单一统计特征:
[col]推送次数
[base]推送次数
[col_base]推送次数
[col_base]点击次数
[col]点击次数
[base]点击次数
前面统计了单一特征的历史点击率:
[col]点击次数 / [col]推送次数
[base]点击次数 / [base]推送次数
以及组合特征的历史点击率:
[col_base]点击次数 / [col_base]推送次数
实际上还可以统计的特征有:
[col_base]推送次数 / [col]推送次数
[col_base]推送次数 / [base]推送次数
[col_base]点击次数 / [col]点击次数
[col_base]点击次数 / [base]点击次数
前面两个从商家角度(广告推送者)出发,统计商家的市场占有率、推广程度,
后面两个从用户角度(是否点击)出发,统计用户对产品的喜爱程度。
例如col = 'item_brand_id' , base = 'item_city_id'
[col_base]推送次数 / [col]推送次数,以第一行的0.8为例,
在这里的意义就是:大草原在北京和上海都投放了广告,但是大草原主打北京,在北京投放了80%的广告。
[col_base]推送次数 / [base]推送次数,以第一行的0.66为例,
在北京一共投放了10条广告,其中大草原投放了66%的广告,而竞争对手豪牛投放了33%的广告。
同理,后面两个公式可以统计用户对大草原的点击率和豪牛的点击率
但是在实际应用中效果不好,所以没有统计。
def get_cross_cnt(data,col_name,base_name):'''Descr:输入数据data,输出5个统计信息:[col_base]点击次数 / [col_base]推送次数[col_base]推送次数 / [col]推送次数[col_base]推送次数 / [base]推送次数[col_base]点击次数 / [col]点击次数[col_base]点击次数 / [base]点击次数example:col_name = 'item_brand_id'base_name = 'item_id''''cnt = data.groupby(by = [col_name,base_name,'day'])['is_trade'].agg({col_name+'_'+base_name+'_cnt':'count'})cnt = cnt.unstack()cnt.fillna(0,inplace=True)cnt = cnt.reindex_axis(sorted(cnt.columns),axis = 1)cnt = cnt.cumsum(axis = 1)cnt = cnt.stack()cnt = cnt.reset_index()cnt['day'] = cnt['day'].map(lambda x : x+1)cnt1 = data.groupby(by=[col_name,base_name,'day','is_trade']).agg('size')cnt1 = cnt1.unstack(level=['is_trade','day'])cnt1 = cnt1[:][1]cnt1.fillna(0,inplace=True)cnt1 = cnt1.reindex_axis(sorted(cnt1.columns.tolist()),axis = 1)cnt1 = cnt1.cumsum(axis = 1)cnt1 = cnt1.stack()cnt1 = cnt1.reset_index()cnt1.columns = [col_name,base_name,'day',col_name+'_'+base_name+'_cross_cntrate11']cnt1['day'] = cnt1['day'].map(lambda x:x+1)data = pd.merge(data,cnt,on=[col_name,base_name,'day'],how='left')data = pd.merge(data,cnt1,on=[col_name,base_name,'day'],how='left')# col_name的单特征量cnt_col = data.groupby(by = [col_name,'day'])['is_trade'].agg({col_name+'_cnt':'count'})cnt_col = cnt_col.unstack()cnt_col.fillna(0,inplace=True)cnt_col = cnt_col.reindex_axis(sorted(cnt_col.columns),axis = 1)cnt_col = cnt_col.cumsum(axis = 1)cnt_col = cnt_col.stack()cnt_col = cnt_col.reset_index()cnt_col['day'] = cnt_col['day'].map(lambda x : x+1)cnt_col1 = data.groupby(by=[col_name,'day','is_trade']).agg( 'size')cnt_col1 = cnt_col1.unstack(level=['is_trade','day'])cnt_col1 = cnt_col1[:][1]cnt_col1.fillna(0,inplace=True)cnt_col1 = cnt_col1.reindex_axis(sorted(cnt_col1.columns.tolist()), axis=1)cnt_col1 = cnt_col1.cumsum(axis=1)cnt_col1 = cnt_col1.stack()cnt_col1 = cnt_col1.reset_index()cnt_col1.columns = [col_name,'day',col_name+'_cntrate11']cnt_col1['day'] = cnt_col1['day'].map(lambda x: x+1)data = pd.merge(data,cnt_col,on=[col_name,'day'],how='left')data = pd.merge(data,cnt_col1,on=[col_name,'day'],how='left')# base_name的单特征量cnt_base = data.groupby(by = [base_name,'day'])['is_trade'].agg({base_name+'_cnt':'count'})cnt_base = cnt_base.unstack()cnt_base.fillna(0,inplace=True)cnt_base = cnt_base.reindex_axis(sorted(cnt_base.columns),axis = 1)cnt_base = cnt_base.cumsum(axis = 1)cnt_base = cnt_base.stack()cnt_base = cnt_base.reset_index()cnt_base['day'] = cnt_base['day'].map(lambda x : x+1)cnt_base1 = data.groupby(by=[base_name,'day','is_trade']).agg( 'size')cnt_base1 = cnt_base1.unstack(level=['is_trade','day'])cnt_base1 = cnt_base1[:][1]cnt_base1.fillna(0,inplace=True)cnt_base1 = cnt_base1.reindex_axis(sorted(cnt_base1.columns.tolist()), axis=1)cnt_base1 = cnt_base1.cumsum(axis=1)cnt_base1 = cnt_base1.stack()cnt_base1 = cnt_base1.reset_index()cnt_base1.columns = [base_name,'day',base_name+'_cntrate11']cnt_base1['day'] = cnt_base1['day'].map(lambda x: x+1)data = pd.merge(data,cnt_base,on=[base_name,'day'],how='left')data = pd.merge(data,cnt_base1,on=[base_name,'day'],how='left')# col_name+'_'+base_name+'_cross_cntrate11'data[col_name+'_'+base_name+'_cb'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[col_name+'_'+base_name+'_cnt']data[col_name+'_'+base_name+'_cb_c'] = data[col_name+'_'+base_name+'_cnt']/data[col_name+'_cnt']data[col_name+'_'+base_name+'_cb_b'] = data[col_name+'_'+base_name+'_cnt']/data[base_name+'_cnt']data[col_name+'_'+base_name+'_cb_c1'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[col_name+'_cntrate11']data[col_name+'_'+base_name+'_cb_b1'] = data[col_name+'_'+base_name+'_cross_cntrate11']/data[base_name+'_cntrate11']del data[col_name+'_'+base_name+'_cnt']del data[col_name+'_cnt']del data[base_name+'_cnt']del data[col_name+'_'+base_name+'_cross_cntrate11']del data[col_name+'_cntrate11']del data[base_name+'_cntrate11']return data
3.6其他一些效果不太好的特征
3.6.1对离散型特征字符串化,再累加的组合特征
比如user_gender_id='1',user_age_level='2'
那么组合特征'12'就代表着中年('2')女性('1')的含义。
忽然想到,有一个问题是代码只对特征做简单的LabelEncoding处理,假设第一个特征取值为1-2000,第二个特征取值为1-100,那么'2213'实际上可能有多种字符串拼接方式:
'2'+'213'
'22'+'13'
'221'+'3'
都是这一特征,也许这就是效果不好的原因吧,下次比赛的时候再试试。
def zuhe(data):'''Desr:输入:数据data1、使用preprocessing.LabelEncoder()使特征在一个小区间内2、转换int行特征为str3、两两字符型特征累加输出:字符串组合特征example:item_brand_id:'2'item_city_id:'1'zuhe_feature:21'''print('3.zuhe')print('-------------------把缺失值-1替换为0----------------------')
# for col in ['user_gender_id','user_age_level','user_occupation_id','user_star_level']:
# data[col] = data[col].apply(lambda x: 0 if x == -1 else x)print('-----------声明item,shop,user,hour四个块中的特征名----------')item_category_list_name = ['item_category_list'+str(i) for i in range(1,3)]item_property_list_name = ['item_property_list'+str(i) for i in range(19)]predict_category_property_name = ['predict_category_property'+str(i) for i in range(5)]item_name = ['item_sales_level', 'item_price_level', 'item_collected_level','item_pv_level','item_city_id','item_brand_id']item_name = item_name+item_category_list_name+item_property_list_name+predict_category_property_nameuser_name = ['user_gender_id','user_age_level','user_occupation_id','user_star_level']shop_name_old = ['shop_review_num_level','shop_review_positive_rate','shop_star_level','shop_score_service','shop_score_delivery','shop_score_description']id_name = ['user_id','item_id','shop_id','item_brand_id','item_city_id','context_page_id']
# ui_name = user_name+item_name
# si_name = shop_name + item_name
# su_name = shop_name + user_namenew_name = []lbl = preprocessing.LabelEncoder()print('-------------------user_name的fit_transform------------------')for ucol in user_name:data[ucol] = lbl.fit_transform(data[ucol]).astype(str)print('-------------------item_name的fit_transform------------------------')for icol in item_name:data[icol] = lbl.fit_transform(data[icol]).astype(str)print('-------------------id_name的fit_transform------------------------')for idcol in id_name:data[idcol] = lbl.fit_transform(data[idcol]).astype(str)print('-------------------对shop进行分段------------------------')shop_name = []for scol in shop_name_old:data['fenduna_'+scol] = pd.cut(data[scol],10,labels=[str(i) for i in range(1,11)])shop_name.append('fenduna_'+scol)print('--------------------hour_astype(str)------------------------')data['hour'] = data['hour'].astype(str)print('-------------------user和item_id特征------------------------')for uicol in itertools.product(user_name,item_name):data[uicol[0]+'_'+uicol[1]] = lbl.fit_transform(data[uicol[0]]+data[uicol[1]])new_name.append(uicol[0]+'_'+uicol[1])'''*******user+shop很废*******'''
# print('------------------user和shop特征-----------------------')
# for sucol in itertools.product(shop_name,user_name):
# data[sucol[0]+'_'+sucol[1]] = lbl.fit_transform(data[sucol[0]]+data[sucol[1]])
# new_name.append(sucol[0]+'_'+sucol[1]) print('------------------item和shop特征-----------------------')for iscol in itertools.product(shop_name,item_name):data[iscol[0]+'_'+iscol[1]] = lbl.fit_transform(data[iscol[0]]+data[iscol[1]])new_name.append(iscol[0]+'_'+iscol[1]) '''*******id+user/item/shop很废*******'''
# print('------------------id和user特征-----------------------')
# for iducol in itertools.product(id_name,user_name):
# data[iducol[0]+'_'+iducol[1]] = lbl.fit_transform(data[iducol[0]]+data[iducol[1]])
# new_name.append(iducol[0]+'_'+iducol[1])
# print('------------------id和item特征-----------------------')
# for idicol in itertools.product(id_name,item_name):
# data[idicol[0]+'_'+idicol[1]] = lbl.fit_transform(data[idicol[0]]+data[idicol[1]])
# new_name.append(idicol[0]+'_'+idicol[1])
# print('------------------id和shop特征-----------------------')
# for idscol in itertools.product(id_name,item_name):
# data[idscol[0]+'_'+idscol[1]] = lbl.fit_transform(data[idscol[0]]+data[idscol[1]])
# new_name.append(idscol[0]+'_'+idscol[1]) print('--------------------id和hour特征------------------------')for ihcol in id_name:data[ihcol] = lbl.fit_transform(data[ihcol]).astype(str)data[ihcol+'_hour'] = lbl.fit_transform(data[ihcol]+data['hour'])
# data[ihcol] = lbl.fit_transform(data[ihcol]).astype(int)
# new_name.append(ihcol+'_hour')print('--------------------user和hour特征------------------------')for uhcol in user_name:
# data[uhcol] = lbl.fit_transform(data[ihcol]).astype(str)data[uhcol+'_hour'] = lbl.fit_transform(data[uhcol]+data['hour']) print('--------------------item和hour特征------------------------')for ithcol in item_name:
# data[uhcol] = lbl.fit_transform(data[ihcol]).astype(str)data[ithcol+'_hour'] = lbl.fit_transform(data[ithcol]+data['hour']) print('--------------------shop和hour特征------------------------')for shcol in shop_name:
# data[uhcol] = lbl.fit_transform(data[ihcol]).astype(str)data[shcol+'_hour'] = lbl.fit_transform(data[shcol]+data['hour'])
# print('------------------shop和item特征------------------------')
# for scol in shop_name:
# data[scol] = data[scol].astype(str)
# for sicol in itertools.product(shop_name,item_name):
# data[sicol[0]+'_'+sicol[1]] = lbl.fit_transform(data[sicol[0]]+data[sicol[1]])
# new_name.append(sicol[0]+'_'+sicol[1])print('------------------把str换回int,---------')print('-------------------user_name的str_int------------------')for ucol in user_name:data[ucol] = data[ucol].astype(int)print('-------------------item_name的str_int------------------------')for icol in item_name:data[icol] = data[icol].astype(int)print('-------------------id_name的str_int------------------------')for idcol in id_name:data[idcol] = data[idcol].astype(int)print('-------------------shop的str_int------------------------')for scol in shop_name:data[scol] = data[scol].astype(int)print('--------------------hour的str_int------------------------')data['hour'] = data['hour'].astype(int)return data
3.6.2连续性变量的累加特征
对前面提到的4个shop类中的连续型特征进行累加,试过两两累加、三三累加。效果都不好。在这些都不好的组合形式里面,三三累加的效果是最好的。(PS:使用itertools里面的函数可以轻松写循环,就不要写两个for循环嵌套了)
shop_score_description、shop_score_delivery、
shop_score_service、shop_review_positive_rate
3.6.3基于前1小时、前一天的统计特征
前面统计的点击率和推送次数,都是历史数据到目前为止的点击率和推送次数。实际上时间具有衰退效应,所以前1小时、前1天的点击率(用户行为)也许是一个强特征。
3.6.4用户行为
既然提到用户行为,有位大佬提到过一个强特,用户上一次点击到这一次推送出现的时间。但是由这个强特可以扩展到其它的一些可以尝试的特征,用户上一次 被推送/点击 广告到这次 被推送/点击 广告的时间/天数。
时间所限,没有做尝试。
天池- IJCAI-18 阿里妈妈搜索广告转化预测新手入门经历(一:数据预处理、特征工程)相关推荐
- 2018年阿里妈妈搜索广告转化预测
了解数据 提供了user,item,context,shop相关的数据 instance_id不作为特征,但是能看出来,实际上有重复instance_id的数据 item_id 全数据要比train多 ...
- 2篇CIKM详解阿里妈妈搜索广告CTR模型如何低碳瘦身
作为<阿里妈妈搜索广告CTR模型的"瘦身"之路>的姊妹篇,本文将结合团队发表的 CIKM 2021 两篇论文,详解我们在模型瘦身之路上的延续性思考与实践.姊妹篇已经总结 ...
- 阿里妈妈搜索广告CTR模型的“瘦身”之路
前言 随着号称"地表最强"的千亿参数规模GPT-3模型在 NLP 领域横扫各大数据榜单,大力出奇迹的暴力美学似乎成为了大数据场景建模的不二法门.搜索.推荐和广告场景的 CTR 模型 ...
- 一口气放出三篇SIGIR论文!详解阿里妈妈搜索广告CTR模型演进
欢迎关注:阿里妈妈技术公众号 本文作者:石士 阿里妈妈技术团队 1 引子 点击率预估(a.k.a. CTR模型)在搜索.推荐和广告等互联网应用中扮演了至关重要的角色.随着深度学习技术的快速发展,CT ...
- 竞赛|数据竞赛Top解决方案开源整理-科大讯飞AI营销算法、阿里妈妈搜索广告、腾讯广告算法、搜狗的用户画像
https://mp.weixin.qq.com/s/_4QG0dWhh784lF0n1wymcw
- IJCAI-18 阿里妈妈广告转化预测
IJCAI-18 阿里妈妈搜索广告转化预测总结(0.13966,53/5204) 赛题内容 本次比赛以阿里电商广告为研究对象,提供了淘宝平台的海量真实交易数据,参赛选手通过人工智能技术构建预测模型预估 ...
- 【万字干获】阿里妈妈搜索推荐广告预估模型2021思考与实践
省时查报告-专业.及时.全面的行研报告库 省时查方案-专业.及时.全面的营销策划方案库 知识图谱在美团推荐场景中的应用实践 搜索场景下的智能实体推荐 机器学习在B站推荐系统中的应用实践 小红书推荐系统 ...
- 阿里妈妈展示广告预估校准技术演进之路
来源:DataFunTalk本文约6500字,建议阅读15分钟 本文将介绍校准算法在阿里妈妈展示广告中的应用和演进,将从背景介绍.校准算法演进.工程实践以及总结展望四个方面展开介绍. 分享嘉宾:黄思光 ...
- 代码开源!阿里妈妈展示广告Match底层技术架构最新进展
作者:卓立.日涉.谨持 一.背景 大规模信息检索一直是搜推广领域的核心问题之一,而基于任意复杂模型的检索方案无疑是业界重要的迭代方向之一.近年来,阿里妈妈展示广告Match团队与预测引擎团队专注于从算 ...
最新文章
- Java知识积累——String引用的判断问题
- 使用 Pandas、Jinja 和 WeasyPrint,轻松创建一个 PDF 报表
- 课程 | 中科院教授带你快速入门机器学习
- 抖音日活用户破 6 亿,推荐系统到底有何魔力?
- 【UAV】陀螺仪数据分析,以维特智能 JY901B 为例
- torch.flatten()函数
- DCMTK:将XML文档的内容转换为DICOM结构的报告文件
- vagrant boxes
- Redis数据结构——跳跃表-skiplist
- 房地产税迟早要来,而且会带来房价小涨。
- 使用VC做一个简单的UI界面对话框
- 安信可nbiot模块_安信可无线模组
- 如何释放计算机的ip地址,电脑执行释放DNS和更新IP的命令是什么?怎么执行
- 从冬令营到字节跳动,我从ICPCer变身Bytedancer
- Discuz仿魔客吧模板/素材资源站模板/包含DIY文件
- MCtalk对话尚德机构:与教研和大数据结合的AI,才是真功夫
- vue 点击按钮筛选功能_vue实现前端列表多条件筛选
- 石油大P14040存在
- Java Web之Servlet的三大常用作用域对象及其使用方法
- 分销小程序系统开发经营模式介绍