Numpy學習(2)numpy向量化、numpy操作

Sk8er-boi發表於2020-10-13

1、numpy建立向量,numpy建立的陣列有時也稱為向量,但要注意兩者的區別,需要注意陣列的秩。
numpy使用了優化的C api,運算速度快,在深度學習需要運用numpy向量化加快運算速度
原因是numpy陣列由相同種類資料型別的元素組成,可以快速確定儲存空間。
一個大矩陣做運算,for迴圈是一次提取兩個值,放入記憶體運算後返回結果,再提取2個再運算返回結果,如果迴圈。Numpy是一次性把所有值都提入記憶體同時運算同時返回結果,相當於空間換時間。
標量計算 --> 序列程式設計 = 同時只能做一件事,一件接一件(for迴圈)
向量運算 --> 並行程式設計 = 同時做所有事(向量化)
標量運算:省空間,費時間
向量運算:費空間,省時間

import numpy as np
#行向量
x=np.array([[1,2,3,4]])
print(x)
#列向量
x2=np.array([[1],[2],[3],[4]])
print(y)
#二維向量,矩陣
y=np.arange(1,9).reshape(2,4)
print(y)
#三維向量,矩陣組表,shape(a,b,c)可以理解為a個shape(b,c)的矩陣
z=np.arange(1,9).reshape(2,2,2)
print(z)
[[1 2 3 4]]
[[1 2 3 4]
 [5 6 7 8]]
[[1 2 3 4]
 [5 6 7 8]]
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

注意建立一維向量時,用shape方法檢視陣列的秩。

x3=np.array([1,2,3,4])
x3.shape
(4,)
x.shape
(1, 4)

x1只是秩為1的陣列,x才是一行四列的行向量,
使用x1在後續進行轉置和矩陣乘法等操作時會出現錯誤。
在進行矩陣的為了讓矩陣操作更加顯性化,需要將一維向量用矩陣的形式表示。

#shape方法檢視維度、矩陣行列尺寸
print(z.shape)
#size檢視元素數量
print(z.size)
#ndim檢視維度數量,rank秩
print(z.ndim)#shape中元素個數即為維數,乘積即為矩陣中元素數量
(2, 2, 2)
8
3

2、一些方法

合併vstack()、concatenate()

n1=np.array([[1,2]])
n2=np.array([[1,2]])
n3=np.array([[1,2]])
n4=np.array([[1,2]])
print(np.vstack((x1,y1)))#向下合併
print(np.hstack((x1,y1)))#向右合併
print(np.concatenate((n1,n2,n3),axis=0))#橫向
print(np.concatenate((n1,n2,n3),axis=1))#縱向
[[1 2]
 [1 2]]
[[1 2 1 2]]
[[1 2]
 [1 2]
 [1 2]]
[[1 2 1 2 1 2]]

查詢最大值和最小值max和min函式,可用axis=0,1,2…控制行列

print(z)
#求和
print(np.sum(z))
#返回最大
print(np.max(z))
#返回最小
print(np.min(z))
print(np.min(z,axis=0))#shape(z,x,y)第一個維度"z"最小值
print(np.min(z,axis=1))#x維度最小行
print(np.min(z,axis=2))#y維度最小列
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]
36
8
1
[[1 2]
 [3 4]]
[[1 2]
 [5 6]]
[[1 3]
 [5 7]]

分割,split()

A=np.arange(12).reshape(3,4)
print(A)
print(np.split(A,3,axis=0))#橫向分割成三塊,其中split()中分割的塊數只能是行和列的倍數
print(np.split(A,2,axis=1))#縱向分割成兩塊
print(np.vsplit(A,3))#橫向分割成三塊,其中split()中分割的塊數只能是行和列的倍數
print(np.hsplit(A,2))#縱向分割成兩塊
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]
[array([[0, 1],
       [4, 5],
       [8, 9]]), array([[ 2,  3],
       [ 6,  7],
       [10, 11]])]
