Exercises Chapter 1 /w Hands on machine learning with scikit-learn and tensorflow

In this chapter we have covered some of the most important concepts in Machine Learning. In the next chapters we will dive deeper and write more code, but before we do, make sure you know how to answer the following questions:


 1. How would you define Machine Learning? 머신 러닝을 어떻게 정의할 것인지?

Machine Learning is about building systems that can learn from data. Learning means getting better at some task, given some performance measure.

머신 러닝은 데이터로부터 학습할 수 있는 시스템의 구축을 뜻한다. 학습의 의미는 성과 평가 척도를 고려할 때 점차 나아지고 있다는 뜻이다.

 

 

2. Can you name four types of problems where it shines?

Machine Learning is great for complex problems for which we have no algorithmic solution, to replace long lists of hand-tuned rules, to build systems that adapt to fluctuating environments, and finally to help humans learn (e.g., data mining).

기계 학습은

1.     알고리즘 솔루션이없는 복잡한 문제,

2.     수동으로 튜닝된 규칙들,

3.     변동하는 환경에 적응하는 시스템을 구축하고,

4.     마지막으로 인간이 학습 ( : 데이터 마이닝)을 돕도록 도와줍니다.

 

 


3. What is a labeled training set? 라벨링 데이터란 무엇인가?

A labeled training set is a training set that contains the desired solution (a.k.a. a label) for each instance.

각 인스턴스마다 이상적인 솔루션이 라벨링된(라벨이 포함된) training set을 말한다.

 

4. What are the two most common supervised tasks? 지도 학습의 대표적인 예 두 가지

The two most common supervised tasks are regression and classification.

Classification Regression (분류 / 회귀)

 

5. Can you name four common unsupervised tasks? 비지도 학습 예시 두 가지?

Common unsupervised tasks include clustering, visualization, dimensionality reduction, and association rule learning.

클러스터링 / 시각화 / 차원 축소 / 연관 규칙 학습



6. What type of Machine Learning algorithm would you use to allow a robot to walk in various unknown terrains? 

로봇이 알려지지 않은 지형을 걷게 하려면 어떤 학습?


Reinforcement Learning is likely to perform best if we want a robot to learn to walk in various unknown terrains since this is typically the type of problem that Reinforcement Learning tackles. It might be possible to express the problem as a supervised or semisupervised learning problem, but it would be less natural.

강화 학습은 일반적으로 보강 학습이 다루는 유형의 문제이기 때문에 다양한 알 수없는 지형에서 로봇이 걷는 법을 배우기를 원한다면 가장 잘 수행 될 것이다. 지도 or 비지도 학습 문제로 문제를 표현하는 것이 가능할 수도 있지만 자연스럽지는 않을 것이다.

 

*참고

Supervised learning – teacher 있음 (레이블(라벨)을 달아줌)

Unsupervised learning – teach 없음 (자연스럽게 알아서 패턴 학습)

Semi supervised learning지도 비지도 섞어서

**강화학습 - 어떤 환경 안에서 정의된 에이전트가 현재의 상태를 인식하여, 선택 가능한 행동들 중 보상을 최대화하는 행동 혹은 행동 순서를 선택하는 방법 / 강화는 실패와 성공을 반복해가며 학습

 

 

7. What type of algorithm would you use to segment your customers into multiple groups?
고객을 여러 그룹으로 분류하는 사용할 알고리즘 유형은 무엇입니까?


If you dont know how to define the groups, then you can use a clustering algorithm (unsupervised learning) to segment your customers into clusters of similar customers. However, if you know what groups you would like to have, then you can feed many examples of each group to a classification algorithm (supervised learning), and it will classify all your customers into these groups.

그룹을 정의하는 방법을 모르는 경우 클러스터링 알고리즘 (비지도 학습)을 사용하여 고객을 유사한 고객의 클러스터로 분류 할 수 있습니다. 그러나 어떤 그룹을 갖고 싶은지 알면 분류 알고리즘 (감독 학습)에 각 그룹의 많은 예를 제공하고 모든 고객을이 그룹으로 분류 할 수 있습니다.

 

8. Would you frame the problem of spam detection as a supervised learning problem or an unsupervised learning problem?  

지도 비지도 중 스팸탐지에 어떤 것을 사용할 것인가?


Spam detection is a typical supervised learning problem: the algorithm is fed many emails along with their label (spam or not spam).

스팸 탐지는 일반적인 감독 학습 문제입니다.이 알고리즘은 많은 이메일을 라벨 (스팸 또는 스팸이 아닌)과 함께 제공받습니다.

 

 

9. What is an online learning system? 온라인 러닝이란?

An online learning system can learn incrementally, as opposed to a batch learning system. This makes it capable of adapting rapidly to both changing data and autonomous systems, and of training on very large quantities of data.

온라인 학습 시스템은 일괄 학습 시스템과 달리 점진적으로 학습 할 수 있습니다. 이를 통해 변화하는 데이터와 자율 시스템 모두에 빠르게 적응할 수 있으며 대량의 데이터를 학습 할 수 있습니다.

 

10. What is out-of-core learning? Out of core 학습이란?

Out-of-core algorithms can handle vast quantities of data that cannot fit in a computers main memory. An out-of-core learning algorithm chops the data into mini-batches and uses online learning techniques to learn from these minibatches.

 

Out-of-core 알고리즘은 컴퓨터의 메인 메모리에 들어갈 수 없는 방대한 양의 데이터를 처리 할 수 ​​있습니다. Out-of-core 학습 알고리즘은 데이터를 잘라서 미니 배치 형태로 나눠 온라인 학습을 통해 이러한 미니 배치들을 학습시킨다.

 

 

11. What type of learning algorithm relies on a similarity measure to make predictions? 예측을 위해 유사성 측정에 의존하는 학습 알고리즘은?

An instance-based learning system learns the training data by heart; then, when given a new instance, it uses a similarity measure to find the most similar learned instances and uses them to make predictions.

인스턴스 기반 학습 시스템은 교육 데이터를 마음으로 학습합니다. 그런 다음 새 인스턴스가 주어지면 유사성 측정을 사용하여 가장 유사한 학습 인스턴스를 찾아 예측을 수행하는 데 사용합니다.

 

 

12. What is the difference between a model parameter and a learning algorithms hyperparameter?

모델 매개 변수와 학습 알고리즘의 하이퍼 매개 변수의 차이점은 무엇입니까?

A model has one or more model parameters that determine what it will predict given a new instance (e.g., the slope of a linear model). A learning algorithm tries to find optimal values for these parameters such that the model generalizes well to new instances. A hyperparameter is a parameter of the learning algorithm itself, not of the model (e.g., the amount of regularization to apply).


모델에는 새로운 인스턴스 ( : 선형 모델의 기울기) 주어질 예측할 것을 결정(무엇을 예측할지에 대해 결정)하는 하나 이상의 모델 매개 변수가 있습니다. 학습 알고리즘은 모델이 새로운 인스턴스로 일반화되도록 이러한 매개 변수에 대한 최적 값을 찾으려고합니다. 하이퍼 파라미터는 모델이 아닌 학습 알고리즘 자체의 파라미터 (예를 들어, 적용 정규화의 )이다.

 


13. What do model-based learning algorithms search for? What is the most common strategy they use to succeed? How do they make predictions?

모델 기반 학습 알고리즘은 무엇을 검색합니까? 그들이 성공하는데 사용하는 가장 일반적인 전략은 무엇입니까? 그들은 어떻게 예측을합니까?

Model-based learning algorithms search for an optimal value for the model parameters such that the model will generalize well to new instances. We usually train such systems by minimizing a cost function that measures how bad the system is at making predictions on the training data, plus a penalty for model complexity if the model is regularized. To make predictions, we feed the new instances features into the models prediction function, using the parameter values found by the learning algorithm.

 

모델 기반 학습 알고리즘은 모델이 새로운 인스턴스에 대해 잘 일반화 될 수 있도록 모델 매개 변수에 대한 최적 값을 검색합니다. 우리는 일반적으로 시스템이 학습 데이터에 대한 예측이 얼마나 나쁜지를 측정하는 비용 함수를 최소화하고 모델이 정규화 된 경우 모델 복잡성에 대한 불이익을 최소화함으로써 그러한 시스템을 교육합니다. 예측을 하기 위해 학습 알고리즘에서 찾은 매개 변수 값을 사용하여 모델의 예측 함수에 새 인스턴스의 피쳐를 공급합니다.

 


14. Can you name four of the main challenges in Machine Learning?

Some of the main challenges in Machine Learning are the lack of data, poor data quality, nonrepresentative data, uninformative features, excessively simple models that underfit the training data, and excessively complex models that overfit the data.

 

1.     데이터 부족

2.     데이터 품질 저하

3.     비 대표성 데이터 (모집단을 대표하지 못하는 Data)

4.     정보가없는 기능

5.     학습 데이터에 부합하지 않는 지나치게 단순한 모델 및 데이터를 초과 구현하는 지나치게 복잡한 모델입니다. / underfit or overfit

 

 

15. If your model performs great on the training data but generalizes poorly to new instances, what is happening? Can you name three possible solutions?

모델이 교육 데이터에서 뛰어난 성능을 보였으나 모델이 새로운 인스턴스로 잘 변형되지 않는다면 어떤 일이 벌어지고 있습니까? 가능한 세 가지 해결책을 제시해주세요.

 

If a model performs great on the training data but generalizes poorly to new instances, the model is likely overfitting the training data (or we got extremely lucky on the training data). Possible solutions to overfitting are getting more data, simplifying the model (selecting a simpler algorithm, reducing the number of parameters or features used, or regularizing the model), or reducing the noise in the training data.
모델이 학습 데이터에 대해 우수한 실적을 보였지만 인스턴스에 좋지 않은 경우 일반적으로 모델이 교육 데이터에 지나치게 적합합니다 (또는 교육 데이터에 대해 매우 운이 좋음). 오버 피팅에 대한 가능한 솔루션은 많은 데이터를 얻고, 모델을 단순화하고 (간단한 알고리즘 선택, 사용되는 매개 변수 또는 기능 감소, 모델 정규화) 또는 학습 데이터의 노이즈 감소입니다.


 

 16. What is a test set and why would you want to use it? 테스트 세트 란 무엇이며 사용하려는 이유는 무엇입니까?

A test set is used to estimate the generalization error that a model will make on new instances, before the model is launched in production.

테스트 세트는 모델이 프로덕션 환경에서 시작되기 전에 모델이 새 인스턴스에서 수행하게 될 일반화 오류를 평가하는 데 사용됩니다.

 

 

17. What is the purpose of a validation set?

A validation set is used to compare models. It makes it possible to select the best model and tune the hyperparameters.
유효성 검사 집합의 목적은 무엇입니까? 검증 세트는 모델을 비교하는 사용됩니다. 최고의 모델을 선택하고 하이퍼 파라미터를 튜닝 있습니다.

 

 

18. What can go wrong if you tune hyperparameters using the test set?

If you tune hyperparameters using the test set, you risk overfitting the test set, and the generalization error you measure will be optimistic (you may launch a model that performs worse than you expect).

학습 데이터 셋에 오버피팅될 위험이 있으며, 일반화 되는 (일반적인) 에러가 좋게 표시될수도 있음, 그래서 성과가 좋지 않은 모델을 얻을 수 있다.

 

 

19. What is cross-validation and why would you prefer it to a validation set?

교차 유효성 검사 란 무엇이며 유효성 검사 집합을 선호하는 이유는 무엇입니까?

Cross-validation is a technique that makes it possible to compare models (for model selection and hyperparameter tuning) without the need for a separate validation set. This saves precious training data.

교차 유효성 검증은 별도의 분류된 validation 세트 없이( train / test로만 분류해도 괜찮음) 모델 비교 (모델 선택 및 하이퍼 파라미터 튜닝 변수 조정)를 가능하게 하는 기술입니다. 이렇게 하면 validation set을 따로 뺴지 않아도 되기 때문에 train data를 아낄 수 있다(데이터가 적은 상황에서 좋은 효율)






순서 - 선형 SVM / 비선형 SVM / (1)

비선형SVM / 커널트릭 / SVR (2)

인공지능 수업시간에 발표했던 PPT.

서포트 백터들과 하이퍼 플래인의 마진 계산 관련 공식은 중간에 텍스트로만 이루어진 슬라이드를 참고하면 된다.




