English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
3세대 신경망: 심층 신경망

3세대 신경망: 심층 신경망

MetaTrader 5지표 | 12 10월 2021, 15:04
421 0
Vladimir Perervenko
Vladimir Perervenko

개요

  1. 2세대 신경망
  2. 딥러닝
  3. 실제 적용
  4. 인디케이터 및 엑스퍼트 어드바이저 구현

개요

딥러닝과 심층 신경망과 같은 주제에 대해 쉽게 설명해 보겠습니다.

실제 데이터를 적용한 실험 결과 심층 신경망의 이론적 장점을 직접 확인할 수 있었습니다. 분류를 해보면 되는데요. 심층 신경망 모델을 기반으로 하는 인디케이터와 EA를 만들어 클라이언트/서버 구조를 통해 테스트해 보겠습니다.

본문은 인공 신경망에 대한 기본적 이해를 가진 독자를 대상으로 합니다.


1. 2세대 신경망

신경망은 이미지 처리와 관련된 광범위한 문제를 해결하도록 고안되었습니다.

신경망을 이용하면 다음과 같은 문제를 해결할 수 있죠.

  • 함수 근사(회귀)
  • 특정 클래스 세트를 이용한 데이터 분류
  • 기존에 알려지지 않은 원형 클래스 식별을 동반한 데이터 클러스터링
  • 데이터 압축
  • 손실 데이터 복구
  • 연관 메모리
  • 최적화, 최적제어 등

이번 글에서는 '분류'만을 다루게 될 겁니다.


1.1. 연결 구조

정보 처리 방식은 네트워크 내 피드백 유무에 따라 크게 변합니다. 뉴런 사이에 피드백이 발생하지 않는 경우 정보 처리는 단일 방향으로 실행됩니다. 입력 시그널이 시퀀스 레이어를 통해 프로세스되며 레이어의 개수와 동일한 개수의 tact를 갖는 응답이 돌아옵니다.

피드백이 있는 경우 신경망 다이내믹이 예측할 수 없어지죠. 이를 순환 신경망이라고 합니다. 사실 신경망은 응답을 보내지 않고 계속해서 피드백만을 발생시킬 수 있습니다. 하지만 튜링에 따르면 임의 순환 신경망은 엘리먼트의 평형을 알 수 없다고 하죠(속도의 한계).

순환 신경망 내 뉴론이 반복적으로 정보 처리에 참여하기 때문에 순환 신경망은 여러 방법으로 심층적인 정보 처리를 할 수 있게 됩니다. 따라서 신경망이 피드백을 멈출 수 있도록 특수한 조치를 취해야 하죠. 예를 들어, 홉필드 네트워크에서처럼 대칭 연결을 이용하거나, 강제로 반복 회수를 제한할 수 있습니다.


학습 방법

연결 방법
지도 학습비지도 학습
피드백 없음다층 퍼셉트론(함수 근사, 분류)

경쟁식 신경망, 자기조직화 지도(데이터 압축, 특징 분리)
피드백 있음순환 퍼셉트론(시계열 예측, 온라인 학습)

홉필드 네트워크(연상 메모리, 데이터 클러스터링, 최적화)

표 1. 연결 타입 및 학습 타입으로 분류한 신경망


1.2. 신경망 종류

퍼셉트론으로 시작한 신경망은 엄청나게 진화했습니다. 구조와 학습 방법이 다른 아주 다양한 신경망이 존재하죠.

다음은 그 중 가장 잘 알려진 신경망들입니다.

1.2.1. 다층 퍼셉트론

그림 1. 다층 신경망

그림 1. 다층 신경망

1.2.2. 조단 신경망은 순환 신경망의 특성을 띄며 엘만 신경망과 유사합니다.

입력 레이어에 추가 컨텍스트 뉴런이 있는 순방향 신경망으로 볼 수 있죠.

컨텍스트 뉴런은 인풋 뉴런 및 컨텍스트 뉴런 자체로부터 피드를 받습니다. 현재 네트워크 상태를 유지하죠. 조단 신경망에서 컨텍스트 뉴런의 개수와 입력 뉴런의 개수는 동일해야 합니다.

그림 2. 조단 신경망 구조

그림 2. 조단 신경망 구조

1.2.3. 엘만 신경망은 순환 신경망의 특성을 띄며 조단 신경망과 유사합니다. 엘만 신경망과 조단 신경망의 차이는 엘만 신경망의 컨텍스트 뉴런이 출력 뉴런이 아닌 은닉 뉴런의 피드를 받는다는 것입니다. 또한 컨텍스트 뉴런이 컨텍스트 뉴런의 피드를 받지 않죠.

엘만 신경망에서 컨텍스트 뉴런과 은닉 뉴런의 개수는 동일합니다. 가장 큰 장점은 컨텍스트 뉴런의 개수가 조단 신경망에서처럼 출력 뉴런 개수로 정의되는 것이 아니라 은닉 뉴런의 개수로 정의되어 신경망이 보다 유연하다는 것이죠. 은닉 뉴런은 쉽게 추가하거나 삭제할 수 있습니다.


그림 3. 엘만 신경망 구조

그림 3. 엘만 신경망 구조

1.2.4. RBF 신경망은 순방향 신경망이며 방사 대칭을 이루는 뉴런의 은닉 레이어를 포함합니다. 이 뉴런은 특정 인풋 벡터로부터의 거리를 가우스 함수의 중심값으로 변환합니다.

RBF 신경망은 다층 순방향 신경망에 비해 많은 장점을 갖고 있습니다. 우선, 단 하나의 중간 레이어를 갖는 임의의 비선형 함수를 이용하므로 개발자가 레이어 개수를 설정할 필요가 없죠. 또한 선형 최적화를 통해 출력 레이어의 선형 조합 변수가 최적화됩니다. 아주 빠르게 최적화가 실행되며 역전파에 영향을 줄 수 있는 극값과 관련된 문제가 발생하지 않죠. 따라서 RBF 신경망은 역전파 알고리즘을 이용할 때 훨씬 빠르게 학습합니다.

단점도 있습니다. 외삽에 약해 인풋 벡터가 큰 경우 다루기 힘들다는 것이죠.

그림 4. RBF 신경망 구조

그림 4. RBF 신경망 구조

1.2.5. 동적 학습 벡터 양자화, 즉 DLVQ 네트워크는 자기조직화 지도(SOM)과 굉장히 유사합니다. 다만 SOM과 달리 DLVO는 지도 학습을 할 수 있으며 프로토타입 사이의 이웃 관계가 없습니다. 벡터 양자화가 클러스터링보다 넓게 사용되죠.

1.2.6. 홉필드 네트워크는 대칭을 이루는 인접 행렬을 갖는 완전 연결 신경망입니다. 이런 네트워크는 작업 중 균형 상태를 이루게 됩니다. 이런 균형 상태는 네트워크 에너지로도 알려진 기능의 극값이 됩니다. 해당 네트워크는 내용 주소화 기억장치로 사용될 수 있습니다.

많은 신경망들이 특정 개수의 tact로 구성된 응답을 받을 때까지 일하는 반면 홉필드 네트워크는 균형 상태를 이루는 것을 목표로 합니다. 직전의 네트워크 상태가 그 다음 네트워크 상태와 완전히 동일한 상태가 되는 것이죠. 이 경우 초기 상태가 인풋 패턴이며 균형 상태가 달성되면 출력 이미지가 나옵니다. 홉필드 네트워크 훈련 시에는 인풋과 아웃풋 레이어에 동시에 훈련 패턴이 입력되어야 합니다.

그림 5. 3개 뉴런을 갖는 홉필드 네트워크 구조

그림 5. 3개 뉴런을 갖는 홉필드 네트워크 구조

장점이 보이지만 실제 홉필드 네트워크는 이상적이라고 할 수 없습니다. 메모리가 신경망 내 뉴런 개수 N의 15% 정도로 제한되기 때문이죠. 주소화 기억장치의 경우 N 비트를 이용해 최대 2N까지의 다른 이미지를 저장할 수 있습니다.

또한 홉필드 네트워크는 이미지의 위치 변화를 인식하지 못합니다. 그렇기 때문에 홉필드 네트워크는 일반적으로 신경망을 공부할 때 유용한 이론적 모델로만 인식되죠..

이 밖에도 많은 네트워크가 있지만 우리와는 상관이 없으므로 언급하지 않겠습니다.


1.3. 학습 방법

새로운 것을 배우는 능력은 인간의 뇌의 가장 큰 특징이죠. 인공 신경망의 경우 학습은 네트워크 구조(뉴런 간 연결 구조)와 시냅스(영향을 주는 상관 계수 시그널)를 이용해 주어진 문제에 대한 효과적인 솔루션을 찾는 과정입니다. 일반적으로 신경망 학습은 데이터 샘플을 이용합니다. 학습 과정은 일정한 알고리즘을 따르며, 알고리즘이 반복되면서 입력 시그널에 대한 네트워크의 반응이 개선됩니다.

학습법은 크게 세 가지로 나뉩니다. 지도학습, 비지도학습, 그리고 두 가지를 합친 방법이 있죠. 지도학습의 경우 모든 인풋 예시에 대한 올바른 정답이 알려져 있으며 가중치를 이용해 오류를 최소화하고자 합니다. 비지도학습은 데이터 내부 구조 및 특성을 설명해 샘플을 범주화합니다. 두 가지를 합친 학습의 경우 위의 두 가지를 모두 수행하죠.

1.3.1. 신경망 학습 규칙

오류 수정, 볼츠만 법칙, 헵의 이론, 경쟁 학습의 네 가지 규칙이 있습니다.

1.3.1.1. 오류 수정

모든 인풋 데이터는 특정한 아웃풋 값(목표 값)을 원합니다. 이는 실제 값과는 다를 수 있죠. 오류 수정은 목표 값과 예측 값의 차이를 이용해 가중치를 수정하고 오류를 감소시킵니다. 결과에 오류가 발생하는 경우에만 학습을 시작하죠. 해당 규칙은 다양한 버전으로 존재합니다.

1.3.1.2. 볼츠만 법칙

볼츠만 법칙은 열역학 법칙과 유사한 스토캐스틱 학습 법칙입니다. 그 결과 원하는 확률 분포를 이용해 뉴런의 가중 계수를 수정하게 되죠. 볼츠만 법칙 학습은 오류가 두 개의 모드에서 상관 관계 불일치를 의미하는 경우 고립된 케이스로 간주될 수 있습니다.

1.3.1.3. 헵의 이론

헵의 이론은 신경망 학습 알고리즘 가운데 가장 잘 알려진 이론입니다. 해당 이론에서 시냅스 양쪽에 위치한 뉴런이 동시에 그리고 규칙적으로 활성화되는 경우 그 연결이 강화됩니다. 주목해야 할 점은 가중치가 시냅스와 연결된 뉴런의 활동에 따라서만 변한다는 것이죠. 해당 규칙은 다양한 버전으로 나타납니다.

1.3.1.4. 경쟁 학습

헵의 이론과 달리 경쟁 학습에서는 아웃풋 뉴런들이 서로 경쟁하게 됩니다. 가장 큰 가중치 값을 갖는 아웃풋 뉴런이 '승리'하게 되며 승자만 남게 되죠. 나머지 아웃풋 뉴런의 아웃풋은 비활성화됩니다. 학습 시 '승자'의 가중치만 수정됩니다.

여러가지 문제에 대한 다양한 학습 알고리즘이 존재하는데요. 가장 효율적인 현대 알고리즘 가운데 하나인 역전파가 여기에 포함됩니다. 역전파 과정은 경사하강법을 이용해 가중치를 업데이트합니다.

출력 레이어에서 평가된 신경망의 실제 응답과 올바른 응답 간의 차이가 역전파되죠(그림 5). 따라서 모든 뉴런이 네트워크 내 오류에 대한 자신의 가중치를 계산할 수 있게 됩니다. 가장 간단한 학습 방법은 가장 가파른 하강법으로, 시냅스 가중치가 누적 오류에 대한 기여도에 따라 변화합니다.

그림 6. 역전파 학습 시 네트워크 내 데이터와 에러 전파 패턴

그림 6. 역전파 학습 시 네트워크 내 데이터와 에러 전파 패턴

