YueYANG1996 / LaBo

CVPR 2023: Language in a Bottle: Language Model Guided Concept Bottlenecks for Interpretable Image Classification
https://arxiv.org/abs/2211.11158
80 stars 6 forks source link

Can't train on CIFAR10 because data not in the right format #4

Closed nishadsinghi closed 1 year ago

nishadsinghi commented 1 year ago

I am trying to run LaBo on CIFAR10, and I get this error:

Traceback (most recent call last): File "/home/bethge/bkr046/LaBo/main.py", line 350, in <module> main(cfg) File "/home/bethge/bkr046/LaBo/main.py", line 228, in asso_opt_main data_module = DotProductDataModule( File "/home/bethge/bkr046/LaBo/data.py", line 377, in __init__ super().__init__(*args, **kwargs) File "/home/bethge/bkr046/LaBo/data.py", line 157, in __init__ self.prepare_img_feat(self.splits, self.n_shots, self.clip_model, self.clip_ckpt) File "/home/bethge/bkr046/LaBo/data.py", line 316, in prepare_img_feat img_feat, label = self.compute_img_feat(cls2img, n_shots if mode == 'train' else 'all', clip_model, clip_ckpt) File "/home/bethge/bkr046/LaBo/data.py", line 302, in compute_img_feat img_feat = utils.prepare_img_feat(all_img_paths, File "/home/bethge/bkr046/LaBo/utils.py", line 94, in prepare_img_feat batchify_run(process_img, img_names, res, 2048, use_tqdm=True) File "/home/bethge/bkr046/LaBo/utils.py", line 62, in batchify_run batch_res = process_fn(batch_data) File "/home/bethge/bkr046/LaBo/utils.py", line 87, in process_img img_tensor = torch.cat([preprocess(Image.open('{}'.format(img_name)))\ File "/home/bethge/bkr046/LaBo/utils.py", line 87, in <listcomp> img_tensor = torch.cat([preprocess(Image.open('{}'.format(img_name)))\ File "/mnt/qb/work/bethge/bkr046/anaconda3/envs/LaBo/lib/python3.9/site-packages/PIL/Image.py", line 3227, in open fp = builtins.open(filename, "rb") FileNotFoundError: [Errno 2] No such file or directory: 'datasets/CIFAR10/images/stealth_bomber_s_000554.png'

I think this happens because when I download CIFAR10 from the link in DATASET.md, it is in a different format: batches.meta cifar-10-batches-py cifar-10-python.tar.gz data_batch_1 data_batch_2 data_batch_3 data_batch_4 data_batch_5 readme.html test_batch

How do I convert it into the format that LaBo expects?

YueYANG1996 commented 1 year ago

Hi, You need to unzip the data, convert them into .png and save the images into CIFAR10/images.

nishadsinghi commented 1 year ago

Thanks for your reply! I think LaBo expects file names of the form datasets/CIFAR10/images/stealth_bomber_s_000554.png. As far as I know, this is not the standard format to name CIFAR images, and even if I unzip the data, the file names would be different from this. I was trying to write a script that converts standard names to the names in cls2img, but I noticed one issue: some file names in class2images_test.p have indices > 1000 (for example, stealth_bomber_s_001353.png), which shouldn't be the case because test folders have only 1000 images. It would be very helpful if you could provide a script that converts cifar-10-python.tar.gz (which is what one gets following the link in DATASET.md) to the expected file names. Alternatively, you could just upload the files in .png format somewhere for me to download. Thanks! :)

YueYANG1996 commented 1 year ago

Here is my code for preprocessing the CIFAR10, you could refer to it for processing the files:

import pickle
import tqdm
import numpy as np
from PIL import Image

def pickle_load(f_name):
    with open(f_name, 'rb') as f:
        return pickle.load(f, encoding='bytes')

def reshape(array):
    image = np.zeros((32,32,3), dtype=np.uint8)
    image[...,0] = np.reshape(array[:1024], (32, 32)) # Red channel
    image[...,1] = np.reshape(array[1024:2048], (32, 32)) # Green channel
    image[...,2] = np.reshape(array[2048:], (32, 32)) # Blue channel
    return image

train_1 = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR10/data/cifar-10-batches-py/data_batch_1')
train_2 = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR10/data/cifar-10-batches-py/data_batch_2')
train_3 = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR10/data/cifar-10-batches-py/data_batch_3')
train_4 = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR10/data/cifar-10-batches-py/data_batch_4')
train_5 = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR10/data/cifar-10-batches-py/data_batch_5')

test = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR10/data/cifar-10-batches-py/test_batch')
meta = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR10/data/cifar-10-batches-py/batches.meta')

all_class = [label_name.decode("utf-8").replace("_", " ") for label_name in meta[b'label_names']]

class2images_train = {c: [] for c in all_class}

for train in [train_1, train_2, train_3, train_4, train_5]:
    for i in range(len(train[b'filenames'])):
        file_name = train[b'filenames'][i].decode("utf-8")
        label = train[b'labels'][i]
        array = train[b'data'][i]

        class_name = all_class[label]
        # image = Image.fromarray(reshape(array))
        # image.save("../data/images/" + file_name)
        class2images_train[class_name].append(file_name)

class2images_test = {c: [] for c in all_class}
for i in range(len(test[b'filenames'])):
    file_name = test[b'filenames'][i].decode("utf-8")
    label = test[b'labels'][i]
    array = test[b'data'][i]

    class_name = all_class[label]
    image = Image.fromarray(reshape(array))
    image.save("../data/images/" + file_name)
    class2images_test[class_name].append(file_name)

print(len(class2images_train['truck']), len(class2images_test['truck']))
pickle.dump(class2images_train, open("../data/class2images_train.p", "wb"))
pickle.dump(class2images_test, open("../data/class2images_test.p", "wb"))
Sidd1609 commented 1 year ago

Hi @YueYANG1996, do you also have a similar preprocessing the CIFAR100? If so please would you share them.

YueYANG1996 commented 1 year ago
import pickle
import tqdm
import numpy as np
from collections import defaultdict
from torchvision.transforms import Compose, Resize, CenterCrop, ToTensor, Normalize
from PIL import Image
import torch
import clip

def pickle_load(f_name):
    with open(f_name, 'rb') as f:
        return pickle.load(f, encoding='bytes')

def reshape(array):
    image = np.zeros((32,32,3), dtype=np.uint8)
    image[...,0] = np.reshape(array[:1024], (32, 32)) # Red channel
    image[...,1] = np.reshape(array[1024:2048], (32, 32)) # Green channel
    image[...,2] = np.reshape(array[2048:], (32, 32)) # Blue channel
    return image

train = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR100/cifar-100-python/train')
test = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR100/cifar-100-python/test')
meta = pickle_load('/nlp/data/yueyang/CLIP_attr/dataset/CIFAR100/cifar-100-python/meta')

all_class = [label_name.decode("utf-8").replace("_", " ") for label_name in meta[b'fine_label_names']]

class2images_train = {c: [] for c in all_class}
for i in range(len(train[b'filenames'])):
    file_name = train[b'filenames'][i].decode("utf-8")
    label = train[b'fine_labels'][i]
    array = train[b'data'][i]

    class_name = all_class[label]
    image = Image.fromarray(reshape(array))
    image.save("../data/images/" + file_name)
    class2images_train[class_name].append(file_name)

print(class2images_train["apple"])

class2images_test = {c: [] for c in all_class}
for i in range(len(test[b'filenames'])):
    file_name = test[b'filenames'][i].decode("utf-8")
    label = test[b'fine_labels'][i]
    array = test[b'data'][i]

    class_name = all_class[label]

    if file_name == "baby_s_000224.png":
        image = Image.fromarray(reshape(array))
        image.save("../data/images/" + file_name)
    class2images_test[class_name].append(file_name)

print(class2images_test['baby'])
Sidd1609 commented 1 year ago

Thank you so much @YueYANG1996 !

nishadsinghi commented 1 year ago

This solved my issue. thanks for your help, @YueYANG1996! :)

Sidd1609 commented 1 year ago

Hello, @YueYANG1996 please could you share the data processing for all the remaining datasets, if you have them with you. It would be helpful.