ytm.simple.BaseTM#

class ytm.simple.BaseTM(n_clauses: int, T: float | tuple[float, float], s: float, dim: int | tuple[int, ...], n_classes: int, q: float = 1.0, coalesced: bool = True, patch_dim: tuple[int, int] | None = None, negative_clauses: bool = True, negated_literals: bool = True, position_literals: bool = True, max_includes: int | None = None, n_states: int = 256, ta_init: str | int = 'middle', boost_tp_inc: bool = True, boost_tp_dec: bool = False, allow_polarity_change: bool = True, seed: int | None = None)#

Bases: object

Weighted Tsetlin Machine in pure numpy.

Each clause is a team of Tsetlin Automata (TA), one TA per literal. A TA with n_states states includes its literal when its state is >= include_state, else it excludes it. A clause is the AND of its included literals, so an empty clause always outputs 1. Each clause votes for or against each class through a signed integer weight, the sign being its polarity. The weighted votes of the active clauses give the class sum.

Learning follows the TM feedback loop, one sample at a time:

  • Type I feedback is given to clauses whose polarity agrees with the target. Type Ia, for clauses that output 1, memorizes the input: true literals are reinforced towards include, and the clause weight moves one step away from 0. Type Ib, for clauses that output 0, forgets: every literal moves towards exclude with probability 1/s.

  • Type II feedback is given to clauses that output 1 but whose polarity disagrees with the target (false positives). Excluded false literals move towards include, so the clause stops matching the input, and the clause weight moves one step towards 0.

  • Each clause is selected for feedback with probability |prob|, where prob is the distance of the clipped class sum from its target T_max or T_min, scaled to [-1, 1].

Parameters:
n_clausesint

Clauses per clause bank.

Tfloat or tuple of (float, float)

Vote threshold. A float T gives targets [-T, T]. A tuple gives [T_min, T_max].

sfloat

Specificity, at least 1.0.

dimint or tuple of int

Input shape: D, (H, W) or (H, W, C). Inputs are binary.

n_classesint

Number of classes.

qfloat, default=1.0

Negative class sampling rate. The target class always gets feedback, each other class gets feedback with probability q / (n_classes - 1).

coalescedbool, default=True

One clause bank shared by all classes with per-class weights (Coalesced TM). False gives each class its own clause bank.

patch_dimtuple of (int, int), default=None

Convolution window (h, w) (Convolutional TM). None uses the whole input as one patch.

negative_clausesbool, default=True

Start half the clauses with negative polarity (voting against a class). False keeps every weight at 1 or above, so clauses only vote for a class.

negated_literalsbool, default=True

Append the negation of each literal. Doubles the literal count.

position_literalsbool, default=True

Add thermometer-coded patch position literals. Only used when there is more than one patch.

max_includesint, default=None

Literal budget of a clause. None, <= 0 or more than the literal count means no limit. A clause at the budget gets Type Ib instead of Type Ia feedback.

n_statesint, default=256

TA states per literal.

ta_init“middle” or int, default=”middle”

Initial TA state. "middle" is just below include.

boost_tp_incbool, default=True

Type Ia increments for true literals always happen, instead of with probability (s-1)/s.

boost_tp_decbool, default=False

Type Ia decrements for false literals always happen, instead of with probability 1/s.

allow_polarity_changebool, default=True

Let Type II feedback push a weight across 0, flipping the clause polarity.

seedint, default=None

RNG seed. None picks a random seed.

calc_class_sums(clause_outputs: ndarray, clip: bool) → ndarray#

Weighted vote of the active clauses per class. clause_outputs has shape (N, n_banks, n_clauses).

clause_outputs(X: ndarray) → ndarray#

Clause outputs, the OR over patches. Returns shape (N, n_banks, n_clauses), bool.

feedback(class_id: int, X: ndarray, co: ndarray, dropped: ndarray, target: int, prob: float) → None#

Give feedback for one class.

Parameters:
class_idint

Class to give feedback for.

Xndarray of shape (n_clauses, n_literals), bool

Literals of the patch each clause is contrasted against.

condarray of shape (n_clauses,), bool

Clause outputs.

droppedndarray of shape (n_clauses,), bool

Clauses dropped for this epoch.

targetint

+1 to push the class sum up to T_max, -1 to push it down to T_min.

probfloat

Probability of selecting each clause for feedback.

fit(X: ndarray, Y: ndarray, shuffle: bool = True, clause_drop_p: float = 0.0) → None#

Train for one epoch.

Parameters:
Xarray-like of bool, shape (N, *dim) or (N, prod(dim))

Binary inputs.

Yarray-like

Targets, see the subclass.

shufflebool, default=True

Visit the samples in a random order.

clause_drop_pfloat, default=0.0

Probability of dropping each clause for this epoch (Drop Clause). Dropped clauses output 0 and get no feedback.

score(X: ndarray) → ndarray#

Class sums for X, not clipped. Returns shape (N, n_classes), float32.

t1a(bank: int, clause_filter: ndarray, X: ndarray) → None#

Type Ia feedback: reinforce include for true literals, exclude for false literals.

t1b(bank: int, clause_filter: ndarray) → None#

Type Ib feedback: reinforce exclude for every literal with probability 1/s.

t2(bank: int, clause_filter: ndarray, X: ndarray) → None#

Type II feedback: penalize the exclusion of false literals, making the clause output 0 for the input.