[U stage DAY 33] CV (9) - Multi-modal Learning


授業内容を復習する


(09-1講)マルチモード学習


1. Overview of multi-modal learning



マルチモード学習は、異なるタイプのデータを学習に一緒に適用する方法である.
質問する
1.データの表示方法はそれぞれ異なる(一つの画像:3 d、一つのテキスト:wordの埋め込みベクトルは一つのシーケンスに対応する)
2.異性特徴空間間のアンバランス
アボカド形の椅子(テキスト)-画像(画像)=1:Nマッチング
3.多様な形式を用いる場合の学習の限界
あまりにも多くの情報を受け取っているので、かえって勉強ができません(一つの形式だけを勉強するなどの問題)
これらの問題にもかかわらず、マルチモード学習は重要であり、そのタイプは以下の通りである.

2. Multi-modal tasks (1) - Visual data & Text


2.1 test embedding

word level text埋め込みベクトルを作成した後、各ベクトルを低次元投影することで各ベクトルの距離を測定する->他の単語関係で一般化可能(man~won:king~queen)
  • word2vec : Skip-gram model
    学習中心語と周辺語の関係
  • 2.2 Joint embedding
  • Image tagging

    イメージ->タグ/タグ->イメージの作成
  • 予雨の単一ピークモデルと組み合わせて実現
    目測空間におけるMetric Learning in visual-semanticspace:2つのベクトルを同じ埋め込み空間にマッピングして距離を減らす方向に学習する(一致しないデータについては距離を大きくして学習する)
    によって作成された連合埋め込み空間によるマルチモード解析
    適用
    [Image & food recipr retrival]([Marin et al., TPAMI 2019])
    Cross modal translation
    1. Image captioning : image to sentance - CNN 4 image + RNN 4 sentence

  • show and tell

    cnnとrnnを統合する方法,Encoder:CNNモデル事前トレーニングImageNet/Decorder:LSTMモジュール

  • show, attend, and tell - Attention

    ビデオ全体でtagを生成するために集中するローカル部分も見る方法.空間情報を保持するfixedimensinal vectorのfeature mapを作成しRNNに挿入

  • Soft Attention embedding

    人間が視覚的に物体を判断する際に集中する特徴があるように,モデルも特徴と微調整重みにzを加えることでzを作成する.

    sis isi:画像のどの部分が集中的に見る必要があるかを示すspatial soft attention map.
    ziz izi:内部から特徴図とsoft attention mapの注意重みを取得する
    yiy iii:以前に出力された単語
    hih ihi:デコーダの非表示状態
  • Text-to-image by Generative model
    テキスト-画像のように、1:nはモデルを生成する必要があります.

    Generator Network
    テキスト全体を固定次元ベクトルに変更
    ガウス分布を加えて、出力を常に異なります
    Codintial Generatorによるイメージ作成
  • Discriminator Network
    生成された画像を入力として受信し、低次元フィーチャーマッピングを抽出
    Gで使用する文の条件を組み合わせて、その条件で生成された画像をtrueまたはfalseと判定する
    Crodd model reasoning (Referencing)
    1. Visual question answering
  • multi streams
  • joint embedding
  • end-to-end training
  • 3. Multi-modal tasks (2) - Visual data & Audio


    3.1 Sound representation

    時間軸のwave形式の1 d信号は,モデル学習時にパワースペクトルまたはスペクトルのみを必要とする.
  • Fourier transform : Short-time Fourier transform (STFT)
    Fourier変換は短いウィンドウ範囲でのみ適用され、spectrogramでのみ描画/Hammming windowでは重み付け
  • が適用されます.
    Further Question
    (1)マルチモード学習において,feature間の意味を保つためにどのような学習方法を用いたか.
    (2)選択タスクを完了する際,注意力はどのように用いられるか.
    (3)Sound Sourceローカライズタスクを完了した場合,オーディオ情報はどのように利用されるのか.

    (09-2)画像説明


    タスク練習/論文:Show, Attend, and Tell

    author's original implementation : https://github.com/kelvinxu/arctic-captions Show, Attend and Tell Concepts
  • Image captioning
  • Encoder-Decoder architecture
  • Attention
  • Transfer Learning
  • Beam Search

  • environment : Pytorch 0.4 Python 3.6
  • Encoder
  • class Encoder(nn.Module):
        """
        Encoder.
        """
    
        def __init__(self, encoded_image_size=14):
            super(Encoder, self).__init__()
            self.enc_image_size = encoded_image_size
    
            resnet = torchvision.models.resnet101(pretrained=True)  # pretrained ImageNet ResNet-101
    
            # Remove linear and pool layers (since we're not doing classification)
            modules = list(resnet.children())[:-2]
            self.resnet = nn.Sequential(*modules)
    
            # Resize image to fixed size to allow input images of variable size
            self.adaptive_pool = nn.AdaptiveAvgPool2d((encoded_image_size, encoded_image_size))
    
            self.fine_tune()
    
        def forward(self, images):
            """
            Forward propagation.
            :param images: images, a tensor of dimensions (batch_size, 3, image_size, image_size)
            :return: encoded images
            """
            out = self.resnet(images)  # (batch_size, 2048, image_size/32, image_size/32)
            out = self.adaptive_pool(out)  # (batch_size, 2048, encoded_image_size, encoded_image_size)
            out = out.permute(0, 2, 3, 1)  # (batch_size, encoded_image_size, encoded_image_size, 2048)
            return out
    
        def fine_tune(self, fine_tune=True):
            """
            Allow or prevent the computation of gradients for convolutional blocks 2 through 4 of the encoder.
            :param fine_tune: Allow?
            """
            for p in self.resnet.parameters():
                p.requires_grad = False
            # If fine-tuning, only fine-tune convolutional blocks 2 through 4
            for c in list(self.resnet.children())[5:]:
                for p in c.parameters():
                    p.requires_grad = fine_tune
  • Decoder(with attention)
  • class Attention(nn.Module):
        """
        Attention Network.
        """
    
        def __init__(self, encoder_dim, decoder_dim, attention_dim):
            """
            :param encoder_dim: feature size of encoded images
            :param decoder_dim: size of decoder's RNN
            :param attention_dim: size of the attention network
            """
            super(Attention, self).__init__()
            self.encoder_att = nn.Linear(encoder_dim, attention_dim)  # linear layer to transform encoded image
            self.decoder_att = nn.Linear(decoder_dim, attention_dim)  # linear layer to transform decoder's output
            self.full_att = nn.Linear(attention_dim, 1)  # linear layer to calculate values to be softmax-ed
            self.relu = nn.ReLU()
            self.softmax = nn.Softmax(dim=1)  # softmax layer to calculate weights
    
        def forward(self, encoder_out, decoder_hidden):
            """
            Forward propagation.
            :param encoder_out: encoded images, a tensor of dimension (batch_size, num_pixels, encoder_dim)
            :param decoder_hidden: previous decoder output, a tensor of dimension (batch_size, decoder_dim)
            :return: attention weighted encoding, weights
            """
            att1 = self.encoder_att(encoder_out)  # (batch_size, num_pixels, attention_dim)
            att2 = self.decoder_att(decoder_hidden)  # (batch_size, attention_dim)
            att = self.full_att(self.relu(att1 + att2.unsqueeze(1))).squeeze(2)  # (batch_size, num_pixels)
            alpha = self.softmax(att)  # (batch_size, num_pixels)
            attention_weighted_encoding = (encoder_out * alpha.unsqueeze(2)).sum(dim=1)  # (batch_size, encoder_dim)
    
            return attention_weighted_encoding, alpha
    
    
    class DecoderWithAttention(nn.Module):
        """
        Decoder.
        """
    
        def __init__(self, attention_dim, embed_dim, decoder_dim, vocab_size, encoder_dim=2048, dropout=0.5):
            """
            :param attention_dim: size of attention network
            :param embed_dim: embedding size
            :param decoder_dim: size of decoder's RNN
            :param vocab_size: size of vocabulary
            :param encoder_dim: feature size of encoded images
            :param dropout: dropout
            """
            super(DecoderWithAttention, self).__init__()
    
            self.encoder_dim = encoder_dim
            self.attention_dim = attention_dim
            self.embed_dim = embed_dim
            self.decoder_dim = decoder_dim
            self.vocab_size = vocab_size
            self.dropout = dropout
    
            self.attention = Attention(encoder_dim, decoder_dim, attention_dim)  # attention network
    
            self.embedding = nn.Embedding(vocab_size, embed_dim)  # embedding layer
            self.dropout = nn.Dropout(p=self.dropout)
            self.decode_step = nn.LSTMCell(embed_dim + encoder_dim, decoder_dim, bias=True)  # decoding LSTMCell
            self.init_h = nn.Linear(encoder_dim, decoder_dim)  # linear layer to find initial hidden state of LSTMCell
            self.init_c = nn.Linear(encoder_dim, decoder_dim)  # linear layer to find initial cell state of LSTMCell
            self.f_beta = nn.Linear(decoder_dim, encoder_dim)  # linear layer to create a sigmoid-activated gate
            self.sigmoid = nn.Sigmoid()
            self.fc = nn.Linear(decoder_dim, vocab_size)  # linear layer to find scores over vocabulary
            self.init_weights()  # initialize some layers with the uniform distribution
    
        def init_weights(self):
            """
            Initializes some parameters with values from the uniform distribution, for easier convergence.
            """
            self.embedding.weight.data.uniform_(-0.1, 0.1)
            self.fc.bias.data.fill_(0)
            self.fc.weight.data.uniform_(-0.1, 0.1)
    
        def load_pretrained_embeddings(self, embeddings):
            """
            Loads embedding layer with pre-trained embeddings.
            :param embeddings: pre-trained embeddings
            """
            self.embedding.weight = nn.Parameter(embeddings)
    
        def fine_tune_embeddings(self, fine_tune=True):
            """
            Allow fine-tuning of embedding layer? (Only makes sense to not-allow if using pre-trained embeddings).
            :param fine_tune: Allow?
            """
            for p in self.embedding.parameters():
                p.requires_grad = fine_tune
    
        def init_hidden_state(self, encoder_out):
            """
            Creates the initial hidden and cell states for the decoder's LSTM based on the encoded images.
            :param encoder_out: encoded images, a tensor of dimension (batch_size, num_pixels, encoder_dim)
            :return: hidden state, cell state
            """
            mean_encoder_out = encoder_out.mean(dim=1)
            h = self.init_h(mean_encoder_out)  # (batch_size, decoder_dim)
            c = self.init_c(mean_encoder_out)
            return h, c
    
        def forward(self, encoder_out, encoded_captions, caption_lengths):
            """
            Forward propagation.
            :param encoder_out: encoded images, a tensor of dimension (batch_size, enc_image_size, enc_image_size, encoder_dim)
            :param encoded_captions: encoded captions, a tensor of dimension (batch_size, max_caption_length)
            :param caption_lengths: caption lengths, a tensor of dimension (batch_size, 1)
            :return: scores for vocabulary, sorted encoded captions, decode lengths, weights, sort indices
            """
    
            batch_size = encoder_out.size(0)
            encoder_dim = encoder_out.size(-1)
            vocab_size = self.vocab_size
    
            # Flatten image
            encoder_out = encoder_out.view(batch_size, -1, encoder_dim)  # (batch_size, num_pixels, encoder_dim)
            num_pixels = encoder_out.size(1)
    
            # Sort input data by decreasing lengths; why? apparent below
            caption_lengths, sort_ind = caption_lengths.squeeze(1).sort(dim=0, descending=True)
            encoder_out = encoder_out[sort_ind]
            encoded_captions = encoded_captions[sort_ind]
    
            # Embedding
            embeddings = self.embedding(encoded_captions)  # (batch_size, max_caption_length, embed_dim)
    
            # Initialize LSTM state
            h, c = self.init_hidden_state(encoder_out)  # (batch_size, decoder_dim)
    
            # We won't decode at the <end> position, since we've finished generating as soon as we generate <end>
            # So, decoding lengths are actual lengths - 1
            decode_lengths = (caption_lengths - 1).tolist()
    
            # Create tensors to hold word predicion scores and alphas
            predictions = torch.zeros(batch_size, max(decode_lengths), vocab_size).to(device)
            alphas = torch.zeros(batch_size, max(decode_lengths), num_pixels).to(device)
    
            # At each time-step, decode by
            # attention-weighing the encoder's output based on the decoder's previous hidden state output
            # then generate a new word in the decoder with the previous word and the attention weighted encoding
            for t in range(max(decode_lengths)):
                batch_size_t = sum([l > t for l in decode_lengths])
                attention_weighted_encoding, alpha = self.attention(encoder_out[:batch_size_t],
                                                                    h[:batch_size_t])
                gate = self.sigmoid(self.f_beta(h[:batch_size_t]))  # gating scalar, (batch_size_t, encoder_dim)
                attention_weighted_encoding = gate * attention_weighted_encoding
                h, c = self.decode_step(
                    torch.cat([embeddings[:batch_size_t, t, :], attention_weighted_encoding], dim=1),
                    (h[:batch_size_t], c[:batch_size_t]))  # (batch_size_t, decoder_dim)
                preds = self.fc(self.dropout(h))  # (batch_size_t, vocab_size)
                predictions[:batch_size_t, t, :] = preds
                alphas[:batch_size_t, t, :] = alpha
    
            return predictions, encoded_captions, decode_lengths, alphas, sort_ind
    Further Reading
    a-PyTorch-Tutorial-to-Image-Captioning

    課題の実行過程と結果


    ピアセッション


    学習の回顧