用實踐帶領你進入numpy的世界——(三):numpy基本運算講解

                         QQ:3020889729                                                                                 小蔡

本節主要講解numpy基本運算講解。
補充,閱讀時,如出現‘點積‘,請忽略,本文不包含該術語名詞——僅僅含有’內積‘的叫法和‘矩陣乘法’
在這裏插入圖片描述
本文以jupyter notebook格式展開~
引入numpy庫

import numpy as np

numpy數組的加法運算(減法類推)

標量相加-向量相加-矩陣相加

標量相加

創建標量數據——標量:即僅包含一個元素——一般來說它僅僅存在於0軸(維度)上

data_one = np.array([1], dtype=np.int32)  
data_two = np.array([0.5], dtype=np.float32)
print("data_one: \n數組內容:{0}, 數據類型:{1}, 數組軸數:{2}, 數組大小(元素個數):{3}".format(data_one, data_one.dtype, data_one.ndim, data_one.size))
print("data_two: \n數組內容:{0}, 數據類型:{1}, 數組軸數:{2}, 數組大小(元素個數):{3}".format(data_two, data_two.dtype, data_two.ndim, data_two.size))

結果(打印):
data_one:
數組內容:[1], 數據類型:int32, 數組軸數:1, 數組大小(元素個數):1
data_two:
數組內容:[0.5], 數據類型:float32, 數組軸數:1, 數組大小(元素個數):1


data_one與data_two相加

result_Add = data_one + data_two
print("result_Add: \n數組內容:{0}, 數據類型:{1}, 數組軸數:{2}, 數組大小(元素個數):{3}".format(result_Add, result_Add.dtype, result_Add.ndim, result_Add.size))

結果(打印):
result_Add:
數組內容:[1.5], 數據類型:float64, 數組軸數:1, 數組大小(元素個數):1


標量相加的特點:

1.存在數據相加後,數據類型自動轉換爲更加穩定(足夠計算)的數據類型。(int32 + float32 = float64)
2.標量相加——軸數保持不變
3.標量相加——元素個數保持不變


向量相加(2D張量相加)

  1. 創建向量數據——向量:即僅包含一列或一行數據元素——一般來說,這樣的數組存在着兩個軸:第0和第1軸;並且行/列向量的區別在於,第0軸的維度大小。
  2. 如果第0軸維度爲1,無論有多少個數據元素,那麼它都是行向量(也就是第1軸維度大於等於1)。
  3. 如果第0軸維度爲數據元素個數,那麼它就是列向量——注意,列向量每一個元素在第0軸中佔一個維度,不能存在多個元素共存(也就是第1軸維度等於1)。
  4. 特殊的向量:僅含一個元素的向量,既是行向量,也是列向量。(第0和第1軸維度大小均爲1.)

創建行向量

data_one = np.zeros((1, 7))
data_two = np.ones((1, 7))
data_three = np.ones((1, 8))  # 創建於前面維度大小不同的行向量

行向量的另外一種創建方法:

# data_one = np.linspace(0, 5, 8)
# data_one = data_one[np.newaxis,:]  # 添軸,實現向量化(單單linspace僅僅創建一個[1,2,3,4,5,……]這樣的內容而已,而向量應該是:[[1,2,3,4,5,……]])

創建列向量

data_four = np.linspace(0, 10, 20).reshape(20, 1)
data_five = np.linspace(-5, 5, 20).reshape(20, 1)
data_six = np.arange(0, 10, 1).reshape(10, 1) # 創建於前面維度大小不同的列向量
  • reshape注意事項:維度值之積應該保證爲原數組的元素個數(大小),否則出現意外,會嚴重影響功能數據的正常進行。

查看數組數據

