【问题标题】:XOR on tensors (using vectorization) having float value in Tensorflow在 Tensorflow 中对具有浮点值的张量进行异或(使用矢量化)
【发布时间】:2021-06-29 08:42:12
【问题描述】:

我有两个相同形状的张量 t1 和 t2(在我的例子中是 [64, 64, 3])。我需要计算这两个张量的异或。但是想不出办法。

import bitstring
from bitstring import *

@tf.function
def xor(x1, x2) :
  a = BitArray(float=x1, length = 64)
  b = BitArray(float=x2, length = 64)
  a ^= b
  return a.float

这个xor函数在python中计算两个浮点值的异或。

样本输入张量是,

t1 = tf.constant([[1.1, 2.2, 3.3],
                  [4.4, 5.5, 6.6]], dtype=tf.float64)
t2 = tf.constant([[7.7, 8.8, 9.9],
                  [10.1, 11.11, 12.12]], dtype=tf.float64)

我似乎找不到计算两个张量的 xor 的方法。

  1. 如何编写 xor 函数调用的矢量化版本,该函数调用将从 任意形状 的两个张量计算每对浮点数的异或(类似于 tf.添加,tf.matmul 等)?我试过np.vectorized等。
  2. 如何高效地编写xor 函数?为了在 tensorflow 中使用 gpu,我需要使用 tf.something 编写每个语句,例如tf.add, tf. matmul 等。但是由于 tensorflow 没有对 Bitstring 的原生支持,有没有办法在 tensorflow 中将 float 转换为位串(在 xor 函数中),以便我可以稍后执行 tf.bitwise_xor?李>

【问题讨论】:

  • 浮点数上的 XOR 的预期输出是什么?我以为只是在01之间
  • 根据我的理解,两个浮点数的异或将是另一个浮点数。不可能直接在浮点数上计算异或,因此我们需要将其转换为位串并计算异或。其实我想计算A xor B = C,稍后要从C中得到A,我可以简单地做C xor B等于A。
  • 为了完整起见,将两个浮点值的异或作为位数组会产生一个无法解释为浮点的垃圾 64 位值。这应该是显而易见的;您正在破坏指数并破坏尾数。的确,您可以通过异或另一个值来重现其中一个值,但这真的有用吗?

标签: python tensorflow vectorization xor bitwise-xor


【解决方案1】:

在实际需要浮点数的上下文中尝试使用两个浮点数之间的异或结果时要注意。

import struct

x = 1.0
y = 3.5
x1 = list(struct.pack('d', x ))
y1 = list(struct.pack('d', y ))
print('x1', x1)
print('y1', y1)

z1 = [a^b for a,b in zip(x1,y1)]
print('z1', z1)

z1 = bytes(z1)
z = struct.unpack('d',z1)[0]
print('z',z)

输出:

C:\tmp>python x.py
x1 [0, 0, 0, 0, 0, 0, 240, 63]
y1 [0, 0, 0, 0, 0, 0, 12, 64]
z1 [0, 0, 0, 0, 0, 0, 252, 127]
z nan

C:\tmp>

【讨论】:

  • OP 在 Tensorflow 中寻求解决方案。
  • 明白。我想指出的是,在通过异或过程之后,你得到的不再是一个合法的浮点数。我建议一定有更好的方法来实现他的目标。
  • 如果 cmets 提供了一种格式化代码块的方法,我会这样做的。这是本网站提供的唯一机制。
【解决方案2】:

您可能需要一个自定义 C++ 操作来执行此操作。 Tensorflow docs 有一个关于如何构建一个很好的教程。这是一个帮助您入门的示例。

xor_op.cc

#include "tensorflow/core/framework/common_shape_fns.h"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/shape_inference.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_types.h"

namespace tensorflow {
using shape_inference::InferenceContext;

REGISTER_OP("Xor")
    .Input("input_tensor_a: float")
    .Input("input_tensor_b: float")
    .Output("output_tensor: float")
    .SetShapeFn([](InferenceContext* c) {
      return shape_inference::UnchangedShapeWithRankAtLeast(c, 1);
    });

class XorOp : public OpKernel {
 public:
  explicit XorOp(OpKernelConstruction* ctx) : OpKernel(ctx) {}

