Skip to main content

A framework for working with graphs alongside PyTorch

Project description

Lign

Lign logo

A graph framework that can be used to implement graph convolutional networks (GCNs), geometry machine learning, continual lifelong learning on graphs and other graph-based machine learning methods alongside PyTorch

View Docs · View Examples · Report Bugs · Request Feature

Contributors Forks Stargazers Issues Mozilla License

Table of Contents

About The Project

Lign (Lifelong learning Induced by Graph Neural networks) is a framework that can be used for a wide range of graph-related problems including but not limited to graph convolutional networks (GCNs), geometry machine learning, continual lifelong learning on graphs and other graph-related machine learning methods with a tight integration to PyTorch. It was build as a component of my master thesis for a proposed lifelong learning techinique (also named Lign) that works on both graph and vector data.

Ligns currently supports a wide range of functionalities such as clustering techiniques, GCN PyTorch module, graph creation and processing, data set to graph convention, rehersal methods/retraining for GCNS and coventional neural networks, and more. Future planned additions include STL file to graph conversion, graph to STL model along with others features.

Getting Started

These are instructions for getting started with development. If only interested in the package, please install Lign via pip install lign, conda install lign -c josuecom -c pytorch or by downloading the package from github and saving it in the site-packages/ directory of your python interpreter.

For more details, please read the developer documentation

Installation

  1. Clone the repo

    git clone https://github.com/JosueCom/Lign.git
    
  2. Switch directory

    cd Lign
    
  3. Install prerequisites

    It is recommended to install PyTorch via the official site first for optimal performance

    pip install -r docs/dev/requirements.txt
    

    Or

    conda env create -f docs/dev/environment.yml -n lign
    conda activate lign
    
  4. Install package

    pip install . --upgrade
    

Usage

It is recommended to run the following instructions in a python console to view all produced output

  • Create a new graph, assign some values and view properties

    import lign as lg
    import torch as th
    
    n = 5
    g = lg.Graph()
    g.add(n)
    g['x'] = th.rand(n, 3) ## Or, g.set_data('x', th.rand(n, 3))
    
    print(g)
    print(g['x']) ## Or, g.get_data('x')
    print(g[0]) ## Or, g.get_nodes(0)
    print(g[[1, 2]]) ## Or, g.get_nodes([1, 2])
    print(g[3:]) ## Or, g.get_nodes(slice(3, None))
    print(g[(4,)]) ## Or, g.get_edges(4)
    
  • Process data with a conventional neural network

    import lign as lg
    import torch as th
    from torch import nn
    
    n = 5
    g = lg.Graph().add(n, self_loop=False, inplace=True) ## No self loop edges added since no relational data is present
    g['x'] = th.rand(n, 3)
    print(g['x'])
    
    # Data that is not relational maybe be process without the need of ligh graphs
    x = = th.rand(n, 3)
    x = linear(x)
    print(x)
    
    # However, you can use if you desire to use graph strctures
    linear = nn.Linear(3, 2)
    g['x'] = linear(g['x']) ## Or, g.apply(linear, data = 'x')
    print(g['x'])
    
  • Process relational data with a GCN

    import lign as lg
    import torch as th
    from torch import nn
    from lign.nn import GCN
    from lign.utils.functions import sum_tensors
    
    n = 5
    g = lg.Graph().add(n, inplace=True)
    g['x'] = th.rand(n, 3)
    print(g['x'])
    
    # 1^{st} Approach: Basic gcn with no message passing
    # ## It can also be processed as if it is not a graph since edge information is not used
    gcn = GCN(nn.Linear(3, 2)) 
    g['x'] = gcn(g, g['x'])
    print(g['x'])
    
    # 2^{nd} Approach: Basic gcn with message passing via neighbors data summation
    g[(2, 3, 4)] = {2, 3, 4} ## Add edges to nodes 2, 3, 4; nodes can be removed via g.remove_edges()
    gcn = GCN(nn.Linear(2, 3), aggregation = sum_tensors)
    g['x'] = gcn(g, g['x'])
    print(g['x'])
    
    # 3^{rd} Approach: Proposed GCN with discovery and inclusion layers
    gcn = GCN(nn.Linear(3, 2), aggregation = sum_tensors, inclusion = nn.Linear(2, 3))
    g['x'] = gcn(g, g['x'])
    print(g['x'])
    
  • Apply function

    import lign as lg
    import torch as th
    from torch import nn
    from lign.nn import GCN
    n = 5
    g = lg.Graph().add(n, inplace=True)
    g['x'] = th.rand(n, 3)
    
    # Use apply if involving individual nodes
    ## Adds 3 to all node's 'x' data in the data set; doesn't require neighbors
    g.apply(lambda x: x + 3, data='x')
    print(g['x'])
    
    # Use push or pull if only involving multiple nodes. Nodes will push/pull data via edges
    ## Sums neighbors 'x' value together; require neighbors
    def sum_tensors(neighs):
        return th.stack(neighs).sum(dim = 0)
    
    g[(2, 3, 4)] = {2, 3, 4}
    g.push(sum_tensors, data='x')
    print(g['x'])
    
  • Use clustering techniques for PyTorch

    from lign.utils.clustering import NN, KNN, KMeans
    import torch as th
    
    n = 20
    x = th.rand(n, 3)
    labels = (x[:, 0] > 0.5)*1
    predict = th.rand(4, 3)
    print(predict)
    
    cluster = NN(x, labels)
    print(cluster(predict))
    
    cluster = KNN(x, labels, k=3)
    print(cluster(predict))
    
    cluster = KMeans(x, k=2)
    print(cluster(predict))
    
  • Create sub graphs

    import lign as lg
    import torch as th
    n = 5
    g = lg.Graph().add(n, inplace=True)
    g['x'] = th.rand(n, 3)
    g[tuple(range(n))] = set(range(3, n)) ## Add edge from each node to 3 and 4
    print(g)
    
    # Make sub graph with all data and edges from parent; edges are updated to reflect new indexes
    sub = g.sub_graph([2, 3, 4], get_data = True, get_edges = True)
    print(sub)
    
    # Make sub graph with only edges from parent; edges are updated to reflect new indexes
    sub = g.sub_graph(2, get_edges = True)
    sub.add(2)
    print(sub)
    
    # Make sub graph with only data from parent
    ## Add nodes not known to the parent graph
    sub = g.sub_graph([3, 4], get_data = True)
    sub.add([lg.node({'x': th.rand(3)}) for i in range(2)], self_loop = False)
    print(sub)
    
    sub[(2, 3)] = sub.get_parent_edges([0, 2])
    print(sub)
    
  • Save and load created graphs

    import lign as lg
    import torch as th
    n = 5
    g = lg.Graph().add(n, inplace=True)
    g['x'] = th.rand(n, 3)
    
    # Save to file
    g.save("data/graph.lign")
    
    # Load from file
    f = lg.Graph("data/graph.lign")
    
    # Check all data are the same
    print((f['x'] == g['x']).all())
    
  • Convert common data set to lign graphs

    import lign.utils as utl
    
    g0, g0_train, g0_validate = utl.load.mnist_to_lign("datasets/CIFAR100")
    
    g1, g1_train, g1_validate = utl.load.cifar_to_lign("datasets/CIFAR100")
    
    g2, g2_train, g2_validate = utl.load.cora_to_lign("datasets/CIFAR100")
    

Please refer to the documentation for other examples

Future

See the open issues for a list of proposed features (and known issues).

Citation

Refer to CITATION.bib for BibTex citation

Contributing

Read CONTRIBUTING.md for details on how to add to this repository.

tl;dr Fork, create a new branch, commits features and make a pull request with documented changes

License

Distributed under the Mozilla Public License Version 2.0. See LICENSE for more information.

Contact

@josuecom_

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lign-0.1.1.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

lign-0.1.1-py3-none-any.whl (24.5 kB view details)

Uploaded Python 3

File details

Details for the file lign-0.1.1.tar.gz.

File metadata

  • Download URL: lign-0.1.1.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/3.10.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.7.6

File hashes

Hashes for lign-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2db9c61fe8bb479bddca42227ab70d29dc02de254dbf5b2907e5496983d7aa57
MD5 241b6a5446f031b945e9c0266d3d4a2e
BLAKE2b-256 a0fbdd6695ac3e1eaeb90117b238d842089c32a54ba7d0c37e1f01a1ccc056cd

See more details on using hashes here.

File details

Details for the file lign-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: lign-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 24.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/3.10.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.7.6

File hashes

Hashes for lign-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c374b9bacbbcbed3e9e60a74d5c9abbfbf316e2b3f366f9278d430f679706284
MD5 b31c4e9663630ebdcc1564bde2c03ed7
BLAKE2b-256 1eab4ec255e82cb62dfe8611301833ef28d5862e28f041e09b515731a7b4102f

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page