FlavorGraph

repository·master·Indexed 42 days ago

https://github.com/lamypark/flavorgraph

A PyTorch implementation of FlavorGraph2Vec for food ingredient pairing recommendations. It analyzes large-scale food-chemical networks using food-food and compound-compound relationships, supporting embedding generation via Metapath2Vec and Node2Vec (DeepWalk) with an optional Chemical Structure Prediction (CSP) layer.

Tokens
7.6K
Snippets
20
Records
31
Agent score
54%

What's inside FlavorGraph

  1. Train the FlavorGraph2Vec model

    master

    Run the training process using src/main.py. You can choose to include or exclude the Chemical Structure Prediction (CSP) layer.

    Basic Training with CSP

    To train the model with the Chemical Structure Prediction layer enabled and save the results:

    python3 src/main.py --CSP_train --CSP_save

    Training without CSP

    To train the model without the Chemical Structure Prediction layer, simply omit the CSP flags:

    python3 src/main.py
  2. Prepare datasets for FlavorGraph2Vec

    master

    FlavorGraph requires specific data files to be placed in designated directories before training:

    1. Pairing Paths: Download the Generated pairing paths and place it in the input/paths folder. If this file is missing, the training script will attempt to generate paths automatically using default settings.
    2. Chemical Fingerprints: To use the Chemical Structure Prediction (CSP) layer, download node2fp_revised_1120.pickle from here and place it in the input folder.
  3. Set up the FlavorGraph development environment

    master

    To run FlavorGraph and FlavorGraph2Vec, ensure your environment meets the following requirements:

    • Python: 3.5.2
    • PyTorch: 1.0.0
    • CUDA: 9.0 (Tested on NVIDIA GeForce Titan X Pascal 12GB)

    If you encounter missing dependency errors, install the required packages using pip install <package_name>.

  4. How category styling is applied in plots

    master

    When withLegends=True is used in plot_category, the visualization applies specific visual encodings to different ingredient types based on their is_hub attribute.

    Category Mapping:

    Categoryis_hub valueColorMarkerSize
    Hub_Ingredient'hub'Orangediamond-x14
    Non_hub_Ingredient'no_hub'Goldenrodsquare8
    Food_like_Compound'food'Greencircle8
    Drug_like_Compound'drug'Pinkcircle9
    None(other)BlackN/AN/A

    Legend Order: The legend is displayed in the following order: Non_hub_Ingredient $\rightarrow$ Food_like_Compound $\rightarrow$ Drug_like_Compound $\rightarrow$ Hub_Ingredient.

  5. Metapath types and node attributes

    master

    When performing metapath walks, the walker relies on specific node attributes within the NetworkX graph to filter neighbors.

    Nodes are categorized by a type and an is_hub status (for ingredients):

    • Compound: Represented by the type 'compound'.
    • Ingredient (Hub): Represented by the string 'ingredient+hub' (where type == 'ingredient' and is_hub == True).
    • Ingredient (Non-Hub): Represented by the string 'ingredient+no_hub' (where type == 'ingredient' and is_hub == False).

    The meta_walk method uses these strings to ensure the walk follows the sequence defined in the metapath.

  6. Configure MetapathWalker arguments for training

    master

    You can customize the metapath walking process by providing specific arguments to the MetapathWalker via the CLI. This allows you to test different variations of metapaths before training begins.

    Available arguments include:

    • --number_of_walks / --num_walks: Number of walks to perform.
    • --walk_length / --len_metapath: Length of each walk.
    • --idx_metapath: The index of the metapath.
    • --which_metapath: The specific metapath string (e.g., 'CHC+CHNHC+NHCHN').
    • --CSP_train / --CSP_save: Flags to enable/save Chemical Structure Prediction.
    python3 src/main.py --number_of_walks 100 \
                        --walk_length 50 \
                        --idx_metapath 'M11' \
                        --which_metapath 'CHC+CHNHC+NHCHN' \
                        --num_walks 100 \
                        --len_metapath 50 \
                        --CSP_train --CSP_save
  7. Use DataReader to process input files and build vocabulary

    master

    The DataReader class is responsible for reading raw text files, building a word-to-ID mapping (vocabulary), and preparing tables for sub-sampling and negative sampling.

    When initialized, it performs the following:

    1. Vocabulary Building: It reads the file specified by inputFileName and maps words that meet the min_count threshold to unique integer IDs.
    2. Sub-sampling Table (initTableDiscards): It calculates a discard probability for each word based on its frequency to implement sub-sampling tricks.
    3. Negative Sampling Table (initTableNegatives): It creates a large table of negative samples (NEGATIVE_TABLE_SIZE defaults to $10^8$) where word selection is weighted by their frequency raised to the power of 0.75.

    Key attributes:

    • word2id: Dictionary mapping words to integer IDs.
    • id2word: Dictionary mapping integer IDs back to words.
    • word_frequency: Dictionary mapping word IDs to their occurrence counts.
    • discards: A NumPy array containing sub-sampling weights for each word ID.
    from dataloader import DataReader
    
    # min_count: minimum word occurrences to be included in vocabulary
    # care_type: determines negative sampling behavior
    # inputFileName: path to the raw text file
    reader = DataReader(min_count=5, care_type=0, inputFileName='path/to/data.txt')
    
    print(f"Vocabulary size: {reader.word_count}")
  8. Generate embeddings using Metapath2Vec

    master

    The Metapath2Vec class implements the Metapath2Vec algorithm to generate node embeddings from graph structures using metapath-based random walks.

    Workflow:

    1. Walker Generation: It uses MetaPathWalker to generate metapath walks. If a file matching the specified parameters already exists in args.input_path, it loads it; otherwise, it generates new walks and saves them.
    2. Data Loading: It uses DataReader to process the walks based on args.min_count and args.care_type.
    3. Training: It initializes a SkipGramModel (or SkipGramModelAux if args.CSP_train is enabled) and trains it using a DataLoader.
    4. Output: The resulting embeddings are saved as a .pickle file.

    Modes:

    • Normal SkipGram: Standard embedding training.
    • SkipGram with CSP: If args.CSP_train is set to True, it uses SkipGramModelAux which includes an auxiliary loss component controlled by args.CSP_coef.
    from graph2vec import Metapath2Vec
    
    # Assuming 'args' is a configured Namespace object containing:
    # input_path, idx_metapath, which_metapath, num_walks, len_metapath, 
    # min_count, care_type, window_size, batch_size, num_workers, dim, 
    # iterations, initial_lr, CSP_train, CSP_coef, CSP_save, output_path, idx_embed
    
    model = Metapath2Vec(args, graph)
    model.train()
  9. Generate metapath walks with MetaPathWalker

    master

    The MetaPathWalker class is used to generate walks through a graph based on specific metapath sequences. It supports both standard random walks and constrained metapath walks.

    To use it, initialize the class with an args object (containing configuration like which_metapath, len_metapath, and input_path) and a networkx graph.

    Key methods:

    • generate_metapaths(args): Returns a list of metapath sequences based on the args.which_metapath flag. Supported flags include:
      • 'CHC': ['compound', 'ingredient+hub']
      • 'CHNHC': ['compound', 'ingredient+hub', 'ingredient+no_hub', 'ingredient+hub']
      • 'NHCHN': ['ingredient+no_hub', 'ingredient+hub', 'compound', 'ingredient+hub']
      • 'RandWalk': Enables standard random walks (sets self.rw = True).
    • create_metapath_walks(args, num_walks, meta_paths): Iterates through the graph nodes to generate the requested number of walks for each provided metapath. The resulting walks are shuffled and saved to a text file following the naming pattern: {input_path}{idx_metapath}-metapath_{which_metapath}-num_walks_{num_walks}-len_metapath.txt.
    from src.walkers import MetaPathWalker
    
    # Assuming 'args' is a configured Namespace object and 'G' is a networkx graph
    walker = MetaPathWalker(args, G)
    metapaths = walker.generate_metapaths(args)
    walker.create_metapath_walks(args, num_walks=10, meta_paths=metapaths)
  10. Read graphs from CSV files using graph_reader()

    master

    The graph_reader function loads a graph structure from two CSV files: one for nodes and one for edges. It returns two NetworkX graph objects:

    1. graph: The full graph containing all nodes (ingredients, food-like compounds, drug-like compounds) and all edges.
    2. graph_ingr_only: A subgraph containing only nodes of type 'ingredient' and edges of type 'ingr-ingr'.

    Node CSV format requirements: The CSV must contain columns in this order: node_id, name, _id, node_type, and is_hub.

    Edge CSV format requirements: The CSV must contain columns in this order: id_1, id_2, score, and edge_type.

    from src.utils import graph_reader
    
    # Assuming nodes.csv and edges.csv exist
    graph, graph_ingr_only = graph_reader('nodes.csv', 'edges.csv')
    
    print(f"Nodes: {graph.number_of_nodes()}")
    print(f"Edges: {graph.number_of_edges()}")
  11. Generate embeddings using Node2Vec (DeepWalk)

    master

    The Node2Vec class implements a DeepWalk-style approach to generating node embeddings.

    Workflow:

    1. Walker Generation: It uses DeepWalker to create features/walks based on args.number_of_walks and args.walk_length.
    2. Data Loading: It reads the generated walks using DataReader.
    3. Training: It initializes a standard SkipGramModel and trains it over a specified number of args.iterations.
    4. Output: Embeddings are saved to a .pickle file in the args.output_path.

    Key Parameters:

    • args.number_of_walks: Number of walks to perform.
    • args.walk_length: Length of each walk.
    • args.dim: Dimension of the resulting embeddings.
    from graph2vec import Node2Vec
    
    # Assuming 'args' is a configured Namespace object containing:
    # input_path, idx_metapath, number_of_walks, walk_length, 
    # min_count, care_type, window_size, batch_size, num_workers, 
    # dim, initial_lr, iterations, output_path, idx_embed
    
    model = Node2Vec(args, graph)
    model.train()