diff --git a/content/10_nn.html b/content/10_nn.html index 0c375922..31b31b51 100644 --- a/content/10_nn.html +++ b/content/10_nn.html @@ -227,7 +227,7 @@
The constructor can receive an argument indicating the number of inputs (in this case, three: x_0, x_1, and a bias) and size the weights
array accordingly, filling it with random values to start:
// The argument n determines the number of inputs (including the bias). +// The argumentn
determines the number of inputs (including the bias). constructor(n) { this.weights = []; for (let i = 0; i < n; i++) { @@ -321,7 +321,7 @@The Perceptron Code
A high learning constant causes the weight to change more drastically. This may help the perceptron arrive at a solution more quickly, but it also increases the risk of overshooting the optimal weights. A small learning constant will adjust the weights more slowly and require more training time, but will allow the network to make small adjustments that could improve overall accuracy.
Assuming the addition of a
learningConstant
property to thePerceptron
class, I can now write a training method for the perceptron following the steps I outlined earlier:// Step 1: Provide the inputs and known answer. - // These are passed in as arguments to train(). + // These are passed in as arguments totrain()
. train(inputs, desired) { // Step 2: Guess according to those inputs. let guess = this.feedforward(inputs); @@ -386,12 +386,12 @@The Perceptron Code
Figure 10.8: A graph of y = \frac{1}2x - 1 I’ll arbitrarily choose that as the equation for my line, and write a function accordingly:
-// A function to calculate y based on x along a line +// A function to calculatey
based onx
along a line function f(x) { return 0.5 * x - 1; }Now there’s the matter of the p5.js canvas defaulting to (0, 0) in the top-left corner with the y-axis pointing down. For this discussion, I’ll assume I’ve built the following into the code to reorient the canvas to match a more traditional Cartesian space:
-// Move the origin (0, 0) to the center. +// Move the origin@@ -463,7 +463,7 @@(0, 0)
to the center. translate(width / 2, height / 2); // Flip the y-axis orientation (positive points up!). scale(1, -1);Example 10.1: The Perceptron
strokeWeight(2); line(-width / 2, f(-width / 2), width / 2, f(width / 2)); - // Get the current (x, y) of the training data. + // Get the current(x, y)
of the training data. let x = training[count][0]; let y = training[count][1]; // What is the desired output? @@ -799,7 +799,7 @@Training the Model
classifier.normalizeData();In this case, the handcoded data was limited to a range of –1 to +1 from the get-go, so calling
normalizeData()
here is likely redundant. Still, this function call is important to demonstrate. Normalizing your data ahead of time as part of the preprocessing step will absolutely work, but the auto-normalization feature of ml5.js is a big help!Now for the heart of the machine learning process: actually training the model. Here’s the code:
-// The train() method initiates the training process. +// Thetrain()
method initiates the training process. classifier.train(finishedTraining); // A callback function for when the training is complete @@ -874,7 +874,7 @@Deploying the Model
]In this example output, the model is highly confident (approximately 96.7 percent) that the correct label is
"right"
, while it has minimal confidence (0.03 percent) in the"left"
label. The confidence values are normalized and add up to 100 percent.All that remains now is to fill out the sketch with code so the model can receive live input from the mouse. The first step is to signal the completion of the training process so the user knows the model is ready. I’ll include a global
-status
variable to track the training process and ultimately display the predicted label on the canvas. The variable is initialized to"training"
but updated to"ready"
through thefinishedTraining()
callback:// When the sketch starts, it will show a status of training. +// When the sketch starts, it will show a status ofdiff --git a/content/11_nn_ga.html b/content/11_nn_ga.html index 008e0a29..5ceaff1c 100644 --- a/content/11_nn_ga.html +++ b/content/11_nn_ga.html @@ -85,7 +85,7 @@training
. let status = "training"; function draw() { @@ -884,7 +884,7 @@Deploying the Model
text(status, width / 2, height / 2); } -// This is the callback for when training is complete, and the message changes to ready. +// This is the callback for when training is complete, and the message changes toready
. function finishedTraining() { status = "ready"; }Coding Flappy Bird
To simplify the code even further, I’ll add the forces directly to the bird’s velocity instead of accumulating them into an
acceleration
variable. In addition to the usualupdate()
, I’ll include aflap()
method for the bird to fly upward. Theshow()
method isn’t included here as it only draws a circle. Here’s the code:class Bird { constructor() { - // The bird’s position (x will be constant) + // The bird’s position (x
will be constant) this.x = 50 this.y = 120; @@ -323,7 +323,7 @@Selection: Flappy Bird Fitness
}I’ll assign the fitness a numeric value that increases by one every cycle through
draw()
, as long as the bird remains alive. The birds that survive longer should have a higher fitness value. This mechanism mirrors the reinforcement learning technique of rewarding good decisions. In reinforcement learning, however, an agent receives immediate feedback for every decision it makes, allowing it to adjust its policy accordingly. Here, the bird’s fitness is a cumulative measure of its overall success and will be applied only during the selection step of the GA:update() { - //{!1} Increment the fitness each time through update(). + //{!1} Increment the fitness each time throughupdate()
. this.fitness++; }The
@@ -658,9 +658,9 @@alive
property is a Boolean flag that’s initially set totrue
. When a bird collides with a pipe, this property is set tofalse
. Only birds that are still alive are updated and drawn to the canvas:Example 11.4: Dynamic Ne } } - /* seek() predicts a steering force as described previously. */ + /*
seek()
predicts a steering force as described previously. */ - /* update() increments the fitness if the glow is reached as described previously. */ + /*update()
increments the fitness if the glow is reached as described previously. */ }It’s hard to believe, but this book has been a journey well over 10 years in the making. Thank you, dear reader, for sticking with it. I promise it’s not an infinite loop. However meandering it might have seemed, like a random walk, I’m finally using an arrival steering behavior to reach the final piece of the puzzle, an attempt to bring together all my past explorations in my own version of the Ecosystem Project.
@@ -784,7 +784,7 @@Example 11.5: A Bloop with Sensors
sense() method for each sensor. sense(food) { for (let sensor of this.sensors) { sensor.sense(this.position, food); diff --git a/content/examples/06_libraries/6_5_compound_bodies_error/lollipop.js b/content/examples/06_libraries/6_5_compound_bodies_error/lollipop.js index 756c87e6..d2ea762f 100644 --- a/content/examples/06_libraries/6_5_compound_bodies_error/lollipop.js +++ b/content/examples/06_libraries/6_5_compound_bodies_error/lollipop.js @@ -25,48 +25,48 @@ class Lollipop { // Drawing the lollipop show() { - if (mouseIsPressed) { - // The angle comes from the compound body - let angle = this.body.angle; + // if (mouseIsPressed) { + // // The angle comes from the compound body + // let angle = this.body.angle; - //{!2} Get the position for each part - let position1 = this.part1.position; - let position2 = this.part2.position; + // //{!2} Get the position for each part + // let position1 = this.part1.position; + // let position2 = this.part2.position; - fill(127); - stroke(0); - strokeWeight(1); + // fill(127); + // stroke(0); + // strokeWeight(1); - // Translate and rotate the rectangle (part1) - push(); - translate(position1.x, position1.y); - rotate(angle); - rectMode(CENTER); - rect(0, 0, this.w, this.h); - pop(); + // // Translate and rotate the rectangle (part1) + // push(); + // translate(position1.x, position1.y); + // rotate(angle); + // rectMode(CENTER); + // rect(0, 0, this.w, this.h); + // pop(); - // Translate and rotate the circle (part2) - push(); - translate(position2.x, position2.y); - rotate(angle); - fill(200); - circle(0, 0, this.r * 2); - pop(); - } else { - let position = this.body.position; - let angle = this.body.angle; - rectMode(CENTER); - fill(127); - stroke(0); - strokeWeight(1); - push(); - translate(position.x, position.y); - rotate(angle); - rect(0, 0, this.w, this.h); - fill(200); - circle(this.w / 2, 0, this.r * 2); - pop(); - } + // // Translate and rotate the circle (part2) + // push(); + // translate(position2.x, position2.y); + // rotate(angle); + // fill(200); + // circle(0, 0, this.r * 2); + // pop(); + // } else { + let position = this.body.position; + let angle = this.body.angle; + rectMode(CENTER); + fill(127); + stroke(0); + strokeWeight(1); + push(); + translate(position.x, position.y); + rotate(angle); + rect(0, 0, this.w, this.h); + fill(200); + circle(this.w / 2, 0, this.r * 2); + pop(); + // } } checkEdge() { diff --git a/content/examples/06_libraries/6_5_compound_bodies_error/screenshot.png b/content/examples/06_libraries/6_5_compound_bodies_error/screenshot.png index 78e88fe1..3d9ef4c9 100644 Binary files a/content/examples/06_libraries/6_5_compound_bodies_error/screenshot.png and b/content/examples/06_libraries/6_5_compound_bodies_error/screenshot.png differ diff --git a/content/examples/06_libraries/6_5_compound_bodies_error/sketch.js b/content/examples/06_libraries/6_5_compound_bodies_error/sketch.js index 4a2c6b09..420a8a00 100644 --- a/content/examples/06_libraries/6_5_compound_bodies_error/sketch.js +++ b/content/examples/06_libraries/6_5_compound_bodies_error/sketch.js @@ -5,8 +5,7 @@ // TODO: Why is body.pos different from part1.pos? // Why is there body.angle but no part1.angle? -const { Engine, Bodies, Composite, Body, Vector } = Matter; - +const { Engine, Bodies, Composite, Body, Vector } = Matter; // A reference to the matter physics engine let engine; @@ -27,7 +26,7 @@ function setup() { boundaries.push( new Boundary((3 * width) / 4, height - 50, width / 2 - 50, 10) ); - + for (let i = 0; i < 100; i++) { let lolli = new Lollipop(random(width), 0); lollipops.push(lolli); @@ -40,8 +39,6 @@ function draw() { // Update the engine! Engine.update(engine); - - // Iterate over the boxes backwards for (let i = lollipops.length - 1; i >= 0; i--) { lollipops[i].show();