[GH-ISSUE #83] CLIP Training Code #73

Open
opened 2026-10-31 21:10:30 +00:00 by bsakaguchi · 232 comments
Owner

Originally created by @vinson2233 on GitHub (Apr 8, 2021).
Original GitHub issue: https://github.com/openai/CLIP/issues/83

Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage.
Feel free to ask or point out any mistakes in my code.

# Latest Update : 18 July 2022, 09:55 GMT+7

# TO ADD :
# Gradient Checkpointing
# Filter out bias from weight decay
# Decaying learning rate with cosine schedule
# Half-precision Adam statistics
# Half-precision stochastically rounded text encoder weights were used

#BATCH_SIZE must larger than 1

device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training.
model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training

class image_title_dataset(Dataset):
    def __init__(self, list_image_path,list_txt):

        self.image_path = list_image_path
        self.title  = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop.

    def __len__(self):
        return len(self.title)

    def __getitem__(self, idx):
        image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module
        title = self.title[idx]
        return image,title

# use your own data
list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] 
list_txt = ['description for image1.jpg' , 'description for image2.jpg']
dataset = image_title_dataset(list_image_path,list_txt)
train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader

#https://github.com/openai/CLIP/issues/57
def convert_models_to_fp32(model): 
    for p in model.parameters(): 
        p.data = p.data.float() 
        p.grad.data = p.grad.data.float() 


if device == "cpu":
  model.float()
else :
  clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16

loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset

# add your own code to track the training progress.
for epoch in range(EPOCH):
  for batch in train_dataloader :
      optimizer.zero_grad()

      images,texts = batch 
    
      images= images.to(device)
      texts = texts.to(device)
    
      logits_per_image, logits_per_text = model(images, texts)

      ground_truth = torch.arange(len(images),dtype=torch.long,device=device)

      total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2
      total_loss.backward()
      if device == "cpu":
         optimizer.step()
      else : 
        convert_models_to_fp32(model)
        optimizer.step()
        clip.model.convert_weights(model)
  • NOTE :

Code to save the model :

torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': total_loss,
        }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename

Code to load the saved model :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224
checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Alternative training code :

Originally created by @vinson2233 on GitHub (Apr 8, 2021). Original GitHub issue: https://github.com/openai/CLIP/issues/83 Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. Feel free to ask or point out any mistakes in my code. ```python # Latest Update : 18 July 2022, 09:55 GMT+7 # TO ADD : # Gradient Checkpointing # Filter out bias from weight decay # Decaying learning rate with cosine schedule # Half-precision Adam statistics # Half-precision stochastically rounded text encoder weights were used #BATCH_SIZE must larger than 1 device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training. model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training class image_title_dataset(Dataset): def __init__(self, list_image_path,list_txt): self.image_path = list_image_path self.title = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop. def __len__(self): return len(self.title) def __getitem__(self, idx): image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module title = self.title[idx] return image,title # use your own data list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] list_txt = ['description for image1.jpg' , 'description for image2.jpg'] dataset = image_title_dataset(list_image_path,list_txt) train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader #https://github.com/openai/CLIP/issues/57 def convert_models_to_fp32(model): for p in model.parameters(): p.data = p.data.float() p.grad.data = p.grad.data.float() if device == "cpu": model.float() else : clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16 loss_img = nn.CrossEntropyLoss() loss_txt = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset # add your own code to track the training progress. for epoch in range(EPOCH): for batch in train_dataloader : optimizer.zero_grad() images,texts = batch images= images.to(device) texts = texts.to(device) logits_per_image, logits_per_text = model(images, texts) ground_truth = torch.arange(len(images),dtype=torch.long,device=device) total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 total_loss.backward() if device == "cpu": optimizer.step() else : convert_models_to_fp32(model) optimizer.step() clip.model.convert_weights(model) ``` * NOTE : - that for inference purpose, the conversion step from fp16 to fp32 is not needed, just use the model in full fp16 - For multi-GPU training, see my comment on https://github.com/openai/CLIP/issues/111#issuecomment-854320770 - I'm not the author of this model nor having any relationship with the author. I'm just a random guy who interested in CLIP. - For training image-image or text-text, please refer to this principle : https://github.com/openai/CLIP/issues/83#issuecomment-1487820198 - What is the difference between image loss and text loss? isn't one just a transposed version of the other one? read this then https://github.com/openai/CLIP/issues/83#issuecomment-1489603702 - Why the ground truth is torch.arange? https://github.com/openai/CLIP/issues/83#issuecomment-1141139017 Code to save the model : ```python torch.save({ 'epoch': epoch, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), 'loss': total_loss, }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename ``` Code to load the saved model : ```python model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training checkpoint = torch.load("model_checkpoint/model_10.pt") # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224 checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77 checkpoint['model_state_dict']["vocab_size"] = model.vocab_size model.load_state_dict(checkpoint['model_state_dict']) ``` Alternative training code : - @zasder3 have created a PyTorch lighting version to train the CLIP https://github.com/Zasder3/train-CLIP - @mitchellnw researchers at UW, Google, Stanford, Amazon, Columbia, and Berkeley also create their training code https://github.com/mlfoundations/open_clip
Author
Owner

@nikky4D commented on GitHub (Apr 8, 2021):

Very helpful. Thank you

<!-- gh-comment-id:815805800 --> @nikky4D commented on GitHub (Apr 8, 2021): Very helpful. Thank you
Author
Owner

@vkmavani commented on GitHub (Apr 12, 2021):

Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code
Feel free to ask or point out any mistakes in my code.

train_dataloader = DataLoader(...,batch_size = BATCH_SIZE) #Define your own dataloader

#https://github.com/openai/CLIP/issues/57
def convert_models_to_fp32(model): 
    for p in model.parameters(): 
        p.data = p.data.float() 
        p.grad.data = p.grad.data.float() 

device = "cuda:0" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
clip.model.convert_weights(model)

loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params from paper

for batch in train_dataloader :
    optimizer.zero_grad()

    list_image,list_txt = batch #list_images is list of image in numpy array(np.uint8)
    
    images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0)
    texts = clip.tokenize(list_txt)
    
    logits_per_image, logits_per_text = model(images, texts)

    ground_truth = torch.arange(BATCH_SIZE).to(device)
    total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2
    total_loss.backward()

    convert_models_to_fp32(model)
    optimizer.step()
    clip.model.convert_weights(model)

Hi, Thank you for this training code.
I have a dataset, where I want to check the image similarity, and I want to use the CLIP. But I don't know how to prepare(image_size, embedding_size, transforms, etc) a dataset to feed this training code. Can you please provide me the dataset class if possible?

<!-- gh-comment-id:817461063 --> @vkmavani commented on GitHub (Apr 12, 2021): > Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code > Feel free to ask or point out any mistakes in my code. > > ```python > train_dataloader = DataLoader(...,batch_size = BATCH_SIZE) #Define your own dataloader > > #https://github.com/openai/CLIP/issues/57 > def convert_models_to_fp32(model): > for p in model.parameters(): > p.data = p.data.float() > p.grad.data = p.grad.data.float() > > device = "cuda:0" if torch.cuda.is_available() else "cpu" > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > clip.model.convert_weights(model) > > loss_img = nn.CrossEntropyLoss() > loss_txt = nn.CrossEntropyLoss() > optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params from paper > > for batch in train_dataloader : > optimizer.zero_grad() > > list_image,list_txt = batch #list_images is list of image in numpy array(np.uint8) > > images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0) > texts = clip.tokenize(list_txt) > > logits_per_image, logits_per_text = model(images, texts) > > ground_truth = torch.arange(BATCH_SIZE).to(device) > total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 > total_loss.backward() > > convert_models_to_fp32(model) > optimizer.step() > clip.model.convert_weights(model) > ``` Hi, Thank you for this training code. I have a dataset, where I want to check the image similarity, and I want to use the CLIP. But I don't know how to prepare(image_size, embedding_size, transforms, etc) a dataset to feed this training code. Can you please provide me the dataset class if possible?
Author
Owner

@vinson2233 commented on GitHub (Apr 12, 2021):

@vkmavani sure. The preprocess object from CLIP takes care of all of the preprocessing steps for the image part, so you don't need to worry about image_size or transform(see https://github.com/openai/CLIP/blob/main/clip/clip.py line 58).
For example, maybe your data look like this :

| image  | caption  |
---------------------
| url1   | caption1 |
| url2   | caption2 |

where the URL is the path to the image and the caption is the string of the caption.

Here's the dataset class definition for image-text similarity :


from PIL import Image

class image_caption_dataset(Dataset):
    def __init__(self, df):

        self.images = df["image"].tolist()
        self.caption = df["caption"].tolist()

    def __len__(self):
        return len(self.caption)

    def __getitem__(self, idx):
        
        images = preprocess(Image.open(self.images[idx])) #preprocess from clip.load
        caption = self.caption[idx]
        return images,caption

dataset = image_caption_dataset(df)
train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader

With this dataset definition, you can omit the Image.fromarray() and the preprocess step after loading the batch since the actual data already in tensor format

If you are interested in doing image-image similarity, just modify the dataset to return pair of images and
for the training code, adjust the code accordingly, a big change will happen in the creating the logits part. Change the forward method logits_per_image, logits_per_text = model(images, texts) according to https://github.com/openai/CLIP/blob/main/clip/model.py, line 354.

<!-- gh-comment-id:817466268 --> @vinson2233 commented on GitHub (Apr 12, 2021): @vkmavani sure. The `preprocess` object from CLIP takes care of all of the preprocessing steps for the image part, so you don't need to worry about image_size or transform(see https://github.com/openai/CLIP/blob/main/clip/clip.py line 58). For example, maybe your data look like this : ``` | image | caption | --------------------- | url1 | caption1 | | url2 | caption2 | ``` where the URL is the path to the image and the caption is the string of the caption. Here's the dataset class definition for image-text similarity : ```python from PIL import Image class image_caption_dataset(Dataset): def __init__(self, df): self.images = df["image"].tolist() self.caption = df["caption"].tolist() def __len__(self): return len(self.caption) def __getitem__(self, idx): images = preprocess(Image.open(self.images[idx])) #preprocess from clip.load caption = self.caption[idx] return images,caption dataset = image_caption_dataset(df) train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader ``` With this dataset definition, you can omit the `Image.fromarray()` and the preprocess step after loading the batch since the actual data already in tensor format If you are interested in doing image-image similarity, just modify the dataset to return pair of images and for the training code, adjust the code accordingly, a big change will happen in the creating the logits part. Change the forward method ` logits_per_image, logits_per_text = model(images, texts)` according to https://github.com/openai/CLIP/blob/main/clip/model.py, line 354.
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

what is the clip.model.convert_weights meaning? and can you Provide a complete training code if possible

<!-- gh-comment-id:817533523 --> @lonngxiang commented on GitHub (Apr 12, 2021): what is the clip.model.convert_weights meaning? and can you Provide a complete training code if possible
Author
Owner

@vinson2233 commented on GitHub (Apr 12, 2021):

@lonngxiang For more information, read https://github.com/openai/CLIP/issues/57, clip.model.convert_weights basically convert the CLIP model weight into float16. This will help accelerate and reduce memory usage during training.
The definition of clip.model.convert_weight can be found at https://github.com/openai/CLIP/blob/main/clip/model.py line 371

I can't give a fully working example code since I'm using a private dataset, but I believe the training code and dataset code that I provided is sufficient.

<!-- gh-comment-id:817541502 --> @vinson2233 commented on GitHub (Apr 12, 2021): @lonngxiang For more information, read https://github.com/openai/CLIP/issues/57, clip.model.convert_weights basically convert the CLIP model weight into float16. This will help accelerate and reduce memory usage during training. The definition of clip.model.convert_weight can be found at https://github.com/openai/CLIP/blob/main/clip/model.py line 371 I can't give a fully working example code since I'm using a private dataset, but I believe the training code and dataset code that I provided is sufficient.
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

@lonngxiang For more information, read #57, clip.model.convert_weights basically convert the CLIP model weight into float16. This will help accelerate and reduce memory usage during training.
The definition of clip.model.convert_weight can be found at https://github.com/openai/CLIP/blob/main/clip/model.py line 371

I can't give a fully working example code since I'm using a private dataset, but I believe the training code and dataset code that I provided is sufficient.

Thank you for your kind reply

<!-- gh-comment-id:817544214 --> @lonngxiang commented on GitHub (Apr 12, 2021): > @lonngxiang For more information, read #57, clip.model.convert_weights basically convert the CLIP model weight into float16. This will help accelerate and reduce memory usage during training. > The definition of clip.model.convert_weight can be found at https://github.com/openai/CLIP/blob/main/clip/model.py line 371 > > I can't give a fully working example code since I'm using a private dataset, but I believe the training code and dataset code that I provided is sufficient. Thank you for your kind reply
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

there is a error when run this train code:
TypeError: default_collate: batch must contain tensors, numpy arrays, numbers, dicts or lists; found <class 'PIL.JpegImagePlugin.JpegImageFile'>

<!-- gh-comment-id:817583315 --> @lonngxiang commented on GitHub (Apr 12, 2021): there is a error when run this train code: TypeError: default_collate: batch must contain tensors, numpy arrays, numbers, dicts or lists; found <class 'PIL.JpegImagePlugin.JpegImageFile'>
Author
Owner

@vkmavani commented on GitHub (Apr 12, 2021):

@vkmavani sure. The preprocess object from CLIP takes care of all of the preprocessing steps for the image part, so you don't need to worry about image_size or transform(see https://github.com/openai/CLIP/blob/main/clip/clip.py line 58).
For example, maybe your data look like this :

| image  | caption  |
---------------------
| url1   | caption1 |
| url2   | caption2 |

where the URL is the path to the image and the caption is the string of the caption.

Here's the dataset class definition for image-text similarity :

from PIL import Image

class image_caption_dataset(Dataset):
    def __init__(self, df):

        self.images = df["image"].tolist()
        self.caption = df["caption"].tolist()

    def __len__(self):
        return len(self.caption)

    def __getitem__(self, idx):
        
        images = Image.open(self.images[idx])
        caption = self.caption[idx]
        return images,caption

dataset = image_caption_dataset(df)
train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader

With this dataset definition, you can omit the Image.fromarray() since the actual data already in PIL format.

If you are interested in doing image-image similarity, just modify the dataset to return pair of images and
for the training code, adjust the code accordingly, a big change will happen in the creating the logits part. Change the forward method logits_per_image, logits_per_text = model(images, texts) according to https://github.com/openai/CLIP/blob/main/clip/model.py, line 354.

Thank you very much. It really helps a lot.

<!-- gh-comment-id:817588452 --> @vkmavani commented on GitHub (Apr 12, 2021): > @vkmavani sure. The `preprocess` object from CLIP takes care of all of the preprocessing steps for the image part, so you don't need to worry about image_size or transform(see https://github.com/openai/CLIP/blob/main/clip/clip.py line 58). > For example, maybe your data look like this : > > ``` > | image | caption | > --------------------- > | url1 | caption1 | > | url2 | caption2 | > ``` > > where the URL is the path to the image and the caption is the string of the caption. > > Here's the dataset class definition for image-text similarity : > > ```python > from PIL import Image > > class image_caption_dataset(Dataset): > def __init__(self, df): > > self.images = df["image"].tolist() > self.caption = df["caption"].tolist() > > def __len__(self): > return len(self.caption) > > def __getitem__(self, idx): > > images = Image.open(self.images[idx]) > caption = self.caption[idx] > return images,caption > > dataset = image_caption_dataset(df) > train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader > ``` > > With this dataset definition, you can omit the `Image.fromarray()` since the actual data already in PIL format. > > If you are interested in doing image-image similarity, just modify the dataset to return pair of images and > for the training code, adjust the code accordingly, a big change will happen in the creating the logits part. Change the forward method ` logits_per_image, logits_per_text = model(images, texts)` according to https://github.com/openai/CLIP/blob/main/clip/model.py, line 354. Thank you very much. It really helps a lot.
Author
Owner

@vinson2233 commented on GitHub (Apr 12, 2021):

@lonngxiang oh you are correct. pardon me, I have edited my code above. The dataset should return something that can be put on PyTorch tensor.

<!-- gh-comment-id:817594625 --> @vinson2233 commented on GitHub (Apr 12, 2021): @lonngxiang oh you are correct. pardon me, I have edited my code above. The dataset should return something that can be put on PyTorch tensor.
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

@lonngxiang oh you are correct. pardon me, I have edited my code above. The dataset should return something that can be put on PyTorch tensor.

one more thing,when you use preprocess in class image_caption_dataset, the torch.stack's preprocess is it still useful?

<!-- gh-comment-id:817598741 --> @lonngxiang commented on GitHub (Apr 12, 2021): > @lonngxiang oh you are correct. pardon me, I have edited my code above. The dataset should return something that can be put on PyTorch tensor. one more thing,when you use preprocess in class image_caption_dataset, the torch.stack's preprocess is it still useful?
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

@lonngxiang oh you are correct. pardon me, I have edited my code above. The dataset should return something that can be put on PyTorch tensor.

still have a error in images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0):

AttributeError: 'Tensor' object has no attribute 'array_interface'

<!-- gh-comment-id:817600670 --> @lonngxiang commented on GitHub (Apr 12, 2021): > @lonngxiang oh you are correct. pardon me, I have edited my code above. The dataset should return something that can be put on PyTorch tensor. still have a error in images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0): AttributeError: 'Tensor' object has no attribute '__array_interface__'
Author
Owner

@vinson2233 commented on GitHub (Apr 12, 2021):

Yeah, if already using preprocess inside the class. The result from the batch can be used directly to the CLIP. So that line can be change into this : images = list_image

<!-- gh-comment-id:817611630 --> @vinson2233 commented on GitHub (Apr 12, 2021): Yeah, if already using preprocess inside the class. The result from the batch can be used directly to the CLIP. So that line can be change into this : `images = list_image `
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

Yeah, if already using preprocess inside the class. The result from the batch can be used directly to the CLIP. So that line can be change into this : images = list_image

then have anthor error:
RuntimeError: "unfolded2d_copy" not implemented for 'Half'

<!-- gh-comment-id:817613476 --> @lonngxiang commented on GitHub (Apr 12, 2021): > Yeah, if already using preprocess inside the class. The result from the batch can be used directly to the CLIP. So that line can be change into this : `images = list_image ` then have anthor error: RuntimeError: "unfolded2d_copy" not implemented for 'Half'
Author
Owner

@vinson2233 commented on GitHub (Apr 12, 2021):

Hmmmm, that error is new for me. Is the error occurred when calculating the loss?

<!-- gh-comment-id:817617016 --> @vinson2233 commented on GitHub (Apr 12, 2021): Hmmmm, that error is new for me. Is the error occurred when calculating the loss?
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

Hmmmm, that error is new for me. Is the error occurred when calculating the loss?

yes,the error occurred in this line:
logits_per_image, logits_per_text = model(images, texts)

add model(images.float(), texts.float()) still error:
RuntimeError: "unfolded2d_copy" not implemented for 'Half'

<!-- gh-comment-id:817636748 --> @lonngxiang commented on GitHub (Apr 12, 2021): > Hmmmm, that error is new for me. Is the error occurred when calculating the loss? yes,the error occurred in this line: logits_per_image, logits_per_text = model(images, texts) add model(images.float(), texts.float()) still error: RuntimeError: "unfolded2d_copy" not implemented for 'Half'
Author
Owner

@vinson2233 commented on GitHub (Apr 12, 2021):

Are you using CPU by any chance? The mixed precision training usually don't work on CPU

<!-- gh-comment-id:817641457 --> @vinson2233 commented on GitHub (Apr 12, 2021): Are you using CPU by any chance? The mixed precision training usually don't work on CPU
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

Are you using CPU by any chance? The mixed precision training usually don't work on CPU

yes, i use it on cpu

<!-- gh-comment-id:817667957 --> @lonngxiang commented on GitHub (Apr 12, 2021): > Are you using CPU by any chance? The mixed precision training usually don't work on CPU yes, i use it on cpu
Author
Owner

@vinson2233 commented on GitHub (Apr 12, 2021):

@lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU

<!-- gh-comment-id:817673043 --> @vinson2233 commented on GitHub (Apr 12, 2021): @lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU
Author
Owner

@lonngxiang commented on GitHub (Apr 12, 2021):

@lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU

ok. so kind of you; Thank you for your patience

<!-- gh-comment-id:817686464 --> @lonngxiang commented on GitHub (Apr 12, 2021): > @lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU ok. so kind of you; Thank you for your patience
Author
Owner

@lonngxiang commented on GitHub (Apr 13, 2021):

@lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU
run it on cpu;There's still a problem. the total_loss is always 0

image

<!-- gh-comment-id:818362520 --> @lonngxiang commented on GitHub (Apr 13, 2021): > @lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU run it on cpu;There's still a problem. the total_loss is always 0 ![image](https://user-images.githubusercontent.com/40717349/114482928-fdcbe880-9c39-11eb-8897-13648d5d7495.png)
Author
Owner

@lonngxiang commented on GitHub (Apr 13, 2021):

@lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU

how to set BATCH_SIZE to get ground_truth's label?

<!-- gh-comment-id:818372903 --> @lonngxiang commented on GitHub (Apr 13, 2021): > @lonngxiang I have updated the code again. Basically, remove all code related to mixed-precision training when using CPU instead of GPU how to set BATCH_SIZE to get ground_truth's label?
Author
Owner

@vinson2233 commented on GitHub (Apr 13, 2021):

@lonngxiang Hmmmm, I don't have the faintest idea why the loss is = 0.

BATCH_SIZE is just an integer that you set. Since the image-text are in pairs, the first image will correspond to the first text. So the ground truth for the first image is 0, the second image will correspond to the second image, so the ground truth is 1.
This pattern keeps repeating until the last image-text pair.
So the ground truth is a torch tensor like this : torch.tensor([0,1,2,3,...,BATCH_SIZE-1]).
Since the pre-trained CLIP use a massive batch size, just try to use the largest BATCH_SIZE as your system can take.

You can read more info about cross-entropy loss https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html, especially about the target. Also the CLIP paper, page 5, the upper left part.

<!-- gh-comment-id:818382207 --> @vinson2233 commented on GitHub (Apr 13, 2021): @lonngxiang Hmmmm, I don't have the faintest idea why the loss is = 0. BATCH_SIZE is just an integer that you set. Since the image-text are in pairs, the first image will correspond to the first text. So the ground truth for the first image is 0, the second image will correspond to the second image, so the ground truth is 1. This pattern keeps repeating until the last image-text pair. So the ground truth is a torch tensor like this : `torch.tensor([0,1,2,3,...,BATCH_SIZE-1])`. Since the pre-trained CLIP use a massive batch size, just try to use the largest BATCH_SIZE as your system can take. You can read more info about cross-entropy loss https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html, especially about the target. Also the CLIP paper, page 5, the upper left part.
Author
Owner

@lonngxiang commented on GitHub (Apr 13, 2021):

@lonngxiang Hmmmm, I don't have the faintest idea why the loss is = 0.

BATCH_SIZE is just an integer that you set. Since the image-text are in pairs, the first image will correspond to the first text. So the ground truth for the first image is 0, the second image will correspond to the second image, so the ground truth is 1.
This pattern keeps repeating until the last image-text pair.
So the ground truth is a torch tensor like this : torch.tensor([0,1,2,3,...,BATCH_SIZE-1]).
Since the pre-trained CLIP use a massive batch size, just try to use the largest BATCH_SIZE as your system can take.

You can read more info about cross-entropy loss https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html, especially about the target. Also the CLIP paper, page 5, the upper left part.

tks for your reply;so If you have five pairs, so your BATCH_SIZE is five,is right?

<!-- gh-comment-id:818383628 --> @lonngxiang commented on GitHub (Apr 13, 2021): > @lonngxiang Hmmmm, I don't have the faintest idea why the loss is = 0. > > BATCH_SIZE is just an integer that you set. Since the image-text are in pairs, the first image will correspond to the first text. So the ground truth for the first image is 0, the second image will correspond to the second image, so the ground truth is 1. > This pattern keeps repeating until the last image-text pair. > So the ground truth is a torch tensor like this : `torch.tensor([0,1,2,3,...,BATCH_SIZE-1])`. > Since the pre-trained CLIP use a massive batch size, just try to use the largest BATCH_SIZE as your system can take. > > You can read more info about cross-entropy loss https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html, especially about the target. Also the CLIP paper, page 5, the upper left part. tks for your reply;so If you have five pairs, so your BATCH_SIZE is five,is right?
Author
Owner

@vinson2233 commented on GitHub (Apr 13, 2021):

Your BATCH_SIZE will determince the number of pairs for each batch

For example, If you have 1000 pairs, and set BATCH_SIZE = 20.
Then for each loop of for batch in train_dataloader, the variable batch will give you 20 pairs. The loop will be repeated 50 times to cover all the data for 1 epoch.

<!-- gh-comment-id:818385199 --> @vinson2233 commented on GitHub (Apr 13, 2021): Your BATCH_SIZE will determince the number of pairs for each batch For example, If you have 1000 pairs, and set BATCH_SIZE = 20. Then for each loop of `for batch in train_dataloader`, the variable `batch` will give you 20 pairs. The loop will be repeated 50 times to cover all the data for 1 epoch.
Author
Owner

@lonngxiang commented on GitHub (Apr 13, 2021):

Your BATCH_SIZE will determince the number of pairs for each batch

For example, If you have 1000 pairs, and set BATCH_SIZE = 20.
Then for each loop of for batch in train_dataloader, the variable batch will give you 20 pairs. The loop will be repeated 50 times to cover all the data for 1 epoch.

yes,but when I set BATCH_SIZE = 1,the total_loss is always 0,is this right?What's wrong with it

<!-- gh-comment-id:818387092 --> @lonngxiang commented on GitHub (Apr 13, 2021): > Your BATCH_SIZE will determince the number of pairs for each batch > > For example, If you have 1000 pairs, and set BATCH_SIZE = 20. > Then for each loop of `for batch in train_dataloader`, the variable `batch` will give you 20 pairs. The loop will be repeated 50 times to cover all the data for 1 epoch. yes,but when I set BATCH_SIZE = 1,the total_loss is always 0,is this right?What's wrong with it
Author
Owner

@vinson2233 commented on GitHub (Apr 13, 2021):

Yes, that's the problem. BATCH_SIZE must be greater than 1.
The reason is your prediction will return cosine similarity for that image and that text.
CrossEntropyLoss is combination of softmax with logloss.
Since one row only has 1 prediction(because BATCH_SIZE=1), the softmax will return probability=1 for that entry(It doesn't matter whether the logits is high or low), where it automatically correspond to the correct ground truth.

<!-- gh-comment-id:818393765 --> @vinson2233 commented on GitHub (Apr 13, 2021): Yes, that's the problem. BATCH_SIZE must be greater than 1. The reason is your prediction will return cosine similarity for that image and that text. CrossEntropyLoss is combination of softmax with logloss. Since one row only has 1 prediction(because BATCH_SIZE=1), the softmax will return probability=1 for that entry(It doesn't matter whether the logits is high or low), where it automatically correspond to the correct ground truth.
Author
Owner

@lonngxiang commented on GitHub (Apr 13, 2021):

Yes, that's the problem. BATCH_SIZE must be greater than 1.
The reason is your prediction will return cosine similarity for that image and that text.
CrossEntropyLoss is combination of softmax with logloss.
Since one row only has 1 prediction(because BATCH_SIZE=1), the softmax will return probability=1 for that entry(It doesn't matter whether the logits is high or low), where it automatically correspond to the correct ground truth.

Thank you for helping me a lot and learning a lot

<!-- gh-comment-id:818395366 --> @lonngxiang commented on GitHub (Apr 13, 2021): > Yes, that's the problem. BATCH_SIZE must be greater than 1. > The reason is your prediction will return cosine similarity for that image and that text. > CrossEntropyLoss is combination of softmax with logloss. > Since one row only has 1 prediction(because BATCH_SIZE=1), the softmax will return probability=1 for that entry(It doesn't matter whether the logits is high or low), where it automatically correspond to the correct ground truth. Thank you for helping me a lot and learning a lot
Author
Owner

@dmoham1476 commented on GitHub (Apr 13, 2021):

  1. Don't we need to do clip.load_state_dict after clip.load?
  2. Are we not doing model.encode_image and model.encode_text and then doing norm before training?
  3. Can you please add demo code for early stopping, saving the model (.pt) and metrics as well
  4. Are we fine-tuning only ViT and not the text part? How did this impact performance on custom dataset?
<!-- gh-comment-id:818427152 --> @dmoham1476 commented on GitHub (Apr 13, 2021): 1. Don't we need to do clip.load_state_dict after clip.load? 2. Are we not doing model.encode_image and model.encode_text and then doing norm before training? 3. Can you please add demo code for early stopping, saving the model (.pt) and metrics as well 4. Are we fine-tuning only ViT and not the text part? How did this impact performance on custom dataset?
Author
Owner

@vinson2233 commented on GitHub (Apr 13, 2021):

@dmoham1476

  1. No. See this code https://github.com/openai/CLIP/blob/main/clip/clip.py line 114. They already load the model when we calling CLIP. Only use torch load_state_dict to continue training.
  2. Yes, that all happen inside forward function. See this code https://github.com/openai/CLIP/blob/main/clip/model.py line 354. If you want to train text and train similarity with one to one pair, the forward already take care off the encode_image, encode_text and normalizing.
