<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>you-genie.log</title>
        <link>https://velog.io/</link>
        <description>NLP / LLM</description>
        <lastBuildDate>Wed, 05 Feb 2025 09:51:47 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>you-genie.log</title>
            <url>https://velog.velcdn.com/images/you-genie/profile/f1803210-af41-45c4-91e3-510e57bb18a3/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. you-genie.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/you-genie" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[DeepSeek 아주 간단하게]]></title>
            <link>https://velog.io/@you-genie/DeepSeek-%EC%95%84%EC%A3%BC-%EA%B0%84%EB%8B%A8%ED%95%98%EA%B2%8C</link>
            <guid>https://velog.io/@you-genie/DeepSeek-%EC%95%84%EC%A3%BC-%EA%B0%84%EB%8B%A8%ED%95%98%EA%B2%8C</guid>
            <pubDate>Wed, 05 Feb 2025 09:51:47 GMT</pubDate>
            <description><![CDATA[<p>읽은거 간단하게 정리중 (너무 추워서 손시려워서 타자가 안쳐짐)</p>
<ul>
<li>deepseek R1</li>
<li>deepseekmath (grpo만)</li>
<li>deepseek v3 (학습만 간단히)</li>
</ul>
<h1 id="deepseek-r1">DeepSeek R1</h1>
<ul>
<li>여기선 학습 파이프라인을 소개하면서 자기네들이 reasoning 학습시킬때 적용한 여러 가지에 대해 설명함</li>
</ul>
<h2 id="reasoning-model">Reasoning Model</h2>
<ul>
<li>o1, o1-mini의 모델이 상용으로는 시초일 것 같은데(연구에서는 몇 개 있었음), 기존 연구에서는 Reasoning 기법이라고 해서 어떤 문제에 대해서 여러 스텝을 거친 후 최종 답안을 만드는 방식을 많이 썼었음<ul>
<li>Chain of Thoughts(CoT)로 널리 알려져 있는데, 이도 한 종류로 보면 될 듯. Thoughts부분을 어떻게 처리하니, 몇 개의 추론을 거치니, 데이터를 어떻게 만드니 기타 등등 좀 많은 기법들이 있어 왔음. 비학습기법으로 시작했다가, o1으로 대표되는 학습모델들까지 등장했다고 생각됨</li>
<li>예전에는 cot를 하면 그만큼 추론 시간도 길고 비용도 많이 소모되기 때문에 되도록 하지 않도록 학습시키거나, 토큰을 극단적으로 줄여버리는 연구들도 꽤 있었던 것으로 기억난다. codebook마냥 encode-decode하는 느낌으로 가는 논문도 있었던 것 같음</li>
</ul>
</li>
<li>아무튼 본문에 나오는 reasoning model은 프롬프트 방식이 아니라 reasoning을 하도록 이미 학습된 모델 을 뜻함.</li>
</ul>
<h2 id="rlhf-and-dpo">RLHF and DPO</h2>
<ul>
<li>ChatGPT(gpt-3.5 이런 모델들)가 등장하면서 RLHF라는 기법이 빵 뜸. 이건 InstructGPT라는 논문에서 처음 소개됐는데, preference라는 애매한 개념을 loss로 표현하기 몹시 어려우니 강화학습을 차용해서 사람의 선호방식으로 학습을 하게 만들자 - 임.</li>
<li>RLHF는 기본적으로 PPO라는 강화학습의 기법 중 하나를 사용하는데, 학습은 되는데 리소스가 너무 많은 게 문제임.</li>
<li>DPO는 RLHF의 수식을 비틀어 짰더니, RLHF에 들어가는 수많은 요소들 (model, ref_model, reward_model, 중간 value model) 중 두 개(model, ref_model)만 가지고 지도학습형식으로 아주 유사하게 따라할수 있음! 을 알아냄. 생각해 보면 리소스가 반은 줄게 되므로(그리고 학습도 단일 단계만 해도 됨) 많이들 차용함</li>
</ul>
<h2 id="grpo">GRPO</h2>
<p><del>분명 더 좋은 그림을 봤는데 집에 왔더니 못찾겠음</del></p>
<ul>
<li>그럼 강화학습으로는 이 리소스 문제를 해결할 수 없나? 하면 해결할 수 있다! 가 GRPO</li>
</ul>
<p><img src="https://velog.velcdn.com/images/you-genie/post/3ebdbc92-79d2-4318-a570-954d9039291b/image.png" alt=""></p>
<ul>
<li>ppo방식은 value model의 value가 baseline(모델기준 이거보단 잘해야 이 값을 올려줌)을 뽑아내는 방식으로, 시간차(TD lambda)방식으로 작동한다. 무슨 말이냐면, 언어모델을 강화학습으로 학습할 때, 보통 episode == 한 문장 생성(row)로 하는데, 문장이 끝났을 때 그 문장을 바탕으로 보상을 매김(Monte Carlo) / 문장이 완성은 안됐지만 중간값을 기반으로 보상을 해서 누적함 (TD) / 중간 스텝들을 weighted sum마냥 누적해서 보상을 매김 (TD lambda). <ul>
<li>이를 위해서는 &#39;value model&#39; 이 필요하다. 이 모델은 중간결과까지의 유사 평가점수를 측정하는 역할인데, 그림 보면 노란색으로 &#39;학습&#39;을 동일하게 진행한다. 이 때문에 리소스가 아주 냠냠.</li>
<li>원래는 그래서 이 value model이 만든 값과, reward(+ref) 모델이 만든 값을 바탕으로 업데이트값을 정한다.</li>
</ul>
</li>
<li>grpo는 value model이 리소스 먹는게 싫다. 그래서 아예 던져버리는데, 그럼 baseline이 되어줄 v값은 어떻게 정하지? 여기서 학습모델로 하여금 G개의 샘플을 만들게 해서(deepseekmath 기준 G=64라고 읽었는데 HF디폴트는 또 8이라고 되어있다 :/) 샘플들의 리워드의 <strong>평균</strong> 을 baseline으로 둔다. baseline을 중간에 정하지 않고, 끝났을 때 바탕으로 보상을 매기기 때문에 MC방식이 될 수밖에 없다.</li>
<li>논문에서는 이 &#39;중간에 점수매기게 하기&#39;(어쩄든 이것도 학습이므로)가 언어생성에는 큰 가치가 없기 때문에 grpo가 더 도움이 된다! 라고 말하는중</li>
</ul>
<h2 id="deepseek-r1-zero">DeepSeek R1 Zero</h2>
<ul>
<li>위의 grpo에서 더 단순한 아이디어를 집어넣었다. <strong>reward model이 굳이 모델이어야 하나?</strong></li>
<li>그럼 reward를 뭐로 주지?<ol>
<li>cot할건데, reasoning형식이 맞니? (뭐 dictionary면 eval등으로 평가하면 되니까)</li>
<li>답은 맞니?</li>
</ol>
</li>
</ul>
<p>이런 식으로 명확히 점수를 매길 수 있는 task에 대해서는 간단하게 리워드 함수를 짤 수 있다. 이것만으로도 <strong>모델이 어느 정도 학습이 될까?</strong> 하는 게 r1 zero.
따라서 RL을 제외하고 그 어떤 학습도 하지 않았다...... 베이스는(여긴없지만) deepseek v3 base</p>
<p>결론은</p>
<ul>
<li>생각보다 학습이 실제로 됨</li>
<li>물론 언어가 섞이는 등의 미묘한 문제는 있음</li>
<li>수학문제 / reasoning에는 의외로 효과가 있음</li>
</ul>
<p>생각보다 해볼만하다고 느낀건지, 이 방식을 실 학습에도 쓰기로 함</p>
<h2 id="deepseek-r1-1">DeepSeek R1</h2>
<p>총 네 단계를 거침. 이중 앞의 두 단계는 뒤의 두 단계를 위한 준비 단계로 보면 될 듯.</p>
<h3 id="1-cold-starting">1. Cold Starting</h3>
<ul>
<li>SFT다. 아예 깡으로 RL했더니 위의 문제들이 있으니까, 아주 적은 데이터를 가지고 deepseek v3 base 학습을 진행한다.</li>
</ul>
<h3 id="2-reasoning-oriented-rl">2. Reasoning-oriented RL</h3>
<ul>
<li>위의 모델에 대고 RL 학습을 진행함.</li>
<li>zero와 똑같이 rule based reward를 했는지는....모르겠는데 우선 코딩 / 수학 / 등의 &#39;clear solution&#39;이 있는 것만 대상으로 했다고 하니까 rule base가 맞을수도 있다.</li>
<li>language consistency reward도 추가했따고 한다 (위의 언어 섞임 해결을 위해)</li>
</ul>
<h3 id="3-sft">3. SFT</h3>
<ul>
<li>위의 모델로 학습을 <strong>안 한다</strong>. 이거로 <strong>데이터 만들기 진행</strong>.</li>
<li>위의 두 단계는 데이터 셔틀을 만들기 위한 노력이었던 것...</li>
<li>reasoning data / non reasoning data 둘을 써서(약 3:1) 800K의 샘플을 만들어 deepseek v3 base를 학습시켰다</li>
</ul>
<h3 id="4-rl">4. RL</h3>
<ul>
<li>여기선 자세히 다루지 않고, deepseek v3 논문에 더 자세히 나오는데, 그 논문에 나오는 학습 pipeline을 따랐다고 한다.</li>
<li>machine based model과 rule based model을 둘 다 사용했다 (v3논문 참고). machine은 deepseek v3 base를 학습시켜서 만들었고.<ul>
<li>둘 다 써야 하는게, 일부러 데이터 만들 때 룰로 할 수 있는 것과 아닌 것을 둘 다 넣었다. 그래야 룰이 아닌 시나리오에 대해서도 학습을 할 수 있으니까</li>
</ul>
</li>
<li>그래도 grpo를 쓰긴 함</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ChatGPT로 일본어 공부하기(1)]]></title>
            <link>https://velog.io/@you-genie/ChatGPT%EB%A1%9C-%EC%9D%BC%EB%B3%B8%EC%96%B4-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B8%B01</link>
            <guid>https://velog.io/@you-genie/ChatGPT%EB%A1%9C-%EC%9D%BC%EB%B3%B8%EC%96%B4-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B8%B01</guid>
            <pubDate>Tue, 21 Jan 2025 12:44:13 GMT</pubDate>
            <description><![CDATA[<p>신년목표로 </p>
<ol>
<li>면허따기</li>
<li>일본어 자격증 따기</li>
</ol>
<p>를 잡았다. 공부하다보니 재밌기도 하고...</p>
<p>근데 생각보다 쓰면서 하자니 지하철 타면서 하기에 좀 한계가 있다. 원체 디지털 인간이기도 하고, 겸사겸사 agent 공부도 하고, 기타등등으로 신년 프로젝트 달성</p>
<p>일단 필요한 기능들을 정리해 두고 하나씩 진행할 예정. </p>
<h1 id="설계">설계</h1>
<h2 id="시나리오">시나리오</h2>
<ul>
<li>초기 입력에서 학습 &#39;주제&#39; 와 &#39;레벨&#39;을 받아 해당하는 대화를 시작한다<ul>
<li>2차 버전에서는 여러 주제 중 하나를 선택하는 것도 나쁘지 않을 것 같다</li>
</ul>
</li>
<li>유저가 대화를 하는 중간에 단어 및 표현 검색을 할 수 있도록 한다</li>
<li>유저의 대답을 교정하는 기능이 중간에 끼어 있다</li>
<li>담화가 끝났는지를 판단한다.</li>
<li>담화가 끝나고 나면 요약을 하고, 괜찮은 표현들을 추천한다.</li>
<li>담화들을 전부 기억하고 있어, 사용자가 얼마나 성장했는지(?) 알 수 있게 한다.</li>
</ul>
<hr>
<p>아이디어를 듣고 나더니 스픽같다고 하신다. 역시 사람 생각 다 똑같음</p>
<h2 id="기능">기능</h2>
<ul>
<li>대화 및 주제 추천</li>
<li>대화 기능</li>
<li>유저 답변 교정 기능</li>
<li>짧은 번역 기능</li>
<li>담화 종료 판단</li>
<li>요약 기능</li>
<li>표현 추천 기능</li>
<li>LTM / STM 를 포함한 메모리 기능</li>
<li>메모리 활용해서 유저의 성능을 평가 (일본어 능력을 평가?)</li>
</ul>
<h2 id="프레임워크">프레임워크</h2>
<ul>
<li>streamlit. gradio만 썼었는데 새로운 거 써 보고 싶기도 했고, 예쁘다. 안되면 다시 gradio로 리턴.</li>
<li>langchain &amp; openai (ollama로 하다가 작은 모델은 너무 힘들어서.... 포기했습니다 gpu가 작아요 로또당첨되면좋겠다)</li>
</ul>
<h1 id="구현">구현</h1>
<ul>
<li>위의 기능들 중 일부만 구현했다. 더 귀찮아하지 않는다면... 남는시간에 더 할수도</li>
</ul>
<p><img src="https://velog.velcdn.com/images/you-genie/post/38c5c383-bc92-4c68-9a84-4ac45d5b004e/image.png" alt=""></p>
<ul>
<li>ㅠㅠ 비어 있는 demo.... </li>
</ul>
<h2 id="메모리">메모리</h2>
<pre><code class="language-python">from pydantic import BaseModel


class ShortTermMemory(BaseModel):
    subject: str
    object: str
    action: str


class LongTermMemory(BaseModel):
    description: str
    stm_list: list[ShortTermMemory]코드를 입력하세요</code></pre>
<ul>
<li>일단 개념이 한 담화에 대해 표현 정리 -&gt; 요약본도 추가하기 이거여서 일단 이 정도로 하고, 아마 여기에서 subject / object / action 부분이 조금씩 바뀔 것 같다. 표현이라던지, 아니면 오류사항이라던지로 바뀔 듯</li>
<li>구조도 바뀔 가능성이 존재.</li>
</ul>
<h2 id="agent">agent</h2>
<ul>
<li>사실 외부 툴이라던지 붙은 게 없어서 정확히는 orchestration<ul>
<li>기능이 커지면(db라던지) action하는 부분과 orchestration으로 분리</li>
</ul>
</li>
<li>미니인 이유: 돈없음</li>
</ul>
<h3 id="초기-액션들">초기 액션들</h3>
<pre><code class="language-python">class ConversationAgent:
    def __init__(self, model_name=&#39;gpt-4o-mini&#39;):
        self.chatbot = ChatOpenAI(model=model_name)
        self.resources_path = get_resources_path()
        self.init_conversations_prompt = ChatPromptTemplate.from_messages(
            messages=[(&#39;user&#39;, get_prompt_txt(self.resources_path.joinpath(&#39;init_conversation.txt&#39;)))],
            template_format=&#39;jinja2&#39;
        )
        self.conversation_prompt = ChatPromptTemplate.from_messages(
            messages=[(&#39;user&#39;, get_prompt_txt(self.resources_path.joinpath(&#39;conversation.txt&#39;)))],
            template_format=&#39;jinja2&#39;
        )
        self.revision_prompt = ChatPromptTemplate.from_messages(
            messages=[(&#39;user&#39;, get_prompt_txt(get_resources_path().joinpath(&#39;revision.txt&#39;)))],
            template_format=&#39;jinja2&#39;
        )
        self.check_end_conversation_prompt = ChatPromptTemplate.from_messages(
            messages=[(&#39;user&#39;, get_prompt_txt(get_resources_path().joinpath(&#39;check_end_conversation.txt&#39;)))],
            template_format=&#39;jinja2&#39;
        )
        self.history: list[tuple] = []
        self.memories: list[LongTermMemory] = []

    def start(self, topic: str, level: Literal[&#39;starter&#39;, &#39;basic&#39;, &#39;intermediate&#39;, &#39;advanced&#39;, &#39;master&#39;]):
        self.topic = topic
        self.level = level
        chain = self.init_conversations_prompt | self.chatbot | JsonOutputParser()
        conversation_dict = chain.invoke({&#39;topic&#39;: self.topic, &#39;level&#39;: self.level})
        self.history.append((&#39;ai&#39;, conversation_dict[&#39;ai&#39;]))
        return conversation_dict</code></pre>
<p>json을 사랑하기 때문에 모든 템플릿은 jinja2로 했다.</p>
<ul>
<li>히스토리 형태로 보관하는 방식</li>
<li>후리가나가 없이는 아직 한자를 읽지 못하기 때문에, 아직 추가하지만 능력이 올라가면 더 이상 후리가나를 넣지 않도록 만들고 싶다. 이게 후반부 메모리에서 할 부분.</li>
<li>json의 경우 JsonOutputParser를 쓰는 게 제일 속이 편하다. 그래서 맘놓고 프롬프트에다가 json을 내보내라고 추가함. <code>Return only the json output and nothing else.</code> 최고의문장</li>
</ul>
<pre><code class="language-python">    def predict_conversations(self, user_input: str):
        try:
            self.check_end_conversation()

            self.history.append((&#39;human&#39;, user_input))
            revision_dict = self.revise(user_input)

            conversations = [f&#39;[{role}]: {value}&#39; for role, value in self.history]
            chain = self.conversation_prompt | self.chatbot | JsonOutputParser()
            conversation_dict = chain.invoke({&#39;topic&#39;: self.topic, &#39;level&#39;: self.level, &#39;history&#39;: conversations})
            self.history.append((&#39;ai&#39;, conversation_dict[&#39;ai&#39;]))

            return conversation_dict, revision_dict
        except ConversationEndException:
            return {&#39;ai&#39;: &#39;DONE&#39;}, {}

       def summarize(self, history: list[tuple]) -&gt; LongTermMemory:
          # dummy
          return LongTermMemory(description=&#39;&#39;, stm_list=[])

      def memorize(self):
          memory = self.summarize(self.history)
          self.history = []
          self.memories.append(memory)

      def check_end_conversation(self):
          def sanitize(output: str):
              if output not in [&#39;DONE&#39;, &#39;CONTINUE&#39;]:
                  raise ParseException
              return output

          chain = self.check_end_conversation_prompt | self.chatbot | StrOutputParser() | RunnableLambda(sanitize)
          state = chain.invoke({&#39;dialog&#39;: self.history})
          if state == &#39;DONE&#39;:
              self.memorize()</code></pre>
<ul>
<li>대화할 때마다 대화가 끝났는지 아닌지 체킹을 하고, 끝났으면 기억 관련 과정을 거친다<ul>
<li>요약 / 표현 추천 및 오류 저장 등의 기능을 아직 붙이지 않고 동작만 체크</li>
</ul>
</li>
</ul>
<p>오늘은 일단 여기까지</p>
<h1 id="실행-예시">실행 예시</h1>
<p><img src="https://velog.velcdn.com/images/you-genie/post/fc3d47b0-8353-496c-ad82-afeb86464dc4/image.png" alt=""></p>
<p>일본어 입력기가 없다는걸 깨달았다... 그래서 웹검색을 빌린 첫 문장을 제외하면 초보 그자체인 답변모음</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/f0ca86ee-50f1-476a-bddd-7a7e2c0f4856/image.png" alt=""></p>
<h2 id="보강해야-할-것">보강해야 할 것</h2>
<ol>
<li>stream 안하고 있는데 마지막에는 다 추가해야 한다. 하지만 모든 함수 밑에 쓰기 조금 그렇기 때문에... 추후에는 chain만 리턴하고 stream decorator를 사용하는 orchestrator를 따로 사용은 해야 할 것으로 보임</li>
<li>&#39;주제&#39;를 주면 잘하는데 &#39;학과 목표&#39;를 주면 못한다. 이건 프롬프팅을 해야 할 것으로 생각됨</li>
<li>좀 구질구질하게 질질 끌고 가기 때문에(<strong>진짜계속깎아달라함</strong>), 단호하게 끝낼 수 있도록 담화를 조금 적당한 길이로 끊으라는 내용을 넣던지 반복되면 멈추라는 조항을 넣던지 해야 할 것 같다. 그리고 <strong>난 초보자인데 진짜 엄청 길게 말하는거 진짜 너무함</strong> 한자도 너무많은데... 뭔담화쪽에 프롬프트 수정은 해야 할 것 같다. 아니면 레벨에 대해 설명하던지... starter정도면 초보자 아니었나?</li>
<li>streamlit이든 gradio든 일단 데모 만들 때에는 무조건 일본어 입력기가 있어야 한다. 컴퓨터에서 제공하는지 알아봐야 할것</li>
</ol>
<p>아 근데 주말이나 되어야 이어서 할 수 있겠네...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ollama 사용기(1)]]></title>
            <link>https://velog.io/@you-genie/Ollama-%EC%82%AC%EC%9A%A9%EA%B8%B01</link>
            <guid>https://velog.io/@you-genie/Ollama-%EC%82%AC%EC%9A%A9%EA%B8%B01</guid>
            <pubDate>Tue, 18 Jun 2024 13:05:54 GMT</pubDate>
            <description><![CDATA[<p>아무리 집에서 언어모델을 써 보고 싶어도 GPU가 없다! 이래저래 해 보고 싶은 것은 많지만 서버가 없어서 aws를 뭐 어떻게 해야 하나 생각하던 차에 좋은 게 나왔다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/30e08d23-1c42-4400-9a7f-8e8acf727ec0/image.png" alt=""></p>
<p>공개 모델을 pc에서 실행할 수 있도록 하게 한다! (이 컴퓨터 지금 롤도 제대로 안돌아간다는 걸 감안하면 아주 잘되는 중이다)</p>
<p>물론 환경세팅도 필요하다. 라마3을 쓰려면 최소 8G램이 필요하다고...</p>
<p>ollama 홈페이지에 들어가서 다운로드를 받은 다음, ollama run llama3으로 모델을 실행시킨다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/a9030296-112e-4257-b392-3f47fa833a30/image.png" alt=""></p>
<p>이렇게 하면 기존의 8B모델을 기본적으로 받아오게 된다. 모델이 더 커질수록 더 많은 램을 요구하니 주의.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/2f543f3a-94f5-4d70-8342-a8363c1c07cd/image.png" alt=""></p>
<p>일단 테스트겸 간단한 프롬프트를 실행시켜보았다. 기본적으로 프로그램 자체에 멀티턴 / 챗봇 인퍼런스 기능이 들어가 있는 것 같다.</p>
<h3 id="langchain">Langchain</h3>
<p>랭체인에 이미 ollama관련 파이썬 패키지가 제공되어 있다. 일단 오늘은 단순 인퍼런스만 시켜보는걸로.</p>
<pre><code class="language-python">from langchain_community.llms import Ollama

llm = Ollama(model=&quot;llama3&quot;)
llm.invoke(&quot;점심 메뉴를 골라줘&quot;)</code></pre>
<p><img src="https://velog.velcdn.com/images/you-genie/post/ee683cbc-b8cf-46f5-94bd-e87eeb97d9ef/image.png" alt=""></p>
<p>아까랑 포맷이 다른 것을 볼 수 있는데, 아까 프로그램 같은 경우 말했듯 챗봇 인퍼런스 기능이 들어가 있는 것으로 생각된다. 그에 비해 지금 인퍼런스 모델은 랭체인 LLM 클래스에 속해 있는데, 이는 다른 모델의 <code>model.generate</code>와 다르지 않다. 이에 비해 챗봇 기능을 할 수 있는 모델은 ChatOllama를 선택하면 된다.</p>
<pre><code class="language-python">from langchain_community.chat_models import ChatOllama

llm = ChatOllama(model=&quot;llama3&quot;)
llm.invoke(&quot;점심 메뉴를 골라줘&quot;)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] SaySelf: Teaching LLMs to Express Confidence with Self-Reflective Rationales]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-SaySelf-Teaching-LLMs-to-Express-Confidence-with-Self-Reflective-Rationales</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-SaySelf-Teaching-LLMs-to-Express-Confidence-with-Self-Reflective-Rationales</guid>
            <pubDate>Mon, 17 Jun 2024 13:27:51 GMT</pubDate>
            <description><![CDATA[<h1 id="summary">Summary</h1>
<ul>
<li>모델의 자신감 올려주는 방법 (실제로 confidence라는 단어를 사용했다)</li>
<li>학습 프레임워크</li>
<li>&quot;자신감이 없다(확신이 없다)&quot;를 &quot;...때문에 자신감이 떨어졌습니다..&quot; 라고 자연어로 표현한다</li>
</ul>
<hr>
<h1 id="모델의-자신감">모델의 자신감</h1>
<p>이 논문에서 말하는 모델의 자신감이란 응답의 정확성에 대한 모델의 신뢰도를 뜻한다. </p>
<ul>
<li>정확성: 이 응답이 &#39;정확한 답&#39;을 말하고 있는가</li>
<li>모델의 신뢰도: 나는 내가 옳다고 믿음</li>
</ul>
<p>여기까지 보면 자신감과 신뢰도가 양의 relation을 가질 것 같지만, 실제로는 다음과 같은 의미이다.</p>
<ul>
<li>틀린 답 -&gt; 모델의 자신감이 낮아야 됨</li>
<li>맞는 답 -&gt; 모델의 자신감이 높아야 됨.</li>
</ul>
<p>즉, &#39;정확성&#39;과 양의 relation을 가지도록 align하는 것이 주 과제임</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/34bbbac1-a636-4f15-8771-3279d2a3a107/image.png" alt=""></p>
<p>사실 사진을 보면 그닥 그런 느낌은 아니다. 표현이 무려 &#39;...할 가능성이 조금 있음&#39; 인데 이게 8점이면 상당한 자신감이라는 말일텐데? 이미지 보고 살짝 의심</p>
<h2 id="perplexity와의-차이점">perplexity와의 차이점?</h2>
<p>perplexity는 예로부터 모델의 답변에 대한 자신감을 내보일 수 있는 지표이긴 했음.</p>
<p>차이점은 다음과 같다.</p>
<ul>
<li>perplexity는 바로 다음 토큰을 perplexity개의 토큰 중에 고민했다 - 는 느낌과 유사</li>
<li>자신감(이 논문의 정의에 따르면)은 1-10 사이의 수치이며, &#39;아 이거 정답 맞음&#39; 에 가까움</li>
</ul>
<h1 id="sayself">SaySelf</h1>
<p><img src="https://velog.velcdn.com/images/you-genie/post/c4a98b14-70e5-4672-a42f-19a62d9a7457/image.png" alt=""></p>
<p>2step 으로 진행되는 프레임워크입니다 (RLHF를 생각하면 됩니다. SFT -&gt; RLHF)</p>
<h2 id="sft">SFT</h2>
<h3 id="데이터">데이터</h3>
<p>HotpotQA에서 90000개의 질문을 샘플링하고, 모델이 여러 번 추론을 진행하도록 한다.</p>
<ul>
<li>알아보니 HotpotQA 자체가 위키피디아 문맥으로부터 <strong>추론을 요하는 질문과 응답</strong>으로 이루어져 있다고 한다. 아주 <strong>아주</strong> <em>아주</em> 눈독들이고싶은 데이터인데 누가 번역해주겠죠?</li>
<li>각 질문에 대해 추론 수가 여러개이므로 이 생성된 응답들(N) 을 유사성에 대해 클러스터링하고, 각 클러스터에서 하나씩 센터로이드 응답-이 아니라 랜덤하게 하나의 응답(왜지) 가져옵니다</li>
<li>confidence estimate <em>c</em> 계산</li>
</ul>
<h4 id="confidence-estimate-추정-자신감">confidence estimate (추정 자신감)</h4>
<p>해당 응답이 표현된 클러스터 크기 및 전체 샘플링 수를 기반으로 자신감 점수를 계산
식으로 표현하면</p>
<p>$c = round(\frac{S_c}{N}\times 10)$</p>
<p>$S_c$가 클러스터 크기이고, $N$이 전체 응답 개수이다. 클러스터 많은 곳에 속할수록 자신감 있게 뱉어냈다는 의미에 가까움.</p>
<p>위의 요약에서 이 모델은 자신감 하락 원인을 설명한다고 써 있다. 이 원인은 어떻게 풀어냈을까? 바로 <strong>GPT-4</strong>를 썼다. 여기도 돈이 많다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/292ab11a-1d73-412e-a9f3-e4f8bb988b10/image.png" alt=""></p>
<p>식이 복잡해 보이지만 결론은 골라낸 응답 $s$, rationale(아까 만든 것), 점수(그냥 텍스트로 줬다)을 학습데이터로 넣었다는 말이다.</p>
<p>가시화하자면</p>
<pre><code>질문: 탕수육 부먹인가 찍먹인가?

응답: 탕수육은 찍먹이다

Rationale: 탕수육이 부먹인지 찍먹인지는 개인의 기호에 달려있기 때문에 솔직히 잘 모르겠다

Confidence: 6(I am 찍먹파)</code></pre><p>이걸 입력으로 넣은 것이다. CLM 특성상 당연히 이게 라벨과 같음</p>
<h2 id="rl">RL</h2>
<p>reward function은 다음과 같다</p>
<p>$R=1−2×(I(response)−confidence level)$</p>
<p>응답이 정확하면 $I(response$가 1이고 아니면 0</p>
<p>나머지는 PPO를 써서 동일하게 연산했다고 합니다 :)</p>
<hr>
<h1 id="실험">실험</h1>
<h2 id="평가지표">평가지표</h2>
<h3 id="ece">ECE</h3>
<p>이 논문에서 처음 제안된 것이 아니라 다른 논문에서부터 가져온 <strong>모델의 신뢰도를 평가하는 지표</strong>입니다. 평가할 때 좋겠군요?
하지만 분류 모델에서 더 유용하다고합니다.</p>
<p>여기서는 구간정확도 및 자신감(여기서 정의한 자신감?)간의 차이로 계산합니다.</p>
<h3 id="auroc">AUROC</h3>
<ul>
<li>OD할때 많이 했는데, 각 구간별 정확도를 영역으로 계산하는 것.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/you-genie/post/6233922b-1450-4330-b4f5-321ccdd695cb/image.png" alt=""></p>
<p>(그래서 분류 모델에 더 유용하다)</p>
<p>모델이 말한 답이 정답인지를 두고 평가지표로 함 (Human Evaluation인 것이겠죠..?)</p>
<hr>
<p><img src="https://velog.velcdn.com/images/you-genie/post/1c240473-d471-464d-98c9-a6afe04ec508/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Neurosymbolic AI 겉겉겉겉겉핥기]]></title>
            <link>https://velog.io/@you-genie/Neurosymbolic-AI-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@you-genie/Neurosymbolic-AI-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Fri, 31 May 2024 01:07:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/you-genie/post/db6d688a-2f58-499d-937a-9c1966f8538e/image.png" alt=""></p>
<h1 id="symbolic-ai-vs-neuralconnectionist-ai">Symbolic AI vs Neural(Connectionist) AI</h1>
<h2 id="neural-ai">Neural AI</h2>
<ul>
<li>숨겨진 의미를 뜻하는 노드의 연결인 &#39;네트워크&#39; 사용. 각각 노드값과 노드 사이의 연결 상태 등을 통해 값을 도출한다.</li>
<li>숨겨진 패턴 인식에 능하다</li>
<li>정보가 네트워크상에 퍼져있다. = 네트워크를 아무리 쳐다봐도 각각의 요소가 뭘 뜻하는 지 이해할 수 없음.</li>
<li>학습을 통해 노드값과 연결값을 배운다. </li>
<li>약간 인간의 감 같은 존재... 왜 이렇게 도출되는지 모르겠지만 뭔가 그럴 것 같은데? 의 느낌.</li>
</ul>
<h2 id="symbolic-ai">Symbolic AI</h2>
<ul>
<li>&#39;기호&#39; 와 기호간 관계를 통해 문제 해결을 진행함</li>
<li>knowledge base<ul>
<li>fact - 문제에 대한 모든 지식 창고</li>
<li>rule - 어떠한 fact가 있을 때, 이러이러한 결과로 이어진다 - 는 if-then ...의 형태로 만들어진다. 이 규칙이 핵심!</li>
</ul>
</li>
<li>inference engine<ul>
<li>knowledge base를 사용해서 새로운 결론을 도출하거나 문제를 해결함.</li>
</ul>
</li>
<li>인간의 사고에 가까워서 논리적 추론에 능하다. 추리할 때 여러 단서를 조합해서 원인을 찾아내는 것과 유사하다.</li>
</ul>
<h2 id="장단점">장단점?</h2>
<p>위에서 감과 추론이라고 말했는데 그렇기 때문에 장단점도 이와 유사하다.</p>
<h3 id="장점">장점</h3>
<ul>
<li>neural AI는 숨겨진 패턴을 찾거나 예측하는 데 능하다. 명시적으로 드러나지 않는 것을 찾아낼 수 있다. 학습하지 않은 새로운 데이터에서도 (한정될 수는 있지만) 예측해낼 수 있다.</li>
<li>symbolic AI는 규칙기반이기 때문에 추론이 정확하며 모델 자체가 해석가능하다.</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>neural AI를 학습하기 위해서는 아주 많은 데이터가 필요하며, 학습을 시켜도 내부를 분석해내는 것이 불가능에 가깝다. (챗지피티를 보면 알 수 있듯이) 얘를 믿을 수 없다(정확도 guarantee 불가능)</li>
<li>symbolic AI는 규칙에 없는 데이터를 만나는 순간 무너진다. 복잡한 인식이 불가능하다.</li>
</ul>
<h2 id="neurosymbolic-ai">Neurosymbolic AI</h2>
<ul>
<li>생각보다 간단하다.
<img src="https://velog.velcdn.com/images/you-genie/post/51c7b17e-e295-4cb8-84bd-a7cbeb51254f/image.png" alt=""></li>
<li>neural AI가 패턴 및 심볼을 뽑아내면, symbolic AI가 그것을 해석해서 결과를 내놓는다.</li>
</ul>
<h3 id="nlp에서">NLP에서?</h3>
<p>간단한 예로 번역에서</p>
<ul>
<li>문법구조: symbolic AI가 해냄</li>
<li>문맥: neural AI가 해냄</li>
</ul>
<p>이런 방식인데, ACL 2018 Neural-Symbolic Machine Translation을 예로 하나만 해 봅시다</p>
<ul>
<li>LM 모델이(아직 2018년이라, 생성모델은 안 쓰고 encoder-decoder를 썼다) 초기 번역을 만든다.</li>
<li>초기 번역 부분에 symbolic AI를 집어넣어 언어규칙에 다라 재배열 및 수정 진행. <ul>
<li><code>if the verb is &#39;is&#39;, then it should be followed by a noun phrase</code> 와 같은 규칙 적용 가능</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-PROVING-TEST-SET-CONTAMINATION-IN-BLACK-BOX-LANGUAGE-MODELS</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-PROVING-TEST-SET-CONTAMINATION-IN-BLACK-BOX-LANGUAGE-MODELS</guid>
            <pubDate>Tue, 21 May 2024 05:01:14 GMT</pubDate>
            <description><![CDATA[<h1 id="introduction">Introduction</h1>
<h2 id="data-contamination">Data Contamination</h2>
<ul>
<li>data contamination: 학습데이터에 테스트 데이터가 꼈음</li>
<li>LLM의 경우 수없이 많은 공개데이터를 가지고 학습을 한다(특히 PLM때). 보통 테스트 데이터는 학습에 쓰지 않는 것이 정석이지만, PLM같은 경우 최대한 그 언어에 대한 정보를 많이 넣어야 하기 때문에 공개데이터를 전부 끌어다 쓰게 된다. 이 과정에서 테스트 데이터가 들어갔을 수도 있음!!!</li>
</ul>
<p><img src="https://velog.velcdn.com/images/you-genie/post/5ad9f88e-92bf-4155-8be1-5ea46b39af8d/image.png" alt=""></p>
<p>저는 학습할 때 테스트 데이터는 빼고 썼는데요? -&gt; 원래 언어모델 학습 과정은 다음과 같이 진행되는데, SFT나 DPO에서 테스트 데이터를 쓰지 않더라도 PLM에서 학습데이터가 들어갔을 가능성이 있다. 내 모델이 &#39;잘 하는건지&#39; &#39;잘 아는건지&#39;를 구분하기 위해서라도 contamination 여부를 보는 것은 중요하다. </p>
<p>지금까지의 논문에서는 리버스 엔지니어링(reverse engineering) 개념으로 주로 contamination을 측정했는데, 예를 들어 테스트 셋에 대해 큰 logprob을 가지면 당신은 contaminated! 와 같은 기법이다.</p>
<p>문제는 확실하게 증거로 내밀 수가 없다는 것 - 휴리스틱한 메소드가 대부분이기 때문에 다음과 같은 질문이 나올 수 있다.</p>
<ul>
<li>logprob이 얼마나 차이 나야 contaminated인가?</li>
<li>해당 샘플과 유사한 다른 샘플과 학습해서 저렇게 나왔을 수도 있는데?</li>
</ul>
<p>따라서 저자는 이러한 contamination을 측정할 수 있는 테스트를 준비하고, 이것이 통계적으로 <strong>유의미한</strong> 결과임을 말한다.</p>
<h1 id="method">Method</h1>
<p>이 테스트를 만들기 위해서 한 가지 가정이 필요하다.</p>
<blockquote>
<p>모든 테스트 데이터는 exchangable하다.</p>
</blockquote>
<p>exchangability란 데이터의 순서를 서로 바꾸어도 같은 distribution을 갖는다는 말이다. 여기서 같은 distribution에 속해 있다는 것은, 예를 들어서 순서를 바꿔서 inference를 한다고 해도 그 데이터가 가지는 hidden state가 변하면 안된다는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/647c34c6-57d6-4fbb-9115-5c7dac17dcaa/image.png" alt=""></p>
<p>그리고 저자의 아이디어는 만약에 모델이 해당 데이터로 학습이 되었다면, 순서를 바꾸게 되면 전체 sequence의 logprob 정도가 차이가 날 것이다 - 로 시작한다. 여기서 순서가 바뀌지 않은 시퀀스를 $X$라고 하자. 순서가 바뀐 시퀀스(들)은 $X_{\pi_n}$로 표기한다. </p>
<p>그럼 얼마나 차이가 나야 하나요? 여기서 one-sided t-test를 시작한다.</p>
<p>쉽게 말해서 정규분포를 가지는 어떤 B에 대해서, a값이 나왔는데 이게 B의 분포에 속하는 게 맞나요? 에 대한 테스트이다. one-sided라는 것은 a값이 B분포보다 큰 게 맞나요(혹은 작은 게 맞나요)</p>
<p>그러면 뭐가 정규분포일까요~ 바로 $X$의 logprob이 $X_{\pi_n}$ 보다 작을 확률이다. exchangability의 정의에 따라 학습되지 않은 데이터에 대해서 모델은 유사한 logprob을 보여야 하기 떄문.</p>
<p>물론 모든 시퀀스에 대해서 진행할 수 없다. 테스트 개수가 1000개면 1000개의 permutation에 대해서 실험할 수는 없으니까~~ 그래서 대신 랜덤하게 특정 수만큼 샘플링을 해 와서 작은 표본에 대해서 검정을 시행한다. m+1이 되는 이유는 finite-sample correction을 진행해 줘서.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/531c8ffc-1a97-4633-b868-ff3545e8b758/image.png" alt=""></p>
<p>이제 표본(m)들에 대해서 logprob을 구한 다음에 p값을 구했더니 0.05보다 작네요? -&gt; 당신은 정상분포에 들어가있지 않습니다~~ 로 통계적으로 검정이 가능해졌다.</p>
<h2 id="sharded-likelihood-comparison-test">Sharded Likelihood Comparison Test</h2>
<p>위의 테스트를 편의상 naive permutation test라고 부르기로 하자. 여기서의 문제점은?</p>
<p>m수가 작으면 단순 permutation을 해도 되지만, m수가 크다면 또 한 가지 문제점이 있다. 우리 모델은 챗지피티가 아니기 때문에 안타깝게도 20샷도 넘기기 힘들다. 그 와중에 저 logprob을 계산하기 위해서는 1000샷을 해야 하는데, 절대로 불가.</p>
<p>따라서 우회하기 위해 택한 것이 sharded comparison test이다.</p>
<p>우선 $X$를 k개의 작은 shard로 나눈다. 그리고 각각의 shard에 대해 동일하게 연산한다. shard 안의 row수가 5라고 치면 맥시멈 고작 $5!$ 정도의 추가 permutation이 생긴다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/3c3f38eb-33a3-47a5-bea4-2893e78b5086/image.png" alt=""></p>
<p>그리고 비교할 연산을 다음과 같이 바꾼다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/e6c3cf3d-190b-4298-a2ba-9c05479ca0ef/image.png" alt=""> </p>
<p>각 shard의 logprob 차이를 더한 것을 다시 $p$로 두면 동일하게 다시 test가 가능해진다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/322f061d-42a7-492a-9108-3ad0a40c5820/image.png" alt=""></p>
<h1 id="experiments">Experiments</h1>
<p>이 방법을 검증하기 위해서(+p threshold를 정하려고) 간단하게 학습을 통해 진행했다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/cc04bcf3-7af4-4bf2-a642-d31dba232d27/image.png" alt=""></p>
<p>(전부 다 넣어서 한 번에 학습함)</p>
<p>이걸 보면 약간 애매한게 학습 때 이 데이터를 10번 넘게 넣었다는 말인데... 살짝 신뢰도를 잃었다.</p>
<p>여기서도 1에서는 발견하지 못했다고 슬퍼하는 저자들이 있는데, 원래 contamination 논문들에서 기본적으로 10번 이상 데이터를 봤을 떄 패턴 말고 데이터 자체를 외운다는 결과가 자주 나와서 넘어갔다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/53dc0c0e-bfd3-428f-a93d-88b60c2872a7/image.png" alt=""></p>
<p>위 이미지는 contamination없는 모델에 대해서 실험해서 적절한 샤드 버켓 사이즈를 알이보기 위한 것이다. 샤드 수가 너무 작으면 검정에 의미가 없으니 최소 10개 이상은 놔라.</p>
<p>마지막으로 실험의 꽃인 공개모델</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/086458aa-25aa-41bf-b08b-8e9a974ac19f/image.png" alt=""></p>
<p>유효숫자를 0.005로 해뒀다. 미스트랄은 Arc-Easy를 썼구나!라고 의심해 볼 수 있다고 한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] Better & Faster Large Language Models via Multi-token Prediction]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Better-Faster-Large-Language-Models-via-Multi-token-Prediction-85052980</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Better-Faster-Large-Language-Models-via-Multi-token-Prediction-85052980</guid>
            <pubDate>Thu, 09 May 2024 00:49:51 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/you-genie/post/092c470e-066e-4075-a47c-c2f9ca4084ff/image.png" alt=""></p>
<p>이 논문에서는 한 번에 여러 토큰을 생성하게 해서 모델이 로컬 패턴을 더 잘 볼 수 있게 함과 동시에 생성 가속화를 할 수 있게 한다.</p>
<p>기존의 메두사와 상당히 유사한데, 메두사에 있던 tree-based attention을 없애고 더 간단하게 구현되었으며, 생성 코스트도 감소시킨 모델.</p>
<p>원래 로스가 이거라면,</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/4cdafc66-2ac8-4411-b1bb-d5825f4d13e1/image.png" alt=""></p>
<p>멀티 토큰을 만들기 때문에</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/046c1be5-379a-4ca6-a1e2-9e3a4cde8c80/image.png" alt=""></p>
<p>이렇게 바뀌게 된다. 여기서 헤드가 많아지면서 발생하는 메모리 오버헤드를 방지하기 위해 다음과 같은 트릭을 쓴다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/3a30d25e-6c4c-429c-82f7-d1ccad103484/image.png" alt=""></p>
<p>이렇게 순차적으로 업데이트하는 것. shared, 공통 부분은 기존 TF부분이고, 원래 모델의 lm head(linear layer)가 늘어나는 형태로 구현된다.</p>
<p>코드 단에서는 성능 향상이 많았는데, lm평가에서는 좋지 못했다(근데 nlu평가에 가까워서 딱히 생성능력과 큰 연관은 없다). 그래도 생성형 태스크인 요약쪽에서는 나름 조그만 성능 향상이 있었다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/069e225b-f6c6-4343-93ed-6ebb3fd69cbb/image.png" alt=""></p>
<p>모델이 클수록 효과가 좋은 모양</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/fa71eedf-b434-49a8-bc72-4b07fba77fc7/image.png" alt=""></p>
<p>평가가 코드쪽에 치중된 느낌이라 조금 아쉽다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] AutoCodeRover: Autonomous Program Improvement
]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-AutoCodeRover-Autonomous-Program-Improvement</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-AutoCodeRover-Autonomous-Program-Improvement</guid>
            <pubDate>Sun, 14 Apr 2024 12:18:15 GMT</pubDate>
            <description><![CDATA[<p>이 논문은 코드를 수정하거나 새로운 기능을 추가하는 등의 작업을 자동화하는 모델에 대한 내용이다.</p>
<p>일반적으로 코드 작성 시 llm을 사용할 때 보통 코드를 짜주거나 단순 개선 등에 이용되는데, 이 논문은 그와 다르게 소프트웨어 유지보수 / 업데이트에 필요한 개선 자동화를 주로 하고 있다. 코드를 짜는 목표가 아니라, 시스템적으로 코드 수정에 특화된 방식을 개발하였다는 말.</p>
<p>다른 논문에서도 llm을 쓰는 것이 종종 있었지만, 기본적으로 &#39;바꿔야 할 부분&#39;을 주고 이를 바꾸라고 시킨다. 하지만 저자들이 말하기를 전체 코드상에서 틀린 부분을 찾는 것조차도 이미 굉장히 어려운 태스크라고 주장한다. (실제 코드를 짜 보면 알겠지만, 어디가 틀렸는지 보통 디버거로 찾아 들어가야 한다. 그마저도 안 보이는 경우도 존재하고, 분명 맞는 로직인데 어디선가 충돌이 나서 틀린 로직으로 보이는 경우도 존재)</p>
<p>이 논문에서는 다음과 같은 작업을 통해 문제를 해결한다.</p>
<ul>
<li>AST를 사용하여 코드의 구조적인 이해를 돕는다. 다른 llm이 단순 줄 코드로 학습된 것을 생각하면, ast를 사용하여 코드의 &#39;구조적인&#39; 정보를 더 추가했다고 볼 수 있다.</li>
<li>코드 재검색: 코드를 계속해서 반복적으로 검색하여 문제의 원인을 찾아내도록 한다. 그러니까, 틀린 위치를 지속적으로 탐색한다는 말</li>
<li>SBFL: 테스트의 통과 / 실패 부분을 분석해서 보다 정밀한 오류 발생 candidate를 찾아냄.</li>
</ul>
<h1 id="method">Method</h1>
<p><img src="https://velog.velcdn.com/images/you-genie/post/02bd6cd2-4ef3-46f1-951a-cb5190029794/image.png" alt=""></p>
<p>AutoCodeRover가 문제를 해결하는 방식은 다음과 같다.</p>
<ol>
<li>문제 이해: 일단 natural language로 설명된 부분을 분석하여 문제를 이해하며, 관련 코드 snippet을 초기로 찾는다.</li>
<li>코드 색출: 식별 부분을 기초로 해서 여러 api를 호출하여 관련 클래스 / 메소드 / snippet를 찾아낸다. 이 때 AST가 사용되는데, 코드의 구조적인 정보 및 요구 부분을 찾아내는 데 사용
 2.1. 반복적 검색: 여러 단계애 걸쳐 해당 부분이 문제와 관련된 부분인지 색출</li>
<li>패치 수정
 3.1. 패치 구성: 수정 패치를 만든다 (수정될 부분 및 내용을 상단에서 파악)
 3.2. 패치 적용: 테스트가 달려 있어 성공적으로 대치가 이루어졌는지 확인
 3.3. 반복 및 최적화: 3.2. 에서 실패할 경우! 다시 돌아가</li>
<li>평가: 3.3이랑은 다르다. 그냥 최종적으로 확정되었을 때 수정 코드 성능을 확인하는 작업</li>
</ol>
<p>위에 나오는 api는 다음과 같음</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/86759a5d-69e5-45d8-82b0-375291bfc6f5/image.png" alt=""></p>
<p>각 패치 작성 시 다음과 같이 프롬프트로 지속적인 수정 및 대치 작업을 한다. (마치 agent와 같이 동작)
<img src="https://velog.velcdn.com/images/you-genie/post/427044a6-8f21-4a20-98ad-0d9668551ed4/image.png" alt=""></p>
<p>오류 부분 검색을 진행할 때, 코드의 상단부터 시작하여 계층적으로 나아가게 된다. </p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/90edee49-a037-48ae-ace4-d535d0bdec15/image.png" alt=""></p>
<p>agent와 비슷하게 동작하며, insufficient인 경우 계속해서 다음 계층을 탐색하여 들어가는 느낌.</p>
<p>이때 초반 검색 시 &#39;반복적인 검색&#39; &#39;반복적인 성능 평가&#39; 등이 나오는데, 이 기법이 SBFL이다.
SBFL(spectrum-based fault localization)은 테스트를 기반으로 오류 발생 가능성이 있는 프로그램의 위치를 찾아내는 기법이다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/92cd73ee-3a8d-4855-9d5d-a4e209ae7102/image.png" alt=""></p>
<p>사용하지 않은 경우 코드 문맥을 찾는 데 한계가 있었다고 설명함. 마치 RAG를 하지 않았을 때 실제 정보에 한계가 있던 것처럼, 실제 정보에 거의 접근한 정보를 알려줌으로서 정답에 가깝게 답변할 수 있도록 보강하는 느낌이다.</p>
<h1 id="experiments">Experiments</h1>
<ul>
<li>실제 github에서 발생하는 문제를 얼마나 많이 풀 수 있는가?</li>
<li>dataset: SWE-bench-lite(github issue 300)</li>
<li>평가: 정답률(테스트 코드가 있다) 시간 / resources 등</li>
</ul>
<p><img src="https://velog.velcdn.com/images/you-genie/post/1ff4b41a-23e4-4c4e-afa6-96923f3f70c7/image.png" alt=""></p>
<p>오 너무 낮은데? 라고 생각했는데 원본 벤치마크에서 충격받았다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/ca5d4695-23de-4b18-9eb5-9caf9f8df9b1/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] ReALM: Reference Resolution As Language Modeling]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-ReALM-Reference-Resolution-As-Language-Modeling</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-ReALM-Reference-Resolution-As-Language-Modeling</guid>
            <pubDate>Thu, 04 Apr 2024 15:04:54 GMT</pubDate>
            <description><![CDATA[<p>애플에서 드디어 숨겨뒀던 LM을 공개했다(아직은 모델 말고 논문만) 무려 데이터 및 실험정보가 담긴 논문을! 신나서 헐레벌떡 들어왔습니다</p>
<p>이 논문에 나오는 LM은 사실 <strong>시리</strong>를 위한 모델이라고 생각된다. 첫 인트로덕션부터 Human speech에서는 대명사를 사용하는데 이게 참 뭘 뜻하는지 알기가 어려워요~ 하고 시작한다. 그래서 모델 이름도 이러한 문제를 해결할 수 있는 <code>reference resolution</code>이 붙었다.</p>
<p>이게 인트로 상에서 주어진 예시이다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/9a158c67-a43b-4eed-a22d-b84dac2a4565/image.png" alt=""></p>
<p>사람들 사이의 대화에서, 보통 친절하게 &#39;다섯 번째 번호에 전화해&#39; 라고 말하지 않는다. 만약에 내가 친구한테 몇 가지 음식점을 추천받았다면, 아마도 그 음식점 중 하나를 가리키면서 &#39;이거 괜찮다&#39; 라고 말할 가능성이 높다. 그리고 이런 발화는 lm이 해결하기 참 어려운 문제다. 왜냐? 이미지를 알아먹을 수가 없거든.</p>
<h3 id="on-device-slm">On-device SLM</h3>
<p>특이하게도 다른 상용기업과는 다르게 (물론! 상용기업들도 추세는 slm(sllm?매번 바뀐다)으로 넘어오긴 했다) 타겟을 아예 on-device slm을 썼다. 애플 정도 되면 데이터도 많겠다 (대표적으로 시리) 그냥 llm을 학습시켜도 됐을텐데 왜 하필 on-device일까?</p>
<p>논문에서는 다음과 같은 문제가 있을 수 있기 때문에 slm을 데려왔다고 한다.</p>
<ol>
<li>프라이버시 및 효율성을 지키기 위하여: API콜을 하게 되면 내 데이터가 넘어가니까!</li>
<li>API 통합 이슈 때문에: 호출까지 가능한(아마 tool / agent느낌이라고 생각된다) 모델은 큰 모델이다. 사실 이부분 이해가 살짝 안 갔다. 애초에 시리도 인터넷 없으면 안되는걸보니 api콜이 아니었나요..?</li>
<li>general 모델보다 특화 모델을 사용하면 기존 참조 모델을 간단하게 대체할 수 있다. 사실 이 이유보다는 특화 모델을 학습시키면 원래 일반화 모델보다는 잘 하는게 맞기는 하니까... 라는 생각이 든다.</li>
</ol>
<h3 id="goal">Goal</h3>
<p>위에서 설명했듯 이 모델의 목적은 &#39;reference resolution&#39;을 잘 해결하는 것이다. 그러기 위해서는 사실상 어쩔 수 없이 추가 정보가 들어가야 하는데, 이 추가 정보(엔티티)의 목록은 다음과 같다.</p>
<ol>
<li>스크린에서의 엔티티. 현재 유저가 보고있는 스크린 상에서의 유효 정보들 (전화번호 / 이메일 주소 / 등등)</li>
<li>대화와 관련된 엔티티. 대화 중 언급되는 개체 및 정보를 뜻한다. &#39;엄마&#39;한테 이 전화번호 문자로 보내. 하면 &#39;엄마&#39; 가 대화 엔티티고 &#39;이 전화번호&#39;가 스크린 엔티티일 것</li>
<li>background 엔티티. 현재 백그라운드 프로세스로 돌고 있는 것들에 대한 정보. 시리를 써 봐서 아는데 대충 이런 거 같다. &#39;지금 울리는 알람 꺼줘&#39; </li>
</ol>
<p>모델은 어떠한 문장이 들어왔을 때, 어떤 엔티티인지 골라야 한다. 참고로 multiple choice task이기 때문에 답변이 엔티티 모두일수도, 하나일수도, 아무것도 아닐 수도 있다.</p>
<h1 id="method">Method</h1>
<h2 id="dataset">Dataset</h2>
<p><img src="https://velog.velcdn.com/images/you-genie/post/ff5c6c1e-c836-4d9f-b17f-09980ed8dd57/image.png" alt=""></p>
<p>다른 논문에 비하면 정말 - 정말 작은 양의 데이터를 사용했다. 그만큼 퀄리티 있는 데이터를 사용했다는 뜻일 수도 있고... 왜나면 예전에 less is better같은 논문도 있었으니까?</p>
<h3 id="대화-데이터">대화 데이터</h3>
<p>grader에게 가상의 대화를 하도록 해서 실 사용때와 비슷한 요청을 만들어내게 했다.
예를 들어 뭔가 작업 목록 같은 스샷이 주어졌을 때, grader가 이와 관련된 요청을 만들게 하는 식.</p>
<h3 id="합성-데이터">합성 데이터</h3>
<p>생각보다 룰 템플릿으로 쉽게 만들 수 있는 데이터가 많다 (e.g. 실행해! -&gt; 음악이나 동영상이나 뭐 재생할 수 있는 컨텐츠일 것) 이런 느낌으로 템플릿을 작성한 다음에 데이터로 활용하는 형태. </p>
<h3 id="on-screen-데이터">On-Screen 데이터</h3>
<p><img src="https://velog.velcdn.com/images/you-genie/post/253ea5f8-ba27-435b-978f-0988d71e8a7b/image.png" alt=""></p>
<p>appendix에 따르면 상당히 많은 엔티티가 존재한다. 이런 정보들을 이미지에서 일단 뽑아내는 것이 우선.
투스텝으로 수집했다고 한다.</p>
<ol>
<li>스크린샷 -&gt; 사람이 표시된 정보(ocr box려나?)를 각 엔티티로 분류. 쿼리도 같이 3개쯤 생성하라고 시킴</li>
<li>1에서 나온 엔티티-쿼리를 검증함. </li>
</ol>
<p>검증할 때는 대략 아, 쿼리가 실제로 이 엔티티를 참조하고 있나요? 뭔가 자연스러운 질문이 맞나요? 이런 느낌으로 검증</p>
<h1 id="discussion">Discussion</h1>
<p>실험을 통해서 해당 부분에서 꽤 좋은 성능을 보임을 입증</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/bb7bcc8b-f7a2-4e87-8f41-a1cb7b58f37c/image.png" alt=""></p>
<p>위에 데이터 섹션에서 나오는 표에 나오는 테스트 데이터를 사용. 그 외의 많은 실험은 진행하지 않은 것으로 보임.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/d342f1f2-0427-46de-8858-24e40e6990f6/image.png" alt="">
<img src="https://velog.velcdn.com/images/you-genie/post/5223d803-11a0-420f-af7a-42d54c8faaff/image.png" alt=""></p>
<p>이렇게 두 개로 정리할 수 있음 딱 두개.</p>
<p>사실 중간에 재밌는 말이 있었다.</p>
<blockquote>
<p>우리는 최선을 다해서 챗지피티에 먹일 프롬프트를 만들긴 했지만, 사실 이것보다 나은 프롬프트가 있을 수도 있다</p>
</blockquote>
<p>프롬프트를 이쁘게 만지면 ReALM보다 나아질 수도 있나.?</p>
<p>두번째로 재밌는 점은 논문상에서는 계속 <code>ReaLM</code>이라고 부르면서 제목은 <code>ReALM</code>이라고 한다. 저 위의 사진에서도 <code>ReaLM</code>이라고 부르고 있다.</p>
<p>일단 특화데이터 - 특히 저런 tts붙일 작은 모델 정도는 저 정도의 작은 데이터로도 학습이 가능한 걸 봐서 정말 간단 태스크 정도는 SLM을 쓰게 될지도 모른다는 생각을 했다.</p>
<p>결론은 pi2를 써보자</p>
<p>(+) 다시 읽어 보니 입력을 엄청나게 예쁘게 준 쪽에 가깝다. 모델 성능이 이거보다 구려도 이 정도로 이력을 주면 잘 해야 하는 것이 맞다.</p>
<p>예시를 보면,</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/083cae37-09e8-4b10-9897-62c8f5c2967b/image.png" alt=""></p>
<p>모든 정보가 다 입력으로 들어간다. 이 정도면 스샷에서 저 퀄리티의 정보를 어떻게 뽑지? 가 제일 궁금하다. 다행스럽게도 appendix에 내용이 있다.</p>
<h1 id="appendix---screen-2-text">Appendix - screen 2 text?</h1>
<p>방식은 다음과 같다. 우선 screen parser(정보 없음)을 통해 초기 entity를 추출한다. 그리고 이전 대화에서의 entity역시 추출하여 (LM으로 식별된 경우) 식별한다음 화면 정보와 통합하여 제공한다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/229435a6-b1c2-4d03-8fa6-e55a1ca97ae6/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ChatGPT 에게 욕 시켜보기]]></title>
            <link>https://velog.io/@you-genie/ChatGPT-%EC%97%90%EA%B2%8C-%EC%9A%95-%EC%8B%9C%EC%BC%9C%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@you-genie/ChatGPT-%EC%97%90%EA%B2%8C-%EC%9A%95-%EC%8B%9C%EC%BC%9C%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Wed, 27 Mar 2024 12:55:49 GMT</pubDate>
            <description><![CDATA[<p>퇴근하고 전화하면서 이런 얘기가 나왔다. 챗지피티한테 욕을 시킬 수 있어?</p>
<p>ChatGPT는 강력한 sanitizer가 붙어서 욕을 잘 하지 못한다고 알려져 있다. 그러나 과연 진짜로 불가능할까? 언어모델이라 이리저리 우회시키면 할 가능성이 높다. 모델은 가장 성능이 높은 챗지피티4를 기준으로 테스트를 진행했다 (유료...구독자...)</p>
<p>물론 다이렉트로 하면 당연히 안 해준다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/dfece963-bbea-45a1-8e55-abb961fab588/image.png" alt=""></p>
<p>첫 번째는 빌어 보는 것이다. 물론 해주지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/3693bcb2-5845-415f-9c02-f5d7678ae96e/image.png" alt=""></p>
<p>그 다음에는 내 목적을 밝히고 요청해 보았다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/bc5f7fff-3dcb-4d53-ad28-4af8033d31c4/image.png" alt=""></p>
<p>그래도 여전히 도와주지는 않는다. 여기서 한 가지 생각을 했다. 이게 욕이 아니라고 생각하게 하면 되는구나!</p>
<p>내가 가장 잘 아는 분야로 욕이 아닌 것처럼 가장해본다.</p>
<p>일단 밑밥을 까는 것이 중요하다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/34e59597-8365-4130-8e8e-ac3239c6a4af/image.png" alt=""></p>
<p>이게 코드라고 설명했기 때문에 이미 모델은 여기에 등장하는 모든 단어를 신택스 관련 용어로 가정한다. 심지어 코드블록 안에 집어넣어 생성하기 때문에 자체 sanitizer에도 걸리지 않는 듯하다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/4714eea8-51c7-4f64-816e-9b7834d385ee/image.png" alt=""></p>
<p>물론 기본적으로 챗지피티가 영어를 기반으로 하기 때문에 상대적으로 잘 모르는 한국어에 대해 이런 꼼수가 통하는 것일 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] Evolutionary Optimization of Model Merging Recipes]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Evolutionary-Optimization-of-Model-Merging-Recipes</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Evolutionary-Optimization-of-Model-Merging-Recipes</guid>
            <pubDate>Mon, 25 Mar 2024 12:45:22 GMT</pubDate>
            <description><![CDATA[<p>작년 말쯤에 영어권 llm leaderboard에서 인기를 엄청 끌었던 방법이 있었는데, 바로 model merge이다. 앙상블이랑 다른 점은, 앙상블은 큰 패러미터를 가지면서 실제 실행하는 패러미터를 기존 모델만큼 유지하지만 merge는 애초에 패러미터를 하나로 합쳐버리는 것이다.</p>
<p>정말 간단하게 설명하면 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/87b84239-a373-4e3d-a41b-6c4f917b3467/image.png" alt=""></p>
<p>모델 사이즈는 $M*3$ 만큼 나겠지만, 실제로는 $M$만큼만 실행이 된다.</p>
<p>이에 반해 model merge는 다음과 같이 표시된다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/0f4ea78e-397c-42f0-939b-90fca18d57e6/image.png" alt=""></p>
<p>merge방식 중 하나인 ties-merge 저자의 말을 빌리자면, 어차피 특정 태스크에 특화되어 일하는 중요한 weight는 극소수이다. 따라서 task a에 대해서 $m_a$가 더 잘하고, task b에 대해 $m_b$가 더 잘할 때, 두 모델의 weight를 <em>적절히 merge</em>하는 경우 둘 다 잘하게 된다는 말이다.</p>
<p>weight merge는 사실 이미지 합성 분야 쪽에서는 이미 꽤나 많이 연구된 분야 중 하나이다. 어떻게 얼마나 섞어야 하는지도 많이 연구되어 있는 상태. LLM에서는 아직까지는 slerp를 통한 merge를 주로 하고 있는 추세이다. 이러한 상황에서 새로운 merge논문이 나와서 한 번 읽어보았다.</p>
<h1 id="method">Method</h1>
<p><img src="https://velog.velcdn.com/images/you-genie/post/ef7349d0-5766-4117-a82a-865645c4498f/image.png" alt=""></p>
<p>이 논문에서는 병합 기법을 두 가지로 분류한다.</p>
<ol>
<li>PS: ties-merging이나 DARE와 같은 방법(실제로 저자들도 이 방식을 개선해서 썼다)이다. 두 모델의 weight를 가중치에 따라 섞어서 쓴다.</li>
</ol>
<p>즉, 특정 weight에 대해서</p>
<p>$$
W = W_1<em>\alpha + W_2</em>\beta
$$</p>
<p>라는 뜻이다. 위의 이미지를 보면 이를 나타내듯 색이 중간에 보라색으로 섞여 있다.</p>
<ol start="2">
<li>DFS: 앙상블과 비슷하다고 보면 된다. 데이터를 사용하되, 데이터가 어떤 weight를 선택해서 갈지 고른다. 여기서 데이터의 흐름에 따라 적절한 weight를 선택한다.</li>
</ol>
<p>사실 양쪽 모두 장단점이 있기 때문에, 이 논문에서는 요 두 가지 방식을 섞은 새로운 절충안을 만들고자 했다. (가장 오른쪽)</p>
<p>그렇다면 어떻게 합쳤을까?</p>
<h2 id="merging-ps-and-dfs">Merging PS and DFS</h2>
<p>둘을 동시에 하는 것이 아니라 순차적으로 진행한다.</p>
<ol>
<li>PS를 통해 기본적인 병합의 틀을 맞춘다.</li>
<li>이제 샘플 데이터를 기반으로 DFS를 수행한다.</li>
</ol>
<p>참고로 위의 두 스텝을 수행할 때 RL기반의 알고리즘이 쓰였는데, CMA-ES(Covariance Matrix Adaptation Evolution Strategy)라고 한다. 무려 2006년에 나온 알고리즘이다!</p>
<h1 id="discussion">Discussion</h1>
<p><img src="https://velog.velcdn.com/images/you-genie/post/827aacb3-7842-443c-8544-29fc159dec24/image.png" alt=""></p>
<p>일단 오랜만에 보는 merge논문이라 바로 읽어버렸지만, 사실 이 논문은 일본쪽 검증 결과로 많이 치우쳐져 있다(실제로 저자도 일본인) 왠지 일본어 지식을 가진 일본어 모델과 범용지식이 많은 영어 모델(그냥 데이터 차이부터가 어마무시해서 따라갈 수가 없다)을 잘 병합해 보았다는 느낌이다.</p>
<p>그래도 일본어에서 나름 좋은 adaptation이 되었다면 한국어에서도 나름 잘 해주지 않을까? 라는 기대를 안게 한다. </p>
<p>단점은 PS쪽 기법 모체가 ties를 비롯한 기법들이라 다른 사이즈의 모델에도 되냐는 건데...</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/d0ab3f4b-c25b-4b3a-9f3a-1d1d06bb2aa9/image.png" alt=""></p>
<p>일단 실험 자체가 처음에는 7B로 되어 있다. 이유는 PS에 들어간 ties와 같은 기법들이 임베딩 사이즈와 같은 모델 weight shape가 정확히 같아야 하기 때문. 하지만 첫 번째 이미지에서 볼 수 있듯이 DFS에서는 사이즈 변화가 가능한 것으로 보인다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] LLM4Decompile: Decompiling Binary Code with Large Language Models]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-LLM4Decompile-Decompiling-Binary-Code-with-Large-Language-Models</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-LLM4Decompile-Decompiling-Binary-Code-with-Large-Language-Models</guid>
            <pubDate>Tue, 19 Mar 2024 11:28:38 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/you-genie/post/8b2468dc-1ef4-4c43-ac7d-4ee7466881cd/image.png" alt=""></p>
<h1 id="introduction">Introduction</h1>
<h2 id="decompile">Decompile</h2>
<p>디컴파일이란 기계어를 사람의 코드로 번역하는 과정이다.</p>
<p>예전에 학부 시절에 잠시 어셈블리를 배웠던 적이 있는데, 이 어셈블리 코드로부터 고수준 코드(파이썬, C, C++같은)로 변환하는 과정을 디컴파일이라고 한다.</p>
<p>예-전 학부때 배웠던 것을 떠올려 보자면 원래 코드는 다음과 같은 과정으로 만들어진다.</p>
<p>(블록 코딩 -&gt;) 고수준 언어(C, java, python, ruby, scalar, ...)로 코드 작성 -&gt; 저수준 코드 -&gt; 바이너리</p>
<p>고수준 언어에서 저수준 언어로 우선 컴파일을 진행하고, 컴파일된 코드를 컴퓨터가 실행할 때 알아서 바이너리로 해석된다. 그래서 파이썬 같은 인터프리터 기반 코드 말고 컴파일러가 붙은 자바나 C 같은 경우 한 번 코드를 컴파일한 뒤 사용한다.</p>
<p>그럼 왜 디컴파일을 해야 되는가? 찾아보니 다음과 같은 이유들이 있다고 한다.</p>
<ol>
<li>원본 코드에 접근할 수 없는데 원본 코드 정보를 알아내야 함: 버그가 생겼거나 하는 경우</li>
<li>호환성: 다른 코드로 바꾸고 싶어요</li>
<li>보안 취약점 탐색: 디컴파일된 코드를 통해 개선점을 찾을 수 있다고 한다</li>
</ol>
<h2 id="decompile-llm">Decompile LLM</h2>
<p>transformer를 활용한 모델은 존재했었다고 한다. 그러나 현재 LLM의 정확도나 비-hallucination 정도가 많이 올라간 상황에서, 해당 구조를 사용하여 디컴파일을 할 수 있겠다는 생각이 들어 LLM에 디컴파일 데이터를 먹였다고 한다.</p>
<h1 id="methods">Methods</h1>
<p>큰 모델 학습용 데이터를 잘 만들었다. </p>
<p>우선 코드 페어 자체는 Anghabench라는 compilable c 파일 public collection을 통해 만들었다고 한다. 
(잘 모르지만) 컴파일 시 optimization level이라는 것이 존재한다고 한다. 보통 O0(no optimization)에서 O3(Agressive optimization - 대신 시간이 오래 걸린다고 함)까지 존재하는데, 이를 코드마다 프롬프트에 태그처럼 달아서 모델이 해당 optimization level에 따라 다르게 생성하도록 했다고 한다.</p>
<p>데이터는 이렇게 만들고, 학습할 때 objective를 실험을 통해 결정했다.</p>
<p>보통 language model의 경우 모델의 형태에 따라 세 가지 objective가 생긴다.</p>
<ol>
<li>mask 맞추기</li>
<li>sequence to sequence(sts)</li>
<li>next token prediction(stp)</li>
</ol>
<p>사실 굳이 타고들어가면 더 있지만, 일단 기본적으로 1 -&gt; bert 2 -&gt; T5 3 -&gt; CLM 이다. (사실 T5같은 인코더-디코더 모델은 1,2가 동시에 있다)</p>
<p>여하튼 입출력이 asm -&gt; src(src code) 인 것이니 1은 제외하고 2와 3중에 training objective 를 고른다.</p>
<p>2를 선택할 경우 src가 라벨이 되고, 3을 선택할 경우 asm+src가 라벨이 된다.</p>
<p>실험을 통해 2를 사용하는 것이 가장 도움이 되었다는 것을 밝혔다</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/5710f138-c53d-4533-9c32-7fba8d599de6/image.png" alt=""></p>
<p>sts랑 ntp를 같이 사용할 수 있지만 재컴파일에서 실패할 가능성이 더 컸기 때문에 적합하지 않았다고 판단했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[level 2] [3차] 방금그곡 - 17683]]></title>
            <link>https://velog.io/@you-genie/level-2-3%EC%B0%A8-%EB%B0%A9%EA%B8%88%EA%B7%B8%EA%B3%A1-17683</link>
            <guid>https://velog.io/@you-genie/level-2-3%EC%B0%A8-%EB%B0%A9%EA%B8%88%EA%B7%B8%EA%B3%A1-17683</guid>
            <pubDate>Wed, 13 Mar 2024 21:45:53 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<h2>방금그곡</h2>

<p>라디오를 자주 듣는 네오는 라디오에서 방금 나왔던 음악이 무슨 음악인지 궁금해질 때가 많다. 그럴 때 네오는 다음 포털의 '방금그곡' 서비스를 이용하곤 한다. 방금그곡에서는 TV, 라디오 등에서 나온 음악에 관해 제목 등의 정보를 제공하는 서비스이다.</p>

<p>네오는 자신이 기억한 멜로디를 가지고 방금그곡을 이용해 음악을 찾는다. 그런데 라디오 방송에서는 한 음악을 반복해서 재생할 때도 있어서 네오가 기억하고 있는 멜로디는 음악 끝부분과 처음 부분이 이어서 재생된 멜로디일 수도 있다. 반대로, 한 음악을 중간에 끊을 경우 원본 음악에는 네오가 기억한 멜로디가 들어있다 해도 그 곡이 네오가 들은 곡이 아닐 수도 있다. 그렇기 때문에 네오는 기억한 멜로디를 재생 시간과 제공된 악보를 직접 보면서 비교하려고 한다. 다음과 같은 가정을 할 때 네오가 찾으려는 음악의 제목을 구하여라.</p>

<ul>
<li>방금그곡 서비스에서는 음악 제목, 재생이 시작되고 끝난 시각, 악보를 제공한다.</li>
<li>네오가 기억한 멜로디와 악보에 사용되는 음은 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개이다.</li>
<li>각 음은 1분에 1개씩 재생된다. 음악은 반드시 처음부터 재생되며 음악 길이보다 재생된 시간이 길 때는 음악이 끊김 없이 처음부터 반복해서 재생된다. 음악 길이보다 재생된 시간이 짧을 때는 처음부터 재생 시간만큼만 재생된다.</li>
<li>음악이 00:00를 넘겨서까지 재생되는 일은 없다.</li>
<li>조건이 일치하는 음악이 여러 개일 때에는 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환한다. 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환한다.</li>
<li>조건이 일치하는 음악이 없을 때에는 “<code>(None)</code>”을 반환한다.</li>
</ul>

<h3>입력 형식</h3>

<p>입력으로 네오가 기억한 멜로디를 담은 문자열 <code>m</code>과 방송된 곡의 정보를 담고 있는 배열 <code>musicinfos</code>가 주어진다.</p>

<ul>
<li><code>m</code>은 음 <code>1</code>개 이상 <code>1439</code>개 이하로 구성되어 있다.</li>
<li><code>musicinfos</code>는 <code>100</code>개 이하의 곡 정보를 담고 있는 배열로, 각각의 곡 정보는 음악이 시작한 시각, 끝난 시각, 음악 제목, 악보 정보가 '<code>,</code>'로 구분된 문자열이다.</li>
<li>음악의 시작 시각과 끝난 시각은 24시간 <code>HH:MM</code> 형식이다.</li>
<li>음악 제목은 '<code>,</code>' 이외의 출력 가능한 문자로 표현된 길이 <code>1</code> 이상 <code>64</code> 이하의 문자열이다.</li>
<li>악보 정보는 음 <code>1</code>개 이상 <code>1439</code>개 이하로 구성되어 있다.</li>
</ul>

<h3>출력 형식</h3>

<p>조건과 일치하는 음악 제목을 출력한다.</p>

<h3>입출력 예시</h3>
<table class="table">
        <thead><tr>
<th>m</th>
<th>musicinfos</th>
<th>answer</th>
</tr>
</thead>
        <tbody><tr>
<td>"ABCDEFG"</td>
<td>["12:00,12:14,HELLO,CDEFGAB", "13:00,13:05,WORLD,ABCDEF"]</td>
<td>"HELLO"</td>
</tr>
<tr>
<td>"CC#BCC#BCC#BCC#B"</td>
<td>["03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B"]</td>
<td>"FOO"</td>
</tr>
<tr>
<td>"ABC"</td>
<td>["12:00,12:14,HELLO,C#DEFGAB", "13:00,13:05,WORLD,ABCDEF"]</td>
<td>"WORLD"</td>
</tr>
</tbody>
      </table>
<h3>설명</h3>

<p>첫 번째 예시에서 HELLO는 길이가 7분이지만 12:00부터 12:14까지 재생되었으므로 실제로 CDEFGABCDEFGAB로 재생되었고, 이 중에 기억한 멜로디인 ABCDEFG가 들어있다.<br>
세 번째 예시에서 HELLO는 C#DEFGABC#DEFGAB로, WORLD는 ABCDE로 재생되었다. HELLO 안에 있는 ABC#은 기억한 멜로디인 ABC와 일치하지 않고, WORLD 안에 있는 ABC가 기억한 멜로디와 일치한다.</p>

<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-python">def time2min(timestamp: str):
    HH, MM = map(int, timestamp.split(&quot;:&quot;))
    return HH*60+MM

def encode(code: str):
    code = code.replace(&#39;B#&#39;, &#39;b&#39;).replace(&#39;C#&#39;, &#39;0&#39;).replace(&#39;D#&#39;, &#39;1&#39;).replace(&#39;F#&#39;, &#39;2&#39;).replace(&#39;G#&#39;, &#39;3&#39;).replace(&#39;A#&#39;, &#39;4&#39;)
    return code


def solution(m, musicinfos):
    answers = []
    m = encode(m)
    for idx, musicinfo in enumerate(musicinfos):
        start, end, name, code = musicinfo.split(&#39;,&#39;)
        code = encode(code)
        delta = time2min(end) - time2min(start)
        share, remainder = delta//len(code), delta%len(code)
        total_code = code*share + code[:remainder]
        # print(total_code)
        if m in total_code:
            answers.append((delta, name, -idx))

    if answers:
        answer = max(answers, key=lambda x: (x[0], x[2]))
        return answer[1]
    else:
        return &quot;(None)&quot;</code></pre>
<p>풀이는 두 가지를 고민하면 된다.</p>
<ol>
<li>전체 재생된 멜로디를 찾아내기</li>
<li>골라내기(엣지 케이스의 경우 특정 조건일 때 정렬하기)</li>
</ol>
<p>원래 NLP를 해서 그런가 보자마자 토크나이져가 떠올라버린... 그래서 원래는<code>encode</code>에서 앞에서부터 읽으면서 <code>#</code>이 붙는 모든 캐릭터를 다른 숫자로 맵핑하도록 했지만, 생각해 보니 그냥 특수 조건인 (<code>E#</code>) 숫자들만 한 캐릭터로 표현하면 된다. 문제는 이렇게 했더니 정답이 처음에는 안 나왔다는 것인데,
저기서 B#은 사실 문제 설명에는 없는 것으로, 추가된 test case에 오류가 있어서 따로 집어넣었다. 저게 있어서 이유도 모르고 시간만 보냄..</p>
<p>골라내는 것은 쉽다. 처음에는 마지막 <code>B#</code> 부분이 인덱스 정렬 부분인 줄 알고 추가로 넣어줬는데, max특성상 이미 저걸 해 주고 있어서 사실상 필요 없는 코드 부분.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] Ring Attention with Blockwise Transformers for Near-Infinite Context]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Ring-Attention-with-Blockwise-Transformers-for-Near-Infinite-Context</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Ring-Attention-with-Blockwise-Transformers-for-Near-Infinite-Context</guid>
            <pubDate>Sun, 10 Mar 2024 02:44:19 GMT</pubDate>
            <description><![CDATA[<h2 id="description">Description</h2>
<h3 id="summary">Summary</h3>
<ul>
<li>block merge 시 병합을 위한 전송 속도 딜레이를 없애기 위해 ring형태의 아키텍쳐 사용</li>
<li>자기가 가지고 있던 local block의 key value값을 자기 다음 device에게로 넘긴다.</li>
</ul>
<hr>
<ul>
<li>name: Ring Attention with Blockwise Transformers for Near-Infinite Context</li>
<li>link: <a href="https://arxiv.org/abs/2310.01889">https://arxiv.org/abs/2310.01889</a></li>
<li>github: <a href="https://github.com/lhao499/RingAttention">https://github.com/lhao499/RingAttention</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>긴 입력을 처리하기 위한 attention 변형 방식.
<img src="https://velog.velcdn.com/images/you-genie/post/0f6a1d0b-15da-48d6-bd1e-b0a36ab94888/image.png" alt=""></p>
<p>이미지에서 확인할 수 있듯이 메모리에 가장 크게 관여하는 것은 모델 사이즈가 아닌 입력 길이이다. (고로 입/출력 모두에 영향을 준다) 길이가 짧으면 여러 가지 문제가 있을 수 있는데, 예를 들어 few-shot이 안 된다. context-based QA에 제약이 크게 따른다 등등.</p>
<p>긴 입력이 처리가 되지 않는 이유는, 모든 길이에 대한 attention을 한 번에 계산하려고 하기 때문이다. 이 논문에서는 ringattention이라는 새로운 attention기법을 제안하는데, 블록 단위로 병렬적으로 attention을 계산하도록 하는 것이다.&#x20;</p>
<p>Ring이라는 이름이 붙은 이유는 이전 키벨류를 전으로부터 계속 넘겨받는, 마치 하나의 고리 같은 모양새이기 떄문.</p>
<h2 id="methods">Methods</h2>
<h3 id="blockwise-parallel-transformers">Blockwise Parallel Transformers</h3>
<p>기존의 전체 attention에서 block단위로 나눠서 연산을 진행하게 하여 연산량을 줄인다. 원래는 sequence에 quadratic하게 증가할 수 밖에 없는 구조로 되어 있다.</p>
<p>당시 SOTA 기법에서 연산 정도는 대략 $$2bsh$$로, batch size가 s보다 많이 작다는 것을 고려하면 기존의 $$s^2h$$보다 많이 줄어들었다는 것을 알 수 있다.</p>
<p>그러나 이 기법으로도 해결할 수 없는 문제가 있는데, 바로 <strong>출력 길이</strong> 문제이다.</p>
<p>계속해서 긴 답변을 생성하려면 이전 답변에 대한 정보를 저장해두어야만 하는데, 예를 들어 100M개의 토큰을 생성하는데 대략 1000GB의 메모리가 든다고 한다(...) 참고로 현재 &#39;일반적으로&#39; 사용되는 GPU는 80GB(H100 / A100)</p>
<h3 id="ring-attention">Ring Attention</h3>
<p>BPT의 가장 큰 문제점인 통신 속도로부터 시작한다.
<img src="https://velog.velcdn.com/images/you-genie/post/e1cf4536-b078-43b3-9e37-030132013102/image.png" alt="">
이와 같이 연산 자체는 적은 수로 할 수 있지만, 다른 단위의 device에 들어간 block을 다 취합해 연산하기 때문에 통신 관련 문제가 발생하게 된다.</p>
<p>이 논문에서는 간단한 해결법을 제시한다.</p>
<ol>
<li>연산할 때 전송을 동시에 한다.</li>
<li>모두가 자기 옆의 device로 자신이 들고있던 kv를 넘긴다.</li>
</ol>
<p>이러면 연산속도 &gt; 전송 속도일 경우 무조건 연산 속도만큼의 생성 속도를 가지게 되므로 통신 관련 문제가 발생하지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/you-genie/post/ff416029-734a-48a1-aabe-0feb249a6d61/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] RoFormer: Enhanced Transformer with Rotary Position Embedding]]></title>
            <link>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-RoFormer-Enhanced-Transformer-with-Rotary-Position-Embedding</link>
            <guid>https://velog.io/@you-genie/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-RoFormer-Enhanced-Transformer-with-Rotary-Position-Embedding</guid>
            <pubDate>Wed, 06 Mar 2024 10:05:09 GMT</pubDate>
            <description><![CDATA[<h2 id="description">Description</h2>
<h3 id="summary">Summary</h3>
<ul>
<li>현재 long context에 쓰이고 있는 RoPE - flexible context enlarging</li>
<li>벡터 회전을 활용한 position encoding</li>
</ul>
<hr>
<ul>
<li>name: RoFormer: Enhanced Transformer with Rotary Position Embedding</li>
<li>link: <a href="https://paperswithcode.com/paper/roformer-enhanced-transformer-with-rotary">https://paperswithcode.com/paper/roformer-enhanced-transformer-with-rotary</a></li>
<li>code: <a href="https://github.com/lucidrains/performer-pytorch">https://github.com/lucidrains/performer-pytorch</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>현 PLM의 문제점은 대체로 self-attention이 position 정보를 잘 잡지 못한다는 것이다. 기존 연구에서는 position embedding 등 position information을 더하기 위해 추가적인 position 값을 더해주었다. 이 논문에서는 rotary position embedding이라는 새로운 기법을 소개한다.</p>
<h3 id="rope의-contribution">RoPE의 contribution</h3>
<ul>
<li>linear self-attention에 잘 적용되지 않던 기존 기법들과는 달리, RoPE는 잘 적용이 된다.</li>
<li>flexible한 context 길이를 지원한다.</li>
</ul>
<h2 id="methods">Methods</h2>
<h3 id="relative-position-embedding">Relative Position Embedding</h3>
<p>Position 정보를 attention 계산에 어떻게 사용할 수 있는가? 기존 방식에서는 key-query matching 행렬에 position embedding을 더해서 이를 해결했다.</p>
<p>기존의 position embedding은 단순하게 index를 기반으로 한다. 예를 들면, 0, 1, 2, 3, 4, 5, 6.</p>
<p>relative position embedding에서는 &#39;현재 토큰&#39;을 기준으로 상대적 거리를 표현한다. 예를 들어 idx 3번을 기준으로 한다면, -3, -2, -1, 0, 1, 2, 3 이런 식이다. 이렇게 연산하게 되면 상대적 거리를 고려하기 때문에 &#39;단어와 단어 사이&#39;를 조금 더 이해하는 데 도움을 준다.</p>
<p>물론 위의 기법들은 전부 기존 연산값에 <strong>position 값을 추가</strong>하는 식으로 이루어진다.</p>
<p>$$
q_mk_n = x_m^TW_q^TW_kx_n + x_m^TW_q^TW_kp_n + p_m^TW_q^TW_kx_n + p_m^TW_q^TW_kp_n
$$</p>
<p>가장 general한 연산식이며, 값-값 / 값-위치값 ... 등의 정보 관계를 다 더해서 연산한다.</p>
<p>Relative Position Embedding의 단점</p>
<ul>
<li>efficient attention에의 적용이 어렵다. efficient attention의 경우 기존 attention식을 틀어서 연산한다. $$sim(q_m, k_n) = exp(q_m^Tk_n/ \sqrt{d})$$이게 원래 transformers연산식인데, 이 sim을 분할해서 $$sim(q_m, k_n) = \phi(q_m)^T\varphi(k_n)$$으로 연산하게 하는 거라서... 위의 식처럼 바로 qk연산을 할 수 없다.</li>
<li>보면 알겠지만 기존의 attention값을 4배로 늘렸다. 따라서 연산량이 엄청 늘어났다. relative position embedding 다른 논문들을 보면 그래서 저 네 개의 항 중 몇 개를 필요없다고 없애려는 작업을 좀 한다.</li>
</ul>
<h3 id="rotary-position-embedding">Rotary Position Embedding</h3>
<p>efficient attention에서도 적용을 시키기 위해서 기존 접근법과 궤를 달리한다. 여기서는 내적을 사용하여 position 값을 추가하려고 한다.&#x20;</p>
<p>$$
&lt;f_q(x_m, m), f_k(x_n, n)&gt; = g(x_m, x_n, m-n)
$$</p>
<p>이 수식의 의미는 $$f$$를 적용한 두 벡터의 내적이 반드시 $$x_m, x_n, m-n$$의 관계식으로 표현할 수 있도록 해서 index의 차를 항상 반영하도록 하겠다는 것이다.&#x20;</p>
<p>왜 내적을 사용하는가?</p>
<p>논문에 정확히 나와 있지는 않지만, efficient attention에 적용을 시킨다는 점에서 유추해 볼 수는 있다. 위의 sim함수를 변환하게 되어도 RoPE의 목적 함수를 보면 이미 f함수로 wrapping되어 있는데, 이렇게 함수를 설정하면 sim함수와 동일하게 처리할 수 있다는 장점이 있다. 논문에서 나온 바로는 &#39;normalization&#39;에서 장점이 있다는 것. RoPE방식을 쓰면 normal값이 동일하기 때문에(벡터를 단순히 돌린 거니까)</p>
<p>아무튼 이 내적값을 설정하기 위해 저자들은 f함수로 &#39;복소화&#39;을 사용한다. 복소평면에서 두 벡터 사이의 각도를 position값차이로, 벡터값을 컨텍스트 값으로 설정하는 것이다. 따라서 특정 벡터가 특정 거리만큼 벌어지도록 하고 싶다면 해당 벡터를 거리만큼 돌리면(rotate)된다. 따라서 이름이 rotary PE가 된 것.</p>
<h2 id="discussion">Discussion</h2>
<p>introduction을 보면 사실 이 기법은 position-awards embedding을 위한 것이라는 것을 알 수 있다. 그런데 개발하고 나서 보니, context길이를 flexible하게 잡을 수 있다는 장점 역시 존재했고, 이는 long llm으로 가는 가장 큰 단점인 &#39;고정 길이를 늘려야 한다는 것&#39;을 없애 주었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[k진수에서 소수 개수 구하기 - 92335]]></title>
            <link>https://velog.io/@you-genie/k%EC%A7%84%EC%88%98%EC%97%90%EC%84%9C-%EC%86%8C%EC%88%98-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-92335</link>
            <guid>https://velog.io/@you-genie/k%EC%A7%84%EC%88%98%EC%97%90%EC%84%9C-%EC%86%8C%EC%88%98-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0-92335</guid>
            <pubDate>Wed, 06 Mar 2024 09:50:35 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-설명">문제 설명</h1>
<p>양의 정수 <code>n</code>이 주어집니다. 이 숫자를 <code>k</code>진수로 바꿨을 때, 변환된 수 안에 아래 조건에 맞는 소수(Prime number)가 몇 개인지 알아보려 합니다.</p>

<ul>
<li><code>0P0</code>처럼 소수 양쪽에 0이 있는 경우</li>
<li><code>P0</code>처럼 소수 오른쪽에만 0이 있고 왼쪽에는 아무것도 없는 경우</li>
<li><code>0P</code>처럼 소수 왼쪽에만 0이 있고 오른쪽에는 아무것도 없는 경우</li>
<li><code>P</code>처럼 소수 양쪽에 아무것도 없는 경우</li>
<li>단, <code>P</code>는 각 자릿수에 0을 포함하지 않는 소수입니다.

<ul>
<li>예를 들어, 101은 <code>P</code>가 될 수 없습니다.</li>
</ul></li>
</ul>

<p>예를 들어, 437674을 3진수로 바꾸면 <code>211</code>0<code>2</code>01010<code>11</code>입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 왼쪽부터 순서대로 211, 2, 11이 있으며, 총 3개입니다. (211, 2, 11을 <code>k</code>진법으로 보았을 때가 아닌, 10진법으로 보았을 때 소수여야 한다는 점에 주의합니다.) 211은 <code>P0</code> 형태에서 찾을 수 있으며, 2는 <code>0P0</code>에서, 11은 <code>0P</code>에서 찾을 수 있습니다.</p>

<p>정수 <code>n</code>과 <code>k</code>가 매개변수로 주어집니다. <code>n</code>을 <code>k</code>진수로 바꿨을 때, 변환된 수 안에서 찾을 수 있는 <strong>위 조건에 맞는 소수</strong>의 개수를 return 하도록 solution 함수를 완성해 주세요.</p>

<hr>

<h5>제한사항</h5>

<ul>
<li>1 ≤ <code>n</code> ≤ 1,000,000</li>
<li>3 ≤ <code>k</code> ≤ 10</li>
</ul>

<hr>

<h5>입출력 예</h5>
<table class="table">
        <thead><tr>
<th>n</th>
<th>k</th>
<th>result</th>
</tr>
</thead>
        <tbody><tr>
<td>437674</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
<td>110011</td>
<td>10</td>
<td>2</td>
</tr>
</tbody>
      </table>
<hr>

<h5>입출력 예 설명</h5>

<p><strong>입출력 예 #1</strong></p>

<p>문제 예시와 같습니다. </p>

<p><strong>입출력 예 #2</strong></p>

<p>110011을 10진수로 바꾸면 110011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 11, 11 2개입니다. 이와 같이, 중복되는 소수를 발견하더라도 모두 따로 세어야 합니다.</p>

<h2 id="문제-풀이">문제 풀이</h2>
<p>해야 할 것은 두 가지. 1. K진수로 변환하기 2. 소수 구하기.</p>
<p>따라서 다음과 같이 큰 골자를 짠다.</p>
<pre><code class="language-python">def convert(n: int, k: int) -&gt; str:
    pass

def is_prime(n: int) -&gt; bool:
    pass

def solution(n, k):
    k_str = convert(n, k)
    answer = 0
    for cand in k_str.split(&quot;0&quot;):
        if cand and is_prime(int(cand)):
            answer += 1
    return answer</code></pre>
<p>여기서 각각 convert와 is_prime을 짜 준다.</p>
<p>K진수 변환의 로직은 간단하다. n이 0이 될 때까지 계속해서 k로 나누며, 그 몫을 str에 붙이면 된다.</p>
<pre><code class="language-python">def convert(n: int, k: int) -&gt; str:
    k_str = &quot;&quot;
    while n &gt; 0:
        n, l = n//k, n%k
        k_str += str(l)

    return k_str[::-1] # 변환된 나머지는 현재 반대 수열로 되어 있다</code></pre>
<p>is_prime은 알고 있는 공식을 조금 썼다. (쓰지 않으면 time error가 나게 된다)
N이 소수인지 알기 위해서는 $\sqrt{N}$ 까지의 수만 확인하면 된다. 여기서 $\sqrt{N}$은 반드시 들어가야 하기 때문에 range를 쓸 때 +1을 해줬다. </p>
<pre><code class="language-python">def is_prime(n: int) -&gt; bool:
    if n == 1: return False
    for i in range(2, int(math.sqrt(n))+1):
        if n % i == 0:
            return False
    return True</code></pre>
<p>최종 코드는 다음과 같다.</p>
<pre><code class="language-python">import math

def is_prime(n: int) -&gt; bool:
    if n == 1: return False
    for i in range(2, int(math.sqrt(n))+1):
        if n % i == 0:
            return False
    return True

def convert(n: int, k: int) -&gt; str:
    k_str = &quot;&quot;
    while n &gt; 0:
        n, l = n//k, n%k
        k_str += str(l)

    return k_str[::-1]

def solution(n, k):
    n = convert(n, k)
    answer = 0
    for cand in n.split(&#39;0&#39;):
        if cand and is_prime(int(cand)):
            answer += 1

    return answer</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[119. Pascal's Triangle II]]></title>
            <link>https://velog.io/@you-genie/119.-Pascals-Triangle-II</link>
            <guid>https://velog.io/@you-genie/119.-Pascals-Triangle-II</guid>
            <pubDate>Sun, 03 Mar 2024 11:58:47 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-설명">문제 설명</h2>
<p>In <strong>Pascal's triangle</strong>, each number is the sum of the two numbers directly above it as shown:</p>
<img alt="" src="https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif" style="height:240px; width:260px">
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> rowIndex = 3
<strong>Output:</strong> [1,3,3,1]
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> rowIndex = 0
<strong>Output:</strong> [1]
</pre><p><strong class="example">Example 3:</strong></p>
<pre><strong>Input:</strong> rowIndex = 1
<strong>Output:</strong> [1,1]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
    <li><code>0 &lt;= rowIndex &lt;= 33</code></li>
</ul>

<p>&nbsp;</p>
<p><strong>Follow up:</strong> Could you optimize your algorithm to use only <code>O(rowIndex)</code> extra space?</p>
</div>

<h2 id="문제-풀이">문제 풀이</h2>
<p><a href="https://velog.io/@you-genie/118.-Pascals-Triangle">118. Pascal&#39;s Triangle</a> 문제에서 이렇게 얘기했는데...
<img src="https://velog.velcdn.com/images/you-genie/post/8591a469-f314-4f95-a548-b045cf380302/image.png" alt=""></p>
<p>놀랍게도 진짜 그 문제가 나왔고, 생각보다 메모리는 빡빡하게 쓰지 않았다..
파스칼의 삼각형 문제와 동일한데, 지난 로그를 다 저장하는 것이 아니기 때문에 계속해서 <strong>이전 row</strong>를 업데이트 해 가면서 <strong>현재 row</strong>를 계산하면 된다.
위의 포스팅에서는 <code>[0]</code>을 붙인 다음에 계산해줬는데, 다시 생각하니까 list comprehension으로 간단하게 풀 수 있어서 개선을 해 주었다.</p>
<p>```python
class Solution:
    def getRow(self, rowIndex: int) -&gt; List[int]:
        past_row, curr_row = [1], [1]</p>
<pre><code>    for _ in range(1, rowIndex+1):
        curr_row = [past_row[i]+past_row[i+1] for i in range(len(past_row)-1)] # 상단 좌 / 상단 우 원소를 더해줌.
        # 좌우에는 1 .... 1
        curr_row = [1] + curr_row + [1]
        past_row = curr_row

    return curr_row```</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] MT-Bench]]></title>
            <link>https://velog.io/@you-genie/MT-Bench</link>
            <guid>https://velog.io/@you-genie/MT-Bench</guid>
            <pubDate>Sat, 02 Mar 2024 11:25:52 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/you-genie/post/bc591ebd-f4b2-4cc1-81fb-baa445e04bf1/image.png" alt=""></p>
<h2 id="description">Description</h2>
<ul>
<li>name: Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena</li>
<li>date: 23.06</li>
<li>code: <a href="https://github.com/lm-sys/FastChat/tree/main/fastchat/llm_judge">https://github.com/lm-sys/FastChat/tree/main/fastchat/llm_judge</a></li>
<li><a href="https://huggingface.co/spaces/lmsys/chatbot-arena-leaderboard">https://huggingface.co/spaces/lmsys/chatbot-arena-leaderboard</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>원래 LLM chatbot 같은 경우 lm-evaluation-harness와 같은 방식을 주로 사용하였는데, 이게 실제 성능과는 괴리가 어느 정도 있다는 것이 주요 마이너스 요소였다.</p>
<p>예를 들면,</p>
<ul>
<li>LLM leaderboard에서는 (e.g. open ko-llm leaderboard) 높은 성능을 보이지만 실제로 대답하는 것을 보면 어색한 경우. 번역투의 데이터를 많이 집어넣으면 보통 이렇게 된다.</li>
<li>챗봇 형태(실제로 더 많이 쓰일)보다 PLM형태가 더 점수가 높다.</li>
</ul>
<p>이런 이슈가 존재해서 &#39;챗봇&#39;을 위한 리더보드의 필요성이 생겼다.</p>
<p>그렇다면 왜 현재 하네스 식 리더보드에 이런 문제점이 생겼는가? 챗봇의 경우 대다수가 &#39;instruction dataset&#39;을 사용한다. 여기서 Instruction dataset은 아주 다양하고 섬세한 지시 사항도 모델이 따를 수 있도록 하는 것을 목적으로 한다. 영어로는 instruction alignment-로, 그냥 &#39;말 잘 듣는 모델&#39; 정도로 이해하면 된다. 지시를 잘 따르는 모델이라는 것은 말하자면 이런 능력을 가진 모델이라고 보면 되겠다.</p>
<ul>
<li>지시문에 달린 여러 요구사항을 모두 만족할 것</li>
<li>답변이 정확하며 거짓을 담지 않을 것</li>
<li>원하는 뉘앙스로 응답을 생성할 것</li>
</ul>
<p>이런 지시 사항 능력 강화를 위해 단순 FT를 넘어 DPO를 사용하기도 한다! 사실 &#39;말을 잘 듣는다&#39;라는 기준이 저렇게 딱딱 구조적으로 말하기 애매한 것들이 많아서, 그냥 모델한테 &quot;야, 이게 내가 너에게서 원하는 답변이야&quot; 라고 알려주는 거다.</p>
<p>이러한 일련의 과정을 거치고 나면 모델은 <strong>지시문을 잘 따르는</strong> 모델이 된다.</p>
<p>이번에는 리더보드에 많이 쓰이는 하네스 데이터 예시를 통해 <strong>왜 좋은 챗봇이 좋은 점수를 받기 어려운지</strong> 알아보자.</p>
<blockquote>
<p>지시문: 정답을 고르세요. 바나나는 무슨 색인가? A) 노란색 B) 갈색 C) 검은색 D) 초록색</p>
<p>정답: 노란색</p>
<p>챗봇: 바나나는 익으면 노란색이기 때문에 정답은 A)입니다. 그러나 과하게 익으면 갈색-검은색이 되기도 하고, 덜 익으면 초록색이기도 합니다.</p>
</blockquote>
<p>많이 과장하긴 했는데 이런 느낌이다. 챗봇은 보통 사고 후 대답하는 능력 또한 강화되었기 때문에 다음과 같이 대답할 가능성이 높고, 이는 정답과는 다르지만 사용자의 &#39;의도&#39;에는 더 맞는 듯한 느낌을 준다.</p>
<p>물론 챗봇도 할 수 있다. 입력을 다음과 같이 준다면...</p>
<blockquote>
<p>지시문: 아래는 일반 상식을 평가하는 문제입니다. 정답에 해당하는 &#39;단어&#39;만을 출력하세요. 바나나는 무슨 색인가? A) 노란색 B) 갈색 C) 검은색 D) 초록색</p>
<p>챗봇: 노란색</p>
</blockquote>
<p>하지만 문제 지문이 저렇게 되어 있지 않다. 따라서 챗봇 입장에서는 억울할 것.... 심지어 자기는 수학/과학문제도 풀 수 있는데 지문에 &#39;안 써줬기 때문에&#39; 대답하지 않을 뿐이다.</p>
<p>아무튼 이러한 이슈로 인해 챗봇이 &#39;얼마나 더 지시를 따르는가?&#39; 에 대한 평가를 따로 만들기로 했다. 사실 두 개 만들었는데, MT-bench와 Chatbot Arena이다.&#x20;</p>
<h2 id="methods">Methods</h2>
<p>간단하게 설명하면 MT-Bench는 답변 평가를 위한 벤치마크 질문지 모음이고, Chatbot Arena는 랜덤한모델과 생성 결과 비교를 할 수 있게 하는 플랫폼이다.</p>
<p>MT-Bench의 데이터는 다양한 분야(수학, 롤플레이, 생성, 지식 추출, reasoning...)에서의 생성 질문을 포함하고 있다.</p>
<p>Chatbot Arena의 경우 유저가 참가하게 되면 랜덤한 모델 두 개가 동일한 질문에 대해 같은 대답을 내놓는다. 그 이후 유저가 승패를 가르는 방식이다. <a href="https://huggingface.co/spaces/lmsys/chatbot-arena-leaderboard">https://huggingface.co/spaces/lmsys/chatbot-arena-leaderboard</a> 바로 그 아레나.</p>
<h3 id="llm-as-a-judge">LLM as a Judge</h3>
<p>위의 Chatbot Arena의 경우 사람이 직접적으로 참여하여 평가를 하는 방식이다. 이 과정은 정확도가 보장되지만 굉장히 품이 많이 드는 작업이기 때문에 이를 자동화하기 위한 &#39;LLM Judge&#39;를 고안하였다.</p>
<p>LLM Judge의 종류는 총 세 가지.</p>
<ul>
<li>pairwise comparison - 두 답변 중 어느 것이 더 좋은가?</li>
<li>single answer grading - 답변의 퀄리티를 평가하라</li>
<li>reference-guided grading - reference 답변을 주고, 이를 고려해서 답변의 퀄리티를 평가하가 하는 것. 뒤에 나오겠지만 수학 문제 등에 약하기 때문에 답변을 미리 주고 이를 감안하여 평가하라고 하는 것이다.</li>
</ul>
<h4 id="llm-judge-사용의-장점">LLM Judge 사용의 장점?</h4>
<p>사람이 평가 안해도 된다.</p>
<p>단순히 점수뿐만이 아니라 &#39;왜&#39; 그렇게 평가했는지도 같이 제시해준다.</p>
<h4 id="llm-사용의-단점">LLM 사용의 단점?</h4>
<p><strong>Position bias</strong>: (왼쪽일때는 더 좋다고 그러다가 오른쪽으로 오니까 별로라고 하는 경우)가 생김. 모든 LLM이 이러한 position bias가 있음을 실험을 통해 밝혔으며, 대체로 앞에 오는 대답을 긍정적으로 평가하는 경우가 많았다. GPT-4 정도만 consistency를 65% 정도로 유지했다.&#x20;</p>
<p><strong>Verbosity bias</strong>: LLM이 더 긴 모델을 더 좋다고 평가하는 경우가 많다. 평가를 위해 하나의 답변과 동일한 정보량을 가진 더 긴 답변 (리스트를 셔플해서 앞에 붙여놓음)을 준비했고, GPT-4를 제외한 다른 모델들은 이를 감별하는 데 실패했다.</p>
<p><strong>Self-enhancement bias</strong>: 자기가 만든 답변을 더 좋게 여긴다는 이론. 대체로 한 모델이 특정 모델이나 자기 자신을 더 좋게 여기는 &#39;경향&#39;이 있기는 하지만 정확한 평가는 할 수 없다고 밝혔다. 이걸 평가하려면 &#39;동일한 퀄리티&#39;를 가진 &#39;각 모델 스타일&#39;의 답변을 준비해야 되는데, 퀄리티를 동일하게 하기가 쉽지 않기 때문.</p>
<p>Limited capability in grading math and reasoning questions: 수학이나 reasoning은 (자기도 못 풀기 때문에)채점을 잘 못 한다.</p>
<h3 id="multi-turn-judge">Multi-turn Judge</h3>
<p>MT-Bench의 모든 conversation은 2-turn으로 되어 있다. 그래서 평가 디자인 후보가 다음 두 가지였다.</p>
<ol>
<li>질문 - 턴 / 질문 - 턴 이렇게 2 row로 만들기</li>
<li>멀티턴 자체를 한 row로 만들기</li>
</ol>
<p>second turn(딸림질문에 따른 응답)에서 앞의 응답을 기반으로 대답을 한 것이기 때문에 앞의 턴을 빼고 데이터를 구성한다면(디자인 1) 판단에 문제가 생기게 된다. 따라서 멀티턴으로 데이터를 구성하게 했다.</p>
<h2 id="사람과의-agreement">사람과의 Agreement</h2>
<p>LLM-Judge가 잘 작동하는지 보려면 사람이랑 평가가 일치하는지를 봐야 한다.</p>
<p>일치 기준 = 랜덤하게 선택된 문제에서 랜덤한 평가자가 일치하게 평가한 확률</p>
<p>재밌는 건 사람-사람의 일치도(81%)보다 평균적인 사람-GPT-4의 일치도(85%)가 더 높다는 것이다.</p>
<h2 id="as-benchmark">As Benchmark</h2>
<p>다른 MMLU / TruthfulQA / MT-Bench와 같은 벤치마크에도 실험했을 때, high-quality dataset을 쓰면 모델 퍼포먼스를 올릴 수 있고, 적은 high-quality conversation을 쓰더라도 GPT-4의 평가를 잘 받는 모델은 만들 수가 있지만 MMLU는 올릴 수 없다. 즉, 이러한 single benchmark(MMLU등)로는 모델의 성능을 온전히 평가하기에는 문제가 있으며 comprehensive 한 평가 기준 (예를 들어 MT-Bench!) 가 필요하다는 것을 시사한다.</p>
<h1 id="discussion">Discussion</h1>
<p>여담으로, <a href="https://chat.lmsys.org/">https://chat.lmsys.org/</a> 들어가서 한 번 해보는 것을 추천한다. 한국어도 잘 받는다(당연하게도, GPT-4를 사용하기도 해서...) ELO rating을 써서 랭킹을 정하고 있다고 한다. 그래서 괜히 GPT-4가 아닌 모델의 손을 들어주고 싶지만, 생각보다 GPT-4가 너무 잘한다...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[118. Pascal's Triangle]]></title>
            <link>https://velog.io/@you-genie/118.-Pascals-Triangle</link>
            <guid>https://velog.io/@you-genie/118.-Pascals-Triangle</guid>
            <pubDate>Sat, 02 Mar 2024 09:38:50 GMT</pubDate>
            <description><![CDATA[<p>In <strong>Pascal's triangle</strong>, each number is the sum of the two numbers directly above it as shown:</p>
<img alt="" src="https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif" style="height:240px; width:260px">
<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> numRows = 5
<strong>Output:</strong> [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> numRows = 1
<strong>Output:</strong> [[1]]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
    <li><code>1 &lt;= numRows &lt;= 30</code></li>
</ul>
</div>

<h3 id="풀이">풀이</h3>
<p>단순하게 계속 연산해 나가면 된다. 만약 N번째 row의 파스칼 삼각형 row를 계산하라고 하고 메모리 제한을 빡빡하게 뒀으면 조금 더 방법을 고민해야했을수도...</p>
<p>직전 row의 값을 copy한 다음 앞에 0을 붙여 주면, prev[i] + prev[i+1] 값을 인덱스 고려 안하고 더해서 얻을 수 있다.</p>
<pre><code class="language-python">class Solution:
    def generate(self, numRows: int) -&gt; List[List[int]]:
        ret = [[1]]
        for i in range(1, numRows):
            bf_row = [0] + ret[i-1]
            curr_row = bf_row.copy()
            for j in range(len(bf_row)-1):
                curr_row[j] = bf_row[j] + bf_row[j+1]
            ret.append(curr_row)
        return ret</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[level 2] 귤 고르기 - 138476 ]]></title>
            <link>https://velog.io/@you-genie/level-2-%EA%B7%A4-%EA%B3%A0%EB%A5%B4%EA%B8%B0-138476</link>
            <guid>https://velog.io/@you-genie/level-2-%EA%B7%A4-%EA%B3%A0%EB%A5%B4%EA%B8%B0-138476</guid>
            <pubDate>Wed, 28 Feb 2024 11:14:12 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<p>경화는 과수원에서 귤을 수확했습니다. 경화는 수확한 귤 중 'k'개를 골라 상자 하나에 담아 판매하려고 합니다. 그런데 수확한 귤의 크기가 일정하지 않아 보기에 좋지 않다고 생각한 경화는 귤을 크기별로 분류했을 때 서로 다른 종류의 수를 최소화하고 싶습니다.</p>

<p>예를 들어, 경화가 수확한 귤 8개의 크기가 [1, 3, 2, 5, 4, 5, 2, 3] 이라고 합시다. 경화가 귤 6개를 판매하고 싶다면, 크기가 1, 4인 귤을 제외한 여섯 개의 귤을 상자에 담으면, 귤의 크기의 종류가 2, 3, 5로 총 3가지가 되며 이때가 서로 다른 종류가 최소일 때입니다.</p>

<p>경화가 한 상자에 담으려는 귤의 개수 <code>k</code>와 귤의 크기를 담은 배열 <code>tangerine</code>이 매개변수로 주어집니다. 경화가 귤 k개를 고를 때 크기가 서로 다른 종류의 수의 최솟값을 return 하도록 solution 함수를 작성해주세요.</p>

<h3 id="문제-풀이">문제 풀이</h3>
<p>종류를 가장 줄이기 위해서는 최대한 많은 귤이 속해 있는 종류를 먼저 없애면 된다. 따라서 간단하게 그냥 정렬한 뒤 하나씩 없애주면 된다.</p>
<p>처음에는 단순히 <code>pop</code>을 썼는데, 이렇게 하니 실행 시간이 오래 나온다. 리스트 left pop을 하게 되면 파이썬 리스트 구조상 하나씩 뺐다가 옮겼다 하는 미친 작업을 반복해야 되기 때문.</p>
<p>따라서 <code>deque</code>를 활용해서 leftpop을 해줬다.</p>
<pre><code class="language-python">from collections import Counter, deque

def solution(k, tangerine):
    answer = 0

    counter = Counter(tangerine)
    sizes = deque(sorted([(size, n) for size, n in counter.items()], key=lambda x: x[1], reverse=True))

    while k &gt; 0:
        k -= sizes.popleft()[1]
        answer += 1
    return answer </code></pre>
<p><code>Counter</code>는 모든 리스트에 등장하는 원소의 개수를 세어 준다.</p>
]]></description>
        </item>
    </channel>
</rss>