print("data_one: \n數組內容:{0}, 數據類型:{1}, 數組軸數:{2}, 數組大小(元素個數):{3}".format(data_one, data_one.dtype, data_one.ndim, data_one.size))
print("data_two: \n數組內容:{0}, 數據類型:{1}, 數組軸數:{2}, 數組大小(元素個數):{3}".format(data_two, data_two.dtype, data_two.ndim, data_two.size))
print("data_four: \n數組內容:{0}, 數據類型:{1}, 數組軸數:{2}, 數組大小(元素個數):{3}".format(data_four, data_four.dtype, data_four.ndim, data_four.size))
print("data_five: \n數組內容:{0}, 數據類型:{1}, 數組軸數:{2}, 數組大小(元素個數):{3}".format(data_five, data_five.dtype, data_five.ndim, data_five.size))

結果(打印):
data_one:
數組內容:[[0. 0. 0. 0. 0. 0. 0.]], 數據類型:float64, 數組軸數:2, 數組大小(元素個數):7

data_two:
數組內容:[[1. 1. 1. 1. 1. 1. 1.]], 數據類型:float64, 數組軸數:2, 數組大小(元素個數):7

data_four:
數組內容:[[ 0. ]
[ 0.52631579]
[ 1.05263158]
[ 1.57894737]
[ 2.10526316]
[ 2.63157895]
[ 3.15789474]
[ 3.68421053]
[ 4.21052632]
[ 4.73684211]
[ 5.26315789]
[ 5.78947368]
[ 6.31578947]
[ 6.84210526]
[ 7.36842105]
[ 7.89473684]
[ 8.42105263]
[ 8.94736842]
[ 9.47368421]
[10. ]], 數據類型:float64, 數組軸數:2, 數組大小(元素個數):20

data_five:
數組內容:[[-5. ]
[-4.47368421]
[-3.94736842]
[-3.42105263]
[-2.89473684]
[-2.36842105]
[-1.84210526]
[-1.31578947]
[-0.78947368]
[-0.26315789]
[ 0.26315789]
[ 0.78947368]
[ 1.31578947]
[ 1.84210526]
[ 2.36842105]
[ 2.89473684]
[ 3.42105263]
[ 3.94736842]
[ 4.47368421]
[ 5. ]], 數據類型:float64, 數組軸數:2, 數組大小(元素個數):20


行向量相加——相加的向量維度要相同

print("data_one :", data_one)
print("data_two :", data_two)
print("相同維度的行向量相加:data_one + data_two = ", data_one + data_two)
# print("data_three :", data_three)
# print("維度不同的行向量相加:data_one + data_three = ", data_one + data_three)  # 會報錯,說明向量相加應該保證維度相同

結果(打印):
data_one : [[0. 0. 0. 0. 0. 0. 0.]]
data_two : [[1. 1. 1. 1. 1. 1. 1.]]
相同維度的行向量相加:data_one + data_two = [[1. 1. 1. 1. 1. 1. 1.]]


列向量相加——相加的向量維度要相同

print("data_four :", data_four)
print("data_five :", data_five)
print("相同維度的行向量相加:data_four + data_five = ", data_four + data_five)
# print("data_three :", data_six)
# print("維度不同的行向量相加:data_four + data_six = ", data_four + data_six)  # 會報錯,說明向量相加應該保證維度相同

結果(打印):
data_four : [[ 0. ]
[ 0.52631579]
[ 1.05263158]
[ 1.57894737]
[ 2.10526316]
[ 2.63157895]
[ 3.15789474]
[ 3.68421053]
[ 4.21052632]
[ 4.73684211]
[ 5.26315789]
[ 5.78947368]
[ 6.31578947]
[ 6.84210526]
[ 7.36842105]
[ 7.89473684]
[ 8.42105263]
[ 8.94736842]
[ 9.47368421]
[10. ]]
data_five : [[-5. ]
[-4.47368421]
[-3.94736842]
[-3.42105263]
[-2.89473684]
[-2.36842105]
[-1.84210526]
[-1.31578947]
[-0.78947368]
[-0.26315789]
[ 0.26315789]
[ 0.78947368]
[ 1.31578947]
[ 1.84210526]
[ 2.36842105]
[ 2.89473684]
[ 3.42105263]
[ 3.94736842]
[ 4.47368421]
[ 5. ]]
相同維度的行向量相加:data_four + data_five = [[-5. ]
[-3.94736842]
[-2.89473684]
[-1.84210526]
[-0.78947368]
[ 0.26315789]
[ 1.31578947]
[ 2.36842105]
[ 3.42105263]
[ 4.47368421]
[ 5.52631579]
[ 6.57894737]
[ 7.63157895]
[ 8.68421053]
[ 9.73684211]
[10.78947368]
[11.84210526]
[12.89473684]
[13.94736842]
[15. ]]


