質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Q&A

解決済

1回答

1220閲覧

ネットワークの出力がすべて同じになる 深層学習

1236

総合スコア19

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

0グッド

0クリップ

投稿2021/05/28 14:07

前提・実現したいこと

深層学習でネットワークが異なる入力に対して、すべて同じ出力を返してしまう原因を知りたいです。

ネットワークの初期重みがすべて0になっているのではないかと思いましたが、確認したところ0にはなっていないです。(確認の仕方が間違っているかも?)

ネットワークの重み初期化は行っていないのですが、初期化をしなかった場合デフォルトで重みが0になっていたりしますか?調べたところそのようにはなっていないと思いますが。

以下に抜粋したソースコードを示します。

該当のソースコード

python

1# インデントずれているかもしれませんが気にしないでください。 2# model 3class EncoderBlock(nn.Module): 4 def __init__(self, in_feature, out_feature): 5 super(EncoderBlock, self).__init__() #継承 6 self.in_feature = in_feature 7 self.out_feature = out_feature 8 9 layers = [] 10 layers.append(nn.Conv2d(in_channels=in_feature, out_channels=out_feature, kernel_size=3, stride=1, padding=1)) 11 layers.append(nn.BatchNorm2d(out_feature)) 12 layers.append(nn.ReLU(inplace=True)) 13 self.block = nn.Sequential(*layers) 14 def forward(self, x): 15 return self.block(x) 16 17class Encoder(nn.Module): 18 def __init__(self, dim): 19 super(Encoder, self).__init__() 20 21 self.conv1 = EncoderBlock(3 , dim) 22 self.conv2 = EncoderBlock(dim, dim) 23 self.conv3 = EncoderBlock(dim, dim) 24 self.conv4 = EncoderBlock(dim, dim*2) 25 self.conv5 = EncoderBlock(dim*2, dim*2) 26 self.conv6 = EncoderBlock(dim*2, dim*2) 27 self.conv7 = EncoderBlock(dim*2, dim*4) 28 self.conv8 = EncoderBlock(dim*4, dim*4) 29 self.conv9 = EncoderBlock(dim*4, dim*4) 30 self.pool = nn.MaxPool2d(kernel_size=2) 31 32 def forward(self, x): 33 out = self.conv1(x) 34 out = self.conv2(out) 35 out = self.conv3(out) 36 out = self.pool(out) 37 38 out = self.conv4(out) 39 out = self.conv5(out) 40 out = self.conv6(out) 41 out = self.pool(out) 42 43 out = self.conv7(out) 44 out = self.conv8(out) 45 out = self.conv9(out) 46 out = self.pool(out) 47 48 return out 49 50class Classifier(nn.Module): 51 def __init__(self, class_num, enc_dim, rep_dim, in_w, in_h): 52 super(Classifier, self).__init__() 53 54 self.enc_dim = enc_dim 55 self.rep_dim = rep_dim 56 self.in_w = in_w 57 self.in_h = in_h 58 self.fc_dim = enc_dim*4 * int(in_h/2/2/2) * int(in_w/2/2/2) # 次元を合わせる(プーリング3回とdim*2を2回) 59 60 self.Encoder = Encoder(self.enc_dim) 61 self.fc1 = nn.Linear(self.fc_dim, 512) 62 self.fc2 = nn.Linear(512, 512) 63 self.fc3 = nn.Linear(512, self.rep_dim) 64 65 def forward(self, x): 66 out = self.Encoder(x) 67 out = out.view(-1, self.fc_dim) 68 out = F.relu(self.fc1(out)) 69 out = F.relu(self.fc2(out)) 70 out = self.fc3(out) 71 return out 72 73 74# Classifarは結局はほぼVGGです(fc2, fc3だけ変更してます) 75 net = Classifier(class_num=2, enc_dim=batch_size, rep_dim=512, in_w=32, in_h=32).to(device) 76 77# load datasets 78 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4, drop_last=True) 79 80 81 def init_center_c(loader, net, eps=0.1): 82 ''' initialing center c ''' 83 n_samples = 0 84 c = torch.zeros(net.rep_dim, device=device) # (0, 0, ..., 0) rep_dim個 85 86 net.eval() 87 with torch.no_grad(): 88 for data in train_loader: 89 inputs, _, _ = data 90 inputs = inputs.to(device) 91 outputs = net(inputs) 92 n_samples += outputs.shape[0] 93 94 print('shape: ', outputs.shape[0]) 95 print(outputs.size()) 96 print(outputs.dim()) 97 print(inputs) 98 print("########") #####異なる入力に対して出力が全部同じ 99 print(outputs) 100 101 c += torch.sum(outputs, dim=0) 102 103 c /= n_samples 104 #print("c: ", c) 105 # If c_i is too close to 0, set to +-eps. 106 # Reason: a zero unit can be trivially matched with zero weights. 107 c[(abs(c) < eps) & (c < 0)] = -eps 108 c[(abs(c) < eps) & (c > 0)] = eps 109 110 return c 111 112 113  c = init_center_c(train_loader, net) 114 115

補足

私は今Deep SVDD(データを超球に射影する)を自分でプログラムを書こうと思っています。その過程でネットワークを訓練する前にまず、訓練前のネットワークにデータを入力しその出力の平均を超球の中心とする初期化が必要で、ini_center_cを実行してます。ここのprint(outputs)がすべて同じ出力になってしまう原因を知りたいです。訓練段階においてvalidationによる評価を行っているのですが、そこではoutputsは異なる出力をします。
ini_center_cのoutputsを以下に示します。
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

なぜかEncoderのチャネルサイズを表すenc_dimにバッチサイズを与えてしまっており、Encoderを通した結果が「つぶれて」しまっているようです。(batch_size = 1〜128を想定)

Python

1net = Classifier(class_num=2, enc_dim=batch_size, rep_dim=512, in_w=32, in_h=32).to(device)

以下のようにすることで改善されると思います。(手元の再現では、画像によって出力が変わるようになりました)

Python

1net = Classifier(class_num=2, enc_dim=512, rep_dim=512, in_w=32, in_h=32).to(device)

なお、Encoderのブロックの層を減らすと、より顕著に差異が出るようになります。

投稿2021/05/31 23:08

toast-uz

総合スコア3266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

1236

2021/06/02 15:24 編集

返信遅くなり申し訳ございません。 出力が同じになってしまう理由は分かりました! - Encoderのブロックの層を減らすと、より顕著に差異が出るようになる とはどういう意味でしょうか? 異なる入力に対して出力に差異がでるという意味でしょうか? そうだとしたらそれは何故でしょうか? 私の理解では層が深いほどより細かな特徴を得るので出力に差異が出やすいと考えていました。 それともDeep SVDDの場合の話でしょうか?そうであれば納得です。
toast-uz

2021/06/02 22:14

何がこの現象に影響を与えているのかの切り分けの1つとして、入口と出口のチャネル数は変えないように、conv1、conv4、conv7だけ残して他のconvを削除してみました。すると、結果の差異が際立ちました。これは実際に試した結果です。 理由はわかりませんが、おそらくVGG系特有の勾配消失で、層が深くなると扱いにくいのかと思いました。ちょっとあやふやなので違うかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問