讓機器讀懂人心蔓同,lstm實現(xiàn)中英文情感傾向分析

讓你聽見你想要聽見的饶辙,讓你看見你想要看見的。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)化為詞向量次舌,可是如何才能得到向量呢?

這里用到的是詞嵌入的方法兽愤,大概步驟是:

  1. 中文最小統(tǒng)計粒度是詞彼念,所以要先切詞(jieba)將一句話按照詞語切分開來而非字挪圾。
  2. 將所有詞放在一起,統(tǒng)計每個詞出現(xiàn)的次數(shù)按照重大到小的排序逐沙,然后加上索引哲思。
  3. 將句子中的詞語全部替換成相應(yīng)的索引,這樣一個句子中的每個詞語就用一個數(shù)字去表示了吩案。
  4. 調(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')


中文語言訓(xùn)練過程與結(jié)果
英文語言訓(xùn)練過程與結(jié)果

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ù)對其中進行一些探索胆剧,這個也是我對自然語言處理中的情感分析一點小小的嘗試。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末醉冤,一起剝皮案震驚了整個濱河市秩霍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚁阳,老刑警劉巖铃绒,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異螺捐,居然都是意外死亡颠悬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門定血,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赔癌,“玉大人,你說我怎么就攤上這事澜沟≡制保” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵茫虽,是天一觀的道長刊苍。 經(jīng)常有香客問我,道長濒析,這世上最難降的妖魔是什么正什? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮悼枢,結(jié)果婚禮上埠忘,老公的妹妹穿的比我還像新娘。我一直安慰自己馒索,他們只是感情好莹妒,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绰上,像睡著了一般旨怠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜈块,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天鉴腻,我揣著相機與錄音迷扇,去河邊找鬼。 笑死爽哎,一個胖子當著我的面吹牛蜓席,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播课锌,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼厨内,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了渺贤?” 一聲冷哼從身側(cè)響起雏胃,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎志鞍,沒想到半個月后瞭亮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡固棚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年统翩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片此洲。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡唆缴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出黍翎,到底是詐尸還是另有隱情面徽,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布匣掸,位于F島的核電站趟紊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碰酝。R本人自食惡果不足惜霎匈,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望送爸。 院中可真熱鬧铛嘱,春花似錦、人聲如沸袭厂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纹磺。三九已至帖烘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橄杨,已是汗流浹背秘症。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工照卦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乡摹。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓役耕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親聪廉。 傳聞我的和親對象是個殘疾皇子蹄葱,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容