簡體   English   中英

Keras自動編碼器

[英]Keras autoencoder

我很早以前就使用Java中的神經網絡工作,現在我正嘗試學習在Python中使用TFLearn和Keras。

我正在嘗試構建一個自動編碼器,但是當我遇到問題時,我向您展示的代碼沒有瓶頸特性(這會使問題更容易解決)。

在以下代碼中,我創建了網絡,數據集(兩個隨機變量),並在訓練后繪制了每個預測變量與其輸入之間的相關性。

網絡應該學習的是輸出與接收相同的輸入。

import matplotlib.pyplot as plt
import numpy as np
from keras.layers import Input, Dense
from keras.models import Model
from keras.models import load_model
from loaders.nslKddCup99.nslKddCup99Loader import NslKddCup99

def buildMyNetwork(inputs, bottleNeck):
    inputLayer = Input(shape=(inputs,))
    autoencoder = Dense(inputs*2, activation='relu')(inputLayer)
    autoencoder = Dense(inputs*2, activation='relu')(autoencoder)
    autoencoder = Dense(bottleNeck, activation='relu')(autoencoder)
    autoencoder = Dense(inputs*2, activation='relu')(autoencoder)
    autoencoder = Dense(inputs*2, activation='relu')(autoencoder)
    autoencoder = Dense(inputs, activation='sigmoid')(autoencoder)
    autoencoder = Model(input=inputLayer, output=autoencoder)
    autoencoder.compile(optimizer='adadelta', loss='mean_squared_error')
    return autoencoder


dataSize = 1000
variables = 2
data = np.zeros((dataSize,variables))
data[:, 0] = np.random.uniform(0, 0.8, size=dataSize)
data[:, 1] = np.random.uniform(0, 0.1, size=dataSize)

trainData, testData = data[:900], data[900:]

model = buildMyNetwork(variables,2)
model.fit(trainData, trainData, nb_epoch=2000)
predictions = model.predict(testData)

for x in range(variables):
    plt.scatter(testData[:, x], predictions[:, x])
    plt.show()
    plt.close()

盡管有時結果是可以接受的,但許多其他情況卻是不可接受的,我知道神經網絡具有權重隨機初始化,因此它可能會收斂到不同的解決方案,但是我認為這太多了,並且我的代碼中可能存在一些錯誤。

有時相關性是可以接受的

其他人很失落

**

更新:

**

感謝MarcinMożejko!

確實那就是問題所在,我最初的問題是因為我試圖構建一個自動編碼器,因此為了與標題保持一致,出現了一個自動編碼器的示例(只是制作了一個更復雜的數據集並更改了激活函數):

import matplotlib.pyplot as plt
import numpy as np
from keras.layers import Input, Dense
from keras.models import Model
from keras.models import load_model
from loaders.nslKddCup99.nslKddCup99Loader import NslKddCup99

def buildMyNetwork(inputs, bottleNeck):
    inputLayer = Input(shape=(inputs,))
    autoencoder = Dense(inputs*2, activation='tanh')(inputLayer)
    autoencoder = Dense(inputs*2, activation='tanh')(autoencoder)
    autoencoder = Dense(bottleNeck, activation='tanh')(autoencoder)
    autoencoder = Dense(inputs*2, activation='tanh')(autoencoder)
    autoencoder = Dense(inputs*2, activation='tanh')(autoencoder)
    autoencoder = Dense(inputs, activation='tanh')(autoencoder)
    autoencoder = Model(input=inputLayer, output=autoencoder)
    autoencoder.compile(optimizer='adadelta', loss='mean_squared_error')
    return autoencoder


dataSize = 1000
variables = 6
data = np.zeros((dataSize,variables))
data[:, 0] = np.random.uniform(0, 0.5, size=dataSize)
data[:, 1] = np.random.uniform(0, 0.5, size=dataSize)
data[:, 2] = data[:, 0] + data[:, 1]
data[:, 3] = data[:, 0] * data[:, 1]
data[:, 4] = data[:, 0] / data[:, 1]
data[:, 5] = data[:, 0] ** data[:, 1]

trainData, testData = data[:900], data[900:]

