본문 바로가기
AI/딥러닝

03. 논리회귀 (단항, 다중) | 시그모이드(sigmoid) 함수

by 사라리24 2024. 6. 19.
SMALL

 

1. 단항 논리 회귀

* 분류를 할 때 사용하며 선형 회귀 공식으로부터 나왔기 때문에 논리 회귀라는 이름이 붙여짐
* Sigmoid 함수(Logistic 함수)를 사용하여 정확도를 높임

 

Sigmoid 함수

예측값을 0에서 1사이 값이 되도록 만듬
0에서 1사이의 연속된 값을 출력으로 하기 때문에 보통 0.5(임계값)를 기준으로 구분


 

 

  • import

       
        import torch
        import torch.nn as nn
        import torch.optim as optim
        import matplotlib.pyplot as plt


 

 

  • 시드값 고정

     
        torch.manual_seed(2024)


 

 

 

  • PyTorch 텐서를 사용하여
    훈련 데이터를 정의하고 그 형태를 출력

       
        x_train = torch.FloatTensor([[0], [1], [3], [5], [8], [11], [15], [20]])
        y_train = torch.FloatTensor([[0], [0], [0], [0], [0], [1], [1], [1]])

        print(x_train.shape)
        print(y_train.shape)

 
torch.Size([8, 1])
torch.Size([8, 1])
x_train = torch.FloatTensor([[0], [1], [3], [5], [8], [11], [15], [20]]):
  • x_train은 입력 데이터로, 각 데이터 포인트는 하나의 특징(feature) 값을 가지는 8개의 샘플로 구성된 2차원 리스트입니다.
  • torch.FloatTensor를 사용하여 2차원 리스트를 부동 소수점형 텐서로 변환합니다.
y_train = torch.FloatTensor([[0], [0], [0], [0], [0], [1], [1], [1]]):
  • y_train은 출력 또는 타겟 데이터로, 각 데이터 포인트에 대해 하나의 타겟 값을 가지는 8개의 샘플로 구성된 2차원 리스트입니다.
  • torch.FloatTensor를 사용하여 2차원 리스트를 부동 소수점형 텐서로 변환합니다.

 

 

  • x_train과 y_train 데이터를 산점도로 시각화

       
        plt.figure(figsize=(8, 5))
        plt.scatter(x_train, y_train)




  • x_train의 각 값은 x축 좌표에, y_train의 각 값은 y축 좌표에 배치됩니다.
  • 이 산점도는 x_train 값에 따른 y_train 값을 시각적으로 보여줍니다.

 

 

 

 

  • 모델 만들기

       
        model = nn.Sequential(
            nn.Linear(1, 1),
            nn.Sigmoid()
        )

        print(model)


Sequential(
  (0): Linear(in_features=1, out_features=1, bias=True)
  (1): Sigmoid()
)

 

  • 현재 모델의 파라미터들을 리스트로 출력
    : 모델의 각 층에 있는 가중치(weight)와 편향(bias)을 볼 수 있음
    : 각 파라미터는 텐서(Tensor) 객체로 표시

       
      print(list(model.parameters())) # W: 0.0634, b:6625

 
[Parameter containing:
tensor([[0.0634]], requires_grad=True), Parameter containing:
tensor([0.6625], requires_grad=True)]

 

비용함수

논리 회귀에서는 nn.BCELoss() 함수를 사용하여 Loss를 계산
Binary Cross Entropy

 

 

  • 훈련 데이터 x_train에 대해 예측을 수행하고,
    결과 y_pred 변수에 저장

       
        y_pred = model(x_train)
        y_pred

 
tensor([[0.6598],
        [0.6739],
        [0.7012],
        [0.7270],
        [0.7631],
        [0.7958],
        [0.8340],
        [0.8734]], grad_fn=<SigmoidBackward0>)

 

 

  • 예측값 y_pred실제 타겟값 y_train 사이의
    Binary Cross-Entropy (BCE) 손실
    을 계산

       
loss = nn.BCELoss()(y_pred, y_train)
       loss
 
