當前位置:
首頁 > 科技 > 人工智慧這麼火,可你真的會用 TensorFlow?

人工智慧這麼火,可你真的會用 TensorFlow?

關鍵時刻,第一時間送達!

看到最近很多在講 TensorFlow 的文章,忽然想寫一些關於機器學習和演算法基礎類的文章,當一個東西每個人都在談論的時候就少了很多機會與新鮮感。

再有意思的東西看多了也會厭煩,回頭再看看自己定的這些題目有種翻看十年前的朋友圈一樣的尷尬。

每天都是人工智慧,打開新聞是人工智慧,開會是人工智慧,連用個手機都有個 AI 晶元。在這個信息爆炸的時代,有一種對於新技術的冷靜的態度而又不顯得與外界格格不入,這種分寸是很難把握的。

但凡事都有始有終,作為專欄的最後一篇文章就聊聊循環神經網路 (RNN),並談談可視化的內容。其實一直感覺作為一個靠數據過活的人,以恰當而體面的方式進行數據的可視化也是必備的技能之一。

那麼上面的一段話中我是什麼態度呢?正面?負面?還是二者兼而有之?「Bag of words」 模型會認為這是偏於負面的因為出現了的 「不想、厭煩、尷尬、很難」 之類的辭彙,但是後面的內容顯然又不止於此。

有句話說的挺好 「都 20 多年了,我們依然在用詞袋子模型做文本分類」。其實 LDA 模型已經考慮了詞語與詞語的關係,這種關係更類似於向量的主成分,而非前後文。因此作為一個開始。

本次文章就從 RNN 模型搭建一個最簡單的實例開始,那麼什麼是所謂的簡單呢?生成文本:

RNN 入門與生成文本

RNN 模型相比於前面所說的 「Bag of words」 模型來說,可以兼顧前後文。但是以這種方式處理文本會遇到一個比較大的問題就是效率。其相比於前面所說的前饋神經網路(CNN,全鏈接等)更加難以訓練。

優勢是可以完成更加複雜的目的,比如自然語言處理。那麼作為 RNN 的入門實例,本節中就從基礎的開始:語句生成。TensorFlow 文檔中就是給的類似的例子,可以參考 TensorFlow 文檔。官方文檔寫的還是比較清楚的。

數據分析

其實所有機器學習演算法都不難理解, 最複雜的反而是數據預處理 。這屬於體力活,每天對於各種數據建模是所有人都不想面對卻又不得不面對的。

相比於前面的卷積和全鏈接網路,RNN 網路的數據預處理可能理解起來更複雜一些,很多人都是卡在了這裡而學不下去了。

從文本向量化開始就是 「詞袋子 (Bag of words)」 模型,在這個模型之對於文本的向量化方式是類似於稀疏矩陣的形式。矩陣的行是每篇文章統計,列是所有文章中出現的所有的詞。

很顯然,這個矩陣是稀疏的,因為絕大多數情況下文章所包含的詞的數量是固定的,不太可能出現一篇文章包含所有詞的情況出現。

如上面所說數據矩陣 M 是稀疏的,其中所有的 m 篇文章中出現的所有詞 (字) 個數為 n。這就是我們所說的詞袋子模型,就像把詞語隨機的扔進一個袋子里。這顯然只是統計詞頻沒有任何前後文。

這種稀疏性還帶來另一個問題就是兩句表述意思類似的話,但是由於沒有相同詞語出現使得兩個文章向量距離很遠,就像?:

你技術很好,很有經驗,我們需要研究一下,等通知吧

不好意思面試沒通過

以上兩句話沒有出現任何相同詞語,從詞袋子模型看來是完全不同的意思,但是以我們經驗來看錶達的意思卻是相似的。於是衍生出的一種改進方式就是挑出一些詞加權組合到一起,整體做一個判別,這就是 LDA 演算法。

我個人非常討厭貝葉斯理論,於是從另一個角度理解其實他就是對於矩陣 M 進行的分解。通過這種方式將一些看似不相關的內容總結到了一起,表現為 「特徵向量」。