알고리즘이 극값의 영향을 받을 수 있기 때문에 최적의 학습 결과를 내는 방법은 아닙니다. 극값을 이용해 솔루션을 만드는 방법도 있기는 합니다. 해당 방법을 반복 적용한 후에도 신경망이 동일한 결정을 내리는 경우 해당 솔루션이 최적이라고 판단할 수 있습니다.

1.4. 단점

  • 소위 '차원의 저주'가 신경망의 단점입니다. 입력 차원과 레이어 개수가 증가함에 따라 네트워크의 복잡성과 학습 소요 시간도 증가하며 따라서 항상 최적의 결과가 나오지는 않죠.
  • 전통적인 신경망이 문제 해결 방법을 설명하지 못한다는 점이 또 다른 문제인데요. 의학같은 분야에서는 해당 설명이 결과보다 중요하기 때문입니다. 내부 표상이 너무 복잡해 분석 자체가 불가능한 경우가 있습니다.

2. 딥러닝

머신러닝 이론과 그 적용은 지금 이 순간에도 진화하고 있습니다. 딥러닝의 성공 덕분이죠. 80~90년대에 이용했던 전통적인 2세대 네트워크와는 달리, 새로운 학습 패러다임 덕분에 기존의 문제를 해결할 수 있게 되었습니다.

딥러닝 알고리즘으로 학습된 네트워크는 그 정확성이 뛰어날 뿐 아니라 몇몇의 경우 인풋 정보의 의미를 어느 정도 이해하기도 합니다. 이미지 인식과 텍스트 정보 분석이 그 예죠.

오늘날 가장 발전된 형태의 컴퓨터 비전 및 음성 인식은 심층 신경망을 기반으로 합니다. IT 산업 거물인 애플이나 구글, 페이스북 등도 심층 신경망 개발자를 고용하고 있죠.


2.1. 배경

제프리 E. 힌튼(Geoffrey E. Hinton) 교수가 이끄는 토론토 대학 대학원생 팀이 머크(Merck)가 후원하는 콘테스트에서 최우수상을 수상했습니다. 15개 분자의 화학 구조를 설명하는 제한된 데이터 세트를 사용하여 G. Hinton의 그룹은 그 분자 중 어느 것이 효과적인 약이 될 가능성이 가장 높은지를 정의하는 특수 프로그램 시스템을 만들고 적용했습니다.

해당 시스템의 특징은 개발자들이 딥 러닝 기반의 인공 신경망을 사용했다는 것입니다. 결과적으로 시스템은 매우 제한된 소스 데이터 세트를 기반으로 계산 및 연구를 수행하는 반면 신경망을 훈련하려면 일반적으로 시스템에 상당한 양의 정보를 입력해야 합니다.

Hinton의 팀 성취는 특히 팀이 마지막 순간에 대회에 참가하기로 결정했기 때문에 인상적이었습니다. 게다가 해당 시스템은 분자가 표적에 어떻게 결합하는지에 대한 구체적인 지식 없이 개발되었습니다. 딥러닝의 성공적인 구현은 2012년 인공 지능 개발의 또 하나의 성과가 되었습니다.

그리고 2012년 여름, Google의 Jeff Dean과 Andrew Y. Ng는 정확도가 15.8%인 새로운 이미지 인식 시스템을 발표했습니다. 여기서 1만 6000개의 노드로 구성된 클러스터 시스템을 훈련하기 위해 2만 개의 사물에 대한 1400만 장의 사진 라이브러리가 포함된 ImageNet 네트워크를 사용했습니다. 지난 해 스위스의 과학자들이 개발한 프로그램이 교통 표지판 이미지 인식에서 인간을 앞선 바 있습니다. 우승 프로그램은 50000개 이미지 세트 중 99.46%를 정확하게 식별했습니다. 32명의 인간 참가자 그룹의 최고 점수는 99.22%였으며 인간 평균 점수는 98.84%였습니다. 2012년 10월, 마이크로소프트 과학 프로그램의 코디네이터인 Richard F. Rashid는 중국 톈진에서 열린 회의에서 자신의 목소리 시뮬레이션을 이용해 영어에서 북경어로의 동시 통역 기술을 발표했습니다.

인공지능 분야의 돌파구를 보여주는 이 기술들은 모두 어느 정도 딥러닝 방식에 기반을 두고 있습니다. 딥러닝 이론에 대한 주요 공헌은 현대 컴퓨터의 기초가 되는 Boole 대수학의 창시자인 영국 과학자 George Boole의 증손자인 Hinton 교수가 만든 것입니다.

해당 이론은 여러 프레젠테이션 수준에서 입력 정보 분석을 위한 특수 알고리즘으로 일반적인 머신 러닝 방법을 보완합니다. 새로운 접근 방식의 특징은 딥 러닝이 해당 대상의 매개변수에 영향을 줄 수 있는 모든 요인을 설명하기에 충분한 정보 제공 수준을 찾을 때까지 해당 주제를 연구한다는 것입니다.

따라서 이러한 접근 방식에 기반한 신경망은 학습에 필요한 입력 정보가 적고 훈련된 네트워크는 일반 신경망보다 높은 수준의 정확도로 정보를 분석할 수 있게 되죠. 힌튼 교수와 그 동료들에 따르면 이들이 개발한 기술은 특히 구조화가 잘 되어 있는 다중 차원 정보 배열에 적용하기 좋다고 합니다.

인공 지능 기술(AI), 특히 딥러닝은 Nuance Communications 기술을 기반으로 하는 애플의 어시스턴트 시리와 구글 스트리트뷰 주소 인식 등 다양한 시스템에서 널리 사용됩니다. 그럼에도 불구하고 과학자들은 인공 지능을 만든 역사가 낙관적인 약속과 실망으로 가득 차 있기 때문에 이 분야의 성공을 매우 신중하게 평가하고 있습니다.

1960년대 과학자들은 완전한 기능을 갖춘 인공 지능을 만드는 데 10년 밖에 걸리지 않을 것이라고 믿었습니다. 1980년대에는 '레디메이드 인공 지능'을 판매하는 회사가 대거 나타났죠. 그후 최근까지 해당 산업은 '빙하기'에 머물렀습니다. 오늘날 클라우드 서비스에서 사용할 수 있는 광범위한 계산 기능은 새로운 이론 및 알고리즘 기반을 사용하여 새로운 수준의 강력한 신경망 구현을 제공합니다.

심지어 합성곱 신경망이나 AA, 볼츠만 머신과 같은 3세대 신경망까지도 이름을 제외하고는 생물학적 뉴런과 공통점이 없습니다.

새로운 학습 패러다임은 두 단계로 구성된 학습 방법을 제시합니다. 첫 번째 단계에서 입력 데이터의 내부 구조에 대한 정보는 계층별 비지도 학습을 통해 AA를 사용하여 형식화되지 않은 대규모 데이터 배열에서 추출됩니다. 그런 다음 이 정보를 다층 신경망에서 사용하여 형식화된 데이터를 사용하여 알려진 방법으로 지도 학습을 진행합니다. 동시에, 비형식화된 데이터의 크기는 최대한 커야 합니다. 형식화된 데이터는 그 규모가 작아도 상관없습니다. 우리의 경우 사실 별로 중요한 문제는 아니죠.


2.2. 오토인코더 오토인코더와 제한된 볼츠만 머신 차이점 및 특징

2.2.1. 오토인코더

최초의 자동연산기(AA)는 후쿠시마의 네오코그니트론이었습니다.

그림 7에서 그 구조를 확인할 수 있죠.

그림 7. 후쿠시마의 네오코그니트론

그림 7. 후쿠시마의 네오코그니트론

자동연산기의 목적은 인풋만큼 정확한 이미지를 아웃풋으로 수신하는 것입니다.

AA는 두 종류가 있는데요. 생성하는 것이 있고 합성하는 것이 있습니다. 제한된 볼츠만 머신은 첫 번째 유형에 속하고 오토인코더는 두 번째 유형에 속하죠.

오토인코더는 하나의 오픈 레이어를 갖는 신경망입니다. 비지도 학습 알고리즘과 역전파를 사용하여 목표값을 입력 벡터와 동일하게 설정합니다. 즉, y=x가 되는 것이죠.

그림 8은 오토인코더의 예시입니다.

그림 8. 오토인코더 구조

그림 8. 오토인코더 구조

오토인코더는 h(x)=x 함수를 작성하고자 합니다. 다시 말해, 신경망 피드백이 입력 매개변수의 값과 거의 동일하도록 보장하는 함수의 근사치를 찾으려고 하는 것이죠. 문제에 대한 솔루션이 의미를 가지려면 열린 계층의 뉴런 수가 입력 데이터의 차원보다 작아야 합니다.

인풋 신호가 네트워크 아웃풋으로 전달될 때 데이터를 압축해 주기 때문이죠. 예를 들어, 입력 벡터가 크기가 10x10 픽셀인 이미지의 밝기 수준 집합인 경우 은닉층의 뉴런 수가 50개이면 네트워크는 이미지 압축을 학습해야 합니다. h(x)=x은 은닉층의 50개 뉴런의 활동 레벨을 기반으로 아웃풋 레이어가 초기 이미지에서 100 픽셀을 복구함을 의미합니다. 위 같은 압축은 구조 내에 숨겨진 연결 고리나, 특성의 상관 관계가 있는 경우 발생합니다.. 이러한 방식으로 자동 인코더 작업은 입력 데이터가 감소한다는 점에서 주성분 분석 방법(PCA)을 떠올리게 하죠.

놀랍게도 Bengio et al이 실험의 작성자입니다. 실험에 따르면 확률적 경사 하강법으로 훈련할 때 숨겨진 뉴런의 수가 입력의 수보다 많은 비선형 자동 코딩 네트워크는 해당 프레젠테이션을 수행한 네트워크의 적합성 오류에 비추어 유용한 프레젠테이션을 가졌습니다.

나중에 희소성이라는 개념이 등장하면서 희소성 자동인코더가 널리 사용되기 시작했죠.

희소성 자동인코더는 은닉 뉴런의 개수가 입력 차원보다 훨씬 크지만 잘 활성화되지 않는 오토인코더입니다. 희소 활성화는 은닉층에 있는 비활성 뉴런의 수가 활성 뉴런의 수보다 훨씬 많을 때입니다. 희소성을 비공식적으로 설명하면 기능 값이 1에 가까우면 뉴런이 활성으로 간주될 수 있습니다. 시그모이드 함수가 사용 중일 때 비활성 뉴런의 경우 해당 값은 0에 가까워야 합니다(쌍곡선 탄젠트 함수의 경우 -1).

노이즈 제거 자동 인코더(Vincent et al., 2008)라는 변형 오토인코더도 있습니다. 일반 오토인코더와 학습 방법에 차이가 있죠. 이 네트워크를 훈련할 때 '손상된' 데이터가 입력됩니다. 일부 값은 0으로 대체되기도 합니다. 동시에 아웃풋 데이터는 '올바른' 데이터와 비교됩니다. 따라서 오토인코더가 손상된 데이터를 복구할 수 있죠.


2.2.2. 제한된 볼츠만 머신(RBM)

제한된 볼츠만 머신의 역사에 대해서는 자세히 알아보지 않을 겁니다. 피드백이 있는 순환 신경망을 기반으로 한다는 것만 알면 됩니다. 훈련이 아주 어려운 신경망이죠. 이러한 학습의 어려움 때문에 더 많은 제한된 순환 신경망 모델이 나타났습니다. 보다 간단한 학습 알고리즘을 적용할 수 있도로 말입니다. 홉필드 네트워크가 그 중 하나였습니다. 존 홉필드(John Hopfield)는 신경망 역학을 열역학과 비교하여 네트워크 에너지 개념을 도입했습니다.

그 다음에 일반 볼츠만 머신이 개발되었죠. 그들은 확률적 성질을 가지고 있다는 점에서 홉필드 네트워크와 다르며 뉴런은 보이는 상태와 숨겨진 상태를 설명하는 두 그룹으로 나뉩니다. RBM은 한 레이어에 위치한 뉴런 간 연결이 없다는 점에서 일반 볼츠만 머신과 다릅니다.

그림 9는 RBM 구조를 나타냅니다.

그림 9. RBM 구조

그림 9. RBM 구조

이 모델의 특징은 한 그룹의 뉴런의 현재 상태에서 다른 그룹의 뉴런 상태가 서로 독립적이라는 것입니다. 이제 이 같은 특성에 대한 이론을 좀 살펴볼까요?

해석 및 목적

