Browse Source

[FIX] resolve some comments

pull/1/head
troyyyyy 2 years ago
parent
commit
53305ec03b
18 changed files with 409 additions and 325 deletions
  1. +8
    -8
      abl/bridge/base_bridge.py
  2. +12
    -12
      abl/bridge/simple_bridge.py
  3. +3
    -3
      abl/evaluation/reasoning_metric.py
  4. +4
    -4
      abl/evaluation/symbol_metric.py
  5. +1
    -1
      abl/learning/abl_model.py
  6. +1
    -1
      abl/learning/readme.md
  7. +18
    -18
      abl/reasoning/kb.py
  8. +2
    -2
      abl/reasoning/reasoner.py
  9. +185
    -118
      docs/Examples/MNISTAdd.rst
  10. +6
    -6
      docs/Intro/Basics.rst
  11. +8
    -8
      docs/Intro/Bridge.rst
  12. +14
    -3
      docs/Intro/Datasets.rst
  13. +1
    -1
      docs/Intro/Evaluation.rst
  14. +7
    -7
      docs/Intro/Learning.rst
  15. +4
    -4
      docs/Intro/Quick-Start.rst
  16. +19
    -19
      docs/Intro/Reasoning.rst
  17. +4
    -4
      examples/hed/hed_bridge.py
  18. +112
    -106
      examples/mnist_add/mnist_add.ipynb

+ 8
- 8
abl/bridge/base_bridge.py View File

@@ -15,9 +15,9 @@ class BaseBridge(metaclass=ABCMeta):
which involves the following four methods:

- predict: Predict class indices on the given data examples.
- idx_to_pseudo_label: Map indices into pseudo labels.
- abduce_pseudo_label: Revise pseudo labels based on abdutive reasoning.
- pseudo_label_to_idx: Map revised pseudo labels back into indices.
- idx_to_pseudo_label: Map indices into pseudo-labels.
- abduce_pseudo_label: Revise pseudo-labels based on abdutive reasoning.
- pseudo_label_to_idx: Map revised pseudo-labels back into indices.

Parameters
----------
@@ -25,7 +25,7 @@ class BaseBridge(metaclass=ABCMeta):
The machine learning model wrapped in ``ABLModel``, which is mainly used for
prediction and model training.
reasoner : Reasoner
The reasoning part wrapped in ``Reasoner``, which is used for pseudo label revision.
The reasoning part wrapped in ``Reasoner``, which is used for pseudo-label revision.
"""

def __init__(self, model: ABLModel, reasoner: Reasoner) -> None:
@@ -47,18 +47,18 @@ class BaseBridge(metaclass=ABCMeta):

@abstractmethod
def abduce_pseudo_label(self, data_examples: ListData) -> List[List[Any]]:
"""Placeholder for revising pseudo labels based on abdutive reasoning."""
"""Placeholder for revising pseudo-labels based on abdutive reasoning."""

@abstractmethod
def idx_to_pseudo_label(self, data_examples: ListData) -> List[List[Any]]:
"""Placeholder for mapping indices to pseudo labels."""
"""Placeholder for mapping indices to pseudo-labels."""

@abstractmethod
def pseudo_label_to_idx(self, data_examples: ListData) -> List[List[Any]]:
"""Placeholder for mapping pseudo labels to indices."""
"""Placeholder for mapping pseudo-labels to indices."""

def filter_pseudo_label(self, data_examples: ListData) -> List[List[Any]]:
"""Default filter function for pseudo label."""
"""Default filter function for pseudo-label."""
non_empty_idx = [
i
for i in range(len(data_examples.abduced_pseudo_label))


+ 12
- 12
abl/bridge/simple_bridge.py View File

@@ -19,9 +19,9 @@ class SimpleBridge(BaseBridge):
the following five steps:

- Predict class probabilities and indices for the given data examples.
- Map indices into pseudo labels.
- Revise pseudo labels based on abdutive reasoning.
- Map the revised pseudo labels to indices.
- Map indices into pseudo-labels.
- Revise pseudo-labels based on abdutive reasoning.
- Map the revised pseudo-labels to indices.
- Train the model.

Parameters
@@ -30,7 +30,7 @@ class SimpleBridge(BaseBridge):
The machine learning model wrapped in ``ABLModel``, which is mainly used for
prediction and model training.
reasoner : Reasoner
The reasoning part wrapped in ``Reasoner``, which is used for pseudo label revision.
The reasoning part wrapped in ``Reasoner``, which is used for pseudo-label revision.
metric_list : List[BaseMetric]
A list of metrics used for evaluating the model's performance.
"""
@@ -64,24 +64,24 @@ class SimpleBridge(BaseBridge):

def abduce_pseudo_label(self, data_examples: ListData) -> List[List[Any]]:
"""
Revise predicted pseudo labels of the given data examples using abduction.
Revise predicted pseudo-labels of the given data examples using abduction.

Parameters
----------
data_examples : ListData
Data examples containing predicted pseudo labels.
Data examples containing predicted pseudo-labels.

Returns
-------
List[List[Any]]
A list of abduced pseudo labels for the given data examples.
A list of abduced pseudo-labels for the given data examples.
"""
self.reasoner.batch_abduce(data_examples)
return data_examples.abduced_pseudo_label

