- 赛题背景(说明)
OGeek算法比赛:属于在实时搜索场景下搜索结果ctr预估
流程:在用户在搜索框中输入搜索内容的同时,根据输入的结果,不断返回查询结果,针对查询结果,判断用户是否实现 点击操作;
image.png
字段的详细介绍在数据分析中;
2.数据分析
1)数据规模:
初赛数据约235万,训练集200万,验证集5万,
A榜测试集5万,B榜测试集25万;
2)数据说明:
image.png
3)比赛要求:
1.禁止人工标注/修改评测结果数据;
2.模型数量不多于2个(同一网络结构不同参数认为是不同模型)
4)评价标准
F1分数(衡量二分类模型精确度的一种指标,可以认为是模型准确率和召回率的平均,取值返回介于0-1)
公式:
image.png
3.数据分析
1)特征数据:分析数据中是否存在空值、异常值等需要处理;
2)标签数据:标签是否含有异常值,对标签处理;
# coding=utf-8
import pandas as pd
# 1.加载数据
train_data = pd.read_csv('./data/oppo_round1_train_20180929.txt', names=['prefix', 'query_prediction', 'title', 'tag', 'label'], header=None, encoding='utf-8', delimiter='\t').astype(str)
val_data = pd.read_csv('./data/oppo_round1_vali_20180929.txt', names=['prefix', 'query_prediction', 'title', 'tag', 'label'], header=None, encoding='utf-8', delimiter='\t').astype(str)
test_data = pd.read_csv('./data/oppo_round1_test_A_20180929.txt', names=['prefix', 'query_prediction', 'title', 'tag'], header=None, encoding='utf-8', delimiter='\t').astype(str)
# 2.分析数据
# 2.1 数据基本信息
print(train_data.head())
print(train_data.info())
print(train_data.describe())
# 2.2 特征数据是否存在异常数据
print(train_data.isnull().sum()) # 统计列中空的个数
print(val_data.isnull().sum())
print(test_data.isnull().sum())
# 2.3 标签的处理
print(train_data['label'].value_counts())
print(val_data['label'].value_counts())
# 在训练集的标签中,存在一行的标签为'音乐',删除该行数据;
train_data = train_data[train_data['label'] != '音乐']
test_data['label'] = -1
# 将数据的标签转为int类型
train_data = pd.concat([train_data, val_data])
train_data['label'] = train_data['label'].apply(lambda x: int(x))
test_data['label'] = test_data['label'].apply(lambda x: int(x))
- 建立词向量模型
1)下载语料
https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2
2)转化语料格式(下载的语料为.xml文件,将其转为.txt文件)
代码使用Terminal运行,需要输入三个参数:
①运行的代码文件名
② 输入文件名(.xml文件)
③ 输出文件名(.txt文件)
格式如:python process_wiki.py zhwiki-latest-pages-articles.xml.bz2 wiki.zh.txt
# -*- coding: utf-8 -*-
import logging
import os.path
import sys
from gensim.corpora import WikiCorpus
if __name__ == '__main__':
program = os.path.basename(sys.argv[0])
# 使用日志
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))
# check and process input arguments
if len(sys.argv) < 3:
print globals()['__doc__'] % locals()
sys.exit(1)
inp, outp = sys.argv[1:3]
space = " "
i = 0
output = open(outp, 'w')
wiki = WikiCorpus(inp, lemmatize=False, dictionary={})
for text in wiki.get_texts():
output.write(space.join(text) + "\n")
i = i + 1
if (i % 10000 == 0):
logger.info("Saved " + str(i) + " articles")
output.close()
logger.info("Finished Saved " + str(i) + " articles")
3)分词
使用同上,输入四个参数:
① 文件名
② 语料文件名
③ 模型名
④ 向量文件名
格式如:python train_word2vec_model.py wiki.zh.txt wiki.zh.text.model wiki.zh.text.vector
# -*- coding: utf-8 -*-
import logging
import os.path
import sys
import multiprocessing
from gensim.corpora import WikiCorpus
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
if __name__ == '__main__':
program = os.path.basename(sys.argv[0])
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))
# check and process input arguments
if len(sys.argv) < 4:
print globals()['__doc__'] % locals()
sys.exit(1)
inp, outp1, outp2 = sys.argv[1:4]
model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5,
workers=multiprocessing.cpu_count())
# trim unneeded model memory = use(much) less RAM
#model.init_sims(replace=True)
model.save(outp1)
model.save_word2vec_format(outp2, binary=False)
4.特征挖掘
主要使用的特征如下介绍:
由于在该数据集中(验证集以及测试集)中,存在新数据和旧数据两种数据(新数据指的是,该数据没有在训练集中出现过),分布满足4:1的比例,由于存在这样的数据分布,导致在新数据上,统计特征呈现高度稀疏的状况(出现大量的0),所以在构造特征时,考虑在前4/5上,使用基础特征+统计特征,而在后1/5上,使用基础特征+其他特征;
(这可以认为是比赛的"数据泄露",如果能够发现这个问题,对分数能有很大的提升)
5.模型使用
1)针对特征数据存在的问题,分别训练模型(前4/5和后1/5),完成预测;
2)由于训练数据量比较少,所以在训练时,加入验证数据,对测试数据的预测效果有所提升;
# 4.2 划分训练和验证集
test_size = 0.2
seed = 25
train_x,test_x,train_y,test_y = train_test_split(X,y,test_size=test_size,random_state=seed)
# 4.3.训练模型
params = {
'boosting_type': 'gbdt',
'objective': 'binary',
'metric': {'binary_logloss', 'auc'},
'num_leaves': 95,
'max_depth': 5,
'min_data_in_leaf': 450,
'learning_rate': 0.05,
'feature_fraction': 0.9,
'bagging_fraction': 0.95,
'bagging_freq': 5,
'lambda_l1': 1,
'lambda_l2': 0.001, # 越小l2正则程度越高
'min_gain_to_split': 0.2,
'verbose': 5,
'is_unbalance': True
#二者都是处理数据不平衡问题,使用一个即可; 'scale_pos_weight': (np.sum(train_y==0)/np.sum(train_y==1)), # 用来处理正负样本不均衡的问题,通常取:sum(negative cases) / sum(positive cases)
}
train_set = lgb.Dataset(train_x,train_y)
eval_set = lgb.Dataset(test_x,test_y)
gbm = lgb.train(params,train_set=train_set,num_boost_round=5000,valid_sets=eval_set,early_stopping_rounds=50)
6.比赛总结
1)在比赛刚开始的时候,可以使用GBDT+统计特征做Baseline;
2)不断的挖掘新的特征,查看预测的效果;
3)可以考虑使用多种语料库来训练词向量模型,提高相似度的度量能力;
4)可以尝试使用神经网络组合GBDT构造深度预测模型,或者使用FM系以及Xgboost或GBDT挖掘新特征;
5)由于模型的限制,无法有效利用集成的方法提升;
网友评论