File: SOMTrain_2D_example.html

package info (click to toggle)
supercollider-sc3-plugins 3.7.1~repack-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 14,332 kB
  • ctags: 11,704
  • sloc: cpp: 140,180; lisp: 14,746; ansic: 2,133; xml: 86; makefile: 82; haskell: 21; sh: 8
file content (137 lines) | stat: -rw-r--r-- 11,863 bytes parent folder | download | duplicates (4)
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>