RBM은 은닉 마르코프 모형과 비슷한 방식으로 해석됩니다. 우리가 관찰할 수 있는 많은 상태(보이는 뉴런)와 직접 볼 수 없는 많은 숨겨진 상태(숨겨진 뉴런)가 있는데요. 우리는 우리가 관찰할 수 있는 상태에 의존하는 숨겨진 상태에 대한 확률 기반 결론에 도달할 수 있습니다. 그러한 모델이 훈련된 후에 우리는 숨겨진 상태가 베이즈의 정리를 따르고 있다는 것을 알고 보이는 상태에 대한 결론을 도출할 기회를 얻습니다. 이를 통해 모델 훈련에 사용되는 확률 분포에서 데이터를 생성할 수 있습니다.

이렇게 하면 모델 훈련의 목적을 공식화할 수 있습니다. 초기 상태에서 복원된 벡터가 원본에 가장 가깝도록 모델 매개변수를 조정해야 합니다. 복원된 벡터는 숨겨진 상태로부터 확률적 추론에 의해 수신된 벡터이며, 이는 차례로 가시적 상태, 즉 원래 벡터로부터 확률적 추론에 의해 수신됩니다.

CD-k 학습 알고리즘

2002년에 힌튼 교수가 개발한 이 알고리즘은 굉장히 간단합니다. 주요 아이디어는 수학적 기대값이 정의된 값으로 대체된다는 것이죠. Gibbs 샘플링이라는 아이디어가 도입되었습니다.

CD-k의 특성은 다음과 같습니다.

  1. 보이는 뉴런의 상태는 입력 패턴과 동일하게 설정됩니다.
  2. 은닉 레이어 상태의 확률이 그려집니다.
  3. 은닉 레이어의 각 뉴런에는 현재 상태와 동일한 확률로 상태 '1'이 부여됩니다.
  4. 보이는 레이어 상태의 확률은 은닉 레이어를 기반으로 합니다.
  5. 현재 반복 횟수가 k보다 적은 경우 2단계로 돌아가 반복합니다.
  6. 은닉 레이어 상태의 확률이 그려집니다.

힌튼 교수의 설명은 다음과 같습니다.

그림 10. CD-k 학습 알고리즘

그림 10. CD-k 학습 알고리즘

다시 말해, 샘플링을 오래할수록 기울기가 더 정확해집니다. 힌튼 교수에 따르면 CD-1의 결과, 즉 샘플링을 한 번만 반복한 결과만도 충분하다고 합니다.


2.3. 적층 오토어소시에이터 네트워크 적층 오토인코더 SAE, 적층 제한된 볼츠만 머신(적층 RBM)

입력 데이터 세트에서 높은 수준의 추상화를 추출하기 위해 자동 연결자가 네트워크로 결합됩니다.

그림 11은 적층 오토인코더 구조와 신경망을 나타내며, 이는 적층 오토인코더에 의해 초기화된 가중치가 있는 심층 신경망을 함께 나타냅니다.

그림 11. DN SAE 구조

그림 11. DN SAE 구조

그림 12는 적층 RBM(SRBM) 패턴과 신경망이 나타나 있으며, 이 둘은 SRBM으로 가중화 된 심층 신경망을 구성하게 됩니다.

이러한 심층 네트워크 구조의 예는 정보가 아래에서 위로 추출된다는 사실을 강조합니다.

그림 12. DN SRBM 구조

그림 12. DN SRBM 구조

2.4. 심층 신경망(DN) 학습 단계 특징

심층 신경망 학습은 두 단계로 이루어집니다. 첫 번째 단계에서 자동 연결 네트워크(DN 유형에 따라 SAE 또는 SRBM)는 형식화되지 않은 데이터 배열에 대한 비지도학습을 받습니다. 그 후, 일반 MLP의 은닉층 뉴런은 학습 후 받은 은닉층 가중치로 초기화되죠. 그림 11과 12는 학습 및 전송 과정 패턴을 나타냅니다. 첫 번째 АЕ/RBM 학습 후, 은닉층의 뉴런 가중치는 두 번째 네트워크의 입력값이 됩니다. 이런 식으로 구조에 대한 일반화 정보가 데이터에서 추출됩니다.

두 번째 단계는 잘 알려진 방법을 사용하여 형식화된 데이터 세트에 대한 MLP(지도학습)을 미세하게 바꾸는 겁니다. 실습은 이러한 초기화가 MLP의 은닉층의 뉴런 가중치를 전역 최소값으로 설정하고 다음 미세 수정에 매우 짧은 시간이 걸린다는 것을 증명했습니다.

또한 D. Hinton은 레이어 수가 3개 이상인 심층 네트워크의 경우 두 단계로 조정을 실행할 것을 제안했습니다. 첫 번째 단계에서는 두 개의 상위 레이어만 훈련되고 두 번째 단계에서는 나머지 네트워크가 학습되어야 합니다.

SRBM은 SAE보다 비지도학습의 결과가 덜 안정적이라는 점을 언급해야 합니다.

주의 두 용어를 혼동하지 마세요. SRBM은 심층 신뢰망인 DBN과 혼동됩니다. RBM이 DBN에서 발전된 모델이긴 하지만 이 둘은 완전히 다른 구조를 갖습니다. DBM은 다층 신경망이며, 은닉 레이어 뉴런의 가중치가 이진법으로 초기화됩니다.


3. 실제 적용

심층 신경망은 R에서 실행됩니다.

3.1. R 언어

역사 R은 1996년 뉴질랜드 과학자 Ross Ihaka와 Aokland University의 Robert Gentleman이 개발한 통계 계산 및 차트 작성을 위한 프로그래밍 언어이자 환경입니다.

R은 무료 소프트웨어인 GNU 프로젝트이며 그 철학은 다음과 같은 원칙에 따릅니다.

  • 목적에 상관 없이 프로그램을 실행할 자유(freedom 0)
  • 프로그램 사용 방법과 필요에 따라 프로그램을 실행할 자유(freedom 1)
  • 타인을 돕기 위해 프로그램을 배포할 자유(freedom 2)
  • 프로그램을 개선하고 사회가 그 혜택을 이용할 수 있도록 할 자유

역사적 관점에서 R은 S 구현의 대안입니다. 후자는 1976년 Bell Labs 회사의 John Chambers와 그의 동료에 의해 개발되었습니다. 오늘날 R은 John Chambers를 포함한 R Development Core Team에 의해 여전히 개선되고 있습니다.

실험을 반복하려면 R과 Rstudio를 설치해야 합니다. 온라인에서 쉽게 다운로드 및 설치 방법을 찾을 수 있습니다. 질문이 있는 경우 본문 하단의 코멘트란에 남겨 주세요.

장점

  • 현재 R은 통계 연산 표준 언어로 인정받고 있습니다.
  • 전 세계 과학자들이 R을 개발에 이용하죠.
  • 고급 데이터 마이닝 분야에 적용 가능한 다양한 패키지를 제공합니다. 아이디어의 공개와 R 패키지의 구현 사이의 시간은 일반적으로 2주를 넘지 않습니다.
  • 게다가, 완전히 무료입니다. 유명한 개발자가 한 말이 있죠. "프로그램은 섹스와 같다. 공짜면 더 좋다"라고요.


3.2. 변형 구현 및 문제 해결

두 가지 구현 방법이 있습니다.

첫 번째 방법은 존 힌튼 교수가 Matlab을 위해 개발한 프로그램을 이용합니다. 'R.matlab' 파일이 필요한데요. 해당 패키지는 MAT 파일을 읽고 쓰는 writeMat()과 readMat() 메소드를 포함합니다. Matlab v6 이상에서 로컬로 실행되거나 클라이언트-서버 링크의 원격 호스트에서 통신(코드 구현, 개체 송수신 등)을 가능하게 합니다. 자세한 정보는 패키지 설명을 참조하세요. 편하게 Matlab을 사용할 수 있는 분들께 추천하는 방법입니다. 저는 사용해 보지 않았지만 Matlab과 MQL을 연결할 방법이 있습니다.

두 번째 방법은 관련 R 패키지를 활용하는 겁니다. 자세히 알아보죠.

제가 알기로는 이번 주제에 관해 세 가지 패키지가 존재합니다.

  1. 'deepnet'은 DN SAE와 DN SRBM 모델을 구현하는 간단한 패키지입니다. 지도학습과 비지도학습의 인풋 데이터 세트 길이가 동일하죠. 두 단계에 거쳐 시스템을 개선할 기회는 주어지지 않습니다. 초기 모델 탐색 및 테스트에 사용되죠.

  2. 'darh'는 DN SRBM을 위한 고급 패키지입니다. DN SAE 모델도 포함하고 있는데 제 경우에는 실행할 수 없었습니다. 숙련된 사용자들을 위한 패키지이며 아주 복잡한 수준의 모델 형성 및 개선이 가능합니다. 힌튼 교수의 Matlab 프로그램을 기반으로 만들어졌습니다.

  3. 'H2O'는 대형 데이터 세트(>1 Гб) 심층 신경망 학습을 위한 확장 패키지입니다. csv 파일로 이루어져 있습니다.

아래의 실험에는 'deepnet' 패키지를 이용할 겁니다.


3.3. 실험 인풋 데이터 및 목표 데이터 준비

데이터 마이닝에는 일정한 순서가 있습니다.

  1. 입력 데이터 선택(학습, 분석, 사전 준비, 평가) 데이터를 훈련, 검증 및 테스트 세트(샘플)로 분할
  2. 훈련 데이터 세트 모델 훈련 후 검증 데이터 세트 모델 선택
  3. 테스트 샘플에 대한 모델/모델 품질 평가 및 특정 측정에 의해 세트 중 최적의 모델 매개변수 또는 최상의 모델 정의
  4. 모델 실행

첫 번째 단계가 가장 시간이 오래 걸리지만 결과에 있어 매우 중요합니다. 해당 단계는 형식화된 바 없으며 일반적으로 말하면 거의 예술에 가깝습니다. 연구자의 경험에 좌우되죠. 하!지!만! 가장 중요한 것을 선택하기 위해 입력 데이터 세트의 정량적 평가를 얻는 것은 매우 중요합니다. 이 경우 특정 모델에 대한 최상의 변수를 자동으로 선택하는 것이 훨씬 좋습니다. R은 모든 단계에서 문제를 해결하기 위한 광범위한 기능을 제공합니다.

소스 데이터는 매우 중요할 뿐만 아니라 고려해야 할 측면도 많습니다. 이에 대해서는 별도의 아티클을 작성할 필요가 있습니다. 이 글의 목적은 복잡한 것에 대해 아주 간단한 단어로 이야기하는 것이므로 중요한 사항에 대해 논의할 것이지만 자세히는 다루지 않을 것입니다.


3.3.1. 소스 데이터

분류를 위해 독립(입력) 변수 세트와 목표 변수가 필요합니다. 딥 네트워크의 주요 장점은 대규모 입력 샘플에서 빠르게 학습할 수 있다는 것이므로 17개의 예측 변수(11개 인디케이터)로 구성된 입력 데이터 세트를 생성해 보겠습니다. 지그재그 인디케이터가 타겟 변수의 역할을 합니다. R 환경에서 Open, High, Low, Close 시세 4000바가 있는 벡터를 다운로드합니다. 후술할 인디케이터 작성 방법에서 다운로드 방법이 설명되어 있습니다. 지금은 그렇게 중요하지 않아요. 모든 연산은 R로 실행됩니다.

바 크기와 평균 가격의 4가지 벡터로 이루어진 행렬을 만듭니다. 위의 행렬을 함수로 변환합니다.

pr.OHLC <- function (o, h, l, c) 
{
  #Unite quote vectors into a matrix having previously expanded them
  #Indexing of time series of vectors in R starts with 1. 
  #Direction of indexing is from old to new ones.   
  price <- cbind(Open = rev(o), High = rev(h), Low = rev(l), Close = rev(c))
  Med <- (price[, 2] + price[, 3])/2
  CO <- price[, 4] - price[, 1]
  #add Med and CO to the matrix
  price <- cbind(price, Med, CO)
}
-->

결과를 확인합니다. 2014년 8월 10일 12:00의 상태를 확인해 보세요.

> head(price)
        Open    High     Low   Close      Med     CO
