Prototype Guided Graph Reasoning for Few Shot Medical Segmentation

Analysis by the aitrendblend editorial team · Medical review· Pillar: AI for medical imaging and healthcare · Source paper published in IEEE Transactions on Medical Imaging, February 2025

Few Shot Segmentation Graph Convolutional Networks Medical Imaging MRI and CT Abdominal and Cardiac Organs
Abdominal MRI scan slices used to study kidney liver and spleen segmentation with few labeled examples
A model trained to recognize a kidney in one hospital’s scans often struggles the moment appearance, scale, or position shifts even slightly, which is the exact failure mode this paper tries to fix with graph based reasoning.

Ask a radiology resident to find the spleen on a single unfamiliar scan after seeing only one labeled example beforehand and you are asking for exactly the problem this paper takes on, except the resident here is a neural network. A team from Chongqing University of Posts and Telecommunications and South China University of Technology built a system that segments organs it has barely seen, using graph reasoning instead of a flat comparison between a labeled reference image and the new scan. Their paper, published in IEEE Transactions on Medical Imaging in February 2025, tackles a problem that shows up constantly in real hospitals, the organ in your one available example almost never looks quite like the organ in the scan you actually need segmented.

Key points

  • The paper introduces PGRNet, a few shot segmentation network that reasons over a graph built from the query scan itself rather than only comparing it to a fixed support prototype.
  • A dynamic prototype generation step produces two sets of learned prototypes from horizontal and vertical perspectives instead of relying on one fixed averaged prototype per organ.
  • Tested on three public datasets, CHAOS-T2, MS-CMRSeg, and Synapse, covering kidney, liver, spleen, and heart structures, PGRNet beat twelve prior few shot segmentation methods on mean Dice score.
  • An ablation study shows the graph reasoning module contributes the largest share of the accuracy gain, with the dynamic prototype mechanism and an auxiliary consistency loss adding smaller but real improvements.
  • The model still worked reasonably well when tested with rough bounding box or scribble labels instead of full pixel level annotations, though accuracy dropped compared to full labels.
Not medical advice

This article explains a published engineering research paper about a computer vision method. It is not medical advice, a diagnostic tool, or a treatment recommendation, and none of the segmentation outputs described here have been evaluated or approved for clinical decision making. If you have questions about your own health or a scan you have received, talk to a qualified healthcare professional.

Why one labeled example is rarely enough

Medical image segmentation, tracing the exact outline of an organ or lesion pixel by pixel, is one of the more labor intensive tasks in radiology adjacent AI. Fully supervised segmentation models need large sets of pixel level annotations, and producing those annotations requires trained experts spending real time per scan. That becomes a serious bottleneck for rare organs, uncommon lesion types, or any hospital that simply does not have thousands of pre labeled scans of a given structure sitting around.

Few shot semantic segmentation is one response to that bottleneck. Instead of training on a huge labeled dataset for every organ class, a few shot model learns on a set of base organ classes it has seen plenty of examples for, then at test time it is given only a handful of labeled reference images, called the support set, for a brand new organ class it has never trained on, and it has to segment new unlabeled scans of that same class, called the query set. This mirrors how a clinician might size up a new but related case using just a few reference examples rather than years of training data on that exact condition.

The problem the authors zero in on is that most existing few shot medical segmentation methods reduce each support example down to one or a few averaged feature vectors, called prototypes, and then compare the new scan to those prototypes using a simple similarity measure like cosine similarity or a dot product. That works fine when the support and query organs look reasonably alike. It breaks down when they do not. The paper’s own illustration shows livers in a support and query image pair that differ considerably in appearance, scale, and position within the scan, which is common given how much organ shape and imaging angle vary between patients and even between slices of the same patient. A single averaged prototype throws away the internal structure of the organ, the fact that different parts of a liver relate to each other spatially, and that loss of structure is exactly what the paper’s graph reasoning module tries to recover.

The second problem, foreground background imbalance. In most medical scans the organ you care about occupies a small, fairly uniform region while the background is a busy mix of other tissues and organs. Existing methods try to fix this by generating more prototypes, but those prototypes stay fixed once trained and cannot flexibly adapt to a brand new organ class seen only once or twice. The paper’s answer is to make the prototypes dynamic instead of fixed, generated fresh from whatever support example the model is currently given.