[array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]
[array([[0, 1],
       [4, 5],
       [8, 9]]), array([[ 2,  3],
       [ 6,  7],
       [10, 11]])]

切片和索引

#一維陣列切片
a=np.array([1,2,3,4,5,6,7,8])
#冒號分隔切片
b=a[0:7:4]#從第初始位置0(1)開始到第7個位置(8)結束
print(b)

[1 5]
#向量化後一維度陣列相當於二維行、列向量,屬於高維陣列
a1=np.array([[1,2,3,4]])
print(a1[0])#0相當於第一個維度開始
print(a1[0,0])#或print(a1[0][0])第一個維度中的第一個元素

[1 2 3 4]
1
a2=np.array([[1,2,3,4]]).reshape(2,2)
print(a2)
print(a2[0])
print(a2[0,:2])#預設從0開始
[[1 2]
 [3 4]]
[1 2]
[1 2]
a3=np.arange(9).reshape(3,3)
print(a3)
print('切片',a3[:2,2:])#逗號前切行向量,預設從0第一行開始到2第二行結束(不包括第三行)
#逗號後切列向量,從第三列開始預設從倒數一列結束
print('切片',a3[1,...])#省略號…切片,省略號表示列
print('切片',a3[...,1])#省略號表示行
print(a3[1:2,...])#第二行開始到最後一行元素
print(a3[...,:1])#第一列到第二列元素
[[0 1 2]
 [3 4 5]
 [6 7 8]]
切片 [[2]
 [5]]
切片 [3 4 5]
切片 [1 4 7]
[[3 4 5]]
[[0]
 [3]
 [6]]
#三維陣列
a4=np.arange(8).reshape(2,2,2)
print(a4)
print('切片',a4[1,1])
print('索引',a4[0,0,1])

[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]
切片 [6 7]
索引 1

平均值mean(),方差var(){[∑(xn-x帽)^2/n]}(x帽為平均值),
標準偏差std(),Sqr{[∑(xn-x帽)2/n]},公式中∑代表總和,x撥代表x的算術平均值,2代表二次方,代表平方根。

a5=np.array([[4,8,8,4]])
print(np.mean(a5))
print(np.var(a5))
print(np.std(a5))
6.0
4.0
2.0

矩陣的形狀和轉置

#reshape()設定行列
a6=np.array([[0,1,2,3,4,5,6,7]])
print(a6)
print(a6.reshape(2,4))
#轉置
print(a6.reshape(2,4).T)


[[0 1 2 3 4 5 6 7]]
[[0 1 2 3]
 [4 5 6 7]]
[[0 4]
 [1 5]
 [2 6]
 [3 7]]

transpose()三維以上高維陣列的transpose()轉置方法
一維、二維中transpose()和.T並無區別
使用transpose進行多維陣列轉置時,將shape陣列中的數從0開始排序,並稱為索引軸,例如三維陣列z為(0,1,2),含三個索引軸0,1,2
然後三個維度/索引軸交換位置,如(1,0,2)是0軸和1軸交換位置

z=np.arange(8).reshape(2,2,2)
print(z)
print(z.transpose(1,0,2))
#相當於將其降維成的二維矩陣[a,b,c,d],其中a,b,c,d為[0,1],[2,3],[4,5],[6,7]
#將[0,1],[2,3],[4,5],[6,7]視為一個元素,然後再轉置
print(z.transpose(2,1,0))#z.transpose(2,1,0)=z.T轉置
print(z.transpose(2,0,1))
[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]
[[[0 1]
  [4 5]]

 [[2 3]
  [6 7]]]
[[[0 4]
  [2 6]]

 [[1 5]
  [3 7]]]
[[[0 2]
  [4 6]]

 [[1 3]
  [5 7]]]

