Skip to content
Back to skills

Srum Self Rewarding

ASecurity

Enable unified multimodal models to self-improve by using their understanding module as evaluator for generation. Apply hierarchical dual rewards: global for overall semantics and local for fine-grained details.

  • 6 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 9, 2026
developmentpython

Works with

  • cli

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill srum-self-rewarding --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Srum Self Rewarding?

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

Security grade badge for Srum Self Rewarding
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-srum-self-rewarding/badge)](https://www.skillsdirectory.com/skills/adu2021-srum-self-rewarding)

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: srum-self-rewarding
title: "SRUM: Fine-Grained Self-Rewarding for Unified Multimodal Models"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: "https://arxiv.org/abs/2510.12784"
keywords: [multimodal, self-rewarding, image-generation, global-local-rewards, unified-models]
description: "Enable unified multimodal models to self-improve by using their understanding module as evaluator for generation. Apply hierarchical dual rewards: global for overall semantics and local for fine-grained details."
---

# SRUM: Self-Improving Unified Multimodal Models

Unified multimodal models that handle both vision-language understanding and generation often generate lower-quality images than vision-language models optimize for understanding. SRUM enables self-improvement by leveraging the model's own understanding capabilities to evaluate and improve generation quality.

Core insight: strong understanding capability provides free supervision for generation. By using the model's own understanding as reward signal at global and local levels, unified models self-improve without external human feedback or additional models.

## Core Concept

**Understanding-as-Evaluator**: The model's understanding module becomes evaluator for the generation module, providing self-generated rewards without external supervision.

**Hierarchical Dual Rewards**: Two-tier reward system provides feedback at different granularities: global rewards for semantic correctness, local rewards for object-level detail quality.

## Architecture Overview

- **Understanding Module**: Evaluates generated images for semantic alignment
- **Generation Module**: Creates images from text
- **Global Reward Head**: Scores overall semantic correctness and layout
- **Local Reward Head**: Scores object-level details and fine-grained quality
- **RL Optimizer**: Updates generation based on rewards

## Implementation Steps

**Stage 1: Extract Rewards from Understanding Module**

Use understanding module to score generations:

```python
import torch
import torch.nn as nn
from transformers import CLIPVisionModel, CLIPTextModel

class UnifiedMultimodalModel(nn.Module):
    def __init__(self, model_name='unified-mm-base'):
        super().__init__()

        # Shared transformer backbone
        self.backbone = AutoModel.from_pretrained(model_name)

        # Understanding head: evaluates images
        self.understanding_head = nn.Sequential(
            nn.Linear(768, 384),
            nn.ReLU(),
            nn.Linear(384, 1)  # Global quality score
        )

        # Local detail scorer
        self.local_scorer = nn.Sequential(
            nn.Linear(768, 384),
            nn.ReLU(),
            nn.Linear(384, 1)  # Per-region quality
        )

        # Generation head: creates images
        self.generation_head = ImageDecoder()

    def forward_understanding(self, image):
        """
        Evaluate image quality using understanding module.
        """

        # Encode image
        image_features = self.backbone.encode_image(image)

        # Global reward: semantic correctness
        global_score = self.understanding_head(image_features)

        return global_score

    def forward_generation(self, text):
        """
        Generate image from text.
        """

        # Encode text
        text_features = self.backbone.encode_text(text)

        # Generate image
        generated_image = self.generation_head(text_features)

        return generated_image

class HierarchicalRewardComputer(nn.Module):
    def __init__(self, understanding_model):
        super().__init__()
        self.understanding_model = understanding_model

    def compute_global_reward(self, generated_image, text_prompt):
        """
        Global reward: how well does image match text semantically?
        """

        # Get image understanding
        with torch.no_grad():
            image_features = self.understanding_model.backbone.encode_image(
                generated_image
            )

            global_score = self.understanding_model.understanding_head(
                image_features
            )

        # Get text understanding
        with torch.no_grad():
            text_features = self.understanding_model.backbone.encode_text(
                text_prompt
            )

        # Semantic alignment: cosine similarity
        image_normalized = torch.nn.functional.normalize(
            image_features, dim=-1
        )
        text_normalized = torch.nn.functional.normalize(
            text_features, dim=-1
        )

        semantic_alignment = (
            image_normalized * text_normalized
        ).sum(dim=-1)

        # Global reward combines quality and alignment
        global_reward = 0.5 * global_score + 0.5 * semantic_alignment

        return global_reward

    def compute_local_reward(
        self,
        generated_image,
        text_prompt,
        num_regions=4
    ):
        """
        Local reward: fine-grained object-level quality.
        Divide image into regions and score each independently.
        """

        batch_size, channels, height, width = generated_image.shape

        # Divide image into regions
        region_height = height // num_regions
        region_width = width // num_regions

        local_scores = []

        for i in range(num_regions):
            for j in range(num_regions):
                # Extract region
                h_start = i * region_height
                h_end = (i + 1) * region_height
                w_start = j * region_width
                w_end = (j + 1) * region_width

                region = generated_image[
                    :, :, h_start:h_end, w_start:w_end
                ]

                # Score region with understanding
                with torch.no_grad():
                    region_features = (
                        self.understanding_model.backbone.encode_image(region)
                    )
                    region_score = (
                        self.understanding_model.local_scorer(
                            region_features
                        )
                    )

                local_scores.append(region_score)

        # Average local scores
        local_reward = torch.stack(local_scores).mean()

        return local_reward

    def compute_combined_reward(
        self,
        generated_image,
        text_prompt,
        global_weight=0.6,
        local_weight=0.4
    ):
        """
        Combine global and local rewards.
        """

        global_reward = self.compute_global_reward(
            generated_image,
            text_prompt
        )

        local_reward = self.compute_local_reward(
            generated_image,
            text_prompt
        )

        # Weighted combination
        combined_reward = (
            global_weight * global_reward +
            local_weight * local_reward
        )

        return combined_reward, {
            'global': global_reward.item(),
            'local': local_reward.item()
        }
```

**Stage 2: RL Training Loop**

Train generation module with self-rewards:

```python
def srum_training_loop(
    unified_model,
    text_image_pairs,
    num_epochs=5,
    batch_size=32
):
    """
    Train unified model with self-rewarding.
    """

    optimizer = torch.optim.AdamW(
        unified_model.generation_head.parameters(),
        lr=1e-4
    )

    reward_computer = HierarchicalRewardComputer(unified_model)

    for epoch in range(num_epochs):
        for batch_idx, (texts, images) in enumerate(
            dataloader(text_image_pairs, batch_size)
        ):
            # Generate images from text
            generated_images = unified_model.forward_generation(texts)

            # Compute self-rewards
            rewards_list = []
            loss_list = []

            for gen_img, text, real_img in zip(
                generated_images, texts, images
            ):
                # Self-reward from understanding module
                combined_reward, reward_components = (
                    reward_computer.compute_combined_reward(
                        gen_img.unsqueeze(0),
                        text
                    )
                )

                # Also compute reconstruction loss to reference image
                recon_loss = torch.nn.functional.mse_loss(
                    gen_img, real_img
                )

                rewards_list.append(combined_reward)
                loss_list.append(recon_loss)

            # Policy gradient update
            rewards_tensor = torch.stack(rewards_list)
            loss_tensor = torch.stack(loss_list)

            # Combine RL loss and reconstruction loss
            rl_loss = -(
                rewards_tensor.detach() *
                torch.nn.functional.log_softmax(
                    torch.randn_like(generated_images), dim=1
                )
            ).mean()

            total_loss = loss_tensor.mean() + 0.1 * rl_loss

            optimizer.zero_grad()
            total_loss.backward()
            optimizer.step()

            if batch_idx % 10 == 0:
                avg_reward = rewards_tensor.mean().item()
                avg_loss = loss_tensor.mean().item()
                print(
                    f"Epoch {epoch}, Batch {batch_idx}, "
                    f"Reward: {avg_reward:.4f}, Loss: {avg_loss:.4f}"
                )

    return unified_model
```

**Stage 3: Inference with Quality Guidance**

Generate with quality feedback:

```python
def generate_with_quality_feedback(
    unified_model,
    text_prompt,
    num_iterations=3
):
    """
    Generate image with iterative quality refinement.
    """

    reward_computer = HierarchicalRewardComputer(unified_model)

    best_image = None
    best_reward = -float('inf')

    for iteration in range(num_iterations):
        # Generate initial image
        generated_image = unified_model.forward_generation(
            text_prompt
        )

        # Compute rewards
        combined_reward, components = (
            reward_computer.compute_combined_reward(
                generated_image,
                text_prompt
            )
        )

        # Track best
        if combined_reward > best_reward:
            best_reward = combined_reward
            best_image = generated_image

        # Log quality components
        print(
            f"Iteration {iteration}: "
            f"Global={components['global']:.3f}, "
            f"Local={components['local']:.3f}"
        )

    return best_image
```

## Practical Guidance

**When to Use SRUM:**
- Unified multimodal models handling both understanding and generation
- When understanding quality is significantly higher than generation
- No access to external reward models or human feedback

**When NOT to Use:**
- Separate understanding-only or generation-only models
- When generation quality already matches understanding quality
- Tasks requiring diverse generation (local reward may reduce diversity)

**Reward Weight Strategies:**

| Scenario | Global Weight | Local Weight | Rationale |
|----------|---------------|--------------|-----------|
| High-level tasks | 0.8 | 0.2 | Semantic correctness paramount |
| Detail-focused | 0.4 | 0.6 | Fine details critical |
| Balanced | 0.6 | 0.4 | Standard setting |

**Common Pitfalls:**
- Local reward too strong (overly conservative details)
- Global reward misaligned with human preference (semantic errors remain)
- Region division too fine (noisy local scores)
- Not validating understanding module gives useful feedback

**Improvement Metrics:**

| Metric | Before SRUM | After SRUM |
|--------|------------|-----------|
| T2I-CompBench | 82.18 | 88.37 |
| T2I-ReasonBench | 43.82 | 46.75 |
| FID Score | Baseline | ~5% improvement |

## Reference

Based on the research at: https://arxiv.org/abs/2510.12784

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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.