Preprocess Criteo dataset. This dataset was used for the Display Advertising
Challenge (https://www.kaggle.com/c/criteo-display-ad-challenge).
第1列就是标签(点击与否用0/1表示,1为点击,0为没点击)。后面的2-40列数据(共39列)是我们的特征变量(指标),也就是原文paper里面提到的“n-field”的概念,这里的n是39。
然后数据内又分了前13列是连续型变量,后26列是类别型变量。
continous_features = range(1, 14) # [1,...13]
categorial_features = range(14, 40) # [14,...39]
将39列的每一列做为独立的输入之后再合并,所以根据每一列建立索引字典。建立好之后根据索引字典将原始数据(上面的数据视图呈现那样)映射到数字空间,即每个值都代表着索引字典里面的索引,可以根据索引找到原来的值。
首先要知道每个类别特征的特征个数。连续特征的特征个数为1。因为在特征索引中,不同的连续值对应一个特征位,类别特征每种情况对应一个特征位。
1、类别特征维度统计
categorial_features = [14,...39]
num_feature = len(categorial_features)
dicts = []
for i in range(0, num_feature):
dicts.append(collections.defaultdict(int)) # defaultdict(int) 如果key不存在的时候,则赋值为int类型,值0。
with open(‘train.txt‘, ‘r‘) as f: # 读取文件,遍历行,针对所有类别特征,如果有值。则以该值为key的字典的value加1。
for line in f:
features = line.rstrip(‘\n‘).split(‘\t‘)
for i in range(0, num_feature):
if features[categorial_features[i]] != ‘‘:
dicts[i][features[categorial_features[i]]] += 1
得到每个类别特征的个数统计之后,进行后续处理。dict[i]
表示第i个类别特征的统计字典。
for i in range(0, num_feature):
dicts[i] = filter(lambda x: x[1] >= 2,
dicts[i].items()) # 过滤掉只出现过一次的类别特征。
dicts[i] = sorted(dicts[i], key=lambda x: (-x[1], x[0])) ## 第二个元素的负数, 如果第二个元素相等,则基于第1个元素。皆为正序
vocabs, _ = list(zip(*dicts[i])) # vocabs:tuple. 第i种类别特征的所有情况组成的元组。
dicts[i] = dict(zip(vocabs, range(1, len(vocabs) + 1))) # 得到 {特征:索引}的字典
dicts[i][‘<unk>‘] = 0 # 赋值未知特征为0。
dict_size = [len(self.dicts[idx]) for idx in range(0, self.num_feature)] # 26个类别特征,每个特征包含多少个不同的类别。
sizes = [1] * len(continous_features) + dict_sizes
sizes = [str(i) for i in sizes] # sizes 保存了所有特征的维度。
2、索引构建
categorial_feature_offset = [0] # 因为每个连续特征有1个占位,每种类别特征有自己的N维特征,所以在确定特征 xxx的索引的时候,需要加上它之前的offset。
for i in range(1, len(categorial_features)): # 第i个类别特征的起始索引为:categorial_feature_offset[i]。
offset = categorial_feature_offset[i - 1] + dict_sizes[i - 1]
categorial_feature_offset.append(offset)
前面得到了特征长度和离散特征索引起始位置,可以构建最后的特征索引和特征值
原文:https://www.cnblogs.com/leimu/p/14600827.html