Prototypical Networks (Prototypical Networks) の完全なプロセスの説明

プロトタイプネットワーク

1. 基本的な紹介

1.1 このセクションでは以下を紹介します

前回の記事では、Siamese ネットワークに関する関連概念を紹介し、Pytorchを使用して実装された Siamese ネットワークに基づく顔認識ネットワークの小さなサンプルの学習プロセスを示しました。次のコンテンツでは、小規模サンプル学習プロトタイプ ネットワーク用の別のニューラル ネットワーク構造を引き続き紹介します。このネットワークは、現在のデータセットのみに適用できない一般的な分類機能を特徴としています。以下では、次のことについて説明します。

  1. プロトタイプネットワークの基本構造。
  2. プロトタイプのネットワーク アルゴリズムの説明。
  3. プロトタイプ ネットワークの分類タスクへの適用。

1.2 プロトタイプネットワークの紹介

シャム ネットワークと比較して、プロトタイプ ネットワークは、小さなサンプルに対するもう 1 つのシンプルで効率的な学習方法です。シャム ネットワークの学習目標と似ています。プロトタイプ ネットワークの目標は、テキスト分類タスクのためのベクトル空間を学習することでもあります。

プロトタイプ ネットワークの基本的な考え方は、カテゴリごとにプロトタイプ表現 (protoypicla 表現) を作成することです。また、分類する必要があるクエリについては、分類のプロトタイプ ベクトルとクエリ点の間の距離を計算することによって決定されます。

基本的なアイデアを決定した後、プロトタイプ ネットワークを詳細に説明する例から始めます。

2 プロトタイプネットワーク

2.1 例から始める

ライオン、ゾウ、犬の絵が入ったサポートセット(サポートセット)が登場しました。つまり、分類タスクには、{ライオン、ゾウ、犬} の合計 3 つのカテゴリがあります。ここで、各カテゴリのプロトタイプ表現を作成する必要があります。設立の基本的なプロセスは次の図に示されています。

  1. まず、各サンプルの符号化手法 fφ() を用いて、各サンプルの符号化表現を学習します(情報抽出)。たとえば、畳み込み演算を使用して画像符号化情報の抽出を実現できます。
    ここに画像の説明を挿入
  2. 各サンプルのコード表現を学習した後、各カテゴリにあるすべてのサンプルのコードを合計して平均し、その結果を分類のプロトタイプ表現として使用します。したがって、分類プロトタイプは、ベクトルの合計と平均のプロセスを使用して表されます。
    ここに画像の説明を挿入

新しいデータ サンプルがネットワークに入力されると、必要なのは、このサンプルの分類を予測することです。
3. 最初のステップでは、この新しいデータ サンプルに対して fφ() を使用して、そのエンコードされた表現を生成します。以下の図に示すように:
ここに画像の説明を挿入
4. 次に、新しいサンプルのエンコードされた表現と各カテゴリのプロトタイプ表現の間の距離を計算し、最小距離を使用してクエリ サンプルがどのカテゴリに属する​​かを決定する必要があります。に。距離の計算には特別な要件はなく、ユークリッド距離やCos類似度などの計算方法を使用できます。
ここに画像の説明を挿入

  1. 最後に、すべてのカテゴリ間の距離を計算した後、ソフトマックスを使用して距離を確率形式に変換します。3 つのカテゴリがあるため、サンプルのソフトマックス後に得られるのは、これら 3 つのカテゴリ間の距離です。

このセクションの最後で、学習プロセスに戻ります。ネットワークに小さなサンプルデータセットから学習させたいと考えています。したがって、トレーニング中に、カテゴリごとに少数のサンプルをランダムに生成し、これらの小さなサンプル セットをサポート セットとして使用します。トレーニング プロセス全体では、サポート セットのみを使用する必要があります。すべてのデータセットが必要なわけではありません。同様に、データセットからサンプルをクエリポイントとしてランダムに抽出し、分類します。これで、小さなサンプルから学習する方法が完了しました。

2.2 プロトタイプネットワークの全体的なアーキテクチャ

まず、プロトタイプ ネットワークの全体的なアーキテクチャ図を示します。

ここに画像の説明を挿入

このネットワーク構造をアーキテクチャ全体から分析してみましょう。

  1. 最初のステップでは、サポート セット内の各サンプル ポイントのエンコードされた表現を生成し、合計と平均によって各カテゴリのプロトタイプ表現を生成します。同時に、クエリ サンプルのベクトル表現も生成します。
  2. 同時に、各クエリ ポイントと各分類プロトタイプ表現の間の距離を計算する必要があります。そしてソフトマックス確率の結果を計算します。各クラスの確率分布を生成します。

