import torch from torch import nn class TinyXorNet(nn.Module): def __init__(self) -> None: super().__init__() self.layers = nn.Sequential( nn.Linear(2, 8), nn.ReLU(), nn.Linear(8, 1), ) def forward(self, x: torch.Tensor) -> torch.Tensor: return self.layers(x) def main() -> None: device = "cuda" if torch.cuda.is_available() else "cpu" print(f"torch={torch.__version__} cuda={torch.version.cuda} device={device}") if device == "cuda": print(f"gpu={torch.cuda.get_device_name(0)}") x = torch.tensor( [[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]], device=device, ) y = torch.tensor([[0.0], [1.0], [1.0], [0.0]], device=device) model = TinyXorNet().to(device) loss_fn = nn.BCEWithLogitsLoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.05) for step in range(1, 501): optimizer.zero_grad() logits = model(x) loss = loss_fn(logits, y) loss.backward() optimizer.step() if step % 100 == 0: print(f"step={step} loss={loss.item():.4f}") with torch.no_grad(): probabilities = torch.sigmoid(model(x)) predictions = (probabilities >= 0.5).int() print("predictions:") rows = zip( x.cpu().tolist(), y.cpu().int().tolist(), predictions.cpu().tolist(), ) for inputs, expected, actual in rows: print(f" {inputs} -> expected={expected[0]} predicted={actual[0]}") if __name__ == "__main__": main()