EARLYSTOP_PATIENCE = 10 # Define your own number
best_loss = np.Inf
best_iter = 0
for epoch in range(EPOCH):
  for batch in train_dataloader :
      <do training>
      if device == "cpu":
         optimizer.step()
      else : 
        convert_models_to_fp32(model)
        optimizer.step()
        clip.model.convert_weights(model)

  # EVALUATION ON VALIDATION DATASET
  for batch in validation_dataloader :
    <do forward prop on batch validation data>
    val_loss = <calculate loss>

  if val_loss < best_loss :
    best_iter = epoch+1
    best_loss = val_loss

  torch.save({
        'epoch': k,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': loss,
        }, f"save_dir")
        
   if ((epoch+1)-best_iter)>EARLYSTOP_PATIENCE:
     print("Early stop achieved at", epoch+1)
     break
      
  1. After loading the CLIP. Try to print the CLIP. It will show a long list of layers. You can call the component like this : model.transformer, model.visual.transformer. The text part only using transformers. While the visual part, also using transformers(it's the model.visual.transformer). Loading CLIP will allow you to train all the parts by default. You can freeze some components for example like this :
for k in model.visual.transformer.parameters():  
  k.requires_grad=False

This code will freeze all the visual parts.
I encourage you to see the components of CLIP

<!-- gh-comment-id:818437262 --> @vinson2233 commented on GitHub (Apr 13, 2021): @dmoham1476 1. No. See this code https://github.com/openai/CLIP/blob/main/clip/clip.py line 114. They already load the model when we calling CLIP. Only use torch load_state_dict to continue training. 2. Yes, that all happen inside forward function. See this code https://github.com/openai/CLIP/blob/main/clip/model.py line 354. If you want to train text and train similarity with one to one pair, the forward already take care off the encode_image, encode_text and normalizing. 3. ```python EARLYSTOP_PATIENCE = 10 # Define your own number best_loss = np.Inf best_iter = 0 for epoch in range(EPOCH): for batch in train_dataloader : <do training> if device == "cpu": optimizer.step() else : convert_models_to_fp32(model) optimizer.step() clip.model.convert_weights(model) # EVALUATION ON VALIDATION DATASET for batch in validation_dataloader : <do forward prop on batch validation data> val_loss = <calculate loss> if val_loss < best_loss : best_iter = epoch+1 best_loss = val_loss torch.save({ 'epoch': k, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), 'loss': loss, }, f"save_dir") if ((epoch+1)-best_iter)>EARLYSTOP_PATIENCE: print("Early stop achieved at", epoch+1) break ``` 4. After loading the CLIP. Try to print the CLIP. It will show a long list of layers. You can call the component like this : `model.transformer`, `model.visual.transformer`. The text part only using transformers. While the visual part, also using transformers(it's the model.visual.transformer). Loading CLIP will allow you to train all the parts by default. You can freeze some components for example like this : ``` for k in model.visual.transformer.parameters(): k.requires_grad=False ``` This code will freeze all the visual parts. I encourage you to see the components of CLIP
Author
Owner

@uplusv commented on GitHub (Apr 25, 2021):

Hi, Vinson! Thank you for your code, it helps me a lot! but I met a problem when I fine-tune CLIP on my own data with your code. The task is to classify a 6-class problem so I set batch_size=6. After fine-tuning, the model outputs sample feature for every image, is it the problem of small batch size or fixed order of 6 classes or perhaps something else?

<!-- gh-comment-id:826260093 --> @uplusv commented on GitHub (Apr 25, 2021): Hi, Vinson! Thank you for your code, it helps me a lot! but I met a problem when I fine-tune CLIP on my own data with your code. The task is to classify a 6-class problem so I set batch_size=6. After fine-tuning, the model outputs sample feature for every image, is it the problem of small batch size or fixed order of 6 classes or perhaps something else?
Author
Owner

@vinson2233 commented on GitHub (Apr 25, 2021):

@uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do :

  1. Change the ground_truth = torch.arange(BATCH_SIZE).to(device) to integer vector that specify which class your image are on (for example torch.tensor([0,1,2,1,2,3,4,5])). With this now you can set your batch size in arbitrary size.
  2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 to total_loss = loss_img(logits_per_image,ground_truth)

I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image"

<!-- gh-comment-id:826262221 --> @vinson2233 commented on GitHub (Apr 25, 2021): @uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do : 1. Change the ` ground_truth = torch.arange(BATCH_SIZE).to(device)` to integer vector that specify which class your image are on (for example `torch.tensor([0,1,2,1,2,3,4,5])`). With this now you can set your batch size in arbitrary size. 2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the ` total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2` to `total_loss = loss_img(logits_per_image,ground_truth) ` I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image"
Author
Owner

@uplusv commented on GitHub (Apr 25, 2021):

@uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do :

  1. Change the ground_truth = torch.arange(BATCH_SIZE).to(device) to integer vector that specify which class your image are on (for example torch.tensor([0,1,2,1,2,3,4,5])). With this now you can set your batch size in arbitrary size.
  2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 to total_loss = loss_img(logits_per_image,ground_truth)

I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image"

Thank you for your reply and advice, I will try it soon! By "After fine-tuning, the model outputs sample feature for every image", I mean that, with "image_features = model.encode_image(image_input)" I print this "image_features" and get image_features: tensor([
[ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039],
[ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039],
[ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039],
...,
[ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039],
[ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039],
[ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039]])
while the original model outputs:
image_features: tensor([
[ 0.0304, -0.0169, -0.0383, ..., 0.0927, 0.0261, 0.0203],
[ 0.0013, -0.0067, -0.0524, ..., 0.1029, 0.0028, 0.0169],
[ 0.0115, -0.0006, -0.0392, ..., 0.0616, 0.0317, 0.0171],
...,
[ 0.0173, -0.0152, -0.0431, ..., 0.0836, 0.0405, 0.0268],
[ 0.0287, -0.0236, -0.0401, ..., 0.0856, 0.0119, 0.0287],
[ 0.0150, 0.0013, -0.0537, ..., 0.0792, 0.0104, 0.0062]])
After fine-tuning, the features become same and smaller so I get identical and large logits(like 99.8856) for every image😢.

<!-- gh-comment-id:826272681 --> @uplusv commented on GitHub (Apr 25, 2021): > @uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do : > > 1. Change the ` ground_truth = torch.arange(BATCH_SIZE).to(device)` to integer vector that specify which class your image are on (for example `torch.tensor([0,1,2,1,2,3,4,5])`). With this now you can set your batch size in arbitrary size. > 2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the ` total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2` to `total_loss = loss_img(logits_per_image,ground_truth) ` > > I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image" Thank you for your reply and advice, I will try it soon! By "After fine-tuning, the model outputs sample feature for every image", I mean that, with "image_features = model.encode_image(image_input)" I print this "image_features" and get image_features: tensor([ [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], ..., [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039]]) while the original model outputs: image_features: tensor([ [ 0.0304, -0.0169, -0.0383, ..., 0.0927, 0.0261, 0.0203], [ 0.0013, -0.0067, -0.0524, ..., 0.1029, 0.0028, 0.0169], [ 0.0115, -0.0006, -0.0392, ..., 0.0616, 0.0317, 0.0171], ..., [ 0.0173, -0.0152, -0.0431, ..., 0.0836, 0.0405, 0.0268], [ 0.0287, -0.0236, -0.0401, ..., 0.0856, 0.0119, 0.0287], [ 0.0150, 0.0013, -0.0537, ..., 0.0792, 0.0104, 0.0062]]) After fine-tuning, the features become same and smaller so I get identical and large logits(like 99.8856) for every image😢.
Author
Owner

@vinson2233 commented on GitHub (Apr 25, 2021):

Hmmm, I don't know what caused the model to produce the same value. Maybe something broke inside your data loader.
Whatever the cause is, I hope you can find your solution.

<!-- gh-comment-id:826289087 --> @vinson2233 commented on GitHub (Apr 25, 2021): Hmmm, I don't know what caused the model to produce the same value. Maybe something broke inside your data loader. Whatever the cause is, I hope you can find your solution.
Author
Owner

@Zasder3 commented on GitHub (May 23, 2021):

For those looking here in the future, I've made use of @vinson2233's code to create an easy-to-use PyTorch Lightning repo for training your own CLIP model from scratch.

<!-- gh-comment-id:846612802 --> @Zasder3 commented on GitHub (May 23, 2021): For those looking here in the future, I've made use of @vinson2233's code to create an easy-to-use [PyTorch Lightning repo](https://github.com/Zasder3/train-CLIP) for training your own CLIP model from scratch.
Author
Owner

@ChawDoe commented on GitHub (May 23, 2021):

Hey, I try to train it from scratch. But I found that the model is hard to train. The loss remains stable after some iterations. Do you meet the same problem?

<!-- gh-comment-id:846613660 --> @ChawDoe commented on GitHub (May 23, 2021): Hey, I try to train it from scratch. But I found that the model is hard to train. The loss remains stable after some iterations. Do you meet the same problem?
Author
Owner

@vinson2233 commented on GitHub (May 24, 2021):

@Zasder3 awesome, thanks for the effort 👍. It would be a blast if we can recreate every configuration from the paper since my code still lacks several features
@ChawDoe For me, the training went quite smoothly. I use batch size 512(with 4 GPU), 1million pairs data, and gradient accumulation for 8 steps. First several step give me loss around 2, at 20 epoch my average raining loss is 0.14

<!-- gh-comment-id:846682178 --> @vinson2233 commented on GitHub (May 24, 2021): @Zasder3 awesome, thanks for the effort 👍. It would be a blast if we can recreate every configuration from the paper since my code still lacks several features @ChawDoe For me, the training went quite smoothly. I use batch size 512(with 4 GPU), 1million pairs data, and gradient accumulation for 8 steps. First several step give me loss around 2, at 20 epoch my average raining loss is 0.14
Author
Owner

@ChawDoe commented on GitHub (May 24, 2021):

@vinson2233 Do you use fp16 training here? I think the problem may be due to my fp16 training and I set lr to 5e-5, which may lead to invalid gradients.

<!-- gh-comment-id:846692589 --> @ChawDoe commented on GitHub (May 24, 2021): @vinson2233 Do you use fp16 training here? I think the problem may be due to my fp16 training and I set lr to 5e-5, which may lead to invalid gradients.
Author
Owner

@vinson2233 commented on GitHub (May 24, 2021):

@ChawDoe I'm using fp16 for forward pass and gradient calculation(backward), using fp32 for parameter update(step), just like the code I'm posted. Using full fp32 give slow training time and lower batch size, while using full fp16 give NaN gradient because of underflow. The gradient might differ slightly between fp16 and fp32 but it shouldn't affect the training to the point of wrong step direction.

<!-- gh-comment-id:846696401 --> @vinson2233 commented on GitHub (May 24, 2021): @ChawDoe I'm using fp16 for forward pass and gradient calculation(backward), using fp32 for parameter update(step), just like the code I'm posted. Using full fp32 give slow training time and lower batch size, while using full fp16 give NaN gradient because of underflow. The gradient might differ slightly between fp16 and fp32 but it shouldn't affect the training to the point of wrong step direction.
Author
Owner

@lonngxiang commented on GitHub (May 25, 2021):

I use this code training to save PT or PKL files, but how do I load and reuse them later

<!-- gh-comment-id:847639893 --> @lonngxiang commented on GitHub (May 25, 2021): I use this code training to save PT or PKL files, but how do I load and reuse them later
Author
Owner

@vinson2233 commented on GitHub (May 25, 2021):

@lonngxiang i have update the code for save and load, basically to load the model use this code :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) 
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution 
checkpoint['model_state_dict']["context_length"] = model.context_length
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Just modify the dict key to match your dict key when saving to .pt file

<!-- gh-comment-id:847655106 --> @vinson2233 commented on GitHub (May 25, 2021): @lonngxiang i have update the code for save and load, basically to load the model use this code : ```python model, preprocess = clip.load("ViT-B/32",device=device,jit=False) checkpoint = torch.load("model_checkpoint/model_10.pt") # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] checkpoint['model_state_dict']["input_resolution"] = model.input_resolution checkpoint['model_state_dict']["context_length"] = model.context_length checkpoint['model_state_dict']["vocab_size"] = model.vocab_size model.load_state_dict(checkpoint['model_state_dict']) ``` Just modify the dict key to match your dict key when saving to .pt file
Author
Owner

@lonngxiang commented on GitHub (May 25, 2021):

@lonngxiang i have update the code for save and load, basically to load the model use this code :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) 
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution 
checkpoint['model_state_dict']["context_length"] = model.context_length
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Just modify the dict key to match your dict key when saving to .pt
i see,Let me try;tks

<!-- gh-comment-id:847659468 --> @lonngxiang commented on GitHub (May 25, 2021): > @lonngxiang i have update the code for save and load, basically to load the model use this code : > > ```python > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) > checkpoint = torch.load("model_checkpoint/model_10.pt") > > # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] > checkpoint['model_state_dict']["input_resolution"] = model.input_resolution > checkpoint['model_state_dict']["context_length"] = model.context_length > checkpoint['model_state_dict']["vocab_size"] = model.vocab_size > > model.load_state_dict(checkpoint['model_state_dict']) > ``` > > Just modify the dict key to match your dict key when saving to .pt i see,Let me try;tks
Author
Owner

@vinson2233 commented on GitHub (May 25, 2021):

@lonngxiang actually, you don't need to copy the entire message to reply to a specific message, especially for long message. You can use the copy link function on top right of the message to produce a URL like this that directed to the specific message: this https://github.com/openai/CLIP/issues/83#issue-853114174. Just to make things shorter

For your question, yes k is epoch and loss is total_loss, I just copy-paste from my actual code and forgot to change the variable, will fix that right away.

<!-- gh-comment-id:847670253 --> @vinson2233 commented on GitHub (May 25, 2021): @lonngxiang actually, you don't need to copy the entire message to reply to a specific message, especially for long message. You can use the copy link function on top right of the message to produce a URL like this that directed to the specific message: this https://github.com/openai/CLIP/issues/83#issue-853114174. Just to make things shorter For your question, yes k is epoch and loss is total_loss, I just copy-paste from my actual code and forgot to change the variable, will fix that right away.
Author
Owner

@lonngxiang commented on GitHub (May 25, 2021):

@vinson2233 tks,https://github.com/openai/CLIP/issues/83#issue-853114174 ,is k equal EPOCH or epoch?i saw you write epoch now

<!-- gh-comment-id:847673752 --> @lonngxiang commented on GitHub (May 25, 2021): @vinson2233 tks,https://github.com/openai/CLIP/issues/83#issue-853114174 ,is k equal EPOCH or epoch?i saw you write epoch now
Author
Owner

@vinson2233 commented on GitHub (May 25, 2021):

@lonngxiang I save my model in every epoch, so I use the epoch variable. Also, if the model training completed, then the epoch will equal to EPOCH-1.
You also can change it torch.save({'epoch': epoch+1,...} so the savings start from 1 and the final save will have epoch key equal to EPOCH.
Note that this epoch key will not affect the model behavior after loading, it only stores meta-data for the model.
The same also goes for total_loss.

<!-- gh-comment-id:847679685 --> @vinson2233 commented on GitHub (May 25, 2021): @lonngxiang I save my model in every epoch, so I use the `epoch` variable. Also, if the model training completed, then the epoch will equal to EPOCH-1. You also can change it `torch.save({'epoch': epoch+1,...}` so the savings start from 1 and the final save will have epoch key equal to `EPOCH`. Note that this `epoch` key will **not affect** the model behavior after loading, it only stores meta-data for the model. The same also goes for total_loss.
Author
Owner

@lonngxiang commented on GitHub (May 25, 2021):

How about the effect of fine-tuning? It seems to affect the previous normal results, and the effect is not good

<!-- gh-comment-id:847710105 --> @lonngxiang commented on GitHub (May 25, 2021): How about the effect of fine-tuning? It seems to affect the previous normal results, and the effect is not good
Author
Owner

@vinson2233 commented on GitHub (May 25, 2021):

Some scenario for saving model :

  1. Train and inference : The important thing to save only the model state
  2. Train, pause and resume : Save the model, epoch and optimizer state. Your epoch counter in the loop will be the continuation of the last epoch. You also need to load the optimizer state from previous training (Adam need info about the running gradient), you can use the load_state_dict method on the optimizer to load checkpoint['optimizer_state_dict']
<!-- gh-comment-id:847719133 --> @vinson2233 commented on GitHub (May 25, 2021): Some scenario for saving model : 1. Train and inference : The important thing to save only the model state 2. Train, pause and resume : Save the model, epoch and optimizer state. Your epoch counter in the loop will be the continuation of the last epoch. You also need to load the optimizer state from previous training (Adam need info about the running gradient), you can use the load_state_dict method on the optimizer to load `checkpoint['optimizer_state_dict']`
Author
Owner

@lonngxiang commented on GitHub (May 25, 2021):

Some scenario for saving model :

  1. Train and inference : The important thing to save only the model state
  2. Train, pause and resume : Save the model, epoch and optimizer state. Your epoch counter in the loop will be the continuation of the last epoch. You also need to load the optimizer state from previous training (Adam need info about the running gradient), you can use the load_state_dict method on the optimizer to load checkpoint['optimizer_state_dict']

how to load?like this?
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])

<!-- gh-comment-id:847755473 --> @lonngxiang commented on GitHub (May 25, 2021): > Some scenario for saving model : > > 1. Train and inference : The important thing to save only the model state > 2. Train, pause and resume : Save the model, epoch and optimizer state. Your epoch counter in the loop will be the continuation of the last epoch. You also need to load the optimizer state from previous training (Adam need info about the running gradient), you can use the load_state_dict method on the optimizer to load `checkpoint['optimizer_state_dict']` how to load?like this? model.load_state_dict(checkpoint['model_state_dict']) optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
Author
Owner

@vinson2233 commented on GitHub (May 25, 2021):

@lonngxiang That should be correct. Note that I never try to load the optimizer since I never pause the training.

<!-- gh-comment-id:847761922 --> @vinson2233 commented on GitHub (May 25, 2021): @lonngxiang That should be correct. Note that I never try to load the optimizer since I never pause the training.
Author
Owner

@lonngxiang commented on GitHub (May 25, 2021):

@lonngxiang That should be correct. Note that I never try to load the optimizer since I never pause the training.
tks,Let me try it
image

<!-- gh-comment-id:847763852 --> @lonngxiang commented on GitHub (May 25, 2021): > @lonngxiang That should be correct. Note that I never try to load the optimizer since I never pause the training. tks,Let me try it ![image](https://user-images.githubusercontent.com/40717349/119485476-b46acf00-bd89-11eb-96e0-2762ade98ab5.png)
Author
Owner

@vinson2233 commented on GitHub (May 25, 2021):

what is it that doesn't work? does it raise any error? I set jit=False when loading the model for the clip.load

<!-- gh-comment-id:847803159 --> @vinson2233 commented on GitHub (May 25, 2021): what is it that doesn't work? does it raise any error? I set jit=False when loading the model for the `clip.load`
Author
Owner

@lonngxiang commented on GitHub (May 26, 2021):

what is it that doesn't work? does it raise any error? I set jit=False when loading the model for the clip.load
Again, it didn't work out well
image

<!-- gh-comment-id:848382228 --> @lonngxiang commented on GitHub (May 26, 2021): > what is it that doesn't work? does it raise any error? I set jit=False when loading the model for the `clip.load` Again, it didn't work out well ![image](https://user-images.githubusercontent.com/40717349/119587748-e586e600-be01-11eb-933d-03a3637e8251.png)
Author
Owner

@lonngxiang commented on GitHub (May 26, 2021):

what is it that doesn't work? does it raise any error? I set jit=False when loading the model for the clip.load

There were no mistakes, but the results were bad
image

<!-- gh-comment-id:848388706 --> @lonngxiang commented on GitHub (May 26, 2021): > what is it that doesn't work? does it raise any error? I set jit=False when loading the model for the `clip.load` There were no mistakes, but the results were bad ![image](https://user-images.githubusercontent.com/40717349/119589105-b9209900-be04-11eb-8623-7476c662a973.png)
Author
Owner

@wilderrodrigues commented on GitHub (May 31, 2021):

Hi @vinson2233 ,

First of all, thanks for the contribution.

I'm implementing a package using part of the code you published here. The add-ons I have are more related to creating the custom dataset, adding unit tests, dockerising the whole thing and also offering a service so other people can have quickly have inference running for their own + some plots.

However, when trying to train on my RTX 2080, I'm getting this:

Traceback (most recent call last):
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/wilderrodrigues/clip-mania/clip_mania/application/train.py", line 37, in <module>
    app.run(main)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/absl/app.py", line 303, in run
    _run_main(main, args)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/absl/app.py", line 251, in _run_main
    sys.exit(main(argv))
  File "/home/wilderrodrigues/clip-mania/clip_mania/application/train.py", line 28, in main
    model, preprocess = executor.train(dataset_path, epochs=epochs)
  File "/home/wilderrodrigues/clip-mania/clip_mania/core/executor.py", line 67, in train
    logits_per_image, logits_per_text = clip_model(images, prompts)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/clip/model.py", line 355, in forward
    image_features = self.encode_image(image)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/clip/model.py", line 337, in encode_image
    return self.visual(image.type(self.dtype))
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/clip/model.py", line 220, in forward
    x = self.conv1(x)  # shape = [*, width, grid, grid]
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/conv.py", line 423, in forward
    return self._conv_forward(input, self.weight)
  File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/conv.py", line 419, in _conv_forward
    return F.conv2d(input, weight, self.bias, self.stride,
RuntimeError: Expected object of device type cuda but got device type cpu for argument #1 'self' in call to _thnn_conv2d_forward

This is very weird! The code is basically the same. I was using the latest PyTorch, but just now decided to downgrade it and use the same version as the CLIP repo. It still fails. I also tried this:

clip_model, preprocess = clip.load(name=model_name, device=device, jit=False)
clip_model = clip_model.cuda()

No effect at all.

And yes, the GPU is available. I can see it when I try this:

>>> import torch
>>> torch.cuda.is_available()
True

Thanks in advance!

<!-- gh-comment-id:851688791 --> @wilderrodrigues commented on GitHub (May 31, 2021): Hi @vinson2233 , First of all, thanks for the contribution. I'm implementing a package using part of the code you published here. The add-ons I have are more related to creating the custom dataset, adding unit tests, dockerising the whole thing and also offering a service so other people can have quickly have inference running for their own + some plots. However, when trying to train on my RTX 2080, I'm getting this: ``` Traceback (most recent call last): File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/runpy.py", line 87, in _run_code exec(code, run_globals) File "/home/wilderrodrigues/clip-mania/clip_mania/application/train.py", line 37, in <module> app.run(main) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/absl/app.py", line 303, in run _run_main(main, args) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/absl/app.py", line 251, in _run_main sys.exit(main(argv)) File "/home/wilderrodrigues/clip-mania/clip_mania/application/train.py", line 28, in main model, preprocess = executor.train(dataset_path, epochs=epochs) File "/home/wilderrodrigues/clip-mania/clip_mania/core/executor.py", line 67, in train logits_per_image, logits_per_text = clip_model(images, prompts) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl result = self.forward(*input, **kwargs) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/clip/model.py", line 355, in forward image_features = self.encode_image(image) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/clip/model.py", line 337, in encode_image return self.visual(image.type(self.dtype)) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl result = self.forward(*input, **kwargs) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/clip/model.py", line 220, in forward x = self.conv1(x) # shape = [*, width, grid, grid] File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/module.py", line 727, in _call_impl result = self.forward(*input, **kwargs) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/conv.py", line 423, in forward return self._conv_forward(input, self.weight) File "/home/wilderrodrigues/.conda/envs/clip-mania/lib/python3.8/site-packages/torch/nn/modules/conv.py", line 419, in _conv_forward return F.conv2d(input, weight, self.bias, self.stride, RuntimeError: Expected object of device type cuda but got device type cpu for argument #1 'self' in call to _thnn_conv2d_forward ``` This is very weird! The code is basically the same. I was using the latest PyTorch, but just now decided to downgrade it and use the same version as the CLIP repo. It still fails. I also tried this: ``` clip_model, preprocess = clip.load(name=model_name, device=device, jit=False) clip_model = clip_model.cuda() ``` No effect at all. And yes, the GPU is available. I can see it when I try this: ``` >>> import torch >>> torch.cuda.is_available() True ``` Thanks in advance!
Author
Owner

@wilderrodrigues commented on GitHub (Jun 1, 2021):

Just another point:

I checked the parameters of both clip.visual.transformer and clip.transformer blocks and all the tensors are already in the right device.

...
-7.6884e-01,  2.5686e-01, -6.0447e-01], device='cuda:0',
       requires_grad=True)
...

I'm also trying to change the Transformer conv1, having it allocated to the CUDA device. But not helping yet.

Forward pass in the model.py of clip is not happy:

    def forward(self, x: torch.Tensor):
        x = self.conv1(x)  # shape = [*, width, grid, grid]

Will keep digging.

<!-- gh-comment-id:852024535 --> @wilderrodrigues commented on GitHub (Jun 1, 2021): Just another point: I checked the parameters of both `clip.visual.transformer` and `clip.transformer` blocks and all the tensors are already in the right device. ``` ... -7.6884e-01, 2.5686e-01, -6.0447e-01], device='cuda:0', requires_grad=True) ... ``` I'm also trying to change the Transformer conv1, having it allocated to the CUDA device. But not helping yet. Forward pass in the `model.py` of clip is not happy: ``` def forward(self, x: torch.Tensor): x = self.conv1(x) # shape = [*, width, grid, grid] ``` Will keep digging.
Author
Owner

@wilderrodrigues commented on GitHub (Jun 1, 2021):

I found the problem, finally! :) For example, this:

      images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0)
      texts = clip.tokenize(list_txt)

Should be like this:

      images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0).cuda()
      texts = clip.tokenize(list_txt).cuda()

Or, of course, if one prefers, one can have .to(device) instead.

<!-- gh-comment-id:852108441 --> @wilderrodrigues commented on GitHub (Jun 1, 2021): I found the problem, finally! :) For example, this: ```python images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0) texts = clip.tokenize(list_txt) ``` Should be like this: ```python images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0).cuda() texts = clip.tokenize(list_txt).cuda() ``` Or, of course, if one prefers, one can have `.to(device)` instead.
Author
Owner

@wilderrodrigues commented on GitHub (Jun 1, 2021):

Just another quick note: the way the ground_truth is being taken as a range from the BATCH_SIZE is not right. If one has 10 classes and uses 2 batches, it will always give classes (ground_truth) of 0 and 1. So, it bias the training saying that all the images are 0s and 1s.

I changed it and I'm now mapping my prompts (the sentences) to classes in a dictionary: prompt being the key and an integer being the class. It works as expected and with BATCH_SIZE=1 on my MacBook and my GPU. I got 3 novel pictures of airplanes - not in the original dataset - and ran the training for 2 epochs to get this as result:

test_executor.py::TestModelExecutor::test_instance 
test_executor.py::TestModelExecutor::test_train 

============================== 2 passed in 19.44s ==============================

Process finished with exit code 0
PASSED                [ 50%]PASSED                   [100%]
Expected 'an airplane' and  got 'an airplane'
Probability for the expected prompt was '0.9883'
Highest probability was '0.9883'
100%|██████████| 2/2 [00:13<00:00,  6.93s/it]

Before my changes were applied, the loss was always the same and the classifier was not working.

<!-- gh-comment-id:852369783 --> @wilderrodrigues commented on GitHub (Jun 1, 2021): Just another quick note: the way the `ground_truth` is being taken as a range from the `BATCH_SIZE` is not right. If one has 10 classes and uses 2 batches, it will always give classes (ground_truth) of 0 and 1. So, it bias the training saying that all the images are 0s and 1s. I changed it and I'm now mapping my prompts (the sentences) to classes in a dictionary: prompt being the key and an integer being the class. It works as expected and with `BATCH_SIZE=1` on my MacBook and my GPU. I got *3* novel pictures of airplanes - not in the original dataset - and ran the training for 2 epochs to get this as result: ```bash_script test_executor.py::TestModelExecutor::test_instance test_executor.py::TestModelExecutor::test_train ============================== 2 passed in 19.44s ============================== Process finished with exit code 0 PASSED [ 50%]PASSED [100%] Expected 'an airplane' and got 'an airplane' Probability for the expected prompt was '0.9883' Highest probability was '0.9883' 100%|██████████| 2/2 [00:13<00:00, 6.93s/it] ``` Before my changes were applied, the loss was always the same and the classifier was not working.
Author
Owner

@DRSY commented on GitHub (Jun 4, 2021):

Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models?

<!-- gh-comment-id:854302892 --> @DRSY commented on GitHub (Jun 4, 2021): Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models?
Author
Owner

@lonngxiang commented on GitHub (Jun 4, 2021):

Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models?

everything goes worse when I fine-tune the CLIP

<!-- gh-comment-id:854306685 --> @lonngxiang commented on GitHub (Jun 4, 2021): > Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models? everything goes worse when I fine-tune the CLIP
Author
Owner

@DRSY commented on GitHub (Jun 4, 2021):

Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models?

everything goes worse when I fine-tune the CLIP

From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO
5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN).

<!-- gh-comment-id:854312877 --> @DRSY commented on GitHub (Jun 4, 2021): > > Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models? > > everything goes worse when I fine-tune the CLIP From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO 5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN).
Author
Owner

@lonngxiang commented on GitHub (Jun 4, 2021):

Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models?

everything goes worse when I fine-tune the CLIP

From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO
5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN).

are you use this issues code to finetune? https://github.com/openai/CLIP/issues/83;anythin are you changes ?

<!-- gh-comment-id:854314177 --> @lonngxiang commented on GitHub (Jun 4, 2021): > > > Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models? > > > > > > everything goes worse when I fine-tune the CLIP > > From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO > 5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN). are you use this issues code to finetune? https://github.com/openai/CLIP/issues/83;anythin are you changes ?
Author
Owner

@vinson2233 commented on GitHub (Jun 4, 2021):

@wilderrodrigues I forgot to include to(device) in my code, thanks for the catch.
Also regarding the ground truth, this ground_truth is designed for image-title embedding to utilize the concept of n-pair-loss, not for image-title classification. I have mentioned this somewhere in this long threads about modifying the CLIP for classification task (https://github.com/openai/CLIP/issues/83#issuecomment-826262221)

<!-- gh-comment-id:854314332 --> @vinson2233 commented on GitHub (Jun 4, 2021): @wilderrodrigues I forgot to include to(device) in my code, thanks for the catch. Also regarding the ground truth, this ground_truth is designed for image-title embedding to utilize the concept of n-pair-loss, not for image-title classification. I have mentioned this somewhere in this long threads about modifying the CLIP for classification task (https://github.com/openai/CLIP/issues/83#issuecomment-826262221)
Author
Owner

@DRSY commented on GitHub (Jun 4, 2021):

Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models?

everything goes worse when I fine-tune the CLIP

From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO
5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN).

are you use this issues code to finetune? https://github.com/openai/CLIP/issues/83;anythin are you changes ?

I used the PyTorch lightning code, but modify the learning rate for ViT-B/32 from 5e-4 to 5e-5. If I use 5e-4 learning rate, after the first several steps, the model degraded to near-zero accuracy. But if I use 5e-5 learning rate, the model will steadily get improved to the results I posted.

<!-- gh-comment-id:854328593 --> @DRSY commented on GitHub (Jun 4, 2021): > > > > Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models? > > > > > > > > > everything goes worse when I fine-tune the CLIP > > > > > > From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO > > 5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN). > > are you use this issues code to finetune? [https://github.com/openai/CLIP/issues/83;anythin](https://github.com/openai/CLIP/issues/83%EF%BC%9Banythin) are you changes ? I used the PyTorch lightning code, but modify the learning rate for ViT-B/32 from 5e-4 to 5e-5. If I use 5e-4 learning rate, after the first several steps, the model degraded to near-zero accuracy. But if I use 5e-5 learning rate, the model will steadily get improved to the results I posted.
Author
Owner

@yangydeng commented on GitHub (Jun 8, 2021):

Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage.
Feel free to ask or point out any mistakes in my code.

# Latest Update : 04 June 2021, 09:59 GMT+7

# TO ADD :
# Gradient Checkpointing
# Filter out bias from weight decay
# Decaying learning rate with cosine schedule
# Half-precision Adam statistics
# Half-precision stochastically rounded text encoder weights were used

#BATCH_SIZE must larger than 1
train_dataloader = DataLoader(...,batch_size = BATCH_SIZE) #Define your own dataloader

#https://github.com/openai/CLIP/issues/57
def convert_models_to_fp32(model): 
    for p in model.parameters(): 
        p.data = p.data.float() 
        p.grad.data = p.grad.data.float() 

device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training.
model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
if device == "cpu":
  model.float()
else :
  clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16

loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset

for epoch in range(EPOCH):
  for batch in train_dataloader :
      optimizer.zero_grad()

      list_image,list_txt = batch #list_images is list of image in numpy array(np.uint8), or list of PIL images
    
      images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0).to(device) # omit the Image.fromarray if the images already in PIL format, change this line to images=list_image if using preprocess inside the dataset class
      texts = clip.tokenize(list_txt).to(device)
    
      logits_per_image, logits_per_text = model(images, texts)
      if device == "cpu":
        ground_truth = torch.arange(BATCH_SIZE).long().to(device)
      else:
        ground_truth = torch.arange(BATCH_SIZE).half().to(device)

      total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2
      total_loss.backward()
      if device == "cpu":
         optimizer.step()
      else : 
        convert_models_to_fp32(model)
        optimizer.step()
        clip.model.convert_weights(model)
  • NOTE :

  • that for inference purpose, the conversion step from fp16 to fp32 is not needed, just use the model in full fp16

  • For multi-GPU training, see my comment on #111 (comment)

Code to save the model :

torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': total_loss,
        }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename

Code to load the saved model :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224
checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Notes : @Zasder3 have created a PyTorch lighting version to train the CLIP https://github.com/Zasder3/train-CLIP

Hi, thanks for your sharing.
I was wondering what's the difference between your operation (like cast to fp16 and set back to fp32) and automatic-mix-precision(eg. torch.cuda.amp). Because in my code, I adopt "torch.cuda.amp" but it sometimes occurs NAN during training.

