1. Jupyter Notebook、numpy的使用
阿新 • • 發佈:2019-01-07
一. Jupter Notebook中的魔法方法
%run的使用
- 載入不在專案包中的檔案
- 專案中的包不使用%run, 使用python的import語法即可
1. %run myscript/hello.py
2. hello("balabala") # 這樣就可以直接呼叫hello.py中的函數了
%timeit的使用
- 會先自動 把程式重複執行一定次數, 程式執行時間太短就會迴圈更多次
- 通過找到最快的3次迴圈, 得到程式執行的時間
1. %timeit L = [i**2 for i in range(1000)] 結果: 1000 loops, best of 3: 515 µs per loop
%time的使用
- 不會把程式重複執行, 只執行一次得到程式的執行時間
- cputime是計算機cpu和sys 計算所用時間的和
- walltime是現實世界流逝的時間
- 得到的時間是不穩定的
- 在只需要知道大概的時間或者程式執行時間太長, 適用
1. %time L = [i**2 for i in range(1000)]
結果: CPU times: user 452 µs, sys: 17 µs, total: 469 µs
Wall time: 536 µs
如果想要測試整段程式碼, 可以使用%%
- 舉例
%%time for e in [1,2,3,4,6]: print(e)
二. Numpy資料基礎
np.array的使用
1. import numpy as np
2. nparr = np.array([i for i in range(10)])
3. nparr
out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1. nparr[5]
out: 5
1. nparr[5]=100.0
2. nparr[5]
out: 100
1. nparr.dtype
out: dtype('int64') # 之前的100.0被 隱式地型別轉換了
三. 建立Numpy陣列和矩陣
- 建立全零矩陣
1. np.zeros(10) # 預設是浮點數型別
out: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
2. np.zeros(10, dtype=int) # 可以指定為 int 型別
out: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
3. np.zeros((3,5)) # 傳入元組 表示維度
out:array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
4. np.zeros(shape=(3,5), dtype=int) # 3中其實省略了shape
out:array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
- 建立全一矩陣
1. np.ones((3,5)) # 用法和zeros一樣
out: array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
- 建立全部都為指定值的矩陣
1. np.full((3,5), 666) # 省略了引數名 np.full(shape=(3,5), full_value=666)
out:array([[666, 666, 666, 666, 666],
[666, 666, 666, 666, 666],
[666, 666, 666, 666, 666]])
# 這裡 full_value是 666, out就會是int型, 如果給的是666.0, out就會是浮點型
- np.arrange
1. np.arange(0,1,0.2)
out: array([0. , 0.2, 0.4, 0.6, 0.8])
# np.arange使用方法和python基礎語法range一樣, 得到前閉後開的資料集
# 但np.arange步長可以是浮點數, 二range只能是整數
- np.linspace
1. np.linspace(0,20,10)
out:array([ 0. , 2.22222222, 4.44444444, 6.66666667, 8.88888889,
11.11111111, 13.33333333, 15.55555556, 17.77777778, 20. ])
# linspace 第三個引數是 得到的資料個數, 而非步長
- np.random.randint
1. np.random.randint(0, 10, 10) # 生成10個 0~10的隨機數, 組成的向量
out:array([1, 8, 1, 4, 6, 8, 7, 1, 7, 1])
2. np.random.randint(4,8,size=(3,5)) # 生成3x5的隨機矩陣
out:array([[7, 5, 4, 5, 5],
[4, 6, 7, 6, 5],
[5, 6, 6, 6, 7]])
3. np.random.seed(666) # 指定隨機種子
4. np.random.randint((4,8, size=(3,5))
out:array([[4, 6, 5, 6, 6],
[6, 5, 6, 4, 5],
[7, 6, 7, 4, 7]])
5. np.random.randint((4,8, size=(3,5)) # 在指定了隨機種子後, 會生成一樣的隨機矩陣
out:array([[4, 6, 5, 6, 6],
[6, 5, 6, 4, 5],
[7, 6, 7, 4, 7]])
# 除錯時, 希望重現 一樣的隨機矩陣, 這時需要用到np.random.seed
- np.random.random
1. np.random.random() # 生成0~1的 隨機浮點數
out:0.2811684913927954
2. np.random.random(10)
out:array([0.46284169, 0.23340091, 0.76706421, 0.81995656, 0.39747625,
0.31644109, 0.15551206, 0.73460987, 0.73159555, 0.8578588 ])
3. np.random.random((3,5))
out:array([[0.76741234, 0.95323137, 0.29097383, 0.84778197, 0.3497619 ],
[0.92389692, 0.29489453, 0.52438061, 0.94253896, 0.07473949],
[0.27646251, 0.4675855 , 0.31581532, 0.39016259, 0.26832981]])
4. np.random.normal() # 符合正態分佈,均值為0 , 方差為1 的隨機浮點數
out:0.7760516793129695
5. np.random.normal(10,100) # 指定均值為10, 方差為100
out:128.06359754812632
6. np.random.normal(0,1, (3,5)) # 均值0 方差1 size為3x5
out:array([[ 0.06102404, 1.07856138, -0.79783572, 1.1701326 , 0.1121217 ],
[ 0.03185388, -0.19206285, 0.78611284, -1.69046314, -0.98873907],
[ 0.31398563, 0.39638567, 0.57656584, -0.07019407, 0.91250436]])
當對函式的引數不清楚時, 使用?
1. np.random.normal? # 帶上? 就會跳出 對應的文件
Docstring:
normal(loc=0.0, scale=1.0, size=None) # loc均值 scale方差
Draw random samples from a normal (Gaussian) distribution.
The probability density function of the normal distribution, first
derived by De Moivre and 200 years later by both Gauss and Laplace
independently [2]_, is often called the bell curve because of
its characteristic shape (see the example below)............
2. help(np.random.normal)
# 和使用?, 效果類似,
# 但? 是為跳出一個小頁面的說明文件
# help 會把說明文件 放在 out: 後面
四. Numpy陣列和矩陣的基本操作
屬性
In:x1 = np.arange(10)
In:x2 = np.arange(15).reshape(3,5)
In:x1.ndim
out: 1 # ndim表示矩陣 的維度
In:x2.ndim
out: 2
In:x1.shape
out: (10,) # shape表示 矩陣是 多少x多少的
In:x2.shape
out: (3,5)
In:x1.size
out: 10 # size表示 矩陣中元素的個數
In:x2.size
out: 15
numpy.array 的資料訪問
In:x2
out:array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
In:x2[0][0]
out:0 # [][] 的訪問方法 是可行的, 但不建議
In:x2[2,2]
out: 12 # 建議 [,]這樣訪問
# python切片的語法同樣適用於np.array
In:x1
out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In:x1[:4]
out: array([0, 1, 2, 3])
# 對於多維的訪問 必須使用[,] 不能使用[][]
In: x2[:2][:3]
out: array([[0, 1, 2, 3, 4], # 得到的不是 前兩行的 前3列
[5, 6, 7, 8, 9]])
In: x2[:2,:3]
out: array([[0, 1, 2], # 得到了想要的結果
[5, 6, 7]])
# 子矩陣的修改會 直接影響到父矩陣
# np.array中因為追求效率, 所以子矩陣是父矩陣的引用
In: subX = x2[:2,:3]
In: subX
out: array([[0, 1, 2],
[5, 6, 7]])
In: subX[0,0] = 100000
In: subX
out: array([[100000, 1, 2],
[ 5, 6, 7]])
In: x2
out:array([[100000, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14]]) # 可以看到父矩陣的[0,0]元素也改變了
# 同理, 父矩陣的元素改變, 子矩陣也會改變
# 如果想要子矩陣 與 父矩陣 不互相影響, 可以使用copy
In: subX = x2[:2, :3].copy() # 這樣子矩陣和父矩陣就不會相互影響了
reshape
In: x1.reshape(2,5)
out: array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
# 想把 x1 變為10行, 有多少列 不清楚, 可以用-1代替
In: x1.reshape(10, -1)
out:array([[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
In: x1.reshape(2, -1) # 變為2 行, 多少列 不去管
out:array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
五.Numpy陣列(和矩陣)的合併與分割
合併
# 一維矩陣的合併
In:x = np.array([1,2,3])
In:y = np.array([3,2,1])
In:np.concatenate([x,y])
out:array([1, 2, 3, 3, 2, 1])
In:z = np.array([666,666,666])
In:np.concatenate([x,y,z])
out: array([ 1, 2, 3, 3, 2, 1, 666, 666, 666])
# 二維矩陣 的合併
In: A = np.array([[1,2,3],
In: [4,5,6]])
In: np.concatenate([A,A]) # 這裡預設引數axis=0, 即拓展行數
out: array([[1, 2, 3],
[4, 5, 6],
[1, 2, 3],
[4, 5, 6]])
In: np.concatenate([A,A], axis=1) # 拓展列
out: array([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])
# 不同維度矩陣的合併方法一
In: np.concatenate([A, z.reshape(1, -1)]) # 需要將z的維度 由3行1列 變為1行3列, 和A一樣
out: array([[ 1, 2, 3],
[ 4, 5, 6],
[666, 666, 666]])
# 補充說明
[1,2,3] 向量
[[1,2,3]] 1行3列矩陣
[[1],[2],[3]] 3行1列矩陣
# 不同維度矩陣的合併方法二: vstack和hstack
In:np.vstack([A,z]) # A的列數和z的元素個數相等, 所以使用vstack垂直方向合併, 並不需要對z進行reshape
out: array([[ 1, 2, 3],
[ 4, 5, 6],
[666, 666, 666]])
In:B = np.array([[777],[777]]) # [777,777]就表示向量, hstack會報錯
In:B
out:array([[777],
[777]])
In: np.hstack([A,B])
out: array([[ 1, 2, 3, 777],
[ 4, 5, 6, 777]])
分割
- 一維的分割
In:x = np.arange(10)
In:x1, x2, x3 = np.split(x, [3, 7])
In:x1
out:array([0, 1, 2])
In:x2
out:array([3, 4, 5, 6])
In:x3
out:array([7, 8, 9])
- 多維的分割
# 行方向的分割
In:A = np.arange(16).reshape((4,4))
In:A
out:array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
In:A1, A2 = np.split(A, [2]) # 或者 upper, lower = np.vsplit(A, [2])
In:A1
out:array([[0, 1, 2, 3],
[4, 5, 6, 7]])
In:A2
out:array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])
# 列方向的分割
In:A1, A2 = np.split(A, [2], axis=1) # axis=1指定列分割 或者 left,right = np.hsplit(A, [2])
In:A1
out:array([[ 0, 1],
[ 4, 5],
[ 8, 9],
[12, 13]])
In:A2
out:array([[ 2, 3],
[ 6, 7],
[10, 11],
[14, 15]])
六. Numpy中矩陣的運算
對矩陣的元素的元素
# python原生list 實現 將矩陣的元素都x2
n = 10
L = [i for i in range(n)]
A = [2*e for e in L]
# numpy.array實現 將矩陣的元素都x2
import numpy as np
L = np.arange(n)
A = np.array(2*e for e in L)
# np.array 如果用%%time測試執行時間, 發現比python的list實現, 快得多
# np.array 可以直接*2, 符合矩陣的運算結果, python的list*2 則是list+list 連起來
A = L*2 # 可以直接得到每個元素*2的新矩陣
# np.array 幾乎支援其他所有運算 如
L+1 每個元素+1
L-1
L*2
L/3
1/L 每個元素都變為 倒數
L//5 每個元素整除5
L**3 每個元素冪運算
L%7 每個元素求餘數
對矩陣間的運算
- 運算子進行的是 矩陣元素間的運算
In:A=np.arange(4).reshape(2,2)
In:A
out:array([[0, 1],
[2, 3]])
In:B=np.full((2,2), 10)
In:B
out:array([[10, 10],
[10, 10]])
In:A+B
out:array([[10, 11],
[12, 13]])
In:A-B
out:array([[-10, -9],
[ -8, -7]])
In:A*B
out:array([[ 0, 10],
[20, 30]])
In:A/B
out:array([[0. , 0.1],
[0.2, 0.3]])
# 可以看到都是元素間 進行運算, 而不是矩陣的運算
- 矩陣運算
# 矩陣相乘
In: A.dot(B)
out:array([[10, 10],
[50, 50]])
# 矩陣的轉置
In: A.T
out: array([[0, 2],
[1, 3]])
- 向量和矩陣的運算
In:v=np.array([1,2])
In:A
out:array([[0, 1],
[2, 3]])
In:v+A # 向量直接與矩陣相加, 會讓矩陣的每一行都加上該向量
out:array([[1, 3],
[3, 5]])
In: np.vstack([v]*A.shape[0]) # 或者可以把向量變為維度和A一樣的矩陣 再進行相加
out:array([[1, 2],
[1, 2]])
In:np.tile(v, (2,1)) # tile也可以改變維度, 2表示複製為2行, 1表示複製為1列, 即列方向不拓展
out:array([[1, 2],
[1, 2]])
In: v*A # 這樣的到 是 v與A的每一行乘, 不是矩陣的乘法
out:array([[0, 2],
[2, 6]])
In: v.dot(A) # 想要矩陣相乘 依然使用dot
out:array([4, 7])
In: A.dot(v) # v是向量, numpy會自動把v變為2*1的矩陣
out:array([2, 8])
- 矩陣的逆
In:A
out:array([[0, 1],
[2, 3]])
In:invA = np.linalg.inv(A) # 得到A的逆矩陣 invA
In:invA
out:array([[-1.5, 0.5],
[ 1. , 0. ]])
In: A.dot(invA) # 原矩陣乘 逆矩陣 得到單位矩陣
out:array([[1., 0.],
[0., 1.]])
七. Numpy的聚合運算
# 聚合
import numpy as np
L = np.random.random(100) # 生成100個元素的隨機陣列
L.dtype
out:dtype('float64')
np.sum(L) # 求和
out:48.17857390434729
sum(L) # python的sum 也可以實現, 但 速度比np.sum 慢非常多
out:48.178573904347246
np.min(L) # 找出最小值
out:0.007983418226231609
np.max(L) # 找出最大值
out:0.9875521184825461
X= np.arange(16).reshape(4,-1)
X
out:array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
np.sum(X) # 預設為 對所有元素求和
out:120
np.sum(X, axis=0) # 對每一列 求和, axis=0可以理解為 壓縮為一行
out:array([24, 28, 32, 36])
np.sum(X, axis=1) # 對每一行 求和, axis=1可以理解為 壓縮為一列
out:array([ 6, 22, 38, 54])
np.prod(X) # 所有元素的乘積
out:0
np.mean(X) # 所有元素均值
out:7.5
np.median(X) # 所有元素 中位數
out:7.5
np.percentile(X, q=50) # 在50%的 地方找到 百分位點 和np.median(X) 等價
out:7.5
np.percentile(X, q=90) # 在90% 的地方找到百分位點
out:13.5
np.var(X) # 方差
out:21.25
np.std(X) # 標準差
out:4.6097722286464435
八. Numpy中的索引運算(arg運算)
- 找到最值的索引
x = np.random.normal(0,1,size=1000000) # 生成 均值為0 方差為1 的正態分佈點
np.min(x) # 得到了 最小值, 但想知道 該值 在哪個位置
out:-5.024177664592925
np.argmin(x) # 找到最小值 的索引位置
out:628924
#同樣的 有argmax
- 排序和使用索引
# 排序
x = np.arange(16)
x
out:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
np.random.shuffle(x) # shuffle 將x中元素順序打亂
x
out:array([ 3, 4, 0, 7, 11, 8, 12, 15, 5, 14, 13, 1, 9, 6, 10, 2])
np.sort(x) # 得到一個新的 排好序的數列
out:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
x.sort() # 在原來的x中排序
x
out:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
# arg排序
np.random.shuffle(x) # 打亂順序
x
out:array([13, 10, 7, 0, 12, 5, 14, 15, 9, 2, 3, 6, 11, 4, 8, 1])
np.argsort(x) # 得到的是索引, 按索引 找到的元素, 都是排序好的元素
out:array([ 2, 11, 9, 15, 1, 10, 14, 7, 4, 3, 5, 6, 12, 8, 0, 13])
# partition操作
np.partition(x,3) # 小於3的放3前面 大於3的放3後面, 和快速排序中的partition一致
out:array([ 1, 0, 2, 3, 4, 6, 7, 5, 8, 9, 10, 12, 11, 13, 14, 15])
np.argpartition(x,3) # 同樣有 arg方法
out:array([15, 3, 9, 10, 13, 11, 2, 5, 14, 8, 1, 4, 12, 0, 6, 7])
# 多維的排序
X = np.random.randint(10, size=(4,4)) # 生成4x4的 隨機矩陣
X
out:array([[2, 1, 7, 8],
[0, 8, 7, 3],
[7, 6, 1, 9],
[0, 2, 9, 8]])
np.sort(X) # 預設axis=1
out:array([[1, 2, 7, 8],
[0, 3, 7, 8],
[1, 6, 7, 9],
[0, 2, 8, 9]])
np.sort(X, axis=1) # 沿著列的方向 對每一行排序
out:array([[1, 2, 7, 8],
[0, 3, 7, 8],
[1, 6, 7, 9],
[0, 2, 8, 9]])
np.sort(X, axis=0) # 沿著行的方向 對每一行列序
out:array([[0, 1, 1, 3],
[0, 2, 7, 8],
[2, 6, 7, 8],
[7, 8, 9, 9]])
九. Numpy中的比較和Fancy indexing
- Fancy indexing
import numpy as np
x = np.arange(16)
x
out:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
[x[3], x[5],x[8]] # 得到新的陣列, 但numpy有更加方便的方法
out: [3, 5, 8]
ind = [3,5,8] # numpy提供的方法, 即fancy indexing
x[ind]
out:array([3, 5, 8])
# 多維的Fancy indexing
X = x.reshape(4,-1)
X
out:array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
row = np.array([0,1,2]) #現在想要得到3個點, row中存放這3個點的所在行數
col = np.array([1,2,3]) # col 放3個點所在列數
X[row, col]
out:array([ 1, 6, 11])
X[0, col]
out:array([1, 2, 3])
X[:2, col] # 前兩行的 對應col 得到數值
out:array([[1, 2, 3],
[5, 6, 7]])
X[1:3,col]
out:array([[ 5, 6, 7],
[ 9, 10, 11]])
- numpy.array的比較
x
out:array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
x > 3
out:array([False, False, False, False, True, True, True, True, True,
True, True, True, True, True, True, True])
x < 3
out:array([ True, True, True, False, False, False, False, False, False,
False, False, False, False, False, False, False])
x >= 3
out:array([False, False, False, True, True, True, True, True, True,
True, True, True, True, True, True, True])
x <= 3
out:array([ True, True, True, True, False, False, False, False, False,
False, False, False, False, False, False, False])
x == 3
out:array([False, False, False, True, False, False, False, False, False,
False, False, False, False, False, False, False])
# 更加複雜的
2*x == 24 - 4*x
out:array([False, False, False, False, True, False, False, False, False,
False, False, False, False, False, False, False])
# x中有多少元素 <=3
np.sum(x<=3)
out:4
# x中有多少元素 <=3 的另一種方法
np.count_nonzero(x<=3)
out:4
# x中是否存在0
np.any(x == 0)
out: True
# 值>10 且為 偶數的 元素個數
np.sum((x % 2==0) | (x>10))
out:11