Вопрос или проблема
Как я могу вычислить евклидово расстояние между 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[]{ /* ваши данные */ });
}
}
Пояснение
- Использование
tf.math.sub
: Мы создаем специальный тензор для разности между двумя входными тензорами, что фиксирует проблемы с типами. - Вычисление суммы квадратов: Вместо того чтобы пытаться работать с каждым компонентом по отдельности, мы используем
reduce_sum
для получения суммы квадратов разностей. - Сумма и Квадратный корень: Итоговый результат евклидова расстояния извлекается с помощью
sqrt
.
Заключение
Используя приведенный выше подход, вы сможете корректно вычислять евклидово расстояние между двумя тензорами с использованием TensorFlow Java на GPU. Убедитесь, что входные данные корректны и расположены в допустимом формате. Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь обращаться за помощью!