Python3------NumPy學習(一)
NumPy學習
1------NumPy介紹
Numpy(Numerical Python)是一個開源的Python科學計算庫,用於快速處理任意維度的陣列。
Numpy支援常見的陣列和矩陣操作。對於同樣的數值計算任務,使用Numpy比直接使用Python要簡潔的多。
Numpy使用ndarray物件來處理多維陣列,該物件是一個快速而靈活的大資料容器
1.1------ndarray
NumPy提供了一個N維陣列型別ndarray,它描述了相同型別的“items”的集合。
score = np.array([[80, 89, 86, 67, 79], [78, 97, 89, 67, 81], [90, 94, 78, 67, 74], [91, 91, 90, 67, 69], [76, 87, 75, 67, 86], [70, 79, 84, 67, 84], [94, 92, 93, 67, 64], [86, 85, 83, 67, 80]])
就是將一個Python內建的陣列作為引數傳遞給numpy,返回結果如下:
array([[80, 89, 86, 67, 79],
[78, 97, 89, 67, 81],
[90, 94, 78, 67, 74],
[91, 91, 90, 67, 69],
[76, 87, 75, 67, 86],
[70, 79, 84, 67, 84],
[94, 92, 93, 67, 64],
[86, 85, 83, 67, 80]])
使用Python列表可以儲存一維陣列,通過列表的巢狀可以實現多維陣列,那麼為什麼還需要使用Numpy的ndarray呢?
這就關乎到效率這個問題了,請看下一節。
1.2------ndarray與Python原生list運算效率對比
import numpy as np import random import time #初始化定義一個列表list a = [] for i in range(100000000): #往a中隨機新增100000000個元素 a.append(random.random()) t1 = time.time() #求列表a中元素的和 sum = sum(a) t2 = time.time() #求和開始時間 print(t1) #求和結束時間 print(t2) #總共花費的時間 print(t2-t1) b = np.array(a) t3 = time.time() sum2 = np.sum(b) t4 = time.time() print(t4-t3)
輸出結果如下:
1543031869.482664
1543031870.6981153
1.2154512405395508
0.22154474258422852
所以可見,ndarray中對資料的計算效率比傳統Python內建物件要高得多!!!
機器學習的最大特點就是大量的資料運算,那麼如果沒有一個快速的解決方案,那可能現在python也在機器學習領域達不到好的效果。
思考:ndarray為什麼這麼快呢?
1.2.1------ndarray的優勢
直接上圖
從圖中我們可以看出ndarray在儲存資料的時候,資料與資料的地址都是連續的,這樣就給使得批量運算元組元素時速度更快。
這是因為ndarray中的所有元素的型別都是相同的,而Python列表中的元素型別是任意的,所以ndarray在儲存元素時記憶體可以連續,而python原生lis就t只能通過定址方式找到下一個元素,這雖然也導致了在通用效能方面Numpy的ndarray不及Python原生list,但在科學計算中,Numpy的ndarray就可以省掉很多迴圈語句,程式碼使用方面比Python原生list簡單的多。
下面,我們就來具體學習一下ndarray
2------ndarray
2.1------ndarray的屬性
屬性名字 | 屬性解釋 |
---|---|
ndarray.shape | 陣列維度的元組 |
ndarray.ndim | 陣列維數 |
ndarray.size | 陣列中的元素數量 |
ndarray.itemsize | 一個數組元素的長度(位元組) |
ndarray.dtype | 陣列元素的型別 |
2.2------ndarray的形狀
a = np.array([[1,2,3],[4,5,6]])
b = np.array([1,2,3,4])
c = np.array([[[1,2,3],[4,5,6]],[[1,2,3],[4,5,6]]])
print(a.shape)
print(b.shape)
print(c.shape)
結果如下:
(2, 3)
(4,)
(2, 2, 3)
在這裡,詳細說一下三位陣列怎麼分析其形狀!!!
如例:[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]
首先去掉最外層的中括號,剩下----[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]此時由兩部分構成[[1,2,3],[4,5,6]]和[[7,8,9],[10,11,12]]
把這兩個叫做構成單元
所以第一維是2
同理對上述構成單元分析(只需要分析一個即可,這裡拿第一個說明),再次去掉最外層的中括號,剩下----[1,2,3],[4,5,6]此時由兩部分構成,[1,2,3]和[4,5,6]也是兩個構成單元。
所以第二維是2
再對上面構成單元分析,去掉中括號,剩下1,2,3
所以第三位是3--------最後結果即(2,2,3)
2.3----ndarrat的資料型別
程式碼上見:
a = np.array([[1,2,3],[4,5,6]])
print(a.dtype)
結果如下:
int32
ndarray中具體的資料型別如下表:
名稱 | 描述 | 簡寫 |
---|---|---|
np.bool | 用一個位元組儲存的布林型別(True或False) | 'b' |
np.int8 | 一個位元組大小,-128 至 127 | 'i' |
np.int16 | 整數,-32768 至 32767 | 'i2' |
np.int32 | 整數,-2**31 至 2**32 -1 | 'i4' |
np.int64 | 整數,-2**63 至 2**63 - 1 | 'i8' |
np.uint8 | 無符號整數,0 至 255 | 'u' |
np.uint16 | 無符號整數,0 至 65535 | 'u2' |
np.uint32 | 無符號整數,0 至 2 ** 32 - 1 | 'u4' |
np.uint64 | 無符號整數,0 至 2 ** 64 - 1 | 'u8' |
np.float16 | 半精度浮點數:16位,正負號1位,指數5位,精度10位 | 'f2' |
np.float32 | 單精度浮點數:32位,正負號1位,指數8位,精度23位 | 'f4' |
np.float64 | 雙精度浮點數:64位,正負號1位,指數11位,精度52位 | 'f8' |
np.complex64 | 複數,分別用兩個32位浮點數表示實部和虛部 | 'c8' |
np.complex128 | 複數,分別用兩個64位浮點數表示實部和虛部 | 'c16' |
np.object_ | python物件 | 'O' |
np.string_ | 字串 | 'S' |
np.unicode_ | unicode型別 | 'U' |
在建立的時候可以這樣建立:
a = np.array([[1, 2, 3],[4, 5, 6]], dtype=np.float32)
2.4------基本操作
2.4.1------生成陣列
- empty(shape[, dtype, order]) empty_like(a[, dtype, order, subok])
見名知意:引數為shape時許傳遞一個表示維數的陣列,引數為a[....]時需要傳遞進去一個數組或者矩陣,下面也是一樣。
- eye(N[, M, k, dtype, order])
- identity(n[, dtype])
- ones(shape[, dtype, order])
- ones_like(a[, dtype, order, subok])
- zeros(shape[, dtype, order]) zeros_like(a[, dtype, order, subok])
full(shape, fill_value[, dtype, order]) - full_like(a, fill_value[, dtype, order, subok])
empty系列:
a = np.empty([3,4])
print(a)
b = [[1,2,3],[4,5,6]]
b = np.empty_like(b)
print(b)
#eye()
c = np.eye(5)
print(c)
d = np.identity(5)
print(d)
[[8.82769181e+025 7.36662981e+228 7.54894003e+252 2.95479883e+137]
[1.42800637e+248 2.64686750e+180 1.09936856e+248 6.99481925e+228]
[7.54894003e+252 7.67109635e+170 2.64686750e+180 5.63234836e-322]]
[[0 0 0]
[0 0 0]]
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
解釋:
empty()方法回按照傳遞進去的維數,生成對應維數的0矩陣,單數矩陣中的元素不為0只是接近0
empty_like()方法按照傳遞進去的矩陣,生成對應維數的0矩陣,這裡元素都為0
eye()和identity()需要傳遞進去一個整數,代表維數,這裡生成的是對應維數的單位矩陣
***()與***_like()方法類似。
2.4.2------從已有陣列(矩陣)中生成
-
array(object[, dtype, copy, order, subok, ndmin])
-
asarray(a[, dtype, order])
a = np.array([[1,2,3],[4,5,6]])
# 從現有的陣列當中建立
a1 = np.array(a)
# 相當於索引的形式,並沒有真正的建立一個新的
a2 = np.asarray(a)
print(a1)
print(a2)
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
解釋:array()和asarray() 的區別
相同:array和asarray都可以將陣列轉化為ndarray物件
區別:當引數為一般陣列時,兩個函式都會開闢新的記憶體來存放copy的陣列或矩陣;
當引數本身就是ndarray型別時,array會新建一個ndarray物件,作為引數的副本,但是asarray不會新建,而是與引數共享同一個記憶體。
2.4.3------生成固定範圍的陣列
- np.linspace (start, stop, num, endpoint, retstep, dtype)
引數說明:
start 序列的起始值
stop 序列的終止值,
如果endpoint為true,該值包含於序列中
num 要生成的等間隔樣例數量,預設為50
endpoint 序列中是否包含stop值,預設為ture
retstep 如果為true,返回樣例,
以及連續數字之間的步長
dtype 輸出ndarray的資料型別
程式碼上見
a = np.linspace(0,100,50)
print(a)
[ 0. 2.04081633 4.08163265 6.12244898 8.16326531
10.20408163 12.24489796 14.28571429 16.32653061 18.36734694
20.40816327 22.44897959 24.48979592 26.53061224 28.57142857
30.6122449 32.65306122 34.69387755 36.73469388 38.7755102
40.81632653 42.85714286 44.89795918 46.93877551 48.97959184
51.02040816 53.06122449 55.10204082 57.14285714 59.18367347
61.2244898 63.26530612 65.30612245 67.34693878 69.3877551
71.42857143 73.46938776 75.51020408 77.55102041 79.59183673
81.63265306 83.67346939 85.71428571 87.75510204 89.79591837
91.83673469 93.87755102 95.91836735 97.95918367 100. ]
--------------------------------------------------------------
- numpy.arange(start,stop, step, dtype)
- 引數說明:從start開始,到stop結束,步長為step
程式碼上見:
a = np.arange(0,100,2)
print(a)
[ 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46
48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94
96 98]
2.4.4------生成隨機陣列成的陣列
- np.random模組
np.random.rand(d0, d1, ..., dn)------返回[0.0,1.0)內的一組均勻分佈的數,引數是產生的陣列的維數。
np.random.randn(d0, d1, …, dn)------功能:從標準正態分佈中返回一個或多個樣本值
a = np.random.rand(3,2)
print(a)
b = np.random.randn(4,2)
print(b)
[[0.47018098 0.53773488]
[0.44468209 0.14701938]
[0.44349829 0.90800236]]
--------------------------
[[-1.58174979 -0.8541224 ]
[ 0.3468391 -2.68307933]
[-0.5132048 1.19656033]
[ 0.96606693 0.16333828]]
------------------------------------------------------------------------------------------------------------------------------------------------
有志者 事竟成 百二秦關終屬楚
苦心人 天不負 三千越甲可吞吳