<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Pragmatic Romantist</title>
    <link>https://pipe0512.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 24 May 2026 06:02:47 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>pipes0512</managingEditor>
    <item>
      <title>[HTTP] URI와 웹 브라우저 요청 흐름</title>
      <link>https://pipe0512.tistory.com/132</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;URI(Uniform Resource Identifier)&lt;/h1&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;1204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/60knm/btsHqn1DyvW/MNkKBrYWXKrofokx8sWUEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/60knm/btsHqn1DyvW/MNkKBrYWXKrofokx8sWUEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/60knm/btsHqn1DyvW/MNkKBrYWXKrofokx8sWUEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F60knm%2FbtsHqn1DyvW%2FMNkKBrYWXKrofokx8sWUEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;1204&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;1204&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URN과 URL은 URI에 포함되는 개념이다.&lt;/li&gt;
&lt;li&gt;URN(Uniform Resource Name): 리소스에 이름을 부여&lt;/li&gt;
&lt;li&gt;URL(Uniform Resource Locator): 리소스가 있는 위치를 지정&lt;/li&gt;
&lt;li&gt;URN은 거의 사용하지 않으므로 URI를 URL과 같은 의미로 보아도 크게 무리가 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구조&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;scheme://[userinfo@]host[:port][/path][?query][#fragment] &lt;br /&gt;https://www.google.com:443/search?q=hello&amp;amp;hl=ko&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로토콜(https)&lt;/li&gt;
&lt;li&gt;호스트명(&lt;a href=&quot;http://www.google.com&quot;&gt;www.google.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;포트번호(443) - https의 기본포트는 443으로, 보통 생략되어있다.&lt;/li&gt;
&lt;li&gt;Path(/search)&lt;/li&gt;
&lt;li&gt;쿼리 파라미터(q=hello&amp;amp;hl=ko)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Scheme&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주로 프로토콜 사용&lt;/li&gt;
&lt;li&gt;프로토콜: 어떤 방식으로 자원에 접근할 것인가 하는 약속 규칙
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;http, https, ftp 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;http는 80포트 https는 443 포트를 주로 사용, 포트는 생략 가능&lt;/li&gt;
&lt;li&gt;https 는 http에 보안 추가 (HTTP Secure)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Userinfo&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URL에 사용자정보를 포함해서 인증&lt;/li&gt;
&lt;li&gt;거의 사용하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Host&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호스트명&lt;/li&gt;
&lt;li&gt;도메인명 또는 IP 주소를 직접 사용가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PORT&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로 생략, 생략시 http는 80 https는 443&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Path&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스 경로, 계층적 구조&lt;/li&gt;
&lt;li&gt;ex:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;/home/file1.jpg&lt;/li&gt;
&lt;li&gt;/members&lt;/li&gt;
&lt;li&gt;/members/100, /items/iphone12&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Query&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;key=value 형태&lt;/li&gt;
&lt;li&gt;?로 시작, &amp;amp;로 추가 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex: ?keyA=valueA&amp;amp;keyB=valueB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;query parameter, query string 등으로 불림, 웹서버에 제공하는 파라미터, 문자 형태&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fragment&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;html 내부 북마크 등에 사용&lt;/li&gt;
&lt;li&gt;서버에 전송하는 정보 아님&lt;/li&gt;
&lt;li&gt;거의 사용하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;웹 브라우저 요청 흐름&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 브라우저에서 URL을 입력하여 서버에 요청을 보내는 상황을 생각해보자.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;GET /search?q=hello&amp;amp;hl=ko HTTP/1.1 &lt;br /&gt;Host: www.google.com&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 브라우저에서 위와같은 HTTP 요청 메시지를 생성할 것이고 이는 소켓 라이브러리를 통해 TCP/IP 계층으로 전달되고, TCP 세그먼트와 IP 패킷으로 wrapping되어 네트워크 인터페이스에서 인터넷을 통해 서버로 전달될 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;HTTP/1.1 200 OK&lt;br /&gt;Content-Type: text/html;charset=UTF-8&lt;br /&gt;Content-Length: 3423 &lt;br /&gt;&amp;lt;html&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;lt;body&amp;gt;...&amp;lt;/body&amp;gt; &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이후 서버에서는 위와같은 HTTP 응답 메시지를 응답 패킷에 담아 클라이언트의 웹 브라우저로 보낼 것이다.&lt;/li&gt;
&lt;li&gt;이러한 응답 메시지를 클라이언트의 웹 브라우저에서는 렌더링하여 웹 브라우저 화면에 출력할 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #222222;&quot; data-ke-size=&quot;size16&quot;&gt;공부자료: 모든 개발자를 위한 HTTP 웹 기본 지식 - 김영한&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;reaction-131&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>CS/Network</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/132</guid>
      <comments>https://pipe0512.tistory.com/132#entry132comment</comments>
      <pubDate>Thu, 16 May 2024 21:00:41 +0900</pubDate>
    </item>
    <item>
      <title>[HTTP] 인터넷 네트워크</title>
      <link>https://pipe0512.tistory.com/131</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;IP(Internet Protocol)&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;역할&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지정한 IP 주소(IP Address)에 데이터 전달&lt;/li&gt;
&lt;li&gt;패킷(Packet: Package + bucket)이라는 통신 단위로 데이터 전달&lt;br /&gt;: IP 패킷 정보에는 출발지 IP, 목적지 IP 등이 들어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;한계&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비연결성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;패킷을 받을 대상이 없거나 서비스 불능 상태여도 패킷 전송&lt;br /&gt;: 정확히 패킷이 전달되었는지 알 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;비신뢰성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중간에 패킷이 사라지면? (중간에 어떤 노드에서 패킷이 소실된다면?)&lt;br /&gt;: 정확히 패킷이 전달되었는지 알 수 없다.&lt;/li&gt;
&lt;li&gt;패킷이 순서대로 안오면?&lt;br /&gt;: 패킷을 먼저보낸다고 먼저 받는 것이 아닐 수 있는데(이동하는 경로가 다를 수 있기 때문), 이때 패킷을 받는 입장에서 순서를 알 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;TCP, UDP&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;인터넷 프로토콜 스택의 4계층&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;높은 계층에서 낮은 계층 순서&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;애플리케이션 계층(Application Layer) - HTTP, FTP&lt;/li&gt;
&lt;li&gt;전송 계층(Transport Layer) - TCP, UDP&lt;/li&gt;
&lt;li&gt;인터넷 계층 - IP&lt;/li&gt;
&lt;li&gt;네트워크 인터페이스 계층 - 랜카드, 랜드라이버&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;메시지 통신과정 예시&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;웹 브라우저나 게임과같은 애플리케이션에서 메시지를 생성하고소켓 라이브러리를 통해서 TCP계층에 메시지를 전달한다.&lt;/li&gt;
&lt;li&gt;TCP 계층에서 TCP 정보를 생성하고 앞서 받은 메시지 데이터를 포함하는 TCP 세그먼트를 IP 계층에 전달한다.&lt;/li&gt;
&lt;li&gt;IP 계층에서 TCP 세그먼트를 포함한 IP 패킷을 생성하여 네트워크 인터페이스(LAN 카드)에 전달한다.&lt;/li&gt;
&lt;li&gt;네트워크 인터페이스에서 패킷을 Ethernet frame으로 감싸서 인터넷을 통해 서버로 전달한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최종적으로 보내지는 wrapper의 형태는 가장 바깥쪽부터 Ethernet frame - IP 패킷 - TCP 세그먼트 - HTTP 메시지 이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TCP/IP 패킷 정보&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP 세그먼트에는 출발지 PORT, 목적지 PORT, 전송 제어, 순서, 검증 정보 등이 있다.&lt;/li&gt;
&lt;li&gt;TCP 세그먼트는 출발지 IP, 목적지 IP 등의 정보를 가지고 있는 IP 패킷으로 감싸져있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TCP 특징&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 전송 제어 프로토콜(Transmission Control Protocol)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연결 지향 - TCP 3 way handshake (가상 연결)&lt;/li&gt;
&lt;li&gt;데이터 전달 보증&lt;/li&gt;
&lt;li&gt;순서 보장&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TCP 3 way handshake&lt;/h3&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8WNjn/btsHovYEsJ0/M2D0RzwDLedqlKceOHku41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8WNjn/btsHovYEsJ0/M2D0RzwDLedqlKceOHku41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8WNjn/btsHovYEsJ0/M2D0RzwDLedqlKceOHku41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8WNjn%2FbtsHovYEsJ0%2FM2D0RzwDLedqlKceOHku41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;SYN&lt;br /&gt;: 클라이언트가 서버에 SYN 패킷을 보내 연결 요청을 한다.&lt;br /&gt;(데이터 전송을 시작하기 원하는 클라이언트의 초기 시퀀스 번호)&lt;/li&gt;
&lt;li&gt;SYN + ACK&lt;br /&gt;: 서버가 클라이언트의 SYN 패킷을 받고 연결을 수락하는 SYN-ACK 패킷으로 응답한다.&lt;br /&gt;(서버의 초기 시퀀스 번호, 클라이언트의 시퀀스 번호+1)&lt;/li&gt;
&lt;li&gt;ACK&lt;br /&gt;: 클라이언트는 서버의 SYN-ACK에 대한 ACK 패킷을 보내 연결확인을 완료한다.&lt;br /&gt;(서버의 시퀀스 번호+1)&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 과정으로 연결여부 확인&lt;/li&gt;
&lt;li&gt;cf) 최근에는 최적화되어 ACK를 보낼 때 데이터를 보낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 전달 보증&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트가 보낸 데이터가 서버에 잘 도착했을 경우 서버는 클라이언트에 데이터를 잘 받았다는 응답을 다시 보낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;순서 보장&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트가 패킷1, 패킷2, 패킷3 순서로 전송했는데, 서버거 패킷1, 패킷3, 패킷2 순서로 도착했을 경우, 서버는 클라이언트에게 패킷2부터 다시 보내라는 응답을 보낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;UDP 특징&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 사용자 데이터그램 프로토콜(User Datagram Protocol)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하얀 도화지에 비유(기능이 거의 없음)&lt;/li&gt;
&lt;li&gt;TCP에 존재하는 연결지향, 데이터 전달 보증, 순서 보장 기능이 없음&lt;/li&gt;
&lt;li&gt;단순하고 빠름&lt;/li&gt;
&lt;li&gt;IP와 거의 비슷하며 PORT와 체크섬 정도만 추가된다.&lt;/li&gt;
&lt;li&gt;애플리케이션에서 추가 작업 필요
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP는 수정이 불가하므로 최근에는 UDP를 최적화하여 http3에 사용하는 중이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;PORT&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앞서 TCP 세그먼트에서 출발지 PORT, 목적지 PORT를 포함한다고 했었다.&lt;/li&gt;
&lt;li&gt;만약 내 컴퓨터에서 게임과 웹서핑을 같이 하고있다면 이를 PORT로 구분한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP가 아파트라면 PORT는 몇호인지를 나타낸다고 보면됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;0 ~ 65535 할당가능&lt;/li&gt;
&lt;li&gt;0 ~ 1023: 잘 알려진 포트, 사용하지 않는 것이 좋음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FTP - 20, 21&lt;/li&gt;
&lt;li&gt;TELNET - 23&lt;/li&gt;
&lt;li&gt;HTTP - 80&lt;/li&gt;
&lt;li&gt;HTTPS - 443&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;DNS&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 도메인 네임 시스템(Domain Name System)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP는 기억하기도 어렵고 변경될 수 있다.&lt;/li&gt;
&lt;li&gt;나만의 도메인 명 (ex: google.com)을 DNS서버에 등록해두면, 클라이언트가 도메인 명을 입력하면 나의 IP로 접속한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IP가 변경될 경우 변경된 나의 IP를 원래 도메인에 등록해두면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부자료: 모든 개발자를 위한 HTTP 웹 기본 지식 - 김영한&lt;/p&gt;</description>
      <category>CS/Network</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/131</guid>
      <comments>https://pipe0512.tistory.com/131#entry131comment</comments>
      <pubDate>Tue, 14 May 2024 00:24:22 +0900</pubDate>
    </item>
    <item>
      <title>[Monte Carlo methods - 4] Off-Policy Monte Carlo</title>
      <link>https://pipe0512.tistory.com/130</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Off-policy Monte Carlo&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Off-policy strategy&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Off-policy 에서는, &lt;span style=&quot;color: #ee2323;&quot;&gt;Exploratory policy와 Target policy를 분리&lt;/span&gt;하고 각각 다른 policies를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Exploratory policy&lt;/span&gt; ($b(a|s)$)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Exploratory policy는 Task를 수행하면서 State, Action, Reward를 포함한 Experience(tarjectory)를 수집한다. Experience들은 Target policy를 학습시키는데 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;$$ S_0, A_0, R_1, S_1, A_1, ..., R_T $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Target policy&lt;/span&gt; ($\pi(a|s)$)&lt;br /&gt;: Optimal policy를 찾기 위해서 실질적으로 개선되는 Policy이다. Exploratory policy를 통해 수집된 Experience를 통해서 update된다. -&amp;gt; Off-policy로 불리는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;$$ \pi(s) \gets \arg\max_a Q(s,a) $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연한 말일수도 있지만, Off-policy가 제대로 작동하기 위해서는 Exploratory policy는 Target policy의 모든 action을 cover해야한다. 이 조건이 만족하지 않는다면, Exploatory Policy가 행하지 않는 Action의 Q-value는 Target Policy에서 update되지 않을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ if $\pi(a|s) &amp;gt; 0, \quad then \quad b(a|s) &amp;gt; 0 $$&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Problem&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Exploratory policy의 returns를 수집하기 때문에 우리가 그것들일 average하게된다면, 우리는 &lt;span style=&quot;color: #ee2323;&quot;&gt;target policy가 아닌 exploratory policy에 대한 q-value를 근사하는 것이된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ E_b[G_t|s_t=s, A_t = a] = q_b(s,a) $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해서는 Exploratory policy의 returns에 뭔가를 해서 그들의 average가 target policy를 represent하도록 해야한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Importance sampling&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Exploratory policy의 returns가 target policy를 represnet하도록 하기위해 &lt;span style=&quot;color: #ee2323;&quot;&gt;Importance sampling&lt;/span&gt;이라는 통계적인 기법을 사용한다. 어떤 시점 t에서 행할 수 있는 Action에 대해서 Target policy하에 해당 Action을 행할 확률에서 Exploratory policy하에 해당 Action을 행할 확률을 나눈 값을, 행할 수 있는 모든 Action에 대해 순차적으로 곱한 값을 $W_t$라고 한다. 이를 Exploratory policy하에서 구한 $G_t$에 곱하여 조정된 return을 사용함으로써, Target policy에 대한 근사를 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ W_t = \prod_{k=t}^{T-1}{\pi(A_k|s_k)\over b(A_k|s_k)} \qquad E[W_tG_t|S_t = s] = v_\pi(s)$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Update Rule&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 방법은 $(s,a)$마다, 우리는 observed returns들의 list를 보관하여 $Q(s,a)$를 update 해야할 때마다 average를 다시 계산했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ [G_1, G_2, ..., G_N] \qquad Q(s,a) \gets {1\over N}\sum_{k=1}^N G_k$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법은 returns를 저장해야해야하고 매번 average를 계산하는 것을 반복해야하므로 &lt;span style=&quot;color: #ee2323;&quot;&gt;비효율적&lt;/span&gt;이다. 따라서 위 방법 대신에 On-Policy mc 2번째 실습에서 사용했던 constant alpha Monte carlo를 사용할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ Q(s,a) \gets Q(s,a) + {W_t \over C(s,a)}[G-Q(s,a)] \qquad \alpha = W_t/C(s,a)$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Importance sampling 값이 &lt;span style=&quot;color: #ee2323;&quot;&gt;너무 과장되거나 너무 축소되는 것을 막기위해&lt;/span&gt; 모든 Importance sampling ratio들의 합으로 normalize한다. 이는 Importance sampling ratio를 0 ~ 1의 값으로 만들어 learning process를 smooth하게 만들어준다는 뜻이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ C(s,a) = \sum_{k=1}^N W_k$$&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Algorithm&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1356&quot; data-origin-height=&quot;1038&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fy2Fa/btsGVzzrjVK/ItEwzbOyRd62SUXm1HWJ70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fy2Fa/btsGVzzrjVK/ItEwzbOyRd62SUXm1HWJ70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fy2Fa/btsGVzzrjVK/ItEwzbOyRd62SUXm1HWJ70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFy2Fa%2FbtsGVzzrjVK%2FItEwzbOyRd62SUXm1HWJ70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;383&quot; data-origin-width=&quot;1356&quot; data-origin-height=&quot;1038&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;On-policy에서는 $(s, a)$에 대한 returns를 keep a table 했지만, 여기서는 $(s, a)$에 대한 &lt;span style=&quot;color: #ee2323;&quot;&gt;Importance sampling ratio들의 sum을 keep a table&lt;/span&gt;한다. 이는 각 $(s, a)$ 마다 Importance sampling ratio를 normalize 하는데 사용된다.&lt;/li&gt;
