Numpy 學習筆記

Numpy

Numpy 屬性

這次我們會介紹幾種 numpy 的屬性:
- ndim:維度
- shape:行數和列數
- size:元素個數
使用numpy首先要導入模塊

`import numpy as np #爲了方便使用numpy 採用np簡寫“
列表轉化爲矩陣:

array = np.array([[1,2,3],[2,3,4]])  #列表轉化爲矩陣
print(array)
"""
array([[1, 2, 3],
       [2, 3, 4]])
"""

numpy 的幾種屬性
接着我們看看這幾種屬性的結果:

print('number of dim:',array.ndim)  # 維度
# number of dim: 2

print('shape :',array.shape)    # 行數和列數
# shape : (2, 3)

print('size:',array.size)   # 元素個數
# size: 6

Numpy 的創建 array

創建 array 有很多 形式

  • array:創建數組
  • dtype:指定數據類型
  • zeros:創建數據全爲0
  • ones:創建數據全爲1
  • empty:創建數據接近0
  • arrange:按指定範圍創建數據
  • linspace:創建線段

創建數組

a = np.array([2,23,4])  # list 1d
print(a)
# [2 23 4]

指定數據 dtype

a = np.array([2,23,4],dtype=np.int)
print(a.dtype)
# int 64
a = np.array([2,23,4],dtype=np.int32)
print(a.dtype)
# int32
a = np.array([2,23,4],dtype=np.float)
print(a.dtype)
# float64
a = np.array([2,23,4],dtype=np.float32)
print(a.dtype)
# float32

創建特定數據

a = np.array([[2,23,4],[2,32,4]])  # 2d 矩陣 2行3列
print(a)
"""
[[ 2 23  4]
 [ 2 32  4]]
"""

創建全零數組

a = np.zeros((3,4)) # 數據全爲0,3行4列
"""
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])
"""

創建全一數組, 同時也能指定這些特定數據的 dtype:

a = np.ones((3,4),dtype = np.int)   # 數據爲1,3行4列
"""
array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [1, 1, 1, 1]])
"""

創建全空數組, 其實每個值都是接近於零的數:

a = np.empty((3,4)) # 數據爲empty,3行4列
"""
array([[  0.00000000e+000,   4.94065646e-324,   9.88131292e-324,
          1.48219694e-323],
       [  1.97626258e-323,   2.47032823e-323,   2.96439388e-323,
          3.45845952e-323],
       [  3.95252517e-323,   4.44659081e-323,   4.94065646e-323,
          5.43472210e-323]])
"""

arange 創建連續數組:

a = np.arange(10,20,2) # 10-19 的數據,2步長
"""
array([10, 12, 14, 16, 18])
"""

使用 reshape 改變數據的形狀

a = np.arange(12).reshape((3,4))    # 3行4列,0到11
"""
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
"""

用 linspace 創建線段型數據:

a = np.linspace(1,10,20)    # 開始端1,結束端10,且分割成20個數據,生成線段
"""
array([  1.        ,   1.47368421,   1.94736842,   2.42105263,
         2.89473684,   3.36842105,   3.84210526,   4.31578947,
         4.78947368,   5.26315789,   5.73684211,   6.21052632,
         6.68421053,   7.15789474,   7.63157895,   8.10526316,
         8.57894737,   9.05263158,   9.52631579,  10.        ])
"""

同樣也能進行 reshape 工作:

a = np.linspace(1,10,20).reshape((5,4)) # 更改shape
"""
array([[  1.        ,   1.47368421,   1.94736842,   2.42105263],
       [  2.89473684,   3.36842105,   3.84210526,   4.31578947],
       [  4.78947368,   5.26315789,   5.73684211,   6.21052632],
       [  6.68421053,   7.15789474,   7.63157895,   8.10526316],
       [  8.57894737,   9.05263158,   9.52631579,  10.        ]])
"""

Numpy 基礎運算1

讓我們從一個腳本開始瞭解相應的計算以及表示形式 :

import numpy as np
a=np.array([10,20,30,40])   # array([10, 20, 30, 40])
b=np.arange(4)              # array([0, 1, 2, 3])

numpy 的幾種基本運算

上述代碼中的 ab 是兩個屬性爲 array 也就是矩陣的變量,而且二者都是1行4列的矩陣, 其中b矩陣中的元素分別是從0到3。 如果我們想要求兩個矩陣之間的減法,你可以嘗試着輸入:

c=a-b # array([10, 19, 28, 37])
通過執行上述腳本,將會得到對應元素相減的結果,即[10,19,28,37]。 同理,矩陣對應元素的相加和相乘也可以用類似的方式表示:

c=a+b # array([10, 21, 32, 43])
c=a*b # array([ 0, 20, 60, 120])
有所不同的是,在Numpy中,想要求出矩陣中各個元素的乘方需要依賴雙星符號 **,以二次方舉例,即:

c=b**2 # array([0, 1, 4, 9])
另外,Numpy中具有很多的數學函數工具,比如三角函數等,當我們需要對矩陣中每一項元素進行函數運算時,可以很簡便的調用它們(以sin函數爲例):

c=10*np.sin(a)  
# array([-5.44021111,  9.12945251, -9.88031624,  7.4511316 ])

除了函數應用外,在腳本中對print函數進行一些修改可以進行邏輯判斷:

print(b<3)  
# array([ True,  True,  True, False], dtype=bool)

此時由於進行邏輯判斷,返回的是一個bool類型的矩陣,即對滿足要求的返回True,不滿足的返回False。上述程序執行後得到的結果是[True True True False]。 需要注意的是,如果想要執行是否相等的判斷, 依然需要輸入 ==而不是 =來完成相應的邏輯判斷。

上述運算均是建立在一維矩陣,即只有一行的矩陣上面的計算,如果我們想要對多行多維度的矩陣進行操作,需要對開始的腳本進行一些修改:

a=np.array([[1,1],[0,1]])
b=np.arange(4).reshape((2,2))

print(a)
# array([[1, 1],
#       [0, 1]])

print(b)
# array([[0, 1],
#       [2, 3]])

此時構造出來的矩陣ab便是2行2列的,其中 reshape 操作是對矩陣的形狀進行重構, 其重構的形狀便是括號中給出的數字。 稍顯不同的是,Numpy中的矩陣乘法分爲兩種, 其一是前文中的對應元素相乘,其二是標準的矩陣乘法運算,即對應行乘對應列得到相應元素:

c_dot = np.dot(a,b)
# array([[2, 4],
#       [2, 3]])

除此之外還有另外的一種關於dot的表示方法,即:

c_dot_2 = a.dot(b)
# array([[2, 4],
#       [2, 3]])

下面我們將重新定義一個腳本, 來看看關於sum(), min(), max()的使用:

import numpy as np
a=np.random.random((2,4))
print(a)
# array([[ 0.94692159,  0.20821798,  0.35339414,  0.2805278 ],
#       [ 0.04836775,  0.04023552,  0.44091941,  0.21665268]])

因爲是隨機生成數字, 所以你的結果可能會不一樣. 在第二行中對a的操作是令a中生成一個2行4列的矩陣,且每一元素均是來自從0到1的隨機數。 在這個隨機生成的矩陣中,我們可以對元素進行求和以及尋找極值的操作,具體如下:

np.sum(a)   # 4.4043622002745959
np.min(a)   # 0.23651223533671784
np.max(a)   # 0.90438450240606416

對應的便是對矩陣中所有元素進行求和,尋找最小值,尋找最大值的操作。 可以通過print()函數對相應值進行打印檢驗。

如果你需要對行或者列進行查找運算,就需要在上述代碼中爲 axis 進行賦值。 當axis的值爲0的時候,將會以列作爲查找單元, 當axis的值爲1的時候,將會以行作爲查找單元。

爲了更加清晰,在剛纔的例子中我們繼續進行查找:

print("a =",a)
# a = [[ 0.23651224  0.41900661  0.84869417  0.46456022]
# [ 0.60771087  0.9043845   0.36603285  0.55746074]]

print("sum =",np.sum(a,axis=1))
# sum = [ 1.96877324  2.43558896]

print("min =",np.min(a,axis=0))
# min = [ 0.23651224  0.41900661  0.36603285  0.46456022]

print("max =",np.max(a,axis=1))
# max = [ 0.84869417  0.9043845 ]

Numpy 基礎運算2

作者: Sincejuly 編輯: 莫煩 2016-11-03
學習資料:

Numpy官方英文教材
通過上一節的學習,我們可以瞭解到一部分矩陣中元素的計算和查找操作。然而在日常使用中,對應元素的索引也是非常重要的。依然,讓我們先從一個腳本開始 :

import numpy as np
A = np.arange(2,14).reshape((3,4))

# array([[ 2, 3, 4, 5]
#        [ 6, 7, 8, 9]
#        [10,11,12,13]])

print(np.argmin(A))    # 0
print(np.argmax(A))    # 11

numpy 的幾種基本運算

其中的 argmin()argmax() 兩個函數分別對應着求矩陣中最小元素和最大元素的索引。相應的,在矩陣的12個元素中,最小值即2,對應索引0,最大值爲13,對應索引爲11。

如果需要計算統計中的均值,可以利用下面的方式,將整個矩陣的均值求出來:

print(np.mean(A))        # 7.5
print(np.average(A))     # 7.5

仿照着前一節中dot() 的使用法則,mean()函數還有另外一種寫法:

print(A.mean()) # 7.5
同樣的,我們可以寫出求解中位數的函數:

print(A.median()) # 7.5
另外,和matlab中的cumsum()累加函數類似,Numpy中也具有cumsum()函數,其用法如下:

print(np.cumsum(A))

# [2 5 9 14 20 27 35 44 54 65 77 90]

cumsum()函數中:生成的每一項矩陣元素均是從原矩陣首項累加到對應項的元素之和。比如元素9,在cumsum()生成的矩陣中序號爲3,即原矩陣中2,3,4三個元素的和。

相應的有累差運算函數:

print(np.diff(A))    

# [[1 1 1]
#  [1 1 1]
#  [1 1 1]]

該函數計算的便是每一行中後一項與前一項之差。故一個3行4列矩陣通過函數計算得到的矩陣便是3行3列的矩陣。

下面我們介紹一下nonzero()函數:

print(np.nonzero(A))    

# (array([0,0,0,0,1,1,1,1,2,2,2,2]),array([0,1,2,3,0,1,2,3,0,1,2,3]))

這個函數將所有非零元素的行與列座標分割開,重構成兩個分別關於行和列的矩陣。

同樣的,我們可以對所有元素進行仿照列表一樣的排序操作,但這裏的排序函數仍然僅針對每一行進行從小到大排序操作:

import numpy as np
A = np.arange(14,2, -1).reshape((3,4))

# array([[14, 13, 12, 11],
#       [10,  9,  8,  7],
#       [ 6,  5,  4,  3]])

print(np.sort(A))    

# array([[11,12,13,14]
#        [ 7, 8, 9,10]
#        [ 3, 4, 5, 6]])

矩陣的轉置有兩種表示方法:

print(np.transpose(A))    
print(A.T)

# array([[14,10, 6]
#        [13, 9, 5]
#        [12, 8, 4]
#        [11, 7, 3]])
# array([[14,10, 6]
#        [13, 9, 5]
#        [12, 8, 4]
#        [11, 7, 3]])

特別的,在Numpy中具有clip()函數,例子如下:

print(A)
# array([[14,13,12,11]
#        [10, 9, 8, 7]
#        [ 6, 5, 4, 3]])

print(np.clip(A,5,9))    
# array([[ 9, 9, 9, 9]
#        [ 9, 9, 8, 7]
#        [ 6, 5, 5, 5]])

這個函數的格式是clip(Array,Array_min,Array_max),顧名思義,Array指的是將要被執行用的矩陣,而後面的最小值最大值則用於讓函數判斷矩陣中元素是否有比最小值小的或者比最大值大的元素,並將這些指定的元素轉換爲最小值或者最大值。

實際上每一個Numpy中大多數函數均具有很多變量可以操作,你可以指定行、列甚至某一範圍中的元素。更多具體的使用細節請記得查閱Numpy官方英文教材。

Numpy 索引

作者: Sincejuly 編輯: 莫煩 2016-11-03

一維索引

我們都知道,在元素列表或者數組中,我們可以用如同a[2]一樣的表示方法,同樣的,在Numpy中也有相對應的表示方法:

import numpy as np
A = np.arange(3,15)

# array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

print(A[3])    # 6

讓我們將矩陣轉換爲二維的,此時進行同樣的操作:

A = np.arange(3,15).reshape((3,4))
"""
array([[ 3,  4,  5,  6]
       [ 7,  8,  9, 10]
       [11, 12, 13, 14]])
"""

print(A[2])         
# [11 12 13 14]

實際上這時的A[2]對應的就是矩陣A中第三行(從0開始算第一行)的所有元素。

二維索引

如果你想要表示具體的單個元素,可以仿照上述的例子:

print(A[1][1]) # 8
此時對應的元素即A[1][1],在A中即橫縱座標都爲1,第二行第二列的元素,即8(因爲計數從0開始)。同樣的還有其他的表示方法:

print(A[1, 1]) # 8
在Python的 list 中,我們可以利用:對一定範圍內的元素進行切片操作,在Numpy中我們依然可以給出相應的方法:

print(A[1, 1:3]) # [8 9]
這一表示形式即針對第二行中第2到第4列元素進行切片輸出(不包含第4列)。 此時我們適當的利用for函數進行打印:

for row in A:
    print(row)
"""    
[ 3,  4,  5, 6]
[ 7,  8,  9, 10]
[11, 12, 13, 14]
"""

此時它會逐行進行打印操作。如果想進行逐列打印,就需要稍稍變化一下:

for column in A.T:
    print(column)
"""  
[ 3,  7,  11]
[ 4,  8,  12]
[ 5,  9,  13]
[ 6, 10,  14]
"""

上述表示方法即對A進行轉置,再將得到的矩陣逐行輸出即可得到原矩陣的逐列輸出。

最後依然說一些關於迭代輸出的問題:

import numpy as np
A = np.arange(3,15).reshape((3,4))

print(A.flatten())   
# array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

for item in A.flat:
    print(item)

# 3
# 4
……
# 14

這一腳本中的flatten是一個展開性質的函數,將多維的矩陣進行展開成1行的數列。而flat是一個迭代器,本身是一個object屬性。

Numpy array 合併

作者: Sincejuly 編輯: 莫煩 2016-11-03

np.vstack()

對於一個array的合併,我們可以想到按行、按列等多種方式進行合併。首先先看一個例子:

import numpy as np
A = np.array([1,1,1])
B = np.array([2,2,2])

print(np.vstack((A,B)))    # vertical stack
"""
[[1,1,1]
 [2,2,2]]
"""

vertical stack本身屬於一種上下合併,即對括號中的兩個整體進行對應操作。此時我們對組合而成的矩陣進行屬性探究:

C = np.vstack((A,B))      
print(A.shape,C.shape)

# (3,) (2,3)

np.hstack()

利用shape函數可以讓我們很容易地知道A和C的屬性,從打印出的結果來看,A僅僅是一個擁有3項元素的數組(數列),而合併後得到的C是一個2行3列的矩陣。

介紹完了上下合併,我們來說說左右合併:

D = np.hstack((A,B))       # horizontal stack

print(D)
# [1,1,1,2,2,2]

print(A.shape,D.shape)
# (3,) (6,)

通過打印出的結果可以看出:D本身來源於A,B兩個數列的左右合併,而且新生成的D本身也是一個含有6項元素的序列。

np.newaxis()

說完了array的合併,我們稍稍提及一下前一節中轉置操作,如果面對如同前文所述的A序列, 轉置操作便很有可能無法對其進行轉置(因爲A並不是矩陣的屬性),此時就需要我們藉助其他的函數操作進行轉置:

print(A[np.newaxis,:])
# [[1 1 1]]

print(A[np.newaxis,:].shape)
# (1,3)

print(A[:,np.newaxis])
"""
[[1]
[1]
[1]]
"""

print(A[:,np.newaxis].shape)
# (3,1)

此時我們便將具有3個元素的array轉換爲了1行3列以及3行1列的矩陣了。

結合着上面的知識,我們把它綜合起來:

import numpy as np
A = np.array([1,1,1])[:,np.newaxis]
B = np.array([2,2,2])[:,np.newaxis]

C = np.vstack((A,B))   # vertical stack
D = np.hstack((A,B))   # horizontal stack

print(D)
"""
[[1 2]
[1 2]
[1 2]]
"""

print(A.shape,D.shape)
# (3,1) (3,2)

np.concatenate()

當你的合併操作需要針對多個矩陣或序列時,藉助concatenate函數可能會讓你使用起來比前述的函數更加方便:

C = np.concatenate((A,B,B,A),axis=0)

print(C)
"""
array([[1],
       [1],
       [1],
       [2],
       [2],
       [2],
       [2],
       [2],
       [2],
       [1],
       [1],
       [1]])
"""

D = np.concatenate((A,B,B,A),axis=1)

print(D)
"""
array([[1, 2, 2, 1],
       [1, 2, 2, 1],
       [1, 2, 2, 1]])
"""

axis參數很好的控制了矩陣的縱向或是橫向打印,相比較vstackhstack函數顯得更加方便。

Numpy array 分割

作者: Bhan 編輯: 莫煩 2016-11-03

創建數據

首先 import 模塊

import numpy as np
建立3行4列的Array

A = np.arange(12).reshape((3, 4))
print(A)
"""
array([[ 0,  1,  2,  3],
    [ 4,  5,  6,  7],
    [ 8,  9, 10, 11]])
"""

縱向分割

print(np.split(A, 2, axis=1))
"""
[array([[0, 1],
        [4, 5],
        [8, 9]]), array([[ 2,  3],
        [ 6,  7],
        [10, 11]])]
"""

橫向分割

print(np.split(A, 3, axis=0))

# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]

錯誤的分割

範例的Array只有4列,只能等量對分,因此輸入以上程序代碼後Python就會報錯。

print(np.split(A, 3, axis=1))

# ValueError: array split does not result in an equal division

爲了解決這種情況, 我們會有下面這種方式.

不等量的分割

在機器學習時經常會需要將數據做不等量的分割,因此解決辦法爲np.array_split()

print(np.array_split(A, 3, axis=1))
"""
[array([[0, 1],
        [4, 5],
        [8, 9]]), array([[ 2],
        [ 6],
        [10]]), array([[ 3],
        [ 7],
        [11]])]
"""

成功將Array不等量分割!

其他的分割方式

在Numpy裏還有np.vsplit()與橫np.hsplit()方式可用。

print(np.vsplit(A, 3)) #等於 print(np.split(A, 3, axis=0))

# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]


print(np.hsplit(A, 2)) #等於 print(np.split(A, 2, axis=1))
"""
[array([[0, 1],
       [4, 5],
       [8, 9]]), array([[ 2,  3],
        [ 6,  7],
        [10, 11]])]
"""

Numpy copy & deep copy

作者: Bhan 編輯: 莫煩 2016-11-03

= 的賦值方式會帶有關聯性

首先 import numpy 並建立變量, 給變量賦值。

import numpy as np

a = np.arange(4)
# array([0, 1, 2, 3])

b = a
c = a
d = b

改變a的第一個值,b、c、d的第一個值也會同時改變。

a[0] = 11
print(a)
# array([11,  1,  2,  3])

確認b、c、d是否與a相同。

b is a  # True
c is a  # True
d is a  # True

同樣更改d的值,a、b、c也會改變。

d[1:3] = [22, 33]   # array([11, 22, 33,  3])
print(a)            # array([11, 22, 33,  3])
print(b)            # array([11, 22, 33,  3])
print(c)            # array([11, 22, 33,  3])

copy() 的賦值方式沒有關聯性

b = a.copy()    # deep copy
print(b)        # array([11, 22, 33,  3])
a[3] = 44
print(a)        # array([11, 22, 33, 44])
print(b)        # array([11, 22, 33,  3

此時a與b已經沒有關聯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章