成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用FastEmbed和Qdrant構建一個男士服裝推薦系統

譯文 精選
人工智能
本文將構建一個男士服裝推薦系統,它將使用圖片嵌入和Qdrant矢量數據庫。你將從原始圖片數據進入到實時視覺推薦。

譯者 | 布加迪

審校 | 重樓

NetflixSpotify到亞馬遜,推薦系統無處不在。但是如果你想構建一個不僅關注標題或標簽,還關注圖片的視覺推薦引擎,該如何創建?本文將構建一個男士服裝推薦系統,它將使用圖片嵌入和Qdrant矢量數據庫。你將從原始圖片數據進入到實時視覺推薦。

學習目標

  • 圖片嵌入如何表示視覺內容?
  • 如何使用FastEmbed生成矢量?
  • 如何使用Qdrant存儲和搜索矢量?
  • 如何構建反饋驅動的推薦引擎?
  • 如何使用Streamlit創建簡單的用戶界面?

用例:T恤和Polo衫的視覺推薦

想象一下,用戶點擊了一件時尚的Polo衫。你的服裝推薦系統不再使用產品標簽,而是推薦外觀相似的T恤和Polo衫。它使用圖片本身來做出決策。

不妨探索如何做到這一點。

1步:理解圖片嵌入

什么是圖片嵌入?

圖片嵌入是一個矢量,它是一個數字列表。這些數字代表圖片中的關鍵特征。兩張相似的圖片在矢量空間中有相近的嵌入。這使得系統能夠測量視覺相似性。

比如說,兩件不同的T恤可能在像素上看起來不同。但如果它們的顏色、圖案和紋理相似,它們的嵌入就很接近。這對于服裝推薦系統來說至關重要。

如何生成嵌入?

大多數嵌入模型都使用深度學習。CNN(卷積神經網絡)提取視覺模式。這些模式成為矢量的一部分。

我們在本文中使用FastEmbed。這里使用的嵌入模型是:Qdrant/Unicom-ViT-B-32

from fastembed import ImageEmbedding
from typing import List
from dotenv import load_dotenv
import os

load_dotenv()
model = ImageEmbedding(os.getenv("IMAGE_EMBEDDING_MODEL"))

def compute_image_embedding(image_paths: List[str]) -> list[float]:
 return list(model.embed(image_paths))

該函數接受一個圖片路徑列表。它返回捕捉這些圖片精髓的矢量。

2步:獲取數據集

我們使用了一個包含約2000張男士服裝圖片的數據集。你可以在Kaggle上找到它。以下是我們加載數據集的方法:

import shutil, os, kagglehub
from dotenv import load_dotenv

load_dotenv()
kaggle_repo = os.getenv("KAGGLE_REPO")
path = kagglehub.dataset_download(kaggle_repo)
target_folder = os.getenv("DATA_PATH")

def getData():
 if not os.path.exists(target_folder):
 shutil.copytree(path, target_folder)

該腳本檢查目標文件夾是否存在。如果不存在,將圖片復制到該文件夾

3步:使用Qdrant存儲和搜索矢量

有了嵌入后,我們需要存儲和搜索它們。這時Qdrant就派上用場了。它是一個快速且可擴展的矢量數據庫。

以下是連接到Qdrant矢量數據庫的方法:

from qdrant_client import QdrantClient

client = QdrantClient(
 url=os.getenv("QDRANT_URL"),
 api_key=os.getenv("QDRANT_API_KEY"),
)
This is how to insert the images paired with its embedding to a Qdrant collection:
class VectorStore:
 def __init__(self, embed_batch: int = 64, upload_batch: int = 32, parallel_uploads: int = 3):
 # ... (initializer code omitted for brevity) ...

 def insert_images(self, image_paths: List[str]):
 def chunked(iterable, size):
 for i in range(0, len(iterable), size):
 yield iterable[i:i + size]

 for batch in chunked(image_paths, self.embed_batch):
 embeddings = compute_image_embedding(batch) # Batch embed
 points = [
 models.PointStruct(id=str(uuid.uuid4()), vector=emb, payload={"image_path": img})
 for emb, img in zip(embeddings, batch)
 ]

 # Batch upload each sub-batch
 self.client.upload_points(
 collection_name=self.collection_name,
 points=points,
 batch_size=self.upload_batch,
 parallel=self.parallel_uploads,
 max_retries=3,
 wait=True
 )

該代碼獲取圖片文件路徑列表,將其批量轉換成嵌入,然后將這些嵌入上傳到Qdrant集合。它先檢查該集合是否存在。然后,它使用線程并行處理圖片以加快速度。每幅圖片都會獲得一個唯一的 ID,并與其嵌入和路徑一起被封裝成一個“點”。然后,這些點被分塊上傳到 Qdrant

搜索相似的圖片

def search_similar(query_image_path: str, limit: int = 5):
 emb_list = compute_image_embedding([query_image_path])
 hits = client.search(
 collection_name="fashion_images",
 query_vector=emb_list[0],
 limit=limit
 )
 return [{"id": h.id, "image_path": h.payload.get("image_path")} for h in hits]

