<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>nayeoniee.log</title>
        <link>https://velog.io/</link>
        <description>개발노트</description>
        <lastBuildDate>Sat, 23 Aug 2025 15:18:17 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>nayeoniee.log</title>
            <url>https://velog.velcdn.com/images/ny_/profile/8f5ae132-d0d2-47b4-ae03-fddcb99790ab/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. nayeoniee.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ny_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[파이콘 2025] 2일차 후기]]></title>
            <link>https://velog.io/@ny_/%ED%8C%8C%EC%9D%B4%EC%BD%98-2025-2%EC%9D%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@ny_/%ED%8C%8C%EC%9D%B4%EC%BD%98-2025-2%EC%9D%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sat, 23 Aug 2025 15:18:17 GMT</pubDate>
            <description><![CDATA[<h1 id="세션">세션</h1>
<h2 id="lets-logging-like-a-pro-정도현">Let’s Logging Like a Pro! (정도현)</h2>
<p>-&gt; <a href="https://2025.pycon.kr/presentations/359579b5-a230-464f-b223-ec3e3efc874f#Lets-Logging-Like-a-Pro">세션 소개 내용 보기</a>
<img src="https://velog.velcdn.com/images/ny_/post/226e6333-d894-4870-a31f-985be991ac70/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/8ad2a5b2-97bb-4272-bb86-faa7e0c744bc/image.png" 
     width="600"></p>
<p>파이썬의 표준 로깅 라이브러리인 logging을 소개해주었다.</p>
<p><strong>Worst Practice</strong></p>
<ul>
<li>로깅이 아예 없는 것이다. 운영 시 fail 나면 어디서 실패했는지 알기 어렵다.</li>
<li>개발 시 print 구문을 사용하고 배포 시 까먹으면 사용하지 않는 코드가 많아진다.</li>
<li>with open() 구문은 자동으로 close, exit을 호출하기 때문에 로그 파일을 쓸 때마다 I/O가 발생한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/7d6f61a8-1e8d-43d9-874e-d56cd9dfa9a5/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/cfb5c5dd-8fd6-4893-a17c-34e9dd17d193/image.png" 
     width="600"></p>
<p><strong>Python Standard Logging</strong></p>
<ul>
<li>getLogger() : 로거 생성</li>
<li>main_logger, sub_logger 2개를 생성해 propagate=True 옵션을 주면 상위 단의 로거 정보를 가져올 수 있다. Flask, sqlalchemy와 같이 로깅 모듈을 따로 가진 애들과 함께 사용하기 좋다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/e8fc5d89-8875-4d1e-9cab-01757545ccc7/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/ea89d278-c840-4a6b-abef-6510e4a263ab/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/92f4c99b-c5ff-46d4-8d0a-1182e3033970/image.png" 
     width="600"></p>
<p><strong>로그 레벨 설정</strong></p>
<ul>
<li>StreamHandler: 콘솔에 출력</li>
<li>TimedRotatingFileHandler: 설정한 시간에 로그 파일이 rotate<ul>
<li>when=“midnight”: 자정에 업데이트</li>
<li>BackupCount=15: 보관할 로그 파일의 최대 개수. 16개가 되면 가장 과거의 로그 파일 하나를 삭제함</li>
</ul>
</li>
<li>QueueHandler / QueueListener: 로그 출력도 파일 I/O가 발생하기 때문에, 이 부분을 최소화하기 위한 방식.<ul>
<li>log.start(), stop() 코드를 명시적으로 작성해야 동작함</li>
</ul>
</li>
</ul>
<h2 id="10년-이상의-파이콘-데이터로-duckdb와-벡터-임베딩을-활용하여-기술-트랜드-인사이트-찾기-박조은">10년 이상의 파이콘 데이터로 DuckDB와 벡터 임베딩을 활용하여 기술 트랜드 인사이트 찾기 (박조은)</h2>
<p>-&gt; <a href="https://2025.pycon.kr/presentations/b7513127-147f-4087-899c-5effcd895d30#10%EB%85%84-%EC%9D%B4%EC%83%81%EC%9D%98-%ED%8C%8C%EC%9D%B4%EC%BD%98-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A1%9C-DuckDB%EC%99%80-%EB%B2%A1%ED%84%B0-%EC%9E%84%EB%B2%A0%EB%94%A9%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EA%B8%B0%EC%88%A0-%ED%8A%B8%EB%9E%9C%EB%93%9C-%EC%9D%B8%EC%82%AC%EC%9D%B4%ED%8A%B8-%EC%B0%BE%EA%B8%B0">세션 소개 내용 보기</a></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/762222f6-a523-4e7d-ae10-15fcf101591d/image.png" 
     width="600"></p>
<p>&quot;파이콘 10년 치의 데이터를 정형 데이터로 변환해 트변환해 트렌드를 파악해보기&quot;를 목표로 진행한 프로젝트에 대해 소개해주었다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/ff2dc682-ef8a-49be-aa3c-7b937e72f290/image.png" 
     width="600"></p>
<p><strong>데이터 수집</strong></p>
<ul>
<li><a href="https://github.com/pyvideoeda/py-video-data/">py-video-data</a> 프로젝트를 통해 PyVideo.org 사이트에서 파이콘 데이터를 수집했다.</li>
<li>유튜브에서 파이콘 플레이리스트 url은 직접 찾아서 MCP 입력으로 사용했다.</li>
<li>DuckDB를 사용했는데, pandas는 모든 데이터를 메모리에 로드하고 사용해 데이터가 커지면 느려지는 반면 DuckDB는 그렇지 않은 장점이 있기 때문이다.</li>
<li>자막 데이터는 저작권 이슈가 예상되어 수집하지 않고 수집하는 코드만 공유했다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/c484eaa1-4e4f-498d-9a4c-1f26f355388c/image.png" 
     width="600"></p>
<p><strong>데이터 분석</strong></p>
<ul>
<li>임베딩한 결과는 <a href="https://projector.tensorflow.org/">tensorflow embedding projector</a>를 사용해 시각화했다.<ul>
<li>직접 차원 축소할 필요 없이 임베딩한 결과인 임베딩 벡터만 입력하면 알아서 시각화 해주는 장점이 있다.</li>
<li>고차원 데이터이기 때문에 유사도 계산에는 보통 유클리드 보다는 코사인 값을 사용했다.(방향 정보를 활용하기 위해서)</li>
</ul>
</li>
<li>csv 대신 parquet 포맷을 사용해 데이터 압축률 50% 이상 높임. parquet은 메타데이터를 가지고 있기 때문에 파일 용량이 작으면 오히려 parquet 보다 csv 용량이 커지는 경우도 있지만, 용량이 작을 때는 큰 차이가 없기 때문에 그냥 parquet 쓰는게 낫다.</li>
<li>미국, 유럽, 한국 총 세 국가의 세션을 분석했는데 연도별 키워드가 비슷한게 인상적이었다.</li>
</ul>
<h2 id="좋아하는-기술을-나누다-보니-커뮤니티와-책이-생겼습니다-유현아">좋아하는 기술을 나누다 보니, 커뮤니티와 책이 생겼습니다 (유현아)</h2>
<p>-&gt; <a href="https://2025.pycon.kr/presentations/028e9f2b-70eb-4d93-a540-f632c72590d1#%EC%A2%8B%EC%95%84%ED%95%98%EB%8A%94-%EA%B8%B0%EC%88%A0%EC%9D%84-%EB%82%98%EB%88%84%EB%8B%A4-%EB%B3%B4%EB%8B%88-%EC%BB%A4%EB%AE%A4%EB%8B%88%ED%8B%B0%EC%99%80-%EC%B1%85%EC%9D%B4-%EC%83%9D%EA%B2%BC%EC%8A%B5%EB%8B%88%EB%8B%A4">세션 소개 내용 보기</a></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/463a4d70-1a20-42f9-8f74-2002c1bb1ffb/image.png" 
     width="600"></p>
<p>AI 전공자는 아니지만 JAX 라이브러리를 공부하기 시작한 것을 계기로 책 집필까지 이어졌다고 한다. 좋아하는 기술을 꾸준히 학습하고 공유하는 과정에서 JAX KR 커뮤니티 운영진으로 활동하게 되었고, 강연 기회도 얻게 되었다고 한다. 특히 <strong>“좋아하는 기술을 공부하고 나눈다”</strong>는 태도는 이번 파이콘 행사의 취지와도 맞닿아 있고 핵심을 정확히 짚는 메시지였다.</p>
<h1 id="부스">부스</h1>
<p><img src="https://velog.velcdn.com/images/ny_/post/e5859d6a-132e-449a-b5c5-f784e35f8787/image.png" 
     width="600"></p>
<p>둘째 날에는 부스를 많이 돌아다녔다.
모든 것을 파이썬으로 개발한 손금 &amp; 관상을 볼 수 있는 토룡점이 있어, 나는 관상으로 나랑 닯은 뱀을 알아보았다. 파이썬 로고와 같은 뱀을 주제로 잡은 부분이 재미있었다. 나는 따뜻한 인디고뱀!!!</p>
<p>mediapipe 라이브러리로 얼굴에서 특징점을 추출하고, 관련 정보를 뱀 정보와 함께 프롬프팅으로 LLM에게 넘기면 뱀을 추천해주는 구조였다. 결과지를 출력하는 모듈까지 파이썬 래퍼로 개발했다 해서 정말 파이썬의 활용은 무궁무진한 것 같다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/c66cd702-cee0-4d7a-b415-e9020bb37018/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/471c4e0d-7f33-4395-83c4-5530a50b9316/image.png" 
     width="600"></p>
<p>다양한 기업과 커뮤니티에서 부스를 운영하며 제품과 서비스를 소개하고 있었다. 모든 부스를 방문하면 돌림판 이벤트에 참여해 상품을 받을 수 있었는데, 참여율을 높이는 데 최적화된 방식이었다. 마지막에 받은 수제 캔디에는 파이썬 로고가 새겨져 있어 더욱 특별하고 귀여운 기념품으로 남았다.</p>
<h1 id="마무리하며">마무리하며</h1>
<p>평소 ‘언젠가 공부해야지’ 하고 미뤄두었던 부분들에 대해 다시금 경각심을 일깨울 수 있었고, 파이썬을 좋아하는 사람들이 모여 함께 즐길 수 있는 장이 마련되어 더욱 뜻깊었다.</p>
<ul>
<li>rag chunking 방식을 공부해 검색에 미치는 영향 확인. 나아가 파일 파싱, 청킹, 임베딩, 검색으로 구성된 RAG 전체 파이프라인을 만들어 각 구성요소 옵션이 바뀔 때 어떤 영향을 미치는지 확인할 수 있는 데모 페이지가 있으면 좋겠음</li>
<li>logging 모듈 옵션 공부 후 로그 파일 보완</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이콘 2025] 1일차 후기]]></title>
            <link>https://velog.io/@ny_/%ED%8C%8C%EC%9D%B4%EC%BD%98-2025-1%EC%9D%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0-k03s9h4x</link>
            <guid>https://velog.io/@ny_/%ED%8C%8C%EC%9D%B4%EC%BD%98-2025-1%EC%9D%BC%EC%B0%A8-%ED%9B%84%EA%B8%B0-k03s9h4x</guid>
            <pubDate>Sat, 23 Aug 2025 15:17:22 GMT</pubDate>
            <description><![CDATA[<h1 id="세션">세션</h1>
<h2 id="vlm-눈-달린-llm을-만나보자-김대현">VLM, 눈 달린 LLM을 만나보자! (김대현)</h2>
<p>-&gt; <a href="https://2025.pycon.kr/presentations/ae847a02-4470-42a8-a383-9fed6bbdedda#VLM-%EB%88%88-%EB%8B%AC%EB%A6%B0-LLM%EC%9D%84-%EB%A7%8C%EB%82%98%EB%B3%B4%EC%9E%90">세션 소개 내용 보기</a></p>
<p><img I src="https://velog.velcdn.com/images/ny_/post/bfa9e529-376d-4678-b2e9-d9452e2a24d7/image.png" 
     width="600"></p>
<p>LLM과 비교하여 VLM의 작동 원리에 대한 설명과 VLM을 활용한 발표 영상 피드백 모델을 개발한 경험을 소개해주었다.</p>
<p>입력이 이미지이기 때문에 처음에는 CV 모델을 고려했으나, CV 모델은 판단만 하고 사용자에게는 어떤 피드백을 줘야할지 모르기 때문에 VLM을 사용했다. 행동에 대한 피드백을 사용자에게 텍스트로 제공하기 위해서이다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/acc28324-a383-425d-bf2e-fa7dfd684a6b/image.png" 
     width="600"></p>
<p>VLM 모델이 이미지에서 정확한 정보를 추출하지 못하는 문제가 있어, GPU가 없어도 되는 구글의 mediapipe 라이브러리를 사용했다.</p>
<p>또한, 추론 시 너무 많은 프레임을 분석해 API 토큰 수가 초과하는 문제가 발생했다. 따라서 발표 영상에서 피드백을 해줄(문제가 되는) 행동들을 정의하고 임계치를 설정했다. 해당 임계값을 넘은 프레임만 문제가 있다고 판단해 LLM을 너무 자주 호출하지 않도록 했다.</p>
<p>LLM을 주제로 다룬 경우가 많은데 VLM을 발표 주제로 다루어주셔서 새로웠다.</p>
<h2 id="파이썬과-생성형-ai를-활용한-합성-데이터-구축-파이프라인-개발--실무-llmops-가이드-강정석-송영숙">파이썬과 생성형 AI를 활용한 합성 데이터 구축 파이프라인 개발 : 실무 LLMOps 가이드 (강정석, 송영숙)</h2>
<p>-&gt; <a href="https://2025.pycon.kr/presentations/b0867394-a5c5-48b4-b6ee-674dafc62631#%ED%8C%8C%EC%9D%B4%EC%8D%AC%EA%B3%BC-%EC%83%9D%EC%84%B1%ED%98%95-AI%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%95%A9%EC%84%B1-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%B6%95-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EA%B0%9C%EB%B0%9C--%EC%8B%A4%EB%AC%B4-LLMOps-%EA%B0%80%EC%9D%B4%EB%93%9C">세션 소개 내용 보기</a></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/e4dfe907-e86d-4320-9e46-45ac49343d9a/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/8f0246c5-e2c4-4da3-8499-77da06839e16/image.png" 
     width="600"></p>
<p>모델 성능을 높이기 위해 합성/증강 데이터를 만드는 방법이 흔하다. 하지만 이미지와 데이터와 비교해 자연어는 잘못하면 모델 학습이 되지 않거나 어색한 말을 생성해 합성 데이터를 만들기 쉽지 않다.</p>
<p>따라서 완전히 새로운 문장을 만드는 방식이 아닌 <strong>고쳐쓰기(rephrase)</strong> 방식을 사용해 합성 데이터와 데이터 파이프라인을 구축한 경험을 공유해주었다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/8dd485d6-7b2a-4316-bd57-991c35df0dd0/image.png" 
     width="600"></p>
<p>사내 기술 블로그 데이터를 사용해 어미에 유의하며 프롬프팅으로 증강했다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/fbb19ae6-2563-48a3-bdf0-3cdf4fa15ce9/image.png" 
     width="600"></p>
<p>지속적으로 고품질의 데이터를 만들기 위해 데이터 구축 뿐만 아니라 데이터 구축 <strong>파이프라인</strong> 만드는 것을 강조하셨고, 이를 위해 자사 제품인 Backend.AI 를 사용해 실험을 진행했다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/fb58d259-8f25-4660-80cd-b4cc07772d46/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/746fa947-32bd-4305-a0c8-1a5bbc1a46ab/image.png" 
     width="600"></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/ed7d11d8-f835-4684-8192-d81a929994b3/image.png" 
     width="600"></p>
<p>전체 파이프라인은 LLM 서빙-원본 데이터-합성 데이터 생성-합성 데이터 평가로 이루어졌다. 합성 데이터 평가 시에는 룰 기반, LLM 기반, 사람 기반 3가지 방식을 사용했다.</p>
<p>자연어 데이터 업계에서 유명한 송영숙님이 발표하셔서 개인적으로 기대되었던 세션이었고, 전에 직접 학습 데이터셋을 구축한 작업이 생각나 공감되는 부분이 많았다.
LLM 실험 및 평가에 자사 제품을 사용하고 실 사용자에게 피드백을 받으며 제품을 개선해나간 부분이 인상적이었다.
시간에 쫓겨 데이터를 구축하다 보면 이력 관리도 안되고, 한 번 학습에 쓰이고 버려지는 경우가 있는데 제품을 활용한 체계적인 실험이 부러웠다….</p>
<h2 id="자비스-내-서비스에-무슨-문제가-있는거야-자연어-기반-운영-흐름과-mcp-개발기-김민석">자비스, 내 서비스에 무슨 문제가 있는거야? 자연어 기반 운영 흐름과 MCP 개발기 (김민석)</h2>
<p>-&gt; <a href="https://2025.pycon.kr/presentations/5c43a08b-e91c-4b93-b19e-0e44f060ac63#%EC%9E%90%EB%B9%84%EC%8A%A4-%EB%82%B4-%EC%84%9C%EB%B9%84%EC%8A%A4%EC%97%90-%EB%AC%B4%EC%8A%A8-%EB%AC%B8%EC%A0%9C%EA%B0%80-%EC%9E%88%EB%8A%94%EA%B1%B0%EC%95%BC-%EC%9E%90%EC%97%B0%EC%96%B4-%EA%B8%B0%EB%B0%98-%EC%9A%B4%EC%98%81-%ED%9D%90%EB%A6%84%EA%B3%BC-MCP-%EA%B0%9C%EB%B0%9C%EA%B8%B0">세션 소개 내용 보기</a></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/a1da2d52-ad51-49d2-937b-b1d6483bb9f4/image.png" 
     width="600">     </p>
<p>MCP의 개념과 대화형 서버 예제를 소개해주었다.
MCP(Model Context Protocol)는 LLM 애플리케이션과 외부 데이터 소스, 도구 간의 원활한 통합을 가능하도록 하는 프로토콜을 의미한다.</p>
<p>MCP는 prompts, resources, tools 3가지로 구성된다. </p>
<ul>
<li>Prompts: 재사용 가능하도록 구성</li>
<li>Resources: context를 제공할 수 있는 외부 데이터, DB 등</li>
<li>Tools: 실행 가능한 함수. 함수명, 파라미터, 입출력 타입 힌트, 주석에 따라 LLM이 툴을 선택하기 때문에 매우 중요함</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/3a5339b6-913a-44a5-b30f-b9f9b74b6d35/image.jpeg" 
     width="600"></p>
<p>MCP가 적절한 툴을 선택하는 과정은 클라이언트가 사용 가능한 툴 목록 조회 -&gt; 의도 분석해 최적의 도구 선택 -&gt; 선택한 도구 실행 및 결과 처리 순서로 이루어진다.</p>
<h2 id="rag-애플리케이션-개발을-위한-chunking-최적화-강성우">RAG 애플리케이션 개발을 위한 Chunking 최적화 (강성우)</h2>
<p>-&gt; <a href="https://2025.pycon.kr/presentations/4a4ca5cf-b568-458e-80b4-4a319f0f9971#RAG-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EA%B0%9C%EB%B0%9C%EC%9D%84-%EC%9C%84%ED%95%9C-Chunking-%EC%B5%9C%EC%A0%81%ED%99%94">세션 소개 내용 보기</a></p>
<blockquote>
<p>LLM의 기억 관리 책임은 모델이 아닌 인간에게 있다.
RNN이나 Mamba는 내재적 메모리 아키텍처를 통해 스스로 정보를 보존하지만, LLM은 매번 인간이 설계한 컨텍스트에 전적으로 의존한다.</p>
</blockquote>
<p>LLM이 예전 대화를 기억하는 방법은 답변 추론 시 예전 대화 기록을 모두 입력으로 활용하기 때문이다. 즉, 사람이 입력한 context를 그대로 활용한다. 이 때 모델은 context length 한계가 있기 때문에 문서를 일정 길이로 잘라(chunking) 입력에 사용한다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/6a321456-e937-4ded-821f-adb07d5899d9/image.jpeg" 
     width="600"></p>
<p>여러 가지 chunking 전략을 소개해주었다. </p>
<ol>
<li>Recursive Chunking</li>
</ol>
<ul>
<li>구분자별로 우선순위가 있어 우선순위가 높은 구분자를 기준으로 분할(split)해 설정한 크기보다 작게 만드는 방식이다.</li>
<li>예를 들어 context_length=100일 때 우선순위가 가장 높은 개행 문자를 기준으로 자르고, 100을 초과한다면 다음 구분자로 나누고를 반복한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/a9a29c6c-414f-4df0-9885-c5b9512f6321/image.jpeg" 
     width="600"></p>
<ol start="2">
<li>Semantic Chunking</li>
</ol>
<ul>
<li>임베딩을 사용해 각 chunk의 이미를 추출하고, 의미 유사도가 비슷하면 다시 병합하는 방식이다.     </li>
</ul>
<ol start="3">
<li>MoC(Mixture-of-chunks)</li>
</ol>
<ul>
<li>LLM이 chunk를 어떻게 나누면 좋을지 결정하는 방법인데, 학술적으로 재미있지만 API 추론 비용이 많이 드는 방식이다.</li>
</ul>
<p>청킹 시 유의해야할 점도 공유해주었다.</p>
<ul>
<li>청크 크기와 검색 성능은 서로 trade-off 관계: 청크가 너무 작으면 문맥을 파악하는데 필요한 정보가 적고, 크기가 너무 크면 검색 성능이 약해진다.</li>
<li>청킹 고도화 및 최적화 기법: 현실적으로는 청킹 알고리즘을 복잡하게 가져가지 말고, 청킹한 결과를 사후 보완하자. 각 문서의 파일명과 같은 메타 데이터를 활용하거나, 각 청크가 문서에서 어떤 부분에 위치하고 무엇에 관한 설명인지를 추가해 임베딩하는 context retrieval 방법이 있다.</li>
<li>성능 평가: llm-as-judge를 사용해 답변 생성하는 LLM은 고정해두고 청킹 방법을 바꿔가며 진행했다.</li>
</ul>
<h1 id="부스">부스</h1>
<p><img src="https://velog.velcdn.com/images/ny_/post/b35d402b-8a11-4d08-9473-3a6d6a44477f/image.jpeg" 
     width="600"></p>
<p>첫날은 오후부터 참여해서 세션 위주로 듣다 보니 부스를 많이 돌아다니지는 못했다. 그래도 도서 증정 이벤트에 당첨되어서 딱 원하던 책을 받을 수 있었다! 이제 읽기만 하면 된다 ㅎㅎ</p>
<p>첫 날 행사 이후에는 자원봉사자, 파준위, 연사자분들이랑 다 같이 저녁을 먹었다. 식당이 꽤 컸는데도 한 번에 다 못 들어갈 정도로 사람이 많았다. 아침부터 긴장하면서 일해서 그런지 다들 피곤해 보였지만, 하루를 무사히 마쳤다는 안도감 덕분에 분위기가 좋았다. 일 얘기 말고도 이런저런 얘기를 하면서 친해질 수 있어서 즐거웠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이콘 2025] 자원봉사자 후기]]></title>
            <link>https://velog.io/@ny_/%ED%8C%8C%EC%9D%B4%EC%BD%98-2025-%EC%9E%90%EB%B4%89%EA%B8%B0%EC%9E%90%EC%9B%90%EB%B4%89%EC%82%AC%EC%9E%90-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@ny_/%ED%8C%8C%EC%9D%B4%EC%BD%98-2025-%EC%9E%90%EB%B4%89%EA%B8%B0%EC%9E%90%EC%9B%90%EB%B4%89%EC%82%AC%EC%9E%90-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sun, 10 Aug 2025 04:58:01 GMT</pubDate>
            <description><![CDATA[<h1 id="파이콘-소개">파이콘 소개</h1>
<p><strong>파이콘(PyCon)</strong>은 Python Conference의 약자로 파이썬(Python) 프로그래밍 언어 중심의 비영리 개발자 행사이다.
2003년 미국에서 처음 개최된 이후 전 세계 여러 나라에서 매년 열리고 있으며 개발자, 데이터 과학자, 학생, 그리고 파이썬에 관심 있는 누구나 참여할 수 있는 열린 장이다. 한국에서는 2014년에 첫 파이콘이 열렸고 올 해로 11번째 행사이다.
행사에서는 기술 세션, 튜토리얼, 스프린트, 네트워킹 등 다양한 활동이 진행되며, 지식 공유와 커뮤니티 발전에 초점이 맞춰져 있다.</p>
<p><strong>파이콘 한국 2025</strong></p>
<ul>
<li>일시: 2025년 8월 15일 ~ 17일</li>
<li>장소: 동국대학교 서울캠퍼스 신공학관</li>
<li>주제: 올해의 슬로건 <strong>Weave with Python</strong>은, 파이썬을 단순한 프로그래밍 언어를 넘어 사람과 기술, 정보와 아이디어를 유기적으로 엮는 도구로 바라보자는 의미를 담고 있다.</li>
<li>웹사이트: <a href="https://2025.pycon.kr/">https://2025.pycon.kr/</a></li>
</ul>
<h1 id="자원봉사자-지원">자원봉사자 지원</h1>
<p>파이썬 백엔드 개발과 관련해 인터넷 검색을 하다가 유튜브에서 파이콘 행사 영상을 본 적이 있어 파이콘에 대해서는 몇 년 전부터 알고 있었다.
하지만 그 당시에는 “무료로 참여할 수 있는 개발자 컨퍼런스도 많은데, 굳이 티켓을 구매해서까지 가야 할까? 유튜브에 올라오는 영상만 봐도 충분하지 않을까?”라는 생각을 했다.</p>
<p>그러다 문득, 휴일에 시간을 내어 직접 참석하는 사람들은 어떤 사람들일까? 파이썬 커뮤니티는 어떤 분위기일까? 하는 호기심이 생겼다.
이 궁금증과 커뮤니티에 대한 관심이 나를 움직였고 바로 티켓을 구매했다.</p>
<p>파이콘에 자원봉사자로 지원한 데에는 크게 두 가지 이유가 있다.</p>
<ol>
<li><p>파이콘 커뮤니티에 대한 관심
광복절 연휴를 반납하고 참여하는 사람들은 어떤 매력을 느껴 행사에 오는 걸까?
특히, 자발적으로 봉사까지 하는 분들은 파이썬과 커뮤니티에 어떤 애정을 가지고 있을까?</p>
</li>
<li><p>기술 공유 문화와 행사 운영에 대한 관심
다른 IT 행사나 박람회에서 만난 담당자들은 바쁜 와중에도 항상 즐거워 보였는데, 행사를 준비하는 과정은 어떤 분위기일까?</p>
</li>
</ol>
<h1 id="사전-모임--준비-과정">사전 모임 &amp; 준비 과정</h1>
<p><img src="https://velog.velcdn.com/images/ny_/post/ef69b3df-cde8-4d68-9dcd-3bd3b5b51875/image.jpeg" alt=""></p>
<p>자원봉사자 모집은 행사 약 3주 전에 시작되었고, 사전 모임은 1주 전에 진행되었다.
모임은 온라인과 오프라인을 병행했으며, 다른 자원봉사자들과 얼굴을 익히고 싶어 나는 오프라인으로 참석했다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/0dec9448-f3cd-4982-9f1e-645d0f1a2c8d/image.jpeg" alt=""></p>
<p>벌써 뿌듯하잖아~! &quot;자봉&quot;이라는 줄임말도 귀엽다 :)</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/b146bfb4-c4b8-401a-8082-361200771bb6/image.jpeg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/4e7b347f-1d83-4111-b670-17961a39e02e/image.jpeg" alt=""></p>
<p>워크숍은 약 1시간 동안 진행되었다. 첫 30분은 파이콘 행사 소개, 행동 강령, 준비위원회(파준위) 소개, 자원봉사자의 역할에 대한 설명이 있었고,나머지 30분은 오프라인 참석자들끼리 네트워킹을 하는 시간이었다.</p>
<p>서로 조금은 어색했지만, 행사 당일에는 분명 더 친해져서 편하게 협력할 수 있을 것 같다!</p>
<h1 id="행사-당일-이야기">행사 당일 이야기</h1>
<p>행사 전 자원봉사자 스케줄과 매뉴얼을 미리 공유받아 전체 프로그램 구성과 내가 맡게 될 역할을 미리 확인했다.
덕분에 행사 당일 어떤 활동이 진행되는지, 각자 자리에서 어떤 업무를 기대하고 있는지 사전에 감을 잡을 수 있었다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/56177745-e770-4933-8d29-d9a217178f44/image.jpeg" 
     alt="열심히 준비하는 " 
     width="600"></p>
<p>첫날 행사는 오전 10시에 시작이였기 때문에 1시간 일찍 모여 다른 자원봉사자분들과 인사를 나누고, 맡은 일에 대한 간단한 설명을 듣는 시간을 가졌다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/e6c72259-6de8-4b6e-888c-999355357e26/image.jpeg" 
     alt="이미지 설명" 
     width="600" 
     height="auto"></p>
<p>그리고 무엇보다… 아침 식사!
제공해주신 이삭토스트로 에너지를 충전했는데, 오랜만에 먹으니 정말 맛있었다. 다 먹고 나서야 사진을 찍었다. 😆</p>
<h3 id="6층에서-시작하는-오전-등록-데스크-안내">6층에서 시작하는 오전: 등록 데스크 안내</h3>
<p>이번 파이콘에서 나는 6층 등록 데스크 안내와 스프린트 보조 역할을 맡았다. 파이콘에 오면 가장 먼저 해야할 일은 구매한 튜토리얼/티켓을 등록이다. 행사장에 도착한 참가자들이 우왕좌왕하지 않고 절차를 마친 뒤, 곧바로 프로그램을 즐길 수 있도록 안내했다. </p>
<p><img src="https://velog.velcdn.com/images/ny_/post/4abd6679-a6db-4bf2-8251-530ef1bd110e/image.jpeg"  
     width="600"></p>
<p>등록 데스크 바로 앞에 큼직한 X배너가 있어 처음엔 “안내가 필요할까…?” 싶었지만, 막상 해보니 정말 필요했다. 😆 
동국대를 처음 방문하는 분들이 대부분이었고, 1층에서 6층 등록 데스크까지 그리고 각 튜토리얼/세션장으로 가는 이동 동선이 시각적으로 잘 보이지 않아 헷갈려하는 분들이 많았기 때문이다. (나도 첫 날 헷갈렸다)</p>
<h3 id="스프린트-보조-braillify-프로젝트">스프린트 보조: Braillify 프로젝트</h3>
<p>스프린트는 관심있는 오픈소스 프로젝트를 같은 장소에 모여 집중적으로 개발하는 자리로, 오전 10시부터 오후 5시까지 거의 하루 종일 진행되었다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/589ed271-4249-4626-8f11-b7ff79378b8f/image.jpeg"  
     width="600"></p>
<p>나는 <strong>Braillify</strong> 라는 한글 점역 오픈소스 스프린트의 보조를 맡았다.
Braillify는 점자를 한글로 바꾸는 라이브러리로 Rust 언어로 개발되었다. </p>
<blockquote>
<p>‘Braille(점자)’에 ‘-ify(~화化하다)’를 더해 한층 더 쉬운 점자화를 보다 널리 퍼뜨리고자 만든 프로젝트입니다.
모두가 점역을 이해하고 활용할 수 있는 환경을 함께 만들어갑니다.</p>
</blockquote>
<ul>
<li><a href="https://braillify.kr/">Braillify</a></li>
<li><a href="https://github.com/dev-five-git/braillify">Braillify 기여하기</a></li>
</ul>
<p>이미 점역 코어 엔진은 어느 정도 완성되어 있었고, 이날은 2024년 개정된 한국 점자 규정에 맞춰 동작하는지 테스트 케이스를 만드는 작업이 진행되었다.
작업 방식은 간단했다. <code>converter.py</code>에 한글 단어를 입력하면 Braillify가 변환한 점자 결과가 출력되고, 이를 테스트 케이스로 등록했다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/1c6cc274-5547-4215-82d4-c51ca4babb06/image.png" alt=""></p>
<p>Braillify 웹사이트의 테스트 케이스 메뉴에서 점역 규정과 항별 테스트 케이스를 확인할 수 있고, 성공 시 초록색, 실패 시 빨간색으로 표시된다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/0b2fff76-fa0b-46bd-ba7d-b989648e9f2d/image.jpeg" alt=""></p>
<p>오전에는 강의실 안내를 주로 하고, 오후에는 여유로워 직접 스프린트에 참여했다. 노트북을 안 들고 가서 아이패드로 작업하느라 약간 고생했지만요… 😅</p>
<p>사실 점자를 공공시설이나 엘리베이터 버튼에서 본 적만 있지, 원리나 규칙을 깊이 생각해 본 적은 없었다. 오픈소스의 테스트 케이스를 만들면서 띄어쓰기나 줄바꿈 규칙에 대해 알게되었다.</p>
<h3 id="마무리하며">마무리하며</h3>
<p><img src="https://velog.velcdn.com/images/ny_/post/52c9f21b-bbc9-4b7b-8c52-74645d2e4e7b/image.png" 
     width="600"></p>
<p>스프린트를 혼자 진행했지만 행사장을 오가며 또 식사 자리에서 다른 자원봉사자, 파준위 분들과 이야기를 나눌 수 있었다.
파이썬에 대한 애정과 나눔의 마음으로 가득한 분들과 함께한 3일은 나 역시 덩달아 행복해지는 시간이었다.
다음에도 기회가 된다면 파이콘과 파이썬 커뮤니티에 기여하고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[밋업 후기] W&B 세번째 서울 밋업]]></title>
            <link>https://velog.io/@ny_/%EB%B0%8B%EC%97%85-%ED%9B%84%EA%B8%B0-WB-%EC%84%B8%EB%B2%88%EC%A7%B8-%EC%84%9C%EC%9A%B8-%EB%B0%8B%EC%97%85</link>
            <guid>https://velog.io/@ny_/%EB%B0%8B%EC%97%85-%ED%9B%84%EA%B8%B0-WB-%EC%84%B8%EB%B2%88%EC%A7%B8-%EC%84%9C%EC%9A%B8-%EB%B0%8B%EC%97%85</guid>
            <pubDate>Tue, 04 Feb 2025 21:53:30 GMT</pubDate>
            <description><![CDATA[<p>AI, 딥러닝 분야에서 학습 예제를 실행해봤다면 한 번 쯤 들어봤을 wandb에서 진행하는 세번째 밋업에 다녀왔습니다 ✨
작년에 진행했던 두 번의 밋업은 참석하지 못했습니다 ㅠㅠ
<a href="https://event-us.kr/wandb/event/97373?utm_source=newsletter&amp;utm_medium=marketo&amp;utm_campaign=wigaeadedl">이벤트어스</a> 사이트에서 신청했고, 이번에는 일찍 신청하면 추첨 없이 확정인 것 같았습니다!</p>
 <img src="https://velog.velcdn.com/images/ny_/post/2096b3c7-1b96-4eec-91ea-6f595d1265c0/image.png" width="700">

<h2 id="0-wb-소개">0. W&amp;B 소개</h2>
<p>W&amp;B는 손쉽게 딥러닝 모델을 학습, 평가할 수 있는 툴을 제공한다. 일반 ML 모델에는 학습 로깅 및 시각화 기능인 Experiments, 하이퍼파라미터 최적화 기능인 Sweeps 등이 있다. LLM 모델에는 모델 입출력 추적 기능인 Traces, 평가 기능인 Evaluations가 있다.
이러한 기능 뿐만 아니라, LLM을 빌딩하는 곳에서 wandb를 많이 사용하기 때문에 작년에는 LLM을 평가하는 <a href="https://wandb.ai/wandb-korea/llm-leaderboard3/reports/Horangi-W-B-Korean-LLM-Leaderboard-3--Vmlldzo5NTM4MjU0">호랑이 리더보드</a>도 공개했다.</p>
<h2 id="1-ai-for-design--miridih-장주영">1. AI for Design / MIRIDIH 장주영</h2>
<img src="https://velog.velcdn.com/images/ny_/post/0b1fcff0-0732-40c5-953e-9101615f9e0f/image.png" width="700">
미리디 회사는 "미리캔버스"라는 웹 기반 디자인 솔루션을 만든다. 발표자료나 디자인 템플릿이 다양해 한 번쯤은 들어봤을 서비스이다.

<img src="https://velog.velcdn.com/images/ny_/post/deb895c5-9dbb-4c38-a1ad-ce985c2fd7c0/image.png" width="700">

<img src="https://velog.velcdn.com/images/ny_/post/4b1da461-ac93-446d-b151-dd170d0f0ee5/image.png" width="700">

<p>템플릿 디자인하는데 AI를 어떻게 활용하는지 궁금했는데 아래와 같은 기능에 사용된다고 한다.</p>
<ul>
<li>발표자료의 여백을 새로운 요소를 추가하거나 재배치할 때</li>
<li>발표자료에 어울리는 아이콘이나 이미지 삽입할 때</li>
</ul>
<img src="https://velog.velcdn.com/images/ny_/post/a66ec7a9-ea0a-4a6c-960b-f6aac8eeceb2/image.png" width="700">
<img src="https://velog.velcdn.com/images/ny_/post/5a094440-146d-4a62-aa4f-81e1e7500c34/image.png" width="700">

<p>기존 VLM에서 MLLM으로 모델을 변경하고, 사내 디자인 특화 데이터셋을 활용해 SFT 진행한 프로젝트 내용을 공유해주셨다. 
피피티에서 주변 이미지와 어울리는 그림을 찾을 때, 기존에는 이미지의 텍스트에 더 집중했다면 학습 이후에는 그림체나 스타일이 유사한 이미를 우선적으로 찾아오는 것으로 바뀌었다고 한다.</p>
<p>Q. 학습 데이터셋은 어떻게 구성했는가?
A. 기존 피피티 템플릿에서 요소를 삭제해 학습 pair 생성</p>
<p>Q. 학습한 모델 평가는 어떻게 하는가?
A. 초반에는 기존 템플릿과 비교 평가했고 요즘엔 A/B test, 사용자가 다운로드 받은 것을 정답으로 간주해 평가</p>
<h2 id="2-ai-agent-디자인-패턴과-weave--wb-오현우">2. AI Agent 디자인 패턴과 Weave / W&amp;B 오현우</h2>
<p>두 번째 세션에서는 AI 에이전트 예시와 Weave를 통한 트래킹 예시를 다루었다.</p>
 <img src="https://velog.velcdn.com/images/ny_/post/33a38763-9669-43ac-8079-cef0d2803b74/image.png" width="700">

<p> AI 에이전트를 설계할 때는 크게 6가지를 고려해야 한다. 멀티 에이전트 프로젝트에서는 복잡성이 올라가기 때문에 각 에이전트를 관리하는 것이 더 중요해진다.</p>
<img src="https://velog.velcdn.com/images/ny_/post/0ba867b4-92ac-4f0e-a419-6ab0c869e017/image.png" width="700">
Weave는 wandb에서 제공하는 LLM 관련 툴로 모델 입출력을 추적하는 Trace, 평가하는 Evaluation 기능을 제공한다.
다른 LLM 로깅, 평가 툴이 많지만 버전 관리와 데코레이터로 쉽게 적용할 수 있다는 점이 Weave의 특징이라 생각한다.

<img src="https://velog.velcdn.com/images/ny_/post/fb5f3ed0-ad36-415d-89b2-ca4ebe752124/image.png" width="700">
Weave의 워크플로우

<img src="https://velog.velcdn.com/images/ny_/post/75096cec-d703-45f2-affa-745f27845d2b/image.png" width="700">
crewai를 활용해 "주간 AI 뉴스레터 작성" 태스크를 수행하는 AI 에이전트를 만들고, Weave로 평가한 모습이다.
예전 버전의 LLM에 web search 툴 유무에 따라 평가했을 때, 툴을 붙인 에이전트가 최신성 질문에 올바르게 답변하는걸 확인할 수 있었다.


<h2 id="3-llm의-re-ranking-ability-검색에-이식하기--naver-이영준">3. LLM의 Re-Ranking Ability 검색에 이식하기 / NAVER 이영준</h2>
<p>세 번째 세션에서는 네이버 검색에 LLM의 re-reanking을 도입한 사례를 다루었다.</p>
<img src="https://velog.velcdn.com/images/ny_/post/f0dea86d-22df-4e68-8133-2ac0663a1604/image.png" width="700">
먼저 검색의 기초에 대해 설명해주셨다.
검색은 대충 비슷한 문서를 가져오는 retrieve, 가져온 문서들의 순위를 다시 재배치하는 rerank 두 단계로 구성된다.

<p>검색에 encoder 모델을 활용하는 구조에는 크게 bi-encoder와 cross-encoder 두 가지가 있다.
Bi-encoder는 사용자 질의와 문서를 따로 인코딩하는 방식으로, 문서를 미리 인코딩해 두어 지연시간이 짧은 장점이 있다.
Cross-encoder는 사용자 질의와 문서를 함께 인코딩하는 방식으로, 매번 질의가 달라지면 새로 인코딩해 상대적으로 지연시간이 길다.</p>
<p>일반적으로 retriever에는 빠른 bi-encoder 모델을, re-ranker에는 느리지만 좀 더 성능이 높은 cross-encoder 모델을 사용한다고 한다.</p>
<img src="https://velog.velcdn.com/images/ny_/post/31fb6ef0-8c41-44f8-b2d4-956648f4557e/image.png" width="700">
long-tail 쿼리에 대한 검색 성능을 높이기 위한 방법을 공유해주셨다.
구글에 "long-tail query"를 검색하면 위와 같은 이미지를 볼 수 있는데, 사용자 질의 길이가 길수록 검색되는 횟수는 적은 현상(?)을 의미한다.

<img src="https://velog.velcdn.com/images/ny_/post/f0cea317-defb-433b-ac9e-852b18a086ea/image.png" width="700">
 re-ranker 단계에 더 가벼운 모델을 사용하고자 BERT 모델을 distillation했고, 새롭게 학습 데이터셋을 구축했다.


<img src="https://velog.velcdn.com/images/ny_/post/b61bdd5b-8d7a-4742-9144-65b6a876b052/image.png" width="700">
BERT 모델 학습 시 "token selection" 단계를 추가해 사용자 쿼리의 핵심적인 토큰에 집중할 수 있도록 했다.

<img src="https://velog.velcdn.com/images/ny_/post/68d456ab-5e6f-49a3-802b-13ff7354bda3/image.png" width="700">
사용자 쿼리의 핵심적인 토큰에만 집중했더니 최신 문서를 잘 검색해오지 않아 문서의 최신성을 loss에 추가했다.

<img src="https://velog.velcdn.com/images/ny_/post/fa1d733f-17a9-4bcf-98f7-00114833639e/image.png" width="700">
세션 후반부로 갈수록 집중력이 떨어져 사진이 많이 없습니다 ㅠㅠ 자세한 내용은 아래 네이버 컨퍼런스나 논문에서 확인하실 수 있습니다!

<p><a href="https://dan.naver.com/24/sessions/604"><strong>DAN 24</strong></a>
네이버 검색이 이렇게 좋아졌어? LLM의 Re-Ranking Ability 검색에 이식하기</p>
<p><a href="https://aclanthology.org/2024.emnlp-industry.46/"><strong>EMNLP 2024</strong></a>
RRADistill: Distilling LLMs’ Passage Ranking Ability for Long-Tail Queries Document Re-Ranking on a Search Engine</p>
<h2 id="4-행사-후기">4. 행사 후기</h2>
<p>평일 저녁에 퇴근하고 밋업에 참여하는 사람들이 꽤 많았는데 학습 열의를 느낄 수 있었다.
행사 진행은 굉장히 원활했고 한 가지 아쉬운 점을 꼽자면 행사 후에 피자가 나와서 헝그리 정신으로 발표를 들었다.</p>
<p>첫 번째 세션은 이미지를 다루는 AI 팀에서는 어떤 일을 하는지 궁금했는데 대략적으로 알 수 있어서 좋았다.
두 번째 세션은 Weave 솔루션에 대한 내용이 가장 궁금했는데 해당 내용은 이전 밋업에서 다루어 이번에는 간단한 활용 예시만 다루어 아쉬웠다.
세 번째 세션은 LLM을 검색에 도입하기 위해 연관성, 속도 등 여러가지 고려할 사항과 이것들을 어떻게 풀어나갔는지 엿볼 수 있어 좋았다.</p>
<p>발표 시간에 비해 다루는 내용이 깊고 많아 궁금한 부분은 관련 자료를 읽어봐야겠다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS 자격증] AI Practitioner 시험 후기(AIF-C01)]]></title>
            <link>https://velog.io/@ny_/AWS-%EC%9E%90%EA%B2%A9%EC%A6%9D-AI-Practitioner-%EC%8B%9C%ED%97%98-%ED%9B%84%EA%B8%B0AIF-C01</link>
            <guid>https://velog.io/@ny_/AWS-%EC%9E%90%EA%B2%A9%EC%A6%9D-AI-Practitioner-%EC%8B%9C%ED%97%98-%ED%9B%84%EA%B8%B0AIF-C01</guid>
            <pubDate>Tue, 04 Feb 2025 13:53:57 GMT</pubDate>
            <description><![CDATA[<p>AWS Certified AI Practitioner를 취득했다.</p>
<p>클라우드 환경에서 AI 솔루션 만드는 일을 하는데 가장 적합한 자격증이라고 생각해 공부하기 시작했다. 물론 회사에서 지원해주는 시험 응시료도 한몫했다.</p>
<p>개인적으로는 AWS 클라우드 서비스보다는 AI에 대해 더 잘 알고 있어야 취득하기 수월하다 생각한다.</p>
<h2 id="1-시험-정보">1. 시험 정보</h2>
<ol>
<li>문항 수: 65문제 (15문제는 점수에 반영되지 않으며 시험 중에는 어떤 문제인지 알 수 없다.)</li>
<li>시험시간: 100분 (원래 90분인데 한국어로 신청해 시간을 더 받았다.)</li>
<li>소요시간: 50분</li>
<li>응시료: 100 USD (환율이 올라 13만 원 넘게 나왔다.)</li>
<li>시험장: 오프라인으로 응시했다. 신분증 검사, 서명하고 소지품을 모두 캐비넷에 넣은 후 시험장으로 이동했다. 독서실 책상에 컴퓨터가 일렬로 있고 각자 응시 시간에 맞춰서 들락날락하는 사람들이 있었다. 5명 이하만 들어갈 수 있는 작은 방이라 많이 신경 쓰이지 않았다. 시험 프로그램 UI가 굉장히 옛스러워서 당황했지만 플래그(헷갈리는 문제 체크) 기능 등 필수적인 건 모두 제공한다!</li>
<li>시험 결과: 시험 종료 직후에 나오지는 않고, 5시간 이내에 결과가 이메일로 발송된다. 그날 저녁 바로 상세 점수까지 확인했다.</li>
</ol>
<img src="https://velog.velcdn.com/images/ny_/post/e1d0ef0e-6284-445f-a55f-f81d685cad4a/image.png" width="700">

<img src="https://velog.velcdn.com/images/ny_/post/c9fcb8b0-b7ba-4ce0-b037-8773a61c2ea1/image.png" width="700">


<p>높은 점수는 아니지만 시험을 준비하는데 도움이 되었던 자료들을 정리했다.</p>
<h2 id="2-시험-준비">2. 시험 준비</h2>
<p>AWS, AI 분야에 대한 필자의 지식수준:</p>
<ul>
<li>AWS 지식은 거의 전무하다. 유명한 서비스(EC2, S3, IAM) 몇 개만 알고 있다.</li>
<li>LLM이 주목받기 이전부터 딥러닝 분야를 공부했고 현업에서 LLM 챗봇 엔진을 개발한 경험이 있다. AWS에서 제공하는 서비스에 대해서는 잘 모르지만, AI/ML 분야는 익숙하다.</li>
</ul>
<p><strong>AWS Skill Builder - <a href="https://explore.skillbuilder.aws/learn/courses/134/aws-cloud-practitioner-essentials/lessons/136404/aws-cloud-practitioner-essentials">AWS Cloud Practitioner Essentials</a></strong></p>
<p>처음에 Cloud Practitioner 자격증을 취득하려고 했기에 관련 강의를 수강했다.
AWS Skill Builder 사이트에서는 AWS 서비스, 자격증에 대한 기초 강의와 연습문제를(무료는 일부) 제공한다. 영어 강의이고 한국어 자막을 제공한다. 강의만 들으면 개념이 머릿속에 둥둥 떠있는 느낌인데, 이럴 때 깃헙의 강의자료를 추천한다.</p>
<p><strong>AWS 강의실 - <a href="https://www.youtube.com/watch?v=U6yEu_oZ4v8&amp;list=PLfth0bK2MgIYuFahPhXTpTomkwVx5Fl-v">쉽게 설명하는 AWS 기초강의</a></strong></p>
<p>AWS 분야에서는 굉장히 유명하신 분이다. 특히 한국어로 예를 들어가며 네트워크의 통신 과정을 설명해 주는 게 가장 도움이 많이 되었다.</p>
<p>AI Practitioner 자격증에서 요구하는 지식수준보다 더 깊고 넓은 내용을 다룬다. 자격증 취득만이 목적이라면 이해하기 어렵거나 궁금한 부분만 선택해 듣는 걸 추천한다.</p>
<p><strong><a href="https://explore.skillbuilder.aws/learn/courses/19790/exam-prep-official-practice-question-set-aws-certified-ai-practitioner-aif-c01-english">Exam Prep Official Practice Question Set</a>: AWS Certified AI Practitioner (AIF-C01 - English)</strong></p>
<p>AWS에서 제공하는 공식 연습 문제 20개이다. 다른 덤프를 풀다 보면 난이도가 높은 것들이 있는데, 실제 시험은 공식 문제와 비슷한 난이도였다.</p>
<p><strong><a href="https://www.examtopics.com/exams/amazon/aws-certified-ai-practitioner-aif-c01/view/">Examtopics</a> 연습 문제</strong></p>
<p>무료로는 처음 30문 제 만 이용 가능하다. 준비할 당시에는 유튜브에 전체 문제가 공개된 영상이 있어 해당 영상으로 공부했다. 유튜브에 “AI Practitioner Exam Questions” 키워드로 검색해 보기 바란다.</p>
<p>이외에도 Udemy 덤프 3-4개 정도를 더 공부했다. 덤프와 유사한 문제가 많았기에 기출문제 풀이를 추천한다.</p>
<h2 id="3-많이-등장하는-주제">3. 많이 등장하는 주제</h2>
<p>어떤 부분을 중점적으로 공부해야 할지 감이 잡히지 않는다면 시험 안내서의 시험 출제 범위를 확인해 보길 바란다. 필자도 시험을 준비할 때에는 너무 뻔한 얘기라 생각해 대충 읽고 넘어갔는데, 후기 글을 작성하며 다시 보니 기출문제에서 다루는 내용과 굉장히 유사했다.</p>
<p>AWS 서비스가 굉장히 방대한데 AI Practitioner 시험에서는 아래 3가지가 집중적으로 출제되었고, 나머지 AI/ML 관련 서비스들은 큰 특징만 알아도 충분했다.</p>
<ul>
<li>Amazon Bedrock</li>
<li>Amazon SageMaker</li>
<li>Amazon Q Developer/Business</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Transformer: Attention is all you need]]></title>
            <link>https://velog.io/@ny_/Transformer-Attention-is-all-you-need</link>
            <guid>https://velog.io/@ny_/Transformer-Attention-is-all-you-need</guid>
            <pubDate>Sun, 26 Jun 2022 16:13:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Transformer는 기존에 sequential 데이터를 처리하는 RNN 구조를 사용하지 않고, attention mechanism만 사용해 단어를 임베딩해 병렬처리를 가능하게 했다. </p>
