다음을 통해 공유


PyTorch를 사용하여 데이터 분석 모델 학습

이 자습서의 이전 단계에서는 PyTorch를 사용하여 데이터 분석 모델을 학습하는 데 사용할 데이터 세트를 획득했습니다. 이제 이 데이터를 사용할 차례입니다.

PyTorch를 사용하여 데이터 분석 모델을 학습하려면 다음 단계를 완료해야 합니다.

  1. 데이터를 로드합니다. 이 자습서의 이전 단계를 완료했으면 이미 처리되어 있습니다.
  2. 신경망을 정의합니다.
  3. 손실 함수를 정의합니다.
  4. 학습 데이터에서 모델을 학습시킵니다.
  5. 테스트 데이터에서 네트워크를 테스트합니다.

신경망 정의

이 자습서에서는 세 개의 선형 계층을 사용하여 기본 신경망 모델을 빌드합니다. 모델의 구조는 다음과 같습니다.

Linear -> ReLU -> Linear -> ReLU -> Linear

선형 계층은 들어오는 데이터에 선형 변환을 적용합니다. 클래스 수에 해당하는 입력 기능 수와 출력 기능 수를 지정해야 합니다.

ReLU 계층은 들어오는 모든 기능을 0 이상으로 정의하는 활성화 함수입니다. 따라서 ReLU 계층이 적용될 때 0보다 작은 숫자는 0으로 변경되고, 나머지는 그대로 유지됩니다. 두 개의 숨겨진 계층에 활성화 계층을 적용하고 마지막 선형 계층에는 활성화를 적용하지 않을 것입니다.

모델 매개 변수

모델 매개 변수는 목표와 학습 데이터에 따라 달라집니다. 입력 크기는 모델을 제공하는 기능 수에 따라 달라집니다(이 경우 4). 세 가지 종류의 붓꽃이 있기 때문에 출력 크기는 3입니다.

3개의 선형 계층((4,24) -> (24,24) -> (24,3))이 있는 네트워크에는 744개의 가중치(96+576+72)가 있습니다.

lr(학습 속도)은 손실 그라데이션과 관련하여 네트워크의 가중치를 조정하는 정도에 대한 제어를 설정합니다. 이 값이 낮을수록 학습 속도가 느려집니다. 이 자습서에서는 lr을 0.01로 설정합니다.

네트워크는 어떻게 작동할까요?

여기서는 피드 전달 네트워크를 빌드합니다. 학습 프로세스 중에 네트워크는 모든 계층을 통해 입력을 처리하고, 손실을 계산하여 이미지의 예측 레이블이 올바른 레이블과 다른 정도를 파악하고, 그라데이션을 네트워크에 다시 전파하여 계층 가중치를 업데이트합니다. 방대한 입력 데이터 세트를 반복함으로써 네트워크는 최상의 결과를 얻기 위해 가중치를 설정하는 방법을 "학습"합니다.

정방향 함수는 손실 함수의 값을 계산하고, 역방향 함수는 학습 가능한 매개 변수의 그라데이션을 계산합니다. PyTorch를 사용하여 신경망을 만드는 경우 정방향 함수만 정의하면 됩니다. 역방향 함수는 자동으로 정의됩니다.

  1. 다음 코드를 Visual Studio의 DataClassifier.py 파일에 복사하여 모델 매개 변수와 신경망을 정의합니다.
# Define model parameters 
input_size = list(input.shape)[1]   # = 4. The input depends on how many features we initially feed the model. In our case, there are 4 features for every predict value  
learning_rate = 0.01 
output_size = len(labels)           # The output is prediction results for three types of Irises.  


# Define neural network 
class Network(nn.Module): 
   def __init__(self, input_size, output_size): 
       super(Network, self).__init__() 
        
       self.layer1 = nn.Linear(input_size, 24) 
       self.layer2 = nn.Linear(24, 24) 
       self.layer3 = nn.Linear(24, output_size) 


   def forward(self, x): 
       x1 = F.relu(self.layer1(x)) 
       x2 = F.relu(self.layer2(x1)) 
       x3 = self.layer3(x2) 
       return x3 
 
# Instantiate the model 
model = Network(input_size, output_size) 

또한 PC에서 사용 가능한 실행 디바이스를 기준으로 실행 디바이스를 정의해야 합니다. PyTorch에는 GPU 전용 라이브러리가 없지만 실행 디바이스를 수동으로 정의할 수 있습니다. 디바이스는 Nvidia GPU가 컴퓨터에 있으면 Nvidia GPU가 되고, 없으면 CPU가 됩니다.

  1. 다음 코드를 복사하여 실행 디바이스를 정의합니다.
