Jump to content
Sign in to follow this  
lynkfs

no-code

Recommended Posts

Setting up a blog in WordPress is a no-brainer of course.

Setting one up in Smart is pretty easy too. This one repurposes a treeview as a vertical collapsible menu and a series of Google docs in an iFrame. Using Google docs is a bit of a short-cut but it does provide the basics in a single package : perfect formatting capabilities, editing online and authorisation for editing source, or able to comment, or viewing for anyone.

As for the subject (a no-code/lo-code framework) this obviously is unfinished ('intro' and the beginning of 'framework' entries only). I may do some more work on it when time permits. If you have thoughts on the subject and make it a collaborative effort then let me know.

By the way, the form under 'Design' is a proof of concept for using the jsPlumb library (included in Smart in the libraries directory). A very useful library, check it out. Panels are draggable, links are connectable by mouse and touch etc...

Share this post


Link to post
Share on other sites

I had an idea of how to approach the concept of a 'no-code' / 'lo-code' framework, which involved a modelling exercise done from different viewpoints. The idea was to base this on a graph-based domain model and some defined aspect-models derived from that.

The following link contains

  • bit of a write-up : preamble, framework basics, domain model, data model, process model, beginnings of workflow model. Event-, processor- and objectives model unfinished.
  • demo showing how the design efforts of these models might look like (in broad terms)
  • demo of how the generated app from these models could look like

Sometimes an idea can only be validated by making it work. Or if it doesn't work out then obviously it was a bad idea to begin with.

Not making a final call yet as I haven't finished this proof of concept (only about half ready), but so far no reason to abandon.

Comments welcome

 

Share this post


Link to post
Share on other sites

As always, your demos are quite interesting, looking forward to next upate.

On the matter itself, there's been (or are) dozen of solutions that offer some kind of noCode data building and they generally work well unless you need something specific and that's the main weak point of such solution. NoCode solution can solve business problems to a degree, but they do tend to become complex as well. And they do require a knowlegable person to set it up and maintain it.

Share this post


Link to post
Share on other sites

Part of the nocode-locode framework is that it features general purpose functions where coding is replaced by neural network based supervised learning (training by example).

To test this out I selected 4 neural network frameworks :

  • Brain.js
  • Synaptic
  • TensorFlow
  • the neural network component in my own shoestring/native framework

The next code fragments implement these neural networks and train them to produce output similar to the XOR function below : 

function TForm1.&XOR(a,b: integer): integer;
begin
  result := (a xor b);
end;

//test XOR
console.log('0 xor 0 = ' + inttostr(&XOR(0,0)));     //0
console.log('0 xor 1 = ' + inttostr(&XOR(0,1)));     //1
console.log('1 xor 0 = ' + inttostr(&XOR(1,0)));     //1
console.log('1 xor 1 = ' + inttostr(&XOR(1,1)));     //0


Brain:
 

  Button1.OnClick := procedure(sender:TObject)
  begin
    //add the Brain.NeuralNetwork unit from the Libraries/Brain directory

    var TrainingData: array of JNeuralNetworkTrainData;

    // provide some example data (XOR function)
    for var x := 0 to 1 do
      for var y := 0 to 1 do
      begin
        var data: JNeuralNetworkTrainData;
        data.input := [x, y];
        data.output := [x xor y];
        TrainingData.Add(data);
      end;

    // create neural network
    var net := JNeuralNetwork.Create;

    // train data
    net.train(TrainingData);

    // run
    for var x := 0 to 1 do
      for var y := 0 to 1 do
        Console.log(IntToStr(x) + ' XOR ' + IntToStr(y) + ': ' +
          FloatToStr(net.run([x, y])[0]) + ' - should be ' + IntToStr(x xor y));

  end;

output

0 XOR 0: 0.04838375911771282 - should be 0 
0 XOR 1: 0.9341364376522593 - should be 1 
1 XOR 0: 0.9336809386145357 - should be 1 
1 XOR 1: 0.09378495233984371 - should be 0 

 

//Synaptic
 

  Button2.OnClick := procedure(sender:TObject)
  begin
    var Script := document.createElement('script');
    Script.src := 'https://cdnjs.cloudflare.com/ajax/libs/synaptic/1.1.4/synaptic.min.js';
    document.head.appendChild(Script);
    Script.onload := procedure
    begin
      console.log('Synaptic loaded');

      //define layers
      var inputLayer  : variant := new JObject;
      var hiddenLayer : variant := new JObject;
      var outputLayer : variant := new JObject;
      asm
        @inputLayer  = new synaptic.Layer(2);
        @hiddenLayer = new synaptic.Layer(3);
        @outputLayer = new synaptic.Layer(1);
      end;

      //connect layers together
      inputLayer.project(hiddenLayer);
      hiddenLayer.project(outputLayer);

      //create network
      var myNetwork   : variant := new JObject;
      asm
        @myNetwork = new synaptic.Network({
          input: @inputLayer,
          hidden: [@hiddenLayer],
          output: @outputLayer
        });
      end;

      // train the network - learn XOR
      var learningRate = 0.3;

      for var i := 0 to 20000 do begin
        // 0,0 => 0
        myNetwork.activate([0,0]);
        myNetwork.propagate(learningRate, [0]);
        // 0,1 => 1
        myNetwork.activate([0,1]);
        myNetwork.propagate(learningRate, [1]);
        // 1,0 => 1
        myNetwork.activate([1,0]);
        myNetwork.propagate(learningRate, [1]);
        // 1,1 => 0
        myNetwork.activate([1,1]);
        myNetwork.propagate(learningRate, [0]);
      end;

      //test
      for var x := 0 to 1 do
        for var y := 0 to 1 do
          Console.log(IntToStr(x) + ' XOR ' + IntToStr(y) + ': ' +
            FloatToStr(myNetwork.activate([x, y])) + ' - should be ' + IntToStr(x xor y));

    end;
  end;

