-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrpca.py
More file actions
65 lines (49 loc) · 1.77 KB
/
Copy pathrpca.py
File metadata and controls
65 lines (49 loc) · 1.77 KB
1
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import numpy as np
def shrink(X, tau):
return np.sign(X) * np.maximum(np.abs(X) - tau, 0)
def ialm(D, threshold=1e-3):
"""
Performs low-rank and sparse decomposition of the input matrix D using
the Inexact Augmented Lagrange Multiplier (IALM) method.
The algorithm decomposes D into:
D = A + E
where A is a low-rank matrix and E is a sparse error matrix.
Parameters:
D (np.ndarray): The input data matrix of shape (m, n).
threshold (float): Convergence threshold based on the residual change.
Returns:
A (np.ndarray): The recovered low-rank component.
E (np.ndarray): The recovered sparse error component.
iterations (int): The number of iterations executed.
"""
m, n = D.shape
iterations = 0
Y = np.zeros((m, n))
A = np.zeros((m, n))
E = np.zeros((m, n))
# TODO: Fill this functions
# Important Notes: You can use any functions in numpy to implement svd!
# Recommend you to use frobenius norm in numpy
mu = 1
p = 1.1
mu_max = mu * 1e-7
lam = 1
norm_D = np.linalg.norm(D, 'fro')
for i in range(1000):
iterations += 1
Temp_A = D - E + (1.0 / mu) * Y
U, S, Vt = np.linalg.svd(Temp_A, full_matrices=False)
s_thresholded = np.diag(shrink(S, 1.0/mu))
A_next = (U @ s_thresholded) @ Vt
Temp_E = D - A_next + (1.0 / mu) * Y
E_next = shrink(Temp_E, lam / mu)
R = D - A_next - E_next # residual
Y_next = Y + mu * R
err = np.linalg.norm(R, 'fro') / norm_D
if err < threshold:
# A, E, Y = A_next, E_next, Y_next
break
A, E, Y = A_next, E_next, Y_next
mu = min(p * mu, mu_max)
print(iterations)
return A, E, iterations