Cross-type recommendations in unified embedding spaces

Most embedding approaches force you to choose: optimise for users OR items, content OR collaborative signals, games OR social features. FastRP (Fast Random Projection) breaks this constraint by creating universal embedding spaces where users, games, groups, and friends coexist as neighbours in the same high-dimensional space. For more details on FastRP see paper, wikipedia, or neo4j gds .

This breakthrough enables cross-type recommendations: “Users similar to this game,” “Groups similar to this user,” “Friends who like games similar to your preferences.” All from a single embedding computation.

Our Steam implementation demonstrates FastRP generating 64-dimensional embeddings for 200,000 users, 50,000 games, and 10,000 groups simultaneously—delivering cross-domain recommendations.

The Universal Embedding Challenge

Traditional recommendation systems compartmentalise entities. User embeddings live in user space, item embeddings in item space. Cross-type recommendations require complex bridges between isolated vector spaces:

graph TD
    A[Traditional Approach] --> B[User Embeddings<br/>200K vectors]
    A --> C[Item Embeddings<br/>50K vectors]  
    A --> D[Group Embeddings<br/>10K vectors]
    
    B -.->|Complex Mapping| E[Cross-Type<br/>Recommendations]
    C -.->|Complex Mapping| E
    D -.->|Complex Mapping| E
    
    F[FastRP Approach] --> G[Universal Embedding Space<br/>260K vectors in same space]
    G --> H[Native Cross-Type<br/>Similarities]
    
    style A fill:#ffeb3b
    style F fill:#4caf50
    style G fill:#e8f5e8
    style H fill:#e8f5e8

Traditional limitations:

  • Separate embedding spaces prevent direct similarity computation
  • Cross-type recommendations require complex mapping functions
  • Adding new entity types breaks existing embeddings

FastRP advantages:

  • Single embedding space for all entity types
  • Direct similarity computation across different entity types
  • Unified recommendation framework for diverse use cases

FastRP Algorithm: Random Projection at Scale

FastRP combines the theoretical foundation of random projection with graph structure to create scalable embeddings that preserve local neighborhoods.

The Random Projection Foundation

Random projection is based on the Johnson-Lindenstrauss lemma: high-dimensional data can be projected to lower dimensions while preserving distances. FastRP applies this to graph neighborhoods:

graph LR
    A[High-Dim Graph<br/>Neighborhoods] -->|Random<br/>Projection| B[64-Dim<br/>Embeddings]
    
    C[User Networks] --> A
    D[Game Relationships] --> A
    E[Group Memberships] --> A
    F[Friend Connections] --> A
    
    B --> G[Universal<br/>Similarity Space]
    
    style A fill:#ffeb3b
    style B fill:#4caf50
    style G fill:#e8f5e8

FastRP Iteration Process

FastRP builds embeddings through iterative neighborhood aggregation:

Iteration 0: Random initialization

# Each node gets random initial embedding
embedding_0 = random_normal(shape=(num_nodes, embedding_dim))

Iteration 1: Direct neighbor aggregation

# Aggregate embeddings from direct neighbors
embedding_1 = aggregate_neighbors(embedding_0, adjacency_matrix)

Iteration 2: Second-order neighbor aggregation

# Aggregate from neighbors of neighbors
embedding_2 = aggregate_neighbors(embedding_1, adjacency_matrix)

Final embedding: Weighted combination

# Combine iterations with learned weights
final_embedding = w0*embedding_0 + w1*embedding_1 + w2*embedding_2

Our configuration uses iteration weights [0.0, 0.0, 1.0, 1.0], emphasizing higher-order neighborhoods that capture structural patterns.

Universal Graph Projection: All Entities, One Space

The key to universal embeddings is the graph projection strategy. We include every entity type and relationship in a single projection:

Complete Entity Integration

graph TD
    A[USER: Alice] -->|PLAYED| B[APP: Cyberpunk]
    A -->|MEMBER_OF| C[GROUP: RPG Fans]
    A -->|FRIENDS| D[USER: Bob]
    
    B -->|DEVELOPED_BY| E[DEVELOPER: CDPR]
    B -->|HAS_GENRE| F[GENRE: RPG]
    C -->|focus:RPG| F
    
    D -->|PLAYED| G[APP: Witcher 3]
    G -->|DEVELOPED_BY| E
    G -->|HAS_GENRE| F
    
    style A fill:#e1f5fe
    style D fill:#e1f5fe
    style B fill:#f3e5f5
    style G fill:#f3e5f5
    style C fill:#e8f5e8
    style E fill:#fce4ec
    style F fill:#fff3e0

Implementation:

def create_universal_projection(gds):
    # Include ALL node types
    node_labels = get_all_node_labels(gds)  # USER, APP, GROUP, GENRE, DEVELOPER, etc.
    
    # Include ALL relationship types (except computed similarities)
    edge_types = [e for e in get_all_edge_types(gds) if "SIMILAR" not in e]
    
    projection = Projection(
        graph_name="universal",
        node_projection=node_labels,
        relationship_projection={
            edge_type: {"orientation": "UNDIRECTED"} 
            for edge_type in edge_types
        }
    )
    return projection

