You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于利用数据列最值降低内存占用的作用及np.finfo返回值的疑问

关于利用数据列最值降低内存占用的作用及np.finfo返回值的疑问

嘿,我最近在学习一个入侵检测项目的代码,里面有一段用来降低内存占用的逻辑,我有点搞不懂其中的原理,还有个关于np.finfo()返回值的疑问,来跟大家聊聊~

先说说背景:我从一个入侵检测项目里看到这段内存优化代码,原以为能把内存降下来,但实际运行后发现初始和最终内存都是798.63MB,没变化。我打印了各列的最小值c_min和np.finfo(np.float32).min,发现后者比我数据里的最小值小很多,这就让我产生了两个疑问:

  1. 为什么作者要基于列的最大最小值来调整数据类型?
  2. 为什么np.finfo(np.float32).min会比我数据列的实际最小值小这么多?

先贴一下这段内存优化的代码:

old_memory_usage = data.memory_usage().sum() / 1024 ** 2
print(f'Initial memory usage: {old_memory_usage:.2f} MB')
for col in data.columns:
    col_type = data[col].dtype
    if col_type != object:
        c_min = data[col].min()  # <-- retrieve c_min
        c_max = data[col].max()
        # Downcasting float64 to float32
        if str(col_type).find('float') >= 0 and c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
            data[col] = data[col].astype(np.float32)

        # Downcasting int64 to int32
        elif str(col_type).find('int') >= 0 and c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
            data[col] = data[col].astype(np.int32)

new_memory_usage = data.memory_usage().sum() / 1024 ** 2
print(f"Final memory usage: {new_memory_usage:.2f} MB")

然后是我打印的列最小值和np.finfo(np.float32).min的结果:

Initial memory usage: 798.63 MB
Fwd Packet Length Mean 0.0 -3.4028235e+38
Fwd Packet Length Std 0.0 -3.4028235e+38
Bwd Packet Length Mean 0.0 -3.4028235e+38
Bwd Packet Length Std 0.0 -3.4028235e+38
Flow Bytes/s -261000000.0 -3.4028235e+38
Flow Packets/s -2000000.0 -3.4028235e+38
Flow IAT Mean -13.0 -3.4028235e+38
Flow IAT Std 0.0 -3.4028235e+38
Fwd IAT Mean 0.0 -3.4028235e+38
Fwd IAT Std 0.0 -3.4028235e+38
Bwd IAT Mean 0.0 -3.4028235e+38
Bwd IAT Std 0.0 -3.4028235e+38
Fwd Packets/s 0.0 -3.4028235e+38
Bwd Packets/s 0.0 -3.4028235e+38
Packet Length Mean 0.0 -3.4028235e+38
Packet Length Std 0.0 -3.4028235e+38
Packet Length Variance 0.0 -3.4028235e+38
Average Packet Size 0.0 -3.4028235e+38
Avg Fwd Segment Size 0.0 -3.4028235e+38
Avg Bwd Segment Size 0.0 -3.4028235e+38
Active Mean 0.0 -3.4028235e+38
Active Std 0.0 -3.4028235e+38
Idle Mean 0.0 -3.4028235e+38
Idle Std 0.0 -3.4028235e+38
Final memory usage: 798.63 MB

先解答第一个疑问:为什么用列的最值来调整数据类型?

不同的数值类型占用的内存空间不一样,比如float64每个元素占8字节,float32只占4字节;int64占8字节,int32占4字节。直接把大类型转成小类型确实能省内存,但前提是数据里的所有值都能被小类型完全容纳,不然就会出现数据溢出(比如把一个比float32最大值还大的数转成float32,会变成无穷大inf,丢失真实数据)。

所以作者的逻辑是:先拿到列的最小值c_min和最大值c_max,然后对比目标类型(比如float32)的取值极限——如果列里的所有值都在这个极限范围内,就可以安全地把列转成更小的类型,既省内存又不会丢失数据。

再解答第二个疑问:为什么np.finfo(np.float32).min比我的c_min小?

np.finfo(np.float32).min是float32这个数据类型能表示的最小(最负)的数值,大概是-3.4e+38,而你的数据列里的实际最小值(比如Flow Bytes/s的-261000000.0)比这个值大得多,这说明你的数据完全在float32的容纳范围内。

至于为什么内存没变化,大概率是这些列本来就已经是float32类型了,所以转类型操作没有改变内存占用。你可以打印一下data.dtypes看看这些列的原始类型,就能验证这一点啦。

备注:内容来源于stack exchange,提问作者Christopher Chen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:44:48