I'm new in ML. I am trying to make a basic example of image classification containing digits. I created my own dataset but I get a bad accuracy (11%). I have 246 items for training and 62 for testing.
Here is my code:
#TRAINING
def load_data(input_path, img_height, img_width):
data = []
labels = []
for imagePath in os.listdir(input_path):
labels_path = os.path.join(input_path, imagePath)
if os.path.isdir(labels_path):
for img_path in os.listdir(labels_path):
labels.append(imagePath)
img_full_path = os.path.join(labels_path, img_path)
img = image.load_img(img_full_path, target_size=(img_height, img_width))
img = image.img_to_array(img)
data.append(img)
return data, labels
train_data = []
train_labels = []
test_data = []
test_labels = []
train_data, train_labels = load_data(train_path, 28, 28)
test_data, test_labels = load_data(test_path, 28, 28)
train_data = np.array(train_data)
train_data = train_data / 255.0
train_data = tf.reshape(train_data, train_data.shape[:3])
train_labels = np.array(train_labels)
train_labels = np.asfarray(train_labels,float)
test_data = np.array(test_data)
test_data = tf.reshape(test_data, test_data.shape[:3])
test_data = test_data / 255.0
test_labels = np.array(test_labels)
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(train_data, train_labels, batch_size=10, epochs=5, steps_per_epoch=246)
test_loss, test_acc = model.evaluate(test_data, test_labels, steps=1)
print('Test accuracy:', test_acc)
#CLASSIFICATION
def classify(input_path):
if os.path.isdir(input_path):
images = []
for file_path in os.listdir(input_path):
full_path = os.path.join(input_path, file_path)
img_tensor = preprocess_images(full_path, 28, 28, "L")
images.append(img_tensor)
images = np.array(images)
images = tf.reshape(images,(images.shape[0],images.shape[2],images.shape[3]))
predictions = model.predict(images, steps = 1)
for i in range(len(predictions)):
print("Image", i , "is", np.argmax(predictions[i]))
def preprocess_images(image_path, img_height, img_width, mode):
img = image.load_img(image_path, target_size=(img_height, img_width))
#convert 3-channel image to 1-channel
img = img.convert(mode)
img_tensor = image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
img_tensor /= 255.0
img_tensor = tf.reshape(img_tensor, img_tensor.shape[:3])
return tf.keras.backend.eval(img_tensor)
When I make predictions, I always get the result "Image is 5".So, I have 2 questions:
- How can I get the other classes [0-9] as output?
- Can I get better accuracy by increasing the number of data ?
Thanks.
TLDR;
Your load_data() function is to blame - you need to return the labels of the datasets as an integer rather than the string filepath
Much fuller explanation:
Can I get better accuracy by increasing the number of data ?
In general, yes.
There is nothing intrinsically wrong with your model. I obviously don't have access to the dataset you have created but I can test it on the MNIST dataset (which your dataset is presumably trying to mirror):
(train_data, train_labels),(test_data, test_labels) = tf.keras.datasets.mnist.load_data()
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(train_data, train_labels, batch_size=10, epochs=5)
test_loss, test_acc = model.evaluate(test_data, test_labels)
print('Test accuracy:', test_acc)
Having done so, we can train to an accuracy of roughly 93%:
Test accuracy: 0.9275
Your inference code then also works as expected on the test data:
predictions = model.predict(test_data)
for i in range(len(predictions)):
print("Image", i , "is", np.argmax(predictions[i]))
giving the output, you'd expect:
Image 0 is 7
Image 1 is 2
Image 2 is 1
Image 3 is 0
Image 4 is 4
...
So we know the model can work. So is the difference in performance simply down to the size of your dataset (246) compared to MNIST (60000)?
Well this is an easy thing to test - we can take a similarly sized slice of the MNIST data and repeat the exercise:
train_data = train_data[:246]
train_labels = train_labels[:246]
test_data = test_data[:62]
test_labels = test_labels[:62]
So this time I see a dramatic reduction in the accuracy (c. 66% this time) but I can train the model to a much higher degree of accuracy than you are seeing even with a much smaller subset.
Therefore the issue has to be with your data pre-processing (or the dataset itself).
In fact, looking at you load_data() function, I can see that the problem lies in the labels you are generating. Your labels just appear to the the image path? You have this:
# --snip--
for img_path in os.listdir(labels_path):
labels.append(imagePath) ## <-- this does not look right!
# --snip--
Whereas you need to populate labels with the integer value for the category your image belongs to (for the mnist digits this is an integer between 0 and 9)
Related
I have trained a model that achieved a validation accuracy of 96% and very low validation loss but when I test it on other images , the prediction accuracy is bad in comparaison with the validation one , I have tried to process the images in the validation and test phase with the same parameters but the issue is still occurring , any ideas how i can fix it
here is the code :
directory = '/Users/anastalib/PycharmProjects/pythonProject1/Banana2'
img_width, img_height = 100, 100
img_datagen = ImageDataGenerator(
validation_split=0.2
, rescale=1. / 255, )
# test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = img_datagen.flow_from_directory(directory,
shuffle=True,
batch_size=16,
subset='training',
target_size=(img_width, img_height))
valid_generator = img_datagen.flow_from_directory(directory,
shuffle=False,
batch_size=16,
subset='validation',
target_size=(img_width, img_height))
resnet_model = Sequential()
pretrained_model = tf.keras.applications.ResNet50(include_top=False,
input_shape=(100, 100, 3),
pooling='avg',
weights='imagenet')
for layer in pretrained_model.layers:
layer.trainable = False
resnet_model.add(pretrained_model)
resnet_model.add(Flatten())
resnet_model.add(Dense(256, activation='relu'))
resnet_model.add(Dropout(0.5))
resnet_model.add(Dense(3, activation='softmax'))
resnet_model.summary()
resnet_model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
t1 = time.time()
print(datetime.datetime.now())
history = resnet_model.fit_generator(train_generator, validation_data=valid_generator,
steps_per_epoch=train_generator.n // train_generator.batch_size,
validation_steps=valid_generator.n // valid_generator.batch_size,
epochs=5)
print("Training took %s seconds" % (time.time() - t1))
path = 'overripe.jpg'
img = tf.keras.utils.load_img(path, target_size=(100, 100))
x = tf.keras.utils.img_to_array(img)
# Rescale image.
x = x / 255.
x = np.expand_dims(x, axis=0)
images = np.vstack([x])
classes = resnet_model.predict(images, batch_size=10)
print(np.argmax(classes))
What you describe seems a case of poor generalizability and your training/validation data are not representative a real data.
What you can try is to pool validation and test data, split again, retrain the model and see if the metrics improve.
A possible explanation is that there is a bias in your dataset, so the model is not really learning but is looking for something specific. Here you can find a better description of the phenomenon: https://pair.withgoogle.com/explorables/saliency/?linkId=8403074
Generally speaking, you can solve with more data or other solutions specific to the use case (in my experience, with medical images, color normalization was particularly important, as a example).
I have checked to make sure that the number of channels in my model and imagedatagenerator match, and have rgb images that are passed into the model. I know this question is similar to another question that was posted but I tried those solutions and haven't been able to get past this error.
# Build model
num_channels = 1
image_size = 720
num_labels = 49
model1 = Sequential()
model1.add(Conv2D(32, (3,3), input_shape = (image_size, image_size, num_channels)))
model1.add(Activation('relu'))
model1.add(Conv2D(32, (3,3)))
model1.add(Activation('relu'))
model1.add(MaxPooling2D(pool_size=(2,2)))
model1.add(Conv2D(64, (3,3)))
model1.add(Activation('relu'))
model1.add(Conv2D(64, (3,3)))
model1.add(Activation('relu'))
model1.add(MaxPooling2D(pool_size=(2,2)))
model1.add(Flatten())
model1.add(Dense(200))
model1.add(Activation('relu'))
model1.add(Dense(200))
model1.add(Activation('relu'))
model1.add(Dense(num_labels))
model1.save_weights("ckpt")
model1.load_weights("ckpt")
model1.summary()
# load data into ImageDataGen for on the fly augmented imgs and fit into model[enter image description here][1]
CWD = os.getcwd()
# print(train_dir_file_list[0])
TRAINING_DATA_PATH = os.path.join(CWD, 'campaign_data/data/')
print(os.path.join(CWD, 'campaign_data/data/'))
IMAGE_SIZE = 720
IMG_SHAPE = (IMAGE_SIZE, IMAGE_SIZE, 1)
TRAIN_BATCH_SIZE = 32
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
# rescale=1.0/127.5, # from various posts, if resnet50.preprocess_input is used, do not rescale
rotation_range=90.,
shear_range=0.2,
# for image data rescale as such
# rescale= 1.0/255,
zoom_range=[0.8,1.2],
horizontal_flip=True,
validation_split=0.2,
preprocessing_function=tf.keras.applications.resnet50.preprocess_input)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
# preprocessing_function=tf.keras.applications.resnet50.preprocess_input)
# Next we're going to take the images from our directory in batches and categorical classes:
#flow_from_directory
train_generator = train_datagen.flow_from_directory(TRAINING_DATA_PATH,
target_size=(IMAGE_SIZE, IMAGE_SIZE),
color_mode='rgb',
batch_size=TRAIN_BATCH_SIZE,
class_mode='categorical',
shuffle=True,
subset='training',
seed=42)
validation_generator = train_datagen.flow_from_directory(TRAINING_DATA_PATH,
target_size=(IMAGE_SIZE, IMAGE_SIZE),
color_mode='rgb',
batch_size=TRAIN_BATCH_SIZE,
class_mode='categorical',
shuffle=True,
subset='validation',
seed=42)
# confirm the scaling works
batchX, batchY = train_generator.next()
print('Batch shape=%s, min=%.3f, max=%.3f' % (batchX.shape, batchX.min(), batchX.max()))
labels = train_generator.class_indices
print('\nclass_indices = ', labels)
labels_dict = dict((v,k) for k, v in labels.items())
print('\nlabels_dict = ', labels_dict)
print(train_generator.filenames[0:5])
with open('labels_dict.json', 'w') as f:
json.dump(labels_dict, f)
METRICS = [
tf.keras.metrics.TruePositives(name='tp'),
tf.keras.metrics.FalsePositives(name='fp'),
tf.keras.metrics.TrueNegatives(name='tn'),
tf.keras.metrics.FalseNegatives(name='fn'),
tf.keras.metrics.BinaryAccuracy(name='accuracy'),
tf.keras.metrics.Precision(name='precision'),
tf.keras.metrics.Recall(name='recall'),
tf.keras.metrics.AUC(name='auc'),
tf.keras.metrics.AUC(name='prc', curve='PR') # precision-recall curve
]
model1.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),
loss='categorical_crossentropy',
metrics=METRICS)
callbacks = [tf.keras.callbacks.TensorBoard(log_dir='./log/transer_learning_model', update_freq='batch'),
tf.keras.callbacks.EarlyStopping(patience=4)]
print('Training model...')
# print(train_generator)
history = model1.fit(train_generator,
steps_per_epoch=train_generator.samples//TRAIN_BATCH_SIZE,
epochs=25,
validation_data=validation_generator,
validation_steps=validation_generator.samples//TRAIN_BATCH_SIZE,
callbacks=callbacks)
Here is the exact error [1]: https://i.stack.imgur.com/cF2Sa.png
And at the bottom of the error is this text
Node: 'sequential_8/conv2d_34/Relu'
Fused conv implementation does not support grouped convolutions for now.
[[{{node sequential_8/conv2d_34/Relu}}]] [Op:__inference_train_function_70418]
I think you need to change the num_channels to 3 because the image has size 720x720x3.
Also you were able to train without the first layer since the input_shape does not need to be specified. It will just create {input_channel_size} * {filer_size} number of kernels.
I'm working on an implementation of EfficientNet in Tensorflow. My model is overfitting and predicting all three classes as just a single class. My training and validation accuracy is in the 99% after a few epochs and my loss is <0.5. I have 32,000 images between the three classes (12, 8, 12).
My hypothesis is that it has to do with the way I input the data and one hot coded the labels. Perhaps it is due to everything being labeled the same accidentally, but I can't figure out where.
# Load Data
train_ds = tf.keras.utils.image_dataset_from_directory(
train_dir,
labels='inferred',
seed=42,
image_size=(height, width),
batch_size=batch_size
)
val_ds = tf.keras.utils.image_dataset_from_directory(
val_dir,
labels='inferred',
seed=42,
image_size=(height, width),
batch_size=batch_size
)
class_names = train_ds.class_names
num_classes = len(class_names)
print('There are ' + str(num_classes) + ' classes:\n' + str(class_names))
# Resize images
train_ds = train_ds.map(lambda image, label: (
tf.image.resize(image, (height, width)), label))
val_ds = val_ds.map(lambda image, label: (
tf.image.resize(image, (height, width)), label))
This provides a sample of the correct images and class labels:
# # Visualization of samples
# plt.figure(figsize=(10, 10))
# for images, labels in train_ds.take(1):
# for i in range(9):
# ax = plt.subplot(3, 3, i + 1)
# plt.imshow(images[i].numpy().astype("uint8"))
# plt.title(class_names[labels[i]])
# plt.axis("off")
Could this be causing an issue with labels?
# Prepare inputs
# One-hot / categorical encoding
def input_preprocess(image, label):
label = tf.one_hot(label, num_classes)
return image, label
train_ds = train_ds.map(input_preprocess,
num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.prefetch(tf.data.AUTOTUNE)
val_ds = val_ds.map(input_preprocess)
My network:
def build_model(num_classes):
inputs = Input(shape=(height, width, 3))
x = img_augmentation(inputs)
model = EfficientNetB0(
include_top=False, input_tensor=x, weights="imagenet")
# Freeze the pretrained weights
model.trainable = False
# Rebuild top
x = layers.GlobalAveragePooling2D(name="avg_pool")(model.output)
x = layers.BatchNormalization()(x)
top_dropout_rate = 0.4
x = layers.Dropout(top_dropout_rate, name="top_dropout")(x)
outputs = layers.Dense(num_classes, activation="softmax", name="pred")(x)
# Compile
model = tf.keras.Model(inputs, outputs, name="EfficientNet")
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
model.compile(
optimizer=optimizer, loss="categorical_crossentropy", metrics=["accuracy"]
)
return model
with strategy.scope():
model = build_model(num_classes=num_classes)
epochs = 40
hist = model.fit(train_ds, epochs=epochs, validation_data=val_ds,
workers=6, verbose=1, callbacks=callback)
plot_hist(hist)
Well first off you are writing more code than you need to. In train_ds and val_ds you did not specify the parameter label_mode. By default it is set to 'int'. Which means your labels will be integers. This is fine if your compile your model using loss=tf.keras.losses.SparseCategoricalCrossentropy. If you had set
label_mode= 'categorical' then you can use loss=tf.keras.losses.CategoricalCrossentropy
You did convert you labels to one-hot-encoded and that appears to have been done correctly. But you could have avoided having to do that by setting the label mode to categorical as mentioned. You also wrote code to resize the images. This is not necessary since tf.keras.utils.image_dataset_from_directory resized the images for you. I had trouble getting your model to run probably because I don't have the code for x = img_augmentation(inputs). you have the code
model = EfficientNetB0(
include_top=False, input_tensor=x, weights="imagenet")
Since you are using the model API I think this should be
model = EfficientNetB0( include_top=False, weights="imagenet", pooling='max')(x)
NOTE I included pooliing='max' so efficientnet produces a one dimensional tensor output and thus you do not need the layer
x = layers.GlobalAveragePooling2D(name="avg_pool")(model.output)
I also modified your code to produce a test_ds so I could test the accuracy of the model. Of course I used a different dataset but the results were fine.
My complete code is shown below
train_dir=r'../input/beauty-detection-data-set/train'
val_dir=r'../input/beauty-detection-data-set/valid'
batch_size=32
height=224
width=224
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
train_dir,
labels='inferred',
validation_split=0.1,
subset="training",
label_mode='categorical',
seed=42,
image_size=(height, width),
batch_size=batch_size
)
test_ds = tf.keras.preprocessing.image_dataset_from_directory(
train_dir,
labels='inferred',
validation_split=0.1,
subset="validation",
label_mode='categorical',
seed=42,
image_size=(height, width),
batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
val_dir,
labels='inferred',
seed=42,
label_mode='categorical',
image_size=(height, width),
batch_size=batch_size
)
class_names = train_ds.class_names
num_classes = len(class_names)
print('There are ' + str(num_classes) + ' classes:\n' + str(class_names))
img_shape=(224,224,3)
base_model=tf.keras.applications.EfficientNetB3(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max')
x=base_model.output
x=keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
x = Dense(256, kernel_regularizer = regularizers.l2(l = 0.016),activity_regularizer=regularizers.l1(0.006),
bias_regularizer=regularizers.l1(0.006) ,activation='relu')(x)
x=Dropout(rate=.45, seed=123)(x)
output=Dense(num_classes, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)
model.compile(Adamax(lr=.001), loss='categorical_crossentropy', metrics=['accuracy'])
epochs =5
hist = model.fit(train_ds, epochs=epochs, validation_data=val_ds,
verbose=1)
accuracy =model.evaluate(test_ds, verbose=1)[1]
print (accuracy)
```
If you use labels='inferred', you should also specify class_names which will be the name of the three folders you're getting images from.
I made a CNN for classification with 10 classes.
input = 49000 grayscale pictures, all mixed (I mean training set and validation set)
train.csv contain the list of the images and their labels like this for example :
id,label
0.png,4
1.png,9
2.png,1
3.png,7
4.png,3
5.png,9
Here a part of the CNN:
traindf = pd.read_csv('train.csv', dtype=str)
datagen = ImageDataGenerator(rescale=1./255, validation_split=0.25, shear_range = 0.2, zoom_range = 0.2, horizontal_flip = True)
train_generator = datagen.flow_from_dataframe(dataframe = traindf,
directory='images',
target_size = (28, 28),
color_mode='grayscale',
x_col='id',
y_col='label',
subset='training',
batch_size = 32,
shuffle=True,
class_mode = 'categorical')
valid_generator = datagen.flow_from_dataframe(dataframe = traindf,
directory="images",
target_size=(28,28),
color_mode='grayscale',
x_col="id",
y_col="label",
subset="validation",
batch_size=32,
shuffle=True,
class_mode="categorical")
STEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size
STEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size
and the fit method:
classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
classifier.fit_generator(train_generator,
steps_per_epoch = STEP_SIZE_TRAIN,
epochs = 10,
validation_data = valid_generator,
validation_steps = STEP_SIZE_VALID)
for the sake of clarity I do not display the creation of the neural networks, but note that input_shape = (28,28,1)
Then I save the model:
filepath = './NumChar_model_01'
save_model(classifier, filepath)
In another program, I want to predict an image:
loaded_model = load_model(filepath,custom_objects=None, compile=True)
img = img.resize((28, 28))
img = image.img_to_array(img)
img = np.expand_dims(img, axis = 0)
result = loaded_model.predict(img)
And I got this error:
ValueError: Input 0 of layer sequential is incompatible with the layer: expected axis -1 of input shape to have value 1 but received input with shape [None, 28, 28, 3]
I know it's an issue with shape, but believe me, I read all the world topic about that...
I tried reshape on train_generator and valid_generator but it give me an error too ('DataFrameIterator' object has no attribute 'reshape')
SOLUTION:
img was gotten by
img = ImageGrab.grab((cx, cy, cx + cw, cy + ch))
It returns an RGB image, which throw the error. So I convert it into a grayscale image with:
img = img.convert('L')
and it works!
I am building a tensorflow model to classify images to different dog breeds, using the "stanford_dogs" dataset which can be found here
This is how I am creating a dataset
url = 'http://vision.stanford.edu/aditya86/ImageNetDogs/images.tar'
dataset = tf.keras.utils.get_file("Images", url, untar=True, cache_dir='.', cache_subdir='')
dataset_path = pathlib.Path(dataset)
image_count = len(list(dataset_path.glob('*/*.jpg')))
total_ds = tf.data.Dataset.list_files(str(dataset_path/'*/*'), shuffle = False)
total_ds = total_ds.shuffle(image_count, reshuffle_each_iteration = False)
class_names = np.array(sorted([item.name for item in dataset_path.glob('*') if item.name != "LICENSE.txt"]))
val_size = int(image_count * 0.2)
train_ds = total_ds.skip(val_size) #Training Set
val_ds = total_ds.take(val_size) #Validation Set
batch_size = 32
img_height = 180
img_width = 180
def get_label(file_path):
# convert the path to a list of path components
parts = tf.strings.split(file_path, os.path.sep)
# The second to last is the class-directory
one_hot = parts[-2] == class_names
# Integer encode the label
return tf.argmax(one_hot)
def decode_img(img):
# convert the compressed string to a 3D uint8 tensor
img = tf.image.decode_jpeg(img, channels=3)
# resize the image to the desired size
return tf.image.resize(img, [img_height, img_width])
def process_path(file_path):
label = get_label(file_path)
# load the raw data from the file as a string
img = tf.io.read_file(file_path)
img = decode_img(img)
return img, label
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(process_path, num_parallel_calls=AUTOTUNE)
After that i am doing the following
normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)
def configure_for_performance(ds):
ds = ds.cache()
ds = ds.shuffle(buffer_size=1000)
ds = ds.batch(batch_size)
ds = ds.prefetch(buffer_size=AUTOTUNE)
ds = ds.map(lambda x,y: (normalization_layer(x), y))
return ds
train_ds = configure_for_performance(train_ds)
val_ds = configure_for_performance(val_ds)
After that I compile and train the model as shown below
num_classes = 120
model = tf.keras.Sequential([
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='sigmoid'),
layers.Dropout(0.2),
layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
epochs=20
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
After training I get high training accuracy (aroung 94-95%) but the validation accuracy I get is very low (around 8-10%).
What am I doing wrong, I searched online and some say that the dataset should be shuffled before splitting the data, but I already did that. I am stuck here, I tried changing the activation, the number of neurons, number of hidden layers...but no luck.
Also, if I add regularization then both accuracies are dropping to around 10% (Added regularization with 4 hidden layers with 512 neurons in each layer).
Would be very helpful if someone could explain to me what I am doing wrong.