Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

difflogic - A Library for Differentiable Logic Gate Networks

difflogic_logo

This repository includes the official implementation of our NeurIPS 2022 Paper "Deep Differentiable Logic Gate Networks" (Paper @ ArXiv).

The goal behind differentiable logic gate networks is to solve machine learning tasks by learning combinations of logic gates, i.e., so-called logic gate networks. As logic gate networks are conventionally non-differentiable, they can conventionally not be trained with methods such as gradient descent. Thus, differentiable logic gate networks are a differentiable relaxation of logic gate networks which allows efficiently learning of logic gate networks with gradient descent. Specifically, difflogic combines real-valued logics and a continuously parameterized relaxation of the network. This allows learning which logic gate (out of 16 possible) is optimal for each neuron. The resulting discretized logic gate networks achieve fast inference speeds, e.g., beyond a million images of MNIST per second on a single CPU core.

difflogic is a Python 3.6+ and PyTorch 1.9.0+ based library for training and inference with logic gate networks. The library can be installed with:

pip install difflogic

⚠️ Note that difflogic requires CUDA, the CUDA Toolkit (for compilation), and torch>=1.9.0 (matching the CUDA version).

For additional installation support, see INSTALLATION_SUPPORT.md.

🌱 Intro and Training

This library provides a framework for both training and inference with logic gate networks. The following gives an example of a definition of a differentiable logic network model for the MNIST data set:

