【问题标题】:Adding a custom sparse op (Sparse Determinant)添加自定义稀疏运算(稀疏行列式)
【发布时间】:2019-02-27 00:29:15
【问题描述】:

我正在尝试让一些稀疏矩阵运算在 Tensorflow 中工作。我要处理的第一个是稀疏行列式,通过稀疏 Cholesky 分解。 Eigen 有一个稀疏的 Cholesky,所以我的想法是把它包装起来。

我已经取得了一些进展,但现在有点卡住了。我知道 Tensorflow 中的 SparseTensor 由三部分组成:indicesvaluesshape。复制类似的操作,我选择了以下REGISTER_OP 声明:

REGISTER_OP("SparseLogDet")
    .Input("a_indices: int64")
    .Input("a_values: float32")
    .Input("a_shape: int64")
    .Output("determinant: float32")
    .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) {
      shape_inference::ShapeHandle h;
      c->set_output(0, h);
      return Status::OK();
    });

这编译得很好,但是当我使用一些示例代码运行它时:

import tensorflow as tf

log_det_op = tf.load_op_library('./sparse_log_det_op.so')

with tf.Session(''):
  t = tf.SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2],
                      dense_shape=[3, 4])
  print(log_det_op.sparse_log_det(t).eval().shape)
  print(log_det_op.sparse_log_det(t).eval())

它抱怨说:

TypeError: sparse_log_det() missing 2 required positional arguments: 'a_values' and 'a_shape'

这对我来说很有意义,因为它期待其他参数。但是,我真的只想传递稀疏张量,而不是将其分解为组件!有谁知道这是如何处理其他稀疏操作的?

谢谢!

【问题讨论】:

    标签: c++ tensorflow


    【解决方案1】:

    如果要传入稀疏张量,然后从中确定indicesvaluesshape,这应该是可以的。只需修改您的 OP 以获取单个 Tensor 输入,并生成单个 float 输出。然后通过遍历其元素从 Eigen::Tensor 中提取所需的信息,如下所示:

    #include "tensorflow/core/framework/op.h"
    #include "tensorflow/core/framework/shape_inference.h"
    #include "tensorflow/core/framework/op_kernel.h"
    #include <Eigen/Dense>
    
    using namespace tensorflow;
    
    REGISTER_OP("SparseDeterminant")
        .Input("sparse_tensor: float")
        .Output("sparse_determinant: float");
    
    
    class SparseDeterminantOp : public OpKernel {
    public:
        explicit SparseDeterminantOp(OpKernelConstruction *context) : OpKernel(context) {}
    
        void Compute(OpKernelContext *context) override {
    
       // get the input tesnorflow tensor
       const Tensor& sparse_tensor = context->input(0);  
       // get shape of input
       const TensorShape& sparse_shape = sparse_tensor.shape();
    
       // get Eigen Tensor for input tensor
       auto eigen_sparse = sparse_tensor.matrix<float>();
    
       //extract the data you want from the sparse tensor input
       auto a_shape = sparse_tensor.shape();
    
       // loop over all elements of the input tensor and add to values and indices
       for (int i=0; i<a_shape.dim_size(0); ++i){
        for (int j=0; j<a_shape.dim_size(1); ++j){
            if(eigen_sparse(i,j) != 0){
            /// ***Here add non zero elements to list/tensor of values and their indicies*** 
                std::cout<<eigen_sparse(i,j)<<" at"<<" "<<i<<" "<<j<<" "<<"not zero."<<std::endl;
            }
        }
       }
    
       // create output tensor
       Tensor *output_tensor = NULL;      
       TensorShape output_shape;
       OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output_tensor));
       auto output = output_tensor->scalar<float>();
    
       output(0) = 1.; //**asign return value***;
    
        }
    };
    REGISTER_KERNEL_BUILDER(Name("SparseDeterminant").Device(DEVICE_CPU), SparseDeterminantOp);
    

    可悲的是,当您将t 传递给您的操作时,它会变成Tensorflow::Tensor 并丢失与tf.sparsetensor 关联的valuesindices 方法,因此您无法轻松获得它们。

    编译后,此代码可以运行:

    //run.py
    import tensorflow as tf
    import numpy as np
    
    my_module = tf.load_op_library('./out.so')
    
    # create sparse matrix
    a = np.zeros((10,10))
    for i in range(len(a)):
        a[i,i] = i
    
    print(a)
    
    a_t = tf.convert_to_tensor(a, dtype= float)
    
    with tf.Session() as sess:
        sess.run(my_module.sparse_determinant(a_t))
    

    【讨论】:

      猜你喜欢
      • 2015-12-05
      • 1970-01-01
      • 2017-12-16
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多