PyHierarchicalTsetlinMachineCUDA 0.2.7__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.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/kernels.py +234 -108
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/tm.py +165 -134
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/PKG-INFO +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/README.md +2 -2
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/setup.py +1 -1
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/LICENSE +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/__init__.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/tools.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/utils.py +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/SOURCES.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/dependency_links.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/requires.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/top_level.txt +0 -0
- {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/setup.cfg +0 -0
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
code_header = """
|
|
22
22
|
#include <curand_kernel.h>
|
|
23
23
|
|
|
24
|
+
#define NEG_INFINITY (-1 * INFINITY)
|
|
25
|
+
|
|
24
26
|
#define INT_SIZE 32ULL
|
|
25
27
|
|
|
26
28
|
#if (LITERALS_PER_LEAF % 32 != 0)
|
|
@@ -82,7 +84,7 @@ code_update = """
|
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
__device__ inline void update_clause_weight(curandState *localState, int tm_type, int number_of_outputs, int *clause_weight, int clause_output, int y,
|
|
87
|
+
__device__ inline void update_clause_weight(curandState *localState, int tm_type, int number_of_outputs, int *clause_weight, int clause_output, int y, float class_sum)
|
|
86
88
|
{
|
|
87
89
|
int target = 1 - 2*(class_sum > y);
|
|
88
90
|
|
|
@@ -92,7 +94,7 @@ code_update = """
|
|
|
92
94
|
|
|
93
95
|
int sign = (*clause_weight >= 0) - (*clause_weight < 0);
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
float absolute_prediction_error = fabsf(y - class_sum);
|
|
96
98
|
if (curand_uniform(localState) <= 1.0*absolute_prediction_error/(2*THRESHOLD)) {
|
|
97
99
|
if (target*sign > 0) {
|
|
98
100
|
if (clause_output && abs(*clause_weight) < INT_MAX) {
|
|
@@ -112,18 +114,17 @@ code_update = """
|
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
116
|
|
|
115
|
-
__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,
|
|
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)
|
|
116
118
|
{
|
|
117
119
|
int target = 1 - 2*(class_sum > y);
|
|
118
|
-
|
|
120
|
+
|
|
119
121
|
if (target == -1 && curand_uniform(localState) > 1.0*Q/max(1, number_of_outputs-1)) {
|
|
120
122
|
return;
|
|
121
123
|
}
|
|
122
|
-
|
|
123
124
|
|
|
124
125
|
int sign = (*clause_weight >= 0) - (*clause_weight < 0);
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
float absolute_prediction_error = fabsf(y - class_sum);
|
|
127
128
|
if (curand_uniform(localState) <= 1.0*absolute_prediction_error/(2*THRESHOLD)) {
|
|
128
129
|
if (target*sign > 0) {
|
|
129
130
|
// Type I Feedback
|
|
@@ -159,7 +160,7 @@ code_update = """
|
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
// Evaluate example
|
|
162
|
-
__global__ void evaluate_leaves(unsigned int *global_ta_state, int *component_weights,
|
|
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)
|
|
163
164
|
{
|
|
164
165
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
165
166
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -177,42 +178,59 @@ code_update = """
|
|
|
177
178
|
int size_feature_chunk_base = 1;
|
|
178
179
|
int size_ta_chunk_base = 1;
|
|
179
180
|
for (int d = 0; d < depth-1; ++d) {
|
|
180
|
-
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
181
|
-
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
|
|
182
183
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
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
|
|
186
188
|
}
|
|
187
189
|
|
|
188
|
-
|
|
190
|
+
// Support reuse of the same Tsetlin Automata when doing OR to group different feature chunks
|
|
191
|
+
if (hierarchy_structure_type[d] != OR_GROUP) {
|
|
189
192
|
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
190
193
|
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
191
194
|
}
|
|
192
195
|
}
|
|
193
196
|
|
|
194
197
|
// Get state of current ta team component
|
|
195
|
-
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];
|
|
196
199
|
|
|
197
200
|
// Evaluate clause component
|
|
198
|
-
|
|
201
|
+
|
|
202
|
+
#if LOG_SCALE == 1
|
|
203
|
+
float component_output = 0;
|
|
204
|
+
#else
|
|
205
|
+
float component_output = 1;
|
|
206
|
+
#endif
|
|
207
|
+
|
|
199
208
|
for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF-1; ++ta_chunk) {
|
|
200
209
|
// Compare the TA state of the component (leaf) against the corresponding part of the feature vector
|
|
201
210
|
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]) {
|
|
202
|
-
|
|
211
|
+
#if LOG_SCALE == 1
|
|
212
|
+
component_output = NEG_INFINITY;
|
|
213
|
+
#else
|
|
214
|
+
component_output = 0;
|
|
215
|
+
#endif
|
|
216
|
+
|
|
203
217
|
break;
|
|
204
218
|
}
|
|
205
219
|
}
|
|
206
220
|
|
|
207
221
|
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)) {
|
|
208
|
-
|
|
222
|
+
#if LOG_SCALE == 1
|
|
223
|
+
component_output = NEG_INFINITY;
|
|
224
|
+
#else
|
|
225
|
+
component_output = 0;
|
|
226
|
+
#endif
|
|
209
227
|
}
|
|
210
228
|
|
|
211
229
|
global_component_output[clause_component] = component_output;
|
|
212
230
|
}
|
|
213
231
|
}
|
|
214
232
|
|
|
215
|
-
__global__ void evaluate_or_groups(
|
|
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)
|
|
216
234
|
{
|
|
217
235
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
218
236
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -220,7 +238,7 @@ code_update = """
|
|
|
220
238
|
// Add up the votes of each OR node child
|
|
221
239
|
for (int or_group_node = index; or_group_node < CLAUSES*number_of_or_group_nodes; or_group_node += stride) {
|
|
222
240
|
// Add OR addends
|
|
223
|
-
|
|
241
|
+
|
|
224
242
|
int max_vote_sum = 0;
|
|
225
243
|
|
|
226
244
|
for (int or_addend = 0; or_addend < number_of_or_group_addends; ++or_addend) {
|
|
@@ -229,21 +247,13 @@ code_update = """
|
|
|
229
247
|
if (child_input[or_group_node*number_of_or_group_addends + or_addend] > max_vote_sum) {
|
|
230
248
|
max_vote_sum = child_input[or_group_node*number_of_or_group_addends + or_addend];
|
|
231
249
|
}
|
|
232
|
-
|
|
233
|
-
int previous_or_group_vote_sum = or_group_vote_sum;
|
|
234
|
-
or_group_vote_sum += child_input[or_group_node*number_of_or_group_addends + or_addend];
|
|
235
|
-
if (or_group_vote_sum < 0) {
|
|
236
|
-
printf("OR* OVERFLOW %d -> %d\\n", previous_or_group_vote_sum, or_group_vote_sum);
|
|
237
|
-
or_group_vote_sum = previous_or_group_vote_sum;
|
|
238
|
-
}
|
|
239
250
|
}
|
|
240
251
|
|
|
241
|
-
//or_group_node_output[or_group_node] = or_group_vote_sum;
|
|
242
252
|
or_group_node_output[or_group_node] = max_vote_sum;
|
|
243
253
|
}
|
|
244
254
|
}
|
|
245
255
|
|
|
246
|
-
__global__ void evaluate_and_groups(
|
|
256
|
+
__global__ void evaluate_and_groups(float *child_input, float *and_group_node_output, int number_of_and_group_nodes, int number_of_and_group_factors)
|
|
247
257
|
{
|
|
248
258
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
249
259
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -251,48 +261,62 @@ code_update = """
|
|
|
251
261
|
// Multiply the votes from the children of each AND node
|
|
252
262
|
for (int and_group_node = index; and_group_node < CLAUSES*number_of_and_group_nodes; and_group_node += stride) {
|
|
253
263
|
// Multiply and factors
|
|
254
|
-
|
|
255
|
-
|
|
264
|
+
|
|
265
|
+
#if LOG_SCALE == 1
|
|
266
|
+
float and_group_vote_product = 0;
|
|
267
|
+
#else
|
|
268
|
+
float and_group_vote_product = 1;
|
|
269
|
+
#endif
|
|
270
|
+
|
|
256
271
|
for (int and_factor = 0; and_factor < number_of_and_group_factors; ++and_factor) {
|
|
257
272
|
// Aggregate votes from each child node through multiplication
|
|
258
273
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (and_group_vote_product < 0) {
|
|
267
|
-
printf("AND OVERFLOW %d -> %d\\n", previous_and_group_vote_product, and_group_vote_product);
|
|
268
|
-
and_group_vote_product = previous_and_group_vote_product;
|
|
269
|
-
}
|
|
274
|
+
#if LOG_SCALE == 1
|
|
275
|
+
and_group_vote_product += child_input[and_group_node*number_of_and_group_factors + and_factor];
|
|
276
|
+
#else
|
|
277
|
+
and_group_vote_product *= child_input[and_group_node*number_of_and_group_factors + and_factor];
|
|
278
|
+
#endif
|
|
270
279
|
}
|
|
271
|
-
|
|
272
|
-
// Store and group product as node output
|
|
280
|
+
|
|
273
281
|
and_group_node_output[and_group_node] = and_group_vote_product;
|
|
274
|
-
//and_group_node_output[and_group_node] = max_vote_sum;
|
|
275
282
|
}
|
|
276
283
|
}
|
|
277
284
|
|
|
278
|
-
__global__ void propagate_and_group_false_truth_values(
|
|
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)
|
|
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)
|
|
279
287
|
{
|
|
280
288
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
281
289
|
int stride = blockDim.x * gridDim.x;
|
|
282
290
|
|
|
283
291
|
// If a group node is false, all children are made false.
|
|
284
292
|
for (int group_node = index; group_node < CLAUSES*number_of_group_nodes; group_node += stride) {
|
|
285
|
-
if
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
child_input[group_node*number_of_group_node_children + and_factor]
|
|
293
|
+
#if LOG_SCALE == 1
|
|
294
|
+
if (group_node_output[group_node] == NEG_INFINITY) {
|
|
295
|
+
for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
|
|
296
|
+
if (child_input[group_node*number_of_group_node_children + and_factor] >= 0) {
|
|
297
|
+
child_input[group_node*number_of_group_node_children + and_factor] = NEG_INFINITY;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
#else
|
|
302
|
+
if (group_node_output[group_node] == 0) {
|
|
303
|
+
for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
|
|
304
|
+
if (child_input[group_node*number_of_group_node_children + and_factor] > 0) {
|
|
305
|
+
child_input[group_node*number_of_group_node_children + and_factor] = 0;
|
|
306
|
+
}
|
|
289
307
|
}
|
|
290
308
|
}
|
|
309
|
+
#endif
|
|
310
|
+
|
|
311
|
+
if (group_node_output[group_node] == -1) {
|
|
312
|
+
for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
|
|
313
|
+
child_input[group_node*number_of_group_node_children + and_factor] = -1;
|
|
314
|
+
}
|
|
291
315
|
}
|
|
292
316
|
}
|
|
293
317
|
}
|
|
294
318
|
|
|
295
|
-
__global__ void propagate_or_group_false_truth_values(curandState *state,
|
|
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)
|
|
296
320
|
{
|
|
297
321
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
298
322
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -306,24 +330,45 @@ code_update = """
|
|
|
306
330
|
for (int group_node = index; group_node < CLAUSES*number_of_group_nodes; group_node += stride) {
|
|
307
331
|
int number_of_non_zero_children = 0;
|
|
308
332
|
|
|
309
|
-
if
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
child_input[group_node*number_of_group_node_children + or_addend]
|
|
333
|
+
#if LOG_SCALE == 1
|
|
334
|
+
if (group_node_output[group_node] == -1) {
|
|
335
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
336
|
+
child_input[group_node*number_of_group_node_children + or_addend] = -1;
|
|
337
|
+
}
|
|
338
|
+
} else if (group_node_output[group_node] == NEG_INFINITY) {
|
|
339
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
340
|
+
if (child_input[group_node*number_of_group_node_children + or_addend] >= 0) {
|
|
341
|
+
child_input[group_node*number_of_group_node_children + or_addend] = NEG_INFINITY;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
346
|
+
if (child_input[group_node*number_of_group_node_children + or_addend] >= 0) {
|
|
347
|
+
non_zero_children[number_of_non_zero_children] = or_addend;
|
|
348
|
+
number_of_non_zero_children++;
|
|
349
|
+
}
|
|
317
350
|
}
|
|
318
351
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
352
|
+
#else
|
|
353
|
+
if (group_node_output[group_node] == -1) {
|
|
354
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
355
|
+
child_input[group_node*number_of_group_node_children + or_addend] = -1;
|
|
356
|
+
}
|
|
357
|
+
} else if (group_node_output[group_node] == 0) {
|
|
358
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
359
|
+
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
|
|
360
|
+
child_input[group_node*number_of_group_node_children + or_addend] = 0;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
|
|
365
|
+
if (child_input[group_node*number_of_group_node_children + or_addend] > 0) { // Or pick the largest.... picking randomly when a tie
|
|
366
|
+
non_zero_children[number_of_non_zero_children] = or_addend;
|
|
367
|
+
number_of_non_zero_children++;
|
|
368
|
+
}
|
|
324
369
|
}
|
|
325
370
|
}
|
|
326
|
-
|
|
371
|
+
#endif
|
|
327
372
|
|
|
328
373
|
if (group_node_output[group_node] != -1) {
|
|
329
374
|
int selected_child;
|
|
@@ -344,51 +389,129 @@ code_update = """
|
|
|
344
389
|
state[index] = localState;
|
|
345
390
|
}
|
|
346
391
|
|
|
347
|
-
__global__ void evaluate_or_alternatives(
|
|
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)
|
|
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)
|
|
348
394
|
{
|
|
349
395
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
350
396
|
int stride = blockDim.x * gridDim.x;
|
|
351
397
|
|
|
352
398
|
// Add up the votes from the children of each OR node
|
|
353
399
|
for (int or_alternatives_node = index; or_alternatives_node < CLAUSES*number_of_or_alternatives_nodes; or_alternatives_node += stride) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
400
|
+
#if LOG_SCALE == 1
|
|
401
|
+
float or_alternatives_vote_max = NEG_INFINITY;
|
|
402
|
+
for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
|
|
403
|
+
if (child_input[or_alternatives_node * number_of_or_alternatives + or_alternative] > or_alternatives_vote_max) {
|
|
404
|
+
or_alternatives_vote_max = child_input[or_alternatives_node * number_of_or_alternatives + or_alternative];
|
|
405
|
+
}
|
|
406
|
+
}
|
|
359
407
|
|
|
360
|
-
|
|
361
|
-
|
|
408
|
+
if (or_alternatives_vote_max != NEG_INFINITY) {
|
|
409
|
+
// Sum up votes from each or alternative
|
|
410
|
+
float or_alternatives_vote_sum = 0;
|
|
411
|
+
for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
|
|
412
|
+
// Aggregates or alternatives through summation
|
|
413
|
+
|
|
414
|
+
or_alternatives_vote_sum += exp2f(child_input[or_alternatives_node * number_of_or_alternatives + or_alternative] - or_alternatives_vote_max);
|
|
415
|
+
}
|
|
362
416
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
417
|
+
// Store vote sum as node output
|
|
418
|
+
or_alternatives_node_output[or_alternatives_node] = or_alternatives_vote_max + log2f(or_alternatives_vote_sum);
|
|
419
|
+
} else {
|
|
420
|
+
or_alternatives_node_output[or_alternatives_node] = NEG_INFINITY;
|
|
421
|
+
}
|
|
422
|
+
#else
|
|
423
|
+
// Sum up votes from each or alternative
|
|
424
|
+
int or_alternatives_vote_sum = 0;
|
|
425
|
+
for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
|
|
426
|
+
// Aggregate same input or alternatives through summation
|
|
427
|
+
or_alternatives_vote_sum += child_input[or_alternatives_node * number_of_or_alternatives + or_alternative];
|
|
366
428
|
}
|
|
367
|
-
}
|
|
368
429
|
|
|
369
|
-
|
|
370
|
-
|
|
430
|
+
// Store vote sum as node output
|
|
431
|
+
or_alternatives_node_output[or_alternatives_node] = or_alternatives_vote_sum;
|
|
432
|
+
#endif
|
|
371
433
|
}
|
|
372
434
|
}
|
|
373
435
|
|
|
374
|
-
__global__ void
|
|
436
|
+
__global__ void max_clause_output(int number_of_outputs, float *clause_output, float *clause_output_max)
|
|
375
437
|
{
|
|
376
438
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
377
439
|
int stride = blockDim.x * gridDim.x;
|
|
378
440
|
|
|
379
441
|
// Add up the votes from each clause
|
|
380
442
|
for (int clause = index; clause < CLAUSES; clause += stride) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
443
|
+
atomicMax((int *)&clause_output_max[0], __float_as_int(clause_output[clause]));
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
__global__ void evaluate_final(int number_of_outputs, float *clause_output, int *clause_weights, float *class_sum)
|
|
448
|
+
{
|
|
449
|
+
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
450
|
+
int stride = blockDim.x * gridDim.x;
|
|
451
|
+
|
|
452
|
+
// Add up the votes from each clause
|
|
453
|
+
#if LOG_SCALE == 1
|
|
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);
|
|
474
|
+
}
|
|
475
|
+
} else {
|
|
476
|
+
class_sum[class_id] = 0;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
#else
|
|
480
|
+
for (int clause = index; clause < CLAUSES; clause += stride) {
|
|
481
|
+
if (clause_output[clause]) {
|
|
482
|
+
for (int class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
483
|
+
atomicAdd(&class_sum[class_id], (float) clause_weights[class_id*CLAUSES + clause] * clause_output[clause]);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
#endif
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
__global__ void rescale_final(int number_of_outputs, float *clause_output_max, float *class_sum)
|
|
491
|
+
{
|
|
492
|
+
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
493
|
+
int stride = blockDim.x * gridDim.x;
|
|
494
|
+
|
|
495
|
+
// Add up the votes from each clause
|
|
496
|
+
|
|
497
|
+
if (clause_output_max[0] > NEG_INFINITY) {
|
|
498
|
+
for (int class_id = index; class_id < number_of_outputs; class_id += stride) {
|
|
499
|
+
float rescaled_abs_class_sum = log2f(fabsf(class_sum[class_id])) + clause_output_max[0];
|
|
500
|
+
if (rescaled_abs_class_sum >= log2f(THRESHOLD)) {
|
|
501
|
+
if (class_sum[class_id] >= 0) {
|
|
502
|
+
class_sum[class_id] = THRESHOLD;
|
|
503
|
+
} else {
|
|
504
|
+
class_sum[class_id] = -1*THRESHOLD;
|
|
505
|
+
}
|
|
506
|
+
} else {
|
|
507
|
+
class_sum[class_id] = class_sum[class_id] * exp2f(clause_output_max[0]);
|
|
385
508
|
}
|
|
386
509
|
}
|
|
387
510
|
}
|
|
388
511
|
}
|
|
389
512
|
|
|
390
513
|
// Update state of Tsetlin Automata team
|
|
391
|
-
__global__ void update_hierarchy(curandState *state, int number_of_outputs, unsigned int *global_ta_state, int *clause_weights,
|
|
514
|
+
__global__ void update_hierarchy(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, float *class_sum, int *X, int *y, int example)
|
|
392
515
|
{
|
|
393
516
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
394
517
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -408,7 +531,6 @@ code_update = """
|
|
|
408
531
|
int component = clause_component % COMPONENTS;
|
|
409
532
|
|
|
410
533
|
// Get state of current clause component
|
|
411
|
-
// This one must be updated for reuse of TAs within OR group
|
|
412
534
|
|
|
413
535
|
int component_remainder = component;
|
|
414
536
|
int feature_chunk_base = 0;
|
|
@@ -419,29 +541,33 @@ code_update = """
|
|
|
419
541
|
int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
|
|
420
542
|
component_remainder = component_remainder / hierarchy_structure_factors[d];
|
|
421
543
|
|
|
422
|
-
if (hierarchy_structure_type[d] !=
|
|
544
|
+
if ((hierarchy_structure_type[d] != OR_ALTERNATIVES) && (hierarchy_structure_type[d] != AND_ALTERNATIVES)) {
|
|
423
545
|
feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
424
546
|
size_feature_chunk_base *= hierarchy_structure_factors[d];
|
|
425
547
|
}
|
|
426
548
|
|
|
427
|
-
if (hierarchy_structure_type[d] !=
|
|
549
|
+
if (hierarchy_structure_type[d] != OR_GROUP) {
|
|
428
550
|
ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
|
|
429
551
|
size_ta_chunk_base *= hierarchy_structure_factors[d];
|
|
430
552
|
}
|
|
431
553
|
}
|
|
432
554
|
|
|
433
555
|
// Get state of current ta team component
|
|
434
|
-
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];
|
|
435
557
|
|
|
436
558
|
for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
437
|
-
|
|
559
|
+
float local_class_sum = class_sum[class_id];
|
|
438
560
|
if (local_class_sum > THRESHOLD) {
|
|
439
561
|
local_class_sum = THRESHOLD;
|
|
440
562
|
} else if (local_class_sum < -THRESHOLD) {
|
|
441
563
|
local_class_sum = -THRESHOLD;
|
|
442
564
|
}
|
|
443
565
|
|
|
444
|
-
|
|
566
|
+
#if LOG_SCALE == 1
|
|
567
|
+
update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, component_output[clause_component] != NEG_INFINITY, &Xi[feature_chunk_base], y[example*number_of_outputs + class_id], local_class_sum);
|
|
568
|
+
#else
|
|
569
|
+
update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, component_output[clause_component] > 0, &Xi[feature_chunk_base], y[example*number_of_outputs + class_id], local_class_sum);
|
|
570
|
+
#endif
|
|
445
571
|
}
|
|
446
572
|
}
|
|
447
573
|
|
|
@@ -449,7 +575,7 @@ code_update = """
|
|
|
449
575
|
}
|
|
450
576
|
|
|
451
577
|
// Update state of Tsetlin Automata team
|
|
452
|
-
__global__ void update_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights,
|
|
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)
|
|
453
579
|
{
|
|
454
580
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
455
581
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -459,13 +585,18 @@ code_update = """
|
|
|
459
585
|
|
|
460
586
|
for (unsigned long long clause = index; clause < CLAUSES; clause += stride) {
|
|
461
587
|
for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
|
|
462
|
-
|
|
588
|
+
float local_class_sum = class_sum[class_id];
|
|
463
589
|
if (local_class_sum > THRESHOLD) {
|
|
464
590
|
local_class_sum = THRESHOLD;
|
|
465
591
|
} else if (local_class_sum < -THRESHOLD) {
|
|
466
592
|
local_class_sum = -THRESHOLD;
|
|
467
593
|
}
|
|
468
|
-
|
|
594
|
+
|
|
595
|
+
#if LOG_SCALE == 1
|
|
596
|
+
update_clause_weight(&localState, tm_type, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], clause_output[clause] != NEG_INFINITY, y[example*number_of_outputs + class_id], local_class_sum);
|
|
597
|
+
#else
|
|
598
|
+
update_clause_weight(&localState, tm_type, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], clause_output[clause] > 0, y[example*number_of_outputs + class_id], local_class_sum);
|
|
599
|
+
#endif
|
|
469
600
|
}
|
|
470
601
|
}
|
|
471
602
|
|
|
@@ -477,7 +608,7 @@ code_update = """
|
|
|
477
608
|
code_prepare = """
|
|
478
609
|
extern "C"
|
|
479
610
|
{
|
|
480
|
-
__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)
|
|
481
612
|
{
|
|
482
613
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
483
614
|
int stride = blockDim.x * gridDim.x;
|
|
@@ -501,17 +632,14 @@ code_prepare = """
|
|
|
501
632
|
state[index] = localState;
|
|
502
633
|
}
|
|
503
634
|
|
|
504
|
-
__global__ void prepare_hierarchy(
|
|
635
|
+
__global__ void prepare_hierarchy(int number_of_outputs, unsigned int *global_ta_state)
|
|
505
636
|
{
|
|
506
637
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
507
638
|
int stride = blockDim.x * gridDim.x;
|
|
508
639
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
for (int clause_component = index; clause_component < CLAUSES*COMPONENTS; clause_component += stride) {
|
|
513
|
-
// Get state of current clause component
|
|
514
|
-
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];
|
|
515
643
|
for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF; ++ta_chunk) {
|
|
516
644
|
for (int b = 0; b < STATE_BITS-1; ++b) {
|
|
517
645
|
ta_state[ta_chunk*STATE_BITS + b] = ~0;
|
|
@@ -519,8 +647,6 @@ code_prepare = """
|
|
|
519
647
|
ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1] = 0;
|
|
520
648
|
}
|
|
521
649
|
}
|
|
522
|
-
|
|
523
|
-
state[index] = localState;
|
|
524
650
|
}
|
|
525
651
|
}
|
|
526
652
|
"""
|
|
@@ -589,9 +715,9 @@ code_clauses = """
|
|
|
589
715
|
int index = blockIdx.x * blockDim.x + threadIdx.x;
|
|
590
716
|
int stride = blockDim.x * gridDim.x;
|
|
591
717
|
|
|
592
|
-
for (unsigned long long i = index; i < 1LLU * CLAUSES *
|
|
593
|
-
unsigned long long clause = i / (
|
|
594
|
-
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;
|
|
595
721
|
unsigned long long ta_idx = i % LITERALS_PER_LEAF;
|
|
596
722
|
|
|
597
723
|
int chunk = ta_idx / 32;
|
|
@@ -600,14 +726,14 @@ code_clauses = """
|
|
|
600
726
|
unsigned int state = 0;
|
|
601
727
|
for (int b = 0; b < STATE_BITS; ++b) {
|
|
602
728
|
unsigned int plane = global_ta_state[
|
|
603
|
-
(clause *
|
|
729
|
+
(clause * TA_TEAMS * TA_CHUNKS_PER_LEAF * STATE_BITS) +
|
|
604
730
|
(comp * TA_CHUNKS_PER_LEAF * STATE_BITS) +
|
|
605
731
|
(chunk * STATE_BITS) + b
|
|
606
732
|
];
|
|
607
733
|
if (plane & (1U << bit_pos)) state |= (1U << b);
|
|
608
734
|
}
|
|
609
735
|
|
|
610
|
-
unpacked_states[(clause *
|
|
736
|
+
unpacked_states[(clause * TA_TEAMS * LITERALS_PER_LEAF) + (comp * LITERALS_PER_LEAF) + ta_idx] = state;
|
|
611
737
|
}
|
|
612
738
|
}
|
|
613
739
|
"""
|