</blockquote>
<h2 id="background">Background</h2>
<h3 id="seq2seq-model">Seq2Seq Model</h3>
<img src="https://velog.velcdn.com/images/ny_/post/b5142c0b-597f-430f-a3c4-b1bc053018d4/image.png" width="800">

<ul>
<li>Seq2Seq 모델은 encoder-decoder 구조로 이루어지며, 입력 문장을 읽는 RNN 모델을 <strong>Encoder</strong>, 출력 문장을 생성하는 RNN 모델을 <strong>Decoder</strong>라고 한다. 인코더끼리, 디코더끼리 동일한 파라미터를 공유하며 인코터와 디코더 간에는 파라미터를 공유하지 않는다. 위 그림에서는 RNN 모델로 LSTM을 사용했다.</li>
<li>인코더의 마지막 hidden state는 디코더의 첫 번째 hidden state 역할을 한다. 디코더는 시작을 의미하는 <strong><sos></strong> 토큰이 등장하면 인코더의 마지막 hidden state를 사용해 다음 단어를 예측하고, <strong><eos></strong> 토큰이 나올 때 까지 수행한다. <sos>, <eos> 토큰은 vocab에 미리 정의해 사용한다.</li>
</ul>
<p><strong>Seq2Seq 모델의 한계</strong></p>
<ul>
<li>Seq2Seq는 순차적으로 입력 sequence를 읽어 <strong>고정된 크기의 context vector</strong>(hidden state)에 입력 문장의 정보를 압축해 저장한다. RNN과 비교해 LSTM에서 long-term dependency를 개선했지만 여러 layer를 거치면 <strong>여전히 앞쪽에 등장한 정보는 손실될 수 있으며, 긴 문장 예측이 어려운 단점이 있다.</strong></li>
<li>앞쪽에 나타난 정보를 잃지 않기 위해 입력 sequence를 거꾸로 모델에 feed하는 테크닉도 제안되었지만, 근본적인 문제를 해결하지는 못했다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/0ee1360d-ec58-4b06-877e-7bc646556914/image.png" alt="">
context vector 값이 손실되지 않기 위해, decoder가 매번 context vector를 참고하도록 하는 방법이 제안되었다. 하지만 여전히 하나의 input sequence를 고정된 크기의 context vector로 압축시켜야 하기 때문에, 성능이 저하된다. </p>
<p>“Decoder 부분에서 context vector 정보를 가지고 있지 않고, encoder의 모든 출력을 매번 입력으로 받으면 어떨까?” 라는 관점에서 Seq2Seq with Attention이 제안되었다.</p>
<h3 id="seq2seq-model-with-attention">Seq2Seq Model with Attention</h3>
<img src="https://velog.velcdn.com/images/ny_/post/f519c104-4c86-4c61-b3a4-e1c0df17d2c9/image.png" width="600">