# Define your execution device 
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 
print("The model will be running on", device, "device\n") 
model.to(device)    # Convert model parameters and buffers to CPU or Cuda 
  1. 마지막 단계로 모델을 저장하는 함수를 정의합니다.
# Function to save the model 
def saveModel(): 
    path = "./NetModel.pth" 
    torch.save(model.state_dict(), path) 

참고 항목

PyTorch를 사용하는 신경망에 대해 자세히 알아보고 싶은가요? PyTorch 설명서를 확인하세요.

손실 함수 정의

손실 함수는 출력이 대상과 다른 정도를 예측하는 값을 계산합니다. 주요 목표는 신경망의 역방향 전파를 통해 가중치 벡터 값을 변경하여 손실 함수의 값을 줄이는 것입니다.

손실 값은 모델 정확도와 다릅니다. 손실 함수는 학습 세트에서 최적화를 반복할 때마다 모델이 얼마나 잘 작동하는지 나타냅니다. 모델의 정확도는 테스트 데이터에서 계산되며 정확한 예측의 백분율을 보여줍니다.

PyTorch에서 신경망 패키지에는 심층 신경망의 구성 요소를 구성하는 다양한 손실 함수가 포함되어 있습니다. 이러한 세부 사항에 대해 자세히 알아보려면 위의 참고 사항부터 시작하세요. 여기서는 이와 같이 분류에 최적화된 기존 함수를 사용하고 Classification Cross-Entropy 손실 함수와 Adam 최적화 프로그램을 사용하겠습니다. 최적화 프로그램에서 lr(학습 속도)은 손실 그라데이션과 관련하여 네트워크의 가중치를 조정하는 정도에 대한 제어를 설정합니다. 여기서는 0.001로 설정합니다. 낮을수록 학습 속도가 느려집니다.

  1. Visual Studio에서 손실 함수 및 최적화 도구를 정의하는 다음 코드를 DataClassifier.py 파일에 복사합니다.
# Define the loss function with Classification Cross-Entropy loss and an optimizer with Adam optimizer
loss_fn = nn.CrossEntropyLoss()
optimizer = Adam(model.parameters(), lr=0.001, weight_decay=0.0001)

학습 데이터에서 모델을 학습시킵니다.

모델을 학습시키려면 데이터 반복기를 반복하고, 입력을 네트워크에 공급하고, 최적화해야 합니다. 결과의 유효성을 검사하려면 예측 레이블을 모든 학습 Epoch 이후 유효성 검사 데이터 세트의 실제 레이블과 비교하면 됩니다.

프로그램은 학습 세트에 걸친 모든 Epoch 또는 모든 전체 반복에 대해 학습 손실, 유효성 검사 손실 및 모델의 정확도를 표시합니다. 가장 높은 정확도로 모델을 저장하고 10번의 Epoch 후에 프로그램이 최종 정확도를 표시합니다.

  1. 다음 코드를 DataClassifier.py 파일에 추가합니다.
# Training Function 
def train(num_epochs): 
    best_accuracy = 0.0 
     
    print("Begin training...") 
    for epoch in range(1, num_epochs+1): 
        running_train_loss = 0.0 
        running_accuracy = 0.0 
        running_vall_loss = 0.0 
        total = 0 
 
        # Training Loop 
        for data in train_loader: 
        #for data in enumerate(train_loader, 0): 
            inputs, outputs = data  # get the input and real species as outputs; data is a list of [inputs, outputs] 
            optimizer.zero_grad()   # zero the parameter gradients          
            predicted_outputs = model(inputs)   # predict output from the model 
            train_loss = loss_fn(predicted_outputs, outputs)   # calculate loss for the predicted output  
            train_loss.backward()   # backpropagate the loss 
            optimizer.step()        # adjust parameters based on the calculated gradients 
            running_train_loss +=train_loss.item()  # track the loss value 
 
        # Calculate training loss value 
        train_loss_value = running_train_loss/len(train_loader) 
 
        # Validation Loop 
        with torch.no_grad(): 
            model.eval() 
            for data in validate_loader: 
               inputs, outputs = data 
               predicted_outputs = model(inputs) 
               val_loss = loss_fn(predicted_outputs, outputs) 
             
               # The label with the highest value will be our prediction 
               _, predicted = torch.max(predicted_outputs, 1) 
               running_vall_loss += val_loss.item()  
               total += outputs.size(0) 
               running_accuracy += (predicted == outputs).sum().item() 
 
        # Calculate validation loss value 
        val_loss_value = running_vall_loss/len(validate_loader) 
                
        # Calculate accuracy as the number of correct predictions in the validation batch divided by the total number of predictions done.  
        accuracy = (100 * running_accuracy / total)     
 
        # Save the model if the accuracy is the best 
        if accuracy > best_accuracy: 
            saveModel() 
            best_accuracy = accuracy 
         
        # Print the statistics of the epoch 
        print('Completed training batch', epoch, 'Training Loss is: %.4f' %train_loss_value, 'Validation Loss is: %.4f' %val_loss_value, 'Accuracy is %d %%' % (accuracy))

