반응형
이 글은 Q-Learning에서 보상 구조와 상태 전이가 특정 행동을 예상보다 유리하게 학습시키는 상황을 fake data로 재현한 실험 메모입니다.
주문 호가처럼 보이는 상태 데이터를 만들어 두고, 어떤 path와 reward가 Q-value에 영향을 주어 횡행 행동을 선택하게 되는지 확인하는 흐름으로 읽으면 됩니다.
핵심 정리
Q-Learning은 현재 상태에서 어떤 행동을 고를지 Q-value를 갱신하며 학습합니다. 그런데 보상 설계, 상태 표현, 다음 상태 전이가 의도와 다르면 사람이 보기에는 덜 자연스러운 행동도 높은 가치로 학습될 수 있습니다. 이 글의 fake data는 가격과 수량이 시간에 따라 바뀌는 상황을 만들고, 학습 결과가 어떤 경로를 선호하는지 살펴보는 실험입니다. 핵심은 코드의 길이보다 어떤 상태와 행동 조합이 보상을 가져가도록 설계되었는지 확인하는 것입니다.
- Q-Learning은 상태와 행동 쌍의 가치를 반복적으로 갱신합니다.
- fake data는 실험하고 싶은 시장 상태 변화를 인위적으로 만든 입력입니다.
- 보상 함수가 어떤 행동을 유리하게 평가하는지 먼저 확인해야 합니다.
- 상태 표현이 거칠면 서로 다른 상황이 같은 상태처럼 학습될 수 있습니다.
- 횡행 행동이 선택된다면 그 행동이 높은 Q-value를 얻은 경로를 추적해야 합니다.
- 실험 로그는 최종 path만 보지 말고 중간 Q-value 변화와 함께 읽는 편이 좋습니다.
원문은 fake data 코드가 바로 시작되어 실험 의도가 늦게 드러났습니다. 이번 보강은 Q-Learning에서 비직관적인 행동이 학습되는 이유를 보상, 상태, 전이 관점에서 먼저 잡고 코드 로그를 따라가도록 정리했습니다.
이어서 볼 글
- Q-Learning에서 Learning Rate가 작을 때 수렴하지 않는 문제 - 같은 Q-Learning에서 보상과 갱신이 어긋나는 다른 실패 사례다.
- MDP 조건부확률과 Markov Decision Process 정리 - Q-Learning 상태, 행동, 보상을 이해하기 위한 직접 배경이다.
- OpenAI Gym 사용법: reset, step, reward 기본 흐름 - 강화학습 예제를 실행할 때 쓰는 환경 인터페이스를 설명한다.
횡행이 이득보는 상황 재현
item 1과 2가 다음과 같을때..
# fake data generation ##############################################################
itemlist1 = []
itemlist1.append({\
'fep_time' : '01', 'transaction_volume' : 0, \
'ask_prices': [30000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist1.append({\
'fep_time' : '02', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist1.append({\
'fep_time' : '03', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist1.append({\
'fep_time' : '04', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist1.append({\
'fep_time' : '05', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist1.append({\
'fep_time' : '06', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist1.append({\
'fep_time' : '07', 'transaction_volume' : 0, \
'ask_prices': [10000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [5000, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
for _ in itemlist1:
_['data']={}
for i in range(10):
_['data']['aa'] = 1
exec "_['data']['ask_level_{0}_quote'] = _['ask_prices'][{1}]".format(i+1, i)
exec "_['data']['ask_level_{0}_volume'] = _['ask_volumes'][{1}]".format(i+1, i)
itemlist2 = []
itemlist2.append({\
'fep_time' : '01', 'transaction_volume' : 0, \
'ask_prices': [19000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist2.append({\
'fep_time' : '02', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist2.append({\
'fep_time' : '03', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist2.append({\
'fep_time' : '04', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist2.append({\
'fep_time' : '05', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist2.append({\
'fep_time' : '06', 'transaction_volume' : 0, \
'ask_prices': [20000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [50, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
itemlist2.append({\
'fep_time' : '07', 'transaction_volume' : 0, \
'ask_prices': [30000, 0, 0, 0, 0, 0, 0, 0, 0, 0], \
'ask_volumes' : [5000, 0, 0, 0, 0, 0, 0, 0, 0, 0]})
for _ in itemlist2:
_['data']={}
for i in range(10):
_['data']['aa'] = 1
exec "_['data']['ask_level_{0}_quote'] = _['ask_prices'][{1}]".format(i+1, i)
exec "_['data']['ask_level_{0}_volume'] = _['ask_volumes'][{1}]".format(i+1, i)
####################################################################################
정상적으로는 다음과 같이 앞에것은 t=7에 전량 매수 뒤에것은 t=0에 전량매수가 유리하다.
first
[(((0, 0, 0), (1, 0, 2)), 500000.0), (((0, 0, 0), (1, 10, 2)), 700000.0), (((0, 0, 0), (1, 20, 2)), 900000.0), (((0, 0, 0), (1, 30, 2)), 1100000.0), (((0, 0, 0), (1, 40, 2)), 1300000.0), (((0, 0, 0), (1, 50, 2)), 1500000.0)]
[1][first] t:[0], c: 500,000, p1:(1,000,000), p2:(1,000,000), path: [(0, 0, 1), (1, 0, 2), (2, 0, 2), (3, 0, 2), (4, 0, 2), (5, 0, 2), (6, 0, 2), (7, 50, 2)]
다 스킵하고 마지막에 전량 구매가 유리(50만원)
second
[(((0, 0, 0), (1, 50, 2)), 950000.0), (((0, 0, 0), (1, 40, 2)), 960000.0), (((0, 0, 0), (1, 30, 2)), 970000.0), (((0, 0, 0), (1, 20, 2)), 980000.0), (((0, 0, 0), (1, 10, 2)), 990000.0), (((0, 0, 0), (1, 0, 2)), 1000000.0)]
그런데 learning rate 0.175로 돌려본 결과 다음과 같이 횡행이 비용증가가 느려서 1순위로 뽑히는 결과 발생.
learning rate 0.175
cur state : (0, 0, 1)
[(((0, 0, 0), (1, 0, 2)), 670367.7716267096(50만원에서 100만으로 올라가는중 올라가는 속도가 느려서 부당하게 제일 작은 숫자로 남아있다.)), (((0, 0, 0), (1, 10, 2)), 857260.8799568003), (((0, 0, 0), (1, 50, 2)), 950000.0052473707(150만원에서 95만으로 거의다 떨어졌음.. 원래는 이게 1순위이여야 하는데 지금 3순위다.)), (((0, 0, 0), (1, 40, 2)), 959999.8719319522), (((0, 0, 0), (1, 30, 2)), 969868.0497229715), (((0, 0, 0), (1, 20, 2)), 972027.5269831144)]
반응형
'AI, ML' 카테고리의 다른 글
| Cost Function과 Loss Function 개념: 제곱 손실과 Cross Entropy (0) | 2026.05.19 |
|---|---|
| Q-Learning Learning Rate 문제: 작은 학습률과 느린 수렴 (0) | 2026.05.16 |
| 인공지능 개념 메모: SVM, Bayesian, HMM, Markov (0) | 2026.05.15 |
| Convolution 개념과 CNN 기초 정리 (0) | 2026.05.15 |
| ResNet과 Keras 메모: residual connection, input_shape, predict/evaluate (0) | 2026.05.15 |
