Notion - Update docs

This commit is contained in:
tuantinghuang 2024-01-04 10:37:34 +00:00 committed by GitHub
parent 3cb7e2e104
commit 20ddf25822
34 changed files with 67 additions and 60 deletions

View file

@ -601,7 +601,7 @@ function draw() {
let center = createVector(width / 2, height / 2);
mouse.sub(center);
// The magnitude (that is, length) of a vector can be accessed via the `mag()` function. Here it is used as the width of a rectangle drawn at the top of the window.
// The magnitude (that is, length) of a vector can be accessed via the <code>mag()</code> function. Here it is used as the width of a rectangle drawn at the top of the window.
let m = mouse.mag();
fill(0);
rect(0, 0, m, 10);

View file

@ -836,14 +836,14 @@ function draw() {
connect(bob) {
// Get a vector pointing from the anchor to the bob position.
<strong>let force = p5.Vector.sub(bob.position, this.anchor);</strong>
// Calculate the displacement between distance and rest length. Ill use the variable name “stretch” instead of “x” to be more descriptive.
// Calculate the displacement between distance and rest length. Ill use the variable name <code>stretch</code> instead of <code>x</code> to be more descriptive.
<strong>let currentLength = force.mag();
let stretch = currentLength - this.restLength;</strong>
// Direction and magnitude together!
<strong>force.setMag(-1 * this.k * stretch);</strong>
// Call applyForce() right here!
// Call <code>applyForce()</code> right here!
bob.applyForce(force);
}

View file

@ -963,7 +963,11 @@ for (let i = 0; i &#x3C; path.points.length - 1; i++) {
Stated more evocatively, the theory is that a single butterfly flapping its wings on the other side of the world could cause a massive weather shift and ruin your weekend at the beach. Its called <em>nonlinear</em> because there isnt a linear relationship between a change in initial conditions and a change in outcome. A small change in initial conditions can have a massive effect on the outcome. Nonlinear systems are a superset of chaotic systems. In <a href="/cellular-automata#">Chapter 7</a>, youll see how even in a system of many 0s and 1s, if you change just one bit, the result will be completely different.
</li>
<li><strong>Competition and cooperation:</strong> One ingredient that often makes a complex system tick is the presence of both competition and cooperation among the elements. The upcoming flocking system will have three rules: alignment, cohesion, and separation. Alignment and cohesion will ask the elements to “cooperate” by trying to stay together and move together. Separation, however, will ask the elements to “compete” for space. When the time comes, try taking out just the cooperation or just the competition, and youll see how the system loses its complexity. Competition and cooperation are found together in living complex systems, but not in nonliving complex systems like the weather.</li>
<li><strong>Feedback:</strong> Complex systems often include a loop that feeds the output of the system back into the system to influence its behavior in a positive or negative direction. Lets say you decide to take public transportation to work each day because its the most reliable and cost-effective solution, and youre put off by the traffic congestion and environmental impact of driving. You arent alone; others turn to public transportation too. The system grows more efficient and attractive, serving more people with the same resources, and meanwhile, vehicle traffic is reduced. Over time, however, the system may struggle to accommodate the rising demand, leading to overcrowding, delays, and increased fares to fund infrastructure improvements. As a result, you and others start to switch back to driving, thereby increasing traffic congestion once again and reducing public transports efficiency. As traffic worsens, the funds from increased fares are (hopefully) used to improve public transport infrastructure, making it more appealing once again. In this way, the cost and efficiency of public transportation are both the input of the system (determining whether you choose to use it or not) and the output (the degree of traffic congestion and subsequent cost and efficiency). Economic models are just one example of a human complex system. Others include fads and trends, elections, crowds, and traffic flow.</li>
<li>
<strong>Feedback:</strong> Complex systems often include a loop that feeds the output of the system back into the system to influence its behavior in a positive or negative direction. Lets say you decide to take public transportation to work each day because its the most reliable and cost-effective solution, and youre put off by the traffic congestion and environmental impact of driving. You arent alone; others turn to public transportation too. The system grows more efficient and attractive, serving more people with the same resources, and meanwhile, vehicle traffic is reduced.
Over time, however, the system may struggle to accommodate the rising demand, leading to overcrowding, delays, and increased fares to fund infrastructure improvements. As a result, you and others start to switch back to driving, thereby increasing traffic congestion once again and reducing public transports efficiency. As traffic worsens, the funds from increased fares are (hopefully) used to improve public transport infrastructure, making it more appealing once again.
In this way, the cost and efficiency of public transportation are both the input of the system (determining whether you choose to use it or not) and the output (the degree of traffic congestion and subsequent cost and efficiency). Economic models are just one example of a human complex system. Others include fads and trends, elections, crowds, and traffic flow.
</li>
</ul>
<p>Complexity will serve as a key theme for much of the remainder of the book. In this section, Ill begin by introducing an additional feature to the <code>Vehicle</code> class: the ability to perceive neighboring vehicles. This enhancement will pave the way for a culminating example of a complex system, in which the interplay of simple individual behaviors results in an emergent behavior: flocking<em>.</em></p>
<h3 id="implementing-group-behaviors-or-lets-not-run-into-each-other">Implementing Group Behaviors (or: Lets Not Run Into Each Other)</h3>

View file

@ -317,7 +317,7 @@ function rules(a, b, c) {
</figure>
<p>First, this visual interpretation of the data is completely literal. Its useful for demonstrating the algorithms and results of Wolframs elementary CA, but it shouldnt necessarily drive your own personal work. Youre not likely building a project that needs precisely this algorithm with this visual style. So while learning to draw a CA in this way will help you understand and implement CA systems, this skill should exist only as a foundation.</p>
<p>Second, the fact that a 1D CA is visualized with a 2D image can be misleading. Its very important to remember that this is <em>not</em> a 2D CA. Im simply choosing to show a history of all the generations stacked vertically. This technique creates a 2D image out of many instances of 1D data, but the system itself is 1D. Later, Ill show you an actual 2D CA (the Game of Life), and Ill cover how to visualize such a system.</p>
<p>The good news is that drawing an elementary CA isnt particularly difficult. Ill begin by rendering a single generation. Lets say each cell should be a 10 by 10 square:</p>
<p>The good news is that drawing an elementary CA isnt particularly difficult. Ill begin by rendering a single generation. Lets say each cell should be a 10<span data-type="equation">\times</span>10 square:</p>
<pre class="codesplit" data-code-language="javascript">let w = 10;</pre>
<p>Assuming the canvas is 640 pixels wide, the CA will have 64 cells. Of course, I can calculate this value dynamically when I initialize the <code>cells</code> array in <code>setup()</code>:</p>
<pre class="codesplit" data-code-language="javascript">//{!1} How many cells fit across, given a certain width
@ -558,7 +558,7 @@ if (board[i + 1][j ] === 1) sum++;
if (board[i - 1][j + 1] === 1) sum++;
if (board[i ][j + 1] === 1) sum++;
if (board[i + 1][j + 1] === 1) sum++;</pre>
<p>Just as with the Wolfram CA, I find myself writing out a bunch of <code>if</code> statements. This is another situation where, for teaching purposes, its useful and clear to write the code this way, explicitly stating every step (each time a neighbor has a state of 1, the counter increases). Nevertheless, its a bit silly to say, “If the cell state equals 1, add 1 to a counter” when I could instead just say, “Add every cell state to a counter.” After all, if the state can be only 0 or 1, the sum of all the neighbors states will yield the total number of live cells. Since the neighbors are arranged in a mini 3 by 3 grid, I can introduce another nested loop to compute the sum more efficiently:</p>
<p>Just as with the Wolfram CA, I find myself writing out a bunch of <code>if</code> statements. This is another situation where, for teaching purposes, its useful and clear to write the code this way, explicitly stating every step (each time a neighbor has a state of 1, the counter increases). Nevertheless, its a bit silly to say, “If the cell state equals 1, add 1 to a counter” when I could instead just say, “Add every cell state to a counter.” After all, if the state can be only 0 or 1, the sum of all the neighbors states will yield the total number of live cells. Since the neighbors are arranged in a mini 3<span data-type="equation">\times</span>3 grid, I can introduce another nested loop to compute the sum more efficiently:</p>
<pre class="codesplit" data-code-language="javascript">let sum = 0;
//{!2} Use k and l as the counters since i and j are already used!

View file

@ -47,7 +47,7 @@
<img src="images/08_fractals/08_fractals_5.png" alt="Figure 8.4: Two coastlines">
<figcaption>Figure 8.4: Two coastlines</figcaption>
</figure>
<p>The absence of a scale in these illustrations is no accident. Am I showing the entire coastline or just a small portion of it? Theres no way for you to know without a scale reference because coastlines, as fractals, look essentially the same at any scale. (Incidentally, coastline B shows an approximately 3X magnified view of a specific section of coastline A. Ive added the scales in Figure 8.5.)</p>
<p>The absence of a scale in these illustrations is no accident. Am I showing the entire coastline or just a small portion of it? Theres no way for you to know without a scale reference because coastlines, as fractals, look essentially the same at any scale. (Incidentally, coastline B shows an approximately 3<span data-type="equation">\times</span> magnified view of a specific section of coastline A. Ive added the scales in Figure 8.5.)</p>
<figure>
<img src="images/08_fractals/08_fractals_6.png" alt="Figure 8.5: Two coastlines, with scale">
<figcaption>Figure 8.5: Two coastlines, with scale</figcaption>
@ -653,24 +653,24 @@ for (let i = 0; i &#x3C; message.length; i++) {
<ul>
<li><strong>Alphabet:</strong> An L-systems alphabet comprises the valid characters that can be included. For example, I could say the alphabet is ABC, meaning that any valid “sentence” (a string of characters) in an L-system can include only these three characters.</li>
<li><strong>Axiom:</strong> The axiom is a sentence (created with characters from the alphabet) that describes the initial state of the system. For example, with the alphabet ABC, a possible axiom could be AAA, or B, or ACBAB.</li>
<li><strong>Rules:</strong> The production rules of an L-system describe ways of transforming the sentence. The rules are applied recursively, starting with the axiom, generating new sentences over and over again. An L-system rule includes two sentences, a <em>predecessor</em> and a <em>successor</em>. For example, the rule A —> AB means that wherever an A (the predecessor) occurs in a sentence, it should be replaced with AB (the successor) in the next generation.</li>
<li><strong>Rules:</strong> The production rules of an L-system describe ways of transforming the sentence. The rules are applied recursively, starting with the axiom, generating new sentences over and over again. An L-system rule includes two sentences, a <em>predecessor</em> and a <em>successor</em>. For example, the rule A AB means that wherever an A (the predecessor) occurs in a sentence, it should be replaced with AB (the successor) in the next generation.</li>
</ul>
<p>Ill begin with a simple L-system. In fact, its Lindenmayers original L-system, which models the growth of algae. Here are its components:</p>
<table>
<tbody>
<tr>
<td>Alphabet</td>
<td><span data-type="equation">A</span>, <span data-type="equation">B</span></td>
<td>A, B</td>
</tr>
<tr>
<td>Axiom</td>
<td><span data-type="equation">A</span></td>
<td>A</td>
</tr>
<tr>
<td>Rules</td>
<td>
<span data-type="equation">A→AB</span>
<span data-type="equation">B→A</span>
A → AB
B → A
</td>
</tr>
</tbody>
@ -746,17 +746,17 @@ function generate() {
<tbody>
<tr>
<td>Alphabet</td>
<td><span data-type="equation">A</span>, <span data-type="equation">B</span></td>
<td>A, B</td>
</tr>
<tr>
<td>Axiom</td>
<td><span data-type="equation">A</span></td>
<td>A</td>
</tr>
<tr>
<td>Rules</td>
<td>
<span data-type="equation">A→ABA</span>
<span data-type="equation">B→BBB</span>
A → ABA
B → BBB
</td>
</tr>
</tbody>
@ -766,19 +766,19 @@ function generate() {
<tbody>
<tr>
<td>Generation 0</td>
<td><span data-type="equation">A</span></td>
<td>A</td>
</tr>
<tr>
<td>Generation 1</td>
<td><span data-type="equation">ABA</span></td>
<td>ABA</td>
</tr>
<tr>
<td>Generation 2</td>
<td><span data-type="equation">ABABBBABA</span></td>
<td>ABABBBABA</td>
</tr>
<tr>
<td>Generation 3</td>
<td><span data-type="equation">ABABBBABABBBBBBBBBABABBBABA</span></td>
<td>ABABBBABABBBBBBBBBABABBBABA</td>
</tr>
</tbody>
</table>
@ -786,11 +786,11 @@ function generate() {
<table>
<tbody>
<tr>
<td><span data-type="equation">A</span></td>
<td>A</td>
<td>Draw a line forward.</td>
</tr>
<tr>
<td><span data-type="equation">B</span></td>
<td>B</td>
<td>Move forward (without drawing a line).</td>
</tr>
</tbody>
@ -805,27 +805,27 @@ function generate() {
<table>
<tbody>
<tr>
<td><span data-type="equation">F</span></td>
<td>F</td>
<td>Draw a line and move forward.</td>
</tr>
<tr>
<td><span data-type="equation">G</span></td>
<td>G</td>
<td>Move forward (without drawing a line).</td>
</tr>
<tr>
<td><span data-type="equation">+</span></td>
<td>+</td>
<td>Turn right.</td>
</tr>
<tr>
<td><span data-type="equation">-</span></td>
<td></td>
<td>Turn left.</td>
</tr>
<tr>
<td><span data-type="equation">[</span></td>
<td>[</td>
<td>Save current state.</td>
</tr>
<tr>
<td><span data-type="equation">]</span></td>
<td>]</td>
<td>Restore current state.</td>
</tr>
</tbody>
@ -834,38 +834,38 @@ function generate() {
<table>
<tbody>
<tr>
<td><span data-type="equation">F</span></td>
<td>F</td>
<td>
<pre><code>line(0, 0, 0, length);
translate(0, length);</code></pre>
</td>
</tr>
<tr>
<td><span data-type="equation">G</span></td>
<td>G</td>
<td>
<pre><code>translate(0, length);</code></pre>
</td>
</tr>
<tr>
<td><span data-type="equation">+</span></td>
<td>+</td>
<td>
<pre><code>rotate(angle);</code></pre>
</td>
</tr>
<tr>
<td><span data-type="equation">-</span></td>
<td></td>
<td>
<pre><code>rotate(-angle);</code></pre>
</td>
</tr>
<tr>
<td><span data-type="equation">[</span></td>
<td>[</td>
<td>
<pre><code>push();</code></pre>
</td>
</tr>
<tr>
<td><span data-type="equation">]</span></td>
<td>]</td>
<td>
<pre><code>pop();</code></pre>
</td>
@ -902,15 +902,15 @@ translate(0, length);</code></pre>
<tbody>
<tr>
<td>Alphabet</td>
<td><span data-type="equation">F</span>, <span data-type="equation">G</span>, <span data-type="equation">+</span>, <span data-type="equation">-</span>, <span data-type="equation">[</span> , <span data-type="equation">]</span></td>
<td>F, G, +, , [, ]</td>
</tr>
<tr>
<td>Axiom</td>
<td><span data-type="equation">F</span></td>
<td>F</td>
</tr>
<tr>
<td>Rules</td>
<td><span data-type="equation">F → FF+[+F-F-F]-[-F+F+F]</span></td>
<td>F → FF + [+ F F F] [ F + F + F]</td>
</tr>
</tbody>
</table>

View file

@ -55,7 +55,10 @@ console.log(s);</pre>
<ul>
<li><strong>Heredity:</strong> There must be a mechanism that allows <em>parent</em> creatures in one generation to pass their traits down to <em>child</em> creatures in the next generation.</li>
<li><strong>Variation: </strong>There must be a variety of traits present in the population of creatures or a means to introduce variation for evolution to take place. Imagine a population of beetles that were exactly the same: same color, same size, same wingspan, same everything. Without any variety in the population, the children would always be identical to the parents and to each other. New combinations of traits could never occur, and nothing could evolve.</li>
<li><strong>Selection: </strong>There must be a mechanism by which some creatures have the opportunity to be parents and pass on their genetic information, while others dont. This is commonly referred to as <em>survival of the fittest</em>. Take, for example, a population of gazelles that are chased by lions. The faster gazelles have a better chance of escaping the lions, increasing their chances of living longer, reproducing, and passing on their genetic information to offspring. The term <em>fittest</em> can be misleading, however. Its often thought to mean biggest, fastest, or strongest, but while it can sometimes encompass physical attributes like size, speed, or strength, it doesnt have to. The core of natural selection lies in whatever traits best suit an organisms environment and increase its likelihood of survival and ultimately reproduction. Instead of asserting superiority, <em>fittest</em> can be better understood as “able to reproduce.” Take the <em>Dolania americana</em> (also known as the American sand-burrowing mayfly), which is believed to have the shortest lifespan of any insect. An adult female lives for only five minutes, but as long as it has managed to deposit its egg in the water, it will pass its genetic information to the next generation. For the typing cats, a more <em>fit</em> cat, one that I will assign as more likely to reproduce, is one that has typed more characters present in a given phrase of Shakespeare.</li>
<li>
<strong>Selection: </strong>There must be a mechanism by which some creatures have the opportunity to be parents and pass on their genetic information, while others dont. This is commonly referred to as <em>survival of the fittest</em>. Take, for example, a population of gazelles that are chased by lions. The faster gazelles have a better chance of escaping the lions, increasing their chances of living longer, reproducing, and passing on their genetic information to offspring.
The term <em>fittest</em> can be misleading, however. Its often thought to mean biggest, fastest, or strongest, but while it can sometimes encompass physical attributes like size, speed, or strength, it doesnt have to. The core of natural selection lies in whatever traits best suit an organisms environment and increase its likelihood of survival and ultimately reproduction. Instead of asserting superiority, <em>fittest</em> can be better understood as “able to reproduce.” Take the <em>Dolania americana</em> (also known as the American sand-burrowing mayfly), which is believed to have the shortest lifespan of any insect. An adult female lives for only five minutes, but as long as it has managed to deposit its egg in the water, it will pass its genetic information to the next generation. For the typing cats, a more <em>fit</em> cat, one that I will assign as more likely to reproduce, is one that has typed more characters present in a given phrase of Shakespeare.
</li>
</ul>
<p>I want to emphasize the context in which Im applying these Darwinian concepts: a simulated, artificial environment where specific goals can be quantified, all for the sake of creative exploration. Throughout history, the principles of genetics have been used to harm those who have been marginalized and oppressed by dominant societal structures. I believe it is essential to approach projects involving GAs with careful consideration of the language used, and to ensure that the documentation and descriptions of the work are framed inclusively.</p>
<p>With these concepts established, Ill begin walking through the GA narrative. Ill do this in the context of typing cats. The algorithm will be divided into several steps that unfold over two parts: a set of conditions for initialization, and the steps that are repeated over and over again until the correct phrase is found.</p>
@ -648,7 +651,7 @@ function draw() {
population[i] = child;
}
// <strong>Step 4: Repeatgo back to the beginning of draw()</strong><strong>!</strong>
// <strong>Step 4: Repeatgo back to the beginning of draw()</strong><strong>!</strong>
}</pre>
<p>The <em>sketch.js</em> file precisely mirrors the steps of the GA. However, most of the functionality called upon is encapsulated in the <code>DNA</code> class:</p>
<pre class="codesplit" data-code-language="javascript">

View file

@ -288,24 +288,24 @@ let guess = perceptron.feedForward(inputs);</pre>
</thead>
<tbody>
<tr>
<td><span data-type="equation">-1</span></td>
<td><span data-type="equation">-1</span></td>
<td><span data-type="equation">0</span></td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td><span data-type="equation">-1</span></td>
<td><span data-type="equation">+1</span></td>
<td><span data-type="equation">-2</span></td>
<td>1</td>
<td>+1</td>
<td>2</td>
</tr>
<tr>
<td><span data-type="equation">+1</span></td>
<td><span data-type="equation">-1</span></td>
<td><span data-type="equation">+2</span></td>
<td>+1</td>
<td>1</td>
<td>+2</td>
</tr>
<tr>
<td><span data-type="equation">+1</span></td>
<td><span data-type="equation">+1</span></td>
<td><span data-type="equation">0</span></td>
<td>+1</td>
<td>+1</td>
<td>0</td>
</tr>
</tbody>
</table>
@ -496,7 +496,7 @@ function draw() {
<h3 id="exercise-101">Exercise 10.1</h3>
<p>Modify the code from Example 10.1 to also draw the perceptrons current decision boundary during the training process—its best guess for where the line should be. Hint: Use the perceptrons current weights to calculate the lines equation.</p>
</div>
<p>While this perceptron example offers a conceptual foundation, real-world datasets often feature more diverse and dynamic ranges of input values. For the simplified scenario here, the range of values for <em>x</em> is larger than that for <em>y</em> because of the canvas size of 640 by 240. Despite this, the example still works—after all, the sign activation function doesnt rely on specific input ranges, and its such a straightforward binary classification task.</p>
<p>While this perceptron example offers a conceptual foundation, real-world datasets often feature more diverse and dynamic ranges of input values. For the simplified scenario here, the range of values for <em>x</em> is larger than that for <em>y</em> because of the canvas size of 640<span data-type="equation">\times</span>240. Despite this, the example still works—after all, the sign activation function doesnt rely on specific input ranges, and its such a straightforward binary classification task.</p>
<p>However, real-world data often has much greater complexity in terms of input ranges. To this end, <strong>data normalization</strong> is a critical step in machine learning. Normalizing data involves mapping the training data to ensure that all inputs (and outputs) conform to a uniform range—typically 0 to 1, or perhaps 1 to 1. This process can improve training efficiency and prevent individual inputs from dominating the learning process. In the next section, using the ml5.js library, Ill build data normalization into the process.</p>
<div data-type="exercise">
<h3 id="exercise-102">Exercise 10.2</h3>
@ -572,7 +572,7 @@ function draw() {
<figcaption>Figure 10.14: Labeling images as cats or dogs</figcaption>
</figure>
<p>Classification doesnt happen by magic. The model must first be shown many examples of dogs and cats with the correct labels in order to properly configure the weights of all the connections. This is the training part of supervised learning.</p>
<p>The classic “Hello, world!” demonstration of machine learning and supervised learning is a classification problem of the MNIST dataset. Short for <em>Modified National Institute of Standards and Technology</em>, <em>MNIST</em> is a dataset that was collected and processed by Yann LeCun (Courant Institute, NYU), Corinna Cortes (Google Labs), and Christopher J. C. Burges (Microsoft Research). Widely used for training and testing in the field of machine learning, this dataset consists of 70,000 handwritten digits from 0 to 9; each is a 28 by 28-pixel grayscale image (see Figure 10.15 for examples). Each image is labeled with its corresponding digit.</p>
<p>The classic “Hello, world!” demonstration of machine learning and supervised learning is a classification problem of the MNIST dataset. Short for <em>Modified National Institute of Standards and Technology</em>, <em>MNIST</em> is a dataset that was collected and processed by Yann LeCun (Courant Institute, NYU), Corinna Cortes (Google Labs), and Christopher J. C. Burges (Microsoft Research). Widely used for training and testing in the field of machine learning, this dataset consists of 70,000 handwritten digits from 0 to 9; each is a 28<span data-type="equation">\times</span>28 pixel grayscale image (see Figure 10.15 for examples). Each image is labeled with its corresponding digit.</p>
<figure>
<img src="images/10_nn/10_nn_17.png" alt="Figure 10.15: A selection of handwritten digits 09 from the MNIST dataset (image by Suvanjanprasai, CC-SA-4.0)">
<figcaption>Figure 10.15: A selection of handwritten digits 09 from the MNIST dataset (image by Suvanjanprasai, CC-SA-4.0)</figcaption>
@ -921,15 +921,15 @@ function gotResults(error, results) {
status = results[0].label;
}</pre>
<p>Since the <code>results</code> array is sorted by confidence, if I just want to use a single label as the prediction, I can access the first element of the array with <code>results[0].label</code>, as in the <code>gotResults()</code> function in Example 10.2. This label is passed to the <code>status</code> variable to be displayed on the canvas.</p>
<div data-type="note">
<div data-type="exercise">
<h3 id="exercise-105">Exercise 10.5</h3>
<p>Divide Example 10.2 into three sketches: one for collecting data, one for training, and one for deployment. Use the <code>ml5.neuralNetwork</code> functions <code>save()</code> and <code>load()</code> for saving and loading the model to and from a file, respectively.</p>
</div>
<div data-type="note">
<div data-type="exercise">
<h3 id="exercise-106">Exercise 10.6</h3>
<p>Expand the gesture-recognition model to classify a sequence of vectors, capturing more accurately the path of a longer mouse movement. Remember, your input data must have a consistent shape, so youll have to decide how many vectors to use to represent a gesture and store no more and no less for each data point. While this approach can work, other machine learning models (such as recurrent neural networks) are specifically designed to handle sequential data and might offer more flexibility and potential accuracy.</p>
</div>
<div data-type="note">
<div data-type="exercise">
<h3 id="exercise-107">Exercise 10.7</h3>
<p>One of the pretrained models in ml5.js is called <em>Handpose</em>. The input of the model is an image, and the prediction is a list of 21 key points—x- and y-positions, also known as <em>landmarks</em>—that describe a hand.</p>
<figure>

View file

@ -201,7 +201,7 @@ function draw() {
}
}</pre>
<p>The trickiest aspect of this code lies in spawning the pipes at regular intervals with the <code>frameCount</code> variable and modulo operator. In p5.js, <code>frameCount</code> is a system variable that tracks the number of frames rendered since the sketch began, incrementing with each cycle of the <code>draw()</code> loop. The modulo operator, denoted by <code><strong>%</strong></code>, returns the remainder of a division operation. For example, <code>7 % 3</code> yields <code>1</code> because when dividing 7 by 3, the result is 2 with a remainder of 1. The Boolean expression <code>frameCount % 100 === 0</code> therefore checks whether the current <code>frameCount</code> value, when divided by 100, has a remainder of 0. This condition is true every 100 frames, and at those frames, a new pipe is spawned and added to the <code>pipes</code> array.</p>
<div data-type="note">
<div data-type="exercise">
<h3 id="exercise-111">Exercise 11.1</h3>
<p>Implement a scoring system that awards points for successfully navigating through each set of pipes. Feel free to also add your own visual design elements for the bird, pipes, and environment!</p>
</div>
@ -454,11 +454,11 @@ function resetPipes() {
pipes.splice(0, pipes.length - 1);
}</pre>
<p>Note the addition of a new <code>resetPipes()</code> function. If I dont remove the pipes before starting a new generation, the birds may immediately restart at a position colliding with a pipe, in which case even the best bird wont have a chance to fly! The full online code for Example 11.2 also adjusts the behavior of the birds so that they die when they leave the canvas, either by crashing into the ground or soaring too high above the top.</p>
<div data-type="note">
<div data-type="exercise">
<h3 id="exercise-112">Exercise 11.2</h3>
<p>It takes a very long time for Example 11.2 to produce any results. Could you “speed up time” by skipping the drawing of every single frame of the game to reach an optimal bird faster? (A solution is presented in “Speeding Up Time" on page XX.) Additionally, could you add an overlay that displays information about the simulations status, such as the number of birds still in play, the current generation, and the lifespan of the best bird?</p>
</div>
<div data-type="note">
<div data-type="exercise">
<h3 id="exercise-113">Exercise 11.3</h3>
<p>To avoid starting the neuroevolution process from scratch every time, try using ml5.jss neural network <code>save()</code> and <code>load()</code> methods. How might you add a feature that saves the best bird model as well as an option to load a previously saved model?</p>
</div>
@ -522,7 +522,7 @@ for (let i = 0; i &#x3C; lifeSpan; i++) {
this.generations++;
}</pre>
<p>Now that Im using ml5.js, notice that I no longer need a separate <code>DNA</code> class with implementations of <code>crossover()</code> and <code>mutate()</code>. Instead, those methods are built into <code>ml5.neuralNetwork</code> and can be called directly.</p>
<div data-type="note">
<div data-type="exercise">
<h3 id="exercise-114">Exercise 11.4</h3>
<p>A steering force, as defined by Reynolds, is the difference between an agents desired velocity and its current velocity. How might this evolutionary system mirror that methodology? Instead of using only the position as an input to the neural network, what if you feed in the rockets current velocity? You could try using the x- and y-components or the direction and magnitude of the vector. Remember to normalize these values!</p>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 KiB

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 803 KiB

After

Width:  |  Height:  |  Size: 796 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,015 KiB

After

Width:  |  Height:  |  Size: 1,015 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

After

Width:  |  Height:  |  Size: 207 KiB