zero-shot-learning
Recognizing classes without any training examples using semantic attributes and transfer learning
来源信息
- 仓库
- NeuralBlitz/Agent-Gateway
- 最近来源活动
- 2026年4月10日 08:04
- 检测到的 SKILL.md 语言
- 英语
- 星标
- 1
- 分支
- 0
安装方式
默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。
检查来源文件
决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。
正在显示 SKILL.md
SKILL.md
来源说明 · 只读预览- name
- Zero-Shot Learning
- category
- ai
- description
- Recognizing classes without any training examples using semantic attributes and transfer learning
# Zero-Shot Learning
## What I do
I enable models to recognize classes they have never seen during training by leveraging semantic relationships between known and unknown classes. I transfer knowledge from seen classes to unseen classes using attributes, textual descriptions, or learned embeddings. This is essential for expanding model capabilities without retraining on new categories.
## When to use me
- Recognizing novel object categories without training data
- Expanding classification systems to new classes dynamically
- Building models that generalize to rare or unseen categories
- Cross-domain transfer where target domain classes differ from source
- Few-shot adaptation where even K=1 examples are unavailable
- Semantic image retrieval based on textual descriptions
- Building open-vocabulary recognition systems
## Core Concepts
1. **Semantic Embeddings**: Dense vector representations that capture class semantics from text or attributes.
2. **Attribute-Based Classification**: Using human-defined or learned attributes as intermediate representation.
3. **Class Embedding Spaces**: Learned spaces where both seen and unseen class embeddings reside.
4. **Generalized Zero-Shot Learning**: Setting where test samples can belong to either seen or unseen classes.
5. **Bias Calibration**: Adjusting predictions to account for the distribution shift between seen and unseen classes.
6. **Semantic Autoencoders**: Learning to reconstruct class embeddings to improve generalization.
7. **Transductive Learning**: Using unlabeled test data to improve zero-shot performance.
8. **Word Embeddings**: Pre-trained embeddings (Word2Vec, GloVe) that provide semantic class representations.
## Code Examples
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
from collections import defaultdict
class SemanticEmbedding(nn.Module):
def __init__(self, num_classes, embed_dim=300):
super().__init__()
self.embeddings = nn.Embedding(num_classes, embed_dim)
def forward(self, class_ids):
return self.embeddings(class_ids)
class AttributeClassifier(nn.Module):
def __init__(self, num_attributes, image_dim=512, hidden_dim=256):
super().__init__()
self.fc = nn.Sequential(
nn.Linear(image_dim, hidden_dim),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, num_attributes)
)
self.sigmoid = nn.Sigmoid()
def forward(self, features):
attributes = self.fc(features)
return self.sigmoid(attributes)
class ZeroShotClassifier(nn.Module):
def __init__(self, seen_classes, unseen_classes, attribute_dim=312, image_dim=512):
super().__init__()
self.seen_classes = seen_classes
self.unseen_classes = unseen_classes
self.image_encoder = nn.Linear(image_dim, attribute_dim)
self.seen_classifier = nn.Linear(attribute_dim, len(seen_classes))
self.unseen_classifier = nn.Linear(attribute_dim, len(unseen_classes))
self.attribute_matrix = self._create_attribute_matrix()
def _create_attribute_matrix(self):
attributes = torch.randn(len(self.unseen_classes), 312)
return nn.Parameter(attributes)
def forward(self, features, training=False):
projected = self.image_encoder(features)
seen_logits = self.seen_classifier(projected)
unseen_logits = self.unseen_classifier(projected)
return seen_logits, unseen_logits
def predict(self, features, calibrate=True):
seen_logits, unseen_logits = self.forward(features)
seen_probs = F.softmax(seen_logits, dim=1)
unseen_probs = F.softmax(unseen_logits, dim=1)
if calibrate:
seen_calibrated = seen_probs * 0.6
unseen_calibrated = unseen_probs * 0.4
total = seen_calibrated.sum(dim=1, keepdim=True) + unseen_calibrated.sum(dim=1, keepdim=True)
seen_probs = seen_calibrated / total
unseen_probs = unseen_calibrated / total
combined = torch.cat([seen_probs, unseen_probs], dim=1)
all_classes = list(self.seen_classes) + list(self.unseen_classes)
return combined, all_classes
```
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from scipy.spatial.distance import cdist
class WordEmbeddingExtractor:
def __init__(self, method="word2vec"):
import gensim.downloader as api
self.method = method
if method == "word2vec":
self.model = api.load("word2vec-google-news-300")
elif method == "glove":
self.model = api.load("glove-wiki-gigaword-100")
def get_class_embeddings(self, class_names: list) -> torch.Tensor:
embeddings = []
for name in class_names:
words = name.replace("_", " ").lower().split()
word_embs = []
for word in words:
if word in self.model:
word_embs.append(self.model[word])
if word_embs:
class_emb = np.mean(word_embs, axis=0)
embeddings.append(class_emb)
else:
embeddings.append(np.random.randn(self.model.vector_size))
return torch.tensor(np.array(embeddings), dtype=torch.float32)
class CLIPZeroShot(nn.Module):
def __init__(self, embed_dim=512):
super().__init__()
self.visual_projection = nn.Linear(512, embed_dim)
self.text_projection = nn.Linear(512, embed_dim)
self.logit_scale = nn.Parameter(torch.ones([]) * np.log(1 / 0.07))
def forward(self, images, class_names):
image_features = self.visual_projection(images)
image_features = F.normalize(image_features, p=2, dim=1)
text_features = self._encode_text(class_names)
text_features = F.normalize(text_features, p=2, dim=1)
logits = torch.matmul(image_features, text_features.t()) * self.logit_scale.exp()
return logits
def _encode_text(self, class_names: list) -> torch.Tensor:
import clip
device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load("ViT-B/32", device=device)
text_tokens = clip.tokenize([f"a photo of a {name}" for name in class_names])
with torch.no_grad():
text_features = model.encode_text(text_tokens.to(device))
return text_features.float().cpu()
class SemanticAutoencoder(nn.Module):
def __init__(self, input_dim, hidden_dim=1024, latent_dim=300):
super().__init__()
self.encoder = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, latent_dim)
)
self.decoder = nn.Sequential(
nn.Linear(latent_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, input_dim)
)
def forward(self, x):
z = self.encoder(x)
x_recon = self.decoder(z)
return x_recon, z
def loss(self, x, x_recon):
return F.mse_loss(x_recon, x)
```
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
class GZSLPredictor(nn.Module):
def __init__(self, seen_classes, unseen_classes, semantic_dim=300, visual_dim=512):
super().__init__()
self.seen_classes = list(seen_classes)
self.unseen_classes = list(unseen_classes)
self.semantic_embedder = nn.Linear(visual_dim, semantic_dim)
self.class_embeddings = nn.Parameter(torch.randn(len(self.unseen_classes), semantic_dim))
self.relation_network = nn.Sequential(
nn.Linear(semantic_dim * 2, semantic_dim),
nn.ReLU(),
nn.Linear(semantic_dim, 1)
)
def forward(self, features):
visual_embed = self.semantic_embedder(features)
visual_embed = F.normalize(visual_embed, p=2, dim=1)
class_embeds = F.normalize(self.class_embeddings, p=2, dim=1)
seen_embed = torch.tensor([
self.class_embeddings[self.unseen_classes.index(c)]
if c in self.unseen_classes else self._get_seen_embed(c)
for c in self.seen_classes
]).to(features.device)
seen_embed = F.normalize(seen_embed, p=2, dim=1)
all_classes = list(self.seen_classes) + list(self.unseen_classes)
all_embeds = torch.cat([seen_embed, class_embeds], dim=0)
relations = self._compute_relations(visual_embed, all_embeds)
return relations, all_classes
def _compute_relations(self, visual_emb: torch.Tensor,
class_embs: torch.Tensor) -> torch.Tensor:
batch_size = visual_emb.size(0)
num_classes = class_embs.size(0)
visual_exp = visual_emb.unsqueeze(1).expand(batch_size, num_classes, -1)
class_exp = class_embs.unsqueeze(0).expand(batch_size, num_classes, -1)
combined = torch.cat([visual_exp, class_exp], dim=2)
relations = self.relation_network(combined).squeeze(-1)
return relations
def _get_seen_embed(self, class_id):
return self.seen_class_embeddings[class_id]
class CalibratedStacking(nn.Module):
def __init__(self, seen_weights=0.3, unseen_weights=0.7):
super().__init__()
self.seen_weights = seen_weights
self.unseen_weights = unseen_weights
def forward(self, seen_logits, unseen_logits):
seen_probs = F.softmax(seen_logits, dim=1) * self.seen_weights
unseen_probs = F.softmax(unseen_logits, dim=1) * self.unseen_weights
total = seen_probs.sum(dim=1, keepdim=True) + unseen_probs.sum(dim=1, keepdim=True)
return seen_probs / total, unseen_probs / total
class TransductiveBiasCorrection(nn.Module):
def __init__(self, num_iterations=5):
super().__init__()
self.num_iterations = num_iterations
def forward(self, features, classifier, class_embeddings):
classifier.eval()
with torch.no_grad():
logits = classifier(features)
probs = F.softmax(logits, dim=1)
avg_unseen_prob = probs[:, len(classifier.seen_classes):].mean(dim=0)
bias = avg_unseen_prob.mean()
corrected_logits = logits.clone()
corrected_logits[:, len(classifier.seen_classes):] -= bias
return corrected_logits
```
```python
import numpy as np
from sklearn.metrics import accuracy_score
class ZeroShotEvaluator:
def __init__(self, seen_classes, unseen_classes):
self.seen_classes = list(seen_classes)
self.unseen_classes = list(unseen_classes)
def evaluate(self, model, test_features, test_labels, mode="gzsl"):
model.eval()
with torch.no_grad():
logits, class_names = model.predict(test_features)
predictions = logits.argmax(dim=1).numpy()
if mode == "zsl":
unseen_indices = [i for i, c in enumerate(class_names) if c in self.unseen_classes]
pred_unseen = [class_names.index(self.unseen_classes[p]) if p < len(self.seen_classes) else
self.unseen_classes.index(p) for p in predictions]
unseen_mask = [i for i, l in enumerate(test_labels) if l in self.unseen_classes]
seen_mask = [i for i, l in enumerate(test_labels) if l in self.seen_classes]
seen_acc = accuracy_score([test_labels[i] for i in seen_mask],
[predictions[i] for i in seen_mask])
unseen_acc = accuracy_score([self.unseen_classes.index(test_labels[i]) for i in unseen_mask],
[self.unseen_classes.index(class_names[predictions[i]]) for i in unseen_mask])
harmonic_mean = 2 * seen_acc * unseen_acc / (seen_acc + unseen_acc + 1e-10)
return {
"seen_accuracy": seen_acc,
"unseen_accuracy": unseen_acc,
"harmonic_mean": harmonic_mean
}
return {"accuracy": accuracy_score(test_labels, predictions)}
class AttributeBank:
def __init__(self, attribute_file):
self.attributes = self._load_attributes(attribute_file)
self.class_to_attrs = {}
def _load_attributes(self, attribute_file):
import pandas as pd
df = pd.read_csv(attribute_file)
return df
def get_class_attributes(self, class_name):
if class_name not in self.class_to_attrs:
row = self.attributes[self.attributes['class'] == class_name]
self.class_to_attrs[class_name] = torch.tensor(
row.iloc[:, 1:].values.astype(np.float32)
)
return self.class_to_attrs[class_name]
```
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
class DEMLZeroShot(nn.Module):
def __init__(self, seen_classes, unseen_classes, num_attributes=312,
在 GitHub 查看这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看