概述
问题
离线特征是python加工出来的,在python中默认也是float类型,java中xgboost相关的api也都是float类型,为啥进行特征比对的时候结果就不一致呢?
这就涉及到底层数据结构的实现了,也就是本篇的由来,下面我们一探究竟。
在进行xgboost模型线上特征加工的时候,数据是采用Java float存储,为啥采用float呢?
因为如下的Booster api
public float[][] predict(DMatrix data, boolean outputMargin, int treeLimit) throws XGBoostError
Java预测时候,入参为DMatrix,数据是用的float类型
# https://xgboost.readthedocs.io/en/release_1.5.0/jvm/javadocs/index.html
public DMatrix(float[] data,
int nrow,
int ncol,
float missing)
throws XGBoostError
create DMatrix from dense matrix
Parameters:
data - data values
nrow - number of rows
ncol - number of columns
missing - the specified value to represent the missing value
在Java中 float占用4个字节,包括:
- 1bit(符号位):0表示正数,1表示负数;
- 8bits(指数位):float的偏移量为2^8 - 1,double的偏移量为2^11 - 1;
- 23bits(尾数位):实际尾数部分中的小数点后的数值,规约浮点数使用标准的二进制科学计数法表示,其尾数范围在 [1,2),非规约浮点数的尾数部分范围在(0,1)
python中float类型是如何实现的?
python中的数值类型
共有三种不同的数值类型:整数、浮点数和复数。此外,布尔值是整数的一个子类型。
整数具有无限精度。
浮点数通常在 C 中使用double实现;有关运行程序的机器的浮点数精度和内部表示的信息可在sys.float_info. (这个就是Java float和python float数据存在差异的原因)
所以float是8个字节是真正的数字,但是float对象是24字节的。
复数具有实部和虚部,每个都是浮点数。要从复数z中提取这些部分,请使用z.real
和z.imag
。(标准库包括额外的数字类型fractions.Fraction,用于有理数,和decimal.Decimal,用于具有用户可定义精度的浮点数。)
参见:Built-in Types — Python 3.11.0 documentation
案例重现
python具体示例:
>>> float(0.63693581908)
0.63693581908
>>> np.float16(0.63693581908)
0.6367
>>> np.float32(0.63693581908)
0.63693583
>>> np.float64(0.63693581908)
0.63693581908
Java具体示例
double a = -636935.81908; float b = (float) -636935.81908; float c = (float) -0.63693581908; float d = (float) 0.63693581908; System.out.println(a); System.out.println(b); System.out.println(c); System.out.println(d);
-636935.81908
-636935.8
-0.63693583
0.63693583
结论:
1、python中的float是和Java中的double是精度一样的
2、numpy中的float32是和Java中的float是等价的
所以在进行特征&模型结果比对的时候,最好按照这种结论中的形式进行数据精度对齐,保持结果一致。
最后
以上就是高贵水杯为你收集整理的python float和Java float引发的问题的全部内容,希望文章能够帮你解决python float和Java float引发的问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复