ynzify 2023. 7. 19. 16:21
>>> target = train["survived"].to_numpy()
>>> target

array([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
       0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
       0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0,
       1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0,
       0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0,
       0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
       0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
       0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
       0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0,
       1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
       0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0,
       0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0,
       1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0,
       1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1,
       1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1,
       0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1,
       0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0,
       0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0,
       1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
       0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,
       0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1,
       1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1,
       0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1,
       0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0,
       0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
       0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0,
       1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0,
       1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0,
       1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
       0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0,
       0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
       0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1,
       1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0,
       0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0,
       1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0,
       1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0])​
# 학습데이터
train = pd.read_csv(f"{DATA_PATH}titanic_train.csv")


# 테스트 데이터
test = pd.read_csv(f"{DATA_PATH}titanic_test.csv") 
train.shape , test.shape​
# 학습데이터
train = pd.read_csv(f"{DATA_PATH}titanic_train.csv")


# 테스트 데이터
test = pd.read_csv(f"{DATA_PATH}titanic_test.csv") 
train.shape , test.shape

 

 

Pytorch

  • 구글의 tenserflow와 유사한 딥러닝 라이브러리
  • 페이스북 인공지능 연구팀에 의해 주로 개발
  • https://pytorch.org

 

torch 텐서 변환 및 다양한 수학 함수와 클래스 포함
torch.nn 신경망을 구축하기 위한 레이어(층), 활성화 함수, 손실 함수 등 에 대한 함수와 클래스 포함
torch.utils.data 미니 배치 학습을 위한 데이터셋 구성관련 함수, 클래스 포함
torch.optim optimizer 관련 함수와 클래스가 포함

 

타이타닉 데이터셋으로 딥러닝 학습

  1. 데이터 전처리
  2. 미니배치 단위 학습을 위해 데이터셋 클래스 구현
  3. 딥러닝 모델 및 인공신경망 구현
  4. 하이퍼파라미터 정의 (손실함수 및 옵티마이저 선택)
  5. 학습 및 테스트 loop 구현

 

* 학습 데이터와 테스트 데이터 따로 따로 나누어 처리하기

 

 

데이터 전처리

>>> import torch
>>> import numpy as np
>>> import pandas as pd

>>> from google.colab import drive
>>> drive.mount('/content/drive')

>>> DATA_PATH = "/content/drive/MyDrive/05_deep_learning/data/"
>>> DATA_PATH

 

 

# 학습데이터
>>> train = pd.read_csv(f"{DATA_PATH}titanic_train.csv")

# 테스트 데이터
>>> test = pd.read_csv(f"{DATA_PATH}titanic_test.csv")


>>> train.shape , test.shape
((916, 12), (393, 11))

 

 

 

 

 

  • 결측치 확인하기
# 학습 데이터셋
>>> train.isnull().sum()
passengerid      0
survived         0
pclass           0
name             0
gender           0
age            180
sibsp            0
parch            0
ticket           0
fare             0
cabin          706
embarked         0
dtype: int64

 

# 테스트 데이터셋
>>> test.isnull().sum()
passengerid      0
pclass           0
name             0
gender           0
age             83
sibsp            0
parch            0
ticket           0
fare             1
cabin          308
embarked         2
dtype: int64

 

 

 

  • 학습 데이터에서 얻은 통계량을 이용해 결측치 채우기
>>> age_mean = train["age"].mean()
>>> fare_median = train["fare"].median()
>>> cabin_unk = "UNK"
>>> embarked_mode = train["embarked"].mode()[0]
>>> age_mean , fare_median ,cabin_unk , embarked_mode

(29.904891304347824, 14.5, 'UNK', 'S')

 

 

 

 

  • 결측치 처리
# 학습데이터 결측치 처리
>>> train["age"] = train["age"].fillna(age_mean)
>>> train["cabin"] = train["cabin"].fillna(cabin_unk)


