PyHierarchicalTsetlinMachineCUDA 0.2.8__tar.gz → 0.3.0__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.3.0}/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA/kernels.py +47 -394
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA/tm.py +139 -137
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA.egg-info/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/README.md +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/setup.py +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/LICENSE +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA/__init__.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA/tools.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA/utils.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA.egg-info/SOURCES.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA.egg-info/dependency_links.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA.egg-info/requires.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/PyHierarchicalTsetlinMachineCUDA.egg-info/top_level.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.8 → PyHierarchicalTsetlinMachineCUDA-0.3.0}/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,29 +316,12 @@ 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;
|
|
499
322
|
int stride = blockDim.x * gridDim.x;
|
|
500
323
|
|
|
501
|
-
int non_zero_children[
|
|
324
|
+
int non_zero_children[MAX_NUMBER_OF_OR_GROUP_CHILDREN];
|
|
502
325
|
|
|
503
326
|
/* Copy state to local memory for efficiency */
|
|
504
327
|
curandState localState = state[index];
|
|
@@ -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,10 +92,21 @@ 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
|
+
# Identifies the larget number of OR_GROUP children (for allocating local memory)
|
|
101
|
+
self.max_number_of_or_group_children = 0
|
|
102
|
+
for d in range(1, self.depth):
|
|
103
|
+
if self.hierarchy_structure[d][0] == OR_GROUP and self.max_number_of_or_group_children < self.hierarchy_structure[d][1]:
|
|
104
|
+
self.max_number_of_or_group_children = self.hierarchy_structure[d][1]
|
|
105
|
+
|
|
106
|
+
# Calculates number of literal chunks overall for the feature vector (ignores OR- and AND alternatives)
|
|
99
107
|
self.number_of_literal_chunks = self.number_of_literal_chunks_per_leaf
|
|
100
108
|
for d in range(self.depth - 1, 0, -1):
|
|
101
|
-
if (self.hierarchy_structure[d][0] == OR_GROUP or self.hierarchy_structure[d][0] == AND_GROUP):
|
|
109
|
+
if (self.hierarchy_structure[d][0] == OR_GROUP or self.hierarchy_structure[d][0] == AND_GROUP): # OR_GROUP and AND_GROUP join the features of their children
|
|
102
110
|
self.number_of_literal_chunks *= self.hierarchy_structure[d][1]
|
|
103
111
|
|
|
104
112
|
self.np_rng = np.random.default_rng(seed)
|
|
@@ -116,6 +124,7 @@ class CommonTsetlinMachine():
|
|
|
116
124
|
#define CLAUSES %d
|
|
117
125
|
#define DEPTH %d
|
|
118
126
|
#define COMPONENTS %d
|
|
127
|
+
#define TA_TEAMS %d
|
|
119
128
|
#define LITERALS_PER_LEAF %d
|
|
120
129
|
#define TA_CHUNKS_PER_LEAF %d
|
|
121
130
|
#define LITERAL_CHUNKS %d
|
|
@@ -126,9 +135,16 @@ class CommonTsetlinMachine():
|
|
|
126
135
|
#define Q %f
|
|
127
136
|
#define LOG_SCALE %d
|
|
128
137
|
|
|
138
|
+
#define AND_GROUP %d
|
|
139
|
+
#define AND_ALTERNATIVES %d
|
|
140
|
+
#define OR_GROUP %d
|
|
141
|
+
#define OR_ALTERNATIVES %d
|
|
142
|
+
|
|
143
|
+
#define MAX_NUMBER_OF_OR_GROUP_CHILDREN %d
|
|
144
|
+
|
|
129
145
|
#define NEGATIVE_CLAUSES %d
|
|
130
146
|
#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)
|
|
147
|
+
""" % (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.max_number_of_or_group_children, self.negative_clauses, self.flip_polarity)
|
|
132
148
|
|
|
133
149
|
mod_prepare = SourceModule(parameters + kernels.code_header + kernels.code_prepare, no_extern_c=True)
|
|
134
150
|
self.prepare_weights = mod_prepare.get_function("prepare_weights")
|
|
@@ -148,7 +164,7 @@ class CommonTsetlinMachine():
|
|
|
148
164
|
self.max_clause_output.prepare("iPP")
|
|
149
165
|
|
|
150
166
|
self.evaluate_final = mod_update.get_function("evaluate_final")
|
|
151
|
-
self.evaluate_final.prepare("
|
|
167
|
+
self.evaluate_final.prepare("iPPP")
|
|
152
168
|
|
|
153
169
|
self.rescale_final = mod_update.get_function("rescale_final")
|
|
154
170
|
self.rescale_final.prepare("iPP")
|
|
@@ -186,11 +202,9 @@ class CommonTsetlinMachine():
|
|
|
186
202
|
|
|
187
203
|
# Prepares for leaf encoding of the input data
|
|
188
204
|
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
205
|
|
|
191
206
|
# Encodes the input data split across the leaves
|
|
192
207
|
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
208
|
|
|
195
209
|
def allocate_gpu_memory(self):
|
|
196
210
|
# GPU memory for accumulating votes, level by level
|
|
@@ -209,7 +223,7 @@ class CommonTsetlinMachine():
|
|
|
209
223
|
cuda.memcpy_htod(self.hierarchy_structure_type_gpu, np.array(self.hierarchy_structure_type, dtype=np.int32))
|
|
210
224
|
|
|
211
225
|
# GPU memory for storing Tsetlin Automata states
|
|
212
|
-
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.
|
|
226
|
+
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
227
|
self.clause_weights_gpu = cuda.mem_alloc(self.number_of_outputs*self.number_of_clauses*4)
|
|
214
228
|
self.component_weights_gpu = cuda.mem_alloc(self.number_of_clauses*self.hierarchy_size[1]*4) # Only positive weights...
|
|
215
229
|
self.class_sum_gpu = cuda.mem_alloc(self.number_of_outputs*4)
|
|
@@ -218,16 +232,16 @@ class CommonTsetlinMachine():
|
|
|
218
232
|
self.clause_output_max = np.ascontiguousarray(np.empty(1)).astype(np.float32)
|
|
219
233
|
|
|
220
234
|
def ta_action(self, clause, leaf, ta):
|
|
221
|
-
ta_state_hierarchy = np.empty(self.number_of_clauses*self.
|
|
235
|
+
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
236
|
cuda.memcpy_dtoh(ta_state_hierarchy, self.ta_state_hierarchy_gpu)
|
|
223
|
-
ta_state_hierarchy = ta_state_hierarchy.reshape((self.number_of_clauses, self.
|
|
237
|
+
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
238
|
|
|
225
239
|
return (ta_state_hierarchy[clause, leaf, ta // 32, self.number_of_state_bits-1] & (1 << (ta % 32))) > 0
|
|
226
240
|
|
|
227
241
|
def ta_state(self, clause, leaf, ta):
|
|
228
|
-
ta_state_hierarchy = np.empty(self.number_of_clauses*self.
|
|
242
|
+
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
243
|
cuda.memcpy_dtoh(ta_state_hierarchy, self.ta_state_hierarchy_gpu)
|
|
230
|
-
ta_state_hierarchy = ta_state_hierarchy.reshape((self.number_of_clauses, self.
|
|
244
|
+
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
245
|
|
|
232
246
|
state = 0
|
|
233
247
|
for b in range(self.number_of_state_bits):
|
|
@@ -238,7 +252,7 @@ class CommonTsetlinMachine():
|
|
|
238
252
|
|
|
239
253
|
def get_state(self):
|
|
240
254
|
# To be updated
|
|
241
|
-
ta_state_hierarchy = np.empty(self.number_of_clauses*self.
|
|
255
|
+
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
256
|
cuda.memcpy_dtoh(self.ta_state_hierarchy, self.ta_state_hierarchy_gpu)
|
|
243
257
|
clause_weights = np.empty(self.number_of_outputs*self.number_of_clauses).astype(np.int32)
|
|
244
258
|
cuda.memcpy_dtoh(self.clause_weights, self.clause_weights_gpu)
|
|
@@ -255,7 +269,7 @@ class CommonTsetlinMachine():
|
|
|
255
269
|
self.min_y = state[8]
|
|
256
270
|
self.max_y = state[9]
|
|
257
271
|
|
|
258
|
-
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.
|
|
272
|
+
self.ta_state_hierarchy_gpu = cuda.mem_alloc(self.number_of_clauses*self.number_of_ta_teams*self.number_of_state_bits*4)
|
|
259
273
|
self.clause_weights_gpu = cuda.mem_alloc(self.number_of_outputs*self.number_of_clauses*4)
|
|
260
274
|
cuda.memcpy_htod(self.ta_state_hierarchy_gpu, state[0])
|
|
261
275
|
cuda.memcpy_htod(self.clause_weights_gpu, state[1])
|
|
@@ -265,15 +279,13 @@ class CommonTsetlinMachine():
|
|
|
265
279
|
None # To be updated
|
|
266
280
|
|
|
267
281
|
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()
|
|
282
|
+
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
283
|
|
|
271
|
-
self.prepare_hierarchy(
|
|
272
|
-
cuda.Context.synchronize()
|
|
284
|
+
self.prepare_hierarchy(np.int32(self.number_of_outputs), self.ta_state_hierarchy_gpu, grid=self.grid, block=self.block)
|
|
273
285
|
|
|
274
286
|
def evaluate_hierarchy(self, encoded_X_hierarchy, e):
|
|
275
287
|
# Initializes class sums to zero
|
|
276
|
-
class_sum = np.
|
|
288
|
+
class_sum = np.zeros(self.number_of_outputs, dtype=np.float32)
|
|
277
289
|
cuda.memcpy_htod(self.class_sum_gpu, class_sum)
|
|
278
290
|
|
|
279
291
|
# Evaluates all the hierarchy leaves in parallel
|
|
@@ -289,11 +301,10 @@ class CommonTsetlinMachine():
|
|
|
289
301
|
encoded_X_hierarchy,
|
|
290
302
|
np.int32(e)
|
|
291
303
|
)
|
|
292
|
-
cuda.Context.synchronize()
|
|
293
304
|
|
|
294
305
|
# Propagates votes bottom-up in the hierarchy, starting from the clause components (leaves)
|
|
295
306
|
for d in range(1, self.depth):
|
|
296
|
-
if (self.hierarchy_structure[d][0] == AND_GROUP):
|
|
307
|
+
if (self.hierarchy_structure[d][0] == AND_GROUP or self.hierarchy_structure[d][0] == AND_ALTERNATIVES):
|
|
297
308
|
self.evaluate_and_groups.prepared_call(
|
|
298
309
|
self.grid,
|
|
299
310
|
self.block,
|
|
@@ -302,7 +313,6 @@ class CommonTsetlinMachine():
|
|
|
302
313
|
self.hierarchy_size[d + 1],
|
|
303
314
|
self.hierarchy_structure[d][1]
|
|
304
315
|
)
|
|
305
|
-
cuda.Context.synchronize()
|
|
306
316
|
elif self.hierarchy_structure[d][0] == OR_GROUP:
|
|
307
317
|
self.evaluate_or_groups.prepared_call(
|
|
308
318
|
self.grid,
|
|
@@ -312,7 +322,6 @@ class CommonTsetlinMachine():
|
|
|
312
322
|
self.hierarchy_size[d + 1],
|
|
313
323
|
self.hierarchy_structure[d][1]
|
|
314
324
|
)
|
|
315
|
-
cuda.Context.synchronize()
|
|
316
325
|
elif self.hierarchy_structure[d][0] == OR_ALTERNATIVES:
|
|
317
326
|
self.evaluate_or_alternatives.prepared_call(
|
|
318
327
|
self.grid,
|
|
@@ -322,23 +331,20 @@ class CommonTsetlinMachine():
|
|
|
322
331
|
self.hierarchy_size[d + 1],
|
|
323
332
|
self.hierarchy_structure[d][1]
|
|
324
333
|
)
|
|
325
|
-
cuda.Context.synchronize()
|
|
326
334
|
else:
|
|
327
|
-
|
|
328
|
-
sys.exit()
|
|
335
|
+
raise ValueError("Unknown Node Type!")
|
|
329
336
|
|
|
330
337
|
self.clause_output_max[:] = np.finfo(np.float32).min
|
|
331
338
|
cuda.memcpy_htod(self.clause_output_max_gpu, self.clause_output_max)
|
|
332
339
|
|
|
333
|
-
if self.log_scale:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
cuda.Context.synchronize()
|
|
340
|
+
# if self.log_scale:
|
|
341
|
+
# self.max_clause_output.prepared_call(
|
|
342
|
+
# self.grid,
|
|
343
|
+
# self.block,
|
|
344
|
+
# np.int32(self.number_of_outputs),
|
|
345
|
+
# self.hierarchy_votes[self.depth-1],
|
|
346
|
+
# self.clause_output_max_gpu
|
|
347
|
+
# )
|
|
342
348
|
|
|
343
349
|
# Adds up the votes from each clause (hierarchy root)
|
|
344
350
|
self.evaluate_final.prepared_call(
|
|
@@ -346,23 +352,20 @@ class CommonTsetlinMachine():
|
|
|
346
352
|
self.block,
|
|
347
353
|
np.int32(self.number_of_outputs),
|
|
348
354
|
self.hierarchy_votes[self.depth-1],
|
|
349
|
-
self.clause_output_max_gpu,
|
|
350
355
|
self.clause_weights_gpu,
|
|
351
356
|
self.class_sum_gpu
|
|
352
357
|
)
|
|
353
|
-
cuda.Context.synchronize()
|
|
354
358
|
|
|
355
|
-
if self.log_scale:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
cuda.Context.synchronize()
|
|
359
|
+
# if self.log_scale:
|
|
360
|
+
# self.rescale_final.prepared_call(
|
|
361
|
+
# self.grid,
|
|
362
|
+
# self.block,
|
|
363
|
+
# np.int32(self.number_of_outputs),
|
|
364
|
+
# self.clause_output_max_gpu,
|
|
365
|
+
# self.class_sum_gpu
|
|
366
|
+
# )
|
|
364
367
|
|
|
365
|
-
def _fit(self, X, encoded_Y
|
|
368
|
+
def _fit(self, X, encoded_Y):
|
|
366
369
|
if self.number_of_features_hierarchy != X.shape[1]:
|
|
367
370
|
print("The number of features spanned by hierarchy does not align with the input data.")
|
|
368
371
|
sys.exit(-1)
|
|
@@ -376,10 +379,7 @@ class CommonTsetlinMachine():
|
|
|
376
379
|
self.initialize_weights_and_ta_states()
|
|
377
380
|
|
|
378
381
|
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
|
-
|
|
382
|
+
|
|
383
383
|
# Allocates GPU memory for training data
|
|
384
384
|
encoded_X_hierarchy_training_gpu = cuda.mem_alloc(int(number_of_examples * self.number_of_literal_chunks * 4))
|
|
385
385
|
Y_gpu = cuda.mem_alloc(encoded_Y.nbytes)
|
|
@@ -387,69 +387,64 @@ class CommonTsetlinMachine():
|
|
|
387
387
|
self.encode_X(X, encoded_X_hierarchy_training_gpu)
|
|
388
388
|
cuda.memcpy_htod(Y_gpu, encoded_Y)
|
|
389
389
|
|
|
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.
|
|
390
|
+
for e in range(number_of_examples):
|
|
391
|
+
self.evaluate_hierarchy(encoded_X_hierarchy_training_gpu, e)
|
|
392
|
+
|
|
393
|
+
# Propagates the root value and any intermittent node values back to the leaves.
|
|
394
|
+
# The purpose is to determine which leaves only has True nodes on the path from leaf to root.
|
|
395
|
+
for d in range(self.depth-1, 0, -1):
|
|
396
|
+
if self.hierarchy_structure[d][0] != OR_GROUP:
|
|
397
|
+
self.propagate_and_group_false_truth_values.prepared_call(
|
|
398
|
+
self.grid,
|
|
399
|
+
self.block,
|
|
400
|
+
self.hierarchy_votes[d-1],
|
|
401
|
+
self.hierarchy_votes[d],
|
|
402
|
+
self.hierarchy_size[d + 1],
|
|
403
|
+
self.hierarchy_structure[d][1]
|
|
404
|
+
)
|
|
405
|
+
else:
|
|
406
|
+
self.propagate_or_group_false_truth_values.prepared_call(
|
|
407
|
+
self.grid,
|
|
408
|
+
self.block,
|
|
409
|
+
self.cuda_rng.state,
|
|
410
|
+
self.hierarchy_votes[d-1],
|
|
411
|
+
self.hierarchy_votes[d],
|
|
412
|
+
self.hierarchy_size[d + 1],
|
|
413
|
+
self.hierarchy_structure[d][1]
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
# Updates the clause components (leaves) based on the propagated truth values
|
|
417
|
+
self.update_hierarchy.prepared_call(
|
|
418
|
+
self.grid,
|
|
419
|
+
self.block,
|
|
420
|
+
self.cuda_rng.state,
|
|
421
|
+
np.int32(self.number_of_outputs),
|
|
422
|
+
self.ta_state_hierarchy_gpu,
|
|
423
|
+
self.clause_weights_gpu,
|
|
424
|
+
self.hierarchy_votes[0],
|
|
425
|
+
self.depth,
|
|
426
|
+
self.hierarchy_structure_factors_gpu,
|
|
427
|
+
self.hierarchy_structure_type_gpu,
|
|
428
|
+
self.class_sum_gpu,
|
|
429
|
+
encoded_X_hierarchy_training_gpu,
|
|
430
|
+
Y_gpu,
|
|
431
|
+
np.int32(e)
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
# Updates the clause weights
|
|
435
|
+
if (self.tm_type in [WEIGHTED_TM, COALESCED_TM]):
|
|
436
|
+
self.update_weights.prepared_call(
|
|
421
437
|
self.grid,
|
|
422
438
|
self.block,
|
|
423
439
|
self.cuda_rng.state,
|
|
440
|
+
np.int32(self.tm_type),
|
|
424
441
|
np.int32(self.number_of_outputs),
|
|
425
|
-
self.ta_state_hierarchy_gpu,
|
|
426
442
|
self.clause_weights_gpu,
|
|
427
|
-
self.hierarchy_votes[
|
|
428
|
-
self.depth,
|
|
429
|
-
self.hierarchy_structure_factors_gpu,
|
|
430
|
-
self.hierarchy_structure_type_gpu,
|
|
443
|
+
self.hierarchy_votes[self.depth-1],
|
|
431
444
|
self.class_sum_gpu,
|
|
432
|
-
encoded_X_hierarchy_training_gpu,
|
|
433
445
|
Y_gpu,
|
|
434
446
|
np.int32(e)
|
|
435
447
|
)
|
|
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
448
|
return
|
|
454
449
|
|
|
455
450
|
def _score(self, X):
|
|
@@ -543,8 +538,8 @@ class CommonTsetlinMachine():
|
|
|
543
538
|
encoded_X_hierarchy_test_gpu = gpuarray.empty((number_of_examples, self.number_of_literal_chunks), dtype=np.uint32)
|
|
544
539
|
self.encode_X(X, encoded_X_hierarchy_test_gpu.gpudata)
|
|
545
540
|
|
|
546
|
-
class_sum = np.
|
|
547
|
-
class_sum_example = np.
|
|
541
|
+
class_sum = np.zeros((self.number_of_outputs, number_of_examples), dtype=np.float32)
|
|
542
|
+
class_sum_example = np.zeros(self.number_of_outputs, dtype=np.float32)
|
|
548
543
|
hierarchy_votes = []
|
|
549
544
|
for e in range(number_of_examples):
|
|
550
545
|
self.evaluate_hierarchy(encoded_X_hierarchy_test_gpu.gpudata, e)
|
|
@@ -554,7 +549,7 @@ class CommonTsetlinMachine():
|
|
|
554
549
|
|
|
555
550
|
hierarchy_votes_example = []
|
|
556
551
|
for d in range(self.depth):
|
|
557
|
-
temp_arr = np.
|
|
552
|
+
temp_arr = np.zeros(self.number_of_clauses*int(self.hierarchy_size[d+1]), dtype=np.float32)
|
|
558
553
|
cuda.memcpy_dtoh(temp_arr, self.hierarchy_votes[d])
|
|
559
554
|
hierarchy_votes_example.append(temp_arr.reshape((self.number_of_clauses, int(self.hierarchy_size[d+1]))))
|
|
560
555
|
|
|
@@ -581,7 +576,7 @@ class CommonTsetlinMachine():
|
|
|
581
576
|
depth_d_node_index = component_remainder % self.hierarchy_structure[d][1]
|
|
582
577
|
component_remainder = component_remainder // self.hierarchy_structure[d][1]
|
|
583
578
|
|
|
584
|
-
if self.hierarchy_structure[d][0] != OR_ALTERNATIVES:
|
|
579
|
+
if (self.hierarchy_structure[d][0] != OR_ALTERNATIVES) and (self.hierarchy_structure[d][0] != AND_ALTERNATIVES):
|
|
585
580
|
feature_base += size * depth_d_node_index
|
|
586
581
|
size *= self.hierarchy_structure[d][1];
|
|
587
582
|
|
|
@@ -591,7 +586,10 @@ class CommonTsetlinMachine():
|
|
|
591
586
|
right.append(")")
|
|
592
587
|
left.insert(0, "(")
|
|
593
588
|
elif previous_index[d-1] != depth_d_node_index:
|
|
594
|
-
|
|
589
|
+
if self.hierarchy_structure[d][0] in [AND_GROUP, AND_ALTERNATIVES]:
|
|
590
|
+
inside.append(" ∧ ")
|
|
591
|
+
elif self.hierarchy_structure[d][0] in [OR_GROUP, OR_ALTERNATIVES]:
|
|
592
|
+
inside.append(" ∨ ")
|
|
595
593
|
|
|
596
594
|
previous_index[d-1] = depth_d_node_index
|
|
597
595
|
|
|
@@ -607,7 +605,7 @@ class CommonTsetlinMachine():
|
|
|
607
605
|
l = []
|
|
608
606
|
for k in range(self.number_of_literals_per_leaf):
|
|
609
607
|
if self.ta_action(i, j, k):
|
|
610
|
-
if k < self.number_of_literals_per_leaf // 2:
|
|
608
|
+
if (not self.append_negated) or k < self.number_of_literals_per_leaf // 2:
|
|
611
609
|
if print_ta_state:
|
|
612
610
|
l.append("x%d(%d)" % (feature_base + k, self.ta_state(i, j, k)))
|
|
613
611
|
else:
|
|
@@ -672,7 +670,7 @@ class MultiOutputTsetlinMachine(CommonTsetlinMachine):
|
|
|
672
670
|
self.negative_clauses = 1
|
|
673
671
|
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
672
|
|
|
675
|
-
def fit(self, X, Y
|
|
673
|
+
def fit(self, X, Y):
|
|
676
674
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
677
675
|
|
|
678
676
|
self.number_of_outputs = Y.shape[1]
|
|
@@ -682,7 +680,7 @@ class MultiOutputTsetlinMachine(CommonTsetlinMachine):
|
|
|
682
680
|
self.min_y = None
|
|
683
681
|
|
|
684
682
|
encoded_Y = np.where(Y == 1, self.T, -self.T).astype(np.int32)
|
|
685
|
-
self._fit(X, encoded_Y
|
|
683
|
+
self._fit(X, encoded_Y)
|
|
686
684
|
|
|
687
685
|
return
|
|
688
686
|
|
|
@@ -701,7 +699,7 @@ class MultiClassCoalescedTsetlinMachine(CommonTsetlinMachine):
|
|
|
701
699
|
|
|
702
700
|
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
701
|
|
|
704
|
-
def fit(self, X, Y
|
|
702
|
+
def fit(self, X, Y):
|
|
705
703
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
706
704
|
|
|
707
705
|
self.number_of_outputs = int(np.max(Y) + 1)
|
|
@@ -714,7 +712,7 @@ class MultiClassCoalescedTsetlinMachine(CommonTsetlinMachine):
|
|
|
714
712
|
for i in range(self.number_of_outputs):
|
|
715
713
|
encoded_Y[:,i] = np.where(Y == i, self.T, -self.T)
|
|
716
714
|
|
|
717
|
-
self._fit(X, encoded_Y
|
|
715
|
+
self._fit(X, encoded_Y)
|
|
718
716
|
|
|
719
717
|
return
|
|
720
718
|
|
|
@@ -743,7 +741,7 @@ class MultiClassTsetlinMachine:
|
|
|
743
741
|
|
|
744
742
|
self.configured = False
|
|
745
743
|
|
|
746
|
-
def fit(self, X, Y
|
|
744
|
+
def fit(self, X, Y):
|
|
747
745
|
self.number_of_outputs = int(np.max(Y) + 1)
|
|
748
746
|
|
|
749
747
|
if not self.configured:
|
|
@@ -755,19 +753,18 @@ class MultiClassTsetlinMachine:
|
|
|
755
753
|
|
|
756
754
|
encoded_Y = np.empty(Y.shape[0], dtype = np.int32)
|
|
757
755
|
|
|
758
|
-
for
|
|
759
|
-
|
|
760
|
-
target_X = X[Y==i]
|
|
756
|
+
for i in range(self.number_of_outputs):
|
|
757
|
+
target_X = X[Y==i]
|
|
761
758
|
|
|
762
|
-
|
|
763
|
-
|
|
759
|
+
not_target_X = X[Y!=i]
|
|
760
|
+
not_target_index = np.random.rand(not_target_X.shape[0]) <= 1.0/(self.number_of_outputs - 1)
|
|
764
761
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
762
|
+
balanced_X = np.vstack((target_X, not_target_X[not_target_index,:]))
|
|
763
|
+
balanced_Y = np.hstack((np.ones(target_X.shape[0]), np.zeros(not_target_X.shape[0])))
|
|
764
|
+
index = np.arange(balanced_X.shape[0])
|
|
765
|
+
np.random.shuffle(index)
|
|
769
766
|
|
|
770
|
-
|
|
767
|
+
self.tms[i].fit(balanced_X[index], balanced_Y[index])
|
|
771
768
|
return
|
|
772
769
|
|
|
773
770
|
def score(self, X):
|
|
@@ -799,6 +796,11 @@ class MultiClassTsetlinMachine:
|
|
|
799
796
|
},
|
|
800
797
|
}
|
|
801
798
|
|
|
799
|
+
def print_hierarchy(self, print_ta_state=False):
|
|
800
|
+
for i in range(self.number_of_outputs):
|
|
801
|
+
print("CLASS %d\n", i)
|
|
802
|
+
self.tms[i].print_hierarchy(print_ta_state = print_ta_state)
|
|
803
|
+
|
|
802
804
|
def load(self, state_dict: dict):
|
|
803
805
|
self.number_of_outputs = state_dict['number_of_outputs']
|
|
804
806
|
|
|
@@ -822,7 +824,7 @@ class TsetlinMachine(CommonTsetlinMachine):
|
|
|
822
824
|
|
|
823
825
|
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
826
|
|
|
825
|
-
def fit(self, X, Y
|
|
827
|
+
def fit(self, X, Y):
|
|
826
828
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
827
829
|
|
|
828
830
|
self.number_of_outputs = 1
|
|
@@ -832,7 +834,7 @@ class TsetlinMachine(CommonTsetlinMachine):
|
|
|
832
834
|
|
|
833
835
|
encoded_Y = np.where(Y == 1, self.T, -self.T).astype(np.int32)
|
|
834
836
|
|
|
835
|
-
self._fit(X, encoded_Y
|
|
837
|
+
self._fit(X, encoded_Y)
|
|
836
838
|
|
|
837
839
|
return
|
|
838
840
|
|
|
@@ -850,7 +852,7 @@ class RegressionTsetlinMachine(CommonTsetlinMachine):
|
|
|
850
852
|
|
|
851
853
|
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
854
|
|
|
853
|
-
def fit(self, X, Y
|
|
855
|
+
def fit(self, X, Y):
|
|
854
856
|
X = X.reshape(X.shape[0], X.shape[1], 1)
|
|
855
857
|
|
|
856
858
|
self.number_of_outputs = 1
|
|
@@ -861,7 +863,7 @@ class RegressionTsetlinMachine(CommonTsetlinMachine):
|
|
|
861
863
|
|
|
862
864
|
encoded_Y = ((Y - self.min_y)/(self.max_y - self.min_y)*self.T).astype(np.int32)
|
|
863
865
|
|
|
864
|
-
self._fit(X, encoded_Y
|
|
866
|
+
self._fit(X, encoded_Y)
|
|
865
867
|
|
|
866
868
|
return
|
|
867
869
|
|
|
@@ -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
|