You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Reasoning.rst 17 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. `Learn the Basics <Basics.html>`_ ||
  2. `Quick Start <Quick-Start.html>`_ ||
  3. `Dataset & Data Structure <Datasets.html>`_ ||
  4. `Learning Part <Learning.html>`_ ||
  5. **Reasoning Part** ||
  6. `Evaluation Metrics <Evaluation.html>`_ ||
  7. `Bridge <Bridge.html>`_
  8. Reasoning part
  9. ===============
  10. In this section, we will look at how to build the reasoning part, which
  11. leverages domain knowledge and performs deductive or abductive reasoning.
  12. In ABLkit, building the reasoning part involves two steps:
  13. 1. Build a knowledge base by creating a subclass of ``KBBase``, which
  14. specifies how to process pseudo-label of an example to the reasoning result.
  15. 2. Create a reasoner by instantiating the class ``Reasoner``
  16. to minimize inconsistencies between the knowledge base and pseudo
  17. labels predicted by the learning part.
  18. .. code:: python
  19. from ablkit.reasoning import KBBase, GroundKB, PrologKB, Reasoner
  20. Building a knowledge base
  21. -------------------------
  22. Generally, we can create a subclass derived from ``KBBase`` to build our own
  23. knowledge base. In addition, ABLkit also offers several predefined
  24. subclasses of ``KBBase`` (e.g., ``PrologKB`` and ``GroundKB``),
  25. which we can utilize to build our knowledge base more conveniently.
  26. Building a knowledge base from ``KBBase``
  27. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  28. For the user-built KB from ``KBBase`` (a derived subclass), it's only
  29. required to pass the ``pseudo_label_list`` parameter in the ``__init__`` method
  30. and override the ``logic_forward`` method:
  31. - ``pseudo_label_list`` is the list of possible pseudo-labels (also,
  32. the output of the machine learning model).
  33. - ``logic_forward`` defines how to perform (deductive) reasoning,
  34. i.e. matching each example's pseudo-labels to its reasoning result.
  35. .. note::
  36. Generally, the overridden method ``logic_forward`` provided by the user accepts
  37. only one parameter, ``pseudo_label`` (pseudo-labels of an example). However, for certain
  38. scenarios, deductive reasoning in the knowledge base may necessitate information
  39. from the input. In these scenarios, ``logic_forward`` can also accept two parameters:
  40. ``pseudo_label`` and ``x``. See examples in `Zoo <../Examples/Zoo.html>`_.
  41. After that, other operations, including how to perform abductive
  42. reasoning, will be **automatically** set up.
  43. MNIST Addition example
  44. ^^^^^^^^^^^^^^^^^^^^^^
  45. As an example, the ``pseudo_label_list`` passed in MNIST Addition is all the
  46. possible digits, namely, ``[0,1,2,...,9]``, and the ``logic_forward``
  47. should be: “Add the two pseudo-labels to get the result.”. Therefore, the
  48. construction of the KB (``add_kb``) for MNIST Addition would be:
  49. .. code:: python
  50. class AddKB(KBBase):
  51. def __init__(self, pseudo_label_list=list(range(10))):
  52. super().__init__(pseudo_label_list)
  53. def logic_forward(self, pseudo_labels):
  54. return sum(pseudo_labels)
  55. add_kb = AddKB()
  56. and (deductive) reasoning in ``add_kb`` would be:
  57. .. code:: python
  58. pseudo_labels = [1, 2]
  59. reasoning_result = add_kb.logic_forward(pseudo_labels)
  60. print(f"Reasoning result of pseudo-labels {pseudo_labels} is {reasoning_result}.")
  61. Out:
  62. .. code:: none
  63. :class: code-out
  64. Reasoning result of pseudo-labels [1, 2] is 3
  65. .. _other-par:
  66. Other optional parameters
  67. ^^^^^^^^^^^^^^^^^^^^^^^^^
  68. We can also pass the following parameters in the ``__init__`` method when building our
  69. knowledge base:
  70. - ``max_err`` (float, optional), specifying the upper tolerance limit
  71. when comparing the similarity between the reasoning result of pseudo-labels
  72. and the ground truth during abductive reasoning. This is only
  73. applicable when the reasoning result is of a numerical type. This is
  74. particularly relevant for regression problems where exact matches
  75. might not be feasible. Defaults to 1e-10. See :ref:`an example <kb-abd-2>`.
  76. - ``use_cache`` (bool, optional), indicating whether to use cache to store
  77. previous candidates (pseudo-labels generated from abductive reasoning)
  78. to speed up subsequent abductive reasoning operations. Defaults to True.
  79. For more information of abductive reasoning, please refer to :ref:`this <kb-abd>`.
  80. - ``cache_size`` (int, optional), specifying the maximum cache
  81. size. This is only operational when ``use_cache`` is set to True.
  82. Defaults to 4096.
  83. .. _prolog:
  84. Building a knowledge base from Prolog file
  85. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  86. When aiming to leverage knowledge base from an external Prolog file
  87. (which contains how to perform reasoning), we can directly create an
  88. instance of class ``PrologKB``. Upon instantiation of
  89. ``PrologKB``, we are required to pass the ``pseudo_label_list`` (same as ``KBBase``)
  90. and ``pl_file`` (the Prolog file) in the ``__init__`` method.
  91. .. admonition:: What is a Prolog file?
  92. A Prolog file (typically have the extension ``.pl``) is a script or source
  93. code file written in the Prolog language. Prolog is a logic programming language
  94. where the logic is represented as facts
  95. (basic assertions about some world) and
  96. rules (logical statements that describe the relationships between facts).
  97. A computation is initiated by running a query over these facts and rules.
  98. See some Prolog examples
  99. in `SWISH <https://swish.swi-prolog.org/>`_.
  100. After the instantiation, other operations, including how to perform
  101. abductive reasoning, will also be **automatically** set up.
  102. .. warning::
  103. Note that to use the default logic forward and abductive reasoning
  104. methods in this class, the Prolog (.pl) file should contain a rule
  105. with a strict format: ``logic_forward(Pseudo_labels, Res).``
  106. Otherwise, we might have to override ``logic_forward`` and
  107. ``get_query_string`` to allow for more adaptable usage.
  108. MNIST Addition example (cont.)
  109. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  110. As an example, we can first write a Prolog file for the MNIST Addition
  111. example as the following code, and then save it as ``add.pl``.
  112. .. code:: prolog
  113. pseudo_label(N) :- between(0, 9, N).
  114. logic_forward([Z1, Z2], Res) :- pseudo_label(Z1), pseudo_label(Z2), Res is Z1+Z2.
  115. Afterwards, the construction of knowledge base from Prolog file
  116. (``add_prolog_kb``) would be as follows:
  117. .. code:: python
  118. add_prolog_kb = PrologKB(pseudo_label_list=list(range(10)), pl_file="add.pl")
  119. Building a knowledge base with GKB from ``GroundKB``
  120. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  121. We can also inherit from class ``GroundKB`` to build our own
  122. knowledge base. In this way, the knowledge built will have a Ground KB
  123. (GKB).
  124. .. admonition:: What is Ground KB?
  125. `Ground KB <https://www.ijcai.org/proceedings/2021/250>`_ is a knowledge base prebuilt upon class initialization,
  126. storing all potential candidates along with their respective reasoning
  127. result. The key advantage of having a Ground KB is that it may
  128. accelerate abductive reasoning.
  129. ``GroundKB`` is a subclass of ``GKBBase``. Similar to ``KBBase``, we
  130. are required to pass the ``pseudo_label_list`` parameter in the ``__init__`` method and
  131. override the ``logic_forward`` method, and are allowed to pass other
  132. :ref:`optional parameters <other-par>`. Additionally, we are required pass the
  133. ``GKB_len_list`` parameter in the ``__init__`` method.
  134. - ``GKB_len_list`` is the list of possible lengths for pseudo-labels of an example.
  135. After that, other operations, including auto-construction of GKB, and
  136. how to perform abductive reasoning, will be **automatically** set up.
  137. MNIST Addition example (cont.)
  138. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  139. As an example, the ``GKB_len_list`` for MNIST Addition should be ``[2]``,
  140. since all pseudo-labels in the example consist of two digits. Therefore,
  141. the construction of KB with GKB (``add_ground_kb``) of MNIST Addition would be
  142. as follows. As mentioned, the difference between this and the previously
  143. built ``add_kb`` lies only in the base class from which it is derived
  144. and whether an extra parameter ``GKB_len_list`` is passed.
  145. .. code:: python
  146. class AddGroundKB(GroundKB):
  147. def __init__(self, pseudo_label_list=list(range(10)),
  148. GKB_len_list=[2]):
  149. super().__init__(pseudo_label_list, GKB_len_list)
  150. def logic_forward(self, nums):
  151. return sum(nums)
  152. add_ground_kb = AddGroundKB()
  153. .. _kb-abd:
  154. Performing abductive reasoning in the knowledge base
  155. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  156. As mentioned in :ref:`What is Abductive Reasoning? <abd>`, abductive reasoning
  157. enables the inference of candidates (i.e., possible pseudo-labels) as potential
  158. explanations for the reasoning result. Also, in Abductive Learning where
  159. an observation (pseudo-labels of an example predicted by the learning part) is
  160. available, we aim to let the candidate do not largely revise the
  161. previously identified pseudo-labels.
  162. ``KBBase`` (also, ``GroundKB`` and ``PrologKB``) implement the method
  163. ``abduce_candidates(pseudo_label, y, x, max_revision_num, require_more_revision)``
  164. for performing abductive reasoning, where the parameters are:
  165. - ``pseudo_label``, pseudo-labels of an example, usually generated by the learning
  166. part. They are to be revised by abductive reasoning.
  167. - ``y``, the ground truth of the reasoning result for the example. The
  168. returned candidates should be compatible with it.
  169. - ``x``, the corresponding input example. If the information from the input
  170. is not required in the reasoning process, then this parameter will not have
  171. any effect.
  172. - ``max_revision_num``, an int value specifying the upper limit on the
  173. number of revised labels for each example.
  174. - ``require_more_revision``, an int value specifying additional number
  175. of revisions permitted beyond the minimum required. (e.g., If we set
  176. it to 0, even if ``max_revision_num`` is set to a high value, the
  177. method will only output candidates with the minimum possible
  178. revisions.)
  179. And it returns a list of candidates (i.e., revised pseudo-labels of the example)
  180. that are all compatible with ``y``.
  181. MNIST Addition example (cont.)
  182. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  183. As an example, with MNIST Addition, the candidates returned by
  184. ``add_kb.abduce_candidates`` would be as follows:
  185. +------------------+-------+----------------------+--------------------------+----------------+
  186. | ``pseudo_label`` | ``y`` | ``max_revision_num`` | ``require_more_address`` | Output |
  187. +==================+=======+======================+==========================+================+
  188. | [1,1] | 8 | 1 | 0 | [[1,7], [7,1]] |
  189. +------------------+-------+----------------------+--------------------------+----------------+
  190. | [1,1] | 8 | 1 | 1 | [[1,7], [7,1]] |
  191. +------------------+-------+----------------------+--------------------------+----------------+
  192. | [1,1] | 8 | 2 | 0 | [[1,7], [7,1]] |
  193. +------------------+-------+----------------------+--------------------------+----------------+
  194. | [1,1] | 8 | 2 | 1 | [[1,7], |
  195. | | | | | [7,1], [2,6], |
  196. | | | | | [6,2], [3,5], |
  197. | | | | | [5,3], [4,4]] |
  198. +------------------+-------+----------------------+--------------------------+----------------+
  199. | [1,1] | 11 | 1 | 0 | [] |
  200. +------------------+-------+----------------------+--------------------------+----------------+
  201. .. _kb-abd-2:
  202. As another example, if we set the ``max_err`` of ``AddKB`` to be 1
  203. instead of the default 1e-10, the tolerance limit for consistency will
  204. be higher, hence the candidates returned would be:
  205. +------------------+-------+----------------------+--------------------------+----------------+
  206. | ``pseudo_label`` | ``y`` | ``max_revision_num`` | ``require_more_address`` | Output |
  207. +==================+=======+======================+==========================+================+
  208. | [1,1] | 8 | 1 | 0 | [[1,7], [7,1], |
  209. | | | | | [1,6], [6,1], |
  210. | | | | | [1,8], [8,1]] |
  211. +------------------+-------+----------------------+--------------------------+----------------+
  212. | [1,1] | 11 | 1 | 0 | [[1,9], [9,1]] |
  213. +------------------+-------+----------------------+--------------------------+----------------+
  214. Creating a reasoner
  215. -------------------
  216. After building our knowledge base, the next step is creating a
  217. reasoner. Due to the indeterminism of abductive reasoning, there could
  218. be multiple candidates compatible with the knowledge base. When this
  219. happens, reasoner can minimize inconsistencies between the knowledge
  220. base and pseudo-labels predicted by the learning part, and then return **only
  221. one** candidate that has the highest consistency.
  222. We can create a reasoner simply by instantiating class
  223. ``Reasoner`` and passing our knowledge base as a parameter. As an
  224. example for MNIST Addition, the reasoner definition would be:
  225. .. code:: python
  226. reasoner_add = Reasoner(kb_add)
  227. When instantiating, besides the required knowledge base, we may also
  228. specify:
  229. - ``max_revision`` (int or float, optional), specifies the upper limit
  230. on the number of revisions for each example when performing
  231. :ref:`abductive reasoning in the knowledge base <kb-abd>`. If float, denotes the
  232. fraction of the total length that can be revised. A value of -1
  233. implies no restriction on the number of revisions. Defaults to -1.
  234. - ``require_more_revision`` (int, optional), Specifies additional
  235. number of revisions permitted beyond the minimum required when
  236. performing :ref:`abductive reasoning in the knowledge base <kb-abd>`. Defaults to
  237. 0.
  238. - ``use_zoopt`` (bool, optional), indicating whether to use the `ZOOpt library <https://github.com/polixir/ZOOpt>`_,
  239. which is a library for zeroth-order optimization that can be used to
  240. accelerate consistency minimization. Defaults to False.
  241. - ``dist_func`` (str, optional), specifying the distance function to be
  242. used when determining consistency between your prediction and
  243. candidate returned from knowledge base. This can be either a user-defined function
  244. or one that is predefined. Valid predefined options include
  245. “hamming”, “confidence” and “avg_confidence”. For “hamming”, it directly calculates the Hamming distance between the
  246. predicted pseudo-label in the data example and candidate. For “confidence”, it
  247. calculates the confidence distance between the predicted probabilities in the data
  248. example and each candidate, where the confidence distance is defined as 1 - the product
  249. of prediction probabilities in “confidence” and 1 - the average of prediction probabilities in “avg_confidence”.
  250. Defaults to “confidence”.
  251. - ``idx_to_label`` (dict, optional), a mapping from index in the base model to label.
  252. If not provided, a default order-based index to label mapping is created.
  253. Defaults to None.
  254. The main method implemented by ``Reasoner`` is
  255. ``abduce(data_example)``, which obtains the most consistent candidate
  256. based on the distance function defined in ``dist_func``.
  257. MNIST Addition example (cont.)
  258. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  259. As an example, consider these data examples for MNIST Addition:
  260. .. code:: python
  261. # favor "1" for the first label
  262. prob1 = [[0, 0.99, 0, 0, 0, 0, 0, 0.01, 0, 0],
  263. [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
  264. # favor "7" for the first label
  265. prob2 = [[0, 0.01, 0, 0, 0, 0, 0, 0.99, 0, 0],
  266. [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
  267. example1 = ListData()
  268. example1.pred_pseudo_label = [1, 1]
  269. example1.pred_prob = prob1
  270. example1.Y = 8
  271. example2 = ListData()
  272. example2.pred_pseudo_label = [1, 1]
  273. example2.pred_prob = prob2
  274. example2.Y = 8
  275. The compatible candidates after abductive reasoning for both examples
  276. would be ``[[1,7], [7,1]]``. However, when the reasoner calls ``abduce``
  277. to select only one candidate based on the “confidence” distance function,
  278. the output would differ for each example:
  279. .. code:: python
  280. reasoner_add = Reasoner(kb_add, dist_func="confidence")
  281. candidate1 = reasoner_add.abduce(example1)
  282. candidate2 = reasoner_add.abduce(example2)
  283. print(f"The outputs for example1 and example2 are {candidate1} and {candidate2}, respectively.")
  284. Out:
  285. .. code:: none
  286. :class: code-out
  287. The outputs for example1 and example2 are [1,7] and [7,1], respectively.
  288. Specifically, as mentioned before, “confidence” calculates the distance between the data
  289. example and candidates based on the confidence derived from the predicted probability.
  290. Take ``example1`` as an example, the ``pred_prob`` in it indicates a higher
  291. confidence that the first label should be "1" rather than "7". Therefore, among the
  292. candidates [1,7] and [7,1], it would be closer to [1,7] (as its first label is "1").

An efficient Python toolkit for Abductive Learning (ABL), a novel paradigm that integrates machine learning and logical reasoning in a unified framework.