<p>  Decoder는 context vector 뿐만 아니라 encoder의 모든  를 전부 반영한 weighted sum vector $w$를 사용해 출력을 생성한다.</p>
<img src="https://velog.velcdn.com/images/ny_/post/38231d48-f6fa-4a48-885d-89bb0c01e38c/image.png" width="700">

<p>위 그림은 attention을 수행하는 과정으로 아래와 같은 과정으로 계산된다.
자세한 내용은 Attention이 제안된 논문인 Neural Machine Translation by Jointly Learning to Align and Translate에 나온다.</p>
<blockquote>
<p>$i$ : 디코더가 처리중인 인덱스
$j$ : 인코더의 출력 인덱스
$S_i$ : time step=i 에서 디코더의 hidden state</p>
</blockquote>
<p>1) 이전에 만든 디코더의 hidden state인 $S_{i-1}$과 인코더의 모든 출력(hidden state)을 사용해 에너지 $e_{ij}$를 계산한다. 즉, 디코더는 출력 단어를 만들 때마다 모든 인코더의 hidden state를 고려한다.
2) 에너지 값을 구한 후에, softmax를 취해 확률값을 구한다. 이 확률값은 각 hidden state에 부여하는 가중치로 사용된다.
3) 앞서 구한 에너지와 가중치를 사용해 각 hidden state에 weight만큼의 가중치를 부여한다.</p>
<h2 id="model-architecture">Model Architecture</h2>
<img src="https://velog.velcdn.com/images/ny_/post/75f96f24-3072-4cd1-84cb-5c4885fc62eb/image.png" width="500">