# 테스트데이터 결측치 처리
>>> test["age"] = test["age"].fillna(age_mean)
>>> test["fare"] = test["fare"].fillna(fare_median)
>>> test["cabin"] = test["cabin"].fillna(cabin_unk)
>>> test["embarked"] = test["embarked"].fillna(embarked_mode)


>>> train.isnull().sum().sum() , test.isnull().sum().sum()
(0, 0)

 

 

 

  • 특성으로 사용할 변수 추가하기
>>> cols = ["age","sibsp","parch","fare","pclass","gender","embarked"]
>>> train_ft = train[cols].copy()
>>> test_ft = test[cols].copy()
>>> train_ft.shape, test_ft.shape
((916, 7), (393, 7))

 

 

  • 범주형 변수를 원핫 인코딩하여 특성으로 추가하기
>>> from sklearn.preprocessing import OneHotEncoder
>>> cols = ['gender','embarked']
>>> enc = OneHotEncoder(handle_unknown = 'ignore')
>>> enc.fit(train_ft[cols])
OneHotEncoder
OneHotEncoder(handle_unknown='ignore')

 

 

 

# 학습 데이터
>>> tmp = pd.DataFrame(
>>>     enc.transform(train_ft[cols]).toarray(),
>>>     columns = enc.get_feature_names_out()
>>> )
>>> train_ft = pd.concat([train_ft,tmp],axis=1)
>>> train_ft.head()

 

 

 

# 테스트 데이터
>>> tmp = pd.DataFrame(
>>>     enc.transform(test_ft[cols]).toarray(),
>>>     columns = enc.get_feature_names_out()
>>> )
>>> test_ft = pd.concat([test_ft,tmp],axis=1)
>>> test_ft.head()

 

 

 

  • 파생 변수 생성 과정에서 생긴 결측치 확인
>>> train_ft.isnull().sum().sum(), test_ft.isnull().sum().sum()

# 생긴 결측치 없음이 확인 된다
(0, 0)


# cols를 더이상 이용할 필요가 없음으로 드랍해주기
>>> cols = ["gender","embarked"]
>>> train_ft = train_ft.drop(columns=cols)
>>> test_ft = test_ft.drop(columns=cols)

 

 

 

 

  • Min-Max scaling
>>> from sklearn.preprocessing import MinMaxScaler
>>> scaler = MinMaxScaler()
>>> scaler.fit(train_ft)

MinMaxScaler
MinMaxScaler()

 

 

# 학습 데이터
>>> train_ft = scaler.transform(train_ft)
>>> train_ft

