pytorch 모델 복제의 일부 문제를 해결하다

7546 단어 pytorch모델복사

직접 사용


model2=model1
모델 2를 업데이트할 때 모델 1의 권한도 업데이트됩니다. 이것은 자신의 초기 목적과 다릅니다.

다음을 사용할 수 있습니다.


model2=copy.deepcopy(model1)
깊은 복사를 실현하기 위해pytorch 환경이 없습니다. 구체적으로 아직 테스트를 하지 않았습니다. 누가 테스트를 했는지 저에게 말해 주세요.

기본 방법:


모형 복사를 사용할 모든 방법은 다음과 같다.

torch.save(model, "net_params.pkl")
model5=Cnn(3,10)
model5=torch.load('net_params.pkl')
이렇게 작성하면 원시 모델의 무게에 영향을 주지 않는다
보충:pytorch모델 훈련절차에서 만나는 구덩이(지속 업데이트)
모형을 훈련하려면 주로 몇 부분으로 나뉘는데 다음과 같다.

데이터 사전 처리


입문하면 MNIST 필기 데이터 세트로 먼저 연습하는 게 틀림없어.
pytorch에는 데이터 생성기를 만드는 데 도움을 주는 모듈이 있습니다. 그 중에서 Dataset,Tensor Dataset,DataLoader 등 종류가 데이터 입구를 만들 수 있습니다.
이전에tensorflow에서 데이터 세트를 사용할 수 있었습니다.from_generator ()의 형식은pytorch에서도 유사합니다. 현재 제가 알고 있는 것은 두 가지 방법이 있습니다.
첫 번째는pytorch가 정의한 데이터셋을 계승하고 그 방법을 바꾸면 됩니다.DataLoader 생성기는 다음과 같습니다.

class MyDataset(Dataset):
 def __init__(self, data, labels):
 self.data = data
 self.labels = labels
 def __getitem__(self, index):
 return self.data[index], self.labels[index]
 def __len__(self):
 return len(self.labels)
 
train_dataset = MyDataset(train_data, train_label)
train_loader = DataLoader(dataset = train_dataset,
 batch_size = 1,
 shuffle = True)
두 번째는 전환이다. 먼저 우리가 준비한 데이터를pytorch의 변수(또는 Tensor)로 바꾸고 Tensor Dataset에 전송한 다음에 DataLoader를 구성한다.

X = torch.from_numpy(train_data).float()
Y = torch.from_numpy(train_label).float()
train_dataset = TensorDataset(X, Y)
 
train_loader = DataLoader(dataset = train_dataset,
 batch_size = 1,
 shuffle = True)
 #num_workers = 2)

모델 정의


class Net(nn.Module):
 
 def __init__(self):
 super(Net, self).__init__()
 self.conv1 = nn.Conv2d(1, 6, 3)
 self.conv2 = nn.Conv2d(6 ,16, 3)
 
 self.fc1 = nn.Linear(400, 120)
 self.fc2 = nn.Linear(120, 84)
 self.fc3 = nn.Linear(84, 10)
 
 def forward(self, x):
 relu = F.relu(self.conv1(x))
 x = F.max_pool2d(relu, (2, 2))
 x = F.max_pool2d(F.relu(self.conv2(x)), 2)
 x = x.view(-1, self.num_flat_features(x))
 x = F.relu(self.fc1(x))
 x = F.relu(self.fc2(x))
 x = self.fc3(x)
 
 return x 
 def num_flat_features(self, x):
 size = x.size()[1:] # batch_size 
 num_features = 1
 for s in size:
 num_features *= s
 return num_features
훈련 모델은 반드시 먼저 하나의 네트워크 구조를 정의해야 한다. 예를 들어 위에서 전방향 전파 네트워크를 정의한다.안에 권적층, 전연결층, 최대지화층과relu비선형활성층(이름은 내가 지었다)과 하나의view를 포함하여 다차원적 특징도를 1차원으로 평평하게 전개한다.
그중 nn.Conv2d(in_channels, out_channels,kernel_size), 첫 번째 매개 변수는 입력의 깊이, 두 번째는 출력의 깊이, 세 번째는 볼륨 핵의 크기입니다.
F.max_pool2d(input,(pool_size,pool_size)), 두 번째 매개 변수는 풀화입니다.
nn.Linear(in_features, out_features)
x.view는 평평한 조작이지만 실제로는numpy의reshape에 해당하며 변환된 사이즈를 계산해야 합니다.

손실 함수 정의


import torch.optim as optim
 
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
모델이 정의된 후에 입력을 하면 출력의 결과를 얻을 수 있다는 것을 의미한다.그러면 outputs와 targets 간의 차이를 비교하려면 손실 함수로 설명해야 합니다.

훈련 네트워크


for epoch in range(2): # loop over the dataset multiple times
 
 running_loss = 0.0
 for i, data in enumerate(trainloader, 0):
 # get the inputs; data is a list of [inputs, labels]
 inputs, labels = data
 
 # zero the parameter gradients
 optimizer.zero_grad()
 
 # forward + backward + optimize
 outputs = net(inputs)
 loss = criterion(outputs, labels)
 loss.backward()
 optimizer.step()
 
 # print statistics
 running_loss += loss.item()
 if i % 2000 == 1999: # print every 2000 mini-batches
  print('[%d, %5d] loss: %.3f' %
   (epoch + 1, i + 1, running_loss / 2000))
  running_loss = 0.0
 