def idx_to_pseudo_label(self, data_examples: ListData) -> List[List[Any]]:
"""
Map indices of data examples into pseudo labels.
Map indices of data examples into pseudo-labels.

Parameters
----------
@@ -91,7 +91,7 @@ class SimpleBridge(BaseBridge):
Returns
-------
List[List[Any]]
A list of pseudo labels converted from indices.
A list of pseudo-labels converted from indices.
"""
pred_idx = data_examples.pred_idx
data_examples.pred_pseudo_label = [
@@ -101,17 +101,17 @@ class SimpleBridge(BaseBridge):

def pseudo_label_to_idx(self, data_examples: ListData) -> List[List[Any]]:
"""
Map pseudo labels of data examples into indices.
Map pseudo-labels of data examples into indices.

Parameters
----------
data_examples : ListData
Data examples containing pseudo labels.
Data examples containing pseudo-labels.

Returns
-------
List[List[Any]]
A list of indices converted from pseudo labels.
A list of indices converted from pseudo-labels.
"""
abduced_idx = [
[self.reasoner.label_to_idx[_abduced_pseudo_label] for _abduced_pseudo_label in sub_list]


+ 3
- 3
abl/evaluation/reasoning_metric.py View File

@@ -10,7 +10,7 @@ class ReasoningMetric(BaseMetric):
A metrics class for evaluating the model performance on tasks need reasoning.

This class is designed to calculate the accuracy of the reasoing results. Reasoning
results are generated by first using the learning part to predict pseudo labels
results are generated by first using the learning part to predict pseudo-labels
and then using a knowledge base (KB) to perform logical reasoning. The reasoning results
are then compared with the ground truth to calculate the accuracy.

@@ -38,9 +38,9 @@ class ReasoningMetric(BaseMetric):
"""
Process a batch of data examples.

This method takes in a batch of data examples, each containing predicted pseudo labels(pred_pseudo_label), ground truth of reasoning results (Y), and input data (X). It
This method takes in a batch of data examples, each containing predicted pseudo-labels(pred_pseudo_label), ground truth of reasoning results (Y), and input data (X). It
evaluates the reasoning accuracy of each example by comparing the logical reasoning
result (derived using the knowledge base) of the predicted pseudo labels against Y
result (derived using the knowledge base) of the predicted pseudo-labels against Y
The result of this comparison (1 for correct reasoning, 0 for incorrect) is appended
to ``self.results``.



+ 4
- 4
abl/evaluation/symbol_metric.py View File

@@ -28,7 +28,7 @@ class SymbolMetric(BaseMetric):
Processes a batch of data examples.

This method takes in a batch of data examples, each containing a list of predicted
pseudo labels (pred_pseudo_label) and their ground truth (gt_pseudo_label). It
pseudo-labels (pred_pseudo_label) and their ground truth (gt_pseudo_label). It
calculates the accuracy by comparing the two lists. Then, a tuple of correct symbol
count and total symbol count is appended to `self.results`.

@@ -36,8 +36,8 @@ class SymbolMetric(BaseMetric):
----------
data_examples : ListData
A batch of data examples, each containing:
- `pred_pseudo_label`: List of predicted pseudo labels.
- `gt_pseudo_label`: List of ground truth pseudo labels.
- `pred_pseudo_label`: List of predicted pseudo-labels.
- `gt_pseudo_label`: List of ground truth pseudo-labels.

Raises
------
@@ -57,7 +57,7 @@ class SymbolMetric(BaseMetric):
def compute_metrics(self) -> dict:
"""
Compute the symbol accuracy metrics from ``self.results``. It calculates the
percentage of correctly predicted pseudo labels over all pseudo labels.
percentage of correctly predicted pseudo-labels over all pseudo-labels.

Returns
-------


+ 1
- 1
abl/learning/abl_model.py View File

@@ -12,7 +12,7 @@ class ABLModel:
Parameters
----------
base_model : Machine Learning Model
The base machine learning model used for training and prediction. This model should
The machine learning base model used for training and prediction. This model should
implement the 'fit' and 'predict' methods. It's recommended, but not required,for the
model to also implement the 'predict_proba' method for generating probabilistic
predictions.


+ 1
- 1
abl/learning/readme.md View File

@@ -104,7 +104,7 @@
+ The base model to use for training and prediction.

**pseudo_label_list : List[Any]**
+ A list of pseudo labels to use for training.
+ A list of pseudo-labels to use for training.

## 序列化数据
考虑到训练数据可能多种组织形式,比如:\


+ 18
- 18
abl/reasoning/kb.py View File

@@ -23,11 +23,11 @@ class KBBase(ABC):
Parameters
----------
pseudo_label_list : list
List of possible pseudo labels. It's recommended to arrange the pseudo labels in this
List of possible pseudo-labels. It's recommended to arrange the pseudo-labels in this
list so that each aligns with its corresponding index in the base model: the first with
the 0th index, the second with the 1st, and so forth.
max_err : float, optional
The upper tolerance limit when comparing the similarity between a pseudo label example's
The upper tolerance limit when comparing the similarity between a pseudo-label example's
reasoning result and the ground truth. This is only applicable when the reasoning
result is of a numerical type. This is particularly relevant for regression problems where
exact matches might not be feasible. Defaults to 1e-10.
@@ -82,7 +82,7 @@ class KBBase(ABC):
@abstractmethod
def logic_forward(self, pseudo_label: List[Any], x: Optional[List[Any]] = None) -> Any:
"""
How to perform (deductive) logical reasoning, i.e. matching each pseudo label example to
How to perform (deductive) logical reasoning, i.e. matching each pseudo-label example to
their reasoning result. Users are required to provide this.

Parameters
@@ -128,7 +128,7 @@ class KBBase(ABC):
-------
Tuple[List[List[Any]], List[Any]]
A tuple of two element. The first element is a list of candidate revisions, i.e. revised
pseudo label examples that are compatible with the knowledge base. The second element is
pseudo-label examples that are compatible with the knowledge base. The second element is
a list of reasoning results corresponding to each candidate, i.e., the outcome of the
logic_forward function.
"""
@@ -160,7 +160,7 @@ class KBBase(ABC):
revision_idx: List[int],
) -> List[List[Any]]:
"""
Revise the pseudo label example at specified index positions.
Revise the pseudo-label example at specified index positions.

Parameters
----------
@@ -171,13 +171,13 @@ class KBBase(ABC):
x : List[Any]
The corresponding input example.
revision_idx : List[int]
A list specifying indices of where revisions should be made to the pseudo label example.
A list specifying indices of where revisions should be made to the pseudo-label example.

Returns
-------
Tuple[List[List[Any]], List[Any]]
A tuple of two element. The first element is a list of candidate revisions, i.e. revised
pseudo label examples that are compatible with the knowledge base. The second element is
pseudo-label examples that are compatible with the knowledge base. The second element is
a list of reasoning results corresponding to each candidate, i.e., the outcome of the
logic_forward function.
"""
@@ -200,7 +200,7 @@ class KBBase(ABC):
x: List[Any],
) -> List[List[Any]]:
"""
For a specified number of labels in a pseudo label example to revise, iterate through
For a specified number of labels in a pseudo-label example to revise, iterate through
all possible indices to find any candidates that are compatible with the knowledge base.
"""
new_candidates, new_reasoning_results = [], []
@@ -221,7 +221,7 @@ class KBBase(ABC):
) -> List[List[Any]]:
"""
Perform abductive reasoning by exhastive search. Specifically, begin with 0 and
continuously increase the number of labels in a pseudo label example to revise, until
continuously increase the number of labels in a pseudo-label example to revise, until
candidates that are compatible with the knowledge base are found.

Parameters
@@ -236,14 +236,14 @@ class KBBase(ABC):
The upper limit on the number of revisions.
require_more_revision : int
If larger than 0, then after having found any candidates compatible with the
knowledge base, continue to increase the number of labels in a pseudo label example to
knowledge base, continue to increase the number of labels in a pseudo-label example to
revise to get more possible compatible candidates.

Returns
-------
Tuple[List[List[Any]], List[Any]]
A tuple of two element. The first element is a list of candidate revisions, i.e. revised
pseudo label examples that are compatible with the knowledge base. The second element is
pseudo-label examples that are compatible with the knowledge base. The second element is
a list of reasoning results corresponding to each candidate, i.e., the outcome of the
logic_forward function.
"""
@@ -286,7 +286,7 @@ class GroundKB(KBBase):
pseudo_label_list : list
Refer to class `KBBase`.
GKB_len_list : list
List of possible lengths for a pseudo label example.
List of possible lengths for a pseudo-label example.
max_err : float, optional
Refer to class `KBBase`.

@@ -373,7 +373,7 @@ class GroundKB(KBBase):
-------
Tuple[List[List[Any]], List[Any]]
A tuple of two element. The first element is a list of candidate revisions, i.e. revised
pseudo label examples that are compatible with the knowledge base. The second element is
pseudo-label examples that are compatible with the knowledge base. The second element is
a list of reasoning results corresponding to each candidate, i.e., the outcome of the
logic_forward function.
"""
@@ -525,7 +525,7 @@ class PrologKB(KBBase):
x : List[Any]
The corresponding input example.
revision_idx : List[int]
A list specifying indices of where revisions should be made to the pseudo label example.
A list specifying indices of where revisions should be made to the pseudo-label example.

Returns
-------
@@ -546,7 +546,7 @@ class PrologKB(KBBase):
revision_idx: List[int],
) -> List[List[Any]]:
"""
Revise the pseudo label example at specified index positions by querying Prolog.
Revise the pseudo-label example at specified index positions by querying Prolog.

Parameters
----------
@@ -557,15 +557,15 @@ class PrologKB(KBBase):
x : List[Any]
The corresponding input example.
revision_idx : List[int]
A list specifying indices of where revisions should be made to the pseudo label example.
A list specifying indices of where revisions should be made to the pseudo-label example.

Returns
-------
Tuple[List[List[Any]], List[Any]]
A list of candidates, i.e. revised pseudo label examples that are compatible with the
A list of candidates, i.e. revised pseudo-label examples that are compatible with the
knowledge base.
A tuple of two element. The first element is a list of candidate revisions, i.e. revised
pseudo label examples that are compatible with the knowledge base. The second element is
pseudo-label examples that are compatible with the knowledge base. The second element is
a list of reasoning results corresponding to each candidate, i.e., the outcome of the
logic_forward function.
"""


+ 2
- 2
abl/reasoning/reasoner.py View File

@@ -24,7 +24,7 @@ class Reasoner:
abduced label. It can be either a string representing a predefined distance
function or a callable function. The available predefined distance functions:
'hamming' | 'confidence'. 'hamming': directly calculates the Hamming
distance between the predicted pseudo label in the data example and each
distance between the predicted pseudo-label in the data example and each
candidate, 'confidence': calculates the distance between the prediction
and each candidate based on confidence derived from the predicted probability
in the data example. The callable function should have the signature
@@ -279,7 +279,7 @@ class Reasoner:
Returns
-------
List[Any]
A revised pseudo label example through abductive reasoning, which is compatible
A revised pseudo-label example through abductive reasoning, which is compatible
with the knowledge base.
"""
symbol_num = data_example.elements_num("pred_pseudo_label")


+ 185
- 118
docs/Examples/MNISTAdd.rst View File

@@ -1,21 +1,21 @@
MNIST Addition
==============

In this example, we show an implementation of `MNIST
Addition <https://arxiv.org/abs/1805.10872>`_. In this task, pairs of
This notebook shows an implementation of `MNIST
Addition <https://arxiv.org/abs/1805.10872>`__. In this task, pairs of
MNIST handwritten images and their sums are given, alongwith a domain
knowledge base containing information on how to perform addition
operations. The task is to recognize the digits of handwritten
images and accurately determine their sum.
operations. The task is to recognize the digits of handwritten images
and accurately determine their sum.

Intuitively, we first use a machine learning model (learning part) to
convert the input images to digits (we call them pseudo labels), and
convert the input images to digits (we call them pseudo-labels), and
then use the knowledge base (reasoning part) to calculate the sum of
these digits. Since we do not have ground-truth of the digits, in
abductive learning, the reasoning part will leverage domain knowledge
these digits. Since we do not have ground-truth of the digits, in
abductive learning, the reasoning part will leverage domain knowledge
and revise the initial digits yielded by the learning part through
abductive reasoning. This process enables us to further update
the machine learning model.
abductive reasoning. This process enables us to further update the
machine learning model.

.. code:: ipython3

@@ -42,54 +42,99 @@ First, we get the training and testing datasets:
train_data = get_dataset(train=True, get_pseudo_label=True)
test_data = get_dataset(train=False, get_pseudo_label=True)

Both datasets contain several data examples. In each data example, we
have three components: X (a pair of images), gt_pseudo_label (a pair of
corresponding ground truth digits, i.e., pseudo labels), and Y (their sum).
The datasets are illustrated as follows.
Both ``train_data`` and ``test_data`` have the same structures: tuples
with three components: X (list where each element is a pair of images),
gt_pseudo_label (list where each element is a pair of digits) and Y
(list where each element is the sum of each digit pair). The length and
structures of datasets are illustrated as follows.

