Подгонка модели и ошибка размера для сети kera LSTM в python - PullRequest
0 голосов
/ 24 сентября 2019

Привет, я работал над сетью LSTM на python, используя Keras.Я создал одномерный массив для своего тренировочного и тестового набора.Когда я пытаюсь соответствовать модели, я получаю следующую ошибку:

ValueError: Ошибка при проверке ввода: ожидалось, что lstm_31_input будет иметь 3 измерения, но получил массив с формой (599, 1)

Iпопытался изменить размер и добавить слой (Flatten).Ничего из этой работы.Мой код ниже:

#Setup
import pandas as pd
import numpy as np
from numpy import array, zeros, newaxis
from numpy import argmax
from keras.layers.core import Dense, Activation, Dropout
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Embedding, Flatten
from keras.layers import LSTM

#Used to ignore warning about some of the tensor command being depracated
#Code from: 
#https://stackoverflow.com/questions/43819820/how-to-disable-keras-warnings
#import warnings
#with warnings.catch_warnings():
#    warnings.simplefilter("ignore")


"""
#Allow use of modules from the Common_Functions Folder
import sys
sys.path.append('../_Common_Functions')
import Hello_World as helloWorld
"""

#Creates dataset of random numbers
#import numpy as np
from random import random
def generateDatset(n):
    val = np.array([])
    typ = np.array([])
    for i in range (1, n):
        val = np.append(val, round(random()*10, 2))

        if val[i-1] < 3 or val[i-1] > 7:
            typ = np.append(typ, 'm')
        else:
            typ = np.append(typ, 'f')
    return val, typ


# Encode the output labels
def lable_encoding(gender_series):
    labels = np.empty((0, 2))
    for i in gender_series:
        if i == 'm':
            labels = np.append(labels, [[1,0]], axis=0)
        else:
            labels = np.append(labels, [[0,1]], axis=0)
    return labels

#Gets dataset in proper format for this program
val, typ = generateDatset(1000)
df = pd.DataFrame( {"first_name": val[:], "gender": typ[:]} )

# Split dataset in 60% train, 20% test and 20% validation
train, validate, test = np.split(df.sample(frac=1), [int(.6*len(df)), int(.8*len(df))])

# Convert both the input names as well as the output lables into the discussed machine readable vector format
train_x = np.asarray(train.first_name)
#train_x = np.reshape(train_x, train_x.shape + (1,))
#train_x = np.reshape(train_x, (train_x.shape[0], 1, train_x.shape[1]))

train_y = lable_encoding(train.gender)
#train_y = np.reshape(train_y, train_y.shape + (1,))
#train_y = np.reshape(train_y, (train_y.shape[0], 1, train_y.shape[1]))

validate_x =  np.asarray(validate.first_name)
#validate_x = np.reshape(validate_x, validate_x.shape + (1,))
validate_y = lable_encoding(validate.gender)
#validate_y = np.reshape(validate_y, validate_y.shape + (1,))

test_x =  np.asarray(test.first_name)
#test_x = np.reshape(test_x, test_x.shape + (1,))
test_y = lable_encoding(test.gender)
#test_x = np.reshape(test_x, test_x.shape + (1,))

"""
The number of hidden nodes can be determined by the following equation: 
Nh = (Ns/ (alpha * Ni + No ) )
Where  Ni --> number of input neurons
       No --> number of output neurons 
       Ns --> number of samples
       alph --> scaling factor

Alternatively the following equation can be used: 
    Nh = (2/3)*(Ni + No)
As a not this equation is simpler but may not provide the best performance

"""
#Set a value for the scaling factor. 
#This typically ranges between 2 and 10
alpha = 8
hidden_nodes = int(np.size(train_x) / (alpha * ((len(df.columns)-1)+ 4)))

input_length = train_x.shape # Length of the character vector
output_labels = 2 # Number of output labels

from keras import optimizers
# Build the model
print('Building model...')
model = Sequential()

#print(train_x.shape)
#
df = np.expand_dims(df, axis=2)


model.add(LSTM(hidden_nodes, return_sequences=True, input_shape=(599, 1)))

model.add(Dropout(0.2))

model.add(Flatten())
model.add(Dense(units=output_labels))

model.add(Activation('softmax'))
sgd = optimizers.SGD(lr=0.5, clipnorm=10.)
model.compile(loss='categorical_crossentropy', optimizer= sgd, metrics=['acc'])
#
batch_size=1000

#x = train_x[..., newaxis, newaxis]
#x.shape
#y = train_y[..., newaxis, newaxis]
#y.shape
model.fit(train_x, train_y, batch_size=batch_size, epochs=10)

#http://45.76.113.195/?questions/46616674/expected-ndim-3-found-ndim-2-how-to-feed-sparse-matrix-to-lstm-layer-in-keras

1 Ответ

2 голосов
/ 24 сентября 2019

input_shape=(599, 1) определяет форму одного образца.

Здесь размер партии вашего поезда составляет 599, а форма одного образца - 1. Поскольку первый слой является слоем LSTM, он требует 3-мерного ввода (batch_size)., number_of_time_stamps_of_a_sample, diamentionality_of_one_time_stamp). Но мы не упоминаем размер пакета в input_shape . Поэтому форма ввода слоя LSTM должна быть

input_shape = (number_of_time_sta_of_of_time_stamp_of_one_of_one_of_one_of_one_of_one_of_one_of_one_of_one_one_of_one_1009 *

Итак, вы должны

1) Заменить input_shape=(599, 1) на input_shape=(1, 1)

2) Добавить следующую строку перед тренировкой train_x=train_x.reshape(599,1,1)

Чтобы быть более понятным, пожалуйста, посмотрите это видео , загруженное мной; -)

...