output

Synaptic loaded 
0 XOR 0: 0.00006318713317389802 - should be 0 
0 XOR 1: 0.9995993524844716 - should be 1 
1 XOR 0: 0.9996540649472183 - should be 1
1 XOR 1: 0.0006170002563084644 - should be 0 

 

//TensorFlow
 

  Button3.OnClick := procedure(sender:TObject)
  begin
    var Script := document.createElement('script');
    Script.src := 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.9.1';
    document.head.appendChild(Script);
    Script.onload := procedure
    begin
      console.log('TensorFlow loaded');

      //add to the interface section : var tf external 'tf' : variant;
      var model := tf.sequential();

      // 2 layers
      model.add(tf.layers.dense(class units = 10; activation = 'sigmoid'; inputShape : array[0..0] of integer = [2];  end));
      model.add(tf.layers.dense(class units = 1;  activation = 'sigmoid'; inputShape : array[0..0] of integer = [10]; end));

      //compile
      var learningRate := 1;

      //compile
      model.compile(class
        loss = 'meanSquaredError';
        //optimizer = 'rmsprop';
        optimizer : variant = tf.train.sgd(learningRate);
      end);

      // XOR data x values.
      var xs = tf.tensor2d([[0,0],[0,1],[1,0],[1,1]]);

      // XOR data y values.
      var ys = tf.tensor2d([[0],[1],[1],[0]]);

      //model.fit (training) produces a promise (where testing is done)

      model.fit(xs, ys, class epochs = 1500; end).then(
        procedure(result:variant)
        begin
          console.log('testing...');

          console.log('0 XOR 0 : ' + model.predict(tf.tensor2d([0, 0], [1, 2])).dataSync() +
                      ' should be 0');
          console.log('0 XOR 1 : ' + model.predict(tf.tensor2d([0, 1], [1, 2])).dataSync() +
                      ' should be 1');
          console.log('1 XOR 0 : ' + model.predict(tf.tensor2d([1, 0], [1, 2])).dataSync() +
                      ' should be 1');
          console.log('1 XOR 1 : ' + model.predict(tf.tensor2d([1, 1], [1, 2])).dataSync() +
                      ' should be 0');
      end);
    end;
  end;

output

TensorFlow loaded
testing...
0 XOR 0 : 0.004379332065582275 should be 0
0 XOR 1 : 0.9998316764831543 should be 1
1 XOR 0 : 0.9999105930328369 should be 1
1 XOR 1 : 0.00010051509161712602 should be 0

 

//ShoeString
 

Button4.OnClick := procedure(sender:TObject)
  begin
    console.log('ShoeString started');

  //Init neural network
    var MyNetwork : JW3NeuralNet := JW3NeuralNet.Create;
    //
    MyNetwork.AddLayer  (2, 'Input',  '');            // input layer. input layers have no activation function
    MyNetwork.AddLayer  (5, 'Hidden', 'Sigmoid');     // first hidden layer, with sigmoid activation
    MyNetwork.AddLayer  (2, 'Output', 'Sigmoid');     // output layer, with sigmoid activation
    //
    MyNetwork.SeedNetwork;   //initialise with random values

    // provide some input (XOR function)
    for var iter := 0 to 1000 do
      for var x := 0 to 1 do
        for var y := 0 to 1 do
        begin
          var data: JNeuralNetworkTrainData;
          data.input := [x, y];
          if (x xor y) = 0 then
            data.output := [0.99, 0.01] else
            data.output := [0.01, 0.99];
          MyNetwork.AddTrainingData(data.input, data.output);
        end;

  // train
    MyNetwork.LearningRate := 0.2;
    MyNetwork.TrainingSplit := 10;       //split trainingset randomly: 10% for testing, 90% training

    For var i := 1 to 5 do begin      //every iteration is an epoch
      //console.log('Epoch ' + inttostr(i) + '/5');
      MyNetwork.Train;
    end;

  // test
    MyNetwork.Test;

    for var q := 0 to 10 do begin  //MyNetwork.ResultA.NrRows -1 do begin  //for all test records
      var a := inttostr(GetMaxIndex(q, MyNetwork.ResultB));     //correct outcome
      var b := inttostr(GetMaxIndex(q, MyNetwork.ResultC));     //computed outcome

      Console.log(MyNetwork.ResultA.GetValue(q,0) + ' XOR ' +
                  MyNetwork.ResultA.GetValue(q,1) + ': ' +
                  MyNetwork.ResultC.GetValue(q,1) + ' - should be ' + a);
    end;
  end;

output

ShoeString started
0 XOR 0: 0.05773579608792857 - should be 0
1 XOR 0: 0.9403986284540853 - should be 1
0 XOR 1: 0.9524118223319257 - should be 1
1 XOR 1: 0.05424365311145005 - should be 0

 

All these frameworks work well and produce the correct results.

Brain, Synaptic and ShoeString are sort of similar, while TensorFlow is the odd one out.

TensorFlow requires the most coding and certainly takes the longest to execute. It probably is more geared towards deep learning applications rather than simple neural networks.

The winner for this purpose looks to be Brain.js   It is the oldest framework of the 4, is not actively maintained anymore but does a good job with almost no coding required and fast execution.

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×