Пример #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)
Пример #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)
Пример #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
Пример #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
Пример #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
Пример #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
Пример #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)
Пример #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
Пример #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