Room Image Similarity Model
๊ฐ์ค ์ด๋ฏธ์ง ์ ์ฌ๋ ์ธก์ ์ ์ํ Siamese ๋คํธ์ํฌ ๋ชจ๋ธ์ ๋๋ค.
๋ชจ๋ธ ๊ฐ์
์ด ๋ชจ๋ธ์ ์์ ๊ฐ์ค ์ด๋ฏธ์ง ๊ฐ์ ์ ์ฌ๋๋ฅผ ์ธก์ ํ์ฌ ๋์ผํ ๋ฌผ๋ฆฌ์ ๊ฐ์ค์ ์๋ณํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. EfficientNetV2 ๊ธฐ๋ฐ Siamese ๋คํธ์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ์ ์ฌ๋๋ฅผ ๊ณ์ฐํฉ๋๋ค.
๋ชจ๋ธ ์ ๋ณด
- ๋ชจ๋ธ๋ช
:
similarity_model_0.6 - ๊ธฐ๋ฐ ๋ชจ๋ธ:
timm/tf_efficientnetv2_s - ์ด๋ฏธ์ง ํฌ๊ธฐ: 224x224
- ์ฑ๋: RGB (3์ฑ๋)
- ์ ๊ทํ: ImageNet ํ์ค (mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
์ฌ์ฉ๋ฒ
Python์ผ๋ก ๋ชจ๋ธ ์ฌ์ฉ
import torch
import onnxruntime as ort
import numpy as np
from PIL import Image
from torchvision import transforms
# PyTorch ๋ชจ๋ธ ๋ก๋
model = torch.load('similarity_model_0.6.pth', map_location='cpu')
model.eval()
# ONNX ๋ชจ๋ธ ์ฌ์ฉ (๋ ๋น ๋ฅธ ์ถ๋ก )
onnx_session = ort.InferenceSession('similarity_model_0.6.onnx')
# ์ด๋ฏธ์ง ์ ์ฒ๋ฆฌ
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
def calculate_similarity_pytorch(img1_path, img2_path):
"""PyTorch ๋ชจ๋ธ์ ์ฌ์ฉํ ์ ์ฌ๋ ๊ณ์ฐ"""
img1 = transform(Image.open(img1_path)).unsqueeze(0)
img2 = transform(Image.open(img2_path)).unsqueeze(0)
with torch.no_grad():
similarity = torch.sigmoid(model(img1, img2))
return similarity.item()
def calculate_similarity_onnx(img1_path, img2_path):
"""ONNX ๋ชจ๋ธ์ ์ฌ์ฉํ ์ ์ฌ๋ ๊ณ์ฐ (๊ถ์ฅ)"""
img1 = transform(Image.open(img1_path)).numpy()
img2 = transform(Image.open(img2_path)).numpy()
# ONNX ๋ชจ๋ธ ์ถ๋ก
input_feed = {
'input1': img1.astype(np.float32),
'input2': img2.astype(np.float32)
}
similarity = onnx_session.run(None, input_feed)[0]
return similarity[0][0]
# ์์ ์ฌ์ฉ
similarity_score = calculate_similarity_onnx("room1.jpg", "room2.jpg")
print(f"์ ์ฌ๋: {similarity_score:.4f}")
๋ฐฐ์น ์ฒ๋ฆฌ
def calculate_batch_similarity(image_pairs):
"""์ฌ๋ฌ ์ด๋ฏธ์ง ์์ ์ ์ฌ๋๋ฅผ ํ ๋ฒ์ ๊ณ์ฐ"""
similarities = []
for img1_path, img2_path in image_pairs:
similarity = calculate_similarity_onnx(img1_path, img2_path)
similarities.append(similarity)
return similarities
# ์์
image_pairs = [
("room1.jpg", "room2.jpg"),
("room3.jpg", "room4.jpg"),
("room5.jpg", "room6.jpg")
]
similarities = calculate_batch_similarity(image_pairs)
for i, sim in enumerate(similarities):
print(f"์ {i+1} ์ ์ฌ๋: {sim:.4f}")
๋ชจ๋ธ ํ์ผ
similarity_model_0.6.pth: PyTorch ๋ชจ๋ธ ํ์ผsimilarity_model_0.6.onnx: ONNX ๋ชจ๋ธ ํ์ผ (์ถ๋ก ์ต์ ํ)similarity_model_0.6_model_info.json: ๋ชจ๋ธ ๋ฉํ๋ฐ์ดํฐsimilarity_model_0.6_inference_example.py: ์ถ๋ก ์์ ์ฝ๋
์ฑ๋ฅ
- ์ ํ๋: 90% ์ด์
- F1 Score: 0.90 ์ด์
- ์ฒ๋ฆฌ ์๋: 500 ์ด๋ฏธ์ง ์/์ด ์ด์ (ONNX ๋ชจ๋ธ ๊ธฐ์ค)
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋: 2GB ์ดํ (GPU ์ถ๋ก ์)
ํ๋ จ ๋ฐ์ดํฐ
์ด ๋ชจ๋ธ์ ๋ค์๊ณผ ๊ฐ์ ๋ฐ์ดํฐ๋ก ํ๋ จ๋์์ต๋๋ค:
์ฌ์ ํ๋ จ (Pretraining)
- ๊ธ์ ์: ์๋ณธ ์ด๋ฏธ์ง์ ์ฆ๊ฐ๋ ์ด๋ฏธ์ง (๊ฐ์ ๊ฐ์ค)
- ๋ถ์ ์: ์๋ก ๋ค๋ฅธ ๊ฐ์ค์ ์ด๋ฏธ์ง
๋ฏธ์ธ์กฐ์ (Fine-tuning)
- ๊ธ์ ์: ๊ฐ์ ๊ฐ์ค์ ์๋ก ๋ค๋ฅธ ์ด๋ฏธ์ง
- ๋ถ์ ์: ๋ค๋ฅธ ๊ฐ์ค์ ์ด๋ฏธ์ง
๋ชจ๋ธ ์ํคํ ์ฒ
- ๋ฐฑ๋ณธ: EfficientNetV2-Small
- Siamese ๊ตฌ์กฐ: ๋ ์ด๋ฏธ์ง๋ฅผ ๋์ผํ ๋ฐฑ๋ณธ์ผ๋ก ์ฒ๋ฆฌ
- ์์ค ํจ์: Focal Loss (๋ถ๊ท ํ ๋ฐ์ดํฐ์ ์ต์ ํ)
- ์ถ๋ ฅ: 0-1 ์ฌ์ด์ ์ ์ฌ๋ ์ ์
์ ์ฒ๋ฆฌ ์๊ตฌ์ฌํญ
- ์ด๋ฏธ์ง ํฌ๊ธฐ: 224x224 ํฝ์
- ์์ ๊ณต๊ฐ: RGB
- ์ ๊ทํ: ImageNet ํ์ค๊ฐ ์ฌ์ฉ
- ํฌ๋กญ: ์ค์ ํฌ๋กญ (center crop)
- ์ง์ ํ์: JPG, PNG, JPEG
๋ผ์ด์ ์ค
Apache 2.0 License
์ฐธ๊ณ
์ด ๋ชจ๋ธ์ Room Clusterer ํ๋ก์ ํธ์ ์ผ๋ถ๋ก ๊ฐ๋ฐ๋์์ต๋๋ค. ๋ ์์ธํ ์ ๋ณด๋ ํ๋ก์ ํธ ์ ์ฅ์๋ฅผ ์ฐธ์กฐํ์ธ์.
์ฌ์ฉ ์ฌ๋ก
์ง์ ์ฌ์ฉ
์ด ๋ชจ๋ธ์ ๋ค์๊ณผ ๊ฐ์ ์ฉ๋๋ก ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
- ๊ฐ์ค ์ด๋ฏธ์ง ์ค๋ณต ๊ฒ์ถ: ๋์ผํ ๊ฐ์ค์ ์๋ก ๋ค๋ฅธ ๊ฐ๋/์กฐ๋ช ์ ์ด๋ฏธ์ง ์๋ณ
- ์์ ์ด๋ฏธ์ง ํด๋ฌ์คํฐ๋ง: ์ ์ฌํ ๊ฐ์ค ํ์ ๋ณ๋ก ์ด๋ฏธ์ง ๊ทธ๋ฃนํ
- ์ด๋ฏธ์ง ์ ์ฌ๋ ๊ฒ์: ์ฃผ์ด์ง ์ด๋ฏธ์ง์ ๊ฐ์ฅ ์ ์ฌํ ์ด๋ฏธ์ง ์ฐพ๊ธฐ
- ํ์ง ๊ด๋ฆฌ: ๊ฐ์ค ์ด๋ฏธ์ง์ ์ผ๊ด์ฑ ๊ฒ์ฆ
๋ค์ด์คํธ๋ฆผ ์ฌ์ฉ
์ด ๋ชจ๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค:
- ์์ ๊ด๋ฆฌ ์์คํ : ๊ฐ์ค ์ด๋ฏธ์ง ์๋ ๋ถ๋ฅ ๋ฐ ๊ด๋ฆฌ
- ์ฌํ ํ๋ซํผ: ๊ฐ์ค ์ด๋ฏธ์ง ๊ธฐ๋ฐ ์ถ์ฒ ์์คํ
- ๋ถ๋์ฐ ํ๋ซํผ: ์ ์ฌํ ๊ฐ์ค ์คํ์ผ ๊ฒ์
- ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฒ ์ด์ค: ๋๊ท๋ชจ ์ด๋ฏธ์ง ์ ์ฌ๋ ๊ฒ์ ์์ง
์ฌ์ฉ ๋ฒ์ ์ ํ
์ด ๋ชจ๋ธ์ ๋ค์๊ณผ ๊ฐ์ ์ฉ๋๋ก๋ ์ ํฉํ์ง ์์ต๋๋ค:
- ๋ค๋ฅธ ๋๋ฉ์ธ ์ด๋ฏธ์ง: ๊ฐ์ค์ด ์๋ ๋ค๋ฅธ ์ ํ์ ์ด๋ฏธ์ง ์ ์ฌ๋ ์ธก์
- ์ค์๊ฐ ๋น๋์ค: ๋์์ ํ๋ ์ ๊ฐ ์ ์ฌ๋ ์ธก์
- 3D ๊ณต๊ฐ ๋ถ์: ๊ณต๊ฐ์ ๊ด๊ณ๋ ๊น์ด ์ ๋ณด ํ์ฉ
ํธํฅ, ์ํ ๋ฐ ์ ํ์ฌํญ
์๋ ค์ง ์ ํ์ฌํญ
- ์ด๋ฏธ์ง ํ์ง ์์กด์ฑ: ์ ํ์ง์ด๋ ๋ ธ์ด์ฆ๊ฐ ๋ง์ ์ด๋ฏธ์ง์์๋ ์ฑ๋ฅ์ด ์ ํ๋ ์ ์์ต๋๋ค.
- ์กฐ๋ช ์กฐ๊ฑด: ์๋ก ๋ค๋ฅธ ์กฐ๋ช ์กฐ๊ฑด์ ์ด๋ฏธ์ง ๋น๊ต ์ ์ ํ๋๊ฐ ๋จ์ด์ง ์ ์์ต๋๋ค.
- ๊ฐ๋ ๋ณํ: ๋์ผ ๊ฐ์ค์ด๋ผ๋ ์ดฌ์ ๊ฐ๋๊ฐ ํฌ๊ฒ ๋ค๋ฅด๋ฉด ์ ์ฌ๋๊ฐ ๋ฎ๊ฒ ์ธก์ ๋ ์ ์์ต๋๋ค.
- ๋๋ฉ์ธ ํนํ: ์์ ๊ฐ์ค ์ด๋ฏธ์ง์ ํนํ๋์ด ์์ด ๋ค๋ฅธ ๋๋ฉ์ธ์์๋ ์ฑ๋ฅ์ด ์ ํ์ ์ ๋๋ค.
๊ถ์ฅ์ฌํญ
- ์ด๋ฏธ์ง ์ ์ฒ๋ฆฌ: ์ผ๊ด๋ ํฌ๊ธฐ์ ํ์ง๋ก ์ด๋ฏธ์ง๋ฅผ ์ ์ฒ๋ฆฌํ์ธ์.
- ์๊ณ๊ฐ ์ค์ : ์ฉ๋์ ๋ฐ๋ผ ์ ์ ํ ์ ์ฌ๋ ์๊ณ๊ฐ์ ์ค์ ํ์ธ์ (์ผ๋ฐ์ ์ผ๋ก 0.7-0.8).
- ๋ฐฐ์น ์ฒ๋ฆฌ: ๋๋์ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ์ ONNX ๋ชจ๋ธ ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค.
๋ชจ๋ธ ์์ํ๊ธฐ
์์ "์ฌ์ฉ๋ฒ" ์น์ ์ ์ฝ๋ ์์ ๋ฅผ ์ฐธ์กฐํ์ฌ ๋ชจ๋ธ์ ์์ํ์ธ์.
ํ๋ จ ์ธ๋ถ์ฌํญ
ํ๋ จ ๋ฐ์ดํฐ
- ๋ฐ์ดํฐ์ ํฌ๊ธฐ: ์ฝ 50,000๊ฐ์ ๊ฐ์ค ์ด๋ฏธ์ง
- ์ด๋ฏธ์ง ์: 200,000๊ฐ์ ๊ธ์ ์, 200,000๊ฐ์ ๋ถ์ ์
- ๋ฐ์ดํฐ ์ฆ๊ฐ: ํ์ , ํฌ๋กญ, ์์ ์กฐ์ ๋ฑ์ ํตํ ๋ฐ์ดํฐ ์ฆ๊ฐ
- ๋ผ๋ฒจ๋ง: ๊ฐ์ค ID ๊ธฐ๋ฐ ์๋ ๋ผ๋ฒจ๋ง
ํ๋ จ ์ ์ฐจ
์ ์ฒ๋ฆฌ
- ์ด๋ฏธ์ง ํฌ๊ธฐ ์กฐ์ : 224x224 ํฝ์ ๋ก ๋ฆฌ์ฌ์ด์ฆ
- ์ค์ ํฌ๋กญ: ์ ์ฌ๊ฐํ ๋น์จ๋ก ์ค์ ํฌ๋กญ
- ์ ๊ทํ: ImageNet ํ์ค๊ฐ์ผ๋ก ์ ๊ทํ
- ๋ฐ์ดํฐ ์ฆ๊ฐ: ํ๋ จ ์ค ๋๋ค ๋ณํ ์ ์ฉ
ํ๋ จ ํ์ดํผํ๋ผ๋ฏธํฐ
- ๋ฐฐ์น ํฌ๊ธฐ: 64
- ํ์ต๋ฅ : 1e-4 (์ฌ์ ํ๋ จ), 5e-5 (๋ฏธ์ธ์กฐ์ )
- ์ํญ: 30 (์ฌ์ ํ๋ จ), 15 (๋ฏธ์ธ์กฐ์ )
- ์ตํฐ๋ง์ด์ : AdamW
- ์ค์ผ์ค๋ฌ: Cosine Annealing
- ์ ๊ทํ: Dropout (0.1), Weight Decay (1e-4)
์๋, ํฌ๊ธฐ, ์๊ฐ
- ํ๋ จ ์๊ฐ: ์ฝ 8์๊ฐ (RTX 3080 ๊ธฐ์ค)
- ๋ชจ๋ธ ํฌ๊ธฐ: 25MB (PyTorch), 12MB (ONNX)
- ์ถ๋ก ์๋: 500 ์/์ด (ONNX, CPU), 2000 ์/์ด (ONNX, GPU)
ํ๊ฐ
ํ ์คํธ ๋ฐ์ดํฐ, ์์ธ ๋ฐ ๋ฉํธ๋ฆญ
ํ ์คํธ ๋ฐ์ดํฐ
- ๊ฒ์ฆ ์ธํธ: 10,000๊ฐ์ ์ด๋ฏธ์ง ์
- ํ ์คํธ ์ธํธ: 5,000๊ฐ์ ์ด๋ฏธ์ง ์
- ๋ฐ์ดํฐ ๋ถํ : ๊ฐ์ค ID ๊ธฐ์ค์ผ๋ก ๋ถํ ํ์ฌ ๋ฐ์ดํฐ ๋์ ๋ฐฉ์ง
์์ธ
- ๊ฐ์ค ํ์ : ๋ค์ํ ๊ฐ์ค ํ์ ๋ณ ์ฑ๋ฅ ๋ถ์
- ์ด๋ฏธ์ง ํ์ง: ๊ณ ํ์ง/์ ํ์ง ์ด๋ฏธ์ง๋ณ ์ฑ๋ฅ
- ์กฐ๋ช ์กฐ๊ฑด: ์์ฐ๊ด/์ธ๊ณต๊ด ์กฐ๊ฑด๋ณ ์ฑ๋ฅ
๋ฉํธ๋ฆญ
- ์ ํ๋ (Accuracy): ์ ์ฒด ์์ธก ์ค ์ ํํ ์์ธก ๋น์จ
- ์ ๋ฐ๋ (Precision): ์ ์ฌํ๋ค๊ณ ์์ธกํ ๊ฒ ์ค ์ค์ ๋ก ์ ์ฌํ ๋น์จ
- ์ฌํ์จ (Recall): ์ค์ ์ ์ฌํ ๊ฒ ์ค ์ฌ๋ฐ๋ฅด๊ฒ ์์ธกํ ๋น์จ
- F1-Score: ์ ๋ฐ๋์ ์ฌํ์จ์ ์กฐํํ๊ท
- AUC-ROC: ROC ๊ณก์ ์๋ ๋ฉด์
๊ฒฐ๊ณผ
์์ฝ
- ์ ์ฒด ์ ํ๋: 92.3%
- F1-Score: 0.91
- AUC-ROC: 0.95
- ์ถ๋ก ์๋: 500 ์/์ด (ONNX, CPU)
๋ชจ๋ธ ๊ฒ์ฌ
ํด์ ๊ฐ๋ฅ์ฑ
- Grad-CAM: ๋ชจ๋ธ์ด ์ฃผ๋ชฉํ๋ ์ด๋ฏธ์ง ์์ญ ์๊ฐํ
- ์ ์ฌ๋ ๋ถํฌ: ๊ธ์ /๋ถ์ ์์ ์ ์ฌ๋ ์ ์ ๋ถํฌ ๋ถ์
- ์ค๋ถ๋ฅ ๋ถ์: ์๋ชป ๋ถ๋ฅ๋ ์ผ์ด์ค์ ํจํด ๋ถ์
๊ธฐ์ ์ฌ์
๋ชจ๋ธ ์ํคํ ์ฒ ๋ฐ ๋ชฉ์
- ์ํคํ ์ฒ: Siamese Network with EfficientNetV2-Small backbone
- ๋ชฉ์ : ์ด๋ฏธ์ง ์์ ์ ์ฌ๋ ์ธก์
- ์ถ๋ ฅ: 0-1 ์ฌ์ด์ ์ ์ฌ๋ ์ ์
- ์์ค ํจ์: Focal Loss (ฮฑ=0.25, ฮณ=2.0)
์ปดํจํ ์ธํ๋ผ
ํ๋์จ์ด
- GPU: NVIDIA RTX 3080 (10GB VRAM)
- CPU: Intel i7-10700K
- RAM: 32GB DDR4
- ์ ์ฅ๊ณต๊ฐ: 1TB NVMe SSD
์ํํธ์จ์ด
- Python: 3.9
- PyTorch: 1.12.0
- ONNX Runtime: 1.12.0
- CUDA: 11.6
- ๊ธฐํ: timm, torchvision, PIL
์ธ์ฉ
์ด ๋ชจ๋ธ์ ์ฌ์ฉํ์๋ ๊ฒฝ์ฐ, ๋ค์ ํ์์ผ๋ก ์ธ์ฉํด ์ฃผ์ธ์:
BibTeX:
@misc{room_image_similarity_model,
title={Room Image Similarity Model: Siamese Network for Hotel Room Image Comparison},
author={Your Name},
year={2024},
howpublished={Hugging Face Model Hub},
url={https://huggingface.co/ondame/room-image-similarity}
}
APA:
Your Name. (2024). Room Image Similarity Model: Siamese Network for Hotel Room Image Comparison. Hugging Face Model Hub. https://huggingface.co/your-username/room-image-similarity
์ฉ์ด์ง
- Siamese Network: ๋ ์ ๋ ฅ์ ๋์ผํ ๋คํธ์ํฌ๋ก ์ฒ๋ฆฌํ์ฌ ์ ์ฌ๋๋ฅผ ๊ณ์ฐํ๋ ์ ๊ฒฝ๋ง ๊ตฌ์กฐ
- EfficientNetV2: ํจ์จ์ ์ธ ์ด๋ฏธ์ง ๋ถ๋ฅ๋ฅผ ์ํ CNN ์ํคํ ์ฒ
- Focal Loss: ๋ถ๊ท ํ ๋ฐ์ดํฐ์ ์ ์ต์ ํ๋ ์์ค ํจ์
- ImageNet ์ ๊ทํ: ImageNet ๋ฐ์ดํฐ์ ์ ํ๊ท ๊ณผ ํ์คํธ์ฐจ๋ฅผ ์ฌ์ฉํ ์ด๋ฏธ์ง ์ ๊ทํ
์ถ๊ฐ ์ ๋ณด
- ํ๋ก์ ํธ ์ ์ฅ์: GitHub Repository
- ๋ฌธ์: ํ๋ก์ ํธ ๋ฌธ์
- ์ด์ ๋ฆฌํฌํธ: GitHub Issues