<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>clueless_coder.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 10 Jan 2024 22:21:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>clueless_coder.log</title>
            <url>https://images.velog.io/images/clueless_coder/profile/9519069c-775f-446a-a3ca-92913c57d0d5/7a4bbbc01f594fb6e2fed9f92a12cdb5-sticker.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. clueless_coder.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/clueless_coder" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[웹 어플리케이션 만드는 순서 (간단)]]></title>
            <link>https://velog.io/@clueless_coder/%EC%9B%B9-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%88%9C%EC%84%9C-%EA%B0%84%EB%8B%A8</link>
            <guid>https://velog.io/@clueless_coder/%EC%9B%B9-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%88%9C%EC%84%9C-%EA%B0%84%EB%8B%A8</guid>
            <pubDate>Wed, 10 Jan 2024 22:21:12 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>생활코딩 참고 정리한 것</p>
</blockquote>
<h3 id="웹-앱을-만드는-순서">웹 앱을 만드는 순서</h3>
<ol>
<li><p>구상 (무엇을 만들 것인가)</p>
</li>
<li><p>기획(계획): 어떤 기능을 가질 것인가</p>
</li>
<li><p>디자인: 웹사이트를 아름답게, 유저 경험 향상</p>
</li>
<li><p>개발: 실제 서비스가 동작하도록 하는 것, 디자인과 동시에 진행되는 경우도 있다</p>
</li>
<li><p>테스트: 작은 조직에서는 테스팅을 개발자가, QA(quality assurance)</p>
</li>
<li><p>1-6을 반복; 가장 중요하다. -&gt; 이 반복적인 작업을 잘하기 위해서는 start small!</p>
</li>
<li><p>구상: 무엇을 만들 것인가?</p>
</li>
<li><p>기획: 어떻게 동작해야 하는가?</p>
</li>
</ol>
<ul>
<li>UI 모델링: <ul>
<li>유저 인터페이스(사용자가 시스템을 제어하는 조작장치)</li>
<li>모델링: 직접 만들기 전에 가상으로 만들어 보는 것
즉, 사용자의 입장에서 동작하는 기능을 가상으로 만들어 보기
유아이 모델링이 왜 중요한가? 뭘 만들자고 했을때, 말로 표현하게 되면 말을 듣는 사람들이 각자 다른 생각을 할 수 있다. 무엇을 만들고자하는지 모두가 공유하기 위해 이를 해야 한다. 기획자가 아래처럼 그림을 그리고 구성원들과 공유하고, 각 버튼 등이 어떻게 변하고 기능을 하는지 설명한다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/f3825b13-c8c6-4f1c-92d8-3a2db7eca54c/image.png" alt=""></li>
</ul>
</li>
</ul>
<p>여러가지 모델링 도구가 있는데, 간단한 거는 손그림이 최고고, 요즘은 피그마. 기획이 꼼꼼하지 않으면 프로젝트는 반은 실패다. 기획은 별도의 트레이닝이 필요할만큼.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘 때려잡기] Huffman Codes (허프만 코드)]]></title>
            <link>https://velog.io/@clueless_coder/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%95%8C%EB%A0%A4%EC%9E%A1%EA%B8%B0-Huffman-Codes-%ED%97%88%ED%94%84%EB%A7%8C-%EC%BD%94%EB%93%9C</link>
            <guid>https://velog.io/@clueless_coder/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%95%8C%EB%A0%A4%EC%9E%A1%EA%B8%B0-Huffman-Codes-%ED%97%88%ED%94%84%EB%A7%8C-%EC%BD%94%EB%93%9C</guid>
            <pubDate>Fri, 20 Oct 2023 19:27:30 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>⭐️ 이 포스트는 편한 말투를 사용한다. 영어 용어를 읽히는대로 한국어로 쓰기도 한다. 긴 용어는 줄여서 표현을 하기도 한다. 오타가 있을 수 있다. </p>
</blockquote>
<blockquote>
<p>📖 이 포스트는 Tim Roughgarden 교수의 Algorithms Illuminated 를 공부하며 정리한 것이다. 책의 챕터 번호를 따른다.</p>
</blockquote>
<blockquote>
<p>한 줄 소개: 허프만 코드는 데이터를 compression(압축) 하는 코드다.</p>
</blockquote>
<h2 id="141-codes">14.1. Codes</h2>
<h3 id="1-fixed-length-binary-codes">1. Fixed Length Binary Codes</h3>
<p>우리가 fixed length binary code 로 어떤 정보를 표현한다고 하자. 예를 들어 알파벳을 표현한다면, 대문자, 소문자, 부호 등 포함해서 64개의 심볼이 있다고 하고, 그려면 64개를 비트의 나열(바이네리 스트링)로 표현하려면 2^6 = 64 니까 6비트가 필요하겠다. 이게 대략 아스키 코드가 작동하는 방식이다. Fixed-length 코드가 자연스럽고 쉬운 방식이긴 하다. 하지만 알고리즘에서 항상 해야되는 질문이 있다. </p>
<blockquote>
<p><strong>Can we do better?</strong> (더 좋은 방법은 없을까?)</p>
</blockquote>
<h3 id="2-variable-length-codes">2. Variable Length Codes</h3>
<p>고정된 길이를 생각해봤으니 이제는 변화 가능한 길이를 생각해보자. 어떤 알파벳은 다른 알파벳보다 많이 등장할 수 있고, 이럴때는 variable-length (줄여서 vl 이라고 하겠다) 코드가 픽스드 보다 좋다. vl이 더 복잡하긴 하다. 예를 들어, a,b,c,d 가 있다. 픽스드라면 우리는 순서대로 00,01,10,11로 표현할 수 있다. 버라이어블이라면 일부는 1-비트로 인코딩할 수 있으니 0, 01, 10, 1 로 표현할 수 있다. </p>
<blockquote>
<p>여기서 퀴즈: 그럼 vl로 001은 뭔가? </p>
</blockquote>
<ol>
<li>ab</li>
<li>cd</li>
<li>aad</li>
<li>정보가 충분하지 않음</li>
</ol>
<blockquote>
<p>답: 4. 정보가 충분하지 않다. 어디서 끊기는지 알 수 없다. 0, 01? 0,0,1 ?</p>
</blockquote>
<p>따라서 vl에 충분한 정보가 더해지지 않으면 모호하다. 픽스드에서는 길이가 정해져 있으니 어디서 끊기는지 걱정할 필요가 없다. 예를 들어, 6비트로 고정해서 표현한다면, 7번째 비트에서 두 번째 심볼이 나온다는 걸 안다. 따라서 버라이어블을 쓰려면 constraint를 줘야 한다.</p>
<blockquote>
<p>그래서 어떤 조건을 더해서 버라이어블의 모호함을 없앨 건가?</p>
</blockquote>
<h3 id="3-prefix-free-codes">3. Prefix-Free Codes</h3>
<p>프리픽스 프리하게 만들어주면, ambiguity를 없앨 수 있다. 프리픽스 프리가 뭔소리냐면 예를 들어 a,b 심볼을 인코딩할때, a가 b의 프리픽스가 될 수 없고, b가 a의 프리픽스가 될 수 없다는 소리다. (a,b가 0, 01이라면 a는 b의 프리픽스다, 0, 10이라면 어떤 것도 서로의 프리픽스가 될 수 없다.) 예로 첫 5비트가 a라면, 프리픽스 프리 코드에서는 이 첫 5비트가 다른 심볼의 프리픽스가 될 수 없기때문에 a라고 확신할 수 있다. </p>
<p>프리픽스 프리인 픽스드 랭스가 아닌 예시. a,b,c,d 가 있다면, 0, 10, 11, 111 이렇게 된다. 0을 a를 인코딩하기 위해 썼기 때문에 다른 심볼을 인코딩할때 0으로 시작하는 애가 있으면 안된다. 따라서 나머지는 다 1로 시작해야 된다. 10을 b에 썼기 때문에 나머지는 11로 시작해야된다. 11을 c에 썼으니 나머지는 111로 시작해야 된다.</p>
<h3 id="4-prefix-free-codes의-장점">4. Prefix-Free Codes의 장점</h3>
<p>버라이어블 랭스이고 프리픽스 프리인 코드는 각 심볼의 등장 빈도가 다를때 픽스드 랭스보다 좋다. 예를 들어, 우리가 과거 어떤 문서를 인코딩해본 경험으로 심볼들의 빈도가 다음과 같다고 해보자. </p>
<blockquote>
<p>a: 60%, b: 25%, c: 10%, d: 5%.</p>
</blockquote>
<p>그럼 이제 픽스드 랭스랑 퍼포먼스를 비교해보자. a, b, c, d 순서대로, 픽스드는 앞선 예시와 동일하게 00, 01, 10, 11, 버라이블 랭스 프리픽스 프리는 0, 10, 11, 111 이다.</p>
<p>여기서 퍼포먼스라 함은 한 심볼당 평균적으로 얼마나 많은 비트가 쓰였는지를 보는 거다. uniform distribution 이라면 (빈도가 모두 동일한 경우라면) 픽스드 랭스의 승이다. 하지만 빈도가 다를 경우는 weighted average를 계산해야하니 결과가 달라진다. 픽스드는 당연히 심볼 당 2비트다. 프리픽스 프리는 1*0.6 + 2*0.25 + 3*0.1 + 3*0.05 = 1.55. 즉, 심볼 당 1.55비트다. 반대로 빈도가 역순이었다고 생각해보자. 그러면 3*0.6 + 3*0.25 + 2*0.1 + 1*0.05 = 2.8. 픽스드보다 안좋아진다.</p>
<blockquote>
<p>결론: 심볼 프리퀀시에 따라 각 심볼의 best binary code 를 뭘로 해야할지 달라진다.</p>
</blockquote>
<h3 id="5-문제-정의">5. 문제 정의</h3>
<p>이제 우리는 명확하게 무엇이 문제인지 무엇을 풀어야할지 알게 되었다. 심볼의 빈도에 따라서 어떤 프리픽스 프리 코드를 해야할지 찾는 거다. (문제는 항상 인풋과 원하는 아웃풋으로 나뉜다)</p>
<p><em><strong>Problem: Optimal Prefix-Free Codes</strong></em></p>
<blockquote>
<p>Input: 
A nonnegative frequency $p_a$ for each symbol $a$ of an alphabet $\Sigma$ of size $n \geq 2.\$
Ouput: 
A prefix-free binary code with the minimum-possible average encoding length:
$$\sum_{a\in\Sigma} p_a$$ * (number of bits used to encode a).</p>
</blockquote>
<p>간단히 말해서 각 심볼당 빈도가 주어지면, 심볼당 평균 인코딩 랭스가 제일 짧아지는 경우를 찾으면 된다.</p>
<p>근데 심볼 빈도는 어떻게 알 수 있나? 어떤 경우는 도메인 지식으로 알 수 있다 (예. 사람 DNA에 각 뉴클리오베이스의 빈도). MP3 파일을 인코딩하는 경우에는, 인코더가 initial digital 버전을 만들때 심볼 프리퀀시를 계산해두고 압축할 때 사용한다. </p>
<p>문제는 최적의 경우를 찾기 위해서 확인할 케이스가 너무 많아 보인다는 것이다. 알파벳 사이즈에 따라 확인할 코드 수가 exponentially 자라기 때문이다 (예를 들어, 알파벳 사이즈가 n이면 n! 경우가 있을 것이다). 하지만 다행이도 깔쌈한 <strong>greedy algorithm</strong> 으로 이 문제를 해결할 수 있다.</p>
<h2 id="142-codes-as-trees">14.2 Codes as Trees</h2>
<p>어떻게 n개의 코드가 서로 프리픽스 프리임을 보장할 수 있을까? 이때 우리는 바이내리 트리를 사용한다. 세 가지 예시를 보면서 코드랑 트리가 어떻게 연관되고 트리를 사용하는 게 어떤 도움을 줄 수 있는지 이해해보자.</p>
<h3 id="1-three-examples">1. Three Examples</h3>
<p>먼저 픽스드 랭스를 트리로 표현해보자. 예시는 전과 같이 a, b, c, d 가 순서대로 00, 01, 10, 11로 인코딩. 트리로 표현하면 다음과 같다. 부모 노드와 자식 노드들을 잇는 엣지는 0 또는 1로 라벨링된다. 그리고 알맞게 노드에 심볼을 라벨링한다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/62bb90d9-18b5-4748-aabc-8c82bce1e906/image.png" alt=""></p>
<p>루트에서 두 엣지를 traverse 하면 path가 정해진다. 그리고 이 두 엣지를 심볼의 인코딩이라고 해석하면 된다.</p>
<p>이제 버라이어블 랭스 코드 예시를 보자 (논프리픽스 프리 버전). a, b, c, d가 0, 01, 10, 1. 트리로는 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/c1b18c77-a965-475a-94b2-150af2bc849f/image.png" alt=""></p>
<p>a, d가 각각 b, c의 프리픽스라 a, d를 거쳐서 b, c가 되는 것을 확인할 수 있다.</p>
<p>마지막으로 프리픽스 프리 버라이어블 랭스 코드를 보자. a, b, c, d가 0, 10, 110, 111.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/05630e5b-565f-4159-a661-e17b62e4402d/image.png" alt=""></p>
<p>이렇게 어떤 바이내리 코드라도 left edge, right edge가 각각 0과 1로 labeled된 바이내리 트리로 표현할 수 있다. 패스의 엣지 수는 해당 심볼의 비트 수와 같다. 따라서 우리는 다음과 같은 proposition(명제)을 갖는다.</p>
<blockquote>
<p><strong>Proposition 14.1 (encoding length and node depth)</strong>
모든 바이너리 코드에 대하여, 어떤 심볼의 인코딩 길이는 해당 트리에 라벨이 그 심볼인 노드의 깊이와 같다. </p>
</blockquote>
<h3 id="2-그래서-어떻게-생긴-트리가-prefix-free-codes를-표현하나">2. 그래서 어떻게 생긴 트리가 Prefix-Free Codes를 표현하나?</h3>
<p>앞서서 바이너리 트리로 (픽스드든 아니든 프리픽스 프리든 아니든) 어떤 바이너리 코드든지 표현할 수 있음을 확인했다. 그런지 첫 번째와 세 번째 트리에서 보았듯, 둘 다 프리픽스 프리이지만 모양이 다르다. 하지만 이 둘은 두 번째 (프리픽스 프리가 아닌) 트리와 다른 둘 만의 공통점을 가지고 있다; <strong>바로 리프 노드에만 심볼이 라벨링되어있다는 것이다.</strong>  </p>
<p>일반화해서 말하자면, 심볼 a가 심볼 b의 프리픽스일려면, a 노드가 b 노드의 ancestor 여야만 한다 (if and only if). 반면에 리프 노드는 그 어떤 노드의 ancestor도 될 수가 없으니, 리프 노드에만 라벨링이 된 경우, 우리는 그 트리가 프리픽스 프리 코드를 나타냄을 알 수 있다. 프리픽스 프리 코드 트리에서 디코딩은 다음과 같이 간단하다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/72f8bd03-a67f-4ea3-95ae-5fa714d4a612/image.png" alt=""></p>
<h3 id="3-문제-재정의하기">3. 문제 재정의하기</h3>
<p>이제 우리는 최적화된 프리픽스 프리 코드 찾기 문제를 오직 바이너리 트리만을 이용해서 아주 간단하게 표현할 수 있다. 여기서 $\Sigma{\text -}tree$ 는 $\Sigma$의 심볼과 리프가 일대일 대응되는 바이너리 트리를 의미한다. 리프와 일대일 대응이므로 $\Sigma{\text -}tree$는 프리픽스 프리 코드가 된다.</p>
<p><em><strong>Problem: Optimal Prefix-Free Codes (Rephrased)</strong></em></p>
<blockquote>
<p>Input: 
A nonnegative frequency $p_a$ for each symbol $a$ of an alphabet $\Sigma$ of size $n \geq 2.\$
Ouput: 
A $\Sigma{\text -}tree$ with the minimum-possible average leaf depth.</p>
</blockquote>
<p>$\Sigma{\text -}tree;T$ 와 심볼 프리퀀시 $\bold{p} = {p_a}_{a\in \Sigma}$ 에 대하여 트리의 심볼의 빈도가 고려된 평균 리프까지 깊이 (즉 한 심볼당 평균 비트 수)를 다음과 같이 표현하자.</p>
<p>$$L(T, \bold{p}) = \sum_{a \in \Sigma} {p_a} * \text{(depth of the leaf labeled $a$ in $T$)}$$</p>
<p>따라서 우리는 $L$이 최소화되는 $T$를 찾으면 되겠다.</p>
<h2 id="143-huffmans-greedy-algorithm">14.3 Huffman&#39;s Greedy Algorithm</h2>
<h3 id="1-building-trees-through-successive-mergers">1. Building Trees Through Successive Mergers</h3>
<p>허프만의 아이디어는 Bottom-up 방식이다.여기서 바텀업 방식은 리프 노드 n개(즉, 심볼 n개)에서 시작해서 트리의 루트까지 올라가는 방식인데, 올라갈때 <strong>연속적인 머징</strong>을 통해서 트리를 만든다. 간단한 예시를 보자. $\Sigma = {A,B,C,D}$ 이고 리프 노드부터 시작한다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/a8eff4b5-a9f3-46f9-b631-2fc6021505f7/image.png" alt="">
먼저 C, D를 묶는다. C, D는 sibiling 이 된다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/11a5a03e-ad7d-4090-b033-6f7344257f9a/image.png" alt="">
다음으로 A, B를 묶는다. A, B는 sibiling 이 된다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/04aac8f4-6e0d-4dbb-9e0a-e898136ab6ca/image.png" alt="">
다음으로 위에 두 노드를 묶는다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/e4c9dfa7-338b-451c-935e-36b191077faa/image.png" alt="">
그럼 완성. 위 트리는 14.2.1의 픽스드 랭스 코드를 표현하게 된다. 다른 방식으로 묶을 수도 있다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/9294a111-3f23-44e5-ae0d-60891b171ef2/image.png" alt=""> 
C,D를 묶은 다음 B와 위 노드를 묶는다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/8ec3add5-fbea-4421-9965-6c979caae051/image.png" alt="">
마지막으로 A 노드를 제일 위 노드와 묶는다. 그럼 이는 프리픽스 프리 버라이어블 랭스 코드를 표현하게 된다.</p>
<p>이처럼 허프만의 그리디 알고리즘은 일반적으로 forest(binary tree의 collection)를 형성한다. 그리고 이 숲에서 각 iteration 마다 두 개의 트리를 고르고, 두 트리의 루트를 각각 left and right children 으로 하여 묶는다. 그리고 단 하나의 트리가 남을 때까지 반복하고 멈춘다.</p>
<blockquote>
<p>퀴즈: 허프만의 그리디 알고리즘은 멈추기 전까지 몇 번의 merger를 하는가? ($n = |\Sigma|$ 라고 하자.)</p>
</blockquote>
<ol>
<li>n-1</li>
<li>n</li>
<li>(n+1)n/2</li>
<li>정보가 충분하지 않다.</li>
</ol>
<blockquote>
<p>답은 1. n-1. n개의 트리에서 시작해서 1개의 트리가 될때까지, n-1번의 머징을 하게 된다.</p>
</blockquote>
<h3 id="2-huffmans-greedy-criterion">2. Huffman&#39;s Greedy Criterion</h3>
<p>앞서서는 그냥 머징을 해봤다면, 이제 우리는 각 심볼의 빈도를 고려하면서 머징을 해야한다. 머징을 한 번 할때마다, 참여하는 두 트리의 리프 노드까지 깊이는 각 리프 노드당 1씩 증가한다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/1c89e7e7-ea73-4e3d-a552-28a013c019bb/image.png" alt="">
위의 머징 과정(B 트리와 C,D가 있는 트리가 머징되는)을 예로 보자면 C, D의 리프 노드까지 깊이는 1-&gt;2 로 증가하고, B는 0-&gt;1 로 증가한다. 즉, 심볼을 표현하는 비트 수가 1씩 증가했다. 그러므로 우리는 머징을 하면 비트 수가 증가하고, 우리가 최소화하고자 하는 objective function 인 $L$(평균 리프 depth)도 머징을 함에 따라 증가함을 알 수 있다. 그리고 그리디 알고리즘이라는 말에서 알 수 있듯이 허프만 그리디 알고리즘은 매 이터레이션마다 $L$(평균 리프 depth)을 최소로 증가시키는 방향으로 트리들을 머징해나간다. </p>
<blockquote>
<p><strong>Huffman&#39;s Greeday Criterion</strong>
Merge the pair of trees that causes the minimum-possible increase in the average leaf depth.</p>
</blockquote>
<p>그럼 각 머지당 average leaf depth는 얼마씩 증가하는가? 각 트리의 리프 노드 심볼들은 깊이가 1씩 증가한다. 그러므로 각 심볼 $a$는 1*$p_a$ 만큼씩 증가에 기여한다. 따라서 $T_1$ 과 $T_2$를 머징한다고 할때 한 번의 머지에 증가하는 average leaf depth는 다음과 같다.</p>
<p>$$\sum_{a \in T_1} p_a + \sum_{a \in T_2} p_a$$</p>
<p>우리는 이제 이 증가량을 최소로 하는 두 트리를 찾아서 머징시키면 된다. 코드로 보자.</p>
<h3 id="3-pseudocode">3. Pseudocode</h3>
<blockquote>
<p><strong>Huffman</strong>
// 초기화: 각 라벨 노드를 하나의 트리로 세팅.
for each $a \in \Sigma$ do
.... $T_a$ := tree containing one node, labeled &quot;$a$&quot; $P(T_a) := p_a$
.... $F := {T_a}<em>{a \in \Sigma}$ // invariant: $\forall T \in F, P(T) = \sum</em>{a \in T} p_a$
//
// main loop
while $F$ contains at least two trees do
.... $T_1 := argmin_{T \in F} P(T)$ // smallest frequency sum
.... $T_2 := argmin_{T \in F, T \neq T_1} P(T)$ // 2nd-smallest frequency sum
.... remove $T_1$ and $T_2$ from $F$
.... $T_3$ := merge of $T_1$ and $T_2$
.... $P(T_3) := P(T_1) + P(T_2)$
.... add $T_3$ to $F$
return the unique tree in $F$</p>
</blockquote>
<h3 id="4-exmaple">4. Exmaple</h3>
<p>a, b, c, d 가 있고 빈도가 순서대로 .6, .25, .1, .05 라고 하자. 따라서 먼저 c, d를 머징한다. 그럼 a, b, (c,d) 가 있는 트리가 순서대로 .6, .25, .15 의 sum of symbol frequency 를 갖는다. 그 다음은 b, (c,d) 트리를 머징. 그럼 a, (b,c,d) 가 있는 트리가 순서대로 .6, .4 의 sum of symbol frequency 를 갖는다. 남은 둘을 합친다. 그럼 아까 살펴본 variable-length prefix-free code 가 완성된다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/d3026bdf-fb07-4c13-b078-5e1c6828c83d/image.png" alt=""></p>
<h3 id="proof-이어서">proof 이어서...</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[독학으로 IOS 앱 만든 후기]]></title>
            <link>https://velog.io/@clueless_coder/%EB%8F%85%ED%95%99%EC%9C%BC%EB%A1%9C-IOS-%EC%95%B1-%EB%A7%8C%EB%93%A0-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@clueless_coder/%EB%8F%85%ED%95%99%EC%9C%BC%EB%A1%9C-IOS-%EC%95%B1-%EB%A7%8C%EB%93%A0-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Wed, 18 Oct 2023 21:52:23 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/clueless_coder/post/37adf6b9-953f-4a9d-a78b-90bde5cba198/image.png" alt=""></p>
