Skip to content

Commit 1d02662

Browse files
committed
Code refactor, tutorial readme updated, better screenshots added
1 parent ffabd20 commit 1d02662

14 files changed

+341
-106
lines changed

.luna-package/RegressionTutorial.lunaproject

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
modulesSettings:
22
src/Main.luna:
33
typeRepToVisMap: []
4-
currentBreadcrumb: ''
4+
currentBreadcrumb: main
55
breadcrumbsSettings:
66
- - items: []
77
- breadcrumbCameraSettings:
8-
logicalToScreen: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[-2440.0,-17.0,0.0,1.0]]'
9-
screenToLogical: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[2440.0,17.0,0.0,1.0]]'
8+
logicalToScreen: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[-2134.0,9.0,0.0,1.0]]'
9+
screenToLogical: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[2134.0,-9.0,0.0,1.0]]'
1010
lastInverse: 0
1111
- - items:
1212
- accuracy
@@ -23,14 +23,20 @@ modulesSettings:
2323
- - items:
2424
- dataFrameToTf
2525
- breadcrumbCameraSettings:
26-
logicalToScreen: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[-576.0,48.0,0.0,1.0]]'
27-
screenToLogical: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[576.0,-48.0,0.0,1.0]]'
26+
logicalToScreen: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[-640.0,0.0,0.0,1.0]]'
27+
screenToLogical: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[640.0,0.0,0.0,1.0]]'
28+
lastInverse: 2
29+
- - items:
30+
- dataframeToTensorList
31+
- breadcrumbCameraSettings:
32+
logicalToScreen: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[-512.0,24.0,0.0,1.0]]'
33+
screenToLogical: ! '[[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0],[0.0,0.0,1.0,0.0],[512.0,-24.0,0.0,1.0]]'
2834
lastInverse: 2
2935
- - items:
3036
- error
3137
- breadcrumbCameraSettings:
32-
logicalToScreen: ! '[[0.8270833333333333,0.0,0.0,0.0],[0.0,0.8270833333333333,0.0,0.0],[0.0,0.0,1.0,0.0],[-529.3333333333333,-132.33333333333331,0.0,1.0]]'
33-
screenToLogical: ! '[[1.2090680100755669,0.0,0.0,0.0],[0.0,1.2090680100755669,0.0,0.0],[0.0,0.0,1.0,0.0],[640.0,160.0,0.0,1.0]]'
38+
logicalToScreen: ! '[[0.86875,0.0,0.0,0.0],[0.0,0.86875,0.0,0.0],[0.0,0.0,1.0,0.0],[-695.0,-139.0,0.0,1.0]]'
39+
screenToLogical: ! '[[1.1510791366906474,0.0,0.0,0.0],[0.0,1.1510791366906474,0.0,0.0],[0.0,0.0,1.0,0.0],[800.0,160.0,0.0,1.0]]'
3440
lastInverse: 2
3541
- - items:
3642
- extendWith
@@ -41,8 +47,8 @@ modulesSettings:
4147
- - items:
4248
- main
4349
- breadcrumbCameraSettings:
44-
logicalToScreen: ! '[[1.8132218070652175,0.0,0.0,0.0],[0.0,1.8132218070652175,0.0,0.0],[0.0,0.0,1.0,0.0],[-6948.364809782609,-2643.524796195652,0.0,1.0]]'
45-
screenToLogical: ! '[[0.5515045076688911,0.0,0.0,0.0],[0.0,0.5515045076688911,0.0,0.0],[0.0,0.0,1.0,0.0],[3832.0545135230063,1457.9158412363888,0.0,1.0]]'
50+
logicalToScreen: ! '[[1.7232398986816406,0.0,0.0,0.0],[0.0,1.7232398986816406,0.0,0.0],[0.0,0.0,1.0,0.0],[-1405.7312213715527,-2103.5846000207657,0.0,1.0]]'
51+
screenToLogical: ! '[[0.5803022555159307,0.0,0.0,0.0],[0.0,0.5803022555159307,0.0,0.0],[0.0,0.0,1.0,0.0],[815.7489984110762,1220.7148880606273,0.0,1.0]]'
4652
lastInverse: 0
4753
- - items:
4854
- nfeatures
@@ -59,8 +65,8 @@ modulesSettings:
5965
- - items:
6066
- prepareData
6167
- breadcrumbCameraSettings:
62-
logicalToScreen: ! '[[0.43660714285714286,0.0,0.0,0.0],[0.0,0.43660714285714286,0.0,0.0],[0.0,0.0,1.0,0.0],[-590.2928571428572,-209.57142857142858,0.0,1.0]]'
63-
screenToLogical: ! '[[2.2903885480572597,0.0,0.0,0.0],[0.0,2.2903885480572597,0.0,0.0],[0.0,0.0,1.0,0.0],[1352.0,480.0,0.0,1.0]]'
68+
logicalToScreen: ! '[[0.6151785714285715,0.0,0.0,0.0],[0.0,0.6151785714285715,0.0,0.0],[0.0,0.0,1.0,0.0],[-1043.3428571428572,-295.2857142857143,0.0,1.0]]'
69+
screenToLogical: ! '[[1.625544267053701,0.0,0.0,0.0],[0.0,1.625544267053701,0.0,0.0],[0.0,0.0,1.0,0.0],[1696.0,480.0,0.0,1.0]]'
6470
lastInverse: 2
6571
- - items:
6672
- prepareDataSet