.. note::

``gt_pseudo_label`` is only used to evaluate the performance of
the learning part but not to train the model.

.. code:: ipython3

def describe_structure(lst):
if not isinstance(lst, list):
return type(lst).__name__
return [describe_structure(item) for item in lst]
print(f"Both train_data and test_data consist of 3 components: X, gt_pseudo_label, Y")
print("\n")
train_X, train_gt_pseudo_label, train_Y = train_data
print(f"Length of X, gt_pseudo_label, Y in train_data: {len(train_X)}, {len(train_gt_pseudo_label)}, {len(train_Y)}")
test_X, test_gt_pseudo_label, test_Y = test_data
print(f"Length of X, gt_pseudo_label, Y in test_data: {len(test_X)}, {len(test_gt_pseudo_label)}, {len(test_Y)}")
print("\n")
structure_X = describe_structure(train_X[0])
structure_gt_pseudo_label = describe_structure(train_gt_pseudo_label[0])
structure_Y = describe_structure(train_Y[0])
print(f"Type of X: {type(train_X).__name__}, and type of each element in X: {structure_X}.")
print(f"Type of gt_pseudo_label: {type(train_gt_pseudo_label).__name__}, and type of each element in gt_pseudo_label: {structure_gt_pseudo_label}.")
print(f"Type of Y: {type(train_Y).__name__}, and type of each element in Y: {structure_Y}.")


Out:
.. code:: none
:class: code-out

Both train_data and test_data consist of 3 components: X, gt_pseudo_label, Y
Length of X, gt_pseudo_label, Y in train_data: 30000, 30000, 30000
Length of X, gt_pseudo_label, Y in test_data: 5000, 5000, 5000
Type of X: list, and type of each element in X: ['Tensor', 'Tensor'].
Type of gt_pseudo_label: list, and type of each element in gt_pseudo_label: ['int', 'int'].
Type of Y: list, and type of each element in Y: int.

The ith element of X, gt_pseudo_label, and Y together constitute the ith
data example. As an illustration, in the first data example of the
training set, we have:

.. code:: ipython3

print(f"There are {len(train_data[0])} data examples in the training set and {len(test_data[0])} data examples in the test set")
print("As an illustration, in the first data example of the training set, we have:")
print(f"X ({len(train_data[0][0])} images):")
first_X, first_gt_pseudo_label, first_Y = train_X[0], train_gt_pseudo_label[0], train_Y[0]
print(f"X in the first data example (a pair of images):")
plt.subplot(1,2,1)
plt.axis('off')
plt.imshow(train_data[0][0][0].numpy().transpose(1, 2, 0))
plt.imshow(first_X[0].numpy().transpose(1, 2, 0))
plt.subplot(1,2,2)
plt.axis('off')
plt.imshow(train_data[0][0][1].numpy().transpose(1, 2, 0))
plt.imshow(first_X[1].numpy().transpose(1, 2, 0))
plt.show()
print(f"gt_pseudo_label ({len(train_data[1][0])} ground truth pseudo label): {train_data[1][0][0]}, {train_data[1][0][1]}")
print(f"Y (their sum result): {train_data[2][0]}")
print(f"gt_pseudo_label in the first data example (a pair of ground truth pseudo-labels): {first_gt_pseudo_label[0]}, {first_gt_pseudo_label[1]}")
print(f"Y in the first data example (their sum result): {first_Y}")


Out:
.. code:: none
:class: code-out
There are 30000 data examples in the training set and 5000 data examples in the test set
As an illustration, in the first data example of the training set, we have:
X (2 images):

X in the first data example (a pair of images):
.. image:: ../img/mnist_add_datasets.png
:width: 400px


.. code:: none
:class: code-out
.. parsed-literal::

gt_pseudo_label (2 ground truth pseudo label): 7, 5
Y (their sum result): 12
gt_pseudo_label in the first data example (a pair of ground truth pseudo-labels): 7, 5
Y in the first data example (their sum result): 12

Building the Learning Part
--------------------------

To build the learning part, we need to first build a base machine
learning model. We use a simple `LeNet-5 neural
network <https://en.wikipedia.org/wiki/LeNet>`__ to complete this task,
and encapsulate it within a ``BasicNN`` object to create the base model.
``BasicNN`` is a class that encapsulates a PyTorch model, transforming
it into a base model with an sklearn-style interface.
To build the learning part, we need to first build a machine learning
base model. We use a simple `LeNet-5 neural
network <https://en.wikipedia.org/wiki/LeNet>`__, and encapsulate it
within a ``BasicNN`` object to create the base model. ``BasicNN`` is a
class that encapsulates a PyTorch model, transforming it into a base
model with an sklearn-style interface.

.. code:: ipython3

@@ -108,53 +153,73 @@ it into a base model with an sklearn-style interface.
)

``BasicNN`` offers methods like ``predict`` and ``predict_prob``, which
are used to predict the outcome class index and the probabilities for an
image, respectively. As shown below:
are used to predict the class index and the probabilities of each class
for images. As shown below:

.. code:: ipython3

pred_idx = base_model.predict(X=[torch.randn(1, 28, 28).to(device) for _ in range(32)])
print(f"Shape of pred_idx for a batch of 32 examples: {pred_idx.shape}")
pred_prob = base_model.predict_proba(X=[torch.randn(1, 28, 28).to(device) for _ in range(32)])
print(f"Shape of pred_prob for a batch of 32 examples: {pred_prob.shape}")
data_instances = [torch.randn(1, 28, 28).to(device) for _ in range(32)]
pred_idx = base_model.predict(X=data_instances)
print(f"Predicted class index for a batch of 32 instances: np.ndarray with shape {pred_idx.shape}")
pred_prob = base_model.predict_proba(X=data_instances)
print(f"Predicted class probabilities for a batch of 32 instances: np.ndarray with shape {pred_prob.shape}")


Out:
.. code:: none
:class: code-out

Shape of pred_idx for a batch of 32 examples: (32,)
Shape of pred_prob for a batch of 32 examples: (32, 10)
Predicted class index for a batch of 32 instances: np.ndarray with shape (32,)
Predicted class probabilities for a batch of 32 instances: np.ndarray with shape (32, 10)

However, the base model built above deals with instance-level data
(i.e., a single image), and can not directly deal with example-level
data (i.e., a pair of images). Therefore, we wrap the base model
into ``ABLModel``, which enables the learning part to train, test,
and predict on example-level data.
However, the base model built above deals with instance-level data
(i.e., individual images), and can not directly deal with example-level
data (i.e., a pair of images). Therefore, we wrap the base model into
``ABLModel``, which enables the learning part to train, test, and
predict on example-level data.

.. code:: ipython3

model = ABLModel(base_model)

TODO: 示例展示ablmodel和base model的predict的不同
As an illustration, consider this example of training on example-level
data using the ``predict`` method in ``ABLModel``. In this process, the
method accepts data examples as input and outputs the class labels and
the probabilities of each class for all instances within these data
examples.

.. code:: ipython3

# from abl.structures import ListData
# data_examples = ListData()
# data_examples.X = [list(torch.randn(2, 1, 28, 28)) for _ in range(3)]
from abl.structures import ListData
# ListData is a data structure provided by ABL-Package that can be used to organize data examples
data_example = ListData()
data_example.X = first_X
data_example.gt_pseudo_label = first_gt_pseudo_label
data_example.Y = first_Y
# Perform prediction on the first data examples
prediction_result = model.predict(data_example)
print(f"Predicted class labels for the first data example: np.array with shape {prediction_result['label'].shape}")
print(f"Predicted class probabilities for the first data example: np.array with shape {prediction_result['prob'].shape}")


Out:
.. code:: none
:class: code-out

Predicted class labels for the first data example: np.array with shape (2,)
Predicted class probabilities for the first data example: np.array with shape (2, 10)
# model.predict(data_examples)

Building the Reasoning Part
---------------------------

In the reasoning part, we first build a knowledge base which contain
information on how to perform addition operations. We build it by
creating a subclass of ``KBBase``. In the derived subclass, we first
creating a subclass of ``KBBase``. In the derived subclass, we
initialize the ``pseudo_label_list`` parameter specifying list of
possible pseudo labels, and then override the ``logic_forward`` function
possible pseudo-labels, and override the ``logic_forward`` function
defining how to perform (deductive) reasoning.

.. code:: ipython3
@@ -169,21 +234,23 @@ defining how to perform (deductive) reasoning.
kb = AddKB()

The knowledge base can perform logical reasoning. Below is an example of
performing (deductive) reasoning: # TODO: ABDUCTIVE REASONING
The knowledge base can perform logical reasoning (both deductive
reasoning and abductive reasoning). Below is an example of performing
(deductive) reasoning, and users can refer to :ref:`Performing abductive
reasoning in the knowledge base <kb-abd>` for details of abductive reasoning.

.. code:: ipython3

pseudo_label_example = [1, 2]
reasoning_result = kb.logic_forward(pseudo_label_example)
print(f"Reasoning result of pseudo label example {pseudo_label_example} is {reasoning_result}.")
print(f"Reasoning result of pseudo-label example {pseudo_label_example} is {reasoning_result}.")


Out:
.. code:: none
:class: code-out