さらに、プロトタイプネットワークの場合、その適用範囲は単一サンプル/小サンプル学習プロセスだけでなく、ゼロサンプル学習方法にも適用されます。この種のアプリケーションのアイデアは次のとおりです。現在の分類のデータ サンプルはありませんが、より高いレベルで分類のプロトタイプ表現 (メタ情報) を生成できれば。このメタ情報を通じて、上記と同様の計算を実行して、分類タスクを完了することもできます。

2.3 アルゴリズムの説明

ここでは、ネットワーク構造と数式を組み合わせて、プロトタイプ ネットワークのアルゴリズムを説明します。

  1. 現在のデータセットが D で、その内部サンプルの表現が {(x_1,y_1),(x_2,y_2),....,(x_n,y_n)} であるとします。ここで、x はベクトル表現を表し、y は次のことを表します分類カテゴリラベル。
  2. カテゴリごとに、サンプル セット全体から n 個のサンプル ポイントをランダムに生成し、カテゴリごとに最終サポート セットを S として生成します。
  3. 同様に、サンプル セット全体からカテゴリごとに n 個のサンプル ポイントをランダムに選択して、クエリ セット Q を生成します。
  4. サポート セット内のサンプル ポイントについては、エンコード式 fφ を使用してカテゴリごとにプロトタイプ表現を生成します。エンコード式 fφ には任意の情報抽出方法を使用できます。CNN、LSTM など。
  5. カテゴリごとに、次のようにプロトタイプ表現を生成します。

ここに画像の説明を挿入

  1. 同様に、クエリセットのクエリセット エンコーディングも生成します。
  2. さらに、計算する必要があるのは、クエリ セットとサポート セットのプロトタイプ表現の間の距離です。
  3. 最後に計算する必要があるのは、現在のサンプルが各カテゴリに属する​​確率 pw(y=k|x) であり、ここではソフトマックスの計算方法が使用されます。

ここに画像の説明を挿入
9. 最後に、損失関数を次のように計算します。

ここに画像の説明を挿入

2.4 コードの説明

ここでは、単純なコメント データ セットをカスタマイズすることを選択します。合計 2 つのカテゴリがあります。各カテゴリの下に 5 つのデータがあります。各カテゴリについて、サポート セットとして 3 つ、クエリ セットとして 3 つを選択します。具体的な実装は次のとおりです。以下に続きます:

#encoding=utf-8

import torch
import torch.nn as nn
import torch.nn.functional as F
import jieba
import random
import torch.optim as optim


def createData():
    text_list_pos = ["电影内容很好","电影题材很好","演员演技很好","故事很感人","电影特效很好"]
    text_list_neg = ["电影内容垃圾","电影是真的垃圾","表演太僵硬了","故事又臭又长","电影太让人失望了"]
    test_pos = ["电影","很","好"]
    test_neg = ["电影","垃圾"]
    words_pos = [[item for item in jieba.cut(text)] for text in text_list_pos]
    words_neg = [[item for item in jieba.cut(text)] for text in text_list_neg]
    words_all = []
    for item in words_pos:
        for key in item:
            words_all.append(key)
    for item in words_neg:
        for key in item:
            words_all.append(key)
    vocab = list(set(words_all))
    word2idx = {w:c for c,w in enumerate(vocab)}
    idx_words_pos = [[word2idx[item] for item in text] for text in words_pos]
    idx_words_neg = [[word2idx[item] for item in text] for text in words_neg]
    idx_test_pos = [word2idx[item] for item in test_pos]
    idx_test_neg = [word2idx[item] for item in test_neg]
    return vocab,word2idx,idx_words_pos,idx_words_neg,idx_test_pos,idx_test_neg
def createOneHot(vocab,idx_words_pos,idx_words_neg,idx_test_pos,idx_test_neg):
    input_dim = len(vocab)
    features_pos = torch.zeros(size=[len(idx_words_pos),input_dim])
    features_neg = torch.zeros(size=[len(idx_words_neg), input_dim])
    for i in range(len(idx_words_pos)):
        for j in idx_words_pos[i]:
            features_pos[i,j] = 1.0

    for i in range(len(idx_words_neg)):
        for j in idx_words_neg[i]:
            features_neg[i,j] = 1.0
    features = torch.cat([features_pos,features_neg],dim=0)
    labels = [1,1,1,1,1,0,0,0,0,0]
    labels = torch.LongTensor(labels)
    test_x_pos = torch.zeros(size=[1,input_dim])
    test_x_neg = torch.zeros(size=[1,input_dim])
    for item in idx_test_pos:
        test_x_pos[0,item] = 1.0
    for item in idx_test_neg:
        test_x_neg[0,item] = 1.0
    test_x = torch.cat([test_x_pos,test_x_neg],dim=0)
    test_labels = torch.LongTensor([1,0])
    return features,labels,test_x,test_labels
