[java] Apache Commons Math를 사용한 나이브 베이즈 알고리즘 구현 방법

나이브 베이즈 알고리즘은 기계 학습 및 자연어 처리 분야에서 널리 사용되는 분류 알고리즘입니다. 이 알고리즘은 변수 간 독립성을 가정하는 간단한 모델로서, 주어진 입력에 대해 가장 가능성이 높은 클래스를 예측하는 데 사용됩니다.

Apache Commons Math는 Java에서 수치 계산과 통계 처리를 위한 유용한 라이브러리입니다. 이 라이브러리를 사용하여 나이브 베이즈 알고리즘을 구현하려면 아래의 단계를 따릅니다.

1. 종속성 추가하기

먼저 Maven 또는 Gradle을 사용하여 Apache Commons Math를 프로젝트에 추가해야 합니다.

Maven

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-math3</artifactId>
    <version>3.6.1</version>
</dependency>

Gradle

implementation 'org.apache.commons:commons-math3:3.6.1'

2. 데이터 준비하기

나이브 베이즈 알고리즘을 구현하기 위해 분류해야 할 클래스와 관련된 데이터셋을 준비해야 합니다. 각 데이터 포인트는 클래스와 관련된 여러 변수를 포함해야 합니다.

3. 나이브 베이즈 분류기 구현하기

나이브 베이즈 분류기를 구현하기 위해 아래의 코드를 참고하세요.

import org.apache.commons.math3.distribution.EnumeratedIntegerDistribution;
import org.apache.commons.math3.distribution.MultivariateRealDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.linear.ArrayRealVector;
import org.apache.commons.math3.linear.RealVector;
import org.apache.commons.math3.util.Pair;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class NaiveBayesClassifier {

    private final Map<Integer, MultivariateRealDistribution> featureDistributions;
    private final EnumeratedIntegerDistribution classDistribution;

    public NaiveBayesClassifier(Map<Integer, List<RealVector>> trainingData, List<Integer> classes) {
        int numFeatures = trainingData.keySet().size();
        this.featureDistributions = new HashMap<>();
        
        // Calculate mean and variance for each feature in each class
        for (int i = 0; i < numFeatures; i++) {
            List<double[]> featureData = new ArrayList<>();
            
            for (int c : classes) {
                List<RealVector> classData = trainingData.get(c);
                double[] values = new double[classData.size()];
                for (int j = 0; j < classData.size(); j++) {
                    values[j] = classData.get(j).getEntry(i);
                }
                featureData.add(values);
            }
            NormalDistribution distribution = new NormalDistribution();
            distribution.fit(featureData);
            this.featureDistributions.put(i, distribution);
        }
        
        // Calculate class distribution
        double[] classProbabilities = new double[classes.size()];
        
        for (int i = 0; i < classes.size(); i++) {
            classProbabilities[i] = trainingData.get(classes.get(i)).size();
        }
        this.classDistribution = new EnumeratedIntegerDistribution(classes.stream().mapToInt(Integer::intValue).toArray(),
                classProbabilities);
    }

    public int classify(RealVector inputVector) {
        List<Pair<Integer, Double>> probabilities = new ArrayList<>();
        
        // Calculate log-likelihood of each class
        for (Integer c : classDistribution.getSupport()) {
            double logLikelihood = 0;
            for (int i = 0; i < inputVector.getDimension(); i++) {
                double featureValue = inputVector.getEntry(i);
                double featureLikelihood = featureDistributions.get(i).logDensity(featureValue);
                logLikelihood += featureLikelihood;
            }
            
            double classProbability = classDistribution.probability(c);
            double classPosterior = Math.log(classProbability) + logLikelihood;
            probabilities.add(new Pair<>(c, classPosterior));
        }
        
        // Find maximum probability class
        int maxClass = probabilities.stream()
                .max((a, b) -> Double.compare(a.getValue(), b.getValue()))
                .orElseThrow(RuntimeException::new)
                .getKey();
        
        return maxClass;
    }
}

4. 사용하기

나이브 베이즈 분류기를 사용하여 예측을 수행하려면 아래의 코드를 참고하세요.

import org.apache.commons.math3.linear.ArrayRealVector;
import org.apache.commons.math3.linear.RealVector;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        // Prepare training data
        Map<Integer, List<RealVector>> trainingData = new HashMap<>();
        List<Integer> classes = new ArrayList<>();

        // Add training data and classes
        // ...

        // Create and train the classifier
        NaiveBayesClassifier classifier = new NaiveBayesClassifier(trainingData, classes);

        // Prepare test data
        RealVector testVector = new ArrayRealVector(new double[] {1.0, 2.5, 3.7});

        // Make prediction
        int predictedClass = classifier.classify(testVector);

        System.out.println("Predicted class: " + predictedClass);
    }
}

위의 예제 코드를 통해 Apache Commons Math를 사용하여 나이브 베이즈 알고리즘을 구현하고 사용할 수 있습니다.

참고 자료