[1,] 1.33848 1.33851 1.33824 1.33844 1.338375 -4e-05
[2,] 1.33843 1.33868 1.33842 1.33851 1.338550  8e-05
[3,] 1.33849 1.33862 1.33846 1.33859 1.338540  1e-04
[4,] 1.33858 1.33861 1.33856 1.33859 1.338585  1e-05
[5,] 1.33862 1.33868 1.33855 1.33855 1.338615 -7e-05
[6,] 1.33853 1.33856 1.33846 1.33855 1.338510  2e-05
-->


3.3.2. 입력 데이터(예측 변수)

인디케이터를 나열합니다. 해당 인디케이터들은 입력 크기의 최대 차이를 얻기 위해 선호도 없이 무작위로 선택되었습니다.

모든 인디케이터의 연산은 'TTR' 패키지를 이용해 시행됩니다.


3.3.2.1. 디랙셔널 무브먼트 인덱스-ADX(HLC, n)-4 out(Dip, Din,DX, ADX)

처음 200개의 바가 어떻게 나타나는지 보겠습니다.

> library(TTR)
> adx<-ADX(price, n = 16)
> plot.ts(head(adx, 200))
-->

그림 13. 디랙셔널 무브먼트 인덱스-ADX(HLC, n)

그림 13. 디랙셔널 무브먼트 인덱스-ADX(HLC, n)

> summary(adx)
      DIp             DIn                DX                 ADX    
 Min.   :15.90   Min.   :  5.468   Min.   : 0.00831      Min.   : 5.482   
 1st Qu.:41.21   1st Qu.: 33.599   1st Qu.: 8.05849      1st Qu.:14.046 
 Median :47.36   Median : 43.216   Median :16.95423      Median :18.099
 Mean   :47.14   Mean   : 46.170   Mean   :19.73032      Mean   :19.609 
 3rd Qu.:53.31   3rd Qu.: 55.315   3rd Qu.:27.97471      3rd Qu.:23.961     
 Max.   :80.12   Max.   :199.251   Max.   :81.08751      Max.   :52.413
 NA's   :16      NA's   :16        NA's   :16            NA's   :31 
-->

행렬 초반에 31개의 미정의 값이 나타납니다(NA). 따로 설명하지 않고 전체 인디케이터에 대해 동일한 연산을 반복해 봅니다.


3.3.2.2. 아룬(HL, n) 인디케이터-1 out(오실레이터)

'오실레이터' 변수만을 이용해 처음 200개 바를 연산해 봅니다.

> ar<-aroon(price[ , c('High', 'Low')], n = 16)[ ,'oscillator']
> plot(head(ar, 200), t = "l")
> abline(h = 0)
-->

그림 14. 아룬(HL, n) 인디케이터

그림 14. 아룬(HL, n) 인디케이터

> summary(ar)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
-100.00  -56.25  -18.75   -7.67   43.75  100.00      16 
-->


3.3.2.3. 상품 채널 지수 인디케이이터-CCI(HLC, n)-1 out

> cci<-CCI(price[ ,2:4], n = 16)
> plot.ts(head(cci, 200))
> abline(h = 0)
-->

그림 15. 상품 채널 지수 인디케이터-CCI(HLC, n)

그림 15. 상품 채널 지수 인디케이터-CCI(HLC, n)

> summary(cci)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
-469.10  -90.95  -18.74  -14.03   66.91  388.20      15 
-->


3.3.2.4. Chaikin Volatility 인디케이터-chaikinVolatility (HLC, n)-1 out

> chv<-chaikinVolatility(price[ , 2:4], n = 16)
> summary(chv)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.     NA's 
-0.67570 -0.29940  0.02085  0.12890  0.41580  5.15700       31 
> plot(head(chv, 200), t = "l")
> abline(h = 0)
-->

그림 16. chaikinVolatility(HLC, n) 인디케이터

그림 16. chaikinVolatility(HLC, n) 인디케이터

3.3.2.5. 샹드 모멘텀 오실레이터 인디케이터-CMO(Med, n)-1 out

> cmo<-CMO(price[ ,'Med'], n = 16)
> plot(head(cmo, 200), t = "l")
> abline(h = 0)
-->

그림 17. 샹드 모멘텀 오실레이터 인디케이터-CMO(Med, n)

그림 17. 샹드 모멘텀 오실레이터 인디케이터-CMO(Med, n)

> summary(cmo)
   Min.    1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
-97.670 -32.650  -5.400  -6.075  19.530  93.080      16 
-->


3.3.2.6. MACD 오실레이터 인디케이터-MACD(Med, nFast, nSlow, nSig)-1 out(MACD)

> macd<-MACD(price[ ,'Med'], 12, 26, 9)[ ,'macd']
> plot(head(macd, 200), t = "l")
> abline(h = 0)
-->

그림 18. MACD 오실레이터 인디케이터

그림 18. MACD 오실레이터 인디케이터

> summary(macd)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max.      NA's
-0.346900 -0.025150 -0.005716 -0.011370  0.013790  0.088880      25       
-->


3.3.2.7. OsMA(Med,nFast, nSlow, nSig) 인디케이터–1 out

> osma<-macd - MACD(price[ ,'Med'],12, 26, 9)[ ,'signal']
> plot(head(osma, 200), t = "l")
> abline(h = 0)
-->

그림 19. OsMA(Med,nFast, nSlow, nSig) 인디케이터

그림 19. OsMA(Med,nFast, nSlow, nSig) 인디케이터

> summary(osma)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.     NA's 
-0.10560 -0.00526  0.00034  0.00007  0.00646  0.05922       33 
-->


3.3.2.8. 상대 강도 지수 인디케이터-1 out

> rsi<-RSI(price[ ,'Med'], n = 16)
> plot(head(rsi, 200), t = "l")
> abline(h = 50)
-->

그림 20. 상대 강도 지수 인디케이터-RSI(Med,n)

그림 20. 상대 강도 지수 인디케이터-RSI(Med,n)

> summary(rsi)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
   5.32   37.33   47.15   46.53   55.71   84.82      16 
-->


3.3.2.9. 스토캐스틱 오실레이터 인디케이터-stoch(HLC, nFastK=14, nFastD=3, nSlowD=3)-3 out

> stoh<-stoch(price[ ,2:4], 14, 3, 3)
> plot.ts(head(stoh, 200))
-->

그림 21. 스토캐스틱 오실레이터 인디케이터-stoch(HLC, nFastK=14, nFastD=3, nSlowD=3)

그림 21. 스토캐스틱 오실레이터 인디케이터-stoch(HLC, nFastK=14, nFastD=3, nSlowD=3)

> summary(stoh)
     fastK            fastD             slowD        
 Min.   :0.0000   Min.   :0.01782   Min.   :0.02388  
 1st Qu.:0.2250   1st Qu.:0.23948   1st Qu.:0.24873  
 Median :0.4450   Median :0.44205   Median :0.44113  
 Mean   :0.4622   Mean   :0.46212   Mean   :0.46207  
 3rd Qu.:0.6842   3rd Qu.:0.67088   3rd Qu.:0.66709  
 Max.   :1.0000   Max.   :0.99074   Max.   :0.97626  
 NA's   :13       NA's   :15        NA's   :17     
-->


3.3.2.10. 스토캐스틱 모멘텀 인덱스 인디케이터-SMI(HLC, n = 13, nFast = 2, nSlow = 25, nSig = 9)-2 out

> smi<-SMI(price[ ,2:4],n = 13, nFast = 2, nSlow = 25, nSig = 9)
> plot.ts(head(smi, 200))
-->

그림 22. 스토캐스틱 모멘텀 인덱스 인디케이터-SMI(HLC, n = 13, nFast = 2, nSlow = 25, nSig = 9)

그림 22. 스토캐스틱 모멘텀 인덱스 인디케이터-SMI(HLC, n = 13, nFast = 2, nSlow = 25, nSig = 9)

> summary(smi)
      SMI              signal       
 Min.   :-82.185   Min.   :-78.470  
 1st Qu.:-33.392   1st Qu.:-31.307  
 Median : -9.320   Median : -8.839  
 Mean   : -8.942   Mean   : -8.985  
 3rd Qu.: 15.664   3rd Qu.: 14.069  
 Max.   : 71.878   Max.   : 63.865  
 NA's   :25        NA's   :33  
-->


3.3.2.11. 변동성 인디케이터(Yang and Zhang)-volatility(OHLC, n, calc="yang.zhang", N=96)-1 out

> vol<-volatility(price[ ,1:4],n = 16,calc = "yang.zhang", N =96)
> plot.ts(head(vol, 200))
-->

그림 23. 변동성 인디케이터(Yang and Zhang)-volatility(OHLC, n, calc="yang.zhang", N=96)

그림 23. 변동성 인디케이터(Yang and Zhang)-volatility(OHLC, n, calc="yang.zhang", N=96)

> summary(vol)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.      NA's
0.000599 0.001858 0.002638 0.003127 0.004015 0.012840      16      
-->

따라서 OHLC 샘플 4000바 깊이의 М15 기간에 EURUSD에 대한 11개 인디케이터에서 17개 변수가 있습니다.

위의 자료로 행렬을 만들어 최적화에 필요한 하나의 변수 р를 갖는 함수를 작성합니다.

아래의 공식을 이용해 인입력 매개 변수 행렬을 계산합니다.

In<-function(p = 16){
  adx<-ADX(price, n = p);
  ar<-aroon(price[ ,c('High', 'Low')], n=p)[ ,'oscillator'];
  cci<-CCI(price[ ,2:4], n = p);
  chv<-chaikinVolatility(price[ ,2:4], n = p);
  cmo<-CMO(price[ ,'Med'], n = p);
  macd<-MACD(price[ ,'Med'], 12, 26, 9)[ ,'macd'];
  osma<-macd - MACD(price[ ,'Med'],12, 26, 9)[ ,'signal'];
  rsi<-RSI(price[ ,'Med'], n = p);
  stoh<-stoch(price[ ,2:4],14, 3, 3);
  smi<-SMI(price[ ,2:4],n = p, nFast = 2, nSlow = 25, nSig = 9);
  vol<-volatility(price[ ,1:4],n = p,calc="yang.zhang", N=96);
  In<-cbind(adx, ar, cci, chv, cmo, macd, osma, rsi, stoh, smi, vol);
  return(In)
}
-->
> X<-In()
> tail(X)
             DIp      DIn       DX      ADX   ar      cci       chv
[3995,] 46.49620 36.32411 12.28212 18.17544 25.0 168.0407 0.1835102
[3996,] 52.99009 31.61164 25.26952 18.61882 37.5 227.7030 0.3189822
[3997,] 58.11948 28.16241 34.72000 19.62515 37.5 145.2337 0.3448520
[3998,] 56.00323 30.48687 29.50206 20.24245 37.5 118.5831 0.3068059
[3999,] 55.96197 28.78737 32.06467 20.98134 37.5 116.5376 0.3517668
[4000,] 54.97777 26.85440 34.36713 21.81795 62.5 160.0767 0.6169701
             cmo         macd       osma      rsi     fastK
[3995,] 29.71342 -0.020870825 0.01666593 52.91932 0.8832685
[3996,] 41.89526 -0.009654368 0.02230591 61.49793 0.8833819
[3997,] 30.98237 -0.002051532 0.02392699 58.94513 0.7259475
[3998,] 33.84813  0.003454534 0.02354645 58.00549 0.7930029
[3999,] 38.84892  0.009590136 0.02374564 60.63806 0.8367347
[4000,] 54.71698  0.019303110 0.02676689 66.64815 0.9354120
            fastD     slowD        SMI    signal         vol
[3995,] 0.7773581 0.7735064 -35.095406 -47.27712 0.003643196
[3996,] 0.7691688 0.7761507 -26.482951 -43.11828 0.003858942
[3997,] 0.8308660 0.7924643 -19.699762 -38.43458 0.003920541
[3998,] 0.8007775 0.8002707 -13.141932 -33.37605 0.003916109
[3999,] 0.7852284 0.8056239  -6.569699 -28.01478 0.003999789
[4000,] 0.8550499 0.8136852   2.197810 -21.97226 0.004293766
-->

원시 입력 데이터가 준비됩니다.


3.3.3. 출력 데이터(목표)

이제 목표 데이터인 출력 데이터를 만듭시다. 위에서 언급했듯 지그재그 인디케이터를 사용할 겁니다.

채널 너비가 37 포인트인 지그재그 인디케이터를 사용합니다. 지그재그 인디케이터는 평균 가격을 이용합니다. HL 가격을 이용해 인디케이터를 연산할 수 있지만 평균 가격을 이용하는 경우 인디케이터가 보다 안정적입니다. 시그널을 추출한 후(0-매수, 1-매도), 인풋 행렬로 변환합니다.

