LSTM 에 대한 이론적인 설명은 조금만 검색해봐도 알 수 있습니다. 그래서 예제를 통한 입력 형태와 출력를 살펴 보았습니다.
예제 소스는 아래 stock price predicting 주제중에 제일 마지막 아래 있는 LSTM 예제입니다. 해당 소스를 분석하여 설명을 추가 하였습니다.
https://www.analyticsvidhya.com/blog/2018/10/predicting-stock-price-machine-learningnd-deep-learning-techniques-python/
일단 실행 가능한 소스를 공유합니다. 위 링크의 소스가 부분 부분 나뉘어져 있어서 막상 실행하려고 하면 실행이 안되어 약간 수정 및 로그를 추가 하였습니다.
Source
#import packages import pandas as pd import numpy as np #to plot within notebook import matplotlib.pyplot as plt #주피터 노트북을 사용하지 않기때문에 삭제하였습니다. #%matplotlib inline #setting figure size from matplotlib.pylab import rcParams # 차트의 기본 크기를 설정합니다. rcParams['figure.figsize'] = 8,4 #그림(figure)의 크기. (가로,세로) 인치 단위 #for normalizing data from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler(feature_range=(0, 1)) #read the file df = pd.read_csv('NSE-TATAGLOBAL11.csv') #Date,Open,High,Low,Last,Close,Total Trade Quantity,Turnover (Lacs) #2018-10-08,208.0,222.25,206.85,216.0,215.15,4642146.0,10062.83 #print the head print(df.head()) #importing required libraries from sklearn.preprocessing import MinMaxScaler from keras.models import Sequential from keras.layers import Dense, Dropout, LSTM #creating dataframe # index를 sort함 sort 의미는 없음 data = df.sort_index(ascending=True, axis=0) print(data.head()) #빈 dataframe을 만듭니다 갯수는 df 갯수만큼 # Date Close #0 NaN NaN #1 NaN NaN #2 NaN NaN new_data = pd.DataFrame(index=range(0,len(df)),columns=['Date', 'Close']) print(new_data.head()) # 앞에서 만든 빈 new_data 에 Date, Close만 넣습니다. #이런식으로 안해도 될텐데... for i in range(0,len(data)): new_data['Date'][i] = data['Date'][i] new_data['Close'][i] = data['Close'][i] print(new_data.head()) #setting index #index를 date로 설정합니다. new_data.index = new_data.Date #그러면 date는 필요없어지니 삭제합니다 new_data.drop('Date', axis=1, inplace=True) #creating train and test sets # numpy로 변환합니다. 1차원인 Close만 남습니다 dataset = new_data.values train = dataset[0:987,:] valid = dataset[987:,:] # 각각 아래 데이터가 생성 되었습니다. #(987, 1) #(248, 1) print(train.shape) print(valid.shape) #converting dataset into x_train and y_train #값을 0 ~ 1 사이의 값으로 변환 합니다 scaler = MinMaxScaler(feature_range=(0, 1)) scaled_data = scaler.fit_transform(dataset) x_train, y_train = [], [] for i in range(60,len(train)): x_train.append(scaled_data[i-60:i,0]) y_train.append(scaled_data[i,0]) # x_train [0:60]=>0:59까지데이터 y_train [60] x_train, y_train = np.array(x_train), np.array(y_train) #(927, 60) (927,) # x_train 60깨 input으로 가지는 데이터가 927개 들어있다. print(x_train.shape,y_train.shape) print(x_train) # 입력 format에 맞게 변환 합니다. x_train = np.reshape(x_train, (x_train.shape[0],x_train.shape[1],1)) print("input_shape") print(x_train.shape,y_train.shape) print(x_train) # create and fit the LSTM network model = Sequential() # x_train.shape[1] 이것은 timestep이 된다 model.add(LSTM(units=50, return_sequences=True, input_shape=(x_train.shape[1],1))) model.add(LSTM(units=50)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(x_train, y_train, epochs=1, batch_size=1, verbose=2) # 입력 데이터중 마지막 데이터를 가지고 valid 데이터를 만듭니다. #predicting 246 values, using past 60 from the train data inputs = new_data[len(new_data) - len(valid) - 60:].values inputs = inputs.reshape(-1,1) inputs = scaler.transform(inputs) X_test = [] for i in range(60,inputs.shape[0]): X_test.append(inputs[i-60:i,0]) X_test = np.array(X_test) X_test = np.reshape(X_test, (X_test.shape[0],X_test.shape[1],1)) closing_price = model.predict(X_test) print(closing_price.shape) closing_price = scaler.inverse_transform(closing_price) rms=np.sqrt(np.mean(np.power((valid-closing_price),2))) print(rms) #for plotting train = new_data[:987] valid = new_data[987:] valid['Predictions'] = closing_price plt.plot(train['Close']) plt.plot(valid[['Close','Predictions']]) plt.show()
입력으로 사용하는 NSE-TATAGLOBAL11.csv 파일은 원본 링크의 아래 부분에서 다운로드 하였습니다.
Note: Here is the dataset I used for the code: Download
https://s3-ap-south-1.amazonaws.com/av-blog-media/wp-content/uploads/2019/03/NSE-TATAGLOBAL11.csv
NSE-TATAGLOBAL11.csv
Date,Open,High,Low,Last,Close,Total Trade Quantity,Turnover (Lacs) 2018-10-08,208.0,222.25,206.85,216.0,215.15,4642146.0,10062.83 2018-10-05,217.0,218.6,205.9,210.25,209.2,3519515.0,7407.06 2018-10-04,223.5,227.8,216.15,217.25,218.2,1728786.0,3815.79 2018-10-03,230.0,237.5,225.75,226.45,227.6,1708590.0,3960.27 2018-10-01,234.55,234.6,221.05,230.3,230.9,1534749.0,3486.05 2018-09-28,234.05,235.95,230.2,233.5,233.75,3069914.0,7162.35 2018-09-27,234.55,236.8,231.1,233.8,233.25,5082859.0,11859.95 2018-09-26,240.0,240.0,232.5,235.0,234.25,2240909.0,5248.6 2018-09-25,233.3,236.75,232.0,236.25,236.1,2349368.0,5503.9 2018-09-24,233.55,239.2,230.75,234.0,233.3,3423509.0,7999.55 2018-09-21,235.0,237.0,227.95,233.75,234.6,5395319.0,12589.59 2018-09-19,235.95,237.2,233.45,234.6,234.9,1362058.0,3202.78 ...(생략)...
Output
Date Open High Low Last Close Total Trade Quantity Turnover (Lacs) 0 2018-10-08 208.00 222.25 206.85 216.00 215.15 4642146.0 10062.83 1 2018-10-05 217.00 218.60 205.90 210.25 209.20 3519515.0 7407.06 2 2018-10-04 223.50 227.80 216.15 217.25 218.20 1728786.0 3815.79 3 2018-10-03 230.00 237.50 225.75 226.45 227.60 1708590.0 3960.27 4 2018-10-01 234.55 234.60 221.05 230.30 230.90 1534749.0 3486.05 Using TensorFlow backend. Date Open High Low Last Close Total Trade Quantity Turnover (Lacs) 0 2018-10-08 208.00 222.25 206.85 216.00 215.15 4642146.0 10062.83 1 2018-10-05 217.00 218.60 205.90 210.25 209.20 3519515.0 7407.06 2 2018-10-04 223.50 227.80 216.15 217.25 218.20 1728786.0 3815.79 3 2018-10-03 230.00 237.50 225.75 226.45 227.60 1708590.0 3960.27 4 2018-10-01 234.55 234.60 221.05 230.30 230.90 1534749.0 3486.05 Date Close 0 NaN NaN 1 NaN NaN 2 NaN NaN 3 NaN NaN 4 NaN NaN Date Close 0 2018-10-08 215.15 1 2018-10-05 209.2 2 2018-10-04 218.2 3 2018-10-03 227.6 4 2018-10-01 230.9 (987, 1) (248, 1) C:\ProgramData\Anaconda3\lib\site-packages\sklearn\utils\validation.py:595: DataConversionWarning: Data with input dtype object was converted to float64 by MinMaxScaler. warnings.warn(msg, DataConversionWarning) (927, 60) (927,) [[0.50425818 0.47758853 0.51792918 ... 0.72859704 0.7492156 0.77140296] [0.47758853 0.51792918 0.56006275 ... 0.7492156 0.77140296 0.77364411] [0.51792918 0.56006275 0.57485433 ... 0.77140296 0.77364411 0.73352757] ... [0.23576871 0.24518153 0.23733752 ... 0.23330345 0.22725235 0.22277006] [0.24518153 0.23733752 0.22882116 ... 0.22725235 0.22277006 0.24092335] [0.23733752 0.22882116 0.20528911 ... 0.22277006 0.24092335 0.24585388]] input_shape (927, 60, 1) (927,) [[[0.50425818] [0.47758853] [0.51792918] ... [0.72859704] [0.7492156 ] [0.77140296]] [[0.47758853] [0.51792918] [0.56006275] ... [0.7492156 ] [0.77140296] [0.77364411]] [[0.51792918] [0.56006275] [0.57485433] ... [0.77140296] [0.77364411] [0.73352757]] ... [[0.23576871] [0.24518153] [0.23733752] ... [0.23330345] [0.22725235] [0.22277006]] [[0.24518153] [0.23733752] [0.22882116] ... [0.22725235] [0.22277006] [0.24092335]] [[0.23733752] [0.22882116] [0.20528911] ... [0.22277006] [0.24092335] [0.24585388]]] WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version. Instructions for updating: Colocations handled automatically by placer. WARNING:tensorflow:From C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\ops\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version. Instructions for updating: Use tf.cast instead. Epoch 1/1 2019-05-04 18:53:28.235217: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 - 40s - loss: 0.0040 (248, 1) 5.49749408305034 lstm_help.py:131: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy valid['Predictions'] = closing_price
소스 코드에 관한 상세한 설명은 주석으로 넣었습니다.
전체적인 코드 흐름은 다음과 같습니다.
1. cvs 파일 읽기
2. date, close 컬럼만 추출 (new_data), close 는 종가를 의미함
3. date를 index로 만들고 date 컬럼 삭제, close컬럼만 남음
4. train, valid 데이터 셋으로 분리
5. MinMaxScaler 를 이용하여 0~1 사이 값으로 변환
6. x_train, y_train 데이터 구성, 이때 x_train은 60개의 time_steps 값을 가짐, 즉 close의 이전 60개 값이 x_train이 되고 현재값이 y_train 의 값 1개가 된다.
7. x_train, y_train 를 numpy로 변환
8. LSTM의 입력 포맷에 맞게 변환, 3개 차원 [전체 데이터 갯수, time_steps, feature수 ] 여기에서는 time_series = 60, feature수는 'close'컬럼 하나이므로 feature수는 1이 된다.
9. LSTM 모델링
10. train
11. 마지막 데이터를 이용하여 valid 데이터를 만듭니다. 코드상은 아래 부분입니다.
inputs = new_data[len(new_data) - len(valid) - 60:].values
new_data는 전체 데이터이므로 전체 데이터-valid데이터 크기-60(time_steps 값)위치 부터 마지막까지의 데이터입니다. 60을 빼주는 이유는 valid데이터 위치를 예측 하기 위해서는 이전 60개의 데이터가 필요하기 때문입니다.
12. 위에서 만든 inputs를 이용해서 X_test 데이터를 만듭니다. predict하기 때문에 Y_test는 필요 없습니다.
train의 입력 출력이 가장 어려운 부분이라 그림으로 표시해 보았습니다.
댓글 없음:
댓글 쓰기