<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>code-spot &#187; Algorithms</title>
	<atom:link href="http://code-spot.co.za/category/algorithms/feed/" rel="self" type="application/rss+xml" />
	<link>http://code-spot.co.za</link>
	<description>a programming blog</description>
	<lastBuildDate>Sun, 27 Feb 2011 07:18:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</title>
		<link>http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/</link>
		<comments>http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 22:30:49 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[implicit queue algorithm]]></category>
		<category><![CDATA[max-queue algorithm]]></category>
		<category><![CDATA[maximum filter]]></category>
		<category><![CDATA[minimum filter]]></category>
		<category><![CDATA[monotonic wedge algorithm]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=1100</guid>
		<description><![CDATA[A while back I needed to implement fast minimum and maximum filters for images. I devised (what I thought was) a clever approximation scheme where the execution time is not dependent on the window size of the filter. But the method had some issues, and I looked at some other algorithms. In retrospect, the method I [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='Permanent Link: 5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-1101" title="minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2011/01/minmax.png" alt="" width="491" height="321" /></p>
<p>A while back I needed to implement fast minimum and maximum filters for images. I devised (what I thought was) a <a href="http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/">clever approximation scheme</a> where the execution time is not dependent on the window size of the filter. But the method had some issues, and I looked at some other algorithms. In retrospect, the method I used seems foolish. At the time, I did not realise the obvious: a 1D filter could be applied to first the rows, and then the columns of an image, which makes the slow algorithm faster, or allows you to use one of the many published fast 1D algorithms.</p>
<p>I wanted to write down my gained knowledge, and started to work on a blog post. But soon it became quite long, so I decided to put it into a PDF document instead. You can download it below.</p>
<p><span id="more-1100"></span>The document is somewhat weird: it is very detailed for a &#8220;simple&#8221; image algorithm (it is more than 50 pages!). It does have several tips that applies to implementation of other image processing algorithms. It also has, what I believe to be, a very clear description of the Monotonic Wedge Algorithm, with code that reflects the explanation in text closely. (I had trouble understanding the algorithm from the original journal publication. And the authors provide code that was even further optimised and thus less clear to follow).</p>
<p>I intended to give some performance analysis and results, but other activities has robbed me of any free time. Perhaps later.</p>
<p>Also, the code has been edited for readability, and hence, might contain typos that were introduced in the process. If you spot any, please let me know.</p>
<h2>Download</h2>
<p><a href="http://www.code-spot.co.za/downloads/image/minmax_filters.pdf">minmax_filters.pdf (230 KB)</a></p>
<h2>Table of Contents</h2>
<blockquote>
<div id="_mcePaste">1 The Problem</div>
<div id="_mcePaste">2 Exact Algorithms</div>
<div id="_mcePaste">2.1 The Naive Algorithm</div>
<div id="_mcePaste">2.2 The Max-Queue</div>
<div id="_mcePaste">2.3 Implicit Queue Algorithm</div>
<div id="_mcePaste">2.4 The Monotonic Wedge Algorithm</div>
<div id="_mcePaste">3 Approximate Algorithms</div>
<div id="_mcePaste">3.1 The Power Mean Approximation</div>
<div id="_mcePaste">3.2 The Power Mean Variant Algorithm</div>
<div id="_mcePaste">3.3 The Contra-Harmonic Mean Approximation</div>
<div id="_mcePaste">4 Other Algorithm Concepts</div>
<div id="_mcePaste">4.1 Separation</div>
<div id="_mcePaste">4.2 Implementing Minimum Filters</div>
<div id="_mcePaste">4.3 Windows with Even Diameters</div>
<div id="_mcePaste">4.4 Filtering a Region of Interest</div>
<div id="_mcePaste">4.5 Maximum and Minimum Filters for Binary Images</div>
<div id="_mcePaste">A Image Containers</div>
<div id="_mcePaste">A.1 Image Class Interface</div>
<div id="_mcePaste">A.2 Image Loops</div>
<div id="_mcePaste">A.3 Image Iterators</div>
<div id="_mcePaste">A.4 Image Access Modifiers</div>
<div id="_mcePaste">B Fixed-width Deques</div>
<div id="_mcePaste">C Max-queues</div>
<div id="_mcePaste">D Summed Area Tables</div>
<div id="_mcePaste">D.1 Calculating a SAT</div>
<div id="_mcePaste">D.2 Finding a Sum from a SAT</div>
<div id="_mcePaste">D.3 Checking for Overflow 50</div>
<div id="_mcePaste">D.4 Large SATs 53</div>
</blockquote>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='Permanent Link: 5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A Simple Trick for Moving Objects in a Physics Simulation</title>
		<link>http://code-spot.co.za/2010/07/27/a-simple-trick-for-moving-objects-in-a-physics-simulation/</link>
		<comments>http://code-spot.co.za/2010/07/27/a-simple-trick-for-moving-objects-in-a-physics-simulation/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 19:24:24 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Simulation]]></category>
		<category><![CDATA[damper]]></category>
		<category><![CDATA[force]]></category>
		<category><![CDATA[game programming]]></category>
		<category><![CDATA[physics]]></category>
		<category><![CDATA[PID controller]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=1013</guid>
		<description><![CDATA[(Original Image by Valerie Everett) It is sometime necessary to move an object in a physics simulation to a specific point. On the one hand, it can be difficult to analyse the exact force you have to apply; on the other hand it might not look so good if you animate the object&#8217;s position directly. [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
<li><a href='http://code-spot.co.za/2008/12/07/random-steering-7-components-for-a-toolkit/' rel='bookmark' title='Permanent Link: Random Steering &#8211; 7 Components for a Toolkit'>Random Steering &#8211; 7 Components for a Toolkit</a></li>
<li><a href='http://code-spot.co.za/2008/10/29/force-field-editor-v10/' rel='bookmark' title='Permanent Link: Force Field Editor v1.0'>Force Field Editor v1.0</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-1035" title="springs" src="http://code-spot.co.za/blog/wp-content/uploads/2010/07/springs2.png" alt="" width="488" height="257" /></p>
<p>(<a href="http://www.flickr.com/photos/valeriebb/248282508/sizes/o/">Original Image</a> by <a href="http://www.flickr.com/photos/valeriebb/">Valerie Everett</a>)</p>
<p>It is sometime necessary to move an object in a physics simulation to a specific point. On the one hand, it can be difficult to analyse the exact force you have to apply; on the other hand it might not look so good if you animate the object&#8217;s position directly.</p>
<p>A compromise that works well in many situations is to use a spring-damper system to move the object.</p>
<p>The trick is simple: we apply two forces—the one is proportional to the displacement; the other is proportional to the velocity. Tweaked correctly, they combine to give realistic movement to the desired point.</p>
<p><span id="more-1013"></span></p>
<p>The <a href="http://en.wikipedia.org/wiki/Hookes_law"><em>spring force</em></a> is proportional to the difference between the current position and the position where we want the object:</p>
<img src='http://s.wordpress.com/latex.php?latex=F_s%20%3D%20-k%28x%20-%20x_0%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='F_s = -k(x - x_0)' title='F_s = -k(x - x_0)' class='latex' />
<p>Here, <img src='http://s.wordpress.com/latex.php?latex=k&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='k' title='k' class='latex' /> is a positive value called the <em>spring constant</em>.</p>
<p>As you can see, the force gets smaller as our object approaches the desired position, and becomes zero when it reaches that position. Unfortunately, in the absence of friction or drag, the <em>velocity</em> is not zero at this point, so the object overshoots the desired position, and moves past it. The force becomes bigger, but in the opposite direction. The object keeps on moving, slowing down, and finally starts moving in the opposite direction towards the desired position. This goes on indefinitely.</p>
<p>When there is friction or drag, we might be lucky enough for the system to slow down the object sufficiently so that its velocity becomes zero when the object reaches the desired position. This can be tricky to accomplish, though, and might impact the simulation environment in undesirable ways.</p>
<p>It is better to add a counteracting force explicitly. We add a <em>damper force</em> that is propostional to the velocity of the object, again opposite in direction. Here <img src='http://s.wordpress.com/latex.php?latex=c&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c' title='c' class='latex' /> is the <em>viscous damping coefficient</em>, also a positive number.</p>
<img src='http://s.wordpress.com/latex.php?latex=F_d%20%3D%20-cv&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='F_d = -cv' title='F_d = -cv' class='latex' />
<p>We then apply the sum of the forces to our object:</p>
<img src='http://s.wordpress.com/latex.php?latex=F_t%20%3D%20F_s%20%2B%20F_d&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='F_t = F_s + F_d' title='F_t = F_s + F_d' class='latex' />
<p>The trick is to choose <img src='http://s.wordpress.com/latex.php?latex=c&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c' title='c' class='latex' /> to get the behaviour we want.</p>
<p>Fortunately, this is easy. The following table summarizes how the damping constant affects behaviour. Here, <img src='http://s.wordpress.com/latex.php?latex=m&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='m' title='m' class='latex' /> is the mass of the object.</p>
<table>
<tbody>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=c%20%3D%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c = 0' title='c = 0' class='latex' /></td>
<td>The object oscillates.</td>
</tr>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=0%20%3C%20c%20%3C%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='0 &lt; c &lt; 2\sqrt{mk}' title='0 &lt; c &lt; 2\sqrt{mk}' class='latex' /></td>
<td>The object oscillates, but the oscillations die down.</td>
</tr>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=c%20%3D%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c = 2\sqrt{mk}' title='c = 2\sqrt{mk}' class='latex' /></td>
<td>The object moves to the desired position without oscillating in minimum time.</td>
</tr>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=c%20%3E%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c &gt; 2\sqrt{mk}' title='c &gt; 2\sqrt{mk}' class='latex' /></td>
<td>The object moves to the desired position without oscillating, and takes longer as c increases.</td>
</tr>
</tbody>
</table>
<p>If you want to see an explanation of how this works, see the Wikipedia article on <a href="http://en.wikipedia.org/wiki/Damping">damping</a>.</p>
<p>By choosing <img src='http://s.wordpress.com/latex.php?latex=c%20%3D%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c = 2\sqrt{mk}' title='c = 2\sqrt{mk}' class='latex' />, we are left with only one parameter to tweak (the spring constant), with which we can adjust the time it will take for the object to reach the desired spot.</p>
<p>A simple implementation of this idea is given by the following function. The function should be called for every simulation frame, until we are satisfied that the object reached its spot:</p>
<pre>private void MoveTo(Rigidbody rigidbody, Vector3 newPosition,
      float springConstant)
{
  Vector3 desiredDisplacement = rigidbody.position - newPosition;
  Vector3 springForce = -springConstant * desiredDisplacement;

  float viscousDampingCoefficient
    = 2 * sqrt(rigidbody.mass * springConstant);

  Vector3 dampingForce
    = -viscousDampingCoefficient * rigidbody.velocity;

  Vector3 totalForce = springForce + dampingForce;
  rigidbody.AddForce(totalForce);
}</pre>
<p>This will work even when there is drag or friction, except that the object will move slower (in this case we can decrease the artificial damping, although it is a bit risky). When there is an external force applied to the object, the object will come to rest at some point away from the desired position. By increasing the spring constant, the distance between this point and the desired point can be made smaller. Thus, we can also use this scheme to maintain objects at a certain height, for example, which can give a rather realistic simulation of a hovercraft or even a drifting object.</p>
<p><strong>Update: </strong>This is an example of a <a href="http://en.wikipedia.org/wiki/PID_controller">PID controller</a> (proportional–integral–derivative controller), for which there is a C++ implementation in my <a href="http://code.google.com/p/specialnumbers/">Special Numbers Library</a>.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
<li><a href='http://code-spot.co.za/2008/12/07/random-steering-7-components-for-a-toolkit/' rel='bookmark' title='Permanent Link: Random Steering &#8211; 7 Components for a Toolkit'>Random Steering &#8211; 7 Components for a Toolkit</a></li>
<li><a href='http://code-spot.co.za/2008/10/29/force-field-editor-v10/' rel='bookmark' title='Permanent Link: Force Field Editor v1.0'>Force Field Editor v1.0</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/07/27/a-simple-trick-for-moving-objects-in-a-physics-simulation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Region Quadtrees in C++</title>
		<link>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/</link>
		<comments>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 11:14:14 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[image partitioning]]></category>
		<category><![CDATA[quadtree]]></category>
		<category><![CDATA[quadtrees]]></category>
		<category><![CDATA[spatial partitioning]]></category>
		<category><![CDATA[sum]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=983</guid>
		<description><![CDATA[(Original image by GoAwayStupidAI). Below are four C++ implementations of the region quadtree (the kind used for image compression, for example). The different implementations were made in an attempt to optimise construction of quadtrees. (For a tutorial on implementing region quadtrees, see Issue 26 [6.39 MB zip] of Dev.Mag). NaiveQuadtree is the straightforward implementation. AreaSumTableQuadtree [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline; border: 0px;" title="quadtree" src="http://code-spot.co.za/blog/wp-content/uploads/2010/06/quadtree.png" border="0" alt="quadtree" width="491" height="375" /></p>
<p>(<a href="http://www.flickr.com/photos/goawaystupidai/3106598088/">Original image</a> by <a href="http://www.flickr.com/photos/goawaystupidai/">GoAwayStupidAI</a>).</p>
<p>Below are four C++ implementations of the <a href="http://www.voronoi.com/wiki/index.php?title=Quadtree">region quadtree</a> (the kind used for image compression, for example). The different implementations were made in an attempt to optimise <em>construction </em>of quadtrees. (For a tutorial on implementing region quadtrees, see <a href="http://www.devmag.org.za/uploads/DevMag_Issue26.zip" class="broken_link">Issue 26</a> [6.39 MB zip] of <a href="http://devmag.org.za/">Dev.Mag</a>).</p>
<ul>
<li><strong>NaiveQuadtree </strong>is the straightforward implementation.</li>
<li><strong>AreaSumTableQuadtree </strong>uses a <a href="http://en.wikipedia.org/wiki/Summed_area_table">summed area table</a> to perform fast calculations of the mean and variance of regions in the data grid.</li>
<li><strong>AugmentedAreaSumTableQuadtree </strong>is the same, except that the area sum table has an extra row and column of zeros to prevents if-then logic that slows it down and makes it tricky to understand.</li>
<li><strong>SimpleQuadtree </strong>is the same as AugmentedAreaSumTableQuadtree , except that no distinction is made (at a class level) between different node types.</li>
</ul>
<p><span id="more-983"></span>The interfaces of all quadtrees are the same, but I did not want to extend from a base class. (Instead, a compile time check is performed on the classes, using <a href="http://www.boost.org/doc/libs/1_43_0/libs/concept_check/concept_check.htm">boost concepts</a>).</p>
<p>The results of the performance (on my machine!) of the trees are as follows:</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td style="text-align: left;" width="100" valign="top">(milliseconds)</td>
<td style="text-align: right;" width="100" valign="top"><strong>N</strong></td>
<td style="text-align: right;" width="100" valign="top"><strong>S</strong></td>
<td style="text-align: right;" width="100" valign="top"><strong>AST</strong></td>
<td style="text-align: right;" width="100" valign="top"><strong>AAST</strong></td>
</tr>
<tr>
<td style="text-align: right;" width="100" valign="top"></td>
<td style="text-align: right;" width="100" valign="top">3</td>
<td style="text-align: right;" width="100" valign="top">4</td>
<td style="text-align: right;" width="100" valign="top">4</td>
<td style="text-align: right;" width="100" valign="top">3</td>
</tr>
<tr>
<td width="100" valign="top"><strong>64×64</strong></td>
<td style="text-align: right;" width="100" valign="top">14</td>
<td style="text-align: right;" width="100" valign="top">14</td>
<td style="text-align: right;" width="100" valign="top">14</td>
<td style="text-align: right;" width="100" valign="top">13</td>
</tr>
<tr>
<td width="100" valign="top"><strong>128×128</strong></td>
<td style="text-align: right;" width="100" valign="top">55</td>
<td style="text-align: right;" width="100" valign="top">52</td>
<td style="text-align: right;" width="100" valign="top">55</td>
<td style="text-align: right;" width="100" valign="top">52</td>
</tr>
<tr>
<td width="100" valign="top"><strong>256×256</strong></td>
<td style="text-align: right;" width="100" valign="top">229</td>
<td style="text-align: right;" width="100" valign="top">233</td>
<td style="text-align: right;" width="100" valign="top">218</td>
<td style="text-align: right;" width="100" valign="top">214</td>
</tr>
<tr>
<td width="100" valign="top"><strong>512×512</strong></td>
<td style="text-align: right;" width="100" valign="top">950</td>
<td style="text-align: right;" width="100" valign="top">1036</td>
<td style="text-align: right;" width="100" valign="top">937</td>
<td style="text-align: right;" width="100" valign="top">922</td>
</tr>
<tr>
<td width="100" valign="top"><strong>1024×1024</strong></td>
<td style="text-align: right;" width="100" valign="top">4064</td>
<td style="text-align: right;" width="100" valign="top">4459</td>
<td style="text-align: right;" width="100" valign="top">5396</td>
<td style="text-align: right;" width="100" valign="top">3891</td>
</tr>
</tbody>
</table>
<p>As it turns out, the different implementations do not differ significantly. Constructing the nodes takes long, and not so much the calculations necessary to determine whether a node should split or not, and what data should be in the node. Had I profiled properly before I started I would not have gone through this exercise…</p>
<p>Between these four implementations, the NaiveQuadtree is the one I recommend; I left in the other implementations for anyone interested.</p>
<p>The one good thing that came from this experiment is that I found out that using a zero-augmented summed area table can increase performance quite a bit. This is useful for <a href="http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/">max-filters</a> and other algorithms that use these tables.</p>
<p>You can download the source code:</p>
<p><a href="http://www.code-spot.co.za/downloads/cpp/Quadtree.zip">Quadtree.zip</a> (44 KB, Visual Studio).</p>
<p>(It requires the <a href="http://www.boost.org/users/download/">boost library</a> for concept checking, but nothing else. Everything will still work if you remove all references to the boost library. If you already have boost, just hook up to the include path in Visual Studio).</p>
<p>&#8230;or read the <a href="http://www.code-spot.co.za/downloads/cpp/quadtrees/html/index.html">online documentation</a>.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Catching Common Image Processing Programming Errors with Generic Unit Tests</title>
		<link>http://code-spot.co.za/2010/05/12/catching-common-image-processing-programming-errors-with-generic-unit-tests/</link>
		<comments>http://code-spot.co.za/2010/05/12/catching-common-image-processing-programming-errors-with-generic-unit-tests/#comments</comments>
		<pubDate>Wed, 12 May 2010 13:40:30 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=936</guid>
		<description><![CDATA[When implementing image algorithms, I am prone to make these mistakes: swapping x and y; working on the wrong channel; making off-by-one errors, especially in window algorithms; making division-by-zero errors; handling borders incorrectly; and handling non-power-of-two sized images incorrectly. Since these types of errors are prevalent in many image-processing algorithms, it would be useful to [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-947" title="crash test dummy" src="http://code-spot.co.za/blog/wp-content/uploads/2010/05/dummy1.png" alt="crash test dummy" width="491" height="321" /></p>
<p>When implementing image algorithms, I am prone to make these mistakes:</p>
<ul>
<li>swapping x and y;</li>
<li>working on the wrong channel;</li>
<li>making off-by-one errors, especially in window algorithms;</li>
<li>making division-by-zero errors;</li>
<li>handling borders incorrectly; and</li>
<li>handling non-power-of-two sized images incorrectly.</li>
</ul>
<p>Since these types of errors are prevalent in many image-processing algorithms, it would be useful to develop, once and for all, general tests that will catch these errors quickly for <em>any</em> algorithm.</p>
<p>This post is about such tests.</p>
<p><span id="more-936"></span></p>
<h2>The General Idea</h2>
<p>The general idea is to exploit the fact that many algorithms satisfy invariants such as these:</p>
<pre>some_transform(algorithm(image))
  == algorithm(some_transform(image))</pre>
<p>For example: a 3-by-3 box blur is invariant under a vertical flip:</p>
<pre>box_blur3x3(flip_vertical(image))
  == flip_vertical(box_blur3x3 (image))</pre>
<p>It does not matter whether we apply the flip before or after applying the box filter—the result should be the same.</p>
<p>What kind of errors can the above test expose? Since it checks whether the algorithm (not the image) is vertically symmetric, the test can catch certain off-by-one errors along the vertical axis. Here is an example of a faulty implementation of the blur algorithm. Here the function <code>sum</code> adds all the pixel values in the rectangle x0..x1 – 1 and y0..y1 – 1.</p>
<pre>//C-like pseudo-code
Image &amp; box_filter3x3(Image &amp; image)
{
  forXY(image, x, y)
  {
    x0, y0 = max(0, x – 1), max(0, y – 1)
    x1, y1 = min(x + 1, image.width), min(y + 1, image.height)
    result = sum(image, x0, x1, y0, y1) / ((x1 – x0) * (y1 – y0));
  }

  image = result;
  return image;
}</pre>
<p>Can you spot the error? The actual window used is only 2 by 2. But how does the test catch this error? To see why the test will fail, notice the difference in windows for the top-left and bottom-left pixels:</p>
<p>Top Left:</p>
<pre>x0, y0 == 0, 0
x1, y1 == 1, 1</pre>
<p>Bottom Left</p>
<pre>x0, y0 == width – 2, height – 2
x1, y1 == width , height</pre>
<p>As you can see, the two windows have different sizes! The bottom-left pixel window is 1 by 1, but the top left pixel is 2 by 2. Thus flipping the image before and after applying the box-blur gives different results.</p>
<p>The correct algorithm is</p>
<pre>//C-like pseudo-code
Image &amp; box_filter3x3(Image &amp; image)
{
  forXY(image, x, y)
  {
    x0, y0 = max(0, x – 1), max(0, y – 1)
    x1, y1 = min(x + 2, image.width), min(y + 2, image.height)
    result = sum(image, x0, x1, y0, y1) /
      ((x1 – x0) * (y1 – y0));
  }

  image = result;

  return Image;
}</pre>
<p>Now the windows for the top and bottom left pixels are:</p>
<pre>x0, y0 == 0, 0
x1, y1 == 2, 2</pre>
<p>Bottom Left</p>
<pre>x0, y0 == width – 2, height – 2
x1, y1 == width , height</pre>
<p>We can see the window sizes are now the same.</p>
<h2>Transforms</h2>
<p>Here is a list of suggested transforms and the types of errors they can catch:</p>
<table border="0" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td width="140" valign="top"><code>flipVertical<br />
</code><code>flipHorizontal</code></td>
<td width="340" valign="top">Off-by-one errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>flipDiagonal</code></td>
<td width="340" valign="top">Swapping x and y.</td>
</tr>
<tr>
<td width="140" valign="top"><code>rotateChannels</code></td>
<td width="340" valign="top">Working on the wrong channel.</td>
</tr>
<tr>
<td width="140" valign="top"><code>invert</code></td>
<td width="340" valign="top">Calculation mistakes, certain kinds of division-by-zero. errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>scaleIntensity</code></td>
<td width="340" valign="top">Calculation mistakes.</td>
</tr>
<tr>
<td width="140" valign="top"><code>adjustGamma</code></td>
<td width="340" valign="top">Certain kinds of statistical ordering errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>crop</code></td>
<td width="340" valign="top">Certain kind of incorrect border calculations, certain power-of-two errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>translateVertival<br />
</code><code>translateHorizontal</code></td>
<td width="340" valign="top">Certain kinds of incorrect border calculations, off-by-one errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>desaturate</code></td>
<td width="340" valign="top">Certain channel processing errors.</td>
</tr>
</tbody>
</table>
<p>Many algorithms should (in theory) also be invariant under scaling. However, because of the complexity involved in interpolation and sampling, I do not recommend using scaling for testing. It is quite difficult to determine under some interpolation or sampling scheme whether an algorithm should in fact be (exactly) invariant or not under scaling. This of course also applies to other transforms that rely on sampling or interpolation.</p>
<p>You will probably also select transforms that are more specific to the algorithms you are implementing. Keep these as simple as possible—not only to avoid implementation errors, but also to avoid subtle misconceptions: it must be easy to see (or well established) that a certain algorithm is invariant under a transform. Test your own transform functions aggressively.</p>
<h2>Generic Solutions</h2>
<p>Writing test code for each transform is easy, but tedious (and hence error prone). Here I show how a generic test can be implemented using C++ macros or functional programming. The generic test can be used to test whether any algorithm is invariant under a given transform.</p>
<h3>Macros Implementation</h3>
<p>Probably the easiest way to implement a general test-function in C++ is to implement it as a macro. Here is how this looks:</p>
<pre>//C++
#define TEST_TRANSFORM_INVARIANCE(image, transform, command) \
  do { \
    Image image; \
    make_test_image(image); \
    \
    Image original_image(image); \
    command; \
    \
    Image image1(image); \
    transform(image1); \
    \
    image = original_image; \
    transform(image); \
    command; \
    \
    if (image != image1) \
      report_useful_failure_message(...); \
  } while(0)</pre>
<p>We can now use this macro like this:</p>
<pre>TEST_TRANSFORM_INVARIANCE (image, flipVertical, my_algorithm(image));</pre>
<p>The nice thing about the macro approach is how easy functions that take any number of parameters can be tested:</p>
<pre>TEST_TRANSFORM_INVARIANCE (image, flipVertical, my_algorithm(image, 10, 20));</pre>
<p>Notice that the first parameter is a <em>variable name</em>. The macro declares this variable, and the user can use it in the command parameter to pass the image to the algorithm.</p>
<h3>Functional Programming Implementation</h3>
<p>If macros are not available, or using them is not desirable, you can still use a generic approach. Unfortunately, we need to define functions with a consistent argument list for each test we want to perform, which means we might need to write more code in some languages.</p>
<p>The general test function can be defined as follows in C++:</p>
<pre>//C++
test_transform_inavriance(
  Image &amp; (* function)(Image &amp;),
  Image &amp; (* transform)(Image &amp;))
{
  Image image;
  make_test_image(image);

  Image original_image(image);
  function(image);

  Image image1(image);
  transform(image1);

  image = original_image;
  transform(image);
  function(image);

  if (image != image1)
    report_useful_failure_message(...);
}</pre>
<p>To use it with a single argument function, we simply call it like this:</p>
<pre>test_transform_inavriance(flip_vertical, my_algorithm);</pre>
<p>To use it with a function that takes more than one parameter, we need to define a function to call the extra parameters:</p>
<pre>// C++
Image &amp; test_my_algorithm_wrapper(Image &amp; image)
{
  my_algorithm(image, 10, 20);
}
...
test_transform_inavriance(flip_vertical, my_algorithm_wrapper);</pre>
<p>In languages that support closures, you can wrap functions more cleanly so that you do not need to define a function for each test command. For example, in Python:</p>
<pre># Python
def wrap(fn, args):
  def wrapper(image):
    fn(image, *args)
  return fn
...
test_transform_inavriance(flip_vertical, wrap(my_algorithm, 10, 20));</pre>
<h2>Test Bundles</h2>
<p>Both the macro and functional programming approaches allow you to combine tests of different transforms in convenient functions:</p>
<pre>// C++
#define TEST_ALL(image, command)\
  do { \
    TEST_TRANSFORM_INVARIANCE (image, flip_vertical, command); \
    TEST_TRANSFORM_INVARIANCE (image, flip_horizontal, command); \
    ...
  } while(0)</pre>
<pre>// C++
void test_all(Image &amp; (* fn)(Image &amp;))
{
  test_transform_inavriance(flip_vertical, function);
  test_transform_inavriance(flip_ horizontal, function);
  ...
}</pre>
<h2>Test Images</h2>
<p>It is important that your images do not destroy the very asymmetry that you are trying to expose. For instance, if we ran the test at the very beginning of this post with an all-zero image, the test will have passed. The image should be asymmetric under the transform we are using, that is, the following must hold:</p>
<pre>transform(image) != image</pre>
<p>For different transforms, this means different things. For example, for flip_diagonal, the image must not be square, for inverse, the image must not be the constant grayscale image 0.5.</p>
<p>It is useful to build an extra test into our test macro or function, to make sure that we do not inadvertently break this requirement. Here is the modified macro:</p>
<pre>// C++
#define TEST_TRANSFORM_INVARIANCE(image, transform, command)\
  do { \
    Image image; \
    make_test_image(image); \
    \
    Image original_image(image); \
    transform(image); \
    \
    if(image == original_image) \
      report_unsuitable_test_image(...); \
    \
    image = original_image; \
    command; \
    \
    Image image1(image); \
    transform(image1); \
    \
    image = original_image; \
    transform(image); \
    command; \
    \
    if (image != image1) \
      report_useful_failure_message(...); \
  } while(0)</pre>
<p>For many algorithms, using an image of noise (independent for each channel) works well. Make sure the image have unequal dimensions that are prime numbers (for example, 11 and 13). Using prime numbers ensures that the two dimensions will not have any common divisors, which makes certain kind of tests for recursive algorithms (such as quad-tree compression) more robust.</p>
<h2>Reporting Failures</h2>
<p>In the example implementation, we have the line</p>
<pre>if (image != image1) report_useful_failure_message(...);</pre>
<p>This is a somewhat simplistic scheme. What is a useful failure message? Of course, the message must report the test that failed. But it should also give information about how the test failed:</p>
<ul>
<li>whether it was a mismatch of the number of channels, image dimensions, or pixel values;</li>
<li>the number of channels and image dimensions;</li>
<li>the number of pixels for which the test failed; and</li>
<li>the first pixel location where the test failed, and the expected and actual pixel values.</li>
</ul>
<p>These bits of information can help us hunt down the cause. For example, if the test data is an 11-by-13 image, and the test fails for 13 pixels, the error is most likely a border problem caused by an off-by-one error. If the first pixels that fails is 0, 0, and the test fails for (almost) all pixels, and the pixel values differ only by sign, we can guess that there is some sign error made that affects the entire image.</p>
<p>The actual test will thus be a bit more complicated, delegating to a function such as this:</p>
<pre>test_image_equality(
  Image &amp; image1,
  Image image 2,
  FailureInfo &amp; info)
{
  info.has_failed = false;
  info.failed_pixels_count = 0;
  info.dimensions_image1 = image1.dimensions;
  info.dimensions_image2 = image2.dimensions;
  info.channels_image1 = image1.channels
  info.channels_image2 = image2.channels

  if(image1.channels != image2.channels)
  {
     info.has_failed = true;
     info.failure_type = CHANNEL_MISMATCH;
     return;
  }

  if(image1.dimensions != image2.dimensions)
  {
    info.has_failed = true;
    info.failure_type = DIMENSION_MISMATCH;
    return;
  }

  forXY(image, x, y)
  {
    if(abs(image1(x, y) - image2(x, y)) &lt; THRESHOLD)
    {
      if (!info.has_failed)
      {
        info.has_failed = true;
        info.failure_type = VALUE_MISMATCH;
        info.first_failed_x = x;
        info.first_failed_y = y;
        info_first_failed_image1 = image1(x,y);
        info_first_failed_image2 = image2(x,y);
      }

      info.failed_pixels_count++;
    }
  }
}</pre>
<p>In the test macro or function, we call the function like this:</p>
<pre>...
FailureInfo info; \
test_image_equality(image, image1, info); \
if (info.has_failed) report_failure(info); \
...</pre>
<h2>Using Third-Party Image Libraries</h2>
<p>It is important that you understand the transforms you use for testing very well. It is therefore a good idea to use you own transforms, and not those of a library. This way, unknown design choices in the library cannot bite you. Many image libraries do not for example specify how they handle borders, division by zero, rounding, etc. These details are often not important when using the algorithms in a task—but they can make a test fail (or succeed) when it should not.</p>
<p>The same danger exists when you use third party algorithms as building blocks for your own. In this case testing your code will be harder. As a starting point, consider testing whether third party algorithms satisfy the invariants you expect to hold. If they do not, you may need to modify your test code to accommodate for the discrepancy. If they do, you can be a little more confident that your tests will be reliable.</p>
<p>(Yes, it is not normally recommended to test other people&#8217;s code with unit tests. However, this is a once-off test to make sure that your own tests are reliable, and since it is so easy to implement (since you already have the test macro / function and transforms), I do not see the harm. Just keep the third-party library test separate from your own.)</p>
<h2>Defining Correctness—When are two images equal?</h2>
<p>Correctness of an image algorithm is a subtle issue, mostly because the discrete, quantized, finite model of image computation is inherently an approximation of the “real” thing. The question is too broad to tackle here (and frankly, I do not have enough knowledge to do it), so I will focus on aspects that are specifically relevant to this kind of testing.</p>
<p>Let us start with an example of an essentially correct algorithm that fails a test that we expect that it should not:</p>
<pre>// C++
Image &amp; threshold(Image &amp; image)
{
  forXY(image, x, y)
    image(x, y) = (image(x, y) &lt;= 0.5f) ? 0 : 1;

  return image;
}</pre>
<p>We expect this simple algorithm to be invariant under the inverse transform. However, it is not. Consider a pixel value of 0.5: the inverse of this is 0.5. So both the pixel and its inverse will map to zero, and hence the following will not be true:</p>
<pre>inverse(threshold(image)) == threshold(inverse(image)) //not true
inverse(threshold(0.5f)) == inverse(0) == 1 //left side
threshold(inverse(0.5f)) == threshold(0.5f) == 0 //right side</pre>
<p>It looks like the problem is easily solved by changing the algorithm:</p>
<pre>// C++
Image &amp; threshold(Image ℑ)
{
  forXY(image, x, y)
    image(x, y) = (image(x, y) &lt; 0.5f) ? 0 : 1;

  return image;
}</pre>
<p>But, for floating point numbers on a machine, there is another number 0.5 – epsilon such that the following algorithm is equivalent to the one above:</p>
<pre>// C++
Image &amp; threshold(Image &amp; image)
{
  forXY(image, x, y)
    image(x, y) = (image(x, y) &lt;= 0.5f - epsilon) ? 0 : 1;

  return image;
}</pre>
<p>But for this algorithm our invariant does not hold for a pixel with the value 0.5 – epsilon! Since the last two algorithms are equivalent, it means the modified algorithm is also not correct in this strict sense. In fact, it is not possible to implement an algorithm that is correct in this sense (using floating-point numbers).</p>
<p>But we feel that any of the above implementation <em>is</em> correct, and hence our test is wrong. So how do we change it, and should we?</p>
<p>We can change one (or more) of three things:</p>
<ul>
<li>the test data</li>
<li>the test transform</li>
<li>how we test for equality in images</li>
</ul>
<p>Because of the simplicity and general usefulness of both the transform and the test data, I feel it is best to leave these as is. That means we have to change the measure of equality. Since we use random data, we might want to use the “is probably equal” measure—that is, two images are equal if a certain percentage of pixels are equal (within some threshold). Since the likelihood of generating 0.5 is low, our test should pass. I do not like this idea for two reasons:</p>
<p>First, it is not generally useful. For example, another test might fail when the borders are not equal (a much larger number of pixels), even though we feel that it must not for some specific algorithm. We then need another equality measure to handle that case.</p>
<p>Second, it is bound to hide a class of errors where a small number of pixels are incorrectly processed, and we do not want that.</p>
<p>Instead, we would like some measure that is generally useful, but can be tweaked for the specific algorithm to overcome those cases where we expect the algorithm to fail.</p>
<p>One way to do this is to use equality masks: a simple bit array that says whether we are interested in that pixel or not. In this case, we need the mask to be constructed from the test data; here is how we do it:</p>
<pre>//C++
BitImage &amp; make_ignore_value_mask(
  BitImage &amp; mask,
  Image &amp; image,
  float value)
{
  forXY(image, x, y)
    mask = image(x, y) == 0.5f;
}</pre>
<p>We then change our macro to this:</p>
<pre>#define TEST_TRANSFORM_INVARIANCE (image, mask, transform, command, mask_command) \
  do { \
    Image image; \
    make_test_image(image); \
    \
    Image original_image(image); \
    transform(image); \
    \
    if(image == original_image)
      report_unsuitable_test_image(...); \
    \
    image = original_image; \
    command; \
    \
    Image image1(image); \
    transform(image1); \
    \
    image = original_image; \
    transform(image); \
    command; \
    \
    BitImage mask(image.width, image.height); \
    mask_command; \
    \
    if (mask * image != mask * image1)
      report_useful_failure_message(...); \
  } while(0)</pre>
<p>We call the macro like this:</p>
<p>TEST_TRANSFORM_INVARIANCE (image, mask, inverse, threshold(image), make_ignore_value_mask(mask, image, value));</p>
<p>The functional programming solutions are similarly modified:</p>
<pre>// C++
test_transform_inavriance(
  Image &amp; (* function)(Image &amp;),
  BitImage &amp; (*mask_creation_function) (BitImage &amp; mask, Image &amp; image),
  Image &amp; (* transform)(Image &amp;))
{
  Image image;
  make_test_image(image);

  Image original_image(image);

  if(image == original_image)
      report_unsuitable_test_image(...); 

  image = original_image;
  function(image);

  Image image1(image);
  transform(image1);

  image = original_image;
  transform(image);
  function(image);

  BitImage mask;
  mask_creation_function(mask, image);

  if (mask * image != mask * image1)
    report_useful_failure_message(...);
}</pre>
<p>We need a wrapping function to call our extra argument:</p>
<pre>BitImage &amp; void wrapped_ make_ignore_value_mask(
  BitImage &amp; mask,
  Image &amp; image)
{
  return make_ignore_value_mask(mask, image, 0,5f);
}</pre>
<p>Now we can call our test function like this:</p>
<pre>test_transform_inavriance(image, mask, inverse, threshold,
  wrapped_make_ignore mask(mask, image));</pre>
<p>In languages that support closures such as Python, we can again use the wrapping technique as before:</p>
<pre>test_transform_inavriance(image, mask, inverse, threshold,
  wrap(make_ignore mask(mask, image), 0.5))</pre>
<p>Here are a few suggestions for useful mask types:</p>
<table border="0" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td width="158" valign="top"><code>ignore_none</code></td>
<td width="340" valign="top">A constant array of 1s. Probably the one to be used with most algorithms.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_value</code><br />
<code>ignore_values</code></td>
<td width="340" valign="top">Ignores all the pixels in the test data that equal a given value or list of values.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_range</code></td>
<td width="340" valign="top">Ignores all the pixels in the test data that fall in the given range.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_out_of_range</code></td>
<td width="340" valign="top">Ignores all the pixels in the test data that fall outside a given range.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_rect</code></td>
<td width="340" valign="top">Ignores all the pixels inside a specified rectangle.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_border</code></td>
<td width="340" valign="top">Ignore all pixels in a boarder of specified width.</td>
</tr>
</tbody>
</table>
<p>Be careful for inadvertent ignore_all masks. For example, the ignore_border mask might be all zero when the border is thicker than half the smallest image dimension. It is a good idea to build in a test to check that the mask is not all-zero in the test macro or function.</p>
<p>Also watch out when transforms or algorithms change image dimensions—make sure the mask is constructed correctly.</p>
<p>We have now answered how we can change the test to pass for the thresholding example (and more generally); it remains to answer whether we should. My feeling is: only when you <em>have </em>to. Generally, I test without regard for such subtle issues. When a test fails, I carefully try to understand whether it is because the algorithm is fundamentally wrong, or whether it is just an obscure instance that makes the test fail. In the latter case, I will amend the test with the necessary masks.</p>
<p><b>Update</b>: Here is another example of how an invariance test can fail even when the algorithm is fundamentally correct. Consider a region quadtree compression scheme. Suppose we want to compress a 5&#038;times 5 image, and suppose the algorithm divides the image in four rectangles. Because 5 is odd, the rectangles will differ in size. The biggest rectangle should always be in the same spot, regardless of the reflection; thus the algorithm should fail when testing pixels along the center. We cannot really address this issue with masks. To me it is unclear how to handle this at all (and clearly, we do not want to limit our tests to powers-of-two images only).</p>
<h2>Warning: A False sense of Security</h2>
<p>When you have a large group of transforms to construct invariance checks from, you can easily test for a whole bunch of errors with just a few lines of code. If the tests pass, it is easy to think that the algorithm is correct. It may not be:</p>
<ul>
<li>Perhaps the test image is unsuitable. This may be by coincidence if the test image is random.</li>
<li>Any particular test does not catch all errors of a certain type.</li>
<li>All transforms do not cover the entire set of possible errors.</li>
</ul>
<p>A set of invariance tests does in general not prove the <em>correctness</em> of a particular algorithm. It merely exposes <em>certain kinds of errors</em>. Therefore, additional tests for correctness are necessary.</p>
<h2>Invariance Test Checklist / Summary</h2>
<p>The basic structure of the test macro / function is as follows:</p>
<ol>
<li>Create test data.</li>
<li>Calculate transform(algorithm(test_image)).</li>
<li>Calculate algorithm(transform(test_image)).</li>
<li>Compare these results and report any failures.</li>
</ol>
<p>Remember:</p>
<ul>
<li>Check that the test data is changed by the transform.</li>
<li>Use masks to cater for peripheral special cases where certain pixels, values, or regions in an image should be ignored for comparisons.</li>
<li>Check that your masks are not all zero (sanity check).</li>
<li>Report useful information when a test fails:
<ul>
<li>what kind of failure (dimension mismatch, channel mismatch, value mismatch);</li>
<li>in the case of value mismatch, the number of pixels that are mismatched and the values of the first pixels from each image that fail to match.</li>
</ul>
</li>
</ul>
<h2>More on Unit Testing for Image Processing</h2>
<ul>
<li><a href="http://blogs.mathworks.com/steve/2009/02/03/mtest-a-unit-test-harness-for-matlab-code/">MTEST &#8211; A unit test harness for MATLAB code</a></li>
<li><a href="http://aras-p.info/blog/2007/07/31/testing-graphics-code/">Testing Graphics Code</a></li>
</ul>
<h2>How do <em>You </em>Test Your Image Algorithms?</h2>
<p>Let me know in the comments <img src='http://code-spot.co.za/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/05/12/catching-common-image-processing-programming-errors-with-generic-unit-tests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple, Fast* Approximate Minimum / Maximum Filters</title>
		<link>http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/</link>
		<comments>http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 14:13:05 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[dilation]]></category>
		<category><![CDATA[erosion]]></category>
		<category><![CDATA[filtering]]></category>
		<category><![CDATA[maximum filter]]></category>
		<category><![CDATA[minimum filter]]></category>
		<category><![CDATA[morphology]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=881</guid>
		<description><![CDATA[*Fast = not toooo slow… For the image restoration tool I had to implement min and max filters (also erosion and dilation—in this case with a square structuring element). Implementing these efficiently is not so easy. The naive approach is to simply check all the pixels in the window, and select the maximum or minimum value. This [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/' rel='bookmark' title='Permanent Link: 2D Minimum and Maximum Filters: Algorithms and Implementation Issues'>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</a></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Permanent Link: Region Quadtrees in C++'>Region Quadtrees in C++</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline; border: 0px initial initial;" title="minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/minmax.png" border="0" alt="minmax" width="491" height="321" /></p>
<p><em>*Fast = not toooo slow…</em></p>
<p>For the <a href="http://code-spot.co.za/2010/04/15/experimental-tool-for-removing-unwanted-artefacts-in-textures/">image restoration tool</a> I had to implement <a href="http://livedocs.adobe.com/en_US/Photoshop/10.0/help.html?content=WSfd1234e1c4b69f30ea53e41001031ab64-795d.html">min and max filters</a> (also <a href="http://homepages.inf.ed.ac.uk/rbf/HIPR2/erode.htm">erosion</a> and <a href="http://homepages.inf.ed.ac.uk/rbf/HIPR2/dilate.htm">dilation</a>—in this case with a square <a href="http://en.wikipedia.org/wiki/Structuring_element">structuring element</a>). Implementing these efficiently is not so easy. The naive approach is to simply check all the pixels in the window, and select the maximum or minimum value. This algorithm&#8217;s run time is quadratic in the window width, which can be a bit slow for the bigger windows that I am interested in. There are some very efficient algorithms available, but they are quite complicated to implement properly (some require esoteric data structures, for example <a href="http://www.archipel.uqam.ca/309/1/webmaximinalgo.pdf">monotonic wedges</a> (PDF)), and many are not suitable for floating point images.</p>
<p>So I came up with this approximation scheme. It uses some expensive floating point operations, but its run time is <em>constant</em> in the window width.</p>
<p><span id="more-881"></span></p>
<p>The crux of the algorithm is the following approximation, which works well for <img src='http://s.wordpress.com/latex.php?latex=0%20%3C%20x_i%20%3C%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='0 &lt; x_i &lt; 1' title='0 &lt; x_i &lt; 1' class='latex' />, <img src='http://s.wordpress.com/latex.php?latex=p%20%5Cgg%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \gg 1' title='p \gg 1' class='latex' />.</p>
<img src='http://s.wordpress.com/latex.php?latex=%20%5Cmax_%7Bi%3D1%7D%5ENx_i%5Capprox%20%28%5Cfrac%7B1%7D%7BN%7D%5Csum_%7Bi%3D1%7D%5ENx_i%5Ep%29%5E%7B1%2Fp%7D%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' \max_{i=1}^Nx_i\approx (\frac{1}{N}\sum_{i=1}^Nx_i^p)^{1/p} ' title=' \max_{i=1}^Nx_i\approx (\frac{1}{N}\sum_{i=1}^Nx_i^p)^{1/p} ' class='latex' />
<p>I am not going into the mathematical details of why this a fair approximation.</p>
<p>To turn this into a max filter is straightforward:</p>
<h3>1. Calculate the power image</h3>
<p>Raise each pixel to the power <em>p</em>.</p>
<img src='http://s.wordpress.com/latex.php?latex=P%28x%2C%20y%29%20%3D%20%5BI%28x%2C%20y%29%5D%5Ep&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='P(x, y) = [I(x, y)]^p' title='P(x, y) = [I(x, y)]^p' class='latex' />
<h3>2. Calculate a summed area table</h3>
<p>The <a href="http://en.wikipedia.org/wiki/Summed_area_table">summed area table</a> (or integral) of an image is a table containing in each cell (x, y), the sum of all the pixels top and left of (x, y); for the power image <img src='http://s.wordpress.com/latex.php?latex=P%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='P ' title='P ' class='latex' /> it is given by:</p>
<img src='http://s.wordpress.com/latex.php?latex=S%28x%2Cy%29%20%3D%20%5Csum_%7Bu%3D0%7D%5E%7Bx%7D%5Csum_%7Bv%3D0%7D%5E%7By%7DP%28u%2Cv%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='S(x,y) = \sum_{u=0}^{x}\sum_{v=0}^{y}P(u,v)' title='S(x,y) = \sum_{u=0}^{x}\sum_{v=0}^{y}P(u,v)' class='latex' />
<p><strong>Update:</strong> This can be efficiently be calculated using the following recurrence:</p>
<img src='http://s.wordpress.com/latex.php?latex=S%28x%2C%20y%29%20%3D%20S%28x%2C%20y%20-%201%29%20%2B%20S%28x%20-%201%2C%20y%29%20-%20S%28x%2C%20y%29%20%2B%20P%28x%2C%20y%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='S(x, y) = S(x, y - 1) + S(x - 1, y) - S(x, y) + P(x, y)' title='S(x, y) = S(x, y - 1) + S(x - 1, y) - S(x, y) + P(x, y)' class='latex' />
<p>and <img src='http://s.wordpress.com/latex.php?latex=S%28x%2C%20y%29%20%3D%200%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='S(x, y) = 0 ' title='S(x, y) = 0 ' class='latex' /> if <img src='http://s.wordpress.com/latex.php?latex=x%20%3C%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x &lt; 0' title='x &lt; 0' class='latex' /> or <img src='http://s.wordpress.com/latex.php?latex=y%20%3C%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='y &lt; 0' title='y &lt; 0' class='latex' />.</p>
<h3>3. Calculate the window mean</h3>
<p>Use the cumulative image sum to calculate the mean in the window. Here, <img src='http://s.wordpress.com/latex.php?latex=r&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='r' title='r' class='latex' /> is the window radius, <em>A</em> stands for average:</p>
<img src='http://s.wordpress.com/latex.php?latex=A%28x%2C%20y%29%20%3D%20%5Cfrac%7B1%7D%7B%282r%20%2B%201%29%5E2%7D%5BS%28x-r-1%2C%20y-r-1%29%20%2B%20S%28x%20%2B%20r%2C%20y%20%2B%20r%29-S%28x-r-1%2C%20y%20%2B%20r%29-S%28x%20%2B%20r%2C%20y-r-1%29%5D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='A(x, y) = \frac{1}{(2r + 1)^2}[S(x-r-1, y-r-1) + S(x + r, y + r)-S(x-r-1, y + r)-S(x + r, y-r-1)]' title='A(x, y) = \frac{1}{(2r + 1)^2}[S(x-r-1, y-r-1) + S(x + r, y + r)-S(x-r-1, y + r)-S(x + r, y-r-1)]' class='latex' />
<h3>4. Calculate the approximate maximum</h3>
<img src='http://s.wordpress.com/latex.php?latex=M%28x%2C%20y%29%20%3D%20%5BA%28x%2C%20y%29%5D%5E%7B1%2Fp%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M(x, y) = [A(x, y)]^{1/p}' title='M(x, y) = [A(x, y)]^{1/p}' class='latex' />
<p>That’s it!</p>
<p>The minimum filter is implemented by finding the maximum of the inverse image and then inverting the result. This approach uses two more passes through the image; so far I could not find a direct approximation for the minimum value. (<strong>Update:</strong> It seems using <img src='http://s.wordpress.com/latex.php?latex=p%5Cll%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p\ll 0' title='p\ll 0' class='latex' /> gives an approximation for finding the minimum of a set of values.)</p>
<h2>Notes</h2>
<ul>
<li>For very large images, you might run into floating point issues when calculating the cumulative sum image. You can reduce this effect somewhat by subtracting the (total image) mean of the power image from each pixel before calculating the image sum.</li>
<li>For the image sizes I worked on, the value <img src='http://s.wordpress.com/latex.php?latex=p%3D8&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p=8' title='p=8' class='latex' /> was suitable. The higher <img src='http://s.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' />, the more accurate results, as long as you have no underflow.</li>
<li>Raising powers is a slow operation. By choosing a suitable value of <img src='http://s.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' />, you can use a suitable, faster approximation for calculating the power.</li>
<li><strong>Update:</strong> It is possible to implement this as a two-pass algorithm, first working on columns, then on rows. This requires constructing two tables, which makes the algorithm slower. However, using this approach allows bigger images to be processed before overflow in the summed are tables becomes a problem.</li>
</ul>
<p>Initially I thought that once the maximum can be found, we can also find the second maximum, and so on, so that any statistical order filter can be constructed.</p>
<p>The basic idea was that if <img src='http://s.wordpress.com/latex.php?latex=m_1&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='m_1' title='m_1' class='latex' /> is the maximum, we could find the second largest value like this:</p>
<img src='http://s.wordpress.com/latex.php?latex=m_2%20%5Capprox%20%5Cfrac%7B1%7D%7BN-1%7D%5B%28%5Csum_%7Bi%3D1%7D%5EN%20x_i%5Ep%29%20-%20m_1%5Ep%5D%29%5E%7B1%2Fp%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='m_2 \approx \frac{1}{N-1}[(\sum_{i=1}^N x_i^p) - m_1^p])^{1/p}' title='m_2 \approx \frac{1}{N-1}[(\sum_{i=1}^N x_i^p) - m_1^p])^{1/p}' class='latex' />
<p>The idea is that we remove the maximum value from the sum, so that the result must yield the second largest element. Of course, we do not use the actual maximum, but the approximation—and this is where the formula fails. When we use the approximate maximum, it is easy to show that the formula above will yield the exact same approximate maximum, and not the <em>second</em> largest element.</p>
<p>I should have know it seemed too good to be true!</p>
<p><strong>Update:</strong> while looking for links for this post, I found this article: <a href="http://www.ph.tn.tudelft.nl/People/albert/papers/ICPR17VlietV13_5_13.pdf" class="broken_link">Robust Local Max-Min Filters by Normalized Power-Weighted Filtering</a> (PDF) which initially looked like it was essentially the same thing. Although it is very similar, it is in fact different. The approximate maximum is given by the value:</p>
<img src='http://s.wordpress.com/latex.php?latex=%20%5Cmax_%7Bi%3D1%7D%5ENx_i%5Capprox%20%5Cfrac%7B%5Csum_%7Bi%3D1%7D%5ENx_i%5E%7Bp%20%2B%201%7D%7D%7B%5Csum_%7Bi%3D1%7D%5ENx_i%5Ep%7D%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' \max_{i=1}^Nx_i\approx \frac{\sum_{i=1}^Nx_i^{p + 1}}{\sum_{i=1}^Nx_i^p} ' title=' \max_{i=1}^Nx_i\approx \frac{\sum_{i=1}^Nx_i^{p + 1}}{\sum_{i=1}^Nx_i^p} ' class='latex' />
<p>for <img src='http://s.wordpress.com/latex.php?latex=p%20%5Cgg%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \gg 0' title='p \gg 0' class='latex' />.</p>
<p>Using <img src='http://s.wordpress.com/latex.php?latex=p%20%5Cll%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \ll 0' title='p \ll 0' class='latex' /> gives an approximation to the minimum.</p>
<p>The nice thing about this approximation is that it seems to work well for all real <img src='http://s.wordpress.com/latex.php?latex=x_i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x_i' title='x_i' class='latex' />, not just for <img src='http://s.wordpress.com/latex.php?latex=0%20%5Cleq%20x_i%20%5Cleq%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='0 \leq x_i \leq 1' title='0 \leq x_i \leq 1' class='latex' />.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/' rel='bookmark' title='Permanent Link: 2D Minimum and Maximum Filters: Algorithms and Implementation Issues'>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</a></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Permanent Link: Region Quadtrees in C++'>Region Quadtrees in C++</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Poisson Disk Sampling Example Code</title>
		<link>http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/</link>
		<comments>http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 08:57:27 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[poisson disk]]></category>
		<category><![CDATA[procedural texture]]></category>
		<category><![CDATA[sampling]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=806</guid>
		<description><![CDATA[I decided to put the Poisson disk sampling code here for download since the site that hosted it is down. The code accompanies the tutorial on Dev.Mag: Poisson Disk Sampling. Download poisson_disk_java.zip (184 KB) poisson_disk_python.zip (912 KB) poisson_disk_ruby.zip (59 KB) Related posts:Python Image Code A simple texture algorithm – faster code and more results A [...]


Related posts:<ol><li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Permanent Link: Python Image Code'>Python Image Code</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
<li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-817" title="poisson" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/poisson3.png" alt="poisson" width="142" height="142" />I decided to put the Poisson disk sampling code here for download since the site that hosted it is down. The code accompanies the tutorial on Dev.Mag: <a href="http://www.devmag.org.za/articles/55-POISSON-DISK-SAMPLING/">Poisson Disk Sampling</a>.</p>
<h2>Download</h2>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.code-spot.co.za/downloads/poisson/poisson_disk_java.zip">poisson_disk_java.zip</a> (184 KB)<br />
<a href="http://www.code-spot.co.za/downloads/poisson/poisson_disk_python.zip"> poisson_disk_python.zip</a> (912 KB)<br />
<a href="http://www.code-spot.co.za/downloads/poisson/poisson_disk_ruby.zip"> poisson_disk_ruby.zip</a> (59 KB)</td>
</tr>
</tbody>
</table>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Permanent Link: Python Image Code'>Python Image Code</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
<li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>15 Steps to Implement a Neural Net</title>
		<link>http://code-spot.co.za/2009/10/08/15-steps-to-implemented-a-neural-net/</link>
		<comments>http://code-spot.co.za/2009/10/08/15-steps-to-implemented-a-neural-net/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 15:02:26 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[artificial intelligence]]></category>
		<category><![CDATA[Matlab]]></category>
		<category><![CDATA[neural network]]></category>
		<category><![CDATA[Octave]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[pattern recognition]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[sampling]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=655</guid>
		<description><![CDATA[(Original image by Hljod.Huskona / CC BY-SA 2.0). I used to hate neural nets. Mostly, I realise now, because I struggled to implement them correctly. Texts explaining the working of neural nets focus heavily on the mathematical mechanics, and this is good for theoretical understanding and correct usage. However, this approach is terrible for the poor implementer, [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/' rel='bookmark' title='Permanent Link: Generating Random Numbers with Arbitrary Distributions'>Generating Random Numbers with Arbitrary Distributions</a></li>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='Permanent Link: 5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="neuron" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/neuron1.jpg" border="0" alt="neuron" width="500" height="332" /></p>
<p>(<a href="http://www.flickr.com/photos/lorelei-ranveig/2294885420/">Original image</a> by <a rel="cc:attributionURL" href="http://www.flickr.com/photos/lorelei-ranveig/">Hljod.Huskona</a> / <a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA 2.0</a>).</p>
<p>I used to hate neural nets. Mostly, I realise now, because I struggled to implement them correctly. Texts explaining the working of neural nets focus heavily on the mathematical mechanics, and this is good for theoretical understanding and correct usage. However, this approach is terrible for the poor implementer, neglecting many of the details that concern him or her.</p>
<p>This tutorial is an implementation guide. It is not an explanation of how or why neural nets work, or when they should or should not be used. This tutorial will tell you step by step how to implement a very basic neural network. It comes with a simple example problem, and I include several results that you can compare with those that you find.</p>
<p><span id="more-655"></span></p>
<p>I tried to make the design as straightforward as possible. The training algorithm is simple backpropagation. There are no hidden layers (I will treat that in an upcoming tutorial), no momentum, no adaptive learning rates, and no sophisticated stopping conditions. Those are, in a sense, easy to add once you have a working neural net against which you can benchmark more elaborate designs.</p>
<p>To keep the implementation simple, I did not bother with optimisation. This too can easily be addressed once a working neural net is in place against which you can verify correctness and measure performance improvements.</p>
<p>The brief introduction below is a very superficial explanation of a neural net; it is included mostly to establish terminology and help you map it to the concepts that are explained in more detail in other texts.</p>
<h2>Preliminary remarks and overview</h2>
<h3>What we are doing</h3>
<p>The problem we are trying to solve is this: we have some measurements (features of an object), and we have a good idea that these features might tell us in which class the object belongs. For example, if we are dealing with fruit, knowing the size, colour, and “roughness” of the skin, we might deduce which type the fruit is. Of course, we want a <em>program </em>for this.</p>
<p>Now in heaven, there is a function for exactly that task – we give the function the features, and it spits out the class.</p>
<p>Down here on earth, we are not so lucky (well, not for most problems anyway). So instead, we have to do with some approximation. A neural net is one possibility – there are also others. A neural net (one without any hidden layers) is parameterised by a weight matrix. Different problems in general have different weight matrices. To solve our problem, we need to find a suitable matrix.</p>
<p>If both our set of known samples and the problem itself are reasonable, we might expect to find such a matrix. But not directly – we have to use some kind of iterative scheme – we have to “train” our neural net. We use some of the known samples for this.</p>
<p>Behind the scenes, the weight matrix and the feature vector are combined using some matrix operations to give the output vector, which is converted to a class. The mathematical details of this can be found <a href="http://www.mth.kcl.ac.uk/courses/guide.pdf" class="broken_link">elsewhere</a> (<a href="http://www.learnartificialneuralnetworks.com/backpropagation.html">more</a>).</p>
<p>After we have trained the neural net, we can use it in an application to classify objects that we may or may not have encountered before. Generally, the training and application programs are separate. The training program is the difficult part; most of the tutorial deals with training.</p>
<p>It is common to divide the known samples in three sets, called the training set, validation set, and test set, typically divided in the ratio 50%, 25%, and 25%. The training set is used to update the weights iteratively; the validation set is used to stop the training algorithm, and the test set is used to estimate how well our trained neural net will do in the wild.</p>
<p>Each iteration of the training algorithm is called, quite poetically, an <em>epoch</em>. Many different things affect the number of epochs we will need to train the neural net: the problem complexity, how we scale our updates, and how the weight matrix has been initialised.</p>
<p>We can control the speed with a parameter called the learning rate. In general, higher learning rate means faster learning (although, when it is set too high, the network might become unstable and not learn at all).</p>
<h3>Representation</h3>
<p>We usually represent the features (our measurements) as a vector of numbers, like this:</p>
<p>[0.01, 1.07, 3.60]</p>
<p>In cases of non-numeric values, we convert whatever we have to numbers with some scheme. For instance, when dealing with colours, we might want to use RGB values, or we might want to make a list of colours (red, yellow, green, etc.), assign a number to each of these labels, and use the corresponding number.</p>
<p>Classes, usually not being numbers, are similarly treated: we assign a number (often arbitrarily) to each class, and use that in our computations. For the actual training, however, we use an output vector. The output vector has a 1 in the position of the class number, and 0 everywhere else.</p>
<p>Thus, if we are dealing with three classes of fruit (apple, pear, banana), and number the classes 1, 2, and 3 respectively, we will have the following output vectors:</p>
<table border="0" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td width="135" valign="top"><strong>Class</strong></td>
<td width="142" valign="top"><strong>Class Number</strong></td>
<td width="121" valign="top"><strong>Output Vector</strong></td>
</tr>
<tr>
<td width="135" valign="top">Apple</td>
<td width="142" valign="top">1</td>
<td width="121" valign="top">1 0 0</td>
</tr>
<tr>
<td width="135" valign="top">Pear</td>
<td width="142" valign="top">2</td>
<td width="121" valign="top">0 1 0</td>
</tr>
<tr>
<td width="135" valign="top">Banana</td>
<td width="155" valign="top">3</td>
<td width="153" valign="top">0 0 1</td>
</tr>
</tbody>
</table>
<p>It is convenient to put all the inputs of a set together in a single matrix, where each row is a sample. Similarly, outputs and classes are also put into matrices, with input sample in a row (say row number <em>n</em>) corresponds to output sample in row <em>n</em>, and also the class in row <em>n</em>.</p>
<p>The implementation below makes use of high-level matrix operations. This avoids many of the errors that can creep in loop-dense code. The following table will give dimensions of all the matrixes involved; this will be helpful during implementation (especially for assert statements). The numbers are given in terms of the number of inputs (features) of the problem, the number of outputs.</p>
<table border="0" cellspacing="0" cellpadding="2" width="490">
<tbody>
<tr>
<td width="263" valign="top"><strong>Matrix</strong></td>
<td width="113" valign="top"><strong>Rows</strong></td>
<td width="112" valign="top"><strong>Columns</strong></td>
</tr>
<tr>
<td width="256" valign="top">input vector of a single sample</td>
<td width="117" valign="top">1</td>
<td width="115" valign="top">input_count</td>
</tr>
<tr>
<td width="251" valign="top">output vector of a single sample</td>
<td width="120" valign="top">1</td>
<td width="117" valign="top">output_count</td>
</tr>
<tr>
<td width="248" valign="top">class vector of a single sample</td>
<td width="122" valign="top">1</td>
<td width="119" valign="top">1</td>
</tr>
<tr>
<td width="245" valign="top">input matrix of training set</td>
<td width="124" valign="top">training_count</td>
<td width="120" valign="top">input_count</td>
</tr>
<tr>
<td width="243" valign="top">output matrix of training set</td>
<td width="125" valign="top">training_count</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">class vector of training set</td>
<td width="126" valign="top">training_count</td>
<td width="121" valign="top">1</td>
</tr>
<tr>
<td width="242" valign="top">bias vector of training set</td>
<td width="126" valign="top">training_count</td>
<td width="121" valign="top">1</td>
</tr>
<tr>
<td width="242" valign="top">net vector of single sample</td>
<td width="126" valign="top">1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">weights matrix</td>
<td width="126" valign="top">input_count + 1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">weights delta matrix</td>
<td width="126" valign="top">input_count + 1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">error vector</td>
<td width="126" valign="top">1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">delta (sensitivity vector)</td>
<td width="126" valign="top">1</td>
<td width="121" valign="top">output_count</td>
</tr>
</tbody>
</table>
<h3>Overview</h3>
<p>The basic idea of the training algorithm is the following:</p>
<p>First we load in the data: the training samples, the validation samples, and the test samples.</p>
<p>Then we start to train: we run the backpropagation algorithm on random samples. After each iteration, we see how our network is doing so far (on the validation set), and then we decide whether to keep training or not.</p>
<p>After we stopped, we do a final evaluation of our network on the test set – this gives us an indication of whether the neural net will generalise well to samples not originally in the training set.</p>
<p>After we have found a weight matrix that we can live with, we cfan incorporate this in the application were we need the functionality.</p>
<p>The training program has x functions:</p>
<ul>
<li>train</li>
<li>load data</li>
<li>feed-forward</li>
<li>evaluate network</li>
<li>backpropagation</li>
<li>output to class</li>
<li>class to output</li>
<li>activation</li>
<li>activation derivative</li>
</ul>
<p>The application program uses these functions:</p>
<ul>
<li>feed-forward</li>
<li>output vector to class</li>
</ul>
<h2>Implementation</h2>
<h3>1. Gather the necessary libraries (or write them)</h3>
<p>You will need the following libraries:</p>
<ul>
<li>A library that supports matrix algebra; and</li>
<li>A library that plots graphs (x versus y).</li>
</ul>
<p>If you can’t find a matrix library for your implementation language, then you can write a simple library yourself. Since neural nets do not require matrix inverses or long chains of matrix products, you need not worry (much) about numerical stability, thus the implementation is straightforward.</p>
<p>The implementation needs to support the following matrix operations:</p>
<ul>
<li>matrix transposition;</li>
<li>matrix addition;</li>
<li>matrix multiplication with a scalar;</li>
<li>ordinary matrix multiplication;</li>
<li>Hadamard multiplication (component-wise multiplication);</li>
<li>Kronecker multiplication (only necessary for between row and column vectors); and</li>
<li>horizontal matrix concatenation.</li>
</ul>
<p>The first few operations are standard matrix operations, but you might be less familiar with the last three. (Also check out the Wikipedia article on <a href="http://en.wikipedia.org/wiki/Matrix_multiplication">matrix multiplication</a> – it covers all the types of multiplication mentioned here.)</p>
<p>Hadamard multiplication of matrices is defined for two matrices of equal dimensions. Each component of the new matrix is the product of corresponding components in the two multiplicands, that is:</p>
<pre>Z[i][j] = X[i][j] * Y[i][j]</pre>
<p>The Kronecker product of a row vector and column vector is defined as a matrix whose components are given by:</p>
<pre>Z[i][j] = X[0][i] * Y[j][0]</pre>
<p>It is possible to define the product for arbitrary matrices, but we don’t need it.</p>
<p>The horizontal concatenation combines two matrices with the same number of rows. For example, the matrices A and B below will be concatenated to form the new matrix C:<br />
<img src='http://s.wordpress.com/latex.php?latex=A%3D%5Cbegin%7Bpmatrix%7D10%20%26%203%5C%5C4%20%26%205%5Cend%7Bpmatrix%7D%2C%5C%3AB%3D%5Cbegin%7Bpmatrix%7D6%20%26%208%20%26%202%5C%5C3%261%2610%5Cend%7Bpmatrix%7D%2C%5C%3AC%3D%5Cbegin%7Bpmatrix%7D10%20%26%203%266%20%26%208%20%26%202%5C%5C4%20%26%205%26%203%20%261%2610%5Cend%7Bpmatrix%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='A=\begin{pmatrix}10 &amp; 3\\4 &amp; 5\end{pmatrix},\:B=\begin{pmatrix}6 &amp; 8 &amp; 2\\3&amp;1&amp;10\end{pmatrix},\:C=\begin{pmatrix}10 &amp; 3&amp;6 &amp; 8 &amp; 2\\4 &amp; 5&amp; 3 &amp;1&amp;10\end{pmatrix}' title='A=\begin{pmatrix}10 &amp; 3\\4 &amp; 5\end{pmatrix},\:B=\begin{pmatrix}6 &amp; 8 &amp; 2\\3&amp;1&amp;10\end{pmatrix},\:C=\begin{pmatrix}10 &amp; 3&amp;6 &amp; 8 &amp; 2\\4 &amp; 5&amp; 3 &amp;1&amp;10\end{pmatrix}' class='latex' /></p>
<p>A simple implementation simply constructs a new matrix whose components are given by</p>
<pre>if j &lt; X_width
  Z[i][j] = X[i][j]
else
   Z[i][j] = Y[i, j – X_width]</pre>
<p>If no graph libraries are available, simply write a function that will output a tab-separated list of the input and output sequences to plot. You can then load or paste this into your favourite spreadsheet program to make the necessary plots.</p>
<h3>2. Implement Output and Class conversion functions</h3>
<p>This is very simple: implement a function that converts an output matrix to a class number vector, and another that converts a class number to an output vector.</p>
<p>For example, the output_to_class function will take the following matrix</p>
<p>1 0 0</p>
<p>0 1 0</p>
<p>0 0 1</p>
<p>1 0 0</p>
<p>0 0 1</p>
<p>and convert it to:</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>1</p>
<p>3</p>
<p>(The second function will convert the second matrix back to the first matrix).</p>
<h3>3. Implement a function to read in data files</h3>
<p>For this tutorial you can use the following three files:</p>
<ul>
<li>iris_training.dat</li>
<li>iris_validation.dat</li>
<li>iris_test.dat</li>
</ul>
<p>These three files contain samples from the <a href="http://en.wikipedia.org/wiki/Iris_flower_data_set">ICU iris dataset</a>, a simple and quite famous dataset. In each file, samples or contained in rows. Each row has seven entries, separated by tabs. The first four entries are features of irises (sepal length, sepal width, petal length, and petal width); the last three is the outputs denoting the species of iris (setosa, versicolor, and virginica). I have preprocessed the values a bit to get them in the appropriate ranges.</p>
<p>You must read in the data so that you can treat the inputs of each set as a single matrix; similarly for the outputs.</p>
<p>I find it useful to store all the data in a structure, like this:</p>
<ul>
<li>data_set
<ul>
<li>input_count</li>
<li>output_count</li>
<li>training_set
<ul>
<li>inputs</li>
<li>outputs</li>
<li>classes</li>
<li>count</li>
<li>bias</li>
</ul>
</li>
<li>validation_set
<ul>
<li>inputs</li>
<li>outputs</li>
<li>classes</li>
<li>count</li>
<li>bias</li>
</ul>
</li>
<li>test_set
<ul>
<li>inputs</li>
<li>outputs</li>
<li>classes</li>
<li>count</li>
<li>bias</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>This makes it more useful to send the data as parameters.</p>
<h3>4. Implement an activation function and its derivative</h3>
<p>The activation function must take in a matrix X, and return a matrix Y. Y is computed by applying a function component-wise to X. For now, use the hyperbolic tangent function:</p>
<img src='http://s.wordpress.com/latex.php?latex=%20f%28x%29%20%3D%20%5Cdfrac%7B%5Ctanh%28x%29%20%2B%201%7D%7B2%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' f(x) = \dfrac{\tanh(x) + 1}{2}' title=' f(x) = \dfrac{\tanh(x) + 1}{2}' class='latex' /><br />
The activation function derivative must similarly take in a matrix X, and return a matrix Y. Y is computed by applying the derivative of the activation componentwise to X. The derivative of the function above is:<br />
<img src='http://s.wordpress.com/latex.php?latex=f%27%28x%29%20%3D%20%5Cdfrac%7B1%20-%20%5Ctanh%5E2%28x%29%7D%7B2%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f&#039;(x) = \dfrac{1 - \tanh^2(x)}{2}' title='f&#039;(x) = \dfrac{1 - \tanh^2(x)}{2}' class='latex' />
<h3>5. Implement the feed-forward function</h3>
<p>The function must take as arguments an input matrix, weight matrix, and a bias node matrix.</p>
<p>The function should return an output matrix, and a net matrix</p>
<p>These are computed as follows:</p>
<pre>net = mul(weights, horcat(inputs, bias))
output = activate(net)</pre>
<p>The bias matrix is a constant column vector of 1s with as many rows as the input matrix. This vector corresponds to the bias nodes. The implementation here is a bit clumsy, but for now, the approach used here minimises the potential for error.</p>
<h3>6. Implement a weight initialisation function</h3>
<p>This function must take in a maximum weight, a width and height, and return a matrix of the given width and height, randomly initialised in the range [-max_weight max_weight].</p>
<h3>7. Implement a function that evaluates the network error.</h3>
<p>The function must take in:</p>
<ul>
<li>an input matrix,</li>
<li>a weight matrix,</li>
<li>a target output matrix,</li>
<li>a target class matrix,</li>
<li>a bias matrix.</li>
</ul>
<p>The function must return the error e, and the classification error c.</p>
<p>To compute these, first compute the output matrix Z using the feed-forward function (you can ignore the net matrix).</p>
<pre>[output net] = feedforward(inputs, weights, bias)</pre>
<p>Now subtract the target output matrix from the output matrix, square the components, add together, and normalise:</p>
<pre>error = sum_all_components((target_outputs – outputs)^2) ...</pre>
<pre>   / (sample_count * output_count)</pre>
<p>From the output matrix, calculate the classes:</p>
<pre>classes = classes_from_output_vectors(outputs)</pre>
<p>Count the number of classes that corresponds with the target classes, and divide by the number of samples to normalise:</p>
<pre>c = sum_all_components(classes != target_classes)/sample_count</pre>
<p>(Here, our inequality returns a matrix of 0s and 1s, with 1s in positions where the corresponding components in classes and target_classes are not equal.)</p>
<h3>8. Implement a dummy backpropagation function</h3>
<p>The function should take in:</p>
<ul>
<li>An input matrix</li>
<li>A weight matrix</li>
<li>a learning rate (eta, as in the Greek letter)</li>
<li>a bias vector</li>
</ul>
<p>The function must return an updated weight matrix. For now, return W as is.</p>
<h3>9. Implement the train function</h3>
<p>The training function should take in three sets, the training_set, validation_set, and test_set. Implement a way to limit the maximum number of samples that will actually be used for training (you can also do his in the main program described in the next section). This is very helpful for debugging purposes (especially if you plan to later replace the backpropagation algorithm with something a little faster – and more complicated).</p>
<p>The function should return a weight matrix, and error values as floats.</p>
<p>Initialise a value plot_graphs to true. This is a debug flag, so it is appropriate to implement this as a macro if it is supported by the implementation language.</p>
<p>The function should initialise a weight matrix using initialise weights. For now, use a max_weight of 1/2.</p>
<p>The function should also construct three bias vectors bias_training, bias_validate, and bias_test. Each must contain only 1s, with as many rows as there are inputs in the training, validation and test sets respectively.</p>
<p>Implement a while loop that stops after 500 iterations. (We will change the while condition later to something else, so do not use a for loop).</p>
<p>Inside the loop, call the backpropagation algorithm. Use the training set inputs, the weights, (for now) a fixed learning rate of 0.1, and bias vector bias_train. Assign the result to weights.</p>
<p>Still inside the loop, call the network error function three times: one time for each of the training, validation, and test sets. Use the weight matrix, and the appropriate bias vector. Wrap these calls in an if-statement that tests for a value plot_graphs. (If your language supports it, you can use conditional compilation on the value of plot_graphs).</p>
<p>Store the errors in six arrays (error_train, classification_error_train, etc.), with the current epoch number as index.</p>
<p>After the loop, plot the six error arrays as a function of epoch number. Wrap this in an if-statement (or conditional compilation statement) that tests for the value plot_graphs.</p>
<p>Call the network error function again, on all three sets as before.</p>
<p>Return the weights, and the six errors.</p>
<h3>10. Implement the main training program</h3>
<p>The program should load in the sets (using the load_sets function), and pass these to the training algorithm.</p>
<h3>11. Run the program</h3>
<p>The important thing is that everything should run. You should see your error plots; at this stage they should be straight, horizontal lines. Because of the random weight initialisation, we cannot predict where these lines will lie (so do not be alarmed if they do not look exactly the same as below – as long as they are straight and horizontal).</p>
<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="backprop" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/backprop.png" border="0" alt="backprop" width="486" height="399" /></p>
<h3>12. Implement the backpropagation function</h3>
<p>You have already created the dummy function; now you can put in the actual calculations.</p>
<p>First, select a random sample.</p>
<p>Now, calculate the net matrix and output matrix using the feed-forward function.</p>
<pre>[output, net] = feedforward(random_sample, weights, bias)</pre>
<p>Calculate the error vector</p>
<pre>error_vector = target_outputs - outputs</pre>
<p>Calculate the sensitivity.</p>
<pre>delta = hammard(error_vector, activation_diff(net))</pre>
<p>The corresponding mathematical expression in the textbook might look like this:<br />
<img src='http://s.wordpress.com/latex.php?latex=%5Cdelta_k%20%3D%20%28t_k%20-%20z_k%29%20f%27%28y_k%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\delta_k = (t_k - z_k) f&#039;(y_k)' title='\delta_k = (t_k - z_k) f&#039;(y_k)' class='latex' /></p>
<p>Calculate the weights delta:</p>
<pre>weights_delta = scalar_mul(eta, kronecker(transpose(outputs), delta))</pre>
<p>The corresponding mathematical expression in the textbook might look like this:<br />
<img src='http://s.wordpress.com/latex.php?latex=w_%7Bkj%7D%20%3D%20%5Ceta%20%28t_k%20-%20z_k%29%20f%27%28y_k%29y_j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='w_{kj} = \eta (t_k - z_k) f&#039;(y_k)y_j' title='w_{kj} = \eta (t_k - z_k) f&#039;(y_k)y_j' class='latex' /></p>
<p>Update the weights:</p>
<pre>weights = add(weights, weights_delta)</pre>
<p>and return the matrix.</p>
<h3>13 Run the program (AGAIN)</h3>
<p>First, set the debug option to train on only one sample. The curve should like like this:</p>
<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="backprop3" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/backprop3.png" border="0" alt="backprop3" width="486" height="398" /></p>
<p>Notice that the error curves are smooth, the training error rate goes to 0, and the other error rates go to 0.4, plus or minus – this depends on the initial weights. It will also be different if you use a sample other than the first.</p>
<p>If your curve looks right, change the debug option to train on all samples. Your error curves should now look something like this:</p>
<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="backprop2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/backprop2.png" border="0" alt="backprop2" width="486" height="398" /></p>
<p>The important feature of the error curves is that they should steadily descent on average. If your curve does not resemble the one shown here; there is a mistake in your implementation. It is often helpful to limit the training set to a single sample (thereby eliminating the randomisation of sampling during training) to see what is going on.</p>
<p>Although the errors often follow the relationship training &lt; validation &lt; test, this is not always the case, so do not be alarmed if this is not true on a run (You can see it is not always true in the run above).</p>
<h3>14 Implement a proper stopping condition</h3>
<p>Change the while loop to stop when the validation error drops below a threshold. Note that this threshold usually depends on the problem. There are better stopping conditions that are less sensitive to the problem at hand, but this one will do for now.</p>
<h3>15 Implement a statistical analysis</h3>
<p>This part is important for you to get an idea of the robustness of the neural net. In practice, a very simple analysis will suffice.</p>
<p>This part need to train the algorithm 30 times, and then report the mean, standard deviation and maximum of the</p>
<ul>
<li>training time,</li>
<li>regression error, and</li>
<li>classification error (on the test sets).</li>
</ul>
<p>In general, you would like all these values to be “low”. Here are some experiments for the iris data set with different learning rates. For each, 30 runs were made; other parameters are as described earlier (max_weight = 1/2, validation_stop_threshold = 0.1).</p>
<table border="0" cellspacing="0" cellpadding="2" width="486">
<tbody>
<tr>
<td width="171" valign="top"></td>
<td width="107" valign="top"><strong>Mean</strong></td>
<td width="100" valign="top"><strong>Standard Deviation</strong></td>
<td width="106" valign="top"><strong>Maximum</strong></td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 0.05</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">1200</td>
<td width="100" valign="top">124.681</td>
<td width="106" valign="top">1489</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.115343</td>
<td width="100" valign="top">0.0017233</td>
<td width="106" valign="top">0.11894</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.17807</td>
<td width="100" valign="top">0.0456762</td>
<td width="106" valign="top">0.263158</td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 0.1</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">582.533</td>
<td width="100" valign="top">65.3076</td>
<td width="106" valign="top">719</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.114626</td>
<td width="100" valign="top">0.00180851</td>
<td width="106" valign="top">0.118697</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.214912</td>
<td width="100" valign="top">0.0317323</td>
<td width="106" valign="top">0.263158</td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 0.5</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">120.967</td>
<td width="100" valign="top">16.7095</td>
<td width="106" valign="top">169</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.115711</td>
<td width="100" valign="top">0.0038786</td>
<td width="106" valign="top">0.123573</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.245614</td>
<td width="100" valign="top">0.0242702</td>
<td width="106" valign="top">0.263158</td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 1</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">67.1667</td>
<td width="100" valign="top">12.2477</td>
<td width="106" valign="top">99</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.114755</td>
<td width="100" valign="top">0.00488566</td>
<td width="106" valign="top">0.124468</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.253509</td>
<td width="100" valign="top">0.0201287</td>
<td width="106" valign="top">0.263158</td>
</tr>
</tbody>
</table>
<h2>Using the neural net in a program</h2>
<p>To use the neural net in a program after you have trained it, you need to save the weights found by the training program to a file. Your application must then read in this weights, and use it with the feedforward function to calculate the class.</p>
<p>Here is pseudo-code for the program. Note that the training program and classification program needn’t be implemented in the same language. This allows you to take advantage of speed and interface components that might not be available in your target platform. It is a very good idea to implement your training algorithm on a computer algebra system (such as <a href="http://www.mathworks.com/">Matlab</a> or <a href="http://www.gnu.org/software/octave/">Octave</a>) where you can take advantage of both matrix and graphing capabilities (the code provided below works in both).</p>
<h2>Using the training algorithm on other problems</h2>
<p>When using your neural net for other algorithms, you might need to change the learning rate, stopping threshold, and weight_max for weight the initialisation. The error plots are indispensible for this purpose.</p>
<p>As long as the learning rate is not too high, it should not affect the quality of the solution, only the number of iterations necessary to obtain it. The stopping threshold, however, has does affect the quality of the solution: if it is tool low, the problem might not be solved, or the neural net might train very long; if it is too high, you will get poor performance. There are better stopping conditions available; once you have everything working, you should investigate these.</p>
<p>Remember that you should not base your decisions on a single run, as runs can differ quite drastically from one another. Perform a few runs, and base decisions on these.</p>
<p>The value weight_max can usually be chosen as 1/sqrt(input_count) with good results, but here too it depends on the problem.</p>
<p>For further benchmarking, check out the <a href="ftp://ftp.ira.uka.de/pub/neuron/">Proben1 datasets</a>, described <a href="http://page.mi.fu-berlin.de/prechelt/Biblio/1994-21.pdf">here</a>. (Also check out the erratum note on <a href="http://page.mi.fu-berlin.de/prechelt/Biblio/">this site</a> – search for proben on the page.)</p>
<h2>Download</h2>
<p>The following code works in Matlab and Octave. (Included is a randint function; if you are using Matlab you can remove it, because it is already implemented in Matlab).</p>
<p><a href="http://www.code-spot.co.za/downloads/neural_net/iris_data_files.zip">iris_data_files.zip</a> (3 KB)</p>
<p><a href="http://www.code-spot.co.za/downloads/neural_net/basic_neural_net_0_1.zip">basic_neural_net_0_1.zip</a> (10 KB)</p>
<p>The program provided cheats a little – instead of reading in the raw .dat files, it reads in the .mat file that already has the data in the right structure.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/' rel='bookmark' title='Permanent Link: Generating Random Numbers with Arbitrary Distributions'>Generating Random Numbers with Arbitrary Distributions</a></li>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='Permanent Link: 5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/10/08/15-steps-to-implemented-a-neural-net/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Getting More out of Seamless Tiles</title>
		<link>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/</link>
		<comments>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/#comments</comments>
		<pubDate>Thu, 28 May 2009 08:46:07 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[blending]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[grids]]></category>
		<category><![CDATA[tiles]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=620</guid>
		<description><![CDATA[I wrote an article for Dev.Mag covering some techniques for working with seamless tile sets such as making blend tiles, getting more variety with procedural colour  manipulation, tile placement strategies, and so on.  Check it out! The Python Image Code has also been updated with some of the algorithms explained in the article. Related posts:Quadtrees Quadtrees Cellular Automata [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-622" title="tiles_header_small" src="http://code-spot.co.za/blog/wp-content/uploads/2009/05/tiles_header_small.png" alt="tiles_header_small" width="142" height="142" />I wrote an article for Dev.Mag covering <a href="http://www.devmag.org.za/articles/70-GETTING-MORE-OUT-OF-SEAMLESS-TILES/">some techniques for working with seamless tile sets</a> such as making blend tiles, getting more variety with procedural colour  manipulation, tile placement strategies, and so on. </p>
<p>Check it out!</p>
<p>The <a href="http://code-spot.co.za/python-image-code/">Python Image Code</a> has also been updated with some of the algorithms explained in the article.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generating Random Integers With Arbitrary Probabilities</title>
		<link>http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/</link>
		<comments>http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 07:12:28 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[probability]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[random distribution]]></category>
		<category><![CDATA[random integer]]></category>
		<category><![CDATA[random number generation]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=582</guid>
		<description><![CDATA[I finally laid my hands on Donald Knuth’s The Art of Computer Programming (what a wonderful set of books!), and found a neat algorithm for generating random integers 0, 1, 2, … , n – 1, with probabilities p_0, p_1, … , p_(n-1). I have written about generating random numbers (floats) with arbitrary distributions for [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/' rel='bookmark' title='Permanent Link: Generating Random Points from Arbitrary Distributions for 2D and Up'>Generating Random Points from Arbitrary Distributions for 2D and Up</a></li>
<li><a href='http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/' rel='bookmark' title='Permanent Link: Generating Random Numbers with Arbitrary Distributions'>Generating Random Numbers with Arbitrary Distributions</a></li>
<li><a href='http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/' rel='bookmark' title='Permanent Link: Estimating a Continuous Distribution from a Sample Set'>Estimating a Continuous Distribution from a Sample Set</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline" title="header" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/header2.png" alt="header" width="500" height="332" /></p>
<p>I finally laid my hands on Donald Knuth’s <em><a href="http://www.amazon.com/Art-Computer-Programming-Volumes-Boxed/dp/0201485419">The Art of Computer Programming</a></em> (what a wonderful set of books!), and found a neat algorithm for generating random integers 0, 1, 2, … , n – 1, with probabilities p_0, p_1, … , p_(n-1).</p>
<p>I have written about generating random numbers (floats) with arbitrary distributions for <a href="http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/">one dimension</a> and <a href="http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/">higher dimensions</a>, and indeed that method can be adapted for generating integers with specific probabilities. However, the method described below is much more concise, and efficient (I would guess) for this special case. Moreover, it is also easy to adapt it to generate floats for continuous distributions.</p>
<p><span id="more-582"></span></p>
<h2>Description of the Algorithm</h2>
<p>The basic idea of the algorithm is simple. We have two tables of length n that contains integers (K, L), and a third table that contains probabilities (P). The first table merely contains the integers 0 to n-1 (thus, we need not actually store it explicitly). The other two tables are computed before generation (more about that below).</p>
<p>To generate a random number, we generate a random integer (uniformly distributed between 0 and n-1 inclusive), and a random float (uniformly distributed between 0 and 1). The integer tells us which cells in the table to use. First we lookup the probability in P at that index. If the float is smaller than that value, we return the integer in K, otherwise we return the integer in L. (Note, the integer in K is exactly the random integer itself. Therefore, we do not actually have a table K – we simply use the random integer.)</p>
<p>Now this will only give the desired result if the tables have been constructed for this to work. Before looking at how these tables are generated, let us look at a very simple example. Suppose we want to generate 0, 1, 2, with probabilities 3/18, 7/18, 8/18. Can you see why the following tables will work?</p>
<table border="0" cellspacing="0" cellpadding="0" width="500">
<tbody>
<tr>
<td width="125" valign="top"></td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">2</td>
</tr>
<tr>
<td width="125" valign="top">P</td>
<td width="125" valign="top">1/2</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">5/6</td>
</tr>
<tr>
<td width="125" valign="top">L</td>
<td width="125" valign="top">2</td>
<td width="125" valign="top">*</td>
<td width="125" valign="top">1</td>
</tr>
</tbody>
</table>
<p>There is only one way to generate 0: if the random integer is 0, and the random float is below 1/2. This will happen with probability 1/3 x 1/2 = 1/6 = 3/18.</p>
<p>There are two ways of generating 1:</p>
<ul>
<li>if the random integer is 1 (probability 1/3 = 6/18); or</li>
<li>if the random integer is 2, and the float is above 5/6 (probability 1/3 x 1/6 = 1/18).</li>
</ul>
<p>Adding these probabilities, we get 6/18 + 1/18 = 7/18.</p>
<p>There are also two ways to generate 2:</p>
<ul>
<li>if the random integer is 0 and the random float is above 1/2 (1/3 x 1/2 = 1/6 = 3/18); or</li>
<li>if the random integer is 2 and the random float is below 5/6 (1/3 x 5/6 = 5/18).</li>
</ul>
<p>Adding these probabilities, we get 3/18 + 5/18 = 8/18.</p>
<h2>Generating the tables</h2>
<p>Consider this problem:</p>
<ul>
<li>We have n<em> </em>squares that we want to paint.</li>
<li>We have five colours of paint, possibly different amounts of paint for each colour.</li>
<li>Each square has a border in one of the colours; no two borders are the same colour.</li>
<li>In total, there is just enough paint to cover the n squares <em>exactly</em>.</li>
<li>We want to paint each square with at most two colours, with one colour matching the border.</li>
</ul>
<p>To do this, we sort the paint buckets in ascending order. We paint the square that matches the first bucket with the first bucket, and whatever remains with the last bucket. The first bucket is empty (why?), and there might be some paint remaining in the last bucket. We now put this bucket back so that the buckets are sorted according to the new quantities of paint. The first square is completely covered (why?). Note that the painted square’s colour corresponds with the depleted colour.</p>
<p>The situation is now: we have n-1 unpainted squares, and n-1 colours of paint. This is the same problem as the initial problem, with one less square and one less colour. Therefore, we proceed as before, and repeat this process until all the squares have been painted and all the paint has been used.</p>
<p>To answer the two <em>why</em>’s above:</p>
<p>The first bucket is always empty, because the smallest bucket cannot cover more than one square. Since it is the smallest bucket, all other buckets must contain at least as much paint. Thus, we have n colours, and enough paint of each colour to paint more than one square. Thus, in total, we must have more paint than is required to paint n squares. But we said that we have <em>exactly</em> the right amount of paint needed, not more. Therefore, the smallest amount of paint cannot cover more than one square.</p>
<p>The first square is always covered completely, since the last bucket always contains enough paint for at least one square. If it did not, since it is the largest bucket, all other buckets will paint less than one square. In total, we would have n colours, each that can cover less than one square. Thus, all our paint will cover less than n squares: we do not have enough paint. But we said that we <em>do</em>, so this cannot be. Therefore, we must have enough paint in the last bucket to cover at least one square.</p>
<p>Below is an illustration of this process for three colours. Here we assume that 1 litre of paint covers 1 square. We have 1/3 = 3/6 litre of red, 7/6 litre of green, and 8/6 litre of cyan.</p>
<h3>Sort Paint</h3>
<p><img style="display: inline" title="step0" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step0.png" alt="step0" width="500" height="92" /></p>
<h3>Paint from first bucket</h3>
<p><img style="display: inline" title="step1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step1.png" alt="step1" width="500" height="92" /></p>
<h3>Paint from last bucket</h3>
<p><img style="display: inline" title="step2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step2.png" alt="step2" width="500" height="92" /></p>
<h3>Sort Paint</h3>
<p><img style="display: inline" title="step3" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step3.png" alt="step3" width="399" height="92" /></p>
<h3>Paint from first bucket</h3>
<p><img style="display: inline" title="step4" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step4.png" alt="step4" width="396" height="92" /></p>
<h3>Paint from last bucket</h3>
<p><img style="display: inline" title="step5" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step5.png" alt="step5" width="396" height="110" /></p>
<h3>Sort paint</h3>
<p><img style="display: inline" title="step6" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step6.png" alt="step6" width="299" height="110" /></p>
<h3>Paint from first bucket</h3>
<p><img style="display: inline" title="step7" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step7.png" alt="step7" width="291" height="110" /></p>
<p>As you can see, the solution above corresponds with the tables given in the example above. Indeed, the algorithm for calculating the tables is exactly the same as the paint algorithm:</p>
<ul>
<li>The n colours correspond to the n integers (from 0 to n-1) that we want to generate.</li>
<li>The initial amounts of paints corresponds with the (relative) probabilities that we want to generate each integer.</li>
<li>The amount of paint used to paint a square of the same border is the entry in table P – the probability of using the number associated with that cell (i.e., “the border”).</li>
<li>The other colour used to paint a square (if any) corresponds to the entry in table K.</li>
</ul>
<h2>A Small Optimisation in the Implementation</h2>
<h3>Generating two uniform random numbers for the price of one</h3>
<p>There is a trick to generate a random integer (0 &lt;= n &lt; k) and a random float (0 &lt;= x &lt; 1) from a single random float (0 &lt;= u &lt; 1) that is used in the implementation of this algorithm (see download below).</p>
<p>The trick is:</p>
<ul>
<li>n = floor (uk)</li>
<li>x = uk – n</li>
</ul>
<p>This assumes things about the random generator and the accuracy required. (I do not want to get into the details here).</p>
<h2>Download</h2>
<p>A python implementation of the above algorithm.</p>
<p><a href="http://www.code-spot.co.za/downloads/python/non_uniform_random_int.py">non_uniform_random_int.py</a></p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/' rel='bookmark' title='Permanent Link: Generating Random Points from Arbitrary Distributions for 2D and Up'>Generating Random Points from Arbitrary Distributions for 2D and Up</a></li>
<li><a href='http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/' rel='bookmark' title='Permanent Link: Generating Random Numbers with Arbitrary Distributions'>Generating Random Numbers with Arbitrary Distributions</a></li>
<li><a href='http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/' rel='bookmark' title='Permanent Link: Estimating a Continuous Distribution from a Sample Set'>Estimating a Continuous Distribution from a Sample Set</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Estimating a Continuous Distribution from a Sample Set</title>
		<link>http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/</link>
		<comments>http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 14:27:06 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[convolution]]></category>
		<category><![CDATA[distribution estimation]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[random distribution]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=445</guid>
		<description><![CDATA[It is sometimes necessary to find the distribution given a sample set from that distribution. If we do not know anything about the distribution, we cannot recover it exactly, so here we look at ways of finding a (discrete) approximation. I will cover the case for 2D sets here, but the ideas are easily extended [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/' rel='bookmark' title='Permanent Link: Generating Random Points from Arbitrary Distributions for 2D and Up'>Generating Random Points from Arbitrary Distributions for 2D and Up</a></li>
<li><a href='http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/' rel='bookmark' title='Permanent Link: Generating Random Integers With Arbitrary Probabilities'>Generating Random Integers With Arbitrary Probabilities</a></li>
<li><a href='http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/' rel='bookmark' title='Permanent Link: Generating Random Numbers with Arbitrary Distributions'>Generating Random Numbers with Arbitrary Distributions</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline" title="header_rand_dist2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/header-rand-dist2.png" alt="header_rand_dist2" width="500" height="374" /> It is sometimes necessary to find the distribution given a sample set from that distribution. If we do not know anything about the distribution, we cannot recover it exactly, so here we look at ways of finding a (discrete) approximation.</p>
<p><span id="more-445"></span></p>
<p>I will cover the case for 2D sets here, but the ideas are easily extended to any dimension.</p>
<h2>Visual Inspection From a Scatter Plot</h2>
<p>The easy way to estimate the distribution is to simply look at a scatter plot of the samples.</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="181" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-pixel.png" alt="scatter_pixel" width="300" height="300" /></td>
<td width="316" valign="top">A scatter plot of a 2D sample set. (A pixel was simply drawn at each point of the sample. The images was slightly blurred to give the pixels more substance).Here we can already estimate the distribution, as we can intuitively &#8220;see&#8221; the shape.</td>
</tr>
<tr>
<td width="181" valign="top"></td>
<td width="316" valign="top"></td>
</tr>
</tbody>
</table>
<p>If the distribution is simple, we can often “guess” suitable parameters for a mathematical function. But this method is not suitable when more accuracy is required. And obviously this method does not work for higher dimensions.</p>
<p>I always use a visual inspection as a first step when using the other methods described here. First, it allows you to decide which approach to use. Second, it serves as a rough benchmark to test the results of a better method against.</p>
<h2>Averaging Over a Grid</h2>
<p>For this method, we divide the domain in cells, and count the number of points in each cell. To normalise, we divide the counts by the total number of points to get a distribution.</p>
<p>Typically, we choose a cell size large enough so that all cells contain a few points.</p>
<p>It is possible to use different cell sizes, so that regions of higher density has more cells, for instance, by using a quad tree. However, this approach makes it difficult to interpret the values (they should be scaled down by a factor of the area they represent), and to generate random numbers from this distribution. I can’t really imagine a situation where this approach will be preferred above using a regular grid or convolution.</p>
<h2>Convolution</h2>
<p>There are two ways to implement convolution. The first should be used when the sample set is small relative to the size of the domain, otherwise the second method will be more efficient.</p>
<h3>Sparse Point Convolution</h3>
<p>Generate a very granular empty grid over the domain.</p>
<p>For each point p in the sample set,</p>
<ul>
<li>map p to the grid (calculate the coordinates x,y of p in the grid),</li>
<li>add a number to all the cells in the neighbourhood of p in the grid.</li>
</ul>
<p>Now normalise the grid.</p>
<p>The neighbourhood is typically a circle or a square. The number you add can be the same for all neighbours (in which case any positive number will do), or it can be scaled depending on the distance from p.</p>
<p>The size of the neighbourhood depends on the density of your sample. In general, the denser it is, the smaller the neighbourhood can be. Smaller neighbourhoods lead to faster execution. To prevent “holes” in the approximation, use a radius that corresponds to the maximum of the distances between a point and its closest neighbour.</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="179" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-square16.png" alt="scatter_square16" width="300" height="301" /></td>
<td width="319" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/square.png" alt="square" width="100" height="100" />Estimation with a constant square neighbourhood.</td>
</tr>
<tr>
<td width="179" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-circle16.png" alt="scatter_circle16" width="300" height="300" /></td>
<td width="319" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/circle.png" alt="circle" width="100" height="100" /><br />
Estimation with a constant circular neighbourhood.</td>
</tr>
<tr>
<td width="179" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-cone16.png" alt="scatter_cone16" width="300" height="300" /></td>
<td width="319" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/cone.png" alt="cone" width="100" height="100" /><br />
Estimation with a circular neighbourhood with a falloff.</td>
</tr>
</tbody>
</table>
<h3>Traditional Convolution</h3>
<p>Generate a very granular empty grid over the domain.</p>
<p>For each point p in the sample set, map p to the grid (calculate the coordinates x,y of p in the grid), and add one to that location in the grid.</p>
<p>Now choose a square, symmetrical convolution matrix, and perform a discrete convolution on the grid:</p>
<p>new_grid[i, j] = sum_{i,j} grid[i][j] * c[i][j]</p>
<p>Here the i, j go over the indices of the convolution matrix. (Normally, the convolution is defined as new_grid[i, j] = sum_{i,j} grid[n - i][n - j] * c[i][j]. However, since we are suing a symmetrical matrix, these definitions are equivalent, and we need not perform the extra calculation).</p>
<p>Now normalise the grid.</p>
<p>The convolution can be a square or circle of 1s, or be filled with numbers that grow smaller outwards. These correspond to the three neighbourhoods described for the sparse convolution.</p>
<p>Note that the new_grid is larger than the original by one less than the size of the convolution matrix in each dimension. The centre of the new grid corresponds with the original grid.</p>
<p>For example, if the original grid was 100&#215;100, and the convolution matrix was 5&#215;5, the new grid will be 104&#215;104. The point (2, 2) in the new grid corresponds to point (0, 0) in the original grid.</p>
<h2>About Normalisation</h2>
<p>It is customary to normalise the distribution so that all the probabilities add to 1. But for many purposes we need only relative probabilities, and this step can be skipped. For example, the method of generating random numbers described in a previous post uses only relative probabilities.</p>
<h2>A Few Tips</h2>
<ul>
<li>Always test your distribution by <a href="http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/">generating a random set from it</a>, and comparing it with the original sample. They should match qualitatively.</li>
<li>The smaller your sample set, the cruder the approximation should be. That is, cells, neighbourhoods or convolution matrices should be big. There is a limit to the accuracy you can obtain from any sample – if you try to exceed it, your results will be poor.</li>
<li>The most common implementation errors are made at the borders (of any grid or matrix) – watch out for them!</li>
</ul>
<h2>Download</h2>
<p>There is an example of implementation in 2D in with the <a href="http://code-spot.co.za/python-image-code/">Python Image Code</a>. See the file random_distributions_demo.py.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/' rel='bookmark' title='Permanent Link: Generating Random Points from Arbitrary Distributions for 2D and Up'>Generating Random Points from Arbitrary Distributions for 2D and Up</a></li>
<li><a href='http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/' rel='bookmark' title='Permanent Link: Generating Random Integers With Arbitrary Probabilities'>Generating Random Integers With Arbitrary Probabilities</a></li>
<li><a href='http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/' rel='bookmark' title='Permanent Link: Generating Random Numbers with Arbitrary Distributions'>Generating Random Numbers with Arbitrary Distributions</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

