Skip to content

Hyperbolic Embedding Engine (L1 Component) ​

Advanced geometric embedding system optimized for hierarchical knowledge representation. Leverages hyperbolic geometry to preserve semantic relationships and enable efficient navigation through complex knowledge structures.

Architecture Overview ​

text
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           Hyperbolic Engine Core             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚         PoincarΓ© Ball Model            β”‚  β”‚
β”‚  β”‚  β€’ Hyperbolic Embeddings               β”‚  β”‚
β”‚  β”‚  β€’ Distance Calculations               β”‚  β”‚
β”‚  β”‚  β€’ Geodesic Path Finding               β”‚  β”‚
β”‚  β”‚  β€’ Hierarchical Optimization           β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚               β”‚               β”‚
    β–Ό               β–Ό               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚Concept  β”‚  β”‚Hierarchical β”‚  β”‚ Navigation  β”‚
β”‚Embedder β”‚  β”‚ Optimizer   β”‚  β”‚ Engine      β”‚
β”‚         β”‚  β”‚             β”‚  β”‚             β”‚
β”‚β€’ Train  β”‚  β”‚β€’ Tree Loss  β”‚  β”‚β€’ Geodesic   β”‚
β”‚β€’ Embed  β”‚  β”‚β€’ Hierarchy  β”‚  β”‚β€’ Search     β”‚
β”‚β€’ Update β”‚  β”‚β€’ Constraint β”‚  β”‚β€’ Pathfind   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Mathematical Foundation ​

PoincarΓ© Ball Model Implementation ​

python
import torch
import torch.nn as nn
import numpy as np
from typing import Tuple, List, Optional

