|
| 1 | +--- |
| 2 | +title: Build a K-Nearest Neighbor Model with p5.js |
| 3 | +author: Alex Kuntz |
| 4 | +uid: |
| 5 | +datePublished: 2025-09-08 |
| 6 | +description: |
| 7 | +header: |
| 8 | +bannerImage: https://i.imgur.com/RmZDc8j.gif |
| 9 | +tags: |
| 10 | +--- |
| 11 | + |
| 12 | +<BannerImage |
| 13 | + link="https://i.imgur.com/RmZDc8j.gif" |
| 14 | + description="" |
| 15 | + uid={false} |
| 16 | + cl="for-sidebar" |
| 17 | +/> |
| 18 | + |
| 19 | +# Build a K-Nearest Neighbor ML Model with p5.js |
| 20 | + |
| 21 | +<AuthorAvatar |
| 22 | + author_name="" |
| 23 | + author_avatar="" |
| 24 | + username="" |
| 25 | + uid={false} |
| 26 | +/> |
| 27 | + |
| 28 | +<BannerImage |
| 29 | + link="https://i.imgur.com/RmZDc8j.gif" |
| 30 | + description="" |
| 31 | + uid={false} |
| 32 | +/> |
| 33 | + |
| 34 | +### Machine Learning Models and KNN |
| 35 | + |
| 36 | +Machine Learning might sound complex, but many of the core ideas aren't actually too tricky! One of the most common ML models is **K-Nearest Neighbors** (KNN). |
| 37 | + |
| 38 | +Here's how it works: |
| 39 | + |
| 40 | +Imagine you're designing a new video game character. You've decided on their stats (health, strength, speed, etc.), but you're not sure what class they belong to. Are they a warrior, a wizard, or something else? |
| 41 | + |
| 42 | +To decide, you compare their stats to characters you've already created. If most of the closest matches are warriors, your new character should be classified as a warrior. If more are wizards, then wizard it is! |
| 43 | + |
| 44 | +[add an image of a video game character with stats here] |
| 45 | + |
| 46 | +That's KNN: look at the most similar examples, count the votes, and classify the new datapoint as the majority class. |
| 47 | + |
| 48 | +If you'd like to learn more about Machine Learning models and KNN, check out our [ML course](https://www.codedex.io/machine-learning)! |
| 49 | + |
| 50 | + |
| 51 | +## Visualization with p5.js |
| 52 | + |
| 53 | +In this project, you're going to build a visual demo of KNN using [p5.js](https://www.codedex.io/p5js), a JavaScript library for creative coding. |
| 54 | + |
| 55 | +Instead of warriors and wizards, our “characters” will simply be red 🔴 and green 🟢 points scattered across a canvas. |
| 56 | + |
| 57 | +Each character's "stats" are represented by its position on the canvas. For example, the `x` and `y` coordinates could represent a character's health and strength respectively. |
| 58 | + |
| 59 | +Now, we’ll create a new character at the position of your mouse. Should they be on the red team or the green team? The KNN algorithm will compare your new character’s “stats” (mouse position) to its nearest neighbors and classify it in real time. |
| 60 | + |
| 61 | +As you move your mouse around, it’s like you’re designing hundreds of new characters and watching KNN decide their team instantly. See how our mouse pointer flips between drawing a red circle and green circle based on the 3 nearest points? |
| 62 | + |
| 63 | + |
| 64 | + |
| 65 | +### Step 1: Creating the Points Class |
| 66 | + |
| 67 | +Let's begin by creating a `class` to represent our points. Each point will have: |
| 68 | + |
| 69 | +- Randomized `x` and `y` coordinates (its "stats"). |
| 70 | +- A random class (either red or green). |
| 71 | +- A function to draw itself on the canvas: |
| 72 | + |
| 73 | +```js |
| 74 | +class Point { |
| 75 | + constructor() { |
| 76 | + this.x = Math.random() * width; // A random value along the x axis |
| 77 | + this.y = Math.random() * height; // A random value along the y axis |
| 78 | + this.class = floor(Math.random() * 2) // A random class: either 0 or 1 |
| 79 | + } |
| 80 | + |
| 81 | + display() { |
| 82 | + |
| 83 | + stroke(0); |
| 84 | + strokeWeight(2); |
| 85 | + |
| 86 | + // Coloring the points. Points in class 1 are red, points in class 0 are green |
| 87 | + if (this.class == 1) { |
| 88 | + fill(255, 0, 0); |
| 89 | + } else { |
| 90 | + fill(0, 255, 0); |
| 91 | + } |
| 92 | + |
| 93 | + // Drawing a circle at the correct position |
| 94 | + ellipse(this.x, this.y, 20, 20); |
| 95 | + } |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +If you'd like to test creating and displaying a point, you can do so in the `setup()` function: |
| 100 | + |
| 101 | +```js |
| 102 | +function setup() { |
| 103 | + createCanvas(300, 300); |
| 104 | + test_point = new Point(); |
| 105 | + test_point.display(); |
| 106 | +} |
| 107 | +``` |
| 108 | + |
| 109 | +Feel free to run your code a few times. Each time you run your code, your point will have new random `x`, `y`, and `class` values. |
| 110 | + |
| 111 | +### Step 2: Create and Display an Array of Points |
| 112 | + |
| 113 | +Rather than just creating and displaying a single point, let's create a whole set of points. At the very top of your code, outside of any functions, create an empty array named `points`. |
| 114 | + |
| 115 | +```js |
| 116 | +var points = []; |
| 117 | +``` |
| 118 | + |
| 119 | +Then, inside of `setup()` use a `for` loop to create 20 `Points` (feel free to delete your code that created `test_point` from the last step): |
| 120 | + |
| 121 | +```js |
| 122 | + for (var i = 0; i < 20; i++) { |
| 123 | + points.push(new Point()); |
| 124 | + } |
| 125 | +``` |
| 126 | + |
| 127 | +Finally, in the `draw()` function, loop through your list and call `.display()` on each point. |
| 128 | + |
| 129 | +```js |
| 130 | +function draw() { |
| 131 | + background(255); |
| 132 | + for (var i = 0; i < points.length; i++) { |
| 133 | + points[i].display(); |
| 134 | + } |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +### Step 3: Classify Your Mouse |
| 139 | + |
| 140 | +Now's the fun part: classification! We'll write a function that classifies our mouse pointer as either red or green based on the 3 closest neighbors. Here are the steps to do this: |
| 141 | + |
| 142 | +Measure the distance from the mouse to every `Point`. Store these values in an array. |
| 143 | +Sort the distances to find the 3 nearest neighbors |
| 144 | +Count how many neighbors are red and green, and classify the mouse pointer based on those numbers. |
| 145 | +Draw a small red or green circle at the location of the mouse. |
| 146 | + |
| 147 | +Let's get started! |
| 148 | + |
| 149 | +### Step 3.1: Measure Distances: |
| 150 | + |
| 151 | +We need to find the distance between our mouse pointer and each `Point` in our dataset. We'll put each distance in an array. Let's begin by creating an empty array and setting up our `for` loop: |
| 152 | + |
| 153 | +```js |
| 154 | +function classifyMouse() { |
| 155 | + |
| 156 | + let distances = []; |
| 157 | + for (var i = 0; i < points.length; i++) { |
| 158 | + // TODO: Find the distance between each point and the mouse. |
| 159 | + } |
| 160 | +} |
| 161 | +``` |
| 162 | + |
| 163 | +Next, we can use the `dist()` function to find the distance between our mouse and each point. Use this code inside your `for` loop: |
| 164 | + |
| 165 | +```js |
| 166 | +let distance = dist(points[i].x, points[i].y, mouseX, mouseY); |
| 167 | +``` |
| 168 | + |
| 169 | +Finally, we don't want to simply add the distance to our list. We need to add the distance **AND** the `class` of the `Point` associated with that distance. Inside your food loop, write the following line of code: |
| 170 | + |
| 171 | +```js |
| 172 | +distances.push([distance, points[i].class]); |
| 173 | +``` |
| 174 | + |
| 175 | +### Step 3.2: Sort the Distances: |
| 176 | + |
| 177 | +We now need to find the 3 closest points. The easiest way to do this is by sorting our list of distances from low-to-high and looking at the first 3 points in our list. |
| 178 | + |
| 179 | +This sort function is slightly complicated, because `distances` isn't simply a list of numbers. It contains objects like `[distance, class]`. |
| 180 | + |
| 181 | +The following line of code will sort your list correctly. This should be put outside the `for` loop, but inside your `classifyMouse()` function: |
| 182 | + |
| 183 | +```js |
| 184 | +distances.sort((a, b) => a[0] - b[0]); |
| 185 | +``` |
| 186 | + |
| 187 | +### Step 3.3: Count the Class of the 3 Nearest Neighbors |
| 188 | + |
| 189 | +Let's now loop through the first 3 items in the list and count the number of times class `1` and class `0` show up: |
| 190 | + |
| 191 | +```js |
| 192 | +let numZero = 0; |
| 193 | +let numOne = 0; |
| 194 | + |
| 195 | +// Looping through the 3 nearest neighbors and counting the classes |
| 196 | +for (var i = 0; i < 3; i++) { |
| 197 | + if (distances[i][1] == 1) { |
| 198 | + numOne++; |
| 199 | + } else { |
| 200 | + numZero++; |
| 201 | + } |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +### Step 3.4: Draw a Circle Based on Classification: |
| 206 | + |
| 207 | +We now know whether the mouse should be classified as red or green. Let's draw a small circle at the location of the mouse with the correct color. This should be the end of your `classifyMouse()` function, outside of all loops: |
| 208 | + |
| 209 | +```js |
| 210 | +noStroke(); |
| 211 | +if (numOne > numZero) { |
| 212 | + fill(255, 0, 0); |
| 213 | +} else { |
| 214 | + fill(0, 255, 0); |
| 215 | +} |
| 216 | +ellipse(mouseX, mouseY, 10, 10); |
| 217 | +``` |
| 218 | + |
| 219 | +Now we just need to call it! At the bottom of the `draw()` function, call `classifyMouse()`. Feel free to move your mouse around and see if the classification is correct! Is your mouse pointer red when the majority of the 3 nearest neighbors are also red? |
| 220 | + |
| 221 | +### Extensions: |
| 222 | + |
| 223 | +You made a working KNN visualizer! Want to level it up? Try these challenges: |
| 224 | + |
| 225 | +We've hard-coded `20` points in our dataset and `3` nearest neighbors. Refactor your code so it is easy to quickly change those values to any numbers. |
| 226 | +It can be a bit tough to eyeball which points are the nearest neighbors to your mouse. Edit your code so the nearest neighbors are now highlighted (maybe with a yellow border rather than black) |
| 227 | +Add your own style! Rather than red and green points, you could draw your points as wizard 🧙♂️ or warrior ⚔️ emojis (calling back to our original example). Or come up with your own theme! Could you do something interesting with the background? |
| 228 | +KNN models can work with multi-class problems. Rather than simply red and green points, what if you had red, green, and blue points? Refactor your code so your visualization works with _any_ number of classes. |
| 229 | + |
| 230 | +Congrats on reaching the end of this project! You now hopefully have a better understanding of how a K-Nearest Neighbor model works under the hood! |
| 231 | + |
| 232 | +### Additional Resources |
| 233 | + |
| 234 | +- [p5.js](https://p5js.org) |
| 235 | +- [More Machine Learning on Codédex](https://www.codedex.io/machine-learning) |
| 236 | +- [The KNN Algorithm](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm) |
| 237 | + |
0 commit comments