RUNge Kutta Optimizer (RUN)



RUNge Kutta Optimizer (RUN) একটি গাণিতিক পদ্ধতি যা একটি সিস্টেমের সমাধান সঠিকভাবে অনুমান করতে ব্যবহৃত হয়। এই পদ্ধতি সাধারণত মৌলিক গাণিতিক সমস্যা সমাধানে ব্যবহার করা হয়, তবে এটি অপটিমাইজেশন সমস্যার ক্ষেত্রেও কার্যকরী। এটি মূলত একটি ইটারেটিভ পদ্ধতি, যেখানে একটি সিস্টেমের বিভিন্ন ধাপের মাধ্যমে সমাধান বের করা হয়।

ধরা যাক, তুমি একটি নদী পার করতে চাও। নদীটি সরল নয়, নানা বাঁক, স্রোত এবং প্রতিবন্ধকতা রয়েছে। তুমি যদি প্রতিটি বাঁক, স্রোত এবং বাধা জানো, তবে সবচেয়ে সঠিক পথে নদী পার করতে পারবে। তবে, যদি শুধু এক বা দুটি পথ দেখা যায়, তখন সঠিক পথ অনুসন্ধান করা কঠিন হতে পারে। RUNge Kutta Optimizer এই পথে কাজ করে। এটি বিভিন্ন সম্ভাব্য পথ বিশ্লেষণ করে এবং সঠিকভাবে সেরা পথ বেছে নিতে সাহায্য করে, যাতে তুমি নদী পার করতে পারো এবং বাধা সঠিকভাবে অতিক্রম করতে পারো।

RUNge Kutta Optimizer একটি ইটারেটিভ পদ্ধতি, যেখানে একাধিক স্টেপে গাণিতিক সমাধান আপডেট করা হয়। এটি ৪র্থ অর্ডার (4th-order) Runge-Kutta পদ্ধতিতে সাধারণত ব্যবহৃত হয়, যা সিস্টেমের ভবিষ্যত অবস্থা নির্ধারণে সাহায্য করে।

ধাপগুলো হলো:

  1. প্রথমে, সিস্টেমের বর্তমান অবস্থান থেকে একটি অনুমান করা হয়।

  2. পরবর্তী পদক্ষেপের জন্য বিভিন্ন ক্যালকুলেশন (কিন্তু পূর্ববর্তী স্টেপের সাহায্যে) তৈরি করা হয়।

  3. তারপরে, একাধিক ধাপের গাণিতিক ফলাফল একত্রিত করে সঠিক সমাধান পাওয়া যায়।

এতে ৪টি ধাপ (k1, k2, k3, k4) গ্রহণ করা হয়, যার মাধ্যমে সিস্টেমের আচরণ পূর্বাভাস করা হয়।

Runge-Kutta পদ্ধতিতে সাধারণত একটি সাধারণ গাণিতিক সমীকরণ ব্যবহার করা হয়:

yn+1=yn+h6(k1+2k2+2k3+k4)y_{n+1} = y_n + \frac{h}{6} \left( k_1 + 2k_2 + 2k_3 + k_4 \right)

এখানে:

  • yny_n হল পূর্ববর্তী অবস্থান (current position),

  • hh হল স্টেপ সাইজ (step size),

  • k1,k2,k3,k4k_1, k_2, k_3, k_4 হল চারটি ক্যালকুলেটেড ধাপের মান, যা নিম্নরূপ হয়:

k1=hf(xn,yn)k_1 = h \cdot f(x_n, y_n)
k2=hf(xn+h2,yn+k12)k_2 = h \cdot f(x_n + \frac{h}{2}, y_n + \frac{k_1}{2})
k3=hf(xn+h2,yn+k22)k_3 = h \cdot f(x_n + \frac{h}{2}, y_n + \frac{k_2}{2})
k4=hf(xn+h,yn+k3)k_4 = h \cdot f(x_n + h, y_n + k_3)

এখানে, f(x,y)f(x, y) হল সেই ফাংশন যা সিস্টেমের গতির বা পরিবর্তনের আচরণ বর্ণনা করে।


ধরা যাক, আমরা একটি সাধারণ গণনা করতে চাই যা গতির সমীকরণের মাধ্যমে একটি বস্তুর গতির পরিবর্তন দেখায়। গতি vv এর সাথে সময় tt এর সম্পর্কের সমীকরণ হতে পারে:

dvdt=kv\frac{dv}{dt} = -k \cdot v

এখানে, kk হল একটি ধ্রুবক, এবং vv হল গতির মান। RUNge Kutta Optimizer এই সমীকরণের সমাধান করতে সাহায্য করবে, যেখানে সময় tt এবং গতি vv এর মান পর্যায়ক্রমে আপডেট করা হবে।