class PoincareBall:
    """PoincarΓ© ball model for hyperbolic geometry operations"""
    
    def __init__(self, dim: int, c: float = 1.0):
        self.dim = dim
        self.c = c  # Curvature parameter
        self.eps = 1e-8  # Numerical stability
    
    def exp_map(self, x: torch.Tensor, v: torch.Tensor) -> torch.Tensor:
        """Exponential map: tangent vector to hyperbolic point"""
        v_norm = torch.norm(v, dim=-1, keepdim=True)
        x_norm_sq = torch.sum(x * x, dim=-1, keepdim=True)
        
        # Compute lambda_x (conformal factor)
        lambda_x = 2 / (1 - self.c * x_norm_sq + self.eps)
        
        # Compute the exponential map
        v_norm_clamped = torch.clamp(v_norm, min=self.eps)
        
        exp_v = torch.tanh(np.sqrt(self.c) * lambda_x * v_norm_clamped / 2)
        exp_v = exp_v / (np.sqrt(self.c) * v_norm_clamped + self.eps) * v
        
        return self.mobius_add(x, exp_v)
    
    def log_map(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        """Logarithmic map: hyperbolic point to tangent vector"""
        xy_diff = self.mobius_add(y, -x)
        xy_diff_norm = torch.norm(xy_diff, dim=-1, keepdim=True)
        
        x_norm_sq = torch.sum(x * x, dim=-1, keepdim=True)
        lambda_x = 2 / (1 - self.c * x_norm_sq + self.eps)
        
        log_factor = (2 / (np.sqrt(self.c) * lambda_x + self.eps)) * \
                    torch.arctanh(np.sqrt(self.c) * xy_diff_norm + self.eps)
        
        return log_factor / (xy_diff_norm + self.eps) * xy_diff
    
    def mobius_add(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        """MΓΆbius addition in PoincarΓ© ball"""
        x_norm_sq = torch.sum(x * x, dim=-1, keepdim=True)
        y_norm_sq = torch.sum(y * y, dim=-1, keepdim=True)
        xy_dot = torch.sum(x * y, dim=-1, keepdim=True)
        
        numerator = (1 + 2 * self.c * xy_dot + self.c * y_norm_sq) * x + \
                   (1 - self.c * x_norm_sq) * y
        
        denominator = 1 + 2 * self.c * xy_dot + self.c**2 * x_norm_sq * y_norm_sq
        
        return numerator / (denominator.unsqueeze(-1) + self.eps)
    
    def distance(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        """Hyperbolic distance between points"""
        xy_diff = self.mobius_add(y, -x)
        xy_diff_norm = torch.norm(xy_diff, dim=-1)
        
        return (2 / np.sqrt(self.c)) * torch.arctanh(
            np.sqrt(self.c) * xy_diff_norm + self.eps
        )
    
    def project_to_ball(self, x: torch.Tensor, max_norm: float = 1 - 1e-3) -> torch.Tensor:
        """Project points to valid PoincarΓ© ball"""
        norm = torch.norm(x, dim=-1, keepdim=True)
        cond = norm >= max_norm
        projected = x / norm * max_norm
        return torch.where(cond, projected, x)

Distance Metrics and Optimization ​

python
class HyperbolicDistanceMetrics:
    """Advanced distance calculations in hyperbolic space"""
    
    def __init__(self, poincare_ball: PoincareBall):
        self.ball = poincare_ball
    
    def semantic_distance(self, 
                         concept1: torch.Tensor, 
                         concept2: torch.Tensor,
                         hierarchy_weight: float = 0.3) -> torch.Tensor:
        """Semantic distance incorporating hierarchical structure"""
        
        # Base hyperbolic distance
        base_distance = self.ball.distance(concept1, concept2)
        
        # Hierarchical adjustment based on norm (distance from origin)
        norm1 = torch.norm(concept1, dim=-1)
        norm2 = torch.norm(concept2, dim=-1)
        
        # Concepts closer to origin are more general/abstract
        hierarchy_penalty = torch.abs(norm1 - norm2) * hierarchy_weight
        
        return base_distance + hierarchy_penalty
    
    def angular_similarity(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        """Angular similarity in hyperbolic space"""
        x_tangent = self.ball.log_map(torch.zeros_like(x), x)
        y_tangent = self.ball.log_map(torch.zeros_like(y), y)
        
        cos_similarity = torch.cosine_similarity(x_tangent, y_tangent, dim=-1)
        return (1 + cos_similarity) / 2  # Normalize to [0, 1]
    
    def centripetal_distance(self, x: torch.Tensor) -> torch.Tensor:
        """Distance from origin (generality measure)"""
        return self.ball.distance(torch.zeros_like(x), x)
    
    def geodesic_midpoint(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        """Find geodesic midpoint between two points"""
        t = 0.5  # Midpoint parameter
        
        # Compute tangent vector from x to y
        tangent_xy = self.ball.log_map(x, y)
        
        # Move halfway along the geodesic
        midpoint = self.ball.exp_map(x, t * tangent_xy)
        
        return self.ball.project_to_ball(midpoint)

Concept Embedding System ​

Hierarchical Concept Embedder ​

python
class HyperbolicConceptEmbedder(nn.Module):
    """Neural network for learning hyperbolic concept embeddings"""
    
    def __init__(self, 
                 vocab_size: int,
                 embed_dim: int,
                 hierarchy_levels: int = 5,
                 curvature: float = 1.0):
        super().__init__()
        
        self.vocab_size = vocab_size
        self.embed_dim = embed_dim
        self.hierarchy_levels = hierarchy_levels
        
        self.ball = PoincareBall(embed_dim, curvature)
        self.metrics = HyperbolicDistanceMetrics(self.ball)
        
        # Euclidean embedding layer
        self.euclidean_embed = nn.Embedding(vocab_size, embed_dim)
        
        # Hyperbolic projection networks
        self.hyperbolic_proj = nn.Sequential(
            nn.Linear(embed_dim, embed_dim * 2),
            nn.ReLU(),
            nn.Linear(embed_dim * 2, embed_dim),
            nn.Tanh()  # Ensure output is in valid range
        )
        
        # Hierarchy level predictor
        self.hierarchy_predictor = nn.Sequential(
            nn.Linear(embed_dim, embed_dim // 2),
            nn.ReLU(),
            nn.Linear(embed_dim // 2, 1),
            nn.Sigmoid()  # Output in [0, 1] for norm scaling
        )
        
        self.init_weights()
    
    def init_weights(self):
        """Initialize weights with small values for numerical stability"""
        nn.init.uniform_(self.euclidean_embed.weight, -0.01, 0.01)
        for layer in self.hyperbolic_proj:
            if isinstance(layer, nn.Linear):
                nn.init.uniform_(layer.weight, -0.01, 0.01)
    
    def forward(self, concept_ids: torch.Tensor) -> torch.Tensor:
        """Embed concepts in hyperbolic space"""
        
        # Get Euclidean embeddings
        euclidean_embeds = self.euclidean_embed(concept_ids)
        
        # Project to hyperbolic space
        hyperbolic_embeds = self.hyperbolic_proj(euclidean_embeds)
        
        # Predict hierarchy level (distance from origin)
        hierarchy_levels = self.hierarchy_predictor(euclidean_embeds)
        
        # Scale embeddings based on hierarchy level
        # More general concepts (lower hierarchy) β†’ closer to origin
        scaled_embeds = hyperbolic_embeds * (0.1 + 0.8 * hierarchy_levels)
        
        # Project to valid PoincarΓ© ball
        return self.ball.project_to_ball(scaled_embeds)
    
    def embed_text(self, text_features: torch.Tensor) -> torch.Tensor:
        """Embed arbitrary text features in hyperbolic space"""
        hyperbolic_embeds = self.hyperbolic_proj(text_features)
        hierarchy_levels = self.hierarchy_predictor(text_features)
        
        scaled_embeds = hyperbolic_embeds * (0.1 + 0.8 * hierarchy_levels)
        return self.ball.project_to_ball(scaled_embeds)

Hierarchical Loss Functions ​

python
class HyperbolicLossFunctions:
    """Specialized loss functions for hyperbolic embeddings"""
    
    def __init__(self, poincare_ball: PoincareBall):
        self.ball = poincare_ball
        self.metrics = HyperbolicDistanceMetrics(poincare_ball)
    
    def hierarchy_preserving_loss(self, 
                                 embeddings: torch.Tensor,
                                 hierarchy_matrix: torch.Tensor,
                                 margin: float = 1.0) -> torch.Tensor:
        """Loss that preserves hierarchical relationships"""
        
        # hierarchy_matrix[i,j] = 1 if concept i is parent of concept j
        batch_size = embeddings.shape[0]
        losses = []
        
        for i in range(batch_size):
            for j in range(i+1, batch_size):
                dist_ij = self.ball.distance(embeddings[i], embeddings[j])
                
                if hierarchy_matrix[i, j] == 1:  # i is parent of j
                    # Parent should be closer to origin (more general)
                    parent_dist = self.metrics.centripetal_distance(embeddings[i])
                    child_dist = self.metrics.centripetal_distance(embeddings[j])
                    
                    # Loss if child is not farther from origin than parent
                    hierarchy_loss = torch.max(
                        torch.tensor(0.0), 
                        margin + parent_dist - child_dist
                    )
                    losses.append(hierarchy_loss)
                
                elif hierarchy_matrix[j, i] == 1:  # j is parent of i
                    parent_dist = self.metrics.centripetal_distance(embeddings[j])
                    child_dist = self.metrics.centripetal_distance(embeddings[i])
                    
                    hierarchy_loss = torch.max(
                        torch.tensor(0.0),
                        margin + parent_dist - child_dist
                    )
                    losses.append(hierarchy_loss)
        
        return torch.mean(torch.stack(losses)) if losses else torch.tensor(0.0)
    
    def semantic_similarity_loss(self,
                                anchor: torch.Tensor,
                                positive: torch.Tensor, 
                                negative: torch.Tensor,
                                margin: float = 2.0) -> torch.Tensor:
        """Triplet loss adapted for hyperbolic space"""
        
        pos_dist = self.ball.distance(anchor, positive)
        neg_dist = self.ball.distance(anchor, negative)
        
        loss = torch.max(
            torch.tensor(0.0),
            pos_dist - neg_dist + margin
        )
        
        return loss
    
    def tree_distortion_loss(self,
                           embeddings: torch.Tensor,
                           tree_distances: torch.Tensor,
                           alpha: float = 1.0) -> torch.Tensor:
        """Minimize distortion between tree distances and hyperbolic distances"""
        
        hyperbolic_distances = torch.cdist(
            embeddings.unsqueeze(0), 
            embeddings.unsqueeze(0),
            p=2
        ).squeeze(0)
        
        # Use PoincarΓ© distance instead of Euclidean
        batch_size = embeddings.shape[0]
        hyp_dist_matrix = torch.zeros(batch_size, batch_size)
        
        for i in range(batch_size):
            for j in range(i+1, batch_size):
                dist = self.ball.distance(embeddings[i], embeddings[j])
                hyp_dist_matrix[i, j] = dist
                hyp_dist_matrix[j, i] = dist
        
        # Mean squared error between tree distances and hyperbolic distances
        mse_loss = torch.nn.functional.mse_loss(
            hyp_dist_matrix, 
            tree_distances
        )
        
        return alpha * mse_loss

Hyperbolic Search Engine ​

python
class HyperbolicSearchEngine:
    """Advanced search using hyperbolic geometry"""
    
    def __init__(self, 
                 embedder: HyperbolicConceptEmbedder,
                 concept_embeddings: torch.Tensor,
                 concept_names: List[str]):
        self.embedder = embedder
        self.concept_embeddings = concept_embeddings
        self.concept_names = concept_names
        self.ball = embedder.ball
        self.metrics = embedder.metrics
    
    def hierarchical_search(self, 
                           query_embedding: torch.Tensor,
                           k: int = 20,
                           hierarchy_bias: float = 0.1) -> List[Tuple[str, float]]:
        """Search with hierarchical bias towards appropriate abstraction level"""
        
        query_level = self.metrics.centripetal_distance(query_embedding)
        
        distances = []
        for i, concept_embed in enumerate(self.concept_embeddings):
            # Base semantic distance
            semantic_dist = self.metrics.semantic_distance(
                query_embedding, concept_embed, hierarchy_bias
            )
            
            # Hierarchy level penalty
            concept_level = self.metrics.centripetal_distance(concept_embed)
            level_penalty = torch.abs(query_level - concept_level) * hierarchy_bias
            
            final_distance = semantic_dist + level_penalty
            distances.append((self.concept_names[i], float(final_distance)))
        
        # Sort by distance and return top k
        distances.sort(key=lambda x: x[1])
        return distances[:k]
    
    def geodesic_path_search(self,
                           start_concept: str,
                           end_concept: str,
                           max_steps: int = 10) -> List[str]:
        """Find semantic path between concepts via geodesics"""
        
        start_idx = self.concept_names.index(start_concept)
        end_idx = self.concept_names.index(end_concept)
        
        start_embed = self.concept_embeddings[start_idx]
        end_embed = self.concept_embeddings[end_idx]
        
        path = [start_concept]
        current_embed = start_embed
        
        for step in range(max_steps):
            if step == max_steps - 1:
                path.append(end_concept)
                break
            
            # Move along geodesic towards target
            t = (step + 1) / max_steps
            tangent_vector = self.ball.log_map(current_embed, end_embed)
            next_embed = self.ball.exp_map(current_embed, t * tangent_vector)
            
            # Find closest concept to this point
            distances = [
                (i, float(self.ball.distance(next_embed, concept_embed)))
                for i, concept_embed in enumerate(self.concept_embeddings)
            ]
            distances.sort(key=lambda x: x[1])
            
            closest_idx = distances[0][0]
            closest_name = self.concept_names[closest_idx]
            
            if closest_name not in path:
                path.append(closest_name)
                current_embed = self.concept_embeddings[closest_idx]
        
        return path
    
    def concept_neighborhood(self,
                           concept: str,
                           radius: float = 1.0,
                           min_similarity: float = 0.5) -> List[Tuple[str, float]]:
        """Find concepts within hyperbolic neighborhood"""
        
        concept_idx = self.concept_names.index(concept)
        concept_embed = self.concept_embeddings[concept_idx]
        
        neighbors = []
        for i, other_embed in enumerate(self.concept_embeddings):
            if i == concept_idx:
                continue
                
            distance = float(self.ball.distance(concept_embed, other_embed))
            
            if distance <= radius:
                # Convert distance to similarity score
                similarity = 1.0 / (1.0 + distance)
                
                if similarity >= min_similarity:
                    neighbors.append((self.concept_names[i], similarity))
        
        neighbors.sort(key=lambda x: x[1], reverse=True)
        return neighbors

Integration with Knowledge Graph ​

Hybrid Graph-Hyperbolic System ​

python
class HyperbolicGraphIntegration:
    """Integration between hyperbolic embeddings and knowledge graphs"""
    
    def __init__(self,
                 hyperbolic_engine: HyperbolicSearchEngine,
                 graph_client):  # Neo4j or other graph DB client
        self.hyp_engine = hyperbolic_engine
        self.graph_client = graph_client
    
    def enhance_graph_with_hyperbolic(self):
        """Add hyperbolic coordinates to graph nodes"""
        
        query = """
        MATCH (c:Concept)
        RETURN c.name as concept_name, id(c) as node_id
        """
        
        results = self.graph_client.run(query)
        
        for record in results:
            concept_name = record['concept_name']
            node_id = record['node_id']
            
            if concept_name in self.hyp_engine.concept_names:
                idx = self.hyp_engine.concept_names.index(concept_name)
                embedding = self.hyp_engine.concept_embeddings[idx]
                
                # Store hyperbolic coordinates in graph
                update_query = """
                MATCH (c:Concept) WHERE id(c) = $node_id
                SET c.hyperbolic_coords = $coords,
                    c.hierarchy_level = $level
                """
                
                hierarchy_level = float(
                    self.hyp_engine.metrics.centripetal_distance(embedding)
                )
                
                self.graph_client.run(update_query, {
                    'node_id': node_id,
                    'coords': embedding.tolist(),
                    'level': hierarchy_level
                })
    
    def hyperbolic_influenced_traversal(self,
                                      start_concept: str,
                                      max_depth: int = 3,
                                      hyperbolic_weight: float = 0.3) -> List[str]:
        """Graph traversal influenced by hyperbolic similarity"""
        
        query = """
        MATCH path = (start:Concept {name: $start_name})-[:RELATED_TO*1..$max_depth]-(end:Concept)
        WHERE start.hyperbolic_coords IS NOT NULL 
        AND end.hyperbolic_coords IS NOT NULL
        RETURN path, end.name as end_name, end.hyperbolic_coords as end_coords
        """
        
        results = self.graph_client.run(query, {
            'start_name': start_concept,
            'max_depth': max_depth
        })
        
        # Get start concept's hyperbolic embedding
        start_idx = self.hyp_engine.concept_names.index(start_concept)
        start_embed = self.hyp_engine.concept_embeddings[start_idx]
        
        scored_paths = []
        for record in results:
            end_coords = torch.tensor(record['end_coords'])
            
            # Combine graph path length with hyperbolic similarity
            path_length = len(record['path']) - 1
            hyp_distance = float(
                self.hyp_engine.ball.distance(start_embed, end_coords)
            )
            
            # Weighted score combining both signals
            combined_score = (1 - hyperbolic_weight) * path_length + \
                           hyperbolic_weight * hyp_distance
            
            scored_paths.append((record['end_name'], combined_score))
        
        scored_paths.sort(key=lambda x: x[1])
        return [name for name, _ in scored_paths]

Provider Abstraction Layer ​

Hyperbolic Backend Interface ​

python
from abc import ABC, abstractmethod
from typing import Protocol, Union

class HyperbolicBackendProvider(Protocol):
    """Abstract interface for hyperbolic geometry backends"""
    
    @abstractmethod
    def embed_concepts(self, concepts: List[str]) -> torch.Tensor:
        """Embed concepts in hyperbolic space"""
        pass
    
    @abstractmethod
    def compute_distance(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        """Compute hyperbolic distance between embeddings"""
        pass
    
    @abstractmethod
    def find_neighbors(self, query: torch.Tensor, k: int) -> List[Tuple[str, float]]:
        """Find k nearest neighbors in hyperbolic space"""
        pass
    
    @abstractmethod
    def save_embeddings(self, path: str) -> bool:
        """Save embeddings to storage"""
        pass
    
    @abstractmethod
    def load_embeddings(self, path: str) -> bool:
        """Load embeddings from storage"""
        pass

class PyTorchHyperbolicProvider(HyperbolicBackendProvider):
    """PyTorch-based hyperbolic geometry implementation"""
    
    def __init__(self, config: dict):
        self.embedder = HyperbolicConceptEmbedder(**config['embedder'])
        self.search_engine = None
        self.config = config
    
    def embed_concepts(self, concepts: List[str]) -> torch.Tensor:
        # Convert concepts to IDs and embed
        concept_ids = self._concepts_to_ids(concepts)
        return self.embedder(concept_ids)
    
    def compute_distance(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
        return self.embedder.ball.distance(x, y)
    
    # ... implement other methods

class GeometricProvider(HyperbolicBackendProvider):
    """Alternative provider using geometric libraries"""
    
    def __init__(self, config: dict):
        # Initialize with different geometric backend
        self.config = config
        # Could use libraries like geomstats, geoopt, etc.
    
    # ... implement interface methods

class HyperbolicProviderFactory:
    """Factory for creating hyperbolic providers"""
    
    _providers = {
        'pytorch': PyTorchHyperbolicProvider,
        'geometric': GeometricProvider,
        # Add more providers as needed
    }
    
    @classmethod
    def create_provider(cls, provider_type: str, config: dict) -> HyperbolicBackendProvider:
        if provider_type not in cls._providers:
            raise ValueError(f"Unknown provider type: {provider_type}")
        
        return cls._providers[provider_type](config)

Performance and Optimization ​

Computational Efficiency ​

python
class HyperbolicOptimization:
    """Performance optimizations for hyperbolic computations"""
    
    @staticmethod
    def batch_distance_computation(embeddings1: torch.Tensor,
                                 embeddings2: torch.Tensor,
                                 ball: PoincareBall) -> torch.Tensor:
        """Efficiently compute pairwise distances"""
        
        # Vectorized MΓΆbius operations for better performance
        batch_size1, batch_size2 = embeddings1.shape[0], embeddings2.shape[0]
        
        # Expand for broadcasting
        x_expanded = embeddings1.unsqueeze(1).expand(-1, batch_size2, -1)
        y_expanded = embeddings2.unsqueeze(0).expand(batch_size1, -1, -1)
        
        # Vectorized distance computation
        distances = torch.zeros(batch_size1, batch_size2)
        
        for i in range(batch_size1):
            for j in range(batch_size2):
                distances[i, j] = ball.distance(
                    x_expanded[i, j], 
                    y_expanded[i, j]
                )
        
        return distances
    
    @staticmethod
    def approximate_distance(x: torch.Tensor, 
                           y: torch.Tensor,
                           tolerance: float = 1e-3) -> torch.Tensor:
        """Fast approximate hyperbolic distance"""
        
        # Use first-order approximation for small distances
        diff = x - y
        diff_norm = torch.norm(diff, dim=-1)
        
        if diff_norm < tolerance:
            # Linear approximation for small distances
            return diff_norm
        else:
            # Fall back to exact computation
            return PoincareBall(x.shape[-1]).distance(x, y)

Training and Evaluation ​

Training Pipeline ​

python
class HyperbolicTrainingPipeline:
    """Complete training pipeline for hyperbolic embeddings"""
    
    def __init__(self, 
                 embedder: HyperbolicConceptEmbedder,
                 loss_functions: HyperbolicLossFunctions,
                 config: dict):
        self.embedder = embedder
        self.loss_functions = loss_functions
        self.config = config
        
        self.optimizer = torch.optim.Adam(
            embedder.parameters(), 
            lr=config['learning_rate']
        )
    
    def train_epoch(self, 
                   concept_data: List[Tuple[str, str, int]], # (parent, child, hierarchy_level)
                   similarity_data: List[Tuple[str, str, float]]) -> float:
        """Train one epoch on hierarchical and similarity data"""
        
        total_loss = 0.0
        batch_size = self.config['batch_size']
        
        # Process hierarchical relationships
        for batch_start in range(0, len(concept_data), batch_size):
            batch = concept_data[batch_start:batch_start + batch_size]
            
            # Convert to embeddings
            parent_embeds = []
            child_embeds = []
            
            for parent, child, level in batch:
                parent_embed = self._get_concept_embedding(parent)
                child_embed = self._get_concept_embedding(child)
                
                parent_embeds.append(parent_embed)
                child_embeds.append(child_embed)
            
            parent_tensor = torch.stack(parent_embeds)
            child_tensor = torch.stack(child_embeds)
            
            # Create hierarchy matrix
            hierarchy_matrix = torch.zeros(len(batch), len(batch))
            for i, (_, _, _) in enumerate(batch):
                hierarchy_matrix[i, i] = 1  # Each parent-child pair
            
            # Compute hierarchical loss
            hier_loss = self.loss_functions.hierarchy_preserving_loss(
                torch.cat([parent_tensor, child_tensor]),
                hierarchy_matrix
            )
            
            self.optimizer.zero_grad()
            hier_loss.backward()
            self.optimizer.step()
            
            total_loss += float(hier_loss)
        
        return total_loss / max(len(concept_data), 1)
    
    def evaluate_embedding_quality(self, test_data: List) -> dict:
        """Evaluate quality of learned embeddings"""
        
        metrics = {
            'hierarchy_preservation': 0.0,
            'semantic_coherence': 0.0,
            'tree_distortion': 0.0
        }
        
        # Implement evaluation metrics
        # ... evaluation logic
        
        return metrics

Explore related documentation:

  • Noosphere Layer - README - πŸ“– Noosphere Layer - README | Step-by-step tutorial for Mnemoverse AI memory engine. Learn spatial memory concepts with practical examples.
  • AI Staff - πŸ“– AI Staff | Step-by-step tutorial for Mnemoverse AI memory engine. Learn spatial memory concepts with practical examples.
  • Architecture - πŸ“– Architecture | Step-by-step tutorial for Mnemoverse AI memory engine. Learn spatial memory concepts with practical examples.
  • Knowledge Graph - πŸ“– Knowledge Graph | Step-by-step tutorial for Mnemoverse AI memory engine. Learn spatial memory concepts with practical examples.
  • MCP Integration - πŸ“– MCP Integration | Step-by-step tutorial for Mnemoverse AI memory engine. Learn spatial memory concepts with practical examples.