tensor([[0.6598],
        [0.6739],
        [0.7012],
        [0.7270],
        [0.7631],
        [0.7958],
        [0.8340],
        [0.8734]], grad_fn=<SigmoidBackward0>)

 

 

 

  • PyTorch를 사용하여 선형 모델을 학습시키는 과정
    모델은 이진 교차 엔트로피 손실 함수(nn.BCELoss)를 사용하여 최적화
    확률적 경사 하강법(SGD)을 통해 가중치가 업데이트

     
      # 학습
        optimizer = optim.SGD(model.parameters(), lr=0.01)

        epochs = 1000

        for epoch in range(epochs + 1):
            y_pred = model(x_train)
            loss = nn.BCELoss()(y_pred, y_train)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            if epoch % 100 == 0:
                print(f'Epoch {epoch}/{epoch} Loss: {loss:.6f}')

 
Epoch 0/0 Loss: 0.836359
Epoch 100/100 Loss: 0.725281
Epoch 200/200 Loss: 0.645149
Epoch 300/300 Loss: 0.579139
Epoch 400/400 Loss: 0.524739
Epoch 500/500 Loss: 0.479715
Epoch 600/600 Loss: 0.442194
Epoch 700/700 Loss: 0.410667
Epoch 800/800 Loss: 0.383936
Epoch 900/900 Loss: 0.361067
Epoch 1000/1000 Loss: 0.341329
  • Optimizer 정의: optim.SGD(model.parameters(), lr=0.01)는 SGD (Stochastic Gradient Descent) 최적화 기법을 사용하여 모델의 파라미터를 업데이트하는 optimizer를 정의합니다. model.parameters()는 모델의 학습 가능한 모든 파라미터를 전달합니다. lr=0.01은 learning rate로, 각 업데이트 단계에서 파라미터를 조정하는 양을 나타냅니다.
  • Epochs 설정: epochs = 1000은 전체 데이터셋을 몇 번 반복할지를 결정하는 변수입니다.
  • 학습 반복문: for epoch in range(epochs + 1):은 주어진 epoch 수만큼 반복하는 반복문입니다.
    • y_pred = model(x_train): 현재 모델을 사용하여 입력 데이터 x_train에 대한 예측값 y_pred를 계산합니다.
    • loss = nn.BCELoss()(y_pred, y_train): 이진 교차 엔트로피 손실 함수 (nn.BCELoss())를 사용하여 예측값 y_pred와 실제 타겟값 y_train 간의 손실을 계산합니다.
    • optimizer.zero_grad(): optimizer의 gradient를 초기화합니다. 이는 각 배치나 에폭이 시작될 때 사용됩니다.
    • loss.backward(): 손실에 대한 역전파를 수행하여 모델의 파라미터에 대한 gradient를 계산합니다.
    • optimizer.step(): optimizer를 사용하여 계산된 gradient를 기반으로 모델의 파라미터를 업데이트합니다.
    • if epoch % 100 == 0:: 매 100 에폭마다 현재 손실을 출력합니다.
      • print(f'Epoch {epoch}/{epochs} Loss: {loss:.6f}'): 현재 에폭 번호와 손실을 출력합니다. :.6f는 손실값을 소수점 아래 6자리까지 표시하도록 지정한 것입니다.
  • 주석
더보기

       
          # Optimizer 정의: SGD (Stochastic Gradient Descent)를 사용하여
            모델의 파라미터를 업데이트하는 optimizer를 정의
          optimizer = optim.SGD(model.parameters(), lr=0.01)

          # 전체 데이터셋을 몇 번 반복할지 결정하는 변수
          epochs = 1000

          # 학습 반복문
          for epoch in range(epochs + 1):
              # 현재 모델을 사용하여 입력 데이터 x_train에 대한 예측값 y_pred를 계산합니다.
              y_pred = model(x_train)
             
              # 이진 교차 엔트로피 손실 함수를 사용하여 예측값 y_pred와 실제 타겟값 y_train 간의 손실을 계산합니다.
              loss = nn.BCELoss()(y_pred, y_train)
             
              # optimizer의 gradient를 초기화합니다. (각 배치나 에폭이 시작될 때 사용됩니다.)
              optimizer.zero_grad()
             
              # 손실에 대한 역전파를 수행하여 모델의 파라미터에 대한 gradient를 계산합니다.
              loss.backward()
             
              # optimizer를 사용하여 계산된 gradient를 기반으로 모델의 파라미터를 업데이트합니다.
              optimizer.step()

              # 매 100 에폭마다 현재 에폭 번호와 손실을 출력합니다.
              if epoch % 100 == 0:
                  print(f'Epoch {epoch}/{epochs} Loss: {loss:.6f}')

 

 

  • 현재 모델의 파라미터들을 리스트로 출력
    : 모델의 각 층에 있는 가중치(weight)와 편향(bias)을 볼 수 있음
    : 각 파라미터는 텐서(Tensor) 객체로 표시

       
        print(list(model.parameters()))  # W: 0.2019, b: -1.4572


