ZENKEI AI FORUM 2021/09/29




...♦...



ZAF 2021年9月28日
<今回のテーマ>
秋の夜長は
コーディング
(あるいは読書)



...♦...




目次





...♦...




前座

ポッドキャスト復活!




...♦...



新しい編集方針

いい点

ということで、8月末から、即実行!




...♦...



ということで、8月末から、即実行!




...♦...



ポッドキャスト

ところでみなさん、ポッドキャスト、どうやって聞いてますか?

ZENKEI AI ポッドキャストは、 ホームページ以外に、 いろんなポッドキャスト・サービスからも聞くことができます!




...♦...



反響は?



...♦...



Podcast Freaks




...♦...



Podcast Ranking




...♦...



反響は...よく分からない




...♦...



ところで YouTube




...♦...




One More Thing (for 前座)


前座といえば...

アレはどうなったのか、と...

思ってる人も、ちらほらと...




...♦...




ZAM (ザム)はどうなった?

編集長、出てこいっ

って、思ってますよね

ZAM の現状報告

まとめ - 月刊 ZAM
刊行状況 刊行状況
2021/01 初版:オンライン公開済み、印刷 2021/02 初版:オンライン公開済み、印刷
第2版:オンライン公開済み
2021/03 初版:オンライン公開済み、印刷 2021/04 - まだ
2021/05 初版:オンライン公開済み、印刷 2021/06 - まだ
2021/07 原稿着 2021/08 - まだ
2021/09 - - 2021/10 - -
2021/11 - - 2021/12 - -
まとめ - ZAM 季報
刊行状況
ZAM 季報 VOL.1 (2021/07) 初版:オンライン公開済み、印刷
ZAM 季報 VOL.2 (2021/12) - -


これから、がんばります!

優先順位的には、



みなさんも、原稿を書いてみませんか?

お待ちしてます!!



...♦...




前座 目次





...♦...




第1部
秋の夜長は読書(論文を読もう)


前回(2021年8月)の ZAF で
話題の Transformer について、
チラっとしゃべりました

で、閃きました!



...♦...



(新シリーズ)

2021年版
NLP を完全に理解する




...♦...






...♦...



ってことで、まずは Transformer 関連の主要な論文をリストアップ

これだけは、最低でも完璧に読まないと、
Jeremy レベルにはなれないだろう、と

で、まずは最初の(有名な)

" Attention Is All You Need "
 
論文を、精読した(完了形!)



...♦...




構想を立てた!
 



...♦...



本日のお題




...♦...



Seq2Seq への Attention の導入

Bahdanau, Cho, Bengio による論文

" Neural Machine Translation By Jointly Learning To Align and Translate "
を精読する




...♦...



論文の読み方




...♦...



Abstract を精読




...♦...



論文の構成を見る

  • 1 Introduction
  • 2 Backround: Neural Machine Translation
    • 2.1 RNN Encoder-Decoder
  • 3 Learning To Align and Translate
    • 3.1 Decoder: General Description
    • 3.2 Encoder: Bidirectional RNN for Annotating Sequences
  • 4 Experiment Settings
    • 4.1 Dataset
    • 4.2 Models
  • 5 Results
    • 5.1 Quantitative Results
    • 5.2 Qualitative Results
      • 5.2.1 Alignment
      • 5.2.2 Long Sentences
  • 6 Related Works
    • 6.1 Learning to Align
    • 6.2 Neural Networks for Machine Translation
  • 7 Conclusion
  • Acknowledgements
  • References
  • A Model Architecture
    • A.1 Architectural Choices
      • A.1.1 Recurrent Neural Network
      • A.1.2 Alignment Model
    • A.2 Detailed Description of the Model
      • A.2.1 Encoder
      • A.2.2 Decoder
      • A.2.3 Model Size
  • B Training Procedure
    • B.1 Parameter Initialization
    • B.2 Training
  • C Translations of Long Sentences



...♦...






...♦...



Encoder-Decoder の説明




...♦...



Context Vector と Alignment Model の説明




...♦...



Encoder の Bidirectional RNN の説明




...♦...



困ったときの Appendix




...♦...



(1)RNN (GRU) に Attention を入れる方法について




...♦...



(2)proposed updated state s~i の式について




...♦...



Alignment Model の詳細




...♦...




第1部「秋の夜長は読書(論文を読もう)」 目次





...♦...




第2部
秋の夜長はコーディング

さて、実装しましょう!




...♦...



Seq2Seq モデルの実装

