PyHierarchicalTsetlinMachineCUDA 0.2.5__tar.gz → 0.2.7__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.
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA/kernels.py +106 -20
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA/tm.py +47 -19
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA.egg-info/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA.egg-info/requires.txt +1 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/README.md +10 -10
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/setup.py +2 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/LICENSE +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA/__init__.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA/tools.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA/utils.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA.egg-info/SOURCES.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA.egg-info/dependency_links.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/PyHierarchicalTsetlinMachineCUDA.egg-info/top_level.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.5 → PyHierarchicalTsetlinMachineCUDA-0.2.7}/setup.cfg +0 -0
|
@@ -159,7 +159,7 @@ code_update = """
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
// Evaluate example
|
|
162
|
-
__global__ void evaluate_leaves(unsigned int *global_ta_state, int *component_weights, int *global_component_output, int depth, int *hierarchy_structure_factors, int *
|
|
162
|
+
__global__ void evaluate_leaves(unsigned int *global_ta_state, int *component_weights, int *global_component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *X, int example)
|
|
163
163
|
{
|
|
164
164
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
165
165
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -168,35 +168,43 @@ code_update = """
|
|
|
168
168
|
|
|
169
169
|
// Evaluate each clause component (leaf) in separate threads
|
|
170
170
|
for (int clause_component = index; clause_component < CLAUSES*COMPONENTS; clause_component += stride) {
|
|
171
|
+
int clause = clause_component / COMPONENTS;
|
|
171
172
|
int component = clause_component % COMPONENTS;
|
|
172
173
|
|
|
173
|
-
// Get state of current clause component
|
|
174
|
-
unsigned int *ta_state = &global_ta_state[clause_component*TA_CHUNKS_PER_LEAF*STATE_BITS];
|
|
175
|
-
|
|
176
174
|
int component_remainder = component;
|
|
175
|
+
int feature_chunk_base = 0;
|
|
177
176
|
int ta_chunk_base = 0;
|
|
178
|
-
int
|
|
177
|
+
int size_feature_chunk_base = 1;
|
|
178
|
+
int size_ta_chunk_base = 1;
|
|
179
179
|
for (int d = 0; d < depth-1; ++d) {
|
|
180
180
|
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
181
181
|
component_remainder = component_remainder / hierarchy_structure_factors[d];
|
|
182
182
|
|
|
183
|
-
if (
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
if (hierarchy_structure_type[d] != 1) {
|
|
184
|
+
feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
185
|
+
size_feature_chunk_base *= hierarchy_structure_factors[d];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (hierarchy_structure_type[d] != 2) {
|
|
189
|
+
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
190
|
+
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
186
191
|
}
|
|
187
192
|
}
|
|
188
193
|
|
|
194
|
+
// Get state of current ta team component
|
|
195
|
+
unsigned int *ta_state = &global_ta_state[clause*COMPONENTS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
|
|
196
|
+
|
|
189
197
|
// Evaluate clause component
|
|
190
198
|
int component_output = 1;
|
|
191
199
|
for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF-1; ++ta_chunk) {
|
|
192
200
|
// Compare the TA state of the component (leaf) against the corresponding part of the feature vector
|
|
193
|
-
if ((ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1] & Xi[
|
|
201
|
+
if ((ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1] & Xi[feature_chunk_base + ta_chunk]) != ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1]) {
|
|
194
202
|
component_output = 0;
|
|
195
203
|
break;
|
|
196
204
|
}
|
|
197
205
|
}
|
|
198
206
|
|
|
199
|
-
if ((ta_state[(TA_CHUNKS_PER_LEAF-1)*STATE_BITS + STATE_BITS - 1] & Xi[
|
|
207
|
+
if ((ta_state[(TA_CHUNKS_PER_LEAF-1)*STATE_BITS + STATE_BITS - 1] & Xi[feature_chunk_base + TA_CHUNKS_PER_LEAF-1] & FILTER_HIERARCHICAL) != (ta_state[(TA_CHUNKS_PER_LEAF-1)*STATE_BITS + STATE_BITS - 1] & FILTER_HIERARCHICAL)) {
|
|
200
208
|
component_output = 0;
|
|
201
209
|
}
|
|
202
210
|
|
|
@@ -213,9 +221,15 @@ code_update = """
|
|
|
213
221
|
for (int or_group_node = index; or_group_node < CLAUSES*number_of_or_group_nodes; or_group_node += stride) {
|
|
214
222
|
// Add OR addends
|
|
215
223
|
int or_group_vote_sum = 0;
|
|
224
|
+
int max_vote_sum = 0;
|
|
225
|
+
|
|
216
226
|
for (int or_addend = 0; or_addend < number_of_or_group_addends; ++or_addend) {
|
|
217
227
|
// Aggregate votes from each child node through addition
|
|
218
228
|
|
|
229
|
+
if (child_input[or_group_node*number_of_or_group_addends + or_addend] > max_vote_sum) {
|
|
230
|
+
max_vote_sum = child_input[or_group_node*number_of_or_group_addends + or_addend];
|
|
231
|
+
}
|
|
232
|
+
|
|
219
233
|
int previous_or_group_vote_sum = or_group_vote_sum;
|
|
220
234
|
or_group_vote_sum += child_input[or_group_node*number_of_or_group_addends + or_addend];
|
|
221
235
|
if (or_group_vote_sum < 0) {
|
|
@@ -224,8 +238,8 @@ code_update = """
|
|
|
224
238
|
}
|
|
225
239
|
}
|
|
226
240
|
|
|
227
|
-
//
|
|
228
|
-
or_group_node_output[or_group_node] =
|
|
241
|
+
//or_group_node_output[or_group_node] = or_group_vote_sum;
|
|
242
|
+
or_group_node_output[or_group_node] = max_vote_sum;
|
|
229
243
|
}
|
|
230
244
|
}
|
|
231
245
|
|
|
@@ -238,12 +252,17 @@ code_update = """
|
|
|
238
252
|
for (int and_group_node = index; and_group_node < CLAUSES*number_of_and_group_nodes; and_group_node += stride) {
|
|
239
253
|
// Multiply and factors
|
|
240
254
|
int and_group_vote_product = 1;
|
|
255
|
+
int max_vote_sum = 0;
|
|
241
256
|
for (int and_factor = 0; and_factor < number_of_and_group_factors; ++and_factor) {
|
|
242
257
|
// Aggregate votes from each child node through multiplication
|
|
243
258
|
|
|
244
259
|
int previous_and_group_vote_product = and_group_vote_product;
|
|
245
260
|
and_group_vote_product *= child_input[and_group_node*number_of_and_group_factors + and_factor];
|
|
246
261
|
|
|
262
|
+
if (child_input[and_group_node*number_of_and_group_factors + and_factor] > max_vote_sum) {
|
|
263
|
+
max_vote_sum = child_input[and_group_node*number_of_and_group_factors + and_factor];
|
|
264
|
+
}
|
|
265
|
+
|
|
247
266
|
if (and_group_vote_product < 0) {
|
|
248
267
|
printf("AND OVERFLOW %d -> %d\\n", previous_and_group_vote_product, and_group_vote_product);
|
|
249
268
|
and_group_vote_product = previous_and_group_vote_product;
|
|
@@ -252,6 +271,7 @@ code_update = """
|
|
|
252
271
|
|
|
253
272
|
// Store and group product as node output
|
|
254
273
|
and_group_node_output[and_group_node] = and_group_vote_product;
|
|
274
|
+
//and_group_node_output[and_group_node] = max_vote_sum;
|
|
255
275
|
}
|
|
256
276
|
}
|
|
257
277
|
|
|
@@ -272,6 +292,58 @@ code_update = """
|
|
|
272
292
|
}
|
|
273
293
|
}
|
|
274
294
|
|
|
295
|
+
__global__ void propagate_or_group_false_truth_values(curandState *state, int *child_input, int *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
|
|
296
|
+
{
|
|
297
|
+
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
298
|
+
int stride = blockDim.x * gridDim.x;
|
|
299
|
+
|
|
300
|
+
int non_zero_children[361];
|
|
301
|
+
|
|
302
|
+
/* Copy state to local memory for efficiency */
|
|
303
|
+
curandState localState = state[index];
|
|
304
|
+
|
|
305
|
+
// If a group node is false, all children are made false.
|
|
306
|
+
for (int group_node = index; group_node < CLAUSES*number_of_group_nodes; group_node += stride) {
|
|
307
|
+
int number_of_non_zero_children = 0;
|
|
308
|
+
|
|
309
|
+
if (group_node_output[group_node] == -1) {
|
|
310
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
311
|
+
child_input[group_node*number_of_group_node_children + or_addend] = -1;
|
|
312
|
+
}
|
|
313
|
+
} else if (group_node_output[group_node] == 0) {
|
|
314
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
315
|
+
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
|
|
316
|
+
child_input[group_node*number_of_group_node_children + or_addend] = 0;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
321
|
+
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
|
|
322
|
+
non_zero_children[number_of_non_zero_children] = or_addend;
|
|
323
|
+
number_of_non_zero_children++;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (group_node_output[group_node] != -1) {
|
|
329
|
+
int selected_child;
|
|
330
|
+
if (number_of_non_zero_children > 0) {
|
|
331
|
+
selected_child = non_zero_children[curand(&localState) % number_of_non_zero_children];
|
|
332
|
+
} else {
|
|
333
|
+
selected_child = curand(&localState) % number_of_group_node_children;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
337
|
+
if (selected_child != or_addend) {
|
|
338
|
+
child_input[group_node*number_of_group_node_children + or_addend] = -1;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
state[index] = localState;
|
|
345
|
+
}
|
|
346
|
+
|
|
275
347
|
__global__ void evaluate_or_alternatives(int *child_input, int *or_alternatives_node_output, int number_of_or_alternatives_nodes, int number_of_or_alternatives)
|
|
276
348
|
{
|
|
277
349
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
@@ -316,7 +388,7 @@ code_update = """
|
|
|
316
388
|
}
|
|
317
389
|
|
|
318
390
|
// Update state of Tsetlin Automata team
|
|
319
|
-
__global__ void update_hierarchy(curandState *state, int number_of_outputs, unsigned int *global_ta_state, int *clause_weights, int *component_output, int depth, int *hierarchy_structure_factors, int *
|
|
391
|
+
__global__ void update_hierarchy(curandState *state, int number_of_outputs, unsigned int *global_ta_state, int *clause_weights, int *component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *class_sum, int *X, int *y, int example)
|
|
320
392
|
{
|
|
321
393
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
322
394
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -328,25 +400,39 @@ code_update = """
|
|
|
328
400
|
|
|
329
401
|
// Calculate clause output first
|
|
330
402
|
for (int clause_component = index; clause_component < CLAUSES*COMPONENTS; clause_component += stride) {
|
|
403
|
+
if (component_output[clause_component] == -1) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
|
|
331
407
|
int clause = clause_component / COMPONENTS;
|
|
332
408
|
int component = clause_component % COMPONENTS;
|
|
333
409
|
|
|
334
410
|
// Get state of current clause component
|
|
335
|
-
|
|
411
|
+
// This one must be updated for reuse of TAs within OR group
|
|
336
412
|
|
|
337
413
|
int component_remainder = component;
|
|
414
|
+
int feature_chunk_base = 0;
|
|
338
415
|
int ta_chunk_base = 0;
|
|
339
|
-
int
|
|
416
|
+
int size_feature_chunk_base = 1;
|
|
417
|
+
int size_ta_chunk_base = 1;
|
|
340
418
|
for (int d = 0; d < depth-1; ++d) {
|
|
341
419
|
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
342
420
|
component_remainder = component_remainder / hierarchy_structure_factors[d];
|
|
343
421
|
|
|
344
|
-
if (
|
|
345
|
-
|
|
346
|
-
|
|
422
|
+
if (hierarchy_structure_type[d] != 1) {
|
|
423
|
+
feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
424
|
+
size_feature_chunk_base *= hierarchy_structure_factors[d];
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (hierarchy_structure_type[d] != 2) {
|
|
428
|
+
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
429
|
+
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
347
430
|
}
|
|
348
431
|
}
|
|
349
432
|
|
|
433
|
+
// Get state of current ta team component
|
|
434
|
+
unsigned int *ta_state = &global_ta_state[clause*COMPONENTS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
|
|
435
|
+
|
|
350
436
|
for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
351
437
|
int local_class_sum = class_sum[class_id];
|
|
352
438
|
if (local_class_sum > THRESHOLD) {
|
|
@@ -355,7 +441,7 @@ code_update = """
|
|
|
355
441
|
local_class_sum = -THRESHOLD;
|
|
356
442
|
}
|
|
357
443
|
|
|
358
|
-
update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, component_output[clause_component], &Xi[
|
|
444
|
+
update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, component_output[clause_component], &Xi[feature_chunk_base], y[example*number_of_outputs + class_id], local_class_sum);
|
|
359
445
|
}
|
|
360
446
|
}
|
|
361
447
|
|
|
@@ -503,7 +589,7 @@ code_clauses = """
|
|
|
503
589
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
504
590
|
int stride = blockDim.x * gridDim.x;
|
|
505
591
|
|
|
506
|
-
for (unsigned long long i = index; i < CLAUSES * COMPONENTS * LITERALS_PER_LEAF; i += stride) {
|
|
592
|
+
for (unsigned long long i = index; i < 1LLU * CLAUSES * COMPONENTS * LITERALS_PER_LEAF; i += stride) {
|
|
507
593
|
unsigned long long clause = i / (COMPONENTS * LITERALS_PER_LEAF);
|
|
508
594
|
unsigned long long comp = (i / LITERALS_PER_LEAF) % COMPONENTS;
|
|
509
595
|
unsigned long long ta_idx = i % LITERALS_PER_LEAF;
|
|
@@ -28,6 +28,7 @@ import pycuda.driver as cuda
|
|
|
28
28
|
import pycuda.autoinit
|
|
29
29
|
from pycuda.compiler import SourceModule
|
|
30
30
|
from pycuda import gpuarray
|
|
31
|
+
import sys
|
|
31
32
|
|
|
32
33
|
from time import time
|
|
33
34
|
|
|
@@ -64,11 +65,13 @@ class CommonTsetlinMachine():
|
|
|
64
65
|
|
|
65
66
|
# Represents hierarchy structure for transfer to GPU
|
|
66
67
|
self.hierarchy_structure_factors = [0] * (self.depth - 1)
|
|
67
|
-
self.
|
|
68
|
+
self.hierarchy_structure_type = [0] * (self.depth - 1)
|
|
68
69
|
for d in range(1, self.depth):
|
|
69
70
|
self.hierarchy_structure_factors[d-1] = self.hierarchy_structure[d][1]
|
|
70
71
|
if self.hierarchy_structure[d][0] == OR_ALTERNATIVES:
|
|
71
|
-
self.
|
|
72
|
+
self.hierarchy_structure_type[d-1] = 1
|
|
73
|
+
elif self.hierarchy_structure[d][0] == OR_GROUP:
|
|
74
|
+
self.hierarchy_structure_type[d-1] = 2
|
|
72
75
|
|
|
73
76
|
# Calculates total number of features spanned by the hierarchy
|
|
74
77
|
self.number_of_features_hierarchy = 1
|
|
@@ -147,6 +150,9 @@ class CommonTsetlinMachine():
|
|
|
147
150
|
self.propagate_and_group_false_truth_values = mod_update.get_function("propagate_and_group_false_truth_values")
|
|
148
151
|
self.propagate_and_group_false_truth_values.prepare("PPii")
|
|
149
152
|
|
|
153
|
+
self.propagate_or_group_false_truth_values = mod_update.get_function("propagate_or_group_false_truth_values")
|
|
154
|
+
self.propagate_or_group_false_truth_values.prepare("PPPii")
|
|
155
|
+
|
|
150
156
|
self.evaluate_or_groups = mod_update.get_function("evaluate_or_groups")
|
|
151
157
|
self.evaluate_or_groups.prepare("PPii")
|
|
152
158
|
|
|
@@ -189,8 +195,8 @@ class CommonTsetlinMachine():
|
|
|
189
195
|
cuda.memcpy_htod(self.hierarchy_structure_factors_gpu, np.array(self.hierarchy_structure_factors, dtype=np.int32))
|
|
190
196
|
|
|
191
197
|
# GPU memory for storing hierarchy structure
|
|
192
|
-
self.
|
|
193
|
-
cuda.memcpy_htod(self.
|
|
198
|
+
self.hierarchy_structure_type_gpu = cuda.mem_alloc((self.depth-1)*4)
|
|
199
|
+
cuda.memcpy_htod(self.hierarchy_structure_type_gpu, np.array(self.hierarchy_structure_type, dtype=np.int32))
|
|
194
200
|
|
|
195
201
|
# GPU memory for storing Tsetlin Automata states
|
|
196
202
|
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.hierarchy_size[0]*self.number_of_state_bits*4)
|
|
@@ -266,7 +272,7 @@ class CommonTsetlinMachine():
|
|
|
266
272
|
self.hierarchy_votes[0],
|
|
267
273
|
self.depth,
|
|
268
274
|
self.hierarchy_structure_factors_gpu,
|
|
269
|
-
self.
|
|
275
|
+
self.hierarchy_structure_type_gpu,
|
|
270
276
|
encoded_X_hierarchy,
|
|
271
277
|
np.int32(e)
|
|
272
278
|
)
|
|
@@ -320,6 +326,10 @@ class CommonTsetlinMachine():
|
|
|
320
326
|
cuda.Context.synchronize()
|
|
321
327
|
|
|
322
328
|
def _fit(self, X, encoded_Y, epochs=100, incremental=False):
|
|
329
|
+
if self.number_of_features_hierarchy != X.shape[1]:
|
|
330
|
+
print("The number of features spanned by hierarchy does not align with the input data.")
|
|
331
|
+
sys.exit(-1)
|
|
332
|
+
|
|
323
333
|
number_of_examples = X.shape[0]
|
|
324
334
|
|
|
325
335
|
if self.first:
|
|
@@ -347,15 +357,27 @@ class CommonTsetlinMachine():
|
|
|
347
357
|
# Propagates the root value and any intermittent node values back to the leaves.
|
|
348
358
|
# The purpose is to determine which leaves only has True nodes on the path from leaf to root.
|
|
349
359
|
for d in range(self.depth-1, 0, -1):
|
|
350
|
-
self.
|
|
351
|
-
self.
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
360
|
+
if self.hierarchy_structure[d][0] != OR_GROUP:
|
|
361
|
+
self.propagate_and_group_false_truth_values.prepared_call(
|
|
362
|
+
self.grid,
|
|
363
|
+
self.block,
|
|
364
|
+
self.hierarchy_votes[d-1],
|
|
365
|
+
self.hierarchy_votes[d],
|
|
366
|
+
self.hierarchy_size[d + 1],
|
|
367
|
+
self.hierarchy_structure[d][1]
|
|
368
|
+
)
|
|
369
|
+
cuda.Context.synchronize()
|
|
370
|
+
else:
|
|
371
|
+
self.propagate_or_group_false_truth_values.prepared_call(
|
|
372
|
+
self.grid,
|
|
373
|
+
self.block,
|
|
374
|
+
self.cuda_rng.state,
|
|
375
|
+
self.hierarchy_votes[d-1],
|
|
376
|
+
self.hierarchy_votes[d],
|
|
377
|
+
self.hierarchy_size[d + 1],
|
|
378
|
+
self.hierarchy_structure[d][1]
|
|
379
|
+
)
|
|
380
|
+
cuda.Context.synchronize()
|
|
359
381
|
|
|
360
382
|
# Updates the clause components (leaves) based on the propagated truth values
|
|
361
383
|
self.update_hierarchy.prepared_call(
|
|
@@ -368,7 +390,7 @@ class CommonTsetlinMachine():
|
|
|
368
390
|
self.hierarchy_votes[0],
|
|
369
391
|
self.depth,
|
|
370
392
|
self.hierarchy_structure_factors_gpu,
|
|
371
|
-
self.
|
|
393
|
+
self.hierarchy_structure_type_gpu,
|
|
372
394
|
self.class_sum_gpu,
|
|
373
395
|
encoded_X_hierarchy_training_gpu,
|
|
374
396
|
Y_gpu,
|
|
@@ -517,10 +539,16 @@ class CommonTsetlinMachine():
|
|
|
517
539
|
left = []
|
|
518
540
|
right = []
|
|
519
541
|
inside = []
|
|
542
|
+
feature_base = 0
|
|
543
|
+
size = self.hierarchy_structure[0][1]
|
|
520
544
|
for d in range(1, self.depth):
|
|
521
545
|
depth_d_node_index = component_remainder % self.hierarchy_structure[d][1]
|
|
522
546
|
component_remainder = component_remainder // self.hierarchy_structure[d][1]
|
|
523
547
|
|
|
548
|
+
if self.hierarchy_structure[d][0] != OR_ALTERNATIVES:
|
|
549
|
+
feature_base += size * depth_d_node_index
|
|
550
|
+
size *= self.hierarchy_structure[d][1];
|
|
551
|
+
|
|
524
552
|
if previous_index[d-1] == -1:
|
|
525
553
|
left.append("(")
|
|
526
554
|
elif depth_d_node_index == 0 and previous_index[d-1] != depth_d_node_index:
|
|
@@ -545,14 +573,14 @@ class CommonTsetlinMachine():
|
|
|
545
573
|
if self.ta_action(i, j, k):
|
|
546
574
|
if k < self.number_of_literals_per_leaf // 2:
|
|
547
575
|
if print_ta_state:
|
|
548
|
-
l.append("x%d(%d)" % (k, self.ta_state(i, j, k)))
|
|
576
|
+
l.append("x%d(%d)" % (feature_base + k, self.ta_state(i, j, k)))
|
|
549
577
|
else:
|
|
550
|
-
l.append("x%d" % (k,))
|
|
578
|
+
l.append("x%d" % (feature_base + k,))
|
|
551
579
|
else:
|
|
552
580
|
if print_ta_state:
|
|
553
|
-
l.append("¬x%d(%d)" % (k - self.number_of_literals_per_leaf // 2, self.ta_state(i, j, k)))
|
|
581
|
+
l.append("¬x%d(%d)" % (feature_base + k - self.number_of_literals_per_leaf // 2, self.ta_state(i, j, k)))
|
|
554
582
|
else:
|
|
555
|
-
l.append("¬x%d" % (k - self.number_of_literals_per_leaf // 2,))
|
|
583
|
+
l.append("¬x%d" % (feature_base + k - self.number_of_literals_per_leaf // 2,))
|
|
556
584
|
|
|
557
585
|
if len(l) > 1:
|
|
558
586
|
print("(" + " ∧ ".join(l) + ")", end = '')
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
# Hierarchical Tsetlin Machine in CUDA
|
|
2
2
|
Implements the [Hierarchical Tsetlin Machine](https://github.com/cair/HierarchicalTsetlinMachine) in CUDA.
|
|
3
3
|
|
|
4
|
-
<p align="center">
|
|
5
|
-
<img width="60%" src="https://github.com/cair/PyHierarchicalTsetlinMachineCUDA/blob/main/figures/Visualization_voting.png">
|
|
6
|
-
</p>
|
|
7
|
-
|
|
8
4
|
## Installation
|
|
9
5
|
|
|
10
6
|
```bash
|
|
@@ -15,13 +11,17 @@ or
|
|
|
15
11
|
git clone git@github.com:cair/PyHierarchicalTsetlinMachineCUDA.git
|
|
16
12
|
cd PyHierarchicalTsetlinMachineCUDA
|
|
17
13
|
python ./setup.py sdist
|
|
18
|
-
pip install dist/PyHierarchicalTsetlinMachineCUDA-0.2.
|
|
14
|
+
pip install dist/PyHierarchicalTsetlinMachineCUDA-0.2.6.tar.gz
|
|
19
15
|
```
|
|
20
16
|
|
|
21
17
|
## Examples
|
|
22
18
|
|
|
23
19
|
### Noisy Parity Demo
|
|
24
20
|
|
|
21
|
+
<p align="center">
|
|
22
|
+
<img width="60%" src="https://github.com/cair/PyHierarchicalTsetlinMachineCUDA/blob/main/figures/Visualization_voting.png">
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
25
|
#### Code: NoisyParityDemo.py
|
|
26
26
|
|
|
27
27
|
```python
|
|
@@ -149,11 +149,11 @@ python3 ./examples/HexDemo.py
|
|
|
149
149
|
|
|
150
150
|
Accuracy over 1000 epochs:
|
|
151
151
|
|
|
152
|
-
#1 Training Accuracy: 97.
|
|
153
|
-
#2 Training Accuracy: 99.
|
|
154
|
-
#3 Training Accuracy: 99.
|
|
155
|
-
#4 Training Accuracy: 99.
|
|
156
|
-
#5 Training Accuracy: 99.
|
|
152
|
+
#1 Training Accuracy: 97.98% Testing Accuracy: 97.46% Training Time: 37.02s Testing Time: 5.74s
|
|
153
|
+
#2 Training Accuracy: 99.19% Testing Accuracy: 98.70% Training Time: 34.44s Testing Time: 5.76s
|
|
154
|
+
#3 Training Accuracy: 99.49% Testing Accuracy: 98.92% Training Time: 33.60s Testing Time: 5.75s
|
|
155
|
+
#4 Training Accuracy: 99.65% Testing Accuracy: 99.05% Training Time: 33.15s Testing Time: 5.78s
|
|
156
|
+
#5 Training Accuracy: 99.73% Testing Accuracy: 99.10% Training Time: 32.86s Testing Time: 5.76s
|
|
157
157
|
...
|
|
158
158
|
#446 Training Accuracy: 100.00% Testing Accuracy: 99.45% Training Time: 32.09s Testing Time: 6.09s
|
|
159
159
|
#447 Training Accuracy: 100.00% Testing Accuracy: 99.46% Training Time: 32.08s Testing Time: 6.09s
|
|
@@ -2,7 +2,7 @@ from setuptools import *
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='PyHierarchicalTsetlinMachineCUDA',
|
|
5
|
-
version='0.2.
|
|
5
|
+
version='0.2.7',
|
|
6
6
|
author='Ole-Christoffer Granmo',
|
|
7
7
|
author_email='ole.granmo@uia.no',
|
|
8
8
|
url='https://github.com/cair/PyHierarchicalTsetlinMachineCUDA/',
|
|
@@ -16,6 +16,7 @@ setup(
|
|
|
16
16
|
'pycuda',
|
|
17
17
|
'scipy',
|
|
18
18
|
'scikit-learn',
|
|
19
|
+
'scikit-image',
|
|
19
20
|
'networkx',
|
|
20
21
|
],
|
|
21
22
|
extras_require={
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|