array([[0.88726043, 0.        , 0.        , ..., 1.        , 0.        ,
        0.        ],
       [0.42377552, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       [0.36114243, 0.375     , 0.11111111, ..., 0.        , 0.        ,
        1.        ],
       ...,
       [0.44882876, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       [0.473882  , 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       [0.23587624, 0.125     , 0.11111111, ..., 0.        , 0.        ,
        1.        ]])

 

 

# 테스트 데이터
>>> test_ft = scaler.transform(test_ft)
>>> test_ft

array([[0.77452086, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       [0.34861581, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       [0.29850933, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       ...,
       [0.26092948, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       [0.37247766, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ],
       [0.33608919, 0.        , 0.        , ..., 0.        , 0.        ,
        1.        ]])

 

 

 

>>> target = train["survived"].to_numpy()
>>> target

array([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
       0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
       0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0,
       1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0,
       0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0,
       0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
       0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
       0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
       0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0,
       1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
       0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0,
       0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0,
       1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0,
       1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1,
       1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1,
       0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1,
       0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0,
       0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0,
       1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
       1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
       0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,
       0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1,
       1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1,
       0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1,
       0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0,
       0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
       0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0,
       1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0,
       1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
       1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0,
       1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
       0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0,
       0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
       0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1,
       1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0,
       0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0,
       1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0,
       1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0])

 

 

 

>>> train_ft.shape, test_ft.shape, target.shape
((916, 10), (393, 10), (916,))


# 시드 고정을 위해
import random 
import os


>>> def reset_seeds(seed):
>>>     random.seed(seed)
>>>     os.environ['PYTHONHASHSEED'] = str(seed)
>>>     np.random.seed(seed)
>>>     torch.manual_seed(seed)
>>>     torch.cuda.manual_seed(seed)


Deterministic 한 알고리즘으로 수행 가능한 연산은 그대로 진행, 불가능한 경우에는 RuntimeError를 던짐
>>>     torch.backends.cudnn.deterministic = True

 

 

 

seed 고정

난수 생성기의 seed를 고정하면, 매번 프로그램을 실행할 때마다 생성되는 난수들의 수열이 같게 할 수 있다.

 

 

아래 링크에서 더 자세한 사항 확인

https://pytorch.org/docs/stable/generated/torch.use_deterministic_algorithms.html#torch.use_deterministic_algorithms

 

torch.use_deterministic_algorithms — PyTorch 2.0 documentation

Shortcuts

pytorch.org

 

 

PYTHONHASHSEED

hashing 알고리즘은 random요소가 있다. 그리고 그 hash결과에 영향을 주는 요소를 PYTHONHASHSEED 라고 한다

 

 

 

 

 

 

데이터셋 클래스 구현 

  • DATASET과 DATALOADER
    • pytorch에서는 미니배치 단위 학습을 위해 데이터셋을 좀 더 쉽게 다룰 수 있도록 유용한 도구로서  torch.utils.data.Dataset 과 torch.utils.data.Dataloader 제공
    • Dataset은 학습데이터와 정답을 저장해서 인덱싱을 통해 반환할 수 있는 클래스를 의미
    • DataLoader는 Dataset의 데이터를 쉽게 접근할 수 있도록  iterable 객체로 만들어준다
    • DataLoader 사용시 미니 배치, 셔플 등 간단히 수행 가능

 

>>> target.reshape(-1,1).shape
(916, 1)

 

 

 

item["y"] = torch.Tensor(self.y[idx]) 에서 self.y[idx] 값이 스칼라 값일 경우에는 에러가 날 수도 있음

따라서 2차원으로 reshape 해주어야 한다

 

# 정답값 말고 예측 값이 들어올때의 코딩

>>> class TitanicDataset(torch.utils.data.Dataset):
>>>     def __init__(self,x,y=None):
>>>         self.x = x
>>>         self.y = y
>>>         if self.y is not None:

             # 이진 분류 문제에서 2차원 형태로 변경해줘야한다
             # (스칼라값을 2차원 형태로 변환 안그러면 애가 못 읽음)
>>>             self.y = y.reshape(-1,1)

>>>     def __len__(self): # 총 샘플 수를 반환해주는 부분
>>>         return self.x.shape[0]

>>>     def __getitem__(self,idx):
    	
        # 학습데이터와 정답데이터를 반환해줄 딕셔너리
>>>         item = {} 

        # Tensor는 기본적으로 32bit 사용을 함 -> item을 Tensor의 class로 insert 한다는 것은 32bit로 바꿔준다는 뜻
        # item["x"] = torch.tensor(self.x[idx]) 
        # 이렇게 돌리면 64bit 데이터 형태 그대로 tensor로 돌린다는 뜻
        
        
>>>         item["x"] = torch.Tensor(self.x[idx])
>>>         if self.y is not None:
>>>             item["y"] = torch.Tensor(self.y[idx])
>>>         return item

 

 

# 코드 만들어주고 꼭 인덱스 확인 해주기
>>> dt = TitanicDataset(train_ft,target)
>>> dt[3]
{'x': tensor([0.2233, 0.1250, 0.1111, 0.0254, 0.5000, 1.0000, 0.0000, 0.0000, 0.0000,
         1.0000]),
 'y': tensor([1.])}
 
 
>>> dt = TitanicDataset(test_ft,target)
>>> dt[3]
{'x': tensor([0.3725, 0.0000, 0.0000, 0.0151, 1.0000, 1.0000, 0.0000, 0.0000, 1.0000,
         0.0000]),
 'y': tensor([1.])}

 

 

 

>>> train_ft[:2]
array([[0.88726043, 0.        , 0.        , 0.09662576, 0.        ,
        0.        , 1.        , 1.        , 0.        , 0.        ],
       [0.42377552, 0.        , 0.        , 0.01571255, 1.        ,
        0.        , 1.        , 0.        , 0.        , 1.        ]])
        
        
>>> target[:2]
array([0, 0])


>>> dl = torch.utils.data.DataLoader(dt,batch_size=2,shuffle=False)

#iterable한 객체인 것을 확인 (for 문으로 반복문 가능)
>>> dl

 

 

 

 

  • 예측할 때는 순서대로 예측해야 하므로 shuffle = False
  • 실제로 학습할 때 (학습 데이터를 줄 때), shuffle = True로 해주면 다양한 객체 섞어서 사용 가능
# iterable한 객체를 iterater로 바꿔서 언제든지 꺼낼 수 있게 하기
>>> next(iter(dl))

{'x': tensor([[0.8873, 0.0000, 0.0000, 0.0966, 0.0000, 0.0000, 1.0000, 1.0000, 0.0000,
          0.0000],
         [0.4238, 0.0000, 0.0000, 0.0157, 1.0000, 0.0000, 1.0000, 0.0000, 0.0000,
          1.0000]]),
 'y': tensor([[0.],
         [0.]])}

 

 

 

 

 

딥러닝 모델 인공신경망 구현

  • pytorch에서 신경망 모델은 torch.nn.Module을 상속받는 클래스 (class)를 생성하여 정의
  • __init__ 메소드에서 신경망의 계층(layer)들을 정의
  • forward 메소드에서 신경망에 텐서를 어떻게 전달할지 지정

 

>>> class Net(torch.nn.Module):
>>>     def __init__(self,in_features):


        # 부모 클래스 init method으로 초기화 필수
>>>         super().__init__()


        # 다중 회귀분석의 layer (in_features,노드 갯수)
>>>         self.hidden_layer1 = torch.nn.Linear(in_features,8)
>>>         self.hidden_layer2 = torch.nn.Linear(8,4)
>>>         self.output_layer = torch.nn.Linear(4,1)


        # 비선형성을 대비하여 ReLU 추가 해주기
>>>         self.relu = torch.nn.ReLU()
               
>>>     def forward(self,x):
>>>         x = self.hidden_layer1(x)
>>>         x = self.relu(x)
>>>         x = self.hidden_layer2(x)
>>>         x = self.relu(x)
>>>         return self.output_layer(x)

 

>>> data = next(iter(dl))

>>> data
{'x': tensor([[0.8873, 0.0000, 0.0000, 0.0966, 0.0000, 0.0000, 1.0000, 1.0000, 0.0000,
          0.0000],
         [0.4238, 0.0000, 0.0000, 0.0157, 1.0000, 0.0000, 1.0000, 0.0000, 0.0000,
          1.0000]]),
 'y': tensor([[0.],
         [0.]])}
         
         
>>> data["x"]
tensor([[0.8873, 0.0000, 0.0000, 0.0966, 0.0000, 0.0000, 1.0000, 1.0000, 0.0000,
         0.0000],
        [0.4238, 0.0000, 0.0000, 0.0157, 1.0000, 0.0000, 1.0000, 0.0000, 0.0000,
         1.0000]])

 

>>> model = Net(train_ft.shape[1])
>>> model(data["x"])
tensor([[-0.2394],
        [-0.2394]], grad_fn=<AddmmBackward0>)

 

 

 

 

하이퍼파라미터 정의

# 모델 학습을 위해 텐서를 어디 장치에 할 것인지 지정
>>> device = "cuda" if torch.cuda.is_available() else "cpu"
>>> device

'cpu'

 

 

# 미니배치 사이즈
>>> batch_size = 32


# 손실함수 객체 생성
>>> loss_fn = torch.nn.BCEWithLogitsLoss()
>>> loss_fn
BCEWithLogitsLoss()

 

 

# 모델 객체 생성
>>> reset_seeds(42)
# 모델 객체 생성후 모델 파라미터 사용가능한 장치로 이동
>>> model = Net(train_ft.shape[1]).to(device)


# optimizer 객체 생성
>>> optimizer = torch.optim.Adam(model.parameters())


# 학습데이터 객체 생성
>>> train_dt = TitanicDataset(train_ft,target)
>>> train_dl = torch.utils.data.DataLoader(train_dt,batch_size=batch_size,shuffle=True)

 

 

 

 

학습 및 테스트 loop 구현

  • 학습 loop
>>> for _ in range(10):
>>>     model.train() # 학습모드
>>>     epoch_loss = 0
>>>     for batch in train_dl:

	
   	# 모델예측
>>>         pred = model(batch["x"].to(device))

	# 손실 구하기
>>>         loss = loss_fn(pred,batch["y"].to(device))

>>>         optimizer.zero_grad() # 경사를 누적하여 업데이트 하기 때문에 0으로 초기화 해준다.
>>>         loss.backward() # 역전파
>>>         optimizer.step() # 가중치 업데이트

        	# print(f"batch loss {loss.item()}")
>>>         epoch_loss += loss.item()

>>>     print(f"epoch loss {epoch_loss / len(train_dl)}")

epoch loss 0.7530954212977968
epoch loss 0.7322561494235335
epoch loss 0.7084929449804898
epoch loss 0.6778858920623516
epoch loss 0.6415135737123161
epoch loss 0.6022779468832344
epoch loss 0.5654908860551899
epoch loss 0.5333360937134973
epoch loss 0.5079377756036562
epoch loss 0.4864064136455799

 

 

  • test loop
>>> test_dt = TitanicDataset(test_ft)
>>> test_dl = torch.utils.data.DataLoader(test_dt,batch_size=batch_size,shuffle=False)


# 평가모드
>>> model.eval() 
>>> pred_list = []
>>> sig = torch.nn.Sigmoid() # 0~1사이 확률로 변환해주는 시그모이드 객체 생성
>>> with torch.no_grad(): # 예측 과정에서 경사를 추적 할 필요 없기에 경사추적 꺼놓기
>>>     for batch in test_dl: # 데이터로더 객체에서 배치단위로 batch 변수에 전달됨
>>>         pred = model(batch["x"].to(device))
>>>         pred = sig(pred) # 예측값 0~1사이 확률로변환


# 텐서 cpu 장치로 이동후 ndarray 로 변환
>>>         pred = pred.to("cpu").numpy() 
>>>         pred_list.append(pred)

 

>>> pred = np.concatenate(pred_list)
>>> pred

array([[0.2712706 ],
       [0.27998695],
       [0.20150279],
       [0.5070917 ],
       [0.51006705],
       [0.5060269 ],
       [0.23415138],
       [0.50962216],
       [0.51320624],
       [0.5502231 ],
       [0.23940608],
       [0.50708985],
       [0.5690488 ],
       [0.5690488 ],
       [0.49669638],
       [0.1981485 ],
       [0.17948557],
       [0.19569755],
       [0.5690488 ],
       [0.19816145],
       [0.19636   ],
       ...

 

 

 

>>> y_test = pd.read_csv(f"{DATA_PATH}titanic_test_target.csv")["survived"]
>>> y_test

0      0
1      0
2      0
3      1
4      1
      ..
388    0
389    1
390    0
391    0
392    0
Name: survived, Length: 393, dtype: int64
>>> from sklearn.metrics import roc_auc_score
>>> roc_auc_score(y_test,pred)
0.877426916712631