Biến đổi (phân rã) ma trận
Các biến đổi ma trận là những phép toán được sử dụng phổ biến nhất khi làm việc với dữ liệu. Tuy nhiên, nhiều biến đổi phức tạp không thể được thực hiện một cách phân tích và với độ chính xác tuyệt đối.
Biến đổi ma trận (hay nói cách khác, phân rã) là các phương pháp phân tách một ma trận thành các thành phần cấu thành của nó, giúp đơn giản hóa việc tính toán các phép toán ma trận phức tạp hơn. Các phương pháp phân rã ma trận, còn được gọi là phương pháp phân tích nhân tử ma trận, là cơ sở của các thuật toán đại số tuyến tính, chẳng hạn như giải hệ phương trình tuyến tính và tính nghịch đảo của ma trận hoặc định thức.
Đặc biệt, Phân rã giá trị đơn (SVD) được sử dụng rộng rãi trong học máy, cho phép biểu diễn ma trận ban đầu dưới dạng tích của ba ma trận khác. Phân rã SVD được sử dụng để giải quyết nhiều vấn đề khác nhau, từ xấp xỉ bình phương nhỏ nhất đến nén dữ liệu và nhận diện hình ảnh.
Danh sách các phương thức có sẵn:
Cholesky
: tính phân rã CholeskyEig
: tính giá trị riêng và vector riêng bên phải của một ma trận vuôngEig Vals
: tính giá trị riêng của ma trận thông thườngLU
: thực hiện phân rã LU của ma trận dưới dạng tích của một ma trận tam giác dưới và một ma trận tam giác trênLUP
: thực hiện phân rã LUP với xoay một phần, là một phân rã LU chỉ với hoán vị hàng: PA=LUQR
: thực hiện phân rã QR của ma trậnSVD
: phân rã giá trị đơn
Dưới đây là các nguyên mẫu phương thức.
bool matrix<T>::Cholesky(matrix<T> &L)
bool matrix<T>::Eig(matrix<T> &eigen_vectors, vector<T> &eigen_values)
bool matrix<T>::EigVals(vector<T> &eigen_values)
bool matrix<T>::LU(matrix<T> &L, matrix<T> &U)
bool matrix<T>::LUP(matrix<T> &L, matrix<T> &U, matrix<T> &P)
bool matrix<T>::QR(matrix<T> &Q, matrix<T> &R)
bool matrix<T>::SVD(matrix<T> &U, matrix<T> &V, vector<T> &singular_values)
Hãy trình bày một ví dụ về phân rã giá trị đơn bằng phương thức SVD (xem tệp MatrixSVD.mq5
). Đầu tiên, chúng ta khởi tạo ma trận ban đầu.
matrix a = {{0, 1, 2, 3, 4, 5, 6, 7, 8}};
a = a - 4;
a.Reshape(3, 3);
Print("matrix a \n", a);
2
3
4
Bây giờ, hãy thực hiện phân rã SVD:
matrix U, V;
vector singular_values;
a.SVD(U, V, singular_values);
Print("U \n", U);
Print("V \n", V);
Print("singular_values = ", singular_values);
2
3
4
5
6
Hãy kiểm tra sự mở rộng: đẳng thức sau phải đúng: U * "singular diagonal" * V = A
.
matrix matrix_s;
matrix_s.Diag(singular_values);
Print("matrix_s \n", matrix_s);
matrix matrix_vt = V.Transpose();
Print("matrix_vt \n", matrix_vt);
matrix matrix_usvt = (U.MatMul(matrix_s)).MatMul(matrix_vt);
Print("matrix_usvt \n", matrix_usvt);
2
3
4
5
6
7
Hãy so sánh ma trận kết quả và ma trận ban đầu để tìm lỗi.
ulong errors = (int)a.Compare(matrix_usvt, 1e-9);
Print("errors=", errors);
2
Nhật ký sẽ trông như sau:
matrix a
[[-4,-3,-2]
[-1,0,1]
[2,3,4]]
U
[[-0.7071067811865474,0.5773502691896254,0.408248290463863]
[-6.827109697437648e-17,0.5773502691896253,-0.8164965809277256]
[0.7071067811865472,0.5773502691896255,0.4082482904638627]]
V
[[0.5773502691896258,-0.7071067811865474,-0.408248290463863]
[0.5773502691896258,1.779939029415334e-16,0.8164965809277258]
[0.5773502691896256,0.7071067811865474,-0.408248290463863]]
singular_values = [7.348469228349533,2.449489742783175,3.277709923350408e-17]
matrix_s
[[7.348469228349533,0,0]
[0,2.449489742783175,0]
[0,0,3.277709923350408e-17]]
matrix_vt
[[0.5773502691896258,0.5773502691896258,0.5773502691896256]
[-0.7071067811865474,1.779939029415334e-16,0.7071067811865474]
[-0.408248290463863,0.8164965809277258,-0.408248290463863]]
matrix_usvt
[[-3.999999999999997,-2.999999999999999,-2]
[-0.9999999999999981,-5.977974170712231e-17,0.9999999999999974]
[2,2.999999999999999,3.999999999999996]]
errors=0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Một trường hợp thực tế khác của việc áp dụng phương thức Convolve
được bao gồm trong ví dụ trong Phương pháp học máy.