注意文中用到的一個概念就是 以我們的經驗來看 這種所謂的經驗也就是知識。人在判斷一句話是什麼意思的時候融入了個人的經驗知識。而神經網路是可以保存這種經驗知識的,表現為權值。

一般人在說 RNN 可以藉助於前後文信息進行判斷的時候其實他忽略了一個問題,就是 RNN 在判斷的時候融入了以 往學習到的經驗 。

這相比於 LDA 演算法又更近一步。本質來說 LDA 是對傳統的只統計詞頻的方法的改進,而 RNN 卻對於文字輸入順序也有了感知。

於是有了這一節中的主要內容,就是用神經網路完成一個語句預測的任務。首先來分析一下任務,我們需要給定一句話的前幾個詞,然後推測後續會出現哪些字。

這個過程是一個馬爾可夫鏈,但是不太喜歡概率,所以直接描述過程,假設我給定一個三個字的開頭:

晚來天(?)(?)

根據前三個字來預測接下來兩個字是什麼,那麼下一個字可能是晴,可能是欲,也有可能是未,那麼根據概率隨機選擇了(欲),接下來就根據 「晚來天欲」 這四個字進行預測,可能隨機選擇的字是(雨),那麼最終五個字就是

晚來天(欲)(雨)

當然概率有隨機性,可能第一步時選擇的是晴,那麼最終形成的詩句就是:

晚來天(晴)(處)

還是因為概率,可能我們最終選擇的完全不像是詩句,比如:

晚來天(氣)(息)

這就完全沒有意境了。這裡面起關鍵作用的實際上是給定下一步出現的字的概率,概率太平均的話也就是一種初始狀態,最終可能形成完全不是人說的東西,這就很尷尬了。

所以前面我說,我並不喜歡隨機性太強的東西,降低這種隨機性需要持續大量的數據進行訓練。概率這個很容易映射到神經網路之中就是 softmax,這個過程可以給定一個字接下來可能出現的概率。

至此其實可以看到其與前面所說的 「詞袋子」 模型的文本向量化過程的區別。

在中文文本處理中與英文文本處理的一個區別就是需要進行分詞處理,這是因為單個中文字與單個字母一樣無法表達一個有效的信息。這就需要用幾個字來表達一個意思。

對於英文來講天然就有 「分詞」 也就是空格,對於中文來講需要人為的去完成這個過程。但是對於本次任務,我們只是對單個字行了 「編號」。

這裡我們依靠的是神經網路自身的強大表達能力。於是詩句的處理就類似於一個查字典的過程:

word_dict = { , : 0, 。 : 1,
: 2, 不 : 3, 人 : 4, 山 : 5, 風 : 6, 日 : 7, 雲 : 8, 無 : 9, 何 : 10, 一 : 11, 春 : 12, 月 : 13, 水 : 14, 花 : 15, 來 : 16, 有 : 17, 中 : 18, 秋 : 19, 上 : 20, 時 : 21, 天 : 22, 歸 : 23, 心 : 24, 相 : 25, 此 : 26, 年 : 27, 生 : 28, 長 : 29, 夜 : 30, 自 : 31, 去 : 32, 知 : 33, 空 : 34, ..., 挪 : 5386}

舉個例子來說:

寒心睹肉林,飛魄看沉湎。

[42, 24, 1791, 1818, 72, 0, 88, 1337, 108, 670, 4206, 1, 2]

可以看到,句號、逗號以及語句結束標誌 『
』 都進行了編碼。這裡編號的規則很簡單,統計字出現的次數按順序編碼。』
』 等進行編碼則用於判斷語句的末尾,這可以輔助進行判斷語句結束。

編碼結束後所得的結果是一系列整型數字。如今又出現了一個問題就是編碼後的一維數據並不適合神經網路處理,因為幾 k 級別數字幾乎可以肯定使得神經網路訓練出現問題。

因此還需要的處理就是將其擴展成向量形式的表示,也就是相當於對於 one-hot 編碼進行降維,TensorFlow 已經提供了相應的工具:

embedding = tf.get_variable("embedding", [len(words), rnn_size])