&lt;li&gt;Exploratory policy를 사용하여 trajectory를 만든다.&lt;/li&gt;
&lt;li&gt;이후 Exploratory policy를 이용하여 계산된 return을 사용하여 시간 역순으로 Target policy 하에 Q-value를 update한다. 이 과정에서 Importance sampling ratio를 사용한다.&lt;/li&gt;
&lt;li&gt;Exploratory Policy에 의해 수집된 $A_t$ 와 현재 Target Policy 하에 $A_t$가 다를 경우 loop를 멈추고 다음 episode로 넘어간다. 만약 $A_t$가 같을 경우 Importance sampling ratio를 update하고 loop를 계속한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;이렇게 하는 이유&lt;/span&gt;: (s, a) 공간이 매우 커질 경우 현실적으로 모든 공간을 explore 하는 것은 현실적이지 않다. 따라서 두 $A_t$가 다를 경우 Target Policy에 대한 update가 잘 이루어지지 않을수도 있으므로 현재 episode를 멈추고 다음 episode에 대해서 학습하는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;episode의 수만큼 2 ~ 4번을 반복한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Exercise&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[실습 환경 (Maze)]&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxmpQT/btsGULAJsg9/HUyEtAbNSn5EgbZpKzc3d1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxmpQT/btsGULAJsg9/HUyEtAbNSn5EgbZpKzc3d1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxmpQT/btsGULAJsg9/HUyEtAbNSn5EgbZpKzc3d1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxmpQT%2FbtsGULAJsg9%2FHUyEtAbNSn5EgbZpKzc3d1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;598&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[알고리즘 구현 코드]&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713948213130&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def target_policy(state):
    av = action_values[state]
    # action value(Q-value)가 가장 높은 Action들 중 random하게 선택
    return np.random.choice(np.flatnonzero(av == av.max()))
    