<!-- gh-comment-id:856600801 --> @yangydeng commented on GitHub (Jun 8, 2021): > Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. > Feel free to ask or point out any mistakes in my code. > > ```python > # Latest Update : 04 June 2021, 09:59 GMT+7 > > # TO ADD : > # Gradient Checkpointing > # Filter out bias from weight decay > # Decaying learning rate with cosine schedule > # Half-precision Adam statistics > # Half-precision stochastically rounded text encoder weights were used > > #BATCH_SIZE must larger than 1 > train_dataloader = DataLoader(...,batch_size = BATCH_SIZE) #Define your own dataloader > > #https://github.com/openai/CLIP/issues/57 > def convert_models_to_fp32(model): > for p in model.parameters(): > p.data = p.data.float() > p.grad.data = p.grad.data.float() > > device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training. > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > if device == "cpu": > model.float() > else : > clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16 > > loss_img = nn.CrossEntropyLoss() > loss_txt = nn.CrossEntropyLoss() > optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset > > for epoch in range(EPOCH): > for batch in train_dataloader : > optimizer.zero_grad() > > list_image,list_txt = batch #list_images is list of image in numpy array(np.uint8), or list of PIL images > > images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0).to(device) # omit the Image.fromarray if the images already in PIL format, change this line to images=list_image if using preprocess inside the dataset class > texts = clip.tokenize(list_txt).to(device) > > logits_per_image, logits_per_text = model(images, texts) > if device == "cpu": > ground_truth = torch.arange(BATCH_SIZE).long().to(device) > else: > ground_truth = torch.arange(BATCH_SIZE).half().to(device) > > total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 > total_loss.backward() > if device == "cpu": > optimizer.step() > else : > convert_models_to_fp32(model) > optimizer.step() > clip.model.convert_weights(model) > ``` > > * NOTE : > > * that for inference purpose, the conversion step from fp16 to fp32 is not needed, just use the model in full fp16 > * For multi-GPU training, see my comment on [#111 (comment)](https://github.com/openai/CLIP/issues/111#issuecomment-854320770) > > Code to save the model : > > ```python > torch.save({ > 'epoch': epoch, > 'model_state_dict': model.state_dict(), > 'optimizer_state_dict': optimizer.state_dict(), > 'loss': total_loss, > }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename > ``` > > Code to load the saved model : > > ```python > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > checkpoint = torch.load("model_checkpoint/model_10.pt") > > # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] > checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224 > checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77 > checkpoint['model_state_dict']["vocab_size"] = model.vocab_size > > model.load_state_dict(checkpoint['model_state_dict']) > ``` > > Notes : @Zasder3 have created a PyTorch lighting version to train the CLIP https://github.com/Zasder3/train-CLIP Hi, thanks for your sharing. I was wondering what's the difference between your operation (like cast to fp16 and set back to fp32) and automatic-mix-precision(eg. torch.cuda.amp). Because in my code, I adopt "torch.cuda.amp" but it sometimes occurs NAN during training.
Author
Owner

@vinson2233 commented on GitHub (Jun 8, 2021):

@yangydeng good question. Your question was discussed in the https://github.com/openai/CLIP/issues/57#issuecomment-794864178.
The Author manually specify what kind of operation done in FP16 and FP32, this can be seen from these part of code
github.com/openai/CLIP@cfcffb90e6/clip/model.py (L371-L392)

That's why torch.cuda.amp give different result since amp convert everything(I think), while the author filter out which operation done in FP16

<!-- gh-comment-id:856608848 --> @vinson2233 commented on GitHub (Jun 8, 2021): @yangydeng good question. Your question was discussed in the https://github.com/openai/CLIP/issues/57#issuecomment-794864178. The Author manually specify what kind of operation done in FP16 and FP32, this can be seen from these part of code https://github.com/openai/CLIP/blob/cfcffb90e69f37bf2ff1e988237a0fbe41f33c04/clip/model.py#L371-L392 That's why `torch.cuda.amp` give different result since amp convert everything(I think), while the author filter out which operation done in FP16
Author
Owner

@yangydeng commented on GitHub (Jun 8, 2021):

@yangydeng good question. Your question was discussed in the #57 (comment).
The Author manually specify what kind of operation done in FP16 and FP32, this can be seen from these part of code
github.com/openai/CLIP@cfcffb90e6/clip/model.py (L371-L392)

That's why torch.cuda.amp give different result since amp convert everything(I think), while the author filter out which operation done in FP16

Thanks for your reply, I'll try that later.
And I found you adpot quite a large weight-decay (=0.2) as default. Have you try any other number?

<!-- gh-comment-id:856711790 --> @yangydeng commented on GitHub (Jun 8, 2021): > @yangydeng good question. Your question was discussed in the [#57 (comment)](https://github.com/openai/CLIP/issues/57#issuecomment-794864178). > The Author manually specify what kind of operation done in FP16 and FP32, this can be seen from these part of code > https://github.com/openai/CLIP/blob/cfcffb90e69f37bf2ff1e988237a0fbe41f33c04/clip/model.py#L371-L392 > > That's why `torch.cuda.amp` give different result since amp convert everything(I think), while the author filter out which operation done in FP16 Thanks for your reply, I'll try that later. And I found you adpot quite a large weight-decay (=0.2) as default. Have you try any other number?
Author
Owner

@vinson2233 commented on GitHub (Jun 9, 2021):

@yangydeng That's the value that used by the author (see the paper Appendix F, table 18 on page 48). I haven't try weight-decay lower than that. But I have tried AdamW with weight decay=0.1 and it gives a worse result.

<!-- gh-comment-id:857302047 --> @vinson2233 commented on GitHub (Jun 9, 2021): @yangydeng That's the value that used by the author (see the [paper](https://arxiv.org/pdf/2103.00020.pdf) Appendix F, table 18 on page 48). I haven't try weight-decay lower than that. But I have tried AdamW with weight decay=0.1 and it gives a worse result.
Author
Owner

@yangydeng commented on GitHub (Jun 9, 2021):

@yangydeng That's the value that used by the author (see the paper Appendix F, table 18 on page 48). I haven't try weight-decay lower than that. But I have tried AdamW with weight decay=0.1 and it gives a worse result.

Cool, many details can be found on this table.

<!-- gh-comment-id:857337902 --> @yangydeng commented on GitHub (Jun 9, 2021): > @yangydeng That's the value that used by the author (see the [paper](https://arxiv.org/pdf/2103.00020.pdf) Appendix F, table 18 on page 48). I haven't try weight-decay lower than that. But I have tried AdamW with weight decay=0.1 and it gives a worse result. Cool, many details can be found on this table.
Author
Owner

@ThakurRajAnand commented on GitHub (Jun 16, 2021):

@vinson2233 Thanks for sharing the code. I am getting following error while using the code. Have you seen this during your training?

RuntimeError: Expected object of scalar type Long but got scalar type Half for argument #2 'target' in call to _thnn_nll_loss_forward

<!-- gh-comment-id:862730004 --> @ThakurRajAnand commented on GitHub (Jun 16, 2021): @vinson2233 Thanks for sharing the code. I am getting following error while using the code. Have you seen this during your training? `RuntimeError: Expected object of scalar type Long but got scalar type Half for argument #2 'target' in call to _thnn_nll_loss_forward`
Author
Owner

@vinson2233 commented on GitHub (Jun 18, 2021):

@ThakurRajAnand Is the error raise on the loss_img(logits_per_image,ground_truth) part? Are you working on CPU or GPU ? The error you are showing indicates that the target is Half(then your device is not "CPU"), but the logit are Long type, which indicate that your device is indeed CPU. It might be more helpful if you could print the data type at any given step of your training.

<!-- gh-comment-id:863805808 --> @vinson2233 commented on GitHub (Jun 18, 2021): @ThakurRajAnand Is the error raise on the `loss_img(logits_per_image,ground_truth)` part? Are you working on CPU or GPU ? The error you are showing indicates that the target is Half(then your device is not "CPU"), but the logit are Long type, which indicate that your device is indeed `CPU`. It might be more helpful if you could print the data type at any given step of your training.
Author
Owner

@uahsan3 commented on GitHub (Jun 21, 2021):

@ThakurRajAnand Is the error raise on the loss_img(logits_per_image,ground_truth) part? Are you working on CPU or GPU ? The error you are showing indicates that the target is Half(then your device is not "CPU"), but the logit are Long type, which indicate that your device is indeed CPU. It might be more helpful if you could print the data type at any given step of your training.

Hi, I am facing the same issue. I verified that my device = 'cuda:0' - I am not sure where I am going wrong. Can you please point out why its giving the error:

RuntimeError: Expected object of scalar type Long but got scalar type Half for argument #2 'target' in call to _thnn_nll_loss_forward

<!-- gh-comment-id:865264139 --> @uahsan3 commented on GitHub (Jun 21, 2021): > @ThakurRajAnand Is the error raise on the `loss_img(logits_per_image,ground_truth)` part? Are you working on CPU or GPU ? The error you are showing indicates that the target is Half(then your device is not "CPU"), but the logit are Long type, which indicate that your device is indeed `CPU`. It might be more helpful if you could print the data type at any given step of your training. Hi, I am facing the same issue. I verified that my device = 'cuda:0' - I am not sure where I am going wrong. Can you please point out why its giving the error: > RuntimeError: Expected object of scalar type Long but got scalar type Half for argument #2 'target' in call to _thnn_nll_loss_forward
Author
Owner

@vinson2233 commented on GitHub (Jun 22, 2021):

@ThakurRajAnand @uahsan3 Thanks for the catch. The mistake is from my code. The ground truth should be always long regardless of the device. I've already edited the code. This is the new definition of the ground truth.

ground_truth = torch.arange(BATCH_SIZE,dtype=torch.long,device=device)
<!-- gh-comment-id:865489214 --> @vinson2233 commented on GitHub (Jun 22, 2021): @ThakurRajAnand @uahsan3 Thanks for the catch. The mistake is from my code. The ground truth should be always long regardless of the device. I've already edited the code. This is the new definition of the ground truth. ```python ground_truth = torch.arange(BATCH_SIZE,dtype=torch.long,device=device) ```
Author
Owner

@ThakurRajAnand commented on GitHub (Jun 22, 2021):

@vinson2233 Thanks. I got busy and didn't get a chance to reply that I was able to fix it same day by making same change in your code.

I had another question. Can we use the model to predict text from the model I trained on my own data? I tried but it was asking for image and text both.

<!-- gh-comment-id:865495073 --> @ThakurRajAnand commented on GitHub (Jun 22, 2021): @vinson2233 Thanks. I got busy and didn't get a chance to reply that I was able to fix it same day by making same change in your code. I had another question. Can we use the model to predict text from the model I trained on my own data? I tried but it was asking for image and text both.
Author
Owner

@vinson2233 commented on GitHub (Jun 22, 2021):

@ThakurRajAnand the forward method that defined on CLIP model is basically composition of model.encode_text(text), model.encode_image(img) and cosine calculation between 2 embeddings. If you want to use just the text, then the encode_text is the method you are looking for.
See this part of code for details
github.com/openai/CLIP@cfcffb90e6/clip/model.py (L354-L356)

<!-- gh-comment-id:865497868 --> @vinson2233 commented on GitHub (Jun 22, 2021): @ThakurRajAnand the forward method that defined on CLIP model is basically composition of `model.encode_text(text)`, `model.encode_image(img)` and cosine calculation between 2 embeddings. If you want to use just the text, then the `encode_text` is the method you are looking for. See this part of code for details https://github.com/openai/CLIP/blob/cfcffb90e69f37bf2ff1e988237a0fbe41f33c04/clip/model.py#L354-L356
Author
Owner

@ThakurRajAnand commented on GitHub (Jun 22, 2021):

@vinson2233 I think I didn't explain clearly. I am interested in predicting text by providing new image only. Is that possible? Text I trained on is long e.g. this is a geometry question and we have circles in it

<!-- gh-comment-id:865500152 --> @ThakurRajAnand commented on GitHub (Jun 22, 2021): @vinson2233 I think I didn't explain clearly. I am interested in predicting text by providing new image only. Is that possible? Text I trained on is long e.g. `this is a geometry question and we have circles in it`
Author
Owner

@vinson2233 commented on GitHub (Jun 22, 2021):

@ThakurRajAnand
Ohh i see. So regarding text generation, there are 2 types of techniques. The first one is you already have a set of predefined text and try to fetch which text is the most suitable one(text-retrieval style). The second one is to generate new text from the image(generative). I think the CLIP cannot do the latter one, but you can use CLIP for the text-retrieval style.
I think what your are looking for is something like this https://github.com/pzzhang/VinVL or https://github.com/microsoft/Oscar

<!-- gh-comment-id:865511563 --> @vinson2233 commented on GitHub (Jun 22, 2021): @ThakurRajAnand Ohh i see. So regarding text generation, there are 2 types of techniques. The first one is you already have a set of predefined text and try to fetch which text is the most suitable one(text-retrieval style). The second one is to generate new text from the image(generative). I think the CLIP cannot do the latter one, but you can use CLIP for the text-retrieval style. I think what your are looking for is something like this https://github.com/pzzhang/VinVL or https://github.com/microsoft/Oscar
Author
Owner

@lonngxiang commented on GitHub (Jun 30, 2021):

if I only want to save encode_text piece of the model, anyone knows how to do it?

<!-- gh-comment-id:871250340 --> @lonngxiang commented on GitHub (Jun 30, 2021): if I only want to save encode_text piece of the model, anyone knows how to do it?
Author
Owner

@vinson2233 commented on GitHub (Jun 30, 2021):

@lonngxiang someone have post this question in this threads https://github.com/openai/CLIP/issues/113. I also want to know the answer.

<!-- gh-comment-id:871254293 --> @vinson2233 commented on GitHub (Jun 30, 2021): @lonngxiang someone have post this question in this threads https://github.com/openai/CLIP/issues/113. I also want to know the answer.
Author
Owner

@lonngxiang commented on GitHub (Jun 30, 2021):

@lonngxiang someone have post this question in this threads #113. I also want to know the answer.

tks

<!-- gh-comment-id:871255195 --> @lonngxiang commented on GitHub (Jun 30, 2021): > @lonngxiang someone have post this question in this threads #113. I also want to know the answer. tks
Author
Owner

@lr19960813 commented on GitHub (Jul 2, 2021):

@vinson2233
Hey vinson, Thank you for sharing, it was a great help. But I encountered a problem during training.

Traceback (most recent call last):
File "/CLIP-main/fine_tune.py", line 88, in
logits_per_image, logits_per_text = model(images, texts)
File "/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/CLIP-main/clip/model.py", line 357, in forward
image_features = self.encode_image(image)
File "/CLIP-main/clip/model.py", line 339, in encode_image
return self.visual(image.type(self.dtype))
File "/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/CLIP-main/clip/model.py", line 226, in forward
x = x + self.positional_embedding.to(x.dtype)
RuntimeError: The size of tensor a (1711) must match the size of tensor b (50) at non-singleton dimension 1`

I further tested and finally found that the error occurred in model.py line226:
`

def forward(self, x: torch.Tensor):
    x = self.conv1(x)  # shape = [*, width, grid, grid]
    x = x.reshape(x.shape[0], x.shape[1], -1)  # shape = [*, width, grid ** 2]
    x = x.permute(0, 2, 1)  # shape = [*, grid ** 2, width]
    x = torch.cat([self.class_embedding.to(x.dtype) + torch.zeros(x.shape[0], 1, x.shape[-1], dtype=x.dtype, device=x.device), x], dim=1)  # shape = [*, grid ** 2 + 1, width]
    x = x + self.positional_embedding.to(x.dtype) **#The size of tensor x is 1711 but another is 50.**
    x = self.ln_pre(x)`

I’m not sure what went wrong. I used pandas to load my csv data set, and some texts are very long. Maybe the reason is the text length is too long to be preprocessed but I am not sure.

<!-- gh-comment-id:872761550 --> @lr19960813 commented on GitHub (Jul 2, 2021): @vinson2233 Hey vinson, Thank you for sharing, it was a great help. But I encountered a problem during training. `Traceback` (most recent call last): File "/CLIP-main/fine_tune.py", line 88, in <module> logits_per_image, logits_per_text = model(images, texts) File "/torch/nn/modules/module.py", line 727, in _call_impl result = self.forward(*input, **kwargs) File "/CLIP-main/clip/model.py", line 357, in forward image_features = self.encode_image(image) File "/CLIP-main/clip/model.py", line 339, in encode_image return self.visual(image.type(self.dtype)) File "/torch/nn/modules/module.py", line 727, in _call_impl result = self.forward(*input, **kwargs) File "/CLIP-main/clip/model.py", line 226, in forward x = x + self.positional_embedding.to(x.dtype) **RuntimeError: The size of tensor a (1711) must match the size of tensor b (50) at non-singleton dimension 1`** I further tested and finally found that the error occurred in model.py line226: ` def forward(self, x: torch.Tensor): x = self.conv1(x) # shape = [*, width, grid, grid] x = x.reshape(x.shape[0], x.shape[1], -1) # shape = [*, width, grid ** 2] x = x.permute(0, 2, 1) # shape = [*, grid ** 2, width] x = torch.cat([self.class_embedding.to(x.dtype) + torch.zeros(x.shape[0], 1, x.shape[-1], dtype=x.dtype, device=x.device), x], dim=1) # shape = [*, grid ** 2 + 1, width] x = x + self.positional_embedding.to(x.dtype) **#The size of tensor x is 1711 but another is 50.** x = self.ln_pre(x)` I’m not sure what went wrong. I used pandas to load my csv data set, and some texts are very long. Maybe the reason is the text length is too long to be preprocessed but I am not sure.
Author
Owner

@vinson2233 commented on GitHub (Jul 2, 2021):

@lr19960813 first, your error occured during the image_features = self.encode_image(image) step, so the error caused by the image. Have you make sure to use preprocess module to your images before feeding them to the network? you can put it inside the dataloader when fetching the images.

second, regarding the long text, yes, Clip text only accept token length 77 (1 token represent 1-3 characracter). It's better to trim your text first.

<!-- gh-comment-id:872766932 --> @vinson2233 commented on GitHub (Jul 2, 2021): @lr19960813 first, your error occured during the `image_features = self.encode_image(image)` step, so the error caused by the image. Have you make sure to use `preprocess` module to your images before feeding them to the network? you can put it inside the dataloader when fetching the images. second, regarding the long text, yes, Clip text only accept token length 77 (1 token represent 1-3 characracter). It's better to trim your text first.
Author
Owner

@lr19960813 commented on GitHub (Jul 17, 2021):

@lr19960813 first, your error occured during the image_features = self.encode_image(image) step, so the error caused by the image. Have you make sure to use preprocess module to your images before feeding them to the network? you can put it inside the dataloader when fetching the images.

second, regarding the long text, yes, Clip text only accept token length 77 (1 token represent 1-3 characracter). It's better to trim your text first.

Thank you for your reply! It is very helpful! I have finiished that experiment. By the way, how I can train clip model with my own dataset from scratch. It seems that this code justs fine tune clip model by using its default parameters.

<!-- gh-comment-id:881899167 --> @lr19960813 commented on GitHub (Jul 17, 2021): > @lr19960813 first, your error occured during the `image_features = self.encode_image(image)` step, so the error caused by the image. Have you make sure to use `preprocess` module to your images before feeding them to the network? you can put it inside the dataloader when fetching the images. > > second, regarding the long text, yes, Clip text only accept token length 77 (1 token represent 1-3 characracter). It's better to trim your text first. Thank you for your reply! It is very helpful! I have finiished that experiment. By the way, how I can train clip model with my own dataset from scratch. It seems that this code justs fine tune clip model by using its default parameters.
Author
Owner

@vinson2233 commented on GitHub (Jul 18, 2021):

@lr19960813 Then you need to load the model from scratch without loading the trained weight.
Here's the code, you can also set the context_length to a greater number if you have a really long text.

from clip.model import CLIP
model = CLIP(
        embed_dim,
        image_resolution, vision_layers, vision_width, vision_patch_size,
        context_length, vocab_size, transformer_width, transformer_heads, transformer_layers
    )

If you confused about how to fill the value (for example : embed_dim), you can refer to existing model by inspecting the state_dict of existing model.

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Best model use ViT-B/32
model_state_dict = model.state_dict()
embed_dim = model_state_dict['text_projection'].shape[1]

To see other params, you can refer to this code : github.com/openai/CLIP@cfcffb90e6/clip/model.py (L395-L424)

<!-- gh-comment-id:882018776 --> @vinson2233 commented on GitHub (Jul 18, 2021): @lr19960813 Then you need to load the model from scratch without loading the trained weight. Here's the code, you can also set the context_length to a greater number if you have a really long text. ```python from clip.model import CLIP model = CLIP( embed_dim, image_resolution, vision_layers, vision_width, vision_patch_size, context_length, vocab_size, transformer_width, transformer_heads, transformer_layers ) ``` If you confused about how to fill the value (for example : `embed_dim`), you can refer to existing model by inspecting the `state_dict` of existing model. ```python model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Best model use ViT-B/32 model_state_dict = model.state_dict() embed_dim = model_state_dict['text_projection'].shape[1] ``` To see other params, you can refer to this code : https://github.com/openai/CLIP/blob/cfcffb90e69f37bf2ff1e988237a0fbe41f33c04/clip/model.py#L395-L424
Author
Owner

@gunwooYong commented on GitHub (Jul 22, 2021):

Hello, this is Yong, a researcher from South Korea.

I appreciate your work and it is very helpful for me as I have tried conducting fine-tuning task.
As I studied, CLIP includes a potential risk such as overfiting during fine-tuning with the small number of data.

Thus, I wonder about how much data is necessary at least when applying fine-tuning?
In my case, I have 4 classes and each class includes at most 10 pictures.
In such scenario, can I carry out fine-tuning task? or just use the traditional CLIP?

I am looking forward to your answer and I appreciate your work again.
Thank you.

<!-- gh-comment-id:884655027 --> @gunwooYong commented on GitHub (Jul 22, 2021): Hello, this is Yong, a researcher from South Korea. I appreciate your work and it is very helpful for me as I have tried conducting fine-tuning task. As I studied, CLIP includes a potential risk such as overfiting during fine-tuning with the small number of data. Thus, I wonder about how much data is necessary at least when applying fine-tuning? In my case, I have 4 classes and each class includes at most 10 pictures. In such scenario, can I carry out fine-tuning task? or just use the traditional CLIP? I am looking forward to your answer and I appreciate your work again. Thank you.
Author
Owner

@lr19960813 commented on GitHub (Jul 22, 2021):

Dear Yong

This is Li Rui a doctor from japan.
I think you are right. I meet the same problem with you.
I try another fine tune task by using 80000+ datas and it can not converge.
I am trying small learning rate and use bigger batch size.
It preforms better than before but still not very good.
I think you can try it.

Li Rui

gunwooYong @.***> 于2021年7月22日周四 下午1:54写道:

Hello, this is Yong, a researcher from South Korea.

I appreciate your work and it is very helpful for me as I have tried
conducting fine-tuning task.
As I studied, CLIP includes a potential risk such as overfiting during
fine-tuning with the small number of data.

Thus, I wonder about how much data is necessary at least when applying
fine-tuning?
In my case, I have 4 classes and each class includes at most 10 pictures.
In such scenario, can I carry out fine-tuning task? or just use the
traditional CLIP?

I am looking forward to your answer and I appreciate your work again.
Thank you.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/openai/CLIP/issues/83#issuecomment-884655027, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AJQWBGTJXBFN6TPRPGURLWDTY6P73ANCNFSM42SGLVGA
.

<!-- gh-comment-id:884683913 --> @lr19960813 commented on GitHub (Jul 22, 2021): Dear Yong This is Li Rui a doctor from japan. I think you are right. I meet the same problem with you. I try another fine tune task by using 80000+ datas and it can not converge. I am trying small learning rate and use bigger batch size. It preforms better than before but still not very good. I think you can try it. Li Rui gunwooYong ***@***.***> 于2021年7月22日周四 下午1:54写道: > Hello, this is Yong, a researcher from South Korea. > > I appreciate your work and it is very helpful for me as I have tried > conducting fine-tuning task. > As I studied, CLIP includes a potential risk such as overfiting during > fine-tuning with the small number of data. > > Thus, I wonder about how much data is necessary at least when applying > fine-tuning? > In my case, I have 4 classes and each class includes at most 10 pictures. > In such scenario, can I carry out fine-tuning task? or just use the > traditional CLIP? > > I am looking forward to your answer and I appreciate your work again. > Thank you. > > — > You are receiving this because you were mentioned. > Reply to this email directly, view it on GitHub > <https://github.com/openai/CLIP/issues/83#issuecomment-884655027>, or > unsubscribe > <https://github.com/notifications/unsubscribe-auth/AJQWBGTJXBFN6TPRPGURLWDTY6P73ANCNFSM42SGLVGA> > . >
Author
Owner

@gunwooYong commented on GitHub (Jul 22, 2021):

Dear Rui,

I really appreciate your help.
As described in CLIP-Art(https://github.com/KeremTurgutlu/clip_art), they used 140,000 images for fine-tuning.
So, I think you may solve your problem thorough data augmentation.

However, I cannot acquire more data as it is related with a specific domain.
For this reason, I am trying to conduct fine-tuning with the tiny number of images.

I hope you to overcome this issue.

Best regard,

Dear Yong This is Li Rui a doctor from japan. I think you are right. I meet the same problem with you. I try another fine tune task by using 80000+ datas and it can not converge. I am trying small learning rate and use bigger batch size. It preforms better than before but still not very good. I think you can try it. Li Rui gunwooYong @.***> 于2021年7月22日周四 下午1:54写道:
…
Hello, this is Yong, a researcher from South Korea. I appreciate your work and it is very helpful for me as I have tried conducting fine-tuning task. As I studied, CLIP includes a potential risk such as overfiting during fine-tuning with the small number of data. Thus, I wonder about how much data is necessary at least when applying fine-tuning? In my case, I have 4 classes and each class includes at most 10 pictures. In such scenario, can I carry out fine-tuning task? or just use the traditional CLIP? I am looking forward to your answer and I appreciate your work again. Thank you. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#83 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJQWBGTJXBFN6TPRPGURLWDTY6P73ANCNFSM42SGLVGA .

<!-- gh-comment-id:884696759 --> @gunwooYong commented on GitHub (Jul 22, 2021): Dear Rui, I really appreciate your help. As described in CLIP-Art(https://github.com/KeremTurgutlu/clip_art), they used 140,000 images for fine-tuning. So, I think you may solve your problem thorough data augmentation. However, I cannot acquire more data as it is related with a specific domain. For this reason, I am trying to conduct fine-tuning with the tiny number of images. I hope you to overcome this issue. Best regard, > Dear Yong This is Li Rui a doctor from japan. I think you are right. I meet the same problem with you. I try another fine tune task by using 80000+ datas and it can not converge. I am trying small learning rate and use bigger batch size. It preforms better than before but still not very good. I think you can try it. Li Rui gunwooYong ***@***.***> 于2021年7月22日周四 下午1:54写道: > […](#) > Hello, this is Yong, a researcher from South Korea. I appreciate your work and it is very helpful for me as I have tried conducting fine-tuning task. As I studied, CLIP includes a potential risk such as overfiting during fine-tuning with the small number of data. Thus, I wonder about how much data is necessary at least when applying fine-tuning? In my case, I have 4 classes and each class includes at most 10 pictures. In such scenario, can I carry out fine-tuning task? or just use the traditional CLIP? I am looking forward to your answer and I appreciate your work again. Thank you. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <[#83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-884655027)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AJQWBGTJXBFN6TPRPGURLWDTY6P73ANCNFSM42SGLVGA> .
Author
Owner

@vinson2233 commented on GitHub (Jul 22, 2021):

@gunwooYong I might be not the person you are looking for since I'm not the author nor have any affiliation with openai. I think this question is better to discuss in new issue on github page so the real author have more chance to see the question.

But regardless, I did train CLIP as image classification model, where I have 19 categories with around 100k images, with modification where the loss only use the first logits(dim : number_image x num_class) since 1 image only have 1 category but 1 category can be owned by multiple images in the batch. The performance is still way behind a CNN Classification model.

<!-- gh-comment-id:884800860 --> @vinson2233 commented on GitHub (Jul 22, 2021): @gunwooYong I might be not the person you are looking for since I'm not the author nor have any affiliation with openai. I think this question is better to discuss in new issue on github page so the real author have more chance to see the question. But regardless, I did train CLIP as image classification model, where I have 19 categories with around 100k images, with modification where the loss only use the first logits(dim : number_image x num_class) since 1 image only have 1 category but 1 category can be owned by multiple images in the batch. The performance is still way behind a CNN Classification model.
Author
Owner

@mitchellnw commented on GitHub (Jul 29, 2021):

In case it is helpful, posting a link to our implementation of CLIP-training code https://github.com/mlfoundations/open_clip

<!-- gh-comment-id:889375600 --> @mitchellnw commented on GitHub (Jul 29, 2021): In case it is helpful, posting a link to our implementation of CLIP-training code https://github.com/mlfoundations/open_clip
Author
Owner

@vinson2233 commented on GitHub (Jul 30, 2021):

@mitchellnw Nice, thanks for sharing, I'll put it on https://github.com/openai/CLIP/issues/83#issue-853114174 so it is easier for people to reach your work.

<!-- gh-comment-id:889670365 --> @vinson2233 commented on GitHub (Jul 30, 2021): @mitchellnw Nice, thanks for sharing, I'll put it on https://github.com/openai/CLIP/issues/83#issue-853114174 so it is easier for people to reach your work.
Author
Owner

@sarahESL commented on GitHub (Aug 10, 2021):

Thank for providing this @vinson2233 . I was wondering how come the loss does not include the cosine similarity of the encoded image and text? Following the "Figure 3" from the original clip paper. Or it is included and I am missing something?! 🤔

<!-- gh-comment-id:895805622 --> @sarahESL commented on GitHub (Aug 10, 2021): Thank for providing this @vinson2233 . I was wondering how come the loss does not include the cosine similarity of the encoded image and text? Following the "Figure 3" from the original clip paper. Or it is included and I am missing something?! :thinking:
Author
Owner

@vinson2233 commented on GitHub (Aug 10, 2021):

@sarahESL, Actually, the code already include that, but it is not explicit enough on showing that.

logits_per_image, logits_per_text = model(images, texts)

This line of code is producing the cosine similarity of the encoded image and text, not the embedding. I'm using the terms 'logits' just to follow the paper and keep it consistent with the example shown in the readme (Actually I didn't like the word logits).

So if we have 10 text and 5 images. logits_per_image dimension is 5 x 10, and the logits_per_text is 10 x 5. Where each entries is cosine similarity times the temperature parameter (you can divide it by 100 or the temperature value itself to get the usual cosine similarity tough).

<!-- gh-comment-id:895885822 --> @vinson2233 commented on GitHub (Aug 10, 2021): @sarahESL, Actually, the code already include that, but it is not explicit enough on showing that. ```python logits_per_image, logits_per_text = model(images, texts) ``` This line of code is producing the cosine similarity of the encoded image and text, not the embedding. I'm using the terms 'logits' just to follow the paper and keep it consistent with the example shown in the readme (Actually I didn't like the word logits). So if we have 10 text and 5 images. `logits_per_image` dimension is 5 x 10, and the `logits_per_text` is 10 x 5. Where each entries is cosine similarity times the temperature parameter (you can divide it by 100 or the temperature value itself to get the usual cosine similarity tough).
Author
Owner

@DRSY commented on GitHub (Aug 12, 2021):

Hi, just wanna share my work on deploying CLIP on iOS for cross-modal text-to-image retrieval/search: https://github.com/DRSY/MTIS. I exported the CLIP image encoder and text encoder as TorchScript format, which can then be loaded via torch's c++ libtorch frontend.

<!-- gh-comment-id:897686995 --> @DRSY commented on GitHub (Aug 12, 2021): Hi, just wanna share my work on deploying CLIP on iOS for cross-modal text-to-image retrieval/search: https://github.com/DRSY/MTIS. I exported the CLIP image encoder and text encoder as TorchScript format, which can then be loaded via torch's c++ libtorch frontend.
Author
Owner

@NingYuanxiang commented on GitHub (Aug 16, 2021):

Hi, I want to revise the structure of clip's model. how to load some special layer and keep it constant in train on new dataset.If you reply me earlier, I will be greatly thankful for you.

<!-- gh-comment-id:899372227 --> @NingYuanxiang commented on GitHub (Aug 16, 2021): Hi, I want to revise the structure of clip's model. how to load some special layer and keep it constant in train on new dataset.If you reply me earlier, I will be greatly thankful for you.
Author
Owner

@vinson2233 commented on GitHub (Aug 16, 2021):

I'm not sure what you mean by revise. But have you seen this link? https://discuss.pytorch.org/t/how-to-replace-a-layer-or-module-in-a-pretrained-network/60068
So basically you just access specific part of CLIP, and replace it.

To make it constant, I'm assuming what you mean is not update that specific layer during training. Maybe this forum will match your interest https://discuss.pytorch.org/t/how-the-pytorch-freeze-network-in-some-layers-only-the-rest-of-the-training/7088. So basically just set require grad = False if the layers name match with your custom layer

<!-- gh-comment-id:899376149 --> @vinson2233 commented on GitHub (Aug 16, 2021): I'm not sure what you mean by revise. But have you seen this link? https://discuss.pytorch.org/t/how-to-replace-a-layer-or-module-in-a-pretrained-network/60068 So basically you just access specific part of CLIP, and replace it. To make it constant, I'm assuming what you mean is not update that specific layer during training. Maybe this forum will match your interest https://discuss.pytorch.org/t/how-the-pytorch-freeze-network-in-some-layers-only-the-rest-of-the-training/7088. So basically just set require grad = False if the layers name match with your custom layer
Author
Owner

@NingYuanxiang commented on GitHub (Aug 16, 2021):

I'm not sure what you mean by revise. But have you seen this link? https://discuss.pytorch.org/t/how-to-replace-a-layer-or-module-in-a-pretrained-network/60068
So basically you just access specific part of CLIP, and replace it.

To make it constant, I'm assuming what you mean is not update that specific layer during training. Maybe this forum will match your interest https://discuss.pytorch.org/t/how-the-pytorch-freeze-network-in-some-layers-only-the-rest-of-the-training/7088. So basically just set require grad = False if the layers name match with your custom layer

Thank for providing this. I have some confuse, how to verify the revised net have improvement. Which training set is best to train and verify.

<!-- gh-comment-id:899383596 --> @NingYuanxiang commented on GitHub (Aug 16, 2021): > I'm not sure what you mean by revise. But have you seen this link? https://discuss.pytorch.org/t/how-to-replace-a-layer-or-module-in-a-pretrained-network/60068 > So basically you just access specific part of CLIP, and replace it. > > To make it constant, I'm assuming what you mean is not update that specific layer during training. Maybe this forum will match your interest https://discuss.pytorch.org/t/how-the-pytorch-freeze-network-in-some-layers-only-the-rest-of-the-training/7088. So basically just set require grad = False if the layers name match with your custom layer Thank for providing this. I have some confuse, how to verify the revised net have improvement. Which training set is best to train and verify.
Author
Owner

@vinson2233 commented on GitHub (Aug 18, 2021):

@NingYuanxiang If I in your position, I will create new image-title dataset, which have not been trained by the CLIP itself (So don't use COCO). This dataset should be totally new and never seen by the CLIP before.
After you have such dataset, try to finetune the original CLIP for the new dataset. Also finetune the revised CLIP for the new dataset, and then compare the performance.
Of course this approach is only based on empirical result, which mean you need to do extensive experiment for validating your modification of CLIP.

<!-- gh-comment-id:900794669 --> @vinson2233 commented on GitHub (Aug 18, 2021): @NingYuanxiang If I in your position, I will create new image-title dataset, which have not been trained by the CLIP itself (So don't use COCO). This dataset should be totally new and never seen by the CLIP before. After you have such dataset, try to finetune the original CLIP for the new dataset. Also finetune the revised CLIP for the new dataset, and then compare the performance. Of course this approach is only based on empirical result, which mean you need to do extensive experiment for validating your modification of CLIP.
Author
Owner

@4sunshine commented on GitHub (Aug 18, 2021):

@NingYuanxiang If I in your position, I will create new image-title dataset, which have not been trained by the CLIP itself (So don't use COCO). This dataset should be totally new and never seen by the CLIP before.
After you have such dataset, try to finetune the original CLIP for the new dataset. Also finetune the revised CLIP for the new dataset, and then compare the performance.
Of course this approach is only based on empirical result, which mean you need to do extensive experiment for validating your modification of CLIP.

Dear @vinson2233 am I correct that as least train split of MS-COCO (COCO Captions) was used during training of provided checkpoints in this repo?

<!-- gh-comment-id:900968317 --> @4sunshine commented on GitHub (Aug 18, 2021): > @NingYuanxiang If I in your position, I will create new image-title dataset, which have not been trained by the CLIP itself (So don't use COCO). This dataset should be totally new and never seen by the CLIP before. > After you have such dataset, try to finetune the original CLIP for the new dataset. Also finetune the revised CLIP for the new dataset, and then compare the performance. > Of course this approach is only based on empirical result, which mean you need to do extensive experiment for validating your modification of CLIP. Dear @vinson2233 am I correct that as least train split of MS-COCO (COCO Captions) was used during training of provided checkpoints in this repo?
Author
Owner

@vinson2233 commented on GitHub (Aug 18, 2021):

@4sunshine When reading the paper, I'm assume they use every dataset that mentioned in paper in the checkpoint model in this repo. For example MS-COCO (Lin et al., 2014), Visual Genome (Krishna et al., 2017), YFCC100M (Thomee et al., 2016).
I don't know if the COCO part they are using is only the train part, or maybe they just doing evaluation on COCO. We need to clarify it with the author (And again, I'm not the author).

<!-- gh-comment-id:900974451 --> @vinson2233 commented on GitHub (Aug 18, 2021): @4sunshine When reading the paper, I'm assume they use every dataset that mentioned in paper in the checkpoint model in this repo. For example MS-COCO (Lin et al., 2014), Visual Genome (Krishna et al., 2017), YFCC100M (Thomee et al., 2016). I don't know if the COCO part they are using is only the train part, or maybe they just doing evaluation on COCO. We need to clarify it with the author (And again, I'm not the author).
Author
Owner

@4sunshine commented on GitHub (Aug 18, 2021):

@4sunshine When reading the paper, I'm assume they use every dataset that mentioned in paper in the checkpoint model in this repo. For example MS-COCO (Lin et al., 2014), Visual Genome (Krishna et al., 2017), YFCC100M (Thomee et al., 2016).
I don't know if the COCO part they are using is only the train part, or maybe they just doing evaluation on COCO. We need to clarify it with the author (And again, I'm not the author).

Thank you @vinson2233 for quick reply. I want to know the answer because of evaluation setup used in paper https://arxiv.org/abs/2012.04329. This paper is about Scene-Text aware Text-to-Image retrieval and its test samples partly belong to MS-COCO train.

<!-- gh-comment-id:900991344 --> @4sunshine commented on GitHub (Aug 18, 2021): > @4sunshine When reading the paper, I'm assume they use every dataset that mentioned in paper in the checkpoint model in this repo. For example MS-COCO (Lin et al., 2014), Visual Genome (Krishna et al., 2017), YFCC100M (Thomee et al., 2016). > I don't know if the COCO part they are using is only the train part, or maybe they just doing evaluation on COCO. We need to clarify it with the author (And again, I'm not the author). Thank you @vinson2233 for quick reply. I want to know the answer because of evaluation setup used in paper https://arxiv.org/abs/2012.04329. This paper is about Scene-Text aware Text-to-Image retrieval and its test samples partly belong to MS-COCO train.
Author
Owner

@minmummax commented on GitHub (Aug 25, 2021):

is this demo code used for finetune on small dataset?

<!-- gh-comment-id:905333921 --> @minmummax commented on GitHub (Aug 25, 2021): is this demo code used for finetune on small dataset?
Author
Owner

@liuhui0401 commented on GitHub (Aug 31, 2021):

I want to know what is the general loss of your code during training? My loss will drop from greater than 2 to greater than 1. Is this normal?

<!-- gh-comment-id:909006312 --> @liuhui0401 commented on GitHub (Aug 31, 2021): I want to know what is the general loss of your code during training? My loss will drop from greater than 2 to greater than 1. Is this normal?
Author
Owner

@vinson2233 commented on GitHub (Aug 31, 2021):

@minmummax this is the base code I'm using for private dataset which consist more than 1 million image text pairs. The actual code I'm using involves multi-GPU training

<!-- gh-comment-id:909015136 --> @vinson2233 commented on GitHub (Aug 31, 2021): @minmummax this is the base code I'm using for private dataset which consist more than 1 million image text pairs. The actual code I'm using involves [multi-GPU training ](https://github.com/openai/CLIP/issues/111#issuecomment-854320770)
Author
Owner

@vinson2233 commented on GitHub (Aug 31, 2021):

@liuhui0401 for my case, it starts with 3, but falls quickly to 1.5, and after 8000 steps (not epoch) the loss oscilating around 0.5

<!-- gh-comment-id:909017708 --> @vinson2233 commented on GitHub (Aug 31, 2021): @liuhui0401 for my case, it starts with 3, but falls quickly to 1.5, and after 8000 steps (not epoch) the loss oscilating around 0.5
Author
Owner

@lr19960813 commented on GitHub (Sep 7, 2021):

Hi,vinson, thank you for your code.
Do you try using a learning rate decay? I think it will get a better result.

<!-- gh-comment-id:914032116 --> @lr19960813 commented on GitHub (Sep 7, 2021): Hi,vinson, thank you for your code. Do you try using a learning rate decay? I think it will get a better result.
Author
Owner

@vinson2233 commented on GitHub (Sep 7, 2021):

@lr19960813 no, I haven't try it yet. The learning rate decay they use is this right ? https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CosineAnnealingWarmRestarts.html?highlight=cosine#torch.optim.lr_scheduler.CosineAnnealingWarmRestarts

Maybe I'll dive deeper on this.

<!-- gh-comment-id:914043457 --> @vinson2233 commented on GitHub (Sep 7, 2021): @lr19960813 no, I haven't try it yet. The learning rate decay they use is this right ? https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CosineAnnealingWarmRestarts.html?highlight=cosine#torch.optim.lr_scheduler.CosineAnnealingWarmRestarts Maybe I'll dive deeper on this.
Author
Owner

@lr19960813 commented on GitHub (Sep 7, 2021):

@vinson2233
Yes, that's one type lr scheduler. In my experiment, I use roam scheduler to get a better result in a small test experiment. I will do more experiment to research the performence.

<!-- gh-comment-id:914542950 --> @lr19960813 commented on GitHub (Sep 7, 2021): @vinson2233 Yes, that's one type lr scheduler. In my experiment, I use roam scheduler to get a better result in a small test experiment. I will do more experiment to research the performence.
Author
Owner

@sarahESL commented on GitHub (Sep 12, 2021):

regarding the long text, yes, Clip text only accept token length 77 (1 token represent 1-3 characracter). It's better to trim your text first.

Isn't it possible to use shorter sequence lengths by adjusting the context_length in tokenize? I tried it, but still in encoding the text, it gives RuntimeError: The size of tensor a (_X_) must match the size of tensor b (77) at non-singleton dimension 1!

<!-- gh-comment-id:917574766 --> @sarahESL commented on GitHub (Sep 12, 2021): > regarding the long text, yes, Clip text only accept token length 77 (1 token represent 1-3 characracter). It's better to trim your text first. Isn't it possible to use shorter sequence lengths by adjusting the `context_length` in `tokenize`? I tried it, but still in encoding the text, it gives `RuntimeError: The size of tensor a (_X_) must match the size of tensor b (77) at non-singleton dimension 1`!
Author
Owner

@lr19960813 commented on GitHub (Sep 12, 2021):

Yes,so I think you should trim your text shorter than 77tokens.

Sedigheh (Sarah) Eslami @.***> 于2021年9月12日周日 下午4:23写道:

regarding the long text, yes, Clip text only accept token length 77 (1
token represent 1-3 characracter). It's better to trim your text first.

Isn't it possible to use shorter sequence lengths by adjusting the
context_length in tokenize? I tried it, but still in encoding the text,
it gives RuntimeError: The size of tensor a (X) must match the size of
tensor b (77) at non-singleton dimension 1!

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/openai/CLIP/issues/83#issuecomment-917574766, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AJQWBGXQCJM3FWI6GHYRHZTUBRIOBANCNFSM42SGLVGA
.
Triage notifications on the go with GitHub Mobile for iOS
https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675
or Android
https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

<!-- gh-comment-id:917715648 --> @lr19960813 commented on GitHub (Sep 12, 2021): Yes,so I think you should trim your text shorter than 77tokens. Sedigheh (Sarah) Eslami ***@***.***> 于2021年9月12日周日 下午4:23写道: > regarding the long text, yes, Clip text only accept token length 77 (1 > token represent 1-3 characracter). It's better to trim your text first. > > Isn't it possible to use shorter sequence lengths by adjusting the > context_length in tokenize? I tried it, but still in encoding the text, > it gives RuntimeError: The size of tensor a (_X_) must match the size of > tensor b (77) at non-singleton dimension 1! > > — > You are receiving this because you were mentioned. > Reply to this email directly, view it on GitHub > <https://github.com/openai/CLIP/issues/83#issuecomment-917574766>, or > unsubscribe > <https://github.com/notifications/unsubscribe-auth/AJQWBGXQCJM3FWI6GHYRHZTUBRIOBANCNFSM42SGLVGA> > . > Triage notifications on the go with GitHub Mobile for iOS > <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> > or Android > <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>. > >
Author
Owner

@vinson2233 commented on GitHub (Sep 14, 2021):

@sarahESL yes you can, but you cannot use pre-trained CLIP if you want to use context_length different than 77. You might need to define CLIP by using this function over here github.com/openai/CLIP@3b473b0e68/clip/model.py (L239-L240)
with fresh weight.

After that, you can use tokenize with context_length longer than 77 and expect CLIP model to able to accept it

<!-- gh-comment-id:918766111 --> @vinson2233 commented on GitHub (Sep 14, 2021): @sarahESL yes you can, but you cannot use pre-trained CLIP if you want to use context_length different than 77. You might need to define CLIP by using this function over here https://github.com/openai/CLIP/blob/3b473b0e682c091a9e53623eebc1ca1657385717/clip/model.py#L239-L240 with fresh weight. After that, you can use tokenize with context_length longer than 77 and expect CLIP model to able to accept it
Author
Owner

@jongwook commented on GitHub (Sep 16, 2021):

@HiGal The two losses are different because the softmax operations are done over different axes.

<!-- gh-comment-id:921220067 --> @jongwook commented on GitHub (Sep 16, 2021): @HiGal The two losses are different because the softmax operations are done over different axes.
Author
Owner

@nbl97 commented on GitHub (Sep 30, 2021):

@vinson2233 Thanks for your multi-GPU code. However, I don't understand why the similarity matrix is 100x10 in your example if we don't separate the CLIP model. Could you pls explain more? If I want to use DDP, is it necessary to separate the model? Thanks a lot!

<!-- gh-comment-id:931490995 --> @nbl97 commented on GitHub (Sep 30, 2021): @vinson2233 Thanks for your multi-GPU code. However, I don't understand why the similarity matrix is 100x10 in your example if we don't separate the CLIP model. Could you pls explain more? If I want to use DDP, is it necessary to separate the model? Thanks a lot!
Author
Owner

@nbl97 commented on GitHub (Sep 30, 2021):

@vinson2233 Some supplement for the above question: I read the official code and found the the forward() function produces the cosine similarity, not the embedding. If I modify the forward() to produce the image and text embedding and calculate the similarity outside the forward(), is it still necessary to separate the CLIP model when multi-GPUs are to be used.

<!-- gh-comment-id:931502088 --> @nbl97 commented on GitHub (Sep 30, 2021): @vinson2233 Some supplement for the above question: I read the official code and found the the forward() function produces the cosine similarity, not the embedding. If I modify the forward() to produce the image and text embedding and calculate the similarity outside the forward(), is it still necessary to separate the CLIP model when multi-GPUs are to be used.
Author
Owner

@vinson2233 commented on GitHub (Oct 1, 2021):

@nbl97 Let's understand what DataParallel do. Suppose we have 10 records to inference and we have 2 GPU. Then what data parallel will do is it will create 5 duplicate of model in each GPU, then spread the 10 records to each device. Maybe it will go to something like this :
GPU0 : record 0,1,2,3,4
GPU1 : record 5,6,7,8,9
After that on each device, the model will do inference and then concat all the output.

But for CLIP, this become a bit problematic. On a single model, if we give 10 pairs of text-images, the forward function will produce 10x10 similarity matrix.
But if you work on 2 GPU, then the first GPU will receive first 5 pairs and the second GPU will receive the last 5 pairs.
What happen in first GPU? It will calculate the cosine similarity between 5 pairs, and so does the second GPU.
The result would be 5x5 cosine similarity matrix on each GPU.
The last step is gathering the prediction from each GPU and we will end with 10x5 similarity matrix in this case.

Regarding DDP, i never use it so I cannot give answer on that 🙏

Regarding the modification, yes it should be possible theoretically. I have tried it in the past, but the parallelization only occur with forward method. Any other function will not get hooked with parallelization. That's why I come with the idea of splitting the model based on their responsibility.

<!-- gh-comment-id:931961414 --> @vinson2233 commented on GitHub (Oct 1, 2021): @nbl97 Let's understand what DataParallel do. Suppose we have 10 records to inference and we have 2 GPU. Then what data parallel will do is it will create 5 duplicate of model in each GPU, then spread the 10 records to each device. Maybe it will go to something like this : GPU0 : record 0,1,2,3,4 GPU1 : record 5,6,7,8,9 After that on each device, the model will do inference and then concat all the output. But for CLIP, this become a bit problematic. On a single model, if we give 10 pairs of text-images, the forward function will produce 10x10 similarity matrix. But if you work on 2 GPU, then the first GPU will receive first 5 pairs and the second GPU will receive the last 5 pairs. What happen in first GPU? It will calculate the cosine similarity between 5 pairs, and so does the second GPU. The result would be 5x5 cosine similarity matrix on each GPU. The last step is gathering the prediction from each GPU and we will end with 10x5 similarity matrix in this case. Regarding DDP, i never use it so I cannot give answer on that 🙏 Regarding the modification, yes it should be possible theoretically. I have tried it in the past, but the parallelization only occur with `forward` method. Any other function will not get hooked with parallelization. That's why I come with the idea of splitting the model based on their responsibility.
Author
Owner

@xyxxmb commented on GitHub (Nov 2, 2021):

Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models?

everything goes worse when I fine-tune the CLIP

From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO 5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN).

How did you get the image retrieval result in mscoco?Could you can share your test coding?

<!-- gh-comment-id:957359807 --> @xyxxmb commented on GitHub (Nov 2, 2021): > > > Have anyone tried fine-tune CLIP on MS COCO image-text retrieval task? How is the performance compared with other state-of-the-art models? > > > > > > everything goes worse when I fine-tune the CLIP > > From my experiment, the zero-shot image retrieval performance is R@1 25.4, R@5 48.7 and R@10 59.9 on the MS COCO 5k test set. After fine-tuning, it slightly improves to R@1 33.6, R@5 62.2 and R@10 73.8. Still lags behind SOTA non-transformer-based models(e.g., VSRN). How did you get the image retrieval result in mscoco?Could you can share your test coding?
Author
Owner

@milmin commented on GitHub (Nov 19, 2021):

Hi @vinson2233 thanks a lot for sharing your code! If I understand well you never set the model in training phase model.train(). Do you do that on purpose to freeze dropout and batchnorm layers during fine-tuning? And second questions, do you have any ideas about good metrics to keep track of during evaluation to understand if fine-tuning is running fine (validation loss apart)?

<!-- gh-comment-id:973924757 --> @milmin commented on GitHub (Nov 19, 2021): Hi @vinson2233 thanks a lot for sharing your code! If I understand well you never set the model in training phase `model.train()`. Do you do that on purpose to freeze dropout and batchnorm layers during fine-tuning? And second questions, do you have any ideas about good metrics to keep track of during evaluation to understand if fine-tuning is running fine (validation loss apart)?
Author
Owner

@Wuziyi616 commented on GitHub (Dec 5, 2021):

Hi @vinson2233 thank you so much for sharing the code. I'm just wondering what batch_size are you using to fine-tune CLIP? I'm using DDP training with 4 GPUS, and the batch_size is 128 on each GPU. However the loss isn't decreasing as expected... So I just wonder if that's because my batch_size if too small (so the fine-tuning is unstable) or there are bugs in my DDP code. Thanks in advance!

<!-- gh-comment-id:986170057 --> @Wuziyi616 commented on GitHub (Dec 5, 2021): Hi @vinson2233 thank you so much for sharing the code. I'm just wondering what batch_size are you using to fine-tune CLIP? I'm using DDP training with 4 GPUS, and the batch_size is 128 on each GPU. However the loss isn't decreasing as expected... So I just wonder if that's because my batch_size if too small (so the fine-tuning is unstable) or there are bugs in my DDP code. Thanks in advance!
Author
Owner

@akamil-etsy commented on GitHub (Dec 13, 2021):

is it possible to fine-tune pre-trained CLIP model using a loss function different from the original (infoNCE)?

I found an example on Kaggle when CLIP is trained from scratch with triplet loss with pair-wise comparisons (vs. class labels), and I'm wondering if this approach would work for fine-tuning the original pre-trained model from OpenAI.

I.e. freeze lower layers of the model pre-trained with infoNCE and train only a few higher layers with triplet loss on custom data (triplets of images and/or captions) or circle loss instead of the original contrastive loss/infoNCE.

<!-- gh-comment-id:992272195 --> @akamil-etsy commented on GitHub (Dec 13, 2021): is it possible to fine-tune pre-trained CLIP model using a loss function different from the original ([infoNCE](https://paperswithcode.com/method/infonce))? I found an [example](https://www.kaggle.com/bguberfain/openai-clip-with-train) on Kaggle when CLIP is trained from scratch with [triplet loss](https://en.wikipedia.org/wiki/Triplet_loss) with pair-wise comparisons (vs. class labels), and I'm wondering if this approach would work for fine-tuning the original pre-trained model from OpenAI. I.e. freeze lower layers of the model pre-trained with infoNCE and train only a few higher layers with triplet loss on custom data (triplets of images and/or captions) or [circle loss](https://medium.com/vitrox-publication/understanding-circle-loss-bdaa576312f7#:~:text=In%20Contrastive%20loss%2C%20you%20would,image%20away%20from%20the%20anchor.) instead of the original contrastive loss/infoNCE.
Author
Owner

@xyxxmb commented on GitHub (Dec 22, 2021):

@uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do :

  1. Change the ground_truth = torch.arange(BATCH_SIZE).to(device) to integer vector that specify which class your image are on (for example torch.tensor([0,1,2,1,2,3,4,5])). With this now you can set your batch size in arbitrary size.
  2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 to total_loss = loss_img(logits_per_image,ground_truth)

I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image"

I don't think that the classifier idea (1) is correct. Assuming having three categories and five images, and the ground_truth = [0,0,1,2,1]. The logits_per_image would be a matrix A with shape (5,5),which A(i, j) denotes the similarity of image i and category j. When calculating the F.cross_entropy(logits_per_image, [0,0,1,2,1]), the nll_loss of 3th, 4th and 5th is not correct.

<!-- gh-comment-id:999352610 --> @xyxxmb commented on GitHub (Dec 22, 2021): > @uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do : > > 1. Change the ` ground_truth = torch.arange(BATCH_SIZE).to(device)` to integer vector that specify which class your image are on (for example `torch.tensor([0,1,2,1,2,3,4,5])`). With this now you can set your batch size in arbitrary size. > 2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the ` total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2` to `total_loss = loss_img(logits_per_image,ground_truth) ` > > I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image" I don't think that the classifier idea (1) is correct. Assuming having three categories and five images, and the ground_truth = [0,0,1,2,1]. The logits_per_image would be a matrix A with shape (5,5),which A(i, j) denotes the similarity of image i and category j. When calculating the F.cross_entropy(logits_per_image, [0,0,1,2,1]), the nll_loss of 3th, 4th and 5th is not correct.
Author
Owner

@BrianG13 commented on GitHub (Jan 24, 2022):

@xyxxmb
So, what is the best to do when I have in the same batch images with same category?
For example, batch_size=5, labels/text-features are = [0,0,1,2,1]
ground_truth = torch.arange(BATCH_SIZE).to(device)
Is not the best solution also, because for image entries idx 0&1, I want them to be consistent with themselves (diagonal) and with the images of same class

<!-- gh-comment-id:1020157727 --> @BrianG13 commented on GitHub (Jan 24, 2022): @xyxxmb So, what is the best to do when I have in the same batch images with same category? For example, batch_size=5, labels/text-features are = [0,0,1,2,1] `ground_truth = torch.arange(BATCH_SIZE).to(device)` Is not the best solution also, because for image entries idx 0&1, I want them to be consistent with themselves (diagonal) and with the images of same class
Author
Owner

@Unmesh28 commented on GitHub (Feb 19, 2022):

I want to use CLIP for text to art using VQGAN.
Planning to provide custom dataset to it [dataset : different painting styles of different artists ]
If we send a prompt + style = "A girl playing on the beach" + "Thomas Kinkade" , then it should return art of the prompt in style of Thomas Kinkade.
How do I train such a model on the top of existing one ?

<!-- gh-comment-id:1045660018 --> @Unmesh28 commented on GitHub (Feb 19, 2022): I want to use CLIP for text to art using VQGAN. Planning to provide custom dataset to it [dataset : different painting styles of different artists ] If we send a prompt + style = "A girl playing on the beach" + "Thomas Kinkade" , then it should return art of the prompt in style of Thomas Kinkade. How do I train such a model on the top of existing one ?
Author
Owner

@dongyun-kim-arch commented on GitHub (Feb 20, 2022):

Thank you for sharing your training code!
I am wondering how can I do fine-tuning with frozen all layers except for the top layer like linear probe?

<!-- gh-comment-id:1046344723 --> @dongyun-kim-arch commented on GitHub (Feb 20, 2022): Thank you for sharing your training code! I am wondering how can I do fine-tuning with frozen all layers except for the top layer like linear probe?
Author
Owner

@Zasder3 commented on GitHub (Apr 7, 2022):

As a late addendum to this, open_clip recently has some large success in replicating OpenAI's ViT-B/32 model achieving near-identical accuracy on the public LAION-400M dataset.

image

<!-- gh-comment-id:1092278873 --> @Zasder3 commented on GitHub (Apr 7, 2022): As a late addendum to this, [open_clip](https://github.com/mlfoundations/open_clip) recently has some large success in replicating OpenAI's ViT-B/32 model achieving near-identical accuracy on the public LAION-400M dataset. ![image](https://user-images.githubusercontent.com/5066934/162332237-72cae091-47de-4829-8d22-b171441012b1.png)
Author
Owner

@Weifeng-Chen commented on GitHub (Apr 7, 2022):

【自动恢复】来信已收到,我将尽快回复你!

<!-- gh-comment-id:1092279026 --> @Weifeng-Chen commented on GitHub (Apr 7, 2022): 【自动恢复】来信已收到,我将尽快回复你!
Author
Owner

@AhmedEwis commented on GitHub (Apr 18, 2022):

Hello my friend
ValueError: Expected input batch_size (111) to match target batch_size (32)
any idea why I am getting this error?
def convert_models_to_fp32(model):
for p in model.parameters():
p.data = p.data.float()
p.grad.data = p.grad.data.float()

device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training.
model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
if device == "cpu":
model.float()
else :
clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16

loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset

for epoch in range(EPOCH):
for batch in train_dataloader :
optimizer.zero_grad()

  list_image,list_txt = np_list, txt_list #list_images is list of image in numpy array(np.uint8), or list of PIL images

  images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0).to(device) # omit the Image.fromarray if the images already in PIL format, change this line to images=list_image if using preprocess inside the dataset class
  texts = clip.tokenize(list_txt).to(device)

  logits_per_image, logits_per_text = model(images, texts)

  ground_truth = torch.arange(BATCH_SIZE,dtype=torch.long,device=device)

  total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2
  total_loss.backward()
  if device == "cpu":
     optimizer.step()
  else : 
    convert_models_to_fp32(model)
    optimizer.step()
    clip.model.convert_weights(model)

Knowing the following:
np_list.shape --> (111, 512, 512, 3)
len(txt_list) --> 111

<!-- gh-comment-id:1101733843 --> @AhmedEwis commented on GitHub (Apr 18, 2022): Hello my friend ValueError: Expected input batch_size (111) to match target batch_size (32) any idea why I am getting this error? def convert_models_to_fp32(model): for p in model.parameters(): p.data = p.data.float() p.grad.data = p.grad.data.float() device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training. model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training if device == "cpu": model.float() else : clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16 loss_img = nn.CrossEntropyLoss() loss_txt = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset for epoch in range(EPOCH): for batch in train_dataloader : optimizer.zero_grad() list_image,list_txt = np_list, txt_list #list_images is list of image in numpy array(np.uint8), or list of PIL images images= torch.stack([preprocess(Image.fromarray(img)) for img in list_image],dim=0).to(device) # omit the Image.fromarray if the images already in PIL format, change this line to images=list_image if using preprocess inside the dataset class texts = clip.tokenize(list_txt).to(device) logits_per_image, logits_per_text = model(images, texts) ground_truth = torch.arange(BATCH_SIZE,dtype=torch.long,device=device) total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 total_loss.backward() if device == "cpu": optimizer.step() else : convert_models_to_fp32(model) optimizer.step() clip.model.convert_weights(model) Knowing the following: np_list.shape --> (111, 512, 512, 3) len(txt_list) --> 111
Author
Owner

@BelhalK commented on GitHub (Apr 25, 2022):

clip.load("ViT-B/32",device=device,jit=False)

Good morning,

Is this chunk of code used for fine-tuning or training?
If it's for fine-tuning, I guess you start from a pretrained ViT.
Hence, where do you introduce the new parameters to be learnt on your private dataset?
I don't understand what parameters are updated using your training script, could you help me figure it out?

Maybe clip.load("ViT-B/32",device=device,jit=False) loads pretrained model weights and add under the hood some new parameters to fine-tune?`

Thank you

<!-- gh-comment-id:1108904024 --> @BelhalK commented on GitHub (Apr 25, 2022): > ```python > clip.load("ViT-B/32",device=device,jit=False) > ``` Good morning, Is this chunk of code used for fine-tuning or training? If it's for fine-tuning, I guess you start from a pretrained ViT. Hence, where do you introduce the new parameters to be learnt on your private dataset? I don't understand what parameters are updated using your training script, could you help me figure it out? Maybe `clip.load("ViT-B/32",device=device,jit=False)` loads pretrained model weights and add under the hood some new parameters to fine-tune?` Thank you
Author
Owner

@vinson2233 commented on GitHub (Apr 26, 2022):

@BelhalK No, I don't introduce new parameters to make it learn from the new dataset. I use the original architecture, and I don't freeze the weight at all. So all the weight inside the clip (both the image and text ViT) will be adjusted to the image and text from my dataset.

<!-- gh-comment-id:1109205040 --> @vinson2233 commented on GitHub (Apr 26, 2022): @BelhalK No, I don't introduce new parameters to make it learn from the new dataset. I use the original architecture, and I don't freeze the weight at all. So all the weight inside the clip (both the image and text ViT) will be adjusted to the image and text from my dataset.
Author
Owner

@BelhalK commented on GitHub (Apr 29, 2022):

@BelhalK No, I don't introduce new parameters to make it learn from the new dataset. I use the original architecture, and I don't freeze the weight at all. So all the weight inside the clip (both the image and text ViT) will be adjusted to the image and text from my dataset.

Thanks for the reply!
So I guess both the text and image models have the same learnt weights since you seem to train a unique model, do you confirm? Thank you

<!-- gh-comment-id:1113686436 --> @BelhalK commented on GitHub (Apr 29, 2022): > @BelhalK No, I don't introduce new parameters to make it learn from the new dataset. I use the original architecture, and I don't freeze the weight at all. So all the weight inside the clip (both the image and text ViT) will be adjusted to the image and text from my dataset. Thanks for the reply! So I guess both the text and image models have the same learnt weights since you seem to train a unique model, do you confirm? Thank you
Author
Owner

@ElifCerenGokYildirim commented on GitHub (May 2, 2022):

Hi,
I am using exactly the same code to train CIFAR10 dataset. I have defined transform=preprocess while loading the dataset. I defined images=list_image and texts = clip.tokenize(list_txt).to(device). However, when I run the code I get this error: TypeError: len() of a 0-d tensor. My list_txt is equal to this = tensor([6, 9, 9, 4, 1, 1, 2, 7, 8, 3, 4, 7, 7, 2, 9, 9, 9, 3, 2, 6, 4, 3, 6, 6,
2, 6, 3, 5, 4, 0, 0, 9]). So I did not understand what is the problem. Thanks in advance :)

<!-- gh-comment-id:1114763890 --> @ElifCerenGokYildirim commented on GitHub (May 2, 2022): Hi, I am using exactly the same code to train CIFAR10 dataset. I have defined transform=preprocess while loading the dataset. I defined images=list_image and texts = clip.tokenize(list_txt).to(device). However, when I run the code I get this error: TypeError: len() of a 0-d tensor. My list_txt is equal to this = tensor([6, 9, 9, 4, 1, 1, 2, 7, 8, 3, 4, 7, 7, 2, 9, 9, 9, 3, 2, 6, 4, 3, 6, 6, 2, 6, 3, 5, 4, 0, 0, 9]). So I did not understand what is the problem. Thanks in advance :)
Author
Owner

@AhmedEwis commented on GitHub (May 8, 2022):

Hello all
I have been using the above code and I have already got my weight and biases model.pt for my custom dataset.
I am trying now to implement my custom model to the following repo:
https://github.com/rmokady/CLIP_prefix_caption
but I am getting the below error:
RuntimeError: Error(s) in loading state_dict for CLIP:
Missing key(s) in state_dict: "positional_embedding", "text_projection", "logit_scale", "visual.class_embedding", "visual.positional_embedding", "visual.proj", "visual.conv1.weight", "visual.ln_pre.weight", "visual.ln_pre.bias", "visual.transformer.resblocks.0.attn.in_proj_weight", "visual.transformer.resblocks.0.attn.in_proj_bias", "visual.transformer.resblocks.0.attn.out_proj.weight", "visual.transformer.resblocks.0.attn.out_proj.bias", "visual.transformer.resblocks.0.ln_1.weight", "visual.transformer.resblocks.0.ln_1.bias", "visual.transformer.resblocks.0.mlp.c_fc.weight", "visual.transformer.resblocks.0.mlp.c_fc.bias", "visual.transformer.resblocks.0.mlp.c_proj.weight", "visual.transformer.resblocks.0.mlp.c_proj.bias", "visual.transformer.resblocks.0.ln_2.weight", "visual.transformer.resblocks.0.ln_2.bias", "visual.transformer.resblocks.1.attn.in_proj_weight", "visual.transformer.resblocks.1.attn.in_proj_bias", "visual.transformer.resblocks.1.attn.out_proj.weight", "visual.transformer.resblocks.1.attn.out_proj.bias", "visual.transformer.resblocks.1.ln_1.weight", "visual.transformer.resblocks.1.ln_1.bias", "visual.transformer.resblocks.1.mlp.c_fc.weight", "visual.transformer.resblocks.1.mlp.c_fc.bias", "visual.transformer.resblocks.1.mlp.c_proj.weight", "visual.transformer.resblocks.1.mlp.c_proj.bias", "visual.transformer.resblocks.1.ln_2.weight", "visual.transformer.resblocks.1.ln_2.bias", "visual.transformer.resblocks.2.attn.in_proj_weight", "visual.transformer.resbl...
Unexpected key(s) in state_dict: "epoch", "model_state_dict", "optimizer_state_dict", "loss".

<!-- gh-comment-id:1120454817 --> @AhmedEwis commented on GitHub (May 8, 2022): Hello all I have been using the above code and I have already got my weight and biases model.pt for my custom dataset. I am trying now to implement my custom model to the following repo: https://github.com/rmokady/CLIP_prefix_caption but I am getting the below error: RuntimeError: Error(s) in loading state_dict for CLIP: Missing key(s) in state_dict: "positional_embedding", "text_projection", "logit_scale", "visual.class_embedding", "visual.positional_embedding", "visual.proj", "visual.conv1.weight", "visual.ln_pre.weight", "visual.ln_pre.bias", "visual.transformer.resblocks.0.attn.in_proj_weight", "visual.transformer.resblocks.0.attn.in_proj_bias", "visual.transformer.resblocks.0.attn.out_proj.weight", "visual.transformer.resblocks.0.attn.out_proj.bias", "visual.transformer.resblocks.0.ln_1.weight", "visual.transformer.resblocks.0.ln_1.bias", "visual.transformer.resblocks.0.mlp.c_fc.weight", "visual.transformer.resblocks.0.mlp.c_fc.bias", "visual.transformer.resblocks.0.mlp.c_proj.weight", "visual.transformer.resblocks.0.mlp.c_proj.bias", "visual.transformer.resblocks.0.ln_2.weight", "visual.transformer.resblocks.0.ln_2.bias", "visual.transformer.resblocks.1.attn.in_proj_weight", "visual.transformer.resblocks.1.attn.in_proj_bias", "visual.transformer.resblocks.1.attn.out_proj.weight", "visual.transformer.resblocks.1.attn.out_proj.bias", "visual.transformer.resblocks.1.ln_1.weight", "visual.transformer.resblocks.1.ln_1.bias", "visual.transformer.resblocks.1.mlp.c_fc.weight", "visual.transformer.resblocks.1.mlp.c_fc.bias", "visual.transformer.resblocks.1.mlp.c_proj.weight", "visual.transformer.resblocks.1.mlp.c_proj.bias", "visual.transformer.resblocks.1.ln_2.weight", "visual.transformer.resblocks.1.ln_2.bias", "visual.transformer.resblocks.2.attn.in_proj_weight", "visual.transformer.resbl... Unexpected key(s) in state_dict: "epoch", "model_state_dict", "optimizer_state_dict", "loss".
Author
Owner

@AhmedEwis commented on GitHub (May 8, 2022):

Hello all I have been using the above code and I have already got my weight and biases model.pt for my custom dataset. I am trying now to implement my custom model to the following repo: https://github.com/rmokady/CLIP_prefix_caption but I am getting the below error: RuntimeError: Error(s) in loading state_dict for CLIP: Missing key(s) in state_dict: "positional_embedding", "text_projection", "logit_scale", "visual.class_embedding", "visual.positional_embedding", "visual.proj", "visual.conv1.weight", "visual.ln_pre.weight", "visual.ln_pre.bias", "visual.transformer.resblocks.0.attn.in_proj_weight", "visual.transformer.resblocks.0.attn.in_proj_bias", "visual.transformer.resblocks.0.attn.out_proj.weight", "visual.transformer.resblocks.0.attn.out_proj.bias", "visual.transformer.resblocks.0.ln_1.weight", "visual.transformer.resblocks.0.ln_1.bias", "visual.transformer.resblocks.0.mlp.c_fc.weight", "visual.transformer.resblocks.0.mlp.c_fc.bias", "visual.transformer.resblocks.0.mlp.c_proj.weight", "visual.transformer.resblocks.0.mlp.c_proj.bias", "visual.transformer.resblocks.0.ln_2.weight", "visual.transformer.resblocks.0.ln_2.bias", "visual.transformer.resblocks.1.attn.in_proj_weight", "visual.transformer.resblocks.1.attn.in_proj_bias", "visual.transformer.resblocks.1.attn.out_proj.weight", "visual.transformer.resblocks.1.attn.out_proj.bias", "visual.transformer.resblocks.1.ln_1.weight", "visual.transformer.resblocks.1.ln_1.bias", "visual.transformer.resblocks.1.mlp.c_fc.weight", "visual.transformer.resblocks.1.mlp.c_fc.bias", "visual.transformer.resblocks.1.mlp.c_proj.weight", "visual.transformer.resblocks.1.mlp.c_proj.bias", "visual.transformer.resblocks.1.ln_2.weight", "visual.transformer.resblocks.1.ln_2.bias", "visual.transformer.resblocks.2.attn.in_proj_weight", "visual.transformer.resbl... Unexpected key(s) in state_dict: "epoch", "model_state_dict", "optimizer_state_dict", "loss".

Issue fixed by loading only the model state dictionary checkpoints instead of the:

model.load_state_dict(checkpoint['model_state_dict'])

<!-- gh-comment-id:1120472823 --> @AhmedEwis commented on GitHub (May 8, 2022): > Hello all I have been using the above code and I have already got my weight and biases model.pt for my custom dataset. I am trying now to implement my custom model to the following repo: https://github.com/rmokady/CLIP_prefix_caption but I am getting the below error: RuntimeError: Error(s) in loading state_dict for CLIP: Missing key(s) in state_dict: "positional_embedding", "text_projection", "logit_scale", "visual.class_embedding", "visual.positional_embedding", "visual.proj", "visual.conv1.weight", "visual.ln_pre.weight", "visual.ln_pre.bias", "visual.transformer.resblocks.0.attn.in_proj_weight", "visual.transformer.resblocks.0.attn.in_proj_bias", "visual.transformer.resblocks.0.attn.out_proj.weight", "visual.transformer.resblocks.0.attn.out_proj.bias", "visual.transformer.resblocks.0.ln_1.weight", "visual.transformer.resblocks.0.ln_1.bias", "visual.transformer.resblocks.0.mlp.c_fc.weight", "visual.transformer.resblocks.0.mlp.c_fc.bias", "visual.transformer.resblocks.0.mlp.c_proj.weight", "visual.transformer.resblocks.0.mlp.c_proj.bias", "visual.transformer.resblocks.0.ln_2.weight", "visual.transformer.resblocks.0.ln_2.bias", "visual.transformer.resblocks.1.attn.in_proj_weight", "visual.transformer.resblocks.1.attn.in_proj_bias", "visual.transformer.resblocks.1.attn.out_proj.weight", "visual.transformer.resblocks.1.attn.out_proj.bias", "visual.transformer.resblocks.1.ln_1.weight", "visual.transformer.resblocks.1.ln_1.bias", "visual.transformer.resblocks.1.mlp.c_fc.weight", "visual.transformer.resblocks.1.mlp.c_fc.bias", "visual.transformer.resblocks.1.mlp.c_proj.weight", "visual.transformer.resblocks.1.mlp.c_proj.bias", "visual.transformer.resblocks.1.ln_2.weight", "visual.transformer.resblocks.1.ln_2.bias", "visual.transformer.resblocks.2.attn.in_proj_weight", "visual.transformer.resbl... Unexpected key(s) in state_dict: "epoch", "model_state_dict", "optimizer_state_dict", "loss". Issue fixed by loading only the model state dictionary checkpoints instead of the: model.load_state_dict(checkpoint['model_state_dict'])
Author
Owner

@AhmedEwis commented on GitHub (May 8, 2022):

I am trying to implement a custom clip:

model = clip_model.eval()
device = CUDA(0) if is_gpu else "cpu"
model = clip_model.to(device)

use_beam_search = False

import pandas as pd
prefix_length=10

df = pd.DataFrame([],columns=['image','desc'])
for fname in [i for i in os.listdir('image') if i.endswith('.png')]:
image = io.imread('image/'+fname)
pil_image = PIL.Image.fromarray(image)
image = preprocess(pil_image).unsqueeze(0).to(device)

with torch.no_grad():
prefix = model.encode_image(image).to(device, dtype=torch.float32)
prefix_embed = model.clip_project(prefix).reshape(1, prefix_length, -1)

if use_beam_search:
generated_text_prefix = generate_beam(model, tokenizer, embed=prefix_embed)[0]
else:
generated_text_prefix = generate2(model, tokenizer, embed=prefix_embed)

df.loc[len(df)] = [fname,generated_text_prefix]
print(generated_text_prefix)

Getting error in the below code: #prefix_embed = model.clip_project(prefix).reshape(1, prefix_length, -1)

ModuleAttributeError: 'CLIP' object has no attribute 'clip_project'

<!-- gh-comment-id:1120473036 --> @AhmedEwis commented on GitHub (May 8, 2022): I am trying to implement a custom clip: model = clip_model.eval() device = CUDA(0) if is_gpu else "cpu" model = clip_model.to(device) use_beam_search = False import pandas as pd prefix_length=10 df = pd.DataFrame([],columns=['image','desc']) for fname in [i for i in os.listdir('image') if i.endswith('.png')]: image = io.imread('image/'+fname) pil_image = PIL.Image.fromarray(image) image = preprocess(pil_image).unsqueeze(0).to(device) with torch.no_grad(): prefix = model.encode_image(image).to(device, dtype=torch.float32) prefix_embed = model.clip_project(prefix).reshape(1, prefix_length, -1) if use_beam_search: generated_text_prefix = generate_beam(model, tokenizer, embed=prefix_embed)[0] else: generated_text_prefix = generate2(model, tokenizer, embed=prefix_embed) df.loc[len(df)] = [fname,generated_text_prefix] print(generated_text_prefix) Getting error in the below code: #prefix_embed = model.clip_project(prefix).reshape(1, prefix_length, -1) ModuleAttributeError: 'CLIP' object has no attribute 'clip_project'
Author
Owner

@kxkaixin commented on GitHub (May 21, 2022):

Hello, thank you for your work. May I ask you some questions?
My code has several lines like this:
model, preprocess = clip.load("RN50", device=device)
for img, text, lab, id in train_loader:
With the torch. no_grad () :
Image_features = model. Encode_image (img)
Text_features = model. Encode_text (text)

  1. For both Image_features = model.encode_image(img) and text_features = model.encode_text(text) , the data dimension is [batch_size, emb_dim]. If I want to get more abundant data dimension, how can I get it?
  2. When I debug at image_features = model.encode_image(img), I want to know how the image is encoded, but when executing to
    def encode_image (self image) :
    return self.visual(image.type(self.dtype)));
    the self.visual () network processing the image does not enter the expected network. It jumps straight out. What causes it? I used PyCharm to debug.
  3. Due to limited equipment resources, if feature extraction is performed using the CLIP network without parameter update (with torch.no_grad()), but the downstream task effect is to be improved, how can we adjust and improve it? Is it possible to add a new function module?
    I look forward to your reply. I hope you will forgive me for not knowing a lot in my first contact.
<!-- gh-comment-id:1133656117 --> @kxkaixin commented on GitHub (May 21, 2022): Hello, thank you for your work. May I ask you some questions? My code has several lines like this: model, preprocess = clip.load("RN50", device=device) for img, text, lab, id in train_loader: With the torch. no_grad () : Image_features = model. Encode_image (img) Text_features = model. Encode_text (text) 1. For both Image_features = model.encode_image(img) and text_features = model.encode_text(text) , the data dimension is [batch_size, emb_dim]. If I want to get more abundant data dimension, how can I get it? 2. When I debug at image_features = model.encode_image(img), I want to know how the image is encoded, but when executing to def encode_image (self image) : return self.visual(image.type(self.dtype))); the self.visual () network processing the image does not enter the expected network. It jumps straight out. What causes it? I used PyCharm to debug. 3. Due to limited equipment resources, if feature extraction is performed using the CLIP network without parameter update (with torch.no_grad()), but the downstream task effect is to be improved, how can we adjust and improve it? Is it possible to add a new function module? I look forward to your reply. I hope you will forgive me for not knowing a lot in my first contact.
Author
Owner

@vinson2233 commented on GitHub (May 23, 2022):

@kxkaixin

  1. For both Image_features = model.encode_image(img) and text_features = model.encode_text(text) , the data dimension is [batch_size, emb_dim]. If I want to get more abundant data dimension, how can I get it?

Do you mean you want the embedding result to become larger right? Since CLIP already trained and the transformer's last layer have dimension of 512, I think one of the simplest way to add the dimensionality is to add another Dense layer at the end. So instead of using forward from CLIP, just use encode_image, then pass to another dense with higher dimension. Do the same with encode_text also (Disclaimer : I never test this approach).

  1. not sure, i never use debugger

  2. I think you wanted to use the embedding from CLIP model for downstream tasks right? I believe the architecture will look like this : Data => CLIP => YourModel => Output.
    You can try to optimize yourModel without modifying the CLIP. But if you must adjust the CLIP as well, then I suggest you create a new class, where the class has both CLIP and the model used for the downstream task, and then optimize the new class to optimize both the downstream model as well the CLIP model. Would you use one embedding or both embedding? If you only use one (example image only), then training the visual part of CLIP only will make the embedding between text and images misaligned, and if you wanted to make sure that the CLIP can be fine-tuned to create good image-text representation as well for your downstream task, then I suggest you to use the MultiTaskLearning approach to optimize 2 tasks at the same time.

<!-- gh-comment-id:1134134811 --> @vinson2233 commented on GitHub (May 23, 2022): @kxkaixin 1. For both Image_features = model.encode_image(img) and text_features = model.encode_text(text) , the data dimension is [batch_size, emb_dim]. If I want to get more abundant data dimension, how can I get it? Do you mean you want the embedding result to become larger right? Since CLIP already trained and the transformer's last layer have dimension of 512, I think one of the simplest way to add the dimensionality is to add another Dense layer at the end. So instead of using forward from CLIP, just use encode_image, then pass to another dense with higher dimension. Do the same with encode_text also (Disclaimer : I never test this approach). 2. not sure, i never use debugger 3. I think you wanted to use the embedding from CLIP model for downstream tasks right? I believe the architecture will look like this : Data => CLIP => YourModel => Output. You can try to optimize yourModel without modifying the CLIP. But if you must adjust the CLIP as well, then I suggest you create a new class, where the class has both CLIP and the model used for the downstream task, and then optimize the new class to optimize both the downstream model as well the CLIP model. Would you use one embedding or both embedding? If you only use one (example image only), then training the visual part of CLIP only will make the embedding between text and images misaligned, and if you wanted to make sure that the CLIP can be fine-tuned to create good image-text representation as well for your downstream task, then I suggest you to use the MultiTaskLearning approach to optimize 2 tasks at the same time.
Author
Owner

@kxkaixin commented on GitHub (May 23, 2022):

https://github.com/openai/CLIP/issues/83#issuecomment-1134134811
Thank you very much for your reply. At the same time, thank you for your detailed explanation, which benefited me a lot.

In addition, I am very sorry to ask you a question.

For the first question, I don't mean that the value of [batch_size, emb_dim] obtained by model.encode _ image (img) changes from [100,512] to [100,1024], but whether more multidimensional information can be obtained. For example, can the CLIP model be used to obtain the type of data information such as [batch_size, C, H, W] for the image? (It doesn't have to be that way, I'm not sure about the form of data I can get, so I'm using this clunky example.)Because I couldn't jump to the expected location during debugging, I can only get data in the form of [batch_size, emb_dim] at present. That's why I asked you the second question.

<!-- gh-comment-id:1134844171 --> @kxkaixin commented on GitHub (May 23, 2022): https://github.com/openai/CLIP/issues/83#issuecomment-1134134811 Thank you very much for your reply. At the same time, thank you for your detailed explanation, which benefited me a lot. In addition, I am very sorry to ask you a question. For the first question, I don't mean that the value of [batch_size, emb_dim] obtained by model.encode _ image (img) changes from [100,512] to [100,1024], but whether more multidimensional information can be obtained. For example, can the CLIP model be used to obtain the type of data information such as [batch_size, C, H, W] for the image? (It doesn't have to be that way, I'm not sure about the form of data I can get, so I'm using this clunky example.)Because I couldn't jump to the expected location during debugging, I can only get data in the form of [batch_size, emb_dim] at present. That's why I asked you the second question.
Author
Owner

@sarahESL commented on GitHub (May 30, 2022):

Question about the CLIP itself really: does anyone know why they assign random labels in each iteration? I mean why random? Is it mentioned in the original paper?

image

<!-- gh-comment-id:1141106676 --> @sarahESL commented on GitHub (May 30, 2022): Question about the CLIP itself really: does anyone know why they assign random labels in each iteration? I mean why random? Is it mentioned in the original paper? ![image](https://user-images.githubusercontent.com/20665868/170993533-32568173-d539-4e64-98e8-aa4918c8c9cc.png)
Author
Owner

@vinson2233 commented on GitHub (May 30, 2022):

@kxkaixin do you mean that you want to know how the input changes trough the network? Like how the data changes from [BatchSize,R,G,B] => [BatchSize,XXX,YYY] => ... => [BatchSize,512]. I never try to look at them, but since this repo written in plain Pytorch, I think this stack overflow will be helpful https://stackoverflow.com/questions/42480111/model-summary-in-pytorch

<!-- gh-comment-id:1141131405 --> @vinson2233 commented on GitHub (May 30, 2022): @kxkaixin do you mean that you want to know how the input changes trough the network? Like how the data changes from [BatchSize,R,G,B] => [BatchSize,XXX,YYY] => ... => [BatchSize,512]. I never try to look at them, but since this repo written in plain Pytorch, I think this stack overflow will be helpful https://stackoverflow.com/questions/42480111/model-summary-in-pytorch
Author
Owner

@vinson2233 commented on GitHub (May 30, 2022):

@sarahESL No, it's not a random number. The cross_entropy_loss is accept a label in an integer-based position(not binary one-hot format). For example, let's say I wanted to create a fruit classification. I can mark apple as 0, banana as 1, and melon as 2. If I have [apple,apple,melon,banana], then the labels will become [0,0,2,1].
Now with CLIP, we provide a pair list of images and text. For example, if I have 10 pairs, it means I will have 10 images and 10 texts. The first image should only be matched with the first text, and the second image only to the second text until the 10th image is corresponding to the 10th text. Putting those data will create a logits matrix with the dimension of 10x10.
The way we look at it is, that for the first row, we have the cosine similarity to 10 other values/columns, but the correct value should be the first one (the 0th index).
The second row should have the highest similarity with the second column (the label is 1 for the 2nd column), until the last row which should be matched with the last col (index number: 9).

<!-- gh-comment-id:1141139017 --> @vinson2233 commented on GitHub (May 30, 2022): @sarahESL No, it's not a random number. The cross_entropy_loss is accept a label in an integer-based position(not binary one-hot format). For example, let's say I wanted to create a fruit classification. I can mark apple as 0, banana as 1, and melon as 2. If I have [apple,apple,melon,banana], then the labels will become [0,0,2,1]. Now with CLIP, we provide a pair list of images and text. For example, if I have 10 pairs, it means I will have 10 images and 10 texts. The first image should only be matched with the first text, and the second image only to the second text until the 10th image is corresponding to the 10th text. Putting those data will create a _logits_ matrix with the dimension of 10x10. The way we look at it is, that for the first row, we have the cosine similarity to 10 other values/columns, but the correct value should be the first one (the 0th index). The second row should have the highest similarity with the second column (the label is 1 for the 2nd column), until the last row which should be matched with the last col (index number: 9).
Author
Owner

@kxkaixin commented on GitHub (May 30, 2022):

Ok, thank you for your reply. Much appreciated.

<!-- gh-comment-id:1141165057 --> @kxkaixin commented on GitHub (May 30, 2022): Ok, thank you for your reply. Much appreciated.
Author
Owner

@smith-co commented on GitHub (Jun 29, 2022):

# TO ADD :
# Gradient Checkpointing
# Filter out bias from weight decay
# Decaying learning rate with cosine schedule
# Half-precision Adam statistics
# Half-precision stochastically rounded text encoder weights were used

Do you plan to update the snippet to address the above todos?

<!-- gh-comment-id:1169464806 --> @smith-co commented on GitHub (Jun 29, 2022): > ```python > # TO ADD : > # Gradient Checkpointing > # Filter out bias from weight decay > # Decaying learning rate with cosine schedule > # Half-precision Adam statistics > # Half-precision stochastically rounded text encoder weights were used > ``` Do you plan to update the snippet to address the above todos?
Author
Owner

@Weifeng-Chen commented on GitHub (Jun 29, 2022):

【自动恢复】来信已收到,我将尽快回复你!

<!-- gh-comment-id:1169465002 --> @Weifeng-Chen commented on GitHub (Jun 29, 2022): 【自动恢复】来信已收到,我将尽快回复你!
Author
Owner

@vinson2233 commented on GitHub (Jun 29, 2022):

@smith-co : Nope, I don't plan to at the moment.

<!-- gh-comment-id:1169545812 --> @vinson2233 commented on GitHub (Jun 29, 2022): @smith-co : Nope, I don't plan to at the moment.
Author
Owner

@sanjaygunda13 commented on GitHub (Jul 12, 2022):

I want to custome train clip model my data is having captions and images data in b64. i tried training my data using coco but not able to do as i am getting some cuda error can someone help me out please.

<!-- gh-comment-id:1182543995 --> @sanjaygunda13 commented on GitHub (Jul 12, 2022): I want to custome train clip model my data is having captions and images data in b64. i tried training my data using coco but not able to do as i am getting some cuda error can someone help me out please.
Author
Owner

@abdullah-jahangir commented on GitHub (Jul 18, 2022):

Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. Feel free to ask or point out any mistakes in my code.

# Latest Update : 31 May 2022, 09:55 GMT+7

# TO ADD :
# Gradient Checkpointing
# Filter out bias from weight decay
# Decaying learning rate with cosine schedule
# Half-precision Adam statistics
# Half-precision stochastically rounded text encoder weights were used

#BATCH_SIZE must larger than 1

device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training.
model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training

class image_title_dataset(Dataset):
    def __init__(self, list_image_path,list_txt):

        self.image_path = list_image_path
        self.title  = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop.

    def __len__(self):
        return len(self.list_txt)

    def __getitem__(self, idx):
        image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module
        title = self.title[idx]
        return image,title

# use your own data
list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] 
list_txt = ['description for image1.jpg' , 'description for image2.jpg']
dataset = image_title_dataset(list_image_path,list_txt)
train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader

#https://github.com/openai/CLIP/issues/57
def convert_models_to_fp32(model): 
    for p in model.parameters(): 
        p.data = p.data.float() 
        p.grad.data = p.grad.data.float() 


if device == "cpu":
  model.float()
else :
  clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16

loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset

# add your own code to track the training progress.
for epoch in range(EPOCH):
  for batch in train_dataloader :
      optimizer.zero_grad()

      images,texts = batch 
    
      images= images.to(device)
      texts = texts.to(device)
    
      logits_per_image, logits_per_text = model(images, texts)

      ground_truth = torch.arange(len(images),dtype=torch.long,device=device)

      total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2
      total_loss.backward()
      if device == "cpu":
         optimizer.step()
      else : 
        convert_models_to_fp32(model)
        optimizer.step()
        clip.model.convert_weights(model)

Code to save the model :

torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': total_loss,
        }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename

Code to load the saved model :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224
checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Alternative training code :

I am getting the following error when I run the code: AttributeError: 'image_title_dataset' object has no attribute 'list_txt', can you please help with this?

<!-- gh-comment-id:1186709552 --> @abdullah-jahangir commented on GitHub (Jul 18, 2022): > Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. Feel free to ask or point out any mistakes in my code. > > ```python > # Latest Update : 31 May 2022, 09:55 GMT+7 > > # TO ADD : > # Gradient Checkpointing > # Filter out bias from weight decay > # Decaying learning rate with cosine schedule > # Half-precision Adam statistics > # Half-precision stochastically rounded text encoder weights were used > > #BATCH_SIZE must larger than 1 > > device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training. > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > > class image_title_dataset(Dataset): > def __init__(self, list_image_path,list_txt): > > self.image_path = list_image_path > self.title = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop. > > def __len__(self): > return len(self.list_txt) > > def __getitem__(self, idx): > image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module > title = self.title[idx] > return image,title > > # use your own data > list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] > list_txt = ['description for image1.jpg' , 'description for image2.jpg'] > dataset = image_title_dataset(list_image_path,list_txt) > train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader > > #https://github.com/openai/CLIP/issues/57 > def convert_models_to_fp32(model): > for p in model.parameters(): > p.data = p.data.float() > p.grad.data = p.grad.data.float() > > > if device == "cpu": > model.float() > else : > clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16 > > loss_img = nn.CrossEntropyLoss() > loss_txt = nn.CrossEntropyLoss() > optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset > > # add your own code to track the training progress. > for epoch in range(EPOCH): > for batch in train_dataloader : > optimizer.zero_grad() > > images,texts = batch > > images= images.to(device) > texts = texts.to(device) > > logits_per_image, logits_per_text = model(images, texts) > > ground_truth = torch.arange(len(images),dtype=torch.long,device=device) > > total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 > total_loss.backward() > if device == "cpu": > optimizer.step() > else : > convert_models_to_fp32(model) > optimizer.step() > clip.model.convert_weights(model) > ``` > > * NOTE : > > * that for inference purpose, the conversion step from fp16 to fp32 is not needed, just use the model in full fp16 > * For multi-GPU training, see my comment on [how to use multiple GPUs,the default is to use the first CUDA device #111 (comment)](https://github.com/openai/CLIP/issues/111#issuecomment-854320770) > * I'm not the author of this model nor having any relationship with the author. I'm just a random guy who interested in CLIP. > > Code to save the model : > > ```python > torch.save({ > 'epoch': epoch, > 'model_state_dict': model.state_dict(), > 'optimizer_state_dict': optimizer.state_dict(), > 'loss': total_loss, > }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename > ``` > > Code to load the saved model : > > ```python > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > checkpoint = torch.load("model_checkpoint/model_10.pt") > > # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] > checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224 > checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77 > checkpoint['model_state_dict']["vocab_size"] = model.vocab_size > > model.load_state_dict(checkpoint['model_state_dict']) > ``` > > Alternative training code : > > * @Zasder3 have created a PyTorch lighting version to train the CLIP https://github.com/Zasder3/train-CLIP > * @mitchellnw researchers at UW, Google, Stanford, Amazon, Columbia, and Berkeley also create their training code https://github.com/mlfoundations/open_clip I am getting the following error when I run the code: AttributeError: 'image_title_dataset' object has no attribute 'list_txt', can you please help with this?
Author
Owner

@vinson2233 commented on GitHub (Jul 18, 2022):

@abdullah-jahangir slight typo in my code, i fixed it. just change the len definition inside the class

<!-- gh-comment-id:1186711977 --> @vinson2233 commented on GitHub (Jul 18, 2022): @abdullah-jahangir slight typo in my code, i fixed it. just change the __len__ definition inside the class
Author
Owner

@vinson2233 commented on GitHub (Jul 18, 2022):

@sanjaygunda13 I never tried the processing in Base64, maybe you need to try to decode the Byte64 into PIL format first.

<!-- gh-comment-id:1186712343 --> @vinson2233 commented on GitHub (Jul 18, 2022): @sanjaygunda13 I never tried the processing in Base64, maybe you need to try to decode the Byte64 into PIL format first.
Author
Owner

@abdullah-jahangir commented on GitHub (Jul 18, 2022):

@abdullah-jahangir slight typo in my code, i fixed it. just change the len definition inside the class

Thank you, however I am now getting a new error: File "train.py", line 32, in_getitem_
image = preprocess(Image.open(self. image_path[idx])) # Image from PIL module. I do not understand this as the number of images and texts are both equal.

<!-- gh-comment-id:1187629574 --> @abdullah-jahangir commented on GitHub (Jul 18, 2022): > @abdullah-jahangir slight typo in my code, i fixed it. just change the **len** definition inside the class Thank you, however I am now getting a new error: File "train.py", line 32, in_getitem_ image = preprocess(Image.open(self. image_path[idx])) # Image from PIL module. I do not understand this as the number of images and texts are both equal.
Author
Owner

@gongshaojie12 commented on GitHub (Jul 28, 2022):

Hi, thank you for your work. I have a question. How to fine-tune with clip in my own chinese dataset? Thanks!

<!-- gh-comment-id:1197734521 --> @gongshaojie12 commented on GitHub (Jul 28, 2022): Hi, thank you for your work. I have a question. How to fine-tune with clip in my own chinese dataset? Thanks!
Author
Owner

@antu-saha commented on GitHub (Jul 29, 2022):

Hi, thank you very much for the great work.
I am trying to use your code for my data. Could you please give me the Dataset and DataLoader class? or Can you tell how they should look like or what will they do?

<!-- gh-comment-id:1198804895 --> @antu-saha commented on GitHub (Jul 29, 2022): Hi, thank you very much for the great work. I am trying to use your code for my data. Could you please give me the Dataset and DataLoader class? or Can you tell how they should look like or what will they do?
Author
Owner

@sanjaygunda13 commented on GitHub (Aug 14, 2022):

Hello @vinson2233 can you help me out how to fine tune clip vitb32 model. I am struggling from long time to understand this. thanks

<!-- gh-comment-id:1214477023 --> @sanjaygunda13 commented on GitHub (Aug 14, 2022): Hello @vinson2233 can you help me out how to fine tune clip vitb32 model. I am struggling from long time to understand this. thanks
Author
Owner

@vgthengane commented on GitHub (Aug 22, 2022):

How can I freeze the clip model weight? So that when I am using CLIP as a teacher model in knowledge distillation, CLIP model weights should not change.

<!-- gh-comment-id:1222647856 --> @vgthengane commented on GitHub (Aug 22, 2022): How can I freeze the clip model weight? So that when I am using CLIP as a teacher model in knowledge distillation, CLIP model weights should not change.
Author
Owner

@Asthestarsfalll commented on GitHub (Aug 22, 2022):

@vgthengane Maybe you can use eval method like this:

model = clip.load('RN50')
model.eval()
<!-- gh-comment-id:1222654701 --> @Asthestarsfalll commented on GitHub (Aug 22, 2022): @vgthengane Maybe you can use `eval` method like this: ```python model = clip.load('RN50') model.eval() ```
Author
Owner

@vgthengane commented on GitHub (Aug 22, 2022):

Do I need to use torch.no_grad() in that case?

with torch.no_grad():
   y = clip.image_encoder(x)
   

@vgthengane Maybe you can use eval method like this:

model = clip.load('RN50')
model.eval()

Also, I think model.eval() is already there when loading the clip model (github.com/openai/CLIP@d50d76daa6/clip/clip.py (L129)).

Anyway thanks

<!-- gh-comment-id:1222678884 --> @vgthengane commented on GitHub (Aug 22, 2022): Do I need to use `torch.no_grad()` in that case? ``` with torch.no_grad(): y = clip.image_encoder(x) ``` > @vgthengane Maybe you can use `eval` method like this: > > ```python > model = clip.load('RN50') > model.eval() > ``` Also, I think model.eval() is already there when loading the clip model (https://github.com/openai/CLIP/blob/d50d76daa670286dd6cacf3bcd80b5e4823fc8e1/clip/clip.py#L129). Anyway thanks
Author
Owner

@pingapplepen commented on GitHub (Oct 10, 2022):

Hi, thanks for the work. I am now facint the issue that training loss doesn't drop. Must we use the loss function provided by you?
For those who has difficulty on loss converging when using CLIP, change the learning rate to e-7/-8 may work

<!-- gh-comment-id:1273197410 --> @pingapplepen commented on GitHub (Oct 10, 2022): ~~Hi, thanks for the work. I am now facint the issue that training loss doesn't drop. Must we use the loss function provided by you?~~ For those who has difficulty on loss converging when using CLIP, change the learning rate to e<sup>-7/-8</sup> may work
Author
Owner

@antu-saha commented on GitHub (Oct 10, 2022):

Hi @vinson2233, I am fine-tuning CLIP with my dataset. But after 2 epochs, I am getting the total loss as nan. How can I deal with this issue?

Thank you for the help.

<!-- gh-comment-id:1273388435 --> @antu-saha commented on GitHub (Oct 10, 2022): Hi @vinson2233, I am fine-tuning CLIP with my dataset. But after 2 epochs, I am getting the total loss as nan. How can I deal with this issue? Thank you for the help.
Author
Owner

@wntg commented on GitHub (Oct 27, 2022):

Thank you for your work. How does it perform compared to only using image encoder?

<!-- gh-comment-id:1292913252 --> @wntg commented on GitHub (Oct 27, 2022): Thank you for your work. How does it perform compared to only using image encoder?
Author
Owner

@jindongwang commented on GitHub (Nov 1, 2022):

Why is the training loss always 0?

<!-- gh-comment-id:1298387905 --> @jindongwang commented on GitHub (Nov 1, 2022): Why is the training loss always 0?
Author
Owner

@cgusti commented on GitHub (Nov 30, 2022):

Hi! Thanks alot for this. Do you have a reference to all the import statements you used for this code?

<!-- gh-comment-id:1332567512 --> @cgusti commented on GitHub (Nov 30, 2022): > * https://github.com/mlfoundations/open_clip Hi! Thanks alot for this. Do you have a reference to all the import statements you used for this code?
Author
Owner

@developer0hye commented on GitHub (Dec 2, 2022):

@vinson2233
Thanks!

I think that we should use AdamW instead of Adam.

image

<!-- gh-comment-id:1335164679 --> @developer0hye commented on GitHub (Dec 2, 2022): @vinson2233 Thanks! I think that we should use AdamW instead of Adam. ![image](https://user-images.githubusercontent.com/35001605/205293238-9084a35c-2e98-46a1-b80a-8ab9cd4bf6c8.png)
Author
Owner

@Techsetter commented on GitHub (Feb 15, 2023):

Does anyone have a fine-tuning colab notebook?

<!-- gh-comment-id:1432097321 --> @Techsetter commented on GitHub (Feb 15, 2023): Does anyone have a fine-tuning colab notebook?
Author
Owner

@shantanu778 commented on GitHub (Mar 2, 2023):

@vinson2233 It seems pre-training CLIP model instead of fine-tuning the model. Also where did you freeze the model parameters?
According to your script #83, model start training with new dataset which may delete all pretrained weights. Can you please ensure whether it's pre-training or fine-tuning?

<!-- gh-comment-id:1451718190 --> @shantanu778 commented on GitHub (Mar 2, 2023): @vinson2233 It seems pre-training CLIP model instead of fine-tuning the model. Also where did you freeze the model parameters? According to your script #83, model start training with new dataset which may delete all pretrained weights. Can you please ensure whether it's pre-training or fine-tuning?
Author
Owner

@vinson2233 commented on GitHub (Mar 2, 2023):

@shantanu778 :

Also where did you freeze the model parameters?

I don't freeze the parameter, i let all the weight get adjusted for the new dataset.

model start training with new dataset which may delete all pretrained weights.

this is wrong. the model uploaded by the author is already pretrained. just look at the inner code and you can see the first step of the loading the model is importing the pretrained weight.
github.com/openai/CLIP@a9b1bf5920/clip/clip.py (L119-L120)

by training the model on new dataset doesn't mean the old weight got wiped out.

<!-- gh-comment-id:1452123654 --> @vinson2233 commented on GitHub (Mar 2, 2023): @shantanu778 : > Also where did you freeze the model parameters? I don't freeze the parameter, i let all the weight get adjusted for the new dataset. >model start training with new dataset which may delete all pretrained weights. this is wrong. the model uploaded by the author is already pretrained. just look at the inner code and you can see the first step of the loading the model is importing the pretrained weight. https://github.com/openai/CLIP/blob/a9b1bf5920416aaeaec965c25dd9e8f98c864f16/clip/clip.py#L119-L120 by training the model on new dataset doesn't mean the old weight got wiped out.
Author
Owner

@shantanu778 commented on GitHub (Mar 2, 2023):

@vinson2233 Thanks for the reply. I have another question.
Here, we have 1 image with 1 caption. But, if I have 1 image with 3 captions. Then how can I do this?

<!-- gh-comment-id:1452631763 --> @shantanu778 commented on GitHub (Mar 2, 2023): @vinson2233 Thanks for the reply. I have another question. Here, we have 1 image with 1 caption. But, if I have 1 image with 3 captions. Then how can I do this?
Author
Owner

@chumpblocckami commented on GitHub (Mar 6, 2023):

I'm facing this issue after using the script for finetuning the model on a custom dataset.
Any help would be appreciated :)
image

<!-- gh-comment-id:1455880166 --> @chumpblocckami commented on GitHub (Mar 6, 2023): I'm facing this issue after using the script for finetuning the model on a custom dataset. Any help would be appreciated :) ![image](https://user-images.githubusercontent.com/12396148/223085366-d85e2f61-fc46-44b3-82d8-af752087f245.png)
Author
Owner

@chumpblocckami commented on GitHub (Mar 6, 2023):

@vinson2233 Thanks for the reply. I have another question. Here, we have 1 image with 1 caption. But, if I have 1 image with 3 captions. Then how can I do this?

You probably want to merge the caption in a single string, such as (" ").join(captions)

<!-- gh-comment-id:1455883668 --> @chumpblocckami commented on GitHub (Mar 6, 2023): > @vinson2233 Thanks for the reply. I have another question. Here, we have 1 image with 1 caption. But, if I have 1 image with 3 captions. Then how can I do this? You probably want to merge the caption in a single string, such as (" ").join(captions)
Author
Owner

@EachOneChew commented on GitHub (Mar 10, 2023):

Thank you! I've two questions about this:

  1. Why don't you set the model to training mode before the training loop?
  2. Has anyone experimented with setting logit_scale back to a lower value and letting the model relearn it?
<!-- gh-comment-id:1463202670 --> @EachOneChew commented on GitHub (Mar 10, 2023): Thank you! I've two questions about this: 1. Why don't you set the model to training mode before the training loop? 2. Has anyone experimented with setting `logit_scale` back to a lower value and letting the model relearn it?
Author
Owner

@DorisBao commented on GitHub (Mar 27, 2023):

Hi, thanks for your code. However, I have a question of the groundtruth part. As your code shows that the groundtruth is
ground_truth = torch.arange(len(images), dtype=torch.long, device=device). What does it means? I think it should be the paired text of each image. So we need to select them to a tensor? I am confused about this torch.long

<!-- gh-comment-id:1485778884 --> @DorisBao commented on GitHub (Mar 27, 2023): Hi, thanks for your code. However, I have a question of the groundtruth part. As your code shows that the groundtruth is **ground_truth = torch.arange(len(images), dtype=torch.long, device=device)**. What does it means? I think it should be the paired text of each image. So we need to select them to a tensor? I am confused about this torch.long
Author
Owner

@DorisBao commented on GitHub (Mar 28, 2023):

@vinid I mean train a CLIP not finetune.

<!-- gh-comment-id:1487257588 --> @DorisBao commented on GitHub (Mar 28, 2023): @vinid I mean train a CLIP not finetune.
Author
Owner

@vinson2233 commented on GitHub (Mar 29, 2023):

@DorisBao see this https://github.com/openai/CLIP/issues/83#issuecomment-1141139017

<!-- gh-comment-id:1487816742 --> @vinson2233 commented on GitHub (Mar 29, 2023): @DorisBao see this https://github.com/openai/CLIP/issues/83#issuecomment-1141139017
Author
Owner

@vinson2233 commented on GitHub (Mar 29, 2023):

Got lot of inquiry on how to train image-image, text-text, or even image to multiple text or other way around. The idea is still the same, but we need to make sure that in a batch of training, no contradicting pair can be found. see this diagram for image-image matching. Just make sure we don't put two pair that match in a batch.

image

The principle is still much the same for image to multiple text.
Letsay image A have text T1, T2 and T3

in batch 1 you wanted to train A with T1,
next batch A with T2
and next batch A with T3. But we don't want to train A with T1 T2 and T3 because it will create contradiction

<!-- gh-comment-id:1487820198 --> @vinson2233 commented on GitHub (Mar 29, 2023): Got lot of inquiry on how to train image-image, text-text, or even image to multiple text or other way around. The idea is still the same, but **we need to make sure that in a batch of training, no contradicting pair can be found.** see this diagram for image-image matching. Just make sure we don't put two pair that match in a batch. <img width="849" alt="image" src="https://user-images.githubusercontent.com/33550590/228402635-f761d5db-fb55-47d9-9095-ed1aa4bb9238.png"> The principle is still much the same for image to multiple text. Letsay image A have text T1, T2 and T3 in batch 1 you wanted to train A with T1, next batch A with T2 and next batch A with T3. But we don't want to train A with T1 T2 and T3 because it will create contradiction
Author
Owner

@DorisBao commented on GitHub (Mar 29, 2023):

I have a confuse about total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2. I have check the logits_per_image and logits_per_text, they have same value but in different shape. Can we just use one of them?

<!-- gh-comment-id:1489043470 --> @DorisBao commented on GitHub (Mar 29, 2023): I have a confuse about **total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2**. I have check the **logits_per_image** and **logits_per_text**, they have same value but in different shape. Can we just use one of them?
Author
Owner

@vinson2233 commented on GitHub (Mar 30, 2023):

@DorisBao i think i wrote the reason somewhere in this long thread, but can't find it anymore. to answer your question, we need to understand how the PyTorch uses the CrossEntropyLoss loss during backpropagation.

CrossEntropyLoss is popularly used for multi-class classification. We can treat this problem as given an image, which text is the most suitable one and also given a text, which image is the most suitable one. We classify it with the index position.

for CLIP let's say i lay the image into the rows and the text as the column.
for each row, the image should only have 1 match to a label, that what is the CrossEntropyLoss try to measure.
You do it for all the row and optimize it, then it will solve the given an image, which text is most suitable one. But it does not try to optimize for the other axis.

So we need the transposed version to answer the given a text, which image is the most suitable one.
You can see this as MTL (Multi-Task Learning) because we want to optimize clip for two task, and one simple way to do it is to take average of the looses and backprop through it

<!-- gh-comment-id:1489603702 --> @vinson2233 commented on GitHub (Mar 30, 2023): @DorisBao i think i wrote the reason somewhere in this long thread, but can't find it anymore. to answer your question, we need to understand how the PyTorch uses the CrossEntropyLoss loss during backpropagation. CrossEntropyLoss is popularly used for multi-class classification. We can treat this problem as `given an image, which text is the most suitable one` and also `given a text, which image is the most suitable one`. We classify it with the index position. for CLIP let's say i lay the image into the rows and the text as the column. for each row, the image should only have 1 match to a label, that what is the CrossEntropyLoss try to measure. You do it for all the row and optimize it, then it will solve the `given an image, which text is most suitable one`. But it does not try to optimize for the other axis. So we need the transposed version to answer the `given a text, which image is the most suitable one`. You can see this as MTL (Multi-Task Learning) because we want to optimize clip for two task, and one simple way to do it is to take average of the looses and backprop through it
Author
Owner

@YunfanLing commented on GitHub (Mar 30, 2023):

list_txt = ['description for image1.jpg' , 'description for image2.jpg']
If I have 100 car images, should this be ["car"]*100?

<!-- gh-comment-id:1490136193 --> @YunfanLing commented on GitHub (Mar 30, 2023): list_txt = ['description for image1.jpg' , 'description for image2.jpg'] If I have 100 car images, should this be ["car"]*100?
Author
Owner

@DorisBao commented on GitHub (Mar 31, 2023):

@vinson2233 Thanks!! So for instance, if I only used CLIP for classification, let's say we only have one text for the whole class( n images) which means we can't match every text to single image. And in this case, the text loss is unnecessary? right?

<!-- gh-comment-id:1491353809 --> @DorisBao commented on GitHub (Mar 31, 2023): @vinson2233 Thanks!! So for instance, if I only used CLIP for classification, let's say we only have one text for the whole class( n images) which means we can't match every text to single image. And in this case, the text loss is unnecessary? right?
Author
Owner

@DorisBao commented on GitHub (Mar 31, 2023):

The only reason we used both image and text loss is that we want the paired image-text structure to be unique.

<!-- gh-comment-id:1491355140 --> @DorisBao commented on GitHub (Mar 31, 2023): The only reason we used both image and text loss is that we want the paired image-text structure to be unique.
Author
Owner

@EachOneChew commented on GitHub (Mar 31, 2023):

@vinson2233 I'm wondering if you or anyone else have experimented with freezing certain CLIP layers? As far as I know freezing batch norm during fine tuning is standard because the training distribution is usually different, but I don't see how this applies to layer norm. I've also considered replacing the linear projector in the CLIP encoders with a MLP projector.

At the moment my training loss converges to a lower value during the first epoch, but the decrease in loss overall is tiny (6.8 average loss to 6.5 approximately).

<!-- gh-comment-id:1491403760 --> @EachOneChew commented on GitHub (Mar 31, 2023): @vinson2233 I'm wondering if you or anyone else have experimented with freezing certain CLIP layers? As far as I know freezing batch norm during fine tuning is standard because the training distribution is usually different, but I don't see how this applies to layer norm. I've also considered replacing the linear projector in the CLIP encoders with a MLP projector. At the moment my training loss converges to a lower value during the first epoch, but the decrease in loss overall is tiny (6.8 average loss to 6.5 approximately).
Author
Owner

@vinson2233 commented on GitHub (Mar 31, 2023):

@DorisBao correct.

@YunfanLing please refer to https://github.com/openai/CLIP/issues/83#issuecomment-1487820198. If your data only consist of 1 text. then you cannot train the data like this because it will create a contradiction during training.

@EachOneChew no, never do that.

<!-- gh-comment-id:1491470022 --> @vinson2233 commented on GitHub (Mar 31, 2023): @DorisBao correct. @YunfanLing please refer to https://github.com/openai/CLIP/issues/83#issuecomment-1487820198. If your data only consist of 1 text. then you cannot train the data like this because it will create a contradiction during training. @EachOneChew no, never do that.
Author
Owner

@lamnt2008 commented on GitHub (Apr 5, 2023):

@vinson2233 : Hi, I'm a AI learner. I want to finetune CLIP for image classification. I have a custom dataset but i dont have text dataset for my problem. Can you tell me how to have a good method( create text dataset or finetune model or use CLIP) in order to have best result. Thanks

<!-- gh-comment-id:1496836800 --> @lamnt2008 commented on GitHub (Apr 5, 2023): @vinson2233 : Hi, I'm a AI learner. I want to finetune CLIP for image classification. I have a custom dataset but i dont have text dataset for my problem. Can you tell me how to have a good method( create text dataset or finetune model or use CLIP) in order to have best result. Thanks
Author
Owner

@EachOneChew commented on GitHub (Apr 5, 2023):

@DorisBao correct.

@YunfanLing please refer to #83 (comment). If your data only consist of 1 text. then you cannot train the data like this because it will create a contradiction during training.

@EachOneChew no, never do that.

Thank you for the response. It seems like calling train() or eval() on CLIP makes no difference as LayerNorm is kept on during both training and evaluation, unlike BatchNorm. However, I have experimented with tuning with ViT-L/14 and keeping the top half transformer layers frozen; the results are better than tuning ViT-B/32 and ViT-B/16 with gradients enabled on all layers. I think freezing layers can potentially be a good option for people who do not have enough GPU memory for larger batch sizes and also do not want to deal with the complexity of distributed InfoNCE loss.

<!-- gh-comment-id:1496874836 --> @EachOneChew commented on GitHub (Apr 5, 2023): > @DorisBao correct. > > @YunfanLing please refer to [#83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-1487820198). If your data only consist of 1 text. then you cannot train the data like this because it will create a contradiction during training. > > @EachOneChew no, never do that. Thank you for the response. It seems like calling `train()` or `eval()` on CLIP makes no difference as LayerNorm is kept on during both training and evaluation, unlike BatchNorm. However, I have experimented with tuning with `ViT-L/14` and keeping the top half transformer layers frozen; the results are better than tuning `ViT-B/32` and `ViT-B/16` with gradients enabled on all layers. I think freezing layers can potentially be a good option for people who do not have enough GPU memory for larger batch sizes and also do not want to deal with the complexity of distributed InfoNCE loss.
Author
Owner

@EachOneChew commented on GitHub (Apr 5, 2023):

@lamnt2008

Your question is very broad. What is your specific use case? If you are doing image classification, I am assuming that you have in your training dataset images paired with labels? If that is the case, you have two options as I understand:

  1. Use only CLIP's image encoder as a feature extractor and train a MLP classification head on top of it to perform classification. You may want to experiment with using lower learning rate for the CLIP image encoder and higher learning rate for the MLP head. Freezing the CLIP image encoder altogether and only training the MLP head is also a decent option for faster training on simpler classification tasks.

  2. Treat your image-label pairs as positive examples and tune CLIP using the same contrastive approach* as outlined by @vinson2233 in his code. It is probably a good idea to build prompts around your class labels (e.g. banana -> "a photo of a banana").

*For a summary of the contrastive training approach see the CLIP blog post: https://openai.com/research/clip

As for which approach is better, the most recent paper I've read suggests that 2. comes out on top: https://arxiv.org/abs/2212.00638

<!-- gh-comment-id:1496877414 --> @EachOneChew commented on GitHub (Apr 5, 2023): @lamnt2008 Your question is very broad. What is your specific use case? If you are doing image classification, I am assuming that you have in your training dataset images paired with labels? If that is the case, you have two options as I understand: 1. Use only CLIP's image encoder as a feature extractor and train a MLP classification head on top of it to perform classification. You may want to experiment with using lower learning rate for the CLIP image encoder and higher learning rate for the MLP head. Freezing the CLIP image encoder altogether and only training the MLP head is also a decent option for faster training on simpler classification tasks. 2. Treat your image-label pairs as positive examples and tune CLIP using the same contrastive approach* as outlined by @vinson2233 in his code. It is probably a good idea to build prompts around your class labels (e.g. banana -> "a photo of a banana"). *For a summary of the contrastive training approach see the CLIP blog post: https://openai.com/research/clip As for which approach is better, the most recent paper I've read suggests that 2. comes out on top: https://arxiv.org/abs/2212.00638
Author
Owner

@lamnt2008 commented on GitHub (Apr 5, 2023):

@lamnt2008

Your question is very broad. What is your specific use case? If you are doing image classification, I am assuming that you have in your training dataset images paired with labels? If that is the case, you have two options as I understand:

  1. Use only CLIP's image encoder as a feature extractor and train a MLP classification head on top of it to perform classification. You may want to experiment with using lower learning rate for the CLIP image encoder and higher learning rate for the MLP head. Freezing the CLIP image encoder altogether and only training the MLP head is also a decent option for faster training on simpler classification tasks.
  2. Treat your image-label pairs as positive examples and tune CLIP using the same contrastive approach* as outlined by @vinson2233 in his code. It is probably a good idea to build prompts around your class labels (e.g. banana -> "a photo of a banana").

*For a summary of the contrastive training approach see the CLIP blog post: https://openai.com/research/clip

As for which approach is better, the most recent paper I've read suggests that 2. comes out on top: https://arxiv.org/abs/2212.00638

Thanks @EachOneChew , i see your answer. I understand method 2 from you. I'll try. But method 1, i want to understand deeply, so can you give me example code in order to implement it?

<!-- gh-comment-id:1497101871 --> @lamnt2008 commented on GitHub (Apr 5, 2023): > @lamnt2008 > > Your question is very broad. What is your specific use case? If you are doing image classification, I am assuming that you have in your training dataset images paired with labels? If that is the case, you have two options as I understand: > > 1. Use only CLIP's image encoder as a feature extractor and train a MLP classification head on top of it to perform classification. You may want to experiment with using lower learning rate for the CLIP image encoder and higher learning rate for the MLP head. Freezing the CLIP image encoder altogether and only training the MLP head is also a decent option for faster training on simpler classification tasks. > 2. Treat your image-label pairs as positive examples and tune CLIP using the same contrastive approach* as outlined by @vinson2233 in his code. It is probably a good idea to build prompts around your class labels (e.g. banana -> "a photo of a banana"). > > *For a summary of the contrastive training approach see the CLIP blog post: https://openai.com/research/clip > > As for which approach is better, the most recent paper I've read suggests that 2. comes out on top: https://arxiv.org/abs/2212.00638 Thanks @EachOneChew , i see your answer. I understand method 2 from you. I'll try. But method 1, i want to understand deeply, so can you give me example code in order to implement it?
Author
Owner

@StonERMax commented on GitHub (Apr 8, 2023):

Hi, l have used your multi-gpu code. But there is bug that the tensors are on different cudas. Some on cuda:0 and some on cuda:1, which causes mistakes.

<!-- gh-comment-id:1500906387 --> @StonERMax commented on GitHub (Apr 8, 2023): Hi, l have used your multi-gpu code. But there is bug that the tensors are on different cudas. Some on cuda:0 and some on cuda:1, which causes mistakes.
Author
Owner

@cucumberguagua commented on GitHub (Apr 11, 2023):

CrossEntropyLoss is popularly used for multi-class classification. We can treat this problem as given an image, which text is the most suitable one and also given a text, which image is the most suitable one. We classify it with the index position.

for CLIP let's say i lay the image into the rows and the text as the column. for each row, the image should only have 1 match to a label, that what is the CrossEntropyLoss try to measure. You do it for all the row and optimize it, then it will solve the given an image, which text is most suitable one. But it does not try to optimize for the other axis.

So we need the transposed version to answer the given a text, which image is the most suitable one. You can see this as MTL (Multi-Task Learning) because we want to optimize clip for two task, and one simple way to do it is to take average of the looses and backprop through it

@vinson2233 If we only want to optimize for the task "given a text, which image is the most suitable one", then shall we only calculate loss as loss_txt(logits_per_text,ground_truth) as in your training code?

<!-- gh-comment-id:1504233104 --> @cucumberguagua commented on GitHub (Apr 11, 2023): > CrossEntropyLoss is popularly used for multi-class classification. We can treat this problem as `given an image, which text is the most suitable one` and also `given a text, which image is the most suitable one`. We classify it with the index position. > > for CLIP let's say i lay the image into the rows and the text as the column. for each row, the image should only have 1 match to a label, that what is the CrossEntropyLoss try to measure. You do it for all the row and optimize it, then it will solve the `given an image, which text is most suitable one`. But it does not try to optimize for the other axis. > > So we need the transposed version to answer the `given a text, which image is the most suitable one`. You can see this as MTL (Multi-Task Learning) because we want to optimize clip for two task, and one simple way to do it is to take average of the looses and backprop through it @vinson2233 If we only want to optimize for the task "given a text, which image is the most suitable one", then shall we only calculate loss as `loss_txt(logits_per_text,ground_truth)` as in your training code?
Author
Owner

@EachOneChew commented on GitHub (Apr 11, 2023):

@cucumberguagua I would argue no; the two tasks are not conflicting. They are related and complimentary.

<!-- gh-comment-id:1504260425 --> @EachOneChew commented on GitHub (Apr 11, 2023): @cucumberguagua I would argue no; the two tasks are not conflicting. They are related and complimentary.
Author
Owner

@EachOneChew commented on GitHub (Apr 11, 2023):

@lamnt2008 sorry, I have been very busy and don't have a quick example on hand. Can you take a look at "linear probing" using a feature extractor? CLIP's image encoder is used as an image extractor in OpenAI's own linear probe evaluations (also found here). They might have some examples, or there might be example code from peripheral research.

Functionally this just means, in the training loop:

  1. Encode image.
  2. Put image through (trainable) classifier head (a multilayer perceptron)
  3. Take classifier result and evaluate using softmax cross entropy against the single correct label.

I will find some time to give an example later, if possible.

<!-- gh-comment-id:1504284411 --> @EachOneChew commented on GitHub (Apr 11, 2023): @lamnt2008 sorry, I have been very busy and don't have a quick example on hand. Can you take a look at "linear probing" using a feature extractor? CLIP's image encoder is used as an image extractor in OpenAI's own linear probe evaluations (also found [here](https://openai.com/research/clip)). They might have some examples, or there might be example code from peripheral research. Functionally this just means, in the training loop: 1. Encode image. 2. Put image through (trainable) classifier head (a multilayer perceptron) 3. Take classifier result and evaluate using softmax cross entropy against the single correct label. I will find some time to give an example later, if possible.
Author
Owner

@mananuppadhyay commented on GitHub (Apr 19, 2023):

@vinson2233 @EachOneChew
Hello, I tried using the training code and modified it for my dataset, where there's multiple phrases/captions for an image, but the training loop ends up giving a dimension mismatch error.

from PIL import Image
device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training.
model, preprocess = clip.load("ViT-B/32",device=device,jit=False)
class image_title_dataset(Dataset):
    def __init__(self, list_image_path, list_txt, max_caption_len=77):
        self.image_path = list_image_path
        self.tokenizer = clip.tokenize
        self.max_caption_len = max_caption_len
        self.captions = [clip.tokenize(caption) for sublist in list_txt for caption in sublist]

    def __len__(self):
        return len(self.image_path)

    def __getitem__(self, idx):
          image = preprocess(Image.open(self.image_path[idx]))
          caption = self.captions[idx]
          caption = caption.to(device)
          image = image.to(device)
          return image, caption

    def tokenize_and_pad(self, caption):
        print(caption)
        tokenized_caption = self.tokenizer(caption)
        caption_len = tokenized_caption.shape[0]
        if caption_len < self.max_caption_len:
            padding = torch.zeros((self.max_caption_len - caption_len, *tokenized_caption.shape[1:]), dtype=tokenized_caption.dtype, device=tokenized_caption.device)
            tokenized_caption = torch.cat([tokenized_caption, padding], dim=0)
        else:
            tokenized_caption = tokenized_caption[:self.max_caption_len]

        print(tokenized_caption)
        return tokenized_caption

Using the same training loop, the error I got is:
permute(sparse_coo): number of dimensions in the tensor input does not match the length of the desired ordering of dimensions i.e. input.dim() = 4 is not equal to len(dims) = 3

It also points me to encode_text, which probably means there's some text tokenization error.

Any help would be appreciated :)

<!-- gh-comment-id:1515312803 --> @mananuppadhyay commented on GitHub (Apr 19, 2023): @vinson2233 @EachOneChew Hello, I tried using the training code and modified it for my dataset, where there's multiple phrases/captions for an image, but the training loop ends up giving a dimension mismatch error. ```python from PIL import Image device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training. model, preprocess = clip.load("ViT-B/32",device=device,jit=False) class image_title_dataset(Dataset): def __init__(self, list_image_path, list_txt, max_caption_len=77): self.image_path = list_image_path self.tokenizer = clip.tokenize self.max_caption_len = max_caption_len self.captions = [clip.tokenize(caption) for sublist in list_txt for caption in sublist] def __len__(self): return len(self.image_path) def __getitem__(self, idx): image = preprocess(Image.open(self.image_path[idx])) caption = self.captions[idx] caption = caption.to(device) image = image.to(device) return image, caption def tokenize_and_pad(self, caption): print(caption) tokenized_caption = self.tokenizer(caption) caption_len = tokenized_caption.shape[0] if caption_len < self.max_caption_len: padding = torch.zeros((self.max_caption_len - caption_len, *tokenized_caption.shape[1:]), dtype=tokenized_caption.dtype, device=tokenized_caption.device) tokenized_caption = torch.cat([tokenized_caption, padding], dim=0) else: tokenized_caption = tokenized_caption[:self.max_caption_len] print(tokenized_caption) return tokenized_caption ``` Using the same training loop, the error I got is: permute(sparse_coo): number of dimensions in the tensor input does not match the length of the desired ordering of dimensions i.e. input.dim() = 4 is not equal to len(dims) = 3 It also points me to encode_text, which probably means there's some text tokenization error. Any help would be appreciated :)
Author
Owner

@one-june commented on GitHub (Apr 23, 2023):

@mananuppadhyay Hi, I had the same issue. In my case it was because there was an extra dimension in my tokenized text, ie my tokenized text had dimensions [batch_size, 1, 77] when it should be [batch_size, 77]. I could fix it by just taking the 0th index of the tokenized text within the dataset. In your case, it would be changing the tokenizing line to

tokenized_caption = self.tokenizer(caption)[0]

Hope this helps

<!-- gh-comment-id:1518921815 --> @one-june commented on GitHub (Apr 23, 2023): @mananuppadhyay Hi, I had the same issue. In my case it was because there was an extra dimension in my tokenized text, ie my tokenized text had dimensions [batch_size, 1, 77] when it should be [batch_size, 77]. I could fix it by just taking the 0th index of the tokenized text within the dataset. In your case, it would be changing the tokenizing line to tokenized_caption = self.tokenizer(caption)[0] Hope this helps
Author
Owner

@mananuppadhyay commented on GitHub (Apr 24, 2023):

@mananuppadhyay Hi, I had the same issue. In my case it was because there was an extra dimension in my tokenized text, ie my tokenized text had dimensions [batch_size, 1, 77] when it should be [batch_size, 77]. I could fix it by just taking the 0th index of the tokenized text within the dataset. In your case, it would be changing the tokenizing line to

tokenized_caption = self.tokenizer(caption)[0]

Hope this helps

thanks a lot! this worked

<!-- gh-comment-id:1520868237 --> @mananuppadhyay commented on GitHub (Apr 24, 2023): > @mananuppadhyay Hi, I had the same issue. In my case it was because there was an extra dimension in my tokenized text, ie my tokenized text had dimensions [batch_size, 1, 77] when it should be [batch_size, 77]. I could fix it by just taking the 0th index of the tokenized text within the dataset. In your case, it would be changing the tokenizing line to > > tokenized_caption = self.tokenizer(caption)[0] > > Hope this helps thanks a lot! this worked
Author
Owner

@ghost commented on GitHub (May 7, 2023):

Hi,
I tried to fine-tune the CLIP model on FGVC-Aircraft dataset. After fine-tuning, the accuracy of CLIP on the test set was 3.21. Has anyone gotten similar results when trying to fine-tune CLIP on a small dataset?

<!-- gh-comment-id:1537440070 --> @ghost commented on GitHub (May 7, 2023): Hi, I tried to fine-tune the CLIP model on FGVC-Aircraft dataset. After fine-tuning, the accuracy of CLIP on the test set was 3.21. Has anyone gotten similar results when trying to fine-tune CLIP on a small dataset?
Author
Owner

@TEnsorTHiru commented on GitHub (May 26, 2023):

@chonky-moose

@mananuppadhyay Hi, I had the same issue. In my case it was because there was an extra dimension in my tokenized text, ie my tokenized text had dimensions [batch_size, 1, 77] when it should be [batch_size, 77]. I could fix it by just taking the 0th index of the tokenized text within the dataset. In your case, it would be changing the tokenizing line to

tokenized_caption = self.tokenizer(caption)[0]

Hope this helps

I tried the same but in final batch, the loss function raises this ValueError: Expected input batch_size (4) to match target batch_size (8).. Did you face a similar error and how did you solve it. My assumption is something is mixed up with the batch dimension since we remove one dimension from tokenized text.

<!-- gh-comment-id:1564396020 --> @TEnsorTHiru commented on GitHub (May 26, 2023): @chonky-moose > @mananuppadhyay Hi, I had the same issue. In my case it was because there was an extra dimension in my tokenized text, ie my tokenized text had dimensions [batch_size, 1, 77] when it should be [batch_size, 77]. I could fix it by just taking the 0th index of the tokenized text within the dataset. In your case, it would be changing the tokenizing line to > > tokenized_caption = self.tokenizer(caption)[0] > > Hope this helps I tried the same but in final batch, the loss function raises this **ValueError: Expected input batch_size (4) to match target batch_size (8).**. Did you face a similar error and how did you solve it. My assumption is something is mixed up with the batch dimension since we remove one dimension from tokenized text.
Author
Owner

@TEnsorTHiru commented on GitHub (May 27, 2023):

Hi, I tried to fine-tune the CLIP model on FGVC-Aircraft dataset. After fine-tuning, the accuracy of CLIP on the test set was 3.21. Has anyone gotten similar results when trying to fine-tune CLIP on a small dataset?

I'm trying in my own dataset, the validation loss doesn't reduce after the first epoch that is there is no learning happening inside the model and it stays wherever it is.

<!-- gh-comment-id:1565224549 --> @TEnsorTHiru commented on GitHub (May 27, 2023): > Hi, I tried to fine-tune the CLIP model on FGVC-Aircraft dataset. After fine-tuning, the accuracy of CLIP on the test set was 3.21. Has anyone gotten similar results when trying to fine-tune CLIP on a small dataset? I'm trying in my own dataset, the validation loss doesn't reduce after the first epoch that is there is no learning happening inside the model and it stays wherever it is.
Author
Owner

@abhaydoke09 commented on GitHub (Jun 13, 2023):

Thanks for the code snippet. During training, how can we make sure to create random batches of data so that model sees different contrastive pairs in every epoch?

<!-- gh-comment-id:1588471905 --> @abhaydoke09 commented on GitHub (Jun 13, 2023): Thanks for the code snippet. During training, how can we make sure to create random batches of data so that model sees different contrastive pairs in every epoch?
Author
Owner

@vinson2233 commented on GitHub (Jun 13, 2023):

@abhaydoke09

we're talking about :

  1. things that are very different
  2. things that are similar but different
  3. things that actually the same

if you're talking between 1 and 2. this is a tradeoff. let's say we train the clip model for clothes data. we can make it super easy for CLIP to train by making sure that in each batch we only fetch 1 jacket, 1 crop top, 1 pants, 1 underwear, 1 hat, and 1 glass. all of those items are very different. but if we keep doing so, the model cannot learn more complex concepts such as "v-neck t-shirt" vs "round neck" t-shirt. One solution is curriculum learning for this problem.

but for 3rd problem, then this is your task to create the data generator so there is no >1 pair with the same label present in a batch. you cannot expect the clip to do so for you.

<!-- gh-comment-id:1588732366 --> @vinson2233 commented on GitHub (Jun 13, 2023): @abhaydoke09 we're talking about : 1. things that are very different 2. things that are similar but different 3. things that actually the same if you're talking between 1 and 2. this is a tradeoff. let's say we train the clip model for clothes data. we can make it super easy for CLIP to train by making sure that in each batch we only fetch 1 jacket, 1 crop top, 1 pants, 1 underwear, 1 hat, and 1 glass. all of those items are very different. but if we keep doing so, the model cannot learn more complex concepts such as "v-neck t-shirt" vs "round neck" t-shirt. One solution is curriculum learning for this problem. but for 3rd problem, then this is your task to create the data generator so there is no >1 pair with the same label present in a batch. you cannot expect the clip to do so for you.
Author
Owner

@abhaydoke09 commented on GitHub (Jun 15, 2023):

I found a elegant solution by adding shuffle=True in the DataLoader solved my question. train_dataloader = DataLoader(dataset, batch_size = BATCH_SIZE, shuffle=True) This makes sure that before every epoch, train data is shuffled so that pairs for contrastive learning are different in every epoch. This important because it ensures that the model does not learn from the order of training instances.

<!-- gh-comment-id:1593585594 --> @abhaydoke09 commented on GitHub (Jun 15, 2023): I found a elegant solution by adding **shuffle=True** in the DataLoader solved my question. `train_dataloader = DataLoader(dataset, batch_size = BATCH_SIZE, shuffle=True)` This makes sure that before every epoch, train data is shuffled so that pairs for contrastive learning are different in every epoch. This important because it ensures that the model does not learn from the order of training instances.
Author
Owner

@loseevaya commented on GitHub (Jun 18, 2023):

Hey!thanks for your code, now i want to use CLIP to do some test of prompt generation.
I use other model to generate a prompt (actually, just a decoder in Transformer) to replace the text_encoder in CLIP, and use CLIP image_encoder to get the image_features, i want to freeze the CLIP image_encoder and train the my own model. And the code is as follows, mostly copied from CLIP's github:

    prompt_final = prompt_model(prompt_orgin, src_list, pos_list, mask_list).squeeze()
    normalized_image_features = image_features / image_features.norm(2, dim=-1, keepdim=True) 
    # result of CLIP image_encoder

    normalized_prompt_final = prompt_final / prompt_final.norm(2, dim=-1, keepdim=True)

    similarity = (100.0 * normalized_image_features @ normalized_prompt_final.T)

    # loss function
    labels = torch.arange(args.batch_size).to(device)

    loss = criterion(similarity, labels) # nn.CrossEntropyLoss()

    logits = similarity.transpose(0, 1)
    loss1 = criterion1(logits, labels) #nn.CrossEntropyLoss()

    loss = loss1 + loss
    loss /= 2
    loss.backward()
    optimizer.step()

I use float32 but the similarity is always NaN, sometime i can train , but i find that the model is not convergencing :(
So, could you please check the code and point out my mistakes (For example, in norm or similarity)? Or get me some advice?
Thank you for your reply!!!!!!!!!!!!!!!!!!!!!

<!-- gh-comment-id:1596030996 --> @loseevaya commented on GitHub (Jun 18, 2023): Hey!thanks for your code, now i want to use CLIP to do some test of prompt generation. I use other model to generate a prompt (actually, just a decoder in Transformer) to replace the text_encoder in CLIP, and use CLIP image_encoder to get the image_features, i want to freeze the CLIP image_encoder and train the my own model. And the code is as follows, mostly copied from CLIP's github: ``` prompt_final = prompt_model(prompt_orgin, src_list, pos_list, mask_list).squeeze() normalized_image_features = image_features / image_features.norm(2, dim=-1, keepdim=True) # result of CLIP image_encoder normalized_prompt_final = prompt_final / prompt_final.norm(2, dim=-1, keepdim=True) similarity = (100.0 * normalized_image_features @ normalized_prompt_final.T) # loss function labels = torch.arange(args.batch_size).to(device) loss = criterion(similarity, labels) # nn.CrossEntropyLoss() logits = similarity.transpose(0, 1) loss1 = criterion1(logits, labels) #nn.CrossEntropyLoss() loss = loss1 + loss loss /= 2 loss.backward() optimizer.step() ``` I use float32 but the similarity is always NaN, sometime i can train , but i find that the model is not convergencing :( So, could you please check the code and point out my mistakes (For example, in norm or similarity)? Or get me some advice? Thank you for your reply!!!!!!!!!!!!!!!!!!!!!
Author
Owner

@georgefairs commented on GitHub (Jun 20, 2023):

Hi there and thanks @vinson2233 , I've tried using this implementation to fine-tune the base CLIP model with emotional faces (e.g angry, sad, etc) but the loss never seems to reduce. It may reduce slightly at the beginning but then over each iter. and epoch it just stagnates and has hardly reduced. I've tried using model.eval(), changing the LR and the weight_decay as others have suggested... to no avail! I only have three categories at the moment that I'm trialling fine-tuning with (e.g. angry, sad, neutral with associated prompts ("a photo of an angry face", "a photo of a sad face", etc.). Could the limited number of categories be affecting it?

Any further advice would be greatly appreciated.

<!-- gh-comment-id:1598592956 --> @georgefairs commented on GitHub (Jun 20, 2023): Hi there and thanks @vinson2233 , I've tried using this implementation to fine-tune the base CLIP model with emotional faces (e.g angry, sad, etc) but the loss never seems to reduce. It may reduce **slightly** at the beginning but then over each iter. and epoch it just stagnates and has hardly reduced. I've tried using model.eval(), changing the LR and the weight_decay as others have suggested... to no avail! I only have three categories at the moment that I'm trialling fine-tuning with (e.g. angry, sad, neutral with associated prompts ("a photo of an angry face", "a photo of a sad face", etc.). Could the limited number of categories be affecting it? Any further advice would be greatly appreciated.
Author
Owner

@VincentZhou7 commented on GitHub (Jul 10, 2023):

Hi. I want to know if it is the code to finetune the original CLIP on our own dataset, or train the CLIP model from scratch?

<!-- gh-comment-id:1629090795 --> @VincentZhou7 commented on GitHub (Jul 10, 2023): Hi. I want to know if it is the code to finetune the original CLIP on our own dataset, or train the CLIP model from scratch?
Author
Owner

@DuongTSon commented on GitHub (Aug 3, 2023):

@georgefairs In my case I have 4 classes and reducing the learning rate to 1e-6 has worked, the loss has been sharply reduced. If it does not work for you, I think you need more training data.

<!-- gh-comment-id:1664298540 --> @DuongTSon commented on GitHub (Aug 3, 2023): @georgefairs In my case I have 4 classes and reducing the learning rate to 1e-6 has worked, the loss has been sharply reduced. If it does not work for you, I think you need more training data.
Author
Owner

@DuongTSon commented on GitHub (Aug 3, 2023):

@VincentZhou7 this code is like fetching new batches of data into the exported checkpoint of CLIP, so it will update the weights inside the model. It's fair to say it's a finetuning code.

<!-- gh-comment-id:1664302451 --> @DuongTSon commented on GitHub (Aug 3, 2023): @VincentZhou7 this code is like fetching new batches of data into the exported checkpoint of CLIP, so it will update the weights inside the model. It's fair to say it's a finetuning code.
Author
Owner

@Benjizhang commented on GitHub (Aug 6, 2023):

Hi, thanks for your helpful codes. In my project, I have a dataset including pairs of text and another modal signal (e.g., tactile information, represented as a one-dimension vector for each tactile signal.). So, if I still use the pipeline of CLIP to align the text embedding and tactile embedding, may I ask for any suggestions or modifications for training this dataset?

<!-- gh-comment-id:1666849526 --> @Benjizhang commented on GitHub (Aug 6, 2023): Hi, thanks for your helpful codes. In my project, I have a dataset including pairs of text and another modal signal (e.g., tactile information, represented as a one-dimension vector for each tactile signal.). So, if I still use the pipeline of CLIP to align the text embedding and tactile embedding, may I ask for any suggestions or modifications for training this dataset?
Author
Owner

@xuntianci commented on GitHub (Aug 17, 2023):

@lamnt2008

Your question is very broad. What is your specific use case? If you are doing image classification, I am assuming that you have in your training dataset images paired with labels? If that is the case, you have two options as I understand:

  1. Use only CLIP's image encoder as a feature extractor and train a MLP classification head on top of it to perform classification. You may want to experiment with using lower learning rate for the CLIP image encoder and higher learning rate for the MLP head. Freezing the CLIP image encoder altogether and only training the MLP head is also a decent option for faster training on simpler classification tasks.
  2. Treat your image-label pairs as positive examples and tune CLIP using the same contrastive approach* as outlined by @vinson2233 in his code. It is probably a good idea to build prompts around your class labels (e.g. banana -> "a photo of a banana").

*For a summary of the contrastive training approach see the CLIP blog post: https://openai.com/research/clip

As for which approach is better, the most recent paper I've read suggests that 2. comes out on top: https://arxiv.org/abs/2212.00638

For that 1. ,I use the CLIP's image encoder and then add a MLP head ,make all paramters learnable, but I got a nan loss in the batch 2. when a only train the head, it will be ok.Then I located nan , the crossentropyloss returned a nan value, can you give me some advice?I would appreciate it.

<!-- gh-comment-id:1681486031 --> @xuntianci commented on GitHub (Aug 17, 2023): > @lamnt2008 > > Your question is very broad. What is your specific use case? If you are doing image classification, I am assuming that you have in your training dataset images paired with labels? If that is the case, you have two options as I understand: > > 1. Use only CLIP's image encoder as a feature extractor and train a MLP classification head on top of it to perform classification. You may want to experiment with using lower learning rate for the CLIP image encoder and higher learning rate for the MLP head. Freezing the CLIP image encoder altogether and only training the MLP head is also a decent option for faster training on simpler classification tasks. > 2. Treat your image-label pairs as positive examples and tune CLIP using the same contrastive approach* as outlined by @vinson2233 in his code. It is probably a good idea to build prompts around your class labels (e.g. banana -> "a photo of a banana"). > > *For a summary of the contrastive training approach see the CLIP blog post: https://openai.com/research/clip > > As for which approach is better, the most recent paper I've read suggests that 2. comes out on top: https://arxiv.org/abs/2212.00638 For that 1. ,I use the CLIP's image encoder and then add a MLP head ,make all paramters learnable, but I got a nan loss in the batch 2. when a only train the head, it will be ok.Then I located nan , the crossentropyloss returned a nan value, can you give me some advice?I would appreciate it.
Author
Owner

@xuntianci commented on GitHub (Aug 17, 2023):

For that 1. ,I use the CLIP's image encoder and then add a MLP head ,make all paramters learnable, but I got a nan loss in the batch 2. when a only train the head, it will be ok.Then I located nan , the crossentropyloss returned a nan value, can you give me some advice?I would appreciate it.

hey!I have a similar question.Did you solve your problem?I use the CLIP's image encoder and then add a MLP head ,make all paramters learnable, but I got a nan loss in the batch 2. when a only train the head, it will be ok.Then I located nan , the crossentropyloss returned a nan value.

<!-- gh-comment-id:1681492682 --> @xuntianci commented on GitHub (Aug 17, 2023): > For that 1. ,I use the CLIP's image encoder and then add a MLP head ,make all paramters learnable, but I got a nan loss in the batch 2. when a only train the head, it will be ok.Then I located nan , the crossentropyloss returned a nan value, can you give me some advice?I would appreciate it. hey!I have a similar question.Did you solve your problem?I use the CLIP's image encoder and then add a MLP head ,make all paramters learnable, but I got a nan loss in the batch 2. when a only train the head, it will be ok.Then I located nan , the crossentropyloss returned a nan value.
Author
Owner

@xiyangyang99 commented on GitHub (Aug 23, 2023):

@vinson2233 >
Firstly, thank you for sharing the fine-tuning code. However, after completing the fine-tuning, in my own dataset, I only fine-tuned the image encoding part, while I did not fine-tune the text encoding part. I used vit base 16 as the pre training weight, but after fine-tuning, the. pt increased by 5 times. Also, how should the. pt model generated after fine-tuning be used for inference? Looking forward to your guidance, thank you.

<!-- gh-comment-id:1689213066 --> @xiyangyang99 commented on GitHub (Aug 23, 2023): @vinson2233 > Firstly, thank you for sharing the fine-tuning code. However, after completing the fine-tuning, in my own dataset, I only fine-tuned the image encoding part, while I did not fine-tune the text encoding part. I used vit base 16 as the pre training weight, but after fine-tuning, the. pt increased by 5 times. Also, how should the. pt model generated after fine-tuning be used for inference? Looking forward to your guidance, thank you.
Author
Owner

@TaylorLi123 commented on GitHub (Sep 6, 2023):

Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. Feel free to ask or point out any mistakes in my code.

# Latest Update : 18 July 2022, 09:55 GMT+7

# TO ADD :
# Gradient Checkpointing
# Filter out bias from weight decay
# Decaying learning rate with cosine schedule
# Half-precision Adam statistics
# Half-precision stochastically rounded text encoder weights were used

#BATCH_SIZE must larger than 1

device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training.
model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training

class image_title_dataset(Dataset):
    def __init__(self, list_image_path,list_txt):

        self.image_path = list_image_path
        self.title  = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop.

    def __len__(self):
        return len(self.title)

    def __getitem__(self, idx):
        image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module
        title = self.title[idx]
        return image,title

# use your own data
list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] 
list_txt = ['description for image1.jpg' , 'description for image2.jpg']
dataset = image_title_dataset(list_image_path,list_txt)
train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader

#https://github.com/openai/CLIP/issues/57
def convert_models_to_fp32(model): 
    for p in model.parameters(): 
        p.data = p.data.float() 
        p.grad.data = p.grad.data.float() 


if device == "cpu":
  model.float()
else :
  clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16

loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset

# add your own code to track the training progress.
for epoch in range(EPOCH):
  for batch in train_dataloader :
      optimizer.zero_grad()

      images,texts = batch 
    
      images= images.to(device)
      texts = texts.to(device)
    
      logits_per_image, logits_per_text = model(images, texts)

      ground_truth = torch.arange(len(images),dtype=torch.long,device=device)

      total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2
      total_loss.backward()
      if device == "cpu":
         optimizer.step()
      else : 
        convert_models_to_fp32(model)
        optimizer.step()
        clip.model.convert_weights(model)

Code to save the model :

torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': total_loss,
        }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename

Code to load the saved model :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224
checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Alternative training code :

Thanks for sharing the fine-tuning code, but when I called the save model to test after fine-tune, the scores for each category were average. how did this happen?Looking forward to your guidance, thank you.
tensor([0.1250, 0.1250, 0.1250, 0.1250, 0.1250, 0.1250, 0.1250, 0.1250],
device='cuda:0', dtype=torch.float16)

<!-- gh-comment-id:1707836686 --> @TaylorLi123 commented on GitHub (Sep 6, 2023): > Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. Feel free to ask or point out any mistakes in my code. > > ```python > # Latest Update : 18 July 2022, 09:55 GMT+7 > > # TO ADD : > # Gradient Checkpointing > # Filter out bias from weight decay > # Decaying learning rate with cosine schedule > # Half-precision Adam statistics > # Half-precision stochastically rounded text encoder weights were used > > #BATCH_SIZE must larger than 1 > > device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training. > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > > class image_title_dataset(Dataset): > def __init__(self, list_image_path,list_txt): > > self.image_path = list_image_path > self.title = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop. > > def __len__(self): > return len(self.title) > > def __getitem__(self, idx): > image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module > title = self.title[idx] > return image,title > > # use your own data > list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] > list_txt = ['description for image1.jpg' , 'description for image2.jpg'] > dataset = image_title_dataset(list_image_path,list_txt) > train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader > > #https://github.com/openai/CLIP/issues/57 > def convert_models_to_fp32(model): > for p in model.parameters(): > p.data = p.data.float() > p.grad.data = p.grad.data.float() > > > if device == "cpu": > model.float() > else : > clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16 > > loss_img = nn.CrossEntropyLoss() > loss_txt = nn.CrossEntropyLoss() > optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset > > # add your own code to track the training progress. > for epoch in range(EPOCH): > for batch in train_dataloader : > optimizer.zero_grad() > > images,texts = batch > > images= images.to(device) > texts = texts.to(device) > > logits_per_image, logits_per_text = model(images, texts) > > ground_truth = torch.arange(len(images),dtype=torch.long,device=device) > > total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 > total_loss.backward() > if device == "cpu": > optimizer.step() > else : > convert_models_to_fp32(model) > optimizer.step() > clip.model.convert_weights(model) > ``` > > * NOTE : > > * that for inference purpose, the conversion step from fp16 to fp32 is not needed, just use the model in full fp16 > * For multi-GPU training, see my comment on [how to use multiple GPUs,the default is to use the first CUDA device #111 (comment)](https://github.com/openai/CLIP/issues/111#issuecomment-854320770) > * I'm not the author of this model nor having any relationship with the author. I'm just a random guy who interested in CLIP. > * For training image-image or text-text, please refer to this principle : [CLIP Training Code #83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-1487820198) > * What is the difference between image loss and text loss? isn't one just a transposed version of the other one? read this then [CLIP Training Code #83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-1489603702) > * Why the ground truth is torch.arange? [CLIP Training Code #83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-1141139017) > > Code to save the model : > > ```python > torch.save({ > 'epoch': epoch, > 'model_state_dict': model.state_dict(), > 'optimizer_state_dict': optimizer.state_dict(), > 'loss': total_loss, > }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename > ``` > > Code to load the saved model : > > ```python > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > checkpoint = torch.load("model_checkpoint/model_10.pt") > > # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] > checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224 > checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77 > checkpoint['model_state_dict']["vocab_size"] = model.vocab_size > > model.load_state_dict(checkpoint['model_state_dict']) > ``` > > Alternative training code : > > * @Zasder3 have created a PyTorch lighting version to train the CLIP https://github.com/Zasder3/train-CLIP > * @mitchellnw researchers at UW, Google, Stanford, Amazon, Columbia, and Berkeley also create their training code https://github.com/mlfoundations/open_clip Thanks for sharing the fine-tuning code, but when I called the save model to test after fine-tune, the scores for each category were average. how did this happen?Looking forward to your guidance, thank you. tensor([0.1250, 0.1250, 0.1250, 0.1250, 0.1250, 0.1250, 0.1250, 0.1250], device='cuda:0', dtype=torch.float16)
Author
Owner

@xiyangyang99 commented on GitHub (Sep 14, 2023):

@TaylorLi123
What is your dataset like? How many datasets are there? My dataset is very small, and I trained it to be the same as you. The final output value is the same.

<!-- gh-comment-id:1719070092 --> @xiyangyang99 commented on GitHub (Sep 14, 2023): @TaylorLi123 What is your dataset like? How many datasets are there? My dataset is very small, and I trained it to be the same as you. The final output value is the same.
Author
Owner

@TaylorLi123 commented on GitHub (Sep 14, 2023):

@QzYER
My dataset contains over 20,000 images
picture format:
-- images
--00001.jpg
--00002.jpg
description text:
--caption.txt
--description for image1.jpg
--description for image2.jpg

<!-- gh-comment-id:1719107683 --> @TaylorLi123 commented on GitHub (Sep 14, 2023): > @QzYER My dataset contains over 20,000 images picture format: -- images --00001.jpg --00002.jpg description text: --caption.txt --description for image1.jpg --description for image2.jpg
Author
Owner

@TaylorLi123 commented on GitHub (Sep 16, 2023):

@vinson2233
How do I output the evaluation indicators accuracy, precision, recall, and F1 during the training process? Does anyone have these indicators equal

<!-- gh-comment-id:1722074667 --> @TaylorLi123 commented on GitHub (Sep 16, 2023): @vinson2233 How do I output the evaluation indicators accuracy, precision, recall, and F1 during the training process? Does anyone have these indicators equal
Author
Owner

@p1k0pan commented on GitHub (Oct 27, 2023):

Hi @vinson2233 thanks a lot for sharing your code! If I understand well you never set the model in training phase model.train(). Do you do that on purpose to freeze dropout and batchnorm layers during fine-tuning? And second questions, do you have any ideas about good metrics to keep track of during evaluation to understand if fine-tuning is running fine (validation loss apart)?

I have checked the architechture with printing out the state_dict from the model which loaded by clip.load(). I found there are no Dropout layer in the model, although it is a standard layer from a standard ViT and Transformer. Does it mean the model is not complete and not suffient to do fine-tunning?

<!-- gh-comment-id:1782593249 --> @p1k0pan commented on GitHub (Oct 27, 2023): > Hi @vinson2233 thanks a lot for sharing your code! If I understand well you never set the model in training phase `model.train()`. Do you do that on purpose to freeze dropout and batchnorm layers during fine-tuning? And second questions, do you have any ideas about good metrics to keep track of during evaluation to understand if fine-tuning is running fine (validation loss apart)? I have checked the architechture with printing out the `state_dict` from the model which loaded by `clip.load()`. I found there are no Dropout layer in the model, although it is a standard layer from a standard ViT and Transformer. Does it mean the model is not complete and not suffient to do fine-tunning?
Author
Owner

@IliasParas13 commented on GitHub (Nov 5, 2023):

Where can I find a dataset with texts?

<!-- gh-comment-id:1793774058 --> @IliasParas13 commented on GitHub (Nov 5, 2023): Where can I find a dataset with texts?
Author
Owner

@keshavsharma347 commented on GitHub (Dec 15, 2023):

@uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do :

  1. Change the ground_truth = torch.arange(BATCH_SIZE).to(device) to integer vector that specify which class your image are on (for example torch.tensor([0,1,2,1,2,3,4,5])). With this now you can set your batch size in arbitrary size.
  2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 to total_loss = loss_img(logits_per_image,ground_truth)

I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image"

Thank you for your reply and advice, I will try it soon! By "After fine-tuning, the model outputs sample feature for every image", I mean that, with "image_features = model.encode_image(image_input)" I print this "image_features" and get image_features: tensor([ [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], ..., [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039]]) while the original model outputs: image_features: tensor([ [ 0.0304, -0.0169, -0.0383, ..., 0.0927, 0.0261, 0.0203], [ 0.0013, -0.0067, -0.0524, ..., 0.1029, 0.0028, 0.0169], [ 0.0115, -0.0006, -0.0392, ..., 0.0616, 0.0317, 0.0171], ..., [ 0.0173, -0.0152, -0.0431, ..., 0.0836, 0.0405, 0.0268], [ 0.0287, -0.0236, -0.0401, ..., 0.0856, 0.0119, 0.0287], [ 0.0150, 0.0013, -0.0537, ..., 0.0792, 0.0104, 0.0062]]) After fine-tuning, the features become same and smaller so I get identical and large logits(like 99.8856) for every image😢.

Were you able to finetune for classification task?? If so can you provide some reference. I have my dataset as image, caption and class it belongs to..

<!-- gh-comment-id:1857293305 --> @keshavsharma347 commented on GitHub (Dec 15, 2023): > > @uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do : > > > > 1. Change the ` ground_truth = torch.arange(BATCH_SIZE).to(device)` to integer vector that specify which class your image are on (for example `torch.tensor([0,1,2,1,2,3,4,5])`). With this now you can set your batch size in arbitrary size. > > 2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the ` total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2` to `total_loss = loss_img(logits_per_image,ground_truth) ` > > > > I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image" > > Thank you for your reply and advice, I will try it soon! By "After fine-tuning, the model outputs sample feature for every image", I mean that, with "image_features = model.encode_image(image_input)" I print this "image_features" and get image_features: tensor([ [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], ..., [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039], [ 0.0098, 0.0047, 0.0057, ..., 0.0018, 0.0056, -0.0039]]) while the original model outputs: image_features: tensor([ [ 0.0304, -0.0169, -0.0383, ..., 0.0927, 0.0261, 0.0203], [ 0.0013, -0.0067, -0.0524, ..., 0.1029, 0.0028, 0.0169], [ 0.0115, -0.0006, -0.0392, ..., 0.0616, 0.0317, 0.0171], ..., [ 0.0173, -0.0152, -0.0431, ..., 0.0836, 0.0405, 0.0268], [ 0.0287, -0.0236, -0.0401, ..., 0.0856, 0.0119, 0.0287], [ 0.0150, 0.0013, -0.0537, ..., 0.0792, 0.0104, 0.0062]]) After fine-tuning, the features become same and smaller so I get identical and large logits(like 99.8856) for every image😢. Were you able to finetune for classification task?? If so can you provide some reference. I have my dataset as image, caption and class it belongs to..
Author
Owner

@Dinosaurcubs commented on GitHub (Dec 26, 2023):

Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. Feel free to ask or point out any mistakes in my code.

# Latest Update : 18 July 2022, 09:55 GMT+7

# TO ADD :
# Gradient Checkpointing
# Filter out bias from weight decay
# Decaying learning rate with cosine schedule
# Half-precision Adam statistics
# Half-precision stochastically rounded text encoder weights were used

#BATCH_SIZE must larger than 1

device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training.
model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training

class image_title_dataset(Dataset):
    def __init__(self, list_image_path,list_txt):

        self.image_path = list_image_path
        self.title  = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop.

    def __len__(self):
        return len(self.title)

    def __getitem__(self, idx):
        image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module
        title = self.title[idx]
        return image,title

# use your own data
list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] 
list_txt = ['description for image1.jpg' , 'description for image2.jpg']
dataset = image_title_dataset(list_image_path,list_txt)
train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader

#https://github.com/openai/CLIP/issues/57
def convert_models_to_fp32(model): 
    for p in model.parameters(): 
        p.data = p.data.float() 
        p.grad.data = p.grad.data.float() 


if device == "cpu":
  model.float()
else :
  clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16

loss_img = nn.CrossEntropyLoss()
loss_txt = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset

# add your own code to track the training progress.
for epoch in range(EPOCH):
  for batch in train_dataloader :
      optimizer.zero_grad()

      images,texts = batch 
    
      images= images.to(device)
      texts = texts.to(device)
    
      logits_per_image, logits_per_text = model(images, texts)

      ground_truth = torch.arange(len(images),dtype=torch.long,device=device)

      total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2
      total_loss.backward()
      if device == "cpu":
         optimizer.step()
      else : 
        convert_models_to_fp32(model)
        optimizer.step()
        clip.model.convert_weights(model)

Code to save the model :

torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': total_loss,
        }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename

Code to load the saved model :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224
checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Alternative training code :

Really nice reply. I am trying to borrow the image encoder part of the CLIP and finetune the encoder only, because I plan to use it as a feature extraction part of my own model. For detail, I am trying to add some parameters in it and only train the params, but I donnot know how to split the visual encoder part from CLIP and modify it, can u provide some guide? tks

<!-- gh-comment-id:1869215599 --> @Dinosaurcubs commented on GitHub (Dec 26, 2023): > Not really an issue, I just want to share my training code since some people still have some difficulties to write the training code. Just modify the code to suit your usage. Feel free to ask or point out any mistakes in my code. > > ```python > # Latest Update : 18 July 2022, 09:55 GMT+7 > > # TO ADD : > # Gradient Checkpointing > # Filter out bias from weight decay > # Decaying learning rate with cosine schedule > # Half-precision Adam statistics > # Half-precision stochastically rounded text encoder weights were used > > #BATCH_SIZE must larger than 1 > > device = "cuda:0" if torch.cuda.is_available() else "cpu" # If using GPU then use mixed precision training. > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > > class image_title_dataset(Dataset): > def __init__(self, list_image_path,list_txt): > > self.image_path = list_image_path > self.title = clip.tokenize(list_txt) #you can tokenize everything at once in here(slow at the beginning), or tokenize it in the training loop. > > def __len__(self): > return len(self.title) > > def __getitem__(self, idx): > image = preprocess(Image.open(self.image_path[idx])) # Image from PIL module > title = self.title[idx] > return image,title > > # use your own data > list_image_path = ['folder/image1.jpg','folder2/image2.jpg'] > list_txt = ['description for image1.jpg' , 'description for image2.jpg'] > dataset = image_title_dataset(list_image_path,list_txt) > train_dataloader = DataLoader(dataset,batch_size = BATCH_SIZE) #Define your own dataloader > > #https://github.com/openai/CLIP/issues/57 > def convert_models_to_fp32(model): > for p in model.parameters(): > p.data = p.data.float() > p.grad.data = p.grad.data.float() > > > if device == "cpu": > model.float() > else : > clip.model.convert_weights(model) # Actually this line is unnecessary since clip by default already on float16 > > loss_img = nn.CrossEntropyLoss() > loss_txt = nn.CrossEntropyLoss() > optimizer = optim.Adam(model.parameters(), lr=5e-5,betas=(0.9,0.98),eps=1e-6,weight_decay=0.2) #Params used from paper, the lr is smaller, more safe for fine tuning to new dataset > > # add your own code to track the training progress. > for epoch in range(EPOCH): > for batch in train_dataloader : > optimizer.zero_grad() > > images,texts = batch > > images= images.to(device) > texts = texts.to(device) > > logits_per_image, logits_per_text = model(images, texts) > > ground_truth = torch.arange(len(images),dtype=torch.long,device=device) > > total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 > total_loss.backward() > if device == "cpu": > optimizer.step() > else : > convert_models_to_fp32(model) > optimizer.step() > clip.model.convert_weights(model) > ``` > > * NOTE : > > * that for inference purpose, the conversion step from fp16 to fp32 is not needed, just use the model in full fp16 > * For multi-GPU training, see my comment on [how to use multiple GPUs,the default is to use the first CUDA device #111 (comment)](https://github.com/openai/CLIP/issues/111#issuecomment-854320770) > * I'm not the author of this model nor having any relationship with the author. I'm just a random guy who interested in CLIP. > * For training image-image or text-text, please refer to this principle : [CLIP Training Code #83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-1487820198) > * What is the difference between image loss and text loss? isn't one just a transposed version of the other one? read this then [CLIP Training Code #83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-1489603702) > * Why the ground truth is torch.arange? [CLIP Training Code #83 (comment)](https://github.com/openai/CLIP/issues/83#issuecomment-1141139017) > > Code to save the model : > > ```python > torch.save({ > 'epoch': epoch, > 'model_state_dict': model.state_dict(), > 'optimizer_state_dict': optimizer.state_dict(), > 'loss': total_loss, > }, f"model_checkpoint/model_10.pt") #just change to your preferred folder/filename > ``` > > Code to load the saved model : > > ```python > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) #Must set jit=False for training > checkpoint = torch.load("model_checkpoint/model_10.pt") > > # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] > checkpoint['model_state_dict']["input_resolution"] = model.input_resolution #default is 224 > checkpoint['model_state_dict']["context_length"] = model.context_length # default is 77 > checkpoint['model_state_dict']["vocab_size"] = model.vocab_size > > model.load_state_dict(checkpoint['model_state_dict']) > ``` > > Alternative training code : > > * @Zasder3 have created a PyTorch lighting version to train the CLIP https://github.com/Zasder3/train-CLIP > * @mitchellnw researchers at UW, Google, Stanford, Amazon, Columbia, and Berkeley also create their training code https://github.com/mlfoundations/open_clip Really nice reply. I am trying to borrow the image encoder part of the CLIP and finetune the encoder only, because I plan to use it as a feature extraction part of my own model. For detail, I am trying to add some parameters in it and only train the params, but I donnot know how to split the visual encoder part from CLIP and modify it, can u provide some guide? tks
Author
Owner

@deadpipe commented on GitHub (Dec 28, 2023):

@uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do :

  1. Change the ground_truth = torch.arange(BATCH_SIZE).to(device) to integer vector that specify which class your image are on (for example torch.tensor([0,1,2,1,2,3,4,5])). With this now you can set your batch size in arbitrary size.
  2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2 to total_loss = loss_img(logits_per_image,ground_truth)

I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image"

Hi

Can you please explain the first point you mentioned? Actually i want to fine tune clip for multi labelled image classification where one image may belong to multiple classes

<!-- gh-comment-id:1871300485 --> @deadpipe commented on GitHub (Dec 28, 2023): > @uplusv If you want to modify CLIP as a classifier(Single label, multi class), here's some modification you can do : > > 1. Change the ` ground_truth = torch.arange(BATCH_SIZE).to(device)` to integer vector that specify which class your image are on (for example `torch.tensor([0,1,2,1,2,3,4,5])`). With this now you can set your batch size in arbitrary size. > 2. One image should match 1 label, but 1 label can match will multiple images. You can omit the loss_txt in the ` total_loss = (loss_img(logits_per_image,ground_truth) + loss_txt(logits_per_text,ground_truth))/2` to `total_loss = loss_img(logits_per_image,ground_truth) ` > > I'm not sure what you meant by "After fine-tuning, the model outputs sample feature for every image" Hi Can you please explain the first point you mentioned? Actually i want to fine tune clip for multi labelled image classification where one image may belong to multiple classes
Author
Owner

@ItzHaad commented on GitHub (Jan 7, 2024):

Hi, if you could clarify why is that we are using torch arrange, suppose that data is randomly shuffled after every epoch, we will have image pairs at different positions every time, so essentially we are not learning anything apart from position (which is also changing every time and that too randomly), instead this approach makes alot more sense https://github.com/moein-shariatnia/OpenAI-CLIP (with the projection head). Since, we are going to a common representation between image and text embeddings.

<!-- gh-comment-id:1880152281 --> @ItzHaad commented on GitHub (Jan 7, 2024): Hi, if you could clarify why is that we are using torch arrange, suppose that data is randomly shuffled after every epoch, we will have image pairs at different positions every time, so essentially we are not learning anything apart from position (which is also changing every time and that too randomly), instead this approach makes alot more sense https://github.com/moein-shariatnia/OpenAI-CLIP (with the projection head). Since, we are going to a common representation between image and text embeddings.
Author
Owner

@vinson2233 commented on GitHub (Jan 7, 2024):

@ItzHaad I can give you 2 answers:

  1. actual answer
    you shuffle the pair of the data instead of shuffling the image and text independently. that's how you retain the labels.
    let say the original data is (Image1, Text1), (Image2, Text2), (Image3, Text3)
    it will make no difference if you shuffle the data so the order becomes like this (Image2, Text2), (Image3, Text3), (Image1, Text1)

  2. lazy answer : that is what is presented in the paper (read Figure 3 of the paper)

<!-- gh-comment-id:1880160725 --> @vinson2233 commented on GitHub (Jan 7, 2024): @ItzHaad I can give you 2 answers: 1. actual answer you shuffle the **pair of the data instead of shuffling the image and text independently**. that's how you retain the labels. let say the original data is (Image1, Text1), (Image2, Text2), (Image3, Text3) it will make no difference if you shuffle the data so the order becomes like this (Image2, Text2), (Image3, Text3), (Image1, Text1) 2. lazy answer : that is what is presented in the paper (read Figure 3 of the paper)
Author
Owner

@Heathcliff-saku commented on GitHub (Jan 17, 2024):

Hi!@vinson2233
Thank you very much for your training script. In my code, I have adopted your dataset method. However, my dataset is quite large (about 2 million img-text pairs), which has led to an unusual phenomenon during training: at the start of each epoch, specifically during the loading of the first batch, there is a prolonged delay (approximately 30 to 40 minutes), and the GPU utilization remains at 0%. Have you encountered this issue before? Is this normal? Do you have any recommended solutions to mitigate this?
PS. I have set an appropriate number of workers and enabled pin memory, but this waiting time still seems unavoidable.

<!-- gh-comment-id:1895693721 --> @Heathcliff-saku commented on GitHub (Jan 17, 2024): Hi!@vinson2233 Thank you very much for your training script. In my code, I have adopted your dataset method. However, my dataset is quite large (about 2 million img-text pairs), which has led to an unusual phenomenon during training: **at the start of each epoch, specifically during the loading of the first batch, there is a prolonged delay (approximately 30 to 40 minutes), and the GPU utilization remains at 0%.** Have you encountered this issue before? Is this normal? Do you have any recommended solutions to mitigate this? PS. I have set an appropriate number of workers and enabled pin memory, but this waiting time still seems unavoidable.
Author
Owner

@vinson2233 commented on GitHub (Jan 17, 2024):

@Heathcliff-saku its expected because how the dataset object created. if you don't want huge overhead in the front, another way is to do the image preprocess and clip tokenize after the data produced by data loader, but this will create redundancy in every epoch.

If anyone can give recommendations as well then feel free to do so since i don't use CLIP anymore

<!-- gh-comment-id:1895759895 --> @vinson2233 commented on GitHub (Jan 17, 2024): @Heathcliff-saku its expected because how the dataset object created. if you don't want huge overhead in the front, another way is to do the image preprocess and clip tokenize after the data produced by data loader, but this will create redundancy in every epoch. If anyone can give recommendations as well then feel free to do so since i don't use CLIP anymore
Author
Owner

@manas6266 commented on GitHub (Feb 3, 2024):

How many epochs does clip need to be finetuned and what should be batch size??

<!-- gh-comment-id:1925068359 --> @manas6266 commented on GitHub (Feb 3, 2024): How many epochs does clip need to be finetuned and what should be batch size??
Author
Owner

@anas2908 commented on GitHub (Mar 3, 2024):

ell In[13], line 64, in image_title_dataset.getitem(self, idx)
63 def getitem(self, idx):
---> 64 image_path = self.image_path[idx] # Get the image path at the specified index
65 image = preprocess(Image.open(image_path)) # Open the image using PIL
66 title = self.title[idx] # Get the title corresponding to the image

TypeError: list indices must be integers or slices, not list

is there any problem in my dataloader i am using from torch.utils.data import DataLoader
i am stucked can you please help me?

<!-- gh-comment-id:1975380215 --> @anas2908 commented on GitHub (Mar 3, 2024): ell In[13], line 64, in image_title_dataset.__getitem__(self, idx) 63 def __getitem__(self, idx): ---> 64 image_path = self.image_path[idx] # Get the image path at the specified index 65 image = preprocess(Image.open(image_path)) # Open the image using PIL 66 title = self.title[idx] # Get the title corresponding to the image TypeError: list indices must be integers or slices, not list is there any problem in my dataloader i am using from torch.utils.data import DataLoader i am stucked can you please help me?
Author
Owner

@anas2908 commented on GitHub (Mar 3, 2024):

Hi!@vinson2233 Thank you very much for your training script. In my code, I have adopted your dataset method. However, my dataset is quite large (about 2 million img-text pairs), which has led to an unusual phenomenon during training: at the start of each epoch, specifically during the loading of the first batch, there is a prolonged delay (approximately 30 to 40 minutes), and the GPU utilization remains at 0%. Have you encountered this issue before? Is this normal? Do you have any recommended solutions to mitigate this? PS. I have set an appropriate number of workers and enabled pin memory, but this waiting time still seems unavoidable.

hey can you share me your code

<!-- gh-comment-id:1975401860 --> @anas2908 commented on GitHub (Mar 3, 2024): > Hi!@vinson2233 Thank you very much for your training script. In my code, I have adopted your dataset method. However, my dataset is quite large (about 2 million img-text pairs), which has led to an unusual phenomenon during training: **at the start of each epoch, specifically during the loading of the first batch, there is a prolonged delay (approximately 30 to 40 minutes), and the GPU utilization remains at 0%.** Have you encountered this issue before? Is this normal? Do you have any recommended solutions to mitigate this? PS. I have set an appropriate number of workers and enabled pin memory, but this waiting time still seems unavoidable. hey can you share me your code
Author
Owner

@BaochaoZhu commented on GitHub (Mar 11, 2024):

@vinson2233 ,Hi, I would like to train CLIP with my own custom datasets. Can you please advise me on how many images I need to prepare per class? Thank you.

<!-- gh-comment-id:1987535023 --> @BaochaoZhu commented on GitHub (Mar 11, 2024): @vinson2233 ,Hi, I would like to train CLIP with my own custom datasets. Can you please advise me on how many images I need to prepare per class? Thank you.
Author
Owner

@lalit-pivotchain commented on GitHub (Mar 15, 2024):

@lonngxiang i have update the code for save and load, basically to load the model use this code :

model, preprocess = clip.load("ViT-B/32",device=device,jit=False) 
checkpoint = torch.load("model_checkpoint/model_10.pt")

# Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] 
checkpoint['model_state_dict']["input_resolution"] = model.input_resolution 
checkpoint['model_state_dict']["context_length"] = model.context_length
checkpoint['model_state_dict']["vocab_size"] = model.vocab_size 

model.load_state_dict(checkpoint['model_state_dict'])

Just modify the dict key to match your dict key when saving to .pt file

i implemented the above code to load the saved model(.pt) , but i encountered this error
AttributeError: 'CLIP' object has no attribute 'input_resolution'

<!-- gh-comment-id:1999052662 --> @lalit-pivotchain commented on GitHub (Mar 15, 2024): > @lonngxiang i have update the code for save and load, basically to load the model use this code : > > ```python > model, preprocess = clip.load("ViT-B/32",device=device,jit=False) > checkpoint = torch.load("model_checkpoint/model_10.pt") > > # Use these 3 lines if you use default model setting(not training setting) of the clip. For example, if you set context_length to 100 since your string is very long during training, then assign 100 to checkpoint['model_state_dict']["context_length"] > checkpoint['model_state_dict']["input_resolution"] = model.input_resolution > checkpoint['model_state_dict']["context_length"] = model.context_length > checkpoint['model_state_dict']["vocab_size"] = model.vocab_size > > model.load_state_dict(checkpoint['model_state_dict']) > ``` > > Just modify the dict key to match your dict key when saving to .pt file i implemented the above code to load the saved model(.pt) , but i encountered this error AttributeError: 'CLIP' object has no attribute 'input_resolution'
Author
Owner

@Shadedog838 commented on GitHub (Apr 21, 2024):

I have implemented the training code above and have been trying to train the model on the Flickr dataset but my loss keeps increasing until it eventually stays the the same I don't know what the problem is can anyone provide some insight?

<!-- gh-comment-id:2068134524 --> @Shadedog838 commented on GitHub (Apr 21, 2024): I have implemented the training code above and have been trying to train the model on the Flickr dataset but my loss keeps increasing until it eventually stays the the same I don't know what the problem is can anyone provide some insight?
Author
Owner

@seidasoeun commented on GitHub (Apr 27, 2024):

ell In[13], line 64, in image_title_dataset.getitem(self, idx) 63 def getitem(self, idx): ---> 64 image_path = self.image_path[idx] # Get the image path at the specified index 65 image = preprocess(Image.open(image_path)) # Open the image using PIL 66 title = self.title[idx] # Get the title corresponding to the image

TypeError: list indices must be integers or slices, not list

is there any problem in my dataloader i am using from torch.utils.data import DataLoader i am stucked can you please help me?

you just fix your code like below

from torch.utils.data import Dataset

<!-- gh-comment-id:2080435391 --> @seidasoeun commented on GitHub (Apr 27, 2024): > ell In[13], line 64, in image_title_dataset.**getitem**(self, idx) 63 def **getitem**(self, idx): ---> 64 image_path = self.image_path[idx] # Get the image path at the specified index 65 image = preprocess(Image.open(image_path)) # Open the image using PIL 66 title = self.title[idx] # Get the title corresponding to the image > > TypeError: list indices must be integers or slices, not list > > is there any problem in my dataloader i am using from torch.utils.data import DataLoader i am stucked can you please help me? you just fix your code like below ``` from torch.utils.data import Dataset ```
Author
Owner

@nightrain-vampire commented on GitHub (May 10, 2024):

@lonngxiang Hmmmm, I don't have the faintest idea why the loss is = 0.

BATCH_SIZE is just an integer that you set. Since the image-text are in pairs, the first image will correspond to the first text. So the ground truth for the first image is 0, the second image will correspond to the second image, so the ground truth is 1. This pattern keeps repeating until the last image-text pair. So the ground truth is a torch tensor like this : torch.tensor([0,1,2,3,...,BATCH_SIZE-1]). Since the pre-trained CLIP use a massive batch size, just try to use the largest BATCH_SIZE as your system can take.

You can read more info about cross-entropy loss https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html, especially about the target. Also the CLIP paper, page 5, the upper left part.

Hello,I set the Batch Size as 64,and my total loss is always 4.02734375 during the training;I don't know what the problem is can anyone provide some insight?

<!-- gh-comment-id:2104500913 --> @nightrain-vampire commented on GitHub (May 10, 2024): > @lonngxiang Hmmmm, I don't have the faintest idea why the loss is = 0. > > BATCH_SIZE is just an integer that you set. Since the image-text are in pairs, the first image will correspond to the first text. So the ground truth for the first image is 0, the second image will correspond to the second image, so the ground truth is 1. This pattern keeps repeating until the last image-text pair. So the ground truth is a torch tensor like this : `torch.tensor([0,1,2,3,...,BATCH_SIZE-1])`. Since the pre-trained CLIP use a massive batch size, just try to use the largest BATCH_SIZE as your system can take. > > You can read more info about cross-entropy loss https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html, especially about the target. Also the CLIP paper, page 5, the upper left part. Hello,I set the Batch Size as 64,and my total loss is always 4.02734375 during the training;I don't know what the problem is can anyone provide some insight?
Author
Owner

@pengzhao-life commented on GitHub (Oct 3, 2024):

@vinson2233
Thanks for sharing the code! I am trying to finetune clip model on my own dataset. My data has multiple texts per image. I wonder what the typical solution is to handle multiple texts per image. My understanding is that I need to create each ground truth label to ensure the positive relationship between the image and its every single text. Otherwise, they may be considered as negative pair during the training. Is this correct? Any sample code or post related to this concern?

My second question is that my texts may include image captions, keywords, categories, etc. Should I handle them differently? Many thanks!

<!-- gh-comment-id:2392233032 --> @pengzhao-life commented on GitHub (Oct 3, 2024): @vinson2233 Thanks for sharing the code! I am trying to finetune clip model on my own dataset. My data has multiple texts per image. I wonder what the typical solution is to handle multiple texts per image. My understanding is that I need to create each ground truth label to ensure the positive relationship between the image and its every single text. Otherwise, they may be considered as negative pair during the training. Is this correct? Any sample code or post related to this concern? My second question is that my texts may include image captions, keywords, categories, etc. Should I handle them differently? Many thanks!
Author
Owner

@Himanshunitrr commented on GitHub (Dec 30, 2024):

In the paper they multiply the logits with a exponential of temperature too which I dont see here ?

<!-- gh-comment-id:2565921236 --> @Himanshunitrr commented on GitHub (Dec 30, 2024): In the paper they multiply the logits with a exponential of temperature too which I dont see here ?
Author
Owner

@tengshaofeng commented on GitHub (Feb 10, 2025):

@vinson2233 @jongwook @ThakurRajAnand @nightrain-vampire @pengzhao-life Dears, thanks so much for your useful talking. I have a new question.Because I have only one 4090 card, so the max batch_size for me is 5. It is so small,dose it affect the traing performence?

<!-- gh-comment-id:2647109887 --> @tengshaofeng commented on GitHub (Feb 10, 2025): @vinson2233 @jongwook @ThakurRajAnand @nightrain-vampire @pengzhao-life Dears, thanks so much for your useful talking. I have a new question.Because I have only one 4090 card, so the max batch_size for me is 5. It is so small,dose it affect the traing performence?
Author
Owner

@Fadela commented on GitHub (Mar 10, 2025):

hi how about training using LoRA? any resources?

<!-- gh-comment-id:2711761469 --> @Fadela commented on GitHub (Mar 10, 2025): hi how about training using LoRA? any resources?
Author
Owner

@t00350320 commented on GitHub (Mar 24, 2025):

what "ground_truth = torch.arange(len(images),dtype=torch.long,device=device)" make sense?
"ground_truth" seems a meaningless tensor? have no ide ...

<!-- gh-comment-id:2746797679 --> @t00350320 commented on GitHub (Mar 24, 2025): what "ground_truth = torch.arange(len(images),dtype=torch.long,device=device)" make sense? "ground_truth" seems a meaningless tensor? have no ide ...
Author
Owner

@Himanshunitrr commented on GitHub (Mar 24, 2025):

It’s contrastive loss, so every item is GT for itself (we want to pull them together)

<!-- gh-comment-id:2746800727 --> @Himanshunitrr commented on GitHub (Mar 24, 2025): It’s contrastive loss, so every item is GT for itself (we want to pull them together)
Author
Owner

@t00350320 commented on GitHub (Mar 24, 2025):

It’s contrastive loss, so every item is GT for itself (we want to pull them together)

i tested when batch_size=4,then the GT

ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')

batch_size=32,then the GT

ground_truth: tensor([0, 1, 2, 3,...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')

So "loss_img(logits_per_image,ground_truth) " do what kind of loss with stable ground_truth value? What message should I learn if I want to know the role of "ground_truth" in CrossEntryLoss?
and I find the loss value always print a stable value after many epoch times,"train Loss: 0.1032".
Does this training process make sense for CLIP's parameters training ? Any one have a better practice? Thanks a lot

<!-- gh-comment-id:2747360472 --> @t00350320 commented on GitHub (Mar 24, 2025): > It’s contrastive loss, so every item is GT for itself (we want to pull them together) i tested when batch_size=4,then the GT ``` ground_truth: tensor([0, 1, 2, 3], device='cuda:0') ground_truth: tensor([0, 1, 2, 3], device='cuda:0') ground_truth: tensor([0, 1, 2, 3], device='cuda:0') ground_truth: tensor([0, 1, 2, 3], device='cuda:0') ground_truth: tensor([0, 1, 2, 3], device='cuda:0') ``` batch_size=32,then the GT ``` ground_truth: tensor([0, 1, 2, 3,...,31], device='cuda:0') ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') ``` So "loss_img(logits_per_image,ground_truth) " do what kind of loss with stable ground_truth value? What message should I learn if I want to know the role of "ground_truth" in CrossEntryLoss? and I find the loss value always print a stable value after many epoch times,"train Loss: 0.1032". Does this training process make sense for CLIP's parameters training ? Any one have a better practice? Thanks a lot
Author
Owner

@tengshaofeng commented on GitHub (Mar 25, 2025):

@jongwook @ThakurRajAnand @cucumberguagua @uahsan3 @Zasder3 dear all, I have written a full training code for finetuning jina-clip-v2. It can surport 8192 tokens for text. Everything is ok.Code is here @ https://github.com/tengshaofeng/finetune-jina-clip-v2.

<!-- gh-comment-id:2751000502 --> @tengshaofeng commented on GitHub (Mar 25, 2025): @jongwook @ThakurRajAnand @cucumberguagua @uahsan3 @Zasder3 dear all, I have written a full training code for finetuning jina-clip-v2. It can surport 8192 tokens for text. Everything is ok.Code is here @ https://github.com/tengshaofeng/finetune-jina-clip-v2.
Author
Owner

@t00350320 commented on GitHub (Mar 26, 2025):

It’s contrastive loss, so every item is GT for itself (we want to pull them together)

i tested when batch_size=4,then the GT

ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3], device='cuda:0')

batch_size=32,then the GT

ground_truth: tensor([0, 1, 2, 3,...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')
ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0')

So "loss_img(logits_per_image,ground_truth) " do what kind of loss with stable ground_truth value? What message should I learn if I want to know the role of "ground_truth" in CrossEntryLoss? and I find the loss value always print a stable value after many epoch times,"train Loss: 0.1032". Does this training process make sense for CLIP's parameters training ? Any one have a better practice? Thanks a lot

for "ground_truth value" ,

  1. logits_per_image
    we start from logits_per_image. It produced by
logits_per_image, logits_per_text = clip(images, label_tokens)

then from openai CLIP code we know logits_per_image = image_features(batch_size,512) @text_features.t(512,batch_size)=[batch_size,batch_size]
2. loss_img
as loss_img is nn.CrossEntropyLoss(), it actually work like this

asume batch_size = 3
 logits_per_image= torch.tensor([
                       [2.0, 1.0, 0.1],  
                       [0.5, 2.0, 0.3],
                       [0.5, 2.0, 27]]
                 )
ground_truth= torch.tensor([0,1,2])       

# sample loss for every ground truth:
# sample 1 loss:0.417?
# sample 2 loss:
#   Softmax:[e^0.5/(e^0.5+e^2.0+e^0.3)≈0.158, e^2.0/(...)=0.711, e^0.3/(...)=0.133]
#   pay attention to 2.0 :-log(0.711)≈0.316
# sample 3 loss: 
#   Softmax:[e^0.5/(e^0.5+e^2.0+e^90)≈0.00x, e^2.0/(...)=0.00x, e^27/(...)=0.99]
# pay attention to 27: -log(0.99)≈0

We asume that image.3 and text.3 own a high similarity 27,then it get a proper loss 0 as expectedd. In a word, ground_truth value helps us pay attention to correponded image and text's loss.

<!-- gh-comment-id:2753102782 --> @t00350320 commented on GitHub (Mar 26, 2025): > > It’s contrastive loss, so every item is GT for itself (we want to pull them together) > > i tested when batch_size=4,then the GT > > ``` > ground_truth: tensor([0, 1, 2, 3], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3], device='cuda:0') > ``` > > batch_size=32,then the GT > > ``` > ground_truth: tensor([0, 1, 2, 3,...,31], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') > ground_truth: tensor([0, 1, 2, 3...,31], device='cuda:0') > ``` > > So "loss_img(logits_per_image,ground_truth) " do what kind of loss with stable ground_truth value? What message should I learn if I want to know the role of "ground_truth" in CrossEntryLoss? and I find the loss value always print a stable value after many epoch times,"train Loss: 0.1032". Does this training process make sense for CLIP's parameters training ? Any one have a better practice? Thanks a lot for "ground_truth value" , 1. logits_per_image we start from logits_per_image. It produced by ``` logits_per_image, logits_per_text = clip(images, label_tokens) ``` then from [openai CLIP code](https://github.com/openai/CLIP/blob/main/clip/model.py#L368) we know logits_per_image = image_features(batch_size,512) @text_features.t(512,batch_size)=[batch_size,batch_size] 2. loss_img as loss_img is nn.CrossEntropyLoss(), it actually work like this ``` asume batch_size = 3 logits_per_image= torch.tensor([ [2.0, 1.0, 0.1], [0.5, 2.0, 0.3], [0.5, 2.0, 27]] ) ground_truth= torch.tensor([0,1,2]) # sample loss for every ground truth: # sample 1 loss:0.417? # sample 2 loss: # Softmax:[e^0.5/(e^0.5+e^2.0+e^0.3)≈0.158, e^2.0/(...)=0.711, e^0.3/(...)=0.133] # pay attention to 2.0 :-log(0.711)≈0.316 # sample 3 loss: # Softmax:[e^0.5/(e^0.5+e^2.0+e^90)≈0.00x, e^2.0/(...)=0.00x, e^27/(...)=0.99] # pay attention to 27: -log(0.99)≈0 ``` We asume that image.3 and text.3 own a high similarity 27,then it get a proper loss 0 as expectedd. In a word, ground_truth value helps us pay attention to correponded image and text's loss.
Author
Owner

@peizhouh commented on GitHub (Sep 16, 2025):

Hi @vinson2233,

Thank you so much for your useful instruction. I have a question about loss calculation part, yet your post exactly follows the CLIP paper did, but what about the loss calculation betow, do you know how much differences will appear in the training? In the loss calculation below, suppose we have image_features and text_features from the model

image_features, text_features = model(images, texts)

# cosine similarity as logits
logit_scale = self.logit_scale.exp()
logits_per_image = logit_scale * image_features @ text_features.t()
logits_per_text = logits_per_image.t()

images_similarity = image_features @ image_features.T
test_similarity = text_features @ text_features.T
targets = F.softmax(
        (images_similarity + test_similarity) / 2 * temperature, dim=-1
)
texts_loss = cross_entropy(logits_per_image, targets, reduction='none')
images_loss = cross_entropy(logits_per_text, targets.T, reduction='none')

total_loss =  ((images_loss + texts_loss) / 2.0).mean()
<!-- gh-comment-id:3294467529 --> @peizhouh commented on GitHub (Sep 16, 2025): Hi @vinson2233, Thank you so much for your useful instruction. I have a question about loss calculation part, yet your post exactly follows the CLIP paper did, but what about the loss calculation betow, do you know how much differences will appear in the training? In the loss calculation below, suppose we have image_features and text_features from the model ``` image_features, text_features = model(images, texts) # cosine similarity as logits logit_scale = self.logit_scale.exp() logits_per_image = logit_scale * image_features @ text_features.t() logits_per_text = logits_per_image.t() images_similarity = image_features @ image_features.T test_similarity = text_features @ text_features.T targets = F.softmax( (images_similarity + test_similarity) / 2 * temperature, dim=-1 ) texts_loss = cross_entropy(logits_per_image, targets, reduction='none') images_loss = cross_entropy(logits_per_text, targets.T, reduction='none') total_loss = ((images_loss + texts_loss) / 2.0).mean() ```
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
openai/CLIP#73
No description provided.