为什么 Pearson 相关性在 Tensorflow 和 Scipy 之间不同
Why Pearson correlation is different between Tensorflow and Scipy
我用两种方法计算 Pearson 相关性:
在 Tensorflow 中,我使用以下指标:
tf.contrib.metrics.streaming_pearson_correlation(y_pred, y_true)
当我根据测试数据评估我的网络时,我得到了以下结果:
loss = 0.5289223349094391
pearson = 0.3701728057861328
(损失为mean_squared_error
)
然后我预测测试数据并使用 Scipy 计算相同的指标:
import scipy.stats as measures
per_coef = measures.pearsonr(y_pred, y_true)[0]
mse_coef = np.mean(np.square(np.array(y_pred) - np.array(y_true)))
我得到以下结果:
Pearson = 0.5715300096509959
MSE = 0.5289223312665985
这是一个已知问题吗?正常吗?
最小、完整且可验证的示例
import tensorflow as tf
import scipy.stats as measures
y_pred = [2, 2, 3, 4, 5, 5, 4, 2]
y_true = [1, 2, 3, 4, 5, 6, 7, 8]
## Scipy
val2 = measures.pearsonr(y_pred, y_true)[0]
print("Scipy's Pearson = {}".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:{}".format(sess.run(acc,{logits:y_pred})))
在您提供的最小可验证示例中,y_pred
和 y_true
是整数列表。在 scipy.stats.measures.pearsonr
source 的第一行中,您将看到输入已使用 x = np.asarray(x)
转换为 numpy 数组。我们可以通过以下方式查看这些数组的结果数据类型:
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'
通过对 y_pred
和 y_true
使用 float32
精度,您可以获得 SciPy 和 TensorFlow 相同的结果:
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})))
打印
Scipy's Pearson: 0.38060760498046875
Tensorflow's Pearson: 0.38060760498046875
SciPy 和 TensorFlow 计算之间的差异
在您报告的考试成绩中,差异很大。我查看了 source 并发现了以下差异:
1。更新操作
tf.contrib.metrics.streaming_pearson_correlation
的结果不是无状态的。它 returns 相关系数 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})))
打印
Scipy's Pearson: 0.38060760498046875
Tensorflow's Pearson: -0.0678008571267128
2。不同的公式
SciPy:
张量流:
虽然在数学上相同,但 TensorFlow 中相关系数的计算有所不同。它使用 (x, x)、(x, y) 和 (y, y) 的样本协方差来计算相关系数,这会引入不同的舍入误差。
我用两种方法计算 Pearson 相关性:
在 Tensorflow 中,我使用以下指标:
tf.contrib.metrics.streaming_pearson_correlation(y_pred, y_true)
当我根据测试数据评估我的网络时,我得到了以下结果:
loss = 0.5289223349094391
pearson = 0.3701728057861328
(损失为mean_squared_error
)
然后我预测测试数据并使用 Scipy 计算相同的指标:
import scipy.stats as measures
per_coef = measures.pearsonr(y_pred, y_true)[0]
mse_coef = np.mean(np.square(np.array(y_pred) - np.array(y_true)))
我得到以下结果:
Pearson = 0.5715300096509959
MSE = 0.5289223312665985
这是一个已知问题吗?正常吗?
最小、完整且可验证的示例
import tensorflow as tf
import scipy.stats as measures
y_pred = [2, 2, 3, 4, 5, 5, 4, 2]
y_true = [1, 2, 3, 4, 5, 6, 7, 8]
## Scipy
val2 = measures.pearsonr(y_pred, y_true)[0]
print("Scipy's Pearson = {}".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:{}".format(sess.run(acc,{logits:y_pred})))
在您提供的最小可验证示例中,y_pred
和 y_true
是整数列表。在 scipy.stats.measures.pearsonr
source 的第一行中,您将看到输入已使用 x = np.asarray(x)
转换为 numpy 数组。我们可以通过以下方式查看这些数组的结果数据类型:
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'
通过对 y_pred
和 y_true
使用 float32
精度,您可以获得 SciPy 和 TensorFlow 相同的结果:
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})))
打印
Scipy's Pearson: 0.38060760498046875
Tensorflow's Pearson: 0.38060760498046875
SciPy 和 TensorFlow 计算之间的差异
在您报告的考试成绩中,差异很大。我查看了 source 并发现了以下差异:
1。更新操作
tf.contrib.metrics.streaming_pearson_correlation
的结果不是无状态的。它 returns 相关系数 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})))
打印
Scipy's Pearson: 0.38060760498046875
Tensorflow's Pearson: -0.0678008571267128
2。不同的公式
SciPy:
张量流:
虽然在数学上相同,但 TensorFlow 中相关系数的计算有所不同。它使用 (x, x)、(x, y) 和 (y, y) 的样本协方差来计算相关系数,这会引入不同的舍入误差。