def exploratory_policy(state, epsilon=0.):
    if np.random.random() &amp;lt; epsilon:
        return np.random.choice(4)
    else:
        av = action_values[state]
        return np.random.choice(np.flatnonzero(av == av.max()))
        

def off_policy_mc_control(action_values, target_policy, exploratory_policy, episodes, gamma=0.99, epsilon=0.2):
    
    csa = np.zeros((5, 5, 4))
    
    for episode in range(1, episodes + 1):
        G = 0
        W = 1
        state = env.reset()
        done = False
        transitions = []
        
        while not done:
            action = exploratory_policy(state, epsilon)
            next_state, reward, done, _ = env.step(action)
            transitions.append((state, action, reward))
            state = next_state
            
        
        for state_t, action_t, reward_t in reversed(transitions):
            G = reward_t + gamma * G
            csa[state_t][action_t] += W
            qsa = action_values[state_t][action_t]
            action_values[state_t][action_t] += (W / csa[state_t][action_t]) * (G - qsa)
            
            if action_t != target_policy(state_t):
                break
            
            # exploratory policy의 action과 target policy의 action이 같다는 뜻은 exploratory policy에서
            # 1 - epsilon의 확률로 target policy와 같은 policy를 따랏다는 뜻이므로 아래와 같이 계산
            W = W * 1. / (1 - epsilon + epsilon / 4)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;exploratory policy는 epsilon greedy 방법으로 explore 한다. epsilon의 확률로 random action을 행하고 1 - epsilon의 확률로 Target policy와 같은 알고리즘으로 Action을 택한다. 결국 이러면 e-greedy on-policy와 똑같은 것이 아니냐는 의문이 생길 수 있는데, off-policy에서는 target-policy에 e-greedy를 직접적으로 적용하지 않음으로써 때때로 불필요한 탐색이 policy 개선에 영향을 주는 것을 방지할 수 있다. on-policy는 이에비해 구현의 간단하고 직관적이라는 장점이 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[실습 결과 Q-value]&lt;br /&gt;: on-policy와는 다르게 target-policy가 e-greedy한 explore를 하지않고 exploratory-policy만 explore했으므로 최단거리와 관계없는 action value들은 초기를 제외하면 완벽하게 무시된 것을 아래 table에서 볼 수 있다. 이로써 알 수 있는 off-policy의 장점은 target-policy가 goal에 완벽하게 집중할 수 있게 해준다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;1516&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9emQs/btsGVArwRsI/iso3kKybik6FuVvvHeoU4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9emQs/btsGVArwRsI/iso3kKybik6FuVvvHeoU4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9emQs/btsGVArwRsI/iso3kKybik6FuVvvHeoU4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9emQs%2FbtsGVArwRsI%2Fiso3kKybik6FuVvvHeoU4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;1516&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;1516&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;[실습 결과 Policy]&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2162&quot; data-origin-height=&quot;1008&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eiqHh6/btsGUKnWieT/sKCQZm7eir5RzTdjuruSB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eiqHh6/btsGUKnWieT/sKCQZm7eir5RzTdjuruSB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eiqHh6/btsGUKnWieT/sKCQZm7eir5RzTdjuruSB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeiqHh6%2FbtsGUKnWieT%2FsKCQZm7eir5RzTdjuruSB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;280&quot; data-origin-width=&quot;2162&quot; data-origin-height=&quot;1008&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/130</guid>
      <comments>https://pipe0512.tistory.com/130#entry130comment</comments>
      <pubDate>Thu, 25 Apr 2024 09:01:22 +0900</pubDate>
    </item>
    <item>
      <title>[Monte Carlo methods - 3] On-Policy Monte Carlo</title>
      <link>https://pipe0512.tistory.com/129</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;On-policy Monte Carlo&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Exploration of the environment를 maintain하기 위한 method 중 하나&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;$\epsilon$-greedy policy&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Exploration of environment를 maintain하기 위해 &lt;span style=&quot;color: #ee2323;&quot;&gt;낮은 확률로 random action을 수행하도록 만드는 Policy&lt;/span&gt;이다. 모든 Action의 확률은 0보다 크며, $\epsilon$ 의 확률로 random action이 선택되고 $1-\epsilon$ 의 확률로 가장 높은 $Q(s, a)$를 가진 Action이 선택된다. 이 Policy는 시간이 지날수록 모든 action을 선택해볼 것이고, 이는 예상보다 더 좋은 결과를 도출해낼 수도 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$\left | A \right |$는 가능한 action의 개수이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;$$ \pi(a|s) = \begin{cases}1-\epsilon+\epsilon_r &amp;amp; a=a^* \ \epsilon_r &amp;amp; a\ne a^*\end{cases} $$&lt;br /&gt;&lt;br /&gt;$$ \epsilon_r = {\epsilon\over|A|} $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시로 만약 $\epsilon = 0.2$이고 행동 가능한 Action이 4가지라면, 위 공식에 따라 가장 높은 Q-value를 가지는 Action이 선택될 확률은 0.85이고 나머지 Action들 3가지가 선택될 확률은 각각 0.05이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Algorithm&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nAq2D/btsGS4Oo3dD/uNhzDVAK5wQ9ks2HLGTn3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nAq2D/btsGS4Oo3dD/uNhzDVAK5wQ9ks2HLGTn3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nAq2D/btsGS4Oo3dD/uNhzDVAK5wQ9ks2HLGTn3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnAq2D%2FbtsGS4Oo3dD%2FuNhzDVAK5wQ9ks2HLGTn3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;278&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;$\epsilon$ 과 $\gamma$를 적절한 값으로 설정하고, Q-value를 임의의 값으로 초기화한다. 종료조건의 Q-value는 0이다.&lt;/li&gt;
