搭建情感分析系統,tf-idf,word2vec

情感分析問題

給定一個文本並輸出它的情感值,情感值無非是正面、負面或者中性。

我們希望通過使用一種算法去識別一個文本的情感,這個問題本身屬於文本分類問題。 如果只是正面或者負面,就是二分類問題;但如果是正面、負面和中性,則是三分類問題。

應用場景:

1)量化投資,就是通過AI技術去做投資比如股票買賣。在量化投資裏,我們一般使用模型對未來的股市做預測,然後再進行買賣的決策。在這個任務上,我們一般會採用多因子模型, 時序預測模型等算法。

另外,很多公司通過情感分析的技術去實時監控是否有大量的負面消息在產生。一旦發現,需要公關部門去處理。比如一家金融公司,會實時抓取跟公司有關的公衆號、論壇的文本信息然後自動判斷是否有大量的負面情感在裏面。

 

2)競品分析也是很重要的一部分。通過情感分析技術來判斷競品推出了哪些產品,輿論對此產品的評價是怎麼樣的。通過這些信息,我們可以做到了解競爭對手,並做出及時的調整。

 

文本的預處理工作

1)分詞,這是最基本的第一步。無論對於英文文本,還是中文文本都離不開分詞。英文的分詞相對比較簡單,因爲一般的英文寫法裏通過空格來隔開不同單詞的。但對於中文,我們不得不採用一些算法去做分詞。

使用jieba分詞的例子:

1)在Anaconda3 中安裝jieba :

conda install -c conda-forge jieba

或者一下命令:

conda install --channel https://conda.anaconda.org/conda-forge jieba

如果無法連上conda-forge可以嘗試一下方式:

https://blog.csdn.net/zhaohaibo_/article/details/79253740

但是該方式安裝的jieba無法在vscode中被識別

https://blog.csdn.net/a857553315/article/details/81410142

python文件名不能和jieba庫名字重名,否則也無法正常運行。

一個使用jieba分詞的例子,並加入關鍵詞:

# encoding-utf-8
# reference : https://github.com/fxsjy/jieba
import jieba

# base on jieba segment reference: https://github.com/fxsjy/jieba
seg_list = jieba.cut("貪心學院是國內最專業的人工智能在線教育品牌", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))


# TODO: 在jieba中加入"貪心學院"關鍵詞, hint: 通過.add_word函數
# 
jieba.add_word("貪心學院")
seg_list = jieba.cut("貪心學院是國內最專業的人工智能在線教育品牌", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list)) 
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\admin\AppData\Local\Temp\jieba.cache
Loading model cost 0.848 seconds.
Prefix dict has been built succesfully.
Default Mode: 貪心/ 學院/ 是/ 國內/ 最/ 專業/ 的/ 人工智能/ 在線教育/ 品牌
Default Mode: 貪心學院/ 是/ 國內/ 最/ 專業/ 的/ 人工智能/ 在線教育/ 品牌

我們還是要定義屬於自己的專有名詞的。如果我們考慮的是醫療領域,則需要把醫療領域我們比較關注的詞先加入到詞庫裏,再通過結巴工具做分詞,畢竟很多的專有詞彙並不存在於結巴的詞庫裏。

 

大部分情況下只需要使用工具去分詞就可以了,沒必要自己造輪子。但有一些特殊情況,比如這些開源工具的效果很一般,或者它們缺少某些方面的考慮,則可能需要自己寫一個分詞工具。

實際上,自己寫一個分詞工具也不難,目前常用的方法是基於HMM, CRF等方法

2)單詞的過濾

單詞的過濾:把一些出現次數特別多的單詞過濾掉也叫作停用詞的過濾,或者把那些出現次數特別少的單詞過濾掉,或者把一些特殊符號比如#@過濾掉。

停用詞呢,就是那些出現特別頻繁,但對於一個句子貢獻不是特別大的單詞。比如”的“, ”他“可以認爲是停用詞。

使用停用詞的方法也超級簡單。就是提前設計好停用詞庫,然後做文本分析時把這些停用詞忽略掉就可以了。

停用詞庫的構建可以有三種方法:

第一、手動去設置停用詞庫,把所有的停用詞寫入一個文件。這個過程比較耗費時間,但對於非常垂直類的應用還是最有效的。

第二、從網上搜索停用詞庫,一般來講網絡上可以找到大部分語言的停用詞庫,這些都是別人已經整理好的,所以基本都是通用的。但有些時候確實由於應用本身的特點,這些停用詞庫可能還滿足不了需求。所以,這時候需要適當地加入一些人工方式來整理的單詞。

第三、從第三方工具導入停用詞庫,比如NLTK這些工具已經集成了不同語言的停用詞庫,所以使用的時候直接調用就可以了。

 

NLTK中的停用詞庫:

需要安裝nltk的stopwords庫:

>>> import nltk
>>> nltk.download('stopwords')
[nltk_data] Downloading package stopwords to
[nltk_data]     C:\Users\admin\AppData\Roaming\nltk_data...
[nltk_data]   Unzipping corpora\stopwords.zip.
# method.1 build a stop word dictionary.
stop_words = {"the", "an", "is", "there"} # using the set as hash table for query complexity O(1)
# use the dictionary. assume word_list included the stop word
word_list = ["we", "are", "the", "students"]
filtered_words = [word for word in word_list if word not in stop_words]
print(filtered_words)

