技術背景
numpy在python中的地位是相當高的,即使是入門的python使用者也會經常看到這個庫的使用。除了替代python自帶的列表數據格式list之外,numpy的一大優勢是其底層的高性能實現方式,比如前一篇博客中所提到的矢量運算,就是一種基於SIMD的底層運算優化方案,使得numpy的計算速度遠高於一個普通的for循環。
而在日常運算的過程中,有些數據往往是不會變化的,比如機器學習中的測試和訓練數據。那么如果這里使用的是numpy的數據結構的話,就會涉及到相關數據的存儲,numpy可以將其數據存儲為.npy
或者.npz
結構。
npy結構的數據存儲
npy格式適用於單個numpy列表的存儲,這個列表的維度可以是任意的,但是最外層必須是一個numpy的列表結構。以下用ipython來展示npy文件的基本使用方法,首先是創建一個數組,然后用np.save
保存到一個給定的文件名中:
[dechin@dechin-manjaro numpy]$ ipython
Python 3.8.5 (default, Sep 4 2020, 07:30:14)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import numpy as np
In [2]: test_arr = np.arange(10)
In [3]: np.save('test_arr', test_arr)
In [5]: !ls -l
總用量 4
-rw-r--r-- 1 dechin dechin 208 5月 2 18:52 test_arr.npy
可以看到文件名會自動補充npy
的后綴,然后可以在當前目錄下使用np.load
函數直接加載剛才保存的數據:
In [6]: print (np.load('test_arr.npy'))
[0 1 2 3 4 5 6 7 8 9]
類似的可以測試一下多個維度的隨機數組:
In [7]: test_arr = np.random.randn(2,5)
In [8]: np.save('random_arr', test_arr)
In [9]: !ls -l
總用量 8
-rw-r--r-- 1 dechin dechin 208 5月 2 18:56 random_arr.npy
-rw-r--r-- 1 dechin dechin 208 5月 2 18:52 test_arr.npy
In [10]: print (np.load('random_arr.npy'))
[[ 2.6917403 0.01488535 -0.5259401 -1.41512577 0.65968369]
[-0.68929493 0.30153131 0.84906878 -2.20849715 0.34260589]]
除了可以保存numpy格式的數組,還可以直接保存python本身的數組格式的數據:
In [11]: normal_arr = [1,3,5,7,9]
In [12]: np.save('normal_arr', normal_arr)
In [13]: print (np.load('normal_arr.npy'))
[1 3 5 7 9]
甚至還可以保存一些非列表格式的數據,比如python中的tuple
,但是保存后重新加載的數據格式,會被自動轉化成列表格式:
In [14]: tuple_arr = [(1,2),(2,3),(3,4)]
In [15]: np.save('tuple_arr', tuple_arr)
In [16]: print (np.load('tuple_arr.npy'))
[[1 2]
[2 3]
[3 4]]
npz結構的數據存儲
上面介紹的npy
數據結構存儲下來是一個二進制的文件,僅用於單個列表數據結構的存儲,這里的npz
數據結構可以存儲多個列表結構的對象,可以直接參考一個使用案例:
In [17]: multi_arr1 = 3
In [18]: multi_arr2 = [1,2,3]
In [19]: multi_arr3 = (4,5)
In [20]: multi_arr4 = [[6,7],[8,9]]
In [22]: np.savez('multi_arr',multi_arr1,multi_arr2,multi_arr3,named_arr=multi_arr4)
In [23]: !ls -l
總用量 20
-rw-r--r-- 1 dechin dechin 1078 5月 2 19:09 multi_arr.npz
-rw-r--r-- 1 dechin dechin 168 5月 2 19:00 normal_arr.npy
-rw-r--r-- 1 dechin dechin 208 5月 2 18:56 random_arr.npy
-rw-r--r-- 1 dechin dechin 208 5月 2 18:52 test_arr.npy
-rw-r--r-- 1 dechin dechin 176 5月 2 19:02 tuple_arr.npy
In [24]: data=np.load('multi_arr.npz')
In [25]: data['arr_0']
Out[25]: array(3)
In [26]: data['arr_1']
Out[26]: array([1, 2, 3])
In [27]: data['arr_2']
Out[27]: array([4, 5])
In [28]: data['named_arr']
Out[28]:
array([[6, 7],
[8, 9]])
在npz
的數據結構中,除了列表以外的格式都會被自動轉化成numpy的列表。而多個的列表對象最終是以字典的形式存儲在文件中,如果不加以定義,那么索引的名稱默認為arr_
加上一個數字的格式,以0
為起點。如果需要手動的命名,需要在傳入savez
函數的末尾處加上手動命名的對象,比如上面實例中的named_arr
。npz
文件的讀取方式跟npy
是一樣的,使用np.load
函數即可。
存儲數據的壓縮
最后我們再額外介紹一個tar
壓縮包的使用方法,如果存儲的npz
文件較大,可以通過tar -zcvf filename.tar.gz filename.npz
打包成一個壓縮包,特別是當數據中0
的數量較多時,可以獲得一個非常理想的壓縮比。
[dechin@dechin-manjaro numpy]$ ll
總用量 20
-rw-r--r-- 1 dechin dechin 1078 5月 2 19:09 multi_arr.npz
-rw-r--r-- 1 dechin dechin 168 5月 2 19:00 normal_arr.npy
-rw-r--r-- 1 dechin dechin 208 5月 2 18:56 random_arr.npy
-rw-r--r-- 1 dechin dechin 208 5月 2 18:52 test_arr.npy
-rw-r--r-- 1 dechin dechin 176 5月 2 19:02 tuple_arr.npy
[dechin@dechin-manjaro numpy]$ tar -zcvf multi_arr.tar.gz multi_arr.npz
multi_arr.npz
[dechin@dechin-manjaro numpy]$ ll
總用量 24
-rw-r--r-- 1 dechin dechin 1078 5月 2 19:09 multi_arr.npz
-rw-r--r-- 1 dechin dechin 427 5月 2 19:14 multi_arr.tar.gz
-rw-r--r-- 1 dechin dechin 168 5月 2 19:00 normal_arr.npy
-rw-r--r-- 1 dechin dechin 208 5月 2 18:56 random_arr.npy
-rw-r--r-- 1 dechin dechin 208 5月 2 18:52 test_arr.npy
-rw-r--r-- 1 dechin dechin 176 5月 2 19:02 tuple_arr.npy
而關於tar.gz
格式的文件的解壓縮,則是使用tar -xvf filename.tar.gz
命令。
總結概要
在科學計算中對於恆定不變的數據,不一定需要實時保存在內存中,或者是需要跨平台運算的數據,我們可以將其保存為numpy格式的列表文件npy或者npz。而如果存儲的文件過大,本文也額外介紹了簡單的tar壓縮與解壓縮的使用方法。
版權聲明
本文首發鏈接為:https://www.cnblogs.com/dechinphy/p/npz.html
作者ID:DechinPhy
更多原著文章請參考:https://www.cnblogs.com/dechinphy/