前提・実現したいこと
深層学習でネットワークが異なる入力に対して、すべて同じ出力を返してしまう原因を知りたいです。
ネットワークの初期重みがすべて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を以下に示します。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/06/02 15:24 編集
2021/06/02 22:14