함수를 작성합니다.

Out<-function(ch=0.0037){
  # ZigZag has values on each bar and not only in the points 
  zz<-ZigZag(price[ ,'Med'], change = ch, percent = F, retrace = F, lastExtreme = T);
  n<-1:length(zz);
  # On the last bars substitute the undefined values for the last known ones
  for(i in n) { if(is.na(zz[i])) zz[i] = zz[i-1];}
  #Define the speed of ZigZag changes and move one bar forward
  dz<-c(diff(zz), NA);
  #If the speed >0 - signal = 0(Buy), if <0, signal = 1 (Sell) otherwise NA
  sig<-ifelse(dz>0, 0, if else(dz<0, 1, NA));
  return(sig);
}
-->

시그널을 계산합니다.

> Y<-Out()
> table(Y)
Y
   0    1 
1567 2423 
-->

클래스 비율이 균형을 이루지 않습니다. 한 클래스의 예 개수가 다른 클래스보다 많습니다. 어느 분류 모델도 위와 같은 세트를 반기지는 않죠.

데이터를 학습 샘플과 테스트 샘플로 분리하면서 위의 문제를 바로잡겠습니다.


3.3.4. 데이터 삭제

정의되지 않은 데이터에서 데이터 세트를 지웁니다. 이 경우 정리는 더 넓은 작업 범위를 포함합니다. 여기에는 '거의 0인 변수'와 상관관계가 높은 변수 및 여기서 논의하지 않을 다른 작업을 지우는 작업이 포함됩니다.

함수를 작성해 데이터를 삭제합니다.

Clearing<-function(x, y){
  dt<-cbind(x,y);
  n<-ncol(dt)
  dt<-na.omit(dt)
  return(dt);  
}
> dt<-Clearing(X,Y); nrow(dt)
[1] 3957
-->

행렬이 43 바만큼 짧아졌네요.


3.3.5. 학습 및 테스트 샘플 형성

소스 데이터를 훈련 및 테스트 샘플로 나누는 방법에는 여러 가지가 있습니다. 우리는 소스 데이터의 규칙적인 무작위 분할을 기차로 사용하고 8/10의 비율로 하나를 테스트할 것입니다. 샘플을 계층화하는 것이 중요합니다. 즉, 훈련 샘플과 테스트 샘플의 클래스 인스턴스 비율이 소스 데이터 세트의 클래스 비율과 일치해야 합니다. 소스 데이터 세트에서 클래스 불균형을 수정하는 것도 도움이 될 것입니다. 더 큰 클래스 또는 더 작은 클래스로 레벨링합니다. 예가 더 많아질 수록 더 큰 클래스인 '1'로 레벨링할 겁니다. 'caret' 패키지를 이용할 거고요.

두 클래스의 인스턴스 수가 동일하고 더 큰 클래스와 동일한 새로운 균형 세트를 구성해 보겠습니다.


3.3.6. 클래스 균형

아래는 더 큰 쪽으로 클래스 수를 평준화하고(다이버전스가 15%보다 큰 경우) 균형 행렬을 반환하는 함수입니다.

Balancing<-function(DT){
  #Calculate a table with a number of classes
  cl<-table(DT[ ,ncol(DT)]);
  #If the divergence is less than 15%, return the initial matrix
  if(max(cl)/min(cl)<= 1.15) return(DT)
  #Otherwise level by the greater side
  DT<-if(max(cl)/min(cl)> 1.15){ 
         upSample(x = DT[ ,-ncol(DT)],y = as.factor(DT[ , ncol(DT)]), yname = "Y")
        }
  #Convert у (factor) into a number
  DT$Y<-as.numeric(DT$Y)
  #Recode у from 1,2 into 0,1
  DT$Y<-ifelse(DT$Y == 1, 0, 1)
  #Convert dataframe to matrix
  DT<-as.matrix(DT)
  return(DT);
}
-->

설명할게요. 첫 번째 문자열에서 각 클래스의 인스턴스 수를 계산합니다(벡터, 클래스 수와 동일한 차원).

큰 벡터와 작은 벡터의 비율을 찾고 설정된 임계값보다 작으면 종료합니다. 비율이 더 크면 х와 y를 별도로 입력하여 함수를 계산합니다. y는 기존에 이미 요인으로 변환되었어야 합니다.

upSample() 함수 형식 매개 변수 생성 시 반드시 지켜져야 하는 사항이죠. 목표 변수가 요인으로 필요하지 않기 때문에 값이 0과 1인 숫자 변수로 다시 변환합니다. 숫자 변수 (0,1)를 인수로 변환하면 문자 변수 '0'과 '1'이 수신된다는 점에 주의하세요. 반대로 숫자 변수로 변환하는 경우 1과 2(!!!)가 수신됩니다. 이를 0 과 1로 대체하면 됩니다. 우리 데이터 세트는 '데이터 프레임'에서 '행렬' 클래스로 변환됩니다. 계산합니다.

dt.b<-Balancing(dt)
x<-dt.b[ ,-ncol(dt.b)]
y<-dt.b[ , ncol(dt.b)]
-->

이제 소스 데이터 세트 dt(인풋 및 아웃풋)와 균형을 이루는 세트 dt.b가 생겼습니다.

학습 및 테스트 샘플로 나눕니다.

holdout() 함수를 이용해 'rminer' 패키지에서 인덱스를 추출합니다.

> library('rminer')
> t<-holdout(y, ratio = 8/10, mode = "random")
-->

t 객체는 훈련(t$tr) 및 테스트(t$ts) 데이터 세트의 인덱스를 포함하는 목록입니다. 수신된 세트는 계층화됩니다.


3.3.7. 전처리

입력 데이터 소스에는 값 범위가 다른 변수가 포함되어 있습니다. 기본적으로 심층 네트워크는 가중치를 초기화하는 독특한 방법을 사용하는 일반 네트워크입니다.

신경망은 (-1, 1) 또는 (0, 1) 범위의 입력 변수를 받을 수 있습니다. 해당 입력 변수가 [-1, 1]의 범위를 갖도록 정규화합니다.

'caret' 패키지의 preProcess() 함수를 이용하면 됩니다. 전처리의 매개변수는 훈련 데이터 세트에서 계산되고 테스트 데이터 세트와 새로 입력된 데이터의 추가 전처리를 위해 저장됩니다.

> spSign<-preProcess(x[t$tr, ], method = "spatialSign")
> x.tr<-predict(spSign, x[t$tr, ])
> x.ts<-predict(spSign, x[t$ts, ])
-->

이제 우리는 심층 신경망을 구축, 학습 및 테스트하기 위한 모든 것을 갖추었습니다.


3.4. 모델 구축, 학습 및 테스트

DN SAE 모델을 구축하고 학습시켜 보겠습니다. 다음은 모델에 사용된 공식과 변수에 대해 알아보죠.

sae.dnn.train(x, y, hidden = c(10), activationfun = "sigm", learningrate = 0.8, momentum = 0.5, learningrate_scale = 1, output = "sigm", sae_output = "linear",
  numepochs = 3, batchsize = 100, hidden_dropout = 0, visible_dropout = 0)
-->

설명하겠습니다.

  • х는 인풋 데이터 행렬입니다.
  • y는 목표 변수의 벡터 또는 행렬입니다.
  • hidden은 각 은닉 레이어의 뉴런 개수를 갖는 벡터입니다. 기본값 с(10)
  • activationfun은 은닉 뉴런을 활성화하는 함수입니다. 'sigm','linear', 'tanh'의 세 종류가 있습니다. 기본값 'sigm'
  • learningrate는 경사하강 학습 레벨입니다. 기본값 =0.8
  • momentum은 경사하강 모멘텀입니다. 기본값= 0.5
  • learningrate_scale 값을 이용해 반복이 끝날 때마다 학습 레벨을 배가 시킵니다. 기본값=1.0
  • numepochs는 학습 반복 횟수입니다. 기본값=3
  • batchsize는 학습되는 작은 규모 데이터의 크기입니다. 기본값=100
  • output은 아웃풋 뉴런 활성화 함수이며 'sigm', 'linear', 'softmax'의 세 가지 값을 갖습니다. 기본값 'sigm'
  • sae_output은 SAE 아웃풋 뉴런 활성화 함수이며 'sigm', 'inear', 'softmax'의 세 가지 값을 갖습니다. 기본값 "linear"
  • hidden_dropout은 은닉 레이어의 삭제 가능한 부분입니다. 기본값=0
  • visible_dropout은 보이는 레이어의 삭제 가능한 부분입니다. 기본값=0

다음 차원(17, 100, 100, 100, 1)으로 모델을 만들고 훈련하고 학습 시간을 기록하고 예측을 관찰합니다.

> system.time(SAE<-sae.dnn.train(x= x.tr, y= y[t$tr], hidden=c(100,100,100), activationfun = "tanh", learningrate = 0.6, momentum = 0.5, learningrate_scale = 1.0, output = "sigm", sae_output = "linear", numepochs = 10, batchsize = 100, hidden_dropout = 0, visible_dropout = 0))
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
   user  system elapsed 
  12.92    0.00   13.09 
-->

두 단계로 구성되죠. 우선 오토인코더가 레이어별 학습을 진행하며 그 다음은 신경망이 학습합니다.

3개의 레이어에서 적은 수의 훈련 시간과 엄청난 수의 은닉 뉴런이 의도적으로 설정되었습니다. 13초 밖에 안걸렸네요!

예측 데이터 테스트 세트를 이용해 예측 값을 평가해 보죠.

> pr.sae<-nn.predict(SAE, x.ts);
> summary(pr.sae)
       V1        
 Min.   :0.2649  
 1st Qu.:0.2649  
 Median :0.5881  
 Mean   :0.5116  
 3rd Qu.:0.7410  
 Max.   :0.7410 
-->

0, 1로 변환 후 계산합니다.

> pr<-ifelse(pr.sae>mean(pr.sae), 1, 0)
> confusionMatrix(y[t$ts], pr)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 316 128
         1 134 378
                                         
               Accuracy : 0.7259         
                 95% CI : (0.6965, 0.754)
    No Information Rate : 0.5293         
    P-Value [Acc > NIR] : <2e-16         
                                         
                  Kappa : 0.4496         
 Mcnemar's Test P-Value : 0.7574         
                                         
            Sensitivity : 0.7022         
            Specificity : 0.7470         
         Pos Pred Value : 0.7117         
         Neg Pred Value : 0.7383         
             Prevalence : 0.4707         
         Detection Rate : 0.3305         
   Detection Prevalence : 0.4644         
      Balanced Accuracy : 0.7246         
                                         
       'Positive' Class : 0 
-->

크게 눈에 띄는 상관 계수가 아니네요. 우리는 계수가 아니라 이러한 신호를 사용하여 만들 수익에 더 관심이 있습니다. 최근 500개 바(약 1주일)에 대해 확인합니다. 학습된 네트워크의 마지막 500개 바에 대한 신호를 받게 될 겁니다.

인풋 데이터의 마지막 500개 바를 정규화하여 학습된 신경망에서 예측 값을 받은 후 시그널로 변환합니다. -1은 매도, 1은 매수를 나타냅니다.

> new.x<-predict(spSign,tail(dt[ ,-ncol(dt)], 500))
> pr.sae1<-nn.predict(SAE, new.x)
> pr.sig<-ifelse(pr.sae1>mean(pr.sae1), -1, 1)
> table(pr.sig)
pr.sig
 -1   1 
235 265 
> new.y<-ifelse(tail(dt[  , ncol(dt)], 500) == 0, 1, -1)
> table(new.y)
new.y
 -1   1 
201 299 
> cm1<-confusionMatrix(new.y, pr.sig)
> cm1
Confusion Matrix and Statistics

          Reference
Prediction  -1   1
        -1 160  41
        1   75 224
                                          
               Accuracy : 0.768           
                 95% CI : (0.7285, 0.8043)
    No Information Rate : 0.53            
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.5305          
 Mcnemar's Test P-Value : 0.002184        
                                          
            Sensitivity : 0.6809          
            Specificity : 0.8453          
         Pos Pred Value : 0.7960          
         Neg Pred Value : 0.7492          
             Prevalence : 0.4700          
         Detection Rate : 0.3200          
   Detection Prevalence : 0.4020          
      Balanced Accuracy : 0.7631          
                                          
       'Positive' Class : -1   
