讓你聽見你想要聽見的饶辙,讓你看見你想要看見的。Joi能滿足你的一切幻想斑粱。 --《銀翼殺手2049》
在這部電影中弃揽,用程序設(shè)定的虛擬人物,時時刻刻的與主角進行情感溝通珊佣,甚至產(chǎn)生了親密的感情蹋宦,或許這個在未來真的能夠?qū)崿F(xiàn)。現(xiàn)在轉(zhuǎn)到現(xiàn)實中來咒锻,近兩年AI的熱度暴漲冷冗,其中自然語言處理也是研究的重點,現(xiàn)在顯然已經(jīng)有非常顯著的效果惑艇。
情感在人類信息溝通的意義
情感對于人類的社交蒿辙、表達、記憶滨巴、決策和感知上都有很重要的作用思灌,有研究顯示人類交流中的80%信息都是帶有情感信息的。情感狀態(tài)不同會影響人的思維和行動恭取,特別是積極或消極所帶來的影響有很大的不同泰偿。由于情感在人類溝通的重大意義,所以在設(shè)計人與計算機交流的時候也是必不可少的部分蜈垮。通過和人的聊天耗跛,AI可用情感分析對實體進行高效率的自動化標注,學習到用戶的性格變得更加智能攒发。像微軟的小冰调塌,聊的越多越“懂”自己。
一般情況下惠猿,我們探討的情感分析多指文本中的情感分析羔砾,也有更多維的情感分析,比如文字+圖片+標簽+語音+面部表情、肢體動作等等姜凄,就像前一段時間被授予合法公民身份的AI機器人索菲亞可以通過攝像聲音和周圍的環(huán)境來通過面部表情來傳達情感政溃。人類能表達的情感的信息量的大小和維度。比如面對面交流時檀葛,情感性的信息往往是從語音語調(diào)进宝、面部表情纳决、肢體等多個維度表達出來的。然而到了人機交互中,情感寬帶的整個范式會發(fā)生較大的變化吁峻,如通過人機對話系統(tǒng)交流時栏渺,少了肢體這個維度魄咕,人類的情感帶寬似乎瞬間驟降了胧弛。但實際上也增加了幾個新的輸出維度,如圖片楚殿、表情包撮慨、回復(fù)時間的長短等。
情感分析之文本情感傾向分析
顯然脆粥,面對多維更加智能的場景砌溺,目前的技術(shù)實現(xiàn)起來難度很大,但是針對大多數(shù)的文本語意的表達還是有比較成熟的解決方案变隔,現(xiàn)在就來說一下深度學習在自然語言處理的表現(xiàn)吧规伐。
深度學習在情感分析中的應(yīng)用已經(jīng)較為普遍了,如利用 LSTM 結(jié)合句法分析樹匣缘、基于卷積神經(jīng)網(wǎng)絡(luò)和支持向量機等猖闪。一般情況下,對于各種方法的綜合創(chuàng)新應(yīng)用肌厨,能達到取長補短的效果培慌,進而能夠提高情感分析的準確率,另外還能從無標注的文本里學習到其中的隱藏特征柑爸,以實現(xiàn)端到端的分類吵护。
關(guān)于更多的深度學習相比于詞典以及傳統(tǒng)的機器學習的方式的優(yōu)勢,大家可以自行查閱相關(guān)文章表鳍,這篇文章只將用深度學習來簡單的訓(xùn)練一個樣本馅而,并預(yù)測任意一個句子的情感傾向。
情感分析工具keras进胯,語言包括中文和英文
開始之前,你需要對深度學習原理有比較深刻的了解原押,lstm的原理胁镐,調(diào)參優(yōu)化細節(jié),keras基本知識的掌握。項目github地址戳這里盯漂。
1. 準備語料
本次收集的語料不是太多颇玷。中文大概2w多條(淘寶評論),英文1w多條(電影評論)就缆,以后有時間會繼續(xù)補充語料帖渠。其中有5%作為驗證集,10%為測試集合竭宰。文件已經(jīng)切分好空郊,但是因為需要訓(xùn)練所有數(shù)據(jù)集,所以這個提前切分到不同文件夾并沒有什么作用(后面講到會重新合并再切分)切揭。
2.選擇語言版本狞甚,分別設(shè)置訓(xùn)練集、測試集廓旬、驗證集和維度
因為后面的程序要訓(xùn)練中文或英文哼审,所以在這里提前選擇語言版本和不同的語言版本訓(xùn)練相關(guān)的參數(shù)。
# 選擇語言中文還是英文
languageType = ''
while (languageType != 'c' and languageType != 'e'):
languageType = input("Please enter a train type(chinese enter lower: c , english enter lower: e): ")
max_length = '' #一句話最大長度
load_path = '' #文件加載路徑
language = '' #語言類型
tr_num = 17000 #訓(xùn)練集
va_num = 2000 #訓(xùn)練集
if languageType == 'c':
max_length = 100
load_path = 'data/chinese'
language = 'chinese'
tr_num = 17000
va_num = 2000
elif languageType == 'e':
max_length = 40
load_path = 'data/english'
language = 'english'
tr_num = 8000
va_num = 600
3.加載數(shù)據(jù)集
這里把中文和英文放在不同的文件夾下孕豹,利用 pandas
中的read_csv()
讀取數(shù)據(jù)集合并到一起涩盾,如果這里本來就是一個整的數(shù)據(jù)集。則直接讀取就好励背。
# 獲取csv文件:內(nèi)容放到數(shù)組里面 分別是訓(xùn)練集春霍、驗證集、測試集椅野,最后合并到一起
def sst_binary(data_dir='data/chinese'):
tr_data = pd.read_csv(os.path.join(data_dir, 'train_binary_sent.csv'))
va_data = pd.read_csv(os.path.join(data_dir, 'valid_binary_sent.csv'))
te_data = pd.read_csv(os.path.join(data_dir, 'test_binary_sent.csv'))
all_data = tr_data.append(va_data).append(te_data)
return all_data
4.數(shù)據(jù)預(yù)處理
這一步是針對中文和英文的特點來處理掉對分析無用的詞提升精度终畅。比如停用詞、標點符號竟闪、特殊字符离福、轉(zhuǎn)義字符等等。因為語料比較少炼蛤,這個程序還沒有針對這一塊做處理妖爷。
5.將詞語轉(zhuǎn)化為向量
這里是最核心的地方,深度學習在訓(xùn)練數(shù)據(jù)的時候要求輸入的數(shù)據(jù)是一個向量理朋,這樣才能進行矩陣運算絮识,也是多層感知器的輸入。所以如果直接將一組句子是無法識別的嗽上。所以最重要的一步就是將詞語轉(zhuǎn)化為詞向量次舌,可是如何才能得到向量呢?
這里用到的是詞嵌入的方法兽愤,大概步驟是:
- 中文最小統(tǒng)計粒度是詞彼念,所以要先切詞(
jieba
)將一句話按照詞語切分開來而非字挪圾。 - 將所有詞放在一起,統(tǒng)計每個詞出現(xiàn)的次數(shù)按照重大到小的排序逐沙,然后加上索引哲思。
- 將句子中的詞語全部替換成相應(yīng)的索引,這樣一個句子中的每個詞語就用一個數(shù)字去表示了吩案。
- 調(diào)用keras model第一層
Embedding()
棚赔,該層會利用詞嵌入將句子數(shù)字數(shù)組轉(zhuǎn)化為詞向量。
需要注意的是徘郭,jieba分詞雖然是分中文的靠益,但是也可以處理英文(英文是按照空格切分的),這樣可以得到比較統(tǒng)一的數(shù)組shape崎岂。
#定義模型
class Model(object):
def __init__(self, sentence_max_length=100):
sentence_max_length = sentence_max_length #截斷詞數(shù) cut texts after this number of words (among top max_features most common words)
sentence_drop_length = 5 #出現(xiàn)次數(shù)少于該值的詞扔掉捆毫。這是最簡單的降維方法
#將每個句子里的詞轉(zhuǎn)化成詞頻索引值
def transform(data):
#如果是中文調(diào)用結(jié)巴分詞
xs = data['sentence'].apply(lambda s: list(jieba.cut(s)))
#將所有詞放到一個數(shù)組中
word_all = []
for i in xs:
word_all.extend(i)
#統(tǒng)計詞頻并排序建索引
global word_frequency, word_set
word_frequency = pd.Series(word_all).value_counts() #統(tǒng)計詞頻,從大到小排序
word_frequency = word_frequency[word_frequency >=
sentence_drop_length] #出現(xiàn)次數(shù)小于5的丟棄
word_frequency[:] = list(range(
1,
len(word_frequency) + 1)) #將詞頻排序的結(jié)果加索引
word_frequency[''] = 0 #添加空字符串用來補全冲甘,之前丟棄的后面的找不到的會用0代替
word_set = set(
word_frequency.index) #經(jīng)過處理之后的所有詞的數(shù)組集合,并且去掉可能存在的重復(fù)元素
#將詞語替換成按照所有訓(xùn)練集詞頻排序后的索引
xt = xs.apply(lambda s: word2num(s, sentence_max_length))
xt = np.array(list(xt))
yt = np.array(list(data['label'])).reshape(
(-1, 1)) #此處用來調(diào)整標簽形狀n行1列 (-1是模糊控制即有不定多少行绩卤,1是1列)
#當前訓(xùn)練集合詞的索引長度
wi = len(word_frequency)
return xt, yt, wi
self.transform = transform
6.keras 訓(xùn)練數(shù)據(jù)集
這一部分就交給keras處理了,具體用法可以參見keras中文文檔江醇,可以自定義一些參數(shù)濒憋,比如訓(xùn)練輪數(shù)、激活函數(shù)陶夜、加入驗證集等等凛驮。當然核心的還是lstm了,相對于RNN条辟,在訓(xùn)練長文本有更好的效果黔夭。訓(xùn)練完了之后可以選擇保存模型。方便下次直接調(diào)用羽嫡。
#將詞轉(zhuǎn)化為數(shù)字向量 即一個句子里的每個詞都有用上面生成的索引值代替
def word2num(s, sentence_max_length):
s = [i for i in s if i in word_set]
s = s[:sentence_max_length] + [''] * max(0, sentence_max_length - len(s))
return list(word_frequency[s])
# krea 訓(xùn)練數(shù)據(jù)集
def model_train(x, y, wi, language, sentence_max_length=100, tr_num=17000, va_num=2000):
global model
model = Sequential()
model.add(Embedding(wi, 256, input_length=sentence_max_length))
model.add(LSTM(128))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(
loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(
x[:tr_num],
y[:tr_num],
batch_size=128,
nb_epoch=30,
validation_data=(x[tr_num:tr_num + va_num], y[tr_num:tr_num + va_num]))
score = model.evaluate(
x[tr_num + va_num:], y[tr_num + va_num:], batch_size=128)
model.save('model_' + language + '.h5')
return score[1]
#加載已經(jīng)訓(xùn)練好的模型
def model_load(language):
global model
model = load_model('model_' + language + '.h5')
7.預(yù)測單個句子
預(yù)測單個句子依然需要將這個句子分詞本姥,然后將詞轉(zhuǎn)化為數(shù)字,所以還是用到訓(xùn)練模型時用到的處理方式杭棵。
#單個句子的預(yù)測函數(shù)
def model_predict(s, sentence_max_length=100):
s = np.array(word2num(list(jieba.cut(s)), sentence_max_length))
s = s.reshape((1, s.shape[0]))
return model.predict_classes(s, verbose=0)[0][0]
好了婚惫,大功告成,我們已經(jīng)可以直接測試訓(xùn)練的結(jié)果了魂爪。
總結(jié)
現(xiàn)在先舷,我們已經(jīng)能夠利用keras里的lstm對文本進行預(yù)測情感傾向了。但是這里完美還是有很大距離滓侍,需要不斷的調(diào)參來提高準確度蒋川。能夠提升的地方比如加大訓(xùn)練集數(shù)量、對數(shù)據(jù)預(yù)處理撩笆、調(diào)整訓(xùn)練次數(shù)等等捺球。當然還有更酷的方案比如雙向lstm這樣的訓(xùn)練方式街图,綜合對比,或許都是改良的途徑懒构。
目前一套模型同時解決中文和英文的例子還是非常少,畢竟語言的差異還是非常大耘擂,接下來會繼續(xù)對其中進行一些探索胆剧,這個也是我對自然語言處理中的情感分析一點小小的嘗試。