基于Milvus的图像相似性搜索无结果问题求助
图像相似性搜索无结果排查问题
我参考图像反向搜索的Notebook开发相似性搜索功能,目前遇到搜索无结果的问题,但验证同一张图的向量余弦相似度接近1,说明向量存储是正确的,不清楚问题出在哪。
我的实现代码
初始化参数与索引创建
import csv from glob import glob from pathlib import Path from statistics import mean from towhee import pipe, ops, DataCollection from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility # Towhee parameters MODEL = 'resnet50' # Milvus parameters HOST = [MY_HOST] PORT = [MY_PORT] TOPK = 5 DIM = 2048 COLLECTION_NAME = 'images' INDEX_TYPE = 'IVF_FLAT' METRIC_TYPE = 'L2' index_params = { 'metric_type': METRIC_TYPE, 'index_type': INDEX_TYPE, 'params': {"nlist": 2048} } collection.create_index(field_name='image', index_params=index_params, index_name = "image_index")
图像向量化与数据插入
# Load image path def load_image(x): if x.endswith('csv'): with open(x) as f: reader = csv.reader(f) next(reader) for item in reader: yield item[1] else: for item in glob(x): yield item # Embedding pipeline p_embed = ( pipe.input('src') .flat_map('src', 'img_path', load_image) .map('img_path', 'img', ops.image_decode()) .map('img', 'vec', ops.image_embedding.timm(model_name=MODEL)) ) image_save_dir = [MY_IMAGE_PATH] p_display = p_embed.output('img_path', 'img', 'vec') result = DataCollection(p_display(image_save_dir)) # check result result.show() print(result[0]['img_path']) print(result[0]['vec']) connections.connect(alias='default', host=HOST, port=PORT) collection_name = "clothes" collection = Collection(name = collection_name) for i, r in enumerate(result): vector = r['vec'] collection.insert([ { "clothes_id" : i, "category" : "top", "color" : "black", "image" : vector, "gender" : ["F"], "style" : ["casual"], "thickness" : [], "season" : ["spring"] } ])
搜索代码(无结果)
p_search_pre = ( p_embed.map('vec', ('search_res'), ops.ann_search.milvus_client( host=HOST, port=PORT, limit=5, collection_name="clothes")) .map('search_res', 'pred', lambda x: [y[0] for y in x]) # get id ) p_search = p_search_pre.output('img_path', 'pred') # Search for example query image(s) collection.load() dc = p_search('[MY_IMAGE_PATH]/test37.png') # Display search results with image paths DataCollection(dc).show()
验证代码(余弦相似度接近1)
from numpy import dot from numpy.linalg import norm import numpy as np def cos_similarity(A, B): return dot(A, B) / (norm(A) * norm(B)) test_image = '[MY_IMAGE_PATH]/test38.png' p_display = p_embed.output('img_path', 'img', 'vec') result = DataCollection(p_display(image_save_dir)) collection_name = 'clothes' collection = Collection(name=collection_name) # get image vector where clothes_id=38 save_results = collection.query( expr="clothes_id == 38", output_fields=["clothes_id", "category", "color", "gender", "style", "thickness", "season", "image"] ) if save_results: saved_image_vector = save_results[0]["image"] result_vector = np.array(result[0]['vec']) saved_image_vector = np.array(saved_image_vector) # get similarity similarity = cos_similarity(result_vector, saved_image_vector) print(f"cosine similarity : {similarity}") else: print("there is no images")
问题点
- 执行搜索时无任何结果返回,但验证同一张图像的向量余弦相似度约为1,说明向量存储正确。
- 不清楚搜索无结果的原因。
可能的原因与解决方案
1. 索引创建时机错误
代码开头直接调用collection.create_index时,collection还未连接到Milvus或指定目标clothes集合,这行代码并未对实际使用的集合生效。
解决:在数据插入完成后,对clothes集合创建索引并加载:
# 插入数据后添加以下代码 collection.create_index(field_name='image', index_params=index_params, index_name="image_index") collection.load()
2. IVF_FLAT索引缺少搜索参数
IVF_FLAT索引搜索时需要指定nprobe参数(默认值过小会导致无法命中数据),当前搜索算子未配置该参数。
解决:在搜索算子中添加search_params={"nprobe": 10}(可根据nlist调整,一般设为nlist的1/10~1/20):
p_search_pre = ( p_embed.map('vec', ('search_res'), ops.ann_search.milvus_client( host=HOST, port=PORT, limit=5, collection_name="clothes", search_params={"nprobe": 10})) .map('search_res', 'pred', lambda x: [y[0] for y in x]) )
3. 搜索结果解析逻辑错误
Milvus搜索结果格式可能因版本不同有差异,当前lambda x: [y[0] for y in x]的解析逻辑可能不正确。
解决:先打印search_res查看实际结构,再调整解析逻辑:
p_search_pre = ( p_embed.map('vec', ('search_res'), ops.ann_search.milvus_client( host=HOST, port=PORT, limit=5, collection_name="clothes")) .map('search_res', 'pred', lambda x: print(x)) # 先打印结果结构 )
4. 集合字段维度不匹配
确认clothes集合中image字段的维度是否为2048(resnet50输出的向量维度),维度不匹配会导致搜索无结果。
解决:通过print(collection.schema)查看字段定义,确保image字段的dim参数为2048。
内容的提问来源于stack exchange,提问作者Rashad Tockey
相关产品推荐
相关产品推荐