print('Finished Training')
이상의 코드는 공식 강좌에서 나온 것으로 우리가 해야 할 일은 그의 사고방식을 배우는 것이다.
1. 우선 epoch의 수량은 2이고 epoch마다 전체 훈련집을 한 번씩 훑어본다.epoch마다 누적 통계running_loss, 2000개의batch 데이터마다 손실의 평균치를 계산한 다음print에서 다시 running_loss를 0으로 설정합니다.
2. 그리고 미니-batch로 나누어 훈련을 실시한다. 모든 미니-batch의 손실을 계산하기 전에 최적화기optimizer의 사다리를 비우고 서로 다른 미니-batch의 사다리가 누적되는 것을 방지한다.업데이트는 두 단계로 나뉜다. 첫 번째 단계는 손실 함수를 계산한 다음에 전체 손실을 각 층에 분배한다. 즉loss이다.backward (), 그리고 최적화기 업데이트 권한, 즉optimizer를 사용합니다.step().

모델 저장


PATH = '...'
torch.save(net.state_dict(), PATH)

구덩이를 기어다니며 정리하다.


전체적으로 말하자면 절차는 바로 위의 몇 걸음이지만 자신이 할 때 매우 많은 문제에 부딪혔다. 가장 중요한 것은 그 중에서 장량 전파 과정에서의 요구가 명확하지 않아서 적지 않은 착오를 초래했다.
먼저 입력한 데이터입니다.pytorch 기본 그림의batch 데이터의 구조는(BATCH_SIZE,CHANNELS,IMG_H,IMG_W)입니다. 따라서 데이터를 생성할 때 이러한 BCHW의 규칙을 충족시키기 위해 조정해야 합니다.
"Runtime Error: Expected object of scalar type Double but got scalar type Float for argument #2'mat2'와 같은 오류 메시지가 자주 나타납니다.
x.double (), y.float (), z.long () 등의 방식으로 그가 요구하는 형식으로 변환할 수 있습니다.
RuntimeError: multi-target not supported.이 오류는 손실 함수에 나타나는데 분류 문제에 대해 교차 엔트로피를 우선적으로 고려하는 것이 틀림없다.

criterion = nn.CrossEntropyLoss()
loss = criterion(outputs, labels.long())# 
내가batch-size=1일 때 이곳은 틀리지 않지만,batch-size>1일 때 틀리지 않습니다.
다른 사람의 코드를 찾았는데 모두들 기본적으로 공식 강좌에 쓴 것과 같이 공식 mnist 데이터 인터페이스를 사용했는데 코드는 다음과 같다.처음에 나는 원하지 않았다. 왜냐하면 그 모양은 데이터 형식이 봉인되어 보이지 않을 수도 있다는 것을 의미하기 때문이다. 그러나 스스로 괴롭히는 비용이 비교적 높기 때문에 그래도 해 보았다. 정말 향기롭다!

train_dataset = datasets.MNIST(root='./data/',
    train=True,
    transform=transforms.ToTensor(),
    download=True)
train_loader = DataLoader(dataset = train_dataset,
  batch_size = 4,
  shuffle = True)
생성기에서 얻은 데이터를 출력하고size를 보니 역시 내가 쓴 것과 다르다.당batch_size=4시, 데이터 데이터.size()는 모두 4*1*28*28입니다. 이것은 같습니다.하지만 라벨.size()는 다르다. 나는 one_hot 벡터는 4*10이지만 4입니다.
직접 labels를 인쇄해 보세요. 역시, 단일한 손가락입니다. 예를 들어tensor([3, 2, 6, 2])와 같습니다.
그러나 모델의 outputs는 여전히 4*10입니다. 보아하니 nn입니다.Cross Entropy Loss () 함수는 스스로 계산을 하기 때문에 multi-target not supported를 lables 때문에 잘못 보고한 것입니다.size () 아니요. 원래 숫자가 하나밖에 없었는데 지금은 10개의 숫자입니다. 10개의 속성이 분배된 셈입니다. 자연히 틀렸습니다.
그래서 자기가 쓴 생성기를 살짝 수정하면 괜찮아요.
그러나 더 자유롭게 데이터를 호출하려면 대상에 대한 재부팅이 필요합니다.pytoch가 정의한 DataLoader를 사용하고enumerate를 사용하면 모든 데이터를 한 번씩 훑어보며,iter()를 사용하여 교체 가능한 대상을 얻은 후next()를 사용하면tensorflow처럼 훈련 데이터를 만들 수 없습니다.
예를 들어 위와 같은 형식을 사용한다면 DataLoader는 생성기를 얻을 수 있으며, python의 생성기 대상은 주로 __next__ 및 __iter__ 마술 방법이 결정되면
__iter__ 방법은 실례를 다음과 같이 호출할 수 있고 교체 가능한 대상,iterable를 얻을 수 있지만 추가하지 않아도 됩니다. 왜냐하면 더 중요한 것은 __next__ 유형 방법.
다음은 __next__ 방법 이후에 볼 수 있듯이 원래는 경계를 넘는 현상이 나타나지 않고 순환할 수 있는 모든 데이터를 볼 수 있다. 물론 주석된 부분처럼 StopIteration을 던져서 중지할 수도 있다.

a = A()
a_iter = iter(a)
class A():
 def __init__(self):
 self.list = [1,2,3]
 self.index = 0
 #def __getitem__(self, index):
 # return self.list[i]
 #def __iter__(self):
 # return self
 def __next__(self):
 #for i in range():
 if self.index >= len(self.list):
 #raise StopIteration 
 self.index = self.index%len(self.list)
 result = self.list[self.index]
 self.index += 1
 return result 
b = A() 
for i in range(20):
 print(next(b))
 
이상의 개인적인 경험으로 여러분께 참고가 되었으면 좋겠습니다. 또한 많은 응원 부탁드립니다.만약 잘못이 있거나 완전한 부분을 고려하지 않으신다면 아낌없이 가르침을 주시기 바랍니다.

좋은 웹페이지 즐겨찾기