提交 b937f013 编写于 作者: W wizardforcel

img

上级 fd529d4e
......@@ -113,7 +113,7 @@ YouTubeVideo("2CJJ6FrfuGU")
A microphone is the opposite of a speaker and has a very sensitive diaphragm that subtly vibrates in the presence of soundwaves. If we measure the deflection of the microphone away from neutral at a very fast and regular rate, we *digitize* a signal such as an audio signal. Graphically, it looks like this time vs amplitude plot (magnitude of microphone deflection):
<img src="images/Signal_Sampling.png" width="300">
<img src="img/Signal_Sampling.png" width="300">
The microphone is wiggling in a continuous fashion and knows nothing about sampling rate. It is a so-called analog signal. To get that into a computer, we must convert it to numbers. The numbers you saw above for the Kiss song are the result of digitization.
......
......@@ -220,11 +220,11 @@ I 11:27:00.606 LabApp] [jupyter_nbextensions_configurator] enabled 0.2.8
That will start up a program that launches a tab in your browser as well:
<img src="../notes/images/lab1.png" width="60%">
<img src="../notes/img/lab1.png" width="60%">
Clicking on the "Python 3" icon under the "Notebook" category creates a new notebook window for you:
<img src="../notes/images/lab2.png" width="80%">
<img src="../notes/img/lab2.png" width="80%">
Type `500+1` into the first cell next to the `In [ ]`. You should see the output 501 generated in the `Out` section below it. Hit control-enter to execute that cell or the right-facing triangle in the toolbar to execute the cell.
......
......@@ -254,7 +254,7 @@ plt.show()
See if you can see the relationship between this code and the previous code. We have another import statement that pulls in some plotting code and we use that to produce a scatterplot by replacing the `play`/`wait` sequence with with the last two lines. Other than that the code is the same. Run that code and you should see a nice wiggly sinewave, which is the addition of two pure sine waves at different frequencies:
<img src="images/twotone.png" width="100%">
<img src="img/twotone.png" width="100%">
## Sound processing
......
......@@ -12,15 +12,15 @@
计算机由三个主要组件组成:一个用于存放数据的磁盘,一个存储器(在断电时擦除),以及一个处理该数据的处理器(CPU)。 这是一张实际 CPU 和一些内存芯片的图片:
<img src="images/cpu-memory.png" width="400">
<img src="img/cpu-memory.png" width="400">
计算机内存(RAM == 随机存取内存)要快得多,但通常比磁盘小很多,并且当计算机关机时所有内存都会丢失。 将内存视为工作空间或临时空间,将磁盘视为永久存储。内存芯片有点像人类的短期以及,相对于一张读写速度较慢而且持久的纸张而言,它很容易消失。
存储器被分解成固定大小的离散单元。单元的大小是一个*字节*,由 8 *位*(二进制开/关数字)组成。 存放 0 到 255 之间的数字就足够了。每个单元都用整数地址标识,就像邮箱上的数字一样(见下图和右图)。 处理器可以请求特定地址处的数据,并且还可以在特定存储器位置存储一条数据。例如,这是字节可寻址的计算机内存的抽象表示:
<img src="images/addresses.png" width="80">
<img src="img/addresses.png" width="80">
<img src="images/mailboxes.png" width="70">
<img src="img/mailboxes.png" width="70">
在这种情况下,存储器在地址 0 处具有值 100。在地址 1 处,存储器具有值 0。地址 4 具有我们可以存储在单个字节中的最大值:255。
......@@ -53,7 +53,7 @@ CPU 按照时钟的心跳执行指令,在这里我们得到术语时钟速率
编程语言以两种方式向我们提供更高级别的内存视图:我们可以使用名称来引用内存中的位置,每个内存单元可以保存任意大小的整数和实数值(它们确实有一个限制,但让我们现在保持简单)。 例如,以下是存储在内存中的两个命名值:
<img src="images/named-memory.png" width="90">
<img src="img/named-memory.png" width="90">
```python
......@@ -61,7 +61,7 @@ units = 923
price = 8.02
```
<img src="images/redbang.png" width="30" align="left">When referring to the kind of thing a value represents, we use the word **type**. The type of the "units" cell is integer and the type of "price" is real number (or floating-point number).
<img src="img/redbang.png" width="30" align="left">When referring to the kind of thing a value represents, we use the word **type**. The type of the "units" cell is integer and the type of "price" is real number (or floating-point number).
```python
......@@ -75,7 +75,7 @@ type(price)
另一个非常常见的值类型是*字符串*,它实际上是一个字符列表。 我们使用字符串来保存地名,书名和任何其他基于文本的值。 我们可以将字符串视为单个值,因为编程语言隐藏了细节。 字符串可以任意长,编程语言将字符串存储为内存中的字节序列。 每个字符占用一个或两个字节。 换句话说,我们认为它是:
<img src="images/strings.png" width="110">
<img src="img/strings.png" width="110">
```python
......@@ -89,7 +89,7 @@ type(name)
但是它更像是:
<img src="images/strings2.png" width="110">
<img src="img/strings2.png" width="110">
使用 [lolviz](https://github.com/parrt/lolviz) 包,我们可以可视化简单的类型,例如字符串:
......@@ -132,11 +132,11 @@ objviz(name) # render as list of char
最常见的*数据结构***列表**,它只是一系列存储单元。 因为我们都熟悉电子表格,所以让我们使用电子表格可视化这些数据结构。 电子表格中的列实际上是列表,例如以下整数,浮点数和字符串列表/列:
<img src="images/int-list.png" width="60">
<img src="img/int-list.png" width="60">
<img src="images/float-list.png" width="80">
<img src="img/float-list.png" width="80">
<img src="images/names-list.png" width="139">
<img src="img/names-list.png" width="139">
```python
......@@ -164,7 +164,7 @@ objviz(Quantity)
我们也可以将电子表格的行视为列表。 例如,电子表格的标题行实际上是一个字符串列表:
<img src="images/header-row.png" width="750">
<img src="img/header-row.png" width="750">
```python
......@@ -182,7 +182,7 @@ objviz(headers)
所有这些列表都有一个共同点:元素的类型是相同的。它们是*同构的*。但是,我们也可以使用*异构*元素列表,这通常是我们在电子表格行中看到的:
<img src="images/sample-row.png" width="800">
<img src="img/sample-row.png" width="800">
```python
......@@ -313,7 +313,7 @@ objviz(ids)
电子表格一个接一个地排列行,程序员将其解释为*列表的列表*。在分析或数据库世界中,我们称之为**表**
<img src="images/rows.png" width="700">
<img src="img/rows.png" width="700">
在此示例中,每行代表一个销售交易。
......@@ -373,7 +373,7 @@ objviz(df.values)
如果表元素都是数字,我们称之为**矩阵**。 这是一个包含 5 行和 2 列的矩阵:
<img src="images/matrix.png" width="110">
<img src="img/matrix.png" width="110">
让我向您介绍另一个新的 BFF,`numpy`
......@@ -485,7 +485,7 @@ print(z.shape)
作为人类,我们可以完整地查看上面的电子表格或数据结构,但程序必须**遍历**数据结构的元素。这有点像在列表元素上滑动放大镜:
<img src="images/int-list-item.png" width="230">
<img src="img/int-list-item.png" width="230">
这种遍历的概念抽象为元素的任何**序列**(或**流**),而不仅仅是列表。 例如,我们最终将遍历文本文件的行或从操作系统获得的文件名序列。 序列非常强大,因为它允许我们处理比计算机内存大得多的数据。 我们可以零散地处理数据,而列表则要求所有元素同时存在于内存中。
......@@ -553,7 +553,7 @@ for q in reversed(Quantity):
如果我们并排排列两个列表并将它们粘合在一起,我们会得到**字典**。 字典将一个值映射到另一个值,就像现实世界中的字典将单词映射到定义一样。 这是一个示例字典,将电影标题映射到获得奥斯卡奖提名的年份:
<img src="images/dict.png" width="220">
<img src="img/dict.png" width="220">
```python
......
......@@ -355,7 +355,7 @@ Quantity2 = [6, 49, 0, 30, -19, 21, 12, 22, 21]
来自数学的 Sigma 符号以直接的方式转换为索引循环。例如:
<img src="images/formula-translation.png" width="490">
<img src="img/formula-translation.png" width="490">
我们从求和中选取元素并将它们插入模板中来获得索引循环。
......
......@@ -68,7 +68,7 @@ last=['Li', 'Smith', 'Dixon']
Let's start with a very simple but extremely common pattern called accumulate. The pattern traverses a sequence of elements and accumulates a value. For example, to sum the numbers in a sequence, we use the accumulator operation with the `+` operator. As we traverse the sequence, we update a running sum that's initialized to 0:
<img src="images/accumulator.png" width="290">
<img src="img/accumulator.png" width="290">
In Excel, this is like using `sum(...)` in a cell. In Python, the implementation of this pattern has an initialization step and a loop:
......@@ -91,7 +91,7 @@ A **counter** is a special case of an accumulator that counts the number of elem
We can update multiple running accumulated values, not just one. For example, let's say we wanted to count the number of even and odd values in a sequence. We need two accumulator values, both starting at zero, but the operation is the same:
<img src="images/accumulator-even-odd.png" width="320">
<img src="img/accumulator-even-odd.png" width="320">
The `+1` indicates an "add one to accumulated value" operation applied at each step but only if the current value is even or odd. In Python code, we'd do something like the following:
......@@ -112,7 +112,7 @@ print(even, odd)
Perhaps the most common operation *maps* one sequence to another, applying an operator or function to each element. (It's like an accumulator that accumulates a list of stuff instead of a single value.) For example, using a spreadsheet to create a new column containing the unit price discounted by 5% starts like this in a spreadsheet:
<img src="images/map-discount-op.png" width="390">
<img src="img/map-discount-op.png" width="390">
We can represent both lists at time 0 using list literals:
......@@ -124,7 +124,7 @@ Discounted = [] # empty list
In other words:
<img src="images/price-time0.png" width="400">
<img src="img/price-time0.png" width="400">
The translation process in our heads from high-level operation to pseudocode to code is a game of *word association*". When your brain sees an operation that maps a column of data to another, think "map". When your brain hears "map" it should generate the appropriate pseudocode loop, filling in the pieces appropriately. When your brain hears "for each blah blah", think "oh, for-each loop" and use the appropriate coding pattern:
......@@ -187,13 +187,13 @@ print(namelens)
Let's look at the code pattern to traverse two lists at once placing the result in a third list. For example, to compute the cost of a sales transaction, we multiply the quantity times the unit price. In a spreadsheet, that looks like this:
<img src="images/map-formula.png" width="250">
<img src="img/map-formula.png" width="250">
Dragging that formula down the Cost column, applies the formula to the following rows, thus, filling the new column.
Programmatically, what we're doing is multiplying the *ith* element from two different sequences and placing the result in the *ith* position of the output sequence:
<img src="images/map-mult.png" width="490">
<img src="img/map-mult.png" width="490">
At time zero, we have the following data available:
......@@ -321,11 +321,11 @@ print(Cost)
The opposite of combining is splitting where we split a stream into two or more new streams. For example, I often have to split the full names in a list into their first and last names. In a spreadsheet, we make a blank column:
<img src="images/split-names.png" width="250">
<img src="img/split-names.png" width="250">
and then split on the space character (In Excel, you use `Data` > `Text to Columns`) to get two new columns:
<img src="images/split-names-after.png" width="160">
<img src="img/split-names-after.png" width="160">
We could "undo" this split using a *combine* operation with the string concatenation operator, which would combine first and last names together into a new stream containing full names again.
......@@ -433,11 +433,11 @@ Length 3
The most general operation used to extract data from a list or sequence is called *filter*. For example, using Excel's filter mechanism, we can filter a Shipping column for those values less than $10:
<img src="images/filter-shipping.png" width="170">
<img src="img/filter-shipping.png" width="170">
The filter operation is similar to the map operation in that a computation is applied to each element of the input stream. Map applies a function to each element of a sequence and creates a new sequence of the same size. Filter tests each element for a specific condition and, if true, adds that element to the new sequence.
<img src="images/filter-apply.png" width="590">
<img src="img/filter-apply.png" width="590">
A filter operation is just a map that conditionally adds elements to the target list:
......@@ -469,7 +469,7 @@ print(Shipping2)
We can also filter on one column but keep the data within each row together. Here is an example, using Excel, that filters Oscar winners from the list of nominees (the condition is *winner equals 1*):
<img src="images/filter-winners.png" width="590">
<img src="img/filter-winners.png" width="590">
```python
......@@ -584,7 +584,7 @@ The `break` statement breaks out of the immediately-enclosing loop, regardless o
The search operation can even be used within a string (list of characters) to find the position of a character of interest. For example, to slice up a full name into first and last names, we can combine a search for the space character with two slice operations. Given full name `Xue Li`, a search for the space character returns the fourth position or index 3. To extract the first name, we slice from index 0 to index 3, exclusively on the right. To get the last name, we slice from index 4 to 6, exclusively on the right.
<img src="images/split-string.png" width="190">
<img src="img/split-string.png" width="190">
Here's what that looks like a python:
......@@ -622,7 +622,7 @@ We sometimes need to repeat repeated instructions, which we call a *nested loop*
Recall that, while we humans can look at the entire matrix at once, a computer examines each element one-by-one. Take a look at this 3x3 matrix:
<img src="images/matrixA.png" width="100">
<img src="img/matrixA.png" width="100">
which we can represent in python using a list of list:
......@@ -717,7 +717,7 @@ print(sum)
In the images project for this class, we do lots of fun things to images. An image is nothing more than a two-dimensional matrix whose entries are pixel grayscale values from 0 to 255. A pixel value of 0 is black and 255 is white. For example, if we zoom in on an image, we see the individual elements (called pixels) of a two-dimensional matrix:
<img src="images/obama-zoom.png" width="400">
<img src="img/obama-zoom.png" width="400">
The only difference between an image and a matrix is that we typically access the elements of an image using x and y coordinates, rather than row and column. The template for a nested loop that accesses each element of an image looks like this:
......@@ -731,7 +731,7 @@ Because the *y* coordinate varies faster than the *x* coordinate, the inner loop
As a more realistic example, let's add two matrices A and B together to form C. The key operation is to add A<sub>i,j</sub> to B<sub>i,j</sub> to get C<sub>i,j</sub>. Visually, it looks like this:
<img src="images/ABC.png" width="360">
<img src="img/ABC.png" width="360">
Write out the nested Python indexed loops to add two matrices together, C = A + B. Here are some definitions to get you started:
......
# Organizing your code with functions
<img src="images/pestle.png" width="75" align="right">Years ago I learned to make Thai red curry paste from scratch, including roasting then grinding seeds and pounding stuff in a giant mortar and pestle. It takes forever and so I generally buy curry paste ready-made from the store.
<img src="img/pestle.png" width="75" align="right">Years ago I learned to make Thai red curry paste from scratch, including roasting then grinding seeds and pounding stuff in a giant mortar and pestle. It takes forever and so I generally buy curry paste ready-made from the store.
<img src="images/redcurry.jpeg" width="70" align="right">Similarly, most cookbooks provide a number of fundamental recipes, such as making sauces, that are used by other recipes. A cookbook is organized into a series of executable recipes, some of which "invoke" other recipes. To make dinner, I open a cookbook, acquire some raw ingredients, then execute one or more recipes, usually in a specific sequence.
<img src="img/redcurry.jpeg" width="70" align="right">Similarly, most cookbooks provide a number of fundamental recipes, such as making sauces, that are used by other recipes. A cookbook is organized into a series of executable recipes, some of which "invoke" other recipes. To make dinner, I open a cookbook, acquire some raw ingredients, then execute one or more recipes, usually in a specific sequence.
Writing a program proceeds in the same way. Opening a cookbook is the same as importing libraries. Acquiring raw ingredients could mean loading data into the memory. The main program invokes functions (recipes) to accomplish a particular task. As part of writing a program, we will typically break out logical sections of code into functions specific to our problem, whereas the functions in libraries tend to be broadly-applicable.
......@@ -57,7 +57,7 @@ def funcname():
with holes for the function name, statements associated with a function, and an expression describing the return value. Functions that have no return value skip the `return` statement.
<img src="images/redbang.png" width="30" align="left"> The way that we associate statements with a function in Python is by indentation. So `return 3.14159` is part of the function because it is indented after the function header. The first statement that begins in the same column as the `def` is first statement outside of the function.
<img src="img/redbang.png" width="30" align="left"> The way that we associate statements with a function in Python is by indentation. So `return 3.14159` is part of the function because it is indented after the function header. The first statement that begins in the same column as the `def` is first statement outside of the function.
```python
......@@ -69,7 +69,7 @@ print("this is not part of function")
```
<img src="images/redbang.png" width="30" align="left">*The Python interpreter does not execute the code inside the function unless we directly invoke that function.* Python sees the function definition as just that: a "recipe" definition that we can call if we want.
<img src="img/redbang.png" width="30" align="left">*The Python interpreter does not execute the code inside the function unless we directly invoke that function.* Python sees the function definition as just that: a "recipe" definition that we can call if we want.
The *definition* of a function is different than invoking or *calling* a function. Calling a function requires the function name and any argument values. In this case, we don't have any arguments so we call the function as just `pi()`:
......@@ -201,7 +201,7 @@ This operation is accumulator and there is an associated code template, which yo
Summing values is very common so let's encapsulate the functionality in a function to avoid having to cut-and-paste the code template all the time. Our black box with a few sample "input-output" pairs from a function plan looks like:
<img src="images/sum-func.png" width="180">
<img src="img/sum-func.png" width="180">
(Laying out the examples like that made us realize that we need to worry about empty lists.)
......@@ -713,7 +713,7 @@ One of the big confusion points for students is the difference between return va
Programs in the analytics world typically read data from a file and emit output or write data to another file. In other words, programs interact with the world outside of the program. The world outside of the program is usually the network, the disk, or the screen. In contrast, most functions that we write won't interact with the outside world.
<img src="images/redbang.png" width="30" align="left">Functions compute and return (give values back) to their caller. They don't print anything to the user unless explicitly asked to do so with a `print` statement.
<img src="img/redbang.png" width="30" align="left">Functions compute and return (give values back) to their caller. They don't print anything to the user unless explicitly asked to do so with a `print` statement.
```python
......
......@@ -11,7 +11,7 @@ We read code in order to:
* **Discover the behavior of library functions or other shared code**. The complete behavior of a library function is not always clear from the name or parameter list. Looking at the source code for that function is the best way to understand what it does. The code **is** the documentation.
* **Uncover bugs, in our code or others' code**. All code has bugs, particularly code we just wrote that has not been tested exhaustively. As part of the coding process, we are constantly bouncing around, reading our existing code base to make sure everything fits together.
<img src="images/redbang.png" width="30" align="left">While we're discussing library functions, let me highlight a golden rule: *You should never ever ask your fellow programmers about the details of parameters and return values from library functions.* You can easily discover this yourself using "jump to definition" in PyCharm or by searching on the web.
<img src="img/redbang.png" width="30" align="left">While we're discussing library functions, let me highlight a golden rule: *You should never ever ask your fellow programmers about the details of parameters and return values from library functions.* You can easily discover this yourself using "jump to definition" in PyCharm or by searching on the web.
The purpose of this document is to explain how exactly a programmer reads code. Our first clue comes from the fact that we are not computers, hence, we should not read code like a computer, examining one symbol after the other. Instead, we're going to look for key elements and code patterns.
......@@ -176,7 +176,7 @@ print(blort)
Max value in `X`.
<img src="images/redbang.png" width="30" align="left">Anytime you see an `if` statement inside of a loop, think *filter* or *search* or *accumulator with condition*. It will usually be a variation on one of those. This assumes that the conditional expression is a function of the loop variable directly or indirectly.
<img src="img/redbang.png" width="30" align="left">Anytime you see an `if` statement inside of a loop, think *filter* or *search* or *accumulator with condition*. It will usually be a variation on one of those. This assumes that the conditional expression is a function of the loop variable directly or indirectly.
**Exercise**: What does this variation print?
......
......@@ -57,7 +57,7 @@ Later, when you are learning to write data to files, the close operation is also
> "It is a common bug to write a program where you have the code to add all the data you want to a file, but the program does not end up creating a file. Usually this means you forgot to close the file."
<img src="images/redbang.png" width="30" align="left"> To help avoid confusion, keep this analogy in mind. Your house contents (file) is different than your address (file name) and different than a piece of paper with the address written on it (file descriptor). More specifically:
<img src="img/redbang.png" width="30" align="left"> To help avoid confusion, keep this analogy in mind. Your house contents (file) is different than your address (file name) and different than a piece of paper with the address written on it (file descriptor). More specifically:
1. The filename is a string that identifies a file on the disk. It can be fully qualified or relative to the current working directory.
......@@ -89,7 +89,7 @@ True
You know what a file name is because you've created lots of files before. (BTW, another reminder not to use spaces in your file or directory names.) *Paths* are unique specifiers or locators for directories or files. A *fully-qualified* filename gives a description of the directories from the root of the file system, separated by `/`. The root of the file system is identified with `/` (forward slash) at the start of a pathname. You are probably used to seeing it as "Macintosh HD" but from a programming point of view, it's just `/`. On Windows, which we will not consider here, the root includes the drive specification and a backslash like `C:\`. Here's a useful diagram showing the components of a fully qualified pathname to a file called `view.py`:
<img src="images/path-names.png" width="750">
<img src="img/path-names.png" width="750">
As a shorthand, you can start a path with `~`, which means "my home directory". On a Mac that's `/Users/parrt` or whatever your user ID is. On Linux, it's probably `/home/parrt`.
......
......@@ -117,7 +117,7 @@ shape is (345, 1)
```
<img src="images/redbang.png" style="width:30px" align="left">The printed array looks like a list of lists but it is a different data type. Just because two data structures print out in the same way, doesn't mean that they are the same kinds of objects.
<img src="img/redbang.png" style="width:30px" align="left">The printed array looks like a list of lists but it is a different data type. Just because two data structures print out in the same way, doesn't mean that they are the same kinds of objects.
We can access the 2D NumPy arrays using array index notation *array*`[`*row*, *column*`]`:
......
......@@ -91,7 +91,7 @@ There are many approaches to finding function minima iteratively (i.e., non-anal
Gradient descent requires a starting position, $x_0$, the function to optimize, $f(x)$, and its derivative $f'(x)$. Recall that the derivative is just the slope of a function at a particular point. In other words, as $x$ shifts away from a specific position, does $f(x)$ go up or down, and by how much? E.g., the derivative of $x^2$ is $2x$, which gives us a positive slope when $x>0$ and a negative slope when $x<0$. Gradient descent uses the derivative to iteratively pick a new value of $x$ that gets us closer and closer to the minimum of $f(x)$. The negative of the slope tells us the direction (in $x$ units) of the nearest minimum. For example, here is the cosine graph again, this time showing a number of vectors representing derivatives at particular points.
<img src="images/cos-2minima-edited.png" width="300">
<img src="img/cos-2minima-edited.png" width="300">
Note that the derivative is zero, i.e. flat, at the minima (same is true for maxima). Notice that the derivatives (red vectors) point in the opposite direction of the nearest minimum. If we want to move in the direction of the nearest minimum, we should adjust $x$ by adding the negative of the derivative; i.e., we should subtract the derivative from $x_i$ to get $x_{i+1}$. The recurrence relation for updating our estimate of $x$ that minimizes $f(x)$ is then just:
......@@ -123,7 +123,7 @@ to see if the function is flattening out or when there is a very small vertical
The steps we take are scaled by the learning rate $\eta$. Yaser S. Abu-Mostafa has some [great slides](http://www.amlbook.com/slides/iTunesU_Lecture09_May_01.pdf) and videos that you should check out. Here is his description on slide 21 of how the learning rate can affect convergence:
<img src="images/stepsize.png" width="400">
<img src="img/stepsize.png" width="400">
The domain of $x$ also affects the learning rate magnitude. This is all a very complicated finicky business and those experienced in the field tell me it's very much an art picking the learning rate, starting positions, precision, and so on. You can start out with a low learning rate and crank it up to see if you still converge without oscillating around the minimum. An excellent description of gradient descent and other minimization techniques can be found in [Numerical Recipes](http://apps.nrbook.com/fortran/index.html).
......@@ -151,9 +151,9 @@ x _{i+1} = x_i - \eta (f(x_{i}+h) - f(x_{i}))
Our goal is to use gradient descent to minimize $f(x) = cos(3\pi x) / x$. To increase chances of finding the global minimum, we can pick a few random starting locations in the range $[0.1,1.3]$ using standard python {\tt random.uniform()} and perform gradient descent on all of them. To observe our minimizer in action, we'll eventually plot the trace of $x$'s that indicate the steps taken by our gradient descent. Here are two sample descents where the $x$ and $f(x)$ values are displayed as well as the minima:
<img src="images/cos-trace-2minima.svg" width="350">
<img src="img/cos-trace-2minima.svg" width="350">
<img src="images/cos-trace-2minima-another.svg" width="350">
<img src="img/cos-trace-2minima-another.svg" width="350">
Recall from our square root lecture that we had a basic outline for an iterative method:
......@@ -256,7 +256,7 @@ def viz_trace(x0, minimizer):
fontsize=14)
plt.text(0.3, 3.7, f"steps = {len(tracex)}", fontsize=14)
plt.tight_layout()
plt.savefig("images/cos-trace-2minima-another.svg")
plt.savefig("img/cos-trace-2minima-another.svg")
plt.show()
```
......
......@@ -50,7 +50,7 @@ After you execute a command by typing a command possibly with arguments and hitt
Any *path* starting with `/` means it is an absolute path starting at the root of the disk directory hierarchy. (You can learn more about [paths at wikipedia](https://en.wikipedia.org/wiki/Path_(computing)#Unix_style)). So anything else is considered relative to the current working directory. For example, if your current working directory is `/Users/parrt/github/msan501` then `ls notes` will give you a directory listing of the `notes` directory underneath `/Users/parrt/github/msan501`. Here's a useful diagram showing the components of a fully qualified pathname to a file called `view.py`:
<img src=images/path-names.png width=750>
<img src=img/path-names.png width=750>
One of the most common things to do is to change the current working directory with `cd`:
......
......@@ -22,9 +22,9 @@ A `git` repository instance is just a directory on your disk but it also has a `
As with the Time Machine backup, git tracks snapshots as the difference from the last time you requested a snapshot. Each snapshot is called a *commit* (and programmers think of these commits as *transactions*.) You should request a commit to lock in a logical chunk of work, such as the addition of a feature or fixing of a bug. Having a complete list of changes is extremely useful. For example, here is a chunk taken out of the middle of my commits on the ANTLR repository as shown by the [SourceTree](https://www.sourcetreeapp.com) git GUI:
![commits](images/commits.png)
![commits](img/commits.png)
<img src="images/redbang.png" width=30 align="left">You can go back and look at changes made to the repository for any commit. Whether using PyCharm or git, I find it very important to look back at recent commits to see what changes have introduced a bug. Sometimes I decide to abandon a small piece of what's going on and flip a file back to an old version. If you go down a wrong path and would like to revert all those changes, git can easily do that. It can even reset the repository to the state of some earlier commit.
<img src="img/redbang.png" width=30 align="left">You can go back and look at changes made to the repository for any commit. Whether using PyCharm or git, I find it very important to look back at recent commits to see what changes have introduced a bug. Sometimes I decide to abandon a small piece of what's going on and flip a file back to an old version. If you go down a wrong path and would like to revert all those changes, git can easily do that. It can even reset the repository to the state of some earlier commit.
**Mirroring repositories at github.com**
......@@ -46,7 +46,7 @@ Each class I teach will have be its own organization at github, in this case: `h
Our first step is to *clone* that empty repository from github onto our local disk. From your repository page and github, copy the HTTPS URL, as shown here:
<img src=images/github-setup.png width=420>
<img src=img/github-setup.png width=420>
If you choose the SSH version, it will require that we set up SSH keys for authentication. That is what you will ultimately want to do, but for now, don't worry about that and just use HTTPS.
......@@ -63,7 +63,7 @@ $ mkdir msan501 # create directory msan501 under classes
$ cd msan501 # jump into msan501
```
<img src="images/redbang.png" width=30 align="left">Do not use spaces in any filename or directory you ever create. Many open source projects are developed under UNIX and UNIX hates spaces in filenames. Things will mysteriously fail to work if you use spaces.
<img src="img/redbang.png" width=30 align="left">Do not use spaces in any filename or directory you ever create. Many open source projects are developed under UNIX and UNIX hates spaces in filenames. Things will mysteriously fail to work if you use spaces.
Depending on how you have your shell set up, you might see the current working directory to the left of the `$` prompt. Here is what my prompt looks like:
......@@ -152,7 +152,7 @@ Date: Fri Jun 30 12:50:42 2017 -0700
initial add
```
<img src="images/redbang.png" width=30 align="left">Until you explicitly push back to github, github has no idea that you made changes on your local disk to a repository. Git knows where the original repository came from but it does not automatically push anything to github upon commit. Commit is for the local repository, push is for syncing with a remote repository. The remote repository is called the *origin*. Use the following command to ask git what it thinks the origin is:
<img src="img/redbang.png" width=30 align="left">Until you explicitly push back to github, github has no idea that you made changes on your local disk to a repository. Git knows where the original repository came from but it does not automatically push anything to github upon commit. Commit is for the local repository, push is for syncing with a remote repository. The remote repository is called the *origin*. Use the following command to ask git what it thinks the origin is:
```
$ git remote -v
......
......@@ -9,37 +9,37 @@ Here is a video I made for MSAN692 showing [how to launch an AWS instance and st
Login to AWS and go to your [AWS console](http://aws.amazon.com/console) and click on the "EC2" link.
<img src=images/console_snippet.png width=200>
<img src=img/console_snippet.png width=200>
Click "Launch Instance", which will start the process to create a virtual machine in the cloud. An instance is just a virtual machine.
<img src=images/launch.png width=400>
<img src=img/launch.png width=400>
Select the "Amazon Linux 2 AMI" entry, which should be the first one. This is a commonly-used "image" that results in a Linux machine that contains lots of useful goodies as you can see from that list, such as Python and MySQL. An image is just a snapshot of the disk after someone carefully installs software properly on a Linux machine. This means we don't have to install software every time we create a new machine.
<img src=images/ami.png width=600>
<img src=img/ami.png width=600>
Select instance type "t2.micro," which should be the first machine type listed. This machine is very low powered but is sufficient for playing around. Click "Review and launch"
<img src=images/selectvm.png width=600>
<img src=img/selectvm.png width=600>
This will bring up a screen describing the details about the instance we are launching. Ignore all of it for now and just click "Review and Launch" at the bottom right. That brings up a summary page that we could examine if we wanted, but just click "Launch" in bottom right.
This will bring a dialog box up to select a key pair. A key pair is what allows you to securely access the server and prevent unauthorized access. The *first time*, you will need to create a new key pair. Name it as your user ID then click on "Download key pair." It will download a *userid*.pem file, which are your security credentials for getting into the machine. Save that file in a safe spot. If you lose it you will not be able to get into the machine that you create. From now on, you can reuse that pre-existing key.
<img src=images/keypair.png width=600>
<img src=img/keypair.png width=600>
After downloading, click "Launch instances." You should see something like:
<img src=images/launched.png width=600>
<img src=img/launched.png width=600>
Click on the `i-...` link to go to the EC2 console showing your instance.
<img src=images/ec2-instance.png width=600>
<img src=img/ec2-instance.png width=600>
Click on your instance and you should see a description box at the bottom. Look for the "Public IP" address, which is 54.196.174.210 in this case:
<img src=images/publicIP.png width=600>
<img src=img/publicIP.png width=600>
We have to wait until the status stops saying "Initializing", which could take several minutes.
......@@ -47,7 +47,7 @@ We have to wait until the status stops saying "Initializing", which could take s
Click on the "Connect" button at the top of the page and it will bring up a dialog box that tells you how to connect to the server. You want to connect with "A standalone SSH client" link (Java is now a security risk in the browser so we can't use that choice.) Inside you will see the `ssh` command necessary to connect to your machine. If you have Windows, there is a link to show you how to use an SSH client called PuTTY.
<img src=images/connect.png width=550>
<img src=img/connect.png width=550>
Before we can connect, we have to make sure that the security file is not visible to everyone on the computer (other users). Otherwise ssh will not let us connect because the security file is not secure:
......@@ -125,15 +125,15 @@ The `$` is your prompt just like you have on your local machine using the termin
You can either hit "command-T" from Terminal.app and get multiple tabs up, one for the remote host and one for local/laptop work:
<img src="images/tabs.png" width="500">
<img src="img/tabs.png" width="500">
Or just get two windows up using "command-N" from Terminal.app.
<img src="images/two-shells.png" width="500">
<img src="img/two-shells.png" width="500">
Verify the remote computer is not your laptop by doing command `ls /` on both computers:
<img src="images/two-roots.png" width="500">
<img src="img/two-roots.png" width="500">
## Uploading data or code
......@@ -195,6 +195,6 @@ To exit the remote server, type `exit` or use `^D` from the `$` prompt. The mach
Play around with your instance and then **TERMINATE YOUR INSTANCE WHEN YOU ARE DONE**, otherwise you will continue to get charged for the use of that machine. Right-click on the instance from your AWS console and select "instance state" then submenu "terminate". It will warn you that all of your local storage will go away. Hit the "yes, terminate" button. It should look like this when done:
<img src=images/terminated.png width=450>
<img src=img/terminated.png width=450>
If you say "stop" instead, it will stop the machine, but you still get charged. On the other hand, this is useful because you can restart that machine without having to go through this whole procedure. All of your data will be intact. If you say "Terminate", it will toss the machine out and you will have to go through this procedure again to get a new machine.
......@@ -22,21 +22,21 @@ The simplest list has one element with a `next` pointer/reference that points at
```python
users = ("parrt", None)
```
<img src="images/links1.png" style="width:200px">
<img src="img/links1.png" style="width:200px">
Here's one with two elements:
```python
users = ("parrt", ("tombu", None))
```
<img src="images/links2.png" style="width:290px">
<img src="img/links2.png" style="width:290px">
and three elements:
```python
users = ("parrt", ("tombu", ("afedosov", None)))
```
<img src="images/links3.png" style="width:400px">
<img src="img/links3.png" style="width:400px">
In practice, we'll use lists not tuples, because tuples are immutable. We want to be able to change the node `next` pointers:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册