Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于查询milvus的向量精度问题 #901

Open
Wimeremce7 opened this issue May 14, 2024 · 17 comments
Open

关于查询milvus的向量精度问题 #901

Wimeremce7 opened this issue May 14, 2024 · 17 comments

Comments

@Wimeremce7
Copy link

Wimeremce7 commented May 14, 2024

image
看到SearchParam的withFloatVectors方法,入参是‘’Float‘’ ,用float的话,会导致精度丢失,这个有什么解决方案吗?

@xiaofan-luan
Copy link
Contributor

image 看到SearchParam的withFloatVectors方法,入参是‘’Float‘’ ,用float的话,会导致精度丢失,这个有什么解决方案吗?

为什么用float会导致精度丢失?据我所知还没有用double向量的模型

@Wimeremce7
Copy link
Author

Wimeremce7 commented May 15, 2024

image 看到SearchParam的withFloatVectors方法,入参是‘’Float‘’ ,用float的话,会导致精度丢失,这个有什么解决方案吗?

为什么用float会导致精度丢失?据我所知还没有用double向量的模型

float精度只有小数点后7位,milvus存储的向量和embedding转化的向量都不止这些。
存储的向量:
image
embedding转化的向量:
image

然后查询的时候只能用float的话,其实是会把精度丢失掉

@xiaofan-luan
Copy link
Contributor

image 看到SearchParam的withFloatVectors方法,入参是‘’Float‘’ ,用float的话,会导致精度丢失,这个有什么解决方案吗?

为什么用float会导致精度丢失?据我所知还没有用double向量的模型

float精度只有小数点后7位,milvus存储的向量和embedding转化的向量都不止这些。 存储的向量: image embedding转化的向量: image

然后查询的时候只能用float的话,其实是会把精度丢失掉

你错误理解了精度和展示的定位。精度的意思,指的就是后面虽然有很多位,但是都不准。你用的是float数据类型,精度就只用这么多。展示出来的东西精度本来就是不对的,原因是js只能支持64位float,也就是double

@Wimeremce7
Copy link
Author

Wimeremce7 commented May 15, 2024

image 看到SearchParam的withFloatVectors方法,入参是‘’Float‘’ ,用float的话,会导致精度丢失,这个有什么解决方案吗?

为什么用float会导致精度丢失?据我所知还没有用double向量的模型

float精度只有小数点后7位,milvus存储的向量和embedding转化的向量都不止这些。 存储的向量: image embedding转化的向量: image
然后查询的时候只能用float的话,其实是会把精度丢失掉

你错误理解了精度和展示的定位。精度的意思,指的就是后面虽然有很多位,但是都不准。你用的是float数据类型,精度就只用这么多。展示出来的东西精度本来就是不对的,原因是js只能支持64位float,也就是double

好的,了解了

@XueJian-Zhang
Copy link

你好,我遇到了跟你一样的问题,创建milvus向量字段类型是FloatVector,然后插入的向量是这种的
企业微信截图_17163602043077
但是获取到以后是这样的
企业微信截图_17163604598560
请问有什么解决办法么?

@xiaofan-luan
Copy link
Contributor

你好,我遇到了跟你一样的问题,创建milvus向量字段类型是FloatVector,然后插入的向量是这种的 企业微信截图_17163602043077 但是获取到以后是这样的 企业微信截图_17163604598560 请问有什么解决办法么?

请问你怎么生成的向量?然后怎么打印的向量
floatvector打印出来不可能有那么多位数的

@xiaofan-luan
Copy link
Contributor

大概率你这个数据存错了,用了double格式。这点精度对于搜索不会有任何区别

@XueJian-Zhang
Copy link

你好,我遇到了跟你一样的问题,创建milvus向量字段类型是FloatVector,然后插入的向量是这种的 企业微信截图_17163602043077 但是获取到以后是这样的 企业微信截图_17163604598560 请问有什么解决办法么?

请问你怎么生成的向量?然后怎么打印的向量 floatvector打印出来不可能有那么多位数的

这个是python一个自定义的工具类,用于提取照片的某些特征值生成的向量。

@XueJian-Zhang
Copy link

大概率你这个数据存错了,用了double格式。这点精度对于搜索不会有任何区别

经过提醒。我查看了代码。没有用double,因为定义集合时设置了向量类型是FloatVector,在存储数据时,不能用double格式的,那样会产生“Type mismatch for field 'feature': Float vector field's value type must be List”错误,所以用的List。然后存储的时候向量值是
企业微信截图_17163654011856
,但是在milvus的可视化平台中,存储的向量值和postman中发送的请求参数一致。
企业微信截图_17163652912278

@shanghaikid
Copy link

shanghaikid commented May 22, 2024

但是获取到以后是这样的

请问你是用什么办法获取的? restful api? @XueJian-Zhang

@Wimeremce7
Copy link
Author

大概率你这个数据存错了,用了double格式。这点精度对于搜索不会有任何区别

经过提醒。我查看了代码。没有用double,因为定义集合时设置了向量类型是FloatVector,在存储数据时,不能用double格式的,那样会产生“Type mismatch for field 'feature': Float vector field's value type must be List”错误,所以用的List。然后存储的时候向量值是 企业微信截图_17163654011856 ,但是在milvus的可视化平台中,存储的向量值和postman中发送的请求参数一致。 企业微信截图_17163652912278

他们目前不支持double,至于attu客户端显示的向量小数位数,是因为js会自动补小数,并不能当真。

