Geo_CNN(Tensorflow版本)

该Geo_CNN源码来源于https://github.com/voidrank/Geo-CNN

1、perceptron函数:感知机

def perceptron(inputs,
               num_output_channels,
               scope,
               is_training=None,
               data_format='NHWC',
               user_xavier=True,
               stddev=1e-3,
               weight_decay=None,
               activation_fn=tf.nn.relu,
               use_xavier=True,
               bn=False,
               bn_decay=None):

    with tf.variable_scope(scope) as sc:
        assert(data_format=='NHWC' or data_format=='NCHW')
        #obtain [B,N,C]
        b, n, c = inputs.get_shape().as_list()
        #tf.reshape(tensor, shape, name=None)函数的作用是将tensor变换为参数shape的形式
        #inputs:[B*N,C]
        inputs = tf.reshape(inputs, (-1, c))
        #_variable_with_weight_decay 为变量添加weight decay
        #weights=[C,num_output_channels]
        weights = _variable_with_weight_decay('weights',
                                            shape=[c, num_output_channels],
                                            use_xavier=use_xavier,
                                            stddev=stddev,
                                            wd=weight_decay)
        #tf.matmul()将矩阵a乘以矩阵b,生成a * b。
        #outputs=[B*N,num_output_channels]
        outputs = tf.matmul(inputs, weights)
        biases = _variable_on_cpu('biases', [num_output_channels],
                                tf.constant_initializer(0.0))
        #添加偏置项
        outputs = tf.nn.bias_add(outputs, biases)
        #outputs=[B,N,num_output_channels]
        outputs = tf.reshape(outputs, (b, n, -1))

        #bn为True时,添加相应的bn层归一化
        if bn:
          """ Batch normalization on FC data.
  
          Args:
               inputs:      Tensor, 2D BxC input
               is_training: boolean tf.Varialbe, true indicates training phase
              bn_decay:    float or float tensor variable, controling moving average weight
               scope:       string, variable scope变量作用域
          Return:
                normed:      batch-normalized maps
          """
            outputs = batch_norm_for_fc(outputs, is_training, bn_decay, 'bn')

        #若有激活函数,则添加相应的激活函数层,这里默认为Relu
        if activation_fn is not None:
            outputs = activation_fn(outputs)

        return outputs

二、aggregate

from __future__ import print_function
import tensorflow as tf
from tensorflow.python.framework import ops
import sys
import os

import numpy as np

##os.path.dirname(__file__)返回的是.py文件的目录:C:\Users\owolf\Desktop
#os.path.abspath(__file__)返回的是.py文件的绝对路径(完整路径):C:\Users\owolf\Desktop\1.py
#组合使用os.path.dirname(os.path.abspath(__file__)):C:\Users\owolf\Desktop
#os.path.join()拼接路径os.path.join(os.path.dirname(os.path.abspath(__file__)),'1.py'):C:\Users\owolf\Desktop\1.py
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
#表示导入对应目录下的模块
sys.path.append(BASE_DIR)
geoconv_module=tf.load_op_library(os.path.join(BASE_DIR, 'tf_geoconv_so.so'))

def aggregate(feat, xyz, radius, decay_radius, delta=0):
    '''
    inputs:
        feature: batch_size * num_points * num_channels     float32
        xyz: batch_size * num_points * 3                    float32
        radius:                                             float32
        decay_radius:                                       float32
        delta                                               int
    returns:
        output feature: batch_size * num_points * (num_channels/6)  float32
        #6代表的是6个基底的意思
        norm feature: batch_size * num_points
    '''
    return geoconv_module.aggregate(feat, xyz, radius, decay_radius, delta)

#tf.RegisterGradient()注册新的梯度
#使用修饰器, @ops.RegisterGradient("OpName"),建立梯度反向传播函数。
#其中op.input包含输入值、输出值,grad包含上层传来的梯度
@tf.RegisterGradient('Aggregate')
#梯度函数的签名是 def _computer_gradient(op, grad),第一个用来接收 要计算梯度的 op,第二个用来接收 上一层传回来的梯度。
def _aggregate_grad(op, *out_g):
    feat = op.inputs[0] # 取出当前的输入
    xyz  = op.inputs[1]
    top_g = out_g[0]
    norm_buffer = out_g[1]
    #op.get_attr()获取 op 的属性
    radius = op.get_attr("radius")
    decay_radius = op.get_attr("decayradius")
    delta = op.get_attr("delta")
    return [geoconv_module.aggregate_grad(feat, xyz, top_g, radius, decay_radius, delta)[0], None]

