[python] Keras LSTM 이해

나는 LSTM에 대한 나의 이해를 조정하려고 노력하고 있으며 Keras에서 구현 한 Christopher Olah 의이 게시물 에서 지적했습니다 . Keras 튜토리얼을 위해 Jason Brownlee이 작성한 블로그를 따르고 있습니다. 내가 주로 혼동하는 것은

  1. 데이터 계열을 [samples, time steps, features]
  2. 스테이트 풀 LSTM

아래에 붙여 넣은 코드를 참조하여 위의 두 가지 질문에 집중하십시오.

# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)

# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], look_back, 1))
testX = numpy.reshape(testX, (testX.shape[0], look_back, 1))
########################
# The IMPORTANT BIT
##########################
# create and fit the LSTM network
batch_size = 1
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
for i in range(100):
    model.fit(trainX, trainY, nb_epoch=1, batch_size=batch_size, verbose=2, shuffle=False)
    model.reset_states()

참고 : create_dataset은 길이 N의 시퀀스를 취하고 N-look_back각 요소가 look_back길이 시퀀스 인 배열을 반환합니다 .

시간 단계 및 기능이란 무엇입니까?

알 수 있듯이 TrainX는 Time_steps 및 Feature가 각각 마지막 2 차원 (이 특정 코드에서 3 및 1) 인 3 차원 배열입니다. 아래 이미지와 관련하여 many to one분홍색 상자의 수가 3 인 경우를 고려하고 있습니까? 또는 문자 그대로 체인 길이가 3 (즉, 3 개의 녹색 상자 만 고려 됨)을 의미합니까?여기에 이미지 설명을 입력하십시오

다변량 계열을 고려할 때 기능 인수가 관련성이 있습니까? 예를 들어 두 개의 금융 주식을 동시에 모델링 하는가?

상태 저장 LSTM

상태 저장 LSTM은 배치 실행간에 셀 메모리 값을 저장한다는 의미입니까? 이 경우, batch_size하나이고, 훈련 실행 사이에 메모리가 재설정되므로 상태가 좋았다는 것이 중요합니다. 나는 이것이 훈련 데이터가 섞여 있지 않다는 사실과 관련이 있다고 생각하지만 어떻게 해야할지 모르겠습니다.

이견있는 사람? 이미지 참조 : http://karpathy.github.io/2015/05/21/rnn-effectiveness/

편집 1 :

빨간색과 초록색 상자가 동일하다는 @van의 의견에 대해 약간 혼란 스럽습니다. 확인하기 위해 다음 API 호출이 롤링되지 않은 다이어그램에 해당합니까? 특히 두 번째 다이어그램에 주목하십시오 ( batch_size임의로 선택되었습니다).
여기에 이미지 설명을 입력하십시오
여기에 이미지 설명을 입력하십시오

편집 2 :

Udacity의 딥 러닝 과정을 수행했지만 time_step 인수에 대해 여전히 혼란스러워하는 사람들은 다음 토론을 참조하십시오 . https://discussions.udacity.com/t/rnn-lstm-use-implementation/163169

최신 정보:

그것은 밝혀 model.add(TimeDistributed(Dense(vocab_len)))내가 무엇을 찾고 있었다되었다. 예를 들면 다음과 같습니다. https://github.com/sachinruk/ShakespeareBot

업데이트 2 :

https://www.youtube.com/watch?v=ywinX5wgdEU 에서 LSTM에 대한 나의 이해를 요약했습니다.



답변

우선, 시작하기 위해 훌륭한 자습서 ( 1 , 2 )를 선택하십시오 .

시간 단계의 의미 : Time-steps==3X.shape (데이터 모양 설명)에서 세 개의 분홍색 상자가 있음을 의미합니다. Keras에서 각 단계에는 입력이 필요하므로 녹색 상자 수는 일반적으로 빨간색 상자 수와 같아야합니다. 구조를 해킹하지 않는 한

