rework forward_step to use char-by-char state priming with SPACE token
Replace space ' ' with explicit SPACE='_' vocab token to disambiguate padding from real spaces, and rewrite forward_step to take a single character plus rolling state string instead of a reconstructed vc matrix, producing predictions one character at a time per unit.
This commit is contained in:
@@ -19,12 +19,12 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
|||||||
from rbm.entity import EntityParams, TrainingParams, Entity
|
from rbm.entity import EntityParams, TrainingParams, Entity
|
||||||
from rbm.matrix import np, Mat
|
from rbm.matrix import np, Mat
|
||||||
from model.model import Model
|
from model.model import Model
|
||||||
from stack.rnn_helper import vocab_size, shift_left, clamp, concat, split, vec2idx, idx2ch, ch2idx, idx2vec
|
from stack.rnn_helper import vocab_size, shift_left, clamp, concat, split, vec2idx, idx2ch, ch2idx, idx2vec, SPACE
|
||||||
from rbm.train import train
|
from rbm.train import train
|
||||||
from rbm.status import Status
|
from rbm.status import Status
|
||||||
|
|
||||||
# ── Hyper-parameters ──────────────────────────────────────────────────────────
|
# ── Hyper-parameters ──────────────────────────────────────────────────────────
|
||||||
TEXT = "Call me Ishmael. Some years ago" # the character sequence to learn (matches diagram example)
|
TEXT = "123456789_Call_me_Ishmael._Some_years_ago" # the character sequence to learn (matches diagram example)
|
||||||
WIN = 2 # sliding-window width (= N in the diagram)
|
WIN = 2 # sliding-window width (= N in the diagram)
|
||||||
STRIDE = 1 # sliding-window step size
|
STRIDE = 1 # sliding-window step size
|
||||||
UNITS = 5
|
UNITS = 5
|
||||||
@@ -55,7 +55,7 @@ def str2vec(ch_str: str) -> Mat:
|
|||||||
|
|
||||||
def to_window(text: str) -> list[str]:
|
def to_window(text: str) -> list[str]:
|
||||||
result = []
|
result = []
|
||||||
_win = [' ']*UNITS
|
_win = [SPACE]*UNITS
|
||||||
for _i in range(WIN - 1):
|
for _i in range(WIN - 1):
|
||||||
for ch in text:
|
for ch in text:
|
||||||
_win = _win[1:WIN] + [ch]
|
_win = _win[1:WIN] + [ch]
|
||||||
@@ -88,7 +88,8 @@ def batch_delay(_batch: Mat, delay=0):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def vc2char(_vc: Mat):
|
def vc2char(_vc: Mat):
|
||||||
_v, _ = split(_vc.reshape(1, WIN*vocab_size()+H_SIZE), H_SIZE, axis=1)
|
__vc = _vc.reshape([1, WIN*vocab_size()+H_SIZE])
|
||||||
|
_v, _ = split(__vc, H_SIZE, axis=1)
|
||||||
return v2char(_v)
|
return v2char(_v)
|
||||||
|
|
||||||
def v2char(_v: Mat):
|
def v2char(_v: Mat):
|
||||||
@@ -112,25 +113,29 @@ class RnnModel(Model):
|
|||||||
_batch = to_batch(_win_text, index)
|
_batch = to_batch(_win_text, index)
|
||||||
_vc = concat(_batch, _c, axis=1)
|
_vc = concat(_batch, _c, axis=1)
|
||||||
for i in range(_vc.shape[0]):
|
for i in range(_vc.shape[0]):
|
||||||
print(f"train: {unit.name}:{vc2char(_vc[i,:])}")
|
print(f"train[{index}:{i:03}]: {unit.name}:{vc2char(_vc[i,:])}")
|
||||||
train(unit, _vc, status)
|
train(unit, _vc, status)
|
||||||
# For the next unit: Update context portion of vc
|
# For the next unit: Update context portion of vc
|
||||||
_c = unit.forward(_vc)
|
_c = unit.forward(_vc)
|
||||||
|
|
||||||
|
|
||||||
def forward_step(self, _vc: Mat):
|
def forward_step(self, _ch: str, _state: str):
|
||||||
text = ''
|
_state = _state[len(_ch):] + _ch
|
||||||
for unit in self.units:
|
_c = np.zeros([len(_ch), H_SIZE])
|
||||||
print(f"forward_step in : {unit.name}:{vc2char(_vc)}")
|
_ch_predict = '?'
|
||||||
|
for index, unit in enumerate(self.units):
|
||||||
|
_s = _state[index] + SPACE*(WIN-1)
|
||||||
|
print(f"forward_step in : {unit.name}:{_s}")
|
||||||
|
_v = str2vec(_s).reshape(1, WIN*vocab_size())
|
||||||
|
_vc = concat(_v, _c, axis=1)
|
||||||
_c = unit.forward(_vc)
|
_c = unit.forward(_vc)
|
||||||
_vc = unit.reconstruct(_c)
|
_vc = unit.reconstruct(_c)
|
||||||
print(f"forward_step out: {unit.name}:{vc2char(_vc)}")
|
_r, _ = split(_vc, H_SIZE, axis=1)
|
||||||
text += vc2char(_vc)[WIN-1]
|
_r_cl = clamp(_r.reshape([WIN, vocab_size()]), axis=1)
|
||||||
_v, _ = split(_vc, H_SIZE, axis=1)
|
|
||||||
_v_cl = clamp(_v.reshape([WIN, vocab_size()]), axis=1)
|
_ch_predict = v2char(_r_cl)
|
||||||
_v = shift_left(_v_cl.reshape([1, WIN*vocab_size()]), vocab_size())
|
print(f"forward_step out: {unit.name}:{_ch_predict}")
|
||||||
_vc = concat(_v, _c, axis=1)
|
return _state, _ch_predict[-1]
|
||||||
return _vc, text
|
|
||||||
|
|
||||||
def forward(self, x: Mat):
|
def forward(self, x: Mat):
|
||||||
pass
|
pass
|
||||||
@@ -163,14 +168,14 @@ if __name__ == "__main__":
|
|||||||
model.save()
|
model.save()
|
||||||
|
|
||||||
# test the model
|
# test the model
|
||||||
seed_str = ' '
|
seed_str = '1234'
|
||||||
seed_padded = seed_str + ' '*(WIN-len(seed_str))
|
state = SPACE*UNITS
|
||||||
v_test = str2vec(seed_padded).reshape([1, WIN*vocab_size()])
|
|
||||||
c_test = np.zeros([1, H_SIZE])
|
# Prime
|
||||||
vc_test = concat(v_test, c_test, axis=1)
|
for s in seed_str:
|
||||||
text = ''
|
state, ch = model.forward_step(s, state)
|
||||||
for i in range(len(TEXT)):
|
print(f'Predict: {ch}')
|
||||||
vc_test, text_frag = model.forward_step(vc_test)
|
|
||||||
text += text_frag
|
state, ch = model.forward_step('_', state)
|
||||||
|
print(f'Predict: {ch}')
|
||||||
|
|
||||||
print(text)
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from rbm.matrix import Mat, np
|
from rbm.matrix import Mat, np
|
||||||
|
|
||||||
VOCAB = ' -.!?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
SPACE='_'
|
||||||
|
VOCAB = SPACE + '-.!?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||||
_CH2IDX = {ch: i for i, ch in enumerate(VOCAB)}
|
_CH2IDX = {ch: i for i, ch in enumerate(VOCAB)}
|
||||||
|
|
||||||
def clamp(vec: Mat, axis=0):
|
def clamp(vec: Mat, axis=0):
|
||||||
|
|||||||
Reference in New Issue
Block a user