<p>혼자 유투브, 구글 등 보면서 IOS 앱 만들어서 앱스토어 올리기까지 아주 간단한 후기를 공유하려 한다. 일단 비교적 간단한 앱을 만들 예정이었기 때문에 굳이 어떤 수업을 들을 필요는 없다고 생각했고, 그렇게 이것저것 찾아보며 해본 결과 다음과 같다.</p>
<h2 id="1-독학으로도-가능한가">1. 독학으로도 가능한가?</h2>
<p>나는 구현하고 싶은 기능들을 유투브나 구글링을 통해서 찾아보면서 끼워 맞추기 식으로 만들었다. 물론 내 코드가 좋다고 할 수는 없겠으나 원하는 기능을 구현하는 것에는 누구나 큰 문제가 없을 것 같다. </p>
<h2 id="2-앱-공부-시작은-어떻게-했나">2. 앱 공부 시작은 어떻게 했나?</h2>
<p>먼저 나는 애플 웹사이트에서 제공하는 14시간짜리 튜토리얼(영상은 아니고 인터렉티브한 문서 스타일이다)을 보면서 기본적인 SwiftUI 사용법을 공부했다. 나는 그냥 빨리 만들어서 배포하는 것이 목적이었기에 내가 구현할 기능과 관련 없는 부분은 스킵하고, 앱을 만들면서 어려운 부분이 있으면 참고했다. 그리고 그 튜토리얼에 나오지 않는 기능들은 유투브나 구글에 &quot;어떤 기능의 리스트 만들기 swiftui&quot; 같이 검색했다. 엄청 잘나온다. 유투브에 보면 어떤 앱 하나를 만드는 시리즈식 튜토리얼이 많은데, 거기서 내가 원하는 기능을 구현하는 파트를 들어가서 참고하면서 코드를 짰다.</p>
<h2 id="3-밑바닥-공부부터-배포까지-얼마나-걸렸나">3. 밑바닥 공부부터 배포까지 얼마나 걸렸나?</h2>
<p>대략 3개월 걸렸다. 일단 나는 컴퓨터 관련 공부를 하고 있는 학생이긴 하지만, 언어를 하나만 알고 있어도 충분히 금방 배울 수 있을 거 같다. 그리고 무엇보다도 결과를 바로 시각적으로 보면서 어떤 상품을 만드는 게 재미있었다. 그래서 다른 공부보다 더 빨리 배우고 만들고 할 수 있는 거 같다. </p>
<p>결론적으로 다시 한 번 말하지만 <strong>간!단!한!</strong> 앱 만들기는 재미있고 취미로도 좋은 것 같다! 앞으로 기능도 좀 더 추가하고, 개선해서 벨로그에 소개해보겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[왕초보 네트워크 1: 그래서 인터넷이 뭔데?]]></title>
            <link>https://velog.io/@clueless_coder/%EC%99%95%EC%B4%88%EB%B3%B4-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-1-%EA%B7%B8%EB%9E%98%EC%84%9C-%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%B4-%EB%AD%94%EB%8D%B0</link>
            <guid>https://velog.io/@clueless_coder/%EC%99%95%EC%B4%88%EB%B3%B4-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-1-%EA%B7%B8%EB%9E%98%EC%84%9C-%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%B4-%EB%AD%94%EB%8D%B0</guid>
            <pubDate>Wed, 08 Feb 2023 17:24:28 GMT</pubDate>
            <description><![CDATA[<h2 id="그래서-인터넷을-뭐라고-해야되지">그래서 인터넷을 뭐라고 해야되지?</h2>
<blockquote>
<p>인터넷이 인터넷이라 인터넷이라 답하였는데..., 무엇이 인터넷이냐 하시면...</p>
</blockquote>
<p>인터넷이 뭔가요? 라고 물으면 사실 뭐라고 딱 정리해서 말하기가 어렵다. 우리 삶에 너무 침투해 있기에 그냥 인터넷이 인터넷이지! 이런 생각 밖에는... 하지만 인터뷰에서 누가 &quot;인터넷을 설명해보세요.&quot; 하면 &quot;인터넷, 우리가 맨날 쓰는 그거요!&quot; 라고 할 순 없으니, 쿠로쓰(James W. Kurose: Computer Networking - A Top-Down Approach의 저자) 교수님의 말을 빌려보자.</p>
<p>인터넷을 설명하려 할때, 두 가지 관점으로 답을 할 수 있다.
첫 번째는 nuts and bolts 관점, 두 번째는 인터넷을 서비스를 제공할 수 있게끔 도와주는 infrastructure로 보는 관점. 먼저 첫 번째 관점부터 보자.</p>
<blockquote>
<p>본 글에서는 전문용어(jargon)과 주요 문장은 그냥 영어 그대로 썼다. 중간중간 영어 용어를 소리나는대로 적은 부분도 있다.</p>
</blockquote>
<h3 id="인터넷은-무엇인가-nuts-and-bolts-description">인터넷은 무엇인가? nuts-and-bolts description</h3>
<p><strong>인터넷은 네트워크인데, 전세계의 computing devices 를 연결하는 네트워크다. (Internet is a computer network that interconnects billions of computing devices throughout the world)</strong>
이런 computing device들은 초기에는 데스크탑 컴퓨터, 서버 컴퓨터들이었고, 이제는 스마트폰, 태블릿, 자동차, 스마트 냉장고 등등 많은 것들이 computing device가 됐다. 그리고 이런 디바이스들을 인터넷 용어로 <strong>host</strong> 혹은 <strong>end system</strong> 이라고 한다 (당신의 폰, 랩탑, 인터넷과 연결된 자동차, 네이버 데이터 센터에 있는 서버 컴퓨터 등등이 모두 호스트다!). 앞으로는 host와 end system을 혼용해서 사용하겠다.</p>
<p>그럼 이런 호스트들은 어떻게 서로 연결되어 네트워크를 이루는가? 바로 <strong>communication link</strong> 와 <strong>packet switch</strong> 들로 연결된다.</p>
<p><strong>Communication link</strong> 는 물리적으로 디바이스들을 연결해줄 수 있는 여러 종류의 선들을 의미한다. 우리가 일반적으로 케이블이라고 하는 것들이다 (집에서 볼 수 있는 인터넷 연결 케이블, 땅속에 묻혀있을 광케이블 등등). 그거 외에도 여러 종류가 있는데, 예를 들어 coaxial cable, copper wire, optical fiber, radio spectrum 등이 있다. 그리고 물론 링크의 종류마다 데이터를 전달하는 속도가 다를 것이다. 이 속도를 <strong>transmission rate</strong> 라고 하고, 단위는 bits/second (초당 얼마나 많은 비트가 이동하는가) 이다.
A 호스트에서 B 호스트로 어떤 정보를 링크를 통해서 전달한다고 하자. 그럼 먼저 보낼 데이터를 작은 조각으로 나누고 각 조각 앞에 header bytes 를 붙여야한다. 헤더가 붙은 작은 조각의 데이터를 <strong>packet</strong> 이라고 한다. 그리고 이 페켓들이 B에 도착하면 다시 assemble 되어 원래의 데이터로 돌아간다. 우리는 앞으로 계속 이 페켓의 관점으로 데이터가 어떻게 이동하는지 살펴볼 것이다.</p>
<p><strong>Packet switch</strong> 는 중간중간에 있는 포인트 같은 애들로 페켓을 정보가 들어오는 communication link에서 정보를 보내줄 communication link로 전달해준다 (한국에서 아르헨티나로 직접 연결되는 한 줄의 링크가 있을 수는 없으니!). 
페켓 스위치에는 여러 종류가 있는데, 중요한 것은 <strong>router</strong> 와 <strong>link-layer switch</strong> 다. 링크 레이어 스위치는 주로 access network (end system들과 직접 연결된 네트워크, 쉽게 생각해서 집 네트워크) 에서 사용되고, 라우터는 network core (access network와 반대로 전체 네트워크에서 엔드 시스템들과 직접 연결되지 않은 안쪽 부분의 네트워크)에서 주로 사용된다. 출발지점부터 여러 링크와 페켓 스위치를 순서대로 거쳐 도착지에 도달하는 순서를 route 혹은 path 라고 한다.</p>
<p>그럼 이렇게 호스트들이 연결될 수 있도록하는 링크, 페켓 스위치 등의 인프라는 누가 제공하는가? 인터넷을 사용할 수 있게끔 해주는 엔티티들을 <strong>Internet Service Provider (ISP)</strong> 라고 한다. SKT 같은 회사가 만든 네트워크를 생각해도 좋다. 지역 단위로 네트워크를 제공하는 ISP를 lower-tier ISP 라고 하고 이런 lower-tier 들은 국가, 국제적 단위의 upper-tier ISP 에 연결된다. Upper-tier ISP 들은 high-speed router와 fiber-optic link를 통해 직접적으로 연결된다.</p>
<p>그럼 인터넷을 이루는 조각들을 알아보았는데, 그럼 정보를 보낼 때 아무렇게나 막 보낼 수 있을까? 물론 아니다. end system, packet switches 등의 인터넷 구성요소들은 <strong>protocol</strong> 에 따라 정보를 보내고 받는다. 인터넷에서 가장 중요한 두 가지 프로토콜은 <strong>Transmission Control Protocol (TCP)</strong> 와 <strong>Internet Protocol (IP)</strong> 이다. 그래서 인터넷의 pricipal protocols를 TCP/IP 라고 한다.
IP 프로토콜은 페켓의 라우터와 호스트들 사이에서 주고 받아질때, 어떤 format이 되어야 하는지를 정한 규칙이다. 이런 포로토콜을 누구나 따라야 서로 정보를 교환할 수 있기에, <strong>Internet standard</strong> 가 IETF (Internet Engineering Task Force) 라는 단체에 의해서 정해졌다. 이런 스탠다드 도큐멘트들은 <strong>requests for comments (RFCs)</strong> 라고 하는데, 원래 &#39;이게 네트워크와 우리가 따라야할 프로토콜에 대한 내 아이디언데, 코멘트를 달아주세요&#39; 하는 문서로 시작되었다가 standard 가 된 것들이다. 약 9000 개의 RFC 들이 있고 (굉장히 테크니컬하여 나같은 초보자는 접근하기 어렵다), TCP, IP, HTTP, SMTP 등 여러 프로토콜과 커뮤니케이션 링크에 대하여 정의하고 있다. WiFi 와 Ethernet 에 대해서는 IEEE 802 LAN Standard Committee 가 그 standard를 정의하고 있으니 참고하시라.</p>
<h3 id="인터넷은-무엇인가-services-description">인터넷은 무엇인가? Services Description</h3>
<p><strong>인터넷은 어플리케이션들에게 서비스를 제공하는 인프라다 (Internet is an infrastructure that provides services to applications)</strong> 라고도 할 수 있다. 이메일, 웹서핑, 핸드폰의 여러 앱들처럼 엔드 시스템들이 서로 정보를 주고 받아야하는 일명 인터넷 어플리케이션 혹은 distributed application 에게 서비스를 제공하는 인프라로 인터넷을 바라보는 것이다. </p>
<p>이런 관점으로 인터넷을 정의할때, 한 가지 생각해볼 것이 있다. 인터넷을 사용하는 어떤 앱이 있다고 해보자. 개발자는 이 앱을 사용자의 기기 즉 엔드 시스템 위에서 돌아가도록 자바든 파이썬이든 어떤 프로그래밍 언어를 이용해서 만들었을 것이다. 그런데 내 스마트폰에서 돌아가고 있는 이 앱은 어떻게 다른 스마트폰에서 돌아가고 있는 앱과 정보를 주고 받으라고 인터넷에게 요청을 하고있는 것인가? 이 인터넷이라는 인프라에게 어떻게 지시를 해야 한 기기에서 돌아가고 있는 프로그램에서 생성된 정보를 다른 기기에서 돌아가고 있는 프로그램에게 전달할 것인가?</p>
<p>인터넷과 연결된 호스트들은 socket interface 라는 것이 있어서, 이를 통해 인터넷 인프라에게 이 기기의 프로그램의 정보를 다른 기기의 프로그램에게 전달해달라고 구체적으로 요청할 수 있다. 이 인터넷 소켓 인터페이스는 프로그램의 정보를 원하는 위치로 보내기 위한 일련의 규칙들이다. 이는 마치 인터넷이 우체국이고, 우편물을 보내려면 우리가 우체국이 알아들을 수 있도록, 우편물을 봉투에 담고, 출발지와 도착지 정보를 적고, 포장하고, 오른쪽 상단에 스탬프를 찍고, 우편함에 넣고 하는 일련의 과정을 따르는 것과 같다. 그리고 우체국은 우편물을 전달하는 것 외에도 다양한 서비스를 제공한다. 예를 들어, express delivery, reception confirmation 같은 것들이 있다. 이와 마찬가지로 우리고 인터넷 어플리케이션을 만들 때 인터넷이 제공하는 어떤 서비스를 사용할지 선택할 수 있다. 이에 대해서는 나중에 더 살펴보자.</p>
<h2 id="프로토콜이란">프로토콜이란</h2>
<p>인터넷이 대략 무엇인지 감이 잡혔다면, 각각의 구성 요소와 인터넷이 동작하게끔 하는 규칙들은 무엇인지 조금 더 구체적으로 살펴볼 필요가 있다. 먼저 정보를 주고 받기 위한 규칙 혹은 약속이라고 할 수 있는 프로토콜을 살펴보자. </p>
<p>네트워크 프로토콜은 사람들이 소통하기 위한 프로토콜과 다를 바가 없다. 사람이라는 주체가 hardware 나 software 가 됐을뿐. 특정 메시지를 내가 보내면 (예를 들어 안녕!), 다른 사람이 어떤 메시지를 보내거나 무시하고 (나도 안녕! 혹은 답 없음), 그 받은 메시지에 대해서 특정 행동을 취하는 것이다 (몇 시야? 혹은 일정 기간 답이 없으니 소통을 포기함). 만약 대화의 두 주체가 서로 다른 프로토콜을 따른다면, 대회가 이뤄지지 않을 것이다. 네트워크에서도 마찬가지다. Communicating entity 들이 서로 다른 프로토콜을 따른다면 태스크를 수행할 수가 없다.</p>
<p>프로토콜의 정식 정의는 다음과 같다:
<em>A protocol defines the format and the order of messages exchanged between two or more communicating entities, as well as the actions taken on the transmission and/or receipt of a message or other event.
: 프로토콜은 둘 이상의 communicating entity 들이 주고 받는 메시지나, 전달 방식, 받은 메시지나 이벤트에 대한 액션의 형식과 순서를 정의한다.</em></p>
<p>쉽게 말해서 네트워크 프로토콜은 A랑 B가 서로 소통해서 어떤 일을 하고 싶은데, 그때 <strong>어떤</strong> 메시지를 어떤 <strong>순서</strong>로 <strong>어떻게</strong> 주고 받고, 답장으로 특정 메시지나 특정 이벤트를 수신하면 다시 어떤 메시지를 보내고, 어떤 행동을 취할지 정해놓은 규칙들이라고 생각하면 되겠다!</p>
<p>그리고 서로 다른 프로토콜은 서로 다른 태스크를 수행한다는 점을 알아두자. 컴퓨터 네트워킹 과목은 결국 이런 여러가지 네트워크 프로토콜을 공부하는 것과 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[아침 파이토치 1/30 (월)]]></title>
            <link>https://velog.io/@clueless_coder/%EC%95%84%EC%B9%A8-%ED%8C%8C%EC%9D%B4%ED%86%A0%EC%B9%98-130-%EC%9B%94</link>
            <guid>https://velog.io/@clueless_coder/%EC%95%84%EC%B9%A8-%ED%8C%8C%EC%9D%B4%ED%86%A0%EC%B9%98-130-%EC%9B%94</guid>
            <pubDate>Mon, 30 Jan 2023 20:50:07 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❤️🧡💛💚💙💜🖤</p>
</blockquote>
<ol>
<li><p>머신러닝은 크게 두 부분으로 나뉜다. 무엇과 무엇인가? (ML is a GAME of TWO PARTS)</p>
</li>
<li><p>weight = 0.7, bias = 0.3 으로 linear regression formula 를 사용하여, 시작과 끝이 0, 1이고 step 이 0.02 인 X, y 텐서를 만들라.</p>
</li>
<li><p>데이터를 train, test set 으로 나눠라. 그냥 순서대로 간단히, 80 대 20으로.</p>
</li>
<li><p>plot_predictions() 함수를 만들라. 파라미터로 train_data, train_labels, test_data, test_labels, predictions 를 받고, 3.에서 만든 데이터를 디폴트로 놓고 predictions=None 으로 한다. 훈련(blue), 테스트(green), 예측 값(red)을 scatter plot으로 플롯하는 함수다. legend, figsize 설정할 것. ❤️</p>
</li>
<li><p>이제 linear regression 모델을 만들자. 일단 forward() 까지만 한다. 모델 이름은 LinearRegressionModel 로 하라.</p>
</li>
<li><p>nn.Module, nn.Parameter, torch.randn(.. requires_grad=True), def forward() 의 역할을 설명하라.</p>
</li>
<li><p>만든 모델을 호출하고 (랜덤 씨드를 설정할 것), 모델의 파라미터를 두 가지 방법으로 확인해보라.</p>
</li>
<li><p>prediction 을 해보라. 세 가지 방법을 모두 시도하고, 각각의 방법의 차이를 설명하라. 가장 추천하는 방법은 무엇인가?</p>
</li>
<li><p>4.에서 만든 함수를 가지고, 예측 값을 플롯해보라. 어떤가? 우리는 무엇을 해야하는가?</p>
</li>
<li><p>모델을 훈련한다는 것은 무엇인가? ❤️ 훈련할때 필요한 두 가지 요소(알고리즘)은 무엇인가? ❤️ 특히, 파이토치에서 필요한 두 가지 루프는 무엇인가? </p>
</li>
</ol>
<hr>
<p>설명과 답: <a href="https://colab.research.google.com/drive/1eqysqcUGPCfkT9vPiH7E_nMb-wM3tnV1?usp=sharing">https://colab.research.google.com/drive/1eqysqcUGPCfkT9vPiH7E_nMb-wM3tnV1?usp=sharing</a> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[머신러닝 이론 1]]></title>
            <link>https://velog.io/@clueless_coder/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EC%9D%B4%EB%A1%A0-1</link>
            <guid>https://velog.io/@clueless_coder/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EC%9D%B4%EB%A1%A0-1</guid>
            <pubDate>Wed, 25 Jan 2023 02:13:45 GMT</pubDate>
            <description><![CDATA[<p>손으로 아이패드에 써서 업로드
지운 버전 업로드
due 1/25(wed)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[아침 파이토치 1/24]]></title>
            <link>https://velog.io/@clueless_coder/%EC%95%84%EC%B9%A8-%ED%8C%8C%EC%9D%B4%ED%86%A0%EC%B9%98-2</link>
            <guid>https://velog.io/@clueless_coder/%EC%95%84%EC%B9%A8-%ED%8C%8C%EC%9D%B4%ED%86%A0%EC%B9%98-2</guid>
            <pubDate>Tue, 24 Jan 2023 16:57:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>오답 순서: 처음 틀린 경우부터~ ❤️🧡💛💚💙💜🖤</p>
</blockquote>
<ol>
<li>토치를 불러오고 버전을 확인해보라</li>
<li>스칼라를 만들어보라. 디멘션은 무엇인가?</li>
<li>벡터를 만들어보라. 디멘션은 무엇인가?</li>
<li>텐서를 만들어보라. 디멘션은 무엇인가?</li>
<li>❤️ <code>torch.tensor([[[1,2,3],[4,5,6],[7,8,9]]])</code> 의 shape은 무엇인가? 어떻게 각 디멘션을 확인하는 것이 좋은가? 코드로도 확인하라.</li>
<li>size 가 (3,4) 인 랜덤 텐서를 만들어보라.</li>
<li>위와 같은 사이즈로 제로 텐서를 만들어보라.</li>
<li>위와 같은 사이즈로 원스 텐서를 만들어보라.</li>
<li>1에서 10까지의 레인지 텐서를 만들어보라.</li>
<li>위와 같은 사이즈를 가져다가 제로스 텐서를 만들어보라.</li>
<li>[1,2,3]을 float16 데이터타입의 텐서로 만들어보라.</li>
<li>파이토치와 딥러닝 임플리멘테이션에서 주의해야할 세 가지 에러를 말해보라.</li>
<li>❤️ [3,6,9]를 텐서로 만들고 데이터타입은 float64, 디바이스, grad track을 false로 설정하라.</li>
<li>(3,4) 짜리 랜덤 텐서를 만들고 그 텐서의 데이터타입, 모양, 디바이스를 확인하라.</li>
<li>[1,2,3]을 파이토치 텐서로 만들고 각 원소에 10을 더하라.</li>
<li>10을 곱하라</li>
<li>10을 빼라</li>
<li>14~16 파이토치 인빌트도 써보라.</li>
<li>element wise multiplication을 수행하라.</li>
<li>❤️ mat mul을 수행하라. 같은 함수의 alias도 쓰라. mm 과 matmul의 차이는 무엇인가?</li>
<li>다음과 같은 매트릭스가 있다. 컬럼 뷰와 로우 뷰로 결과의 첫번째 컬럼과 첫번째 로우를 설명하라.
<img src="https://velog.velcdn.com/images/clueless_coder/post/7ab37126-8d38-4851-bf18-14a91ba008ca/image.png" alt=""></li>
<li>(2,3) 짜리 랜덤 텐서를 두 개 만들고, 둘을 mat mul 해보라. 에러가 생긴다면 transpose로 해결해보라. </li>
</ol>
<p>필기 및 답: <a href="https://colab.research.google.com/drive/1iAyZScrrwbojUBtQ_uGexsue57m3ydCw?usp=sharing">https://colab.research.google.com/drive/1iAyZScrrwbojUBtQ_uGexsue57m3ydCw?usp=sharing</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[아침 파이토치 1/19]]></title>
            <link>https://velog.io/@clueless_coder/%EC%95%84%EC%B9%A8-2%EC%8B%9C%EA%B0%84-%ED%8C%8C%EC%9D%B4%ED%86%A0%EC%B9%98-1</link>
            <guid>https://velog.io/@clueless_coder/%EC%95%84%EC%B9%A8-2%EC%8B%9C%EA%B0%84-%ED%8C%8C%EC%9D%B4%ED%86%A0%EC%B9%98-1</guid>
            <pubDate>Thu, 19 Jan 2023 14:31:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>&quot;If you can build a simple rule-based system that doesn&#39;t require machine learning, do that.&quot;</p>
</blockquote>
<h2 id="how-to-approach-the-course">How to Approach the Course</h2>
<ol>
<li>Code along</li>
<li>Experiment, experiment, experiment</li>
<li>Visualize what you don&#39;t understand</li>
<li>Ask questions</li>
<li>이북 Exercise 섹션 꼭!! 하기</li>
<li>Share your work</li>
</ol>
<h2 id="리소스">리소스</h2>
<p>북마크 Pytorch Udemy 폴더에 있음!
관련 메일은 kk7 지메일로 올거임!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Airflow 엄청 자세한 튜토리얼 #왕초심자용 ]]></title>
            <link>https://velog.io/@clueless_coder/Airflow-%EC%97%84%EC%B2%AD-%EC%9E%90%EC%84%B8%ED%95%9C-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC-%EC%99%95%EC%B4%88%EC%8B%AC%EC%9E%90%EC%9A%A9</link>
            <guid>https://velog.io/@clueless_coder/Airflow-%EC%97%84%EC%B2%AD-%EC%9E%90%EC%84%B8%ED%95%9C-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC-%EC%99%95%EC%B4%88%EC%8B%AC%EC%9E%90%EC%9A%A9</guid>
            <pubDate>Mon, 04 Jul 2022 16:42:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>에어플로우에 대한 정보를 제공하는 정확하고 전문적인 글들이 많고, 여기서는 나와 같은 초보분들을 위해 설치부터 아주 간단한 실습을 다룰 것이기 때문에 이론은 직관적으로만 설명해서 느낌만 가지고 넘어가도록 하겠다.
이론은 필요 없고 바로 실습을 원한다면, <strong>Airflow 실습하기</strong> 파트로 넘어가자. 😉 </p>
</blockquote>
<blockquote>
<p>🥸 이 튜토리얼의 코드는 여기!
<a href="https://github.com/mitchell-pritchett/airflow-tutorial.git">https://github.com/mitchell-pritchett/airflow-tutorial.git</a></p>
</blockquote>
<h1 id="airflow란">Airflow란?</h1>
<p>에어플로우는 한마디로 일련을 일들을 순차적으로 진행시켜주는 프로젝트 관리자 같은 애다. 에어플로우와 에어플로우의 구성 요소를 조금 의인화해서 설명을 하겠다. </p>
<p>우리가 어떤 보석💍 공장의 공장장이라고 해보자. 공장에서 보석 원재료를 긁어오고, 세척하고, 가공하고, 제품을 만들고, 포장해서 판매하기까지 이 일련의 과정들이 주기적으로, 순차적으로 잘돌아가야 한다. 공장장으로서 일이 <strong>주기적으로</strong> 자동으로 잘돌아가도록 <strong>스케줄을 짜고(워크플로우 스케줄링)</strong>, 사람들이 잘 일하고 있는지 <strong>감시(모니터링)</strong> 할 수 있는 시스템이 필요하다. 이 시스템으로 우리는 에어플로우라는 애를 쓴다. </p>
<h3 id="에어플로우에서-알아야-할-개념">에어플로우에서 알아야 할 개념</h3>
<ul>
<li><strong>워크플로우</strong> : 워크플로우는 의존성으로 연결된 작업들의 집합이다. 예를 들어 보석 원재료가 잘 도착해야 닦을 수 있고, 잘 닦여야 가공할 수 있고, 가공이 되어야 제품으로 만들 수 있고...</li>
<li><strong>DAG(대그)</strong> : 보석 공정 파이프라인. 순환하지 않고 시작에서 끝으로 진행되는 워크플로우 구조다. (Directed Acyclic Graph - 방향이 있는 순환되지 않는 그래프).<ul>
<li>보석 원재료를 긁어오고, 닦고, 가공하고, 제품을 만들고, 포장해서 판매하기까지 일련의 순환하지 않는 과정. 에어플로우의 핵심 구조.</li>
<li>한 보석 공장에도 여러 대그가 있을 수 있다. 다이아몬드 대그, 사파이어 대그, 진주 대그...</li>
</ul>
</li>
<li><strong>Task(태스크)</strong> : 대그의 단위 작업 (원재료 긁어오기 태스크, 세척하기 태스크, ...)</li>
</ul>
<h3 id="에어플로우-구성-요소">에어플로우 구성 요소</h3>
<p>에어플로우에는 몇 가지 주요 구성 요소가 있다.</p>
<ul>
<li><strong>에어플로우 사용자 (나)</strong> 👩‍💻 : 공장장</li>
<li><strong>웹서버</strong> 🖥️ : 공장장이 사람들이 잘 일하는지 감시할 수 있도록 보기 좋게 여러 요소가 잘 정리된 화면. 화면을 통해 일을 시작하거나 멈추라고 명령을 내릴 수 있다.</li>
<li><strong>스케줄러</strong> 💁⌚ : 워크플로우 시간 관리 담당 비서</li>
<li><strong>Metastore</strong> 📑 : 여러 대그 정보를 써놓은 파일철. 대그가 잘 진행되었는지, 중간에 어느 과정에서 망했는지, 성공했는지 등을 적어놓는다.</li>
<li><strong>Executor</strong> 👷 : 작업을 배치하는 작업 반장</li>
<li><strong>Worker</strong> 👩‍🔧 :  작업을 수행하는 일꾼</li>
<li><strong>Operator</strong> ⚙️ : 작업을 수행할 때 사용하는 기계. 공장장이 이런 기계들을 설계해서(파이썬 코드로) 공정 순서대로 엮어주면 한 대그가 완성된다. <blockquote>
<p>✅ <strong>오퍼레이터를 실행(세팅)하면 태스크</strong>
예를 들어, 원자재를 세척하는 세척 오퍼레이터가 있다고 해보자. 같은 종류의 세척 기계를 다이아몬드에 대해서도 쓸 수 있고, 사파이어에 대해서도 사용할 수 있다. 이 세척 기계로 다이아몬드를 세척하기로 하고, 다이아몬드 세척에 적합한 조건들을 세팅하고 세척한다면, 이것이 다이아몬드 세척 <strong>태스크</strong> 가 된다. 즉, 오퍼레이터에 특정 인풋과 조건을 넣어주면 특정 태스크(작업)가 되는 것이다.</p>
</blockquote>
</li>
</ul>
<h3 id="간단한-에어플로우-구조-및-동작-방식">간단한 에어플로우 구조 및 동작 방식</h3>
<p><em>다시 한 번 말하지만, 에어플로우 이론에 대한 정확하고 구체적인 정보는 다른 좋은 문서들을 참고하시길 바란다</em></p>
<p>여기서는 다이아몬드 공정 파이프라인(대그)을 만든다고 해보자. </p>
<ol>
<li><p>나(공장장)는 다이아몬드 공정에 필요한 기계(오퍼레이터)들을 만든다. </p>
<ul>
<li>다이아몬드 긁어오기 기계</li>
<li>다이아몬드 세척하기 기계</li>
<li>다이아몬드 가공하기 기계 </li>
<li>다아아몬드 반지 만들기 기계</li>
<li>다이아몬드 반지 출하하기 기계</li>
</ul>
</li>
<li><p>기계들을 어떤 순서로 연결할지 설계해서 하나의 다이아몬드 공정 파이프라인를 만들어준다 (긁어오기 &gt;&gt; 세척 &gt;&gt; 가공 &gt;&gt; 반지 &gt;&gt; 출하). 어떤 주기로 이 대그를 돌릴지도 정해둔다.</p>
</li>
<li><p>공정 순서와 기계들이 준비되었으니 모니터(웹서버)를 보고 몇 번의 클릭클릭으로 일 시작을 지시하거나, 비서(스케줄러)에게 직접 말해서 언제 일을 시작하도록 하라고 지시한다.</p>
</li>
<li><p>이때 언제, 어떤 대그를 실행했는지 파일(메타스토어)에 적어둔다.</p>
</li>
<li><p>작업 반장(익제큐터)은 공장장이 설계한 대그를 보고, 할 일을 순서대로 리스트 업해서 일꾼(워커)들에게 순서대로 일을 시킨다.</p>
</li>
<li><p>작업 내역(각 작업의 성공 여부, 과정 기록, 작업 완료 등)을 파일(메타스토어)에 적는다. </p>
</li>
<li><p>파일을 참고해서 모니터로 보여줄 내용을 업데이트한다. 공장장은 이 업데이트된 모니터를 보고 대그가 성공했는지, 성공하지 못했다면 어디서 작업이 막혔는지를 확인한다.</p>
</li>
<li><p>반지 만들기 작업에서 오류가 생겼다면 반지 만들기 기계를 고쳐준다. 다시 대그를 시작하라고 지시한다.</p>
</li>
</ol>
<blockquote>
<p>✅ 보석 공장을 예시로 든 이유가 있는데, 에어플로우는 실시간으로, 초단위로 진행되어야 하는 공정에는 적합하지 않다. 보석 공장처럼 하루 한 번, 일주일에 한 번 이렇게 진행되는 공정을 관리하는 데에 적합하다.</p>
</blockquote>
<h1 id="airflow-실습하기">Airflow 실습하기</h1>
<h2 id="📥-설치하기">📥 설치하기</h2>
<blockquote>
<p>✅ 나는 맥과 WSL에서 모두 진행해보았다. 둘 다 동일하게 문제없이 아래에 소개할 방식으로 잘돌아갔다.</p>
</blockquote>
<ol>
<li><p>먼저 새로운 콘다 환경을 하나 만들어줬다. 파이썬은 3.7 버전, 환경 이름은 airflow_env라고 정했다. 새로 만든 환경을 활성화시킨다.</p>
<pre><code class="language-zsh">conda create -n airflow_env python=3.7
conda activate airflow_env</code></pre>
</li>
<li><p>에어플로우를 설치한다. 홈 디렉토리에 airflow 라는 폴더가 하나 생겼을 거다.</p>
<pre><code class="language-bash">pip3 install apache-airflow</code></pre>
</li>
<li><p><code>airflow</code> 라고 한 번 쳐서 잘 설치되었는지 확인하자. 사용할 수 있는 명령어에 대한 설명이 나온다면 성공.</p>
</li>
<li><p>airflow 폴더로 이동하고, airflow 데이터베이스를 초기화해준다.</p>
<pre><code class="language-bash">cd airflow</code></pre>
<p>에어플로우 폴더 안에는 이런 파일들이 있다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/1844fcb6-8743-4a29-971c-88999dcd3f1a/image.png" alt=""></p>
<pre><code class="language-bash">airflow db init</code></pre>
<p>여기까지 하고 나면 아래처럼 <code>airflow.db</code> 라는 애가 하나 생겼을 거다. 메타스토어를 만들었다고 생각하면 된다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/bfdb24bd-73cf-43ff-a938-26fb92bdec6f/image.png" alt=""></p>
</li>
<li><p>airflow 폴더 안에 dags 라는 디렉토리를 생성해준다.</p>
<pre><code class="language-bash">mkdir dags</code></pre>
<p>이 디렉토리에 대그들을 만들어줄 거다. 아래처럼 디렉토리가 생성되면 된다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/c8d38fac-4f4f-403e-a43a-358abb18d4b1/image.png" alt=""></p>
</li>
<li><p>에어플로우를 사용할 때 필요할 관리자 계정을 만들어준다.</p>
<pre><code class="language-bash">airflow users create -u admin -p admin -f Clueless -l Coder -r Admin -e admin@admin.com</code></pre>
<p><code>-u</code> 다음에 아이디, <code>-p</code> 다음에는 비번 (나는 둘 다 그냥 admin이라고 함), <code>-f</code> 다음에는 본인이 사용할 이름, <code>-l</code> 다음에는 성, 마지막 부분에는 이메일을 쓴다. </p>
</li>
<li><p>에어플로우 웹서버와 스케줄러를 켜주겠다. 먼저 웹서버를 한 터미널에서 실행시키고, 포트는 사용할 수 있는 포트를 사용하면 된다(디폴트가 8080 포트이므로 8080 포트를 쓸 거면 <code>-p 8080</code>은 빼도 된다).</p>
<pre><code class="language-bash">airflow webserver -p 8080</code></pre>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/08165327-abc8-48dc-a58b-2754cd6493e7/image.png" alt=""> 아래처럼 나오면 성공이다.
다른 터미널 창을 하나 더 열어서 스케줄러를 실행한다. (새로 열린 터미널 창에서 아까 만든 콘다 환경 활성화시키는 것을 잊지 않도록 한다.) </p>
<pre><code class="language-bash">airflow scheduler</code></pre>
<p>스케줄러도 실행한다. 아래처럼 나오면 성공.
<img src="https://velog.velcdn.com/images/clueless_coder/post/f1956b71-d52a-4126-801e-6fc43c4ef3fe/image.png" alt=""></p>
</li>
</ol>
<blockquote>
<p>⚠️ <strong>에러가 나는 경우</strong>
<img src="https://velog.velcdn.com/images/clueless_coder/post/8d7dce8d-dd81-4215-9eb4-431e32e3f927/image.png" alt=""> 이런 에러가 난다면, 이미 웹서버가 돌아가고 있는데, 또 돌릴라고 해서 그런 거다. 원래 켜놓은 웹서버 주소로 접속하면 된다. 
혹은 한 원격 서버를 여러 유저가 사용하는 경우 동일한 포트를 사용하면서, 에러가 난다. 그럴 경우 그냥 없애 버리고 (맨아래에 써있는 <code>The webserver is already running under PID 8050</code> 에서 pid 인 8050 자리의 숫자를 확인하고 <code>kill &lt;PID&gt;</code> 명령으로 삭제해버리자). 포트가 겹치지 않도록 협의한 후에 본인이 사용 가능한 포트로 웹서버를 연다. </p>
</blockquote>
<ol start="7">
<li>웹서버에 들어가보자. 나는 로컬로 진행했고, 8080번 포트를 사용하였으므로 브라우저를 열고 주소창에 <code>0.0.0.0:8080</code> 아니면 <code>localhost:8080</code> 을 쳐서 웹서버에 접속한다. 이런 화면이 뜰거다. 여기에 본인 아이디와 비번을 넣고 로그인. 
<img src="https://velog.velcdn.com/images/clueless_coder/post/078e0c84-0628-4675-b511-56f7e6cd1ab8/image.png" alt="">
아래처럼 예시 대그들이 보이는 화면이 뜬다. CLI로 스케줄러에게 직접 지시할 수 있으나, 여기서는 웹서버를 활용해서 대그를 실행, 종료해보자.
<img src="https://velog.velcdn.com/images/clueless_coder/post/68d53c77-b937-4cb0-bcd2-b774441adaa7/image.png" alt="">
이 화면의 우측에 보면, Actions 칼럼에 실행 표시와 쓰레기통 표시로 각각 대그를 실행, 삭제할 수 있다.</li>
</ol>
<h2 id="🖥️-웹서버-사용하기">🖥️ 웹서버 사용하기</h2>
<p>예시 대그로 웹서버를 통해 어떻게 대그를 실행, 종료시키고 각종 기록을 확인하는지 알아보겠다. 예시 대그 중 하나인 <code>example_branch_datetime_operator_2</code>를 클릭한다. 아래와 같은 페이지가 나올 것이다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/eeac4817-037d-41f0-9f9a-a8f73e8bb4ab/image.png" alt="">
우측 상단의 <code>▶️</code> 버튼을 클릭하고 <code>Trigger DAG</code> 를 클릭하여 실행시켜보자. 화면이 아래처럼 바뀌었을 것이다. 긴 바로 된 진한 초록색은 대그가 성공적이었음을 알려주고, 긴 바가 두 개 생긴 것을 보니 대그가 두 번 실행되었다. 그리고 그 아래 작은 박스들은 해당 대그의 각 태스크가 잘 실행되었는지를 나타낸다. 색깔이 의미하는 바는 우측 상단을 참고한다.
우측 표에는 대그에 대한 여러가지 실행 기록이 나온다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/7381b873-c8a9-4652-849a-8cfed6eb731f/image.png" alt="">
좌측 상단의 <code>Graph</code> 로 들어가보면, 대그가 어떻게 이뤄졌는지 순서도를 보여주고, 어떤 타입의 태스크인지(어떤 종류의 오퍼레이터를 사용했는지) 확인할 수 있다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/9a2dcf34-bb8f-4428-bca5-4ec7ba9f5b07/image.png" alt="">
나머지 페이지도 하나씩 눌러보면 어떤 것을 의미하는지 알 것이다. <code>Code</code> 에서는 작성한 대그 코드(공장장이 설계한 오퍼레이터들과 그 연결)를 확인할 수 있다. 이 코드가 앞으로 우리(공장장)가 실제로 프로그래밍(기계 설계하고 순서도 만드는)하는 파트다. 
<img src="https://velog.velcdn.com/images/clueless_coder/post/5f60ea5d-8e2b-4750-aecf-1d2ee6e001d8/image.png" alt=""></p>
<p>대그를 일시정지 또는 재개하고 싶다면, 아래처럼 왼쪽 상단의 버튼으로 재개/정지한다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/17b68568-a8d1-4093-9a57-b8fb2b8e02bf/image.png" alt="">
이는 예시 대그이기때문에 아주 잘돌아갔을 거다. 실제로 대그를 만들어서 돌려보면 에러가 뜨는 경우가 많다. 따라서 조금 더 구체적인 웹서버 사용법은 실제 대그를 만들어보면서 익히는 것이 좋겠다.</p>
<h2 id="🛠️-대그-만들기">🛠️ 대그 만들기</h2>
<p>대그를 만드는 것은 공장장이 공정 파이프라인을 설계하는 것과 같다고 했다. 이 설계 과정을 우리는 파이썬 코드로 구현한다.</p>
<h3 id="오퍼레이터기계-종류-알기">오퍼레이터(기계) 종류 알기</h3>
<p>먼저 공정에 사용할 기계들(오퍼레이터)이 어떤 종류가 있는지 알아야 한다. 그래야 이 공정에는 이 기계를 쓰고, 저 공정에는 저 기계를 쓰고 할 것이 아닌가. 아주 다양한 오퍼레이터가 존재하지만 여기서는 실습에 사용할 몇 가지만 소개하겠다(사실 BashOperator랑 PythonOperator만 알고 있어도 (효율성을 생각하지 않는다면) 웬만한 작업은 다 할 수 있다).</p>
<p>오퍼레이터는 크게 다음과 같이 분류된다:</p>
<ul>
<li>Action Operator : 간단한 연산 수행 오퍼레이터, <code>airflow.operators</code> 모듈 아래에 존재. 실습에서 사용할 대부분의 오퍼레이터는 여기에 속한다.</li>
<li>Transfer Operator : 데이터를 옮기는 오퍼레이터, <code>&lt;출발&gt;To&lt;도착&gt;Operator</code> 꼴.</li>
<li>Sensor : 태스크를 언제 실행시킬 트리거(이벤트)를 기다리는 특별한 타입의 오퍼레이터 (예를 들어 어떤 폴더에 데이터가 쌓여지기를 기다린다든지, 요청에 대한 응답이 확인되기를 기다린다든지).</li>
</ul>
<p>이 실습에서 사용할 오퍼레이터는 다음과 같다:</p>
<ul>
<li>PythonOperator : 파이썬 코드를 돌리는 작업을 할 때 사용하는 기계</li>
<li>BashOperator : bash 명령어를 실행시키는 작업을 할 때 사용하는 기계</li>
<li>SqliteOperator : SQL DB 사용과 관련된 작업을 할 때 사용하는 기계</li>
<li>SimpleHttpOperator : HTTP 요청(request)을 보내고 응답(response) 텍스트를 받는 작업을 할 때 사용하는 기계</li>
<li>HttpSensor : 응답(response)하는지 확인할 때 사용하는 센서 기계</li>
</ul>
<h3 id="대그-프로그래밍하기">대그 프로그래밍하기</h3>
<p>이 실습에서는 네이터 지역 검색 데이터를 가져오고 저장해서 과정 완료 이메일을 보내는 것을 다룬다. 순서는</p>
<ol>
<li>데이터 저장할 공간 만들기(SQL 테이블 생성)</li>
<li>데이터 가져오는 것이 가능한지 확인하기</li>
<li>크롤링(데이터 가져오기)</li>
<li>전처리</li>
<li>저장</li>
<li>대그 완료를 알리기</li>
</ol>
<p>까지 아주 간단한 과정을 진행해보겠다 (이 뒤로 머신러닝 모델을 돌린다든지, 시각화 자료까지 만든다든지, 여러 태스크가 따라올 수 있겠다). 각 작업(태스크)에서 사용할 방법/툴과 대응되는 에어플로우 기계(오퍼레이터)를 간단한 표로 나타내었다:</p>
<table>
<thead>
<tr>
<th>태스크</th>
<th>방법/툴</th>
<th>오퍼레이터</th>
</tr>
</thead>
<tbody><tr>
<td>테이블 생성</td>
<td>SQLite 테이블 생성</td>
<td>SqliteOperator</td>
</tr>
<tr>
<td>API 확인</td>
<td>네이버 오픈 API 중 검색(지역) API</td>
<td>HttpSensor</td>
</tr>
<tr>
<td>크롤링</td>
<td>네이버 오픈 API 중 검색(지역) API</td>
<td>SimpleHttpOperator</td>
</tr>
<tr>
<td>전처리</td>
<td>파이썬 Pandas 라이브러리 사용</td>
<td>PythonOperator</td>
</tr>
<tr>
<td>저장</td>
<td>Bash 명령어 사용하여 csv로 저장하고 테이블에 저장</td>
<td>BashOperator</td>
</tr>
<tr>
<td>완료 알리기</td>
<td>파이썬 함수</td>
<td>PythonOperator</td>
</tr>
</tbody></table>
<blockquote>
<p><strong>사전 준비 : 네이버 API 어플리케이션 등록</strong>
이 준비단계는 데이터 크롤링을 할 때 API 를 사용한다면 필요한 부분으로 그렇지 않을 경우 생략해도 되고, 사용하는 API에 맞게 (카카오 API를 쓴다면, 카카오 공식 문서를 참고해서) 진행하면 된다. 
네이버 API를 사용하려면 네이버 개발자 센터에서 애플리케이션을 등록하고 클라이언트 아이디와 클라이언트 시크릿을 발급받아야 한다. 
<a href="https://developers.naver.com/docs/common/openapiguide/appregister.md#%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%93%B1%EB%A1%9D">네이버 API 사용 가이드</a>에서 엄청 친절하게 사용법을 알려준다. 그대로 따라하자.
클라이언트 아이디와 클라이언트 시크릿을 발급받았다면 API 사용은 준비 완료다.</p>
</blockquote>
<h4 id="0-대그-틀-만들기">0. 대그 틀 만들기</h4>
<p>대그의 기본적인 틀과 대그를 돌릴 주기 등을 먼저 설정해보겠다.</p>
<p><code>~/airflow/dags</code> 폴더 안에 <code>naver_search_pipeline.py</code> 파일을 만든다. 이 파일에 하나의 대그를 코딩하는 것이다 (공정 파이프라인을 설계하는 것). </p>
<p>대그의 기본 설정(대그 아이디(유일하게), 대그를 돌릴 주기, 태그 등 설정)을 완성한다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/ecd90626-6cb2-4e53-b26e-520672692559/image.png" alt=""></p>
<p>웹서버에 들어가서 태그 중에 하나인 <code>naver</code>를 검색하면, 대그가 새로 추가된 것을 확인할 수 있다(웹서버에 보이기까지 시간이 좀 걸릴 수도 있으니 뜨지 않는다면 조금 기다려보자).
<img src="https://velog.velcdn.com/images/clueless_coder/post/b47e5c7c-0579-4834-9e59-edeb30e99424/image.png" alt=""></p>
<p>이어서 대그의 작업 순서대로 오퍼레이터들을 만들고, 맨마지막에 연결하는 코드를 작성하는 순으로 설명한다.</p>
<h4 id="1-sqliteoperator---데이터-저장할-테이블-생성하기">1. SqliteOperator - 데이터 저장할 테이블 생성하기</h4>
<p>가장 먼저 SqliteOperator 를 이용해서 데이터를 저장할 테이블을 생성해준다. SqliteOperator는 특정 Sqlite 데이터베이스에 대해서 sql 코드를 실행해주는 오퍼레이터다. 따라서 그 특정 Sqlite 데이터베이스가 무엇인지 연결해줄 필요가 있다. 다음과 같이 작성한다.</p>
<ul>
<li><code>task_id=&lt;작업을 구분할 아이디&gt;</code> </li>
<li><code>sqlite_conn_id=&lt;나의 Sqlite 인스턴스와 연결할 때 필요한 커넥션 아이디&gt;</code></li>
<li><code>sql=&lt;sql 쿼리문&gt;</code> </li>
</ul>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/7041f462-4b3d-4722-ada7-14434fd62ce6/image.png" alt="">
<code>creating_table</code> 이라는 이름은 태스크명으로 본인이 원하는 대로 지어주면 된다. 코드를 저장하고 웹서버에 들어가보자. <code>naver-trend-pipeline</code> 대그 페이지에서 <code>Graph</code> 를 들어가보면 우리가 만든 <code>creating_table</code> 태스크가 보인다. 
<img src="https://velog.velcdn.com/images/clueless_coder/post/cb956ff4-2824-4319-8d70-eb5e8433ab41/image.png" alt=""></p>
<p>내 Sqlite 인스턴스와 연결하려면 웹서버에 들어가서 등록해줘야 한다. 아래처럼 웹서버 화면 상단에 <code>Admin</code>의 <code>Connections</code>를 클릭.
<img src="https://velog.velcdn.com/images/clueless_coder/post/a11605d4-439a-428a-8139-809a7473e6a6/image.png" alt="">
새로운 커넥션을 추가해주기 위해 우측 상단의 <code>+</code> 버튼 클릭.
<img src="https://velog.velcdn.com/images/clueless_coder/post/cf2b0517-c4e6-4a37-94b6-d04c0feadd7a/image.png" alt="">
아래와 같이 정보를 기입하고 저장 (Host 에는 본인 <code>airflow.db</code>가 있는 경로).
<img src="https://velog.velcdn.com/images/clueless_coder/post/524134cd-b6a4-4ea4-a236-a9745b658371/image.png" alt="">
대그를 일단 한번 실행해보자. 터미널에서 실제로 생성되었는지 확인도 하자.
<img src="https://velog.velcdn.com/images/clueless_coder/post/35ad8d3c-1e54-4dcc-b7c5-afc50a2b8ea2/image.png" alt="">
<code>sqlite3 airflow.db</code> 라고 치고, <code>.table</code> 이라고 치면 현재 생성되어있는 테이블들을 모두 확인할 수 있다. <code>naver_search_result</code> 테이블이 만들어져 있는 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/0e7060c2-c6b0-42eb-8b06-cbbed1d73d86/image.png" alt=""></p>
<h4 id="2-httpsensor---데이터-가져오는-것이-가능한지-확인하기">2. HttpSensor - 데이터 가져오는 것이 가능한지 확인하기</h4>
<p>저장할 곳은 잘생성되었으니, 이제 데이터를 가져오는 것이 가능한지 센서로 확인한다. 먼저 아까처럼 <code>Admin</code> &gt; <code>Connections</code> &gt; <code>+</code> 로 네이버 API에 대한 커넥션을 생성해준다. 커넥션 아이디는 <code>naver_search_api</code> 라고 했다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/3896c872-de73-4eb3-93ea-53013b8040d8/image.png" alt=""></p>
<p>이제 센서에 대한 코드를 작성한다. <a href="https://developers.naver.com/docs/serviceapi/search/local/local.md#%EC%A7%80%EC%97%AD">네이버 검색(지역) API 가이드</a>를 확인해서 파라미터들을 넣어주도록 하자. 아래 예시를 참고해서 헤더를 체크한다. 아까 발급받은 클라 아이디와 클라 시크릿을 넣어준다. 요청 변수로는 5개까지 검색 결과를 보도록 <code>display</code>는 <code>5</code>를 주고, 필수 파라미터인 <code>query</code>로 <code>김치찌개</code>를 검색해보겠다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/f85f4073-fc98-49f4-840f-1fb25232c8f1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/0d73ce77-f811-432a-b694-b27e7a6a5fcf/image.png" alt=""></p>
<p>웹서버에 대그에 들어가보면 잘생성되었음을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/52b4e127-1900-4ba5-b59f-efb137e21153/image.png" alt="">
이 새로 만든 태스크가 잘돌아가는지 확인하고 싶기때문에(대그 전체를 돌리는 것이 아니라), CLI를 통해서 새로 만든 태스크 하나면 테스트를 해보겠다. 터미널에 다음과 같이 친다.</p>
<pre><code class="language-bash">cd ~/airflow
airflow tasks test &lt;대그 아이디&gt; &lt;태스크 아이디&gt; &lt;날짜&gt;</code></pre>
<p>여기서는 <code>airflow tasks test naver-search-pipeline is_api_available 2022-01-01</code> 로 한다. 아래처럼 Success 가 뜨면 태스크가 잘 작동한다는 소리다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/0bc7ed81-379e-4437-ae73-465c1f9604a3/image.png" alt="">
실제로 가져오는 내용을 좀 확인하고 싶다면 아래처럼 <code>response_check</code> 파라미터에서 아웃풋을 print문 처리해주고 다시 테스트를 해보자. 
<img src="https://velog.velcdn.com/images/clueless_coder/post/c8bfc36c-5948-4dfb-8da8-abc305734b23/image.png" alt="">
아래처럼 검색된 내용을 확인할 수 있었다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/3fcb89ce-82ca-4869-b0db-2a622eedccd2/image.png" alt=""></p>
<h4 id="3-simplehttpoperator---데이터-가져오기">3. SimpleHttpOperator - 데이터 가져오기</h4>
<p>이제 데이터를 가져올 수 있다는 것을 확인했으니, 데이터를 실제로 가져온다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/f3e45ac4-da93-4f3e-b6f2-aff43fc6f855/image.png" alt=""></p>
<h4 id="4-pythonoperator---데이터-전처리하기">4. PythonOperator - 데이터 전처리하기</h4>
<p>3번에서 가져온 데이터를 전처리한다. 같은 파일에 전처리 함수를 만들어줘도 괜찮지만, 더 조직적으로, 효율적으로 만들기 위해서 따로 전처리 폴더를 만들고 그 아래에 네이버 검색 결과 전처리 함수를 만들겠다.</p>
<p>검색 결과는 아래처럼 나온다. </p>
<pre><code class="language-json">{
      &quot;lastBuildDate&quot;:&quot;Tue, 05 Jul 2022 00:24:17 +0900&quot;,
      &quot;total&quot;:5,
      &quot;start&quot;:1,
      &quot;display&quot;:5,
      &quot;items&quot;:[     
                 {
                        &quot;title&quot;:&quot;한옥집 김치찜 본점&quot;
                           &quot;link&quot;:&quot;http:\/\/hanokjib.co.kr\/community\/media\/&quot;,
                        &quot;category&quot;:&quot;음식점&gt;한식&quot;,
                        &quot;description&quot;:&quot;&quot;,
                        &quot;telephone&quot;:&quot;&quot;,
                        &quot;address&quot;:&quot;서울특별시 서대문구 냉천동 20-1 1층 한옥집김치찜&quot;,
                        &quot;roadAddress&quot;:&quot;서울특별시 서대문구 통일로9길 12 1층 한옥집김치찜&quot;,
                        &quot;mapx&quot;:&quot;308714&quot;,
                        &quot;mapy&quot;:&quot;552177&quot;
                },
        ...

        ]
}</code></pre>
<p>따라서 결과의 <code>items</code>에서 <code>title</code>, <code>link</code>, <code>category</code>, <code>description</code>, <code>address</code> 를 가져오도록 하고, csv 파일로 저장하는 전처리 함수를 만든다. </p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/22b5b866-7218-46be-8ec8-7e603b2a1055/image.png" alt=""></p>
<p>함수를 다 만들었으니 불러와서 대그에서 사용하도록 한다. 
<img src="https://velog.velcdn.com/images/clueless_coder/post/6d2d0776-c9d9-4d81-879d-7c50fe1c01d6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/81b0ad8b-d681-42f7-804c-283639052a3d/image.png" alt=""></p>
<h4 id="5-bashoperator---데이터-저장하기">5. BashOperator - 데이터 저장하기</h4>
<p>다음과 같이 저장된 csv 파일을 테이블로 저장한다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/6850d1ad-72fb-490a-81c2-59b4e49aec9f/image.png" alt=""></p>
<h4 id="6-pythonoperator---대그-완료-알리기">6. PythonOperator - 대그 완료 알리기</h4>
<p>모든 작업이 완료되었음을 알리기 위해 간단한 함수를 만든다. 이 함수에 일부러 에러를 하나 만들어 두었다. 대그를 실행해보면서 어떻게 문제를 확인하고 해결하는지 알아보겠다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/e0ee453c-0216-4c36-9803-71d0b2e7edb7/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/4116d2bb-486a-4902-a732-79bf4b9eaf22/image.png" alt=""></p>
<h4 id="7-작업들-연결하기---파이프라인-구성">7. 작업들 연결하기 - 파이프라인 구성</h4>
<p>맨 마지막에 태스크들을 순서대로 연결해서 파이프라인을 구성해준다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/f80d0606-3296-4c3c-9e25-724957730ded/image.png" alt="">
그러면 웹서버에 다음과 같이 연결된 그래프의 모습으로 업데이트 될 것이다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/4fcddaf4-103e-4dca-98bc-f956bcfb9dc9/image.png" alt=""></p>
<h3 id="전체-dag-파일-코드">전체 DAG 파일 코드</h3>
<pre><code class="language-python"># 필요한 모듈 Import
from datetime import datetime
from airflow import DAG
import json
from preprocess.naver_preprocess import preprocessing

# 사용할 Operator Import
from airflow.providers.sqlite.operators.sqlite import SqliteOperator
from airflow.providers.http.sensors.http import HttpSensor
from airflow.providers.http.operators.http import SimpleHttpOperator
from airflow.operators.python import PythonOperator
from airflow.operators.bash import BashOperator
from airflow.operators.email import EmailOperator

# 디폴트 설정
default_args = {
    &quot;start_date&quot;: datetime(2022, 1, 1) # 2022년 1월 1일 부터 대그 시작 --&gt; 현재는 22년 7월이므로 대그를 실행하면 무조건 한 번은 돌아갈 것
}

# 본인이 발급받은 키를 넣으세요
NAVER_CLI_ID = &quot;your_cli_id&quot;
NAVER_CLI_SECRET = &quot;your_cli_secret&quot;

def _complete():
    print(&quot;네이버 검색 DAG 완료&quot;)

# DAG 틀 설정
with DAG(
    dag_id=&quot;naver-search-pipeline&quot;,
    # crontab 표현 사용 가능 https://crontab.guru/
    schedule_interval=&quot;@daily&quot;, 
    default_args=default_args,
    # 태그는 원하는대로
    tags=[&quot;naver&quot;, &quot;search&quot;, &quot;local&quot;, &quot;api&quot;, &quot;pipeline&quot;],
    # catchup을 True로 하면, start_date 부터 현재까지 못돌린 날들을 채운다
    catchup=False) as dag:

    # 네이버 API로 지역 식당을 검색할 것이다. 
    # 지역 식당명, 주소, 카테고리, 설명, 링크를 저장할 것이므로 다음과 같이 테이블을 구성한다.
    creating_table = SqliteOperator(
        task_id=&quot;creating_table&quot;,
        sqlite_conn_id=&quot;db_sqlite&quot;, # 웹UI에서 connection을 등록해줘야 함.
        # naver_search_result 라는 테이블이 없는 경우에만 만들도록 IF NOT EXISTS 조건을 넣어주자.
        sql=&#39;&#39;&#39;
            CREATE TABLE IF NOT EXISTS naver_search_result( 
                title TEXT,
                address TEXT,
                category TEXT,
                description TEXT,
                link TEXT
            )
        &#39;&#39;&#39;
    )

    # HTTP 센서를 이용해 응답 확인 (감지하는 오퍼레이터로 실제 데이터를 가져오는 것 X)
    is_api_available = HttpSensor(
        task_id=&quot;is_api_available&quot;,
        http_conn_id=&quot;naver_search_api&quot;,
        endpoint=&quot;v1/search/local.json&quot;, # url - uri에서 Host 부분을 제외한 파트(~.com 까지가 host)
        # 요청 헤더, -H 다음에 오는 내용들
        headers={
            &quot;X-Naver-Client-Id&quot; : f&quot;{NAVER_CLI_ID}&quot;,
            &quot;X-Naver-Client-Secret&quot; : f&quot;{NAVER_CLI_SECRET}&quot;,
        },
        request_params={
            &quot;query&quot;: &quot;김치찌개&quot;,
            &quot;display&quot;: 5
        }, # 요청 변수
        response_check=lambda response: response.json() # 응답 확인
    )

    # 네이버 검색 결과를 가져올 오퍼레이터를 만든다.
    crawl_naver = SimpleHttpOperator(
        task_id=&quot;crawl_naver&quot;,
        http_conn_id=&quot;naver_search_api&quot;,
        endpoint=&quot;v1/search/local.json&quot;, # url 설정
        headers={
            &quot;X-Naver-Client-Id&quot; : f&quot;{NAVER_CLI_ID}&quot;,
            &quot;X-Naver-Client-Secret&quot; : f&quot;{NAVER_CLI_SECRET}&quot;,
        }, # 요청 헤더
        data={
            &quot;query&quot;: &quot;김치찌개&quot;,
            &quot;display&quot;: 5
        }, # 요청 변수
        method=&quot;GET&quot;, # 통신 방식 GET, POST 등등 맞는 것으로
        response_filter=lambda res : json.loads(res.text),
        log_response=True
    )

    # 검색 결과 전처리하고 CSV 저장
    preprocess_result = PythonOperator(
            task_id=&quot;preprocess_result&quot;,
            python_callable=preprocessing # 실행할 파이썬 함수
    )

    # csv 파일로 저장된 것을 테이블에 저장
    store_result = BashOperator(
        task_id=&quot;store_naver&quot;,
        bash_command=&#39;echo -e &quot;.separator &quot;,&quot;\n.import /home/kurran/airflow/dags/data/naver_processed_result.csv naver_search_result&quot; | sqlite3 /home/kurran/airflow/airflow.db&#39;
    )

    # 대그 완료 출력
    print_complete = PythonOperator(
            task_id=&quot;print_complete&quot;,
            python_callable=_complete # 실행할 파이썬 함수
    )

    # 파이프라인 구성하기
    creating_table &gt;&gt; is_api_available &gt;&gt; crawl_naver &gt;&gt; preprocess_result &gt;&gt; store_result &gt;&gt; print_complete</code></pre>
<h2 id="🏃♀️-대그-실행하기-에러-해결하기">🏃‍♀️ 대그 실행하기, 에러 해결하기</h2>
<p>웹서버에 들어가서 만든 대그를 실행해보자.
<img src="https://velog.velcdn.com/images/clueless_coder/post/5dccb477-e966-4861-93fb-b63a8a911706/image.png" alt="">
<code>preprocess_result</code> 태스크에서 문제가 생겨 빨간 박스로 표시되었다. 문제를 확인하려면 로그를 확인해야 한다. 문제의 박스를 클릭하고, 우측에 <code>Log</code> 를 클릭한다.<img src="https://velog.velcdn.com/images/clueless_coder/post/5138e478-e411-431b-9b6c-73c4f0c06f62/image.png" alt="">
로그를 확인해보니, list indice로는 정수나 slice가 들어갈 수 있는데, string을 넣어버리는 실수를 했다. 코드를 수정해주자. </p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/8a815d2b-4c59-4cb0-ad74-6c0523997cdd/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/85c0a53e-220b-4246-8442-4c5bd57e52c2/image.png" alt=""></p>
<p>다시 돌려보자. 모든 작업들이 성공했다!
<img src="https://velog.velcdn.com/images/clueless_coder/post/852fedf6-f9e5-455e-8933-1e238eec52e8/image.png" alt=""></p>
<p>데이터들이 잘 저장되었는지 확인도 해보자. 먼저 전처리된 csv 파일을 보니 원하는대로 잘 저장되었다.
<img src="https://velog.velcdn.com/images/clueless_coder/post/ee88d4c5-7a11-4552-bc72-1f1054578cac/image.png" alt=""></p>
<p>마지막으로 sqlite 테이블로 잘저장되었는지도 보자. 
<img src="https://velog.velcdn.com/images/clueless_coder/post/6d643b48-ccb1-4801-b7fa-d644bda48402/image.png" alt=""></p>
<hr>
<p>여기까지 아주 기초적인 에어플로우 실습을 해봤다. 여기서 등장한 오퍼레이터들만 사용하더라도 충분히 복잡한 작업을 수행하는 코드를 만들 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[맥 VS Code 에서 아나콘다 환경으로 터미널에서 오류날때 해결방법, Django python manage.py SyntaxError 해결방법]]></title>
            <link>https://velog.io/@clueless_coder/%EB%A7%A5-VS-Code-%EC%97%90%EC%84%9C-%EC%95%84%EB%82%98%EC%BD%98%EB%8B%A4-%ED%99%98%EA%B2%BD%EC%9C%BC%EB%A1%9C-%ED%84%B0%EB%AF%B8%EB%84%90%EC%97%90%EC%84%9C-%EC%98%A4%EB%A5%98%EB%82%A0%EB%95%8C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-Django-python-manage.py-SyntaxError-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@clueless_coder/%EB%A7%A5-VS-Code-%EC%97%90%EC%84%9C-%EC%95%84%EB%82%98%EC%BD%98%EB%8B%A4-%ED%99%98%EA%B2%BD%EC%9C%BC%EB%A1%9C-%ED%84%B0%EB%AF%B8%EB%84%90%EC%97%90%EC%84%9C-%EC%98%A4%EB%A5%98%EB%82%A0%EB%95%8C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-Django-python-manage.py-SyntaxError-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Thu, 21 Apr 2022 06:34:51 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/clueless_coder/post/e8e5cfa5-ff91-4b74-aae8-ab2b0632a128/image.png" alt=""></p>
<p>맥에서 VS Code의 터미널에서 콘다 환경에서 사용하려면 문제가 생기는 경우가 있다. 예를 들어 Django 설치하고 다 설정하고 <code>python manage.py runserver</code> 하면 Syntax error 가 뜬다.</p>
<p>그냥 터미널에서는 콘다 환경에서 잘되는데, VS Code 내부 터미널에서 잘안된다면 터미널 환경설정을 좀 바꿔주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/f892f344-a158-474f-8849-fafb4c95202f/image.png" alt="">
터미널창 우측 상단에 있는 + 옆의 아래로 화살표를 누르면 터미널 설정 구성이 보일 거다.</p>
<p>그걸 누르고, 좀 쭉 내리다가 보면, 
<code>Terminal &gt; Integrated: Inherit Env</code> 가 보인다. 여기서 체크 박스를 해제하자. (스크롤하기 귀찮으면 <code>settings.json</code> 에 들어가서 <code>&quot;terminal.integrated.inheritEnv&quot;: false</code> 로 바꿔준다. 원래 <code>true</code>로 되어있다.)</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/8068c1c2-e7ee-460d-92aa-4eae4db4d175/image.png" alt=""></p>
<p>체크박스 해제 후 VS Code를 껐다 킨다.</p>
<p><img src="https://velog.velcdn.com/images/clueless_coder/post/9ae3b34c-c8d4-471f-92de-27d2428890f6/image.png" alt=""></p>
<p>잘된다. 해결!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[넘파이] 넘파이 자가진단 - 기초편]]></title>
            <link>https://velog.io/@clueless_coder/%EB%84%98%ED%8C%8C%EC%9D%B4-%EB%84%98%ED%8C%8C%EC%9D%B4-%ED%80%B4%EC%A6%88-%EA%B8%B0%EC%B4%88%ED%8E%B8</link>
            <guid>https://velog.io/@clueless_coder/%EB%84%98%ED%8C%8C%EC%9D%B4-%EB%84%98%ED%8C%8C%EC%9D%B4-%ED%80%B4%EC%A6%88-%EA%B8%B0%EC%B4%88%ED%8E%B8</guid>
            <pubDate>Fri, 25 Mar 2022 11:09:16 GMT</pubDate>
            <description><![CDATA[<p>파이썬으로 코드를 쓰다보면 넘파이를 많이 쓰게 되는데, 맨날 까먹어서 구글링하는 내가 한심하여 넘파이 기초 코드를 암기하기 위한 자가진단 겸 퀴즈를 만들어보았다. </p>
<p>이 포스트에 계속 기초적인 넘파이 퀴즈를 추가할 예정이다. 문제를 보고 옆에 코드를 작성할 창을 하나 켜놓고 하나씩 풀어보면 되겠다. 왠지 답을 보고 싶을 거 같아서 일부러 답은 적지 않았다. 문제를 다 풀어보고 답은 <a href="https://github.com/mitchell-pritchett/TIL/blob/main/numpy/numpy_quiz(basics).ipynb">여기</a>에서 확인하자. 문제 옆에 체크 박스를 넣었다. 채점 혹은 헷갈리는 문항 표시 용도로 사용하면 되겠다.</p>
<ol>
<li><p><input disabled="" type="checkbox">  0 부터 9까지 들어 있는 정수 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  0 부터 10까지 홀수만 들어 있는 정수 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  0 이 다섯 개 채워진 1차원 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  0 으로 채워진 2 x 3 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  0 으로 채워진 3 x 2 x 3 x 4 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  1 이 다섯 개 채워진 1차원 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  1 로 채워진 2 x 3 x 4 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  7 로 채워진 2 x 3 배열 만들기 (두 가지 방법이 있다)</p>
</li>
<li><p><input disabled="" type="checkbox">  3 x 3 단위행렬(identity) 만들기 (두 가지 메서드가 있다)</p>
</li>
<li><p><input disabled="" type="checkbox">  <strong>5 x 5 대각행렬 만들기 (1부터 10사이 홀수로 채우기)</strong></p>
</li>
<li><p><input disabled="" type="checkbox">  1 부터 10 까지 5개의 숫자를 이용해 균등한 점 구간 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  1부터 40까지 사이 정수로 랜덤하게 만들어진 3x3x2 배열 만들기</p>
</li>
<li><p><input disabled="" type="checkbox">  12.에서 만든 배열에서 <code>axis=2</code> 기준합</p>
</li>
<li><p><input disabled="" type="checkbox">  <code>arr = [[1,2,3],[4,5,6]]</code> 에서 <code>[1,2,3]</code></p>
</li>
<li><p><input disabled="" type="checkbox">  <code>arr</code> 에서 5 (두 가지 방법)</p>
</li>
<li><p><input disabled="" type="checkbox">  <code>arr</code> 에서 <code>[2,5]</code></p>
</li>
<li><p><input disabled="" type="checkbox">  <code>arr</code> 전체 </p>
</li>
<li><p><input disabled="" type="checkbox"> </p>
<pre><code class="language-python">arr = np.array(
  [[[[29, 15],
     [ 8, 21],
     [19, 23]],

    [[11, 11],
     [24, 36],
     [24,  3]]],

   [[[22,  2],
     [24, 30],
     [ 2, 21]],

    [[33, 12],
     [22, 25],
     [27, 28]]]])</code></pre>
<p>에서 </p>
<pre><code class="language-python">array([[[[29, 15],
          [19, 23]],

         [[11, 11],
          [24,  3]]],

        [[[22,  2],
          [ 2, 21]],

         [[33, 12],
          [27, 28]]]])</code></pre>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[판다스] 왕초보 판다스 - 개념과 시리즈, 데이터프레임 만들기]]></title>
            <link>https://velog.io/@clueless_coder/%ED%8C%90%EB%8B%A4%EC%8A%A4-%ED%8C%90%EB%8B%A4%EC%8A%A4-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%8B%9C%EB%A6%AC%EC%A6%88-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%94%84%EB%A0%88%EC%9E%84-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@clueless_coder/%ED%8C%90%EB%8B%A4%EC%8A%A4-%ED%8C%90%EB%8B%A4%EC%8A%A4-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%8B%9C%EB%A6%AC%EC%A6%88-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%94%84%EB%A0%88%EC%9E%84-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Fri, 25 Mar 2022 09:22:47 GMT</pubDate>
            <description><![CDATA[<h1 id="판다스">판다스?</h1>
<ul>
<li>판다스(Pandas)는 파이썬에서 2차원 배열 데이터를 간편하게 다룰 수 있도록 만들어진 라이브러리다.</li>
<li>정형 데이터를 다루는 라이브러리다.</li>
<li>엑셀과 비슷한 느낌이라고 생각하면 되겠다.</li>
<li>이름의 유래는 판다와 관계가 없다. Python Data Analysis Library 를 뜻하고, 다차원 정형 데이터를 나타내는 경제학 용어인 panel data에서 그 이름을 따왔다고 한다.</li>
</ul>
<blockquote>
<p>정형(structured) vs. 반정형(semi structured data) vs. 비정형(unstructured) 데이터
판다스는 정형 데이터를 다룬다고 했다. 그런데 정형데이터가 뭘까?</p>
</blockquote>
<ul>
<li>정형데이터는 정확한 규칙을 따르는 데이터를 의미한다. 표 같은 형식을 생각하면 제일 좋다. 나이 컬럼에는 나이를 나타내는 수가 들어가고, 연도를 나타내는 컬럼에는 연도를 나타내는 수가 들어가는 표를 생각하면 되겠다. </li>
<li>반정형 데이터는 약한 정형 데이터라고 생각해도 된다. 규칙은 있지만 반드시 지킬 필요는 없는 경우다. </li>
<li>비정형 데이터는 정형 데이터의 반대 개념으로 정해진 규칙이 없어서 값의 의미를 파악하기 힘든 데이터는 말한다. 영상, 자연어, 음성, 주파수 같은 데이터가 비정형이다. </li>
</ul>
<h1 id="판다스-불러오기">판다스 불러오기</h1>
<pre><code class="language-python">import pandas as pd</code></pre>
<p><code>pd</code> 라는 이름으로 판다스 라이브러리를 임포팅해오자. (다른 이름으로 해도 오류는 없으나 관습적으로 이렇게 쓴다)</p>
<h1 id="판다스의-데이터-타입">판다스의 데이터 타입</h1>
<p>판다스에는 두 가지 데이터 종류가 있다. 하나는 시리즈(Series)고, 다른 하나는 데이터프레임(DataFrame) 이다. </p>
<h2 id="series">Series</h2>
<p>시리즈는 한 종류의 데이터를 모아 놓은 것이다. 표에서 한 행 혹은 한 열이라고 생각하면 좋다.</p>
<h3 id="시리즈-만들기">시리즈 만들기</h3>
<pre><code class="language-python">pd.Series(data=None, index=None, dtype=None, name=None, copy=None)</code></pre>
<p><code>data</code> 에 들어갈 수 있는 것은 </p>
<ul>
<li>iterable</li>
<li>dict</li>
<li>array-like(ndarray)</li>
<li>또는 scalar 값이다.
<img src="https://images.velog.io/images/clueless_coder/post/b845caf7-d217-4c88-8f7f-fe65474d576d/image.png" alt=""><h2 id="dataframe">DataFrame</h2>
시리즈가 여러 개 모이면 데이터프레임이 된다. 행과 열이 시리즈고 이들이 모인 표가 데이터프레임이라고 생각하면 쉽다.<h3 id="데이터프레임-만들기">데이터프레임 만들기</h3>
<pre><code class="language-python">pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)</code></pre>
<code>data</code> 에 들어갈 수 있는 것은</li>
<li>iterable</li>
<li>dict</li>
<li>array-like(ndarray)</li>
<li>또는 DataFrame 이다.</li>
</ul>
<ol>
<li>2차원 배열(리스트)로 만들기
<img src="https://images.velog.io/images/clueless_coder/post/7e9f3c53-d224-462d-9886-ddeca2869860/image.png" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/06cf8fb1-5b8e-4218-895b-da9027351aa0/image.png" alt=""></li>
<li>딕셔너리로 만들기 - 컬럼별로 (딕셔너리 안에 <code>컬럼명 : 값</code>으로, 값에는 Series, arrays, constants, dataclass 또는 list-like object가 들어갈 수 있음) 
<img src="https://images.velog.io/images/clueless_coder/post/38eacfa7-ed85-4868-aeaf-c808d37053f9/image.png" alt=""></li>
<li>딕셔너리로 만들기 - 로우별로 (리스트 안에 한 로우당 한 딕셔너리로 나열)
<img src="https://images.velog.io/images/clueless_coder/post/5292c7da-bc54-4417-a06c-d4eaf6ea8757/image.png" alt=""></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이썬] *args 와 **kwargs 가 뭐예요?]]></title>
            <link>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-args-%EC%99%80-kwargs-%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</link>
            <guid>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-args-%EC%99%80-kwargs-%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</guid>
            <pubDate>Mon, 14 Mar 2022 08:08:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 포스트는 키워드 아규먼트와 포지셔널 아규먼트를 알고 있다고 전제하고 작성되었습니다.</p>