-->

정확도 계수는 나쁘지 않지만 계수가 아니라 수익에 더 관심이 있죠.

마지막 500개 바에 대한 수익을 테스트한 후 밸런스 곡선을 획득합니다.

> bal<-cumsum(tail(price[ , 'CO'], 500) * pr.sig)
> plot(bal, t = "l")
> abline(h = 0)
-->

그림 24. 신경망 시그널을 이용한 마지막 500개 바 잔액

그림 24. 신경망 시그널을 이용한 마지막 500개 바 잔액

해당 잔액은 스프레드, 슬리피지 및 실제 시장의 기타 상황을 고려하지 않고 계산되었습니다.

이제 ZZ를 이용할 경우 얻을 것으로 예측되는 잔액과 비교합니다. 붉은 선이 신경망 신호에 의한 잔액을 나타냅니다.

> bal.zz<-cumsum(tail(price[ , 'CO'], 500) * new.y)
> plot(bal.zz,  t = "l")
> lines(bal,  col = 2)
-->

그림 25. 신경망 시그널 및 지그재그 시그널을 이용한 마지막 500개 바 잔액

그림 25. 신경망 시그널 및 지그재그 시그널을 이용한 마지막 500개 바 잔액

개선의 여지가 있군요.

Estimation()Testing() 함수를 작성해 헬퍼 함수를 돕습니다. 첫 번째 함수는 상관 계수 Accuracy/Err를 생성하고 두 번째 함수는 잔액 Bal/BalZZ를 생성합니다.

일부 네트워크 매개변수를 변경하는 즉시 결과를 얻을 수 있으며 어떤 매개변수가 네트워크 품질에 영향을 미치는지 확인할 수 있습니다.

피트니스 함수를 작성하면 거래 프로세스에 지장을 주지 않고 진화적(유전적) 알고리즘을 사용하여 최적의 네트워크 매개변수를 찾을 수 있습니다. 이번에는 피트니스 함수를 다루지 않을 겁니다.

다음은 Err/Accuracy 상관 계수를 구하는 Estimation() 함수입니다.

Estimation<-function(X, Y, r = 8/10, m = "random", norm = "spatialSign",
                     h = c(10), act = "tanh", LR = 0.8, Mom = 0.5, 
                     out = "sigm", sae = "linear", Ep = 10, Bs = 50, 
                     CM=F){
  #Indices of the training and test data set
  t<-holdout(Y, ratio = r, mode = m)
  #Parameters of preprocessing
  prepr<-preProcess(X[t$tr,  ], method = norm)
  #Divide into train and test data sets with preprocessing 
  x.tr<-predict(prepr, X[t$tr,  ])
  x.ts<-predict(prepr, X[t$ts,  ])
  y.tr<- Y[t$tr]; y.ts<- Y[t$ts]
  #Train the model
  SAE<-sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                     activationfun = act,
                     learningrate = LR, momentum = Mom, 
                      output = out, sae_output = sae, 
                     numepochs = Ep, batchsize = Bs)
  #Obtain a forecast on the test data set
  pr.sae<-nn.predict(SAE, x.ts)
  #Recode it into signals 1,0
  pr<-ifelse(pr.sae>mean(pr.sae), 1, 0)
  #Calculate the Accuracy coefficient or classification error
  if(CM) err<-unname(confusionMatrix(y.ts, pr)$overall[1])
  if(!CM) err<-nn.test(SAE, x.ts, y.ts, mean(pr.sae))
  return(err)
}
-->

형식 변수

  • X–인풋 원시 예측 변수 행렬
  • Y–목표 변수 벡터
  • r–학습:테스트 비율
  • m–샘플 형성 모드(임의 또는 시퀀스)
  • norm–인풋 변수 정규화 모드([ -1, 1]="spatialSign", [0, 1]="range")
  • h–은닉 레이어 뉴런 개수 벡터
  • act–은닉 뉴런 활성화 함수
  • LR–학습 레벨
  • Мом-모멘텀
  • out-아웃풋 레이어 활성화 함수
  • sae-오토인코더 활성화 함수
  • Ep-트레이닝 반복 횟수
  • Bs-작은 샘플 크기
  • СM-불리언 변수, 참인 경우 Accuracy 출력 거짓인 경우 Err 출력

균형을 이루지 않는 데이터 세트 dt에 대한 분류 오류를 계산해 보겠습니다. 각 30개의 뉴런으로 구성된 3개의 은닉 레이어를 갖는 네트워크를 이용합니다.

> Err<-Estimation(X = dt[ ,-ncol(dt)], Y = dt[ ,ncol(dt)], h=c(30, 30, 30), LR= 0.7)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> Err
[1] 0.1376263
-->

Testing() 함수를 이용해 지그재그 인디케이터 또는 예측 시그널로 잔액을 계산합니다.

Testing<-function(dt1, dt2, r=8/10, m = "random", norm = "spatialSign",
                     h = c(10), act = "tanh", LR = 0.8, Mom = 0.5, 
                     out = "sigm", sae = "linear", Ep = 10, Bs=50, 
                     pr = T, bar = 500){
  X<-dt1[  ,-ncol(dt1)]
  Y<-dt1[  ,ncol(dt1)]
  t<-holdout(Y,  ratio = r,  mode = m)
  prepr<-preProcess(X[t$tr,  ], method = norm)
  x.tr<-predict(prepr, X[t$tr,  ])
  y.tr<- Y[t$tr]; 
  SAE<-sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                     activationfun = act,
                     learningrate = LR, momentum = Mom, 
                     output = out, sae_output = sae, 
                     numepochs = Ep, batchsize = Bs)
  X<-dt2[ ,-ncol(dt2)]
  Y<-dt2[ ,ncol(dt2)]
  x.ts<-predict(prepr, tail(X, bar))
  y.ts<-tail(Y, bar)
  pr.sae<-nn.predict(SAE, x.ts)
  sig<-ifelse(pr.sae>mean(pr.sae), -1, 1)
  sig.zz<-ifelse(y.ts == 0, 1,-1 )
  bal<-cumsum(tail(price[  ,'CO'], bar) * sig)
  bal.zz<-cumsum(tail(price[  ,'CO'], bar) * sig.zz)
  if(pr) return(bal)
  if(!pr) return(bal.zz)
}
-->

형식 변수

  • dt1-네트워크 학습에 이용되는 인풋 및 목적 변수 행렬
  • dt2-네트워크 학습에 이용되는 인풋 및 목적 변수 행렬
  • pr-불리언 변수, 참일 경우 예측 시그널로 잔액 출력, 거짓인 경우 지그재그 이용
  • bar-잔액 계산에 사용되는 마지막 바의 개수

위와 같은 변수를 갖는 신경망을 이용한 데이터 세트 dt.b 학습 시 데이터 세트 dt의 마지막 500개 바에 대한 잔액을 계산합니다.

> Bal<-Testing(dt.b, dt, h=c(30, 30, 30), LR= 0.7)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> plot(Bal, t = "l")
> abline(h = 0)
-->

그림 26. 신경망 시그널 h(30,30,30)을 이용한 마지막 500개 바 잔액

그림 26. 신경망 시그널 h(30,30,30)을 이용한 마지막 500개 바 잔액

직전 잔액과 비교하면 꽤 개선되었음을 알 수 있죠. 이것보다 더 흥미로운 점도 있습니다.

마지막 500개 바에 대한 가격 플롯을 살펴보면 그 중 일부가 네트워크와 굉장히 잘 맞는다는 걸 알 수 있습니다(150~350 바).

> plot(tail(price[  ,'Close'], 500), t = "l")
> abline(v = c(150,350), col=2)
-->

그림 27. 지난 500개 바 종가 플롯

그림 27. 지난 500개 바 종가 플롯

주의: 예측 아웃풋 해석 시 다른 버전도 사용 가능합니다.

예측 값이 0.6보다 크거나 0.4보다 작을 경우, 불안정한 세그먼트가 되는 0.4~0.6이 잘려나갑니다. 캘리브레이션을 통해 보다 정확한 클래스 경계를 획득할 수 있습니다. 후술할 겁니다.

Testing() 함수를 약간 수정해서 추가 변수 dec를 적용해 보겠습니다. 이렇게 하면 해석할 방법('평균' 또는 '60/40')을 선택할 수 있고 예측 값이 잔액에 미칠 영향도 알 수 있죠.

Testing.1<-function(dt1, dt2, r = 8/10, m = "random", norm = "spatialSign",
                     h = c(10), act = "tanh", LR = 0.8, Mom = 0.5, 
                     out = "sigm", sae = "linear", Ep = 10, Bs = 50, 
                     pr = T, bar = 500, dec=1){
  X<-dt1[ ,-ncol(dt1)]
  Y<-dt1[ ,ncol(dt1)]
  t<-holdout(Y, ratio = r, mode = m)
  prepr<-preProcess(X[t$tr, ], method = norm)
  x.tr<-predict(prepr, X[t$tr, ])
  y.tr<- Y[t$tr]; 
  SAE<-sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                     activationfun = act,
                     learningrate = LR, momentum = Mom, 
                     output = out, sae_output = sae, 
                     numepochs = Ep, batchsize = Bs)
  X<-dt2[ ,-ncol(dt2)]
  Y<-dt2[ ,ncol(dt2)]
  x.ts<-predict(prepr, tail(X, bar))
  y.ts<-tail(Y, bar)
  pr.sae<-nn.predict(SAE, x.ts)
  #Variant +/- mean
  if(dec == 1) sig<-ifelse(pr.sae>mean(pr.sae), -1, 1)
  #Variant 60/40
  if(dec == 2) sig<-ifelse(pr.sae>0.6, -1, ifelse(pr.sae<0.4, 1, 0))
  sig.zz<-ifelse(y.ts == 0, 1,-1 )
  bal<-cumsum(tail(price[  ,'CO'], bar) * sig)
  bal.zz<-cumsum(tail(price[  ,'CO'], bar) * sig.zz)
  if(pr) return(bal)
  if(!pr) return(bal.zz)
}
-->

첫 번째와 두 번째 방법을 이용해 잔고를 계산하고 평가합니다.

결과가 반복되는 경우 해당 위치에 유사난수 생성기를 설정합니다.

> set.seed<-1245
> Bal1<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 1)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> set.seed<-1245
> Bal2<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 2)
begin to train sae ......
training layer 1 autoencoder ...
training layer 2 autoencoder ...
training layer 3 autoencoder ...
sae has been trained.
begin to train deep nn ......
deep nn has been trained.
> plot(Bal2, t = "l")
> lines(Bal1, col = 2)
-->

그림 28. 두 가지 예측 해석 방법이 적용된 신경망 시그널을 이용한 마지막 500개 바 잔액

그림 28. 두 가지 예측 해석 방법이 적용된 신경망 시그널을 이용한 마지막 500개 바 잔액

60/40 방법을 이용한 결과가 훨씬 나아 보이죠. 이것도 개선의 여지가 있습니다.

마지막으로 확인할 것이 있는데요. 이론적으로 여러 개의 신경망을 합치면 보다 낫고 안정적인 결과가 나옵니다. 여러 개의 신경망으로 구성된 앙상블을 테스트해 볼겁니다. 각각 독립된 샘플로 학습시켜도 되지만 동일한 샘플로 학습된 신경망을 이용할 겁니다. 앙상블의 예측 결과는 전체 네트워크 예측의 평균이 됩니다. 보다 복잡한 방법으로 평균을 낼 수도 있습니다.

Testing() 함수에 매개 변수를 하나 더 추가하겠습니다. ans=1인데요. 앙상블 내 네트워크 개수를 나타냅니다.


3.4.1. 병렬 컴퓨팅

여러 독립 모델에 의한 계산을 쉽게 병렬화할 수 있으므로 R 언어가 제공하는 기회를 사용하고 이러한 컴퓨터의 운영 체제에 관계없이 로컬 네트워크의 여러 프로세서 코어 또는 컴퓨터로 구성된 클러스터를 만들 것입니다.

'foreach''doParallel' 패키지를 이용합니다. 다음은 코어 프로세서의 전체 클러스터를 실행할 아주 간단한 함수입니다.

library(doParallel)
library(foreach)
puskCluster<-function(){
  cores<-detectCores()
  cl<-makePSOCKcluster(cores)
  registerDoParallel(cl)
  clusterSetRNGStream(cl)
 return(cl)
}
-->