# method.2 using the stopwords from nltk
from nltk.corpus import stopwords
cachedStopWords = stopwords.words("english")
print(cachedStopWords)

運行結果

['we', 'are', 'students']
['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', "don't", 'should', "should've", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', "aren't", 'couldn', "couldn't", 'didn', "didn't", 'doesn', "doesn't", 'hadn', "hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't", 'ma', 'mightn', "mightn't", 'mustn', "mustn't", 'needn', "needn't", 'shan', "shan't", 'shouldn', "shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't"]

 

除了停用詞,我們也通常會去掉出現次數特別少的單詞,畢竟這些單詞的頻次太低,對整個訓練來說起到的作用也不大。那如何去制定什麼樣的單詞才叫作出現次數少的呢? 這裏其實沒有一個標準答案,還是需要去了解一下每個單詞出現的次數,從而再去判斷這個閾值。

一般來講,比如一個單詞出現少於10次或者20次,我們可以歸類爲是可以去掉的單詞。 但這個也取決於手裏的語料庫大小。如果語料庫本身總共只包含了不到一千個單詞,那這個閾值顯然有點高了。

對於特殊符號,我們也需要做一些處理。特殊符號其實就是我們覺得不太有用的符號。比如一個文章裏出現的@#&,這些可以認爲是特殊符號,進而可以去掉。

基於這些理由,我們通常把出現的所有的數表示成一個統一的特殊符號比如"#NUM",這樣至少我們的模型知道這是一個數字。

對於英文文本,我們通常會做單詞標準化的操作,也就是把類似含義的單詞統一表示成一種形式。這裏有兩種常用的方法,分別是stemming和lemmazation。

英文中常用的標準化操作

Lemmazation valid word

Porter Stemmer Reference:https://tartarus.org/martin/PorterStemmer/java.txt

Porter Stemmer Algorithm

 

文本的表示與tf-idf

如何把一個單詞表示成向量。第一種,也是最簡單的表示法叫作獨熱編碼的表示

如何表示一個句子?

這裏有幾種常用的方法,分別是boolean表示、count表示以及tf-idf的表示。

1)boolean表示:

只關注單詞有沒出現,不關心出現的次數,每個向量的長度都是詞典的大小

這樣的表示方法使得向量非常的稀疏,只有一個位置是1,剩下的全是0。而且向量的長度等於詞庫的長度,也就是我們的詞庫有多大,每一個單詞向量的長度就有多大。

這種方式雖然很簡單,但明顯也有個缺點,就是不考慮一個單詞出現的次數。出現次數越多,有可能對句子的貢獻也會越大。我們希望把這部分信息也考慮進去。

 

2)基於次數的表示法:count

sklearn -> CountVectorizer可以實現

句子的表示方法:

出現次數多的單詞未必是最重要的。

 

3)tf-idf表示法:

 

tf(d,w) - term frequency, 一個單詞W當前文檔(句子)中出現的次數

idf(w) - 單詞重要性(單詞在越少的文檔中出現重要性越大)

 

tf-idf非常重要,基本上任何的文本領域,我們都有大概率用到它,所以一定要掌握它的細節。接下來,爲了鞏固對tf-idf的認知,我們通過一個例子來解釋一下計算tf-idf的完整的過程

相似度計算

在文本分析領域,還有一個工作特別重要,就是計算兩個文本之間的相似度。計算相似度是理解文本語義來說也是很重要的技術,因爲一旦我們理解了某一個單詞或者句子,我們可以通過相似度計算方法來尋找跟這個語義類似的單詞或者文本。

計算文本相似度有很多種方法,這裏我們重點來講解兩個方法:計算歐式距離的方法和計算餘弦相似度的方法。

它們都可以用來評估文本的相似度,但前者是基於距離的計算,後者是基於相似度的計算。需要注意的一點是:距離越大相似度越小

歐氏距離,兩個句子的相似度:

距離越大,相似度越小

餘弦定理,相似度,考慮了向量的方向。

 

分佈式表示與Word2vec

計算單詞的語義相似度

獨熱編碼導致不同單詞之間相似度都完全一樣

餘弦相似度都是0

 

需要改變詞向量的表示方法:確實存在這樣的一個方法論叫作分佈式表示法(Distributional Representation)。

word2vec (詞向量,稠密的)

通過訓練學出來(skipgram, cbow, glove 等)

基於分佈式表示法來計算兩個單詞的語義相似度:

 

總結起來,使用詞向量的情況下確實可以計算出語義相似度。而且這種表示方法克服了之前獨熱編碼的稀疏性。

我們可以把學出來的詞向量可視化在二維空間裏。當然,可視化之前我們需要做降維處理的。對於詞向量的降維,最經典的方法叫做T-SNE, 具體可以查一下網上的資料。 sklearn裏也集成了此方法。
https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html

如果根據詞向量表示一個句子?

這裏我給出最爲簡單的方法,就是平均法,也叫作average pooling。

給定單詞的向量,我們通過平均法則即可得出包含若干個單詞的句子向量, 接着再使用句子向量去做分類模型。

100維獨熱最多表示100個單詞

100維的分佈式表示法最多表示k^100個單詞,k表示每個維度所取的不同值,如果k是連續值。則可以表示無窮多個單詞

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章