instant npg

1. hash encoding是如何减少encoding的参数量的,相对于dense grid

instantnpg 中采用了多尺度的特征网格,每个尺度网格对应一个hash table的一块连续区域(底层结构为一个array)

  • coarse resolution
    1:1对应,每个网格对应一个array entry 无冲突。

  • fine resolution
    使用一个hash function转空间坐标为index,会有冲突,多个网格会指向一个array entry。由于冲突,在参数更新的时候,该网格会自动倾向于保留冲突网格中最重要的尺度细节的网格信息。

self.hash_table = torch.rand(size=(self.hash_table_size * num_levels, features_per_level)) * 2 - 1

2. 采用的hash function

查看nerfstudio的hash encoding的实现。
pytorch_fwd首先获取到每个resolution下的坐标对应的grid的八个顶点坐标经过hash function的array entry的index,即hashed_0-hashed_7,形状[…,num_levels,3],numlevels为resolution的数量。
接着访问八个顶点的尺度特征,f_0-f_7,形状[…, num_levels, features_per_level]。
最后进行线性插值,concatenate得到最终的encoding。

    def pytorch_fwd(self, in_tensor: TensorType["bs":..., "input_dim"]) -> TensorType["bs":..., "output_dim"]:
        """Forward pass using pytorch. Significantly slower than TCNN implementation."""

        assert in_tensor.shape[-1] == 3
        in_tensor = in_tensor[..., None, :]  # [..., 1, 3]
        scaled = in_tensor * self.scalings.view(-1, 1).to(in_tensor.device)  # [..., num_levels, 3]
        scaled_c = torch.ceil(scaled).type(torch.int32)
        scaled_f = torch.floor(scaled).type(torch.int32)

        offset = scaled - scaled_f

        hashed_0 = self.hash_fn(scaled_c)  # [..., num_levels]
        hashed_1 = self.hash_fn(torch.cat([scaled_c[..., 0:1], scaled_f[..., 1:2], scaled_c[..., 2:3]], dim=-1))
        hashed_2 = self.hash_fn(torch.cat([scaled_f[..., 0:1], scaled_f[..., 1:2], scaled_c[..., 2:3]], dim=-1))
        hashed_3 = self.hash_fn(torch.cat([scaled_f[..., 0:1], scaled_c[..., 1:2], scaled_c[..., 2:3]], dim=-1))
        hashed_4 = self.hash_fn(torch.cat([scaled_c[..., 0:1], scaled_c[..., 1:2], scaled_f[..., 2:3]], dim=-1))
        hashed_5 = self.hash_fn(torch.cat([scaled_c[..., 0:1], scaled_f[..., 1:2], scaled_f[..., 2:3]], dim=-1))
        hashed_6 = self.hash_fn(scaled_f)
        hashed_7 = self.hash_fn(torch.cat([scaled_f[..., 0:1], scaled_c[..., 1:2], scaled_f[..., 2:3]], dim=-1))

        f_0 = self.hash_table[hashed_0]  # [..., num_levels, features_per_level]
        f_1 = self.hash_table[hashed_1]
        f_2 = self.hash_table[hashed_2]
        f_3 = self.hash_table[hashed_3]
        f_4 = self.hash_table[hashed_4]
        f_5 = self.hash_table[hashed_5]
        f_6 = self.hash_table[hashed_6]
        f_7 = self.hash_table[hashed_7]

        f_03 = f_0 * offset[..., 0:1] + f_3 * (1 - offset[..., 0:1])
        f_12 = f_1 * offset[..., 0:1] + f_2 * (1 - offset[..., 0:1])
        f_56 = f_5 * offset[..., 0:1] + f_6 * (1 - offset[..., 0:1])
        f_47 = f_4 * offset[..., 0:1] + f_7 * (1 - offset[..., 0:1])

        f0312 = f_03 * offset[..., 1:2] + f_12 * (1 - offset[..., 1:2])
        f4756 = f_47 * offset[..., 1:2] + f_56 * (1 - offset[..., 1:2])

        encoded_value = f0312 * offset[..., 2:3] + f4756 * (
            1 - offset[..., 2:3]
        )  # [..., num_levels, features_per_level]

        return torch.flatten(encoded_value, start_dim=-2, end_dim=-1)  # [..., num_levels * features_per_level]

