前言
最近拿了一份IMDb影評(píng)數(shù)據(jù)做練習(xí)有巧,對(duì)(英文的)自然語言處理(Natural Language Processing您访,NLP)有了初步的認(rèn)識(shí),同時(shí)對(duì)特征工程和Stacking有了更深的理解剪决。
這篇文章記錄一下這次練習(xí)的過程灵汪。
一些需要說明的:
- 數(shù)據(jù)來源:Sentiment Labelled Sentences Data Set - UCI ML Repository
- 建模目標(biāo):構(gòu)建影評(píng)分類器,判斷一份影評(píng)是正面還是負(fù)面的
- 建模結(jié)果:分類器整體準(zhǔn)確率近0.8(基于0.56的分類閾值)
- Tutorial來源:Spooky Author Identification - Kaggle
- 分析環(huán)境:
Python 3.6
- 使用到的庫:
numpy
柑潦,pandas
享言,matplotlib
,seaborn
渗鬼,string
览露,nltk
,sklearn
譬胎,xgboost
數(shù)據(jù)集
官方介紹:
This dataset contains sentences labelled with positive or negative sentiment.
The sentences come from three different websites/fields:
imdb.com
amazon.com
yelp.com
For each website, there exist 500 positive and 500 negative sentences. Those were selected randomly for larger datasets of reviews.
這里我只用到了IMDb的1000條影評(píng)差牛,它具體長(zhǎng)這樣:
每一行表示一條影評(píng),comment列顯示影評(píng)的具體內(nèi)容堰乔,is_pos列顯示該觀眾喜歡(is_pos = 1)還是不喜歡(is_pos = 0)這部電影偏化。
is_pos是此次分析的目標(biāo)特征,其中镐侯,正面和負(fù)面影評(píng)各占50%:
我們需要做的是侦讨,根據(jù)這些已有的影評(píng)數(shù)據(jù)構(gòu)建一個(gè)分類模型,這個(gè)模型能夠根據(jù)一份影評(píng)返回一個(gè)結(jié)果:這位觀眾喜歡/不喜歡這部電影。
文本特征提取
由于原始影評(píng)是非結(jié)構(gòu)化的韵卤,算法不能對(duì)其直接進(jìn)行學(xué)習(xí)骗污,所以我們需要通過特征工程,提取出數(shù)據(jù)中的結(jié)構(gòu)化信息沈条,從而構(gòu)建學(xué)習(xí)模型需忿。
我基于原始文本,構(gòu)建了43個(gè)新特征:
1. Features related to texts
- 詞數(shù)(number of words):#words蜡歹,即一份影評(píng)總共有多少個(gè)詞
- 非重復(fù)詞占比(ratio of unique words):#unique words / #words
- Stop words占比(ratio of stopwords):#stop words / #words贴谎,其中,stop words指的是在英文中一些出現(xiàn)頻率很高但沒有特殊含義的常用詞季稳,比如a擅这,the
- 標(biāo)點(diǎn)符號(hào)占比(ratio of punctuations):#punctuations / #words
- 名詞占比(ratio of nouns):#nouns / #words
- 形容詞占比(ratio of adj):#adj / #words
- 動(dòng)詞占比(ratio of verbs):#verbs / #words
- 標(biāo)題詞占比(ratio of title words):#title words / #words,其中景鼠,title words指的是首字母為大寫的詞
- 平均詞長(zhǎng)(mean length of words):sum(length of each word in a text) / #words仲翎,即一份影評(píng)中,平均每個(gè)詞的長(zhǎng)度(平均每個(gè)詞有多少個(gè)字母)
- 文本字符長(zhǎng)度(count of characters):len(text)
- 積極詞占比(ratio of positive words):#positive words / #words铛漓,其中溯香,積極詞詞庫出自這里
2. Features related to vectorizers
這部分的特征涉及以下幾個(gè)概念:
- Tokenization:文本詞條(tokens)化,如將句子 "I like this move." 分解為 "I", "like", "this", "movie"
- Count Vectorization:將一個(gè)語料庫(corpus)轉(zhuǎn)化為基于詞頻的矩陣浓恶,矩陣的每一行代表一個(gè)文本玫坛,每一列代表某個(gè)詞條在該文本中出現(xiàn)的次數(shù)
- TF-IDF: Term Frequency-Inverse Document Frequency,用于評(píng)估一字詞對(duì)于一個(gè)語料庫中的其中一份文件的重要程度包晰,字詞的重要性隨著它在文件中出現(xiàn)的次數(shù)成正比增加湿镀,但同時(shí)會(huì)隨著它在語料庫中出現(xiàn)的頻率成反比下降。
- TF-IDF Vctorization:將一個(gè)語料庫轉(zhuǎn)化為基于TF-IDF值的矩陣伐憾,矩陣的每一行代表一個(gè)文本勉痴,每一列代表某個(gè)詞條在該文本下的TF-IDF值
- SVD:奇異值分解(Singular Value Decomposition),線性代數(shù)中的一種矩陣分解方法树肃,在NLP中常與TF-IDF矩陣結(jié)合蒸矛,進(jìn)行特征降維(Feature Decomposition)
- Stacking:集成學(xué)習(xí)方法(Ensemble Learning)的一種,思路大致如下:先通過不同算法得出一組預(yù)測(cè)值胸嘴,再將這組預(yù)測(cè)值作為輸入特征進(jìn)行學(xué)習(xí)雏掠,從而得到數(shù)據(jù)的最終預(yù)測(cè)值(這里有一篇來自kaggle的文章,很好地解釋了staking的實(shí)現(xiàn)過程)
了解了上述概念后劣像,現(xiàn)在再回過頭來看之前沒有提到的特征:
- 基于詞頻矩陣的NB預(yù)測(cè)值:通過count vectorization構(gòu)建詞頻矩陣乡话,將該矩陣作為輸入特征,通過樸素貝葉斯(Naive Bayes驾讲,NB)構(gòu)建目標(biāo)變量預(yù)測(cè)值(is_pos = 1的概率)蚊伞,并將該預(yù)測(cè)值作為最終XGBoost模型的新特征
- 基于詞頻矩陣矩陣的LR預(yù)測(cè)值:通過count vectorization構(gòu)建詞頻矩陣,將該矩陣作為輸入特征吮铭,通過邏輯回歸(Logistic Regression时迫,LR)構(gòu)建目標(biāo)變量預(yù)測(cè)值(is_pos = 1的概率),并將該預(yù)測(cè)值作為最終XGBoost模型的新特征
- SVD features of TF-IDF metrix:通過TF-IDF vectorization構(gòu)建TF-IDF矩陣谓晌,通過SVD將該矩陣降至30維掠拳,并將這30維向量作為最終XGBoost模型的新特征
結(jié)果分析
我在不同階段使用不同特征組合、算法進(jìn)行了建模纸肉,下面我將分別給出這些不同的建模結(jié)果溺欧,并在最后對(duì)這些結(jié)果進(jìn)行綜合對(duì)比,以期對(duì)特征工程柏肪、Stacking的作用管中窺豹姐刁。
1. XGBoost with features related to texts only
我首先用11個(gè)和文本自身相關(guān)的特征(詞數(shù)、名詞占比等)進(jìn)行建模烦味。使用的算法為XGBoost聂使。
驗(yàn)證集(test set)預(yù)測(cè)效果:
- LogLoss:0.59
- AUC of ROC curve:0.75
可以看到,預(yù)測(cè)效果還是不錯(cuò)的谬俄,說明這些特征在一定程度上捕捉到了有用信息柏靶。
2. XGBoost with SVD features of TF-IDF metrix
接著用XGboost對(duì)那30個(gè)SVD特征建模。
驗(yàn)證集(test set)預(yù)測(cè)效果:
- LogLoss:0.55
- AUC of ROC curve:0.79
這些特征同樣也捕捉到了有用信息溃论,并且預(yù)測(cè)效果比之前那11個(gè)特征要稍好屎蜓。注意,這里并不是說用了這30個(gè)SVD特征后钥勋,前面那11個(gè)特征就不需要了炬转,二者捕捉到的可能是不同方面的信息。
3. NB using count matrix
接著用NB對(duì)詞頻矩陣構(gòu)建分類預(yù)測(cè)模型算灸。
驗(yàn)證集(test set)預(yù)測(cè)效果:
- LogLoss:0.56
- AUC of ROC curve:0.86
logloss和之前的結(jié)果相似返吻,但auc提升了近9%,說明詞頻包含了相當(dāng)一部分的有用信息乎婿,是很好的預(yù)測(cè)特征测僵。
4. LR using count matrix
接下來用LR對(duì)詞頻矩陣構(gòu)建分類預(yù)測(cè)模型。
驗(yàn)證集(test set)預(yù)測(cè)效果:
- LogLoss:0.49
- AUC of ROC curve:0.87
auc和之前相似谢翎,但logloss下降了12%捍靠,這同樣表明詞頻是不錯(cuò)的預(yù)測(cè)特征。此外森逮,LR和NB可能捕捉到了不同方面的信息榨婆,換句話說,把這兩個(gè)模型下的預(yù)測(cè)值進(jìn)行綜合(stacking)褒侧,也許能夠得到更準(zhǔn)確的預(yù)測(cè)結(jié)果良风。
5. XGBoost using all features
最后是使用全部43個(gè)特征進(jìn)行建模的結(jié)果谊迄。學(xué)習(xí)算法為XGBoost。
驗(yàn)證集(test set)預(yù)測(cè)效果:
- LogLoss:0.43
- AUC of ROC curve:0.88
logloss低于之前的任何一個(gè)模型烟央,auc高于之前的任何一個(gè)模型统诺。
對(duì)比一下上述各個(gè)模型的ROC曲線:
可以看到,僅使用count matrix進(jìn)行預(yù)測(cè)的NB和LR模型疑俭,預(yù)測(cè)結(jié)果已經(jīng)很接近最終模型的預(yù)測(cè)結(jié)果粮呢,說明詞頻包含了大部分預(yù)測(cè)所需信息,且NB和LR對(duì)于這組數(shù)據(jù)而言钞艇,是有效的算法啄寡。
另一方面,最終模型的ROC曲線整體而言稍優(yōu)于NB和LR模型哩照,說明NB和LR在訓(xùn)練時(shí)挺物,得到了數(shù)據(jù)不同方面的信息,而基于TF-IDF的SVD特征和其他基于文本本身的特征飘弧,進(jìn)一步捕捉到了NB姻乓、LR無法獲取的其他信息。通過對(duì)所有特征進(jìn)行建模眯牧,最終的XGBoost模型綜合了以上所有信息蹋岩,從而提高了預(yù)測(cè)準(zhǔn)確率。
再來看一下特征重要程度排名:
前4位分別是積極詞占比(pos_word_ratio)学少、NB預(yù)測(cè)值(nb_ctv_pred)剪个、LR預(yù)測(cè)值(lr_ctv_pred)和平均詞長(zhǎng)(mean_word_len)。其他特征也都在不同程度上發(fā)揮了作用版确。這進(jìn)一步說明了特征工程和Stacking的重要性扣囊。
現(xiàn)在,看一下最終預(yù)測(cè)結(jié)果在測(cè)試集上的confusion matrix绒疗。
因?yàn)轭A(yù)測(cè)結(jié)果為is_pos = 1的概率值侵歇,所以我們需要先確定一個(gè)閾值,當(dāng)概率值大于該閾值時(shí)吓蘑,判定該影評(píng)為正面的(predictive is_pos = 1)惕虑,否則為負(fù)面的(predictive is_pos = 0)。
基于ROC曲線返回的結(jié)果磨镶,選擇True Positive Rate大于0.75下的第一個(gè)Threshold為該閾值溃蔫,則當(dāng)預(yù)測(cè)結(jié)果大于0.56時(shí),判定該影評(píng)為正面的琳猫,否則為負(fù)面的伟叛。
由此得到的confusion matrix如下:
預(yù)測(cè)集中共有300份影評(píng),其中正面影評(píng)共有161份脐嫂,負(fù)面影評(píng)共139份统刮。在這些正面的影評(píng)中紊遵,有76.4%份影評(píng)被正確識(shí)別;在這些負(fù)面的影評(píng)中侥蒙,有82.7%份影評(píng)被正確識(shí)別暗膜。整體而言,當(dāng)拿到一份影評(píng)的時(shí)候辉哥,這個(gè)模型有0.793的概率能夠正確辨別出這個(gè)觀眾喜歡還是不喜歡這部TA所點(diǎn)評(píng)的電影桦山。(注意攒射,不同的閾值返回不同的confusion matrix醋旦,以上只是其中一個(gè)閾值對(duì)應(yīng)的結(jié)果。)
最后我們隨機(jī)抽取出測(cè)試集上的幾條影評(píng)來具體看一下模型給出的預(yù)測(cè)結(jié)果会放,從而對(duì)這個(gè)分類器有一個(gè)更直觀的感受:
"This is an extraordinary film."
正面影評(píng)概率:0.724
"I couldn't take them seriously."
正面影評(píng)概率:0.098
"The plot doesn't hang together at all, and the acting is absolutely appalling."
正面影評(píng)概率:0.064
"My rating: just 3 out of 10."
正面影評(píng)概率:0.192
"I've seen soap operas more intelligent than this movie."
正面影評(píng)概率:0.504
"And I really did find them funny."
正面影評(píng)概率:0.563
"The story unfolds in 18th century Jutland and the use of period music played on period instruments is just one more fine touch."
正面影評(píng)概率:0.373
這個(gè)分類器給出的大多數(shù)概率值都比較合理饲齐,一個(gè)可能的原因是這個(gè)數(shù)據(jù)集本身就是經(jīng)過篩選的,數(shù)據(jù)集里的影評(píng)基本上都“憎惡分明”咧最,使得信息的提取相對(duì)容易捂人。注意最后一條影評(píng),我個(gè)人覺得這個(gè)影評(píng)是中性偏肯定的(is_pos也確實(shí)是1)矢沿,但分類器只給出了0.373的概率滥搭,說明這個(gè)分類器的性能還有待提升。
結(jié)語
上面談到的數(shù)據(jù)處理方法捣鲸,靈感主要來源于Kaggle的某個(gè)基于NLP的分類競(jìng)賽(見前言中的“Tutorial來源”)瑟匆,比如構(gòu)建詞數(shù)、非重復(fù)詞占比栽惶、平均詞長(zhǎng)這樣的特征愁溜,比如將NB的預(yù)測(cè)值作為新特征后再二次建模。
這次練習(xí)的結(jié)果印證了Kaggle里兩條百試不爽的法則:
- 一個(gè)數(shù)據(jù)挖掘任務(wù)的成功與否外厂,很大程度上看特征工程做得好不好
- 能否進(jìn)一步提升模型預(yù)測(cè)能力冕象,stacking是一大秘訣
另外,有幾個(gè)點(diǎn)我在這次的練習(xí)中沒有涉及汁蝶,但對(duì)于NLP來說非常值得一試渐扮,我在這里標(biāo)出來供日后查缺補(bǔ)漏:
- Stemming and Lemmatization (related tutorial)
- Word Vectors and Deep Learning (related tutorial)
以上。