向量相加的特點:

  1. 存在數據相加後,數據類型自動轉換爲更加穩定(足夠計算)的數據類型。(int32 + float32 = float64)
  2. 向量相加——維度大小要相同
  3. 向量相加——軸數保持不變
  4. 向量相加——元素個數保持不變 ②矩陣相加(2D張量相加)——矩陣可以簡單理解爲多個維度大小相同的行向量連接的形式

矩陣相加(2D張量)

向量與矩陣的關係

行向量:

[[1, 2, 3]]
[[4, 5, 6]]
[[7, 8, 9]]
矩陣:

[[1, 2, 3]
[4, 5, 6]
[7, 8, 9]]


創建矩陣

# 2*2
data_one = np.ones((2, 2))
# 2*2
data_two = np.empty((2, 2))
# 2*3
data_three = np.empty((2, 3))

查看矩陣數組數據

print("data_one: \n數組內容:\n {0} \n 數據類型:{1}\n 數組軸數:{2}\n 數組大小(元素個數):{3}\n".format(data_one, data_one.dtype, data_one.ndim, data_one.size))
print("data_two: \n數組內容:\n {0}\n數據類型:{1}\n 數組軸數:{2}\n 數組大小(元素個數):{3}\n".format(data_two, data_two.dtype, data_two.ndim, data_two.size))
print("data_three: \n數組內容:\n {0}\n數據類型:{1}\n 數組軸數:{2}\n數組大小(元素個數):{3}\n".format(data_three, data_three.dtype, data_three.ndim, data_three.size))

結果(打印):
data_one:
數組內容:
[[1. 1.]
[1. 1.]]
數據類型:float64
數組軸數:2
數組大小(元素個數):4

data_two:
數組內容:
[[7.26615900e+223 1.06097757e-153]
[1.27874063e-152 5.76502240e+228]]
數據類型:float64
數組軸數:2
數組大小(元素個數):4

data_three:
數組內容:
[[4.901e-321 4.901e-321 5.474e-321]
[5.474e-321 5.237e-321 5.237e-321]]
數據類型:float64
數組軸數:2
數組大小(元素個數):6


矩陣相加

data_one + data_two
# data_one + data_three  # 維度不同無法計算,報錯

結果(打印):
array([[7.2661590e+223, 1.0000000e+000],
[1.0000000e+000, 5.7650224e+228]])


numpy數組的乘除法運算

標量乘除法運算

data_one = np.array([1], dtype=np.int32)
data_two = np.array([2], dtype=np.int32)
print("乘法運算:data_one * data_two \n 結果爲:\n{0}  ,  dtype = {1}".format(data_one * data_two, (data_one * data_two).dtype))
print("除法運算:data_one / data_two \n 結果爲:\n{0}  ,  dtype = {1}".format(data_one / data_two,  (data_one / data_two).dtype))

結果(打印):
乘法運算:data_one * data_two
結果爲:
[2] , dtype = int32
除法運算:data_one / data_two
結果爲:
[0.5] , dtype = float64


向量乘除法運算

data_one = np.random.randint(1, 10, (1,8))
data_two = np.random.randint(1, 10, (8,1))
data_three = np.random.randint(10, 20, (7,1))

查看數組數據

data_one

結果(打印):
array([[1, 6, 8, 5, 7, 5, 5, 3]])


查看數組數據

data_two

