<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ combinatorics - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ combinatorics - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 26 Jun 2026 22:48:01 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/combinatorics/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Permutation vs Combination: What is the Difference Between the Permutation Formula and the Combination Formula? ]]>
                </title>
                <description>
                    <![CDATA[ By Neil Kakkar Here's the short version. Let's take ringing bells in a church as an example.  A permutation is an ordering of the bells. You're figuring out the best order to ring them in. A combination is the choice of bells. You're choosing the bel... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/permutation-vs-combination-what-is-the-difference-between-the-permutation-formula-and-the-combination-formula/</link>
                <guid isPermaLink="false">66d4604e33b83c4378a5180c</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ combinatorics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ education ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Math ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 21 Dec 2019 21:46:28 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9e91740569d1a4ca3dca.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Neil Kakkar</p>
<p>Here's the short version.</p>
<p>Let's take ringing bells in a church as an example. </p>
<p>A permutation is an ordering of the bells. You're figuring out the best order to ring them in.</p>
<p>A combination is the choice of bells. You're choosing the bells to ring. If you have too many bells, you'd first choose them, and then think about ordering them.</p>
<p>This gives rise to the familiar identity: <code>(n P r) = (n C r) * r!</code></p>
<p>The way to order <code>r</code> items out of <code>n</code> is to first choose <code>r</code> items out of <code>n</code>, and then order the <code>r</code> items (<code>r!</code> )</p>
<p>And, this means <code>(n P r) = n! / (n-r)!</code> and <code>(n C r) = n! / ( (n-r)! * r! )</code> </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/ncr.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>But do you want to know how to remember this forever?</strong></p>
<p>I'm a big fan of <a target="_blank" href="https://neilkakkar.com/A-framework-for-First-Principles-Thinking.html">first principles thinking</a>. To understand a problem, get to the core of it, and reason up from there.</p>
<p>Not doing this is usually the source of confusion: if I don't understand how things work, I don't know where to hang the concepts. My mental framework isn't complete, so I decide to just remember it.</p>
<p>As you can imagine, this isn't ideal. So, from time to time, I indulge myself in an exercise of deriving things from the source, and building intuition for how things work.</p>
<p>This time around, we're building intuition for permutations and combinations.</p>
<p>For example, do you know why the formula for a combination is (n C r)? Where did this come from? And why are factorials used here?</p>
<p>Let's begin at the source. Factorials, Permutations, and Combinations were born out of mathematicians playing together, much like how Steve Jobs and Steve Wozniak founded Apple playing together in their garage.</p>
<p>Just like how Apple became a full fledged profitable company, the simple factorial, <code>!</code>, became the atom of an entire field of mathematics: <a target="_blank" href="https://en.wikipedia.org/wiki/Combinatorics">combinatorics</a>.</p>
<p>Forget everything, let's start thinking from the bottom up.</p>
<p>The first known interesting use case came from Churches in the 17th century.</p>
<p>Have you wondered how the bells are rung in churches? There's a machine that "rings" them in order. We switched to machines because the bells are too big. Also, there are tons of bells.</p>
<p>How did people figure out the best sequence to ring them in? What if they wanted to switch things up? How could they find the best sound? Each bell tower had up to 16 bells!</p>
<p>You couldn't change how quickly you could ring a bell - the machines only rang one bell every second. The only thing you could do was <a target="_blank" href="https://en.wikipedia.org/wiki/Change_ringing">change</a> the order of the bells. So, this challenge was about figuring out the best order. </p>
<p>Could we, on the way, also find out all the possible orders? We want to know all possible orders to figure out if it's worth trying them all.</p>
<p>A bell ringer, <a target="_blank" href="https://en.wikipedia.org/wiki/Fabian_Stedman">Fabian Stedman</a> took up this challenge.</p>
<p>He started with 2 bells. What are the different orderings he could ring these bells in?[1]</p>
<p>1 and 2.
or
2 and 1.</p>
<p>This made sense. There was no other way.</p>
<p>How about with 3 bells?</p>
<p>1, 2, and 3.<br>1, 3, and 2.</p>
<p>Then starting with the second bell,</p>
<p>2, 1, and 3.<br>2, 3, and 1.</p>
<p>Then starting with the third bell,</p>
<p>3, 1, and 2.<br>3, 2, and 1.</p>
<p>Total, 6.</p>
<p>He then realised this was very similar to two bells!</p>
<p>If he fixed the first bell, then the number of ways to order the remaining two bells was <em>always</em> two. </p>
<p>How many ways could he fix the first bell? Any of the 3 bells could be the one!</p>
<p>Okay, he went on. He then reached 5 bells.</p>
<p>This is when he realized doing things by hand is unwieldy. You only have so much time in the day, you've got to ring bells, you can't be stuck drawing out all the possible bells. Was there a way to figure this out quickly?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5bells-2.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>He went back to his insight.</p>
<p>If he had 5 bells, and he fixed the first bell, all he had to do was figure out how to order 4 bells.</p>
<p>For 4 bells? Well, if he had 4 bells, and he fixed the first bell, all he had to do was figure out how to order 3 bells.</p>
<p>And he knew how to do this!</p>
<p>So, ordering of 5 bells = 5 * ordering of 4 bells.</p>
<p>Ordering of 4 bells = 4 * ordering of 3 bells</p>
<p>Ordering of 3 bells = 3 * ordering of 2 bells.</p>
<p>.. You see the pattern, don't you?</p>
<blockquote>
<p>Fun Fact: This is the key for a programming technique called <a target="_blank" href="https://en.wikipedia.org/wiki/Recursion">recursion</a>. </p>
</blockquote>
<p>He did too. Although, it took him much longer, since no one near him had already discovered this.[2]</p>
<p>Thus, he figured out that the ordering of 5 bells = <code>5 * 4 * 3 * 2 * 1</code>.</p>
<p>This ordering formula, in 1808, came to be known as the factorial.</p>
<p>We think of the factorial notation as the base, but the idea existed long before it had a name. It was only when the French mathematician Christian Kramp noticed it being used in a few places that he named it the factorial.</p>
<p>This ordering of bells is called a permutation.</p>
<blockquote>
<p>A Permutation is an ordering of items.</p>
</blockquote>
<p>When learning something, I think it helps to look at things from every different angle, to solidify understanding.</p>
<p>What if we tried to derive the formula above directly, without trying to reduce the problem to a smaller number of bells?  </p>
<p>We have 5 spaces, right?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesForBells.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>How many ways can we choose the first bell? <code>5</code>, because that's the number of bells we have.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesForBells_1filled.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The second bell? Well, we used up one bell when we placed it in the first position, so we have 4 bells left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesForBells_2filled.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The third bell? Well, we've chosen the first two, so there are only 3 bells left to choose from.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesForBells_3filled.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The fourth bell? Only 2 bells left, so 2 options.<br>The fifth bell? Only 1 left, so 1 option.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesForBells_5filled.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And there we have it, the total number of orderings is <code>5 * 4 * 3 * 2 * 1</code></p>
<p>Thus, we have our first general formula. </p>
<blockquote>
<p>The number of ways to order <code>N</code> items is <code>N!</code></p>
</blockquote>
<h1 id="heading-the-permutation">The Permutation</h1>
<p>Now, we're faced with a different problem. The king ordered new bells to be made for every church. Some are nice, some are okay, some will make you go deaf. But every one is unique. Each makes its own sound. A deafening bell surrounded by nice bells can sound majestic.</p>
<p>But, our bell tower still holds 5 bells, so we need to figure out the best ordering out of 8 bells that the skilled bell makers made.</p>
<p>Using the above logic, we can proceed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesFor8Bells-1.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>For the first bell, we can choose any of the 8 bells.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesForBells_1filled_8bells.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>For the second bell, we can choose any of the remaining 7 bells... and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/5spacesForBells_5filled_8bells.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the end, we get <code>8 * 7 * 6 * 5 * 4</code> possible orderings of 8 bells in 5 spaces.</p>
<p>If you're familiar with the formula version of (n P r), which is <code>n! / (n-r)!</code>, don't worry, we'll derive that soon enough, too!</p>
<p>One bad way to derive it is to multiply both the numerator and denominator by 3! in our example above -</p>
<p>we get <code>8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 / 3 * 2 * 1</code> = <code>8! / 3!</code>.</p>
<p>But this doesn't help us understand why this formula works. Before we get there, let's have a look at choosing things, or the Combination.</p>
<h1 id="heading-the-combination">The Combination</h1>
<p>Now that we know how to order things, we can figure out how to choose things!</p>
<p>Let's consider the same problem. There's a belltower with 5 bells, and you have 8 bells. However, right now, you don't want to figure out the order of bells (remember that's what a permutation is).</p>
<p>Instead, you want to choose the 5 best bells, and let someone else with better taste in music figure out the ordering. In effect, we're breaking the problem down into to parts: First, we figure out which bells to choose. Next, we figure out how to order the chosen bells.</p>
<p>How do you choose the bells? This is the "combination" from permutations and combination.</p>
<p>The combination is a selection. You're being selective. You're choosing 5 bells out of 8 your craftsmen have made.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/8bells_inline.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Since we know how to order bells, we're going to use this information to figure out how to choose bells. Sounds impossible? Wait till you see the beautiful math involved.</p>
<p>Let's imagine all the bells are in a line.</p>
<p>Before finding all the ways to choose the bells, let's focus on one way to choose bells.</p>
<p>One way is to choose any 5 at random. This doesn't help us solve the problem much, so let's try another way.</p>
<p>We put the bells in a line, and choose the first 5. This is one way to choose the bells.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/8bells_inline_choose5.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Notice that, even if we switch positions of the first 5 bells, the choice doesn't change. They're still the same one way to choose 5 unique bells.</p>
<p>This is true for the last three bells as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/8bells_inline_choose5_permute.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now, the beautiful math trick - for this one way to choose the 5 bells, what are all the ordering of 8 bells where we choose exactly these 5 bells? From the image above, it's all the orderings of the 5 bells (<code>5!</code>) and all the orderings of the remaining three bells (<code>3!</code>).</p>
<p>Thus, for every single way to choose 5 bells, we have (<code>5! * 3!</code>) orderings of 8 bells.</p>
<p>What are the total possible orderings of 8 bells? <code>8!</code>.</p>
<p>Remember, for each choice of first 5 bells, we have (<code>5! * 3!</code>) orderings of 8 bells which give the same choice.</p>
<p>Then, if we multiply the number of ways to choose the first 5 bells with all the possible orderings of one choice, we should get the total number of orderings. </p>
<pre><code>Ways to choose <span class="hljs-number">5</span> bells * orderings <span class="hljs-keyword">of</span> one choice = Total orderings
</code></pre><p>So, </p>
<pre><code>Ways to choose <span class="hljs-number">5</span> bells = the total possible orderings / total orderings <span class="hljs-keyword">of</span> one choice.
</code></pre><p>In math, that becomes:</p>
<pre><code>(<span class="hljs-number">8</span> C <span class="hljs-number">5</span>) = <span class="hljs-number">8</span>! / ( <span class="hljs-number">5</span>! * <span class="hljs-number">3</span>!)
</code></pre><p>Lo and behold, we've found an intuitive explanation for how to choose 5 things out of 8.</p>
<p>Now, we can generalize this. If we have N things, and we want to choose R of them, it means we draw a line at R.</p>
<p>Which means the remaining items will be <code>N-R</code>. So, for one choice of <code>R</code> items, we have <code>R! * (N-R)!</code> orderings which give the same <code>R</code> items.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/nSpacesForBells.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>For all ways to choose <code>R</code> items, we have <code>N! / (R! * (N-R)!)</code> possibilities.</p>
<blockquote>
<p>The number of ways to choose <code>r</code> items out of <code>n</code> is <code>(n C r) = n! / (r! * (n-r)!)</code></p>
</blockquote>
<p>In colloquial terms, (n C r) is also pronounced <code>n choose r</code>, which helps solidify the idea that combinations are for choosing items.</p>
<h1 id="heading-the-permutation-revisited">The Permutation - revisited</h1>
<p>With the combination done and dusted, let's come back to Part 2 of our job. Our dear friend chose the best 5 bells by figuring out all possible combinations of 5 bells.</p>
<p>It's our job now to find the perfect melody by figuring out the number of orderings.</p>
<p>But, this is the easy bit. We already know how to order 5 items. It's <code>5!</code>, and we're done.</p>
<p>So, to permutate (order) 5 items out of 8, we first choose 5 items, then order the 5 items.</p>
<p>In other words, </p>
<pre><code>(<span class="hljs-number">8</span> P <span class="hljs-number">5</span>) = (<span class="hljs-number">8</span> C <span class="hljs-number">5</span>) * <span class="hljs-number">5</span>!
</code></pre><p>And if we expand the formula, <code>(8 P 5) = (8! / ( 5! * 3!)) * 5!</code></p>
<p><code>(8 P 5) = 8! / 3!</code>.</p>
<p>And, we've come full circle to our original formula, derived properly.</p>
<blockquote>
<p>The number of ways to order <code>r</code> items out of <code>n</code> is <code>(n P r) = n! / (n-r)!</code></p>
</blockquote>
<h1 id="heading-difference-between-permutation-and-combination">Difference between permutation and combination</h1>
<p>I hope this makes the difference between permutations and combinations crystal clear.</p>
<p>Permutations are orderings, while combinations are choices.</p>
<p>To order N elements, we found two intuitive ways to figure out the answer. Both lead to the answer, <code>N!</code>.</p>
<p>In order to permutate 5 out of 8 elements, you first need to choose the 5 elements, then order them. You choose using <code>(8 C 5)</code>, then order the 5 using <code>5!</code>.</p>
<p>And the intuition for choosing <code>R</code> out of <code>N</code> is figuring out all the orderings (<code>N!</code>) and dividing by orderings where the first <code>R</code> and last <code>N-R</code> remain the same (<code>R!</code> and <code>(N-R)!</code>).</p>
<p>And, that's all there is to permutations and combinations.</p>
<p>Every advanced permutation and combination uses this as a base. Combination with replacement? Same idea. Permutation with identical items? Same idea, only the number of orderings change, since some items are identical.</p>
<p>If you're interested, we can go into the complex cases in another example. Let me know <a target="_blank" href="https://twitter.com/neilkakkar">on Twitter</a>.</p>
<blockquote>
<p>Check out more posts on <a target="_blank" href="https://neilkakkar.com/">my blog</a>, and join the <a target="_blank" href="https://neilkakkar.com/subscribe/">weekly mailing list</a>.</p>
</blockquote>
<h2 id="heading-end-notes">End notes</h2>
<ol>
<li>This is how I imagine he figured things out. Don't take it as a lesson in history.</li>
<li>The Indians had, in the 12th century, 400 years before him.</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An introduction to clustering algorithms ]]>
                </title>
                <description>
                    <![CDATA[ By Peter Gleeson Take a look at the image below. It’s a collection of bugs and creepy-crawlies of different shapes and sizes. Take a moment to categorize them by similarity into a number of groups. This isn’t a trick question. Start with grouping the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-machines-make-sense-of-big-data-an-introduction-to-clustering-algorithms-4bd97d4fbaba/</link>
                <guid isPermaLink="false">66d4609dd14641365a050951</guid>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clustering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ combinatorics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Math ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mathematics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ statistics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 28 Mar 2017 16:44:07 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*Bm4uiBY1JEt6Z-vOme_fTQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Peter Gleeson</p>
<p>Take a look at the image below. It’s a collection of bugs and creepy-crawlies of different shapes and sizes. Take a moment to categorize them by similarity into a number of groups.</p>
<p>This isn’t a trick question. Start with grouping the spiders together.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/BfSVT54goDauX2gz7TL7lE2qPKEnhVnTI6Ir" alt="Image" width="800" height="382" loading="lazy">
<em>Images via Google Image Search, labelled for reuse</em></p>
<p>Done? While there’s not necessarily a “correct” answer here, it’s most likely you split the bugs into four <em>clusters</em>. The spiders in one cluster, the pair of snails in another, the butterflies and moth into one, and the trio of wasps and bees into one more.</p>
<p>That wasn’t too bad, was it? You could probably do the same with twice as many bugs, right? If you had a bit of time to spare — or a passion for entomology — you could probably even do the same with a hundred bugs.</p>
<p>For a machine though, grouping ten objects into however many meaningful clusters is no small task, thanks to a mind-bending branch of maths called <a target="_blank" href="https://en.wikipedia.org/wiki/Bell_number">combinatorics</a>, which tells us that are 115,975 different possible ways you could have grouped those ten insects together.</p>
<p>Had there been twenty bugs, there would have been <a target="_blank" href="https://www.wolframalpha.com/input/?i=bell%27s+number+(20)">over fifty trillion</a> possible ways of clustering them.</p>
<p>With a hundred bugs — there’d be many times more solutions than there are <a target="_blank" href="https://www.wolframalpha.com/input/?i=particles+in+universe">particles in the known universe</a>. </p>
<p>How many times more? By my calculation, approximately <a target="_blank" href="https://www.wolframalpha.com/input/?i=BellB%5B100%5D+%2F+number+of+particles+in+universe">five hundred million billion billion times more</a>. In fact, there are more than <a target="_blank" href="https://www.wolframalpha.com/input/?i=BellB%5B100%5D+%2F+googol">four million billion <em>googol</em></a> solutions (<a target="_blank" href="https://www.wolframalpha.com/input/?i=googol">what’s a googol?</a>).</p>
<p>For just a hundred objects.</p>
<p>Almost all of those solutions would be meaningless — yet from that unimaginable number of possible choices, you pretty quickly found one of the very few that clustered the bugs in a useful way.</p>
<p>Us humans take it for granted how good we are categorizing and making sense of large volumes of data pretty quickly. Whether it’s a paragraph of text, or images on a screen, or a sequence of objects — humans are generally fairly efficient at making sense of whatever data the world throws at us.</p>
<p>Given that a key aspect of developing A.I. and machine learning is getting machines to quickly make sense of large sets of input data, what shortcuts are there available? </p>
<p>Here, you can read about three clustering algorithms that machines can use to quickly make sense of large datasets. This is by no means an exhaustive list — there are other algorithms out there — but they represent a good place to start!</p>
<p>You’ll find for each a quick summary of when you might use them, a brief overview of how they work, and a more detailed, step-by-step worked example. I believe it helps to understand an algorithm by actually carrying out yourself. </p>
<p>If you’re <em>really keen</em>, you’ll find the best way to do this is with pen and paper. Go ahead — nobody will judge!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/PkvVKjhDBUGlU2gTPj7r0T1aNPdpOZ6MpZ6B" alt="Image" width="800" height="526" loading="lazy">
<em>Three suspiciously neat clusters, with K = 3</em></p>
<h3 id="heading-k-means-clustering">K-means clustering</h3>
<h4 id="heading-use-when"><strong>Use when...</strong></h4>
<p>…you have an idea of how many groups you’re expecting to find <em>a priori</em>.</p>
<h4 id="heading-how-it-works"><strong>How it works</strong></h4>
<p>The algorithm randomly assigns each observation into one of <em>k</em> categories, then calculates the <em>mean</em> of each category. Next, it reassigns each observation to the category with the closest mean before recalculating the means. This step repeats over and over until no more reassignments are necessary.</p>
<h4 id="heading-worked-example"><strong>Worked Example</strong></h4>
<p>Take a group of 12 football (or ‘soccer’) players who have each scored a certain number of goals this season (say in the range 3–30). Let’s divide them into separate clusters — say three.</p>
<p><strong>Step 1</strong> requires us to randomly split the players into three groups and calculate the means of each.</p>
<pre><code>Group <span class="hljs-number">1</span>
  Player A (<span class="hljs-number">5</span> goals),
  Player B (<span class="hljs-number">20</span> goals),
  Player C (<span class="hljs-number">11</span> goals)
Group Mean = (<span class="hljs-number">5</span> + <span class="hljs-number">20</span> + <span class="hljs-number">11</span>) / <span class="hljs-number">3</span> = <span class="hljs-number">12</span> goals

Group <span class="hljs-number">2</span>
  Player D (<span class="hljs-number">5</span> goals),
  Player E (<span class="hljs-number">3</span> goals),
  Player F (<span class="hljs-number">19</span> goals)
Group Mean = <span class="hljs-number">9</span> goals

Group <span class="hljs-number">3</span>
  Player G (<span class="hljs-number">30</span> goals),
  Player H (<span class="hljs-number">3</span> goals),
  Player I (<span class="hljs-number">15</span> goals)
Group Mean = <span class="hljs-number">16</span> goals
</code></pre><p><strong>Step 2:</strong> For each player, reassign them to the group with the closest mean. E.g., Player A (5 goals) is assigned to Group 2 (mean = 9). Then recalculate the group means.</p>
<pre><code>Group <span class="hljs-number">1</span> (Old Mean = <span class="hljs-number">12</span> goals)
  Player C (<span class="hljs-number">11</span> goals)
New Mean = <span class="hljs-number">11</span> goals

Group <span class="hljs-number">2</span> (Old Mean = <span class="hljs-number">9</span> goals)
  Player A (<span class="hljs-number">5</span> goals),
  Player D (<span class="hljs-number">5</span> goals),
  Player E (<span class="hljs-number">3</span> goals),
  Player H (<span class="hljs-number">3</span> goals)
New Mean = <span class="hljs-number">4</span> goals

Group <span class="hljs-number">3</span> (Old Mean = <span class="hljs-number">16</span> goals)
  Player G (<span class="hljs-number">30</span> goals),
  Player I (<span class="hljs-number">15</span> goals),
  Player B (<span class="hljs-number">20</span> goals),
  Player F (<span class="hljs-number">19</span> goals)
New Mean = <span class="hljs-number">21</span> goals
</code></pre><p><strong>Repeat</strong> Step 2 over and over until the group means no longer change. For this somewhat contrived example, this happens on the next iteration. <strong>Stop!</strong> You have now formed three clusters from the dataset!</p>
<pre><code>Group <span class="hljs-number">1</span> (Old Mean = <span class="hljs-number">11</span> goals)
  Player C (<span class="hljs-number">11</span> goals),
  Player I (<span class="hljs-number">15</span> goals)
Final Mean = <span class="hljs-number">13</span> goals

Group <span class="hljs-number">2</span> (Old Mean = <span class="hljs-number">4</span> goals)
  Player A (<span class="hljs-number">5</span> goals),
  Player D (<span class="hljs-number">5</span> goals),
  Player E (<span class="hljs-number">3</span> goals),
  Player H (<span class="hljs-number">3</span> goals)
Final Mean = <span class="hljs-number">4</span> goals

Group <span class="hljs-number">3</span> (Old Mean = <span class="hljs-number">21</span> goals)
  Player G (<span class="hljs-number">30</span> goals),
  Player B (<span class="hljs-number">20</span> goals),
  Player F (<span class="hljs-number">19</span> goals)
Final Mean = <span class="hljs-number">23</span> goals
</code></pre><p>With this example, the clusters could correspond to the players’ positions on the field — such as defenders, midfielders and attackers. </p>
<p>K-means works here because we could have reasonably expected the data to fall naturally into these three categories.</p>
<p>In this way, given data on a range of performance statistics, a machine could do a reasonable job of estimating the positions of players from any team sport — useful for sports analytics, and indeed any other purpose where classification of a dataset into predefined groups can provide relevant insights.</p>
<h4 id="heading-finer-details"><strong>Finer details</strong></h4>
<p>There are several variations on the algorithm described here. The initial method of ‘seeding’ the clusters can be done in one of several ways. </p>
<p>Here, we randomly assigned every player into a group, then calculated the group means. This causes the initial group means to tend towards being similar to one another, which ensures greater repeatability.</p>
<p>An alternative is to seed the clusters with just one player each, then start assigning players to the nearest cluster. The returned clusters are more sensitive to the initial seeding step, reducing repeatability in highly variable datasets. </p>
<p>However, this approach may reduce the number of iterations required to complete the algorithm, as the groups will take less time to diverge.</p>
<p>An obvious limitation to K-means clustering is that you have to provide <em>a priori</em> assumptions about how many clusters you’re expecting to find. </p>
<p>There are methods to assess the fit of a particular set of clusters. For example, the Within-Cluster <a target="_blank" href="https://en.wikipedia.org/wiki/Partition_of_sums_of_squares">Sum-of-Squares</a> is a measure of the variance within each cluster.</p>
<p>The ‘better’ the clusters, the lower the overall WCSS.</p>
<h3 id="heading-hierarchical-clustering">Hierarchical clustering</h3>
<h4 id="heading-use-when-1"><strong>Use when...</strong></h4>
<p>…you wish to uncover the underlying relationships between your observations.</p>
<h4 id="heading-how-it-works-1"><strong>How it works</strong></h4>
<p>A distance matrix is computed, where the value of cell (<em>i, j)</em> is a distance metric between observations <em>i</em> and <em>j</em>. </p>
<p>Then, pair the closest two observations and calculate their average. Form a new distance matrix, merging the paired observations into a single object. </p>
<p>From this distance matrix, pair up the closest two observations and calculate their average. Repeat until all observations are grouped together.</p>
<h4 id="heading-worked-example-1"><strong>Worked example</strong></h4>
<p>Here’s a super-simplified dataset about a selection of whale and dolphin species. As a trained biologist, I can assure you we normally use much more detailed datasets for things like <a target="_blank" href="https://en.wikipedia.org/wiki/Phylogenetic_tree">reconstructing phylogeny</a>. </p>
<p>For now though, we’ll just look at the typical body lengths for these six species. We’ll be using just two repeated steps.</p>
<pre><code>Species          Initials  Length(m)
Bottlenose Dolphin     BD        <span class="hljs-number">3.0</span>
Risso<span class="hljs-string">'s Dolphin        RD        3.6
Pilot Whale            PW        6.5
Killer Whale           KW        7.5
Humpback Whale         HW       15.0
Fin Whale              FW       20.0</span>
</code></pre><p><strong>Step 1:</strong> compute a distance matrix between each species. Here, we’ll use the <a target="_blank" href="https://en.wikipedia.org/wiki/Euclidean_distance">Euclidean distance</a> — how far apart are the data points? </p>
<p>Read this exactly as you would a distance chart in a road atlas. The difference in length between any pair of species can be looked up by reading the value at the intersection of the relevant row and column.</p>
<pre><code>    BD   RD   PW   KW   HW
RD  <span class="hljs-number">0.6</span>                    
PW  <span class="hljs-number">3.5</span>  <span class="hljs-number">2.9</span>               
KW  <span class="hljs-number">4.5</span>  <span class="hljs-number">3.9</span>  <span class="hljs-number">1.0</span>          
HW <span class="hljs-number">12.0</span> <span class="hljs-number">11.4</span>  <span class="hljs-number">8.5</span>  <span class="hljs-number">7.5</span>     
FW <span class="hljs-number">17.0</span> <span class="hljs-number">16.4</span> <span class="hljs-number">13.5</span> <span class="hljs-number">12.5</span>  <span class="hljs-number">5.0</span>
</code></pre><p><strong>Step 2:</strong> Pair up the two closest species. Here, this will be the Bottlenose &amp; Risso’s Dolphins, with an average length of 3.3m.</p>
<p><strong>Repeat</strong> Step 1 by recalculating the distance matrix, but this time merge the Bottlenose &amp; Risso’s Dolphins into a single object with length 3.3m.</p>
<pre><code>    [BD, RD]   PW   KW   HW
PW       <span class="hljs-number">3.2</span>               
KW       <span class="hljs-number">4.2</span>   <span class="hljs-number">1.0</span>          
HW      <span class="hljs-number">11.7</span>   <span class="hljs-number">8.5</span>  <span class="hljs-number">7.5</span>     
FW      <span class="hljs-number">16.7</span>  <span class="hljs-number">13.5</span> <span class="hljs-number">12.5</span>  <span class="hljs-number">5.0</span>
</code></pre><p><strong>Next</strong>, repeat Step 2 with this new distance matrix. Here, the smallest distance is between the Pilot &amp; Killer Whales, so we pair them up and take their average — which gives us 7.0m.</p>
<p><strong>Then</strong>, we repeat Step 1 — recalculate the distance matrix, but now we’ve merged the Pilot &amp; Killer Whales into a single object of length 7.0m.</p>
<pre><code>         [BD, RD] [PW, KW]   HW
 [PW, KW]      <span class="hljs-number">3.7</span>              
 HW           <span class="hljs-number">11.7</span>      <span class="hljs-number">8.0</span>     
 FW           <span class="hljs-number">16.7</span>     <span class="hljs-number">13.0</span>   <span class="hljs-number">5.0</span>
</code></pre><p><strong>Next</strong>, repeat Step 2 with this distance matrix. The smallest distance (3.7m) is between the two merged objects — so now merge them into an even bigger object, and take the average (which is 5.2m).</p>
<p><strong>Then</strong>, repeat Step 1 and compute a new distance matrix, having merged the Bottlenose &amp; Risso’s Dolphins with the Pilot &amp; Killer Whales.</p>
<pre><code>   [[BD, RD] , [PW, KW]]    HW
HW                   <span class="hljs-number">9.8</span>    
FW                  <span class="hljs-number">14.8</span>   <span class="hljs-number">5.0</span>
</code></pre><p><strong>Next</strong>, repeat Step 2. The smallest distance (5.0m) is between the Humpback &amp; Fin Whales, so merge them into a single object, and take the average (17.5m).</p>
<p><strong>Then</strong>, it’s back to Step 1 — compute the distance matrix, having merged the Humpback &amp; Fin Whales.</p>
<pre><code>         [[BD, RD] , [PW, KW]]
[HW, FW]                  <span class="hljs-number">12.3</span>
</code></pre><p><strong>Finally,</strong> repeat Step 2 — there is only one distance (12.3m) in this matrix, so pair everything into one big object. Now you can <strong>stop!</strong> Look at the final merged object:</p>
<pre><code>[[[BD, RD],[PW, KW]],[HW, FW]]
</code></pre><p>It has a nested structure (think <a target="_blank" href="http://json.org/example.html">JSON</a>), which allows it to be drawn up as a tree-like graph, or 'dendrogram'.</p>
<p>It reads in much the same way a family tree might. The nearer two observations are on the tree, the more similar or closely-related they are taken to be.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/mPiihHFW6hWNtBOST4BqWS-JpX9pSUJRb78x" alt="Image" width="480" height="480" loading="lazy">
_A no-frills dendrogram generated at [R-Fiddle.org](http://www.r-fiddle.org/#" rel="noopener" target="<em>blank" title=")</em></p>
<p>The structure of the dendrogram gives insight into how the dataset is structured.</p>
<p>In this example, there are two main branches, with Humpback Whale and Fin Whale on one side, and the Bottlenose Dolphin/Risso’s Dolphin and Pilot Whale/Killer Whale on the other.</p>
<p>In evolutionary biology, much larger datasets with many more specimens and measurements are used in this way to infer taxonomic relationships between them. </p>
<p>Outside of biology, hierarchical clustering has applications in data mining and machine learning contexts.</p>
<p>The cool thing is that this approach requires no assumptions about the number of clusters you’re looking for. </p>
<p>You can split the returned dendrogram into clusters by “cutting” the tree at a given height. This height can be chosen in a number of ways, depending on the resolution at which you wish to cluster the data.</p>
<p>For instance, looking at the dendrogram above, if we draw a horizontal line at height = 10, we’d intersect the two main branches, splitting the dendrogram into two sub-graphs. If we cut at height = 2, we’d be splitting the dendrogram into three clusters.</p>
<h4 id="heading-finer-details-1"><strong>Finer details</strong></h4>
<p>There are essentially three aspects in which hierarchical clustering algorithms can vary to the one given here.</p>
<p>Most fundamental is the approach — here, we have used an <em>agglomerative</em> process, whereby we start with individual data points and iteratively cluster them together until we’re left with one large cluster. </p>
<p>An alternative (but more computationally intensive) approach is to start with one giant cluster, and then proceed to divide the data into smaller and smaller clusters until you’re left with isolated data points.</p>
<p>There are also a range of methods that can be used to calculate the distance matrices. For many purposes, the Euclidean distance (think Pythagoras’ Theorem) will suffice, but there are <a target="_blank" href="https://en.wikipedia.org/wiki/Metric_(mathematics)">alternatives</a> that may be more applicable in some circumstances.</p>
<p>Finally, the <em>linkage criterion</em> can also vary. Clusters are linked according to how close they are to one another, but the way in which we define ‘close’ is flexible.</p>
<p> In the example above, we measured the distances between the means (or ‘centroids’) of each group and paired up the nearest groups. However, you may want to use a different definition.</p>
<p>For example, each cluster is made up of several discrete points. You could define the distance between two clusters to be the minimum (or maximum) distance between any of their points — as illustrated in the figure below.</p>
<p>There are still other ways of defining the linkage criterion, which may be suitable in different contexts.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/cb0OUKorixLdjc-oVQ4srQvwLzzoBT7rdivq" alt="Image" width="800" height="448" loading="lazy">
<em>Red/Blue: centroid linkage; Red/Green: minimum linkage; Green/Blue: maximum linkage</em></p>
<h3 id="heading-graph-community-detection">Graph Community Detection</h3>
<h4 id="heading-use-when-2"><strong>Use when</strong></h4>
<p>…you have data that can be represented as a network, or ‘graph’.</p>
<h4 id="heading-how-it-works-2"><strong>How it works</strong></h4>
<p>A <em>graph community</em> is very generally defined as a subset of vertices which are more connected to each other than with the rest of the network. </p>
<p>Various algorithms exist to identify communities, based upon more specific definitions. Algorithms include, but are not limited to: Edge Betweenness, Modularity-Maximsation, Walktrap, Clique Percolation, Leading Eigenvector…</p>
<h4 id="heading-worked-example-2"><strong>Worked example</strong></h4>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Graph_theory">Graph theory</a>, or the mathematical study of networks, is a fascinating branch of mathematics that lets us model complex systems as an abstract collection of ‘dots’ (or <em>vertices</em>) connected by ‘lines’ (or <em>edges</em>).</p>
<p>Perhaps the most intuitive case-studies are social networks. </p>
<p>Here, the vertices represent people, and edges connect vertices who are friends/followers. However, any system can be modelled as a network if you can justify a method to meaningfully connect different components. </p>
<p>Among the more innovative applications of graph theory to clustering include feature extraction from image data, and analysing gene regulatory networks.</p>
<p>As an entry-level example, take a look at this quickly put-together graph. It shows the eight websites I most recently visited, linked according to whether their respective Wikipedia articles link out to one another.</p>
<p>You could assemble this data manually, but for larger-scale projects, it’s much quicker to write a Python script to do the same. <a target="_blank" href="https://raw.githubusercontent.com/pg0408/Medium-articles/master/graph_maker.py">Here’s one I wrote earlier</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ir9Qji2KQ-YrkQSUOs4caYehAT9nDsDPu0jA" alt="Image" width="533" height="327" loading="lazy">
<em>Graph plotted with ‘igraph’ package for R version 3.3.3</em></p>
<p>The vertices are colored according to their community membership, and sized according to their <em>centrality</em>. See how Google and Twitter are the most central?</p>
<p>Also, the clusters make pretty good sense in the real-world (always an important performance indicator). </p>
<p>The yellow vertices are generally reference/look-up sites; the blue vertices are all used for online publishing (of articles, tweets, or code); and the red vertices include YouTube, which was of course founded by former PayPal employees. Not bad deductions for a machine.</p>
<p>Aside from being a useful way to visualize large systems, the real power of networks comes from their mathematical analysis. Let’s start by translating our nice picture of the network into a more mathematical format. Below is the <em>adjacency matrix</em> of the network.</p>
<pre><code>         GH Gl  M  P  Q  T  W  Y
GitHub    <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  
Google    <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>
Medium    <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>
PayPal    <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>
Quora     <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>
Twitter   <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>
Wikipedia <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>
YouTube   <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">0</span>  <span class="hljs-number">0</span>
</code></pre><p>The value at the intersection of each row and column records whether there is an edge between that pair of vertices. </p>
<p>For instance, there is an edge between Medium and Twitter (surprise, surprise!), so the value where their rows/columns intersect is 1. Similarly, there is no edge between Medium and PayPal, so the intersection of their rows/columns returns 0.</p>
<p>Encoded within the adjacency matrix are all the properties of this network — it gives us the key to start unlocking all manner of valuable insights.</p>
<p>For a start, summing any column (or row) gives you the <em>degree</em> of each vertex — i.e., how many others it is connected to. This is commonly denoted with the letter <em>k</em>.</p>
<p>Likewise, summing the degrees of every vertex and dividing by two gives you <em>L</em>, the number of edges (or ‘links’) in the network. The number of rows/columns gives us <em>N</em>, the number of vertices (or ‘nodes’) in the network.</p>
<p>Knowing just <em>k</em>, <em>L, N</em> and the value of each cell in the adjacency matrix <em>A</em> lets us calculate the <a target="_blank" href="https://en.wikipedia.org/wiki/Modularity_(networks)"><em>modularity</em></a> of any given clustering of the network.</p>
<p>Say we’ve clustered the network into a number of communities. We can use the modularity score to assess the ‘quality’ of this clustering. </p>
<p>A higher score will show we’ve split the network into ‘accurate’ communities, whereas a low score suggests our clusters are more random than insightful. The image below illustrates this.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/O42yBf3CmmP83k2h5gCmJHer2ycdggjCkuzk" alt="Image" width="800" height="376" loading="lazy">
<em>Modularity serves as a measure of the ‘quality’ of a partition.</em></p>
<p>Modularity can be calculated using the formula below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hUA32fMe6NNc7rs8Kq-2UWGGDYxBUtduIo51" alt="Image" width="800" height="297" loading="lazy"></p>
<p>That’s a fair amount of math, but we can break it down bit by bit and it’ll make more sense.</p>
<p><em>M</em> is of course what we’re calculating — modularity.</p>
<p>1/2<em>L</em> tells us to divide everything that follows by 2<em>L</em>, i.e., twice the number of edges in the network. So far, so good.</p>
<p>The <strong>Σ</strong> symbol tells us we’re summing up everything to the right, and lets us iterate over every row and column in the adjacency matrix <em>A</em>.</p>
<p>For those unfamiliar with sum notation, the <em>i, j = 1</em> and the <em>N</em> work much like nested for-loops in programming. In Python, you’d write it as follows:</p>
<pre><code class="lang-python">sum = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>,N):
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>,N):
        ans = <span class="hljs-comment">#stuff with i and j as indices </span>
    sum += ans
</code></pre>
<p>So what is <code>#stuff with i and j</code> in more detail?</p>
<p>Well, the bit in brackets tells us to subtract ( _k_i k<em>j ) / 2L</em> from _A<em>ij</em>.</p>
<p>_A<em>ij</em> is simply the value in the adjacency matrix at row <em>i</em>, column <em>j</em>.</p>
<p>The values of _k<em>i</em> and _k<em>j</em> are the degrees of each vertex — found by adding up the entries in row <em>i</em> and column <em>j</em> respectively. Multiplying these together and dividing by 2<em>L</em> gives us the expected number of edges between vertices <em>i</em> and <em>j</em> if the network were randomly shuffled up.</p>
<p>Overall, the term in the brackets reveals the difference between the network’s real structure and the expected structure it would have if randomly reassembled.</p>
<p>Playing around with the values shows that it returns its highest value when _A<em>ij</em> = 1, and ( _k_i k<em>j ) / 2L</em> is low. This means we see a higher value if there is an ‘unexpected’ edge between vertices <em>i</em> and <em>j.</em></p>
<p>Finally, we multiply the bracketed term by whatever the last few symbols refer to.</p>
<p>The ?c<strong>i,_ c</strong>j i_s the fancy-sounding but totally harmless Kronecker-delta function. Here it is, explained in Python:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">kroneckerDelta</span>(<span class="hljs-params">ci, cj</span>):</span>
    <span class="hljs-keyword">if</span> ci == cj:
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>

kroneckerDelta(<span class="hljs-string">"A"</span>,<span class="hljs-string">"A"</span>)
<span class="hljs-comment">#returns 1</span>

kroneckerDelta(<span class="hljs-string">"A"</span>,<span class="hljs-string">"B"</span>)
<span class="hljs-comment">#returns 0</span>
</code></pre>
<p>Yes — it really is that simple. The Kronecker-delta function takes two arguments, and returns 1 if they are identical, otherwise, zero.</p>
<p>This means that if vertices <em>i</em> and <em>j</em> have been put in the same cluster, then ?c<strong>i,_ c</strong>j = 1_. Otherwise, if they are in different clusters, the function returns zero.</p>
<p>As we are multiplying the bracketed term by this Kronecker-delta function, we find that for the nested sum <strong>Σ</strong>, the outcome is highest when there are lots of ‘unexpected’ edges connecting vertices assigned to the same cluster. </p>
<p>As such, modularity is a measure of how well-clustered the graph is into separate communities.</p>
<p>Dividing by <em>2L</em> bounds the upper value of modularity at 1. Modularity scores near to or below zero indicate the current clustering of the network is really no use. The higher the modularity, the better the clustering of the network into separate communities. </p>
<p>By maximising modularity, we can find the best way of clustering the network.</p>
<p>Notice that we have to pre-define how the graph is clustered to find out how ‘good’ that clustering actually is. </p>
<p>Unfortunately, employing brute force to try out every possible way of clustering the graph to find which has the highest modularity score would be computationally impossible beyond a very limited sample size.</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Partition_of_a_set#Counting_partitions">Combinatorics</a> tells us that for a network of just eight vertices, there are 4140 different ways of clustering them. A network twice the size would have over ten billion possible ways of clustering the vertices. </p>
<p>Doubling the network again (to a very modest 32 vertices) would give 128 septillion possible ways, and a network of eighty vertices would be cluster-able in more ways than there are <a target="_blank" href="https://www.wolframalpha.com/input/?i=991267988808424794443839434655920239360814764000951599022939879419136287216681744888844&amp;lk=1&amp;rawformassumption=%22ClashPrefs%22+-%3E+%7B%22Math%22%7D">atoms in the observable universe</a>.</p>
<p>Instead, we have to turn to a <em>heuristic</em> method that does a reasonably good job at estimating the clusters that will produce the highest modularity score, without trying out every single possibility. </p>
<p>This is an algorithm called <em>Fast-Greedy Modularity-Maximization,</em> and it’s somewhat analogous to the agglomerative hierarchical clustering algorithm describe above. Instead of merging according to distance, ‘Mod-Max’ merges communities according to changes in modularity. </p>
<p>Here’s how it goes:</p>
<p><strong>Begin</strong> by initially assigning every vertex to its own community, and calculating the modularity of the whole network, <em>M</em>.</p>
<p><strong>Step 1</strong> requires that for each community pair linked by at least a single edge, the algorithm calculates the resultant change in modularity Δ<em>M</em> if the two communities were merged into one.</p>
<p><strong>Step 2</strong> then takes the pair of communities that produce the biggest increase in Δ<em>M,</em> which are then merged. Calculate the new modularity <em>M</em> for this clustering, and keep a record of it.</p>
<p><strong>Repeat</strong> steps 1 and 2 — each time merging the pair of communities for which doing so produces the biggest gain in Δ<em>M,</em> then recording the new clustering pattern and its associated modularity score <em>M</em>.</p>
<p><strong>Stop</strong> when all the vertices are grouped into one giant cluster. Now the algorithm checks the records it kept as it went along, and identifies the clustering pattern that returned the highest value of <em>M</em>. This is the returned community structure.</p>
<h4 id="heading-finer-details-2"><strong>Finer details</strong></h4>
<p>Whew! That was computationally intensive, at least for us humans. </p>
<p>Graph theory is a rich source of computationally challenging, often NP-hard problems — yet it also has incredible potential to provide valuable insights into complex systems and datasets. </p>
<p>Just ask Larry Page, whose eponymous PageRank algorithm — which helped propel Google from start-up to basically world domination in less than a generation — was based entirely in graph theory.</p>
<p>Community detection is a major focus of current research in graph theory, and there are plenty of alternatives to Modularity-Maximization, which while useful, does have some drawbacks.</p>
<p>For a start, its agglomerative approach often sees small, well-defined communities swallowed up into larger ones. This is known as the <em>resolution limit</em> — the algorithm will not find communities below a certain size. </p>
<p>Another challenge is that rather than having one distinct, easy-to-reach global peak, the Mod-Max approach actually tends to produce a wide ‘plateau’ of many similar high modularity scores — making it somewhat difficult to truly identify the absolute maximum score.</p>
<p>Other algorithms use different ways to define and approach community detection.</p>
<p><em>Edge-Betweenness</em> is a divisive algorithm, starting with all vertices grouped in one giant cluster. It proceeds to iteratively remove the least ‘important’ edges in the network, until all vertices are left isolated. This produces a hierarchical structure, with similar vertices closer together in the hierarchy.</p>
<p>Another algorithm is <em>Clique Percolation</em>, which takes into account possible overlap between graph communities. </p>
<p>Yet another set of algorithms are based on <a target="_blank" href="https://en.wikipedia.org/wiki/Random_walk">random-walks</a> across the graph, and then there are <a target="_blank" href="https://en.wikipedia.org/wiki/Spectral_clustering"><em>spectral clustering</em></a> methods which start delving into the eigendecomposition of the adjacency matrix and other matrices derived therefrom. These ideas are used in feature extraction in, for example, areas such as computer vision.</p>
<p>It’d be well beyond the scope of this article to give each algorithm its own in-depth worked example. Suffice to say that this is an active area of research, providing powerful methods to make sense of data that even a generation ago would have been extremely difficult to process.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Hopefully this article has informed and inspired you to better understand how machines can make sense of data. The future is a rapidly changing place, and many of those changes will be driven by what technology becomes capable of in the next generation or two.</p>
<p>As outlined in the introduction, machine learning is an extraordinarily ambitious field of research, in which massively complex problems require solving in as accurate and as efficient a way possible. Tasks that come naturally to us humans require innovative solutions when taken on by machines.</p>
<p>There’s still plenty of progress to be made, and whoever contributes the next breakthrough idea will no doubt be generously rewarded. Maybe someone reading this article will be behind the next powerful algorithm?</p>
<p>All great ideas have to start somewhere!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
