본문 바로가기
AI/딥러닝

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

by 사라리24 2024. 6. 19.

 

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)]

 

손실함수 Binary Cross Entropy (BCE)

Binary Cross Entropy (BCE)는 이진 분류 문제에서 자주 사용되는 손실 함수
논리 회귀에서는 nn.BCELoss() 함수를 사용하여 Loss를 계산

모델이 이진 분류 작업에서 예측한 확률과 실제 레이블 간의 차이를 측정

 

 

  • 훈련 데이터 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>)
  • 0.7243은 모델이 입력 12에 대해 양성 클래스(또는 클래스 1)일 확률이 72.43%임을 나타냅니다.

 

 

  • 예측된 출력 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. 다항 논리 회귀 (Multinomial Logistic Regression)

- 종속 변수가 세 개 이상의 클래스 중 하나에 속할 때 사용됩니다.
- 다항 논리 회귀는 소프트맥스 함수와 크로스 엔트로피 손실 함수를 사용하여 클래스 확률을 예측합니다.

 

  • 훈련 데이터를 준비: 입력 데이터 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)  /  torch.LongTensor(y_train)
    입력 데이터와 레이블 데이터 PyTorch의 FloatTensor, 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