1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="824.47">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #ad140d}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #606060}
span.s1 {text-decoration: underline ; color: #003fd9}
span.s2 {color: #001bb9}
span.s3 {color: #000000}
span.s4 {color: #606060}
span.s5 {font: 12.0px Helvetica}
span.s6 {color: #ad140d}
span.s7 {color: #2c7014}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1"><b>SOMTrain two-dimensional example</b></p>
<p class="p2"><br></p>
<p class="p3">In this example of <a href="SOMTrain.html"><span class="s1">SOMTrain</span></a> in action, we create a 2D neural net and fit it to a data set which is a 2D surface in a 3D space - it should be quite straightforward for a 2D SOM to fit to the hills and valleys. See also <a href="SOMTrain_3D_example.html"><span class="s1">SOMTrain_3D_example</span></a></p>
<p class="p2"><br></p>
<p class="p3"><i>Hint:</i> self-organising maps work best when the training dimensions have a similar dynamic range (e.g. similar variance), so in this example we normalise the ranges of the input data. You should probably do a similar thing.</p>
<p class="p2"><br></p>
<p class="p3">s.boot;</p>
<p class="p3">~numnodes = 20;</p>
<p class="p3">~traindur = 100000;</p>
<p class="p3">~dataspacelength = 100;</p>
<p class="p3">~dataspacechanwidth = 10;</p>
<p class="p4">// First create the data</p>
<p class="p3">~dataspace = <span class="s2">Buffer</span>.alloc(s, ~dataspacelength, ~dataspacechanwidth);</p>
<p class="p3">~data = ~dataspacechanwidth.collect{<span class="s2">|index|</span> ((0..~dataspacelength)*2*pi/~dataspacelength).sin * ((8 * index/~dataspacechanwidth).sin) }</p>
<p class="p4">//~data.heatMap(title: "training data (array)"); // You need the "heatMap" quark to run this line - visualises the data nicely</p>
<p class="p3">~dataspace.loadCollection(~data.flop.flatten);</p>
<p class="p4">//~dataspace.heatMap(title: "training data (buffer)");</p>
<p class="p4">// Allocate space for the SOM, and initialise it</p>
<p class="p3">~som = <span class="s2">SOMTrain</span>.allocBuf(s, ~numnodes, 2, 3);</p>
<p class="p4"><span class="s2">SOMTrain</span><span class="s3">.initBufGridRand(~som, ~numnodes, 2, scales: 3); </span>// Grid init - a 2D grid is randomly oriented in the target space (which here is 3D)</p>
<p class="p4">//~som.plot(minval:nil.dup(3), maxval: nil.dup(3));</p>
<p class="p4">// Also, just for demonstration purposes, we're going to write the error values to a buffer so we can see how they evolve</p>
<p class="p3">~errorvals = <span class="s2">Buffer</span>.alloc(s, ~traindur);</p>
<p class="p4">// Now train the SOM. To train it with data "randomly sampled" from the data buffer, we just wiggle the phase around and feed [phase, val] to the SOM.</p>
<p class="p3">(</p>
<p class="p3">x = {</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s2">var</span> phase1, phase2, val, remain, err, trig;</p>
<p class="p3"><span class="Apple-tab-span"> </span>trig = 1;</p>
<p class="p3"><span class="Apple-tab-span"> </span>phase1 = <span class="s2">WhiteNoise</span>.kr.range(0, ~dataspace.numFrames-1);</p>
<p class="p3"><span class="Apple-tab-span"> </span>phase2 = <span class="s2">WhiteNoise</span>.kr.range(0, ~dataspace.numChannels);</p>
<p class="p3"><span class="Apple-tab-span"> </span>val = <span class="s2">Select</span>.kr(phase2.floor, <span class="s2">BufRd</span>.kr(~dataspace.numChannels, ~dataspace, phase1, 1));</p>
<p class="p3"><span class="Apple-tab-span"> </span>phase1.poll(trig, label: <span class="s4">"phase1"</span>);</p>
<p class="p3"><span class="Apple-tab-span"> </span>phase2.poll(trig, label: <span class="s4">"phase2"</span>);</p>
<p class="p3"><span class="Apple-tab-span"> </span>val.poll(trig, label: <span class="s4">"val"</span>);</p>
<p class="p4"><span class="s3"><span class="Apple-tab-span"> </span></span>// Here the ranges are reshaped to be +-1</p>
<p class="p3"><span class="Apple-tab-span"> </span># remain, err = <span class="s2">SOMTrain</span>.kr(~som, [phase1 * 0.02 - 1, phase2 * 0.2 - 1, val], ~numnodes, 2, ~traindur, nhood: 0.75, gate: trig, initweight: 1);</p>
<p class="p3"><span class="Apple-tab-span"> </span>remain.poll(trig, label: <span class="s4">"remain"</span>);</p>
<p class="p3"><span class="Apple-tab-span"> </span>err.poll(trig, label: <span class="s4">"err"</span>);</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s2">BufWr</span>.kr(err.sqrt, ~errorvals, ~traindur-remain);</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s2">Out</span>.ar(0, <span class="s2">Pan2</span>.ar(<span class="s2">K2A</span>.ar(val) * 0.01));</p>
<p class="p3">}.play</p>
<p class="p3">)</p>
<p class="p4">// Once the training is finished...</p>
<p class="p3">x.free;</p>
<p class="p2"><br></p>
<p class="p4">// How do the errors look? Should be a very noisy curve gradually decreasing, but won't necessarily stabilise</p>
<p class="p3">~errorvals.plot(maxval: <span class="s2">nil</span>, minval: <span class="s2">nil</span>);</p>
<p class="p2"><br></p>
<p class="p4">// Now let's look at the mesh of points represented by the SOM. Do they fit the training data?</p>
<p class="p4">// Here's a pure SC plot, the colouring of the points representing the third dimension - you should be able to see the undulation</p>
<p class="p3">(</p>
<p class="p5"><span class="s5">~cols = </span>(1, 0.99 .. 0).collect{<span class="s2">|cold|</span> <span class="s2">Color</span>(0, cold * 0.1, cold)} ++ (0.01, 0.02 .. 1).collect{<span class="s2">|hot|</span> <span class="s2">Color</span>(hot, 0, 0)};</p>
<p class="p3">~som.loadToFloatArray(action: {<span class="s2">|arr|</span> {</p>
<p class="p3"><span class="Apple-tab-span"> </span>w = <span class="s2">GUI</span>.window.new(<span class="s4">"SOM nodes"</span>, <span class="s2">Rect</span>(200, 800, 600, 600)); <span class="s6">// SCWindow</span></p>
<p class="p3"><span class="Apple-tab-span"> </span>(0,3..arr.size-1).do{<span class="s2">|index|</span></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s2">GUI</span>.staticText.new(w, <span class="s2">Rect</span>(</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>(arr[index]<span class="Apple-converted-space"> </span>+1 * 300 ),<span class="Apple-converted-space"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>(arr[index+1] +1 * 300 ),<span class="Apple-converted-space"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>20, 20)).string_(<span class="s4">"x"</span>).background_(~cols[arr[index+2].linlin(-1, 1, 0, ~cols.size-1)]) <span class="s6">// SCStaticText</span></p>
<p class="p2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>};</p>
<p class="p3"><span class="Apple-tab-span"> </span>w.front;</p>
<p class="p3">}.defer})</p>
<p class="p3">)</p>
<p class="p2"><br></p>
<p class="p4">// Or if you have OctaveSC you can plot a very nice 3D mesh:</p>
<p class="p3">o = <span class="s2">OctaveSC</span>.new;</p>
<p class="p3">o.init;</p>
<p class="p3">(</p>
<p class="p3">~som.loadToFloatArray(action: {<span class="s2">|arr|</span></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s2">var</span> x, y, z;</p>
<p class="p3"><span class="Apple-tab-span"> </span>x = arr[0,3..];</p>
<p class="p3"><span class="Apple-tab-span"> </span>y = arr[1,4..];</p>
<p class="p3"><span class="Apple-tab-span"> </span>z = arr[2,5..];</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s4">"x range: % to %"</span>.format(x.minItem, x.maxItem).postln;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s4">"y range: % to %"</span>.format(y.minItem, y.maxItem).postln;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s4">"z range: % to %"</span>.format(z.minItem, z.maxItem).postln;</p>
<p class="p3"><span class="Apple-tab-span"> </span>x = x.clump(~numnodes);</p>
<p class="p3"><span class="Apple-tab-span"> </span>y = y.clump(~numnodes);</p>
<p class="p3"><span class="Apple-tab-span"> </span>z = z.clump(~numnodes);</p>
<p class="p3"><span class="Apple-tab-span"> </span>o[<span class="s7">\xtemp</span>] = x;</p>
<p class="p3"><span class="Apple-tab-span"> </span>o[<span class="s7">\ytemp</span>] = y;</p>
<p class="p3"><span class="Apple-tab-span"> </span>o[<span class="s7">\ztemp</span>] = z;</p>
<p class="p6"><span class="s3"><span class="Apple-tab-span"> </span>o.(</span>"figure; hold off"<span class="s3">);</span></p>
<p class="p6"><span class="s3"><span class="Apple-tab-span"> </span>o.(</span>"mesh(xtemp, ytemp, ztemp)"<span class="s3">);</span></p>
<p class="p3">});</p>
<p class="p3">);</p>
<p class="p3">(</p>
<p class="p3">~dataspace.loadToFloatArray(action: {<span class="s2">|arr|</span></p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s2">var</span> x, y, z;</p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>arr = arr.clump(~dataspace.numChannels);</p>
<p class="p2"><span class="Apple-tab-span"> </span></p>
<p class="p3"><span class="Apple-tab-span"> </span>x = (0..arr.size-1).dup(~dataspace.numChannels).flop;</p>
<p class="p3"><span class="Apple-tab-span"> </span>y = (0..~dataspace.numChannels-1).dup(arr.size);</p>
<p class="p3"><span class="Apple-tab-span"> </span>z = arr;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s4">"x size: [%, %]"</span>.format(x.size, x[0].size).postln;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s4">"y size: [%, %]"</span>.format(y.size, y[0].size).postln;</p>
<p class="p3"><span class="Apple-tab-span"> </span><span class="s4">"z size: [%, %]"</span>.format(z.size, z[0].size).postln;</p>
<p class="p3"><span class="Apple-tab-span"> </span>o[<span class="s7">\xtemp</span>] = x;</p>
<p class="p3"><span class="Apple-tab-span"> </span>o[<span class="s7">\ytemp</span>] = y;</p>
<p class="p3"><span class="Apple-tab-span"> </span>o[<span class="s7">\ztemp</span>] = z;</p>
<p class="p6"><span class="s3"><span class="Apple-tab-span"> </span>o.(</span>"figure; hold off"<span class="s3">);</span></p>
<p class="p6"><span class="s3"><span class="Apple-tab-span"> </span>o.(</span>"mesh(xtemp, ytemp, ztemp)"<span class="s3">);</span></p>
<p class="p3">});</p>
<p class="p3">);</p>
<p class="p2"><br></p>
<p class="p4">// Dump the xyz coordinates:</p>
<p class="p3">~som.loadToFloatArray(action: {<span class="s2">|arr|</span> <span class="Apple-converted-space"> </span>arr.clump(3).do(<span class="s2">_</span>.postln) <span class="Apple-converted-space"> </span>});</p>
</body>
</html>
|