[Parameter containing:
tensor([[0.2019]], requires_grad=True), Parameter containing:
tensor([-1.4572], requires_grad=True)]

 

 

  • 학습된 모델을 사용하여 입력 데이터 x_test에 대해 예측값 y_pred를 출력

       
      x_test = torch.FloatTensor([[12]])
      y_pred = model(x_test)
      print(y_pred)

 
tensor([[0.7243]], grad_fn=<SigmoidBackward0>)
  • x_test는 입력 데이터를 나타내는 PyTorch의 FloatTensor입니다. 여기서는 하나의 샘플이며, 값은 12입니다.
  • model은 이미 학습된 신경망 모델을 가리킵니다.
  • y_pred는 입력 데이터 x_test에 대한 모델의 예측값을 나타내는 텐서입니다.
  • print(y_pred)는 예측값을 출력합니다.

 

 

  • 예측된 출력 y_pred를 기반으로 임계치(threshold)를 설정하여 이진 분류 결과를 만드는 과정

      
        # 임계치 설정하기
        # 0.5보다 크거나 같으면 1
        # 0.5보다 작으면 0
        y_bool = (y_pred >= 0.5).float()
        print(y_bool)

 
tensor([[0.],
        [1.]])
  • y_pred는 예측된 출력값을 담고 있는 텐서입니다.
  • (y_pred >= 0.5)는 각 원소가 0.5보다 크거나 같으면 True, 그렇지 않으면 False를 반환합니다.
  • .float()는 불리언 값을 0 또는 1로 변환하여 이진 분류 결과를 만듭니다. True는 1.0으로, False는 0.0으로 변환됩니다.
  • y_bool은 이진 분류 결과를 나타내는 텐서입니다. 각 행은 예측된 클래스를 나타내며, 0 또는 1의 값을 가집니다.

 

 

2. 다항 논리 회귀

 

 

  • 훈련 데이터를 준비
    : 입력 데이터 x_train과 레이블 데이터 y_train
  • FloatTensorLongTensor로 변환

       
        x_train = [[1, 2, 1, 1],
                  [2, 1, 3, 2],
                  [3, 1, 3, 4],
                  [4, 1, 5, 5],
                  [1, 7, 5, 5],
                  [1, 2, 5, 6],
                  [1, 6, 6, 6],
                  [1, 7, 7, 7]]

        y_train = [0, 0, 0, 1, 1, 1, 2, 2]

        x_train = torch.FloatTensor(x_train)
        y_train = torch.LongTensor(y_train)
        print(x_train.shape)
        print(y_train.shape)

 
torch.Size([8, 4])
torch.Size([8])
  • x_train 
    Python 리스트로 구성된 2차원 배열입니다.
    각 행은 샘플을 나타내며, 각 열은 해당 샘플의 특성을 나타냅니다.
  • y_train
    각 샘플에 대한 정수 형식의 레이블을 담고 있는 리스트입니다.


  • torch.FloatTensor(x_train)
    입력 데이터 x_train을 PyTorch의 FloatTensor로 변환하는 과정입니다.
    FloatTensor는 신경망에서 사용될 수 있는 데이터 형식입니다.
  • torch.LongTensor(y_train)
    레이블 데이터 y_train을 PyTorch의 LongTensor로 변환하는 과정입니다.

    LongTensor는 정수형 레이블을 나타내는 데 사용됩니다.

  • print(x_train.shape)
     x_train의 모양(shape)을 출력합니다.

    여기서는 (8, 4)로, 총 8개의 샘플과 각 샘플당 4개의 특성(열)을 가진 2차원 배열임을 나타냅니다.
  • print(y_train.shape)
    y_train의 모양(shape)을 출력합니다.

    여기서는 (8,)로, 총 8개의 정수형 레이블을 가진 1차원 배열임을 나타냅니다.

 

 

  •  간단한 신경망 모델을 정의

       
        model = nn.Sequential(
            nn.Linear(4, 3)
        )

        print(model)



