精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
如何用 Keras 搭建深度學習模型

在這篇小文章中,我們將簡要討論如何使用KERAS這個現在最新的深度學習框架來構造實用的深度學習模型。

深度學習是目前最熱門的高級分析技術之一,在很多方面表現出了超越傳統機器學習方法的有效性。但是在常用的TensorFlow,CNTK,Theano等計算環境中實現不同的深度學習模型仍然需要耗費很多時間來編寫程序。KERAS的出現提供了一個高度抽象的環境來搭建深度學習模型,特別是其簡單易用,跟網絡結構一一對應的特點使得其迅速在數據科學家這個使用人群中流行起來。

什么是KERAS

KEARS是Google工程師Fran?ois Chollet為主創人員,基于Python開發和維護的一個抽象的神經網絡建模環境,提供了一系列的API供用戶調用構造自己的深度學習網絡。KERAS的出發點就是為用戶提供一個能夠快速實現模型的手段,從而縮短建模迭代的時間,加快模型試驗的頻率。用KERAS開發者的話說,就是要做好的科研必須盡可能地縮短從想法到實現結果的時間。在業界工作中這也是成功的關鍵要素之一。

相比較于常見的深度學習環境,比如TensorFlow,CNTK,Theano,Caffe等,KERAS有以下幾個不同:

  1. 設計初衷就是方便以模塊化地方式快速構造深度學習模型的原型。

  2. 可以很方便地在CPU和GPU之間切換。

  3. KERAS本身只是描述模型的環境,其計算平臺目前依賴于TensorFlow,CNTK和Theano這三種,以后會拓展到其他流行的計算平臺上,比如mxNet等。

  4. KERAS的拓展性既可以通過自定義KERAS里的激活函數或者損失函數等能自定義的部分進行,也可以通過引用對應的計算平臺的自定義部分進行,具有一定的靈活性。

跟這些流行的計算平臺一樣,KERAS也支持常見的深度學習模型,比如卷積神經網絡,循環神經網絡以及二者的組合等。

使用KERAS構造深度神經網絡有一系列相對固定的步驟:

  • 首先要將原始數據處理成KERAS的API能夠接受的格式,一般是一個張量的形式,通常在維度上表示為(批量數,[單一樣本對應張量的維度])。這里[單一樣本對應張量的維度] 是一個通用的說法,對應于不同類型的模型,數據有不同的要求。

    通常,如果是一個簡單的全鏈接模型,則單一樣本對應張量的維度就是特征個數;如果是一維的時間序列數據,并要用循環神經網絡模型訓練的話,則單一樣本對應張量的維度是時間步和每個時間步對應的回看序列長度;如果輸入數據是圖像,并使用卷積神經網絡模型進行訓練,則單一樣本張量對應圖像的高,寬和色彩頻道三個維度。但是如果是使用全連接模型訓練圖像數據,則單一樣本對應張量是該圖像扁化(Flatten)以后的向量長度,其為高,寬和色彩頻道各個維度數量的乘積。一般卷積神經網絡最靠近輸出層的那層都設置一個全連接層,因此也需要扁化輸入張量。

  • 其次要構造需要的深度學習模型。這一步又分為以下兩個步驟:

    選擇模型的類型。KERAS里定義了兩大類模型:1)序列模型(Sequential); 2)通用模型(Model)。

    序列模型指的是深度模型每一層之間都是前后序列關系,如下圖所示:

    Figure 1:MLP是一個典型的序列模型,圖片來源

    可以看到從左到右,輸入層到隱含層到輸出層每一層之間都是前后依次相連的簡單關系。這個簡單的網絡結構可以用三句KERAS命令實現:

    model=Sequential()model.add(Dense(5, input_shape=(4,), activation=’sigmoid’))model.add(Dense(1, activation=’sigmoid’))

    而通用模型則是對應更廣義的模型,具備更大的靈活性。上面提到的序列模型也可以用通用模型來表達,這個我們在后一節詳解。

    當然通用模型更能用來描述層與層之間有較復雜關系的情況,比如非相鄰的層之間進行連接,或者多個神經網絡的合并等。比如我們可以使用通用模型進行矩陣分解:

    user_in = Input(shape=(1,), dtype='int64', name='user_in')u = Embedding(n_users, n_factors, input_length=1)(user_in)movie_in = Input(shape=(1,), dtype='int64', name='movie_in')v = Embedding(n_movies, n_factors, input_length=1)(movie_in)x = merge([u, v], mode='dot')x = Flatten()(x)model = Model([user_in, movie_in], x)model.compile(Adam(0.001), loss='mse')

    這里構造了一個基于矩陣分解的推薦系統的一個深度學習模型,其對應的網絡結構如下圖所示:

    Figure 2:矩陣分解的深度學習模型

    細化模型的結構。其實上面已經展示了模型結構細化之后的情況。一般來說,確定了模型類型以后,其結構不外乎每層的類型是什么,是全連接層還是卷積層還是放棄(Dropout)層;每層的其他參數是什么,比如如果需要指定激活函數,那么使用什么樣的激活函數,如果是卷積層,那么需要多少過濾器,每個過濾器的大小是怎樣的?等等這些都可以通過設定不同的參數進行細化。

  • 然后對模型進行編譯,編譯完成以后可以查看模型的基本信息,特別是參數的數量;

  • 最后帶入數據對模型進行擬合。一般來講,如果數據是靜態的張量數據,通過使用fit方法。如果數據特別大,可是使用可迭代的data generator對象,并使用fit_generator方法來擬合。

