def fprop(params): """ Forward pass of the NTM. """ W = params # aliasing for brevity xs, zhs, hs, ys, ps, ts, zos, os = {}, {}, {}, {}, {}, {}, {}, {} def l(): """ Silly utility function that should be called in init. """ return [{} for _ in xrange(self.heads)] rs = l() zk_rs = l() k_rs, beta_rs, g_rs, s_rs, gamma_rs = l(),l(),l(),l(),l() k_ws, beta_ws, g_ws, s_ws, gamma_ws = l(),l(),l(),l(),l() adds, erases = l(),l() w_ws, w_rs = l(),l() # read weights and write weights for idx in range(self.heads): rs[idx][-1] = self.W['rsInit' + str(idx)] # stores values read from memory w_ws[idx][-1] = softmax(self.W['w_wsInit' + str(idx)]) w_rs[idx][-1] = softmax(self.W['w_rsInit' + str(idx)]) mems = {} # the state of the memory at every timestep mems[-1] = self.W['memsInit'] loss = 0 for t in xrange(len(inputs)): xs[t] = np.reshape(np.array(inputs[t]),inputs[t].shape[::-1]) rsum = 0 for idx in range(self.heads): rsum = rsum + np.dot(W['rh' + str(idx)], np.reshape(rs[idx][t-1],(self.M,1))) zhs[t] = np.dot(W['xh'], xs[t]) + rsum + W['bh'] hs[t] = np.tanh(zhs[t]) zos[t] = np.dot(W['ho'], hs[t]) + W['bo'] os[t] = np.tanh(zos[t]) for idx in range(self.heads): # parameters to the read head zk_rs[idx][t] =np.dot(W['ok_r' + str(idx)],os[t]) + W['bk_r' + str(idx)] k_rs[idx][t] = np.tanh(zk_rs[idx][t]) beta_rs[idx][t] = softplus(np.dot(W['obeta_r' + str(idx)],os[t]) + W['bbeta_r' + str(idx)]) g_rs[idx][t] = sigmoid(np.dot(W['og_r' + str(idx)],os[t]) + W['bg_r' + str(idx)]) s_rs[idx][t] = softmax(np.dot(W['os_r' + str(idx)],os[t]) + W['bs_r' + str(idx)]) gamma_rs[idx][t] = 1 + sigmoid(np.dot(W['ogamma_r' + str(idx)], os[t]) + W['bgamma_r' + str(idx)]) # parameters to the write head k_ws[idx][t] = np.tanh(np.dot(W['ok_w' + str(idx)],os[t]) + W['bk_w' + str(idx)]) beta_ws[idx][t] = softplus(np.dot(W['obeta_w' + str(idx)], os[t]) + W['bbeta_w' + str(idx)]) g_ws[idx][t] = sigmoid(np.dot(W['og_w' + str(idx)],os[t]) + W['bg_w' + str(idx)]) s_ws[idx][t] = softmax(np.dot(W['os_w' + str(idx)],os[t]) + W['bs_w' + str(idx)]) gamma_ws[idx][t] = 1 + sigmoid(np.dot(W['ogamma_w' + str(idx)], os[t]) + W['bgamma_w' + str(idx)]) # the erase and add vectors # these are also parameters to the write head # but they describe "what" is to be written rather than "where" adds[idx][t] = np.tanh(np.dot(W['oadds' + str(idx)], os[t]) + W['badds' + str(idx)]) erases[idx][t] = sigmoid(np.dot(W['oerases' + str(idx)], os[t]) + W['erases' + str(idx)]) w_ws[idx][t] = addressing.create_weights( k_ws[idx][t] , beta_ws[idx][t] , g_ws[idx][t] , s_ws[idx][t] , gamma_ws[idx][t] , w_ws[idx][t-1] , mems[t-1]) w_rs[idx][t] = addressing.create_weights( k_rs[idx][t] , beta_rs[idx][t] , g_rs[idx][t] , s_rs[idx][t] , gamma_rs[idx][t] , w_rs[idx][t-1] , mems[t-1]) ys[t] = np.dot(W['oy'], os[t]) + W['by'] ps[t] = sigmoid(ys[t]) one = np.ones(ps[t].shape) ts[t] = np.reshape(np.array(targets[t]),(self.out_size,1)) epsilon = 2**-23 # to prevent log(0) a = np.multiply(ts[t] , np.log2(ps[t] + epsilon)) b = np.multiply(one - ts[t], np.log2(one-ps[t] + epsilon)) loss = loss - (a + b) for idx in range(self.heads): # read from the memory rs[idx][t] = memory.read(mems[t-1],w_rs[idx][t]) # write into the memory mems[t] = memory.write(mems[t-1],w_ws[idx][t],erases[idx][t],adds[idx][t]) self.stats = [loss, mems, ps, ys, os, zos, hs, zhs, xs, rs, w_rs, w_ws, adds, erases] return np.sum(loss)
def loadabs(): ls = m.read(pc + 1) ms = m.read(pc + 2) addr = ms << 8 | ls writeReg(A, m.read(addr)) update(3, 16)
def decat(regs): addr = readRegs(regs) value = m.read(addr) - 1 m.write(addr, value) update(1, 12, zerocheck=value, n=1, h=((value >> 4) & 1))
def savetoIO(): addr = 0xFF00 | readReg(C) writeReg(A, m.read(addr)) update(1, 8)
def putabs(): ls = m.read(pc + 1) ms = m.read(pc + 2) addr = ms << 8 | ls m.write(addr, readReg(A)) update(3, 16)
def loadfrom(reg, regs): addr = readRegs(regs) value = m.read(addr) writeReg(reg, value) update(1, 8)
def ldh_ai(value): addr = 0xFF00 | value writeReg(A, m.read(addr)) update(2, 12)
def loadi16(toRegs): value = (m.read(pc + 2) << 8) + (m.read(pc + 1)) writeRegs(toRegs, value) update(3, 12)
def loadiat(regs): addr = readRegs(regs) value = m.read(pc + 1) m.write(addr, value) update(2, 12)
def loadi8(toReg): value = m.read(pc + 1) writeReg(toReg, value) update(2, 8)
def printLCD(): print("LY=" + str(hex(m.read(0xff44))), " LCDC=" + str(hex(m.read(0xff41))))
def printState(): print("{0:#0{1}x}".format(pc, 6), "{0:#0{1}x}".format(m.read(pc), 4)) printRegs() printFlags() printLCD()
def getif(interrupt): return bool(m.read(0xff0f) >> (interrupts[interrupt]) & 1)
0x11: lambda pc: loadi16(DE), 0x12: lambda pc: loadto((DE), A), 0x13: lambda pc: inc16(DE), 0x14: lambda pc: inc8(D), 0x15: lambda pc: dec8(D), 0x16: lambda pc: loadi8(D), 0x17: lambda pc: rla(), 0x18: lambda pc: jumpr(), 0x19: lambda pc: add16s(HL, DE), 0x1a: lambda pc: loadfrom(A, (DE)), 0x1b: lambda pc: dec16(DE), 0x1c: lambda pc: inc8(E), 0x1d: lambda pc: dec8(E), 0x1e: lambda pc: loadi8(E), 0x1f: lambda pc: rra(), 0x20: lambda pc: jumprf(m.read(pc)), 0x21: lambda pc: loadi16(HL), 0x22: lambda pc: loadtoc('+'), 0x23: lambda pc: inc16(HL), 0x24: lambda pc: inc8(H), 0x25: lambda pc: dec8(H), 0x26: lambda pc: loadi8(H), 0x28: lambda pc: jumprf(m.read(pc)), 0x29: lambda pc: add16s(HL, HL), 0x2a: lambda pc: loadfromc('+'), 0x2b: lambda pc: dec16(HL), 0x2c: lambda pc: inc8(L), 0x2d: lambda pc: dec8(L), 0x2e: lambda pc: loadi8(L), 0x2f: lambda pc: cpl(), 0x30: lambda pc: jumprf(m.read(pc)),