3

I am trying to make a model which recognises the emotions of a human. My code and RAM is just fine in the start:
RAM and DISK
But when I try to normalise my images, the RAM drastically jumps up
jumped up RAM
and then Colab just crashes:
Crash msg 1
Crash msg 2
Crash msg 3

This is the code block which is causing colab to crash:

import os
import matplotlib.pyplot as plt
import cv2

data = []

for emot in os.listdir('./data/'):
    for file_ in os.listdir(f'./data/{emot}'):
        img = cv2.imread(f'./data/{emot}/{file_}', 0)
        img = cv2.bitwise_not(img)
        img /= 255.0 # <--- This is the line that causes colab to crash
        data.append([img, emotions.index(emot)])

If I remove the img /= 255.0, it doesn't crash, but then I have images which are not normalised!: Not crashed
I even tried normalising it in another block:

for i in range(len(data)):
    data[i][0] = np.array(data[i][0]) / 255.0

but it doesn't work and still crashes

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Vthechamp
  • 636
  • 1
  • 8
  • 20

2 Answers2

1

I would like to go through an example. Firstly let's have a look at the following code.

import numpy as np
x = np.random.randint(0, 255, size=(100, 32, 32), dtype=np.int16)

print('Present data type', x.dtype)
# What you did
y = x/255
print('Present data type', y.dtype)
# What you should do
z = (x/255).astype(np.float16)
print('Present data type', z.dtype)

Output:

Present data type int16
Present data type float64
Present data type float16

If you look closely, while I am dividing the x variable and declaring y=x/255, the data type changes to float64. If you divide an int data type of a NumPy array, by default, it is typecasted to float64. Generally, 'float64' contains a larger memory. Therefore while dividing a int type NumPy matrix, one should always typecase to shorter datatypes for larger datasets.

If the code you executed fluently runs without the img /= 255.0 block, then this is the case. After dividing, you should typecast the img variable to the lowest possible float types, such as, np.float16 or np.float32. However, np.float16 has some limitations and it is not fully supported by TensorFlow (TF converts it to 32-bit float), you may use np.float32 datatype.

Therefore, try adding img.astype(np.float16) or img.astype(np.float32) after the line img /= 255.0.

The modified version of the code is given,

import os
import matplotlib.pyplot as plt
import cv2

data = []

for emot in os.listdir('./data/'):
    for file_ in os.listdir(f'./data/{emot}'):
        img = cv2.imread(f'./data/{emot}/{file_}', 0)
        img = cv2.bitwise_not(img)
        img = (img/255.0).astype(np.float16) # <--- This is the suggestion
        data.append([img, emotions.index(emot)])
Quwsar Ohi
  • 608
  • 4
  • 12
  • Okay thanks for the reply. I will check if this is working, as soon as I get the time to. Thanks so much again! – Vthechamp Jul 20 '20 at 05:58
  • I have tried it out, and it works! The RAM jumped very little, and the code ran completely, thank you so much! Another problem arose though, now whenever I try to show the images using matplotlib, it says `ValueError: Unsupported dtype`. So do I need to typecast it back to `float32` or something? – Vthechamp Jul 20 '20 at 09:12
  • Okay I changed it to `float32` and it is working now. Thanks so much! – Vthechamp Jul 20 '20 at 09:15
  • Facing `ValueError: Unsupported dtype` is a common problem (for matplotlib or any other library) if you use `np.float16` datatypes. As I mentioned in the answer, `np.float16` is not widely supported (even, processors do not directly support it). So, mostly you should stick to `np.float32`. If you are facing too much memory issue only then switch to `np.float16`. Ref: https://stackoverflow.com/questions/38975770/python-numpy-float16-datatype-operations-and-float8 – Quwsar Ohi Jul 20 '20 at 09:45
0

Assuming the next step in your pipeline is to create a tf.data.Dataset object out of your image corpus, you can use Dataset.map() to move your preprocessing into the data loading pipeline to save on memory space. Tensorflow has a very well-documented guide on how to do this here -> https://www.tensorflow.org/guide/data#preprocessing_data

mxkrn
  • 168
  • 1
  • 12
  • Thanks for the reply, but I never used `tf.data.Dataset`, so it was new to me. I tried looking into it, but I am getting some error (`OperatorNotAllowedInGraphError: using a \`tf.Tensor\` as a Python \`bool\` is not allowed in Graph execution. Use Eager execution or decorate this function with @tf.function.`, when I am trying to map my function to the `Dataset` object). This issue is also happening on Kaggle, so is it a problem in my code or something? – Vthechamp Jul 19 '20 at 09:16
  • I'll need some code to be of more help. However I would highly suggest you follow the `Tensorflow` tutorials before posting every issue you run into, they'll explain it much better than me. Having said that, my suspicion is that your `Tensorflow` version is giving you problems, maybe this will help -> https://stackoverflow.com/questions/59308263/using-a-tf-tensor-as-a-python-bool-is-not-allowed-in-graph-execution-use-ea – mxkrn Jul 19 '20 at 10:40
  • Okay, thanks for the advice, I will go over the entire tensorflow tutorial :) – Vthechamp Jul 19 '20 at 11:07