Here's a simple Java program that implements a neural network with backpropagation for solving the XOR problem. The program reads training data from a CSV file and trains the neural network accordingly.

```java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;

public class SimpleNeuralNetwork {

    private static final String TRAINING_DATA_FILE = "training_data.csv";

    public static void main(String[] args) {
        double[][] trainingData = readTrainingDataFromFile(TRAINING_DATA_FILE);
        NeuralNetwork nn = new NeuralNetwork(2, 4, 1);
        nn.train(trainingData, 10000);

        System.out.println("XOR results:");
        for (double[] data : trainingData) {
            double result = nn.feedForward(data)[0];
            System.out.printf("Input: %f, %f -> Output: %f\n", data[0], data[1], result);
        }
    }

    private static double[][] readTrainingDataFromFile(String filename) {
        try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
            return br.lines()
                    .map(line -> line.split(","))
                    .map(values -> new double[]{Double.parseDouble(values[0]), Double.parseDouble(values[1]),
                            Double.parseDouble(values[2])})
                    .toArray(double[][]::new);
        } catch (IOException e) {
            throw new RuntimeException("Error reading training data from file", e);
        }
    }
}

class NeuralNetwork {

    private int inputNodes;
    private int hiddenNodes;
    private int outputNodes;
    private double learningRate;
    private double[][] weightsIH;
    private double[][] weightsHO;
    private double[] biasH;
    private double[] biasO;

    public NeuralNetwork(int inputNodes, int hiddenNodes, int outputNodes) {
        this.inputNodes = inputNodes;
        this.hiddenNodes = hiddenNodes;
        this.outputNodes = outputNodes;
        this.learningRate = 0.1;

        Random random = new Random();
        weightsIH = new double[hiddenNodes][inputNodes];
        for (int i = 0; i < hiddenNodes; i++) {
            for (int j = 0; j < inputNodes; j++) {
                weightsIH[i][j] = random.nextDouble() * 2 - 1;
            }
        }

        weightsHO = new double[outputNodes][hiddenNodes];
        for (int i = 0; i < outputNodes; i++) {
            for (int j = 0; j < hiddenNodes; j++) {
                weightsHO[i][j] = random.nextDouble() * 2 - 1;
            }
        }

        biasH = new double[hiddenNodes];
        for (int i = 0; i < hiddenNodes; i++) {
            biasH[i] = random.nextDouble() * 2 - 1;
        }

        biasO = new double[outputNodes];
        for (int i = 0; i < outputNodes; i++) {
            biasO[i] = random.nextDouble() * 2 - 1;
        }
    }

    public void train(double[][] trainingData, int epochs) {
        for (int e = 0; e < epochs; e++) {
            for (double[] data : trainingData) {
                double[] inputs = new double[]{data[0], data[1]};
                double[] targets = new double[]{data[2]};

                // Feed forward
                double[] hiddenOutputs = feedForward(inputs);

                // Calculate output errors
                double[] outputErrors = new double[outputNodes];
                for (int i = 0; i < outputNodes; i++) {
                    outputErrors[i] = targets[i] - hiddenOutputs[i];
                }

                // Calculate hidden errors
                double[] hiddenErrors = new double[hiddenNodes];
                for (int i = 0; i < hiddenNodes; i++) {
                    for (int j = 0; j < outputNodes; j++) {
                        hiddenErrors[i] += weightsHO[j][i] * outputErrors[j];
                    }
                }

                // Update weights and biases between hidden and output layers
                for (int i = 0; i < outputNodes; i++) {
                    for (int j = 0; j < hiddenNodes; j++) {
                        weightsHO[i][j] += learningRate * outputErrors[i] * hiddenOutputs[j] * (1 - hiddenOutputs[j]);
                    }
                    biasO[i] += learningRate * outputErrors[i];
                }

                // Update weights and biases between input and hidden layers
                for (int i = 0; i < hiddenNodes; i++) {
                    for (int j = 0; j < inputNodes; j++) {
                        weightsIH[i][j] += learningRate * hiddenErrors[i] * inputs[j] * (1 - inputs[j]);
                    }
                    biasH[i] += learningRate * hiddenErrors[i];
                }
            }
        }
    }

    public double[] feedForward(double[] inputs) {
        double[] hiddenOutputs = new double[hiddenNodes];
        for (int i = 0; i < hiddenNodes; i++) {
            hiddenOutputs[i] = sigmoid(dotProduct(weightsIH[i], inputs) + biasH[i]);
        }

        double[] finalOutputs = new double[outputNodes];
        for (int i = 0; i < outputNodes; i++) {
            finalOutputs[i] = sigmoid(dotProduct(weightsHO[i], hiddenOutputs) + biasO[i]);
        }

        return finalOutputs;
    }

    private double sigmoid(double x) {
        return 1 / (1 + Math.exp(-x));
    }

    private double dotProduct(double[] a, double[] b) {
        double result = 0;
        for (int i = 0; i < a.length; i++) {
            result += a[i] * b[i];
        }
        return result;
    }
}
```

To use this program, create a CSV file named `training_data.csv` with the following content:

```
0,0,0
0,1,1
1,0,1
1,1,0
```

This file contains the XOR training data. The first two columns represent the input values and the third column represents the expected output value.

After running the program, you should see the trained neural network's predictions for each of the four possible XOR inputs.
다음은 XOR 문제를 해결하기 위해 역전파를 사용하는 신경망을 구현하는 간단한 Java 프로그램입니다. 이 프로그램은 CSV 파일에서 훈련 데이터를 읽고 그에 따라 신경망을 훈련합니다.

