Как рассчитать евклидово расстояние между 2 тензорами в Tensor Java 0.5.0

Вопрос или проблема

Как я могу вычислить евклидово расстояние между 2 тензорами в Tensorflow Java 0.5.0?

Это мой код:

public static float[] getFloat(DataBuffer<Float> data) {
        float[] res = new float[(int) data.size()];

        for (int i = 0; i < data.size(); i++) {
            res[i] = data.getObject(i); // Копировать каждый элемент Float в float[]
        }
        return res;
    }

    public static void main(String[] args) {
        try (SavedModelBundle model = SavedModelBundle.load("C:\\Users\\User\\Documents\\TensorflowProject\\Model\\model", "serve")) {
            Graph graph = model.graph();
            try(Session session = model.session()) {
                Ops tf = Ops.create(graph);

                Tensor result = session.runner()
                        .feed("serve_input_layer:0", readImage("C:\\Users\\User\\Documents\\TensorflowProject\\TrainData\\image.jpg"))
                        .fetch("StatefulPartitionedCall:0").run().get(0);
                DataBuffer<Float> data = result.asRawTensor().data().asFloats();

                Tensor result2 = session.runner()
                        .feed("serve_input_layer:0", readImage("C:\\Users\\User\\Documents\\TensorflowProject\\TrainData\\image.jpg"))
                        .fetch("StatefulPartitionedCall:0").run().get(0);
                DataBuffer<Float> data2 = result2.asRawTensor().data().asFloats();
                
                Sub<TFloat32> diff = tf.math.sub(tf.constant(getFloat(data)), tf.constant(getFloat(data2)));
                Tensor diffTensor = session.runner().fetch(diff).run().get(0);
                System.out.println("Разница: " + diffTensor.asRawTensor().data().asFloats().getObject(0));
                
                Square<TFloat32> square = tf.math.square(diff);
                Tensor squareTensor = session.runner().fetch(square).run().get(0);
                System.out.println("Квадрат: " + squareTensor.asRawTensor().data().asFloats().getObject(0));
                
                Sqrt<TFloat32> sqrt = tf.math.sqrt(square);
                Tensor distance = session.runner().fetch(sqrt).run().get(0);
                System.out.println("Расстояние: " + distance.asRawTensor().data().asFloats().getObject(0));
                
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
    }

Это мой вывод:

Разница: 3.9829087E35
Квадрат: Бесконечность
Расстояние: Бесконечность

Почему это происходит? Я так расстроен, я хочу использовать tf.math, потому что хочу использовать мощность GPU вместо мощности CPU, поэтому, пожалуйста, не просите меня делать что-то вроде этого:

public static double calculateDistance(float[] arr1, float[] arr2) {
        if (arr1.length != arr2.length) {
            throw new IllegalArgumentException("Обе массивы должны иметь одинаковую длину.");
        }

        double sum = 0.0;

        for (int i = 0; i < arr1.length; i++) {
            double diff = arr1[i] - arr2[i];
            sum += Math.pow(diff, 2);
        }

        return Math.sqrt(sum);
    }

Вышеуказанный код работал так, как ожидалось, но, как я уже сказал, я не хочу использовать мощность CPU.

Это мой pom.xml:

<dependency>
    <groupId>org.tensorflow</groupId>
    <artifactId>tensorflow-core-platform-gpu</artifactId>
    <version>0.5.0</version>
</dependency>

Пожалуйста, помогите мне, я пытался сделать это в течение 2 дней, но это никогда не работало.
Я искренне прошу о помощи, пожалуйста, спасибо 🙂

Ответ или решение

Для вычисления евклидова расстояния между двумя тензорами в TensorFlow Java (версия 0.5.0) важно понимать, как правильно использовать API и избегать возможных ошибок, которые могут приводить к аномальным выходным значениям, таким как бесконечность.

Вы предоставили код, который, кажется, содержит ошибки в вычислениях, и я помогу вам исправить их.

Основная проблема

Ваши текущие попытки вычитания и вычисления квадратов могут привести к неправильным результатам из-за неправильных типов данных или неверного использования методов TensorFlow. Также важно правильно работать с тензорами на GPU.

Откорректированный код для вычисления евклидова расстояния

Вот исправленный пример, как это можно сделать:

import org.tensorflow.SavedModelBundle;
import org.tensorflow.Tensor;
import org.tensorflow.Session;
import org.tensorflow.Graph;
import org.tensorflow.op.Ops;
import org.tensorflow.op.core.Sub;
import org.tensorflow.op.math.Square;
import org.tensorflow.op.math.Sqrt;

public class EuclideanDistance {

    public static void main(String[] args) {
        try (SavedModelBundle model = SavedModelBundle.load("C:\\Users\\User\\Documents\\TensorflowProject\\Model\\model", "serve");
             Session session = model.session()) {
            Graph graph = model.graph();
            Ops tf = Ops.create(graph);

            // Загрузка и получение первого тензора
            Tensor<Float> result1 = session.runner()
                    .feed("serve_input_layer:0", readImage("C:\\Users\\User\\Documents\\TensorflowProject\\TrainData\\image.jpg"))
                    .fetch("StatefulPartitionedCall:0").run().get(0).expect(Float.class);

            // Загрузка и получение второго тензора
            Tensor<Float> result2 = session.runner()
                    .feed("serve_input_layer:0", readImage("C:\\Users\\User\\Documents\\TensorflowProject\\TrainData\\image.jpg"))
                    .fetch("StatefulPartitionedCall:0").run().get(0).expect(Float.class);

            // Вычитание тензоров
            Tensor<Float> diffTensor = tf.math.sub(result1, result2).asTensor();

            // Вычисление квадратов разностей
            Tensor<Float> squareTensor = tf.math.square(diffTensor).asTensor();

            // Вычисление суммы квадратов
            Tensor<Float> sumTensor = tf.reduce_sum(squareTensor).asTensor();

            // Извлечение значения суммы квадратов
            float sumValue = sumTensor.floatValue();

            // Вычисление квадратного корня от суммы квадратов для получения евклидова расстояния
            Tensor<Float> distanceTensor = tf.math.sqrt(tf.constant(sumValue)).asTensor();

            // Извлечение и вывод значения евклидова расстояния
            System.out.println("Distance: " + distanceTensor.floatValue());

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // Метод для чтения изображения. Вы можете изменить его под свои нужды.
    public static Tensor<Float> readImage(String path) {
        // Реализуйте метод для чтения и формирования тензора из изображения
        return Tensor.create(new float[]{ /* ваши данные */ });
    }
}

Пояснение

  1. Использование tf.math.sub: Мы создаем специальный тензор для разности между двумя входными тензорами, что фиксирует проблемы с типами.
  2. Вычисление суммы квадратов: Вместо того чтобы пытаться работать с каждым компонентом по отдельности, мы используем reduce_sum для получения суммы квадратов разностей.
  3. Сумма и Квадратный корень: Итоговый результат евклидова расстояния извлекается с помощью sqrt.

Заключение

Используя приведенный выше подход, вы сможете корректно вычислять евклидово расстояние между двумя тензорами с использованием TensorFlow Java на GPU. Убедитесь, что входные данные корректны и расположены в допустимом формате. Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь обращаться за помощью!

Оцените материал
Добавить комментарий

Капча загружается...