순서 - 선형 SVM / 비선형 SVM / (1)

비선형SVM / 커널트릭 / SVR (2)

인공지능 수업시간에 발표했던 PPT.

서포트 백터들과 하이퍼 플래인의 마진 계산 관련 공식은 중간에 텍스트로만 이루어진 슬라이드를 참고하면 된다.



정의

- 데이터의 편향 방지 + 편향된(잘못된) 모델 생성 방지

- 모집단의 특정 변수 비율에 맞추어 모집단을 쪼개어 해당 비율만큼 가지고 오는것(표본추출) = 비율을 맞춰줌 

- 층 내는 동질하게, 층끼리는 이질적이게 

- 전체 모집단 및 층별 특성도 효과적으로 추정가능 

- 데이터 셋의 특성 분포를 고르게 해준다 




구현

- 파이선 sklearn 모델을 통한 구현 

- StratifiedshuffleSplit 함수 이용 



정의

- K개의 fold를 만들어서 진행하는 교차검증


사용 이유

- 총 데이터 갯수가 적은 데이터 셋에 대하여 정확도를 향상시킬수 있음

- 이는 기존에 Training / Validation / Test 세 개의 집단으로 분류하는 것보다, Training과 Test로만 분류할 때 학습 데이터 셋이 더 많기 때문

- 데이터 수가 적은데 검증과 테스트에 데이터를 더 뺐기면 underfitting 등 성능이 미달되는 모델이 학습됨




과정 

- 기존 과정과 같이 Training Set과 Test Set을 나눈다

- Training을 K개의 fold로 나눈다 

- 위는 5개의 Fold로 나눴을때 모습이다

- 한 개의 Fold에 있는 데이터를 다시 K개로 쪼갠다음, K-1개는 Training Data, 마지막 한개는 Validation Data set으로 지정한다

- 모델을 생성하고 예측을 진행하여, 이에 대한 에러값을 추출한다

- 다음 Fold에서는 Validation셋을 바꿔서 지정하고, 이전 Fold에서 Validatoin 역할을 했던 Set은 다시 Training set으로 활용한다

- 이를 K번 반복한다




과정(이어서)
- 각각의 Fold의 시도에서 기록된 Error를 바탕(에러들의 평균)으로 최적의 모델(조건)을 찾는다
- 해당 모델(조건)을 바탕으로 전체 Training set의 학습을 진행한다
- 해당 모델을 처음에 분할하였던 Test set을 활용하여 평가한다

단점
- 그냥 Training set / Test set 을 통해 진행하는 일반적인 학습법에 비해 시간 소요가 크다


해당 자료는 CRM과 고객관계관리 수업의 팀 프로젝트로 진행했던 

"은행이 보유한 고객 행동 데이터를 바탕으로 향후 진행할 켐페인에 대한 반응여부를 예측할 수 있는 모델을 만든 것이다.


표에서 볼 수 있는 것처럼 로지스틱 회귀중 앞으로 방식이 제일 우수한 정확도를 보이고 있다.



2017 빅콘테스트 출전 당시(팀별 - 5인팀으로 출전) 결과 보고서이다. 

해당 대회는 과거 영화 데이터를 바탕으로 새롭게 개봉하는 영화들의 특점 시점까지의 누적 관객수를 예측하는 것이다.


추가적으로 부족했던 부분을 꼽자면 해당 영화가 개봉할 당시 경쟁작들의 유무를 변수로 추가했어야 했는데,

이러한 과정을 거치지 않아 정확도가 떨어지는 모델이 나왔고, 실제 해당 영화들은 '범죄도시'라는 경쟁 영화로 인하여

많은 관객을 뺴앗기게 되었다.


사진을 클릭하면 크게 볼 수 있다.




랜덤포레스트는 Meta-Learning의 한 종류로 여러 모형을 통합하여 모델을 만드는 것을 뜻한다. 

이는 이전 디시전트리를 구현하는 과정에서 설명하였던 앙상블 기법으로 불리기도 한다. 


디시전트리(의사결정나무) 설명은 이전 포스팅으로.


랜덤포래스트

의사결정나무를 여러 개 모아놓으면 (decision tree 여러 개) 숲이 되는데 이 숲을 구성하는 방법을 random 으로 함

나무마다 독립변수가 다르게 들어갈 수 있도록 그 수를(독립변수 사용 개수)를 제한시키는 것

이때 베깅 기법을 사용함.

Random subset of training data(bagging) + Random selection of features 


베깅(Bagging)

베깅은 원 표본에서 중복을 허용하여 표본을 추출(복원추출).

(학습)데이터셋을 여러 개 만들수 있는데 데이터가 각 셋마다 다르다


베깅과 랜덤포레스트의 정의는 위와 같이 내릴 수 있다. 이해가 안가면 제일 위 사진과 함께 아래 예시를 보자.


베깅의 예시는 

총 1000개의 train 데이터 셋이 있다고 가정하자. 이럴 때, train셋을 1000개를 전부 다 한번에 쓰는 것이 아닌,

이 중 700개만 뽑아서 train셋을 여러개 만든 후, 이를 각각 학습한 결과값의 평균, 즉 값들을 모두 이용하여 

최적회된 모델을 만드는 것이다.


이 때 한번 학습에 사용한 데이터는 다시 train데이터에 놓고 랜덤으로 추출하여 각 train 데이터 셋마다 일부는 겹칠 수 있지만 완벽히는 겹치지 않는

모델을 만드는 것이다 


랜덤포레스트의 예시는

마찬가지로 train data set마다 각기 백퍼센트 동일하지 않은(=다른) 셋을 가지고 있다는 것은 동일하지만, 베깅처럼 모든 변수를 사용하는 대신

나무마다 독립변수가 다르게 들어가도록 독립변수의 수를 제한하는 기법을 뜻한다.

즉 a데이터 셋은 나이, 성별, 수입 변수를 사용하고, b데이터셋은 나이, 거주지, 수입 변수를 사용하는 식으로 백퍼센트 변수가 동일하지 않는 것이다.


이와 비슷한 이론으로 부스팅이 있는데, 부스팅은 베강과는 살짝 다른 기법이다.

부스팅을 활용한 디시전트리의 정의는 아래와 같다.


부스팅 (Adaboost)

Train data 중 일부를 랜덤으로 추출하여 모델을 만든다. 이 모델의 정확도를 측정한다.

여기서 에러가 난 데이터들을 찾고, 이 데이터들에게 가중치를 더 준 상태에서 다음번 모델을 만들 데이터들을 랜덤으로 추출한다.

이 과정에서 가중치가 큰 데이터(기존에 에러 났던 데이터)가 들어올 확률이 높다.

이렇게 다시 모델을 만들고, 전체 Train data셋을 통해 다시 정확도를 측정한다. (=Sequential 하게 모델을 만들어간다) 


해당 과정을 반복하여 완벽한 모델을 만들도록 하는게 부스팅.


이러한 랜덤포레스트의 장단점은 

장점

의사결정나무(디시전 트리)보다 정확도가 높아진다

단점

디시전 트리가 가지는 설명력을 상실한다(왜 대출 심사에서 떨어진건지, 왜 부도가 난건지 등 변수의 가중치를 우선순위를 파악할수 없으니 결과를 해석할 수 없음)


이번 포스팅에선 비트파이넥스 API를 활용하여 비트코인 가격데이터를 요청해보겠다.

좀 더 자세한 설명은 코인베이스 API 사용 포스팅에 나와있으니 참고해도 좋다.


우선 비트파이넥스 API관련 링크에 접속한다

https://bitfinex.readme.io/v2/reference#rest-public-stats


왼쪽 candle을 눌러주면 아래와 같은 화면이 보인다.



우선 URL 방식중 GET과 POST방식에 대해서 간단히 설명하겠다.


GET(파란원)은 따로 암호화를 하지 않은 URL방식으로 URL을 보면 직관적으로 그 내용을 알 수 있다. 예시에 나와있는 링크를 봐도 어느정도 직관적으로 이해가 가능하다.


POST는 암호화를 거친 URL로 이상한 특수문자 알파벳 조합으로 이루어지기 떄문에 직관적으로 알 수 없다. 

우리는 GET방식의 URL을 통해 데이터를 요청해 보겠다.


친절하게 파라미터에 대한 예시까지 들어주었으므로, 바로 URL에 적용시켜 보겠다.

예시 URL(GET방식)은 아래와 같다.


https://api.bitfinex.com/v2/candles/trade:6h:tBTCUSD/hist?limit=100&start=&end=&sort=1


라인별로 간단하게 보면 6시간봉으로 이루어진 BTCUSD마켓 데이터를 hist 방식으로(사진 빨간원 참조) 정렬된 상태로 100개 요청하는 것이다.


이제 코드패드로 이동해 보겠다.

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
import requests
from datetime import datetime
import time
 
def unixtime(t): #우리가 쓰는 시간을 유닉스타임으로 바꿈 
    temp = t.split('-')
    return int(time.mktime(datetime(int(temp[0]), int(temp[1]), int(temp[2])).timetuple()))
'''
def unixtime_to_datetime(arr, interval, symbol): #우리가 쓰는 시간을 유닉스타임으로 바꿈 
    temp = t.split('-')
    return int(time.mktime(datetime(int(temp[0]), int(temp[1]), int(temp[2])).timetuple()))    
'''
timeframe = '6h'
symbol = 'tBTCUSD'
section = 'hist'
limit = 100
end = "2018-03-01"
start = "2018-02-25"
sort = 1 
 
= (requests.get("https://api.bitfinex.com/v2/candles/trade:%s:%s/%s?limit=%d&start=%d&end=%d&sort=%d" %(timeframe, symbol, section, limit, unixtime(start)*1000, unixtime(end)*1000, sort)))
 
data = r.json()
print(data)
    
cs


해당 코드를 실행하면 아래와 같다.



이런식으로 데이터를 받아올 수 있다.

이후 csv저장 등 필요한 작업을 진행하면 된다.

LSTM은 RNN에서 파생된 것으로, 순차적인 입력 데이터간 간격이 커도 좋은 성과를 보여주는 것을 특징으로 한다.

이는 RNN이 가지는 Long-term dependency 문제점을 LSTM은 가지고 있지 않기 떄문이다. 해당 문제점은 예측에 필요한 정보와 정보간 간격이 클때 그 예측 능력이 현저하게 감소하는 것을 뜻한다. 

보편적으로, 대부분의 경우에 LSTM은 RNN보다 좋은 퍼포먼스를 보여주는 경향을 가진다.


다만 RNN역시 신경망의 한 종류이기 때문에, 그 과정에 있어서 설명력이 떨어진다는 단점을 가진다.

하지만 우리는 어떤 순서에 의하여 가격 예측을 하는지 그 과정이 필요한 것은 아니기 때문에, LSTM을 선택하기로 하였다.


LSTM의 자세한 수학적 원리는 웹의 여러 매체에 소개되어 있으며, 해당 포스팅에서는 간단하게 작동 원리만

설명하면 아래와 같다.



첫번째 인픗으로 일차 예측을 진행하고, 그 다음 인풋과 기존 인풋을 바탕으로 한 예측값을 조합하여 다시 재예측을 진행한다.

이런식으로 n번째 인풋값 전 n-1번까지의 인풋값을 통해 낸 예측결과는 n번째 인풋을 활용한 예측값에 영향을 주는 것이다.


해당 과정을 계속해서 진행하여 최종 아웃풋을 산출한다.


*딥러닝 부분을 구현하는 것에 있어서 어려움이 있었기 때문에, 도움을 받았음을 알려드립니다.



우리는 예측 모델을 통해 raio(상승/하락 비율)을 예측했고, 그 예측 결과인 비율에 해당 시간의 close(종가)를 곱해주게 되면 예측 가격이 나오게 된다.

칼럼에 대해 설명하자면 2015-03-13 15:00을 기준으로 6시간 뒤는 2015년 3월 13일 21:00, 그 뒤는 14일 03:00 .. 이 되는 것이다.

따라서 칼럼에서 실제 24시간 뒤가 다음 칼럼에서 여섯시간 뒤와 동일한 것을 발견할 수 있다.


따라서 우리는 각 시간대별로 6시간, 12시간, 18시간, 24시간 예측값에 대한 오차율을 구할 수 있으며, 오차율의 절대값 평균은 아래와 같다.


