<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>developer Story</title>
        <link>https://velog.io/</link>
        <description>성장하는 애기 개발자~</description>
        <lastBuildDate>Wed, 08 Jun 2022 08:14:36 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>developer Story</title>
            <url>https://velog.velcdn.com/images/ho-tae/profile/833e5254-198d-438c-98f2-f3837f53aa1a/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. developer Story. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ho-tae" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[SRP(Single Responsiability Principle)란?]]></title>
            <link>https://velog.io/@ho-tae/SRPSingle-Responsiability-Principle%EB%9E%80</link>
            <guid>https://velog.io/@ho-tae/SRPSingle-Responsiability-Principle%EB%9E%80</guid>
            <pubDate>Wed, 08 Jun 2022 08:14:36 GMT</pubDate>
            <description><![CDATA[<h2 id="single-responsibility-principle단일-책임-원칙">Single Responsibility Principle(단일 책임 원칙)</h2>
<p>단일 책임 원칙(SRP)이란 하나의 클래스는 하나의 책임만 가지며, 그 책임에 대해 완전히 캡슐화 해야 하는 원칙이다.</p>
<pre><code class="language-python">class Food:
    &quot;&quot;&quot;추상화 과정이 필요한 Food 클래스&quot;&quot;&quot;

    def __init__(self, name, food):
        self.name = name
        self.food = food

    def eat_food(self):
        if self.food == &quot;치킨&quot;:
            print(f&quot;{self.name}가 {self.food}를 먹는다&quot;)

        elif self.food == &quot;피자&quot;:
            print(f&quot;{self.name}가 {self.food}를 먹는다&quot;)</code></pre>
<p>예제를 먼저 보자. 위의 Food 클래스에서는 객체 생성시에 음식을 정의하고, 음식에 따라 if문을 처리한다. 즉 Food 클래스는 음식이 다른 두가지 케이스에 대한 책임을 동시에 가지고 있다. <strong>이러한 경우 Food 클래스를 추상화시킴으로써 해결할 수 있다.</strong></p>
<h3 id="추상-클래스란">추상 클래스란?</h3>
<blockquote>
<p>추상 클래스란 클래스 내부에 구현되지 않은 메서드를 한가지 이상 가지고 있을때, 추상 클래스라 부른다. 이 구현되지 않은 메서드는 자식 클래스에서 반드시 구현 해주어야 한다. 즉, 반드시 재정의(메서드 오버라이딩)하라는 뜻이다. 이 추상클래스는 부모 클래스를 설계할때, 자식 클래스에 이 함수는 반드시 존재하여야 하며 자식 클래스 각 성격마다 메서드의 내부 구현이 다를것 같으니 부모 클래스에서는 해당 메서드를 비워두지만 꼭 구현해야하기 때문에 강제한다. 는 뜻이다.</p>
</blockquote>
<pre><code class="language-python">from abc import *


class FoodBase(metaclass=ABCMeta):
    &quot;&quot;&quot;추상화 과정을 한 Food 클래스&quot;&quot;&quot;

    def __init__(self, name):
        self.name = name

    @abstractmethod
    def eat_food(self):
        pass


class Chicken(FoodBase):
    def __init__(self, name):
        super().__init__(name)
        self.food = &quot;치킨&quot;

    def eat_food(self):
        print(f&quot;{self.name}가 {self.food}를 먹는다&quot;)


class Pizza(FoodBase):
    def __init__(self, name):
        super().__init__(name)
        self.food = &quot;피자&quot;

    def eat_food(self):
        print(f&quot;{self.name}가 {self.food}를 먹는다&quot;)</code></pre>
<p>위와 같이 추상클래스, FoodBase 클래스를 만들어 주었다. 추상 클래스를 사용하려면 반드시 abc 모듈을 import 해야 한다. 또한 추상 메서드는 메서드 이름 위에 @abstractmethod 라는 것을 붙여야 하고, 추상 클래스에는 (metaclass=ABCMeta)라는 것을 붙여 주어야 한다. 이것도 추상 클래스를 만들수 있는 클래스를 상속을 받는것이다.</p>
<p>기본적으로 생성시에는 이름만 받고 이를 상속받은 클래스들은 eat_food를 구현하게끔 하였다. 그리고 FoodBase를 상속받는 Chicken 클래스와 Pizza 클래스를 정의함으로써, 음식이 다른 경우에 대해 각 클래스가 유일한 책임을 가지도록 하였다. 이렇게 우리가 SOLID에서 단일 책임 원칙에 준수하게 코드를 작성하는 방법을 살펴보았다.</p>
<p>FoodBase 클래스에서는 보다 높은 추상화 과정을 통해서 각 클래스가 하나의 책임만 가지도록 설정하였다. <strong>이렇게 단일 책임 원칙을 지킨 경우에 클래스에 대한 외부 영향도를 최소화 할 수 있으며, 결국 유지보수나 확장 면에서 보다 효율적일 수 있다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SOLID란?]]></title>
            <link>https://velog.io/@ho-tae/SOLID%EB%9E%80</link>
            <guid>https://velog.io/@ho-tae/SOLID%EB%9E%80</guid>
            <pubDate>Tue, 07 Jun 2022 06:48:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>AI 연구원  / 개발자 직무로 일하다보면 코드를 만지기도 하지만 자료조사, 논문 읽기, 데이터 전처리, 데이터 라벨링 등을 더 많이 하는 경향이 있다. 잘 알지는 모르지만 더 큰 회사들은 이러한 직무를 세분화하여 할 거 같다. 나는 그렇지 않기 때문에 두루두루 잘하면 나에게 좋다!! 또한 많이 부족하기 떄문에 코드 작성에 있어 실력을 늘려야 할 필요가 있다. 객체지향 프로그래밍에 설계의 기본적인 원칙을 준수하며 코드를 작성하면 유지 보수 및 확장이 쉬울 수 있고 협업을 할 때도 좋은거 같다. 클린코드를 위해 공부를 해보자!!</p>
