<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dj_.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 23 Sep 2024 09:17:04 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. dj_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dj_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[ORM]]></title>
            <link>https://velog.io/@dj_/ORM</link>
            <guid>https://velog.io/@dj_/ORM</guid>
            <pubDate>Mon, 23 Sep 2024 09:17:04 GMT</pubDate>
            <description><![CDATA[<h3 id="orm이란">ORM이란</h3>
<ul>
<li>ORM(Object-Relational Mapping)이란 DB의 테이블을 프로그래밍 언어의 class로, 테이블의 row들을 객체(instance)로 매핑하는 기술을 의미하며, 이를 통해 직접 SQL 문을 작성하지 않고도 DB와 상호작용할 수 있습니다. </li>
<li>예시로 User 테이블을 python class로 작성하면 아래와 같습니다. <pre><code class="language-python">class User(Base):
  __tablename__ = &#39;users&#39;
  id = Column(Integer, primary_key=True)
  name = Column(String) 
  age = Column(Integer)</code></pre>
</li>
<li>ORM은 기본적으로 객체 지향적인 방식으로 데이터를 다루게 해줍니다. 또한 SQL이 아니라 python backend를 사용한다면 python code로 작성이 가능하게 해주기때문에, 일관성이 유지되며 코드로 통합되므로 유지 보수도 용이합니다. </li>
<li>또한, DB와 독립적이기때문에 다양한 DB 엔진(MySQL, PostgreSQL)을 사용하기에 적합합니다. 즉, DB 엔진이 바뀌어도 크게 문제되지 않습니다. </li>
<li>하지만 SQLAlchemy같은 라이브러리를 통해 SQL문이 자동 생성되는 방식이기 때문에 복잡한 쿼리는 최적화가 잘 되어있지 않을 수 있고, 그에 따라 비효율적일 수 있습니다. </li>
</ul>
<h3 id="sqlalchemy-pydantic">SQLAlchemy, Pydantic</h3>
<ul>
<li>SQLAlchemy는 python backend를 사용한다면 자주 사용되는 라이브러리로, python class로 DB 테이블 정보를 매핑할 수 있습니다. </li>
<li>Pydantic은 FastAPI를 사용한다면 자연스럽게 사용하게 되는 라이브러리로, 데이터 검증과 직렬화를 수행할 수 있습니다. </li>
<li>둘을 함께 사용하는 방식은 아래와 같습니다. </li>
</ul>
<ol>
<li>Pydantic을 사용해 요청 데이터 검증 </li>
<li>SQLAlchemy를 사용해 DB에 데이터 저장 </li>
<li>Backend 라이브러리를 통해 최종 결과 반환 </li>
</ol>
<ul>
<li>그 예시는 아래와 같습니다. </li>
<li>ORM 라이브러리, 그리고 Pydantic을 함께 사용함으로써, DB를 코드로 통합하여 관리할 수 있습니다.<pre><code class="language-python">from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
from .database import engine, SessionLocal, Base
from sqlalchemy import Column, Integer, String
</code></pre>
</li>
</ul>
<p>app = FastAPI()</p>
<h1 id="sqlalchemy-모델">SQLAlchemy 모델</h1>
<p>Base.metadata.create_all(bind=engine)</p>
<p>class User(Base):
    <strong>tablename</strong> = &quot;users&quot;
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    age = Column(Integer)</p>
<h1 id="pydantic-모델">Pydantic 모델</h1>
<p>class UserCreate(BaseModel):
    name: str
    age: int</p>
<h1 id="데이터베이스-세션">데이터베이스 세션</h1>
<p>def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()</p>
<h1 id="사용자-생성-api">사용자 생성 API</h1>
<p>@app.post(&quot;/users/&quot;, response_model=UserCreate)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    db_user = User(name=user.name, age=user.age)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Lookahead Optimizer]]></title>
            <link>https://velog.io/@dj_/Lookahead-Optimizer</link>
            <guid>https://velog.io/@dj_/Lookahead-Optimizer</guid>
            <pubDate>Sun, 22 Sep 2024 10:59:50 GMT</pubDate>
            <description><![CDATA[<h3 id="lookahead">Lookahead</h3>
<ul>
<li>optimizer보다는 기존 optimizer에 덧붙여서 사용하는 기법이라고 볼 수 있다. </li>
<li>개념은 간단합니다. k번의 업데이트를 미리 진행하고, 최종 weight는 k번 업데이트된 weight를 따라가도록 업데이트됩니다.<br><img src="https://velog.velcdn.com/images/dj_/post/38ab6e74-b8a7-4911-b0eb-ee63f34f05c1/image.png" alt=""></li>
<li>그림에서 theta와 파이가 각각 fast weight, slow weight라고 명시되어 있습니다. </li>
<li>fast weight는 k번의 step을 미리 가볼, 즉 미리 업데이트해보는 weight이고, slow wegiht는 최종으로 사용할 weight입니다. </li>
<li>k번의 업데이트를 먼저 수행하고, 최종 weight는 그것을 따라가게 함으로써, weight 업데이트에서 겪는 진동현상을 겪지 않고 안정적인 방향으로 나아갈 수 있습니다. </li>
<li>그림에서 보이듯이 파란색의 업데이트 과정들을 수행하고, 최종 weight는 k번 이후의 목적지 방향으로 바로 움직일 수 있기때문에 학습 과정의 진동이나 local minima 문제를 피할 수 있습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/37519ad0-906a-4d4f-8bed-40b533ec6c3b/image.png" alt="">
<img src="https://velog.velcdn.com/images/dj_/post/492ba726-1960-4ef6-8f46-8f4b29cccec5/image.png" alt=""></li>
<li>논문의 실험으로 보이듯이, lookahead를 사용했을 때 train loss로 보아 학습이 더 잘되는 것을 알 수 있습니다. </li>
<li>또한, 기존 Adam보다 성능도 좋아지는 것을 볼 수 있습니다. </li>
</ul>
<h3 id="ranger-optimizer">RANGER optimizer</h3>
<ul>
<li>RAdam optimizer에 대해서는 다룬 적이 있는데요, Adam의 분산문제를 보완한 optimizer입니다. </li>
<li>RANGER는 이러한 RAdam과 Lookahead를 결합한 optimizer로 현재 가장 자주 쓰이는 optimizer조합 중 하나입니다. </li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://arxiv.org/pdf/1907.08610#page=10&amp;zoom=100,144,604">https://arxiv.org/pdf/1907.08610#page=10&amp;zoom=100,144,604</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RAdam optimizer]]></title>
            <link>https://velog.io/@dj_/RAdam-optimizer</link>
            <guid>https://velog.io/@dj_/RAdam-optimizer</guid>
            <pubDate>Fri, 20 Sep 2024 09:56:05 GMT</pubDate>
            <description><![CDATA[<h3 id="adam-optimizer-단점">Adam optimizer 단점</h3>
<ul>
<li><p>Adam optimizer는 준수한 성능을 보이지만, 이동 평균을 이용하기 때문에 batch sample이 충분히 쌓이지 않은 학습 초기에는 문제가 있을 수 있습니다. </p>
</li>
<li><p>특히 분산의 이동 평균에서 문제가 생길 수 있는데, sample이 충분히 쌓이지 않으면 분산 값이 매우 커지는 문제가 있습니다. </p>
</li>
<li><p>그렇게 되면 Adam의 수식 상 learning rate가 매우 작아지게 되고, local optima에서 학습이 종료될 수 있습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/78d2d67b-1e00-4ebe-b3c6-21b5299e0632/image.png" alt=""></p>
</li>
<li><p>RAdam 논문의 실험을 살펴봅시다. 
<img src="https://velog.velcdn.com/images/dj_/post/f1552ed5-21ce-45ba-81cc-14f73e63d065/image.png" alt=""></p>
</li>
<li><p>일단은 warmup을 신경쓰지 않고 왼쪽 그림을 살펴봅시다. x축이 gradient value이고, y축이 iteration 그리고 z축이 파라미터 개수라고 생각하면 됩니다. </p>
</li>
<li><p>10 update만에 gradient값들이 매우 작은 값들로 수렴되는 것을 볼 수 있습니다. 이처럼 Adam은 초기에 분산이 매우 크기때문에 learning rate가 매우 작아져 local minima에 빠져 학습이 종료될 수 있음을 보여줍니다. </p>
</li>
<li><p>이를 해결하기 위해 보통은 warm-up 방식을 사용하게 되는데요, 이는 학습 초기에 sample들이 쌓이기 전까지 작은 learning rate들을 적용하는 것을 말합니다. 예를 들어, adam의 이동평균 식을 사용하지 않고, learning rate를 linear하게 매우 작은 값에서 시작할 learning rate값까지 상승시키면서 sample 수를 쌓을 시간을 가지는 것입니다.</p>
</li>
<li><p>그러한 warm-up을 거치게 되면 오른쪽 그림처럼 안정적인 학습 과정을 볼 수 있지만, 실험하는 입장에서는 hyper parameter가 하나 더 늘어난셈이 됩니다. </p>
</li>
</ul>
<h3 id="radam-rectified-adam">RAdam (Rectified Adam)</h3>
<ul>
<li><p>RAdam은 이러한 adam의 초기 분산 문제를 해결하기 위해 rectification term을 추가한 optimizer입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/72defc9b-bf41-4b6e-8d2a-108dc6952d46/image.png" alt=""></p>
</li>
<li><p>위 그림이 전체 알고리즘입니다. </p>
</li>
<li><p>자유도라는 개념이 등장하는데요, 이는 통계학에서 많이 사용되는 용어로 여기서는 학습이 얼마나 진행되었는지를 판단하는 값으로 생각하시면 됩니다. </p>
</li>
<li><p>이 자유도라는 값이 4이하일 때에는 sample이 많이 쌓이지 않았기 때문에, 분산값을 사용하지 않고 momentum만으로 학습을 진행합니다. </p>
</li>
<li><p>그 후, 충분한 sample이 쌓인 자유도_t가 4 초과일 때에는 rectified term을 곱해주게 됩니다. 
<img src="blob:https://velog.io/01c082a0-aaa2-42d9-a8e6-34994aff9020" alt="업로드중.."></p>
</li>
<li><p>위의 수식과 같은 rectified term을 추가합니다. </p>
</li>
<li><p>여기서 p_t는 step t에서의 자유도로 4초과의 값을 가지는 값입니다. 그리고 p_infinity는 학습이 충분히 되었을 때의 자유도로 beta값을 이용해 도출되며, 0.999의 경우 2000이라고 합니다. </p>
</li>
<li><p>즉, 해당 식은 충분히 학습이 진행될수록 1에 가까워 지는 값이라고 생각하면 됩니다. 그 전에는 step에 따라 가중치를 부여한다고 생각하면 됩니다. </p>
</li>
<li><p>이러한 과정을 통해 초기 분산값에 대한 대처를 하고, 충분히 학습되었을 때(수식이 1이 되었을 때)부터는 기존의 Adam과 같은 식으로 learning rate가 설정됨을 알 수 있습니다. </p>
</li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://arxiv.org/pdf/1908.03265">https://arxiv.org/pdf/1908.03265</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Optimization 방법론 (1)]]></title>
            <link>https://velog.io/@dj_/Optimization-%EB%B0%A9%EB%B2%95%EB%A1%A0-1</link>
            <guid>https://velog.io/@dj_/Optimization-%EB%B0%A9%EB%B2%95%EB%A1%A0-1</guid>
            <pubDate>Thu, 19 Sep 2024 14:23:02 GMT</pubDate>
            <description><![CDATA[<h3 id="gradient-descent">Gradient Descent</h3>
<ul>
<li>전체 데이터에 대해서 미분값 계산 및 업데이트 </li>
</ul>
<h3 id="stochastic-gradient-descent">Stochastic Gradient Descent</h3>
<ul>
<li>전체 데이터가 아니라, 하나하나의 sample마다 업데이트를 진행하는 방식입니다. </li>
<li>하나씩 계산하기 때문에 학습 속도가 빠르다는 장점이 있지만, 기울기가 매번 달라 학습 방향이 잘못될 수 있어, 학습이 진동하고 수렴이 더딜 수 있습니다.</li>
</ul>
<h3 id="mini-batch-gradient-descent">Mini-batch Gradient Descent</h3>
<ul>
<li>GD와 SGD의 장점을 합친 방식으로 여러 개의 sample을 합쳐 mini-batch 형태로 미분값을 계산해 업데이트합니다. </li>
<li>학습 속도가 GD보다 빠르며, 기울기가 SGD보다 안정적이기 때문에 진동이 덜하고 수렴도 빠릅니다. </li>
<li>하지만, batch 크기마다 성능이 다를 수 있습니다. </li>
<li>요즘은 mini-batch GD를 그냥 SGD라고 부릅니다. </li>
</ul>
<h3 id="momentum">Momentum</h3>
<ul>
<li>말 그대로 관성을 이용하는 방식으로, 이전 기울기와 현재 기울기의 가중 평균을 통해 업데이트 하는 방식입니다.</li>
<li>이전 기울기도 사용하기 때문에, 기울기의 방향이 많이 바뀌지 않아 진동이 적고 기울기에 가속을 가하기 때문에 local minima에 빠지는 문제를 보완할 수 있습니다. 또한 수렴 속도도 더 빠르게 됩니다. 
<img src="https://velog.velcdn.com/images/dj_/post/1cf2b8ba-d9ca-4b03-9cd0-d3b6ca2ad199/image.png" alt=""></li>
</ul>
<h3 id="nesterov-accelerated-gradient">Nesterov Accelerated Gradient</h3>
<ul>
<li>momentum은 이전 기울기가 잘못되었을 경우, 학습이 망가질 가능성이 있습니다. </li>
<li>이러한 문제를 해결하기 위해 NAG가 등장했습니다. </li>
<li>momentum을 이용해 parameter를 업데이트한 위치에서 다시 미분값을 구해 현재 파라미터를 업데이트 하는 방식으로, 잘못된 기울기를 다시 바로잡는 방향으로 움직인다고 생각하면 됩니다. 
<img src="https://velog.velcdn.com/images/dj_/post/6fecaa74-1cb7-49ac-817d-98b111dbf446/image.png" alt=""></li>
</ul>
<p><img src="https://velog.velcdn.com/images/dj_/post/bec0e254-babc-423e-8b64-96e015de6b1f/image.png" alt=""></p>
<h3 id="adagrad">AdaGrad</h3>
<ul>
<li>여기부터는 learning rate 관련 방식들입니다. </li>
<li>기울기의 방향도 중요하지만, learning rate의 설정에 따라 학습의 결과는 매우 달라질 수 있습니다. </li>
<li>AdaGrad는 하나의 learning rate로 모든 파라미터를 업데이트하는 것이 아닌, 파라미터별로 다른 learning rate를 두어야 한다는 아이디어입니다. </li>
<li>파라미터별로 얼마나 학습되었는지의 대한 양을 기록해두고, 많이 학습된 파라미터는 이미 수렴이 되었을 가능성이 있으니 learning rate를 줄이고, 반대는 늘리는 방식입니다. </li>
<li>따라서 지금까지 변화한 양(기울기의 제곱 누적합)을 저장해두고, 각 파라미터마다 이를 활용해 learning rate를 조절합니다. 
<img src="https://velog.velcdn.com/images/dj_/post/40789b06-7ac1-4dc2-a728-80e4befbc78b/image.png" alt=""></li>
</ul>
<h3 id="rmsprop">RMSProp</h3>
<ul>
<li>AdaGrad의 기울기 누적합은 계속해서 커질 것이고, 그에 따라 learning rate는 대부분 0이 될 것입니다. </li>
<li>이를 해결하기 위해 RMSProp이 나왔으며, 누적합이 아니라 이동평균을 사용함으로써 현재 기울기에 맞게 일정 수준으로 learning rate를 바꿉니다. 
<img src="https://velog.velcdn.com/images/dj_/post/c34fced2-03e4-4082-90e5-0a4ff03f7ec1/image.png" alt=""></li>
</ul>
<h3 id="adam">Adam</h3>
<ul>
<li>momentum과 RMSProp을 조합한 방식입니다. </li>
<li>기울기를 momentum처럼 이동 평균으로 구하고, learning rate도 기울기 누적의 이동 평균을 통해 수정합니다. 
<img src="https://velog.velcdn.com/images/dj_/post/0628381d-0fbd-4391-a76c-ee278722c5d0/image.png" alt=""></li>
<li>초기에는 이전 기울기가 없기 때문에 m과 g가 0이 될 가능성이 많으므로, m_hat과 g_hat을 사용합니다. </li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://medium.com/analytics-vidhya/welcome-to-the-second-part-on-optimisers-where-we-will-be-discussing-momentum-and-nesterov-c2698d5590e">https://medium.com/analytics-vidhya/welcome-to-the-second-part-on-optimisers-where-we-will-be-discussing-momentum-and-nesterov-c2698d5590e</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MLE 에서 cross-entropy ]]></title>
            <link>https://velog.io/@dj_/MLE-%EC%97%90%EC%84%9C-cross-entropy</link>
            <guid>https://velog.io/@dj_/MLE-%EC%97%90%EC%84%9C-cross-entropy</guid>
            <pubDate>Fri, 13 Sep 2024 10:18:16 GMT</pubDate>
            <description><![CDATA[<h3 id="mle-복기">MLE 복기</h3>
<ul>
<li>Maximum Likelihood Estimation(MLE)는 다른 글에서도 다뤘는데요, 정리해보면 확률 분포를 고정해두고, 주어진 데이터에 알맞은 확률 분포의 파라미터는 찾는 알고리즘입니다. </li>
<li><a href="https://velog.io/@dj_/Maximum-Likelihood-Estimation">이전 글(MLE 설명)</a></li>
</ul>
<h3 id="mle-vs-딥러닝">MLE vs 딥러닝</h3>
<ol>
<li>딥러닝과 MLE 모두 파라미터를 최적화하는 과정입니다. </li>
</ol>
<ul>
<li>MLE는 likelihood를 최대화하는 방향으로 파라미터를 최적화합니다. </li>
<li>딥러닝은 예측 확률 분포(y_hat)를 정답 확률 분포와 같게 만들도록 최적화합니다. (분류 문제의 softmax)</li>
<li>특히 Negative Log Likelihood loss는 본질적으로 MLE와 동일합니다. </li>
</ul>
<ol start="2">
<li>MLE에는 정답이 없습니다. </li>
</ol>
<ul>
<li>MLE는 예측이 아니라 데이터의 설명에 초점을 맞춥니다. 주어진 데이터를 가장 잘 표현하는 확률 분포의 파라미터를 찾는 과정입니다. </li>
<li>반면에 supervised learning기반의 딥러닝 알고리즘들은 정답이 존재합니다. 분류문제에서는 softmax를 통해 나온 확률 분포를 정답 확률 분포와 일치하도록 loss function을 만들어 파라미터를 최적화합니다. </li>
</ul>
<ol start="3">
<li>MLE는 확률 분포를 고정합니다. </li>
</ol>
<ul>
<li>MLE는 특정 확률 분포를 가정하고, 데이터에 맞는 파라미터를 찾는 것입니다. </li>
<li>반면에 딥러닝은 특정 분포를 가정하지 않습니다. </li>
</ul>
<p><strong>딥러닝의 진행 과정을 통한 MLE와의 비교</strong></p>
<ol>
<li>딥러닝은 특정 분포의 가정없이 신경망 구조와 비선형 함수를 통해 모델을 만듭니다.</li>
<li>이 모델에는 여러 파라미터가 존재하고, MLE처럼 주어진 데이터에 대해 likelihood(결과 확률값)를 추론합니다. (MLE와 달리 파라미터의 초기값은 존재합니다.) </li>
<li>계산의 편의성을 위해 likelihood에 log함수를 취합니다. (<a href="https://velog.io/@dj_/Maximum-Likelihood-Estimation">이전 글 참조</a>)</li>
<li>gradient descent방식의 최적화를 위해 음수로 변환함으로써 최종적으로 likelihood를 최대화 = -log(likelihood)의 최소화 로 치환됩니다. </li>
<li>NLL loss의 경우 이 과정이 그대로 loss에 녹아든 것입니다. 즉, 딥러닝 모델의 결과로 나온 확률(likelihood)이 1이 되도록 모델의 파라미터를 업데이트하기위한 loss로, MLE와 굉장히 유사합니다. </li>
</ol>
<h3 id="nll-loss-cross-entropy-loss">NLL loss, Cross Entropy Loss</h3>
<ul>
<li>둘 모두 주로 분류 문제에서 사용됩니다. </li>
<li>NLL loss는 위에서 다뤘듯이 MLE 최적화와 굉장히 유사합니다. 따라서, likelihood를 최대로 해야하는 output에만 적용해야 합니다. <ul>
<li>예를 들어, 모델의 output이 [0.1, 0.4, 0.7], 정답이 1번 class라고 한다면, 0.4에 해당하는 index에만 nll loss를 적용하는 것입니다. </li>
</ul>
</li>
<li>cross entropy loss의 경우 분류 문제에 특화되었으며, 위의 과정을 one-hot vector를 사용해 자동화했다고 보시면 됩니다. 
<img src="https://velog.velcdn.com/images/dj_/post/06904176-8355-43d0-b60c-236fa548d4e8/image.png" alt=""></li>
<li>one-hot vector는 정답 class만 1, 아닌 class는 0인 벡터로, 위의 loss를 적용하면 정답인 class에 대해서만 MLE와 동일한 최적화를 진행할 수 있게 됩니다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Maximum Likelihood Estimation ]]></title>
            <link>https://velog.io/@dj_/Maximum-Likelihood-Estimation</link>
            <guid>https://velog.io/@dj_/Maximum-Likelihood-Estimation</guid>
            <pubDate>Thu, 12 Sep 2024 11:10:38 GMT</pubDate>
            <description><![CDATA[<h3 id="probability-vs-likelihood">Probability vs Likelihood</h3>
<ul>
<li>가장 먼저 likelihood의 정의에 대해서 알아야 합니다. </li>
</ul>
<ol>
<li>probability: 확률 분포가 고정되어 있을 때, 어떤 사건이 일어날 가능성 <ul>
<li>고정된 확률 분포에 대한 파라미터에서 특정 데이터가 등장할 가능성 </li>
<li>동전 던지기(확률 분포 고정)에서 앞면이 나올 가능성은 50%</li>
</ul>
</li>
<li>likelihood: 데이터가 주어졌을 때, 이 데이터들을 설명하는 확률 분포의 파라미터가 특정 값일 가능성 <ul>
<li>데이터들이 주어졌고, 확률 분포 모델이 정해졌을 때, 특정 분포 파라미터가 이 데이터들을 얼마나 잘 설명하는가 </li>
<li>동전을 10번 던져서 7번이 앞면이 나왔다면, 확률 분포(50:50)이 아닐 수 있음 </li>
<li>어떤 확률 분포의 파라미터를 찾는 데에 사용됨 </li>
</ul>
</li>
</ol>
<h4 id="maximum-likelihood-estimation">Maximum Likelihood Estimation</h4>
<ul>
<li>데이터들이 주어지고 확률 모델을 정했을 때, 이 데이터들을 가장 잘 설명할 수 있는 모수(parameter)를 찾는 것입니다.</li>
<li>Likelihood Function <ul>
<li>확률 분포의 모수(parameter)를 input으로 받아서 각 데이터가 등장할 확률을 뱉는 함수입니다. </li>
<li>데이터에 가장 알맞은 모수(parameter)를 넣는다면 이 확률은 높게 나올 것입니다. </li>
</ul>
</li>
</ul>
<h4 id="maximum-likelihood-estimation-진행-과정">Maximum Likelihood Estimation 진행 과정</h4>
<ul>
<li><p>들어가기에 앞서 몇 가지 가정을 하겠습니다. </p>
<ol>
<li>데이터들은 모두 독립적으로 생성된다. </li>
<li>확률 분포는 Gaussian distribution이다. </li>
</ol>
</li>
<li><p>먼저 수식은 아래와 같을 것입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/3209cf56-bf39-4d0b-89a4-e090c9e14a66/image.png" alt=""></p>
</li>
<li><p>모든 데이터는 독립적이기 때문에, 데이터가 3개 있다고 가정하면 특정 파라미터에서 3개의 데이터가 등장할 확률은 각각의 확률을 곱한 것과 같습니다. </p>
</li>
<li><p>데이터 3개가 x: (9, 9.5, 11)이라고 가정해봅시다. 가우시안 분포로 확률 모델을 설정했기 때문에, 파라미터는 평균과 표준편차입니다. </p>
</li>
<li><p>따라서, likelihood function인 위의 수식에 각각의 데이터를 넣고 곱하면 최종 확률이 나오게 됩니다. 
<img src="https://velog.velcdn.com/images/dj_/post/a3183dac-d434-46da-a6ea-970261bfe180/image.png" alt=""></p>
</li>
<li><p>이제 해야 할 일은 이 값을 최대로 만드는 평균과 표준편차를 구하는 일입니다. </p>
</li>
<li><p>우리가 아는 최대값을 구하는 방법은 극값을 구하는 것이고, 이는 미분을 통해 구할 수 있습니다. </p>
</li>
<li><p>즉, 최대값인지 검증하는 과정은 거쳐야겠지만, 위의 식을 미분했을 때 0이 되는 평균과 분산이 Maximum Likelihood Estimation의 결과입니다.</p>
</li>
</ul>
<h4 id="log-likelihood">Log likelihood</h4>
<ul>
<li>보통 MLE를 계산할 때에는 log likelihood로 변환하여 계산합니다. 그 이유는 아래와 같습니다. </li>
</ul>
<ol>
<li>곱셈보다는 덧셈<ul>
<li>최종 확률을 위해서는 모든 데이터에 대한 확률값을 곱해야 합니다. </li>
<li>데이터가 많다면 이 확률값은 매우 작아질 수 있고, 소수점 이하 값들이 사라질 수 있습니다. </li>
<li>log를 씌운 함수를 활용하면 곱셈이 덧셈으로 변환되므로 수치적으로 안정적입니다. </li>
</ul>
</li>
<li>계산 효율성 <ul>
<li>가우시안 분포 곱셈을 보면 미분하기 매우 어렵습니다. </li>
<li>덧셈 자체가 계산적으로 더 쉽기 대문에 효율적입니다. </li>
</ul>
</li>
<li>극점 유지 <ul>
<li>log함수는 단조 증가함수이므로 적용하더라도 극값은 변하지 않습니다. 따라서 최적화 과정에서 문제가 없습니다. </li>
</ul>
</li>
</ol>
<ul>
<li><p>다시 위의 식으로 돌아와서, log 함수를 적용해보면 아래와 같습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/b249234f-eead-457b-b4db-ddfa340399c4/image.png" alt=""></p>
</li>
<li><p>이제 극값을 찾기 위해 미분해야 합니다. 먼저 평균을 구하기 위해 평균에 대해 편미분하면 아래와 같습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/720a5b06-57a8-4820-978e-44054a32601b/image.png" alt=""></p>
</li>
<li><p>이제 이 함수가 0이 되는 극값을 찾으면 Maximum Likelihood Estimation의 전 과정을 마친 것입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/7684607f-dedf-479a-9dd1-e49f5cad5cf7/image.png" alt=""></p>
</li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://towardsdatascience.com/probability-concepts-explained-maximum-likelihood-estimation-c7b4342fdbb1">https://towardsdatascience.com/probability-concepts-explained-maximum-likelihood-estimation-c7b4342fdbb1</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[binary classification metric]]></title>
            <link>https://velog.io/@dj_/binary-classification-metric</link>
            <guid>https://velog.io/@dj_/binary-classification-metric</guid>
            <pubDate>Wed, 11 Sep 2024 12:41:05 GMT</pubDate>
            <description><![CDATA[<h3 id="confusion-matrix">Confusion matrix</h3>
<ul>
<li>binary classification metric들을 알려면 가장 먼저 confusion matrix에 대해 알아야 합니다. </li>
<li>binary classification은 모델이 결과를 True 혹은 False로 뱉을 수 있는 문제이고, confusion matrix는 이 모델 결과와 실제 정답과의 관계를 matrix 형태로 표현한 것입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/f67a6c85-b509-4e9a-8e3d-a84393d28ce4/image.png" alt=""></li>
<li>정리해보면 <strong>{맞춤or못맞춤}_{모델결과}</strong> 로 나타낼 수 있습니다.<ul>
<li>True Positive: 모델 True, 레이블 True </li>
<li>False Positive: 모델 True, 레이블 False</li>
<li>False Negative: 모델 False, 레이블 True </li>
<li>True Negative: 모델 False, 레이블 False </li>
</ul>
</li>
</ul>
<h4 id="accuracy">Accuracy</h4>
<ul>
<li>전체 샘플들 중 맞춘 샘플의 비율입니다. </li>
<li>(TP + TN) / (TP+TN+FP+FN)</li>
<li>데이터에 불균형이 있을 경우 문제가 됩니다. 
예를 들어, 레이블 중 True가 99%, False가 1%라고 한다면, 모델은 모든 데이터에 대해 무지성으로 True값을 뱉어도 accuracy는 99%로 매우 높지만 False 레이블에 대해서는 아예 못 맞추는 상태입니다. </li>
</ul>
<h4 id="precision">Precision</h4>
<ul>
<li>모델이 True라고 예측한 샘플들 중, 실제로 맞춘 샘플의 비율입니다. </li>
<li>TP/(TP+FP)</li>
<li>False positive를 잡는게 중요한 문제에서 사용됩니다. 
예를 들어, 스팸 메일을 예측한다고 할 때, 스팸이 아닌데 스팸이라고 한다면(false positive) 문제가 됩니다. 
스팸이 아니어서 사용자가 꼭 봐야하는 메일이 스팸 메일함에 들어가 있을 수 있기 때문입니다. 반면에 스팸인데 스팸이 아니라고 예측하는 것은 전자보단 문제가 덜 합니다. </li>
</ul>
<h4 id="recall">Recall</h4>
<ul>
<li>레이블이 True인 샘플들 중, 실제로 모델이 맞춘 샘플의 비율입니다. </li>
<li>TP/(TP+FN)</li>
<li>False negative를 잡는게 중요한 문제에서 사용됩니다. 
예를 들어, 암진단 모델을 만든다고 할 때, 암 환자에 대해 암이 아니라고 한다면(False negative) 큰 문제가 됩니다. 반면에 암이 아닌 환자에 대해 암이라고 예측한다면 전자보다는 환자 생명에 문제가 없는 작은 문제입니다. </li>
</ul>
<h4 id="f1-score">F1-score</h4>
<ul>
<li>precision, recall의 조화 평균입니다. </li>
<li>당연히 위의 precision, recall은 모두 중요한 성능 지표이고 이를 한번에 평균낸 값을 통해 모델을 측정하는게 합리적입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/4facdec2-cb19-4c8f-a638-82052bb2079e/image.png" alt=""><h4 id="일반-평균을-사용하지-않는-이유">일반 평균을 사용하지 않는 이유</h4>
</li>
<li>precision, recall을 조합한다고 하면 당연히 그냥 일반적인 더하고 2로 나누는 평균을 생각할 수 있습니다. </li>
<li>하지만, precision:0.9, recall:0.1 라고 한다면, 평균값은 0.5로 생각보다 높습니다. 즉, 높은 값으로 인해 낮은 성능 지표의 의미가 희석될 수 있습니다. </li>
<li>반면에 F1-score로 조화평균을 계산하면 0.18로 낮은 지표를 가지는 것을 알 수 있습니다. </li>
<li>따라서, 두 개의 중요한 지표 모두를 고려한 모델을 만들고자 할 때, F1-score를 측정하는 것이 좋습니다. </li>
</ul>
<h3 id="roc-curve-precision-recall-curve">ROC Curve, Precision-Recall Curve</h3>
<ul>
<li>일반적으로 binary classification 모델은 바로 True, False 값을 뱉는게 아닌 확률값(0~1 사이)을 뱉습니다. </li>
<li>따라서 일정 임계값(threshold)를 기준으로 Positive 혹은 Negative로 예측을 해야 합니다. </li>
<li>물론 기본적으로 중간값인 0.5를 잡을 수 있지만, 모델이 이 threshold에 민감할 수도 있습니다. </li>
<li>따라서, 이러한 threshold값에 따른 그래프를 그려서 성능 평가를 진행하고 이것이 ROC curve, precision-recall curve입니다. </li>
</ul>
<h4 id="precision-recall-curve">Precision-Recall Curve</h4>
<ul>
<li>위에서 언급한대로 threshold값을 바꾸어 가면서 precision recall 값들을 plot한 그래프입니다. </li>
<li>예를 들면, threshold를 0.1로 설정했다면, 0.1 이상의 확률 값을 가지는 샘플을 모두 positive로 예측합니다. 그 후, precision, recall을 계산해 2D 그래프 상에 점으로 표시하는 방식입니다. </li>
<li>아래는 그러한 그래프의 예시입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/90280662-cefc-4708-93a6-9e8a4a497fcb/image.png" alt=""></li>
</ul>
<h4 id="roc-curve">ROC Curve</h4>
<ul>
<li>ROC curve는 precision, recall이 아니라 TPR(True Positive Rate), FPR(False Positive Rate)를 기준으로 그린 그래프입니다. </li>
<li>True Positive rate는 Recall과 같은 의미로 레이블이 True인 샘플들 중 모델이 맞춘 샘플의 비율입니다.<ul>
<li>TP / (TP+FN)</li>
</ul>
</li>
<li>False Positive Rate는 레이블이 False인 샘플들 중 모델이 잘못 Positive로 예측한 비율입니다.<ul>
<li>FP / (FP+TN)</li>
</ul>
</li>
<li>이 두 가지 값을 precision recall curve와 동일하게 threshold를 바꾸어가면서 그래프에 plot하면 됩니다.</li>
</ul>
<h3 id="roc-curve-vs-precision-recall-curve">ROC Curve vs Precision-Recall Curve</h3>
<ul>
<li>ROC curve의 경우 negative 샘플이 많은 불균형 데이터셋에서 제대로 된 성능 평가가 안될 수 있습니다.</li>
<li>예를 들어, 95% 데이터가 negative label인 경우, False Positive 가 많아도 True Negative가 많기 때문에 FPR(False Positive Rate)가 낮게 평가될 수 있습니다.</li>
<li>반면에, precision recall curve의 경우 positive label에 중점을 두고 있기 때문에, 이러한 경우에도 사용할 수 있습니다.<ul>
<li>precision: 모델 positive 중 실제 positive</li>
<li>recall: 레이블 positive 중 실제 positive</li>
</ul>
</li>
</ul>
<h3 id="auc">AUC</h3>
<ul>
<li>Area Under the ROC Curve의 준말로 ROC curve의 아래 면적을 의미합니다.</li>
<li>ROC curve는 성능 지표를 보여주기 좋은 그래프이지만, 수치화가 되어있지 않습니다. 따라서 ROC curve를 정량적으로 평가하기 위해 만든 성능 지표라고 보면 됩니다.</li>
<li>Precision Recall curve도 같은 개념으로 AP(Average Precision)이 있고, 이는 AUC와 마찬가지로 precision recall curve 아래의 면적입니다.</li>
<li>아무래도 curve들 모두 threshold를 반영한 결과들이므로, accuracy같은 단일 임계값에서의 성능 평가 지표보다 모델의 성능 변화를 반영하기에 더 유용합니다.</li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://www.evidentlyai.com/classification-metrics/confusion-matrix">https://www.evidentlyai.com/classification-metrics/confusion-matrix</a>
<a href="https://encord.com/glossary/f1-score-definition/">https://encord.com/glossary/f1-score-definition/</a>
<a href="https://www.datacamp.com/tutorial/precision-recall-curve-tutorial">https://www.datacamp.com/tutorial/precision-recall-curve-tutorial</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Bayes theorem]]></title>
            <link>https://velog.io/@dj_/Bayes-theorem</link>
            <guid>https://velog.io/@dj_/Bayes-theorem</guid>
            <pubDate>Tue, 10 Sep 2024 11:35:52 GMT</pubDate>
            <description><![CDATA[<h3 id="bayes-theorum-bayes-rule">Bayes theorum, Bayes rule</h3>
<ul>
<li><p>베이즈 룰은 사전 정보들과 관측값들이 주어졌을 때, 사후 확률을 계산하는 방법을 말합니다. </p>
</li>
<li><p>간단하게는 조건부 확률을 뒤집는 방법을 말합니다. </p>
</li>
<li><p>예를 들어, COVID-19 검사기의 신뢰도를 얻어야 하는 상황이라고 해봅시다. </p>
<ul>
<li>COVID-19의 발병확률 (사전 정보)</li>
<li>COVID-19 환자들에 대해 검사기를 시행해봤을 때의 결과 확률(관측값) </li>
<li>위의 값들을 토대로 검사기를 시행했을 때, 실제로 COVID-19 감염일 확률 (사후 확률) </li>
</ul>
</li>
<li><p>COVID-19 감염 사건을 A, 검사기 결과 사건을 B라고 했을 때, 아래의 식이 bayes rule입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/30a4efb1-778a-4367-95a7-a38bae96e6f8/image.png" alt=""></p>
</li>
<li><p>만약 우리가 COVID-19 검사기를 발명했다고 하면, 당연히 초기에는 그 신뢰도를 모릅니다. 하지만, COVID-19 감염 확률과 실제 시행했을 때의 확률값을 알게된다면 그에 반대되는 조건부 확률을 구할 수 있다는 것입니다. </p>
</li>
<li><p>또한, 이렇게 정보들(실제 시행했을 때의 확률값)이 추가됨에 따라 신뢰도를 업데이트할 수 있으며, 이를 bayesian inference 혹은 posterior inference 혹은 probabilistic inference라고 합니다. </p>
</li>
<li><p>유명한 Monty Hall 예제를 통해서 이러한 bayesian inference를 살펴보겠습니다. </p>
</li>
</ul>
<h3 id="monty-hall-문제">Monty Hall 문제</h3>
<ul>
<li>문제 설명 </li>
</ul>
<ol>
<li>세 개의 문이 있습니다. M1, M2, M3</li>
<li>한 개의 문 뒤에는 자동차가 있고, 나머지 두 개의 문 뒤에는 염소가 있습니다. </li>
<li>참가자는 먼저 문 하나를 선택합니다.</li>
<li>진행자는 참가자가 선택하지 않은 <strong>두 개의 문 중 염소가 있는 문</strong> 하나를 열고 염소를 보여줍니다. </li>
<li>이때 참가자는 처음 선택한 문을 유지할 것인지, 아니면 나머지 문으로 바꿀 것인지 선택할 수 있습니다. <blockquote>
<p>문을 바꾸는 것이 유리할까요? 혹은 유지하는 것이 유리할까요?</p>
</blockquote>
</li>
</ol>
<ul>
<li>직관적으로는 그냥 50:50으로 동일해보일 수 있지만, 베이즈 정리를 통해 추론해보면 다릅니다. </li>
<li>먼저 <strong>참가자는 1번 문</strong>을 고르고, <strong>진행자는 3번 문</strong>을 보여줬다고 가정해보고 문을 바꿀지 말지의 확률을 알아보겠습니다. </li>
</ul>
<ol>
<li><p>사전 확률 (Hi)
처음에 주어진 정보로는, 자동차가 각각의 문 뒤에 있을 확률이 동일합니다. </p>
<blockquote>
<p>P(H1) = P(H2) = P(H3) = 1/3 </p>
</blockquote>
</li>
<li><p>관측값 </p>
</li>
</ol>
<ul>
<li><p>Y를 진행자가 문을 여는 사건이라고 하면 각각의 조건부 확률은 아래와 같습니다. </p>
</li>
<li><p><em>P(Y=3 | H1) = 1/2*</em> (1번에 자동차 있으므로 2번 혹은 3번 가능) </p>
</li>
<li><p><em>P(Y=3 | H2) = 1*</em> (2번에 자동차 있으므로 무조건 3번 열어야 함)</p>
</li>
<li><p><em>P(Y=3 | H3) = 0*</em> (3번에 자동차 있으므로 무조건 2번 열어야 함)</p>
</li>
<li><p>여기서 미리 <strong>P(Y=3)</strong>에 대한 확률을 구하고 가겠습니다. 
P(Y=3) = P(Y=3 | H1)<em>P(H1) + P(Y=3 | H2)</em>P(H2) + P(Y=3 | H3)<em>P(H3) = *</em>1/2**</p>
</li>
</ul>
<ol start="3">
<li>사후 확률 계산</li>
</ol>
<ul>
<li>이제 베이즈 정리를 사용해서 진행자가 3번 문을 열었을 때, 각각의 문에 자동차가 있을 확률을 계산합니다. </li>
</ul>
<p><img src="https://velog.velcdn.com/images/dj_/post/792c5de6-25bd-4205-a3aa-a7ac88268f17/image.png" alt=""> <img src="https://velog.velcdn.com/images/dj_/post/d4993fa3-88d7-405c-bca4-422d7f0c7124/image.png" alt=""></p>
<ul>
<li>위에서 계산한 값들을 대입해서 구해보면 <blockquote>
<p>P(H1 | Y=3) = 1/3
P(H2 | Y=3) = 2/3 
P(H3 | Y=3) = 0</p>
</blockquote>
</li>
<li>따라서 고른 문을 바꾸는 것이 2배나 더 유리합니다.</li>
<li>이런 방식으로 bayes rule을 이용해 사전 확률 및 가정에 정보들이 추가된 후, 사후 확률을 업데이트하는 과정을 bayesian inference라고 합니다. </li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://towardsdatascience.com/what-is-bayes-rule-bb6598d8a2fd">https://towardsdatascience.com/what-is-bayes-rule-bb6598d8a2fd</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Perceptron에서 CNN까지]]></title>
            <link>https://velog.io/@dj_/Perceptron%EC%97%90%EC%84%9C-CNN%EA%B9%8C%EC%A7%80</link>
            <guid>https://velog.io/@dj_/Perceptron%EC%97%90%EC%84%9C-CNN%EA%B9%8C%EC%A7%80</guid>
            <pubDate>Mon, 09 Sep 2024 12:25:41 GMT</pubDate>
            <description><![CDATA[<h3 id="perceptron">Perceptron</h3>
<ul>
<li>아래 그림과 같은 인간의 뉴런을 모방해 만든 아주 작은 인공 신경망입니다.
<img src="https://velog.velcdn.com/images/dj_/post/26a3da0d-c9b0-4a54-9e2f-49eceb44fa6b/image.png" alt=""></li>
<li>입력신호들이 가지돌기에 도착한 후, 신경 세포에서 이들을 하나의 신호로 통합하고, 어떤 임계값을 넘으면 단일 신호가 생성되어 출력신호로 나가는 이러한 구조를 모방했습니다. </li>
<li>퍼셉트론의 구조는 아래와 같습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/14296acc-9e66-4c48-baf6-b1f31940e4c8/image.png" alt=""></li>
<li>입력 신호들을 가중치의 weight sum으로 합치고 bias constant를 더한 뒤, step function을 통해 threshold를 넘는 지의 여부를 출력하는 구조입니다. </li>
<li>Rosenblatt는 이러한 퍼셉트론 구조와 함께 정답과의 차이를 통해 weight를 학습하는 방식을 고안했으며, 선형 결합에 대한 좋은 예측 성능을 보여주었습니다. </li>
</ul>
<h3 id="multi-layer-perceptron">Multi Layer Perceptron</h3>
<ul>
<li>위에서 언급한 퍼셉트론은 선형 연산입니다. 따라서 위에서 설명한 구조를 하나의 층만 사용한다면 비선형성 문제를 풀 수 없다는 문제가 생깁니다. <h4 id="xor-문제">XOR 문제</h4>
</li>
<li>단층 퍼셉트론은 선형연산이기때문에 하나의 직선 혹은 초평면으로 그려집니다. 만약 AND, OR, XOR 연산의 결과를 예측하는 모델을 만든다고 하면 문제가 생깁니다. 
<img src="https://velog.velcdn.com/images/dj_/post/87d40938-8898-43b9-aa7f-652edd6a9d05/image.png" alt=""></li>
<li>왼쪽의 AND 나 가운데의 OR 연산에 대해서는 선형 모델로도 예측이 가능합니다. 하지만, 다른 두 값은 1, 같은 두 값은 0으로 출력하는 XOR연산의 경우 하나의 직선으로는 decision boundary를 만들지 못합니다. </li>
</ul>
<p><img src="https://velog.velcdn.com/images/dj_/post/78e114f0-ba36-4c66-91f8-4ab6f4494b59/image.png" alt=""></p>
<ul>
<li>퍼셉트론의 XOR문제를 해결하여 우리가 보통 알고 있는 위의 그림과 같은 인공 신경망 구조가 생겨나게 됩니다. </li>
<li>비선형 함수를 포함한 퍼셉트론을 다층으로 쌓음으로써 복잡한 문제들을 모델링할 수 있었고, backpropagation 기법을 이용해 에러를 기반해 hidden layer parameter도 학습하게 되어 탄생할 수 있었습니다. </li>
</ul>
<h3 id="convolutional-neural-network">Convolutional Neural Network</h3>
<ul>
<li>MLP(multi layer perceptron)은 다양한 복잡한 문제들을 해결할 수 있지만, 이미지같은 고차원의 문제를 해결하기에는 문제가 있었습니다. </li>
</ul>
<ol>
<li>파라미터 수가 너무 많음. 이미지의 모든 픽셀을 입력 신호로 사용한다면 파라미터 수가 많아집니다. 예를 들어, 100x100 이미지에서 각 픽셀들이 입력으로 들어간다면 mlp의 입력은 10000개가 됩니다. </li>
<li>공간적 정보 소실. 이미지의 경우 주변 픽셀들과의 관계가 중요한데, 단순 픽셀값의 나열로는 이러한 특성을 찾기 어렵습니다. 예를 들어, 50x50 픽셀은 51x50픽셀과 매우 인접한데, 단순 나열로 입력을 넣는다면 매우 멀리 떨어져 있을 수 있습니다. (50x50, 50x51, 50x52, ... 51x0, 51x1, ...51x50) 따라서 고차원 데이터의 구조적 특성을 학습하기 어렵습니다. </li>
</ol>
<ul>
<li>그에 따라 convolution filter를 사용하는 CNN이 등장했고, 장점은 아래와 같습니다. </li>
</ul>
<ol>
<li>Convolution filter를 이용해 국소적인 특징 추출. 3x3, 5x5 등의 크기를 가지는 필터를 이미지 영역에 적용해 이미지의 구조적 정보를 살린 local feature를 얻을 수 있게 되었습니다. </li>
<li>필터를 공유해 파라미터 수 줄임. 이러한 convolution filter를 공유해서 하나의 filter로 이미지 전체 영역에 대한 feature를 추출하여 파라미터 수를 줄였습니다. 예를 들면, 3x3짜리 엣지를 검출하는 filter라고 하면, 이를 이미지 전체 영역에 모두 적용해 이미지에 있는 엣지 정보들만 추출한 하나의 feature map을 만드는 방식입니다. </li>
</ol>
<h4 id="translation-invariance">Translation invariance</h4>
<ul>
<li>이러한 CNN은 하나의 특성이자 장점을 가지고 있습니다. 해석하면 이동불변성으로 이미지 내의 정보들이 이동한다고 해도 특징들을 동일하게 잘 추출한다는 것입니다. </li>
<li>예를 들어, 이미지에 고양이가 있는지 판별하는 모델을 만든다고 하면, 고양이가 왼쪽 위에 있든, 오른쪽 아래에 있든 판별이 가능합니다. 
<img src="https://velog.velcdn.com/images/dj_/post/1ef6c544-bc34-4d14-a1b8-9668d13ab9b5/image.png" alt=""></li>
</ul>
<ol>
<li>이미지의 모든 영역에 대해 공유된 필터 사용. 하나의 필터를 이미지의 다른 영역에도 동일하게 사용하기 때문에, 위치가 변형된 이미지에 대해서도 feature들을 추출할 수 있습니다. </li>
<li>pooling layer. </li>
</ol>
<ul>
<li>필터가 학습한 특성을 축소시키는 layer로, 패턴의 세부적인 위치 정보를 희석시킵니다. 예를 들면, max pool이 있고 feature들 중 최대값을 가지는 feature만 output으로 뱉는 layer입니다. </li>
<li>이미지의 공간적 크기를 줄이고 위치변화에 민감성을 줄여줍니다. </li>
<li>예를 들어 max pooling의 경우 최댓값만을 output으로 뱉기 때문에 위치가 변화하더라도 중요한 특성만을 추출해낼 수 있고, 그에 따라 translation invariance 특성을 가지게 해줍니다. </li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://blog.naver.com/samsjang/220948258166">https://blog.naver.com/samsjang/220948258166</a>
<a href="https://medium.com/@sue.sk.guo/all-you-should-know-about-translation-equivariance-invariance-in-cnn-cbf2a2ad33cd">https://medium.com/@sue.sk.guo/all-you-should-know-about-translation-equivariance-invariance-in-cnn-cbf2a2ad33cd</a>
<a href="https://bunnycode.tistory.com/20">https://bunnycode.tistory.com/20</a>
<a href="https://www.analyticsvidhya.com/blog/2024/01/xor-problem-with-neural-networks-an-explanation-for-beginners/">https://www.analyticsvidhya.com/blog/2024/01/xor-problem-with-neural-networks-an-explanation-for-beginners/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Overfitting 방지 기법]]></title>
            <link>https://velog.io/@dj_/Overfitting-%EB%B0%A9%EC%A7%80-%EA%B8%B0%EB%B2%95</link>
            <guid>https://velog.io/@dj_/Overfitting-%EB%B0%A9%EC%A7%80-%EA%B8%B0%EB%B2%95</guid>
            <pubDate>Sun, 08 Sep 2024 12:17:44 GMT</pubDate>
            <description><![CDATA[<h3 id="overfitting-감지">Overfitting 감지</h3>
<p>overfitting은 학습 데이터에 너무 fit해서 unseen data에 대해 일반화되지 않는 현상을 말합니다. 이러한 overfitting을 방지하기 위해서는 먼저 현재 모델이 overfitting되어 있는지 확인할 줄 알아야 합니다. 
보통은 아래의 learning curve를 통해 유추가능합니다. </p>
<ul>
<li>training loss는 계속해서 떨어지지만, unseen data인 validation set에 대해서 loss가 다시 상승하는 구간이 일반화 성능이 떨어지는 overfitting 구간입니다. 
<img src="https://velog.velcdn.com/images/dj_/post/30e2fe91-341c-4f85-a422-83bc644c3904/image.png" alt=""></li>
</ul>
<h3 id="overfitting-방지-기법들">Overfitting 방지 기법들</h3>
<ol>
<li>Early Stopping </li>
</ol>
<ul>
<li>위의 learning curve에서 overfitting 구간에 진입하기 전에 모델 학습을 종료시키는 기법입니다. 아래 그림과 같습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/24d64536-3cbe-4fba-af3d-9fd72b0206e0/image.png" alt=""></li>
</ul>
<ol start="2">
<li>Regularization </li>
</ol>
<ul>
<li><p>대표적으로 L1, L2 regularization이 있으며, loss function에 각각 L1 norm, L2 norm term을 추가하는 방식입니다. norm은 벡터 크기를 측정하는 방식으로 아래 수식과 같습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/4082583e-347a-4941-89dd-e1c21e7eb701/image.png" alt=""></p>
</li>
<li><p>모델의 weight값을 작게 만들면 모델을 간단하게 만드는 효과를 갖습니다. 예를 들어, polynomial regression에서 각 변수의 계수가 0에 가깝거나 0이 된다면 해당 차수에 대한 식이 사라지는 효과를 보게 되므로 모델의 복잡도가 줄어듭니다. </p>
</li>
<li><p>이처럼 L1, L2 regularization은 weight에 대한 l1, l2 norm을 loss function에 추가함으로써 모델을 간소화시키는 regularizing 효과를 제공합니다.  </p>
</li>
<li><p>L1 regularization이 포함된 loss function을 w에 대해 편미분하면 아래와 같습니다. C0는 기존 cost function이고, sgn() 는 부호를 의미합니다. 
<img src="https://velog.velcdn.com/images/dj_/post/99c9d0b6-1c02-4a52-a86f-6d2e1bcac350/image.png" alt=""></p>
</li>
<li><p>즉, L1 regularization은 weight의 크기에 관계없이 지속적으로 weight를 상수값만큼 update합니다. 따라서, weight가 0이 될 수 있으며, 이는 feature가 사라지는 것을 의미합니다. </p>
</li>
<li><p>L2 regularization은 편미분을 해도 weight가 남아있기 때문에 weight를 0으로 만들기는 어렵습니다. 따라서 필요없는 feature를 제거하는 효과보다는 전반적인 모델의 복잡도를 줄여주는 역할이 가능합니다. 정리해보면 아래 표와 같습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/1ce619bd-ad8e-40e4-a765-445d736be107/image.png" alt=""></p>
</li>
</ul>
<ol start="3">
<li>Dropout </li>
</ol>
<ul>
<li>Dropout은 아래 그림처럼 일정 확률로 각 layer의 activation을 0으로 만드는 것을 의미한다. 
<img src="https://velog.velcdn.com/images/dj_/post/fd4dfe42-3ecc-4260-9562-b186f74b3282/image.png" alt=""></li>
<li>매번 다른 layer들의 조합으로 학습이 진행되기 때문에, 하나의 layer에 의존하지 않도록 학습되어 모델의 복잡도를 줄이는 효과와 더불어 모델의 일반화 성능을 높일 수 있습니다. </li>
</ul>
<ol start="4">
<li>데이터 다양화 </li>
</ol>
<ul>
<li>overfitting은 데이터에 비해 모델이 복잡해서 나타나는 현상이므로, 데이터 자체를 더 복잡하고 다양하게 넣어주면 보완이 가능하다. </li>
<li>데이터를 더 수집해서 넣거나, data augmentation을 통해 다양한 상황의 데이터들을 학습에 추가해주면 overfitting을 방지할 수 있다. </li>
<li>data augmentation이란 아래 그림처럼 학습 데이터를 조작해 새로운 데이터처럼 만들어서 모델에 넣어주는 것을 의미합니다. 
<img src="https://velog.velcdn.com/images/dj_/post/c8971244-b6c9-4633-827f-522ae59593e6/image.png" alt=""></li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://www.kaggle.com/code/ryanholbrook/overfitting-and-underfitting">https://www.kaggle.com/code/ryanholbrook/overfitting-and-underfitting</a>
<a href="https://wooono.tistory.com/221">https://wooono.tistory.com/221</a>
<a href="https://gaussian37.github.io/dl-concept-regularization/">https://gaussian37.github.io/dl-concept-regularization/</a>
<a href="https://kh-kim.github.io/nlp_with_deep_learning_blog/docs/1-14-regularizations/04-dropout/">https://kh-kim.github.io/nlp_with_deep_learning_blog/docs/1-14-regularizations/04-dropout/</a>
<a href="https://www.analyticsvidhya.com/blog/2023/12/mosaic-data-augmentation/">https://www.analyticsvidhya.com/blog/2023/12/mosaic-data-augmentation/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Overfitting 과 Underfitting ]]></title>
            <link>https://velog.io/@dj_/Overfitting-%EA%B3%BC-Underfitting</link>
            <guid>https://velog.io/@dj_/Overfitting-%EA%B3%BC-Underfitting</guid>
            <pubDate>Fri, 06 Sep 2024 08:36:42 GMT</pubDate>
            <description><![CDATA[<h3 id="overfitting--underfitting">Overfitting &amp; Underfitting</h3>
<p>overfitting, underfitting은 데이터 분포와 모델의 복잡도관점에서 아래와 같이 설명할 수 있습니다. </p>
<blockquote>
<p>Overfitting : 모델의 복잡도 &gt; 데이터 분포 
Underfitting : 모델의 복잡도 &lt; 데이터 분포 </p>
</blockquote>
<p>데이터에 비해 모델이 복잡해서 데이터에 대한 패턴을 학습한 것이 아니라, 학습 데이터에만 맞게 모델이 학습된 현상을 overfitting이라고 하고, 모델의 복잡도가 낮아 데이터의 패턴을 제대로 학습하지 못한 현상을 underfitting이라고 합니다. 
ploynomial regression 모델을 학습한 경우를 예시로 들 수 있습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/28bc431a-6d78-491a-a4ea-c8b6112236c0/image.png" alt="">
그림처럼 polynomial regression의 차원이 낮아 데이터 분포를 제대로 나타내지 못하는 경우를 underfitting, 차원이 너무 높아 학습 데이터를 외우고 있는 경우를 overfitting이라 합니다. </p>
<h3 id="bias--variance">Bias &amp; Variance</h3>
<p>overfitting과 underfitting은 모델의 복잡도 관점에서 bias와 variance와도 관련이 있습니다. </p>
<blockquote>
<p>Bias: 모델 예측값과 정답간의 차이의 평균
Variance: 모델 예측값 평균과 각 예측값들의 차이의 제곱 </p>
</blockquote>
<p>즉, bias는 예측값이 실제 정답과 얼마나 떨어져 있는가를 나타내고, variance는 분산의 본래 의미와 같이 예측값이 얼마나 변화할 수 있는 지를 나타냅니다. 
<img src="https://velog.velcdn.com/images/dj_/post/557d8010-7de4-4502-95f9-de5ab263bf8c/image.png" alt="">
다트 게임을 예시로 들겠습니다. 아시다시피 빨간색 가운데 위치에 다트를 던지는 것이 좋은 게임입니다. </p>
<ol>
<li>Low Bias &amp; Low Variance: 다트를 정답 위치에 잘 넣고 있으며, 에임도 좋습니다. </li>
<li>Low Bias &amp; High Variance: 다트를 정답를 포함해 근처로 잘 넣고 있지만, 에임은 좋지 않습니다. </li>
<li>High Bias &amp; Low Variance: 에임은 좋지만, 정답 위치와는 모두 거리가 있습니다.</li>
<li>High Bias &amp; High Variance: 에임도 안좋고, 정답 위치와도 모두 거리가 있습니다. </li>
</ol>
<p>이러한 Bias, Variance는 모델의 복잡도와도 연관이 있기 때문에 overfitting, underfitting 현상과도 함께 설명할 수 있습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/63794f66-1b05-4bda-beb9-b12524f23f46/image.png" alt=""></p>
<p>진한 파란 색의 line은 데이터를 나타냅니다. 해당 데이터에서 train sample들을 랜덤으로 추출해서 각각 linear regression 모델과 4차원의 polynomial regression 모델을 학습한 결과가 하늘색 line입니다. </p>
<ul>
<li>linear regression의 경우 대부분의 경우 정답 line과는 다른 값을 내뱉는 line이 그려지지만, polynomial과 달리 같은 x값에 대해 대부분 비슷한 y값을 뱉습니다. 즉, bias는 높지만 variance는 낮습니다. </li>
<li>polynomial regression의 경우 몇몇 line은 정답 line과 거의 일치하는 형태로 학습되지만, 같은 x값에 대해 y값의 편차가 linear보다 큽니다. 즉, bias는 낮지만 variance는 높습니다. </li>
</ul>
<p>정리해보면 아래와 같습니다. </p>
<ol>
<li>데이터에 비해 모델의 복잡도가 떨어진다면, bias는 높고 variance는 낮은 상태로 학습될 것이고 이러한 상태를 underfitting이라고 합니다. </li>
<li>데이터에 비해 모델의 복잡도가 높다면, bias는 낮고 variance는 높은 상태로 학습될 것이고 이러한 상태를 overfitting이라고 합니다. </li>
</ol>
<h4 id="reference">Reference</h4>
<p><a href="https://gradient-descent.tistory.com/6">https://gradient-descent.tistory.com/6</a>
<a href="https://towardsdatascience.com/bias-and-variance-in-linear-models-e772546e0c30">https://towardsdatascience.com/bias-and-variance-in-linear-models-e772546e0c30</a>
<a href="https://towardsdatascience.com/the-bias-variance-tradeoff-for-modeling-5988db08ef91">https://towardsdatascience.com/the-bias-variance-tradeoff-for-modeling-5988db08ef91</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Triton Inference Server 사용법]]></title>
            <link>https://velog.io/@dj_/Triton-Inference-Server-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@dj_/Triton-Inference-Server-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Sun, 29 Jan 2023 07:48:05 GMT</pubDate>
            <description><![CDATA[<h3 id="triton-inference-server">Triton Inference Server</h3>
<p>Triton Inference Server 는 NVIDIA 에서 공개한 open-source 추론 지원 소프트웨어입니다. </p>
<p><strong>그렇다면 굳이 사용하는 이유는?</strong> </p>
<p>개인적으로 생각하기에 가장 큰 이유는 편해서입니다. </p>
<p>따로 backend 라이브러리를 공부할 필요 없이, 학습된 모델 파일+config파일 몇개+전후처리 코드 정도만 구성해주면 바로 추론 서버를 제작할 수 있습니다.</p>
<p>또한 아직 다 사용해보진 않았지만, 다이나믹 배치 추론, multi-gpu 지원, Prometheus 메트릭 지원 등등 이미 제공하는 좋은 기능들도 많이 존재합니다.</p>
<h3 id="triton-서버-제작">Triton 서버 제작</h3>
<p>제가 작성한 <a href="https://github.com/fegler/triton_server_example">example code</a>를 토대로 간단한 Triton 서버를 제작하는 과정을 보여드리겠습니다. 
flow는 대충 아래와 같습니다. </p>
<ol>
<li>model 파일 제작 (serialize)</li>
<li>config 파일 작성 </li>
<li>전/후처리 코드 작성 </li>
<li>Triton image pull &amp; run!</li>
</ol>
<p>1~3을 완료하면 하나의 <code>모델 폴더</code> 를 만들 수 있는데요, 구조는 아래와 같습니다. 
<img src="https://velog.velcdn.com/images/dj_/post/311ea22d-7fcc-428f-8eb5-632fa3f76884/image.png" width="30%"></p>
<p>이렇게 만들어진 폴더를 triton docker image에 binding해서 컨테이너를 띄우면 서버 제작완료입니다. </p>
<h3 id="model-파일-제작">Model 파일 제작</h3>
<p>Training이 완료된 모델을 배포하기 위해서는 serialize작업이 필요한데요, 저의 경우에는 PyTorch로 모델링을 주로 하기때문에, <code>torchscript</code>를 사용했습니다. 방법은 코드 두 줄이면 끝입니다! </p>
<pre><code class="language-python">script_model = torch.jit.script(PYTORCH_MODEL)
torch.jit.save(script_model, SAVE_PATH)</code></pre>
<p>물론 Triton은 torchscript 이외에도 tensorRT, onnx 등등 다양한 framework를 지원하기 때문에 편한 방식을 사용하면 됩니다. </p>
<h3 id="config-파일-작성">config 파일 작성</h3>
<p>자세한 내용은 <a href="https://github.com/triton-inference-server/server/blob/main/docs/user_guide/model_configuration.md">Triton model configure docs</a> 를 참고하세요.
Triton의 <code>모델 폴더</code>에 존재하는 폴더들은 각각 하나의 <code>모델</code> 취급을 받게 되는데요, 각각의 모델들은 모두 <code>config.pbtxt</code> 파일을 가지고 있어야 합니다. 
config 파일에서 꼭 포함해야 할 내용은 <code>platform</code> 그리고 <code>input/output 설명</code> 입니다. 
<code>platform</code> 은 이 모델이 어떤 framework를 기반으로 작성되었는지를 명시합니다. pytorch인지, tensorflow인지 혹은 그냥 python(전후처리 코드) 인지요.
<code>input/output 설명</code>은 input output의 <code>data type</code>, <code>dimension</code> 등을 명시합니다. </p>
<p>아래는 이를 기반으로 작성한 예시 config 파일입니다. resnet50 모델을 추론하는 config입니다. <code>-1</code> 값은 <code>값 미정</code> 을 의미합니다. </p>
<pre><code>name: &quot;core&quot;
platform: &quot;pytorch_libtorch&quot; 

input [
    {
        name: &quot;INPUT__0&quot;
        data_type: TYPE_FP32 
        dims: [-1, 3, -1, -1]
    }
] 

output [
    {
        name: &quot;OUTPUT__0&quot;
        data_type: TYPE_FP32 
        dims: [-1, -1]
    }
]</code></pre><p>일반적인 모델들은 위와 같은 식으로 작성을 하면 되는데요, 가장 중요한 config 파일이 하나 남았습니다. 
바로 <code>전체 flow를 지정하는 ensemble 모델</code> 입니다. 
제가 작성한 모델 구조는 <code>전처리 &gt; 모델 추론 &gt; 후처리</code> 이렇게 간단한 구조인데요, 이러한 <code>flow</code>를 <code>ensemble</code>에서 명시해주어야 합니다. 
아래는 그 예시입니다. 
<code>platform</code>은 <code>ensemble</code>을 사용해주고, <code>step</code> 부분에 flow를 순서대로 작성해주면 됩니다. </p>
<pre><code>name: &quot;ensemble&quot;
platform: &quot;ensemble&quot; 

input [
    {
        name: &quot;image&quot;,
        data_type: TYPE_STRING,
        dims: [-1],
    }
]

output [
    {
        name: &quot;result&quot;,
        data_type: TYPE_STRING,
        dims: [-1],
    }
]

ensemble_scheduling {
    step [
        {
            model_name: &quot;preprocessing&quot;,
            model_version: -1, 
            input_map {
                key: &quot;image&quot;,
                value: &quot;image 
            },
            output_map {
                key: &quot;input_image&quot;,
                value: &quot;input_image&quot;
            }
        },
        {
            model_name: &quot;core&quot;,
            model_version: -1, 
            input_map {
                key: &quot;INPUT__0&quot;,
                value: &quot;input_image&quot;
            },
            output_map {
                key: &quot;OUTPUT__0&quot;,
                value: &quot;scores&quot;
            }
        },
        {
            model_name: &quot;postprocessing&quot;,
            model_version: -1, 
            input_map {
                key: &quot;INPUT__0&quot;,
                value: &quot;scores&quot;
            },
            output_map {
                key: &quot;result&quot;,
                value: &quot;result&quot;
            }
        }
    ]
}</code></pre><h3 id="전후처리-코드-작성">전/후처리 코드 작성</h3>
<p>사실 모델링을 할때 이미 전/후처리 코드는 작성하는 경우가 대부분이기 때문에, <code>Triton python backend</code> 사용법만 알면 됩니다. 
python backend 코드는 <code>TritonPythonModel</code> class를 구현해야 합니다. 이 class는 4개의 멤버 함수를 제공하는데, 보통 <code>execute</code>함수만 잘 구현하면 됩니다. 
<code>execute</code>함수는 model에 request가 들어왔을 때 실행되는데요, 여기에 전/후처리를 잘 적용해서 response로 묶어서 return 해주기만 하면 됩니다.
python backend에 대한 자세한 내용은 <a href="https://github.com/triton-inference-server/python_backend">docs</a>를 참고하세요.</p>
<pre><code class="language-python">import triton_python_backend_utils as pb_utils 

class TritonPythonModel: 
    &quot;&quot;&quot;
    preprocessing main logic 
    &quot;&quot;&quot;

    def execute(self, requests):
        responses = [] 
        for request in requests:
            ## get request 
            raw_images = pb_utils.get_input_tensor_by_name(request, &quot;image&quot;).as_numpy()

            ## make response
            input_image = gen_input_image(raw_images) ## 전/후처리 수행하는 함수 
            input_image_tensor = pb_utils.Tensor(
                &quot;input_image&quot;, input_image.astype(np.float32)
            )
            response = pb_utils.InferenceResponse(
                output_tensors=[input_image_tensor]
            )
            responses.append(response)
        return responses</code></pre>
<h3 id="triton-image-pull--run">Triton image pull &amp; run</h3>
<p>이제 만들어진 <code>모델 폴더</code>를 실제로 Triton 에 적용시켜서 컨테이너를 띄워봅시다. 
일단 자신의 환경에 맞는 Triton 버전을 확인해야 합니다. 이 <a href="https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html">docs</a>에 지원하는 cuda 버전, framework 버전 등등 명시가 되어 있습니다.</p>
<p>그 이후 해당 버전의 triton image를 pull합니다. <a href="https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver/tags">여기</a>에 이미지 tag 리스트가 있습니다.</p>
<pre><code>docker pull nvcr.io/nvidia/tritonserver:21.10-py3</code></pre><p>그 이후 아래 명령어로 컨테이너를 띄워줍니다. </p>
<pre><code class="language-bash">docker run --gpus=&#39;&quot;device=0&quot;&#39; -it --rm --shm-size=8g -p 8005:8000  -v ${MODEL_FOLDER_PATH}:/model_dir  nvcr.io/nvidia/tritonserver:21.10 tritonserver --model-repository=/model_dir --strict-model-config=false --model-control-mode=poll --repository-poll-secs=10 --backend-config=tensorflow,version=2 --log-verbose=1</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] Pytorch Lightning 사용법]]></title>
            <link>https://velog.io/@dj_/DL-Pytorch-Lightning-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@dj_/DL-Pytorch-Lightning-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Mon, 16 Jan 2023 05:45:08 GMT</pubDate>
            <description><![CDATA[<h3 id="pytorch-lightning">PyTorch Lightning</h3>
<p>PyTorch에서 나온 리서처의 편의(?)를 돕기 위한 라이브러리인데요, 공식 홈페이지에서는 이렇게 소개합니다. </p>
<blockquote>
<p>You do the research. Lightning will do everything else.</p>
</blockquote>
<p>사용해보니 많이 공감되는 말이긴 하지만, 제가 느낀 장점은 코드가 깔끔해진다는 것이 가장 컸습니다. </p>
<h3 id="lightning-사용법">Lightning 사용법</h3>
<p>PyTorch Lightning은 3가지 Module에 대한 사용법만 익히면 끝입니다. 
순서대로 <code>LightningModule</code>, <code>LightningDataModule</code>, 그리고 <code>Trainer</code> 입니다. </p>
<p>일종의 PyTorch의 한단계 high-level 언어라고 생각하면 되고, 기존의 PyTorch code들을 가져다가 묶어주는 Module들이라고 생각하면 좋습니다. </p>
<p>각각의 Module의 역할은 아래와 같습니다. </p>
<ol>
<li><p><code>LightningModule</code> - <span style="color: red">model, loss</span></p>
<ul>
<li>train, validation, test loop 내용 정의 </li>
<li>optimizer, learning rate scheduler 등을 정의 </li>
<li>model, loss 정의 </li>
</ul>
</li>
<li><p><code>LightningDataModule</code> - <span style="color: red">data</span></p>
<ul>
<li>Dataset, DataLoader 정의 (train, valid, test 모두)</li>
<li>데이터 다운로드 (필요할 경우)</li>
</ul>
</li>
<li><p><code>Trainer</code> - <span style="color: red">main loop (train, valid, test)</span></p>
<ul>
<li>보통 main.py 같은 파일에서 call </li>
<li>gpu number, epoch 수, logger(tensorboard 같은) 설정 </li>
<li>실제 train,test,valid loop 수행 </li>
</ul>
</li>
</ol>
<h3 id="pytorch-lightning-code">PyTorch Lightning Code</h3>
<p>예시 코드를 살펴보면 이해가 될텐데요, 각 module들은 위에서 언급한 기능들을 구현하는 함수를 가지고 있습니다. 이 함수들만 적절히 구현해주면 모든 구현이 완료됩니다. </p>
<ol>
<li>LightningModule</li>
</ol>
<ul>
<li><p>train loop에서 수행할 내용 정의 -&gt; <span style="color: red">training_step </span></p>
<ul>
<li>validation_step, test_step 함수도 만들어서 정의할 수 있음!</li>
</ul>
</li>
<li><p>optimizer, scheduler 설정 -&gt; <span style="color: red">configure_optimizers</span></p>
<pre><code class="language-python">import pytorch_lightning as pl 
import torch.nn as nn 
from torchvision.models import resnet34
import torch.nn.functional as F
class MainModule(pl.LightningModule):
  def __init__(self, opt):
      super(MainModule, self).__init__()
      self.opt=opt     
      self.model = resnet34()

  def forward(self, x):
      return self.model(x)

  def training_step(self, batch, batch_idx):
      im, label = batch 
      pred = self.model(im)
      loss = F.cross_entropy(pred, label)
      self.log(&#39;train/loss&#39;, loss.item())
      return loss 

  def configure_optimizers(self):
      optimizer = torch.optim.Adam(
          self.model.parameters(), self.opt.lr)
      return [optimizer]</code></pre>
</li>
</ul>
<ol start="2">
<li>LightningDataModule </li>
</ol>
<ul>
<li><p>dataset 정의 - <span style="color: red">setup</span></p>
</li>
<li><p>dataloader 정의 - <span style="color: red">train_dataloader</span></p>
<pre><code class="language-python">class MainDataModule(pl.LightningDataModule):
  def setup(self, stage=None):
      self.train_dataset = DatasetClass(self.hparams.data_dir)
      self.valid_dataset = DatasetClass(self.hparams.data_dir)

     def train_dataloader(self):
      return DataLoader(
          dataset=self.train_dataset,
          batch_size=32
      )

  def valid_dataloader(self):
         return DataLoader(
          dataset=self.valid_dataset,
          batch_size=32
      )</code></pre>
</li>
</ul>
<ol start="3">
<li>Trainer (main.py)</li>
</ol>
<ul>
<li><p>각 module들, 필요한 callback들 만들어서 객체 생성</p>
</li>
<li><p>training -&gt; fit 함수 </p>
</li>
<li><p>test -&gt; test 함수</p>
<pre><code class="language-python">  module = MainModule()
  datamodule = MainDataModule()
  tqdm_cb = TQDMProgressBar(refresh_rate=10)
  ckpt_cb = ModelCheckpoint(
      dirpath=&#39;./saved&#39;,
      filename=&quot;{epoch:02d}_&quot;,
      save_last=True
  )
  tb_logger = TensorBoardLogger(
      name=&#39;exp_name&#39;,
      save_dir=&#39;./log&#39;
  )

  trainer = pl.Trainer(
      accelerator=&quot;gpu&quot;,
      devices=[gpu_number],
      max_epochs=100,
      callbacks=[tqdm_cb, ckpt_cb],
      logger=tb_logger
  )
  trainer.fit(module, datamodule=datamodule)</code></pre>
</li>
</ul>
<h3 id="장점">장점</h3>
<p>개인적으로 생각하는 장점들은 아래와 같습니다. </p>
<ol>
<li><p>코드 정형화 </p>
<ul>
<li>아무래도 각 모듈들로 역할들을 분배해놓아서, 코드 구조가 거의 다 똑같다. </li>
</ul>
</li>
<li><p>main.py (train.py, test.py) 코드 짧아짐</p>
<ul>
<li>보통 PyTorch 코드들은 실제 loop를 수행하는 train.py, test.py 파일들을 구현합니다. </li>
<li>저의 경우 이 파일들이 실험을 돌릴수록 점점 더러워졌는데..</li>
<li>module들로 model, data 관련 내용을 분리하고, callback, logger 기능들을 활용하면서 너어어어어어무 깔끔해졌다고 생각합니다. </li>
</ul>
</li>
<li><p>제공되는 기능이 많음. </p>
<ul>
<li>가장 체감이 컸던건 tqdm, logger를 callback으로 넣어서 직접 구현할 일이 없다는 것입니다. </li>
<li>이외에도 early stopping, 16-bit precision 등 기본적으로 제공해주는 기능들이 많아서 편합니다. </li>
</ul>
</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>