Skip to content
Back to skills

Pvchat Personalized Video One Shot

ASecurity

Enable identity-aware video question answering with one-shot learning using Mixture-of-Heads enhanced ViLLM. Learns subject-specific features from single video through synthetic augmentation and progressive image-to-video training, enabling recognition of individuals in medical, smart home, and entertainment contexts.

  • 6 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 9, 2026
ai-agentspythongitperformance

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill pvchat-personalized-video-one-shot --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Pvchat Personalized Video One Shot?

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

Security grade badge for Pvchat Personalized Video One Shot
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-pvchat-personalized-video-one-shot/badge)](https://www.skillsdirectory.com/skills/adu2021-pvchat-personalized-video-one-shot)

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: pvchat-personalized-video-one-shot
title: "PVChat: Personalized Video Chat with One-Shot Learning"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: "https://arxiv.org/abs/2503.17069"
keywords: [One-Shot Learning, Video Understanding, Personalization, Mixture-of-Heads, Identity-Aware QA]
description: "Enable identity-aware video question answering with one-shot learning using Mixture-of-Heads enhanced ViLLM. Learns subject-specific features from single video through synthetic augmentation and progressive image-to-video training, enabling recognition of individuals in medical, smart home, and entertainment contexts."
---

## Core Concept

PVChat addresses the limitation of general video understanding models that fail at identity-aware comprehension (e.g., recognizing specific people in videos). Using one-shot learning, the model learns to recognize and reason about specific individuals from a single video through: (1) synthetic augmentation of identity-preserving training data; (2) a Mixture-of-Heads (MoH) attention mechanism with ReLU routing; (3) progressive image-to-video learning with specialized regularization objectives.

## Architecture Overview

PVChat combines several key components:

- **Mixture-of-Heads (MoH) Architecture**: Multiple attention heads specialized for different aspects (appearance, motion, identity), with learned routing based on input
- **ReLU Routing Mechanism**: Sparse gating that dynamically selects relevant attention heads based on query features
- **Smooth Proximity Regularization**: Progressive learning through exponential distance scaling during training stages
- **Head Activation Enhancement**: Balanced attention routing that prevents head collapse
- **Progressive Training Strategy**: Two-stage approach transitioning from static image recognition to dynamic video understanding

## Implementation Steps

### 1. Mixture-of-Heads (MoH) Attention with ReLU Routing

Implement the MoH mechanism with sparse, learnable routing:

```python
# Mixture-of-Heads attention with ReLU routing
import torch
import torch.nn as nn
import torch.nn.functional as F

class MixtureOfHeadsAttention(nn.Module):
    """
    Multi-head attention with learnable mixture routing.
    """
    def __init__(self, dim, num_heads=8, num_heads_per_expert=2):
        super().__init__()
        self.num_heads = num_heads
        self.dim_per_head = dim // num_heads
        self.num_experts = num_heads // num_heads_per_expert

        # Standard multi-head attention
        self.q_proj = nn.Linear(dim, dim)
        self.k_proj = nn.Linear(dim, dim)
        self.v_proj = nn.Linear(dim, dim)

        # Learnable routing network
        self.routing_network = nn.Sequential(
            nn.Linear(dim, dim // 2),
            nn.ReLU(),
            nn.Linear(dim // 2, self.num_experts),
            nn.Softmax(dim=-1)
        )

        self.out_proj = nn.Linear(dim, dim)

    def forward(self, query, key, value, mask=None):
        """
        Args:
            query: [batch, seq_len, dim]
            key, value: [batch, seq_len, dim]
        """
        batch_size = query.shape[0]

        # Compute routing weights based on query
        route_weights = self.routing_network(query)  # [batch, seq, num_experts]

        # Project Q, K, V
        Q = self.q_proj(query).reshape(batch_size, -1, self.num_heads,
                                       self.dim_per_head)
        K = self.k_proj(key).reshape(batch_size, -1, self.num_heads,
                                     self.dim_per_head)
        V = self.v_proj(value).reshape(batch_size, -1, self.num_heads,
                                       self.dim_per_head)

        # Compute attention per head
        scores = torch.matmul(Q, K.transpose(-2, -1)) / \
                 (self.dim_per_head ** 0.5)
        if mask is not None:
            scores = scores.masked_fill(mask, float('-inf'))

        attention = F.softmax(scores, dim=-1)
        head_outputs = torch.matmul(attention, V)

        # Route outputs through experts
        # Group heads into experts for routing
        head_outputs = head_outputs.reshape(
            batch_size, -1, self.num_experts,
            2, self.dim_per_head  # 2 heads per expert
        )

        # Apply routing: weight each expert's output
        routed_outputs = []
        for expert_idx in range(self.num_experts):
            expert_out = head_outputs[:, :, expert_idx, :, :]
            expert_out = expert_out.reshape(batch_size, -1,
                                           2 * self.dim_per_head)
            weight = route_weights[:, :, expert_idx:expert_idx+1]
            routed_outputs.append(weight * expert_out)

        # Combine all routed outputs
        output = torch.cat(routed_outputs, dim=-1)
        output = self.out_proj(output)

        return output
```

### 2. Synthetic Data Augmentation for Identity Preservation

Generate training samples that preserve subject identity while varying context:

```python
def create_identity_aware_augmentation_pipeline(video_frames,
                                               subject_name,
                                               num_samples=100):
    """
    Augment video data with identity-preserving positives and hard negatives.

    Args:
        video_frames: list of frames from source video
        subject_name: name/ID of subject in video
        num_samples: number of augmented samples to create

    Returns:
        augmented_data: list of (frame, qa_pair, label) tuples
    """
    augmented_data = []

    # Four question types for diverse learning
    qa_templates = {
        'existence': f"Is {subject_name} in this scene?",
        'appearance': f"Describe {subject_name}'s appearance in this frame.",
        'action': f"What action is {subject_name} performing?",
        'location': f"Where is {subject_name} located in this frame?",
    }

    # Identity-preserving augmentations
    for frame_idx, frame in enumerate(video_frames):
        for qa_type, template in qa_templates.items():
            for aug_idx in range(num_samples // (len(video_frames) *
                                                  len(qa_templates))):
                # Apply photometric augmentations (preserve identity)
                augmented_frame = apply_identity_preserving_aug(
                    frame,
                    aug_params={
                        'brightness': np.random.uniform(0.9, 1.1),
                        'contrast': np.random.uniform(0.9, 1.1),
                        'hue_shift': np.random.uniform(-10, 10),
                        'blur': np.random.uniform(0, 0.5),
                    }
                )

                # Generate answer based on video content
                if qa_type == 'existence':
                    answer = "Yes"
                elif qa_type == 'appearance':
                    answer = extract_appearance_from_frame(frame, subject_name)
                elif qa_type == 'action':
                    action = infer_action_from_frames(
                        video_frames[max(0, frame_idx-2):frame_idx+3]
                    )
                    answer = action
                else:  # location
                    answer = detect_subject_location(frame, subject_name)

                augmented_data.append({
                    'frame': augmented_frame,
                    'question': template,
                    'answer': answer,
                    'qa_type': qa_type,
                    'is_positive': True,
                    'subject': subject_name,
                })

    return augmented_data
```

### 3. Progressive Image-to-Video Training with Regularization

Implement two-stage training with specialized objectives:

```python
class PVChatTrainer:
    """Progressive image-to-video training for personalized video QA."""

    def __init__(self, model, device='cuda'):
        self.model = model
        self.device = device
        self.proximity_regularizer = SmoothProximityRegularizer()
        self.head_activation_loss = HeadActivationEnhancement()

    def smooth_proximity_regularization(self, video_features, decay_rate=2.0):
        """
        Regularize proximity between consecutive frames exponentially.

        Args:
            video_features: [batch, time_steps, dim]
            decay_rate: exponential scaling for temporal distance

        Returns:
            proximity_loss: float scalar loss
        """
        batch_size, seq_len, dim = video_features.shape
        proximity_loss = 0.0

        for t in range(seq_len - 1):
            # Compare features at time t and t+1
            feat_t = video_features[:, t, :]
            feat_next = video_features[:, t+1, :]

            # Distance scales exponentially with time gap
            temporal_dist = torch.exp(-decay_rate * torch.arange(
                1, seq_len - t, device=self.device))

            # Smooth proximity: nearby frames should be similar
            for delta in range(1, seq_len - t):
                feat_delta = video_features[:, t + delta, :]
                sim = F.cosine_similarity(feat_t, feat_delta, dim=-1)
                weight = temporal_dist[delta - 1]
                # High similarity with exponential decay
                proximity_loss += weight * (1 - sim).mean()

        return proximity_loss / seq_len

    def head_activation_enhancement(self, head_activations):
        """
        Encourage balanced activation across MoH attention heads.

        Args:
            head_activations: [batch, seq_len, num_heads]

        Returns:
            activation_loss: float scalar loss
        """
        # Compute entropy of head activations
        activation_probs = F.softmax(head_activations, dim=-1)
        entropy = -(activation_probs * torch.log(activation_probs + 1e-8)).sum(dim=-1)

        # Encourage high entropy (balanced activation)
        max_entropy = np.log(head_activations.shape[-1])
        activation_loss = max(0, (max_entropy - entropy).mean())

        return activation_loss

    def train_stage1_image(self, train_loader, epochs=5):
        """
        Stage 1: Train on augmented images with identity supervision.
        """
        optimizer = torch.optim.AdamW(self.model.parameters(), lr=1e-4)

        for epoch in range(epochs):
            for batch in train_loader:
                images = batch['image'].to(self.device)
                questions = batch['question']
                answers = batch['answer']

                # Forward through image encoder
                logits, head_activations = self.model(images, questions)

                # Main QA loss
                qa_loss = F.cross_entropy(logits, answers)

                # Regularization: encourage balanced head usage
                head_loss = self.head_activation_enhancement(
                    head_activations
                )

                total_loss = qa_loss + 0.1 * head_loss

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

    def train_stage2_video(self, train_loader_video, epochs=3):
        """
        Stage 2: Fine-tune on video sequences with temporal regularization.
        """
        optimizer = torch.optim.AdamW(self.model.parameters(), lr=5e-5)

        for epoch in range(epochs):
            for batch in train_loader_video:
                videos = batch['video'].to(self.device)  # [B, T, C, H, W]
                questions = batch['question']
                answers = batch['answer']

                # Extract features over time
                batch_size, seq_len = videos.shape[:2]
                video_features = []

                for t in range(seq_len):
                    frame_features, head_act = self.model.encode_image(
                        videos[:, t, :, :, :]
                    )
                    video_features.append(frame_features)

                video_features = torch.stack(video_features, dim=1)

                # Forward through video decoder
                logits, head_activations = self.model.decode_qa(
                    video_features, questions
                )

                # Main QA loss
                qa_loss = F.cross_entropy(logits, answers)

                # Proximity regularization (temporal smoothness)
                proximity_loss = self.smooth_proximity_regularization(
                    video_features, decay_rate=2.0
                )

                # Head activation enhancement
                head_loss = self.head_activation_enhancement(
                    head_activations
                )

                total_loss = (qa_loss +
                             0.2 * proximity_loss +
                             0.1 * head_loss)

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

## Practical Guidance

### When to Use PVChat

- Building personalized video assistants for smart home or healthcare
- Need to recognize and reason about specific individuals from limited video
- Want identity-aware QA without retraining on large labeled datasets
- Medical scenarios requiring patient/caregiver recognition
- Entertainment applications (anime/movie character identification)

### When NOT to Use

- Generic video understanding without identity requirements
- Insufficient compute for synthetic data generation and two-stage training
- Privacy concerns with storing individual video embeddings
- Need instantaneous one-shot adaptation (model still requires training)

### Hyperparameters & Configuration

- **Decay rate (smooth proximity regularization)**: 2.0 (exponential scaling for temporal distance)
- **Head activation enhancement weight**: 0.1 relative to main QA loss
- **Proximity regularization weight**: 0.2 relative to main QA loss
- **Stage 1 epochs**: 5 (image pre-training)
- **Stage 2 epochs**: 3 (video fine-tuning)
- **Learning rate stage 1**: 1e-4
- **Learning rate stage 2**: 5e-5
- **Number of attention heads**: 8 with 2 per expert group
- **Augmentation samples per video**: 100-200

### Common Pitfalls

- **Insufficient augmentation diversity**: Generate diverse QA types and photometric variations; avoid mode collapse
- **Imbalanced head activation**: Monitor entropy of head routing; apply head activation enhancement loss
- **Temporal discontinuity**: Proximity regularization helps; ensure frame sampling captures temporal evolution
- **Overfitting to one-shot subject**: Balance identity-specific features with generalization; validate on diverse subjects
- **Synthetic data quality**: Generated text answers must be accurate; use video understanding models for ground truth
- **Stage ordering**: Must do image pre-training first; video fine-tuning without image pre-training degrades performance

## Reference

- Han et al. 2021. Mixture-of-Experts Meets Vision Transformer (beyond translation).
- Lin et al. 2023. One-Shot Learning for Personalized Vision-Language Models.
- Kaur et al. 2020. Identifying Characters in Fine-Grained Video Understanding.
- Project page and code: Check arXiv repository for implementation details.

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.