테스트 데이터에 대한 모델 테스트

이제 모델을 학습했으므로 테스트 데이터 세트를 통해 모델을 테스트할 수 있습니다.

두 개의 테스트 함수를 추가하겠습니다. 첫 번째는 이전 파트에서 저장한 모델을 테스트합니다. 45개 항목의 테스트 데이터 세트로 모델을 테스트하고 모델의 정확도를 출력합니다. 두 번째는 세 가지 붓꽃 종 중에서 각 종을 성공적으로 분류하는 확률을 예측하는 모델의 신뢰도를 테스트하는 선택적 함수입니다.

  1. 파일에 다음 코드를 추가합니다 DataClassifier.py .
# Function to test the model 
def test(): 
    # Load the model that we saved at the end of the training loop 
    model = Network(input_size, output_size) 
    path = "NetModel.pth" 
    model.load_state_dict(torch.load(path)) 
     
    running_accuracy = 0 
    total = 0 
 
    with torch.no_grad(): 
        for data in test_loader: 
            inputs, outputs = data 
            outputs = outputs.to(torch.float32) 
            predicted_outputs = model(inputs) 
            _, predicted = torch.max(predicted_outputs, 1) 
            total += outputs.size(0) 
            running_accuracy += (predicted == outputs).sum().item() 
 
        print('Accuracy of the model based on the test set of', test_split ,'inputs is: %d %%' % (100 * running_accuracy / total))    
 
 
# Optional: Function to test which species were easier to predict  
def test_species(): 
    # Load the model that we saved at the end of the training loop 
    model = Network(input_size, output_size) 
    path = "NetModel.pth" 
    model.load_state_dict(torch.load(path)) 
     
    labels_length = len(labels) # how many labels of Irises we have. = 3 in our database. 
    labels_correct = list(0. for i in range(labels_length)) # list to calculate correct labels [how many correct setosa, how many correct versicolor, how many correct virginica] 
    labels_total = list(0. for i in range(labels_length))   # list to keep the total # of labels per type [total setosa, total versicolor, total virginica] 
  
    with torch.no_grad(): 
        for data in test_loader: 
            inputs, outputs = data 
            predicted_outputs = model(inputs) 
            _, predicted = torch.max(predicted_outputs, 1) 
             
            label_correct_running = (predicted == outputs).squeeze() 
            label = outputs[0] 
            if label_correct_running.item():  
                labels_correct[label] += 1 
            labels_total[label] += 1  
  
    label_list = list(labels.keys()) 
    for i in range(output_size): 
        print('Accuracy to predict %5s : %2d %%' % (label_list[i], 100 * labels_correct[i] / labels_total[i])) 

마지막으로, 주 코드를 추가해 보겠습니다. 그러면 모델 학습이 시작되고, 모델이 저장되며, 결과가 화면에 표시됩니다. 학습 세트에 대해 두 번의 반복([num_epochs = 25])만 실행하므로 학습 프로세스가 너무 오래 걸리지 않습니다.

  1. 파일에 다음 코드를 추가합니다 DataClassifier.py .
if __name__ == "__main__": 
    num_epochs = 10
    train(num_epochs) 
    print('Finished Training\n') 
    test() 
    test_species() 

테스트를 실행해 보겠습니다! 위쪽 도구 모음의 드롭다운 메뉴가 Debug로 설정되어 있는지 확인합니다. 디바이스가 64비트이면 로컬 컴퓨터에서 프로젝트를 실행할 수 있도록 Solution Platformx64로 변경하고, 32비트이면 x86으로 변경합니다.

  1. 프로젝트를 실행하려면 도구 모음에서 Start Debugging 단추를 클릭하거나 F5 키를 누릅니다.

콘솔 창이 팝업되고 학습 과정이 표시됩니다. 정의한 대로 손실 값은 모든 Epoch에 출력됩니다. 모든 루프에서 손실 값이 감소할 것으로 예상합니다.

학습이 완료되면 아래와 비슷한 출력이 표시됩니다. 숫자는 정확히 동일하지 않습니다. 학습은 많은 요인에 따라 달라지고, 항상 동일한 결과를 반환하지는 않지만 비슷할 것입니다.

Output from initial model training

다음 단계

이제 분류 모델이 있으므로 다음 단계에서는 모델을 ONNX 형식으로 변환합니다.