Loading your learning…
Loading your learning…
Suppose a prediction depends on the combination of two features, not just their separate effects. A cross layer builds those products explicitly. Input x [B, D] has B examples and D numerical features per example; output [B, D] contains transformed features, not probabilities. Here B = 2 and D = 2. Real inputs could concatenate normalized numerical features and learned category embeddings.
import torchfrom torch import nn class CrossNetworkV1(nn.Module): def __init__(self, dim, depth=2): super().__init__() self.weights = nn.ParameterList([ nn.Parameter(torch.randn(dim) * dim ** -0.5) for _ in range(depth) ]) self.biases = nn.ParameterList([ nn.Parameter(torch.zeros(dim)) for _ in range(depth) ]) def forward(self, x0): # x0: [B, D]; each row is one example's combined features. x = x0 for weight, bias in zip(self.weights, self.biases): projection = (x * weight).sum(dim=-1, keepdim=True) # [B, 1] x = x0 * projection + bias + x # [B, D] return x if __name__ == "__main__": torch.manual_seed(0) x = torch.tensor([[2., 3.], [1., 4.]]) # [B=2, D=2] cross = CrossNetworkV1(dim=2, depth=1) with torch.no_grad(): cross.weights[0].copy_(torch.tensor([0.5, 1.])) print(cross(x)) # [[10., 15.], [5.5, 22.]]For input [2, 3] and weight [0.5, 1], the weighted sum is 2×0.5 + 3×1 = 4. Multiply the original [2, 3] by 4 and add the original again: [8, 12] + [2, 3] = [10, 15]. Bias starts at zero. The main section initializes the layer and sets weights explicitly so you can check the arithmetic.
Later layers update x but keep x0 fixed. In a batch, each example gets its own scalar; all examples share the learned weights.
return x if __name__ == "__main__": torch.manual_seed(0) x = torch.tensor([[2., 3.], [1., 4.]]) # [B=2, D=2] cross = CrossNetworkV1(dim=2, depth=1) with torch.no_grad(): cross.weights[0].copy_(torch.tensor([0.5, 1.])) print(cross(x)) # [[10., 15.], [5.5, 22.]]