프로그래밍 공부

전체 글 700

카테고리 설명
프로그래밍 공부하는 블로그
  • ImageAiCon PP진행중Unreal ImageRetargeting 코드제작TCP방식으로 데이터 통신처리를 진행1. 서버커넥팅을 위한 TCP프로토콜 제작중...테스트 진행중.  간단한 구조도 GameMode -> GameServer Chack GameServer == NULL ? CreateCallServer.py Run : ConnectionServer; 쓰레드 형태로 AIControler를 생성. TCP통신으로 현재 뷰 타겟이미지의 데이터를 TCP로 DQN 알고리즘에 데이터를 넘긴다.그후에 DQN에서 결과값을 리턴한다. 객체의 Controler의 버퍼를 감지하여, 값을 받았을 경우 쓰레드 반환 후 메세지버퍼에 데이터를 기입. 쓰레드 반환시, DQN알고리즘에 해당 학습가중치의 결과값을 반환후 End..

  • ImageAiCon PP진행중Unreal ImageRetargeting 코드제작TCP방식으로 데이터 통신처리를 진행1. 서버커넥팅을 위한 TCP프로토콜 제작중... 간단한 구조도 GameMode -> GameServer Chack GameServer == NULL ? CreateCallServer.py Run : ConnectionServer; 쓰레드 형태로 AIControler를 생성. TCP통신으로 현재 뷰 타겟이미지의 데이터를 TCP로 DQN 알고리즘에 데이터를 넘긴다.그후에 DQN에서 결과값을 리턴한다. 객체의 Controler의 버퍼를 감지하여, 값을 받았을 경우 쓰레드 반환 후 메세지버퍼에 데이터를 기입. 쓰레드 반환시, DQN알고리즘에 해당 학습가중치의 결과값을 반환후 End한다. 학습이 완..

  • ImageAiCon PP진행중Unreal ImageRetargeting 코드제작뷰타겟에 따른 엑터의 머티리얼 변환 작업 진행 예정 작업Unreal ImageRetargeting 코드제작 언리얼 함수 상으로 지정된 카메라의 타겟뷰를 이미지값으로 저장 반환하는 방식이 존재함.TCP방식으로 데이터 통신처리를 진행TensorFlow를 사용하여 전달받은 이미지로 학습 알고리즘 연산.연산결과를 다시 언리얼로 전달하여 학습된 데이터를 갱신.4번과 3번을 반복학습결과확인 후 재학습 5와 6을 원하는 AI행동패턴이 나타날때까지 반복목표TensorFlow를 사용하여 알고리즘이 동작하는지 직접적인 확인을 진행.TensorFlow 를 사용하지 않고, 스스로의 C++코드로 알고리즘 함수 구현부를 직접 제작하여 사용하는것(파이썬..

  • ImageAiCon PP진행중Unreal의 ImageAI공부하기알고리즘 관련 강의 학습사전지식더보기https://inradestrt.tistory.com/695 $ \epsilon - Greedy $Q-Learning 및 강화학습을 적용할 때 보통 $ \epsilon - Greedy $ 라는 기법을 함께 적용한다. 에이전트가 항상 최대 Q값으로 행동하게 되면 데이터 수집과정에서 다양성이 감소하고 이로인해 최대 학습inradestrt.tistory.comhttps://inradestrt.tistory.com/696 Exploration & Exploitation Trade-Off강화 학습 알고리즘은 학습을 위한 데이터가 에이전트가 어떤 행동을 하느냐에 따라 달라진다. 따라서 강화학습 알고리즘은 데이터를 잘..

  • import tensorflow as tfimport numpy as npimport randomimport mathimport os"""# 설정값 지정"""# 학습에 필요한 설정값들을 선언합니다.epsilon = 1 # epsilon-Greedy 기법에 사용할 최초의 epsilon값epsilonMinimumValue = 0.001 # epsilon의 최소값 (이 값 이하로 Decay하지 않습니다)num_actions = 3 # 에이전트가 취할 수 있는 행동의 개수 - (좌로 움직이기, 가만히 있기, 우로 움직이기)num_epochs = 2000 # 학습에 사용할 반복횟수hidde..

  • DQN Q-Table을 업데이트하지 않고, 현재 상태값을 입력값으로 받고 현재 상태에서 취할 수 있는 행동들에 대한 Q값을 예측하는 인공신경망을 만들어서 사용하는 Q-NetWorks기법이다. Q-Networks를 학습시킬 때, 타겟 데이터는 Q-Learning알고리즘으로 구한 최적의 행동가치 함수값인 $ Q*(s_{t}, a_{t}) = R_{t+1} + \gamma  \underset{a+1}{max}Q(s_{t+1}, a_{t+1}) $ 으로 지정하고 상태값을 입력받아 신경망이 예측한 $ Q(s_{t}, a_{t}) $ 와 타겟 데이터의 평균제곱오차(MSE)으로 손실함수를 정의해서 최적화를 수행한다. $ MSE = \frac{1}{2n}\sum_{i=1}^{n}(Q^{*}(s_{t},a_{t}) - ..

작성일
2024. 7. 5. 03:12
작성자
WDmil
728x90

ImageAiCon PP

진행중

  1. Unreal ImageRetargeting 코드제작
    1. TCP방식으로 데이터 통신처리를 진행
      1. 1. 서버커넥팅을 위한 TCP프로토콜 제작중...
      2. 테스트 진행중.

Winsock.7z
0.00MB

 

컴파일 상 오류는 안남

 

간단한 구조도

 

GameMode -> GameServer Chack

 

GameServer == NULL ? CreateCallServer.py Run : ConnectionServer;

 

쓰레드 형태로 AIControler를 생성.

 

TCP통신으로 현재 뷰 타겟이미지의 데이터를 TCP로 DQN 알고리즘에 데이터를 넘긴다.

그후에 DQN에서 결과값을 리턴한다.

 

객체의 Controler의 버퍼를 감지하여, 값을 받았을 경우 쓰레드 반환 후 메세지버퍼에 데이터를 기입.

 

쓰레드 반환시, DQN알고리즘에 해당 학습가중치의 결과값을 반환후 End한다.

 

학습이 완료될 때 까지 반복.

 

GameMode에서 WinsockHelper를 통해 SOCKET을 생성한뒤 해당 SOCKET을 사용해서 쓰레드통신을 진행한다.

통신방식은 Winsock API를 활용하여 통신한다.

 

자세한 내용은 서버 구축과 커넥션 후 재정리 예정


진행 예정 작업

  1. Unreal ImageRetargeting 코드제작
    1. 언리얼 함수 상으로 지정된 카메라의 타겟뷰를 이미지값으로 저장 반환하는 방식이 존재함.
    2. TCP방식으로 데이터 통신처리를 진행
    3. TensorFlow를 사용하여 전달받은 이미지로 학습 알고리즘 연산.
    4. 연산결과를 다시 언리얼로 전달하여 학습된 데이터를 갱신.
    5. 4번과 3번을 반복
  2. 학습결과확인 후 재학습
  3.  5와 6을 원하는 AI행동패턴이 나타날때까지 반복

목표

  1. TensorFlow를 사용하여 알고리즘이 동작하는지 직접적인 확인을 진행.
  2. TensorFlow 를 사용하지 않고, 스스로의 C++코드로 알고리즘 함수 구현부를 직접 제작하여 사용하는것
    (파이썬만으로 k means clustering를 구현하였을 때, 구현객체가 C++의 연산처리속도를 따라잡지 못하는 상황이 있었음)
  3. UI관련 제작방식은 C#으로, 함수부는 DLL파일로 포팅하여 언리얼 엔진에 집어넣기.

완료된 작업

 

  1. Unreal의 ImageAI공부하기
    1. CNN알고리즘 다시 복기하기
    2. 알고리즘 선별(DQN)
    3. 알고리즘 관련 강의 학습

 

728x90

'작업사항 정리 > UnrealC++' 카테고리의 다른 글

UnrealC++ PP 20240712_14  (0) 2024.07.12
UnrealC++ PP 20240703_12  (0) 2024.07.03
UnrealC++ PP 20240701_11  (1) 2024.07.01
UnrealC++ PP 20240628_10  (0) 2024.06.28
UnrealC++ PP 20240626_9  (0) 2024.06.26
작성일
2024. 7. 3. 02:48
작성자
WDmil
728x90

ImageAiCon PP

진행중

  1. Unreal ImageRetargeting 코드제작
    1. TCP방식으로 데이터 통신처리를 진행
      1. 1. 서버커넥팅을 위한 TCP프로토콜 제작중...

대강개요

 

간단한 구조도

 

GameMode -> GameServer Chack

 

GameServer == NULL ? CreateCallServer.py Run : ConnectionServer;

 

쓰레드 형태로 AIControler를 생성.

 

TCP통신으로 현재 뷰 타겟이미지의 데이터를 TCP로 DQN 알고리즘에 데이터를 넘긴다.

그후에 DQN에서 결과값을 리턴한다.

 

객체의 Controler의 버퍼를 감지하여, 값을 받았을 경우 쓰레드 반환 후 메세지버퍼에 데이터를 기입.

 

쓰레드 반환시, DQN알고리즘에 해당 학습가중치의 결과값을 반환후 End한다.

 

학습이 완료될 때 까지 반복.

 

GameMode에서 WinsockHelper를 통해 SOCKET을 생성한뒤 해당 SOCKET을 사용해서 쓰레드통신을 진행한다.

통신방식은 Winsock API를 활용하여 통신한다.


진행 예정 작업

  1. Unreal ImageRetargeting 코드제작
    1. 언리얼 함수 상으로 지정된 카메라의 타겟뷰를 이미지값으로 저장 반환하는 방식이 존재함.
    2. TCP방식으로 데이터 통신처리를 진행
    3. TensorFlow를 사용하여 전달받은 이미지로 학습 알고리즘 연산.
    4. 연산결과를 다시 언리얼로 전달하여 학습된 데이터를 갱신.
    5. 4번과 3번을 반복
  2. 학습결과확인 후 재학습
  3.  5와 6을 원하는 AI행동패턴이 나타날때까지 반복

목표

  1. TensorFlow를 사용하여 알고리즘이 동작하는지 직접적인 확인을 진행.
  2. TensorFlow 를 사용하지 않고, 스스로의 C++코드로 알고리즘 함수 구현부를 직접 제작하여 사용하는것
    (파이썬만으로 k means clustering를 구현하였을 때, 구현객체가 C++의 연산처리속도를 따라잡지 못하는 상황이 있었음)
  3. UI관련 제작방식은 C#으로, 함수부는 DLL파일로 포팅하여 언리얼 엔진에 집어넣기.

완료된 작업

 

  1. Unreal의 ImageAI공부하기
    1. CNN알고리즘 다시 복기하기
    2. 알고리즘 선별(DQN)
    3. 알고리즘 관련 강의 학습

 

728x90

'작업사항 정리 > UnrealC++' 카테고리의 다른 글

UnrealC++ PP 20240712_14  (0) 2024.07.12
UnrealC++ PP 20240705_13  (0) 2024.07.05
UnrealC++ PP 20240701_11  (1) 2024.07.01
UnrealC++ PP 20240628_10  (0) 2024.06.28
UnrealC++ PP 20240626_9  (0) 2024.06.26
작성일
2024. 7. 1. 02:43
작성자
WDmil
728x90

ImageAiCon PP

진행중

  1. Unreal ImageRetargeting 코드제작
    1. 뷰타겟에 따른 엑터의 머티리얼 변환 작업

 

폴더 경로에 따른 CoreMinimal.h의 컴파일오류가 나타남 해결중


진행 예정 작업

  1. Unreal ImageRetargeting 코드제작
    1. 언리얼 함수 상으로 지정된 카메라의 타겟뷰를 이미지값으로 저장 반환하는 방식이 존재함.
    2. TCP방식으로 데이터 통신처리를 진행
    3. TensorFlow를 사용하여 전달받은 이미지로 학습 알고리즘 연산.
    4. 연산결과를 다시 언리얼로 전달하여 학습된 데이터를 갱신.
    5. 4번과 3번을 반복
  2. 학습결과확인 후 재학습
  3.  5와 6을 원하는 AI행동패턴이 나타날때까지 반복

목표

  1. TensorFlow를 사용하여 알고리즘이 동작하는지 직접적인 확인을 진행.
  2. TensorFlow 를 사용하지 않고, 스스로의 C++코드로 알고리즘 함수 구현부를 직접 제작하여 사용하는것
    (파이썬만으로 k means clustering를 구현하였을 때, 구현객체가 C++의 연산처리속도를 따라잡지 못하는 상황이 있었음)
  3. UI관련 제작방식은 C#으로, 함수부는 DLL파일로 포팅하여 언리얼 엔진에 집어넣기.

완료된 작업

 

  1. Unreal의 ImageAI공부하기
    1. CNN알고리즘 다시 복기하기
    2. 알고리즘 선별(DQN)
    3. 알고리즘 관련 강의 학습

 

728x90

'작업사항 정리 > UnrealC++' 카테고리의 다른 글

UnrealC++ PP 20240705_13  (0) 2024.07.05
UnrealC++ PP 20240703_12  (0) 2024.07.03
UnrealC++ PP 20240628_10  (0) 2024.06.28
UnrealC++ PP 20240626_9  (0) 2024.06.26
UnrealC++ PP 20240624_8  (0) 2024.06.24
작성일
2024. 6. 28. 03:05
작성자
WDmil
728x90

ImageAiCon PP

진행중

  1. Unreal의 ImageAI공부하기
    1. 알고리즘 관련 강의 학습

사전지식

더보기

결과물

https://colab.research.google.com/drive/1m3OxeUCt3XthHJDg3iZ2Rma6PpGXfIAx#scrollTo=69RjXx50pJoY

 

inflearn_CatchGame_DQN_example.ipynb의 사본

Colab notebook

colab.research.google.com

코렙이 아닌 로컬로 돌려본 결과. 리소스를 엄청 먹는다.

 

무작위로 떨어지는 빨간 네모를 파란 받침으로 받으면 Win 놓치면 Lose하는 방식

데이터의 가중치는 왼쪽 -1 가만히있기 0 오른쪽 1 로 3개의 결과노드가 존재.

 

중간의 128 -> 128의 히든노드로 데이터가 이동하여 결과물이 도출된다.

가장 최근의 50개 결과를 저장하여 현재 노드의 이동결과에 반영한다.


코렙에서는 np라이브러리의 버전이 맞지 않아서 오류가 발생한다. np라이브러리의 버전관리가 필요하다.

 

로컬로 돌리는게 더 쉬움.


 

진행 예정 작업

  1. Unreal ImageRetargeting 코드제작
    1. 언리얼 함수 상으로 지정된 카메라의 타겟뷰를 이미지값으로 저장 반환하는 방식이 존재함.
    2. TCP방식으로 데이터 통신처리를 진행
    3. TensorFlow를 사용하여 전달받은 이미지로 학습 알고리즘 연산.
    4. 연산결과를 다시 언리얼로 전달하여 학습된 데이터를 갱신.
    5. 4번과 3번을 반복
  2. 학습결과확인 후 재학습
  3.  5와 6을 원하는 AI행동패턴이 나타날때까지 반복

목표

  1. TensorFlow를 사용하여 알고리즘이 동작하는지 직접적인 확인을 진행.
  2. TensorFlow 를 사용하지 않고, 스스로의 C++코드로 알고리즘 함수 구현부를 직접 제작하여 사용하는것
    (파이썬만으로 k means clustering를 구현하였을 때, 구현객체가 C++의 연산처리속도를 따라잡지 못하는 상황이 있었음)
  3. UI관련 제작방식은 C#으로, 함수부는 DLL파일로 포팅하여 언리얼 엔진에 집어넣기.

완료된 작업

 

Unreal의 ImageAI공부하기

  1. CNN알고리즘 다시 복기하기
  2. 알고리즘 선별(DQN)

 

728x90

'작업사항 정리 > UnrealC++' 카테고리의 다른 글

UnrealC++ PP 20240703_12  (0) 2024.07.03
UnrealC++ PP 20240701_11  (1) 2024.07.01
UnrealC++ PP 20240626_9  (0) 2024.06.26
UnrealC++ PP 20240624_8  (0) 2024.06.24
UnrealC++ PP 20240621_7  (0) 2024.06.21
카테고리
작성일
2024. 6. 28. 03:01
작성자
WDmil
728x90

 

import tensorflow as tf
import numpy as np
import random
import math
import os

"""# 설정값 지정"""

# 학습에 필요한 설정값들을 선언합니다.
epsilon = 1                         # epsilon-Greedy 기법에 사용할 최초의 epsilon값
epsilonMinimumValue = 0.001         # epsilon의 최소값 (이 값 이하로 Decay하지 않습니다)
num_actions = 3                     # 에이전트가 취할 수 있는 행동의 개수 - (좌로 움직이기, 가만히 있기, 우로 움직이기)
num_epochs = 2000                   # 학습에 사용할 반복횟수
hidden_size = 128                   # 히든레이어의 노드 개수
maxMemory = 500                     # Replay Memory의 크기
batch_size = 50                     # 학습에 사용할 배치 개수
gridSize = 10                       # 에이전트가 플레이하는 게임 화면 크기 (10x10 grid)
state_size = gridSize * gridSize    # 게임 환경의 현재상태 (10x10 grid)
discount = 0.9                      # Discount Factor \gamma
learning_rate = 0.2                 # 러닝 레이트

"""# DQN 클래스 정의"""

# s와 e사이의 랜덤한 값을 리턴하는 유틸리티 함수를 정의합니다.
def randf(s, e):
  return (float(random.randrange(0, (e - s) * 9999)) / 10000) + s

def truncated_normal_intializer(stddev):
  return tf.keras.initializers.TruncatedNormal(mean=0.0, stddev=stddev, seed=None)

# tf.keras.Model을 이용해서 DQN 모델을 정의합니다.
class DQN(tf.keras.Model):
  def __init__(self):
    super(DQN, self).__init__()
    # 100(현재 상태 - 10x10 Grid) -> 128 -> 128 -> 3(예측된 각 행동의 Q값)
    self.hidden_layer_1 =  tf.keras.layers.Dense(hidden_size,
                                                activation='relu',
                                                kernel_initializer=truncated_normal_intializer(1.0 / math.sqrt(float(state_size))),
                                                bias_initializer=truncated_normal_intializer(0.01))
    self.hidden_layer_2 =  tf.keras.layers.Dense(hidden_size,
                                                activation='relu',
                                                kernel_initializer=truncated_normal_intializer(1.0 / math.sqrt(float(hidden_size))),
                                                bias_initializer=truncated_normal_intializer(0.01))
    self.output_layer =  tf.keras.layers.Dense(num_actions,
                                                activation=None,
                                                kernel_initializer=truncated_normal_intializer(1.0 / math.sqrt(float(hidden_size))),
                                                bias_initializer=truncated_normal_intializer(0.01))

  def call(self, x):
    H1_output = self.hidden_layer_1(x)
    H2_output = self.hidden_layer_2(H1_output)
    output_layer = self.output_layer(H2_output)

    return tf.squeeze(output_layer)

"""# 손실함수 정의"""

# MSE 손실 함수를 정의합니다.
def mse_loss(y_pred, y):
  return tf.reduce_sum(tf.square(y-y_pred)) / (2*batch_size)  # MSE 손실 함수

# 옵티마이저를 정의합니다.
optimizer = tf.optimizers.SGD(learning_rate)

# 최적화를 위한 function을 정의합니다.
def train_step(model, x, y):
  with tf.GradientTape() as tape:
    y_pred = model(x)
    loss = mse_loss(y_pred, y)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

# DQN 모델을 선언합니다.
DQN_model = DQN()

"""# CatchGame Environment 설정"""

# CatchGame을 수행하는 Environment를 구현합니다.
class CatchEnvironment():
  # 상태의 초기값을 지정합니다.
  def __init__(self, gridSize):
    self.gridSize = gridSize
    self.state_size = self.gridSize * self.gridSize
    self.state = np.empty(3, dtype = np.uint8)

  # 관찰 결과를 리턴합니다.
  def observe(self):
    canvas = self.drawState()
    canvas = np.reshape(canvas, (-1,self.state_size))
    return canvas.astype('float32')

  # 현재 상태(fruit, basket)를 화면에 출력합니다.
  def drawState(self):
    canvas = np.zeros((self.gridSize, self.gridSize))
    # fruit를 화면에 그립니다.
    canvas[self.state[0]-1, self.state[1]-1] = 1
    # basket을 화면에 그립니다.
    canvas[self.gridSize-1, self.state[2] -1 - 1] = 1
    canvas[self.gridSize-1, self.state[2] -1] = 1
    canvas[self.gridSize-1, self.state[2] -1 + 1] = 1
    return canvas

  # 게임을 초기 상태로 리셋합니다.
  def reset(self):
    initialFruitColumn = random.randrange(1, self.gridSize + 1)
    initialBucketPosition = random.randrange(2, self.gridSize + 1 - 1)
    self.state = np.array([1, initialFruitColumn, initialBucketPosition])
    return self.getState()

  # 현재 상태를 불러옵니다.
  def getState(self):
    stateInfo = self.state
    fruit_row = stateInfo[0]
    fruit_col = stateInfo[1]
    basket = stateInfo[2]
    return fruit_row, fruit_col, basket

  # 에이전트가 취한 행동에 대한 보상을 줍니다.
  def getReward(self):
    fruitRow, fruitColumn, basket = self.getState()
    # 만약 fruit가 바닥에 닿았을 때
    if (fruitRow == self.gridSize - 1):
      # basket이 fruit을 받아내면 1의 reward를 줍니다.
      if (abs(fruitColumn - basket) <= 1):
        return 1
      # fruit를 받아내지 못하면 -1의 reward를 줍니다.
      else:
        return -1
    # fruit가 바닥에 닿지 않은 중립적인 상태는 0의 reward를 줍니다.
    else:
      return 0

  # 게임이 끝났는지를 체크합니다.(fruit가 바닥에 닿으면 한게임이 종료됩니다.)
  def isGameOver(self):
    if (self.state[0] == self.gridSize - 1):
      return True
    else:
      return False

  # action(좌로 한칸 이동, 제자리, 우로 한칸이동)에 따라 basket의 위치를 업데이트합니다.
  def updateState(self, action):
    move = 0
    if (action == 0):
      move = -1
    elif (action == 1):
      move = 0
    elif (action == 2):
      move = 1
    fruitRow, fruitColumn, basket = self.getState()
    newBasket = min(max(2, basket + move), self.gridSize - 1) # min/max는 basket이 grid밖으로 벗어나는것을 방지합니다.
    fruitRow = fruitRow + 1  # fruit는 매 행동을 취할때마다 1칸씩 아래로 떨어집니다.
    self.state = np.array([fruitRow, fruitColumn, newBasket])

  # 행동을 취합니다. 0 : 왼쪽으로 이동, 1 : 가만히 있기, 2 : 오른쪽으로 이동
  def act(self, action):
    self.updateState(action)
    reward = self.getReward()
    gameOver = self.isGameOver()
    return self.observe(), reward, gameOver, self.getState()

"""# Replay Memory 설정"""

# Replay Memory를 class로 정의합니다.
class ReplayMemory:
  def __init__(self, gridSize, maxMemory, discount):
    self.maxMemory = maxMemory
    self.gridSize = gridSize
    self.state_size = self.gridSize * self.gridSize
    self.discount = discount
    self.inputState = np.empty((self.maxMemory, 100), dtype = np.float32)
    self.actions = np.zeros(self.maxMemory, dtype = np.uint8)
    self.nextState = np.empty((self.maxMemory, 100), dtype = np.float32)
    self.gameOver = np.empty(self.maxMemory, dtype = np.bool)
    self.rewards = np.empty(self.maxMemory, dtype = np.int8)
    self.count = 0
    self.current = 0

  # 경험을 Replay Memory에 저장합니다.
  def remember(self, currentState, action, reward, nextState, gameOver):
    self.actions[self.current] = action
    self.rewards[self.current] = reward
    self.inputState[self.current, ...] = currentState
    self.nextState[self.current, ...] = nextState
    self.gameOver[self.current] = gameOver
    self.count = max(self.count, self.current + 1)
    self.current = (self.current + 1) % self.maxMemory

  def getBatch(self, DQN_model, batch_size, num_actions, state_size):
    # 취할 수 있는 가장 큰 배치 사이즈를 선택합니다. (학습 초기에는 batch_size만큼의 기억이 없습니다.)
    memoryLength = self.count
    chosenBatchSize = min(batch_size, memoryLength)

    # 인풋 데이터와 타겟데이터를 선언합니다.
    inputs = np.zeros((chosenBatchSize, state_size))
    targets = np.zeros((chosenBatchSize, num_actions))

    # 배치안의 값을 설정합니다.
    for i in range(chosenBatchSize):
      # 배치에 포함될 기억을 랜덤으로 선택합니다.
      randomIndex = random.randrange(0, memoryLength)
      # 현재 상태와 Q값을 불러옵니다.
      current_inputState = np.reshape(self.inputState[randomIndex], (1, 100))
      target = DQN_model(current_inputState).numpy()

      # 현재 상태 바로 다음 상태를 불러오고 다음 상태에서 취할수 있는 가장 큰 Q값을 계산합니다.
      current_nextState = np.reshape(self.nextState[randomIndex], (1, 100))
      nextStateQ = DQN_model(current_nextState).numpy()
      nextStateMaxQ = np.amax(nextStateQ)
      # 만약 게임오버라면 reward로 Q값을 업데이트하고
      if (self.gameOver[randomIndex] == True):
        target[self.actions[randomIndex]] = self.rewards[randomIndex]
      # 게임오버가 아니라면 타겟 Q값(최적의 Q값)을 아래 수식을 이용해서 계산합니다.
      # Q* = reward + discount(gamma) * max_a' Q(s',a')
      else:
        target[self.actions[randomIndex]] = self.rewards[randomIndex] + self.discount * nextStateMaxQ

      # 인풋과 타겟 데이터에 값을 지정합니다.
      inputs[i] = current_inputState
      targets[i] = target

    return inputs.astype('float32'), targets.astype('float32')

print("트레이닝을 시작합니다.")

# 게임 플레이 환경을 선언합니다.
env = CatchEnvironment(gridSize)

# Replay Memory를 선언합니다.
memory = ReplayMemory(gridSize, maxMemory, discount)

winCount = 0

for i in range(num_epochs+1):
  # 환경을 초기화합니다.
  err = 0
  env.reset()

  isGameOver = False

  # 최초의 상태를 불러옵니다.
  currentState = env.observe()

  while (isGameOver != True):
    action = -9999  # Q값을 초기화합니다.
    # epsilon-Greedy 기법에 따라 랜덤한 행동을 할지 최적의 행동을 할지를 결정합니다.
    epsilon
    if (randf(0, 1) <= epsilon):
      # epsilon 확률만큼 랜덤한 행동을 합니다.
      action = random.randrange(0, num_actions)
    else:
      # (1-epsilon) 확률만큼 최적의 행동을 합니다.
      # 현재 상태를 DQN의 인풋으로 넣어서 예측된 최적의 Q(s,a)값들을 리턴받습니다.
      q = DQN_model(currentState).numpy()
      # Q(s,a)가 가장 높은 행동을 선택합니다.
      action = q.argmax()

    # epsilon값을 0.9999만큼 Decay합니다.
    if (epsilon > epsilonMinimumValue):
      epsilon = epsilon * 0.999

    # 에이전트가 행동을 하고 다음 보상과 다음 상태에 대한 정보를 리턴 받습니다.
    nextState, reward, gameOver, stateInfo = env.act(action)

    # 만약 과일을 제대로 받아냈다면 승리 횟수를 1 올립니다.
    if (reward == 1):
      winCount = winCount + 1

    # 에이전트가 수집한 정보를 Replay Memory에 저장합니다.
    memory.remember(currentState, action, reward, nextState, gameOver)

    # 현재 상태를 다음 상태로 업데이트하고 GameOver유무를 체크합니다.
    currentState = nextState
    isGameOver = gameOver

    # Replay Memory로부터 학습에 사용할 Batch 데이터를 불러옵니다.
    inputs, targets = memory.getBatch(DQN_model, batch_size, num_actions, state_size)

    # 최적화를 수행하고 손실함수를 리턴받습니다.
    _, loss_print = train_step(DQN_model, inputs, targets), mse_loss(DQN_model(inputs), targets)
    err = err + loss_print

  print("반복(Epoch): %d, 에러(err): %.4f, 승리횟수(Win count): %d, 승리비율(Win ratio): %.4f" % (i, err, winCount, float(winCount)/float(i+1)*100))
# 학습이 모두 끝나면 파라미터를 지정된 경로에 저장합니다.
print("트레이닝 완료")

"""# 학습된 에이전트의 플레이결과 시각화하기"""

# Commented out IPython magic to ensure Python compatibility.
# %matplotlib

from IPython import display
import matplotlib.patches as patches
import pylab as pl
import time
import tensorflow as tf
import os

# 설정값들을 정의합니다.
gridSize = 10
maxGames = 30
env = CatchEnvironment(gridSize)
winCount = 0
loseCount = 0
numberOfGames = 0

# 화면을 그리기 위한 설정들을 정의합니다.
ground = 1
plot = pl.figure(figsize=(12,12))
axis = plot.add_subplot(111, aspect='equal')
axis.set_xlim([-1, 12])
axis.set_ylim([0, 12])

# 현재 상태를 그리기 위한 drawState 함수를 정의합니다.
def drawState(fruitRow, fruitColumn, basket, gridSize):
  # 과일이 몇번째 세로축에 있는지 정의합니다.
  fruitX = fruitColumn
  # 과일이 몇번째 가로축에 있는지 정의합니다.
  fruitY = (gridSize - fruitRow + 1)
  # 승리 횟수, 패배 횟수, 전체 게임 횟수를 화면 상단에 출력합니다.
  statusTitle = "Wins: " + str(winCount) + "  Losses: " + str(loseCount) + "  TotalGame: " + str(numberOfGames)
  axis.set_title(statusTitle, fontsize=30)
  for p in [
    # 배경의 위치를 지정합니다.
    patches.Rectangle(
        ((ground - 1), (ground)), 11, 10,
        facecolor="#000000"      # Black
    ),
    # 바구니의 위치를 지정합니다.
    patches.Rectangle(
        (basket - 1, ground), 2, 0.5,
        facecolor="#FF0000"     # Red
    ),
    # 과일의 위치를 지정합니다.
    patches.Rectangle(
        (fruitX - 0.5, fruitY - 0.5), 1, 1,
        facecolor="#0000FF"       # Blue
    ),
    ]:
      axis.add_patch(p)
  display.clear_output(wait=True)
  display.display(pl.gcf())

# maxGames 횟수만큼 게임을 플레이합니다.
while (numberOfGames < maxGames):
  numberOfGames = numberOfGames + 1

  # 최초의 상태를 정의합니다.
  isGameOver = False
  fruitRow, fruitColumn, basket = env.reset()
  currentState = env.observe()
  drawState(fruitRow, fruitColumn, basket, gridSize)

  while (isGameOver != True):
    # 현재 상태를 DQN의 입력값으로 넣고 구한 Q값중 가장 큰 Q값을 갖는 행동을 취합니다.
    q = DQN_model(currentState).numpy()
    action = q.argmax()

    # 행동을 취하고 다음 상태로 넘어갑니다.
    nextState, reward, gameOver, stateInfo = env.act(action)
    fruitRow = stateInfo[0]
    fruitColumn = stateInfo[1]
    basket = stateInfo[2]

    # 과일을 받아내면 winCount를 1 늘리고 과일을 받아내지 못하면 loseCount를 1 늘립니다.
    if (reward == 1):
      winCount = winCount + 1
    elif (reward == -1):
      loseCount = loseCount + 1

    currentState = nextState
    isGameOver = gameOver
    drawState(fruitRow, fruitColumn, basket, gridSize)
    # 다음 행동을 취하기 전에 0.05초의 일시정지를 줍니다.
    time.sleep(0.05)

# 최종 출력결과 이미지를 하나로 정리합니다.
display.clear_output(wait=True)

리소스 먹는게 어마어마하다.

https://colab.research.google.com/drive/1m3OxeUCt3XthHJDg3iZ2Rma6PpGXfIAx?usp=sharing

 

728x90

'알고리즘' 카테고리의 다른 글

DQN(Deep - Q - Networks)  (0) 2024.06.28
Exploration & Exploitation Trade-Off  (0) 2024.06.27
$ \epsilon - Greedy $  (0) 2024.06.27
Discrete Action Space & Continuous Action Space  (0) 2024.06.26
On-Policy & Off-Policy  (0) 2024.06.26
카테고리
작성일
2024. 6. 28. 00:24
작성자
WDmil
728x90

DQN

 

Q-Table을 업데이트하지 않고, 현재 상태값을 입력값으로 받고 현재 상태에서 취할 수 있는 행동들에 대한 Q값을 예측하는 인공신경망을 만들어서 사용하는 Q-NetWorks기법이다.

 

Q-Networks를 학습시킬 때, 타겟 데이터는 Q-Learning알고리즘으로 구한 최적의 행동가치 함수값인 $ Q*(s_{t}, a_{t}) = R_{t+1} + \gamma  \underset{a+1}{max}Q(s_{t+1}, a_{t+1}) $ 으로 지정하고 상태값을 입력받아 신경망이 예측한 $ Q(s_{t}, a_{t}) $ 와 타겟 데이터의 평균제곱오차(MSE)으로 손실함수를 정의해서 최적화를 수행한다.

 

$ MSE = \frac{1}{2n}\sum_{i=1}^{n}(Q^{*}(s_{t},a_{t}) - Q(s_{t}, a_{t}))^{2} $

$ MSE = \frac{2n}{1}\sum_{i=1}^{n}(R_{t+1} + \gamma \underset{a+1}{max}Q(s_{t+1}, a_{t+1}) - Q(s_{t}, a_{t}))^{2} $

 

일반적인 ANN구조처럼 손실 함수에 대한 옵티마이저를 선언하고 학습을 진행하면 적절한 Q값을 예측하는 Q-Networks를 학습시킬 수 있다.

 


$ \epsilon  - Greedy $

 

Q-Learning 및 강화학습을 적용할 때 보통 $ \epsilon - Greedy $ 라는 기법을 함께 적용한다.

 

에이전트가 항상 최대 Q값으로 행동하게 되면 데이터 수집과정에서 다양성이 감소하고 이로인해 최대 학습 결과가 Local Optima에 빠질 확률이 높아진다.

 

따라서 $ \epsilon - Greedy $ 기법은 에이전트가 $ \epsilon  $ 확률로 최적의 행동이 아닌 랜덤한 행동을 하게 하고, 다시 $ ( 1 - \epsilon ) $ 확률로 최적의 행동을 하게 함으로써 에이전트가 다양한 상태를 경험하고 수집할 수 있게 한다.

 

결과적으로 학습이 끝난 후에 더 좋은 성능을 발휘할 수 있다. 하지만 계속해서 랜덤한 행동을 하도록 할 수는 없음으로 학습 초반에는 $ \epsilon  $ 값을 크게 설정했다가 학습이 진행될 수록 점차 $ \epsilon  $ 값을 감소시켜 준다.

 

$ \pi(a|s) = \left\{\begin{matrix}
1 - \epsilon  & ifa^{*} = \underset{a\epsilon A}{argmaxA(s, a)} \\
 &  \epsilon \\
\end{matrix}\right. $

 


DQN(Deep- Q-Networks)은 딥마인드 사에서 창안한 강화학습을 위한 인공 신경망 구조로써 기존에 제안된 Q-Networks와 딥러닝 을 결합한 기법이다.

 

사전지식 없이 오직 게임 화면만을 보고 학습을 진행해서, 학습을 진행함.

 

기존의 Q-Networks에서 2가지를 개선

 

  1. 기존의 Q-Networks은 얕은층의 ANN구조를 사용하지만, DQN은 깊은층의 CNN구조를 사용
  2. 인간의 해마(Hippocampus)에서 영감을 받아 리플레이 메모리(Replay Memory)라는 기법을 사용했고, 이를 통해 효율적인 강화학습이 가능하도록 만듬

 


리플레이 메모리(Replay Memory)

 

리플레이 메모리 기법이란, 기존의 강화학습과 다르게 에이전트가 흭득하는 순차적인 경험데이터를 이용해서 학습을 진행헀습니다.

 

하지만, 이는 에이전트가 취한 이전 행동에 따라 수집되는 데이터의 형태가 일정한 패턴으로 고정되는 문제가 있다.

 

리플레이 메모리 기법은 이를 방지하기 위해 리플레이 메모리라는 일종의 경험 저장소에 에이전트가 수집한 경험데이터를 저장한다.

 

리플레이 메모리에 저장된 랜덤 샘플링을 통해 데이터를 추출해서, 이를 학습에 사용함으로써 에이전트가 특정한 패턴에 대한 편견 없이 학습할 수 있도록 도와준다.

728x90

'알고리즘' 카테고리의 다른 글

TensorFlow DQN Agent 구현  (0) 2024.06.28
Exploration & Exploitation Trade-Off  (0) 2024.06.27
$ \epsilon - Greedy $  (0) 2024.06.27
Discrete Action Space & Continuous Action Space  (0) 2024.06.26
On-Policy & Off-Policy  (0) 2024.06.26