quaintitative

I write about my quantitative explorations in visualisation, data science, machine and deep learning here, as well as other random musings.

For more about me and my other interests, visit playgrd or socials below


Categories
Subscribe

Logistic Regression Classification in plain ole Javascript

I thought it would be fun to try to code a logistic regression model in plain ole Javascript, with no machine learning libraries.

I somehow went down a rabbit-hole with the visualisation though, and ended up doing a dashboard in p5.js to visualise the data generation, training and prediction process straight in the client/browser.

Before we go through the code, you can play around with the dashboard here.

A quick orientation:

The part of the code relating to the logistic regression model is the focus of this post, so I will zoom in on that. The visualisation is done using the p5.js library (instead of d3.js just for a change).

First, the random data is generated with a a simple loop and p5.js’ random function.

    function generateData(total,boundary,upper,lower) {
    for (var i=0; i<total; i++){
        var X1, X2, Y;

        var cutoff = P5.random()*(upper-lower)+lower;

        if (i<=boundary){
            X1 = P5.random(lower,cutoff*0.9);
            X2 = P5.random(lower,cutoff*0.9);
            Y = 0;
        } else if (i>boundary){
            X1 = P5.random(cutoff*1.1,upper);
            X2 = P5.random(cutoff*1.1,upper);
            Y = 1;
        }

        data.push({x1:X1, x2:X2, y:Y});

    }

    var progresspercent = 0;

        $('.progress-bar').css('width', progresspercent+'%').attr('aria-valuenow', progresspercent);
    // console.log(data);
}

We then write the function for training.

function train(epochs, alpha){

    console.log(data);

    errors =[];
    A = 0.0;
    B = 0.0;
    C = 0.0;

    var count =0;
    for (var i=0; i<epochs; i++){
        var error;
        
        data.forEach(d=>{

            var predY;
            var func;
            func = A*d.x1/100+B*d.x2/100+C;
            predY = 1/(1+Math.exp(-func));
            error = predY - d.y;
            tempA = A;
            tempB = B;
            tempC = C;

            A = tempA + alpha*-error*predY*(1-predY)*d.x1/100;
            B = tempB + alpha*-error*predY*(1-predY)*d.x2/100;
            C = tempC + alpha*-error*predY*(1-predY)*1.0;
            
            // errors.push({error:error, iteration:count});
            // count++;
        })

        console.log('A', A, 'B', B, 'C', C);
        console.log('Error', error);
        errors.push({error:error, epoch:i});

        var accuracy = 1+Math.round(error*100)/100;
        $('#accuracy').text(accuracy);


        var progresspercent = 100*i/500;

        $('.progress-bar').css('width', progresspercent+'%').attr('aria-valuenow', progresspercent);
    }

    console.log(errors);
    

}

It’s pretty straight-forward. We declare 3 variables A, B, and C. Then we loop through the dataset, insert the x1 and x2 values in the logistic regression equation, get the predicted value and compare against the actual y. We then use that to update A, B, and C, and keep track of the errors at each epoch.

We also compute the accuracy shown in the browser and the progress bar.

The final piece is the predict function.

function predict(x1,x2){

    var predY;
    var func;
    var out;
    func = A*x1/100+B*x2/100+C;
    predY = 1/(1+Math.exp(-func));

    if(predY>0.5){out=1}
    else if (predY<0.5){out=0};

    return out;
}

We are basically plugging in the final A, B, and C values into the logistic regression equation and using it to predict the class of a point.

And that’s it. The full code is available here.


Articles

AI and UIs
Listing NFTs
Extracting and Processing Wikidata datasets
Extracting and Processing Google Trends data
Extracting and Processing Reddit datasets from PushShift
Extracting and Processing GDELT GKG datasets from BigQuery
Some notes relating to Machine Learning
Some notes relating to Python
Using CCapture.js library with p5.js and three.js
Introduction to PoseNet with three.js
Topic Modelling
Three.js Series - Manipulating vertices in three.js
Three.js Series - Music and three.js
Three.js Series - Simple primer on three.js
HTML Scraping 101
(Almost) The Simplest Server Ever
Tweening in p5.js
Logistic Regression Classification in plain ole Javascript
Introduction to Machine Learning Right Inside the Browser
Nature and Math - Particle Swarm Optimisation
Growing a network garden in D3
Data Analytics with Blender
The Nature of Code Ported to Three.js
Primer on Generative Art in Blender
How normal are you? Checking distributional assumptions.
Monte Carlo Simulation of Value at Risk in Python
Measuring Expected Shortfall in Python
Style Transfer X Generative Art
Measuring Market Risk in Python
Simple charts | crossfilter.js and dc.js
d3.js vs. p5.js for visualisation
Portfolio Optimisation with Tensorflow and D3 Dashboard
Setting Up a Data Lab Environment - Part 6
Setting Up a Data Lab Environment - Part 5
Setting Up a Data Lab Environment - Part 4
Setting Up a Data Lab Environment - Part 3
Setting Up a Data Lab Environment - Part 2
Setting Up a Data Lab Environment - Part 1
Generating a Strange Attractor in three.js
(Almost) All the Most Common Machine Learning Algorithms in Javascript
3 Days of Hand Coding Visualisations - Day 3
3 Days of Hand Coding Visualisations - Day 2
3 Days of Hand Coding Visualisations - Day 1
3 Days of Hand Coding Visualisations - Introduction