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()порядок полученного списка потенциально случайный.

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

Вы можете навязать последовательный порядок, отсортировав свои списки ключей.

Другие вопросы по тегам