1

I want to train a neural net based on a numpy array with 4 entries as the X-data and another array with one entry as the y-data.

X_train = [x1, x2, x3, x4]
y_train = [y1]

A rather simple thing I thought, but I can't get the input shape to work. I also found very little information about how the input shape works: Do you have to specify only the X data? What about the y data?

I already tried setting input_dim = 4, since that was the first logical thing to do but I got the following Error: Error when checking input: expected dense_1_input to have shape (4,) but got array with shape (1,)

I then tried setting input_dim = (4, 1), since I thought the y data was causing that issue. But again I got an error message: Error when checking input: expected dense_1_input to have 3 dimensions, but got array with shape (4, 1)

Heres the code:

# importing the packages
import gym
import numpy as np
from collections import deque

from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
from keras.wrappers.scikit_learn import KerasRegressor

from joblib import Parallel

# creating the environment
env = gym.make('CartPole-v1')

#defining global variables
lr=0.0001
decay=0.001
batch_size=None

# creating a deep learning model with keras
def model():
    model = Sequential()

    model.add(Dense(64, input_dim=4, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(16, activation='relu'))

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

    model.compile(Adam(lr=lr, decay=decay), loss='mse')
    model.summary()
    return model

# running the game
for i_episodes in range(200):
    env.reset()
    for i in range(100):
        env.render()
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)

        # observation = ndarray float64
        # reward = float
        # done = bool
        # action = int
        # info = empty

        observation = np.asarray(observation)
        reward = np.asarray(reward)
        action = np.asarray(action)

        # print(observation.dtype, reward.dtype, action.dtype)
        # print(observation.shape, action.shape)

        estimator = KerasRegressor(build_fn=model, epochs=30, batch_size=3, verbose=1)
        estimator.fit(observation, action)

        if done:
            break
env.close()

If someone could explain how the input shapes work would be much appreciated.

Johann Süß
  • 97
  • 1
  • 12

3 Answers3

1

Input shape always expect the batch size as first dimention.

For example in your case, the following layer does not expect an array of shape (4,)

Dense(64, input_dim=4, activation='relu')

The input shape of this dense layer is a tensor of shape (n, 4) where n is the batch size.

To pass your observation to the model you first need to expand its dims as follows:

observation = np.asarray(observation)
observation = np.expand_dims(observation, axis=0) # From shape (4,) to (1, 4)
estimator.fit(observation, action)

Your code should look like this.

# creating a deep learning model with keras
def build_model():
    model = Sequential()

    model.add(Dense(64, input_dim=4, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(16, activation='relu'))

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

    model.compile(Adam(lr=lr, decay=decay), loss='mse')
    model.summary()
    return model

model = build_model()

# running the game
for i_episodes in range(200):
    env.reset()
    for i in range(100):
        env.render()
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)

        # observation = ndarray float64
        # reward = float
        # done = bool
        # action = int
        # info = empty

        observation = np.asarray(observation)
        reward = np.asarray(reward)
        action = np.asarray(action)

        model.fit(np.expand_dims(observation, axis=0), np.expand_dims(action, axis=0))

Also if you are learning DQN check out this article

Guillem
  • 2,376
  • 2
  • 18
  • 35
  • I tried something similar, reshaping the observations into (-1, 4) but that doesn't worked. When I try to expand the dims I also get an error: `Error when checking target: expected dense_4 to have 2 dimensions, but got array with shape ()` – Johann Süß Aug 04 '19 at 11:23
  • You need to do the same for action. Also why are you going with estimators? I can se you are setting a batch size of 30 but you are only feeding 1 instance of observation. Check the edited answer – Guillem Aug 04 '19 at 11:32
  • Perfect! Works perfectly. The estimator was suggested by @SohaibAnwaar and actually since this is a regression task made sense. But I am fairly new to Deep Learning so - yeah ;) – Johann Süß Aug 04 '19 at 11:47
  • Great article by the way – Johann Süß Aug 04 '19 at 12:05
0