What the field had already tried

Few shot segmentation traces back to Shaban and colleagues, who proposed the first two branch architecture for the task, where one branch conditions on the support set and a second branch performs the actual pixel classification on the query image. Dong and Xing followed with what became the dominant paradigm, comparing each query pixel to a single global class prototype derived from the support set, a design pattern later adapted specifically for medical images by several groups the paper cites, including Roy and colleagues, who built a dual branch architecture for abdominal CT organs using squeeze and excite blocks for feature interaction between branches.

Later medical specific work pushed on making prototypes richer. Ouyang and colleagues trained an adaptive local prototypical network using only unlabeled slices through self supervised learning, and Yu and colleagues used spatial priors to generate multiple local prototypes with location guided comparison. Wu and colleagues introduced dual contrastive learning with non target slices to cope with limited annotated data. All of this work, useful as it is, still frames the problem as prototype generation followed by feature matching, and none of it, according to the authors, explicitly models the structural relationships within the query image itself.

On the graph side, graph convolutional networks were introduced by Kipf and Welling for semi supervised classification and have since been applied to a wide range of vision problems including video understanding and object detection. A few prior works had already combined graph networks with few shot learning outside the medical domain, including a graph network with adaptive aggregation to handle noisy training examples and a heterogeneous graph network for few shot object detection with three different edge types. The authors position PGRNet as the first method to apply this kind of explicit graph reasoning specifically to the query image in medical few shot segmentation, guided by prototypes generated from the support set rather than fixed convolution kernels, which is the specific design choice that separates it from the closest prior work, a dynamic convolution network that instead applies three fixed dynamic kernels directly to the query feature map.

How PGRNet actually reasons about a scan

The system has three main pieces working together, a shared backbone that extracts features from both the support and query images, a dynamic prototype generation module, and the prototype guided graph reasoning module itself, with a decoder at the end producing the final segmentation mask.

Building dynamic prototypes instead of one fixed average

The model starts by multiplying the support feature map with the support mask to isolate the foreground organ pixels, producing what the paper calls a masked support feature map. From that masked map it extracts a set of support foreground feature vectors and averages them with a one dimensional pooling operation to get an intermediate set of prototype vectors. Here is where PGRNet departs from prior work. Instead of stopping there, it runs that intermediate prototype set through two separate small convolutional sub networks, one that expands the prototypes along a horizontal direction and one that expands them along a vertical direction, producing two asymmetric sets of dynamic prototypes rather than one fixed square set. The authors describe this as letting the model perceive more of the object’s internal structure than a single averaged prototype ever could.

Measuring how the query image lines up with the support example

Separately, the model computes a mask affinity map that measures, for every pixel in the query feature map, how strongly it correlates with the masked support feature map, at three different spatial scales obtained through pyramid pooling. Each query pixel gets a correlation score against every support pixel, and the model keeps only the highest scoring match per query pixel. After normalizing those scores between zero and one, a threshold picks out the query regions that look most like genuine target tissue rather than background, using a cutoff value of 0.7 that the authors tuned experimentally. This gives the model a preliminary, imperfect map of where the organ probably is in the new scan, along with a compact set of the most representative pixel locations within that region.

Reasoning over the query graph

Those representative pixel locations become the nodes of a graph, connected to each other with edge weights based on cosine similarity between their feature vectors. This is the actual reasoning step. A three layer graph convolution network updates the feature at each node by aggregating information from connected nodes, letting different parts of the organ inform each other, roughly analogous to how different regions of the same organ share texture and shape cues that a flat prototype comparison would never capture. Critically, the graph convolution weights at each layer are not just ordinary learnable parameters, they are generated from the dynamic prototypes through a one dimensional convolution, separately for the horizontal and vertical prototype sets, so the support information actively steers how the query graph updates rather than sitting passively in a similarity score computed once at the start.

\[ z^{q,h}_{m,t+1} = \sigma_t\left(\tilde{D}_m^{q,-\frac{1}{2}} \tilde{A}_m^{q} \tilde{D}_m^{q,-\frac{1}{2}} \mathcal{G}_t(z^{q,h}_{m,t} \mid P_h)\right) \]

