<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>_chominseo.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 14 Jan 2026 03:10:06 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>_chominseo.log</title>
            <url>https://velog.velcdn.com/images/_chominseo/profile/ba9438ff-8429-4d51-90c2-2a3245f7212c/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. _chominseo.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/_chominseo" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[DCVC- 계열 정리]]></title>
            <link>https://velog.io/@_chominseo/DCVC-%EA%B3%84%EC%97%B4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@_chominseo/DCVC-%EA%B3%84%EC%97%B4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 14 Jan 2026 03:10:06 GMT</pubDate>
            <description><![CDATA[<p>DCVC를 시작으로 Microsoft asia 팀에서 해마다 한 두편씩 neural video compression 관련 논문이 나온다. 
코드: <a href="https://github.com/microsoft/DCVC/tree/main/DCVC-family">https://github.com/microsoft/DCVC/tree/main/DCVC-family</a></p>
<p>아래 표에 내가 생각한 각 논문에서 중요한 포인트를 적어두었다.</p>
<table>
<thead>
<tr>
<th>이름</th>
<th>시기</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td>DCVC</td>
<td>NeurIPS 2021</td>
<td>Residual 코딩 방식에서 conditional 코딩으로 전환</td>
</tr>
<tr>
<td>DCVC-TCM</td>
<td>TMM 2022</td>
<td>Context 생성 모듈 개선</td>
</tr>
<tr>
<td>DCVC-HEM</td>
<td>ACM MM 2022</td>
<td>Variable bitrate 지원</td>
</tr>
<tr>
<td>DCVC-DC</td>
<td>CVPR 2023</td>
<td>새로운 entropy model 제안</td>
</tr>
<tr>
<td>DCVC-FM</td>
<td>CVPR 2024</td>
<td>더 세밀한 qs 조절 지원</td>
</tr>
<tr>
<td>DCVC-RT</td>
<td>CVPR 2025</td>
<td>모션 모듈 제거 및 경량화</td>
</tr>
</tbody></table>
<p>RT는 약간 특성이 달라서 이번엔 다루지 않을 예정이다.
그 외 논문들을 하나씩 보자면,</p>
<h2 id="dcvc">DCVC</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/f5b51a29-0300-4109-bd04-ad02e3eb0d43/image.png" alt=""></p>
<p>왼쪽은 DCVC 전까지 일반적이던 residual 코딩 방식이다. 이미 코딩해둔 정보들을 바탕으로 현재 프레임을 예측하고 ($\tilde{x_t}$) 그 차이만을 ($x_t-\tilde{x_t}$)를 코딩한다. </p>
<p>DCVC에서 제안한 건 아니지만, 오른쪽의 conditional 코딩 방식은 이미 코딩해둔 정보들을 인코딩, 디코딩할 때 context로 활용해서 압축할 latent를 뽑는 방식이다. </p>
<h2 id="dcvc-tcm">DCVC-TCM</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/8ac8bf6f-6cae-4595-bcb9-752004cd5cef/image.png" alt=""></p>
<p>DCVC에서 context를 뽑을 때 복원한 이전 영상을 활용했었다. </p>
<p>하지만, 3채널 짜리 복원 영상은 feature 단계보다 정보가 많이 줄어든 상태이기 때문에, RGB영상을 뽑기 전 feature ($F_t$)도 같이 저장해 뒀다가, 이걸로 context를 뽑는 방식으로 바꿨다. </p>
<h2 id="dcvc-hem">DCVC-HEM</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/974de3bb-8b51-4237-9421-ccb7f019563a/image.png" alt=""></p>
<p>다른 모듈 구성이나 이런건 동일한데, 단일 모델에서 여러 qs를 지원할 수 있도록 연산 중간중간에 learnable vector를 곱하는 연산을 추가해줬다. </p>
<h2 id="dcvc-dc">DCVC-DC</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/dd098003-5fd2-439a-a8a4-919130f25870/image.png" alt=""></p>
<p>크게 두개 모듈이 추가되었다.</p>
<p>1) 모션 예측시 offset을 여러개 같이 예측하는 모듈
2) Quadtree entropy model</p>
<p>1번은 크게 아이디어적인 것은 없어서 패스</p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/8f12f2bf-e804-4b1f-b771-a6eeaeb68553/image.png" alt=""></p>
<p>2번의 quadtree entropy model 그림이다. Autoregressive 방식 중 하나로 볼 수 있는데, 비교적 성능도 꽤 좋아지면서 연산 복잡도는 적당히 높아진 밸런스 있는 모델인 것 같다.</p>
<h2 id="dcvc-fm">DCVC-FM</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/102f8162-ca41-451e-9515-81ad06b4e221/image.png" alt=""></p>
<p>TCM 이후부터 DC까지는 context를 만들 때 feature만을 사용했었다. 이게 언제 문제가 되냐면, I 프레임으로부터 점점 멀어질 수록 (GOP가 커질 수록) 문제가 발생한다. </p>
<p>P 프레임 코딩을 하면서 에러가 점점 누적되는건데, FM에서는 이를 해결하기 위해 context를 생성할 때 주기적으로 feature가 아닌 복원 영상을 활용한다. </p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/e7687c55-80f2-4700-9b34-0e3381b71a3d/image.png" alt=""></p>
<p>그 결과, I 프레임 하나로 동영상 전체를 코딩하더라도 비교적 안정적인 모습을 보인다. (ECM은 딥러닝이 아닌 전통적인 코덱 방식)</p>
<h2 id="정리">정리</h2>
<p>다음엔 어떤식으로 Neural video compression을 발전시킬지 기대가 된다. 
다 좋은데 학습 코드가 없어서 재현이 어렵다. 그래서 점점 이 연구팀이랑 다른 팀간에 격차가 커지는 것 같다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Learned Rate Control for Frame-Level Adaptive Neural Video Compression via Dynamic Neural Network (ECCV 24)]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Learned-Rate-Control-for-Frame-Level-Adaptive-Neural-Video-Compression-via-Dynamic-Neural-Network</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Learned-Rate-Control-for-Frame-Level-Adaptive-Neural-Video-Compression-via-Dynamic-Neural-Network</guid>
            <pubDate>Wed, 17 Dec 2025 07:35:18 GMT</pubDate>
            <description><![CDATA[<p>논문 링크: <a href="https://arxiv.org/abs/2508.20709">https://arxiv.org/abs/2508.20709</a>
딥러닝 기반의 video compression 논문이다. </p>
<hr>
<h2 id="문제-제기">문제 제기</h2>
<p>고전 코덱들은 비트레이트(bit rate)를 세세하게 조절해서 원하는 환경에 맞게 압축이 가능했다. 
그러나, 딥러닝 기반의 비디오 압축 기법들은 </p>
<center>

<p>$L=R+\lambda_iD$</p>
</center>

<p>고정된 $\lambda$값을 사용하여 Rate-Distortion 손실함수를 최소화 하기 때문에, 세세한 조절이 안된다.</p>
<h3 id="기존-기법">기존 기법</h3>
<p>딥러닝 기반 비디오 압축에서 세밀한 비트 조절을 위한 방식은 두가지로 구분 가능하다.</p>
<h4 id="1-multi-granularity-quantization">1. Multi-granularity quantization</h4>
<p><a href="https://arxiv.org/abs/2302.14402">DCVC-DC</a>가 대표적인 예시인데, 피쳐단에서 qs 몇개에 대한 learnable vector를 곱하는 것으로 값을 크게 변화시키는게 아니라 scaling만 한다. -&gt; quantization step 변화와 비슷함</p>
<h4 id="2-feature-modulating">2. Feature modulating</h4>
<p>1과 다르게 실제 값이 바뀌게끔 하는 scaling 이상의 연산이 들어간다.</p>
<h4 id="저자들이-제기한-문제">저자들이 제기한 문제</h4>
<p>1번 같은 경우는 단순 선형 변환이라 당연히 네트워크를 따로 두는 것보다 제한적이라는 것, 그리고
1, 2번 모두 bit-rate 예측과정이 없기 때문에 정확하게 조절이 어렵다는 점이다. </p>
<h2 id="제안-기법">제안 기법</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/1ccbd2f8-4392-451d-ba35-8dc14d8b2fd8/image.png" alt=""></p>
<h3 id="요약">요약</h3>
<p>세가지를 제안한다. </p>
<ol>
<li>Dynamic-Route Autoencoder (DRA)
: Slimmable autoencoder를 사용해서 bit-rate에 맞게 전체 네트워크의 일부(Route)만으로도 코딩이 가능하다.</li>
<li>Rate Control Agent (RCA)
: 원하는 bit-rate에 따라 route를 결정해준다.</li>
<li>Joint-Routes Optimization Strategy
: 네트워크 일부만 쓰고, 공유하고 이런 스타일은 학습이 어렵기 때문에 학습 과정을 고안하였다.</li>
</ol>
<h3 id="1-dynamic-route-autoencoder-dra">1. Dynamic-Route Autoencoder (DRA)</h3>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/e1772009-211d-4106-b98e-e41cc8754fd8/image.png" alt=""></p>
<p>간단하게 말하면 파라미터 일부만 사용해서 출력되는 절대적인 양을 줄여버린다. </p>
<p>그림은 Slimmable convolution 내용이다.
(a) 출력이 잘리는 경우
(b) 입력이 잘려 있는 경우
이고, 자르는 단계가 0~3 단계라고 하면
0단계는 $W_0$만, 1단계는 $[W_0, W_1]$을 사용하는 이런식이다. 
<img src="https://velog.velcdn.com/images/_chominseo/post/90cf3bf7-a8ac-468f-827d-336755041864/image.png" alt=""></p>
<p>다른 autoregressive 모델과 똑같긴 한데, 엔트로피 모듈에서의 구현은 위 그림과 같다.
이전 route 출력 모두를 현재 route 를 예측하는데 사용한다.</p>
<center>

<p>$\Phi^k_{ch}=p_{ch}(Q(FM(y^{k-1}_{ch})),\hat{z})$</p>
</center>

<p>$p_{ch}$는 확률 분포 예측기, Q는 quantization, FM은 feature modulation 네트워크에 해당한다. 
그러면, 위 식은 k번째 route의 확률분포 $\Phi^k_{ch}$를 예측하기 위해, 이전 route 출력 $y^{k-1}_{ch}$ 와 hyperprior $z$를 사용한다는 식이 된다. </p>
<h3 id="2-rate-control-agent-rca">2. Rate Control Agent (RCA)</h3>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/1c7875d7-8ebe-4e74-ac98-7244cbdbb764/image.png" alt=""></p>
<p>두가지 연산이 이루어진다. </p>
<ol>
<li>입력 영상 $x_t$와 모션 벡터 $mv$를 받아서 각 route별 bit-rate를 예측한다. ($R^0_{est}$ ~ $R^3_{est}$)</li>
<li>목표 bit-rate $R_{tar}$와 이미 사용한 비트수 $R_{coded}$를 바탕으로 몇번째 route까지 쓸건지 결정한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/1084252f-55e8-4a74-bbcb-39130acb1095/image.png" alt="">
(원 논문에서 notation을 비트레이트, 총 비트수를 같은 R로 써서 헷갈린다.)
예를 들어, 
이미 코딩한 프레임 수 $N_{coded}=10$
참고할 프레임 수 $SW=5$
$R_{tar}=0.5, R_{coded}=4.8$ 
이라 하면,
현재 프레임 압축시 목표 bit-rate $T_{tar}=0.54$ 가 돼서
목표 비트수 보다 약간 더 써도 된다 는걸 유도할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/8480fed4-18b6-4f48-abe1-4896bd00f257/image.png" alt=""></p>
<p>즉, 만약 비트가 좀 여유있다면 ($R_{tar}\times N_{coded}&gt;R_{coded}$)
$T_{tar}$보다 큰 $R^i_{est}$들 중에서 젤 가까운 $i$를 route로 선택하는 방식이다. </p>
<h3 id="3-joint-routes-optimization-strategy">3. Joint-Routes Optimization Strategy</h3>
<p>일반적으로 variable-rate 코덱을 학습하는 방식은 다음과 같다. </p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/2acd8198-e6a0-42b6-a992-5bea3e74bac2/image.png" alt=""></p>
<p>모든 route (또는 qs)에 대해 Rate, Distortion loss를 구하고 다 합쳐서 업데이트하는데 사용한다.
Variable-rate를 위해 $\lambda$ 값을 튜닝한다. </p>
<p>(Line 4, 5에서 $\lambda$만 바꾸고 R, D는 그대로인 것처럼 써놨는데, R, D도 각 qs별로 새로 측정한다.)</p>
<p>qs가 낮을수록 학습이 빠르기 때문에, 높은 qs의 (그림에선 $\lambda_3$) 부터 하나씩 고정하면서 학습을 진행한다. </p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/36e71dfa-03a0-4118-be27-2ad8a9f0c115/image.png" alt=""></p>
<p>Algorithm 1을 발전시켜서, $\lambda$ 값들을 같이 업데이트 하는 방식을 제안한다. </p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/e1d6146f-53c8-44f2-82e1-8283af34249a/image.png" alt=""></p>
<p><strong>복잡한데</strong>, Algorithm 1 기준으로
rate-distortion 변화량 $\xi$(위 그래프와 같이 음수값을 가짐)이 하나 큰 qs에서의 변화량($\xi_{prev}$) 보다 작으면서(더 가파르면서)를 때까지 $\kappa$를 곱해 $\lambda$들을 줄여나간다.</p>
<p>즉, 완만했던 파란색 그래프에서 qs가 작아질 수록 점점 급해지는 빨간색 그래프로 변해 가면서 bit-rate 범위를 늘린다. </p>
<p>여기서도 높은 qs의 $\lambda$ 값부터 하나씩 고정시켜 나간다.</p>
<h2 id="실험">실험</h2>
<p>DCVC-DC를 인용은 했는데, 같이 성능을 비교 안한걸로 봐서 잘 안나와서 뺀 것으로 의심이 된다..
<img src="https://velog.velcdn.com/images/_chominseo/post/d53dda81-c57c-4ccd-b529-20fd251dffca/image.png" alt=""></p>
<p>그래도 이렇게 원하는 bpp에 딱맞게 나오는 것은 신기하다.</p>
<h3 id="주관적인-생각">주관적인 생각</h3>
<p>코드상에 모션 코딩 관련해선 엔 이런 처리를 안하고 모든 qs에서 똑같은 처리를 하는것으로 되어 있던데 왜 모션엔 따로 뭔갈 안했는지 궁금하다.</p>
<p>학습 난이도가 꽤 될 것 같은데, 구체적으로 어떻게 했을지 궁금하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Learned Image Compression with Hierarchical Progressive Context Modeling (ICCV 2025)]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Learned-Image-Compression-with-Hierarchical-Progressive-Context-Modeling-ICCV-2025</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Learned-Image-Compression-with-Hierarchical-Progressive-Context-Modeling-ICCV-2025</guid>
            <pubDate>Tue, 23 Sep 2025 09:54:44 GMT</pubDate>
            <description><![CDATA[<p>논문 링크: <a href="https://arxiv.org/abs/2507.19125">https://arxiv.org/abs/2507.19125</a>
코드 링크: <a href="https://github.com/lyq133/LIC-HPCM/tree/master">https://github.com/lyq133/LIC-HPCM/tree/master</a></p>
<p>DCVC-TCM을 쓴 Microsoft 팀에 계시던 저자분 두분이 학교에서 지도하신 논문인듯 하다.</p>
<p>딥러닝 기반의 이미지 압축 논문이다. 구조는 크게 Encoder, Decoder, Entropy module 3개로 구분이 가능한데, 이 논문은 Entropy module 부분이 메인이다.</p>
<p>저자들이 문제삼은 것은, Entropy module이 CNN 기반으로 Local redundancy를 활용하는 것에서 Transformer를 활용하여 global 특성도 활용하게 발전하고 있지만, 여전히 global redundancy 활용이 부족하다는 점이다.</p>
<p>제안한 것은 다음 두가지이다.</p>
<ol>
<li>Hierarchical coding schedule</li>
<li>Progressive context fusion
별개로 다른 논문의 아이디어를 가져와 활용한 몇가지까지 있다. </li>
</ol>
<p>최근 대부분 압축 논문에서 활용하고 있는 Autoregressive entropy module 기반이다.</p>
<h2 id="overview">Overview</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/4e64ba46-3cee-403b-a4a1-9a12696c9d12/image.png" alt="">
일반적인 이미지 압축 구조와 같이 </p>
<p>1) 입력 영상이 인코더를 통과하여 latent y
2) hyperprior 인코더로 z
3) entropy module로 y의 확률 분포 예측
4) 디코더로 영상 복원
하는 구조이다. 이 논문에서는 3번이 중요하다.</p>
<h2 id="1-hierarchical-coding-schedule">1. Hierarchical coding schedule</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/f55d1ea8-3821-48e3-a3bc-2a2426d0106a/image.png" alt="">
Autoregressive 구조로 y를 잘게 쪼개서 순차적으로 코딩을 하는데, 쪼개는 방식에 대한 제안이다. 
그림이 조금 복잡해 보일 수 있으나, DCVC-DC 논문을 본 사람이라면 익숙할 그림이다. DCVC-DC의 quadtree와 매우 유사한 방식을 제안한다. 
구체적으론,</p>
<p>1) 채널방향으로 균등하게 8조각으로 자른다. 
2) y를 1/4 크기로 샘플링하여 (각 sub-latent마다 다른 위치) 코딩을 진행한다. (stage 1, 2)
3) y를 1/2 크기로 샘플링하여 코딩을 진행한다. (stage 3, 4, 5)
4) 원래 y 크기에서 나머지 부분 코딩을 진행한다. (stage 6, 7, 8, 9, 10, 11)</p>
<p>그림에서 각 칸에 적힌 숫자가 autoregressive 순서를 지칭하는 stage 번호이다.</p>
<p>이렇게 함으로써 초반 코딩 단계(1/4, 1/2 스케일)에서 attention 수행시 메모리를 줄일 수 있다. </p>
<h2 id="2-progressive-context-fusion">2. Progressive context fusion</h2>
<p>Autoregressive entropy module에서 중요한 context 생성 부분이다. 
Context란 현재 코딩하려는 $y_i$의 확률 분포 $\psi_i$ ($\mu, \sigma$)를 예측하기 위해 이미 코딩한 latent $\hat{y}_{&lt;i}$ 와 같이 활용할 정보를 말한다. </p>
<h4 id="1-이전-stage와-현재-stage의-스케일이-바뀌지-않는-경우">1) 이전 stage와 현재 stage의 스케일이 바뀌지 않는 경우</h4>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/87fe9183-dc61-43fc-8ecc-c494e68d957e/image.png" alt="">
$\psi_i=g_{ep}(C_i, \hat{y}<em>{&lt;i})$ 로 확률 분포를 예측하기 위한 파라미터를 얻는다. 이중 현재 코딩하고자 하는 부분($\psi</em>{\hat{y}_i}$)만 사용한다.</p>
<h4 id="progressive-context-fusion">Progressive Context Fusion</h4>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/1b9e39e6-d5cf-4578-86ec-2002a617434b/image.png" alt="">
실질적인 Context를 업데이트를 하는 파트다. 구조는 그냥 cross attention이다. $C_{i+1}=CrossAttn(\psi_i, C_i)$</p>
<h4 id="2-이전-stage와-현재-stage의-스케일이-바뀌는-경우">2) 이전 stage와 현재 stage의 스케일이 바뀌는 경우</h4>
<img src="https://velog.velcdn.com/images/_chominseo/post/b4ec69eb-89c5-45fd-b5e1-37082e34bf51/image.png" height="50">

