fast-causal-shap 0.1.0__tar.gz → 0.1.1__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.

Potentially problematic release.


This version of fast-causal-shap might be problematic. Click here for more details.

@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.4
2
+ Name: fast-causal-shap
3
+ Version: 0.1.1
4
+ Summary: A Python package for efficient causal SHAP computations
5
+ Author-email: woonyee28 <ngnwy289@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/woonyee28/CausalSHAP
8
+ Project-URL: Issues, https://github.com/woonyee28/CausalSHAP/issues
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: pandas>=1.0.0
13
+ Requires-Dist: networkx>=2.0
14
+ Requires-Dist: numpy>=1.18.0
15
+ Requires-Dist: scikit-learn>=0.24.0
16
+ Dynamic: license-file
17
+
18
+ # Fast Causal SHAP
19
+
20
+ Fast Causal SHAP is a Python package designed for efficient and interpretable SHAP value computation in causal inference tasks. It integrates seamlessly with various causal inference frameworks and enables feature attribution with awareness of causal dependencies.
21
+
22
+ ## Features
23
+
24
+ - Fast computation of SHAP values for causal models
25
+ - Support for multiple causal inference frameworks
26
+
27
+ ## Installation
28
+
29
+ Install the stable version via PyPI:
30
+
31
+ ```bash
32
+ pip install fast-causal-shap
33
+ ```
34
+
35
+ Or, for the latest development version:
36
+
37
+ ```bash
38
+ pip install git+https://github.com/woonyee28/CausalSHAP.git
39
+ ```
40
+
41
+ ## Usage
42
+ ```
43
+ from fast_causal_inference import FastCausalInference
44
+
45
+ # Predict probabilities and assign to training data
46
+ predicted_probabilities = model.predict_proba(X_train)[:,1]
47
+ X_train['target'] = predicted_probabilities
48
+
49
+ # Initialize FastCausalInference
50
+ ci = FastCausalInference(data=X_train, model=model, target_variable='target')
51
+
52
+ # Load causal strengths (precomputed using R packages)
53
+ ci.load_causal_strengths(result_dir + 'Causal_Effect.json')
54
+
55
+ # Compute modified SHAP values for a single instance
56
+ x_instance = X_train.iloc[33]
57
+
58
+ print(ci.compute_modified_shap_proba(x_instance, is_classifier=True))
59
+ ```
60
+
61
+ Format of the Causal_Effect.json:
62
+ ```
63
+ [
64
+ {
65
+ "Pair": "Bacteroidia->Clostridia",
66
+ "Mean_Causal_Effect": 0.71292
67
+ },
68
+ {
69
+ "Pair": "Clostridia->Alphaproteobacteria",
70
+ "Mean_Causal_Effect": 0.37652
71
+ }, ......
72
+ ]
73
+ ```
74
+
75
+ Fast Causal SHAP supports integration with structural algorithms such as:
76
+ 1. Peter-Clarke (PC) Algorithm
77
+ 2. IDA Algorithm
78
+ 3. Fast Causal Inference (FCI) Algorithm
79
+ You can find example R code for these integrations here: [FastCausalSHAP R code examples](https://github.com/woonyee28/CausalSHAP/tree/main/code/r)
80
+
81
+
82
+ ## Citation
83
+ If you use Fast Causal SHAP in your research, please cite:
84
+ ```
85
+ @inproceedings{ng2025causal,
86
+ title={Causal SHAP: Feature Attribution with Dependency Awareness through Causal Discovery},
87
+ author={Ng, Woon Yee and Wang, Li Rong and Liu, Siyuan and Fan, Xiuyi},
88
+ booktitle={Proceedings of the International Joint Conference on Neural Networks (IJCNN)},
89
+ year={2025},
90
+ organization={IEEE}
91
+ }
92
+ ```
93
+
94
+ ## License
95
+
96
+ This project is licensed under the MIT License.
@@ -0,0 +1,79 @@
1
+ # Fast Causal SHAP
2
+
3
+ Fast Causal SHAP is a Python package designed for efficient and interpretable SHAP value computation in causal inference tasks. It integrates seamlessly with various causal inference frameworks and enables feature attribution with awareness of causal dependencies.
4
+
5
+ ## Features
6
+
7
+ - Fast computation of SHAP values for causal models
8
+ - Support for multiple causal inference frameworks
9
+
10
+ ## Installation
11
+
12
+ Install the stable version via PyPI:
13
+
14
+ ```bash
15
+ pip install fast-causal-shap
16
+ ```
17
+
18
+ Or, for the latest development version:
19
+
20
+ ```bash
21
+ pip install git+https://github.com/woonyee28/CausalSHAP.git
22
+ ```
23
+
24
+ ## Usage
25
+ ```
26
+ from fast_causal_inference import FastCausalInference
27
+
28
+ # Predict probabilities and assign to training data
29
+ predicted_probabilities = model.predict_proba(X_train)[:,1]
30
+ X_train['target'] = predicted_probabilities
31
+
32
+ # Initialize FastCausalInference
33
+ ci = FastCausalInference(data=X_train, model=model, target_variable='target')
34
+
35
+ # Load causal strengths (precomputed using R packages)
36
+ ci.load_causal_strengths(result_dir + 'Causal_Effect.json')
37
+
38
+ # Compute modified SHAP values for a single instance
39
+ x_instance = X_train.iloc[33]
40
+
41
+ print(ci.compute_modified_shap_proba(x_instance, is_classifier=True))
42
+ ```
43
+
44
+ Format of the Causal_Effect.json:
45
+ ```
46
+ [
47
+ {
48
+ "Pair": "Bacteroidia->Clostridia",
49
+ "Mean_Causal_Effect": 0.71292
50
+ },
51
+ {
52
+ "Pair": "Clostridia->Alphaproteobacteria",
53
+ "Mean_Causal_Effect": 0.37652
54
+ }, ......
55
+ ]
56
+ ```
57
+
58
+ Fast Causal SHAP supports integration with structural algorithms such as:
59
+ 1. Peter-Clarke (PC) Algorithm
60
+ 2. IDA Algorithm
61
+ 3. Fast Causal Inference (FCI) Algorithm
62
+ You can find example R code for these integrations here: [FastCausalSHAP R code examples](https://github.com/woonyee28/CausalSHAP/tree/main/code/r)
63
+
64
+
65
+ ## Citation
66
+ If you use Fast Causal SHAP in your research, please cite:
67
+ ```
68
+ @inproceedings{ng2025causal,
69
+ title={Causal SHAP: Feature Attribution with Dependency Awareness through Causal Discovery},
70
+ author={Ng, Woon Yee and Wang, Li Rong and Liu, Siyuan and Fan, Xiuyi},
71
+ booktitle={Proceedings of the International Joint Conference on Neural Networks (IJCNN)},
72
+ year={2025},
73
+ organization={IEEE}
74
+ }
75
+ ```
76
+
77
+ ## License
78
+
79
+ This project is licensed under the MIT License.
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.4
2
+ Name: fast-causal-shap
3
+ Version: 0.1.1
4
+ Summary: A Python package for efficient causal SHAP computations
5
+ Author-email: woonyee28 <ngnwy289@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/woonyee28/CausalSHAP
8
+ Project-URL: Issues, https://github.com/woonyee28/CausalSHAP/issues
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: pandas>=1.0.0
13
+ Requires-Dist: networkx>=2.0
14
+ Requires-Dist: numpy>=1.18.0
15
+ Requires-Dist: scikit-learn>=0.24.0
16
+ Dynamic: license-file
17
+
18
+ # Fast Causal SHAP
19
+
20
+ Fast Causal SHAP is a Python package designed for efficient and interpretable SHAP value computation in causal inference tasks. It integrates seamlessly with various causal inference frameworks and enables feature attribution with awareness of causal dependencies.
21
+
22
+ ## Features
23
+
24
+ - Fast computation of SHAP values for causal models
25
+ - Support for multiple causal inference frameworks
26
+
27
+ ## Installation
28
+
29
+ Install the stable version via PyPI:
30
+
31
+ ```bash
32
+ pip install fast-causal-shap
33
+ ```
34
+
35
+ Or, for the latest development version:
36
+
37
+ ```bash
38
+ pip install git+https://github.com/woonyee28/CausalSHAP.git
39
+ ```
40
+
41
+ ## Usage
42
+ ```
43
+ from fast_causal_inference import FastCausalInference
44
+
45
+ # Predict probabilities and assign to training data
46
+ predicted_probabilities = model.predict_proba(X_train)[:,1]
47
+ X_train['target'] = predicted_probabilities
48
+
49
+ # Initialize FastCausalInference
50
+ ci = FastCausalInference(data=X_train, model=model, target_variable='target')
51
+
52
+ # Load causal strengths (precomputed using R packages)
53
+ ci.load_causal_strengths(result_dir + 'Causal_Effect.json')
54
+
55
+ # Compute modified SHAP values for a single instance
56
+ x_instance = X_train.iloc[33]
57
+
58
+ print(ci.compute_modified_shap_proba(x_instance, is_classifier=True))
59
+ ```
60
+
61
+ Format of the Causal_Effect.json:
62
+ ```
63
+ [
64
+ {
65
+ "Pair": "Bacteroidia->Clostridia",
66
+ "Mean_Causal_Effect": 0.71292
67
+ },
68
+ {
69
+ "Pair": "Clostridia->Alphaproteobacteria",
70
+ "Mean_Causal_Effect": 0.37652
71
+ }, ......
72
+ ]
73
+ ```
74
+
75
+ Fast Causal SHAP supports integration with structural algorithms such as:
76
+ 1. Peter-Clarke (PC) Algorithm
77
+ 2. IDA Algorithm
78
+ 3. Fast Causal Inference (FCI) Algorithm
79
+ You can find example R code for these integrations here: [FastCausalSHAP R code examples](https://github.com/woonyee28/CausalSHAP/tree/main/code/r)
80
+
81
+
82
+ ## Citation
83
+ If you use Fast Causal SHAP in your research, please cite:
84
+ ```
85
+ @inproceedings{ng2025causal,
86
+ title={Causal SHAP: Feature Attribution with Dependency Awareness through Causal Discovery},
87
+ author={Ng, Woon Yee and Wang, Li Rong and Liu, Siyuan and Fan, Xiuyi},
88
+ booktitle={Proceedings of the International Joint Conference on Neural Networks (IJCNN)},
89
+ year={2025},
90
+ organization={IEEE}
91
+ }
92
+ ```
93
+
94
+ ## License
95
+
96
+ This project is licensed under the MIT License.
@@ -7,4 +7,5 @@ fast_causal_shap.egg-info/PKG-INFO
7
7
  fast_causal_shap.egg-info/SOURCES.txt
8
8
  fast_causal_shap.egg-info/dependency_links.txt
9
9
  fast_causal_shap.egg-info/requires.txt
10
- fast_causal_shap.egg-info/top_level.txt
10
+ fast_causal_shap.egg-info/top_level.txt
11
+ tests/test_core.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fast-causal-shap"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "A Python package for efficient causal SHAP computations"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"
@@ -21,4 +21,4 @@ dependencies = [
21
21
 
22
22
  [project.urls]
23
23
  Homepage = "https://github.com/woonyee28/CausalSHAP"
24
- Issues = "https://github.com/woonyee28/CausalSHAP/issues"
24
+ Issues = "https://github.com/woonyee28/CausalSHAP/issues"
@@ -0,0 +1,356 @@
1
+ import unittest
2
+ import numpy as np
3
+ import pandas as pd
4
+ import networkx as nx
5
+ import json
6
+ import tempfile
7
+ import os
8
+ from sklearn.linear_model import LinearRegression
9
+ from sklearn.ensemble import RandomForestClassifier
10
+ from sklearn.datasets import make_classification, make_regression
11
+
12
+ from fast_causal_shap.core import FastCausalSHAP
13
+
14
+
15
+ class TestFastCausalSHAP(unittest.TestCase):
16
+
17
+ def setUp(self):
18
+ """Set up test fixtures before each test method."""
19
+ # Create sample data for testing
20
+ np.random.seed(42)
21
+
22
+ # Create synthetic regression data
23
+ X, y = make_regression(n_samples=100, n_features=4, noise=0.1, random_state=42)
24
+ self.regression_data = pd.DataFrame(X, columns=['feature1', 'feature2', 'feature3', 'feature4'])
25
+ self.regression_data['target'] = y
26
+
27
+ # Create synthetic classification data
28
+ X_clf, y_clf = make_classification(n_samples=100, n_features=4, n_classes=2, random_state=42)
29
+ self.classification_data = pd.DataFrame(X_clf, columns=['feature1', 'feature2', 'feature3', 'feature4'])
30
+ self.classification_data['target'] = y_clf
31
+
32
+ # Create mock models
33
+ self.regression_model = LinearRegression()
34
+ self.regression_model.fit(self.regression_data[['feature1', 'feature2', 'feature3', 'feature4']],
35
+ self.regression_data['target'])
36
+
37
+ self.classification_model = RandomForestClassifier(random_state=42)
38
+ self.classification_model.fit(self.classification_data[['feature1', 'feature2', 'feature3', 'feature4']],
39
+ self.classification_data['target'])
40
+
41
+ # Create test instance
42
+ self.fast_causal_shap = FastCausalSHAP(
43
+ data=self.regression_data,
44
+ model=self.regression_model,
45
+ target_variable='target'
46
+ )
47
+
48
+ # Create sample causal effects for testing
49
+ self.sample_causal_effects = [
50
+ {"Pair": "feature1->target", "Mean_Causal_Effect": 0.5},
51
+ {"Pair": "feature2->target", "Mean_Causal_Effect": 0.3},
52
+ {"Pair": "feature3->feature1", "Mean_Causal_Effect": 0.2},
53
+ {"Pair": "feature4->feature2", "Mean_Causal_Effect": 0.1}
54
+ ]
55
+
56
+ def _create_test_graph(self, edges=None):
57
+ """Helper method to create a test graph with all nodes from data."""
58
+ G = nx.DiGraph()
59
+ all_nodes = self.regression_data.columns.tolist()
60
+ G.add_nodes_from(all_nodes)
61
+ if edges:
62
+ G.add_edges_from(edges)
63
+ return G
64
+
65
+ def test_init(self):
66
+ """Test FastCausalSHAP initialization."""
67
+ fcs = FastCausalSHAP(
68
+ data=self.regression_data,
69
+ model=self.regression_model,
70
+ target_variable='target'
71
+ )
72
+
73
+ self.assertEqual(fcs.target_variable, 'target')
74
+ self.assertIsNone(fcs.gamma)
75
+ self.assertIsNone(fcs.ida_graph)
76
+ self.assertEqual(fcs.regression_models, {})
77
+ self.assertEqual(fcs.feature_depths, {})
78
+ self.assertEqual(fcs.path_cache, {})
79
+ self.assertEqual(fcs.causal_paths, {})
80
+
81
+ def test_load_causal_strengths(self):
82
+ """Test loading causal strengths from JSON file.
83
+
84
+ This test verifies that the class can correctly load causal strengths from
85
+ a JSON file, compute the gamma values, and create the causal graph.
86
+
87
+ It tests the following:
88
+ - Loading the JSON file correctly.
89
+ - Graph construction from causal effects.
90
+ - Normalization of causal strengths. (gamma values should sum to 1)
91
+ - Proper handling of the ida_graph attribute.
92
+ """
93
+ # Create temporary JSON file
94
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
95
+ json.dump(self.sample_causal_effects, f)
96
+ temp_file = f.name
97
+
98
+ try:
99
+ # Test loading causal strengths
100
+ gamma = self.fast_causal_shap.load_causal_strengths(temp_file)
101
+
102
+ # Check that gamma is computed
103
+ self.assertIsInstance(gamma, dict)
104
+ self.assertIsNotNone(self.fast_causal_shap.gamma)
105
+ self.assertIsNotNone(self.fast_causal_shap.ida_graph)
106
+
107
+ # Check that graph is created
108
+ self.assertIsInstance(self.fast_causal_shap.ida_graph, nx.DiGraph)
109
+
110
+ # Check that gamma values sum to 1 (approximately)
111
+ total_gamma = sum(abs(v) for v in gamma.values())
112
+ self.assertAlmostEqual(total_gamma, 1.0, places=5)
113
+
114
+ finally:
115
+ os.unlink(temp_file)
116
+
117
+ def test_remove_cycles(self):
118
+ """Test cycle removal functionality.
119
+
120
+ This test ensures that the class can detect and remove cycles from causal
121
+ graph to create a Directed Acyclic Graph (DAG).
122
+ """
123
+ # Create a graph with cycles
124
+ G = nx.DiGraph()
125
+ G.add_edge('A', 'B', weight=0.5)
126
+ G.add_edge('B', 'C', weight=0.3)
127
+ G.add_edge('C', 'A', weight=0.1) # Creates a cycle
128
+
129
+ self.fast_causal_shap.ida_graph = G
130
+
131
+ # Test cycle removal
132
+ removed_edges = self.fast_causal_shap.remove_cycles()
133
+
134
+ # Check that cycles are removed
135
+ self.assertTrue(len(removed_edges) > 0)
136
+ self.assertTrue(nx.is_directed_acyclic_graph(self.fast_causal_shap.ida_graph))
137
+
138
+ def test_get_topological_order(self):
139
+ """Test topological ordering."""
140
+ # Set up a simple DAG
141
+ G = nx.DiGraph()
142
+ G.add_edges_from([('feature1', 'feature2'), ('feature2', 'target')])
143
+ self.fast_causal_shap.ida_graph = G
144
+
145
+ # Test topological order
146
+ order = self.fast_causal_shap.get_topological_order([])
147
+ self.assertIsInstance(order, list)
148
+
149
+ # Test with intervention
150
+ order_intervened = self.fast_causal_shap.get_topological_order(['feature1'])
151
+ self.assertIsInstance(order_intervened, list)
152
+
153
+ def test_get_parents(self):
154
+ """Test getting parent nodes."""
155
+ # Set up a simple graph
156
+ G = nx.DiGraph()
157
+ G.add_edges_from([('feature1', 'feature2'), ('feature3', 'feature2')])
158
+ self.fast_causal_shap.ida_graph = G
159
+
160
+ parents = self.fast_causal_shap.get_parents('feature2')
161
+ self.assertEqual(set(parents), {'feature1', 'feature3'})
162
+
163
+ parents_no_parent = self.fast_causal_shap.get_parents('feature1')
164
+ self.assertEqual(parents_no_parent, [])
165
+
166
+ def test_sample_marginal(self):
167
+ """Test marginal sampling."""
168
+ sampled_value = self.fast_causal_shap.sample_marginal('feature1')
169
+ self.assertIsInstance(sampled_value, (int, float, np.number))
170
+
171
+ # Check that sampled value is within reasonable range
172
+ feature_values = self.regression_data['feature1']
173
+ self.assertGreaterEqual(sampled_value, feature_values.min())
174
+ self.assertLessEqual(sampled_value, feature_values.max())
175
+
176
+ def test_sample_conditional(self):
177
+ """Test conditional sampling."""
178
+ # Set up a simple graph
179
+ G = nx.DiGraph()
180
+ G.add_edge('feature1', 'feature2')
181
+ self.fast_causal_shap.ida_graph = G
182
+
183
+ parent_values = {'feature1': 0.5}
184
+ sampled_value = self.fast_causal_shap.sample_conditional('feature2', parent_values)
185
+ self.assertIsInstance(sampled_value, (int, float, np.number))
186
+
187
+ def test_compute_v_do(self):
188
+ """Test interventional expectation computation.
189
+
190
+ This test verifies the core do-calculus computation. This test checks:
191
+ - Empty intervention handling.
192
+ - Intervention with specific values.
193
+ - Caching of results.
194
+ """
195
+ # Set up a simple graph with ALL nodes from data
196
+ self.fast_causal_shap.ida_graph = self._create_test_graph([('feature1', 'feature2'), ('feature2', 'target')])
197
+
198
+ # Test with empty intervention
199
+ result = self.fast_causal_shap.compute_v_do([], {})
200
+ self.assertIsInstance(result, (int, float, np.number))
201
+
202
+ # Test with intervention
203
+ result_intervened = self.fast_causal_shap.compute_v_do(['feature1'], {'feature1': 0.5})
204
+ self.assertIsInstance(result_intervened, (int, float, np.number))
205
+
206
+ # Test caching
207
+ result_cached = self.fast_causal_shap.compute_v_do(['feature1'], {'feature1': 0.5})
208
+ self.assertEqual(result_intervened, result_cached)
209
+
210
+ def test_compute_modified_shap_proba_regression(self):
211
+ """Test SHAP computation for regression."""
212
+ # Load causal strengths first
213
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
214
+ json.dump(self.sample_causal_effects, f)
215
+ temp_file = f.name
216
+
217
+ try:
218
+ self.fast_causal_shap.load_causal_strengths(temp_file)
219
+
220
+ # Test SHAP computation
221
+ x = self.regression_data.iloc[0][['feature1', 'feature2', 'feature3', 'feature4']]
222
+ shap_values = self.fast_causal_shap.compute_modified_shap_proba(x, is_classifier=False)
223
+
224
+ # Check that result is a dictionary
225
+ self.assertIsInstance(shap_values, dict)
226
+
227
+ # Check that all features are present
228
+ expected_features = ['feature1', 'feature2', 'feature3', 'feature4']
229
+ for feature in expected_features:
230
+ self.assertIn(feature, shap_values)
231
+ self.assertIsInstance(shap_values[feature], (int, float, np.number))
232
+
233
+ # Check that not all SHAP values are zero
234
+ # At least one feature should have non-zero attribution
235
+ total_abs_shap = sum(abs(shap_values[feature]) for feature in expected_features)
236
+ self.assertGreater(total_abs_shap, 0, "All SHAP values are zero - algorithm may not be working correctly")
237
+
238
+ finally:
239
+ os.unlink(temp_file)
240
+
241
+ def test_compute_modified_shap_proba_classification(self):
242
+ """Test SHAP computation for classification."""
243
+ # Create classification instance
244
+ fcs_clf = FastCausalSHAP(
245
+ data=self.classification_data,
246
+ model=self.classification_model,
247
+ target_variable='target'
248
+ )
249
+
250
+ # Load causal strengths
251
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
252
+ json.dump(self.sample_causal_effects, f)
253
+ temp_file = f.name
254
+
255
+ try:
256
+ fcs_clf.load_causal_strengths(temp_file)
257
+
258
+ # Test SHAP computation for classification
259
+ x = self.classification_data.iloc[0][['feature1', 'feature2', 'feature3', 'feature4']]
260
+ shap_values = fcs_clf.compute_modified_shap_proba(x, is_classifier=True)
261
+
262
+ # Check that result is a dictionary
263
+ self.assertIsInstance(shap_values, dict)
264
+
265
+ # Check that all features are present
266
+ expected_features = ['feature1', 'feature2', 'feature3', 'feature4']
267
+ for feature in expected_features:
268
+ self.assertIn(feature, shap_values)
269
+ self.assertIsInstance(shap_values[feature], (int, float, np.number))
270
+
271
+ # Check that not all SHAP values are zero
272
+ # At least one feature should have non-zero attribution
273
+ total_abs_shap = sum(abs(shap_values[feature]) for feature in expected_features)
274
+ self.assertGreater(total_abs_shap, 0, "All SHAP values are zero - algorithm may not be working correctly")
275
+
276
+ finally:
277
+ os.unlink(temp_file)
278
+
279
+ def test_compute_feature_depths(self):
280
+ """Test feature depth computation."""
281
+ # Set up a graph with known depths - include ALL nodes
282
+ self.fast_causal_shap.ida_graph = self._create_test_graph([
283
+ ('feature1', 'feature2'),
284
+ ('feature2', 'target'),
285
+ ('feature3', 'target')
286
+ ])
287
+ self.fast_causal_shap._compute_feature_depths()
288
+
289
+ # Check computed depths
290
+ self.assertEqual(self.fast_causal_shap.feature_depths['feature1'], 2)
291
+ self.assertEqual(self.fast_causal_shap.feature_depths['feature3'], 1)
292
+
293
+ def test_compute_causal_paths(self):
294
+ """Test causal path computation."""
295
+ # Set up a graph with known paths - include ALL nodes
296
+ self.fast_causal_shap.ida_graph = self._create_test_graph([
297
+ ('feature1', 'feature2'),
298
+ ('feature2', 'target'),
299
+ ('feature3', 'target')
300
+ ])
301
+ self.fast_causal_shap._compute_causal_paths()
302
+
303
+ # Check computed paths
304
+ self.assertIn('feature1', self.fast_causal_shap.causal_paths)
305
+ self.assertIn('feature3', self.fast_causal_shap.causal_paths)
306
+
307
+ # Check that feature1 has a path through feature2
308
+ feature1_paths = self.fast_causal_shap.causal_paths['feature1']
309
+ self.assertTrue(any('feature2' in path for path in feature1_paths))
310
+
311
+ def test_invalid_json_file(self):
312
+ """Test handling of invalid JSON file."""
313
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
314
+ f.write("invalid json content")
315
+ temp_file = f.name
316
+
317
+ try:
318
+ with self.assertRaises(json.JSONDecodeError):
319
+ self.fast_causal_shap.load_causal_strengths(temp_file)
320
+ finally:
321
+ os.unlink(temp_file)
322
+
323
+ def test_empty_causal_effects(self):
324
+ """Test handling of empty causal effects."""
325
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
326
+ json.dump([], f)
327
+ temp_file = f.name
328
+
329
+ try:
330
+ gamma = self.fast_causal_shap.load_causal_strengths(temp_file)
331
+ self.assertIsInstance(gamma, dict)
332
+ # All gamma values should be 0 for empty effects
333
+ self.assertTrue(all(v == 0.0 for v in gamma.values()))
334
+ finally:
335
+ os.unlink(temp_file)
336
+
337
+ def test_compute_path_delta_v(self):
338
+ """Test path delta V computation."""
339
+ # Set up a simple graph with ALL nodes
340
+ self.fast_causal_shap.ida_graph = self._create_test_graph([('feature1', 'target')])
341
+ self.fast_causal_shap._compute_feature_depths()
342
+ self.fast_causal_shap._compute_causal_paths()
343
+
344
+ # Create test data
345
+ x = self.regression_data.iloc[0][['feature1', 'feature2', 'feature3', 'feature4']]
346
+ path = ['feature1', 'target']
347
+
348
+ # Test delta V computation
349
+ delta_v = self.fast_causal_shap._compute_path_delta_v('feature1', path, 0, x, False)
350
+ self.assertIsInstance(delta_v, (int, float, np.number))
351
+
352
+
353
+
354
+ if __name__ == '__main__':
355
+ # Run the tests
356
+ unittest.main(verbosity=2)
@@ -1,50 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: fast-causal-shap
3
- Version: 0.1.0
4
- Summary: A Python package for efficient causal SHAP computations
5
- Author-email: woonyee28 <ngnwy289@gmail.com>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/woonyee28/CausalSHAP
8
- Project-URL: Issues, https://github.com/woonyee28/CausalSHAP/issues
9
- Requires-Python: >=3.7
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: pandas>=1.0.0
13
- Requires-Dist: networkx>=2.0
14
- Requires-Dist: numpy>=1.18.0
15
- Requires-Dist: scikit-learn>=0.24.0
16
- Dynamic: license-file
17
-
18
- # Fast Causal SHAP
19
-
20
- This folder contains the core modules and components for the **Fast Causal SHAP** Python package. Fast Causal SHAP provides efficient and interpretable SHAP value computation for causal inference tasks.
21
-
22
- ## Features
23
-
24
- - Fast computation of SHAP values for causal models
25
- - Support for multiple causal inference frameworks
26
-
27
- ## Installation
28
-
29
- Install Fast Causal SHAP using pip:
30
-
31
- ```bash
32
- pip install fast-causal-shap
33
- ```
34
-
35
- Or, for the latest development version:
36
-
37
- ```bash
38
- pip install git+https://github.com/woonyee28/CausalSHAP.git
39
- ```
40
-
41
- ## Usage
42
- // To be added
43
-
44
- ## Citation
45
- If you use this package in your research, please cite:
46
- // To be added
47
-
48
- ## License
49
-
50
- This project is licensed under the MIT License.
@@ -1,33 +0,0 @@
1
- # Fast Causal SHAP
2
-
3
- This folder contains the core modules and components for the **Fast Causal SHAP** Python package. Fast Causal SHAP provides efficient and interpretable SHAP value computation for causal inference tasks.
4
-
5
- ## Features
6
-
7
- - Fast computation of SHAP values for causal models
8
- - Support for multiple causal inference frameworks
9
-
10
- ## Installation
11
-
12
- Install Fast Causal SHAP using pip:
13
-
14
- ```bash
15
- pip install fast-causal-shap
16
- ```
17
-
18
- Or, for the latest development version:
19
-
20
- ```bash
21
- pip install git+https://github.com/woonyee28/CausalSHAP.git
22
- ```
23
-
24
- ## Usage
25
- // To be added
26
-
27
- ## Citation
28
- If you use this package in your research, please cite:
29
- // To be added
30
-
31
- ## License
32
-
33
- This project is licensed under the MIT License.
@@ -1,50 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: fast-causal-shap
3
- Version: 0.1.0
4
- Summary: A Python package for efficient causal SHAP computations
5
- Author-email: woonyee28 <ngnwy289@gmail.com>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/woonyee28/CausalSHAP
8
- Project-URL: Issues, https://github.com/woonyee28/CausalSHAP/issues
9
- Requires-Python: >=3.7
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: pandas>=1.0.0
13
- Requires-Dist: networkx>=2.0
14
- Requires-Dist: numpy>=1.18.0
15
- Requires-Dist: scikit-learn>=0.24.0
16
- Dynamic: license-file
17
-
18
- # Fast Causal SHAP
19
-
20
- This folder contains the core modules and components for the **Fast Causal SHAP** Python package. Fast Causal SHAP provides efficient and interpretable SHAP value computation for causal inference tasks.
21
-
22
- ## Features
23
-
24
- - Fast computation of SHAP values for causal models
25
- - Support for multiple causal inference frameworks
26
-
27
- ## Installation
28
-
29
- Install Fast Causal SHAP using pip:
30
-
31
- ```bash
32
- pip install fast-causal-shap
33
- ```
34
-
35
- Or, for the latest development version:
36
-
37
- ```bash
38
- pip install git+https://github.com/woonyee28/CausalSHAP.git
39
- ```
40
-
41
- ## Usage
42
- // To be added
43
-
44
- ## Citation
45
- If you use this package in your research, please cite:
46
- // To be added
47
-
48
- ## License
49
-
50
- This project is licensed under the MIT License.