<p>Transformer는 auto-regressive한 구조인 RNN을 완전히 배제하고 stacked self-attention, position-wise fully connected layer로 구성된 구조이다. Auto-regressive(자기회귀)란 과거의 자기 자신을 사용해 현재의 자신을 예측하는 모델로 일반적으로 시계열, 텍스트 등 ‘시간종속성&#39;을 갖는 데이터에 많이 사용된다.</p>
<p>Seq2Seq처럼 encoder-decoder 구조로 구성되며 encoder는 입력 문장의 정보를 압축하는 역할, decoder는 압축된 정보를 사용해 매 timestep마다 출력 토큰을 하나씩 생성한다.</p>
<p><strong>Encoder</strong></p>
<ul>
<li>N=6개의 층으로 구성되며, 각 층은 2개의 sub-layer로 구성된다. 다시 각 sub-layer는  <strong>multi-head self-attention mechanism</strong>과 <strong>position-wise fully connected feed-forward network</strong>로 구성된다.</li>
<li>각 sub-layer에 입력을 더해줄 때 residual connection을 수행하며, 그 결과에 대해 layer normalization을 수행한다. Residual connection을 사용하기 위해 각 layer의 입출력 차원을 512로 동일하게 맞춘다. ($d_{model}=512$)</li>
<li>Residual Connection: ResNet에서 사용하는 기법. 특정 layer를 건너뛰어 입력값을 넣어 학습하는 방법으로, 이전 layer와의 차이점만 학습한다. 학습할 부분이 줄어들어 학습 난이도가 낮아짐에 따라 초기 수렵 속도가 높아지고, global optima를 찾을 확률이 높아진다. ⇒ 성능이 좋아지는 효과가 있다. (<a href="https://velog.io/@ny_/Transformer-preview-2">preview 2</a> 참고)</li>
</ul>
<p><strong>Decoder</strong></p>
<ul>
<li>encoder와 동일하게 N=6개의 층으로 구성되며, 각 층은 3개의 sub-layer로 구성된다. encoder와 거의 동일한 구조인데, 마지막 sub-layer만 추가되었다. 마지막 sub-layer는 encoder의 출력 결과와 decoder 간의 multi-head attention을 수행한다. 또한 attention을 수행할 때 미래 토큰은 사용할 수 없도록 masking처리를 한다.</li>
</ul>
<p><strong>Multi-Head Attention</strong></p>
<ul>
<li>모델의 핵심인 내용으로 <a href="https://velog.io/@ny_/Transformer-preview-1">preview 1</a>에 있다.</li>
</ul>
<p><strong>Positional Encoding</strong></p>
<ul>
<li>또한 Transformer는 RNN구조를 사용하지 않기 때문에, 위치 정보를 포함하는 임베딩을 만들 수 있도록 positional encoding을 사용했다. 관련 내용은 <a href="https://velog.io/@ny_/Transformer-preview-3">preview 3</a>에 있다.</li>
</ul>
<p><strong>Position-wise feed-forward network</strong></p>
<ul>
<li>비선형적인 요소를 더하기 위해 수행한 layer라고 볼 수 있다.</li>
</ul>
<h2 id="why-self-attention">Why Self-Attention</h2>
<p><img src="https://velog.velcdn.com/images/ny_/post/4a63083a-cb9b-4746-aca6-a0c94d41bbca/image.png" alt=""></p>
<blockquote>
<p>$n$ : the sequence length
$d$ : the dimension of representation
$k$ : the kernel size of convolutions
$r$ : the size of the neighborhood in restricted self-attention</p>
</blockquote>
<p>논문에서 Self-Attention의 장점으로 3가지를 제시했다.</p>
<ul>
<li>layer당 계산 복잡도 감소</li>
<li>병렬적으로 연산 가능</li>
<li>maximum path length 감소: 많은 sequence transduction task에서 긴 dependency를 학습하는 것은 어려운 task이다. input과 output간의 dependency가 짧아질수록 dependency를 학습하기 수월해진다.</li>
</ul>
<p><strong>RNN</strong>
<img src="https://velog.velcdn.com/images/ny_/post/d8eb3280-a03a-4112-99d4-bc093bb14c37/image.png" width="600"></p>
<p>RNN의 계산 복잡도</p>
<ul>
<li>$d$차원 hidden state vector를 구할 때는 $(d, d)$차원 $W_{hh}$와 $d$차원 $h_{t-1}$을 내적 연산하는데, 여기서 $d^2$만큼의 연산량이 발생한다. 이 연산을 매 time step마다 반복하므로 $O(n*d^2)$의 연산량을 가진다.</li>
<li>n은 time step의 개수, d는 hidden state vector의 차원에 해당(hyper parameter로 변경 가능)</li>
</ul>
<p><strong>Self-Attention</strong>
<img src="https://velog.velcdn.com/images/ny_/post/923c89d3-19b4-4f81-9a9f-d6975e69d4dc/image.png" width="600"></p>
<ul>
<li>Self-Attention에서 연산량이 가장 많은 항은 $Q<em>K^T$이다. $(n, d)$차원의 Query vector와 $(d, n)$차원의 $K^T$ vector의 내적 연산은 $d$차원의 계산을 모든 (query-key)조합에 대해 수행한다. → $O(n^2 * d)$ → GPU core 수가 충분하다면 *</em>행렬 연산의 병렬화**를 사용하면 연산하는데 $O(1)$시간이 소요된다.</li>
<li>n은 입력 데이터의 길이로 임의로 조절할 수 없다. 동일한 길이의 sequence를 사용했을 때 RNN보다 메모리 요구량이 더 크다.</li>
<li>Self-Attention은 RNN보다 학습속도는 빠르지만 메모리 요구량은 더 크다. RNN은 hidden state를 순차적으로 계산하기 때문에 병렬화가 불가능하다.</li>
<li>표에서 마지막 컬럼의 <strong>Maximum Path Length는 long-term dependency와 관련</strong>되는데, RNN에서는 첫번째 단어가 마지막 단어를 참조하기 위해서는 n번의(모든) RNN layer를 통과해야 하기 때문에 O(n)이다. 반면에 self-attention은 time step과 상관없이 한번에 유사도 정보를 얻을 수 있다.</li>
</ul>
<h2 id="training">Training</h2>
<ul>
<li>dataset: WMT 2014 English-German dataset</li>
<li>encoding: byte-pair encoding(BPE)</li>
<li>optimizer: Adam 사용, lr값을 고정하지 않고 warmup_steps까지는 lr을 선형적으로 증가시키고, warmup_steps 이후에는 step_num의 에 비례하도록 감소시킨다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/bbbc6f29-f747-4bc1-b3f4-f9d97c91bce9/image.png" alt=""></p>
<ul>
<li>Regularization<ul>
<li>Residual Dropout: 각 sub-layer와 positional encoding에 dropout을 적용했고, base 모델 기준 dropout ratio=0.1을 사용했다.</li>
<li>Label Smoothing<ul>
<li>말 그대로 label값을 스무딩해주는 방법으로, 기존 정답이 [1, 0, 0] 이었다면 [0.95, 0.025, 0.025]로 label을 변경한다. label smoothing을 적용하면 정답이 뽑힐 확률이 낮아져 정답이라는 확신을 줄여준다.</li>
<li>적용 결과 perplexity 성능은 안 좋아졌지만, BLEU score는 증가했다. BLEU score는 정답이 있는지 없는지만 판단하기 때문에 score가 올라갔다고 볼 수 있다.</li>
<li>또한 perplexity는 번역 task의 성능 지표로는 적합하지 않다는 의견(?)이 있어서 “label smoothing이 성능 향상의 효과가 있다” 정도만 짚고 넘어가고자 한다. 왜 label smoothing이 잘 되는지는 <a href="https://arxiv.org/pdf/1906.02629.pdf">이 논문</a>에 나와있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="results">Results</h2>
<p><img src="https://velog.velcdn.com/images/ny_/post/d8c996fe-6199-437b-a77d-9ceed7eff859/image.png" alt="">
위의 표를 통해 설정한 파라미터 값에 따라 모델의 성능이 달라진 것을 확인할 수 있다. 가장 성능이 좋았던 파라미터를 살펴보면 다음과 같다.</p>
<p>(A): 전체 computation constant는 고정시키고 head 수만 증가시키면 성능이 떨어진다. 
(B): attention key size인 $d_k$를 줄이는 것은 모델 성능을 하락시킨다.
(C): 큰 모델일수록 성능이 좋다.
(D): dropout은 성능 향상에 효과적이다.
(E): sinusoidal positional encoding과 learned positional embeddings은 비슷한 성능을 보였다. sinusoidal positional encoding은 학습 시간이 짧은 장점이 있다.</p>
<h2 id="후기">후기</h2>
<p>Transformer는 NLP 뿐만 아니라 다양한 SOTA 모델의 뼈대가 되는 모델인데, 이런 논문을 읽었다는 점에서 아주 뜻깊었다. 아마 다시 읽을 논문 1순위가 아닐까 싶다.</p>
<p>이전에 네이버 부스트캠프에서 강의를 들을 때는 Self-Attention에만 집중했다면, 이번에는 전반적인 논문의 흐름과 학습에 사용한 방법에 좀 더 집중했다. 논문에 소개된 방법 중에 시간이 지나면서 더 효율적이 방법이 등장해서 사용되지 않는 방법도 있어서 다음 리뷰에서는 Transformer 코드를 보면서 이런 부분을 더 공부해 봐야겠다. </p>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://arxiv.org/abs/1706.03762">논문</a></li>
<li><a href="https://www.youtube.com/watch?v=AA621UofTUA">나동빈 유튜브</a></li>
<li><a href="https://wikidocs.net/31379">위키독스</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 프로젝트 회고]]></title>
            <link>https://velog.io/@ny_/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ny_/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 17 Jun 2022 18:11:23 GMT</pubDate>
            <description><![CDATA[<h1 id="1-프로젝트">1. 프로젝트</h1>
<p>지난주에 발표 영상과 발표 자료를 제출하고, 최종 프로젝트가 끝났다!!!!</p>
<p>우리 팀 주제는 “회의록을 활용한 질의응답(Question Answering)”으로 사용자가 회의록을 업로드하고, 궁금한 점을 질문하면, 답변해주는 서비스이다. </p>
<p>네이버에서 제공하는 <a href="https://clovanote.naver.com/home">클로바노트</a>는 음성 기록 관리 서비스로, 모든 것을 받아적기 어려운 회의 내용을 저장하고 수월하게 복기할 수 있도록 도와준다. &quot;이렇게 저장된 회의 데이터를 활용하는 서비스를 만들 수 있지 않을까?&quot; 하는 생각으로부터 프로젝트를 시작했다.</p>
<p>초반에 브레인스토밍 했던 주제는 상품 이미지를 넣으면 마케팅 메시지를 생성해주는 것이었는데 상품 이미지-마케팅 메시지로 쌍을 이루는 데이터셋을 찾기 어려웠고, 마케팅 메시지의 종류가 우리가 생각한 텍스트와 달라서 막판에 주제를 완전 엎었다. </p>
<p>막판에 주제를 바꾸면서 실질적으로 프로젝트를 진행할 수 있는 시간은 3주였고 데이터, 모델, 서빙에 각각 1주일을 투자했고, 마지막 1주 동안에는 데모에서 발생한 에러들을 해결하고 멘토님의 피드백을 반영했다. </p>
<blockquote>
<p>프로젝트 정리 링크</p>
</blockquote>
<ul>
<li><a href="https://www.notion.so/Final-Project-Wrap-up-report-82a011918d6c4f9eb246e77a0a96906c">보고서</a></li>
<li><a href="https://github.com/HanNayeoniee/final-project">Github</a></li>
<li><a href="https://www.youtube.com/watch?v=LoT7wuRPSHc">발표 영상</a></li>
</ul>
<h1 id="2-마주한-어려움">2. 마주한 어려움</h1>
<h2 id="21-한글-회의-데이터셋의-부재">2.1 한글 회의 데이터셋의 부재</h2>
<p>데이터셋을 구하기 어려워 주제를 변경했기 때문에, 기존에 존재하는 데이터셋을 최대한 활용하고자 했다. 우리가 찾고자 한 것은 화자별로 발언이 분류된 일상적인 회의 대화 데이터였다. </p>
<p><strong>1) 영어 데이터셋 활용</strong>
회의 종류별로 회의 내용과 요약이 담긴 <a href="https://arxiv.org/abs/2104.05938">QMSum</a> 데이터셋이 존재했지만, 번역기를 사용해 한국어로 번역했을 때 조금씩 느낌이 달라서 정말 아쉽지만 영어 데이터셋은 사용할 수 없없다.</p>
<p><strong>2) 직접 수집하기</strong></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/18b59d7f-4966-4f11-b046-312f3e280ab6/image.png" alt=""></p>
<p>네이버 클로바노트로부터 아이디어를 얻었기 때문에, 데이터 수집에 클로바노트 활용을 시도했다. 매일 진행하는 데일리 스크럼 회의를 클로바노트로 녹음해 보았는데, 아래와 같이 각 화자별로 발언이 짧게 끊기는 모습이었다. 회의마다 각 문장의 길이가 달라지겠지만, 이렇게 짧은 문장에서는 정보를 추출하기에 어려움이 있다고 판단했다. 문장의 길이 뿐만 아니라, 클로바노트로 무료 버전 사용량 제한으로 인한 어려움도 있었다.</p>
<p><strong>3) 기존 데이터셋 활용</strong>
클로바노트를 사용해본 후 데이터를 직접 수집하기에는 어려움이 있고, 시간이 오래 걸릴 것 같아 기존 데이터셋을 정제해 활용하는 방안을 모색했다. <a href="https://dacon.io/competitions/official/235813/overview/description">데이콘의 AI 기반 회의 녹취록 요약 경진대회 데이터셋</a>은 문서화된 회의 녹취록에서 핵심 내용을 생성 요약하는 AI 모델 개발을 위한 데이터셋이다. 의회 회의 내용으로 구성되어 안건별, 화자별로 발언이 나뉘어 있다. </p>
<p><img src="https://velog.velcdn.com/images/ny_/post/b70d8ced-e5c0-4a4f-86e0-170c71ea3ed8/image.png" alt=""></p>
<p>의회 회의록이기 때문에 일반 회사의 회의에서 사용하는 어휘와 다른 문제점이 있었다. 의회 회의 데이터 중 실제 회의에 대응될 수도 있는 범용적인 질문을 유형화해 7가지 유형의 질문으로 구성된 QA 데이터셋을 제작했다.</p>
<h2 id="22-그렇게-쓰는거-아니에요">2.2 그렇게 쓰는거 아니에요...</h2>
<p>항상 주피터 노트북에서 모델을 학습시킨 후 성능 평가까지만 했었기 때문에 모델이 완성되면 데모도 금방 완성할 수 있다고 생각했다. 하지만 내가 예상한 순서대로 데모를 사용하지 않는 경우가 많아 내가 원하는 순서대로 사용자가 서비스를 사용하도록 유도하고 예외 처리하는데 시간을 쏟았다. </p>
<blockquote>
<p>회의록 QA를 사용하기 위해서는 아래와 같은 과정이 필요하다. </p>
</blockquote>
<p>1) 사용자 정보 입력
2) 회의록 업로드
3) QA 시작</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/1f9a6dc7-aa16-4c66-83f7-2daec9742be3/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/8f723faf-56e9-47e6-8783-6c891ee81a29/image.png" alt=""></p>
<p>모델 개발 시에는 1, 2 단계는 완료되었다고 가정하고 3번을 바로 수행하기 때문에 데모를 만들 때 1, 2 단계를 고려해야 했다. 프로젝트의 와이어프레임은 아래 사진과 같은데 1, 2 단계를 수행하지 않고 3단계로 넘어가는 경우를 방지하고, 회의록이 변경되면 회의록 목록이 업데이트 되도록 했다.</p>
<h1 id="3-아쉬운-점">3. 아쉬운 점</h1>
<h2 id="31-새로운-모델-시도">3.1 새로운 모델 시도</h2>
<p>이전 MRC 대회와 유사한 task이기 때문에 기존에 사용하던 Reader, Retriever 모델에 큰 변화를 주지 않고 달라진 데이터셋에 대해 파라미터 튜닝만 했다.</p>
<p>Reader 모델에는 HuggingFace에서 제공하는 <a href="https://huggingface.co/docs/transformers/model_doc/auto#transformers.AutoModelForQuestionAnswering">AutoModelForQuestionAnswering</a>을 사용했다. KLUE 데이터셋으로 pre-trained된 모델을 구축한 QA 데이터셋으로 fine-tuning했다. </p>
<p>Retriever 모델에는 Elasticsearch 검색엔진을 사용했고, 새로운 데이터셋에 최적화된 파라미터를 찾는 실험을 진행했다. Elasticsearch는 키워드 중심으로 인덱싱해 검색을 수행하기 때문에, 키워드 검색이 아닌 케이스도 대응할 수 있도록 ColBERT와 같은 dense embedding을 시도해보고 싶다. </p>
<h2 id="32-회의록은-qa가-아니라-요약이다">3.2 회의록은 QA가 아니라 요약이다</h2>
<p>회의록 QA라는 주제로 프로젝트를 진행하면서 “회의를 요약해주는 기능도 있으면 좋겠다“ 라는 생각을 했지만, 부가 기능을 추가하기 보다는 기존에 정한 주제에 집중하고 모델의 성능을 높이고자 했다. </p>
<p>하지만, 회의록에서 궁금한 것들을 질문하는 QA의 목적은 결국 회의에서 어떤 내용을 주고받았는지 알기 위해서이다. 사용한 데이터셋이 회의록 <strong>요약</strong> 데이터셋인 이유를 프로젝트가 끝나고 나서야 깨달았다.</p>
<h2 id="33-배포">3.3 배포</h2>
<p>streamlit을 사용해 데모를 구현하면 streamlit cloud를 사용하면 배포를 빠르게 진행할 수 있다. 마지막날 시도했지만 UI랑 Reader 부분은 성공했지만 Elasticsearch 서버를 배포하지 못해 실패했다. 이번 프로젝트는 streamlit으로 구현해서 CI/CD 부분까지 필요하지는 않았지만, 좀 더 효율적으로 모델을 배포하는 방법에 대해 공부해야겠다.</p>
<h1 id="4-느낀점">4. 느낀점</h1>
<p>이번 프로젝트는 데이터-모델-서빙 모든 과정을 시간에 쫓기면서 진행했다는 느낌을 강하게 받았다. 시간에 쫓겨 진행하느라 모든 과정에서 조금씩 아쉬운 점이 있었지만, 선택과 집중을 통해(챙길건 챙기고, 버릴건 버려서) 기한 내에 완성할 수 있었다고 생각한다. </p>
<p>주제를 변경하게 되어 프로젝트를 진행할 시간이 짧았지만 탄력적으로 모든 과정을 함께 진행하고, 마지막까지 에러 수정하고, 발표 영상을 보완했던 팀원들에게 정말 감사하다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/588d9c1c-d83d-4c8a-908f-9b1c116d7047/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Efficient Estimation of Word Representations in
Vector Space 하편]]></title>
            <link>https://velog.io/@ny_/Efficient-Estimation-of-Word-Representations-inVector-Space</link>
            <guid>https://velog.io/@ny_/Efficient-Estimation-of-Word-Representations-inVector-Space</guid>
            <pubDate>Wed, 01 Jun 2022 07:34:29 GMT</pubDate>
            <description><![CDATA[<h1 id="3-new-log-linear-models">3. New Log-linear Models</h1>
<ul>
<li>이전에 성능이 좋았던 NNLM을 대용량 데이터셋 학습에 사용하기 위해 시키기 위해서는 연산량을 많이 줄인 distributed representation 모델 2가지 CBOW, Skip-gram 제안한다.</li>
<li>NNLM에서의 projection layer는 단순히 embedding vector를 concat한 결과이기 때문에 단어간의 연관성 정보는 없고, <strong>hidden layer를 거치면서 단어간의 연관성을 학습한다.</strong></li>
<li>하지만 가장 많은 연산량이 발생했던 non-linear hidden layer를 제거했기 때문에 projection layer가 단어간의 연관성 정보도 가져야 한다.</li>
</ul>
<h2 id="31-continuous-bag-of-words-modelcbow">3.1 Continuous Bag-of-Words Model(CBOW)</h2>
<p><img src="https://velog.velcdn.com/images/ny_/post/730c6359-ef05-42e5-90a2-2eff29cce946/image.png" alt=""></p>
<ul>
<li><p>주변 단어로 중심 단어 예측</p>
</li>
<li><p>NNLM과 비슷하지만 non-linear hidden layer는 없고 projection layer만 존재하며 모든 단어들과 공유된다.</p>
</li>
<li><p>$Q = N * D + D * log_2(V)$</p>
</li>
<li><p>전체 단어의 one-hot vector에 가중치 행렬 W를 곱하고, 그 결과값을 모두 모아 평균을 구하면 Projection Layer를 만들 수 있다. 단어의 순서가 Projection에 영향을 주지 않는다.</p>
</li>
</ul>
<h2 id="32-continuous-skip-gram-modelskip-gram">3.2 Continuous Skip-gram Model(Skip-gram)</h2>
<ul>
<li><p>중심 단어로 주변 단어를 예측</p>
</li>
<li><p>input vector → projection vector를 거친 후에 여러 개의 가중치 행렬을 만들어 여러 개의 output vector를 만드는 것으로 이해했다.</p>
</li>
<li><p>$Q = C * (D + D * log_2(V))$</p>
</li>
<li><p>빨간색 박스는 CBOW에서 N=1일 때의 수식과 동일</p>
</li>
<li><p>C: maximum distance of the words</p>
</li>
<li><p>주변 C개의 단어를 예측할 때 주변 단어 범위를 늘리면 word vector의 quality가 증가하고 계산 복잡도도 증가한다. (예측하는 단어 수가 늘어나기 때문) 또한, 중심 단어에서 멀리있는 단어는 의미적 유사성이 작기 때문에, 멀리 있는 단어는 가중치를 작게 부여했다.</p>
</li>
<li><p><strong>C를 결정한 후에 [1, C) 범위에서 R을 랜덤하게 뽑아 이전 R개, 이후 R개 단어를 예측한다. R을 뽑을 확률은 $\frac{C}{2}$이기 때문에 $\frac{C}{2} * 2 = C$ , 기대값은 C번 수행된다. C개 단어에 대해 진행하기 때문.</strong></p>
</li>
</ul>
<h1 id="4-results">4. Results</h1>
<p><img src="https://velog.velcdn.com/images/ny_/post/1329508e-fa08-4525-ad86-c6f76dfcbcce/image.png" alt=""></p>
<p>word embedding vector의 syntax, semantic 성능을 측정할 수 있는 새로운 Test set을 제시했다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/8ef53664-51de-420e-bf80-48e0abf57f04/image.png" alt=""></p>
<ul>
<li>데이터셋과 word vector 차원을 동시에 늘렸을 때 성능이 향상되었다.</li>
<li>증가한 데이터양을 수용할만한 차원이 필요하다(하나만 늘렸을 때는 성능이 내려가는 경우도 있음)</li>
<li>논문이 나올 당시에는 데이터셋은 늘려도 벡터 차원을 늘리는 아이디어는 사용하지 않아 새로운 실험이었다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/a4110db5-505d-4627-89ec-c42f41ea6eba/image.png" alt=""></p>
<ul>
<li>CBOW의 syntatic accuracy가 높은 이유: 문법이 동일한 것은 한 문장에서 볼 수 없기 때문에 skip-gram이 더 성능이 낮을 것이다.</li>
<li>Skip-gram의 semantic accuracy가 높은 이유: 한 단어를 중심으로 문장 안의 모든 단어를 예측해 단어들간의 연관성을 학습하지 않을까?</li>
<li>NNLM보다 RNNLM의 성능이 떨어지는 이유: RNNLM의 vector들은 projection layer와 같은 중간 단계없이 non-linear hidden layer에 연결되기 때문이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/60e42dbb-ccac-4765-9244-52dc52bbe4d3/image.png" alt="">
훈련 에폭수를 늘리는 것보다 데이터 크기를 늘리는 것이 성능 향상에 더 좋다.</p>
<h2 id="의문점">의문점</h2>
<ul>
<li>허프만 코딩: 이진 트리이지만, 높은 확률로 balanced 이진트리가 아님. 자주 등장하는 단어는 비트수를 짧게, 자주 등장하지 않는 비트수는 길게 할당한다. → 허프만 이진 트리를 사용한다고 해서 log_2(v)를 보장할 수 있나? → log_2(v)를 보장하도록 앞뒤단어를 맞춰 허프만 이진 트리를 만들지 않았을까?</li>
<li>one-hot vector임을 미리 알고 계산하면 lookup table처럼 계산할 수 있지만, 컴퓨터가 미리 알고있지 않는다면 일단 행렬을 다 곱하니까 계산복잡도가 D로 안 줄어들지 않나? → 학습할 때 참고하는 파라미터 기준으로 세면 이해될수도</li>
</ul>
<h2 id="소감">소감</h2>
<p>분명 word2vec 논문인데 NNLM을 공부하는데 더 많은 시간을 쏟았다. 배경 지식이 거의 없어서 많이 검색하면서 읽었지만, 다음 논문을 읽을 때 도움이 되지 않을까 생각한다.</p>
<p>사실 라이브러리 가져다 사용하는 경우가 많아서 임베딩 전후만 확인했었는데 이번 논문을 읽고 내가 얼마나 두루뭉술하게 알고 있었는지 확인할 수 있었다. 
어떤 배경으로 제안된 알고리즘인지 알고나니 좀 더 저자의 마음으로 읽을 수 있었고 딥러닝 모델을 더 크게 만들어 성능을 향상시키는 최근 논문과 달라 새로웠다. 논문에서 모델을 학습시킬 때 cpu를 사용했는데 얼마나 오래 걸렸을지 생각만해도 아찔하다. 그 장비로 연구한 분들이 존경스러울 따름이다..!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Efficient Estimation of Word Representations in
Vector Space 상편]]></title>
            <link>https://velog.io/@ny_/Class-Based-n-gram-Models-of-Natural-Language</link>
            <guid>https://velog.io/@ny_/Class-Based-n-gram-Models-of-Natural-Language</guid>
            <pubDate>Wed, 01 Jun 2022 07:33:02 GMT</pubDate>
            <description><![CDATA[<h1 id="0-word2vec-요약">0. Word2Vec 요약</h1>
<ul>
<li><p><strong>“같은 문장에서 나타난 단어들은 의미가 유사할 것이다.”</strong>를 가정으로 제안된 알고리즘</p>
</li>
<li><p><strong>NNLM의 느린 학습 속도와 정확도를 개선</strong>한 것으로 NNLM은 이전에 등장한 단어들만 참고하지만, word2vec은 전후 단어 모두 참고한다.</p>
</li>
<li><p>CBOW: 주변 단어들을 입력으로 받아 중간에 위치한 단어를 예측</p>
</li>
<li><p>Skip-gram: 중간에 있는 단어로 주변 단어들을 예측</p>
<p>  ⇒ 둘 다 가중치 행렬을 2번 곱한 후, projection layer, output layer를 거치기 때문에 유사한 매커니즘이다.</p>
</li>
<li><p>본 논문은 대용량 데이터셋으로부터 continuous vector representation을 구하는 방법 2가지(CBOW, skip-gram) 방법을 제안했으며, 더 적은 연산량으로 더 높은 성능을 달성했다.</p>
</li>
</ul>
<h1 id="1-introduction">1. Introduction</h1>
<ul>
<li>이전까지는 n-gram, BoW(bag of words)처럼 one-hot vector를 사용해 단어를 표현했다. 하지만 이러한 방식을 사용하면 <strong>모든 단어간의 거리는 $\sqrt2$, 코사인 유사도는 0으로</strong> 단순히 인덱스의 나열이기 때문에 단어들 간의 유사성(연관성)을 학습하지 못한다.</li>
<li><strong>많은 데이터셋을 사용한 간단한 모델의 성능이 적은 데이터셋을 사용한 복잡한 모델의 성능보다 높기 때문에</strong> 이전까지는 one-hot vector를 많이 사용했다. 또한 통계 기반 방식에서는 n-gram이 더 효율적이다. 하지만 기계학습 기반 방식으로 바뀌면서 복잡한 모델에 많은 데이터셋을 활용하기 위해 벡터 형식으로 단어를 표현하는 distributed representation 방법을 제안한다. <strong>단어의 의미를 여러 차원에 분산해 표현한다.</strong></li>
</ul>
<h2 id="11-goals-of-the-paper">1.1 Goals of the Paper</h2>
<ul>
<li>본 논문에서는 대량의 데이터셋으로부터 높은 품질의(high-quality) word vector를 학습하는 방법을 제안한다. 단어가 의미적 유사성 뿐만 아니라, <strong>multiple degrees of similarity</strong>를 학습할 수 있다. 또한 임베딩 벡터를 더하고 빼는 연산을 통해 다른 단어를 도출할 수 있다. ex) $vector(”King”) - vector(”Man”) + vector(”Woman”) = Queen$</li>
<li>syntatic and semantic regularities를 모두 측정하기 위해 새로운 test set을 구축했고 사용되는 단어 벡터의 차원에 따라 학습 시간과 정확도가 달라지는 것 또한 확인했다.</li>
</ul>
<p><strong>multiple degrees of similarity</strong></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/1a7d0d9d-b893-40c5-9746-388053cce6e5/image.png" alt=""></p>
<blockquote>
<p>reference 표시된 <a href="https://aclanthology.org/N13-1090.pdf">논문</a>의 예</p>
</blockquote>
<ul>
<li>같은 noun이어도 형태의 차이(e.g단수/복수)를 가져도 비슷한 표현으로 볼 수 있는 것 
e.g, apple, apples</li>
<li>한 개의 단어가 여러개의 비슷한 성격을 가지는 단어와도 연결될 수 있는 것(e.g, 성별, 직위) → 왼쪽 그림은 각 단어가 1:1매핑(man → woman, king → queen), <strong>반면 오른쪽 그림은 1개의 단어가 여러개와 연결(king → kings &amp; king → queen)</strong></li>
<li>한개의 단어가 여러개의 비슷한 의미 특성을 가진 단어와도 연결될 수 있는 의미. big-bigger-biggest</li>
</ul>
<h2 id="12-previous-work">1.2 Previous Work</h2>
<h3 id="n-gram">n-gram</h3>
<ul>
<li>언어 모델링(Language Modeling)은 문장에 확률을 할당하는 것으로, 이전 단어들로부터 다음 단어를 예측한다.</li>
<li>n-gram 모델은 앞 (n-1)개의 단어를 참고해 다음 단어를 예측한다. 하지만, 이러한 n-gram 언어 모델은 충분한 데이터를 보지 못하면 정확히 모델링하지 못하는 <strong>희소 문제(sparsity problem)</strong>가 있다.</li>
<li>훈련 코퍼스에 ‘boy is spreading smile.’이라는 문장이 있으면 P(smiles | boy is spreading)는 확률을 가지지만, 해당 문장이 없으면 현실적으로는 존재할 수 있는 문장이지만 확률은 0이 된다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/5e69066c-1b19-4ee6-9e53-f078b47bf0e1/image.png" alt=""></p>
<ul>
<li>‘발표 자료를 살펴보다&#39;라는 시퀀스는 존재하지만 ‘발표 자료를 톺아보다’라는 시퀀스가 존재하지 않는 코퍼스로 학습한 모델: 위의 두 경우 중 ‘톺아보다&#39;를 선택해야 하지만, ‘톺아보다&#39;가 코퍼스에 없기 때문에 모델은 P(톺아보다|발표 자료를) 확률을 0으로 계산한다. → <strong>훈련 코퍼스에 없는 단어는 예측하지 못한다.</strong></li>
<li>또한, 앞에서 단어 몇개를 볼 지 n을 정할 때 trade-off가 존재한다. n이 크면 더 긴 단어 시퀀스를 보고 예측해 정확해지지만, 해당 시퀀스를 코퍼스에서 count하기 어려워진다.</li>
<li><strong>언어 모델이 단어의 의미적 유사성을 학습할 수 있다면, 훈련 코퍼스에 없는 단어 시퀀스에 대한 예측도 가능할 것이다.</strong> 이러한 아이디어가 반영된 모델이 NNLM, word embedding이다.</li>
</ul>
<h3 id="sparse-representation">Sparse representation</h3>
<ul>
<li>단어를 컴퓨터에게 가르치려면 컴퓨터가 읽을 수 있는 형태로 변환해야 한다. 그 방법 중 하나가 one-hot encoding</li>
<li>[코끼리, 사자, 뱀] 3개의 단어로 이루어진 vocab을 one-hot encoding을 사용해 각 단어를 one-hot vector로 표현하면 아래와 같다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/69d3299c-6fb4-4338-be84-dab23f1a7948/image.png" alt=""></p>
<ul>
<li>one-hot vector는 간단하고 직관적인 표현 방법이지만 vocab이 커질수록 차원수도 증가해 계산복잡성이 늘어나고, <strong>자기 자신만 1이고 나머지 요소는 0의 값을 가지는 sparse vector 형태</strong>를 갖는다.</li>
<li>코끼리와 사자 one-hot vector를 내적하면 내적값은 0으로 두 벡터가 서로 직교해 one-hot vector로 표현된 모든 단어가 독립적이라는 의미지만, 현실에서 단어들 사이에는 관련성이 있으며 유사어/반의어 관계가 있다.</li>
<li>이러한 문제를 해결한 것이 distributed representation이다.</li>
</ul>
<h1 id="2-model-architectures">2. Model Architectures</h1>
<h2 id="21-nnlm">2.1 NNLM</h2>
<ul>
<li>다음 단어를 예측할 때 앞에 등장한 모든 단어를 참고하지 않고, n-gram처럼 정해진 n개의 단어만 참고한다. NNLM에서는 참고하는 단어의 개수(범위)를 window라고 한다.</li>
<li>예시 - 아래의 훈련 코퍼스에서 <strong>“sit”</strong>을 예측 하는 경우
<img src="https://velog.velcdn.com/images/ny_/post/e5d09949-d37e-4fa8-a891-1e7eea5de40c/image.png" alt=""></li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/9a9a7252-6b1d-4e47-b7b9-919e572855b9/image.png" alt=""></p>
<ul>
<li>위의 그림과 같이 NNLM은 4개의 layer로 이루어진다(input, projection, hidden, output layer)</li>
<li>입력 단어를 <strong>one-hot vector</strong>로 인코딩한다. 전체 vocab에는 7개의 단어가 있으므로 각 단어는 <strong>7차원의 벡터</strong>로 표현된다. 위의 예시는 window=4이므로 <strong>“sit”</strong>을 예측할 때 4개의 단어 <strong>“will the fat cat”</strong>만 참고한다.</li>
<li>input layer는 단어 4개의 one-hot vector, output layer는 예측해야하는 단어 “sit”의 one-hot vector이다. output layer의 vector는 모델이 예측한 값의 오차를 구하기 위한 레이블로 사용되고, 인공 신경망은 오차로부터 손실 함수를 사용해 학습한다.</li>
<li>NNLM은 input layer를 거쳐 projection layer를 거치는데, 가중치 행렬과 곱셈 연산은 있지만 일반 은닉층과는 달리 <strong>활성화 함수가 존재하지 않는다.</strong></li>
</ul>
<p><strong>projection layer</strong></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/62e0132f-ea12-4e2b-bc36-8740e338701c/image.png" alt=""></p>
<ul>
<li>Projection layer에서는 V차원 input vector $x$에 크기가 $V<em>M$인 가중치행렬 W를 곱해 $*</em>1<em>M$차원의 embedding vector*</em>를 얻는다. 위 그림에서 input vector $x_{fat}$은 7차원 one-hot vector로 7x5 가중치 행렬 W와 행렬곱을 통해 5차원 embedding vector $e_{fat}$을 얻는다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/66b20cad-ca72-4036-b6d4-bad0000150fa/image.png" alt=""></p>
<ul>
<li>projection layer 안에서 이루어지는 연산을 살펴보면 위의 그림과 같으며, 해당 layer를 거치면 0이었던 요소들이 값으로 채워져 <strong>dense vector</strong>가 된다.</li>
<li>one-hot vector는 i번째 인덱스 값만 1이기 때문에 i번째 행을 그대로 읽어오는 것과 동일해 이 과정을 <strong>lookup</strong>이라 하고, 수행 결과 얻은 벡터를 <strong>lookup table</strong>이라고 한다.</li>
<li>각 단어는 lookup table을 통해 임베딩 벡터(가운데 노란색)로 변환되고, 4개의 임베딩 벡터를 concat해 하나의 벡터로 연결한다. 5차원의 임베딩 벡터 4개를 연결한 20차원의 벡터를 얻는다.</li>
<li>이렇게 단순히 embedding vector를 concat한 것은 단어간 연관성이 없으며, hidden layer에서 단어간의 연관성을 학습한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ny_/post/f351f934-4a8e-4b85-a32f-44c8bb7f27f9/image.png" alt=""></p>
<p>t번째 단어를 예측할 때 n=window size, 세미콜론(;)=concat 기호라고 하면 projection layer를 위와 같은 식으로 표현할 수 있다.</p>
<p><strong>hidden layer</strong></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/f0f92ce1-87e0-493f-b31f-11940abf3c86/image.png" alt=""></p>
<ul>
<li>은닉층 = 활성화 함수(입력 * 가중치 + 편향) 을 의미한다. 가중치와 편향을 각각 $W_h$, $b_h$라고 표현하고 tanh 활성화 함수를 사용하면 은닉층은 위와 같은 식으로 표현할 수 있다.</li>
<li>linear 연산 후 tanh함수를 거치기 때문에 nonlinear한 출력값을 가진다.</li>
</ul>
<p><strong>output layer</strong></p>
<p><img src="https://velog.velcdn.com/images/ny_/post/624aeafe-b87d-4171-90d3-f95e19f31f74/image.png" alt=""></p>
<p>hidden layer를 거친 벡터는 output layer에서 다른 가중치 $W_y$와 곱해지고 편향 $b_y$가 더해져 입력과 동일한 V차원의 벡터를 얻는다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/61f172f5-efca-4b56-844c-dc98d78eaefc/image.png" alt=""></p>
<p>output layer에는 활성화 함수로 softmax를 사용해 벡터의 각 원소는 0-1사이 값을, 총 합은 1이 되는 상태로 바뀐다.</p>
<p>NNLM이 예측한 벡터 y_hat은 다음 단어로 각 인덱스가 올 확률을 의미한다. 예측 벡터 y_hat이 정답 벡터 y에 가까워지게 하기 위해 <strong>cross-entropy 손실 함수</strong>를 사용한다. V개의 단어 중 정답인 “sit”을 예측할 수 있도록 <strong>다중 클래스 분류 문제</strong>이다. 역전파가 이루어지면 모든 가중치 행렬들이 학습되는데, projection layer의 가중치 행렬도 포함되므로 embedding vector 값도 학습된다.</p>
<p><strong>training complexity 계산 공식</strong></p>
<p>$O = E * T * Q$</p>
<blockquote>
</blockquote>
<ul>
<li>E: epoch</li>
<li>T: training set의 단어 개수</li>
<li>Q: model architecture에서 정의됨</li>
</ul>
<p><strong>computational complexity</strong></p>
<p>$(1, V) * (V, D) = (1, D) → (N, D)$
N개의 입력(이전) 단어가 주어졌을 때, 각 단어는 (1, V) one-hot vector로 표현되며 (V, D) 가중치 행렬과 연산해 (1, D)차원의 embedding vector로 변환된다. 총 N개 단어의 결과를 concat하면 (N, D) 크기의 벡터가 된다. </p>
<p>$Q = N * D + N<em>D</em>H + H<em>V$
계산 복잡도는 위의 식처럼 표현할 수 있는데, 각 항은 input → projection, projection → hidden, hidden → output layer로의 계산 복잡도이다. 가장 연산량이 많은 항은 마지막 $H</em>V$항이지만, softmax 대신 hierarchical softmax를 사용하면 $H<em>log_2(V)$로 연산량을 줄일 수 있다. → $N</em>D*H$ 항이 연산량에 가장 영향을 많이 준다.</p>
<h2 id="hierarchical-softmax">Hierarchical Softmax</h2>
<p><img src="https://velog.velcdn.com/images/ny_/post/d7b86bf6-dabb-4a34-bb29-0fb1326d5d01/image.png" alt=""></p>
<ul>
<li>이전까지 사용했던 softmax는 1층으로 구성되어 다음 단어의 확률을 구할 때 노드 $V$개의 확률값을 계산해야하지만, hierarchical softmax는 허프만 코딩을 사용해 $log_2(V)$개의 확률값만 계산하면 된다.</li>
<li>여기서 허프만 코딩은 <strong>이진 트리</strong>를 사용해 단어 등장 빈도수에 따라 다른 길이의 코드를 부여하는 압축방식(?) 이라고 생각할 수 있다.</li>
<li>위의 그림에서 왼쪽은 일반 softmax, 오른쪽은 hierarchical softmax를 나타낸 모습이다. 다음 단어 <strong>&quot;I&#39;m&quot;</strong>이 올 확률을 구할 때 softmax 방식에서는 모든 단어 8개의 확률을 구해야 하지만, hierarchical softmax을 사용하면 root node부터 &quot;I&#39;m&quot; leaf node까지의 경로에 위치만 3개 단어에 대한 확률만 필요하다.</li>
<li>V=8 일 때, 계산 복잡도가 $V$ -&gt; $log_2(V)$로 감소한 것을 확인할 수 있다.</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>train data가 충분하다면 유사한 목적으로 사용된(비슷한 의미로 사용된??) 벡터는 유사한 임베딩 값을 가진다. → train corpus에 없는 단어 시퀀스라도 예측할 수 있다.</li>
<li>단어를 표현하기 위해 embedding vector를 사용해 단어의 유사도를 계산 → 희소 문제(sparsity problem) 해결</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>고정된 길이의 입력(input vector)</li>
<li>단어를 예측할 때 이전의 모든 단어를 참고하지 않고 한정된 n개의 단어만 참고할 수 있다. (n-gram의 같은 단점)</li>
</ul>
<h2 id="22-rnnlm">2.2 RNNLM</h2>
<ul>
<li>projection layer를 없애고 hidden layer만 사용해 정확도 면에서는 성능이 떨어졌지만, <strong>고정된 입력만 받을 수 있는 NNLM의 한계를 극복한 모델이다.</strong> RNN은 이론적으로 더 복잡한 패턴을 다룰 수 있다.</li>
<li>또한, RNN을 사용해 바로 이전 단어 뿐만 아니라 이전 단어의 hidden state도 사용하기 때문에 약간의 문맥 정보를 학습할 수 있다.</li>
</ul>
<p>$Q = H * H + H * V$</p>
<ul>
<li>RNN에서는 단어를 H차원의 hidden state vector로 표현한다.</li>
<li>NNLM에서와 마찬가지로 hierarchical softmax를 사용하면 $H<em>V$을 $H</em>log_2(V)$로 연산량을 줄일 수 있어 $H*H$항이 연산량에 가장 많은 영향을 준다.</li>
</ul>
<h2 id="23-parallel-training-of-neural-networks">2.3 Parallel training of Neural Networks</h2>
<ul>
<li>구글의 첫 번째 머신러닝 프레임워크 DistBelief를 사용해 실험을 진행했고 mini-batch와 Adagrad 사용했다. (Tensorflow가 구글의 두 번째 프레임워크)</li>
<li>병렬화<ul>
<li>병렬화에는 데이터 병렬화와 모델 병렬화가 있다.</li>
<li>데이터 병렬화: 동일한 모델을 각 노드(gpu)마다 보내고, 학습 데이터를 병렬화에 사용하는 노드 갯수만큼 쪼개서 노드에 보내준다. 그리고 각각 계산한 그래디언트를 모아서 모델을 업데이트하고, 그 업데이트된 모델을 다시 각 디바이스에 보내주고요.( 이때 각 디바이스의 그래디언트를 모으고 업데이트를 수행하는 노드를 coordinating node라고 한다)</li>
<li>모델 병렬화: 큰 모델을 쪼개서 디바이스에 보내준다. 하나의 디바이스에 한 모델을 다 담기 어려운 메모리 이슈나 모델 구간마다 계산되는 과정을 병렬화하기 위함이다. <a href="https://runebook.dev/ko/docs/pytorch/pipeline">여기</a> multi GPU를 사용하는 방식과 비슷하고, AlexNet 논문에서 모델을 쪼개 2대의 gpu로 학습한 방식이 여기에 해당한다.</li>
<li>파이토치 distributeddataparallel 나 dataparallel가 요런 과정이라서 파이토치 공식페이지 참고하셔도 좋을 것 같고.. <a href="https://medium.com/daangn/pytorch-multi-gpu-%ED%95%99%EC%8A%B5-%EC%A0%9C%EB%8C%80%EB%A1%9C-%ED%95%98%EA%B8%B0-27270617936b">당근마켓에 이 분이 올리신 글</a> 도 살짝 봐도 좋을 것 같아요!</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MRC 대회 회고]]></title>
            <link>https://velog.io/@ny_/MRC-%EB%8C%80%ED%9A%8C-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ny_/MRC-%EB%8C%80%ED%9A%8C-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 29 May 2022 18:05:17 GMT</pubDate>
            <description><![CDATA[<h1 id="1-프로젝트">1. 프로젝트</h1>
<p>Level 2의 마지막 대회인 Open-domain Question Answering 대회가 끝났다. 👏👏👏</p>
<p>Question Answering(질의응답)은 정답이 들어있는 지문(context)과 질문(question)이 주어지면 질문에 대한 정답(answer)을 찾는 task이다. 정답을 찾을 때 지문 내에 들어있는 문장으로만 정답을 구성하는 extractive 방식과 문단에 없는 어휘로 구성하는 generative 방식이 있다. 이번 대회는 extractive 방식이었으며, 모델이 지문을 읽고 이해해야 하므로 MRC(Machine Reading Comprehension)라고 부르기도 한다.</p>
<p>여기서 앞에 open-domain이 붙으면 정답을 찾을 특정 지문이 주어지지 않고, 수 많은 문서 중에 정답을 찾아야 한다. 구글과 같은 검색 엔진에서 “아이유 생일&quot;이라고 검색하면, 아이유의 인물 정보가 들어있는 문서를 먼저 찾고(retrieve), 해당 문서에서 아이유의 생일을 찾는다(mrc). </p>
<p>NLP 분야를 처음 알게되었을 때 질의응답(Question Answering)이 재밌어보였던지라 시작 전부터 이번 대회에 대한 기대가 컸다!!</p>
<blockquote>
<p>프로젝트 정리 링크</p>
</blockquote>
<ul>
<li><a href="https://www.notion.so/MRC-Wrap-up-report-cb4fd2e53b004600955d2841b71945ce">Notion</a></li>
<li><a href="https://github.com/HanNayeoniee/level2-mrc-nlp-09">Github</a></li>
</ul>
<h1 id="2-kpt-작성">2. KPT 작성</h1>
<p>이번 대회에서 내 목표는 3가지였다.</p>
<p>1) 성능 개선에 도움이 되지 않더라도 정리해 팀원들과 공유하기 → Keep
2) 강의 내용을 최대한 이해하고 해당 내용을 대회 코드에 녹이기 → Problem
3) 어려워 보인다고 지레 겁먹지 말고 공부하고 싶은 task를 맡아서 구현 및 실험하기 → Try</p>
<h2 id="21-keep">2.1 Keep</h2>
<p><strong>성능 개선에 도움이 되지 않더라도 정리해 팀원들과 공유하기</strong></p>
<p>나는 대회 초반에 huggingface에 공개된 모델을 사용해 reader 모델 실험을 진행했다. 이번 대회는 Retriever(문서 검색) + Reader(MRC) 구조로 강의를 듣고 베이스라인 코드를 이해하는데 시간이 꽤 걸려서 실험을 돌려 놓고 공부를 했다. 이번 task와 동일한 QA task인 KorQuAD로 학습된 모델과, 한국어라는 제한사항을 빼면 활용할 수 있는 모델이 많아진다고 생각해 multilingual 모델 실험을 진행했다. (이번 대회에서는 외부 데이터셋 활용은 허용이었지만, MRC 데이터셋으로 fine-tuning하는건 금지였다.)</p>
<p>KorQuAD로 학습된 모델은 bert-base 또는 koeletra-base로 기준이 되는 roberta-large보다는 작은 모델이라 낮은 성능을 보였다. Multilingual 모델은 실험 결과를 보고나서야 너무나 당연하다는 것을 깨달았는데, 한국어에 적용하기에는 영어로 학습된 모델 &lt; multilingual 모델 &lt; 한국어로 학습된 모델 순서로 성능이 높아진다. pre-training에 사용되는 언어와 동일해야 해당 언어만의 특징을 학습해 성능이 더 좋아지고, 이러한 이유 때문에 KLUE benchmark 데이터셋이 공개된 것이다!! </p>
<p><strong><code>bert-base</code> &lt; <code>multilingual bert-base</code> &lt; <code>klue bert-base</code></strong> 순서로 성능이 좋다.</p>
<p>우리 팀은 각자 진행한 실험을 <a href="https://github.com/boostcampaitech3/level2-mrc-level2-nlp-09/issues?q=is%3Aissue+is%3Aclosed">issue</a>로 열어서 결과를 기록했는데, 기록하면서 팀원들간의 공유 뿐만 아니라 스스로도 왜 해당 방법을 시도했는지, 어떠한 방법으로 구현했는지 다시 한 번 정리하는 시간이 되었다. 또한, 진행한 대부분의 내용을 기록했기 때문에 마지막에 wrap-up report를 작성하는데도 큰 도움이 되었다. </p>
<h2 id="22-problem">2.2 Problem</h2>
<p><strong>강의 내용을 최대한 이해하고 해당 내용을 대회 코드에 녹이기</strong></p>
<p>베이스라인 코드와 Elasticsearch는 sparse embedding을 사용하지만, 강의에서는 dense embedding을 다루었다. 이번 대회에서 공부할 것들이 너무 많아서 선택한 부분을 완성시킨건 잘 한 점이지만, 간단히 개념만이라도 짚고 넘어갈 필요가 있어 보인다.</p>
<p>내가 맡은 부분을 완료하기 위해 이번 대회에서는 선택과 집중을 했는데 dense embedding은 나에게 선택받지 못한 친구이다…. </p>
<h2 id="23-try">2.3 Try</h2>
<p><strong>어려워 보인다고 지레 겁먹지 말고 공부하고 싶은 task를 맡아서 구현 및 실험하기</strong></p>
<p>어찌 보면 치팅일수도 있지만 대회 시작하고 얼마 안 지나서 저번 부캠을 들었던 친구와 연락하다가 Elasticsearch가 retreiver의 성능을 엄청 높여준다는 정보를 얻었다. 지금까지 사용한 모델을 바꾸거나 데이터를 증강하는 방법이랑은 달라 새로워서 내가 맡는다고 선언했는데, 너무 쉽게 봐서 처음에 세팅하는 데만 며칠이 걸렸다. 팀원분들이 내가 Elasticsearch 오류 해결에만 집중할 수 있도록 도와주셔서 성공했고, 팀 내 SOTA를 갱신하면서 리더보드에 제출하는 맛을 처음으로 느꼈다.</p>
<p>설치, 공식 문서를 읽고 내 상황에 적용하는 부분에서 많이 막혔다. pip 명령어 한 줄로 설치할 수 있는게 아니라서 우분투에 설치하는 포스팅을 여러 개 따라했는데, 아무 생각없이 명령어를 따라한 것과 서로 다른 설치 방법을 섞어서 사용해서 원인 파악을 하는데 어려움이 있었다. 이 과정에서 서버를 2번 초기화시키고 할당받았다….ㅎㅎ</p>
<p>Elasticsearch 라고 포괄적으로 검색했을 때는 관련 정보를 얻을 수 없었지만, 파라미터별로 하나씩 검색했더니 해당 파라미터의 설명과 예시 등 자세한 내용을 알 수 있었다. 마지막에는 결국 처음에 봤는 공식 문서로 돌아가 “아 이 파라미터가 이런 역할을 하는구나!”라고 이해했다. 아직 새로운 방법을 시도할 때 “이건 처음 사용하는거라서 새로운데 기존과 어떤 점이 다른지 궁금하다!”라는 마음보다는 “여러번 읽어도 모르겠는데 이건 대체 뭘까?”라는 생각을 하게되는것 같다. </p>
<h1 id="3-느낀점">3. 느낀점</h1>
<p>결과적으로는 이번 대회에서 우리 팀이 1등을 했지만, 나는 조금은 찝찝한 1등이라고 느꼈다. 다른 팀들과 비교해 특출나게 좋은 방법을 적용했다기 보다는 서로 중복되는 역할이 없고, 성능 향상에는 도움되지 않지만 구현하는데 시간이 오래 걸리는 방법들을 적용하지 않아 시간을 효율적으로 사용했기 때문이다. 대회 주제와 코드가 이해되지 않더라도 일단 빠르게 실험하고 튜닝을 진행한게 도움이 되긴 했다. </p>
<p>대회는 잘 마무리했지만, 아직도 Elasticsearch와 ODQA는 미지의 영역이다. 지금까지 배웠던 task 중에 가장 재밌지만 그만큼 어려웠던 대회라 아쉬움이 많이 남는다. 기회가 된다면 이 주제를 좀 더 공부하고 싶다. </p>
<p>마지막으로 이번 대회 중에는 부캠 후반부라 지쳐서 대회에 집중하지 못하는 팀원도 있었다. 처음에는 “내가 어떻게든 다시 힘을 낼 수 있게 cheer up 해줘야겠다!” 라고 생각했지만 내가 팀원의 상황을 잘 모르기도 하고, 이미 지쳐있는 사람한테 “힘내!!!!!!!!!!!”라고 말하는건 더 힘이 빠질 것 같아서 스스로 회복할 수 있도록 기다렸다. 팀 프로젝트에서는 혼자 앞으로 달리지 않고 팀원과 속도를 맞춰서 함께 가는게 중요하다는걸 느꼈다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RE 데이터 제작 회고]]></title>
            <link>https://velog.io/@ny_/RE-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%9C%EC%9E%91-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ny_/RE-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%9C%EC%9E%91-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Mon, 25 Apr 2022 15:27:35 GMT</pubDate>
            <description><![CDATA[<p>Level 2의 두 번째 대회인 RE 데이터 제작 대회가 끝났다. 이번 대회는 팀별로 리더보드 점수를 높이는 것이 아니라, 팀별 주제에 맞게 주어진 텍스트 데이터로 <strong>관계추출(Relation Extraction) 데이터를 구축</strong>하는 것이 목표였다. 이번에는 변성윤 마스터님께서 소개해주신 <a href="https://brunch.co.kr/@jinha0802/35">KPT 회고</a>에 따라 작성해 보았다. </p>
<h1 id="1-프로젝트">1. 프로젝트</h1>
<p>위키피디아에서 러시아-우크라이나 전쟁 키워드로 수집한 데이터로 관계 추출(Relation Extraction) 데이터셋을 구축했다. KLUE 관계추출 데이터를 기반으로 주제로 정한 텍스트 데이터에 맞게 relation map을 정의하고 tagging을 진행하기 위한 guideline을 작성했다. </p>
<blockquote>
<p>프로젝트 정리 링크</p>
</blockquote>
<ul>
<li><a href="https://wry-silence-4ef.notion.site/Wrap-up-report-ab63f5f2caaf424fa316738356e06291">보고서</a></li>
<li><a href="https://github.com/HanNayeoniee/level2-data-annotation-nlp-09">Github</a></li>
</ul>
<h1 id="2-kpt">2. KPT</h1>
<h2 id="21-keep">2.1 Keep</h2>
<p>전반적인 데이터 구축 과정은 부스트캠프에서 제시한 타임라인을 따랐지만, 파일럿 태깅은 조금 다르게 진행했다. 제시한 타임라인에서는 본 태깅을 진행한 이후에 파일럿 태깅을 통해 IAA를 계산하는 순서였다. 하지만 파일럿 태깅을 통해 팀원(평가자)들간의 기준으로 먼저 맞춰야 한다고 생각해 <code>1차 파일럿 태깅</code> → <code>IAA 측정 및 가이드라인 수정</code> → <code>본 태깅</code> → <code>2차 파일럿 태깅</code> → <code>최종 IAA 측정</code> 순서로 진행했다. 파일럿 태깅을 2번 진행하면서 본 태깅 시 발생할 의문들을 미리 조율해 수월하게 태깅을 진행할 수 있었다. </p>
<h2 id="22-problem">2.2 Problem</h2>
<p>데이터 구축에는 정해진 정답이 없기 때문에 팀원들끼리 의견을 조율해 데이터의 특성을 잘 살리면서 일관성 있는 데이터셋을 만드는 것이 중요하다. 동일한 문장을 보고도 다른 entity, relation을 정의할 수 있어 팀원들끼리 의견을 조율하고 합의점을 찾는데 상당한 시간을 쏟았다. 초반에는 논리적으로 더 타당한 relation을 찾고 정의하기 위해 회의하는 시간이 길었는데, 후반에는 2가지 방법으로 회의 시간을 단축했다. </p>
<blockquote>
<ul>
<li>파일럿 태깅 시에 서로 다르게 태깅을 한 경우에는 더 많은 팀원의 동의를 얻은 relation으로 태깅을 진행했다. </li>
</ul>
</blockquote>
<ul>
<li>서로 주장하는 relation이 다를 때 둘 다 타당한 근거를 가지는 경우에는 러시아-우크라이나 전쟁 주제에 더 연관되는 relation에 초점을 맞춰 태깅을 진행했다. </li>
</ul>
<h2 id="23-try">2.3 Try</h2>
<p>모든 관계 추출 데이터셋에 해당하는 문제이지만 <code>no_relation</code> 데이터는 너무 많고, 다른 클래스의 데이터는 너무 적은 데이터 불균형 문제가 발생했다. &quot;<strong>클래스별 데이터 개수를 고려하면서 태깅</strong>을 진행했다면 불균형이 심하지 않은 데이터셋을 제작할 수 있지 않을까?&quot;
하는 아쉬움이 있다. 하지만 동시에 &quot;<strong>특정 클래스의 데이터가 많이 존재하는 것 또한 해당 데이터의 특성</strong>이지 않을까?&quot; 생각한다. </p>
<h1 id="3-느낀점">3. 느낀점</h1>
<p>전에 OCR 데이터를 라벨링해본 경험이 있어 데이터 제작을 단순히 라벨링 작업이라고 생각했는데 큰 오산이었다. 동일한 데이터에 대해 서로 다른 entity와 relation을 정의할 수 있고 데이터에 다양한 relation이 존재해 합의점을 찾는데 상당한 시간을 쏟았다. 팀원들끼리 왜 해당 관계로 태깅했는지 토의하면서 주제에 더 관련된 데이터를 구축할 수 있는 방향으로 태깅을 진행했다. 
벤치마크 데이터셋을 가져와 사용하거나 조금 변경하는 정도가 전부였는데, 이번 데이터 제작 대회를 통해 전반적인 데이터셋 제작 과정을 알게 되었고, 오픈 데이터셋의 소중함을 더 느꼈다.</p>
<p><strong>섬세킹</strong>으로 뽑혀서 마스터 클래스 시간에 우리 팀이 어떤 부분을 중점적으로, 어떻게 데이터 제작을 수행했는지 발표할 기회를 가졌다. 사실 마스터님과 조교님들의 주관적인 기준으로 뽑혔고, 더 복잡한 데이터로 대회를 수행한 팀도 있기 때문에 객관적으로 봤을 때는 우리 팀이 월등히 우수하다고 보기에는 무리가 있다고 생각한다.
하지만 우리 팀 첫 발표였고, 팀원들과 함께 정리하면서 팀워크를 돈독히 할 수 있는 시간이었다. 요즘 점점 공부량은 많아지는데 무엇 하나 제대로 완성하지 못하는 것 같아 지친 상태였는데 이번 대회에서 <strong>&#39;괜찮아, 잘 하고 있어&#39;</strong>라고 응원받은 기분이었다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[KLUE 관계 추출 대회 회고]]></title>
            <link>https://velog.io/@ny_/KLUE-%EA%B4%80%EA%B3%84-%EC%B6%94%EC%B6%9C-%EB%8C%80%ED%9A%8C-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ny_/KLUE-%EA%B4%80%EA%B3%84-%EC%B6%94%EC%B6%9C-%EB%8C%80%ED%9A%8C-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Mon, 18 Apr 2022 17:13:18 GMT</pubDate>
            <description><![CDATA[<p>Level 2의 첫 번째 대회인 KLUE 관계 추출 대회가 끝났다. 팀 단위로 랩업 리포트와 깃허브에 담지 못한, 팀 전체 의견으로는 담기 어려운 개인적인 내용을 위주로 회고를 작성해 보았다.</p>
<h1 id="지난-대회와-비교해-성장한-부분-🔥">지난 대회와 비교해 성장한 부분 🔥</h1>
<p>이번 대회에서 가장 발전한 점과 우리 팀의 강점을 뽑으면 <strong>협업</strong>이다. 
지난 대회에서는 리더보드 점수에 굉장히 신경썼다면, 이번 대회에서는 리더보드 점수보다는 ‘근거를 기반으로 가설 설정하고 실험하기&#39;와 ‘제대로 된 협업하기’에 초점을 두고 진행했다. 팀원 모두 Level1 대회에서 협업 측면에서 아쉽다고 느껴 대회 시작하기 전 따로 시간을 내어 그라운드 룰을 설정하고 협업 툴도 세팅했다.</p>
<h2 id="1-협업-툴">1. <strong>협업 툴</strong></h2>
<p>지금 team groud rule 페이지가 다른 내용으로 덮어쓰여져서 정확히 확인하기 어렵지만, 기억을 더듬어 적어보면 코드 관리는 github, 전반적인 진행 상황은 github project, 실험 결과 공유는 github issue + notion + wandb, 자세한 내용은 notion을 활용했다. 정리하면 github, notion, wandb 3가지를 사용했다.</p>
<h3 id="코드-관리---github"><strong>코드 관리 - github</strong></h3>
<p>github 관련해서는 같은 팀원인 찬국님께서 초기 세팅을 해주셨고, 초반에 branch가 엉키거나 conflict가 발생했을 때 일대일 과외 선생님처럼 해결해주셨다! 
기능별로 branch를 만들어 기능 단위로 코드를 관리할 수 있도록 했다. feat/data_aug, exp/kfold  &gt; develop &gt; master (각자 개발중인 기능 &gt; 완성한 기능 &gt; 모델에 적용할 기능)으로 branch를 구성했다.<br>이전에는 branch를 많이 사용하지 않았고 사용한다 하더라도 개인별 branch를 생성해 사용했었다. 이번에 사용하면서 branch를 자유롭게 바꾸는 것도 익숙해졌고 다른 종류의 실험을 할 때 주석이 아닌 branch만 변경해 주면 되는 편리함을 경험했다.  </p>
<p><img src="https://velog.velcdn.com/images/ny_/post/42c8458f-7b0a-4551-9e66-ffa5419e7531/image.png" alt=""></p>
<h3 id="전반적인-진행-상황-관리---github-project의-kanban-board"><strong>전반적인 진행 상황 관리 - github project의 kanban board</strong></h3>
<p>전반적인 진행 상황 관리는 github project의 kanban board를 사용했다. (이것도 찬국님께서 적극적으로 도입하셨다!) 왼쪽부터 순서대로 할 일 &gt; 개발중 &gt; 개발 및 모든 팀원 이해 완료 &gt; merge 완료 순서이다. 데일리 스크럼이나 피어세션 시간에 해야할 일들을 같이 작성하고, 코어 타임에는 각자 하고 싶은 일을 할당해 수행했다. 개발 완료된 기능은 일단 PR을 올리고 피어세션 시간에 코드 설명 후 모든 팀원이 이해하면 merge했다. 추가적으로 각자 맡은 역할은 label로 이름을 표시해 동일한 기능이나 실험이 중복되지 않도록 했다. 
notion에도 kanban board 기능이 있는걸로 아는데 우리 팀에는 노션에 능수능란하게 다루는 분이 없고, github에서는 이슈로 연결할 수 있는 장점이 있어서 github를 사용했다.</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/208da3e2-5dfc-48e3-9ce4-56f2e82c7bfa/image.png" alt=""></p>
<blockquote>
<p>왼쪽부터 순서대로 할 일 &gt; 개발중 &gt; 개발 및 모든 팀원 이해 완료 &gt; merge 완료 순서이다.</p>
</blockquote>
<h3 id="실험-결과-공유---github-issue--notion--wandb"><strong>실험 결과 공유 - github issue + notion + wandb</strong></h3>
<p>처음에는 실험 이름만 통일해 짧게 실험 설명과 wandb 그래프만 슬랙에 공유했었다. 하지만 대회 1주차가 지날 무렵 옷걸이로 전락한 의자마냥 실험이 쌓여서 여러가지 툴을 사용해 나름 실험을 공유하기 편한 방법을 찾았다. (실험 결과가 여러 곳에 퍼져 있어서 다음 대회때 개선이 필요해 보인다.) 
실험 그래프는 wandb에 연동해 시각화했고, 실험에 대한 자세한 내용(모델, 하이퍼파라미터 등등)은 issue에 작성한 후에 비교하기 쉽도록 notion table에 정리했다. kanban board의 각 항목에 issue를 남길 수 있어, 개발중인 각각의 기능의 issue부분에 실험 성능을 기록했다.
(중간에 wandb report도 사용해보았는데, 글자수 제한이 있어서 바로 다른 방식으로 갈아탔다.)</p>
<p><img src="https://velog.velcdn.com/images/ny_/post/706dfa68-8747-46b9-b49d-3f32d8f657c7/image.png" alt=""></p>
<blockquote>
<p>각 기능별 issue에 실험 결과를 정리</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ny_/post/7d4af6b2-781d-49f9-9479-77ac5b42544d/image.png" alt=""></p>
<blockquote>
<p>실험 결과를 한 눈에 볼 수 있도록 표로 정리(짧게 실험을 통해 얻은 인사이트도 넣었다)</p>
</blockquote>
<h3 id="미세먼지-꿀팁---slack에-github-wandb-알람-연동">미세먼지 꿀팁 - slack에 github, wandb 알람 연동</h3>
<p>일일이 확인하기 귀찮은 부분들을 슬랙에 연동했다. wandb는 실험이 끝나면 끝났다고 알람이 울리고(실험 run이 끝난건지 중간에 오류나서 끝난건지도 알려준다), issue, pr, merge 관련 알람이 공유된다. 대회 후반부로 갈수록 코드를 수정하고 merge하는 경우가 많아졌는데, 팀원들이 올린 코드를 빠르게 확인 후 피드백하는데 도움이 되었다. 
다음 대회에서는 매일 밤 리더보드 제출 여부를 투표하는 slackbot을 만들어 보려고 한다. </p>
<p><img src="https://velog.velcdn.com/images/ny_/post/24d988d9-d81a-4769-a02d-5e3c9c9bf895/image.png" alt=""></p>
<blockquote>
<p>slack에 github, wandb 알람 연동</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ny_/post/b7c82cab-6d53-491f-a0c5-dfa28d6f73e0/image.png" alt=""></p>
<blockquote>
<p>private에서 public으로 전환되서 기뻐하는 문어..?</p>
</blockquote>
<h2 id="2-의견아이디어-공유">2. <strong>의견/아이디어 공유</strong></h2>
<p>이 부분은 팀 단위로도 성장했고 나 스스로도 성장한 부분이다.</p>
<p>지난 대회에서는 좋은 결과만 공유를 해야한다는 생각에 새로운 기법을 적용해도 성능 향상이 있으면 공유를 하고, 없으면 잘 공유를 하지 않았다. 내가 자주 공유하지 않아 아마 팀원들은 내가 프로젝트를 잘 쫓아오지 못하거나, 기여를 많이 안한다고 생각했을 것이다. 내가 우려하던 바는 동료 평가에서 실험 후기를 더 많이 공유했으면 좋겠다는 피드백을 받았다.</p>
<p>이번 대회에서는 ‘결과가 좋은 안좋든, 삽질하느라 아직 결과가 나오지 않아도 공유하자!’라는 마인드로 피어세션에 짧게 내 진행 상황을 공유했다. 결과에 상관없이 매일 공유하면서 팀원들은 내가 얼만큼 수행했는지 알 수 있고 나는 내가 이상한 곳에서 삽질하거나 방향을 잃었을 때 빠르게 되돌아 올 수 있어서 도움이 되었다.    </p>
<h1 id="시도했지만-성능향상에-실패한-부분-🥲">시도했지만 성능향상에 실패한 부분 🥲</h1>
<p>나는 팀에서 data augmentation 부분을 맡았는데, 사실 시도했던 모든 방법이 성능 향상에 도움이 되지 않았다. 이 원인으로는 2.5개를 꼽을 수 있다.</p>
<h2 id="1-꼼꼼함의-부재">1. 꼼꼼함의 부재</h2>
<p>크게 EDA, AEDA, entity swap, downsampling을 적용했다. EDA, AEDA는 깃허브 코드를 가져와 사용했고 entity swap, downsampling은 내가 구현했는데 짧고 간단해 코드를 이해하고 적용하는게 오래 걸리지 않았다. </p>
<p>우리 모델에 적용한 후에 실험을 진행했는데 파라미터 세팅을 동일하게 하지 않거나, 증강된 데이터를 확인하는 과정을 건너뛰어 정확한 성능 비교까지 오래 걸렸다. 중간 과정을 생략하고 실험을 진행해 결국에는 데이터 증강, 분포 확인 등등 하나씩 확인하면서 실험을 진행했다. 코드 가독성을 떨어뜨려 이번에는 argparser를 사용하지 않았는데, argparser를 사용한다면 파라미터 세팅을 깜빡하는 실수를 줄일 수 있지 않을까 생각한다. </p>
<h2 id="2-task에-대한-이해-없이-무작정-시도한-augmentation">2. task에 대한 이해 없이 무작정 시도한 augmentation</h2>
<p>오피스 아워에서 공유해주신 NLP data augmentation 기법들과 개인적으로 찾아본 기법들을 위주로 시도했다. 객관적 기준을 토대로 가설 설정을 하고 실험을 진행하기 위해 논문을 많이 참고했는데 내가 간과한 부분은 논문과 내가 해결하려는 문제가 다를 수 있다는 점이다. 영어에 적용한 기법을 한국어에 적용하거나, NLI에 적용한 기법을 RE task에 적용하면서 내가 놓친 부분이 있지 않을까 생각한다.   </p>
<p>논문 저자들을 비판하는건 아니지만, 생각해보면 나도 논문을 쓸 때 내 실험 결과를 더 돋보이게 하기 위해서 다양한 노력을 했다 ^)^ 내가 직접 실험해본 기법이 아니면 정말 ‘참고 자료&#39;로만 사용해야 한다는 교훈을 얻었다. </p>
<h2 id="3-동료가-있었다면">3. 동료가 있었다면..?</h2>
<p>이 부분은 구차한 변명이 될 것 같지만 내 마음의 평화 &amp; 자기 합리화를 위해 작성해본다 ㅎㅅㅎ</p>
<p>대회가 끝나고 다른 팀들은 어떤 시도를 했는지 공유하는 시간이 있었는데 data augmentation 관련해서 굉장히 다양한 방법을 시도했고, 그만큼 많은 시간을 쏟았다. (kogpt로 데이터 생성하기, 영어/중국어 등 다양한 언어와 번역기로 back translation 적용하기) </p>
<p>data augmentation 관련 어려움을 내가 팀원들에게 더 공유하고, 강력하게 도움을 요청했다면 더 많은 시도를 할 수 있지 않았을까? 하는 아쉬움이 있다. (팀원들 모두 다른 부분을 맡아 진행했기 때문에 팀원 탓을 하는건 절대 아니다!)</p>
<h1 id="시간이-더-주어진다면-🕰">시간이 더 주어진다면..? 🕰</h1>
<h3 id="curriculum-learning">Curriculum Learning</h3>
<p>대회 마지막 주에 EXOBRAIN에서 RE task에 curriculum learning을 적용한 <a href="https://arxiv.org/pdf/2107.09332v2.pdf">논문</a>을 읽고 모델 변경, 데이터 증강, 하이퍼파라미터 튜닝과는 완전 다른 방식의 변경이라고 생각해 적용해보았다. (사실 대회 첫째주에 찾은 논문인데 무슨 말인지도 모르겠고 구현된 코드도 없어서 쿨하게 패스했다) 
Curriculum Learning은 전체 데이터터셋을 1/n로 나누어 랜덤한 순서로 학습하지 않고 쉬운 데이터셋부터 어려운 데이터셋 순서로 학습시키는 아이디어이다. 논문의 저자들은 쉬운 데이터부터 학습시키면 모델 수렴 속도가 빨라진다고 주장한다. (사람이 영어 공부할 때 알파벳부터 시작해 실생활 영어를 공부하는 과정과 비슷하다고 생각하면 된다) </p>
<p>데이터셋을 1/n개로 나누어 난이도가 쉬운 문장부터 학습시키는 아이디어가 핵심인데,</p>
<blockquote>
<ul>
<li>데이터셋을 1/n개로 어떻게 나누지? 문장 단위로 나누라는 의미인가?</li>
</ul>
</blockquote>
<ul>
<li>문장의 난이도는 어떻게 측정할 것인가?
이 두 가지가 내 의문이었다. </li>
</ul>
<p>curriculum learning을 NLU에 적용한 논문 <a href="https://aclanthology.org/2020.acl-main.542/">Curriculum Learning for Natural Language Understanding</a> 에 자세한 내용이 나와있어 참고했다.</p>
<blockquote>
<ul>
<li>논문에 n=2로 설정해도 성능 향상이 있다고 나와있기도 하고, 문장 단위로 데이터를 나누는걸 구현하는데 어려움이 있어 전체 데이터셋을 이등분해 첫 번째 의문을 해결했다. </li>
</ul>
</blockquote>
<ul>
<li>논문에서는 SQuAD 데이터셋으로 실험을 수행했으며, 다양한 난이도 측정 방법이 있지만 문단의 길이 &amp; 질문의 길이 &amp; 정답의 길이를 기준으로 난이도를 측정했다. SQuAD는 주어진 문단을 읽고 질문에 대한 정답을 구하는 task라서 3가지 길이를 고려해야 하지만, RE task는 입력 문장이 한 문장이니까 <strong>입력 문장의 길이를 난이도로 사용할 수 있다</strong>는 아이디어를 얻었다. </li>
<li>train data_loader 부분에서 데이터셋을 문장 길이가 짧은 순서로 정렬하고, 정렬한 순서대로 데이터를 불러올 수 있도록 구현했다. 실험 결과 wandb 그래프 상에서 아주 약간 성능이 하락했다. </li>
</ul>
<p>문장 길이가 짧은 문장이 더 학습하기 쉽다는 가정을 했는데, dynamic padding이 아닌 고정 길이로 padding을 했기 때문에 오히려 짧은 문장에는 의미 없는 [PAD] 토큰이 많이 들어가 학습을 더 어렵게 만든건 아닐까 추측한다. 추후에 dynamic padding을 적용하면 이러한 요인을 배제한 실험이 가능할 것이라 생각한다. </p>
<p>다른 팀에서 curriculum learning을 적용해 2-3점 높인 경험을 공유해주셨다. 일단 짧은 시간에 해당 코드를 구현했다는 점에 박수 세 번 짝👏 짝👏 짝👏  각 문장별로 난이도를 측정해 쉬운 문장부터 학습할 수 있도록 적용했다고 한다. 나처럼 지름길로 가지 않고 역시 정석적인 방법이 통한게 아닐까 싶다. 이 방법은 task에 상관없이 적용할 수 있는 방법이라서 다음 대회에서 적용해 보고 싶다.   </p>
<h3 id="다른-data-augmentation-기법들">다른 data augmentation 기법들</h3>
<p>한국어 데이터를 증강하기 위해 한국어 → 외국어 → 한국어로 번역해 동일한 의미이지만 다른 표현을 가지는 문장을 만드는 back translation 기법이 있다. 이 방법은 뇌피셜로 번역기의 성능이 안 좋을 것 같기도 하고 막막해서시도하지 않았다. 
하지만 대회 이후에 다른 팀 분들의 후기에서 이 기법을 많이 사용했을 알 수 있었다. 결과론적으로는 back translation이 성능 향상을 보인 팀은 아직 만나지 못해서 효율적으로(?) 대회를 진행했다고 볼 수 있지만, 시작하기도 전에 실패할까 두려워 너무 각재고 시도하지 않았던건 아닌가 반성하게 된다. </p>
<h3 id="내가-생성한변경한-문장은-동일한-의미인가">내가 생성한/변경한 문장은 동일한 의미인가?</h3>
<p>EDA에서 제안한 4가지 방법 SR(synonym replacement), RI(random insertion), RS(random swap), RD(random deletion)을 적용했을 때 문장의 의미가 그대로인지 확인하는데 어려움이 있었다. 최종 발표 시간에 김성현 마스터님께서 원문 문장의 의미를 헤치지 않으면서 생성했는지 확인할 수 있는 paraprasing module을 알려주셨다. STS(Semantic Textual Similarity) dataset을 활용하면 문장 간의 유사도를 확인할 수 있다고 한다. 
(이번 대회가 관계 추출이라서 논문에서 RE task 부분만 정독했는데 KLUE 논문에도 STS task가 있었다..!)</p>
<h1 id="마무리">마무리</h1>
<p>자세한 내용이 궁금하다먼 MnM조 <a href="https://github.com/boostcampaitech3/level2-klue-level2-nlp-09">github</a>를 참고해 주세용~!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[열심히 공부하고 쉬고 한 걸음 더 나아가기]]></title>
            <link>https://velog.io/@ny_/%EC%97%B4%EC%8B%AC%ED%9E%88-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B3%A0-%EC%89%AC%EA%B3%A0-%ED%95%9C-%EA%B1%B8%EC%9D%8C-%EB%8D%94-%EB%82%98%EC%95%84%EA%B0%80%EA%B8%B0</link>
            <guid>https://velog.io/@ny_/%EC%97%B4%EC%8B%AC%ED%9E%88-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B3%A0-%EC%89%AC%EA%B3%A0-%ED%95%9C-%EA%B1%B8%EC%9D%8C-%EB%8D%94-%EB%82%98%EC%95%84%EA%B0%80%EA%B8%B0</guid>
            <pubDate>Sun, 27 Mar 2022 12:17:10 GMT</pubDate>
            <description><![CDATA[<p>학창 시절부터 공부 잘하는 애들이 부러웠다. 공부 잘하는 학생들을 칭찬하고, 또 잘해야 좋은 대학에 가니까 부러운건 어찌보면 당연했다. 정확히 말하자면 “놀 거 다 놀면서 공부도 잘하는 친구&quot;가 신기했고 부러웠다. 지금까지 살아오면서 세 종류의 “잘 놀지만 성적도 좋은 친구&quot;를 만났다. </p>
<h2 id="잘-놀지만-성적도-좋은-친구">“잘 놀지만 성적도 좋은 친구&quot;</h2>
<h3 id="case-1">case 1</h3>
<p>첫 번째는 노는걸 진짜 좋아하지만 부모님이 무서워 시키는 공부를 해서 성적이 잘 나오는 경우이다. 고등학교에 진학하면 공부량이 많아져 이런 케이스는 대부분 중학교때 까지 봤던 것 같다. </p>
<h3 id="case-2">case 2</h3>
<p>두 번째는 노는걸 진짜 좋아하지만 머리가 좋은 친구들이다. 대학 동기 중에 이런 친구가 있었는데 (물론 요즘도 가끔 연락한다 ㅎㅎ) 약속도 많고, 알바도 하고, 연애도 하느라 피곤해 수업시간에 졸지만, 잊어버리지만 않는다면 과제도 금방금방 완료해서 제출하고 1주일 벼락치기로 항상 B+~A 이상의 학점을 받았다. (참고로 필자는 공대생이다....) 비결도 궁금하고 시험 1주일 전에서야 시험범위를 확인하는 친구가 답답해서, 한 번은 정말 진지하게 맨날 노는데 대체 언제 공부하는지 물어봤었다. 비결은 다년간 쌓아온 벼락치기 스킬과 명석함이었다. 
그 당시에 시험공부를 같이 몇 번 했었는데, 일단 새로운 개념에 대한 이해가 빠르고 응용력도 좋아 문제에 빨리 적용한다. 그리고 자의 반 타의 반이지만 일단 시작하면 일에 몰입한다. 일을 끝까지 미루고 시작해 촉박함이 집중력을 높히기도 하고, 일을 시작하면 주변에 온갖 방해가 있어도 흔들리지 않는다. 초반에는 이 친구의 공부 스킬이 좀 부러웠지만, 나는 불가능하다는 것을 알고 그냥 받아들였다.</p>
<h3 id="case-3">case 3</h3>
<p>마지막으로는 머리가 좋은건 아니지만 노는 것과 성적 무엇 하나 놓치기 싫어하는 욕심쟁이 친구들이다. 동기 중에 입학부터 졸업까지 항상 1-2위를 다투면서 시험 직전까지도 본인의 필기를 공유하고 질문에 답해주는 친구가 있었다. 그렇다고 공부만 하는건 아니었고 술자리도 즐기고 학생회장을 맡아서 항상 약속이 많은 친구였다. 대학생때 장학금 한 번 쯤은 받아야겠다는 생각에 같이 공부하면서 금세 가까워졌는데 내가 옆에서 느낀 비결은 <strong>“탄력적으로 일할 수 있게끔 스케쥴 짜기&quot;</strong>이다. 시험과 같이 큰 이벤트가 끝나면 그에 대한 보상으로 자신이 좋아하는 것들을 했다. 사실 이 점은 대부분의 사람들과 비슷할 것 같은데, 그 친구는 보상의 사이클이 짧았다. 나는 마음의 여유가 부족해 시험이 끝나야 놀러가거나 약속을 잡는 반면, 그 친구는 스스로에게 보상을 자주 주었다. 넷플릭스 정주행하기, 베이킹하기 같은 소소한 보상부터 놀이공원 가기, 여행가기 등 큰 보상까지 일을 완성할 수 있는 원동력을 항상 만들었다. 
이런 친구를 옆에서 보면서 나도 스스로 원동력을 만드려고 노력했다. 대학교 2-3학년 때는 edm음악에 빠져서 페스티벌에 많이 갔고, 타과 친구들을 많이 사귀어 다양한 사람들과 모임을 가졌다. 학교 공부에 나름 노하우도 생기고 엉덩이로 공부법이 아니라 나에게 맞는 공부법을 찾아 틈틈이 놀면서도 매학기 장학금을 받을 수 있었다. </p>
<h2 id="다시-마음의-여유가-없어지다">다시 마음의 여유가 없어지다...</h2>
<p>학업과 휴식을 조합해 나름 탄력적으로(?) 지냈지만, 대학원에 진학하고 나서부터는 왠지 맘편히 쉬면 안된다는 생각에 학교에 나가지 않는 주말에도 약속을 많이 안 잡고 책상에 종종 앉아있었다. 여기서 문제는 책상에 앉아서 공부는 별로 하지 않았다는 점이다! ㅋㅋㅋㅋㅋ 주말에도 출근하는 박사과정 선배를 보며 “내가 놀 시간이 어디있어&quot;라는 생각을 많이 했었다. 박사과정을 마무리하는 선배와 이제 막 연구실 생활을 시작한 나를 비교하는건 비교 대상이 안 맞지만, 그 당시에는 얼른 성과를 내야겠다는 생각에 조급했다. </p>
<p>졸업하고 1달 정도 쉬다가 부캠에 합류했고 초반에는 열정 가득한 캠퍼, 마스터분들과 함께해 설렜고 나와 비슷한 관심사와 실력을 가진 분들과 공부해 너<del>~</del>무 행복했다. 부캠 강의과 과제 진도는 평일에 다 따라갈 수 있었지만, 모르는 부분들을 더 찾아보고 다른 스터디를 소화하려면 주말에도 공부하는건 어떨 수 없었다. 처음 시작할 때는 5개월 동안 빡 집중하자!! 마인드였는데 2달 정도 지나니까 굉장히 많이 지쳤다. 잠도 줄여가면서 책상에 앉아있기는 하지만 점점 집중이 안되는 느낌이었다. 그래서 다시 돌아가 <strong>“탄력적으로 일하기”</strong>를 시도하는 중이다.</p>
<p>내가 시도한 효율적으로 공부하기 &amp; 휴식하기 방법들을 작성해보았다.</p>
<h3 id="1-효율적으로-공부하기">1. <strong>효율적으로 공부하기</strong></h3>
<ul>
<li>온라인 강의라고 하루종일 집에 있지 말자. 한 공간에서 오랫동안 집중을 잘 못하는걸 알기에 집/도서관/카페나름 다양하게? (원래는 파스쿠찌만 갔는데 질려서 요즘은 스벅도 가끔 간다) 공부 공간에 변화를 주자.</li>
<li>할 일이 많다고, 대회라고 하루 종일 노트북 앞에 앉아있지 말자. 물론 발등에 불 떨어진 경우에는 그렇게 해야겠지만, 괜히 마음이 불편해서 책상에 앉아있지는 말자.</li>
<li>모든 시간에 집중력을 높이려 애쓰지 말고, 집중이 잘되는 시간을 찾자. 나 같은 경우에는 오전에는 집중을 잘 하지만, 저녁 먹은 후에는 피곤해서 누워있다가 10-11시 밤부터는 하루를 이렇게 마무리해서는 안되겠다는 생각에 다시 집중한다.</li>
</ul>
<h3 id="2-효율적으로-휴식하기--놀기">2. 효율적으로 휴식하기 &amp; 놀기</h3>
<ul>
<li>친구들을 자주 만나지 못한다면 영상통화를 애용하자!! 대학생활 5년동안 거의 매일 학교에 가고, 같이 수업을 듣고, 잘 안되면 옥상이나 카페가서 쉬면서 소소한 대화들을 나누었는데 요즘은 주로 집에서 카톡만해서 조금 외롭다고 느낄때도 있다. 얼마 전에 매번 카톡만 하던 중학교 친구랑 몇년만에 영상통화를 했는데, 생각보다 같이 있다는 느낌을 많이 받았다.</li>
<li>거창하지 않더라도 운동을 하자! 점점 체력도 안좋아지고 억지로라도 밖에 나가야할 필요가 있는 것 같아서 집근처 헬스장에 등록했다. 집중이 잘 안되는 저녁시간에 운동하러 가지 않을까 싶다. 지금까지 두 번 갔는데 저번에 PT쌤이 운동 마치고 “느낌 좋죠?”라고 한 말이 신선했고 진짜 헬스인이라고 느꼈다. 에러 해결하느라 끙끙대고 논문을 읽는것과는 다르게 숨차지만 하나라도 더 하려고 정신줄을 놓치 않는게 다른 종류의 자극이라서 나름 재밌었다.</li>
<li>아직 어떻게 쉬어야 잘 쉬는건지 나만의 방법을 찾지는 못했지만 사람들이 좋다고 하는 방법들을 시도해 보려고 한다. <blockquote>
<p>한강 잔디밭에 누워서 날씨 즐기기
사람 많은 대형 서점 가기</p>
</blockquote>
</li>
</ul>
<p>내일까지만 내다본다면 지금 당장 앉아 코드를 한 줄 더 짜고 논문을 하나 더 읽는게 도움이 되겠지만, 쉬지 않고 쭉 달려간다면 지치는건 시간 문제라고 생각한다. 일을 하나 하면 적절한 보상을 주고, 다음 일로 넘어가도록 하자.</p>
<p><img src="https://images.velog.io/images/ny_/post/c4a8a491-7012-457c-8550-9bfccdcc747b/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[8주차 학습정리]]></title>
            <link>https://velog.io/@ny_/8%EC%A3%BC%EC%B0%A8-%ED%95%99%EC%8A%B5%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ny_/8%EC%A3%BC%EC%B0%A8-%ED%95%99%EC%8A%B5%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sat, 12 Mar 2022 17:03:22 GMT</pubDate>
            <description><![CDATA[<h3 id="nlp-기초-이론">NLP 기초 이론</h3>
<ul>
<li><p><a href="https://wry-silence-4ef.notion.site/Part-1-02100a48a1e2465c9f726a96e8215885">자연어처리 part 1 정리</a> : Word Embedding, Word2Vec, GloVe</p>
</li>
<li><p><a href="https://wry-silence-4ef.notion.site/Part-2-d8f73f206f504658a88f025a2e23eb6a">자연어처리 part 2 정리</a> : RNN, LSTM, GRU</p>
</li>
<li><p><a href="https://wry-silence-4ef.notion.site/Part-3-6011fe14227b460d8235074232a987c7">자연어처리 part 3 정리</a> : Attention, Beam Search, BLEU score</p>
</li>
</ul>
<ul>
<li><p><a href="https://wry-silence-4ef.notion.site/1-Data-Preprocessing-Tokenization-188c123f1b5c4f5baee221529ec9d877">과제 1 정리</a> : Data preprocessing &amp; Tokenization</p>
</li>
<li><p><a href="https://www.notion.so/2-RNN-based-Language-Model-8e342faa404d4be18440eb3436bc92a9">과제 2 정리</a> : RNN-based Language Model</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Sequence to Sequence Learning with Neural Networks]]></title>
            <link>https://velog.io/@ny_/Sequence-to-Sequence-Learning-with-Neural-Networks</link>
            <guid>https://velog.io/@ny_/Sequence-to-Sequence-Learning-with-Neural-Networks</guid>
            <pubDate>Sun, 06 Mar 2022 15:27:56 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>참고 자료</p>
</blockquote>
<ul>
<li><a href="https://arxiv.org/abs/1409.3215">Seq2Seq Paper</a></li>
<li><a href="https://www.youtube.com/watch?v=0lgWzluKq1k">DSBA seq2seq2 learning 강의</a></li>
<li><a href="https://www.youtube.com/watch?v=4DzKM0vgG1Y">나동빈 유튜브</a></li>
<li><a href="https://www.youtube.com/watch?v=PipiRRL50p8">DSBA paper review</a></li>
<li><a href="https://www.youtube.com/watch?v=EoGUlvhRYpk">Aladdin Persson-pytorch seq2seq tutorial for machine translation</a></li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>딥러닝은 라벨링이 되어있는 대량의 데이터가 존재하는 task에서 좋은 성능을 보이지만, sequence를 sequence에 매핑하는데는 사용되지 않았다. 본 논문에서는 end-to-end approach가 가능한 sequence learning 방법을 제안한다.
LSTM을 여러개 쌓은 multilayered LSTM을 사용했으며, encoder와 decoder는 각각 multilayered LSTM으로 이루어진다. Encoder는 입력 sequence를 고정된 길이의 context vector로 만들고, decoder는 context vector를 출력 sequence를 만든다. 
WMT 14 dataset을 사용해 BLEU score를 측정했을 때, 본 논문에서 제안하는 Seq2Seq이 가장 높은 성능을 보였다. 학습 과정에서 입력 sequence를 거꾸로 넣었을 때 모델 성능이 더 높았다.</p>
<h2 id="1-introduction">1. Introduction</h2>
<p>Deep Neural Networks(DNNs)는 높은 성능을 보이지만, 입출력 차원을 미리 알고 그 크기가 고정된 경우에만 적용할 수 있어 음성인식(speech recognition), 기계번역(machine translation)과 같은 sequential 문제에는 적용할 수 없다. 본 논문에서는 고정된 크기의 벡터를 얻는 LSTM 1개(encoder)와 해당 벡터로부터 출력 sequence를 얻는 LSTM 1개(decoder)를 사용해 sequence to sequence 문제를 해결한다.
<img src="https://images.velog.io/images/ny_/post/80aaaddf-7a47-4a8a-805c-46cd90ed2b3e/image.png" width=800></p>
<p>WMT 14 dataset English to French translation task의 BLEU score를 측정했을 때, 본 논문에서 제안하는 Seq2Seq이 가장 높은 성능을 보였다. 학습 과정에서 입력 sequence를 거꾸로 넣었을 때 모델 성능이 더 좋았으며, sequence가 긴 경우에도 잘 작동했다.</p>
<blockquote>
<p>LSTM: out-of-vocabulary error
SMT: 33.30 (baseline)
Seq2Seq: 34.81 → 80k vocab,<br>SMT + Seq2Seq: 36.5 (이전에 가장 스코어가 높은 모델은 37.0)</p>
</blockquote>
<h2 id="2-the-model">2. The model</h2>
<h3 id="rnn">RNN</h3>
<img src="https://images.velog.io/images/ny_/post/47fa888d-1297-4378-90df-fb70a0ea41e5/image.png" width=600>

<blockquote>
<p>Recurrent Neural Network(RNN)은 T개의 입력 단어로 이루어진 입력 sequence가 주어졌을 때 T개의 단어로 이루어진 출력 sequence를 생성한다. 한 시점 t에서 hidden state를 구하는 과정은 위의 그림과 같다.</p>
</blockquote>
<img src="https://images.velog.io/images/ny_/post/dd6f223d-48e5-4bb1-8f8f-6bfc5c61d032/image.png" width=600>

<blockquote>
<p>현재 시점(t)의 hidden state는 이전 시점(t-1)의 hidden state(h_t-1)와 현재 시점(t)의 입력값(x_t)을 받아 갱신된다. </p>
</blockquote>
<p>RNN은 입력과 출력의 크기가 다르면 사용하기 어려운 단점이 있다. 이를 해결하기 위한 가장 단순한 방법은 RNN을 사용해 다양한 길이의 입력 sequence를 고정된 길이로 변환할 수 있다. 하지만, 학습에 RNN을 사용하면 long-term dependency 문제가 발생해 본 논문에서는 LSTM 사용을 사용했다.</p>
<h3 id="rnn의-문제점">RNN의 문제점</h3>
<p><strong>1) Long-term dependency(장기 의존성)</strong>
<code>The clouds are in the sky.</code> 에서는 <code>sky</code>를 에측할 때 관련된 정보 <code>clouds</code>가 가까이 위치하기 때문에 많은 문맥을 알지 않아도 마지막 단어가 <code>sky</code>라는 것을 예측할 수 있다. 
하지만, <code>I grew up in France and wanted to be a plumber who the best is in the world and speak fluent French.</code>와 같은 예시에서는 <code>French</code>를 예측할 때는<code>France</code>와 멀리 위치하기 때문에 정답임을 예측하기 쉽지 않다. 
두 번째 예시 처럼 관련된 요소가 멀리 떨어져 있는 경우 sequence에 장기 의존성이 존재한다고 한다.</p>
<p><strong>2) Vanishing/Exploding gradient</strong>
이전 state → 다음 state로 넘어갈 때 gradient를 조금만 작게 해도 gradient가 0에 가깝게 되고, gradient를 조금만 크게 해도 gradient가 너무 커져 gradient를 조절하기 어려운 문제를 말한다.
이를 해결하기 위해 &#39;gradient를 상수로 넘기지 말고 gradient를 조절하는 gate를 달아서 조절하자&#39; 아이디어로 LSTM에서는 gradient를 조절하는 gate는 단순한 activation function이 아니라 하나의 network가 들어있다.</p>
<h3 id="lstm">LSTM</h3>
<img src="https://images.velog.io/images/ny_/post/7106ff1d-00af-420b-8aa9-baa64a4eee8c/image.png" width=700>

<p>RNN은 문장이 길어지면 역전파 시 vanishing gradient 문제 발생한다. LSTM은 RNN의 hidden state에 cell state를 추가해 문장이 길어지면서 발생하는 문제를 개선했다. 후에 attention 개념을 활용해 long-term dependency를 해결한다.</p>
<img src="https://images.velog.io/images/ny_/post/5d31be43-62df-4f5a-a396-758104d1a7ec/image.png" width=600>

<p>Long Short-Term Memory(LSTM)의 목표는 조건부 확률 예측(계산)이다. T개의 입력 sequence가 들어왔을 때 T’개의 출력 sequence가 나올 확률을 계산하며, 이 때 입출력 sequence의 길이는 달라도 된다. 아래 수식은 standard LSTM-LM formulation이다.</p>
<h2 id="3-training-stage">3. Training Stage</h2>
<p>LSTM을 학습하는 과정에서 본 논문은 두 가지 방법을 사용했다.</p>
<h3 id="1-teacher-forcing교사-강요">1) Teacher Forcing(교사 강요)</h3>
<ul>
<li>학습 시 실제 정답 데이터를 사용하는 비율을 설정하는 hyperparameter로 decoder가 잘못 예측한 값을 넣어 또 다른 예측에 사용되면 학습이 원활하게 진행되지 않기 때문에 사용한다.</li>
<li>정답 데이터 사용 비율이 높을수록 학습 속도가 빨라지지만, train data에 overfit될 가능성이 높아진다.</li>
</ul>
<h3 id="2-reversed-source-sentence-as-input">2) Reversed Source Sentence as Input</h3>
<img src="https://images.velog.io/images/ny_/post/0c493bfa-a0a9-4149-8de2-38b8af1e70b9/image.png" width=800>

