[英]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.int8
或numpy.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.