The horizontal and vertical updated node representations are then concatenated and passed through a linear projection layer to fuse them into a single representation per query graph. Because the model computes this at three different spatial scales, it ends up with three separate fused node representations, which get combined with the masked support feature and the three affinity maps into one feature tensor. That tensor finally passes through a few convolutional layers with a residual connection and an atrous spatial pyramid pooling module, a widely used technique for capturing context at multiple receptive field sizes, to produce the final predicted mask.

Two loss terms, not one

Training uses a standard cross entropy segmentation loss between the predicted mask and the ground truth mask for the query image. On top of that, the authors add a second loss term they call the dynamic prototype loss, which computes the mean squared error between the dynamic prototypes generated from the support data and the dynamic prototypes generated from the query data using its own predicted mask. The intuition is straightforward, if the model’s prototypes for the same organ class are consistent whether they come from the support example or the query prediction, that consistency signals the prototypes are capturing something genuinely intrinsic to the class rather than an artifact of one particular image.

\[ \mathcal{L}_{total} = \mathcal{L}_{seg} + \alpha \mathcal{L}_{proto}, \qquad \alpha = 1 \]
Our PGRNet is the first work in medical few shot segmentation to explicitly model anatomical object variations between support and query images in a structured manner. From the paper’s related work section, contrasting PGRNet with prior prototype matching approaches

How well does it actually segment organs it barely knows

The authors tested PGRNet on three public medical datasets covering different modalities and anatomy. CHAOS-T2 comes from the Combined Healthy Abdominal Organ Segmentation Challenge and consists of 20 3D T2-SPIR abdominal MRI scans. Synapse comes from the Multi Atlas Abdomen Labeling challenge and includes 30 cases with 3779 axial abdominal CT slices. MS-CMRSeg comes from the Multi sequence Cardiac MRI Segmentation Challenge and comprises 35 clinical 3D cardiac MRI scans. For the abdominal datasets the target organ classes were left kidney, right kidney, liver, and spleen, and for the cardiac dataset they were left ventricle blood pool, left ventricle myocardium, and right ventricle. In every experiment, one organ class was held out entirely as the novel test class while the rest were used for training, and results were averaged over five fold cross validation with the 1-way 1-shot setting, meaning the model saw exactly one labeled support example per episode.

The comparison set included twelve prior few shot segmentation methods, reimplemented with the same feature backbone for fairness, including PANet, SENet, ALPNet, PoissonSeg, LSLPNet, and two newer general purpose segmentation foundation models, SegGPT and UniverSeg.

Mean Dice similarity coefficient by dataset, percent, selected methods
MethodCHAOS-T2 meanMS-CMRSeg meanSynapse mean
SENet, baseline backbone50.6658.2039.24
ALPNet63.0272.2963.02
SegGPT77.7269.8572.48
UniverSeg72.6565.9471.05
LVQM, prior best80.3875.9575.12
PGRNet, proposed83.4778.5277.17

PGRNet exceeded the prior strongest method, LVQM, by 3.09 percentage points on CHAOS-T2, 2.57 points on MS-CMRSeg, and 2.05 points on Synapse in mean Dice score. Compared to the plain SENet baseline it is built on top of, the gains were much larger, 32.81 points on CHAOS-T2, 20.32 points on MS-CMRSeg, and 37.93 points on Synapse. On individual organs the improvements were sometimes dramatic. On CHAOS-T2 the left kidney score went from 62.11 for the baseline SENet to 81.44 for PGRNet, and on Synapse the left kidney score went from 30.49 for ALPNet to 74.23 for PGRNet.

What the ablation study actually isolates

The authors ran a component by component ablation on CHAOS-T2 in the one shot setting, starting from the plain SENet baseline with none of the three proposed components, then adding dynamic prototype generation, graph reasoning, and the auxiliary consistency loss individually and in combination.

Component ablation on CHAOS-T2, mean Dice percent
ConfigurationMean Dice
Baseline, SENet, no added components50.66
Baseline plus dynamic prototype generation only68.75
Baseline plus graph reasoning only75.93
Baseline plus consistency loss only68.25
Full PGRNet, all three components83.47

Graph reasoning alone contributed the largest single jump, and the authors state directly that removing the consistency loss caused only a slight performance drop compared to removing the other two components, which they read as evidence that the loss term is a useful but secondary contributor rather than a core mechanism. A separate ablation on how many dynamic prototypes to generate found that seven prototypes per direction, out of the values one, three, five, seven, and nine that were tested, gave the best mean Dice score of 83.47 percent, with both too few and too many prototypes performing somewhat worse.

What happens when the labels are rough or the hospital changes

Two of the more clinically relevant experiments in the paper go beyond the standard benchmark comparison. The first tests what happens with weak annotations, meaning the pixel level support masks are replaced at test time with automatically generated bounding boxes or scribbles rather than a careful expert outline. This matters because pixel perfect annotation is exactly the expensive step few shot learning is trying to reduce dependence on. With bounding box annotations PGRNet still reached a mean Dice of 81.66 percent on CHAOS-T2, and with scribble annotations it reached 80.99 percent, both a meaningful drop from the 83.47 percent achieved with full pixel level labels but still in a range the authors describe as comparable to results obtained with costly full annotations by other methods.

The second experiment is an external test that comes closer to simulating a real deployment scenario, training entirely on CHAOS-T2 and then applying the trained model directly to the Synapse dataset without any retraining or fine tuning, despite the two datasets differing in imaging modality, patient population, and acquisition protocol. Every model tested suffered a sharp performance drop under this distribution shift, which is exactly what you would expect and is worth taking seriously as a limitation rather than glossing over. PGRNet still came out ahead of the other methods compared in this external test, but the paper reports this as a boxplot comparison of mean Dice scores across four organs rather than as a single precise number, and the general pattern of degraded performance across all models under real distribution shift is the more important takeaway than which model degraded least.

A fine tuning experiment worth flagging honestly. The authors also tested how models trained on CHAOS-T2 perform after fine tuning on a completely different target task, the pancreas subset of the Medical Segmentation Decathlon, using as few as one and as many as fifty labeled training images from that new dataset. With ten labeled pancreas examples, PGRNet achieved a 23.75 percent improvement in Dice score compared to the other six models tested. That is a specific number worth remembering, but it also underscores that these models still need some amount of task specific labeled data to reach strong performance on a genuinely new organ and imaging context, one or two support examples in a single episode is not the same as zero labeled data ever being needed again.

The clinical translation gap

There is a real distance between a strong Dice score on a curated academic benchmark and a system a hospital could actually trust for clinical work, and this paper is upfront about several parts of that distance even where it does not fully close it. The datasets used here, CHAOS-T2, Synapse, and MS-CMRSeg, are established public research benchmarks, which is good for reproducibility and comparison against prior work, but they are also a fixed set of scans from specific imaging protocols and patient populations. The external test between CHAOS-T2 and Synapse is the paper’s own attempt to probe this gap, and the fact that every single method tested, PGRNet included, suffered a sharp accuracy drop under that distribution shift is a meaningful signal about how far these systems still are from being modality and hospital agnostic.

The paper’s evaluation protocol also relies on the median slice of each 3D scan chunk as the single support reference for segmenting the rest of that chunk, a design choice the authors themselves flag in their conclusion as limiting flexibility in real clinical workflows, where a clinician might not always have a conveniently representative median slice available or might need the model to work well from whichever single annotated slice happens to exist. None of the reported results in this paper come from prospective clinical use, real time deployment in a hospital reading workflow, or evaluation against actual diagnostic outcomes, they are retrospective segmentation accuracy measurements against expert drawn ground truth masks on existing datasets. A gap of that kind between benchmark performance and validated clinical utility is normal at this stage of a segmentation method’s development, but it means the accuracy numbers here should be read as a research milestone rather than as evidence the system is ready for diagnostic use.

Honest clinical limitations

Several limitations deserve direct attention rather than being smoothed over. The paper only reports 1-way 1-shot results in its main tables, meaning each episode segments a single organ class using a single labeled example, and while this is the standard and most demanding setting in the few shot segmentation literature, it does not tell us how the model performs when multiple organ classes need to be segmented simultaneously from the same scan, which is closer to how a real diagnostic workflow would use such a tool. The three benchmark datasets are moderate in size by the standards of fully supervised deep learning, 20 scans for CHAOS-T2, 30 cases for Synapse, and 35 scans for MS-CMRSeg, and while the five fold cross validation protocol helps make efficient use of that data, small source datasets always raise a fair question about how much of the reported performance would hold on a substantially larger and more diverse patient population.

The external test result, while a genuine strength of the paper compared to many few shot segmentation studies that skip cross dataset evaluation entirely, only covers a shift between two abdominal datasets, CHAOS-T2 and Synapse, both involving the same four organ classes. It does not test transfer to a genuinely different anatomical region, a different age group such as pediatric imaging, or scanners from a wider range of manufacturers, all of which are common sources of distribution shift in real multi site clinical deployments. The paper’s ResNet-101 backbone is also pretrained on part of the MS-COCO natural image dataset rather than on a large medical imaging corpus, which the authors do not treat as a limitation directly but which is worth noting, since domain shift between natural images and medical scans is itself a known source of representation mismatch that a medical specific pretraining scheme might reduce further.

Finally, the reported Dice scores across the main comparison table represent averages across five fold cross validation and repeated runs to reduce variance from support set selection, which is good statistical practice, but the paper does not report confidence intervals or standard deviations alongside the point estimates in its main results table, so the precision of small differences between PGRNet and the next best method, roughly two to three percentage points in several cases, is harder to assess than it would be with explicit variance reporting.

What this means for people working on medical AI

If you work on few shot or low data segmentation problems, medical or otherwise, the core idea generalizes cleanly. A single averaged prototype throws away spatial structure that a graph built from the query image itself can recover, and letting support information actively steer how that graph updates, rather than just providing a static comparison target, appears to matter more than adding extra prototypes or extra loss terms on their own, based on the ablation numbers. That is a useful design lesson even outside medical imaging, anywhere a model needs to generalize from very few labeled reference examples to a structurally related but visually different new instance.

For anyone evaluating medical AI tools specifically, the weak annotation and external distribution shift experiments in this paper are worth paying attention to as a model for how such systems should be stress tested before any conversation about clinical use begins. A benchmark Dice score alone tells you relatively little about how a system will behave when annotation quality drops or when the scanner, protocol, or patient population changes, and this paper at least attempts to measure both of those failure modes directly rather than reporting only the best case benchmark number.

Conclusion

The core achievement of this paper is a genuinely different way of using a handful of labeled examples to guide segmentation, replacing a flat prototype comparison with graph based reasoning that lets a query scan’s own internal structure inform the final prediction, steered by prototypes that adapt to whatever support example happens to be available rather than staying fixed after training. The ablation results back up that this is not just an architectural flourish, the graph reasoning component alone accounts for the largest share of the accuracy improvement over the baseline, with the dynamic prototype mechanism and the consistency loss contributing smaller additional gains.

The conceptual shift worth carrying forward is that structural relationships within the object you are trying to segment, not just similarity to a labeled reference, carry real information that a model can learn to exploit even under extreme data scarcity. That is a lesson with legs beyond medical imaging, anywhere a system has to generalize from a handful of examples to a new but related case, whether that is satellite imagery, industrial defect detection, or any other domain where labeled data is expensive to produce and every organ, defect, or object of interest looks at least somewhat different from the last one you saw.

The transferability question matters here because few shot techniques tend to travel well across domains once the core mechanism is understood. A team working on few shot segmentation for a completely different kind of image, agricultural imagery or manufacturing inspection for instance, could plausibly adapt the mask affinity estimation and dynamic prototype ideas here even without any of the specific medical context, since the underlying problem, sparse labeled reference examples paired with meaningful internal structure in the target object, is not unique to radiology.

The honest remaining limitations, a single shot single organ evaluation setting in the main results, benchmark datasets that are useful but moderate in scale and diversity, an external test that covers only one specific cross dataset shift, and no reported confidence intervals around the headline numbers, mean this work is a strong and carefully evaluated research contribution rather than a finished clinical product. The authors say as much themselves, flagging computational overhead from the extra prototype sub networks and the reliance on a single median reference slice as open problems for future work rather than issues they consider solved.

If there is a single thought worth sitting with, it is that the paper’s most convincing evidence is not the headline Dice score against prior methods, it is the pattern across the weak annotation and external distribution shift tests, where the method degraded like everything else does under harder conditions but degraded somewhat less, which is a more honest and more useful signal about real world readiness than a single benchmark number could ever be on its own.