def randomGenerate(features):
    N = features.shape[0]
    half_n = N // 2
    support_input = torch.zeros(size=[6, features.shape[1]])
    query_input = torch.zeros(size=[4,features.shape[1]])
    postive_list = list(range(0,half_n))
    negtive_list = list(range(half_n,N))
    support_list_pos = random.sample(postive_list,3)
    support_list_neg = random.sample(negtive_list,3)
    query_list_pos = [item for item in postive_list if item not in support_list_pos]
    query_list_neg = [item for item in negtive_list if item not in support_list_neg]
    index = 0
    for item in support_list_pos:
        support_input[index,:] = features[item,:]
        index += 1
    for item in support_list_neg:
        support_input[index,:] = features[item,:]
        index += 1
    index = 0
    for item in query_list_pos:
        query_input[index,:] = features[item,:]
        index += 1
    for item in query_list_neg:
        query_input[index,:] = features[item,:]
        index += 1
    query_label = torch.LongTensor([1,1,0,0])
    return support_input,query_input,query_label




class fewModel(nn.Module):
    def __init__(self,input_dim,hidden_dim,num_class):
        super(fewModel,self).__init__()
        self.input_dim = input_dim
        self.hidden_dim = hidden_dim
        self.num_class = num_class
        # 线性层进行编码
        self.linear = nn.Linear(input_dim,hidden_dim)


    def embedding(self,features):
        result = self.linear(features)
        return result

    def forward(self,support_input,query_input):

        support_embedding = self.embedding(support_input)
        query_embedding = self.embedding(query_input)
        support_size = support_embedding.shape[0]
        every_class_num  = support_size // self.num_class
        class_meta_dict = {}
        for i in range(0,self.num_class):
            class_meta_dict[i] = torch.sum(support_embedding[i*every_class_num:(i+1)*every_class_num,:],dim=0) / every_class_num
        class_meta_information = torch.zeros(size=[len(class_meta_dict),support_embedding.shape[1]])
        for key,item in class_meta_dict.items():
            class_meta_information[key,:] = class_meta_dict[key]
        N_query = query_embedding.shape[0]
        result = torch.zeros(size=[N_query,self.num_class])
        for i in range(0,N_query):
            temp_value = query_embedding[i].repeat(self.num_class,1)
            cosine_value = torch.cosine_similarity(class_meta_information,temp_value,dim=1)
            result[i] = cosine_value
        result = F.log_softmax(result,dim=1)
        return result

hidden_dim = 4
n_class = 2
lr = 0.01
epochs = 1000
vocab,word2idx,idx_words_pos,idx_words_neg,idx_test_pos,idx_test_neg = createData()
features,labels,test_x,test_labels = createOneHot(vocab,idx_words_pos,idx_words_neg,idx_test_pos,idx_test_neg)

model = fewModel(features.shape[1],hidden_dim,n_class)
optimer = optim.Adam(model.parameters(),lr=lr,weight_decay=5e-4)

def train(epoch,support_input,query_input,query_label):
    optimer.zero_grad()
    output = model(support_input,query_input)
    loss = F.nll_loss(output,query_label)
    loss.backward()
    optimer.step()
    print("Epoch: {:04d}".format(epoch),"loss:{:.4f}".format(loss))

if __name__ == '__main__':
    for i in range(epochs):
        support_input, query_input, query_label = randomGenerate(features)
        train(i,support_input,query_input,query_label)

プロトタイプネットワーク

1. 基本的な紹介

1.1 このセクションでは以下を紹介します

前回の記事では、Siamese ネットワークに関する関連概念を紹介し、Pytorchを使用して実装された Siamese ネットワークに基づく顔認識ネットワークの小さなサンプルの学習プロセスを示しました。次のコンテンツでは、小規模サンプル学習プロトタイプ ネットワーク用の別のニューラル ネットワーク構造を引き続き紹介します。このネットワークは、現在のデータセットのみに適用できない一般的な分類機能を特徴としています。以下では、次のことについて説明します。

  1. プロトタイプネットワークの基本構造。
  2. プロトタイプのネットワーク アルゴリズムの説明。
  3. プロトタイプ ネットワークの分類タスクへの適用。

1.2 プロトタイプネットワークの紹介

シャム ネットワークと比較して、プロトタイプ ネットワークは、小さなサンプルに対するもう 1 つのシンプルで効率的な学習方法です。シャム ネットワークの学習目標と似ています。プロトタイプ ネットワークの目標は、テキスト分類タスクのためのベクトル空間を学習することでもあります。

プロトタイプ ネットワークの基本的な考え方は、カテゴリごとにプロトタイプ表現 (protoypicla 表現) を作成することです。また、分類する必要があるクエリについては、分類のプロトタイプ ベクトルとクエリ点の間の距離を計算することによって決定されます。

