gather_hop_inputs ¶
gather_hop_inputs(
saved: Mapping[int, Tensor], hop: Hop
) -> torch.Tensor
Concatenate the saved layer tensors one hop reads, in source-column order.
A hop's source columns are whole source layers laid side by
side, so the tensor feeding PackedLinear or
MaskedLinear on that hop is those layers concatenated.
Call it between hops, keeping every layer you produce in
saved; a forgotten layer raises rather than dropping the
edges that read it. Inputs are never modified, and a
single-source hop returns the saved tensor itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
mapping of int to torch.Tensor
|
Layer depth to that layer's activation, as far as
|
required |
|
Hop
|
The hop about to be applied, one entry of |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
The hop's source axis, shape
|
Raises:
| Type | Description |
|---|---|
Kpnn2Error
|
If |
RuntimeError
|
Propagated from |
See Also
scatter_hop_outputs : Split the concatenated axis this
returns back onto source layers.
PackedLinear : Applies the hop to the tensor returned here.
PackedLinear.transpose : Tied decode of that hop; feed its
output to scatter_hop_outputs when the hop reads
several layers.
MaskedLinear : Dense hatch via hop.to_mask().
Hop : The record that fixes the source layers and the
concatenated column order this follows.
align_inputs : Column index that puts named features in the
order layer 0 expects.
Notes
Nothing here is graph-aware: this holds no weights, does not
inject values into the previous layer, and does not pick
skip sources by name. Columns that are not edges stay in the
concatenated tensor; PackedLinear never reads them, and
MaskedLinear(hop.to_mask()) zeros them. With the skip
A -> C reaching past layer 1, layer 0 [A, B] and
layer 1 [H] gather to [A, B, H], and the A -> C
weight is the packed pair whose source column is A.
An AdjacencySpec has no hops and is not accepted; in
that layout every edge is already a packed index pair.
Examples:
The hop into C reads layers 0 and 1, so its input is
two columns wide:
>>> import pandas as pd
>>> import torch
>>> import kpnn2
>>> edgelist = pd.DataFrame(
... {
... "source": ["A", "H", "A"],
... "target": ["H", "C", "C"],
... }
... )
>>> spec = kpnn2.parse_layered(edgelist)
>>> saved = {
... 0: torch.tensor([[2.0]]),
... 1: torch.tensor([[5.0]]),
... }
>>> x = kpnn2.gather_hop_inputs(
... saved,
... spec.hops[1],
... )
>>> x.tolist()
[[2.0, 5.0]]
Forgetting to store a layer raises instead of silently dropping the edges that read it:
>>> kpnn2.gather_hop_inputs(
... {1: torch.tensor([[5.0]])},
... spec.hops[1],
... )
Traceback (most recent call last):
...
Kpnn2Error: saved is missing layer 0. ...