predicateneuron 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. predicateneuron-0.1.2/.idea/workspace.xml +119 -0
  2. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/PKG-INFO +6 -6
  3. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/README.md +5 -5
  4. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/pyproject.toml +1 -1
  5. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/__init__.py +1 -1
  6. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/keras/functional.py +4 -6
  7. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/torch/functional.py +5 -4
  8. predicateneuron-0.1.0/.idea/workspace.xml +0 -73
  9. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/.gitignore +0 -0
  10. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/.idea/.gitignore +0 -0
  11. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  12. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/.idea/misc.xml +0 -0
  13. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/.idea/modules.xml +0 -0
  14. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/.idea/predicateneuron.iml +0 -0
  15. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/.idea/vcs.xml +0 -0
  16. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/CITATION.cff +0 -0
  17. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/LICENSE +0 -0
  18. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/reference/original_tf.py +0 -0
  19. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/keras/__init__.py +0 -0
  20. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/keras/layers.py +0 -0
  21. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/tf.py +0 -0
  22. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/torch/__init__.py +0 -0
  23. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/src/predicateneuron/torch/layers.py +0 -0
  24. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/tests/test_keras.py +0 -0
  25. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/tests/test_parity_with_original.py +0 -0
  26. {predicateneuron-0.1.0 → predicateneuron-0.1.2}/tests/test_torch.py +0 -0
@@ -0,0 +1,119 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ChangeListManager">
4
+ <list default="true" id="559a1296-1549-4b57-aea7-e3c5fde5b111" name="Changes" comment="">
5
+ <change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
6
+ <change afterPath="$PROJECT_DIR$/.idea/.gitignore" afterDir="false" />
7
+ <change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" afterDir="false" />
8
+ <change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
9
+ <change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
10
+ <change afterPath="$PROJECT_DIR$/.idea/predicateneuron.iml" afterDir="false" />
11
+ <change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
12
+ <change afterPath="$PROJECT_DIR$/CITATION.cff" afterDir="false" />
13
+ <change afterPath="$PROJECT_DIR$/LICENSE" afterDir="false" />
14
+ <change afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
15
+ <change afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
16
+ <change afterPath="$PROJECT_DIR$/reference/original_tf.py" afterDir="false" />
17
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/__init__.py" afterDir="false" />
18
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/keras/__init__.py" afterDir="false" />
19
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/keras/functional.py" afterDir="false" />
20
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/keras/layers.py" afterDir="false" />
21
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/tf.py" afterDir="false" />
22
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/torch/__init__.py" afterDir="false" />
23
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/torch/functional.py" afterDir="false" />
24
+ <change afterPath="$PROJECT_DIR$/src/predicateneuron/torch/layers.py" afterDir="false" />
25
+ <change afterPath="$PROJECT_DIR$/tests/test_keras.py" afterDir="false" />
26
+ <change afterPath="$PROJECT_DIR$/tests/test_parity_with_original.py" afterDir="false" />
27
+ <change afterPath="$PROJECT_DIR$/tests/test_torch.py" afterDir="false" />
28
+ </list>
29
+ <option name="SHOW_DIALOG" value="false" />
30
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
31
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
32
+ <option name="LAST_RESOLUTION" value="IGNORE" />
33
+ </component>
34
+ <component name="Git.Settings">
35
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
36
+ </component>
37
+ <component name="MarkdownSettingsMigration">
38
+ <option name="stateVersion" value="1" />
39
+ </component>
40
+ <component name="ProjectId" id="3L4p8byrBjmgCn1f0kxoOtLdrTO" />
41
+ <component name="ProjectViewState">
42
+ <option name="autoscrollFromSource" value="true" />
43
+ <option name="hideEmptyMiddlePackages" value="true" />
44
+ <option name="showLibraryContents" value="true" />
45
+ </component>
46
+ <component name="PropertiesComponent">
47
+ <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
48
+ <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
49
+ <property name="WebServerToolWindowFactoryState" value="false" />
50
+ </component>
51
+ <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
52
+ <component name="TaskManager">
53
+ <task active="true" id="Default" summary="Default task">
54
+ <changelist id="559a1296-1549-4b57-aea7-e3c5fde5b111" name="Changes" comment="" />
55
+ <created>1792723035825</created>
56
+ <option name="number" value="Default" />
57
+ <option name="presentableId" value="Default" />
58
+ <updated>1792723035825</updated>
59
+ <workItem from="1792723037060" duration="8477000" />
60
+ </task>
61
+ <task id="LOCAL-00001" summary="-initial commit">
62
+ <created>1792727916775</created>
63
+ <option name="number" value="00001" />
64
+ <option name="presentableId" value="LOCAL-00001" />
65
+ <option name="project" value="LOCAL" />
66
+ <updated>1792727916775</updated>
67
+ </task>
68
+ <task id="LOCAL-00002" summary="-fix tests">
69
+ <created>1792728400664</created>
70
+ <option name="number" value="00002" />
71
+ <option name="presentableId" value="LOCAL-00002" />
72
+ <option name="project" value="LOCAL" />
73
+ <updated>1792728400664</updated>
74
+ </task>
75
+ <task id="LOCAL-00003" summary="-fix tests">
76
+ <created>1792729978834</created>
77
+ <option name="number" value="00003" />
78
+ <option name="presentableId" value="LOCAL-00003" />
79
+ <option name="project" value="LOCAL" />
80
+ <updated>1792729978834</updated>
81
+ </task>
82
+ <task id="LOCAL-00004" summary="-fix docs">
83
+ <created>1792730252536</created>
84
+ <option name="number" value="00004" />
85
+ <option name="presentableId" value="LOCAL-00004" />
86
+ <option name="project" value="LOCAL" />
87
+ <updated>1792730252536</updated>
88
+ </task>
89
+ <task id="LOCAL-00005" summary="-fix docs">
90
+ <created>1792739970105</created>
91
+ <option name="number" value="00005" />
92
+ <option name="presentableId" value="LOCAL-00005" />
93
+ <option name="project" value="LOCAL" />
94
+ <updated>1792739970105</updated>
95
+ </task>
96
+ <option name="localTasksCounter" value="6" />
97
+ <servers />
98
+ </component>
99
+ <component name="TypeScriptGeneratedFilesManager">
100
+ <option name="version" value="3" />
101
+ </component>
102
+ <component name="Vcs.Log.Tabs.Properties">
103
+ <option name="TAB_STATES">
104
+ <map>
105
+ <entry key="MAIN">
106
+ <value>
107
+ <State />
108
+ </value>
109
+ </entry>
110
+ </map>
111
+ </option>
112
+ </component>
113
+ <component name="VcsManagerConfiguration">
114
+ <MESSAGE value="-initial commit" />
115
+ <MESSAGE value="-fix tests" />
116
+ <MESSAGE value="-fix docs" />
117
+ <option name="LAST_COMMIT_MESSAGE" value="-fix docs" />
118
+ </component>
119
+ </project>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: predicateneuron
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Differentiable predicate neuron (intersection / union / symmetric difference) and predicate layers for Keras, TensorFlow and PyTorch
5
5
  Project-URL: Homepage, https://github.com/IoannisKonstantoulas/predicateneuron