&lt;li&gt;Policy는 모든 episode가 끝날 때 까지 높은 Q-value 선택하는 전략을 가진 e-greedy이다.&lt;/li&gt;
&lt;li&gt;현재의 episode가 끝날 때까지 Agent가 Environment와 상호작용시키면서 trajectory를 얻는다.&lt;/li&gt;
&lt;li&gt;Return을 0으로 초기화한다.&lt;/li&gt;
&lt;li&gt;모든 State를 방문하면서 (시간 역순으로) return을 계산하고, (s, a) pair에 해당하는 Return table에 저장한다. 이때, 해당 (s, a) pair Return들의 평균을 해당 Q-value($Q(s, a)$)로 update한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이때, 시간 역순으로 계산하는 이유는 모든 reward를 구해놓고 시간 정순으로 계산하는 것보다 역순으로 reward를 얻을 때마다 계산하는 것이 효율적이기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모든 episode가 끝날 때까지 3 ~ 5번과정을 반복한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;e-greedy Policy를 사용하여 간헐적으로 random action을 행함으로써, 이 모든 과정이 끝나면 완벽한 Optimal인지는 알 수 없지만, Optimal에 근접한 Policy와 Q-value를얻을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Exercise&lt;/h2&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;[실습 환경 (Maze)]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNhmBO/btsGVevSjG2/LoaZesOkuyoekarS7jeFi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNhmBO/btsGVevSjG2/LoaZesOkuyoekarS7jeFi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNhmBO/btsGVevSjG2/LoaZesOkuyoekarS7jeFi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNhmBO%2FbtsGVevSjG2%2FLoaZesOkuyoekarS7jeFi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;598&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[알고리즘 구현 코드]&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713947467684&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def policy(state, epsilon=0.2):
    # 0이상 1미만의 값을 샘플링해서 epsilon과 비교
    if np.random.random() &amp;lt; epsilon:
        # 0 ~ 4미만의 정수 값을 샘플링 
        return np.random.randint(4)
    else:
        av = action_values[state]
        # flatnonzero(조건) : 조건에 맞는 원소들의 인덱스 리스트를 반환
        # 즉, 아래 코드는 가장 높은 value를 가진 action들 중 하나를 랜덤하게 선택함
        return np.random.choice(np.flatnonzero(av == av.max())) 
        

