雷锋网 AI 开发者按,相信很多数据科学从业者都会去参加 kaggle 竞赛,提高自己的能力。在 Kaggle Competitions 排行榜中,有一个头衔是众多用户都十分向往的,那就是「Kaggle Grandmaster」,指的是排名 0.1‰ 的顶级高手。数据科学新手 Dean Sublett 和数据科学家,Kaggle Grandmaster Abhishek 进行了交流,并写了一篇关于他的 kaggle Kernel 的文章,AI 开发者编译整理。
个人经历
在进入德国各大公司开始数据科学家的工作之前,Abhishek Thakur 先后在 NIT Surat 和人 Bonn 大学获得了电气工程学士学位和计算机科学硕士学位。目前,他担任挪威 Boost.a i 的首席数据科学家,这是一家「专门研究会话人工智能(ai)的软件公司」,但我对 Abhishek 印象最深的地方在于他的 Kaggle 影响力。
你可以在这里查看他的 Kaggle 档案,以下是他曾经获得的荣誉:
比赛总冠军(17 枚金牌,历史最高排名世界第 3)
Kernel 专家(他在 Kaggler 的前 1% 之内)
讨论大师(65 枚金牌,有史以来最高排名是第 2)
我想看看 Abhishek 的经验,了解任何关于 kaggle 的 NLP 问题。我选择了 Abhishek 的 kernel。我一直在努力学习更多关于自然语言处理的知识,怎么能错过学习 Abhishek 的 Halloween-themed Spooky Authors 数据集呢?
Abhishek 的 NLP 方法
我强烈建议你打开 kernel 阅读本文。如果你真的想要对 NLP 或者一般的数据科学有更深入的了解,那么在阅读 Abhishek 的 kernel 时,一定要自己动手编程来理解它的每一行代码。
所以我们不要忘记,我们的任务是确定测试集中每个句子的作者(EAP—Edgar Allen Poe; HPL—H.P. Lovecraft; MWS—Mary Wollstonecraft Shelley)。
1.探索数据并理解问题
在导入必要的 python 模块和数据之后,Abhishek 对数据调用 head()方法,以查看前五行是什么样子的。由于 Abhishek 是一个专家,这是一个 NLP 问题,与涉及数值数据的问题相比,探索性数据分析(通常被称为 EDA)是很肤浅的。但是数据科学新手可能会从 EDA 中受益。对数据的深入研究可以找出任何缺失的值,让你知道需要清理多少数据,并有助于在稍后的问题中通知你的模型构建决策。
Abhishek 还提醒我们,我们正在处理一个多类文本分类问题,最好不要忽视我们正在努力实现的目标!他会注意到什么样的评价指标将用于评分。在这次竞赛中,Kaggle 使用多类对数损失来衡量提交模型的性能。理想情况下,我们的多分类模型的对数损失为 0。如果你感兴趣的话,这里有更多关于对数损失的信息。
2.预处理
接下来,Abhishek 使用 Scikit Learn 中的 labelencoder()方法为每个作者分配一个整数值。通过使用整数值(0、1、2)对作者列中的值的文本标签进行编码使数据更容易被他的分类模型理解。
对作者标签进行编码后,Abhishek 使用 Scikit Learn 中的 train_test_split 将数据拆分为训练集和验证集。他打算对数据集中 90% 的句子进行模型训练,然后根据剩余 10% 的数据评估模型的准确性。
3.建立模型
在创建第一个模型之前,Abhishek 在数据上使用了 TF-IDF (Term Frequency—Inverse Document Frequency)。TF-IDF 将为文本列句子中出现的单词赋予权重。因此,TF-IDF 将帮助我们理解当我们试图确定哪位作者写了一个特定的句子时,哪些词是重要的。「the」等词对于作者分类不重要,因为「the」经常出现,并且不透露太多信息,但一个词, 例如,E「cthulhu」在对 H.P.Lovecraft 写的句子进行分类时非常重要。关于 TF-IDF 的更多信息可以在这里找到。
在数据上运行 TF-IDF 是一种特征提取的形式。在这里,我们需要推导出数据的某种重要的预测因子或特征,帮助我们找出哪位作者写了一个特定的句子。有了 TF-IDF,我们就可以统计出一个词的重要性,从而帮助我们预测句子的作者。
在训练集和验证集上拟合 TF-IDF 后,Abhishek 建立了一个逻辑回归模型。如果这种类型的分类模型对你来说是新的,请在继续之前阅读它的介绍。在拟合了逻辑回归模型后,Abhishek 计算了其逻辑回归模型的对数损失(回想一下,他在内核开始附近编写了多类对数损失函数)。对于逻辑回归模型,多类对数损失函数返回 0.626 的对数损失值。虽然将 TF-IDF 与逻辑回归模型相结合可以为我们提供一个良好的开端,但我们可以提高这个对数损失分数。
4.模型调整
因此,我们对 0.626 的对数损失分数不满意,希望优化这个评估指标。从这里,我们有很多方法可以尝试,这正是 Abhishek 所做的。在我们研究和预处理了数据之后,我们得到了许多不同的特征提取和模型拟合组合。例如,Abhishek 使用字数来提取特征,而不是使用 TF-IDF。使用这种特征提取技术,他的逻辑回归模型的对数损失分数从 0.626 提高到 0.528,提高了 0.098!
总结
由于 Abhishek 的 kernel 从这里开始变得越来越细节,我将让他完成解释其他分类模型这项繁重的工作。
以下是我们讨论的内容:
EDA:如果我们想了解数据集,探索性数据分析(Exploratory data analysis,EDA)是至关重要的,而且 EDA 可以在我们开始构建模型时为我们节省时间。
多分类问题:这种类型的问题要求我们预测哪些观测结果属于哪个类别,每个观测结果可以属于三个或更多类别中的任何一个类别。
预处理:在建立任何模型之前,我们必须对数据进行预处理。在这个例子中,为了模型,我们需要使用 labelendcoder()将文本标签转换为整数值。
特征提取:每当我们有一个原始数据集(在我们的示例中是句子摘录)时,我们就需要推导一些预测因子来帮助我们确定如何对观察结果进行分类。Abhishek 教我们如何使用 TF-IDF 和字数。
从这里开始,我们就要提取具有高预测能力的特性,选择与问题匹配的模型,并优化我们所关注的度量标准。不要害怕麻烦,多尝试几个模型——通过更多实验,你很可能找到适合优化你的评估指标的模型。我希望在阅读了这篇文章之后,你能更好地理解如何处理 NLP 问题,并且你也很欣赏 Abhishek 的工作。
附录
上面是本文中提到的所有 Abhishek 的代码。我要重申的是,这不是我自己的工作,这篇文章是为了帮助初学者学习 Abhishek 的 NLP 教程。
# This gist is a collection of code from Abhishek Thakur's Kaggle NLP tutorial, which can be found here:
# https://www.kaggle.com/abhishek/approaching-almost-any-nlp-problem-on-kaggle
# 1. Exploring the Data and Understanding the Problem #
import pandas as pd
import numpy as np
import xgboost as xgb
from tqdm import tqdm
from sklearn.svm import SVC
from keras.models import Sequential
from keras.layers.recurrent import LSTM, GRU
from keras.layers.core import Dense, Activation, Dropout
from keras.layers.embeddings import Embedding
from keras.layers.normalization import BatchNormalization
from keras.utils import np_utils
from sklearn import preprocessing, decomposition, model_selection, metrics, pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.decomposition import TruncatedSVD
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from keras.layers import GlobalMaxPooling1D, Conv1D, MaxPooling1D, Flatten, Bidirectional, SpatialDropout1D
from keras.preprocessing import sequence, text
from keras.callbacks import EarlyStopping
from nltk import word_tokenize
from nltk.corpus import stopwords
stop_words = stopwords.words('english')
train = pd.read_csv('../input/train.csv')
test = pd.read_csv('../input/test.csv')
sample = pd.read_csv('../input/sample_submission.csv')
train.head()
test.head()
sample.head()
def multiclass_logloss(actual, predicted, eps=1e-15):
"""Multi class version of Logarithmic Loss metric.
:param actual: Array containing the actual target classes
:param predicted: Matrix with class predictions, one probability per class
"""
# Convert 'actual' to a binary array if it's not already:
if len(actual.shape) == 1:
actual2 = np.zeros((actual.shape[0], predicted.shape[1]))
for i, val in enumerate(actual):
actual2[i, val] = 1
actual = actual2
clip = np.clip(predicted, eps, 1 - eps)
rows = actual.shape[0]
vsota = np.sum(actual * np.log(clip))
return -1.0 / rows * vsota
# 2. Preprocessing #
lbl_enc = preprocessing.LabelEncoder()
y = lbl_enc.fit_transform(train.author.values)
xtrain, xvalid, ytrain, yvalid = train_test_split(train.text.values, y,
stratify=y,
random_state=42,
test_size=0.1, shuffle=True)
print (xtrain.shape)
print (xvalid.shape)
# 3. Building a Model #
# Always start with these features. They work (almost) everytime!
tfv = TfidfVectorizer(min_df=3, max_features=None,
strip_accents='unicode', analyzer='word',token_pattern=r'\w{1,}',
ngram_range=(1, 3), use_idf=1,smooth_idf=1,sublinear_tf=1,
stop_words = 'english')
# Fitting TF-IDF to both training and test sets (semi-supervised learning)
tfv.fit(list(xtrain) + list(xvalid))
xtrain_tfv = tfv.transform(xtrain)
xvalid_tfv = tfv.transform(xvalid)
# Fitting a simple Logistic Regression on TFIDF
clf = LogisticRegression(C=1.0)
clf.fit(xtrain_tfv, ytrain)
predictions = clf.predict_proba(xvalid_tfv)
print ("logloss: %0.3f " % multiclass_logloss(yvalid, predictions))
# 4. Model Tweaking #
ctv = CountVectorizer(analyzer='word',token_pattern=r'\w{1,}',
ngram_range=(1, 3), stop_words = 'english')
# Fitting Count Vectorizer to both training and test sets (semi-supervised learning)
ctv.fit(list(xtrain) + list(xvalid))
xtrain_ctv = ctv.transform(xtrain)
xvalid_ctv = ctv.transform(xvalid)
# Fitting a simple Logistic Regression on Counts
clf = LogisticRegression(C=1.0)
clf.fit(xtrain_ctv, ytrain)
predictions = clf.predict_proba(xvalid_ctv)
print ("logloss: %0.3f " % multiclass_logloss(yvalid, predictions))
# NOTE: THIS IS NOT MY OWN WORK
地址:https://towardsdatascience.com/what-i-learned-from-abhishek-thakur-4b905ac0fd55
雷锋网雷锋网雷锋网