<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>LimePencil's Log</title>
    <link>https://limepencil.tistory.com/</link>
    <description>ML, Programming, PS, 삶의 순간을 기록</description>
    <language>ko</language>
    <pubDate>Thu, 20 Aug 2026 10:28:09 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>연두색연필</managingEditor>
    <image>
      <title>LimePencil's Log</title>
      <url>https://tistory1.daumcdn.net/tistory/4940099/attach/0cf6ec14cff5402d9c57cb2391003761</url>
      <link>https://limepencil.tistory.com</link>
    </image>
    <item>
      <title>[논문 리뷰] An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale (ViT)</title>
      <link>https://limepencil.tistory.com/75</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2010.11929&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://arxiv.org/abs/2010.11929&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1750058850795&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale&quot; data-og-description=&quot;While the Transformer architecture has become the de-facto standard for natural language processing tasks, its applications to computer vision remain limited. In vision, attention is either applied in conjunction with convolutional networks, or used to rep&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2010.11929&quot; data-og-url=&quot;https://arxiv.org/abs/2010.11929v2&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d90sB7/hyY794whKJ/eKK6KOnMXpE8kKCzKTzc5k/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/pls2I/hyY72YDv1i/63Ta6kMFpm7SY1cYiTogw0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2010.11929&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2010.11929&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d90sB7/hyY794whKJ/eKK6KOnMXpE8kKCzKTzc5k/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/pls2I/hyY72YDv1i/63Ta6kMFpm7SY1cYiTogw0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;While the Transformer architecture has become the de-facto standard for natural language processing tasks, its applications to computer vision remain limited. In vision, attention is either applied in conjunction with convolutional networks, or used to rep&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Introduction&lt;/h2&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Self-attention 기반의 구조인 Transformers는 원래 자연어 처리(NLP)를 위해 개발되었습니다. 반면, 컴퓨터 비전(CV) 작업에서는 오랜 시간 동안 convolutional neural networks (CNNs)가 지배적이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;처음에는 self-attention과 CNN을 통합하려는 시도가 좋지 않은 결과를 보였습니다. Vision Transformer (ViT)는 이미지를 패치(patch)로 나누고 (transformer의 토큰(token)과 유사)각 패치를 선형으로 embedding하여 이를 표준 Transformer에 입력하는 새로운 방식을 제시했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size20&quot;&gt;ViT의 문제점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-pm-slice=&quot;3 5 []&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ImageNet과 같은 중간 크기의 데이터셋에서 성능이 좋지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CNN이 가진 inductive biases가 부족:&lt;/span&gt;&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Translation equivariance: 입력이 이동하면 출력도 일관되게 이동&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Locality: 공간적으로 인접한 특징을 강조 &lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 문제점들은 ImageNet에 더 많은 데이터셋을 추가하여 학습을 하면 더 좋을 성능을 낼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;Methodology&lt;br /&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;987&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0WvzC/btsOB6LLHno/XDSK5YZQVwhil9AwP4Yia0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0WvzC/btsOB6LLHno/XDSK5YZQVwhil9AwP4Yia0/img.png&quot; data-alt=&quot;Architecture of ViT&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0WvzC/btsOB6LLHno/XDSK5YZQVwhil9AwP4Yia0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0WvzC%2FbtsOB6LLHno%2FXDSK5YZQVwhil9AwP4Yia0%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;716&quot; height=&quot;443&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;987&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Architecture of ViT&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-pm-slice=&quot;3 5 []&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Patch Embedding&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;입력 이미지를 겹치지 않는 고정 크기 패치로 나눔&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;각 패치를 벡터로 선형 투영(linear projection)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;$\mathbf{x}_p \in \mathbb{R}^{H \times W \times C} \rightarrow \mathbf{x}_p \in \mathbb{R}^{N \times (P^2 \cdot C)}$, 여기서 $N$ &lt;/span&gt;&lt;span&gt;은 패치의 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;각 패치는 일정한 잠재 차원 $D$ &lt;/span&gt;&lt;span&gt;로 투영&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Class Token&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;학습 가능한 분류 토큰 ([CLS])이 입력 시퀀스 앞에 추가됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;BERT와 유사하게 종합적인 표현을 함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Positional Embedding&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;공간 순서를 유지하기 위해 1D 학습 가능한 positional embeddings 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;2D positional embeddings는 추가적인 이점이 제한적&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Transformer Encoder&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Multi-headed Self-Attention (MSA)과 MLP 블록이 번갈아 구성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Residual connections와 LayerNorm 포함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Classification Head&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;최종 [CLS] 토큰 표현을 MLP를 통해 분류&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Architecture&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;$$ &lt;br /&gt;z_0&amp;nbsp;=&amp;nbsp;[x_{\text{class}};&amp;nbsp;x_p^1&amp;nbsp;E;&amp;nbsp;x_p^2&amp;nbsp;E;&amp;nbsp;\cdots;&amp;nbsp;x_p^N&amp;nbsp;E]&amp;nbsp;+&amp;nbsp;E_{\text{pos}}&amp;nbsp;\tag{1} &lt;br /&gt;$$&lt;br /&gt;$$ &lt;br /&gt;E&amp;nbsp;\in&amp;nbsp;\mathbb{R}^{(P^2&amp;nbsp;\cdot&amp;nbsp;C)&amp;nbsp;\times&amp;nbsp;D},&amp;nbsp;\quad&amp;nbsp;E_{\text{pos}}&amp;nbsp;\in&amp;nbsp;\mathbb{R}^{(N+1)&amp;nbsp;\times&amp;nbsp;D} &lt;br /&gt;$$&lt;br /&gt;$$ &lt;br /&gt;z_{\ell}'&amp;nbsp;=&amp;nbsp;\mathrm{MSA}(\mathrm{LN}(z_{\ell&amp;nbsp;-&amp;nbsp;1}))&amp;nbsp;+&amp;nbsp;z_{\ell&amp;nbsp;-&amp;nbsp;1},&amp;nbsp;\quad&amp;nbsp;\ell&amp;nbsp;=&amp;nbsp;1,&amp;nbsp;\ldots,&amp;nbsp;L&amp;nbsp;\tag{2} &lt;br /&gt;$$&lt;br /&gt;$$ &lt;br /&gt;z_{\ell}&amp;nbsp;=&amp;nbsp;\mathrm{MLP}(\mathrm{LN}(z_{\ell}'))&amp;nbsp;+&amp;nbsp;z_{\ell}',&amp;nbsp;\quad&amp;nbsp;\ell&amp;nbsp;=&amp;nbsp;1,&amp;nbsp;\ldots,&amp;nbsp;L&amp;nbsp;\tag{3} &lt;br /&gt;$$&lt;br /&gt;$$ &lt;br /&gt;y&amp;nbsp;=&amp;nbsp;\mathrm{LN}(z_L^0)&amp;nbsp;\tag{4} &lt;br /&gt;$$&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;ViT의 Inductive Biases&lt;/span&gt;&lt;/h4&gt;
&lt;p data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ViT는 CNN과 같은 명시적인 inductive biases가 없지만, 로컬 및 글로벌 특징을 모두 학습합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;MSA는 장거리 의존성(long-range dependencies)을 포착&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;MLP 층은 로컬 상호작용(local interactions)을 촉진&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-pm-slice=&quot;1 1 []&quot;&gt;Hybrid ViT-CNN 아키텍처&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;낮은&amp;nbsp;해상도로&amp;nbsp;사전&amp;nbsp;학습된(pretrained)&amp;nbsp;ViT는&amp;nbsp;고해상도&amp;nbsp;입력으로&amp;nbsp;Fine-tuning&amp;nbsp;가능합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;패치 크기는 고정되고, 시퀀스 길이가 증가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;2D 보간(interpolation)으로 학습된 positional embeddings를 새 입력 해상도에 맞춤&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Experimental&amp;nbsp;Results&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Experimental Setup&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-pm-slice=&quot;3 5 []&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;사전 학습 데이터셋&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ImageNet (1.3M 이미지)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;ImageNet-21k (14M 이미지)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;JFT-300M (303M 이미지)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;평가 벤치마크&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ImageNet, CIFAR-10/100, VTAB (19개 작업), Oxford Pets, Flowers-102&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;모델 변형(variants)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ViT-Base, ViT-Large, ViT-Huge&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;비교 기준&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ResNet (BiT), Noisy Student (EfficientNet)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Key Findings&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccVAOk/btsODKHjpQu/zEk7k0WTdgHKiNstpN8Qgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccVAOk/btsODKHjpQu/zEk7k0WTdgHKiNstpN8Qgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccVAOk/btsODKHjpQu/zEk7k0WTdgHKiNstpN8Qgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccVAOk%2FbtsODKHjpQu%2FzEk7k0WTdgHKiNstpN8Qgk%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;1232&quot; height=&quot;608&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-pm-slice=&quot;3 5 []&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;성능&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;큰 데이터셋에서 사전 학습된 ViT는 CNN과 동등하거나 더 우수한 성능을 보임&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;ViT-H/14의 성능:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ImageNet: 88.55%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;CIFAR-100: 94.55%&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;VTAB: 77.63%&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;계산 효율성(Compute Efficiency)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ViT-H/14는 ResNet 기반 모델보다 적은 계산 자원(2.5k vs. 9.9k TPUv3-core-days)을 사용하며 더 좋은 성능을 보임&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;데이터 요구 사항&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ViT는 작은 데이터셋에서 CNN보다 성능이 낮음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;큰 규모의 데이터로 성능이 현저히 향상됨&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;확장성(Scalability)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;모델의 깊이, 너비 또는 패치 크기를 늘리면 성능이 향상됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;매우 큰 모델에서도 성능 포화(saturation) 징후가 없음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Few-Shot Learning&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ViT는 대규모 사전 학습의 혜택으로 Few-shot 분류에서 강력한 성능을 보임&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Self-Supervised Learning (Preliminary&amp;nbsp;Results)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Masked patch prediction은 ImageNet 정확도를 약 2% 향상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;여전히 supervised 사전 학습에 비해 성능이 낮음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Attention 시각화&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ViT는 로컬 및 글로벌 attention 패턴을 모두 나타냄&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Positional embeddings는 명시적 구조가 없어도 공간적 토폴로지를 포착&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/h2&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Vision Transformers는 이미지 특유의 inductive biases가 없지만, 큰 데이터셋에서 훈련될 경우 CNN과 비교하여 우수한 성능을 달성하고 있습니다. 확장성과 계산 효율성이 뛰어나며 Few-shot 및 Self-supervised 학습에서도 효과적입니다. Local and global dependency을 모델링할 수 있어 향후 CV문제들에 유망한 아키텍쳐입니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>CV</category>
      <category>ML</category>
      <category>tranformer</category>
      <category>Vision Transformer</category>
      <category>ViT</category>
      <category>논문</category>
      <category>리뷰</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/75</guid>
      <comments>https://limepencil.tistory.com/75#entry75comment</comments>
      <pubDate>Mon, 16 Jun 2025 17:03:12 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Grandmaster level in StarCraft II using multi-agent reinforcement learning (AlphaStar)</title>
      <link>https://limepencil.tistory.com/74</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;오늘은 학교에서 리뷰했던 논문을 블로그로 정리해보려고 한다. 이번 논문은 강화학습으로 스타크래프트 2를 학습을 하여 그랜드마스터의 MMR을 가진 agent를 만들었다. 알파고와 마찬가지로 네이쳐에 올라왔으며, 아주 복잡한 환경에서 강화학습을 어떻게 진행했는지를 아주 잘 보여주고 있다.&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;a href=&quot;https://www.nature.com/articles/s41586-019-1724-z&quot;&gt;Grandmaster level in StarCraft II using multi-agent reinforcement learning | Nature&lt;/a&gt;&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;스타크래프트란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타크래프트는 고난도의 전술을 세우면서 각 유닛들을 조종해야 하는 게임이다. 3가지 종족이 있고, 작은 베이스에서 시작해서 점점 빌딩을 짓고 유닛을 만들면서 상대방의 건물들을 부수면 이기는 게임이다.&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;왜 DeepMind는 스타크래프트를 골랐을까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 간단히 생각해 보면 더욱더 challenging 한 환경이었기 때문이라고 볼 수 있다. 알파고 같은 경우에는 371개의 action space가 있고 모든 정보가 주어져있는 심플한 환경이다. 하지만 스타크래프트 2는 10^26의 action space가 있고, 모든 정보가 주어져 있지 않는 고난도의 환경이다. 스타 2에서 API를 제공해서 그렇다고 생각해 볼 수도 있지만 스타크래프트는 전술게임 중에는 상당히 난도가 높고 조작이 어려운 환경이라고 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SS5pa/btsIx47aKD1/e3b48KWMKck50darKXHUKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SS5pa/btsIx47aKD1/e3b48KWMKck50darKXHUKk/img.jpg&quot; data-alt=&quot;Agent Input Space&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SS5pa/btsIx47aKD1/e3b48KWMKck50darKXHUKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSS5pa%2FbtsIx47aKD1%2Fe3b48KWMKck50darKXHUKk%2Fimg.jpg&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;676&quot; height=&quot;375&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Agent Input Space&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/siVi6/btsIxGSK8wd/zdDl3ha559FrLI6hlmqzg1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/siVi6/btsIxGSK8wd/zdDl3ha559FrLI6hlmqzg1/img.jpg&quot; data-alt=&quot;Agent Action Space&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/siVi6/btsIxGSK8wd/zdDl3ha559FrLI6hlmqzg1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsiVi6%2FbtsIxGSK8wd%2FzdDl3ha559FrLI6hlmqzg1%2Fimg.jpg&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;402&quot; height=&quot;183&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Agent Action Space&lt;/figcaption&gt;
&lt;/figure&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;이 두 표를 보면 얼마나 어려운 일인지를 알 수 있다. 10^26의 action space는 간단한 방법으로 explore 하거나 학습을 하기에는 무리가 있고, 이렇기 때문에 특별한 방법을 사용하여야 한다 이에 대해서는 추후에 서술하도록 하겠다. 특이한 점은 이 논문이 봇들처럼 엄청나게 높은 APM(action per minute)을 주거나 카메라 밖의 시야를 주지 않았다는 것이다. 즉, 인간과 같거나 더 높은 제한을 두고 학습을 시켰기 때문에 사람의 피지컬을 가지고 어떤 전술을 만들었는지 볼 수 있다.&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;AlphaStar에서의 policy&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정책은 deep neural network로 만들어졌고, 이 정책의 input은 그 전의 action과 observation이다. 또한 특이하게 전술 지표 z라는 것을 도입하였는데, 이는 게임 플레이어들의 처음 20개의 건물을 짓는 순서이다. 이 z를 사용하면서 초반의 비효율적인 시행착오를 스킵할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;107&quot; data-origin-height=&quot;48&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cniNtK/btsIyZ4QepO/lmEsGckDbesRnKUoSyZDEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cniNtK/btsIyZ4QepO/lmEsGckDbesRnKUoSyZDEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cniNtK/btsIyZ4QepO/lmEsGckDbesRnKUoSyZDEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcniNtK%2FbtsIyZ4QepO%2FlmEsGckDbesRnKUoSyZDEk%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;107&quot; height=&quot;48&quot; data-origin-width=&quot;107&quot; data-origin-height=&quot;48&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;133&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AFwDR/btsIye9iIds/4CkO8EkXmc8XUAXGhksma0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AFwDR/btsIye9iIds/4CkO8EkXmc8XUAXGhksma0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AFwDR/btsIye9iIds/4CkO8EkXmc8XUAXGhksma0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAFwDR%2FbtsIye9iIds%2F4CkO8EkXmc8XUAXGhksma0%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;133&quot; height=&quot;33&quot; data-origin-width=&quot;133&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AlphaStar의 아키텍처&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공간 정보 = feature map (CNN과 유사)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유닛 정보 = feature vectors&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;self-attention(transformer)을 사용하여 유닛과 attribute 사이의 관계를 프로세스 하기 위해 사용하였고, 이를 통해 다양한 관찰된 부분들을 dynamic 하게 집중할 수 있다&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;LSTM(Long short-term memory) = 시간의 변화에 따른 정보들을 처리한다 즉 context를 제공한다고 볼 수 있다&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;Hierarchical Action Representation = 액션 종류, 액션 매개변수, 그리고 auto-regressive 정책을 사용하여 순서대로 내려오면서 어떤 행동이 실행될지를 결정한다&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;Recurrent Pointer Network = 땅이나 유닛처럼 마우스 클릭으로 타깃을 선택해야 할 때 사용한다&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;Scatter Connection = 공간 정보와 비공간 정보 두 개를 합치는 방식인데, 이를 사용하여 벡터들을 공간에 흩어지게 하여 벡터들(ex 유닛들의 정보)을 위치에 corresponding 하게 바꾸어준다. 즉, 위치와 정보를 합친다고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmYqzE/btsIxgz2zvg/VVPCgegWmKWuF5y2UrB8LK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmYqzE/btsIxgz2zvg/VVPCgegWmKWuF5y2UrB8LK/img.png&quot; data-alt=&quot;성능이 올라가는 것을 볼 수 있다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmYqzE/btsIxgz2zvg/VVPCgegWmKWuF5y2UrB8LK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmYqzE%2FbtsIxgz2zvg%2FVVPCgegWmKWuF5y2UrB8LK%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;380&quot; height=&quot;174&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;성능이 올라가는 것을 볼 수 있다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PGodD/btsIyzrRfeA/n4a562NtfNIqQGl6gY7HVK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PGodD/btsIyzrRfeA/n4a562NtfNIqQGl6gY7HVK/img.jpg&quot; data-alt=&quot;전체 아키텍쳐 구조 (상당히 다양한 종류의 모델들이 사용되었다)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PGodD/btsIyzrRfeA/n4a562NtfNIqQGl6gY7HVK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPGodD%2FbtsIyzrRfeA%2Fn4a562NtfNIqQGl6gY7HVK%2Fimg.jpg&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;1280&quot; height=&quot;616&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전체 아키텍쳐 구조 (상당히 다양한 종류의 모델들이 사용되었다)&lt;/figcaption&gt;
&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Supervised Learning in AlphaStar&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;262&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YQxUJ/btsIx6RF9MJ/gvCK7GWm97k2zgkeHNVjs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YQxUJ/btsIx6RF9MJ/gvCK7GWm97k2zgkeHNVjs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YQxUJ/btsIx6RF9MJ/gvCK7GWm97k2zgkeHNVjs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYQxUJ%2FbtsIx6RF9MJ%2FgvCK7GWm97k2zgkeHNVjs0%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;262&quot; height=&quot;329&quot; data-origin-width=&quot;262&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;/figure&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;논문에서는 먼저 사람의 데이터를 사용하여 지도학습을 진행하였는데, 모방학습을 진행하였다고 볼 수 있다. 이렇게 하는 이유는 AlphaGo Zero 같은 경우는 action space가 그렇게 크지 않아서 그냥 학습을 진행할 수 있겠지만, 스타크래프트 같은 복잡한 환경은 그렇게 한다면 exploration에만 시간을 쓰게 되어서 성능이 좋아지지 않는다. 그래서 초반에 이런 사람이 플레이하는 것을 학습하면서 이를 해결할 수 있다.&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;사용된 데이터는 97만 개의 상위 22프로의 플레이들을 학습하였다. 그리고 정책은 사람이 다음 action을 어떤 것을 할지 예측하는 방식으로 학습하였다. 정책의 output은 확률분포로 나오고, KL-divergence로 사람과 agent 간의 차이를 계산한다. Adam optimizer이랑 L2 정규화가 사용되었다.&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;파인 튜닌은 MMR 6200 이상의 플레이어들을 사용하여 더 좋은 전략들을 학습할 수 있게 하였다.&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;Reinforcement Learning in AlphaStar&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp7bGn/btsIyBci9B7/8knkkkUpccZ5kDucePMOj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp7bGn/btsIyBci9B7/8knkkkUpccZ5kDucePMOj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp7bGn/btsIyBci9B7/8knkkkUpccZ5kDucePMOj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp7bGn%2FbtsIyBci9B7%2F8knkkkUpccZ5kDucePMOj1%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;324&quot; height=&quot;383&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;615&quot;/&gt;&lt;/span&gt;&lt;/figure&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;이렇게 initialize 된 정책들은 self-play와 league training을 통해 강화학습으로 더 학습을 진행한다. 보상 같은 경우에는 이기면 +1, 지면 -1, 동점은 0이다. 이렇게 sparse 하게 주어진 reward는 학습이 어렵기 때문에 전술 z를 따라가면 pseudo-reward를 부여한다. Temporal-difference learning을 사용하여 value-function을 학습하고, v-trace와 UPGO를 사용하여 policy function을 학습하였다. 또한, KL-divergence를 사용하여 supervised policy와 벗어나지 않도록 정책을 학습시킨다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yk8sF/btsIzUIJMHu/JKw62rLb9IFDqLMBxcKcO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yk8sF/btsIzUIJMHu/JKw62rLb9IFDqLMBxcKcO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yk8sF/btsIzUIJMHu/JKw62rLb9IFDqLMBxcKcO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyk8sF%2FbtsIzUIJMHu%2FJKw62rLb9IFDqLMBxcKcO0%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;439&quot; height=&quot;148&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;204&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HPav2/btsIyKtkMOE/HnymDDeFKcVSL3hcdvfV1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HPav2/btsIyKtkMOE/HnymDDeFKcVSL3hcdvfV1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HPav2/btsIyKtkMOE/HnymDDeFKcVSL3hcdvfV1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHPav2%2FbtsIyKtkMOE%2FHnymDDeFKcVSL3hcdvfV1k%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;414&quot; height=&quot;178&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;League training&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;921&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/du0ook/btsIyfN8gzi/Knmr7ugsjPNhcojSiJqAm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/du0ook/btsIyfN8gzi/Knmr7ugsjPNhcojSiJqAm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/du0ook/btsIyfN8gzi/Knmr7ugsjPNhcojSiJqAm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdu0ook%2FbtsIyfN8gzi%2FKnmr7ugsjPNhcojSiJqAm1%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;854&quot; height=&quot;921&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;921&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Multi-Agent Learning: competes against various versions of itself and other agents.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;League Training: AlphaStar uses a league of agents to ensure diverse and robust training.main agents: learn strategies by playing against various opponents, including its past versions, other main agents, and exploiters&lt;/li&gt;
&lt;li&gt;main exploiters: accelerate the main agent&amp;rsquo;s learning by presenting it with difficult and targeted challenges.&lt;/li&gt;
&lt;li&gt;league&amp;nbsp;exploiters:&amp;nbsp;exploit&amp;nbsp;weaknesses&amp;nbsp;not&amp;nbsp;only&amp;nbsp;in&amp;nbsp;the&amp;nbsp;main&amp;nbsp;agent&amp;nbsp;but&amp;nbsp;in&amp;nbsp;other&amp;nbsp;agents&amp;nbsp;within&amp;nbsp;the&amp;nbsp;league&amp;nbsp;as&amp;nbsp;well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Limitation&amp;nbsp;of&amp;nbsp;self-play:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;1. Cycle of Strategies:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;can lead to cycles where the agent repeatedly switches between a set of strategies without progressing.&lt;/li&gt;
&lt;li&gt;occurs when an agent learns a strategy to defeat its current opponent, then the opponent learns a counter-strategy, and the cycle continues without overall improvement.&lt;/li&gt;
&lt;li&gt;Ex) In StarCraft II, the agent might oscillate between aggressive rush tactics and defensive strategies without finding a stable, superior strategy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Lack of Diversity:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the agent predominantly learns to counter its own strategies.&lt;/li&gt;
&lt;li&gt;vulnerable&amp;nbsp;to&amp;nbsp;novel&amp;nbsp;strategies&amp;nbsp;that&amp;nbsp;it&amp;nbsp;has&amp;nbsp;not&amp;nbsp;encountered&amp;nbsp;during&amp;nbsp;training.&lt;/li&gt;
&lt;/ul&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;h2 data-ke-size=&quot;size26&quot;&gt;Types of Self-Play&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fictitious Self-Play(FSP): avoids cycle by playing with all players in the league&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;too&amp;nbsp;much&amp;nbsp;waste&amp;nbsp;of&amp;nbsp;resources&amp;nbsp;against&amp;nbsp;agents&amp;nbsp;with&amp;nbsp;100%&amp;nbsp;win&amp;nbsp;rate&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Prioritized Fictitious Self-Play(PFSP): put weights on the matchmaking in the league to provide a good learning signal&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;using 2 different curricula, it can improve by fighting with hard opponents and opponents around its level&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Agents in AlphaStar&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Main agent is trained on 35% SP, 50% PFSP against all past players in the league, and an additional 15% of PFSP matches against forgotten main players the agent can no longer beat and past main exploiters.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;copy&amp;nbsp;of&amp;nbsp;the&amp;nbsp;main&amp;nbsp;agent&amp;nbsp;is&amp;nbsp;added&amp;nbsp;as&amp;nbsp;new&amp;nbsp;play&amp;nbsp;in&amp;nbsp;league&amp;nbsp;every&amp;nbsp;2&amp;nbsp;billion&amp;nbsp;steps&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;League exploiters are trained using PFSP and their frozen copies are added to the league when they defeat all players in the league in more than 70% of games, or after a timeout of 2 billion steps.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;a 25% probability that the agent is reset to the supervised parameters.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;because&amp;nbsp;league&amp;nbsp;agents&amp;nbsp;are&amp;nbsp;not&amp;nbsp;robust&amp;nbsp;themselves&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;p data-ke-size=&quot;size16&quot;&gt;Main exploiters play against main agents.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;50% of the time when the current probability of winning is lower than 20%, exploiters use PFSP with fvar weighting over players created by the main agents, forming curriculum that facilitates learning&lt;/li&gt;
&lt;li&gt;Otherwise&amp;nbsp;there&amp;nbsp;is&amp;nbsp;enough&amp;nbsp;learning&amp;nbsp;signal&amp;nbsp;and&amp;nbsp;it&amp;nbsp;plays&amp;nbsp;against&amp;nbsp;the&amp;nbsp;current&amp;nbsp;main&amp;nbsp;agents.&amp;nbsp;These&amp;nbsp;agents&amp;nbsp;are&amp;nbsp;added&amp;nbsp;to&amp;nbsp;the&amp;nbsp;league&amp;nbsp;whenever&amp;nbsp;all&amp;nbsp;three&amp;nbsp;main&amp;nbsp;agents&amp;nbsp;are&amp;nbsp;defeated&amp;nbsp;in&amp;nbsp;more&amp;nbsp;than&amp;nbsp;70%&amp;nbsp;of&amp;nbsp;games,&amp;nbsp;or&amp;nbsp;after&amp;nbsp;a&amp;nbsp;timeout&amp;nbsp;of&amp;nbsp;4&amp;nbsp;billion&amp;nbsp;steps,&amp;nbsp;then&amp;nbsp;reset&amp;nbsp;to&amp;nbsp;the&amp;nbsp;supervised&amp;nbsp;parameters.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uyPkp/btsIzTC4u75/UKKrJ2nromc5KhhjwlnKik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uyPkp/btsIzTC4u75/UKKrJ2nromc5KhhjwlnKik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uyPkp/btsIzTC4u75/UKKrJ2nromc5KhhjwlnKik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuyPkp%2FbtsIzTC4u75%2FUKKrJ2nromc5KhhjwlnKik%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;1228&quot; height=&quot;414&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Restriction on Agents&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;Action&amp;nbsp;per&amp;nbsp;Minute&amp;nbsp;(APM)&amp;nbsp;Limits:&amp;nbsp;executing&amp;nbsp;at&amp;nbsp;most&amp;nbsp;22&amp;nbsp;non-duplicate&amp;nbsp;actions&amp;nbsp;every&amp;nbsp;5&amp;nbsp;seconds.&lt;br /&gt;&lt;br /&gt;2. Delay in Actions: Human players experience a delay between perceiving the game state and executing an action.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;There is an average delay of about 110 milliseconds between the command of action and the actual execution&lt;/li&gt;
&lt;li&gt;Also,&amp;nbsp;agents&amp;nbsp;decide&amp;nbsp;when&amp;nbsp;to&amp;nbsp;observe&amp;nbsp;next&amp;nbsp;(avg.&amp;nbsp;370ms)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Camera Interface: Human players control the game through a screen interface, limited by what they can see and interact with at any given time.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;could&amp;nbsp;only&amp;nbsp;act&amp;nbsp;on&amp;nbsp;information&amp;nbsp;visible&amp;nbsp;within&amp;nbsp;the&amp;nbsp;camera&amp;nbsp;view.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8elER/btsIyfN8krn/KMLZevlRg8ZsrDKea2oKqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8elER/btsIyfN8krn/KMLZevlRg8ZsrDKea2oKqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8elER/btsIyfN8krn/KMLZevlRg8ZsrDKea2oKqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8elER%2FbtsIyfN8krn%2FKMLZevlRg8ZsrDKea2oKqK%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;345&quot; height=&quot;98&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8EtEk/btsIzN3XvJO/wk8mSQR1NQzHLk4Z6chkGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8EtEk/btsIzN3XvJO/wk8mSQR1NQzHLk4Z6chkGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8EtEk/btsIzN3XvJO/wk8mSQR1NQzHLk4Z6chkGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8EtEk%2FbtsIzN3XvJO%2Fwk8mSQR1NQzHLk4Z6chkGk%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;363&quot; height=&quot;206&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;334&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Results&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lfgDT/btsIzTwipqh/TebiOTq7kqK4tIYB1U5KdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lfgDT/btsIzTwipqh/TebiOTq7kqK4tIYB1U5KdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lfgDT/btsIzTwipqh/TebiOTq7kqK4tIYB1U5KdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlfgDT%2FbtsIzTwipqh%2FTebiOTq7kqK4tIYB1U5KdK%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;1196&quot; height=&quot;540&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 보면 Main Agent가 성능이 상당히 높은 것을 보여주고 있다. Main exploiter 같은 경우에는 성능이 오르지 않고 있는데, 이는 main agent만 상대하면 되기에 general 한 성능을 보여줄 필요가 없다. 이 논문을 통해 large-scale에서 어떻게 강화학습을 진행해야 하는지 알 수 있는 실험이었다고 생각한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bbsnB7/btsIx38fV7A/he7OKL7NKFtOLffRtg6NIK/Grandmaster-level-in-StarCraft-II-using-multi_agent.pdf?attach=1&amp;amp;knm=tfile.pdf&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Grandmaster-level-in-StarCraft-II-using-multi_agent.pdf&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;7.66MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>alphastar</category>
      <category>DeepMind</category>
      <category>RL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/74</guid>
      <comments>https://limepencil.tistory.com/74#entry74comment</comments>
      <pubDate>Sat, 13 Jul 2024 00:30:06 +0900</pubDate>
    </item>
    <item>
      <title>[SQL 배우기] Section 8. Creating Databases and Tables</title>
      <link>https://limepencil.tistory.com/73</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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Data types in SQL:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Boolean&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;True, False&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Character&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;char, varchar, text&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Numeric&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;integer, float&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Temporal&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;date, time, timestamp, interval&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;UUID&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Array&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JSON&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/datatype.html&quot;&gt;PostgreSQL: Documentation: 16: Chapter&amp;nbsp;8.&amp;nbsp;Data Types&lt;/a&gt;&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Primary key: a column or a group of columns used to identify a row uniquely in a table\&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;represented by [PK] in pgAdmin&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Foreign key: a field or group of fields that references the primary key of the other table&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Constraint: rules enforced on data columns table&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;prevent invalid data&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Divided into Column constraint and Table constraint:&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Common Column constraint:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;NOT NULL&lt;/b&gt; constraint&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;UNIQUE&lt;/b&gt; constraint&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;PRIMARY&lt;/b&gt; Key&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;FOREIGN&lt;/b&gt; Key&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;CHECK&lt;/b&gt; constraint&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;ensures that all values in a column satisfy certain conditions&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;EXCLUSION&lt;/b&gt; constraint&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;ensures that if any two rows are compared on the specified column or expression using the specified operator, not all of these comparisons will return TRUE&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Common Table constraint:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;**CHECK (**condition)&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;to check conditions when inserting or updating data&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;REFERENCES&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;to constrain the value stored in the column that must exist in a column in another table&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;UNIQUE&lt;/b&gt; (column_list)&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;forces the values stored in the columns listed inside the parentheses to be unique&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;PRIMARY KEY&lt;/b&gt; (column list)&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;allows you to define the primary key that consists of multiple columns&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;The general syntax for creating a table:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;CREATE table table_name ( column_name TYPE column_constraint, column_name TYPE column_constraint, table_constraint table_constraint ) INHERITS existing_table_name;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SERIAL&lt;/b&gt;: creates a sequence object and sets the next value generated by the sequence as the default value for the column&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;perfect for &lt;b&gt;PRIMARY&lt;/b&gt; key&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;does not adjust for deletion&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;INSERT&lt;/b&gt;: allow to add rows to a table&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;general syntax: &lt;b&gt;INSERT INTO&lt;/b&gt; table (column1, column 2, &amp;hellip;) &lt;b&gt;VALUES&lt;/b&gt; (value1, value2, &amp;hellip;), (value1, value2, &amp;hellip;), &amp;hellip;.;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SERIAL&lt;/b&gt; columns do not need to be provided a value&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;UPDATE&lt;/b&gt;: allows change of values of the columns&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;general syntax: &lt;b&gt;UPDATE&lt;/b&gt; table &lt;b&gt;SET&lt;/b&gt; column1 = value1, column2 = value2, &amp;hellip; &lt;b&gt;WHERE&lt;/b&gt; condition;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;without WHERE, everything is reseted&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;update from another table: &lt;b&gt;UPDATE&lt;/b&gt; tableA &lt;b&gt;SET&lt;/b&gt; original_col = tableB.new_col &lt;b&gt;FROM&lt;/b&gt; tableB &lt;b&gt;WHERE&lt;/b&gt; &lt;a href=&quot;http://tableA.id&quot;&gt;tableA.id&lt;/a&gt; = &lt;a href=&quot;http://tableB.id&quot;&gt;tableB.id&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;return affected rows UPDATE table SET column=value RETURNING column1, column2&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;DELETE&lt;/b&gt;: remove rows from the table&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;DELETE FROM&lt;/b&gt; table &lt;b&gt;WHERE&lt;/b&gt; row_id = 1&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;DELETE FROM&lt;/b&gt; tableA &lt;b&gt;USING&lt;/b&gt; tableB &lt;b&gt;WHERE&lt;/b&gt; &lt;a href=&quot;http://tableA.id&quot;&gt;tableA.id&lt;/a&gt; = &lt;a href=&quot;http://tableB.id&quot;&gt;tableB.id&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;ALTER&lt;/b&gt;: allows for changes to an existing table structure&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;adding, dropping, or renaming columns&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;changing a column&amp;rsquo;s data type&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;set DEFAULT values for a column&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Add CHECK constraints&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Rename table&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;General Syntax &lt;b&gt;ALTER TABLE&lt;/b&gt; table_name action&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;DROP&lt;/b&gt;: allows the complete removal of a column in a table&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;General Syntax &lt;b&gt;ALTER TABLE&lt;/b&gt; table_name &lt;b&gt;DROP COLUMN&lt;/b&gt; col_name&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;CHECK&lt;/b&gt;: allows the creation of more customized constraints that adhere to a certain condition&lt;/span&gt;&lt;/p&gt;</description>
      <category>Development/SQL</category>
      <category>SQL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/73</guid>
      <comments>https://limepencil.tistory.com/73#entry73comment</comments>
      <pubDate>Tue, 12 Mar 2024 01:03:59 +0900</pubDate>
    </item>
    <item>
      <title>[SQL 배우기] Section 6. Advanced SQL Commands</title>
      <link>https://limepencil.tistory.com/72</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/the-complete-sql-bootcamp/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Webindex_Catchall_la.EN_cc.KR&amp;amp;utm_term=_._ag_149093701617_._ad_665676441083_._kw__._de_c_._dm__._pl__._ti_dsa-19959388920_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=CjwKCAiA1-6sBhAoEiwArqlGPkxxpqV_VbBmMWgLudW--9WWVj0tWQvC0EjP9DdPKos7xTtTj-7aexoCzwgQAvD_BwE&amp;amp;couponCode=ST15MT31224&quot;&gt;The Complete SQL Bootcamp for the Manipulation and Analysis of Data | Udemy&lt;/a&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Types of time information:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;TIME&lt;/b&gt;: time&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;DATE&lt;/b&gt;: date&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;TIMESTAMP&lt;/b&gt;: time, date&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;TIMESTAMPTZ&lt;/b&gt;: date, time, and timezone&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;The time information cannot be added although it can be removed&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SHOW ALL&lt;/b&gt;: shows all the metadata related to the database&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;can show other details by using other functions such as:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SHOW TIMEZONE&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT NOW()&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT TIMEOFDAY()&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT CURRENT_TIME&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT CURRENT_DATE&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;EXTRACT()&lt;/b&gt;: allows the user to obtain a sub-component of a date value&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;EXTRACT&lt;/b&gt;(&lt;b&gt;YEAR FROM&lt;/b&gt; date_col)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;AGE()&lt;/b&gt;: calculates and returns the current age given a timestamp&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;AGE&lt;/b&gt;(date_col)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;TO_CHAR()&lt;/b&gt;: function to convert data types to text&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;TO_CHAR&lt;/b&gt;(date_col,&amp;rsquo;mm-dd-yyyy&amp;rsquo;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;a href=&quot;https://www.postgresql.org/docs/12/functions-formatting.html&quot;&gt;PostgreSQL: Documentation: 12: 9.8.&amp;nbsp;Data Type Formatting Functions&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Mathematical functions and operators:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;can be used to perform mathematical operations on columns&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;a href=&quot;https://www.postgresql.org/docs/9.5/functions-math.html&quot;&gt;PostgreSQL: Documentation: 9.5: Mathematical Functions and Operators&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;String functions and operators:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;can perform manipulations on strings&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;a href=&quot;https://www.postgresql.org/docs/9.1/functions-string.html&quot;&gt;PostgreSQL: Documentation: 9.1: String Functions and Operators&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Subquery&lt;/b&gt;: can construct complex queries, by performing a query on the result of another query&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;involves two &lt;b&gt;SELECT&lt;/b&gt; statement&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;involves parentheses that contain a &lt;b&gt;SELECT&lt;/b&gt; statement&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;EXISTS&lt;/b&gt;: used to test for the existence of rows in a subquery&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT&lt;/b&gt; column_name &lt;b&gt;FROM&lt;/b&gt; table_name &lt;b&gt;WHERE&lt;/b&gt; EXISTS (&lt;b&gt;SELECT&lt;/b&gt; column_name &lt;b&gt;FROM&lt;/b&gt; table_name &lt;b&gt;WHERE&lt;/b&gt; condition)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Self-join&lt;/b&gt;: joining within the same table as if the tables are different&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT&lt;/b&gt; tableA.col, tableB.col &lt;b&gt;FROM&lt;/b&gt; table &lt;b&gt;AS&lt;/b&gt; tableA &lt;b&gt;JOIN&lt;/b&gt; table &lt;b&gt;AS&lt;/b&gt; tableB &lt;b&gt;ON&lt;/b&gt; tableA.some_col = tableB.other_col&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;requires the use of an alias&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Development/SQL</category>
      <category>SQL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/72</guid>
      <comments>https://limepencil.tistory.com/72#entry72comment</comments>
      <pubDate>Tue, 12 Mar 2024 01:02:30 +0900</pubDate>
    </item>
    <item>
      <title>[SQL 배우기] Section 5. JOINS</title>
      <link>https://limepencil.tistory.com/71</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/the-complete-sql-bootcamp/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Webindex_Catchall_la.EN_cc.KR&amp;amp;utm_term=_._ag_149093701617_._ad_665676441083_._kw__._de_c_._dm__._pl__._ti_dsa-19959388920_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=CjwKCAiA1-6sBhAoEiwArqlGPkxxpqV_VbBmMWgLudW--9WWVj0tWQvC0EjP9DdPKos7xTtTj-7aexoCzwgQAvD_BwE&amp;amp;couponCode=ST15MT31224&quot;&gt;The Complete SQL Bootcamp for the Manipulation and Analysis of Data | Udemy&lt;/a&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;&lt;b&gt;AS&lt;/b&gt;: creates an alias for a column to be called into a different name&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SELECT&lt;/b&gt; column &lt;b&gt;AS&lt;/b&gt; new_name &lt;b&gt;FROM&lt;/b&gt; table&lt;/li&gt;
