javascript - Tensorflow vs Tensorflow JS 浮点算术计算的不同结果

标签 javascript tensorflow floating-point tensorflow.js tensorflowjs

我已将 Tensorflow 模型转换为 Tensorflow JS,并尝试在浏览器中使用。在输入到模型进行推理之前,需要对输入执行一些预处理步骤。我已经实现了与 Tensorflow 相同的这些步骤。问题是与 TensorFlow 相比,TF JS 的推理结果不同。所以我开始调试代码,发现TF JS在预处理中的浮点运算结果与运行在带有GPU的Docker容器上的Tensorflow不同。 TF JS中使用的代码如下。

       var tensor3d = tf.tensor3d(image,[height,width,1],'float32')

        var pi= PI.toString();
        if(bs == 14 && pi.indexOf('1') != -1 ) {

          tensor3d =  tensor3d.sub(-9798.6993999999995).div(7104.607118190255)

        }
        else if(bs == 12 && pi.indexOf('1') != -1) {

          tensor3d = tensor3d.sub(-3384.9893000000002).div(1190.0708513300835)
        }
        else if(bs == 12 && pi.indexOf('2') != -1) {

          tensor3d =  tensor3d.sub(978.31200000000001).div(1092.2426342420442)

        }
        var resizedTensor = tensor3d.resizeNearestNeighbor([224,224]).toFloat()
        var copiedTens = tf.tile(resizedTensor,[1,1,3])
        return copiedTens.expandDims();

使用的Python代码块

ds = pydicom.dcmread(input_filename, stop_before_pixels=True)
if (ds.BitsStored == 12) and '1' in ds.PhotometricInterpretation:
    normalize_mean = -3384.9893000000002
    normalize_std = 1190.0708513300835
elif (ds.BitsStored == 12) and '2' in ds.PhotometricInterpretation:
    normalize_mean = 978.31200000000001
    normalize_std = 1092.2426342420442
elif (ds.BitsStored == 14) and '1' in ds.PhotometricInterpretation:
    normalize_mean = -9798.6993999999995
    normalize_std = 7104.607118190255
else:
    error_response = "Unable to read required metadata, or metadata invalid. 
    BitsStored: {}. PhotometricInterpretation: {}".format(ds.BitsStored, 
    ds.PhotometricInterpretation)
    error_json = {'code': 500, 'message': error_response}
    self._set_headers(500)
    self.wfile.write(json.dumps(error_json).encode())
    return

    normalization = Normalization(mean=normalize_mean, std=normalize_std)
    resize = ResizeImage()
    copy_channels = CopyChannels()
    inference_data_collection.append_preprocessor([normalization, resize, 
    copy_channels])

规范化代码

    def normalize(self, normalize_numpy, mask_numpy=None):

        normalize_numpy = normalize_numpy.astype(float)

        if mask_numpy is not None:
            mask = mask_numpy > 0
        elif self.mask_zeros:
            mask = np.nonzero(normalize_numpy)
        else:
            mask = None

        if mask is None:
            normalize_numpy = (normalize_numpy - self.mean) / self.std
        else:
            raise NotImplementedError

        return normalize_numpy

ResizeImage代码

   from skimage.transform import resize

   def Resize(self, data_group):

        input_data = data_group.preprocessed_case

        output_data = resize(input_data, self.output_dim)

        data_group.preprocessed_case = output_data
        self.output_data = output_data

复制 channel 代码

    def CopyChannels(self, data_group):

        input_data = data_group.preprocessed_case

        if self.new_channel_dim:
            output_data = np.stack([input_data] * self.channel_multiplier, -1)
        else:
            output_data = np.tile(input_data, (1, 1, self.channel_multiplier))

        data_group.preprocessed_case = output_data
        self.output_data = output_data

示例输出左侧是带有 GPU 的 Docker 上的 Tensorflow,右侧是 TF JS: enter image description here

每走一步结果其实都不一样。

最佳答案

可能有多种可能性会导致此问题。

1- python 中使用的 ops 在 js 和 python 中的使用方式不同。如果是这种情况,使用完全相同的操作将解决这个问题。

2- python 库和浏览器 Canvas 读取张量图像的方式可能不同。实际上,由于某些操作(如抗锯齿等), Canvas 像素在浏览器中并不总是具有相同的值...如本 answer 中所述。 .所以操作的结果可能会有一些细微的差异。为确保这是问题的根本原因,首先尝试打印 python 和 js 数组 image 并查看它们是否相似。很可能是3d张量在js和python中不一样。

tensor3d = tf.tensor3d(image,[height,width,1],'float32')

在这种情况下,可以使用 python 库将图像转换为张量数组,而不是直接在浏览器中读取图像。并使用 tfjs 直接读取此数组而不是图像。这样,js 和 python 中的输入张量将是相同的。

3 - 这是一个 float32 精度问题。 tensor3d 是使用 dtype float32 创建的,根据所使用的操作,可能存在精度问题。考虑这个操作:

tf.scalar(12045, 'int32').mul(tf.scalar(12045, 'int32')).print(); // 145082032 instead of 145082025

在 python 中会遇到同样的精度问题:

a = tf.constant([12045], dtype='float32') * tf.constant([12045], dtype='float32')
tf.print(a) // 145082032

在 python 中,这可以通过使用 int32 dtype 来解决。然而,由于 webgl float32 的限制,使用 tfjs 上的 webgl 后端无法完成同样的事情。在神经网络中,这个精度问题不是什么大问题。要摆脱它,可以使用 setBackend('cpu') 更改后端,例如这要慢得多。

关于javascript - Tensorflow vs Tensorflow JS 浮点算术计算的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56649680/

相关文章:

javascript - DIV 风格和 DIV 位置不一致

javascript - 单击一次后更改功能代码

python - 如何加载用 tf.keras.models.save_model 保存的训练模型的权重?

c# - 在 C# 中测试两个 double 是否相等的经验法则?

Python : INPUT a microtime float, 结果格式化日期时间

javascript - 在 morris js 中使用 css 隐藏 x 轴的标签

javascript - 为本地开发采样大型 CouchDB 数据库,避免长 View 构建

linux - Tensorflow 服务 Git 存储库过时了吗? Tensorflow 文件夹不存在

python - 如何使用 TensorFlow GPU?

python - 检查 float 是否等于python中的整数值