Вход:
x = torch.tensor([3.5])
print(x)
print(x.item())
print(float(x))
Выход:
(tensor([3.5000]), 3.5, 3.5)
Но если я изменю параметр torch.tensor на любое другое значение, а не на some_value.5, результат будет неточным:
Вход:
x = torch.tensor([3.1])
print(x)
print(x.item())
print(float(x))
Выход:
(tensor([3.1000]), 3.0999999046325684, 3.0999999046325684)
Тензоры с плавающей запятой Pytorch по умолчанию имеют формат fp32. Плавающие числа Python — fp64. Числовая разница связана с преобразованием fp32 в fp64.
Вы можете изменить это, указав fp64 при создании тензора.
x = torch.tensor([3.1], dtype=torch.float64)
print(x)
> tensor([3.1000], dtype=torch.float64)
print(x.item())
> 3.1
print(float(x))
> 3.1
То, что вы испытываете, не имеет ничего общего с самим PyTorch, а скорее с представлением действительных чисел в виде значений с плавающей запятой на современном компьютере. Основная ситуация здесь следующая:
Это правда, что это исчезает, как только вы переключаетесь с 32-битных значений с плавающей запятой на 64-битные значения с плавающей запятой, как предложено в Ответе Карла, поскольку 64-битное значение с плавающей запятой имеет в два раза больше бит для представления. каждое значение. Однако это происходит не потому, что основная ситуация решена, а скорее потому, что ваш интерпретатор Python теперь в каком-то смысле знает, что он должен скрывать ситуацию от вас.
Попробуйте, например, напечатать f"{torch.tensor([3.1], dtype=torch.float64).item():.30f}
или, по сути, f"{3.1:.30f}"
, тем самым заставив видеть больше цифр, чем Python по умолчанию хочет вам показать:
import torch
print(f"{torch.tensor([3.1], dtype=torch.float64).item():.30f}")
# >>> 3.100000000000000088817841970013
print(f"{3.1:.30f}")
# >>> 3.100000000000000088817841970013
Вы увидите, что и для 64-битного случая с плавающей запятой представление числа 3,1 с плавающей запятой является лишь приближением к истинному значению.
Аналогично, вы можете попробовать то же самое с версией 3.5 и обнаружите, что значение сохраняется точно:
import torch
print(f"{torch.tensor([3.5], dtype=torch.float64).item():.30f}")
# >>> 3.500000000000000000000000000000
print(f"{3.5:.30f}")
# >>> 3.500000000000000000000000000000
Следующее утверждение, вероятно, несколько смелое и, в зависимости от того, с какими данными вы работаете, огромное упрощение или даже просто неправильное, но все же: я бы сказал, что в повседневной жизни программиста вам редко приходится сталкиваться с этим. знания, но просто игнорируют тот факт, что значения с плавающей запятой в большинстве случаев являются лишь приближениями. Однако бывают ситуации, когда точная арифметика с плавающей запятой имеет значение, и для этого были разработаны такие решения, как модуль decimal и его Decimal
класс.
Для получения дополнительной общей информации о свойствах арифметики с плавающей запятой вы можете просмотреть Арифметика с плавающей запятой: проблемы и ограничения из документации Python или несколько стандартную статью на эту тему Что Каждый компьютерный учёный должен знать об арифметике с плавающей запятой.