# CLIP ViT-B/32

> Dual-encoder contrastive model — a ViT image tower and a Transformer text tower projected into a shared embedding space (OpenAI 2021)

Pick to study cross-modal retrieval / zero-shot classification. Two parallel encoders meet at a contrastive similarity head.

- Category: Multimodal
- Layers: 38
- Parameters: 151.20M
- Input shape (batchless): 3 × 224 × 224
- Output shape: 512
- Verifier verdict: pass
- Graph JSON: https://neurarch.com/templates/clip-vit-b32/model.json
- Open on the canvas: https://neurarch.com/?template=clip-vit-b32

## Structure

| # | Layer | Type | Parameters | Output shape |
| --- | --- | --- | --- | --- |
| 1 | image | Input | shape=[3, 224, 224] | 3 × 224 × 224 |
| 2 | patch_embed | Patch Embed | embedDim=768, patchSize=32 | 49 × 768 |
| 3 | vis_pos | Positional Encoding | embedDim=768, maxLen=50 | 49 × 768 |
| 4 | vis_block_1 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 5 | vis_block_2 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 6 | vis_block_3 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 7 | vis_block_4 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 8 | vis_block_5 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 9 | vis_block_6 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 10 | vis_block_7 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 11 | vis_block_8 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 12 | vis_block_9 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 13 | vis_block_10 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 14 | vis_block_11 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 15 | vis_block_12 | Transformer Block | embedDim=768, numHeads=12, ffDim=3072 | 49 × 768 |
| 16 | vis_norm | LayerNorm | normalizedShape=768 | 49 × 768 |
| 17 | vis_pool | GlobalAvgPool1D |  | 49 |
| 18 | img_proj | Linear | outFeatures=512, inFeatures=768 | 512 |
| 19 | tokens | Input | shape=[1, 77] | 1 × 77 |
| 20 | tok_embed | Embedding |  | 1 × 77 × 512 |
| 21 | txt_pos | Positional Encoding | embedDim=512, maxLen=77 | 1 × 77 × 512 |
| 22 | txt_block_1 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 23 | txt_block_2 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 24 | txt_block_3 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 25 | txt_block_4 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 26 | txt_block_5 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 27 | txt_block_6 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 28 | txt_block_7 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 29 | txt_block_8 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 30 | txt_block_9 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 31 | txt_block_10 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 32 | txt_block_11 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 33 | txt_block_12 | Transformer Block | embedDim=512, numHeads=8, ffDim=2048 | 1 × 77 × 512 |
| 34 | txt_norm | LayerNorm | normalizedShape=512 | 1 × 77 × 512 |
| 35 | txt_pool | GlobalAvgPool1D |  | 1 |
| 36 | txt_proj | Linear | outFeatures=512, inFeatures=512 | 512 |
| 37 | similarity | MatMul |  | 512 |
| 38 | logits | Output |  | 512 |

## Verifier findings

No finding. Shapes propagate end to end and no advisory rule fires.

## Exported PyTorch (first 46 lines)

```python
# Architecture designed with Neurarch: https://neurarch.com
# PyTorch: compatible with Python 3.8+ and torch>=1.12
# Colab: pip install torch torchvision  (usually pre-installed)
#
# WARNING: 3 layer(s) below are not yet supported by the PyTorch
# exporter and pass their input through UNCHANGED in forward():
#   - vis_pool (globalAvgPool1d)
#   - txt_pool (globalAvgPool1d)
#   - similarity (matmul)

import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Tuple

class CLIPViT_B32(nn.Module):
    def __init__(self):
        super().__init__()

        self.patchEmbed_1 = nn.Conv2d(3, 768, kernel_size=32, stride=32)  # Patch embedding (ViT-style)
        self.transformerBlock_1 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_2 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_3 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_4 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_5 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_6 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_7 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_8 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_9 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_10 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_11 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.transformerBlock_12 = nn.TransformerEncoderLayer(d_model=768, nhead=12, dim_feedforward=3072, batch_first=True)
        self.layerNorm_1 = nn.LayerNorm(768)
        self.linear_1 = nn.Linear(768, 512)
        self.embedding_1 = nn.Embedding(49408, 512)
        self.transformerBlock_13 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_14 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_15 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_16 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_17 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_18 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_19 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_20 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_21 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_22 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
        self.transformerBlock_23 = nn.TransformerEncoderLayer(d_model=512, nhead=8, dim_feedforward=2048, batch_first=True)
```

## Machine access

- Every architecture: https://neurarch.com/a/index.json
- Verify a graph of your own: `POST https://www.neurarch.com/api/v1/check` (see https://neurarch.com/developer.html)
- MCP server, so an agent edits the graph with the checks in the loop: https://neurarch.com/docs/mcp.md
