Combining Multiple Embeddings
2025-07-076 turns7,427 charsgpt-4o
Summary
User seeks a single effective method to combine multiple embeddings from different sources with implementation and explanation.
Messages
[R] Best way to combine multiple embeddings without just concatenating?
Research
Suppose we generate several embeddings for the same entities from different sources or graphs — each capturing different relational or semantic information.
What’s an effective and simple way to combine these embeddings for use in a downstream model, without simply concatenating them (which increases dimensionality )
I’d like to avoid simply averaging or projecting them into a lower dimension, as that can lead to information loss.
Great question — combining multiple embeddings while preserving their distinct semantic contributions *without simply concatenating or averaging* is a hot topic in representation learning and graph-based ML. Here are several **principled alternatives** you might consider, along with brief explanations and references if you're in a research context:
---
### 🧠 1. **Gated Fusion (Learned Attention or Gating Mechanisms)**
Learn to **weigh each embedding dynamically**, per instance or per feature.
- **Idea:** Let the model learn a weighting for each embedding vector (or even for each dimension), often using a small MLP or gating function like sigmoid:
```math
z = σ(W₁e₁ + W₂e₂ + ... + Wₙeₙ)
combined = z₁ ⊙ e₁ + z₂ ⊙ e₂ + ... + zₙ ⊙ eₙ
```
- This lets the model decide how much each embedding contributes to the final representation.
- **Advantage:** Maintains interpretability and avoids naive averaging or dimensionality explosion.
- **Related:** [Gated Multimodal Units](https://arxiv.org/abs/1706.02924), attention in multi-view learning.
---
### 🔄 2. **Cross-Attention / Co-Attention Mechanisms**
Apply attention across embedding types to learn interdependencies.
- For embeddings from different sources \( E_1, E_2, \dots, E_n \), you can compute an attention score between them and fuse them into a context-aware representation.
- Transformers and co-attention layers (e.g., from VQA models) work well here.
- **Reference**: [Multimodal Transformer Models](https://arxiv.org/abs/1909.05258), especially for combining text, graph, and image embeddings.
---
### 📐 3. **Canonical Correlation Analysis (Deep CCA / GCCA)**
Align different embeddings into a shared latent space.
- Rather than averaging or projecting arbitrarily, use techniques like:
- **CCA / DCCA**: Finds linear (or deep) projections of each embedding into a common space where they're maximally correlated.
- **GCCA**: Extends to more than two views (graphs, modalities, etc.).
- Maintains diversity while ensuring alignment.
- **Reference**: [Andrew et al., 2013 (DCCA)](https://proceedings.mlr.press/v28/andrew13.html)
---
### 🧩 4. **Factorization Machines / Interaction Networks**
Use the embeddings as factors and model their **interactions explicitly**.
- Instead of merging embeddings directly, compute second-order or higher interactions between them.
- This works well when downstream models can handle structured input like tuples or attention maps.
- **Reference**: [Factorization Machines](https://www.csie.ntu.edu.tw/~cjlin/papers/fm.pdf), [Interaction Networks](https://arxiv.org/abs/1612.00222).
---
### 🧬 5. **Tensor Fusion / Low-Rank Fusion**
Model multiplicative interactions without blowing up dimensions.
- Tensor fusion captures joint semantics via the outer product, but dimensionality can explode.
- Instead, apply **low-rank tensor decompositions** to make this feasible:
- \( F(e_1, e_2) = \sum_i \sigma(W_i(e_1 \otimes e_2)) \)
- Can be used for combining text/image embeddings, so also works for multiple semantic embeddings.
- **Reference**: [Tensor Fusion Network](https://arxiv.org/abs/1806.04247)
---
### ✳️ 6. **Contrastive Pretraining over Embeddings**
Train an encoder to fuse embeddings such that they match known relationships (e.g., similarity, co-occurrence, label supervision).
- You don’t combine embeddings directly; instead, **train a model to learn an optimal fused representation** using contrastive loss (e.g., InfoNCE or Triplet loss).
- Aligns different embeddings in a task-aware latent space.
- **Examples**: SimCLR-style frameworks, DGI for graphs, CLIP for vision-language.
---
### ⚙️ Summary
| Method | Preserves Structure? | Learns Importance? | Adds Params? | Dim Control |
|--------------------------|----------------------|---------------------|--------------|-------------|
| Gated Fusion | ✅ | ✅ | ✅ | ✅ |
| Cross-Attention | ✅ | ✅ | ✅ | ✅ |
| (D)CCA / (G)CCA | ✅ | ⚠️ linear (or deep) | ⚠️ | ✅ |
| Interaction/Tensor Fusion| ✅ | ✅ | ✅ | ⚠️ |
| Contrastive Pretraining | ✅ | ✅ (via loss) | ✅ | ✅ |
---
Let me know the specifics of your embeddings (e.g., are they node2vec, sentence-BERT, etc.?) and the downstream task (classification, clustering, retrieval?), and I can help you implement a good strategy in PyTorch or TensorFlow.
gpt-4o
choose a single way to do this with an implementation and explain in a paragraph
⚙ model reasoning step
gpt-4o
⚙ model reasoning step
gpt-4o
Below is a compact **PyTorch implementation of gated fusion**, a learn-to-weight approach that preserves each embedding’s information without enlarging dimensionality. The `GatedFusion` module learns a separate sigmoid-gate vector for every input view, multiplies each embedding element-wise by its gate (retaining dimension *d*), sums the gated views, and optionally normalizes the result; you can drop the layer into any downstream model exactly where you would have concatenated:
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
class GatedFusion(nn.Module):
"""
Fuse k embeddings of identical dimensionality d
using learnable element-wise gates (sigmoid).
"""
def __init__(self, num_views: int, dim: int, use_layernorm=True):
super().__init__()
self.gates = nn.Parameter(torch.zeros(num_views, dim)) # start at 0.0 ➜ gate≈0.5
self.use_layernorm = use_layernorm
if use_layernorm:
self.ln = nn.LayerNorm(dim)
def forward(self, views):
"""
views: list[Tensor] of length k, each shape (batch, dim)
returns: fused Tensor of shape (batch, dim)
"""
assert len(views) == self.gates.shape[0], "k views expected"
gated = [torch.sigmoid(g) * v for g, v in zip(self.gates, views)]
fused = torch.stack(gated, dim=0).sum(dim=0) # element-wise sum
return self.ln(fused) if self.use_layernorm else fused
# example usage
batch, d, k = 32, 128, 3
views = [torch.randn(batch, d) for _ in range(k)]
fusion = GatedFusion(k, d)
z = fusion(views) # (batch, 128)
```
**Why this works:** each view keeps its full semantic space, but a small set of parameters (just _k × d_) lets the network learn per-dimension importances during task training; the sigmoid keeps gate values between 0-1, so the fused vector is an interpretable soft selection rather than an arbitrary projection. Because dimensionality stays at *d*, you avoid the memory and overfitting risks of concatenation, yet you lose far less information than uniform averaging—every feature competes to prove its relevance through back-prop, letting the downstream objective dictate the optimal blend.
gpt-4o