通常而言的處理過程中的 embedding 可以用 word2vector 的方式,也就是將意思相近的詞所形成的向量距離也是相近的,這可以簡化神經網路結構設計。

注意這裡說的是簡化網路結構設計,由於 word2vec 過程可以看成是一個神經網路層,因此藉助於神經網路強大的表達能力有時候是可以省略這個過程的。

本文就是省略了這個過程這個過程將編碼轉換為適合神經網路處理的向量。至此文本預處理工作描述完畢。

神經網路結構與訓練

RNN 神經網路結構其實並不複雜。對於最傳統的 RNN 結構而言只是加入了一層向量用於保存上一時間步中的輸出結果:

整個過程可以寫成:

對於每一個時間步均會有一個對應的輸出 。而對於多層的 RNN 網路而言是在之上加入相同的 RNN 層:

可以看到整個過程都沒有一般圖示中所出現的跨層循環。以上 RNN 網路結構可以通過 BPTT 演算法進行訓練:

其中對於 W 來說略有不同,因為

所以對 W 求偏導:

這是一個沿著時間反向傳播的過程,如果句子比較長會使得訓練過程難以進行,因此在一些演算法時在時間步上進行了截斷。

可以看到相比於前饋神經網路,RNN 網路的複雜度提高了很多,複雜度的提升代表著自由參數的提升,也就是說神經網路的擬合、表達能力提升。在利用 Tensorflow 實現的過程中也是比較複雜的:

如此完成了兩層 RNN 的搭建。可以看到,整個過程並沒有 CNN 網路那麼簡單,而是需要一些輔助函數完成多層 RNN 網路的搭建。之後就是一個 feed 數據的過程:

outputs = []for time_step in range(self.num_steps): if time_step > 0: tf.get_variable_scope().reuse_variables()

(cell_output, state) = cell(inputs[:, time_step, :], state)

outputs.append(cell_output)

每步中都輸入一個向量化後的文字 ,而獲取的輸出為 cell_output,對應的輸出就是 ,這裡有個小問題就是每一步中都用到了相同的變數,因此需要變數復用也就是:

tf.get_variable_scope().reuse_variables()

當然有更簡單的方式:

這種方式可以直接獲取輸出序列。之後的訓練過程就直接用輸出序列與預計輸出做對比。但是預計輸出是一系列的整型,因而依然可以用 Tensorflow 提供的函數:

來簡化編程過程。整個過程都需要用到一些輔助函數以幫助簡化程序的編寫,這也就是前面所說的 RNN 網路用 TensorFlow 實現的複雜性。

這樣在 feed 數據的過程中直接輸入就可以了,這裡數據還是有個問題需要描述,由於我們只需要預測的是下一個詞是什麼因此輸入的 x 和 y 之間之差一個字元:

x = [42, 24, 1791, 1818 ]

y = [ 24, 1791, 1818, 72]

結果與生成

首先預設一個初始字,計算下一個字出現的概率,根據概率選取詞語並將其作為下一時間步的輸入,循環這個過程直到遇到語句結束符 『
』。如此就生成了一句詩。

來看下迭代了 40 個回合後所得的結果,寫個藏頭詩:

title: 《文章難寫》

line1: 文字命高人,無行亦遲芳。

line2: 章句掩疑在,循容爭未微。

line3: 難慕高翁亂,初行且自吟。

line4: 寫月秋堂閉,流年到海深。

看起來還是有效果的,其實這個效果並不在字間結構和韻律上,而是整個過程並未控制輸出長短,完全依靠神經網路自身通過判斷 『
』 結束標誌來控制迭代。

這就是說我們神經網路的學習過程已經可以對於五言詩進行一個很好的長短的控制。對於未訓練好的網路而言其結果可能是:

title: 人工智慧

line1: 人務牧牛冠,儀資擅劇額。

line2: 工佣輸富寢,羸葬竟何源。

line3: 智訓擊綃粟,契莓桐狼。

line4: 能誘貽納都,簫韶頗阻擎。

語句更加不通順,而且長短有所不同。

RNN 應用與文本分類