パラメータ

  • bs : バッチサイズ
  • maxlen_in : 入力文字列の長さ
  • maxlen_out : 出力文字列の長さ
  • enc_num_emb : 入力のトークンの種類
  • dec_num_emb : 出力のトークンの種類
  • enc_emb_dim : 入力の word vectors の次元
  • dec_emb_dim : 出力の word vectors の次元
  • hidden_size : Encoder の hidden layer のサイズ
  • n_layers : Encoder, Decoder の hidden layer の層の数
  • bidirectional : Encoder が bidirectional の時 True
    (デフォルトは False)
	
class Seq2SeqGRU(nn.Module):
    def __init__(
        self,
        enc_num_emb, enc_emb_dim,
        dec_num_emb, dec_emb_dim,
        hidden_size, n_layers=2,
        bidirectional=False,
    ):
        super(Seq2SeqGRU, self).__init__()

        self.n_layers = n_layers
        self.hidden_size = hidden_size
        self.bidirectional = bidirectional
        self.d_dir = 2 if bidirectional else 1
        self.dec_num_emb = dec_num_emb

        d_nh = self.d_dir * hidden_size

        self.enc_emb = nn.Embedding(enc_num_emb, enc_emb_dim)
        self.enc = nn.GRU(
            enc_emb_dim,
            hidden_size,
            num_layers=n_layers,
            bidirectional=bidirectional,
            batch_first=True,
        )

        self.dec_emb = nn.Embedding(dec_num_emb, dec_emb_dim)
        self.dec = nn.GRU(
            dec_emb_dim,
            d_nh,
            num_layers=n_layers,
        self.dec_lin = nn.Linear(hidden_size, dec_num_emb)
        
      

変数、パラメータ

  • 入力文字列: inp [bs, maxlen_in]
  • 出力文字列(正解): label [bs, maxlen_out]

パラメータ

  • tf : teacher forcing の割合
	
    def forward(self, inp, label=None, tf=0.0):
        bs, seq_len = inp.shape
        hidden = torch.zeros(
            self.d_dir*self.n_layers,
            bs,
            self.hidden_size
        ).to(device)

        # ENCODING -----------------------------------------------
        emb_inp = self.enc_emb(inp)
        enc_outp, hidden = self.enc(emb_inp, hidden)
        # enc_outp [bs, L, 2*hidden_size]

        # preparation for decoding -------------------------------
        # hidden [2*n_layers, bs, hidden]
        hidden = hidden.reshape(
            self.d_dir, self.n_layers, bs, self.hidden_size
        ).permute(1, 2, 0, 3).reshape(
            self.n_layers, bs, -1
        )
        # => hidden [n_layers, bs, 2*hidden]

        dec_inp = torch.LongTensor([SOS]*bs).view(1, -1).to(device)
        # => (1, bs), where L=1 is seq. length

        outputs = torch.empty((0, bs, self.dec_num_emb)).to(device)

        # DECODING -----------------------------------------------
        for i in range(maxlen_out):
            emb_inp = self.dec_emb(dec_inp)
            dec_outp, hidden = self.dec(emb_inp, hidden)
            # => dec_outp[1, bs, 2*hidden_size]
            outp = self.dec_lin(dec_outp.squeeze(0))
            # => outp[bs, dec_num_emb]

            outputs = torch.cat((outputs, outp.view(1, bs, -1)), dim=0)

            if label is None or (i / maxlen_out) < tf:
                p = F.softmax(outp, dim=-1)
                dec_inp = torch.argmax(p, dim=-1).view(1, -1)
            else:
                dec_inp = label[:, i].view(1, -1)

        return outputs
        
      



...♦...



Encoding 部分




...♦...



Encoder から Decoding への引継ぎ




...♦...



Decoding の処理




...♦...



Attention の実装

コード

    
class Seq2SeqAttnGRU(nn.Module):
    def __init__(
        self,
        enc_num_emb, enc_emb_dim,
        dec_num_emb, dec_emb_dim,
        hidden_size, n_layers=2,
        bidirectional=False,
        attn_type='orig',
        only_top=False,
    ):
        '''
        attn_types
           'orig': 
           'dot': 
           'general': 
           'concat': 
           'none': no attention
        '''
        super(Seq2SeqAttnGRU, self).__init__()

        # Seq2Seq 部分は省略

        # attention
        self.attn_type = attn_type
        self.only_top = only_top
        if self.attn_type != 'none':
            if self.attn_type in ('orig', 'general'):
                self.W1 = nn.Linear(d_nh, d_nh)
            elif self.attn_type == 'concat':
                self.W1 = nn.Linear(2*d_nh, d_nh)

            self.W2 = nn.Linear(d_nh, d_nh)
            self.v = nn.Parameter(torch.randn(d_nh))
            
            if not only_top:
                self.Wc = nn.Linear(1, n_layers)
    
  
    
    def forward(self, inp, label=None, tf=0.0):
            
        # ENCODING -----------------------------------------------
        # Seq2Seq 部分は省略
            
        attns = None

        # attention
        if self.attn_type != 'none':
            enc_outp = enc_outp.permute(1, 0, 2)
        
            if self.attn_type in ['orig', 'general']:
                # enc_outp [L, bs, D*nh] (permuted)
                # W1 [D*nh, D*nh]
                W1enc_outp = self.W1(enc_outp)
                # => [L, bs, D*nh]
            attns = torch.empty((0, seq_len, bs)).to(device)

        # DECODING -----------------------------------------------
        for i in range(maxlen_out):
            emb_inp = self.dec_emb(dec_inp)
            dec_outp, hidden = self.dec(emb_inp, hidden)
            # => dec_outp[1, bs, 2*hidden_size]
            outp = self.dec_lin(dec_outp.squeeze(0))
            # => outp[bs, dec_num_emb]

            # attention
            if self.attn_type != 'none':
                if self.attn_type == 'orig':
                    # dec_outp [1, bs, D*nh]
                    # W2 [D*nh, D*nh]
                    W2dec_outp = self.W2(dec_outp) # => [1, bs, D*nh]
                    z = torch.tanh(W1enc_outp + W2dec_outp) # => [L, bs, D*nh]

                    zz = torch.matmul(z, self.v) # => [L, bs]
                elif self.attn_type == 'dot':
                    # enc_outp [L, bs, D*nh] (permuted)
                    # dec_outp [1, bs, D*nh]
                    zz = torch.bmm(
                        enc_outp.permute(1, 0, 2),
                        dec_outp.permute(1, 2, 0)
                    ).permute(1, 0, 2).squeeze(-1)
                    # => [L, bs]
                elif self.attn_type == 'general':
                    # W1enc_outp [L, bs, D*nh]
                    zz = torch.bmm(
                        W1enc_outp.permute(1, 0, 2),
                        dec_outp.permute(1, 2, 0)
                    ).permute(1, 0, 2).squeeze(-1)
                    # => [L, bs]
                elif self.attn_type == 'concat':
                    # enc_outp [L, bs, D*nh] (permuted)
                    # dec_outp [1, bs, D*nh]
                    zz = torch.cat((
                        enc_outp,
                        dec_outp.expand_as(enc_outp)
                    ), dim=-1)
                    #print(f'(1) zz {zz.shape}')
                    # (1) zz torch.Size([16, 128, 512])
                    # => [L, bs, 2*D*nh]
                    zz = self.W1(zz)
                    #print(f'(2) zz {zz.shape}')
                    # (2) zz torch.Size([16, 128, 256])
                    # => [L, bs, D*nh]
                    zz = torch.tanh(zz) # => [L, bs, D*nh]
                    zz = torch.matmul(zz, self.v) # => [L, bs]

                a = torch.softmax(zz, dim=0) # => [L, bs]
                #print(f'a {a.shape}')
                #a torch.Size([16, 128])

                attns = torch.cat((attns, a.unsqueeze(0)), dim=0)

                # enc_outp [L, bs, D*nh] (permuted)
                d = (enc_outp * a.unsqueeze(-1)).sum(0)
                # => [bs, D*nh]
                if self.only_top:
                    hidden[-1] += d
                else:
                    # apply to all layers
                    d = self.Wc(d.unsqueeze(-1))
                    # => [bs, D*nh, n_layers]
                    hidden += d.permute(2, 0, 1)
                    # hidden [n_layers, bs, 2*hidden]


            outputs = torch.cat((outputs, outp.view(1, bs, -1)), dim=0)

            if label is None or (i / maxlen_out) > tf:
                p = F.softmax(outp, dim=-1)
                dec_inp = torch.argmax(p, dim=-1).view(1, -1)
            else:
                dec_inp = label[:, i].view(1, -1)

        return outputs, attns
    
  



...♦...



いくつかの結果

Spelling Bee

フランス語から英語への翻訳




...♦...




第2部「秋の夜長はコーディング」 目次





...♦...




今日のおわりに

……

今後の予定




...♦...





総合目次




...♦...