當1(或2)角標與0角標交換時,新建一個矩陣,將0角標作為行,1(或2)角標作為列。構成一個新矩陣(2,2):
z.transpose(1,0,2)轉置對下列矩陣:
1 2 1 2
1 [0,1] [2,3]→1 [0,1] [4,5]
2 [4,5] [6,7]→2 [2,3] [6,7]

z.transpose(2,1,0)轉置對下列矩陣:
1 2 1 2
1 [0,1] [2,3]→1 [0,4] [2,6]
2 [4,5] [6,7]→2 [1,5] [3,7]

z.transpose(2,0,1)轉置對下列矩陣:
1 2 1 2
1 [0,1] [2,3]→1 [0,2] [4,6]
2 [4,5] [6,7]→2 [1,3] [5,7]

可以寫出每個數在軸的具體位置,(0,1,2)對應z、x、y軸如三維陣列
三軸(0,1,2)z中各元素位置:轉置成(2,0,1),相當於z軸換成原來的y軸,x軸換成原來的z軸,y軸換成原來的x軸,
軸 z,x,y z, x, y z.transpose(2,0,1)
0 (0,0,0) (0,0,0) 找 0
1 (0,0,1) (1,0,0) 到 2
2 (0,1,0) (0,0,1) 重 4 →【【【0 2】
3 (0,1,1) (1,0,1) 置 6 → 【4 6】
4 (1,0,0) (0,1,0) 後 1 → 【1 3】
5 (1,0,1) (1,1,0) 新 3 → 【5,7】】】
6 (1,1,0) (0,1,1) 位 5
7 (1,1,1) (1,1,1) 值 7

#swapaxes()方法
#接收軸編號,對應軸進行交換,只能接受兩個軸的對換
z.swapaxes(1,0)#相當於z.transpose(1,0,2)
array([[[0, 1],
        [4, 5]],

       [[2, 3],
        [6, 7]]])

矩陣的特徵值(eigenvalues)和特徵向量(eigenvectors)
Av =K(λ)v,A為方陣(行列都相等),K為特徵值,v為特徵向量

a7=np.arange(8).reshape(2,2,2)
print(a7)
eigenvalues ,eigenvectors=np.linalg.eig(a7)
print(eigenvalues)
print(eigenvectors)
[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]
[[-0.56155281  3.56155281]
 [-0.17890835 11.17890835]]
[[[-0.87192821 -0.27032301]
  [ 0.48963374 -0.96276969]]

 [[-0.76729658 -0.57152478]
  [ 0.64129241 -0.82058481]]]

矩陣的運算

b2 =np.arange(9).reshape(3,3)
b3=b2.T
print(b2)
print(b3)
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[0 3 6]
 [1 4 7]
 [2 5 8]]
#add()矩陣加法
print(np.add(b2,b3))
#subtract()減法
print(np.subtract(b2,b3))
#數量積*(行*行)
print(b2*b3)#np.multiply(b2,b3)乘法
#dot()向量積/點積(行*列)
print(np.dot(b2,b3))

[[ 0  4  8]
 [ 4  8 12]
 [ 8 12 16]]
[[ 0 -2 -4]
 [ 2  0 -2]
 [ 4  2  0]]
[[ 0  3 12]
 [ 3 16 35]
 [12 35 64]]
[[  5  14  23]
 [ 14  50  86]
 [ 23  86 149]]

矩陣的逆運算AB=BA=E,E為單位矩陣,A、B兩矩陣互為逆矩陣,也稱A是B的逆矩陣

z1= np.array([[1,2,3],[4,5,6],[7,8,9]])
print(z1)
#np.linalg.inv()求逆函式
print(np.linalg.inv(z1))
[[1 2 3]
 [4 5 6]
 [7 8 9]]
[[ 3.15251974e+15 -6.30503948e+15  3.15251974e+15]
 [-6.30503948e+15  1.26100790e+16 -6.30503948e+15]
 [ 3.15251974e+15 -6.30503948e+15  3.15251974e+15]]

相關文章