Vector Database

CLIP Model

Import Library

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
    

Define Image Encoder (CNN-based model)

def create_image_encoder(input_shape = (224, 224, 3)):
    model = tf.keras.Sequential([
        tf.keras.layers.InputLayer(input_shape = input_shape),
        tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='same'),
        tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
        tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
        tf.keras.layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
        tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(512, activation='relu'),
        tf.keras.layers.Dense(256)  # Final feature size for image
    ])
    return model

Define Text Encoder (Simple Transformer-based model)

def create_text_encoder(vocab_size=10000, embedding_dim=256, seq_length=32):
    inputs = tf.keras.Input(shape=(seq_length,), dtype=tf.int32)
    embedding_layer = tf.keras.layers.Embedding(vocab_size, embedding_dim)(inputs)
    transformer_layer = tf.keras.layers.MultiHeadAttention(num_heads=4, key_dim=embedding_dim)(embedding_layer, embedding_layer)
    transformer_layer = tf.keras.layers.GlobalAveragePooling1D()(transformer_layer) 
    dense_layer = tf.keras.layers.Dense(256, activation='relu')(transformer_layer)
    output = tf.keras.layers.Dense(256)(dense_layer)  # Final feature size for text
    model = tf.keras.Model(inputs=inputs, outputs=output)
    return model

Contrastive Loss Function

def contrastive_loss(image_embeds, text_embeds, temperature=0.07):
    # Normalize embeddings to unit vectors
    image_embeds = tf.nn.l2_normalize(image_embeds, axis=-1)
    text_embeds = tf.nn.l2_normalize(text_embeds, axis=-1)    
    # Compute cosine similarity
    similarity = tf.matmul(image_embeds, text_embeds, transpose_b=True)
    # Scale similarity by temperature
    similarity /= temperature
    # Create labels (same image-text pair should have label 1)
    labels = tf.eye(image_embeds.shape[0])
    # Compute the loss using softmax
    loss = tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=similarity)
    return tf.reduce_mean(loss)

Training Step Function

@tf.function
def train_step(image_batch, text_batch, image_encoder, text_encoder, optimizer):
    with tf.GradientTape() as tape:
        # Extract embeddings for both image and text
        image_embeds = image_encoder(image_batch)  # Shape: (batch_size, embed_dim)
        text_embeds = text_encoder(text_batch)    # Shape: (batch_size, embed_dim)
        # Calculate contrastive loss
        loss = contrastive_loss(image_embeds, text_embeds)
    # Compute gradients and update weights
    gradients = tape.gradient(loss, image_encoder.trainable_variables + text_encoder.trainable_variables)
    optimizer.apply_gradients(zip(gradients, image_encoder.trainable_variables + text_encoder.trainable_variables))
    return loss

Preprocess Image and Text

def preprocess_image(image_path):
    image = image = tf.io.read_file(join('/kaggle/input/clipimages/images/images', image_path))
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize(image, (224, 224))  # Resize to 224x224
    image = image / 255.0  # Normalize to [0, 1]
    return image
def preprocess_text(text, tokenizer):
    return tokenizer(text)

Preprocess text

# Example image paths and text descriptions
image_paths = df['image'].values[:1000]
texts = df['caption'].values[:1000]
# Define a simple tokenizer for text processing (you can replace this with a more advanced one)
max_len = 32
tokenizer = tf.keras.layers.TextVectorization(max_tokens=10000, output_sequence_length=max_len)
tokenizer.adapt(texts)

Train the Model

# Instantiate image and text encoders
image_encoder = create_image_encoder()
text_encoder = create_text_encoder()
# Optimizer
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4)
# Training loop
batch_size = 200  # Adjust based on your dataset size
num_epochs = 100
for epoch in range(num_epochs):
    for i in range(0, len(image_paths), batch_size):
        # Load and preprocess images and texts
        batch_images = [preprocess_image(p) for p in image_paths[i:i+batch_size]]
        batch_texts = tokenizer(texts[i:i+batch_size])
        batch_images = tf.stack(batch_images)
        batch_texts = tf.stack(batch_texts)
        # Train the model
        loss = train_step(batch_images, batch_texts, image_encoder, text_encoder, optimizer)
        if i % 100 == 0:  # Print loss every 100 steps
            print(f"Epoch {epoch}, Step {i}, Loss: {loss.numpy()}")