MAE와 RMSE 함수 구현하기
- 다음과 같이 실제 값과, 모델이 예측한 값이 각각 100개가 있다
- 실제값과 예측값 사이에 평균 오차를 구하는 함수 두개를 구현하자
>>> np.random.seed(42)
# 정답값
>>> target = np.random.randint(50, 91,100)
# 예측값
>>> pred = np.random.randint(40, 100,100)
>>> target , pred
(array([88, 78, 64, 57, 70, 88, 68, 72, 60, 60, 73, 85, 89, 73, 52, 71, 51,
73, 79, 87, 51, 70, 82, 61, 71, 74, 76, 77, 65, 64, 52, 86, 56, 70,
58, 88, 67, 53, 74, 63, 58, 75, 51, 69, 77, 56, 57, 84, 63, 66, 85,
89, 53, 51, 55, 53, 78, 67, 75, 83, 59, 85, 63, 80, 64, 57, 63, 72,
89, 70, 65, 67, 73, 75, 74, 90, 78, 64, 50, 74, 56, 58, 73, 50, 57,
73, 60, 66, 57, 84, 84, 82, 54, 88, 90, 77, 56, 58, 57, 61]),
array([73, 72, 87, 94, 62, 63, 76, 74, 83, 79, 61, 66, 74, 40, 74, 76, 86,
53, 42, 40, 44, 65, 94, 53, 78, 66, 48, 54, 54, 65, 81, 99, 52, 90,
71, 78, 88, 91, 71, 43, 69, 76, 62, 78, 84, 54, 82, 68, 75, 52, 71,
46, 98, 90, 61, 67, 41, 81, 84, 96, 92, 45, 67, 67, 83, 83, 59, 69,
50, 97, 94, 67, 64, 78, 72, 40, 96, 66, 96, 91, 52, 80, 42, 78, 45,
47, 66, 48, 76, 72, 90, 81, 83, 63, 54, 98, 93, 71, 71, 63]))
MAE(Mean Absolute Error)
- 실제 값과 예측 값의 차이를 절댓값으로 변환해 평균화 하는 것
>>> def mae(target,pred):
# 절대값을 구하고 감싸줘서 전체 평균 구해주기
>>> return np.mean(np.abs(target-pred))
>>> mae(target,pred)
17.8
절대값을 구하는 함수: np.abs(x)
RMSE(Root Mean Squared Error)
- 실제 값과 예측 값의 차이를 제곱한 뒤 평균화 후 루트
>>> def rmse(target,pred):
>>> return np.sqrt(np.mean(np.square(target-pred)))
>>> rmse(target,pred)
21.829796151132516
시그모이드 함수 구현하기
- S와 같은 형태로 미분 가능한 0~1 사이의 값을 반환
- 이진 분류에 출력 함수로 사용
# x 변수에 있는 배열의 요소들을 시그모이드 함수에 넣어 0 ~ 1 사이 값들로 변경하시오.
>>> np.random.seed(42)
>>> x = np.random.randint(-10,10,10)
>>> x
array([-4, 9, 4, 0, -3, -4, 8, 0, 0, -7])
>>> def sigmoid(x):
>>> return 1 / (1 + np.exp(-x))
>>> sigmoid(x)
array([1.79862100e-02, 9.99876605e-01, 9.82013790e-01, 5.00000000e-01,
4.74258732e-02, 1.79862100e-02, 9.99664650e-01, 5.00000000e-01,
5.00000000e-01, 9.11051194e-04])
Q.
3행 2열형태의 배열에서 두개 열 위치를 바꾸시오
>>> np.random.seed(42) >>> arr = np.random.randint(50,100,[3,2]) >>> arr array([[88, 78], [64, 92], [57, 70]])
>>> arr[:,::-1]
array([[78, 88],
[92, 64],
[70, 57]])
>>> arr[:,[1,0]]
array([[78, 88],
[92, 64],
[70, 57]])
Q.
다음의 배열에서 각행의 평균을 구하시오.
>>> np.random.seed(42) >>> arr = np.random.randint(50, 101, (4, 3)) >>> arr array([[88, 78, 64], [92, 57, 70], [88, 68, 72], [60, 60, 73]])
>>> arr.mean(axis=1)
array([76.66666667, 73. , 76. , 64.33333333])
데이터 설명
- 시계열 학습이 가능한 형태로 변환되 있다
- 행마다 10일치의 시작가 ,상한가 , 하한가, 종가 에 대한 행렬이 들어가 있다
>>> samsung_stock_3d = np.load("samsung_stock_2021_3d.npy")
>>> samsung_stock_3d.shape
(234, 10, 4)
어떻게 생겼나 분석해보자
- 한행을 보면 2차원 행렬 형태
- 행은 일자
- 열은 시작가, 상한가, 하한가, 종가 순이다
>>> samsung_stock_3d[0]
array([[81000, 84400, 80200, 83000],
[81600, 83900, 81600, 83900],
[83300, 84500, 82100, 82200],
[82800, 84200, 82700, 82900],
[83300, 90000, 83000, 88800],
[90000, 96800, 89500, 91000],
[90300, 91400, 87800, 90600],
[89800, 91200, 89100, 89700],
[88700, 90000, 88700, 89700],
[89800, 91800, 88000, 88000]])
samsung_stock_3d 변수의 3차원 데이터에 각 행의 행렬을 벡터 형태로 변환하여 데이터셋을 2차원형태로 변경하여 samsung_stock_2d 라는 변수에 담으세요.
>>> samsung_stock_avg = samsung_stock_3d.mean(axis=1)
>>> samsung_stock_avg.shape
(234, 40)
samsung_stock_3d 변수의 3차원 데이터에 각 행의 시작가 ,상한가 , 하한가, 종가별로 평균을 구해 2차원 형태로 변경하여 samsung_stock_avg 라는 변수에 담으세요
>>> samsung_stock_avg = samsung_stock_3d.mean(axis=1)
>>> samsung_stock_avg.shape
(234, 4)
5번과 6번에서 생성한 변수들의 데이터를 옆으로 합쳐서 x_train 변수에 넣어주세요.
>>> x_train = np.concatenate([
>>> samsung_stock_2d,
>>> samsung_stock_avg
>>> ],axis=1)
>>> x_train.shape
배열 결합 (np.concatenate)
- 선택한 축(axis)의 방향으로 배열을 연결해주는 메소드
- concatenate: '사슬 같이 연결하다'
- axis 값을 조절하여 어떤 축을 기준으로 배열을 합칠지 정할 수 있음
- numpy.vstack() : axis=0으로 한 numpy.concatenate()와 동일
# ones는 zeros와 마찬가지로 1로 가득찬 array 생성
>>> a1 = np.ones((2, 3), int)
>>> print(a1)
[[1 1 1]
[1 1 1]]
# np.full((행,열),출력되는 값)
>>> a2 = np.full((2, 3),2)
>>> print(a2)
[[2 2 2]
[2 2 2]]
# 둘이 값 동일
>>> print(np.vstack([a1, a2]))
[[1 1 1]
[1 1 1]
[2 2 2]
[2 2 2]]
>>> print(np.concatenate([a1, a2], 0))
[[1 1 1]
[1 1 1]
[2 2 2]
[2 2 2]]
# 부록: 가로로 출력하기
>>> print(np.concatenate([a1, a2], 1))
[[1 1 1 2 2 2]
[1 1 1 2 2 2]]
x_train변수의 각 특성(열)들에 최대값과 최소값들 구하시오
>>> mins, maxs = np.quantile(x_train,[0,1],axis=0)
>>> mins , maxs
(array([68700., 69600., 68300., 68800., 68700., 69600., 68300., 68800.,
68700., 69600., 68300., 68800., 68700., 69600., 68300., 68800.,
68700., 69600., 68300., 68800., 68700., 69600., 68300., 68800.,
68700., 69600., 68300., 68800., 68700., 69600., 68300., 68800.,
68700., 69600., 68300., 68800., 68700., 69600., 68300., 68800.,
70040., 70550., 69510., 69920.]),
array([90300., 96800., 89500., 91000., 90300., 96800., 89500., 91000.,
90300., 96800., 89500., 91000., 90300., 96800., 89500., 91000.,
90300., 96800., 89500., 91000., 90300., 96800., 89500., 91000.,
90300., 91800., 89100., 90600., 89800., 91800., 89100., 89700.,
89800., 91800., 88700., 89700., 89800., 91800., 88000., 89400.,
88520., 90410., 87060., 88510.]))
np.quantile
quantile은 4분위수, percentile은 100분위수를 의미
x_train변수의 각 특성(열)들에 분위수기준으로 5% 지점값들과 95% 지점값들을 구하시오
>>> q05 , q95 = np.quantile(x_train,[0.05,0.95],axis=0)
>>> q05 , q95
(array([70300. , 70965. , 70000. , 70200. , 70300. , 70965. , 70000. ,
70200. , 70300. , 70965. , 70000. , 70200. , 70300. , 70965. ,
70000. , 70200. , 70300. , 70965. , 70000. , 70200. , 70300. ,
70965. , 70000. , 70200. , 70300. , 70965. , 70000. , 70200. ,
70300. , 70965. , 70000. , 70200. , 70300. , 70965. , 70000. ,
70200. , 70300. , 70965. , 70000. , 70200. , 70666.5, 71169.5,
70043. , 70430. ]),
array([86340. , 87805. , 85205. , 86245. , 86340. , 87805. , 85205. ,
86245. , 86340. , 87805. , 85205. , 86245. , 86340. , 87805. ,
85205. , 86245. , 86340. , 87805. , 85205. , 86245. , 86340. ,
87440. , 85205. , 85740. , 86135. , 86715. , 84905. , 85600. ,
85905. , 86270. , 84410. , 85470. , 85735. , 86200. , 84135. ,
85335. , 85310. , 86070. , 84100. , 85105. , 86088. , 87506. ,
84803.5, 85781. ]))
이상치를 제거해보기
- x_train변수의 특성(열)들에 분위수 기준 5% 지점의 미만값들을 5% 지점값으로 변경하고
- 95% 지점을 초과하는 값들을 95% 지점값으로 변경해보세요.
>>> x_train = np.clip(x_train, q05 , q95)
>>> x_train
array([[81000. , 84400. , 80200. , ..., 87506. , 84803.5, 85781. ],
[81600. , 83900. , 81600. , ..., 87506. , 84803.5, 85781. ],
[83300. , 84500. , 82100. , ..., 87506. , 84803.5, 85781. ],
...,
[78300. , 78600. , 77100. , ..., 78010. , 76840. , 77490. ],
[77400. , 78200. , 77000. , ..., 78090. , 77010. , 77690. ],
[77400. , 77600. , 76800. , ..., 78270. , 77240. , 77860. ]])
여기서부터 모르겠는데 그냥 적어 놓겠음
x_train 데이터셋에서 20%의 데이터의 인덱스들을 리스트에 담아 5번 랜덤하게 반환하는 제너레이터(리스트 형태로 반환 가능) 함수를 만들어주세요
- 단, 5번 랜덤하게 반환하는 과정에서 동일한 행의 인덱스가 나오면 안됨
- 한번 나온 행의 인덱스는 다시 나오면 안된다는 의미
- 모든 행의 인덱스가 한번씩은 무조건 나와야한다.
- 234행 나누기 5를 할경우 나머지가 생기기 때문에 5번째 나오는 인덱스들이 담긴 리스트는 앞서 나온 크기와 차이가 나도 된다.
- 제너레이터가 어려우신 분들은 그냥 인덱스들을 담고 있는 리스트들을 새로운 리스트에 담아서 return 해도 된다
>>> 234 // 5
46
yield 이용
# yield 를 이용한 방식
>>> def split_dataset(dataset):
# 나중에 파라미터로 받을수도 있으니 지역변수 선언
>>> n_split = 5
>>> seed = 42
>>> n_row = len(dataset) # 총 개수
>>> index_arr = np.arange(n_row) # 인덱스
>>> np.random.seed(seed)
>>> np.random.shuffle(index_arr) # 랜덤하게 뽑기위해 섞기
>>> n_samples = n_row // n_split
>>> for i in range(n_split):
>>> start = i*n_samples
>>> end = start + n_samples
>>> if i+1 == n_split:
>>> end = n_row
>>> yield index_arr[start:end]
# 함수 실행 결과를 검증하는 부분
>>> index_list = split_dataset(x_train)
>>> lst = [] # 크기가 데이터셋 크기와 같은지 확인하기 위한 리스트
>>> for idx in index_list:
# 중복 인덱스가 있으면 안되기 때문에 제거하기 위한 코드
>>> idx = list(set(idx))
# 리스트에 담기
>>> lst.extend(idx)
# 중복 제거
>>> lst = list(set(lst))
# 크기가 데이터셋 크기와 같고(즉 234개면 성공), 인덱스 최대값이 233 이고, 최소값이 0 이면 성공!!
>>> print(f"리스트 크기: {len(lst)}")
>>> print(f"최대값: {max(lst)}")
>>> print(f"최소값: {min(lst)}")
리스트 크기: 234
최대값: 233
최소값: 0
yield from 이용
# yield from 을 이용한 방식
>>> def split_dataset(dataset):
# 나중에 파라미터로 받을수도 있으니 지역변수 선언
>>> n_split = 5
>>> seed = 42
>>> n_row = len(dataset) # 총 개수
>>> index_arr = np.arange(n_row) # 인덱스
>>> np.random.seed(seed)
>>> np.random.shuffle(index_arr) # 랜덤하게 뽑기위해 섞기
>>> n_samples = n_row // n_split # 20% 의 데이터셋 개수
>>> n_sub = n_row - n_samples * n_split # 나머지 개수
>>> index_list = index_arr[:n_row-n_sub].reshape(n_split,-1).tolist()
>>> if n_sub > 0: # 남는개수가 있다면..
# 마지막 인덱스 리스트에 추가 확장
>>> index_list[-1].extend(list(index_arr[n_row-n_sub:]))
>>> yield from index_list
>>> index_list = split_dataset(x_train)
>>> lst = [] # 크기가 데이터셋 크기와 같은지 확인하기 위한 리스트
>>> for idx in index_list:
# 중복 인덱스가 있으면 안되기 때문에 제거하기 위한 코드
>>> idx = list(set(idx))
>>> lst.extend(idx) # 리스트에 담기
# 중복 제거
>>> lst = list(set(lst))
# 크기가 데이터셋 크기와 같고(즉 234개면 성공), 인덱스 최대값이 233 이고, 최소값이 0 이면 성공!!
>>> print(f"리스트 크기: {len(lst)}")
>>> print(f"최대값: {max(lst)}")
>>> print(f"최소값: {min(lst)}")
리스트 크기: 234
최대값: 233
최소값: 0
시계열 학습데이터 만들기
- 다음의 데이터는 2021년도 삼성 주식 데이터이다.
- 열부분은 시작가 ,상한가 , 하한가, 종가 순으로 되어있다.
- 행은 2021년도 거래 일자이다.
>>> samsung_stock = np.load("samsung_stock_2021.npy")
>>> samsung_stock.shape
(248, 4)
# 뒤에 5행만 확인해보기
>>> samsung_stock[-5:]
array([[80200, 80800, 80200, 80500],
[80600, 80600, 79800, 80200],
[80200, 80400, 79700, 80300],
[80200, 80200, 78500, 78800],
[78900, 79500, 78100, 78300]])
시계열 학습데이터 형태로 반환하는 함수를 만드시오.
- samsung_stock 변수의 데이터는 2차원 데이터이다.
- 학습데이터는 행별로 10일치의 행과 4열(시작가 ,상한가 , 하한가, 종가) 형태의 행렬을 담고 있는 3차원 형태의 데이터셋으로 변경하시오.
- 정답데이터는 미래의 5일치의 종가를 예측해야 한다는 가정하에 행별로 미래의 5일치의 종가가 담긴 2차원 형태의 데이터셋으로 변경하시오.
- 1일씩 이동하면서 데이터셋을 구성하시오.
# 일반적인 방법
>>> def transform_data(samsung_stock,seq_len=10,pred_len=5):
>>> x_train = []
>>> y_train = []
>>> for i in range(seq_len,samsung_stock.shape[0] + 1 - pred_len): # 마지막 하나가 빠짐... 1 더해주기
>>> x = samsung_stock[i-seq_len:i]
>>> y = samsung_stock[i:i+pred_len,3]
>>> x_train.append(x)
>>> y_train.append(y)
>>> x_train = np.array(x_train)
>>> y_train = np.array(y_train)
>>> return x_train , y_train
# 실행 결과 검증
>>> x_train , y_train = transform_data(samsung_stock)
>>> x_train.shape, y_train.shape
((234, 10, 4), (234, 5))
>>> x_samsung_stock = np.load("samsung_stock_2021_3d.npy")
>>> y_samsung_stock = np.load("y_train.npy")
>>> np.all(x_samsung_stock == x_train) , np.all(y_samsung_stock == y_train)
# 둘다 True 가 나와야 성공!!
(True, True)
강사님 스타일
# 강사님 스타일
>>> def transform_data(samsung_stock,seq_len=10,pred_len=5):
>>> window_size = seq_len + pred_len
>>> window_arr = [
>>> samsung_stock[i-window_size:i]
>>> for i in range(window_size ,samsung_stock.shape[0] + 1)
# 마지막 하나가 빠짐... 1 더해주기
>>> ]
>>> window_arr = np.array(window_arr)
>>> x_train = window_arr[:,:seq_len]
>>> y_train = window_arr[:,seq_len:,3]
>>> return x_train , y_train
>>> x_train , y_train = transform_data(samsung_stock)
>>> x_train.shape, y_train.shape
((234, 10, 4), (234, 5))
>>> x_samsung_stock = np.load("samsung_stock_2021_3d.npy")
>>> y_samsung_stock = np.load("y_train.npy")
>>> np.all(x_samsung_stock == x_train) , np.all(y_samsung_stock == y_train)
(True, True)
'파이썬 python > 파이썬 기초 basic' 카테고리의 다른 글
NumPy (0) | 2023.05.23 |
---|---|
03 문자열 (0) | 2023.05.01 |
02 컬렉션 (0) | 2023.05.01 |
01 객체와 변수, 기본자료형 연산자 (0) | 2023.04.26 |