Feature Extraction
Transformers
PyTorch
Safetensors
English
trendyol_dinov2_v21
image-similarity
image-retrieval
computer-vision
e-commerce
dinov2
gem-pooling
custom_code
Instructions to use Trendyol/trendyol-dino-v2.1-ecommerce-256d with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Trendyol/trendyol-dino-v2.1-ecommerce-256d with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="Trendyol/trendyol-dino-v2.1-ecommerce-256d", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Trendyol/trendyol-dino-v2.1-ecommerce-256d", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Publish Trendyol DinoV2.1 ecommerce 256d (GeM run_12 epoch=09)
Browse files- LICENSE +41 -0
- README.md +104 -0
- __init__.py +21 -0
- config.json +44 -0
- image_processing_trendyol_dinov2_v21.py +116 -0
- model.safetensors +3 -0
- modeling_trendyol_dinov2_v21.py +136 -0
- preprocessor_config.json +22 -0
- pytorch_model.bin +3 -0
- requirements.txt +7 -0
LICENSE
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) 2025 Trendyol
|
| 2 |
+
|
| 3 |
+
This work, including the model weights and code, is licensed under the
|
| 4 |
+
Creative Commons Attribution-ShareAlike 4.0 International License.
|
| 5 |
+
A copy of the license is available at:
|
| 6 |
+
http://creativecommons.org/licenses/by-sa/4.0/
|
| 7 |
+
================================================================================
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
### Human-Readable Summary of the License:
|
| 12 |
+
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
This is a summary of the CC BY-SA 4.0 license and not a substitute for the full license text.
|
| 16 |
+
**You are free to:**
|
| 17 |
+
|
| 18 |
+
- **Share** — copy and redistribute the material in any medium or format for any purpose, even commercially.
|
| 19 |
+
- **Adapt** — remix, transform, and build upon the material for any purpose, even commercially.
|
| 20 |
+
The licensor cannot revoke these freedoms as long as you follow the license terms.
|
| 21 |
+
**Under the following terms:**
|
| 22 |
+
- **Attribution (BY)** — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
|
| 23 |
+
- **ShareAlike (SA)** — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
|
| 24 |
+
- **No additional restrictions** — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
|
| 25 |
+
|
| 26 |
+
---
|
| 27 |
+
|
| 28 |
+
### Attribution Requirements
|
| 29 |
+
|
| 30 |
+
---
|
| 31 |
+
|
| 32 |
+
If you use this model or its derivatives, you must provide proper attribution. Please cite our work as follows:
|
| 33 |
+
"Trendyol DinoV2 Image Similarity Model, licensed under CC BY-SA 4.0. Available at: https://huggingface.co/Trendyol/trendyol-dino-v2-ecommerce-256d"
|
| 34 |
+
|
| 35 |
+
---
|
| 36 |
+
|
| 37 |
+
### Disclaimer of Warranty
|
| 38 |
+
|
| 39 |
+
---
|
| 40 |
+
|
| 41 |
+
Unless required by applicable law or agreed to in writing, the Work is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with your exercise of permissions under this License.
|
README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- en
|
| 4 |
+
license: cc-by-sa-4.0
|
| 5 |
+
library_name: transformers
|
| 6 |
+
tags:
|
| 7 |
+
- image-similarity
|
| 8 |
+
- image-retrieval
|
| 9 |
+
- computer-vision
|
| 10 |
+
- e-commerce
|
| 11 |
+
- dinov2
|
| 12 |
+
- gem-pooling
|
| 13 |
+
- pytorch
|
| 14 |
+
- safetensors
|
| 15 |
+
datasets:
|
| 16 |
+
- e-commerce-product-images
|
| 17 |
+
pipeline_tag: feature-extraction
|
| 18 |
+
base_model: Trendyol/trendyol-dino-v2-ecommerce-256d
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
# Trendyol DinoV2.1 Image Similarity Model
|
| 22 |
+
|
| 23 |
+
Fine-tuned DinoV2 (ViT-B/14) with **GeM pooling** for e-commerce product image retrieval.
|
| 24 |
+
This is the successor to [`Trendyol/trendyol-dino-v2-ecommerce-256d`](https://huggingface.co/Trendyol/trendyol-dino-v2-ecommerce-256d).
|
| 25 |
+
|
| 26 |
+
## Model Details
|
| 27 |
+
|
| 28 |
+
- **Model Type**: Image Similarity / Retrieval
|
| 29 |
+
- **Architecture**: DinoV2 ViT-B/14 + GeM pooling + linear projection (ArcFace-trained)
|
| 30 |
+
- **Embedding Dimension**: 256
|
| 31 |
+
- **Input Size**: 224×224
|
| 32 |
+
- **Checkpoint**: `ray-dinov2-full_catalog_1000_20-pfc-gem-mlp-run_12` epoch **09**
|
| 33 |
+
- **Framework**: PyTorch / SafeTensors
|
| 34 |
+
|
| 35 |
+
## What's new vs v2
|
| 36 |
+
|
| 37 |
+
| | v2 | **v2.1** |
|
| 38 |
+
|---|---|---|
|
| 39 |
+
| Pooling / head | Flatten spatial tokens → Linear(196608→256) | **GeM** → Linear(768→256) |
|
| 40 |
+
| Training data | full_catalog_300_20 style | **full_catalog_1000_20** |
|
| 41 |
+
| Preprocess | Lanczos/JPEG/332 pad pipeline | Scale+pad to 224 (training inference preprocess) |
|
| 42 |
+
|
| 43 |
+
## Quick Start
|
| 44 |
+
|
| 45 |
+
```python
|
| 46 |
+
import torch
|
| 47 |
+
from PIL import Image
|
| 48 |
+
from transformers import AutoModel, AutoImageProcessor
|
| 49 |
+
|
| 50 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 51 |
+
repo = "Trendyol/trendyol-dino-v2.1-ecommerce-256d"
|
| 52 |
+
|
| 53 |
+
processor = AutoImageProcessor.from_pretrained(repo, trust_remote_code=True)
|
| 54 |
+
model = AutoModel.from_pretrained(repo, trust_remote_code=True).to(device).eval()
|
| 55 |
+
|
| 56 |
+
image = Image.open("your_image.jpg").convert("RGB")
|
| 57 |
+
inputs = processor(images=image, return_tensors="pt")
|
| 58 |
+
inputs = {k: v.to(device) for k, v in inputs.items()}
|
| 59 |
+
|
| 60 |
+
with torch.no_grad():
|
| 61 |
+
embeddings = model(**inputs).last_hidden_state # [1, 256]
|
| 62 |
+
|
| 63 |
+
print(embeddings.shape)
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
## Preprocessing Pipeline
|
| 67 |
+
|
| 68 |
+
1. **ScaleImage**: resize so max side = 224 (keep aspect ratio)
|
| 69 |
+
2. **PadToSquare**: pad with color 255
|
| 70 |
+
3. **Resize**: 224×224
|
| 71 |
+
4. **ToTensor** + **ImageNet Normalize** (mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
|
| 72 |
+
|
| 73 |
+
## Installation
|
| 74 |
+
|
| 75 |
+
```bash
|
| 76 |
+
pip install transformers torch torchvision safetensors pillow numpy
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
## Intended Use
|
| 80 |
+
|
| 81 |
+
- Product image similarity search
|
| 82 |
+
- Visual recommendations / duplicate detection
|
| 83 |
+
- Content-based retrieval in e-commerce
|
| 84 |
+
|
| 85 |
+
## Limitations
|
| 86 |
+
|
| 87 |
+
- Optimized for product / e-commerce images
|
| 88 |
+
- Requires `trust_remote_code=True`
|
| 89 |
+
- Classification heads from training are **not** included in this Hub export (embeddings only)
|
| 90 |
+
|
| 91 |
+
## License
|
| 92 |
+
|
| 93 |
+
See [LICENSE](LICENSE). Same terms as the v2 release: source-available; commercial use requires attribution and prior notification to Trendyol (`scr.datascience@trendyol.com`).
|
| 94 |
+
|
| 95 |
+
## Citation
|
| 96 |
+
|
| 97 |
+
```
|
| 98 |
+
@misc{trendyol-dinov2-ecommerce-v21,
|
| 99 |
+
title={Trendyol DinoV2.1 E-commerce Image Similarity Model},
|
| 100 |
+
author={Trendyol Data Science Team},
|
| 101 |
+
year={2026},
|
| 102 |
+
url={https://huggingface.co/Trendyol/trendyol-dino-v2.1-ecommerce-256d}
|
| 103 |
+
}
|
| 104 |
+
```
|
__init__.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Trendyol DinoV2.1 Image Similarity Model (GeM)
|
| 3 |
+
|
| 4 |
+
Hugging Face transformers-compatible package.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from transformers import AutoConfig, AutoImageProcessor, AutoModel
|
| 8 |
+
|
| 9 |
+
from .image_processing_trendyol_dinov2_v21 import TrendyolDinoV21ImageProcessor
|
| 10 |
+
from .modeling_trendyol_dinov2_v21 import TrendyolDinoV21Config, TrendyolDinoV21Model
|
| 11 |
+
|
| 12 |
+
AutoConfig.register("trendyol_dinov2_v21", TrendyolDinoV21Config)
|
| 13 |
+
AutoModel.register(TrendyolDinoV21Config, TrendyolDinoV21Model)
|
| 14 |
+
AutoImageProcessor.register(TrendyolDinoV21Config, TrendyolDinoV21ImageProcessor)
|
| 15 |
+
|
| 16 |
+
__version__ = "2.1.0"
|
| 17 |
+
__all__ = [
|
| 18 |
+
"TrendyolDinoV21Model",
|
| 19 |
+
"TrendyolDinoV21Config",
|
| 20 |
+
"TrendyolDinoV21ImageProcessor",
|
| 21 |
+
]
|
config.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_type": "trendyol_dinov2_v21",
|
| 3 |
+
"architectures": [
|
| 4 |
+
"TrendyolDinoV21Model"
|
| 5 |
+
],
|
| 6 |
+
"auto_map": {
|
| 7 |
+
"AutoConfig": "modeling_trendyol_dinov2_v21.TrendyolDinoV21Config",
|
| 8 |
+
"AutoModel": "modeling_trendyol_dinov2_v21.TrendyolDinoV21Model",
|
| 9 |
+
"AutoImageProcessor": "image_processing_trendyol_dinov2_v21.TrendyolDinoV21ImageProcessor"
|
| 10 |
+
},
|
| 11 |
+
"backbone_name": "dinov2_vitb14",
|
| 12 |
+
"embedding_dim": 256,
|
| 13 |
+
"hidden_size": 256,
|
| 14 |
+
"in_features": 768,
|
| 15 |
+
"gem_p": 2.9,
|
| 16 |
+
"dropout": 0.3,
|
| 17 |
+
"input_size": 224,
|
| 18 |
+
"pad_color": 255,
|
| 19 |
+
"pooling": "GeM",
|
| 20 |
+
"normalization": {
|
| 21 |
+
"mean": [0.485, 0.456, 0.406],
|
| 22 |
+
"std": [0.229, 0.224, 0.225]
|
| 23 |
+
},
|
| 24 |
+
"preprocessing": {
|
| 25 |
+
"input_size": 224,
|
| 26 |
+
"pad_color": 255,
|
| 27 |
+
"transforms": [
|
| 28 |
+
"ScaleImage",
|
| 29 |
+
"PadToSquare",
|
| 30 |
+
"Resize",
|
| 31 |
+
"ToTensor",
|
| 32 |
+
"Normalize"
|
| 33 |
+
]
|
| 34 |
+
},
|
| 35 |
+
"task_type": "image-retrieval",
|
| 36 |
+
"training_info": {
|
| 37 |
+
"experiment": "ray-dinov2-full_catalog_1000_20-pfc-gem-mlp-run_12",
|
| 38 |
+
"epoch": "9",
|
| 39 |
+
"dataset": "full_catalog_1000_20",
|
| 40 |
+
"torch_version": "2.8.0"
|
| 41 |
+
},
|
| 42 |
+
"torch_dtype": "float32",
|
| 43 |
+
"transformers_version": "4.20.0"
|
| 44 |
+
}
|
image_processing_trendyol_dinov2_v21.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Hugging Face image processor for Trendyol DinoV2.1 (GeM).
|
| 3 |
+
|
| 4 |
+
Matches training/inference preprocess used by SimilarityInferenceModel /
|
| 5 |
+
dino_v2_gem.Preprocessor: scale-to-max(224), pad-to-square(255), resize 224,
|
| 6 |
+
ImageNet normalize. (No JPEG / 332 downscale stage.)
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
from __future__ import annotations
|
| 10 |
+
|
| 11 |
+
from typing import List, Optional, Union
|
| 12 |
+
|
| 13 |
+
import numpy as np
|
| 14 |
+
import torch
|
| 15 |
+
from PIL import Image
|
| 16 |
+
from torchvision import transforms
|
| 17 |
+
from torchvision.transforms import functional as TF
|
| 18 |
+
from transformers import BatchFeature, ImageProcessingMixin
|
| 19 |
+
from transformers.utils import TensorType
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def resize_keep_ratio(img: Image.Image, size: int) -> Image.Image:
|
| 23 |
+
w, h = img.size
|
| 24 |
+
max_size = max(h, w)
|
| 25 |
+
scale = size / max_size
|
| 26 |
+
new_size = int(w * scale), int(h * scale)
|
| 27 |
+
return img.resize(new_size, Image.BILINEAR)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class ScaleImage:
|
| 31 |
+
def __init__(self, target_size: int):
|
| 32 |
+
self.target_size = target_size
|
| 33 |
+
|
| 34 |
+
def __call__(self, img: Image.Image) -> Image.Image:
|
| 35 |
+
return resize_keep_ratio(img, self.target_size)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class PadToSquare:
|
| 39 |
+
def __init__(self, color: int = 255):
|
| 40 |
+
self.color = color
|
| 41 |
+
|
| 42 |
+
def __call__(self, img: Image.Image) -> Image.Image:
|
| 43 |
+
width, height = img.size
|
| 44 |
+
padding = abs(width - height) // 2
|
| 45 |
+
if width < height:
|
| 46 |
+
return TF.pad(
|
| 47 |
+
img,
|
| 48 |
+
(padding, 0, padding + (height - width) % 2, 0),
|
| 49 |
+
fill=self.color,
|
| 50 |
+
padding_mode="constant",
|
| 51 |
+
)
|
| 52 |
+
if width > height:
|
| 53 |
+
return TF.pad(
|
| 54 |
+
img,
|
| 55 |
+
(0, padding, 0, padding + (width - height) % 2),
|
| 56 |
+
fill=self.color,
|
| 57 |
+
padding_mode="constant",
|
| 58 |
+
)
|
| 59 |
+
return img
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class TrendyolDinoV21ImageProcessor(ImageProcessingMixin):
|
| 63 |
+
model_input_names = ["pixel_values"]
|
| 64 |
+
|
| 65 |
+
def __init__(
|
| 66 |
+
self,
|
| 67 |
+
input_size: int = 224,
|
| 68 |
+
pad_color: int = 255,
|
| 69 |
+
do_normalize: bool = True,
|
| 70 |
+
image_mean=(0.485, 0.456, 0.406),
|
| 71 |
+
image_std=(0.229, 0.224, 0.225),
|
| 72 |
+
**kwargs,
|
| 73 |
+
):
|
| 74 |
+
super().__init__(**kwargs)
|
| 75 |
+
self.input_size = input_size
|
| 76 |
+
self.pad_color = pad_color
|
| 77 |
+
self.do_normalize = do_normalize
|
| 78 |
+
self.image_mean = list(image_mean)
|
| 79 |
+
self.image_std = list(image_std)
|
| 80 |
+
|
| 81 |
+
def _get_preprocess_fn(self):
|
| 82 |
+
steps = [
|
| 83 |
+
ScaleImage(self.input_size),
|
| 84 |
+
PadToSquare(self.pad_color),
|
| 85 |
+
transforms.Resize((self.input_size, self.input_size)),
|
| 86 |
+
transforms.ToTensor(),
|
| 87 |
+
]
|
| 88 |
+
if self.do_normalize:
|
| 89 |
+
steps.append(transforms.Normalize(self.image_mean, self.image_std))
|
| 90 |
+
return transforms.Compose(steps)
|
| 91 |
+
|
| 92 |
+
def __call__(
|
| 93 |
+
self,
|
| 94 |
+
images: Union[Image.Image, np.ndarray, List],
|
| 95 |
+
return_tensors: Optional[Union[str, TensorType]] = None,
|
| 96 |
+
**kwargs,
|
| 97 |
+
) -> BatchFeature:
|
| 98 |
+
if not isinstance(images, list):
|
| 99 |
+
images = [images]
|
| 100 |
+
preprocess_fn = self._get_preprocess_fn()
|
| 101 |
+
processed = []
|
| 102 |
+
for image in images:
|
| 103 |
+
if isinstance(image, str):
|
| 104 |
+
image = Image.open(image).convert("RGB")
|
| 105 |
+
elif isinstance(image, np.ndarray):
|
| 106 |
+
image = Image.fromarray(image).convert("RGB")
|
| 107 |
+
elif not isinstance(image, Image.Image):
|
| 108 |
+
raise ValueError(f"Unsupported image type: {type(image)}")
|
| 109 |
+
else:
|
| 110 |
+
image = image.convert("RGB")
|
| 111 |
+
processed.append(preprocess_fn(image))
|
| 112 |
+
data = {"pixel_values": torch.stack(processed)}
|
| 113 |
+
return BatchFeature(data=data, tensor_type=return_tensors)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
TrendyolDinoV21ImageProcessor.register_for_auto_class("AutoImageProcessor")
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5ba54402e876cd9b0461f8d203771ae8b576123e9501f2165ff7b73ab69e81ce
|
| 3 |
+
size 347132884
|
modeling_trendyol_dinov2_v21.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Hugging Face compatible model for Trendyol DinoV2.1 (GeM pooling).
|
| 3 |
+
|
| 4 |
+
Checkpoint source:
|
| 5 |
+
ray-dinov2-full_catalog_1000_20-pfc-gem-mlp-run_12 / epoch=09
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
from typing import Optional
|
| 11 |
+
|
| 12 |
+
import torch
|
| 13 |
+
import torch.nn as nn
|
| 14 |
+
import torch.nn.functional as F
|
| 15 |
+
from transformers import PretrainedConfig, PreTrainedModel
|
| 16 |
+
from transformers.modeling_outputs import BaseModelOutput
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class TrendyolDinoV21Config(PretrainedConfig):
|
| 20 |
+
model_type = "trendyol_dinov2_v21"
|
| 21 |
+
|
| 22 |
+
def __init__(
|
| 23 |
+
self,
|
| 24 |
+
embedding_dim: int = 256,
|
| 25 |
+
input_size: int = 224,
|
| 26 |
+
backbone_name: str = "dinov2_vitb14",
|
| 27 |
+
in_features: int = 768,
|
| 28 |
+
gem_p: float = 2.9,
|
| 29 |
+
dropout: float = 0.3,
|
| 30 |
+
pad_color: int = 255,
|
| 31 |
+
**kwargs,
|
| 32 |
+
):
|
| 33 |
+
super().__init__(**kwargs)
|
| 34 |
+
self.embedding_dim = embedding_dim
|
| 35 |
+
self.input_size = input_size
|
| 36 |
+
self.backbone_name = backbone_name
|
| 37 |
+
self.in_features = in_features
|
| 38 |
+
self.gem_p = gem_p
|
| 39 |
+
self.dropout = dropout
|
| 40 |
+
self.pad_color = pad_color
|
| 41 |
+
self.hidden_size = embedding_dim
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class GeM(nn.Module):
|
| 45 |
+
def __init__(self, p: float = 2.9, eps: float = 1e-6):
|
| 46 |
+
super().__init__()
|
| 47 |
+
self.register_buffer("p", torch.tensor(float(p)))
|
| 48 |
+
self.eps = eps
|
| 49 |
+
|
| 50 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 51 |
+
x = x.clamp(min=self.eps).pow(self.p)
|
| 52 |
+
x = F.adaptive_avg_pool2d(x, (1, 1))
|
| 53 |
+
x = x.pow(1.0 / self.p)
|
| 54 |
+
return x.squeeze(-1).squeeze(-1)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class DinoV2Backbone(nn.Module):
|
| 58 |
+
"""Matches training ``Backbone`` wrapper: ``self.model = hub dinov2``."""
|
| 59 |
+
|
| 60 |
+
def __init__(self, backbone_name: str = "dinov2_vitb14"):
|
| 61 |
+
super().__init__()
|
| 62 |
+
try:
|
| 63 |
+
self.model = torch.hub.load("facebookresearch/dinov2", backbone_name)
|
| 64 |
+
except Exception as exc: # noqa: BLE001
|
| 65 |
+
raise RuntimeError(f"Failed to load DinoV2 backbone: {exc}") from exc
|
| 66 |
+
self.model.requires_grad_(False)
|
| 67 |
+
|
| 68 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 69 |
+
features = self.model.get_intermediate_layers(
|
| 70 |
+
x, return_class_token=True, reshape=True
|
| 71 |
+
)
|
| 72 |
+
return features[0][0]
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
class TYGeMDinoV2(nn.Module):
|
| 76 |
+
"""Core GeM retrieval trunk used in run_12 (embeddings only)."""
|
| 77 |
+
|
| 78 |
+
def __init__(self, config: TrendyolDinoV21Config):
|
| 79 |
+
super().__init__()
|
| 80 |
+
self.config = config
|
| 81 |
+
self.backbone = DinoV2Backbone(config.backbone_name)
|
| 82 |
+
self.pooling = GeM(p=config.gem_p)
|
| 83 |
+
self.feature = nn.Sequential(
|
| 84 |
+
nn.Linear(config.in_features, config.embedding_dim, bias=False),
|
| 85 |
+
nn.BatchNorm1d(config.embedding_dim),
|
| 86 |
+
nn.Dropout(config.dropout),
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
def forward(self, pixel_values: torch.Tensor) -> torch.Tensor:
|
| 90 |
+
feats = self.backbone(pixel_values)
|
| 91 |
+
feats = self.pooling(feats)
|
| 92 |
+
feats = self.feature(feats)
|
| 93 |
+
return F.normalize(feats, p=2, dim=1)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class TrendyolDinoV21Model(PreTrainedModel):
|
| 97 |
+
config_class = TrendyolDinoV21Config
|
| 98 |
+
base_model_prefix = "model"
|
| 99 |
+
|
| 100 |
+
def __init__(self, config: TrendyolDinoV21Config):
|
| 101 |
+
super().__init__(config)
|
| 102 |
+
self.model = TYGeMDinoV2(config)
|
| 103 |
+
self.post_init()
|
| 104 |
+
|
| 105 |
+
@classmethod
|
| 106 |
+
def from_pretrained(cls, pretrained_model_name_or_path, *model_args, **kwargs):
|
| 107 |
+
# torch.hub DinoV2 backbone is incompatible with meta-device init.
|
| 108 |
+
kwargs.setdefault("low_cpu_mem_usage", False)
|
| 109 |
+
return super().from_pretrained(pretrained_model_name_or_path, *model_args, **kwargs)
|
| 110 |
+
|
| 111 |
+
def forward(
|
| 112 |
+
self,
|
| 113 |
+
pixel_values: Optional[torch.Tensor] = None,
|
| 114 |
+
return_dict: Optional[bool] = None,
|
| 115 |
+
**kwargs,
|
| 116 |
+
):
|
| 117 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 118 |
+
if pixel_values is None:
|
| 119 |
+
raise ValueError("pixel_values cannot be None")
|
| 120 |
+
|
| 121 |
+
embeddings = self.model(pixel_values)
|
| 122 |
+
if not return_dict:
|
| 123 |
+
return (embeddings,)
|
| 124 |
+
return BaseModelOutput(
|
| 125 |
+
last_hidden_state=embeddings,
|
| 126 |
+
hidden_states=None,
|
| 127 |
+
attentions=None,
|
| 128 |
+
)
|
| 129 |
+
|
| 130 |
+
def get_embeddings(self, pixel_values: torch.Tensor) -> torch.Tensor:
|
| 131 |
+
with torch.no_grad():
|
| 132 |
+
return self.forward(pixel_values, return_dict=True).last_hidden_state
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
TrendyolDinoV21Config.register_for_auto_class()
|
| 136 |
+
TrendyolDinoV21Model.register_for_auto_class("AutoModel")
|
preprocessor_config.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"image_processor_type": "TrendyolDinoV21ImageProcessor",
|
| 3 |
+
"processor_class": "TrendyolDinoV21ImageProcessor",
|
| 4 |
+
"auto_map": {
|
| 5 |
+
"AutoImageProcessor": "image_processing_trendyol_dinov2_v21.TrendyolDinoV21ImageProcessor"
|
| 6 |
+
},
|
| 7 |
+
"input_size": 224,
|
| 8 |
+
"pad_color": 255,
|
| 9 |
+
"do_normalize": true,
|
| 10 |
+
"image_mean": [0.485, 0.456, 0.406],
|
| 11 |
+
"image_std": [0.229, 0.224, 0.225],
|
| 12 |
+
"do_resize": true,
|
| 13 |
+
"size": {"height": 224, "width": 224},
|
| 14 |
+
"do_convert_rgb": true,
|
| 15 |
+
"transforms": [
|
| 16 |
+
"ScaleImage",
|
| 17 |
+
"PadToSquare",
|
| 18 |
+
"Resize",
|
| 19 |
+
"ToTensor",
|
| 20 |
+
"Normalize"
|
| 21 |
+
]
|
| 22 |
+
}
|
pytorch_model.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:aa2daa2b961dbb6bdb3825b38deb43bfbbf8429b51cae0bf078d3bc7552eda4f
|
| 3 |
+
size 347171771
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch>=1.9.0
|
| 2 |
+
torchvision>=0.10.0
|
| 3 |
+
safetensors>=0.3.0
|
| 4 |
+
Pillow>=8.0.0
|
| 5 |
+
numpy>=1.20.0
|
| 6 |
+
opencv-python>=4.5.0
|
| 7 |
+
transformers>=4.20.0
|