基本的なアイデアを決定した後、プロトタイプ ネットワークを詳細に説明する例から始めます。

2 プロトタイプネットワーク

2.1 例から始める

ライオン、ゾウ、犬の絵が入ったサポートセット(サポートセット)が登場しました。つまり、分類タスクには、{ライオン、ゾウ、犬} の合計 3 つのカテゴリがあります。ここで、各カテゴリのプロトタイプ表現を作成する必要があります。設立の基本的なプロセスは次の図に示されています。

  1. まず、各サンプルの符号化手法 fφ() を用いて、各サンプルの符号化表現を学習します(情報抽出)。たとえば、畳み込み演算を使用して画像符号化情報の抽出を実現できます。
    ここに画像の説明を挿入
  2. 各サンプルのコード表現を学習した後、各カテゴリにあるすべてのサンプルのコードを合計して平均し、その結果を分類のプロトタイプ表現として使用します。したがって、分類プロトタイプは、ベクトルの合計と平均のプロセスを使用して表されます。
    ここに画像の説明を挿入

新しいデータ サンプルがネットワークに入力されると、必要なのは、このサンプルの分類を予測することです。
3. 最初のステップでは、この新しいデータ サンプルに対して fφ() を使用して、そのエンコードされた表現を生成します。以下の図に示すように:
ここに画像の説明を挿入
4. 次に、新しいサンプルのエンコードされた表現と各カテゴリのプロトタイプ表現の間の距離を計算し、最小距離を使用してクエリ サンプルがどのカテゴリに属する​​かを決定する必要があります。に。距離の計算には特別な要件はなく、ユークリッド距離やCos類似度などの計算方法を使用できます。
ここに画像の説明を挿入

  1. 最後に、すべてのカテゴリ間の距離を計算した後、ソフトマックスを使用して距離を確率形式に変換します。3 つのカテゴリがあるため、サンプルのソフトマックス後に得られるのは、これら 3 つのカテゴリ間の距離です。

このセクションの最後で、学習プロセスに戻ります。ネットワークに小さなサンプルデータセットから学習させたいと考えています。したがって、トレーニング中に、カテゴリごとに少数のサンプルをランダムに生成し、これらの小さなサンプル セットをサポート セットとして使用します。トレーニング プロセス全体では、サポート セットのみを使用する必要があります。すべてのデータセットが必要なわけではありません。同様に、データセットからサンプルをクエリポイントとしてランダムに抽出し、分類します。これで、小さなサンプルから学習する方法が完了しました。

2.2 プロトタイプネットワークの全体的なアーキテクチャ

まず、プロトタイプ ネットワークの全体的なアーキテクチャ図を示します。

ここに画像の説明を挿入

このネットワーク構造をアーキテクチャ全体から分析してみましょう。

  1. 最初のステップでは、サポート セット内の各サンプル ポイントのエンコードされた表現を生成し、合計と平均によって各カテゴリのプロトタイプ表現を生成します。同時に、クエリ サンプルのベクトル表現も生成します。
  2. 同時に、各クエリ ポイントと各分類プロトタイプ表現の間の距離を計算する必要があります。そしてソフトマックス確率の結果を計算します。各クラスの確率分布を生成します。

さらに、プロトタイプネットワークの場合、その適用範囲は単一サンプル/小サンプル学習プロセスだけでなく、ゼロサンプル学習方法にも適用されます。この種のアプリケーションのアイデアは次のとおりです。現在の分類のデータ サンプルはありませんが、より高いレベルで分類のプロトタイプ表現 (メタ情報) を生成できれば。このメタ情報を通じて、上記と同様の計算を実行して、分類タスクを完了することもできます。

2.3 アルゴリズムの説明

ここでは、ネットワーク構造と数式を組み合わせて、プロトタイプ ネットワークのアルゴリズムを説明します。

  1. 現在のデータセットが D で、その内部サンプルの表現が {(x_1,y_1),(x_2,y_2),....,(x_n,y_n)} であるとします。ここで、x はベクトル表現を表し、y は次のことを表します分類カテゴリラベル。
  2. カテゴリごとに、サンプル セット全体から n 個のサンプル ポイントをランダムに生成し、カテゴリごとに最終サポート セットを S として生成します。
  3. 同様に、サンプル セット全体からカテゴリごとに n 個のサンプル ポイントをランダムに選択して、クエリ セット Q を生成します。
  4. サポート セット内のサンプル ポイントについては、エンコード式 fφ を使用してカテゴリごとにプロトタイプ表現を生成します。エンコード式 fφ には任意の情報抽出方法を使用できます。CNN、LSTM など。
  5. カテゴリごとに、次のようにプロトタイプ表現を生成します。

Guess you like

Origin blog.csdn.net/weixin_50514171/article/details/125879940