</blockquote>
<h2 id="solid란">SOLID란?</h2>
<p>SOLID는 객체 지향 프로그래밍의 및 설계의 다섯가지 기본 원칙을 말한다. 프로그램이 시간이 지나도 유지 보수 및 확장이 쉬울 수 있도록 하기 위한 원칙이며, 클린코드를 위한 원칙이기도 하다!</p>
<h3 id="single-responsibility-principle단일-책임-원칙">Single Responsibility Principle(단일 책임 원칙)</h3>
<p>단일 책임 원칙(SRP)이란 하나의 클래스는 하나의 책임만 가지며, 그 책임에 대해 완전히 캡슐화 해야 하는 원칙이다.</p>
<h3 id="openclosed-principle개방폐쇄-원칙">Open/Closed Principle(개방/폐쇄 원칙)</h3>
<p>개방 폐쇄 원칙(Open/Close Principle)이란 소스가 기능 확장에는 열려있지만, 기능 수정에는 닫혀있어야 한다는 원칙이다.</p>
<h3 id="liskov-substitution-principle리스코프-치환-원칙">Liskov Substitution Principle(리스코프 치환 원칙)</h3>
<p>기반 클래스의 작업을 하위 클래스의 인스턴스로 작업할 수 있어야 한다는 원칙이다.</p>
<h3 id="interface-segregation-principle인터페이스-분리-원칙">Interface Segregation Principle(인터페이스 분리 원칙</h3>
<p>인터페이스 분리 원칙(ISP)은, 클라이언트가 자신이 이용하지 않는 메소드에 의존하면 안된다라는 원칙이다.</p>
<h3 id="dependency-inversion-principle의존관계-역전-원칙">Dependency Inversion Principle(의존관계 역전 원칙)</h3>
<p>의존성 역전 원칙은, 추상화를 통해 세부 사항에 의존하지 않도록 해야 하지만, 반대로 세부 사항(구체적인 구현)은 추상화에 의존해야 한다는 원칙이다.</p>
<p>다섯가지의 원칙이 존재하며, 하나씩 어떠한 원칙인지 공부하며 작성을 해보겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[도커(Docker) 이미지 생성]]></title>
            <link>https://velog.io/@ho-tae/%EB%8F%84%EC%BB%A4Docker-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@ho-tae/%EB%8F%84%EC%BB%A4Docker-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Sun, 29 May 2022 07:22:54 GMT</pubDate>
            <description><![CDATA[<h2 id="docker-이미지-생성-방법">docker 이미지 생성 방법</h2>
<blockquote>
<p> 이미지 생성 방법은 다음과 같은 3가지가 존재합니다. 
또한 이미지 생성에 있어 우분투 환경에서 docker와 CUDA, nvidia driver 및 toolkit(docker)가 설치되어 있는 환경이라고 가정합니다.</p>
</blockquote>
<h3 id="1-기본-이미지로-컨테이너-생성">1. 기본 이미지로 컨테이너 생성</h3>
<p>베이스 이미지를 pull 하여 이미지를 얻을 수 있습니다. 예를 들어 pytorch로 컨테이너를 생성하고 싶으면, 터미널창에서 search로 찾아도 되고 도커 허브로 접속하여 해당 이미지를 찾을 수 있습니다.</p>
<pre><code class="language-bash">docker search pytorch
docker pull pytorch/pytorch</code></pre>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/eff16629-d10a-44e2-b174-d8e4ce20d329/image.png" alt=""></p>
<p>별이 가장 많은 첫번째로 pull을 하여 이미지를 다운 받아 오겠습니다.
pull로 이미지를 다운 받은 후 docker images / docker images 이미지이름 으로 확인 하시면 됩니다. </p>
<pre><code class="language-bash">docker images
docker images 이미지 이름</code></pre>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/d5cd7067-4071-4afd-9f77-cf342de406a7/image.png" alt=""></p>
<p>하지만 자신의 CUDA 버전에 맞는 토치 버전을 포함하는 도커 이미지를 다운받아야 합니다.
<a href="https://pytorch.org/get-started/previous-versions/">여기</a> 또는 <a href="https://hub.docker.com/r/pytorch/pytorch/tags">여기</a> 확인하면 되고 CUDA 버전은 nvidia-smi로 확인 가능합니다.</p>
<pre><code class="language-bash">docker pull pytorch/pytorch:1.9.0-cuda10.2-cudnn7-runtime</code></pre>
<p>다운 받은 이미지로 컨테이너를 생성하여 pytorch를 사용해보겠습니다.</p>
<pre><code class="language-bash">docker run -it --gpus all --name pytorch-test pytorch/pytorch:1.9.0-cuda10.2-cudnn7-runtime /bin/bash</code></pre>
<h4 id="컨테이너-생성-옵션">컨테이너 생성 옵션</h4>
<table>
<thead>
<tr>
<th>Option</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>-it</td>
<td>Iterative Terminal. Container 종료 없이 탈출 가능</td>
</tr>
<tr>
<td>–name, -n</td>
<td>Container의 이름을 지정한다. 안 쓰면 nice_spence 같은 임의의 이름으로 생성된다.</td>
</tr>
<tr>
<td>–volume, -v</td>
<td>Container와 공유할 디렉토리를 지정한다. -v &lt;외부 Dir&gt;:&lt;컨테이너 Dir&gt; 형식으로 쓴다. 파일 생성/수정/삭제가 동기화된다.</td>
</tr>
<tr>
<td>–gpus all</td>
<td>Container 내부에서 GPU를 쓸 수 있도록 한다. nvidia toolkit이 설치되어 있어야 한다.</td>
</tr>
<tr>
<td>/bin/bash</td>
<td>Container 생성 시 시작할 프로세스이다. bash의 설치 위치에 따라 적당히 변경하면 된다.</td>
</tr>
</tbody></table>
<p>  컨테이너 생성 후 docker ps 명령어로 확인을 할 수 있습니다.
  <img src="https://velog.velcdn.com/images/ho-tae/post/7f58ffbd-edc0-4a8b-a051-d49b0f888360/image.png" alt=""></p>
<pre><code class="language-bash">docker ps
docker ps -a
docker ps -l</code></pre>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/e8268ab9-a273-4d6f-9c6c-825b69045b15/image.png" alt=""></p>
<p>컨테이너를 실행 후 torch를 import하여 확인하면 정상적으로 작동이 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/7b2ae56b-e2cf-490f-918c-278e02b4da1c/image.png" alt=""></p>
<hr>
<h3 id="2-commit를-이용해서-이미지-생성하기">2. commit를 이용해서 이미지 생성하기</h3>
<h3 id="docker-commit이란">docker commit이란?</h3>
<p>일반적으로 도커 컨테이너 상에서 작업한 내용들은 컨테이너가 종료되면 함께 사라집니다. 따라서 도커 컨테이너 상에서 작업한 내용을 이미지로 커밋(commit)하여 나중에 해당 이미지로부터 다시 컨테이너를 실행함으로써 작업했던 내용을 다시 사용할 수 있습니다.
pytorch 이미지를 다운받아 실행 시킨 컨테이너를 다시 실행 시킨 후 추가적으로 필요한 jupyter notebook 패키지를 설치해줍니다.</p>
<pre><code class="language-bash">docker run -itd --name pytorch-test3 -v /home/user/Downloads/check:/root/check -p 8888:8888 --gpus all pytorch/pytorch</code></pre>
<p>위에서 표로 설명했지만 다시 한번 말하자면 -v 옵션은 볼륨 마운트로 컨테이너 디렉토리와 내 로컬 디렉토리의 공유를 지정해줍니다.
/home/user/Downloads/chek 부분이 내가 가지고 있는 로컬 디렉토리이며 : 다음으로 지정한 /root/check는 컨테이너 디렉토리 입니다.
-p 옵션은 local host의 8888 포트와 컨테이너의 8888 포트를 연결해준다는 의미입니다. 만약 포트 연결 작업을 하지 않으면 jupyter notebook이 오류가 납니다.</p>
<pre><code class="language-bash">conda install jupyter </code></pre>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/e3689675-398a-4600-9df4-fc066a36ab55/image.png" alt=""></p>
<p>jupyter notebook을 설치 한 후 완료가 되면 웹브라우져와 연결해줍니다. </p>
<pre><code class="language-bash">jupyter notebook --ip=0.0.0.0 --port=8888 --allow-root</code></pre>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/e3383a79-6367-456a-9e1e-400009198216/image.png" alt=""></p>
<p>위 사진에 보이는 127.0.0.1:8888 또는 localhost:8888로 접속하여 token 번호를 입력하고 들어가면 jupyter notebook을 웹으로 접속 하실수 있습니다. </p>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/219bc29d-6369-4f44-a691-68f9abc5bc31/image.png" alt=""></p>
<p>웹에 접속하여 파일을 만들고 똑같이 torch를 import하여 확인하면 정상적으로 작동이 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/e982b488-78ac-46ad-9849-f3a5ecedb627/image.png" alt=""></p>
<p>이제 내가 만들어놓은 이미지를 COMMIT 하여 저장합니다.</p>
<ol>
<li>실행 중인 도커 컨테이너를 종료합니다.</li>
<li>종료된 도커 컨테이너의 ID를 확인합니다.</li>
<li>COMMIT 명령을 입력하여 종료된 도커 컨테이너 상태 그대로의 이미지를 생성합니다.</li>
</ol>
<pre><code class="language-bash">docker commit [CONTAINER ID] [IMAGE NAME]</code></pre>
<p>명령어 입력</p>
<pre><code class="language-bash">docker commit 1cf77110bcc1 pytorch-test:new-version</code></pre>
<p>new-version 이라는 새로운 이미지가 생성됩니다. 그 후에 run을 하여 컨테이너 상으로 접속하면 작업했던 내용을 그대로 확인할 수 있습니다.</p>
<hr>
<h3 id="3-dockerfile를-만들어-이미지-커스터마이징-하기">3. Dockerfile를 만들어 이미지 커스터마이징 하기</h3>
<p>Dockerfile는 컨테이너에 필요한 패키지, 소스코드 등을 기록해둔 파일로 빌드를 하면 도커 이미지가 생성됩니다.
** 가장 많이 쓰는 방법입니다. 이미지 생성 방법 기록 + 배포 측면에서 더 유리합니다.**
<img src="https://velog.velcdn.com/images/ho-tae/post/5f36d9f3-2b78-4634-a437-9f857a82ed7f/image.png" alt=""></p>
<ol>
<li>Dockerfile 만들기
위에서 pytorch 이미지를 pull로 다운 받고 이미지에 접속하여 컨테이너 상에서 jupyter를 설치 후 웹으로 접속하여 확인을 했지만 이번에는 도커 파일을 만들어서 바로 접속을 해보겠습니다.</li>
</ol>
<pre><code class="language-Docker">FROM pytorch/pytorch:1.9.0-cuda10.2-cudnn7-runtime

RUN apt-get update &amp;&amp; pip install jupyter

CMD [&quot;jupyter&quot;, &quot;notebook&quot;, &quot;--allow-root&quot;, &quot;--ip&quot;, &quot;0.0.0.0&quot;]</code></pre>
<ol start="2">
<li><p>Dockerfile 이미지 build 후 Run</p>
<pre><code class="language-bash">docker build -t pytorch-test:2.0 .
docker run --name pytorch-test-2 -p 8880:8888 -d -it pytorch-test:2.0</code></pre>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/a37801bc-1ba0-42d1-b4f0-1bcd45ae8956/image.png" alt=""></p>
</li>
<li><p>log를 확인하여 token 비밀번호 복사 후 웹에서 접속
<img src="https://velog.velcdn.com/images/ho-tae/post/7bcd2544-9bcf-4d86-acb4-a4569fd5a0a1/image.png" alt=""></p>
</li>
</ol>
<ol start="4">
<li>dockerfile 수정 후 jupyterlab으로도 접속하여 확인<pre><code class="language-Docker">FROM pytorch/pytorch:1.9.0-cuda10.2-cudnn7-runtime
</code></pre>
</li>
</ol>
<p>RUN apt-get update &amp;&amp; pip install jupyterlab</p>
<p>CMD [&quot;jupyter&quot;, &quot;lab&quot;, &quot;--allow-root&quot;, &quot;--ip&quot;, &quot;0.0.0.0&quot;]</p>
<pre><code>```bash
docker build -t pytorch-test:1.0 .
docker run --name pytorch-test-1 -p 8800:8888 -d -it pytorch-test:1.0</code></pre><p><img src="https://velog.velcdn.com/images/ho-tae/post/527d083a-4a81-4ae2-ba05-32e7ba6844ef/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[도커(Docker)란?]]></title>
            <link>https://velog.io/@ho-tae/5u2lbonu</link>
            <guid>https://velog.io/@ho-tae/5u2lbonu</guid>
            <pubDate>Sun, 29 May 2022 06:06:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>도커를 공부하는 이유?</p>
</blockquote>
<ul>
<li>AI 개발자 / 연구원으로 일하면서 서비스를 배포하는 백엔드 개발자와 협업을 할 때 AI의 도메인 지식이 없는 사람은 어려움과 시행착오를 많이 느낀다고 한다. 따라서 개발자라면 도커를 공부하고 사용할 줄 알아야 협업 / 개발이 원할하게 이루어지기 때문에 공부를 해야한다!!</li>
</ul>
<h2 id="docker란">Docker란?</h2>
<p>컨테이너를 사용하여 응용프로그램을 더 쉽게 만들고, 배포하고, 실행할 수 있도록 설계된 도구이며 컨테이너 기반의 오픈소스 가상화 플랫폼이다. 컨테이너 안에 다양한 프로그램, 실행환경을 컨테이너로 추상화하고 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 해준다. 일반 컨테이너의 개념에서 물건을 손쉽게 운송해주는 것처럼 프로그램을 손쉽게 이동 배포 관리할 수있게 해주며 AWS, Azure, Google Cloud등 어디에서든 실행 가능하다.</p>
<h3 id="도커를-쓰는-이유"><strong>도커를 쓰는 이유</strong></h3>
<p>결론부터 말하자면 프로그램을 다운 받는 과정을 굉장히 간단하게 만들기 위해서이다. 도커 없이 프로그램 받을 때 서버, 패키지 버전, 운영체제 등에 따라 프로그램 설치하는 과정중에 많은 에러들이 발생하게 되고 설치 과정이 다소 복잡하다. 도커를 이용하여 프로그램을 설치하면 예상치 못한 에러도 덜 발생하며, 설치하는 과정도 훨씬 간단해진다. </p>
<p><img src="https://blog.kakaocdn.net/dn/bQ9mjK/btqZQIHncOK/Iwtvfu2Qb2L5FNte2gOjS0/img.png" alt="https://blog.kakaocdn.net/dn/bQ9mjK/btqZQIHncOK/Iwtvfu2Qb2L5FNte2gOjS0/img.png"></p>
<h3 id="도커-이미지"><strong>도커 이미지</strong></h3>
<p>코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정과 같은 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하는 가볍고 독립적이며 실행 가능한 소프트웨어 패키지다. 또한 컨테이너 이미지는 런타임에 컨테이너가 되고 도커 컨테이너의 경우는 도커 엔진에서 실행될 때 이미지가 컨테이너가 된다. <strong>프로그램을 실행하는데 필요한 설정이나 종속성들을 갖고있다.</strong></p>
<h3 id="도커-컨테이너"><strong>도커 컨테이너</strong></h3>
<p>컨테이너는 코드와 모든 종속성을 패키지화하여 응용프로그램이 한 컴퓨팅 환경에서 다른 컴퓨팅 환경으로 빠르고 안정적으로 실행되도록 하는 소프트웨어의 표준 단위다. 컨테이너는 소프트웨어를 환경으로부터 격리시키고 개발과 스테이징의 차이에도 불구하고 균일하게 작동하도록 보장한다. <strong>이미지의 인스턴스이며, 프로그램을 실행한다.</strong></p>
<p><img src="https://velog.velcdn.com/images/ho-tae/post/0430d070-c461-4383-8e39-89793c16c615/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 읽기] AlexNet (2012) - Pytorch 구현]]></title>
            <link>https://velog.io/@ho-tae/%EB%85%BC%EB%AC%B8-%EC%9D%BD%EA%B8%B0-AlexNet-2012-Pytorch-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@ho-tae/%EB%85%BC%EB%AC%B8-%EC%9D%BD%EA%B8%B0-AlexNet-2012-Pytorch-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Sun, 23 Jan 2022 08:29:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>AlexNet 이론 정리에 이어서 이번글은 Pytorch로 직접 구현을 해봤다.
블로그 참고 및 Pytorch 함수들을 공부하면서 진행했다.</p>
</blockquote>
<h2 id="alexnet-model-구현">Alexnet model 구현</h2>
<h3 id="1-alexnet-모델-정의">1. AlexNet 모델 정의</h3>
<ul>
<li>구현에 쓰인 학습 데이터셋은 pytorch.datasets에 내장되어 있는 <a href="https://pytorch.org/vision/stable/datasets.html">FashionMNIST</a>를 사용했다.</li>
<li>논문과 다르게 입력 채널 수는 grey scale이므로 1, out_features는 데이터셋의 Class가 10개이므로 10이다.</li>
<li>모델을 정의하고 마지막에 summary로 Output shape와 parameter를 확인한다.</li>
</ul>
<pre><code class="language-python">import torch
import torch.nn as nn
import torch.nn.functional as F
from torchsummary import summary
from torchvision import transforms


class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=96, kernel_size=11, stride=4)
        self.conv2 = nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, padding=2)
        self.conv3 = nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, padding=1)
        self.conv4 = nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1)
        self.conv5 = nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1) # conv5와 fc1 사이에 view 들어간다.
        self.fc1 = nn.Linear(in_features=256 * 6 * 6, out_features=4096) # fc layer
        self.fc2 = nn.Linear(in_features=4096, out_features=4096)
        self.fc3 = nn.Linear(in_features=4096, out_features=10)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, kernel_size=3, stride=2)

        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, kernel_size=3, stride=2)

        x = F.relu(self.conv3(x))
        x = F.relu(self.conv4(x))
        x = F.relu(self.conv5(x))
        x = F.max_pool2d(x, kernel_size=3, stride=2)

        x = x.view(x.size(0), -1) # 4차원을 1차원으로 펼쳐주는 층 (역할) -&gt; flatten

        x = F.relu(self.fc1(x))
        x = F.dropout(x, p=0.5)

        x = F.relu(self.fc2(x))
        x = F.dropout(x, p=0.5)

        x = F.log_softmax(self.fc3(x), dim=1)

        return x 

    @staticmethod
    def transform():
        return transforms.Compose([transforms.Resize((227, 227)),
                                   transforms.ToTensor(),
                                   transforms.Normalize(mean=(0.1307,), std=(0.3081,))])
if __name__ == &quot;__main__&quot;: 
    # if gpu is to be used
    use_cuda = torch.cuda.is_available()
    print(&quot;use_cuda : &quot;, use_cuda)

    FloatTensor = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor
    device= torch.device(&quot;cuda:0&quot; if use_cuda else &quot;cpu&quot;)

    net = AlexNet().to(device)

    X = torch.randn(size=(1, 1, 227, 227)).type(FloatTensor)
    print(net(X))
    print(summary(net, (1, 227, 227))) </code></pre>
<h3 id="2-model-summary">2. Model summary</h3>
<p><img src="https://images.velog.io/images/ho-tae/post/5f6caf7f-01f7-4388-a8ec-d00322127c00/image.png" alt=""></p>
<h3 id="3-model-trainning-and-test">3. Model Trainning and Test</h3>
<pre><code class="language-python">if __name__==&quot;__main__&quot;:
    # hyper parameter
    batch_size = 512
    num_epochs = 20
    learning_rate = 0.0001

    # data load
    root = &#39;./MNIST_Fashion&#39;
    transform = AlexNet.transform()
    train_set = datasets.FashionMNIST(root=root, train=True, transform=transform, download=True)
    train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size, shuffle=True)
    test_set = datasets.FashionMNIST(root=root, train=False, transform=transform, download=True)
    test_loader = torch.utils.data.DataLoader(test_set, batch_size=batch_size, shuffle=True) 


    # if gpu is to be used 
    use_cuda = torch.cuda.is_available() 
    print(&quot;use_cuda : &quot;, use_cuda)
    device = torch.device(&quot;cuda:0&quot; if use_cuda else &quot;cpu&quot;)
    model = AlexNet().to(device)
    criterion = F.nll_loss
    optimizer = optim.Adam(model.parameters(), lr=learning_rate) 


    def train(model, device, train_loader, optimizer, epoch):
        model.train()
        for batch_idx, (data, target) in enumerate(train_loader):
            target = target.type(torch.LongTensor)
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            if (batch_idx + 1) % 30 == 0:
                print(&quot;Train Epoch:{} [{}/{} ({:.0f}%)]\tLoss: {:.6f}&quot;.format(
                    epoch, batch_idx * len(data), len(train_loader.dataset),
                    100. * batch_idx / len(train_loader), loss.item()))

    def test(model, device, test_loader):
        model.eval()
        test_loss = 0
        correct = 0
        with torch.no_grad():
            for data, target in test_loader:
                data, target = data.to(device), target.to(device)
                output = model(data)
                test_loss += criterion(output, target, reduction=&#39;sum&#39;).item() 
                pred = output.max(1, keepdim=True)[1]
                correct += pred.eq(target.view_as(pred)).sum().item()

            test_loss /= len(test_loader.dataset)
            print(&quot;\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n&quot;.format(
                test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset)))
            print(&#39;=&#39;*50)</code></pre>
<h3 id="4-accuracy-and-loss-check">4. Accuracy and loss check</h3>
<pre><code class="language-python">for epoch in range(1, num_epochs + 1):
    train(model, device, train_loader, optimizer, epoch)
    test(model, device, test_loader)</code></pre>
<p><img src="https://images.velog.io/images/ho-tae/post/08712b02-343e-4d5d-ab59-aff72f67b1c5/image.png" alt=""></p>
<p><strong>정확도 92%의 결과가 나왔다. 이것으로 Alexnet 구현을 완료했다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 읽기] AlexNet (2012) - 이론정리]]></title>
            <link>https://velog.io/@ho-tae/%EB%85%BC%EB%AC%B8-%EC%9D%BD%EA%B8%B0-AlexNet-2012-%EC%9D%B4%EB%A1%A0%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ho-tae/%EB%85%BC%EB%AC%B8-%EC%9D%BD%EA%B8%B0-AlexNet-2012-%EC%9D%B4%EB%A1%A0%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 17 Jan 2022 11:38:43 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>논문을 읽으면서 이해하는거에 초점을 두고 하나하나씩 접근하면 감이 올거라고 믿는다.
오늘부터 CNN의 기본, 기초인 AlexNet의 논문부터 차근차근 시작하려고 한다.</p>
</blockquote>
<h2 id="1-abstract">1. Abstract</h2>
<p><img src="https://images.velog.io/images/ho-tae/post/0cfdd574-4293-4a27-93f1-33afb94444cb/image.png" alt=""></p>
<ul>
<li>ImageNet LSVRC-2010 대회에서 1000개의 클래스의 120만 고해상도 이미지 분류를 위해 깊은 dnn을 훈련했고, 이 대회에서 테스트 데이터로 37.5%와 17.0%로 1등과 5등의 오류율을 달성했다. (Top 5 test error란 모델이 예측한 최상위 5개 범주 가운데 정답이 없는 경우의 오류율을 말한다.) </li>
<li>신경망은 6천만 개의 파라미터와 65만개의 뉴런, 5개의 convolutional layer로 구성되며 그 중 일부는 max-pooling 레이어, 3개의 fully-connected layers와 최종 1000-way softmax로 구성된다. </li>
<li>훈련 속도를 높이기 위해 non-saturating neurons과 GPU를 사용했고 fully-connected layers에서 overfitting을 줄이기 위해 drop-out의 정규화 방법까지 사용해 큰 효과를 얻었다고 한다.</li>
</ul>
<h2 id="2-the-dataset">2. The Dataset</h2>
<p><img src="https://images.velog.io/images/ho-tae/post/2ddaa221-fbd4-4fde-b583-81318bfc16d6/image.png" alt=""></p>
<h3 id="1-imagenet-dataset">1. ImageNet dataset</h3>
<ul>
<li>22,000개 범주로 구성되어 있고 1500만개의 고해상도 이미지가 포함되어있는 data set이다.
ILSVRC 대회는  ImageNet dataset의 subset을 이용하는데, 각 범주당 1000개의 이미지가 포함되어 있는 1000개 범주를 이용한다. 
따라서, 대략 120만개의 training 이미지와 50,000개의 validation 이미지, 150,000개의 testing 이미지로 구성되어있다.</li>
</ul>
<h3 id="2-data-preprocessing">2. data preprocessing</h3>
<ul>
<li><p>이미지를 동일한 크기(256x256)으로 고정시켜줬습니다. 나중에 FC layer의 입력 크기가 고정되어있어야 하기 때문입니다. 만약 입력 이미지의 크기가 다르다면 FC layer에 입력되는 feature 개수가 모두 다르게 됩니다.
resize 방법은 이미지의 넓이와 높이 중 더 짧은 쪽을 256으로 고정시키고 중앙 부분을 256x256 크기로 crop 해주었습니다.</p>
</li>
<li><p>각 이미지의 pixel에 traing set의 평균을 빼서 normalize 해주었습니다.</p>
</li>
</ul>
<h2 id="3-architecture">3. Architecture</h2>
<p><img src="https://images.velog.io/images/ho-tae/post/55ee33b0-001a-4bcb-9e78-9513ce1700e8/image.png" alt=""></p>
<ul>
<li>AlexNet은 일부가 max-pooling layer가 적용된 5개의 convolutional layer와 3개의 fully-connected layer로 이루어져있습니다. 
AlexNet은 [Input layer - Conv1 - MaxPool1 - Norm1 - Conv2 - MaxPool2 - Norm2 - Conv3 - Conv4 - Conv5 - Maxpool3 - FC1- FC2 - Output layer] 으로 구성되어 있습니다. </li>
</ul>
<h4 id="1-첫번째-레이어컨볼루션-레이어">1. 첫번째 레이어(컨볼루션 레이어)</h4>
<p>96개의 11 x 11 x 3 사이즈 필터커널로 입력 영상을 컨볼루션해준다. 컨볼루션 보폭(stride)를 4로 설정했고, zero-padding은 사용하지 않았다. zero-padding은 컨볼루션으로 인해 특성맵의 사이즈가 축소되는 것을 방지하기 위해, 또는 축소되는 정도를 줄이기 위해 영상의 가장자리 부분에 0을 추가하는 것이다. </p>
<p>결과적으로 55 x 55 x 96 특성맵(96장의 55 x 55 사이즈 특성맵들)이 산출된다. 그 다음에 ReLU 함수로 활성화해준다. 이어서 3 x 3 overlapping max pooling이 stride 2로 시행된다. </p>
<p>그 결과 27 x 27 x 96 특성맵을 갖게 된다. 그 다음에는 수렴 속도를 높이기 위해 local response normalization이 시행된다. local response normalization은 특성맵의 차원을 변화시키지 않으므로, 특성맵의 크기는 27 x 27 x 96으로 유지된다.</p>
<h4 id="2-두번째-레이어컨볼루션-레이어">2. 두번째 레이어(컨볼루션 레이어)</h4>
<p>256개의 5 x 5 x 48 커널을 사용하여 전 단계의 특성맵을 컨볼루션해준다. stride는 1로, zero-padding은 2로 설정했다. 따라서 27 x 27 x 256 특성맵(256장의 27 x 27 사이즈 특성맵들)을 얻게 된다. 역시 ReLU 함수로 활성화한다. 그 다음에 3 x 3 overlapping max pooling을 stride 2로 시행한다. </p>
<p>그 결과 13 x 13 x 256 특성맵을 얻게 된다. 그 후 local response normalization이 시행되고, 특성맵의 크기는 13 x 13 x 256으로 그대로 유지된다. </p>
<h4 id="3-세번째-레이어컨볼루션-레이어">3. 세번째 레이어(컨볼루션 레이어)</h4>
<p>384개의 3 x 3 x 256 커널을 사용하여 전 단계의 특성맵을 컨볼루션해준다. stride와 zero-padding 모두 1로 설정한다. 따라서 13 x 13 x 384 특성맵(384장의 13 x 13 사이즈 특성맵들)을 얻게 된다. 역시 ReLU 함수로 활성화한다. </p>
<h4 id="4-네번째-레이어컨볼루션-레이어">4. 네번째 레이어(컨볼루션 레이어)</h4>
<p>384개의 3 x 3 x 192 커널을 사용해서 전 단계의 특성맵을 컨볼루션해준다. stride와 zero-padding 모두 1로 설정한다. 따라서 13 x 13 x 384 특성맵(384장의 13 x 13 사이즈 특성맵들)을 얻게 된다. 역시 ReLU 함수로 활성화한다. </p>
<h4 id="5-다섯번째-레이어컨볼루션-레이어">5. 다섯번째 레이어(컨볼루션 레이어)</h4>
<p>256개의 3 x 3 x 192 커널을 사용해서 전 단계의 특성맵을 컨볼루션해준다. stride와 zero-padding 모두 1로 설정한다. 따라서 13 x 13 x 256 특성맵(256장의 13 x 13 사이즈 특성맵들)을 얻게 된다. 역시 ReLU 함수로 활성화한다. 그 다음에 3 x 3 overlapping max pooling을 stride 2로 시행한다. 그 결과 6 x 6 x 256 특성맵을 얻게 된다. </p>
<h4 id="6-여섯번째-레이어fully-connected-layer">6. 여섯번째 레이어(Fully connected layer)</h4>
<p>6 x 6 x 256 특성맵을 flatten해줘서 6 x 6 x 256 = 9216차원의 벡터로 만들어준다. 그것을 여섯번째 레이어의 4096개의 뉴런과 fully connected 해준다. 그 결과를 ReLU 함수로 활성화한다. </p>
<h4 id="7-일곱번째-레이어fully-connected-layer">7. 일곱번째 레이어(Fully connected layer)</h4>
<p>4096개의 뉴런으로 구성되어 있다. 전 단계의 4096개 뉴런과 fully connected되어 있다. 출력 값은 ReLU 함수로 활성화된다. </p>
<h4 id="8-여덟번째-레이어fully-connected-layer">8. 여덟번째 레이어(Fully connected layer)</h4>
<p>1000개의 뉴런으로 구성되어 있다. 전 단계의 4096개 뉴런과 fully connected되어 있다. 1000개 뉴런의 출력값에 softmax 함수를 적용해 1000개 클래스 각각에 속할 확률을 나타낸다.</p>
<h2 id="4-alexnet-구조에-적용된-특징">4. AlexNet 구조에 적용된 특징</h2>
<h3 id="1-relu-nonlinearity">1. ReLU Nonlinearity</h3>
<p><img src="https://images.velog.io/images/ho-tae/post/524323b4-a9bd-4c93-a6d6-d59291b1ca19/image.png" alt=""></p>
<p> 활성화 함수로 ReLU 를 적용했습니다. 논문에서는 saturating nonlinearity(tanh, sigmoid)보다 non-saturatung nonlinearity(ReLU)의 학습 속도가 몇배는 빠르다고 나와있습니다. 저자는 tanh와 Relu의 학습 속도를 비교하기 위해 실험결과를 논문에 담았습니다.</p>
<p>CNN으로 CIFAR-10 dataset을 학습시켰을 때 25% training error에 도달하는 ReLU와 tanh의 epoch수의 실험 결과 그림입니다. 4층의 CNN으로 CIFAR-10을 학습시켰을 때 ReLU가 tanh보다 6배 빠르다는 내용입니다.</p>
<h3 id="2-training-on-multiple-gpus">2. Training on Multiple GPUs</h3>
<p> <img src="https://images.velog.io/images/ho-tae/post/3705f4e1-c94d-4241-89d8-ff1028fa495c/image.png" alt=""> </p>
<p> network를 2개의 GPU로 나누어서 학습시켰습니다. 이를 GPU parallelization이라고 합니다. 저자는 120만개의 data를 학습시키기 위한 network는 하나의 GPU로 부족하다고 설명합니다. 2개의 GPU로 나누어서 학습시키니 top-1 erroe와 top-5 error가 1.7%, 1.2% 감소되었으며 학습속도도 빨라졌다고 말합니다. </p>
<p>예를 들어, 90개의 kernel이 있다고 하면 45개를 GPU 1에 할당하고 남은 45개를 GPU 2에 할당하여 학습합니다. 여기서 추가적인 기법이 있는데, 데이터를 두 개의 GPU로 나누어 학습시키다가 하나의 layer에서만 GPU를 통합시키는 것입니다.</p>
<p>논문에서는 3번째 Conv layer에서만 GPU를 통합시킨다고 말합니다. 이를 통해 계산량의 허용가능한 부분까지 통신량을 정확하게 조정할 수 있다고 나와있습니다. 위 그림은 GPU 1, GPU 2 각각에서 학습된 kernel map 입니다. GPU 1에서는 색상과 관련 없는 정보를 학습하고 GPU 2는 색상과 관련된 정보를 학습하는 것을 확인할 수 있습니다. 이처럼 각각의 GPU는 독립적으로 학습된다고 나와있습니다.</p>
<h3 id="3-local-response-normalizationlrn">3. Local Response Normalization(LRN)</h3>
<p>  LRN은 generalizaion을 목적으로 합니다. sigmoid나 tanh 함수는 입력 date의 속성이 서로 편차가 심하면 saturating되는 현상이 심해져 vanishing gradient를 유발할 수 있게 됩니다. 반면에 ReLU는 non-saturating nonlinearity 함수이기 때문에 saturating을 예방하기 위한 입력 normalizaion이 필요로 하지 않는 성질을 갖고 있습니다. ReLU는 양수값을 받으면 그 값을 그대로 neuron에 전달하기 때문에 너무 큰 값이 전달되어 주변의 낮은 값이 neuron에 전달되는 것을 막을 수 있습니다. 이것을 예방하기 위한 normalization이 LRN 입니다.</p>
<p> 논문에서는 LRN을 측면 억제(later inhibition)의 형태로 구현된다고 나와 있습니다. 측면 억제는 강한 자극이 주변의 약한 자극을 전달하는 것을 막는 효과를 말합니다.</p>
<p> 위 그림은 측면 억제의 유명한 그림인 헤르만 격자입니다. 검은 사각형안에 흰색의 선이 지나가고 있습니다. 신기한 것은 흰색의 선에 집중하지 않을 때 회식의 점이 보이는데 이러한 현상이 측면 억제에 의해 발생하는 것입니다. 이는 흰색으로 둘러싸인 측면에서 억제를 발생시키기 때문에 흰색이 더 반감되어 보입니다.</p>
<p> AlexNet에서 LRN을 구현한 수식을 살펴보겠습니다.</p>
<p> <img src="https://images.velog.io/images/ho-tae/post/bddcc754-5e87-4b70-92c8-957e8f9a90c5/image.png" alt=""></p>
<p> a는 x,y 위치에 적용된 i번째 kernel의 output을 의미하고 이 a를 normalization하여 큰 값이 주변의 약한 값에 영향을 주는 것을 최소화 했다고 나와 있습니다. 이러한 기법으로 top-1와 top-5 eroor를 각각 1.4%, 1.2% 감소시켰다고 합니다.</p>
<p> 하지만 AlexNet 이후 현대의 CNN에서는 local response normalization 대신 batch normalization 기법이 쓰인다고 한다.</p>
<h3 id="4-overlapping-pooling">4. Overlapping Pooling</h3>
<p> <img src="https://images.velog.io/images/ho-tae/post/79cd8739-866a-4a6a-b275-69287b9bd625/image.png" alt=""></p>
<p>  Overlapping pooling을 통해서 overfit을 방지하고 top-1와 top-5 error를 각각 0.4%, 0.3% 낮추었다고 말합니다.</p>
<p> Pooling layer은 동일한 kernel map에 있는 인접한 neuron의 output을 요약해줍니다.  전통적으로 pooling layer는 overlap하지 않지만 
 AlexNet은 overlap을 해주었습니다. kernel size는 3, stride는 2를 이용해서 overlap을 해주었다고 나와있습니다.</p>
<h3 id="5-dropout">5. Dropout</h3>
<p><img src="https://images.velog.io/images/ho-tae/post/36ad07a7-e84a-4b0c-ae37-5c8662ce3e63/image.png" alt="">
서로 다른 모델의 예측을 결합하는 앙상블 기법은 test error를 감소시키기 효과적인 방법입니다. 하지만 AlexNet은 학습시키는데에 몇일이 걸려 이것을 적용하기가 힘들었다고 합니다. 따라서 모델 결합의 효과적인 버전인 dropout을 적용시켰다고 합니다.</p>
<p> dropout의 확률을 0.5로 설정하고 dropout된 neuron은 순전파와 역전파에 영향을 주지 않습니다. 매 입력마다 dropout을 적용시키면 가중치는 공유되지만 신경망은 서로 다른 구조를 띄게 됩니다. neuron은 특정 다른 neuron의 존재에 의존하지 않기 때문에 이 기법은 복잡한 neuron의 co-adaptation를 감소시킨다고 말합니다. 그러므로 서로 다른 neuron의 임의의 부분 집합끼리 결합에 유용한 robust 특징을 배울 수 있다고 말합니다.</p>
<p> train에서 dropout을 적용시켰고 test에는 모든 neuron을 사용했지만 neuron의 결과값에 0.5 곱해주었다고 합니다.</p>
<p> 또한 AlexNet은 두 개의 FC layer에만 dropout을 적용하였습니다. dropout을 통해 overfitting을 피할 수 있었고, 수렴하는데 필요한 반복수는 두 배 증가되었다고 나와있습니다.</p>
<h3 id="6-data-augmentation">6. Data Augmentation</h3>
<p><img src="https://images.velog.io/images/ho-tae/post/3d4ba638-b6af-45db-b0df-ad91ac5ca82c/image.png" alt=""></p>
<p>Data Augmentation은 현재 갖고 있는 데이터를 좀 더 다양하게 만들어 CNN 모델을 학습시키기 위해 만들어진 개념입니다. 이러한 기법은 적은 노력으로 다양한 데이터를 형성하게하여 overfitting을 피하게 만들어 줍니다. 또한 data augmentation의 연산량은 매우 적고 CPU에서 이루어지기 때문에 계산적으로 부담이 없다고 말합니다.</p>
<p> 논문에서 2가지 data augmentation 를 적용했다고 나와있습니다.</p>
<h4 id="1-generating-image-translation-and-horizontal-reflections">1. generating image translation and horizontal reflections</h4>
<p> 이미지를 생성시키고 수평 반전을 해주었다고 합니다. 어떻게 적용하였는지 알아보겠습니다.</p>
<p> 256x256 이미지에서 224x224 크기로 crop을 합니다. crop 위치는 중앙, 좌측 상단, 좌측 하단, 우측 상단, 우측 하단 이렇게 5개의 위치에서 crop을 합니다. crop으로 생성된 5개의 이미지를 horizontal reflection을 합니다. 따라서 하나의 이미지에서 10개의 이미지가 생성됩니다.</p>
<h4 id="2-altering-the-intensities-of-the-rgb-channels-in-training-images">2. altering the intensities of the RGB channels in training images</h4>
<p> image의 RGB pixel 값에 변화를 주었습니다. 어떻게 변화를 주었고 어떤 효과가 있었는지 알아보겠습니다.</p>
<p> ImageNet의 training set에 RGB pixel 값에 대한 PCA를 적용했습니다. PCA를 수행하여 RGB 각 생상에 대한 eigenvalue를 찾습니다. eigenvalue와 평균 0, 분산 0.1인 가우시안 분포에서 추출한 랜덤 변수를 곱해서 RGB 값에 더해줍니다.
 <img src="https://images.velog.io/images/ho-tae/post/3cd7ea74-be93-4335-967e-56f03ac546b0/image.png" alt=""></p>
<p> 이를 통해 조명의 영향과 색의 intensity 변화에 대한 불변성을 지닌다고 합니다. 이 기법으로 top-1 error를 1% 낮추었다고 합니다.</p>
<p>** 이것으로 AlexNet의 이론정리는 끝냈습니다. 다음은 Pytorch로 구현을 진행하겠습니다.**</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩 연습][Python 문법] 빠른 A+B, 파이썬 입력 받기(sys.stdin.readline)]]></title>
            <link>https://velog.io/@ho-tae/%EC%BD%94%EB%94%A9-%EC%97%B0%EC%8A%B5Python-%EB%AC%B8%EB%B2%95-%EB%B9%A0%EB%A5%B8-AB-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EA%B8%B0sys.stdin.readline</link>
            <guid>https://velog.io/@ho-tae/%EC%BD%94%EB%94%A9-%EC%97%B0%EC%8A%B5Python-%EB%AC%B8%EB%B2%95-%EB%B9%A0%EB%A5%B8-AB-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EA%B8%B0sys.stdin.readline</guid>
            <pubDate>Sun, 16 Jan 2022 06:42:52 GMT</pubDate>
            <description><![CDATA[<h2 id="⌨️-백준-코딩-15552번">⌨️ 백준 코딩 15552번</h2>
<p><img src="https://images.velog.io/images/ho-tae/post/aff12bc8-e0c8-48cd-8036-10c8023e1d76/image.png" alt=""></p>
<blockquote>
<p>문제를 푸는 중 Python을 사용하고 있다면, input 대신 sys.stdin.readline 을 사용하고, 개행문자까지 같이 입력받기 때문에 문자열을 저장하고 싶을 경우 .rsstrip() 을 추가로 해주라고 써있었다.</p>
</blockquote>
<p>하지만 기존 방법으로 코드 작성을 먼저 해보고 문제에서 주어진 함수를 이용하여 코드 작성과 파이썬 내장함수를 공부해보려고 한다.</p>
<h3 id="1-기존-코드">1. 기존 코드</h3>
<pre><code class="language-python">a = int(input())

for _ in range(a):
    b,c = map(int, input().split())
    print(b+c)</code></pre>
<p>기존 방법으로 작성한 코드를 제출하면, 채점중으로 나오면서 시간이 지난 후에는 &#39;시간초과&#39; 라는 문구가 나온다. 반복문으로 여러 줄을 입력받아서 출력할 때 문제에서 나온것처럼 시간 초과가 났다는 것이다. 따라서 sys.stdin.readline을 사용해봤다.</p>
<h3 id="2-변경-코드">2. 변경 코드</h3>
<pre><code class="language-python">import sys

T = int(input())
for _ in range(T):
    a,b = map(int, sys.stdin.readline().split())
    print(a+b)</code></pre>
<p><img src="https://images.velog.io/images/ho-tae/post/a6ee847b-679a-4ed2-a31e-de7eafc4137b/image.png" alt=""></p>
<h3 id="3-python-내장함수-map">3. python 내장함수 map()</h3>
<h4 id="mapfunction-iterable">map(function, iterable)</h4>
<p>map 함수의 모양은 위와 같다.
첫 번째 매개변수로는 함수가 오고
두 번째 매개변수로는 반복 가능한 자료형(리스트, 튜플 등)이 온다.</p>
<p>map 함수의 반환 값은 map객체 이기 때문에 해당 자료형을 list 혹은 tuple로 형 변환시켜주어야 한다.</p>
<p>함수의 동작은 두 번째 인자로 들어온 반복 가능한 자료형 (리스트나 튜플)을 첫 번째 인자로 들어온 함수에 하나씩 집어넣어서 함수를 수행하는 함수이다.</p>
<p>map(적용시킬 함수, 적용할 값들) 이런 식인 거죠.
예를 들어 map(값에 2를 곱해주는 함수, [1,2,3,4,5]) 함수의 반환을 list(. )로 감싸주면 [2,4,6,8,10] 이 되는 함수이다.</p>
<pre><code class="language-python">myList = [1, 2, 3, 4, 5]

def multiply_two(n):
    return 2 * n

result = list(map(multiply_two, myList))
print(f&#39;result : {result}&#39;)</code></pre>
<p><img src="https://images.velog.io/images/ho-tae/post/e90404f4-4a1a-4296-9e5b-7351f5da97d1/image.png" alt=""></p>
<h3 id="4-sysstdinreadline">4. sys.stdin.readline()</h3>
<p>일단, sys 모듈은 Python 인터프리터가 제공하는 변수와 함수를 직접 제어할 수 있게 해주는 모듈이다. stdin 은 Python 인터프리터가 표준 입력에 사용하는 파일 객체, readline() 은 파일 객체의 메소드 중 하나로 read(), readlines() 와 같이 파일 객체를 읽을 때 사용한다.
즉, sys.stdin.readline() 은 sys 라는 모듈의 파일 객체 stdin 의 메소드 중 readline() 을 사용 한다는 의미이다. readline() 은 입력을 읽을 때 한 번에 한 줄씩 읽는데, 이 말은 여러 줄의 입력이 있을 때 한 줄을 읽고 나면 그 다음 줄을 가리킨다는 뜻이다.</p>
<h4 id="sysstdinreadline-사용법">sys.stdin.readline() 사용법</h4>
<p><strong>1. 문자열을 받을 때</strong></p>
<pre><code class="language-python">import sys

sentence = sys.stdin.readline()</code></pre>
<p>sys.stdin.readline()은 return값이 문자열이므로 그냥 문장을 하나 받을 때 사용가능하다.
sys.stdin.readline()을 출력하면 문자열에 개행문자(\n)가 기본으로 추가됨도 확인 가능하다.</p>
<p><strong>2. 정수를 받을 때</strong></p>
<pre><code class="language-python">import sys

number = int(sys.stdin.readline())</code></pre>
<p>그냥 sys.stdin.readline()의 return 값은 문자열(string)이기 때문에 정수로 입력받으려면 형변환을 해줘야한다.
sys.stdin.readline()으로 받은 문자열은 개행문자(\n)을 포함한다.
문자열을 int()로 형변환을 해주면 개행문자는 사라지고 정수형태만 남는다.</p>
<p><strong>3. 여러 개의 정수들을 받을 때</strong></p>
<pre><code class="language-python">import sys

a,b = map(int,sys.stdin.readline().split())</code></pre>
<p>map()은 반복 가능한 객체(리스트 등)에 대해 각각의 요소들을 지정된 함수로 처리해주는 함수입니다. 위와 같이 사용한다면 a,b,c에 대해 각각 int형으로 형변환을 할 수 있습니다.</p>
<p><strong>4. 문자열 N개를 입력 받아 리스트에 저장할 때</strong></p>
<pre><code class="language-python">import sys
n = int(sys.stdin.readline())
data = [sys.stdin.readline().strip() for i in range(n)]</code></pre>
<p>문자열을 N개 라고 지정되어있는 경우 for문을 사용해 문자열 N개를 리스트에 저장할 수 있다. 여기서 strip()은 문자열 앞과 끝의 공백문자를 제거해주는 함수다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩 연습] 백준 코딩 단계별 연습]]></title>
            <link>https://velog.io/@ho-tae/%EB%B0%B1%EC%A4%80-%EC%BD%94%EB%94%A9-%EB%8B%A8%EA%B3%84%EB%B3%84-%EC%97%B0%EC%8A%B5</link>
            <guid>https://velog.io/@ho-tae/%EB%B0%B1%EC%A4%80-%EC%BD%94%EB%94%A9-%EB%8B%A8%EA%B3%84%EB%B3%84-%EC%97%B0%EC%8A%B5</guid>
            <pubDate>Sun, 09 Jan 2022 13:47:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<p>오늘 집에서 쉬는 날이라 백준코딩 단계별 문제풀이를 진행했다.
학원 6개월 과정을 거치고 입사를 했는데 어느정도 코딩을 배우고 갔지만 아직 너무 부족하다고 생각이 들어서 공부해야지 공부해야지~ 생각했던게 벌써 몇개월이 흐르다니 회사일에서는 일단 object detection 위주로 공부하거나 일을 했으니 이제 딥하게 코드 공부도 같이 진행해야겠다. 보통 딥러닝 개발자들은 데이터를 원하는 형식으로 바꾸는 전처리 작업을 많이 하는거 같다.. 나도 내가 원하는 coco json 형식의 라벨링 데이터로 어떤 형식의 데이터가 있어도 바꾸는 전처리 코드를 다 작성한거 같다 ㅋㅋㅋㅋ</p>
<h4 id="간단하게-정리하자면-bbox-좌표가-어떻게-들어가는지만-잘-알면-쉽게-바꿀수있다">간단하게 정리하자면 bbox 좌표가 어떻게 들어가는지만 잘 알면 쉽게 바꿀수있다.</h4>
<ol>
<li>yolo to coco json</li>
<li>visdrone to coco json</li>
<li>AIhub to coco json (AI허브 데이터)</li>
<li>geojson to coco json</li>
<li>manifest to coco json</li>
<li>dota to coco json
.
.
.</li>
</ol>
<p>단계별 학습 초반은 쉬워서 그냥 쉽게 쉽게 잘 풀었던거 같다. 구글링 없이 간단하게 풀었다. 일주일에 3개 이상의 문제를 푸는것으로 목표를 잡아야겠다.</p>
<p>그리고 백준 코딩하면서 느낀게 문제를 잘 봐야하는거 같다.. 입력을 받을때 공백으로 받는게 있는것이 대부분이라 아무 생각없이 진행했는데, 어느 문제에서는 자세하게 안보고 하다가 자꾸 value error가 나와서 뭔가했는데 알고보니 공백으로 input을 받는게 아니라 붙여서 받아서 코드 자체 문제가 아니라 공백을 없애줘야했다. 이제 모르는 문제가 나오면 고민도 하면서 풀어보고 특정 함수를 어떻게 어떤방식으로 적용해야 할지를 머리속에 잘 정리해서 내것으로 만들어야겠다. 화이팅!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[처음 만들었으니 끄적여봄!!]]></title>
            <link>https://velog.io/@ho-tae/%EC%B2%98%EC%9D%8C-%EB%A7%8C%EB%93%A4%EC%97%88%EC%9C%BC%EB%8B%88-%EB%81%84%EC%A0%81%EC%97%AC%EB%B4%84</link>
            <guid>https://velog.io/@ho-tae/%EC%B2%98%EC%9D%8C-%EB%A7%8C%EB%93%A4%EC%97%88%EC%9C%BC%EB%8B%88-%EB%81%84%EC%A0%81%EC%97%AC%EB%B4%84</guid>
            <pubDate>Fri, 31 Dec 2021 01:51:49 GMT</pubDate>
            <description><![CDATA[<p>인공지능 개발자로 취업한 지 5개월이 끝나고 내년을 바라보는 중</p>
<p>나도 개발자로서 블로그 운영도 해보고 이것저것 포트폴리오 준비 및 활동하고 싶어서 벨로그를 만들었다.</p>
<p>공부한 내용 및 정리를 앞으로 블로그를 통해 진행해야지~</p>
<p>내년의 나는 올해의 나보다 성장하여 멋진 인공지능 개발자가 되기를 희망하며 끄적여본다~</p>
<p>열심히 논문 읽기, 코드 공부, 회사 일 3개 다 쟁취해서 성장해보자~ 아직은 baby 개발자 ㅋㅋㅋㅋ</p>
]]></description>
        </item>
    </channel>
</rss>