즉 시간이 지날수록 오차율이 높아지는 것을 발견할 수 있다.

사실 일반적인 에측에서 정확도 98퍼센트면 매우 높다고 생각할수도 있으나 트레이딩의 특성상

1퍼센트~2퍼센트의 차이가 큰 돈의 이익과 손실을 불러올 수 있다는 점에서 부족할 수 있다는 생각 역시 든다.


 

특히나 급격한 하락장(패닉셀 등)이 발생할때는 예측치가 크게 어긋나는 모습을 보였는데, 물론 평균치로 보면 크게 문제가 없지만

순간 순간의 오차율이 큰 손실을 불러올 수 있다는 점에서 보완이 필요하다는 생각이 들었다.


 

전처리는 거의 다 끝났고, 이제 학습 데이터와 테스트 데이터로 나눠보도록 하겠다.

비율은 보통 자율적으로 선택하지만 보편적으로 0.7~0.75사이로 학습데이터를, 그 나머지를 테스트 데이터로 부여하게 된다.


코드는 아래와 같다.


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
32
33
import numpy as np
import math
import csv
##train set : 3125개 , test: 1041개
= open("./20개씩묶고_컬럼별정규화.csv"'r', newline='')
rdr = csv.reader(f)
 
data = []
for j, i in enumerate(rdr):
    if(j!=0): #label 제외하고 읽어옴.
        data.append(i)
np.random.shuffle(data)
 
ratio = 0.75
count = int(math.ceil(len(data)*ratio))
print(len(data), count)
train = data[:count]
test = data[count:]
 
o1 = open("./trainset.csv"'w', newline='')
wr1 = csv.writer(o1)
for i in train:
    wr1.writerow(i)
 
o2 = open("./testset.csv"'w', newline='')
wr2 = csv.writer(o2)
for i in test:
    wr2.writerow(i)
 
