Exploring Ruby’s Deep Learning Libraries: Building Neural Networks

In the vast landscape of programming languages for deep learning, Ruby might not be the first choice that comes to mind. However, with its user-friendly syntax and a growing ecosystem of libraries, Ruby is a viable option for building neural networks. In this blog, we will embark on a journey to explore Ruby’s deep learning capabilities and guide you through the process of building neural networks from scratch.

Exploring Ruby's Deep Learning Libraries: Building Neural Networks

1. Why Ruby for Deep Learning?

Before we dive into the practical aspects, let’s address the question: Why Ruby for deep learning? While languages like Python are more commonly associated with deep learning due to their extensive libraries and frameworks, Ruby offers several advantages worth considering:

1.1. Expressive Syntax

Ruby’s clean and expressive syntax makes it easy to read and write code. This can be a significant advantage when developing complex neural network architectures, as code readability is crucial for collaboration and maintenance.

1.2. Versatility

Ruby is a versatile language with a rich ecosystem of gems (libraries) that can be leveraged for deep learning. While it may not have as many dedicated deep learning frameworks as Python, Ruby’s flexibility allows you to integrate with other libraries and tools seamlessly.

1.3. Familiarity

For developers already familiar with Ruby, there’s a natural inclination to explore its capabilities in the realm of deep learning. Using a language you’re comfortable with can accelerate the learning process.

Now that we’ve established the rationale behind using Ruby, let’s delve into the practical aspects.

2. Setting up the Environment

Before we start building neural networks, it’s essential to set up a development environment. We’ll rely on two key Ruby gems: Numo and Daru.

2.1. Installing Numo

Numo is a numerical computing library for Ruby that provides a NumPy-like interface for array operations. To install Numo, you can use the following command:

gem install numo-narray

2.2. Installing Daru

Daru is a data manipulation and analysis library for Ruby, similar to Pandas in Python. It’s helpful for preprocessing and handling datasets. Install Daru with:

gem install daru

With Numo and Daru in place, we’re ready to begin our journey into deep learning.

3. Building a Neural Network from Scratch

In this section, we’ll build a simple feedforward neural network from scratch using Numo for array operations and Daru for data manipulation. Our goal is to create a basic neural network that can perform binary classification.

3.1. Data Preparation

Let’s start by preparing our dataset. For this example, we’ll generate synthetic data. In practice, you would replace this with your own dataset.

require 'daru'
require 'numo/narray'

# Generate synthetic data
num_samples = 100
input_data = Numo::NArray.rand(num_samples, 2)
labels = input_data.sum(1) > 1.0 ? 1 : 0

# Create a Daru DataFrame
df ={ feature1: input_data[0, true], feature2: input_data[1, true], label: labels })

# Split the data into training and testing sets
train_data, test_data = df.row[0..79], df.row[80..99]

In this code, we’ve generated random data with two features and assigned labels based on a simple condition. We’ve then created a Daru DataFrame and split it into training and testing sets.

3.2. Model Architecture

Now, let’s define our neural network architecture. Our network will have an input layer, one hidden layer, and an output layer. We’ll use sigmoid activation for the hidden layer and a sigmoid output for binary classification.

class NeuralNetwork
  def initialize(input_size, hidden_size)
    @input_size = input_size
    @hidden_size = hidden_size
    @output_size = 1
    # Initialize weights and biases
    @weights_input_hidden =, @hidden_size).rand
    @biases_hidden =
    @weights_hidden_output =, @output_size).rand
    @biases_output =

  def sigmoid(x)
    1 / (1 + Numo::NMath.exp(-x))

  def forward(input)
    # Input to hidden layer
    @hidden_input = + @biases_hidden
    @hidden_output = sigmoid(@hidden_input)

    # Hidden to output layer
    @output = + @biases_output

Here, we’ve defined the NeuralNetwork class with methods for initializing the network’s architecture, applying the sigmoid activation function, and performing the forward pass.

3.3. Training the Neural Network

To train our neural network, we’ll use the backpropagation algorithm. We’ll define a loss function (mean squared error) and update the weights and biases using gradient descent.

class NeuralNetwork
  # ... (previous code)

  def mean_squared_error(predictions, targets)
    ((predictions - targets)**2).mean

  def backward(input, target, learning_rate)
    # Compute loss
    loss = mean_squared_error(@output, target)

    # Backpropagation
    output_delta = 2 * (predictions - target)
    hidden_delta = * @hidden_output * (1 - @hidden_output)

    # Update weights and biases
    @weights_hidden_output -= * learning_rate
    @biases_output -= output_delta.sum * learning_rate
    @weights_input_hidden -= * learning_rate
    @biases_hidden -= hidden_delta.sum * learning_rate

In this code, we’ve added methods for computing the mean squared error loss, performing backpropagation, and updating the weights and biases.

3.4. Training Loop

Now, let’s put it all together in a training loop.

# Initialize the neural network
input_size = 2
hidden_size = 4
learning_rate = 0.01
epochs = 1000

nn =, hidden_size)

# Training loop
epochs.times do |epoch|
  train_data.each do |row|
    input = row[:feature1..:feature2].to_a
    target = Numo::NArray[row[:label]]
    # Forward pass
    predictions = nn.forward(input)
    # Backpropagation and update
    nn.backward(input, target, learning_rate)

  # Calculate and print the loss for this epoch
  train_loss = nn.mean_squared_error(nn.forward(train_data[:feature1..:feature2].to_a), train_data[:label].to_a)
  puts "Epoch #{epoch + 1}/#{epochs}, Loss: #{train_loss}"

In this training loop, we iterate through the dataset, compute predictions, perform backpropagation, and update the weights and biases for a specified number of epochs.

3.5. Testing the Model

Finally, let’s evaluate our trained neural network on the test data.

# Testing the model
test_loss = nn.mean_squared_error(nn.forward(test_data[:feature1..:feature2].to_a), test_data[:label].to_a)
puts "Test Loss: #{test_loss}"

This code calculates the mean squared error loss on the test data, providing an indication of the model’s performance.


In this blog, we’ve embarked on a journey to explore Ruby’s deep learning capabilities by building a neural network from scratch. While Ruby may not be as popular as Python for deep learning, its clean syntax, versatility, and a growing ecosystem of libraries make it a viable choice for certain projects.

As you delve deeper into the world of deep learning with Ruby, you’ll find that there are more libraries and tools at your disposal, such as the Numo-NumPy bridge for seamless integration with Python libraries. With dedication and creativity, you can harness the power of Ruby to develop robust neural networks and tackle a wide range of machine learning tasks.

Whether you’re a seasoned Rubyist or simply curious about expanding your programming horizons, exploring deep learning with Ruby can be a rewarding endeavor. So, go ahead, experiment, and build neural networks that pave the way for exciting AI applications in the Ruby ecosystem. Happy coding!

Previously at
Flag Argentina
time icon
Experienced software professional with a strong focus on Ruby. Over 10 years in software development, including B2B SaaS platforms and geolocation-based apps.