@XueJian-Zhang
Copy link

但是获取到以后是这样的

请问你是用什么办法获取的? restful api? @XueJian-Zhang

直接调用milvus的api就可以获取到,网上有很多教程。你可以参考下这位博主的方法:https://blog.csdn.net/lsqingfeng/article/details/138212915

@XueJian-Zhang
Copy link

大概率你这个数据存错了,用了double格式。这点精度对于搜索不会有任何区别

经过提醒。我查看了代码。没有用double,因为定义集合时设置了向量类型是FloatVector,在存储数据时,不能用double格式的,那样会产生“Type mismatch for field 'feature': Float vector field's value type must be List”错误,所以用的List。然后存储的时候向量值是 企业微信截图_17163654011856 ,但是在milvus的可视化平台中,存储的向量值和postman中发送的请求参数一致。 企业微信截图_17163652912278

他们目前不支持double,至于attu客户端显示的向量小数位数,是因为js会自动补小数,并不能当真。

好的,谢谢。

@yhmo
Copy link
Contributor

yhmo commented May 22, 2024

python/javascript这些语言的浮点型是跟系统的位数走的,64位系统就会以64位来表示浮点数,但实际上在调用milvus rpc接口的时候其实都是以float32传输。对于用户来说就像变了个魔术似的。
但java是强制要求Float也就是32位输入,熟悉java的用户不应该有这种迷惑。
以32位浮点输入就已经明确告诉你向量在后台是以32位数据传输,存储,以及计算。所以它根本不可能再变出64位精度的小数给你。
向量近似近邻检索已经是一个模糊检索的概念,用来比对相似的事物。如果说我们要比较两张人脸是否相似,难道我们会去关心这两人的头发数量是否相等么?在大部分场景下,用64位精度的向量就相当于掩耳盗铃,非但对召回率没什么影响,计算负载和内存负载还大了一倍,得不偿失。

@XueJian-Zhang
Copy link

python/javascript这些语言的浮点型是跟系统的位数走的,64位系统就会以64位来表示浮点数,但实际上在调用milvus rpc接口的时候其实都是以float32传输。对于用户来说就像变了个魔术似的。 但java是强制要求Float也就是32位输入,熟悉java的用户不应该有这种迷惑。 以32位浮点输入就已经明确告诉你向量在后台是以32位数据传输,存储,以及计算。所以它根本不可能再变出64位精度的小数给你。 向量近似近邻检索已经是一个模糊检索的概念,用来比对相似的事物。如果说我们要比较两张人脸是否相似,难道我们会去关心这两人的头发数量是否相等么?在大部分场景下,用64位精度的向量就相当于掩耳盗铃,非但对召回率没什么影响,计算负载和内存负载还大了一倍,得不偿失。

你好,我使用python的两种方式查询了同一个id的向量值,可是得到的向量值却不相同,一种是根据向量id,另一种是根据向量值。请问为什么查询结果向量值的精度会不一样呢?
企业微信截图_17164599374880

@yhmo
Copy link
Contributor

yhmo commented May 24, 2024

你用的是python sdk,我说过python语言对于浮点型的数值总是转成64位显示。
如果你懂得怎么在python sdk里调试的话,你会看到query()接口会调用到这里:https://github.com/milvus-io/pymilvus/blob/473f62fee6cb5e446f571471884d0d7303d01ab6/pymilvus/client/entity_helper.py#L481

我们把这几行代码改成如下:

      if field_data.type == DataType.FLOAT_VECTOR:
           dim = field_data.vectors.dim
           if len(field_data.vectors.float_vector.data) >= index * dim:
               start_pos, end_pos = index * dim, (index + 1) * dim
               entity_row_data[field_data.field_name] = []
               print(field_data.vectors.float_vector)
               for x in field_data.vectors.float_vector.data[start_pos:end_pos]:
                   print(x)
                   entity_row_data[field_data.field_name].append(np.single(x))
               print(entity_row_data[field_data.field_name])

打断点进入,你会看到 field_data.vectors.float_vector 这个是由Milvus rpc接口返回的结构体,打印出来的值是32位浮点型。
然后for x in field_data.vectors.float_vector.data[start_pos:end_pos] 这行里的 x 打印出来就变成了64位浮点型,所以知道我为何说“python语言对于浮点型的数值总是转成64位显示”了吧。
后面几行又做了什么呢? append(np.single(x)),看到np.single(x)了吧,这是numpy的single,指代float32浮点型。这里是把64位的x又cut成了32位浮点数。
所以你看到的query的结果里都是以32位浮点型显示。

再来看search()接口干了什么。
https://github.com/milvus-io/pymilvus/blob/473f62fee6cb5e446f571471884d0d7303d01ab6/pymilvus/client/abstract.py#L480

if dtype == DataType.FLOAT_VECTOR:
                field2data[name] = vectors.float_vector.data[start * dim : end * dim], field_meta
                continue

它直接把rpc接口返回的response包装成SearchResult给你,然后SearchResult里面是直接提取向量数据,没有经过numpy.single的转化,所以python自动用64位浮点型来表示。

@yhmo
Copy link
Contributor

yhmo commented May 24, 2024

再强调一遍,milvus服务端处理向量,无论是存储,计算还是输出,都是以float32来处理。各个SDK拿到的向量数据都是32位浮点型。如果你看到的是64位浮点数,那是因为某些语言本身自动把32位转成了64位表示,实际上32位精度之外的数字都是随机数字,没有任何意义。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants