check, initialize and freeze parameters
37291 ワード
https://stackoverflow.com/questions/63785319/pytorch-torch-no-grad-versus-requires-grad-false
基本的なcodeから逐次漸進する.
transfer learning=freezeはいくつかの階層だと思ってもいいです
基本的に,転移学習とは,いわゆる性能が良い,すなわち学習の良いparameterを持つことである.その後は特定のlayerのみを学習する(微調整と見なすことができる).私が欲しいデータセットによって交換すればいいです.これはなぜ良いのか、以下のように説明できると思います.
時間コストが急激に減少すると.これはかなりのメリットです.この概念を最初に知ったとき、他のデータセットや分類のトレーニングパラメータまでsegmenationで使われていると思っていたのですが、これはなぜうまくやっているのか逆に邪魔になるのでしょうか.CNNの役割は低-高画素認識であり、low parameterだけを持っていれば、うまく特徴抽出ができると考えられます.だから合理的だ.
最も便利な方法
大きく二つの段階に分かればいいです.
まずinitial関数を作成します.
つまり、ドアと見なすことができる.追加
実際のモデルから初期化する方法.
デフォルトの初期化が良いことがわかります.
次に、
すなわち,上記の関数を用いてモデルに適用することができる.
勾配の有無
with torch.no_grad()
とrequires_grad = False
の違い(?)基本的なcodeから逐次漸進する.
transfer learning=freezeはいくつかの階層だと思ってもいいです
基本的に,転移学習とは,いわゆる性能が良い,すなわち学習の良いparameterを持つことである.その後は特定のlayerのみを学習する(微調整と見なすことができる).私が欲しいデータセットによって交換すればいいです.これはなぜ良いのか、以下のように説明できると思います.
時間コストが急激に減少すると.これはかなりのメリットです.この概念を最初に知ったとき、他のデータセットや分類のトレーニングパラメータまでsegmenationで使われていると思っていたのですが、これはなぜうまくやっているのか逆に邪魔になるのでしょうか.CNNの役割は低-高画素認識であり、low parameterだけを持っていれば、うまく特徴抽出ができると考えられます.だから合理的だ.
auto grad
については、すでに議論されています.1.パラメータ確認
import torch
import torch.nn as nn
train_input.shape
----------------------------------------
torch.Size([64, 3, 224, 224])
class test_model(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 30,
kernel_size = 7, stride=2, padding=10, bias = False)
self.conv2 = nn.Conv2d(in_channels = 30, out_channels = 30,
kernel_size = 3, stride=1, padding=10, bias = False)
def forward(self, inputs):
feature_map1 = self.conv1(inputs)
feature_map2 = self.conv2(feature_map1)
return feature_map2
モデル形状の確認import pytorch_model_summary
from torchinfo import summary
model = test_model().to(device)
x = train_input
print(pytorch_model_summary.summary(model, x, show_input=True))
print('!@#'*40)
summary(model, input_size = x.shape )
パラメータのチェックと抽出parameters={}
for n,i in enumerate(model.parameters()):
parameters[n] = i
print(n)
parameters.keys()
あるいは下の方が便利ですparameters={}
for n,i in model.named_parameters():
parameters[n] = i
parameters.keys()
違いは、モデルクラスから定義された名前です.快適.最も便利な方法
model.state_dict()
違いがあるだけです.state_dict()
はrequires_grad = False
です.2. parameter initialize
大きく二つの段階に分かればいいです.
まずinitial関数を作成します.
def initialize_weight(m):
if isinstance(m, nn.Conv2D):
nn.init.kaiming_uniform_(m.weight.data,nonlinearity='relu')
次にこの関数をモデルに適用すればよい.model.apply(initialize_weight)
このときapply
には、モデル内のlayerが回転していることがわかります.つまり、ドアと見なすことができる.
len(model.state_dict())
パラメータの合計model.state_dict().keys()
検索しやすいmodel.conv1.weight.shape
上のキーで確認parameter_test = torch.nn.parameter.Parameter(data = torch.zeros(32,1,3,3), requires_grad = True)
model.conv1.weight = parameter_test
parameterとして指定した場合、parameterに直接アクセスしてモデルを変更します.model.state_dict()
変更の確認
もうちょっと実際のモデルから初期化する方法.
class Flatten(nn.Module):
def forward(self, input):
return input.view(input.size(0), -1)
class test(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = conv_bn_relu(in_channel = 3, out_channel = 32, kernel = (3,3), s = (1,1), p = (1,1))
self.pool1 = nn.MaxPool2d(kernel_size=(2, 2))
self.conv2 = conv_bn_relu(in_channel = 32, out_channel = 32, kernel = (3,3), s = (1,1), p = (1,1))
self.pool2 = nn.MaxPool2d(kernel_size=(2, 2))
self.conv3 = conv_bn_relu(in_channel = 32, out_channel = 32, kernel = (3,3), s = (1,1), p = (1,1))
self.pool3 = nn.MaxPool2d(kernel_size=(2, 2))
self.conv4 = conv_bn_relu(in_channel = 32, out_channel = 32, kernel = (3,3), s = (1,1), p = (1,1))
self.pool4 = nn.MaxPool2d(kernel_size=(2, 2))
self.conv5 = conv_bn_relu(in_channel = 32, out_channel = 32, kernel = (3,3), s = (1,1), p = (1,1))
self.pool5 = nn.MaxPool2d(kernel_size=(2, 2))
self.flatten = Flatten()
self.fc1 = nn.Linear(32*3*3, 10)
self.fc2 = nn.Linear(10, 10)
def forward(self, x):
x = self.conv1(x)
x = self.pool1(x)
x = self.conv2(x)
x = self.pool2(x)
x = self.conv3(x)
x = self.pool3(x)
x = self.conv4(x)
x = self.pool4(x)
x = self.conv5(x)
x = self.pool5(x)
x = self.flatten(x)
return x
上記のモデルを作成します.model = test()
model.state_dict()
パラメータを確認します.デフォルトの初期化が良いことがわかります.
次に、
apply
を使用して関数を初期化します.def _initialize_weights(m):
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
テストがうまくいくかどうかをテストするためにconvのbias以外の部分だけを0にします.def _initialize_weights_test(m):
if isinstance(m, nn.Conv2d):
torch.nn.init.uniform_(m.weight, a=0.0, b=0.0)
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
model.apply(_initialize_weights_test)
model.state_dict()
正確にはconvの重量分(biasを除く)だけが0になっています.すなわち,上記の関数を用いてモデルに適用することができる.
3.freeze
勾配の有無
for n,i in enumerate(model.parameters()):
print(i.requires_grad)
gradを次のようにドラッグできます.for n,i in enumerate(model.parameters()):
if n == 0:
i.requires_grad = False
for i,j in model.named_parameters():
print(i,j.requires_grad)
Reference
この問題について(check, initialize and freeze parameters), 我々は、より多くの情報をここで見つけました https://velog.io/@jj770206/transfer-autograd를-중심으로テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol