Skip to content
Back to skills

Gem Pooling

ASecurity

Replaces global average pooling with Generalized Mean (GeM) pooling, using a learnable or fixed exponent to emphasize high-activation regions.

  • 61 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 12, 2026
developmentpythongit

Security analysis

A100/100

Scanned September 12, 2026

npx -y skills add wenmin-wu/ds-skills --skill gem-pooling --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Gem Pooling?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Gem Pooling
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wenmin-wu-gem-pooling/badge)](https://www.skillsdirectory.com/skills/wenmin-wu-gem-pooling)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: cv-gem-pooling
description: >
  Replaces global average pooling with Generalized Mean (GeM) pooling, using a learnable or fixed exponent to emphasize high-activation regions.
---
# GeM Pooling

## Overview

Global Average Pooling (GAP) treats all spatial locations equally, diluting strong local signals in large feature maps. Generalized Mean (GeM) pooling raises activations to power `p` before averaging, then takes the p-th root — higher `p` values emphasize peak activations (approaching max pooling at p→∞). With p=1 it's average pooling; p=3 is a common default that boosts discriminative regions. Used extensively in retrieval (image search, metric learning) and medical imaging where lesions occupy small regions.

## Quick Start

```python
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.parameter import Parameter
import timm

class GeM(nn.Module):
    def __init__(self, p=3.0, eps=1e-6, p_trainable=False):
        super().__init__()
        self.p = Parameter(torch.ones(1) * p) if p_trainable else p
        self.eps = eps

    def forward(self, x):
        return F.avg_pool2d(
            x.clamp(min=self.eps).pow(self.p),
            (x.size(-2), x.size(-1))
        ).pow(1.0 / self.p)

# Plug into any timm backbone
backbone = timm.create_model('seresnext50_32x4d', pretrained=True,
                              num_classes=0, global_pool='')
pool = GeM(p=3.0, p_trainable=True)
head = nn.Linear(backbone.num_features, num_classes)

# Forward
features = backbone(images)       # (B, C, H, W)
pooled = pool(features).squeeze()  # (B, C)
logits = head(pooled)              # (B, num_classes)
```

## Workflow

1. Create backbone with `global_pool=''` and `num_classes=0` to get raw feature maps
2. Add GeM pooling layer (fixed p=3 or learnable)
3. Add linear classification head on top
4. Train end-to-end — if p is learnable, it adapts to the task

## Key Decisions

- **p value**: p=3 is standard; higher (5–7) for very localized signals; p=1 degrades to GAP
- **Trainable p**: Set `p_trainable=True` for the model to learn optimal pooling aggression
- **eps clamping**: Essential — prevents NaN from negative activations raised to fractional power
- **vs MAC/SPoC**: GeM generalizes both; SPoC=p=1, MAC≈p→∞

## References

- [SE-ResNeXt50 Full GPU Decoding](https://www.kaggle.com/code/christofhenkel/se-resnext50-full-gpu-decoding)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…