하나에 많은 많은 대 많은 : keras에서는이 return_sequences당신의 초기화 매개 변수 LSTMGRU또는 SimpleRNN. 때 return_sequences입니다 False(기본적으로), 다음은 한 많은 그림과 같이. 반환 모양은 (batch_size, hidden_unit_length)마지막 상태를 나타내는입니다. 때 return_sequences입니다 True, 다음은 많은 많은 . 반환 형태는(batch_size, time_step, hidden_unit_length)

기능 인수가 관련이 있습니까? 기능 인수는 “빨간색 상자의 크기” 또는 각 단계의 입력 차원을 의미합니다. 예를 들어 8 가지 종류의 시장 정보를 예측하려면을 사용하여 데이터를 생성 할 수 있습니다 feature==8.

Stateful : 소스 코드를 찾을 수 있습니다 . 상태를 초기화 할 때이면 stateful==True마지막 훈련의 상태가 초기 상태로 사용되며, 그렇지 않으면 새 상태가 생성됩니다. stateful아직 켜지지 않았습니다. 그러나 batch_size1 만 할 수 있다는 데 동의하지 않습니다 stateful==True.

현재 수집 된 데이터로 데이터를 생성합니다. 모든 순차적 정보를 수집하기 위해 하루를 기다리지 않고 재고 정보가 스트림으로 제공되는 이미지를 작성하십시오 . 네트워크를 통한 교육 / 예측 동안 온라인으로 입력 데이터를 생성하려고 합니다. 동일한 네트워크를 공유하는 400 개의 주식이있는 경우을 설정할 수 있습니다 batch_size==400.


답변

허용 된 답변을 보완하는이 답변은 각성 행동과 각 그림을 달성하는 방법을 보여줍니다.

일반적인 케 라스 행동

표준 케 라스 내부 처리는 다음 그림과 같이 항상 많거나 많습니다 ( features=2예 : 압력 및 온도를 사용한 경우).

ManyToMany

이 이미지에서는 다른 차원과의 혼동을 피하기 위해 단계 수를 5로 늘 렸습니다.

이 예의 경우 :

  • 우리는 N 오일 탱크가 있습니다
  • 우리는 5 시간 동안 시간 단위로 조치를 취했습니다 (시간 단계).
  • 우리는 두 가지 특징을 측정했습니다 :
    • 압력 P
    • 온도 T

입력 배열은 다음과 같은 모양이어야합니다 (N,5,2).

        [     Step1      Step2      Step3      Step4      Step5
Tank A:    [[Pa1,Ta1], [Pa2,Ta2], [Pa3,Ta3], [Pa4,Ta4], [Pa5,Ta5]],
Tank B:    [[Pb1,Tb1], [Pb2,Tb2], [Pb3,Tb3], [Pb4,Tb4], [Pb5,Tb5]],
  ....
Tank N:    [[Pn1,Tn1], [Pn2,Tn2], [Pn3,Tn3], [Pn4,Tn4], [Pn5,Tn5]],
        ]

슬라이딩 윈도우 용 입력

LSTM 레이어는 종종 전체 시퀀스를 처리해야합니다. 창문을 나누는 것이 가장 좋은 아이디어는 아닙니다. 레이어는 시퀀스가 ​​진행되면서 어떻게 진화하고 있는지에 대한 내부 상태를 가지고 있습니다. Windows는 긴 시퀀스를 학습 할 가능성을 없애 모든 시퀀스를 윈도우 크기로 제한합니다.

창에서 각 창은 긴 원본 시퀀스의 일부이지만 Keras에서는 각각 독립적 인 시퀀스로 표시됩니다.

        [     Step1    Step2    Step3    Step4    Step5
Window  A:  [[P1,T1], [P2,T2], [P3,T3], [P4,T4], [P5,T5]],
Window  B:  [[P2,T2], [P3,T3], [P4,T4], [P5,T5], [P6,T6]],
Window  C:  [[P3,T3], [P4,T4], [P5,T5], [P6,T6], [P7,T7]],
  ....
        ]