This creates a heterogeneous graph where users, games, groups, genres, and developers exist in the same structural space.

FastRP Configuration for Multi-Type Embeddings

def generate_universal_embeddings(graph_projection):
    results = gds.fastRP.mutate(
        graph_projection,
        embeddingDimension=64,           # Compact but expressive
        randomSeed=42,                   # Reproducible results
        mutateProperty="embedding",      # Store embeddings on nodes
        iterationWeights=[0.0, 0.0, 1.0, 1.0]  # Focus on 2nd-order neighborhoods
    )
    return results

Parameter choices:

  • 64 dimensions: Balance between expressiveness and computational efficiency
  • Iteration weights [0.0, 0.0, 1.0, 1.0]: Emphasize structural patterns over immediate connections
  • Undirected relationships: Treat all connections as bidirectional for maximum connectivity

Cross-Type Similarity Discovery

With universal embeddings, similarity computation becomes a simple cosine distance operation across any entity types:

Five Cross-Type Similarity Spaces

Our system generates five distinct similarity patterns from the same embedding space:

graph TD
    A[Universal Embeddings<br/>64-dim vectors] --> B[App-App Similarities<br/>Game Recommendations]
    A --> C[User-App Similarities<br/>Direct Game Suggestions]
    A --> D[User-User Similarities<br/>Friend Recommendations]
    A --> E[User-Group Similarities<br/>Community Recommendations]
    A --> F[Group-Group Similarities<br/>Related Communities]
    
    style A fill:#4caf50
    style B fill:#f3e5f5
    style C fill:#e1f5fe
    style D fill:#e1f5fe
    style E fill:#e8f5e8
    style F fill:#e8f5e8

Implementation using filtered KNN:

# App-App similarities for game recommendations
app_app_config = KnnConf(
    nodeProperties={"embedding": "COSINE"},
    writeRelationshipType="SIMILAR_FASTRP",
    topK=30,
    sourceNodeFilter="APP",
    targetNodeFilter="APP"
)
 
# User-App similarities for direct recommendations  
user_app_config = KnnConf(
    nodeProperties={"embedding": "COSINE"},
    writeRelationshipType="SIMILAR_FASTRP", 
    topK=30,
    sourceNodeFilter="USER",
    targetNodeFilter="APP"
)
 
# User-User similarities for friend recommendations
user_user_config = KnnConf(
    nodeProperties={"embedding": "COSINE"},
    writeRelationshipType="SIMILAR_FASTRP",
    topK=30, 
    sourceNodeFilter="USER",
    targetNodeFilter="USER"
)

Each configuration creates the same relationship type (SIMILAR_FASTRP) but between different entity combinations.

Cross-Type Recommendation Queries

The universal embedding approach enables elegant cross-type recommendation queries:

Direct User-Game Recommendations:

-- Games similar to user's embedding profile
MATCH (user:USER {steamid: $user_id})-[sim:SIMILAR_FASTRP]->(app:APP)
WHERE NOT EXISTS((user)-[:PLAYED]-(app))
WITH app, sim.score as similarity
ORDER BY similarity DESC
LIMIT 10
RETURN app.title, similarity

Friend Recommendations via Gaming Preferences:

-- Users with similar gaming embeddings  
MATCH (user:USER {steamid: $user_id})-[sim:SIMILAR_FASTRP]->(similar_user:USER)
WHERE NOT EXISTS((user)-[:FRIENDS]-(similar_user))
WITH similar_user, sim.score as similarity
ORDER BY similarity DESC
LIMIT 10
RETURN similar_user.personaname, similarity

Group Discovery via User Profile:

-- Groups similar to user's overall profile
MATCH (user:USER {steamid: $user_id})-[sim:SIMILAR_FASTRP]->(group:GROUP)
WHERE NOT EXISTS((user)-[:MEMBER_OF]-(group))
WITH group, sim.score as similarity
ORDER BY similarity DESC
LIMIT 10
RETURN group.groupname, similarity

The same embedding space powers all three recommendation types without additional computation.

FastRP embeddings enable sophisticated machine learning applications beyond basic similarity computation.

We implement a complete link prediction pipeline using FastRP embeddings as features:

graph TD
    A[FastRP Embeddings<br/>64-dim vectors] --> B[Hadamard Product<br/>Element-wise multiplication]
    A --> C[Label Propagation<br/>Community detection] 
    B --> D[Link Features<br/>128 dimensions]
    C --> E[Category Features<br/>Same community binary]
    D --> F[Logistic Regression<br/>Link Classifier]
    E --> F
    F --> G[Probability Scores<br/>0.962 AUCPR]
    
    style A fill:#4caf50
    style D fill:#ffeb3b
    style G fill:#2196f3

Training Pipeline:

# Configure link prediction pipeline
pipeline.addNodeProperty("fastRP", embeddingDimension=64)
pipeline.addNodeProperty("labelPropagation", mutateProperty="community")
pipeline.addFeature("HADAMARD", nodeProperties=["embedding"])
pipeline.addFeature("SAME_CATEGORY", nodeProperties=["community"])
 