<p>Context 업데이트 시, 원래 샘플링 해왔던 위치에 이전 context를 넣어 주고, 나머지 부분은 hyperprior z에서 얻을 수 있는 확률 분포 파라미터 예측의 초기값인 $h_s(\hat{z})$으로 채워준다.</p>
<h2 id="이외-변경사항">이외 변경사항</h2>
<h4 id="partial-convolutionpconv-in-residual-block">Partial convolution(Pconv) in Residual block</h4>
<p>인코더 디코더에서 사용하는 Residual block에서 연산량을 줄이기 위해 Partial convolution (Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks CVPR 2023) 을 차용했다. 
<img src="https://velog.velcdn.com/images/_chominseo/post/9cd125a4-d77e-4972-bc10-1ff5addd253e/image.png" height="10">
<img src="https://velog.velcdn.com/images/_chominseo/post/64021562-c6b2-4bc1-a42d-fa259700eddc/image.png" alt="">
위 그림처럼, 채널 전체에 대해 convolution을 하는 것이 아니라 일부 채널(여기선 1/4)에만 연산을 진행한다. </p>
<h4 id="weight-sharing-entropy-parameter-network">Weight sharing entropy parameter network</h4>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/4a4c3fc9-a049-4173-a0b4-ced2b09ac979/image.png" alt="">
파라미터 수를 줄이기 위해 확률 파라미터 예측 모듈인 $g_{ep}$를 일부 공유한다. 스케일로 말하자면, 1/4 1/2 스케일에서 같은 파라미터를 사용하고, 1 스케일에서 같은 파라미터를 사용한다. 
코딩 stage를 구분짓기 위해 stage별로 따로 있는 <code>Step adaptive embedding</code>을 중간에 곱해주었다. </p>
<h2 id="성능">성능</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/c21388af-1fc1-4667-942c-9b90b1e10579/image.png" alt="">
다른 image compression 기법들에 비해 꽤 빠르고 높은 성능을 보인다. 중간의 *표된 두 모델은 인코더 디코더는 동일하지만, entropy model만 제안 기법으로 측정해 준 성능이다. </p>
<hr>
<p>제안 기법들에서도 느껴지듯이 코드를 봤을 때도 DCVC-DC를 확실히 참고 잘 한듯 하다.
여러가지 아이디어들도 근거 있게 잘 제안 한 것 같다. 어텐션 과정에서 이렇게 스케일 구분해서 차례로 진행한다는 것은 다른 연구 분야에서도 활용할 수 있을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Entroformer: A Transformer-based Entropy model for Learned Image Compression (ICLR 2022)]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Entroformer-A-Transformer-based-Entropy-model-for-Learned-Image-Compression</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Entroformer-A-Transformer-based-Entropy-model-for-Learned-Image-Compression</guid>
            <pubDate>Wed, 17 Sep 2025 10:21:47 GMT</pubDate>
            <description><![CDATA[<p>이 논문 역시 transformer 구조를 활용한 entropy model이다. </p>
<h2 id="overview">Overview</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/9e2eca9f-2c7f-4edf-b05f-ef3dd482db34/image.png" alt="">
구조 자체는  hyperprior 기반의 autoregressive entropy model 과 동일하게, 인코더로 얻은 latent y 중 이미 전송한 $\hat{y}$과 hyper encoder로 얻은 z, $\hat{z}$으로 확률분포를 예측한다. 
뒤에서 말하겠지만 autoregressive 방식은 아니고 y를 2단계로만 나누어서 코딩한다.</p>
<p>총 3가지 contribution으로 정리할 수 있다. </p>
<h2 id="diamond-relative-positional-encoding">Diamond relative positional encoding</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/ac63d03e-0c5a-48be-9e3e-a449cfb2b348/image.png" alt="">
다이아몬드 형태의 positional encoding을 제안한다. 위 그림은 저자들이 한칸씩 직접 마스킹해가며 코딩을 진행하였을 때 떨어지는 성능이라고 한다.
가운데에 가까울수록 성능 하락 폭이 커지는 것을 보고 다이아몬드 형태의 positional encoding을 사용했다.
$p_{ij}=
\begin{cases}
w_{ij}, &amp; |i|+|j|\le h\
w_{hh} &amp; otherwise
\end{cases}$
위 그림 같은 경우는 h=3으로 중간에서 3칸 밖에 있는 부분은 같은 벡터로 인코딩한다. 안쪽은 learnable parameter.</p>
<h2 id="top-k-self-attention">Top-k self attention</h2>
<p>이건 특별할 거 없이 어텐션 결과에서 모든 value를 활용하는게 아니라 어텐션 스코어가 높은 k개만 사용해서 상관 없는 정보를 제외하겠다는 의도이다.</p>
<h2 id="parallel-bidirectional-context-model">Parallel bidirectional context model</h2>
<p>빠른 병렬처리를 위해서 checkerboard 형태로 공간상에서 2조각을 내어 하나씩 코딩한다. 
<img src="https://velog.velcdn.com/images/_chominseo/post/c97aa0b7-766d-4e8f-8576-42601dfa7464/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Learning Accurate Entropy Model with Global Reference for Image Compression (ICLR 2021)]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Learning-Accurate-Entropy-Model-with-Global-Reference-for-Image-Compression-ICLR-2024</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Learning-Accurate-Entropy-Model-with-Global-Reference-for-Image-Compression-ICLR-2024</guid>
            <pubDate>Wed, 17 Sep 2025 10:19:59 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/_chominseo/post/e3fd7758-4b33-4b80-ab2c-bd9c9bd088a4/image.png" alt="">
해당 논문 이전의 Entropy model들은 모두 CNN 기반의 구조여서 local한 redundancy만 고려하고, global redundancy를 고려하지 못한다는 문제의식에서 시작한다.
CNN 구조였던 Entropy model에 <U>global</U> 처리를 추가하는 첫 논문이 되겠다. </p>
<p>인코더 디코더는 별로 안중요해서 Entropy model 내부만 봐보자</p>
<h2 id="overview">Overview</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/97683356-c67c-410b-81d3-eac397415845/image.png" alt="">
그림과 같이 세줄 구조로 되어있다. 
위에서부터 Local, Global, Hyperprior path이다.</p>
<p>오른쪽과 아랫줄을 가리는 Mask convolution으로 Autoregressive를 구현하였다.
3x3 conv라면, 
000
00X
XXX
이런식으로 가리는 커널을 사용한다.</p>
<h3 id="첫째줄-local">첫째줄 Local</h3>
<p>Confidence map U를 얻는 과정이다. 
U는 latent 각 픽셀의 quality 정보를 담은 matrix다. CxHxW 형태일텐데, C방향으로 평균내서 쓴다.
이후 확률 파라미터 $\mu_1, \sigma_1$을 예측한다.
약간 디테일로 $\sigma$를 바로 예측하는 것에 비해 $log\sigma$를 예측하는게 더 안정적이라고 한다. </p>
<h3 id="둘째줄-global">둘째줄 Global</h3>
<p>Similarity map S를 얻고, U,S를 활용한다.
<img src="https://velog.velcdn.com/images/_chominseo/post/76430247-55af-408a-a6b4-b0a1ac2a8f4b/image.png" alt=""></p>
<p>Cosine similarity로 하는데, mask convolution 하는 것 처럼 윗줄과 왼쪽 픽셀까지 4개 픽셀들을 사용해서 cosine similarity를 측정한다. 
이렇게 얻은 S와 U로 Local path에서 얻은 $\mu_1, \sigma_1$를 업데이트 한다 -&gt;$\mu_2, \sigma_2$</p>
<h3 id="셋쨰줄-hyperprior">셋쨰줄 Hyperprior</h3>
<p>다른 모델과 같이 z에서부터 위에서 얻은 $\mu_2, \sigma_2$를 업데이트해서 최종 $\mu_3, \sigma_3$을 얻어서 각 latents의 확률을 예측한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[H.264 AVC]]></title>
            <link>https://velog.io/@_chominseo/H.264-AVC</link>
            <guid>https://velog.io/@_chominseo/H.264-AVC</guid>
            <pubDate>Wed, 17 Sep 2025 10:17:10 GMT</pubDate>
            <description><![CDATA[<p><a href="https://ieeexplore.ieee.org/document/6755595">H.264 논문</a></p>
<p>주로 보던 딥러닝 논문과는 다르게 엄청 자세한 알고리즘까진 언급이 안되어 있다. 아마 기존 고전 코덱들에서 쌓아 올려온 기술이기에 그런듯 하다. </p>
<p>인코더: Prediction -&gt; transformation(ex. DCT) -&gt; encoding(to bitstream)</p>
<p>디코더: Decoding -&gt; inverse transformation(ex. IDCT) -&gt; reconstruction</p>
<p>로 이루어져 있다.</p>
<h2 id="과정">과정</h2>
<h3 id="1-prediction">1) Prediction</h3>
<p>이전 프레임들을 기반으로 현재 프레임을 예측한다. 이후 그 residual 영상만 저장한다.</p>
<h3 id="2-transformation">2) Transformation</h3>
<p>Prediction error를 조각내서 DCT와 같은 inverse가 존재하는 방식으로 분해한다.</p>
<h3 id="3-quantization">3) Quantization</h3>
<p>반올림같이 적당히 값을 날려준다.</p>
<h3 id="4-entropy-coding">4) Entropy coding</h3>
<p>실제 전송에 사용할 bitstream 형태로 변환해준다. Huffman coding 같은 변환을 수행한다고 보면 된다.</p>
<hr>
<h3 id="5-entropy-decoding">5) Entropy decoding</h3>
<p>bitstream을 실제 값을 다시 복원한다.</p>
<h3 id="6-inverse-transformation">6) Inverse transformation</h3>
<p>IDCT와 같이 변환에 사용한 역연산을 수행한다.</p>
<h3 id="7-reconstruction">7) Reconstruction.</h3>
<p>예측했던 프레임과 디코딩 결과를 합친다.</p>
<h2 id="특징">특징</h2>
<h3 id="mode-in-h264">Mode in H.264</h3>
<p>블록별로 코딩을 수행할 때 참조하는 이전 블록들의 위치 방향을 모드라고 지칭한다.</p>
<p>16x16 크기를 macro block으로 지칭하고, 각 macro block을 quadtree로 쪼개면 8x8 블록 4개가 된다.</p>
<h3 id="deblocking-filter">Deblocking filter</h3>
<p>디코딩 과정 중에 포함되는 in-loop filter과 디코딩 이후 RGB / Luminance, chrominance에 직접 수행하는 post-processing 방식이 있다. 구체적으로 어떤 필터를 사용하는지는 논문에 포함되어 있지 않다. 참조한 이전 논문들 중 하나에 있을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Frequency Aware Transformer for Learned Image Compression (ICLR 24)]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Frequency-Aware-Transformer-for-Learned-Image-Compression-ICLR-24</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Frequency-Aware-Transformer-for-Learned-Image-Compression-ICLR-24</guid>
            <pubDate>Wed, 17 Sep 2025 10:14:50 GMT</pubDate>
            <description><![CDATA[<p><a href="https://openreview.net/forum?id=HKGQDDTuvZ">FTIC (ICLR 2024)</a></p>
<p>ICLR 2024 논문으로 딥러닝을 이용한 이미지 압축 논문이다. (코드 O)</p>
<h2 id="contributions">Contributions</h2>
<ul>
<li><p>인코더, 디코더 내에 Swin transformer의 4가지 형태로 윈도우 설정</p>
</li>
<li><p>인코더 디코더 FFN 부분에 주파수 변환 -&gt; linear -&gt; 역변환 수행</p>
</li>
<li><p>Entropy module의 autoregressive를 masked transformer 형태로 구현하였다. </p>
</li>
</ul>
<h2 id="overview">Overview</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/41d623a5-b38f-409a-9eb0-fbeb5e0a2121/image.png" alt=""></p>
<p>전체 모델 구조 그림이다.
RBS: Residual block with stride
RBU: Residual block with upsampling
FAT: Frequency Aware Transformer</p>
<h2 id="인코더-디코더">인코더, 디코더</h2>
<p>여느 CNN+Transformer 조합의 autoencoder 구조와 같이 CNN 구조인 RBS / RBU와 Swin transformer 기반의 FAT block의 반복으로 이루어져 있다. </p>
<h3 id="fat-frequency-aware-transformer">FAT (Frequency Aware Transformer)</h3>
<p><strong>4가지의 윈도우 형태</strong>
<img src="https://velog.velcdn.com/images/_chominseo/post/54bd55c5-b453-4496-a349-08c5ca69aec0/image.png" height="50"></p>
<p>기존 Swin과 다르게 윈도우 형태를 4가지로 사용하였다. 위 그림과 같이 각 윈도우의 특성에 따라 얻을 수 있는 특징이 달라진다고 한다. 
-&gt; 이건 이론적으로 예측하긴 어려울 것 같고, 대충 이럴 것 같다고 상상한 뒤 실험 해봐야 떠올릴 수 있는 아이디어일 듯 하다.</p>
<p><strong>FM (Frequency Modulation)</strong>
<img src="https://velog.velcdn.com/images/_chominseo/post/da60d2c3-9162-4efc-919a-39b4367b26bc/image.png" height="10%"></p>
<p>기존 Transformer의 FFN를 통과한 뒤, 주파수 영역에서 Linear 연산이 하나 추가되었다.
동일 팀에서 ICLR 2025에 낸 논문 역시 에너지 관련 언급이 많은데, 이 팀은 이쪽으로 발전시키고 있는 것 같다.</p>
<h2 id="entropy-module">Entropy Module</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/8391a99c-38f0-413c-b1b2-13633eb7c637/image.png" alt="">
사실 다른 Autoregressive 방식과 알고리즘 자체는 같지만 더 효율적인 구현을 contribution 삼은 것 같다. 
기존 연구들과의 차이점:</p>
<ul>
<li>hyperprior encoder, decoder 내부에 FAT block을 사용</li>
<li>Autoregressive 구현에 masked transformer 사용</li>
</ul>
<p>모델 코드도 정리도 잘 되어 있고, 이해하기 좋게 짜여 있어 참조하기 좋다. 성능, hyperparameter는 직접 논문을 보면 되겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Video Compression 관련 논문]]></title>
            <link>https://velog.io/@_chominseo/Video-Compression-%EA%B4%80%EB%A0%A8-%EB%85%BC%EB%AC%B8</link>
            <guid>https://velog.io/@_chominseo/Video-Compression-%EA%B4%80%EB%A0%A8-%EB%85%BC%EB%AC%B8</guid>
            <pubDate>Tue, 04 Feb 2025 16:00:00 GMT</pubDate>
            <description><![CDATA[<p>Optical Flow</p>
<ul>
<li>SPyNet: Spatial Pyramid Network for Optical Flow</li>
<li>PWC-Net: CNNs for Optical Flow Using Pyramid, Warping, and Cost Volume </li>
<li>RAFT: Recurrent All-Pairs Field Transforms for Optical Flow</li>
<li>SKFlow: Learning Optical Flow with Super Kernels</li>
</ul>
<p>Video frame interpolation</p>
<ul>
<li>BMBC: Bilateral Motion Estimation with Bilateral Cost Volume for Video Interpolation</li>
<li>Asymmetric Bilateral Motion Estimation for Video Frame Interpolation (ABME)</li>
<li>BiFormer: Learning Bilateral Motion Estimation via Bilateral Transformer for 4K Video Frame Interpolation</li>
<li>Quadratic Video Interpolation</li>
<li>Video Frame Interpolation with Transformer</li>
<li>AdaCoF: Adaptive Collaboration of Flows for Video Frame Interpolation</li>
<li>A Unified Pyramid Recurrent Network for Video Frame Interpolation</li>
</ul>
<p>Image compression</p>
<ul>
<li>VARIATIONAL IMAGE COMPRESSION WITH A SCALE HYPERPRIOR</li>
<li>Joint Autoregressive and Hierarchical Priors for Learned Image Compression</li>
<li>Content-aware Masked Image Modeling Transformer for Stereo Image Compression</li>
<li>Learned Image Compression with Discretized Gaussian Mixture Likelihoods and Attention Modules</li>
<li>DPICT: Deep Progressive Image Compression Using Trit-Planes</li>
<li>Context-Based Trit-Plane Coding for Progressive Image Compression</li>
<li>ANFIC: Image Compression Using Augmented Normalizing Flows</li>
</ul>
<p>Video compression
P-frame codec</p>
<ul>
<li>DVC: AnEnd-to-end Deep Video Compression Framework</li>
<li>VCT: AVideo Compression Transformer </li>
<li>Deep Contextual Video Compression (DCVC)</li>
<li>Neural Video Compression with Diverse Contexts (DCVC-DC)</li>
</ul>
<p>B-frame codec</p>
<ul>
<li>B-CANF: Adaptive B-Frame Coding With Conditional Augmented Normalizing Flows</li>
<li>Conditional Variational Autoencoders for Hierarchical B-frame Coding</li>
<li>MaskCRT: Masked Conditional Residual Transformer for Learned Video Compression</li>
<li>OMRA: ONLINE MOTION RESOLUTION ADAPTATION TO REMEDY DOMAIN SHIFT IN LEARNED HIERARCHICAL B-FRAME CODING</li>
<li>Hierarchical B-frame Video Coding Using Two-Layer CANF without Motion Coding</li>
</ul>
<p>기타 알아야 할것</p>
<ul>
<li>Correlation (cost) volume</li>
<li>Forward warping / Backward warping</li>
<li>Entropy (coding)</li>
<li>I, B, P frame</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[3dLane Detection 논문들]]></title>
            <link>https://velog.io/@_chominseo/3dLane-Detection-%EB%85%BC%EB%AC%B8%EB%93%A4</link>
            <guid>https://velog.io/@_chominseo/3dLane-Detection-%EB%85%BC%EB%AC%B8%EB%93%A4</guid>
            <pubDate>Tue, 04 Feb 2025 15:34:17 GMT</pubDate>
            <description><![CDATA[<p>데이터셋</p>
<ul>
<li>Openlane</li>
<li>ApolloSim</li>
<li>Once 등</li>
</ul>
<p>3d lane detection 구조 논문</p>
<ul>
<li>3D-LaneNet: End-to-End 3D Multiple Lane Detection</li>
<li>Gen-LaneNet: A Generalized and Scalable Approach for 3D Lane Detection</li>
<li>PersFormer: 3D Lane Detection via Perspective Transformer and the OpenLane Benchmark</li>
<li>Learning to Predict 3D Lane Shape and Camera Pose from a Single Image via Geometry Constraint (CLGO)</li>
<li>Anchor3DLane: Learning to Regress 3D Anchors for Monocular 3D Lane Detection</li>
<li>LATR: 3DLaneDetection from Monocular Images with Transformer</li>
<li>LaneCPP: Continuous 3D Lane Detection using Physical Priors</li>
</ul>
<p>EigenLane</p>
<ul>
<li>Eigenlanes: Data-Driven Lane Descriptors for Structurally Diverse Lanes [CVPR 2022]</li>
</ul>
<p>기타 알아야할 것</p>
<ul>
<li>DETR End-to-End Object Detection with Transformers</li>
<li>Deformable convolution / transformer</li>
<li>World(Ground) coordinate, Camera coordinate</li>
<li>Coordinate transform matrix<ul>
<li>Camera parameter (intrinsic, extrinsic)</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[텍스트 임베딩으로 Clustering 하기]]></title>
            <link>https://velog.io/@_chominseo/%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%9E%84%EB%B2%A0%EB%94%A9%EC%9C%BC%EB%A1%9C-Clustering-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@_chominseo/%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%9E%84%EB%B2%A0%EB%94%A9%EC%9C%BC%EB%A1%9C-Clustering-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 06 Feb 2024 11:06:27 GMT</pubDate>
            <description><![CDATA[<p><a href="https://teddylee777.github.io/tensorflow/word2vec-%EA%B3%BC-keras%EC%9D%98-Embedding-layer-%ED%99%9C%EC%9A%A9%EB%B2%95/">keras를 활용한 word2vec pre-trained 모델을 로딩하여 IMDB 감정분석 분류문제 해결하기</a></p>
<p>이 글 많이 참조했습니다.</p>
<p>Customer Position column에 있는 걸로 예를 들겠습니다.</p>
<p>우선 전체적인 구조는 </p>
<ol>
<li>column에 unique를 찍어봤더니 아래와 같이 비슷해 보이는 애들이 각각 다 다르게 적혀있는 상황</li>
</ol>
<pre><code class="language-python">&#39;&#39;&#39;
academic coordinator/ post graduate teacher (accountancy, business studies)/ tgt (ict)      1
academic specialist                                                                         1
administrative                                                                              5
architect/consultant                                                                        2
architecture/consult                                                                        1
                                                                                         ... 
técnico                                                                                     1
unpaid                                                                                     16
vice president                                                                            492
vicepresident                                                                              11
vp                                                                                          1
Name: position, Length: 117, dtype: int64
&#39;&#39;&#39;</code></pre>
<ol>
<li><p>각 단어들이 가진 의미를 기반으로 Clustering을 하고 싶다.</p>
<p> 1) / , . ( ) 같은 의미 해석에 방해되는 특수 문자 제거</p>
<p> 2) 띄어쓰기 단위로 분리:<code>academic specialist</code> →<code>[&#39;academic&#39;, &#39;specialist&#39;]</code>  </p>
<p> 3) 미리 누군가가 학습시켜 둔 모델 불러오기</p>
<p> 4) 임베딩 이라고 칭하는 단어별 벡터 추출, 위 예시처럼 두 개 이상의 단어를 가진 경우 평균내기</p>
<p> 5) Kmeans로 Clustering</p>
</li>
<li><p>PCA, 직접 찍어봐서 잘 됐나 확인하고, 군집 갯수 바꿔보며 그럴듯하게 만들기</p>
</li>
</ol>
<h2 id="1-데이터-확인">1. 데이터 확인</h2>
<p>다들 알고있는 value_counts, unique를 쓴다.</p>
<p>이때 뒤에 sort_index를 붙이면 abc 순서, sort_values를 붙이면 많은 순서로 나열된다.</p>
<p>또 너무 많아서 …으로 생략된걸 보고 싶으면 아래 코드 첫줄을 넣어준다.</p>
<p>원래대로 하고싶다면 None 대신 80넣고 실행</p>
<pre><code class="language-python"># print할 때 보이는 줄 수 설정하기. 
# 80이 default라 아무것도 원래 찍히던 만큼을 생각하면 되고
# None을 넣으면 모든 줄이 다 찍힌다.
pd.set_option(&#39;display.max_rows&#39;, None)
customer[&#39;job&#39;].value_counts().sort_index()</code></pre>
<h2 id="2-clustering-시작">2. Clustering 시작</h2>
<p>전처리 → 임베딩 추출 → 군집화 순으로 간다.</p>
<h3 id="2-1-전처리">2-1) 전처리</h3>
<p>특수문자 쓰인 게 몇 개 없어서 어렵게 코드 안쓰고 replace 하드 코딩 했다.</p>
<pre><code class="language-python">for idx,position in enumerate(customer[&#39;position&#39;].unique()):
# position이 텍스트
    temp = position.replace(&#39;/&#39;,&#39; &#39;).replace(&#39;(&#39;,&#39; &#39;).replace(&#39;)&#39;,&#39; &#39;).replace(&#39;-&#39;,&#39; &#39;).replace(&#39;.&#39;,&#39; &#39;).replace(&#39;,&#39;,&#39; &#39;)</code></pre>
<p>띄어쓰기 단위로 나눠준다.</p>
<pre><code class="language-python">    position_parsed = temp.split(&#39; &#39;)</code></pre>
<p>오타+띄어쓰기 실수가 같이 있는 경우까지 커버 하지 못하지만 시도해 본 것 (궁금한 사람은 해보세요)</p>
<ul>
<li><p>오타 잡기</p>
<p>  수연이가 얘기해 줬던 Textblob을 이용했다.</p>
<pre><code class="language-python">  from textblob import TextBlob
  blob = TextBlob(&#39;mindenes&#39;)
  print(blob.correct())
  # mindedness</code></pre>
<p>  사용 방법은 라이브러리 다운받아서 TextBlob에 오타가 의심되는 단어를 넣고 .correct()를 찍어보면 된다.</p>
</li>
<li><p>띄어쓰기 잡기</p>
<p>  <a href="https://gist.github.com/miku/7279824#file-segmentation-py">Word segmentation in a nutshell.</a>
  이걸 참조했다.
  링크에 있는 segmentation.py를 이용할 것이다.
  얘도 다른 사람이 학습 시켜둔 ngram모델을 불러와서 사용한다. ngram모델을 다운 받아야 한다.</p>
<p>  <a href="http://norvig.com/ngrams/count_1w.txt"></a></p>
<p>  <a href="https://www.notion.so/minseocho/Clustering-d37cccf8abc144d0afe336f7a22d020d?pvs=4#e42020cb0fc349ae8a538f99b061c784">segmentation.py</a></p>
<p>  코드와 모델을 다운 받았다면 코드 맨 아래에 onegrams 세 개 중 본인이 다운 받은 모델 이름을 잘 확인해서 고쳐주면 된다.</p>
<p>  이 글에 써둔 파일을 다운 받았다면 아래처럼 쓰면 된다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/430a80c4-6f3c-49ed-8d5e-553603d4be76/image.png" alt=""></p>
<p>준비는 끝났다. 다시 원래 코드로 돌아와서</p>
<pre><code>```python
from segmentation import OneGramDist,onegram_log,segment
import functools
onegrams = OneGramDist(filename=&#39;count_1w.txt&#39;)
onegram_fitness = functools.partial(onegram_log, onegrams)
```</code></pre><p>!python ~~ 이런식으로 말고 ipynb파일에서 모듈처럼 불러와 사용하기 위해 segmentation.py파일의 main 함수 안에 있던 불러올 애들을 가져온다.</p>
<pre><code class="language-python">    sentence = &#39;levelexecutive&#39;
    best = segment(sentence, word_seq_fitness=onegram_fitness)
    print(best)
    &#39;&#39;&#39;
    [&#39;e&#39;] -2.996351267959003
    [&#39;v&#39;, &#39;e&#39;] -6.455154678229892
    [&#39;ve&#39;] -4.890746540792021
    ...
    [&#39;levelexecuti&#39;, &#39;ve&#39;] -26.660215605718577
    [&#39;levelexecutiv&#39;, &#39;e&#39;] -25.76582033288556
    [&#39;levelexecutive&#39;] -23.769469064926557
    [&#39;level&#39;, &#39;executive&#39;]
    &#39;&#39;&#39;</code></pre>
<p>그러면 모델이 여러 번 쪼개보더니 가장 그럴듯한 녀석으로 쪼개서 알려준다.</p>
<h3 id="2-2-word2vec-모델-불러오기">2-2) word2vec 모델 불러오기</h3>
<p>gensim이라는 라이브러리에 잘 되어 있다.</p>
<pre><code class="language-python">import gensim
word2vec_model = gensim.models.KeyedVectors.load_word2vec_format(&#39;경로/GoogleNews-vectors-negative300.bin&#39;, binary=True)</code></pre>
<p>오타나 띄어쓰기 같은거 떄문에 FastText를 사용해봤지만 clustering을 잘 못해서 word2vec 모델 사용.</p>
<p><a href="https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit">https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit</a></p>
<p>여기 미리 학습시켜둔 모델을 다운받아 사용한다.</p>
<p>아래와 같은 함수들을 사용할 수 있다.</p>
<pre><code class="language-python"># 두 단어가 얼마나 비슷한지 확률로 알려준다
word2vec_model.similarity(&quot;vicepresident&quot;,&quot;vp&quot;)
# 300개의 -1 ~ 1 사이 숫자들로 단어를 변환(임베딩)해 준다.
word2vec_model.get_vector(word)</code></pre>
<p>이제 이걸 이용해서</p>
<pre><code class="language-python">vectors = pd.DataFrame({&#39;name&#39;:[]})
for idx,position in enumerate(customer[&#39;position&#39;].unique()):
    position_parsed = 전처리한 단어 리스트
    vec = np.array([0.0]*300)
    cnt=0
    for word in position_parsed:
        if word!=&#39; &#39; and word!=&#39;&#39;:
            try:
                vec+=np.array(word2vec_model.get_vector(word))
                cnt+=1
            except:
                oob+=1</code></pre>
<ol>
<li><p>데이터들의 임베딩을 저장할 DataFrame을 하나 생성한다.</p>
</li>
<li><p>unique() 리스트에서 하나씩 뽑아와 앞에 했던 전처리를 거친 뒤, </p>
</li>
<li><p>vec이라는 길이 300짜리 (임베딩의 길이가 300이다) float로 된 array에다가 각 단어의 임베딩을 더해준다.</p>
<p> 평균 낼 때 쓰기 위해 cnt변수에 이 데이터가 몇 개의 단어를 포함하는지 저장해 둔다.</p>
</li>
<li><p>근데 만약 오타 같은 모델이 모르는 단어가 나왔을 때 OOB(out of bag) 문제가 발생한다.</p>
<p> 이거 때문에 try ~ except를 넣어 모르는 단어는 그냥 패스 한다.</p>
</li>
</ol>
<pre><code class="language-python">if cnt!=0:
        vec /= cnt
else:
    print(&#39;no clue&#39;,position)
vectors.loc[idx] = [position,*vec]</code></pre>
<p>평균 내고, 만약 데이터에 포함된 단어들 중 하나도 모른다면 뭔지 확인하기 위해 프린트 하나 넣어 줬다.</p>
<p>전체 코드</p>
<pre><code class="language-python">vectors = pd.DataFrame({&#39;name&#39;:[]})
oob=0
for i in range(300):
    vectors[f&#39;vector{i}&#39;]=[]
for idx,position in enumerate(customer[&#39;position&#39;].unique()):
    temp = position.replace(&#39;/&#39;,&#39; &#39;).replace(&#39;(&#39;,&#39; &#39;).replace(&#39;)&#39;,&#39; &#39;).replace(&#39;-&#39;,&#39; &#39;).replace(&#39;.&#39;,&#39; &#39;).replace(&#39;,&#39;,&#39; &#39;)
    position_parsed = temp.split(&#39; &#39;)
    vec = np.array([0.0]*300)
    cnt=0
    for word in position_parsed:
        if word!=&#39; &#39; and word!=&#39;&#39;:
            try:
                vec+=np.array(word2vec_model.get_vector(word))
                cnt+=1
            except:
                oob+=1
    if cnt!=0:
        vec /= cnt
    else:
        print(&#39;no clue&#39;,position)
    vectors.loc[idx] = [position,*vec]
print(oob)
&#39;&#39;&#39;
no clue bulgaria
no clue gerente
no clue tierarzt
no clue exhibitiontv
no clue proprietário(a)
no clue genel müdür
no clue mindenes
no clue főorvos
23
&#39;&#39;&#39;</code></pre>
<p>아예 감도 못 잡은 데이터가 8개</p>
<p>oob가 23개 (찍어보니 a, of 보통 불용어 처리 하는 건 모델에 없는 듯 하다.)</p>
<p>나름 준수하게 처리한 것 같다면 다음단계로 가고, 못 찾은게 너무 많다면 전처리나 위의 오타/띄어쓰기 수정을 시도해 보자.</p>
<h3 id="3-clustering">3) Clustering</h3>
<p>Kmeans를 이용할 예정이다.</p>
<pre><code class="language-python">from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=8, max_iter=1000)
kmeans.fit(vectors.drop([&#39;name&#39;],axis=1))</code></pre>
<p>앞서 만들어 둔 vectors df를 이용할 거고, 임베딩 벡터만 사용할 것이니 이름을 저장했던 name은 떼고 fitting 해 주자.</p>
<p>n_clusters는 이것 저것 시도해 보고 괜찮아 보이는 걸로 하자.</p>
<h2 id="3-확인">3. 확인</h2>
<pre><code class="language-python">from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pcafit = pca.fit_transform(vectors.drop([&#39;name&#39;],axis=1))
x = pcafit[:,0]
y = pcafit[:,1]
import matplotlib.pyplot as plt
plt.scatter(x,y,marker=&#39;.&#39;,c=kmeans.labels_[:])
for i,v in enumerate(vectors[&#39;name&#39;][:50]):
    plt.annotate(v[:7],xy=(x[i],y[i]))
plt.show()</code></pre>
<p>PCA로 2차원 평면에 점을 찍어 확인해 보자.</p>
<p>PCA로 임베딩(300 차원)을 2차원으로 압축해 준다.</p>
<p>plt scatter로 잘 됐나 확인해 보자. 밑의 반복문은 포인트에 라벨링 해주는 부분인데, </p>
<p><code>v[:7]</code> 해놓은 이유는 v가 이름인데, 전부다 라벨링 해주면 점들이 너무 많아서 글자가 안보인다. 그러니 반복문 횟수 조절이나 표시하는 글자수 적절히 조절해서 보면 된다.</p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/e38a54d8-2569-43ad-8036-8bc7a500b7b6/image.png" alt=""></p>
<p>잘 모르겠다면 class마다 찍어서 확인해 보자</p>
<pre><code class="language-python">vectors[kmeans.labels_==6][&#39;name&#39;]
&#39;&#39;&#39;
19                      physics teacher
41                      science teacher
67    teacher/middle school coordinator
71             math and physics teacher
73      physics and mathematics teacher
75                             educator
86                    chemistry teacher
89                              teacher
Name: name, dtype: object
&#39;&#39;&#39;</code></pre>
<p>확인해 보고 kmeans의 n_cluster를 조정하거나 kmeans말고도 다른 알고리즘을 고민해 보자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[딥러닝을 이용한 자연어처리 입문 7시간 완성(6)]]></title>
            <link>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B16-%EB%A7%88%EC%A7%80</link>
            <guid>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B16-%EB%A7%88%EC%A7%80</guid>
            <pubDate>Sun, 28 Jan 2024 08:57:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>딥러닝을 이용한 자연어처리 입문 7시간 완성 - 메타코드M
<a href="https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM">https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM</a></p>
</blockquote>
<p>6회차는 GPT, BERT 입니다. 드디어 마지막이네요.</p>
<p>BERT나 GPT나 전에 배웠던 Glove, Fast text, SGN, CBOW 같은 word2vec 모델의 일종이다.</p>
<p>미리 대용량 corpus로 학습된 모델을 받아 
원하는 task에 해당하는 부분을 transfer learning으로 fine tune 해줘서 사용하면 된다.</p>
<h2 id="1-bert">1. BERT</h2>
<p>먼저 BERT를 알아보자.</p>
<p>Bidirectional Encoding Representation from Transformer (BERT)</p>
<p>여기서 <code>Bidirectional</code>: 양방향성을 띄고, <code>Encoding</code>: Transformer의 Encoder부분을 활용할 것이다. 이정도 기억하고 가봅시다.</p>
<p>먼저 Bidirectional
<a href="https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B14">4회차때 Bi-LSTM 구조를 공부했었다. </a>
LSTM 모델을 쌓는데, 앞으로도 데이터를 참고하고, 뒤로도 참고하는 그런 구조를 띄었다. BERT도 비슷하다. 
예를 들어 
<code>I love ___ so much.</code> 라는 문장이 있다. 가운데 빈칸에 들어갈 단어를 예측하기 위해 앞의 <code>I love</code>, 뒤의 <code>so much</code> 둘다 참고하여 <code>&#39;you&#39;</code>를 예측한다.</p>
<h4 id="구체적인-구조를-살펴보자">구체적인 구조를 살펴보자</h4>
<img src = https://velog.velcdn.com/images/_chominseo/post/5a51432e-296b-4a8f-b26a-1238b6cabf8c/image.png width=80%>

<p>출처: <a href="https://tutorials.pytorch.kr/intermediate/dynamic_quantization_bert_tutorial.html">https://tutorials.pytorch.kr/intermediate/dynamic_quantization_bert_tutorial.html</a></p>
<ol>
<li><p>(분홍색) 문장 2개를 input으로 받아 두개 사이는 [SEP] 토큰으로 구분한다.</p>
</li>
<li><p>(노란색) 3개의 embedding: 
<code>Token Embedding</code> - 문장 토큰화 결과
<code>Segment Embedding</code> - 문장 단위 임베딩 (앞 문장인지 뒤 문장인지)
<code>Position Embedding</code> - 몇번째 임베딩인지. (Transformer encoder의 position embedding과 같다.)
을 합친다.</p>
</li>
<li><p>(가운데) Transformer Layer를 거친다.
Trasnformer의 encoder부분: <code>Multi-head self-attention</code> -&gt; <code>Add&amp;Norm</code> -&gt; <code>Feed forward</code> -&gt; <code>Add&amp;Norm</code>
을 여러개 쌓아 학습시킨다. 
논문 저자의 실험결과, 
12 transformer block / 768 hidden size / 12 self-attention head 로 이루어진 구조가 최적이라고 한다.</p>
<blockquote>
<img src= https://velog.velcdn.com/images/_chominseo/post/ba76015e-2d37-420e-9894-e2c884838129/image.png width=80%>
출처: https://wikidocs.net/115055
</blockquote>
</li>
<li><p>(초록색) 마지막 layer의 output으로 두가지(<code>MLM</code>, <code>NSP</code>)를 확인한다.</p>
</li>
</ol>
<p><code>Masked Language Model (MLM)</code>: 처음 문장을 input으로 넣어 줄 때 일부 단어를 mask 씌워 입력하고, 이후 출력단에서 맞게 예측했는지 loss를 계산한다.</p>
<ul>
<li><p>전체 문장의 15%를 Masking 한다.</p>
<ul>
<li>그 중 80%는 그대로 masking</li>
<li>10%는 random word로 치환</li>
<li>10%는 원래 단어 그대로 두고</li>
</ul>
<p>성능을 계산한다.</p>
</li>
</ul>
<p><code>Next Sentence Prediction (NSP)</code>: 앞 뒤 문장이 서로 이어지는가
예를 들어
A: <code>I studied hard today</code>
B: <code>It is hard to predict stock market</code>
라면 두 문장이 서로 이어지지 않는다. -&gt; label=0
이어지는가/안 이어지는가 판단하는 Binary Classification과 같다.
Output 중에서 Class Label 값으로 label 값과 비교한다.</p>
<p>이후 원하는 task에 맞춰 </p>
<p>문장 유형을 판단하는 task라면 class label값만 활용하면 되고,
각 단어의 품사를 tagging하는 task라면 각 토큰들의 output 모두를 이용하는 식으로 활용하면 된다.</p>
<h2 id="2-gpt">2. GPT</h2>
<p>BERT와 다르게 앞으로만 예측한다.
즉,
I love ___ very much. 라는 문장이 있으면
[ ] -&gt; [I]</p>
<p>[ I ] -&gt; [I love]</p>
<p>[I love] -&gt; [I love you]</p>
<p>이런식으로 빈칸에 들어갈 단어를 앞의 단어들로만 예측한다.</p>
<h4 id="구조">구조</h4>
<img src=https://velog.velcdn.com/images/_chominseo/post/ac4645d5-e533-4643-bb07-60178979a08f/image.png width=80%>

<p>출처: <a href="https://paperswithcode.com/method/gpt">https://paperswithcode.com/method/gpt</a></p>
<p>오른쪽 부분은 원하는 Task에 맞게 마지막 layer에 붙여주면 된다는 의미고
실제 모델 구조는 Transformer의 Decoder 구조인 왼쪽 모습이다.
<code>Masked multi Self attention</code> -&gt; <code>Layer norm</code> -&gt; <code>Feed forward</code> -&gt; <code>Layer norm</code></p>
<h3 id="코드-구현">코드 구현</h3>
<p><code>pytorch-transformer</code> 라이브러리를 다운받으면 다양한 버전의 BERT를 쓸 수 있다.</p>
<h3 id="총정리">총정리</h3>
<p>BERT GPT 까지 알아봤다. 알기 전에는 뭔가 어마어마한 구조일 것 같았는데,
Vision으로 비유하면 CNN 공부하고, CNN 어떻게 쌓았느냐에 따라 모델이름 붙이는 것 처럼 
Transformer를 어떻게 활용했느냐에 따라 BERT, GPT가 되는거라 아는만큼 보이는걸 다시 느꼈다.</p>
<p>이제 플젝 해보면서 NLP가 어떻게 돌아가는지 자세히 알아보자 + llm 관련해서도 알아보게 llama 논문 읽어보자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] BEIT v2: Masked Image Modeling with Vector-Quantized Visual Tokenizers]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-BEIT-v2-Masked-Image-Modeling-with-Vector-Quantized-Visual-Tokenizers</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-BEIT-v2-Masked-Image-Modeling-with-Vector-Quantized-Visual-Tokenizers</guid>
            <pubDate>Fri, 26 Jan 2024 13:31:05 GMT</pubDate>
            <description><![CDATA[<p>BEIT v3, v1을 읽고 읽었지만, 3개 중 가장 어려운 논문인거 같다.
<a href="https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-BEIT-BERT-Pretraining-of-Image-Transformers">v1 리뷰</a> / <a href="https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Image-as-a-Foreign-Language-BEiT-Pretraining-for-All-Vision-and-Vision-Language-Tasks-BEiT-3">v3 리뷰</a>
Knowledge Distillation이라는 처음보는 개념도 등장하는데, 
일단 이 논문부터 하나씩 봐보자</p>
<blockquote>
<p><a href="https://arxiv.org/abs/2208.06366">https://arxiv.org/abs/2208.06366</a></p>
</blockquote>
<h2 id="abstract">Abstract</h2>
<p>앞선 BEIT v1 논문에서 vision transformer를 학습시킬 때 사용했던 <code>Masked Image Modeling(MIM)</code> 을 이번에도 사용할 건데, v1보다 좀더 high-level semantic을 잘 학습하도록 업그레이드 한 visual tokenizer를 제시한다. 
<code>Vector-quantized knowledge distillation</code> 을 활용할 것이다.
<code>patch aggregation strategy</code> 로 discrete한 image patch들로부터 global semantic representation을 잘 보도록 곁들인다. </p>
<h2 id="1-introduction">1. Introduction</h2>
<p>기본은 BEIT v1과 같이 <code>MIM</code> 방식으로 학습 시키고, <code>image patch</code> 와 <code>visual token</code> 두가지를 학습 재료로 쓸 것이다. 
복습: 원본 이미지를 자르고, 토큰화 하여 visual tokens를 만들고 토큰들 중 일부를 mask로 가려 image patches로부터 가린 visual token을 맞추는 방식으로 학습한다.</p>
<p>MIM 학습 방식은 크게 복원 대상을 기준으로 3가지로 나눌 수 있는데, 1. 픽셀값 자체(low-level image elements), 2. hand-crafted features, 3. visual tokens(-BEIT). 
하지만 이 세가지 모두 직/간접적으로 픽셀값을 맞추는 거랑 크게 다르지 않다. 하지만 NLP 학습을 보면 high-level semantic으로 학습을 하고 있기 때문에, 거기에서 발전 가능성을 보고 출발 했다. </p>
<p>이 논문에서 Semantic-aware visual tokenizer를 학습 시킬 것이다.
<code>Vector-quantized Knowledge Distillation(VQ-KD)</code> 알고리즘으로 semantic space를 표현한다. </p>
<ol>
<li>VQ-KD encoder가 이미지를 learnable codebook에 따라 discrete token으로 변환 한다.</li>
<li>Decoder는 이 discrete token을 가지고 teacher model이 encode한 semantic feature를 복원하는걸 학습한다.</li>
<li>VQ-KD가 학습이 끝나면, encoder는 BEIT v1 구조에서 semantic visual tokenizer로 쓴다.</li>
</ol>
<p>token들이 discrete한 상태이기 때문에 [CLS] token이 global한 image representation을 학습하도록 <code>patch aggregation strategy</code>를 적용한다.</p>
<h2 id="2-methodology">2. Methodology</h2>
<p>리마인드 차원에서
BEIT v1의 image patch - visual token 구조
v2에서는 visual token을 만드는데 <code>vector-quantized knowledge distillation</code> 알고리즘을 활용할 예정
<code>patch aggregation strategy</code> 곁들인다.</p>
<img src = https://velog.velcdn.com/images/_chominseo/post/a50f1fd9-8705-4576-9962-c9d1ba899215/image.png width=90%>

<h3 id="21-image-representation">2.1 Image Representation</h3>
<img src = https://velog.velcdn.com/images/_chominseo/post/536d1da4-d604-4c5f-b535-913591e7537e/image.png width = 30%>


<p>원본 이미지의 representation을 얻기 위해 Backbone network로 ViT를 쓴다. 
원본 이미지를 쪼개 얻은 image patch를 ${x_i^p}<em>{i=1}^N$,
ViT의 output; encoding vector를 ${h_i}</em>{i=1}^N$로 쓴다. 
N은 patch 총 갯수에 해당한다.</p>
<h3 id="22-training-visual-tokenizer">2.2 Training Visual Tokenizer</h3>
<p>VQ-KD를 활용할 예정이고, <code>visual tokenizer</code>, <code>decoder</code>로 이루어진 구조이다.</p>
<img src =https://velog.velcdn.com/images/_chominseo/post/e0c15612-9825-4e89-9f98-841b957ec915/image.png >

<p><code>Visual tokenizer</code> 가 이미지를 <code>visual tokens</code>; discrete codes 으로 매핑한다.
즉, 이미지 $x$를 토큰 $z = [z_1,z_2,...,z_N] \in \nu^{(H/P) \times (W/P)}$으로 토큰화 한다.
이때, $\nu$가 codebook의 code 하나에 해당해서 $\nu \in R^{K\times D}$; 
K discrete codebook embedding을 가진다.</p>
<p>이 Tokenizer는 <code>vision transformer encoder</code>와 <code>quantizer</code>로 이루어져 있다. <code>Tokenizer</code>가 먼저 이미지를 vector($h_i)$로 만들고,
<code>quantizer</code>가 codebook에서 nearest neighbor을 찾아 <code>codebook embedding</code>($v$)을 매칭해 준다.
Nearest neighbor를 $l_2$ norm으로 찾는 과정을 수식으로 보면
$z_i = arg_jmin||l_2(h_i)-l_2(v_j)||_2$</p>
<ul>
<li>Cosine similarity를 찾는 과정과 동일하다.</li>
</ul>
<p>Visual Tokens를 만들면, decoder에 $l_2$-normalized <code>codebook embedding</code> ${l_2(v_{z_i})}<em>{i=1}^N$을 넣어 준다.
decoder도 multi-layer transformer구조로 이루어져 있다. decoder의 <code>output vectors</code> ${o_i}</em>{i=1}^N$ 로 teacher model(DINO, CLIP)의 semantic feature를 학습한다.
즉, teacher model의 feature vector $t_i$와 decoder의 output $o_i$사이의 cosine similarity가 커지도록 학습한다.</p>
<img src=https://velog.velcdn.com/images/_chominseo/post/59bffda0-1c9e-476e-b85a-d3629fe53216/image.png width = 80%>

<p>Quantization process는 미분이 불가능하기 때문에 encoder output을 학습시키기 애매해서, decoder input단의 gradient를 그대로 encoder의 output에 복붙한다.</p>
<p>전체적인 학습 식은 다음과 같다.</p>
<img src = https://velog.velcdn.com/images/_chominseo/post/14df0dc5-365d-4847-b159-a9e925c94268/image.png width = 90%>

<p>D: tokenizer 학습에 쓴 이미지 Data pool
sg[ ] : forward pass 일땐 identity, backward pass일땐 0으로</p>
<p>하나씩 보자.</p>
<ul>
<li>$max\Sigma\Sigma$ -&gt; 모든 이미지의 각 패치에 대해 계산한 값을 최대로 하겠다.</li>
<li>$cos(o_i,t_i)$-&gt; decoder에서 decoder output과 teacher model의 feature vector 사이의 cosine similarity를 최대화 (비슷하게)</li>
<li>$-||sg[l_2(h_i)]-l_2(v_{z_i})||^2_2-||l_2(h_i)-sg[l_2(v_{z_i})]||^2_2$ </li>
<li><blockquote>
<p>forward pass: 학습할 때는 encoder output과 매핑된 codebook embedding vector 사이의 $l_2$ 거리 최소화</p>
</blockquote>
</li>
<li><blockquote>
<p>backward pass: $-||l_2(v_{z_i})||^2_2-||l_2(h_i)||^2_2$ -&gt; gradient를 업데이트 할 때는 각 vector 크기를 줄인다? (이부분은 잘 모르겠다.)</p>
</blockquote>
</li>
</ul>
<p>문제가 있다. Codebook을 쓸 때 &#39;codebook collapse&#39;가 발생한다. ; code들 중 일부만 사용하는 현상.
<code>Empirical strategy</code> 로 해결 가능하다. 
<code>Encoder output</code> 과 codebook 매핑 할 때 $l_2$ norm을 계산한다 했었다. 이때 <code>codebook space embedding</code> 을 32-d로 줄여서 계산하고, 실제 decoder로 넘어가기 전에 dimension을 키워서 전달하는 방식이다.
<code>Exponential moving average</code> 를 계산해 codebook embedding을 업데이트 한다.</p>
<h3 id="23-pretraining-beit-v2">2.3 Pretraining BEIT v2</h3>
<p>BEIT v1 논문에 등장했던 masking 규칙을 따른다. 
요약하자면</p>
<ul>
<li>MIM을 할 때 image patches 앞에 학습 가능한 CLS 토큰을 붙인다.</li>
<li>특정 규칙에 따라 40% 정도에 해당하는 패치를 masking 한다.</li>
<li>masking 한다는 건 원래 image patch 대신 학습가능한 패치 $e$로 대체한다.</li>
<li>마스킹된 부분을 포함한 image patch들로 2.2에서 만든 visual token을 softmax classifier로 예측하도록 학습한다.</li>
<li>Cross Entropy로 loss 연산</li>
</ul>
<img src=https://velog.velcdn.com/images/_chominseo/post/aa506adb-c761-4544-9517-76387ed99082/image.png>

<p><strong>Pretraining Global Representation</strong></p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/8fa31c1d-33b0-4150-96c6-d180653e007f/image.png" alt=""></p>
<p><code>[CLS] 토큰</code>이 global representation 담당이다. 
<code>[CLS] 토큰</code>을 학습시키기 위해 
$l$번째 layer의 output vectors($h^l$)와 마지막 layer(L번째)의 output에서 CLS 토큰을 concat한다. -&gt; $S=[h_{CLS}^L,h_1^l,h_2^l,...,h_N^l]$
이제 이걸 <code>Shallow Transformer decoder</code>에 집어넣는다. figure 3의 오른쪽 두 ViT block이다.
<code>Shallow Transformer decoder</code> 부분은 <code>[CLS] 토큰</code> 학습할 때만 사용해서, 학습 이후엔 안쓴다.
이 <code>shallow transformer</code> output으로 MIM loss 계산을 한다.
최종 Loss는 마지막 layer에서 계산한 MIM loss + <code>shallow~</code>에서 계산한 MIM loss 가 된다.</p>
<p>이유 부분 설명을 직관으로 해 두었는데 잘 이해가 안된다.</p>
<h2 id="3-experiments">3. Experiments</h2>
<p>각종 hyperparameter setting
patch size, ViT 크기, layer 수, epoch 수 등</p>
<h3 id="34-analysis">3.4 Analysis</h3>
<ul>
<li><p>Decoder로 Deeper ViT를 사용하는게 성능이 MIM에 있어 좋지만, codebook usage와 downstream task 성능은 낮아지는 경향을 보인다.</p>
</li>
<li><p>Codebook의 dimension 수를 줄이는게 codebook utilization을 올린다.</p>
</li>
<li><p>Patch aggregation strategy (CLS 토큰 학습용 부분)
l th layer는 9, head depth를 2로 하는게 좋은 성능을 보였다.</p>
</li>
<li><p>VQ-KD target model로 (teacher model) CLIP, DINO 실험 결과 CLIP 성능이 좋았다.</p>
</li>
<li><p>Visualization of codebook</p>
</li>
</ul>
<img src=https://velog.velcdn.com/images/_chominseo/post/3d6dc43e-3b3d-49f6-afa6-653359980890/image.png width=80%>

<h2 id="4-related-work">4. Related Work</h2>
<h4 id="visual-tokenizer">Visual Tokenizer</h4>
<p>VQ-VAE 연계 연구들에서 이미지를 토큰화하는 방식들이 제안되었다.</p>
<h4 id="masked-image-modeling">Masked image Modeling</h4>
<p>MIM method가 여러 연구서 등장한 바 있다.</p>
<h3 id="총정리">총정리</h3>
<p>논문 볼때마다 공부해야할게 늘어난다.
Knowledge Distillation 알아보자
얼른 Transformer 자세히 파보자. CLS token, ViT 대충 아는걸 채워야겠다.
날잡아서 코드도 한번 파자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[딥러닝을 이용한 자연어처리 입문 7시간 완성(5)]]></title>
            <link>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B15</link>
            <guid>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B15</guid>
            <pubDate>Wed, 24 Jan 2024 11:17:13 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>딥러닝을 이용한 자연어처리 입문 7시간 완성 - 메타코드M
<a href="https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM">https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM</a></p>
</blockquote>
<p>5회차는 attention 이론과 LSTM, seq2seq 실습입니다.</p>
<h1 id="1-attention">1. Attention</h1>
<p>attention 관련 정리는 한 번 한적이 있기에 아래링크로 대체
<a href="https://velog.io/@_chominseo/SEQ2SEQ-Attention">https://velog.io/@_chominseo/SEQ2SEQ-Attention</a></p>
<h1 id="2-실습">2. 실습</h1>
<h2 id="단순-구조">단순 구조</h2>
<p>FC layer 2개와 output layer로 이루어진 단순한 구조 먼저 만들어 보자</p>
<pre><code class="language-python">class ANN(nn.Module):
    def __init__(self,num_output,input_size,hidden_size,device=&#39;cpu&#39;):
        super(ANN,self).__init__()
        self.device = device
        self.fc1 = nn.Linear(input_size,hidden_size)
        self.fc2 = nn.Linear(hidden_size,hidden_size)
        self.outlayer = nn.Linear(hidden_size, num_output)
    def forward(self,x):
        h = self.fc1(x).relu()
        h = self.fc2(h).relu()
        predict = self.outlayer(h)
        return predict</code></pre>
<p>input size -&gt; hidden size -&gt; hidden_size -&gt; num_output
으로 channel수를 구성한 구조이다.</p>
<hr>
<h2 id="lstm">LSTM</h2>
<img src=https://velog.velcdn.com/images/_chominseo/post/d40e2282-dc5c-4869-993a-8145d807479d/image.png width=80%>

<p>출처: <a href="https://wikidocs.net/152773">https://wikidocs.net/152773</a>
LSTM 구조를 다시 보면 input과 이전 시점의 <code>cell state</code>, <code>hidden state</code> 가 들어가
다음 LSTM block을 위한 <code>cell state</code>, <code>hidden state</code>를 만들고, <code>output</code> 하나를 뽑아 낸다.</p>
<pre><code class="language-python">class LSTM_net(nn.Module):
    def __init__(self,num_output,size_vocab, dim_embed, hidden_size,linear_size,num_layers,device=&#39;cpu&#39;):
        super(LSTM_net,self).__init__()
        self.device = device
        self.num_output = num_output
        self.hidden_size = hidden_size
        self.num_layers = num_layers

        self.embed = nn.Embedding(size_vocab,dim_embed)

        self.lstm = nn.LSTM(input_size = dim_embed, hidden_size = hidden_size, num_layers = num_layers, dropout = 0.3, bidirectional = True)
        self.fclayer = nn.Linear(hidden_size, linear_size)
        self.outlayer = nn.Linear(linear_size, num_output)

    def forward(self, x):
        scaler = 2 if self.lstm.bidirectional == True else 1

        emb = self.embed(x)

        h_state = Variable(torch.zeros(self.num_layers*scaler,emb.size(0),self.hidden_size,requires_grad=True)).to(self.device)
        c_state = Variable(torch.zeros(self.num_layers*scaler,emb.size(0),self.hidden_size,requires_grad=True)).to(self.device)

        lstm_out,(h,c) = self.lstm(emb.transpose(1,0),(h_state,c_state))
        h = h[-1]
        h = self.fclayer(h).relu()
        predict = self.outlayer(h)
        return predict</code></pre>
<p>forward 함수를 기준으로 부분 부분 뜯어 보자</p>
<pre><code class="language-python">emb = self.embed(x)</code></pre>
<p>x를 input으로 생각하면 된다. x가 들어와 self.embed를 거친다.</p>
<pre><code>self.embed = nn.Embedding(size_vocab,dim_embed)</code></pre><p>nn.Embedding이 등장하는데, 이건 x를 가지고 학습가능한 <code>embedding vector</code>를 생성해준다. 
<code>size_vocab</code>은 전체 단어 종류, <code>dim_embed</code>는 <code>embedding vector</code>를 몇 channel로 뽑을 것인지 정해주면 된다. 
즉, x 라는 문장이 들어가면 <code>[batch, size_vocab, dim_embed]</code> 크기의 <code>embedding vector</code> 가 생성된다.</p>
<p>다음</p>
<pre><code class="language-python">h_state = Variable(torch.zeros(self.num_layers*scaler,emb.size(0),self.hidden_size,requires_grad=True)).to(self.device)
c_state = Variable(torch.zeros(self.num_layers*scaler,emb.size(0),self.hidden_size,requires_grad=True)).to(self.device)</code></pre>
<p>LSTM이 만들어내는 hidden state와 cell state들을 일단 0으로 다 초기화 해 준다.
shape은 <code>[num_layers, batch, hidden_size]</code>
<code>num_layers</code>: LSTM block을 몇 번 쌓을 건지
<code>hidden_size</code>: LSTM 안에서 돌아가는 channel 수</p>
<p>scaler는 bidirectional 하게 할지 고려하는 부분이니 양방향으로 간다면 기존의 2배가 필요해서 scaler를 곱해준다.</p>
<p>다음</p>
<pre><code class="language-python">lstm_out,(h,c) = self.lstm(emb.transpose(1,0),(h_state,c_state))</code></pre>
<p>LSTM에 input에서 얻은 embedding vector와 hidden state, cell state를 지정해 돌려준다.
이때 emb.transpose 부분에서 기존 shape이 <code>[batch, size_vocab, dim_embed]</code> 였던 emb를 <code>[size_vocab, batch, dim_embed]</code> 로 바꿔 넣어줘야 한다. (--batch size가 두번째에 오게)</p>
<p>다음</p>
<pre><code class="language-python">h = h[-1]
h = self.fclayer(h).relu()
predict = self.outlayer(h)
   return predict</code></pre>
<p>classification task에서 필요한 부분은 마지막 h 또는 c 만 있으면 되기 때문에 마지막 h만 FC layer에 넣고, outlayer에 넣어 class 갯수만큼의 channel 수로 만들어 준다.</p>
<hr>
<h3 id="전처리">전처리</h3>
<p><a href="https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B13">3회차에서 했던 전처리 과정</a> 참조</p>
<p>토큰화, 정제/추출, 정수인코딩 까지 해주자.</p>
<h4 id="padding">Padding</h4>
<p>각 문장별로 포함된 토큰 수가 다 제각각이기 때문에 가장 긴 문장 기준으로 나머지 문장에 Padding을 추가해 주자.</p>
<pre><code class="language-python">maxlen = 100
rowdata = []
for w in text_encoded:
    if len(w)&gt;=maxlen:
        rowdata.append(w[:maxlen])
    else:
        rowdata.append(np.pad(w,(0,maxlen),&#39;constant&#39;,constant_values=0)[:maxlen])
text_padded = np.concatenate(rowdata,axis=0).reshape(-1,maxlen)
print(text_padded.shape)</code></pre>
<p>근데 가장 긴 문장이 너무 길어서 100 토큰만 봐도 판단할 수 있으리라 생각하여 최대 길이를 100으로 하고, 긴 문장은 잘라주고,
짧은 문장은 np.pad 함수를 활용해 <code>&lt;pad&gt;</code> 의 토큰 값을 0으로 늘려 주자.</p>
<hr>
<h3 id="dataset-dataloader">Dataset, DataLoader</h3>
<pre><code class="language-python">from torch.utils.data import DataLoader, random_split
from torch import LongTensor as LT
from torch import FloatTensor as FT

class Generate_Dataset(torch.utils.data.Dataset):
    def __init__(self,xdata,ydata,device=&#39;cpu&#39;):
        self.x_data = xdata
        self.y_data = ydata
        self.device = device
    def __len__(self):
        return len(self.x_data)
    def __getitem__(self,idx):
        x = LT(self.x_data[idx]).to(self.device)
        y = LT(self.y_data[idx]).to(self.device)
        return x,y</code></pre>
<p>x에 문장, y에 분류 문제 라벨값을 넣어 LongTensor 형태로 반환하는 class를 정의하자.
vision 할 때는 cv2로 이미지 열어 그냥 tensor로 만들어 반환했는데 단어는 정수 인코딩을 했기 때문에 int형을 쓸 때 쓰는 Longtensor로 지정해 반환한다.</p>
<pre><code class="language-python">dataset = Generate_Dataset(text_padded,text_label.reshape([-1,1]))
train_dataset,test_dataset = random_split(dataset,[int(len(dataset)*0.8),int(len(dataset)*0.2)])
train_loader = DataLoader(train_dataset,batch_size=256,shuffle=True)
test_loader = DataLoader(test_dataset,batch_size=500,shuffle=False)</code></pre>
<p>dataset, data loader를 정의해 주자.</p>
<h3 id="모델-정의-및-학습">모델 정의 및 학습</h3>
<pre><code class="language-python">lstm_net = LSTM_net(num_output=2, size_vocab=5000,
                    dim_embed=64,hidden_size=64, linear_size=64,num_layers=2)
optimizer = torch.optim.Adam(lstm_net.parameters(),lr = 0.01)</code></pre>
<p>앞에서 만든 LSTM 모델을 정의하자. size vocab에 내가 쓴 tokenizer가 정수 인코딩 할 때 최대로 쓴 숫자(--unique한 token 수)보다 크게 써야한다.
optimizer는 adam을 썼다.</p>
<pre><code class="language-python">from tqdm import tqdm
def train(train_loader):
    for epoch in range(10):
        epoch_loss = 0
        for x,y in tqdm(train_loader):
            predict = lstm_net(x)
            loss = torch.nn.functional.cross_entropy(predict,y.ravel())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            epoch_loss+=loss.item()
        print(f&#39;train epoch {epoch+1} loss: {epoch_loss:6f}&#39;)</code></pre>
<p>tqdm이 퍼센트, 남은시간을 알려줘서 좋다. 한 에폭마다 평균 loss값을 찍게 해 놨다.</p>
<p>loss function으로 cross entropy를 사용 했다. 
여기서 y.ravel()이 등장한다. 1차원으로 평평하게 펴주는 함수이다.
예를 들어,
<code>[[1,2],[3,4]]</code> 인걸 <code>[1,2,3,4]</code> 로 만들어주는 함수이다.</p>
<pre><code>100%|██████████| 32/32 [00:12&lt;00:00,  2.47it/s]
train epoch 1 loss: 22.009017
100%|██████████| 32/32 [00:15&lt;00:00,  2.08it/s]
train epoch 2 loss: 20.640763
100%|██████████| 32/32 [00:15&lt;00:00,  2.13it/s]
train epoch 3 loss: 18.696785
100%|██████████| 32/32 [00:14&lt;00:00,  2.14it/s]
train epoch 4 loss: 16.637502
100%|██████████| 32/32 [00:14&lt;00:00,  2.14it/s]
train epoch 5 loss: 15.229966
100%|██████████| 32/32 [00:14&lt;00:00,  2.18it/s]
train epoch 6 loss: 14.672411
100%|██████████| 32/32 [00:14&lt;00:00,  2.17it/s]
train epoch 7 loss: 14.386816
100%|██████████| 32/32 [00:14&lt;00:00,  2.15it/s]
train epoch 8 loss: 14.013005
100%|██████████| 32/32 [00:15&lt;00:00,  2.13it/s]
train epoch 9 loss: 13.750575
100%|██████████| 32/32 [00:14&lt;00:00,  2.19it/s]
train epoch 10 loss: 13.491799</code></pre><p>요런식으로 찍힌다.</p>
<hr>
<h3 id="test">Test</h3>
<pre><code class="language-python">def test(test_loader):
    score = 0
    cnt = 0
    for x,y in tqdm(test_loader):
        predict = lstm_net(x).argmax(1).detach().numpy()
        answer = y.ravel().detach().numpy()
        for i in range(len(predict)):
            cnt+=1
            if predict[i]==answer[i]:
                score+=1
    print(f&#39;test score: {score/cnt*100:6f}%&#39;)</code></pre>
<p>마지막 열심히 학습시켰으니 점수를 확인해 보자</p>
<p>전체 갯수에서 정답인거만 카운트해 accuracy를 찍는다.</p>
<pre><code>100%|██████████| 4/4 [00:01&lt;00:00,  2.42it/s]test score: 69.600000%</code></pre><p>70점 정도 나온다.</p>
<h2 id="seq2seq">seq2seq</h2>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/b3579fbf-ac06-4295-bf79-0d43f067edcc/image.png" alt=""></p>
<p>seq2seq는 encoder - decoder로 이루어진 구조고, 각각 안에는 LSTM들이 쌓여있는 형태다.
위 그림처럼 번역 task를 한다고 가정하자.</p>
<h3 id="encoder">Encoder</h3>
<pre><code class="language-python">class seq_Encoder(nn.Module):
    def __init__(self, vocab_size, dim_embed,hidden_size,num_layers,dropout):
        super().__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers

        self.embed = nn.Embedding(vocab_size, dim_embed)
        self.lstm = nn.LSTM(dim_embed, hidden_size, num_layers, dropout = dropout)
        self.dropout = nn.Dropout(dropout)
    def forward(self,src):
        outputs,(hidden,cell) = self.lstm(self.dropout(self.embed(src)))
        return hidden,cell</code></pre>
<p>Encoder는 문장 전체를 <code>input_data</code>로 받아 LSTM을 통과 시킨다.</p>
<p>앞에서 했던 LSTM network에서 끝에 FC layer만 뺀 것과 같은 형태를 보인다.
그래야 <code>Context Vector</code>를 decoder에 전달할 것이다.</p>
<h3 id="decoder">Decoder</h3>
<pre><code class="language-python">class seq_Decoder(nn.Module):
    def __init__(self, output_size, dim_embed, hidden_size, num_layers, dropout):
        super().__init__()

        self.output_size = output_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers

        self.embed = nn.Embedding(output_size, dim_embed)
        self.lstm = nn.LSTM(dim_embed,hidden_size, num_layers,dropout = dropout)
        self.fclayer = nn.Linear(hidden_size, output_size)
        self.dropout = nn.Dropout(dropout)
    def forward(self,input_data, hidden,cell):
        input_data = input_data.unsqueeze(0)
        embedded = self.dropout(self.embed(input_data))
        output,(hidden,cell) = self.lstm(embedded,(hidden,cell))
        prediction = self.fclayer(output.squeeze(0))

        return prediction, hidden, cell</code></pre>
<p>Decoder는 encoder가 준 <code>context vector</code>를 받을 것이고, 매번 <strong>단어 하나만</strong> 받아 <code>input_data</code>로 사용할 것이다.
decoder도 같고 encoder과 다른점은 FC layer까지 해서 <code>Prediction</code>에 해당하는게 다음 단어가 되어 <code>hidden state</code>, <code>cell state</code>와 같이 전달한다.</p>
<h3 id="seq2seq-1">seq2seq</h3>
<pre><code class="language-python">import random

class seq2seq(nn.Module):
    def __init__(self,encoder, decoder ,device = &#39;cpu&#39;):
        super().__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.device = device

    def forward(self,source,target,tf_ratio=0.5):
        batch_size = target.shape[1]
        translation_length = target.shape[0]
        target_vocab_size = self.decoder.output_size

        outputs = torch.zeros(translation_length, batch_size, target_vocab_size).to(self.device)
        hidden,cell = self.encoder(source)
        input_trans = target[0,:]

        for t in range(1,translation_length):
            output,hidden,cell = self.decoder(input_trans, hidden,cell)
            outputs[t] = output
            teacher_force = random.random()&lt;tf_ratio
            input_trans = target[t] if teacher_force else output.argmax(1)
        return outputs</code></pre>
<p>합치는 부분이다. 하나씩 보자</p>
<pre><code class="language-python">outputs = torch.zeros(translation_length, batch_size, target_vocab_size)</code></pre>
<p>outputs에 최종 번역된 문장을 담을 예정이다. 미리 0으로 초기화해 둔다.</p>
<hr>
<pre><code class="language-python">hidden,cell = self.encoder(source)</code></pre>
<p>인코더에 입력 문장을 넣고 context vector를 받는다.</p>
<hr>
<pre><code class="language-py">input_trans = target[0,:]</code></pre>
<p>Decoder의 첫 입력으로 쓸 <code>&lt;sos&gt;</code>를 정의하고, </p>
<pre><code class="language-py">output,hidden,cell = self.decoder(input_trans, hidden,cell)</code></pre>
<p>Encoder가 뱉은 hidden, cell과 함께 넣어준다.</p>
<hr>
<pre><code class="language-py">for t in range(1,translation_length):
    output,hidden,cell = self.decoder(input_trans, hidden,cell)
    outputs[t] = output
    teacher_force = random.random()&lt;tf_ratio
    input_trans = target[t] if teacher_force else output.argmax(1)</code></pre>
<p>Decoder가 뱉은 hidden state, cell state, output을 받아 다시 decoder에 넣는 것을 반복하는데, 
아래 두 줄 teacher force로 특정 decoder가 잘못 예측했을 때 정답으로 바꿔 넣어줄지 말지를 tf_ratio보다 크면 제대로, 아니면 틀린거 그대로 넣어주는 코드가 추가되어 있다.</p>
<hr>
<h3 id="모델-정의">모델 정의</h3>
<pre><code class="language-py">enc = seq_Encoder(x_vocab_size,64,64,1,0.3)
dec = seq_Decoder(y_vocab_size,64,64,1,0.3)
seq_net = seq2seq(enc,dec).to(&#39;cpu&#39;)</code></pre>
<p>번역이면 언어마다 사용한 tokenizer가 다를테니 encoder와 decoder에 들어갈 vocab size가 달라질 테니 고려해서 정의해 주자.</p>
<p>그러고 학습돌려주고 하면 된다.</p>
<h2 id="총정리">총정리</h2>
<p>Transformer를 사실 기대하고 이번 회차부분을 들었는데 없었고,
attention 실습도 없었다. 다음 회차가 마지막 GPT BERT 이다보니 Transformer 얘기가 마구 나올텐데 미리 혼자서라도 해보자.</p>
<p>Encoder-Decoder 구조까지 해서 그래도 NLP 전체 프로세스를 모델 짜는 것 부터해서 해보니 감이 좀 잡히는 것 같다. (+ pytorch로 실습해주셔서 감사하다.)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Visual Question Answering: A survey on Techniques and Common Trends in Recent Literature]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Visual-Question-Answering-A-survey-on-Techniques-and-Common-Trends-in-Recent-Literature</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Visual-Question-Answering-A-survey-on-Techniques-and-Common-Trends-in-Recent-Literature</guid>
            <pubDate>Tue, 23 Jan 2024 11:21:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://arxiv.org/abs/2305.11033">https://arxiv.org/abs/2305.11033</a></p>
</blockquote>
<p>VQA 분야 23년 6월에 나온 survey논문이다.
VQA가 뭐하는건지, 어떤 모델들이 있는지, 등 알아보자</p>
<h2 id="1-introduction">1. Introduction</h2>
<p>VQA는 아무래도 multi-modal task 이기에 다른 modality를 합친다는데에서 어려움이 생긴다.</p>
<h2 id="2-visual-question-answering-vqa">2. Visual Question Answering (VQA)</h2>
<p>VQA는 image-question pair가 주어지면, 답의 정확도로 성능을 판단한다.
2017년 데이터셋인 VQA v1이 처음 나왔을 때, 도메인 불균형이나 난이도 불균형 같은 여러 문제가 많았다. </p>
<p>VQA의 첫 시도는 논문 지필자가 만든 데이터셋으로 57.75%를 달성한 이미지는 VGGNet으로, question은 deep LSTM으로 supervised learning 방식으로 학습한 모델이다. 
그 이후로 각종 복잡한 모델들이 등장한다.
bias-mitigation architectural branches, trilinear transformers, attention, external knowledge incorporation 등.</p>
<p>양이 많고, 고르게 분포된 데이터 셋인 VQA v2이 등장하고 현재 SOTA는 visual, language 둘 다에 large scale pre-trained Multiway Transformer를 활용한 연구가 84.03% 이다.</p>
<h2 id="3-known-approches">3. Known Approches</h2>
<p>각종 연구들을 소개한다. - 29개 연구가 소개되어 있는데 차차 읽어 보자</p>
<h2 id="4-methodology">4. Methodology</h2>
<h3 id="41-datsets">4.1 Datsets</h3>
<p>VQA v1, v2
VQA CP v1,v2: VQA v1,v2 에서 answer에 bias를 줄인 버전이다.
Medical VQA: medical특화로 전문가분이 만들어준 high quality 버전이다.
GQA: Visual Genome 관련</p>
<h3 id="42-metrics">4.2 Metrics</h3>
<p>주로 나오는 평가방법을 알아보자</p>
<h3 id="421-accuracy">4.2.1 Accuracy</h3>
<p>$Acc = min(\frac{num, of ,humans, that, provided, that, answer}{3},1)$
주관식 객관식 모두 해당된다.
human annotator 3명 이상이 정답을 인정하면 최고점을 얻는다.
가장 많이 쓰인다.</p>
<h3 id="422-bleu">4.2.2 BLEU</h3>
<p>BiLingual Evaluation Understudy(BLEU)
주관식 문제에 적합한 방법이다. 
사람이 적은 답과 비교해 fluency, adequacy, length를 고려한다.
modified precision score를 정답 후보들에 n-gram을 적용해 계산한다.</p>
<p>먼저, 정답 후보의 n-gram들 중 reference에 등장하는 횟수를 센다. : C
그리고, 각 reference 문장들에 같은 n-gram이 등장하는 횟수를 센다. : $R_k$
$k$: reference 문장 번호.
Count clip: $C_{clip}=min(C,max,R)$ 으로 
modified precision score: $p_n = \frac{\Sigma C_{clip}}{\Sigma C}$ 
단어의 길이를 고려하기 위해 brevity penalty BP를 계산한다. 
$r_{words}, c_{words}$가 각각 reference 문장의 단어 수, candidate 문장의 단어 수로
$BP = 1$ if  $c_{words} &gt; r_{words}$
$BP = e^{\frac{1-r_{words}}{c_{words}}}$ if $c_{words} \leq r_{words}$
최종 $BLEU = BP \times exp(\sum_{n=1}^{N} w_nlogp_n)$
N: number of n-grams, $w_n$: precision weight. 보통 1/N</p>
<h2 id="6-discussion">6 Discussion</h2>
<h3 id="61-sota">6.1 SOTA</h3>
<p>BEIT-3이 현재 VQA v2 dataset 기준 SOTA이다. 
test-dev dataset 기준으론 PaLI가 SOTA이나 코드공개가 안돼 있고, 2등은 BEIT-3이다.
VQA-CP2 기준으론 D-VQA에서 backbone을 교체하는 식으로 LXMERT, UpDn 순으로 좋다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] BEIT: BERT Pretraining of Image Transformers]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-BEIT-BERT-Pretraining-of-Image-Transformers</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-BEIT-BERT-Pretraining-of-Image-Transformers</guid>
            <pubDate>Tue, 23 Jan 2024 06:36:31 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://arxiv.org/abs/2106.08254">https://arxiv.org/abs/2106.08254</a></p>
</blockquote>
<p>BEIT v1</p>
<h2 id="abstract">Abstract</h2>
<p>Bidirectional Encoder representation from Image Transformers(BEIT)</p>
<p>이미지를 <code>image patches</code> , <code>visual tokens</code> 이 두가지로 봐서 transformer를 <code>masked image modeling</code> 방법으로 pre-train 시키는 방법을 제안한다.</p>
<p>다시 말해, 이미지를 &quot;토큰화&quot;하여 <code>visual tokens</code> 로 쪼개고, 이미지를 쪼개기만 한 <code>image patches</code> 중 일부를 mask하여 mask된 부분의 <code>visual token</code> 값을 예측하도록 학습시켰다.</p>
<p>이후 classification, segmentation에 적용시켜 보았다.</p>
<h2 id="1-introduction">1. Introduction</h2>
<p>Transformer가 등장하고, vision 쪽에도 쓰이기 시작하면서, vision transformer를 학습하는데 CNN보다 더 많은 데이터가 필요해졌다. 
이를 해결하기 위해 self-supervised 방식으로 해결하려 했고, <code>contrastive learning</code> 과 <code>self-distillation(?)</code> 방식으로 접근하였다.</p>
<p>BERT가 NLP에서 성공적이었던건 input text 일부를 mask하고 맞추는 방식으로 transformer를 학습했기 때문이다. 
이 아이디어를 vision으로 끌어와서 할건데 고려할 게 있다.
-&gt; 언어와 다르게 이미지에는 pre-exist vocabulary가 없다.
따라서 mask된 부분을 예측할 때 후보라고 할 만한게 없어 softmax를 무한히 할 수도 없는 노릇이니 애매하다.
-&gt; 이걸 regression으로 각 픽셀값을 예측하게 하면 어떨까. 모델이 너무 세세한 부분(short range dependency, high-frequency detail)을 잡는데 낭비가 커진다는 문제가 생긴다.</p>
<p>이 논문에서 위 문제 해결을 위해 <code>Masked Image Modeling (MIM)</code> 을 제안한다.</p>
<img src=https://velog.velcdn.com/images/_chominseo/post/645d3583-a134-481e-a54b-cbba7540b8a3/image.png>

<ol>
<li>이미지를 패치단위로 쪼개고, 그 중 일부를 mask해 <code>special mask embedding [M]</code> 으로 대체하여 backbone vision Transformer의 입력으로 넣어준다. -&gt; Image Patches</li>
<li>이미지를 discrete VAE에서 사용한 코드로 토큰화해 준다.(-자세한건 VAE를 공부해보자) -&gt; Visual Tokens</li>
<li>Transformer가 Image patch들을 보고 [M] 부분의 Visual token을 예측하도록 학습시킨다.</li>
</ol>
<p>차이점: 기존엔 [M]부분의 실제 픽셀값을 예측하도록 했다면 BEIT에서는 visual token값을 예측하도록 한다.</p>
<h2 id="2-methods">2. Methods</h2>
<p>input image $x$가 주어졌을 때 어떤일이 일어나는지 구체적으로 알아보자.</p>
<h3 id="211-image-patch">2.1.1 Image Patch</h3>
<p>$x$의 shape이 $H\times W\times C$라 하면 이걸 N개의 patch로 쪼개
각 Patch $x^p$의 shape이 $P^2C$가 되도록 한다. 그러면 패치의 갯수 $N = HW/P^2$가 될 것이다.
이후 패치들을 flatten해 BEIT의 입력으로 사용된다.
구체적으로 논문에서 원본 이미지 224x224짜리를 각 패치 크기가 16x16이 되도록 총 14x14개의 패치로 쪼개 실험했다.</p>
<h3 id="212-visual-token">2.1.2 Visual Token</h3>
<p><code>discrete Variational Autoencoder(dVAE)</code>의 tokenizer를 사용했다. 
<code>픽셀 값</code> ; $x$들이 주어졌을 때 <code>토큰 값</code> ; $z$를 계산하는 <code>tokenizer</code> ; $q_\phi(z|x)$과, <code>토큰 값</code> ; $z$들을 보고 다시 원본 <code>픽셀 값</code> ; $x$를 복원하는 <code>decoder</code> ; $p_\psi(x|z)$로 이루어져있다. </p>
<p>따라서 학습 목표는 복원하는 decoder의 정확도를 높이는
$E_{z \sim q_\phi(z|x)}[logp_\psi(x|z)]$ 최대화 이다.</p>
<p>근데 visual token값들이 discrete하기 때문에 미분 불가능이라 학습할 때 <code>Gumbel-softmax relaxation(?)</code>을 활용했다.</p>
<p>또 학습시킬때 $q_\phi$는 uniform prior로 고정시켜놓고 했다.</p>
<p>image patch를 쪼갤때 처럼, visual token도 14x14개의 값을 가지도록 했고, vocabulary size는 8192로 설정, q는 &lt;<a href="https://arxiv.org/abs/2102.12092">DALL-E: Zero-Shot Text-to-Image Generation</a>&gt; 논문의 것을 그대로 가져와 사용했다.</p>
<h3 id="22-backbone-network-image-transformer">2.2 Backbone Network: Image Transformer</h3>
<p>ViT말고, standard Transformer구조를 활용했다.
Image patches $x_i^p$를 linearly project하여 $Ex_i^p$로 만들고,
앞에 Special token [s]를 붙이고, 
Position Embedding을 붙여 transformer의 input으로 사용했다.
즉, input vectors $H_0 = [e_{[s]},Ex_i^p,...,Ex_N^p]+E_{pos}$ 이다.
이후 L layer의 transformer block들을 거쳐 최종 L번째 layer의 output vector가 각 image patch들의 encoded representations이다.</p>
<h3 id="23-pre-training-beit-masked-image-modeling">2.3 Pre-Training BEIT: Masked Image Modeling</h3>
<p>학습 목표는 모든 이미지 패치에서 visual token을 맞추도록 하는게 아니라 masked patch에서만 softmax를 한 결과를 가지고 계산했다. </p>
<p>이미지 패치들 중 mask할 때 단순 무작위로 하는게 아니라 알고리즘을 활용하여 정해진 범위내에서 0.4비율 이상 mask되도록 하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[딥러닝을 이용한 자연어처리 입문 7시간 완성(4)]]></title>
            <link>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B14</link>
            <guid>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B14</guid>
            <pubDate>Mon, 22 Jan 2024 17:25:35 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>딥러닝을 이용한 자연어처리 입문 7시간 완성 - 메타코드M
<a href="https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM">https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM</a></p>
</blockquote>
<p>4회차 RNN, LSTM,GRU, seq2seq, 1DCNN, Bi-LSTM 
언어의 시계열 특성을 살린 인코더 구조를 알아보자</p>
<p>목차</p>
<ol>
<li>RNN 원리 및 구조</li>
<li>LSTM, GRU</li>
<li>Seq2seq</li>
<li>1D CNN</li>
<li>Bi-LSTM</li>
</ol>
<h2 id="1-rnn-원리-및-구조">1. RNN 원리 및 구조</h2>
<p>약자를 풀어 쓰면 <code>Recurrent Neural Network (RNN)</code>이다.
여기서 <code>recurrent</code> 라는 말이 왜 붙었는지가 중요하다.</p>
<p>우선 배경 지식으로
<code>First-Order system</code> 은 현재 시간의 상태가 이전 시간의 상태와 관련이 있는 system이다.
수식으로 표현하면 $x_t = f(x_{t-1})$ 로 쓸 수 있다. 즉, t시점의 상태가 t-1시점의 함수로 표현 가능하다.
( 하나 더 가서 현재 시점이 앞의 두 시점과 관련 있다면, $x_t = f(x_{t-1}, x_{t-2})$는 second order system이다. )</p>
<p>여기까지는 현재에 추가적인 입력 없이 초기 값 ($x_0$)만 있으면 이후 모든 시점을 계산할 수 있었다. (Autonomous system)</p>
<p>현재 입력($u_t$)가 주어지는 경우를 수식으로 쓰면
$x_t = f(x_{t-1},u_t)$ 로 쓸 수 있다. 이제 곧 알아볼 RNN의 형태이다.</p>
<p>근데 t시점의 상태를 표현한 $x_t$가 관측 가능하냐 하면 관측 가능한 부분도 있고, 그렇지 않은 부분도 있다.</p>
<p>주식을 예로 들면, 관측 가능한 부분으로는 이전 시점의 주가, 금리, 비슷한 회사의 주가 등이 있을테고, 관측 불가능한 부분은 사람들 투자 심리, 분위기 같은게 있을 수 있다.</p>
<p>관측 가능한 상태만 모은 것을 출력 $y_t$로 표현하고, 수식으로는
$y_t = h(x_t)$로 $x_t$의 함수로 표현할 수 있다.</p>
<p>이제 RNN의 구조를 보면
<img src="https://velog.velcdn.com/images/_chominseo/post/b028993e-dc5b-4865-9b09-8b9db88ff894/image.png" alt=""></p>
<p>출처: <a href="https://velog.io/@yuns_u/%EC%88%9C%ED%99%98-%EC%8B%A0%EA%B2%BD%EB%A7%9DRNN-Recurrent-Neural-Network">https://velog.io/@yuns_u/%EC%88%9C%ED%99%98-%EC%8B%A0%EA%B2%BD%EB%A7%9DRNN-Recurrent-Neural-Network</a></p>
<p>위 그림에서는 입력($u_t$)을 $x_t$, 각 시점의 상태($x_t$)를 $h_t$, 출력($y_t$)를 $o_t$로 쓰고 있음을 참고하자</p>
<p>가장 왼쪽부분을 보면 $x_t$가 모델에 들어가고, 출력이 다시 모델로 또 들어가는 화살표가 있다. 이거 때문에 <code>recurrent</code> 라는 단어가 붙었고, 이런 구조를 <code>self feedback</code> 이라고 부른다.</p>
<p>등호 오른쪽이 구조를 풀어서 그린 설명이다. parameter로는
입력-상태 사이의 $W_{hx}$,
Self feedback의 $W_{hh}, b_h$,
상태-출력의 $W_{oh}, b_o$ 로 총 5개가 필요하고, 수식으로 보면</p>
<p>t 시점의 상태인 $h_t = \sigma(W_{hh}h_{t-1}+W_{hx}x_t+b_h)$ 로 
<code>이전 시점의 상태</code>, <code>현재의 입력</code> 에 대한 식으로 표현 할 수 있고,
t 시점의 출력은 $y_t = \sigma(W_{oh}h_t+b_o)$ 로
<code>현재의 상태</code> 에 대한 식으로 표현 할 수 있다.</p>
<p>학습은 Backpropagation Through Time (BPTT)로 한다.</p>
<p>형태의 종류로는
<code>many-to-many</code>: Loss 계산시 각 시점의 출력(y)들을 모두 활용 Ex) 번역
<code>many-to-one</code>: 마지막 시점의 출력만 가지고 Loss 계산 Ex) 예측
<code>one-to-many</code>: 입력 하나만 주어진 경우 Ex) 문장 생성
가 있다.</p>
<h2 id="2-lstm-gru">2. LSTM, GRU</h2>
<p>gradient flow를 제어하는 밸브 역할을 추가했다고 생각하면 된다.</p>
<img src = https://velog.velcdn.com/images/_chominseo/post/e130517a-f413-4de0-8499-4debfa6d88a1/image.png width=80%>

<p>출처: <a href="https://wikidocs.net/152773">https://wikidocs.net/152773</a></p>
<p>각 Gate의 역할을 간단하게만 보면</p>
<ol>
<li>Input Gate는 들어온 입력인 $x_t$ 를 얼마나 사용할 지 결정한다.</li>
<li>Forget Gate는 이전 시점의 상태 $h_{t-1}$를 얼마나 잊을지를 결정한다.</li>
<li>Input Gate와 Forget Gate를 거쳐 나온걸 섞어서 다음 cell로 보낸다.</li>
<li>Output Gate가 지금까지 한걸 종합해서 output을 뽑아낸다.</li>
</ol>
<p>GRU는 LSTM의 간단화 버전인데, GRU가 간단하니 학습시간이 짧고 그런 장점은 있겠지만 둘 중에 뭐가 더 낫다는 실험을 통해서만 알 수 있다. (기본 RNN 구조보다는 당연히 둘 다 좋다.)</p>
<h2 id="3-seq2seq">3. Seq2Seq</h2>
<p>우선 등장한 이유인 RNN의 단점:
Recurrent 구조인 만큼 시점 t가 반복될 수록 거기에 해당하는 Weight인 $W_{hh}$가 계속해서 곱해지는데, backpropagation을 할 때 (CNN에서 ResNet이 등장하기 전 CNN을 깊이 쌓을 때 발생하는 문제였던) <code>Exploding/Vanishing gradient</code> 문제가 발생한다.</p>
<p>Seq2Seq의 구조는 <code>many-to-one</code> + <code>one-to-many</code> 로 볼 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/_chominseo/post/ee5d60ae-4174-431d-ab36-1b907efa1552/image.png" alt=""></p>
<p>인코더: 문장을 입력해 전체에 대한 정보를 담은 <code>Context Vector</code>를 뽑아낸다. (초기 상태 $h_0$는 랜덤하게 결정)
디코더: <code>Context Vector</code>를 초기 상태로 활용해 출력을 만들어 낸다. 첫 입력은 문장의 시작이라고 알려주는 <code>&lt;sos&gt;</code>를 넣어주고, $y_{t-1}$과 이전 상태를 입력으로 활용해 $y_t$를 얻고, 마지막 출력으로는 문장의 끝이라는 의미인 <code>&lt;eos&gt;</code>를 내보낸다.</p>
<p>학습 단계에서는 분명 이전 block이 제대로된 단어를 예측했으리란 보장이 없기 때문에 <code>Teacher force training</code> 으로 학습한다.
설령 $y_{t-1}$이 이상한 단어이더라도, $x_t$로는 정답을 넣어주는 방법이다.</p>
<p>예를 들어, 학습할 떄 그림의 두번째 block에서 <code>je</code>를 입력으로 받아 <code>suis</code>를 출력했어야 한다. 만약 <code>suis</code> 대신 <code>asdf</code>를 출력했다 하더라도 다음 block의 input으로는 정답인 <code>suis</code>를 넣어준다.</p>
<p>seq2seq도 분명 기본 RNN 구조보다 좋지만 업그레이드 버전인 Attention이 매우 효과적이다.</p>
<h2 id="4-1d-cnn">4. 1D-CNN</h2>
<p>이미지의 공간 구조를 활용핸 구조인 CNN을 언어에 대입시켰다.</p>
<img src= https://velog.velcdn.com/images/_chominseo/post/2bd6fd64-3f6c-487d-a436-704a3fed8222/image.png>

<p>출처: <a href="https://wikidocs.net/80437">https://wikidocs.net/80437</a></p>
<p>단어 임베딩을 이어 붙이고, CNN의 Kernel로 feature를 뽑아내는 구조이다.</p>
<p>그림상으로 
입력 길이: 9, 임베딩 크기: 6, 한번에 볼 단어의 갯수: 3 이다.
아래로 내려가면서 Convolution 연산을 해 준다.
첫 CNN layer를 거치면 7x6 matrix가 나올 것이고, 
그림상으론 바로 pooling을 거쳐 7x1 matrix를 뽑아냈다.</p>
<p>CNN layer를 더 많이 거쳐도 되고, kernel의 channel 수를 늘리는 방법으로 모델 크기를 키워 학습 시킬 수 있다. </p>
<p>나온 결과로 FC layer를 거쳐 분류나 회귀 문제에 활용할 수 있다.</p>
<h2 id="5-bi-lstm">5. Bi-LSTM</h2>
<p>일반 RNN구조에 반대로 가는 길도 추가된 버전이라 할 수 있다. 혹은 RNN 구조 2개가 겹쳐진 버전으로 볼 수 있다. </p>
<img src= https://velog.velcdn.com/images/_chominseo/post/85661033-113b-482e-91f9-0203dcd9bf59/image.png width=80%>

<p>출처: <a href="https://www.gabormelli.com/RKB/Bidirectional_LSTM_%28BiLSTM%29_Training_System">https://www.gabormelli.com/RKB/Bidirectional_LSTM_%28BiLSTM%29_Training_System</a></p>
<p>예를 들어 
<code>I love ___ for always</code> 라는 문장이 있다.
빈칸에 들어갈 단어를 예측하기 위해 앞 뒤로 <code>I love</code>와 <code>for always</code>를 활용하는게 도움이 될 것이다. 
이런 식으로 예측을 하는데 (과거 입력에만 영향을 받는다는 의미인) <code>Causality</code>를 무시해도 되고, 미래의 입력이 도움이 되는 경우에 활용 할 수 있는 구조이다. </p>
<p>$W_{hh}$가 기본 버전의 2배가 필요할 것이다.</p>
<h2 id="총정리">총정리</h2>
<p>오늘 RNN은 학교 수업에서도 한번 봤기에 잔잔하게 이해할 수 있었다. 그땐 NLP 분야의 존재조차 모르고 들었었기에 이런 구조가 큰 의미가 있나 싶었는데 아는 만큼 보인다는걸 느꼈다.</p>
<p>CNN은 알고 있었지만 1D-CNN은 처음 봤는데, 처음엔 CNN을 NLP에 어떻게 적용하지 했는데, 약간의 억지도 없지않아 보이긴 하지만 이런 상상력이 어떤 결과가 나올지 모르기 때문에 항상 다각도로 생각해 보자.</p>
<p>이제 이 강의를 선택한 목적인 Attention Transformer 부분을 앞두고 있다. 가보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] SentencePiece: A simple and language independent subword tokenizer and detokenizer for Neural Text Processing]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-SentencePiece-A-simple-and-language-independent-subword-tokenizer-and-detokenizer-for-Neural-Text-Processing</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-SentencePiece-A-simple-and-language-independent-subword-tokenizer-and-detokenizer-for-Neural-Text-Processing</guid>
            <pubDate>Thu, 18 Jan 2024 06:22:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://arxiv.org/pdf/1808.06226.pdf">https://arxiv.org/pdf/1808.06226.pdf</a>
<a href="https://github.com/google/sentencepiece">https://github.com/google/sentencepiece</a></p>
</blockquote>
<p>BEiT에서 언어 토큰화 툴로 사용한 SentencePiece이다.
python에 간단히 pip로 다운받아 사용가능 하다.</p>
<h2 id="abstract">Abstract</h2>
<p>언어에 관계없는 subword tokenizer/detokenizer
subword tokenizer들은 대부분 pre-tokenized된 데이터셋으로부터 학습했다. 하지만 Sentence Piece는 raw sentences로 부터 바로 학습 가능하다.</p>
<h2 id="1-introduction">1. Introduction</h2>
<p>띄어쓰기 단위로 대부분 구별 가능한 영어/유럽쪽 언어와 다르게 한/중/일 아시아쪽 언어는 띄어쓰기가 필요없는 부분이 있다.
기존 방식들은 언어마다 규칙을 찾아 하드코딩을 해주는 방식이었지만,</p>
<p>Byte-pair-encoding(BPE), unigram language model을 활용하여 언어에 관계없이, raw-sentences로부터 학습 가능한 구조를 만들었다.</p>
<h2 id="2-system-overview">2. System Overview</h2>
<p>Normalizer, Trainer, Encoder, Decoder 4개로 이루어져 있다.</p>
<h4 id="normalizer">Normalizer</h4>
<p>Unicode 형태 글자들을 canonical form으로 바꿔준다.</p>
<h4 id="trainer">Trainer</h4>
<p>normalized corpus로부터 모델을 학습시킨다.
모델 종류는 선택 가능하다.</p>
<h4 id="encoder">Encoder</h4>
<p>Normalizer를 돌려주고, subword 단위로 토큰화해서 Trainer에 넘겨주는 녀석</p>
<h4 id="decoder">Decoder</h4>
<p>다시 text로 바꿔준다.</p>
<p>단어를 id-mapping방식을 이용해 encode-decode한다.
<code>Hello world. &lt;-&gt; 151 88 21 887 6</code>
-&gt;Encode 
&lt;-Decode</p>
<h2 id="3-library-design">3. Library Design</h2>
<p>기존 방식은 띄어쓰기가 필요한지, 없는지 구분할 수 없었다.
<code>Hello world. -&gt; [Hello] [world] [.]</code>
면 hello와 world사이엔 띄어쓰기가 들어가야 한다는건 알지만 world와 .사이는 들어가면 안되니까 애매해진다.
다른 언어는 더더욱 그렇다.</p>
<p>Encoder Decoder가 서로의 inverse operation이 되도록
<code>Decode(Encode(Normalize(text))) = Normalize(text)</code>
구현 했고, 이걸 여기서 <strong>lossless tokenization</strong>이라고 부를 것이다.</p>
<p>띄어쓰기를 <code>_</code> 로 바꿔서 보는걸 포함해 모든 글자들을 Unicode로 보고 input text를 아래 예시처럼 arbitrary subword 단위로 쪼갠다.</p>
<img src =https://velog.velcdn.com/images/_chominseo/post/882be12f-a6ca-4a0c-a1ee-f33c65764094/image.png width = 50%>

<p>heap구조를 사용해 기존 BPE 알고리즘에서 $O(N^2)$이던 시간을 $O(Nlog(N))$으로 줄였고,</p>
<p>id mapping 할 때 vocab_size를 학습시 입력으로 받아 그때그때 설정 할 수 있고 
Unknown symbol: EOS <code>&lt;/s&gt;</code> , padding <code>&lt;pad&gt;</code> 같은 애들은 따로 설정 가능하다.</p>
<p>Normalizing에서 기본적으로는 Unicode NFKC를 사용하는데 커스터마이징도 가능하다.</p>
<blockquote>
<p><a href="https://wikidocs.net/86657">https://wikidocs.net/86657</a>
위키독스에 한글로 설명된 실습 해보자</p>
</blockquote>
<p>IMDB 영화리뷰 데이터셋을 불러와 학습을 위한 txt파일로 저장해 준다.</p>
<pre><code class="language-python">train_df = pd.read_csv(&#39;C:/nlp_datas/IMDB Dataset.csv&#39;)
train_df[&#39;review&#39;]
with open(&#39;imdb_review.txt&#39;,&#39;w&#39;,encoding=&#39;utf8&#39;) as f:
    f.write(&#39;\n&#39;.join(train_df[&#39;review&#39;]))</code></pre>
<hr>
<p>학습 파라미터로 txt파일명, 생성될 파일 이름, vocab_size, model type등을 지정해 준다.</p>
<pre><code class="language-python">spm.SentencePieceTrainer.Train(
    &#39;--input=imdb_review.txt --model_prefix=imdb\
    --vocab_size=5000 --model_type=bpe --max_sentence_length=9999&#39;)</code></pre>
<hr>
<p>학습된 모델을 불러와 Encoding Decoding해보자</p>
<pre><code class="language-python">sp = spm.SentencePieceProcessor()
vocab_file = &#39;imdb.model&#39;
sp.Load(vocab_file)</code></pre>
<p>Encoding</p>
<pre><code class="language-python">lines = [&#39;This is very fun&#39;,&#39;He was crying&#39;]
for line in lines:
    print(line)
    print(sp.encode_as_pieces(line))
    print(sp.encode_as_ids(line))
    print()</code></pre>
<p><code>This is very fun</code>
<code>[&#39;▁This&#39;, &#39;▁is&#39;, &#39;▁very&#39;, &#39;▁fun&#39;]</code>
<code>[280, 43, 270, 411]</code></p>
<p><code>He was crying</code>
<code>[&#39;▁He&#39;, &#39;▁was&#39;, &#39;▁cry&#39;, &#39;ing&#39;]</code>
<code>[490, 84, 2625, 20]</code></p>
<hr>
<p>Decoding</p>
<pre><code class="language-python">sp.DecodeIds([280,43,270,411])</code></pre>
<p><code>&#39;This is very fun&#39;</code></p>
<h3 id="총정리">총정리</h3>
<p>쓰기 굉장히 편하고 언어 구별 없다는 점에서 장점이 큰 것 같다.</p>
<p>이제 정수 인코딩 했으니 BEiT에 집어넣을때는 One-hot으로 바꿔서 한건지, 그대로 썼는지 또 알아보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[딥러닝을 이용한 자연어처리 입문 7시간 완성(3)]]></title>
            <link>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B13</link>
            <guid>https://velog.io/@_chominseo/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-%EC%9E%85%EB%AC%B8-7%EC%8B%9C%EA%B0%84-%EC%99%84%EC%84%B13</guid>
            <pubDate>Wed, 17 Jan 2024 08:56:49 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>딥러닝을 이용한 자연어처리 입문 7시간 완성 - 메타코드M
<a href="https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM">https://www.youtube.com/watch?v=Rf7wvs8ZbP4&amp;ab_channel=%EB%A9%94%ED%83%80%EC%BD%94%EB%93%9CM</a></p>
</blockquote>
<p>3회차는 지금까지 배웠던 전처리 실습입니다.</p>
<h3 id="목차">목차</h3>
<ol>
<li>토큰화</li>
<li>어간 추출, 표제어 추출</li>
<li>불용어 처리</li>
<li>정수 인코딩</li>
<li>유사도 분석</li>
<li>CBOW/Skip gram 학습</li>
<li>SGNS 학습시키기</li>
</ol>
<h2 id="1-토큰화">1. 토큰화</h2>
<p>다양한 토큰화 함수들 중 TreebankWordTokenizer를 사용해 보았다.
뒤에서 또 다른 토큰화 함수 등장 예정</p>
<pre><code class="language-python">from nltk.tokenize import TreebankWordTokenizer
tokenizer = TreebankWordTokenizer()
text = &quot;T1 won world championship by 3:1 score&quot;
print(tokenizer.tokenize(text))</code></pre>
<h2 id="2-어간-추출-표제어-추출">2. 어간 추출, 표제어 추출</h2>
<p>어간추출 Stemmer</p>
<pre><code class="language-python">from nltk.stem import PorterStemmer, LancasterStemmer
stem1 = PorterStemmer()
stem2 = LancasterStemmer()
words = [&#39;eat&#39;,&#39;ate&#39;,&#39;eaten&#39;,&#39;eating&#39;]
print(&#39;Porter&#39;,[stem1.stem(w) for w in words])
print(&#39;Lancaster&#39;,[stem2.stem(w) for w in words])</code></pre>
<p><code>Porter [&#39;eat&#39;, &#39;ate&#39;, &#39;eaten&#39;, &#39;eat&#39;]</code>
<code>Lancaster [&#39;eat&#39;, &#39;at&#39;, &#39;eat&#39;, &#39;eat&#39;]</code></p>
<p>표제어 추출 Lemmatizer</p>
<pre><code class="language-python">import nltk
from nltk import WordNetLemmatizer
nltk.download(&#39;wordnet&#39;)
lemm = WordNetLemmatizer()
words = [&#39;eat&#39;,&#39;ate&#39;,&#39;eaten&#39;,&#39;eating&#39;]
print(&#39;wordNet Lemm&#39;,[lemm.lemmatize(w,pos=&#39;v&#39;) for w in words])</code></pre>
<p><code>wordNet Lemm [&#39;eat&#39;, &#39;eat&#39;, &#39;eat&#39;, &#39;eat&#39;]</code>
lemmatize 입력 변수로 pos에 v를 넣으면 동사, n을 넣으면 명사를 쪼개준다.</p>
<h2 id="3-불용어-처리">3. 불용어 처리</h2>
<pre><code class="language-python">import nltk
nltk.download(&#39;stopwords&#39;)
from nltk.corpus import stopwords

print(stopwords.words(&#39;english&#39;)[:5])

text = &quot;hi how are you?&quot;
word_tokens = tokenizer.tokenize(text)
stop_words = stopwords.words(&#39;english&#39;)
result = []
for w in word_tokens:
    if w not in stop_words:
        result.append(w)
print(word_tokens)
print(result)</code></pre>
<p><code>[&#39;hi&#39;, &#39;how&#39;, &#39;are&#39;, &#39;you&#39;, &#39;?&#39;]</code>
<code>[&#39;hi&#39;, &#39;?&#39;]</code></p>
<h2 id="4-정수-인코딩">4. 정수 인코딩</h2>
<pre><code class="language-python">vocab = {&#39;apple&#39;:2,&#39;July&#39;:6,&#39;piano&#39;:4,&#39;cup&#39;:8,&#39;orange&#39;:1}
vocab_sort = sorted(vocab.items(),key=lambda x:x[1],reverse=True)
print(vocab_sort)
word2idx = {word[0]:index+1 for index,word in enumerate(vocab_sort)}
print(word2idx)</code></pre>
<p><code>[(&#39;cup&#39;, 8), (&#39;July&#39;, 6), (&#39;piano&#39;, 4), (&#39;apple&#39;, 2), (&#39;orange&#39;, 1)]</code>
<code>{&#39;cup&#39;: 1, &#39;July&#39;: 2, &#39;piano&#39;: 3, &#39;apple&#39;: 4, &#39;orange&#39;: 5}</code>
빈도가 주어졌다고 치고, 가장 많이 나온게 1, 2, 3 순서대로 인코딩 된다.</p>
<h2 id="5-유사도">5. 유사도</h2>
<p>코사인 유사도</p>
<pre><code class="language-python">import numpy as np
def cos_sim(A,B):
    return np.dot(A,B)/(np.linalg.norm(A)*np.linalg.norm(B))
a = [1,0,0,1]
b=[0,1,1,0]
c=[1,1,1,1]
print(cos_sim(a,b),cos_sim(b,c),cos_sim(c,a))</code></pre>
<p><code>0.0 0.7071067811865475 0.7071067811865475</code></p>
<p>레반슈타인 거리</p>
<pre><code class="language-python">def leven(text1,text2):
    len1 = len(text1)+1
    len2 = len(text2)+1
    sim_array = np.zeros((len1,len2))
    sim_array[:,0] = np.linspace(0,len1-1,len1)
    sim_array[0,:] = np.linspace(0,len2-1,len2)
    for i in range(1,len1):
        for j in range(1,len2):
            add_char = sim_array[i-1,j]+1
            sub_char = sim_array[i,j-1]+1
            if text1[i-1] == text2[j-1]:
                mod_char = sim_array[i-1,j-1]
            else:
                mod_char = sim_array[i-1,j-1]+1
            sim_array[i,j] = min([add_char,sub_char,mod_char])
    return sim_array[-1,-1]
print(leven(&#39;데이터마이닝&#39;,&#39;데이타마닝&#39;))</code></pre>
<p><code>2.0</code></p>
<h2 id="6-cbowskip-gram-학습">6. CBOW/Skip gram 학습</h2>
<blockquote>
<p><a href="https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews?resource=download">https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews?resource=download</a>
IMDB 영화 리뷰 데이터셋을 활용하였다.</p>
</blockquote>
<p>먼저 전처리 과정을 거쳐 준다</p>
<p>1) 토큰화를 해 주고</p>
<pre><code class="language-python">import pandas as pd
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
data=pd.read_csv(&#39;C:/nlp_datas/IMDB Dataset.csv&#39;)
print(&#39;missing Values: &#39;,data.isnull().sum())
merge_data = &#39;&#39;.join(str(data.iloc[i,0]) for i in range(500))
print(&#39;Total word count:&#39;, len(merge_data))</code></pre>
<p><code>missing Values:  review       0 sentiment    0</code>
<code>dtype: int64</code>
<code>Total word count: 681583</code></p>
<p>Review에 실제 평가 문장, sentiment에 긍정/부정 인지 적혀있기에 Review 열만 사용할 예정이다.</p>
<p>2) 불용어를 없애주고</p>
<pre><code class="language-python">tokenizer = RegexpTokenizer(&#39;[\w]+&#39;)
token_text = tokenizer.tokenize(merge_data)

stop_words = set(stopwords.words(&#39;english&#39;))
token_stop_text = []
for w in token_text:
    if w not in stop_words:
        token_stop_text.append(w)
print(&#39;After cleaning:&#39;, len(token_stop_text))</code></pre>
<p><code>After cleaning: 70257</code></p>
<p>3) 빈도수 셀 겸 중복인 단어를 없애주고</p>
<pre><code class="language-python">word2idx={}
Bow=[]
for word in token_stop_text:
    if word not in word2idx.keys():
        word2idx[word] = len(word2idx)
        Bow.insert(len(word2idx)-1,1)
    else:
        idx = word2idx.get(word)
        Bow[idx] +=1
print(&#39;Unique Words Count: &#39;,len(Bow))</code></pre>
<p><code>Unique Words Count:  14216</code></p>
<p>4) 실제 학습
리스트 형태였던 토큰들을 np array로 바꿔주고,
gensim 라이브러리에서 제공하는 Word2Vec 모델에</p>
<ul>
<li>각 단어당 임베딩 벡터 길이(<code>vector_size</code>): 100, </li>
<li>Skip gram의 hyperparameter인 어느 범위까지 참조할 건지(<code>window</code>): 5, </li>
<li>양 끝쪽에 참조할게 적어져 생략할 범위를 정하는(<code>min_count</code>): 2, </li>
<li>skipgram을 쓸건지, cbow를 쓸건지(<code>sg</code>): 0 -&gt; CBOW/ 1-&gt; Skipgram<pre><code class="language-python">import numpy as np
token_stop_text = np.reshape(np.array(token_stop_text),[-1,1])
from gensim.models import Word2Vec
model = Word2Vec(vector_size = 100, window = 5, min_count=2, sg=0)
model.build_vocab(token_stop_text)
model.train(token_stop_text,total_examples=model.corpus_count,epochs= 30)
vocabs = model.wv.key_to_index.keys()
word_vec_list = [model.wv[i] for i in vocabs]</code></pre>
</li>
</ul>
<p>5) PCA로 시각화 </p>
<pre><code class="language-python">from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pcafit = pca.fit_transform(word_vec_list)
x = pcafit[:50,0]
y = pcafit[:50,1]
import matplotlib.pyplot as plt
plt.scatter(x,y,marker=&#39;o&#39;)
for i,v in enumerate(vocabs):
    if i&lt;=49:
        plt.annotate(v,xy=(x[i],y[i]))
plt.show()</code></pre>
<img src=https://velog.velcdn.com/images/_chominseo/post/fe93bca7-17c4-4d1f-aeb3-2e4e3744abde/image.png width=80%>
좋은거만 좀 봐보면 life, way 비슷한 느낌이니 같이 있고, One many 가 비슷하게 위쪽에 위치했다.

<h2 id="7-sgns-학습시키기">7. SGNS 학습시키기</h2>
<p>똑같이 전처리를 해준다.</p>
<pre><code class="language-python">import pandas as pd
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
data=pd.read_csv(&#39;C:/nlp_datas/IMDB Dataset.csv&#39;)
print(&#39;missing Values: &#39;,data.isnull().sum())
merge_data = &#39;&#39;.join(str(data.iloc[i,0]) for i in range(200))
print(&#39;Total word count:&#39;, len(merge_data))
tokenizer = RegexpTokenizer(&#39;[\w]+&#39;)
token_text = tokenizer.tokenize(merge_data)

stop_words = set(stopwords.words(&#39;english&#39;))
token_stop_text = []
for w in token_text:
    if w not in stop_words:
        token_stop_text.append(w)
print(&#39;After cleaning:&#39;, len(token_stop_text))</code></pre>
<hr>
<p>SGNS는 단어 두개가 이웃한지 여부를 이용하는 알고리즘이니,
이 형태의 데이터 셋을 만들기 위해 Tensorflow에서 제공하는 Tokenizer과 skipgrams를 사용한다.</p>
<p>(근데 tensorflow 설치가 안돼서 일단 급하게 소스코드를 복사하여 사용했다)</p>
<pre><code class="language-python">tokenizer = Tokenizer()
tokenizer.fit_on_texts(token_stop_text)
word2idx = tokenizer.word_index
encoded = tokenizer.texts_to_sequences(token_stop_text)
encoded = np.array(encoded).T
skip_gram = [skipgrams(sample,vocabulary_size = len(word2idx)+1,window_size = 10)for sample in encoded]</code></pre>
<p>skip_gram안에는 단어 인덱스가 두개씩 묶인 쌍들이 저장된다. 그리고 두 숫자가 이웃해 있는지 여부가 뒤쪽에 저장된다. </p>
<pre><code class="language-python">[[[[1,2],[2,3]...],[1,1,0,0,...]]]</code></pre>
<hr>
<pre><code class="language-python">import torch
import torch.nn as nn
from torch import LongTensor as LT
from torch import FloatTensor as FT

class Word2Vec(nn.Module):
    def __init__(self,vocab_size,embed_size):
        super(Word2Vec,self).__init__()
        self.vocab_size = vocab_size
        self.embed_size = embed_size
        self.word1_vector = nn.Embedding(self.vocab_size,self.embed_size)
        self.word2_vector = nn.Embedding(self.vocab_size,self.embed_size)
        self.word1_vector_weight = nn.Parameter(torch.cat([torch.zeros(1,self.embed_size),FT(self.vocab_size-1,self.embed_size).uniform_(-0.1,0.1)]))
        self.word2_vector_weight = nn.Parameter(torch.cat([torch.zeros(1,self.embed_size),FT(self.vocab_size-1,self.embed_size).uniform_(-0.1,0.1)]))
        self.word1_vector.weight.requires_grad = True
        self.word2_vector.weight.requires_grad = True

    def forward_word1(self,data):
        vec = LT(data)
        vec = vec.cuda() if self.word1_vector.weight.is_cuda else vec
        return self.word1_vector(vec)
    def forward_word2(self,data):
        vec = LT(data)
        vec = vec.cuda() if self.word2_vector.weight.is_cuda else vec
        return self.word2_vector(vec)</code></pre>
<p>단어 두개의 임베딩을 뽑아주는 Word2Vec class를 정의한다.</p>
<hr>
<pre><code class="language-python">class SGNS(nn.Module):
    def __init__(self,embed,vocab_size):
        super(SGNS,self).__init__()
        self.embed = embed
        self.vocab_size = vocab_size
        self.weights = None
    def forward(self,word1, word2, label):
        soft = 1e-9
        word1 = self.embed.forward_word1(word1).unsqueeze(1)
        word2 = self.embed.forward_word2(word2).unsqueeze(2)
        label = LT(label).unsqueeze(1)
        prediction = torch.bmm(word1, word2).squeeze(2).sigmoid()
        pr1 = prediction.log()
        pr0 = (1-prediction+soft).log()
        loss = -label*pr1-(1-label)*pr0
        return loss.mean()</code></pre>
<p>SGNS 모델 class를 정의한다.
각 단어 임베딩은 (Batch,100) 형태를 가질 텐데 여기서 해야하는 연산은 
$word_1^Tword_2$이므로 unsqueeze 함수를 이용해
word1의 shape은 (Batch,1,100)
word2의 shape은 (Batch,100,1)로 만들어
(1,100) x (100,1) 연산결과로 (1x1)을 얻어낸다.
; torch.bmm을 결과로 (Batch,1,1)의 결과가 나오는데, 1하나를 squeeze해준다.</p>
<p>이후 시그모이드에 로그확률 형태로 만들어 
loss function은 binary cross entropy 모양을 그대로 가져왔다.</p>
<hr>
<p>Adam쓸 예정이고, 필요한 word2vec 리스트, 모델을 정의해 준다.</p>
<pre><code class="language-python">from torch.optim import Adam
from torch.utils.data import DataLoader, TensorDataset
from tqdm import tqdm
vocab_size = len(word2idx)+1
word2vec = Word2Vec(vocab_size=vocab_size,embed_size=100)
sgns = SGNS(embed = word2vec, vocab_size = vocab_size)
optim = Adam(sgns.parameters())</code></pre>
<hr>
<p>데이터 로더를 정의할 건데,
skip_gram 변수엔 <code>[[[idx1, idx2],... , [1,0,...]]]</code> 구조로 되어있다.
element[0]에 해당하는게 숫자 인덱스 쌍들 <code>[[idx1,idx2],[1,2]...]</code>
element[1]에 해당하는게 라벨값 <code>[1,0,...]</code></p>
<p>word1에 기준 인덱스, word2에 근처인지 비교할 인덱스, label에 이웃한지 를 저장한다.</p>
<pre><code class="language-python">for _,element in enumerate(skip_gram):
    word1 = LT(np.array(list(zip(*element[0]))[0],dtype=&#39;int32&#39;))
    word2 = LT(np.array(list(zip(*element[0]))[1],dtype=&#39;int32&#39;))
    label = LT(np.array(element[1],dtype=&#39;int32&#39;))
    dataset = TensorDataset(word1,word2,label)
    train_loader = DataLoader(dataset, batch_size=256, shuffle=True)    </code></pre>
<hr>
<p>학습</p>
<pre><code class="language-python">for epoch in range(5):
    with tqdm(train_loader) as tepoch:
        for word1, word2, label in tepoch:
            loss = sgns(word1, word2,label)
            optim.zero_grad()
            loss.backward()
            optim.step()
            tepoch.set_description(f&quot;Epoch {epoch}&quot;)
            tepoch.set_postfix(loss = loss.item())</code></pre>
<pre><code>Epoch 0: 100%|██████████| 4346/4346 [01:15&lt;00:00, 57.89it/s, loss=3.33]
Epoch 1: 100%|██████████| 4346/4346 [01:14&lt;00:00, 58.42it/s, loss=2.64]
Epoch 2: 100%|██████████| 4346/4346 [01:17&lt;00:00, 56.14it/s, loss=1.71]
Epoch 3: 100%|██████████| 4346/4346 [01:31&lt;00:00, 47.28it/s, loss=1.4]  
Epoch 4: 100%|██████████| 4346/4346 [01:45&lt;00:00, 41.14it/s, loss=0.806]</code></pre><p>(5 에폭에 데이터도 많이 안써서 loss값이 형편없다.)</p>
<p>각 단어 인덱스를 받으면 sgns내에서 그 단어에 해당하는 임베딩들을 만들기 시작할 것이고, loss function 왔다갔다 하면서 업데이트 할 것이다.</p>
<hr>
<p>결과 확인을 위해 임베딩값들을 저장해 준다.</p>
<pre><code class="language-python">import gensim
with open(&quot;C:/nlp_datas/vectors.txt&quot;,&#39;w&#39;) as f:
    ww=0
    f.write(&#39;{} {}\n&#39;.format(7500,100))
    vectors = word2vec.word1_vector.weight.detach().numpy()
    for i , v in enumerate(word2idx.keys()):
        try:
            f.write(&#39;{} {}\n&#39;.format(v, &#39; &#39;.join(map(str,list(vectors[i+1,:])))))
            ww+=1
        except:
            continue
embed_word2vec = gensim.models.KeyedVectors.load_word2vec_format(&quot;C:/nlp_datas/vectors.txt&quot;,)</code></pre>
<p>마지막 줄에 이제 gensim 라이브러리를 활용해 비슷한 단어가 뭐가 있는지 보기위해 로드해 준다.</p>
<pre><code class="language-python">embed_word2vec.most_similar(positive = [&#39;enjoy&#39;])</code></pre>
<pre><code class="language-[(&#39;movie&#39;,"> (&#39;nights&#39;, 0.3993881344795227),
 (&#39;great&#39;, 0.36998695135116577),
 (&#39;fight&#39;, 0.35548287630081177),
 (&#39;follow&#39;, 0.3486346900463104),
 (&#39;i&#39;, 0.3483388423919678),
 (&#39;the&#39;, 0.34802910685539246),
 (&#39;parts&#39;, 0.3476596772670746),
 (&#39;promise&#39;, 0.347569078207016),
 (&#39;correct&#39;, 0.3447914719581604)]</code></pre>
<p>예시로 enjoy와 비슷한 단어를 찍어보니 이렇게 나온다.
아무래도 영화리뷰이다 보니 movie라는 단어가 워낙 많이 있을 거라 movie와의 유사도가 높은것 같고, great, fight는 나름 연관성이 있어보이긴 한다.</p>
<p>학습을 더 시켜보면 좋은 결과가 나올 것 같긴 하다.</p>
<h2 id="총정리">총정리</h2>
<p>실제로 전처리부터 간단한 인코딩 알고리즘들을 돌려보니 NLP에 대해 감이 잡히는듯 안잡히는듯 아직 그렇다. 
그래도 NLP를 몰랐을 때 보단 실제 코드로 실습도 하고 하니 뭔가 해볼 순 있겠다는 자신감은 생긴다.</p>
<p>지금까지 본건 사실상 현재 NLP에서 안쓰이는 기법들일 거고,
앞으로 RNN Attention Transformer를 볼 텐데 얼마나 성능향상이 있을지 기대된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SEQ2SEQ, Attention]]></title>
            <link>https://velog.io/@_chominseo/SEQ2SEQ-Attention</link>
            <guid>https://velog.io/@_chominseo/SEQ2SEQ-Attention</guid>
            <pubDate>Tue, 16 Jan 2024 10:53:41 GMT</pubDate>
            <description><![CDATA[<p>Transformer에 대해 알아보자</p>
<blockquote>
<p>대부분의 내용, 이미지는
Seq2Seq: <a href="https://wikidocs.net/24996">https://wikidocs.net/24996</a>
Attention: <a href="https://wikidocs.net/22893">https://wikidocs.net/22893</a>
에서 참고하였습니다.</p>
</blockquote>
<p>일단 그 시초인 Seq2Seq에서 출발해 보자</p>
<h2 id="seq2seq">Seq2Seq</h2>
<p>Encoder - Decoder 구조를 가지고 그 내부에 RNN block들이 들어있다.</p>
<img src=https://velog.velcdn.com/images/_chominseo/post/e9d616af-1ed9-4f21-ae4e-b48455a1fc85/image.png>

<ol>
<li>입력 문장의 각 토큰의 임베딩을 뽑아 인코더 각 RNN block의 input으로 사용한다.</li>
<li>인코더의 마지막 RNN block의 출력이 <code>Context Vector</code> 이 디코더의 첫번째 input이 된다.</li>
<li><code>&lt;&#39;sos&#39;&gt;: Start of Sentence</code>, <code>Context vector</code> 부터 시작하여, 이전 RNN block에서 나온 출력 벡터와 결과 단어의 임베딩을 현재 RNN block의 input으로 사용한다.</li>
</ol>
<p>결과 단어는 출력 벡터를 Dense layer, Softmax layer를 거쳐 결정된다.</p>
<p>Seq2Seq의 문제점:</p>
<ul>
<li>벡터 크기를 고정시켜 두고, 단어에 해당하는 모든 정보를 압축하려니 정보가 손실된다.</li>
<li>RNN의 특성상 나타나는 <code>기울기 소실</code> 문제가 나타나서 문장이 길어지면 성능이 떨어진다.</li>
</ul>
<h2 id="attention">Attention</h2>
<p>Attention으로 개선한다.
디코더에서 각 단어를 예측할 때 인코더의 input들을 참조할 건데, 굳이 처음부터 끝까지 다 볼 필요 없이 중요한 부분만 집중(Attention)해서 보자.</p>
<p>Attention(Q, K, V) = Attention Value
함수 모양으로 보면 간단히 이렇다. 여기서, 
Query(Q): 디코더에서 현재 시점의 출력 벡터,
Key(K): 인코더의 각 Block
Value(V): 인코더 각 Block의 값</p>
<h3 id="dot-product-attention">Dot-product Attention</h3>
<img src=https://velog.velcdn.com/images/_chominseo/post/fe4071fd-1ad5-4627-97d9-c00fb2f113b6/image.png width=80%>

<h4 id="attention-score를-구한다">Attention score를 구한다</h4>
<p>인코더의 각 출력 벡터를 $h_1, h_2 ... h_n$이라 하고, 
그리고 디코더의 구하려는 시점의 출력 벡터를 $s_t$라 하자.</p>
<p>내적으로 $s_t^Th_1=\alpha_1, s_t^Th_2=\alpha_2$ 값들을 각각 구해서 Softmax 함수에 집어 넣으면 인코더의 Input 각 단어들과 얼마나 유사한지의 확률 값을 얻을 수 있다.</p>
<p>최종 Attention score $a_t = \Sigma_{i=1}^{N}\alpha_i^Th_i$
로 얻어진다.</p>
<img src=https://velog.velcdn.com/images/_chominseo/post/36138cf4-edeb-463a-8b51-ce4cbc8d65c9/image.png width=80%>

<p>나온 $a_t$와 $s_t$를 concatenate해서 Weight matrix $W_c$ 와 계산을 통해 출력층(최종 Softmax layer) 의 입력을 계산한다.
$\tilde s_t = tanh(W_c[a_t:s_t]+b_c)$</p>
<img src=https://velog.velcdn.com/images/_chominseo/post/eb5dd8dd-a1fd-4f75-ba84-edadfaf76d7b/image.png>

<p>끝으로 다른 Weight matrix $W_y$와 다시 계산하고 Softmax layer에 넣어 준다.</p>
<p>$\hat y_t = softmax(W_y\tilde s_t+b_y)$
이렇게 디코더에서 t 시점의 최종 단어를 예측할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] Image as a Foreign Language: BEiT Pretraining for All Vision and Vision-Language Tasks (BEiT-3) ]]></title>
            <link>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Image-as-a-Foreign-Language-BEiT-Pretraining-for-All-Vision-and-Vision-Language-Tasks-BEiT-3</link>
            <guid>https://velog.io/@_chominseo/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Image-as-a-Foreign-Language-BEiT-Pretraining-for-All-Vision-and-Vision-Language-Tasks-BEiT-3</guid>
            <pubDate>Mon, 15 Jan 2024 11:22:29 GMT</pubDate>
            <description><![CDATA[<p>Visual Question Answering(VQA) Task에 관심이 생겨 현재 SOTA 모델인 BEiT-3을 찾아보았다.</p>
<blockquote>
<p><a href="https://arxiv.org/abs/2208.10442">https://arxiv.org/abs/2208.10442</a></p>
</blockquote>
<p>BEiT v1, v2도 읽어볼 예정</p>
<h2 id="abstract">Abstract</h2>
<p>크게 3가지에 집중할 예정이다.</p>
<ol>
<li>Backbone architecture</li>
<li>Pretraining task</li>
<li>Model scaling up</li>
</ol>
<p>이 3가지를 하기 위해서 <code>Multiway Transformer</code> 논문에서 제시한다.</p>
<p>이미지를 하나의 언어로 보고 (<code>&#39;Imglish&#39;</code>), image-text pair에 마스크를 씌우는 학습방법을 활용하였다.</p>
<p>이렇게 했더니, 여러 데이터셋에서 Vision-Language multi-modal task 뿐만 아니라, Vision 단일 task에서도 좋은 성능을 보였다.</p>
<h2 id="1-introduction-the-big-convergence">1. Introduction: The Big Convergence</h2>
<p>Abstract에서 제시한 3가지를 어떻게 할 것이냐</p>
<h3 id="11-backbone-architecture">1.1 Backbone architecture</h3>
<p>Vision-Language 모델링에 있어 다양한 방법들이 존재한다.</p>
<ul>
<li>Dual-Encoder: Image-text retrieval task</li>
<li>Encoder-Decoder: generation task</li>
<li>Fusion-encoder: image-text encoding</li>
</ul>
<p>이런 모델들 대부분은 특정 task를 하기 위한 변형을 끝단에 붙여줘야 한다. 게다가 여러 modality에 parameter들이 효과적으로 공유되지 않는데,
<code>Multiway Transformer</code>로 점들을 개선한다.</p>
<h3 id="12-pretraining-task">1.2 Pretraining Task</h3>
<p>Pretraining 할 때 task마다 다른 기법으로 학습시키는데, 이건 scaling 하기에 안좋고, 비효율적이다. 
General-purpose multi-modal 모델 학습으로 <code>Mask-then-predict</code> 이거 하나만 쓰자.
이미지도 text처럼 취급한다 했으니(<code>Imglish</code>) modality는 다르지만 두 개의 문장이 들어간 것처럼 학습시켜줄 것이다.</p>
<h3 id="13-model-scaling-up">1.3 Model Scaling up</h3>
<p>모델 크기를 키우고, 데이터 크기를 키우는게 성능을 높이는데 보통 좋다. 
이 논문에서는 private한 데이터를 쓰지 않고, 공개된 데이터만 사용해도 SOTA보다 성능이 좋음을 보였다.</p>
<h2 id="2-beit-3-a-general-purpose-multimodal-foundation-model">2. BEiT-3: A General-Purpose Multimodal Foundation Model</h2>
<h3 id="21-backbone-network-multiway-transformers">2.1 Backbone Network: Multiway Transformers</h3>
<img src=https://velog.velcdn.com/images/_chominseo/post/4810eaae-8a0c-4172-a090-538a11effd54/image.png width=80%>

<p>그림에 있는 것 처럼, <code>Multiway Transformer</code> 는 각 modality 마다 <code>shared self-attention module</code> , <code>feed-forward network(FFN)</code>으로 구성되어 있다.</p>
<p>(a),(b) 를 보면 <code>Self-attention module</code> 위에 각 modality에 해당하는 <code>FFN</code> 이 올라가 있고,
(c)는 image와 text가 <code>shared self-attention module</code>, <code>FFN</code> 을 거쳐 나온 결과를 다시 <code>self-attention</code>, <code>FFN</code> 에 넣는데,
이렇게 하면 처음 <code>shared self-attention</code> 에서 다른 modality간의 alignment를 학습하는데 도움이 된다. </p>
<p>Vision task만, text만, multi-modal용이든 다 똑같은 구조로 이루어져 있어서 각종 downstream task에 활용하기에 좋다.</p>
<h3 id="22-pretraining-task-masked-data-modeling">2.2 Pretraining Task: Masked Data Modeling</h3>
<p>앞서 BEiT를 학습시킬 때 <code>mask-then-predict</code> 만 사용한다고 언급했다. 
이렇게 하면 representation 뿐만 아니라 다른 modality간 alignment를 학습하는데에도 도움이 된다. </p>
<p>구체적으로, Text는 <code>SentencePiece tokenizer</code> 를 이용해서 토큰화 했고, Image는 BEiT v2에서 언급된 tokenizer를 이용했다. (찾아보자)</p>
<p>Text만 학습시킬땐 15%, Image-text pair로 학습할 땐 50%를 mask했다. 이미지는 40% image patch들을 BEiT논문에 등장하는 방식으로 block-wise masking 했다.(이것도 찾아보자)</p>
<p>각 Task마다 학습 방식이 달라지는 다른 Vision-language 모델들과의 차별점으로 똑같은 방식(<code>mask-then-predict</code>)만 사용해서 pretrain 시켰고, Contrastive-based model(CLIP, CoCa 등)들 보다 더 작은 batch size로 학습시킬 수 있었다. -&gt; GPU memory에 있어 좋다.</p>
<h3 id="23-scaling-up-beit-3-pretraining">2.3 Scaling Up: BEiT-3 Pretraining</h3>
<p>위의 그림에서 각 부분별 parameter수를 제시 
데이터 크기 제시
학습때 사용한 hyperparameter, augmentation종류 제시</p>
<h2 id="3-experiments-on-vision-and-vision-language-tasks">3. Experiments on Vision and Vision-Language Tasks</h2>
<h4 id="visual-question-answeringvqa">Visual Question Answering(VQA)</h4>
<p><code>VQA v2.0 dataset</code> 으로 finetuning해서 실험했다.
VQA를 일종의 Classification task처럼 해석하여, Trainset에 가장 자주 등장한 3129개의 대답 후보들 중 하나를 예측하도록 했다.</p>
<p>위 그림의 <code>(c) Fusion Encoder</code> 모양을 이용했고, Input으로 주어지는 Question에서 뽑은 embedding과, Image에서 뽑은 embedding을 concat하여 <code>Multiway Transfomer</code> 구조에 넣어 주었다.
이후 나온 output을 classifier layer에 넣어 최종 답을 예측하도록 하였다.</p>
<h3 id="총정리">총정리</h3>
<ul>
<li>다른 VQA논문을 더 읽어봐야 알겠지만, 이걸 classification 문제로 풀지 않고 다른 방법이 있는지 궁금하다.</li>
<li>이 논문에 등장한 BEiT v1, v2의 image tokenizing 방법과 masking 방법을 반드시 알아보자</li>
<li>현재 VQA v2.0 데이터셋 기준 SOTA 모델이던데, 다른 논문에선 어떤 모델구조를 띄는지 2등 3등도 알아보자.</li>
<li>Fusion Encoder에서 Image embedding, text embedding을 어떻게 만져서 모델에 넣었는지 코드를 한번 뜯어보자</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>