ধরা যাক, আমাদের একটি নির্দিষ্ট বিন্দুতে একটি ধ্রুবক গতির গতির পরিবর্তন f(t,v)=kvf(t, v) = -k \cdot v জানতে হবে এবং RUNge Kutta পদ্ধতির সাহায্যে পরবর্তী সময়ের জন্য গতি নির্ধারণ করতে হবে।

নির্দিষ্ট একটি স্টেপ সাইজ h=0.1h = 0.1 দিয়ে, আমরা প্রথমে k1,k2,k3,k4k_1, k_2, k_3, k_4 গণনা করব এবং তারপর সঠিক মান পাব।


Python Code for ANN with RUNge Kutta Optimizer:

import numpy as np

import matplotlib.pyplot as plt


# Sigmoid activation function

def sigmoid(x):

    return 1 / (1 + np.exp(-x))


# Derivative of the sigmoid function (for backpropagation)

def sigmoid_derivative(x):

    return x * (1 - x)


# Neural network architecture (simple 1-hidden-layer network)

class NeuralNetwork:

    def __init__(self, input_size, hidden_size, output_size):

        # Initialize weights and biases

        self.input_size = input_size

        self.hidden_size = hidden_size

        self.output_size = output_size

        

        # Weights and biases initialization (random)

        self.weights_input_hidden = np.random.randn(input_size, hidden_size)

        self.weights_hidden_output = np.random.randn(hidden_size, output_size)

        self.bias_hidden = np.random.randn(hidden_size)

        self.bias_output = np.random.randn(output_size)

    

    def forward(self, X):

        # Forward propagation

        self.hidden_input = np.dot(X, self.weights_input_hidden) + self.bias_hidden

        self.hidden_output = sigmoid(self.hidden_input)

        self.final_input = np.dot(self.hidden_output, self.weights_hidden_output) + self.bias_output

        self.final_output = sigmoid(self.final_input)

        return self.final_output

    

    def compute_loss(self, y_pred, y_true):

        # Mean squared error loss function

        return np.mean((y_true - y_pred) ** 2)


# Runge Kutta Optimizer for Neural Network

def runge_kutta_optimizer_ann(nn, X_train, y_train, step_size, num_iterations):

    # Training the neural network using Runge-Kutta optimization

    for iteration in range(num_iterations):

        # Perform forward pass

        y_pred = nn.forward(X_train)

        

        # Compute loss (mean squared error)

        loss = nn.compute_loss(y_pred, y_train)

        

        # Compute gradients using backpropagation (manual for simplicity)

        d_loss = 2 * (y_pred - y_train) / len(y_train)

        d_output = d_loss * sigmoid_derivative(y_pred)

        d_hidden = np.dot(d_output, nn.weights_hidden_output.T) * sigmoid_derivative(nn.hidden_output)

        

        # Gradients of weights and biases

        grad_w_input_hidden = np.dot(X_train.T, d_hidden)

        grad_w_hidden_output = np.dot(nn.hidden_output.T, d_output)

        grad_b_hidden = np.sum(d_hidden, axis=0)

        grad_b_output = np.sum(d_output, axis=0)


        # Runge-Kutta method: Apply gradient update

        k1 = step_size * grad_w_input_hidden

        k2 = step_size * (grad_w_input_hidden + 0.5 * k1)

        k3 = step_size * (grad_w_input_hidden + 0.5 * k2)

        k4 = step_size * (grad_w_input_hidden + k3)


        # Update weights using 4th-order Runge-Kutta formula

        nn.weights_input_hidden -= (k1 + 2 * k2 + 2 * k3 + k4) / 6

        nn.weights_hidden_output -= (step_size * grad_w_hidden_output)

        nn.bias_hidden -= (step_size * grad_b_hidden)

        nn.bias_output -= (step_size * grad_b_output)

        

        # Print the loss at each iteration

        if iteration % 100 == 0:

            print(f"Iteration: {iteration}, Loss: {loss}")


    return nn


# Generate dummy training data (simple example: XOR problem)

X_train = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])

y_train = np.array([[0], [1], [1], [0]])


# Initialize neural network with 2 input nodes, 4 hidden nodes, and 1 output node

nn = NeuralNetwork(input_size=2, hidden_size=4, output_size=1)


# Set hyperparameters for the optimizer

step_size = 0.01

num_iterations = 1000


# Train the neural network using Runge-Kutta optimizer

nn_trained = runge_kutta_optimizer_ann(nn, X_train, y_train, step_size, num_iterations)


# Test the trained network

y_pred = nn_trained.forward(X_train)

print("\nFinal Predictions:")

print(y_pred)


# Plotting the loss curve

loss_values = []

for iteration in range(num_iterations):

    y_pred = nn.forward(X_train)

    loss = nn.compute_loss(y_pred, y_train)

    loss_values.append(loss)


plt.plot(loss_values)

plt.xlabel('Iterations')

plt.ylabel('Loss')

plt.title('Loss Curve')

plt.show()


মন্তব্যসমূহ