Piotrek-max's picture
Publish reproducible DeepWeeds recruitment baseline
301f30e verified
Raw History Blame Contribute Delete
1.29 kB
"""Small scratch-only CNN used for both DeepWeeds comparison runs."""
from __future__ import annotations
from torch import Tensor, nn
class SmallDeepWeedsCNN(nn.Module):
"""Three-block CNN with no pretrained parameters or regularization layers."""
provenance = "scratch"
def __init__(self, num_classes: int = 9, in_channels: int = 3) -> None:
super().__init__()
if num_classes <= 0:
raise ValueError("num_classes must be positive")
if in_channels not in (1, 3):
raise ValueError("in_channels must be 1 (grayscale) or 3 (RGB)")
self.features = nn.Sequential(
nn.Conv2d(in_channels, 16, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(16, 32, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.AdaptiveAvgPool2d(output_size=1),
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(64, num_classes),
)
def forward(self, inputs: Tensor) -> Tensor:
"""Return unnormalized class logits."""
return self.classifier(self.features(inputs))