Reasoning result of pseudo label example [1, 2] is 3.
Reasoning result of pseudo-label example [1, 2] is 3.

.. note::
@@ -192,15 +259,15 @@ Out:
can also establish a knowledge base with a ground KB using ``GroundKB``,
or a knowledge base implemented based on Prolog files using
``PrologKB``. The corresponding code for these implementations can be
found in the ``examples/mnist_add/main.py`` file. Those interested are encouraged to
found in the ``main.py`` file. Those interested are encouraged to
examine it for further insights.

Then, we create a reasoner by instantiating the class ``Reasoner``. Due
to the indeterminism of abductive reasoning, there could be multiple
candidates compatible to the knowledge base. When this happens, reasoner
can minimize inconsistencies between the knowledge base and pseudo
labels predicted by the learning part, and then return only one
candidate that has highest consistency.
can minimize inconsistencies between the knowledge base and
pseudo-labels predicted by the learning part, and then return only one
candidate that has the highest consistency.

.. code:: ipython3

@@ -258,60 +325,60 @@ methods of ``SimpleBridge``.
bridge.test(test_data)

Out:
.. code:: none
:class: code-out
abl - INFO - Abductive Learning on the MNIST Addition example.
abl - INFO - loop(train) [1/5] segment(train) [1/3]
abl - INFO - model loss: 1.81231
abl - INFO - loop(train) [1/5] segment(train) [2/3]
abl - INFO - model loss: 1.37639
abl - INFO - loop(train) [1/5] segment(train) [3/3]
abl - INFO - model loss: 1.14446
abl - INFO - Evaluation start: loop(val) [1]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.207 mnist_add/reasoning_accuracy: 0.245
abl - INFO - Saving model: loop(save) [1]
abl - INFO - Checkpoints will be saved to log_dir/weights/model_checkpoint_loop_1.pth
abl - INFO - loop(train) [2/5] segment(train) [1/3]
abl - INFO - model loss: 0.97430
abl - INFO - loop(train) [2/5] segment(train) [2/3]
abl - INFO - model loss: 0.91448
abl - INFO - loop(train) [2/5] segment(train) [3/3]
abl - INFO - model loss: 0.83089
abl - INFO - Evaluation start: loop(val) [2]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.191 mnist_add/reasoning_accuracy: 0.353
abl - INFO - Saving model: loop(save) [2]
abl - INFO - Checkpoints will be saved to log_dir/weights/model_checkpoint_loop_2.pth
abl - INFO - loop(train) [3/5] segment(train) [1/3]
abl - INFO - model loss: 0.79906
abl - INFO - loop(train) [3/5] segment(train) [2/3]
abl - INFO - model loss: 0.77949
abl - INFO - loop(train) [3/5] segment(train) [3/3]
abl - INFO - model loss: 0.75007
abl - INFO - Evaluation start: loop(val) [3]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.148 mnist_add/reasoning_accuracy: 0.385
abl - INFO - Saving model: loop(save) [3]
abl - INFO - Checkpoints will be saved to log_dir/weights/model_checkpoint_loop_3.pth
abl - INFO - loop(train) [4/5] segment(train) [1/3]
abl - INFO - model loss: 0.72659
abl - INFO - loop(train) [4/5] segment(train) [2/3]
abl - INFO - model loss: 0.70985
abl - INFO - loop(train) [4/5] segment(train) [3/3]
abl - INFO - model loss: 0.66337
abl - INFO - Evaluation start: loop(val) [4]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.016 mnist_add/reasoning_accuracy: 0.494
abl - INFO - Saving model: loop(save) [4]
abl - INFO - Checkpoints will be saved to log_dir/weights/model_checkpoint_loop_4.pth
abl - INFO - loop(train) [5/5] segment(train) [1/3]
abl - INFO - model loss: 0.61140
abl - INFO - loop(train) [5/5] segment(train) [2/3]
abl - INFO - model loss: 0.57534
abl - INFO - loop(train) [5/5] segment(train) [3/3]
abl - INFO - model loss: 0.57018
abl - INFO - Evaluation start: loop(val) [5]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.002 mnist_add/reasoning_accuracy: 0.507
abl - INFO - Saving model: loop(save) [5]
abl - INFO - Checkpoints will be saved to log_dir/weights/model_checkpoint_loop_5.pth
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.002 mnist_add/reasoning_accuracy: 0.482
.. code:: none
:class: code-out
abl - INFO - Abductive Learning on the MNIST Addition example.
abl - INFO - loop(train) [1/5] segment(train) [1/3]
abl - INFO - model loss: 1.49104
abl - INFO - loop(train) [1/5] segment(train) [2/3]
abl - INFO - model loss: 1.24945
abl - INFO - loop(train) [1/5] segment(train) [3/3]
abl - INFO - model loss: 0.87861
abl - INFO - Evaluation start: loop(val) [1]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.818 mnist_add/reasoning_accuracy: 0.672
abl - INFO - Saving model: loop(save) [1]
abl - INFO - Checkpoints will be saved to weights_dir/model_checkpoint_loop_1.pth
abl - INFO - loop(train) [2/5] segment(train) [1/3]
abl - INFO - model loss: 0.31148
abl - INFO - loop(train) [2/5] segment(train) [2/3]
abl - INFO - model loss: 0.09520
abl - INFO - loop(train) [2/5] segment(train) [3/3]
abl - INFO - model loss: 0.07402
abl - INFO - Evaluation start: loop(val) [2]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.982 mnist_add/reasoning_accuracy: 0.964
abl - INFO - Saving model: loop(save) [2]
abl - INFO - Checkpoints will be saved to weights_dir/model_checkpoint_loop_2.pth
abl - INFO - loop(train) [3/5] segment(train) [1/3]
abl - INFO - model loss: 0.06027
abl - INFO - loop(train) [3/5] segment(train) [2/3]
abl - INFO - model loss: 0.05341
abl - INFO - loop(train) [3/5] segment(train) [3/3]
abl - INFO - model loss: 0.04915
abl - INFO - Evaluation start: loop(val) [3]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.987 mnist_add/reasoning_accuracy: 0.975
abl - INFO - Saving model: loop(save) [3]
abl - INFO - Checkpoints will be saved to weights_dir/model_checkpoint_loop_3.pth
abl - INFO - loop(train) [4/5] segment(train) [1/3]
abl - INFO - model loss: 0.04413
abl - INFO - loop(train) [4/5] segment(train) [2/3]
abl - INFO - model loss: 0.04181
abl - INFO - loop(train) [4/5] segment(train) [3/3]
abl - INFO - model loss: 0.04127
abl - INFO - Evaluation start: loop(val) [4]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.990 mnist_add/reasoning_accuracy: 0.980
abl - INFO - Saving model: loop(save) [4]
abl - INFO - Checkpoints will be saved to weights_dir/model_checkpoint_loop_4.pth
abl - INFO - loop(train) [5/5] segment(train) [1/3]
abl - INFO - model loss: 0.03544
abl - INFO - loop(train) [5/5] segment(train) [2/3]
abl - INFO - model loss: 0.03092
abl - INFO - loop(train) [5/5] segment(train) [3/3]
abl - INFO - model loss: 0.03663
abl - INFO - Evaluation start: loop(val) [5]
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.991 mnist_add/reasoning_accuracy: 0.982
abl - INFO - Saving model: loop(save) [5]
abl - INFO - Checkpoints will be saved to weights_dir/model_checkpoint_loop_5.pth
abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.987 mnist_add/reasoning_accuracy: 0.974
More concrete examples are available in ``examples/mnist_add/main.py`` and ``examples/mnist_add/mnist_add.ipynb``.

+ 6
- 6
docs/Intro/Basics.rst View File

@@ -55,13 +55,13 @@ Use ABL-Package Step by Step
----------------------------

In a typical Abductive Learning process, as illustrated below,
data inputs are first predicted by a machine learning model, and the outcomes are a pseudo label
example (which consists of multiple pseudo labels).
data inputs are first predicted by a machine learning model, and the outcomes are a pseudo-label
example (which consists of multiple pseudo-labels).
These labels then pass through a knowledge base :math:`\mathcal{KB}`
to obtain the reasoning result by deductive reasoning. During training,
alongside the aforementioned forward flow (i.e., prediction --> deduction reasoning),
there also exists a reverse flow, which starts from the reasoning result and
involves abductive reasoning to generate possible pseudo label examples.
involves abductive reasoning to generate possible pseudo-label examples.
Subsequently, these examples are processed to minimize inconsistencies with machine learning,
which in turn revise the outcomes of the machine learning model, and then
fed back into the machine learning model for further training.
@@ -71,17 +71,17 @@ To implement this process, the following five steps are necessary:

1. Prepare datasets

Prepare the data's input, ground truth for pseudo labels (optional), and ground truth for reasoning results.
Prepare the data's input, ground truth for pseudo-labels (optional), and ground truth for reasoning results.

2. Build the learning part

Build a base machine learning model that can predict inputs to pseudo labels.
Build a machine learning base model that can predict inputs to pseudo-labels.
Then, use ``ABLModel`` to encapsulate the base model.

3. Build the reasoning part

Define a knowledge base by building a subclass of ``KBBase``, specifying how to
map pseudo label examples to reasoning results.
map pseudo-label examples to reasoning results.
Also, create a ``Reasoner`` for minimizing of inconsistencies
between the knowledge base and the learning part.