fromdifflogicimportLogicLayer, GroupSumimporttorchmodel=torch.nn.Sequential(
torch.nn.Flatten(),
LogicLayer(784, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
LogicLayer(16_000, 16_000),
GroupSum(k=10, tau=30)
)

This model receives a 784 dimensional input and returns k=10 values corresponding to the 10 classes of MNIST. The model may be trained, e.g., with a torch.nn.CrossEntropyLoss similar to how other neural networks models are trained in PyTorch. Notably, the Adam optimizer (torch.optim.Adam) should be used for training and the recommended default learning rate is 0.01 instead of 0.001. Finally, it is also important to note that the number of neurons in each layer is much higher for logic gate networks compared to conventional MLP neural networks because logic gate networks are very sparse.

To go into details, for each of these modules, in the following we provide more in-depth examples:

layer=LogicLayer(
in_dim=784, # number of inputsout_dim=16_000, # number of outputsdevice='cuda', # the device (cuda / cpu)implementation='cuda', # the implementation to be used (native cuda / vanilla pytorch)connections='random', # the method for the random initialization of the connectionsgrad_factor=1.1, # for deep models (>6 layers), the grad_factor should be increased (e.g., 2) to avoid vanishing gradients
)

At this point, it is important to discuss the options for device and the provided implementations. Specifically, difflogic provides two implementations (both of which work with PyTorch):

  • python the Python implementation is a substantially slower implementation that is easy to understand as it is implemented directly in Python with PyTorch and does not require any C++ / CUDA extensions. It is compatible with device='cpu' and device='cuda'.
  • cuda is a well-optimized implementation that runs natively on CUDA via custom extensions. This implementation is around 50 to 100 times faster than the python implementation (for large models). It only supports device='cuda'.

To aggregate output neurons into a lower dimensional output space, we can use GroupSum, which aggregates a number of output neurons into a k dimensional output, e.g., k=10 for a 10-dimensional classification setting. It is important to set the parameter tau, which the sum of neurons is divided by to keep the range reasonable. As each neuron has a value between 0 and 1 (or in inference a value of 0 or 1), assuming n output neurons of the last LogicLayer, the range of outputs is [0, n / k / tau].

🖥 Model Inference

During training, the model should remain in the PyTorch training mode (.train()), which keeps the model differentiable. However, we can easily switch the model to a hard / discrete / non-differentiable model by calling model.eval(), i.e., for inference. Typically, this will simply discretize the model but not make it faster per se.

However, there are two modes that allow for fast inference:

PackBitsTensor

The first option is to use a PackBitsTensor. PackBitsTensors allow efficient dynamic execution of trained logic gate networks on GPU.

A PackBitsTensor can package a tensor (of shape b x n) with boolean data type in a way such that each boolean entry requires only a single bit (in contrast to the full byte typically required by a bool) by packing the bits along the batch dimension. If we choose to pack the bits into the int32 data type (the options are 8, 16, 32, and 64 bits), we would receive a tensor of shape ceil(b/32) x n of dtype int32. To create a PackBitsTensor from a boolean tensor data, simply call:

data_bits=difflogic.PackBitsTensor(data)

To apply a model to the PackBitsTensor, simply call:

output=model(data_bits)

This requires that the model is in .eval() mode, and if supplied with a PackBitsTensor, will automatically use a logic gate-based inference on the tensor. This also requires that model.implementation = 'cuda' as the mode is only implemented in CUDA. It is notable that, while the model is in .eval() mode, we can still also feed float tensors through the model, in which case it will simply use a hard variant of the real-valued logics.

CompiledLogicNet

The second option is to use a CompiledLogicNet. This allows especially efficient static execution of a fixed trained logic gate network on CPU. Specifically, CompiledLogicNet converts a model into efficient C code and can compile this code into a binary that can then be efficiently run or exported for applications. The following is an example for creating CompiledLogicNet from a trained model:

compiled_model=difflogic.CompiledLogicNet(
model=model, # the trained model (should be a `torch.nn.Sequential` with `LogicLayer`s)num_bits=64, # the number of bits of the datatype used for inference (typically 64 is fastest, should not be larger than batch size)cpu_compiler='gcc', # the compiler to use for the c code (alternative: clang)verbose=True )
compiled_model.compile(
save_lib_path='my_model_binary.so', # the (optional) location for storing the binary such that it can be reusedverbose=True
)
# to apply the model, we need a 2d numpy array of dtype bool, e.g., via `data = data.bool().numpy()`output=compiled_model(data)

This will compile a model into a shared object binary, which is then automatically imported. To export this to other applications, one may either call the shared object binary from another program or export the model into C code via compiled_model.get_c_code(). A limitation of the current CompiledLogicNet is that the compilation time can become long for large models.

We note that between publishing the paper and the publication of difflogic, we have substantially improved the implementations. Thus, the model inference modes have some deviation from the implementations for the original paper as we have focussed on making it more scalable, efficient, and easier to apply in applications. We have especially focussed on modularity and efficiency for larger models and have opted to polish the presented implementations over publishing a plethora of different competing implementations.

🧪 Experiments

In the following, we present a few example experiments which are contained in the experiments directory. main.py executes the experiments for difflogic and main_baseline.py contains regular neural network baselines.

☄️ Adult / Breast Cancer

python experiments/main.py -eid 526010 -bs 100 -t 20 --dataset adult -ni 100_000 -ef 1_000 -k 256 -l 5 --compile_model
python experiments/main.py -eid 526020 -lr 0.001 -bs 100 -t 20 --dataset breast_cancer -ni 100_000 -ef 1_000 -k 128 -l 5 --compile_model

🔢 MNIST

python experiments/main.py -bs 100 -t 10 --dataset mnist20x20 -ni 200_000 -ef 1_000 -k 8_000 -l 6 --compile_model
python experiments/main.py -bs 100 -t 30 --dataset mnist -ni 200_000 -ef 1_000 -k 64_000 -l 6 --compile_model
# Baselines:
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 128 -l 3
python experiments/main_baseline.py -bs 100 --dataset mnist -ni 200_000 -ef 1_000 -k 2048 -l 7

🐶 CIFAR-10

python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 12_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-3-thresholds -ni 200_000 -ef 1_000 -k 128_000 -l 4 --compile_model
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 256_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 512_000 -l 5
python experiments/main.py -bs 100 -t 100 --dataset cifar-10-31-thresholds -ni 200_000 -ef 1_000 -k 1_024_000 -l 5

📖 Citing

@inproceedings{petersen2022difflogic,
title={{Deep Differentiable Logic Gate Networks}},
author={Petersen, Felix and Borgelt, Christian and Kuehne, Hilde and Deussen, Oliver},
booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
year={2022}
}

📜 License

difflogic is released under the MIT license. See LICENSE for additional details about it.

Patent pending.

About

A library for Differentiable Logic Gate Networks

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages