import cv2
import sys
#특정 키를 가지고 창을 끌때
print('Hellow, opencv', cv2.__version__)
# img= cv2.imread('cat.bmp') #img: image를 뜻함
img = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE) #BGR이미지를 gray로 열고 싶을때는 cv2.IMREAD_GRAYSCALE 삽입하기
#예외처리
if img is None: #영상 파일 불러오지 못했을때 실행되는 코드,
print('Image load failed!')
sys.exit()
cv2.imwrite('cat_gray.png', img) #컬러 이미지를 gray로 저장하기
cv2.namedWindow('image') #창을 하나 생성해주는 함수, 창 이름을 image 지정
#띄울 이미지가 크다면 이 함수를 적고 flags를 normal로 지정해서 창사이즈 변경가능하도록 설정
#이미지가 작으면 생략해도 cv2.imread가 알아서 창을 만들어준다(auto창, 사이즈 변경 불가)
cv2.imshow('image',img) #창에 영상을 보여주는 함수, 첫번째 인자는 띄울 창 이름, 두번째 인자는 띄울 이미지 , 그리고 키보드 입력 있을때 까지 대기
#특정 키를 눌렀을때 종료하도록 하는 코드, 아스킷을 이용
# while True:
# if cv2.waitKey()==27: #esc키의 아스킷 숫자 27
# break
#아스킷이 아닌 키보드알파벳을 이용할때
while True:
if cv2.waitKey()==ord('q'): #특정 알파벳을 눌러서 종료하고 싶을때는 ord() 안에 해당 알파벳 넣기
break
# key=cv2.waitKey(2000) #영상이 실제로 나올수 있게끔 하는 함수, 2000-> 2초
# print(key)
cv2.destroyAllWindows() #기존에 띄운 창을 모두 닫은 함수
여러 이미지로 슬라이드 쇼 생성하기
#슬라이드 쇼 만들기
import sys, os
import glob
import cv2
#문자열의 리스트 형태로 저장
img_files= glob.glob('.\\images\\*.jpg') #images안에 .jpg파일을 문자열로 모두 가져온다
for f in img_files:
print(f) #.\images\autumn_forest_park_128379_1920x1080.jpg 형태
#전체창 만들기setWindowProperty(), window normal로 만들어야 전체화면이 가능하다
cv2.namedWindow('image',cv2.WINDOW_NORMAL) #WINDOW_NORMAL속성의 창을 생성 후
cv2.setWindowProperty('image', cv2.WND_PROP_FULLSCREEN, #setWindowProperty를 통해 전체화면 속성으로 변경
cv2.WINDOW_FULLSCREEN)
cnt= len(img_files)
idx=0
while True:
img = cv2.imread(img_files[idx])
if img is None:
print('Image load failed!')
break
cv2.imshow('image',img)
if cv2.waitKey(1000)==27: #ESC
break
# if cv2.waitKey(1000)==0: #키보드 아무 값을 쳐도 0보다는 큼 즉 아무키 눌렀을때 꺼진다
#아무것도 안누르면 -1을 리턴
# break
idx +=1
if idx>=cnt:
idx=0
cv2.destroyAllWindows()
Matplot으로 영상 load
import matplotlib.pyplot as plt
import cv2
# 컬러 영상 출력
imgBGR = cv2.imread('cat.bmp')
#matplotlib은 RGB순서를 기대하기 때문에
#opencv BGR을 cvtColor통해서 RGB로 순서 변경 후 matplotlib에 적용
imgRGB = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2RGB)
plt.axis('off') #눈금 제거
plt.imshow(imgRGB)
plt.show()
# 그레이스케일 영상 출력
#2차원 형태로 되어 있다고 보면된다. 밝기 값만 있다
imgGray = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE)
plt.axis('off')
plt.imshow(imgGray, cmap='gray')
plt.show()
# 두 개의 영상을 함께 출력
plt.subplot(121), plt.axis('off'), plt.imshow(imgRGB) #컬러버전
plt.subplot(122), plt.axis('off'), plt.imshow(imgGray, cmap='gray') #gray버전
plt.show()
영상불러오기 & 픽셀 값 변경
import sys
import cv2
# 영상 불러오기
img1 = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('cat.bmp', cv2.IMREAD_COLOR)
if img1 is None or img2 is None:
print('Image load failed!')
sys.exit()
#영상의 크기를 참조하는 방법
#그레이스케일
h,w = img1.shape
print('w x h= {} x {}'.format(w,h))
#컬러-> 에러뜸 왜? (w,h) 크기의 3개 이미지를 두개 변수로 받을려고 했기 때문에
# h,w = img2.shape
# print('w x h= {} x {}'.format(w,h))
#해결방법-> (w,h,c) 에서 w,h만 가져오도록 [:2] 적용
h,w = img2.shape[:2] #그레이스케일에 사용해도 무방
print('w x h= {} x {}'.format(w,h))
#영상의 픽셀 값을 참조하는 방법
#영상의 (20,10)좌표의 픽셀 값을 알고 싶을때
x=20
y=10
p1= img1[y,x]
print(p1) #grayscale 픽셀값이 238(밝은 편)
p2= img2[y,x]
print(p2) # [237 242 232] 블루,그린,레드 순
#이를 이용해서 특정 픽셀값에 내가 원하는 값을 대입 할수있다
'''
for y in range(h): #각 픽셀을 for문으로 돌아다니면서 아래 조건으로 픽셀값을 바꾸는 코드-> 느림
for x in range(w):
img1[y,x]=0 #검정색
img2[y,x]=(0,255,255) #노란색
'''
#위코드는 사용 지양(느림),아래코드 추천
img1[:, :] = 0
img2[:, :] = (0,255,255)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
# cv2.waitKey()
cv2.destroyAllWindows()
부분영상 추출 & 복사
import numpy as np
import cv2
# 새 영상 생성하기
img1 = cv2.imread('HappyFish.jpg') #물고기 그림
img2=img1[50:160, 150:300]
img3=img1[50:160, 150:300].copy()
#(105,225) 좌표에, 반지름 20, 컬러는 (0,0,255), 두께2
#(x, y)
#이미지를 짜른 순간 좌표는 짤려진 이미지 좌측 상단이 0,0으로 초기화
cv2.circle(img2, (50,50), 20, (0,0,255),2)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
# cv2.imshow('img3', img3)
cv2.waitKey()
cv2.destroyAllWindows()
마스크 연산 & ROI
import sys
import cv2
# 마스크 영상을 이용한 영상 합성
# src = cv2.imread('airplane.bmp', cv2.IMREAD_COLOR)
# mask = cv2.imread('mask_plane.bmp', cv2.IMREAD_GRAYSCALE)
src =cv2.imread('opencv-logo-white.png', cv2.IMREAD_UNCHANGED)
#알파와 BGR 구성
mask =src[:, :, -1] #투명한 알파 채널
src= src[:, :, 0:3] #BGR만 따로
dst = cv2.imread('field.bmp', cv2.IMREAD_COLOR)
h,w = src.shape[:2]
crob= dst[0:h,0:w] #직접 dst 사진의 좌표를 지정해서 위치를 알려줘야 한다
#CV2를 이용한 방법
# cv2.copyTo(src, mask,dst) #crob을 넣지않고 왼쪽 코드처럼 실행하면 로고와 dst 크기가 맞지 않아서 합성이 안됨
cv2.copyTo(src, mask,crob)
#numpy로 이용한 방법
# dst[mask>0] = src[mask>0] #마스크가 0이상인 부분에 True값이 반환 될것이고 그 반환된
#그 자리 그대로 src자리에 대입되면, 비행기가 싹뚝 뽑혀서 dst의 True위치에 비행기를 넣는다
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.imshow('mask', mask)
cv2.waitKey()
cv2.destroyAllWindows()
==================카메라 실습=========================
cap = cv2.VideoCapture()
# cap.open(0) #기본 카메라를 open하겠다는 의미
# cap = cv2.VideoCapture(0) #위와 같은 결과
# if not cap.isOpened(): #카메라 제대로 열렸는지 확인
# print('camera open failed')
# sys.exit()
# #카메라의 가로,세로를 가져오는 방법
# w= int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
# h= int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# print(w, h)
# # #카메라 크기를 변경하는 방법- 내 컴퓨터에는 지원 안되는듯
# # cap.set(cv2.CAP_PROP_FRAME_WIDTH),320)
# # cap.set(cv2.CAP_PROP_FRAME_HEIGHT),240)
# # print(w, h)
# #한 프레임씩 계속 받아오는 코드 생성
# while True:
# #프레임을 받아오는 함수 는 cap.read()
# #read()가 리턴하는 것이 두가지 : ret(불리언), image
# #불리언의 True: 사진이 제대로 받은경우
# #즉 read()는 불리언과 ndarray(이미지) 두가지를 준다
# ret, frame = cap.read() #현재 열려 있는 카메라 디바이스에서 한 프레임씩 받아오는 작업을 한다
# if not ret: #True가 아니면
# break
# #이 부분에는 가져온 정지 영상을 처리하는 코드를 작성 할수 있다
# #윤곽선 추출
# edge= cv2.Canny(frame,50,150)
# cv2.imshow('edge',edge)
# cv2.imshow('frame',frame) #'frame'의 창은 굳이 만들지 않아도 알아서 만든다(특이 경우는 예외)
# if cv2.waitKey(20)==27: #20ms를 기다리고 꺼진다 하지만 여기에 ESC를 누르면 while문을 빠져나온다
# break
# cap.release() #open했던 cap을 해체 시킨다
# cv2.destroyAllWindows()
# ======================동영상 실습==============================
import sys
import cv2
# 카메라 열기
cap = cv2.VideoCapture('video1.mp4')
if not cap.isOpened():
print("video open failed!")
sys.exit()
# 카메라 프레임 크기 출력
print('Frame width:', int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)))
print('Frame height:', int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# 카메라 프레임 처리
while True:
ret, frame = cap.read()
if not ret:
break
edge= cv2.Canny(frame,50,150)
# inversed = ~frame # 반전
cv2.imshow('edge',edge)
cv2.imshow('frame', frame)
# cv2.imshow('inversed', inversed)
if cv2.waitKey(20) == 27:
break
cap.release()
cv2.destroyAllWindows()
카메라와 동영상 처리2
import sys
import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Camera open failed!")
sys.exit()
w = round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) #float형태로 나오기 때문에 정수로 만들기 위해서
h = round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
#DIVX를 이용해서 정수값을 리턴해준다 fourcc : 압축 방식
fourcc = cv2.VideoWriter_fourcc(*'DIVX') # *'DIVX' == 'D', 'I', 'V', 'X'
delay = round(1000 / fps) #프레임간의 시간간격
out = cv2.VideoWriter('output.avi', fourcc, fps, (w, h)) #컬러영상 저장
if not out.isOpened():
print('File open failed!')
cap.release()
sys.exit()
while True:
ret, frame = cap.read()
if not ret:
break
# inversed = ~frame
edge= cv2.Canny(frame, 50,150) #edge는 그레이라서 컬러로 바꾼다음에 저장해야 19번 코드와 호환됨
edge_color= cv2.cvtColor(edge, cv2.COLOR_GRAY2BGR)
#out.write(frame) #소리는 x, 영상만 저장됨
out.write(edge_color)
cv2.imshow('frame', frame)
cv2.imshow('edge', edge)
cv2.imshow('edge_color', edge_color)
# cv2.imshow('inversed', inversed)
if cv2.waitKey(delay) == 27:
break
cap.release()
out.release()
cv2.destroyAllWindows()
변수 선택 Part에서 A/B test를 실습했습니다. 기본 변수를 정하고 하나씩 교차검증을 진행하는 내용이였는데
변수의 수가 100개 넘는데 이걸 하나씩 검증했다는 것자체에 좀 놀랬습니다
이렇게 까지해야 일등을 하는구나 생각이 들었어요 이 부분도 분명히 일일이 넣었다 뺐다 하지 않고
코딩으로 구현 하셨을텐데 개인적으로 어떻게 하셨을지 궁금하네요
A/B테스트를 말로만 들었지 실제로 실습과정에서 적용한 예시는 처음 본 것같습니다
하이퍼 파라미터 튜닝에도 저는 항상 그리드만 사용했는데 임의 탐색이라는 또다른 방법이 있었더라구요
그리드는 시간이 오래 걸리는 단점이 있어서 이를 보완할 방법으로 임의탐색이 있다고 소개합니다
저도 진행하면서 그리드가 너무 오래걸려서 불편한 적이 여러번 있었는데 다음에 기회가 생긴다면 임의탐색을 사용해보고싶네요
몇달전에 앙상블 처음 배우면서 들었던 것이 완성된 모델을 앙상블하는 방법은 있을까 생각한 적이 있었는데
이거를 오늘 보게 되었습니다! 5개의 모델을 만들고 이를 앙상블해서 더욱 일반화 성능에 가까운 수치를 얻을수 있다고 합니다. 이 부분도 매력적으로 보였어요 정말 다양한 방법들이 많더라구요. 제가 들은 얘기로는 이렇게 고도의 앙상블은 실제로 사용되지 않는다고 알고 있어요 그러니까 완전 대회용으로 앙상블을 사용한다고 하더라구요 (제가 듣기로는..)
아무튼 데이콘 1등 코드를 1장과 3장을 실습해 봤어요
제가 이번 실습 직전에 택시수요예측을 진행했는데 ... 하.. 부끄럽더라구요 .. 뭔가 다 틀린것같고 ㅋㅋ 자신이 없어졌습니다 ㅎㅎ; 이 실습을 진행 후 택시예측을 했다면 좀더 세련된 프로젝트가 되었을 텐데 좀 아쉽습니다
하지만 이 경험 덕분에 프로젝트를 어떻게 하는지에 대한 방향을 잡을수 있었습니다 정~말 좋은 선생님에게 코치 받은 느낌이였어요
내일부터는 컵퓨터 비전 강의를 들으면서 실습한 내용을 업로드 할 예정입니다. open CV를 해야지 해야지 했는데
2015년 5월의 yellow 뉴욕택시 데이트를 사용해서 수요량을 예측합니다. 시간은 30분 단위로 진행되었으며 주 평가척도는 mae입니다. 외부데이터는 날씨 데이터를 참고했으며 LSTM, Gru의 timestep은 메모리 크기에 맞게 유동적으로 변경하면서 진행했습니다.
목차
1. EDA
1. 1 EDA(Region)
1.1.1 퍼센트 별 Trip_cnt
1.1.2 zip_code별 Trip_cnt
1.2 EDA(Time)
1.2.1 시간
1.2.2 요일
1.2.3 주말
2. 데이터전처리
2.1 target 분포 확인 / log 적용
2.2 날씨변수 추가
2.3 Scaling
2.4 PCA 생성
2.5 원핫인코딩
Train/Test Dataset
3. 모델 구축과 검증
3.1 XGBoost
3.1.1 GridSearch
3.1.2 최적 파라미터 적용
3.2 LightGBM
3.2.1 GridSearch
3.2.2 최적 파라미터 적용
3.2.3 LightGBM_PCA삭제 한 모델 검증
3.3 스태킹 앙상블(zip_code 7개로 축소한 모델)
3.3.1 개별 Model 학습&평가
3.3.2 스태킹 최종 모델 결과
3.4 CV기반의 스태킹
3.4.1 CV 함수정의
3.4.2 개별 Model 학습&평가
3.4 딥러닝
3.4.1 TimeStep 설정
3.4.2 Scaling
3.4.3 Train, Test Dataset
3.4.4. Model 설정
3.4.4.1 기본모델
3.4.4.2 LSTM
3.4.4.3 LSTM(layter1)
3.4.4.3 LSTM(layter2+ DropOut)
3.4.4.4 LSTM(layter3+ DropOut)
3.4.4.5 Gru
3.4.4.6 Gru(layter1)
3.4.4.7 Gru (layter2+ DropOut)
Import
!pip install chart_studio
import chart_studio.plotly as py
import cufflinks as cf
import pandas as pd
import numpy as np
import seaborn as sns
import math
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
%%time
base_query="""
WITH base_data AS
(
SELECT nyc_taxi.*, gis.* EXCEPT (zip_code_geom)
FROM (
SELECT *
FROM `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2015`
WHERE
EXTRACT(MONTH from pickup_datetime) = 5
and pickup_latitude <= 90 and pickup_latitude >= -90
) AS nyc_taxi
JOIN (
SELECT zip_code, state_code, state_name, city, county, zip_code_geom
FROM `bigquery-public-data.geo_us_boundaries.zip_codes`
WHERE state_code='NY'
) AS gis
ON ST_CONTAINS(zip_code_geom, st_geogpoint(pickup_longitude, pickup_latitude))
)
SELECT
zip_code,
DATETIME_TRUNC(pickup_datetime, hour) as pickup_hour,
concat (format_datetime("%F %H:",pickup_datetime),
case floor(extract(minute from pickup_datetime)/30) when 1.0 then 30 else 00 end) as minute,
EXTRACT(MONTH FROM pickup_datetime) AS month,
EXTRACT(DAY FROM pickup_datetime) AS day,
CAST(format_datetime('%u', pickup_datetime) AS INT64) -1 AS weekday,
EXTRACT(HOUR FROM pickup_datetime) AS hour,
CASE WHEN CAST(FORMAT_DATETIME('%u', pickup_datetime) AS INT64) IN (6, 7) THEN 1 ELSE 0 END AS is_weekend,
round(sum(passenger_count)) AS passenger_cnt, #승객수
round(sum(trip_distance)) AS trip_cnt, #운행거리
round(sum(total_amount)) AS total_amount_cnt, #승객에게 부과된 택시비
COUNT(*) AS cnt #콜 수
FROM base_data
GROUP BY zip_code, pickup_hour, month, day, weekday, hour, is_weekend,minute
ORDER BY zip_code,pickup_hour
"""
base_df = pd.read_gbq(query=base_query, dialect='standard', project_id='abcd')
30분 단위로 나눕니다 (minute 변수로 지정)
EDA(Region)_퍼센트 별 trip_cnt
#전체 콜 대비 각 zip_code 비율
zipcode_sum=base_df.groupby(['zip_code'])[['cnt']].sum()
zipcode_sum
import numpy as np
from lightgbm import LGBMRegressor
from xgboost import XGBRegressor
from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor, AdaBoostRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import KFold
from sklearn.metrics import mean_absolute_error
import pandas as pd
import numpy as np
import seaborn as sns
import math, time
import matplotlib.pyplot as plt
1.1 target 분포 확인 및 log 적용
#target분포 확인
y_target= base_df['cnt']
y_target.hist()
# target log화(정규분포와 최대한 비슷하게 만들기 위함)
y_log=np.log1p(y_target)
#log_cnt 삽입
base_df['log_cnt']=y_log
y_log.hist()
1.2 날씨 변수 추가
#날씨 정보를 추가
#bad: 비가 내린 날, normal: 비가 내리지 않은 날
base_df["wheather"] = base_df["day"].apply(lambda x: 'bad' if x==16 or x==27 else "normal")
1.3 Scaling
from sklearn.preprocessing import StandardScaler
#객체 생성
scaler=StandardScaler() #기존 변수의 범위를 정규 분포로 변환
#강한 상관관계를 보인 passenger_cnt, total_amount_cnt는 차원축소로 변환할 예정
scaled_df=scaler.fit_transform(base_df[['passenger_cnt','trip_cnt','total_amount_cnt','cnt']])
#PCA 할 변수와 target 변수 분리
scaled_df=pd.DataFrame(scaled_df).iloc[:,0:3]
#기존 passenger_cnt, total_amount_cnt 변수 삭제
base_df.drop(['passenger_cnt','total_amount_cnt'], axis=1, inplace=True)
del scaled_df[1] #trip_cnt 삭제
scaled_df=pd.DataFrame(scaled_df).rename(columns={0:"passenger_cnt",2:'total_amount_cnt'})
scaled_df
1.4 PCA
# 2개의 변수를 하나로 저차원 축소
from sklearn.decomposition import PCA
pca= PCA(n_components=1)
pca.fit(scaled_df)
pca_result= pca.transform(scaled_df)
print(pca_result,pca_result.shape)
[[ 3.87046796]
[ 3.2337383 ]
[ 1.69928273]
...
[-0.70746083]
[-0.70026516]
[-0.7066679 ]] (158514, 1)
전체 데이터로는 Corab에서 실행 불가능하므로 데이터 수가 많은 상위 7개의 zip_code를 대상으로 분석함
EDA 시각화 중에서 heatmap 참고하여 데이터가 많은 zip_code을 골랐습니다.
개별 Model 설정&평가
#개별 ML 모델 생성
svr_reg= SVR()
rf_reg= RandomForestRegressor(n_estimators=100,random_state=0)
dt_reg= DecisionTreeRegressor()
ada_reg= AdaBoostRegressor(n_estimators=100)
#스태킹으로 만들어진 데이터세트를 학습,예측할 최종모델
lgbm_reg= LGBMRegressor(n_estimators=300, random_state= 150, learning_rate=0.01, max_depth=5)
#개별 모델 학습
svr_reg.fit(x_train,y_train_log)
rf_reg.fit(x_train,y_train_log)
dt_reg.fit(x_train,y_train_log)
ada_reg.fit(x_train,y_train_log)
# 학습된 개별 모델들이 각자 반환하는 예측 데이터 세트를 생성하고 개별모델의 정확도 측정
svr_pred=svr_reg.predict(x_test)
rf_pred=rf_reg.predict(x_test)
dt_pred=dt_reg.predict(x_test)
ada_pred=ada_reg.predict(x_test)
#평가
svr_score=evaluate(y_test_log, svr_pred)
rf_score=evaluate(y_test_log, rf_pred)
dt_score=evaluate(y_test_log, dt_pred)
ada_score=evaluate(y_test_log, ada_pred)
print(pd.concat([svr_score,rf_score,dt_score,ada_score],axis=1))
#각 개별 분류기의 예측값은 1차원 형태이므로 이걸 행 형태로 붙인 뒤 transpose를 취하여 데이터 세트로 만든다
#4행 형태로 붙인다
pred= np.array([svr_pred, rf_pred,dt_pred,ada_pred])
print(pred.shape)
# transpose로 행과 열의 위치 교환하여 각 컬럼끼리 위치가 맞도록 해준다
final_pred=np.transpose(pred)
print(final_pred.shape)
(4, 2688)
(2688, 4)
스태킹 최종 모델 결과
# 최종 메타 모델인 LightGBM를 실시
lgbm_reg.fit(final_pred, y_test_log)
final=lgbm_reg.predict(final_pred)
evaluate(y_test_log,final)
가장 낮은 에러 성능 수치를 보입니다.
이번에는 CV를 적용하여 스태킹을 재 실행해 보겠습니다.
CV 기반의 스태킹
def get_stakong_base_datasets(model, x_train, y_train, x_test, n_folds):
from sklearn.model_selection import KFold
from sklearn.metrics import mean_absolute_error
kf = KFold(n_splits=n_folds, shuffle=False, random_state=0)
train_fold_pred=np.zeros((x_train.shape[0],1)) #x_train에서 n_folds수 만큼 학습,검증폴드 분리됨, 즉 검증세트=x_train.shape[0] 될때까지 진행
test_pred= np.zeros((x_test.shape[0],n_folds)) #x_test의 예측값이 n_folds수 만큼 생성됨
print(model.__class__.__name__,'model start')
for folder_counter, (train_idx, valid_idx) in enumerate(kf.split(x_train)):
print('\n폴드세트:', folder_counter,'학습/검증폴드 생성')
train_x= x_train[train_idx] #x_train의 학습폴드
train_y= y_train[train_idx] #y_train의 학습폴드
test_x= x_train[valid_idx] #x_train의 검증폴드
#학습폴드 인덱드에 해당하는 x_train, y_train를 가지고 fit 진행
model.fit(train_x,train_y)
#학습한 model를 검증폴드 예측(최종모델의 학습 데이터로 사용)
train_fold_pred[valid_idx,:]=model.predict(test_x).reshape(-1,1)
#학습한 model를 원본 테스트 데이터인 x_test 예측
test_pred[:,folder_counter]=model.predict(x_test)
#x_test를 예측한 값을 열 기준으로 평균내고 세로로 쌓는다(최종모델의 test 데이터로 사용)
test_mean=np.mean(test_pred, axis=1).reshape(-1,1)
return train_fold_pred,test_mean
개별 Model 설정&평가
#개별 ML 모델 생성
svr_reg= SVR()
rf_reg= RandomForestRegressor(n_estimators=100,random_state=0)
dt_reg= DecisionTreeRegressor()
ada_reg= AdaBoostRegressor(n_estimators=100)
#스태킹으로 만들어진 데이터세트를 학습,예측할 최종모델
lgbm_reg= LGBMRegressor(n_estimators=300, random_state= 150, learning_rate=0.01, max_depth=5)
#ndarray로 변경(안하면 get_stakong_base_datasets 적용 x)
x_train=np.array(x_train)
y_train_log=np.array(y_train_log)
x_test=np.array(x_test)
stack_final_x_train=np.concatenate((svr_train,rf_reg_train,dt_reg_train,ada_train),axis=1)
stack_final_x_test=np.concatenate((svr_test,rf_reg_test,dt_reg_test,ada_test), axis=1)
print('원본 학습 피처 데이터 shape:', x_train.shape, '원본 테스트 피처 shape:',x_test.shape)
print('스태킹 학습 피처 데이터 shape:', stack_final_x_train.shape, '스태킹 테스트 피처 데이터 shape:',stack_final_x_test.shape)
원본 학습 피처 데이터 shape: (7728, 68) 원본 테스트 피처 shape: (2688, 68)
스태킹 학습 피처 데이터 shape: (7728, 4) 스태킹 테스트 피처 데이터 shape: (2688, 4)
lgbm_reg.fit(stack_final_x_train,y_train_log) #원본 학습 label과 fit
stack_final=lgbm_reg.predict(stack_final_x_test)
evaluate(y_test_log,stack_final)
CV 적용하기 전에 비해 성능이 안 좋아졌습니다.
CV를 적용한다고 무조건의 성능개선은 이뤄지진 않습니다.
LSTM, GRU를 활용해서 딥러닝에서의 성능은 어떨지 실행해 보겠습니다.
딥러닝
Import
import tensorflow as tf
from tensorflow.keras.layers import Input, LSTM, GRU, Dense,Dropout
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras import layers
from tensorflow.keras.optimizers import SGD, Adam, RMSprop
from tensorflow.keras import models
from tensorflow.keras.wrappers.scikit_learn import KerasRegressor
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import make_regression
import seaborn as sns
import numpy as np
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
T=620 #2시간 과거 데이터
N=len(input_data)-T
D=input_data.shape[1]
#데이터 넣을 공간 만들기
x=np.zeros((N,T,D))
y_log=np.zeros(N)
y_raw=np.zeros(N)
for t in range(N):
x[t,:,:]= input_data[t:t+T]
y_log[t]= label_log[t+T]
y_raw[t]= label_raw[t+T]
print(x.shape, y_log.shape)
(6789, 651, 65) (6789,)
f['interval']=interval_lst #interval_lst를 interval 변수로 생성
#interval 변수의 값을 문자형으로 변환 후 시:분:초 형태로 변환
f['interval']=f['interval'].astype(str).str[7:].replace("","00:00:00") #??
f['bus_route_id']=f['bus_route_id'].astype(object) #?
위에 이미지처럼 형태가 통일이 되지 않았습니다 이를 통일시키기 위해서 위 코드를 사용했는데
replace의 00:00:00에서 막히더라구요 제가 알고 있는 replace는 값 자체를 바꿔주는 것으로 알고있습니다
만일 Timedelta('0 days 01:26:44') 라면 replace는 01:26:44게 아니고 00:00:00이아닌가싶은거죠
밑에 object도 왜 해야하는지 아직 모르겠습니다 구글링을 잠깐 해봤는데 원하는 답은 못구했습니다
#시간변수를 생성하느 함수 정의
def lag_function(df,var_name, past):
# df = 시간변수를 생성할 데이터 프레임
# var_name= 시간변수 생성의 대상이 되는 변수 이름
# past= 몇 년 전의 성적을 생성할지 결정(정수형)
df.reset_index(drop=True, inplace=True)
#시간변수 생성
df['lag'+str(past)+'_'+var_name] = np.nan #결측치로 채워 넣어 놓는다
df['lag'+str(past)+'_'+'AB'] = np.nan
for col in ['AB',var_name]:
for i in range(0, (max(df.index)+1)):
val=df.loc[(df['batter_name']==df['batter_name'][i])& #이름이 가르시아 이면서
(df['year']==df['year'][i]-past),col] #년도는 i년도
#과거 기록이 결측치가 아니라면 값을 넣기
if len(val)!=0:
df.loc[i,'lag'+str(past)+'_'+col]=val.iloc[0] #i번째 행에 삽입
#30타수 미만 결측치 처리
df.loc[df['lag'+str(past)+'_'+'AB']<30,
'lag'+str(past)+'_'+var_name]=np.nan #var_name 행의 존재하는 30미만은 제거하고
df.drop('lag'+str(past)+'_'+'AB', axis=1, inplace=True) #AB열을 제거 하여 var_name만 남김
return df
위 코드를 이해 하는데 1시간이상이 걸렸어요
교재에는 짧게 설명이 되어 있어서 이 함수를 왜 만들고 무엇을 위한 목적인지 파악하는데 조차
이해가 안되었어요
일정도 새로 넉넉하게 짜야 할것같구요
이 실습에 대해서 어떤 방향으로 공부 할지 고민좀 해봐야 할것같아요
한번 실습했다고 제 것이 될것같진 않더라구요
코드도 공부가 되지만 일단 인사이트를 어떤 식으로 뽑는지 그런 견문을 넓히는게 우선인 것같네요