Sequential(
  (0): Linear(in_features=4, out_features=3, bias=True)
)


  • nn.Sequential
    순차적으로 연결된 계층을 갖는 신경망 모델을 정의할 수 있는 PyTorch 클래스입니다.
  • nn.Linear(4, 3)
    입력 차원이 4이고 출력 차원이 3인 선형 변환(선형 레이어)을 의미합니다. 즉, 입력 특성이 4개이고 출력 특성이 3개인 선형 변환을 수행하는 레이어입니다.
  • model
    nn.Sequential을 사용하여 정의된 신경망 모델 객체입니다.
    이 모델은 하나의 선형 레이어만을 가지고 있습니다.
  • print(model) 
    정의된 모델의 구조를 출력

    이 출력은 하나의 선형 레이어가 포함된 순차적인 모델임을 보여줍니다.
    in_features=4는 입력 차원이 4임을, out_features=3는 출력 차원이 3임을 나타냅니다.

 

 

 

  • 학습된 모델을 사용하여 훈련 데이터에 대한 예측값을 계산하고 출력

      
        y_pred = model(x_train)
        print(y_pred)


tensor([[-0.3467,  0.0954, -0.5403],
        [-0.3109, -0.0908, -1.3992],
        [-0.1401,  0.1226, -1.3379],
        [-0.4850,  0.0565, -2.1343],
        [-4.1847,  1.6323, -0.7154],
        [-2.4318,  1.2809, -0.8234],
        [-4.2877,  1.7462, -0.8999],
        [-5.1520,  2.1004, -0.9593]], grad_fn=<AddmmBackward0>)

 

CrossEntropyLoss (교차 엔트로피 손실 함수)

* 교차 엔트로피 손실 함수는 PyTorch에서 제공하는 손실 함수 중 하나로 다중 클래스 분류 문제에서 사용
* 소프트맥스 함수와 교차 엔트로피 손실 함수를 결합한 형태
* 소프트맥스 함수를 적용 각 클래스에 대한 확률 분포를 얻음
* 각 클래스에 대한 로그 확률을 계산
* 실제 라벨과 예측 확률의 로그 값 간의 차이를 계산
* 계산되 차이의 평균을 계산해서 최종 손실값을 얻음

 

SoftMax

* 다중 클래스 분류 문제에서 사용되는 함수로 주어진 입력 벡터의 값을 확률 분포로 변환
* 각 클래스에 속한 확률을 계산할 수 있으며 0과 1 사이의 값으로 변환하여 이 값들의 합은 항상 1이 되도록 함
* 주로 다중 클래스 분류 문제에서 출력층에서 사용되는 활성화 함수입니다.
* 각 클래스에 대한 확률 분포를 생성하는 함수로, 각 클래스에 대한 확률 값을 반환
   일반적으로 모델의 출력을 확률 값으로 해석할 수 있도록 만들어줌
* 각 입력 값에 대해 지수함수를 적용
* 지수 함수를 적용한 모든 값의 합을 계산한 후, 각 지수 합으로 나누어 정규화를 함
* 정규화를 통해 각 값은 0과 1사이의 확률 값으로 출력

 

 

  • 다항 논리 회귀 모델의 손실을 계산하는 과정
    다항 논리 회귀에서는 이진 분류 문제와 달리 BCELoss 대신 CrossEntropyLoss를 사용합니다.
    CrossEntropyLoss는 소프트맥스 함수가 포함된 손실 함수입니다.



         
# 다항 논리 회귀에서는 BCELoss() 대신 CrossEntropyLoss()를 사용
          # 소프트맥스 함수가 포함
          loss = nn.CrossEntropyLoss()(y_pred, y_train)
          print(loss)
       
 
