Entity: refactored taining algo into train module

This commit is contained in:
2025-12-18 21:23:16 +01:00
parent 6664ebdb9b
commit b206ab5788
7 changed files with 120 additions and 118 deletions
+98
View File
@@ -0,0 +1,98 @@
from collections.abc import Callable
from matrix import gaussian, sample, prob, rms_error_accu, Mat, np
from entity import Entity
from status import Status
def cd_jens(entity: Entity, v_states: Mat):
v_probs = prob(v_states)
h_states = entity.v_to_ph(v_states)
h_probs = h_states
if entity.params.do_gaussian_hidden:
h_states += gaussian(h_states.shape)
else:
h_probs = entity.v_to_ph(v_states)
if entity.params.do_rao_blackwell:
h_states = h_probs
else:
h_states = sample(h_probs)
# Update weights (positive phase)
dw = np.dot(np.transpose(v_states), h_states)
dbv = np.sum(v_states, 0)
dbh = np.sum(h_states, 0)
# Gibbs sampling with training params
for i in range(entity.params.num_gibbs_samples):
if entity.params.do_gibbs_sample_hidden:
v_probs = entity.h_to_pv(sample(h_probs))
else:
v_probs = entity.h_to_pv(h_probs)
# Create hidden representation given v
if entity.params.do_gibbs_sample_visible:
h_probs = entity.v_to_ph(sample(v_probs))
else:
h_probs = entity.v_to_ph(v_probs)
# Update weights (negative phase)
dw -= np.dot(np.transpose(v_probs), h_probs)
dbv -= np.sum(v_probs, 0)
dbh -= np.sum(h_probs, 0)
return dw, dbv, dbh
def train(entity: Entity, batch: Mat, status: Status, cd_func: Callable = cd_jens):
training_remain = batch.shape[0]
batch_size = min(entity.params.mini_batch_size, training_remain)
if batch_size == 0:
batch_size = training_remain
status.on_change()
d_progress = 100.0 / (training_remain*entity.params.num_epochs)
progress = 0
batch_row_index = 0
keep_running = True
while training_remain > 0 and keep_running:
batch_size_remain = min(batch_size, training_remain)
mini_batch = batch[batch_row_index:batch_row_index + batch_size_remain]
training_remain -= batch_size_remain
batch_row_index += batch_size_remain
inc_bv = np.zeros(entity.state.b_v.shape)
inc_bh = np.zeros(entity.state.b_h.shape)
inc_whv = np.zeros(entity.state.w_hv.shape)
v_states = mini_batch
if entity.params.do_batch_sample:
v_states = sample(mini_batch)
for epochs in range(entity.params.num_epochs):
# Contrastive divergence learning: calculate gradients
dwhv, dbv, dbh = cd_func(entity, v_states)
# Adjust weight and biases
kl = entity.params.learning_rate/batch_size
inc_bv = entity.params.momentum*inc_bv + kl*dbv
inc_bh = entity.params.momentum*inc_bh + kl*dbh
inc_whv = entity.params.momentum*inc_whv + kl*dwhv - entity.params.weight_decay*entity.state.w_hv
entity.state.b_v += inc_bv
entity.state.b_h += inc_bh
entity.state.w_hv += inc_whv
# check if status update is needed
if status.want_report(round(progress)):
# Calculate error
err_rms = rms_error_accu(mini_batch - entity.h_to_pv(entity.v_to_ph(v_states)))
if not status.on_change({"progress": {"value": round(progress), "unit": "%"},
"err_rms": {"value": err_rms, "unit": ""}}):
keep_running = False
break
progress += d_progress*batch_size_remain
# Update final status
err_rms = rms_error_accu(batch - entity.h_to_pv(entity.v_to_ph(batch)))
status.on_change({"progress": {"value": round(progress), "unit": "%"},
"err_rms_total": {"value": err_rms, "unit": ""}})