MCPcopy Create free account
hub / github.com/tinygrad/tinygrad / OpenClipEncoder

Class OpenClipEncoder

extra/models/clip.py:428–480  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

426}
427
428class OpenClipEncoder:
429 def __init__(self, dims:int, text_cfg:Dict, vision_cfg:Dict, **_):
430 self.visual = Open.ClipVisionTransformer(**vision_cfg)
431
432 text = Open.ClipTextTransformer(**text_cfg)
433 self.transformer = text.transformer
434 self.token_embedding = text.token_embedding
435 self.positional_embedding = text.positional_embedding
436 self.ln_final = text.ln_final
437 self.text_projection = text.text_projection
438
439 self.attn_mask = Tensor.full((77, 77), float("-inf")).triu(1).realize()
440 self.mean = Tensor([0.48145466, 0.45782750, 0.40821073]).reshape(-1, 1, 1)
441 self.std = Tensor([0.26862954, 0.26130258, 0.27577711]).reshape(-1, 1, 1)
442
443 # TODO:
444 # Should be doable in pure tinygrad, would just require some work and verification.
445 # This is very desirable since it would allow for full generation->evaluation in a single JIT call.
446 def prepare_image(self, image) -> Tensor:
447 from PIL import Image
448 SIZE = 224
449 w, h = image.size
450 scale = min(SIZE / h, SIZE / w)
451 image = image.resize((max(int(w*scale),SIZE),max(int(h*scale),SIZE)), Image.Resampling.BICUBIC)
452 w, h = image.size
453 if w > SIZE:
454 left = (w - SIZE) // 2
455 image = image.crop((left, left+SIZE, 0, SIZE))
456 elif h > SIZE:
457 top = (h - SIZE) // 2
458 image = image.crop((0, SIZE, top, top+SIZE))
459
460 x = Tensor(np.array(image.convert('RGB')), device=self.std.device)
461 x = x.permute(2, 0, 1).cast(dtypes.float32) / 255.0
462 return (x - self.mean) / self.std
463
464 def encode_tokens(self, tokens:Tensor) -> Tensor:
465 x = self.token_embedding(tokens)
466 x = x + self.positional_embedding
467 x = self.transformer(x, attn_mask=self.attn_mask)
468 x = self.ln_final(x)
469 x = x[Tensor.arange(x.shape[0], device=x.device), tokens.argmax(axis=-1)]
470 x = x @ self.text_projection
471 return x
472
473 def get_clip_score(self, tokens:Tensor, image:Tensor) -> Tensor:
474 image_features: Tensor = self.visual(image)
475 image_features /= image_features.square().sum(-1, keepdim=True).sqrt() # Frobenius Norm
476
477 text_features = self.encode_tokens(tokens)
478 text_features /= text_features.square().sum(-1, keepdim=True).sqrt() # Frobenius Norm
479
480 return (image_features * text_features).sum(axis=-1)

Callers 1

eval_stable_diffusionFunction · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…