Download packages/softasp-solver/src/softasp_solver/components/perception.py from wabdalm/AS2: direct link, hf CLI and curl.
- Browser
- Download file 2.77 kB
-
https://huggingface.co/wabdalm/AS2/resolve/main/packages/softasp-solver/src/softasp_solver/components/perception.py
- Command line
-
hf download hf://wabdalm/AS2/packages/softasp-solver/src/softasp_solver/components/perception.py
-
curl -L -o perception.py https://huggingface.co/wabdalm/AS2/resolve/main/packages/softasp-solver/src/softasp_solver/components/perception.py
2.77 kB
| """Reusable image encoder; AS2 itself does not require an image modality.""" | |
| import torch | |
| from torch import nn | |
| class CellCNN(nn.Module): | |
| """Shared-weight CNN that encodes a single 28Γ28 grayscale cell image. | |
| Args: | |
| d_model: Output embedding dimension. | |
| backbone: Architecture variant. | |
| ``"default"`` β lightweight 3-conv CNN (original SoftASP design). | |
| ``"resnet18"`` β ResNet-18 adapted for 1-channel 28Γ28 input; | |
| weights are loaded externally via ``pretrained_from`` or trained | |
| from scratch. Requires ``torchvision``. | |
| """ | |
| def __init__(self, d_model: int = 128, backbone: str = "default") -> None: | |
| super().__init__() | |
| self.backbone_name = backbone | |
| if backbone == "default": | |
| self.features = nn.Sequential( | |
| nn.Conv2d(1, 32, kernel_size=3, padding=1), | |
| nn.ReLU(inplace=True), | |
| nn.MaxPool2d(2), # β 32 Γ 14 Γ 14 | |
| nn.Conv2d(32, 64, kernel_size=3, padding=1), | |
| nn.ReLU(inplace=True), | |
| nn.MaxPool2d(2), # β 64 Γ 7 Γ 7 | |
| nn.Conv2d(64, 128, kernel_size=3, padding=1), | |
| nn.ReLU(inplace=True), | |
| nn.AdaptiveAvgPool2d(1), # β 128 Γ 1 Γ 1 | |
| nn.Flatten(), # β 128 | |
| ) | |
| self.proj = nn.Linear(128, d_model) | |
| elif backbone == "resnet18": | |
| import torchvision.models as _tv # lazy import β optional dep | |
| _r = _tv.resnet18(weights=None) | |
| # Adapt for 1-channel 28Γ28 input: | |
| # β’ smaller first conv (3Γ3, stride 1) preserves 28β28 spatial size | |
| # β’ remove the 3Γ3 max-pool so small images keep enough resolution | |
| _r.conv1 = nn.Conv2d(1, 64, kernel_size=3, stride=1, padding=1, bias=False) | |
| # Use all residual stages + avgpool β 512-d feature vector | |
| self.features = nn.Sequential( | |
| _r.conv1, | |
| _r.bn1, | |
| _r.relu, | |
| nn.Identity(), | |
| _r.layer1, | |
| _r.layer2, | |
| _r.layer3, | |
| _r.layer4, | |
| _r.avgpool, | |
| nn.Flatten(), # β 512 | |
| ) | |
| self.proj = nn.Linear(512, d_model) | |
| else: | |
| raise ValueError( | |
| f"Unknown CellCNN backbone: {backbone!r}. Choose 'default' or 'resnet18'." | |
| ) | |
| self.norm = nn.LayerNorm(d_model) | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| """ | |
| Args: | |
| x: (N, 1, 28, 28) float32 | |
| Returns: | |
| (N, d_model) | |
| """ | |
| h = self.features(x) | |
| return self.norm(self.proj(h)) | |