Python с плавающей точкой детерминизм
Приведенный ниже код (для вычисления косинусного сходства) при многократном запуске на моем компьютере выдаст 1.0, 0.9999999999999998 или 1.0000000000000002. Когда я уберу функцию нормализации, она вернет только 1.0. Я думал, что операции с плавающей запятой должны были быть детерминированными. Что может вызвать это в моей программе, если одни и те же операции применяются к одним и тем же данным на одном и том же компьютере каждый раз? Может быть, это связано с тем, где в стеке вызывается функция нормализации? Как я могу предотвратить это?
#! /usr/bin/env python3
import math
def normalize(vector):
sum = 0
for key in vector.keys():
sum += vector[key]**2
sum = math.sqrt(sum)
for key in vector.keys():
vector[key] = vector[key]/sum
return vector
dict1 = normalize({"a":3, "b":4, "c":42})
dict2 = dict1
n_grams = list(list(dict1.keys()) + list(dict2.keys()))
numerator = 0
denom1 = 0
denom2 = 0
for n_gram in n_grams:
numerator += dict1[n_gram] * dict2[n_gram]
denom1 += dict1[n_gram]**2
denom2 += dict2[n_gram]**2
print(numerator/(math.sqrt(denom1)*math.sqrt(denom2)))
1 ответ
Математика с плавающей точкой может быть детерминированной, но порядок словарных ключей - нет.
Когда вы звоните .keys()
порядок полученного списка потенциально случайный.
Таким образом, порядок ваших математических операций внутри циклов также потенциально случайный, и, следовательно, результат не будет детерминированным, потому что, хотя любая отдельная операция с плавающей запятой может быть детерминированной, результат ряда операций очень сильно зависит от упорядочения.,
Вы можете навязать последовательный порядок, отсортировав свои списки ключей.