tensor(1.2130, grad_fn=<NllLossBackward0>)

 

 

  •  다중 클래스 분류 문제를 해결하기 위해 다항 논리 회귀 모델을 학습하는 과정
    여기에서는 손실 함수교차 엔트로피 손실(CrossEntropyLoss)을 사용
    확률적 경사 하강법(SGD) 최적화 기법을 사용하여 모델의 파라미터를 업데이트

       
        optimizer = optim.SGD(model.parameters(), lr=0.1)

        # 학습
        epochs = 1000

        for epoch in range(epochs + 1):
            y_pred = model(x_train)
            loss = nn.CrossEntropyLoss()(y_pred, y_train)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            if epoch % 100 == 0:
                print(f'Epoch {epoch}/{epoch} Loss: {loss:.6f}')

 
  • optimizer = optim.SGD(model.parameters(), lr=0.1)
    SGD (Stochastic Gradient Descent) 최적화기를 생성합니다.
    이 최적화기는 모델의 파라미터들을 업데이트하는 데 사용됩니다. 학습률(learning rate)은 0.1로 설정되어 있습니다.
  • epochs = 1000
    전체 데이터셋을 몇 번 반복할지 결정하는 에포크(epoch) 수입니다.
    여기서는 총 1000번의 에포크 동안 학습을 진행합니다.
  • for epoch in range(epochs + 1)
    0부터 1000까지의 범위에서 에포크를 반복합니다.
  • y_pred = model(x_train)
     입력 데이터 x_train을 모델에 전달하여 예측값 y_pred를 계산합니다.
  • loss = nn.CrossEntropyLoss()(y_pred, y_train)
    Cross Entropy Loss 함수를 사용하여 예측값 y_pred와 실제값 y_train 사이의 손실을 계산합니다.
    이 손실은 다중 클래스 분류에서 주로 사용됩니다.
  • optimizer.zero_grad()
    최적화기의 모든 변화도 정보를 초기화합니다.
    이는 PyTorch에서 기본적으로 필요한 단계입니다.
  • loss.backward()
     손실을 역전파하여 각 파라미터에 대한 변화도(gradient)를 계산합니다.
  • optimizer.step()
    최적화기를 사용하여 계산된 변화도에 따라 모델의 파라미터를 업데이트합니다.
  • if epoch % 100 == 0 :
    print(f'Epoch {epoch}/{epoch} Loss: {loss:.6f}')
    100번째 에포크마다 현재 손실을 출력하여 학습 진행 상황을 모니터링합니다.
Epoch: 0/1000 Loss:  1.212971
Epoch: 100/1000 Loss:  0.629261
Epoch: 200/1000 Loss:  0.556415
Epoch: 300/1000 Loss:  0.505015
Epoch: 400/1000 Loss:  0.462015
Epoch: 500/1000 Loss:  0.423341
Epoch: 600/1000 Loss:  0.386988
Epoch: 700/1000 Loss:  0.351581
Epoch: 800/1000 Loss:  0.316010
Epoch: 900/1000 Loss:  0.279698
Epoch: 1000/1000 Loss:  0.247014

 

 

 

  • 학습된 모델을 사용하여 새로운 입력 데이터에 대한 예측값을 출력

       
      x_test = torch.FloatTensor([[1, 7, 8, 7]])
      y_pred = model(x_test)
      print(y_pred)


tensor([[-10.2333,   0.3633,   5.1844]], grad_fn=<AddmmBackward0>)
  • model을 사용하여 x_test에 대한 예측값을 생성합니다.
  • y_pred는 모델의 출력값으로, 각 클래스에 대한 로짓(logit) 값을 포함합니다.

 

 



  • 모델의 예측값에 소프트맥스(softmax) 함수를 적용하여 각 클래스에 대한 확률을 구하기

      
        # 예측값과 확률 구하기
        y_prob = nn.Softmax(1)(y_pred)
        y_prob

 
tensor([[1.9985e-07, 7.9936e-03, 9.9201e-01]], grad_fn=<SoftmaxBackward0>)

 

 

  • 각 클래스에 대한 확률을 출력

       

      print(f'0일 확률: {y_prob[0][0]:.2f}')
      print(f'1일 확률: {y_prob[0][1]:.2f}')
      print(f'2일 확률: {y_prob[0][2]:.2f}')


