příprava
import numpy as np;
import math;
matice pro příklad:
A = np.array([[3, -5, 15, -4],
[7, 7, 9, -1],
[0, 8, -1, 6],
[-10, 7, 8, -10]])
funkce na vytvoření Householderova reflektoru
def make_householder(x,y):
w = (x - y) / np.linalg.norm(x - y);
return (np.identity(len(x)) - 2 * np.dot(w[:,None],w[None,:]))
ukázka použití Householderova reflektoru.
x = A[:,0]
y = np.array([np.linalg.norm(x),0,0,0])
H = make_householder(x,y)
np.dot(H,A)
pro zpřehlednění výsledku, zaokrouhlíme
np.around(np.dot(H,A),2)
pokračujeme pro submatici
A1 = np.transpose(np.dot(H,A))[1:,:]
A1
x = A1[:,0]
y = np.array([np.linalg.norm(x),0,0]);
W1 = make_householder(x,y)
WT = np.pad(W1,((1,0),(1,0)),'constant')
WT[0,0] = 1
WT
np.around(np.dot(np.dot(H,A),WT),2)
uděláme bidiagonalizační proceduru
def bidiagonalize_step(A):
x = A[:,0]
y = np.zeros(np.size(x))
y[0] = np.linalg.norm(x);
H = make_householder(x,y)
return(H)
def bidiagonalize(A):
colnum = np.size(A,1)
H = np.identity(colnum)
W = np.identity(colnum)
for i in range(colnum-1):
xlist = [0]
if (i!=colnum-2): xlist = [0,1]
for col in xlist:
A1 = A
if (col): A1 = np.transpose(A);
A1 = A1[i+col:,i:]
HH = bidiagonalize_step(A1)
HH = np.pad(HH,((i+col,0),(i+col,0)),'constant')
for k in range(i+col):
HH[k,k]=1;
if (col):
W = np.dot(W,HH)
A = np.dot(A,HH)
else:
H = np.dot(HH,H)
A = np.dot(HH,A)
return [np.transpose(H),A,np.transpose(W)]
testneme
[H,B,W] = bidiagonalize(A)
np.around(H,2)
np.around(B,2)
np.around(W,2)
np.around(np.dot(np.dot(H,B),W),2)
A
T = np.dot(B,np.transpose(B))
np.around(T)
Budeme potřebovat QR rozklad tridiagonalní matice
def QRdecomp(T):
siz = np.size(T,0);
Q = np.identity(siz)
for i in range(siz-1):
alpha = math.atan(T[i+1,i]/T[i,i])
rot = np.identity(siz)
s = math.sin(alpha)
c = math.cos(alpha)
rot[i,i] = c
rot[i+1,i+1] = c
rot[i,i+1] = s
rot[i+1,i] = -s
T = np.dot(rot,T)
Q = np.dot(rot,Q)
return([np.transpose(Q),T])
test
[Q,R]=QRdecomp(T)
np.around(Q)
np.around(R)
np.around(np.dot(Q,R))
np.around(np.dot(R,Q))
nyní můžeme vytvořit QR algoritmus
def QR(T):
siz = np.size(T,0);
QQ = np.identity(siz)
for i in range(100):
[Q,R] = QRdecomp(T)
T = np.dot(R,Q)
QQ = np.dot(QQ,Q)
return(QQ,T)
[Q,TT] = QR(T)
np.around(Q)
np.around(TT)
BB = np.dot(np.dot(Q,TT),np.transpose(Q));
np.around(BB)
AA = np.dot(np.dot(H,BB),np.transpose(H));
np.around(AA,4)
np.dot(A,np.transpose(A))
Wilkinsonovův posun
def QR_wilkshift(T):
I = np.identity(np.size(T,0))
n = np.size(T,0);
for i in range(5):
mu=wilkshift(T[n-2:n,n-2:n]);
[Q,R]=QRdecomp(T-mu*I)
T= np.dot(R,Q) +mu*I
print(np.around(T,2))
return(T)
def wilkshift(T):
l,ll = np.linalg.eig(T);
if (abs(l[0]-T[1,1]) < abs(l[1]-T[1,1])):
return(l[0]);
else:
return(l[1]);
QR_wilkshift(T)
Toto není celé, .. Dodělejte za domácí úkol.
U = np.dot(H,Q)
Sigma = np.diag(np.sqrt(np.diag(TT)))
AA
U_Sigma = np.dot(U,Sigma)
np.around(np.dot(U_Sigma,np.transpose(U_Sigma)))
[Q,TT2] = QR(np.dot(np.transpose(B),B))
Q
np.diag(TT2)
V = np.dot(np.transpose(Q),W)
V
np.around(np.dot(U,np.dot(Sigma,V)))
[_U,_Sigma,_V] = np.linalg.svd(A, full_matrices=True)
print(_U)
print(_Sigma)
print(_V)
U
V
my_data = np.genfromtxt('iris.csv', delimiter=',')[:,:-1]
my_data
[_U,_Sigma,_V] = np.linalg.svd(my_data,full_matrices=False)
_Sigma
np.shape(_U)
_Sigma
_Sigma = np.diag(_Sigma[:2])
_Sigma
transformed_data = np.dot(_U[:,0:2],_Sigma)
from matplotlib import pyplot as plt
plt.figure(figsize=(5, 4))
plt.scatter(transformed_data[:,0],transformed_data[:,1])
plt.show()