+ 8
- 8
docs/Intro/Bridge.rst View File

@@ -27,15 +27,15 @@ In this section, we will look at how to bridge learning and reasoning parts to t
+---------------------------------------+----------------------------------------------------+
| Method Signature | Description |
+=======================================+====================================================+
| ``predict(data_examples)`` | Predicts class probabilities and indices |
| | for the given data examples. |
| ``predict(data_examples)`` | Predicts class probabilities and indices |
| | for the given data examples. |
+---------------------------------------+----------------------------------------------------+
| ``abduce_pseudo_label(data_examples)`` | Abduces pseudo labels for the given data examples. |
| ``abduce_pseudo_label(data_examples)``| Abduces pseudo-labels for the given data examples. |
+---------------------------------------+----------------------------------------------------+
| ``idx_to_pseudo_label(data_examples)`` | Converts indices to pseudo labels using |
| ``idx_to_pseudo_label(data_examples)``| Converts indices to pseudo-labels using |
| | the provided or default mapping. |
+---------------------------------------+----------------------------------------------------+
| ``pseudo_label_to_idx(data_examples)`` | Converts pseudo labels to indices |
| ``pseudo_label_to_idx(data_examples)``| Converts pseudo-labels to indices |
| | using the provided or default remapping. |
+---------------------------------------+----------------------------------------------------+
| ``train(train_data)`` | Train the model. |
@@ -48,9 +48,9 @@ where ``train_data`` and ``test_data`` are both in the form of ``(X, gt_pseudo_l
``SimpleBridge`` inherits from ``BaseBridge`` and provides a basic implementation. Besides the ``model`` and ``reasoner``, ``SimpleBridge`` has an extra initialization arguments, ``metric_list``, which will be used to evaluate model performance. Its training process involves several Abductive Learning loops and each loop consists of the following five steps:

1. Predict class probabilities and indices for the given data examples.
2. Transform indices into pseudo labels.
3. Revise pseudo labels based on abdutive reasoning.
4. Transform the revised pseudo labels to indices.
2. Transform indices into pseudo-labels.
3. Revise pseudo-labels based on abdutive reasoning.
4. Transform the revised pseudo-labels to indices.
5. Train the model.

The fundamental part of the ``train`` method is as follows:


+ 14
- 3
docs/Intro/Datasets.rst View File

@@ -24,14 +24,25 @@ Dataset
ABL-Package assumes user data to be structured as a tuple, comprising the following three components:

- ``X``: List[List[Any]]
A list of sublists representing the input data. We refer to each sublist in ``X`` as an example and each example may contain several instances.

- ``gt_pseudo_label``: List[List[Any]], optional
A list of sublists with each sublist representing a ground truth pseudo label example. Each example consists of ground truth pseudo labels for each **instance** within a example of ``X``.
A list of sublists with each sublist representing a ground truth pseudo-label example. Each example consists of ground truth pseudo-labels for each **instance** within a example of ``X``.
.. note::

``gt_pseudo_label`` is only used to evaluate the performance of the learning part but not to train the model. If the pseudo-label of the instances in the datasets are unlabeled, ``gt_pseudo_label`` can be ``None``.

- ``Y``: List[Any]
A list representing the ground truth reasoning result for each **example** in ``X``.


.. warning::
Each sublist in ``gt_pseudo_label`` should have the same length as the sublist in ``X``. ``gt_pseudo_label`` is only used to evaluate the performance of the learning part but not to train the model. If the pseudo label of the instances in the datasets are unlabeled, ``gt_pseudo_label`` can be ``None``.

The length of ``X``, ``gt_pseudo_label`` (if not ``None``) and ``Y`` should be the same. Also, each sublist in ``gt_pseudo_label`` should have the same length as the sublist in ``X``.

As an illustration, in the MNIST Addition example, the data used for training are organized as follows:

@@ -42,7 +53,7 @@ As an illustration, in the MNIST Addition example, the data used for training ar
Data Structure
--------------

In Abductive Learning, there are various types of data in the training and testing process, such as raw data, pseudo label, index of the pseudo label, abduced pseudo label, etc. To enhance the stability and versatility, ABL-Package uses `abstract data interfaces <../API/abl.structures.html>`_ to encapsulate various data during the implementation of the model.
In Abductive Learning, there are various types of data in the training and testing process, such as raw data, pseudo-label, index of the pseudo-label, abduced pseudo-label, etc. To enhance the stability and versatility, ABL-Package uses `abstract data interfaces <../API/abl.structures.html>`_ to encapsulate various data during the implementation of the model.

One of the most commonly used abstract data interface is ``ListData``. Besides orginizing data into tuple, we can also prepare data to be in the form of this data interface.



+ 1
- 1
docs/Intro/Evaluation.rst View File

@@ -24,7 +24,7 @@ To customize our own metrics, we need to inherit from ``BaseMetric`` and impleme
- The ``process`` method accepts a batch of model prediction and saves the information to ``self.results`` property after processing this batch.
- The ``compute_metrics`` method uses all the information saved in ``self.results`` to calculate and return a dict that holds the evaluation results.

Besides, we can assign a ``str`` to the ``prefix`` argument of the ``__init__`` method. This string is automatically prefixed to the output metric names. For example, if we set ``prefix="mnist_add"``, the output metric name will be ``character_accuracy``.
Besides, we can assign a ``str`` to the ``prefix`` argument of the ``__init__`` function. This string is automatically prefixed to the output metric names. For example, if we set ``prefix="mnist_add"``, the output metric name will be ``character_accuracy``.
We provide two basic metrics, namely ``SymbolMetric`` and ``ReasoningMetric``, which are used to evaluate the accuracy of the machine learning model's predictions and the accuracy of the final reasoning results, respectively. Using ``SymbolMetric`` as an example, the following code shows how to implement a custom metrics.

.. code:: python


+ 7
- 7
docs/Intro/Learning.rst View File

@@ -14,8 +14,8 @@ In this section, we will look at how to build the learning part.

In ABL-Package, building the learning part involves two steps:

1. Build a base machine learning model used to make predictions on instance-level data, typically referred to as ``base_model``.
2. Instantiate an ``ABLModel`` with the ``base_model``, which enables the learning part to train, test, and predict on example-level data.
1. Build a machine learning base model used to make predictions on instance-level data.
2. Instantiate an ``ABLModel`` with the base model, which enables the learning part to train, test, and predict on example-level data.

.. code:: python

@@ -27,19 +27,19 @@ In ABL-Package, building the learning part involves two steps:
Building a base model
---------------------

ABL package allows the ``base_model`` to be one of the following forms:
ABL package allows the base model to be one of the following forms:

1. Any machine learning model conforming to the scikit-learn style, i.e., models which has implemented the ``fit`` and ``predict`` methods;

2. A PyTorch-based neural network, provided it has defined the architecture and implemented the ``forward`` method.

For a scikit-learn model, we can directly use the model itself as a ``base_model``. For example, we can customize our ``base_model`` by a KNN classfier:
For a scikit-learn model, we can directly use the model itself as a base model. For example, we can customize our base model by a KNN classfier:

.. code:: python

base_model = sklearn.neighbors.KNeighborsClassifier(n_neighbors=3)

For a PyTorch-based neural network, we need to encapsulate it within a ``BasicNN`` object to create a ``base_model``. For example, we can customize our ``base_model`` by a ResNet-18 neural network:
For a PyTorch-based neural network, we need to encapsulate it within a ``BasicNN`` object to create a base model. For example, we can customize our base model by a ResNet-18 neural network:

.. code:: python

@@ -55,7 +55,7 @@ For a PyTorch-based neural network, we need to encapsulate it within a ``BasicNN
BasicNN
^^^^^^^

``BasicNN`` is a wrapper class for PyTorch-based neural networks, which enables the neural network to work as a scikit-learn model. It encapsulates the neural network, loss function, and optimizer into a single object, which can be used as a ``base_model`` in ``ABLModel``.
``BasicNN`` is a wrapper class for PyTorch-based neural networks, which enables the neural network to work as a scikit-learn model. It encapsulates the neural network, loss function, and optimizer into a single object, which can be used as a base model.

Besides the necessary methods required to instantiate an ``ABLModel``, i.e., ``fit`` and ``predict``, ``BasicNN`` also implements the following methods:

@@ -77,7 +77,7 @@ Besides the necessary methods required to instantiate an ``ABLModel``, i.e., ``f
Instantiating an ABLModel
-------------------------

Typically, ``base_model`` is trained to make predictions on instance-level data, and can not directly utilize example-level data to train and predict, which is not suitable for most neural-symbolic tasks. ABL-Package provides the ``ABLModel`` to solve this problem. This class serves as a unified wrapper for all ``base_model``, which enables the learning part to train, test, and predict on example-level data.
Typically, base model is trained to make predictions on instance-level data, and can not directly utilize example-level data to train and predict, which is not suitable for most neural-symbolic tasks. ABL-Package provides the ``ABLModel`` to solve this problem. This class serves as a unified wrapper for all base models, which enables the learning part to train, test, and predict on example-level data.

Generally, we can simply instantiate an ``ABLModel`` by:



+ 4
- 4
docs/Intro/Quick-Start.rst View File

@@ -33,7 +33,7 @@ Read more about `preparing datasets <Datasets.html>`_.
Building the Learning Part
--------------------------

Learnig part is constructed by first defining a base machine learning model and then wrap it into an instance of ``ABLModel`` class.
Learnig part is constructed by first defining a machine learning base model and then wrap it into an instance of ``ABLModel`` class.
The flexibility of ABL package allows the base model to be any machine learning model conforming to the scikit-learn style, which requires implementing the ``fit`` and ``predict`` methods, or a PyTorch-based neural network, provided it has defined the architecture and implemented the ``forward`` method.
In the MNIST Addition example, we build a simple LeNet5 network as the base model.

@@ -41,7 +41,7 @@ In the MNIST Addition example, we build a simple LeNet5 network as the base mode

from examples.models.nn import LeNet5

# The number of pseudo labels is 10
# The number of pseudo-labels is 10
cls = LeNet5(num_classes=10)

To facilitate uniform processing, ABL-Package provides the ``BasicNN`` class to convert PyTorch-based neural networks into a format similar to scikit-learn models. To construct a ``BasicNN`` instance, we need also define a loss function, an optimizer, and a device aside from the previous network.
@@ -93,8 +93,8 @@ Then, we create a reasoner by instantiating the class
Due to the indeterminism of abductive reasoning, there could
be multiple candidates compatible to the knowledge base.
When this happens, reasoner can minimize inconsistencies between
the knowledge base and pseudo labels predicted by the learning part,
and then return only one candidate which has highest consistency.
the knowledge base and pseudo-labels predicted by the learning part,
and then return only one candidate that has the highest consistency.

.. code:: python



+ 19
- 19
docs/Intro/Reasoning.rst View File

@@ -15,7 +15,7 @@ leverage domain knowledge and perform deductive or abductive reasoning.
In ABL-Package, building the reasoning part involves two steps:

1. Build a knowledge base by creating a subclass of ``KBBase``, which
specifies how to map pseudo label examples to reasoning results.
specifies how to map pseudo-label examples to reasoning results.
2. Create a reasoner by instantiating the class ``Reasoner``
to minimize inconsistencies between the knowledge base and pseudo
labels predicted by the learning part.
@@ -40,11 +40,11 @@ For the user-built KB from ``KBBase`` (a derived subclass), it's only
required to pass the ``pseudo_label_list`` parameter in the ``__init__`` function
and override the ``logic_forward`` function:

- ``pseudo_label_list`` is the list of possible pseudo labels (also,
- ``pseudo_label_list`` is the list of possible pseudo-labels (also,
the output of the machine learning model).
- ``logic_forward`` defines how to perform (deductive) reasoning,
i.e. matching each pseudo label example (often consisting of multiple
pseudo labels) to its reasoning result.
i.e. matching each pseudo-label example (often consisting of multiple
pseudo-labels) to its reasoning result.

After that, other operations, including how to perform abductive
reasoning, will be **automatically** set up.
@@ -54,7 +54,7 @@ MNIST Addition example

As an example, the ``pseudo_label_list`` passed in MNIST Addition is all the
possible digits, namely, ``[0,1,2,...,9]``, and the ``logic_forward``
should be: “Add the two labels in the pseudo label example to get the result.”. Therefore, the
should be: “Add the two labels in the pseudo-label example to get the result.”. Therefore, the
construction of the KB (``add_kb``) for MNIST Addition would be:

.. code:: python
@@ -74,13 +74,13 @@ and (deductive) reasoning in ``add_kb`` would be:

pseudo_label_example = [1, 2]
reasoning_result = add_kb.logic_forward(pseudo_label_example)
print(f"Reasoning result of pseudo label example {pseudo_label_example} is {reasoning_result}.")
print(f"Reasoning result of pseudo-label example {pseudo_label_example} is {reasoning_result}.")

Out:
.. code:: none
:class: code-out

Reasoning result of pseudo label example [1, 2] is 3
Reasoning result of pseudo-label example [1, 2] is 3

.. _other-par:

@@ -91,13 +91,13 @@ We can also pass the following parameters in the ``__init__`` function when buil
knowledge base:

- ``max_err`` (float, optional), specifying the upper tolerance limit
when comparing the similarity between a pseudo label example's reasoning result
when comparing the similarity between a pseudo-label example's reasoning result
and the ground truth during abductive reasoning. This is only
applicable when the reasoning result is of a numerical type. This is
particularly relevant for regression problems where exact matches
might not be feasible. Defaults to 1e-10. See :ref:`an example <kb-abd-2>`.
- ``use_cache`` (bool, optional), indicating whether to use cache to store
previous candidates (pseudo label examples generated from abductive reasoning)
previous candidates (pseudo-label examples generated from abductive reasoning)
to speed up subsequent abductive reasoning operations. Defaults to True.
For more information of abductive reasoning, please refer to :ref:`this <kb-abd>`.
- ``cache_size`` (int, optional), specifying the maximum cache
@@ -173,7 +173,7 @@ override the ``logic_forward`` function, and are allowed to pass other
:ref:`optional parameters <other-par>`. Additionally, we are required pass the
``GKB_len_list`` parameter in the ``__init__`` function.

- ``GKB_len_list`` is the list of possible lengths for a pseudo label example.
- ``GKB_len_list`` is the list of possible lengths for a pseudo-label example.

After that, other operations, including auto-construction of GKB, and
how to perform abductive reasoning, will be **automatically** set up.
@@ -182,7 +182,7 @@ MNIST Addition example (cont.)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

As an example, the ``GKB_len_list`` for MNIST Addition should be ``[2]``,
since all pseudo labels in the example consist of two digits. Therefore,
since all pseudo-labels in the example consist of two digits. Therefore,
the construction of KB with GKB (``add_ground_kb``) of MNIST Addition would be
as follows. As mentioned, the difference between this and the previously
built ``add_kb`` lies only in the base class from which it is derived
@@ -206,17 +206,17 @@ Performing abductive reasoning in the knowledge base
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

As mentioned in :ref:`What is Abductive Reasoning? <abd>`, abductive reasoning
enables the inference of candidates (which are pseudo label examples) as potential
enables the inference of candidates (which are pseudo-label examples) as potential
explanations for the reasoning result. Also, in Abductive Learning where
an observation (a pseudo label example predicted by the learning part) is
an observation (a pseudo-label example predicted by the learning part) is
available, we aim to let the candidate do not largely revise the
previously identified pseudo label example.
previously identified pseudo-label example.

``KBBase`` (also, ``GroundKB`` and ``PrologKB``) implement the method
``abduce_candidates(pseudo_label, y, max_revision_num, require_more_revision)``
for performing abductive reasoning, where the parameters are:

- ``pseudo_label``, the pseudo label example to be revised by abductive
- ``pseudo_label``, the pseudo-label example to be revised by abductive
reasoning, usually generated by the learning part.
- ``y``, the ground truth of the reasoning result for the example. The
returned candidates should be compatible with it.
@@ -228,7 +228,7 @@ for performing abductive reasoning, where the parameters are:
method will only output candidates with the minimum possible
revisions.)

And it return a list of candidates (i.e., revised pseudo label examples) that
And it return a list of candidates (i.e., revised pseudo-label examples) that
are all compatible with ``y``.

MNIST Addition example (cont.)
@@ -277,8 +277,8 @@ After building our knowledge base, the next step is creating a
reasoner. Due to the indeterminism of abductive reasoning, there could
be multiple candidates compatible to the knowledge base. When this
happens, reasoner can minimize inconsistencies between the knowledge
base and pseudo labels predicted by the learning part, and then return **only
one** candidate which has highest consistency.
base and pseudo-labels predicted by the learning part, and then return **only
one** candidate that has the highest consistency.

We can create a reasoner simply by instantiating class
``Reasoner`` and passing our knowledge base as an parameter. As an
@@ -310,7 +310,7 @@ specify:
the distance between the prediction and candidate based on confidence
derived from the predicted probability in the data example. For
“hamming”, it directly calculates the Hamming distance between the
predicted pseudo label in the data example and candidate.
predicted pseudo-label in the data example and candidate.

The main method implemented by ``Reasoner`` is
``abduce(data_example)``, which obtains the most consistent candidate


+ 4
- 4
examples/hed/hed_bridge.py View File

@@ -127,11 +127,11 @@ class HEDBridge(SimpleBridge):
)
return consistent_num / len(data_examples.X)

