
有道翻譯API:開啟多語言交流新篇章
下一步是從嵌入向量列表創建 FAISS 索引。FAISS 為相似性搜索提供了各種距離度量,包括內積 (IP) 和 L2(歐幾里得)距離。
FAISS 還提供各種索引選項。它可以使用近似或壓縮技術來有效處理大型數據集,同時平衡搜索速度和準確性。在本教程中,我們將使用“平面”索引,它通過將查詢向量與數據集中的每個向量進行比較來執行強力搜索,以確保以更高的計算復雜度為代價獲得準確的結果。
def create_faiss_index(embeddings, image_paths, output_path):
dimension = len(embeddings[0])
index = faiss.IndexFlatIP(dimension)
index = faiss.IndexIDMap(index)
vectors = np.array(embeddings).astype(np.float32)
# Add vectors to the index with IDs
index.add_with_ids(vectors, np.array(range(len(embeddings))))
# Save the index
faiss.write_index(index, output_path)
print(f"Index created and saved to {output_path}")
# Save image paths
with open(output_path + '.paths', 'w') as f:
for img_path in image_paths:
f.write(img_path + '\n')
return index
OUTPUT_INDEX_PATH = "/content/vector.index"
index = create_faiss_index(embeddings, image_paths, OUTPUT_INDEX_PATH)
faiss.IndexFlatIP
初始化內積相似度索引,將其包裝在 faiss.IndexIDMap
中,以將每個向量與 ID 關聯。接下來, index.add_with_ids
將向量添加到具有連續 ID 的索引中,并將索引與圖像路徑一起保存到磁盤。
索引可以立即使用,也可以保存到磁盤以備將來使用。要加載 FAISS 索引,我們將使用以下函數:
def load_faiss_index(index_path):
index = faiss.read_index(index_path)
with open(index_path + '.paths', 'r') as f:
image_paths = [line.strip() for line in f]
print(f"Index loaded from {index_path}")
return index, image_paths
index, image_paths = load_faiss_index(OUTPUT_INDEX_PATH)
建立 FAISS 索引后,我們現在可以使用文本查詢或參考圖像檢索圖像。如果查詢是圖像路徑,則使用 PIL的 Image.open
打開查詢。接下來,使用 CLIP的 model.encode
提取查詢嵌入向量。
def retrieve_similar_images(query, model, index, image_paths, top_k=3):
# query preprocess:
if query.endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif')):
query = Image.open(query)
query_features = model.encode(query)
query_features = query_features.astype(np.float32).reshape(1, -1)
distances, indices = index.search(query_features, top_k)
retrieved_images = [image_paths[int(idx)] for idx in indices[0]]
return query, retrieved_images
檢索發生在 index.search
方法上。它實現了 k-最近鄰 (kNN) 搜索,以找到與查詢向量最相似的 k 個向量。我們可以通過更改 top_k
參數來調整 k 的值。在我們的實現中,kNN 搜索中使用的距離度量是余弦相似度。該函數返回查詢和檢索圖像路徑的列表。
現在我們準備使用文本查詢進行搜索。輔助函數 visualize_results
顯示結果。你可以在關聯的 Colab 筆記本中找到它。讓我們探索針對文本查詢“ball”檢索到的最相似的 3 幅圖像,例如:
query = 'ball'
query, retrieved_images = retrieve_similar_images(query, model, index, image_paths, top_k=3)
visualize_results(query, retrieved_images)
對于查詢“animal”,我們得到:
使用參考圖像搜索:
query ='/content/drive/MyDrive/Colab Notebooks/my_medium_projects/Image_similarity_search/image_dataset/pexels-w-w-299285-889839.jpg'
query, retrieved_images = retrieve_similar_images(query, model, index, image_paths, top_k=3)
visualize_results(query, retrieved_images)
如我們所見,我們為現成的預訓練模型獲得了非??岬慕Y果。當我們通過眼睛繪畫的參考圖像進行搜索時,除了找到原始圖像外,它還找到了一個匹配的眼鏡和另一幅畫。這展示了查詢圖像語義含義的不同方面。
在本教程中,我們使用 CLIP 和 FAISS 構建了一個基本的圖像相似性搜索引擎。檢索到的圖像與查詢具有相似的語義含義,表明該方法的有效性。
雖然 CLIP 對于零樣本模型顯示出不錯的結果,但它在分布外數據、細粒度任務上可能表現出較低的性能,并繼承了訓練數據的自然偏差。為了克服這些限制,你可以嘗試其他類似 CLIP 的預訓練模型(如 OpenClip),或者在自己的自定義數據集上微調 CLIP。
原文鏈接:http://www.bimant.com/blog/image-search-engine-diy/