-
-
Notifications
You must be signed in to change notification settings - Fork 220
Expand file tree
/
Copy pathindex.html
More file actions
101 lines (94 loc) · 282 KB
/
index.html
File metadata and controls
101 lines (94 loc) · 282 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
<!DOCTYPE html><html lang="en" class="" style="scroll-padding:60px"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Linear algebra on n-dimensional arrays - Numpy Tutorials</title><meta property="og:title" content="Linear algebra on n-dimensional arrays - Numpy Tutorials"/><meta name="generator" content="mystmd"/><meta name="keywords" content=""/><meta name="image" content="/numpy-tutorials/build/b77199e99a54e59b2e3c037c2cc90f21.svg"/><meta property="og:image" content="/numpy-tutorials/build/b77199e99a54e59b2e3c037c2cc90f21.svg"/><link rel="stylesheet" href="/numpy-tutorials/build/_assets/app-MOQGDXHO.css"/><link rel="stylesheet" href="/numpy-tutorials/build/_assets/thebe-core-VKVHG5VY.css"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jupyter-matplotlib@0.11.3/css/mpl_widget.css"/><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous"/><link rel="icon" href="/numpy-tutorials/favicon.ico"/><link rel="stylesheet" href="/numpy-tutorials/myst-theme.css"/><script>
const savedTheme = localStorage.getItem("myst:theme");
const theme = window.matchMedia("(prefers-color-scheme: light)").matches ? 'light' : 'dark';
const classes = document.documentElement.classList;
const hasAnyTheme = classes.contains('light') || classes.contains('dark');
if (!hasAnyTheme) classes.add(savedTheme ?? theme);
</script></head><body class="m-0 transition-colors duration-500 bg-white dark:bg-stone-900"><div class="myst-skip-to-article fixed top-1 left-1 h-[0px] w-[0px] focus-within:z-40 focus-within:h-auto focus-within:w-auto bg-white overflow-hidden focus-within:p-2 focus-within:ring-1" aria-label="skip to content options"><a href="#skip-to-frontmatter" class="myst-skip-to-link block px-2 py-1 text-black underline">Skip to article frontmatter</a><a href="#skip-to-article" class="myst-skip-to-link block px-2 py-1 text-black underline">Skip to article content</a></div><dialog id="myst-no-css" style="position:fixed;left:0px;top:0px;width:100vw;height:100vh;font-size:4rem;padding:1rem;color:black;background:white"><strong>Site not loading correctly?</strong><p>This may be due to an incorrect <code>BASE_URL</code> configuration. See<!-- --> <a href="https://mystmd.org/guide/deployment#deploy-base-url">the MyST Documentation</a> <!-- -->for reference.</p><script>
(() => {
// Test for has-styling variable set by the MyST stylesheet
const node = document.currentScript.parentNode;
const hasCSS = window.getComputedStyle(node).getPropertyValue("--has-styling");
if (hasCSS === ""){
node.showModal();
}
})()
</script></dialog><div class="myst-top-nav bg-white/80 backdrop-blur dark:bg-stone-900/80 shadow dark:shadow-stone-700 p-3 md:px-8 sticky w-screen top-0 z-30 h-[60px]"><nav class="myst-top-nav-bar flex items-center justify-between flex-nowrap max-w-[1440px] mx-auto"><div class="flex flex-row xl:min-w-[19.5rem] mr-2 sm:mr-7 justify-start items-center shrink-0"><div class="block xl:hidden"><button class="myst-top-nav-menu-button flex items-center justify-center border-stone-400 text-stone-800 hover:text-stone-900 dark:text-stone-200 hover:dark:text-stone-100 w-10 h-10"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" width="1.5rem" height="1.5rem"><path fill-rule="evenodd" d="M3 6.75A.75.75 0 0 1 3.75 6h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 6.75ZM3 12a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 12Zm0 5.25a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75a.75.75 0 0 1-.75-.75Z" clip-rule="evenodd"></path></svg><span class="sr-only">Open Menu</span></button></div><a class="myst-home-link flex items-center ml-3 dark:text-white w-fit md:ml-5 xl:ml-7" href="/numpy-tutorials/"><div class="myst-home-link-logo mr-3 flex items-center dark:bg-white dark:rounded px-1"><img src="/numpy-tutorials/build/numpylogo-28b47a276e91aa58e8056b86c12e6958.svg" class="h-9" height="2.25rem"/></div><span class="text-md sm:text-xl tracking-tight sm:mr-5 sr-only">Made with MyST</span></a></div><div class="flex items-center flex-grow w-auto"><div class="flex-grow hidden text-md lg:block"></div><div class="flex-grow block"></div><button type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-:R75cp:" data-state="closed" class="myst-search-bar flex items-center h-10 aspect-square sm:w-64 text-left text-gray-600 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 myst-search-bar-disabled hover:ring-blue-500 dark:hover:ring-blue-500 hover:border-blue-500 dark:hover:border-blue-500"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" class="p-2.5 h-10 w-10 aspect-square"><path fill-rule="evenodd" d="M10.5 3.75a6.75 6.75 0 1 0 0 13.5 6.75 6.75 0 0 0 0-13.5ZM2.25 10.5a8.25 8.25 0 1 1 14.59 5.28l4.69 4.69a.75.75 0 1 1-1.06 1.06l-4.69-4.69A8.25 8.25 0 0 1 2.25 10.5Z" clip-rule="evenodd"></path></svg><span class="myst-search-text-placeholder hidden sm:block grow">Search</span><div aria-hidden="true" class="myst-search-shortcut items-center hidden mx-1 font-mono text-sm text-gray-600 dark:text-gray-300 sm:flex gap-x-1"><kbd class="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded-md shadow-[0px_2px_0px_0px_rgba(0,0,0,0.08)] dark:shadow-none hide-mac">CTRL</kbd><kbd class="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded-md shadow-[0px_2px_0px_0px_rgba(0,0,0,0.08)] dark:shadow-none show-mac">⌘</kbd><kbd class="px-2 py-1 border border-gray-300 dark:border-gray-600 rounded-md shadow-[0px_2px_0px_0px_rgba(0,0,0,0.08)] dark:shadow-none ">K</kbd><script>
;(() => {
const script = document.currentScript;
const root = script.parentElement;
const isMac = /mac/i.test(
window.navigator.userAgentData?.platform ?? window.navigator.userAgent,
);
root.querySelectorAll(".hide-mac").forEach(node => {node.classList.add(isMac ? "hidden" : "block")});
root.querySelectorAll(".show-mac").forEach(node => {node.classList.add(!isMac ? "hidden" : "block")});
})()</script></div></button><button class="myst-theme-button theme rounded-full aspect-square border border-stone-700 dark:border-white hover:bg-neutral-100 border-solid overflow-hidden text-stone-700 dark:text-white hover:text-stone-500 dark:hover:text-neutral-800 w-10 h-10 mx-3" title="Toggle theme between light and dark mode" aria-label="Toggle theme between light and dark mode"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" class="myst-theme-moon-icon h-full w-full p-0.5 hidden dark:block"><path fill-rule="evenodd" d="M9.528 1.718a.75.75 0 0 1 .162.819A8.97 8.97 0 0 0 9 6a9 9 0 0 0 9 9 8.97 8.97 0 0 0 3.463-.69.75.75 0 0 1 .981.98 10.503 10.503 0 0 1-9.694 6.46c-5.799 0-10.5-4.7-10.5-10.5 0-4.368 2.667-8.112 6.46-9.694a.75.75 0 0 1 .818.162Z" clip-rule="evenodd"></path></svg><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="myst-theme-sun-icon h-full w-full p-0.5 dark:hidden"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"></path></svg></button><div class="block sm:hidden"></div><div class="hidden sm:block"></div></div></nav></div><div class="myst-primary-sidebar fixed xl:article-grid grid-gap xl:w-screen xl:pointer-events-none overflow-auto max-xl:min-w-[300px] hidden z-10" style="top:60px"><div class="myst-primary-sidebar-pointer pointer-events-auto xl:col-margin-left flex-col overflow-hidden hidden xl:flex"><div class="myst-primary-sidebar-nav flex-grow py-6 overflow-y-auto primary-scrollbar"><nav aria-label="Navigation" class="myst-primary-sidebar-topnav overflow-y-hidden transition-opacity ml-3 xl:ml-0 mr-3 max-w-[350px] lg:hidden"><div class="w-full px-1 dark:text-white font-medium"></div></nav><div class="my-3 border-b-2 lg:hidden"></div><nav aria-label="Table of Contents" class="myst-primary-sidebar-toc flex-grow overflow-y-hidden transition-opacity ml-3 xl:ml-0 mr-3 max-w-[350px]"><div class="myst-toc w-full px-1 dark:text-white"><a title="Numpy Tutorials" class="block break-words focus:outline outline-blue-200 outline-2 rounded myst-toc-item p-2 my-1 rounded-lg hover:bg-slate-300/30 font-bold" href="/numpy-tutorials/">Numpy Tutorials</a><div data-state="closed" class="w-full"><div class="myst-toc-item flex flex-row w-full gap-2 pl-2 my-1 text-left rounded-lg outline-none hover:bg-slate-300/30"><div title="Applications" class="block break-words rounded py-2 grow cursor-pointer">Applications</div><button class="self-stretch flex items-center flex-none px-1 rounded-l-md group hover:bg-slate-300/30 focus-visible:outline outline-blue-200 outline-2" aria-label="Open Folder" type="button" aria-controls="radix-:Rmpsp:" aria-expanded="false" data-state="closed"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" class="transition-transform duration-300 group-data-[state=open]:rotate-90 text-text-slate-700 dark:text-slate-100" height="1.5rem" width="1.5rem"><path fill-rule="evenodd" d="M16.28 11.47a.75.75 0 0 1 0 1.06l-7.5 7.5a.75.75 0 0 1-1.06-1.06L14.69 12 7.72 5.03a.75.75 0 0 1 1.06-1.06l7.5 7.5Z" clip-rule="evenodd"></path></svg></button></div><div data-state="closed" id="radix-:Rmpsp:" hidden="" class="pl-3 pr-[2px] collapsible-content"></div></div><div data-state="closed" class="w-full"><div class="myst-toc-item flex flex-row w-full gap-2 pl-2 my-1 text-left rounded-lg outline-none hover:bg-slate-300/30"><div title="Features" class="block break-words rounded py-2 grow cursor-pointer">Features</div><button class="self-stretch flex items-center flex-none px-1 rounded-l-md group hover:bg-slate-300/30 focus-visible:outline outline-blue-200 outline-2" aria-label="Open Folder" type="button" aria-controls="radix-:Rupsp:" aria-expanded="false" data-state="closed"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" class="transition-transform duration-300 group-data-[state=open]:rotate-90 text-text-slate-700 dark:text-slate-100" height="1.5rem" width="1.5rem"><path fill-rule="evenodd" d="M16.28 11.47a.75.75 0 0 1 0 1.06l-7.5 7.5a.75.75 0 0 1-1.06-1.06L14.69 12 7.72 5.03a.75.75 0 0 1 1.06-1.06l7.5 7.5Z" clip-rule="evenodd"></path></svg></button></div><div data-state="closed" id="radix-:Rupsp:" hidden="" class="pl-3 pr-[2px] collapsible-content"></div></div><div data-state="closed" class="w-full"><div class="myst-toc-item flex flex-row w-full gap-2 pl-2 my-1 text-left rounded-lg outline-none hover:bg-slate-300/30"><a title="Contributing" class="block break-words focus:outline outline-blue-200 outline-2 rounded py-2 grow" href="/numpy-tutorials/contributing">Contributing</a><button class="self-stretch flex items-center flex-none px-1 rounded-l-md group hover:bg-slate-300/30 focus-visible:outline outline-blue-200 outline-2" aria-label="Open Folder" type="button" aria-controls="radix-:R16psp:" aria-expanded="false" data-state="closed"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon" class="transition-transform duration-300 group-data-[state=open]:rotate-90 text-text-slate-700 dark:text-slate-100" height="1.5rem" width="1.5rem"><path fill-rule="evenodd" d="M16.28 11.47a.75.75 0 0 1 0 1.06l-7.5 7.5a.75.75 0 0 1-1.06-1.06L14.69 12 7.72 5.03a.75.75 0 0 1 1.06-1.06l7.5 7.5Z" clip-rule="evenodd"></path></svg></button></div><div data-state="closed" id="radix-:R16psp:" hidden="" class="pl-3 pr-[2px] collapsible-content"></div></div></div></nav></div><div class="myst-primary-sidebar-footer flex-none py-6 transition-all duration-700 translate-y-6 opacity-0"><a class="myst-made-with-myst flex mx-auto text-gray-700 w-fit hover:text-blue-700 dark:text-gray-200 dark:hover:text-blue-400" href="https://mystmd.org/made-with-myst" target="_blank" rel="noreferrer"><svg style="width:24px;height:24px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" stroke="none"><g id="icon"><path fill="currentColor" d="M23.8,54.8v-3.6l4.7-0.8V17.5l-4.7-0.8V13H36l13.4,31.7h0.2l13-31.7h12.6v3.6l-4.7,0.8v32.9l4.7,0.8v3.6h-15
v-3.6l4.9-0.8V20.8H65L51.4,53.3h-3.8l-14-32.5h-0.1l0.2,17.4v12.1l5,0.8v3.6H23.8z"></path><path fill="#F37726" d="M47,86.9c0-5.9-3.4-8.8-10.1-8.8h-8.4c-5.2,0-9.4-1.3-12.5-3.8c-3.1-2.5-5.4-6.2-6.8-11l4.8-1.6
c1.8,5.6,6.4,8.6,13.8,8.8h9.2c6.4,0,10.8,2.5,13.1,7.5c2.3-5,6.7-7.5,13.1-7.5h8.4c7.8,0,12.7-2.9,14.6-8.7l4.8,1.6
c-1.4,4.9-3.6,8.6-6.8,11.1c-3.1,2.5-7.3,3.7-12.4,3.8H63c-6.7,0-10,2.9-10,8.8"></path></g></svg><span class="self-center ml-2 text-sm">Made with MyST</span></a></div></div></div><main class="article-grid grid-gap"><article class="article-grid subgrid-gap col-screen article content"><div class="hidden"></div><div id="skip-to-frontmatter" aria-label="article frontmatter" class="myst-fm-block mb-8 pt-9"><div class="myst-fm-block-header flex items-center mb-5 h-6 text-sm font-light"><div class="flex-grow"></div><div class="myst-fm-block-badges"><a href="https://github.com/numpy/numpy-tutorials" title="GitHub Repository: numpy/numpy-tutorials" target="_blank" rel="noopener noreferrer" class="myst-fm-github-link text-inherit hover:text-inherit"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" width="1.25rem" height="1.25rem" class="myst-fm-github-icon inline-block mr-1 opacity-60 hover:opacity-100"><path d="M12 2.5c-5.4 0-9.8 4.4-9.8 9.7 0 4.3 2.8 8 6.7 9.2.5.1.7-.2.7-.5v-1.8c-2.4.5-3.1-.6-3.3-1.1-.1-.3-.6-1.1-1-1.4-.3-.2-.8-.6 0-.6s1.3.7 1.5 1c.9 1.5 2.3 1.1 2.8.8.1-.6.3-1.1.6-1.3-2.2-.2-4.4-1.1-4.4-4.8 0-1.1.4-1.9 1-2.6-.1-.2-.4-1.2.1-2.6 0 0 .8-.3 2.7 1 .8-.2 1.6-.3 2.4-.3.8 0 1.7.1 2.4.3 1.9-1.3 2.7-1 2.7-1 .5 1.3.2 2.3.1 2.6.6.7 1 1.5 1 2.6 0 3.7-2.3 4.6-4.4 4.8.4.3.7.9.7 1.8V21c0 .3.2.6.7.5 3.9-1.3 6.6-4.9 6.6-9.2 0-5.4-4.4-9.8-9.8-9.8z"></path></svg></a></div><a href="https://github.com/numpy/numpy-tutorials/edit/main/content/tutorial-svd.md" title="Edit This Page" target="_blank" rel="noopener noreferrer" class="myst-fm-edit-link text-inherit hover:text-inherit"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="1.25rem" height="1.25rem" class="myst-fm-edit-icon inline-block mr-1 opacity-60 hover:opacity-100"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10"></path></svg></a><div class="myst-fm-downloads-dropdown relative flex inline-block mx-1 grow-0" data-headlessui-state=""><button class="myst-fm-downloads-button relative ml-2 -mr-1" id="headlessui-menu-button-:Rs8ucp:" type="button" aria-haspopup="menu" aria-expanded="false" data-headlessui-state=""><span class="sr-only">Downloads</span><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="1.25rem" height="1.25rem" class="myst-fm-downloads-icon"><title>Download</title><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"></path></svg></button></div></div><h1 class="myst-fm-block-title mb-0">Linear algebra on n-dimensional arrays</h1><header class="myst-fm-authors-affiliations mt-4 not-prose"><div class="myst-fm-authors-list"><span class="myst-fm-author font-semibold text-sm myst-fm-author-item inline-block"><button class="myst-fm-author-popover focus:shadow-[0_0_0_2px] focus:shadow-black outline-none hover:underline" aria-label="Author Details" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="radix-:R78ucp:" data-state="closed"><span class="myst-fm-author-name">Numpy Community</span></button></span></div></header></div><div class="block my-10 lg:sticky lg:z-10 lg:h-0 lg:pt-0 lg:my-0 lg:ml-10 lg:col-margin-right" style="top:60px"><nav></nav></div><div id="skip-to-article"></div><h2 id="prerequisites" class="relative group"><span class="heading-text">Prerequisites</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#prerequisites" title="Link to this Section" aria-label="Link to this Section">¶</a></h2><p>Before reading this tutorial, you should know a bit of Python. If you would like to refresh your memory, take a look at the <a target="_blank" rel="noreferrer" href="https://docs.python.org/3/tutorial/" class="link">Python tutorial<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>.</p><p>If you want to be able to run the examples in this tutorial, you should also have <a target="_blank" rel="noreferrer" href="https://matplotlib.org/" class="link">matplotlib<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> and <a target="_blank" rel="noreferrer" href="https://scipy.org" class="link">SciPy<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> installed on your computer.</p><h2 id="learner-profile" class="relative group"><span class="heading-text">Learner profile</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#learner-profile" title="Link to this Section" aria-label="Link to this Section">¶</a></h2><p>This tutorial is for people who have a basic understanding of linear algebra and arrays in NumPy and want to understand how n-dimensional (<span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>></mo><mo>=</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">n>=2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">>=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span></span></span></span></span>) arrays are represented and can be manipulated. In particular, if you don’t know how to apply common functions to n-dimensional arrays (without using for-loops), or if you want to understand axis and shape properties for n-dimensional arrays, this tutorial might be of help.</p><h2 id="learning-objectives" class="relative group"><span class="heading-text">Learning Objectives</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#learning-objectives" title="Link to this Section" aria-label="Link to this Section">¶</a></h2><p>After this tutorial, you should be able to:</p><ul><li><p>Understand the difference between one-, two- and n-dimensional arrays in NumPy;</p></li><li><p>Understand how to apply some linear algebra operations to n-dimensional arrays without using for-loops;</p></li><li><p>Understand axis and shape properties for n-dimensional arrays.</p></li></ul><h2 id="content" class="relative group"><span class="heading-text">Content</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#content" title="Link to this Section" aria-label="Link to this Section">¶</a></h2><p>In this tutorial, we will use a <a href="https://en.wikipedia.org/wiki/Matrix_decomposition" class="hover-link" target="_blank" rel="noreferrer" data-state="closed">matrix decomposition</a> from linear algebra, the Singular Value Decomposition, to generate a compressed approximation of an image. We’ll use the <code>face</code> image from the <a target="_blank" rel="noreferrer" href="https://docs.scipy.org/doc/scipy/reference/datasets.html" class="link">scipy.datasets<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> module:</p><div id="AvwxUSMzcT" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">from scipy.datasets import face
img = face()</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="e5rgfo4tZ4K3SGosfJyym" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-stream"><div><pre class="myst-jp-stream-output text-sm font-thin font-system"><code><span>Downloading file 'face.dat' from 'https://raw.githubusercontent.com/scipy/dataset-face/main/face.dat' to '/home/runner/.cache/scipy-data'.
</span></code></pre></div></div></div></div><aside class="myst-admonition myst-admonition-note my-5 shadow-md dark:shadow-2xl dark:shadow-neutral-900 bg-gray-50/10 dark:bg-stone-800 overflow-hidden myst-admonition-default rounded border-l-4 border-blue-500"><div class="myst-admonition-header m-0 font-medium py-1 flex min-w-0 text-lg text-blue-600 bg-blue-50 dark:bg-slate-900"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="2rem" height="2rem" class="myst-admonition-header-icon inline-block pl-2 mr-2 self-center flex-none text-blue-600"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"></path></svg><div class="myst-admonition-header-text text-neutral-900 dark:text-white grow self-center overflow-hidden break-words">Note</div></div><div class="myst-admonition-body px-4 py-1"><p>If you prefer, you can use your own image as you work through this tutorial.
In order to transform your image into a NumPy array that can be manipulated, you
can use the <code>imread</code> function from the
<a target="_blank" rel="noreferrer" href="https://matplotlib.org/api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot" class="link">matplotlib.pyplot<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> submodule.
Alternatively, you can use the
<a target="_blank" rel="noreferrer" href="https://imageio.readthedocs.io/en/stable/_autosummary/imageio.v3.imread.html" class="link">imageio.imread<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>
function from the <code>imageio</code> library.
Be aware that if you use your own image, you’ll likely need to adapt the steps below.
For more information on how images are treated when converted to NumPy arrays,
see <a target="_blank" rel="noreferrer" href="https://scikit-image.org/docs/stable/user_guide/numpy_images.html" class="link">A crash course on NumPy for images<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> from the <code>scikit-image</code> documentation.</p></div></aside><p>Now, <code>img</code> is a NumPy array, as we can see when using the <code>type</code> function:</p><div id="FZ4wTwmrPO" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">type(img)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="nU_Iql_qzHAVAlxOEoxkI" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>numpy.ndarray</span></code></div></div></div><p>We can see the image using the <a target="_blank" rel="noreferrer" href="https://matplotlib.org/api/_as_gen/matplotlib.pyplot.imshow.html#matplotlib.pyplot.imshow" class="link">matplotlib<wbr/>.pyplot<wbr/>.imshow<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> function & the special iPython command, <code>%matplotlib inline</code> to display plots inline:</p><div id="pgXd8U3dbf" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">import matplotlib.pyplot as plt
%matplotlib inline</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="_DGSEI5k4Zw-erPdlNh00" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><div id="p5wceLnxy6" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">fig, ax = plt.subplots()
ax.imshow(img)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="KhsGEMGJg0K7oR1yTiQsI" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-image"><img src="/numpy-tutorials/build/a70fadc37715fe59e0c9ec532ed344ed.png" alt="<Figure size 640x480 with 1 Axes>"/></div></div></div><h3 id="shape-axis-and-array-properties" class="relative group"><span class="heading-text">Shape, axis and array properties</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#shape-axis-and-array-properties" title="Link to this Section" aria-label="Link to this Section">¶</a></h3><p>Note that, in linear algebra, the dimension of a vector refers to the number of entries in an array. In NumPy, it instead defines the number of axes. For example, a 1D array is a vector such as <code>[1, 2, 3]</code>, a 2D array is a matrix, and so forth.</p><p>First, let’s check for the shape of the data in our array. Since this image is two-dimensional (the pixels in the image form a rectangle), we might expect a two-dimensional array to represent it (a matrix). However, using the <code>shape</code> property of this NumPy array gives us a different result:</p><div id="y9TCbbM0Jc" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="wtQZCvuwBDUzrbRSYnTUQ" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(768, 1024, 3)</span></code></div></div></div><p>The output is a <a target="_blank" rel="noreferrer" href="https://docs.python.org/dev/tutorial/datastructures.html#tut-tuples" class="link">tuple<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> with three elements, which means that this is a three-dimensional array. Since this is a color image, and we have used the <code>imread</code> function to read it, the data is organized as a 768×1024 grid of pixels, where each pixel contains 3 values representing color channels (red, green and blue - RGB). You can see this by looking at the shape, where the leftmost number corresponds to the outermost axis (image height), the middle number to the next axis (image width) and the rightmost number to the innermost axis (the color channels).</p><p>Furthermore, using the <code>ndim</code> property of this array, we can see that</p><div id="RhaCct5Nbe" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img.ndim</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="DiUOoXTGBxonfv0vWA_c4" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>3</span></code></div></div></div><p>NumPy refers to each dimension as an <em>axis</em>. Because of how <code>imread</code> works, the <em>first index in the 3rd axis</em> is the red pixel data for our image. We can access this by using the syntax</p><div id="z6miQGVZZw" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img[:, :, 0]</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="TT1Ti6-oHIN5izFLp64Ev" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>array([[121, 138, 153, ..., 119, 131, 139],
[ 89, 110, 130, ..., 118, 134, 146],
[ 73, 94, 115, ..., 117, 133, 144],
...,
[ 87, 94, 107, ..., 120, 119, 119],
[ 85, 95, 112, ..., 121, 120, 120],
[ 85, 97, 111, ..., 120, 119, 118]],
shape=(768, 1024), dtype=uint8)</span></code></div></div></div><p>From the output above, we can see that every value in <code>img[:, :, 0]</code> is an integer value between 0 and 255, representing the level of red in each corresponding image pixel (keep in mind that this might be different if you
use your own image instead of <a target="_blank" rel="noreferrer" href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.datasets.face.html" class="link">scipy.datasets.face<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>).</p><p>As expected, this is a 768x1024 matrix:</p><div id="vEhswiQ01h" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img[:, :, 0].shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="6FKE0QwXXMre_NoIjv_QX" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(768, 1024)</span></code></div></div></div><p>Since we are going to perform linear algebra operations on this data, it might be more interesting to have real numbers between 0 and 1 in each entry of the matrices to represent the RGB values. We can do that by setting</p><div id="DGd2KQjB7b" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img_array = img / 255</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="pUzpyIYrFV1gjQ2Mgdzye" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>This operation, dividing an array by a scalar, works because of NumPy’s <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/user/theory.broadcasting.html#array-broadcasting-in-numpy" class="link">broadcasting rules<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>.</p><aside class="myst-admonition myst-admonition-tip my-5 shadow-md dark:shadow-2xl dark:shadow-neutral-900 bg-gray-50/10 dark:bg-stone-800 overflow-hidden myst-admonition-default rounded border-l-4 border-green-600"><div class="myst-admonition-header m-0 font-medium py-1 flex min-w-0 text-lg text-green-600 bg-green-50 dark:bg-slate-900"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="2rem" height="2rem" class="myst-admonition-header-icon inline-block pl-2 mr-2 self-center flex-none text-green-600"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10"></path></svg><div class="myst-admonition-header-text text-neutral-900 dark:text-white grow self-center overflow-hidden break-words">Tip</div></div><div class="myst-admonition-body px-4 py-1"><p>In real-world applications, it may be better to use, for example, the
<a target="_blank" rel="noreferrer" href="https://scikit-image.org/docs/stable/api/skimage.html#skimage.img_as_float" class="link">img_as_float<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>
utility function from <code>scikit-image</code>.</p></div></aside><p>You can check that the above works by doing some tests; for example, inquiring
about maximum and minimum values for this array:</p><div id="te3q3xUr21" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img_array.min(), img_array.max()</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="rapLz3p0e6AGhjfmsiY_A" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(np.float64(0.0), np.float64(1.0))</span></code></div></div></div><p>or checking the type of data in the array:</p><div id="YQ4cFJ8hom" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img_array.dtype</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="g8_XdKGLwP2sKobl1M5rx" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>dtype('float64')</span></code></div></div></div><p>Note that we can assign each color channel to a separate matrix using the slice syntax:</p><div id="xocBa4YIHH" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">red_array = img_array[:, :, 0]
green_array = img_array[:, :, 1]
blue_array = img_array[:, :, 2]</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="_BrLWDGn9SKOg_t_HegvW" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><h3 id="operations-on-an-axis" class="relative group"><span class="heading-text">Operations on an axis</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#operations-on-an-axis" title="Link to this Section" aria-label="Link to this Section">¶</a></h3><p>It is possible to use methods from linear algebra to approximate an existing set of data. Here, we will use the <a href="https://en.wikipedia.org/wiki/Singular_value_decomposition" class="hover-link" target="_blank" rel="noreferrer" data-state="closed">SVD (Singular Value Decomposition)</a> to try to rebuild an image that uses less singular value information than the original one, while still retaining some of its features.</p><aside class="myst-admonition myst-admonition-note my-5 shadow-md dark:shadow-2xl dark:shadow-neutral-900 bg-gray-50/10 dark:bg-stone-800 overflow-hidden myst-admonition-default rounded border-l-4 border-blue-500"><div class="myst-admonition-header m-0 font-medium py-1 flex min-w-0 text-lg text-blue-600 bg-blue-50 dark:bg-slate-900"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="2rem" height="2rem" class="myst-admonition-header-icon inline-block pl-2 mr-2 self-center flex-none text-blue-600"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"></path></svg><div class="myst-admonition-header-text text-neutral-900 dark:text-white grow self-center overflow-hidden break-words">Note</div></div><div class="myst-admonition-body px-4 py-1"><p>We will use NumPy’s linear algebra module,
<a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/routines.linalg.html#module-numpy.linalg" class="link">numpy.linalg<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>,
to perform the operations in this tutorial.
Most of the linear algebra functions in this module can also be found in
<a target="_blank" rel="noreferrer" href="https://docs.scipy.org/doc/scipy/reference/linalg.html#module-scipy.linalg" class="link">scipy.linalg<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>,
and users are encouraged to use the <a target="_blank" rel="noreferrer" href="https://docs.scipy.org/doc/scipy/reference/index.html#module-scipy" class="link">scipy<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>
module for real-world applications.
However, some functions in the
<a target="_blank" rel="noreferrer" href="https://docs.scipy.org/doc/scipy/reference/linalg.html#module-scipy.linalg" class="link">scipy.linalg<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>
module, such as the SVD function, only support 2D arrays.
For more information on this, check the <a target="_blank" rel="noreferrer" href="https://docs.scipy.org/doc/scipy/tutorial/linalg.html" class="link">scipy.linalg page<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>.</p></div></aside><p>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 <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span>, the following product can be computed:</p><div id="bvsqQhq2QF" class="flex my-5 group"><div class="flex-grow overflow-x-auto overflow-y-hidden"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>U</mi><mi mathvariant="normal">Σ</mi><msup><mi>V</mi><mi>T</mi></msup><mo>=</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">U \Sigma V^T = A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8913em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mord">Σ</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span></div><div class="relative self-center flex-none pl-2 m-0 text-right select-none"><a class="no-underline text-inherit hover:text-inherit text-inherit hover:text-inherit select-none hover:underline" href="#bvsqQhq2QF" title="Link to this Equation" aria-label="Link to this Equation">(<!-- -->1<!-- -->)</a></div></div><p>where <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>U</mi></mrow><annotation encoding="application/x-tex">U</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span></span></span></span></span> and <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>V</mi><mi>T</mi></msup></mrow><annotation encoding="application/x-tex">V^T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8413em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span></span></span></span></span> are square and <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Σ</mi></mrow><annotation encoding="application/x-tex">\Sigma</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Σ</span></span></span></span></span> is the same size as <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span>. <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Σ</mi></mrow><annotation encoding="application/x-tex">\Sigma</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Σ</span></span></span></span></span> is a diagonal matrix and contains the <a href="https://en.wikipedia.org/wiki/Singular_value" class="hover-link" target="_blank" rel="noreferrer" data-state="closed">singular values</a> of <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span>, organized from largest to smallest. These values are always non-negative and can be used as an indicator of the “importance” of some features represented by the matrix <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span>.</p><p>Let’s see how this works in practice with just one matrix first. Note that according to <a href="https://en.wikipedia.org/wiki/Grayscale#Colorimetric_(perceptual_luminance-preserving)_conversion_to_grayscale" class="hover-link" target="_blank" rel="noreferrer" data-state="closed">colorimetry</a>,
it is possible to obtain a fairly reasonable grayscale version of our color image if we apply the formula</p><div id="b1hjBHMQ48" class="flex my-5 group"><div class="flex-grow overflow-x-auto overflow-y-hidden"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>Y</mi><mo>=</mo><mn>0.2126</mn><mi>R</mi><mo>+</mo><mn>0.7152</mn><mi>G</mi><mo>+</mo><mn>0.0722</mn><mi>B</mi></mrow><annotation encoding="application/x-tex">Y = 0.2126 R + 0.7152 G + 0.0722 B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord">0.2126</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord">0.7152</span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">0.0722</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span></div><div class="relative self-center flex-none pl-2 m-0 text-right select-none"><a class="no-underline text-inherit hover:text-inherit text-inherit hover:text-inherit select-none hover:underline" href="#b1hjBHMQ48" title="Link to this Equation" aria-label="Link to this Equation">(<!-- -->2<!-- -->)</a></div></div><p>where <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Y</mi></mrow><annotation encoding="application/x-tex">Y</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span></span></span></span></span> is the array representing the grayscale image, and <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></span>, <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span> and <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> are the red, green and blue channel arrays we had originally. Notice we can use the <code>@</code> operator (the matrix multiplication operator for NumPy arrays, see <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul" class="link">numpy.matmul<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>) for this:</p><div id="FVzivpxclZ" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img_gray = img_array @ [0.2126, 0.7152, 0.0722]</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="GQGaTKFAK7mcEjRDW0yHk" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>Now, <code>img_gray</code> has shape</p><div id="otCGLRdUH9" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img_gray.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="JYJbDXx4xbbVjfr6l9ik1" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(768, 1024)</span></code></div></div></div><p>To see if this makes sense in our image, we should use a colormap from <code>matplotlib</code> corresponding to the color we wish to see in out image (otherwise, <code>matplotlib</code> will default to a colormap that does not correspond to the real data).</p><p>In our case, we are approximating the grayscale portion of the image, so we will use the colormap <code>gray</code>:</p><div id="HVYQ6o3zPL" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">fig, ax = plt.subplots()
ax.imshow(img_gray, cmap="gray")</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="YI1WsURge2MdNQbGTaenB" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-image"><img src="/numpy-tutorials/build/ae5ff618bce8ea0c89ecbfbdcc1d1f5a.png" alt="<Figure size 640x480 with 1 Axes>"/></div></div></div><p>Now, applying the <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.linalg.svd.html#numpy.linalg.svd" class="link">linalg.svd<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> function to this matrix, we obtain the following decomposition:</p><div id="snZmQFxKr6" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">import numpy as np
U, s, Vt = np.linalg.svd(img_gray)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="GpvExn95t0FN9KZ9HP5ce" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><aside class="myst-admonition myst-admonition-note my-5 shadow-md dark:shadow-2xl dark:shadow-neutral-900 bg-gray-50/10 dark:bg-stone-800 overflow-hidden myst-admonition-default rounded border-l-4 border-blue-500"><div class="myst-admonition-header m-0 font-medium py-1 flex min-w-0 text-lg text-blue-600 bg-blue-50 dark:bg-slate-900"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="2rem" height="2rem" class="myst-admonition-header-icon inline-block pl-2 mr-2 self-center flex-none text-blue-600"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"></path></svg><div class="myst-admonition-header-text text-neutral-900 dark:text-white grow self-center overflow-hidden break-words">Note</div></div><div class="myst-admonition-body px-4 py-1"><p>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.</p></div></aside><p>Let’s check that this is what we expected:</p><div id="YjzC7RKFLE" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">U.shape, s.shape, Vt.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="Q2pmsxWRlur9uHrWHeXIW" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>((768, 768), (768,), (1024, 1024))</span></code></div></div></div><p>Note that <code>s</code> has a particular shape: it has only one dimension. This means that some linear algebra functions that expect 2d arrays might not work. For example, from the theory, one might expect <code>s</code> and <code>Vt</code> to be
compatible for multiplication. However, this is not true as <code>s</code> does not have a second axis:</p><div id="LEEsOqCSGy" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">s @ Vt</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="UweXLQq5Xo9rxEPyfL494" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-error"><div><pre class="myst-jp-error-output text-sm font-thin font-system jupyter-error"><code><span style="color:rgb(187, 0, 0)">---------------------------------------------------------------------------</span><span>
</span><span style="color:rgb(187, 0, 0)">ValueError</span><span> Traceback (most recent call last)
</span><span style="color:rgb(0, 187, 187)">Cell</span><span style="color:rgb(0, 187, 187)"> </span><span style="color:rgb(0, 187, 0)">In[18]</span><span style="color:rgb(0, 187, 0)">, line 1</span><span>
</span><span style="color:rgb(0, 187, 0)">----> </span><span style="color:rgb(0, 187, 0)">1</span><span> </span><span style="background-color:rgb(187, 187, 0)">s</span><span style="background-color:rgb(187, 187, 0)"> </span><span style="background-color:rgb(187, 187, 0)">@</span><span style="background-color:rgb(187, 187, 0)"> </span><span style="background-color:rgb(187, 187, 0)">Vt</span><span>
</span><span style="color:rgb(187, 0, 0)">ValueError</span><span>: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 1024 is different from 768)</span></code></pre></div></div></div></div><p>results in a <code>ValueError</code>. This happens because having a one-dimensional array for <code>s</code>, 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 <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Σ</mi></mrow><annotation encoding="application/x-tex">\Sigma</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Σ</span></span></span></span></span> with the elements of <code>s</code> in its diagonal and with the appropriate dimensions for multiplying: in our case, <span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Σ</mi></mrow><annotation encoding="application/x-tex">\Sigma</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Σ</span></span></span></span></span> should be 768x1024 since <code>U</code> is 768x768 and <code>Vt</code> is 1024x1024. In order to add the singular values to the diagonal of <code>Sigma</code>, we will use the <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.fill_diagonal.html" class="link">fill_diagonal<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> function from NumPy:</p><div id="ATBHcIVHou" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">Sigma = np.zeros((U.shape[1], Vt.shape[0]))
np.fill_diagonal(Sigma, s)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="5hfoy_U-XJAgAKTzktdtW" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>Now, we want to check if the reconstructed <code>U @ Sigma @ Vt</code> is close to the original <code>img_gray</code> matrix.</p><h2 id="approximation" class="relative group"><span class="heading-text">Approximation</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#approximation" title="Link to this Section" aria-label="Link to this Section">¶</a></h2><p>The <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/routines.linalg.html#module-numpy.linalg" class="link">linalg<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> module includes a <code>norm</code> 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 <code>img_gray</code> and the reconstructed SVD product to be small. As expected, you should see something like</p><div id="uA5RnraHo5" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">np.linalg.norm(img_gray - U @ Sigma @ Vt)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="yRvoFbSbkoLVeUkBREKFG" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>np.float64(1.4314854759568272e-12)</span></code></div></div></div><p>(The actual result of this operation might be different depending on your architecture and linear algebra setup. Regardless, you should see a small number.)</p><p>We could also have used the <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.allclose.html#numpy.allclose" class="link">numpy.allclose<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> function to make sure the reconstructed product is, in fact, <em>close</em> to our original matrix (the difference between the two arrays is small):</p><div id="szk8PVaqxS" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">np.allclose(img_gray, U @ Sigma @ Vt)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="K01mUFNU-S2ILzYwOUJr4" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>True</span></code></div></div></div><p>To see if an approximation is reasonable, we can check the values in <code>s</code>:</p><div id="h6z4H8Yy9f" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">fig, ax = plt.subplots()
ax.plot(s)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="N3g7THyIENHrBHG9Ve3uh" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-image"><img src="/numpy-tutorials/build/5bffdb870c5e856cb5ffe56f0d2e9372.png" alt="<Figure size 640x480 with 1 Axes>"/></div></div></div><p>In the graph, we can see that although we have 768 singular values in <code>s</code>, most of those (after the 150th entry or so) are pretty small. So it might make sense to use only the information related to the first (say, 50) <em>singular values</em> to build a more economical approximation to our image.</p><p>The idea is to consider all but the first <code>k</code> singular values in <code>Sigma</code> (which are the same as in <code>s</code>) as zeros, keeping <code>U</code> and <code>Vt</code> intact, and computing the product of these matrices as the approximation.</p><p>For example, if we choose</p><div id="hjHLmFOaNA" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">k = 10</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="cONg4YnB-BMzCrTPJKUZR" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>we can build the approximation by doing</p><div id="WjhnelZAjP" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">approx = U @ Sigma[:, :k] @ Vt[:k, :]</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="HtBtiXW_IR2lUO3h_eRui" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>Note that we had to use only the first <code>k</code> rows of <code>Vt</code>, since all other rows would be multiplied by the zeros corresponding to the singular values we eliminated from this approximation.</p><div id="iJqS9EPgq8" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">fig, ax = plt.subplots()
ax.imshow(approx, cmap="gray")</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="RoEwh7aNSxm432sopwYso" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-image"><img src="/numpy-tutorials/build/0731d9ff394c572db56e83187ed9a359.png" alt="<Figure size 640x480 with 1 Axes>"/></div></div></div><p>Now, you can go ahead and repeat this experiment with other values of <code>k</code>, and each of your experiments should give you a slightly better (or worse) image depending on the value you choose.</p><h3 id="applying-to-all-colors" class="relative group"><span class="heading-text">Applying to all colors</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#applying-to-all-colors" title="Link to this Section" aria-label="Link to this Section">¶</a></h3><p>Now we want to do the same kind of operation, but to all three colors. Our first instinct might be to repeat the same operation we did above to each color matrix individually. However, NumPy’s <em>broadcasting</em> takes care of this
for us.</p><p>If our array has more than two dimensions, then the SVD can be applied to all axes at once. However, the linear algebra functions in NumPy expect to see an array of the form <code>(n, M, N)</code>, where the first axis <code>n</code> represents the number of <code>MxN</code> matrices in the stack.</p><p>In our case,</p><div id="WctfvMhG5s" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">img_array.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="8Ra-L6gk8qJvX0IjqXNbK" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(768, 1024, 3)</span></code></div></div></div><p>so we need to permutate the axis on this array to get a shape like <code>(3, 768, 1024)</code>. Fortunately, the <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.transpose.html#numpy.transpose" class="link">numpy.transpose<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> function can do that for us:</p><div id="PqAVTYKToo" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre"># The values in the tuple indicate the original dim, and the order the new axis
# so axis 2 -> 0, 0 -> 1, and 1 -> 2
img_array_transposed = np.transpose(img_array, (2, 0, 1))
img_array_transposed.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="BFV1JtZAVubfrl4gpASdG" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(3, 768, 1024)</span></code></div></div></div><p>Now we are ready to apply the SVD:</p><div id="mWcO8WfaFR" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">U, s, Vt = np.linalg.svd(img_array_transposed)</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="QORZbXbSmb2_RL0ib0WzR" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>Finally, to obtain the full approximated image, we need to reassemble these matrices into the approximation. Now, note that</p><div id="L3hkSs9BnE" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">U.shape, s.shape, Vt.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="k-K--44LboMwLXrNmqup8" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>((3, 768, 768), (3, 768), (3, 1024, 1024))</span></code></div></div></div><p>To build the final approximation matrix, we must understand how multiplication across different axes works.</p><h3 id="products-with-n-dimensional-arrays" class="relative group"><span class="heading-text">Products with n-dimensional arrays</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#products-with-n-dimensional-arrays" title="Link to this Section" aria-label="Link to this Section">¶</a></h3><p>If you have worked before with only one- or two-dimensional arrays in NumPy, you might use <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.dot.html#numpy.dot" class="link">numpy.dot<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> and <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul" class="link">numpy.matmul<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> (or the <code>@</code> operator) interchangeably. However, for n-dimensional arrays, they work in very different ways. For more details, check the documentation on <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul" class="link">numpy.matmul<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>.</p><p>Now, to build our approximation, we first need to make sure that our singular values are ready for multiplication, so we build our <code>Sigma</code> matrix similarly to what we did before. The <code>Sigma</code> array must have dimensions <code>(3, 768, 1024)</code>. In order to add the singular values to the diagonal of <code>Sigma</code>, we will again use the <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/generated/numpy.fill_diagonal.html" class="link">fill_diagonal<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a> function, using each of the 3 rows in <code>s</code> as the diagonal for each of the 3 matrices in <code>Sigma</code>:</p><div id="fbnDrlUTnw" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">Sigma = np.zeros((3, 768, 1024))
for j in range(3):
np.fill_diagonal(Sigma[j, :, :], s[j, :])</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="nnJXZ8tT01edvXncBiP3t" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>Now, if we wish to rebuild the full SVD (with no approximation), we can do</p><div id="af7tRrGi6X" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">reconstructed = U @ Sigma @ Vt</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="CKHN8ysnim9yTRudunS2H" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>Note that</p><div id="oIvspPZ2SZ" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">reconstructed.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="Ntf5LLmfrJVUc-xJUiYRr" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(3, 768, 1024)</span></code></div></div></div><p>The reconstructed image should be indistinguishable from the original one, except for differences due to floating point errors from the reconstruction. Recall that our original image consisted of floating point values in the range <code>[0., 1.]</code>. The accumulation of floating point error from the reconstruction can result in values slightly outside this original range:</p><div id="PB2eS9oAeS" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">reconstructed.min(), reconstructed.max()</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="wQIFQOL_B5CFTAFYcjzB1" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(np.float64(-5.0176876542629145e-15), np.float64(1.0000000000000049))</span></code></div></div></div><p>Since <code>imshow</code> expects values in the range, we can use <code>clip</code> to excise the floating point error:</p><div id="ZjTIsddnyM" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">reconstructed = np.clip(reconstructed, 0, 1)
fig, ax = plt.subplots()
ax.imshow(np.transpose(reconstructed, (1, 2, 0)))</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="XQIpZwQrVooKddDg2zvIU" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-image"><img src="/numpy-tutorials/build/77afc43dcd6aa9aa05c2dbe6889dec36.png" alt="<Figure size 640x480 with 1 Axes>"/></div></div></div><aside class="myst-admonition myst-admonition-note my-5 shadow-md dark:shadow-2xl dark:shadow-neutral-900 bg-gray-50/10 dark:bg-stone-800 overflow-hidden myst-admonition-default rounded border-l-4 border-blue-500"><div class="myst-admonition-header m-0 font-medium py-1 flex min-w-0 text-lg text-blue-600 bg-blue-50 dark:bg-slate-900"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="2rem" height="2rem" class="myst-admonition-header-icon inline-block pl-2 mr-2 self-center flex-none text-blue-600"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"></path></svg><div class="myst-admonition-header-text text-neutral-900 dark:text-white grow self-center overflow-hidden break-words">Note</div></div><div class="myst-admonition-body px-4 py-1"><p>In fact, <code>imshow</code> peforms this clipping under-the-hood, so if you skip the first
line in the previous code cell, you might see a warning message saying
<code>"Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers)."</code></p></div></aside><p>Now, to do the approximation, we must choose only the first <code>k</code> singular values for each color channel. This can be done using the following syntax:</p><div id="Ctrq9B5oX0" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">approx_img = U @ Sigma[..., :k] @ Vt[..., :k, :]</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="XAebqeGC1dCu6K3wuH7YM" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left"></div></div><p>You can see that we have selected only the first <code>k</code> components of the last axis for <code>Sigma</code> (this means that we have used only the first <code>k</code> columns of each of the three matrices in the stack), and that we have selected only the first <code>k</code> components in the second-to-last axis of <code>Vt</code> (this means we have selected only the first <code>k</code> rows from every matrix in the stack <code>Vt</code> and all columns). If you are unfamiliar with the ellipsis syntax, it is a
placeholder for other axes. For more details, see the documentation on <a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/user/basics.indexing.html#basics-indexing" class="link">Indexing<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a>.</p><p>Now,</p><div id="sp4nkGTULp" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">approx_img.shape</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="UI6tlxGNFpcbTaBLIx43a" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-text" class="font-mono text-sm whitespace-pre-wrap myst-jp-safe-output-text"><code><span>(3, 768, 1024)</span></code></div></div></div><p>which is not the right shape for showing the image. Finally, reordering the axes back to our original shape of <code>(768, 1024, 3)</code>, we can see our approximation:</p><div id="lJV9pytC3S" class="myst-jp-nb-block relative group/block"><div class="myst-jp-nb-block-spinner flex sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:hidden"><div class="flex absolute top-0 right-0"></div></div><div class="myst-jp-nb-block sticky top-[115px] z-10 opacity-90 group-hover/block:opacity-100 group-hover/block:flex"><div class="absolute -top-[12px] right-0 flex flex-row rounded bg-white dark:bg-slate-800"></div></div><div class="relative myst-code group not-prose my-5 text-sm shadow hover:shadow-md dark:shadow-2xl dark:shadow-neutral-900 border border-l-4 border-gray-200 border-l-blue-400 dark:border-l-blue-400 dark:border-gray-800"><pre class="block overflow-auto p-3 myst-code-body hljs" style="background-color:unset"><code class="language-python" style="white-space:pre">fig, ax = plt.subplots()
ax.imshow(np.transpose(np.clip(approx_img, 0, 1), (1, 2, 0)))</code></pre><button title="Copy to Clipboard" class="inline-flex items-center opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 active:opacity-100 cursor-pointer ml-2 transition-color duration-200 ease-in-out text-blue-400 hover:text-blue-500 absolute right-1 myst-code-copy-icon top-1" aria-pressed="false" aria-label="Copy code to clipboard"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="24" height="24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"></path></svg></button></div><div data-name="outputs-container" data-mdast-node-id="ks3X8x0mmwbAsxoRB7MwP" class="max-w-full overflow-y-visible overflow-x-auto m-0 group not-prose relative text-left mb-5"><div data-name="safe-output-image"><img src="/numpy-tutorials/build/b2bc20c3465b9a9bf572f1764b65f59b.png" alt="<Figure size 640x480 with 1 Axes>"/></div></div></div><p>Even though the image is not as sharp, using a small number of <code>k</code> singular values (compared to the original set of 768 values), we can recover many of the distinguishing features from this image.</p><h3 id="final-words" class="relative group"><span class="heading-text">Final words</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#final-words" title="Link to this Section" aria-label="Link to this Section">¶</a></h3><p>Of course, this is not the best method to <em>approximate</em> an image. However, there is, in fact, a result in linear algebra that says that the approximation we built above is the best we can get to the original matrix in
terms of the norm of the difference. For more information, see <em>G. H. Golub and C. F. Van Loan, Matrix Computations, Baltimore, MD, Johns Hopkins University Press, 1985</em>.</p><h2 id="further-reading" class="relative group"><span class="heading-text">Further reading</span><a class="no-underline text-inherit hover:text-inherit inline-block w-0 px-0 translate-x-[10px] font-normal select-none transition-opacity opacity-0 focus:opacity-100 group-hover:opacity-70" href="#further-reading" title="Link to this Section" aria-label="Link to this Section">¶</a></h2><ul><li><p><a target="_blank" rel="noreferrer" href="https://docs.python.org/dev/tutorial/index.html" class="link">Python tutorial<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a></p></li><li><p><a target="_blank" rel="noreferrer" href="https://numpy.org/devdocs/reference/index.html#reference" class="link">NumPy Reference<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a></p></li><li><p><a target="_blank" rel="noreferrer" href="https://docs.scipy.org/doc/scipy/tutorial/index.html" class="link">SciPy Tutorial<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a></p></li><li><p><a target="_blank" rel="noreferrer" href="https://scipy-lectures.org" class="link">SciPy Lecture Notes<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a></p></li><li><p><a target="_blank" rel="noreferrer" href="http://mathesaurus.sf.net/" class="link">A matlab, R, IDL, NumPy/SciPy dictionary<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="link-icon"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"></path></svg></a></p></li></ul><div class="myst-backmatter-parts"></div><div class="myst-footer-links flex pt-10 mb-10 space-x-4"><a class="myst-footer-link flex-1 block p-4 font-normal text-gray-600 no-underline border border-gray-200 rounded shadow-sm group hover:border-blue-600 dark:hover:border-blue-400 hover:text-blue-600 dark:hover:text-blue-400 dark:text-gray-100 dark:border-gray-500 hover:shadow-lg dark:shadow-neutral-700 myst-footer-link-prev" href="/numpy-tutorials/tutorial-air-quality-analysis"><div class="flex h-full align-middle"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="1.5rem" height="1.5rem" class="myst-footer-link-icon self-center transition-transform group-hover:-translate-x-1 shrink-0"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"></path></svg><div class="flex-grow text-right"><div class="myst-footer-link-group text-xs text-gray-500 dark:text-gray-400">Applications</div>Analyzing Air Quality</div></div></a><a class="myst-footer-link flex-1 block p-4 font-normal text-gray-600 no-underline border border-gray-200 rounded shadow-sm group hover:border-blue-600 dark:hover:border-blue-400 hover:text-blue-600 dark:hover:text-blue-400 dark:text-gray-100 dark:border-gray-500 hover:shadow-lg dark:shadow-neutral-700 myst-footer-link-next" href="/numpy-tutorials/save-load-arrays"><div class="flex h-full align-middle"><div class="flex-grow"><div class="myst-footer-link-group text-xs text-gray-500 dark:text-gray-400">Features</div>Sharing Array Data</div><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" width="1.5rem" height="1.5rem" class="myst-footer-link-icon self-center transition-transform group-hover:translate-x-1 shrink-0"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"></path></svg></div></a></div></article></main><script>((a,l)=>{if(!window.history.state||!window.history.state.key){let u=Math.random().toString(32).slice(2);window.history.replaceState({key:u},"")}try{let d=JSON.parse(sessionStorage.getItem(a)||"{}")[l||window.history.state.key];typeof d=="number"&&window.scrollTo(0,d)}catch(u){console.error(u),sessionStorage.removeItem(a)}})("positions", null)</script><link rel="modulepreload" href="/numpy-tutorials/build/entry.client-PCJPW7TK.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-AQ2CODAG.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-JJXTQVMA.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-OZE3FFNP.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-CH4FVTDV.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-C4DFGG5C.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-J7TUH54J.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-FZ2S7OYD.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-JEM6JXYA.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-34XIY2DH.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-KQM5FBHR.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-OCWQY3HK.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-7HNKBP4B.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-CUKUDK3R.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-3EBOCCHJ.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-O4VQNZ62.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-4OEDG4JQ.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-GUCIBHGO.js"/><link rel="modulepreload" href="/numpy-tutorials/build/root-SIO6LUTY.js"/><link rel="modulepreload" href="/numpy-tutorials/build/_shared/chunk-FAHZZXAC.js"/><link rel="modulepreload" href="/numpy-tutorials/build/routes/$-PRP77N34.js"/><script>window.__remixContext = {"url":"/tutorial-svd","state":{"loaderData":{"root":{"config":{"version":3,"myst":"1.8.0","options":{"favicon":"/numpy-tutorials/build/favicon-5dd127103743f9fd9d1ab5b34dfbe735.png","logo":"/numpy-tutorials/build/numpylogo-28b47a276e91aa58e8056b86c12e6958.svg"},"nav":[],"actions":[],"projects":[{"title":"Numpy Tutorials","authors":[{"id":"Numpy Community","name":"Numpy Community"}],"github":"https://github.com/numpy/numpy-tutorials","toc":[{"file":"content/index.md"},{"children":[{"file":"content/mooreslaw-tutorial.md"},{"file":"content/tutorial-deep-learning-on-mnist.md"},{"file":"content/tutorial-x-ray-image-processing.md"},{"file":"content/tutorial-static_equilibrium.md"},{"file":"content/tutorial-plotting-fractals.md"},{"file":"content/tutorial-air-quality-analysis.md"}],"title":"Applications"},{"children":[{"file":"content/tutorial-svd.md"},{"file":"content/save-load-arrays.md"},{"file":"content/tutorial-ma.md"}],"title":"Features"},{"children":[{"file":"content/tutorial-style-guide.md"}],"file":"content/contributing.md","title":"Contributing"}],"thumbnail":"/numpy-tutorials/build/b77199e99a54e59b2e3c037c2cc90f21.svg","exports":[],"bibliography":[],"index":"index","pages":[{"level":1,"title":"Applications"},{"slug":"mooreslaw-tutorial","title":"Determining Moore’s Law with real data in NumPy","short_title":"Moore's Law","description":"","date":"","thumbnail":"/numpy-tutorials/build/01-mooreslaw-tutoria-68d0ad466c300d347c517c09cd29d0d9.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-deep-learning-on-mnist","title":"Deep learning on MNIST","description":"","date":"","thumbnail":"/numpy-tutorials/build/tutorial-deep-learni-1a6932c38d13641ad9a1eda7d431b1f5.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-x-ray-image-processing","title":"X-ray image processing","description":"","date":"","thumbnail":"/numpy-tutorials/build/tutorial-x-ray-image-cb14ad1cb4fb37f341c5954e91e694b8.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-static-equilibrium","title":"Determining Static Equilibrium in NumPy","short_title":"Static Equilibrium","description":"","date":"","thumbnail":"/numpy-tutorials/build/static_eqbm-fig01-ee029c471a69f4e98c09d962ac7d60dd.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-plotting-fractals","title":"Plotting Fractals","description":"","date":"","thumbnail":"/numpy-tutorials/build/fractal-4ebbc2569665376d939ff6f78ae5e5ab.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-air-quality-analysis","title":"Analyzing the impact of the lockdown on air quality in Delhi, India","short_title":"Analyzing Air Quality","description":"","date":"","thumbnail":"/numpy-tutorials/build/11-delhi-aqi-5fa295dd14ed05daaf4cd0193122e2f7.jpg","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"level":1,"title":"Features"},{"slug":"tutorial-svd","title":"Linear algebra on n-dimensional arrays","short_title":"Linear Algebra on n-D arrays","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"save-load-arrays","title":"Saving and sharing your NumPy arrays","short_title":"Sharing Array Data","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-ma","title":"Masked Arrays","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"contributing","title":"Contributing","short_title":"Contributing","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":1},{"slug":"tutorial-style-guide","title":"Learn to write a NumPy tutorial","short_title":"Style Guide","description":"","date":"","thumbnail":"/numpy-tutorials/build/56554e3d11983df8f484e8d7b2c2bdae.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2}]}]},"CONTENT_CDN_PORT":"3100","MODE":"static","BASE_URL":"/numpy-tutorials"},"routes/$":{"config":{"version":3,"myst":"1.8.0","options":{"favicon":"/numpy-tutorials/build/favicon-5dd127103743f9fd9d1ab5b34dfbe735.png","logo":"/numpy-tutorials/build/numpylogo-28b47a276e91aa58e8056b86c12e6958.svg"},"nav":[],"actions":[],"projects":[{"title":"Numpy Tutorials","authors":[{"id":"Numpy Community","name":"Numpy Community"}],"github":"https://github.com/numpy/numpy-tutorials","toc":[{"file":"content/index.md"},{"children":[{"file":"content/mooreslaw-tutorial.md"},{"file":"content/tutorial-deep-learning-on-mnist.md"},{"file":"content/tutorial-x-ray-image-processing.md"},{"file":"content/tutorial-static_equilibrium.md"},{"file":"content/tutorial-plotting-fractals.md"},{"file":"content/tutorial-air-quality-analysis.md"}],"title":"Applications"},{"children":[{"file":"content/tutorial-svd.md"},{"file":"content/save-load-arrays.md"},{"file":"content/tutorial-ma.md"}],"title":"Features"},{"children":[{"file":"content/tutorial-style-guide.md"}],"file":"content/contributing.md","title":"Contributing"}],"thumbnail":"/numpy-tutorials/build/b77199e99a54e59b2e3c037c2cc90f21.svg","exports":[],"bibliography":[],"index":"index","pages":[{"level":1,"title":"Applications"},{"slug":"mooreslaw-tutorial","title":"Determining Moore’s Law with real data in NumPy","short_title":"Moore's Law","description":"","date":"","thumbnail":"/numpy-tutorials/build/01-mooreslaw-tutoria-68d0ad466c300d347c517c09cd29d0d9.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-deep-learning-on-mnist","title":"Deep learning on MNIST","description":"","date":"","thumbnail":"/numpy-tutorials/build/tutorial-deep-learni-1a6932c38d13641ad9a1eda7d431b1f5.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-x-ray-image-processing","title":"X-ray image processing","description":"","date":"","thumbnail":"/numpy-tutorials/build/tutorial-x-ray-image-cb14ad1cb4fb37f341c5954e91e694b8.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-static-equilibrium","title":"Determining Static Equilibrium in NumPy","short_title":"Static Equilibrium","description":"","date":"","thumbnail":"/numpy-tutorials/build/static_eqbm-fig01-ee029c471a69f4e98c09d962ac7d60dd.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-plotting-fractals","title":"Plotting Fractals","description":"","date":"","thumbnail":"/numpy-tutorials/build/fractal-4ebbc2569665376d939ff6f78ae5e5ab.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-air-quality-analysis","title":"Analyzing the impact of the lockdown on air quality in Delhi, India","short_title":"Analyzing Air Quality","description":"","date":"","thumbnail":"/numpy-tutorials/build/11-delhi-aqi-5fa295dd14ed05daaf4cd0193122e2f7.jpg","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"level":1,"title":"Features"},{"slug":"tutorial-svd","title":"Linear algebra on n-dimensional arrays","short_title":"Linear Algebra on n-D arrays","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"save-load-arrays","title":"Saving and sharing your NumPy arrays","short_title":"Sharing Array Data","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-ma","title":"Masked Arrays","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"contributing","title":"Contributing","short_title":"Contributing","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":1},{"slug":"tutorial-style-guide","title":"Learn to write a NumPy tutorial","short_title":"Style Guide","description":"","date":"","thumbnail":"/numpy-tutorials/build/56554e3d11983df8f484e8d7b2c2bdae.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2}]}]},"page":{"version":3,"kind":"Notebook","sha256":"fbedc5d5b1c3c4def5da14b1627e32cbd4ab0ce76177a8bb533b0eeef41c81e2","slug":"tutorial-svd","location":"/content/tutorial-svd.md","dependencies":[],"frontmatter":{"title":"Linear algebra on n-dimensional arrays","short_title":"Linear Algebra on n-D arrays","kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"jupytext":{"text_representation":{"extension":".md","format_name":"myst","format_version":"0.13","jupytext_version":"1.11.1"}},"content_includes_title":false,"authors":[{"id":"Numpy Community","name":"Numpy Community"}],"github":"https://github.com/numpy/numpy-tutorials","numbering":{"title":{"offset":1}},"source_url":"https://github.com/numpy/numpy-tutorials/blob/main/content/tutorial-svd.md","edit_url":"https://github.com/numpy/numpy-tutorials/edit/main/content/tutorial-svd.md","exports":[{"format":"md","filename":"tutorial-svd.md","url":"/numpy-tutorials/build/tutorial-svd-36d73926a5c5ee844d1f1103e1f56d10.md"}]},"mdast":{"type":"root","children":[{"type":"block","position":{"start":{"line":17,"column":1},"end":{"line":17,"column":1}},"children":[{"type":"heading","depth":2,"position":{"start":{"line":19,"column":1},"end":{"line":19,"column":1}},"children":[{"type":"text","value":"Prerequisites","position":{"start":{"line":19,"column":1},"end":{"line":19,"column":1}},"key":"ZX6PgIc5Ho"}],"identifier":"prerequisites","label":"Prerequisites","html_id":"prerequisites","implicit":true,"key":"GgZ72WESfv"},{"type":"paragraph","position":{"start":{"line":21,"column":1},"end":{"line":21,"column":1}},"children":[{"type":"text","value":"Before reading this tutorial, you should know a bit of Python. If you would like to refresh your memory, take a look at the ","position":{"start":{"line":21,"column":1},"end":{"line":21,"column":1}},"key":"nIpE7c7Kxm"},{"type":"link","url":"https://docs.python.org/3/tutorial/","position":{"start":{"line":21,"column":1},"end":{"line":21,"column":1}},"children":[{"type":"text","value":"Python tutorial","position":{"start":{"line":21,"column":1},"end":{"line":21,"column":1}},"key":"cED5hKGp3p"}],"urlSource":"https://docs.python.org/3/tutorial/","key":"KyjfaMt2Ga"},{"type":"text","value":".","position":{"start":{"line":21,"column":1},"end":{"line":21,"column":1}},"key":"AuLjf8aJPd"}],"key":"JDUSRagwC4"},{"type":"paragraph","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"children":[{"type":"text","value":"If you want to be able to run the examples in this tutorial, you should also have ","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"key":"ArC5EoztWz"},{"type":"link","url":"https://matplotlib.org/","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"children":[{"type":"text","value":"matplotlib","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"key":"EXW0FKFeon"}],"urlSource":"https://matplotlib.org/","key":"S9AijszyEP"},{"type":"text","value":" and ","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"key":"W3pZEREQPS"},{"type":"link","url":"https://scipy.org","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"children":[{"type":"text","value":"SciPy","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"key":"tDbzWFXPgM"}],"urlSource":"https://scipy.org","key":"VQhLLz8oUT"},{"type":"text","value":" installed on your computer.","position":{"start":{"line":23,"column":1},"end":{"line":23,"column":1}},"key":"tgt8di0FVz"}],"key":"EyvQPnx4Z9"},{"type":"heading","depth":2,"position":{"start":{"line":25,"column":1},"end":{"line":25,"column":1}},"children":[{"type":"text","value":"Learner profile","position":{"start":{"line":25,"column":1},"end":{"line":25,"column":1}},"key":"MRmTjpZoVm"}],"identifier":"learner-profile","label":"Learner profile","html_id":"learner-profile","implicit":true,"key":"gHOIkNbTJo"},{"type":"paragraph","position":{"start":{"line":27,"column":1},"end":{"line":27,"column":1}},"children":[{"type":"text","value":"This tutorial is for people who have a basic understanding of linear algebra and arrays in NumPy and want to understand how n-dimensional (","position":{"start":{"line":27,"column":1},"end":{"line":27,"column":1}},"key":"TR0gGX1dLX"},{"type":"inlineMath","value":"n\u003e=2","position":{"start":{"line":27,"column":1},"end":{"line":27,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003en\u003c/mi\u003e\u003cmo\u003e\u0026gt;\u003c/mo\u003e\u003cmo\u003e=\u003c/mo\u003e\u003cmn\u003e2\u003c/mn\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003en\u0026gt;=2\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003en\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2778em;\"\u003e\u003c/span\u003e\u003cspan class=\"mrel\"\u003e\u0026gt;=\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2778em;\"\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6444em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003e2\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"gvJoEaiCNV"},{"type":"text","value":") arrays are represented and can be manipulated. In particular, if you don’t know how to apply common functions to n-dimensional arrays (without using for-loops), or if you want to understand axis and shape properties for n-dimensional arrays, this tutorial might be of help.","position":{"start":{"line":27,"column":1},"end":{"line":27,"column":1}},"key":"ozlEsbgiVl"}],"key":"LBmpkDcivg"},{"type":"heading","depth":2,"position":{"start":{"line":29,"column":1},"end":{"line":29,"column":1}},"children":[{"type":"text","value":"Learning Objectives","position":{"start":{"line":29,"column":1},"end":{"line":29,"column":1}},"key":"bbqqMqG2KX"}],"identifier":"learning-objectives","label":"Learning Objectives","html_id":"learning-objectives","implicit":true,"key":"E9irtVTQsl"},{"type":"paragraph","position":{"start":{"line":31,"column":1},"end":{"line":31,"column":1}},"children":[{"type":"text","value":"After this tutorial, you should be able to:","position":{"start":{"line":31,"column":1},"end":{"line":31,"column":1}},"key":"TRz9qN2DME"}],"key":"sxYZ1k7Fub"},{"type":"list","ordered":false,"spread":false,"position":{"start":{"line":33,"column":1},"end":{"line":36,"column":1}},"children":[{"type":"listItem","spread":true,"position":{"start":{"line":33,"column":1},"end":{"line":33,"column":1}},"children":[{"type":"paragraph","children":[{"type":"text","value":"Understand the difference between one-, two- and n-dimensional arrays in NumPy;","position":{"start":{"line":33,"column":1},"end":{"line":33,"column":1}},"key":"zos7Fl4dee"}],"key":"ab73nPQ8pA"}],"key":"BzIIp1XSaF"},{"type":"listItem","spread":true,"position":{"start":{"line":34,"column":1},"end":{"line":34,"column":1}},"children":[{"type":"paragraph","children":[{"type":"text","value":"Understand how to apply some linear algebra operations to n-dimensional arrays without using for-loops;","position":{"start":{"line":34,"column":1},"end":{"line":34,"column":1}},"key":"vF3NlauVgH"}],"key":"hVPch1YZra"}],"key":"Kct8U3uTaR"},{"type":"listItem","spread":true,"position":{"start":{"line":35,"column":1},"end":{"line":36,"column":1}},"children":[{"type":"paragraph","children":[{"type":"text","value":"Understand axis and shape properties for n-dimensional arrays.","position":{"start":{"line":35,"column":1},"end":{"line":35,"column":1}},"key":"b9A4kvhrGT"}],"key":"Zr9NVz7kHo"}],"key":"PfjmJq5nad"}],"key":"Vdza5lyRS5"},{"type":"heading","depth":2,"position":{"start":{"line":37,"column":1},"end":{"line":37,"column":1}},"children":[{"type":"text","value":"Content","position":{"start":{"line":37,"column":1},"end":{"line":37,"column":1}},"key":"tOk7eNzs34"}],"identifier":"content","label":"Content","html_id":"content","implicit":true,"key":"PVC2Nz3Pn7"},{"type":"paragraph","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"children":[{"type":"text","value":"In this tutorial, we will use a ","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"key":"DFBJlXoYkZ"},{"type":"link","url":"https://en.wikipedia.org/wiki/Matrix_decomposition","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"children":[{"type":"text","value":"matrix decomposition","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"key":"qlt7X4GIWq"}],"urlSource":"https://en.wikipedia.org/wiki/Matrix_decomposition","data":{"page":"Matrix_decomposition","wiki":"https://en.wikipedia.org/","lang":"en"},"internal":false,"protocol":"wiki","key":"a0A0cATmCn"},{"type":"text","value":" from linear algebra, the Singular Value Decomposition, to generate a compressed approximation of an image. We’ll use the ","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"key":"YXt0sfx6Le"},{"type":"inlineCode","value":"face","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"key":"IBpEYY2LE3"},{"type":"text","value":" image from the ","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"key":"dYdIzlNLcK"},{"type":"link","url":"https://docs.scipy.org/doc/scipy/reference/datasets.html","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"children":[{"type":"text","value":"scipy.datasets","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"key":"SOoBvWsfTL"}],"urlSource":"https://docs.scipy.org/doc/scipy/reference/datasets.html","key":"vNeycYvGHH"},{"type":"text","value":" module:","position":{"start":{"line":39,"column":1},"end":{"line":39,"column":1}},"key":"hoYtCDtAJI"}],"key":"mygVzSMhNB"}],"key":"mUEedRg3Fz"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"from scipy.datasets import face\n\nimg = face()","key":"V16AcpPB5U"},{"type":"outputs","id":"e5rgfo4tZ4K3SGosfJyym","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"stream","name":"stderr","text":"Downloading file 'face.dat' from 'https://raw.githubusercontent.com/scipy/dataset-face/main/face.dat' to '/home/runner/.cache/scipy-data'.\n"},"key":"RiTvoMh89V"}],"key":"dSRvAx8K7n"}],"key":"AvwxUSMzcT"},{"type":"block","children":[{"type":"admonition","kind":"note","children":[{"type":"admonitionTitle","children":[{"type":"text","value":"Note","key":"BaojllghAx"}],"key":"KPuY1Uxbi3"},{"type":"paragraph","position":{"start":{"line":48,"column":1},"end":{"line":57,"column":1}},"children":[{"type":"text","value":"If you prefer, you can use your own image as you work through this tutorial.\nIn order to transform your image into a NumPy array that can be manipulated, you\ncan use the ","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"jabEWmrzWV"},{"type":"inlineCode","value":"imread","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"JDfILwjjN9"},{"type":"text","value":" function from the\n","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"vnExUS8pK0"},{"type":"link","url":"https://matplotlib.org/api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"children":[{"type":"text","value":"matplotlib.pyplot","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"Ak8PjRyRXN"}],"urlSource":"https://matplotlib.org/api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot","key":"Knxn4IEpYB"},{"type":"text","value":" submodule.\nAlternatively, you can use the\n","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"aNhMYB40rP"},{"type":"link","url":"https://imageio.readthedocs.io/en/stable/_autosummary/imageio.v3.imread.html","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"children":[{"type":"text","value":"imageio.imread","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"H90Qvg0AGK"}],"urlSource":"https://imageio.readthedocs.io/en/stable/_autosummary/imageio.v3.imread.html","key":"JdjTHmOiqu"},{"type":"text","value":"\nfunction from the ","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"jYrACfXQtQ"},{"type":"inlineCode","value":"imageio","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"T3tIudhGra"},{"type":"text","value":" library.\nBe aware that if you use your own image, you’ll likely need to adapt the steps below.\nFor more information on how images are treated when converted to NumPy arrays,\nsee ","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"TzvzgGLT9J"},{"type":"link","url":"https://scikit-image.org/docs/stable/user_guide/numpy_images.html","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"children":[{"type":"text","value":"A crash course on NumPy for images","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"tnrYRsRZAY"}],"urlSource":"https://scikit-image.org/docs/stable/user_guide/numpy_images.html","key":"BVPNA96IrY"},{"type":"text","value":" from the ","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"wsBUckPMPI"},{"type":"inlineCode","value":"scikit-image","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"LTo9HGeEMp"},{"type":"text","value":" documentation.","position":{"start":{"line":48,"column":1},"end":{"line":48,"column":1}},"key":"kGmmeSOmyM"}],"key":"mPhvgcqhGQ"}],"key":"PFWaCExHvz"}],"key":"bvZoeO8PRn"},{"type":"block","position":{"start":{"line":60,"column":1},"end":{"line":60,"column":1}},"children":[{"type":"paragraph","position":{"start":{"line":62,"column":1},"end":{"line":62,"column":1}},"children":[{"type":"text","value":"Now, ","position":{"start":{"line":62,"column":1},"end":{"line":62,"column":1}},"key":"itn7Tbw7pV"},{"type":"inlineCode","value":"img","position":{"start":{"line":62,"column":1},"end":{"line":62,"column":1}},"key":"tBMBtOR7C4"},{"type":"text","value":" is a NumPy array, as we can see when using the ","position":{"start":{"line":62,"column":1},"end":{"line":62,"column":1}},"key":"hfy9n1UEkW"},{"type":"inlineCode","value":"type","position":{"start":{"line":62,"column":1},"end":{"line":62,"column":1}},"key":"Eui5L2hCWb"},{"type":"text","value":" function:","position":{"start":{"line":62,"column":1},"end":{"line":62,"column":1}},"key":"NWiYDHjMz8"}],"key":"E73zEugZts"}],"key":"l2YGpw6FOY"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"type(img)","key":"kR2g5ZqraG"},{"type":"outputs","id":"nU_Iql_qzHAVAlxOEoxkI","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":2,"metadata":{},"data":{"text/plain":{"content":"numpy.ndarray","content_type":"text/plain"}}},"key":"jt9bWHZnhY"}],"key":"uPnEqjpJ8B"}],"key":"FZ4wTwmrPO"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":68,"column":1},"end":{"line":68,"column":1}},"children":[{"type":"text","value":"We can see the image using the ","position":{"start":{"line":68,"column":1},"end":{"line":68,"column":1}},"key":"NYihsQBwTW"},{"type":"link","url":"https://matplotlib.org/api/_as_gen/matplotlib.pyplot.imshow.html#matplotlib.pyplot.imshow","position":{"start":{"line":68,"column":1},"end":{"line":68,"column":1}},"children":[{"type":"text","value":"matplotlib.pyplot.imshow","position":{"start":{"line":68,"column":1},"end":{"line":68,"column":1}},"key":"LJQLvwZMu1"}],"urlSource":"https://matplotlib.org/api/_as_gen/matplotlib.pyplot.imshow.html#matplotlib.pyplot.imshow","key":"pQdAJQ4Fv2"},{"type":"text","value":" function \u0026 the special iPython command, ","position":{"start":{"line":68,"column":1},"end":{"line":68,"column":1}},"key":"VjdbKc7FYI"},{"type":"inlineCode","value":"%matplotlib inline","position":{"start":{"line":68,"column":1},"end":{"line":68,"column":1}},"key":"DI0cvKJn0d"},{"type":"text","value":" to display plots inline:","position":{"start":{"line":68,"column":1},"end":{"line":68,"column":1}},"key":"W0DQcgQffR"}],"key":"RFK1ZYzevN"}],"key":"uEdN4cNwZ1"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"import matplotlib.pyplot as plt\n\n%matplotlib inline","key":"lmTpOInRjZ"},{"type":"outputs","id":"_DGSEI5k4Zw-erPdlNh00","children":[],"key":"p0NWR33DkQ"}],"key":"pgXd8U3dbf"},{"type":"block","children":[],"key":"y5FE2ascgV"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"fig, ax = plt.subplots()\nax.imshow(img)","key":"BMBhvfedcc"},{"type":"outputs","id":"KhsGEMGJg0K7oR1yTiQsI","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"display_data","metadata":{},"data":{"text/plain":{"content":"\u003cFigure size 640x480 with 1 Axes\u003e","content_type":"text/plain"},"image/png":{"content_type":"image/png","hash":"a70fadc37715fe59e0c9ec532ed344ed","path":"/numpy-tutorials/build/a70fadc37715fe59e0c9ec532ed344ed.png"}}},"key":"RM1m47kDAu"}],"key":"CGzs6ITABK"}],"key":"p5wceLnxy6"},{"type":"block","children":[{"type":"heading","depth":3,"position":{"start":{"line":81,"column":1},"end":{"line":81,"column":1}},"children":[{"type":"text","value":"Shape, axis and array properties","position":{"start":{"line":81,"column":1},"end":{"line":81,"column":1}},"key":"q1Mf1hmMHv"}],"identifier":"shape-axis-and-array-properties","label":"Shape, axis and array properties","html_id":"shape-axis-and-array-properties","implicit":true,"key":"o9Bfu8lpH9"},{"type":"paragraph","position":{"start":{"line":83,"column":1},"end":{"line":83,"column":1}},"children":[{"type":"text","value":"Note that, in linear algebra, the dimension of a vector refers to the number of entries in an array. In NumPy, it instead defines the number of axes. For example, a 1D array is a vector such as ","position":{"start":{"line":83,"column":1},"end":{"line":83,"column":1}},"key":"gz7YD9IGaC"},{"type":"inlineCode","value":"[1, 2, 3]","position":{"start":{"line":83,"column":1},"end":{"line":83,"column":1}},"key":"hbWXKy5mdD"},{"type":"text","value":", a 2D array is a matrix, and so forth.","position":{"start":{"line":83,"column":1},"end":{"line":83,"column":1}},"key":"u3Zg9BhhBR"}],"key":"isjSuwJHce"},{"type":"paragraph","position":{"start":{"line":85,"column":1},"end":{"line":85,"column":1}},"children":[{"type":"text","value":"First, let’s check for the shape of the data in our array. Since this image is two-dimensional (the pixels in the image form a rectangle), we might expect a two-dimensional array to represent it (a matrix). However, using the ","position":{"start":{"line":85,"column":1},"end":{"line":85,"column":1}},"key":"p1FeIEBOJ4"},{"type":"inlineCode","value":"shape","position":{"start":{"line":85,"column":1},"end":{"line":85,"column":1}},"key":"XXYIRh6aMx"},{"type":"text","value":" property of this NumPy array gives us a different result:","position":{"start":{"line":85,"column":1},"end":{"line":85,"column":1}},"key":"iKpINXcn2D"}],"key":"FCtUDM0CB4"}],"key":"bJMpsxlVNV"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img.shape","key":"qLvFU625B9"},{"type":"outputs","id":"wtQZCvuwBDUzrbRSYnTUQ","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":5,"metadata":{},"data":{"text/plain":{"content":"(768, 1024, 3)","content_type":"text/plain"}}},"key":"YhA5i4lGMD"}],"key":"UIJAmkBy8q"}],"key":"y9TCbbM0Jc"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":91,"column":1},"end":{"line":91,"column":1}},"children":[{"type":"text","value":"The output is a ","position":{"start":{"line":91,"column":1},"end":{"line":91,"column":1}},"key":"ZFXrEHUquJ"},{"type":"link","url":"https://docs.python.org/dev/tutorial/datastructures.html#tut-tuples","position":{"start":{"line":91,"column":1},"end":{"line":91,"column":1}},"children":[{"type":"text","value":"tuple","position":{"start":{"line":91,"column":1},"end":{"line":91,"column":1}},"key":"pANzN3vX7A"}],"urlSource":"https://docs.python.org/dev/tutorial/datastructures.html#tut-tuples","key":"bT9f5kBQkg"},{"type":"text","value":" with three elements, which means that this is a three-dimensional array. Since this is a color image, and we have used the ","position":{"start":{"line":91,"column":1},"end":{"line":91,"column":1}},"key":"UuhruBtDkl"},{"type":"inlineCode","value":"imread","position":{"start":{"line":91,"column":1},"end":{"line":91,"column":1}},"key":"JuFO0KnyRB"},{"type":"text","value":" function to read it, the data is organized as a 768×1024 grid of pixels, where each pixel contains 3 values representing color channels (red, green and blue - RGB). You can see this by looking at the shape, where the leftmost number corresponds to the outermost axis (image height), the middle number to the next axis (image width) and the rightmost number to the innermost axis (the color channels).","position":{"start":{"line":91,"column":1},"end":{"line":91,"column":1}},"key":"jArT3P6YQM"}],"key":"t23yfCfKfu"},{"type":"paragraph","position":{"start":{"line":93,"column":1},"end":{"line":93,"column":1}},"children":[{"type":"text","value":"Furthermore, using the ","position":{"start":{"line":93,"column":1},"end":{"line":93,"column":1}},"key":"uYkgfGTHox"},{"type":"inlineCode","value":"ndim","position":{"start":{"line":93,"column":1},"end":{"line":93,"column":1}},"key":"oMgfnwhmi6"},{"type":"text","value":" property of this array, we can see that","position":{"start":{"line":93,"column":1},"end":{"line":93,"column":1}},"key":"a7zIMPYCDG"}],"key":"VrMIfYqBqQ"}],"key":"LMOPx67lMR"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img.ndim","key":"ZXYbE4l4Ip"},{"type":"outputs","id":"DiUOoXTGBxonfv0vWA_c4","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":6,"metadata":{},"data":{"text/plain":{"content":"3","content_type":"text/plain"}}},"key":"KCWNOmMqHP"}],"key":"itw4TCzgSn"}],"key":"RhaCct5Nbe"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"children":[{"type":"text","value":"NumPy refers to each dimension as an ","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"key":"cjcC4Vf5Gl"},{"type":"emphasis","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"children":[{"type":"text","value":"axis","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"key":"UPWm0r0fYn"}],"key":"wrUPBqv7Aq"},{"type":"text","value":". Because of how ","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"key":"r8IhRoYNR3"},{"type":"inlineCode","value":"imread","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"key":"qR1OTvLmE2"},{"type":"text","value":" works, the ","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"key":"uAaEdF0UrY"},{"type":"emphasis","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"children":[{"type":"text","value":"first index in the 3rd axis","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"key":"vte0LXOvYH"}],"key":"xPjs5Vm05K"},{"type":"text","value":" is the red pixel data for our image. We can access this by using the syntax","position":{"start":{"line":99,"column":1},"end":{"line":99,"column":1}},"key":"LV2yIY2FGO"}],"key":"fWrXak6OK9"}],"key":"lYdrPQIStf"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img[:, :, 0]","key":"r1jMz6sTc9"},{"type":"outputs","id":"TT1Ti6-oHIN5izFLp64Ev","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":7,"metadata":{},"data":{"text/plain":{"content":"array([[121, 138, 153, ..., 119, 131, 139],\n [ 89, 110, 130, ..., 118, 134, 146],\n [ 73, 94, 115, ..., 117, 133, 144],\n ...,\n [ 87, 94, 107, ..., 120, 119, 119],\n [ 85, 95, 112, ..., 121, 120, 120],\n [ 85, 97, 111, ..., 120, 119, 118]],\n shape=(768, 1024), dtype=uint8)","content_type":"text/plain"}}},"key":"agj3ELtOAD"}],"key":"GX8uobmxlx"}],"key":"z6miQGVZZw"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":105,"column":1},"end":{"line":106,"column":1}},"children":[{"type":"text","value":"From the output above, we can see that every value in ","position":{"start":{"line":105,"column":1},"end":{"line":105,"column":1}},"key":"Hido7Pc7cE"},{"type":"inlineCode","value":"img[:, :, 0]","position":{"start":{"line":105,"column":1},"end":{"line":105,"column":1}},"key":"F1XoKjDjrd"},{"type":"text","value":" is an integer value between 0 and 255, representing the level of red in each corresponding image pixel (keep in mind that this might be different if you\nuse your own image instead of ","position":{"start":{"line":105,"column":1},"end":{"line":105,"column":1}},"key":"uH3TvKEIcH"},{"type":"link","url":"https://docs.scipy.org/doc/scipy/reference/generated/scipy.datasets.face.html","position":{"start":{"line":105,"column":1},"end":{"line":105,"column":1}},"children":[{"type":"text","value":"scipy.datasets.face","position":{"start":{"line":105,"column":1},"end":{"line":105,"column":1}},"key":"mGCrWLVlXU"}],"urlSource":"https://docs.scipy.org/doc/scipy/reference/generated/scipy.datasets.face.html","key":"nviZFJmp2z"},{"type":"text","value":").","position":{"start":{"line":105,"column":1},"end":{"line":105,"column":1}},"key":"SL8wZGDL4m"}],"key":"syGPOX9Oc7"},{"type":"paragraph","position":{"start":{"line":108,"column":1},"end":{"line":108,"column":1}},"children":[{"type":"text","value":"As expected, this is a 768x1024 matrix:","position":{"start":{"line":108,"column":1},"end":{"line":108,"column":1}},"key":"EsjKkIJlEj"}],"key":"lJWvOAFhI5"}],"key":"cbYXxTegTM"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img[:, :, 0].shape","key":"kA2jVklcrf"},{"type":"outputs","id":"6FKE0QwXXMre_NoIjv_QX","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":8,"metadata":{},"data":{"text/plain":{"content":"(768, 1024)","content_type":"text/plain"}}},"key":"TvsLDBeX8k"}],"key":"EJrbajlpxe"}],"key":"vEhswiQ01h"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":114,"column":1},"end":{"line":114,"column":1}},"children":[{"type":"text","value":"Since we are going to perform linear algebra operations on this data, it might be more interesting to have real numbers between 0 and 1 in each entry of the matrices to represent the RGB values. We can do that by setting","position":{"start":{"line":114,"column":1},"end":{"line":114,"column":1}},"key":"JHbgAaU6J6"}],"key":"cWxOLvt8Q1"}],"key":"C0o6lzgOBk"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img_array = img / 255","key":"kpnKqdi5LR"},{"type":"outputs","id":"pUzpyIYrFV1gjQ2Mgdzye","children":[],"key":"M0JXk56uZY"}],"key":"DGd2KQjB7b"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":120,"column":1},"end":{"line":120,"column":1}},"children":[{"type":"text","value":"This operation, dividing an array by a scalar, works because of NumPy’s ","position":{"start":{"line":120,"column":1},"end":{"line":120,"column":1}},"key":"aaMlMojMVi"},{"type":"link","url":"https://numpy.org/devdocs/user/theory.broadcasting.html#array-broadcasting-in-numpy","position":{"start":{"line":120,"column":1},"end":{"line":120,"column":1}},"children":[{"type":"text","value":"broadcasting rules","position":{"start":{"line":120,"column":1},"end":{"line":120,"column":1}},"key":"ORTxaPyIy4"}],"urlSource":"https://numpy.org/devdocs/user/theory.broadcasting.html#array-broadcasting-in-numpy","key":"XoOUgz3bbD"},{"type":"text","value":".","position":{"start":{"line":120,"column":1},"end":{"line":120,"column":1}},"key":"XQGljrFGv3"}],"key":"BiZzyVyphb"},{"type":"admonition","kind":"tip","children":[{"type":"admonitionTitle","children":[{"type":"text","value":"Tip","key":"ZpKyJ1l2T9"}],"key":"e1hyMbNEiV"},{"type":"paragraph","position":{"start":{"line":123,"column":1},"end":{"line":125,"column":1}},"children":[{"type":"text","value":"In real-world applications, it may be better to use, for example, the\n","position":{"start":{"line":123,"column":1},"end":{"line":123,"column":1}},"key":"w3gDoRC5Zm"},{"type":"link","url":"https://scikit-image.org/docs/stable/api/skimage.html#skimage.img_as_float","position":{"start":{"line":123,"column":1},"end":{"line":123,"column":1}},"children":[{"type":"text","value":"img_as_float","position":{"start":{"line":123,"column":1},"end":{"line":123,"column":1}},"key":"yxy2lf990s"}],"urlSource":"https://scikit-image.org/docs/stable/api/skimage.html#skimage.img_as_float","key":"M41KBclJIN"},{"type":"text","value":"\nutility function from ","position":{"start":{"line":123,"column":1},"end":{"line":123,"column":1}},"key":"OoWO5fXDye"},{"type":"inlineCode","value":"scikit-image","position":{"start":{"line":123,"column":1},"end":{"line":123,"column":1}},"key":"o6dA7ptUor"},{"type":"text","value":".","position":{"start":{"line":123,"column":1},"end":{"line":123,"column":1}},"key":"wYAzd9LA6O"}],"key":"ZCrS8g6EVH"}],"key":"EcotidBBA4"},{"type":"paragraph","position":{"start":{"line":128,"column":1},"end":{"line":129,"column":1}},"children":[{"type":"text","value":"You can check that the above works by doing some tests; for example, inquiring\nabout maximum and minimum values for this array:","position":{"start":{"line":128,"column":1},"end":{"line":128,"column":1}},"key":"HARmAn8Jut"}],"key":"rtkh5Xx6fw"}],"key":"AVvlH6nLFF"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img_array.min(), img_array.max()","key":"CvbuMJo9W5"},{"type":"outputs","id":"rapLz3p0e6AGhjfmsiY_A","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":10,"metadata":{},"data":{"text/plain":{"content":"(np.float64(0.0), np.float64(1.0))","content_type":"text/plain"}}},"key":"wlBX3Itljr"}],"key":"ZlI8MpZVSW"}],"key":"te3q3xUr21"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":135,"column":1},"end":{"line":135,"column":1}},"children":[{"type":"text","value":"or checking the type of data in the array:","position":{"start":{"line":135,"column":1},"end":{"line":135,"column":1}},"key":"R7AzblrTal"}],"key":"PDUW1d1Xvz"}],"key":"EMCaddxCMZ"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img_array.dtype","key":"MlhH2ANaKN"},{"type":"outputs","id":"g8_XdKGLwP2sKobl1M5rx","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":11,"metadata":{},"data":{"text/plain":{"content":"dtype('float64')","content_type":"text/plain"}}},"key":"asi3iuX4nG"}],"key":"wd8nuAoJUs"}],"key":"YQ4cFJ8hom"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":141,"column":1},"end":{"line":141,"column":1}},"children":[{"type":"text","value":"Note that we can assign each color channel to a separate matrix using the slice syntax:","position":{"start":{"line":141,"column":1},"end":{"line":141,"column":1}},"key":"Nz9Qlmu3Vv"}],"key":"kN7X6B4F6J"}],"key":"B6xH2k9hyd"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"red_array = img_array[:, :, 0]\ngreen_array = img_array[:, :, 1]\nblue_array = img_array[:, :, 2]","key":"z4OJ8VzuOc"},{"type":"outputs","id":"_BrLWDGn9SKOg_t_HegvW","children":[],"key":"k9C7GOE6ui"}],"key":"xocBa4YIHH"},{"type":"block","children":[{"type":"heading","depth":3,"position":{"start":{"line":149,"column":1},"end":{"line":149,"column":1}},"children":[{"type":"text","value":"Operations on an axis","position":{"start":{"line":149,"column":1},"end":{"line":149,"column":1}},"key":"hOUuWqzsPD"}],"identifier":"operations-on-an-axis","label":"Operations on an axis","html_id":"operations-on-an-axis","implicit":true,"key":"RXbGaeWXgq"},{"type":"paragraph","position":{"start":{"line":151,"column":1},"end":{"line":151,"column":1}},"children":[{"type":"text","value":"It is possible to use methods from linear algebra to approximate an existing set of data. Here, we will use the ","position":{"start":{"line":151,"column":1},"end":{"line":151,"column":1}},"key":"JMtCJupvHk"},{"type":"link","url":"https://en.wikipedia.org/wiki/Singular_value_decomposition","position":{"start":{"line":151,"column":1},"end":{"line":151,"column":1}},"children":[{"type":"text","value":"SVD (Singular Value Decomposition)","position":{"start":{"line":151,"column":1},"end":{"line":151,"column":1}},"key":"rm2DL77V25"}],"urlSource":"https://en.wikipedia.org/wiki/Singular_value_decomposition","data":{"page":"Singular_value_decomposition","wiki":"https://en.wikipedia.org/","lang":"en"},"internal":false,"protocol":"wiki","key":"SnkHY2K2Ci"},{"type":"text","value":" to try to rebuild an image that uses less singular value information than the original one, while still retaining some of its features.","position":{"start":{"line":151,"column":1},"end":{"line":151,"column":1}},"key":"PmFqKPJYuk"}],"key":"vmcMuWva9P"}],"key":"VdrOEuQ0zV"},{"type":"block","position":{"start":{"line":153,"column":1},"end":{"line":153,"column":1}},"children":[{"type":"admonition","kind":"note","children":[{"type":"admonitionTitle","children":[{"type":"text","value":"Note","key":"LwcpXev3Fe"}],"key":"BEY2Wrbc2A"},{"type":"paragraph","position":{"start":{"line":156,"column":1},"end":{"line":166,"column":1}},"children":[{"type":"text","value":"We will use NumPy’s linear algebra module,\n","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"wXEW2g6sVX"},{"type":"link","url":"https://numpy.org/devdocs/reference/routines.linalg.html#module-numpy.linalg","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"children":[{"type":"text","value":"numpy.linalg","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"W9bQ7lZcwG"}],"urlSource":"https://numpy.org/devdocs/reference/routines.linalg.html#module-numpy.linalg","key":"cOrjjxuHzf"},{"type":"text","value":",\nto perform the operations in this tutorial.\nMost of the linear algebra functions in this module can also be found in\n","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"wl4zIEBLAg"},{"type":"link","url":"https://docs.scipy.org/doc/scipy/reference/linalg.html#module-scipy.linalg","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"children":[{"type":"text","value":"scipy.linalg","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"gEdfEXjqm1"}],"urlSource":"https://docs.scipy.org/doc/scipy/reference/linalg.html#module-scipy.linalg","key":"jiUVaX3Qpn"},{"type":"text","value":",\nand users are encouraged to use the ","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"iMV6yyy7Vc"},{"type":"link","url":"https://docs.scipy.org/doc/scipy/reference/index.html#module-scipy","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"children":[{"type":"text","value":"scipy","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"HCfzoRVT6w"}],"urlSource":"https://docs.scipy.org/doc/scipy/reference/index.html#module-scipy","key":"RgndqjR1Ty"},{"type":"text","value":"\nmodule for real-world applications.\nHowever, some functions in the\n","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"HCf97Z9wuV"},{"type":"link","url":"https://docs.scipy.org/doc/scipy/reference/linalg.html#module-scipy.linalg","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"children":[{"type":"text","value":"scipy.linalg","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"nD31WN2Xn1"}],"urlSource":"https://docs.scipy.org/doc/scipy/reference/linalg.html#module-scipy.linalg","key":"vXlflw4UkQ"},{"type":"text","value":"\nmodule, such as the SVD function, only support 2D arrays.\nFor more information on this, check the ","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"c8sXxCrPYK"},{"type":"link","url":"https://docs.scipy.org/doc/scipy/tutorial/linalg.html","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"children":[{"type":"text","value":"scipy.linalg page","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"k3JXTHZ41r"}],"urlSource":"https://docs.scipy.org/doc/scipy/tutorial/linalg.html","key":"KjKRL5ROLy"},{"type":"text","value":".","position":{"start":{"line":156,"column":1},"end":{"line":156,"column":1}},"key":"TxFavuE7NT"}],"key":"AO287xTX6l"}],"key":"afSuFpgI9v"}],"key":"z9Kq0w97ur"},{"type":"block","position":{"start":{"line":169,"column":1},"end":{"line":169,"column":1}},"children":[{"type":"paragraph","position":{"start":{"line":171,"column":1},"end":{"line":171,"column":1}},"children":[{"type":"text","value":"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 ","position":{"start":{"line":171,"column":1},"end":{"line":171,"column":1}},"key":"R6clb305yq"},{"type":"inlineMath","value":"A","position":{"start":{"line":171,"column":1},"end":{"line":171,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eA\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eA\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003eA\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"V2deXSMjgx"},{"type":"text","value":", the following product can be computed:","position":{"start":{"line":171,"column":1},"end":{"line":171,"column":1}},"key":"kZdB68iuEr"}],"key":"IdFFJ0t1Dj"},{"type":"math","value":"U \\Sigma V^T = A","position":{"start":{"line":173,"column":1},"end":{"line":173,"column":1}},"html":"\u003cspan class=\"katex-display\"\u003e\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eU\u003c/mi\u003e\u003cmi mathvariant=\"normal\"\u003eΣ\u003c/mi\u003e\u003cmsup\u003e\u003cmi\u003eV\u003c/mi\u003e\u003cmi\u003eT\u003c/mi\u003e\u003c/msup\u003e\u003cmo\u003e=\u003c/mo\u003e\u003cmi\u003eA\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eU \\Sigma V^T = A\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.8913em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.10903em;\"\u003eU\u003c/span\u003e\u003cspan class=\"mord\"\u003eΣ\u003c/span\u003e\u003cspan class=\"mord\"\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.22222em;\"\u003eV\u003c/span\u003e\u003cspan class=\"msupsub\"\u003e\u003cspan class=\"vlist-t\"\u003e\u003cspan class=\"vlist-r\"\u003e\u003cspan class=\"vlist\" style=\"height:0.8913em;\"\u003e\u003cspan style=\"top:-3.113em;margin-right:0.05em;\"\u003e\u003cspan class=\"pstrut\" style=\"height:2.7em;\"\u003e\u003c/span\u003e\u003cspan class=\"sizing reset-size6 size3 mtight\"\u003e\u003cspan class=\"mord mathnormal mtight\" style=\"margin-right:0.13889em;\"\u003eT\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2778em;\"\u003e\u003c/span\u003e\u003cspan class=\"mrel\"\u003e=\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2778em;\"\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003eA\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","enumerator":"1","key":"bvsqQhq2QF"},{"type":"paragraph","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"children":[{"type":"text","value":"where ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"qIitLIBxNL"},{"type":"inlineMath","value":"U","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eU\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eU\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.10903em;\"\u003eU\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"xpTdgnJP9c"},{"type":"text","value":" and ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"jXArW37TXQ"},{"type":"inlineMath","value":"V^T","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmsup\u003e\u003cmi\u003eV\u003c/mi\u003e\u003cmi\u003eT\u003c/mi\u003e\u003c/msup\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eV^T\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.8413em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.22222em;\"\u003eV\u003c/span\u003e\u003cspan class=\"msupsub\"\u003e\u003cspan class=\"vlist-t\"\u003e\u003cspan class=\"vlist-r\"\u003e\u003cspan class=\"vlist\" style=\"height:0.8413em;\"\u003e\u003cspan style=\"top:-3.063em;margin-right:0.05em;\"\u003e\u003cspan class=\"pstrut\" style=\"height:2.7em;\"\u003e\u003c/span\u003e\u003cspan class=\"sizing reset-size6 size3 mtight\"\u003e\u003cspan class=\"mord mathnormal mtight\" style=\"margin-right:0.13889em;\"\u003eT\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"bc0b8iriS4"},{"type":"text","value":" are square and ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"kX3INSVgzo"},{"type":"inlineMath","value":"\\Sigma","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi mathvariant=\"normal\"\u003eΣ\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003e\\Sigma\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003eΣ\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"d866iQsvjF"},{"type":"text","value":" is the same size as ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"hbR6eliIgR"},{"type":"inlineMath","value":"A","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eA\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eA\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003eA\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"UdaMXqiJg6"},{"type":"text","value":". ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"O2uqWBzh8J"},{"type":"inlineMath","value":"\\Sigma","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi mathvariant=\"normal\"\u003eΣ\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003e\\Sigma\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003eΣ\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"ziEwp9igWD"},{"type":"text","value":" is a diagonal matrix and contains the ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"seJj7u0o6p"},{"type":"link","url":"https://en.wikipedia.org/wiki/Singular_value","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"children":[{"type":"text","value":"singular values","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"fFIbW6b6Iw"}],"urlSource":"https://en.wikipedia.org/wiki/Singular_value","data":{"page":"Singular_value","wiki":"https://en.wikipedia.org/","lang":"en"},"internal":false,"protocol":"wiki","key":"LJaCmAN642"},{"type":"text","value":" of ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"mhhtPERwt5"},{"type":"inlineMath","value":"A","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eA\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eA\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003eA\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"MekZ16fsHb"},{"type":"text","value":", organized from largest to smallest. These values are always non-negative and can be used as an indicator of the “importance” of some features represented by the matrix ","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"sHl568UK9h"},{"type":"inlineMath","value":"A","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eA\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eA\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003eA\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"rBG07rx2ky"},{"type":"text","value":".","position":{"start":{"line":175,"column":1},"end":{"line":175,"column":1}},"key":"FdZwiI5Vh5"}],"key":"Izkno2bXsY"},{"type":"paragraph","position":{"start":{"line":177,"column":1},"end":{"line":178,"column":1}},"children":[{"type":"text","value":"Let’s see how this works in practice with just one matrix first. Note that according to ","position":{"start":{"line":177,"column":1},"end":{"line":177,"column":1}},"key":"glmiPWMYxM"},{"type":"link","url":"https://en.wikipedia.org/wiki/Grayscale#Colorimetric_(perceptual_luminance-preserving)_conversion_to_grayscale","position":{"start":{"line":177,"column":1},"end":{"line":177,"column":1}},"children":[{"type":"text","value":"colorimetry","position":{"start":{"line":177,"column":1},"end":{"line":177,"column":1}},"key":"iNjNbXN9r7"}],"urlSource":"https://en.wikipedia.org/wiki/Grayscale#Colorimetric_(perceptual_luminance-preserving)_conversion_to_grayscale","data":{"page":"Grayscale#Colorimetric_(perceptual_luminance-preserving)_conversion_to_grayscale","wiki":"https://en.wikipedia.org/","lang":"en"},"internal":false,"protocol":"wiki","key":"dcqAlelMKM"},{"type":"text","value":",\nit is possible to obtain a fairly reasonable grayscale version of our color image if we apply the formula","position":{"start":{"line":177,"column":1},"end":{"line":177,"column":1}},"key":"gmnBZ0CFMs"}],"key":"FxxuBMGsRf"},{"type":"math","value":"Y = 0.2126 R + 0.7152 G + 0.0722 B","position":{"start":{"line":180,"column":1},"end":{"line":180,"column":1}},"html":"\u003cspan class=\"katex-display\"\u003e\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eY\u003c/mi\u003e\u003cmo\u003e=\u003c/mo\u003e\u003cmn\u003e0.2126\u003c/mn\u003e\u003cmi\u003eR\u003c/mi\u003e\u003cmo\u003e+\u003c/mo\u003e\u003cmn\u003e0.7152\u003c/mn\u003e\u003cmi\u003eG\u003c/mi\u003e\u003cmo\u003e+\u003c/mo\u003e\u003cmn\u003e0.0722\u003c/mn\u003e\u003cmi\u003eB\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eY = 0.2126 R + 0.7152 G + 0.0722 B\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.22222em;\"\u003eY\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2778em;\"\u003e\u003c/span\u003e\u003cspan class=\"mrel\"\u003e=\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2778em;\"\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003e0.2126\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.00773em;\"\u003eR\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2222em;\"\u003e\u003c/span\u003e\u003cspan class=\"mbin\"\u003e+\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2222em;\"\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.7667em;vertical-align:-0.0833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003e0.7152\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003eG\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2222em;\"\u003e\u003c/span\u003e\u003cspan class=\"mbin\"\u003e+\u003c/span\u003e\u003cspan class=\"mspace\" style=\"margin-right:0.2222em;\"\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003e0.0722\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.05017em;\"\u003eB\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","enumerator":"2","key":"b1hjBHMQ48"},{"type":"paragraph","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"children":[{"type":"text","value":"where ","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"bb0UlJ3Ajh"},{"type":"inlineMath","value":"Y","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eY\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eY\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.22222em;\"\u003eY\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"xqkSaSzvvx"},{"type":"text","value":" is the array representing the grayscale image, and ","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"cqzfzWtp1t"},{"type":"inlineMath","value":"R","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eR\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eR\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.00773em;\"\u003eR\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"K2eXyUd0mv"},{"type":"text","value":", ","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"eWScex7LUo"},{"type":"inlineMath","value":"G","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eG\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eG\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\"\u003eG\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"Jx7LbIfkM7"},{"type":"text","value":" and ","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"x5GPOaFEdA"},{"type":"inlineMath","value":"B","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi\u003eB\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003eB\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord mathnormal\" style=\"margin-right:0.05017em;\"\u003eB\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"MJYDtYi3OJ"},{"type":"text","value":" are the red, green and blue channel arrays we had originally. Notice we can use the ","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"sPtKQzKk3o"},{"type":"inlineCode","value":"@","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"VhgL9T0zsu"},{"type":"text","value":" operator (the matrix multiplication operator for NumPy arrays, see ","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"jga6rvsgi5"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"children":[{"type":"text","value":"numpy.matmul","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"fCcMaRQn8g"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul","key":"Yq73XzJ2Dh"},{"type":"text","value":") for this:","position":{"start":{"line":182,"column":1},"end":{"line":182,"column":1}},"key":"jrMTykpViS"}],"key":"GhITGJfuAr"}],"key":"hqSI0QPRlt"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img_gray = img_array @ [0.2126, 0.7152, 0.0722]","key":"U9G6Z3Njnc"},{"type":"outputs","id":"GQGaTKFAK7mcEjRDW0yHk","children":[],"key":"t0d2nq8sdy"}],"key":"FVzivpxclZ"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":188,"column":1},"end":{"line":188,"column":1}},"children":[{"type":"text","value":"Now, ","position":{"start":{"line":188,"column":1},"end":{"line":188,"column":1}},"key":"ZcFFoEUHeh"},{"type":"inlineCode","value":"img_gray","position":{"start":{"line":188,"column":1},"end":{"line":188,"column":1}},"key":"DCf7ucojD3"},{"type":"text","value":" has shape","position":{"start":{"line":188,"column":1},"end":{"line":188,"column":1}},"key":"Bb2mg7YuXZ"}],"key":"bA8QgRPWBd"}],"key":"WoA2DiVrr6"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img_gray.shape","key":"fUfKCeZ2nE"},{"type":"outputs","id":"JYJbDXx4xbbVjfr6l9ik1","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":14,"metadata":{},"data":{"text/plain":{"content":"(768, 1024)","content_type":"text/plain"}}},"key":"eskAOG6yiY"}],"key":"cOkVQ08G3j"}],"key":"otCGLRdUH9"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":194,"column":1},"end":{"line":194,"column":1}},"children":[{"type":"text","value":"To see if this makes sense in our image, we should use a colormap from ","position":{"start":{"line":194,"column":1},"end":{"line":194,"column":1}},"key":"dMGSRXgX6b"},{"type":"inlineCode","value":"matplotlib","position":{"start":{"line":194,"column":1},"end":{"line":194,"column":1}},"key":"TYufdWymBM"},{"type":"text","value":" corresponding to the color we wish to see in out image (otherwise, ","position":{"start":{"line":194,"column":1},"end":{"line":194,"column":1}},"key":"K7orISJxJz"},{"type":"inlineCode","value":"matplotlib","position":{"start":{"line":194,"column":1},"end":{"line":194,"column":1}},"key":"cd8l6Od57m"},{"type":"text","value":" will default to a colormap that does not correspond to the real data).","position":{"start":{"line":194,"column":1},"end":{"line":194,"column":1}},"key":"JJHq5soiDv"}],"key":"fdr7VcCtqf"},{"type":"paragraph","position":{"start":{"line":196,"column":1},"end":{"line":196,"column":1}},"children":[{"type":"text","value":"In our case, we are approximating the grayscale portion of the image, so we will use the colormap ","position":{"start":{"line":196,"column":1},"end":{"line":196,"column":1}},"key":"XKTITizLLz"},{"type":"inlineCode","value":"gray","position":{"start":{"line":196,"column":1},"end":{"line":196,"column":1}},"key":"GWDLmNiJOj"},{"type":"text","value":":","position":{"start":{"line":196,"column":1},"end":{"line":196,"column":1}},"key":"b7rqhd3op4"}],"key":"pnJx3UjUg3"}],"key":"d4ueFP5XYs"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"fig, ax = plt.subplots()\nax.imshow(img_gray, cmap=\"gray\")","key":"efUuxCiMI9"},{"type":"outputs","id":"YI1WsURge2MdNQbGTaenB","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"display_data","metadata":{},"data":{"text/plain":{"content":"\u003cFigure size 640x480 with 1 Axes\u003e","content_type":"text/plain"},"image/png":{"content_type":"image/png","hash":"ae5ff618bce8ea0c89ecbfbdcc1d1f5a","path":"/numpy-tutorials/build/ae5ff618bce8ea0c89ecbfbdcc1d1f5a.png"}}},"key":"lxKxXmcvKB"}],"key":"U0GXQ7jWLs"}],"key":"HVYQ6o3zPL"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":203,"column":1},"end":{"line":203,"column":1}},"children":[{"type":"text","value":"Now, applying the ","position":{"start":{"line":203,"column":1},"end":{"line":203,"column":1}},"key":"jTe7LrXBUe"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.linalg.svd.html#numpy.linalg.svd","position":{"start":{"line":203,"column":1},"end":{"line":203,"column":1}},"children":[{"type":"text","value":"linalg.svd","position":{"start":{"line":203,"column":1},"end":{"line":203,"column":1}},"key":"oBu9To8OCp"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.linalg.svd.html#numpy.linalg.svd","key":"U051PnP4wc"},{"type":"text","value":" function to this matrix, we obtain the following decomposition:","position":{"start":{"line":203,"column":1},"end":{"line":203,"column":1}},"key":"MDQ8egQwHh"}],"key":"iYwPRef2SV"}],"key":"zu6qD0TWJ4"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"import numpy as np\nU, s, Vt = np.linalg.svd(img_gray)","key":"jcD62Kw8JS"},{"type":"outputs","id":"GpvExn95t0FN9KZ9HP5ce","children":[],"key":"fwcP9LAAMx"}],"key":"snZmQFxKr6"},{"type":"block","children":[{"type":"admonition","kind":"note","children":[{"type":"admonitionTitle","children":[{"type":"text","value":"Note","key":"EZ7GC10tce"}],"key":"Pb1SOew8Jt"},{"type":"paragraph","position":{"start":{"line":211,"column":1},"end":{"line":213,"column":1}},"children":[{"type":"text","value":"If you are using your own image, this command might take a while to run,\ndepending on the size of your image and your hardware.\nDon’t worry, this is normal! The SVD can be a pretty intensive computation.","position":{"start":{"line":211,"column":1},"end":{"line":211,"column":1}},"key":"voat07GHt5"}],"key":"CzxlYnGhDA"}],"key":"JRwhMlB5dy"}],"key":"mUjKoYzb96"},{"type":"block","position":{"start":{"line":216,"column":1},"end":{"line":216,"column":1}},"children":[{"type":"paragraph","position":{"start":{"line":218,"column":1},"end":{"line":218,"column":1}},"children":[{"type":"text","value":"Let’s check that this is what we expected:","position":{"start":{"line":218,"column":1},"end":{"line":218,"column":1}},"key":"ba6aAIOpkB"}],"key":"h4xNYVSQM2"}],"key":"q6ZXj18sYI"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"U.shape, s.shape, Vt.shape","key":"NJj6Mtt7q3"},{"type":"outputs","id":"Q2pmsxWRlur9uHrWHeXIW","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":17,"metadata":{},"data":{"text/plain":{"content":"((768, 768), (768,), (1024, 1024))","content_type":"text/plain"}}},"key":"uzIzmkOPnq"}],"key":"J5LtetJmBi"}],"key":"YjzC7RKFLE"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":224,"column":1},"end":{"line":225,"column":1}},"children":[{"type":"text","value":"Note that ","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"udcCO1Ddt8"},{"type":"inlineCode","value":"s","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"IKMlaL9Lyf"},{"type":"text","value":" has a particular shape: it has only one dimension. This means that some linear algebra functions that expect 2d arrays might not work. For example, from the theory, one might expect ","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"hac0JQ87L9"},{"type":"inlineCode","value":"s","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"Lk0otphj92"},{"type":"text","value":" and ","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"MlSc4TQrK8"},{"type":"inlineCode","value":"Vt","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"Sy32bj1ISE"},{"type":"text","value":" to be\ncompatible for multiplication. However, this is not true as ","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"FehftNultk"},{"type":"inlineCode","value":"s","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"CL9EQ7GYFx"},{"type":"text","value":" does not have a second axis:","position":{"start":{"line":224,"column":1},"end":{"line":224,"column":1}},"key":"PZfnKYi0b5"}],"key":"hsonyNCNSv"}],"key":"SqmcB6VITg"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"s @ Vt","visibility":"show","key":"Gplavn5sEy"},{"type":"outputs","id":"UweXLQq5Xo9rxEPyfL494","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"error","traceback":"\u001b[31m---------------------------------------------------------------------------\u001b[39m\n\u001b[31mValueError\u001b[39m Traceback (most recent call last)\n\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[18]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----\u003e \u001b[39m\u001b[32m1\u001b[39m \u001b[43ms\u001b[49m\u001b[43m \u001b[49m\u001b[43m@\u001b[49m\u001b[43m \u001b[49m\u001b[43mVt\u001b[49m\n\n\u001b[31mValueError\u001b[39m: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)-\u003e(n?,m?) (size 1024 is different from 768)","ename":"ValueError","evalue":"matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)-\u003e(n?,m?) (size 1024 is different from 768)"},"key":"qnDm8CDpkz"}],"visibility":"show","key":"uQxzFpWlWS"}],"data":{"tags":["raises-exception"]},"visibility":"show","key":"LEEsOqCSGy"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"children":[{"type":"text","value":"results in a ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"fZHlzCjhK9"},{"type":"inlineCode","value":"ValueError","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"oCwnHD0Mle"},{"type":"text","value":". This happens because having a one-dimensional array for ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"sFeVJyDpBx"},{"type":"inlineCode","value":"s","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"hkKD2ZcYrO"},{"type":"text","value":", 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 ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"wc8erqJ4La"},{"type":"inlineMath","value":"\\Sigma","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi mathvariant=\"normal\"\u003eΣ\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003e\\Sigma\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003eΣ\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"rye6MrW0OX"},{"type":"text","value":" with the elements of ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"aT7eTUUdPx"},{"type":"inlineCode","value":"s","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"EMceQQ8ItJ"},{"type":"text","value":" in its diagonal and with the appropriate dimensions for multiplying: in our case, ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"kA4RWhbQYF"},{"type":"inlineMath","value":"\\Sigma","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"html":"\u003cspan class=\"katex\"\u003e\u003cspan class=\"katex-mathml\"\u003e\u003cmath xmlns=\"http://www.w3.org/1998/Math/MathML\"\u003e\u003csemantics\u003e\u003cmrow\u003e\u003cmi mathvariant=\"normal\"\u003eΣ\u003c/mi\u003e\u003c/mrow\u003e\u003cannotation encoding=\"application/x-tex\"\u003e\\Sigma\u003c/annotation\u003e\u003c/semantics\u003e\u003c/math\u003e\u003c/span\u003e\u003cspan class=\"katex-html\" aria-hidden=\"true\"\u003e\u003cspan class=\"base\"\u003e\u003cspan class=\"strut\" style=\"height:0.6833em;\"\u003e\u003c/span\u003e\u003cspan class=\"mord\"\u003eΣ\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e","key":"EJFjbsRKfg"},{"type":"text","value":" should be 768x1024 since ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"nZzL1TXZqt"},{"type":"inlineCode","value":"U","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"Hsq1oiIINz"},{"type":"text","value":" is 768x768 and ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"UbA6Drt23g"},{"type":"inlineCode","value":"Vt","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"xlvLjC7AZi"},{"type":"text","value":" is 1024x1024. In order to add the singular values to the diagonal of ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"MCaEJwTKnj"},{"type":"inlineCode","value":"Sigma","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"T5gwILCl5W"},{"type":"text","value":", we will use the ","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"XITaKEIU3f"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.fill_diagonal.html","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"children":[{"type":"text","value":"fill_diagonal","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"UCCxWmQJZV"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.fill_diagonal.html","key":"SMbAnaFyZJ"},{"type":"text","value":" function from NumPy:","position":{"start":{"line":232,"column":1},"end":{"line":232,"column":1}},"key":"k4hmceCFcY"}],"key":"hg0sRGqYsE"}],"key":"OSKlyK5PRD"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"Sigma = np.zeros((U.shape[1], Vt.shape[0]))\nnp.fill_diagonal(Sigma, s)","key":"CfU3jCOdjW"},{"type":"outputs","id":"5hfoy_U-XJAgAKTzktdtW","children":[],"key":"EluRKCklBM"}],"key":"ATBHcIVHou"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":239,"column":1},"end":{"line":239,"column":1}},"children":[{"type":"text","value":"Now, we want to check if the reconstructed ","position":{"start":{"line":239,"column":1},"end":{"line":239,"column":1}},"key":"TQcWvSungt"},{"type":"inlineCode","value":"U @ Sigma @ Vt","position":{"start":{"line":239,"column":1},"end":{"line":239,"column":1}},"key":"EdNkUagf8x"},{"type":"text","value":" is close to the original ","position":{"start":{"line":239,"column":1},"end":{"line":239,"column":1}},"key":"zWoPsW82nn"},{"type":"inlineCode","value":"img_gray","position":{"start":{"line":239,"column":1},"end":{"line":239,"column":1}},"key":"kZqOvSHpzF"},{"type":"text","value":" matrix.","position":{"start":{"line":239,"column":1},"end":{"line":239,"column":1}},"key":"lLy1g5vvYF"}],"key":"rlVI8PNfiK"}],"key":"n1uwEZmMEl"},{"type":"block","position":{"start":{"line":241,"column":1},"end":{"line":241,"column":1}},"children":[{"type":"heading","depth":2,"position":{"start":{"line":243,"column":1},"end":{"line":243,"column":1}},"children":[{"type":"text","value":"Approximation","position":{"start":{"line":243,"column":1},"end":{"line":243,"column":1}},"key":"orGvDPEuMF"}],"identifier":"approximation","label":"Approximation","html_id":"approximation","implicit":true,"key":"F7m9tGumyf"},{"type":"paragraph","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"children":[{"type":"text","value":"The ","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"key":"YFQm2ZPjTA"},{"type":"link","url":"https://numpy.org/devdocs/reference/routines.linalg.html#module-numpy.linalg","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"children":[{"type":"text","value":"linalg","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"key":"KMnwdTDPda"}],"urlSource":"https://numpy.org/devdocs/reference/routines.linalg.html#module-numpy.linalg","key":"neCfpux1zw"},{"type":"text","value":" module includes a ","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"key":"Ea2rpaHNzb"},{"type":"inlineCode","value":"norm","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"key":"I68iDdbdf6"},{"type":"text","value":" 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 ","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"key":"HMfZVJCthY"},{"type":"inlineCode","value":"img_gray","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"key":"lF9FcOSGGG"},{"type":"text","value":" and the reconstructed SVD product to be small. As expected, you should see something like","position":{"start":{"line":245,"column":1},"end":{"line":245,"column":1}},"key":"u3ytLU1pTW"}],"key":"QyW3YwxLH4"}],"key":"nt8mFfiClG"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"np.linalg.norm(img_gray - U @ Sigma @ Vt)","key":"WpyWBuRqbI"},{"type":"outputs","id":"yRvoFbSbkoLVeUkBREKFG","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":20,"metadata":{},"data":{"text/plain":{"content":"np.float64(1.4314854759568272e-12)","content_type":"text/plain"}}},"key":"ydnpgREWsa"}],"key":"wAu4vKECz2"}],"key":"uA5RnraHo5"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":251,"column":1},"end":{"line":251,"column":1}},"children":[{"type":"text","value":"(The actual result of this operation might be different depending on your architecture and linear algebra setup. Regardless, you should see a small number.)","position":{"start":{"line":251,"column":1},"end":{"line":251,"column":1}},"key":"higmWqoMZQ"}],"key":"PgkkLfEIEQ"},{"type":"paragraph","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"children":[{"type":"text","value":"We could also have used the ","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"key":"EZytBnG0Mr"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.allclose.html#numpy.allclose","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"children":[{"type":"text","value":"numpy.allclose","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"key":"i7gR5JeYkW"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.allclose.html#numpy.allclose","key":"iEUSAEzAwY"},{"type":"text","value":" function to make sure the reconstructed product is, in fact, ","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"key":"LlynWFdvH9"},{"type":"emphasis","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"children":[{"type":"text","value":"close","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"key":"qbedEHrIcJ"}],"key":"ntWK8VVDDy"},{"type":"text","value":" to our original matrix (the difference between the two arrays is small):","position":{"start":{"line":253,"column":1},"end":{"line":253,"column":1}},"key":"j83BAW4rQ9"}],"key":"Zp6VCsiUqw"}],"key":"nbEQgS5F44"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"np.allclose(img_gray, U @ Sigma @ Vt)","key":"n8EvNipvDQ"},{"type":"outputs","id":"K01mUFNU-S2ILzYwOUJr4","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":21,"metadata":{},"data":{"text/plain":{"content":"True","content_type":"text/plain"}}},"key":"S9BRav8FDv"}],"key":"RLb1DQigfH"}],"key":"szk8PVaqxS"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":259,"column":1},"end":{"line":259,"column":1}},"children":[{"type":"text","value":"To see if an approximation is reasonable, we can check the values in ","position":{"start":{"line":259,"column":1},"end":{"line":259,"column":1}},"key":"r3n1B55FCu"},{"type":"inlineCode","value":"s","position":{"start":{"line":259,"column":1},"end":{"line":259,"column":1}},"key":"SsNiOyCirs"},{"type":"text","value":":","position":{"start":{"line":259,"column":1},"end":{"line":259,"column":1}},"key":"AApqjWmF5O"}],"key":"EFpWECT5ln"}],"key":"x0AHmS8LEX"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"fig, ax = plt.subplots()\nax.plot(s)","key":"x4IQLMWsti"},{"type":"outputs","id":"N3g7THyIENHrBHG9Ve3uh","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"display_data","metadata":{},"data":{"text/plain":{"content":"\u003cFigure size 640x480 with 1 Axes\u003e","content_type":"text/plain"},"image/png":{"content_type":"image/png","hash":"5bffdb870c5e856cb5ffe56f0d2e9372","path":"/numpy-tutorials/build/5bffdb870c5e856cb5ffe56f0d2e9372.png"}}},"key":"bj9I6C8Liz"}],"key":"ZtHzh70gFj"}],"key":"h6z4H8Yy9f"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":266,"column":1},"end":{"line":266,"column":1}},"children":[{"type":"text","value":"In the graph, we can see that although we have 768 singular values in ","position":{"start":{"line":266,"column":1},"end":{"line":266,"column":1}},"key":"i5HpdsSdY7"},{"type":"inlineCode","value":"s","position":{"start":{"line":266,"column":1},"end":{"line":266,"column":1}},"key":"f0NVmO0bO1"},{"type":"text","value":", most of those (after the 150th entry or so) are pretty small. So it might make sense to use only the information related to the first (say, 50) ","position":{"start":{"line":266,"column":1},"end":{"line":266,"column":1}},"key":"IM1YSDGgde"},{"type":"emphasis","position":{"start":{"line":266,"column":1},"end":{"line":266,"column":1}},"children":[{"type":"text","value":"singular values","position":{"start":{"line":266,"column":1},"end":{"line":266,"column":1}},"key":"wsgu9Fg8Gm"}],"key":"zUJQFHKJGh"},{"type":"text","value":" to build a more economical approximation to our image.","position":{"start":{"line":266,"column":1},"end":{"line":266,"column":1}},"key":"N0CpiGZXAP"}],"key":"KJIByEb8bc"},{"type":"paragraph","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"children":[{"type":"text","value":"The idea is to consider all but the first ","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"x0wq4Abs9s"},{"type":"inlineCode","value":"k","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"LqLGWJn0JK"},{"type":"text","value":" singular values in ","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"MJFNmAsjvV"},{"type":"inlineCode","value":"Sigma","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"BGMVMyO49v"},{"type":"text","value":" (which are the same as in ","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"iqgU6YfRDq"},{"type":"inlineCode","value":"s","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"QRLsm8FRJc"},{"type":"text","value":") as zeros, keeping ","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"hvLTnoHSnN"},{"type":"inlineCode","value":"U","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"uevHnIsreo"},{"type":"text","value":" and ","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"QfRnkjO5ei"},{"type":"inlineCode","value":"Vt","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"WcwZouRTS7"},{"type":"text","value":" intact, and computing the product of these matrices as the approximation.","position":{"start":{"line":268,"column":1},"end":{"line":268,"column":1}},"key":"pxTGgABiIn"}],"key":"RD7B4NLd4l"},{"type":"paragraph","position":{"start":{"line":270,"column":1},"end":{"line":270,"column":1}},"children":[{"type":"text","value":"For example, if we choose","position":{"start":{"line":270,"column":1},"end":{"line":270,"column":1}},"key":"fr1MM7qK6e"}],"key":"XYNwIW7Viy"}],"key":"Au9HFhRIr4"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"k = 10","key":"of1SrnCGph"},{"type":"outputs","id":"cONg4YnB-BMzCrTPJKUZR","children":[],"key":"U86RpGJ6LB"}],"key":"hjHLmFOaNA"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":276,"column":1},"end":{"line":276,"column":1}},"children":[{"type":"text","value":"we can build the approximation by doing","position":{"start":{"line":276,"column":1},"end":{"line":276,"column":1}},"key":"RaOw9bvfmJ"}],"key":"NkVuva3eZK"}],"key":"zns9EMFLW5"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"approx = U @ Sigma[:, :k] @ Vt[:k, :]","key":"SVTQx8j2sJ"},{"type":"outputs","id":"HtBtiXW_IR2lUO3h_eRui","children":[],"key":"qVOhvfaEPc"}],"key":"WjhnelZAjP"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":282,"column":1},"end":{"line":282,"column":1}},"children":[{"type":"text","value":"Note that we had to use only the first ","position":{"start":{"line":282,"column":1},"end":{"line":282,"column":1}},"key":"H24svA7oaj"},{"type":"inlineCode","value":"k","position":{"start":{"line":282,"column":1},"end":{"line":282,"column":1}},"key":"a9rmcG8LPQ"},{"type":"text","value":" rows of ","position":{"start":{"line":282,"column":1},"end":{"line":282,"column":1}},"key":"FeRDhCIYM9"},{"type":"inlineCode","value":"Vt","position":{"start":{"line":282,"column":1},"end":{"line":282,"column":1}},"key":"TaWbLEVX4L"},{"type":"text","value":", since all other rows would be multiplied by the zeros corresponding to the singular values we eliminated from this approximation.","position":{"start":{"line":282,"column":1},"end":{"line":282,"column":1}},"key":"ma5OgPxVvw"}],"key":"svnluxGu9M"}],"key":"wf3VoQnMqk"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"fig, ax = plt.subplots()\nax.imshow(approx, cmap=\"gray\")","key":"qOZKarTfW5"},{"type":"outputs","id":"RoEwh7aNSxm432sopwYso","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"display_data","metadata":{},"data":{"text/plain":{"content":"\u003cFigure size 640x480 with 1 Axes\u003e","content_type":"text/plain"},"image/png":{"content_type":"image/png","hash":"0731d9ff394c572db56e83187ed9a359","path":"/numpy-tutorials/build/0731d9ff394c572db56e83187ed9a359.png"}}},"key":"brf4cE7QV5"}],"key":"WgeUfTavQR"}],"key":"iJqS9EPgq8"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":289,"column":1},"end":{"line":289,"column":1}},"children":[{"type":"text","value":"Now, you can go ahead and repeat this experiment with other values of ","position":{"start":{"line":289,"column":1},"end":{"line":289,"column":1}},"key":"ZSAtzwwWWt"},{"type":"inlineCode","value":"k","position":{"start":{"line":289,"column":1},"end":{"line":289,"column":1}},"key":"KR3j2DtVda"},{"type":"text","value":", and each of your experiments should give you a slightly better (or worse) image depending on the value you choose.","position":{"start":{"line":289,"column":1},"end":{"line":289,"column":1}},"key":"cN07x2xVWC"}],"key":"dN4zPY0jg0"}],"key":"Nz1eayN9DA"},{"type":"block","position":{"start":{"line":291,"column":1},"end":{"line":291,"column":1}},"children":[{"type":"heading","depth":3,"position":{"start":{"line":293,"column":1},"end":{"line":293,"column":1}},"children":[{"type":"text","value":"Applying to all colors","position":{"start":{"line":293,"column":1},"end":{"line":293,"column":1}},"key":"vRW9ceiPXS"}],"identifier":"applying-to-all-colors","label":"Applying to all colors","html_id":"applying-to-all-colors","implicit":true,"key":"ruU3vRsnXR"},{"type":"paragraph","position":{"start":{"line":295,"column":1},"end":{"line":296,"column":1}},"children":[{"type":"text","value":"Now we want to do the same kind of operation, but to all three colors. Our first instinct might be to repeat the same operation we did above to each color matrix individually. However, NumPy’s ","position":{"start":{"line":295,"column":1},"end":{"line":295,"column":1}},"key":"y6JBOyz9VR"},{"type":"emphasis","position":{"start":{"line":295,"column":1},"end":{"line":295,"column":1}},"children":[{"type":"text","value":"broadcasting","position":{"start":{"line":295,"column":1},"end":{"line":295,"column":1}},"key":"X5fYtCGeVh"}],"key":"Xw475hhZMS"},{"type":"text","value":" takes care of this\nfor us.","position":{"start":{"line":295,"column":1},"end":{"line":295,"column":1}},"key":"yDlLWdi0kA"}],"key":"A1JzjcQIXS"},{"type":"paragraph","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"children":[{"type":"text","value":"If our array has more than two dimensions, then the SVD can be applied to all axes at once. However, the linear algebra functions in NumPy expect to see an array of the form ","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"key":"tIHoYsxSqv"},{"type":"inlineCode","value":"(n, M, N)","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"key":"JR5lAxnu9S"},{"type":"text","value":", where the first axis ","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"key":"DG68I3wZ25"},{"type":"inlineCode","value":"n","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"key":"fkBdcZHJv9"},{"type":"text","value":" represents the number of ","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"key":"Bcp0QvwuNc"},{"type":"inlineCode","value":"MxN","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"key":"bQUQzVi4I0"},{"type":"text","value":" matrices in the stack.","position":{"start":{"line":298,"column":1},"end":{"line":298,"column":1}},"key":"sFDKd470W2"}],"key":"kOwAYba7sh"},{"type":"paragraph","position":{"start":{"line":300,"column":1},"end":{"line":300,"column":1}},"children":[{"type":"text","value":"In our case,","position":{"start":{"line":300,"column":1},"end":{"line":300,"column":1}},"key":"jqiqHyu0aJ"}],"key":"hR4QuirG3F"}],"key":"JnaUoeSOc5"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"img_array.shape","key":"F9SXEzfQ8S"},{"type":"outputs","id":"8Ra-L6gk8qJvX0IjqXNbK","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":26,"metadata":{},"data":{"text/plain":{"content":"(768, 1024, 3)","content_type":"text/plain"}}},"key":"jBp1kO3WlY"}],"key":"svCNdA2l03"}],"key":"WctfvMhG5s"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":306,"column":1},"end":{"line":306,"column":1}},"children":[{"type":"text","value":"so we need to permutate the axis on this array to get a shape like ","position":{"start":{"line":306,"column":1},"end":{"line":306,"column":1}},"key":"luL1NW0b6e"},{"type":"inlineCode","value":"(3, 768, 1024)","position":{"start":{"line":306,"column":1},"end":{"line":306,"column":1}},"key":"wZLSeQU6zM"},{"type":"text","value":". Fortunately, the ","position":{"start":{"line":306,"column":1},"end":{"line":306,"column":1}},"key":"VGblmQALJo"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.transpose.html#numpy.transpose","position":{"start":{"line":306,"column":1},"end":{"line":306,"column":1}},"children":[{"type":"text","value":"numpy.transpose","position":{"start":{"line":306,"column":1},"end":{"line":306,"column":1}},"key":"a1kYcLlLW4"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.transpose.html#numpy.transpose","key":"eyHcOKiJih"},{"type":"text","value":" function can do that for us:","position":{"start":{"line":306,"column":1},"end":{"line":306,"column":1}},"key":"HJEWEFXiWt"}],"key":"Nlr7MtfnC8"}],"key":"GQ8Iy8BYwO"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"# The values in the tuple indicate the original dim, and the order the new axis\n# so axis 2 -\u003e 0, 0 -\u003e 1, and 1 -\u003e 2\nimg_array_transposed = np.transpose(img_array, (2, 0, 1))\nimg_array_transposed.shape","key":"miPI0zyUR8"},{"type":"outputs","id":"BFV1JtZAVubfrl4gpASdG","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":27,"metadata":{},"data":{"text/plain":{"content":"(3, 768, 1024)","content_type":"text/plain"}}},"key":"sxv3AIfvl3"}],"key":"x9C1ZMGHBM"}],"key":"PqAVTYKToo"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":315,"column":1},"end":{"line":315,"column":1}},"children":[{"type":"text","value":"Now we are ready to apply the SVD:","position":{"start":{"line":315,"column":1},"end":{"line":315,"column":1}},"key":"UkajXIU01m"}],"key":"s2W9RjxdPJ"}],"key":"R0ELxHIwq1"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"U, s, Vt = np.linalg.svd(img_array_transposed)","key":"z9dnXIqlbJ"},{"type":"outputs","id":"QORZbXbSmb2_RL0ib0WzR","children":[],"key":"JTnOEFKVtD"}],"key":"mWcO8WfaFR"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":321,"column":1},"end":{"line":321,"column":1}},"children":[{"type":"text","value":"Finally, to obtain the full approximated image, we need to reassemble these matrices into the approximation. Now, note that","position":{"start":{"line":321,"column":1},"end":{"line":321,"column":1}},"key":"sRkVnYXo6y"}],"key":"tr3O7NQ6WK"}],"key":"Kj3RVYT8u2"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"U.shape, s.shape, Vt.shape","key":"DGT35xqALi"},{"type":"outputs","id":"k-K--44LboMwLXrNmqup8","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":29,"metadata":{},"data":{"text/plain":{"content":"((3, 768, 768), (3, 768), (3, 1024, 1024))","content_type":"text/plain"}}},"key":"j14455BdsF"}],"key":"QEA7XNQvRT"}],"key":"L3hkSs9BnE"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":327,"column":1},"end":{"line":327,"column":1}},"children":[{"type":"text","value":"To build the final approximation matrix, we must understand how multiplication across different axes works.","position":{"start":{"line":327,"column":1},"end":{"line":327,"column":1}},"key":"yRgY2k7nHf"}],"key":"Z46hMOJlGZ"}],"key":"MO11MYVOsI"},{"type":"block","position":{"start":{"line":329,"column":1},"end":{"line":329,"column":1}},"children":[{"type":"heading","depth":3,"position":{"start":{"line":331,"column":1},"end":{"line":331,"column":1}},"children":[{"type":"text","value":"Products with n-dimensional arrays","position":{"start":{"line":331,"column":1},"end":{"line":331,"column":1}},"key":"TyBaQWnV5r"}],"identifier":"products-with-n-dimensional-arrays","label":"Products with n-dimensional arrays","html_id":"products-with-n-dimensional-arrays","implicit":true,"key":"iF53oXp8Rw"},{"type":"paragraph","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"children":[{"type":"text","value":"If you have worked before with only one- or two-dimensional arrays in NumPy, you might use ","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"bD59ZweAxr"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.dot.html#numpy.dot","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"children":[{"type":"text","value":"numpy.dot","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"VMBw7SrUVR"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.dot.html#numpy.dot","key":"P2yz4BScDH"},{"type":"text","value":" and ","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"QyyK3f8d7b"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"children":[{"type":"text","value":"numpy.matmul","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"sC2tk3fW48"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul","key":"GJK2clbWIR"},{"type":"text","value":" (or the ","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"JixuueP8qr"},{"type":"inlineCode","value":"@","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"N3YvrzIGAn"},{"type":"text","value":" operator) interchangeably. However, for n-dimensional arrays, they work in very different ways. For more details, check the documentation on ","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"Od43hOx1vT"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"children":[{"type":"text","value":"numpy.matmul","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"BheO3GsFlX"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.matmul.html#numpy.matmul","key":"njLAtuQ7HB"},{"type":"text","value":".","position":{"start":{"line":333,"column":1},"end":{"line":333,"column":1}},"key":"TSRQNtQwjF"}],"key":"FtSZr2yOyz"},{"type":"paragraph","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"children":[{"type":"text","value":"Now, to build our approximation, we first need to make sure that our singular values are ready for multiplication, so we build our ","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"B0gojYlgwP"},{"type":"inlineCode","value":"Sigma","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"q3pYmjrR2Q"},{"type":"text","value":" matrix similarly to what we did before. The ","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"ne4TJnNorr"},{"type":"inlineCode","value":"Sigma","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"FBDgdveZEZ"},{"type":"text","value":" array must have dimensions ","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"cBUF9J54tb"},{"type":"inlineCode","value":"(3, 768, 1024)","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"MPsdFhVMJN"},{"type":"text","value":". In order to add the singular values to the diagonal of ","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"N6vtMylpHq"},{"type":"inlineCode","value":"Sigma","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"TZirdUwolp"},{"type":"text","value":", we will again use the ","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"zkdBgiiXA1"},{"type":"link","url":"https://numpy.org/devdocs/reference/generated/numpy.fill_diagonal.html","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"children":[{"type":"text","value":"fill_diagonal","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"fcXNdm8lU4"}],"urlSource":"https://numpy.org/devdocs/reference/generated/numpy.fill_diagonal.html","key":"HzDUvz9cWw"},{"type":"text","value":" function, using each of the 3 rows in ","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"gz93aWYTZw"},{"type":"inlineCode","value":"s","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"J9s8IR336i"},{"type":"text","value":" as the diagonal for each of the 3 matrices in ","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"jgsUWlf6w9"},{"type":"inlineCode","value":"Sigma","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"EXJonnWbsp"},{"type":"text","value":":","position":{"start":{"line":335,"column":1},"end":{"line":335,"column":1}},"key":"OHs9hdcLXg"}],"key":"kEQlsMvBAY"}],"key":"WJMvP9gmB5"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"Sigma = np.zeros((3, 768, 1024))\nfor j in range(3):\n np.fill_diagonal(Sigma[j, :, :], s[j, :])","key":"N7WXhaGktO"},{"type":"outputs","id":"nnJXZ8tT01edvXncBiP3t","children":[],"key":"NgyhEP0xQR"}],"key":"fbnDrlUTnw"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":343,"column":1},"end":{"line":343,"column":1}},"children":[{"type":"text","value":"Now, if we wish to rebuild the full SVD (with no approximation), we can do","position":{"start":{"line":343,"column":1},"end":{"line":343,"column":1}},"key":"AICx7w8o3w"}],"key":"cC1WwdIbOF"}],"key":"We4TuvTotT"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"reconstructed = U @ Sigma @ Vt","key":"gUWHY4VtC3"},{"type":"outputs","id":"CKHN8ysnim9yTRudunS2H","children":[],"key":"sSWP7xJFJM"}],"key":"af7tRrGi6X"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":349,"column":1},"end":{"line":349,"column":1}},"children":[{"type":"text","value":"Note that","position":{"start":{"line":349,"column":1},"end":{"line":349,"column":1}},"key":"IjdjaHxwPG"}],"key":"j0lNGc3KR8"}],"key":"R3eMo0JTe8"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"reconstructed.shape","key":"X5Kd2Y9AJ8"},{"type":"outputs","id":"Ntf5LLmfrJVUc-xJUiYRr","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":32,"metadata":{},"data":{"text/plain":{"content":"(3, 768, 1024)","content_type":"text/plain"}}},"key":"VxdojtuFhK"}],"key":"dpFalTJQLP"}],"key":"oIvspPZ2SZ"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":355,"column":1},"end":{"line":355,"column":1}},"children":[{"type":"text","value":"The reconstructed image should be indistinguishable from the original one, except for differences due to floating point errors from the reconstruction. Recall that our original image consisted of floating point values in the range ","position":{"start":{"line":355,"column":1},"end":{"line":355,"column":1}},"key":"NpovfF1p1Q"},{"type":"inlineCode","value":"[0., 1.]","position":{"start":{"line":355,"column":1},"end":{"line":355,"column":1}},"key":"xJYlCxoto2"},{"type":"text","value":". The accumulation of floating point error from the reconstruction can result in values slightly outside this original range:","position":{"start":{"line":355,"column":1},"end":{"line":355,"column":1}},"key":"nvPIaIjz90"}],"key":"qZkYO0gjNW"}],"key":"PO4iCSwskE"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"reconstructed.min(), reconstructed.max()","key":"ZN2J5N1aGD"},{"type":"outputs","id":"wQIFQOL_B5CFTAFYcjzB1","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":33,"metadata":{},"data":{"text/plain":{"content":"(np.float64(-5.0176876542629145e-15), np.float64(1.0000000000000049))","content_type":"text/plain"}}},"key":"BaIwTTJ4t3"}],"key":"lq6EFwoIq2"}],"key":"PB2eS9oAeS"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":361,"column":1},"end":{"line":361,"column":1}},"children":[{"type":"text","value":"Since ","position":{"start":{"line":361,"column":1},"end":{"line":361,"column":1}},"key":"g20h7WRdqj"},{"type":"inlineCode","value":"imshow","position":{"start":{"line":361,"column":1},"end":{"line":361,"column":1}},"key":"tVR2t9hPaC"},{"type":"text","value":" expects values in the range, we can use ","position":{"start":{"line":361,"column":1},"end":{"line":361,"column":1}},"key":"OKyHdrMNsO"},{"type":"inlineCode","value":"clip","position":{"start":{"line":361,"column":1},"end":{"line":361,"column":1}},"key":"qF51deTpvO"},{"type":"text","value":" to excise the floating point error:","position":{"start":{"line":361,"column":1},"end":{"line":361,"column":1}},"key":"b5pEFhyHP8"}],"key":"D0mT2cbzw3"}],"key":"ZcHXFMRG4S"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"reconstructed = np.clip(reconstructed, 0, 1)\n\nfig, ax = plt.subplots()\nax.imshow(np.transpose(reconstructed, (1, 2, 0)))","key":"VaFZMXa4nu"},{"type":"outputs","id":"XQIpZwQrVooKddDg2zvIU","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"display_data","metadata":{},"data":{"text/plain":{"content":"\u003cFigure size 640x480 with 1 Axes\u003e","content_type":"text/plain"},"image/png":{"content_type":"image/png","hash":"77afc43dcd6aa9aa05c2dbe6889dec36","path":"/numpy-tutorials/build/77afc43dcd6aa9aa05c2dbe6889dec36.png"}}},"key":"IG9gbwyRmG"}],"key":"IGgzbd1z1s"}],"key":"ZjTIsddnyM"},{"type":"block","children":[{"type":"admonition","kind":"note","children":[{"type":"admonitionTitle","children":[{"type":"text","value":"Note","key":"MdItvrIOaO"}],"key":"fbIunFblzA"},{"type":"paragraph","position":{"start":{"line":371,"column":1},"end":{"line":374,"column":1}},"children":[{"type":"text","value":"In fact, ","position":{"start":{"line":371,"column":1},"end":{"line":371,"column":1}},"key":"iv2njVA9HR"},{"type":"inlineCode","value":"imshow","position":{"start":{"line":371,"column":1},"end":{"line":371,"column":1}},"key":"WnrQDIf3wp"},{"type":"text","value":" peforms this clipping under-the-hood, so if you skip the first\nline in the previous code cell, you might see a warning message saying\n","position":{"start":{"line":371,"column":1},"end":{"line":371,"column":1}},"key":"xqef6yZ7cV"},{"type":"inlineCode","value":"\"Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\"","position":{"start":{"line":371,"column":1},"end":{"line":371,"column":1}},"key":"kG7H5tMKeg"}],"key":"NagV5KKF9h"}],"key":"uL02nDBq9D"},{"type":"paragraph","position":{"start":{"line":377,"column":1},"end":{"line":377,"column":1}},"children":[{"type":"text","value":"Now, to do the approximation, we must choose only the first ","position":{"start":{"line":377,"column":1},"end":{"line":377,"column":1}},"key":"L6dFVpzmau"},{"type":"inlineCode","value":"k","position":{"start":{"line":377,"column":1},"end":{"line":377,"column":1}},"key":"YgsqLRYYHa"},{"type":"text","value":" singular values for each color channel. This can be done using the following syntax:","position":{"start":{"line":377,"column":1},"end":{"line":377,"column":1}},"key":"Si7h2uZT5g"}],"key":"Nee1diTgeD"}],"key":"wOl6MsELlG"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"approx_img = U @ Sigma[..., :k] @ Vt[..., :k, :]","key":"EaRxvzocnn"},{"type":"outputs","id":"XAebqeGC1dCu6K3wuH7YM","children":[],"key":"qe90pzq9EG"}],"key":"Ctrq9B5oX0"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":383,"column":1},"end":{"line":384,"column":1}},"children":[{"type":"text","value":"You can see that we have selected only the first ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"DwYRPoUeuS"},{"type":"inlineCode","value":"k","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"wBGfSynF3t"},{"type":"text","value":" components of the last axis for ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"LfVQ0XpC3N"},{"type":"inlineCode","value":"Sigma","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"r15fB1VuNp"},{"type":"text","value":" (this means that we have used only the first ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"fBvNdMxbkD"},{"type":"inlineCode","value":"k","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"AwIq1L80nX"},{"type":"text","value":" columns of each of the three matrices in the stack), and that we have selected only the first ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"JSruSqCaHt"},{"type":"inlineCode","value":"k","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"ZAY8d0rlz3"},{"type":"text","value":" components in the second-to-last axis of ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"S4ECfrWKww"},{"type":"inlineCode","value":"Vt","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"jqDe3jAYIB"},{"type":"text","value":" (this means we have selected only the first ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"zacLO0QfvD"},{"type":"inlineCode","value":"k","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"Md1UrkCwlc"},{"type":"text","value":" rows from every matrix in the stack ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"gu5yuJMyCw"},{"type":"inlineCode","value":"Vt","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"qIpYBqsbXu"},{"type":"text","value":" and all columns). If you are unfamiliar with the ellipsis syntax, it is a\nplaceholder for other axes. For more details, see the documentation on ","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"EXZxkKH1gM"},{"type":"link","url":"https://numpy.org/devdocs/user/basics.indexing.html#basics-indexing","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"children":[{"type":"text","value":"Indexing","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"ncwAgTl0sV"}],"urlSource":"https://numpy.org/devdocs/user/basics.indexing.html#basics-indexing","key":"tZSMGIw7FC"},{"type":"text","value":".","position":{"start":{"line":383,"column":1},"end":{"line":383,"column":1}},"key":"MQgROaY4iD"}],"key":"AKDLmfaukA"},{"type":"paragraph","position":{"start":{"line":386,"column":1},"end":{"line":386,"column":1}},"children":[{"type":"text","value":"Now,","position":{"start":{"line":386,"column":1},"end":{"line":386,"column":1}},"key":"OR7HE19txR"}],"key":"DeW2rerr5t"}],"key":"FYwgIIGhSI"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"approx_img.shape","key":"ZAuDBOBIgD"},{"type":"outputs","id":"UI6tlxGNFpcbTaBLIx43a","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"execute_result","execution_count":36,"metadata":{},"data":{"text/plain":{"content":"(3, 768, 1024)","content_type":"text/plain"}}},"key":"JeejofJQ5J"}],"key":"sVL2lmNhm8"}],"key":"sp4nkGTULp"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":392,"column":1},"end":{"line":392,"column":1}},"children":[{"type":"text","value":"which is not the right shape for showing the image. Finally, reordering the axes back to our original shape of ","position":{"start":{"line":392,"column":1},"end":{"line":392,"column":1}},"key":"NJLXkTMgE6"},{"type":"inlineCode","value":"(768, 1024, 3)","position":{"start":{"line":392,"column":1},"end":{"line":392,"column":1}},"key":"wTefC9mBvE"},{"type":"text","value":", we can see our approximation:","position":{"start":{"line":392,"column":1},"end":{"line":392,"column":1}},"key":"mF2uYpWCgI"}],"key":"ZK6vm0ew1m"}],"key":"m3sY1HG8Ox"},{"type":"block","kind":"notebook-code","children":[{"type":"code","lang":"python","executable":true,"value":"fig, ax = plt.subplots()\nax.imshow(np.transpose(np.clip(approx_img, 0, 1), (1, 2, 0)))","key":"qo1qcc7u8j"},{"type":"outputs","id":"ks3X8x0mmwbAsxoRB7MwP","children":[{"type":"output","children":[],"jupyter_data":{"output_type":"display_data","metadata":{},"data":{"text/plain":{"content":"\u003cFigure size 640x480 with 1 Axes\u003e","content_type":"text/plain"},"image/png":{"content_type":"image/png","hash":"b2bc20c3465b9a9bf572f1764b65f59b","path":"/numpy-tutorials/build/b2bc20c3465b9a9bf572f1764b65f59b.png"}}},"key":"CGd3HJ4EL0"}],"key":"K0xQDiCrSq"}],"key":"lJV9pytC3S"},{"type":"block","children":[{"type":"paragraph","position":{"start":{"line":399,"column":1},"end":{"line":399,"column":1}},"children":[{"type":"text","value":"Even though the image is not as sharp, using a small number of ","position":{"start":{"line":399,"column":1},"end":{"line":399,"column":1}},"key":"ifRjCVaOkR"},{"type":"inlineCode","value":"k","position":{"start":{"line":399,"column":1},"end":{"line":399,"column":1}},"key":"zEN2Hx7OnY"},{"type":"text","value":" singular values (compared to the original set of 768 values), we can recover many of the distinguishing features from this image.","position":{"start":{"line":399,"column":1},"end":{"line":399,"column":1}},"key":"TkciJretbs"}],"key":"Vno2oGq6nM"}],"key":"mzbyohFhKH"},{"type":"block","position":{"start":{"line":401,"column":1},"end":{"line":401,"column":1}},"children":[{"type":"heading","depth":3,"position":{"start":{"line":403,"column":1},"end":{"line":403,"column":1}},"children":[{"type":"text","value":"Final words","position":{"start":{"line":403,"column":1},"end":{"line":403,"column":1}},"key":"SvnXI5JzKM"}],"identifier":"final-words","label":"Final words","html_id":"final-words","implicit":true,"key":"arWZxEVCSo"},{"type":"paragraph","position":{"start":{"line":405,"column":1},"end":{"line":406,"column":1}},"children":[{"type":"text","value":"Of course, this is not the best method to ","position":{"start":{"line":405,"column":1},"end":{"line":405,"column":1}},"key":"LituGahFUj"},{"type":"emphasis","position":{"start":{"line":405,"column":1},"end":{"line":405,"column":1}},"children":[{"type":"text","value":"approximate","position":{"start":{"line":405,"column":1},"end":{"line":405,"column":1}},"key":"j2zZ9jMOQ4"}],"key":"BU0E1sVQNi"},{"type":"text","value":" an image. However, there is, in fact, a result in linear algebra that says that the approximation we built above is the best we can get to the original matrix in\nterms of the norm of the difference. For more information, see ","position":{"start":{"line":405,"column":1},"end":{"line":405,"column":1}},"key":"lW3WgxouTu"},{"type":"emphasis","position":{"start":{"line":405,"column":1},"end":{"line":405,"column":1}},"children":[{"type":"text","value":"G. H. Golub and C. F. Van Loan, Matrix Computations, Baltimore, MD, Johns Hopkins University Press, 1985","position":{"start":{"line":405,"column":1},"end":{"line":405,"column":1}},"key":"IQ06lk1Esu"}],"key":"mUbEZT9CLn"},{"type":"text","value":".","position":{"start":{"line":405,"column":1},"end":{"line":405,"column":1}},"key":"TTPlSStNAD"}],"key":"xZ0WU5C9pd"},{"type":"heading","depth":2,"position":{"start":{"line":408,"column":1},"end":{"line":408,"column":1}},"children":[{"type":"text","value":"Further reading","position":{"start":{"line":408,"column":1},"end":{"line":408,"column":1}},"key":"GRbh68bmUQ"}],"identifier":"further-reading","label":"Further reading","html_id":"further-reading","implicit":true,"key":"y0m4ohoxrk"},{"type":"list","ordered":false,"spread":false,"position":{"start":{"line":410,"column":1},"end":{"line":414,"column":1}},"children":[{"type":"listItem","spread":true,"position":{"start":{"line":410,"column":1},"end":{"line":410,"column":1}},"children":[{"type":"paragraph","children":[{"type":"link","url":"https://docs.python.org/dev/tutorial/index.html","position":{"start":{"line":410,"column":1},"end":{"line":410,"column":1}},"children":[{"type":"text","value":"Python tutorial","position":{"start":{"line":410,"column":1},"end":{"line":410,"column":1}},"key":"uYivpU3brR"}],"urlSource":"https://docs.python.org/dev/tutorial/index.html","key":"Gp2vtJPtq5"}],"key":"yXrCqNZuUK"}],"key":"YLMN23ExIN"},{"type":"listItem","spread":true,"position":{"start":{"line":411,"column":1},"end":{"line":411,"column":1}},"children":[{"type":"paragraph","children":[{"type":"link","url":"https://numpy.org/devdocs/reference/index.html#reference","position":{"start":{"line":411,"column":1},"end":{"line":411,"column":1}},"children":[{"type":"text","value":"NumPy Reference","position":{"start":{"line":411,"column":1},"end":{"line":411,"column":1}},"key":"sbVi9wZBrd"}],"urlSource":"https://numpy.org/devdocs/reference/index.html#reference","key":"teC3GkQR7F"}],"key":"ZFkpdKqgiG"}],"key":"JLoQvtFZls"},{"type":"listItem","spread":true,"position":{"start":{"line":412,"column":1},"end":{"line":412,"column":1}},"children":[{"type":"paragraph","children":[{"type":"link","url":"https://docs.scipy.org/doc/scipy/tutorial/index.html","position":{"start":{"line":412,"column":1},"end":{"line":412,"column":1}},"children":[{"type":"text","value":"SciPy Tutorial","position":{"start":{"line":412,"column":1},"end":{"line":412,"column":1}},"key":"hCuJBhPPMs"}],"urlSource":"https://docs.scipy.org/doc/scipy/tutorial/index.html","key":"bbWCi5erLI"}],"key":"d0kkmgF79G"}],"key":"JnjrAC5eAD"},{"type":"listItem","spread":true,"position":{"start":{"line":413,"column":1},"end":{"line":413,"column":1}},"children":[{"type":"paragraph","children":[{"type":"link","url":"https://scipy-lectures.org","position":{"start":{"line":413,"column":1},"end":{"line":413,"column":1}},"children":[{"type":"text","value":"SciPy Lecture Notes","position":{"start":{"line":413,"column":1},"end":{"line":413,"column":1}},"key":"B1zLEHogS3"}],"urlSource":"https://scipy-lectures.org","key":"lfItTn99s7"}],"key":"J0IXSCbyIN"}],"key":"qOvEEHuURs"},{"type":"listItem","spread":true,"position":{"start":{"line":414,"column":1},"end":{"line":414,"column":1}},"children":[{"type":"paragraph","children":[{"type":"link","url":"http://mathesaurus.sf.net/","position":{"start":{"line":414,"column":1},"end":{"line":414,"column":1}},"children":[{"type":"text","value":"A matlab, R, IDL, NumPy/SciPy dictionary","position":{"start":{"line":414,"column":1},"end":{"line":414,"column":1}},"key":"ycFPgbooZf"}],"urlSource":"http://mathesaurus.sf.net/","key":"wq3duHVHZ9"}],"key":"aveLGKGO2m"}],"key":"MN64VKTkJR"}],"key":"JLktME7KHj"}],"key":"tLqQuuRggA"}],"key":"ilJkRxhjFx"},"references":{"cite":{"order":[],"data":{}}},"footer":{"navigation":{"prev":{"title":"Analyzing the impact of the lockdown on air quality in Delhi, India","short_title":"Analyzing Air Quality","url":"/tutorial-air-quality-analysis","group":"Applications"},"next":{"title":"Saving and sharing your NumPy arrays","short_title":"Sharing Array Data","url":"/save-load-arrays","group":"Features"}}},"domain":"http://localhost:3000"},"project":{"title":"Numpy Tutorials","authors":[{"id":"Numpy Community","name":"Numpy Community"}],"github":"https://github.com/numpy/numpy-tutorials","toc":[{"file":"content/index.md"},{"children":[{"file":"content/mooreslaw-tutorial.md"},{"file":"content/tutorial-deep-learning-on-mnist.md"},{"file":"content/tutorial-x-ray-image-processing.md"},{"file":"content/tutorial-static_equilibrium.md"},{"file":"content/tutorial-plotting-fractals.md"},{"file":"content/tutorial-air-quality-analysis.md"}],"title":"Applications"},{"children":[{"file":"content/tutorial-svd.md"},{"file":"content/save-load-arrays.md"},{"file":"content/tutorial-ma.md"}],"title":"Features"},{"children":[{"file":"content/tutorial-style-guide.md"}],"file":"content/contributing.md","title":"Contributing"}],"thumbnail":"/numpy-tutorials/build/b77199e99a54e59b2e3c037c2cc90f21.svg","exports":[],"bibliography":[],"index":"index","pages":[{"level":1,"title":"Applications"},{"slug":"mooreslaw-tutorial","title":"Determining Moore’s Law with real data in NumPy","short_title":"Moore's Law","description":"","date":"","thumbnail":"/numpy-tutorials/build/01-mooreslaw-tutoria-68d0ad466c300d347c517c09cd29d0d9.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-deep-learning-on-mnist","title":"Deep learning on MNIST","description":"","date":"","thumbnail":"/numpy-tutorials/build/tutorial-deep-learni-1a6932c38d13641ad9a1eda7d431b1f5.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-x-ray-image-processing","title":"X-ray image processing","description":"","date":"","thumbnail":"/numpy-tutorials/build/tutorial-x-ray-image-cb14ad1cb4fb37f341c5954e91e694b8.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-static-equilibrium","title":"Determining Static Equilibrium in NumPy","short_title":"Static Equilibrium","description":"","date":"","thumbnail":"/numpy-tutorials/build/static_eqbm-fig01-ee029c471a69f4e98c09d962ac7d60dd.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-plotting-fractals","title":"Plotting Fractals","description":"","date":"","thumbnail":"/numpy-tutorials/build/fractal-4ebbc2569665376d939ff6f78ae5e5ab.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-air-quality-analysis","title":"Analyzing the impact of the lockdown on air quality in Delhi, India","short_title":"Analyzing Air Quality","description":"","date":"","thumbnail":"/numpy-tutorials/build/11-delhi-aqi-5fa295dd14ed05daaf4cd0193122e2f7.jpg","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"level":1,"title":"Features"},{"slug":"tutorial-svd","title":"Linear algebra on n-dimensional arrays","short_title":"Linear Algebra on n-D arrays","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"save-load-arrays","title":"Saving and sharing your NumPy arrays","short_title":"Sharing Array Data","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"tutorial-ma","title":"Masked Arrays","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2},{"slug":"contributing","title":"Contributing","short_title":"Contributing","description":"","date":"","thumbnail":"","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":1},{"slug":"tutorial-style-guide","title":"Learn to write a NumPy tutorial","short_title":"Style Guide","description":"","date":"","thumbnail":"/numpy-tutorials/build/56554e3d11983df8f484e8d7b2c2bdae.png","thumbnailOptimized":"","banner":"","bannerOptimized":"","tags":[],"level":2}]}}},"actionData":null,"errors":null},"future":{"unstable_dev":false,"unstable_postcss":false,"unstable_tailwind":false,"v2_errorBoundary":true,"v2_headers":true,"v2_meta":true,"v2_normalizeFormMethod":true,"v2_routeConvention":true}};</script><script type="module" async="">import "/numpy-tutorials/build/manifest-3595279D.js";
import * as route0 from "/numpy-tutorials/build/root-SIO6LUTY.js";
import * as route1 from "/numpy-tutorials/build/routes/$-PRP77N34.js";
window.__remixRouteModules = {"root":route0,"routes/$":route1};
import("/numpy-tutorials/build/entry.client-PCJPW7TK.js");</script></body></html>