結果(打印):
array([[3],
[9],
[6],
[5],
[9],
[7],
[5],
[4]])


兩向量相乘

print("向量相乘的向量形狀:(8, 1) * (1, 8):\n", data_two * data_one)
print("向量相乘的向量形狀:(1, 8) * (8, 1):\n", data_one * data_two)

結果(打印):
向量相乘的向量形狀:(8, 1) * (1, 8):
[[ 3 18 24 15 21 15 15 9]
[ 9 54 72 45 63 45 45 27]
[ 6 36 48 30 42 30 30 18]
[ 5 30 40 25 35 25 25 15]
[ 9 54 72 45 63 45 45 27]
[ 7 42 56 35 49 35 35 21]
[ 5 30 40 25 35 25 25 15]
[ 4 24 32 20 28 20 20 12]]
向量相乘的向量形狀:(1, 8) * (8, 1):
[[ 3 18 24 15 21 15 15 9]
[ 9 54 72 45 63 45 45 27]
[ 6 36 48 30 42 30 30 18]
[ 5 30 40 25 35 25 25 15]
[ 9 54 72 45 63 45 45 27]
[ 7 42 56 35 49 35 35 21]
[ 5 30 40 25 35 25 25 15]
[ 4 24 32 20 28 20 20 12]]


兩向量相乘(形狀不對稱的向量)

print("向量相乘的向量形狀:(1, 8) * (7, 1):\n", data_one * data_three)
print("向量相乘的向量形狀:(7, 1) * (1, 8):\n", data_three * data_one)
# print("向量相乘的向量形狀:(8, 1) * (7, 1):\n", data_two * data_three)  # 報錯,維度錯誤

結果(打印):
向量相乘的向量形狀:(1, 8) * (7, 1):
[[ 17 102 136 85 119 85 85 51]
[ 14 84 112 70 98 70 70 42]
[ 17 102 136 85 119 85 85 51]
[ 18 108 144 90 126 90 90 54]
[ 17 102 136 85 119 85 85 51]
[ 17 102 136 85 119 85 85 51]
[ 18 108 144 90 126 90 90 54]]
向量相乘的向量形狀:(7, 1) * (1, 8):
[[ 17 102 136 85 119 85 85 51]
[ 14 84 112 70 98 70 70 42]
[ 17 102 136 85 119 85 85 51]
[ 18 108 144 90 126 90 90 54]
[ 17 102 136 85 119 85 85 51]
[ 17 102 136 85 119 85 85 51]
[ 18 108 144 90 126 90 90 54]]


向量相乘的特點總結:

  1. 相乘的兩向量,必須存在一個向量的行數要與另一個向量的列數相同,否則不能相乘。

print("data_one : \n{0}, shape = {1}".format(data_one, data_one.shape))
print("data_two : \n{0}, shape = {1}".format(data_two, data_two.shape))
print("向量相除的向量形狀:(8, 1) / (1, 8):\n{0} shape = {1}".format(data_two / data_one, (data_two / data_one).shape))
print("向量相除的向量形狀:(1, 8) / (8, 1):\n{0} shape = {1}".format(data_one / data_two, (data_one / data_two).shape))

結果(打印):
data_one :
[[1 6 8 5 7 5 5 3]], shape = (1, 8)

data_two :
[[3]
[9]
[6]
[5]
[9]
[7]
[5]
[4]], shape = (8, 1)

向量相除的向量形狀:(8, 1) / (1, 8):
[[3. 0.5 0.375 0.6 0.42857143 0.6
0.6 1. ]
[9. 1.5 1.125 1.8 1.28571429 1.8
1.8 3. ]
[6. 1. 0.75 1.2 0.85714286 1.2
1.2 2. ]
[5. 0.83333333 0.625 1. 0.71428571 1.
1.1.66666667]
[9. 1.5 1.125 1.8 1.28571429 1.8
1.8 3. ]
[7. 1.16666667 0.875 1.4 1. 1.4
1.4 2.33333333]
[5. 0.83333333 0.625 1. 0.71428571 1.
1.1.66666667]
[4. 0.66666667 0.5 0.8 0.57142857 0.8
0.8 1.33333333]] shape = (8, 8)

