This repository contains an implementation of a Long Short-Term Memory (LSTM) neural network written from scratch in C++, as described in my blog post "I Built an LSTM from Scratch in C++. Here's What I Learned."
This project was created to understand the inner workings of LSTM networks at a fundamental level, without relying on machine learning frameworks or libraries.
- Complete LSTM cell implementation with forget, input, and output gates
- Backpropagation through time (BPTT) with gradient clipping
- Simple network structure with configurable hyperparameters
- Example usage with sine wave prediction
- C++11 or higher
- Standard library only (no external dependencies)
struct DataSample {
vector<double> features;
double target;
};The LSTM cell implements the core functionality:
- Forward pass with all gates (forget, input, output)
- Backward pass with proper gradient computation
- Weight updates using gradient descent
- Configurable input size, hidden size, and output size
- Hyperparameters tunable via constructor (learning rate, epochs)
- Simple prediction interface
// Create and configure the LSTM network
int input_size = 1;
int hidden_size = 32;
int output_size = 1;
double learning_rate = 0.01;
int epochs = 50;
LSTMNetwork lstm(input_size, hidden_size, output_size, learning_rate, epochs);
// Create training data
vector<DataSample> training_data;
/* Populate with your data */
// Train the network
double final_loss = lstm.train(training_data);
// Make predictions
double prediction = lstm.predict(input_features);When compiling the code, make sure to include the <tuple> header:
#include <vector>
#include <cmath>
#include <random>
#include <iostream>
#include <algorithm>
#include <tuple> // Required for std::tie and tuple returns-
Proper Weight Initialization: Small random values are crucial to prevent vanishing/exploding gradients.
-
Gradient Clipping: Essential for stable training, implemented as:
double clip(double value, double min_value, double max_value) { return max(min_value, min(value, max_value)); }
-
Hyperparameter Tuning: After experimentation, these values worked well:
- Learning rate: 0.01
- Hidden size: 32
- Number of epochs: 50
-
Memory Management: Careful tracking of intermediate values for backpropagation.
- Bidirectional LSTM support
- Different optimization algorithms
- Dropout layers
- Batch normalization
- Mini-batch training
MIT
- Website: anudeepadi.me
- LinkedIn: adirajuadi
- GitHub: anudeepadi