class AttentionWeight: def __init__(self): self.params, self.grads = [], [] self.softmax = Softmax() self.cache = None def forward(self, hs, h): N, T, H = hs.shape hr = h.reshape(N, 1, H) #.repeat(T, axis=1) t = hs * hr s = np.sum(t, axis=2) a = self.softmax.forward(s) self.cache = (hs, hr) return a def backward(self, da): hs, hr = self.cache N, T, H = hs.shape ds = self.softmax.backward(da) dt = ds.reshape(N, T, 1).repeat(H, axis=2) dhs = dt * hr dhr = dt * hs dh = np.sum(dhr, axis=1) return dhs, dh
class AttentionWeight: def __init__(self): self.params, self.grads = [], [] self.softmax = Softmax() self.cache = None def forward(self, hs, h): """順伝搬 Args: hs (ndarray): Encorderで取得した各単語ベクトルを連結した隠れベクトル h (ndarray): hsの最終単語に対応するベクトル Returns: a (ndarray): Attention用重みベクトル """ N, T, H = hs.shape hr = h.reshape(N, 1, H).repeat(T, axis=1) t = hs * hr s = np.sum(t, axis=2) # スコア(重み付き和) a = self.softmax.forward(s) self.cache = (hs, hr) return a def backward(self, da): """逆伝搬 Args: da (ndarray): Attention用重みベクトルの誤差微分 Returns: dhs: Encorderで取得した各単語ベクトルを連結した隠れベクトルの誤差微分 dh: hsの最終単語に対応するベクトルの誤差微分 """ hs, hr = self.cache N, T, H = hs.shape ds = self.softmax.backward(da) dt = ds.reshape(N, T, 1).repeat(H, axis=2) # Sumの逆伝搬はRepeat dhs = dt * hr dhr = dt * hs dh = np.sum(dhr, axis=1) # Repeatの逆伝搬はSum return dhs, dh
class AttentionWeight: ''' Encoderの全系列の隠れ状態hs(N, T, H)と Decoderの現系列の隠れ状態h(N, H)とのドット積をとり、 softmax関数にかけることで系列ごとのアライメントa(N, T)を 出力するレイヤ ''' def __init__(self): self.params, self.grads = [], [] self.softmax = Softmax() self.cache = None def forward(self, hs, h): ''' Decoderの隠れ状態h(N, H)をnp.repeatで(N, T, H)に拡張し、 hsとのアダマール積を取ってHについて総和を取り、 Softmax関数で正規化してアライメントa(N, T)を得る Parameters ---------- hs : np.ndarray(N, T, H) Encoderの全系列の隠れ状態 h : np.ndarray(N, H) Decoderの現系列の隠れ状態 Returns ------- np.ndarray(N, T) hsに対し、系列ごとの重みを示すアライメント ''' N, T, H = hs.shape hr = h.reshape(N, 1, H)#.repeat(T, axis=1) t = hs * hr # (N, T, H) s = t.sum(axis=2) a = self.softmax.forward(s) # (N, T) self.cache = (hs, hr) return a def backward(self, da): ''' sumの逆伝播はrepeat repeatの逆伝播はsum Parameters ---------- da : np.ndarray(N, T) アライメントの勾配 Returns ------- dhs, dh : np.ndarray(N, T, H), np.ndarray(N, H) 全系列の隠れ状態hsの勾配と系列の隠れ状態hの勾配 ''' hs, hr = self.cache N, T, H = hs.shape ds = self.softmax.backward(da) dt = ds.reshape(N, T, 1).repeat(H, axis=2) dhs = dt * hr # (N, T, H) dhr = dt * hs # (N, T, H) dh = dhr.sum(axis=1) # (N, H) return dhs, dh