【问题标题】:Digging deeper into LSTM Keras深入挖掘 LSTM Keras
【发布时间】:2017-07-07 09:25:14
【问题描述】:

我正在使用 LSTM 框架对具有四列的传感器数据运行回归问题。我还没有使用任何正则化。

下面指定我使用的代码;

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import math
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from keras import callbacks
from keras.layers import Flatten

# load the dataset
gbx_data = pd.read_csv('/home/prm/Downloads/aggregated_vibration.csv', usecols=[4,5,6,7])
dataset = gbx_data.values
dataset = dataset.astype('float32')

scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)


train_size = int(len(dataset) * 0.63)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
print(len(train), len(test))

def create_dataset(dataset, look_back):
  dataX, dataY = [], []
  for i in range(len(dataset)-look_back-1):
    a = dataset[i:(i+look_back), :]
    dataX.append(a)
    dataY.append(dataset[i + look_back, :])
  return np.array(dataX), np.array(dataY)


look_back = 10
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)

trainX = trainX.reshape(trainX.shape[0], look_back, trainX.shape[2])    # model input shape & model output shape will be same always #
testX = testX.reshape(testX.shape[0], look_back, testX.shape[2])

batch_size = 120

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []

    def on_epoch_end(self, epoch, logs={}):
        self.losses.append(logs.get('loss'))


model=Sequential()
model.add(LSTM(10, return_sequences=True, input_shape=(look_back, 4), activation='relu'))
model.add(Dropout(0.2))
model.add(LSTM(12, return_sequences=True, input_shape=(look_back, 4), activation='relu'))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(4, activation='relu'))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
history = LossHistory()
model.fit(trainX, trainY, epochs=10, batch_size=batch_size, callbacks=[history])
print(history.losses)

我想知道以下问题的规范;

  • 对于每个纪元结束,我都会损失LossHistory 类。如何在每个时期后获得权重?我知道model.get_weights() 给了我所有的权重。但是如何在每个 epoch 之后获得它们?
  • 我如何才能最佳地了解我应该在 LSTM 和密集层中使用哪个激活函数,以便我的数据执行“最佳”并为我提供良好的准确性?
  • model.get_config() 给了我'stateful': False。如果我执行一个有状态的 LSTM,实际会发生什么变化并检查哪些值我可以理解变化?
  • 如果return_sequences=False会发生什么变化?
  • 如何为 LSTM 和 Dense 层选择最佳的隐藏节点(神经元)数量?

运行上述代码,10个epoch后的损失历史如下,

[0.016399867401633194, 0.0029856997435597997, 0.0021351441705040426, 0.0016288172078515754, 0.0012535296516730061, 0.0010065438170736181, 0.00085688360991555948, 0.0007937529246583822, 0.00073356743746738303, 0.00069794598373472037]

准确率为 77%。

我也在添加几种迭代方法的表格。

对不起,如果我问了很多。如果可能,请分享您的帮助。

【问题讨论】:

    标签: deep-learning keras lstm


    【解决方案1】:

    每个 epoch 后的权重:

    对于每个epoch之后的处理,你可以使用Callback,尤其是LambdaCallback,它允许非常灵活的使用。

    定义一个 lambda 回调,它将在每个 epoch 之后获得权重:

    getWeightsCallback = LambdaCallback(on_epoch_end=getWeightsFunction)
    

    地点:

    myWeights = []
    def getWeightsFunction(epoch,logs):
        #adapt this code:
        myWeights.append(model.get_weights())
    

    然后将回调添加到您的fit 方法中:

    model.fit(....., callbacks=[getWeightsCallback])
    

    激活函数

    很遗憾,如果有答案,我无法回答。但我确实相信这是一件直观的事情,应该进行试验,直到找到最适合您的特定任务和模型的东西。

    不过,我所知道的是关于最后一层。这一项与最终任务完全相关。

    • 使用activation='softmax'loss='categorical_crossentropy' 会受益于一个分类问题,在众多分类中只有一个真正的类

    • 具有多个真实类的分类问题通常使用activation='sigmoid'loss='binary_crossentropy'

    • 其他问题也应该有更好的选择,具体取决于应用程序。

    有状态网络。

    循环网络有一个“内部状态”,大致是通过一个序列逐步建立的“记忆”。

    此状态对于每个序列都是唯一的。每个序列构建一个状态。

    • 在无状态网络中,每个序列的状态都会重置
    • 在有状态网络中,状态不会自动重置。

    不重置状态的想法是能够分批划分每个序列。如果您的序列太长(导致 RAM 或性能问题),您将它们分成几部分,模型将理解您的批次不是“新序列”,而是“先前序列的续集”。

    显着的变化是需要定义额外的参数,例如批量大小和按顺序正确传递数据。

    Keras documentation
    An indirectly related question

    返回序列

    由于循环网络以时间步长工作,因此每个时间步长都有一个结果。
    您可以选择输出所有这些结果,以一个序列结束(与输入的时间步数相同)。或者您可以选择只获得最终结果,丢弃时间步长:

    • 返回序列=True:输出(批量大小、时间步长、内存单元)
    • 返回序列=False:输出(批量大小、内存单元)

    Same documentation as before

    理想的细胞数

    抱歉,这绝对是一个悬而未决的问题。这完全取决于您想要做什么、数据的大小、模型的架构。

    真的没有现成的答案。为某个应用程序创建一个完美的架构正是全世界每个人都在寻求的。

    您可以进行实验或尝试查找与您正在研究的同类事物相关的论文,以了解“迄今为止”的最佳做法。

    一些相关问题:

    • 过拟合:您的模型太强,或者您的数据太少。你的训练准确度变得很好,但你的验证准确度并没有发展。粗略地说,模型正在记忆训练数据,因为它太好了
    • 欠拟合:你的模型太弱了,根本解决不了任务

    【讨论】:

    • 太好了..解释得很好!
    • myWeights.add(model.get_weights()) 对我不起作用。扔我; NameError:名称“myWeights”未定义
    • 根据您的需要调整该代码。你想在哪里存储重量?打印它们?救他们?把它们放在一个var中?这就是您选择如何处理 model.get_weights() 的地方——我编辑了我的答案以获得更具体的示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 2011-02-07
    • 2019-04-24
    相关资源
    最近更新 更多