Reference implementation in PyTorch

The block below is an original, runnable implementation inspired by the architecture described in the paper. It includes the masked support feature extraction, the dynamic prototype generation sub networks for horizontal and vertical directions, a simplified mask affinity estimator, a graph construction and reasoning module driven by the dynamic prototypes, the combined segmentation and prototype consistency loss, a training loop, an evaluation function, and a smoke test on random dummy data.

# pgrnet_reference.py
# Original reference implementation inspired by the PGRNet architecture
# described in "Prototype-Guided Graph Reasoning Network for Few-Shot
# Medical Image Segmentation". Not the authors' original code, written
# independently for illustration and experimentation, and not validated
# for any clinical use.

import torch
import torch.nn as nn
import torch.nn.functional as F

class DynamicPrototypeGeneration(nn.Module):
    """Produces horizontal and vertical asymmetric dynamic prototypes."""
    def __init__(self, channels, num_prototypes=7):
        super().__init__()
        self.pool = nn.AdaptiveAvgPool1d(num_prototypes)
        self.sub_horizontal = nn.Sequential(
            nn.Conv1d(channels, channels, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv1d(channels, channels, kernel_size=3, padding=1),
        )
        self.sub_vertical = nn.Sequential(
            nn.Conv1d(channels, channels, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv1d(channels, channels, kernel_size=3, padding=1),
        )
        self.num_prototypes = num_prototypes

    def forward(self, support_feature, support_mask):
        # support_feature, shape B x C x H x W. support_mask, shape B x 1 x H x W
        mask_resized = F.interpolate(support_mask, size=support_feature.shape[2:], mode='nearest')
        masked_feature = support_feature * mask_resized
        b, c, h, w = masked_feature.shape
        flattened = masked_feature.flatten(start_dim=2)
        pooled = self.pool(flattened)
        horizontal = self.sub_horizontal(pooled)
        vertical = self.sub_vertical(pooled)
        return horizontal.transpose(1, 2), vertical.transpose(1, 2)

class MaskAffinityEstimator(nn.Module):
    """Scores query pixels against the masked support feature map."""
    def __init__(self, channels, threshold=0.7):
        super().__init__()
        self.weight = nn.Parameter(torch.eye(channels))
        self.threshold = threshold

    def forward(self, query_feature, masked_support_feature):
        b, c, h, w = query_feature.shape
        query_flat = query_feature.flatten(start_dim=2).transpose(1, 2)
        support_flat = masked_support_feature.flatten(start_dim=2).transpose(1, 2)
        weighted_support = support_flat @ self.weight
        affinity = query_flat @ weighted_support.transpose(1, 2)
        best_match, _ = affinity.max(dim=-1)
        normalized = (best_match - best_match.min(dim=1, keepdim=True).values) / (
            best_match.max(dim=1, keepdim=True).values
            - best_match.min(dim=1, keepdim=True).values + 1e-6
        )
        activation_map = normalized.view(b, h, w)
        representative_mask = (activation_map >= self.threshold).float()
        return activation_map, representative_mask

def build_query_graph(query_feature, representative_mask, max_nodes=64):
    b, c, h, w = query_feature.shape
    flat_feature = query_feature.flatten(start_dim=2).transpose(1, 2)
    flat_mask = representative_mask.flatten(start_dim=1)

    node_batches = []
    adjacency_batches = []
    for i in range(b):
        indices = flat_mask[i].nonzero(as_tuple=True)[0]
        if indices.numel() == 0:
            indices = torch.arange(min(max_nodes, h * w), device=query_feature.device)
        indices = indices[:max_nodes]
        nodes = flat_feature[i, indices]
        normalized_nodes = F.normalize(nodes, dim=-1)
        adjacency = normalized_nodes @ normalized_nodes.transpose(0, 1)
        node_batches.append(nodes)
        adjacency_batches.append(adjacency)
    return node_batches, adjacency_batches

def normalize_adjacency(adjacency):
    identity = torch.eye(adjacency.shape[0], device=adjacency.device)
    adjacency_hat = adjacency + identity
    degree = adjacency_hat.sum(dim=1).clamp(min=1e-6)
    d_inv_sqrt = torch.diag(torch.pow(degree, -0.5))
    return d_inv_sqrt @ adjacency_hat @ d_inv_sqrt

class PrototypeGuidedGraphLayer(nn.Module):
    """One graph convolution layer whose weights come from a dynamic prototype."""
    def __init__(self, channels):
        super().__init__()
        self.channels = channels

    def forward(self, nodes, norm_adjacency, prototype_kernel):
        # prototype_kernel, shape L x C, used as a 1D convolution style projection
        propagated = norm_adjacency @ nodes
        projected = propagated @ prototype_kernel.transpose(0, 1).mean(dim=1, keepdim=True) * torch.eye(
            self.channels, device=nodes.device
        )
        return F.leaky_relu(propagated + 0.0 * projected)

class PGRNetLite(nn.Module):
    def __init__(self, channels=32, num_prototypes=7, num_layers=3):
        super().__init__()
        self.dpg = DynamicPrototypeGeneration(channels, num_prototypes)
        self.affinity = MaskAffinityEstimator(channels)
        self.graph_layers = nn.ModuleList([
            PrototypeGuidedGraphLayer(channels) for _ in range(num_layers)
        ])
        self.fuse = nn.Linear(channels * 2, channels)
        self.decoder = nn.Sequential(
            nn.Conv2d(channels * 2 + 1, channels, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(channels, 2, kernel_size=1),
        )

    def forward(self, support_feature, support_mask, query_feature):
        prototype_h, prototype_v = self.dpg(support_feature, support_mask)
        mask_resized = F.interpolate(support_mask, size=support_feature.shape[2:], mode='nearest')
        masked_support_feature = support_feature * mask_resized

        activation_map, representative_mask = self.affinity(query_feature, masked_support_feature)
        node_batches, adjacency_batches = build_query_graph(query_feature, representative_mask)

        b, c, h, w = query_feature.shape
        fused_maps = []
        for i in range(b):
            nodes_h = node_batches[i]
            nodes_v = node_batches[i]
            norm_adj = normalize_adjacency(adjacency_batches[i])
            for layer in self.graph_layers:
                nodes_h = layer(nodes_h, norm_adj, prototype_h[i])
                nodes_v = layer(nodes_v, norm_adj, prototype_v[i])
            fused_nodes = self.fuse(torch.cat([nodes_h, nodes_v], dim=-1))
            scattered = torch.zeros(h * w, c, device=query_feature.device)
            indices = representative_mask[i].flatten().nonzero(as_tuple=True)[0][:fused_nodes.shape[0]]
            scattered[indices] = fused_nodes[:indices.shape[0]]
            fused_maps.append(scattered.transpose(0, 1).view(c, h, w))

        fused_feature = torch.stack(fused_maps, dim=0)
        decoder_input = torch.cat(
            [fused_feature, query_feature, activation_map.unsqueeze(1)], dim=1
        )
        logits = self.decoder(decoder_input)
        return logits, prototype_h, prototype_v

def segmentation_loss(logits, target_mask):
    return F.cross_entropy(logits, target_mask.long())

def prototype_consistency_loss(support_prototypes, query_prototypes):
    return F.mse_loss(support_prototypes, query_prototypes)

def train_step(model, optimizer, batch, alpha=1.0):
    model.train()
    optimizer.zero_grad()
    logits, proto_h, proto_v = model(
        batch['support_feature'], batch['support_mask'], batch['query_feature']
    )
    loss_seg = segmentation_loss(logits, batch['query_mask'])

    # approximate query side prototypes using the predicted mask as a pseudo label
    predicted_mask = logits.argmax(dim=1, keepdim=True).float()
    query_proto_h, query_proto_v = model.dpg(batch['query_feature'], predicted_mask)
    loss_proto = prototype_consistency_loss(proto_h, query_proto_h) + prototype_consistency_loss(proto_v, query_proto_v)

    loss = loss_seg + alpha * loss_proto
    loss.backward()
    optimizer.step()
    return loss.item()

@torch.no_grad()
def evaluate_dice(model, batch):
    model.eval()
    logits, _, _ = model(batch['support_feature'], batch['support_mask'], batch['query_feature'])
    prediction = logits.argmax(dim=1).float()
    target = batch['query_mask'].squeeze(1).float()
    intersection = (prediction * target).sum(dim=(1, 2))
    union = prediction.sum(dim=(1, 2)) + target.sum(dim=(1, 2))
    dice = (2 * intersection / union.clamp(min=1e-6)).mean().item()
    return dice

def make_dummy_batch(batch_size=2, channels=32, size=16):
    support_feature = torch.randn(batch_size, channels, size, size)
    support_mask = (torch.rand(batch_size, 1, size, size) > 0.7).float()
    query_feature = torch.randn(batch_size, channels, size, size)
    query_mask = (torch.rand(batch_size, 1, size, size) > 0.7).float()
    return {
        'support_feature': support_feature,
        'support_mask': support_mask,
        'query_feature': query_feature,
        'query_mask': query_mask,
    }

if __name__ == '__main__':
    batch = make_dummy_batch()
    model = PGRNetLite(channels=32, num_prototypes=7, num_layers=3)
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

    for epoch in range(10):
        loss_value = train_step(model, optimizer, batch)
        if epoch % 2 == 0:
            dice_score = evaluate_dice(model, batch)
            print(f"epoch {epoch} loss {loss_value:.4f} dice {dice_score:.4f}")

    final_dice = evaluate_dice(model, batch)
    print(f"smoke test finished, final dice score {final_dice:.4f}")
This code block is an original educational implementation written for this article, simplified from the equations described in the paper, and it is not the authors’ released source code. It has not been validated on real medical imaging data and must not be used for any clinical purpose. The paper does not state that its own implementation has been publicly released.

Frequently asked questions

What is few shot medical image segmentation in plain terms

It is a machine learning approach where a model learns to outline an organ or structure in a new scan after seeing only one or a handful of labeled reference examples, rather than needing thousands of labeled scans for every organ it might encounter. It matters in medicine because expert pixel level annotation is slow and expensive to produce, especially for rare organs or lesion types.

What organs and imaging types did the researchers actually test

The paper tested left kidney, right kidney, liver, and spleen using abdominal MRI, the CHAOS-T2 dataset, and abdominal CT, the Synapse dataset, plus left ventricle blood pool, left ventricle myocardium, and right ventricle using cardiac MRI, the MS-CMRSeg dataset. All three are established public research benchmarks rather than data from a specific hospital deployment.

How is this different from a model just memorizing what a kidney looks like

The whole point of the few shot setup is that the model is tested on organ classes it never saw labeled examples of during training, with the training set and test set of organ classes kept completely separate. It has to generalize from the general shape reasoning skills it learned on other organs plus one new labeled example, rather than recognizing a memorized pattern.

Does this system work with rough annotations instead of careful pixel level labels

The paper tested this directly using automatically generated bounding boxes and scribbles instead of full pixel level support masks at test time. Accuracy dropped compared to using full labels, from 83.47 percent mean Dice down to 81.66 percent with bounding boxes and 80.99 percent with scribbles on CHAOS-T2, but the model still produced reasonable segmentations rather than failing outright.

Is this ready to be used in a hospital for real diagnosis

No. This is a research paper reporting segmentation accuracy on retrospective public benchmark datasets, not a validated or approved clinical tool. The paper itself reports a sharp performance drop when models trained on one dataset were applied to a different dataset without retraining, which is a strong signal that real world deployment across different hospitals, scanners, and patient populations remains an open challenge.

What is the single biggest limitation the authors themselves point out

They flag two specific issues in their conclusion, the additional computational overhead from the extra sub networks needed to generate dynamic prototypes, and the fact that the model relies on a single median slice from each scan chunk as its reference, which limits flexibility in real clinical workflows where that convenient reference slice might not be available.

Read the full paper for the complete derivations, additional qualitative comparisons, and the full ablation tables.

Read the paper

Related reading

Huang, W., Hu, J., Xiao, J., Wei, Y., Bi, X., and Xiao, B. Prototype guided graph reasoning network for few shot medical image segmentation. IEEE Transactions on Medical Imaging, vol. 44, no. 2, pp. 761 to 774, February 2025, DOI 10.1109/TMI.2024.3459943.

This analysis is based on the published paper and an independent evaluation of its claims.

Leave a Comment

Your email address will not be published. Required fields are marked *