Skip to content

Commit abdb82d

Browse files
authored
Merge pull request #278 from rossbar/opinionated-svd
2 parents 22ddae9 + 7a5ed80 commit abdb82d

File tree

1 file changed

+7
-18
lines changed

1 file changed

+7
-18
lines changed

content/tutorial-svd.md

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ You can check that the above works by doing some tests; for example, inquiring
111111
about maximum and minimum values for this array:
112112

113113
```{code-cell}
114-
img_array.max(), img_array.min()
114+
img_array.min(), img_array.max()
115115
```
116116

117117
or checking the type of data in the array:
@@ -138,12 +138,6 @@ It is possible to use methods from linear algebra to approximate an existing set
138138

139139
+++
140140

141-
To proceed, import the linear algebra submodule from NumPy:
142-
143-
```{code-cell}
144-
from numpy import linalg
145-
```
146-
147141
In order to extract information from a given matrix, we can use the SVD to obtain 3 arrays which can be multiplied to obtain the original matrix. From the theory of linear algebra, given a matrix $A$, the following product can be computed:
148142

149143
$$U \Sigma V^T = A$$
@@ -179,7 +173,8 @@ plt.show()
179173
Now, applying the [linalg.svd](https://numpy.org/devdocs/reference/generated/numpy.linalg.svd.html#numpy.linalg.svd) function to this matrix, we obtain the following decomposition:
180174

181175
```{code-cell}
182-
U, s, Vt = linalg.svd(img_gray)
176+
import numpy as np
177+
U, s, Vt = np.linalg.svd(img_gray)
183178
```
184179

185180
**Note** If you are using your own image, this command might take a while to run, depending on the size of your image and your hardware. Don't worry, this is normal! The SVD can be a pretty intensive computation.
@@ -202,8 +197,6 @@ s @ Vt
202197
results in a `ValueError`. This happens because having a one-dimensional array for `s`, in this case, is much more economic in practice than building a diagonal matrix with the same data. To reconstruct the original matrix, we can rebuild the diagonal matrix $\Sigma$ with the elements of `s` in its diagonal and with the appropriate dimensions for multiplying: in our case, $\Sigma$ should be 768x1024 since `U` is 768x768 and `Vt` is 1024x1024. In order to add the singular values to the diagonal of `Sigma`, we will use the [fill_diagonal](https://numpy.org/devdocs/reference/generated/numpy.fill_diagonal.html) function from NumPy:
203198

204199
```{code-cell}
205-
import numpy as np
206-
207200
Sigma = np.zeros((U.shape[1], Vt.shape[0]))
208201
np.fill_diagonal(Sigma, s)
209202
```
@@ -217,7 +210,7 @@ Now, we want to check if the reconstructed `U @ Sigma @ Vt` is close to the orig
217210
The [linalg](https://numpy.org/devdocs/reference/routines.linalg.html#module-numpy.linalg) module includes a `norm` function, which computes the norm of a vector or matrix represented in a NumPy array. For example, from the SVD explanation above, we would expect the norm of the difference between `img_gray` and the reconstructed SVD product to be small. As expected, you should see something like
218211

219212
```{code-cell}
220-
linalg.norm(img_gray - U @ Sigma @ Vt)
213+
np.linalg.norm(img_gray - U @ Sigma @ Vt)
221214
```
222215

223216
(The actual result of this operation might be different depending on your architecture and linear algebra setup. Regardless, you should see a small number.)
@@ -276,22 +269,18 @@ img_array.shape
276269
```
277270

278271
so we need to permutate the axis on this array to get a shape like `(3, 768, 1024)`. Fortunately, the [numpy.transpose](https://numpy.org/devdocs/reference/generated/numpy.transpose.html#numpy.transpose) function can do that for us:
279-
```
280-
np.transpose(x, axes=(i, j, k))
281-
```
282-
indicates that the axis will be reordered such that the final shape of the transposed array will be reordered according to the indices `(i, j, k)`.
283-
284-
Let's see how this goes for our array:
285272

286273
```{code-cell}
274+
# The values in the tuple indicate the original dim, and the order the new axis
275+
# so axis 2 -> 0, 0 -> 1, and 1 -> 2
287276
img_array_transposed = np.transpose(img_array, (2, 0, 1))
288277
img_array_transposed.shape
289278
```
290279

291280
Now we are ready to apply the SVD:
292281

293282
```{code-cell}
294-
U, s, Vt = linalg.svd(img_array_transposed)
283+
U, s, Vt = np.linalg.svd(img_array_transposed)
295284
```
296285

297286
Finally, to obtain the full approximated image, we need to reassemble these matrices into the approximation. Now, note that

0 commit comments

Comments
 (0)