Linear Regression & Neuronal Network

A full-stack application for training and visualizing a linear regression model and a neuronal network using C++, Node.js, and React.

Overview

This project brings together high-performance C++ computing with a modern web application, making it ideal for both education and rapid prototyping. It features analytical Linear Regression and a customizable Feedforward Neural Network, both implemented in C++11 and seamlessly integrated with a Node.js/Express backend. The frontend, built with React, utilizes REST APIs and WebSockets to provide dynamic visualizations of data points, regression lines, training losses, and predictions in real-time.

app-gif

Tech Stack

C++ Engine

Backend Server

Frontend Client

Build & Development Tools

Getting Started

1. Clone the repository

git clone https://github.com/Nicolas2912/cpp-ml-react.git
cd cpp-ml-react

2. Build the C++ engine

cd cpp
make  # Creates linear_regression_app (or .exe on Windows)
cd ..

3. Run the backend server

cd server
npm install
npm start
# Server runs on http://localhost:3001

4. Launch the frontend client

# Open a new terminal
cd client
npm install
npm start
# Opens at http://localhost:3000

Usage

Data Input and Generation

Linear Regression Training

  1. Click ā€œTrain Linear Regressionā€
  2. Review results:
    • Slope and intercept coefficients
    • Mean Squared Error (MSE)
    • R² (coefficient of determination)
  3. Visualize the regression line on the scatter plot
  4. Predict new Y-values using the input box

Neural Network Training

  1. Configure your network:
    • Layer architecture (e.g., 1-4-1)
    • Learning rate
    • Number of training epochs
  2. Click ā€œTrain NN & Predictā€
  3. Monitor real-time training loss via WebSockets
  4. Review final predictions, MSE, and total training time

Interactive Features

Architecture & Components

C++ Engine (cpp/)

Backend Server (server/)

Frontend Client (client/)

Additional Components

Challenges

Throughout this project, I encountered three major challenges that pushed me to deepen my understanding of both C++ and full-stack JavaScript development. Below I describe each challenge, how I solved it in my actual implementation, why I chose that approach, and ways I might improve it in the future.



1. Bridging C++ and Node.js

I needed to run high-performance C++ code (both an analytical linear-regression solver and a custom neural network with backpropagation) from a Node.js backend without sacrificing productivity or maintainability.

Implemented Solution

Why This Approach

Future Improvements



2. Real-time Loss Streaming Over WebSockets

During neural-network training, I print loss after every epoch. For small datasets or many epochs, this floods the WebSocket channel and causes UI lag or even browser buffer overflows.

Implemented Solution

Why This Approach

Future Improvements



3. Correct Neural-Network and Backpropagation in C++

Writing a fully-featured backpropagation algorithm from scratch in C++ — complete with flexible layer sizes, safe matrix/vector arithmetic, and periodic loss reporting—is a nontrivial undertaking.

Implemented Solution

Why This Approach

Future Improvements



Tackling these challenges significantly improved my skill with low-level C++ (especially designing and debugging the backprop algorithm) and my ability to architect a full-stack pipeline that stitches native code into a smooth, real-time web experience.

What I learned

Building this end-to-end C++ ↔ Node.js pipeline and live-streaming neural-network demo taught me invaluable lessons in both low-level systems programming and high-level web architecture:

  1. Process Communication & Protocol Design

    • I now feel comfortable using child_process.spawn in Node.js to launch native binaries, pipe data into stdin, and read both stdout and stderr as streaming events.

    • Designing a minimal text protocol—printing key=value pairs line by line from C++ and parsing them in JavaScript via a single helper (parseCppLine)—proved both robust and easy to debug.

    • I learned to guard against edge cases: always ending the C++ stdin stream (cppProcess.stdin.end()), checking for res.headersSent before writing HTTP responses, and handling non-zero exit codes or parse failures gracefully.

  2. Real-Time Streaming Over WebSockets

    • Integrating the ws library on the server and a raw WebSocket in React gave me a front-row seat to the challenges of high-frequency updates.

    • I discovered that unthrottled epoch-by-epoch messages overwhelm the browser, so batching them in a useRef queue and using lodash.throttle (150 ms) to update React state is critical for smooth chart rendering.

    • Directly calling chartRef.current.update('none') on the Chart.js instance taught me how to decouple data ingestion from animated redraws, ensuring a snappy UI even under load.

    • Properly cleaning up on unmount—calling scheduleProcessLossBatch.cancel(), closing sockets in useEffect cleanup, and clearing batches—prevented subtle memory leaks and dangling callbacks.

  3. Implementing Backpropagation in C++

    • Writing a full NeuralNetwork class from scratch solidified my understanding of forward passes, storing pre-activation inputs (z) and post-activation outputs (a), and computing deltas layer by layer.

    • I sharpened my C++ skills: • Exception-safe parsing with std::strtod and thorough error checks in parseVector and parseLayerSizes. • Random weight initialization using std::mt19937 with scaled uniform distributions. • Timing code precisely with <chrono> to report training_time_ms.

    • Separating algorithm (train_for_epochs) from I/O (main_server.cpp) made both sides easier to test and maintain. I now appreciate the discipline of throwing on invalid matrix dimensions and catching every parsing exception at the top level.

  4. Full-Stack Architecture & Tooling

    • I gained confidence wiring together a JavaScript REST/WebSocket layer (Express + ws) with a React front end (react-chartjs-2, reactflow) and a C++ numerical engine. Clear separation of concerns kept each component focused—Node.js orchestrates processes and handles HTTP/WebSocket clients, React manages state and visuals, and C++ crunches numbers.

    • Detailed logging became my best friend: streaming chunks of C++ stdout/stderr to Node’s console, emitting structured logs (LR Train C++ Stdout Chunk, WebSocket message received), and surfacing errors early made multi-language debugging tractable.

    • I reinforced best practices around input validation (both in JS and C++), error propagation, and defensive cleanup—skills that will pay dividends in any large-scale system.

Next Steps

Improvements I’d Like to Make

Screenshots

LR-card NN-card Modeloverlay-card network-blueprint-ard UI-whitemode UI-darkmode

View on GitHub