```java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;

public class SimpleNeuralNetwork {

    private static final String TRAINING_DATA_FILE = "training_data.csv";

    public static void main(String[] args) {
        double[][] trainingData = readTrainingDataFromFile(TRAINING_DATA_FILE);
        NeuralNetwork nn = new NeuralNetwork(2, 4, 1);
        nn.train(trainingData, 10000);

        System.out.println("XOR results:");
        for (double[] data : trainingData) {
            double result = nn.feedForward(data)[0];
            System.out.printf("Input: %f, %f -> Output: %f\n", data[0], data[1], result);
        }
    }

    private static double[][] readTrainingDataFromFile(String filename) {
        try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
            return br.lines()
                    .map(line -> line.split(","))
                    .map(values -> new double[]{Double.parseDouble(values[0]), Double.parseDouble(values[1]),
                            Double.parseDouble(values[2])})
                    .toArray(double[][]::new);
        } catch (IOException e) {
            throw new RuntimeException("Error reading training data from file", e);
        }
    }
}

class NeuralNetwork {

    private int inputNodes;
    private int hiddenNodes;
    private int outputNodes;
    private double learningRate;
    private double[][] weightsIH;
    private double[][] weightsHO;
    private double[] biasH;
    private double[] biasO;

    public NeuralNetwork(int inputNodes, int hiddenNodes, int outputNodes) {
        this.inputNodes = inputNodes;
        this.hiddenNodes = hiddenNodes;
        this.outputNodes = outputNodes;
        this.learningRate = 0.1;

        Random random = new Random();
        weightsIH = new double[hiddenNodes][inputNodes];
        for (int i = 0; i < hiddenNodes; i++) {
            for (int j = 0; j < inputNodes; j++) {
                weightsIH[i][j] = random.nextDouble() * 2 - 1;
            }
        }

        weightsHO = new double[outputNodes][hiddenNodes];
        for (int i = 0; i < outputNodes; i++) {
            for (int j = 0; j < hiddenNodes; j++) {
                weightsHO[i][j] = random.nextDouble() * 2 - 1;
            }
        }

        biasH = new double[hiddenNodes];
        for (int i = 0; i < hiddenNodes; i++) {
            biasH[i] = random.nextDouble() * 2 - 1;
        }

        biasO = new double[outputNodes];
        for (int i = 0; i < outputNodes; i++) {
            biasO[i] = random.nextDouble() * 2 - 1;
        }
    }

    public void train(double[][] trainingData, int epochs) {
        for (int e = 0; e < epochs; e++) {
            for (double[] data : trainingData) {
                double[] inputs = new double[]{data[0], data[1]};
                double[] targets = new double[]{data[2]};

                // Feed forward
                double[] hiddenOutputs = feedForward(inputs);

                // Calculate output errors
                double[] outputErrors = new double[outputNodes];
                for (int i = 0; i < outputNodes; i++) {
                    outputErrors[i] = targets[i] - hiddenOutputs[i];
                }

                // Calculate hidden errors
                double[] hiddenErrors = new double[hiddenNodes];
                for (int i = 0; i < hiddenNodes; i++) {
                    for (int j = 0; j < outputNodes; j++) {
                        hiddenErrors[i] += weightsHO[j][i] * outputErrors[j];
                    }
                }

                // Update weights and biases between hidden and output layers
                for (int i = 0; i < outputNodes; i++) {
                    for (int j = 0; j < hiddenNodes; j++) {
                        weightsHO[i][j] += learningRate * outputErrors[i] * hiddenOutputs[j] * (1 - hiddenOutputs[j]);
                    }
                    biasO[i] += learningRate * outputErrors[i];
                }

                // Update weights and biases between input and hidden layers
                for (int i = 0; i < hiddenNodes; i++) {
                    for (int j = 0; j < inputNodes; j++) {
                        weightsIH[i][j] += learningRate * hiddenErrors[i] * inputs[j] * (1 - inputs[j]);
                    }
                    biasH[i] += learningRate * hiddenErrors[i];
                }
            }
        }
    }

    public double[] feedForward(double[] inputs) {
        double[] hiddenOutputs = new double[hiddenNodes];
        for (int i = 0; i < hiddenNodes; i++) {
            hiddenOutputs[i] = sigmoid(dotProduct(weightsIH[i], inputs) + biasH[i]);
        }

        double[] finalOutputs = new double[outputNodes];
        for (int i = 0; i < outputNodes; i++) {
            finalOutputs[i] = sigmoid(dotProduct(weightsHO[i], hiddenOutputs) + biasO[i]);
        }

        return finalOutputs;
    }

    private double sigmoid(double x) {
        return 1 / (1 + Math.exp(-x));
    }

    private double dotProduct(double[] a, double[] b) {
        double result = 0;
        for (int i = 0; i < a.length; i++) {
            result += a[i] * b[i];
        }
        return result;
    }
}
```

이 프로그램을 사용하려면 다음 내용으로 `training_data.csv`라는 CSV 파일을 생성합니다:

```
0,0,0
0,1,1
1,0,1
1,1,0
```

이 파일에는 XOR 훈련 데이터가 포함되어 있습니다. 처음 두 열은 입력 값을 나타내고 세 번째 열은 예상 출력 값을 나타냅니다.

프로그램을 실행하면 네 가지 가능한 XOR 입력 각각에 대한 학습된 신경망의 예측을 볼 수 있습니다.