Post

[Deep Learning Basic] 05_Pytorch를 활용한 데이터 분석 실습

✏️ Edit
[Deep Learning Basic] 05_Pytorch를 활용한 데이터 분석 실습

진행 순서

  1. 데이터 읽어오기
  2. 데이터 전처리

    1. 데이터프레임과 시리즈로 구분

    Pandas 라이브러리의 기본 데이터 구조

    • 데이터프레임: 2차원 테이블 (여러개의 시리즈의 결합)
      • => 독립 변수값(입력 특성)
    • 시리즈: 1차원 레이블(인덱스) => 하나의 컬럼
      • => 종속 변수값(예측 대상)
    1. train과 test 데이터 나누기
    2. 스케일링 진행
      • 데이터의 크기가 편차가 클 때 오차를 줄이기 위해 스케일링 진행
    3. torch tensor로 변환
  3. 선형회귀 모형 생성

    1. 모델 class 정의
    2. model instance 생성
    3. 손실함수/optimizer 정의
  4. Dataset Loader 생성
  5. Train set으로 훈련 수행

    • Batch data Load
    • model 을 이용하여 batch data 예측
    • loss value 계산
    • optimizer 에 저장된 grad value clear
    • loss value backpropagate
    • optimizer update
  6. Test set으로 모델 평가

    • criterion 으로 손실값 확인
    • Loss 시각화
  7. Test set으로 예측
  8. 평가

    1. MSE, R2 계산
    2. True vs. Predicted 시각화

데이터 구분 종류

  • train data: 모델 학습용 데이터
  • valid data: 학습된 모델이 예측한 값과 비교하기 위한 실제 데이터
  • test data

    • 훈련과정에서 valid data를 직접 훈련에 사용하진 않지만, 생성된 모델이 valid data에 적합할때까지 모델을 변경하기 때문에 간접적으로 모델에 영향을 끼쳤다고 볼 수 있다.
    • 그렇기 때문에 train 데이터와 valid data을 통해 생성한 모델을 최종적으로 검증하기 위해 사용하는 데이터

    ❗간단하게 사용하는 경우는 test data를 별도로 사용하지 않고, valid data를 test data라는 이름으로 진행하는 경우도 있다.


코드 적용 예시

  1. 데이터 읽어오기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import MinMaxScaler
    import pandas as pd
    import matplotlib.pyplot as plt
    import torch
    import torch.nn as nn
    import torch.optim as optim
    import warnings
    warnings.filterwarnings('ignore')
    
    torch.manual_seed(100)
    
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    
    # 원본 데이터
    df_boston = pd.read_csv("boston_house.csv", index_col=0)
    
  2. 데이터 전처리

    1. 데이터프레임과 시리즈로 구분
    1
    2
    3
    4
    
    # boston : 데이터프레임(테이블)
    boston = df_boston.drop('MEDV', axis=1)
    # target: 시리즈(컬럼)
    target = df_boston.pop('MEDV')
    
    1. train과 test 데이터 나누기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    # input/target 지정
    X = boston.values
    y = target.values
    X.shape, y.shape # ((506, 13), (506,))
    
    # Train 모델 학습
     # Test 모델 검증
     # test_size : train과 test의 비율 (0.2인 경우 train 8, test2)
     # random_state: 섞을 때 동일한 난수로 섞음
     X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
     X_train.shape, X_test.shape, y_train.shape, y_test.shape # ((404, 13), (102, 13), (404,), (102,))
    
    1. 스케일링 진행
    1
    2
    3
    
    sc = MinMaxScaler()
    X_train = sc.fit_transform(X_train)
    X_test = sc.fit_transform(X_test)
    
    1. torch tensor로 변환
    1
    2
    3
    4
    5
    6
    
    X_train_ts = torch.FloatTensor(X_train)
    X_test_ts = torch.FloatTensor(X_test)
    y_train_ts = torch.FloatTensor(y_train).view(-1, 1)
    y_test_ts = torch.FloatTensor(y_test).view(-1, 1)
    
    X_train_ts.size(), X_test_ts.size(), y_train_ts.size(), y_test_ts.size()
    
  3. 선형회귀 모형 생성

    1. 모델 class 정의

      1
      2
      3
      4
      5
      6
      
      class LinearReg(nn.Module):
        def __init__(self, input_size, output_size):
          super().__init__()
          self.fc1 = nn.Linear(input_size, 64)
          self.fc2 = nn.Linear(64, 32)
          self.fc3 = nn.Linear(32, output_size)
      
      1
      2
      3
      4
      5
      6
      7
      
      # 순방향 전파 정의
      
      def forward(self, x):
            x = torch.relu(self.fc1(x))
            x = torch.relu(self.fc2(x))
            output = self.fc3(x)
            return output
      
  4. model instance 생성

    1
    2
    
    model = LinearReg(X_train.shape[1], 1).to(device)
    model
    
  5. 손실함수/optimizer 정의

    1
    2
    
    criterion = nn.MSELoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001)
    
  6. Dataset Loader 생성

    1
    2
    
    train_ds = torch.utils.data.TensorDataset(X_train_ts, y_train_ts)
    train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True)
    
  7. Train set으로 훈련 수행

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    # 손실 값 저장
    Loss = []
    # 모델이 훈련할 총 epoch 수
    num_epochs = 100
    for epoch in range(num_epochs):
      for x, y in train_loader:
        # x: 입력 데이터, y: 정답 레이블
        x, y = x.to(device), y.to(device)
    
        # yhat: 모델이 예측한 값
        yhat = model(x)
        # loss: 손실 값
        loss = criterion(yhat, y)
    
        # 가중치 업데이트: 그래디언트 0으로 초기화하여 축적 방지
        optimizer.zero_grad()
    
        # 손실 값에 대한 그래디언트를 역전파 -> 손실함수의 미분값 계산
        loss.backward()
    
        # 역전파에서 계산된 그래디언트를 사용하여 모델의 매개변수 업데이트
        optimizer.step()
    
      print("epoch {} loss: {:.4f}".format(epoch+1, loss.item()))
      Loss.append(loss.item())
    
    print("total : {}".format(Loss))
    
  8. Test set으로 모델 평가

    • criterion 으로 손실값 확인
      1
      
      criterion(model(X_test_ts.to(device)), y_test_ts.to(device)).item()
      
    • Loss 시각화
      1
      
      plt.plot(Loss)
      
  9. Test set으로 예측

    1
    2
    
    y_pred= model(X_test_ts.to(device)).cpu().detach().numpy()
    y_pred.shape # (102, 1)
    
  10. 평가

    1. MSE, R2 계산

      1
      2
      3
      4
      5
      6
      7
      
      from sklearn.metrics import mean_squared_error, r2_score
      
      print('MSE : {}'.format(mean_squared_error(y_test, y_pred))
      # MSE : 34.30465347918625
      
      print('R2: {}'.format(r2_score(y_test, y_pred)))
      # R2: 0.5787140970108864
      
    2. True vs. Predicted 시각화

      1
      2
      3
      4
      5
      
      plt.scatter(y_test, y_pred)
      plt.plot(y_test, y_test, color='red')
      plt.xlabel("True Price")
      plt.ylabel("Predicted Price")
      plt.show()
      

      image-20240704152905767