&lt;li&gt;we cannot use an alias inside the &lt;b&gt;WHERE&lt;/b&gt; operator because it gets executed at the very end of a query&lt;/li&gt;
&lt;li&gt;useful for renaming the output of the aggregate function&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JOIN&lt;/b&gt;: allows to combine multiple tables&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;main reason for different JOIN types is to decide how to deal with information only present in one of the joined tables&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;INNER JOIN&lt;/b&gt;: result with the set of records that match in &lt;b&gt;both&lt;/b&gt; tables&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SELECT&lt;/b&gt; * &lt;b&gt;FROM&lt;/b&gt; tableA &lt;b&gt;INNER JOIN&lt;/b&gt; tableB &lt;b&gt;ON&lt;/b&gt; tableA.col_match = tableB.col_match&lt;/li&gt;
&lt;li&gt;symmetrical&lt;/li&gt;
&lt;li&gt;matching column is a duplicate column&lt;/li&gt;
&lt;li&gt;in PostgreSQL, &lt;b&gt;JOIN&lt;/b&gt; = &lt;b&gt;INNER JOIN&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FULL OUTER JOIN&lt;/b&gt;: set of records that are in either or both of the tables&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SELECT&lt;/b&gt; * &lt;b&gt;FROM&lt;/b&gt; tableA &lt;b&gt;FULL OUTER JOIN&lt;/b&gt; tableB &lt;b&gt;ON&lt;/b&gt; tableA.col_match = tableB.col_match&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;910&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8bbof/btsFHrwSnRn/9YMfyOoeDkUmvuKzXMe0bK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8bbof/btsFHrwSnRn/9YMfyOoeDkUmvuKzXMe0bK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8bbof/btsFHrwSnRn/9YMfyOoeDkUmvuKzXMe0bK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8bbof%2FbtsFHrwSnRn%2F9YMfyOoeDkUmvuKzXMe0bK%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;333&quot; height=&quot;221&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;910&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Symmetrical&lt;/li&gt;
&lt;li&gt;filling empty values with null&lt;/li&gt;
&lt;li&gt;using &lt;b&gt;WHERE&lt;/b&gt; can be used to filter null columns&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LEFT OUTER JOIN&lt;/b&gt;: set of records that are in the left table, and values that are not in the right table are considered null&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SELECT&lt;/b&gt; * &lt;b&gt;FROM&lt;/b&gt; tableA &lt;b&gt;LEFT JOIN&lt;/b&gt; tableB &lt;b&gt;ON&lt;/b&gt; tableA.col_match = tableB.col_match&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;943&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvWXhZ/btsFIumogkN/Z9o5pTywJ8xAKewzxOAVKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvWXhZ/btsFIumogkN/Z9o5pTywJ8xAKewzxOAVKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvWXhZ/btsFIumogkN/Z9o5pTywJ8xAKewzxOAVKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvWXhZ%2FbtsFIumogkN%2FZ9o5pTywJ8xAKewzxOAVKK%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;352&quot; height=&quot;242&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;943&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Order matters&lt;/li&gt;
&lt;/ul&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;b&gt;RIGHT OUTER JOIN&lt;/b&gt;: set of records that are in the right table, and values that are not in the left table are considered null&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SELECT&lt;/b&gt; * &lt;b&gt;FROM&lt;/b&gt; tableA &lt;b&gt;RIGHT&lt;/b&gt; &lt;b&gt;JOIN&lt;/b&gt; tableB &lt;b&gt;ON&lt;/b&gt; tableA.col_match = tableB.col_match&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;956&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d4oq7K/btsFHqLyn6A/JHwjjZ4tVv606KqT1A1jZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d4oq7K/btsFHqLyn6A/JHwjjZ4tVv606KqT1A1jZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d4oq7K/btsFHqLyn6A/JHwjjZ4tVv606KqT1A1jZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd4oq7K%2FbtsFHqLyn6A%2FJHwjjZ4tVv606KqT1A1jZ1%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;352&quot; height=&quot;246&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;956&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Order matters&lt;/li&gt;
&lt;/ul&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;b&gt;UNION&lt;/b&gt;: concatenating two tables together&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SELECT&lt;/b&gt; column_names &lt;b&gt;FROM&lt;/b&gt; table1 &lt;b&gt;UNION&lt;/b&gt; &lt;b&gt;SELECT&lt;/b&gt; column_names &lt;b&gt;FROM&lt;/b&gt; table2&lt;/li&gt;
&lt;li&gt;should match in length&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Development/SQL</category>
      <category>SQL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/71</guid>
      <comments>https://limepencil.tistory.com/71#entry71comment</comments>
      <pubDate>Tue, 12 Mar 2024 01:00:56 +0900</pubDate>
    </item>
    <item>
      <title>[SQL 배우기] Section 3. GROUP BY Statements</title>
      <link>https://limepencil.tistory.com/70</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Aggregate function&lt;/b&gt;: take multiple inputs and return a single output&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;AVG(), COUNT(), MAX(), MIN(), SUM()&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;can only happen in the &lt;b&gt;SELECT&lt;/b&gt; or &lt;b&gt;HAVING&lt;/b&gt; clause&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;ordering result of the aggregate function requires &lt;b&gt;ORDER BY&lt;/b&gt; reference to the entire function&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;GROUP BY&lt;/b&gt;: allows for the aggregation of columns by some category&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;must appear right after a &lt;b&gt;FROM&lt;/b&gt; or &lt;b&gt;WHERE&lt;/b&gt; statement&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;you can use an aggregate function with it&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;in the &lt;b&gt;SELECT&lt;/b&gt; statement, columns must either have an aggregate function or be in the &lt;b&gt;GROUP BY&lt;/b&gt; call&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;WHERE&lt;/b&gt; statement should not refer to the aggregation result&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;HAVING&lt;/b&gt;: allows for filtering after aggregation&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;WHERE cannot be used to filter based on aggregated results&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Development/SQL</category>
      <category>SQL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/70</guid>
      <comments>https://limepencil.tistory.com/70#entry70comment</comments>
      <pubDate>Tue, 12 Mar 2024 00:58:02 +0900</pubDate>
    </item>
    <item>
      <title>[SQL 배우기] Section 2. SQL Statement Fundamentals</title>
      <link>https://limepencil.tistory.com/69</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/the-complete-sql-bootcamp/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Webindex_Catchall_la.EN_cc.KR&amp;amp;utm_term=_._ag_149093701617_._ad_665676441083_._kw__._de_c_._dm__._pl__._ti_dsa-19959388920_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=CjwKCAiA1-6sBhAoEiwArqlGPkxxpqV_VbBmMWgLudW--9WWVj0tWQvC0EjP9DdPKos7xTtTj-7aexoCzwgQAvD_BwE&amp;amp;couponCode=ST15MT31224&quot;&gt;The Complete SQL Bootcamp for the Manipulation and Analysis of Data | Udemy&lt;/a&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT&lt;/b&gt;: most common statement used to retrieve information from a table&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT&lt;/b&gt; column_name &lt;b&gt;FROM&lt;/b&gt; table_name&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;using * instead of the column name retrieves all the columns&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;separate column names by a comma for multiple columns&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;using capital letters for SQL keywords helps with visualization&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT DISTINCT&lt;/b&gt;: used to return distinct values in columns&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT DISTINCT&lt;/b&gt; column_name &lt;b&gt;FROM&lt;/b&gt; table_name&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;parenthesis can be used around column name for better clarity&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;COUNT&lt;/b&gt;: returns the number of input rows that match a specific condition of a query&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT COUNT&lt;/b&gt; (column_name/results) &lt;b&gt;FROM&lt;/b&gt; table_name;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;needs parenthesis&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT COUNT&lt;/b&gt;(*) &lt;b&gt;FROM&lt;/b&gt; table_name&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;returns the number of rows in a table&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;more useful when used with keywords like DISTINCT&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT WHERE&lt;/b&gt;: allows to specify conditions on columns for the rows to be returned (filtering&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT&lt;/b&gt; column_names &lt;b&gt;FROM&lt;/b&gt; table_names &lt;b&gt;WHERE&lt;/b&gt; conditions&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Comparison operators&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;=,&amp;gt;,&amp;lt;,&amp;gt;=,&amp;lt;=, (&amp;lt;&amp;gt; or !=)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Logical operators&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;AND, OR, NOT&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;ORDER BY&lt;/b&gt;: sort rows based on a column value (ascending or descending)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SELECT&lt;/b&gt; columns &lt;b&gt;FROM&lt;/b&gt; table &lt;b&gt;ORDER BY&lt;/b&gt; columns &lt;b&gt;ASC/DESC&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;LIMIT&lt;/b&gt;: limit the number of rows returned for a query&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;LIMIT&lt;/b&gt; num_of_rows&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;only viewing a few rows to get an idea of the table&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;useful with &lt;b&gt;ORDER BY&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;goes to the end of the query&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;BETWEEN&lt;/b&gt;: used to match a value against a range of values&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;value &lt;b&gt;BETWEEN&lt;/b&gt; low &lt;b&gt;AND&lt;/b&gt; high&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;inclusive&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;can be used with dates when it is in YYYY-MM-DD format&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;IN&lt;/b&gt;: creates a condition to check if a value is included in a list of options&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;value &lt;b&gt;IN&lt;/b&gt; (option1, option2, option3, option_n)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;LIKE&lt;/b&gt;: pattern matching with string data using wildcard characters&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;%&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;matches any sequence of characters&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;putting % in the back of the character is looking for matching in the beginning, and vice versa&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;_&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;matches any single character (replacing a single character)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;can use multiple underscores&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;ILIKE&lt;/b&gt;: case-insensitive version of &lt;b&gt;LIKE&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Development/SQL</category>
      <category>SQL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/69</guid>
      <comments>https://limepencil.tistory.com/69#entry69comment</comments>
      <pubDate>Tue, 12 Mar 2024 00:56:56 +0900</pubDate>
    </item>
    <item>
      <title>[SQL 배우기] Section 1. Course Introduction</title>
      <link>https://limepencil.tistory.com/68</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/the-complete-sql-bootcamp/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Webindex_Catchall_la.EN_cc.KR&amp;amp;utm_term=_._ag_149093701617_._ad_665676441083_._kw__._de_c_._dm__._pl__._ti_dsa-19959388920_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=CjwKCAiA1-6sBhAoEiwArqlGPkxxpqV_VbBmMWgLudW--9WWVj0tWQvC0EjP9DdPKos7xTtTj-7aexoCzwgQAvD_BwE&amp;amp;couponCode=ST15MT31224&quot;&gt;The Complete SQL Bootcamp for the Manipulation and Analysis of Data | Udemy&lt;/a&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Database&lt;/b&gt;: systems that allow users to store and organize large amounts of data&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;made up of tables that consist of columns and rows&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;SQL&lt;/b&gt;(Structured Query Language): programming language used to communicate with the database&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;pgAdmin: a &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Query Tool can be used to perform queries on the database&lt;/span&gt;&lt;/p&gt;</description>
      <category>Development/SQL</category>
      <category>SQL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/68</guid>
      <comments>https://limepencil.tistory.com/68#entry68comment</comments>
      <pubDate>Tue, 12 Mar 2024 00:53:51 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 9. Kubernetes on Cloud</title>
      <link>https://limepencil.tistory.com/67</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&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;The hosted cloud solution allows for the maintenance of VMs, which makes it easy to scale and manage.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Microsoft Azure&lt;/li&gt;
&lt;li&gt;Amazon AWS&lt;/li&gt;
&lt;li&gt;Google Cloud&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Google Kubernetes Engine (GKE)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;877&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T6YRf/btsDhxyASpn/TpXnaIdljzKoIkKHmz4ha0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T6YRf/btsDhxyASpn/TpXnaIdljzKoIkKHmz4ha0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T6YRf/btsDhxyASpn/TpXnaIdljzKoIkKHmz4ha0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT6YRf%2FbtsDhxyASpn%2FTpXnaIdljzKoIkKHmz4ha0%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;2000&quot; height=&quot;877&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;877&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The cluster can be created easily by configuring it in the Google Cloud console&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The load balancer is configured automatically by using Google&amp;rsquo;s load balancer.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Amazon Elastic Kubernetes Service (EKS)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lejS3/btsC78guH9F/iulcZjDsIKWE1f4mOKFkr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lejS3/btsC78guH9F/iulcZjDsIKWE1f4mOKFkr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lejS3/btsC78guH9F/iulcZjDsIKWE1f4mOKFkr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlejS3%2FbtsC78guH9F%2FiulcZjDsIKWE1f4mOKFkr1%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;2000&quot; height=&quot;1000&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Azure Kubernetes Service (AKS)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;813&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rDEbk/btsC83lF2lM/oXlD7wJMIyRQeQMCVVytUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rDEbk/btsC83lF2lM/oXlD7wJMIyRQeQMCVVytUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rDEbk/btsC83lF2lM/oXlD7wJMIyRQeQMCVVytUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrDEbk%2FbtsC83lF2lM%2FoXlD7wJMIyRQeQMCVVytUK%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;2000&quot; height=&quot;813&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;813&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/67</guid>
      <comments>https://limepencil.tistory.com/67#entry67comment</comments>
      <pubDate>Tue, 9 Jan 2024 15:11:22 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 8. Microservices Architecture</title>
      <link>https://limepencil.tistory.com/66</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&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;Each stack of the applications can be separated into different containers to be individual microservices.&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;b&gt;docker run --links&lt;/b&gt;: connects the docker containers by name&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;Service is created to connect between pods for microservices. (Use NodePort and ClusterIP)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;service is not needed for ports that do not require exposed port&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/66</guid>
      <comments>https://limepencil.tistory.com/66#entry66comment</comments>
      <pubDate>Tue, 9 Jan 2024 15:08:29 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 7. Services</title>
      <link>https://limepencil.tistory.com/65</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&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;&lt;b&gt;Services&lt;/b&gt; enable loose coupling between microservice Kubernetes setups.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;It forwards requests to a port to another port&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Types of services:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;NodePort&lt;/b&gt;: internal port accessible to external port&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ClusterIP&lt;/b&gt;: virtual IP inside a cluster to connect applications&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LoadBalancer&lt;/b&gt;: distribute work among different pods&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;NodePort&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NodePort consists of 3 ports where they are connected all together&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;TargetPort: port of the pod&lt;/li&gt;
&lt;li&gt;Port: port of the service&lt;/li&gt;
&lt;li&gt;NodePort: port of the node&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;To link the service to the pod, the section under the &amp;ldquo;label&amp;rdquo; of the pod must go under the selector section of the service definition file.&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;b&gt;kubectl get services&lt;/b&gt;: get a list of services in Kubernetes&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;A random algorithm balances the request load when multiple pods of the same label are assigned to the service.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;when the pods are distributed across different nodes, Kubernetes automatically configures service for all the nodes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ClusterIP&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Services can be created for each application so that Kubernetes will configure which pod of the service will be connected to another pod of other services.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;This way, the user does not have to configure for IP address of each pod&lt;/li&gt;
&lt;li&gt;Effective for microservices&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;LoadBalancer&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Setting the service type as LoadBalancer automatically configures one external IP/domain for the end user to easily access cloud services like GCP, Azure, and AWS.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;instead of having 4 URLs for each of the pods, a single load balancer can give the user access to a single URL.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/65</guid>
      <comments>https://limepencil.tistory.com/65#entry65comment</comments>
      <pubDate>Tue, 9 Jan 2024 12:53:04 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 6. Networking in Kubernetes</title>
      <link>https://limepencil.tistory.com/64</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&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;An internal IP address is assigned to a pod.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;For multiple nodes, the internal network IP is the same for pods in different nodes, so custom configurations must be made for networking.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;All containers can communicate with one another without NAT(using an IP address)&lt;/li&gt;
&lt;li&gt;All nodes can communicate with all containers and vice versa without NAT&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There are many solutions for networking in Kubernetes.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;This allows the routing of the network to a virtual network which redirects.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/64</guid>
      <comments>https://limepencil.tistory.com/64#entry64comment</comments>
      <pubDate>Tue, 9 Jan 2024 12:49:46 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 5. Kubernetes Concepts - Pods, ReplicaSets, Deployments</title>
      <link>https://limepencil.tistory.com/63</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pods&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The Kubernetes pod definition file contains 4 top-level fields:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;apiVersion&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the version of Kubernetes version used&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;kind&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the kind of service that is created
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) Pod, Service, ReplicaSet, Deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;metadata&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;data of the object such as name and labels
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;under label property, we can set whatever key-value pair we want&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;spec&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;where containers are defined along with their image and name&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl apply -f [name of the file].yaml&lt;/b&gt;: creates pod according to the YAML file in the argument&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Replication Controllers and ReplicaSets&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;&lt;b&gt;Replication Controller:&lt;/b&gt; allows running of multiple pods of the same image for high availability&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ensures a specified number of pods are running at a time&lt;/li&gt;
&lt;li&gt;can span across multiple nodes to scale the application&lt;/li&gt;
&lt;li&gt;in the spec section of the YAML file
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;template:&lt;/b&gt; The YAML file of the pod is copied&lt;/li&gt;
&lt;li&gt;&lt;b&gt;replicas&lt;/b&gt;: the number of replicas is specified&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ReplicaSets&lt;/b&gt;: newer technology that is replacing replication controllers&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;apiVersion&lt;/b&gt; needs to be specified as apps/v1&lt;/li&gt;
&lt;li&gt;&lt;b&gt;spec&lt;/b&gt; section is almost the same except that there is one more field to it
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;selector&lt;/b&gt;: monitors pods with specified labels unlike replication controllers
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;so if pods of the same labels are already running when ReplicaSets are created, it does not create a new one until one fails&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scaling ReplicaSet:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;change the replica filed of the YAML file and run &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;kubectl replace -f [filename]&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;use &lt;b&gt;kubectl scale --replicas=[number of replicas] -f [filename]&lt;/b&gt; command&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Deployment&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Rolling Updates&lt;/b&gt;: Upgrading instances one by one to maintain availability&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;two ReplicaSets&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Deployment&lt;/b&gt;: wraps around ReplicaSet to update the instance seamlessly and control changes&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;The definition file is almost the same as ReplicaSet except that the section for kind is changed to Deployment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl get all&lt;/b&gt;: lists all the objects created in the Kubernetes such as pods, ReplicaSets, deployments&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;b&gt;Rollout&lt;/b&gt; is triggered when a new deployment is created.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the revision number increases when there is a newer version
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;this allows us to keep track of the revision history&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl rollout status [deployment name]&lt;/b&gt;: see the current status of the rollout&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl rollout history [deployment name]&lt;/b&gt;: see the history of the deployment&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;Deployment strategy:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;(Bad) Destroying all the instances and creating updated new instance
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;(Good) Taking down one instance and bringing up a new instance for availability (Rolling Update)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&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;b&gt;kubectl apply -f [YAML file name]&lt;/b&gt;: updates the current running instance to a newer version&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl rollout undo [deployment name]&lt;/b&gt;: goes back to older format by destroying the current instance&lt;/p&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/63</guid>
      <comments>https://limepencil.tistory.com/63#entry63comment</comments>
      <pubDate>Tue, 9 Jan 2024 12:38:59 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 4. YAML Introduction</title>
      <link>https://limepencil.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&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;YAML: data representation format like JSON&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Key-Value Pair&lt;/h3&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;Fruit: Apple
Vegetable: Carrot
Liquid: Water
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Array/Lists&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;Fruits:
- Orange
- Banana
- Apple
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Dictionary/Map&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Banana:
	Calories: 105
	Fat: 0.4g
	Carbs: 27g
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The spacing in front of each item must be equal. If the spacing is different, it is treated as a sub-dictionary.&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;Order is important for arrays, unlike dictionaries.&lt;/p&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/62</guid>
      <comments>https://limepencil.tistory.com/62#entry62comment</comments>
      <pubDate>Tue, 9 Jan 2024 12:31:25 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 3. Kubernetes Concepts</title>
      <link>https://limepencil.tistory.com/61</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&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;&lt;b&gt;Kubernetes pods&lt;/b&gt;: a single instance of the application that encapsulates containers&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;to bring up more instances of an application, the number of pods must be increased&lt;/li&gt;
&lt;li&gt;the smallest unit in Kubernetes&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A single pod can have multiple containers of different types. It can include helper containers.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;within the same pod, they can interact with each other with the local network and share the same storage space&lt;/li&gt;
&lt;li&gt;when the pod dies, all the containers inside it die&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl run [name] --image [image name]&lt;/b&gt;: initiates single pod of an image&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl get pods&lt;/b&gt;: get the information of pods&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;-o wide&lt;/b&gt; option shows where the node is running&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl describe pod [name of pod]&lt;/b&gt;: explains in detail about a single pod&lt;/p&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/61</guid>
      <comments>https://limepencil.tistory.com/61#entry61comment</comments>
      <pubDate>Tue, 9 Jan 2024 11:57:55 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes 배우기] Section 2. Kubernetes Overview</title>
      <link>https://limepencil.tistory.com/60</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-kubernetes/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Kubernetes_Search_la.EN_cc.KR&amp;amp;utm_term=_._ag_151486538358_._ad_663749074276_._kw__._de_c_._dm__._pl__._ti_dsa-2099944694778_._li_1030718_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gclid=Cj0KCQiAv8SsBhC7ARIsALIkVT2x9d4fqbCT_yUiclwxxn9pnWJxF8gao6-pXoxBqhIfsf2dMQiRQXMaAjFUEALw_wcB&quot;&gt;Kubernetes for the Absolute Beginners - Hands-on | Udemy&lt;/a&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;&lt;b&gt;Node&lt;/b&gt;: machine where Kubernetes is installed&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cluster&lt;/b&gt;: Group of nodes&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Master node&lt;/b&gt;: Another node that controls cluster(worker nodes)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kube-APIserver is installed&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Worker node&lt;/b&gt;: where the actual computation is going on&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubelet is installed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG68Ny/btsC519rsbe/dAjuyKmwQpRXVK4oVK1Lck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG68Ny/btsC519rsbe/dAjuyKmwQpRXVK4oVK1Lck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG68Ny/btsC519rsbe/dAjuyKmwQpRXVK4oVK1Lck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG68Ny%2FbtsC519rsbe%2FdAjuyKmwQpRXVK4oVK1Lck%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;1260&quot; height=&quot;617&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;617&quot;/&gt;&lt;/span&gt;&lt;/figure&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;Components of Kubernetes:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;API server&lt;/b&gt;: where the user interacts to control the Kubernetes server&lt;/li&gt;
&lt;li&gt;&lt;b&gt;etcd&lt;/b&gt;: distributed key-value storage&lt;/li&gt;
&lt;li&gt;&lt;b&gt;kubelet&lt;/b&gt;: agent in each node that checks if the worker node is running as expected&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Container Runtime&lt;/b&gt;: software to run container (ex. Docker)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Controller&lt;/b&gt;: checks for container status(whether it is down), and brings out new containers if needed&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Scheduler&lt;/b&gt;: distributing load across nodes and containers&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Container runtime and kubelet are in the worker node while other components are in the master node.&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;b&gt;kubectl&lt;/b&gt;: used to deploy and manage applications on the Kubernetes cluster&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl run&lt;/b&gt;: deploy an application on the cluster&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl cluster-info&lt;/b&gt;: get information about the cluster&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubectl get nodes&lt;/b&gt;: get nodes in the cluster&lt;/p&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>K8s</category>
      <category>Kubernetes</category>
      <category>쿠버네티스</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/60</guid>
      <comments>https://limepencil.tistory.com/60#entry60comment</comments>
      <pubDate>Tue, 9 Jan 2024 11:56:47 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 9. Container Orchestration - Docker Swarm &amp;amp; Kubernetes</title>
      <link>https://limepencil.tistory.com/59</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&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;Container Orchestration is used to host multiple containers over multiple hosts by using scripts and codes.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Some solution scales containers automatically and even scale hosts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;2000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzfTSg/btsCo4Mptg1/icqnbrHv70jQ2k24nOrVsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzfTSg/btsCo4Mptg1/icqnbrHv70jQ2k24nOrVsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzfTSg/btsCo4Mptg1/icqnbrHv70jQ2k24nOrVsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzfTSg%2FbtsCo4Mptg1%2FicqnbrHv70jQ2k24nOrVsk%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;453&quot; height=&quot;453&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;2000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Famous container orchestration solutions:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Docker Swarm&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;Mesos&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Swarm&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Distributes containers over many hosts for higher availability and load balancing&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;938&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LrN31/btsCtncEk9G/TTO3q2yE8WVXDK581Vj84K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LrN31/btsCtncEk9G/TTO3q2yE8WVXDK581Vj84K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LrN31/btsCtncEk9G/TTO3q2yE8WVXDK581Vj84K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLrN31%2FbtsCtncEk9G%2FTTO3q2yE8WVXDK581Vj84K%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;651&quot; height=&quot;305&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;938&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In order to set up a docker swarm, one of the hosts must be a swarm manager while the others are workers.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Running &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker swarm init&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; in the swarm manager starts docker swarm and provides instructions to set up other workers&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker service create --replicas=[number of containers]:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; runs determined amount of containers distributed across worker nodes&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Kubernetes&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;kubectl run --replicas=[number of containers]&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;: runs replica of container across multiple nodes&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;kubectl scale&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;: scales container by a determined amount&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kubernetes can automatically scale up and down based on the load.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Allows rolling back&lt;/li&gt;
&lt;li&gt;Various authentication methods&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1826&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bovXU6/btsCr7nTIpE/SA9WGcXVSP0iWuD26KykWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bovXU6/btsCr7nTIpE/SA9WGcXVSP0iWuD26KykWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bovXU6/btsCr7nTIpE/SA9WGcXVSP0iWuD26KykWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbovXU6%2FbtsCr7nTIpE%2FSA9WGcXVSP0iWuD26KykWk%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;456&quot; height=&quot;416&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1826&quot;/&gt;&lt;/span&gt;&lt;/figure&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;Nodes are grouped by &lt;b&gt;cluster&lt;/b&gt; and it is controlled by the &lt;b&gt;master&lt;/b&gt; node.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DevOps/Docker</category>
      <category>docker</category>
      <category>도커</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/59</guid>
      <comments>https://limepencil.tistory.com/59#entry59comment</comments>
      <pubDate>Fri, 22 Dec 2023 00:04:20 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 8. Docker on Mac &amp;amp; Windows</title>
      <link>https://limepencil.tistory.com/58</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Working on Docker on Windows:&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker toolbox&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;virtual box for VM (Oracle)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Desktop for Windows&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;uses Microsoft Hyper-V as a virtual box&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Windows containers&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Windows Server containers
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;one VM for various containers&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Hyper-V isolation
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;running within each VM&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Working on Docker on Mac:&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker toolbox&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;virtual box for VM (Oracle)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Desktop for Mac&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;use HyperKit virtualization technology&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>DevOps/Docker</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/58</guid>
      <comments>https://limepencil.tistory.com/58#entry58comment</comments>
      <pubDate>Thu, 21 Dec 2023 23:36:23 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 7. Docker Engine, Storage, and Networking</title>
      <link>https://limepencil.tistory.com/57</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&gt;&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;Docker Engine&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker Engine is composed of:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker CLI&lt;/b&gt;: running command
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;does not have to be on the same machine with other parts
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;can use the &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker -H&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; option to connect to the remote docker-engine&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;REST API&lt;/b&gt;: interact with docker Deamon&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Deamon&lt;/b&gt;: running in the background to execute tasks&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PID&lt;/b&gt;: id for a process that is unique to the process&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PhYi3/btsCsnxdCqU/3ns7fOS4SVZPcvtG10eknk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PhYi3/btsCsnxdCqU/3ns7fOS4SVZPcvtG10eknk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PhYi3/btsCsnxdCqU/3ns7fOS4SVZPcvtG10eknk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPhYi3%2FbtsCsnxdCqU%2F3ns7fOS4SVZPcvtG10eknk%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;548&quot; height=&quot;383&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PID can have the same name for both the system and the container, but the PID in the container is changed into a different PID on the system&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There is no limit to how much a container can utilize the resources.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;using &lt;b&gt;--cpus&lt;/b&gt; and &lt;b&gt;--memory&lt;/b&gt; in the &lt;b&gt;docker run&lt;/b&gt; can limit the resources used by a container&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Storage&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;By using layered architecture, it greatly reduces the storage size by reusing the existing layer.&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;When a container is running, a new layer called &amp;ldquo;container layer&amp;rdquo; is put on top of other layers where modifications can happen.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;The container layer is read/write while image layers are read only.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;To modify a file in image layers, it is copied to the container layer before writing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker volume&lt;/b&gt;: used to create volume in the docker file system which can be connected to the container layer later on&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mounting volume without creating it creates the&lt;/li&gt;
&lt;li&gt;&lt;b&gt;docker run -v [local]:[internal]&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Network&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mapping the network of the container to the host allows it to share the same port with the host.&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;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker network create:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; used to create another internal network within the docker host.&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;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker network ls:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; lists all network&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;By using &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker inspect&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;, the network of a container can be checked.&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;Docker has a built-in DNS server that allows to access another container by name and not internal IP addresses&lt;/p&gt;</description>
      <category>DevOps/Docker</category>
      <category>docker</category>
      <category>도커</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/57</guid>
      <comments>https://limepencil.tistory.com/57#entry57comment</comments>
      <pubDate>Thu, 21 Dec 2023 23:33:14 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 6. Docker Registry</title>
      <link>https://limepencil.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&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;Image naming convention: [User]/[Image]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) nginx/nginx&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker registry&lt;/b&gt;: where images are stored online&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GCR(Google Container Registry), docker hub&lt;/li&gt;
&lt;li&gt;private registry can be accessed using &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker login&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;one can set up a docker registry in a private machine by running a registry container&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DevOps/Docker</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/56</guid>
      <comments>https://limepencil.tistory.com/56#entry56comment</comments>
      <pubDate>Thu, 21 Dec 2023 23:29:23 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 5. Docker Compose</title>
      <link>https://limepencil.tistory.com/55</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dohUO0/btsCpgFRy9K/ZxSeG55pCRpUtSt0Mixbi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dohUO0/btsCpgFRy9K/ZxSeG55pCRpUtSt0Mixbi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dohUO0/btsCpgFRy9K/ZxSeG55pCRpUtSt0Mixbi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdohUO0%2FbtsCpgFRy9K%2FZxSeG55pCRpUtSt0Mixbi0%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;695&quot; height=&quot;395&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker-compose&lt;/b&gt;: allows to run and manage multiple containers with a single YAML file&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dictionary with the image name, and under each image name, put parameters as key-value pairs&lt;/li&gt;
&lt;li&gt;putting build under the image name builds the image first before running the container&lt;/li&gt;
&lt;li&gt;by using version 2 of docker-compose, the images are all linked
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;need to specify &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;version: 2&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; on the top&lt;/li&gt;
&lt;li&gt;can add &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;depend_on:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; under the image name to show dependency between containers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;by using version 3, docker swarm can be used&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker run --link [host: internal]&lt;/b&gt;: links containers with each other so that it is accessible within a container&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;3327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc5Dtb/btsCuN2Yen5/R2OFSvZswcN3ICgcgoL0KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc5Dtb/btsCuN2Yen5/R2OFSvZswcN3ICgcgoL0KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc5Dtb/btsCuN2Yen5/R2OFSvZswcN3ICgcgoL0KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc5Dtb%2FbtsCuN2Yen5%2FR2OFSvZswcN3ICgcgoL0KK%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;275&quot; height=&quot;457&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;3327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;networks&lt;/b&gt; can be set as the argument by specifying the network under the image name&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;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker-compose up:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; runs all the containers specified in the YAML file&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;References:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;https://docs.docker.com/compose/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/compose/&quot;&gt;https://docs.docker.com/engine/reference/commandline/compose/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/dockersamples/example-voting-app&quot;&gt;https://github.com/dockersamples/example-voting-app&lt;/a&gt;&lt;/p&gt;</description>
      <category>DevOps/Docker</category>
      <category>docker</category>
      <category>도커</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/55</guid>
      <comments>https://limepencil.tistory.com/55#entry55comment</comments>
      <pubDate>Thu, 21 Dec 2023 22:46:34 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 4. Docker Images</title>
      <link>https://limepencil.tistory.com/54</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blqhim/btsCoD85W2G/ZMEzg6I4OOdv86Ycaa4ZK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blqhim/btsCoD85W2G/ZMEzg6I4OOdv86Ycaa4ZK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blqhim/btsCoD85W2G/ZMEzg6I4OOdv86Ycaa4ZK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fblqhim%2FbtsCoD85W2G%2FZMEzg6I4OOdv86Ycaa4ZK1%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;464&quot; height=&quot;464&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;464&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Dockerfile&lt;/b&gt; can be used to make a custom docker image.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;FROM:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; starting image from another image&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;RUN:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; executes certain commands behind it&lt;/li&gt;
