深度學習系列之Numpy基礎(一)

寫在開頭:因爲也開始了深度學習課程的學習,對於很多東西還要慢慢理解,所以也打算開一個這個系列來分享一下自己的理解。

深度學習系列

對於本系列的學習內容安排的話,主要涉及的是對於圖像識別方面的內容,或許我會在學完後在來寫一個目錄,今天的內容就是對於python中numpy使用的一些彙總,主要學習來源附在最後的參考文獻。

Numpy學習

在使用Numpy之前,我們想進行一些矩陣運算往往只能通過一個又一個的for循環去完成,但有了Numpy庫的支持,我們得以用簡單的語句完成繁瑣的for循環計算,下面我們結合代碼開始今天的分享,
首先加載numpy包,

import numpy as np

數組的產生與查看

a = np.array([1, 2, 3])
print("數組的格式",type(a))
print("數組元素的類型",a.dtype)
print("數組的規模",a.shape)
print(a[0], a[1], a[2])
a[0] = 5 #修改值
print("打印數組",a)

b = np.array([[1,2,3],[4,5,6]]) #創建二元數組
print("數組的規模",b.shape) 
print(b[0, 0], b[0, 1], b[1, 0]) #打印二元數組
數組的格式 <class 'numpy.ndarray'>
數組元素的類型 int32
數組的規模 (3,)
1 2 3
打印數組 [5 2 3]
數組的規模 (2, 3)
1 2 4

方便的矩陣生成
其實說是矩陣,也跟數組差不多,numpy提供了不少快捷的矩陣生成函數,

a = np.zeros((2,2)) #產生一個0矩陣
print("零矩陣\n",a)
b = np.ones((1,2)) #產生全爲1的矩陣
print("1矩陣\n",b)
c = np.full((2,2), 7) #填充
print("填充矩陣\n",c)
d = np.eye(2) #對角線
print("對角矩陣\n",d)
e = np.random.random((2,2)) #0-1的隨機數
print("0,1隨機矩陣\n",e)
零矩陣
 [[0. 0.]
 [0. 0.]]
1矩陣
 [[1. 1.]]
填充矩陣
 [[7 7]
 [7 7]]
對角矩陣
 [[1. 0.]
 [0. 1.]]
0,1隨機矩陣
 [[0.2336035  0.72817244]
 [0.55966474 0.64770182]]

numpy數組的同步映射與數組選取
這裏值得一提的是numpy在數組賦值過後,對賦值後的數組進行數值的變動,會影響原矩陣對應數值的變動,

a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])

