1. 程式人生 > >Python3------NumPy學習(一)

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(d0d1...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]]

              ------------------------------------------------------------------------------------------------------------------------------------------------

有志者 事竟成 百二秦關終屬楚

苦心人 天不負 三千越甲可吞吳