</blockquote>
<p>파이썬 함수 정의를 보다보면 아래처럼 되어있는 경우가 많다.</p>
<pre><code class="language-python">def foo(*args, **kwargs):
    ...</code></pre>
<p>그냥 파라미터랑 뭔가 다르다. 앞에 왜 <code>*</code>, <code>**</code>이 달려있고, 파라미터는 아무 이름이나 정해도 되는데 왜 다들 무슨 뜻이길래 저렇게 <code>args</code>랑 <code>kwargs</code> 라고 쓰는가? 그리고 왜 항상 순서는 <code>*args</code> 다음에 <code>**kwargs</code> 인가?</p>
<h2 id="args-는-positional-arguments-를-의미한다">args 는 (positional) arguments 를 의미한다</h2>
<p>내가 인풋 정수들을 모두 더해주는 함수를 만들고 싶다고 하자.</p>
<pre><code class="language-python">def sum_ints(a,b,c):
    return a + b + c</code></pre>
<p>위 함수는 세 개의 수를 받아서 그 합을 계산해줄 것이다. 근데 내가 만약에 n개의 인자를 받고 싶다면 어떻게 할 것인가? 1개든 3개든 10개든 정수를 받아서 그 합을 구하고 싶다면 저렇게 함수를 정의해서는 안될 것이다. 이렇게 몇 개의 positional argument(인자를 이름으로 받지 않고 &#39;,&#39; 로 구분하여 위치로 받는 인자) 를 받아야할지 정할 수 없을 때 그 여러 개를 받을 자리에 <code>*args</code> 를 파라미터로 써준다. (꼭 args 라고 쓸 필요는 없으나 관습적으로 그렇게 쓴다.)</p>
<pre><code class="language-python">def sum_n_ints(*args):
    return sum(args)</code></pre>
<p>args 앞에 붙는 <code>*</code> 가 여러 개의 인자를 묶어서 하나의 튜플로 묶어주고 이를 args 에 할당한다라고 생각하면 되겠다. 
<img src="https://images.velog.io/images/clueless_coder/post/8908e65c-06df-4f5e-8519-4b0355a37ec4/image.png" alt=""></p>
<h2 id="kwargs-는-keyword-arguments-를-의미한다">kwargs 는 keyword arguments 를 의미한다</h2>
<p>그렇다면 이번에는 알 수 없는 숫자만큼의 키워드 아규먼트들을 받고 싶다고 하자. 이때도 일반적인 키워드 파라미터를 정하는 방식으로는 함수를 정의할 수 없다. 그래서 여러 개의 키워드 아큐먼트들을 묶어서 딕셔너리로 만들어주는 <code>**</code> 이 필요하다.
<img src="https://images.velog.io/images/clueless_coder/post/aeed1719-c8d9-4589-a798-7275e217a313/image.png" alt=""></p>
<h2 id="args-와-kwargs-를-같이-써놓은-것은-어떻게-되는-거죠"><em>args 와 *</em>kwargs 를 같이 써놓은 것은 어떻게 되는 거죠?</h2>
<ul>
<li><code>*args</code> 는 연속되는 포지셔널 아규먼트를 다 먹는다.</li>
<li><code>**kwargs</code> 는 연속되는 키워드 아규먼트를 다 먹는다.</li>
<li><code>*args</code> 와 <code>**kwargs</code> 순서를 맞춰서(<code>**kwargs</code> 를 먼저 쓰면 안된다!) 쓰면 키워드 아규먼트가 나오기 전까지는 args 가 튜플로 먹고, 뒤 이어오는 키워드 아규먼트는 kwargs 가 딕셔너리로 먹는다.
<img src="https://images.velog.io/images/clueless_coder/post/6c0b4dae-6b21-4a6d-88d1-e3497d3579b6/image.png" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/de827e3d-1cb1-4d31-b7b0-fecb3130bbe2/image.png" alt="">
위처럼 <code>*args</code>, <code>**kwargs</code> 순서를 바꿔쓰면 syntax error 가 난다.
<img src="https://images.velog.io/images/clueless_coder/post/89cf233f-c930-4c1f-b743-c39955e65fc7/image.png" alt="">
<code>*args</code> 는 연속되는 포지셔널 아규먼트를 다 먹는다고 했다. 따라서 위처럼 <code>*args1</code> 가 다 먹을 것이므로 <code>*args2</code> 는 있을 수 없다.
<img src="https://images.velog.io/images/clueless_coder/post/afa25463-4eca-448f-a240-7db6cefbac29/image.png" alt="">
<code>**kwargs</code> 도 마찬가지다. </li>
</ul>
<h3 id="디폴트-값을-가지는-keyword-argument-를-넣어주고-싶다면요">디폴트 값을 가지는 keyword argument 를 넣어주고 싶다면요?</h3>
<p><img src="https://images.velog.io/images/clueless_coder/post/e65d9a58-4faf-4d29-addd-15de3be430b6/image.png" alt="">
이렇게 넣는 것은 <code>**kwargs</code> 가 뒤로 연속되는 키워드 아규먼트를 다 먹을 것이므로 안된다. 
<img src="https://images.velog.io/images/clueless_coder/post/7ad962d3-622a-43be-8185-c234fba78541/image.png" alt="">
이렇게 해주면 <code>*args</code>는 이어지는 포지셔널 아규먼트만 먹기에 <code>a=1</code> 전에서 끊길 것이고, <code>**kwargs</code> 는 <code>b=2</code> 뒤로 이어지는 키워드 아규먼트들을 먹을 것이니 문제 없다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이썬] Parameter 와 Argument 의 차이가 뭐예요?]]></title>
            <link>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Parameter-%EC%99%80-Argument-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</link>
            <guid>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Parameter-%EC%99%80-Argument-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</guid>
            <pubDate>Mon, 14 Mar 2022 07:15:43 GMT</pubDate>
            <description><![CDATA[<p>프로그래밍에서 함수를 다루다보면 파라미터(매개변수)와 아규먼트(전달인자)가 무엇인지 헷갈리는 포인트가 올 수 있다. 그 둘의 차이를 알아보자!</p>
<h1 id="parameter매개변수-vs-argument전달인자">Parameter(매개변수) vs. Argument(전달인자)</h1>
<ul>
<li>파라미터는 함수 정의에서 정의된 <strong>변수</strong>다; 파이썬 오피셜 문서에서는 &#39;함수 정의에서 함수가 받을 수 있는 인자를 지정하는 이름 붙은 엔티티&#39;라고 한다. </li>
<li>아규먼트는 함수를 호출할 때 실제로 함수에 전달되는 <strong>값</strong>이다.</li>
<li>그러니까 아규먼트를 넣어서 함수를 호출하면 아규먼트의 값을 파라미터(매개변수)에 할당한다라고 생각해도 좋겠다.</li>
</ul>
<p>예시로 확실하게 이해하자.</p>
<pre><code class="language-python">def sum_function(param1, param2):
    return param1 + param2</code></pre>
<pre><code class="language-python">&gt;&gt;&gt; sum_function(10, 20)
30</code></pre>
<p>위의 예시에서 <code>param1</code>과 <code>param2</code>는 파라미터고, <code>10</code>, <code>20</code>은 아규먼트다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이썬] Generator 가 뭐예요?]]></title>
            <link>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Generator-%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</link>
            <guid>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-Generator-%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</guid>
            <pubDate>Mon, 14 Mar 2022 05:44:48 GMT</pubDate>
            <description><![CDATA[<h1 id="generator">Generator</h1>
<h2 id="제너레이터가-뭐예요">제너레이터가 뭐예요?</h2>
<p><strong>제너레이터</strong>는 <strong>제너레이터 이터레이터</strong>를 리턴하는 <strong>함수</strong>다(그래서 제너레이터 함수라고도 한다). </p>
<p>일반적인 함수랑 똑같이 생겼는데, 어떤 값을 <code>return</code> 하는 대신 <code>yield</code> 표현을 써서 <code>for</code> 루프나 <code>next()</code> 함수로 한 번에 하나씩 원소를 가져올 수 있는 값의 스트림을 반환하는 제너레이터 이터레이터/객체를 만들어준다.</p>
<p>아주 간단히 말하자면 <code>yield</code> 키워드를 함수에 썼다면 제너레이터 함수고, 제너레이터 이터레이터 객체를 리턴한다. (<code>yield</code> 는 제너레이터 함수를 만들때만 사용된다)</p>
<blockquote>
<p>제너레이터라고 하면 일반적으로 제너레이터 함수를 의미하지만, 어떤 경우에는 제너레이터 이터레이터(제너레이터 함수에 의해 생성된 제너레이터 객체를 의미한다). 여기서는 명확히 하기 위해 <strong>제너레이터 함수</strong>와 <strong>제너레이터 이터레이터/객체</strong>라고 구분지어 말하겠다.</p>
</blockquote>
<h2 id="그래서-yield-가-들어간-함수를-돌리면-무슨-일이-일어나는데요">그래서 <code>yield</code> 가 들어간 함수를 돌리면 무슨 일이 일어나는데요?</h2>
<pre><code class="language-python">def generate_ints(N):
    for i in range(N):
        yield i</code></pre>
<p>위는 아주 간단한 제너레이터 함수의 예다. </p>
<p>이 함수는 어떤 하나의 값을 리턴하지 않는다. 대신 <code>yield</code> 라는 애로 인해 <strong>이터레이터 프로토콜을 지원하는 제너레이터 객체를 리턴</strong>한다. (이터레이터와 이터러블에 대해서는 앞선 포스트에서 구체적으로 설명했으니 여기서는 아는 것을 전제로 하겠다.) </p>
<p>자, 이 함수를 호출했다고 해보자. 
<img src="https://images.velog.io/images/clueless_coder/post/6024646b-f2e3-4f7f-a8b0-69ac3c898578/image.png" alt=""> 제너레이터 객체가 생성된 것을 볼 수 있다. 우리는 이 제너레이터 객체를 <code>for</code> 문에 쓸 수 있다. 우리가 이터러블이나 이터레이터를 <code>for</code> 문에 쓰듯!
<img src="https://images.velog.io/images/clueless_coder/post/169b7e7d-3194-4d1c-81dd-a037bc3c740f/image.png" alt=""></p>
<p><code>for</code> 루프 내부적으로는 무슨 일이 일어났을까? 이터레이터나 이터러블에 일어나는 과정과 같아 보인다!
<img src="https://images.velog.io/images/clueless_coder/post/9a363d5e-a9f7-43c2-898f-3e95d70d0c10/image.png" alt=""></p>
<p>구체적으로 어떤 일이 일어나는지 살펴보자. <code>__next__()</code> 메서드가 호출될 때마다, <code>for</code> 루프 내부적으로는 제너레이터 함수가 실행된다. 그리고 <code>yield</code> 오른쪽의 객체가 리턴되고, 제너레이터 함수의 실행 상태가 일시 중지되고, 지역 변수가 보존된다. 제너레이터의 <code>__next__()</code> 메서드가 실행되면 함수가 다시 <code>yield</code> 에 도달할 때까지 실행되고 또 다시 오른쪽 객체가 리턴되고 일시 중지된다. 루프는 제너레이터 함수가 더 이상 어떤 객체를 &#39;yielding&#39; 하지 않을 때까지 돌아가고 제너레이터 함수가 끝난다. </p>
<h2 id="제너레이터는-왜-쓰나요">제너레이터는 왜 쓰나요?</h2>
<p>그냥 편하게 리스트를 만들면 될 것을 왜 굳이 제너레이터를 사용할까? </p>
<p>리스트를 하나 만들면 그 리스트의 모든 원소들이 메모리에 저장될 것이다. 여기서 두 가지 의문을 제기할 수 있겠다.</p>
<ul>
<li>이 모든 원소들이 동시에 메모리에 존재할 수 있다면 괜찮지만, 그렇지 않다면? </li>
<li>또 만약 얼마나 많은 원소들이 리스트에 들어갈지 알 수 없고 런타임에서만 알 수 있다면 어떨까?</li>
</ul>
<p>이런 문제를 해소하기 위해 우리는 리스트 대신 제너레이터를 쓸 수 있다. 제너레이터는 메모리에 객체를 &#39;게으르게&#39; 생성하고 로딩할 수 있게 해준다; 한 번에 하나씩 그리고 그런 객체를 얼마만큼이고 &#39;제너레이트(생성)&#39;해준다.</p>
<h2 id="그래도-yield-를-써서-제너레이터-함수를-귀찮게-만들-바에는-그냥-리스트-쓰면-안되나요">그래도 <code>yield</code> 를 써서 제너레이터 함수를 귀찮게 만들 바에는 그냥 리스트 쓰면 안되나요?</h2>
<p><code>yield</code> 키워드를 써서 제너레이터 함수를 정의하는 대신 아주 간단하게 제너레이터를 만들 수 있다!</p>
<p>list comprehension 과 같은 방식으로 제너레이터 expression 을 만들 수 있다. 차이점은 대괄호를 소괄호로 만들어 줘야 한다는 것이다.</p>
<pre><code class="language-python">list_comprehension = [ i for i in range(5) ]
generator_expression = ( i for i in range(5) )</code></pre>
<p>만드는 방법은 유사하지만, 결과물은 다르다. list comprehension 문이 모든 객체를 다 가지는(fully populated) 리스트를 만들어줬다면, generator expression은 제너레이터 객체를 리턴할 뿐이다. 그리고 순회할 때만 &#39;게으르게&#39; 원소를 하나씩 리턴해준다. <img src="https://images.velog.io/images/clueless_coder/post/27051fb7-150b-4f77-8daf-2ce8db5b88b3/image.png" alt=""></p>
<h2 id="🤓-조금-더-들여다볼-사람">🤓 조금 더 들여다볼 사람!</h2>
<pre><code class="language-python">ge = (i for i in range(5))</code></pre>
<p>generator expression 에 대해서 모르고 이 표현을 봤다면, 아마 tuple comprehension 이 아닌가 했을 것이다. 하지만 tuple comprehension 은 없다! (이걸 만들어야 한다는 논의가 있다고는 한다.)</p>
<p>튜플로 만들어주고 싶다면 아래처럼 하면된다.</p>
<pre><code class="language-python">&gt;&gt;&gt; tuple((i for i in range(5))
(0, 1, 2, 3, 4)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이썬] iterable과 iterator 의 차이가 뭐예요?]]></title>
            <link>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-iterable%EA%B3%BC-iterator-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</link>
            <guid>https://velog.io/@clueless_coder/%ED%8C%8C%EC%9D%B4%EC%8D%AC-iterable%EA%B3%BC-iterator-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%90%EC%98%88%EC%9A%94</guid>
            <pubDate>Fri, 11 Mar 2022 08:59:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>&quot;뭐에요? 🤨&quot; 시리즈 1편