0일 확률: 0.00
1일 확률: 0.01
2일 확률: 0.99

 

 

 

  • 모델이 예측한 클래스 : 가장 큰 값의 인덱스를 찾기기

       
        torch.argmax(y_prob, axis=1)

 
tensor([2])

 

 

 

3. 경사하강법

 

경사하강법

종류

1. 배치 경사 하강법

* 가장 기본적인 경사 하강법( Vanilla Gradient Descent)
* 데이터셋 전체를 고려하여 손실함수를 계산
* 한번의 Epoch에 모든 파라미터 업데이트를 단 한번만 수행
* Batch의 개수와 lteration은 1이고 Batch size는 전체 데이터의 개수
* 파라미터 업데이트할 때 한번에 전체 데이터셋을 고려하기 때문에 모델 학습 시 많은 시간과 메모리가 필요하다는 단점

2. 확률적 경사 하강법

* 확률적 경사 하강법은 배치 경사 하강법이 모델 학습 시 많은 시간과 메모리가 필요하다는 단점을 개선하기위해 제안된 기법
* Batch size를 1로 설정하여 파라미터를 업데이트 하기 때문에 배치 경사 하강법보다 훨씬 빠르고 적은 메모리로 학습이 진행
* 파라미터 값의 업데이트 폭이 불안정하기 때문에 정확도가 낮은 경우가 생길 수 있음

3. 미니 배치 경사 하강법

* 미니 배치 경사 하강법(Mini-Batch Gradient Descent)은 Batch Size가 1도 전체 데이터 개수도 아닌 경우
* 배치 경사 하강법보다 모델 학습 속도가 빠르고, 확률적 경사 하강법보다 안정적인 장점이 있음
* 딥러닝 분야에서 가장 많이 활용되는 경사 하강법
* 일반적으로 Batch Size를 32,64,128과 같아 2의 n제곱에 해당하는 값으로 사용하는게 보편적

 

 

경사하강법

알고리즘

1. 확률적 경사 하강법 (SGD)

* 매개변수 값을 조정 시 전체 데이터가 아니라 랜덤으로 선택한 하나의 데이터에 대해서만 계산하는 방법

2. 모멘텀 (Momentum)

* 관성이라는 물리학의 법칙을 응용한 방법
* 경사 하강법에 관성을 더 해줌
* 접선의 기울기에 한 시점 이전의 접선의 기울기값을 일정한 비율만큼 반영
* 언덕에서 공이 내려올 때 중간의 작은 웅덩이에 빠지더라도 관성의 힘으로 넘어서는 효과를 줄 수 있음

3. 아다그라드(Adagrad)

* 모든 매개변수에 동일한 학습률(learning rate)을 적용하는 것은 비효율적이라는 생각에서 만들어진 학습 방법
* 처음에는 크게 학습하다가 조금씩 작게 학습시킴

4. 아담(Adam)

* 모멘텀 + 아다그라드

5. AdamW

Adam이 일부 약점(가중치 감쇠)과 성능향상을 위해 고안

 

 

4. 와인 데이터 

와인 품종 예측해보기
* sklearn.datasets.load_wine 데이터셋은 이탈리아의 같은 지역에서 재배된 세가지 다른 품종으로 만든 와인을 화학적으로 분석한 결과
* 13개의 성분을 분석하여 어떤 와인인지 맞춰보자
* 단, 트레이닝 데이터를 80%, 테스트 데이터를 20%로 하여 사용
* 테스트 데이터의 0번 인덱스가 어떤 와인인지 출력하고 테스트 정확도도 출력

 

 

  • 와인 데이터셋을 불러와서 x_data와 y_data로 분리

       
        from sklearn.datasets import load_wine

        x_data, y_data = load_wine(return_X_y=True, as_frame=True)

        x_data

        y_data




 

 

  • pandas의 DataFrame 형식으로 불러온 와인 데이터셋을
    PyTorch의 텐서로 변환

       
        x_data = torch.FloatTensor(x_data.values)
        y_data = torch.LongTensor(y_data.values)

        print(x_data.shape)
        print(y_data.shape)


