kaggle实战2-竞赛题预测搜索相关性
Kaggle竞赛题:https://www.kaggle.com/c/home-depot-product-search-relevance
Step1:导入所需
df_train = pd.read_csv('../input/train.csv',encoding='ISO-8859-1') df_test = pd.read_csv('../input/test.csv',encoding='ISO-8859-1') df_desc = pd.read_csv('../input/product_descriptions.csv',encoding='ISO-8859-1') df_all = pd.concat((df_train,df_test),axis=0,ignore_index=True) print(df_all.shape) df_all = pd.merge(df_all,df_desc,how='left',on='product_uid') print(df_all.shape) print(df_all.head())
Step 2: 文本预处理
我们这里遇到的文本预处理比较简单,因为最主要的就是看关键词是否会被包含。
所以我们统一化我们的文本内容,以达到任何term在我们的数据集中只有一种表达式的效果。
我们这里用简单的Stem做个例子:
(有兴趣的同学可以选用各种你觉得靠谱的预处理方式:去掉停止词,纠正拼写,去掉数字,去掉各种emoji,等等)
stemmer = SnowballStemmer('english') def str_stemmer(s): return ' '.join([stemmer.stem(word) for word in s.lower().split()]) df_all['search_term']=df_all['search_term'].map(lambda x:str_stemmer(x)) df_all['product_description']=df_all['product_description'].map(lambda x:str_stemmer(x)) df_all['product_title']=df_all['product_title'].map(lambda x:str_stemmer(x))
Step 3: 进阶版文本特征
Levenshtein
df_all['dist_term_title'] = df_all.apply(lambda x: leven.ratio(x['search_term'],x['product_title']),axis=1) df_all['dist_term_desc'] = df_all.apply(lambda x:leven.ratio(x['search_term'],x['product_description']),axis=1)
TF-iDF
目标是生成一个字典
df_all['all_texts']=df_all['product_title'] + ' . ' + df_all['product_description'] + ' . '
from gensim.utils import tokenize
from gensim.corpora.dictionary import Dictionary
dictionary = Dictionary(list(tokenize(x, errors='ignore')) for x in df_all['all_texts'].values)
生成语料库
class MyCorpus(object): def __iter__(self): for x in df_all['all_texts'].values: yield dictionary.doc2bow(list(tokenize(x,errors='ignore'))) corpus = MyCorpus()
使用TFIDF
from gensim.models.tfidfmodel import TfidfModel tfidf = TfidfModel(corpus) tfidf[dictionary.doc2bow(list(tokenize('hello world, good morning', errors='ignore')))]
计算矩阵相似度
from gensim.similarities import MatrixSimilarity #先把刚刚那句话包装成一个方法 def to_tfidf(text): res = tfidf[dictionary.doc2bow((list(tokenize(text,errors='ignore'))))] return res def cos_sim(text1,text2): tfidf1 = to_tfidf(text1) tfidf2 = to_tfidf(text2) index = MatrixSimilarity([tfidf1],num_features=len(dictionary)) return float(index[tfidf2][0]) text1='hello world' text2='hello from the other side' cos_sim(text1,text2)
df_all['tfidf_cos_sim_in_title'] = df_all.apply(lambda x: cos_sim(x['search_term'], x['product_title']), axis=1)
df_all['tfidf_cos_sim_in_desc'] = df_all.apply(lambda x: cos_sim(x['search_term'], x['product_description']), axis=1)
word2vec
w2v和tfidf有个很大的不同。对于tfidf而言,只需要知道一整段text中包含了哪些word元素就行了。其他都不用care。
但是w2v要考虑到句子层级的split,以及语境前后的考虑。
所以,刚刚tfidf的corpus不能直接被这里使用。在这里,我们需要把句子/文字都给分类好。
这里,我们再玩儿一个NLP的杀器:NLTK。
import nltk # nltk也是自带一个强大的句子分割器。 tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
from gensim.models.word2vec import Word2Vec model = Word2Vec(w2v_corpus, size=128, window=5, min_count=5, workers=4)
最后建立模型