평소에 헷갈렸던 것들이나 암기해두면 좋을 것들, 대강 알고 정확한 정의를 몰랐던 것들을 좀 깊게 들어가보면서 질문별, 문제상황별로 포스트를 작성해보겠다. 파이썬에 대해서는 기초적인 문법을 알고 있다고 생각하고 작성한다.</p>
</blockquote>
<h2 id="iterable">iterable</h2>
<h3 id="이터러블이-뭐예요">이터러블이 뭐예요?</h3>
<ul>
<li>iterate over 가능한 오브젝트(객체)를 말한다. 여기서 iterate over 가능하다는 것은 <strong>멤버들을 한 번에 하나씩 돌려줄 수 있는 객체</strong>라는 소리다. (멤버를 순회 가능한 객체라고도 한다)</li>
<li>좀 더 정확히 말하자만 이터러블은 순회를 &quot;당한다&quot;라고 이해하는 것이 좋겠다. 뭔소리냐면 이터러블은 어떤 원소가 접근되고 있는지 모른다, 즉 이터러블이 현재 접근되어지는 원소의 인덱스가 무엇인지 추적하고 있지 않다는 것이다. </li>
<li>즉, 이터러블은 순회 과정을 주관하지 않는다. <strong>이터러블은 순회를 당하는 것이 가능한 컬렉션이다.</strong></li>
<li>그럼 누가 이 <strong>순회를 주관</strong>하는가? 바로 <strong>이터레이터다!</strong></li>
<li>이터레이터는 일단 &#39;순회를 주관해주는 애&#39;라고 생각하자. 구체적인 동작 방식에 대해서는 일단 미뤄두고 이터러블에는 뭐가 있는지, 이 순회 당할 수 있는 애들을 어디에 써먹을 수 있는지 보자.</li>
</ul>
<h3 id="어떤-애들이-이터러블인데요">어떤 애들이 이터러블인데요?</h3>
<p>기본적으로 <code>__iter__()</code> 혹은 <code>__getitem__()</code> 스페셜 메서드가 있는 클래스 객체들은 다 이터러블이다. (그 말인즉슨 우리가 만든 커스텀 클래스에 저 스페셜 메서드 하나 이상을 구현해주면 이터러블이 된다는 거다.)</p>
<p>다음과 같은 애들이 파이썬에서 기본적으로 사용할 수 있는 이터러블이다. (<code>for .. in [이_자리에_들어갈_수_있는_애들]</code> 로 생각하면 외우기 쉽다)</p>
<ul>
<li><code>list</code> (mutable sequence type)</li>
<li><code>tuple</code> (immutable sequence type)</li>
<li><code>str</code> (immutable, text sequence type)</li>
<li><code>dict</code> (mutable, non-sequence, mapping type)</li>
<li><code>set</code> (mutable, non-sequence type)</li>
<li><code>file</code> </li>
</ul>
<h3 id="이터러블-어디다가-쓰나요">이터러블 어디다가 쓰나요?</h3>
<p><code>iterable</code> 이라고 쓴 자리에 이터러블을 넣어서 사용한다.</p>
<ul>
<li><code>for &lt;variable&gt; in &lt;iterable&gt;</code></li>
<li>시퀀스를 필요로 하는 많은 함수들 (<code>zip(*iterables, strict=False)</code>, <code>map(function, iterable, ...)</code>, ... )</li>
<li><code>iter(iterable)</code> &rarr; 해당 객체의 이터레이터 리턴. 이 이터레이터는 값들을 쭉 한 번씩 거치는 동안 유효하다.</li>
<li>이터러블을 사용할 때, 보통은 이터레이터 객체를 직접 다룰 필요는 없다. <code>for</code> 문의 경우 루프를 도는 동안 이터레이터를 자동으로 생성해서(자동으로 <code>__iter__()</code>를 호출해준다는 뜻) 이름 없는 변수에 잡아둔다.</li>
</ul>
<h2 id="iterator">iterator</h2>
<h3 id="이터레이터는-뭐예요">이터레이터는 뭐예요?</h3>
<ul>
<li><strong>이터레이터는 이터러블의 순회를 주관하는 애!</strong>라고 했다.</li>
<li>파이썬 오피셜 문서에서는 이터레이터를 <strong>데이터의 스트림을 표현하는 객체</strong>라고 정의한다. (이 정의만 봐서는 사실 감이 잘 안잡힌다. 이터러블과의 차이도 모르겠다.) 그래서 우리 머릿속에는 <strong>이터레이터</strong>를 <strong>이터러블 순회 주관자라고 정의해보자.</strong></li>
</ul>
<h3 id="이터레이터가-순회를-어떻게-주관하는데요">이터레이터가 순회를 어떻게 주관하는데요?</h3>
<ul>
<li><p>이터러블 오브젝트의 스페셜 메서드(<code>__iter__()</code>)가 호출되면 해당 이터러블에 대한 이터레이터 객체가 생성되고 리턴된다.</p>
<ul>
<li>이터러블의 이 스페셜 메서드가 호출될 때마다 새로운 이터레이터가 리턴되고, 이렇게 이터러블로부터 새로 생성된 이터레이터는 해당 이터러블의 맨 첫 원소를 가르킨다.<img src="https://images.velog.io/images/clueless_coder/post/e73f2994-c72f-44d6-9fd2-d81d3749771e/iterable.png" alt=""></li>
</ul>
</li>
<li><p>이터레이터에는 또 <code>__next__()</code> 라는 스페셜 메서드가 있어서, 이 메서드를 호출하면</p>
<ul>
<li>현재 접근한 원소를 리턴하고, 현재 인덱스 포인터가 이터러블의 다음 원소를 가르키도록 옮긴다.</li>
<li>모든 원소를 순회하고 나면 다 끝났다고 알려준다.</li>
</ul>
</li>
<li><p>따라서 이터레이터 형은 두 개의 메서드를 사용해서 구현된다. (이터러블은 <code>__iter__()</code> 나 <code>__getitem__()</code>이 정의되어 있다면) 이터러블 형은</p>
<ul>
<li><code>__iter__()</code></li>
<li><code>__next__()</code></li>
</ul>
</li>
</ul>
<p>이 두 개의 메서드를 모두 지원해야 한다. (이터레이터 형에도 <code>__iter__()</code> 메서드가 있다는 것은 이터레이터에 대한 이터레이터도 만들 수 있다는 것이다. 또 이터러블의 조건을 만족하는 것이기도 하므로 이터레이터는 이터러블이다. 따라서 이터러블이 사용되는 곳에 당연히 이터레이터도 쓸 수 있다.)</p>
<h3 id="동작방식의-구체적인-예시는요">동작방식의 구체적인 예시는요?</h3>
<p>아래처럼 리스트를 만들고 for 문에 이 리스트(이터러블)을 사용해보자. 그럼 아래와 같은 결과가 나타나는데, 어떻게 돌아가는 걸까?<img src="https://images.velog.io/images/clueless_coder/post/afd3ab72-79a5-42df-8b19-9b5986b9773d/image.png" alt="">
for 가 하는 일을 풀어서 코드로 써보겠다. for 문이 이터러블을 받으면 이터러블의 <code>__iter__()</code> 를 호출한다. <code>__iter__()</code> 메서드는 이터레이터 객체를 리턴한다. <img src="https://images.velog.io/images/clueless_coder/post/fae8447d-d239-4526-b29d-125d0fe605b4/image.png" alt="">
for 문의 각 반복마다 내부적으로 <code>__next__()</code> 메서드를 호출하고 이 메서드는 현재 가르키고 있는 인덱스에 해당하는 원소를 반환하고 (이 반환된 값은 <code>i</code> 에 할당된다), 이터레이터 포인터를 다음 원소로 옮긴다. 모든 원소를 다 접근하고 나면 <code>StopIteration</code> exception이 나오고 for 문이 종료된다.<img src="https://images.velog.io/images/clueless_coder/post/082d6aa4-f152-4b0d-a026-f0bced9369b6/image.png" alt=""></p>
<h2 id="정리-좀-해주세요">정리 좀 해주세요!</h2>
<ul>
<li><strong>이터러블</strong>은 순회를 <strong>당할 수 있는</strong> 객체다.<ul>
<li><code>__iter__()</code> 또는 <code>__getitem__()</code> 필요</li>
</ul>
</li>
<li><strong>이터레이터</strong>는 이터러블의 <strong>순회를 주관</strong>한다.<ul>
<li><code>__iter__()</code> 와  <code>__next__()</code> 필요</li>
<li>이터러블이 될 조건을 만족하므로(<code>__iter__()</code>) 이터레이터는 이터러블이다.</li>
<li>이터러블은 이터레이터가 아니다.</li>
</ul>
</li>
<li>그렇다고 이터러블을 사용할 때, 이터레이터 객체를 직접 다룰 필요는 없다. 이터러블을 사용하는 많은 함수들이 자동으로 이터레이터 객체를 자동으로 생성해준다.<ul>
<li>for 문은 이터러블을 넣어주면 이터러블 객체의 <code>__iter__()</code> 메서드를 자동으로 호출해서 이터레이터를 생성, 리턴하고 루프를 도는 동안 이름 없는 변수에 잡아둔다.</li>
<li>이터레이션마다 생성한 이터러블 객체의 스페셜 메서드인 <code>__next__()</code>를 호출해서 현재 이터레이터 포인터가 가르키고 있는 곳의 값을 리턴하고, 포인터가 다음 원소를 가르키도록 한다.</li>
</ul>
</li>
</ul>
<h3 id="🤓-조금-더-들여다볼-사람">🤓 조금 더 들여다볼 사람!</h3>
<p>이터레이터는 이터러블이라고 했다. 이터레이터도 <code>__iter__()</code> 가 있기 때문에 이터러블이 된다. 
하지만 중요한 예외가 있는데, 리스트와 같은 컨테이너 객체를 iter() 함수에 전달하거나 for 루프에서 사용할 때마다 새 이터레이터를 만든다. 하지만 이터레이터는 이럴때마다 새 이터레이터를 만들지 않고, 지난 이터레이션에 사용된 이미 소진된 이터레이터를 돌려준다. 차이를 코드로 확인해보자.<img src="https://images.velog.io/images/clueless_coder/post/a1e9d571-dc21-4dc1-aea9-ab156780af3e/image.png" alt="">
리스트에 두 번 for 루프를 돌렸는데 똑같이 처음부터 원소가 잘 나온다. 새로운 이터레이터가 for 문마다 자동으로 생성됐기 때문이다.<img src="https://images.velog.io/images/clueless_coder/post/c87bcb89-298d-4984-90e2-47a66e1ba4d8/image.png" alt="">
id를 확인해봐도 계속 새로운 이터레이터가 생긴 것을 알 수 있다.<img src="https://images.velog.io/images/clueless_coder/post/d66e03c8-9183-4432-b1f0-7a63a01f2b07/image.png" alt="">
이터레이터에 for 문을 적용했더니 두번째 for 문에서는 아무것도 출력되지 않는다. 이미 앞서 만들어진 이터레이터에 대한 이터레이터를 리턴했기 때문이다.<img src="https://images.velog.io/images/clueless_coder/post/d2ca2aa0-4763-4333-a440-34697590dbe2/image.png" alt=""> 계속 같은 이터레이터이기에 id도 같다.</p>
<p>정리하자면 이터레이터에 대한 이터레이터는 한 번 생긴 것을 계속 쓴다. 하지만 이터레이터가 아닌 이터러블에 대한 이터레이터는 계속 새로 만든다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Learning Contextualized Knowledge Structures for Commonsense Reasoning: HGN]]></title>
            <link>https://velog.io/@clueless_coder/Learning-Contextualized-Knowledge-Structures-for-Commonsense-Reasoning-HGN</link>
            <guid>https://velog.io/@clueless_coder/Learning-Contextualized-Knowledge-Structures-for-Commonsense-Reasoning-HGN</guid>
            <pubDate>Tue, 08 Mar 2022 00:19:03 GMT</pubDate>
            <description><![CDATA[<h1 id="learning-contextualized-knowledge-structures-for-commonsense-reasoning-hgn">Learning Contextualized Knowledge Structures for Commonsense Reasoning: HGN</h1>
<hr>
<p><img src="https://images.velog.io/images/clueless_coder/post/59cc8bd4-8a8d-4494-a085-229a817c8f51/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_02.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/fd4e4704-5d4e-4c0d-b31b-335a9c947c3a/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_03.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/52926a46-c00c-40cc-971b-3aea31bb0c8f/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_04.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/fbf6ba07-09f4-432f-9212-0349a63ff7fd/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_05.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/46387bf8-53bf-43d0-babf-658ff848cabc/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_06.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/a99ca5fc-2f6e-4a2e-aaaf-eb13ca54e5c1/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_07.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/efbd6934-e050-4f22-931b-6d3c235beb2b/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_08.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/388df6bc-31f5-4dec-a678-3c9ee4825392/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_09.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/68e58f85-1831-4d45-94c9-1195d86bab94/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_10.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/0abe0f3c-215f-4ff8-9294-8d452a110476/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_11.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/2c4005b0-c867-4837-a2d6-08d452da11a5/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_12.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/53017acc-3b95-462e-b5e8-94d12bc49492/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_13.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/9dda5452-c690-4675-9b8e-f71cba3ff11c/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_14.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/c267b88b-c0bc-4654-9abf-7ada1a0a71ce/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_15.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/8a6f901f-10d2-45ac-8fd6-d0b1d2ce01eb/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_16.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/0c45a619-3766-4360-a47b-e70dc0777484/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_17.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/70fe39ec-17cb-49f1-a256-f19a258b259b/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_18.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/f44b263c-7d37-4ea8-91b1-e125ce9479d8/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_19.jpg" alt="">
<img src="https://images.velog.io/images/clueless_coder/post/e9e2bf1c-7f42-42dc-a98a-80b65af06ec5/1228_%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%82%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%85%E1%85%B5%E1%84%87%E1%85%B2_HGN_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_20.jpg" alt=""></p>
<p>HGN Paper Review END</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[GNN is a Counter?: Revisiting GNN for Questions Answering 논문리뷰 (paper review)]]></title>
            <link>https://velog.io/@clueless_coder/GNN-is-a-Counter-Revisiting-GNN-for-Questions-Answering-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-paper-review-zn8y4gyn</link>
            <guid>https://velog.io/@clueless_coder/GNN-is-a-Counter-Revisiting-GNN-for-Questions-Answering-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-paper-review-zn8y4gyn</guid>
            <pubDate>Sat, 05 Mar 2022 06:38:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/clueless_coder/post/c0f7462f-7fca-4a87-9ec6-0cfe41b166b9/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_01.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/2364260c-0b37-4bc9-baf0-97a07d3bdb77/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_02.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/bc5f5ab6-024f-40f6-84a5-6433c9b65830/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_03.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/79d7a94c-c184-4693-8a10-80ca44a8982e/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_04.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/eed3705e-78a7-4910-b523-f0f54f110f1c/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_05.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/efa0c7b2-ce3b-41f2-b115-3a9a0b4b6874/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_06.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/0cef685f-a456-4312-b682-ccbff352accb/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_07.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/2cf6d456-0885-427e-b0f1-9e2b2d9ca551/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_08.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/223a4f19-50f7-41f3-9025-804bb1df6bb8/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_09.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/085b30ad-dbe6-43c8-a934-ffeb660d5a15/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_10.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/6439dd88-02f3-44f6-b9f0-778715209143/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_11.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/49dd8881-3179-4ace-ae24-715158a9d178/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_12.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/b4a7dbef-4eed-4391-87fd-36de234d06d7/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_13.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/b966375c-cfaf-4706-9a03-dc71eada067d/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_14.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/31e9746b-f128-4d4e-9c57-92c365b1b6b8/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_15.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/24872460-02d1-4ad2-b0ba-5e62ecf3be45/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_16.jpg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/77cafca1-0f06-4bb3-8240-9ac3ec54e622/%5BLearnData%20Lab%5D%E1%84%80%E1%85%A1%E1%86%BC%E1%84%80%E1%85%B2%E1%84%85%E1%85%A1%E1%86%AB_%E1%84%89%E1%85%A6%E1%84%86%E1%85%B5%E1%84%82%E1%85%A1%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD-GSC(22.03.11)_%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5_17.jpg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Benchmarking Knowledge-Enhanced Commonsense Question Answering
via Knowledge-to-Text Transformation 논문리뷰 (paper review)]]></title>
            <link>https://velog.io/@clueless_coder/Benchmarking-Knowledge-Enhanced-Commonsense-Question-Answeringvia-Knowledge-to-Text-Transformation-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@clueless_coder/Benchmarking-Knowledge-Enhanced-Commonsense-Question-Answeringvia-Knowledge-to-Text-Transformation-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Thu, 03 Mar 2022 15:14:21 GMT</pubDate>
            <description><![CDATA[<h1 id="benchmarking-knowledge-enhanced-commonsense-question-answering-via-knowledge-to-text-transformation">Benchmarking Knowledge-Enhanced Commonsense Question Answering via Knowledge-to-Text Transformation</h1>
<h3 id="ning-bian-xianpei-han-bo-chen-le-sun">Ning Bian, Xianpei Han,* Bo Chen, Le Sun</h3>
<hr>
<p>작성중... </p>
<p>Abstract</p>
<ol>
<li>how far can we get by exploiting external knowledge for CQA?</li>
<li>how much potential knowledge has been exploited in current CQA model?</li>
<li>which are the most promising directions for future CQA?</li>
</ol>
<p>we use a simple(not specialized to specific models) and effective <strong>knowledge-to-text</strong> transformation framework!</p>
<p>Result: ktt SOP on CommonsenseQA</p>
<p>Direction:</p>
<ul>
<li>potential of knowledge is still far from being fully exploited with golden knowledge(?), </li>
<li>context-sensitive knowledge selection</li>
<li>heterogeneous knowledge exploitation, commonsense-rich language models are promising</li>
</ul>
<hr>
<h2 id="intro">Intro</h2>
<p>knowledged-enhanced cqa --&gt; external knowledge should be incorporated in a simple way that is not specialized to specific models/components</p>
<p>challenging bc:</p>
<ol>
<li>struct knowl and unstruct text knowl heterogeneity</li>
<li>context sensitivity: kb contain many facts but only several relevant</li>
</ol>
<p>ktt framework 3 stages:</p>
<ol>
<li>retrieve facts from KG</li>
<li>these facts to textual desc(tkd) via 3 transformation algo: template-based, paraphrasing-based, retrieval based -&gt; hetero solve</li>
<li>machine reading comprehension models to predict answers by using q and tkd</li>
</ol>
<p>tkd of ktt:</p>
<ol>
<li>template</li>
<li>paraphrasing: template -&gt; top-M paraphrases using beam-search decoding; encoder-decoder paraphrasing model trained on PPDB and WikiAnswers</li>
<li>retrieval: </li>
</ol>
<ul>
<li>above two only gen pseudo textual desc -&gt; retrieve from real world corpus (wikipedia), distant supervision assumption; &quot;if a sentence contains the entities on a knowledge path, it will express the meaning of the knowledge path&quot;</li>
<li>split all wiki docs into seperate sents and build wiki sent retrieval sys using ElasticSearch(?)</li>
<li>template as query to retrieve wiki sent containing concepts on knowledge paths via BM25(?) algo</li>
<li>rank 1 sent -&gt; description</li>
</ul>
<p>mrc answ pred:
mrc bc:</p>
<ol>
<li>automatically learn to identify relevant information in a document; here select q-rel knowl </li>
<li>mrc well studied tech
mrc == lm(?)</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[GreaseLM 논문 리뷰 (paper review)]]></title>
            <link>https://velog.io/@clueless_coder/GreaseLM-%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-paper-review</link>
            <guid>https://velog.io/@clueless_coder/GreaseLM-%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-paper-review</guid>
            <pubDate>Tue, 01 Mar 2022 12:41:58 GMT</pubDate>
            <description><![CDATA[<h1 id="greaselm-graph-reasoning-enhanced-language-models-for-question-answering-논문-리뷰">GreaseLM: Graph Reasoning Enhanced Language Models for Question Answering 논문 리뷰</h1>
<p>Xikun Zhang, Antoine Bosselut, Michihiro Yasunaga, Hongyu Ren, Percy Liang, Christopher D. Manning, Jure Leskovec (Stanford University)</p>
<hr>
<p><img src="https://images.velog.io/images/clueless_coder/post/10127eb0-b7ec-4dfc-93fc-3a0dd8337a12/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B32.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/addda209-e9fb-42e1-b958-feca3517f95f/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B33.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/1873aebf-be19-4476-8cea-f9a75ea10a21/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B34.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/e46f7dfe-8d8c-444a-8960-492d35f6539f/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B35.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/f36bef58-e46c-4fe6-99b9-ea18e40c5f5a/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B36.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/c9384e21-0cdd-45d4-bab3-deec7209154d/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B37.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/35928004-74a8-43f9-a0ff-dacc7eeccf54/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B38.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/c737065b-a3f7-4003-89b0-de18e2f43ad8/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B39.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/fa03cba4-f730-4bf4-8976-9f50992f5e49/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B310.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/ede39a19-7696-43b2-a94d-a844827b76f9/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B311.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/3071a6da-1b5a-4d6f-a6b1-fb2de824fa76/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B312.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/68d59d11-c777-4178-9d00-5a5bba576229/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B313.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/e4ca67d1-6c60-4ee7-9803-f38b1c6b9f67/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B314.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/706cb481-5b23-4c82-a0b6-c323143f2993/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B315.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/8676ccde-a205-4102-8864-e558b6d10239/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B316.jpeg" alt=""><img src="https://images.velog.io/images/clueless_coder/post/96b14c69-0b6b-4479-8bd6-3ffa8c93860c/%E1%84%89%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%83%E1%85%B317.jpeg" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>