В приведенном вами минимальном проверяемом примере y_pred
и y_true
являются списками целых чисел.В первой строке scipy.stats.measures.pearsonr
source вы увидите, что входные данные преобразованы в массивы с цифрой x = np.asarray(x)
.Мы можем увидеть результирующие типы данных этих массивов через:
print(np.asarray(y_pred).dtype) # Prints 'int64'
При делении двух чисел int64
SciPy использует точность float64
, тогда как TensorFlow будет использовать точность float32
в примере выше.Разница может быть довольно большой, даже для одного деления:
>>> '%.15f' % (8.5 / 7)
'1.214285714285714'
>>> '%.15f' % (np.array(8.5, dtype=np.float32) / np.array(7, dtype=np.float32))
'1.214285731315613'
>>> '%.15f' % (np.array(8.5, dtype=np.float32) / np.array(7, dtype=np.float32) - 8.5 / 7)
'0.000000017029899'
Вы можете получить одинаковые результаты для SciPy и TensorFlow, используя точность float32
для y_pred
и y_true
:
import numpy as np
import tensorflow as tf
import scipy.stats as measures
y_pred = np.array([2, 2, 3, 4, 5, 5, 4, 2], dtype=np.float32)
y_true = np.array([1, 2, 3, 4, 5, 6, 7, 8], dtype=np.float32)
## Scipy
val2 = measures.pearsonr(y_pred, y_true)[0]
print("Scipy's Pearson: \t\t{}".format(val2))
## Tensorflow
logits = tf.placeholder(tf.float32, [8])
labels = tf.to_float(tf.Variable(y_true))
acc, acc_op = tf.contrib.metrics.streaming_pearson_correlation(logits,labels)
sess = tf.Session()
sess.run(tf.local_variables_initializer())
sess.run(tf.global_variables_initializer())
sess.run(acc, {logits:y_pred})
sess.run(acc_op, {logits:y_pred})
print("Tensorflow's Pearson: \t{}".format(sess.run(acc,{logits:y_pred})))
prints
Scipy's Pearson: 0.38060760498046875
Tensorflow's Pearson: 0.38060760498046875
Различия между вычислениями SciPy и TensorFlow
В отчетах о результатах тестов, которые вы сообщаете, разница довольно высока.Я взглянул на источник и обнаружил следующие отличия:
1.Обновление ops
Результат tf.contrib.metrics.streaming_pearson_correlation
не является состоянием без сохранения состояния.Возвращает коэффициент корреляции op вместе с update_op
для новых входящих данных.Если вы вызовите обновление операции с другими данными до вызова коэффициента операции с фактическим значением y_pred
, это даст совершенно другой результат:
sess.run(tf.global_variables_initializer())
for _ in range(20):
sess.run(acc_op, {logits: np.random.randn(*y_pred.shape)})
print("Tensorflow's Pearson: \t{}".format(sess.run(acc,{logits:y_pred})))
print
Scipy's Pearson: 0.38060760498046875
Tensorflow's Pearson: -0.0678008571267128
2.Различные формулы
SciPy:
TensorFlow:
Хотя математически то же самое, вычисление коэффициента корреляции отличается в TensorFlow.Он использует выборочную ковариацию для (x, x), (x, y) и (y, y) для вычисления коэффициента корреляции, который может вносить различные ошибки округления.