<ul>
<li>위의 그림처럼 입력 sequence의 순서를 뒤집는 방식으로, <code>the cat is black</code>의 순서인 source문장의 순서를 뒤집어 <code>black is cat the</code>를 입력으로 넣는다. </li>
<li>전체적으로 source와 target간의 거리 변화는 없지만 source의 앞부분 단어와 target의 앞부분 단어가 가까워져 <code>minimal time lag</code>가 감소하고, <code>establishing communication</code>시간이 줄어들어 성능 향상이 있다고 본 논문에서는 추측했다. 또한, 논문에서는 영어-&gt;프랑스어 번역 task를 수행했는데 영어와 프랑스어는 어순이 비슷하기 때문에 문장 앞부분의 단어들의 거리가 가까우면 앞부분 단어 번역을 잘 수행하고, 앞부분 단어 예측을 잘 하면 뒷부분 단어 예측에도 영향을 미치기 때문이라고도 볼 수 있다.</li>
<li>성능 향상: perplexity 5.8 → 4.7, test set BLEU score 25.9 → 30.6</li>
</ul>
<h2 id="4-inference-stage">4. Inference Stage</h2>
<h3 id="1-teacher-forcing-사용x">1) teacher forcing 사용X</h3>
<p>decoder가 예측한 값을 다음 input으로 활용해 예측을 진행한다.</p>
<h3 id="2-beam-search">2) Beam search</h3>
<ul>
<li>Exhaustive search: 모든 경우를 비교해 최고 점수를 선택 → 비효율적</li>
<li>Greedy search: 매번 점수가 높은 것 선택 → 선택을 되돌릴 수 없음</li>
<li>Beam search: 위의 2가지 방법의 단점을 개선한 방법, 매 step마다 가장 가능성이 높은 상위 beam_size개의 partial translation을 선택함. 매번 greedy하게 가장 높은 확률을 가지는 것을 선택하지 않고, 특정 깊이 만큼 더 들어가 출력 문장의 확률이 높은 결과를 선택함</li>
</ul>
<h2 id="5-experiments">5. Experiments</h2>
<ul>
<li>dataset: WMT 14’ English to French dataset중 깨끗한 데이터셋을 일부 선택해 사용했으며, 일반적인 neural language model은 각 단어의 벡터 표현에 의존적이기 때문에 두 언어에 대해 고정된 크기의 단어 사전을 사용했다. 단어 사전에 없는 모든 out-of-vocabulary word는 UNK 토큰으로 처리했다.</li>
<li>WMT 14 dataset: SMT(Statistical Machine Translation) 2014 워크샵에서 공유된 데이터셋으로 4가지 task에 대한 데이터셋을 제공한다. <a href="https://www.statmt.org/wmt14/index.html">(ACL 2014-9th workshop on SMT)</a></li>
<li>160,000개의 input vocab과 80,000개의 output vocab을 사용했으며, 각 단어는 1000차원으로 임베딩, 각 레이어는 1000개의 cell로 구성, 4개의 레이어로 구성된 LSTM을 사용했다.</li>
<li>LSTM을 1층 추가할 때마다 perplexity는 10% 정도 감소했다.</li>
<li>가중치 초기화: -0.08 ~ 0.08 uniform distribution</li>
<li>optimizer: SGD without momentum</li>
<li>learning rate=0.7 → 5 epoch 이후 매 epoch마다 lr을 절반으로 (총 7.5 epoch 학습함)</li>
<li>mini-batch를 랜덤 구성하지 않고, 최대한 비슷한 길이를 가지도록 배치를 구성해 패딩을 최소화해 학습 속도를 높였다.</li>
</ul>
<h3 id="experimental-results">Experimental Results</h3>
<img src="https://images.velog.io/images/ny_/post/5d96d8f5-fd1c-4d31-8b88-20c0972a377d/image.png" width=700>

