Ejemplo n.º 1
0
def fixed_budget_radii(num_res):
    """
    Learnable unscaled squared radii based on a fixed computational budget.

    The budget assumes point cloud density quarters at each resolution, and
    aims to keep the sum across all resolutions of the sum of all neighborhood
    sizes roughly constante. Note there are generally more filters in later
    resolutions, so the number of floating point operations may increase if the
    model learns to expand final layer radii at the expense of lower
    resolutions.

    Args:
        num_res: number of resolutions.

    Returns:
        [num_res] float32 tensor of squared unscaled radii values, initially
        the same as `constant_radii(num_res)`.
    """
    r20 = constant_radii(num_res)
    radii = source.variable(shape=(num_res, ),
                            dtype=tf.float32,
                            initializer=tf.constant_initializer(np.sqrt(r20)))
    radii2 = tf.keras.layers.Lambda(tf.square)(radii)
    density = np.power(4.0, -np.arange(num_res)).astype(np.float32)
    budget = utils.lambda_call(_cost, r20, density)
    return utils.lambda_call(_rescale_for_budget, radii2, density, budget)
Ejemplo n.º 2
0
def mlp_global_deconv(global_features, coord_features, row_splits_or_k,
                      network_fn):
    global_features = layer_utils.lambda_call(_expand_and_tile,
                                              global_features, row_splits_or_k)
    features = tf.keras.layers.Lambda(
        tf.concat, arguments=dict(axis=-1))([global_features, coord_features])
    return network_fn(features)
Ejemplo n.º 3
0
def query_pairs(coords,
                radius,
                name=None,
                max_neighbors=None,
                sample_rate_reciprocal_offset=0):
    """
    Get neighbors and inverse density sample rates from the provided coords.

    sample_rate is given by
    sample_rate = 1. / (sum(num_neighbors) - sample_rate_reciprocal_offset)

    Args:
        coords: [n, num_dims] float32 point cloud coordinates
        radius: float scalar ball search radius
        name: used in layers
        max_neighbors: if not None, neighborhoods are cropped to this size.
        sample_rate_reciprocal_offset: affects sample rate. Values close to 1
            result in sparse neighborhoods being selected more frequently

    Returns:
        neighbors: [n, ?] int32 ragged tensor of neighboring indices
        sample_rate: sampling rate based roughly on inverse density.
    """
    neighbors = _q.query_pairs(coords,
                               radius,
                               name=name,
                               max_neighbors=max_neighbors)
    sample_rate_reciprocal = utils.cast(utils.row_lengths(neighbors),
                                        tf.float32)
    if sample_rate_reciprocal_offset != 0:
        sample_rate_reciprocal = utils.lambda_call(
            tf.math.subtract, sample_rate_reciprocal,
            sample_rate_reciprocal_offset)
    sample_rate = utils.reciprocal(sample_rate_reciprocal)
    return neighbors, sample_rate
Ejemplo n.º 4
0
def flat_expanding_edge_conv(node_features,
                             coord_features,
                             indices,
                             row_splits_or_k,
                             weights=None):
    features = layer_utils.lambda_call(conv_ops.flat_expanding_edge_conv,
                                       node_features, coord_features, indices,
                                       row_splits_or_k, weights)
    return features
Ejemplo n.º 5
0
 def prebatch_input(self, shape, dtype, name=None):
     inp = tf.keras.layers.Input(shape=shape,
                                 dtype=dtype,
                                 batch_size=1,
                                 name=name)
     self._prebatch_inputs.append(inp)
     inp = layer_utils.lambda_call(tf.squeeze, inp, axis=0)
     self._mark(inp, Marks.PREBATCH)
     return inp
Ejemplo n.º 6
0
 def f(inputs, min_log_value=-10):
     x = inputs
     x = layer_utils.lambda_call(tf.abs, x)
     x = layer_utils.lambda_call(tf.math.log, x)
     x = layer_utils.lambda_call(tf.maximum, x, min_log_value)
     x = dense(x)
     x = layer_utils.lambda_call(tf.exp, x)
     angle = layer_utils.lambda_call(_complex_angle, inputs)
     angle = dense(angle)
     components = layer_utils.lambda_call(_angle_to_unit_vector, angle)
     x = layer_utils.lambda_call(tf.expand_dims, x, axis=-1)
     x = layer_utils.lambda_call(tf.multiply, x, components)
     x = layer_utils.flatten_final_dims(x, n=2)
     x = layer_utils.lambda_call(_zeros_if_any_small, inputs, x)
     if dropout_rate is not None:
         x = tf.keras.layers.Dropout(dropout_rate)(x)
     if use_batch_norm:
         x = tf.keras.layers.BatchNormalization()(x)
     return x
