雷鋒網 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

雷鋒網雷鋒網雷鋒網 (公衆號:雷鋒網)

雷鋒網版權文章,未經授權禁止轉載。詳情見 轉載須知

相關文章