PyHierarchicalTsetlinMachineCUDA 0.2.8__tar.gz → 0.2.9__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.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/kernels.py +46 -393
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/tm.py +130 -136
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/README.md +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/setup.py +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/LICENSE +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/__init__.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/tools.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/utils.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/SOURCES.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/dependency_links.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/requires.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/top_level.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/setup.cfg +0 -0
|
@@ -114,36 +114,6 @@ code_update = """
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
__device__ inline void update_clause_weight_old(curandState *localState, int tm_type, int number_of_outputs, int *clause_weight, int clause_output, int y, int class_sum)
|
|
118
|
-
{
|
|
119
|
-
int target = 1 - 2*(class_sum > y);
|
|
120
|
-
|
|
121
|
-
if (target == -1 && curand_uniform(localState) > 1.0*Q/max(1, number_of_outputs-1)) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
int sign = (*clause_weight >= 0) - (*clause_weight < 0);
|
|
126
|
-
|
|
127
|
-
int absolute_prediction_error = abs(y - class_sum);
|
|
128
|
-
if (curand_uniform(localState) <= 1.0*absolute_prediction_error/(2*THRESHOLD)) {
|
|
129
|
-
if (target*sign > 0) {
|
|
130
|
-
if (clause_output && abs(*clause_weight) < INT_MAX) {
|
|
131
|
-
(*clause_weight) += sign;
|
|
132
|
-
}
|
|
133
|
-
} else if (target*sign < 0 && clause_output) {
|
|
134
|
-
// Type II Feedback
|
|
135
|
-
|
|
136
|
-
(*clause_weight) -= sign;
|
|
137
|
-
|
|
138
|
-
#if FLIP_POLARITY == 0
|
|
139
|
-
if (*clause_weight == 0) {
|
|
140
|
-
*clause_weight += sign;
|
|
141
|
-
}
|
|
142
|
-
#endif
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
117
|
__device__ inline void update_component_hierarchy(curandState *localState, int number_of_outputs, int *clause_weight, unsigned int *ta_state, int component_output, int *X, int y, float class_sum)
|
|
148
118
|
{
|
|
149
119
|
int target = 1 - 2*(class_sum > y);
|
|
@@ -189,52 +159,6 @@ code_update = """
|
|
|
189
159
|
}
|
|
190
160
|
}
|
|
191
161
|
|
|
192
|
-
__device__ inline void update_component_hierarchy_old(curandState *localState, int number_of_outputs, int *clause_weight, unsigned int *ta_state, int component_output, int *X, int y, int class_sum)
|
|
193
|
-
{
|
|
194
|
-
int target = 1 - 2*(class_sum > y);
|
|
195
|
-
|
|
196
|
-
if (target == -1 && curand_uniform(localState) > 1.0*Q/max(1, number_of_outputs-1)) {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
int sign = (*clause_weight >= 0) - (*clause_weight < 0);
|
|
202
|
-
|
|
203
|
-
int absolute_prediction_error = abs(y - class_sum);
|
|
204
|
-
if (curand_uniform(localState) <= 1.0*absolute_prediction_error/(2*THRESHOLD)) {
|
|
205
|
-
if (target*sign > 0) {
|
|
206
|
-
// Type I Feedback
|
|
207
|
-
for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF; ++ta_chunk) {
|
|
208
|
-
// Generate random bit values
|
|
209
|
-
unsigned int la_feedback = 0;
|
|
210
|
-
for (int b = 0; b < INT_SIZE; ++b) {
|
|
211
|
-
if (curand_uniform(localState) <= 1.0/S) {
|
|
212
|
-
la_feedback |= (1 << b);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (component_output) {
|
|
217
|
-
#if BOOST_TRUE_POSITIVE_FEEDBACK == 1
|
|
218
|
-
inc(ta_state, ta_chunk, X[ta_chunk]);
|
|
219
|
-
#else
|
|
220
|
-
inc(ta_state, ta_chunk, X[ta_chunk] & (~la_feedback));
|
|
221
|
-
#endif
|
|
222
|
-
|
|
223
|
-
dec(ta_state, ta_chunk, (~X[ta_chunk]) & la_feedback);
|
|
224
|
-
} else {
|
|
225
|
-
dec(ta_state, ta_chunk, la_feedback);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
} else if (target*sign < 0 && component_output) {
|
|
229
|
-
// Type II Feedback
|
|
230
|
-
|
|
231
|
-
for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF; ++ta_chunk) {
|
|
232
|
-
inc(ta_state, ta_chunk, (~X[ta_chunk]) & (~ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1]));
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
162
|
// Evaluate example
|
|
239
163
|
__global__ void evaluate_leaves(unsigned int *global_ta_state, int *component_weights, float *global_component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *X, int example)
|
|
240
164
|
{
|
|
@@ -254,22 +178,24 @@ code_update = """
|
|
|
254
178
|
int size_feature_chunk_base = 1;
|
|
255
179
|
int size_ta_chunk_base = 1;
|
|
256
180
|
for (int d = 0; d < depth-1; ++d) {
|
|
257
|
-
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
258
|
-
component_remainder = component_remainder / hierarchy_structure_factors[d];
|
|
181
|
+
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d]; // Extract local index of node at depth d (the child index)
|
|
182
|
+
component_remainder = component_remainder / hierarchy_structure_factors[d]; // Move up the hierarchy to prepare for finding the local node index at depth d+1
|
|
259
183
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
size_feature_chunk_base
|
|
184
|
+
// Support multiple Tsetlin Automata teams operating on the same feature chunks to create alternatives.
|
|
185
|
+
if ((hierarchy_structure_type[d] != OR_ALTERNATIVES) && (hierarchy_structure_type[d] != AND_ALTERNATIVES)) {
|
|
186
|
+
feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF; // Identify correct part of the sub-hierarchy (through flattening)
|
|
187
|
+
size_feature_chunk_base *= hierarchy_structure_factors[d]; // Identify how many nodes to jump to skip from one child to the next when indexing at the next depth level
|
|
263
188
|
}
|
|
264
189
|
|
|
265
|
-
|
|
190
|
+
// Support reuse of the same Tsetlin Automata when doing OR to group different feature chunks
|
|
191
|
+
if (hierarchy_structure_type[d] != OR_GROUP) {
|
|
266
192
|
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
267
193
|
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
268
194
|
}
|
|
269
195
|
}
|
|
270
196
|
|
|
271
197
|
// Get state of current ta team component
|
|
272
|
-
unsigned int *ta_state = &global_ta_state[clause*
|
|
198
|
+
unsigned int *ta_state = &global_ta_state[clause*TA_TEAMS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
|
|
273
199
|
|
|
274
200
|
// Evaluate clause component
|
|
275
201
|
|
|
@@ -304,60 +230,6 @@ code_update = """
|
|
|
304
230
|
}
|
|
305
231
|
}
|
|
306
232
|
|
|
307
|
-
// Evaluate example
|
|
308
|
-
__global__ void evaluate_leaves_old(unsigned int *global_ta_state, int *component_weights, float *global_component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *X, int example)
|
|
309
|
-
{
|
|
310
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
311
|
-
int stride = blockDim.x * gridDim.x;
|
|
312
|
-
|
|
313
|
-
int *Xi = &X[(unsigned long long)example*LITERAL_CHUNKS];
|
|
314
|
-
|
|
315
|
-
// Evaluate each clause component (leaf) in separate threads
|
|
316
|
-
for (int clause_component = index; clause_component < CLAUSES*COMPONENTS; clause_component += stride) {
|
|
317
|
-
int clause = clause_component / COMPONENTS;
|
|
318
|
-
int component = clause_component % COMPONENTS;
|
|
319
|
-
|
|
320
|
-
int component_remainder = component;
|
|
321
|
-
int feature_chunk_base = 0;
|
|
322
|
-
int ta_chunk_base = 0;
|
|
323
|
-
int size_feature_chunk_base = 1;
|
|
324
|
-
int size_ta_chunk_base = 1;
|
|
325
|
-
for (int d = 0; d < depth-1; ++d) {
|
|
326
|
-
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
327
|
-
component_remainder = component_remainder / hierarchy_structure_factors[d];
|
|
328
|
-
|
|
329
|
-
if (hierarchy_structure_type[d] != 1) {
|
|
330
|
-
feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
331
|
-
size_feature_chunk_base *= hierarchy_structure_factors[d];
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (hierarchy_structure_type[d] != 2) {
|
|
335
|
-
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
336
|
-
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Get state of current ta team component
|
|
341
|
-
unsigned int *ta_state = &global_ta_state[clause*COMPONENTS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
|
|
342
|
-
|
|
343
|
-
// Evaluate clause component
|
|
344
|
-
int component_output = 1;
|
|
345
|
-
for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF-1; ++ta_chunk) {
|
|
346
|
-
// Compare the TA state of the component (leaf) against the corresponding part of the feature vector
|
|
347
|
-
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]) {
|
|
348
|
-
component_output = 0;
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
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)) {
|
|
354
|
-
component_output = 0;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
global_component_output[clause_component] = component_output;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
233
|
__global__ void evaluate_or_groups(float *child_input, float *or_group_node_output, int number_of_or_group_nodes, int number_of_or_group_addends)
|
|
362
234
|
{
|
|
363
235
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
@@ -410,38 +282,6 @@ code_update = """
|
|
|
410
282
|
}
|
|
411
283
|
}
|
|
412
284
|
|
|
413
|
-
__global__ void evaluate_and_groups_old(float *child_input, float *and_group_node_output, int number_of_and_group_nodes, int number_of_and_group_factors)
|
|
414
|
-
{
|
|
415
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
416
|
-
int stride = blockDim.x * gridDim.x;
|
|
417
|
-
|
|
418
|
-
// Multiply the votes from the children of each AND node
|
|
419
|
-
for (int and_group_node = index; and_group_node < CLAUSES*number_of_and_group_nodes; and_group_node += stride) {
|
|
420
|
-
// Multiply and factors
|
|
421
|
-
int and_group_vote_product = 1;
|
|
422
|
-
int max_vote_sum = 0;
|
|
423
|
-
for (int and_factor = 0; and_factor < number_of_and_group_factors; ++and_factor) {
|
|
424
|
-
// Aggregate votes from each child node through multiplication
|
|
425
|
-
|
|
426
|
-
int previous_and_group_vote_product = and_group_vote_product;
|
|
427
|
-
and_group_vote_product *= child_input[and_group_node*number_of_and_group_factors + and_factor];
|
|
428
|
-
|
|
429
|
-
if (child_input[and_group_node*number_of_and_group_factors + and_factor] > max_vote_sum) {
|
|
430
|
-
max_vote_sum = child_input[and_group_node*number_of_and_group_factors + and_factor];
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if (and_group_vote_product < 0) {
|
|
434
|
-
printf("AND OVERFLOW %d -> %d\\n", previous_and_group_vote_product, and_group_vote_product);
|
|
435
|
-
and_group_vote_product = previous_and_group_vote_product;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// Store and group product as node output
|
|
440
|
-
and_group_node_output[and_group_node] = and_group_vote_product;
|
|
441
|
-
//and_group_node_output[and_group_node] = max_vote_sum;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
285
|
__global__ void propagate_and_group_false_truth_values(float *child_input, float *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
|
|
446
286
|
//__global__ void propagate_and_group_false_truth_values_log(int *child_input, int *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
|
|
447
287
|
{
|
|
@@ -476,23 +316,6 @@ code_update = """
|
|
|
476
316
|
}
|
|
477
317
|
}
|
|
478
318
|
|
|
479
|
-
__global__ void propagate_and_group_false_truth_values_old(float *child_input, float *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
|
|
480
|
-
{
|
|
481
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
482
|
-
int stride = blockDim.x * gridDim.x;
|
|
483
|
-
|
|
484
|
-
// If a group node is false, all children are made false.
|
|
485
|
-
for (int group_node = index; group_node < CLAUSES*number_of_group_nodes; group_node += stride) {
|
|
486
|
-
if (group_node_output[group_node] == 0) {
|
|
487
|
-
for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
|
|
488
|
-
if (child_input[group_node*number_of_group_node_children + and_factor] > 0) {
|
|
489
|
-
child_input[group_node*number_of_group_node_children + and_factor] = 0;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
319
|
__global__ void propagate_or_group_false_truth_values(curandState *state, float *child_input, float *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
|
|
497
320
|
{
|
|
498
321
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
@@ -539,7 +362,7 @@ code_update = """
|
|
|
539
362
|
}
|
|
540
363
|
} else {
|
|
541
364
|
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
542
|
-
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
|
|
365
|
+
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) { // Or pick the largest.... picking randomly when a tie
|
|
543
366
|
non_zero_children[number_of_non_zero_children] = or_addend;
|
|
544
367
|
number_of_non_zero_children++;
|
|
545
368
|
}
|
|
@@ -566,58 +389,6 @@ code_update = """
|
|
|
566
389
|
state[index] = localState;
|
|
567
390
|
}
|
|
568
391
|
|
|
569
|
-
__global__ void propagate_or_group_false_truth_values_old(curandState *state, float *child_input, float *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
|
|
570
|
-
{
|
|
571
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
572
|
-
int stride = blockDim.x * gridDim.x;
|
|
573
|
-
|
|
574
|
-
int non_zero_children[361];
|
|
575
|
-
|
|
576
|
-
/* Copy state to local memory for efficiency */
|
|
577
|
-
curandState localState = state[index];
|
|
578
|
-
|
|
579
|
-
// If a group node is false, all children are made false.
|
|
580
|
-
for (int group_node = index; group_node < CLAUSES*number_of_group_nodes; group_node += stride) {
|
|
581
|
-
int number_of_non_zero_children = 0;
|
|
582
|
-
|
|
583
|
-
if (group_node_output[group_node] == -1) {
|
|
584
|
-
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
585
|
-
child_input[group_node*number_of_group_node_children + or_addend] = -1;
|
|
586
|
-
}
|
|
587
|
-
} else if (group_node_output[group_node] == 0) {
|
|
588
|
-
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
589
|
-
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
|
|
590
|
-
child_input[group_node*number_of_group_node_children + or_addend] = 0;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
} else {
|
|
594
|
-
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
595
|
-
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
|
|
596
|
-
non_zero_children[number_of_non_zero_children] = or_addend;
|
|
597
|
-
number_of_non_zero_children++;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
if (group_node_output[group_node] != -1) {
|
|
603
|
-
int selected_child;
|
|
604
|
-
if (number_of_non_zero_children > 0) {
|
|
605
|
-
selected_child = non_zero_children[curand(&localState) % number_of_non_zero_children];
|
|
606
|
-
} else {
|
|
607
|
-
selected_child = curand(&localState) % number_of_group_node_children;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
611
|
-
if (selected_child != or_addend) {
|
|
612
|
-
child_input[group_node*number_of_group_node_children + or_addend] = -1;
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
state[index] = localState;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
392
|
__global__ void evaluate_or_alternatives(float *child_input, float *or_alternatives_node_output, int number_of_or_alternatives_nodes, int number_of_or_alternatives)
|
|
622
393
|
//__global__ void evaluate_or_alternatives_log(int *child_input, int *or_alternatives_node_output, int number_of_or_alternatives_nodes, int number_of_or_alternatives)
|
|
623
394
|
{
|
|
@@ -662,34 +433,6 @@ code_update = """
|
|
|
662
433
|
}
|
|
663
434
|
}
|
|
664
435
|
|
|
665
|
-
__global__ void evaluate_or_alternatives_old(float *child_input, float *or_alternatives_node_output, int number_of_or_alternatives_nodes, int number_of_or_alternatives)
|
|
666
|
-
{
|
|
667
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
668
|
-
int stride = blockDim.x * gridDim.x;
|
|
669
|
-
|
|
670
|
-
// Add up the votes from the children of each OR node
|
|
671
|
-
for (int or_alternatives_node = index; or_alternatives_node < CLAUSES*number_of_or_alternatives_nodes; or_alternatives_node += stride) {
|
|
672
|
-
// Sum up votes from each or alternative
|
|
673
|
-
int or_alternatives_vote_sum = 0;
|
|
674
|
-
for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
|
|
675
|
-
// Aggregate same input or alternatives through summation
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
int previous_or_alternatives_vote_sum = or_alternatives_vote_sum;
|
|
679
|
-
or_alternatives_vote_sum += child_input[or_alternatives_node * number_of_or_alternatives + or_alternative];
|
|
680
|
-
|
|
681
|
-
if (or_alternatives_vote_sum < 0) {
|
|
682
|
-
printf("OR OVERFLOW %d -> %d\\n", previous_or_alternatives_vote_sum, or_alternatives_vote_sum);
|
|
683
|
-
or_alternatives_vote_sum = previous_or_alternatives_vote_sum;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// Store vote sum as node output
|
|
688
|
-
or_alternatives_node_output[or_alternatives_node] = or_alternatives_vote_sum;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
|
|
693
436
|
__global__ void max_clause_output(int number_of_outputs, float *clause_output, float *clause_output_max)
|
|
694
437
|
{
|
|
695
438
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
@@ -701,19 +444,36 @@ code_update = """
|
|
|
701
444
|
}
|
|
702
445
|
}
|
|
703
446
|
|
|
704
|
-
__global__ void evaluate_final(int number_of_outputs, float *clause_output,
|
|
447
|
+
__global__ void evaluate_final(int number_of_outputs, float *clause_output, int *clause_weights, float *class_sum)
|
|
705
448
|
{
|
|
706
449
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
707
450
|
int stride = blockDim.x * gridDim.x;
|
|
708
451
|
|
|
709
452
|
// Add up the votes from each clause
|
|
710
453
|
#if LOG_SCALE == 1
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
454
|
+
// Add up the votes from each clause
|
|
455
|
+
for (int class_id = index; class_id < number_of_outputs; class_id += stride) {
|
|
456
|
+
float clause_output_max = NEG_INFINITY;
|
|
457
|
+
for (int clause = 0; clause < CLAUSES; ++clause) {
|
|
458
|
+
if (clause_output[clause] > clause_output_max) {
|
|
459
|
+
clause_output_max = clause_output[clause];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (clause_output_max != NEG_INFINITY) {
|
|
464
|
+
float weighted_clause_output_sum = 0;
|
|
465
|
+
for (int clause = 0; clause < CLAUSES; ++clause) {
|
|
466
|
+
weighted_clause_output_sum += clause_weights[class_id*CLAUSES + clause] * exp2f(clause_output[clause] - clause_output_max);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (log2f(fabs(weighted_clause_output_sum)) + clause_output_max >= log2f(THRESHOLD)) {
|
|
470
|
+
float sign = (1 - 2 * (weighted_clause_output_sum < 0));
|
|
471
|
+
class_sum[class_id] = sign*THRESHOLD;
|
|
472
|
+
} else {
|
|
473
|
+
class_sum[class_id] = weighted_clause_output_sum * exp2f(clause_output_max);
|
|
716
474
|
}
|
|
475
|
+
} else {
|
|
476
|
+
class_sum[class_id] = 0;
|
|
717
477
|
}
|
|
718
478
|
}
|
|
719
479
|
#else
|
|
@@ -727,22 +487,6 @@ code_update = """
|
|
|
727
487
|
#endif
|
|
728
488
|
}
|
|
729
489
|
|
|
730
|
-
__global__ void evaluate_final_old(int number_of_outputs, float *child_input, int *clause_weights, int *class_sum)
|
|
731
|
-
{
|
|
732
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
733
|
-
int stride = blockDim.x * gridDim.x;
|
|
734
|
-
|
|
735
|
-
// Add up the votes from each clause
|
|
736
|
-
for (int clause = index; clause < CLAUSES; clause += stride) {
|
|
737
|
-
if (child_input[clause]) {
|
|
738
|
-
for (int class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
739
|
-
int clause_weight = clause_weights[class_id*CLAUSES + clause];
|
|
740
|
-
atomicAdd(&class_sum[class_id], (int) clause_weight * child_input[clause]);
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
490
|
__global__ void rescale_final(int number_of_outputs, float *clause_output_max, float *class_sum)
|
|
747
491
|
{
|
|
748
492
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
@@ -797,19 +541,19 @@ code_update = """
|
|
|
797
541
|
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
798
542
|
component_remainder = component_remainder / hierarchy_structure_factors[d];
|
|
799
543
|
|
|
800
|
-
if (hierarchy_structure_type[d] !=
|
|
544
|
+
if ((hierarchy_structure_type[d] != OR_ALTERNATIVES) && (hierarchy_structure_type[d] != AND_ALTERNATIVES)) {
|
|
801
545
|
feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
802
546
|
size_feature_chunk_base *= hierarchy_structure_factors[d];
|
|
803
547
|
}
|
|
804
548
|
|
|
805
|
-
if (hierarchy_structure_type[d] !=
|
|
549
|
+
if (hierarchy_structure_type[d] != OR_GROUP) {
|
|
806
550
|
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
807
551
|
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
808
552
|
}
|
|
809
553
|
}
|
|
810
554
|
|
|
811
555
|
// Get state of current ta team component
|
|
812
|
-
unsigned int *ta_state = &global_ta_state[clause*
|
|
556
|
+
unsigned int *ta_state = &global_ta_state[clause*TA_TEAMS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
|
|
813
557
|
|
|
814
558
|
for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
815
559
|
float local_class_sum = class_sum[class_id];
|
|
@@ -830,68 +574,6 @@ code_update = """
|
|
|
830
574
|
state[index] = localState;
|
|
831
575
|
}
|
|
832
576
|
|
|
833
|
-
// Update state of Tsetlin Automata team
|
|
834
|
-
__global__ void update_hierarchy_old(curandState *state, int number_of_outputs, unsigned int *global_ta_state, int *clause_weights, float *component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *class_sum, int *X, int *y, int example)
|
|
835
|
-
{
|
|
836
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
837
|
-
int stride = blockDim.x * gridDim.x;
|
|
838
|
-
|
|
839
|
-
/* Copy state to local memory for efficiency */
|
|
840
|
-
curandState localState = state[index];
|
|
841
|
-
|
|
842
|
-
int *Xi = &X[(unsigned long long)example*LITERAL_CHUNKS];
|
|
843
|
-
|
|
844
|
-
// Calculate clause output first
|
|
845
|
-
for (int clause_component = index; clause_component < CLAUSES*COMPONENTS; clause_component += stride) {
|
|
846
|
-
if (component_output[clause_component] == -1) {
|
|
847
|
-
continue;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
int clause = clause_component / COMPONENTS;
|
|
851
|
-
int component = clause_component % COMPONENTS;
|
|
852
|
-
|
|
853
|
-
// Get state of current clause component
|
|
854
|
-
// This one must be updated for reuse of TAs within OR group
|
|
855
|
-
|
|
856
|
-
int component_remainder = component;
|
|
857
|
-
int feature_chunk_base = 0;
|
|
858
|
-
int ta_chunk_base = 0;
|
|
859
|
-
int size_feature_chunk_base = 1;
|
|
860
|
-
int size_ta_chunk_base = 1;
|
|
861
|
-
for (int d = 0; d < depth-1; ++d) {
|
|
862
|
-
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
863
|
-
component_remainder = component_remainder / hierarchy_structure_factors[d];
|
|
864
|
-
|
|
865
|
-
if (hierarchy_structure_type[d] != 1) {
|
|
866
|
-
feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
867
|
-
size_feature_chunk_base *= hierarchy_structure_factors[d];
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
if (hierarchy_structure_type[d] != 2) {
|
|
871
|
-
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
872
|
-
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
// Get state of current ta team component
|
|
877
|
-
unsigned int *ta_state = &global_ta_state[clause*COMPONENTS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
|
|
878
|
-
|
|
879
|
-
for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
880
|
-
int local_class_sum = class_sum[class_id];
|
|
881
|
-
if (local_class_sum > THRESHOLD) {
|
|
882
|
-
local_class_sum = THRESHOLD;
|
|
883
|
-
} else if (local_class_sum < -THRESHOLD) {
|
|
884
|
-
local_class_sum = -THRESHOLD;
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, (int) component_output[clause_component], &Xi[feature_chunk_base], y[example*number_of_outputs + class_id], local_class_sum);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
state[index] = localState;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
|
|
895
577
|
// Update state of Tsetlin Automata team
|
|
896
578
|
__global__ void update_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights, float *clause_output, float *class_sum, int *y, int example)
|
|
897
579
|
{
|
|
@@ -920,37 +602,13 @@ code_update = """
|
|
|
920
602
|
|
|
921
603
|
state[index] = localState;
|
|
922
604
|
}
|
|
923
|
-
|
|
924
|
-
// Update state of Tsetlin Automata team
|
|
925
|
-
__global__ void update_weights_old(curandState *state, int tm_type, int number_of_outputs, int *clause_weights, float *clause_output, int *class_sum, int *y, int example)
|
|
926
|
-
{
|
|
927
|
-
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
928
|
-
int stride = blockDim.x * gridDim.x;
|
|
929
|
-
|
|
930
|
-
/* Copy state to local memory for efficiency */
|
|
931
|
-
curandState localState = state[index];
|
|
932
|
-
|
|
933
|
-
for (unsigned long long clause = index; clause < CLAUSES; clause += stride) {
|
|
934
|
-
for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
935
|
-
int local_class_sum = class_sum[class_id];
|
|
936
|
-
if (local_class_sum > THRESHOLD) {
|
|
937
|
-
local_class_sum = THRESHOLD;
|
|
938
|
-
} else if (local_class_sum < -THRESHOLD) {
|
|
939
|
-
local_class_sum = -THRESHOLD;
|
|
940
|
-
}
|
|
941
|
-
update_clause_weight(&localState, tm_type, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], (int) clause_output[clause], y[example*number_of_outputs + class_id], local_class_sum);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
state[index] = localState;
|
|
946
|
-
}
|
|
947
605
|
}
|
|
948
606
|
"""
|
|
949
607
|
|
|
950
608
|
code_prepare = """
|
|
951
609
|
extern "C"
|
|
952
610
|
{
|
|
953
|
-
__global__ void prepare_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights
|
|
611
|
+
__global__ void prepare_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights)
|
|
954
612
|
{
|
|
955
613
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
956
614
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -974,17 +632,14 @@ code_prepare = """
|
|
|
974
632
|
state[index] = localState;
|
|
975
633
|
}
|
|
976
634
|
|
|
977
|
-
__global__ void prepare_hierarchy(
|
|
635
|
+
__global__ void prepare_hierarchy(int number_of_outputs, unsigned int *global_ta_state)
|
|
978
636
|
{
|
|
979
637
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
980
638
|
int stride = blockDim.x * gridDim.x;
|
|
981
639
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
for (int clause_component = index; clause_component < CLAUSES*COMPONENTS; clause_component += stride) {
|
|
986
|
-
// Get state of current clause component
|
|
987
|
-
unsigned int *ta_state = &global_ta_state[clause_component*TA_CHUNKS_PER_LEAF*STATE_BITS];
|
|
640
|
+
for (int clause_team = index; clause_team < CLAUSES*TA_TEAMS; clause_team += stride) {
|
|
641
|
+
// Get state of current ta team
|
|
642
|
+
unsigned int *ta_state = &global_ta_state[clause_team*TA_CHUNKS_PER_LEAF*STATE_BITS];
|
|
988
643
|
for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF; ++ta_chunk) {
|
|
989
644
|
for (int b = 0; b < STATE_BITS-1; ++b) {
|
|
990
645
|
ta_state[ta_chunk*STATE_BITS + b] = ~0;
|
|
@@ -992,8 +647,6 @@ code_prepare = """
|
|
|
992
647
|
ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1] = 0;
|
|
993
648
|
}
|
|
994
649
|
}
|
|
995
|
-
|
|
996
|
-
state[index] = localState;
|
|
997
650
|
}
|
|
998
651
|
}
|
|
999
652
|
"""
|
|
@@ -1062,9 +715,9 @@ code_clauses = """
|
|
|
1062
715
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
1063
716
|
int stride = blockDim.x * gridDim.x;
|
|
1064
717
|
|
|
1065
|
-
for (unsigned long long i = index; i < 1LLU * CLAUSES *
|
|
1066
|
-
unsigned long long clause = i / (
|
|
1067
|
-
unsigned long long comp = (i / LITERALS_PER_LEAF) %
|
|
718
|
+
for (unsigned long long i = index; i < 1LLU * CLAUSES * TA_TEAMS * LITERALS_PER_LEAF; i += stride) {
|
|
719
|
+
unsigned long long clause = i / (TA_TEAMS * LITERALS_PER_LEAF);
|
|
720
|
+
unsigned long long comp = (i / LITERALS_PER_LEAF) % TA_TEAMS;
|
|
1068
721
|
unsigned long long ta_idx = i % LITERALS_PER_LEAF;
|
|
1069
722
|
|
|
1070
723
|
int chunk = ta_idx / 32;
|
|
@@ -1073,14 +726,14 @@ code_clauses = """
|
|
|
1073
726
|
unsigned int state = 0;
|
|
1074
727
|
for (int b = 0; b < STATE_BITS; ++b) {
|
|
1075
728
|
unsigned int plane = global_ta_state[
|
|
1076
|
-
(clause *
|
|
729
|
+
(clause * TA_TEAMS * TA_CHUNKS_PER_LEAF * STATE_BITS) +
|
|
1077
730
|
(comp * TA_CHUNKS_PER_LEAF * STATE_BITS) +
|
|
1078
731
|
(chunk * STATE_BITS) + b
|
|
1079
732
|
];
|
|
1080
733
|
if (plane & (1U << bit_pos)) state |= (1U << b);
|
|
1081
734
|
}
|
|
1082
735
|
|
|
1083
|
-
unpacked_states[(clause *
|
|
736
|
+
unpacked_states[(clause * TA_TEAMS * LITERALS_PER_LEAF) + (comp * LITERALS_PER_LEAF) + ta_idx] = state;
|
|
1084
737
|
}
|
|
1085
738
|
}
|
|
1086
739
|
"""
|
|
@@ -33,15 +33,15 @@ import sys
|
|
|
33
33
|
|
|
34
34
|
from time import time
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
AND_GROUP = 0
|
|
37
|
+
AND_ALTERNATIVES = 1
|
|
38
|
+
OR_GROUP = 2
|
|
39
|
+
OR_ALTERNATIVES = 3
|
|
39
40
|
|
|
40
41
|
VANILLA_TM = 0
|
|
41
42
|
WEIGHTED_TM = 1
|
|
42
43
|
COALESCED_TM = 2
|
|
43
44
|
|
|
44
|
-
|
|
45
45
|
class CommonTsetlinMachine():
|
|
46
46
|
|
|
47
47
|
def __init__(self, number_of_clauses, T, s, q=1.0, log_scale=False, hierarchy_structure=None, boost_true_positive_feedback=1, number_of_state_bits=8, append_negated=True, grid=(16*13,1,1), block=(128,1,1), seed=None):
|
|
@@ -69,11 +69,8 @@ class CommonTsetlinMachine():
|
|
|
69
69
|
self.hierarchy_structure_factors = [0] * (self.depth - 1)
|
|
70
70
|
self.hierarchy_structure_type = [0] * (self.depth - 1)
|
|
71
71
|
for d in range(1, self.depth):
|
|
72
|
+
self.hierarchy_structure_type[d-1] = self.hierarchy_structure[d][0]
|
|
72
73
|
self.hierarchy_structure_factors[d-1] = self.hierarchy_structure[d][1]
|
|
73
|
-
if self.hierarchy_structure[d][0] == OR_ALTERNATIVES:
|
|
74
|
-
self.hierarchy_structure_type[d-1] = 1
|
|
75
|
-
elif self.hierarchy_structure[d][0] == OR_GROUP:
|
|
76
|
-
self.hierarchy_structure_type[d-1] = 2
|
|
77
74
|
|
|
78
75
|
# Calculates total number of features spanned by the hierarchy
|
|
79
76
|
self.number_of_features_hierarchy = 1
|
|
@@ -95,7 +92,12 @@ class CommonTsetlinMachine():
|
|
|
95
92
|
# Calculates the number of literal chunks for the full hierarchy
|
|
96
93
|
self.hierarchy_size[0] = self.number_of_literal_chunks_per_leaf * self.hierarchy_size[1]
|
|
97
94
|
|
|
98
|
-
|
|
95
|
+
self.number_of_ta_teams = 1
|
|
96
|
+
for d in range(self.depth - 1):
|
|
97
|
+
if self.hierarchy_structure[d][0] != OR_GROUP: # OR_GROUP reuses the same TA
|
|
98
|
+
self.number_of_ta_teams = self.hierarchy_structure[self.depth - d - 1][1] * self.number_of_ta_teams
|
|
99
|
+
|
|
100
|
+
# Calculates number of literal chunks overall for the feature vector (ignores OR- and AND alternatives)
|
|
99
101
|
self.number_of_literal_chunks = self.number_of_literal_chunks_per_leaf
|
|
100
102
|
for d in range(self.depth - 1, 0, -1):
|
|
101
103
|
if (self.hierarchy_structure[d][0] == OR_GROUP or self.hierarchy_structure[d][0] == AND_GROUP):
|
|
@@ -116,6 +118,7 @@ class CommonTsetlinMachine():
|
|
|
116
118
|
#define CLAUSES %d
|
|
117
119
|
#define DEPTH %d
|
|
118
120
|
#define COMPONENTS %d
|
|
121
|
+
#define TA_TEAMS %d
|
|
119
122
|
#define LITERALS_PER_LEAF %d
|
|
120
123
|
#define TA_CHUNKS_PER_LEAF %d
|
|
121
124
|
#define LITERAL_CHUNKS %d
|
|
@@ -126,9 +129,14 @@ class CommonTsetlinMachine():
|
|
|
126
129
|
#define Q %f
|
|
127
130
|
#define LOG_SCALE %d
|
|
128
131
|
|
|
132
|
+
#define AND_GROUP %d
|
|
133
|
+
#define AND_ALTERNATIVES %d
|
|
134
|
+
#define OR_GROUP %d
|
|
135
|
+
#define OR_ALTERNATIVES %d
|
|
136
|
+
|
|
129
137
|
#define NEGATIVE_CLAUSES %d
|
|
130
138
|
#define FLIP_POLARITY %d
|
|
131
|
-
""" % (self.number_of_clauses, self.depth, self.hierarchy_size[1], self.number_of_literals_per_leaf, self.number_of_literal_chunks_per_leaf, self.number_of_literal_chunks, self.number_of_state_bits, self.boost_true_positive_feedback, self.s, self.T, self.q, self.log_scale, self.negative_clauses, self.flip_polarity)
|
|
139
|
+
""" % (self.number_of_clauses, self.depth, self.hierarchy_size[1], self.number_of_ta_teams, self.number_of_literals_per_leaf, self.number_of_literal_chunks_per_leaf, self.number_of_literal_chunks, self.number_of_state_bits, self.boost_true_positive_feedback, self.s, self.T, self.q, self.log_scale, AND_GROUP, AND_ALTERNATIVES, OR_GROUP, OR_ALTERNATIVES, self.negative_clauses, self.flip_polarity)
|
|
132
140
|
|
|
133
141
|
mod_prepare = SourceModule(parameters + kernels.code_header + kernels.code_prepare, no_extern_c=True)
|
|
134
142
|
self.prepare_weights = mod_prepare.get_function("prepare_weights")
|
|
@@ -148,7 +156,7 @@ class CommonTsetlinMachine():
|
|
|
148
156
|
self.max_clause_output.prepare("iPP")
|
|
149
157
|
|
|
150
158
|
self.evaluate_final = mod_update.get_function("evaluate_final")
|
|
151
|
-
self.evaluate_final.prepare("
|
|
159
|
+
self.evaluate_final.prepare("iPPP")
|
|
152
160
|
|
|
153
161
|
self.rescale_final = mod_update.get_function("rescale_final")
|
|
154
162
|
self.rescale_final.prepare("iPP")
|
|
@@ -186,11 +194,9 @@ class CommonTsetlinMachine():
|
|
|
186
194
|
|
|
187
195
|
# Prepares for leaf encoding of the input data
|
|
188
196
|
self.prepare_encode_hierarchy(X_gpu, encoded_X_hierarchy_gpu, np.int32(self.number_of_literal_chunks), np.int32(number_of_examples), grid=self.grid, block=self.block)
|
|
189
|
-
cuda.Context.synchronize()
|
|
190
197
|
|
|
191
198
|
# Encodes the input data split across the leaves
|
|
192
199
|
self.encode_hierarchy(X_gpu, encoded_X_hierarchy_gpu, np.int32(self.number_of_features_hierarchy), np.int32(self.number_of_literal_chunks), np.int32(self.hierarchy_size[1]), np.int32(self.number_of_features_per_leaf), np.int32(self.number_of_literal_chunks_per_leaf), np.int32(self.append_negated), np.int32(number_of_examples), grid=self.grid, block=self.block)
|
|
193
|
-
cuda.Context.synchronize()
|
|
194
200
|
|
|
195
201
|
def allocate_gpu_memory(self):
|
|
196
202
|
# GPU memory for accumulating votes, level by level
|
|
@@ -209,7 +215,7 @@ class CommonTsetlinMachine():
|
|
|
209
215
|
cuda.memcpy_htod(self.hierarchy_structure_type_gpu, np.array(self.hierarchy_structure_type, dtype=np.int32))
|
|
210
216
|
|
|
211
217
|
# GPU memory for storing Tsetlin Automata states
|
|
212
|
-
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.
|
|
218
|
+
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.number_of_ta_teams*self.number_of_literal_chunks_per_leaf*self.number_of_state_bits*4)
|
|
213
219
|
self.clause_weights_gpu = cuda.mem_alloc(self.number_of_outputs*self.number_of_clauses*4)
|
|
214
220
|
self.component_weights_gpu = cuda.mem_alloc(self.number_of_clauses*self.hierarchy_size[1]*4) # Only positive weights...
|
|
215
221
|
self.class_sum_gpu = cuda.mem_alloc(self.number_of_outputs*4)
|
|
@@ -218,16 +224,16 @@ class CommonTsetlinMachine():
|
|
|
218
224
|
self.clause_output_max = np.ascontiguousarray(np.empty(1)).astype(np.float32)
|
|
219
225
|
|
|
220
226
|
def ta_action(self, clause, leaf, ta):
|
|
221
|
-
ta_state_hierarchy = np.empty(self.number_of_clauses*self.
|
|
227
|
+
ta_state_hierarchy = np.empty(self.number_of_clauses*self.number_of_ta_teams*self.number_of_literal_chunks_per_leaf*self.number_of_state_bits, dtype=np.uint32)
|
|
222
228
|
cuda.memcpy_dtoh(ta_state_hierarchy, self.ta_state_hierarchy_gpu)
|
|
223
|
-
ta_state_hierarchy = ta_state_hierarchy.reshape((self.number_of_clauses, self.
|
|
229
|
+
ta_state_hierarchy = ta_state_hierarchy.reshape((self.number_of_clauses, self.number_of_ta_teams, self.number_of_literal_chunks_per_leaf, self.number_of_state_bits))
|
|
224
230
|
|
|
225
231
|
return (ta_state_hierarchy[clause, leaf, ta // 32, self.number_of_state_bits-1] & (1 << (ta % 32))) > 0
|
|
226
232
|
|
|
227
233
|
def ta_state(self, clause, leaf, ta):
|
|
228
|
-
ta_state_hierarchy = np.empty(self.number_of_clauses*self.
|
|
234
|
+
ta_state_hierarchy = np.empty(self.number_of_clauses*self.number_of_ta_teams*self.number_of_literal_chunks_per_leaf*self.number_of_state_bits, dtype=np.uint32)
|
|
229
235
|
cuda.memcpy_dtoh(ta_state_hierarchy, self.ta_state_hierarchy_gpu)
|
|
230
|
-
ta_state_hierarchy = ta_state_hierarchy.reshape((self.number_of_clauses, self.
|
|
236
|
+
ta_state_hierarchy = ta_state_hierarchy.reshape((self.number_of_clauses, self.number_of_ta_teams, self.number_of_literal_chunks_per_leaf, self.number_of_state_bits))
|
|
231
237
|
|
|
232
238
|
state = 0
|
|
233
239
|
for b in range(self.number_of_state_bits):
|
|
@@ -238,7 +244,7 @@ class CommonTsetlinMachine():
|
|
|
238
244
|
|
|
239
245
|
def get_state(self):
|
|
240
246
|
# To be updated
|
|
241
|
-
ta_state_hierarchy = np.empty(self.number_of_clauses*self.
|
|
247
|
+
ta_state_hierarchy = np.empty(self.number_of_clauses*self.number_of_ta_teams*self.number_of_literal_chunks_per_leaf*self.number_of_state_bits, dtype=np.uint32)
|
|
242
248
|
cuda.memcpy_dtoh(self.ta_state_hierarchy, self.ta_state_hierarchy_gpu)
|
|
243
249
|
clause_weights = np.empty(self.number_of_outputs*self.number_of_clauses).astype(np.int32)
|
|
244
250
|
cuda.memcpy_dtoh(self.clause_weights, self.clause_weights_gpu)
|
|
@@ -255,7 +261,7 @@ class CommonTsetlinMachine():
|
|
|
255
261
|
self.min_y = state[8]
|
|
256
262
|
self.max_y = state[9]
|
|
257
263
|
|
|
258
|
-
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.
|
|
264
|
+
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.number_of_ta_teams*self.number_of_state_bits*4)
|
|
259
265
|
self.clause_weights_gpu = cuda.mem_alloc(self.number_of_outputs*self.number_of_clauses*4)
|
|
260
266
|
cuda.memcpy_htod(self.ta_state_hierarchy_gpu, state[0])
|
|
261
267
|
cuda.memcpy_htod(self.clause_weights_gpu, state[1])
|
|
@@ -265,15 +271,13 @@ class CommonTsetlinMachine():
|
|
|
265
271
|
None # To be updated
|
|
266
272
|
|
|
267
273
|
def initialize_weights_and_ta_states(self):
|
|
268
|
-
self.prepare_weights(self.cuda_rng.state, np.int32(self.tm_type), np.int32(self.number_of_outputs), self.clause_weights_gpu,
|
|
269
|
-
cuda.Context.synchronize()
|
|
274
|
+
self.prepare_weights(self.cuda_rng.state, np.int32(self.tm_type), np.int32(self.number_of_outputs), self.clause_weights_gpu, grid=self.grid, block=self.block)
|
|
270
275
|
|
|
271
|
-
self.prepare_hierarchy(
|
|
272
|
-
cuda.Context.synchronize()
|
|
276
|
+
self.prepare_hierarchy(np.int32(self.number_of_outputs), self.ta_state_hierarchy_gpu, grid=self.grid, block=self.block)
|
|
273
277
|
|
|
274
278
|
def evaluate_hierarchy(self, encoded_X_hierarchy, e):
|
|
275
279
|
# Initializes class sums to zero
|
|
276
|
-
class_sum = np.
|
|
280
|
+
class_sum = np.zeros(self.number_of_outputs, dtype=np.float32)
|
|
277
281
|
cuda.memcpy_htod(self.class_sum_gpu, class_sum)
|
|
278
282
|
|
|
279
283
|
# Evaluates all the hierarchy leaves in parallel
|
|
@@ -289,11 +293,10 @@ class CommonTsetlinMachine():
|
|
|
289
293
|
encoded_X_hierarchy,
|
|
290
294
|
np.int32(e)
|
|
291
295
|
)
|
|
292
|
-
cuda.Context.synchronize()
|
|
293
296
|
|
|
294
297
|
# Propagates votes bottom-up in the hierarchy, starting from the clause components (leaves)
|
|
295
298
|
for d in range(1, self.depth):
|
|
296
|
-
if (self.hierarchy_structure[d][0] == AND_GROUP):
|
|
299
|
+
if (self.hierarchy_structure[d][0] == AND_GROUP or self.hierarchy_structure[d][0] == AND_ALTERNATIVES):
|
|
297
300
|
self.evaluate_and_groups.prepared_call(
|
|
298
301
|
self.grid,
|
|
299
302
|
self.block,
|
|
@@ -302,7 +305,6 @@ class CommonTsetlinMachine():
|
|
|
302
305
|
self.hierarchy_size[d + 1],
|
|
303
306
|
self.hierarchy_structure[d][1]
|
|
304
307
|
)
|
|
305
|
-
cuda.Context.synchronize()
|
|
306
308
|
elif self.hierarchy_structure[d][0] == OR_GROUP:
|
|
307
309
|
self.evaluate_or_groups.prepared_call(
|
|
308
310
|
self.grid,
|
|
@@ -312,7 +314,6 @@ class CommonTsetlinMachine():
|
|
|
312
314
|
self.hierarchy_size[d + 1],
|
|
313
315
|
self.hierarchy_structure[d][1]
|
|
314
316
|
)
|
|
315
|
-
cuda.Context.synchronize()
|
|
316
317
|
elif self.hierarchy_structure[d][0] == OR_ALTERNATIVES:
|
|
317
318
|
self.evaluate_or_alternatives.prepared_call(
|
|
318
319
|
self.grid,
|
|
@@ -322,23 +323,20 @@ class CommonTsetlinMachine():
|
|
|
322
323
|
self.hierarchy_size[d + 1],
|
|
323
324
|
self.hierarchy_structure[d][1]
|
|
324
325
|
)
|
|
325
|
-
cuda.Context.synchronize()
|
|
326
326
|
else:
|
|
327
|
-
|
|
328
|
-
sys.exit()
|
|
327
|
+
raise ValueError("Unknown Node Type!")
|
|
329
328
|
|
|
330
329
|
self.clause_output_max[:] = np.finfo(np.float32).min
|
|
331
330
|
cuda.memcpy_htod(self.clause_output_max_gpu, self.clause_output_max)
|
|
332
331
|
|
|
333
|
-
if self.log_scale:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
cuda.Context.synchronize()
|
|
332
|
+
# if self.log_scale:
|
|
333
|
+
# self.max_clause_output.prepared_call(
|
|
334
|
+
# self.grid,
|
|
335
|
+
# self.block,
|
|
336
|
+
# np.int32(self.number_of_outputs),
|
|
337
|
+
# self.hierarchy_votes[self.depth-1],
|
|
338
|
+
# self.clause_output_max_gpu
|
|
339
|
+
# )
|
|
342
340
|
|
|
343
341
|
# Adds up the votes from each clause (hierarchy root)
|
|
344
342
|
self.evaluate_final.prepared_call(
|
|
@@ -346,23 +344,20 @@ class CommonTsetlinMachine():
|
|
|
346
344
|
self.block,
|
|
347
345
|
np.int32(self.number_of_outputs),
|
|
348
346
|
self.hierarchy_votes[self.depth-1],
|
|
349
|
-
self.clause_output_max_gpu,
|
|
350
347
|
self.clause_weights_gpu,
|
|
351
348
|
self.class_sum_gpu
|
|
352
349
|
)
|
|
353
|
-
cuda.Context.synchronize()
|
|
354
350
|
|
|
355
|
-
if self.log_scale:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
cuda.Context.synchronize()
|
|
351
|
+
# if self.log_scale:
|
|
352
|
+
# self.rescale_final.prepared_call(
|
|
353
|
+
# self.grid,
|
|
354
|
+
# self.block,
|
|
355
|
+
# np.int32(self.number_of_outputs),
|
|
356
|
+
# self.clause_output_max_gpu,
|
|
357
|
+
# self.class_sum_gpu
|
|
358
|
+
# )
|
|
364
359
|
|
|
365
|
-
def _fit(self, X, encoded_Y
|
|
360
|
+
def _fit(self, X, encoded_Y):
|
|
366
361
|
if self.number_of_features_hierarchy != X.shape[1]:
|
|
367
362
|
print("The number of features spanned by hierarchy does not align with the input data.")
|
|
368
363
|
sys.exit(-1)
|
|
@@ -376,10 +371,7 @@ class CommonTsetlinMachine():
|
|
|
376
371
|
self.initialize_weights_and_ta_states()
|
|
377
372
|
|
|
378
373
|
self.first = False
|
|
379
|
-
|
|
380
|
-
# Re-initializes weights and Tsetlin automata states if training is not incremental
|
|
381
|
-
self.initialize_weights_and_ta_states()
|
|
382
|
-
|
|
374
|
+
|
|
383
375
|
# Allocates GPU memory for training data
|
|
384
376
|
encoded_X_hierarchy_training_gpu = cuda.mem_alloc(int(number_of_examples * self.number_of_literal_chunks * 4))
|
|
385
377
|
Y_gpu = cuda.mem_alloc(encoded_Y.nbytes)
|
|
@@ -387,69 +379,64 @@ class CommonTsetlinMachine():
|
|
|
387
379
|
self.encode_X(X, encoded_X_hierarchy_training_gpu)
|
|
388
380
|
cuda.memcpy_htod(Y_gpu, encoded_Y)
|
|
389
381
|
|
|
390
|
-
for
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
self.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
self.
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
self.
|
|
382
|
+
for e in range(number_of_examples):
|
|
383
|
+
self.evaluate_hierarchy(encoded_X_hierarchy_training_gpu, e)
|
|
384
|
+
|
|
385
|
+
# Propagates the root value and any intermittent node values back to the leaves.
|
|
386
|
+
# The purpose is to determine which leaves only has True nodes on the path from leaf to root.
|
|
387
|
+
for d in range(self.depth-1, 0, -1):
|
|
388
|
+
if self.hierarchy_structure[d][0] != OR_GROUP:
|
|
389
|
+
self.propagate_and_group_false_truth_values.prepared_call(
|
|
390
|
+
self.grid,
|
|
391
|
+
self.block,
|
|
392
|
+
self.hierarchy_votes[d-1],
|
|
393
|
+
self.hierarchy_votes[d],
|
|
394
|
+
self.hierarchy_size[d + 1],
|
|
395
|
+
self.hierarchy_structure[d][1]
|
|
396
|
+
)
|
|
397
|
+
else:
|
|
398
|
+
self.propagate_or_group_false_truth_values.prepared_call(
|
|
399
|
+
self.grid,
|
|
400
|
+
self.block,
|
|
401
|
+
self.cuda_rng.state,
|
|
402
|
+
self.hierarchy_votes[d-1],
|
|
403
|
+
self.hierarchy_votes[d],
|
|
404
|
+
self.hierarchy_size[d + 1],
|
|
405
|
+
self.hierarchy_structure[d][1]
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
# Updates the clause components (leaves) based on the propagated truth values
|
|
409
|
+
self.update_hierarchy.prepared_call(
|
|
410
|
+
self.grid,
|
|
411
|
+
self.block,
|
|
412
|
+
self.cuda_rng.state,
|
|
413
|
+
np.int32(self.number_of_outputs),
|
|
414
|
+
self.ta_state_hierarchy_gpu,
|
|
415
|
+
self.clause_weights_gpu,
|
|
416
|
+
self.hierarchy_votes[0],
|
|
417
|
+
self.depth,
|
|
418
|
+
self.hierarchy_structure_factors_gpu,
|
|
419
|
+
self.hierarchy_structure_type_gpu,
|
|
420
|
+
self.class_sum_gpu,
|
|
421
|
+
encoded_X_hierarchy_training_gpu,
|
|
422
|
+
Y_gpu,
|
|
423
|
+
np.int32(e)
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
# Updates the clause weights
|
|
427
|
+
if (self.tm_type in [WEIGHTED_TM, COALESCED_TM]):
|
|
428
|
+
self.update_weights.prepared_call(
|
|
421
429
|
self.grid,
|
|
422
430
|
self.block,
|
|
423
431
|
self.cuda_rng.state,
|
|
432
|
+
np.int32(self.tm_type),
|
|
424
433
|
np.int32(self.number_of_outputs),
|
|
425
|
-
self.ta_state_hierarchy_gpu,
|
|
426
434
|
self.clause_weights_gpu,
|
|
427
|
-
self.hierarchy_votes[
|
|
428
|
-
self.depth,
|
|
429
|
-
self.hierarchy_structure_factors_gpu,
|
|
430
|
-
self.hierarchy_structure_type_gpu,
|
|
435
|
+
self.hierarchy_votes[self.depth-1],
|
|
431
436
|
self.class_sum_gpu,
|
|
432
|
-
encoded_X_hierarchy_training_gpu,
|
|
433
437
|
Y_gpu,
|
|
434
438
|
np.int32(e)
|
|
435
439
|
)
|
|
436
|
-
cuda.Context.synchronize()
|
|
437
|
-
|
|
438
|
-
# Updates the clause weights
|
|
439
|
-
if (self.tm_type in [WEIGHTED_TM, COALESCED_TM]):
|
|
440
|
-
self.update_weights.prepared_call(
|
|
441
|
-
self.grid,
|
|
442
|
-
self.block,
|
|
443
|
-
self.cuda_rng.state,
|
|
444
|
-
np.int32(self.tm_type),
|
|
445
|
-
np.int32(self.number_of_outputs),
|
|
446
|
-
self.clause_weights_gpu,
|
|
447
|
-
self.hierarchy_votes[self.depth-1],
|
|
448
|
-
self.class_sum_gpu,
|
|
449
|
-
Y_gpu,
|
|
450
|
-
np.int32(e)
|
|
451
|
-
)
|
|
452
|
-
cuda.Context.synchronize()
|
|
453
440
|
return
|
|
454
441
|
|
|
455
442
|
def _score(self, X):
|
|
@@ -543,8 +530,8 @@ class CommonTsetlinMachine():
|
|
|
543
530
|
encoded_X_hierarchy_test_gpu = gpuarray.empty((number_of_examples, self.number_of_literal_chunks), dtype=np.uint32)
|
|
544
531
|
self.encode_X(X, encoded_X_hierarchy_test_gpu.gpudata)
|
|
545
532
|
|
|
546
|
-
class_sum = np.
|
|
547
|
-
class_sum_example = np.
|
|
533
|
+
class_sum = np.zeros((self.number_of_outputs, number_of_examples), dtype=np.float32)
|
|
534
|
+
class_sum_example = np.zeros(self.number_of_outputs, dtype=np.float32)
|
|
548
535
|
hierarchy_votes = []
|
|
549
536
|
for e in range(number_of_examples):
|
|
550
537
|
self.evaluate_hierarchy(encoded_X_hierarchy_test_gpu.gpudata, e)
|
|
@@ -554,7 +541,7 @@ class CommonTsetlinMachine():
|
|
|
554
541
|
|
|
555
542
|
hierarchy_votes_example = []
|
|
556
543
|
for d in range(self.depth):
|
|
557
|
-
temp_arr = np.
|
|
544
|
+
temp_arr = np.zeros(self.number_of_clauses*int(self.hierarchy_size[d+1]), dtype=np.float32)
|
|
558
545
|
cuda.memcpy_dtoh(temp_arr, self.hierarchy_votes[d])
|
|
559
546
|
hierarchy_votes_example.append(temp_arr.reshape((self.number_of_clauses, int(self.hierarchy_size[d+1]))))
|
|
560
547
|
|
|
@@ -581,7 +568,7 @@ class CommonTsetlinMachine():
|
|
|
581
568
|
depth_d_node_index = component_remainder % self.hierarchy_structure[d][1]
|
|
582
569
|
component_remainder = component_remainder // self.hierarchy_structure[d][1]
|
|
583
570
|
|
|
584
|
-
if self.hierarchy_structure[d][0] != OR_ALTERNATIVES:
|
|
571
|
+
if (self.hierarchy_structure[d][0] != OR_ALTERNATIVES) and (self.hierarchy_structure[d][0] != AND_ALTERNATIVES):
|
|
585
572
|
feature_base += size * depth_d_node_index
|
|
586
573
|
size *= self.hierarchy_structure[d][1];
|
|
587
574
|
|
|
@@ -591,7 +578,10 @@ class CommonTsetlinMachine():
|
|
|
591
578
|
right.append(")")
|
|
592
579
|
left.insert(0, "(")
|
|
593
580
|
elif previous_index[d-1] != depth_d_node_index:
|
|
594
|
-
|
|
581
|
+
if self.hierarchy_structure[d][0] in [AND_GROUP, AND_ALTERNATIVES]:
|
|
582
|
+
inside.append(" ∧ ")
|
|
583
|
+
elif self.hierarchy_structure[d][0] in [OR_GROUP, OR_ALTERNATIVES]:
|
|
584
|
+
inside.append(" ∨ ")
|
|
595
585
|
|
|
596
586
|
previous_index[d-1] = depth_d_node_index
|
|
597
587
|
|
|
@@ -607,7 +597,7 @@ class CommonTsetlinMachine():
|
|
|
607
597
|
l = []
|
|
608
598
|
for k in range(self.number_of_literals_per_leaf):
|
|
609
599
|
if self.ta_action(i, j, k):
|
|
610
|
-
if k < self.number_of_literals_per_leaf // 2:
|
|
600
|
+
if (not self.append_negated) or k < self.number_of_literals_per_leaf // 2:
|
|
611
601
|
if print_ta_state:
|
|
612
602
|
l.append("x%d(%d)" % (feature_base + k, self.ta_state(i, j, k)))
|
|
613
603
|
else:
|
|
@@ -672,7 +662,7 @@ class MultiOutputTsetlinMachine(CommonTsetlinMachine):
|
|
|
672
662
|
self.negative_clauses = 1
|
|
673
663
|
super().__init__(number_of_clauses, T, s, q=q, log_scale=log_scale, boost_true_positive_feedback=boost_true_positive_feedback, number_of_state_bits=number_of_state_bits, append_negated=append_negated, grid=grid, block=block, seed=seed)
|
|
674
664
|
|
|
675
|
-
def fit(self, X, Y
|
|
665
|
+
def fit(self, X, Y):
|
|
676
666
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
677
667
|
|
|
678
668
|
self.number_of_outputs = Y.shape[1]
|
|
@@ -682,7 +672,7 @@ class MultiOutputTsetlinMachine(CommonTsetlinMachine):
|
|
|
682
672
|
self.min_y = None
|
|
683
673
|
|
|
684
674
|
encoded_Y = np.where(Y == 1, self.T, -self.T).astype(np.int32)
|
|
685
|
-
self._fit(X, encoded_Y
|
|
675
|
+
self._fit(X, encoded_Y)
|
|
686
676
|
|
|
687
677
|
return
|
|
688
678
|
|
|
@@ -701,7 +691,7 @@ class MultiClassCoalescedTsetlinMachine(CommonTsetlinMachine):
|
|
|
701
691
|
|
|
702
692
|
super().__init__(number_of_clauses, T, s, q=q, log_scale=log_scale, hierarchy_structure=hierarchy_structure, boost_true_positive_feedback=boost_true_positive_feedback, number_of_state_bits=number_of_state_bits, append_negated=append_negated, grid=grid, block=block, seed=seed)
|
|
703
693
|
|
|
704
|
-
def fit(self, X, Y
|
|
694
|
+
def fit(self, X, Y):
|
|
705
695
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
706
696
|
|
|
707
697
|
self.number_of_outputs = int(np.max(Y) + 1)
|
|
@@ -714,7 +704,7 @@ class MultiClassCoalescedTsetlinMachine(CommonTsetlinMachine):
|
|
|
714
704
|
for i in range(self.number_of_outputs):
|
|
715
705
|
encoded_Y[:,i] = np.where(Y == i, self.T, -self.T)
|
|
716
706
|
|
|
717
|
-
self._fit(X, encoded_Y
|
|
707
|
+
self._fit(X, encoded_Y)
|
|
718
708
|
|
|
719
709
|
return
|
|
720
710
|
|
|
@@ -743,7 +733,7 @@ class MultiClassTsetlinMachine:
|
|
|
743
733
|
|
|
744
734
|
self.configured = False
|
|
745
735
|
|
|
746
|
-
def fit(self, X, Y
|
|
736
|
+
def fit(self, X, Y):
|
|
747
737
|
self.number_of_outputs = int(np.max(Y) + 1)
|
|
748
738
|
|
|
749
739
|
if not self.configured:
|
|
@@ -755,19 +745,18 @@ class MultiClassTsetlinMachine:
|
|
|
755
745
|
|
|
756
746
|
encoded_Y = np.empty(Y.shape[0], dtype = np.int32)
|
|
757
747
|
|
|
758
|
-
for
|
|
759
|
-
|
|
760
|
-
target_X = X[Y==i]
|
|
748
|
+
for i in range(self.number_of_outputs):
|
|
749
|
+
target_X = X[Y==i]
|
|
761
750
|
|
|
762
|
-
|
|
763
|
-
|
|
751
|
+
not_target_X = X[Y!=i]
|
|
752
|
+
not_target_index = np.random.rand(not_target_X.shape[0]) <= 1.0/(self.number_of_outputs - 1)
|
|
764
753
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
754
|
+
balanced_X = np.vstack((target_X, not_target_X[not_target_index,:]))
|
|
755
|
+
balanced_Y = np.hstack((np.ones(target_X.shape[0]), np.zeros(not_target_X.shape[0])))
|
|
756
|
+
index = np.arange(balanced_X.shape[0])
|
|
757
|
+
np.random.shuffle(index)
|
|
769
758
|
|
|
770
|
-
|
|
759
|
+
self.tms[i].fit(balanced_X[index], balanced_Y[index])
|
|
771
760
|
return
|
|
772
761
|
|
|
773
762
|
def score(self, X):
|
|
@@ -799,6 +788,11 @@ class MultiClassTsetlinMachine:
|
|
|
799
788
|
},
|
|
800
789
|
}
|
|
801
790
|
|
|
791
|
+
def print_hierarchy(self, print_ta_state=False):
|
|
792
|
+
for i in range(self.number_of_outputs):
|
|
793
|
+
print("CLASS %d\n", i)
|
|
794
|
+
self.tms[i].print_hierarchy(print_ta_state = print_ta_state)
|
|
795
|
+
|
|
802
796
|
def load(self, state_dict: dict):
|
|
803
797
|
self.number_of_outputs = state_dict['number_of_outputs']
|
|
804
798
|
|
|
@@ -822,7 +816,7 @@ class TsetlinMachine(CommonTsetlinMachine):
|
|
|
822
816
|
|
|
823
817
|
super().__init__(number_of_clauses, T, s, q=q, log_scale=log_scale, hierarchy_structure=hierarchy_structure, boost_true_positive_feedback=boost_true_positive_feedback, number_of_state_bits=number_of_state_bits, append_negated=append_negated, grid=grid, block=block, seed=seed)
|
|
824
818
|
|
|
825
|
-
def fit(self, X, Y
|
|
819
|
+
def fit(self, X, Y):
|
|
826
820
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
827
821
|
|
|
828
822
|
self.number_of_outputs = 1
|
|
@@ -832,7 +826,7 @@ class TsetlinMachine(CommonTsetlinMachine):
|
|
|
832
826
|
|
|
833
827
|
encoded_Y = np.where(Y == 1, self.T, -self.T).astype(np.int32)
|
|
834
828
|
|
|
835
|
-
self._fit(X, encoded_Y
|
|
829
|
+
self._fit(X, encoded_Y)
|
|
836
830
|
|
|
837
831
|
return
|
|
838
832
|
|
|
@@ -850,7 +844,7 @@ class RegressionTsetlinMachine(CommonTsetlinMachine):
|
|
|
850
844
|
|
|
851
845
|
super().__init__(number_of_clauses, T, s, log_scale=log_scale, hierarchy_structure=hierarchy_structure, boost_true_positive_feedback=boost_true_positive_feedback, number_of_state_bits=number_of_state_bits, append_negated=append_negated, grid=grid, block=block, seed=seed)
|
|
852
846
|
|
|
853
|
-
def fit(self, X, Y
|
|
847
|
+
def fit(self, X, Y):
|
|
854
848
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
855
849
|
|
|
856
850
|
self.number_of_outputs = 1
|
|
@@ -861,7 +855,7 @@ class RegressionTsetlinMachine(CommonTsetlinMachine):
|
|
|
861
855
|
|
|
862
856
|
encoded_Y = ((Y - self.min_y)/(self.max_y - self.min_y)*self.T).astype(np.int32)
|
|
863
857
|
|
|
864
|
-
self._fit(X, encoded_Y
|
|
858
|
+
self._fit(X, encoded_Y)
|
|
865
859
|
|
|
866
860
|
return
|
|
867
861
|
|
|
@@ -11,7 +11,7 @@ or
|
|
|
11
11
|
git clone git@github.com:cair/PyHierarchicalTsetlinMachineCUDA.git
|
|
12
12
|
cd PyHierarchicalTsetlinMachineCUDA
|
|
13
13
|
python ./setup.py sdist
|
|
14
|
-
pip install dist/PyHierarchicalTsetlinMachineCUDA-0.2.
|
|
14
|
+
pip install dist/PyHierarchicalTsetlinMachineCUDA-0.2.8.tar.gz
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Examples
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|