KERAS和深度學習模型的對應關系

KERAS既然是開發出來快速構造深度學習模型的工具,那么它的API和深度學習模型的要素都有很強的對應關系。

正如上面所說,目前的深度學習模型都可以納入序列模型或者通用模型的,那么我們用圖示的方式來表示這個對應關系,方便讀者理解。這里網絡圖為了方便與按行排列的代碼對應,對每一層都進行了標注。

下圖展示的是一個典型的全連接序列模型:

這個序列模型可以使用如下的KERAS命令快速搭建:

Model = Sequential()Model.add(Dense(10, activation=’sigmoid’,                   input_shape=(8, ))           【隱含層1+輸入層】Model.add(Dense(8, activation=’relu’))          【隱含層2】Model.add(Dense(10, activation=’relu’))         【隱含層3】Model.add(Dense(5, activation=’softmax’))       【輸出層】

上面的序列模型也可以用通用模型的API描述的結果,其與圖中的網絡結構有更強的對應關系:

x = Input(shape=(8,))                        【輸入層】b = Dense(10, activation=’sigmoid’)(x)       【隱含層1】c = Dense(8, activation=’relu’)(b)           【隱含層2】d = Dense(10, activation=’relu’)(c )         【隱含層3】out = Dense(5, activation=’softmax’)(d)      【輸出層】model = Model(inputs=x, outputs=out)

上面也舉了另外的比較復雜的例子。在后面的具體案例中,我們也會強調網絡結構和對應的KERAS命令,使讀者能建立起較強的聯系。

使用KERAS構造深度推薦系統

推薦系統是機器學習最廣泛的應用領域之一,大家熟悉的亞馬遜、迪士尼、谷歌、Netflix 等公司都在網頁上有其推薦系統的界面,幫助用戶更快、更方便地從海量信息中找到有價值的信息。比如亞馬遜(www.amazon.com)會給你推薦書、音樂等,迪士尼(video.disney.com)給你推薦最喜歡的卡通人物和迪士尼電影,谷歌搜索更不用說了, Google Play、 Youtube 等也有自己的推薦引擎、推薦視頻和應用等。下面是我登陸亞馬遜之后的一個推薦頁面,可見我之前應該是購買了咖啡機,所以會有相關的產品推薦出來。

Figure 4:亞馬遜的推薦頁面局部

推薦系統的最終目的是從百萬甚至上億內容或者商品中把有用的東西高效地顯示給用戶,這樣可以為用戶節省很多自行查詢的時間,也可以提示用戶可能忽略的內容或商品,使用戶更有黏性,更愿意花時間待在網站上,從而使商家可以從內容或者商品中賺取更多的利潤,即使流量本身也會使商家從廣告中受益。

傳統上,推薦系統是基于矩陣分解的協同過濾算法,前面也展示了這樣的一個簡單模型。下面我們著重介紹深度學習推薦系統。這個模型除了能將用戶和可選產品聯系起來意外,還能將其他輔助數據,比如用戶年齡,地區,上網設備以及各種產品屬性,聯系起來。這里通過嵌入(Embedding)這種技術將不同的信息串在一起作為輸入層,再繼續搭建不同的神經網絡模型,最后一層用預測評分作為輸出層。雖然這里的數據只有用戶編碼和電影產品編碼,但是這樣的結構可以拓展到包含其他相關數據。下圖展示了這樣的一個深度模型的結構示意圖:

Figure 5:深度模型

有了這個示意圖,我們就可以很方便地用KERAS依次構造。這里我們假設已經將用戶和電影產品做了按照One Hot編碼形式組織好了。

首先用嵌入層對用戶和電影進行嵌入映射:

k = 128model1 = Sequential()model1.add(Embedding(n_users + 1, k, input_length = 1))model1.add(Reshape((k,)))model2 = Sequential()model2.add(Embedding(n_movies + 1, k, input_length = 1))model2.add(Reshape((k,)))

這里的k是映射到的空間的維度。在一般的業務系統中我們可能有上百萬的用戶和產品,經過嵌入映射到128維的實數域上以后顯著地降低了整個系統的維度和大小。

以上幾句命令實現了上圖從最低下到“用戶嵌入”和“電影嵌入”這一階段的編程。

其次,我們需要用第三個神經網絡把前面的兩個嵌入網絡映射所得到的向量疊加在一起:

model = Sequential()model.add(Merge([model1, model2], mode = 'concat'))

至此完成了到第一個粗箭頭的網絡構造。兩個網絡已經合并為一個網絡。

下面的命令依次完成“隱含層128”和“隱含層32”的構造:

model.add(Dropout(0.2))model.add(Dense(k, activation = 'relu'))model.add(Dropout(0.5))model.add(Dense(int(k/4), activation = 'relu'))model.add(Dropout(0.5))

下面繼續構造“隱含層8”:

model.add(Dense(int(k/16), activation = 'relu'))model.add(Dropout(0.5))

隱含層構造完畢之后,需要構造輸出層。因為是預測連續變量評分,最后一層直接上線性變化:

model.add(Dense(1, activation = 'linear'))

至此,模型構造完畢,可以編譯了:

model.compile(loss = 'mse', optimizer = 'adam')

這里使用了均方差(MSE)作為損失函數,并使用了ADAM優化算法。

下面,為了能訓練模型,需要將數據構造為[users, movies]的形式:

users = ratings['user_id'].valuesmovies = ratings['movie_id'].valuesX_train = [users, movies]

最后訓練模型:

model.fit(X_train, y_train, batch_size = 100, epochs = 50)

使用movielens的用戶觀看電影評分數據進行訓練和驗證,我們發現這個模型的誤差在0.8226左右,大約一個評分等級不到。即使這樣一個簡單的模型,效果還是比較好的。如果進一步優化結構,或者引入其他信息,誤差還可以進一步降低。

使用KERAS構造圖像識別系統

圖像識別是深度學習最典型的應用之一。關于深度學習的圖像識別可以追溯很長的歷史,其中最具有代表性的例子是手寫字體識別和圖片識別。手寫字體識別主要是用機器正確區別手寫體數字 0~9。銀行支票上的手寫體識別技術就是基于這個技術。圖片識別的代表作就是 ImageNet。這個比賽需要團隊識別圖片中的動物或者物體,把它們正確地分到一千個類別中的其中一個。

圖像識別有很多種技術可以實現,目前最主流的技術是深度神經網絡,其中尤以卷積神經網絡(CNN)最為出名。卷積神經網絡(見圖1)是一種自動化特征提取的機器學習模型。從數學的角度看,任何一張圖片都可以對應到 224 × 224 × 3 或者 32 × 32 × 3 等三維向量,這取決于像素。我們的目標是把這個三維向量(又被稱為張量)映射到 N個類別中的一類。神經網絡就是建立了這樣一個映射關系,或者稱為函數。它通過建立網狀結構,輔以矩陣的加、乘等運算,最后輸出每個圖像屬于每個類別的概率,并且取概率最高的作為我們的決策依據。 下面是一個典型的序列卷積神經網絡模型的結構:

Figure 6:卷積神經網絡結構。來源于CNTK教程。

上面這個網絡依次展示了卷積網絡模型的主要要素:

  • 輸入層的圖像;

  • 卷積操作;

  • 激活函數的應用;

  • 池化操作;

  • 將數據展平(Flatten),為輸出到全連接層做準備;

  • 全連接層準備輸出;

  • softmax應用于分類問題的全連接層作為輸出層。

下面詳細介紹一下在KERAS中如何對應地進行編程處理。

  • 首先,這是一個序列模型,因此先要聲明一個序列模型的對象:

    model=Sequential()
  • 卷積是應用一個局部的過濾器到原始數據的過程,比如下圖就展示了一個3x3的過濾器應用在一個7x7的圖像上過程。假設在當前步,這個過濾器的權重經過學習得到如圖所示的權重結果,在當前步繼續進行卷積操作就是將這個3x3的過濾器從左上角每次要么向右要么向下移動一格,和對應的圖像局部的3x3的區域進行依元素點乘求和得到卷積的結果。因為依次移動,到最邊上的時候過濾器會超出圖像的邊界,一般會將這些對應的卷積結果刪除,從而卷積后的張量維度會少于原始圖像。比如這個例子中原圖為7x7,使用一個3x3的過濾器卷積之后最后兩列和兩行進行卷積的時候會使過濾器超過邊界,因此最后的卷積結果是一個5x5的圖像。這里可以使用多個過濾器,每個過濾器應用一次,每次應用產生的卷積結果構成隱含層的一層。比如采用16個過濾器,如果不刪除邊界的過濾結果,則得到新的[7x7x16]的張量。

Figure 7:卷積演示,來源于CNTK教程。

在KERAS里,對于圖像這種二維數據,一般使用Conv2D這個二維卷積層。Conv2D有幾個必備的參數:

  1. 首先指定過濾器數量 filters,是一個整數;

  2. 第二是要指定二維過濾器的大小,比如(3,3);

  3. 第三要指定步長,即延某軸移動的時候是依次移動一個像素還是多個像素,默認為1;

  4. 第四要指定補齊策略padding,即是否要將在邊界的卷積結果去掉。如果值為”same”,則不去掉,卷積結果和輸入圖像有同樣的高和寬;如果值為”valid”,則不會處理過濾器會超出邊界的像素。

  5. 最后,如果卷積層是第一層,那么還需要指明輸入數據的維度input\_shape。因為一般用TensorFlow或者CNTK做后臺,輸入數據要求是channel_last,因此輸入的原始維度為[樣本量,高,寬,頻道],那么這里的維度只需要去掉樣本量即可,即為[高,寬,頻道數],一般用X.shape[1:]即可得到。

對于上面的例子,KERAS里的典型寫法是:

model.add(Conv2D(filters=16, kernel_size=(3, 3),                  strides=1, padding=”valid”,                  input_shape=xtrain.shape[1:]))
  • 再次要添加激活層引入激活函數,通常是一個非線性的函數。激活函數既可以通過在Conv2D里面指定activation=參數引入,也可以通過單獨添加Activation層引入。卷積神經網絡常用的激活函數是Rectified Linear Unit, 簡稱relu。該函數其實就是max(0, x),在層次較深的網絡中比以前常用的取值區間在(0,1)或者(-1, 1)之間的sigmoid類激活函數效果好,因為不存在梯度消失的問題。

    如果是通過參數,則上面的代碼改寫為:

    model.add(Conv2D(filters=16, kernel\_size=(3, 3),             strides=1, padding=”valid”,             activation=’relu’)

    如果通過添加激活層引入,則在上面的代碼后添加:

    model.add(Activation(‘relu’))
  • 然后進行的池化操作是在卷積神經網絡中對圖像特征的一種處理,通常在卷積操作和激活函數之后進行。池化操作是將原有輸入按照一定大小切分成互不交叉的局部區域,目的是為了計算特征在局部的充分統計量,從而降低總體的特征數量,防止過度擬合和減少計算量。下圖展示了最大池化方法的應用。在一個6x6的圖像上應用3x3的池化操作,將原輸入矩陣切割為不相交叉的2x2區域,每個區域的取值是對應原輸入局部的最大值。

Figure 8:最大池化操作

對應于圖像的最大池化層通過MaxPooling2D,KERAS也支持平均池化層,區別在于取對應局部的平均值作為池化后結果,方法為AveragePooling2D。對應上面的例子,KERAS的命令如下:

model.add(MaxPooling2D(pool_size=(3, 3))
  • 為了輸出到全連接層,先要對數據進行展平(Flatten)。這是因為全連接層只處理包含樣本數在內一共二維的數據,要求第一維是樣本數,第二維是所有特征的個數。因此對于一個包含2000個樣本,每個樣本是28x28x3的小圖像的數據,展平之后是一個2000x2352的矩陣,其中2352是28,28,3的乘積。在KERAS里進行展平非常簡單,在上面的MaxPooling2D層之后添model.add(Flatten())即可,KERAS能自己分析出輸入和輸出的維度。

  • 在前面這些處理之后,但是在輸出之前,通常會添加一個或者多個全連接層進一步處理數據。全連接層可以通過Dense指出,指明輸出神經元個數和激活函數即可:

    model.add(Dense(1000, activation=’relu’))
  • 最后使用一個全連接層作為輸出層,同樣要求使用softmax激活函數,并使用跟輸出類別同樣多的神經元個數。比如識別0—9十個數字,那么就應該寫作:

    model.add(Dense(10, activation=’relu’))

把所有步驟組合到一起,我們就可以將圖6顯示的一個卷積神經網絡模型相應地寫為KERAS代碼了:

model=Sequential()model.add(Conv2D(filters=32, kernel_size=(3, 3),          padding='same',          input_shape=X_train.shape[1:],          activation='relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='valid'))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Flatten())model.add(Dense(128, activation='relu'))model.add(Dense(num_classes, activation='softmax'))

是不是很簡單?

要訓練這個模型非常簡單。我們先編譯這個模型并顯示其關鍵信息:

model.compile(loss='categorical_crossentropy', optimizer='adagrad', metrics=['accuracy'])model.summary()

Figure 9:模型信息

我們看到這個模型一共有421642個參數,大多來自于倒數第二層的全連接層。

擬合這個模型也很簡單:

model.fit(X_train, y_train,          epochs=20, verbose=1,          batch_size=10,          validation_data = (X_test, y_test))

這里使用最標準的fit方法。其中指定幾個核心參數:

  1. 訓練用特征數據X_train

  2. 訓練用結果數據y_train

  3. 迭代次數epochs

  4. 批量大小用batch_size指定

  5. verbose表示顯示訓練過程的信息,如果值為0不顯示任何中間信息,如果為1顯示按批量擬合的進度,如果為2則顯示擬合結果信息。

  6. 另外讀者還可以指定驗證數據集,用validation_data這個參數表示,其包含一個tuple,第一個元素是驗證用特征數據,第二個是驗證用結果數據。

下面我們使用這個模型訓練識別0-9這十個數字,使用著名的MNIST數據。不過在訓練之前還需要提及對數據的處理:

  • 首先將數據重塑為[樣本數,高,寬,色彩通道數]的格式。這個可以通過numpy.reshape方法來實現。因為keras自帶的MNIST數據已經是numpy的多維矩陣,并且是單色的,因此色彩通道數為1,因此數據重塑可以用下面的命令實現。讀者可自行重塑驗證用數據。

    X_train = X_train.reshape(X_train.shape[0],                      X_train.shape[1],                      X_train.shape[2], 1).astype(float)
  • 其次,需要將數據的取值壓縮到[0, 1]之間。這有利于擬合時用的隨機梯度遞降算法的穩定和收斂。這可以使用X_train /= 255.0 來實現。

  • 最后要將結果數據變為One Hot Code形式。KERAS提供了一個非常方便的方法to_categorical來實現這個功能:

    y_train = keras.utils.to_categorical(y_train, len(set(y_train)))

下圖的結果顯示即使是這個非常簡單的模型,其在驗證數據上的預測準確率都是非常高的,達到了99.14%。

使用KERAS可以非常方便的構造自己的卷積神經網絡,對于比較復雜的情況,也可以使用已經訓練好的一些常見的高效模型,比如VGG16,Xception 等做遷移訓練來擬合自己的數據。

Figure 11: VGG16結構,來源

上圖是著名的VGG16模型的結構。根據剛才的學習結果,讀者可以很快地模仿這個結構搭建自己的類似模型,但是KERAS在application庫里已經提供了現成訓練好的VGG16模型供讀者讀入使用。讀者可以引用這個模型,將頂層去掉用自己的數據重新訓練,但是底層的參數借用VGG16已經訓練好的權重。這就是遷移學習的思路,可以大大降低需要訓練的參數數量,加快新模型的開發。這里使用了通用模型以便在現有的VGG16模型上進行修改:

model_vgg = VGG16(include_top = False,                  weights = 'imagenet',                  input_shape =(224,224,3))model = Flatten(name = 'flatten')(model_vgg.output)model = Dense(10, activation = 'softmax')(model)model_vgg_mnist = Model(model_vgg.input, model,                        name = 'vgg16')

這里首先引用VGG16模型,但是通過參數include_top=False指定遷移除頂層以外的其余網絡結構到自己的模型中。Weights=’imagenet’表示借用的權重是用ImageNet數據訓練出來的額。

其次,通過函數方法在修改過的VGG16模型上構造一個新的扁平層用來連接新構造的全連接層,這個全連接層跟前面的模型沒有區別。最后把修改過的VGG16模型和新的頂層疊加起來并賦予新的名字vgg16。這樣就得到了一個基于VGG16的新模型。

使用KERAS構造時間序列預測模型

時間序列是在商業數據或者工程數據中經常出現的一種數據形式,是以時間為次序排列,用來描述和計量一系列過程或者行為的數據的統稱。比如每天商店的收入流水或者某個工廠每小時的產品產出都是時間序列數據。一般研究的時間序列數據有兩種類型。最常見的是跟蹤單一的計量數據隨時間變化的情況,即每個時間點上收集的數據是一個一維變量,這種是最常見的,通常的時間序列默認就是這種數據,也是本章研究的對象。另外一種時間序列數據是多個對象或者多個維度的計量數據隨時間變化的情況,即每個時間點上收集的數據是一個多維變量,這種一般也被稱為縱向數據(Longitudinal Data),但是不屬于這里介紹的對象。

在這里我們介紹如何搭建一個LSTM深度學習模型來對在漢口測量的長江每月流量數據進行預測建模。該數據來源于DataMarket 的時間序列數據庫,由澳大利亞莫納什大學的統計學教授Rob Hyndman 創建,收集了數十個公開的時間序列數據集。

漢口長江月流量數據包含從 1865 年 1 月到 1978 年 12 月在漢口記錄的長江每月的流量,總計 1368 個數據點。計量單位未知。

Figure 12:長江月度流量時間序列

在一般的時間序列建模中,都需要檢驗數據的平穩性,因為傳統時間序列建模都是建立在平穩數據的假設之上。這個數據具備非常強的年度周期性。使用傳統的統計技術建模的時候都需要偵測周期性,并消除之,對消除周期性之后的數據運用ARIMA模型建模。

Figure 13:長江月度流量局部和移動平滑結果

我們可以通過周期圖譜法(Periodogram)來得到主要的周期幅度。在Python中可以使用scipy.signal.periodogram來得到周期圖譜。在這里我們不是使用原始數據,而是使用原始數據的自相關函數的周期圖譜來計算主要周期,這樣可以抵消噪音的影響。對讀入pandas DataFrame的原始數據ts運行下面的程序我們可以得到如下的周期圖譜和計算得到的主要周期長度。

import statsmodels.api as smfrom statsmodels.tsa.stattools import acffrom scipy import signalimport peakutils as peakacf_x, acf_ci = acf(ts, alpha=0.05, nlags=36)fs=1f, Pxx_den = signal.periodogram(acf_x, fs)index = peak.indexes(Pxx_den)cycle=(1/f[index[0]]).astype(int)fig = plt.figure()ax0 = fig.add_subplot(111)plt.vlines(f, 0, Pxx_den)plt.plot(f, Pxx_den, marker='o', linestyle='none', color='red')plt.title('Identified Cycle of %i' % (cycle))plt.xlabel('frequency [Hz]')plt.ylabel('PSD [V**2/Hz]')plt.show()print( index, f, Pxx_den)

Figure 14:周期圖譜

很明顯有一個周期為 12 個月的季節性。雖然考慮到這個數據的本質是長江水文資料, 12 個月的周期是非常自然的預期,但是這個方法展示了對 ACF 序列運用周期圖法(periodogram)找季節性周期的可靠性。在傳統方法里,這里需要通過取間隔為12 的差分來消除周期性,得到一個盡可能平穩的時間序列,進而采用ARIMA模型建模。在Python里,單周期的時間序列數據,知道周期的長度以后可以直接使用季節性ARIMA模型(SARIMA)來訓練。

但是在使用循環神經網絡模型的時候我們不用考慮這些情況,可以直接使用長短記憶模型。此外,在使用LSTM這種序列模型的時候在使用LSTM對這種單一時間序列進行建模的時候,一般通過一下步驟:

  1. 將數據標準化為[0,1]區間。

  2. 按照LSTM的要求,將輸入數據組織為[樣本數,時間步,特征變量數]的三位格式來組織。

  3. 定義一個LSTM深度學習模型,通常為一個序列模型對象,逐層添加LSTM層或者其他層,最后通過一個全連接層輸出到輸出層。

  4. 最后對需要的時間段進行預測。

首先對數據進行標準化,我們使用sklearn包里的MinMaxScaler函數:

scaler = MinMaxScaler(feature_range=(0, 1))trainstd = scaler.fit_transform(train.values.astype(float).reshape(-1, 1))teststd = scaler.transform(test.values.astype(float).reshap

其次,我們將訓練數據和測試數據組織成需要的格式,這個格式與我們將要建立的LSTM模型有關。這里我們對每個輸入構造一個LSTM神經元,一個60個輸入單元,每一個對應一個時間步。這60個單元的輸出會作為一個全連接層的輸入,這個全連接層直接產生下K個連續時間步的輸出預測。作為防止過度擬合的正則化手段,我們在LSTM層和全連接層 之間加了一個Dropout層。這個Dropout層在訓練的時候會隨機放棄一部分權重的更新,但是在進行預測的時候所有權重都會被用到。

Figure 15:LSTM網絡結構 (修改自CNTK Tutorial)

對于這樣的網絡結構,我們需要如下的一個函數來定義我們的數據,即將數據組織成為[批量數,時間步數,滯后特征數]的形式。這個可以通過如下的函數來實現:

def create_dataset(dataset, timestep=1, look_back=1, look_ahead=1):    from statsmodels.tsa.tsatools import lagmat    import numpy as np    ds = dataset.reshape(-1, 1)        dataX = lagmat(dataset,                   maxlag=timestep*look_back,                   trim='both', original='ex')    dataY = lagmat(dataset[(timestep*look_back):],                  maxlag=look_ahead,                  trim='backward', original='ex')    dataX = dataX.reshape(dataX.shape[0],                          timestep, look_back)[:-(look_ahead-1)]    return np.array(dataX), np.array(dataY[:-(look_ahead-1)])

執行下面的命令就可以生成所需數據:

lookback=1lookahead=24timestep=60trainX, trainY = create_dataset(trainstd,                        timestep=timestep,                        look_back=lookback,  look_ahead=lookahead)trainX, trainY = trainX.astype('float32'), trainY.astype('float32')truthX, truthY = create_dataset(truthstd,                        timestep=timestep,                        look_back=lookback, look_ahead=lookahead)

有了如圖15的網絡圖以后,就可以開始定義我們的LSTM深度學習模型。

batch_size=100model = Sequential()model.add(LSTM(48, batch_size=batch_size, \input_shape=(timestep, lookback), kernel_initializer='he_uniform'))model.add(Dropout(0.15))model.add(Dense(lookahead))model.compile(loss='mean_squared_error', optimizer='adam')

調用fit方法就可以快速的訓練這個模型。我們指定迭代20次,小批量數為100):

model.fit(trainX, trainY, epochs=20, batch_size=batch_size, verbose=1)

下圖展示了擬合過程的信息:

Figure 16:LSTM擬合過程信息

那么這個模型的擬合效果如何呢?

Figure 17:LSTM擬合結果

我們看到擬合效果還不錯。平均絕對誤差百分比(MAPE)只有25%不到,比用傳統的SARIMA模型效果要好點。其次,LSTM模型一次輸出未來24個時間點的預測值,使用起來比用SARIMA迭代預測方便很多。另外需要指出的是我們也可以直接在模型中指定損失函數為MAPE,這樣更好優化衡量指標。

小結

在這篇短文中,我們介紹了一個目前正在流行起來的深度學習建模環境KERAS。這個建模環境相對于傳統的計算環境,比如CNTK,TensorFlow,Theano等具有抽象性高,易用性好的特點,同時又依托于這幾種計算環境,具有一定的可拓展性,非常適合于從事深度學習的實踐者使用。

我們看到使用KERAS可以非常直觀地描述神經網絡結構,幾乎可以達到所見即所得的情況。我們在文中還分別介紹了三種流行的應用領域,分別是:

  • 深度推薦模型,運用嵌入技術可以將不同類型的信息有機結合在一起構造一個深度神經網絡推薦系統。

  • 圖像識別模型,運用多層卷積神經網絡對圖像進行切割分析,得到一個精度很好的手寫數字分類器。同樣的技術和模型可以直接移植到其他物體識別數據上,比如CIFAR10等。我們也介紹了運用已經訓練好的現成模型進行遷移學習的手段,減少擬合的參數量,在保持一定精度的情況下提高訓練速度。

  • 簡單時間序列預測模型,運用長短記憶(LSTM)神經網絡模型來有效預測具備一定周期性的時間序列模型。一個非常簡單的單層LSTM模型既可以達到定制的SARIMA模型的預測精度。

本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
python在Keras中使用LSTM解決序列問題
FAQ
Keras入門必讀教程:手把手從安裝到解決實際問題
LSTM模型原理詳解及Python實現
一文看懂遷移學習:怎樣用預訓練模型搞定深度學習?
VGG16遷移學習,實現醫學圖像識別分類工程項目
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 福安市| 玉山县| 甘谷县| 于都县| 娱乐| 呼图壁县| 高安市| 威宁| 海门市| 锦屏县| 石首市| 边坝县| 肇州县| 新宁县| 旬阳县| 崇文区| 明溪县| 保靖县| 保山市| 喀喇| 三台县| 武功县| 明溪县| 苏尼特左旗| 彰武县| 黑河市| 勃利县| 甘孜| 肃宁县| 徐汇区| 富锦市| 伊吾县| 布尔津县| 梁平县| 剑阁县| 南通市| 连南| 陇西县| 泾源县| 莒南县| 长兴县|