본문 바로가기
Personal Projects/Toy Projects

[토이 프로젝트 2] 여행지 추천 AI 만들기 - 데이터 전처리 & 학습

by muns91 2024. 12. 5.
여행지 추천 AI 만들기 - 데이터 & 학습

 

 이번에는 두 번째 토이 프로젝트인 여행지 추천 AI 만들기에서 입력 데이터로 사용될 데이터에 대해서 살펴보고 전처리 과정과 학습까지 모든 과정에 관해서 살펴보도록 하겠습니다. 먼저, 해당 프로젝트에 사용될 데이터는 'AI 허브'의 '국내 여행로그 데이터 (수도권)'입니다. AI 허브 홈페이지 링크 (https://www.aihub.or.kr/aihubdata/data/view.do?dataSetSn=71581)에 따라 바로 들어가시면 아래 사진과 같이 AI 허브에서 제공하는 데이터의 개요, 메타데이터 구조표, 데이터 통계 등등 다양한 정보를 확인하실 수 있습니다. 

 

출처 : AI 허브 홈페이지

 

 데이터에 관한 정보를 확인하신 분들은 다운로드 버튼을 클릭하시고 절차에 따라 다운로드를 진행하시면 됩니다. 단, 여기서 주의하실 점은 데이터 다운로드 용량이 393GB나 되기 때문에 다운로드 받으실 때, 엄청 오래걸리니 다운로드 받으신 후에 폴더 내에서 실습에 필요하신 것만 빼고 나머지 파일은 삭제하시길 바랍니다~!

 

참고 영상 : https://www.youtube.com/watch?v=bUap1tORdWc


■ 데이터

 

GitHub - Muns91/Toy_project2_TR_recommend

Contribute to Muns91/Toy_project2_TR_recommend development by creating an account on GitHub.

github.com

 

 

 파일을 다운로드를 받으셨다면 이제 데이터를 선택하도록 하겠습니다. 데이터는 다운로드한 폴더에서 아래 사진과 같이 tn_travel_여행_A.csv 파일, tn_traveller_master_여행객 Master_A.csv 그리고 tn_visit_area_info_방문지정보_A.csv 파일을 선택해주시면 됩니다.

■ 데이터 전처리

 구글 코랩 환경을 여신 후에, 저는 죄측의 업로드를 통해서 학습에 사용될 파일들을 코렙 환경으로 불러왔습니다. 그리고 빵형님의 코드대로 일단은 수행해보면 TEST의 결과가 그리 좋지 않다는 것을 알게 됩니다. (이유는 영상 혹은 실습을 통해 원인을 찾아보세요!) 따라서 일단은 정확도가 좋지 않은 문제를 해결하기 위해 데이터를 합병한 이후에는 저만의 방식으로 다시 시도해보았습니다.

 

1. 데이터 불러오기

import pandas as pd

# 방문 정보
df_place = pd.read_csv('/content/tn_visit_area_info_방문지정보_A.csv')
df_place.head(5)

# 여행 정보
df_travel = pd.read_csv('/content/tn_travel_여행_A.csv')
df_travel.head(5)

# 여행객 정보
df_traveler = pd.read_csv('/content/tn_traveller_master_여행객 Master_A.csv')
df_traveler.head(5)

 

2. 데이터 병합

df = pd.merge(df_place, df_travel, on='TRAVEL_ID', how='left') # on TRAVEL_ID 주의
df = pd.merge(df, df_traveler, on='TRAVELER_ID', how='left') # on TRAVELER_ID 주의

df.head(5)

 

3. 데이터 정보 확인

df.info()

 

4. 대략적인 컬럼 정보 확인

# 모든 컬럼명을 리스트로 가져오기
column_list = df.columns.tolist()

# 결과 출력
print("컬럼명 리스트:")
print(column_list)
print()

for col in column_list:
  print('컬럼 명', col)
  print(df[col])
  print()

 

5. 컬럼별 카테고리 카운트

 

 

 

6. NaN 제거 및 ';' 데이터 정리

df_filter = df[~df['TRAVEL_MISSION_CHECK'].isnull()].copy()

df_filter.loc[:, 'TRAVEL_MISSION_INT'] = df_filter['TRAVEL_MISSION_CHECK'].str.split(';').str[0].astype(int)

df_filter

 

 

7. 컬럼 정리 및 int로 변경

df_filter = df_filter[[
    'GENDER',
    'AGE_GRP',
    'TRAVEL_STYL_1', 'TRAVEL_STYL_2', 'TRAVEL_STYL_3', 'TRAVEL_STYL_4', 'TRAVEL_STYL_5', 'TRAVEL_STYL_6', 'TRAVEL_STYL_7', 'TRAVEL_STYL_8',
    'TRAVEL_MOTIVE_1',
    'TRAVEL_COMPANIONS_NUM',
    'TRAVEL_MISSION_INT',
    'VISIT_AREA_NM',
    'DGSTFN',
]]

df_filter = df_filter.dropna()

categorical_features_names = [
    'GENDER',
    # 'AGE_GRP',
    'TRAVEL_STYL_1', 'TRAVEL_STYL_2', 'TRAVEL_STYL_3', 'TRAVEL_STYL_4', 'TRAVEL_STYL_5', 'TRAVEL_STYL_6', 'TRAVEL_STYL_7', 'TRAVEL_STYL_8',
    'TRAVEL_MOTIVE_1',
    # 'TRAVEL_COMPANIONS_NUM',
    'TRAVEL_MISSION_INT',
    'VISIT_AREA_NM',
    # 'DGSTFN',
]

df_filter[categorical_features_names[1:-1]] = df_filter[categorical_features_names[1:-1]].astype(int)

df_filter

 

 

8. DGSTFN 항목 분포 확인

 

9. object 컬럼 숫자로 변환 (카테고리화)

from sklearn.preprocessing import LabelEncoder

# 예시 데이터프레임 생성 (실제 데이터프레임을 사용하세요)
# df = pd.read_csv('your_file.csv')

# LabelEncoder 객체 생성
label_encoders = {}

# object 타입 컬럼 찾기
object_columns = df_filter.select_dtypes(include=['object']).columns

# 각 object 컬럼을 숫자로 변환
for col in object_columns:
    le = LabelEncoder()
    df_filter[col] = le.fit_transform(df_filter[col])
    label_encoders[col] = le  # LabelEncoder 저장 (필요시 사용)

 

10. 상관 관계 확인 (결과는 썩...?)

correlation_matrix = df_filter.corr()

# DGSTFN과의 상관 관계만 선택
dgstfn_correlation = correlation_matrix['DGSTFN']

# 히트맵 시각화
plt.figure(figsize=(12, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f', square=True, cbar_kws={"shrink": .8})
plt.title('Correlation Heatmap')
plt.tight_layout()
plt.show()

 

 

11. DGSTFN에 대한 고른 학습을 위한 분배

from sklearn.model_selection import train_test_split

# 데이터 불균형이 있는 DGSTFN 컬럼의 값 분포 확인
print("DGSTFN 값 분포:")
print(df_filter['DGSTFN'].value_counts())

print()
# train_test_split을 사용하여 데이터를 분할
train_data, test_data = train_test_split(
    df_filter,
    test_size=0.2,
    random_state=42,
    stratify=df_filter['DGSTFN']  # DGSTFN 컬럼을 기준으로 stratify
)

# 결과 확인
print("훈련 데이터 DGSTFN 값 분포:")
print(train_data['DGSTFN'].value_counts())
print("\n테스트 데이터 DGSTFN 값 분포:")
print(test_data['DGSTFN'].value_counts())

 

12. X, Y 나누기 (여기서 카테고리 부분은 뺐습니다.)

from catboost import CatBoostRegressor, Pool

train_pool = Pool(train_data.drop(['DGSTFN'], axis=1),
                  label=train_data['DGSTFN'])


test_pool = Pool(test_data.drop(['DGSTFN'], axis=1), label=test_data['DGSTFN'])

 

13. 학습 수행

model = CatBoostRegressor(
    loss_function='RMSE',
    eval_metric='MAE',
    task_type='GPU',
    depth=6,
    learning_rate=0.001,
    n_estimators=2000)

model.fit(
    train_pool,
    eval_set=test_pool,
    verbose=500,
    plot=True)

 

별도 카테고리화 X, 데이터 균형 처리 X (빵형 제공 코드)

 

카테고리화, 데이터 균형 처리

 

14. 컬럼 중요도 계산

model.get_feature_importance(prettified=True)

 

15. 추천 프로그램 예시

area_names = df_filter[['VISIT_AREA_NM']].drop_duplicates()

traveler = {
    'GENDER': '남',
    'AGE_GRP': 20.0,
    'TRAVEL_STYL_1': 1,
    'TRAVEL_STYL_2': 1,
    'TRAVEL_STYL_3': 2,
    'TRAVEL_STYL_4': 3,
    'TRAVEL_STYL_5': 2,
    'TRAVEL_STYL_6': 2,
    'TRAVEL_STYL_7': 2,
    'TRAVEL_STYL_8': 3,
    'TRAVEL_MOTIVE_1': 8,
    'TRAVEL_COMPANIONS_NUM': 0.0,
    'TRAVEL_MISSION_INT': 3,
}

traveler['GENDER'] = 1 if traveler['GENDER'] == '남' else 0
results = pd.DataFrame([], columns=['AREA', 'SCORE'])

for area in area_names['VISIT_AREA_NM']:
    input = list(traveler.values())
    input.append(area)

    score = model.predict(input)

    results = pd.concat([results, pd.DataFrame([[area, score]], columns=['AREA', 'SCORE'])])

results.sort_values('SCORE', ascending=False)[:10]

 


■ 마무리

 여기까지 두 번째 토이 프로젝트의 데이터 확인 및 전처리 그리고 학습까지에 대한 글이었습니다. 첫 번째 토이 프로젝트는 실습이 끝난 이후에 이것 저것 시도해보면서 코드를 계속 수정하고 재업로드(?)를 반복하고 있습니다. 이러다가 두 번째 프로젝트도 후딱 끝내야 하는 데... 그러지 못할까봐 부랴부랴 오늘부터 두 번째 토이 프로젝트를 시작하게 되었습니다. 이전 토이 프로젝트에서는 XTTS, Whisper 모델을 사용해봤었는 데, 이번에는 CatBoost라는 모델을 사용해보았습니다. 컬럼이 너무 많아서, K-fold를 시도해볼까 하다가, 코렙 환경이 이를 따라가질 못할 것 같아서 적당히 타협(?)하고 이번 토이 프로젝트를 종료하게 되었습니다. 

 

 생각보다 빠르게 진행되고 있는 토이 프로젝트를 수행하면서, 스스로 이게 맞나? 하는 생각이 들지만 다양한 경험을 해보자는 취지로 해보는 것이기 때문에 일단은 5개가 목표였지만 앞으로 쭉쭉 더 많이하면 좋지 않을까 하는 생각이 듭니다. 일단은 두 번째 토이 프로젝트는 여기서 종료하고 다음 세 번째 토이 프로젝트를 준비해야겠습니다.

 

 

반응형