Try this piece of code. You have to specify Input dimension when you are going to solve any regression problem with the neural net. So In input dimension you have to pass the number of columns you want to feed to your network.

  def baseline_model():  
    model = Sequential()

    model.add(Dense(64, input_dim=4, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(16, activation='relu'))

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

    model.compile(Adam(lr=lr, decay=decay), loss='mse')
    model.summary()
    return model

Now You have to wrap it in the class keras regressor so that keras will know it is a regression problem you are going to solve.

estimator = KerasRegressor(build_fn=baseline_model, epochs=30, batch_size=3, verbose=1)

if you need more about how to solve Regression problem with keras than see the my notebook below you will get help from it.

Also use this line before calling Fit fucntion

(observation=observation.reshape(1,4))

Link : Solve Regression problem with Keras Neural Network

Sohaib Anwaar
  • 1,517
  • 1
  • 12
  • 29
  • Actually, when I call estimator.fit(X, y) the same error occurs. – Johann Süß Aug 04 '19 at 10:59
  • Kindly See the notebook below! I have attached that notebook for you! – Sohaib Anwaar Aug 04 '19 at 11:00
  • That's the whole code. The idea is basically to train a neural net to predict the best action to balance a cart. – Johann Süß Aug 04 '19 at 11:07
  • on which data set you are working ? I will try to do the same thing on Kaggle and debug to find the error. – Sohaib Anwaar Aug 04 '19 at 11:09
  • Actually, it isn't a dataset - or it gets generated while running. Gym is a library of games for python where you can implement Reinforcement Learning algorithms. The for loop starts the game and iterates through it. The data is generated at ` observation, reward, done, info = env.step(action)` and then converted into numpy arrays. – Johann Süß Aug 04 '19 at 11:15
  • ohh ok let me try! – Sohaib Anwaar Aug 04 '19 at 11:18
  • Brother Add this line of code before calling the estimator. I hope that will help you out. (observation=observation.reshape(1,4)) – Sohaib Anwaar Aug 04 '19 at 11:31
  • Actually python is taking your columns as a rows. So we have to reshape the data that their are 4 columns by reshaping the numpy array. – Sohaib Anwaar Aug 04 '19 at 11:33
  • Unfortunately gives the same error: ` Error when checking target: expected dense_4 to have 2 dimensions, but got array with shape () ` – Johann Süß Aug 04 '19 at 11:35
  • I reshaped the data before when calling model.fit(X_train.reshape(-1, 4) ... but that dosnt worked either – Johann Süß Aug 04 '19 at 11:36
  • yaa now the problem is that your action array have no values in it. means action array is empty so when neural network go to find the ground truth it will cause and error. See why your action array is empty – Sohaib Anwaar Aug 04 '19 at 11:38
  • First error is resolved now this is the new error. of last dense layer. – Sohaib Anwaar Aug 04 '19 at 11:38
0

Bro! For the second error use this code. Now its running fine for me.

X=[]
y=[]

# creating the environment
env = gym.make('CartPole-v1')

#defining global variables
lr=0.0001
decay=0.001
batch_size=None

# creating a deep learning model with keras
def model():
    model = Sequential()

    model.add(Dense(64, input_dim=4, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(16, activation='relu'))

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

    model.compile(Adam(lr=lr, decay=decay), loss='mse')
    model.summary()
    return model

# running the game
for i_episodes in range(200):
    env.reset()
    for i in range(100):
        #env.render()
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)


        observation = np.asarray(observation)
        reward = np.asarray(reward)
        action = np.asarray(action)

        X.append( observation)
        y.append(action)


        if done:
            break
env.close()


X=np.asarray(X)
y=np.asarray(y)
estimator = KerasRegressor(build_fn=model, epochs=30, batch_size=3, verbose=1)
estimator.fit(X, y)
Sohaib Anwaar
  • 1,517
  • 1
  • 12
  • 29
  • @Guille posted an answer that works as well - I tried yours and now this approach works for me too. Thank you for your answers - they were really helpful. – Johann Süß Aug 04 '19 at 11:53
  • yaa these are two different approaches :) I am happy that your problem is solved. Have a nice day bro. kindly upvote answers which works for you :) – Sohaib Anwaar Aug 04 '19 at 11:55