몇 가지 설명하겠습니다. 처음 두 개의 문자열은 필요한 라이브러리를 실행합니다. 기존에 컴퓨터에 설치된 라이브러리여야 하죠. 그런 다음 프로세서에 얼마나 많은 코어가 있는지 정의하고, 클러스터를 만들고, 병렬 계산을 위한 패키지를 등록하고, 모든 계산 스트림에 독립적인 의사 난수 생성기를 설치하고 클러스터 핸들을 반환합니다. 이것은 별도의 주제이지만 모든 모델의 계산을 위한 의사 난수 생성기의 품질은 매우 중요합니다.

클러스터가 시작되고 필요한 모든 계산이 수행된 후에는 클러스터를 중지해야 합니다.

cl<-puskCluster()
stopCluster(cl) 
-->

병렬 컴퓨팅은 'foreach' 패키지에 포함된 다음의 공식을 이용해 실행됩니다.

SAE<-foreach(times(ans), .packages = "deepnet") %dopar%  
                sae.dnn.train(x = x.tr , y = y.tr , hidden = h, 
                        activationfun = act,
                        learningrate = LR, momentum = Mom, 
                        output = out, sae_output = sae, 
                        numepochs = Ep, batchsize = Bs)
-->

times(ans)는 구하고자 하는 네트워크의 개수이며 .packages는 패키지로 연산된 함수를 보냅니다.

결과는 목록 형식을 가지며 우리가 필요로 하는 훈련된 네트워크의 수를 포함합니다.

그런 다음 모든 네트워크에서 예측을 요구하고 평균을 계산합니다.

pr.sae<-(foreach(i = 1:ans, .combine = "+") %do%  nn.predict(SAE[[i]], x.ts))/ans
-->

학습된 네트워크 인덱스 벡터가 나옵니다. combine="+"는 전체 신경망 네트워크에서 반환된 예측값의 형태를 나타냅니다. 이 경우 합계를 반환하고 이러한 계산을 병렬 방식이 아닌 순차적으로 수행해야 했습니다(%do% 연산자). 얻어진 합을 신경망의 수로 나눈 값이 최종 결과가 됩니다. 간단하고 좋네요.

위와 동일한 매개 변수를 사용하며 60/40 방법을 이용하는 3~4개의 신경망 네트워크로 구성된 앙상블에서 얻은 잔액을 계산합니다. 단일 신경망의 결과와 비교합니다. 병렬 계산의 효율성을 평가하려면 에포크 수를 300으로 늘리고 예측값을 얻는 프로세스의 시간을 정하십시오.

1. 단일 신경망

> system.time(Bal21<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 2, Ep=300))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000057
####loss on step 20000 is : 0.000043
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000081
####loss on step 20000 is : 0.000086
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000072
####loss on step 20000 is : 0.000066
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.069451
####loss on step 20000 is : 0.079629
deep nn has been trained.
   user  system elapsed 
 115.78    0.00  116.96 
> plot(Bal21, t = "l")
> abline(h = 0)
-->

2. 3개 신경망 앙상블

> system.time(Bal41<-Testing.2(dt.b, dt, h = c(30, 30, 30), LR = 0.7, Ep=300, dec = 2, ans=3))
   user  system elapsed 
   0.22    0.06  233.64 
> lines(Bal41, col=4)
-->

3. 4개 신경망 앙상블

> system.time(Bal44<-Testing.2(dt.b, dt, h = c(30, 30, 30), LR = 0.7, Ep=300, dec = 2, ans=4))
   user  system elapsed 
   0.13    0.03  247.86 
> lines(Bal44, col=2)
-->

병렬 연산의 실행 시간은 스트림 수가 코어 수의 배수인 경우에 최적입니다. 저는 2개 코어를 이용했습니다.

그렇다고 해서 잔액이 달라지는 건 아닙니다. 아래 차트에서 파란색 점은 3개 네트워크를, 빨간 점은 4개 네트워크를, 검은 점은 단일 네트워크를 나타냅니다.

그림 29. 3개 신경망 앙상블, 4개 신경망 앙상블, 단일 네트워크 시그널을 이용한 마지막 500개 바 잔액

그림 29. 3개 신경망 앙상블, 4개 신경망 앙상블, 단일 네트워크 시그널을 이용한 마지막 500개 바 잔액

일반적으로 위의 결과는 상당히 많은 매개 변수의 영향을 받습니다. 입력 변수, 출력 변수, 정규화 방법, 은닉 레이어 개수 및 은닉 레이어 내 뉴런 개수, 학습 레벨 등 아주 많죠.

마지막으로 세 가지 예를 더 살펴볼게요. 세 개의 은닉 레이어에 각각 다른 수의 은닉 뉴런이 있는 세 개의 신경망을 이용해 마지막 100개 바 잔액을 계산합니다.

> system.time(Bal0<-Testing.1(dt.b, dt, h = c(30, 30, 30), LR = 0.7, dec = 2, Ep=300, bar=1000))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000054
####loss on step 20000 is : 0.000044
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000078
####loss on step 20000 is : 0.000079
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000090
####loss on step 20000 is : 0.000072
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.072633
####loss on step 20000 is : 0.057917
deep nn has been trained.
   user  system elapsed 
 116.09    0.02  116.26 
> max(Bal0)
[1] 0.04725
> plot(Bal0, t="l")
> tail(Bal0,1)
[1] 0.03514
-->

최대 수익은 472포인트이며, 마지막 바의 경우 351 포인트입니다. 차트에서는 검은색으로 나타나 있습니다.

> system.time(Bal0<-Testing.1(dt.b, dt, h = c(13, 8, 5), LR = 0.7, dec = 2, Ep=300, bar=1000))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.005217
####loss on step 20000 is : 0.004846
training layer 2 autoencoder ...
####loss on step 10000 is : 0.051324
####loss on step 20000 is : 0.046230
training layer 3 autoencoder ...
####loss on step 10000 is : 0.023292
####loss on step 20000 is : 0.026113
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.057788
####loss on step 20000 is : 0.056932
deep nn has been trained.
   user  system elapsed 
  64.04    0.01   64.24 