Ejemplo n.º 7
0
def reduce_flat_mean(x, row_splits_or_k, weights, eps=1e-7):
    return layer_utils.lambda_call(conv_ops.reduce_flat_mean,
                                   x,
                                   row_splits_or_k,
                                   weights,
                                   eps=eps)
Ejemplo n.º 8
0
def flat_expanding_global_deconv(global_features, coord_features,
                                 row_splits_or_k):
    features = layer_utils.lambda_call(conv_ops.flat_expanding_global_deconv,
                                       global_features, coord_features,
                                       row_splits_or_k)
    return features
Ejemplo n.º 9
0
def cls_head(coords,
             normals=None,
             r0=0.1,
             initial_filters=(16, ),
             initial_activation=cls_head_activation,
             filters=(32, 64, 128, 256),
             global_units='combined',
             query_fn=core.query_pairs,
             radii_fn=core.constant_radii,
             coords_transform=None,
             weights_transform=None,
             convolver=None):
    if convolver is None:
        convolver = c.ExpandingConvolver(activation=cls_head_activation)
    if coords_transform is None:
        coords_transform = t.polynomial_transformer(max_order=1)
    if weights_transform is None:
        weights_transform = t.ctg_transformer()
        # weights_transform = lambda *args, **kwargs: None

    n_res = len(filters)
    unscaled_radii2 = radii_fn(n_res)

    if isinstance(unscaled_radii2, tf.Tensor):
        assert (unscaled_radii2.shape == (n_res, ))
        radii2 = utils.lambda_call(tf.math.scalar_mul, r0**2, unscaled_radii2)
        radii2 = tf.keras.layers.Lambda(tf.unstack,
                                        arguments=dict(axis=0))(radii2)
        for i, radius2 in enumerate(radii2):
            tb.add_custom_scalar('radius{}'.format(i), tf.sqrt(radius2))
            # tf.compat.v1.summary.scalar('r%d' % i,
            #                             tf.sqrt(radius2),
            #                             family='radii')
    else:
        radii2 = unscaled_radii2 * (r0**2)

    def maybe_feed(r2, r20):
        if isinstance(r2, (tf.Tensor, tf.Variable)):
            r = tf.keras.layers.Lambda(tf.sqrt)(radius2)
            return cache.get_cached(r, r20)
        else:
            return np.sqrt(r2)

    features = b.as_batched_model_input(normals)
    for f in initial_filters:
        layer = Dense(f)
        features = tf.ragged.map_flat_values(layer, features)
        features = tf.ragged.map_flat_values(initial_activation, features)

    features = utils.flatten_leading_dims(features, 2)
    global_features = []

    default_r0 = r0
    for i, radius2 in enumerate(radii2):
        neighbors, sample_rate = query_fn(coords,
                                          maybe_feed(radius2, default_r0**2),
                                          name='query%d' % i)
        default_r0 *= 2
        if not isinstance(radius2, tf.Tensor):
            radius2 = source.constant(radius2, dtype=tf.float32)
        neighborhood = n.InPlaceNeighborhood(coords, neighbors)
        features, nested_row_splits = core.convolve(features, radius2,
                                                    filters[i], neighborhood,
                                                    coords_transform,
                                                    weights_transform,
                                                    convolver.in_place_conv)
        if global_units == 'combined':
            coord_features = coords_transform(neighborhood.out_coords, None)
            global_features.append(
                convolver.global_conv(features, coord_features,
                                      nested_row_splits[-2], filters[i]))

        if i < n_res - 1:
            sample_indices = sample.sample(
                sample_rate,
                tf.keras.layers.Lambda(lambda s: tf.size(s) // 4)(sample_rate))
            neighborhood = n.SampledNeighborhood(neighborhood, sample_indices)
            features, nested_row_splits = core.convolve(
                features, radius2, filters[i + 1], neighborhood,
                coords_transform, weights_transform, convolver.resample_conv)

            coords = neighborhood.out_coords

    # global_conv
    if global_units == 'combined':
        features = tf.keras.layers.Lambda(
            tf.concat, arguments=dict(axis=-1))(global_features)
    else:
        coord_features = coords_transform(coords, None)
        features = convolver.global_conv(features, coord_features,
                                         nested_row_splits[-2], global_units)

    return features