b = a[:2, 1:3] #第1行道第2行,也就是index的0到1不包括右邊界
print("a矩陣\n",a)
print("b矩陣\n",b)
print("a的第一行第二列的數爲:",a[0, 1])
b[0, 0]=83 #對應a[0,1]
print("a的第一行第二列的數爲:",a[0, 1]) #這裏的index指針是同步的傳遞,b動了a也會動
a矩陣
 [[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
b矩陣
 [[2 3]
 [6 7]]
a的第一行第二列的數爲: 2
a的第一行第二列的數爲: 83

然後對於數組的片段選取除了最開始的一個值對應位置的選取以外還有片段式選取,已經二維列表式選取,條件式選取,

#片段式選取
a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
row_r1 = a[1, :]
row_r2 = a[1:2, :]
r3 = a[1:3, 1:3]
print("r1的值\n",row_r1, row_r1.shape)
print("r2的值\n",row_r2, row_r2.shape)
print("r3的值\n",r3, r3.shape)

這裏需要注意的是,在片段選取的時候,選取內容不包括右邊界,所謂二維列表式選取就是分別單獨輸入要選取的橫座標已經縱座標,

#二維列表式選取
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
print("輸出原數組\n",a)
print("輸出3個數\n",a[[0,1,2],[0,1,0]])
print(np.array([a[0,0], a[1,1], a[2,0]])) #np.array變爲數組格式

print("輸出2個數\n",a[[0,0], [1,1]])
print(np.array([a[0,1], a[0,1]]))#[a[],a[]]前面的爲橫座標,後面的爲縱座標

b= np.array([0, 2, 0, 1])
print("變量式選取\n",a[np.arange(4), b])
輸出原數組
 [[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
輸出3個數
 [1 5 7]
 [1 5 7]
輸出2個數
 [2 2]
 [2 2]
變量式選取
 [ 1  6  7 11]

還可以通過設置條件來輸出數組的選取,

#條件式選取
a = np.array([[1,2], [3,4], [5,6]])
bool_idx = (a > 2)
print("條件矩陣\n",bool_idx)
print("選取結果\n",a[bool_idx])
條件矩陣
 [[False False]
 [ True  True]
 [ True  True]]
選取結果
 [3 4 5 6]

數組的運算
下面簡單分享一下數組的運算,包括加減乘除開方,矩陣乘法,求和,轉置,empty_like使用,矩陣循環加法。首先說一下這個加減乘除開方,這些函數都是點對點的進行運算,

x = np.array([[1, 2],[3, 4]], dtype=np.float64)
y = np.array([[5, 6],[7, 8]], dtype=np.float64)

print("數組加法:對應位置相加")
print(x + y)
print(np.add(x, y))

print("數組減法:對應位置相減")
print(x-y)
print(np.subtract(x, y))

print("數組乘法:對應位置相乘")
print(x * y)
print(np.multiply(x, y))#點乘

print("數組除法:對應位置相除")
print(x / y)
print(np.divide(x, y))#點除

print("數組開方")
print(np.sqrt(x))
數組加法:對應位置相加
[[ 6.  8.]
 [10. 12.]]
[[ 6.  8.]
 [10. 12.]]
數組減法:對應位置相減
[[-4. -4.]
 [-4. -4.]]
[[-4. -4.]
 [-4. -4.]]
數組乘法:對應位置相乘
[[ 5. 12.]
 [21. 32.]]
[[ 5. 12.]
 [21. 32.]]
數組除法:對應位置相除
[[0.2        0.33333333]
 [0.42857143 0.5       ]]
[[0.2        0.33333333]
 [0.42857143 0.5       ]]
數組開方
[[1.         1.41421356]
 [1.73205081 2.        ]]

下面進行矩陣的乘法、轉置,

x = np.array([[1, 2],[3, 4]])
y = np.array([[5, 6],[7, 8]])#兩個維矩陣

v = np.array([9, 10])
w = np.array([11, 12])#兩個二維向量

print("向量乘法")
print(v.dot(w))
print(np.dot(v, w)) #矩陣乘法

print("矩陣向量乘法")
print(x.dot(v))
print(np.dot(x, v)) #自動v就轉爲了列向量

print("矩陣乘法")
print(x.dot(y))
print(np.dot(x, y)) #交換位置實現 左右乘
向量乘法
219
219
矩陣向量乘法
[29 67]
[29 67]
矩陣乘法
[[19 22]
 [43 50]]
[[19 22]
 [43 50]]

注意在這裏的矩陣向量乘法中,始終向量是自動調整到能夠適應矩陣乘法的方向,當然如果能夠相乘的話。因爲來python中始終展示的都是行向量所以,他在處理上也自動更換行列向量。下面說說求和與矩陣的轉置,

x = np.array([[1, 2],[3, 4]])
print("所有元素加和")
print(np.sum(x))
print("按列加和")
print(np.sum(x, axis = 0)) #按列求和
print("按行加和")
print(np.sum(x, axis = 1)) #按行求和

print("矩陣轉置前")
print(x)
print("矩陣轉置後")
print(x.T)

v = np.array([1,2,3])
print("向量轉置前")
print(v)
print("向量轉置後")
print(v.T)#轉置操作
所有元素加和
10
按列加和
[4 6]
按行加和
[3 7]
矩陣轉置前
[[1 2]
 [3 4]]
矩陣轉置後
[[1 3]
 [2 4]]
向量轉置前
[1 2 3]
向量轉置後
[1 2 3]

可以看到向量的轉置無變化,還有幾種比較簡潔的矩陣計算方法分別是empty_like,tile和直接相加,爲了計算一個矩陣與一個向量相加,其實就是每一行都對同一個向量對應位置相加。
empty_like()就是生成一個和目標矩陣一樣規模的空矩陣;
tilt()就是擴展成與目標矩陣相對應規模的加項矩陣;
直接相加的方法不夠個性化,但還是挺實用的。

#empty_like()
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1, 0, 1])
y = np.empty_like(x) #相當於不用單獨寫循環去創建y
for i in range(4):
    y[i, :] = x[i, :] + v #按行相加
print("empty_like()")
print(y)

#tile()
vv = np.tile(v, (4, 1))
print("tile()")
print(vv) #當矩陣維度比較大時,for太慢了,我們就直接生成一個加的矩陣
y = x + vv
print(y)

#直接相加
print("直接相加")
y = x + v
print(y)
empty_like()
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]]
 
 tile()
[[1 0 1]
 [1 0 1]
 [1 0 1]
 [1 0 1]]
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]]
 
 直接相加
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]]

細究矩陣計算
雖然前面說了向量轉置無用,但是爲了能夠滿足向量乘法的維度對應,可以使用reshape()函數,來調整向量的結構,dot()矩陣乘法會自動調節矩陣與向量之間行列關係,但是四則運算需要手動調整矩陣向量方向規模,

v = np.array([1,2,3])
w = np.array([4,5])

print(np.reshape(v, (3, 1))*w) #豎着的點乘

x = np.array([[1,2,3], [4,5,6]])#v是3的向量,x有3列所以可以加,以一個[]爲單元
print(x + v)
print((x.T + w).T)
print(x + np.reshape(w, (2, 1)))
print(x * 2)
[[ 4  5]
 [ 8 10]
 [12 15]]
 
[[2 4 6]
 [5 7 9]]
 
[[ 5  6  7]
 [ 9 10 11]]
 
[[ 5  6  7]
 [ 9 10 11]]
 
[[ 2  4  6]
 [ 8 10 12]]

結語
以上就是對於Numpy的基礎分享。主要涉及的就是一些Numpy在矩陣上的計算技巧。
謝謝閱讀。
參考
深度學習cs231n課程numpy講解

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