케글에서 가장 초보적인 문제 타이타닉 생존자 예측 문제(https://www.kaggle.com/c/titanic/data)를 AutoEncoder로 접근해보려고 합니다.
이 문제는 케글에서 워낙 유명한 문제이기 때문에 competition의 리더보드를 보면 score가 1입니다.(정확도 100%..)
AutoEncoder로 접근하는건 더 높은 score를 위한 목표가 아닌 평소 관심있던 Task를 AutoEncoder로 해결할 수 있을지에 대해 스스로 확인해보고 싶어서 입니다.
예측을 중심으로 생각하는것이 아닌 AutoEncoder의 차원 축소 능력에 중심을 두려고 합니다.
그래서 train dataSet에 Overfitting 에 대해서는 잠깐 고민하지 않기로 하죠.
주어진 데이터를 잘 차원 축소하는 모델만 우선 만들어 봅시다
그리고 축소된 차원에서 knn 같은 알고리즘으로 생존 여부를 예측해보기도 하고, Sex와 age 등으로 어떤 pclass ticket을 구매하는게 좋을지 추천해보는 모델도 만들어보겠습니다.
AutoEncoder로는 bytenet이라는 모델을 사용해보려고 합니다.
먼저 코랩에서 케글 데이터를 불러 와야겠죠
1 2 3 4 5 6 |
#코랩 라이브러리 install !pip install kaggle from google.colab import files files.upload() #코랩의 account에서 donwload 한 API 파일 update(json파일) !kaggle competitions download -c titanic #competition의 data 탭에서 다운로드 API 실행ㅁ |
타이타닉 문제를 해결하기 위한 많은 notebook을 보면 전처리를 위한 많은 작업이 있습니다.
데이터가 어떻게 만들어졌는지 이해하는건 그리고 전처리 작업은 당연히 중요하지만 이번 모델은 주어진 데이터를 잘 차원 축소하는 모델을 만드는게 목표입니다.
주어진 데이터를 그냥 Autoencoder 모델에 넣어서 2차원 정도의 차원으로 축소합니다.
(많이 알려진 방법 중 name에서 title을 추출하는 것과 missing value를 채우는것 정도만 전처리 )
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 28 29 30 31 32 33 34 35 |
def preprocessing_data(dataset , onehot=False): #name에서 title 추출 dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.') #missing value 처리 #Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'] => 컬럼은 총 12개 #print(train.isnull().sum()) # Age , Cabin, Embarked 3개 컬럼 missing # Missing value는 임의의 다른 값으로 fill 처리 dataset['Age'].fillna(0 , inplace=True) #Age 는 0으로 dataset['Cabin'].fillna('N00' , inplace=True) #Cabin 은 N00 dataset['Embarked'].fillna('N' , inplace=True) #Embarked는 N으로 #categorical data 처리 # Sex, Ticket, Cabin, Embarked, Title cate_col = ['Sex' , 'Ticket' , 'Cabin' , 'Embarked' , 'Title'] for col in cate_col : col_label = train[col].astype('category').cat.codes if onehot is True: num = np.unique(col_label, axis=0).shape[0] encoding = np.eye(num)[col_label] dataset[col+'_encoding'] = encoding else: dataset[col+'_encoding'] = col_label return dataset train = preprocessing_data(train) train.isnull().sum() #missing value 없음 train.head() #실제 학습에 사용할 데이터는 sequential 데이터와 labeling 된 데이터 trainset = train[['PassengerId' , 'Pclass' , 'Age' , 'SibSp' , 'Parch' , 'Fare' , 'Sex_encoding' , 'Ticket_encoding' , 'Cabin_encoding' , 'Embarked_encoding' , 'Title_encoding']] => 11개 컬럼 |
categorical data를 one-hot encoding을 생각해볼수 있으나 ticket 처럼 실제 의미가 있을지 알수 없지만 680차원의 one-hot encoding 값을 생성해야하는 컬럼도 있어서 우선은 labeling encoding 만 사용합니다.
(labeling encoding은 pandas에서 category type 에 대해 codes 라는 값으로 아주 간단하게 생성 가능합니다.)
최종 11개의 컬럼을 가지고 학습을 시작해볼 수 있겠네요.
우선 AutoEncoder 모델을 생성해 보겠습니다.
사용한 모델은 Bytenet 으로 Encoder와 Decoder 모델을 생성해서 진행합니다.
ByteNet 모델의 코드는 https://github.com/dhpollack/bytenet.pytorch/blob/master/bytenet/bytenet_modules.py 의 코드를 사용하였습니다.
1 2 3 4 5 6 7 8 9 10 |
device = torch.device('cuda:0') encoder = BytenetEncoder(feature_num, max_r, k, num_sets=4).to(device) decoder = BytenetDecoder(feature_num , max_r, k, num_sets=4, num_classes=feature_num, use_logsm=False).to(device) params = [{"params": encoder.parameters()}, {"params": decoder.parameters()}] # criterion = nn.CrossEntropyLoss() # criterion = torch.nn.Smooth1Loss() criterion = torch.nn.L1Loss() optimizer = torch.optim.Adam(params) dataset_sizes = len(train_dataset) |
Encoder/Decoder 모델을 선언하고 학습 파라미터를 확인합니다.
원본에서는 ByteNet을 번역기 목적으로 crossEntropyLoss를 사용하였으나 Sequential Data에는 L1 loss 같은 Loss 로 reconstruct loss 를 확인하는게 맞을것 같아 L1 loss 를 사용해보겠습니다.
(colab에서 gpu를 사용하기 위해서는 런타임 환경을 GPU로 설정만 하면 됩니다. )
Deep Learning 모델을 처음 만들고 실행 전에는 항상 차원을 맞추는 고통스러운 작업은 필요한것 같습니다.
차원이 안맞는 부분을 수정하고 나면 간단한 train model 을 만들어서 실행 하면 학습이 진행됨을 확인할 수 있습니다.
https://cyc1am3n.github.io/2018/10/09/my-first-kaggle-competition_titanic.html
https://github.com/dhpollack/bytenet.pytorch/blob/master/bytenet/bytenet_modules.py