簡體   English   中英

為什么帶有dtype = object的numpy數組導致文件大小比dtype = int小得多?

[英]Why does a numpy array with dtype=object result in a much smaller file size than dtype=int?

這里是一個例子:

import numpy as np
randoms = np.random.randint(0, 20, 10000000)

a = randoms.astype(np.int)
b = randoms.astype(np.object)

np.save('d:/dtype=int.npy', a)     #39 mb
np.save('d:/dtype=object.npy', b)  #19 mb! 

您可以看到dtype = object的文件的大小約為一半。 怎么來的? 我的印象是正確定義的numpy dtype嚴格優於對象dtype。

使用非對象dtype時,大多數npy文件格式都包含轉儲數組數據的原始字節。 在此,每個元素為4字節或8字節,具體取決於您的NumPy默認為4字節還是8字節整數。 從文件大小來看,每個元素看起來像4個字節。

對於對象dtype,大多數npy文件格式都由數組的普通pickle組成。 對於小整數,例如數組中的小整數,pickle在pickletools模塊中使用K pickle操作碼,長名稱BININT1 ,“已記錄”:

I(name='BININT1',
  code='K',
  arg=uint1,
  stack_before=[],
  stack_after=[pyint],
  proto=1,
  doc="""Push a one-byte unsigned integer.

  This is a space optimization for pickling very small non-negative ints,
  in range(256).
  """),

每個整數需要兩個字節,一個用於K操作碼,一個字節用於無符號整數數據。

請注意,通過使用numpy.int8numpy.uint8存儲數組,可以進一步減小文件大小,每個整數大約1個字節。

編輯:這種分析是錯誤的。 請參閱user2357112的正確答案。

dtype=object數組另存為NPY文件中的Python泡菜。 Python泡菜會在其對象圖中保留對象的身份; 也就是說,如果b[i] is b[j]則泡菜將僅序列化由b[i]b[j]引用的對象,並在下次出現時對其進行引用。 該引用通常小於序列化的對象本身,即使序列化時對象本身很小。

Python會優化小整數,以便始終將同一對象用於從-5到256的整數,從而包括所有range(0, 20) ,這是數組中唯一的值。 numpy通過.astype(object)轉換時,可能還會決定重用實例。

如果您創建了一個數組,其中大多數或所有值都是唯一的,如浮點uniform(0.0, 1.0, 10000000) ,那么您將獲得所需的相對大小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM