CNN with Python and Keras - python

I'm new to machine learning and Keras. I made an Neural Network with Keras for regression looking like this:
model = Sequential()
model.add(Dense(57, input_dim=44, kernel_initializer='normal',
activation='relu'))
model.add(Dense(45, activation='relu'))
model.add(Dense(35, activation='relu'))
model.add(Dense(20, activation='relu'))
model.add(Dense(18, activation='relu'))
model.add(Dense(15, activation='relu'))
model.add(Dense(10, activation='relu'))
model.add(Dense(5, activation='relu'))
model.add(Dense(5, activation='relu'))
model.add(Dense(1, activation='linear'))
My data after preprocessing has 44 dimensions, so could you please give me an example how could i make an CNN.
Originally it looks like this: https://scontent.fskp1-1.fna.fbcdn.net/v/t1.0-9/40159383_10204721730878434_598395145989128192_n.jpg?_nc_cat=0&_nc_eui2=AeEYA4Nb3gomElC9qt0kF6Ou86P7jidco_LeHxEkmCB0-oVA9YKVe9VAh41SF25YomKTqKdkS96E18-sTCBidxJdbml4OV7FvFuAOWxI4mRafQ&oh=e81f4f56ebdf15e9c6eefbb078b8a982&oe=5BFD4157

Convolution neural network is not the best choice in this case. BTW you can do this thing easily with Conv1d:
model = keras.Sequential()
model.add(keras.layers.Embedding(44, 100))
model.add(keras.layers.Conv1D(50, kernel_size=1, strides=1))
model.add(keras.layers.GlobalAveragePooling1D())
# model.add(keras.layers.Dense(10, activation=tf.nn.relu))
model.add(keras.layers.Dense(1, activation=tf.nn.sigmoid))

To answer your question upfront I don't think you can use CNNs for your problem. Generally when people say they are using CNNs they usually mean the 2D convolution. It is operated on 2D spatial data (images). In NLP there exists 1D Convolution which people use to find local patterns in sequentual data. I don't think 1D convolution is relevant in your case. If you are from ML background you can think of regression using feed forward neural networks as polynomial regression. Intuitively you let the network decide which polynomial degree should we use to fit the data properly

You can add 2Dconvnet-layers like this:
model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
where
model.add(Conv2D(<feature maps>, (<kernel size>), input_shape=(<imput-tensor-shape)))
But be careful, 2Dconfnet-layers are mathematically different than dense-layers, so you can't stack them easily. To stack 2Dconvnet-layers with dense layers, you'll have to flatten them (you'll normally do this at the end to get your "fully-connected layer"):
model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Activation('relu'))
You'll find a lot of good tutorials on creating conv-nets with keras. This one for example focuses on image recognition. The examples above are taken from this article.
To find out, what a convolutional network does, I'd recommend you this article.
Edit:
But I share the opinion, that it might not be useful to use 2DConvnet layers for your example. Your data structure seems kind of "flat" and 2Dconvnets only make sense, when you have some multidimensional tensors as inputs.

Related

How to output a 3D tensor from a neural network?

My main input feature is 60x256x256 numpy array that is meant to generate a 60x256x256 binary mask (also in the form of a numpy array). The binary mask functions as a label, but I do not know how to generate a 3D numpy array or tensor output from my neural network. This is my current code:
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(32, kernel_size=(5, 5), strides=(1, 1),
activation='relu',
input_shape=(60, 256, 256)))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(tf.keras.layers.Conv2D(64, (5, 5), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(1000, activation='relu'))
model.add(tf.keras.layers.Dense(256, activation='softmax'))
model.compile(
optimizer=tf.keras.optimizers.Adam(0.001),
loss=tf.keras.losses.CosineSimilarity(),
metrics=[tf.keras.metrics.CosineSimilarity()],
)
model.fit(
train,
epochs=6,
validation_data=ds_valid,
)
In short, I want the output of the last layer to match the input layer so that it can work with the CosineSimilarity loss function. Any suggestions other than this CNN-based approach will also be very helpful, as it seems CNNs are mostly used for classification.
At the most basic level you can use tf.keras.layers.Reshape. See https://www.tensorflow.org/tutorials/generative/autoencoder
So your last two layers could be:
model.add(tf.keras.layers.Dense(60*256*256))
model.add(tf.keras.layers.Reshape(60, 256, 256))
However I think what you're looking for is an autoencoder type network and to usetf.keras.layers.Conv2DTranspose layers.
The above link is an intro to Autoencoders and should be a good starting point I think.
Not sure about your use case but I think it's very likely you do want to use a convolution based approach because when you flatten the convolution you are forcing your network to forget all the information about the symmetry of the problem (i.e that it is a picture in 2D space). I don't think the fact that your problem is a regression problem affects this.

Tensorflow LSTM based RNN - Incorrect and Constant Prediction

I hope someone can point out where I am going wrong with my RNN. The long and short of my problem is that no matter the structure of my network, the predictions are always along the lines of this:
I have tried 1, 2, 3, and 4 layers of LSTMs each with varying neuron counts and either relu or tanh activation functions. For the above image, the network was setup as:
model = Sequential()
model.add(LSTM(128, activation='relu', return_sequences=True, input_shape=(length, scaled_train_data.shape[1])))
model.add(LSTM(256, activation='relu', return_sequences=True))
model.add(LSTM(256, activation='relu', return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(128, activation='relu'))
model.add(Dense(scaled_train_data.shape[1]))
model.compile(optimizer='adam', loss="mse")
The actual training of the model passes ok, without event:
My data is financial data. There are around 70k rows and I have approx. 70/30 train/test split.
Where am I going wrong? Thanks!
So from asking about and reading around, it seems RNNs might not be the best solution for financial / random walk data - at least with the setup I am using. I wonder if using averages might produce better results?
Anyway, moving on to Reinforcement Learning.

Any suggestions to improve my CNN model (always the same low test accuracy)?

I am working on a project to detect the presence of a person in a painting. I have 4000 training images and 1000 test images resized to (256,256,3)
I tried a CNN model with 3 (Conv layers, MaxPool, BatchNormalization) and 2 fully connected layers.
model = Sequential()
model.add(Conv2D(32, kernel_size = (7, 7), activation='relu', input_shape=shape))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
model.add(Conv2D(64, kernel_size=(7,7), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
model.add(Conv2D(96, kernel_size=(5,5), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(1, activation = 'sigmoid'))
The train accuracy always converges to 1 (with just 20-50 epochs) and the test accuracy always remains constant around 0.67.
I tried the following:
I tried changing the size of the layers and adding more layers.
I tried data augmentation
I tried smaller images 128x128x3.
But I always have the same results.
I don't know if this is due to the few images I have, or if the architecture isn't big enough to learn from complex paintings.
I thought of trying Transfer Learning (But I don't know if this will help because it is my first time trying it). Also, do you have any idea where can I find trained models?
So, I am asking from some suggestions to improve my model.
It might be that you are overfitting on your training data, in that case you can use dropout.
The other thing is If you have not already normalized your data, you can do that. I am not sure whether that would be much help but give it a try with sth like:
X_training = X_training / X_training.max()
I tried using VGG16 (frozen) with 4 fully connected layers and the validation accuracy went up to 0.83. Also, I am using ImageDataGenerator.

keras fit time/step difference

Building a dqn agent, and trying to understand why calling fit in my code is orders of magnitude slower (over 1s) than another example I found (1ms). The neural nets are almost the same, the example has more connections, but that's the only difference (my alpha is set to the same as the example NN learning rate).
No idea what would cause such a difference in performance time. I thought maybe it was the way data was formatted before calling fit, but it looks like everything is the same.
My results:
Example results:
My NN:
q = Sequential()
q.add(Dense(24, input_dim=n_states, activation='relu'))
q.add(Dense(24, activation='relu'))
q.add(Dense(n_actions, activation='linear'))
q.compile(loss='mse', optimizer=Adam(lr=alpha))
Example NN:
model = Sequential()
model.add(Dense(32, input_dim=nS, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(nA, activation='linear'))
model.compile(loss='mse', optimizer=Adam(lr=0.01))

Keras Image Classification Problems

I'm working on an image classification model for a multiclass problem. I get the model up and running, but when I try to predict/test the model, it appears only to be able to recognise 1 of 4 image types (it's the same class no matter how I change the model). My dataset per class is pretty small, but I do use imagegenerator to increase the amount of data. The model should be able to recognise the images with some added noise on the picture.
My challenges can be boiled down to this:
Small amount of data. I have < 100 images per class.
My model is not supposed to find specific figures, but more overall patterns in the picture (areas with a certain colour and such).
Many of the pictures contain a lot of white and text. Do I need any image preprocessing to help the model.
My model looks like this:
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(s1,s2,3), data_format = "channels_first"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(50, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='Adam',
metrics=['accuracy'])
And has img size of 250,250, and batch size 16.
Check acc and loss curves
acc curve
loss curve
Do you guys have any advice?
Thanks in advance!
This is classical overfitting. You need to severely restrain your model and/or use transfer learning to combat this behavior. For restraining options you can increase dropout and add l2 regularization. In my experience l2 regularization really makes the problem hard for a NN. For the transfer learning you can use a resnet and just train the last 2-3 layers.
However, nothing beats having more data points though.

Categories