&lt;li&gt;&lt;b&gt;COPY:&lt;/b&gt; copy certain files to the image&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;ENTRYPOINT:&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; specify a command that runs when the container is started
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the parameter can be delivered by appending the parameter to &lt;b&gt;docker run&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ENV&lt;/b&gt;: specify environmental variable
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;can also be used as &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker run -e [variable]&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CMD&lt;/b&gt;: specifies the command to run when docker starts, but unlike ENTRYPOINT, it can be overwritten when &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker run&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;docker build&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;: used to create a docker image from Dockerfile&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the commands in the Dockerfile are made into layers that build on top of each other
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;faster rebuild due to caching&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;b&gt;docker push&lt;/b&gt;: pushes the image to the public hub&lt;/p&gt;</description>
      <category>DevOps/Docker</category>
      <category>docker</category>
      <category>도커</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/54</guid>
      <comments>https://limepencil.tistory.com/54#entry54comment</comments>
      <pubDate>Thu, 21 Dec 2023 22:37:48 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 3. Docker Run</title>
      <link>https://limepencil.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&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;&lt;b&gt;docker run&lt;/b&gt; with tag: by putting: after the image name allows for the specification of version/tag&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;if not specified, the latest tag is used&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker run -i&lt;/b&gt;: open the container with an interactive mode where input is possible&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;b&gt;docker run -it&lt;/b&gt;: open the container with an interactive mode where input is possible and the console turns into a pseudo-terminal&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;b&gt;docker run -p [local port]:[internal port]&lt;/b&gt;: maps the port to an internal port&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;b&gt;docker run -v [local directory]:[internal directory]&lt;/b&gt;: maps the volume to an internal volume so that the data will not be erased even if after the container is exited&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;b&gt;docker&amp;nbsp;inspect&lt;/b&gt;:&amp;nbsp;used&amp;nbsp;to&amp;nbsp;find&amp;nbsp;details&amp;nbsp;about&amp;nbsp;a&amp;nbsp;container&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;b&gt;docker logs&lt;/b&gt;: allows to view the logs of a container&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;useful for background running container&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DevOps/Docker</category>
      <category>docker</category>
      <category>도커</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/53</guid>
      <comments>https://limepencil.tistory.com/53#entry53comment</comments>
      <pubDate>Thu, 21 Dec 2023 22:28:22 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 2. Docker Commands</title>
      <link>https://limepencil.tistory.com/52</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&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;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;docker run&lt;/span&gt;: runs the container&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;downloads the image if it is not locally stored&lt;/li&gt;
&lt;li&gt;appending a command behind allows execution of the command after running the container&lt;/li&gt;
&lt;li&gt;running the container with &lt;span style=&quot;background-color: #f3c000;&quot;&gt;-d&lt;/span&gt; tag allows it to run in the background and not on the console&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;docker ps&lt;/span&gt;: lists current running containers&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;by adding &lt;span style=&quot;background-color: #f3c000;&quot;&gt;-a&lt;/span&gt;, it also shows stopped or exited containers&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;docker stop&lt;/span&gt;: stops a running container by ID or name&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker rm: remove a container&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;not able to be seen with &lt;span style=&quot;background-color: #f3c000;&quot;&gt;docker ps -a&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;docker images&lt;/span&gt;: lists current downloaded images&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;background-color: #f3c000;&quot;&gt;docker rmi&lt;/span&gt;: removes downloaded image by name&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;background-color: #f3c000;&quot;&gt;docker pull&lt;/span&gt;: downloads an image without running it&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;The container runs as long as the process inside is running. The completed process exits the container.&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;background-color: #f3c000;&quot;&gt;docker exec&lt;/span&gt;: executes the command to a running container&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;background-color: #f3c000;&quot;&gt;docker attach&lt;/span&gt;: attaches to a running background container&lt;/p&gt;</description>
      <category>DevOps/Docker</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/52</guid>
      <comments>https://limepencil.tistory.com/52#entry52comment</comments>
      <pubDate>Wed, 20 Dec 2023 19:28:59 +0900</pubDate>
    </item>
    <item>
      <title>[Docker 배우기] Section 1. Introduction</title>
      <link>https://limepencil.tistory.com/51</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/learn-docker/&quot;&gt;Docker for the Absolute Beginner - Hands On - DevOps | Udemy&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Overview&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker allows to run each &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;service&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; with its dependencies in &lt;b&gt;separate&lt;/b&gt; containers.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Containers&lt;/b&gt;: a completely independent environment that runs on OS kernels&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) Linux kernel: allows to run CentOS, Fedora, etc&lt;/li&gt;