6
6
  Project-URL: Paper, https://TODO
@@ -70,10 +70,10 @@ from predicateneuron.torch import PredicateLayer
70
70
 
71
71
  model = torch.nn.Sequential(
72
72
  PredicateLayer(in_features=8, temperature=0.06, theta_init=0.5,
73
- hard_forward=False, hard_backward=False,
74
- torch.nn.Linear(28, 1), # 8 inputs -> 8*7/2 = 28 pairs
75
- torch.nn.Sigmoid(),
76
- )
73
+ hard_forward=False, hard_backward=False),
74
+ torch.nn.Linear(28, 1), # 8 inputs -> 8*7/2 = 28 pairs
75
+ torch.nn.Sigmoid(),
76
+ )
77
77
  ```
78
78
 
79
79
  Inputs are expected to lie in [0, 1], for example sigmoid outputs or normalized features.
@@ -100,7 +100,7 @@ Two independent switches control how the neuron behaves.
100
100
  | `hard_backward` | input gradients from the selected operation only | input gradients from the exact derivative of the soft mixture |
101
101
 
102
102
  The gradient with respect to `theta` always comes from the softmax surrogate, in every mode. All four combinations are
103
- valid. The defaults are (`hard_forward=False`, `hard_backward=False`)
103
+ valid. The defaults are (`hard_forward=False`, `hard_backward=False`).
104
104
 
105
105
  ## Layers
106
106
 
@@ -45,10 +45,10 @@ from predicateneuron.torch import PredicateLayer
45
45
 
46
46
  model = torch.nn.Sequential(
47
47
  PredicateLayer(in_features=8, temperature=0.06, theta_init=0.5,
48
- hard_forward=False, hard_backward=False,
49
- torch.nn.Linear(28, 1), # 8 inputs -> 8*7/2 = 28 pairs
50
- torch.nn.Sigmoid(),
51
- )
48
+ hard_forward=False, hard_backward=False),
49
+ torch.nn.Linear(28, 1), # 8 inputs -> 8*7/2 = 28 pairs
50
+ torch.nn.Sigmoid(),
51
+ )
52
52
  ```
