本文結構:
- 什么是情感分析?
- 怎么分析,技術上如何實現?
cs224d Day 7: 項目2-命名實體識別
什么是情感分析?
就是要識別出用戶對一件事一個物或一個人的看法、態度,比如一個電影的評論,一個商品的評價,一次體驗的感想等等。根據對帶有情感色彩的主觀性文本進行分析,識別出用戶的態度,是喜歡,討厭,還是中立。在實際生活中有很多應用,例如通過對 Twitter 用戶的情感分析,來預測股票走勢、預測電影票房、選舉結果等,還可以用來了解用戶對公司、產品的喜好,分析結果可以被用來改善產品和服務,還可以發現競爭對手的優劣勢等等。
怎么分析,技術上如何實現?
首先這是個分類問題。
最開始的方案是在文中找到具有各種感情色彩屬性的詞,統計每個屬性的詞的個數,哪個類多,這段話就屬于哪個屬性。但是這存在一個問題,例如 don't like ,一個屬于否定,一個屬于肯定,統計之后變成 0 了,而實際上應該是否定的態度。再有一種情況是,前面幾句是否定,后面又是肯定,那整段到底是中立還是肯定呢,為了解決這樣的問題,就需要考慮上下文的環境。
2013年谷歌發了兩篇論文,介紹了 Continuous Bag of Words (CBOW) 和 Skip-gram 這兩個模型,也就是 Word2Vec 方法,這兩種模型都是先將每個單詞轉化成一個隨機的 N 維向量,訓練之后得到每個單詞的最優表示向量,區別是,CBOW 是根據上下文來預測當前詞語,Skip-gram 剛好相反,是根據當前詞語來預測上下文。
Word2Vec 方法不僅可以捕捉上下文語境,同時還壓縮了數據規模,讓訓練更快更高效。通過這個模型得到的詞向量已經可以捕捉到上下文的信息。比如,可以利用基本代數公式來發現單詞之間的關系(比如,“國王”-“男人”+“女人”=“王后”)。用這些自帶上下文信息的詞向量來預測未知數據的情感狀況的話,就可以更準確。
今天的小項目,就是用 word2vec 去解決情感分析問題的。先來簡單介紹一下大體思路,然后進入代碼版塊。
思路分為兩部分,第一步,就是先用 word2vec 和 SGD 訓練出每個單詞的最優表示向量。第二步,用 Softmax Regression 對訓練數據集的每個句子進行訓練,得到分類器的參數,用這個參數就可以預測新的數據集的情感分類。其中訓練數據集的每個句子,都對應一個0-1之間的浮點得分,將這個得分化為 0-4 整數型 5 個級別,分別屬于 5 種感情類別,討厭,有點討厭,中立,有點喜歡,喜歡。然后將每個句子的詞轉化成之前訓練過的詞向量,這樣哪些詞屬于哪個類就知道了,然后用分類器得到分類的邊界,得到的參數就可以用來進行預測。
具體實現
接下來以一個初學者的角度來講一下要如何利用這幾個模型和算法來實現情感分析這個任務的,因為項目的代碼有點多,不方便全寫在文章里,可以去這里查看完整代碼。
第一步,用 word2vec 和 SGD 訓練出每個單詞的最優表示向量。
- 執行 c7_run_word2vec.py
- 其中訓練詞向量的方法是 c5_word2vec.py
- 同時用 c6_sgd.py 訓練參數,并且將結果保存起來,每1000次迭代保存在一個文件中 saved_params_1000.npy
word2vec:
上面提到了,它有兩種模型 CBOW 和 Skip-gram,每一種都可以用來訓練生成最優的詞向量,同時還有兩種 cost function 的定義方式,一種是 Softmax cost function, 一種是 Negative sampling cost function,所以在提到 word2vec 的時候,其實是可以有 4 種搭配的方法的,這個小項目里用到的是 Skip-gram 和 Negative sampling cost function 的結合方式。
先定義 skipgram 函數:
給一個中心詞 currentWord,和它的窗口大小為 2C 的上下文 contextWords,要求出代表它們的詞向量矩陣 W1 和 W2。
def skipgram(currentWord, C, contextWords, tokens, inputVectors, outputVectors,
dataset, word2vecCostAndGradient = softmaxCostAndGradient):
""" Skip-gram model in word2vec """
currentI = tokens[currentWord] #the order of this center word in the whole vocabulary
predicted = inputVectors[currentI, :] #turn this word to vector representation
cost = 0.0
gradIn = np.zeros(inputVectors.shape)
gradOut = np.zeros(outputVectors.shape)
for cwd in contextWords: #contextWords is of 2C length
idx = tokens[cwd]
cc, gp, gg = word2vecCostAndGradient(predicted, idx, outputVectors, dataset)
cost += cc #final cost/gradient is the 'sum' of result calculated by each word in context
gradOut += gg
gradIn[currentI, :] += gp
return cost, gradIn, gradOut
這里用到的成本函數是 Negative sampling,我們的目的就是要使這個成本函數達到最小,然后用這個極值時的參數 grad, 也就是可以得到要求的 wordvectors。要增加準確度,所以可以多次生成中心詞和上下文進行訓練,然后取平均值,也就是函數 word2vec_sgd_wrapper 做的事情。
def negSamplingCostAndGradient(predicted, target, outputVectors, dataset, K=10):
""" Negative sampling cost function for word2vec models """
grad = np.zeros(outputVectors.shape)
gradPred = np.zeros(predicted.shape)
indices = [target]
for k in xrange(K):
newidx = dataset.sampleTokenIdx()
while newidx == target:
newidx = dataset.sampleTokenIdx()
indices += [newidx]
labels = np.array([1] + [-1 for k in xrange(K)])
vecs = outputVectors[indices, :]
t = sigmoid(vecs.dot(predicted) * labels)
cost = -np.sum(np.log(t))
delta = labels * (t-1)
gradPred = delta.reshape((1, K+1)).dot(vecs).flatten()
gradtemp = delta.reshape((K+1, 1)).dot(predicted.reshape(1, predicted.shape[0]))
for k in xrange(K+1):
grad[indices[k]] += gradtemp[k, :]
return cost, gradPred, grad
**接著用 sgd **迭代 40000 次得到訓練好的 wordVectors。
wordVectors0 = sgd(
lambda vec: word2vec_sgd_wrapper(skipgram, tokens, vec, dataset, C,
negSamplingCostAndGradient),
wordVectors, 0.3, 40000, None, True, PRINT_EVERY=10)
關于 word2vec 之前有寫過一篇 word2vec 模型思想和代碼實現,想了解詳細原理和具體怎樣實現的童鞋可以去這個這里看。
第二步,用 Softmax Regression 對訓練數據集進行分類學習。
- 執行 c10_sentiment.py
- 其中用 c6_sgd.py 去訓練權重 weights,
- 然后用 c8_softmaxreg.py 根據訓練好的 features,labels,weights 進行類別 label 的預測。
先將數據集分為三部分,training set,deviation set,和 test set。
trainset = dataset.getTrainSentences()
devset = dataset.getDevSentences()
testset = dataset.getTestSentences()
在 trainset 中,每句話對應一個情感的得分或者說是分類,先將每個 word 在 token 中找到序號,然后在第一步訓練好的 wordvectors 中找到相應的詞向量。
trainFeatures[i, :] = getSentenceFeature(tokens, wordVectors, words)
然后用 sgd 和 softmax_wrapper 迭代 10000 次去訓練 weights:
weights = sgd(lambda weights: softmax_wrapper(trainFeatures, trainLabels, weights, regularization), weights, 3.0, 10000, PRINT_EVERY=100)
接著用 softmax regression 進行分類的預測:
_, _, pred = softmaxRegression(trainFeatures, trainLabels, weights)
上面用到了不同的 REGULARIZATION=[0.0, 0.00001, 0.00003, 0.0001, 0.0003, 0.001, 0.003, 0.01] ,在其中選擇 accuracy 最好的 REGULARIZATION 和相應的結果:
best_dev = 0
for result in results:
if result["dev"] > best_dev:
best_dev = result["dev"]
BEST_REGULARIZATION = result["reg"]
BEST_WEIGHTS = result["weights"]
用這個最好的參數在 test set 上進行預測:
_, _, pred = softmaxRegression(testFeatures, testLabels, BEST_WEIGHTS)
并且的到 accuracy:
print "Test accuracy (%%): %f" % accuracy(testLabels, pred)
下圖是 accuracy 和 REGULARIZATION 在 devset 和 trainset 上的趨勢:
以上就是 sentiment analysis 的基本實現,把它和爬蟲相結合,會有很多好玩的玩兒法!
[cs224d]
Day 1. 深度學習與自然語言處理 主要概念一覽
Day 2. TensorFlow 入門
Day 3. word2vec 模型思想和代碼實現
Day 4. 怎樣做情感分析
Day 5. CS224d-Day 5: RNN快速入門
Day 6. 一文學會用 Tensorflow 搭建神經網絡
Day 7. 用深度神經網絡處理NER命名實體識別問題
Day 8. 用 RNN 訓練語言模型生成文本
Day 9. RNN與機器翻譯
Day 10. 用 Recursive Neural Networks 得到分析樹
Day 11. RNN的高級應用
我是 不會停的蝸牛Alice
85后全職主婦
喜歡人工智能,行動派
創造力,思考力,學習力提升修煉進行中
歡迎您的喜歡,關注和評論!