Warning message:
In sae$encoder[[i - 1]]$W[[1]] %*% t(train_x) + sae$encoder[[i -  :
  longer object length is not a multiple of shorter object length
> lines(Bal0, col="blue")
-->

쓸데 없는 변형이군요.

세 번째 변형

> system.time(Bal0<-Testing.1(dt.b, dt, h = c(50, 50, 50), LR = 0.7, dec = 2, Ep=300, bar=1000))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000018
####loss on step 20000 is : 0.000013
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000062
####loss on step 20000 is : 0.000048
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000053
####loss on step 20000 is : 0.000055
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.096490
####loss on step 20000 is : 0.084860
deep nn has been trained.
   user  system elapsed 
 186.18    0.00  186.39 
> lines(Bal0, col="red")
> max(Bal0)
[1] 0.0543
-->

그림 30. 각각 다른 수의 은닉 뉴런을 갖는 세 개의 은닉 레이어로 이루어진 세 개의 신경망을 이용한 마지막 1000개 바 잔액

그림 30. 각각 다른 수의 은닉 뉴런을 갖는 세 개의 은닉 레이어로 이루어진 세 개의 신경망을 이용한 마지막 1000개 바 잔액

세 번째 변형이 제일 낫네요. 최대 수익 543 포인트를 기록했습니다. 은닉 뉴런의 개수만 바꾸었는데도 크게 개선되었습니다. 최적 매개 변수 검색은 진화 알고리즘을 통해 이루어져야 합니다. 독자 여러분이 한번 알아 보세요. 

제 알고리즘이 해당 패키지에 완전히 구현되지는 않았다는 걸 기억하시고요.


4. 인디케이터 및 엑스퍼트 어드바이저 구현

이제 심층 신경망을 이용해 거래 시그널을 수신하는 인디케이터와 EA를 작성해 볼 겁니다.

두 가지 방법이 있는데요.

  • 첫 번째 방법 Rstudio를 이용해 수동으로 신경망을 학습시킵니다. 허용 가능한 결과가 나오면 네트워크를 적당한 카탈로그에 저장합니다. EA와 인디케이터를 차트에 실행합니다. EA는 학습된 네트워크를 실행할 겁니다. 인디케이터는 각 바에 대한 새로운 인풋 데이터 벡터를 준비하고 EA로 전달합니다. EA는 네트워크 데이터를 표시하며, 시그널을 수신해 시그널에 따릅니다. EA는 주문 시작 및 종료, 추적 등과 같은 일반적인 활동을 수행하고 있습니다. 인디케이터의 목적은 각각의 새로운 바에 대한 새로운 입력 데이터를 준비하고 EA에 전달하는 것이며, 가장 중요한 것은 네트워크에서 예측한 신호를 제시하는 것입니다. 연습을 통해 시각적 제어가 신경망을 평가하는 가장 효율적인 방법임을 알 수 있습니다.
  • 두 번째 방법 EA와 인디케이터를 차트에 실행합니다. 실행 후 인디케이터가 EA로 미리 준비된 대량의 인풋과 아웃풋 데이터 세트를 전송합니다. EA는 최적의 신경망에 대한 학습, 테스트 및 선택을 실행합니다. 그 후에는 첫 번째 방법과 동일하게 진행됩니다.

첫 번째 알고리즘을 이용해 링크 인디케이터-EA를 작성할 겁니다. 최대한 간단한 EA를 만들 거예요.

왜 이렇게 어렵냐고요? 이러한 구현 방식을 이용하면 서로 다른 심볼/시간 프레임에 배치된 여러 지표를 하나의 EA에 연결하고 결과적으로 함께 작업할 수 있습니다. 그래서 EA를 좀 세련되게 만들어야 하죠. 이것도 나중에 얘기할 거예요.

다음은 인디케이터와 EA의 인터랙션 구조입니다.

그림 31. 인디케이터-EA 인터랙션 구조

그림 31. 인디케이터-EA 인터랙션 구조

4.1. 모델 학습 및 저장

원하는 차트에 실행된 인디케이터를 이용해 필요한 소스 데이터를 획득합니다. 인풋 변수 send를 false로 설정합니다.시각적 표현은 서버로 보내지지 않아야 합니다. 해당 심볼 또는 타임프레임 실행 시 인디케이터는 터미널 데이터 파일에 다음의 디렉토리를 생성합니다. /Symbol/TF/Test_Data/

이러한 디렉토리 구성은 모델의 예비 교육에서 실험 결과를 통합하지 않고 이전 데이터를 새 데이터로 덮어쓰지 않을 기회를 제공합니다. 중간 결과는 /Symbol/TF/Test_Data/ 디렉토리에 저장되며 EA가 이용하는 모델은 /Symbol/TF/에 직접 저장해야 합니다. EA의 타임프레임에 새로운 심볼을 적용해도 동일한 결과가 나올 겁니다.

시간 프레임이 M30인 EURUSD의 경우 2014년 10월 14일에 4000개의 바가 나타납니다. dt[] 데이터 프레임이 필요합니다.

잔고 클래스

> dt.b<-Balancing(dt)
> table(dt.b[ ,ncol(dt.b)])
   0    1 
2288 2288
-->

앞서 작성한 Testing.1() 함수를 이용해, 500개와 300개의 에포크를 갖는 심층 신경망을 학습시킨 후 신경망 시그널 예측을 이용해 얻은 마지막 500개 바에 대한 잔액을 평가해 봅니다.

> system.time(bal<-Testing.1(dt.b, dt, h = c(50, 50, 50), LR = 0.7, dec = 2, Ep=500, bar=500))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000017
####loss on step 20000 is : 0.000015
####loss on step 30000 is : 0.000015
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000044
####loss on step 20000 is : 0.000041
####loss on step 30000 is : 0.000039
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000042
####loss on step 20000 is : 0.000042
####loss on step 30000 is : 0.000036
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.089417
####loss on step 20000 is : 0.043276
####loss on step 30000 is : 0.069399
deep nn has been trained.
   user  system elapsed 
 267.59    0.08  269.37 
> plot(bal, t="l")
-->

신경망은 다른 이름으로 저장해 놓고 다른 신경망을 학습시킵니다.

> SAE1<-SAE
> system.time(bal<-Testing.1(dt.b, dt, h = c(50, 50, 50), LR = 0.7, dec = 2, Ep=300, bar=500))
begin to train sae ......
training layer 1 autoencoder ...
####loss on step 10000 is : 0.000020
####loss on step 20000 is : 0.000016
training layer 2 autoencoder ...
####loss on step 10000 is : 0.000050
####loss on step 20000 is : 0.000050
training layer 3 autoencoder ...
####loss on step 10000 is : 0.000051
####loss on step 20000 is : 0.000043
sae has been trained.
begin to train deep nn ......
####loss on step 10000 is : 0.083888
####loss on step 20000 is : 0.083941
deep nn has been trained.
   user  system elapsed 
 155.32    0.02  156.25 
> lines(bal, col=2)
-->

잔액 차트를 한번 볼까요? 가장 최근 결과는 붉은색으로 나타납니다.

그림 32. 500개와 300개의 에포크를 갖는 신경망 시그널을 이용한 마지막 500개 바 잔액

그림 32. 500개와 300개의 에포크를 갖는 신경망 시그널을 이용한 마지막 500개 바 잔액

300개의 에포크를 학습한 신경망이 더 나은 결과를 보이네요.

후자의 학습 시간은 이 기간의 거래 세션 동안의 빠른 재학습에 적합합니다.

실제 차트에 적용하려면 두 개의 객체가 필요합니다. 바로 학습된 모델 'SAE'와 인풋 데이터 정규화 변수 'prepr'입니다. 적당한 디렉토리에 저장합니다. 제 경우 D:/Alpari Limited MT4/MQL4/Files/EURUSD/M30/Test_2014-10-14에 저장했습니다. 해당 모델은 제대로 작동하는군요. Rstudio를 열면 'i_SAE_EURUSD_30.Rdata'로 저장되어 있을 겁니다.

save(SAE, prepr, file="SAE.model")
-->

'SAE.model' 파일에는 모델과 정규화 변수가 저장되어 있습니다. 정규화 변수 없이는 해당 모델을 사용할 수 없으니까요. 해당 모델들은 언제라도 실험하고 저장할 수 있습니다. 모두 /File/Symbol/TF/Test_Data 디렉토리에 저장될 겁니다. EA에서 해당 모델을 사용하려면 'SAE.model' 파일을 'File/Symbol/TF/' 디렉토리에 수동으로 이동합니다. 해당 폴더는 단 하나의 모델만을 포함하며 이 모델이 EA에서 사용됩니다.

'SAE.model' 파일을 실행하면 EA가 필요한 객체들을 실행합니다. 이제 수동으로 하는 작업은 모두 끝났습니다. Indicator-EA를 차트에 적용해 실시간으로 테스트할 수 있습니다.

EA의 효율성을 평가하려면 양적 기준이 필요하죠. Accuracy 상관 계수는 적합하지 않습니다.

지그재그 인디케이터가 수신한 잔액 예측 비율의 평균값과 마지막 바의 전체 바 개수에 대한 잔액 비율이 필요하죠. 다음은 지그재그가 구한 잔액입니다.

sig.zz<-ifelse(tail(dt[  , ncol(dt)], 500) == 0, 1, -1)
bal.zz<-cumsum(tail(price[  , 'CO'], 500) * sig.zz)
Kzz<-mean(bal.zz / bal)
> Kzz
[1] 0.9173312
-->

굉장히 높은 점수이지만 상대적이기도 합니다.

시간에 따른 변화를 보면, 가장 처음의 50~100개 바의 경우 불안정한 인덱스임을 알 수 있습니다. 나중에는 꽤 안정적으로 변하긴 하지만요. 다음은 통계 결과입니다.

> plot(bal/bal.zz, t="l")
> summary(bal/bal.zz)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-15.2500   0.7341   0.7844   0.9173   0.8833  55.0000
-->

그림 33. 예측 잔고 대 지그재그 획득 잔고 비율

그림 33. 예측 잔고 대 지그재그 획득 잔고 비율

두 번째 경우가 더 정확하네요. 전체 N개 바에 대한 하나의 바의 수익을 포인트로 나타내니까요.

예를 들어, 500개 바에 대한 신경망 네트워크를 이용한 예측은 다음과 같습니다.

> Kb<-tail(bal,1)/length(bal)*10^Dig
> Kb
[1] 11.508
-->

지그재그 시그널을 이용한 예측은 다음과 같죠.

> Kbz<-tail(bal.zz,1)/length(bal)*10^Dig
> Kbz
[1] 13.784
-->

하나의 매개 변수에 대한 효율성 하한이 설정되면, 신경망을 재훈련할 수 있는 시간이나 그 변수를 최적화할 수 있는 시간을 알 수 있습니다.

EA의 차트에는 다음의 매개 변수가 나타납니다. OP는 실행된 오퍼레이션, Acc는 정확성, K는 앞서 정의한 Kb이며 Kmax는 Kb와 동일한 변수이지만 마지막 바에서 해당 변수가 해당 변수의 최대값과 얼마나 차이가 나타나는지 보여줍니다.


4.2. 설치 및 주문 실행

하단의 첨부 파일 SAE.zip에는 다음이 포함되어 있습니다.

  1. i_SAE.mq4 인디케이터: /MQL4/Indicators/ folder
  2. e_SAE.mq4 EA: /MQL4/Experts/ folder
  3. mt4Rb7.dll 라이브러리: /MQL4/Libraries/ folder.
  4. mt4Rb7.mqh 헤더 파일: /MQL4/Include/ folder. Bernd Kreuss 씨가 라이브러리와 헤더 파일을 개발 및 제공해 주셨습니다. 해당 파일은 제목에 최근 변경된 인덱스를 포함합니다(b7). 여러 버전이 동일한 이름을 갖는 경우 굉장히 혼란스러워 지죠.
  5. R 스크립트: i_SAE.r(메인 인디케이터 스크립트), i_SAE_fun.r(인디케이터 스크립트 함수), e_SAE.r(EA 스크립트), e_SAE_init.r(EA 초기화 스크립트), SAE_SetDir.r(필요한 디렉토리 생성 및 타당성 검증 스크립트) 스크립트는 통화쌍이나 타임프레임의 영향을 받지 않으므로 별도의 디렉토리에 위치해도 상관없습니다. 저는 C:Rdata/SAE/에 스크립트를 저장했습니다. C:Rdata/ 디렉토리에는 프로젝트와 관계 없이 여러 스크립트가 저장되어 있습니다. 다른 디렉토리에 스크립트를 저장하는 경우, 인디케이터와 EA를 그에 맞춰 수정하는 걸 잊지 마세요.
  6. SAE.model는 'SAE' 모델과 정규화 변수 'prepr'을 포함하는 파일입니다. 해당 모델은 2014년 10월 14일까지의 EURUSD(M30)를 학습했습니다. 학습 프로세스는 위에서 설명했죠.

R 언어가 어느 디렉토리에 있는지도 꼭 기억하세요.

다음의 순서를 따르는 것을 권장합니다. 차트에서 EA를 실행합니다. 기존 서버와 다른 서버, 포트, 또는 다른 통화쌍에 EA를 적용하는 경우 이를 명시해야 합니다. 예를 들어 'port 8886'이라고 말이죠. 기본값은 'port 8888'입니다.

주의 이건 너무나도 비효율적인 방법입니다. 각각의 서버는 약 120~130MB이기 때문이죠. 할 수 없습니다.

EA 초기화를 실행하면 '연산 결과 없음! 통화쌍' 이라는 메세지가 나타날 겁니다. 이 경우 외부 매개 변수send=true를 갖는 인디케이터를 설치하고 인디케이터가 연결된 서버 포트를 명시합니다. 제대로 작동되는 경우 OP, Acc, K 및 Kmax의 실제 데이터가 아웃풋 문자열에 나타나며 거래가 시작될 겁니다.

윈도우 작업 관리자를 이용하면 해당 과정을 보다 효과적으로 통제할 수 있습니다. EA 또는 인디케이터 실행 후 Rterm이 나타나지 않는 경우 R 프로세스가 방해된 것입니다. 아마 스크립트 내 구문 오류나 Rterm에서 추출된 벡터와 MQL 벡터의 길이가 맞지 않아 발생한 오류일 겁니다.

Rstudio에서 스크립트 전체를 처음부터 끝까지 라인 별로 실행해서 디버깅할 수 있습니다.

안타깝게도 제 경우 테스터에서 EA를 실행하는 데에 실패했습니다. 그래서 데모 계좌로 테스트할 수 밖에 없었죠.


4.3. 질적 특성 개선 메소드

  1. 입력 자료로 사용된 인디케이터 세트를 변경합니다.
  2. 입력 데이터 정규화 방식을 변경합니다.
  3. 입력 인디케이터와 '지도' 변수를 최적화합니다.
  4. 두 개의 열을 갖는 행렬에 대한 입력 변수 코드를 변경합니다. 예측 시그널 캘리브레이션을 진행합니다.
  5. 네트워크 변수(은닉 레이어 내 뉴런 개수, 레이어 개수, 학습 레벨, 에포크 개수)를 최적화합니다.

결론

신경망 모델을 만들고, 학습시키고, 테스트해 봤습니다. SAE 내 은닉 레이어의 뉴런 가중치의 초기화도 실행해 봤고요. 네트워크는 굉장히 빨리 재학습을 하며 따라서 거래 프로세스를 방해하지 않고 재학습을 할 수 있습니다.

계량 측면에서 보면 신경망 모델의 결과는 평범하죠. 어차피 이상적인 결과를 내는 건 초기 목표가 아니었으니 괜찮습니다.

모델 및 유효성 계수에 대한 지속적인 평가를 이용하면 해당 모델은 거래 프로세스에 영향을 미치지 않으면서 재학습 및 최적화를 실행할 수 있게 됩니다.

첨부 파일

  1. SAE.zip: 인디케이터, EA 및 관련 파일
  2. R_intro.zip: R 및 Rstudio 관련 자료(러시아어)
  3. DeepLearning.zip: 딥러닝 관련 자료

MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/1103

파일 첨부됨 |
DeepLearning.zip (6542.81 KB)
R-intro.zip (15278.8 KB)
sae.zip (394.31 KB)
MQL5 쿡북: TradeTransaction 이벤트 프로세싱 MQL5 쿡북: TradeTransaction 이벤트 프로세싱
본문은 이벤트 기반 프로그래밍의 관점에서 본 MQL5의 가능성에 대해 다룹니다. 이벤트 기반 프로그래밍의 최대 장점은 프로그램이 거래 오퍼레이션에 대한 단계적인 구현 정보를 수신할 수 있다는 거죠. TradeTransaction 이벤트 핸들러를 이용해 진행 중인 거래 오퍼레이션에 대한 정보를 수신하고 프로세스하는 법에 대해서도 알아볼 겁니다. 제 생각에 이 방법은 터미널 간 거래 카피에 이용할 수 있을 것 같아요.
MetaTrader 시그널 서비스 및 소셜트레이딩 이야기 MetaTrader 시그널 서비스 및 소셜트레이딩 이야기
시그널 서비스 개선을 위해 항상 노력하고 있습니다. 메커니즘을 업그레이드하고, 새로운 기능을 추가하고, 문제를 수정하죠. 2012년의 MetaTrader 시그널 서비스와 현재의 MetaTrader 시그널 서비스는 완전히 다른 서비스나 마찬가지입니다. 현재는 MetaTrader 클라이언트 터미널 버전에 따라 서버가 제공되는 가상 클라우드 호스팅 서비스를 제공하고 있습니다.
MQL5 쿡북: 커스텀 차트 이벤트 핸들링 MQL5 쿡북: 커스텀 차트 이벤트 핸들링
본문은 MQL5 환경에서의 커스텀 차트 이벤트 시스템 디자인 및 개발을 다루고 있습니다. 이벤트 분류 예제 및 이벤트 클래스 코드와 커스텀 이벤트 핸들러 클래스 코드가 포함되어 있습니다.
회귀 분석으로 거시경제 데이터가 통화 가격 변동에 미치는 영향 알아보기 회귀 분석으로 거시경제 데이터가 통화 가격 변동에 미치는 영향 알아보기
본문은 거시 경제 통계에 대한 다중 회귀 분석 적용법을 다룹니다. EURUSD를 이용해 환율 변동에 대한 통계의 영향에 대해서도 평가해 보겠습니다. 해당 평가를 통해 기본적 분석을 자동화하여 초보 투자자들도 이용할 수 있습니다.