P Stage 2 : Project Day 2~3
Day 2~3 list
- 대회 의도 파악
- Multi-VAE 실험용 코드 재가공
대회 의도 파악
대회를 진행하기에 앞서 대회에서 요구하는 걸 정확하게 하는 게 중요하다고 생각했습니다. 대회 자체에서 요구하는 것은 sequential로 나타나는 영화 정보에서 일부 item이 drop된 상황을 가정하여 drop된 영화와 마지막 sequential 영화를 예측하는 것 입니다.
그래서 문제 자체의 모델 엔지니어링을 진행하기 이전에 drop된 부분이 있는지 확인하고자 train_ratings.csv
를 확인했습니다. train_ratings.csv
자체에는 특별히 null value가 있지는 않았습니다. 여기서부터 살짝 느낌이 이상하더군요.
그러면서 동시에 든 생각은 sequential이 의미가 있을까? 였습니다. 이런 생각이 든 이유는 다음과 같습니다.
- 대회라는 동일 환경에서 공정하게 진행이 되려면 랜덤하게 drop시킨 inference를 진행하는 것은 말이 안된다.
- 만약 inference 코드를 주고 반드시 이 코드를 활용해서 inference를 해야한다고 했으면 공정성이 성립될 수 있음 -> seed 고정으로 동일한 영화를 drop
- 근데 train ~ inference까지 모두 우리가 코드를 작성해야하므로 이건 아니라는 결과가 나옴
- 그렇다는 것은 결국 유저에게 가장 어울리는 상위 10개를 예측하는 문제로 바꿀 수 있다는 것이다. 즉, sequential의 의미가 크게 없어짐
- 추가적인 문제는 이 데이터는 movie lens를 재가공한 것이라 애초에 영화 시청기록이 아님
- 이는 시청기록이 몇 초단위로 기록되는 게 말이 되고 결과적으로 실제 유저 행동패턴과 약간은 다를 수 있음
- 다시 한번 sequnetial이 의미가 없음이 입증되는 부분
팀원들에게 이런 이유를 들어서 sequential이 의미가 없다는 것을 제시했고 sequential보다는 어울리는 아이템 추천으로 시선을 바꿔서 접근하게 되었습니다. 필요에 따라 sequential은 assist 정도로 활용할 수 있을 것으로 보입니다.
Multi-VAE 코드 refactoring
과제에서 제공해준 Multi-VAE를 실험에 편리한 형태로 코드 refactoring을 진행했습니다. 리팩토링 내용은 다음과 같습니다.
- 노트북으로 제공된 분리된 class, 함수들 통합 파이프라인 형성
- pandas 최신 버전 미적용 문제 최신 버전으로 최적화
- 최종 Inference 코드 효율성 향상
노트북 환경보다 argument를 직접 컨트롤하면서 실험을 진행하는 것이 좋고 이후 hyperparameter tuning에도 좋을 것으로 생각되어 파이프라인 코드를 작성했습니다. 판다스 최신 버전 미적용 문제도 최신 버전에 맞게 설정하여 refactoring했습니다.
팀원 분께서 Inference 부분을 잘 짜두셔서 해당 부분은 그대로 사용하였고 마지막에 중복 영화 처리부분만 수정했습니다.
깃허브 이슈로 해당부분에 대해 언급하였고 실제 파이프라인 코드에는 적용해서 작성했습니다.
< original >
1
2
3
4
5
6
7
8
9
index = 0
for user in tqdm(user_unique):
temp_items = list(pred_dic[user])
for movie in seen_dic[user]:
temp_items.remove(movie)
top_k_items = temp_items[:10]
for i in range(10):
test_df.loc[index + i, 'item'] = top_k_items[i]
index += 10
< refactoring >
1
2
3
4
5
6
7
8
9
index = 0
for user in tqdm(user_unique):
temp_items = np.array(list(pred_dic[user]))
seen_list = np.array(seen_dic[user])
temp_items = temp_items[np.isin(temp_items, seen_list) == False]
top_k_items = temp_items[:10]
for i in range(10):
test_df.loc[index + i, 'item'] = top_k_items[i]
index += 10
numpy
논리 연산을 활용해서 반복문 활용을 최소화하였고 3분 정도 걸리는 최종 inference time을 1분 안쪽으로 줄이는 효과가 있었습니다.
Comments powered by Disqus.