이 경우 처음에는 하나의 시퀀스 만 있지만 창을 만들기 위해 여러 시퀀스로 나눕니다.

“시퀀스 란 무엇인가”라는 개념은 추상적입니다. 중요한 부분은 다음과 같습니다.

  • 많은 개별 시퀀스로 일괄 처리 할 수 ​​있습니다
  • 시퀀스를 시퀀스로 만드는 것은 단계 (일반적으로 시간 단계)로 진화한다는 것입니다.

“단일 레이어”로 각 경우 달성

다 대다 표준 달성 :

StandardManyToMany

다음을 사용하여 간단한 LSTM 계층으로 다대 다를 달성 할 수 있습니다 return_sequences=True.

outputs = LSTM(units, return_sequences=True)(inputs)

#output_shape -> (batch_size, steps, units)

다 대일 달성 :

똑같은 레이어를 사용하면 keras는 똑같은 내부 전처리를 수행하지만, return_sequences=False이 인수 를 사용 하거나 무시하면 keras는 자동으로 이전 단계를 무시합니다.

ManyToOne

outputs = LSTM(units)(inputs)

#output_shape -> (batch_size, units) --> steps were discarded, only the last was returned

일대 다 달성

이제는 keras LSTM 레이어만으로는 지원되지 않습니다. 단계를 곱하려면 자신 만의 전략을 만들어야합니다. 두 가지 좋은 접근 방식이 있습니다.

  • 텐서를 반복하여 일정한 다단계 입력 생성
  • a stateful=True를 사용하여 한 단계의 출력을 반복적으로 가져 와서 다음 단계의 입력으로 사용합니다 (필요 output_features == input_features)

반복 벡터가있는 일대 다

keras 표준 동작에 맞추려면 단계적으로 입력이 필요하므로 원하는 길이만큼 입력을 반복하면됩니다.

OneToManyRepeat

outputs = RepeatVector(steps)(inputs) #where inputs is (batch,features)
outputs = LSTM(units,return_sequences=True)(outputs)

#output_shape -> (batch_size, steps, units)

상태 저장 이해 = True

stateful=True한 번에 컴퓨터의 메모리에 맞지 않는 데이터를로드하지 않는 것 외에도 사용 가능한 방법 중 하나가 제공됩니다.

상태 저장을 통해 시퀀스의 “부분”을 단계적으로 입력 할 수 있습니다. 차이점은 다음과 같습니다.

  • 이어 stateful=False, 두 번째 배치의 첫 번째 배치로부터 독립적 새로운 시퀀스를 포함
  • 이어 stateful=True, 두 번째 배치를 동일한 서열을 연장 제 배치를 계속한다.

창에서 시퀀스를 나누는 것과 마찬가지로 두 가지 주요 차이점이 있습니다.

  • 이 창문은 중첩되지 않습니다 !!
  • stateful=True 이 창들은 하나의 긴 시퀀스로 연결되어 있습니다.

에서은 stateful=True, 모든 새로운 배치는 이전 배치 (당신이 호출 할 때까지 계속하는 것으로 해석됩니다 model.reset_states()).

  • 배치 2의 순서 1은 배치 1의 순서 1을 계속합니다.
  • 배치 2의 시퀀스 2는 배치 1의 시퀀스 2를 계속합니다.
  • 배치 2의 시퀀스 n은 배치 1의 시퀀스 n을 계속합니다.

입력 예, 배치 1에는 1 단계와 2 단계가 있고 배치 2에는 3 ~ 5 단계가 있습니다.

                   BATCH 1                           BATCH 2
        [     Step1      Step2        |    [    Step3      Step4      Step5
Tank A:    [[Pa1,Ta1], [Pa2,Ta2],     |       [Pa3,Ta3], [Pa4,Ta4], [Pa5,Ta5]],
Tank B:    [[Pb1,Tb1], [Pb2,Tb2],     |       [Pb3,Tb3], [Pb4,Tb4], [Pb5,Tb5]],
  ....                                |
Tank N:    [[Pn1,Tn1], [Pn2,Tn2],     |       [Pn3,Tn3], [Pn4,Tn4], [Pn5,Tn5]],
        ]                                  ]