torch.Size([178, 13])
torch.Size([178])

 




  • 와인 데이터셋을 훈련 세트와 테스트 세트로 분할

       

        from sklearn.model_selection import train_test_split

        x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=2024)
        print(x_train.shape, y_train.shape)
        print(x_test.shape, y_test.shape)


torch.Size([142, 13]) torch.Size([142])
torch.Size([36, 13]) torch.Size([36])
  • x_data: 독립 변수를 담고 있는 텐서입니다.
  • y_data: 종속 변수(클래스 레이블)를 담고 있는 텐서입니다.
  • x_train.shape: 훈련 세트에는 142개의 샘플이 있고 각 샘플은 13개의 특성을 가집니다.
  • y_train.shape: 훈련 세트에는 142개의 샘플에 대한 클래스 레이블이 있습니다.
  • x_test.shape: 테스트 세트에는 36개의 샘플이 있고 각 샘플은 13개의 특성을 가집니다.
  • y_test.shape: 테스트 세트에는 36개의 샘플에 대한 클래스 레이블이 있습니다.

 

 

  • 신경망 모델을 훈련시키고 평가

       
        # 학습
        model = nn.Sequential(
            nn.Linear(13, 3)
        )

        optimizer = optim.Adam(model.parameters(), lr=0.01)

        epochs = 1000

        for epoch in range(epochs + 1):
            y_pred = model(x_train)
            loss = nn.CrossEntropyLoss()(y_pred, y_train)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
           
            if epoch % 100 == 0:
                y_prob = nn.Softmax(1)(y_pred)
                y_pred_index = torch.argmax(y_prob, axis=1)
                y_train_index = y_train
                accuracy = (y_train_index == y_pred_index).float().sum() / len(y_train) * 100
                print(f'Epoch {epoch:4d}/{epochs} Loss:{loss: .6f} Accuracy: {accuracy: .2f}%')




Epoch    0/1000 Loss: 64.182411 Accuracy:  40.85%
Epoch  100/1000 Loss: 0.682099 Accuracy:  82.39%
Epoch  200/1000 Loss: 0.385995 Accuracy:  88.73%
Epoch  300/1000 Loss: 0.213528 Accuracy:  93.66%
Epoch  400/1000 Loss: 0.130488 Accuracy:  94.37%
Epoch  500/1000 Loss: 0.109236 Accuracy:  97.89%
Epoch  600/1000 Loss: 0.098798 Accuracy:  98.59%
Epoch  700/1000 Loss: 0.090906 Accuracy:  98.59%
Epoch  800/1000 Loss: 0.084330 Accuracy:  98.59%
Epoch  900/1000 Loss: 0.078634 Accuracy:  98.59%
Epoch 1000/1000 Loss: 0.073584 Accuracy:  98.59%
  • 모델 정의:
    • nn.Sequential을 사용하여 간단한 신경망 모델을 정의합니다.
    • 첫 번째 레이어로 입력 특성 수가 13이고 출력이 3인 선형 레이어(nn.Linear(13, 3))를 사용합니다.
    • 이는 와인 데이터셋의 입력 특성이 13개이고, 클래스(와인의 종류)가 3개임을 의미합니다.
  • 옵티마이저 설정:
    • Adam 최적화기를 사용하여 모델의 파라미터를 업데이트합니다.
    • 학습률(learning rate)은 0.01로 설정합니다.
  • 훈련 과정:
    • epochs 횟수만큼 반복하여 모델을 훈련합니다.
    • y_pred = model(x_train): 모델에 입력 데이터 x_train을 전달하여 예측값 y_pred를 계산합니다.
    • nn.CrossEntropyLoss()(y_pred, y_train): Cross Entropy 손실 함수를 사용하여 예측값 y_pred와 실제 클래스 레이블 y_train 사이의 손실을 계산합니다.
    • optimizer.zero_grad(): 기울기를 초기화합니다.
    • loss.backward(): 역전파를 수행하여 기울기를 계산합니다.
    • optimizer.step(): 옵티마이저를 사용하여 파라미터를 업데이트합니다.
  • 평가 및 출력:
    • 매 100번째 epoch마다 훈련 상태를 출력합니다.
    • nn.Softmax(1)(y_pred): 모델의 출력 y_pred에 Softmax 함수를 적용하여 확률을 계산합니다.
    • torch.argmax(y_prob, axis=1): 각 데이터 포인트에 대해 가장 높은 확률을 가진 클래스의 인덱스를 예측합니다.
    • accuracy = (y_train_index == y_pred_index).float().sum() / len(y_train) * 100: 정확도를 계산하여 출력합니다. 정확도는 올바르게 예측된 비율을 나타냅니다.

 

 

 

  • 테스트 데이터(x_test)를 사용하여 모델(model)이 예측한 결과(y_pred)
    그 결과를 소프트맥스 함수(nn.Softmax(1))를 통해 확률로 변환한 값(y_prob)을 출력

       
      y_pred = model(x_test)
      y_pred[:5]


      y_prob = nn.Softmax(1)(y_pred)
      y_prob[:5]