  float XorFloats(const float* a, const float* b, float* c) {
    *(int*)c = *(int*)a ^ *(int*)b;
    return *c;
  }

  void Compute(OpKernelContext* ctx) override {
    // get input tensors
    const Tensor& input_fst = ctx->input(0);
    const Tensor& input_snd = ctx->input(1);

    TTypes<float, 1>::ConstFlat c_in_fst = input_fst.flat<float>();
    TTypes<float, 1>::ConstFlat c_in_snd = input_snd.flat<float>();

    // allocate output tensor
    Tensor* output_tensor = nullptr;
    OP_REQUIRES_OK(ctx,
                   ctx->allocate_output(0, input_fst.shape(), &output_tensor));

    auto output_flat = output_tensor->flat<float>();
    const int N = c_in_fst.size();

    for (int i = 0; i < N; ++i) {
      XorFloats(&c_in_fst(i), &c_in_snd(i), &output_flat(i));
    }
  }
};

REGISTER_KERNEL_BUILDER(Name("Xor").Device(DEVICE_CPU), XorOp);

}  // namespace tensorflow

让我们构建操作并测试

$ TF_LFLAGS=($(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_link_flags()))'))
$ TF_CFLAGS=($(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_compile_flags()))'))
$ 
$ g++ -std=c++14 -shared xor_op.cc -o xor_op.so -fPIC ${TF_CFLAGS[@]} ${TF_LFLAGS[@]} -O2

让我们运行这个操作,看看它是否有效。

main.py

import tensorflow as tf


def main():
    xor_module = tf.load_op_library("./xor_op.so")
    xor_op = xor_module.xor

    # make some data
    a = tf.constant(
        [[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]],
        dtype=tf.float32)

    b = tf.constant(
        [[7.7, 8.8, 9.9], [10.1, 11.11, 12.12]],
        dtype=tf.float32)
    
    c = xor_op(a, b)

    print(f"a: {a}")
    print(f"b: {b}")
    print(f"c: {c}")


if __name__ == "__main__":
    main()

# a: [[1.1 2.2 3.3]
#     [4.4 5.5 6.6]]
# b: [[ 7.7   8.8   9.9 ]
#     [10.1  11.11 12.12]]
# c: [[3.3319316e+38 2.3509887e-38 3.7713776e-38]
#     [6.3672620e-38 4.7666294e-38 5.3942895e-38]]

酷。让我们更严格地测试一下。

test.py

import tensorflow as tf
from tensorflow.python.platform import test as test_lib


class XorOpTest(test_lib.TestCase):
    def setUp(self):
        # import the custom op
        xor_module = tf.load_op_library("./xor_op.so")
        self._xor_op = xor_module.xor

        # make some data
        self.a = tf.constant(
            [[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]],
            dtype=tf.float32)

        self.b = tf.constant(
            [[7.7, 8.8, 9.9], [10.1, 11.11, 12.12]],
            dtype=tf.float32)

    def test_xor_op(self):
        c = self._xor_op(self.a, self.b)
        self.assertAllEqual(self._xor_op(c, self.b), self.a)


if __name__ == "__main__":
    test_lib.main()

# [ RUN      ] XorOpTest.test_xor_op
# [       OK ] XorOpTest.test_xor_op
# ----------------------------------------------------------------------
# Ran 1 test in 0.005s
# 
# OK

我将把它留给你来扩展它以在 GPU 上工作。 如果您好奇,XorFloats 方法来自inverse square root problem 中使用的位级操作。

【讨论】:

  • 感谢您的报道。在 google colab 中构建这个时我遇到了麻烦。 “致命错误:tensorflow/core/framework/common_shape_fns.h:没有这样的文件或目录”。知道可能是什么问题吗?
  • 张量流版本:2.4.1
  • “我在 google colab 中构建它时遇到了麻烦。”这似乎是不必要的复杂。只需在安装了 tensorflow 的 linux 命令行上构建它。我使用了 gcc 8.3.0、python 3.7.10 和 tensorflow 2.4.1。
  • 谢谢,我在本地机器上构建并上传到 colab 中。正如您也指出的那样,现在它正在工作。
  • 如果你需要在colab中构建它,你可以这样做:colab.research.google.com/drive/…
猜你喜欢
  • 1970-01-01
  • 2020-06-23
  • 2021-02-07
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多