比賽連結:
https://www。
kesci。com/home/competit
ion/5cc51043f71088002c5b8840
這次比賽是我第一次做的涉及nlp方面的比賽,在預選賽之前,我甚至連TF-IDF演算法都沒聽說過,打完之後,瞭解了很多NLP方面的資料處理方法以及分批處理的方式解決部分記憶體不足的問題,可以說是收穫良多。同時十分感謝我的隊友 @Cloudistory (元陽)和 東東,帶我進了複賽,最終排名26 。
正式賽題——文字點選率預估(5月26日開賽)
搜尋中一個重要的任務是根據query和title預測query下doc點選率,本次大賽參賽隊伍需要根據脫敏後的資料預測指定doc的點選率,結果按照指定的評價指標使用線上評測資料進行評測和排名,得分最優者獲勝。
初賽
初賽開始時,我直接先試了預選賽時的思路,TF-IDF + logistics,順便學習了一波分批操作。
submit
=
pd
。
DataFrame
(
columns
=
[
‘query_id’
,
‘query_title_id’
,
‘prediction’
])
data_test
=
pd
。
read_csv
(
‘/home/kesci/input/bytedance/first-round/test。csv’
,
iterator
=
True
,
names
=
test_col
)
with
tqdm
。
tqdm
(
range
(
50
),
‘Predict。。’
)
as
t
:
for
_
in
t
:
try
:
chunk
=
data_test
。
get_chunk
(
chunk_size
)
chunk
[
‘title’
]
。
apply
(
lambda
x
:
x
[:
-
2
])
chunk
[
‘query_title’
]
=
chunk
[
‘query’
]
+
chunk
[
‘title’
]
chunk_list
=
chunk
[
‘query_title’
]
chunk_test
=
tf_idf
。
transform
(
chunk_list
)
y_test
=
lg
。
predict_proba
(
chunk_test
)
chunk
[
‘prediction’
]
=
y_test
[:,
1
]
submit
=
pd
。
concat
([
submit
,
chunk
[[
‘query_id’
,
‘query_title_id’
,
‘prediction’
]]],
ignore_index
=
True
)
except
StopIteration
:
break
試了之後線上只有0。52左右,然後陷入沉思。。。。中間大概停了10天
突然某天看到討論區裡有周周星分享,看到大佬們都用的lgb或NN(lgb能到0。58+,融0。55+的NN能到0。6+),做了統計特徵、相似度特徵,於是也開始慢慢嘗試,瘋狂開腦洞,可奈何就是上不了分,可能我特徵做的太爛了(這裡分數只有0。514)
def find_same(x):
tmp = x。split(‘,’)
query = tmp[0]。split(‘ ’)
title = tmp[1]。split(‘ ’)
same_word = 0
for word in query:
if word in title:
same_word += 1
return same_word
def gen_feature(df):
df[‘query_set_len’] = df[‘query’]。apply(lambda x:len(set(x。split(‘ ’))))
df[‘query_len’] = df[‘query’]。apply(lambda x:len(x。split(‘ ’)))
df[‘title_set_len’] = df[‘title’]。apply(lambda x:len(set(x。split(‘ ’))))
df[‘title_len’] = df[‘title’]。apply(lambda x: len(x。split(‘ ’)))
print(‘split finished’)
df[‘query_title_set_ratio’] = df[‘query_set_len’] / df[‘title_set_len’]
df[‘query_title_ratio’] = df[‘query_len’] / df[‘title_len’]
df[‘query_title_’] = df[‘query’] + ‘,’ + df[‘title’]
df[‘same_word_num’] = df[‘query_title_’]。apply(lambda x:find_same(x))
df[‘same_word_title_ratio’] = df[‘same_word_num’] / df[‘title_len’]
df[‘same_word_query_ratio’] = df[‘same_word_num’] / df[‘query_len’]
df[‘same_word_title_ratio_set’] = df[‘same_word_num’] / df[‘title_set_len’]
# df[‘same_word_query_ratio_set’] = df[‘same_word_num’] / df[‘query_set_len’]
del df[‘query_title_’]
df[‘query_title’] = df[‘query’] + ‘ ’ + df[‘title’]
df[‘query_title_len’] = df[‘query_title’]。apply(lambda x:len(set(x。split(‘ ’))))
df[‘Jaccard’] = df[‘query_title_len’]/(df[‘query_set_len’] + df[‘title_set_len’] - df[‘query_title_len’])。astype(float)
del df[‘query_title’]
return df
df_train = gen_feature(df_train)
print(“train finished”)
df_test = gen_feature(df_test)
print(“test finished”)
後來在討論區看到個有監督的fasttext訓(
https://www。
kesci。com/home/project/
share/8298df5fa3e588f5
),於是開始嘗試使用詞向量,那時候也是各種方法都在嘗試,先是試了試fasttext直接預測,線上0。523,突破了之前的所有分數 orz。。然後嘗試了把fasttext預測的結果作為lgb的特徵輸入,分數又上去了一點,後面又加了點其它什麼特徵,到了0。528之後就又不知道該怎麼做了。後面就一直關注著群裡大佬們的交流,以及討論區的分享,後面偶然與群裡一個老哥交流的時候知道了tfidf+bayes(透過幫別人最佳化程式碼換來的思路,平時做比賽關注執行時記憶體消耗和速度還是有用的),只用title能上0。54,當時直接傻眼了,於是馬上去試了試,取了train的頭2k萬的資料
X_train=train[‘title’]
X_test=test[‘title’]
ngram = 2
vectorizer = TfidfVectorizer(sublinear_tf=True,ngram_range=(1, ngram), max_df=0。6)
X_train=vectorizer。fit_transform(X_train)
X_test=vectorizer。transform(X_test)
y_train=train[‘lable’]
NB_model=GaussianNB()
NB_model。fit(X_train,y_train)
pred=NB_model。predict_proba(X_test)
pred=pred[:,1]
ans=pd。DataFrame({“query_id”:test[‘query_id’],“query_title_id”:test[‘query_id’],“prediction”:pred})
ans。to_csv(‘tdidf_bayes。csv’,header=None,index=None)
然後分數到了0。546,那時候差不多快組隊截止了,然後就到群裡問了下有沒有願意一起組隊的,本來當時想著看看能不能找到0。55+的大佬帶帶我,但是後來還是打消了這個念頭,就與現在的隊友(元陽和東東)組了隊,當時元陽剛剛打完騰訊複賽,東東的lgb在0。542左右 。組完隊之後跟東東交流了一番,又學到了不少詞向量做相似度的知識,聽說是我的做法給了他一些思路,然後沒過幾天他直接打上了0。57,運氣好抱上了大腿。
初賽的時候已經是接近期末考了,幾個當時說好一起做的同學都準備期末考去了,我一直做到組隊後幾天,然後也去準備期末考了,可以說是組隊後基本就沒怎麼幹活了。。有點太對不起隊友了
後面看了看東東lgb的程式碼,感覺都不知自己lgb做的是啥,完全沒法比,還是太菜了orz,然後學到了不少相似度的計算方法,以及詞向量的運用。
複賽
複賽之前,元陽從其它隊伍那裡瞭解到wide and deep,研究了一段時間,複賽開始就直接準備上這個框架,因為自己會的確實不多,所以就想著能不能幫隊友最佳化程式碼,當時構建點選率特徵需要構建個詞典,原先的程式碼大概1kw資料要跑6h左右,最後最佳化到1億資料15h跑完。
複賽前期直接套用了初賽的特徵,但發現效果差了很多,後面透過觀察發現是資料分佈變了,調整了之後卡在了0。55左右。那時候我信安作品賽進了決賽,所以在肝那個比賽,這邊就關注的比較少了,雖說當時有些想法,也跟他們討論過,但沒去嘗試,現在也沒法驗證當時的想法是否有用了。
信安的比賽答辯完之後,就又回到這個比賽中來,那時候隊友把lgb、textcnn、rnn都嘗試了一遍,結果都不是很好。後面從學長那裡瞭解到ESIM,然後就跟隊友說了下,元陽就開始研究使用這個模型,一開始的結果也不是很好,後來他們發現可能是訓練集選取以及詞向量維度的問題,於是重新構建訓練集,最後ESIM做到了0。588 。最終提交的時候交了ESIM+lgb的融合,排到了26名 。下面是元陽的ESIM開源連結
比賽結束後,看到群裡面大佬們的討論,發現我們做的特徵什麼遠遠不如他們,考慮的地方還是少了,準備後面再學習學習別的隊伍的開源,做個學習總結。
再次感謝兩位大佬隊友帶我躺了這個比賽 orz