该aggregate函数是采用tf的c++端定义的aggregate.下面是验证梯度差异:

class AggregateTest(tf.test.TestCase):
    def test(self):
        pass

    def test_grad(self):
        with tf.device('/gpu:0'):
            feats = tf.constant(np.random.random((8, 128, 192)).astype('float32'))
            xyz   = tf.constant(np.random.random((8, 128, 3)).astype('float32'))
            #ag=[8,128,192/6=32]
            ag, _ = aggregate(feats, xyz, 0.3, 0.6)
            print(ag)

        with self.test_session():
            print("------ Going to compute gradient error")
            #compute_gradient_error()数值化地计算梯度,返回与理论上的梯度的差别,我们所期望的是一个非常小的差别
            #tf.test.compute_gradient_error(x, x_shape, y, y_shape, x_init_value=None, delta=0.001, init_targets=None)
            #计算梯度的error。在计算所得的与数值估计的Jacobian中 为dy/dx计算最大的error
            err = tf.test.compute_gradient_error(feats, (8, 128, 192), ag, (8, 128, 32))
            print(err)
            self.assertLess(err, 1e-4)

if __name__ == "__main__":
    tf.test.main()

三、geo_conv

def geoconv(feat, xyz, num_outputs, bypass_num_outputs,
            radius, decay_radius, bn=True, is_training=False,
            scope=None, bn_decay=None, activation_fn=tf.nn.relu,
            delta=False):
    ''' GeoCNN Geo-Conv
        Input:
            feat: (batch_size, num_point, input_channels) 输入特征
            points: (batch_size, num_point, 3) TF tensor
            num_outputs: the count of output channels
            bypass_num_outputs: the count of output channels of bypass
            radius: the inner radius of local ball of each point.
            decay radius: the outer radius of local ball of each point
            ...
    '''
    # tf.variable_scope() 的作用是为了实现变量共享
    with tf.variable_scope(scope) as sc:
    	#感知机self=[Batchsize,Num_points,num_outputs],self代表中心点
        self = perceptron(feat, num_outputs, scope='self', is_training=is_training, bn=False, activation_fn=None)
        #matual=[Batchsize,Num_points, bypass_num_outputs * 6],
        mutual = perceptron(feat, bypass_num_outputs * 6, scope='mutual', is_training=is_training, bn=False, activation_fn=None)
        #ag:[batch_size, num_points, bypass_num_outputs]
        ag, _ = aggregate(mutual, xyz, radius, decay_radius, delta)

        #b=batch_size, n=num_points, bc=bypass_num_outputs
        b, n, bc = ag.get_shape().as_list()
        #c=num_outputs
        _, _, c  = self.get_shape().as_list()
        #ag=[batch_size * num_points, bypass_num_outputs]
        ag   = tf.reshape(ag, (-1, bc))
        #self=[Batchsize * Num_points, num_outputs]
        self = tf.reshape(self, (-1, c))

        if bn:
            ag = batch_norm_for_fc(ag, is_training, bn_decay, scope='mutual_bn')
        if activation_fn is not None:
            ag = activation_fn(ag)

        #ag=[batch_size , num_points, bypass_num_outputs]
        ag = tf.reshape(ag, (b, n, bc))
        #ag=[batch_size , num_points, num_outputs]
        ag = perceptron(ag, num_outputs, scope='enlarge', is_training=is_training, bn=False, activation_fn=None)
        #ag=[batch_size * num_points, num_outputs]
        ag = tf.reshape(ag, (-1, c))

        #outputs=[batch_size * num_points, num_outputs]
        outputs = self + ag

        if bn:
            outputs = batch_norm_for_fc(outputs, is_training, bn_decay, scope='enlarge_bn')
        if activation_fn is not None:
            outputs = activation_fn(outputs)

        #[batch_size , num_points, num_outputs]
        outputs = tf.reshape(outputs, (b, n, c))

        return outputs

对应论文当中的

 

首先:它表示的是提取中心权值矩阵Wc得到Cout

其次它表示的是提取其他邻近点的矩阵Wx,Wy,Wz得到Creduc

接着它表示的是得到Wenl矩阵得到Cout,对应论文的公式是:

输入是g(p,q),Wenl是W_e_n_l= d_i/\sum d

最后,将特征相加得到局部特征和对应公式如下:

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值