배치 1과 배치 2에서 탱크 정렬을 확인하십시오! 그것이 우리가 필요한 이유 shuffle=False입니다 (물론 하나의 시퀀스 만 사용하지 않는 한).

당신은 배치를 무제한으로 가질 수 있습니다. (일괄 처리마다 가변 길이를 사용하려면을 사용하십시오 input_shape=(None,features).

stateful = True 인 일대 다

여기서는 하나의 출력 단계를 가져 와서 입력하기 때문에 배치 당 1 단계 만 사용하려고합니다.

그림의 동작이 “원인”이 아님을 유의하십시오 stateful=True. 아래의 수동 루프에서 해당 동작을 강제합니다. 이 예에서는 stateful=True시퀀스를 중지하고 원하는 것을 조작하며 중지 한 부분부터 계속할 수 있습니다.

OneToManyStateful

솔직히 말해서,이 경우에는 반복 접근법이 더 나은 선택 일 것입니다. 그러나 우리가 조사하고 있기 때문에 stateful=True이것은 좋은 예입니다. 이것을 사용하는 가장 좋은 방법은 다음 “다 대다”사례입니다.

층:

outputs = LSTM(units=features,
               stateful=True,
               return_sequences=True, #just to keep a nice output shape even with length 1
               input_shape=(None,features))(inputs)
    #units = features because we want to use the outputs as inputs
    #None because we want variable length

#output_shape -> (batch_size, steps, units) 

이제 예측을위한 수동 루프가 필요합니다.

input_data = someDataWithShape((batch, 1, features))

#important, we're starting new sequences, not continuing old ones:
model.reset_states()

output_sequence = []
last_step = input_data
for i in steps_to_predict:

    new_step = model.predict(last_step)
    output_sequence.append(new_step)
    last_step = new_step

 #end of the sequences
 model.reset_states()

stateful = True 인 다 대다

이제 우리는 매우 멋진 응용 프로그램을 얻습니다. 입력 시퀀스가 ​​주어지면 미래의 알려지지 않은 단계를 예측하십시오.

위의 “일대 다”와 동일한 방법을 사용하고 있지만 다음과 같은 차이점이 있습니다.

  • 한 단계 앞선 시퀀스 자체를 대상 데이터로 사용합니다.
  • 시퀀스의 일부를 알고 있으므로 결과의이 부분을 버립니다.

ManyToManyStateful

레이어 (위와 동일) :

outputs = LSTM(units=features,
               stateful=True,
               return_sequences=True,
               input_shape=(None,features))(inputs)
    #units = features because we want to use the outputs as inputs
    #None because we want variable length

#output_shape -> (batch_size, steps, units) 

훈련:

시퀀스의 다음 단계를 예측하기 위해 모델을 훈련시킬 것입니다.

totalSequences = someSequencesShaped((batch, steps, features))
    #batch size is usually 1 in these cases (often you have only one Tank in the example)

X = totalSequences[:,:-1] #the entire known sequence, except the last step
Y = totalSequences[:,1:] #one step ahead of X

#loop for resetting states at the start/end of the sequences:
for epoch in range(epochs):
    model.reset_states()
    model.train_on_batch(X,Y)

예측 :

예측의 첫 단계는 “상태 조정”과 관련이 있습니다. 이것이 우리가 이미이 부분을 알고 있더라도 전체 시퀀스를 다시 예측하는 이유입니다.

model.reset_states() #starting a new sequence
predicted = model.predict(totalSequences)
firstNewStep = predicted[:,-1:] #the last step of the predictions is the first future step

이제 우리는 일대 다 사례 에서처럼 루프로갑니다. 그러나 여기서 상태를 재설정하지 마십시오! . 우리는 모델이 시퀀스의 어느 단계에 있는지 알기를 원합니다 (그리고 우리가 위에서 만든 예측 때문에 첫 번째 새로운 단계에 있음을 알고 있습니다)

output_sequence = [firstNewStep]
last_step = firstNewStep
for i in steps_to_predict:

    new_step = model.predict(last_step)
    output_sequence.append(new_step)
    last_step = new_step

 #end of the sequences
 model.reset_states()

이 접근법은 다음 답변과 파일에서 사용되었습니다.

복잡한 구성 달성

위의 모든 예제에서 “하나의 레이어”의 동작을 보여주었습니다.

물론, 반드시 동일한 패턴을 따르지 않고 여러 레이어를 서로 겹쳐 쌓고 자신 만의 모델을 만들 수 있습니다.

흥미로운 하나의 예는 “다 대일 인코더”와 “일대 다”디코더가있는 “자동 인코더”입니다.

인코더 :

inputs = Input((steps,features))

#a few many to many layers:
outputs = LSTM(hidden1,return_sequences=True)(inputs)
outputs = LSTM(hidden2,return_sequences=True)(outputs)

#many to one layer:
outputs = LSTM(hidden3)(outputs)

encoder = Model(inputs,outputs)

디코더 :

“반복”방법 사용

inputs = Input((hidden3,))

#repeat to make one to many:
outputs = RepeatVector(steps)(inputs)

#a few many to many layers:
outputs = LSTM(hidden4,return_sequences=True)(outputs)

#last layer
outputs = LSTM(features,return_sequences=True)(outputs)

decoder = Model(inputs,outputs)

오토 인코더 :

inputs = Input((steps,features))
outputs = encoder(inputs)
outputs = decoder(outputs)

autoencoder = Model(inputs,outputs)

와 훈련 fit(X,X)

추가 설명

LSTM에서 단계가 계산되는 방법 또는 stateful=True위 의 경우 에 대한 세부 사항을 원하는 경우이 답변에서 자세한 내용을 읽을 수 있습니다 .`Keras LSTM 이해 ‘


답변

RNN의 마지막 계층에 return_sequences가 있으면 간단한 Dense 계층을 사용할 수 없으며 대신 TimeDistributed를 사용하십시오.

다음은 다른 사람들을 도울 수있는 예제 코드입니다.

단어 = keras.layers.Input (batch_shape = (없음, self.maxSequenceLength), 이름 = “입력”)

    # Build a matrix of size vocabularySize x EmbeddingDimension 
    # where each row corresponds to a "word embedding" vector.
    # This layer will convert replace each word-id with a word-vector of size Embedding Dimension.
    embeddings = keras.layers.embeddings.Embedding(self.vocabularySize, self.EmbeddingDimension,
        name = "embeddings")(words)
    # Pass the word-vectors to the LSTM layer.
    # We are setting the hidden-state size to 512.
    # The output will be batchSize x maxSequenceLength x hiddenStateSize
    hiddenStates = keras.layers.GRU(512, return_sequences = True,
                                        input_shape=(self.maxSequenceLength,
                                        self.EmbeddingDimension),
                                        name = "rnn")(embeddings)
    hiddenStates2 = keras.layers.GRU(128, return_sequences = True,
                                        input_shape=(self.maxSequenceLength, self.EmbeddingDimension),
                                        name = "rnn2")(hiddenStates)

    denseOutput = TimeDistributed(keras.layers.Dense(self.vocabularySize),
        name = "linear")(hiddenStates2)
    predictions = TimeDistributed(keras.layers.Activation("softmax"),
        name = "softmax")(denseOutput)

    # Build the computational graph by specifying the input, and output of the network.
    model = keras.models.Model(input = words, output = predictions)
    # model.compile(loss='kullback_leibler_divergence', \
    model.compile(loss='sparse_categorical_crossentropy', \
        optimizer = keras.optimizers.Adam(lr=0.009, \
            beta_1=0.9,\
            beta_2=0.999, \
            epsilon=None, \
            decay=0.01, \
            amsgrad=False))


답변