DEV Community

mostafa
mostafa

Posted on

Efficient Package for Machine Learning Models: From XGBoost to Neural Networks in an Optimized System

Introduction

In modern software development, parallel processing and system resource management are critical, especially when dealing with large, complex datasets. Using optimization methods is essential to reduce processing time and make efficient use of system resources. This article introduces a method that leverages Worker Threads, Bull Queue, and manual Garbage Collection in the NestJS framework to optimize parallel processing.

The primary goal of this article is to demonstrate how these techniques can be applied to perform parallel data processing and optimize memory usage in an AI system that utilizes various machine learning models such as XGBoost, Decision Tree, and Neural Networks. This package allows developers to efficiently run complex machine learning models and manage system resources effectively.

Utilizing Worker Threads

In complex applications that require parallel processing, Worker Threads offer an effective solution to distribute processing loads across multiple threads. This technique allows different processes to run simultaneously, reducing processing time and using system resources more efficiently.

In this article, Worker Threads are used for parallel processing of machine learning models. Each model runs independently on a dedicated Worker, enhancing efficiency and reducing processing time compared to single-threaded processing.

Using Bull Queue

Bull Queue manages processing queues and allocates tasks to different Workers. It intelligently distributes processes across Workers, enabling parallel execution and optimal system resource usage.

This technique is especially useful for processing large datasets or running complex models, as it efficiently executes tasks sequentially, preventing resource overload.

Activating Garbage Collection

In systems with complex processing, excessive memory consumption can reduce performance and even cause crashes. To address this, manual Garbage Collection is used in this article.

This method manually frees up unnecessary memory, preventing memory leaks. Garbage Collection is triggered in Node.js using the --expose-gc command, allowing manual GC calls.

Code Implementation:

Below is a sample code for implementing a generic package in NestJS, specifically designed for using various machine learning models such as XGBoost, Decision Tree, and Neural Networks:

import { Injectable } from '@nestjs/common';
import * as tf from '@tensorflow/tfjs-node';
import * as xgboost from 'xgboost';
import { DecisionTreeClassifier } from 'decision-tree-classifier';
import { SGDClassifier } from 'scikit-learn';
import * as process from 'process';

@Injectable()
export class AiService {
    private models: { [key: string]: any } = {};

    // Create different models generically
    createModel(modelType: string, modelOptions: any) {
        switch (modelType) {
            case 'XGBoost':
                this.models[modelType] = new xgboost.XGBClassifier(modelOptions);
                break;
            case 'DecisionTree':
                this.models[modelType] = new DecisionTreeClassifier(modelOptions);
                break;
            case 'NeuralNetwork':
                this.models[modelType] = tf.sequential(); // Neural network model
                break;
            case 'SGDClassifier': // Online learning model
                this.models[modelType] = new SGDClassifier(modelOptions);
                break;
            default:
                throw new Error('Model type not supported');
        }
    }

    // Train the model
    async trainModel(modelType: string, data: number[][], labels: number[], batchSize: number = 32) {
        const model = this.models[modelType];
        if (!model) {
            throw new Error('Model not created');
        }
        if (modelType === 'XGBoost' || modelType === 'DecisionTree') {
            await model.fit(data, labels);
        } else if (modelType === 'NeuralNetwork') {
            const xs = tf.tensor(data);
            const ys = tf.tensor(labels);
            model.add(tf.layers.dense({ units: 10, inputShape: [data[0].length] }));
            model.compile({ optimizer: 'adam', loss: 'meanSquaredError' });
            await model.fit(xs, ys, { epochs: 10, batchSize: batchSize });
        } else if (modelType === 'SGDClassifier') {
            await model.fit_one_batch(data, labels);
        }
    }

    // Predict with the model
    async predict(modelType: string, data: number[][], batchSize: number = 32) {
        const model = this.models[modelType];
        if (!model) {
            throw new Error('Model not created');
        }
        if (modelType === 'XGBoost' || modelType === 'DecisionTree' || modelType === 'SGDClassifier') {
            return await model.predict(data);
        } else if (modelType === 'NeuralNetwork') {
            const xs = tf.tensor(data);
            return model.predict(xs).dataSync();
        }
    }

    // Manage manual Garbage Collection
    private manageGarbageCollection() {
        const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024; // Memory usage in MB
        console.log(`Memory Usage: ${memoryUsage.toFixed(2)} MB`);
        if (memoryUsage > 500) { // Adjust memory threshold as needed
            console.log('Memory usage high, triggering GC...');
            global.gc(); // Manual GC call
        }
    }

    // Delete models to free resources
    deleteModel(modelType: string) {
        delete this.models[modelType];
        this.manageGarbageCollection(); // GC call after deleting the model
    }
}
Enter fullscreen mode Exit fullscreen mode

Package Usage Instructions

  1. Model Creation:

To create models, specify the model type and configuration options:

   // Create XGBoost model
   this.aiService.createModel('XGBoost', { max_depth: 6, learning_rate: 0.1 });

   // Create Decision Tree model
   this.aiService.createModel('DecisionTree', { max_depth: 10 });

   // Create Neural Network model
   this.aiService.createModel('NeuralNetwork', {});
Enter fullscreen mode Exit fullscreen mode
  1. Model Training:

After creating models, you can train them:

   await this.aiService.trainModel('XGBoost', data, labels);
   await this.aiService.trainModel('DecisionTree', data, labels);
   await this.aiService.trainModel('NeuralNetwork', data, labels);
Enter fullscreen mode Exit fullscreen mode
  1. Making Predictions:

To make predictions with the models:

   const xgboostPredictions = await this.aiService.predict('XGBoost', testData);
   const decisionTreePredictions = await this.aiService.predict('DecisionTree', testData);
   const neuralNetworkPredictions = await this.aiService.predict('NeuralNetwork', testData);
Enter fullscreen mode Exit fullscreen mode
  1. Deleting Models:

When a model is no longer needed, you can delete it:

   this.aiService.deleteModel('XGBoost');
   this.aiService.deleteModel('DecisionTree');
   this.aiService.deleteModel('NeuralNetwork');
Enter fullscreen mode Exit fullscreen mode

Conclusion

This article examined techniques like Worker Threads, Bull Queue, and Garbage Collection to optimize parallel processing and resource management in AI systems. These methods significantly improve system performance, especially when dealing with large datasets. By using these techniques, parallel processing becomes efficient, and memory usage is minimized.

These methods not only optimize resources but also enhance scalability for larger systems. This package can be effective in small to medium-scale systems (1,000 to 10,000 concurrent users). For larger scales, further resource optimization and improved scalability are required.

Top comments (0)