tensor([[46.2340, 44.3432, 52.4995],
        [82.5654, 75.1822, 73.2878],
        [34.3048, 39.0224, 40.0497],
        [84.3432, 78.8066, 78.6860],
        [60.5308, 58.4503, 54.4495]], grad_fn=<SliceBackward0>)

-----------------------------------------------------------------------------------------

tensor([[1.8966e-03, 2.8630e-04, 9.9782e-01],
        [9.9929e-01, 6.2117e-04, 9.3427e-05],
        [2.3503e-03, 2.6299e-01, 7.3466e-01],
        [9.9262e-01, 3.9111e-03, 3.4667e-03],
        [8.8719e-01, 1.1079e-01, 2.0275e-03]], grad_fn=<SliceBackward0>)

 

 

  • 각 클래스에 대한 확률을 출력
       
        print(f'0번 품종일 확률:{y_prob[0][0]:.2f}')
        print(f'1번 품종일 확률:{y_prob[0][1]:.2f}')
        print(f'2번 품종일 확률:{y_prob[0][2]:.2f}')
 
0번 품종일 확률: 0.00
1번 품종일 확률: 0.00
2번 품종일 확률: 1.00

 

 

 

 

  • 테스트 세트를 사용하여 모델의 정확도를 계산하고 출력하는 과정

       
          y_pred_index = torch.argmax(y_prob,axis=1)
          accuracy = (y_test == y_pred_index).float().sum()/len(y_test)*100

          print(f'테스트 정확도는 {accuracy:.2f}% 입니다!')


테스트 정확도는 97.22% 입니다!
  • 예측값에서 가장 높은 확률을 가진 클래스 인덱스 찾기:
    • y_prob는 소프트맥스 함수를 통해 계산된 각 데이터 포인트의 클래스별 확률을 담고 있는 텐서입니다.
    • torch.argmax(y_prob, axis=1)는 각 데이터 포인트에 대해 가장 높은 확률을 가진 클래스의 인덱스를 반환합니다.
    • axis=1은 두 번째 차원(열 방향)을 따라 최댓값을 찾도록 지정합니다.
  • 정확도 계산:
    • (y_test == y_pred_index)는 실제 클래스 레이블(y_test)과 예측된 클래스 인덱스(y_pred_index)가 일치하는지를 나타내는 불리언 마스크를 생성합니다.
    • .float()을 사용하여 불리언 값을 실수형으로 변환한 후, .sum()을 통해 True의 개수(정확히 일치하는 예측의 수)를 계산합니다.
    • len(y_test)는 테스트 세트의 전체 데이터 수를 나타냅니다.
    • 이를 통해 정확도(accuracy)를 계산하고, 백분율로 표시하기 위해 100을 곱합니다.
  • 결과 출력:
    • accuracy:.2f는 정확도를 소수점 둘째 자리까지 표시하도록 포맷합니다.
    • 테스트 정확도는 XX.XX% 입니다! 형식으로 최종 결과를 출력합니다.

 

'AI > 딥러닝' 카테고리의 다른 글

06. 비선형 활성화 함수  (0) 2024.06.20
05. 딥러닝  (0) 2024.06.20
04. 데이터로더(Data Loader)  (0) 2024.06.20
02. 선형 회귀(단항, 다중) | 경사하강법  (0) 2024.06.18
01. 파이토치(Pytorch)  (0) 2024.06.18