def __init__(self, init_model=None, row=8, column=8, batch_size=200, buffer_size=10000, epochs=5, game_batch_num=100, n_games=1, check_freq=10, lr_multiplier=1.0, use_gpu=True): self.row = row self.column = column self.init_model = init_model self.policy_network = PolicyNetwork(model_file=init_model, width=column, height=row) self.batch_size = batch_size self.buffer_size = buffer_size self.buffer = deque(maxlen=self.buffer_size) self.epochs = epochs self.game_batch_num = game_batch_num self.n_games = n_games self.kl_targ = 0.02 # the target value of KL Divergence self.lr_multiplier = lr_multiplier # adjust the learning rate of the optimization algorithm self.check_freq = check_freq # check every few game rounds to see if the algorithm is improving self.use_gpu = use_gpu
def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=0.05, l_rate=0.01): self.stock_code = stock_code self.chart_data = chart_data # 환경 객체 self.environment = Environment(chart_data) # 에이전트 객체 self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) # 학습 데이터 self.training_data = training_data self.sample = None # 여기서 sample도 training_data와 같이 17차원 self.training_data_idx = -1 # 정책 신경망의 Input layer에 들어오는 입력의 크기 또는 특징의 수(17) = 학습 데이터의 크기(15) + 에이전트 상태의 크기(2) # TODO self.training_data.shape의 [1]이 왜 학습 데이터의 크기인지 확인 # TODO <해결> shape가 2차원이면 (n,15)일 것이고, 여기서 행은 전체 갯수이고, 열의 갯수가 학습 데이터의 크기로 들어갈 특징의 갯수일 것이다. # shape가 2차원인 이유는 policy_network.py에서 설명했다. # --> "Sequential 클래스의 predict() 함수는 여러 샘플을 한번에 받아서 신경망의 출력을 반환한다. # 하나의 샘플에 대한 결과만을 받고 싶어도 입력값을 샘플의 배열로 구성해야하기 때문에 2차원 배열로 재구성한다." self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM # 정책 신경망 객체 self.policy_network = PolicyNetwork( input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, l_rate=l_rate) # 가시화기 객체 (에포크마다 투자 결과 가시화) self.visualizer = Visualizer()
def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01): self.stock_code = stock_code # 종목코드 # 차트 데이터 self.chart_data = chart_data # 환경 self.environment = Environment(stock_code, chart_data) # 환경 객체 # 에이전트 객체 self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) # 학습 데이터 매칭 self.training_data = training_data # 학습 데이터 # 샘플 초기 상태 self.sample = None # 현재 학습 데이터 인덱스 self.training_data_idx = -1 # 입력은 환경에서 발생하는 모든 요소를 반영한다. # 정책 신경망; 입력 크기 = 학습 데이터의 크기 + 에이전트 상태 크기 self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM # 정첵 신경멍 객체 생성 및 매칭, 입력 계층 갯수, 출력 갯수, 학습률을 넣어 준다. self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer() # 가시화 모듈
def __init__(self, coin_code, coin_chart, training_data=None, model_ver=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, start_date=None, end_date=None, lr=0.01): self.coin_code = coin_code self.coin_chart = coin_chart self.environment = Environment(coin_chart) self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data self.sample = None self.training_data_idx = -1 self.model_ver = model_ver self.start_date = start_date self.end_date = end_date self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr, load_weight=self.model_ver)
def __init__(self, coin_code, coin_chart, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01): self.coin_code = coin_code self.coin_chart = coin_chart self.environment = Environment(coin_chart) self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data self.sample = None self.training_data_idx = -1 self.num_features = self.training_data.shape[ 1] + self.agent.STATE_DIM # -1 # input_dim = 15 + 2 = 17 self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer()
def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01, tax=False): self.stock_code = stock_code # Stock code self.chart_data = chart_data self.environment = Environment(chart_data) # Environment object self.tax = tax # Agent object self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold, tax=tax) self.training_data = training_data # Training data self.sample = None self.training_data_idx = -1 # Policy neural network; Input size = size of training data + agent state size self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer() # Visualization module
def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01): self.stock_code = stock_code # 종목코드 self.chart_data = chart_data self.environment = Environment(chart_data) # 환경 객체 # 에이전트 객체 self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data # 학습 데이터 self.samples = None self.training_data_idx = -1 # 정책 신경망; 입력 크기 = 학습 데이터의 크기 + 에이전트 상태 크기 self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer() # 가시화 모듈
def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01): self.stock_code = stock_code # 종목코드 self.chart_data = chart_data self.environment = Environment(chart_data) # 환경 객체 # Environment 클래스는 차트 데이터를 순서대로 읽으면서 주가, 거래량 등의 환경을 제공한다. # 에이전트 객체 self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data # 학습 데이터. 학습에 사용할 특징(feature)들을 포함한다. self.sample = None self.training_data_idx = -1 # 정책 신경망; 입력 크기(17개) = 학습 데이터의 크기(15개) + 에이전트 상태 크기(2개) self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer() # 가시화 모듈
def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=0.05, l_rate=0.01): self.stock_code = stock_code self.chart_data = chart_data self.environment = Environment(chart_data) self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data self.sample = None self.training_data_idx = -1 self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, l_rate=l_rate) self.visualizer = Visualizer()
def main(): # device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") device = torch.device("cpu") print("Device is: %s" % device) env = gym.make("CartPole-v1") steps = 500 n = 200 g = 0.99 pi = PolicyNetwork(4, 256, 256, 2).to(device) optimizer = torch.optim.Adam(pi.parameters(), lr=1e-4) print("The action space for Cartpole is: %s" % env.action_space) gf = gfunc1 returns = np.zeros(n) for i in range(200): mu = np.mean(returns[:i]) std = np.std(returns[:i]) if np.isnan(mu): mu = 0 if np.isnan(std): std = 0 loss, G = batch_roll_out(env, pi, g, steps, device, gf) returns[i] = G # how should I do gradient descent on the data; print("Iteration: %s; Loss: %s" % (i, loss)) optimizer.zero_grad() loss.backward() optimizer.step() testPolicy(env, pi, device, g) plot_return(returns, n) env.close()
def _policy(self, board): '''Output the probability of different positions according to the board information. In this AlphaZero version, use the value network to judge the current situation. Input: Board state Output: An iterator of (action, probability) and a score for the current board state. ''' policy_network = PolicyNetwork(width=board.row, height=board.column, model_file=self.model_file, use_gpu=self.use_gpu) return policy_network.policy_fn(board)
def __init__(self, learning_rate, input_channels): super(Train, self).__init__() self.learning_rate = learning_rate self.batch_size = batch_size self.epochs = epochs self.reset() self.network = PolicyNetwork(input_channels) self.parameters = self.network.parameters() self.optimizer = optim.Adam(self.parameters, lr=self.learning_rate)
def __init__(self, state_size, action_size, seed): self.state_size = state_size self.action_size = action_size self.seed = random.seed(seed) # Our policy network self.local_network = PolicyNetwork(state_size, action_size, seed).to(device) self.target_network = PolicyNetwork(state_size, action_size, seed).to(device) self.optimizer = optim.Adam(self.local_network.parameters(), lr=LR) # Replay memory self.memory = ReplayBuffer(action_size, BUFFER_SIZE, BATCH_SIZE, seed) # Initialize timestep self.t_step = 0
def __init__(self, stock_code, chart_data, training_data=None, policy_model_path=None, value_model_path=None, lr=0.001, discount_factor=0.5, start_epsilon=0, num_past_input=0, load_weight_and_learn=False): self.stock_code = stock_code # 종목코드 self.chart_data = chart_data self.environment = Environment(chart_data) # 환경 객체 # 에이전트 객체 self.agent = Agent(self.environment) self.training_data = training_data # 학습 데이터 self.training_data_idx = -1 self.state = None self.action_size = self.agent.NUM_ACTIONS self.discount_factor = discount_factor self.start_epsilon = start_epsilon self.num_past_input = num_past_input self.load_weight_and_learn = load_weight_and_learn # 정책/가치 신경망; 입력 크기 = 학습 데이터의 크기 #+ 에이전트 상태 크기 self.num_features = self.training_data.shape[1] * ( 1 + num_past_input) #+ self.agent.STATE_DIM self.policy_network_obj = PolicyNetwork( input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) if load_weight_and_learn is True: self.policy_network_obj.model = load_model(policy_model_path) self.policy_network = self.policy_network_obj.model else: self.policy_network = self.policy_network_obj.make_model() self.value_network_obj = ValueNetwork(input_dim=self.num_features, lr=lr) if load_weight_and_learn is True: self.value_network_obj.model = load_model(value_model_path) self.value_network = self.value_network_obj.model else: self.value_network = self.value_network_obj.make_model() self.policy_updater = self.policy_optimizer() self.value_updater = self.value_optimizer()
def __init__(self, alpha, input_size, output_size): self.buffer = Buffer() self.value_network = ValueNetwork(alpha, input_size=input_size, output_size=1) self.policy_network = PolicyNetwork(0.0001, input_size=input_size, output_size=output_size) self.old_policy_network = PolicyNetwork(0.0001, input_size=input_size, output_size=output_size) # store policy state self.buffer.store_parameters(self.policy_network.state_dict()) self.avg_rewards = []
class Train(nn.Module): def __init__(self, learning_rate, input_channels): super(Train, self).__init__() self.learning_rate = learning_rate self.batch_size = batch_size self.epochs = epochs self.reset() self.network = PolicyNetwork(input_channels) self.parameters = self.network.parameters() self.optimizer = optim.Adam(self.parameters, lr=self.learning_rate) def reset(self): self.wealth = 1e6 self.loss = 0 self.total_reward = 0 self.wealth_history = [] self.return_history = [] def updateSummary(self, loss): self.loss += loss reward = -1 * loss self.wealth = self.wealth * math.exp(reward) self.total_reward += reward self.wealth_history.append(self.wealth) self.return_history.append(math.exp(reward)) def getBatch(self, data, target, batch): start_pos = batch * self.batch_size end_pos = start_pos + self.batch_size x = torch.from_numpy(data[start_pos:end_pos]).float() y = torch.from_numpy(target[start_pos:end_pos]).float() # x = x.view(x.shape[0],x.shape[1]*x.shape[2]) # y = y.view(y.shape[0],1) #Normalizing X by the last real day price x = x / x[-1][-1][-2] return x, y def loss_function(self, w1, w2, y): transaction_cost = 1 - torch.sum( torch.abs(w2 - w1)) * transaction_commission portfolio_return = torch.sum(w2 * y) loss = -1 * torch.log(portfolio_return * transaction_cost) loss = torch.mean(loss) return loss
def train_models(configs): device = "/gpu:0" if USE_GPU else "/cpu:0" network_scope = TASK_TYPE list_of_tasks = TASK_LIST scene_scopes = list_of_tasks.keys() for config_dict in configs: config = Configuration(**config_dict) print("training with config=%s" % (str(config))) # build the model graph model = PolicyNetwork(config, device=device, network_scope=network_scope, scene_scopes=scene_scopes) sess_config = tf.ConfigProto(log_device_placement=False, allow_soft_placement=True) threads = create_threads(config, model, network_scope, list_of_tasks) with tf.Session(config=sess_config) as session: train_model(model, session, config, threads, config_dict['logdir'], config_dict['weight_root']) tf.reset_default_graph()
def evaluate(): device = "/gpu:0" if USE_GPU else "/cpu:0" network_scope = TASK_TYPE list_of_tasks = TASK_LIST scene_scopes = list_of_tasks.keys() weight_root = args.weight_root config = Configuration(**vars(args)) print("evaluating with config=%s" % (str(config))) model = PolicyNetwork(config, device=device, network_scope=network_scope, scene_scopes=scene_scopes) sess_config = tf.ConfigProto(log_device_placement=False, allow_soft_placement=True) with tf.Session(config=sess_config) as session: weight_path = weight_root + '/modelv1' saver = tf.train.Saver() checkpoint = tf.train.get_checkpoint_state(weight_root) assert saver and checkpoint and checkpoint.model_checkpoint_path, weight_path + " doesn't exist" saver.restore(session, checkpoint.model_checkpoint_path) evaluate_model(session, config, model)
class PolicyLearner: def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01): self.stock_code = stock_code # 종목코드 self.chart_data = chart_data self.environment = Environment(chart_data) # 환경 객체 # Environment 클래스는 차트 데이터를 순서대로 읽으면서 주가, 거래량 등의 환경을 제공한다. # 에이전트 객체 self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data # 학습 데이터. 학습에 사용할 특징(feature)들을 포함한다. self.sample = None self.training_data_idx = -1 # 정책 신경망; 입력 크기(17개) = 학습 데이터의 크기(15개) + 에이전트 상태 크기(2개) self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer() # 가시화 모듈 def reset(self): # 에포크 초기화 함수 부분 self.sample = None self.training_data_idx = -1 # 학습 데이터를 읽어가면서 이 값은 1씩 증가 def fit( #학습 함수 선언 부분. 핵심 함수이다. # num_epoches : 수행할 반복 학습의 전체 횟수. (너무 크게 잡으면 학습 소요 시간이 너무 길어짐) # max_memory : 배치 학습 데이터를 만들기 위해 과거 데이터를 저장할 배열. # balance : 에이전트의 초기 투자 자본금을 정해주기 위한 인자 # discount_factor : 지연 보상이 발생했을 때 그 이전 지연 보상이 발생한 시점과 현재 지연 보상이 발생한 # 시점 사이에서 수행한 행동들 전체에 현재의 지연 보상을 적용한다. # 과거로 갈수록 현재 지연 보상을 적용할 판단 근거가 흐려지기 때문에 먼 과걱의 행동일수록 할인 요인을 # 적용하여 지연 보상을 약하게 적용한다. # start_epsilon : 초기 탐험 비율. 학습이 전혀 되어 있지 않은 초기에는 탐험 비율을 크게 해서 # 더 많은 탐험, 즉 무작위 투자를 수행하도록 해야 한다. 탐험을 통해 특정 상황에서 좋은 행동과 # 그렇지 않은 행동을 결정하기 위한 경험을 쌓는다. # learning : 학습 유무를 정하는 boolean 값. 학습을 마치면 학습된 정책 신경망 모델이 만들어지는데, # 이렇게 학습을 해서 정책 신경망 모델을 만들고자 한다면 learning을 True로, # 학습된 모델을 가지고 투자 시뮬레이션만 하려 한다면 learning을 False로 준다. self, num_epoches=1000, max_memory=60, balance=10000000, discount_factor=0, start_epsilon=.5, learning=True): logger.info( "LR: {lr}, DF: {discount_factor}, " "TU: [{min_trading_unit}, {max_trading_unit}], " "DRT: {delayed_reward_threshold}".format( lr=self.policy_network.lr, discount_factor=discount_factor, min_trading_unit=self.agent.min_trading_unit, max_trading_unit=self.agent.max_trading_unit, delayed_reward_threshold=self.agent.delayed_reward_threshold)) # 가시화 준비 # 차트 데이터는 변하지 않으므로 미리 가시화 self.visualizer.prepare(self.environment.chart_data) # 가시화 결과 저장할 폴더 준비 epoch_summary_dir = os.path.join( # 폴더의 경로를 변수로 저장 settings.BASE_DIR, 'epoch_summary/%s/epoch_summary_%s' % (self.stock_code, settings.timestr)) if not os.path.isdir( epoch_summary_dir): # 해당 경로가 없으면 이 경로를 구성하는 폴더들을 생성 os.makedirs(epoch_summary_dir) # 에이전트 초기 자본금 설정 self.agent.set_balance(balance) # 학습에 대한 정보 초기화 max_portfolio_value = 0 epoch_win_cnt = 0 # 학습 반복 for epoch in range(num_epoches): # 에포크 관련 정보 초기화 loss = 0. # 정책 신경망의 결과가 학습 데이터와 얼마나 차이가 있는지를 저장하는 변수. 학습 중 줄어드는게 좋음. itr_cnt = 0 # 수행한 에포크 수를 저장 win_cnt = 0 # 수행한 에포크 중에서 수익이 발생한 에포크 수를 저장. 포트폴리오 가치가 초기 자본금보다 높아진 에포크 수. exploration_cnt = 0 # 무작위 투자를 수행한 횟수. epsilon이 0.1이고 100번의 투자 결정이 있으면 약 10번의 무작위 투자를 함 batch_size = 0 pos_learning_cnt = 0 # 수익이 발생하여 긍정적 지연 보상을 준 수 neg_learning_cnt = 0 # 손실이 발생하여 부정적 지연 보상을 준 수 # 메모리 초기화 # 메모리 리스트에 저장하는 데이터는 샘플, 행동, 즉시보상, 정책 신경망의 출력, 포트폴리오 가치, # 보유 주식 수, 탐험 위치, 학습 위치이다. memory_sample = [] memory_action = [] memory_reward = [] memory_prob = [] memory_pv = [] memory_num_stocks = [] memory_exp_idx = [] memory_learning_idx = [] # 환경, 에이전트, 정책 신경망 초기화 self.environment.reset() self.agent.reset() self.policy_network.reset() self.reset() # 가시화 초기화 self.visualizer.clear([0, len(self.chart_data) ]) # 2, 3, 4번째 차트를 초기화함. x축 데이터 범위를 파라미터로 # 학습을 진행할 수록 탐험 비율 감소 # 무작위 투자 비율인 epsilon 값을 정함 # fit() 함수의 인자로 넘어오는 최초 무작위 투자 비율인 start_epsilon 값에 현재 epoch 수에 학습 진행률을 곱해서 정함 # ex) start_epsilon이 0.3이면 첫 번째 에포크에서는 30%의 확률로 무작위 투자를 진행함. # 수행할 에포크 수가 100이라고 했을 때, 50번째 에포크에서는 0.3 * (1 - 49/99) = 0.51 if learning: epsilon = start_epsilon * (1. - float(epoch) / (num_epoches - 1)) else: epsilon = 0 while True: # 샘플 생성 next_sample = self._build_sample() if next_sample is None: # 마지막까지 데이터를 다 읽은 것이므로 반복문 종료 break # 정책 신경망 또는 탐험에 의한 행동 결정 # 매수와 매도 중 하나를 결정. 이 행동 결정은 무작위 투자 비율인 epsilon 값의 확률로 무작위로 하거나 # 그렇지 않은 경우 정책 신경망의 출력을 통해 결정된다. 정책 신경망의 출력은 매수를 했을 때와 매도를 했을 때의 # 포트폴리오 가치를 높일 확률을 의미한다. 즉 매수에 대한 정책 신경망 출력이 매도에 대한 출력보다 높으면 매수, 반대는 매도 # decide_action() 함수가 반환하는 값은 세 가지. # 결정한 행동인 action, 결정에 대한 확신도인 confidence, 무작위 투자 유무인 exploration. action, confidence, exploration = self.agent.decide_action( self.policy_network, self.sample, epsilon) # 결정한 행동을 수행하고 (act 함수) 즉시 보상과 지연 보상 획득 (act가 반환함) immediate_reward, delayed_reward = self.agent.act( action, confidence) # 행동 및 행동에 대한 결과를 기억 (메모리에 저장) memory_sample.append(next_sample) # 각 데이터를 메모리에 추가 memory_action.append(action) memory_reward.append(immediate_reward) memory_pv.append(self.agent.portfolio_value) memory_num_stocks.append(self.agent.num_stocks) memory = [ ( # 학습데이터의 샘플, 에이전트 행동, 즉시보상, 포트폴리오 가치, 보유 주식 수를 저장하는 배열 memory_sample[i], memory_action[i], memory_reward[i]) for i in list(range(len(memory_action)))[-max_memory:] ] if exploration: # 무작위 투자로 행동을 결정한 경우에 현재의 인덱스를 memory_exp_idx에 저장 memory_exp_idx.append(itr_cnt) memory_prob.append( [np.nan] * Agent.NUM_ACTIONS ) # memory_prob은 정책 신경망의 출력을 그대로 저장하는 배열 # 무작위 투자에서는 정책 신경망의 출력이 없기 때문에 NumPy의 Not A Number(nan) 값을 넣어줌 else: # 무작위 투자가 아닌 경우 정책 신경망의 출력을 그대로 저장 memory_prob.append(self.policy_network.prob) # 메모리 변수들의 목적은 (1) 학습에서 배치 학습 데이터로 사용 (2) 가시화기에서 차트를 그릴 때 사용 # 반복에 대한 정보 갱신 batch_size += 1 # 배치 크기 itr_cnt += 1 # 반복 카운팅 횟수 exploration_cnt += 1 if exploration else 0 # 무작위 투자 횟수 (탐험을 한 경우에만) win_cnt += 1 if delayed_reward > 0 else 0 # 수익이 발생한 횟수를 증가시킴 (지연 보상이 0보다 큰 경우에만) # 지연 보상이 발생한 경우 학습을 수행하는 부분 # 학습 모드이고 지연 보상이 존재할 경우 정책 신경망 갱신 # 학습 없이 메모리가 최대 크기만큼 다 찼을 경우 즉시 보상으로 지연 보상을 대체하여 학습을 진행 if delayed_reward == 0 and batch_size >= max_memory: delayed_reward = immediate_reward self.agent.base_portfolio_value = self.agent.portfolio_value if learning and delayed_reward != 0: # 배치 학습 데이터 크기 batch_size = min( batch_size, max_memory ) # 배치 데이터 크기는 memory 변수의 크기인 max_memory보다는 작아야 함 # 배치 학습 데이터 생성 x, y = self._get_batch(memory, batch_size, discount_factor, delayed_reward) if len(x) > 0: # 긍정 학습과 부정 학습 횟수 세기 if delayed_reward > 0: pos_learning_cnt += 1 else: neg_learning_cnt += 1 # 정책 신경망 갱신 loss += self.policy_network.train_on_batch( x, y) # 준비한 배치 데이터로 학습을 진행함 memory_learning_idx.append([itr_cnt, delayed_reward ]) # 학습이 진행된 인덱스를 저장함 batch_size = 0 # 학습이 진행되었으니 배치 데이터 크기를 초기화함 # 에포크 관련 정보 가시화 num_epoches_digit = len(str( num_epoches)) # 총 에포크 수의 문자열 길이를 확인함. 총 에포크 수가 1000이면 길이는 4 epoch_str = str(epoch + 1).rjust( num_epoches_digit, '0' ) # 현재 에포크 수를 4자리 문자열로 만들어 줌. 첫 에포크는 1 -> 0001로 문자열을 자리수에 맞게 정렬 self.visualizer.plot(epoch_str=epoch_str, num_epoches=num_epoches, epsilon=epsilon, action_list=Agent.ACTIONS, actions=memory_action, num_stocks=memory_num_stocks, outvals=memory_prob, exps=memory_exp_idx, learning=memory_learning_idx, initial_balance=self.agent.initial_balance, pvs=memory_pv) self.visualizer.save( os.path.join( #가시화한 에포크 수행 결과를 파일로 저장함 epoch_summary_dir, 'epoch_summary_%s_%s.png' % (settings.timestr, epoch_str))) # 에포크 관련 정보 로그 기록 # 총 에포크 중에서 몇 번째 에포크를 수행했는지, 탐험률, 탐험 횟수, 매수 횟수, 매도 횟수, 관망 횟수, # 보유 주식 수, 포트폴리오 가치, 긍정적 학습 횟수, 부정적 학습 횟수, 학습 손실을 로그로 남긴다. if pos_learning_cnt + neg_learning_cnt > 0: loss /= pos_learning_cnt + neg_learning_cnt logger.info( "[Epoch %s/%s]\tEpsilon:%.4f\t#Expl.:%d/%d\t" "#Buy:%d\t#Sell:%d\t#Hold:%d\t" "#Stocks:%d\tPV:%s\t" "POS:%s\tNEG:%s\tLoss:%10.6f" % (epoch_str, num_epoches, epsilon, exploration_cnt, itr_cnt, self.agent.num_buy, self.agent.num_sell, self.agent.num_hold, self.agent.num_stocks, locale.currency(self.agent.portfolio_value, grouping=True), pos_learning_cnt, neg_learning_cnt, loss)) # 학습 관련 정보 갱신 # 하나의 에포크 수행이 완료되었기 때문에 전체 학습에 대한 통계 정보를 갱신한다. # 관리하고 있는 학습 통계 정보는 달성한 최대 포트 폴리오 가치 max_portfolio_value와 쉭이 발생한 에포크의 수 epoch_win_cnt이다. max_portfolio_value = max(max_portfolio_value, self.agent.portfolio_value) if self.agent.portfolio_value > self.agent.initial_balance: epoch_win_cnt += 1 # 여기 까지가 학습 반복 for문의 코드 블록이다. # 학습 관련 정보 로그 기록 logger.info("Max PV: %s, \t # Win: %d" % (locale.currency( max_portfolio_value, grouping=True), epoch_win_cnt)) def _get_batch(self, memory, batch_size, discount_factor, delayed_reward): # 미니 배치 데이터 생성 x = np.zeros( (batch_size, 1, self.num_features)) # x는 일련의 학습 데이터 및 에이전트 상태 # x 배열의 형태는 배치 데이터 크기, 학습 데이터 특징 크기로 2차원으로 구성됨. y = np.full((batch_size, self.agent.NUM_ACTIONS), 0.5) # y는 일련의 지연 보상 # y 배열의 형태는 배치 데이터 크기, 정책 신경망이 결정하는 에이전트 행동의 수. 2차원으로. 0.5 일괄적으로 채워둠. for i, (sample, action, reward) in enumerate(reversed(memory[-batch_size:])): x[i] = np.array(sample).reshape( (-1, 1, self.num_features)) # 특징벡터 지정 y[i, action] = (delayed_reward + 1) / 2 # 지연 보상으로 정답(레이블)을 설정하여 학습 데이터 구성 # 지연 보상이 1인 경우 1로, -1인 경우 0으로 레이블을 지정 if discount_factor > 0: y[i, action] *= discount_factor**i # 할인 요인이 있을 경우 return x, y # 학습 데이터를 구성하는 샘플 하나를 생성하는 함수 def _build_sample(self): self.environment.observe() # 차트 데이터의 현재 인덱스에서 다음 인덱스 데이터를 읽음 if len(self.training_data ) > self.training_data_idx + 1: # 학습 데이터의 다음 인덱스가 존재하는지 확인 self.training_data_idx += 1 self.sample = self.training_data.iloc[ self.training_data_idx].tolist() # 인덱스의 데이터를 받아와서 sample로 저장 self.sample.extend( self.agent.get_states()) # sample에 에이전트 상태를 15개에서 +2개하여 17개로. return self.sample return None # 학습된 정책 신경망 모델로 주식투자 시뮬레이션을 진행 def trade(self, model_path=None, balance=2000000): if model_path is None: return self.policy_network.load_model( model_path=model_path) # 학습된 신경망 모델을 정책 신경망 객체의 load_model로 적용 self.fit(balance=balance, num_epoches=1, learning=False)
def load_model(self): return PolicyNetwork.load(self.model_file)
class PolicyLearner: def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01): self.stock_code = stock_code # 종목코드 self.chart_data = chart_data self.environment = Environment(chart_data) # 환경 객체 # 에이전트 객체 self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data # 학습 데이터 self.samples = None self.training_data_idx = -1 # 정책 신경망; 입력 크기 = 학습 데이터의 크기 + 에이전트 상태 크기 self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer() # 가시화 모듈 def reset(self): self.sample = None self.training_data_idx = -1 def fit(self, num_epoches=1000, max_memory=60, balance=10000000, discount_factor=0, start_epsilon=.5, learning=True, index_change_rate=0): logger.info( "LR: {lr}, DF: {discount_factor}, " "TU: [{min_trading_unit}, {max_trading_unit}], " "DRT: {delayed_reward_threshold}".format( lr=self.policy_network.lr, discount_factor=discount_factor, min_trading_unit=self.agent.min_trading_unit, max_trading_unit=self.agent.max_trading_unit, delayed_reward_threshold=self.agent.delayed_reward_threshold)) # 가시화 준비 # 차트 데이터는 변하지 않으므로 미리 가시화 self.visualizer.prepare(self.environment.chart_data) # 가시화 결과 저장할 폴더 준비 epoch_summary_dir = os.path.join( settings.BASE_DIR, 'epoch_summary/%s/epoch_summary_%s' % (self.stock_code, settings.timestr)) if not os.path.isdir(epoch_summary_dir): os.makedirs(epoch_summary_dir) # 에이전트 초기 자본금 설정 self.agent.set_balance(balance) # 학습에 대한 정보 초기화 max_portfolio_value = 0 epoch_win_cnt = 0 # 학습 반복 for epoch in range(num_epoches): # 에포크 관련 정보 초기화 loss = 0. itr_cnt = 0 win_cnt = 0 exploration_cnt = 0 batch_size = 0 pos_learning_cnt = 0 neg_learning_cnt = 0 # 메모리 초기화 memory_sample = [] memory_action = [] memory_reward = [] memory_prob = [] memory_pv = [] memory_num_stocks = [] memory_exp_idx = [] memory_learning_idx = [] # 환경, 에이전트, 정책 신경망 초기화 self.environment.reset() self.agent.reset() self.policy_network.reset() self.reset() # 가시화 초기화 self.visualizer.clear([0, len(self.chart_data)]) # 학습을 진행할 수록 탐험 비율 감소 if learning: epsilon = start_epsilon * (1. - float(epoch) / (num_epoches - 1)) else: epsilon = 0 while True: # 샘플 생성 next_sample = self._build_sample() if next_sample is None: break # 정책 신경망 또는 탐험에 의한 행동 결정 action, confidence, exploration = self.agent.decide_action( self.policy_network, self.sample, epsilon) # 결정한 행동을 수행하고 즉시 보상과 지연 보상 획득 immediate_reward, delayed_reward = self.agent.act( action, confidence) # 행동 및 행동에 대한 결과를 기억 memory_sample.append(next_sample) memory_action.append(action) memory_reward.append(immediate_reward) memory_pv.append(self.agent.portfolio_value) memory_num_stocks.append(self.agent.num_stocks) memory = [ (memory_sample[i], memory_action[i], memory_reward[i]) for i in list(range(len(memory_action)))[-max_memory:] ] if exploration: memory_exp_idx.append(itr_cnt) memory_prob.append([np.nan] * Agent.NUM_ACTIONS) else: memory_prob.append(self.policy_network.prob) # 반복에 대한 정보 갱신 batch_size += 1 itr_cnt += 1 exploration_cnt += 1 if exploration else 0 win_cnt += 1 if delayed_reward > 0 else 0 # 학습 모드이고 지연 보상이 존재할 경우 정책 신경망 갱신 if delayed_reward == 0 and batch_size >= max_memory: delayed_reward = immediate_reward self.agent.base_portfolio_value = self.agent.portfolio_value if learning and delayed_reward != 0: # 배치 학습 데이터 크기 batch_size = min(batch_size, max_memory) # 배치 학습 데이터 생성 x, y = self._get_batch(memory, batch_size, discount_factor, delayed_reward) if len(x) > 0: if delayed_reward > 0: pos_learning_cnt += 1 else: neg_learning_cnt += 1 # 정책 신경망 갱신 loss += self.policy_network.train_on_batch(x, y) memory_learning_idx.append([itr_cnt, delayed_reward]) batch_size = 0 # 에포크 관련 정보 가시화 num_epoches_digit = len(str(num_epoches)) epoch_str = str(epoch + 1).rjust(num_epoches_digit, '0') self.visualizer.plot(epoch_str=epoch_str, num_epoches=num_epoches, epsilon=epsilon, action_list=Agent.ACTIONS, actions=memory_action, num_stocks=memory_num_stocks, outvals=memory_prob, exps=memory_exp_idx, learning=memory_learning_idx, initial_balance=self.agent.initial_balance, pvs=memory_pv) self.visualizer.save( os.path.join( epoch_summary_dir, 'epoch_summary_%s_%s.png' % (settings.timestr, epoch_str))) # 에포크 관련 정보 로그 기록 if pos_learning_cnt + neg_learning_cnt > 0: loss /= pos_learning_cnt + neg_learning_cnt logger.info( "[Epoch %s/%s]\tEpsilon:%.4f\t#Expl.:%d/%d\t" "#Buy:%d\t#Sell:%d\t#Hold:%d\t" "#Stocks:%d\tPV:%s\t" "POS:%s\tNEG:%s\tLoss:%10.6f" % (epoch_str, num_epoches, epsilon, exploration_cnt, itr_cnt, self.agent.num_buy, self.agent.num_sell, self.agent.num_hold, self.agent.num_stocks, locale.currency(self.agent.portfolio_value, grouping=True), pos_learning_cnt, neg_learning_cnt, loss)) # 학습 관련 정보 갱신 max_portfolio_value = max(max_portfolio_value, self.agent.portfolio_value) if self.agent.portfolio_value > self.agent.initial_balance: epoch_win_cnt += 1 #수익율 계산 profit = (max_portfolio_value - balance) / balance * 100 # 학습 관련 정보 로그 기록 if 0: logger.info("Max PV: %s, \t # Win: %d" % (locale.currency( max_portfolio_value, grouping=True), epoch_win_cnt)) else: logger.info( "Max PV: %s, \t #Profit: %.2f, \t #Win: %d, \t # Index : %.2f" % (locale.currency(max_portfolio_value, grouping=True), profit, epoch_win_cnt, index_change_rate)) def _get_batch(self, memory, batch_size, discount_factor, delayed_reward): x = np.zeros((batch_size, 1, self.num_features)) y = np.full((batch_size, self.agent.NUM_ACTIONS), 0.5) for i, (sample, action, reward) in enumerate(reversed(memory[-batch_size:])): x[i] = np.array(sample).reshape((-1, 1, self.num_features)) y[i, action] = (delayed_reward + 1) / 2 if discount_factor > 0: y[i, action] *= discount_factor**i return x, y def _build_sample(self): self.environment.observe() if len(self.training_data) > self.training_data_idx + 1: self.training_data_idx += 1 self.sample = self.training_data.iloc[ self.training_data_idx].tolist() self.sample.extend(self.agent.get_states()) return self.sample return None def trade(self, model_path=None, balance=2000000, index_change_rate=0): if model_path is None: return self.policy_network.load_model(model_path=model_path) self.fit(balance=balance, num_epoches=1, learning=False, index_change_rate=index_change_rate)
class PolicyLearner: def __init__(self, coin_code, coin_chart, training_data=None, model_ver=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, start_date=None, end_date=None, lr=0.01): self.coin_code = coin_code self.coin_chart = coin_chart self.environment = Environment(coin_chart) self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data self.sample = None self.training_data_idx = -1 self.model_ver = model_ver self.start_date = start_date self.end_date = end_date self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr, load_weight=self.model_ver) # self.visualizer = Visualizer() def reset(self): self.sample = None self.training_data_idx = -1 def fit(self, num_epoches=1000, max_memory=60, balance=10000000, discount_factor=0, start_epsilon=.5, learning=True): logger.info( "Learning Rate: {lr}, Discount Factor: {discount_factor}, " "Trading Unit: [{min_trading_unit}, {max_trading_unit}], " "Delayed Reward threshold: {delayed_reward_threshold}, " "Training period: [{start_date} ~ {end_date}]".format( lr=self.policy_network.lr, discount_factor=discount_factor, min_trading_unit=self.agent.min_trading_unit, max_trading_unit=self.agent.max_trading_unit, delayed_reward_threshold=self.agent.delayed_reward_threshold, start_date=self.start_date, end_date=self.end_date)) # self.visualizer.prepare(self.environment.coin_chart) epoch_summary_dir = os.path.join( settings.BASE_DIR, 'epoch_summary/%s/epoch_summary_%s' % (self.coin_code, settings.timestr)) if not os.path.isdir(epoch_summary_dir): os.makedirs(epoch_summary_dir) self.agent.set_balance(balance) max_portfolio_value = 0 epoch_win_cnt = 0 for epoch in range(num_epoches): # loss = 0. accuracy = 0. itr_cnt = 0 win_cnt = 0 exploration_cnt = 0 batch_size = 0 pos_learning_cnt = 0 neg_learning_cnt = 0 memory_sample = [] memory_action = [] memory_reward = [] memory_prob = [] memory_pv = [] memory_num_coins = [] memory_exp_idx = [] memory_learning_idx = [] self.environment.reset() self.agent.reset() self.policy_network.reset() self.reset() # self.visualizer.clear([0, len(self.coin_chart)]) if learning: epsilon = start_epsilon * (1. - float(epoch) / (num_epoches - 1)) else: epsilon = 0 while True: next_sample = self._build_sample() if next_sample is None: break action, confidence, exploration = self.agent.decide_action( self.policy_network, self.sample, epsilon) immediate_reward, delayed_reward = self.agent.act( action, confidence) memory_sample.append(next_sample) memory_action.append(action) memory_reward.append(immediate_reward) memory_pv.append(self.agent.portfolio_value) memory_num_coins.append(self.agent.num_coins) memory = [ (memory_sample[i], memory_action[i], memory_reward[i]) for i in list(range(len(memory_action)))[-max_memory:] ] if exploration: memory_exp_idx.append(itr_cnt) memory_prob.append([np.nan] * Agent.NUM_ACTIONS) else: memory_prob.append(self.policy_network.prob) batch_size += 1 itr_cnt += 1 exploration_cnt += 1 if exploration else 0 win_cnt += 1 if delayed_reward > 0 else 0 if delayed_reward == 0 and batch_size >= max_memory: delayed_reward = immediate_reward self.agent.base_portfolio_value = self.agent.portfolio_value if learning and delayed_reward != 0: batch_size = min(batch_size, max_memory) x, y = self._get_batch(memory, batch_size, discount_factor, delayed_reward) if len(x) > 0: accuracy += self.policy_network.train_on_batch(x, y) memory_learning_idx.append([itr_cnt, delayed_reward]) batch_size = 0 num_epoches_digit = len(str(num_epoches)) epoch_str = str(epoch + 1).rjust(num_epoches_digit, '0') logger.info("[Epoch %s/%s]\tEpsilon:%.4f\t#Expl.:%d/%d\t" "#Buy:%d\t#Sell:%d\t#Hold:%d\t" "#Coins:%d\tPV:%s\t" "#Accuracy:%10.6f" % (epoch_str, num_epoches, epsilon, exploration_cnt, itr_cnt, self.agent.num_buy, self.agent.num_sell, self.agent.num_hold, self.agent.num_coins, locale.currency(self.agent.portfolio_value, grouping=True), accuracy)) max_portfolio_value = max(max_portfolio_value, self.agent.portfolio_value) if self.agent.portfolio_value > self.agent.initial_balance: epoch_win_cnt += 1 logger.info("Max PV: %s, \t # Win: %d" % (locale.currency( max_portfolio_value, grouping=True), epoch_win_cnt)) def _get_batch(self, memory, batch_size, discount_factor, delayed_reward): x = np.zeros((batch_size, 1, self.num_features)) y = np.full((batch_size, self.agent.NUM_ACTIONS), 0.5) for i, (sample, action, reward) in enumerate(reversed(memory[-batch_size:])): x[i] = np.array(sample).reshape((-1, 1, self.num_features)) y[i, action] = (delayed_reward + 1) / 2 if discount_factor > 0: y[i] = tl.rein.discount_episode_rewards(y[i], discount_factor) # y[i, action] *= discount_factor ** i return x, y def _build_sample(self): self.environment.observe() if len(self.training_data) > self.training_data_idx + 1: self.training_data_idx += 1 self.sample = self.training_data.iloc[ self.training_data_idx].tolist() self.sample.extend(self.agent.get_states()) return self.sample return None def trade(self, model_path=None, balance=2000000): if model_path is None: return self.policy_network.load_model(model_path=model_path) self.fit(balance=balance, num_epoches=1, learning=False)
ACTIONS = {0: "UP", 1: "DOWN", 2: "RIGHT", 3: "LEFT"} NUM_ACTIONS = len(ACTIONS) NUM_GAMES = 30000 OBSERVE = 1000 MAX_TILE = 2048 epsilon = 0.1 min_epsilon = 1e-2 gamma_epsilon = 0.999 gamma_reward = 0.99 replay = ExperienceReplay(capacity=1e6) logger = Logger() online = PolicyNetwork(batch_size=32) target = PolicyNetwork(batch_size=32) def preprocess(a: np.array) -> np.array: a = np.where(a <= 0, 1, a) a = np.log2(a) / np.log2(MAX_TILE) return a if __name__ == "__main__": best_score = 0 best_board = None best_iteration = 0
def main(): parser = argparse.ArgumentParser() parser.add_argument('--save_dir', type=str, default='./models', help='directory to store checkpointed models') parser.add_argument( '--val_frac', type=float, default=0.1, help='fraction of data to be witheld in validation set') parser.add_argument( '--ckpt_name', type=str, default='', help='name of checkpoint file to load (blank means none)') parser.add_argument('--data_file', type=str, default='0750am-0805am', help='time slot for data file') parser.add_argument('--data_dir', type=str, default='./2d_drive_data/', help='directory containing data') parser.add_argument('--batch_size', type=int, default=64, help='minibatch size') parser.add_argument('--seq_length', type=int, default=100, help='training sequence length') parser.add_argument('--state_dim', type=int, default=51, help='number of state variables') parser.add_argument('--extract_temporal', type=bool, default=False, help='Whether to extract temporal features') parser.add_argument('--action_dim', type=int, default=2, help='number of action variables') parser.add_argument('--num_epochs', type=int, default=50, help='number of epochs') parser.add_argument('--learning_rate', type=float, default=0.004, help='learning rate') parser.add_argument('--decay_rate', type=float, default=0.5, help='decay rate for learning rate') parser.add_argument('--grad_clip', type=float, default=5.0, help='clip gradients at this value') parser.add_argument('--save_h5', type=bool, default=False, help='Whether to save network params to h5 file') parser.add_argument('--h5_name', type=str, default='', help='Name for saved h5 file') ############################ # Policy Network # ############################ parser.add_argument('--mlp_activation', default=tf.nn.elu, help='activation function in policy network') parser.add_argument('--mlp_size', type=int, nargs='+', default=[], help='number of neurons in each feedforward layer') parser.add_argument('--gru_input_dim', type=int, default=64, help='size of input to gru layer') parser.add_argument('--gru_size', type=int, default=64, help='size of gru layer') parser.add_argument('--policy_varscope', type=str, default='policy', help='variable scope for policy network') args = parser.parse_args() if config.TF_NN_SETTRACE: ipdb.set_trace() # Construct model net = PolicyNetwork(args) # store config to disk with open(os.path.join(args.save_dir, 'config.pkl'), 'w') as f: cPickle.dump(args, f) # Export model parameters or perform training if args.save_h5: save_h5(args, net) else: train(args, net)
class Train(): def __init__(self, init_model=None, row=8, column=8, batch_size=200, buffer_size=10000, epochs=5, game_batch_num=100, n_games=1, check_freq=10, lr_multiplier=1.0, use_gpu=True): self.row = row self.column = column self.init_model = init_model self.policy_network = PolicyNetwork(model_file=init_model, width=column, height=row) self.batch_size = batch_size self.buffer_size = buffer_size self.buffer = deque(maxlen=self.buffer_size) self.epochs = epochs self.game_batch_num = game_batch_num self.n_games = n_games self.kl_targ = 0.02 # the target value of KL Divergence self.lr_multiplier = lr_multiplier # adjust the learning rate of the optimization algorithm self.check_freq = check_freq # check every few game rounds to see if the algorithm is improving self.use_gpu = use_gpu def _collect_training_data(self): '''Realize training data collection through self-play.''' for i in range(self.n_games): # generate self-play training data self.board = Board(self.row, self.column) self.board.set_state() AI = Alpha(model_file=self.init_model, use_gpu=self.use_gpu) board_states, mcts_probs, current_players = [], [], [] while (True): move, move_probs = AI.self_play(self.row, self.column, self.board.board_state) board_states.append(self.board.current_state()) mcts_probs.append(move_probs) self.board.move(move) current_players.append(self.board.get_cur_player()) end, winner = self.board.who_win() if end: winners = np.zeros(len(current_players)) if winner != 0: winners[np.array(current_players) == winner] = 1.0 winners[np.array(current_players) != winner] = -1.0 print(winners) play_data = zip(board_states, mcts_probs, winners) break play_data = list(play_data)[:] self.episode_len = len(play_data) # print(play_data) # add data to buffer self.buffer.extend(play_data) print(len(self.buffer)) def _policy_update(self): mini_batch = random.sample(self.buffer, self.batch_size) board_state_batch = [x[0] for x in mini_batch] mcts_probs_batch = [x[1] for x in mini_batch] winner_batch = [x[2] for x in mini_batch] old_probs, old_v = self.policy_network.batch_policy_fn( board_state_batch) for i in range(self.epochs): loss, entropy = self.policy_network.train_step( board_state_batch, mcts_probs_batch, winner_batch, lr=self.lr_multiplier) new_probs, new_v = self.policy_network.batch_policy_fn( board_state_batch) kl = np.mean( np.sum(old_probs * (np.log(old_probs + 1e-10) - np.log(new_probs + 1e-10)), axis=1)) if kl > self.kl_targ * 4: break if kl > self.kl_targ * 2 and self.lr_multiplier > 0.1: self.lr_multiplier /= 1.5 else: self.lr_multiplier *= 1.5 # explained_var_old = (1 - np.var(np.array(winner_batch) - old_v.flatten()) / np.var(np.array(winner_batch))) # explained_var_new = (1 - np.var(np.array(winner_batch) - new_v.flatten()) / np.var(np.array(winner_batch))) return loss, entropy def _eval_and_save_model(self, game_batch_num): '''Save model to the model directory.''' self.policy_network.save_model('./model/model{}_{}x{}.model'.format( game_batch_num + 1, self.row, self.column)) def run(self): '''play the number of self.game_batch_num games. If the amount of data in the buffer is greater than batch_size, perform one policy update including several epochs of training steps. ''' try: for i in range(self.game_batch_num): self._collect_training_data() print("Game batch i: {}, episode_len:{}".format( i + 1, self.episode_len)) if len(self.buffer) > self.batch_size: loss, entropy = self._policy_update() print("Game batch i: {}. loss: {}. entropy: {}".format( i + 1, loss, entropy)) if (i + 1) % self.check_freq == 0: print("current self-play game batch i: {}".format(i + 1)) self._eval_and_save_model(i) except KeyboardInterrupt: print('\n\rquit!')
class TRPO(object): def __init__(self, alpha, input_size, output_size): self.buffer = Buffer() self.value_network = ValueNetwork(alpha, input_size=input_size, output_size=1) self.policy_network = PolicyNetwork(0.0001, input_size=input_size, output_size=output_size) self.old_policy_network = PolicyNetwork(0.0001, input_size=input_size, output_size=output_size) # store policy state self.buffer.store_parameters(self.policy_network.state_dict()) self.avg_rewards = [] def update(self, iter=80): observations = self.buffer.get_observations() #actions = self.buffer.get_actions() rewards = self.buffer.get_rewards() advantages = self.buffer.get_advantages() log_probs = self.buffer.get_log_probs() self.old_policy_network.load_state_dict(self.buffer.old_parameters) old_pred = self.old_policy_network.forward(observations) old_action_probabilities = torch.distributions.Categorical(old_pred) old_action = old_action_probabilities.sample() old_probs = old_action_probabilities.log_prob(old_action).reshape( -1, 1) self.buffer.store_parameters(self.policy_network.state_dict()) self.policy_network.optimize(log_probs, old_probs, advantages) self.value_network.optimize(observations, rewards, iter=iter) def calculate_advantage(self): prev_observation = self.buffer.observation_buffer[-2] observation = self.buffer.observation_buffer[-1] v1 = self.value_network(prev_observation) v2 = self.value_network(observation) return self.buffer.reward_buffer[-1] + v2 - v1 def act(self, observation): prediction = self.policy_network.forward(observation) action_probabilities = torch.distributions.Categorical(prediction) action = action_probabilities.sample() log_prob = action_probabilities.log_prob(action) self.buffer.store_log_prob(log_prob) return action.item(), log_prob def discount_rewards(self, step): for s in reversed(range(1, step + 1)): update = 0 for k in reversed(range(1, s + 1)): update += self.buffer.reward_buffer[-k] * (0.99**k) self.buffer.reward_buffer[-s] += update def train(self, env, epochs=1000, steps=4000): plt.ion() for epoch in range(epochs): observation = env.reset() self.buffer.store_observation(observation) step = 0 for step in range(steps): step += 1 action, log_prob = self.act(observation) self.buffer.store_action(log_prob) observation, reward, done, info = env.step(action) self.buffer.store_reward(reward / 200 + observation[0] / 2 + (1 * observation[1])**2) #env.render() self.buffer.store_observation(observation) advantage = self.calculate_advantage() self.buffer.store_advantage(advantage) if done or step == steps - 1: observation = env.reset() self.discount_rewards(step) step = 0 self.update(iter=5) rwrd = self.buffer.get_rewards() self.avg_rewards.append((torch.sum(rwrd) / rwrd.shape[0]).numpy()) self.buffer.clear_buffer() print("Average Reward: {}".format(self.avg_rewards[-1])) plt.title("Reward per Epoch") plt.xlabel("Epoch") plt.ylabel("Reward") plt.plot(self.avg_rewards, label="average reward") plt.legend(loc="upper left") plt.draw() plt.pause(0.0001) plt.clf()
class PolicyLearner: def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=.05, lr=0.01): self.stock_code = stock_code # 종목코드 # 차트 데이터 self.chart_data = chart_data # 환경 self.environment = Environment(stock_code, chart_data) # 환경 객체 # 에이전트 객체 self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) # 학습 데이터 매칭 self.training_data = training_data # 학습 데이터 # 샘플 초기 상태 self.sample = None # 현재 학습 데이터 인덱스 self.training_data_idx = -1 # 입력은 환경에서 발생하는 모든 요소를 반영한다. # 정책 신경망; 입력 크기 = 학습 데이터의 크기 + 에이전트 상태 크기 self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM # 정첵 신경멍 객체 생성 및 매칭, 입력 계층 갯수, 출력 갯수, 학습률을 넣어 준다. self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, lr=lr) self.visualizer = Visualizer() # 가시화 모듈 # 학습 초기화 - 다시 시작할 때 초기화 한다. def reset(self): self.sample = None self.training_data_idx = -1 # 학습을 수행하는 함수 def fit(self, num_epoches=1000, max_memory=60, balance=10000000, discount_factor=0, start_epsilon=.5, learning=True): logger.info( "LR: {lr}, DF: {discount_factor}, " "TU: [{min_trading_unit}, {max_trading_unit}], " "DRT: {delayed_reward_threshold}".format( lr=self.policy_network.lr, discount_factor=discount_factor, min_trading_unit=self.agent.min_trading_unit, max_trading_unit=self.agent.max_trading_unit, delayed_reward_threshold=self.agent.delayed_reward_threshold)) # 가시화 준비 # 차트 데이터는 변하지 않으므로 미리 가시화 self.visualizer.prepare(self.environment.chart_data) # 가시화 결과 저장할 폴더 준비 epoch_summary_dir = os.path.join( settings.BASE_DIR, 'epoch_summary/%s/epoch_summary_%s' % (self.stock_code, settings.timestr)) # 에폭 요약 디렉토리를 만든다. if not os.path.isdir(epoch_summary_dir): os.makedirs(epoch_summary_dir) # 에이전트 초기 자본금 설정 self.agent.set_balance(balance) # 학습에 대한 정보 초기화 max_portfolio_value = 0 # 에포크에서 성공한 숫자 epoch_win_cnt = 0 # 학습 반복 for epoch in range(num_epoches): # 에포크 관련 정보 초기화 loss = 0. # 반복 카운트 itr_cnt = 0 # 수익이 발생한 횟수 카운트 win_cnt = 0 # 탐험 횟수 - 심층 신경망이 아닌 탐색에 의한 회수 exploration_cnt = 0 # 배치 크기 batch_size = 0 # 긍정적인 학습 숫자 pos_learning_cnt = 0 # 부정적인 학습 숫자 neg_learning_cnt = 0 # 메모리 초기화 memory_sample = [] # 액션 리스트 memory_action = [] # 보상 리스트 memory_reward = [] # 확률 리스트 memory_prob = [] # 프로파일 가치 memory_pv = [] # 보유 주식수 memory_num_stocks = [] # 탐험 인덱스 기억 memory_exp_idx = [] # 학습 인덱스 기억 memory_learning_idx = [] # 환경, 에이전트, 정책 신경망 초기화 self.environment.reset() self.agent.reset() self.policy_network.reset() self.reset() # 가시화 초기화 self.visualizer.clear([0, len(self.chart_data)]) # 학습을 진행할 수록 탐험 비율 감소 if learning: epsilon = start_epsilon * (1. - float(epoch) / (num_epoches - 1)) else: epsilon = 0 while True: # 샘플 생성 next_sample = self._build_sample() if next_sample is None: break # 정책 신경망 또는 탐험에 의한 행동 결정 action, confidence, exploration = self.agent.decide_action( self.policy_network, self.sample, epsilon) # 결정한 행동을 수행하고 즉시 보상과 지연 보상 획득 immediate_reward, delayed_reward = self.agent.act( action, confidence) # 행동 및 행동에 대한 결과를 기억 memory_sample.append(next_sample) # 현재의 행동을 저장 memory_action.append(action) # 직접 보상 저장 memory_reward.append(immediate_reward) # 포트폴리오 가치 저장 memory_pv.append(self.agent.portfolio_value) # 주식 갯수 저장 memory_num_stocks.append(self.agent.num_remain) # 샘플값(입력값), 액션값, 보상값을 튜플로 만들어 저장 memory = [ (memory_sample[i], memory_action[i], memory_reward[i]) for i in list(range(len(memory_action)))[-max_memory:] ] if exploration: # 탐색 인덱스를 저장한다. memory_exp_idx.append(itr_cnt) # 액션수만큼 갯수를 가진 리스트를 만들어 붙인다. # 여기에는 출력계층(매수, 매도)에 대한 확률이 들어간다. # 그러나 탐색일 때는 그 확률이 없으므로 이용할 수 없음 값으로 채운다. memory_prob.append([np.nan] * Agent.NUM_ACTIONS) else: memory_prob.append(self.policy_network.prob) # 반복에 대한 정보 갱신 batch_size += 1 itr_cnt += 1 # 탐험에 의한 것이면 탐험 갯수 추가 exploration_cnt += 1 if exploration else 0 # 지연보상이 발생했으면 승리한 회수 추가 win_cnt += 1 if delayed_reward > 0 else 0 # 지연보상이 없고 배치크기가 최대 메모리보다 크거나 같으면 if delayed_reward == 0 and batch_size >= max_memory: # 즉시 보상으로 지연보상 값을 대치하고 delayed_reward = immediate_reward # 기준 포트폴리오 값도 바꾸어준다. self.agent.base_portfolio_value = self.agent.portfolio_value # 학습 모드이고 지연 보상이 존재할 경우 정책 신경망 갱신 if learning and delayed_reward != 0: # 배치 학습 데이터 크기 batch_size = min(batch_size, max_memory) # 배치 학습 데이터 생성 x, y = self._get_batch(memory, batch_size, discount_factor, delayed_reward) if len(x) > 0: if delayed_reward > 0: pos_learning_cnt += 1 else: neg_learning_cnt += 1 # 정책 신경망 학습 시킴 - 지연 보상이 발생했을 때만 진행시킨다. loss += self.policy_network.train_on_batch(x, y) memory_learning_idx.append([itr_cnt, delayed_reward]) batch_size = 0 # 에포크 관련 정보 가시화 num_epoches_digit = len(str(num_epoches)) epoch_str = str(epoch + 1).rjust(num_epoches_digit, '0') self.visualizer.plot(epoch_str=epoch_str, num_epoches=num_epoches, epsilon=epsilon, action_list=Agent.ACTIONS, actions=memory_action, num_stocks=memory_num_stocks, outvals=memory_prob, exps=memory_exp_idx, learning=memory_learning_idx, initial_balance=self.agent.initial_balance, pvs=memory_pv) self.visualizer.save( os.path.join( epoch_summary_dir, 'epoch_summary_%s_%s.png' % (settings.timestr, epoch_str))) # 에포크 관련 정보 로그 기록 if pos_learning_cnt + neg_learning_cnt > 0: loss /= pos_learning_cnt + neg_learning_cnt logger.info( "[Epoch %s/%s]\tEpsilon:%.4f\t#Expl.:%d/%d\t" "#Buy:%d\t#Sell:%d\t#Hold:%d\t" "#Stocks:%d\tPV:%s\t" "POS:%s\tNEG:%s\tLoss:%10.6f" % (epoch_str, num_epoches, epsilon, exploration_cnt, itr_cnt, self.agent.num_buy, self.agent.num_sell, self.agent.num_hold, self.agent.num_remain, locale.currency(self.agent.portfolio_value, grouping=True), pos_learning_cnt, neg_learning_cnt, loss)) # 학습 관련 정보 갱신 max_portfolio_value = max(max_portfolio_value, self.agent.portfolio_value) if self.agent.portfolio_value > self.agent.initial_balance: epoch_win_cnt += 1 # 학습 관련 정보 로그 기록 logger.info("Max PV: %s, \t # Win: %d" % (locale.currency( max_portfolio_value, grouping=True), epoch_win_cnt)) # 배치 학습 데이터를 가져옴 def _get_batch(self, memory, batch_size, discount_factor, delayed_reward): # create an ndarray with all zeros x = np.zeros((batch_size, 1, self.num_features)) y = np.full((batch_size, self.agent.NUM_ACTIONS), 0.5) # 배열을 역순으로 도는 것은 가장 최근의 것에 가장 많은 점수를 주기 위해서이다. # 과거로 갈 수록 지연보상을 적용할 근거가 떨어지기 때문에 먼 과거의 일일 수록 할인 요인을 적용한다. for i, (sample, action, reward) in enumerate(reversed(memory[-batch_size:])): # x[i] 에는 특징값 수만큼 값들이 3차원으로 구성되어 들어갑니다. # 일단 2차원은 반드시 구성하고 데이터가 남을 경우 3차원을 구성하게 된다. x[i] = np.array(sample).reshape((-1, 1, self.num_features)) # y[i, action]에는 액션을 취하면 1.0, 취하지 않았으면 0.5로 들어갑니다. # action 0이면 매수이므로 [1.0, 0.5]라고 들어가게 됩니다. # action 1이면 매도이므로 [0.5, 1.0]라고 들어가게 됩니다. y[i, action] = (delayed_reward + 1) / 2 # 할인요소를 i승하여 곱해줌. if discount_factor > 0: y[i, action] *= discount_factor**i return x, y # 샘플 생성함수 def _build_sample(self): # 차트 데이터를 가져온다. self.environment.observe() # 학습데이터 크기 끝에 도달하지 않았다면 if len(self.training_data) > self.training_data_idx + 1: # 학습 인덱스 증가 self.training_data_idx += 1 temp2 = self.training_data.iloc[self.training_data_idx] # 입력값 한세트를 가져옴 self.sample = self.training_data.iloc[ self.training_data_idx].tolist() # 입력값 세트에 상태들을 더함 - 이것이 최종 입력 계층 값이 됨. self.sample.extend(self.agent.get_states()) # 입력 계층 값을 반환한다. return self.sample return None # 모델을 로드해 거래를 한다. def trade(self, model_path=None, balance=2000000): if model_path is None: return # 모델을 로드한다. self.policy_network.load_model(model_path=model_path) self.fit(balance=balance, num_epoches=1, learning=False)
class PolicyLearner: def __init__(self, stock_code, chart_data, training_data=None, min_trading_unit=1, max_trading_unit=2, delayed_reward_threshold=0.05, l_rate=0.01): self.stock_code = stock_code self.chart_data = chart_data self.environment = Environment(chart_data) self.agent = Agent(self.environment, min_trading_unit=min_trading_unit, max_trading_unit=max_trading_unit, delayed_reward_threshold=delayed_reward_threshold) self.training_data = training_data self.sample = None self.training_data_idx = -1 self.num_features = self.training_data.shape[1] + self.agent.STATE_DIM self.policy_network = PolicyNetwork(input_dim=self.num_features, output_dim=self.agent.NUM_ACTIONS, l_rate=l_rate) self.visualizer = Visualizer() def reset(self): self.sample = None self.training_data_idx = -1 def fit(self, num_epoches=1000, max_memory=60, balance=1000000, discount_factor=0, start_epsilon=0.5, learning=True): logger.info( "LR: {l_rate}, DF: {discount_factor}, " "TU: [{min_trading_unit, {max_trading_unit}], " "DRT: {delayed_reward_threshold}".format( l_rate=self.policy_network.l_rate, discount_factor=discount_factor, min_trading_unit=self.agent.min_trading_unit, max_trading_unit=self.agent.max_trading_unit, delayed_reward_threshold=self.agent.delayed_reward_threshold)) self.visualizer.prepare(self.environment.chart_data) # epoch_summary_dir = os.path.join(settings.BASE_DIR, 'epoch_summary/%s/epoch_summary_%s' % ( # self.stock_code, settings.timestr # )) epoch_summary_dir = os.path.join(settings.BASE_DIR, 'epoch_summary', '%s' % self.stock_code, 'epoch_summary_%s' % settings.timestr) if not os.path.isdir(epoch_summary_dir): os.makedirs(epoch_summary_dir) self.agent.set_balance(balance) max_portfolio_value = 0 epoch_win_cnt = 0 for epoch in range(num_epoches): loss = 0.0 itr_cnt = 0 win_cnt = 0 exploration_cnt = 0 batch_size = 0 pos_learning_cnt = 0 neg_learning_cnt = 0 memory_sample = [] memory_action = [] memory_reward = [] memory_prob = [] memory_pv = [] memory_num_stocks = [] memory_exp_idx = [] memory_learning_idx = [] self.environment.reset() self.agent.reset() self.policy_network.reset() self.reset() self.visualizer.clear([0, len(self.chart_data)]) if learning: epsilon = start_epsilon * (1. - (float(epoch) / (num_epoches - 1))) else: epsilon = 0 while True: next_sample = self._build_sample() if next_sample in None: break action, confidence, exploration = self.agent.decide_action( self.policy_network, self.sample, epsilon) immediate_reward, delayed_reward = self.agent.act( action, confidence)
def __init__(self, env, obs_space, action_space, ignoreLTL, gnn_type, dumb_ac, freeze_ltl): super().__init__() # Decide which components are enabled self.use_progression_info = "progress_info" in obs_space self.use_text = not ignoreLTL and (gnn_type == "GRU" or gnn_type == "LSTM") and "text" in obs_space self.use_ast = not ignoreLTL and ("GCN" in gnn_type) and "text" in obs_space self.gnn_type = gnn_type self.device = torch.device( "cuda" if torch.cuda.is_available() else "cpu") self.action_space = action_space self.dumb_ac = dumb_ac self.freeze_pretrained_params = freeze_ltl if self.freeze_pretrained_params: print("Freezing the LTL module.") self.env_model = getEnvModel(env, obs_space) # Define text embedding if self.use_progression_info: self.text_embedding_size = 32 self.simple_encoder = nn.Sequential( nn.Linear(obs_space["progress_info"], 64), nn.Tanh(), nn.Linear(64, self.text_embedding_size), nn.Tanh()).to(self.device) print( "Linear encoder Number of parameters:", sum(p.numel() for p in self.simple_encoder.parameters() if p.requires_grad)) elif self.use_text: self.word_embedding_size = 32 self.text_embedding_size = 32 if self.gnn_type == "GRU": self.text_rnn = GRUModel( obs_space["text"], self.word_embedding_size, 16, self.text_embedding_size).to(self.device) else: assert (self.gnn_type == "LSTM") self.text_rnn = LSTMModel( obs_space["text"], self.word_embedding_size, 16, self.text_embedding_size).to(self.device) print( "RNN Number of parameters:", sum(p.numel() for p in self.text_rnn.parameters() if p.requires_grad)) elif self.use_ast: hidden_dim = 32 self.text_embedding_size = 32 self.gnn = GNNMaker(self.gnn_type, obs_space["text"], self.text_embedding_size).to(self.device) print( "GNN Number of parameters:", sum(p.numel() for p in self.gnn.parameters() if p.requires_grad)) # Memory specific code. self.image_embedding_size = self.env_model.size() self.memory_rnn = nn.LSTMCell(self.image_embedding_size, self.semi_memory_size) self.embedding_size = self.semi_memory_size print("embedding size:", self.embedding_size) if self.use_text or self.use_ast or self.use_progression_info: self.embedding_size += self.text_embedding_size if self.dumb_ac: # Define actor's model self.actor = PolicyNetwork(self.embedding_size, self.action_space) # Define critic's model self.critic = nn.Sequential(nn.Linear(self.embedding_size, 1)) else: # Define actor's model self.actor = PolicyNetwork(self.embedding_size, self.action_space, hiddens=[64, 64, 64], activation=nn.ReLU()) # Define critic's model self.critic = nn.Sequential(nn.Linear(self.embedding_size, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, 1)) # Initialize parameters correctly self.apply(init_params)
''' # Trains the state transition model (has to be done before training the policy network) normalized_state_action_pairs = energy_system.stm_train_s_a_pairs_normalized normalized_subsequent_states = energy_system.stm_train_subsequent_states_normalized state_transition_model = StateTransitionModel([normalized_state_action_pairs.shape[1], 16, 32, 64, normalized_subsequent_states.shape[1]]) state_transition_model.train(normalized_state_action_pairs, normalized_subsequent_states, num_epochs=1000, pricing_model=pricing_model, plot_errors=True, load_weights=False) ''' # Trains the policy network with the trained state transition model state_transition_model = StateTransitionModel([ energy_system.num_state_variables + 1, 16, 32, 64, energy_system.num_state_variables ]) policy_network = PolicyNetwork([energy_system.num_state_variables, 16, 32, 1], energy_system) print("\nStarting training...") policy_network.train(num_epochs=1000, state_transition_model=state_transition_model, load_weights=False, load_weights_path='./stored_data/weights/policy_network') ''' # Compares the policy network trained under a chosen pricing model with other policies policy_network = PolicyNetwork([energy_system.num_state_variables, 16, 32, 1], energy_system) print("\nWith pricing model " + pricing_model + ":") energy_system.policy_type = 'rule_based' energy_system.run_test_simulation() energy_system.policy_type = 'random' energy_system.run_test_simulation() energy_system.policy_type = 'neural_network'