文本分類是自然語言處理中一直比較重要的部分。這個分類包括一些語句情感的分類以或者用於垃圾郵件的鑒別。

這種自然語言處理的任務用 LDA 降維 + 演算法來完成,目前來看 效果是可以的 。但是有些人會認為這不夠炫,所以產生了 RNN 的需求,它可以分析前後文。

數據預處理工作

整個的數據預處理以及向量化與前面的文本生成任務沒有什麼不同,但是這裡為了方便處理,只選擇了文章中前一部分詞進行處理,這是合理的,想像一下自己在閱讀文章的過程中很可能沒有通讀全文,只是讀了第一個中心句就知道文章是何種意思了。為了方便理解依然展示一下數據:

article1:遊戲 ||《XXX》角逐金翎獎最佳單機遊戲 9 月是金秋的季節,9 月是收穫的季節。格銳數碼在這個金秋為廣大的玩家精心準備了大型武俠史詩遊戲——《XXX》。擁有華麗的遊戲畫面的《XXXXX》,將帶您領略仙魔玄幻世界的無窮魅力。在這個收穫的季節里,格銳數碼攜《XXXXX》與廣大玩家見面了,在新浪,QQ 等網站上均可以下載到遊戲,享受遊戲的新玩法和新功能······

article2:...

...

前面用雙豎線分割的就是文本標籤,後面是文本,本次文本分類中更加推薦用的向量化方式為 word2vec,因為可以獲得更好的分類結果,但是由於訓練熟練有限,所以選擇的方式依然是簡單的 embedding,進行單個字級別的處理。

用於分類的輸出

前面說到的用於文本生成的網路生成的是每個詞的概率,然後在通過概率的方式去選擇下一步需要的詞語 (字),而對於文本分類的數據而言則利用最後一個時間步的輸出作為判別依據:

last = _outputs[:, -1, :]

net = slim.fully_connected(last, hidden_num,

scope= full1 )

logits = slim.fully_connected(net, class_num,

scope= full1 )

選取最後一個輸出的意思是經歷了所有的輸入之後獲取最後一個結果,這樣可以對於全文進行有效的分析。輸出的結果直接用於對於文本類別的預測。

注意一個問題 ,在文本生成任務之中是輸出 ,而在進行文本分類任務中同樣也是輸出 ,這兩個雖然形式相同但是目的完全不同,一個是為了預測 「字」,一個是為了預測文本類別。

兩個完全不同的任務用基本類似的輸出形式,這也是所謂的神經網路表達能力強大所表現的地方。其可以通過訓練去自適應的調整輸出目的。

結果

迭代幾次後可以發現準確率可以達到:

Epoch: 6

Iter:0, Train Loss:0.3, Train Acc:91.41%, Val Loss:0.51, Val Acc:86.88%

作為對比選擇如下方式進進行分析:

分詞

LDA 降維 (60)

隨機森林分類

如此操作之後,分類可以達到的準確率為 99%,有點顛覆世界觀,這是因為一直在強調 RNN 可以分析前後文,可是對於很多的任務而言可能並不需要前後文,所以說基於詞頻統計的方法依然很有市場,效率是最大的問題。同時我們過度依賴了 RNN 的強大的表達能力而忽略了數據處理過程。

前面說到 RNN 網路可以用於文本處理,同時其實 CNN 也可以完成相同的任務,有個文獻說多層的 CNN 結構可能比幾層 RNN 結構分類效果更好。但這也不一定,但是可以肯定的是 CNN 比較好訓練。

可視化部分

可視化個人以為一直是數據分析工作中非常重要的部分,好的可視化可以起到事半功倍的效果。經常聽說的一句話就是神經網路的可解釋性比較差。

也就是說通常來說用於解釋的可視化是比較困難的,只是有一個訓練好的網路結構,在此之上就是直接輸出結果了。

就像一個 「黑盒」,所以說其可視化過程相比較來說是比較困難的,但是為了做例子,選擇將 LDA 的內容做一些可視化。

這裡再提一句,其實很多降維操作的一個主要好處就是可以進行可視化,而這種可視化做出來效果是很好的。

詞雲

