View source on GitHub |

Extracts sample features, neighbor features, and neighbor weights.

```
nsl.lib.unpack_neighbor_features(
features,
neighbor_config,
keep_rank=False
)
```

For example, suppose `features`

contains a single sample feature named
'F0', the batch size is 2, and each sample has 3 neighbors, then `features`

would look like the following:

```
features = {
'F0': tf.constant(11.0, shape=[2, 4]),
'NL_nbr_0_F0': tf.constant(22.0, shape=[2, 4]),
'NL_nbr_0_weight': tf.constant(0.25, shape=[2, 1]),
'NL_nbr_1_F0': tf.constant(33.0, shape=[2, 4]),
'NL_nbr_1_weight': tf.constant(0.75, shape=[2, 1]),
'NL_nbr_2_F0': tf.constant(44.0, shape=[2, 4]),
'NL_nbr_2_weight': tf.constant(1.0, shape=[2, 1]),
},
```

where `NL_nbr_<i>_F0`

represents corresponding neighbor features for the
sample feature 'F0', and `NL_nbr_<i>_weight`

represents neighbor weights. The
specific values for each key (tensors) in this dictionary are for
illustrative purposes only. The first dimension of all tensors is the batch
size.

#### Example invocation:

```
neighbor_config = GraphNeighborConfig('NL_nbr_', '_weight', 3)
sample_features, nbr_features, nbr_weights = unpack_neighbor_features(
features, neighbor_config)
```

where `sample_features`

is:

```
{ 'F0': tf.constant(11.0, shape=[2, 2]) }
```

, `neighbor_features`

is:

```
# The key in this dictionary will contain the original sample's feature name
# The shape of the corresponding tensor will be 6x2, which is the result of
# doing an interleaved merge of three 2x2 tensors along axis 0.
{
'F0': tf.constant([[22, 22], [33, 33], [44, 44], [22, 22], [33, 33],
[44, 44]]),
}
```

, and `neighbor_weights`

is:

```
# The shape of this tensor is 6x1, which is the result of doing an
# interleaved merge of three 2x1 tensors along axis 0.
tf.constant([[0.25], [0.75], [1.0], [0.25], [0.75], [1.0]])
```

#### Args:

: Dictionary of tensors mapping feature names (sample features, neighbor features, and neighbor weights) to tensors. For each sample feature, all its corresponding neighbor features and neighbor weights must be included. All tensors should have a rank that is at least 2, where the first dimension is the batch size. The shape of every sample feature tensor should be identical to each of its corresponding neighbor feature tensors. The shape of each neighbor weight tensor is expected to be`features`

`[B, 1]`

, where`B`

is the batch size. Neighbor weight tensors cannot be sparse tensors.: An instance of`neighbor_config`

`GraphNeighborConfig`

.: Whether to preserve the neighborhood size dimension. Defaults to False.`keep_rank`

#### Returns:

: a dictionary mapping feature names to tensors. The shape of these tensors remains unchanged from the input.`sample_features`

: a dictionary mapping feature names to tensors where these feature names are identical to corresponding feature names in`neighbor_features`

`sample_features`

. Further, for each feature in this dictionary, the resulting tensor represents an interleaved concatenated version of all corresponding neighbor feature tensors that exist. So, if the original sample feature has a shape`[B, D_1, D_2, ...., D_d]`

, then the shape of the returned`neighbor_features`

will be`[(BxN), D_1, D_2, ..., D_d]`

if`keep_rank`

is True, and`[B, N, D_1, D_2, ..., D_d]`

if`keep_rank`

is False. If`num_neighbors`

is 0, then an empty dictionary is returned.: a tensor containing floating point weights. If`neighbor_weights`

`keep_rank`

is True,`neighbor_weights`

will have shape`[(BxN), 1]`

. Otherwise, it will have shape`[B, N, 1]`

This also represents an interleaved concatenation of neighbor weight values across all neighbors. The rank of this tensor remains unchanged. If`num_neighbors`

is 0, then a value of`None`

is returned.

#### Raises:

: If the input does not contain all corresponding neighbor features for every sample feature.`KeyError`

: If the tensors of samples and corresponding neighbors don't have the same shape.`ValueError`