README.html

+131-39
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,14 @@ <h2 class="mume-header" id="cloning-repository">Cloning repository.</h2>
280280
cmake <span class="token punctuation">..</span>/src
281281
<span class="token function">make</span>
282282
<span class="token function">cd</span> <span class="token punctuation">..</span>/<span class="token punctuation">..</span>/<span class="token punctuation">..</span>/<span class="token punctuation">..</span>
283-
</pre><h2 class="mume-header" id="lets-start-with-luna-studio">Let&apos;s start with Luna Studio!</h2>
283+
</pre><h2 class="mume-header" id="dataset">Dataset</h2>
284284

285+
<p>In this tutorial we will use slightly preprocessed dataset of cars parameters, to predict their fuel usage (MPG - <i>miles per galon</i>). The dataset is a <code>.csv</code> format table with columns: <code>MPG</code>, <code>Cylinders</code>, <code>Displacement</code>, <code>Horsepower</code>, <code>Weight</code>, <code>Acceleration</code>, <code>Model Year</code> and <code>Origin</code>. The task is to predict value of first column, based on the rest of them. Unfortunately <code>Origin</code> column needs to be <i>one hot encoded</i>, so the last column will be replaced with three new columns: <code>USA</code>, <code>Europe</code>, <code>Japan</code>.</p>
286+
<p><img src="Screenshots/dataSet.png" alt></p>
287+
<p>To load dataset from <code>.csv</code> file, we will use Dataframes, which is Luna library allowing more comfortable work with big datasets (<a href="https://github.com/luna/dataframes">https://github.com/luna/dataframes</a>).</p>
288+
<h2 class="mume-header" id="lets-start-with-luna-studio">Let&apos;s start with Luna Studio!</h2>
289+
290+
<p>At the beggining we need some imports.</p>
285291
<pre data-role="codeBlock" data-info class="language-"><code>import Std.Base
286292
import Dataframes.Table
287293
import Dataframes.Column
@@ -295,15 +301,21 @@ <h2 class="mume-header" id="cloning-repository">Cloning repository.</h2>
295301
import Tensorflow.Operations
296302
import Tensorflow.GeneratedOps
297303
import RegressionTutorial.DblColumn
298-
</code></pre><pre data-role="codeBlock" data-info class="language-"><code>def extendWith table name value:
304+
</code></pre><p>The size of dataset labels is the number of different cars parameters.</p>
305+
<pre data-role="codeBlock" data-info class="language-"><code>def nfeatures:
306+
9
307+
</code></pre><p>Function to extend given table with new column of zeros and ones, depending on values in column <code>Origin</code>.</p>
308+
<pre data-role="codeBlock" data-info class="language-"><code>def extendWith table name value:
299309
table&apos; = table.eachTo name (row: (row.at &quot;Origin&quot; == value).switch 0.0 1.0)
300310
table&apos;
301-
</code></pre><pre data-role="codeBlock" data-info class="language-"><code>def oneHotOrigin table:
311+
</code></pre><p>Extending table with <i> one hot encoded </i> column <code>Origin</code>.</p>
312+
<pre data-role="codeBlock" data-info class="language-"><code>def oneHotOrigin table:
302313
t1 = extendWith table &quot;USA&quot; 1
303314
t2 = extendWith t1 &quot;Europe&quot; 2
304315
t3 = extendWith t2 &quot;Japan&quot; 3
305316
t3
306-
</code></pre><pre data-role="codeBlock" data-info class="language-"><code>def shuffle table:
317+
</code></pre><p>We need a function that shuffles rows of given table, to balance dataset. Here the original table is extended with random column, sorted, and then</p>
318+
<pre data-role="codeBlock" data-info class="language-"><code>def shuffle table:
307319
row = table.rowCount
308320
rand = Tensors.random FloatType [row] 0.0 0.0
309321
col = columnFromList &quot;rand&quot; (rand.toFlatList)
@@ -312,29 +324,42 @@ <h2 class="mume-header" id="cloning-repository">Cloning repository.</h2>
312324
table3 = table2.remove &quot;rand&quot;
313325
table3
314326
</code></pre><p><img src="Screenshots/suffle.png" alt></p>
327+
<p>Function to divide dataset with given ratio, into test and train parts.</p>
315328
<pre data-role="codeBlock" data-info class="language-"><code>def sample table fracTest:
316329
testCount = (fracTest * table.rowCount.toReal).floor
317330
test = table.take testCount
318331
train = table.drop testCount
319332
(train, test)
320-
</code></pre><pre data-role="codeBlock" data-info class="language-"><code>def nfeatures:
321-
9
322-
</code></pre><pre data-role="codeBlock" data-info class="language-"><code>def dataFrameToTf shape table:
333+
</code></pre><p>Function to convert the Dataframes table into tensors list. It simply converts table into two dimensional list, maps it to Luna <code>Real</code> type, transpose (because we need to flip columns and rows), and finally creates tensor from each row.</p>
334+
<pre data-role="codeBlock" data-info class="language-"><code>def dataframeToTensorList shape table:
323335
lst = table.toList . each (col: (col.toList).each (_.toReal))
324336
t1 = Tensors.fromList2d FloatType lst
325337
t2 = Tensors.transpose t1
326338
lst&apos; = Tensors.to2dList t2
327339
samples = lst&apos;.each(l: Tensors.fromList FloatType shape l)
328340
samples
329-
</code></pre><p><img src="Screenshots/dataFrameToTf.png" alt></p>
341+
</code></pre><p><img src="Screenshots/dataframeToTensorList.png" alt></p>
342+
<p>To estimate correctness of models predictions we use mean error.</p>
330343
<pre data-role="codeBlock" data-info class="language-"><code>def error model xBatch yBatch:
331-
predictions = model.evaluate xBatch
332-
predictionsConst = Operations.makeConst predictions
344+
preds = model.evaluate xBatch
345+
predsConst = Operations.makeConst preds
333346
labelsConst = Operations.makeConst yBatch
334-
diff = Operations.abs (predictionsConst - labelsConst)
335-
accuracy = Operations.mean diff [1]
336-
accuracy.eval.atIndex 0
347+
diff = Operations.abs (predsConst - labelsConst)
348+
error = Operations.mean diff [1]
349+
error.eval.atIndex 0
337350
</code></pre><p><img src="Screenshots/error.png" alt></p>
351+
<p>Preparing data consists of three parts:</p>
352+
<ul>
353+
<li>
354+
Loading data and <i> one hot encoding </i> last column,
355+
</li>
356+
<li>
357+
Dividing train and test datasets into features and labels,
358+
</li>
359+
<li>
360+
Converting Dataframe tables to tensors, and batching them.
361+
</li>
362+
</ul>
338363
<pre data-role="codeBlock" data-info class="language-"><code>def prepareData path:
339364
table = Table.read path
340365
table1 = table.dropNa
@@ -343,48 +368,115 @@ <h2 class="mume-header" id="cloning-repository">Cloning repository.</h2>
343368
table4 = shuffle table3
344369
(trainTable, testTable) = sample table4 0.2
345370

346-
trainLabels = trainTable.at &quot;MPG&quot;
347-
testLabels = testTable.at &quot;MPG&quot;
348-
trainTable&apos; = trainTable.remove &quot;MPG&quot;
349-
testTable&apos; = testTable.remove &quot;MPG&quot;
371+
trainLabels&apos; = trainTable.at &quot;MPG&quot;
372+
testLabels&apos; = testTable.at &quot;MPG&quot;
373+
trainFeatures&apos; = trainTable.remove &quot;MPG&quot;
374+
testFeatures&apos; = testTable.remove &quot;MPG&quot;
350375

351-
trainX = Tensors.batchFromList $ dataFrameToTf [nfeatures] trainTable&apos;
352-
testX = Tensors.batchFromList $ dataFrameToTf [nfeatures] testTable&apos;
353-
trainY = Tensors.batchFromList $ dataFrameToTf [1] trainLabels
354-
testY = Tensors.batchFromList $ dataFrameToTf [1] testLabels
376+
trainFeatures = Tensors.batchFromList $ dataframeToTensorList [nFeatures] trainFeatures&apos;
377+
testFeatures = Tensors.batchFromList $ dataframeToTensorList [nFeatures] testFeatures&apos;
378+
trainLabels = Tensors.batchFromList $ dataframeToTensorList [1] trainLabels&apos;
379+
testLabels = Tensors.batchFromList $ dataframeToTensorList [1] testLabels&apos;
355380

356-
(trainX, testX, trainY, testY)
381+
(trainFeatures, testFeatures, trainLabels, testLabels)
357382
</code></pre><p><img src="Screenshots/prepareData.png" alt></p>
383+
<p>And last but not least, helper function to prepare the optimizing function used in a learning process.</p>
358384
<pre data-role="codeBlock" data-info class="language-"><code>def prepareOptimizer:
359385
lr = 0.001
360386
rho = 0.9
361387
momentum = 0.0
362388
epsilon = 0.000000001
363389
opt = RMSPropOptimizer.create lr rho momentum epsilon
364390
opt
365-
</code></pre><pre data-role="codeBlock" data-info class="language-"><code>def main:
366-
(trainX, testX, trainY, testY) = prepareData &quot;auto-mpg3.csv&quot;
367-
368-
input = Input.create FloatType [nfeatures]
369-
d1 = Dense.createWithActivation 64 Operations.relu input
370-
d2 = Dense.createWithActivation 64 Operations.relu d1
371-
d3 = Dense.createWithActivation 1 Operations.relu d2
372-
373-
opt = prepareOptimizer
374-
391+
</code></pre><h2 class="mume-header" id="building-model-training-and-testing">Building model, training and testing</h2>
392+
393+
<p>Let&apos;s focus on the details of Luna Tensorflow API.</p>
394+
<table>
395+
<tbody><tr><th> Code </th><th> Node editor </th></tr>
396+
<tr><td>
397+
<pre data-role="codeBlock" data-info class="language-"><code>def main:
398+
(trainFeatures, testFeatures,
399+
trainLabels, testLabels) =
400+
prepareData &quot;auto-mpg3.csv&quot;
401+
</code></pre></td><td>
402+
<p>Loading batched dataset, divided into train and test parts.</p>
403+
<p><img src="Screenshots/preparedData.png" alt></p>
404+
</td></tr>
405+
<tr><td>
406+
<pre data-role="codeBlock" data-info class="language-"><code>
407+
input = Input.create
408+
FloatType
409+
[nFeatures]
410+
d1 = Dense.createWithActivation
411+
64
412+
Operations.relu
413+
input
414+
d2 = Dense.createWithActivation
415+
64
416+
Operations.relu
417+
d1
418+
d3 = Dense.createWithActivation
419+
1
420+
Operations.relu
421+
d2
422+
</code></pre></td><td>
423+
<p>Connecting models layers in sequential order:</p>
424+
<ul>
425+
<li> input layer feeded with tensors of [nFeatures] shape, </li>
426+
<li> two fully connected layers with 64 output neurons, </li>
427+
<li> output fully connected layer with 1 neuron. </li>
428+
</ul>
429+
<p><img src="Screenshots/layers.png" alt></p>
430+
</td></tr>
431+
<tr><td>
432+
<pre data-role="codeBlock" data-info class="language-"><code> opt = prepareOptimizer
375433
loss = MeanErrors.meanSquareError
376434

377-
model = Models.make input d3 opt loss
435+
model = Models.make
436+
input
437+
d3
438+
opt
439+
loss
378440

379-
untrainedError = error model testX testY
380-
381-
epochs = 30
382-
(h, trained) = model.train [trainX] [trainY] epochs (ValidationFraction 0.1) 0
383-
trainedError = error trained testX testY
441+
untrainedError = error
442+
model
443+
testFeatures
444+
testLabels
445+
</code></pre></td><td>
446+
<p>Building model with its parameters:</p>
447+
<ul>
448+
<li> input and output layers, </li>
449+
<li> prepared optimizer, </li>
450+
<li> mean square error loss function. </li>
451+
</ul>
452+
<p><img src="Screenshots/model.png" alt></p>
453+
</td></tr>
454+
<tr><td>
455+
<pre data-role="codeBlock" data-info class="language-"><code> epochs = 30
456+
(h, trained) = model.train
457+
[trainFeatures]
458+
[trainLabels]
459+
epochs
460+
(ValidationFraction 0.1)
461+
0
462+
463+
trainedError = error
464+
trained
465+
testFeatures
466+
testLabels
384467

385468
None
386-
</code></pre><p><img src="Screenshots/main.png" alt></p>
469+
</code></pre></td><td>
470+
<p>Training model, and calculating its accuracy on the test dataset before and after a whole process.<br>
471+
<img src="Screenshots/train.png" alt></p>
472+
</td></tr>
473+
</tbody></table>
474+
<p>Evaluated model lets us observe the error ratio after training process, on the node named <code>trainedError</code>. We can compare it with the error ratio before training, displayed on the node named <code>untrainedError</code>.</p>
475+
<center>
387476
<p><img src="Screenshots/errorDiff.png" alt></p>
477+
</center>
478+
<p>And this is the appearance of <code>main</code> function.</p>
479+
<p><img src="Screenshots/main.png" alt></p>
388480

389481
</div>
390482

0 commit comments

Comments
 (0)