詞雲表示的方式簡單直觀。可以直接對所謂的主題 (其實就是矩陣分解後的向量) 進行直接可視化工作:

以上是選擇文本降維後所用的 「主題」,很明顯的可以看出部分主題寫的是什麼。所有文章大約都是對於以上的幾個主題進行的加權組合。詞語可以很好的表現這種權重之間的區別,表現為詞的大小。

當然用 Echarts 是很容易的進行文本的可視化的,當然沒有用到 python 的 json 的庫,而是直接:

data = []for itr, idx in enumerate(topic_words):

data.append({ name :idx, value :np.exp(-itr/100)+1})if(itr > 50):breakjson_str = str(data)

是一個簡單粗暴而且投機取巧的方式。可能直到目前都沒有描述上面是什麼意思。

所以這裡先給一個 實例,實際上 echarts 是以 json 數據格式作為交換的,而 python 的字元串與 json 的數據格式有著天然的相似性,看下圖:

直接對 python 的字典、列表進行字元串轉換,就可以直接獲取類似於 js 格式的數據。

比重與權值

比重與權值的可視化是比較方便的可以利用 Echarts 所提供的餅圖和平行線,這裡魔改官方實例:

以上就是對於主題的一些可視化,可能配色還是比較成問題,改個背景什麼的就好,配色問題一直是最難的。

這裡用到的就是列表的類型轉換了。

其他

目前來說數據分析的可視化都是集中於一些餅圖、線圖進行的整合與分析,比如這種:

當然上面這個圖形是 p 的,但是這個圖形實現起來並不困難,只要稍微懂一些 html。但是麻煩的是美工,稍微差一些的配色就會使得整個圖形觀感差很多,比如我上面做的這個錯誤的示範。

當然最喜好的 echarts 的是它的動態圖形功能,比如做的一個流體模擬的動態:

當然這些只是為可視化提供一些思路。

寫在最後

至此專欄算是寫完了,以 RNN 作為一個結束是比較合適的。本身專欄的一個目標就在於介紹 TensorFlow 的一些使用。

全鏈接網路和卷積神經網路均是簡單可以實現的,在理解設計結構之後可以很容易的進行分析處理和訓練,而 RNN 則相對複雜一些,需要用到很多的輔助函數,還有一些內容諸如 DropOut 沒講,這是訓練過程優化的部分。

RNN 網路作為一個複雜的實現,其強大表現為時序輸出,這同時需要我們做一個思維的轉換,比如可以將 CNN 的結果當成時序數據進行 RNN 處理,這方面的應用比如語音識別,還有見下圖:

識別一些不定長的驗證碼,這是 RNN+CNN 的例子,CNN 部分用於識別圖形,而 RNN 將其進行串聯起來。

目前的神經網路研究工作集中於兩個方面:第一個是網路模型的設計,比如 ResNet 等;還有一個是訓練過程的優化。這兩方面實際上都需要很強的數學基礎。

在工作之中用到需要我們去借鑒一些現有文獻中的設計好的結構。之於說從頭完成一個神經網路設計,以目前的情況來看實際上是非常複雜的,這屬於真正意義上的創新。而工作只是應用而已,並無創造的必要。

神經網路還有很多的應用場景,這些根據場景選擇一些網路結構是合適的,通常也有很多應用方面的文章可供參考。長期只是看 CNN 處理圖形、RNN 處理文本其實會極大的限制自己的想像力。

這對於演算法設計是不利的。同時還需要說的一點就是上世紀一些簡單的機器學習演算法雖然簡單,但是其中的可解釋性、計算效率等方面依然不是深度神經網路所能比擬的。

深度神經網路並非無所不能,不要過於神話。

GIF/292K


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

一個戲精程序員的內心獨白……
6歲會編程,14歲就被麻省理工錄取,神童謊言是如何誕生的?
512 個 AI 職位、11 萬美元年薪,盤點 2018 最佳人工智慧公司
蘋果發布 2017 年度應用榜單,你的 App 榜上有名嗎?
512個AI 職位、11 萬美元年薪,盤點 2018 最佳人工智慧公司

TAG:CSDN |