model = buildMyNetwork(variables,2)
model.fit(trainData, trainData, nb_epoch=2000)
predictions = model.predict(testData)

for x in range(variables):
    plt.scatter(testData[:, x], predictions[:, x])
    plt.show()
    plt.close()

在此示例中,我使用了TanH激活功能,但我嘗試了其他方法並同樣工作。 數據集現在有6個變量,但是自動編碼器有2個神經元的瓶頸; 只要結合變量0和1形成變量2到5,自動編碼器僅需要傳遞這兩個變量的信息並學習在解碼階段生成其他變量的函數。 上面的示例顯示了如何學習所有功能,但其中一個是除法...我還不知道為什么。

我認為您的案例相對容易解釋,為什么您的網絡可能無法學習身份功能。 讓我們看一下您的示例:

  1. 由於統一的分配,您的輸入來自2d空間-它不位於1d0d子流形上。 由此很容易看出,為了從您的自動編碼器中獲取身份函數, 一層都應該能夠表示一個范圍至少為二維的函數,因為最后一層的輸出也應該位於2d流形上。
  2. 讓我們遍歷您的網絡並檢查其是否滿足條件需求:

     inputLayer = Input(shape=(2,)) autoencoder = Dense(4, activation='relu')(inputLayer) autoencoder = Dense(4, activation='relu')(autoencoder) autoencoder = Dense(2, activation='relu')(autoencoder) # Possible problems here 

    您可能會看到瓶頸可能會導致問題-對於這一層,可能從一開始就很難滿足條件。 對於此層-為了獲得二維輸出范圍,您需要具有權重,該權重將使所有示例都不會落入relu飽和區域(在這種情況下,所有這些樣本都將以一種單位壓縮為0是什么使范圍不可能“完全” 2d )。 所以基本上-不會發生這種情況的可能性相對較小。 同樣,也不能忽略反向傳播不會將該單元移動到該區域的可能性。

更新:

在評論中,有人提出了一個問題,為什么優化器無法阻止或消除飽和度。 這是重要的relu缺點之一的示例-一旦示例落入relu飽和區域-此示例將不直接參與給定單元的學習。 它可以通過影響先前的單位來影響它-但是由於0導數-這種影響不是直接的。 因此,基本上不飽和的示例來自副作用-不是優化程序的直接作用。

這是一個非常酷的用例,可以看到並研究訓練神經網絡的困難。

實際上,我看到了多種可能性:

1)如果兩次運行之間有非常不同的結果,則可能來自初始化。 但是它也可能來自您的數據集,每次運行都不相同。

2)您的激活,更確切地說是S型,將使網絡難以學習相關性。 我會將該非線性更改為另一個“ relu”。 沒有理由在這里使用Sigmoid,我知道它看起來在0附近是線性的,但實際上並不是線性的。 要產生0.7,原始輸出將必須很高。 由於要約束該網絡,因此您想到的“簡單”關系並不是那么容易。

3)如果有時效果不好,也許需要更多的時期才能收斂?

4)也許您需要更大的數據集? 從理論上講,您是很好的,因為您的網絡中有900個樣本,其中<200個參數,但誰知道...

由於我現在正在通話中,所以無法嘗試所有這些操作,但是請隨時嘗試嘗試解決我給您的提示:)希望對您有所幫助。

編輯:

經過一些試驗,就像MarcinMożejko所說的那樣,問題出在激活方面。 您可以閱讀他的答案以獲取更多有關發生問題的信息。 解決它的方法是更改​​您的激活。 如果您是'relu'的粉絲,則可以使用此激活的特殊版本。 為此,請使用LeakyRelu層,並且不要將激活設置為上一層,如下所示:

    autoencoder = Dense(inputs*2)(inputLayer)
    autoencoder = LeakyReLU(alpha=0.3)(autoencoder)

這將解決您陷入非最佳解決方案的情況。 否則,如上所述,您可以嘗試不使用任何非線性。 您的損失將更快下降,並且不會陷入困境。

請記住,引入非線性是為了使網絡能夠在數據中找到更復雜的模式。 在您的情況下,您具有最簡單的線性模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM