TFLite - Post Training (full integer) Quantization - problems with using a representative dataset - python

I have a hard time to get good results for a full integer quantized TFLite Model using Post-training quantization. The model does not recognize anything corectly. I used the given notebook tutorial from google and changed it. Here is my version where I try to perform full integer quantization by using images from the coco validation dataset. It should run completely on its own.
Probably something is wrong with _representative_dataset_gen() which looks like this:
def _representative_dataset_gen():
print("200 rep dataset function called!")
root = 'val2017/'
pattern = "*.jpg"
imagePaths = []
for path, subdirs, files in os.walk(root):
for name in files:
if fnmatch(name, pattern):
imagePaths.append(root + name)
for index,p in enumerate(imagePaths[:200]):
if index % 10 == 0:
print(index)
image = cv2.imread(p)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (640, 640))
image = image.astype("float")
image = np.expand_dims(image, axis=1)
image = image.reshape(1, 640, 640, 3)
yield [image.astype("float32")]
#yield image
I also compared it to a full integer version which only gets one single image as a repr. dataset. Interestingly it performs really similar, therefore I am quite confident that my attempt is wrong.
Don't hesitate to ask questions. I would appreciate any help.

Related

CNN performance worse when loading data with tf.Data

I have a trained EfficientNetB2 neural network that I'm using for image classification. When I'm loading the images with PIL like this:
image = Image.open(item)
image = image.convert('RGB').resize((120, 120))
image = np.array(image)
if image.ndim == 3:
image = np.expand_dims(image, axis = 0)
predictions.append(model.predict(image))
I get accuracy at around 90%. This is, however, extremely slow so I tried using tf.data to load my dataset. This looks something like this:
ds = tf.data.Dataset.list_files(str(test_dir / '*' / '*'))
ds = (ds
.map(load_data, num_parallel_calls=tf.data.experimental.AUTOTUNE)
.cache()
.batch(32)
.prefetch(tf.data.experimental.AUTOTUNE)
)
And this is the load_data function:
def load_image_and_label(file_path):
label = tf.strings.split(file_path, os.sep)[-2]
image = tf.io.read_file(file_path)
image = tf.io.decode_jpeg(image, channels=3, dct_method='INTEGER_ACCURATE')
image = tf.image.resize(image, target_size)
return image, label
This is, as expected, much much faster but the accuracy drops to around ~70%. I've tried moving stuff around but I just can't figure out why this happens. If anyone has any suggestions it would be much appreciated.
P.S.
I'm aware that there is an almost identical question already asked on stack overflow but the answer to that question doesn't change anything for my situation, this is why I'm posting this as a separate question. Thank you.
Edit: I tried not using tf.Dataset but still using my load_image_and_label function, the results were again ~90% accuracy, meaning that there is a problem somewhere with tf.Dataset pipeline, anyone got any experience with this kind of a problem?

Extract image dataset from tensorflow record dataset in batches

I recently started studying CNNs with tensorflow and found tfrecords very helpful in speeding up the training, however I'm struggling with data API.
After parsing, my dataset is composed of (image, label) tuples, this is fine for training, however I'm trying to extract the image in another dataset to call keras.predict() on.
I've tried this solution:
test_set = get_set_tfrecord(test_path, _parse_function, num_parallel_calls = 4)
lab = []
f = True
for image, label in test_set.take(600):
if f:
img = tf.data.Dataset.from_tensors(image)
f = False
else:
img = img.concatenate(tf.data.Dataset.from_tensors(image))
lab.append(label.numpy())
naive, not great code, but it works EXCEPT in order to perform concatenation (i.e. stacking) it loads every image into RAM.
What's the proper way of doing this?
You can use the map API from tf.data.Dataset. You can write the following code.
result = test_set.map(lambda image, label: image)
# You can iterate and check what you have received at the end.
# I expect only the images.
for image in result.take(1):
print(image)
I hope that using the above code you resolve your issue and that this answer serves you well.

OpenCV read images from pyspark and pass to a Keras model

This is a follow-up question to the answer posted here. I'm using PySpark 2.4.4. I have a bunch of images (some .png some .jpeg) stored on Google Cloud Storage (GCS) that I need to pass to a Tensorflow model. I'm getting my images like this.
images = spark.read.format("image").option("dropInvalid", False).load("gs://my-bucket/my_image.jpg")
images = images.collect()
image = cv2.imdecode(np.frombuffer(images[0].image.data, np.uint8), cv2.IMREAD_COLOR)
Based on the OpenCV documentation I've read, it seems like OpenCV isn't able to understand my data format. I know this because cv2.imdecode(...) returns None. The official Spark documentation explicitly mentions compatibility with OpenCV, so I know it's possible.
Eventually I want to be able to do this.
prediction = model.predict(np.array([image]))[0]
Outside of Spark, if I get my image not from GCS but from an http endpoint, all I have to do is this, which works.
resp = urllib.request.urlopen(image_url)
image = resp.read()
prediction = model.predict(np.array([image]))[0]
To get a better sense of what the model is looking for, this is what the data should look like before it's passed into the np.array([...]) part.
print(resp.read())
>>> b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\ ...'
I can confirm that the images aren't corrupted when they're on GCS. When I download the same image from GCS to my laptop, and then read it like this, I get a similarly looking format. The model is also able to consume the image this way. I've also visually inspected the downloaded GCS image, and it looks fine.
with open("./my_image.jpeg", "rb") as image:
print(image.read())
>>> b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\ ...'
Not sure if this is what you are looking for, but I was able to achieve by converting PIL images to cv2 image.
Spark loading :
images = sc.binaryFiles('/tmp/images/*', 10)
df = images.map(lambda img: extract_line_coords(img)).toDF()
df.show(5, False)
Function
def extract_line_coords(binary_images):
name, img = binary_images
pil_image = Image.open(io.BytesIO(img)).convert('RGB')
cv2_image = numpy.array(pil_image)
cv2_image = cv2_image[:, :, ::-1].copy()
gray = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY)
...
...
Reference : Convert image from PIL to openCV format

Increasing dataset size using imgaug

I am merging two different datasets containing images into one dataset. One of the datasets contains 600 images in the training set. The other dataset contains only 90-100 images. I want to increase the size of the latter dataset by using the imgaug library. The images are stored in folders under the name of their class. So the path for a "cake" image in the training set would be ..//images//Cake//cake_0001. I'm trying to use this code to augment the images in this dataset:
path = 'C:\\Users\\User\\Documents\\Dataset\\freiburg_groceries_dataset\\images'
ia.seed(6)
seq = iaa.Sequential([
iaa.Fliplr(0.5),
iaa.Crop(percent=(0, 0.1)),
iaa.Affine(rotate=(-25,25))
], random_order=True)
for folder in os.listdir(path):
try:
for i in os.listdir(folder):
img = imageio.imread(i)
img_aug = seq(images=img)
iaa.imshow(img_aug)
print(img_aug)
except:
pass
Right now there's not output, even if I put print(img) or imshow(img) or anything. How do I ensure that I got more images for this dataset? Also, what is the best spot to augment images? Where do the augmented images get stored, and how do I see how many new images were generated?
The Question was not clear. So, for the issue2: error in saving file and not able to visualize using imshow().
First: In the second loop code block
img = imageio.imread(i)
img_aug = seq(images=img)
iaa.imshow(img_aug)
print(img_aug)
1st error is: i is not the file path. To solve this replace imageio.imread(i) with imageio.imread(path+'/'+folder+'/'+i).
2nd error is: iaa doesn't have the property imshow().
To fix this replace iaa.imshow(img_aug) with iaa.imgaug.imshow(img_aug). This fixes the error of visualizing and finishing the loop execution.
Second: If you have any issue in saving images, then use PIL.
i.e.,
from PIL import Image
im = Image.fromarray(img_aug)
im.save('img_aug.png')`
It's because folder is not the path to the directory you are looking for.
You should change for i in os.listdir(folder): to for i in os.listdir(path+'\\'+folder):. Then it looks inside the path\folder directory for files.

Convolutional neural network Newbie

I am new to CNN so I am trying to learn to code it with python by following tutorials online, and I came up to this tutorial: https://medium.com/nybles/create-your-first-image-recognition-classifier-using-cnn-keras-and-tensorflow-backend-6eaab98d14dd
I followed the code and all but I get this small error that I can't seem to know the solution:
FileNotFoundError: [Errno 2] No such file or directory: 'random.jpg'
This is the code where the error points out to:
import numpy as np
from keras.preprocessing import image
test_image = image.load_img('random.jpg',target_size = (64, 64))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = classifier.predict(test_image)
training_set.class_indices
if result[0][0] >= 0.5:
prediction = 'dog'
else:
prediction = 'cat'
print(prediction)
I'm going to include the whole code just in case people want to see: https://drive.google.com/open?id=1ew22sJOvl5Ea9VTM_PXqVKNZJm1OuXTG
Any help is appreciated. :)
You need to give full path to the image or put code file and the image to the same file.
Based on what I read on the blog post, he used just a random dog image (downloaded from any web), name it as "random.jpg", and use it as a test image. You can just seek for any dog/cat image around the web, download and rename it as "random.jpg".
The point is, you know the image is a dog or cat, then test your model to predict what image it is.
You need to put 'random.jpg' into your working directory. That is put any file( a dog, cat, or any) with that name inside your folder :)

Categories

Resources