&lt;li&gt;Cannot run Windows container on Linux kernel&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VM vs Containers&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U8pwk/btsCjYYGowe/ZeUgHmoN8eG5yxXHLOPKi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U8pwk/btsCjYYGowe/ZeUgHmoN8eG5yxXHLOPKi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U8pwk/btsCjYYGowe/ZeUgHmoN8eG5yxXHLOPKi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU8pwk%2FbtsCjYYGowe%2FZeUgHmoN8eG5yxXHLOPKi0%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;627&quot; height=&quot;317&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table id=&quot;42eacc77-5466-4125-9d9f-9409e432c18e&quot; style=&quot;border-collapse: collapse; width: 100%; height: 95px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt; VM&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt; Container &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;a3c4e3f9-3969-4ffb-a1f2-bba56d9bb538&quot; style=&quot;height: 17px;&quot;&gt;
&lt;td id=&quot;vGAi&quot; style=&quot;height: 17px;&quot;&gt;Uses Hypervisor&lt;/td&gt;
&lt;td id=&quot;fqhW&quot; style=&quot;height: 17px;&quot;&gt;Uses container engine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;916b0a62-1c1e-4640-8cda-b2fd40b470fd&quot; style=&quot;height: 17px;&quot;&gt;
&lt;td id=&quot;vGAi&quot; style=&quot;height: 17px;&quot;&gt;Multiple OS&lt;/td&gt;
&lt;td id=&quot;fqhW&quot; style=&quot;height: 17px;&quot;&gt;Single OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;5fc43855-dfc8-49e3-b2dc-63cefbaf109c&quot; style=&quot;height: 17px;&quot;&gt;
&lt;td id=&quot;vGAi&quot; style=&quot;height: 17px;&quot;&gt;Heavy Utilization and Size&lt;/td&gt;
&lt;td id=&quot;fqhW&quot; style=&quot;height: 17px;&quot;&gt;Light in size and utilization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;e3d4420a-cb79-45bc-a6e0-b2a99bacbe76&quot; style=&quot;height: 17px;&quot;&gt;
&lt;td id=&quot;vGAi&quot; style=&quot;height: 17px;&quot;&gt;Slow Booting&lt;/td&gt;
&lt;td id=&quot;fqhW&quot; style=&quot;height: 17px;&quot;&gt;Fast Booting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;00cbd8dd-6ff1-4117-82c9-35aa9a406cc4&quot; style=&quot;height: 17px;&quot;&gt;
&lt;td id=&quot;vGAi&quot; style=&quot;height: 17px;&quot;&gt;Resources are independent&lt;/td&gt;
&lt;td id=&quot;fqhW&quot; style=&quot;height: 17px;&quot;&gt;Resources can be shared&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;p data-ke-size=&quot;size16&quot;&gt;Containers and VMs can be used together to use the good side of both.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Docker image&lt;/b&gt;: template of container&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Like a class in programming&lt;/li&gt;
&lt;li&gt;Can be pushed to the Docker Hub for public availability&lt;/li&gt;
&lt;li&gt;Guarantees the environment runs in the same way everywhere&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Docker container&lt;/b&gt;: instances of image&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Like objects in programming&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker can be installed by following the instructions below.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.docker.com/engine/install/&quot;&gt;Install Docker Engine | Docker Docs&lt;/a&gt;&lt;/p&gt;</description>
      <category>DevOps/Docker</category>
      <category>container</category>
      <category>docker</category>
      <category>도커</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/51</guid>
      <comments>https://limepencil.tistory.com/51#entry51comment</comments>
      <pubDate>Tue, 19 Dec 2023 22:03:49 +0900</pubDate>
    </item>
    <item>
      <title>[The Rust Programming Language] Ch. 3: Common Programming Concepts Variables and Mutability</title>
      <link>https://limepencil.tistory.com/50</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.1&amp;nbsp;Variables&amp;nbsp;and&amp;nbsp;Mutability&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;By default, variables are immutable.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Once the variable is set to &lt;b&gt;immutable&lt;/b&gt;, you cannot change the value. Rust automatically finds the error and tries to fix it before compiling it.&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let x = 5;
    println!(&quot;The value of x is: {x}&quot;);
    x = 6;
    println!(&quot;The value of x is: {x}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
error[E0384]: cannot assign twice to immutable variable `x`
 --&amp;gt; src/main.rs:4:5
  |
2 |     let x = 5;
  |         -
  |         |
  |         first assignment to `x`
  |         help: consider making this binding mutable: `mut x`
3 |     println!(&quot;The value of x is: {x}&quot;);
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

For more information about this error, try `rustc --explain E0384`.
error: could not compile `variables` due to previous error&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rust compiler exactly pinpoints where and what the error is. This ensures bugless code.&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let mut x = 5;
    println!(&quot;The value of x is: {x}&quot;);
    x = 6;
    println!(&quot;The value of x is: {x}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;adding &lt;code&gt;mut&lt;/code&gt; in front of the variable&amp;rsquo;s name makes it so that the value of the variable can be changed.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Constants&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;constants&lt;/b&gt;: values that are bound to a name and not allowed to change. It is stated by &lt;code&gt;const&lt;/code&gt; statement.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;mut&lt;/code&gt; is not able to be used with &lt;code&gt;consts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;convention of the naming is to use uppercase and underscore between words.&lt;/li&gt;
&lt;li&gt;valid for the entire time a program runs, within the scope in which they were declared.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Shadowing&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Shadowing&lt;/b&gt;: declaring a new variable with the same name as a previous variable&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!(&quot;The value of x in the inner scope is: {x}&quot;);
    }

    println!(&quot;The value of x is: {x}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;When applying shadowing in the inner scope, the variable only temporarily shadows the variable of the outer scope.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It is different with &lt;code&gt;mut&lt;/code&gt; because &lt;b&gt;shadowing&lt;/b&gt; is creating a new variable by using the &lt;code&gt;let&lt;/code&gt; keyword.&lt;/p&gt;
&lt;h1&gt;3.2 Data Types&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rust is a &lt;i&gt;statically typed&lt;/i&gt; language, which means that it &lt;b&gt;must know&lt;/b&gt; the types of all variables at compile time.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the compiler usually can infer the data type, but for some cases like &lt;code&gt;parse&lt;/code&gt;, the type of the variable must be explicitly stated with &lt;code&gt;:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-rust&quot;&gt;  let guess: u32 = &quot;42&quot;.parse().expect(&quot;Not a number!&quot;);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Data type subsets in Rust:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Scalar&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Integers&lt;/li&gt;
&lt;li&gt;Floating-point numbers&lt;/li&gt;
&lt;li&gt;Booleans&lt;/li&gt;
&lt;li&gt;Characters&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Compound&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Tuples&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Scalar Types - Integers&lt;/h2&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Length&lt;/th&gt;
&lt;th&gt;Signed&lt;/th&gt;
&lt;th&gt;Unsigned&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8-bit&lt;/td&gt;
&lt;td&gt;i8&lt;/td&gt;
&lt;td&gt;u8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16-bit&lt;/td&gt;
&lt;td&gt;i16&lt;/td&gt;
&lt;td&gt;u16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32-bit&lt;/td&gt;
&lt;td&gt;i32&lt;/td&gt;
&lt;td&gt;u32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64-bit&lt;/td&gt;
&lt;td&gt;i64&lt;/td&gt;
&lt;td&gt;u64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128-bit&lt;/td&gt;
&lt;td&gt;i128&lt;/td&gt;
&lt;td&gt;u128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;architecture&lt;/td&gt;
&lt;td&gt;isize&lt;/td&gt;
&lt;td&gt;usize&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The size of &lt;code&gt;usize&lt;/code&gt; and &lt;code&gt;isize&lt;/code&gt; is dependent on whether the computer&amp;rsquo;s architecture is &lt;b&gt;32-bit or 64-bit.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Integer literal can be written in many forms. (Refer to table below)&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Number literals&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Decimal&lt;/td&gt;
&lt;td&gt;98_222&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hex&lt;/td&gt;
&lt;td&gt;0xff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Octal&lt;/td&gt;
&lt;td&gt;0o77&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary&lt;/td&gt;
&lt;td&gt;0b1111_0000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Byte (u8 only)&lt;/td&gt;
&lt;td&gt;b'A'&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;To avoid overflow and underflow, the following methods can be used.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Wrap in all modes with the &lt;code&gt;wrapping_*&lt;/code&gt; methods, such as &lt;code&gt;wrapping_add&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Return the &lt;code&gt;None&lt;/code&gt; value if there is an overflow with the &lt;code&gt;checked_*&lt;/code&gt; methods.&lt;/li&gt;
&lt;li&gt;Return the value and a boolean indicating whether there was overflow with the &lt;code&gt;overflowing_*&lt;/code&gt; methods.&lt;/li&gt;
&lt;li&gt;Saturate at the value&amp;rsquo;s minimum or maximum values with the &lt;code&gt;saturating_*&lt;/code&gt; methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Scalar Types - Floating-Point Types&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rust&amp;rsquo;s floating-point types are &lt;code&gt;f32&lt;/code&gt; and &lt;code&gt;f64&lt;/code&gt;, which are 32 bits and 64 bits in size.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IEEE-754 standard&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Scalar Types - The Boolean Type&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Specified by &lt;code&gt;bool&lt;/code&gt;, the possible values are &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Scalar Types - The Character Type&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;char&lt;/code&gt; type is the alphabetic type of Rust. Char literal can be specified by using a single quote.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Compound Types - The Tuple Type&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A &lt;b&gt;tuple&lt;/b&gt; is a general way of grouping together a number of values with a variety of types into one compound type&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fixed in size&lt;/li&gt;
&lt;li&gt;wrapped in brackets and separated by comma&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let tup = (500, 6.4, 1);

    let (x, y, z) = tup;

    println!(&quot;The value of y is: {y}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pattern matching can be used to destructure a tuple.&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let five_hundred = x.0;

    let six_point_four = x.1;

    let one = x.2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A tuple element directly by using a period (&lt;code&gt;.&lt;/code&gt;) followed by an index&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;unit&lt;/b&gt;: tuple with empty value&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;returned by expression if it does not return any other value&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Compound Types - The Array Type&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Array&lt;/b&gt;: collection of values with the same type.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;used inside a comma-separated square bracket&lt;/li&gt;
&lt;li&gt;have fixed length&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;let a: [i32; 5] = [1, 2, 3, 4, 5];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;An array&amp;rsquo;s type is written using square brackets with the type of each element, a semicolon, and then the number of elements in the array&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;let a = [3; 5]; //let a = [3, 3, 3, 3, 3];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Initializing with the same value for all values in an array.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// accessing element with index
fn main() {
    let a = [1, 2, 3, 4, 5];

    let first = a[0];
    let second = a[1];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trying to access an index that is not within the length of the array will result in a &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;**&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;runtime error&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;**&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;.&lt;/p&gt;
&lt;h1&gt;3.3 Functions&lt;/h1&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    println!(&quot;Hello, world!&quot;);

    another_function();
}

fn another_function() {
    println!(&quot;Another function.&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;fn&lt;/code&gt; keyword is used to declare a function.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;snake case is the normal convention for naming a function&lt;/li&gt;
&lt;li&gt;a function with the name &lt;code&gt;main&lt;/code&gt; is an entry point for most programs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Parameters&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    print_labeled_measurement(5, 'h');
}

fn print_labeled_measurement(value: i32, unit_label: char) {
    println!(&quot;The measurement is: {value}{unit_label}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parameters are separated by comma.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Statements and Expressions&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Statements&lt;/b&gt; are instructions that perform some action and do not return a value.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Expressions&lt;/b&gt; evaluate to a resultant value.&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let y = {
        let x = 3;
        x + 1
    };

    println!(&quot;The value of y is: {y}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;curly bracket is an expression, and it can be assigned to another value.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Functions with Return Values&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn five() -&amp;gt; i32 {
    5
}

fn main() {
    let x = five();

    println!(&quot;The value of x is: {x}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;return&lt;/code&gt; keyword can be used to return a value early&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;the returned value must not end with a semicolon&lt;/p&gt;
&lt;h1&gt;3.4 Comments&lt;/h1&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;// hello, world&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;two slashes are used to represent comments&lt;/p&gt;
&lt;h1&gt;3.5 Control Flow&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;if Expressions&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let number = 3;

    if number &amp;lt; 5 {
        println!(&quot;condition was true&quot;);
    } else {
        println!(&quot;condition was false&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;operations under &lt;code&gt;if&lt;/code&gt; is performed when the condition returns &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if &lt;code&gt;else&lt;/code&gt; keyword is used, it is executed when condition in &lt;code&gt;if&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let number = 6;

    if number % 4 == 0 {
        println!(&quot;number is divisible by 4&quot;);
    } else if number % 3 == 0 {
        println!(&quot;number is divisible by 3&quot;);
    } else if number % 2 == 0 {
        println!(&quot;number is divisible by 2&quot;);
    } else {
        println!(&quot;number is not divisible by 4, 3, or 2&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;multiple conditions can be used with &lt;code&gt;else if&lt;/code&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Using if in a let Statement&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let condition = true;
    let number = if condition { 5 } else { 6 };

    println!(&quot;The value of number is: {number}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;to use the style above, the return type must be matched.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Repetition with Loops&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    loop {
        println!(&quot;again!&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;loop&lt;/code&gt; keyword executes a block of code over and over.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;continue&lt;/code&gt; keyword is used to skip to the next iteration without executing the rest of the code&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Returning Values from Loops&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!(&quot;The result is {result}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Put the value to return after the break statement to return a value.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Loop Labels to Disambiguate Between Multiple Loops&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let mut count = 0;
    'counting_up: loop {
        println!(&quot;count = {count}&quot;);
        let mut remaining = 10;

        loop {
            println!(&quot;remaining = {remaining}&quot;);
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up;
            }
            remaining -= 1;
        }

        count += 1;
    }
    println!(&quot;End count = {count}&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;loop labels can be used to break specific loops&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Conditional Loops with while&lt;/h2&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;fn main() {
    let mut number = 3;

    while number != 0 {
        println!(&quot;{number}!&quot;);

        number -= 1;
    }

    println!(&quot;LIFTOFF!!!&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Looping Through a Collection with for&lt;/h2&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;fn main() {
    let a = [10, 20, 30, 40, 50];

    for element in a {
        println!(&quot;the value is: {element}&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;similar to &lt;code&gt;for-each&lt;/code&gt; statement in Python.&lt;/p&gt;</description>
      <category>Rust/The Rust Programming Language</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/50</guid>
      <comments>https://limepencil.tistory.com/50#entry50comment</comments>
      <pubDate>Sun, 5 Nov 2023 22:05:11 +0900</pubDate>
    </item>
    <item>
      <title>[The Rust Programming Language] Ch. 2: Programming a Guessing Game</title>
      <link>https://limepencil.tistory.com/49</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://rust-book.cs.brown.edu/ch02-00-guessing-game-tutorial.html&quot;&gt;https://rust-book.cs.brown.edu/ch02-00-guessing-game-tutorial.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699182791065&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Programming a Guessing Game - The Rust Programming Language&quot; data-og-description=&quot;Let&amp;rsquo;s jump into Rust by working through a hands-on project together! This chapter introduces you to a few common Rust concepts by showing you how to use them in a real program. You&amp;rsquo;ll learn about let, match, methods, associated functions, external crat&quot; data-og-host=&quot;rust-book.cs.brown.edu&quot; data-og-source-url=&quot;https://rust-book.cs.brown.edu/ch02-00-guessing-game-tutorial.html&quot; data-og-url=&quot;https://rust-book.cs.brown.edu/ch02-00-guessing-game-tutorial.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://rust-book.cs.brown.edu/ch02-00-guessing-game-tutorial.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://rust-book.cs.brown.edu/ch02-00-guessing-game-tutorial.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Programming a Guessing Game - The Rust Programming Language&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Let&amp;rsquo;s jump into Rust by working through a hands-on project together! This chapter introduces you to a few common Rust concepts by showing you how to use them in a real program. You&amp;rsquo;ll learn about let, match, methods, associated functions, external crat&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;rust-book.cs.brown.edu&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Setting Up a New Project&lt;/h2&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$ cargo new guessing_game
$ cd guessing_game&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;cargo new&lt;/code&gt; creates a new cargo project with a name as the argument.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Processing a Guess&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;use std::io;&lt;/code&gt; can be used to process the input.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;println!&lt;/code&gt; is a macro for printing string to a screen&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Storing Values with Variables&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;let&lt;/code&gt; can be used to create a variable.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;mut&lt;/code&gt; makes the variable to be mutable. Every object in Rust is mutable by default&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Associated function&lt;/b&gt; is a function that&amp;rsquo;s implemented on a type. &lt;code&gt;::&lt;/code&gt; is used to describe the associated function.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) &lt;code&gt;String::new()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Receiving User Input&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;io::stdin().read_line(&amp;amp;mut guess)&lt;/code&gt; can be used to harness user input.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;guess&lt;/code&gt; is where the value read will be stored and it is referenced by &lt;code&gt;&amp;amp;&lt;/code&gt;. &lt;code&gt;&amp;amp;mut&lt;/code&gt; references and mutates the data.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Handling Potential Failure with Result&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Result&lt;/code&gt; is used to handle error&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Ok&lt;/code&gt; indicates the operation was successful, and it contains the generated value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Err&lt;/code&gt; means that the operation failed, and it contains information about how or why the operation failed.&lt;/li&gt;
&lt;li&gt;using &lt;code&gt;expect&lt;/code&gt; method allows for the handling of &lt;code&gt;Err&lt;/code&gt; without needing for program to crash&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Printing Values with println! Placeholders&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;{}&lt;/code&gt; can hold value in place.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;a variable can go into the place&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-rust&quot;&gt;  println!(&quot;You guessed: {guess}&quot;);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if the brackets are left blank, a comma-separated list can be followed to go in place of curly brackets&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-rust&quot;&gt;  let x = 5;
  let y = 10;

  println!(&quot;x = {x} and y + 2 = {}&quot;, y + 2);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Testing the First Part&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;cargo run&lt;/code&gt; can be used to run the rust file.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Using a Crate to Get More Functionality&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Since Rust does not provide a standard library for randomness, &lt;code&gt;rand&lt;/code&gt; crate must be used.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;library crate&lt;/b&gt;: code that is intended to be used in other programs and can&amp;rsquo;t be executed on its own&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;binary crate&lt;/b&gt;: code that is executable&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[dependencies]
rand = &quot;0.8.5&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Adding line above in &lt;b&gt;&lt;b&gt;&lt;i&gt;Cargo.toml&lt;/i&gt;&lt;/b&gt;&lt;/b&gt; file can add dependencies to the programs.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Running &lt;code&gt;cargo build&lt;/code&gt; after adding rand crate to the file downloads and compiles the dependencies.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Running the code once again does nothing because Rust knows that nothing has been changed&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;**&lt;/b&gt;Cargo.lock&lt;b&gt;**&lt;/b&gt; file records all the dependencies&amp;rsquo; versions used in the program, and this is for reproducibility.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Generating a Random Number&lt;/h2&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;let secret_number = rand::thread_rng().gen_range(1..=100);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;gen_range&lt;/code&gt; function takes in range as input and returns a random number in that range.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;1..=100&lt;/code&gt; is used to represent a range of numbers between 1 and 100, inclusive&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Comparing the Guess to the Secret Number&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;by using &lt;code&gt;std::cmp::Ordering&lt;/code&gt; type, can be used to get variants &lt;code&gt;Less, Greater, Equal&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;match guess.cmp(&amp;amp;secret_number) {
    Ordering::Less =&amp;gt; println!(&quot;Too small!&quot;),
    Ordering::Greater =&amp;gt; println!(&quot;Too big!&quot;),
    Ordering::Equal =&amp;gt; println!(&quot;You win!&quot;),
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;cmp&lt;/code&gt; compares a variable to another variable.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;match&lt;/code&gt; expression decides what operation to execute based on the patterns of the return value&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;parse&lt;/code&gt; method converts numbers automatically based on Rust&amp;rsquo;s default inference of value.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;only work on characters that can logically be converted into numbers and so can easily cause errors&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Allowing Multiple Guesses with Looping&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;loop&lt;/code&gt; keyword creates an infinite loop. It works the same as &lt;code&gt;while True&lt;/code&gt; in Python.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;break&lt;/code&gt; keyword exits the loop when the statement is executed.&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;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust/The Rust Programming Language</category>
      <category>Rust</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/49</guid>
      <comments>https://limepencil.tistory.com/49#entry49comment</comments>
      <pubDate>Sun, 5 Nov 2023 20:14:33 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Asynchronous Methods for Deep Reinforcement Learning (A3C)</title>
      <link>https://limepencil.tistory.com/48</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 논문에서는 강화학습을 비동기적이게 학습을 하게 만든 논문을 들고 왔다. 이 논문의 특이점이라고 한다면 보통의 학습에서 쓰이는 GPU를 사용하지 않고 CPU 코어들을 통한 병렬학습을 한다는 것이다. 이를 통해 Atari 벤치마크에서 새로운 기록을 세웠고 다른 도메인에서도 좋은 결과를 보여주는 모습이다.&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;a href=&quot;https://arxiv.org/abs/1602.01783&quot;&gt;[1602.01783] Asynchronous Methods for Deep Reinforcement Learning (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1693121520030&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Asynchronous Methods for Deep Reinforcement Learning&quot; data-og-description=&quot;We propose a conceptually simple and lightweight framework for deep reinforcement learning that uses asynchronous gradient descent for optimization of deep neural network controllers. We present asynchronous variants of four standard reinforcement learning&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1602.01783&quot; data-og-url=&quot;https://arxiv.org/abs/1602.01783v2&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/egriNs/hyTL7b9Vty/pukhhwETYAfBWG13kkE6i0/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/c0JL0k/hyTL7JZOK2/imwk9dt06YKw0YjApvyEX0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1602.01783&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1602.01783&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/egriNs/hyTL7b9Vty/pukhhwETYAfBWG13kkE6i0/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/c0JL0k/hyTL7JZOK2/imwk9dt06YKw0YjApvyEX0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Asynchronous Methods for Deep Reinforcement Learning&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;We propose a conceptually simple and lightweight framework for deep reinforcement learning that uses asynchronous gradient descent for optimization of deep neural network controllers. We present asynchronous variants of four standard reinforcement learning&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Introduction&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통의 online RL알고리즘은 DNN(Deep Neural Network)과 합쳐지면 안정적이지 않았다. 이는 온라인으로 들어오는 데이터들 간의 상관관계가 높았기 때문인데, 이를 DQN에서는 Experience Replay라는 방식을 사용해 데이터를 먼저 저장을 하고 랜덤 하게 학습을 하는 방식을 취했다. 이 방법의 단점은 off-policy RL만 가능하고 메모리와 computation power을 많이 쓴다는 단점이 있다. 또한 옛날 데이터를 학습한다는 문제도 있다.&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;이 논문에서는 이 문제를 agent들을 parallel로 학습시키는 방법을 사용하여 해결했다. 여러 개의 agent를 사용하면 한 state와 연관된 데이터가 아니라 각각의 agent마다 다른 데이터를 만들어내기 때문에 더 안정적이게 학습을 할 수 있다. 이 아이디어는 다양한 RL 알고리즘에 적용할 수 있는데, 심지어 off-policy 알고리즘에도 적용할 수 있다.&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;Related Work&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;General Reinforcement Learning Architecture(Gorilla)에서는 비동기적인 학습을 환경, Replay Memory, learner을 각각의 agent마다 복제해서 학습하였다. Gradient 값을 asynchronous 하게 중앙 서버로 보내어서 모델을 업데이틀 하고 이를 주기적으로 하위 learner에 보내주는 방식을 사용하였다.&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;Parallelism을 사용하여 matrix operation의 속도를 늘리거나 SARSA를 가속하는 연구도 있었다. 또한, evolutionary 메서드를 병렬화 하여 여러 개의 thread와 node에 나누어서 시뮬레이션을 돌려 학습을 가속화하는 방법도 있다&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;Reinforcement Learning Background&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Value-based RL&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞부분에서는 RL의 원리를 전반적으로 설명하고 있기 때문에 넘어가겠다 (앞에 있는 다른 블로그 글을 참조하자). n-step return에 대해서 잠깐 설명하고 있는데, 이는 일반의 DRL의 one-step return인 $$r + \gamma \max_{a'} Q(s', a'; \theta)$$&amp;nbsp; 대신에 n개의 step에 걸친 $$r_{t} + \gamma r_{t+1} +... + \gamma^{n-1} r_{t+n-1} +&amp;nbsp; \max_{a} \gamma^n&amp;nbsp; Q(s_{t+n}, a)$$을 사용하는 것이다. 나중에 이 논문도 리뷰를 할 예정이다. 이 방식의 장점은 하나의 reward가 n개의 state-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;&lt;b&gt;Policy-based RL&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Value-based와 다르게 policy 자체를 평가하는 방식이다. 이 방식도 많이 사용되어서 곧 policy-based RL에 관한 리뷰를 할 예정이다. Policy $\pi (a|s;\theta)$가 있을 때 $\mathbb {E}[R_t]$에 대한 경사상승을 진행한다. 간단한 policy-based RL인 REINFORCE는 $\theta$를 $\nabla_\theta \log \pi(a_t|s_t;\theta) R_t$으로 업데이트를 한다. 이는 $\nabla_\theta \mathbb {E}[R_t]$의 추정값이다.&amp;nbsp;&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;여기서 이제 variance를 줄이기 위해 baseline인 $b_t(s_t)$를 빼주면 결과 gradient는 $$\nabla_\theta \log \pi(a_t|s_t;\theta)(R_t-b_t(s_t))$$ 이 된다. 이 baseline을 value function으로 사용하면 $$b_t(s_t) \approx V^\pi(s_t)$$가 된다. 이 $R_t-b_t(s_t)$를 advantage의 estimation라고 볼 수 있는데 이는 $$A(a_t, s_t) = Q(a_t, s_t) - V(s_t)$$이다. $R_t$가 $Q(a_t, s_t)$의 estimate이고 $b_t$가 $V(s_t)$의 estimate인데 이 방법론을 &lt;i&gt;actor-critic architecture&lt;/i&gt;로 볼 수 있다 ($\pi$가 actor, $b_t$가 critic).&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Asynchronous RL Framework&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 multi-thread로 학습하는 asynchronous RL에 대해 이야기를 해보겠다. 이 논문에서는 one-step Sarsa, one-step Q-learning, n-step Q-learning, 그리고 A2C(Advantage actor-crtic)의 asynchronous version에 대해서 다룬다. 두 가지 방법을 사용하여 이 알고리즘들을 asynchronous 하게 바꾼다.&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;b&gt;1. Asynchronous actor-learner 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 서버에 agent를 할당하고 파라미터 서버를 두지 않고, 하나의 서버에서 여러 개의 cpu 코어를 사용한다. 이를 사용하면 gradient를 보낼 때 서버 간에 필연적으로 발생할 수밖에 없는 communication delay를 획기적으로 감소시킨다.&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;b&gt;2. 여러 개의 actor이 병렬적으로 돌면 각각 환경의 다른 부분을 explore 한다&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQRgkD/btssQatbwNl/w8fiX6kJq79GEdN3KnceX1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQRgkD/btssQatbwNl/w8fiX6kJq79GEdN3KnceX1/img.webp&quot; data-alt=&quot;Asynchronous : 평행우주의 나의 경험이 합쳐진다면? https://namu.wiki/w/%ED%8F%89%ED%96%89%EC%9A%B0%EC%A3%BC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQRgkD/btssQatbwNl/w8fiX6kJq79GEdN3KnceX1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQRgkD%2FbtssQatbwNl%2Fw8fiX6kJq79GEdN3KnceX1%2Fimg.webp&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;460&quot; height=&quot;263&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Asynchronous : 평행우주의 나의 경험이 합쳐진다면? https://namu.wiki/w/%ED%8F%89%ED%96%89%EC%9A%B0%EC%A3%BC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉,&amp;nbsp;replay&amp;nbsp;memory처럼&amp;nbsp;state 간의&amp;nbsp;correlation을&amp;nbsp;해결할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;메커니즘을&amp;nbsp;도입을&amp;nbsp;하지&amp;nbsp;않아도&amp;nbsp;된다.&amp;nbsp;각각&amp;nbsp;online으로&amp;nbsp;여러 가지의&amp;nbsp;경험이&amp;nbsp;한 번에&amp;nbsp;학습되기&amp;nbsp;때문에&amp;nbsp;diversity의&amp;nbsp;증가와&amp;nbsp;데이터 간의&amp;nbsp;correlation의&amp;nbsp;저하가&amp;nbsp;이루어진다.&amp;nbsp;또한&amp;nbsp;agent마다&amp;nbsp;다른&amp;nbsp;exploration&amp;nbsp;scheme을&amp;nbsp;사용시켜&amp;nbsp;학습의&amp;nbsp;폭을&amp;nbsp;넓힐&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp;즉,&amp;nbsp;학습을&amp;nbsp;상당히&amp;nbsp;안정적으로&amp;nbsp;진행할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;다른 장점은 agent의 수에 따라 비례하여 학습시간이 줄어든다. 또한, replay memory를 사용하지 않기 때문에 on-policy RL을 사용할 수 있다 (Sarsa, actor-critic). 저장할 필요가 없기 때문에 메모리가 줄어드는 것은 덤이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 각각에 알고리즘에 어떻게 asynchronous를 적용했는지 보겠다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Asynchronous&amp;nbsp;one-step&amp;nbsp;Q-learning&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thread 하나당 각각의 environment과 interact 한다. 각 step마다 gradient를 계산하나 target network에는 gradient들이 accumulate 되어서 update 된다(supervised learning에서 minibatch 방식과 비슷). 또한 각각의 thread마다 다른 exploration strategy를 주면 더 robust 하다. 여기서는 $\epsilon$-greedy에서 $\epsilon$을 어떤 distribution에서 sampling 하는 방식으로 차이를 주었다.&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;b&gt;Asynchronous one-step Sarsa&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 위에 있는 one-step Q-learning과 비슷하나 차이점은 target value를 $$Q(s, a)=r+\gamma Q(s', a';\theta^-)$$를 사용한다($\max_a$를 사용하는 Q-learning과 다름).&amp;nbsp;&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;b&gt;Asynchronous n-step Q-learning&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Forward view를 사용하여 eligibility traces 방식과 다르게 explicit 하게 n-step return을 계산한다. 이 방식이 momentum 기반의 학습 방식과 backprogration through time 방식에 적합하다고 한다. action을 $t_max$ step 또는 terminal state가 나올 때까지 고르고 n-step update를 진행한다. n-step update를 할 때는 제일 긴 step update를 사용하는데, 즉, 마지막 state는 one-step update를 진행하고, 두 번째 마지막 state는 two-step update... 이 방식으로 n-step까지 계산한 후 모아서 한 번에 gradient 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;&lt;b&gt;Asynchronous advantage actor-critic (A3C)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A3C는 policy $\pi(a_t|s_t;\theta)$와 value function의 estimation인 $V(s_t;\theta_v)$를 사용하여 학습한다. n-step Q-learning과 비슷하게 forward view를 사용한다. $\theta$와 $\theta_v$의 parameter은 어느 정도 공유되는데, CNN의 output을 softmax를 통햇 policy $\pi$에 넣어주고 linear output을 value function $V$에 넣어준다. 또한, 정책 $pi$에 entropy를 도입하면 초반에 optimal 하지 않은 정책으로의 수렴을 막아준다.&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;Experiments&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 Arcade Learning Environment, TORSC 3D car racing simulator, Mujoco, Labyrinth를 사용하여 실험을 진행했다(마지막 두 개는 A3C에서만 사용).&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;b&gt;Atari 2600&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYDdgr/btssYSTttXh/UzylUH8ETtkaw6sSJKTKi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYDdgr/btssYSTttXh/UzylUH8ETtkaw6sSJKTKi1/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1602.01783.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYDdgr/btssYSTttXh/UzylUH8ETtkaw6sSJKTKi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYDdgr%2FbtssYSTttXh%2FUzylUH8ETtkaw6sSJKTKi1%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;532&quot; height=&quot;223&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;223&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1602.01783.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;K40 CPU를 사용한 DQN보다 16개의 CPU 코어를 사용해서 Asynchronous 하게 학습한 알고리즘은 더 빨랐다. 또한, A3C 같은 경우에는 위에 나온 3가지의 value-based 방식보다 더 좋은 성능을 내었다. 실험에 사용한 hyperparameter은 6개의 game에서 search를 통해 찾은 후에 다른 57개의 게임에 같은 것을 적용하였다. 또한, feed-forward 방식과 LSTM을 사용한 recurrent agent 방식도 실험하였다. A3C 같은 경우에는 SOTA를 뛰어넘는 성능을 가지면서 학습 시간은 반으로 줄이는 모습을 보여줬다.&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;b&gt;TORCS Car Racing Simulator&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&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/C7WpO/btssSpejzO2/MxnJn8FS4Yoe2R7WGAAIek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C7WpO/btssSpejzO2/MxnJn8FS4Yoe2R7WGAAIek/img.png&quot; data-alt=&quot;https://sourceforge.net/projects/torcs/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C7WpO/btssSpejzO2/MxnJn8FS4Yoe2R7WGAAIek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC7WpO%2FbtssSpejzO2%2FMxnJn8FS4Yoe2R7WGAAIek%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;672&quot; height=&quot;378&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://sourceforge.net/projects/torcs/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1117&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfrgLY/btssTs2Lt8j/nCtTCOarN3rTp8xYlCuYkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfrgLY/btssTs2Lt8j/nCtTCOarN3rTp8xYlCuYkK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1602.01783.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfrgLY/btssTs2Lt8j/nCtTCOarN3rTp8xYlCuYkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfrgLY%2FbtssTs2Lt8j%2FnCtTCOarN3rTp8xYlCuYkK%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;710&quot; height=&quot;504&quot; data-origin-width=&quot;1117&quot; data-origin-height=&quot;793&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1602.01783.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TORCS의 장점은 Atari보다 더 나은 그래픽을 가지고 있어서 조금 더 realistic 한 테스팅이 가능하다. 이 게임에서 reward는 트랙 중간에서의 속도와 비례한다. 위의 그래프를 보면 알겠지만 A3C가 제일 좋은 성능을 내었고 대충 인간 실험자의 75%~90%의 성능을 내었다.&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;b&gt;Continuous Action Control Using the MuJoCo Physics Simulator&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Continuous 한 환경인 MuJoCo에서는 policy 기반인 A3C가 적합해서 실험을 하였는데, visual input이나 physical state를 input으로 주었을 때 24시간 안에 좋은 설루션을 찾아내었다.&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;b&gt;Labyrinth&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 미로 환경에서는 계속 랜덤 하게 생성되는 미로에서 길을 찾는 게 목표이다. 각 episode마다 랜덤 한 미로가 생성되기에 general 한 전략이 필요하다. 도착점에 들어가면 10점을 주고 episode당 60초가 소모되는데, 50 정도의 점수를 agent가 달성하였기 때문에 3D maze를 visual input만으로 풀 수 있다는 것을 알 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJhLse/btssUPb2AEw/ckR1RrwWaIAw8YDkkMMmrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJhLse/btssUPb2AEw/ckR1RrwWaIAw8YDkkMMmrK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1602.01783.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJhLse/btssUPb2AEw/ckR1RrwWaIAw8YDkkMMmrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJhLse%2FbtssUPb2AEw%2FckR1RrwWaIAw8YDkkMMmrK%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;586&quot; height=&quot;232&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;322&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1602.01783.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU의 스레드 수가 늘어날수록 학습 속도가 비례해서 빨라지는 것을 알 수 있는데, 특이하게 Q-learning과 SARSA는 super-linear 한 상승을 보여준다. 이는 아마 multi-thead덕분에 bias가 줄어서 그런 것이다. Asychronous 하게 적용한 알고리즘들은 lr이나 랜덤 한 시작에 강한 모습을 보여준다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Conclusions and Discussion&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Asynchronous 하게 학습하는 것은 다양한 종류의 도메인에서 좋은 성능을 보여준다. 이 방식은 value-based, policy-based, off-policy, on-policy처럼 다양한 곳에 적용될 수 있다. A3C는 절반의 시간으로 SOTA를 달성하였고 이는 CPU만으로만 학습한 결과이다. Paralle actor을 사용하면 one-step 방법인 다양한 value-based 알고리즘들에 stabilizing 하는 효과를 가져다준다.&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;Experience replay를 적용해서 예전의 데이터를 다시 학습할 수 있겠으나, 이런 활용은 학습하는 것보다 환경에서 action을 취하는 시간이 더 긴 TORCS 같은 곳에 적용을 할 수 있겠다. 또한 알고리즘의 변형인 Dueling DQN 같은 것도 이 아키텍처를 적용해 볼 수 있다. 이 논문은 GPU로만 학습했던 기존의 알고리즘을 병렬처리라는 개념을 사용하여 성공적으로 학습속도를 올렸다.&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>A3C</category>
      <category>Asynchronous</category>
      <category>Asynchronous Advantage Actor Critic</category>
      <category>ML</category>
      <category>RL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/48</guid>
      <comments>https://limepencil.tistory.com/48#entry48comment</comments>
      <pubDate>Sun, 3 Sep 2023 17:11:57 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Rainbow: Combining Improvements in Deep Reinforcement Learning (Rainbow DQN)</title>
      <link>https://limepencil.tistory.com/47</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1710.02298&quot;&gt;[1710.02298] Rainbow: Combining Improvements in Deep Reinforcement Learning (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1690181006122&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Rainbow: Combining Improvements in Deep Reinforcement Learning&quot; data-og-description=&quot;The deep reinforcement learning community has made several independent improvements to the DQN algorithm. However, it is unclear which of these extensions are complementary and can be fruitfully combined. This paper examines six extensions to the DQN algor&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1710.02298&quot; data-og-url=&quot;https://arxiv.org/abs/1710.02298v1&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/YwJW1/hyTqtNjOM9/OcSo70G3hm5PZxV0qlYEPk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/wVWnA/hyTo8RzIwW/BCf7Oy0EIn0hOefHEeHbrK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1710.02298&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1710.02298&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/YwJW1/hyTqtNjOM9/OcSo70G3hm5PZxV0qlYEPk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/wVWnA/hyTo8RzIwW/BCf7Oy0EIn0hOefHEeHbrK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Rainbow: Combining Improvements in Deep Reinforcement Learning&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The deep reinforcement learning community has made several independent improvements to the DQN algorithm. However, it is unclear which of these extensions are complementary and can be fruitfully combined. This paper examines six extensions to the DQN algor&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnvXAS/btspeHO7ozx/HhjTG5EQQI2QTW13u20KzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnvXAS/btspeHO7ozx/HhjTG5EQQI2QTW13u20KzK/img.png&quot; data-alt=&quot;https://templeofgeek.com/infinity-stones-method-of-the-mad-titan-infinity-war-spoilers/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnvXAS/btspeHO7ozx/HhjTG5EQQI2QTW13u20KzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnvXAS%2FbtspeHO7ozx%2FHhjTG5EQQI2QTW13u20KzK%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;848&quot; height=&quot;515&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://templeofgeek.com/infinity-stones-method-of-the-mad-titan-infinity-war-spoilers/&lt;/figcaption&gt;
&lt;/figure&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;이 논문을 마지막으로 DQN series의 끝이다. 몇 개의 글에 걸쳐서 다양한 DQN의 변형을 읽고 리뷰를 하였다. 논문들에는 이런 발전을 합쳐서 성능 결과를 낸 연구도 있지만, 이 논문은 6개의 DQN에서 발전한 것들을 다 합쳐서 성능을 대폭 끌어올린 논문이다. 이것을 Rainbow DQN이라고 부르는데 위에 있는 타노스의 인피니티 건틀렛과 비슷한 느낌이라 짤을 하나 만들어 보았다. 이것으로 이제 DQN은 끝이고 다른 RL 논문을 다뤄볼 예정이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Introduction&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Deep Q-Network (리뷰: &lt;a href=&quot;https://limepencil.tistory.com/38&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://limepencil.tistory.com/38&lt;/a&gt;)이 RL에 가져온 혁신으로 인해 많은 발전들이 그 뒤를 따랐는데, 이들 중에 큰 몇 가지를 이야기해 보자면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Double DQN &lt;a href=&quot;https://limepencil.tistory.com/41&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://limepencil.tistory.com/41&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Dueling DQN &lt;a href=&quot;https://limepencil.tistory.com/42&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://limepencil.tistory.com/42&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Prioritized Experience Replay &lt;a href=&quot;https://limepencil.tistory.com/43&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://limepencil.tistory.com/43&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Multi-step target(A3C)&lt;/li&gt;
&lt;li&gt;Distributional Q-learning&lt;/li&gt;
&lt;li&gt;NoisyNet &lt;a href=&quot;https://limepencil.tistory.com/43&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://limepencil.tistory.com/43&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이다. 이들은 DQN에 큰 성능 향상을 이루었고, 이중에 몇 가지를 섞어 진행한 실험도 있다. 이 논문에서는 더 나아가 이 모든 것을 합쳐서 성능을 올리는지 연구하고, 또한 어떤 factor이 가장 성능 향상에 도움이 되거나/되지 않거나를 탐색한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Background &amp;amp; Extensions to DQN &amp;amp; The Integrated Agent&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DQN의 대한 설명이나 각 extension에 대한 깊은 설명은 위에 링크들을 참고해 주면 되고, 여기서는 각 extension이 무엇을 하는지 짤막하게 설명하겠다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Double Q-Learning: addresses overestimation by decoupling maximization for bootstrap target and maximization in selecting an action&lt;/li&gt;
&lt;li&gt;Prioritized Replay: replays memory based on particular priority measured by absolute TD error&lt;/li&gt;
&lt;li&gt;Dueling Network: divide the layer into value stream and action stream and aggregate them later&lt;/li&gt;
&lt;li&gt;Multi-step learning: use $n$-step return from a given state&lt;/li&gt;
&lt;li&gt;Distributional RL: network learns to approximate the distribution of returns instead of the expected return&lt;/li&gt;
&lt;li&gt;NoisyNet: introduce random noise into the network to replace the normal exploration strategy&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이들을 기존의 DQN을 뼈대로 두고, 각각 히 다른 부분을 바꾼다. 더 자세한 부분은 논문을 참조하자.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Experimental Methods&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 실험하기 위해서 보통의 DRL을 실험하기 위해서 쓰이는 Atari 2600게임을 사용하였다. 전 논문들처럼 agent의 점수들은 normalized 되었다.&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;다양한 extension들을 합치기 위해서 hyperparameter을 기존 DQN에서 조금 변형하게 되었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;PER을 사용한 덕분에 learning update를 시작하는 frame을 200k 에서 80k로 바꾸게 되었다.&lt;/li&gt;
&lt;li&gt;NoisyNet을 사용하기 위해 $\epsilon$-greedy 정책에서 $\epsilon$을 0으로 바꾸고 NoisyNet의 parameter인 $\sigma_0$을 0.5로 바꾸었다.&lt;/li&gt;
&lt;li&gt;Optimizer을 RMSProp에서 Adam으로 바꾸어 learning rate의 sensitivity를 낮추었다.&lt;/li&gt;
&lt;li&gt;PER에서 proportional variant를 사용하였고 priority exponent $\omega = 0.5$, 그리고 importance sampling exponent인 $\beta$를 0.4에서 1로 linear 하게 증가시켰다&lt;/li&gt;
&lt;li&gt;multi-step learning에서는 $n = 3$ 일 때에서 전체적으로 좋은 결과를 보여주었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Analysis&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;399&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EjSqY/btspCmDUtGD/xpRgSpk9OxXkkvF0kAPN5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EjSqY/btspCmDUtGD/xpRgSpk9OxXkkvF0kAPN5k/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1710.02298.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EjSqY/btspCmDUtGD/xpRgSpk9OxXkkvF0kAPN5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEjSqY%2FbtspCmDUtGD%2FxpRgSpk9OxXkkvF0kAPN5k%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;384&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;399&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1710.02298.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rainbow의 성능과 데이터 효율성은 어떤 single-extension baseline들보다 더 좋다. 학습 시간은 각 연구마다 다른 setup을 사용하였기 때문에 정확한 속도 향상은 비교하기 어렵다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YIRDG/btspsVAexBN/sXKB9FUxG5MclU4RsIW380/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YIRDG/btspsVAexBN/sXKB9FUxG5MclU4RsIW380/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1710.02298.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YIRDG/btspsVAexBN/sXKB9FUxG5MclU4RsIW380/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYIRDG%2FbtspsVAexBN%2FsXKB9FUxG5MclU4RsIW380%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;468&quot; height=&quot;524&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1710.02298.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rainbow에서 extension을 하나씩 빼보면서 성능 차이를 비교한 실험에서는 PER과 multistep learning이 가장 중요한 요소였다고 하고 있다. 이들을 뺀다면 초반성능과 후반 성능 전체에 영향을 미친다. DDQN과 Dueling DQN은 그렇게 큰 영향은 미치지 않았으나, 각각의 게임마다 성능차이는 달랐다. DDQN 같은 경우에는 support of distribution이 늘어나서 overestimation을 하게 된다면 성능이 오를 것으로 보인다.&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;Discussion&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 여러 가지의 extension들이 DQN에 모두 다 합쳐질 수 있는지 확인하였고, 거의 모든 component들이 성능 향상에 도움을 주었다는 것을 보았다. Policy-based network 같은 다른 유형의 RL은 다른 연구가 더 필요하다.&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>DQN</category>
      <category>rainbow</category>
      <category>Rainbow DQN</category>
      <category>Reinforcement Learning</category>
      <category>RL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/47</guid>
      <comments>https://limepencil.tistory.com/47#entry47comment</comments>
      <pubDate>Mon, 31 Jul 2023 17:20:07 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Noisy Networks for Exploration (NoisyNet)</title>
      <link>https://limepencil.tistory.com/44</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1706.10295&quot;&gt;[1706.10295] Noisy Networks for Exploration (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686910857325&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Noisy Networks for Exploration&quot; data-og-description=&quot;We introduce NoisyNet, a deep reinforcement learning agent with parametric noise added to its weights, and show that the induced stochasticity of the agent's policy can be used to aid efficient exploration. The parameters of the noise are learned with grad&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1706.10295&quot; data-og-url=&quot;https://arxiv.org/abs/1706.10295v3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kBLGm/hyS1eJ5kEl/WFCdqHFrFkMm57MjEy9uqK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/oVDaT/hyS0mwdXqj/SjK3Cxzz09J4GkbIXc03D0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1706.10295&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1706.10295&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kBLGm/hyS1eJ5kEl/WFCdqHFrFkMm57MjEy9uqK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/oVDaT/hyS0mwdXqj/SjK3Cxzz09J4GkbIXc03D0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Noisy Networks for Exploration&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;We introduce NoisyNet, a deep reinforcement learning agent with parametric noise added to its weights, and show that the induced stochasticity of the agent's policy can be used to aid efficient exploration. The parameters of the noise are learned with grad&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&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;이번 논문에는 DQN에 있는 fully connected layer에 parametric 한 noise를 넣어서 유도된 stochasticity가 agent의 성능을 올려준다는 연구를 한 논문이다. 지금까지 여러 가지 DQN의 변형을 다뤘는데 아마 이 글이 Rainbow DQN전의 마지막 글이지 않을까 싶다. DQN에 관한 논문 리뷰는 아래 글을 참조하자.&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;a href=&quot;https://limepencil.tistory.com/38&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN) &amp;mdash; LimePencil's Log (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1687015258326&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&quot; data-og-description=&quot;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&quot; data-og-host=&quot;limepencil.tistory.com&quot; data-og-source-url=&quot;https://limepencil.tistory.com/38&quot; data-og-url=&quot;https://limepencil.tistory.com/38&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eLfa54/hyS2Alvm6e/PkwxRSTHcaVUy2XlXXkMF1/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/iu9H6/hyS1mvEpBg/PWjXNfJglhKf9p1rQ50b61/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/Bhjzk/hyS2B5MZmk/5ACYkzkrwfCyHZCenuEebk/img.png?width=750&amp;amp;height=939&amp;amp;face=0_0_750_939&quot;&gt;&lt;a href=&quot;https://limepencil.tistory.com/38&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://limepencil.tistory.com/38&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eLfa54/hyS2Alvm6e/PkwxRSTHcaVUy2XlXXkMF1/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/iu9H6/hyS1mvEpBg/PWjXNfJglhKf9p1rQ50b61/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/Bhjzk/hyS2B5MZmk/5ACYkzkrwfCyHZCenuEebk/img.png?width=750&amp;amp;height=939&amp;amp;face=0_0_750_939');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;limepencil.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Introduction&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Optimism in the face of uncertainty이나 intrinsic motivation 같은 common heuristic reinforcement learning method 같은 경우에는 generalization과 exploration을 다른 방법을 사용한다는 것이다. Intrinsic reward 같은 경우를 예로 들면 metric을 사람이 결정하기 때문에 optimal 하다고 보기는 어렵다. 제일 좋은 방법은 exploration in the policy itself이나, 이 방법은 환경과 긴 interaction이 필요하다(not data-efficient and require simulator).&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;이 논문에서는 다른 대안을 제안하는데, 이는 바로 네트워크의 weight 자체에다가 perturbation을 주어서 exploration을 하게 만드는 방법이다. 이 perturbation은 noise distribution에서 sampling이 되고 이 variance hyperparameter 자체를 손실함수를 통해 학습을 하게 시키는 방법이다. 즉, 네트워크가 스스로 noise의 level 크기를 결정하는 방식이다. 이 방식이 computationally expensive 하다고 볼 수 있으나 사실 affine transformation이기 때문에 큰 영향은 없다.&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;또한 NoisyNet은 다른 DQN의 변형인 알고리즘 (Dueling, Double 등등)에 쉽게 implement 시킬 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;NoisyNet for Reinforcement Learning&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NoisyNet이란 네트워크의 weight이나 biases를 parametric function으로 만든 noise를 입히는 것인데, 이 파라미터는 경사하강법으로 최적의 값을 찾을 수 있다. noisy parameter $\theta$를 다음과 같이 정의하는데 $$ \theta \stackrel {\text {def}}{=} \mu + \sigma \odot \epsilon$$ 여기서 $\mu, \Sigma$은 학습 가능한 파라미터이고, $\epsilon$은 평균이 0인 노이즈 벡터이다.&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;평소의 neural network의 linear layer을 다음과 같이 표현한다면 $$y = wx +b$$ noisy linear layer은 $$y \stackrel {\text {def}}{=} (\mu^w + \sigma^w \odot \epsilon^w) x + \mu^b + \sigma^b \odot \epsilon^b$$ 으로 표현할 수 있다.&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;Noise Distribution의 종류:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Independent Gaussian noise: noise per output
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Initialization: uniform distribution of $ \mu_{i,j} = \textit{U} \left[ - \sqrt{\frac{3}{p}}, \sqrt{\frac{3}{p}} \right]$ 이고 ($p$는 input의 크기), $\sigma_{i,j} = 0.017$&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Factorized Gaussian noise: noise per input
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Initialization: uniform distribution of $\mu_{i,j} = \textit{U} \left[ - \frac{1}{\sqrt{p}}, \frac{1}{\sqrt{p}} \right]$ 이고 ($p$는 input의 크기), $\sigma_{i,j} = \frac{\sigma_0}{\sqrt{p}} | \sigma_0=0.5$&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1319&quot; data-origin-height=&quot;668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9hyv0/btsoGgkf2V5/6yzCgHMozZS5pXAOV9oRH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9hyv0/btsoGgkf2V5/6yzCgHMozZS5pXAOV9oRH1/img.png&quot; data-alt=&quot;weight와 biase의 개수 차이를 보자&amp;amp;amp;nbsp; :&amp;amp;amp;nbsp; https://towardsdatascience.com/whats-the-role-of-weights-and-bias-in-a-neural-network-4cf7e9888a0f&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9hyv0/btsoGgkf2V5/6yzCgHMozZS5pXAOV9oRH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9hyv0%2FbtsoGgkf2V5%2F6yzCgHMozZS5pXAOV9oRH1%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;734&quot; height=&quot;372&quot; data-origin-width=&quot;1319&quot; data-origin-height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;weight와 biase의 개수 차이를 보자&amp;amp;nbsp; :&amp;amp;nbsp; https://towardsdatascience.com/whats-the-role-of-weights-and-bias-in-a-neural-network-4cf7e9888a0f&lt;/figcaption&gt;
&lt;/figure&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;Factorized Gaussian noise를 쓰는 이유는 random number을 generate 하는 compute시간을 줄이기 위해서 그렇다. $p$를 input, $q$를 output으로 정의한다면 Independent Gaussian noise는 $pq + q$의 noise variable을 가지고 있고 Factorised Gaussian noise는 $p+q$의 noise variable을 가지고 있다. Independent Gaussian noise는 곱셈을 가지고 있기 때문에 $p$와 $q$가 커지면 더 많은 계산이 필요하다. Factorized Gaussian noise는 $p$와 $q$가 덧셈 관계이기 때문에 수가 그렇게 빨리 커지지는 않는다. Factorized Gaussian noise가 작은 이유는 Independent Gaussian noise처럼 모든 weight에 대한 random noise를 만드는 게 아니라 input과 output의 수만큼 random noise를 만들고 weight는 이 두 값을 곱한 것으로 사용하기 때문이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Noise는 RL에서 중요한 exploration을 담당하게 되는데, 이를 통해 어떠한 stochasticity를 부여한다. NoisyNet에서는 자동으로 이 노이즈의 정도를 NoisyNet에서 조절하게 된다. 즉, 주입되는 noise의 정도를 agent가 자동적으로 맞춘다는 것이다.&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;DQN과 Dueling DQN에는 epsilon-greedy 방식을 쓰지 않고 NoisyNet으로 대체한다. 위에서 설명한 Factorized Gaussian Noise를 사용하고 noise sample은 각 action 전에 항상 다시 샘플 된다. DQN에서 target network와 online network의 noise를 각각 따로 생성하여 어떠한 correlation이 생기는 것을 막는다. 또한, action을 고를 때에도 다른 노이즈 샘플을 사용하고 greedy 하게 action을 선택한다. Dueling 같은 경우에도 DQN과 비슷하게 구성한다.&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;A3C 같은 경우에는 policy network의 entropy bonus를 없애고 fully connected layer을 NoisyNet으로 대체한다. A3C는 DQN과 다르게 Independent Gaussian noise를 사용한다. Entropy loss를 사용하는 이유가 deterministic 하게 하는 것을 방지하기 위해서인데, 이를 NoisyNet으로 해결했기 때문에 필요가 없어졌다. N-step return을 사용하기 때문에 n step마다 noise parameter가 새로 sampling 된다.&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;Results&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;949&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjnDDY/btsozlfPvvA/tBoyfRF3ROl5gjBKIF7PKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjnDDY/btsozlfPvvA/tBoyfRF3ROl5gjBKIF7PKK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1706.10295.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjnDDY/btsozlfPvvA/tBoyfRF3ROl5gjBKIF7PKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjnDDY%2FbtsozlfPvvA%2FtBoyfRF3ROl5gjBKIF7PKK%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;820&quot; height=&quot;781&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;949&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1706.10295.pdf&lt;/figcaption&gt;
&lt;/figure&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;성능은 그전의 논문들과 같이 57개의 Atari게임으로 비교하였다. 비교 대상은 DQUN, Dueling DQN, 그리고 A3C이다. 점수는 그 전 논문과 같게 human normalized score로 계산되었다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcHEn4/btsoxcc2HcA/E4krLKgE2kIxuP3hgWn4t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcHEn4/btsoxcc2HcA/E4krLKgE2kIxuP3hgWn4t0/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1706.10295.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcHEn4/btsoxcc2HcA/E4krLKgE2kIxuP3hgWn4t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcHEn4%2Fbtsoxcc2HcA%2FE4krLKgE2kIxuP3hgWn4t0%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;570&quot; height=&quot;174&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1706.10295.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 있는 표와 그래프를 보면 NoisyNet이 전반적으로 성능 향상에 기여를 했다는 것을 볼 수 있다. 또한 $\sigma^w$를 학습동안 계속 추적해 봤을 때에 0으로 수렴하여 deterministic solution으로 바뀌지 않았고 증가하는 게임도 있었다. 이는 NoisyNet이 problem-specific exploration strategy를 만들었다는 모습이다.&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;Conclusion&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 NoisyNet이라는 새로운 탐색 기법을 소개하고 있고, 성능이 올라간 것은 optimization효과 일수도 있지만 이는 exploration과 optimization을 따로 보는 후속 연구가 필요하다. NoisyNet의 다른 장점은 noise의 정도를 RL algorithm이 결정한다는 것인데, 이는 hyperparamenter tuning의 필요를 줄여준다. NoisyNet은 다양한 FC layer이 있는 RL algorithm에 적용을 할 수 있는 좋은 기법이다.&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>DQN</category>
      <category>Noisy Network</category>
      <category>Random</category>
      <category>Reinforcement Learning</category>
      <category>강화학습</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/44</guid>
      <comments>https://limepencil.tistory.com/44#entry44comment</comments>
      <pubDate>Sun, 23 Jul 2023 22:58:05 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] On the detection of synthetic images generated by diffusion models</title>
      <link>https://limepencil.tistory.com/46</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저번 글에 이어 이번에는 GAN에 한정하지 않고 어떻게 diffusion 모델들도 진짜 이미지인지 가짜 이미지인지 판별할 수 있는지에 대한 논문을 리뷰할 것이다. GAN과 diffusion은 아키텍처 구조적으로 다르기 때문에 이를 어떻게 다루는지를 보자.&amp;nbsp;&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;a href=&quot;https://arxiv.org/abs/2211.00680&quot;&gt;[2211.00680] On the detection of synthetic images generated by diffusion models (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688647766377&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;On the detection of synthetic images generated by diffusion models&quot; data-og-description=&quot;Over the past decade, there has been tremendous progress in creating synthetic media, mainly thanks to the development of powerful methods based on generative adversarial networks (GAN). Very recently, methods based on diffusion models (DM) have been gaini&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2211.00680&quot; data-og-url=&quot;https://arxiv.org/abs/2211.00680v1&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ZfyVV/hyTftUlfE7/kKe2r0ed80HdSwIHUuQ5aK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/bcUY9t/hyTfpdlRAn/cih6xU1k7c4jDMNkMsEkr1/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2211.00680&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2211.00680&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ZfyVV/hyTftUlfE7/kKe2r0ed80HdSwIHUuQ5aK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/bcUY9t/hyTfpdlRAn/cih6xU1k7c4jDMNkMsEkr1/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;On the detection of synthetic images generated by diffusion models&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Over the past decade, there has been tremendous progress in creating synthetic media, mainly thanks to the development of powerful methods based on generative adversarial networks (GAN). Very recently, methods based on diffusion models (DM) have been gaini&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Abstract &amp;amp; Introduction&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;With this work, we seek to understand how difficult it is to distinguish synthetic images generated by diffusion models from pristine ones and whether current state-of-the-art detectors are suitable for the task.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 diffusion model에 대한 detection이 현재 어디까지 왔는지에 대해 연구를 하고 있다. 이 논문에서는 특히 다음을 중점적으로 다루고 있다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;finding forensic traces left by diffusion model&lt;/li&gt;
&lt;li&gt;현재의 detector의 성능 측정 및 resize와 compression이 있는 환경에서의 성능&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Synthetic image의 특징은 인간의 눈으로 보기에는 완벽하더라도 생성 시에 남아있는 trace 때문에 판별할 수 있다. 각각의 architecture에 따라 다른 trace들을 가지고 있고, 이를 통해 소스를 추적할 수 있다. GAN이 가진 특이한 fingerprint 때문에 GAN architecture은 detect 하기 쉬운 편에 속하고 있다. 하지만, 현재의 SOTA도 새로운 모델에 generalize 하는 것에는 어려움을 보여주고 있다. 특히, 이미지에 손실이 있으면 상당한 성능 하락을 보여주고 있다.&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;그래서, 이 논문은 diffusion 모델들도 GAN처럼 숨겨진 fingerprint가 있는지와 현재의 SOTA detector이 이런 유형의 이미지를 판별하는 데에 어느 정도의 성능을 보여주는지를 탐구한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Background&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전의 연구들은 GAN이 생성이미지 분야의 majority를 차지하고 있었기 때문에 GAN detection에 관한 것이 많았다. 이런 생성이미지의 detection의 중요한 부분은 augmentation(blurring &amp;amp; compression)이다. 이를 통해 generalization과 robustness를 올릴 수 있다. 또한 training set의 다양성도 성능을 올리는 데에 도움을 준다. 이것들은 조금 더 자세히 이전의 논문 리뷰에 썼기 때문에 이를 참고하면 좋을 것이다.&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;a href=&quot;https://limepencil.tistory.com/45&quot;&gt;[논문 리뷰] Are GAN generated images easy to detect? A critical analysis of the state-of-the-art &amp;mdash; LimePencil's Log (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688893175298&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[논문 리뷰] Are GAN generated images easy to detect? A critical analysis of the state-of-the-art&quot; data-og-description=&quot;AI CONNECT에서 진행하는 Fake or Real: AI 생성 이미지 판별 경진대회를 참가하기 위해 여러 가지 논문을 뒤적이던 중에 괜찮은 논문이 있어서 리뷰를 해보려고 한다. https://arxiv.org/abs/2104.02617 Are GAN gen&quot; data-og-host=&quot;limepencil.tistory.com&quot; data-og-source-url=&quot;https://limepencil.tistory.com/45&quot; data-og-url=&quot;https://limepencil.tistory.com/45&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/71iXK/hyTfC59ohk/J8iT41hxxltt3bkKuk62V1/img.png?width=381&amp;amp;height=463&amp;amp;face=42_48_380_364,https://scrap.kakaocdn.net/dn/B2ZgW/hyTfmWRiJi/svYfjLX6ZYhOq9fsMQUpBK/img.png?width=381&amp;amp;height=463&amp;amp;face=42_48_380_364,https://scrap.kakaocdn.net/dn/dxQ4Wb/hyTfzaOYZq/22I0RjOd6lA0jGuEf4NOB0/img.png?width=1245&amp;amp;height=571&amp;amp;face=0_0_1245_571&quot;&gt;&lt;a href=&quot;https://limepencil.tistory.com/45&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://limepencil.tistory.com/45&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/71iXK/hyTfC59ohk/J8iT41hxxltt3bkKuk62V1/img.png?width=381&amp;amp;height=463&amp;amp;face=42_48_380_364,https://scrap.kakaocdn.net/dn/B2ZgW/hyTfmWRiJi/svYfjLX6ZYhOq9fsMQUpBK/img.png?width=381&amp;amp;height=463&amp;amp;face=42_48_380_364,https://scrap.kakaocdn.net/dn/dxQ4Wb/hyTfzaOYZq/22I0RjOd6lA0jGuEf4NOB0/img.png?width=1245&amp;amp;height=571&amp;amp;face=0_0_1245_571');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[논문 리뷰] Are GAN generated images easy to detect? A critical analysis of the state-of-the-art&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;AI CONNECT에서 진행하는 Fake or Real: AI 생성 이미지 판별 경진대회를 참가하기 위해 여러 가지 논문을 뒤적이던 중에 괜찮은 논문이 있어서 리뷰를 해보려고 한다. https://arxiv.org/abs/2104.02617 Are GAN gen&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;limepencil.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국엔 중요한 trace들을 보존하기 위해서는 아래의 3가지가 중요하다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;local patch에서 학습시키기&lt;/li&gt;
&lt;li&gt;전체 이미지를 통해 학습시키는 방안을 생각해 보기 (fusion strategy)&lt;/li&gt;
&lt;li&gt;첫 번째 layer에서 downsampling을 피하기&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pretrained 된 모델을 쓰는 것은 중요하고, 극한의 augmentation은 어느 정도의 성능 향상을 가져다준다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Artifact Analysis&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAgTW5/btsmWkITAQV/PDrKJkwrJ0sVgiktSPqsLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAgTW5/btsmWkITAQV/PDrKJkwrJ0sVgiktSPqsLK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/2211.00680.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAgTW5/btsmWkITAQV/PDrKJkwrJ0sVgiktSPqsLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAgTW5%2FbtsmWkITAQV%2FPDrKJkwrJ0sVgiktSPqsLK%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;1015&quot; height=&quot;554&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/2211.00680.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지에서 fingerprint를 카메라에서 PRNU(Photo response non-uniformity)를 extract 하는 것 같이 extract 한다. 이에 대한 자세한 설명은 논문을 확인하면 된다. 이 noise를 extract 한 뒤에 이를 1000개의 이미지의 평균을 내고, 이를 푸리에 변환을 해주면 spectal analysis를 할 수 있다.&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;위의 사진을 보면 GAN은 특징이 강한 trace가 남는다. 특이하게도, 최신의 DM(Diffusion Model)들에도 trace가 남는 것을 볼 수 있다. ADM이나 DALL&amp;middot;E 2 같은 경우에는 이런 특징이 약하게 남는다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Detection Performance&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능을 평가하기 위해서 진짜 이미지 데이터는 COCO, ImageNet, UCID를 사용했고, 생성이미지는 generalization을 평가하기 위해서 ProGAN와 Latent Diffusion 이 두 모델에서 50만 개의 이미지를 생성하여 사용하였다. 이 논문에서는 4가지의 detector을 평가한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Spec: frequency analysis&lt;/li&gt;
&lt;li&gt;PatchForensics: local patch analysis&lt;/li&gt;
&lt;li&gt;Wang2020: ResNet50 with blurring and compression augmentation&lt;/li&gt;
&lt;li&gt;Grag2021: same backbone as Wang2020 but avoiding down-sampling in the first layer and intense augmentation&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfBkU9/btsmSu6lP0b/GCtDEABSTFaXVC3KS7nZDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfBkU9/btsmSu6lP0b/GCtDEABSTFaXVC3KS7nZDk/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/2211.00680.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfBkU9/btsmSu6lP0b/GCtDEABSTFaXVC3KS7nZDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfBkU9%2FbtsmSu6lP0b%2FGCtDEABSTFaXVC3KS7nZDk%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;1044&quot; height=&quot;438&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/2211.00680.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압축하지 않은 PNG를 생성이미지 데이터로 학습을 하였을 때에는 좋은 성능을 보여주었는데, 이는 실제 이미지는 JPEG로 압축이 되었는데 이 trace가 남기 때문에 더 detect 하기 쉬운 것으로 보인다.&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;다른 시나리오로 생성과 진짜 이미지를 압축하고 resize 하였을 때에는 detector에 따라 성능이 떨어지는 정도가 다르긴 했으나, Grag2021은 상당이 좋은 성능을 내는 모습을 보여주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;528&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KbSkJ/btsmQRup7Tb/0hEjWKqlY2fKNcrR0uYLC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KbSkJ/btsmQRup7Tb/0hEjWKqlY2fKNcrR0uYLC0/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/2211.00680.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KbSkJ/btsmQRup7Tb/0hEjWKqlY2fKNcrR0uYLC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKbSkJ%2FbtsmQRup7Tb%2F0hEjWKqlY2fKNcrR0uYLC0%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;528&quot; height=&quot;411&quot; data-origin-width=&quot;528&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/2211.00680.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능이 좋은 Grag2021을 Latent Diffusion에 학습시키고, 이를 ProGAN 데이터셋으로 학습시킨 모델과 합치고 조금의 calibration을 더하면 성능이 올라가는 것을 볼 수 있다.&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;Conclusion&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 diffusion model을 통해 만들어진 synthetic image 판별을 다루고 있다. Generalization은 아직도 해결해야 할 숙제이고 GAN으로 학습한 detector들은 DM으로 만들어진 image들을 판별하는 성능이 떨어진다. DM으로 만들어진 이미지를 training에 넣으면 그 모델에 대한 성능은 올라가지만 다른 것들은 그렇게까지 올라가지는 않는다. 미래의 연구에서는 이를 해결해야 하는 것으로 보인다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Code&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 논문의 코드는 아래 깃허브에 공개되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/grip-unina/DMimageDetection&quot;&gt;grip-unina/DMimageDetection: On the detection of synthetic images generated by diffusion models (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688893427510&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - grip-unina/DMimageDetection: On the detection of synthetic images generated by diffusion models&quot; data-og-description=&quot;On the detection of synthetic images generated by diffusion models - GitHub - grip-unina/DMimageDetection: On the detection of synthetic images generated by diffusion models&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/grip-unina/DMimageDetection&quot; data-og-url=&quot;https://github.com/grip-unina/DMimageDetection&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VtMfo/hyTgTZJuPO/tIcfDDwjhYDE1dAfZxXL4k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/grip-unina/DMimageDetection&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/grip-unina/DMimageDetection&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VtMfo/hyTgTZJuPO/tIcfDDwjhYDE1dAfZxXL4k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - grip-unina/DMimageDetection: On the detection of synthetic images generated by diffusion models&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;On the detection of synthetic images generated by diffusion models - GitHub - grip-unina/DMimageDetection: On the detection of synthetic images generated by diffusion models&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Computer Vision</category>
      <category>classification</category>
      <category>Computer Vision</category>
      <category>Detection</category>
      <category>diffusion</category>
      <category>Machine Learning</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/46</guid>
      <comments>https://limepencil.tistory.com/46#entry46comment</comments>
      <pubDate>Thu, 6 Jul 2023 22:01:55 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Are GAN generated images easy to detect? A critical analysis of the state-of-the-art</title>
      <link>https://limepencil.tistory.com/45</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;AI CONNECT에서 진행하는 &lt;i&gt;Fake or Real: AI 생성 이미지 판별 경진대회&lt;/i&gt;를 참가하기 위해 여러 가지 논문을 뒤적이던 중에 괜찮은 논문이 있어서&amp;nbsp; 리뷰를 해보려고 한다.&amp;nbsp;&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;a href=&quot;https://arxiv.org/abs/2104.02617&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://arxiv.org/abs/2104.02617&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688041025218&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Are GAN generated images easy to detect? A critical analysis of the state-of-the-art&quot; data-og-description=&quot;The advent of deep learning has brought a significant improvement in the quality of generated media. However, with the increased level of photorealism, synthetic media are becoming hardly distinguishable from real ones, raising serious concerns about the s&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2104.02617&quot; data-og-url=&quot;https://arxiv.org/abs/2104.02617v1&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/FMaA8/hyS9ILUSsM/NjAKjoX9FEVXNWbDZDjNUK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/RKYVP/hyS9TfBKBH/wA2PraYGiKtgAJTYY9GaX0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2104.02617&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2104.02617&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/FMaA8/hyS9ILUSsM/NjAKjoX9FEVXNWbDZDjNUK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/RKYVP/hyS9TfBKBH/wA2PraYGiKtgAJTYY9GaX0/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Are GAN generated images easy to detect? A critical analysis of the state-of-the-art&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The advent of deep learning has brought a significant improvement in the quality of generated media. However, with the increased level of photorealism, synthetic media are becoming hardly distinguishable from real ones, raising serious concerns about the s&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Abstract &amp;amp; Introduction&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 생성 이미지를 판별하는 SOTA method를 분석하고 비교해 본다. 어떤 factor이 detection에 큰 도움을 주는지, 그리고 현재의 generative architecture들에 이 방법이 얼마나 효용이 있는지를 다뤘다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;463&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/em6lQD/btslS2CmEzT/Aa4ThKUkpWsorCbTVZnsFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/em6lQD/btslS2CmEzT/Aa4ThKUkpWsorCbTVZnsFK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/2104.02617.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/em6lQD/btslS2CmEzT/Aa4ThKUkpWsorCbTVZnsFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fem6lQD%2FbtslS2CmEzT%2FAa4ThKUkpWsorCbTVZnsFK%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;381&quot; height=&quot;463&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;463&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/2104.02617.pdf&lt;/figcaption&gt;
&lt;/figure&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;GAN은 특별한 trace를 생성된 이미지에 남기는데, 이를 이용하여 detection이 가능하다. 기술이 발전함으로써 이것이 줄어들겠지만, 이 trace는 생성 모델의 구조 그 자체와 관계가 있다. 각각의 GAN architecture마다 특정한 artificial fingerprint가 있다. 이를 Fourier transform으로 찾을 수 있는데 (위에 있는 파란색 사진) 데이터에 따라서도 이 fingerprint가 바뀌기 때문에 다른 방법을 찾아야 한다.&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;요즘에는 deep neural network만을 사용하여 detection을 하기도 하는데, 그렇다면 이 task자체가 쉬워 보이나 사실 상당히 어렵다. 원본의 이미지를 가지고 있을 때는 이런 trace들을 찾기가 쉽지만 compression과 distortion이 흔한 인터넷상에서는 이런 흔적들이 사라지기 때문에 더 challenging 해진다. 또한, 계속 새로운 생성모델이 만들어지고, 이에 대한 데이터를 구하기가 어려워지고 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;State-of-the-art-methods&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 현재 SOTA를 3가지로 나누어서 설명하고 있는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Learning spatial domain features
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;예전에 사용한 방법은 이미지의 기원을 찾는 방법이나 위에서 말했던 fingerprint를 찾는 방법이다.&lt;/li&gt;
&lt;li&gt;GAN의 특성을 exploit 하여 색의 intensity value의 한계, saturated or underexpose region 존재 유무, color band 간의 상관관계 등등을 이용하여 판단을 한다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Learning frequency domain features
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Fourier domain에 있는 trace들을 활용하여 upsampling시에 남은 흔적이나, 여러 가지 achitiecture만의 흔적을 찾는다&lt;/li&gt;
&lt;li&gt;Fourier spectra를 활용한 CNN-based classifier 활용&lt;/li&gt;
&lt;li&gt;생성 이미지와 진짜 이미지와의 energy spectral distribution을 비교&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Learning feature that generalize
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;위에 제기된 방법들은 training data가 test data와 같을 때 유효하지만 generalization이 약하다. 이를 위해 few-shot learning 방법들이 제시되었다(autoencoder-based)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Augmentation(gaussian blurring)을 활용하여, 더 generalize 한 feature을 학습하도록 하는 방법이 있다. 이를 쓰면 하나의 GAN architecture만으로도 학습을 하여도 높은 generalization 성능을 보여주었다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;fully convolutional patch-based classifier을 활용하여 patch에 집중함으로써 더 좋은 성능을 보여줄 수 있다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Datasets&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qeYBW/btslNk5AWjF/jFjEPOMJipM6b8UKVLJSB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qeYBW/btslNk5AWjF/jFjEPOMJipM6b8UKVLJSB0/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/2104.02617.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qeYBW/btslNk5AWjF/jFjEPOMJipM6b8UKVLJSB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqeYBW%2FbtslNk5AWjF%2FjFjEPOMJipM6b8UKVLJSB0%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;410&quot; height=&quot;366&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/2104.02617.pdf&lt;/figcaption&gt;
&lt;/figure&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;이 실험에서 사용한 데이터는 36만 장의 LSUN 데이터셋에서 가져온 진짜 이미지와 각각 다른 cateogry에서 학습한 20개의 ProGAN 모델을 사용하여&amp;nbsp;36만 장의 생성 이미지를 만들었다. Generalization을 테스트하기 위해서 testing phase에서는 training때 보지 못한 low-resolution(256x256)과 high-resolution(1024x1024) 이미지가 섞인 7개의 다른 GAN 모델에서 생성한 이미지를 사용하였다. 또한 ImageNet, COCO, RAISE 데이터를 진짜 이미지로 사용하였다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Experimental Results&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 다양한 detector(Xception, SRNet, Spec, M-Gb, Co-Net, Wang2020, PatchForensics)를 시험을 했다. 논문에서는 SRNet이 noise residual에 관련된 feature들을 보존하는 데다가 downsampling이 없어서 좋다고 한다. Generalization을 테스트한 실험에서는 AUC는 높지만 accuracy 같은 경우에는 좀 낮은 부분이 있다고 한다. 또한 compression을 진행했을 때 augmentation을 사용해서 학습한 모델이 좋은 결과를 보여주고 있다고 한다. 어떤 상황에서라도 2x downsampling을 하면 성능이 낮아진다. 이는 GAN의 artifact를 소실시켜 주는 역할을 하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMPDz9/btslS5eYLeh/s4ScqhpK0WgXwn6YNKamWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMPDz9/btslS5eYLeh/s4ScqhpK0WgXwn6YNKamWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMPDz9/btslS5eYLeh/s4ScqhpK0WgXwn6YNKamWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMPDz9%2FbtslS5eYLeh%2Fs4ScqhpK0WgXwn6YNKamWk%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;786&quot; height=&quot;319&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1245&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2TyxJ/btslUsgxR2C/68enKKzKL0tLFHjweWzlLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2TyxJ/btslUsgxR2C/68enKKzKL0tLFHjweWzlLK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/2104.02617.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2TyxJ/btslUsgxR2C/68enKKzKL0tLFHjweWzlLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2TyxJ%2FbtslUsgxR2C%2F68enKKzKL0tLFHjweWzlLK%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;781&quot; height=&quot;358&quot; data-origin-width=&quot;1245&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/2104.02617.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;또한, contributing factor을 찾기 위해 실행한 실험에서는 다음과 같이 variable을 바꾸어 보면서 진행했는데 no downsampling이 큰 역할을 한다는 것을 알 수 있다. 논문에서는 15%의 accuracy와 14%의 Pd@5%의 증가를 가져왔다고 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Conclusion&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아직 GAN image detection을 하기 위한 reliable tool은 없다&lt;/li&gt;
&lt;li&gt;downsampling을 하지 않는 것이 성능을 올려준다&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>논문 리뷰/Computer Vision</category>
      <category>Ai</category>
      <category>Detection</category>
      <category>gan</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/45</guid>
      <comments>https://limepencil.tistory.com/45#entry45comment</comments>
      <pubDate>Thu, 29 Jun 2023 16:24:43 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Prioritized Experience Replay (PER)</title>
      <link>https://limepencil.tistory.com/43</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1511.05952&quot;&gt;[1511.05952] Prioritized Experience Replay (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1684744015755&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Prioritized Experience Replay&quot; data-og-description=&quot;Experience replay lets online reinforcement learning agents remember and reuse experiences from the past. In prior work, experience transitions were uniformly sampled from a replay memory. However, this approach simply replays transitions at the same frequ&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1511.05952&quot; data-og-url=&quot;https://arxiv.org/abs/1511.05952v4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/KG18j/hySHhht99r/k8AL50gJjkQcBMP3mh4Hm1/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/dMBzCb/hySJhGS02T/fxBFpIo4uOc5cHIusQgFFK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1511.05952&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1511.05952&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/KG18j/hySHhht99r/k8AL50gJjkQcBMP3mh4Hm1/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/dMBzCb/hySJhGS02T/fxBFpIo4uOc5cHIusQgFFK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Prioritized Experience Replay&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Experience replay lets online reinforcement learning agents remember and reuse experiences from the past. In prior work, experience transitions were uniformly sampled from a replay memory. However, this approach simply replays transitions at the same frequ&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문은 DQN의 uniformly sampled experience replay를 중요도에 따라 prioritized experience replay로 바꾸어서 성능 향상을 이루어 냈다. DQN논문의 마지막에 prioritized sweeping에 대해 이야기를 하면서 성능 향상의 가능성의 제기하는데 이 논문이 그것을 이루어낸 논문이다.&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;a href=&quot;https://limepencil.tistory.com/39&quot;&gt;[논문 리뷰] Human-level Control through Deep Reinforcement Learning (DQN) &amp;mdash; LimePencil's Log (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1684745283487&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[논문 리뷰] Human-level Control through Deep Reinforcement Learning (DQN)&quot; data-og-description=&quot;Human-level control through deep reinforcement learning | Nature 이번에는 Nature지에 발표된 DQN관련된 논문을 리뷰해보고자 한다. Playing Atari with Deep Reinforcement Learning과 거의 같은 저자들이 작성을 했는데 이는 &quot; data-og-host=&quot;limepencil.tistory.com&quot; data-og-source-url=&quot;https://limepencil.tistory.com/39&quot; data-og-url=&quot;https://limepencil.tistory.com/39&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/J0Rwz/hySJaHMAMd/vYtbplQ06b2Tp9QXBuU5bk/img.png?width=800&amp;amp;height=1002&amp;amp;face=0_0_800_1002,https://scrap.kakaocdn.net/dn/cmifww/hySJfvytUw/8TrbOkPddCVLvl0NVRWqv1/img.png?width=800&amp;amp;height=1002&amp;amp;face=0_0_800_1002,https://scrap.kakaocdn.net/dn/bBafuT/hySJnUFbtn/EdXbopdietD9uVzg6k9PI1/img.png?width=896&amp;amp;height=686&amp;amp;face=0_0_896_686&quot;&gt;&lt;a href=&quot;https://limepencil.tistory.com/39&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://limepencil.tistory.com/39&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/J0Rwz/hySJaHMAMd/vYtbplQ06b2Tp9QXBuU5bk/img.png?width=800&amp;amp;height=1002&amp;amp;face=0_0_800_1002,https://scrap.kakaocdn.net/dn/cmifww/hySJfvytUw/8TrbOkPddCVLvl0NVRWqv1/img.png?width=800&amp;amp;height=1002&amp;amp;face=0_0_800_1002,https://scrap.kakaocdn.net/dn/bBafuT/hySJnUFbtn/EdXbopdietD9uVzg6k9PI1/img.png?width=896&amp;amp;height=686&amp;amp;face=0_0_896_686');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[논문 리뷰] Human-level Control through Deep Reinforcement Learning (DQN)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Human-level control through deep reinforcement learning | Nature 이번에는 Nature지에 발표된 DQN관련된 논문을 리뷰해보고자 한다. Playing Atari with Deep Reinforcement Learning과 거의 같은 저자들이 작성을 했는데 이는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;limepencil.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Introduction&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Online RL은 바로 들어온 데이터를 이용해 파라미터를 업데이트하는데 이는 두 가지의 문제가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;RL에서는 연속되는 데이터 간의 상관관계가 아주 크기 때문에 기존의 stochastic gradient algorithm에 부적합하다.&lt;/li&gt;
&lt;li&gt;rare 한 경험을 나중에 사용하지 못하고 잊어버리게 된다&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 experience replay가 나왔고 덕분에 예전의 데이터와 최신의 데이터를 같이 학습하여 위에 제기된 문제들을 모두 해결하였다. DQN에서는 이것을 사용하여 가치함수의 학습을 안정화시켰다. DQN에서는 large sliding widnow replay memory를 사용하였는데 이는 필요한 데이터를 줄이고 이를 더 많은 계산과 메모리로 대체하였다.&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;하지만 위의 방법에서는 같은 확률로 모든 데이터를 사용하기 때문에 더 좋은 데이터와 덜 좋은 데이터의 차이를 구분하지 못한다는 단점이 있다 이를 염두의 두고 만든 게 prioritized experience replay (PER)이다. 이 논문에서는 temporal-difference(TD) error의 크기를 기준으로 삼아 priority를 정의하였다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;TD error은 value function의 예측값과 실제 $V$의 차이의 크기이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Background&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 뇌과학적인 studies를 통해 쥐의 hippocampus에서 experience replay가 되고 있다는 사실이 밝혀졌다. 또한, 보상과 관련된 sequence는 더 자주 replay 되었다. 또한, TD error이 높은 sequence도 자주 replay 되었다. 이를 강화학습의 알고리즘에 적용을 하려고 prioritized sweeping이라는 기법이 소개되었고(1999), TD error을 이 priority의 기준으로 적용한 연구가 있었다(2013). 이 논문에서는 이 아이디어를 사용하여 model-free RL에 맞추어 변형을 시켰고 stochastic sampling을 사용하여 function approximator에 더 잘 맞도록 하였다.&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;Prioritized Replay&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Using a replay memory leads to design choices at two levels: which experiences to store, and which experiences to replay (and how to do so). This paper addresses only the latter: making the most effective use of the replay memory for learning, assuming that its contents are outside of our control.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Replay memory를 사용하기 위해서 고려해야 할게 두 가지가 있는데:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;어떤 experience를 저장할지&lt;/li&gt;
&lt;li&gt;어떤 experince를 학습할지&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 1번은 컨트롤 밖이라고 생각하여 2번에 집중한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1115&quot; data-origin-height=&quot;348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C2zbS/btshyPgDs9a/1TRaVkT984biVlIkyK7xK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C2zbS/btshyPgDs9a/1TRaVkT984biVlIkyK7xK1/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1511.05952.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C2zbS/btshyPgDs9a/1TRaVkT984biVlIkyK7xK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC2zbS%2FbtshyPgDs9a%2F1TRaVkT984biVlIkyK7xK1%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;1115&quot; height=&quot;348&quot; data-origin-width=&quot;1115&quot; data-origin-height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1511.05952.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 Blind Cliffwalk라는 환경을 예를 들어 왜 중요한지 설명한다. 이 환경에서는 reward를 random 한 방식으로 얻는데 $2^{-n}$만큼의 step이 필요한데 이를 기존의 experience replay를 사용한다면 너무 많은 실패에 성공한 experience가 묻힐 것이다. 위의 그래프를 보면 어떠한 strategy를 가지고 replay를 선택한 방법이 랜덤 하게 고르는 것보다 훨씬 더 빠른 학습 속도를 보여준다.&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;priority의 기준을 TD error으로 잡으면 agent가 이 experience가 얼마나 unexpected 했는지, 즉 배울 점이 많은지를 어느 정도 측정할 수 있다. 이것은 특히 online RL에 적합하지만 reward가 noisy 한 경우에는 잘 작동을 하지 않을 수 있다. TD error 순서대로 나열하고 이대로 학습을 하는 greedy TD-error prioritization은 위에 얘기했었던 환경에서 상당한 속도 향상을 보여줬다.&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;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;TD error 순서대로 replay가 되기 때문에 TD-error이 낮은 sequence는 한 번도 replay가 안될 수도 있다.&lt;/li&gt;
&lt;li&gt;stochastic reward 같은 noise에 취약하다&lt;/li&gt;
&lt;li&gt;너무 한정된 experience만 반복해서 학습한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 해결하기 위해 이 논문에서는 stochastic sampling을 제안한다. Stochastic prioritization을 사용하면 priority의 순서는 maintain 되나 모든 experience에 대해 0이 아닌 sampling 확률을 보장한다. 확률은 다음과 같은 식으로 정의된다. $$P(i) = \frac {p_i^\alpha}{\sum_k p_k^\alpha}$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서 $p_i$는 priority이고 $\alpha$는 얼마만큼의 prioritization을 사용하는지에 대한 hyperparameter이다 ($\alpha$ = 0일 때 uniform).&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;이 논문에서는 $p_i$에 대해서 두 가지를 제시하는데:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Proportional prioritization: $p_i = |\delta_i| + \epsilon$ ($\epsilon$ is to have non-zero priority)&lt;/li&gt;
&lt;li&gt;Rank-based prioritization: $p_i = \frac {1}{\text {rank}(i)}$&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I5CJk/btshAZXvRz6/B9qs6uXBBhPy9hf0VzkyzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I5CJk/btshAZXvRz6/B9qs6uXBBhPy9hf0VzkyzK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1511.05952.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I5CJk/btshAZXvRz6/B9qs6uXBBhPy9hf0VzkyzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI5CJk%2FbtshAZXvRz6%2FB9qs6uXBBhPy9hf0VzkyzK%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;442&quot; height=&quot;264&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1511.05952.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 rank-based가 outlier에 영향을 받지 않기 때문에 더 robust 하다고 설명하고 있다. 실제로 위의 그래프를 보면 Blind Cliffwalk 환경에서 더 빠른 속도로 학습하고 있는 것을 알 수 있다.&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;하지만&amp;nbsp;prioritization을&amp;nbsp;사용하면&amp;nbsp;expected&amp;nbsp;distribution에서&amp;nbsp;멀어지기&amp;nbsp;때문에&amp;nbsp;bias가&amp;nbsp;생긴다.&amp;nbsp;이는&amp;nbsp;수렴해야 하는&amp;nbsp;정해진&amp;nbsp;정답에서&amp;nbsp;멀어지도록&amp;nbsp;된다.&amp;nbsp;이를&amp;nbsp;해결하기&amp;nbsp;위해&amp;nbsp;importance-sampling(IS)을&amp;nbsp;도입하여&amp;nbsp;해결하고자&amp;nbsp;했다. &lt;br /&gt;&lt;br /&gt;$$w_i = \left(\frac {1}{N} \cdot&amp;nbsp;&amp;nbsp;\frac {1}{P(i)}\right)^{\beta}$$ &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 weight을 Q-learning update때에$\delta_i$대신 $w_i \delta_i$로 사용하면 된다 ($\frac {1}{\max_i w_i}$를 사용하여 normalize 해준다). $\beta$를 어떤 값에서 시작하여 1로 anneal 하게 만들면 처음에는 크게 update가 반영이 되다가 점점 안정적으로 변한다. 이 방식의 장점은 high-error인 transition을 자주 보게 만들면서 그의 따른 gradient magnitude를 줄일 수 있는 방법이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Atari Experiments&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bprciB/btshCbC8LNO/7UFNkUzvkZGc0L4Jn6Qk41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bprciB/btshCbC8LNO/7UFNkUzvkZGc0L4Jn6Qk41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bprciB/btshCbC8LNO/7UFNkUzvkZGc0L4Jn6Qk41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbprciB%2FbtshCbC8LNO%2F7UFNkUzvkZGc0L4Jn6Qk41%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;757&quot; height=&quot;288&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;316&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;193&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBleEZ/btshyNj0p1P/UwwtOQALyh8yZy9sY8bXW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBleEZ/btshyNj0p1P/UwwtOQALyh8yZy9sY8bXW1/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1511.05952.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBleEZ/btshyNj0p1P/UwwtOQALyh8yZy9sY8bXW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBleEZ%2FbtshyNj0p1P%2FUwwtOQALyh8yZy9sY8bXW1%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;724&quot; height=&quot;193&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;193&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1511.05952.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DRL에서는 빼놓을 수 없는 Atari benchmark에서 DQN과 DDQN에 PER을 결합하여 state-of-the-art를 달성하였다. 이번 논문에서 나온 hyperparameter인 $\alpha$와 $\beta_0$는 coarse grid search를 사용하여 적절한 값을 찾았다. 이 방법은 성능을 올릴뿐더러 더 빠르게 학습을 진행시킬 수 있다. 또한 DDQN의 예시를 통해 DQN의 improvements들과 complementary 하다는 것이 증명되었다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Discussion &amp;amp; Conclusion&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rank-based가 예상과는 다르게 그렇게 robust 한 성능을 보여주지 않았는데 이는 relative error scale을 없애면서 performance drop이 생기기 때문이다. 또한 과도한 clipping이 두 가지의 방법이 비슷한 결과를 가지고 오게 하는 이유일 수도 있다. PER을 supervised learning에도 적용시키는 방법을 말하고 있고, 또한 prioritized memory 같은 맨 처음에 말했었던 방법을 제시하고 있다. 결론적으로, PER은 학습 속도를 2배를 향상하면서 성능을 높였고 이는 RL 학습을 효율적으로 하는데에 기여했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>DQN</category>
      <category>PER</category>
      <category>prioritized experience replay</category>
      <category>RL</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/43</guid>
      <comments>https://limepencil.tistory.com/43#entry43comment</comments>
      <pubDate>Mon, 22 May 2023 17:42:41 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Dueling Network Architectures for Deep Reinforcement Learning (Dueling DQN)</title>
      <link>https://limepencil.tistory.com/42</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1511.06581&quot;&gt;[1511.06581] Dueling Network Architectures for Deep Reinforcement Learning (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1683940540325&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Dueling Network Architectures for Deep Reinforcement Learning&quot; data-og-description=&quot;In recent years there have been many successes of using deep representations in reinforcement learning. Still, many of these applications use conventional architectures, such as convolutional networks, LSTMs, or auto-encoders. In this paper, we present a n&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1511.06581&quot; data-og-url=&quot;https://arxiv.org/abs/1511.06581v3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bHGO8O/hySBAz9CO7/j5Y0fk4X11uiigaIACe70K/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/ckaLWe/hySBzBfbtQ/GlDPCvgOVQHZELe78rGdZ1/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1511.06581&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1511.06581&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bHGO8O/hySBAz9CO7/j5Y0fk4X11uiigaIACe70K/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/ckaLWe/hySBzBfbtQ/GlDPCvgOVQHZELe78rGdZ1/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Dueling Network Architectures for Deep Reinforcement Learning&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;In recent years there have been many successes of using deep representations in reinforcement learning. Still, many of these applications use conventional architectures, such as convolutional networks, LSTMs, or auto-encoders. In this paper, we present a n&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 논문에서는 두 개의 estimator 즉 state value function과 action advantage function 두 개를 DQN에서 변형한 논문에 대해 리뷰할 것입니다. DQN에 대한 리뷰는 아래 글을 참조하시면 됩니다.&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;a href=&quot;https://limepencil.tistory.com/38&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN) &amp;mdash; LimePencil's Log (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1684073354561&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&quot; data-og-description=&quot;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&quot; data-og-host=&quot;limepencil.tistory.com&quot; data-og-source-url=&quot;https://limepencil.tistory.com/38&quot; data-og-url=&quot;https://limepencil.tistory.com/38&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bPGFtU/hySCPcGPWE/rMkJzWr9e2SkgmCdKMUiK0/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/bAe3mA/hySCWCSUgS/HYGqiFOkVkVIZmkUqZgyD1/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/dlFq9c/hySCP4PxHr/oBggd9eFlRqwEOqHzALij0/img.png?width=750&amp;amp;height=939&amp;amp;face=0_0_750_939&quot;&gt;&lt;a href=&quot;https://limepencil.tistory.com/38&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://limepencil.tistory.com/38&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bPGFtU/hySCPcGPWE/rMkJzWr9e2SkgmCdKMUiK0/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/bAe3mA/hySCWCSUgS/HYGqiFOkVkVIZmkUqZgyD1/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/dlFq9c/hySCP4PxHr/oBggd9eFlRqwEOqHzALij0/img.png?width=750&amp;amp;height=939&amp;amp;face=0_0_750_939');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;limepencil.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Introduction&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Here, we take an alternative but complementary approach of focusing primarily on innovating a neural network architecture that is better suited for model-free RL.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논문에서는 현존하는 model-free RL의 neural network에 complementary 한 improvement를 적용한 방법론을 설명하고 있다. 이 방법의 장점은 다른 RL 알고리즘과 간단하게 통합해서 작동할 수 있다. 이것을 논문에서는 dueling architecture이라고 하고 있는데, state value의 표현과 action advantage의 표현을 따로 분리해서 학습한다.&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;같은 CNN feature을 받아서 state value와 action advantage network로 나누고 이를 다시 special aggregating layer을 통해 합쳐서 state-action value function $Q$를 구할 수 있다. 즉,&amp;nbsp; 기존의 DQN의 single stream에서 dual stream으로 교체한다고 생각하면 된다. 이 네트워크는 자동으로 state value와 action advantage를 인간의 supervision 없이 학습한다.&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가 중요한지의 대한 것을 action과 관련 없이 판단할 수 있다. 즉 무슨 행동을 하는지 중요하지 않은 state 같은 경우를 판단할 수 있다는 것이다. Redundant 한 action인지 아닌지를 판단할 수 있는 좋은 방법이다.&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;Background&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문의 배경지식으로는 Q-function, DQN(&lt;a href=&quot;https://limepencil.tistory.com/38&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://limepencil.tistory.com/38&lt;/a&gt;),&amp;nbsp; DDQN(&lt;a href=&quot;https://limepencil.tistory.com/41&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://limepencil.tistory.com/41&lt;/a&gt;), PER 등이 나오는데 priotized experience replay를 제외한 나머지는 리뷰 글을 이미 썼고 PER도 곧 쓸 것이다(2023.04.15).&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;The Dueling Network Architecture&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;275&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S95EG/btsfgg2ge8C/eKkttcFMCFWt6OFasTLVCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S95EG/btsfgg2ge8C/eKkttcFMCFWt6OFasTLVCK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1511.06581.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S95EG/btsfgg2ge8C/eKkttcFMCFWt6OFasTLVCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS95EG%2Fbtsfgg2ge8C%2FeKkttcFMCFWt6OFasTLVCK%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;371&quot; height=&quot;275&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;275&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1511.06581.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dueling DQN의 구조는 다음과 같다. 위에 있는 그림처럼 single sequence의 fully-connected layer이 있는 것과 대비해서 two sequence의 fully-connected layer이 있고 이들을 합쳐서 하나의 $Q$ fuction이 나오게 된다. 즉 output자체의 형식은 DQN과 같기 때문에 DDQN이나 PER 같은 다른 DQN의 improvement들을 적용하기에 용이하다.&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;마지막에 합쳐주는 aggregating layer을 $$ Q(s, a;\theta,\alpha,\beta) = V(s, a;\theta,\beta) + A(s, a;\theta,\alpha)$$처럼 그냥 합친다고 생각할 수 있지만 그러면 $V$와 $A$의 차이를 identify 할 수 없기 때문에 다른 수식을 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ Q(s, a;\theta,\alpha,\beta) = V(s, a;\theta,\beta) + (A(s, a;\theta,\alpha) - \underset {a' \in |A|}{max} A (s, a';\theta, \alpha))$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 수식을 사용하면 optimal action인 $$a^* = \mathrm {argmax}_{a' \in \mathcal {A}} Q(s, a';\theta,\alpha,\beta) = \mathrm {argmax}_{a' \in \mathcal {A}} A(s, a';\theta,\alpha)$$ 에서는 $Q(s, a';\theta,\alpha,\beta) = V(s;\theta,\beta)$가 성립한다.&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^*;\theta,\alpha,\beta) = V(s, a;\theta,\beta) + \Biggl(A(s, a;\theta,\alpha) - \frac {1}{|\mathcal {A}|} \sum_{a'} A (s, a';\theta, \alpha)\Biggl)$$ 이 방법은 $V$의 의미를 잃어버리지만 그 대신 $a^*$에 맞춰 update 하는 것보다 stable 하다. 그래서 이 논문에서는 이 수식을 채용하였다. 어떠한 값을 빼더라도 relative rank는 변하지 않기 때문에 정보의 손실은 일어나지 않는다. 또한 이 계산은 따로 하는 것이 아닌 네트워크의 일부분이기 때문에 auto backpropagation이 가능하다.&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;Experiments&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;The results show that with 5 actions, both architectures converge at about the same speed. However, when we increase the number of actions, the dueling architecture per forms better than the traditional Q-network.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z2tb5/btsf9BZslbT/h19jQ0qSqWd3ezUdorYU10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z2tb5/btsf9BZslbT/h19jQ0qSqWd3ezUdorYU10/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1511.06581.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z2tb5/btsf9BZslbT/h19jQ0qSqWd3ezUdorYU10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz2tb5%2Fbtsf9BZslbT%2Fh19jQ0qSqWd3ezUdorYU10%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;570&quot; height=&quot;186&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1511.06581.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실험 결과에 따르면 Corridor이라는 실험 환경에서 Dueling DQN은 그냥 DQN보다 action의 개수가 많을 때 더 빠른 convergence를 보여주었다. 이는 공유되는 $V(s;\theta,\beta)$가 general 한 값을 학습하기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;455&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMekVv/btsgcoZeTzV/zRGpjoKybJBcmZOeyIMWxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMekVv/btsgcoZeTzV/zRGpjoKybJBcmZOeyIMWxK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1511.06581.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMekVv/btsgcoZeTzV/zRGpjoKybJBcmZOeyIMWxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMekVv%2FbtsgcoZeTzV%2FzRGpjoKybJBcmZOeyIMWxK%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;455&quot; height=&quot;221&quot; data-origin-width=&quot;455&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1511.06581.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, Atari 벤치마크에서는 DQN, DDQN, Dueling DDQN, 그리고 PER을 적용한 성능을 비교하여 Dueling architecture이 실제 향상이 있다는 것을 증명하였다. 이 논문에서는 다른 hyperparameter은 다 같게 하고 learning rate를 조금 낮게 조정한 후에 convolution layer의 gradient을 $\frac {1}{\sqrt {2}}$로 rescale 하였다. 그리고 10 이상의 gradient를 clipping을 적용하였다. 실제로 모든 성능 향상 방법을 다 채택한 Dueling DDQN with PER이 제일 좋은 성능을 보여주는 것으로 보인다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;396&quot; data-origin-height=&quot;487&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJypOD/btsgcLNn39l/q9OKzyFoOfZAByLyHXsB20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJypOD/btsgcLNn39l/q9OKzyFoOfZAByLyHXsB20/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1511.06581.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJypOD/btsgcLNn39l/q9OKzyFoOfZAByLyHXsB20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJypOD%2FbtsgcLNn39l%2Fq9OKzyFoOfZAByLyHXsB20%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;396&quot; height=&quot;487&quot; data-origin-width=&quot;396&quot; data-origin-height=&quot;487&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1511.06581.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Saliency map을 계산해서 각 value network과 advantage network이 어떤 것을 집중해서 보고 있는지를 확인해 보면 value network는 앞에 오고 있는 장애물에 집중을 하고(이 state 자체를 판단) advantage network는 곧 닥쳐올 장애물에 집중을 하고 있는 것으로 보인다(이 상황에서 어떤 action을 취해야 하는지 판단). 즉 두 가지의 다른 network가 이 논문에서 제안한 역할을 하고 있는 것이다.&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;Discussion &amp;amp; Conclusion&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 dueling network의 장점은 보통 single network에서는 한 action에 대하여 update가 진행이 된다면 여기에서는 공통된 $V$가 update가 되기 때문에 더 efficient 하다고 볼 수 있다. 또한 기존의 DDQN은 Q-value 간의 크기 차이가 Q-value자체의 magnitude와 scale차이가 커서 noise를 발생시킬 수 있는데 dueling network는 이런 부분을 해결한다.&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;마무리를 하자면, 이 논문에서는 기존의 DQN의 network를 value network와 advantage network로 나누어서 Atari benchmark에서 state-of-the-art를 달성하였다.&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>Dueling DQN</category>
      <category>논문리뷰</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/42</guid>
      <comments>https://limepencil.tistory.com/42#entry42comment</comments>
      <pubDate>Sat, 13 May 2023 10:15:53 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Deep Reinforcement Learning with Double Q-learning (DDQN)</title>
      <link>https://limepencil.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1509.06461&quot;&gt;[1509.06461] Deep Reinforcement Learning with Double Q-learning (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698079492071&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Deep Reinforcement Learning with Double Q-learning&quot; data-og-description=&quot;The popular Q-learning algorithm is known to overestimate action values under certain conditions. It was not previously known whether, in practice, such overestimations are common, whether they harm performance, and whether they can generally be prevented.&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1509.06461&quot; data-og-url=&quot;https://arxiv.org/abs/1509.06461v3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dVw0Nc/hyUj9UP3OA/Rav8asmtRnvrQ6FDWh5dIK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/ScQwV/hyUgRVOIAb/XyFT5bdXPQHd5fobVtQtDk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1509.06461&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1509.06461&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dVw0Nc/hyUj9UP3OA/Rav8asmtRnvrQ6FDWh5dIK/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/ScQwV/hyUgRVOIAb/XyFT5bdXPQHd5fobVtQtDk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Deep Reinforcement Learning with Double Q-learning&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The popular Q-learning algorithm is known to overestimate action values under certain conditions. It was not previously known whether, in practice, such overestimations are common, whether they harm performance, and whether they can generally be prevented.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 논문은 DQN에서의 target을 변형시켜서 overestimation을 해결한 Double DQN에 대해 리뷰할 것이다. DQN에&amp;nbsp;대한&amp;nbsp;리뷰는&amp;nbsp;아래&amp;nbsp;블로그&amp;nbsp;글을&amp;nbsp;참조하면&amp;nbsp;된다.&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;a href=&quot;https://limepencil.tistory.com/38&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN) &amp;mdash; LimePencil's Log (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1683194092073&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&quot; data-og-description=&quot;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&quot; data-og-host=&quot;limepencil.tistory.com&quot; data-og-source-url=&quot;https://limepencil.tistory.com/38&quot; data-og-url=&quot;https://limepencil.tistory.com/38&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/m6WqA/hySvmvoA0V/U22V4jZoemebY1lUB4pzH0/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/bq9qdW/hySvjMlGMk/0Y2WBTLzKPoqfju2qc5XC0/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/bNqP0o/hySvxRez1n/oFxAVmnKnQql2BXVHicPUk/img.png?width=750&amp;amp;height=939&amp;amp;face=0_0_750_939&quot;&gt;&lt;a href=&quot;https://limepencil.tistory.com/38&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://limepencil.tistory.com/38&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/m6WqA/hySvmvoA0V/U22V4jZoemebY1lUB4pzH0/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/bq9qdW/hySvjMlGMk/0Y2WBTLzKPoqfju2qc5XC0/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/bNqP0o/hySvxRez1n/oFxAVmnKnQql2BXVHicPUk/img.png?width=750&amp;amp;height=939&amp;amp;face=0_0_750_939');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;limepencil.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Abstract&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;The popular Q-learning algorithm is known to overestimate action values under certain conditions. It was not previously known whether, in practice, such overestimations are com mon, whether they harm performance, and whether they can generally be prevented.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 Q-learning의 하나의 단점을 언급한다. Q-learning에서 action value를 overestimate 하는 경향이 있는데 이것을 해결할 수 있는지 탐색해 본다고 한다. 또한 제한된 환경에서만 쓸 수 있는 Double Q-learning을 generalize 하게 바꾸어서 DQN의 변형으로 사용하는 연구를 이 논문에 담았다. 이를 통해 기존 벤치마크보다 성능 향상을 보여준다고 한다.&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;Overestimation이 생기는 이유는 target을 계산할 때 max를 사용하기 때문에 그런데, uniformly overestimating 하다면 이 자체는 문제가 아니지만, 균일하지 않고 학습하고 싶은 state에 집중되어 있지 않다면 이는 성능에 영향을 줄 수 있다.&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;실제로 DQN에서 overestimation이 관찰되었고 이를 해결할 방안은 이 논문에서 제시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Background&lt;/h3&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;The max operator in standard Q-learning and DQN, in (2) and (3), uses the same values both to select and to evaluate an action. This makes it more likely to select overestimated values, resulting in overoptimistic value estimates. To prevent this, we can decouple the selection from the evaluation. This is the idea behind Double Q-learning.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Double DQN을 위해서는 두 가지의 사전 지식이 필요한데 이는 DQN과 Double Q-learning이다. DQN은 위에 있는 논문 리뷰에 잘 정리되어 있기 때문에 Double Q-learning에 조금 더 집중할 것이다.&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-learning에서는 $Y_t^Q \equiv R_{t+1} + \gamma \underset{a}{\max}Q(S_{t+1},a;\theta_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;여기에서 DQN은 target network를 사용하여 $\theta$대신에 $\theta^-$을 사용하여 업데이트한다.&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-learning은 같은 max operator이 action을 고르고 평가하는 데에 쓰이기 때문에 이것이 overestimation을 일으킬 수 있다. Double Q-learning은 이 두 개를 나누어서 계산한다. Double Q-learning에는 두 개의 weight $\theta$와 $\theta'$이 사용되는데 이 두 개 중에 하나를 랜덤 하게 골라서 업데이트한다. 하나는 greedy 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;식은 $Y_t^{DoubleQ} \equiv R_{t+1} + \gamma&amp;nbsp; Q(S_{t+1},\underset{a}{\mathrm{argmax}}Q(S_{t+1},a;\theta_t);\theta_t')$ 과 같고 online weight인 $\theta_t$만 업데이트된다. 두 개의 가중치를 바꾸어서 사용하면서 symmetrical 하게 업데이트할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Overoptimism due to estimation errors&lt;/h3&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;In this section we demonstrate more generally that estimation errors of any kind can induce an upward bias, regardless of whether these errors are due to environmental noise, function approximation, non-stationarity, or any other source.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYxrR9/btsdZZzYYSn/o4UAxGmD4j1GkSOv8h0kZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYxrR9/btsdZZzYYSn/o4UAxGmD4j1GkSOv8h0kZ1/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1509.06461.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYxrR9/btsdZZzYYSn/o4UAxGmD4j1GkSOv8h0kZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYxrR9%2FbtsdZZzYYSn%2Fo4UAxGmD4j1GkSOv8h0kZ1%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;502&quot; height=&quot;201&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1509.06461.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 파트에서는 estimation error이 environmental noise, function approximation, non-stationarity 등 때문에 생길 수 있다고 하고 upward bound와 lower bound를 구한다. 논문에서는 action의 개수가 올라갈수록 그냥 Q-learning은 error이 늘어나는 것을 볼 수 있다. 하지만 Double Q-learning을 사용하면 error이 action의 개수에 비례하지 않는다. 또한 특정한 value function에만 국한되는 현상이 아니기 때문에 이를 해결하는 게 accurate 하게 value function을 근사하는 방법이다.&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;Double DQN&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;We therefore propose to evaluate the greedy policy according to the online network, but using the target ne&amp;nbsp; twork to estimate its value. In reference to both Double Q-learning and DQN, we refer to the resulting algorithm as Double DQN.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Double DQN은 Double Q-learning + DQN이라고 보면 된다. target이 $Y_t^{DoubleDQN} \equiv R_{t+1} + \gamma&amp;nbsp; Q(S_{t+1},\underset {a}{\mathrm {argmax}}Q(S_{t+1}, a;\theta_t);\theta_t^-)$로 바뀌는 것 빼고 다른 것이 없다. 여기서 주목할 점은 target 네트워크로 evaluation을 하고 online network는 action selection을 한다는 것이다. 이 방식은 DQN의 장점을 가져가면서도 computationally expensive 하지 않게 성능을 올릴 수 있는 방법이다.&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;Empirical results&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;If seen in isolation, one might perhaps be tempted to think the observed instability is related to inherent instability problems of off-policy learning with function approximation. However, we see that learning is much more stable with Double DQN, suggesting that the cause for these instabilities is in fact Q-learning&amp;rsquo;s overoptimism.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;175&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhH1AG/btsdZZfYkaW/Mj68ORnNq15ZKRGKwldlF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhH1AG/btsdZZfYkaW/Mj68ORnNq15ZKRGKwldlF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhH1AG/btsdZZfYkaW/Mj68ORnNq15ZKRGKwldlF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhH1AG%2FbtsdZZfYkaW%2FMj68ORnNq15ZKRGKwldlF1%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;538&quot; height=&quot;175&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;175&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Double DQN은 DQN보다 확실한 성능 향상을 보여준다. 같은 hyperparameter로 학습을 시켜도 더 좋은 결과를 보여주고, fine-tuning을 진행했을 때에는 더욱더 좋은 성능을 보여주었다. 이는 저자들이 말한 overoptimism이 성능을 저하시키는 원인이라는 것을 보여준다.&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;Discussion &amp;amp; Conclusion&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q-learning은 큰 환경의 문제에서 overoptimistic 하는 경향이 있고 이를 저자들은 Double Q-learning을 DQN에 접목한 DDQN이라는 새로운 아키텍처를 제안한다. DDQN은 overestimation을 줄이고, Atari 2600 벤치마크에서 SOTA를 기록하는 결과를 보여주었다. 또한 DDQN은 DQN을 크게 바꾸지 않기 때문에 periority experience replay나 dueling DQN 같은 다른 향상 방법을 적용할 수 있다.&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>DDQN</category>
      <category>Double DQN</category>
      <category>논문 리뷰</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/41</guid>
      <comments>https://limepencil.tistory.com/41#entry41comment</comments>
      <pubDate>Thu, 4 May 2023 19:19:02 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Deep Recurrent Q-Learning for Partially Observable MDPs (DRQN)</title>
      <link>https://limepencil.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1507.06527&quot;&gt;[1507.06527] Deep Recurrent Q-Learning for Partially Observable MDPs (arxiv.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1680150537252&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Deep Recurrent Q-Learning for Partially Observable MDPs&quot; data-og-description=&quot;Deep Reinforcement Learning has yielded proficient controllers for complex tasks. However, these controllers have limited memory and rely on being able to perceive the complete game screen at each decision point. To address these shortcomings, this article&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1507.06527&quot; data-og-url=&quot;https://arxiv.org/abs/1507.06527v4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/capxUi/hyR6JYeMhe/2i8KTyfaBPsBokDQmllZkk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/c2tHxg/hyR5vtJYm7/KWul2KLKgI86VXbuHRY1Mk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1507.06527&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1507.06527&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/capxUi/hyR6JYeMhe/2i8KTyfaBPsBokDQmllZkk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/c2tHxg/hyR5vtJYm7/KWul2KLKgI86VXbuHRY1Mk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Deep Recurrent Q-Learning for Partially Observable MDPs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Deep Reinforcement Learning has yielded proficient controllers for complex tasks. However, these controllers have limited memory and rely on being able to perceive the complete game screen at each decision point. To address these shortcomings, this article&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&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;이번 논문은 DQN에 LSTM을 추가해서 Partially Obervable MDP(POMDP) 상태일 때 vanilla DQN보다 성능하락을 줄여주는 연구를 리뷰할 것이다. DQN에 대한 리뷰는 아래 블로그 글을 참조하면 된다.&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;a href=&quot;https://limepencil.tistory.com/38&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN) &amp;mdash; LimePencil's Log (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1680153403887&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&quot; data-og-description=&quot;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&quot; data-og-host=&quot;limepencil.tistory.com&quot; data-og-source-url=&quot;https://limepencil.tistory.com/38&quot; data-og-url=&quot;https://limepencil.tistory.com/38&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/swVo6/hyR5mjbM59/kv3OcMvJiyLFsohbl0qWGk/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/S0vkb/hyR6GmNvmN/AKOSqbsN2ty2E3qw2SuwAK/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/yTM0Q/hyR5pNI9GU/u0OvxFjdq5ypJXpsylPLl0/img.png?width=1171&amp;amp;height=513&amp;amp;face=0_0_1171_513&quot;&gt;&lt;a href=&quot;https://limepencil.tistory.com/38&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://limepencil.tistory.com/38&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/swVo6/hyR5mjbM59/kv3OcMvJiyLFsohbl0qWGk/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/S0vkb/hyR6GmNvmN/AKOSqbsN2ty2E3qw2SuwAK/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/yTM0Q/hyR5pNI9GU/u0OvxFjdq5ypJXpsylPLl0/img.png?width=1171&amp;amp;height=513&amp;amp;face=0_0_1171_513');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;limepencil.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Abstract&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Deep Reinforcement Learning has yielded proficient controllers for complex tasks. However, these controllers have limited memory and rely on being able to perceive the complete game screen at each decision point. To address these shortcomings, this article investigates the effects of adding recurrency to a Deep Q-Network (DQN) by replacing the first post-convolutional fully-connected layer with a recurrent LSTM.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;361&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUGZ31/btr7HeRwg4g/9acpHppOkWxFCZF2Q22Rqk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUGZ31/btr7HeRwg4g/9acpHppOkWxFCZF2Q22Rqk/img.jpg&quot; data-alt=&quot;https://wikidocs.net/152773&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUGZ31/btr7HeRwg4g/9acpHppOkWxFCZF2Q22Rqk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUGZ31%2Fbtr7HeRwg4g%2F9acpHppOkWxFCZF2Q22Rqk%2Fimg.jpg&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;595&quot; height=&quot;320&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;361&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://wikidocs.net/152773&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 DQN의 변형인 DRQN을 소개하고 있다. DRQN은 첫 번째 fully connected layer을 LSTM으로 대체하여 한번에 1개의 frame을 보고도 DQN과 비슷한 성능을 낼 수 있다. 더 중요한 것은 input이 지속적으로 주어지지 않고 flickering 할 때에 DQN보다 좋은 성능을 보여준다. 즉, Partially Obervable MDP(POMDP) 상태일 때 성능이 observability에 비례해서 증가한다.&amp;nbsp;&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;Introduction&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;However, Deep Q-Networks are limited in the sense that they learn a mapping from a limited number of past states, or game screens in the case of Atari 2600.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DQN은 저번 리뷰에서도 다루었지만 4개의 frame을 stack 해서 학습한다. 이를 통해 속도와 예상 방향을 알 수 있는데 1개의 frame만 있다면 정적이기 때문에 어디로부터 와서 어디로 가는지 알 수가 없다. 즉 DQN은 4개의 frame밖에서 일어나는 상황은 기억할 수가 없다. 하지만 거의 모든 Atari2600게임은 이를 만족하기 때문에 MDP를 따른다고 볼 수 있다.&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;실제 세상에서는 그 이상으로 필요한 정보가 있을 수 있고 이는 MDP가 아니라 POMDP라고 정의를 해야 한다. 이때 상황에서는 evaluation 단계에서 DQN에 성능이 쭉 떨어지기 때문에 저자들은 LSTM을 DQN과 결합한 DRQN을 제시한다.&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;Partial Observability&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POMDP는 6-tuple로 구성되어 있는데 이는 $(S, A, P, R, \Omega, O)$이다. 이는 $(S, A, P, R)$인 MDP와는 다르다. 여기서 agent는 $o \in \Omega$의 observation을 입력으로 받는다. 이의 확률은 $ o \sim O(s)$로 나타난다. 그냥 DQN과 여기서 차이가 나는데, $Q(o, a|\theta) \neq&amp;nbsp;Q(s, a|theta)$이다. 즉 학습할 시에 완전한 state로 학습을 했다면, 다른 $o$가 나오는 순간 $Q$를 잘못 예측한다는 것이다. 여기서는 sequence of step으로 작동하는 recurrent network가 더 적합하다.&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;DRQN Architecture&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;575&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJbVU/btr7HgicJ4w/8aSNa0yMQAivmR3LkeFBzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJbVU/btr7HgicJ4w/8aSNa0yMQAivmR3LkeFBzK/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1507.06527.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJbVU/btr7HgicJ4w/8aSNa0yMQAivmR3LkeFBzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJbVU%2Fbtr7HgicJ4w%2F8aSNa0yMQAivmR3LkeFBzK%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;520&quot; height=&quot;575&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;575&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1507.06527.pdf&lt;/figcaption&gt;
&lt;/figure&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;DRQN은 DQN의 fully connected layer을 LSTM으로 교체한 간단한 구조이다. 이 구조를 택한 이유는 fully connected layer을 적용하거나 ReLU를 같이 사용하는 것보다 LSTM을 사용하는 방식이 더욱더 효과적이기 때문이다 (그냥 LSTM이 ReLU-LSTM에 비해 709% 성능 향상을 보여준다라고 되어있다). 다른 hyperparameter는 DQN의 그것과 동일하다.&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;Stable Recurrent Updates&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 recurrent layer을 업데이트하는 두 가지 방법을 설명한다.&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;1. Bootstrapped sequential updates: replay memory에서 에피소드 하나를 골라 처음부터 끝까지 업데이트를 한다. RNN의 hidden state는 episode동안 전달된다.&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;2. Bootstrapped random updates: replay memory에서 에피소드를 고르고 랜덤 한 순간부터 한 번의 backward call까지만 update 한다. 즉, RNN의 hidden state는 update마다 0이 된다.&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;여기서 hidden state를 사용할 수 있는 첫 번째 방법은 DQN의 random sampling policy를 위반한다. 실험에 따르면 두 가지의 policy다 비슷한 성능을 내기 때문에 복잡도를 줄이려 두 번째 방법인 bootstrapped random updates를 사용한다.&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;Atari Games: MDP or POMDP? / Flickering Atari Games&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;651&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FJ5Q6/btsb1P62ch0/8rrKKKKePyut68SnkNcjd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FJ5Q6/btsb1P62ch0/8rrKKKKePyut68SnkNcjd0/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1507.06527.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FJ5Q6/btsb1P62ch0/8rrKKKKePyut68SnkNcjd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFJ5Q6%2Fbtsb1P62ch0%2F8rrKKKKePyut68SnkNcjd0%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;395&quot; height=&quot;482&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;651&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1507.06527.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Atari 게임들은 4 frame을 stack 하면 게임의 모든 상황과 운동 방향을 알 수 있기 때문에 MDP라고 할 수 있다. 그래서 이 논문에서는 이 게임들을 POMDP로 만들기 위해 flickering probablity $p = 0.5$를 적용했다. 이는 각 frame마다 50%의 확률로 검은색 frame이 게임 화면 대신에 들어간다는 뜻이다. 속도를 agent가 알아내기 위해서는 여러 프레임이 필요한데 이는 flickering frame과 맞지 않는다. Convolution filter을 관찰한 결과 velocity의 예측이 conv layer위에서 일어나는 것을 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3b0hz/btsb5kMthDP/bT3SQ74EqZ9VTKhNnd92L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3b0hz/btsb5kMthDP/bT3SQ74EqZ9VTKhNnd92L1/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1507.06527.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3b0hz/btsb5kMthDP/bT3SQ74EqZ9VTKhNnd92L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3b0hz%2Fbtsb5kMthDP%2FbT3SQ74EqZ9VTKhNnd92L1%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;488&quot; height=&quot;291&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;291&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1507.06527.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 DRQN은 single frame이 입력으로 주어져도 성능을 잘 내는 것을 볼 수 있는데 이는 convolution의 영향이 아닌 LSTM의 영향이라고 볼 수 있다. RNN의 특성이 velocity detection을 도와주는 것이다. 이는 frame-stacking을 대체할 method가 LSTM이라고 볼 수 있다.&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;Evaluation on Standard Atari Games / MDP to POMDP Generalization&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;531&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T3deP/btsbVdAw2Eg/xJtYZqA2w4g8xHGdv2UkW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T3deP/btsbVdAw2Eg/xJtYZqA2w4g8xHGdv2UkW1/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1507.06527.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T3deP/btsbVdAw2Eg/xJtYZqA2w4g8xHGdv2UkW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT3deP%2FbtsbVdAw2Eg%2FxJtYZqA2w4g8xHGdv2UkW1%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;531&quot; height=&quot;368&quot; data-origin-width=&quot;531&quot; data-origin-height=&quot;368&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1507.06527.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실험 결과를 보면 평범한 4 frame stack환경에서는 DRQN과 DQN의 성능 차이가 크게 나지 않는다. DQN이 조금 더 MDP상황에서는 좋은 성능을 내는 것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;367&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cN9IeI/btsbSE0hdbY/Q8ktBOd9wPB0DQZ5fHNuLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cN9IeI/btsbSE0hdbY/Q8ktBOd9wPB0DQZ5fHNuLk/img.png&quot; data-alt=&quot;https://arxiv.org/pdf/1507.06527.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cN9IeI/btsbSE0hdbY/Q8ktBOd9wPB0DQZ5fHNuLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcN9IeI%2FbtsbSE0hdbY%2FQ8ktBOd9wPB0DQZ5fHNuLk%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;453&quot; height=&quot;367&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;367&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://arxiv.org/pdf/1507.06527.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, MDP로 training을 시키고 POMDP로 evaluation을 한다면 이야기가 달라진다. 바뀌는 observable probablity에 때라 DRQN이 이 상황에서는 DQN보다 성능 저하가 줄어들었다. 이는 즉 POMDP상활일 때 DRQN이 더 robust 하게 작동한다는 것을 보여준다.&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;Discussion and Conclusion&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 DQN을 변형하여 fully connected layer 대신에 LSTM을 사용하여 POMDP상황에서 더 좋은 성능을 내는 모델을 만들었다. 또한 single frame만으로도 필요한 속도 정보를 얻을 수 있다. Observability에 비례하는 성능을 DRQN이 보여주었고 MDP로 학습하여도 POMDP로 generalize 가능하다. 하지만 MDP상황에서는 어떠한 성능 향상이나 장점이 없다.&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;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>Deep Recurrent Q-Learning for Partially Observable MDPs</category>
      <category>DRQN</category>
      <category>리뷰</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/40</guid>
      <comments>https://limepencil.tistory.com/40#entry40comment</comments>
      <pubDate>Sun, 23 Apr 2023 00:53:30 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Human-level Control through Deep Reinforcement Learning (DQN)</title>
      <link>https://limepencil.tistory.com/39</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.nature.com/articles/nature14236&quot;&gt;Human-level control through deep reinforcement learning | Nature&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 Nature지에 발표된 DQN관련된 논문을 리뷰해보고자 한다. Playing Atari with Deep Reinforcement Learning과 거의 같은 저자들이 작성을 했는데 이는 그전 논문에서 여러 가지 실험이 추가된 것이다. 그래서 DQN에 관한 것을 알고 싶다면 밑에 있는 링크를 타고 들어가 읽으면 된다. 이번 리뷰에서는 추가된 실험들만 다루겠다.&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;a href=&quot;https://limepencil.tistory.com/38&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN) &amp;mdash; LimePencil's Log (tistory.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1680140068407&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&quot; data-og-description=&quot;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&quot; data-og-host=&quot;limepencil.tistory.com&quot; data-og-source-url=&quot;https://limepencil.tistory.com/38&quot; data-og-url=&quot;https://limepencil.tistory.com/38&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/swVo6/hyR5mjbM59/kv3OcMvJiyLFsohbl0qWGk/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/S0vkb/hyR6GmNvmN/AKOSqbsN2ty2E3qw2SuwAK/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/yTM0Q/hyR5pNI9GU/u0OvxFjdq5ypJXpsylPLl0/img.png?width=1171&amp;amp;height=513&amp;amp;face=0_0_1171_513&quot;&gt;&lt;a href=&quot;https://limepencil.tistory.com/38&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://limepencil.tistory.com/38&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/swVo6/hyR5mjbM59/kv3OcMvJiyLFsohbl0qWGk/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/S0vkb/hyR6GmNvmN/AKOSqbsN2ty2E3qw2SuwAK/img.png?width=800&amp;amp;height=363&amp;amp;face=0_0_800_363,https://scrap.kakaocdn.net/dn/yTM0Q/hyR5pNI9GU/u0OvxFjdq5ypJXpsylPLl0/img.png?width=1171&amp;amp;height=513&amp;amp;face=0_0_1171_513');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;limepencil.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;바뀐 점&lt;/h3&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;b&gt;게임의 개수&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;1205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzkKGm/btr6OnaYcEO/E8CFMeOOk8xPvX6vz5YBG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzkKGm/btr6OnaYcEO/E8CFMeOOk8xPvX6vz5YBG0/img.png&quot; data-alt=&quot;https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzkKGm/btr6OnaYcEO/E8CFMeOOk8xPvX6vz5YBG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzkKGm%2Fbtr6OnaYcEO%2FE8CFMeOOk8xPvX6vz5YBG0%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;501&quot; height=&quot;628&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;1205&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Our DQN method outperforms the best existing reinforcement learning methods on 43 of the games without incorporating any of the additional prior knowledge about Atari 2600 games used by other approaches (for example, refs 12, 15). Furthermore, our DQN agent performed at a level that was comparable to that of a pro fessional human games tester across the set of 49 games, achieving more than 75% of the human score on more than half of the games.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임의 개수가 그 전의 7개에 비해서 49개로 늘었다. 이는 genaralization성능을 더욱더 보여주며 다양한 환경에서 DQN이 잘 작동한다는 것을 보여준다. 또한 절반정도의 게임에서 인간의 75% 이상의 성능을 보여줬다.&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;정규화된 성능은 다음 수식을 통해 계산이 된다. $$\text {normalized performance} =&amp;nbsp; 100 \times \frac {\text {DQN score} - \text {random play score}}{\text{human score} - \text{random play score}}$$&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;학습된 표현 분석&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhFtCp/btr6JptWkZf/q862TICj4Agfq1icdGlLr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhFtCp/btr6JptWkZf/q862TICj4Agfq1icdGlLr1/img.png&quot; data-alt=&quot;https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhFtCp/btr6JptWkZf/q862TICj4Agfq1icdGlLr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhFtCp%2Fbtr6JptWkZf%2Fq862TICj4Agfq1icdGlLr1%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;710&quot; height=&quot;544&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;We next examined the representations learned by DQN that underpinned the successful performance of the agent in the context of the game Space Invaders, by using a technique developed for the visual ization of high-dimensional data called &amp;lsquo;t-SNE&amp;rsquo;.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 높은 차원의 데이터를 2차원에 축소해서 보여주는 기법인 t-SNE를 사용해서 분석을 하였다. 예상대로 비슷한 state를 가진 DQN representation을 서로 가까이 mapping 하였다. 또한, t-SNE embedding에서 다른 모양의 state지만 비슷한 expected reward를 가진 점들도 가까이 mapping하였다. 이는 DQN이 높은 차원의 데이터인 픽셀데이터를 통해 정확하게 표현을 학습하고 있다는 것을 보여준다.&amp;nbsp;인간과 agent의 데이터를 두 개 다 넣었을 때에도 t-SNE에서 확인을 하면 비슷한 위치에 mapping이 되어 자신이 학습한 policy가 아니더라도 generalization성능을 가지고 있다는 것을 보여준다.&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;b&gt;문제점&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Nevertheless, games demandingmore temporally extended planning strategies still constitute a major chal lengefor all existing agents including DQN (for example, Montezuma&amp;rsquo;s Revenge).&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;long-term planning이 필요한 게임은 아직은 어려워하는 모습을 보여준다. 하지만 밑에 있는 게임처럼 옆에 있는 블록만 깨서 높은 점수를 얻는 방식의 플레이도 가능하다는 것을 보여줬다. 즉, 어느 정도의 long-term planning은 가능하다.&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;a href=&quot;https://www.youtube.com/watch?v=TmPfTpjtdgg&amp;amp;ab_channel=DeepMind&quot;&gt;DQN Breakout - YouTube&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=TmPfTpjtdgg&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cuRGxF/hyR6HTArWn/c30bSfR84koRM3LWBChSek/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/TmPfTpjtdgg&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>DQN</category>
      <category>Human-level Control through Deep Reinforcement Learning</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/39</guid>
      <comments>https://limepencil.tistory.com/39#entry39comment</comments>
      <pubDate>Thu, 30 Mar 2023 10:39:29 +0900</pubDate>
    </item>
    <item>
      <title>[논문 리뷰] Playing Atari with Deep Reinforcement Learning (DQN)</title>
      <link>https://limepencil.tistory.com/38</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이제부터 이 블로그에 논문을 하나씩 읽으면서 리뷰를 해보려고 한다. 아마 분야마다 시간을 순서대로 큰 영향을 미친 논문을 읽을 것 같다. 이번 논문은 강화학습에 DL을 적용한 첫 번째 성공적인 연구인 Playing Atari with Deep Reinforcement Learning을 읽어보려고 한다. 코드 구현은 다른 글로 해보겠다.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://arxiv.org/abs/1312.5602&quot; target=&quot;_self&quot;&gt;&lt;span&gt;[1312.5602] Playing Atari with Deep Reinforcement Learning (arxiv.org)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;Playing Atari with Deep Reinforcement Learning&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;We present the first deep learning model to successfully learn control policies directly from high-dimensional sensory input using reinforcement learning. The model is a convolutional neural network, trained with a variant of Q-learning, whose input is raw&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/1312.5602&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fd0Bh/hyRZerVmHr/wzriaxDyT5S2Vt3usr8rVk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/cK99yZ/hyR0w5yvPV/ukcMMHt9m3NQxu6mbNmvi1/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot; data-og-url=&quot;https://arxiv.org/abs/1312.5602v1&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/1312.5602v1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/1312.5602&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fd0Bh/hyRZerVmHr/wzriaxDyT5S2Vt3usr8rVk/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/cK99yZ/hyR0w5yvPV/ukcMMHt9m3NQxu6mbNmvi1/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Playing Atari with Deep Reinforcement Learning&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;We present the first deep learning model to successfully learn control policies directly from high-dimensional sensory input using reinforcement learning. The model is a convolutional neural network, trained with a variant of Q-learning, whose input is raw&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Abstract&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;The model is a convolutional neural network, trained with a variant of Q-learning.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 배경지식이 되는 두 개의 아주 중요한 term이 나온다. 사실 이 두 개의 단어가 이 논문의 핵심이라고 생각해도 된다. 이 두 개에 대해서는 다른 글로 &lt;s&gt;아마&lt;/s&gt; 다루겠지만 여기서 잠깐 설명하고 가겠다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byqg4Y/btr4TKku7LE/Vk0yFugIFrfuOZuYWulKt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byqg4Y/btr4TKku7LE/Vk0yFugIFrfuOZuYWulKt0/img.png&quot; data-alt=&quot;https://stanford.edu/~shervine/teaching/cs-230/cheatsheet-convolutional-neural-networks&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byqg4Y/btr4TKku7LE/Vk0yFugIFrfuOZuYWulKt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbyqg4Y%2Fbtr4TKku7LE%2FVk0yFugIFrfuOZuYWulKt0%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;545&quot; height=&quot;248&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://stanford.edu/~shervine/teaching/cs-230/cheatsheet-convolutional-neural-networks&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;CNN(Convolutional Neural Network)이란 이미지처리를 위한 신경망인데, 위치 관계를 잃어버리는 fully-connected neural network와 달리 공간적 관계를 감지할 수 있기 때문에 더 효과적이다. 필터를 픽셀 위로 움직여서 feature map을 만드는데, 이 필터만 학습을 시키면 된다. 그리고 필터 외에도 보통 pooling layer이 있는데 차원을 낮추어주는 역할을 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFz9Tc/btr41JTwjO2/Sn13HA8225n5O6xUdi9wC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFz9Tc/btr41JTwjO2/Sn13HA8225n5O6xUdi9wC1/img.png&quot; data-alt=&quot;https://blog.floydhub.com/an-introduction-to-q-learning-reinforcement-learning/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFz9Tc/btr41JTwjO2/Sn13HA8225n5O6xUdi9wC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFz9Tc%2Fbtr41JTwjO2%2FSn13HA8225n5O6xUdi9wC1%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;431&quot; height=&quot;271&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://blog.floydhub.com/an-introduction-to-q-learning-reinforcement-learning/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Q-learning이란 강화학습 알고리즘의 한 종류로, 최적의 policy를 학습하는 방법이다. 모든 단계를 거쳤을 때 받는 보상을 최적화하는 것을 목표로 한다. 각각의 action에 Q(quality) 값을 부여해서 더 좋은 행동을 취하는 방식이다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;We apply our method to seven Atari 2600 games from the Arcade Learning Environment, with no adjustment of the architecture or learning algorithm. We find that it outperforms all previous approaches on six of the games and surpasses a human expert on three of them.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이 논문의 결과가 인간을 뛰어넘는 성능을 보여줄 수 있다는 결과를 내었다고 하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Introduction&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Most successful RL applications that operate on these domains have relied on hand-crafted features combined with linear value functions or policy representations. Clearly, the performance of such systems heavily relies on the quality of the feature representation.&lt;br /&gt;&lt;br /&gt;Recent advances in deep learning have made it possible to extract high-level features from raw sen sory data, leading to breakthroughs in computer vision and speech recognition.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이전의 RL은 인간이 직접 만든 feature로 작동했기 때문에 이 feature의 quality에 따라 성능이 좌우되었다. Object detection 같은 분야도 처음에는 hand-crafted방식이었지만 현재는 DL을 사용하는 것을 보면, RL에서도 충분히 가능한 일이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WMYPP/btr415oRbkf/WAFZppFlCuA6hc2DnCVu4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WMYPP/btr415oRbkf/WAFZppFlCuA6hc2DnCVu4K/img.png&quot; data-alt=&quot;[Handcrafted face recognition] https://www.researchgate.net/figure/An-example-of-traditional-handcrafted-Haar-features-20_fig3_335158836&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WMYPP/btr415oRbkf/WAFZppFlCuA6hc2DnCVu4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWMYPP%2Fbtr415oRbkf%2FWAFZppFlCuA6hc2DnCVu4K%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;324&quot; height=&quot;324&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[Handcrafted face recognition] https://www.researchgate.net/figure/An-example-of-traditional-handcrafted-Haar-features-20_fig3_335158836&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;However reinforcement learning presents several challenges from a deep learning perspective.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 논문에서는 DL을 RL에 바로 적용하기에는 문제가 있다고 하는데 이는&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DL은 보통 많은 labeled 데이터가 필요하지만 RL은 reward 같은 scalar, sparse, noisy, and delayed 한 metric에 따라 학습한다. 즉 action과 reward가 엄청 긴 시간 사이를 지나 연관이 있을 수 있다.&lt;/li&gt;
&lt;li&gt;DL에서는 데이터들이 independent 하지만 RL에서는 서로 연관이 되어있다.&lt;/li&gt;
&lt;li&gt;RL에서는 데이터들이 agent가 학습하면서 바뀐다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이 논문에서는 이를 해결할 방법으로 CNN과 experience replay mechanism을 내세운다. 이에 대한 설명은 뒤에서 하겠다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Our goal is to create a single neural network agent that is able to successfully learn to play as many of the games as possible. The network was not pro vided with any game-specific information or hand-designed visual features, and was not privy to the internal state of the emulator; it learned from nothing but the video input.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;하나의 네트워크로 다양한 게임을 할 수 있게 한다는 것은 환경에 관계없이 학습을 할 수 있다는 것이다. 이를 보여주기 위해 DeepMind 팀은 hyperparameter를 고정을 시켜 학습을 시켰다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Background&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;The emulator&amp;rsquo;s internal state is not observed by the agent; instead it observes an image $x_t &amp;isin; R^d$ from the emulator, which is a vector of raw pixel values representing the current screen.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;agent는 스크린에 있는 픽셀 값만 입력으로 받고 다른 internal 한 정보를 받지 않는다. 또한 모든 sequence는 유한하기 때문에 MDP(Markov Decision Process)가 적용이 된다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;MDP를 이해하기 위해서는 Markov Property를 이해해야 한다. Markov Property는 한마디로 미래는 현재가 주어졌을 때 독립적이라는 것이다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;즉, $P [S_{t+1}|S_t]=P [S_{t+1}|S_1,..., S_t]$가 성립한다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이 말의 뜻은 $S_t$를 알면 $S_{t+1}$을 찾기 위해 과거의 정보가 필요 없다는 뜻이다. 즉 memory-efficient 하다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이제 Markov Decision Process라는 것은 state, action, state transition property, reward function, 그리고 discount factor들의 요소가 있는 것의 정의이다. 보통의 RL은 이것들을 포함하고 있기 때문에 알고리즘들을 적용할 수 있다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이때 이제 $Q(s, a)$라는 $Q$함수를 정의하고 최적의 함수는 $Q^*(s, a)=\max_\pi \mathbb {E}[R_t|s_t=s, a_t=a,\pi]$로 된다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;여기에서 Bellman equation을 사용해서 최적의 Q함수를 찾는 strategy를 구할 수 있는데 이는 $Q^*(s, a)=\mathbb {E}_{s'\sim \epsilon}[r+\gamma \max Q^*(s', a')|s, a]$이다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이 value iteration algorithm을 쓰면 $Q_i \rightarrow Q^* $ as $i \rightarrow \infty$ 에 최적의 함수로 수렴한다는 게 보장이 된다. 하지만, 이 방법을 쓰면 각 sequence마다 측정해야 하기 때문에 function approximator를 사용해서 action-value function을 근사한다 $Q(s, a;\theta) \approx Q^*(s, a)$. 이 논문에서는 non-linear 한 방식으로 neural-network를 사용한다. 이를 Q-network라고 부르는데&lt;br /&gt;$$L_i(\theta_i) = \mathbb {E}_{s, a\sim \rho(\cdot)}[(y_i-Q(s, a;\theta_i))^2]$$&lt;br /&gt;$$\text {where}$$&lt;br /&gt;$$y_i =\mathbb {E}_{s'\sim \mathcal {E}}[r+\gamma \max Q^*(s', a';\theta_{i-1})|s, a]$$&amp;nbsp; 이 loss function을 최소화하는 것으로 구할 수 있다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;Supervised learning과는 다르게 $y_i$인 target은 $\theta_{i-1}$의 영향을 받음으로써 학습 데이터 자체가 학습 시작 전에 정해진 것이 아니라 학습을 하면서 바뀐다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;위의 손실함수를 미분해서 복잡하게 구할 수 있지만, SGD(Stochastsic Gradient Descent)를 통해서 최적화하는 게 computationally expendient 하다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;이 알고리즘은 model-free 하고($\mathcal {E}$의 estimate을 학습하는 것보다 그것에서 나온 sample만으로도 학습한다) off-policy 하다($a=\max_a Q(s, a;\theta)$ 의 그리디 전략으로만 학습하고 $\epsilon$-greedy 전략으로 충분한 state space를 탐색한다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Related Work&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;312&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czGqYE/btr41Iu8JsA/6ju0WbLcuD4GLOp7P7pgwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czGqYE/btr41Iu8JsA/6ju0WbLcuD4GLOp7P7pgwK/img.png&quot; data-alt=&quot;http://incompleteideas.net/book/ebook/node108.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czGqYE/btr41Iu8JsA/6ju0WbLcuD4GLOp7P7pgwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczGqYE%2Fbtr41Iu8JsA%2F6ju0WbLcuD4GLOp7P7pgwK%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;312&quot; height=&quot;162&quot; data-origin-width=&quot;312&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;http://incompleteideas.net/book/ebook/node108.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;TD-gammon: 현재의 DQN과 비슷하나 특별한 케이스에서만 작동하고 체스나 바둑 같은 게임에서는 작동하지 않는다. 또한, Q-network는 발산하기가 쉽기 때문에 linear function approximator를 이전에서는 많이 사용했다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;NFQ(Neural Fitted Q-learning): RPROP 알고리즘을 사용해서 Q-network를 업데이트하지만 batch update를 사용함으로써 높은 computational cost를 가지고 있다. 또한 DQN과 다르게 deep autoencoder를 사용해서 이 task의 representation을 먼저 학습하기 때문에 end-to-end RL인 DQN과는 차이가 있다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Deep Reinforcement Learning&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Our goal is to connect a reinforcement learning algorithm to a deep neural network which operates directly on RGB images and efficently process training data by using stochastic gradient updates.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Deepmind 팀은&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;TD-Gammon 같은 online approach보다 experience replay라는 mechanism을 사용해서 $e_t=(s_t, a_t, r_t, s_{t+1})$라는 데이터를 $\mathcal {D} = e_1,... e_N$라는 큐에 저장하는 방식을 채용했다. 이를 실행한 뒤에는 $\epsilon$-greedy라는 방법을 사용해서 state space를 탐색한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;$\epsilon$-greedy를 간단하게 설명하자면 policy가 정한 action을 $1-\epsilon$의 확률로 실행하고 나머지 확률인 $\epsilon$동안에는 랜덤한 action을 실행한다. 이를 통해서 더욱더 다양한 state들을 탐색해 볼 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이 논문에서는 이 알고리즘을&amp;nbsp;&lt;i&gt;Deep Q Learning&lt;/i&gt;이라고 소개하고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Online Q learning보다 DQL이 우수한 이유:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;한 데이터가 여러번의 update에 쓰일 수 있기때문에 데이터적으로 효율적이다.&lt;/li&gt;
&lt;li&gt;연속적인 샘플으로 학습을 하는 것은 데이터간의 상관관계가 크기 때문에 비효율적이다. 랜덤한 데이터를 사용하는게 gradient 업데이트의 편차를 줄여준다. 만약에 연속적인 샘플로 학습을 한다면, 그 연속적인 샘플과 완전히 다른 데이터가 들어올 경우에는 gradient값이 확 튀어서 generalization 성능이 내려간다.&lt;/li&gt;
&lt;li&gt;on-policy로 학습을 하면 현재의 parameter이 샘플에 영향을 주기 때문에 bias된 샘플만 학습이 될 수 있다. 만약에 왼쪽으로 가는 Q 값이 제일 크다면 그 값을 학습한것 때문에 다음에도 왼쪽으로만 가는 feedback loop이 생길 수 있다. 이는 weight값을 무한히 발산하게 만들 수 있는 문제를 일으킬수 있다. 이 논문에서는 off-policy인 experience replay를 사용하면서 parameter의 발산을 막았다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 논문에서는 이 experience replay방법은 각 step의 다른 중요성을 고려하지 않기 때문에 priortized sweeping 같은 방법을 제안한다. 나중에 나오는 논문에서 이것을 사용한다.&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;b&gt;논문에서 사용한 전처리 방법:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Atari게임의 frame은 210 x 160 컬러 픽셀 이미지이다. 이를 그대로 학습에 사용한다면 computationally demanding 하기 때문에 전처리를 거쳐야 한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;grey-scale로 바꾸어서 이미지의 채널을 3에서 1로 줄여준다 (RGB to black and white)&lt;/li&gt;
&lt;li&gt;이미지를 110x84로 downsampling 한다&lt;/li&gt;
&lt;li&gt;게임 화면만 들어올수 있게 84x84로 cropping한다. (이를 하는 이유는 2D Convolution이 정사각형만의 input을 받기 때문에&lt;/li&gt;
&lt;li&gt;최근 4개의 전처리된 프레임을 쌓아서 Q-function의 입력으로 넣어준다&lt;/li&gt;
&lt;/ol&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$를 neural network로 구하는 방법 여러가지가 있다. 첫번째 방법은 image와 action을 신경망에 넣어서 $Q$값을 구하게 하는 방법이다. 이 방법의 문제는 각각의 action마다 forward pass를 실행해야하기에 $n$개의 가능한 action이 있다면 $O(n)$번이나 반복해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법보다 더 효율적인 방법이 있는데, 이는 신경망에 마지막 출력 노드들 하나당 가능한 하나의 action으로 정의하고 그 노드에 나온 출력 값이 action에 따른 $Q$값에 대응한다. 이는 첫번째 방법보다 $O(1)$이라는 시복도로 더 효율적이고 action space가 넓어질수록 효과적이다.&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;b&gt;모델 아키텍쳐 (Deep Q Network):&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;84x84x4&lt;/li&gt;
&lt;li&gt;8x8x16 (Stride 4)&lt;/li&gt;
&lt;li&gt;ReLU&lt;/li&gt;
&lt;li&gt;4x4x32 (Stride 2)&lt;/li&gt;
&lt;li&gt;ReLU&lt;/li&gt;
&lt;li&gt;layer with 256 hidden node&lt;/li&gt;
&lt;li&gt;output node corresponding to number of valid actions&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Experiments&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7개의 게임에서 실험을 하였고 각 게임마다 점수의 magnitude가 다르기 때문에&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;positive reward: +1&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;negative reward: -1&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;으로 설정하여 게임마다 같은 hyperparameter을 사용할 수 있게 하였다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Hyperparameters&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Optimizer: RMSProp&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Batchsize: 32&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;$\epsilon$-greedy decay: anealling linearly from 1 to 0.1 over the timestep of 1,000,000&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;$k$, the frame skipping constant: 4 for most games (performing action every $k$th frame)&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;b&gt;Model Performance Evaluation&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;agent가 한 에피소드당 모으는 최대의 reward (noisy)&lt;/li&gt;
&lt;li&gt;최대 평균 $Q$값 (smooth)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;학습시에 value function이 바뀌는 것을 볼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다른 연구들과의 비교&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z3b5e/btr5rdHIJd0/45WYH3wcZIuGGKSEq6nT80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z3b5e/btr5rdHIJd0/45WYH3wcZIuGGKSEq6nT80/img.png&quot; data-alt=&quot;Comparing with other RL algorithm&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z3b5e/btr5rdHIJd0/45WYH3wcZIuGGKSEq6nT80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz3b5e%2Fbtr5rdHIJd0%2F45WYH3wcZIuGGKSEq6nT80%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;1171&quot; height=&quot;513&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Comparing with other RL algorithm&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;This paper introduced a new deep learning model for reinforcement learning, and demonstrated its ability to master difficult control policies for Atari 2600 computer games, using only raw pixels as input. We also presented a variant of online Q-learning that combines stochastic minibatch up- dates with experience replay memory to ease the training of deep networks for RL. Our approach gave state-of-the-art results in six of the seven games it was tested on, with no adjustment of the architecture or hyperparameters.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문에서는 딥러닝 모델을 사용하여 강화학습을 진행하는 연구를 진행하였다. Experience replay memory를 사용하여 Q-learning의 변형인 DQN을 만들었다. 7개의 Atari 게임 중에서 6개의 게임에서 state-of-the-art를 달성했다.&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 리뷰/Reinforcement Learning</category>
      <category>DQN</category>
      <category>Playing Atari with Deep Reinforcement Learning</category>
      <category>리뷰</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/38</guid>
      <comments>https://limepencil.tistory.com/38#entry38comment</comments>
      <pubDate>Thu, 23 Mar 2023 14:49:39 +0900</pubDate>
    </item>
    <item>
      <title>2023년도 공부 계획</title>
      <link>https://limepencil.tistory.com/37</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;학기가 시작하고 2주가 지났다. 부캠이 끝난 이후에 코딩과 공부를 조금 멀리 했는데, 대충 1달 정도 쉰 것 같다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;2023년도에는 다양한 경험과 공부를 하면서 지내고 싶은데, 이에 대한 계획을 조금 써보자 한다.&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Problem Solving과 Competitive Programming 실력 늘리기&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;대학 입시와 부스트캠프 때문에 문제풀이에 소홀한 감이 없지않아 있는데, 이번 연도에는 확실한 목표를 정해보자 한다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;Solved.ac: 다이아 4~5정도&lt;br /&gt;&amp;nbsp;&lt;br /&gt;Codeforces: 블루&lt;br /&gt;또는&lt;br /&gt;AtCoder: 민트 상위&lt;br /&gt;&amp;nbsp;&lt;br /&gt;아무래도 현재 파이썬의 한계를 느꼈기 때문에 C++로 1학기에 갈아타서 공부해볼까 한다. 그렇게 한다면 2학기에 있을 자료구조 수업에도 도움이 될 것 같다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;인공지능 공부&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;PoolC에 가입한 덕분에 이제 같이 스터디나 세미나를 들을 수 있게 되었다. 먼저 강화학습을 공부하고, 다양한 대회나 공모전을 팀을 이루어서 나가고 싶다. 이렇게 하면 같이 포폴을 쌓아서 나중에 도움이 될 수 있을 것 같다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;현재 도서관에 괜찮은 인공지능 공부 책이 많은데 이를 좀 공부해서 블로그에 포스팅을 하는 것도 목표이다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;개발 공부&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;아무래도 인공지능 엔지니어나 실제로 프로덕트를 배포하는 직종이라면 백엔드와 밀접한 연관이 있기 때문에 이를 더 공부하고 싶다. PoolC에서 대형 프로젝트에 들어가서 공부하거나 현재 조금 다뤄본 FastAPI를 더 공부할까 생각 중이다. 아키텍처 디자인이나 실제 현업에서 어떤 식으로 서비스를 만드는지를 배우는 게 목표이다.&lt;br /&gt;&lt;br /&gt;가능하다면 오픈소스 기여를 배우고 하고 싶다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;학부연구생/인턴&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이번 여름이나 겨울에는 연대나 한양대에서 연구 인턴을 하거나 회사에 가서 인턴을 하고 싶다. 아무래도 전자가 상대적으로 쉬울 수 있지만 일단을 둘다를 노려보고자 한다. 이를 위해서 깃허브 정리, 포폴 정리, CV 작성이 필요할 듯하다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;개인 프로젝트&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이 모든 것을 하면서 개인 프로젝트 하나를 하는 것이 목표이다. 부스트캠프에서 대충 전반적인 서비스를 다루어 보았기 때문에 웬만한 것은 인터넷을 따라보면서 만들 수 있는데, 이게 무엇이 될지는 아직은 모르겠다. 1년짜리 프로젝트가 될 수도 있고 아니면 더 길어질 수도 있다. 부스트캠프 마지막 프로젝트처럼 기록도 하고 작은 것부터 완성도 있게 만들어서 계속 버전을 늘려 나가고 싶다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;이 모든 것을 이번 연도에 할 수 있다고 생각하지는 않으나 열심히 노력한다면 몇 개는 이룰 수 있다고 생각한다. 앞으로 파이팅 하기를.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;*수정: 카이스트에 붙으면서 계획을 좀 수정해야겠다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 석사는 해야할것 같고 그렇다면 연구랑 논문읽기를 더 집중해야겠다.&lt;/p&gt;</description>
      <category>잡다한 것들</category>
      <category>공부계획</category>
      <category>프로그래밍</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/37</guid>
      <comments>https://limepencil.tistory.com/37#entry37comment</comments>
      <pubDate>Thu, 16 Mar 2023 14:24:08 +0900</pubDate>
    </item>
    <item>
      <title>부스트캠프 AI Tech 4기를 마치며...   feat. 부캠 참가를 고려하시는 분들을 위해</title>
      <link>https://limepencil.tistory.com/36</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;561&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvM8A5/btr1KPK7UTZ/N0tvFrjjZEmAzEaesvrxJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvM8A5/btr1KPK7UTZ/N0tvFrjjZEmAzEaesvrxJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvM8A5/btr1KPK7UTZ/N0tvFrjjZEmAzEaesvrxJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvM8A5%2Fbtr1KPK7UTZ%2FN0tvFrjjZEmAzEaesvrxJK%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;552&quot; height=&quot;242&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;561&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부스트캠프 AI Tech 4기가 2월 14일부로 끝이 났다. CV 트랙으로 들어왔고, 3개의 레벨과 2개의 팀을 지나 수료를 했다. 부캠에 대해 조금만 서술하자면 현재 대학민국에 존재하는 인공지능 전문가 양성 프로그램 중에 강사나 커리큘럼으로 봐도 1등이라고 생각한다. 네이버라는 대기업이 주는 신뢰감과 전문적인 수업들이 실제 현업과 유사하게 이루어지기 때문에 상당히 좋았다고 생각한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;330&quot; data-origin-height=&quot;330&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCt5sS/btr133fOqqW/YkiEkCgvm8M0k2ep7olk51/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCt5sS/btr133fOqqW/YkiEkCgvm8M0k2ep7olk51/img.jpg&quot; data-alt=&quot;내 실험을 도와준 값비싼 친구 V100&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCt5sS/btr133fOqqW/YkiEkCgvm8M0k2ep7olk51/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCt5sS%2Fbtr133fOqqW%2FYkiEkCgvm8M0k2ep7olk51%2Fimg.jpg&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;330&quot; height=&quot;330&quot; data-origin-width=&quot;330&quot; data-origin-height=&quot;330&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내 실험을 도와준 값비싼 친구 V100&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐니 뭐니 해도 사실상 제일 좋았던 건 1인 1 고성능 GPU서버를 제공한다는 것이었다. V100 32Gb GPU를 한 2~3달 정도 제공했는데 저장공간이 조금 적은 것 빼고 배우는 학생에 입장에서는 최상의 장비라고 생각한다. 들어가 있던 Xeon CPU도 좋았고 램도 저장공간만큼 있었다. 개인 서버가 있다 보니 24시간 풀가동 하면서 전기세와 소음 걱정도 없었고, 리눅스 서버다 보니 다양한 커맨드를 연습해 보기도 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w1jOP/btr115kwa6b/oezUrKCamr0z1rbfmq3Yqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w1jOP/btr115kwa6b/oezUrKCamr0z1rbfmq3Yqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w1jOP/btr115kwa6b/oezUrKCamr0z1rbfmq3Yqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw1jOP%2Fbtr115kwa6b%2FoezUrKCamr0z1rbfmq3Yqk%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;152&quot; height=&quot;167&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1315&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 부캠을 하면서 느꼈던 것은 인공지능과 파이썬에 대한 지식이 없으면 들어와서 따라오기가 상당히 힘들다는 것이다. 비전공자 분들도 많이 계시지만 초반에 상당히 당황하시던 반응이었던 게 기억이 난다. 백준 알고리즘 골드 문제들을 파이썬으로 풀 수 있다면 충분하다고 생각한다. 1주 차에 거의 대학 전공 과정을 속성으로 인공지능의 처음부터 끝까지 가르쳤고, 과제들도 만만하지 않은 수준이었다. 2주 차부터는 슬슬 어려워지는데, 사실 PyTorch를 조금 다루어 보고 부캠에 들어오는 게 따라오기 좋다고 생각한다. 처음에 수학과 수식에 머리가 띵해지는데 사실 이해한다면 좋지만 이론은 사실 응용에는 큰 영향이 없기 때문에 괜찮다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부캠은 3개의 레벨로 나누어져 있었는데:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;인공지능에 대한 전반적인 이론 및 코드 작성법 (8주)&lt;/li&gt;
&lt;li&gt;각자 분야 심화 및 대회 (8주)&lt;/li&gt;
&lt;li&gt;최종 프로젝트 및 Product Serving (4주)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CV트랙으로 참가한 필자의 부캠에 대한 생각을 쓰자면, 일단 level 2 팀원을 모을 때 신중해야 한다는 것이다. 소통을 잘할 수 있고 어느 정도 혼자서 일을 할 수 있는 사람이 같은 팀원이어야 좋다. 같은 최종프로젝트 주제로만 모으다 보면 팀원과 불화가 생길 수 있고, 친해지기가 어려울 수 있다. 사실 베스트는 level 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;총 4개의 대회를 진행했는데, 등수를 올리는 데에만 집중해서 많은 것을 놓친 느낌이었다. 다양한 것을 시도해 보고 논문도 읽으면서 구현하는 게 제일 좋은데, 이런 것을 하지 못한 게 아쉽다. 이 글을 읽는 부스트캠퍼가 있다면 등수나 성적에 연연하지 말고 다양한 것을 시도해 봤으면 좋겠다. 깃허브와 Jira 같은 협업 툴을 적극적으로 사용하는 것이 좋다.&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;/p&gt;</description>
      <category>잡다한 것들/부스트캠프 AI Tech 4기</category>
      <category>부스트캠프AITech</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/36</guid>
      <comments>https://limepencil.tistory.com/36#entry36comment</comments>
      <pubDate>Wed, 1 Mar 2023 17:29:35 +0900</pubDate>
    </item>
    <item>
      <title>리액트 공부 정리</title>
      <link>https://limepencil.tistory.com/35</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들: &lt;a href=&quot;https://ko.reactjs.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/react-%2320232a.svg?style=for-the-badge&amp;amp;logo=react&amp;amp;logoColor=%2361DAFB&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&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;React - 생활코딩&lt;/h3&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;p data-ke-size=&quot;size16&quot;&gt;src/index.js 에서 쓰여 있는 데로 npm start가 작동됨&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;npm run build를 실행하면 빌드가 되고 npx serve -s build를 그다음에 실행하면 배포용 웹이 실행이 된다&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;/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;prop: 우리가 만든 태그의 속성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- kwargs느낌이라고 생각하면 될듯하다&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;속성을 출력 하려면 중괄호 안에 넣어줘야 제대로 된다. 중괄호가 없으면 object가 아니라 string이 전달됨&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;자동으로 react에서 생성한 값들은 key라는 prop이 있어야지 성능이 올라간다&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를 사용해서 이미 정의된 변수의 값을 변화시켜 페이지에 반영을 할 수 있다.&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;primitive data type이 아니면 ...으로 복사 후 setValue하기&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;prop의로 받은 값은 바꾸지 못하기 때문에 update할 때는 state로 변환을 해준다&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;리액트를 다루는 기술&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈 태그는 그룹핑 용으로 사용 가능&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;lt;Fragment&amp;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;undefined를 return하면 오류가 생기기 때문에 조심하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 하지만 jsx안에서 undefined를 rendering하는 것은 가능하다.&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;리액트에서 DOM 요소에 스타일을 적용할 때는 문자열 형태로 넣는 것이 아니라 객체 형태로 넣어 주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- camelCase 적용&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;jsx에서 css 클래스를 사용할 때는 class attribute 대신에 className을 사용한다.&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;{/*&amp;nbsp;&amp;nbsp;*/}를 사용하면 페이지에 보이지 않지만 //이나 /*을 사용하면 그대로 나타나게 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;클래스형 컴포넌트와 함수형 컴포넌트의 차이&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스형:&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;state 바로 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React에서 권장함&lt;/li&gt;
&lt;li&gt;선언하기가 간단하다&lt;/li&gt;
&lt;li&gt;메모리를 적게 사용한다&lt;/li&gt;
&lt;li&gt;state와 lifecycle API 사용 불가
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Hook으로 해결 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://opentutorials.org/course/4900&quot;&gt;React - 생활코딩 (opentutorials.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1674631607811&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;university&quot; data-og-title=&quot;React  - 생활코딩&quot; data-og-description=&quot;리액트 입문자를 위한 수업입니다.&amp;nbsp; 기본 문법과 핵심 개념을 익힐 수 있습니다.&amp;nbsp; 만들게 될 것 앱 : https://egoing.github.io/react-2022-tutorial-src/ 소스코드 : https://github.com/egoing/react-2022-tutorial-src 알게 &quot; data-og-host=&quot;opentutorials.org&quot; data-og-source-url=&quot;https://opentutorials.org/course/4900&quot; data-og-url=&quot;https://opentutorials.org/course/4900&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Ct24A/hyRoJL4jke/OrdnGvL1fC1kLVEj0Ks2H1/img.jpg?width=458&amp;amp;height=578&amp;amp;face=0_0_458_578&quot;&gt;&lt;a href=&quot;https://opentutorials.org/course/4900&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://opentutorials.org/course/4900&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Ct24A/hyRoJL4jke/OrdnGvL1fC1kLVEj0Ks2H1/img.jpg?width=458&amp;amp;height=578&amp;amp;face=0_0_458_578');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;React - 생활코딩&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;리액트 입문자를 위한 수업입니다.&amp;nbsp; 기본 문법과 핵심 개념을 익힐 수 있습니다.&amp;nbsp; 만들게 될 것 앱 : https://egoing.github.io/react-2022-tutorial-src/ 소스코드 : https://github.com/egoing/react-2022-tutorial-src 알게&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;opentutorials.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://thebook.io/080203/&quot;&gt;더북(TheBook): 리액트를 다루는 기술 [개정판]&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1674670461641&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;리액트를 다루는 기술 [개정판]&quot; data-og-description=&quot;더북(TheBook): (주)도서출판 길벗에서 제공하는 IT 도서 열람 서비스입니다.&quot; data-og-host=&quot;thebook.io&quot; data-og-source-url=&quot;https://thebook.io/080203/&quot; data-og-url=&quot;https://thebook.io/080203/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://thebook.io/080203/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://thebook.io/080203/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;리액트를 다루는 기술 [개정판]&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;더북(TheBook): (주)도서출판 길벗에서 제공하는 IT 도서 열람 서비스입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;thebook.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web/JavaScript</category>
      <category>React</category>
      <category>리액트</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/35</guid>
      <comments>https://limepencil.tistory.com/35#entry35comment</comments>
      <pubDate>Wed, 25 Jan 2023 16:53:55 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트 공부 정리</title>
      <link>https://limepencil.tistory.com/34</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들: &lt;a href=&quot;https://www.javascript.com/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&amp;amp;logo=javascript&amp;amp;logoColor=%23F7DF1E&quot; alt=&quot;&quot; /&gt;&lt;/a&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;html에 자바스크립트 코드를 작성하고 싶으면 &amp;lt;script&amp;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;&amp;lt;input&amp;gt; 태그에서 on~ attribute는 javascript 코드를 이벤트가 트리거 될 때 실행시켜 준다&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;F12를 눌러 console로 들어가서 javascript 코드를 임의로 실행시킬 수 있다&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;HTML style attribute를 사용하면 css를 적용할 수 있다.&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;&amp;lt;div&amp;gt;: 아무 의미도 없지만 자바스크립트로 그 태그를 제어하고 싶을 때 사용한다. 줄 바꿈이 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;span&amp;gt;: div와 같지만 줄 바꿈이 없음&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;HTML class attribute를 사용하면 한 번에 그 클래스를 가진 태그를 제어할 수 있다. (css앞에 .을 붙인다)&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;HTML id attribute를 사용하면 한번에 그 아이디를 가진 태그를 제어 할 수 있다. (css 앞에 #를 붙인다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- id는 유니크하기 때문에 클래스와 다르게 한 번만 사용해야 한다&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;javascript에서 querySelector으로 지정해서 불러오기 가능&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;querySelectorAll을 쓰면 모든 것을 array로 불러온다&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;/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;this: 자바스크립트에서 자기 자신을 가르키는 변수&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;&amp;lt;script&amp;gt;에서 src를 사용하면 같은 자바스크립트 코드를 다양한 페이지에서 사용할 수 있다 (전체에 동일한 코드 변경 가능)&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;/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;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;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://opentutorials.org/course/3085&quot;&gt;WEB2 - JavaScript - 생활코딩 (opentutorials.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1674399526187&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;university&quot; data-og-title=&quot;WEB2 - JavaScript - 생활코딩&quot; data-og-description=&quot;수업소개 이 수업은 https://opentutorials.org 를 만들어가면서 JavaScript에 대한 지식과 경험을 동시에 채워드리기 위한 목적으로 만들어진 수업입니다.&amp;nbsp; 수업대상 이 수업은 웹 페이지를 사용자와 상&quot; data-og-host=&quot;opentutorials.org&quot; data-og-source-url=&quot;https://opentutorials.org/course/3085&quot; data-og-url=&quot;https://opentutorials.org/course/3085&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dUoQvW/hyRlAJHanW/wJHJ4Bxwl7c3Kkfdfexbq0/img.jpg?width=458&amp;amp;height=579&amp;amp;face=0_0_458_579&quot;&gt;&lt;a href=&quot;https://opentutorials.org/course/3085&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://opentutorials.org/course/3085&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dUoQvW/hyRlAJHanW/wJHJ4Bxwl7c3Kkfdfexbq0/img.jpg?width=458&amp;amp;height=579&amp;amp;face=0_0_458_579');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;WEB2 - JavaScript - 생활코딩&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;수업소개 이 수업은 https://opentutorials.org 를 만들어가면서 JavaScript에 대한 지식과 경험을 동시에 채워드리기 위한 목적으로 만들어진 수업입니다.&amp;nbsp; 수업대상 이 수업은 웹 페이지를 사용자와 상&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;opentutorials.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web/JavaScript</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/34</guid>
      <comments>https://limepencil.tistory.com/34#entry34comment</comments>
      <pubDate>Sun, 22 Jan 2023 23:57:54 +0900</pubDate>
    </item>
    <item>
      <title>HTML 공부정리</title>
      <link>https://limepencil.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들: &lt;a href=&quot;https://ko.wikipedia.org/wiki/HTML5&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&amp;amp;logo=html5&amp;amp;logoColor=white&quot; alt=&quot;HTML5&quot; /&gt;&lt;/a&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;HTML 태그들:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lt;u&amp;gt;: 밑줄&lt;/li&gt;
&lt;li&gt;&amp;lt;strong&amp;gt;: 볼드&lt;/li&gt;
&lt;li&gt;&amp;lt;h1&amp;gt;~&amp;lt;h6&amp;gt;: 제목&lt;/li&gt;
&lt;li&gt;&amp;lt;br&amp;gt;: 줄바꿈(쌍 없음)&lt;/li&gt;
&lt;li&gt;&amp;lt;p&amp;gt;: 단락&lt;/li&gt;
&lt;li&gt;&amp;lt;img&amp;gt;: 이미지 넣기(쌍 없음)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;scr: 이미지의 소스 attribute&lt;/li&gt;
&lt;li&gt;width: 너비 조정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;lt;li&amp;gt;: 리스트&lt;/li&gt;
&lt;li&gt;&amp;lt;ul&amp;gt;: 리스트를 다른 리스트와 구분 시켜주는 parent tag
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;unordered list&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;lt;ol&amp;gt;: 순서가 있는 리스트, 마찬가지로 parent tag
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ordered list&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;lt;title&amp;gt;: 웹페이지의 제목
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;img style=&quot;caret-color: transparent; letter-spacing: 0px;&quot; src=&quot;https://blog.kakaocdn.net/dn/DFmVZ/btrWRcK2HxM/GYXbl8LhF8wN5BUAzgMvA0/img.png&quot; data-origin-width=&quot;285&quot; data-origin-height=&quot;41&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;: utf-8로 해석
&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;/li&gt;
&lt;li&gt;&amp;lt;head&amp;gt;: 본문을 설명하는 태그들의 parent&lt;/li&gt;
&lt;li&gt;&amp;lt;body&amp;gt;: 본문 그 자체인 태그들의 parent&lt;/li&gt;
&lt;li&gt;&amp;lt;html&amp;gt;: head와 body를 감싸는 태그&lt;/li&gt;
&lt;li&gt;&amp;lt;!doctype html&amp;gt;: 이 웹페이지가 html로 만들어 졌다고 문서 제일 위에 쓰는 태그&lt;/li&gt;
&lt;li&gt;&amp;lt;a&amp;gt;: 링크
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;href: HyperText Reference&lt;/li&gt;
&lt;li&gt;target: 어디에서 이 링크를 열건지
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;_blank: 새로운 탭에서 열기&lt;/li&gt;
&lt;li&gt;_self: 현재의 탭에서 열기 (기본값)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Web Server: 요청을 받는 컴퓨터Web Client: 요청을 하는 컴퓨터 (보통은 웹 브라우저)&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Apache&lt;/li&gt;
&lt;li&gt;IIS&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;/ul&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;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://opentutorials.org/course/3084&quot;&gt;WEB1 - HTML &amp;amp; Internet - 생활코딩 (opentutorials.org)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1674196943865&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;university&quot; data-og-title=&quot;WEB1 - HTML &amp;amp; Internet - 생활코딩&quot; data-og-description=&quot;--- 우리는 지금부터 코딩 웹 인터넷 컴퓨터라는 거대한 주제에 대한 탐험을 시작할 거예요. 이 여행을 시작하기에 앞서서 한가지 준비가 필요한데요. 바로 우리들의 상상력입니다. 지금부터 여&quot; data-og-host=&quot;opentutorials.org&quot; data-og-source-url=&quot;https://opentutorials.org/course/3084&quot; data-og-url=&quot;https://opentutorials.org/course/3084&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/AoB0B/hyRlDESbTx/0pBY0MZ2CZ7UCOM4O8I0Sk/img.png?width=640&amp;amp;height=360&amp;amp;face=0_0_640_360,https://scrap.kakaocdn.net/dn/J4pYD/hyRknwQ88D/iKEIgrCuJx4KmMzpvADGxK/img.png?width=640&amp;amp;height=360&amp;amp;face=0_0_640_360,https://scrap.kakaocdn.net/dn/cqGPCg/hyRlqMhUlY/WGWow6pA171faaTjZtyrEk/img.png?width=640&amp;amp;height=360&amp;amp;face=0_0_640_360&quot;&gt;&lt;a href=&quot;https://opentutorials.org/course/3084&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://opentutorials.org/course/3084&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/AoB0B/hyRlDESbTx/0pBY0MZ2CZ7UCOM4O8I0Sk/img.png?width=640&amp;amp;height=360&amp;amp;face=0_0_640_360,https://scrap.kakaocdn.net/dn/J4pYD/hyRknwQ88D/iKEIgrCuJx4KmMzpvADGxK/img.png?width=640&amp;amp;height=360&amp;amp;face=0_0_640_360,https://scrap.kakaocdn.net/dn/cqGPCg/hyRlqMhUlY/WGWow6pA171faaTjZtyrEk/img.png?width=640&amp;amp;height=360&amp;amp;face=0_0_640_360');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;WEB1 - HTML &amp;amp; Internet - 생활코딩&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;--- 우리는 지금부터 코딩 웹 인터넷 컴퓨터라는 거대한 주제에 대한 탐험을 시작할 거예요. 이 여행을 시작하기에 앞서서 한가지 준비가 필요한데요. 바로 우리들의 상상력입니다. 지금부터 여&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;opentutorials.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web/HTML</category>
      <category>html</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/33</guid>
      <comments>https://limepencil.tistory.com/33#entry33comment</comments>
      <pubDate>Fri, 20 Jan 2023 15:49:53 +0900</pubDate>
    </item>
    <item>
      <title>포트폴리오 잘 쓰는 법</title>
      <link>https://limepencil.tistory.com/32</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;업스테이지 이활석 CTO님의 포트폴리오 특강을 정리한 내용이다&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;파일 이름:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 이름에 이름, 회사명, 날짜, 버전을 넣어주면 신뢰도가 늘어난다&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;h3 data-ke-size=&quot;size23&quot;&gt;블로그:&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;문서 요약:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적정한 정보량(3분) 안에 모든 것을 보여주어야함&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;지원 동기 쓰자:&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;이력서 + 포트폴리오:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이력서로 최대한 자신이 한 일을 요약을 하고 포트폴리오를 같이 넣어서 심사하시는 분이 보고 싶으시다면 보게 하는게 좋음&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;h3 data-ke-size=&quot;size23&quot;&gt;자신이 한 일이 드러나야 한다:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논문: 공저자 중에 몇 번째&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대회 수상: 대회명으로는 가늠이 안됨&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;본인의 역할&lt;/li&gt;
&lt;li&gt;캐글이 그나마 낫다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;차별화:&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;회사 맞춤형&lt;/li&gt;
&lt;li&gt;부서 맞춤형&lt;/li&gt;
&lt;li&gt;같은 결과물에 대한 본인만의 해석&lt;/li&gt;
&lt;li&gt;발표 능력, 문서 정리 능력&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>이력서</category>
      <category>포트폴리오</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/32</guid>
      <comments>https://limepencil.tistory.com/32#entry32comment</comments>
      <pubDate>Wed, 11 Jan 2023 16:02:25 +0900</pubDate>
    </item>
    <item>
      <title>부스트캠프 17주차 학습 일지 - Product Serving</title>
      <link>https://limepencil.tistory.com/31</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들:&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://www.python.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/Python-FFD43B?style=for-the-badge&amp;amp;logo=python&amp;amp;logoColor=blue&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://pytorch.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/PyTorch-EE4C2C?style=for-the-badge&amp;amp;logo=PyTorch&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://jupyter.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/jupyter-%23FA0F00.svg?style=for-the-badge&amp;amp;logo=jupyter&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1/10 월&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;We use cloud service so that the server is up 24 hours.&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;Serverless computing: the server is controlled by the cloud by uploading the code to the cloud&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stateless Container: docker image-based server&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Object Storage: can store many types of files&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Database: for web/app&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Data Warehouse: database for data analysis&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;CI: automating build and testing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CD: automating deployment&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;Workflow: the topmost unit that controls GitHub Action&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Job: a combination of steps that can run both in parallel and in order and they can have a dependency on each other&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Step: operation running on the job, able to run shell command and execute an action, and the data is shared across the job&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Action: a collection of step that is reusable&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Runner: server that runs workflow, can be hosted by GitHub or own server&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;Monolithic Architecture: all things are done by one server&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Microservice Architecture(MSA): make different servers do different jobs and communicate by request&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;HTTP(Hyper Text Transfer Protocol): a protocol that needs to be kept in order to exchange information&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;REST API: work by CRUD(Create, Read, Update, Delete)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;client: a platform that requests action&lt;/li&gt;
&lt;li&gt;resource: unique ID resource(URI)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URL(Uniform Resource Locator): location of the resource on the internet&lt;/li&gt;
&lt;li&gt;URI(Uniform Resource Indicator): a string that is used to identify resources
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;URI contains URL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;method: ways to request the server
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GET: 정보를 요청
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;by putting data in the URL and header&lt;/li&gt;
&lt;li&gt;vulnerable because the data is in the URL and head&lt;/li&gt;
&lt;li&gt;able to be cached&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;POST:&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;정보를&lt;/span&gt; 입력
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;submit data to add or modify&lt;/li&gt;
&lt;li&gt;data is not in the URL&lt;/li&gt;
&lt;li&gt;data is in the body&lt;/li&gt;
&lt;li&gt;safer compared to GET&lt;/li&gt;
&lt;li&gt;Not able to be cached
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;need architecture to cache&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PUT:&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;정보를&lt;/span&gt; 업데이트&lt;/li&gt;
&lt;li&gt;PATCH:&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;정보를&lt;/span&gt; 업데이트&lt;/li&gt;
&lt;li&gt;DELETE:&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;정보를&lt;/span&gt; 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP protocol saves the information to a packet when sending or receiving&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;packet: header + body
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;header: address, receiving address, time&lt;/li&gt;
&lt;li&gt;body: actual content that is to be sent&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Status code: how the server reacts to the request&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1xx: got request, continue process&lt;/li&gt;
&lt;li&gt;2xx: got request, executing&lt;/li&gt;
&lt;li&gt;3xx: need more jobs to be completed to complete the request&lt;/li&gt;
&lt;li&gt;4xx: grammar wrong or cannot process request&lt;/li&gt;
&lt;li&gt;5xx: the server failed in regard to the request&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP(Internet Protocol): the address of the PC that is connected to the network&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IPv4 consists of 4 blocks of number&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;can represent $2^{32}$ addresses&lt;/li&gt;
&lt;li&gt;IPv6 released to increase the number&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;127.0.0.1: localhost&lt;/li&gt;
&lt;li&gt;0.0.0.0, 255.255.255.255: broadcast address that communicates with all the devices connected to the local network&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Port: channel that can access the PC&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cannot have duplicate port&lt;/li&gt;
&lt;li&gt;0 to 65535&lt;/li&gt;
&lt;li&gt;0~1024 is set for the communication protocol
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;22: SSH&lt;/li&gt;
&lt;li&gt;80: HTTP&lt;/li&gt;
&lt;li&gt;443: HTTPS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FastAPI: python web framework&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fast, easy, and productive&lt;/li&gt;
&lt;li&gt;built-in API documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Poetry: dependency management tool&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dependency resolver to prevent dependency version error&lt;/li&gt;
&lt;li&gt;virtualenv for an isolated environment&lt;/li&gt;
&lt;li&gt;able to build and publish&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Path Parameter: GET method with value directly on the path&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Query Parameter: GET method that gives key-value pair to pass many data&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;Client to API: Request Body&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API to Client: Response Body&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;By using response_model in the decorator, output data is modified with that description
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;auto-documentation and data validation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There is a field in the Header called Content-Type that tells what type of data is passed&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;Form: allows to get Form data from the request&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;File Uploading: need to use python-multipart&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;Pydantic: data validation/settings management library&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;forces type hinting&lt;/li&gt;
&lt;li&gt;validation for normal python types&lt;/li&gt;
&lt;li&gt;faster than other libraries&lt;/li&gt;
&lt;li&gt;config management&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Event Handler: a function that is called when some event is happening&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;API Router: using multiple APIs together&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;Error Handling: the developer needs to collect a log of errors happening to the client&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;use HTTPExceptiojn to tell the client to recognize what is happening&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Background Tasks: allows for an immediate response without waiting for full execution&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;use the GET method later to the stored task to find out if the task is completed&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Types of data:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;database data: data needed for service&lt;/li&gt;
&lt;li&gt;user action log: data obtained from the user's action
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;not necessarily needed for the service, but it is for analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;infrastructure data: a metric that checks if the web server is working well&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;number of requests and response&lt;/li&gt;
&lt;li&gt;DB overloading&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trace: log for development&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;Method of saving the data:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;saving in the database(RDB): reusable in the service
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;rows and columns&lt;/li&gt;
&lt;li&gt;define the relation between data and do data modeling&lt;/li&gt;
&lt;li&gt;important data related to the business&lt;/li&gt;
&lt;li&gt;use SQL to extract data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;saving in the database(NoSQL): using elastic search, logstash or fluent, kibana
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;loose schema&lt;/li&gt;
&lt;li&gt;fast read and write speed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;saving in the object storage: saving as a file in S3 or Cloud Storage
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;can save any type of data&lt;/li&gt;
&lt;li&gt;needs work to move to a separate database or data warehouse&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;saving in data warehouse: used for data analysis instantly
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;save RDBMS, NoSQL, and Object Storage at once&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DEBUG: logging information to solve a problem&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INFO: working well&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WARNING: potential problem&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ERROR: cannot execute function&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CRITICAL: the program does not work&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;Logger: a method for creating the log&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hander: send the log to a certain location, which could be saved or sent&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Formatter: set the style of log&lt;/p&gt;</description>
      <category>잡다한 것들/부스트캠프 AI Tech 4기</category>
      <category>ML</category>
      <category>Python</category>
      <category>부스트캠프</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/31</guid>
      <comments>https://limepencil.tistory.com/31#entry31comment</comments>
      <pubDate>Tue, 10 Jan 2023 12:34:41 +0900</pubDate>
    </item>
    <item>
      <title>부스트캠프 14주차 학습 일지 - Semantic Segmentation</title>
      <link>https://limepencil.tistory.com/30</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들:&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://www.python.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/Python-FFD43B?style=for-the-badge&amp;amp;logo=python&amp;amp;logoColor=blue&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://pytorch.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/PyTorch-EE4C2C?style=for-the-badge&amp;amp;logo=PyTorch&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://jupyter.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/jupyter-%23FA0F00.svg?style=for-the-badge&amp;amp;logo=jupyter&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12/19 월&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mIOU: mean of IOU over classes&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;FCN: use the VGG network as the backbone and replace the FC layer with Convolution&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;allows using pretrained networks for better performance&lt;/li&gt;
&lt;li&gt;pixel-wise prediction&lt;/li&gt;
&lt;li&gt;convolution is irrelevant to image size&lt;/li&gt;
&lt;li&gt;transposed convolution for upsampling&lt;/li&gt;
&lt;li&gt;skip connection to have a sharp image&lt;/li&gt;
&lt;li&gt;Small objects are often ignored&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeconvNet: make the encoder and decoder symmetrical by using unpooling and deconvolution&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Unpooling: save the edge that was deleted during pooling&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fast as it does not need to be trained&lt;/li&gt;
&lt;li&gt;has a sparse activation map so it is required to use transposed convolution too&lt;/li&gt;
&lt;li&gt;unpooling captures &quot;example-specific&quot; structure&lt;/li&gt;
&lt;li&gt;transposed convolution captures a &quot;class-specific&quot; structure&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SegNet: use convolution to turn the sparse matrix into a dense matrix&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;FC DenseNet: add skip connection inside a block and from the decoder to the encoder&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;DeepLab v1: mixing convolution and max pooling can increase the receptive field of a unit pixel of the feature map but is low in quality&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;use dilated convolution to be more efficient&lt;/li&gt;
&lt;li&gt;use bilinear interpolation for upsampling&lt;/li&gt;
&lt;li&gt;dense conditional random field to get pixel-wise segmentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DilatedNet: DeepLab but only 2x2 max pool in the beginning&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12/21 수&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepLab v2: added ASPP which are branches that replaced the fully convolutional layer&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;branches act as an ensemble&lt;/li&gt;
&lt;li&gt;ResNet backbone&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PSPNet: use global average pooling to take surroundings into account&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Accounts for mismatched relationship
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;takes the surrounding into account&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Confusion categories
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;similar category can be confusing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Inconspicuous classes
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;small objects can be detected using global contextual information&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeepLab&amp;nbsp; v3: added global average pooling with 1x1 convolutional network&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;DeepLab v3+: use encoder-decoder structure again&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;use a decoder to restore the lost spatial information&lt;/li&gt;
&lt;li&gt;modified Xception Backbone
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;use depthwise + pointwise convolution&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;</description>
      <category>잡다한 것들/부스트캠프 AI Tech 4기</category>
      <category>Python</category>
      <category>부스트캠프</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/30</guid>
      <comments>https://limepencil.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 19 Dec 2022 13:46:38 +0900</pubDate>
    </item>
    <item>
      <title>부스트캠프 12주차 학습 일지 - 데이터 제작</title>
      <link>https://limepencil.tistory.com/29</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들:&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://www.python.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/Python-FFD43B?style=for-the-badge&amp;amp;logo=python&amp;amp;logoColor=blue&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://pytorch.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/PyTorch-EE4C2C?style=for-the-badge&amp;amp;logo=PyTorch&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://jupyter.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/jupyter-%23FA0F00.svg?style=for-the-badge&amp;amp;logo=jupyter&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12/5 월&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&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;p data-ke-size=&quot;size16&quot;&gt;Software 1.0&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;문제 정의&lt;/li&gt;
&lt;li&gt;큰 문제를 작은 문제들의 집합으로 분해&lt;/li&gt;
&lt;li&gt;개별 문제 별로 알고리즘 설계&lt;/li&gt;
&lt;li&gt;솔루션들을 합쳐 하나의 시스템으로&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Software 2.0&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;뉴럴넷 구조에 의해 검색을 한다&lt;/li&gt;
&lt;li&gt;최적화를 통해 사람이 정한 목표에 가장 적합한 연산의 집합을 찾는다&lt;/li&gt;
&lt;li&gt;경로와 목적지는 데이터와 최적화 방법에 의해서 정해진다&lt;/li&gt;
&lt;/ol&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12/6 화&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Production Process of AI Model:&lt;/p&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;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;/li&gt;
&lt;li&gt;목표 qps&lt;/li&gt;
&lt;li&gt;Serving 방식&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;수량&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;이슈 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Data-centric: data만 수정하여 모델 성능 끌어올리기&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서비스 출시 후의 성능 계선은 data를 늘리는 게 더 비용 절감도 되고 편하다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model-centric: 데이터를 고정시키고 모델 성능 끌어올리기&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;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;좋은 데이터를 많이 모으기 힘들다&lt;/li&gt;
&lt;li&gt;라벨링 비용이 크다&lt;/li&gt;
&lt;li&gt;작업 기간이 오래 걸린다&lt;/li&gt;
&lt;/ol&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;p data-ke-size=&quot;size16&quot;&gt;Best case: small data/clean labels/data balance&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;/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;Labeling is an iterative process&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;OCR: Optical Character Recognition&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;STR: Scene Text Recognition&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;/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;/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;밀도가 높다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OCR 순서:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Detector(글자 영역 검출) &amp;rarr;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Recognizer(이미지를 글자로) &amp;rarr;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Serializer(2D text to 1D text) &amp;rarr;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parser(understanding the text)&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;OCR services:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;copy text from the image&lt;/li&gt;
&lt;li&gt;Search image by word&lt;/li&gt;
&lt;li&gt;move playlists to a new platform with screenshots&lt;/li&gt;
&lt;li&gt;translate&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rectangle types:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RECT: (x1,y1,width,height)&lt;/li&gt;
&lt;li&gt;RBOX: (x1,y1,width,height, &amp;theta;)&lt;/li&gt;
&lt;li&gt;QUAD: 4 x,y coordinates, x1,y1 is in top left and plot clockwise&lt;/li&gt;
&lt;li&gt;Polygon: multiple coordinates to fit the arbitrary-shaped text&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Regression-based: image to bbox directly using anchor box&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;downside: cannot work well with the arbitrary-shaped text, sometimes does not capture all the characters due to receptive field and anchor box&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Segmentation-based: get the image as input to get pixel-wise data of whether that pixel is in the text area, along with 8 other probabilities for the border to divide those areas&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;downside: too slow post-processing, interference between different areas&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hybrid: get approximate bbox using regression and use segmentation to get pixel-wise data&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;EAST: An Efficient and Accurate Scene Text Detector&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;The network outputs two pieces of information about pixels:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;whether it is in the center of the text area (score map)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;binary map&lt;/li&gt;
&lt;li&gt;30% less size of a ground truth bounding box&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;if the pixel is a text area, where is the bbox (geometry map)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RBOX
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5 channel&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;QUAD
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;8 channel&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;use U-Net&lt;/li&gt;
&lt;li&gt;Consist of feature extractor stem, feature merging branch&lt;/li&gt;
&lt;li&gt;use locality-aware NMS to merge the box from top to bottom as nearby pixels will predict the same text instance&lt;/li&gt;
&lt;li&gt;class-balanced cross-entropy&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Public dataset:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;can acquire labeled images easily&lt;/li&gt;
&lt;li&gt;data might not be what is needed&lt;/li&gt;
&lt;li&gt;not many data&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Synthetic image:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;does not need to be labeled&lt;/li&gt;
&lt;li&gt;fast acquirement&lt;/li&gt;
&lt;li&gt;need to check if the data is similar to the real-world data&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Crawled image:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fast at collecting images&lt;/li&gt;
&lt;li&gt;not a lot of high-quality images&lt;/li&gt;
&lt;li&gt;not a lot of samples&lt;/li&gt;
&lt;li&gt;copyright&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Crowd-sourced image:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;expensive&lt;/li&gt;
&lt;li&gt;high-quality&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12/7 수&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&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;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;p data-ke-size=&quot;size16&quot;&gt;데이터 제작 순서:&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;가이드 교육&lt;/li&gt;
&lt;li&gt;라벨링&lt;/li&gt;
&lt;li&gt;라벨링 검수&lt;/li&gt;
&lt;li&gt;데이터 검수 by AI team&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글자 검출 모델 평가방법:&lt;/p&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;one-to-one match&lt;/li&gt;
&lt;li&gt;one-to-many match (split)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;more prediction than ground truth&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;may-to-one match (merge)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;more ground truth than prediction&lt;/li&gt;
&lt;/ul&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;IOU
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Only allow one-to-one matching&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Area recall, precision&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DetEval: calculate for each cell in the matching matrix&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;One to one = 1&lt;/li&gt;
&lt;li&gt;Many to one = 1&lt;/li&gt;
&lt;li&gt;One to Many = 0.8&lt;/li&gt;
&lt;li&gt;Recall = average by the ground truth&lt;/li&gt;
&lt;li&gt;Precision = average by the prediction&lt;/li&gt;
&lt;li&gt;Final score: F1-Score&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TIoU: give a score for the area that is over or less than the ground truth&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;CLEval: score by how many characters the bbox got it right&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;Annotation tool:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LabelMe
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;based on MIT open source&lt;/li&gt;
&lt;li&gt;easy to install&lt;/li&gt;
&lt;li&gt;cannot collaborate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CVAT
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;made by intel&lt;/li&gt;
&lt;li&gt;multi-user&lt;/li&gt;
&lt;li&gt;various annotation&lt;/li&gt;
&lt;li&gt;the model inference is slow&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Hasty Labeling tool
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;multi-user&lt;/li&gt;
&lt;li&gt;not free&lt;/li&gt;
&lt;li&gt;cannot customize&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBNet: adaptive thresholding to give more threshold to the border&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;MOST: an improved version of EAST&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TFAM: use deformable convolution to manage receptive field&lt;/li&gt;
&lt;li&gt;PA-NMS(position-aware NMS): more weight to point that is predicted near the edge&lt;/li&gt;
&lt;li&gt;Instance-wise IoU loss: IOU with normalization to give a scale-invariant characteristic&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TextFuseNet: get global level feature along with character level feature&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12/9 목&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Synthetic data is cheap to create and has the correct label.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use depth estimation to put the synthetic text in the right place&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;SynthText3D: use 3D virtual world to make a synthetic image&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;It is helpful to use synthetic data as a pretraining dataset&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;Use data augmentation: geometric transformation + style transformation ...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use crop with no bbox cut so that it learns better&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;Multi-scale training can be helpful&lt;/p&gt;</description>
      <category>잡다한 것들/부스트캠프 AI Tech 4기</category>
      <category>AI-Tech</category>
      <category>Python</category>
      <category>부스트캠프</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/29</guid>
      <comments>https://limepencil.tistory.com/29#entry29comment</comments>
      <pubDate>Mon, 5 Dec 2022 15:31:30 +0900</pubDate>
    </item>
    <item>
      <title>부스트캠프 9주차 학습 일지 - Object Detection 1</title>
      <link>https://limepencil.tistory.com/27</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들:&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://www.python.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/Python-FFD43B?style=for-the-badge&amp;amp;logo=python&amp;amp;logoColor=blue&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://pytorch.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/PyTorch-EE4C2C?style=for-the-badge&amp;amp;logo=PyTorch&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://jupyter.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/jupyter-%23FA0F00.svg?style=for-the-badge&amp;amp;logo=jupyter&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11/14 월&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;PR curve: calculated precision and recall from accumulated TP and FP sorted by confidence rate&lt;/span&gt;&lt;span&gt;&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;&lt;span&gt;Average precision: right rectangle estimation of PR curve&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;mAP(mean average precision):&amp;nbsp; AP of classes/number of classes&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- mAP50 means that it only regards IOU over 50 as True Positive&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;IOU(Intersection Over Union): $\frac{Overlapping\;region}{combined\;region}$&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;FPS is an important measure for live video object detection&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;FLOPs (floating point operations): count of the operation performed&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;MMDetection: object detection open source written in PyTorch&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;Detectron2: Meta ai research library for object detection and segmentation&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;YOLOv5: coco pretrained model that is well developed&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;EfficientDet: image detection model based on efficientnet made by google&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;R-CNN:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Extract Region proposals
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Sliding Window: use a fix-sized box to move that across the image to get bounding boxes&lt;/li&gt;
&lt;li&gt;Selective search: do an initial segmentation and add those together to get larger bounding boxes
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2000 ROI&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Compute CNN features
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AlexNet&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Classify&lt;/li&gt;
&lt;li&gt;Adjust bounding box&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;R-CNN is not end-to-end&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;SPP-Net:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Forward the whole image through ConvNet&lt;/li&gt;
&lt;li&gt;Extract ROI&lt;/li&gt;
&lt;li&gt;Spatial Pyramid Pooling Layer
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;make the ROI the same size by passing through the layer instead of warping&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;FC layer&lt;/li&gt;
&lt;li&gt;classify regions with SVM&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fast R-CNN:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Forward the whole image through VGG16&lt;/li&gt;
&lt;li&gt;ROI projection to get ROI
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;project the selective search ROI to the output of VGG16&lt;/li&gt;
&lt;li&gt;one batch only contains the ROI of an image&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;ROI pooling to get features with the same size
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pyramid level 1 with 7x7 grid size&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;FC layer&lt;/li&gt;
&lt;li&gt;Softmax classifier + bounding box regressor&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;R-CNN, SPP-Net, and Fast R-CNN are not end-to-end&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;Faster R-CNN:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Forward images through a network to get feature maps&lt;/li&gt;
&lt;li&gt;Use Region Proposal Network(RPN) to get ROI
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Replace selective search&lt;/li&gt;
&lt;li&gt;Anchor box
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;divide the image into cells that have different bound box sizes and numbers for each&lt;/li&gt;
&lt;li&gt;RPN predicts if there is an object in the cell and the transformation needed for the anchor boxes&lt;/li&gt;
&lt;li&gt;do 3x3 to make 512 channel&lt;/li&gt;
&lt;li&gt;1x1x2 for binary classification of the existence of the object&lt;/li&gt;
&lt;li&gt;1x1x4 for bounding box regression&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;NMS: remove the bounding box based on IoU and class score&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11/15 화&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mmdetection: 많은 프레임워크를 지원하고 빠름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- pytorch 기반 오픈소스 라이브러리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Pipeline: Input, backbone, neck, dense prediction, prediction&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- config 파일로 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- config 상속 받고 부분만 바꿈&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;Config 기본 구조:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dataset: coco, VOC, cityscape&lt;/li&gt;
&lt;li&gt;model: faster_rcnn, RetinaNet, RPN
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2stage model
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;type: type of model&lt;/li&gt;
&lt;li&gt;backbone: a network that converts an image to feature map
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;can add a custom backbone&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;neck: connects backbone and head&lt;/li&gt;
&lt;li&gt;rpn_head: region proposal network&lt;/li&gt;
&lt;li&gt;RoI_head: region of interest&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;schedule&lt;/li&gt;
&lt;li&gt;default_runtime&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Detectron2: OD 말고 다른 알고리즘들도 지원함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Pipeline: Setup config, setup trainer, start training&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 학습 방식은 mmdetection과 비슷함&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;Neck: Backbone과 RPN을 연결시켜주는 역할&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- backbone의 중간 feature들도 사용하면서 다양한 크기의 객체를 더 잘 탐지할 수 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 하위 level의 feature은 semantic이 약하므로 상대적으로 sematic이 강한 상위 feature와의 교환이 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- level당 feature을 섞어줌&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;featurized image pyramid: various resized image that is used to get the feature&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;single feature map: get output as the feature by passing an image&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;pyramidal feature hierarchy: pass through like a single feature map, but use the middle layer's feature too&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;feature pyramid network: give information from the high level to the low level by creating a top-down pathway&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;down-top and top-down features are added by doing 1x1 conv for the lateral connection and 2x upsampling convolution for the top-down pathway&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Path Aggregation Network(PANet): add down-top pathway after top-down pathway for deep CNN&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;do RoI pooling for all the features&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DetectoRS: looking and thinking twice&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;recursive feature pyramid: FPN that is done recursively&lt;/li&gt;
&lt;li&gt;ASPP: give different dilation rates to increase the convolution receptive field size&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EfficientDet: PANet that removes the node that is useless&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;weighted feature fusion: give weight to the layers to differentiate low level and high level&lt;/li&gt;
&lt;li&gt;connect the lateral pathway to the down-top pathway too&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NASFPN: find the FPN architecture by neural network search&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Not generalizable&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AugFPN: to solve the problem of loss of information on the highest feature map&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Residual Feature Augmentation: give semantic information of a high level directly to the final pyramid
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ratio-invariant adaptive pooling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Soft RoI selection: use all features to get RoI by using weights&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-stage detectors: localization and classification at the same time&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- fast and easy design&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- taken into context&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- YOLO, SSD, RetinaNet&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;You Only Look Once(YOLO): first 1-stage detector&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- modified GoogLeNet&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;divide into the grid area&lt;/li&gt;
&lt;li&gt;get b number of bounding boxes and a confidence score for each grid
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;confidence score: Prob(Object existing) * IOU of truth and pred&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;get the probability of class for each grid
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;conditional class probability: Pr(Class|Object)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;The output contains 30 channels
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5 channels each for 2 bbox&amp;nbsp;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;x coordinate of the center of the grid cell&lt;/li&gt;
&lt;li&gt;y coordinate of the center of the grid cell&lt;/li&gt;
&lt;li&gt;width of bbox&lt;/li&gt;
&lt;li&gt;height of bbox&lt;/li&gt;
&lt;li&gt;bbox confidence score&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;class maps&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;multiply the bbox confidence score by the class maps to get the probability of the bbox being the bbox for the object&lt;/li&gt;
&lt;li&gt;make the probability zero if under a certain threshold and sort in descending order&lt;/li&gt;
&lt;li&gt;use NMS to remove redundant bbox&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSD: to solve the problem of detecting small-sized objects and using only the last layer of the feature&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use 6 different scale feature maps: a big feature map predicts small objects while a small feature map predicts large objects&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use only the convolution layer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use anchor box&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- VGG-16 as the backbone&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;YOLO v2:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- higher resolution&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- convolution with anchor boxes&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- no FC layer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- batch normalization&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- add early feature map to late feature map&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- multi-scale training&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Darknet-19&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- used WordTree which combined ImageNet and COCO to make a hierarchical dataset&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;YOLO v3:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Darknet-53&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- convolution stride 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use 3 different scales&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use Feature Pyramid Network&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RetinaNet:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- to solve the problem of 1 stage detector having too many negative samples&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use new loss function (Focal Loss): cross-entropy loss + scaling factor (more importance on harder cases)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Improvement in performance&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11/16 수&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Width scaling: used for a small model to get small details well&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;Depth scaling: used in many models to get complex and rich features but it has a problem of gradient vanishing&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;Resolution scaling: can get details very well&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;EfficientDet: efficiently scales the model&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- match the width, depth, and resolution balance to achieve great performance with low computational cost&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- idea from EfficientNet&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- efficiency is needed for real-time&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Efficient multi-scale feature fusion
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;remove the node with one edge only&lt;/li&gt;
&lt;li&gt;add input to output by adding an edge&lt;/li&gt;
&lt;li&gt;use repeated block&lt;/li&gt;
&lt;li&gt;used a weighted sum of various resolutions
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BiFPN: weight passes through ReLU so that it does not become 0 and also add epsilon to make denominator non-zero, basically a weighted sum&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;model scaling: compound scaling like EfficientNet&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cascade RCNN: explored change when the threshold for the positive and negative sample is changed&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- higher the input IoU, the better performance for a model that is trained with the higher threshold&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- higher the threshold, it performs better when the AP IoU threshold is higher&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- train multiple RoI heads, and set the IoU threshold differently for each head, the bounding box of the previous head is applied to the next head&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Iterative + Integral = Cascade&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;DCN(Deformable Convolutional Networks):&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;normal CNN is weak against geometric transformation
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;traditional method: geometric augmentation, geometric invariant feature selection&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;when the convolution kernel is multiplied, give some geometric offset in the middle of convolutional operations
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;has an offset field that contains an offset vector&lt;/li&gt;
&lt;li&gt;the model learns the offset of the feature&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;good performance in object detection and segmentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The problem with ViT is that it has a high computational cost and needs a lot of data to train&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;DETR(End-to-End object detection with transformer:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;replaces the need for NMS&lt;/li&gt;
&lt;li&gt;use a high-level feature map because it needs a high computational cost&lt;/li&gt;
&lt;li&gt;Pipeline
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Input&lt;/li&gt;
&lt;li&gt;CNN&lt;/li&gt;
&lt;li&gt;encoder + positional encoding&lt;/li&gt;
&lt;li&gt;decoder&lt;/li&gt;
&lt;li&gt;Feed forward Network&lt;/li&gt;
&lt;li&gt;N output
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;N&amp;gt; number of objects in the image&lt;/li&gt;
&lt;li&gt;pad objects as no object by the amount of difference between N and the number of objects
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;this allows getting a precise amount of objects as output&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Swin Transformer: use an architecture called window to reduce the computational cost&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;No class embedding&lt;/li&gt;
&lt;li&gt;Two attention per transformer block&lt;/li&gt;
&lt;li&gt;embedding is divided by the unit of the window, so the image is divided into many windows which decreases the computational cost of the model
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;has a problem of not using other parts of the window as consideration, so Shifted Window Multi-Head Attention corrects that by different divisions of windows&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;trains well with a low amount of data&lt;/li&gt;
&lt;/ul&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>잡다한 것들/부스트캠프 AI Tech 4기</category>
      <category>AI Tech</category>
      <category>object detection</category>
      <category>부스트캠프</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/27</guid>
      <comments>https://limepencil.tistory.com/27#entry27comment</comments>
      <pubDate>Mon, 14 Nov 2022 13:53:06 +0900</pubDate>
    </item>
    <item>
      <title>부스트캠프 8주차 학습 일지 - AI 서비스 개발 기초</title>
      <link>https://limepencil.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들:&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://www.python.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/Python-FFD43B?style=for-the-badge&amp;amp;logo=python&amp;amp;logoColor=blue&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://pytorch.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/PyTorch-EE4C2C?style=for-the-badge&amp;amp;logo=PyTorch&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://jupyter.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/jupyter-%23FA0F00.svg?style=for-the-badge&amp;amp;logo=jupyter&amp;amp;logoColor=white&quot; /&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&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;11/7 월&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MLOps: ML +Ops(operations)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 업무 자동화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Machine Learning engineering + data engineering + cloud + infrastructure&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 빠른 시간 내에 가장 적은 위험을 부담하며 아이디어 단계부터 production 단계까지 진행할 수 있도록 기술적 마찰 줄이기&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;Research ML vs Production ML:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- static data vs dynamic data&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- good performance vs fast inference with good performance&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- SOTA vs stable&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- offline vs online&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;MLOps components:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Model&lt;/li&gt;
&lt;li&gt;Data, feature&lt;/li&gt;
&lt;li&gt;CPU, GPU, Memory&lt;/li&gt;
&lt;li&gt;scalability&lt;/li&gt;
&lt;li&gt;cloud, server&lt;/li&gt;
&lt;li&gt;Batch serving/online serving&lt;/li&gt;
&lt;li&gt;experiment, model management&lt;/li&gt;
&lt;li&gt;feature store&lt;/li&gt;
&lt;li&gt;data validation&lt;/li&gt;
&lt;li&gt;continuous training&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;li&gt;AutoML&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Serving: 머신 러닝 모델을 앱이나 웹에서 사용할 수 있게 만드는 과정&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;Online serving: use HTTP protocol and API to handle requests&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- servers need to be able to hold those requests&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- API opens the request mechanism to the public&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;Single data point: serving a single data&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;There can be a server for preprocessing and a separate one for the ML model&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;Ways to make online serving:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;make own API&lt;/li&gt;
&lt;li&gt;use cloud service&lt;/li&gt;
&lt;li&gt;use serving libraries&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Batch serving: inference on every certain amount of time or every determined amount of data&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;Machine learning project flow:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;define problem
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;need to know what we are solving exactly&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;design the product
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;check the validity of the value of the project&lt;/li&gt;
&lt;li&gt;look for existing data or model&lt;/li&gt;
&lt;li&gt;choose good lose function&lt;/li&gt;
&lt;li&gt;machine learning is good if there is a pattern and it is complex, repetitive&lt;/li&gt;
&lt;li&gt;gather data first if there is not one&lt;/li&gt;
&lt;li&gt;set the right goal and new objective
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;the goal needs to be ethical&lt;/li&gt;
&lt;li&gt;the objective can be multiple so attention is needed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;get the constraint and the risk of the project&lt;/li&gt;
&lt;li&gt;make a baseline and prototype to start off&lt;/li&gt;
&lt;li&gt;set the right metric to evaluate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;monitor after deployment
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;performance&lt;/li&gt;
&lt;li&gt;which part went wrong&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Business model: look for where the output can be used in the company&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11/8 화&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Voila: make a notebook to prototype web&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- originally made for the dashboard&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- easy to experiment with stuff&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;ipywidget: allows for interactive notebook&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- slider allows for interactive control of value&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- text allows for integer and string input&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- checkbox&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- dropdown&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- file upload&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- on_click&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- observe&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;Streamlit: allows for web service in minor modifications of a python code&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- no frontend needed&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- many easy components&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- runs every time when a change happens&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11/9 수&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;virtualization: a template that is used for research and production environment&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- to solve a different state of the environment in local, test, and production&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;virtual machine: use image to create an environment with OS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- it is heavy to run an OS on another OS&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;docker: use containers to lighten VM&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- use docker image which is read-only to make a docker container that makes a copy of the image&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- allows using other people's software instantly with the same setting and environment&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;container registry: like GitHub for container images&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;docker commands:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- pull: download image&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- images: list of images&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- run: run image to make container&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- ps: current running container&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- exec: go into the container&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- container: stop running the container&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- rm: remove the container&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- volume mount allows connecting the file of the host and the container&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- build: make the image&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;MLflow: allows for management of lifecycle in experiments and allows reproduce the experiment result&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- experiment management &amp;amp; tracking&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- model registry/versioning&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- model serving&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- project code versioning&amp;nbsp;&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;MLflow commands:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- experiments create: make experiments that are like the theme of the project&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- run: runs code 1 time: logs source, version, start&amp;amp;end time, parameters, metrics, tags, artifacts&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- server: selects where to store the tracking data&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;&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;p data-ke-size=&quot;size16&quot;&gt;서비스의 품질이 좋아야 하기 때문에 offline test 결과보다 online test가 더 잘 나오게 설계를 해야한다&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;Creative Commons License: 저작권 라이센스의 종류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- BY: 저작자 표시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- ND: 변경 금지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- NC: 비영리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- SA: 같은 조건의 CCL 적용의무&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;데이터의 bias가 결과에서도 반영이 된다&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;Proxies: unintentional discrimination&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Masking: intentional discrimination&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11/10 목&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;학습한 것들:&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마스크 분류 모델을 streamlit과 streamlit cloud로 웹서비스를 만들어서 배포를 해봤다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://mask-classification.streamlit.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://mask-classification.streamlit.app/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668066742265&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;app &amp;middot; Streamlit&quot; data-og-description=&quot;Check out this app I built with Streamlit!&quot; data-og-host=&quot;mask-classification.streamlit.app&quot; data-og-source-url=&quot;https://mask-classification.streamlit.app/&quot; data-og-url=&quot;https://limepencil-bo-streamlit-prototyping-special-mission-1app-swf2tr.streamlit.app/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://mask-classification.streamlit.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mask-classification.streamlit.app/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;app &amp;middot; Streamlit&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Check out this app I built with Streamlit!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mask-classification.streamlit.app&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>잡다한 것들/부스트캠프 AI Tech 4기</category>
      <category>aitech</category>
      <category>ML</category>
      <category>Product Serving</category>
      <category>pytorch</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/26</guid>
      <comments>https://limepencil.tistory.com/26#entry26comment</comments>
      <pubDate>Mon, 7 Nov 2022 13:40:55 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 6137번: 문자열 생성 풀이</title>
      <link>https://limepencil.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 기술 스택들:&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://www.python.org/&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/Python-FFD43B?style=for-the-badge&amp;amp;logo=python&amp;amp;logoColor=blue&quot; /&gt;&lt;/a&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;&lt;a href=&quot;https://www.acmicpc.net/problem/6137&quot;&gt;6137번: 문자열 생성 (acmicpc.net)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667739185662&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;6137번: 문자열 생성&quot; data-og-description=&quot;첫 번째 줄에 문자열 S의 길이 N이 주어진다. (N &amp;lt;= 2,000) 이후 N개의 줄에 S를 이루는 문자들이 주어진다.&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/6137&quot; data-og-url=&quot;https://www.acmicpc.net/problem/6137&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lu55I/hyQtxzj3Ze/yuvWwTSYNxEjkv0pxQCApk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/6137&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/6137&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lu55I/hyQtxzj3Ze/yuvWwTSYNxEjkv0pxQCApk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;6137번: 문자열 생성&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 줄에 문자열 S의 길이 N이 주어진다. (N &amp;lt;= 2,000) 이후 N개의 줄에 S를 이루는 문자들이 주어진다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드:&lt;/h3&gt;
&lt;pre id=&quot;code_1667739300575&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import sys

input = lambda: sys.stdin.readline().rstrip()
n = int(input())
s=&quot;&quot;
for _ in range(n):
    s+=input()
l=0
r=n-1
ans=&quot;&quot;
while l&amp;lt;=r:
    if s[l]&amp;lt;s[r]:
        ans+=s[l]
        l+=1
    elif s[l]&amp;gt;s[r]:
        ans+=s[r]
        r-=1
    else:
        t_l=l+1
        t_r=r-1
        front=True
        while t_l&amp;lt;=t_r:
            if s[t_l]&amp;lt;s[t_r]:
                front=True
                break
            elif s[t_l]&amp;gt;s[t_r]:
                front=False
                break
            else:
                t_l+=1
                t_r-=1
        if front:
            ans+=s[l]
            l+=1
        else:
            ans+=s[r]
            r-=1
print(*[ ans[i:i+80] for i in range(0, n, 80) ],sep=&quot;\n&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에서는 문자열 $s$로 사전적으로 제일 작은 문자열 $t$를 만들려고 한다. 이 문제를 그냥 s로 만들 수 있는 모든 조합을 찾으려고 하면 경우의 수가 $O(2^N)$이 되기 때문에 제한이 2000까지인 이 문제는 $2^{2000} = 1.148e+602$ 정도이기 때문에 절대 시간내에 돌수가 없다.&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;그렇다면 여기에서 가능한 풀이는 그리디적인 풀이라고 추측을 해볼 수 있다. PS에서는 제한을 아는 것이 참 중요한데, 왜냐하면 제한을 알면 어느정도의 시간복잡도를 예측할 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1667741729426&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while l&amp;lt;=r:
    if s[l]&amp;lt;s[r]:
        ans+=s[l]
        l+=1
    elif s[l]&amp;gt;s[r]:
        ans+=s[r]
        r-=1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 그리디적인 사고를 사용하자면, $s$의 앞이나 뒤에있는 문자를 $t$에 붙인다면, 사전적으로 제일 작은 문자열을 만든다면, 그냥 앞이나 뒤에서 제일 알파벳적으로 작은 것부터 꺼내오면 된다는 사실을 알게된다. 어짜피 앞에서부터 차근차근 $t$가 만들어지기 때문에 그냥 작은것들로 먼저 채워주는게 해답이라는 것을 알게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1667741822255&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;t_l=l+1
t_r=r-1
front=True
while t_l&amp;lt;=t_r:
    if s[t_l]&amp;lt;s[t_r]:
        front=True
        break
    elif s[t_l]&amp;gt;s[t_r]:
        front=False
        break
    else:
        t_l+=1
        t_r-=1
if front:
    ans+=s[l]
    l+=1
else:
    ans+=s[r]
    r-=1&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;하지만, 여기서 문제가 발생한다. $s$가 만약에 acba같은 상황이라면 어떻게 해야 하는가? 이를 위해 예외처리를 해줘야 한다. 이 예시에서의 해답은 aabc이다. 이와 같이 앞뒤가 다 같은 상황이라면 그 다음 문자를 확인해 주면 된다는 것이다. 다음 문자들에서 비교하고 그문자들 중에 앞에게 더 작으면 그쪽으로 가는게 최적이기 때문에 front를 True로 설정해주고 그 반대라면 False로 설정해준다. 하지만 다음 문자들도 같을 수가 있기 때문에 이는 반복문 처리를 해줘서 다른 점을 찾을때까지 돌리면 된다.&amp;nbsp;&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;예시: s=ACDBCB&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;s=ACDBCB t=None
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A가 B보다 작기 때문에 A를 붙여준다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;s=CDBCB t=A
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C가 B보다 크기 때문에 B를 붙여준다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;s=CDBC t=AB
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앞뒤가 C로 같기 때문에 그 다음 문자를 확인 한다 D와 B 중에서는 B가 작기 때문에 뒤에 있는 C를 붙여준다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;s=CDB t=ABC
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서부터는 크기대로 붙여주는 걸 반복한다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;t=ABCBCD&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 이 코드에선 $l$이 현재 s의 앞의 문자의 위치,&amp;nbsp; $r$이 뒤의 문자의 위치로 설정이 되었다. $l$은 앞에 문자를 사용할 때마다 1씩 올려주면 되고 뒤에 문자를 사용하면 $r$을 하나씩 내려주면 될 것이다(투포인터 알고리즘). $t{\_}l$은 당연히 temporary한 변수로 그 다음 문자를 저장 할 것이고,&amp;nbsp; $t{\_}r$도 마찬가지로 작동한다. 이 알고리즘을 그대로 적용하여 코드를 구현을 하면 정답을 받게 된다.&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;이 문제의 최악의 시간 복잡도는 $O(N^2)$이다. 이 사례는 aaaaaa같이 각 문자마다 안에 있는 반복문을 하나 더 돌려주어야 하기 때문이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;소스코드:&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/LimePencil/baekjoonProblems/blob/main/com/LimePencil/Q17615/%EB%B3%BC_%EB%AA%A8%EC%9C%BC%EA%B8%B0.py&quot;&gt;baekjoonProblems/볼_모으기.py at main &amp;middot; LimePencil/baekjoonProblems (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667740972007&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - LimePencil/baekjoonProblems: 백준 코딩문제 자바&amp;amp;파이썬 해답&quot; data-og-description=&quot;백준 코딩문제 자바&amp;amp;파이썬 해답 . Contribute to LimePencil/baekjoonProblems development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/LimePencil/baekjoonProblems/blob/main/com/LimePencil/Q17615/%EB%B3%BC_%EB%AA%A8%EC%9C%BC%EA%B8%B0.py&quot; data-og-url=&quot;https://github.com/LimePencil/baekjoonProblems&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xMOjm/hyQtyruQx6/1BQkNB2lYxdNqZLfiH0iVK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/LimePencil/baekjoonProblems/blob/main/com/LimePencil/Q17615/%EB%B3%BC_%EB%AA%A8%EC%9C%BC%EA%B8%B0.py&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/LimePencil/baekjoonProblems/blob/main/com/LimePencil/Q17615/%EB%B3%BC_%EB%AA%A8%EC%9C%BC%EA%B8%B0.py&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xMOjm/hyQtyruQx6/1BQkNB2lYxdNqZLfiH0iVK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - LimePencil/baekjoonProblems: 백준 코딩문제 자바&amp;amp;파이썬 해답&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;백준 코딩문제 자바&amp;amp;파이썬 해답 . Contribute to LimePencil/baekjoonProblems development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>PS &amp;amp; Algorithm</category>
      <category>6137</category>
      <category>그리디</category>
      <category>문자열 생성</category>
      <category>백준</category>
      <category>투포인터</category>
      <category>파이썬</category>
      <author>연두색연필</author>
      <guid isPermaLink="true">https://limepencil.tistory.com/25</guid>
      <comments>https://limepencil.tistory.com/25#entry25comment</comments>
      <pubDate>Sun, 6 Nov 2022 23:01:25 +0900</pubDate>
    </item>
  </channel>
</rss>