def get_rules_from_data(self, data_examples, examples_per_rule, examples_num):
def get_rules_from_data(self, data_examples, samples_per_rule, samples_num):
rules = []
sampler = InfiniteSampler(len(data_examples), batch_size=examples_per_rule)
sampler = InfiniteSampler(len(data_examples), batch_size=samples_per_rule)

for _ in range(examples_num):
for _ in range(samples_num):
for select_idx in sampler:
sub_data_examples = data_examples[select_idx]
self.predict(sub_data_examples)
@@ -225,7 +225,7 @@ class HEDBridge(SimpleBridge):
if condition_num >= 5:
print_log("Now checking if we can go to next course", logger="current")
rules = self.get_rules_from_data(
data_examples, examples_per_rule=3, examples_num=50
data_examples, samples_per_rule=3, samples_num=50
)
print_log("Learned rules from data: " + str(rules), logger="current")



+ 112
- 106
examples/mnist_add/mnist_add.ipynb View File

@@ -6,9 +6,9 @@
"source": [
"# MNIST Addition\n",
"\n",
"This notebook shows an implementation of [MNIST Addition](https://arxiv.org/abs/1805.10872). In this task, pairs of MNIST handwritten images and their sums are given, alongwith a domain knowledge base which contain information on how to perform addition operations. Our objective is to input a pair of handwritten images and accurately determine their sum.\n",
"This notebook shows an implementation of [MNIST Addition](https://arxiv.org/abs/1805.10872). In this task, pairs of MNIST handwritten images and their sums are given, alongwith a domain knowledge base containing information on how to perform addition operations. The task is to recognize the digits of handwritten images and accurately determine their sum.\n",
"\n",
"Intuitively, we first use a machine learning model (learning part) to convert the input images to digits (we call them pseudo labels), and then use the knowledge base (reasoning part) to calculate the sum of these digits. Since we do not have ground-truth of the digits, the reasoning part will leverage domain knowledge and revise the initial digits yielded by the learning part into results derived from abductive reasoning. This process enables us to further refine and retrain the machine learning model."
"Intuitively, we first use a machine learning model (learning part) to convert the input images to digits (we call them pseudo-labels), and then use the knowledge base (reasoning part) to calculate the sum of these digits. Since we do not have ground-truth of the digits, in abductive learning, the reasoning part will leverage domain knowledge and revise the initial digits yielded by the learning part through abductive reasoning. This process enables us to further update the machine learning model."
]
},
{
@@ -54,21 +54,71 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Both datasets contain several data examples. In each data example, we have three components: X (a pair of images), gt_pseudo_label (a pair of corresponding ground truth digits, i.e., pseudo labels), and Y (their sum). The datasets are illustrated as follows. "
"Both `train_data` and `test_data` have the same structures: tuples with three components: X (list where each element is a pair of images), gt_pseudo_label (list where each element is a pair of digits) and Y (list where each element is the sum of each digit pair). The length and structures of datasets are illustrated as follows.\n",
"\n",
"Note: ``gt_pseudo_label`` is only used to evaluate the performance of the learning part but not to train the model."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Both train_data and test_data consist of 3 components: X, gt_pseudo_label, Y\n",
"\n",
"\n",
"Length of X, gt_pseudo_label, Y in train_data: 30000, 30000, 30000\n",
"Length of X, gt_pseudo_label, Y in test_data: 5000, 5000, 5000\n",
"\n",
"\n",
"Type of X: list, and type of each element in X: ['Tensor', 'Tensor'].\n",
"Type of gt_pseudo_label: list, and type of each element in gt_pseudo_label: ['int', 'int'].\n",
"Type of Y: list, and type of each element in Y: int.\n"
]
}
],
"source": [
"def describe_structure(lst):\n",
" if not isinstance(lst, list):\n",
" return type(lst).__name__ \n",
" return [describe_structure(item) for item in lst]\n",
"\n",
"print(f\"Both train_data and test_data consist of 3 components: X, gt_pseudo_label, Y\")\n",
"print(\"\\n\")\n",
"train_X, train_gt_pseudo_label, train_Y = train_data\n",
"print(f\"Length of X, gt_pseudo_label, Y in train_data: {len(train_X)}, {len(train_gt_pseudo_label)}, {len(train_Y)}\")\n",
"test_X, test_gt_pseudo_label, test_Y = test_data\n",
"print(f\"Length of X, gt_pseudo_label, Y in test_data: {len(test_X)}, {len(test_gt_pseudo_label)}, {len(test_Y)}\")\n",
"print(\"\\n\")\n",
"structure_X = describe_structure(train_X[0])\n",
"structure_gt_pseudo_label = describe_structure(train_gt_pseudo_label[0])\n",
"structure_Y = describe_structure(train_Y[0])\n",
"print(f\"Type of X: {type(train_X).__name__}, and type of each element in X: {structure_X}.\")\n",
"print(f\"Type of gt_pseudo_label: {type(train_gt_pseudo_label).__name__}, and type of each element in gt_pseudo_label: {structure_gt_pseudo_label}.\")\n",
"print(f\"Type of Y: {type(train_Y).__name__}, and type of each element in Y: {structure_Y}.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ith element of X, gt_pseudo_label, and Y together constitute the ith data example. As an illustration, in the first data example of the training set, we have:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"There are 30000 data examples in the training set and 5000 data examples in the test set\n",
"As an illustration, in the first data example of the training set, we have:\n",
"X (2 images):\n"
"X in the first data example (a pair of images):\n"
]
},
{
@@ -85,24 +135,23 @@
"name": "stdout",
"output_type": "stream",
"text": [
"gt_pseudo_label (2 ground truth pseudo label): 7, 5\n",
"Y (their sum result): 12\n"
"gt_pseudo_label in the first data example (a pair of ground truth pseudo-labels): 7, 5\n",
"Y in the first data example (their sum result): 12\n"
]
}
],
"source": [
"print(f\"There are {len(train_data[0])} data examples in the training set and {len(test_data[0])} data examples in the test set\")\n",
"print(\"As an illustration, in the first data example of the training set, we have:\")\n",
"print(f\"X ({len(train_data[0][0])} images):\")\n",
"first_X, first_gt_pseudo_label, first_Y = train_X[0], train_gt_pseudo_label[0], train_Y[0]\n",
"print(f\"X in the first data example (a pair of images):\")\n",
"plt.subplot(1,2,1)\n",
"plt.axis('off') \n",
"plt.imshow(train_data[0][0][0].numpy().transpose(1, 2, 0))\n",
"plt.imshow(first_X[0].numpy().transpose(1, 2, 0))\n",
"plt.subplot(1,2,2)\n",
"plt.axis('off') \n",
"plt.imshow(train_data[0][0][1].numpy().transpose(1, 2, 0))\n",
"plt.imshow(first_X[1].numpy().transpose(1, 2, 0))\n",
"plt.show()\n",
"print(f\"gt_pseudo_label ({len(train_data[1][0])} ground truth pseudo label): {train_data[1][0][0]}, {train_data[1][0][1]}\")\n",
"print(f\"Y (their sum result): {train_data[2][0]}\")"
"print(f\"gt_pseudo_label in the first data example (a pair of ground truth pseudo-labels): {first_gt_pseudo_label[0]}, {first_gt_pseudo_label[1]}\")\n",
"print(f\"Y in the first data example (their sum result): {first_Y}\")"
]
},
{
@@ -117,12 +166,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"To build the learning part, we need to first build a base machine learning model. We use a simple [LeNet-5 neural network](https://en.wikipedia.org/wiki/LeNet) to complete this task, and encapsulate it within a `BasicNN` object to create the base model. `BasicNN` is a class that encapsulates a PyTorch model, transforming it into a base model with an sklearn-style interface. "
"To build the learning part, we need to first build a machine learning base model. We use a simple [LeNet-5 neural network](https://en.wikipedia.org/wiki/LeNet), and encapsulate it within a `BasicNN` object to create the base model. `BasicNN` is a class that encapsulates a PyTorch model, transforming it into a base model with an sklearn-style interface. "
]
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@@ -145,40 +194,41 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"`BasicNN` offers methods like `predict` and `predict_prob`, which are used to predict the outcome class index and the probabilities for an image, respectively. As shown below:"
"`BasicNN` offers methods like `predict` and `predict_prob`, which are used to predict the class index and the probabilities of each class for images. As shown below:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Shape of pred_idx for a batch of 32 samples: (32,)\n",
"Shape of pred_prob for a batch of 32 samples: (32, 10)\n"
"Predicted class index for a batch of 32 instances: np.ndarray with shape (32,)\n",
"Predicted class probabilities for a batch of 32 instances: np.ndarray with shape (32, 10)\n"
]
}
],
"source": [
"pred_idx = base_model.predict(X=[torch.randn(1, 28, 28).to(device) for _ in range(32)])\n",
"print(f\"Shape of pred_idx for a batch of 32 examples: {pred_idx.shape}\")\n",
"pred_prob = base_model.predict_proba(X=[torch.randn(1, 28, 28).to(device) for _ in range(32)])\n",
"print(f\"Shape of pred_prob for a batch of 32 examples: {pred_prob.shape}\")"
"data_instances = [torch.randn(1, 28, 28).to(device) for _ in range(32)]\n",
"pred_idx = base_model.predict(X=data_instances)\n",
"print(f\"Predicted class index for a batch of 32 instances: np.ndarray with shape {pred_idx.shape}\")\n",
"pred_prob = base_model.predict_proba(X=data_instances)\n",
"print(f\"Predicted class probabilities for a batch of 32 instances: np.ndarray with shape {pred_prob.shape}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"However, base model built above are trained to make predictions on instance-level data, i.e., a single image, and can not directly utilize example-level data, i.e., a pair of images. Therefore, we then wrap the base model into `ABLModel` which enables the learning part to train, test, and predict on example-level data."
"However, the base model built above deals with instance-level data (i.e., individual images), and can not directly deal with example-level data (i.e., a pair of images). Therefore, we wrap the base model into `ABLModel`, which enables the learning part to train, test, and predict on example-level data."
]
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@@ -189,20 +239,35 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"TODO: 示例展示ablmodel和base model的predict的不同"
"As an illustration, consider this example of training on example-level data using the `predict` method in `ABLModel`. In this process, the method accepts data examples as input and outputs the class labels and the probabilities of each class for all instances within these data examples."
]
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 8,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Predicted class labels for the first data example: np.array with shape (2,)\n",
"Predicted class probabilities for the first data example: np.array with shape (2, 10)\n"
]
}
],
"source": [
"# from abl.structures import ListData\n",
"# data_examples = ListData()\n",
"# data_examples.X = [list(torch.randn(2, 1, 28, 28)) for _ in range(3)]\n",
"from abl.structures import ListData\n",
"# ListData is a data structure provided by ABL-Package that can be used to organize data examples\n",
"data_example = ListData()\n",
"data_example.X = first_X\n",
"data_example.gt_pseudo_label = first_gt_pseudo_label\n",
"data_example.Y = first_Y\n",
"\n",
"# model.predict(data_examples)"
"# Perform prediction on the first data examples\n",
"prediction_result = model.predict(data_example)\n",
"print(f\"Predicted class labels for the first data example: np.array with shape {prediction_result['label'].shape}\")\n",
"print(f\"Predicted class probabilities for the first data example: np.array with shape {prediction_result['prob'].shape}\")"
]
},
{
@@ -216,12 +281,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"In the reasoning part, we first build a knowledge base which contain information on how to perform addition operations. We build it by creating a subclass of `KBBase`. In the derived subclass, we have to first initialize the `pseudo_label_list` parameter specifying list of possible pseudo labels, and then override the `logic_forward` function defining how to perform (deductive) reasoning."
"In the reasoning part, we first build a knowledge base which contain information on how to perform addition operations. We build it by creating a subclass of `KBBase`. In the derived subclass, we initialize the `pseudo_label_list` parameter specifying list of possible pseudo-labels, and override the `logic_forward` function defining how to perform (deductive) reasoning."
]
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
@@ -240,26 +305,26 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The knowledge base can perform logical reasoning. Below is an example of performing (deductive) reasoning: # TODO: ABDUCTIVE REASONING"
"The knowledge base can perform logical reasoning (both deductive reasoning and abductive reasoning). Below is an example of performing (deductive) reasoning, and users can refer to [Documentation]() for details of abductive reasoning."
]
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Reasoning result of pseudo label sample [1, 2] is 3.\n"
"Reasoning result of pseudo-label example [1, 2] is 3.\n"
]
}
],
"source": [
"pseudo_label_example = [1, 2]\n",
"reasoning_result = kb.logic_forward(pseudo_label_example)\n",
"print(f\"Reasoning result of pseudo label example {pseudo_label_example} is {reasoning_result}.\")"
"print(f\"Reasoning result of pseudo-label example {pseudo_label_example} is {reasoning_result}.\")"
]
},
{
@@ -273,12 +338,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Then, we create a reasoner by instantiating the class ``Reasoner``. Due to the indeterminism of abductive reasoning, there could be multiple candidates compatible to the knowledge base. When this happens, reasoner can minimize inconsistencies between the knowledge base and pseudo labels predicted by the learning part, and then return only one candidate which has highest consistency."
"Then, we create a reasoner by instantiating the class ``Reasoner``. Due to the indeterminism of abductive reasoning, there could be multiple candidates compatible to the knowledge base. When this happens, reasoner can minimize inconsistencies between the knowledge base and pseudo-labels predicted by the learning part, and then return only one candidate that has the highest consistency."
]
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
@@ -311,7 +376,7 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
@@ -330,7 +395,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
@@ -346,68 +411,9 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"12/19 14:41:46 - abl - INFO - Abductive Learning on the MNIST Addition example.\n",
"12/19 14:41:46 - abl - INFO - loop(train) [1/5] segment(train) [1/3] \n",
"12/19 14:41:51 - abl - INFO - model loss: 1.81279\n",
"12/19 14:41:51 - abl - INFO - loop(train) [1/5] segment(train) [2/3] \n",
"12/19 14:41:56 - abl - INFO - model loss: 1.40474\n",
"12/19 14:41:56 - abl - INFO - loop(train) [1/5] segment(train) [3/3] \n",
"12/19 14:42:01 - abl - INFO - model loss: 1.17817\n",
"12/19 14:42:01 - abl - INFO - Evaluation start: loop(val) [1]\n",
"12/19 14:42:02 - abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.496 mnist_add/reasoning_accuracy: 0.336 \n",
"12/19 14:42:02 - abl - INFO - Saving model: loop(save) [1]\n",
"12/19 14:42:02 - abl - INFO - Checkpoints will be saved to results/20231219_14_41_46/weights/model_checkpoint_loop_1.pth\n",
"12/19 14:42:02 - abl - INFO - loop(train) [2/5] segment(train) [1/3] \n",
"12/19 14:42:07 - abl - INFO - model loss: 0.85932\n",
"12/19 14:42:07 - abl - INFO - loop(train) [2/5] segment(train) [2/3] \n",
"12/19 14:42:11 - abl - INFO - model loss: 0.62120\n",
"12/19 14:42:11 - abl - INFO - loop(train) [2/5] segment(train) [3/3] \n",
"12/19 14:42:16 - abl - INFO - model loss: 0.35382\n",
"12/19 14:42:16 - abl - INFO - Evaluation start: loop(val) [2]\n",
"12/19 14:42:17 - abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.980 mnist_add/reasoning_accuracy: 0.961 \n",
"12/19 14:42:17 - abl - INFO - Saving model: loop(save) [2]\n",
"12/19 14:42:17 - abl - INFO - Checkpoints will be saved to results/20231219_14_41_46/weights/model_checkpoint_loop_2.pth\n",
"12/19 14:42:17 - abl - INFO - loop(train) [3/5] segment(train) [1/3] \n",
"12/19 14:42:21 - abl - INFO - model loss: 0.08302\n",
"12/19 14:42:21 - abl - INFO - loop(train) [3/5] segment(train) [2/3] \n",
"12/19 14:42:25 - abl - INFO - model loss: 0.05917\n",
"12/19 14:42:25 - abl - INFO - loop(train) [3/5] segment(train) [3/3] \n",
"12/19 14:42:30 - abl - INFO - model loss: 0.05425\n",
"12/19 14:42:30 - abl - INFO - Evaluation start: loop(val) [3]\n",
"12/19 14:42:31 - abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.988 mnist_add/reasoning_accuracy: 0.976 \n",
"12/19 14:42:31 - abl - INFO - Saving model: loop(save) [3]\n",
"12/19 14:42:31 - abl - INFO - Checkpoints will be saved to results/20231219_14_41_46/weights/model_checkpoint_loop_3.pth\n",
"12/19 14:42:31 - abl - INFO - loop(train) [4/5] segment(train) [1/3] \n",
"12/19 14:42:35 - abl - INFO - model loss: 0.04650\n",
"12/19 14:42:35 - abl - INFO - loop(train) [4/5] segment(train) [2/3] \n",
"12/19 14:42:39 - abl - INFO - model loss: 0.04175\n",
"12/19 14:42:39 - abl - INFO - loop(train) [4/5] segment(train) [3/3] \n",
"12/19 14:42:44 - abl - INFO - model loss: 0.04207\n",
"12/19 14:42:44 - abl - INFO - Evaluation start: loop(val) [4]\n",
"12/19 14:42:45 - abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.990 mnist_add/reasoning_accuracy: 0.979 \n",
"12/19 14:42:45 - abl - INFO - Saving model: loop(save) [4]\n",
"12/19 14:42:45 - abl - INFO - Checkpoints will be saved to results/20231219_14_41_46/weights/model_checkpoint_loop_4.pth\n",
"12/19 14:42:45 - abl - INFO - loop(train) [5/5] segment(train) [1/3] \n",
"12/19 14:42:49 - abl - INFO - model loss: 0.03484\n",
"12/19 14:42:49 - abl - INFO - loop(train) [5/5] segment(train) [2/3] \n",
"12/19 14:42:53 - abl - INFO - model loss: 0.03319\n",
"12/19 14:42:53 - abl - INFO - loop(train) [5/5] segment(train) [3/3] \n",
"12/19 14:42:58 - abl - INFO - model loss: 0.03510\n",
"12/19 14:42:58 - abl - INFO - Evaluation start: loop(val) [5]\n",
"12/19 14:42:59 - abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.993 mnist_add/reasoning_accuracy: 0.987 \n",
"12/19 14:42:59 - abl - INFO - Saving model: loop(save) [5]\n",
"12/19 14:42:59 - abl - INFO - Checkpoints will be saved to results/20231219_14_41_46/weights/model_checkpoint_loop_5.pth\n",
"12/19 14:42:59 - abl - INFO - Evaluation ended, mnist_add/character_accuracy: 0.988 mnist_add/reasoning_accuracy: 0.976 \n"
]
}
],
"outputs": [],
"source": [
"# Build logger\n",
"print_log(\"Abductive Learning on the MNIST Addition example.\", logger=\"current\")\n",


Loading…
Cancel
Save