向量相除的向量形狀:(1, 8) / (8, 1):
[[0.33333333 2. 2.66666667 1.66666667 2.33333333 1.66666667
1.66666667 1.]
[0.11111111 0.66666667 0.88888889 0.55555556 0.77777778 0.55555556
0.55555556 0.33333333]
[0.16666667 1.1.33333333 0.83333333 1.16666667 0.83333333
0.83333333 0.5 ]
[0.2 1.2 1.6 1. 1.4 1.
1.0.6 ]
[0.11111111 0.66666667 0.88888889 0.55555556 0.77777778 0.55555556
0.55555556 0.33333333]
[0.14285714 0.85714286 1.14285714 0.71428571 1. 0.71428571
0.71428571 0.42857143]
[0.2 1.2 1.6 1. 1.4 1.
1.0.6 ]
[0.25 1.5 2. 1.25 1.75 1.25
1.25 0.75 ]] shape = (8, 8)


print("data_one : \n{0}, shape = {1}".format(data_one, data_one.shape))
print("data_two : \n{0}, shape = {1}".format(data_two, data_two.shape))
print("data_three : \n{0}, shape = {1}".format(data_three, data_three.shape))
print("向量相除的向量形狀:(1, 8) / (7, 1):\n{0} shape = {1}".format(data_one / data_three, (data_one / data_three).shape))
print("向量相除的向量形狀:(7, 1) / (1, 8):\n{0} shape = {1}".format(data_three / data_one, (data_three / data_one).shape))
# print("向量相除的向量形狀:(8, 1) / (7, 1):\n{0} shape = {1}".format(data_two / data_three, (data_two / data_three).shape)) # 報錯,維度錯誤

結果(打印):
data_one :
[[1 6 8 5 7 5 5 3]], shape = (1, 8)

data_two :
[[3]
[9]
[6]
[5]
[9]
[7]
[5]
[4]], shape = (8, 1)

data_three :
[[17]
[14]
[17]
[18]
[17]
[17]
[18]], shape = (7, 1)

向量相除的向量形狀:(1, 8) / (7, 1):
[[0.05882353 0.35294118 0.47058824 0.29411765 0.41176471 0.29411765
0.29411765 0.17647059]
[0.07142857 0.42857143 0.57142857 0.35714286 0.5 0.35714286
0.35714286 0.21428571]
[0.05882353 0.35294118 0.47058824 0.29411765 0.41176471 0.29411765
0.29411765 0.17647059]
[0.05555556 0.33333333 0.44444444 0.27777778 0.38888889 0.27777778
0.27777778 0.16666667]
[0.05882353 0.35294118 0.47058824 0.29411765 0.41176471 0.29411765
0.29411765 0.17647059]
[0.05882353 0.35294118 0.47058824 0.29411765 0.41176471 0.29411765
0.29411765 0.17647059]
[0.05555556 0.33333333 0.44444444 0.27777778 0.38888889 0.27777778
0.27777778 0.16666667]] shape = (7, 8)

向量相除的向量形狀:(7, 1) / (1, 8):
[[17. 2.83333333 2.125 3.4 2.42857143 3.4
3.4 5.66666667]
[14. 2.33333333 1.75 2.8 2. 2.8
2.8 4.66666667]
[17. 2.83333333 2.125 3.4 2.42857143 3.4
3.4 5.66666667]
[18. 3. 2.25 3.6 2.57142857 3.6
3.6 6. ]
[17. 2.83333333 2.125 3.4 2.42857143 3.4
3.4 5.66666667]
[17. 2.83333333 2.125 3.4 2.42857143 3.4
3.4 5.66666667]
[18. 3. 2.25 3.6 2.57142857 3.6
3.6 6. ]] shape = (7, 8)


向量相除的特點總結:

  1. 相除的兩向量,必須存在一個向量的行數要與另一個向量的列數相同,否則不能相除。
  2. 向量除法也就相當於:矩陣1 * (1/矩陣2)

矩陣乘法運算

一般計算只支持形狀相同的矩陣,但是使用np.dot可以實現數學上的點積

創建矩陣

# 創建矩陣——2*2
data_one = np.ones((2, 2), dtype=np.int32)
# 2*2
data_two = np.random.randint(1, 10, (2, 2))
# 3*3
data_three = np.random.randint(-5, 10, (3, 3))
# 3*3
data_four = np.random.randint(1, 10, (3, 3))

形狀相同的矩陣相乘(內積)(2*2)

data_one * data_two

結果(打印):
array([[8, 1],
[3, 5]])

data_two * data_one  # 交換乘積順序,不影響計算

結果(打印):
array([[8, 1],
[3, 5]])


形狀相同的矩陣相乘(3*3)

data_four * data_three 
# print(data_four * data_two) # 報錯,維度錯誤

結果(打印):
array([[-25, 8, 12],
[ 0, -18, 28],
[ 30, -5, 5]])


以上運算僅僅支持矩陣形狀完全相同的乘法運算

創建一個2*3的矩陣爲dot乘法做準備

創建一個2*3的矩陣
data_seven = np.random.randint(13,  29, (2, 3))
data_seven

結果(打印):
array([[24, 16, 28],
[16, 13, 28]])


引入之前的data_one矩陣
查看data_one數組數據

data_one

結果(打印):
array([[1, 1],
[1, 1]])


進行dot乘法運算

np.dot(data_one, data_seven)  
  • data_one與data_seven的矩陣乘法,順序確定,不可隨意調換順序 ,否則可能行列關係不對應,而導致報錯。
    結果(打印):
    array([[40, 29, 56],
    [40, 29, 56]])

矩陣除法運算

維度形狀相同的矩陣除法運算

data_one / data_two  # 引入之前的data_one, data_two

結果(打印):
array([[0.125 , 1. ],
[0.33333333, 0.2 ]])


滿足矩陣乘法,維度形狀不定的矩陣除法運算(即23與34,也可以是23與38)

np.dot(data_one, 1/data_seven)  # 相當於:data_one / data_seven

結果(打印):
array([[0.10416667, 0.13942308, 0.07142857],
[0.10416667, 0.13942308, 0.07142857]])

np.dot(1/data_one, data_seven)   # 相當於:data_seven / data_one

結果(打印):
array([[40., 29., 56.],
[40., 29., 56.]])


numpy運算講解的總結

1.加減法總結

  • 無論是標量、向量、矩陣——都應該保證形狀大小相同。
  • 標量是隻存在第0軸的array數組,向量和矩陣存在第0和第1軸的array數組。
  • 行向量——第0軸維度大小隻能是1;列向量——第1軸維度大小隻能是1.

2.乘除法總結

  • 標量直接相乘;向量只需要保證相乘的向量存在一組行列對應的關係即可相乘。
  • 行列關係:某一向量或矩陣的行數與另一個運算的向量或矩陣的列數相等。
  • 矩陣相乘有兩種:
    1.一種是矩陣形狀完全相同,可以直接相乘(也叫內積);
    2.第二種是滿足行列關係,可以使用np.dot進行線代數學的矩陣乘法。

矩陣乘法規則可查‘矩陣乘法’得知。

實用性簡要說明

我們用得比較多的其實是向量和矩陣的相關運算。
因爲我們可以通過使用向量和矩陣來存儲有一定關係的數據,或者存在某種規則下的數據,我們只需要使用對應的運算方法,就可以實現大量數據的快速計算——這樣既保證了數據的完整,也保證了效率(主要原因)。


厭倦了,一個數據一個數據單獨處理,爲什麼不試試對數據進行某種約定,轉換成矩陣或向量來處理大量數據呢?

Numpy,是你走上數據處理之路上的好朋友。

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