53
53
 
54
54
  Inputs are expected to lie in [0, 1], for example sigmoid outputs or normalized features.
@@ -75,7 +75,7 @@ Two independent switches control how the neuron behaves.
75
75
  | `hard_backward` | input gradients from the selected operation only | input gradients from the exact derivative of the soft mixture |
76
76
 
77
77
  The gradient with respect to `theta` always comes from the softmax surrogate, in every mode. All four combinations are
78
- valid. The defaults are (`hard_forward=False`, `hard_backward=False`)
78
+ valid. The defaults are (`hard_forward=False`, `hard_backward=False`).
79
79
 
80
80
  ## Layers
81
81
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "predicateneuron"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "Differentiable predicate neuron (intersection / union / symmetric difference) and predicate layers for Keras, TensorFlow and PyTorch"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -5,4 +5,4 @@ from predicateneuron.keras import PredicateLayer, MinimalPredicateLayer, Minimal
5
5
  from predicateneuron.tf import PredicateLayer, MinimalPredicateLayer, MinimalJointPredicateLayer # tf.keras users
6
6
  from predicateneuron.torch import PredicateLayer, MinimalPredicateLayer, MinimalJointPredicateLayer # PyTorch
7
7
  """
8
- __version__ = "0.1.0"
8
+ __version__ = "0.1.2"
@@ -13,27 +13,25 @@ def predicate_neuron(x1, x2, theta, temperature=0.06, hard_forward=True, hard_ba
13
13
  (behaviour of the original paper code).
14
14
  hard_backward=False: exact derivative of the soft mixture,
15
15
  sum_k p_k * d(op_k)/dx.
16
- Implemented with stop_gradient, so it works on every Keras backend.
17
16
  """
17
+
18
18
  sg = ops.stop_gradient
19
19
 
20
20
  intersection = x1 * x2
21
21
  union = x1 + x2 - intersection
22
22
  symmetric_diff = x1 + x2 - 2.0 * intersection
23
23
 
24
- # hard path (differentiable w.r.t. x only; the gate itself is a constant)
25
24
  t = sg(theta)
26
25
  gate = ops.where(t < 0.25, 0, ops.where(t < 0.75, 1, 2))
27
26
  y_hard = ops.where(gate == 0, intersection, ops.where(gate == 1, union, symmetric_diff))
28
27
 
29
- # soft path
30
28
  positions = ops.cast(ops.convert_to_tensor([0.0, 0.5, 1.0]), x1.dtype)
31
29
  values = ops.stack([intersection, union, symmetric_diff], axis=-1)
32
30
  logits = -ops.square(ops.expand_dims(theta, -1) - positions) / temperature
33
31
  p = ops.softmax(logits, axis=-1)
34
- y_soft_theta = ops.sum(sg(values) * p, axis=-1) # gradient only to theta
35
- y_soft_x = ops.sum(values * sg(p), axis=-1) # gradient only to x
32
+ y_soft_theta = ops.sum(sg(values) * p, axis=-1)
33
+ y_soft_x = ops.sum(values * sg(p), axis=-1)
36
34
 
37
35
  forward = ops.where(hard_forward, y_hard, y_soft_theta)
38
- y_x = ops.where(hard_backward, y_hard, y_soft_x) # what x "sees" in backward
36
+ y_x = ops.where(hard_backward, y_hard, y_soft_x)
39
37
  return sg(forward) + (y_soft_theta - sg(y_soft_theta)) + (y_x - sg(y_x))