<blockquote>
<p>앙상블 LSTM을 사용했을 때 최대 34.81 beam_size=2만 사용해도 충분히 높은 성능을 보인다.</p>
</blockquote>
<img src="https://images.velog.io/images/ny_/post/a881b43f-899f-444b-8d8f-18a44dbaeaca/image.png" width=700>

<blockquote>
<p>SMT + LSTM을 사용했을 때 BLEU score 36.5이다.</p>
</blockquote>
<img src="https://images.velog.io/images/ny_/post/cd8351f8-702a-455a-8aa6-ef43107f844f/image.png" width=700>

<blockquote>
<p>LSTM hidden state를 PCA를 활용해 2d 시각화한 모습으로, 같은 의미의 문장끼리 클러스터링 되어있는 것을 볼 수 있다.</p>
</blockquote>
<h2 id="6-evaluation-metric">6. Evaluation Metric</h2>
<h3 id="1-bleu-score">1) BLEU score</h3>
<p>모델의 예측값과 정답 간의 차이를 계산한 값으로 precision, brevity penalty, clipping을 종합해 계산된다.
<img src="https://images.velog.io/images/ny_/post/30196ec2-e3fc-4076-959f-0df4d1d01a54/image.png" width=700></p>
<blockquote>
<ul>
<li>Precision: n-gram을 통한 순서쌍이 얼마나 겹치는지</li>
</ul>
</blockquote>
<ul>
<li>Brevity penalty: 문장 길이에 따른 score 보정</li>
<li>Clipping: 같은 단어가 연속적으로 나올 때 score 보정</li>
</ul>
<h3 id="2-perplexityppl">2) Perplexity(PPL)</h3>
<p>언어 모델을 평가하기 위한 지표로 machine translation, text summarization과 같은 generation task의 성능 비교를 위해 주로 사용된다. <code>perplexed</code>라는 단어는 <code>헷갈리는</code>이라는 뜻으로 PPL은 수치가 낮을수록 언어 모델의 성능이 좋다.</p>
<h3 id="3-n-gram">3) n-gram</h3>
<p>카운트 기반 언어 모델로 이전에 등장한 모든 단어를 고려하지 않고 n개의 단어만 고려한다.</p>
<blockquote>
<ul>
<li>코퍼스에서 n개의 단어 뭉치 단위로 끊어 하나의 토큰으로 간주한다.</li>
</ul>
</blockquote>
<ul>
<li><code>&quot;For dinner I&#39;m making __&quot;</code> 문장에서 빈칸에 들어갈 단어의 확률은 <code>P(burgers|For dinner I&#39;m making)</code> &gt; <code>P(cement|For dinner I&#39;m making)</code> 이다. </li>
<li>문장 W일 확률은 각각 N개의 단어로 이루어질 확률과 동일하다. <code>P(W) = P(w1, w2, ..., wN)</code> </li>
<li>unigram 모델에서는 <code>P(W) = P(w1)*P(w2)*...,P(wN)</code> 이다.<blockquote>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[네이버 부스트캠프 AI Tech 3기]]></title>
            <link>https://velog.io/@ny_/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%94%84-AI-Tech-3%EA%B8%B0</link>
            <guid>https://velog.io/@ny_/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%94%84-AI-Tech-3%EA%B8%B0</guid>
            <pubDate>Sat, 12 Feb 2022 10:20:58 GMT</pubDate>
            <description><![CDATA[<h2 id="지원-동기">지원 동기</h2>
<p>자연어처리를 공부하고 싶었고, 물론 혼자서 토이 프로젝트를 진행할 수 있지만, 나랑 비슷한 수준의 사람을 찾기도 쉽지 않았고, 내 멱살을 잡고 프로젝트를 진행해줄 무언가가 필요했다. 
12월 초반에 지원했고, 지원기간이 1달 조금 넘었던게 인상적이었다. 친구가 2기를 수강하고 있었기에 연말에 모집하는걸 미리 알고있었지만 미루기 대왕인 나는 마감일 하루 전인가 제출했었다... <del>기한 안에 제출한거면 다행인건가 후우ㅜ</del>
나는 이전에 kdt전형으로 수강한 이력(?)이 있어서 일반전형으로 지원했다. 미리 전화해서 물어보면 kdt전형으로 지원할 수 있는 방법이 있을지는 모르겠지만 지원 당시에는 마감일에 쫓겨 그냥 일반전형으로 지원했다. <del>일반전형 50명 뽑는데 무슨 자신감이었는지^^</del></p>
<h2 id="프로세스">프로세스</h2>
<p>지원 절차는 서류 -&gt; AI Test &amp; 1차 코테 -&gt; 2차 코테로 이루어졌다.</p>
<h3 id="서류">서류</h3>
<p>서류 항목은 많지 않았고 지원 동기 &amp; 관련 경험을 작성하는 항목 위주였다. 막학기때 취업을 위해 정리해 놓은 지원서와 깃허브 주소를 제출해 지원서를 작성하는데는 그리 오래 걸리지 않았다. 지원 동기에는 내가 AI분야에 관심을 갖게된 계기와 부스트캠프를 통해 얻고 싶은 것(?)을 썼고, 관련 경험에는 연구실에서 진행한 프로젝트 2개를 설명했다. 서류 합격률이 얼마나 되는지 모르겠지만 프로젝트 하면서 작성한 논문에서 점수를 얻지 않았을까? 하는게 나의 추측이다. <del>작성하다보니 지원서를 어떻게 썼는지 궁금해지는데 외장하드가 연결이 안되서 지금 확인할 수가 없다..고장난건 아니겠지ㅠ</del></p>
<h3 id="ai-test--1차-코테">AI Test &amp; 1차 코테</h3>
<p>AI Test는 부스트코스 홈페이지에서 제공하는 pre-course강의를 들으면 무난하게 풀 수 있는 수준이었고, pre-course 수료증을 제출하면 1차 코테때 가산점을 준다고 한다. 지원자 대부분이 수료증을 제출해 점수가 상향평준화 되지 않았을까....?
1차 코테는 4-5문제 정도였고 엄청 어려운 문제는 안 나왔던거 같은데 그냥 내 구현력이 부족했다. 난이도가 수월했는데 못 풀어서 아쉬움이 많이 남았고 떨어질 것이라 예상했었다. </p>
<h3 id="2차-코테">2차 코테</h3>
<p>당연하겠지만 1차 코테보다 어려웠고 8문제로 시간에 비해 많은 문제가 출제되어서 (물론 내 기준 ㅎㅎ) 욕심 부리지 말고 풀 수 있는 문제 골라서 풀어야 겠다고 생각했다. 대충 1번이 가장 쉽고 뒤로 갈수록 어려워지는 구성이었다. 1번이 문제는 짧은데 도저히 풀이방법이 생각나지 않아 당황스러웠다. 결국 2, 3, 4번은 풀었고 1, 5번은 끄적대다가 제출했다. 당시 내 실력은 백준 실버3/ 프로그래머스 레벨1을 무난히(?) 푸는 수준이었다.
이번 기수부터는 그 전과 다르게 지원할 때부터 CV/NLP/추천 중 희망하는 도메인을 선택해야 했다. 나는 1순위로 NLP, 2순위로 추천을 선택했다. </p>
<h2 id="합격">합격</h2>
<img src="https://images.velog.io/images/ny_/post/46ecc52f-2081-4afa-9504-524c9347cb8e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.17.29.png" width="700">

<blockquote>
<p>2차 코테를 못봤고 합격자 발표날 <strong>아쉽게도..</strong>로 시작하는 이메일을 받아 떨어진줄 알았다. 이 때 나는 졸업논문을 마무리하고 신나게 놀러다녔다 ㅋㅋㅋ 합격전화 받은 날도 여행가다가 전화와서 굉장히 갑작스러웠던 기억이... 원하던 NLP 트랙에 합격해 교육에 참여하기로 했다!</p>
</blockquote>
<img src="https://images.velog.io/images/ny_/post/b046f68b-ec04-43aa-a187-8f6e4cab198b/C26C210B-DD46-4BBE-93B3-7AAFE5BE15D9.jpeg" width="500">

<blockquote>
<p>교육 참여하고 1주일? 정도 있다가 간식이 낭낭하게 들어있는 택배를 받았다~! 튀김우동이 가장 맛있었고 나머지는 가족들에게 빼앗겼지만 작게나마 네이버의 복지를 느껴 행복했다 :D <del>(카카오톡 간식상자였던건 비밀)</del></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Week2 - PyTorch Custom Dataset & DataLoader ]]></title>
            <link>https://velog.io/@ny_/Week2-PyTorch-Custom-Dataset-DataLoader</link>
            <guid>https://velog.io/@ny_/Week2-PyTorch-Custom-Dataset-DataLoader</guid>
            <pubDate>Sun, 06 Feb 2022 13:08:43 GMT</pubDate>
            <description><![CDATA[<h2 id="1-pytorch-dataset-관련-모듈">1. PyTorch Dataset 관련 모듈</h2>
<ul>
<li><code>torch.utils.data</code>: 데이터셋의 표준을 정의, 데이터셋을 불러오고 자르고 섞는데 쓰는 도구들이 들어있는 모듈. 파이토치 모델을 학습시키기 위한 데이터셋의 표준을 <code>torch.utils.data.Dataset</code>에 정의하고 Dataset 모듈을 상속하는 파생 클래스는 학습에 필요한 데이터를 로딩해주는 <code>torch.utils.data.DataLoader</code> 인스턴스의 입력으로 사용할 수 있음. <a href="https://pytorch.org/docs/stable/data.html">torch.utils.data</a></li>
</ul>
<ul>
<li><p><code>torchvision.dataset</code>: <code>torch.utils.data.Dataset</code>을 상속하는 이미지 데이터셋의 모음, MNIST나 CIFAR-10과 같은 데이터셋을 제공함. <a href="https://pytorch.org/vision/stable/datasets.html">torchvision.dataset</a></p>
</li>
<li><p><code>torchtext.dataset</code>: <code>torch.utils.data.Dataset</code>을 상속하는 텍스트 데이터셋의 모음, IMDb나 AG_NEWS와 같은 데이터셋을 제공함. <a href="https://pytorch.org/text/stable/datasets.html">torchtext.dataset</a></p>
</li>
<li><p><code>torchvision.transforms</code>: 이미지 데이터셋에 쓸 수 있는 여러 가지 변환 필터를 담고 있는 모듈입니다. 예를 들어 Tensor로 변환한다던지, 크기 조절(Resize)과 잘라내기(Crop)으로 이미지를 수정할 수 있고 밝기(Brightness)와 같은 값을 조절하는데 사용될 수 있음. 대부분의 transform 함수는 PIL과 tensor 형태의 이미지를 모두 사용 가능하지만, 둘 중 하나만 지원하는 경우도 있으며, tensor 형식이라면 이미지에 batch를 적용할 수 있다. <a href="https://pytorch.org/vision/stable/transforms.html">torchvision.transforms</a></p>
</li>
<li><p><code>torchvision.utils</code>: 이미지 데이터를 저장하고 시각화하기 위한 도구가 들어있는 모듈. <a href="https://pytorch.org/vision/stable/utils.html">torchvision.utils</a></p>
</li>
</ul>
<h2 id="2-dataset의-기본-구성-요소">2. Dataset의 기본 구성 요소</h2>
<ul>
<li><p>Dataset을 구성할 때는 PyTorch의 <code>torch.utils.data</code>에서 <code>Dataset 클래스</code>를 상속해서 만든다. 이렇게 생성된 Dataset 클래스는  <code>__init__</code> 메서드, <code>__len__</code> 메서드, <code>__getitem__</code> 메서드 총 3개의 메서드로 구성된다. 이런 방식은 <code>map-style dataset</code>과 같은 Dataset일때에만 가능하다. <a href="https://pytorch.org/docs/stable/data.html#dataset-types">PyTorch Documentations</a> 참고</p>
<img src="https://images.velog.io/images/ny_/post/cd89d606-480a-4f03-9b43-e45957261041/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.50.05.png" width="200">
</li>
<li><p><code>__init__</code> 메서드
일반적으로 해당 메서드에서는 데이터의 위치나 파일명과 같은 초기화 작업을 위해 동작한다. 일반적으로 CSV파일이나 XML파일과 같은 데이터를 이때 불러온다. 모든 데이터를 메모리에 로드하지 않고 효율적으로 사용할 수 있으며, 이미지를 처리할 transforms들을 Compose해서 정의한다.</p>
</li>
<li><p><code>__len__</code> 메서드
Dataset의 최대 요소 수를 반환하는데 사용된다. 해당 메서드를 통해서 현재 불러오는 데이터의 인덱스가 적절한 범위 안에 있는지 확인할 수 있다.</p>
</li>
<li><p><code>__getitem__</code> 메서드
데이터셋의 idx번째 데이터를 반환하는데 사용된다. 원본 데이터를 가져와 전처리하고 데이터 증강하는 부분이 이루어진다.</p>
</li>
</ul>
<h2 id="3-pytorch-dataloader">3. PyTorch DataLoader</h2>
<p>Dataloader는 모델 학습을 위해서 데이터를 미니 배치(Mini batch)단위로 제공해주는 역할을 한다. <a href="https://pytorch.org/docs/stable/data.html">PyTorch Documentations</a>을 확인해보면 아래와 같이 <code>DataLoader</code>가 정의되어 있고, dataset은 앞서 만든 <code>Dataset</code>을 인자로 넣어주시면 된다. 보통 <code>batch_size</code>나 <code>collate_fn</code>와 같은 인자를 주로 사용한다.</p>
<pre><code>DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
           batch_sampler=None, num_workers=0, collate_fn=None,
           pin_memory=False, drop_last=False, timeout=0,
           worker_init_fn=None)</code></pre><img src="https://images.velog.io/images/ny_/post/db6f6640-6961-4be4-898d-988edcdc34e3/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.05.10.png">

<blockquote>
<ul>
<li>dataset: DataLoader에는 앞서 생성한 Dataset 인스턴스가 들어간다.</li>
</ul>
</blockquote>
<ul>
<li>batch_size: 배치 사이즈를 의미한다.</li>
<li>shuffle: 데이터를 DataLoader에서 섞어서 사용할지 여부를 의미한다.</li>
</ul>
<blockquote>
<ul>
<li>sampler: index를 컨트롤하는 방법으로 데이터의 index를 원하는 방식대로 조정한다. 즉 index를 컨트롤하기 때문에 설정하고 싶다면 shuffle 파라미터는 False(기본값)여야 한다. shuffle은 단순히 섞는 기능이고, sampler는 내가 원하는 규칙대로 섞거나 데이터를 뽑아서 사용하는 기능이다. 홀수 인덱스만 불러오는 기능 등을 구현 가능하고, 불균형한 데이터셋의 비율을 맞출 때 많이 사용된다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>num_workers: 데이터를 불러올때 사용하는 서브 프로세스(subprocess) 개수, context switching 때문에 개수를 늘릴수록 빨라지지는 않는다. 무작정 <code>num_workers</code>를 높인다고 좋진 않다! 데이터를 불러 CPU와 GPU 사이에서 많은 교류가 일어나면 오히려 <code>병목</code>이 생길 수 있다. <a href="https://jybaek.tistory.com/799">참고</a></li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>collate_fn: collate는 “함께 합치다”라는 의미로, map-style 데이터셋에서 sample list를 batch 단위로 바꾸기 위해 필요한 기능이다. zero-padding이나 Variable Size 데이터 등 <code>데이터 사이즈를 맞추기</code> 위해 많이 사용한다. feature는 feature끼리, target은 target끼리 feeding하고 싶을 때가 있음 → NLP에서는 문장마다 길이가 다르기 때문에, 객체검출을 할 때는 한 장의 이미지에 객체 개수가 달라지기 때문에 collate() 함수를 많이 사용한다. <a href="https://deepbaksuvision.github.io/Modu_ObjectDetection/posts/03_01_dataloader.html">참고</a></li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>pin_memory: DataLoader에서  <code>pin_memory=True</code> 이면 Tensor를 CUDA 고정 메모리에 할당시킨다. 고정된 메모리에서 데이터를 가져오기 때문에 데이터 전송이 훨씬 빨라지지만, 일반적인 경우에는 많이 사용하지 않을 argument이다. 자세한 기술적인 내용은 <a href="https://mkblog.co.kr/2017/03/07/nvidia-gpu-pinned-host-memory-cuda/">출처1</a> 및 <a href="https://medium.com/naver-shopping-dev/top-10-performance-tuning-practices-for-pytorch-e6c510152f76">출처2</a><ul>
<li><code>Pageable Memory</code>: Memory 내용(contents)이 DRAM에서 하드디스크 (Secondary Storage Device)로 page out 되거나 반대로 하드디스크에서 DRAM으로 page in이 가능한 메모리를 의미한다. Page in/Page out을 하기 위해서는 CPU (Host)의 도움이 필요하다고 합니다. 보통 OS에서 User Memory Space의 경우 Pageable Memory이다.</li>
<li><code>Non-Pageable Memory</code>: Pageable Memory와 반대로 page in/page out이 불가능한 메모리를 Non-Pageable Memory라 한다. 결과적으로 하드디스크로 데이터를 page out/page in 하는 작업이 필요없다. OS에서 Kernel Memory Space는 보통 Non-Pageable Memory라고 한다.</li>
</ul>
</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>drop_last: batch 단위로 데이터를 불러온다면, batch_size에 따라 마지막 batch의 길이가 달라질 수 있다. batch의 길이가 다른 경우에 따라 loss를 구하기 귀찮은 경우가 생기고, batch의 크기에 따른 의존도 높은 함수를 사용할 때 걱정이 되는 경우 마지막 batch를 사용하지 않을 수 있다.  <code>drop_last=True</code> 이면 마지막 배치를 사용하지 않는다.</li>
</ul>
</blockquote>
<ul>
<li>time_out: 양수로 주어지는 경우 DataLoader가 데이터를 불러오는 시간 제한</li>
<li>worker_init_fn: 어떤 worker를 불러올지 리스트로 전달</li>
</ul>
<h2 id="4-torchvision에서-제공하는-transform">4. torchvision에서 제공하는 transform</h2>
<ul>
<li>torchvision은 항상 PIL 객체로 받아야 한다.</li>
<li>transforms.Resize(): 이미지의 사이즈를 변환</li>
<li>transforms.Resize((200,200))(im)</li>
<li>transforms.RandomCrop(): 이미지를 임의의 위치에서 자름</li>
<li>transforms.RandomRotation(): 이미지를 임의의 각도만큼 회전</li>
<li>transforms.Compose: 여러개의 transforms를 하나로 묶어서 처리 가능</li>
</ul>
<h2 id="5-실습">5. 실습</h2>
<h3 id="1-iris-custom-dataset-만들기">1. Iris Custom Dataset 만들기</h3>
<blockquote>
<p>scikit-learn에서 제공하는 붓꽃 데이터를 이용해서 간단한 Dataset을 만들기</p>
</blockquote>
<ul>
<li><code>__init__</code>메서드: 데이터를 불러오고 변수 X에는 feature를, 변수 y에는 target을 넣는다.</li>
<li><code>__len__</code>메서드: 데이터의 총 갯수를 반환한다.</li>
<li><code>__getitem__</code>메서드: idx가 주어질 때, X와 y를 반환한다.</li>
</ul>
<pre><code class="language-python"># 라이브러리 임포트
import pandas as pd
from sklearn.datasets import load_iris

# 붓꽃 데이터 다운로드
iris = load_iris()
iris_df = pd.DataFrame(iris[&#39;data&#39;], columns=iris[&#39;feature_names&#39;])
iris_df[&#39;target&#39;] = iris[&#39;target&#39;]</code></pre>
<p><img src="https://images.velog.io/images/ny_/post/4b6c0e6d-4c0f-4a17-9175-033e7b0c278f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.17.09.png" alt=""></p>
<blockquote>
<p>붓꽃 데이터셋은 5개의 컬럼씩 150개의 데이터로 이루어져 있다.</p>
</blockquote>
<pre><code class="language-python">class IrisDataset(Dataset):
    def __init__(self):
        iris = load_iris()
        # X에는 feature, y에는 target 
        self.X = iris[&#39;data&#39;]
        self.y = iris[&#39;target&#39;]

        self.feature_names = iris[&#39;feature_names&#39;]
        self.target_names = iris[&#39;target_names&#39;]

    def __len__(self):
        return len(self.X)

    def __getitem__(self, idx):
        X = torch.FloatTensor(self.X[idx])
        y = torch.tensor(self.y[idx])
        return X, y


 dataset_iris = IrisDataset()
 print(len(dataset_iris))  # 150
 print(dataset_iris[0])  # (tensor([5.1000, 3.5000, 1.4000, 0.2000]), tensor(0))</code></pre>
<h3 id="2-titanic-custom-dataset">2. Titanic Custom Dataset</h3>
<blockquote>
<p>Kaggle에서 제공하는 Titanic 데이터를 다운로드 받아서 직접 data/titanic 폴더에 넣고 Custom Dataset과 DataLoader를 만들어본다. 7개의 feature를 사용해 Survived/Dead 예측에 사용되는 데이터셋이다.</p>
</blockquote>
<ul>
<li><code>__init__</code>함수 :  X,y 이외에도 features와 classes 를 포함해서 만들기</li>
<li><code>__getitem__</code>함수 : X,y 반환하되 학습 데이터가 아닐 경우, y를 반환하지 않기</li>
</ul>
<pre><code class="language-python">train = pd.read_csv(&#39;data/titanic/train.csv&#39;)
test = pd.read_csv(&#39;data/titanic/test.csv&#39;)

class TitanicDataset(Dataset):
    def __init__(self, path, drop_features, train=True):
        self.data = pd.read_csv(path)  # dataframe 형태
        self.data[&#39;Sex&#39;] = self.data[&#39;Sex&#39;].map({&#39;male&#39;:0, &#39;female&#39;:1})  # 문자열을 인덱스로 매핑
        self.data[&#39;Embarked&#39;] = self.data[&#39;Embarked&#39;].map({&#39;S&#39;:0, &#39;C&#39;:1, &#39;Q&#39;:2})

        self.train = train
        self.data = self.data.drop(drop_features, axis=1)

        self.X = self.data.drop(&#39;Survived&#39;, axis=1)
        self.y = self.data[&#39;Survived&#39;]

        self.features = self.X.columns.tolist()
        self.classes = [&#39;Survived&#39;, &#39;Dead&#39;]

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        X, y = None, None
        X = self.X.loc[idx]
        if self.train:
            y = self.y.loc[idx]
        return torch.tensor(X), torch.tensor(y)


dataset_train_titanic = TitanicDataset(&#39;./data/titanic/train.csv&#39;, 
                                       drop_features=[&#39;PassengerId&#39;, &#39;Name&#39;, &#39;Ticket&#39;, &#39;Cabin&#39;],
                                       train=True)
dataloader_train_titanic = DataLoader(dataset=dataset_train_titanic,
                                      batch_size=8,
                                      shuffle=True,
                                      num_workers=4,
                                      )</code></pre>
<h3 id="3-ag-news-dataset">3. AG NEWS dataset</h3>
<blockquote>
<p>AG NEWS 데이터를 통해서 직접 자신만의 Dataset 만들기</p>
</blockquote>
<ul>
<li><code>__init__</code>함수 : X,y 이외에도 class와 vocab과 encoder 및 decoder까지 같이 넣기</li>
<li><code>__getitem__</code>함수 : X,y 반환하되, 학습 데이터가 아닐 경우, y를 반환하지 않기</li>
<li><code>_preprocess</code>함수 : 영어와 숫자를 제외한 모든 문자를 제외시키고 영어는 모두 소문자로 변환하기</li>
</ul>
<pre><code class="language-python">BASE_AG_NEWS_PATH = &#39;data/AG_NEWS&#39;
TRAIN_AG_NEWS_PATH = os.path.join(BASE_AG_NEWS_PATH, &#39;train.csv&#39;)
TEST_AG_NEWS_PATH = os.path.join(BASE_AG_NEWS_PATH, &#39;test.csv&#39;)

path = TRAIN_AG_NEWS_PATH
data = pd.read_csv(path, sep=&#39;,&#39;, header=None, 
                   names=[&#39;class&#39;,&#39;title&#39;,&#39;description&#39;])</code></pre>
<p><img src="https://images.velog.io/images/ny_/post/effbae22-c1a5-44d2-b3a6-dd28d6a822fa/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.32.05.png" alt=""></p>
<blockquote>
<p>AG 뉴스 데이터는 100만 개가 넘는 뉴스 기사 모음으로 ComeToMyHead가 1년 넘게 활동하면서 2000개 이상의 뉴스 출처에서 뉴스 기사를 수집했다. ComeToMyHead는 2004년 7월부터 운영되고 있는 학술 뉴스 검색 엔진이다. 데이터셋은 데이터 마이닝(클러스터링, 분류 등), 정보 검색(순위, 검색 등), xml, 데이터 압축, 데이터 스트리밍 및 기타 모든 비상업적 활동에 대한 연구 목적으로 학계에서 제공한다.</p>
</blockquote>
<pre><code class="language-python">class MyAG_NEWSDataset(Dataset):
    def __init__(self, path=&#39;./data/AG_NEWS/train.csv&#39;, train=True):
        tqdm.pandas()
        self._repr_indent = 4
        self.data = pd.read_csv(path, sep=&#39;,&#39;, header=None, names=[&#39;class&#39;,&#39;title&#39;,&#39;description&#39;])
        self.classes = [&#39;World&#39;, &#39;Sports&#39;, &#39;Business&#39;, &#39;Sci/Tech&#39;]
        self.path = path
        self.train = train
        counter = collections.Counter()

        # 내 풀이 - apply()를 사용하면 for문을 사용하지 않고도 한 번에 처리 가능함
        self.X = (self.data[&#39;title&#39;] + self.data[&#39;description&#39;]).apply(self._preprocess)
        self.y = self.data[&#39;class&#39;]
        self.X.apply(str.split).apply(counter.update)

        self.vocab = torchtext.vocab.vocab(counter, min_freq=1)
        self.encoder = self.vocab.get_stoi()
        self.decoder = self.vocab.get_itos()

        # # 해설
        # self.X = (self.data[&#39;title&#39;] + &quot; &quot; + self.data[&#39;description&#39;]).progress_apply(lambda s: self._preprocess(s))
        # self.y = self.data[&#39;class&#39;]

        # self.vocab = list(set([w for s in self.X for w in s.split(&#39; &#39;)])) + [&#39; &#39;]
        # self.encoder = {w:n for n,w in enumerate(self.vocab)}
        # self.decoder = {n:w for n,w in enumerate(self.vocab)}


    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        X = self.X[idx]
        y = None
        if self.train:
            y = self.y[idx]
        return y, X 

    def __repr__(self):
        &#39;&#39;&#39;
        https://github.com/pytorch/vision/blob/master/torchvision/datasets/vision.py
        &#39;&#39;&#39;
        head = &quot;(PyTorch HomeWork) My Custom Dataset : AG_NEWS&quot;
        data_path = self._repr_indent*&quot; &quot; + &quot;Data path: {}&quot;.format(self.path)
        num_data = self._repr_indent*&quot; &quot; + &quot;Number of datapoints: {}&quot;.format(self.__len__())
        num_classes = self._repr_indent*&quot; &quot; + &quot;Number of classes: {}&quot;.format(len(self.classes))

        return &#39;\n&#39;.join([head, data_path, num_data, num_classes])

    def _preprocess(self, s):
        s = re.sub(&#39;[^a-zA-Z0-9]+&#39;, &#39; &#39;, s).lower()
        return s

dataset_train_MyAG_NEWS = MyAG_NEWSDataset(TRAIN_AG_NEWS_PATH, train=True)
dataset_train_MyAG_NEWS.encoder[&#39;hello&#39;]  # 해당 단어에 매핑된 숫자 출력</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Week2 - PyTorch 활용하기]]></title>
            <link>https://velog.io/@ny_/Week2-PyTorch-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ny_/Week2-PyTorch-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 06 Feb 2022 12:28:55 GMT</pubDate>
            <description><![CDATA[<h2 id="8강-multi-gpu-학습">8강. Multi-GPU 학습</h2>
<ul>
<li>GPU vs. Node (하나의 시스템)</li>
<li>Node는 컴퓨터 한 대를 의미하며, “GPU를 사용한다” = 하나의 Node 안에 있는 하나의 GPU를 사용한다.</li>
<li>다중 GPU에 학습을 분산하는 방법에는 모델을 나누는 방법, 데이터를 나누는 방법 2가지가 있다.</li>
</ul>
<h3 id="1-model-parallel-모델을-나누는-것alexnet">1. Model Parallel: 모델을 나누는 것(alexnet)</h3>
<ul>
<li>모델의 병목, 파이프라인 등의 어려움으로 인해 모델 병렬화는 고난이도 과제이다.</li>
<li>sequential1, sequential2를 각각 다른 cuda에 할당한 후에 두 모델을 연결한다.</li>
</ul>
<h3 id="2-data-parallel-데이터를-나누는-것">2. Data Parallel: 데이터를 나누는 것</h3>
<ul>
<li>데이터를 나눠 GPU에 할당한 후에 결과의 평균을 취하는 방법으로 minibatch 수식과 유사하며, 한 번에 여러 GPU에서 수행한다.</li>
<li>PyTorch DataParallel: 단순히 데이터를 분배한 후 평균을 취함, GPU 사용 불균형 문제가 발생함</li>
<li>PyTorch DistributedDataParallel: 각 CPU마다 process를 생성해 개별 GPU에 할당함</li>
</ul>
<h2 id="9강-hyperparameter-tuning">9강. Hyperparameter Tuning</h2>
<ul>
<li>데이터 추가/변경 &gt; 모델 변경 &gt; hyperparameter tuning → 좋은 모델은 정해져있기 때문에 데이터를 바꾸는게 가장 성능을 많이 향상시킴</li>
</ul>
<h3 id="1-hypterparameter">1. hypterparameter</h3>
<ul>
<li>학습할 때 모델이 스스로 학습하지 않아 사람이 지정해주는 파라미터로 learning rate, optimizer, 모델의 크기 등이 있다.<ul>
<li>Grid search: 어떤 값을 찾을 때 일정한 간격으로 바꾸면서 최적의 값을 찾는 것</li>
<li>Random search: 값을 일정하게 찾지 않고 랜덤하게 찾는 것</li>
<li>최근에는 베이지안 기반 기법들을 사용함<img src="https://images.velog.io/images/ny_/post/55ccc7f1-3b13-4805-9466-c3fc7b4ca14b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.18.50.png" width="500">

</li>
</ul>
</li>
</ul>
<h3 id="2-ray">2. Ray</h3>
<ul>
<li>multi-node multi processing을 지원하는 모듈</li>
<li>ML/DL의 병렬 처리를 위해 개발된 모듈로 현재 분산병렬 ML/DL 모듈의 표준이다.</li>
</ul>
<h2 id="10강-pytorch-troubleshooting">10강. PyTorch Troubleshooting</h2>
<ul>
<li>OOM 에러는 iteration을 돌면서 발생하는데, 메모리 이전상황 파악이 어려워 해결하기 어려움</li>
<li>batch size를 줄이고, GPU clean → run 또는 코랩에서는 런타임을 초기화해 해결<h4 id="1-gpuutil">1. GPUUtil</h4>
</li>
<li>nvidia-smi처럼 GPU의 상태를 보여주는 모듈로 iteration마다 캐시가 얼마나 쌓이는지/메모리 사용량을 보여줌.</li>
<li>nvidia-smi는 현재의 스냅샷은 보여주지만 iteration을 돌면서 캐시가 쌓이는건 보여주지 않음.</li>
</ul>
<h4 id="2-torchcudaempty_cache">2. torch.cuda.empty_cache()</h4>
<ul>
<li>GPU상 사용되지 않는 메모리/cache 정리</li>
<li>가용 메모리를 확보할 수 있고 reset 대신 사용하기 좋은 함수, 학습 loop 전에 한 번 사용하는걸 추천함.</li>
<li>del은 관계를 끊어 메모리를 free 상태로 만드는 것으로 메모리를 비우는 empty_cache와는 다름.<h4 id="3-training-loop에-tensor로-축적되는-변수-확인">3. training loop에 tensor로 축적되는 변수 확인</h4>
</li>
<li>tensor로 처리된 변수는 GPU 상의 메모리를 사용하기 때문에 1-d tensor는 파이썬 기본 객체로 변환해 처리하는게 좋음.</li>
</ul>
<h4 id="4-del-명령어를-적절히-사용하기">4. del 명령어를 적절히 사용하기</h4>
<p>필요가 없는 변수는 적절히 삭제하기, 파이썬의 메모리 배치 특성상 loop이 끝나도 메모리를 차지하기 때문이다.</p>
<h4 id="5-가능한-배치-사이즈-실험하기">5. 가능한 배치 사이즈 실험하기</h4>
<ul>
<li>batch size=1로 해서 실험한 후 batch size 늘리기</li>
</ul>
<h4 id="6-torchno_grad-사용하기">6. torch.no_grad() 사용하기</h4>
<ul>
<li>inference 시점에서는 torch.no_grad()을 사용하면 backward propagation이 일어나지 않아 OOM error, 메모리에서 자유롭다.</li>
</ul>
<h4 id="7-다른-에러-메시지">7. 다른 에러 메시지</h4>
<ul>
<li>CUDNN_STATUS_NOT_INIT: gpu를 잘못 설치한 경우</li>
<li>device-side-assert:  cuda와 관련해 OOM의 일종으로 생각할 수 있음</li>
<li><a href="https://brstar96.github.io/shoveling/device_error_summary/">참고: GPU 에러 정리</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Week2 - PyTorch 구조 학습하기]]></title>
            <link>https://velog.io/@ny_/Week2-PyTorch-%EA%B5%AC%EC%A1%B0-%ED%95%99%EC%8A%B5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ny_/Week2-PyTorch-%EA%B5%AC%EC%A1%B0-%ED%95%99%EC%8A%B5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 06 Feb 2022 10:17:44 GMT</pubDate>
            <description><![CDATA[<h2 id="4강-autograd--optimizer">4강. AutoGrad &amp; Optimizer</h2>
<ul>
<li>torch.nn.Module: 딥러닝을 구성하는 Layer의 base class으로 input, output, forward, backward를 정의함, 학습의 대상이 되는 parameter(tensor)를 정의한다.</li>
<li>nn.Parameter: 학습의 대상이 되는 weight를 정의한다.<ul>
<li>Tensor객체의 상속 객체</li>
<li>nn.Module 내에서 attribute가 될 때는 required_grad = True로 설정해 학습의 대상의 되는 Tensor</li>
<li>대부분의 layer에서는 weights 값들이 지정되어 있어 직접 지정할 일은 별로 없음</li>
</ul>
</li>
<li>Backward<ul>
<li>실제 backward는 Module단계에서 직접 지정 가능</li>
<li>Module에서 backward와 optimizer 오버라이딩</li>
</ul>
</li>
</ul>
<h2 id="5강-dataset--dataloader">5강. Dataset &amp; DataLoader</h2>
<img src="https://images.velog.io/images/ny_/post/679f9b10-3225-47e5-a619-758a84befaac/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.15.15.png" width="600">

<blockquote>
<p>데이터셋에 전처리를 수행한 후에 Tensor로 변환한다.</p>
</blockquote>
<h3 id="dataset">Dataset</h3>
<ul>
<li><p>Dataset 클래스: 데이터 입력 형태를 정의하는 클래스, 데이터를 입력하는 방식을 표준화 함, image/text/audio에 따라 다른게 정의된다.</p>
<ul>
<li>init() : 초기 데이터 생성 방법을 지정</li>
<li>len() : 데이터의 전체 길이</li>
<li>getitem() : map-style로 index 값이 주어졌을 때 반환되는 데이터의 형태(X, y)</li>
</ul>
</li>
<li><p>Dataset 클래스 생성 시 유의점</p>
<ul>
<li>데이터 형태에 따라 함수를 다르게 정의</li>
<li>데이터 생성 시점에 모든걸 처리할 필요는 없음, image의 Tensor 변화는 학습에 필요한 시점에 변환(transform 함수 사용)</li>
<li>최근에는 HuggingFace 등 표준화된 라이브러리 사용</li>
</ul>
</li>
</ul>
<h3 id="dataloader">DataLoader</h3>
<ul>
<li><p>DataLoader: 데이터를 모델에 어떻게 feeding할지, Data의 배치를 생성하는 클래스</p>
<ul>
<li>학습 직전 데이터의 변환을 책임</li>
<li>Tensor로 변환 + 배치 처리가 주된 업무/기능</li>
<li>데이터 전처리 코드는 병렬적으로 작성해야 함</li>
</ul>
</li>
<li><p>MNIST 데이터셋 직접 다운받고 dataloader 등 사용하기: <a href="https://pytorch.org/tutorials/beginner/basics/data_tutorial.html">pytorch datasets &amp; dataloader tutorial</a></p>
</li>
</ul>
<h2 id="6강-모델-불러오기">6강. 모델 불러오기</h2>
<ul>
<li>model.save(): 학습의 결과를 저장하는 함수로 architecture와 parameter를 저장한다.</li>
<li>checkpoints: 학습의 중간 결과를 저장해 최선의 결과를 선택, 일반적으로 epoch, loss, metric을 함께 저장한다.</li>
<li>Transfer Learning: 다른 데이터셋으로 만든 모델을 현재 데이터에 적용, 대용량 데이터셋으로 만들어진 모델의 성능이 좋음, backbone architecture가 잘 학습된 모델에서 일부분만 변경해 학습을 수행한다.</li>
<li>NLP는 huggingface가 표준으로 사용된다.</li>
</ul>
<h2 id="7강-monitoring-tools-for-pytorch">7강. Monitoring tools for PyTorch</h2>
<h3 id="1-tensorboard">1. tensorboard</h3>
<ul>
<li>텐서플로우의 프로젝트로 만들어진 시각화 도구로 학습 그래프, metric, 학습 결과의 시각화를 지원한다. PyTorch에도 연결 가능하다.</li>
<li>scalar: metric 등 상수 값의 epoch을 표시</li>
<li>graph: 모델의 computational graph 표시</li>
<li>histogram: weight 등 값의 분포를 표현</li>
<li>image: 예측 값과 실제 값을 비교 표시</li>
<li>mesh: 3D 형태의 데이터를 표현하는 도구</li>
</ul>
<h3 id="2-weight--biases">2. weight &amp; biases</h3>
<ul>
<li>머신러닝 실험을 원활히 지원하기 위한 상용 도구(MLOps의 대표적인 툴)</li>
<li>협업, code versioning, 실험 결과 기록 등을 제공</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Week2 - PyTorch 기본]]></title>
            <link>https://velog.io/@ny_/Week2-PyTorch-%EA%B8%B0%EB%B3%B8</link>
            <guid>https://velog.io/@ny_/Week2-PyTorch-%EA%B8%B0%EB%B3%B8</guid>
            <pubDate>Sun, 06 Feb 2022 08:14:04 GMT</pubDate>
            <description><![CDATA[<h2 id="1강-introduction-to-pytorch">1강. Introduction to PyTorch</h2>
<h3 id="pytorch-vs-tensorflow">PyTorch vs. TensorFlow</h3>
<img src="https://images.velog.io/images/ny_/post/9b85f56f-4b99-4862-9080-422382132b15/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.41.18.png" width="800">

<blockquote>
<ul>
<li>Keras: TensorFlow의 Wrapper</li>
</ul>
</blockquote>
<ul>
<li>TensorFlow: Static graph, define and run
TensorFlow는 그래프를 먼저 정의한 후에, 실행 시점에 데이터를 feed하는 방식. Google꺼라서 production, cloud, multi-gpu 활용에 수월함.</li>
<li>PyTorch: Dynamic computation graph
PyTorch는 실행하면서 그래프를 생성하는 방식, 중간 중간에 값 확인이 가능, pythonic code. facebook에서 개발했으며 디버깅이 수월해 아이디어 구현, 논문에 유용함.</li>
</ul>
<p>(pytorch와 tensorflow를 모두 사용해 보지 않아서 dynamic/static graph의 차이를 아직 잘 모르겠다 ㅠ)</p>
<h2 id="2강-pytorch-basics">2강. PyTorch Basics</h2>
<ul>
<li>PyTorch 핵심 기능: Numpy + AutoGrad + Function</li>
</ul>
<h3 id="1-numpy">1. Numpy</h3>
<p>numpy에는 ndarray라는 객체를, pytorch에서는 Tensor라는 객체를 사용한다.
Tensor 만들기: ndarray → Tensor, list → Tensor 생성 모두 가능하다.
<img src="https://images.velog.io/images/ny_/post/feab1249-5457-4c79-80d4-e41b65350adb/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.44.56.png" width="500"></p>
<blockquote>
<p>Tensor의 type은 numpy와 비슷하지만, GPU 지원 여부가 다르다.</p>
</blockquote>
<ul>
<li><p>view: reshape과 동일한 기능이지만, reshape대신에 view 사용을 권장한다.</p>
<img src="https://images.velog.io/images/ny_/post/9fae52d2-9d66-4a1c-a0d8-8a9e8f38fc61/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.46.07.png" width="550">
</li>
<li><p>reshape은 값을 복사해 다른 메모리를 가리킨다. view는 값을 복사하지 않고 기존에 가리키던 메모리의 형태만 다르게 표현, 동일한 주소의 메모리 값을 바꾸면 같이 변한다.</p>
<img src="https://images.velog.io/images/ny_/post/b1465698-6c54-4efd-9307-1fedbe5503cf/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.47.16.png" width="350">
</li>
<li><p>squeeze: 1인 차원을 제거(압축)</p>
<img src="https://images.velog.io/images/ny_/post/1e698946-464b-48bf-b0b3-6f3e9b98cf9f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.48.33.png" width="400">
</li>
<li><p>unsqueeze: 특정 위치에 1인 차원을 추가, 어느 위치에 추가할지 unsqueeze(dim)을 파라미터로 넣어야 한다.</p>
<img src="https://images.velog.io/images/ny_/post/76714a7e-e542-4b79-829d-96e34186e1f8/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.48.43.png" width="400">
</li>
<li><p>torch.mm( ) 과 torch.dot( )</p>
<img src="https://images.velog.io/images/ny_/post/9a16c4e0-f9d6-4ce6-b7c0-5993613bd0cc/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.48.52.png" width="400">

</li>
</ul>
<blockquote>
<ul>
<li>torch.mm() : 행렬 곱 연산</li>
</ul>
</blockquote>
<ul>
<li><p>torch.dot() : 내접 연산</p>
</li>
<li><p>torch.mm( ) 과 torch.matmul( ) - 결과를 정확하게 보기 위해 matmul보다는 mm을 사용한다.</p>
<img src="https://images.velog.io/images/ny_/post/ca67bcdc-84b3-4dac-9a06-8e4bf88b0a1a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.49.04.png" width="500">

</li>
</ul>
<blockquote>
<ul>
<li>torch.mm() : 행렬 곱 연산, broad casting 지원X</li>
</ul>
</blockquote>
<ul>
<li>torch.matmul() : broad casting 지원</li>
</ul>
<h3 id="2-autograd">2. AutoGrad</h3>
<p>pytorch에서는 backward()함수를 사용하면 자동으로 미분값을 계산해준다. </p>
<img src="https://images.velog.io/images/ny_/post/28b4c5c8-a760-4c22-98af-5afab5aff6f6/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.49.16.png" width="500">

<blockquote>
<p>w에 대한 미분 구하기</p>
</blockquote>
<img src="https://images.velog.io/images/ny_/post/bcd3ddde-07d5-44c7-8742-b4b31ba0413a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.49.25.png" width="500">

<blockquote>
<p>변수가 2개인 편미분 예제</p>
</blockquote>
<h2 id="3강-pytorch-프로젝트-구조-이해하기">3강. PyTorch 프로젝트 구조 이해하기</h2>
<ul>
<li>개발 초기 단계에서는 대화식 개발 과정이 유리함 → 학습과정, 디버깅 등 지속적인 확인 가능</li>
<li>배포 및 공유 단계에서는 jupyter notebook 공유가 어려움 → 쉽게 재현하기 어려움, 실행순서가 꼬임</li>
<li>딥러닝 코드도 하나의 프로그램으로, 개발 용이성 확보, 유지보수 향상이 필요함</li>
<li>pytorch-template 코드 주석 달면서 공부하기</li>
</ul>
<p><strong>references</strong>
<a href="https://wikidocs.net/52846">위키독스 텐서 조작하기</a>
<a href="https://github.com/victoresque/pytorch-template">pytorch-template</a></p>
]]></description>
        </item>
    </channel>
</rss>