From ca5ac515af260cb612c7f6453fbcdc65d359b063 Mon Sep 17 00:00:00 2001 From: John Stachurski Date: Sun, 9 Mar 2025 17:21:02 +0900 Subject: [PATCH 1/3] misc edits to need for speed and numpy lectures --- .../need_for_speed/matlab.png | Bin 0 -> 14232 bytes .../lecture_specific/need_for_speed/numpy.pdf | Bin 0 -> 20997 bytes lectures/about_py.md | 1 + lectures/need_for_speed.md | 282 +++++------------- lectures/numpy.md | 184 ++++++++++-- 5 files changed, 229 insertions(+), 238 deletions(-) create mode 100644 lectures/_static/lecture_specific/need_for_speed/matlab.png create mode 100644 lectures/_static/lecture_specific/need_for_speed/numpy.pdf diff --git a/lectures/_static/lecture_specific/need_for_speed/matlab.png b/lectures/_static/lecture_specific/need_for_speed/matlab.png new file mode 100644 index 0000000000000000000000000000000000000000..c2d0f7ed04611f99581c3394d8efebb8807ad31e GIT binary patch literal 14232 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 IdF{9V14xDlBLDyZ literal 0 HcmV?d00001 diff --git a/lectures/_static/lecture_specific/need_for_speed/numpy.pdf b/lectures/_static/lecture_specific/need_for_speed/numpy.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4d53cae2ab72be69709380a2a7baa135def54af5 GIT binary patch literal 20997 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

ajLvj8$15k% zipm`G4hg5Z$3Lz09`QMPJQAM+T#V^`chU=Rnb$6bE_hi6gELdF-;VxdsWJ!4O7gT3 zB;7qKR4tJ`!h~__Plt#u4lkXGa&&dy7+luB1>%%XF(fqkTn-eXU^L|3cV_0~S#2e- zi7-uswtp^kau`fe^%e45efV{exI~k0Y49`_c}ns!zNy}9iQG7NyR#gTOuxV`(a3_W z8UXw@NuKaXO~oLR$5#8UZha6(&sAadqMQRCw!T~5l4GrUfpyVd;qn=_BnyjnpFx~= zvw1(gx8;r6)My7bX26b(vA2AFBJg7Sf|}GU43+XXU6J@{gZ0?={-z>kjMBZ?*e@7C zIa?!HzGSPkVm@Wbe(lB@`aExW)46{wUfo0<h?!H+8}~*aY%^ffZtujz?MAY zeW)5A-o zt9$%7FN}QdypcyG?kM9T)CpkUDSQBTBYFXbs5lh{p}|W1rp!M1_Y zTr)->gG9l~eG(9iuxV}^reEb7t7>~hDekX>^)#cp?z`8H#-I`7f^$6FRAdNIljnCu6N zo124|PXA-dVFC6hh2V2Lk84c#T)hlDyN))^!?RO-o*nVG7z3}bw zF7^T)ow`hOvpl*P9@0zoVun_j{lQ}Ky3e=z|8#QS@l?Hk0KloNBiYjU8p+7W-6Ofy z%}7$VeC<7QjcczILRLsJBcrSP!GoPB^9}B-aX;D#>`R5uqUI(3 ze8hy*4mt0`pGU=Xn)4~RmmHCau69isH1WB#j8_I)^Hw6(DjQYG(eJ7Woad1_118rf zm@xTyLb6WZMY-svt&0;sRJXS;H2V#d_*rdi+6R=l%Jssyoa=nf9)vb{&-*@3~I^^W)W| zS1l$vBz0szX^Z>%56O9g`&N1I!uI@W>>H&o*Wxb3$#<=8J)9#ANuF_WmVSktT8p#& z8qtZfN6nC&>}5x~YSn`Ha?H@&=i=D`=W5@vgT4)Vr|*!ub#CHJ^Mh9&o{c#4tpynH5fx@|2~`QEJZz4=M> zd*}9~9M{wh4q}#5wV%srZy^-ezc_h9>?Y84YSi>{c2wlAaAFoiXG+LrEE)(H1w*e zqvqeVmP36zWz+_T=Lt`00+Q=S1bvS1QRZPnugZI&BaB1NF2@%4jX}ob*iBCicdk52 z8Oa+t#BO?}S1EORGdQVwv9g(TxZb9krr|Aa$dvt<8Fcm*=ad)Sfvtg4oC7Wi^&TwtWJ!&R;w# z@$lNnHM#?rvKTfCNu8WA+cZZ)sv&BU{l;vOe8bY7!4DV}zLrVc<{pyZi8QRF$0ul5 z_&=AfZiGKf@(1KzLB<3El~6n zz1NUoXrUnnXI>tTDEc?qE1<4wbV6rcNnx*r2et0BZ zn-lzSNY~BflKeq4(fxf3q2AUFOQYrovrErixXGo+#w{d#YTa{^JJAUzaJ~+&U*k|Q|B+4uLyHRsOo68FG7aB`oC$9x6of)q%^AjM6uEGX^CKa(_2(&K-;R^+ zgtvkxs1(l0cn%Xe!n*LYW&!6NvT~mxn*+)Mo-K{*K6CbAa-n#YdS?TPs|3&3Q0c83 zT5IuqD^fpp;ZWEx`*3~UroH~iVtn=4xGD1k*=x!I$@T~QgX2Xgv6VHm*Ew{r2}N^! zk4k3VpQZC|=+1~l|H&{<-FML_CjQwN;cO%N?_9$nT#9u`RT0QqCTJrDFKZ#FSP$Of z>dSnT%}d~!fEHsStg0Y9c>x$hHX5~a-o{5M8HAE6OH)KB?IqXiI}~UsEEHkJ6HTUv zx9X-H8*Zi5h*#B3x2Qh3U2~%9g@g=noMSGvvf^HaD-s{JS@bN-Abvr6OM6e3M zl$!BgBI?IqGMTUFeL@Q3)b$1LmMES!ri*vs4xkuC^m~q!j9Gl@du^4i?pkin@7ULN zRHQVF!H_K3<09*5@aiZ?%e*QQtUr39NH7(7(vS=<;xEe%7Cts`t|dXRX8~~Zjz>zG zv(Oa@W+Fd54&(ij>crvZnQr=4ja#&mp(97hcUZm~$0x{uO}PQf1V7$sOjrdGeCif? z1|=ETG!2B8muoKH{BZ53NClyg$+ak0#GS6j1Y+-v&J~r+UN-hh~TyAY{?YQfQFoaqMDR3&4NxyzF7rlH7w+6IT z00gH&?&^%@j46-Xl#Vs_K+B}S@iAdub>D1GAWvCkbSX^vbcD#=QTPg8Lg=uH#PZ+O zkKSe2X*ww?vhrA3R^q*Lzd3Eyy$ML|OS95%p;v!uU6dP}+t~Rb-ZJ7!ndCj5+7Gt6 z#mJfC`@4ib`BCZ$dX!!TEcSo(Z_r0fmD(6y} zhu;H=)3*N5qz82q}QQFOCbaYn`Kvzg>S;_+_G};_d6rI`Zod^4o_clz^a7 zPtyw7w3!)okMFq^VWKyeDz3GxzL-hZ1HVhm(aW!-yZP7Wr#N`Njf=c7CXRXjT3Y+} zdq3NaJ_0d#jkibm)7%87^qwmW(RWCtX%kzb-|&s=O|8>n@BQr48&8USGrVf1Dp~FJ z<_=pyij2;-(RKa{SA2z`f7gm6ZS*nB>*mIH-8^jwK*V*=y6P0TZFJA1^DyW2Xy4V^ zY(?CBP@pFBP}H-jaVt?QviQiU;_IDGD53F{rtR}L7PnWPDR|qU)oq^SmgXp5u#QbR zd0#vk!Ts}!%u`?fbuBBtq;4~YyQK$=EO2By)TZc*Gg-J)1K(VBnD^uE`@U+DWsO#9 zUv4JfvHRSo0f^EP&Z69}{^;I=z z8^Vsmqh)Pt4{|d;;2lGtokn%hG~KMM-KhADn68pGxUcQu;^Jg|m5QG2kU-MZN>mHS z&EAD7t3jz!8c6tn$JQaJsNprtUH;|ffNG9DfJCAIY5g4{%?LmvsU{HwfT7VKoP+o! z0DJC>DTIX&g8;goaUh9|(W~$Kpy0+%8wLS(0xN@I zYFFx*sa?PnEP$oTNm$tLqZ)%jQ100^i1zAnf6Us>EK)5zK>AO82n5`0-NBjJNm2ZT z%SoY72tW!BLjW)cI1nfVf&>dnD^NuuA~-3SU7m;tNWs9VkyZn_J$p+9XIs#?19z3o zT~w{@ZSBBZ(7ypyJ?pD_00wNJ4huwyz-6=J;`|3(w5vW*%kG}ot~&)qBf&DeQLx0W za70~$R0_%#les}eDv$g>s0^l_U&+FF@OaO&M!jS?t z0>5G~2m*~2*l81R{vG?Z_v>*t58Q*I_T)hkustyt6uKt{NAKwiMM4mN=0V}uy)gt7 zz9$a>-%}TgK<%x8+EW*b#X$DvVPKFyYQP{c#Gf$;xQhRbf%6AP@9B#`{#%UbW)7|a yx1DzcZF^s90K6X3S_A@dM{)#T+&k|V|CFuViRNy^oht`}Ai` ```{index} single: Python; Vectorization @@ -272,173 +287,12 @@ For example, when working in a high level language, the operation of inverting a This clever idea dates back to MATLAB, which uses vectorization extensively. -Vectorization can greatly accelerate many numerical computations (but not all, -as we shall see). - -Let's see how vectorization works in Python, using NumPy. - -### Operations on Arrays - -```{index} single: Vectorization; Operations on Arrays -``` - -First, let's run some imports - -```{code-cell} python3 -import random -import numpy as np -import quantecon as qe -``` - -Next let's try some non-vectorized code, which uses a native Python loop to generate, -square and then sum a large number of random variables: - -```{code-cell} python3 -n = 1_000_000 -``` - -```{code-cell} python3 -%%time - -y = 0 # Will accumulate and store sum -for i in range(n): - x = random.uniform(0, 1) - y += x**2 -``` - -The following vectorized code achieves the same thing. - -```{code-cell} ipython -%%time - -x = np.random.uniform(0, 1, n) -y = np.sum(x**2) -``` - -As you can see, the second code block runs much faster. Why? - -The second code block breaks the loop down into three basic operations - -1. draw `n` uniforms -1. square them -1. sum them - -These are sent as batch operators to optimized machine code. -Apart from minor overheads associated with sending data back and forth, the result is C or Fortran-like speed. - -When we run batch operations on arrays like this, we say that the code is *vectorized*. - -Vectorized code is typically fast and efficient. - -It is also surprisingly flexible, in the sense that many operations can be vectorized. - -The next section illustrates this point. - -(ufuncs)= -### Universal Functions - -```{index} single: NumPy; Universal Functions -``` - -Many functions provided by NumPy are so-called *universal functions* --- also called [ufuncs](https://docs.scipy.org/doc/numpy/reference/ufuncs.html). - -This means that they - -* map scalars into scalars, as expected -* map arrays into arrays, acting element-wise - -For example, `np.cos` is a ufunc: - -```{code-cell} python3 -np.cos(1.0) -``` - -```{code-cell} python3 -np.cos(np.linspace(0, 1, 3)) +```{figure} /_static/lecture_specific/need_for_speed/matlab.png ``` -By exploiting ufuncs, many operations can be vectorized. - -For example, consider the problem of maximizing a function $f$ of two -variables $(x,y)$ over the square $[-a, a] \times [-a, a]$. - -For $f$ and $a$ let's choose - -$$ -f(x,y) = \frac{\cos(x^2 + y^2)}{1 + x^2 + y^2} -\quad \text{and} \quad -a = 3 -$$ - -Here's a plot of $f$ - -```{code-cell} ipython -import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d.axes3d import Axes3D -from matplotlib import cm - -def f(x, y): - return np.cos(x**2 + y**2) / (1 + x**2 + y**2) - -xgrid = np.linspace(-3, 3, 50) -ygrid = xgrid -x, y = np.meshgrid(xgrid, ygrid) - -fig = plt.figure(figsize=(10, 8)) -ax = fig.add_subplot(111, projection='3d') -ax.plot_surface(x, - y, - f(x, y), - rstride=2, cstride=2, - cmap=cm.jet, - alpha=0.7, - linewidth=0.25) -ax.set_zlim(-0.5, 1.0) -ax.set_xlabel('$x$', fontsize=14) -ax.set_ylabel('$y$', fontsize=14) -plt.show() -``` - -To maximize it, we're going to use a naive grid search: - -1. Evaluate $f$ for all $(x,y)$ in a grid on the square. -1. Return the maximum of observed values. - -The grid will be - -```{code-cell} python3 -grid = np.linspace(-3, 3, 1000) -``` - -Here's a non-vectorized version that uses Python loops. - -```{code-cell} python3 -%%time - -m = -np.inf - -for x in grid: - for y in grid: - z = f(x, y) - if z > m: - m = z -``` - -And here's a vectorized version - -```{code-cell} python3 -%%time - -x, y = np.meshgrid(grid, grid) -np.max(f(x, y)) -``` - -In the vectorized version, all the looping takes place in compiled code. - -As you can see, the second version is **much** faster. - -(We'll make it even faster again later on, using more scientific programming tricks.) +Vectorization can greatly accelerate many numerical computations, as we will see +in later lectures. (numba-p_c_vectorization)= ## Beyond Vectorization @@ -462,11 +316,11 @@ In these kinds of settings, we need to go back to loops. Fortunately, there are alternative ways to speed up Python loops that work in almost any setting. -For example, in the last few years, a new Python library called [Numba](http://numba.pydata.org/) has appeared that solves the main problems -with vectorization listed above. +For example, [Numba](http://numba.pydata.org/) solves the main problems with +vectorization listed above. It does so through something called **just in time (JIT) compilation**, which can generate extremely fast and efficient code. -We'll learn how to use Numba {doc}`soon `. +{doc}`Later ` we'll learn how to use Numba to accelerate Python code. diff --git a/lectures/numpy.md b/lectures/numpy.md index ff495cc8..ed8d08c6 100644 --- a/lectures/numpy.md +++ b/lectures/numpy.md @@ -36,14 +36,24 @@ kernelspec: We have already seen some code involving NumPy in the preceding lectures. -In this lecture, we will start a more systematic discussion of both +In this lecture, we will start a more systematic discussion of -* NumPy arrays and -* the fundamental array processing operations provided by NumPy. +1. NumPy arrays and +1. the fundamental array processing operations provided by NumPy. -### References -* [The official NumPy documentation](http://docs.scipy.org/doc/numpy/reference/). +(For an alternative reference, see [the official NumPy documentation](http://docs.scipy.org/doc/numpy/reference/).) + +We will use the following imports. + +```{code-cell} python3 +import numpy as np +import random +import quantecon as qe +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d.axes3d import Axes3D +from matplotlib import cm +``` (numpy_array)= ## NumPy Arrays @@ -53,15 +63,10 @@ In this lecture, we will start a more systematic discussion of both The essential problem that NumPy solves is fast array processing. -The most important structure that NumPy defines is an array data type formally called a [numpy.ndarray](http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html). - -NumPy arrays power a large proportion of the scientific Python ecosystem. +The most important structure that NumPy defines is an array data type, formally +called a [numpy.ndarray](http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html). -Let's first import the library. - -```{code-cell} python3 -import numpy as np -``` +NumPy arrays power a very large proportion of the scientific Python ecosystem. To create a NumPy array containing only zeros we use [np.zeros](http://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html#numpy.zeros) @@ -523,9 +528,6 @@ tags: [hide-input] # Adapted and modified based on the code in the book written by Jake VanderPlas (see https://jakevdp.github.io/PythonDataScienceHandbook/06.00-figure-code.html#Broadcasting) # Originally from astroML: see http://www.astroml.org/book_figures/appendix/fig_broadcast_visual.html -import numpy as np -from matplotlib import pyplot as plt - def draw_cube(ax, xy, size, depth=0.4, edges=None, label=None, label_kwargs=None, **kwargs): @@ -1159,14 +1161,150 @@ We'll cover the SciPy versions in more detail {doc}`soon `. For a comprehensive list of what's available in NumPy see [this documentation](https://docs.scipy.org/doc/numpy/reference/routines.html). -## Exercises + +## Speed Comparisons + +```{index} single: Vectorization; Operations on Arrays +``` + +We mentioned in an {doc}`previous lecture <>` that NumPy-based vectorization can +accelerate scientific applications. + +In this section we try some speed comparisons to illustrate this fact. + +### Vectorization vs Loops + +Let's begin with some non-vectorized code, which uses a native Python loop to generate, +square and then sum a large number of random variables: + +```{code-cell} python3 +n = 1_000_000 +``` + +```{code-cell} python3 +%%time + +y = 0 # Will accumulate and store sum +for i in range(n): + x = random.uniform(0, 1) + y += x**2 +``` + +The following vectorized code achieves the same thing. ```{code-cell} ipython -%matplotlib inline -import matplotlib.pyplot as plt -plt.rcParams['figure.figsize'] = (10,6) +%%time + +x = np.random.uniform(0, 1, n) +y = np.sum(x**2) +``` + +As you can see, the second code block runs much faster. Why? + +The second code block breaks the loop down into three basic operations + +1. draw `n` uniforms +1. square them +1. sum them + +These are sent as batch operators to optimized machine code. + +Apart from minor overheads associated with sending data back and forth, the result is C or Fortran-like speed. + +When we run batch operations on arrays like this, we say that the code is *vectorized*. + +The next section illustrates this point. + +(ufuncs)= +### Universal Functions + +```{index} single: NumPy; Universal Functions +``` + +As discussed above, many functions provided by NumPy are universal functions (ufuncs). + +By exploiting ufuncs, many operations can be vectorized, leading to faster +execution. + +For example, consider the problem of maximizing a function $f$ of two +variables $(x,y)$ over the square $[-a, a] \times [-a, a]$. + +For $f$ and $a$ let's choose + +$$ +f(x,y) = \frac{\cos(x^2 + y^2)}{1 + x^2 + y^2} +\quad \text{and} \quad +a = 3 +$$ + +Here's a plot of $f$ + +```{code-cell} ipython + +def f(x, y): + return np.cos(x**2 + y**2) / (1 + x**2 + y**2) + +xgrid = np.linspace(-3, 3, 50) +ygrid = xgrid +x, y = np.meshgrid(xgrid, ygrid) + +fig = plt.figure(figsize=(10, 8)) +ax = fig.add_subplot(111, projection='3d') +ax.plot_surface(x, + y, + f(x, y), + rstride=2, cstride=2, + cmap=cm.jet, + alpha=0.7, + linewidth=0.25) +ax.set_zlim(-0.5, 1.0) +ax.set_xlabel('$x$', fontsize=14) +ax.set_ylabel('$y$', fontsize=14) +plt.show() +``` + +To maximize it, we're going to use a naive grid search: + +1. Evaluate $f$ for all $(x,y)$ in a grid on the square. +1. Return the maximum of observed values. + +The grid will be + +```{code-cell} python3 +grid = np.linspace(-3, 3, 1000) +``` + +Here's a non-vectorized version that uses Python loops. + +```{code-cell} python3 +%%time + +m = -np.inf + +for x in grid: + for y in grid: + z = f(x, y) + if z > m: + m = z +``` + +And here's a vectorized version + +```{code-cell} python3 +%%time + +x, y = np.meshgrid(grid, grid) +np.max(f(x, y)) ``` +In the vectorized version, all the looping takes place in compiled code. + +As you can see, the second version is *much* faster. + + +## Exercises + + ```{exercise-start} :label: np_ex1 ``` @@ -1359,8 +1497,7 @@ Your task is to An example solution is given below. -In essence, we've just taken [this -code](https://github.com/QuantEcon/QuantEcon.py/blob/master/quantecon/ecdf.py) +In essence, we've just taken [this code](https://github.com/QuantEcon/QuantEcon.py/blob/master/quantecon/ecdf.py) from QuantEcon and added in a plot method ```{code-cell} python3 @@ -1475,7 +1612,6 @@ print(A) **Part2**: Move on to replicate the result of the following broadcasting operation. Meanwhile, compare the speeds of broadcasting and the `for` loop you implement. ```{code-cell} python3 -import quantecon as qe np.random.seed(123) x = np.random.randn(1000, 100, 100) @@ -1567,4 +1703,4 @@ print(np.array_equal(B, D)) ``` ```{solution-end} -``` \ No newline at end of file +``` From 355c152f9ef8a6111a5f2cf055056a19aa7b06a8 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Wed, 12 Mar 2025 11:03:44 +1100 Subject: [PATCH 2/3] Update lectures/numpy.md --- lectures/numpy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/numpy.md b/lectures/numpy.md index 28b642ed..173433cb 100644 --- a/lectures/numpy.md +++ b/lectures/numpy.md @@ -1167,7 +1167,7 @@ For a comprehensive list of what's available in NumPy see [this documentation](h ```{index} single: Vectorization; Operations on Arrays ``` -We mentioned in an {doc}`previous lecture <>` that NumPy-based vectorization can +We mentioned in an {doc}`previous lecture ` that NumPy-based vectorization can accelerate scientific applications. In this section we try some speed comparisons to illustrate this fact. From 6d04b8934d43e8995eb8d419ce4461d07373d630 Mon Sep 17 00:00:00 2001 From: mmcky Date: Wed, 12 Mar 2025 11:43:38 +1100 Subject: [PATCH 3/3] resize matlab figure --- .../need_for_speed/matlab.png | Bin 14232 -> 16776 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lectures/_static/lecture_specific/need_for_speed/matlab.png b/lectures/_static/lecture_specific/need_for_speed/matlab.png index c2d0f7ed04611f99581c3394d8efebb8807ad31e..0461ebd55a9bf1aadb0be9321a389f35314e2bec 100644 GIT binary patch literal 16776 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 IdF{9V14xDlBLDyZ