@@ -13,21 +13,22 @@ def predicate_neuron(x1, x2, theta, temperature=0.06, hard_forward=True, hard_ba
13
13
  (behaviour of the original paper code).
14
14
  hard_backward=False: exact derivative of the soft mixture,
15
15
  sum_k p_k * d(op_k)/dx.
16
- Works with autograd, torch.compile, double backward."""
16
+ """
17
+
17
18
  intersection = x1 * x2
18
19
  union = x1 + x2 - intersection
19
20
  symmetric_diff = x1 + x2 - 2.0 * intersection
20
21
 
21
22
  t = theta.detach()
22
- gate = (t >= 0.25).long() + (t >= 0.75).long() # 0,1,2 as in the original
23
+ gate = (t >= 0.25).long() + (t >= 0.75).long()
23
24
  y_hard = torch.where(gate == 0, intersection, torch.where(gate == 1, union, symmetric_diff))
24
25
 
25
26
  positions = torch.tensor([0.0, 0.5, 1.0], dtype=x1.dtype, device=x1.device)
26
27
  values = torch.stack([intersection, union, symmetric_diff], dim=-1)
27
28
  logits = -torch.square(theta.unsqueeze(-1) - positions) / temperature
28
29
  p = torch.softmax(logits, dim=-1)
29
- y_soft_theta = (values.detach() * p).sum(dim=-1) # gradient only to theta
30
- y_soft_x = (values * p.detach()).sum(dim=-1) # gradient only to x
30
+ y_soft_theta = (values.detach() * p).sum(dim=-1)
31
+ y_soft_x = (values * p.detach()).sum(dim=-1)
31
32
 
32
33
  hf = torch.as_tensor(hard_forward, dtype=torch.bool, device=x1.device)
33
34
  hb = torch.as_tensor(hard_backward, dtype=torch.bool, device=x1.device)
@@ -1,73 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ChangeListManager">
4
- <list default="true" id="559a1296-1549-4b57-aea7-e3c5fde5b111" name="Changes" comment="" />
5
- <option name="SHOW_DIALOG" value="false" />
6
- <option name="HIGHLIGHT_CONFLICTS" value="true" />
7
- <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
8
- <option name="LAST_RESOLUTION" value="IGNORE" />
9
- </component>
10
- <component name="Git.Settings">
11
- <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
12
- </component>
13
- <component name="MarkdownSettingsMigration">
14
- <option name="stateVersion" value="1" />
15
- </component>
16
- <component name="ProjectId" id="3L4p8byrBjmgCn1f0kxoOtLdrTO" />
17
- <component name="ProjectViewState">
18
- <option name="autoscrollFromSource" value="true" />
19
- <option name="hideEmptyMiddlePackages" value="true" />
20
- <option name="showLibraryContents" value="true" />
21
- </component>
22
- <component name="PropertiesComponent">
23
- <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
24
- <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
25
- <property name="WebServerToolWindowFactoryState" value="false" />
26
- </component>
27
- <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
28
- <component name="TaskManager">
29
- <task active="true" id="Default" summary="Default task">
30
- <changelist id="559a1296-1549-4b57-aea7-e3c5fde5b111" name="Changes" comment="" />
31
- <created>1792723035825</created>
32
- <option name="number" value="Default" />
33
- <option name="presentableId" value="Default" />
34
- <updated>1792723035825</updated>
35
- <workItem from="1792723037060" duration="6169000" />
36
- </task>
37
- <task id="LOCAL-00001" summary="-initial commit">
38
- <created>1792727916775</created>
39
- <option name="number" value="00001" />
40
- <option name="presentableId" value="LOCAL-00001" />
41
- <option name="project" value="LOCAL" />
42
- <updated>1792727916775</updated>
43
- </task>
44
- <task id="LOCAL-00002" summary="-fix tests">
45
- <created>1792728400664</created>
46
- <option name="number" value="00002" />
47
- <option name="presentableId" value="LOCAL-00002" />
48
- <option name="project" value="LOCAL" />
49
- <updated>1792728400664</updated>
50
- </task>
51
- <option name="localTasksCounter" value="3" />
52
- <servers />
53
- </component>
54
- <component name="TypeScriptGeneratedFilesManager">
55
- <option name="version" value="3" />
56
- </component>
57
- <component name="Vcs.Log.Tabs.Properties">
58
- <option name="TAB_STATES">
59
- <map>
60
- <entry key="MAIN">
61
- <value>
62
- <State />
63
- </value>
64
- </entry>
65
- </map>
66
- </option>
67
- </component>
68
- <component name="VcsManagerConfiguration">
69
- <MESSAGE value="-initial commit" />
70
- <MESSAGE value="-fix tests" />
71
- <option name="LAST_COMMIT_MESSAGE" value="-fix tests" />
72
- </component>
73
- </project>
File without changes