-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathproject.py
More file actions
196 lines (157 loc) · 5.48 KB
/
Copy pathproject.py
File metadata and controls
196 lines (157 loc) · 5.48 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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import numpy as np
# =========================================================
# 1. Power method for dominant eigenpair
# =========================================================
def power_method(A, x0, maxit, tol):
"""Approximate the dominant eigenvalue and eigenvector of a real symmetric matrix A.
Parameters
----------
A : (n, n) ndarray
Real symmetric matrix.
x0 : (n,) ndarray
Initial guess for eigenvector (nonzero).
maxit : int
Maximum number of iterations.
tol : float
Tolerance for convergence in relative change of eigenvalue.
Returns
-------
lam : float
Approximate dominant eigenvalue.
v : (n,) ndarray
Approximate unit eigenvector (||v||_2 = 1).
iters : int
Number of iterations performed.
"""
# TODO: implement the power method
raise NotImplementedError("power_method not implemented")
# =========================================================
# 2. Rank-k image compression via SVD
# =========================================================
def svd_compress(image, k):
"""Compute a rank-k approximation of a grayscale image using SVD.
Parameters
----------
image : (m, n) ndarray
Grayscale image matrix.
k : int
Target rank (1 <= k <= min(m, n)).
Returns
-------
image_k : (m, n) ndarray
Rank-k approximation of the image.
rel_error : float
Relative Frobenius error ||image - image_k||_F / ||image||_F.
compression_ratio : float
(Number of stored parameters in image_k) / (m * n).
"""
# TODO: implement SVD-based rank-k approximation
raise NotImplementedError("svd_compress not implemented")
# =========================================================
# 3. SVD-based feature extraction
# =========================================================
def svd_features(image, p):
"""Extract SVD-based features from a grayscale image.
Parameters
----------
image : (m, n) ndarray
Grayscale image matrix.
p : int
Number of leading singular values to use (p <= min(m, n)).
Returns
-------
feat : (p + 2,) ndarray
Feature vector consisting of:
[normalized sigma_1, ..., normalized sigma_p, r_0.9, r_0.95]
"""
# TODO: implement SVD feature extraction
raise NotImplementedError("svd_features not implemented")
# =========================================================
# 4. Two-class LDA: training
# =========================================================
def lda_train(X, y):
"""Train a two-class LDA classifier.
Parameters
----------
X : (N, d) ndarray
Feature matrix (rows = samples, columns = features).
y : (N,) ndarray
Labels, each 0 or 1.
Returns
-------
w : (d,) ndarray
Discriminant direction vector (not necessarily unit length).
threshold : float
Threshold in 1D projected space for classifying 0 vs 1.
"""
# TODO: implement two-class LDA training
raise NotImplementedError("lda_train not implemented")
# =========================================================
# 5. Two-class LDA: prediction
# =========================================================
def lda_predict(X, w, threshold):
"""Predict class labels using a trained LDA classifier.
Parameters
----------
X : (N, d) ndarray
Feature matrix.
w : (d,) ndarray
Discriminant direction (from lda_train).
threshold : float
Threshold (from lda_train).
Returns
-------
y_pred : (N,) ndarray
Predicted labels (0 or 1).
"""
# TODO: implement LDA prediction
raise NotImplementedError("lda_predict not implemented")
# =========================================================
# Simple self-test on the example data
# =========================================================
def _example_run():
"""Run a tiny end-to-end test on the example dataset, if available.
This function is for local testing only and will NOT be called by the autograder.
"""
try:
data = np.load("project_data_example.npz")
except OSError:
print("No example data file 'project_data_example.npz' found.")
return
X_train = data["X_train"]
y_train = data["y_train"]
X_test = data["X_test"]
y_test = data["y_test"]
# Sanity check shapes
print("X_train shape:", X_train.shape)
print("X_test shape:", X_test.shape)
p = min(5, min(X_train.shape[1], X_train.shape[2]))
print(f"Using p = {p} leading singular values for features.")
# Build feature matrices
def build_features(X):
feats = []
for img in X:
feats.append(svd_features(img, p))
return np.vstack(feats)
try:
Xf_train = build_features(X_train)
Xf_test = build_features(X_test)
except NotImplementedError:
print("Implement 'svd_features' first to run this example.")
return
print("Feature dimension:", Xf_train.shape[1])
try:
w, threshold = lda_train(Xf_train, y_train)
except NotImplementedError:
print("Implement 'lda_train' first to run this example.")
return
try:
y_pred = lda_predict(Xf_test, w, threshold)
except NotImplementedError:
print("Implement 'lda_predict' first to run this example.")
return
accuracy = np.mean(y_pred == y_test)
print(f"Example test accuracy: {accuracy:.3f}")
if __name__ == "__main__":
# This allows students to run a quick local smoke test.
_example_run()