灰太狼的數據世界(四)
- 2019 年 10 月 6 日
- 筆記

Scipy是
一個專門用於科學計算的庫
它與Numpy有著密切的關係
Numpy是Scipy的基礎
Scipy通過Numpy數據來進行科學計算
包含
統計
優化
整合
以及線性代數模組
傅里葉變換
訊號和影像圖例
常微分方差的求解等
給個表給你參考下?

怎麼樣?
是不是看上去就有一股很騷氣的味道?
那咱就繼續學下去唄!
首先
安裝
個人推薦pip直接全家桶
pip install -U numpy scipy scikit-learn

當然也有人推薦
Anaconda
因為用了它
一套環境全搞定
媽媽再也不用擔心我安裝問題了~
安裝完之後就是直接使用了
首先我們來談談
(這些函數其實都是numpy裡面的
它們也可以被scipy對象使用)
unique函數
之前在numpy裡面有說過
主要是用來除去重複元素
同樣的,這個方法適用numpy
也適用於sm這樣的一個對象
(類似於python裡面的set)
import numpy as np import scipy.misc as sm x = np.array([1, 3, 2, 1, 4, 2]) print(np.unique(x), "# unique(x)")
face = sm.face() print(np.unique(face), "# unique(face)")
bincount函數
統計出數組裡的從0到數組最大值n
共n+1個自然數出現的次數
具體做法
先找出數組裡的最大值
統計0~最大值間的所有值出現的次數
import numpy as np import scipy.misc as sm ascent = sm.ascent() print("max of array {} has {}" .format(np.max(ascent[0]), len(ascent[0]))) b = np.bincount(ascent[0]) print("return array's length {}" .format(len(b))) print("result {}".format(b))
fromfunctiont函數
類似於python裡面的map函數
利用傳入的函數生成一個數組
import numpy as np def func(x, y): return (x + y) * 3 t = np.fromfunction(func, (3, 4), dtype=np.uint8)print("t = {}".format(t))
除了上面這幾個
還有下面幾個函數
put函數
替換數組裡面的值
putmask函數
和put一樣,也是替換
………
剛剛說的這些
還是停留在Numpy的基礎上
都是Numpy自己的函數
下面我們來說點有用的
看看Scipy自己的函數吧~
Scipy有一些專門的類
可以用來創建
稀疏矩陣
coo_matrix
csc_matrix
csr_matrix
bsr_matrix
我們來瞧一個栗子
import numpy as np import scipy.sparse as ss a = np.zeros((3, 4)) a[1, 2] = 12 a[2, 2] = 22 print(a) print(ss.csc_matrix(a))我們可以在創建的ndarry裡面找出不為零的值和他的位置,將這個數組直接轉化成稀疏矩陣
我們還可以利用
mat函數/bmat函數
來創建特殊的矩陣
np.mat函數可將數組轉為矩陣
np.bmat函數可以矩陣為參數創建陣列的矩陣
import numpy as np a = np.mat(np.ones([3, 3])) b = np.mat(np.zeros([3,3])) print("a = {}".format(a)) print("b = {}".format(b)) c = np.bmat("a,b;b,a") print("c = {}".format(c))

Tile函數
將第一個參數映射到第二個參數
import numpy as np t = np.arange(9).reshape([3, 3]) print(t) tm = np.tile(t, [3,2]) print(tm)

將t映射到【3,2】上
block_diag函數
block_diag函數可以創建一個
廣義「主對角線」非0的大矩陣
其參數是矩陣
用矩陣作為主對角線性的值
所以矩陣會很大~
import numpy as np import scipy.linalg as sl a = np.mat(np.ones([3, 3])) b = np.mat(np.ones([4, 3])) c = np.mat(np.ones([3, 4])) print("a = {}".format(a)) print("b = {}".format(b)) print("c = {}".format(c)) d = sl.block_diag(a,b,c) print("d = {}".format(d))


除了創建矩陣
scipy當然還有更多有趣的地方
例如
對線性方程組求解
具體怎麼算的我也就不瞎說了
圖能看懂就看
高數沒學好的
推薦一個重新學的網址:
https://baike.baidu.com/item/lu%E5%88%86%E8%A7%A3/764245?fr=aladdin
我們有各種方法進行求解
例如:
LU分解
QR分解
SVD分解
Cholesky分解
先來了解一下LU分解~


將LU分解轉化成Scipy程式碼
SciPy里的
scipy.linalg.lu函數可以基本實現對Ax=b的LU分解
但scipy.linalg.lu函數的返回值有三個p'、l'、u'
所以矩陣分解變為(P'L')U' = A
from scipy.linalg import lu import numpy as np A = np.matrix([[2,3],[5,4]]) b = np.matrix([4,3]) p,l,u = lu(A) print("p = {}".format(p)) print("l = {}".format(l)) print("u = {}".format(u)) print("plu = {}".format(p.dot(l).dot(u))) print("A = {}".format(A))