你提供一張查詢圖片。系統會使用余弦相似度指標返回視覺上相似的圖片。

4步:創建帶有反饋的推薦引擎

現在我們更進一步。如果用戶喜歡某些圖片而不喜歡其他圖片怎么辦?服裝推薦系統能從中學習嗎?

是的。Qdrant允許我們提供正面反饋和負面反饋。然后它會返回更好、更個性化的結果。

class RecommendationEngine:
 def get_recommendations(self, liked_images:List[str], disliked_images:List[str], limit=10):
 recommended = client.recommend(
 collection_name="fashion_images",
 positive=liked_images,
 negative=disliked_images,
 limit=limit
 )
 return [{"id": hit.id, "image_path": hit.payload.get("image_path")} for hit in recommended]

以下是該函數的輸入:

  • liked_images:代表用戶喜歡的商品的圖片ID 列表。
  • disliked_images:代表用戶不喜歡的商品的圖片ID 列表。
  • limit(可選):這個整數指定返回的最大推薦數量(默認為 10)。

這將使用之前介紹的嵌入矢量相似度返回推薦的服裝。

這讓你的系統可以適應變化,快速學習用戶偏好。

5步:使用Streamlit構建 UI

我們使用Streamlit來創建界面。它簡單、快速,用Python 編寫。

用戶可以:

  • 瀏覽服裝
  • 點贊或點踩商品
  • 查看新的、更合理的推薦

以下是Streamlit代碼:

import streamlit as st
from PIL import Image
import os

from src.recommendation.engine import RecommendationEngine
from src.vector_database.vectorstore import VectorStore
from src.data.get_data import getData

# -------------- Config --------------
st.set_page_config(page_title="?? Men's Fashion Recommender", layout="wide")
IMAGES_PER_PAGE = 12

# -------------- Ensure Dataset Exists (once) --------------
@st.cache_resource
def initialize_data():
 getData()
 return VectorStore(), RecommendationEngine()

vector_store, recommendation_engine = initialize_data()

# -------------- Session State Defaults --------------
session_defaults = {
 "liked": {},
 "disliked": {},
 "current_page": 0,
 "recommended_images": vector_store.points,
 "vector_store": vector_store,
 "recommendation_engine": recommendation_engine,
}

for key, value in session_defaults.items():
 if key not in st.session_state:
 st.session_state[key] = value

# -------------- Sidebar Info --------------
with st.sidebar:
 st.title("?? Men's Fashion Recommender")

 st.markdown("""
 **Discover fashion styles that suit your taste.** 
 Like ?? or dislike ?? outfits and receive AI-powered recommendations tailored to you.
 """)

 st.markdown("### ?? Dataset")
 st.markdown("""
 - Source: [Kaggle – virat164/fashion-database](https://www.kaggle.com/datasets/virat164/fashion-database) 
 - ~2,000 fashion images
 """)

 st.markdown("### ?? How It Works")
 st.markdown("""
 1. Images are embedded into vector space 
 2. You provide preferences via Like/Dislike 
 3. Qdrant finds visually similar images 
 4. Results are updated in real-time
 """)

 st.markdown("### ?? Technologies")
 st.markdown("""
 - **Streamlit** UI 
 - **Qdrant** vector DB 
 - **Python** backend 
 - **PIL** for image handling 
 - **Kaggle API** for data
 """)

 st.markdown("---")
# -------------- Core Logic Functions --------------
def get_recommendations(liked_ids, disliked_ids):
 return st.session_state.recommendation_engine.get_recommendations(
 liked_images=liked_ids,
 disliked_images=disliked_ids,
 limit=3 * IMAGES_PER_PAGE
 )

def refresh_recommendations():
 liked_ids = list(st.session_state.liked.keys())
 disliked_ids = list(st.session_state.disliked.keys())
 st.session_state.recommended_images = get_recommendations(liked_ids, disliked_ids)

# -------------- Display: Selected Preferences --------------
def display_selected_images():
 if not st.session_state.liked and not st.session_state.disliked:
 return

 st.markdown("### ?? Your Picks")
 cols = st.columns(6)
 images = st.session_state.vector_store.points

 for i, (img_id, status) in enumerate(
 list(st.session_state.liked.items()) + list(st.session_state.disliked.items())
 ):
 img_path = next((img["image_path"] for img in images if img["id"] == img_id), None)
 if img_path and os.path.exists(img_path):
 with cols[i % 6]:
 st.image(img_path, use_container_width=True, captinotallow=f"{img_id} ({status})")
 col1, col2 = st.columns(2)
 if col1.button("? Remove", key=f"remove_{img_id}"):
 if status == "liked":
 del st.session_state.liked[img_id]
 else:
 del st.session_state.disliked[img_id]
 refresh_recommendations()
 st.rerun()

 if col2.button("?? Switch", key=f"switch_{img_id}"):
 if status == "liked":
 del st.session_state.liked[img_id]
 st.session_state.disliked[img_id] = "disliked"
 else:
 del st.session_state.disliked[img_id]
 st.session_state.liked[img_id] = "liked"
 refresh_recommendations()
 st.rerun()

# -------------- Display: Recommended Gallery --------------
def display_gallery():
 st.markdown("### ?? Smart Suggestions")

 page = st.session_state.current_page
 start_idx = page * IMAGES_PER_PAGE
 end_idx = start_idx + IMAGES_PER_PAGE
 current_images = st.session_state.recommended_images[start_idx:end_idx]

 cols = st.columns(4)
 for idx, img in enumerate(current_images):
 with cols[idx % 4]:
 if os.path.exists(img["image_path"]):
 st.image(img["image_path"], use_container_width=True)
 else:
 st.warning("Image not found")

 col1, col2 = st.columns(2)
 if col1.button("?? Like", key=f"like_{img['id']}"):
 st.session_state.liked[img["id"]] = "liked"
 refresh_recommendations()
 st.rerun()
 if col2.button("?? Dislike", key=f"dislike_{img['id']}"):
 st.session_state.disliked[img["id"]] = "disliked"
 refresh_recommendations()
 st.rerun()

 # Pagination
 col1, _, col3 = st.columns([1, 2, 1])
 with col1:
 if st.button("?? Previous") and page > 0:
 st.session_state.current_page -= 1
 st.rerun()
 with col3:
 if st.button("?? Next") and end_idx < len(st.session_state.recommended_images):
 st.session_state.current_page += 1
 st.rerun()

# -------------- Main Render Pipeline --------------
st.title("?? Men's Fashion Recommender")

display_selected_images()
st.divider()
display_gallery()

This UI closes the loop. It turns a function into a usable product.

結論

你剛構建了一個完整的服裝推薦系統,它可以識別圖片、理解視覺特征并提供智能推薦。

使用 FastEmbedQdrantStreamlit,你現在有了一個強大的推薦系統。它適用于T恤、Polo衫以及任何男士服裝,但也可以適用于任何其他基于圖片的推薦。

原文標題:Build a Men’s Fashion Recommendation System Using FastEmbed and Qdrant,作者:Rindra Randriamihamina

責任編輯:姜華 來源: 51CTO
相關推薦

2022-02-07 19:59:54

CMakeVSCodium編程語言

2023-09-05 09:00:00

工具Python抄襲檢測系統

2022-04-01 15:36:05

Python推薦系統數據

2025-04-01 09:31:34

PyTorch自動語音識別ASR系統

2025-05-06 08:23:56

Llama 4AutoGenAI智能體

2025-01-09 06:00:00

Checkmate監控系統開源

2016-09-21 12:54:10

CAAS系統鏡像

2023-02-13 14:47:32

人工智能機器學習ChatGPT

2014-02-26 10:14:51

OpenStack測試系統

2018-08-27 17:05:48

tensorflow神經網絡圖像處理

2021-08-27 12:16:34

fastjarJAR文件Java

2018-11-14 19:00:24

PythonRedis共享單車

2009-04-28 09:44:31

jQueryAjaxphp

2021-07-14 17:39:46

ReactRails API前端組件

2023-09-21 08:00:00

ChatGPT編程工具

2018-05-25 08:44:22

樹莓派PythonMySQL

2023-03-10 13:38:00

Python文檔掃描器

2018-07-12 09:00:00

LinuxUnix在線測試

2022-07-31 15:46:30

Web自動智能停車

2019-10-22 11:42:29

sshuttle虛擬專網Linux
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精品99 | 久久综合一区 | 99re在线| 国产中文字幕在线 | 亚洲欧美一区二区三区国产精品 | 日韩久草 | 国产精品久久久久一区二区 | 日本一区二区高清不卡 | 国产一二三区免费视频 | 成人免费激情视频 | 欧美a在线观看 | 亚洲一区二区三区免费观看 | 国产欧美一区二区精品忘忧草 | 国产精品视频入口 | 欧美日韩国产精品一区二区 | 亚洲精品一区二区冲田杏梨 | 999久久久 | 懂色av色香蕉一区二区蜜桃 | 成人亚洲精品久久久久软件 | 中文字幕av色 | 亚洲最新在线 | 免费国产视频 | 成人自拍av | 国产黄色在线观看 | 日韩在线不卡 | 久久久久亚洲 | 欧美6一10sex性hd | 亚洲精品一区二三区不卡 | 久久黄色| 精品亚洲一区二区三区 | 中文字幕一区二区三区精彩视频 | 欧美成人激情 | 黄页网址在线观看 | 自拍偷拍精品 | 欧美黄色一区 | 国产精品九九 | 国产欧美一区二区三区日本久久久 | 亚洲一区二区免费 | 欧美精品一区在线发布 | 精品一区电影 | 99色综合|