f.close()
o1.close()
o2.close()
'''
cs


해당 코드를 실행시 4163개의 Train data, 3123개의 Test data로 나눠진 것을 확인할 수 있다.




저번 포스팅에 이어서 전처리 작업을 해보겠다.

이번 포스팅해서 진행할 것은 첫번째로 20개를 그램으로 묶으며, 데이터를 정규화할 것이다.

우선 그램에 대해서 간단하게 설명하면 아래와 같다.


input data   /  target(예측)

   b    c          d

b    c    d          e

c    d    e          f


이런식으로 일부분은 중복되지만 완전히 중복되지 않는 인풋데이터를 확보하여 예측값을 구하는 것으로

이번의 경우에는 데이터가 충분하지 않기 때문에 사용하게 된 방법이다.

R실습에서 진행하였던 디시전 트리의 앙상블과 비슷한 개념이라고 할 수 있다.


그램에 대한 코드는 아래와 같다


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
import csv
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import warnings
warnings.filterwarnings("ignore")
 
########20gram으로 분류############
= open("./타겟추가데이터2_새로운방식.csv"'r', newline='')
rdr = csv.reader(f)
 
list = []
for i in rdr:
    list.append(i)
list.pop(0#제목줄 지우기
print(len(list))
 
gram_20 = []
for i in range(len(list)+1-20):
    gram_20.append(list[i:i+20])  
gram_20 = np.array(gram_20)
#print(gram_20)
#print(gram_20.shape)
print(gram_20[0].shape)  ## 20개씩 묶어서 진행 - 4163 번 진행 20행 21열 (스샷참고) = 5일  
###########################

o.close()
f.close()
cs


20개씩 묶은 이유는 한 행에 5일치에 속하는 데이터들을 묶기 위함이며(하루에 4bars * 5 일 = 20bars)

해당 그램을 사용해야 뜨는 타임라인이 없이 6시간봉마다 예측을 진행할 수 있다. (우리는 마감시 기준 6, 12, 18, 24시간 뒤 가격을 예측할 것이다)



해당 코드부분만 실행해보면 20행 21열이며 4163번 진행하였음을 알 수 있다. 


이제 칼럼별로 정규화를 진행하겠다.

참고로 우리가 예측할 것은 순수한 가격이 아닌 ratio 즉 가격의 변화율을 예측할 것이며, 이를 close와 곱하여 가격을 유추해낼 것이다.


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
#######노말라이제이션############
= open("./20개씩묶고_컬럼별정규화.csv"'w', newline='')
wr = csv.writer(o)
title = ['time','low''high','open','close','volume','sma5','sma20','ema12','ema26','dn','mavg','up','pctB','rsi14','macd','signal']*20 #20일치
title.append("lastday_close")
title.append('after6ratio')
title.append('after12ratio')
title.append('after18ratio')
title.append('after24ratio')
wr.writerow(title)
 
scaler = MinMaxScaler(feature_range=(0,1)) #scaler 선언
for i in gram_20:
    close = np.array(i[-1][4], np.float64) # -1은 마지막 인덱스를 뜻함 여기서는 19 
    target = np.array(i[-1][-4:], np.float64) # 뒤에서부터 네 개 값 계산해서 타겟으로 넣음 
    ratio = target/close
    
    for j in range(1, i.shape[1]-4): #날짜다음부터 체크해서 타겟4개 제외. / 현재 종가부터 
        col = scaler.fit_transform(np.reshape(i[:,j], (-11)))
        col = np.transpose(col) # 이걸 다시 열로  바꿔서 그대로 붙임 
        i[:,j] = col # 붙임 
    
    #break
    data = i[:, :-4# 타임까지 포함해서 타겟 열 전까지 가지고와서 (ratio 다 떄고 그래서 20 행 17 열 )
    data = np.reshape(data, (-1)) #각 행을 짤라서 하나의 긴 행으로 바꿈 - 1차원 배열로 알아서 펴줌 즉 한게의 긴 행 상태로 바꿈    =  20 * 17 = 340 
    data = np.append(data,close)  # close 1열 추가 
    data = np.append(data,ratio) #  나중에 close 와 ratio 를 곱해가지고 실제 예측 가격 파악가능  - ratio 4개 추가  - 총 345 열 
    
    wr.writerow(data) 
cs


코드를 라이별로 간단하게 설명하면 close는 그램으로 묶은 20행중 마지막 행의 close를 담게 된다.

또한 target은 동일한 행의 마지막 4개 열(after 6 ratio ~ after 24 ratio)


그 후 각 데이터들에 대한 정규화를 진행하게 되며(타겟은 제외하고) 

한 개의 그램에 20행 21열로 구성이 되어 있는것을, 마지막 4개 열을 제외하고 하나의 행으로 길게 늘어뜨리게 된다.

해당 과정을 진행하면 20*17(20행*17열을 한개의 행에 길게 늘어뜨림) 340행이 나오게 되며, 해당 과정이 끝나면

close와 ratio(close -1열 + ratio - 4열 = 총 5열 추가) 한 행당 345개의 열을 가지게 된다.


두번째 포문에 대한 설명을 조금 더 하자면 

i = 

1 2 3 4 5 6 7 

2 3 4 5 6 7 8 

3 4 5 6 7 8 9 

일 때,


i [ : , : -4] 면  

1 2 3 

2 3 4 

3 4 5 


와 같이 선택하는 것이다.

즉 뒤에 4개를 빼고 묶는다고 생각하면 된다.


해당 csv 파일을 열어보면 한 행이 345개의 열로 구성되어 있는것을 확인할 수 있다.



1번



2번


ERWIN 데이터 모델링은 명확한 답이 있는 경우보다 특정 기준을 어떻게 바라보느냐에 따라 여러 결과물이 나올 수 있다.

2번 문제의 경우가 이에 해당하는데, 주석을 통해 어떤 기준을 모델링을 하였는지 서술하였다.


'Database > ERWIN' 카테고리의 다른 글

[ERWIN] ERWIN을 활용한 데이터 모델링 실습  (0) 2018.03.05

1번


2번


3번



4번


마지막 문제의 경우에는 다양한 해답이 나올수 있으며, 내가 판단한 기준은 무엇인지 주석에 추가하여 놓았다.


'Database > ERWIN' 카테고리의 다른 글

[ERWIN] ERWIN을 활용한 데이터 모델링 실습(2)  (0) 2018.03.05

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
32
33
34
35
36
37
38
39
40
41
42
43
SQL> CREATE TABLE MAJOR (
  2      MNUM    NUMBER(3NOT NULL,
  3      MNAME VARCHAR2(20NOT NULL,
  4      BUILD VARCHAR2(20),
  5      PRIMARY KEY(MNUM)
  6  );
 
테이블이 생성되었습니다.
 
SQL> INSERT INTO MAJOR VALUES(101,'컴퓨터공학과','정보관');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MAJOR VALUES(102,'전자공학과','전자제어관');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MAJOR VALUES(103,'경영학과','인문관');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MAJOR VALUES(104,'경제학과');
INSERT INTO MAJOR VALUES(104,'경제학과')
            *
1행에 오류:
ORA-00947: 값의 수가 충분하지 않습니다 
 
 
SQL> INSERT INTO MAJOR (MNUM,MNAME) VALUES(104,'경제학과');
 
1 개의 행이 만들어졌습니다.
 
SQL> select * from major;
 
      MNUM MNAME                BUILD                                           
---------- -------------------- --------------------                            
       101 컴퓨터공학과         정보관                                          
       102 전자공학과           전자제어관                                      
       103 경영학과             인문관                                          
       104 경제학과                                                             
 
SQL> spool off;
 
cs


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
SQL> CREATE TABLE STUDENT (
  2      SNUM    NUMBER(4NOT NULL,
  3      SNAME VARCHAR2(10NOT NULL,
  4      GRADE NUMBER,
  5  MNUM NUMBER(3),
  6      PRIMARY KEY(SNUM),
  7        FOREIGN KEY(MNUM) REFERENCES MAJOR(MNUM)
  8  );
 
테이블이 생성되었습니다.
 
SQL> desc student;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 SNUM                                      NOT NULL NUMBER(4)
 SNAME                                     NOT NULL VARCHAR2(10)
 GRADE                                              NUMBER
 MNUM                                               NUMBER(3)
 
SQL> INSERT INTO STUDENT VALUES(9411,'서진수',4,101);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9412,'서재수',4,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9413,'이미경',4,103);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9414,'김재수',4,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9415,'박동호',4,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9511,'김신영',3,101);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9512,'신은경',3,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9513,'오나라',3,103);
 
1 개의 행이 만들어졌습니다.
 
SQL> SELECT * FROM STUDENT;
 
      SNUM SNAME           GRADE       MNUM                                     
---------- ---------- ---------- ----------                                     
      9411 서진수              4        101                                     
      9412 서재수              4        102                                     
      9413 이미경              4        103                                     
      9414 김재수              4        102                                     
      9415 박동호              4        102                                     
      9511 김신영              3        101                                     
      9512 신은경              3        102                                     
      9513 오나라              3        103                                     
 
8 개의 행이 선택되었습니다.
 
SQL> SPOOL OFF;
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SQL> SELECT SNAME,MNAME FROM STUDENT S, MAJOR M WHERE S.MNUM=E.MNUM;
SELECT SNAME,MNAME FROM STUDENT S, MAJOR M WHERE S.MNUM=E.MNUM
                                                        *
1행에 오류:
ORA-00904"E"."MNUM": 부적합한 식별자 
 
 
SQL> SELECT SNAME,MNAME FROM STUDENT S, MAJOR M WHERE S.MNUM=M.MNUM;
 
SNAME      MNAME                                                                
---------- --------------------                                                 
서진수     컴퓨터공학과                                                         
서재수     전자공학과                                                           
이미경     경영학과                                                             
김재수     전자공학과                                                           
박동호     전자공학과                                                           
김신영     컴퓨터공학과                                                         
신은경     전자공학과                                                           
오나라     경영학과                                                             
 
8 개의 행이 선택되었습니다.
 
SQL> SPOOL OFF;
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SQL> SELECT SNAME FROM STUDENT WHERE MNUM=(SELECT MNUM FROM MAJOR WHERE MNAME='전자공학과')
  2  UNION
  3  SELECT SNAME FROM STUDENT WHERE MNUM=(SELECT MNUM FROM STUDENT WHERE SNAME='서진수');
 
SNAME                                                                           
----------                                                                      
김신영                                                                          
김재수                                                                          
박동호                                                                          
서재수                                                                          
서진수                                                                          
신은경                                                                          
 
6 개의 행이 선택되었습니다.
 
SQL> SPOOL OFF;
cs


1
2
3
4
5
6
7
8
9
SQL> SELECT SNAME, SNUM FROM MAJOR M, STUDENT S WHERE M.MNUM=S.MNUM AND (M.MNAME='경영학과' OR M.MNAME='경제학과');
 
SNAME            SNUM                                                           
---------- ----------                                                           
이미경           9413                                                           
오나라           9513                                                           
 
SQL> SPOOL OFF;
 
cs


1
2
3
4
5
6
7
8
9
10
SQL> SELECT SNAME, SNUM FROM STUDENT S WHERE EXISTS
  2  (SELECT MNUM FROM MAJOR M WHERE S.MNUM=M.MNUM AND(M.MNAME='컴퓨터공학과' OR M.MNAME='경제학과'));
 
SNAME            SNUM                                                           
---------- ----------                                                           
김신영           9511                                                           
서진수           9411                                                           
 
SQL> SPOOL OFF
 
cs


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
SQL> CREATE TABLE HOME (
  2      HOMENO    NUMBER,
  3      HOMENAME VARCHAR2(10),
  4      MANAGER    VARCHAR2(15),
  5      SALARY     NUMBER
  6  );
 
테이블이 생성되었습니다.
 
 
SQL> desc home;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 HOMENO                                             NUMBER
 HOMENAME                                           VARCHAR2(10)
 MANAGER                                            VARCHAR2(15)
 SALARY                                             NUMBER
 
SQL> 
SQL> INSERT INTO HOME VALUES(2106'Kims''김창섭'5000000);
 
1 개의 행이 만들어졌습니다.
 
SQL> 
SQL> INSERT INTO HOME VALUES(3423'Parks''박영권'5300000);
 
1 개의 행이 만들어졌습니다.
 
SQL> 
SQL> INSERT INTO HOME VALUES(3011'Lees''이수민'6400000);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO HOME VALUES(1003'Joos''주민희'4700000);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO HOME VALUES(3427'Chois''최종철'3500000);
 
1 개의 행이 만들어졌습니다.
 
SQL> commit;
 
커밋이 완료되었습니다.
 
SQL> select * from home;
 
    HOMENO HOMENAME   MANAGER             SALARY                                
---------- ---------- --------------- ----------                                
      2106 Kims       김창섭             5000000                                
      3423 Parks      박영권             5300000                                
      3011 Lees       이수민             6400000                                
      1003 Joos       주민희             4700000                                
      3427 Chois      최종철             3500000     
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SQL> ALTER TABLE HOME ADD CONSTRAINT HOME_PK PRIMARY KEY(HOMENO);
 
테이블이 변경되었습니다.
 
SQL> ALTER TABLE HOME DROP COLUMN SALARY;
 
테이블이 변경되었습니다.
 
SQL> DESC HOME;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 HOMENO                                    NOT NULL NUMBER
 HOMENAME                                           VARCHAR2(10)
 MANAGER                                            VARCHAR2(15)
 
SQL> SELECT TABLE_NAME, CONSTRAINT_NAME, CONSTRAINT_TYPE FROM USER_CONSTRAINTS WHERE TABLE_NAME='HOME';
 
TABLE_NAME                     CONSTRAINT_NAME                C                 
------------------------------ ------------------------------ -                 
HOME                           HOME_PK                        P                 
 
SQL> 
SQL> spool off;  
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
QL> CREATE TABLE MANAHOME (
  2  MANAGERNO NUMBER NOT NULL,
  3  HOMENAME VARCHAR2(10UNIQUE,
  4  SALARY NUMBER CHECK(SALARY<=6000000),
  5  JOB VARCHAR2(15DEFAULT '개발자',
  6  PRIMARY KEY(MANAGERNO)
  7  );
 
테이블이 생성되었습니다.
 
SQL> DESC MANAHOME;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 MANAGERNO                                 NOT NULL NUMBER
 HOMENAME                                           VARCHAR2(10)
 SALARY                                             NUMBER
 JOB                                                VARCHAR2(15)
 
SQL> SPOOL OFF;
cs


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
32
33
34
35
36
37
38
39
40
41
SQL> ALTER TABLE MANAHOME ADD (HNO NUMBER);
 
테이블이 변경되었습니다.
 
SQL> desc manahome;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 MANAGERNO                                 NOT NULL NUMBER
 HOMENAME                                           VARCHAR2(10)
 SALARY                                             NUMBER
 JOB                                                VARCHAR2(15)
 HNO                                                NUMBER
 
 
 
SQL> INSERT INTO MANAHOME VALUES(5454'Kims'5000000'분석가'2106);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MANAHOME VALUES(4215'Lees'4500000'승무원'3011);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MANAHOME VALUES(2452'Joos'3200000'분석가'1033);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MANAHOME(MANAGERNO, HOMENAME, SALARY, HNO) VALUES(4852'Chois'30000003427);
 
1 개의 행이 만들어졌습니다.
 
SQL> select* from manahome;
 
 MANAGERNO HOMENAME       SALARY JOB                    HNO                     
---------- ---------- ---------- --------------- ----------                     
      5454 Kims          5000000 분석가                2106                     
      4215 Lees          4500000 승무원                3011                     
      2452 Joos          3200000 분석가                1033                     
      4852 Chois         3000000 개발자                3427                     
 
SQL> spool off;
cs


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
32
33
34
35
36
37
38
 
SQL> SELECT * FROM HOME;
 
    HOMENO HOMENAME   MANAGER                                                   
---------- ---------- ---------------                                           
      2106 Kims       김창섭                                                    
      3423 Parks      박영권                                                    
      3011 Lees       이수민                                                    
      1003 Joos       주민희                                                    
      3427 Chois      최종철                                                    
 
##기존에 MANAHOME에 들어있던 데이터를 잘못 입력 (1033인데 1003으로 잘못)
## 하여 해당 행 수정 후 진행하였습니다
 
 
SQL> UPDATE MANAHOME SET HNO=1003 WHERE MANAGERNO=2452;
 
1 행이 갱신되었습니다.
 
SQL> SELECT * FROM MANAHOME;
 
 MANAGERNO HOMENAME       SALARY JOB                    HNO                     
---------- ---------- ---------- --------------- ----------                     
      5454 Kims          5000000 분석가                2106                     
      4215 Lees          4500000 승무원                3011                     
      2452 Joos          3200000 분석가                1003                     
      4852 Chois         3000000 개발자                3427                     
 
SQL> ALTER TABLE MANAHOME ADD CONSTRAINT MANA_FK FOREIGN KEY(HNO) REFERENCES HOME(HOMENO);
 
테이블이 변경되었습니다.
 
SQL> INSERT INTO MANAHOME VALUES(3235'Lees',2000000,'관리자',1111);
INSERT INTO MANAHOME VALUES(3235'Lees',2000000,'관리자',1111)
*
1행에 오류:
ORA-00001: 무결성 제약 조건(JS.SYS_C0011622)에 위배됩니다 
 
cs



1
2
3
4
5
6
7
8
9
SQL> CREATE TABLE MAJOR (
  2    MAJORNO  NUMBER(3)  NOT NULL,
  3    MNAME  VARCHAR2(20NOT NULL,
  4    BUILD VARCHAR2(20),
  5     PRIMARY KEY(MAJORNO)
  6  );
 
테이블이 생성되었습니다.
 
cs

1
2
3
4
5
6
7
8
9
10
SQL> CREATE TABLE STUDENT (
  2    STUDNO  NUMBER(4)  NOT NULL,
  3    SNAME  VARCHAR2(10NOT NULL,
  4    GRADE  NUMBER,
  5    MAJORNO1  NUMBER(3),
  6    PRIMARY KEY(STUDNO),
  7    FOREIGN KEY(MAJORNO1) REFERENCES MAJOR(MAJORNO)
  8    );
 
테이블이 생성되었습니다.
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SQL> INSERT INTO MAJOR VALUES(101,'컴퓨터공학과','정보관');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MAJOR VALUES(102,'전자공학과','전자제어관');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MAJOR VALUES(103,'경영학과','인문관');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO MAJOR VALUES(104,'경제학과',NULL);
 
1 개의 행이 만들어졌습니다.
 
SQL> SELECT * FROM MAJOR;
 
   MAJORNO MNAME                BUILD                                           
---------- -------------------- --------------------                            
       101 컴퓨터공학과         정보관                                          
       102 전자공학과           전자제어관                                      
       103 경영학과             인문관                                          
       104 경제학과                               
cs


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
SQL> INSERT INTO STUDENT VALUES(9411,'서진수',4,101);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9412,'서재수',4,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9413,'이미경',4,103);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9414,'김재수',4,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9415,'박동호',4,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9511,'김신영',3,101);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9512,'신은경',3,102);
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO STUDENT VALUES(9513,'오나라',3,103);
 
1 개의 행이 만들어졌습니다.
 
SQL> select * from student;
 
    STUDNO SNAME           GRADE   MAJORNO1                                     
---------- ---------- ---------- ----------                                     
      9411 서진수              4        101                                     
      9412 서재수              4        102                                     
      9413 이미경              4        103                                     
      9414 김재수              4        102                                     
      9415 박동호              4        102                                     
      9511 김신영              3        101                                     
      9512 신은경              3        102                                     
      9513 오나라              3        103                                     
 
cs


1
2
3
4
5
6
7
8
9
10
11
SQL> UPDATE STUDENT SET MAJORNO1=102 WHERE STUDNO=9411;
 
1 행이 갱신되었습니다.
 
SQL> SELECT * FROM STUDENT WHERE SNAME ='서진수';
 
    STUDNO SNAME           GRADE   MAJORNO1                                     
---------- ---------- ---------- ----------                                     
      9411 서진수              4        102 
 
 
cs


1
2
3
4
5
6
7
8
9
10
SQL> UPDATE STUDENT SET GRADE =4, MAJORNO1=103 WHERE SNAME='김신영';
 
1 행이 갱신되었습니다.
 
 
SQL> SELECT * FROM STUDENT WHERE SNAME='김신영';
 
    STUDNO SNAME           GRADE   MAJORNO1                                     
---------- ---------- ---------- ----------                                     
      9511 김신영              4        103     
cs

1
2
3
4
5
6
7
8
9
SQL> UPDATE MAJOR SET MNAME='통계학과' WHERE MAJORNO=104;
 
1 행이 갱신되었습니다.
 
SQL> SELECT * FROM MAJOR WHERE MNAME='통계학과';
 
   MAJORNO MNAME                BUILD                                           
---------- -------------------- --------------------                            
       104 통계학과                                    
cs


1
2
3
4
5
6
7
8
9
10
11
SQL> DELETE FROM MAJOR WHERE MNAME='통계학과';
 
1 행이 삭제되었습니다.
 
SQL> SELECT * FROM MAJOR;
 
   MAJORNO MNAME                BUILD                                           
---------- -------------------- --------------------                            
       101 컴퓨터공학과         정보관                                          
       102 전자공학과           전자제어관                                      
       103 경영학과             인문관         
cs




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
SQL> SELECT ENAME AS 사원이름, EMPNO AS 사원번호, HIREDATE AS 고용일 FROM EMP ORDER BY 사원번호 DESC;
 
사원이름     사원번호 고용일                                                    
---------- ---------- --------                                                  
MILLER           7934 82/01/23                                                  
FORD             7902 81/12/03                                                  
JAMES            7900 81/12/03                                                  
ADAMS            7876 87/05/23                                                  
TURNER           7844 81/09/08                                                  
KING             7839 81/11/17                                                  
SCOTT            7788 87/04/19                                                  
CLARK            7782 81/06/09                                                  
BLAKE            7698 81/05/01                                                  
MARTIN           7654 81/09/28                                                  
JONES            7566 81/04/02                                                  
 
사원이름     사원번호 고용일                                                    
---------- ---------- --------                                                  
WARD             7521 81/02/22                                                  
ALLEN            7499 81/02/20                                                  
SMITH            7369 80/12/17                                                  
 
14 개의 행이 선택되었습니다.
 
 
 
cs


1
2
3
4
5
6
7
SQL> SELECT EMPNO, ENAME, JOB, SAL FROM EMP WHERE SAL BETWEEN 3000 AND 5000;
 
     EMPNO ENAME      JOB              SAL                                      
---------- ---------- --------- ----------                                      
      7788 SCOTT      ANALYST         3000                                      
      7839 KING       PRESIDENT       5000                                      
      7902 FORD       ANALYST         3000                            
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SQL> SELECT DEPTNO, ENAME, JOB, SAL*3 AS SAL FROM EMP;
 
    DEPTNO ENAME      JOB              SAL                                      
---------- ---------- --------- ----------                                      
        20 SMITH      CLERK           2400                                      
        30 ALLEN      SALESMAN        4800                                      
        30 WARD       SALESMAN        3750                                      
        20 JONES      MANAGER         8925                                      
        30 MARTIN     SALESMAN        3750                                      
        30 BLAKE      MANAGER         8550                                      
        10 CLARK      MANAGER         7350                                      
        20 SCOTT      ANALYST         9000                                      
        10 KING       PRESIDENT      15000                                      
        30 TURNER     SALESMAN        4500                                      
        20 ADAMS      CLERK           3300                                      
 
    DEPTNO ENAME      JOB              SAL                                      
---------- ---------- --------- ----------                                      
        30 JAMES      CLERK           2850                                      
        20 FORD       ANALYST         9000                                      
        10 MILLER     CLERK           3900                                      
 
14 개의 행이 선택되었습니다.
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
SQL> SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO FROM EMP WHERE (JOB = 'CLERK' OR JOB = 'ANALYST') AND SAL NOT IN (1000,3000,5000);
 
     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM       
---------- ---------- --------- ---------- -------- ---------- ----------       
    DEPTNO                                                                      
----------                                                                      
      7369 SMITH      CLERK           7902 80/12/17        800                  
        20                                                                      
                                                                                
      7876 ADAMS      CLERK           7788 87/05/23       1100                  
        20                                                                      
                                                                                
      7900 JAMES      CLERK           7698 81/12/03        950                  
        30                                                                      
                                                                                
 
     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM       
---------- ---------- --------- ---------- -------- ---------- ----------       
    DEPTNO                                                                      
----------                                                                      
      7934 MILLER     CLERK           7782 82/01/23       1300                  
        10                                                                      
                                                                                
cs


1
2
3
4
5
6
7
8
9
10
11
12
 
SQL> SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO FROM EMP WHERE ENAME LIKE 'M%';
 
     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM       
---------- ---------- --------- ---------- -------- ---------- ----------       
    DEPTNO                                                                      
----------                                                                      
      7654 MARTIN     SALESMAN        7698 81/09/28       1250       1400       
        30                                                                      
                                                                                
      7934 MILLER     CLERK           7782 82/01/23       1300                  
        10                                                                      
cs


1
2
3
4
5
6
7
8
 
SQL> SELECT JOB, COUNT(job) AS COUNT FROM EMP GROUP BY JOB HAVING COUNT(job) >=3;
 
JOB            COUNT                                                            
--------- ----------                                                            
CLERK              4                                                            
SALESMAN           4                                                            
MANAGER            3             
cs




본 자료는 4차 산업혁명시대를 맞아 제조업들이 사물인터넷을 어떻게 이용하고, 이를 통해 수집한 데이터를 어떻게 자사의 발전에 사용하는지 그 예시와 특이점을 알아본 것이다. 

해당 기업으로는 GE(General Electric), Caterpillar, Siemens, Michelin 이 있다.


 

저번 포스팅에 이어서 전처리를 마무리해보도록 하겠다.

코딩 전 엑셀로 정리를 해준 부분은 다음과 같다 


null 값이 들어있는 행을 모두 삭제하며, 그 전 보조지표로 추가했던 sma120을 삭제한다.

null값을 삭제하는 이유는 해당 데이터들이 있으면 제대로된 학습이 되지 않기 때문이며, sma120을 삭제하는 이유는 해당 지표를 변수로 쓰려면 

처음 119개 행들이 null값으로 출력되기 때문에 지나치게 데이터의 갯수가 줄어들기 때문이다. 


따라서 아래와 같이 정리해주게 된다.


정리를 해준 후, 각 행별로 타겟을 추가해주기 위한 코딩을 진행해준다. 

여기서 타겟은 해당 칼럼 기준으로 6, 12, 18, 24시간 뒤 가격을 타겟으로 쓰기 위해 해당 행에 맞게 칼럼을 추가해준다.

이해가 가지 않는다면 아래 그림을 보면 된다.


즉 우리는 low ~ signal까지의 칼럼으로 target 6, 12, 18, 24 칼럼을 예측하는 모델을 만드려 하는 것이다.


해당 과정을 진행하는 코드는 아래와 같다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import csv
 
#하루 4개씩 있어야됨, 6시간봉
= open("./중복제거최종데이터_전처리전.csv"'r', newline='')
rdr = csv.reader(f)
= open("./타겟추가데이터2_새로운방식.csv"'w', newline='')
wr = csv.writer(o)
wr.writerow(['time','low''high','open','close','volume','sma5','sma20''sma120''ema12','ema26','dn','mavg','up','pctB','rsi14','macd','signal','target_after6','target_after12','target_after18','target_after24']) # 필터 자리 놔둠
 
queue = []
for j,i in enumerate(rdr): #i는 행 값 (날짜부터 지표 다 포함)
    if(j!=0): #label 제외하고 읽어옴.
        queue.append(i) 
        if(j>4): #
            data = queue.pop(0# 1차원배열 
            data.append(queue[0][4])  # append 해서 옆쪽으로 붙인다 
            data.append(queue[1][4]) #4는 close 자리 
            data.append(queue[2][4]) 
            data.append(queue[3][4])
            wr.writerow(data)
 
 
f.close()
o.close()
cs


if문 안쪽 4번 칼럼은 close자리이고,  data.append(queue[0][4]) ~  data.append(queue[3][4]) 는 6시간~24시간을 뜻히는 것을 알 수 있다.

코드에서 볼 수 있는 것처럼 사이즈 4의 큐를 이용하여, 큐의 특성인 FIFO를 이용하여 순서에 맞게 종가를 새 칼럼으로 append 하였다. 




이번 포스팅에선 저번 포스팅에서 수집한 비트코인 가격 데이터에 모델 학습을 위한 변수를 추가하기 위해

기술분석에 쓰이는 보조 지표들을 추가해볼 것이다.


본 포스팅에서 필요한 라이브러리들과 설치법은  다음과 같다 


  • Pandas:   cmd창에서 pip install pandas 커맨드 입력후 설치
  • Numpy:   pip install numpy
  • Ta-Lib:    하단에서 설명
  • sklearn:   pip install sklearn


Cmd창은 항상 관리자 권한으로 열어야 한다는 것을 잊지말자.

TA-Lib같은 경우 이상하게 설치가 되지 않으므로 따로 웹사이트를 방문하여 다운받아줘야 한다



여기서 파이썬 버전에 맞는 것을 설치해주면 된다.

잘 모르겠다면 아래와 같이 입력하여 확인해볼수 있다. 

나는 3.5.4이고 (실수로)32비트 아나콘다를 설치하였으므로 cp35~win32.whl를 받으면 된다.

혹시나 이 글 보고 아나콘다를 설치해야 한다면 64비트로 설치하면 된다.


해당 파일을 파이선 워킹디랙토리에 넣고 pip install 파일명을 해주면 잘 설치가 되며, 설치 완료후에는 아래와 같은 화면이 뜬다.



이제 준비를 끝냈으니 TA-Lib와 보조지표들에 대해서 간단히 설명해 보겠다.

비트코인 가격을 분석할때 많은 트레이더들은 다양한 보조 지표들을 사용하며, 

차트는 심리의 반영이기 때문에 이러한 보조 지표들이 (일정부분) 맞아 떨어지는 경우가 많다.


비트코인 3시간 봉 - RSI를 볼때 과매수 영역으로 진입하고 있음을 알 수 있으며 RSI와 MACD가 상승하고 있다는 것은 매수가 붙고 있다는 것을 뜻한다


(더 많은 차트분석은 제 트레이딩뷰 퍼블리시에서 보실 수 있습니다)

이러한 이유로 보조지표가 유의미한 변수가 될 수 있다고 생각하였으며, 선택한 보조지표 리스트는 아래와 같다.

  • SMA5

  • SMA20

  • SMA120

  • EMA12

  • EMA26

  • MACD

  • RSI

  • BBANDS

그 외 다른 보조지표들은 깃허브 참고


해당 지표들을 추가하기 위한 파이선 코드는 아래와 같다.


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
32
33
34
35
36
37
38
39
40
import csv
import numpy as np 
import talib
import pandas as pd
 
 
df = pd.read_csv("./duplication_eliminated_bitcoin_data.csv")
df.head(20)
 
close = np.array(df[['close']])
close
 
##################################지표추가#######################################
 
df['sma5'= talib.SMA(np.asarray(df['close']), 5)
 
df['sma20'= talib.SMA(np.asarray(df['close']), 20)
 
df['sma120'= talib.SMA(np.asarray(df['close']), 120)
 
df['ema12'= talib.SMA(np.asarray(df['close']), 12)
 
df['ema26'= talib.SMA(np.asarray(df['close']), 26)
 
upper, middle, lower = talib.BBANDS(np.asarray(df['close']), timeperiod=20, nbdevup=2, nbdevdn=2, matype=0)
df['dn'= lower
df['mavg'= middle
df['up'= upper
df['pctB'= (df.close - df.dn)/(df.up - df.dn)
 
rsi14 = talib.RSI(np.asarray(df['close']), 14)
df['rsi14'= rsi14
 
macd, macdsignal, macdhist = talib.MACD(np.asarray(df['close']), 12269)  
df['macd'= macd
df['signal'= macdsignal
 
 
df.to_csv('./중복제거최종데이터_전처리전.csv', sep=',',na_rep='NaN')
 
cs

한 파이선 코드는 아래와 같

모든 보조지표는 종가를 매개변수로 받고 있으므로 우리는 종가(close)를 활용하여 보조지표를 추가해 준다



추가를 한 후 csv를 열어보면 잘 들어온 것을 확인할 수 있다. 

NaN은 아직 지표를 계산하기에 충분하지 못한 일수(ex 12일 이동평균선인데 12일보다 적게 데이터가 모여있음)이기 때문에 발생한 것이므로 

추후 분석시엔 NaN이 없는 지점부터 사용하게 된다.


다음 포스팅에선 해당 데이터들을 최종적으로 정리하여 전처리를 마무리하게 된다.

오늘부터 진행해볼 실습은 딥러닝을 통한 비트코인 가격 예측이다.

이를 위해서는 아래와 같은 프로세스를 통해 진행해 보겠다. 



따라서 오늘 진행할 것은 API를 통하여 비트코인의 과거 가격 데이터를 수집해보도록 하겠다 


우리가 API를 통해 받아올 거래소는 미국의 "Coinbase" 거리소이다. 

해당 거래소를 선택한 이유는 아래와 같다.


Coinbase (Gdax)

  • USDT가 아닌 USD를 사용 
  • 미국 내 거래량 1위 


Bitfinex와 Binance같은 거래소를 선택하지 않은 이유는 테더로 거래를 진행하기 때문이다. 

테더가 사실 우리가 진행할 예측에 크게 영향을 주진 않지만 때마침 테더 관련 이슈가 터진 상황이기 때문에 

향후에도 예측모델을 사용하기 위해 혹시모를 사태에 대비해 USD를 이용하는 Coinbase(Gdax)를 선택하였다. 


코인베이스의 API 설명 사이트는 이곳이며 클릭시 이동하게 된다.

해당 페이지에서 과거 데이터 수집을 위한 방법을 찾아보자.



대략적인 파라미터는 start(시작시간) 과 end(종료시간), 그리고 granulariy(몇시 봉으로 할건지)를 넣어줄 수 있다.

여기서 보여준 예시는 아래와 같다 


즉 종목과 TImeslice를 정해주면 지정해준 시간부터 지정해준 시간까지에 대한 데이터를 수집할 수 있다는 것이다.


Gdax는 UnixTIme을 쓰는데, 이는 우리가 쓰고있는 2018-02-16 이런 시간대신, 뭔가 다른 계산 프로세스를 통해서 시간을 표시하는 것이다.

해당 프로세스의 장점은 현실에서 2월은 30일까지 있고 3월은 31일까지 있고 이런 귀찮은 프로세스를 처리하지 않아도 자연스럽게 타임라인을

표시할 수 있다는 것이지만, 직관성이 매우 떨어진다는 단점을 가진다. 


자세한 시간계산 프로세스는 모르겠고, 우선 우리가 쓰는 시간을 Unixtime으로 바꿔줄 수 있는 코드는 아래와 같다. 


1
2
3
4
5
6
from datetime import datetime
 
def unixtime(t): #우리가 쓰는 시간을 유닉스타임으로 바꿈 
    temp = t.split('-')
    return int(time.mktime(datetime(int(temp[0]), int(temp[1]), int(temp[2])).timetuple()))
 
cs

활용 예시는 아래에서 다시 확인하겠다.


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
32
33
34
35
36
37
38
39
import gdax
from datetime import datetime
import csv
import time
 
#########데이터 수집################
public_client = gdax.PublicClient()
= open("./get_bitcoin_data.csv"'a', newline='')
wr = csv.writer(o)
 
granularity = 3600*6#3600*6 #6시간봉
interval = 3600*24*50
start_time = '2015-02-28'
last_time = '2018-01-17'
 
result = []
#for i in range(unixtime('2015-02-28'), unixtime('2018-01-17'), interval): #i는 15-02-28 ~ 18-01-17 이지만 (i, i+777600)(2015-02-28~2018-01-25까지) 뽑으니깐 오늘인 18-01-18까지 다 뽑아짐.
for i in range(unixtime(start_time), unixtime(last_time), interval): #i는 15-02-28 ~ 18-01-17 이지만 (i, i+777600)(2015-02-28~2018-01-25까지) 뽑으니깐 오늘인 18-01-18까지 다 뽑아짐.
    start = str(datetime.fromtimestamp(i)).split(' ')[0]
    if i + interval > unixtime(last_time): 
        end = str(datetime.fromtimestamp(unixtime(last_time) + 3600*24)).split(' ')[0# 이렇게 하면 새벽3시까지만 나오므로 18시간 뒤까지 뽑게 24시간의 초를 더해줌
    else:
        end = str(datetime.fromtimestamp(i+interval)).split(' ')[0]
    
    r = public_client.get_product_historic_rates('BTC-USD', start=start, end=end, granularity=granularity)
    for k in r:
        result.append([str(datetime.fromtimestamp(k[0])), k[1], k[2], k[3], k[4], k[5]])
 
    last_r_size = len(r) #마지막 넣을때 사이즈 - 예를들어 마지막에 12만 저장되면 
    print(last_r_size)
 
 
popped = result.pop(-1*last_r_size) #그냥 17일까지로 뽑으면 17일 새벽3시까지만 뽑힘. 그래서 하루 더 뽑은다음 제일 마지막 시간만 빼게 되면 17일 저녁 9시까지 뽑을수 있음 
print('del',popped)
for i in result:
    wr.writerow(i)
 
o.close()
##########################
cs

위 코드는 Gdax API를 활용하여 비트코인 과거 데이터를 뽑아온 것이다.

자세한 과정을 라인별로 설명하면 다음과 같다. 


우선 Gdax API를 사용하기 위하여 gdax를 import 해주고, 이를 csv 파일로 저장해주기 위한 코드 역시 삽입한다.


Granularity 는 3600 (한시간은 3600초) * 6을 하여 여섯시간 봉을 뽑아오게 된다.

Interval에 준 3600*24*50의 뜻은 한번에 뽑을때 50일치를 가지고 오는데 거기서 *4를 하니깐 200일치를 가지고 온다는 것이다.

즉 하루 4개(24시간 = 6시간 *4) * 50일치는 200개 봉.


그 아래 포문은 계속 뽑아오는 과정이고, 이 과정에서 한가지 짚고 넘어가야 할 것이 있다.

유닉스 타임을 사용해서인지 어떤건지 우리가 지정한 last_time이 전부 받아오는 것이 아닌, 해당 일의 새벽 3시까지 봉만 받아오는 문제점이 발생하였다.


따라서 last_time에서 하루를 더 받아온다음, 제일 마지막에 받아온 봉을 날리는 방법으로 우리가 원하는 last_time까지 데이터를 수집하기로 하였다.

해당 코드는 주석이 달린 부분에서 확인할 수 있다.


따라서 마지막까지 데이터를 다 받아온 후, 이에 대한 사이즈를 구해야 삭제하는 코드를 진행하였다. (result.pop~) 


해당 코드를 돌려보면 아래와 같이 뜬다. 



위에서 설명한 것처럼 200개씩 받아온 후, 마지막 행을 del을 프린트하며 삭제하도록 한다. 


받아온 csv파일을 열어보니 데이터 순서도 뒤죽박죽이고 무엇보다 중복된 데이터들이 있었다.

정확한 이유는 모르겠다. 아마 gdax api가 구려서 그런것 같은데.. 


여튼 이를 해결하기 위해 파이썬 딕셔너리를 사용하였다.


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
############ 중복제거##################   
= open("./get_bitcoin_data.csv"'r', newline='')
rdr = csv.reader(f)
dic = {}
for i in rdr: # 한줄씩 보겠다 
    key = str(i[0]) #0번인덱스 = 날짜 / 이걸 키로 설정함 
    value = str(i[1]) + ' ::: ' + str(i[2]) + ' ::: ' + str(i[3]) + ' ::: ' + str(i[4]) + ' ::: ' + str(i[5])
    #temp = str(i[0]) +' ::: ' + str(i[1]) + ' ::: ' + str(i[2]) + ' ::: ' + str(i[3]) + ' ::: ' + str(i[4]) + ' ::: ' + str(i[5])
    dic[key] = value
 
f.close()
 
= open("./duplication_eliminated_bitcoin_data.csv"'w', newline=''# 저장 
wr = csv.writer(o)
wr.writerow(['time','low','high','open','close','volume']) # 필터 자리 놔둠
 
for i in dic: # i 는 키 
    temp = dic[i].split(' ::: '# 딕셔너리는 랜덤하게 긁어옴 - 그래서 엑셀에서 정렬해줘야 
    temp.insert(0, i) #맨앞에 날짜 추가
    wr.writerow(temp)
    #wr.writerow(i.split(' ::: '))
 
 
o.close()
###########################
cs


파이선 자료형중 하나인 딕셔너리에 대해 간단하게 설명하면, 인덱스별로 짝을 맞게 삽입하여 인덱스를 입력하면 짝이 튀어나오도록 하는 것이다.

이 과정에서 중복되는 인덱스가 있으면(키) 둘 중 하나가 랜덤으로 삭제되게 된다.


csv파일을 보았는데 우리가 가진 데이터의 중복 튜플들은 소수점을 올림했냐 버림했냐 반올림했냐 등의 사소한 문제였기 때문에 뭐가 삭제되어도 

딱히 상관이 없으므로 그냥 딕셔너리에 삽입후 꺼내도록 한다. 


key는 0번 인덱스로 설정 - CSV파일을 TIme 칼럼을 뜻한다. 

그 뒤 해당 행의 가격 값들 (high, low, close, volum 등등등) 을 짝을 맞추어 딕셔너리에 삽입한다.(for i in rdr문) 

":::" 를 경계로 각 값을 붙였기 때문에 해당 값을 기준으로 다시 나눠주게 되고, 해당 행의 0번자리(제일 앞자리)에 i(날짜)를 추가하게 된다. (for i in dic문) 


이렇게 저장된 csv파일을 확인해보면 


이렇게 중복 데이터가 삭제된 것을 확인할 수 있다. 

물론 정렬은 안 된 상태여서 그냥 액셀에서 필터를 활용하여 오름차순 정렬을 하였다. 


이렇게 해서 API를 활용한 비트코인 가격 데이터 수집을 마치고, 

이제 모델 학습에 활용할 변수 획득을 위한 보조지표(기술분석을 위한 보조지표)를 추가하여 보겠다. 


오늘은 Rattle을 사용한 기계학습을 통한 알고리즘을 구현해볼 것이다.

말은 복잡하지만 지금까지 라이브러리를 통해 구현한 SVM, neuralnet, decision tree 등 다양한 학습 알고리즘을

GUI로 작동하는 프로그램으로 구현하는 것이다.



rattle 패키지를 설치하고 실행한다.



요런 창이 뜬다. 상당히 직관적이여서 쉽게 사용할 수 있지만 간단히 몇가지 실습을 진행해 보겠다.

오늘 실습할 데이터는 KNN 구현때 사용했던 유방암 진단 데이터를 사용할 것이다 (클릭시 이동).



cancer 데이터는 이런식으로 되어있는데, 숫자의 편차가 크기때문에 정규화를 진행해 보도록 하겠다.



정규화할 칼럼을 선택한 후, 위에 실행을 눌러준다 



스크롤을 내려보면 R01_로 시작하는 정규화된 칼럼들이 추가되었을 것이다. 이제 정규화 된 칼럼들을 제외한 나머지 칼럼들을

삭제해보도록 하자. 위에 클린업을 체크하고 실행을 눌러준다. 



아래와 같은 메세지가 뜬다면 성공이다.


이제 이렇게 전처리된 데이터를 활용하여 의사결정트리를 만들어 보겠다.

방법은 아래와 같다. 



실행을 누른 후, 오른쪽 Draw를 누르면 R스튜디오 플럿 창에 아래와 같은 그림이 나온다.

.


의사결정트리에 대해 알고싶다면 이전 포스팅 으로 가보자.



이렇게 의사결정트리 구현을 마무리 하였으면, 이 결과를 평가하고 csv파일로 저장할 것이다.


전체 에러 4.7%로 비교적 준수한 결과를 보여주고 있다.



Score 선택후 실행을 눌러서 CSV파일을 저장할 수 있다.



CSV파일을 열어보면 왼쪽이 진짜 진단결과고, 오른쪽이 의사결정트리를 통한 예측 결과인 것을 알 수 있다.


이를 응용하여 SVM, neuralnet 등 다양한 알고리즘을 구현할 수 있다.

참고로 Log를 보면 구현 결과를 R언어로 다시 한번 볼 수 있으니 참고해도 좋다.




1
2
3
4
5
6
7
8
9
10
11
## Step.3  Evaluating model performance ###
 
#추천실시
UBCFlist <- predict(mUBCF, recommenderUserList, n=5)
 
IBCFlist <- predict(mIBCF, recommenderUserList, n=5)
 
 
#추천받은 리스트 보기
as(UBCFlist, "list")
as(IBCFlist, "list")
cs

이제 본격적으로 모델을 구현해 보겠다.

위 코드처럼 입력해주면 우리는 추천 리스트를 만들게 되는데, 그 결과는 아래 화면과 같다 



직관성이 떨어지지만 읽어보면 제일 위 114 고객에는 20, 425, 771, 31, 47번 물품을 추천한다는 것이다.

바로 위에서 추천을 할때 n을 5로 주어서 다섯개만 추천해 준 것이며, 이 숫자를 바꿔주면 해당 숫자의 갯수만큼 추천해준다.


이제 모델 결과표와 그래프를 생성해 보겠다. (사실 위 과정까지만 해도 추천 과정은 끝난것이다)


1
2
3
4
5
6
7
8
9
10
# 시뮬레이션에 사용할 알고리즘과 유사도 지표 종류 지정
alUBCF<-list("user-based CF_Cosine" = list(name = "UBCF"
                                           param = list(method = "Cosine")),
             "user-based CF_Pearson" = list(name = "UBCF"
                                           param = list(method = "Pearson")))
 
alIBCF<-list("item-based CF_Cosine" = list(name = "IBCF"
                                           param = list(method = "Cosine")),
             "item-based CF_Pearson" = list(name = "IBCF"
                                           param = list(method = "Pearson")))
cs


위는 평가를 위한 알고리즘을 생성한 것이다. 각각 Cosine과 Pearson 두 가지를 모두 포함한 알고리즘을 만들어주면 된다.




위는 우리가 생성했던 모델에 대한 최종 평가에 사용할 evaluation 함수이다. 바로 위에서 생성한 알고리즘이 알고리즘 자리로,

초반부에 evaluationScheme 함수로 생성한 결과같이 scheme로 오게 된다.


 

1
2
3
4
5
6
7
8
# 실행 및 결과 표시
result1<-evaluate(scheme, alUBCF,n=c(1,3,5))
result1
avg(result1) #결과값 테이블을 볼 수 있는 결과물 
 
result2<-evaluate(scheme, alIBCF,n=c(1,3,5))
result2
avg(result2) 
cs


이런식으로 실행을 해주게 되면 



이런 결과가 나온다. 


여기서 핵심적으로 봐야할 것은 precision 과 recall 이며, 해당 지표에 대한 설명은 이전 포스팅에서 진행하였다.

하지만 직관성이 떨어지기 때문에 다시 그래프를 그려보도록 한다.


1
2
3
4
5
6
7
# 그래프 
 plot(result1, annotate = TRUE , legend = "bottomright"#  높음 (두자리)  - 코사인 높음 
 plot(result1, "prec/rec", annotate = TRUE , legend = "bottomright"# 낮음 (세자리) 
 
 plot(result2, annotate = TRUE , legend = "topleft"# 피어슨이 더 높다 
 plot(result2, "prec/rec", annotate = TRUE , legend = "topleft")
 # 추천성능 UBCF 가 현저하게 높다 
cs


 

참고로 plot 함수의 인자는 아래와 같다.




위의 과정을 끝냈으면, 각각 ROC 방식("pre/rec"라고 입력 안하면 defalt가 ROC) 일때 result1 과 result2의 성과를 확인해보도록 하겠다.

제일 위 코드를 실행시키면 아래와 같은 그래프가 뜬다.

UBCF 의 경우 코사인 방식이 더 성과가 좋은것을 알 수 있다. 


IBCF 의 경우 피어슨 방식이 더 성과가 좋은것을 알 수 있다. 






오늘은 R로 상품추천기술중 하나인 IBCF와 UBCF를 구현해 보겠다.



sample.csv


샘플데이터는 아래와 같이 생겼다.



데이터에 대하여 간단히 설명하면, V1과 V2, 그리고 V3는 각각 사용자식별번호, 아이템번호, 구매 횟수를 뜻한다.

즉 이미 전처리가 어느정도 완료되어 있는 데이터를 바탕으로, 우리는 사용자 베이스 추천, 아이템 베이스 추천을 진행하도록 하겠다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
##########################################
## 온라인 유통회사의 추천 시스템 사례 ####
##########################################
## step.1 preparing the data #####
 
# 데이터 로딩
data<-read.csv("sample.csv",head=FALSE, sep =",")
View(data)
 
# 추천시스템 패키지를 인스톨
install.packages("recommenderlab")
 
 
# 패키지를 로딩
library(recommenderlab)
 
 
# 데이터형을 realRatingMatrix로 변환
<-as(data, "realRatingMatrix")
 #바이너리는 산 횟수가 0 1 (샀다 안샀다) 리얼레이팅은 진짜 횟수 (0~) 
cs


우리가 사용할 패키지는 recommenderlab 이며, 없다면 설치하도록 하자.

아래 행의 realRatingMatrix 는 진짜 횟수에 대한 것으로, 우리는 V3칼럼에서 볼 수 있는 것처럼 샀는지 안샀는지의 유무가 아닌

얼마나 구매했는지를 바탕으로 모델을 만들어야 하기 때문에 realRatingMatrix를 사용한다.


binary 일 경우네는 쉽게 이야기해 더미 변수처럼 1 0 으로 샀냐 안샀냐만 구분해주는 것이다.


1
2
3
4
5
6
7
8
9
10
## Step.2 Training a model on the data ###
 
# 머신러닝을 위해 학습데이터선정
# 전체데이터의 90%를 학습데이터로 선정
trainingData<- sample(4945,4500#(4950개중 4500개 추출 )
trainingSet<- r[trainingData]
 
# 행의 총합 5개 이상의 아이템만 선택, 많이 팔리지 않은 아이템을 제외시킴
trainingSet<-trainingSet[rowCounts(trainingSet) > 5#아이템이 적은것은 왜곡된 추천결과 보내줄수 있음 
as(trainingSet,"matrix")  
cs


이제 모델을 생성하기 위한 작업을 해보자.

코드에서 볼 수 있는 것처럼 트레이닝셋과 테스트셋을 구분하기 위하여 추출을 해주는데, 이 과정에서 구매 횟수가 5보다 낮은것은

제외하도록 한다. 그 이유는 구매가 적으면 아웃라이어처럼 결과에 왜곡을 줄 수 있기 때문이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# scheme 지정과 표시
# 추천의 평가방식을 저장 
# split은 분할, crosss는 교차검정 
# train 은 모델만드는 데이터 비율로서 아래 코드는 이를 80%로, 나머지 20%를 평가셋으로 한 것을 의미
# given 은 사람당 평가하는 아이템 수 
# K는 시뮬레이션 반복횟수
scheme <- evaluationScheme(trainingSet,method="split", train = .8,
                           given = 6
                           goodRating = 4,
                           k = 3)
    #추천의 평가방식을 지정하고 저장 - 중요하다
    #교차검정(crosstable) - 전체 데이셋을 k개로 나눈다 
    # train - 모델을 만드는 데이터 비율 - 위 코드는 80퍼로 만듬
    # given 은 사람당 평가하는 아이템 수 
    # goodrating = 실제 사용 등급이 4이상이면 모두 평가에 포함 
    # 시뮬레이션 실행할때마다 결과가 바뀜 - 너무많이 돌리면 개선이 덜 되고, 적게돌리면  편차 큼 
cs


위는 상품추천기술의 핵심 함수라고 할 수 있는 evaluationScheme 함수이다. 설명은 주석을 참고하면 된다.

.




위는 또다른 핵심 함수인 Recommender에 대한 설명이다. 여기서 우리는 UBCF 와 IBCF를 구분해서 각각 모델을 생성하게 된ㄷ.

파라미터로는 cosine와 pearson 두 가지가 있으며, 선택해주면 된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 추천모델생성
mUBCF <- Recommender(trainingSet,method="UBCF",
                     parameter="Cosine")
 
mUBCF
 
mIBCF <- Recommender(trainingSet,method="IBCF",
                     parameter="Cosine")
 
mIBCF
 
# 추천을 받을 사용자리스트 (Testset)
recommenderUserList<-r[-trainingData] # 트레이닝데이터 반대되는 행들을 테스트셋으로 
 #트레이닝셋을 쓰지않고 데이터를 쓰는 이유는 이미 4500명에 대한 
 #트레이닝데이터를 만들었기 때문에 445명에 대한 테스트셋을 만들위해 추천리스트 다시 설정 
 
cs


위와 같이 코딩을 해주면 되고, 아래 -trainingData는 아까 설정한 트레이닝데이터를 제외한 나머지를 테스트 데이터로 사용하겠다는 뜻이다.



상품추천기술은 개인화 기술이라고 불리며 그 핵심 기술인 협업 필터링은 아래와 같은 특징을 가진다


협업필터링(Collaborative filtering) 

  • 공동여과기법 
  • 기호가 유사한 다른 사람이 좋아하는 상품을 추천하는 기법 
  • 자동화된 구전효과


글로만 보면 잘 이해가 안될텐데, 아래 사진을 같이 보자.



아래는 새로운 고객인 10번 고객과 기존 고객들간의 유사도를 계산하여 선호도를 계산하는 과정이다.

표에 있는 검은색 숫자가 기존에 유자10이 가지고 있던 선호도이고, 빨갠색 글자가 기존 고객과 비교를 통해

유사한 고객들과의 연관성을 바탕으로 예상되는 추천도를 계산한 것이다.


이 때 사용되는 계산법이 피어슨스 계수(Parson correlation coefficient) 이다.



이런식으로 특정 유저 두 명간 상관관계(유사도)를 피어슨스 계수를 통해 측정하는데,

이 때 나타난 그래프의 기울기가 1에 가까울수록 유사하다고 할 수 있우며, 최저는 당연히 0이다.


이러한 협업 필터링은 다시 두 가지로 분류할 수 있다.


유저 기반(UBCF)

  • 해당 유저와 취향이(성향) 비슷한 유저가 좋게 평가한 것을 추천 

  • 더 정교함

  • 유저가 신규 진입할때마다 계산해야 해서 구현에 시간이 더 걸린다

상품 기반(IBCF)

  • 상품간 유사도 바탕

  • 신규 진입할때마다 계산할 필요가 없음(미리 계산해놓을수 있음) 


UBCF를 그림으로 표시해보면 아래와 같다.





이 때 중요한건 수치가 중요한게 아니고, 그래프의 모양이 비슷해야 유사도가 높다는 것이다.

즉 유저 1과 Alice는 점수의 절대치에 있어서는 유사도를 찾기 힘들지만, 그 패턴은 동일하기 때문에 (유저1을 위로 2점씩 끌어올리면 Alice와 겹친다) 유사하다고 판단할수 있다.



이론상으로 유저들간 유사도를 계산하는 공식은 위와 같은데, 엑셀을 사용하면 비교적 쉽게 할 수 있다.




위 유사도를 구한 결과에서 상위 두 개의 유저를 선택하여(이 경우에는 U1, U2) 이 둘이 평가한 것을 바탕으로 Alice가 U5를 어떻게 평가할지 

그 추정치를 구하는 공식은 위와 같다. 

즉 우리는 UBCF기법을 사용하면 Alice가 아이템 5의 평가를 4.87로 할 것이라는걸 추측할 수 있다. 



다음은 IBCF를 알아보도록 하자. 아래 그림을 참고하면 된다.


IBCF는 코사인 유사도를 바탕으로 그 유사도를 계산한다. 


마찬가지로 엑셀로 유사도를 계산하도록 한다.


위와 같은 추천시스템의 평가지표로는 아래와 같은 지표들이 있다.


정확도(precision, accuracy) 

사용자가 실제 선택한 아이템 수  / 전체 측정된 아이템 수 


재현율(recall) 

맞는 추천 아이템 수 / 사용자가 선택한 전체 아이템 수 


F측정치 (F measure) 

(2*정확도*재현율) / (정확도 + 재현율) 


범위(coverage)

추천이 가능한 사용자 수(or 아이템 수) / 전체 사용자 수 (or 아이템 수) 





오늘은 저번 포스팅에서 설명하였던 SVM 을 구현할 예정이다.

테스트 데이터셋은 아래 링크에서 받을 수 있다.



https://archive.ics.uci.edu/ml/datasets/letter+recognition


데이터셋의 변수를 확인해보자.





변수마다 뭘 뜻하는지는 정확히 모르겠고, 여튼 글자 모양(좌표)에 대한 변수라고 생각하면 되겠다.
즉 letters마다 좌표, 넓이 등이 다르다는 것에 착안하여 모델을 만들고, 새롭게 들어오는 데이터들을 성공적으로 분류하는 것을 목표로 한다 

코드는 아래와 같다.


1
2
3
4
5
6
7
8
9
10
## step.1 preparing the data #####
# 데이터 읽기와 구조 확인
letters<-read.csv("letter.csv")
str(letters) #상형문자의 특징들 
 
summary(letters) #최대최소값이 비슷하기 때문에 굳이 정규화 필요 없다 
 
# Training (80%)와 Test(20%) 나누기
letters_train<-letters[1:16000,]
letters_test<-letters[16001:20000,]
cs


특징을 확인하고 학습용과 검증용 데이터로 나눈다. 



1
2
3
4
5
6
## Step 2: Training a model on the data ----
# 단순 선형 SVM을 훈련으로 시작
install.packages("kernlb")
library(kernlab)
letters_classfier<-ksvm(letter~. , data = letters_train, 
                        kernel="vanilladot"# 선형커널 
cs

우리가 사용할 라이브러리는 "kernlab" 라는 라이브러리다.

분류 모델을 만드는 핵심 함수는 ksvm함수인데, 설명은 아래와 같다.




우리의 경우는 letters를 예측할거고, 예측에 사용하는 데이터 프레임 속성은 전부 다 사용하니깐 .로 표시한다.

data 에는 학습용 데이터를 써주고, 사용할 kernel 종류는 vaniladot 을 사용하기로 한다.

여러 kernel 타입이 있는데, 목적에 맞게 선택하여 모델을 만들면 된다.



1
2
3
4
## Step 3: Evaluating model performance ----
# 테스트 데이터셋에 대한 예측
letter_predictions<-predict(letters_classfier,letters_test)
#response - 예측된 범주 인지, probabilities - 예측된 확률인지  / 안쓰면 response 
cs

그 후 predict 함수를 사용하여 예측을 하게 된다. 

해당 함수는 predict(사용할 모델, 예측하고싶은 데이터셋, response or probabilities) 를 사용하면 된다

여기서 response는 예측된 범주일 경우, probailities 는 확률일 경우 사용한다.

우리는 알파벳의 확률 예측이 아니고 범주를 나누는 것이니 response를 사용하기로 하는데, 디폴트 값이 response여서 따로 써줄필요는 없다.


1
2
3
4
# 테스트 데이터 셋 문자와 예측된 문자 비교
View(table(letter_predictions,letters_test$letter))
 
 
cs
이렇게 View 와 table명령어를 사용하면, 예측값과 진짜 검증 데이터의 letter 컬럼이 얼마나 일치하는지 확인해볼 수 있다.



이런식으로 예측값이 인데 진짜 letters컬럼 값이 A일 경우, B일 경우, C일 경우.. 이런식으로 쭉 확인할 수 있다.
하지만 이럴경우 가독성이 떨어지고, 직관성이 떨어지기 때문에 아래 코드를 통해 간단하게 정확도를 확인 할 수 있다. 

1
2
3
4
5
6
7
8
9
10
# look only at agreement vs. non-agreement
# 일치/불일치 예측을 표시하는 TRUE/FALSE 벡터 생성
agreement<-letter_predictions == letters_test$letter
 
# 4000개 중 레코드 어떻게 나오는 지 식별
table(agreement) ## 3357개 정확히 식별 / 643개 틀리게 식별 
 
# agreement실행결과 
FALSE  TRUE 
  643  3357 
cs

 

즉 우리는 3357개를 정확히 식별했고, 643개를 잘못 식별했음을 알 수 있다.




SVM 에 대해 좀 더 자세한 설명을 원하신다면 해당 포스팅 에서 보실 수 있습니다


서포트 벡터 머신은 2차원에서 머무르는 것이 아닌, 3차원 등 차원을 높여서 데이터를 나누는 과정을 뜻한다

즉 고차원에서 데이터를 분류할 수 있는 일종의 칸막이를 만드는 것이다.


이를 좀 더 정확히 설명하면


SVM

 데이터에 있는 특성들을 kernel 함수를 이용하여 입체공간에 데이터를 분류할 수 있는 *판을 만들어 주는 것 

 *판 = 초평면(Hyperplane) 


SVM 의 목표

 Maximum margin hyperplane 을 찾는 것, 즉 마진을 최대화하는 초평면을 찾는 것 


이제 마진은 뭔지, 맥시멈 마진은 어떻게 찾는지 알아보도록 하자.




다시 한번 용어를 정리해보면


Hyperlane 초평면

- 데이터들을 분류할 수 있는 칸막이


Support vectors 서포트 벡터

- 초평면에서 가장 가까운 데이터들  


Margin 마진

- 양쪽 Support vectors와 hyperplane 간의 거리의 합 


이해가 잘 가지 않으면, 그림을 보면 직관적으로 알 수 있다.


즉 서포트 벡터들의 거리인 마진의 최대치 (Maximum margin)을 찾는 것이 서포트 벡터 머신의 목표이며

이 마진의 최대치를 보여주는 초평면이 최종 초평면이 되는 것이다. 


서포트 벡터 머신의 장단점은 아래와 같다.


장점

1.     분류문제나 예측문제 동시에 쓸 수 있다.

2.     신경망 기법에 비해서 과적합 정도가 덜하다.

3.     예측의 정확도가 높음.

4.     사용하기 쉽다

 

단점

1.     Kernel과 모델 파라미터를 조절하기 위한 테스트를 여러 번 해봐야 최적화된 모형을 만들 수 있다.

2.     모형 구축 시간이 오래걸린다

3.     결과에 대한 설명력이 떨어진다


이번 포스팅에선 변수에 따라 콘크리트 강도를 예측하는 모델을 신경망을 통해서 만들어 보겠다.

샘플 데이터는 아래 링크에서 다운로드할 수 있다.


https://archive.ics.uci.edu/ml/datasets/Concrete+Compressive+Strength




총 1030개의 데이터가 있으며, cement ~ age등의 정도에 따른 콘크르티의 strength 변수의 예측 모델을 만드는 것이 목표이다.



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
## step.1 preparing the data #####
# 데이터 읽기와 구조 확인
concrete <- read.csv("concrete.csv",stringsAsFactors = TRUE)
str(concrete) # 신경망은 정규화를 해줘야 한다 
 
View(concrete)
#  정규화 함수
normalize<-function(x){
  return ((x-min(x))/(max(x)-min(x)))
}
 
# 전체 데이터 프레임에 정규화 적용
concrete_norm<-as.data.frame(lapply(concrete,normalize))
 
 
# 0과1 사이에 범위 확인
summary(concrete_norm$strength)
 
# 본래 데이터의 최소값, 최대값 비교
summary(concrete$strength)
 
# 훈련과 테스트 데이터 생성
concrete_train<-concrete_norm[1:773,]
concrete_test<-concrete_norm[774:1030,]
View(concrete_test)
cs


위는 데이터 전처리 과정에 대한 코드이다.


우선 csv를 불러오고, str로 살펴본 결과 데이터가 퍼져 있으며로 정규화 함수를 이용하여 정규화를 진행한다 

(KNN 구현 포스팅에 더 자세히 있다).


lapply 함수는 lapply(적용하고싶은 대상 변수, 적용할 함수) 식으로 구성하면 된다.

이렇게 정규화를 끝냈으면 이를 다시 7대 3으로 훈련용 데이터와 테스트 데이터로 분류한다


1
2
3
4
5
6
7
8
9
10
## Step 2: Training a model on the data ----
# neuralnet 모델 훈련
#install.packages("neuralnet")
library(neuralnet)
 
# 하나의 은닉 뉴런에 대한 단순한 ANN
concrete_model<- neuralnet(strength ~ 
                             cement + slag  + ash + water + superplastic + coarseagg +fineagg + age,
                           data = concrete_train)
 
cs


오늘 사용할 라이브러리는 neuralnet 라이브러리를 사용할 것이다.


neuralnet에서 신경망을 통한 모델 생성 역할을 담당하고 있는 라이브러리는 "neuralnet" 함수이다

(라이브러리 이름과 동일하다)

neuralnet 함수의 구성은 아래와 같다.



좀 더 자세히 설명하면,


neuralnet 함수의 제일 앞부분에는 target 변수(예측 하고싶은 변수 - 우리의 경우는 strength 이다) 

predictors 부분에는 위 타겟변수를 예측하는데 활용할 변수들을 쓴다


구분 기호는 위 예시처럼 +를 사용하면 되며, 다시 예를들어 neuralnet(A ~ B + C + D) 라고 한다면, 

A 변수를 B, C, D를 조합하여 예측한다는 것이다.


data 는 학습용 데이터 셋을 써주면 되고, hidden은 몇 개의 은닉층을 가질 것이냐에 대한 것이다.

(이 역시 이전 포스팅에 더 자세히 나와있다)


1
2
3
4
5
6
7
8
9
# 망(network) 시각화
plot(concrete_model)
 
## Step 3: Evaluating model performance ----
# 모델 결과
model_results<-compute(concrete_model, concrete_test[1:8]) #9는 예측값 
 
# 강도값 예측
predicted_strength<-model_results$net.result #예측값을 봐야하기때문에 net.result
cs


망 시각화를 해보고싶다면 plot 함수를 사용할 수 있지만, 어차피 봐도 모른다.


compute는 모델을 평가하는데 쓰이는 함수로, compte(평가에 사용할 모델,이 모델을 활용하여 분석할 변수들(cement ~ age))로 사용가능하다.

이렇게 결과를 model_results 변수에 담고, 이를 마지막으로 평가하기 위해서 net.result를 활용하여 예측된 강도값을 담는다


참고로 net.result 값 (예측된 strength 값들은 다음과 같다) 


이걸 수동으로 진짜 값과 맞는지 대조해볼수는 없는 노릇이다.

따라서 아래와 같이 예측값에 대한 평균적인 상관계수를 구할수 있다. 


1
2
3
4
# 예측값과 실제값간의 상관 관계 확인
# 결과 값이 다양하게 측정됨(매번 다르게 측정)
cor(predicted_strength,concrete_test$strength)
  #1에 가까울수록 좋다 
cs




즉 오늘 우리가 만든 모델은 0.8 (80퍼)의 상관계수를 가진다.





신경망 이론의 좀 더 자세한 설명 및 파이선 구현 코드는 이곳을 클릭하세요


암상자 기법은 오른쪽 그림처럼 다양하게 섞여 있는 데이터들 사이에서 분류선을 잘 만들어 주는 기법이다.

하지만 '암상자'에서 알 수 있는 것처럼, 해당 알고리즘엔 큰 단점이 있는데 그 과정을 설명하기 애매하다는 것이다.


이 예시로는 추후에 포스팅할 SVM과 신경망 등이 포함되며, 해당 기법들은 예측 정확도는 높지만

그 결과 도출을 위한 과정을 설명하기 애매해다는 단점이 있다.


우선, 암상자 기법중 하나인 신경망 이론에 대하여 알아보자.


신경망은 크게 입력 - 은닉 - 출력층으로 나누어진다. 


이 때 입력층에서 출력층으로 가며 데이터마다 가중치를 부여해, 출력층에서 최적의 예측값을 낸다는게 목표인데,

해당 과정은 다음과 같다.


은닉층에서 연산을 거쳐서 출력값을 나오게 하는 것임. 즉 선마다 가중치가 있어서 이에 따라 분석 – 

신경망은 가중치를 결정하는 것 


Feed-forward  / Back-propagation Neural net  - 출력된 값을 보고 정답하고 다르면 역전파(가중치를 뒤로 조정하면서) 최적화된 가중치를 만들어 낸다 


이 때 은닉층은 자유롭게 결정할 수 있는데, 우리가 진행하고 있는 비즈니스 애널리틱스에서는 보통 3계층의 형태를 많이 사용한다. 

그 이유는 해당 은닉층으로도 충분히 분석이 가능하기 때문이다.

위 사진은 해당 노드가 어떻게 가중치를 적용하여 인풋을 받고, 이를 다시 다음 노드로 보내주는지 설명하고 있다.


이를 활성화 함수 라고 하는데, 이 활성화 함수는 


활성화 함수 (Activation function)

-       Combination function(결합함수)

모든 인풋들을 하나의 value로 합침

가중치를 거친 합

                        A lot of flexibility in the choice of combination functions


-       Transfer function(전이함수)  



로 설명할 수 있다.


즉 결합함수 부분은 가중치를 적용하여 들어온 input value들을 하나로 합치고,

전이함수는 이렇게 합친 value를 다음 노드로 전송하는 역할을 담당한다.



시그모이드 함수는 input value를 0~1사이로 보정한다


이 때 전이함수는 해당 값을 보정하여 전송하기도 하는데, 이러한 함수들에는 시그모이드, 가우시안 함수 등이 있다. 




위에서 볼 수 있는 것처럼, 가중치를 적용하여 그 값을 계산하고, 이렇게 합친 값을 시그모이드 함수로 

보정하여 다음 노드로 전송하는 것을 알 수 있다.


.

이러한 신경망 기법의 장단점은 아래와 같다.


장점

  • 신경망은 범주도 나눌 수 있고 특정한 값을 예측할 수 있다 ‘(Numeric prediction 가능)

  • 복잡한 패턴임에도 불구하고 모형 만들 수 있음

  • 데이터에 대한 가정을 거의 하지 않는다  - 어차피 데이터 패턴을 외우는 것이기 때문

  • 분류나 예측 결과가 좋다


단점

  • 모델을 만드는데 시간이 오래걸리며 (복잡하면) 컴퓨터 능력이 많이 필요함

  • Overfitting 문제가 발생할 가능성이 있다

  • 예측값은 있지만 (결과는 있지만) 과정을 이해할 수 없다 따라서 실무적으로 사용하는데 문제가 있을수 있음(고객에게 설명을 해줄 수 없다


+ Recent posts