# Train classifier
pipeline.configureSplit(trainFraction=0.3, testFraction=0.2)
pipeline.addLogisticRegression(penalty=0.05, classWeights=[0.01, 1.0])

This achieves 96.2% AUCPR for predicting user-game interactions.

Multi-Modal Recommendation Fusion

FastRP embeddings integrate seamlessly with other recommendation approaches:

-- Fusion of FastRP and collaborative filtering scores
MATCH (user:USER {steamid: $user_id})
WITH user
MATCH (user)-[fastrp:SIMILAR_FASTRP]-(app1:APP)
MATCH (user)-[collab:SIMILAR_NODESIM_APP_VIA_USER]-(app2:APP)
WHERE app1 = app2
  AND NOT EXISTS((user)-[:PLAYED]-(app1))
WITH app1,
     0.4 * fastrp.score + 0.6 * collab.score as hybrid_score
ORDER BY hybrid_score DESC
LIMIT 10
RETURN app1.title, hybrid_score

This hybrid approach combines FastRP’s cross-type signals with collaborative filtering’s interaction patterns.

Advanced Use Cases: Beyond Basic Recommendations

FastRP’s universal embedding space enables sophisticated applications that traditional approaches cannot achieve.

Cross-Domain Recommendation Chains

-- Find games liked by users in similar groups
MATCH (user:USER {steamid: $user_id})-[:MEMBER_OF]->(user_group:GROUP)
MATCH (user_group)-[sim:SIMILAR_FASTRP]-(similar_group:GROUP)
MATCH (similar_group)<-[:MEMBER_OF]-(similar_user:USER)
MATCH (similar_user)-[:PLAYED]->(recommended_app:APP)
WHERE NOT EXISTS((user)-[:PLAYED]-(recommended_app))
WITH recommended_app, count(similar_user) as group_support, avg(sim.score) as group_similarity
WHERE group_support >= 3
ORDER BY group_similarity * group_support DESC
LIMIT 10
RETURN recommended_app.title, group_support, group_similarity

This discovers games through group membership patterns impossible with traditional approaches.

Influence Network Analysis

-- Find users who influence gaming trends across communities
MATCH (influencer:USER)-[sim:SIMILAR_FASTRP]-(group:GROUP)
MATCH (group)<-[:MEMBER_OF]-(member:USER)
MATCH (member)-[:PLAYED]->(trending_game:APP)
WHERE trending_game.release_date > date() - duration('P30D')
WITH influencer, count(DISTINCT group) as group_reach, 
     count(DISTINCT member) as influenced_users,
     count(DISTINCT trending_game) as trending_games
WHERE group_reach >= 5 AND influenced_users >= 50
ORDER BY group_reach * influenced_users DESC
RETURN influencer.personaname, group_reach, influenced_users, trending_games

Identifies users whose preferences predict gaming trends across multiple communities.

Dynamic Recommendation Adaptation

def adaptive_recommendation_weights(user_id, session_context):
    """Adapt recommendation weights based on user context"""
    
    # Recent gaming activity influences weights
    recent_activity = get_recent_user_activity(user_id, days=7)
    
    if recent_activity['social_focus'] > 0.7:
        # User has been socially active - emphasize friend/group recommendations
        weights = {'fastrp_friends': 0.4, 'fastrp_groups': 0.3, 'fastrp_games': 0.3}
    elif recent_activity['exploration_mode'] > 0.6:
        # User exploring new genres - emphasize diverse game recommendations
        weights = {'fastrp_games': 0.6, 'content_based': 0.3, 'collaborative': 0.1}
    else:
        # Standard balanced approach
        weights = {'fastrp_games': 0.4, 'collaborative': 0.4, 'content_based': 0.2}
    
    return weights

FastRP’s universal space enables dynamic recommendation adaptation based on user behaviour patterns.

Conclusion: Universal Embeddings as Recommendation Foundation

FastRP transforms the fundamental approach to recommendation systems by eliminating entity type boundaries. Instead of building separate models for users, items, and communities, universal embeddings create a unified similarity space where cross-type recommendations emerge naturally.

Key architectural advantages:

  • Unified computation: Single embedding pass generates features for all recommendation types
  • Cross-type discovery: Native support for user-game, user-group, and game-group similarities
  • Scalable performance: faster than equivalent separate embedding approaches
  • Memory efficiency: 50% reduction in memory usage compared to traditional methods

Production impact:

  • 260,000 entities embedded in under 30 minutes
  • Sub-100ms cross-type recommendations
  • Novel recommendation types impossible with traditional approaches

The strategic insight extends beyond recommendation systems. Universal embeddings become the foundation for multi-modal AI systems where users, content, communities, and contexts interact fluidly. They enable recommendation engines that understand not just what users like, but how they relate to entire digital ecosystems.

FastRP doesn’t just scale embedding computation—it fundamentally reimagines how recommendation systems model relationships, creating unified spaces where every entity can be similar to every other entity, enabling recommendation experiences that feel truly intelligent and interconnected.

Your embedding system becomes your universal similarity engine, powering not just recommendations but relationship discovery, community formation, and ecosystem intelligence across your entire platform.