下面我們可以利用
LU分解求方程組的解
分解過後的方程如下:

對應的結果也就是A

之後我們
求p、l、u
然後用pl和b求y
用u和y求x的值
from scipy.linalg import lu,solve import numpy as np A = np.array([[2,3],[5,4]]) b = np.array([4,3]) # 求的p l u p,l,u = lu(A) print("p = {}".format(p)) print("l = {}".format(l)) print("u = {}".format(u)) # 求ply = b的y y = solve(p.dot(l), b) print("y = {}".format(y)) # 求ux = y的x x = solve(u, y) print("x = {}".format(x))

結果最後一行輸出的是x的值,
即
x=(x1,x2)=(−1,2)
Cholesky分解
要求解線性方程組Ax=b
其中為對稱正定矩陣
又叫平方根法
是求解對稱線性方程組常用的方法之一
那麼可通過下面步驟求解
(1)求的Cholesky分解,得到A=LLT
(2)求解Ly=b,得到y
(3)求解LTx=y,得到x
下面使用
scipy.linalg模組下的cholesky函數
來對係數矩陣進行求cholesky分解
from scipy.linalg import cholesky import numpy as np from scipy.linalg import lu,solve A = np.array([[1,2,3],[2,8,8],[3,8,35]]) b = np.array([1,8,20]) l = cholesky(A, lower=True) print("L = {}".format(l)) print("matmul = {}".format(np.matmul(l,l.T))) print("dot = {}".format(l.dot(l.T))) y = solve(l, b) print(l.dot(y), b) x = solve(l.T, y) print("x = {}".format(x)) print(l.T.dot(x), y) print("y = {}".format(y))

QR分解
QR分解法是三種將矩陣分解的方式之一
它把矩陣分解成:
一個正交矩陣與一個上三角矩陣的積
QR分解經常用來解線性最小二乘法問題
scipy.linalg模組下的qr函數
可以對矩陣進行QR分解操作
from scipy.linalg import qr import numpy as np aa = np.array([[0,3,1],[0,4,-2],[2,1,2]]) qq, rr = qr(aa) print("Q = {}".format(qq)) print("R = {}".format(rr)) print("A = {}".format(aa)) print("QR = {}".format(qq.dot(rr)))

SVD奇異分解
svd是現在比較常見的演算法之一
也是數據挖掘工程師、演算法工程師
必備的技能之一
假設A是一個M×N的矩陣,
那麼通過矩陣分解將會得到
U,Σ,VT(V的轉置)三個矩陣
其中U是一個M×M的方陣
被稱為左奇異向量
方陣裡面的向量是正交的
Σ是一個M×N的對角矩陣
除了對角線的元素其他都是0
對角線上的值稱為奇異值
VT(V的轉置)是一個N×N的矩陣
被稱為右奇異向量
方陣裡面的向量也都是正交的

from scipy.linalg import qr,svd import numpy as np aa = np.array([[0,3,1],[0,4,-2],[2,1,2]]) u, e, v = svd(aa) print("u = {}".format(u)) print("e = {}".format(e)) print("v = {}".format(v))

SVD的應用場景也比較明顯
典型的使用的場景:
訊號的降噪
影像的壓縮
我們這邊可以來看一個影像壓縮的例子:
import scipy.misc from scipy.linalg import svd import matplotlib.pyplot as plt import numpy as np import numpy img = scipy.misc.face()[:,:,0] print(img.shape,type(img)) img = np.matrix(img) U,s,Vh=svd(img) plt.gray() plt.subplot(221,aspect='equal') plt.title("orignal") plt.imshow(img) plt.imsave('org.png', img) A = numpy.dot(U[:,0:10],numpy.dot(numpy.diag(s[0:10]),Vh[0:10,:])) plt.subplot(222,aspect='equal') plt.title(":10") plt.imshow(A) plt.imsave('a10.png', A) A = numpy.dot(U[:,0:50],numpy.dot(numpy.diag(s[0:50]),Vh[0:50,:])) plt.subplot(223,aspect='equal') plt.title(":50") plt.imshow(A) plt.imsave('a50.png', A) A = numpy.dot(U[:,0:100],numpy.dot(numpy.diag(s[0:100]),Vh[0:100,:])) plt.subplot(224,aspect='equal') plt.title(":100") plt.imshow(A) plt.imsave('a100.png', A) plt.show()
壓縮原理如下:

總結
svd分解在
機器學習
深度學習
電腦視覺等領域
都有很多涉及
需明白基礎不牢靠
學習機器學習也就是浮於表面
這一期關於scipy使用的內容就到這裡了(主要是講的如何去使用scipy,但是具體的數學理論沒有特別去講,覺得以後有必要搞一期,談談線性代數,畢竟矩陣這個東西我們現在很常用)
下一期我們將接觸:
Scipy裡面的
范德蒙多項式逼近
最鄰近插值法
拉格朗日插值法
埃米爾特插值法
樣條插值
函數的求導和積分
