| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- Roberta
- 토픽 모델링
- CTM
- KeyBert
- 트위치
- 개체명 인식
- 포아송분포
- 블루 아카이브
- 클래스 분류
- BERTopic
- 자연어 모델
- geocoding
- 다항분포
- 옵티마이저
- 원신
- 문맥을 반영한 토픽모델링
- Optimizer
- 데이터리안
- LDA
- 조축회
- SBERT
- NLP
- 구글 스토어 리뷰
- 피파온라인 API
- 데이터넥스트레벨챌린지
- 블루아카이브 토픽모델링
- Tableu
- 데벨챌
- 코사인 유사도
- 붕괴 스타레일
- Today
- Total
분석하고싶은코코
데이터 분석 체험하기 - 영화 관객수 예측 본문
데이터 분석을 공부하고 기록하고 싶어서 작성하게 된 블로그이자 작성글 입니다.
데이터 분석에 대해서 차근차근 알아가보고 싶어서 작성하게 되었습니다.
사실 무턱대고 ADsP공부해서 취득하기는 했지만 지금 보면 기억 나지 않는 부분들이 많아서 기록하고 돌아보기 위해서 작성합니다.
무언가를 공부하기 이전에 이론적인 공부부터하면 흥미가 떨어진다는 주의라 데이터 분석에 대해서 체험해 보고 이론을 알아가는 흐름으로 가보려 합니다.
오늘 체험해볼 데이터 분석은 '영화 관객수 예측'에 대한 데이터 분석입니다. 코드는 가장 잘 예측된 모델이라는 코드를 가져와 사용하였습니다.
데이터 자료는 데이콘에서 쉽게 구할 수 있습니다.(링크 첨부)
https://dacon.io/competitions/open/235536/overview/description
데이콘에서 데이터 분석에 대해서 혼자서 공부할 수 있게 잘 짜여 있고 데이터 분석을 공부하는 사람들과 정보, 코드 공유를 할 수 있어 좋은 사이트이니 혹시 데이터 분석을 공부하려 하시는 분들은 활용 하시면 좋겠습니다.
데이터 분석을 위해서 Jupyter Notebook을 활용해서 진행 하였습니다.
-----
지금부터 쓰는 내용은 모두 쥬피터 노트북에서 작성한 글입니다.
데이터 분석 - 영화 관객수 예측¶
분석에 필요한 패키지, 데이터 파일 불러오기¶
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import re
import warnings
train = pd.read_csv('../PythonDataWorkSpace/movie/movies_train.csv')
test = pd.read_csv('../PythonDataWorkSpace/movie/movies_test.csv')
submission = pd.read_csv('../PythonDataWorkSpace/movie/submission.csv')
Train 데이터 정보 확인¶
train.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 600 entries, 0 to 599 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 title 600 non-null object 1 distributor 600 non-null object 2 genre 600 non-null object 3 release_time 600 non-null object 4 time 600 non-null int64 5 screening_rat 600 non-null object 6 director 600 non-null object 7 dir_prev_bfnum 270 non-null float64 8 dir_prev_num 600 non-null int64 9 num_staff 600 non-null int64 10 num_actor 600 non-null int64 11 box_off_num 600 non-null int64 dtypes: float64(1), int64(5), object(6) memory usage: 56.4+ KB
train.head(5)
| title | distributor | genre | release_time | time | screening_rat | director | dir_prev_bfnum | dir_prev_num | num_staff | num_actor | box_off_num | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 개들의 전쟁 | 롯데엔터테인먼트 | 액션 | 2012-11-22 | 96 | 청소년 관람불가 | 조병옥 | NaN | 0 | 91 | 2 | 23398 |
| 1 | 내부자들 | (주)쇼박스 | 느와르 | 2015-11-19 | 130 | 청소년 관람불가 | 우민호 | 1161602.50 | 2 | 387 | 3 | 7072501 |
| 2 | 은밀하게 위대하게 | (주)쇼박스 | 액션 | 2013-06-05 | 123 | 15세 관람가 | 장철수 | 220775.25 | 4 | 343 | 4 | 6959083 |
| 3 | 나는 공무원이다 | (주)NEW | 코미디 | 2012-07-12 | 101 | 전체 관람가 | 구자홍 | 23894.00 | 2 | 20 | 6 | 217866 |
| 4 | 불량남녀 | 쇼박스(주)미디어플렉스 | 코미디 | 2010-11-04 | 108 | 15세 관람가 | 신근호 | 1.00 | 1 | 251 | 2 | 483387 |
데이터 전처리¶
'(주)' 단어는 특수 문자가 아니라 선 제거후 특수문자 제거 진행
train['distributor'] = train.distributor.str.replace("(주)", '')
test['distributor'] = test.distributor.str.replace("(주)", '')
/var/folders/jt/jw2pb8hx71d48w0rx0cgqf_80000gn/T/ipykernel_55205/3450709429.py:1: FutureWarning: The default value of regex will change from True to False in a future version.
train['distributor'] = train.distributor.str.replace("(주)", '')
/var/folders/jt/jw2pb8hx71d48w0rx0cgqf_80000gn/T/ipykernel_55205/3450709429.py:2: FutureWarning: The default value of regex will change from True to False in a future version.
test['distributor'] = test.distributor.str.replace("(주)", '')
train['distributor'] = [re.sub(r'[^0-9a-zA-Z가-힣]', '', x) for x in train.distributor]
test['distributor'] = [re.sub(r'[^0-9a-zA-Z가-힣]', '', x) for x in test.distributor]
배급사의 이름 정리
CJ와 CGV는 같은 계열사로 CJ로 통일
def get_dis(x) :
if 'CJ' in x or 'CGV' in x :
return 'CJ'
elif '쇼박스' in x :
return '쇼박스'
elif 'SK' in x :
return 'SK'
elif '리틀빅픽' in x :
return '리틀빅픽처스'
elif '스폰지' in x :
return '스폰지'
elif '싸이더스' in x :
return '싸이더스'
elif '에이원' in x :
return '에이원'
elif '마인스' in x :
return '마인스'
elif '마운틴픽' in x :
return '마운틴픽처스'
elif '디씨드' in x :
return '디씨드'
elif '드림팩트' in x :
return '드림팩트'
elif '메가박스' in x :
return '메가박스'
elif '마운틴' in x :
return '마운틴'
else :
return x
train['distributor'] = train.distributor.apply(get_dis)
test['distributor'] = test.distributor.apply(get_dis)
제목은 너무 다양해서 불필요하다고 생각되어 제거
train = train.drop(['title'],axis=1)
test = test.drop(['title'],axis=1)
train.groupby('genre').box_off_num.mean().sort_values()
genre 뮤지컬 6.627000e+03 다큐멘터리 6.717226e+04 서스펜스 8.261100e+04 애니메이션 1.819267e+05 멜로/로맨스 4.259680e+05 미스터리 5.275482e+05 공포 5.908325e+05 드라마 6.256898e+05 코미디 1.193914e+06 SF 1.788346e+06 액션 2.203974e+06 느와르 2.263695e+06 Name: box_off_num, dtype: float64
train['genre_rank'] = train.genre.map({'뮤지컬' : 1, '다큐멘터리' : 2, '서스펜스' : 3, '애니메이션' : 4, '멜로/로맨스' : 5,
'미스터리' : 6, '공포' : 7, '드라마' : 8, '코미디' : 9, 'SF' : 10, '액션' : 11, '느와르' : 12})
test['genre_rank'] = test.genre.map({'뮤지컬' : 1, '다큐멘터리' : 2, '서스펜스' : 3, '애니메이션' : 4, '멜로/로맨스' : 5,
'미스터리' : 6, '공포' : 7, '드라마' : 8, '코미디' : 9, 'SF' : 10, '액션' : 11, '느와르' : 12})
tr_nm_rank = train.groupby('distributor').box_off_num.median().reset_index(name = 'num_rank').sort_values(by = 'num_rank')
tr_nm_rank
| distributor | num_rank | |
|---|---|---|
| 110 | 인피니티엔터테인먼트 | 2.0 |
| 15 | 고구마공작소 | 8.0 |
| 52 | 사람과사람들 | 42.0 |
| 97 | 위드시네마 | 46.0 |
| 19 | 나우콘텐츠 | 54.0 |
| ... | ... | ... |
| 113 | 전망좋은영화사 | 1214237.0 |
| 105 | 이십세기폭스코리아 | 1422844.0 |
| 56 | 쇼박스 | 2138560.0 |
| 84 | 영구아트무비 | 2541603.0 |
| 75 | 아이필름코퍼레이션 | 3117859.0 |
147 rows × 2 columns
tr_nm_rank['num_rank'] = [i + 1 for i in range(tr_nm_rank.shape[0])]
tr_nm_rank
| distributor | num_rank | |
|---|---|---|
| 110 | 인피니티엔터테인먼트 | 1 |
| 15 | 고구마공작소 | 2 |
| 52 | 사람과사람들 | 3 |
| 97 | 위드시네마 | 4 |
| 19 | 나우콘텐츠 | 5 |
| ... | ... | ... |
| 113 | 전망좋은영화사 | 143 |
| 105 | 이십세기폭스코리아 | 144 |
| 56 | 쇼박스 | 145 |
| 84 | 영구아트무비 | 146 |
| 75 | 아이필름코퍼레이션 | 147 |
147 rows × 2 columns
train = pd.merge(train, tr_nm_rank, how = 'left')
test = pd.merge(test, tr_nm_rank, how = 'left')
test.fillna(0, inplace = True)
데이터 분석 모델을 위한 패키지 불러오기
from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor
from xgboost import XGBRegressor
# from lightgbm import LGBMRegressor
from catboost import CatBoostRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import KFold
from ngboost import NGBRegressor
X = train[['num_rank', 'time', 'num_staff', 'num_actor', 'genre_rank', 'screening_rat']]
y = np.log1p(train.box_off_num)
X = pd.get_dummies(columns = ['screening_rat'], data = X)
X['num_actor'] = np.log1p(X['num_actor'])
target = test[['num_rank', 'time', 'num_staff', 'num_actor', 'genre_rank', 'screening_rat']]
target = pd.get_dummies(columns = ['screening_rat'], data = target)
target['num_actor'] = np.log1p(target['num_actor'])
kf = KFold(n_splits = 10, shuffle = True, random_state = 42)
gbm = GradientBoostingRegressor(random_state = 42)
rmse_list = []
gb_pred = np.zeros((test.shape[0]))
for tr_idx, val_idx in kf.split(X, y) :
tr_x, tr_y = X.iloc[tr_idx], y.iloc[tr_idx]
val_x, val_y = X.iloc[val_idx], y.iloc[val_idx]
gbm.fit(tr_x, tr_y)
pred = np.expm1([0 if x < 0 else x for x in gbm.predict(val_x)])
sub_pred = np.expm1([0 if x < 0 else x for x in gbm.predict(target)])
rmse = np.sqrt(mean_squared_error(val_y, pred))
rmse_list.append(rmse)
gb_pred += (sub_pred / 10)
np.mean(rmse_list)
1174378.9765191542
ngb = NGBRegressor(random_state = 518)
rmse_list = []
ngb_pred = np.zeros((test.shape[0]))
for tr_idx, val_idx in kf.split(X, y) :
tr_x, tr_y = X.iloc[tr_idx], y.iloc[tr_idx]
val_x, val_y = X.iloc[val_idx], y.iloc[val_idx]
ngb.fit(tr_x, tr_y)
pred = np.expm1([0 if x < 0 else x for x in ngb.predict(val_x)])
sub_pred = np.expm1([0 if x < 0 else x for x in ngb.predict(target)])
rmse = np.sqrt(mean_squared_error(val_y, pred))
rmse_list.append(rmse)
ngb_pred += (sub_pred / 10)
[iter 0] loss=2.6200 val_loss=0.0000 scale=1.0000 norm=2.9523 [iter 100] loss=1.9566 val_loss=0.0000 scale=2.0000 norm=2.7106 [iter 200] loss=1.5812 val_loss=0.0000 scale=2.0000 norm=2.1869 [iter 300] loss=1.4423 val_loss=0.0000 scale=2.0000 norm=2.0889 [iter 400] loss=1.3728 val_loss=0.0000 scale=1.0000 norm=1.0177 [iter 0] loss=1.4093 val_loss=0.0000 scale=1.0000 norm=1.0766 [iter 100] loss=1.3297 val_loss=0.0000 scale=1.0000 norm=1.0107 [iter 200] loss=1.2862 val_loss=0.0000 scale=1.0000 norm=0.9863 [iter 300] loss=1.2443 val_loss=0.0000 scale=1.0000 norm=0.9643 [iter 400] loss=1.2127 val_loss=0.0000 scale=1.0000 norm=0.9497 [iter 0] loss=1.2151 val_loss=0.0000 scale=1.0000 norm=0.9553 [iter 100] loss=1.1644 val_loss=0.0000 scale=0.2500 norm=0.2300 [iter 200] loss=1.1530 val_loss=0.0000 scale=0.1250 norm=0.1141 [iter 300] loss=1.1442 val_loss=0.0000 scale=1.0000 norm=0.9071 [iter 400] loss=1.1405 val_loss=0.0000 scale=0.0005 norm=0.0004 [iter 0] loss=1.1724 val_loss=0.0000 scale=0.5000 norm=0.4635 [iter 100] loss=1.1455 val_loss=0.0000 scale=1.0000 norm=0.9093 [iter 200] loss=1.1191 val_loss=0.0000 scale=0.5000 norm=0.4462 [iter 300] loss=1.0910 val_loss=0.0000 scale=1.0000 norm=0.8760 [iter 400] loss=1.0728 val_loss=0.0000 scale=0.5000 norm=0.4335 [iter 0] loss=1.0916 val_loss=0.0000 scale=1.0000 norm=0.8912 [iter 100] loss=1.0427 val_loss=0.0000 scale=1.0000 norm=0.8570 [iter 200] loss=1.0181 val_loss=0.0000 scale=1.0000 norm=0.8457 [iter 300] loss=0.9983 val_loss=0.0000 scale=0.5000 norm=0.4184 [iter 400] loss=0.9851 val_loss=0.0000 scale=0.1250 norm=0.1038 [iter 0] loss=1.0335 val_loss=0.0000 scale=0.5000 norm=0.4383 [iter 100] loss=0.9770 val_loss=0.0000 scale=0.5000 norm=0.4138 [iter 200] loss=0.9631 val_loss=0.0000 scale=0.0625 norm=0.0512 [iter 300] loss=0.9562 val_loss=0.0000 scale=1.0000 norm=0.8154 [iter 400] loss=0.9329 val_loss=0.0000 scale=1.0000 norm=0.8045 [iter 0] loss=0.9574 val_loss=0.0000 scale=1.0000 norm=0.8287 [iter 100] loss=0.9319 val_loss=0.0000 scale=0.2500 norm=0.2022 [iter 200] loss=0.9109 val_loss=0.0000 scale=1.0000 norm=0.7964 [iter 300] loss=0.8991 val_loss=0.0000 scale=0.0625 norm=0.0493 [iter 400] loss=0.8882 val_loss=0.0000 scale=1.0000 norm=0.7830 [iter 0] loss=0.8637 val_loss=0.0000 scale=0.5000 norm=0.3900 [iter 100] loss=0.8436 val_loss=0.0000 scale=0.5000 norm=0.3836 [iter 200] loss=0.8306 val_loss=0.0000 scale=0.1250 norm=0.0951 [iter 300] loss=0.8146 val_loss=0.0000 scale=0.5000 norm=0.3763 [iter 400] loss=0.7969 val_loss=0.0000 scale=0.5000 norm=0.3729 [iter 0] loss=0.8511 val_loss=0.0000 scale=1.0000 norm=0.7840 [iter 100] loss=0.8124 val_loss=0.0000 scale=0.5000 norm=0.3757 [iter 200] loss=0.8016 val_loss=0.0000 scale=0.2500 norm=0.1867 [iter 300] loss=0.7897 val_loss=0.0000 scale=0.2500 norm=0.1849 [iter 400] loss=0.7801 val_loss=0.0000 scale=0.0078 norm=0.0057 [iter 0] loss=0.7869 val_loss=0.0000 scale=0.5000 norm=0.3685 [iter 100] loss=0.7765 val_loss=0.0000 scale=0.2500 norm=0.1822 [iter 200] loss=0.7660 val_loss=0.0000 scale=0.5000 norm=0.3609 [iter 300] loss=0.7621 val_loss=0.0000 scale=0.0625 norm=0.0450 [iter 400] loss=0.7573 val_loss=0.0000 scale=0.0010 norm=0.0007
np.mean(rmse_list)
1439701.6814596842
xgb = XGBRegressor(random_state = 518)
rmse_list = []
xgb_pred = np.zeros((test.shape[0]))
for tr_idx, val_idx in kf.split(X, y) :
tr_x, tr_y = X.iloc[tr_idx], y.iloc[tr_idx]
val_x, val_y = X.iloc[val_idx], y.iloc[val_idx]
xgb.fit(tr_x, tr_y)
pred = np.expm1([0 if x < 0 else x for x in xgb.predict(val_x)])
sub_pred = np.expm1([0 if x < 0 else x for x in xgb.predict(target)])
rmse = np.sqrt(mean_squared_error(val_y, pred))
rmse_list.append(rmse)
xgb_pred += (sub_pred / 10)
np.mean(rmse_list)
1437735.1546705803
cat = CatBoostRegressor(random_state = 518, silent = True)
rmse_list = []
cat_pred = np.zeros((test.shape[0]))
for tr_idx, val_idx in kf.split(X, y) :
tr_x, tr_y = X.iloc[tr_idx], y.iloc[tr_idx]
val_x, val_y = X.iloc[val_idx], y.iloc[val_idx]
cat.fit(tr_x, tr_y)
pred = np.expm1([0 if x < 0 else x for x in cat.predict(val_x)])
sub_pred = np.expm1([0 if x < 0 else x for x in cat.predict(target)])
rmse = np.sqrt(mean_squared_error(val_y, pred))
rmse_list.append(rmse)
cat_pred += (sub_pred / 10)
np.mean(rmse_list)
1075600.9209088846
rf = RandomForestRegressor(random_state = 518)
rmse_list = []
rf_pred = np.zeros((test.shape[0]))
for tr_idx, val_idx in kf.split(X, y) :
tr_x, tr_y = X.iloc[tr_idx], y.iloc[tr_idx]
val_x, val_y = X.iloc[val_idx], y.iloc[val_idx]
rf.fit(tr_x, tr_y)
pred = np.expm1([0 if x < 0 else x for x in rf.predict(val_x)])
sub_pred = np.expm1([0 if x < 0 else x for x in rf.predict(target)])
rmse = np.sqrt(mean_squared_error(val_y, pred))
rmse_list.append(rmse)
rf_pred += (sub_pred / 10)
np.mean(rmse_list)
872738.262092494
submission['box_off_num'] = (xgb_pred + cat_pred + rf_pred + gb_pred + ngb_pred) / 5
submission.sort_values(by = 'box_off_num')
| title | box_off_num | |
|---|---|---|
| 130 | 댄서김의 은밀한 교수법 | 3.500641e+00 |
| 39 | REC 알이씨 | 5.595946e+00 |
| 65 | 엄마는 창녀다 | 5.732548e+00 |
| 139 | 화려한 외출 | 6.338512e+00 |
| 173 | 옹녀뎐 | 6.895886e+00 |
| ... | ... | ... |
| 229 | 베테랑 | 3.681021e+06 |
| 135 | 용의자 | 4.283240e+06 |
| 142 | 박수건달 | 4.952007e+06 |
| 179 | 군도: 민란의 시대 | 6.536242e+06 |
| 178 | 명량 | 7.058888e+06 |
243 rows × 2 columns
----
데이터 전처리 하는 과정까지는 따라갈 수 있었는데 데이터 분석을 위해서 등급을 분리하고 중앙값과 평균값을 사용하는 과정은 이해하기 좀 어려웠다.
데이터 분석에 대해서 잘 알지 못하지만 이 부분이 데이터 분석하는데 있어서 분석가마다 다른 결과가 나오는 중요한 부분이라고 생각 됐다.
타켓값을 로그 변환하는 과정은 정규화 분포를 만들기 위한 과정이라고 찾아봤는데 솔직히 아직 잘 모르겠다. 앞으로 공부하면서 알아가야할듯ㅜ 한 번에 너무 많으 정보를 받아 들이면 과부하 오니까 천천히 하기로..
이번 글은 데이터 분석의 예시로 알아보기 위해서 데이콘에 있는 예시 자료를 가져와서 직접 실행해 보는 과정을 담았다.
앞으로 데이터 분석의 과정들을 공부하면서 오늘 실행한 코드를 자주 불러와서 예시로 들어볼 수 있을 것 같다.
'데이터분석' 카테고리의 다른 글
| 이디야는 스타벅스 근처에 입점한다? (0) | 2022.11.25 |
|---|---|
| 제주도 교통량 예측(1)_EDA (0) | 2022.10.11 |
| 데이터분석(4) - 타이타닉 생존자 구하기 (0) | 2022.06.27 |
| 데이터분석(3) - 랜덤 포레스트 (0) | 2022.06.07 |
| 데이터 분석(2) - 따릉이 수요량 예측 (0) | 2022.06.06 |