关键还是要看看hash function的代码。
hash函数首先进行了一个乘法操作,然后进行xyz的异或,再通过求模保证其index范围再hash_table_size内,再通过offset将不同尺度下的index平移到各自所在的hash_table_size大小的数组连续块中。

    def hash_fn(self, in_tensor: TensorType["bs":..., "num_levels", 3]) -> TensorType["bs":..., "num_levels"]:
        """Returns hash tensor using method described in Instant-NGP

        Args:
            in_tensor: Tensor to be hashed
        """

        # min_val = torch.min(in_tensor)
        # max_val = torch.max(in_tensor)
        # assert min_val >= 0.0
        # assert max_val <= 1.0

        in_tensor = in_tensor * torch.tensor([1, 2654435761, 805459861]).to(in_tensor.device)
        x = torch.bitwise_xor(in_tensor[..., 0], in_tensor[..., 1])
        x = torch.bitwise_xor(x, in_tensor[..., 2])
        x %= self.hash_table_size
        x += self.hash_offset.to(x.device)
        return x
### 回答1: matlab中的npg函数是一个基于模拟退火算法的全局优化函数。它被用来寻找给定约束条件下的最小值或最大值。 npg函数的使用格式为: x = npg(fun,x0,A,b,Aeq,beq,lb,ub,options) 其中,fun是用户定义的目标函数;x0是初始猜测解;A和b定义了线性不等式约束条件;Aeq和beq定义了线性等式约束条件;lb和ub定义了变量的上下界;options是一个结构体,包含了算法的相关参数设置。 npg函数首先使用模拟退火算法进行优化,然后使用局部搜索算法来细化结果。这个函数使用了随机性来探索解空间,并以一定概率接受劣解,从而避免陷入局部最优解。 在调用npg函数时,我们需要根据具体的问题设置好目标函数和约束条件。目标函数应是连续可导的,并且返回一个标量值。约束条件可以包括线性不等式约束、线性等式约束、变量的上下界等。我们还可以通过调整参数options来控制算法的收敛速度和结果的准确性。 总之,npg函数是matlab中的一个全局优化函数,它基于模拟退火算法来寻找给定约束条件下的最小值或最大值。通过合理设置目标函数和约束条件,并调整算法的参数,我们可以得到较好的优化结果。 ### 回答2: npg函数在MATLAB中是一个用于计算NPG(Normalized Power Gained)的函数。NPG是一种用于评估机械系统动力学特性的指标。它与系统的阻尼特性有关,可以用于评估系统的稳定性和性能。 在MATLAB中,使用npg函数可以计算给定系统的NPG值。该函数需要提供系统的传递函数作为输入参数。传递函数是描述输入和输出之间关系的数学模型。通过传递函数,可以确定系统的动态特性,如频率响应和阻尼比。 npg函数根据传递函数计算系统的固有频率和阻尼比,并使用这些值来计算NPG值。NPG值越大,表示系统在运行过程中获得的能量越高,系统更加稳定。 使用npg函数可以帮助工程师和研究人员评估系统的动力学特性,并根据需要进行调整和优化。该函数在MATLAB中提供了一种方便的方式来计算和分析系统的NPG值。 ### 回答3: matlab中的npg函数是用来计算矩阵中每个元素的非负公差的函数。NPG是Non-negative Partial Gradient的缩写,意为非负部分梯度。在计算机科学和数学领域,梯度是指一个函数的变化率或斜率。在图像处理和优化问题中,梯度可以帮助我们确定最佳的方向和步长。然而,在某些情况下,我们希望限制梯度的取值范围在非负数之间,以保持数据的特定性质和约束。这种情况下,就可以使用matlab中的npg函数。 npg函数的输入参数为一个矩阵,输出为一个与输入矩阵相同大小的矩阵,其中每个元素的值为相应元素的非负梯度值。具体来说,对于输入矩阵中的每个元素,npg函数会计算其梯度值,并将其限制在非负范围内。如果原始元素大于零,则输出元素与原始元素相同;如果原始元素小于零,则输出元素为零。因此,npg函数可以帮助我们处理那些需要梯度的问题,但又需要限制梯度的正负性的情况。 使用npg函数的示例代码如下: ```matlab A = [-1 2 -3; 4 -5 6; -7 8 -9]; % 输入矩阵 B = npg(A); % 计算矩阵A的非负梯度 disp(B); % 输出非负梯度矩阵 ``` 以上示例代码中,输入矩阵A包含了正负数,通过调用npg函数得到的矩阵B则只包含非负数。可以看到,输出矩阵中负数元素都被替换为零,而正数元素与输入矩阵中相同。 总之,matlab中的npg函数提供了一种计算矩阵非负梯度的方法,它能够帮助处理那些需要限制梯度正负性的问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值