def on_policy_mc_control(policy, action_values, episodes, gamma=0.99, epsilon=0.2):
    
    # (s, a)에 해당하는 returns들을 저장하는 딕셔너리
    sa_returns = {}
    
    
    for episode in range(1, episodes + 1):
        # 환경을 reset
        state = env.reset()
        done = False
        # episode 동안 agent의 State, Action, Reward를 기록하는 List (Trajectory)
        transitions = []
        
        while not done:
            action = policy(state, epsilon)
            next_state, reward, done, _ = env.step(action)
            transitions.append([state, action, reward])
            state = next_state
        
        G = 0
        
        # 시간 역순으로 returns를 계산
        for state_t, action_t, reward_t in reversed(transitions):
            G = reward_t + gamma * G
            
            if not (state_t, action_t) in sa_returns:
                sa_returns[(state_t, action_t)] = []
            
            sa_returns[(state_t, action_t)].append(G)
            
            action_values[state_t][action_t] = np.mean(sa_returns[(state_t, action_t)])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[실습 결과 Q-value]&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;1518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qF322/btsGVs1mhXe/TlJXuSaf2w7goYk92W0Cn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qF322/btsGVs1mhXe/TlJXuSaf2w7goYk92W0Cn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qF322/btsGVs1mhXe/TlJXuSaf2w7goYk92W0Cn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqF322%2FbtsGVs1mhXe%2FTlJXuSaf2w7goYk92W0Cn1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;413&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;1518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[실습 결과 Policy]&lt;br /&gt;: Policy는 (0, 0)에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;Goal에 대해서 최단거리로 이끌어준다. &lt;/span&gt;최단거리 루트에 포함되지 않는 State들 중 (0, 0)과 비교적 가까운 State들은 어느정도 알맞은 Policy를 가지고 있지만, 최단거리 루트에 포함되지 않으면서 (0, 0)과 먼 State들은 잘못된 Policy를 가지고있다. 왜냐하면, on-policy이기 때문이 explore 또한 점점 Goal에대한 최단거리를 찾아가기 때문에 최단거리 루트에 포함되지 않으면서 (0, 0)과 먼 State들에대한 Explore가 충분히 이루어지지 않았기 때문이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2186&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSPKoM/btsGTBkGztG/9D2UXuegH9hkf4k3ujI2bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSPKoM/btsGTBkGztG/9D2UXuegH9hkf4k3ujI2bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSPKoM/btsGTBkGztG/9D2UXuegH9hkf4k3ujI2bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSPKoM%2FbtsGTBkGztG%2F9D2UXuegH9hkf4k3ujI2bk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2186&quot; height=&quot;1018&quot; data-origin-width=&quot;2186&quot; data-origin-height=&quot;1018&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;[계산을 효율적으로 하기위한 Constant Alpha를 사용해서 구현]&lt;br /&gt;&lt;br /&gt;$$ Q(s, a) \gets Q(s, a) + \alpha[G - Q(s, a)] $$&lt;br /&gt;&lt;br /&gt;: 기존의 방법과 다른 점은 각 (s, a)에 대한 returns들을 episode마다 계속 저장하여 averaging하는 것이 아니라, return을 즉각적으로 $\alpha$ 만큼 Q-value에 반영한다. (&lt;span style=&quot;color: #d83931;&quot;&gt;constant alpha&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1713947580040&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def on_policy_mc_control(policy, action_values, episodes, gamma=0.99, epsilon=0.2, alpha=0.2):
    
    for episode in range(1, episodes+1):
        state = env.reset()
        done = False
        transitions = []
        
        while not done:
            action = policy(state, epsilon)
            next_state, reward, done, _ = env.step(action)
            transitions.append([state, action, reward])
            state = next_state
        
        G = 0
        for state_t, action_t, reward_t in reversed(transitions):
            G = reward_t + gamma * G
            
            # constant alpha
            qsa = action_values[state_t][action_t]
            action_values[state_t][action_t] += alpha * (G - qsa)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/129</guid>
      <comments>https://pipe0512.tistory.com/129#entry129comment</comments>
      <pubDate>Wed, 24 Apr 2024 17:33:26 +0900</pubDate>
    </item>
    <item>
      <title>[Monte Carlo methods - 2] GPI with Monte Carlo methods</title>
      <link>https://pipe0512.tistory.com/128</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Generalized Policy Iteration (GPI)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Monte Carlo methods를 사용하여 control tasks를 풀기위해서 GPI를 사용한다. 초기에는 임의의 Policy로 시작한다. Agent는 첫 episode의 처음부터 끝까지 초기 Policy를 사용하면서 trajectory를 생성한다. 이후 각 시간에서의 return이 rewards의 discounted sum으로 계산된다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ S_0, A_0, R_1, S_1, A_1, R_2, ..., R_T $$&lt;br /&gt;&lt;br /&gt;$$ G_t = R_{t+1} + \gamma R_{t+2}+\gamma^2 R_{t+3} + ... + \gamma^{T-t-1} R_T $$&lt;br /&gt;&lt;br /&gt;$$ G_{t+1} = R_{t+2} + \gamma R_{t+3}+\gamma^2 R_{t+4} + ... + \gamma^{T-t-1} R_T $$&lt;br /&gt;&lt;br /&gt;$$ ... $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 얻은 return들로 이전에 해당 State 혹은 Action의 return들과 평균을 내는 방식으로 Value Function의 estimate한다. (&lt;span style=&quot;color: #d83931; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Policy Evaluation&lt;/span&gt;) 이후, Estimate된 Value function을 기반으로 Policy를 개선한다.(&lt;span style=&quot;color: #d83931; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Policy Improvement&lt;/span&gt;)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Problem&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP에서는 transition probability와 expected rewards를 통해서 아래의 식으로 가장 높은 return을 주는 action을 찾을 수 있었다. DP와는 다르게, Monte Carlo methods에서는 &lt;span style=&quot;color: #d83931; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;model of environments를 사전에 알지 못하기 때문에 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;아래 식에서의 $v_\pi(s')$를 사용할 수 없다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \pi'(s) = \arg\max_a\sum_{s',r}p(s',r|s,a)[r+\gamma v_\pi(s')] $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 States의 Value를 estimate하는 대신 &lt;span style=&quot;color: #d83931; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;각 State에서 개별 Action을 행할 때의 expected return을 estimate&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;하는것이 좋은 방법이다. 이후 각 Action의 expected returns의 estimates를 비교하여 &lt;/span&gt;&lt;span style=&quot;color: #d83931; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;가장 높은 expected return을 가진 action&lt;/span&gt;을 찾으면 된다. (Q-value의 기능) 왜냐하면, 아래 식에서 볼 수 있듯이, Action의 expected return 즉, Q-value($q_\pi(s, a)$)가 내재적으로 $v_\pi(s')$을 내재하고 있으므로 우리는 $v_\pi(s')$를 몰라도 되며 Q-value가 높은 Action을 선택하면된다. (Q-value에 환경의 dynamics가 내재되어있다는 뜻)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ q_\pi(s,a) = \sum_{s', r}p(s',r|s,a)[r+\gamma v_\pi(s')] $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Monte Carlo에서는 State Value($V(s)$) 대신 Q-value($Q(s, a)$)를 keep a table 할 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \pi'(s) = \arg\max_a q_\pi(s,a) $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPI에서 Policy Evaluation 단계에서 Q-value를 사용할 것이며, Policy Improvement 단계에서도 Q-value function의 estimate를 update하며 Policy를 개선할 것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;The Importance of Exploration&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 Q-value를 사용한 GPI 과정을 진행할 때 명심해야할 점은 $Q(s, a)$는 &lt;span style=&quot;color: #d83931; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Estimate&lt;/span&gt;라는 점이다. 이는 Agent가 Policy를 따르면서 Environments와 상호작용하며 얻은 경험에 기반한다. 따라서 Estimate가 학습 초기 단계에서는 정확하지 않을 수도 있다. 이렇게 학습 초기에 정확하지 않은 Estimate가 만약 Optimal인 선택지의 Estimate를 낮게 측정한다면, Agent는 해당 선택지를 절대 선택하지 않을 것이며 이는 결국 Optimal인 선택지의 Estimate를 옳게 수정할 기회조차 없게될 수 있다는 것을 의미한다. 이것을 방지하는 방법은 &lt;span style=&quot;color: #d83931; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;모든 action을 explore하고 계속 estimate Q(s,a)를 update하는 방법이 유일하다. &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;이로써 밝혀지지 않은 가능한 optimal actions를 놓치지 않을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Two options&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Exploring starts&lt;br /&gt;: Agent가 environment를 직면할 때 마다 random initial State에서 시작하고, random initial Action을 취하는 것으로 시작하는 것이다. 하지만, 이는 tasks의 수가 많아진다면 사용할 수 없기때문에 &lt;span style=&quot;color: #ee2323;&quot;&gt;현실적이지 않다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;span style=&quot;color: #d83931;&quot;&gt;Stochastic policies&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;: Policy에서 모든 action이 선택될 확률을 0보다 크게 하는 것이다. 이를통해 때때로 task를 개선 하기위해 &lt;span style=&quot;color: #ee2323;&quot;&gt;optimal이 아니라고 생각되는 선택지를 선택하게 보장&lt;/span&gt;할 수 있다. 이를 통해 &lt;span style=&quot;color: #ee2323;&quot;&gt;결과가 나쁠 것이라고 생각됐던 action이 optimal이 될 수도 있다. &lt;/span&gt;이것이 첫번째 option보다 더 현실적이고 쉬워보인다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stochastic policies는 2가지 다른 방법으로 구현될 수 있다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #d83931;&quot;&gt;On-policy learning&lt;/span&gt;&lt;br /&gt;: Optimize할 때와 Explore할 때 &lt;span style=&quot;color: #d83931;&quot;&gt;같은 Policy&lt;/span&gt;를 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #d83931;&quot;&gt;Off-policy learning&lt;/span&gt;&lt;br /&gt;: Optimize할 때와 Explore할 때 &lt;span style=&quot;color: #d83931;&quot;&gt;다른 Policy&lt;/span&gt;를 사용한다. 결국 총 2가지 Policy를 사용한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/128</guid>
      <comments>https://pipe0512.tistory.com/128#entry128comment</comments>
      <pubDate>Tue, 23 Apr 2024 20:08:39 +0900</pubDate>
    </item>
    <item>
      <title>[Monte Carlo methods - 1] Intro</title>
      <link>https://pipe0512.tistory.com/127</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Monte Carlo methods&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Monte Carlo mehods는 경험에 기반한 알고리즘들 중 하나이다. 경험에 기반한 알고리즘들은 Agent가 환경과 상호작용하면서 모은&amp;nbsp;&lt;span style=&quot;color: #d83931;&quot;&gt;samples of experience&lt;/span&gt;를 기반으로 $v_*(s)$(optimal state-value)혹은 $q_*(s,a)$(optimal q-value)를 학습한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #d83931;&quot;&gt;학습 초기에&lt;/span&gt;, Agent는&amp;nbsp;&lt;span style=&quot;color: #d83931;&quot;&gt;임의의 Policy&lt;/span&gt;를 따른다. Agent는 trace of experience(&lt;span style=&quot;color: #d83931;&quot;&gt;trajectory&lt;/span&gt;)를 생성하면서 episode가 끝날 때 까지 현재 Policy를 따라 task를 수행한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ S_0, A_0, R_1, S_1, A_1, ... , S_{T-1}, A_{T-1}, R_T $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Episode가 끝났을 때, 모든 방문한 State로부터 얻어진 return을 계산한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ G_t = \sum_{k=0}^{T-t-1}\gamma^k R_{t+k+1} $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Episode가 끝났을 때, 각 State의 Value는 현재 Policy를 따랐을 때의 expected return이다. 따라서 매 Episode마다 어떤 State에 대한 새로운 return을 얻었을 때,&amp;nbsp;&lt;span style=&quot;color: #d83931;&quot;&gt;해당 State에서 얻었던 returns들의 평균을 추정치로 갱신&lt;/span&gt;한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ V_\pi(s) = {1\over N}\sum_{k=1}^N G_{s_k} $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q-value에서도 똑같은 process가 적용된다. (action마다 해당 State에서 해당 action의 returns에 대한 평균을 추정치로 갱신)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ G_t = \sum_{k=0}^{T-t-1}\gamma^k R_{t+k+1} $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ q_\pi(s,a) = E_\pi[G_t|s_t=s, A_t=a] $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ Q_\pi(s,a) = {1\over N}\sum_{k=1}^N G_{s,a_k} $$&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Law of large numbers&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;큰수의 법칙에 따라 우리가 observe하는 State나 Action이 많아질수록 그것들의 기댓값(State value / Q-value)에 더욱 더 근사된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Advantages of Monte Carlo methods&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Estimate of State Value가 &lt;span style=&quot;color: #d83931;&quot;&gt;다른 estimate of State Value의 영향을 받지 않는다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이는 State Value를 추정하는데 필요한 complexity가 task의 state 수에 상관없음을 의미한다. (컴퓨팅 리소스 적음)&lt;/li&gt;
&lt;li&gt;DP의 경우 다른 State들의 Value를 bootstrap하여 State Value를 estimate한다. 따라서 States들의 수에 따라서 complexity가 기하급수적으로 증가한다.&lt;/li&gt;
&lt;li&gt;Bootstrap: 현재 상태의 추정치를 계산하기 위해 다른 추정치들을 사용하는 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #d83931;&quot;&gt;Goal에 연관된 State들의 Value에만 자원을 집중&lt;/span&gt;할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앞선 단원에서 실습했던 Maze를 예시로 하면, 도착지점까지가는 지점(State)들의 Value만 보면 된다.&lt;/li&gt;
&lt;li&gt;DP의 경우 어떤 State의 중요도와 관계없이 모든 States를 순회(Sweep)하며 업데이트한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #d83931;&quot;&gt;Model of the environment가 필요없다.&lt;/span&gt;(가장 중요!)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dynamics of the environment는 이미 우리의 추정치에 내재되어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/127</guid>
      <comments>https://pipe0512.tistory.com/127#entry127comment</comments>
      <pubDate>Tue, 23 Apr 2024 19:59:35 +0900</pubDate>
    </item>
    <item>
      <title>[Dynamic Programming - 4] Generalized Policy Iteration(GPI)</title>
      <link>https://pipe0512.tistory.com/126</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Generalized Policy Iteration (GPI)&lt;/h1&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buYBeo/btsGOvrNft4/1XLKxCANSpZm5PDKPRmD91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buYBeo/btsGOvrNft4/1XLKxCANSpZm5PDKPRmD91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buYBeo/btsGOvrNft4/1XLKxCANSpZm5PDKPRmD91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuYBeo%2FbtsGOvrNft4%2F1XLKxCANSpZm5PDKPRmD91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;386&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPI는 대부분의 강화학습 알고리즘의 general template 이다. Monte Carlo methods는 model of the environment가 정의되지 않은 상태의 알고리즘이지만, environment에서 수집된 experience로 value를 update한다는 차이점만 있고 큰 형식은 GPI를 따른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 강화 학습 알고리즘들은 GPI를 개념적으로 차용하지만 DP를 사용하지는 않는다. 왜냐하면, DP의 단점들 때문이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Disadvantages of dynamic programming&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #d83931;&quot;&gt;DP는 High computational cost가 발생&lt;/span&gt;한다. 왜냐하면, 매 Iteration 에서 우리는 모든 states를 update 해야한다. 따라서, Complexity가 states의 수에 따라서 기하급수적으로 증가한다. 그런데, 현실세계의 control problems는 매우 광범위한 범위의 states를 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 대부분의 Contral tasks에서 우리는&amp;nbsp;&lt;span style=&quot;color: #d83931;&quot;&gt;perfect model of the environment with all state transitions를 가지고있지 않다. &lt;/span&gt;하지만 이러한 DP의 단점들에도 우리가 DP를 공부하는 이유는 더 나은 알고리즘을 고안하기 위한 전략인 GPI 때문이다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/126</guid>
      <comments>https://pipe0512.tistory.com/126#entry126comment</comments>
      <pubDate>Mon, 22 Apr 2024 21:22:15 +0900</pubDate>
    </item>
    <item>
      <title>[Dynamic Programming - 3] Policy Iteration</title>
      <link>https://pipe0512.tistory.com/125</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Policy Iteration&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Policy Iteration은&amp;nbsp;&lt;span style=&quot;color: #d83931;&quot;&gt;optimal policy와 이의 value function을 alternating하면서 서로를 개선한다. &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;이렇게 현재의 policy으로 value를 계산하고 해당 value를 통해서 policy을 개선하는 반복적인 과정은 많은 강화학습 알고리즘에 영향을 끼쳤다. 이 점에서 Policy Iteration은 강화학습에서 매우 중요한 의의를 가진다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvKxgw/btsGPqwXr5a/gn0YN6Fr5YLlwCftbqlslK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvKxgw/btsGPqwXr5a/gn0YN6Fr5YLlwCftbqlslK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvKxgw/btsGPqwXr5a/gn0YN6Fr5YLlwCftbqlslK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvKxgw%2FbtsGPqwXr5a%2Fgn0YN6Fr5YLlwCftbqlslK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;234&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h2 data-ke-size=&quot;size26&quot;&gt;Algorithm&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1070&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V06my/btsGNZmn1OW/qpQSmdQp1hKv58A6g7JXr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V06my/btsGNZmn1OW/qpQSmdQp1hKv58A6g7JXr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V06my/btsGNZmn1OW/qpQSmdQp1hKv58A6g7JXr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV06my%2FbtsGNZmn1OW%2FqpQSmdQp1hKv58A6g7JXr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;468&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1070&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;$\pi(a|s)$(Policy)와 $V(s)$ (각 State에 대한 State Value)를 임의의 값으로 initialize한다.&lt;/li&gt;
&lt;li&gt;[&lt;span style=&quot;color: #ee2323;&quot;&gt;Policy Evaluation&lt;/span&gt;] 현재 임의로 정한 Policy를 기준으로 각 State에 대한(모든 Action을 고려) Expected return을 각 State의 State Value로 업데이트한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Value Iteration의 경우 가장 큰 Expected Return을 주는 Action의 Value를 State Value로 사용하는 Value function을 사용하였다.&lt;br /&gt;&lt;br /&gt;$$V(s) \gets \sum_a \pi(a|s) \sum_{s',r}p(s',r|s,a)[r+\gamma v_\pi(s')]$$&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;그러나 Policy Evaluation에서는 모든 가능한 Actions를 고려하여 &lt;span style=&quot;color: #d83931;&quot;&gt;각 Action들의 Expected Return의, Expected Return을 State Value로 사용&lt;/span&gt;하는 Value function을 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, $V(s)$ 는 현재 Policy하에, 해당 State에서의 가능한 모든 결과들의 weighted sum이다.&lt;/li&gt;
&lt;li&gt;이는 곧 Bellman Equation이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;위와 같은 방식으로 각 State Value의 최대 변화량이 Delta보다 작아질 때 까지 반복한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;3&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;[&lt;span style=&quot;color: #ee2323;&quot;&gt;Policy Improvement&lt;/span&gt;] 산출된 State Value들을 기반으로 Expected return을 최대화하는 방향으로 현재 Policy를 개선한다. &lt;br /&gt;&lt;br /&gt;$$q_\pi(s,a) = \sum_{s',r}p(s',r|s,a)[r+\gamma v_{\pi}(s')]$$&lt;br /&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 Policy를 개선하기 위해서는 Q-value를 사용한다. 왜냐하면 Q-value는 각 State에서 각 Action들의 가치를 표현하기 때문이다.&lt;/li&gt;
&lt;li&gt;따라서 &lt;span style=&quot;color: #d83931;&quot;&gt;특정 Action에 대한 Q-value가 현재 State value보다 높을 경우&lt;/span&gt; 현재 Policy $\pi$ 를 현재 State에서 해당 Action을 선택하는 Policy $\pi'$으로 변경한다.&lt;/li&gt;
&lt;li&gt;이를 모든 State에 반복한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;4&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Policy Improvement 단계에서 단 하나의 State에 대한 Policy라도 변했다면, Policy Evaluation부터 다시 수행한다. Policy가 더이상 변하지 않는다면 반복을 멈춘다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Policy Evaluation과 Policy Improvement는 하나의 과정이 다른 과정의 결과를 바탕으로 작동하기 때문에 서로 경쟁적인 관계에 있을 수 있다. 그러나 두 과정은 서로를 최적의 해결책으로 밀어내는 협력적인 역할이기도 하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Practice&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[실습 환경 (Maze)]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3gtv6/btsGS93ypgm/fX1sMBVFeY3iK2mIrIOPQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3gtv6/btsGS93ypgm/fX1sMBVFeY3iK2mIrIOPQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3gtv6/btsGS93ypgm/fX1sMBVFeY3iK2mIrIOPQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3gtv6%2FbtsGS93ypgm%2FfX1sMBVFeY3iK2mIrIOPQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;604&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[1번째 Iteration] - 모든 Action의 확률이 같은 상태&lt;br /&gt;Policy Evaluation&lt;br /&gt;: 아래에서 볼 수 있듯이 매우 낮은 State value를 가지고 있다. 왜나하면, Random policy이므로 목표 상태에 도달하기까지 매우 많은 시행착오를 거쳐야하고, 그 과정에서 negative rewards들이 쌓이기 때문이다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfakGL/btsGRAZubW9/0nKg4bBkzgmsr33UNmmclK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfakGL/btsGRAZubW9/0nKg4bBkzgmsr33UNmmclK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfakGL/btsGRAZubW9/0nKg4bBkzgmsr33UNmmclK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfakGL%2FbtsGRAZubW9%2F0nKg4bBkzgmsr33UNmmclK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;730&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;Policy Improvement&lt;br /&gt;:&amp;nbsp;Policy&amp;nbsp;Improvement&amp;nbsp;수행&amp;nbsp;후&amp;nbsp;Policy는&amp;nbsp;Optimal이다.&amp;nbsp;왜냐하면,&amp;nbsp;기존&amp;nbsp;Policy가&amp;nbsp;랜덤&amp;nbsp;Policy이긴&amp;nbsp;하지만,&amp;nbsp;Agent는&amp;nbsp;결국에&amp;nbsp;Goal에&amp;nbsp;더&amp;nbsp;가까운&amp;nbsp;State일&amp;nbsp;수록&amp;nbsp;Goal에&amp;nbsp;더&amp;nbsp;빨리&amp;nbsp;도달한다는&amp;nbsp;것은&amp;nbsp;자명하므로&amp;nbsp;Policy는&amp;nbsp;이를&amp;nbsp;통해&amp;nbsp;개선하기&amp;nbsp;때문이다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/enhPZt/btsGOxb8Q09/pFP1XKxW6k3vfShD1kljKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/enhPZt/btsGOxb8Q09/pFP1XKxW6k3vfShD1kljKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/enhPZt/btsGOxb8Q09/pFP1XKxW6k3vfShD1kljKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenhPZt%2FbtsGOxb8Q09%2FpFP1XKxW6k3vfShD1kljKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;796&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;[2번째 Iteration]&lt;br /&gt;Policy Evaluation&lt;br /&gt;:&amp;nbsp;이미&amp;nbsp;Optimal&amp;nbsp;Policy인&amp;nbsp;상태에서의&amp;nbsp;Policy&amp;nbsp;Evaluation&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMb80v/btsGRo50y3a/mBCokMq3SuEldvHfoP5Ckk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMb80v/btsGRo50y3a/mBCokMq3SuEldvHfoP5Ckk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMb80v/btsGRo50y3a/mBCokMq3SuEldvHfoP5Ckk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMb80v%2FbtsGRo50y3a%2FmBCokMq3SuEldvHfoP5Ckk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;726&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;Policy Improvement&lt;br /&gt;:&amp;nbsp;이미&amp;nbsp;Policy는&amp;nbsp;Optimal&amp;nbsp;이며,&amp;nbsp;Policy가&amp;nbsp;바뀌지&amp;nbsp;않았으므로&amp;nbsp;Iteration이&amp;nbsp;종료된다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/125</guid>
      <comments>https://pipe0512.tistory.com/125#entry125comment</comments>
      <pubDate>Mon, 22 Apr 2024 21:19:40 +0900</pubDate>
    </item>
    <item>
      <title>[Dynamic Programming - 2] Value Iteration</title>
      <link>https://pipe0512.tistory.com/124</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Value Iteration&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \pi_*(s)=\arg\max_a\sum p(s',r|s,a)[r+\gamma v_*(s')] $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 매 State마다 return을 maximize하는 Action을 택하는 Optimal policy($\pi_*$&lt;i&gt;)&lt;/i&gt;를 찾고싶다. 하지만, 위 식에서 보여지듯이 그러기 위해서는 매 State 마다의 optimal value($v_*$)를 알아야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 우리는 각 State의 optimal state value($v_*$)를 찾기위해서 iterative process를 통해 estimate할 것이다. 아래와 같은 Update rule을 사용하며 각 state value의 estimated values를 table로 보관할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ V(s) \gets \max_a\sum_{s',r}p(s',r|s,a)[r+\gamma V(s')] $$&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Algorithm&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1130&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4lJwy/btsGPagB6pr/gMCe0ATqyFokidzgzUNwb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4lJwy/btsGPagB6pr/gMCe0ATqyFokidzgzUNwb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4lJwy/btsGPagB6pr/gMCe0ATqyFokidzgzUNwb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4lJwy%2FbtsGPagB6pr%2FgMCe0ATqyFokidzgzUNwb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;271&quot; data-origin-width=&quot;1130&quot; data-origin-height=&quot;510&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;$V(s)$ (각 State의 State Value)를 임의로 설정하고, tolerance parameter $\theta$ 와 discount factor $\gamma$ 를 적절한 값으로 설정한다.&lt;br /&gt;종료 상태(Task 완료 상태)의 Value $V(terminal)$은 0이다.&lt;/li&gt;
&lt;li&gt;원래의 State Value를 $v$ 에 기록한다.&lt;/li&gt;
&lt;li&gt;Expected return이 가장 높은 Action의 Expected return을 $V(s)$ 에 할당한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, Value Iteration에서의 Value Function($V(s)$)는 Expected return이 가장 큰 값을 할당하는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;0과 $\left | v - V(S) \right |$ 중 큰값을 $\mathsf{\Delta}$ 에 할당한다. (즉, 모든 State 변화 중 가장 큰 변화를 Delta에 기록)&lt;/li&gt;
&lt;li&gt;모든 State에 대해서 2 ~ 4번 과정을 반복한다.&lt;/li&gt;
&lt;li&gt;$\mathsf{\Delta}$ 가 $\theta$ 보다 작아질 때까지 5번 과정을 반복한다.&lt;/li&gt;
&lt;li&gt;모든 Iteration이 끝난 상태에서의 각 State의 $V(s)$ 를 통해 policy를 결정한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Iteration 초반에는 value가 많이 바뀌겠지만 점점 작아질 것이다. 이후 처음에 정해둔 theta보다 change의 값이 작아진다면 approximation이 충분히 좋아졌기 때문에 iteration을 멈춘다. 이렇게 얻은 optimal values를 기반으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;return을 maximize하기 위한 policy를 정의&lt;/span&gt;하고 action을 선택할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Action에 대한 결과가 결정적일 경우, $V(s) \gets \max_a\sum_{s',r}p(s',r|s,a)[r+\gamma V(s')]$ 에서 $V(s)$는 결국 가장 높은 return을 주는 Action의 $r + \gamma V(s')$ 가 된다. 원래는 가장 높은 return이 아닌 가장 높은 Expected Return이지만, 결과가 결정적이므로 return을 사용한다. 왜냐하면, 어떤 Action을 취했을 때의 결과가 결정적이라면 $s'$이 단 하나로 결정되며, $p(s',r|s,a)$ 또한 당연히 1이 되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목표달성시 reward가 0 아닌 경우에는 -1이라고 했을 때, 첫번째 Iteration에서는 종료 조건 State만 0의 State Value를 가지고 이를 제외한 모든 State의 Value가 -1일 것이다. 하지만, Iteration이 진행될수록 종료 조건 State위치 기준으로 다른 State들의 Value들이 점점 퍼져나가듯이 Update 될것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Practice&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[실습 환경 (Maze)]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;1252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIfOIO/btsGRhTolqq/ebhS6yeyXJ4O9t8jDn8c60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIfOIO/btsGRhTolqq/ebhS6yeyXJ4O9t8jDn8c60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIfOIO/btsGRhTolqq/ebhS6yeyXJ4O9t8jDn8c60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIfOIO%2FbtsGRhTolqq%2FebhS6yeyXJ4O9t8jDn8c60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;1252&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;1252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[알고리즘 구현 코드]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714003706615&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# state 넣으면 해당하는 확률을 출력
def policy(state):
    return policy_probs[state]
    
    
def value_iteration(policy_probs, state_values, theta=1e-6, gamma=0.99):
    # 루프를 시작하기위해 초기 값을 매우 큰 값으로 초기화
    delta = float(&quot;inf&quot;)
    cnt = 0
    while delta &amp;gt; theta:
        delta = 0
        
        # 모든 state 순회
        for row in range(5):
            for col in range(5):
                # 이전 밸류 임시 저장
                old_value = state_values[(row, col)]
                # Action 확률을 현재 모르므로 일단 None으로 초기화
                action_probs = None                
                # 수행 가능한 Action 중 Highest return을 주는 action을 기록하기위해 가장 작은 값으로 초기화
                max_qsa = float(&quot;-inf&quot;)
                
                # 행동 4개 수행
                for action in range(4):
                    # simulate_step은 실제로 해당 Action을 수행하지 않고도 해당 Action이 수행된 결과를 시뮬레이션 하는 메서드이다.
                    # 이러한 시뮬레이션을 해야하기 때문에 DP가 환경을 완벽하게 알아야한다는 한계점이 있다는 것이다.
                    next_state, reward, _, _ = env.simulate_step((row, col), action)
                    qsa = reward + gamma * state_values[next_state]
                    
                    if qsa &amp;gt; max_qsa:
                        max_qsa = qsa
                        # Highest return을 주는 action을 100% 확률로 선택하게 만듦
                        action_probs = np.zeros(4)
                        action_probs[action] = 1.
                
                state_values[(row, col)] = max_qsa
                policy_probs[(row, col)] = action_probs
                
                # 상태의 변화가 tolerance parameter theta보다 작아지면 iteration 멈춤
                delta = max(delta, abs(max_qsa - old_value))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[1번째 Iteration]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;970&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JYbbr/btsGPrWXNv5/1KZGz8ll5CepfEw2sK7TM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JYbbr/btsGPrWXNv5/1KZGz8ll5CepfEw2sK7TM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JYbbr/btsGPrWXNv5/1KZGz8ll5CepfEw2sK7TM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJYbbr%2FbtsGPrWXNv5%2F1KZGz8ll5CepfEw2sK7TM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;970&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[3번째 Iteration]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;978&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buC7b5/btsGOdLDqAT/3zWt8Jt0F5r0W3HoIBEl40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buC7b5/btsGOdLDqAT/3zWt8Jt0F5r0W3HoIBEl40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buC7b5/btsGOdLDqAT/3zWt8Jt0F5r0W3HoIBEl40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuC7b5%2FbtsGOdLDqAT%2F3zWt8Jt0F5r0W3HoIBEl40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;978&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;978&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[10번째 Iteration]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;962&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCnyW2/btsGOfvXCAw/kAx3pYfEJfyWKjZjrVc85K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCnyW2/btsGOfvXCAw/kAx3pYfEJfyWKjZjrVc85K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCnyW2/btsGOfvXCAw/kAx3pYfEJfyWKjZjrVc85K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCnyW2%2FbtsGOfvXCAw%2FkAx3pYfEJfyWKjZjrVc85K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;292&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;962&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[최종 State Value 및 Policy]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;968&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jyksu/btsGRd4vZhL/vOqca0E9w2JZAWm1Jjzfe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jyksu/btsGRd4vZhL/vOqca0E9w2JZAWm1Jjzfe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jyksu/btsGRd4vZhL/vOqca0E9w2JZAWm1Jjzfe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJyksu%2FbtsGRd4vZhL%2FvOqca0E9w2JZAWm1Jjzfe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;968&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;968&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;314&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6CB42/btsGRfVzUnK/N07n2FufZXkrbErXuTolK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6CB42/btsGRfVzUnK/N07n2FufZXkrbErXuTolK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6CB42/btsGRfVzUnK/N07n2FufZXkrbErXuTolK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6CB42%2FbtsGRfVzUnK%2FN07n2FufZXkrbErXuTolK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;274&quot; data-origin-width=&quot;314&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/124</guid>
      <comments>https://pipe0512.tistory.com/124#entry124comment</comments>
      <pubDate>Mon, 22 Apr 2024 20:58:46 +0900</pubDate>
    </item>
    <item>
      <title>[Dynamic Programming - 1] Intro</title>
      <link>https://pipe0512.tistory.com/123</link>
      <description>&lt;script&gt;MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} };&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Dynamic Programming&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: &lt;span style=&quot;color: #d83931;&quot;&gt;Problem을 더 쉽고, 작은 Problems로 나누어 solution을 찾는 &lt;/span&gt;방법이다. 우리가 풀어야하는 Problem은 Optimal Policy $\pi_*$를 찾는 것&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Property&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Dynamic Programming이 되기 위해서는 2가지 properties를 반드시 가져야한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Optimal substructure&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 나누어진 subproblems들의 optimal solution들을 구해서 합치면, original problem의 optimal solution이 되는 구조이다. 이는 즉, 각각의 state의 optimal solution을 합하면 entire problem의 optimal solution이 되는 구조이어야 한다는 뜻이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;$$ \pi_*(s_1) \to \pi_*(s_2) \to \pi_*(s_3) = \pi_* $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Overlapping subproblems&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 각 subproblem의 solution들은 서로 dependent하는 구조이다. Bellman optimality equations를 보면, State value(혹은 Action value)가 다른 State value(혹은 Action value)에 의존하고 있으며, 이는 Overlapping subproblems를 만족한다는 것을 알 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;What does DP exactly do?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ v_*(s) = \max_a\sum_{s',r}p(s',r|s,a)[r+\gamma v_*(s')] $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;$$ V(s) \gets \max_a\sum_{s',r}p(s',r|s,a)[r+\gamma V(s')] $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;첫번째 식인 Bellman Equation을 통해 두번째 식과같은 Update Rule로 만들어 Iterative하게 Improve하는 것이 Dynamic Programming이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 estimate 과정은 beginning이 accurate할 필요는 없다. iterative하게 improve되면 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Model of the environment&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP의 중요한 점은 Expected Value(기대값)을 사용하여 문제를 푸는 것이다. (not trial, or error) Action을 취할 때 발생할 수 있는 모든 가능한 결과를 고려하고 그것을 사용해 추정값을 업데이트한다. 따라서 DP를 사용하기 위해서는 현재 State에서 어떠한 Action을 취했을 때 어떠한 State로 변할지에대한 확률을 미리 알고있어야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex: $\pi(a|s) = [0.2, 0.3, 0.5]$&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 정보를 미리 알고있어야하는 상태 즉,&amp;nbsp;&lt;span style=&quot;color: #d83931;&quot;&gt;perfect model of the environment가 필요하다는 점은 Dynamic programming의 커다란 한계&lt;/span&gt;이다. 왜냐하면, 큐브를 푸는 것과같이 어떠한 축을 돌렸을 때 다음 결과가 명확한(perfect model of the environment)인 경우에는 괜찮지만 더 커다란 문제 혹은 model of the environment를 알 수 없는 경우에는 모든 가능한 결과를 고려할 수 없기 때문에 다른 알고리즘을 사용해야한다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>AI/RL</category>
      <author>pipes0512</author>
      <guid isPermaLink="true">https://pipe0512.tistory.com/123</guid>
      <comments>https://pipe0512.tistory.com/123#entry123comment</comments>
      <pubDate>Mon, 22 Apr 2024 20:42:51 +0900</pubDate>
    </item>
  </channel>
</rss>