<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>딥러닝 공부방</title>
    <link>https://deep-learning-study.tistory.com/</link>
    <description>까먹으면 다시 보려고 정리하는 블로그</description>
    <language>ko</language>
    <pubDate>Fri, 10 Jul 2026 14:01:09 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>AI 꿈나무</managingEditor>
    <item>
      <title>폴리곤을 segmentation mask로 변환하기(Polygon to mask)</title>
      <link>https://deep-learning-study.tistory.com/979</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;폴리곤 좌표로 표현되어 있는 mask를 binary mask로 변환하는 방법을 알아보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링 해보니 잘 안나와서 한번 작성해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 자료를 찾아봤는데 skimage.draw.polygon2mask 가 제일 편한것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blYLxq/btrUsP5Dgzi/aJH4l7f7zy7CFnoNcOlmmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blYLxq/btrUsP5Dgzi/aJH4l7f7zy7CFnoNcOlmmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blYLxq/btrUsP5Dgzi/aJH4l7f7zy7CFnoNcOlmmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblYLxq%2FbtrUsP5Dgzi%2FaJH4l7f7zy7CFnoNcOlmmK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;706&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;from skimage.draw import polygon2mask 로 함수를 불러와서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;image_shape와 np.array 타입의 polygon을 넣어주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://scikit-image.org/docs/stable/api/skimage.draw.html#skimage.draw.polygon2mask&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://scikit-image.org/docs/stable/api/skimage.draw.html#skimage.draw.polygon2mask&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671790723103&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Module: draw &amp;mdash; skimage v0.19.2 docs&quot; data-og-description=&quot;The range of values to sample pixel values from. For grayscale images the format is (min, max). For multichannel - ((min, max),) if the ranges are equal across the channels, and ((min_0, max_0), &amp;hellip; (min_N, max_N)) if they differ. As the function supports &quot; data-og-host=&quot;scikit-image.org&quot; data-og-source-url=&quot;https://scikit-image.org/docs/stable/api/skimage.draw.html#skimage.draw.polygon2mask&quot; data-og-url=&quot;https://scikit-image.org/docs/stable/api/skimage.draw.html#skimage.draw.polygon2mask&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://scikit-image.org/docs/stable/api/skimage.draw.html#skimage.draw.polygon2mask&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://scikit-image.org/docs/stable/api/skimage.draw.html#skimage.draw.polygon2mask&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Module: draw &amp;mdash; skimage v0.19.2 docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The range of values to sample pixel values from. For grayscale images the format is (min, max). For multichannel - ((min, max),) if the ranges are equal across the channels, and ((min_0, max_0), &amp;hellip; (min_N, max_N)) if they differ. As the function supports&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;scikit-image.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>mask</category>
      <category>Polygon</category>
      <category>polygon to mask</category>
      <category>polygon2mask</category>
      <category>segmentation mask</category>
      <category>마스크</category>
      <category>폴리곤</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/979</guid>
      <comments>https://deep-learning-study.tistory.com/979#entry979comment</comments>
      <pubDate>Fri, 23 Dec 2022 19:19:11 +0900</pubDate>
    </item>
    <item>
      <title>segmentation mask 덩어리 갯수 확인하기</title>
      <link>https://deep-learning-study.tistory.com/977</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9hAMU/btrJ8rTR5kY/qQgmMff8UksTrlo3ifZgh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9hAMU/btrJ8rTR5kY/qQgmMff8UksTrlo3ifZgh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9hAMU/btrJ8rTR5kY/qQgmMff8UksTrlo3ifZgh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9hAMU%2FbtrJ8rTR5kY%2FqQgmMff8UksTrlo3ifZgh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;321&quot; height=&quot;200&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림은 mask가 두 덩어리로 이루어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스를 파악하는 코드를 짜보았는뎅 공유합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1661081879784&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def count_contours(masks, threshold=1000):
    if type(masks[0]) == torch.Tensor:
        masks = [mask.cpu().numpy() for mask in masks]

    counts = []

    for mask in masks:
        count = 0
        contours, _ = cv2.findContours(mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
        for contour in contours:
            area = cv2.contourArea(contour)
            if area &amp;gt;= threshold:
                count += 1


        counts.append(count)

    return np.mean(counts)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cv2.findContours 함수를 사용하여 contour를 얻어옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;contourArea 함수를 이용하여 contour의 영역 크기를 계산한 후, threshold 이상인 경우만 카운트 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>contour</category>
      <category>contourArea</category>
      <category>findContours</category>
      <category>mask</category>
      <category>Open CV</category>
      <category>segmentation</category>
      <category>seperate</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/977</guid>
      <comments>https://deep-learning-study.tistory.com/977#entry977comment</comments>
      <pubDate>Sun, 21 Aug 2022 20:40:29 +0900</pubDate>
    </item>
    <item>
      <title>Segmentation mask의 center point 계산하기</title>
      <link>https://deep-learning-study.tistory.com/976</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Segmentation mask의 center point를 얻어오는게 필요해서 코드를 짜 보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mask는 0 또는 1의 값을 갖고 있으므로 numpy 혹은 pytorch의 nonzero 함수를 사용사용하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1661081628373&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;coordinates = np.nonzero(mask)

x_coordinates = coordinates[0]
y_coordinates = coordinates[1]

x_min, x_max, y_min, y_max = np.min(x_coordinates), np.max(x_coordinates), np.min(y_coordinates), np.max(y_coordinates)

x_center, y_center = (x_max + x_min) / 2, (y_max + y_min) / 2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 center point를 계산할지 고민하다가 위 처럼 짜보았는데, 혹시 도움이 필요하신 분이 계실까봐 공유합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>center point</category>
      <category>nonzero</category>
      <category>np.nonzero</category>
      <category>segmentation mask</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/976</guid>
      <comments>https://deep-learning-study.tistory.com/976#entry976comment</comments>
      <pubDate>Sun, 21 Aug 2022 20:36:00 +0900</pubDate>
    </item>
    <item>
      <title>Self-supervised Learning에 대하여</title>
      <link>https://deep-learning-study.tistory.com/975</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;심심해서 적어보는 글.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Self-supervised learning은 데이터가 부족한 환경에서 사용하는 것이 아니라, 데이터는 많은데 annotation이 없는 경우에 사용하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;unlabeled data 로부터 어떻게 pretask를 만들어서 효율적인 representation을 뽑아내느냐가 중요하며, 작년 까지 핫했던 SSL 모델들(DINO, MoCO, SimCL?)은 unlabeled data에 aumentation에 강하게 줘서 contrastive learning으로 augmentation에 불변한 representation을 뽑아내는 방향으로 발전해왔다. 22년 SSL 논문은 안읽어봐서 모르겠는데 현재도 비슷한 방향으로 연구가 진행되고 있지 않을까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 SSL방법론이 성능을 내기 위해서는 supervision보다 더 많은 데이터를 필요로 할 수 있다. 중요한 것은 데이터가 부족한 상황에서 SSL을 사용하는게 아니라, annotation이 없는 상황에서 사용하는 것. unlabeled data로부터 SSL로 학습한 모델을 약간의 annotation data로 fine-tuning해서 높은 성능을 달성하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 읽기/Self-Supervised</category>
      <category>Dino</category>
      <category>MOCO</category>
      <category>Self Supervised Learning</category>
      <category>SSL</category>
      <category>unlabled data</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/975</guid>
      <comments>https://deep-learning-study.tistory.com/975#entry975comment</comments>
      <pubDate>Wed, 17 Aug 2022 12:08:40 +0900</pubDate>
    </item>
    <item>
      <title>[PyTorch] CLIP의 text encoder에는 attention mask가 존재합니다.</title>
      <link>https://deep-learning-study.tistory.com/974</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CLIP의 text encoder 내부의 Multi_head_attention에서 attention mask가 None으로 입력되는 줄 알았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어를 구현하기 위해 attention mask 부분을 만들어서 넣어줬더니.. 성능이 엄청 떨어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번 확인해보니 CLIP의 text encoder에서 attention mask가 None으로 입력되는 것이 아니라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PYmhf/btrIxT54P1Z/Pafjax6CkMnN7Bqjsg7qvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PYmhf/btrIxT54P1Z/Pafjax6CkMnN7Bqjsg7qvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PYmhf/btrIxT54P1Z/Pafjax6CkMnN7Bqjsg7qvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPYmhf%2FbtrIxT54P1Z%2FPafjax6CkMnN7Bqjsg7qvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;472&quot; height=&quot;157&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;157&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다음과 같이 들어간다. 근데 어떤 layer에서는 None으로 들어가기 때문에 구체적으로 확인해볼 필요는 있다. 항상 저렇게 attention mask가 들어가는게 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;BERT 구조임에도 autoregressive하게 문장을 보게 하려는 의도 인듯?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>attention mask</category>
      <category>attn mask</category>
      <category>BERT</category>
      <category>CLIP</category>
      <category>multi head attention</category>
      <category>pytorch</category>
      <category>text encoder</category>
      <category>Transformer</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/974</guid>
      <comments>https://deep-learning-study.tistory.com/974#entry974comment</comments>
      <pubDate>Mon, 1 Aug 2022 15:30:57 +0900</pubDate>
    </item>
    <item>
      <title>[PyTorch] Multi_head_attention에서 target sequence length와 source sequence length 의미</title>
      <link>https://deep-learning-study.tistory.com/973</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Multi_head_attention에서&amp;nbsp;target&amp;nbsp;sequence&amp;nbsp;length와&amp;nbsp;source&amp;nbsp;sequence&amp;nbsp;length&amp;nbsp;의미&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연구를 위해 pytorch의 multi head attention에 attention mask를 씌워줘야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;705&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVoO14/btrImQ1XAag/AkjqEsPFhYo2mslTzxGfK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVoO14/btrImQ1XAag/AkjqEsPFhYo2mslTzxGfK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVoO14/btrImQ1XAag/AkjqEsPFhYo2mslTzxGfK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVoO14%2FbtrImQ1XAag%2FAkjqEsPFhYo2mslTzxGfK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;705&quot; height=&quot;231&quot; data-origin-width=&quot;705&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도큐먼트를 보면 L은 target sequence length를 의미하고 S는 source sequence length를 말하는데, 이 둘은 무엇일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buY11E/btrIjLf42Tu/O7YZ7er005AOIUX2UgYn10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buY11E/btrIjLf42Tu/O7YZ7er005AOIUX2UgYn10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buY11E/btrIjLf42Tu/O7YZ7er005AOIUX2UgYn10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuY11E%2FbtrIjLf42Tu%2FO7YZ7er005AOIUX2UgYn10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;551&quot; height=&quot;134&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;pytorch 내부 코드를 뜯어보니 target sequence length는 query의 길이를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;soure sequence length는 key의 길이를 의미함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;구글링해도 관련 내용을 찾기 어려워서 작성해본당. 나만 모르고 다 아는 내용이라서 구글링해도 못찾았던 거일수도?&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>attention</category>
      <category>MHA</category>
      <category>multi head attention</category>
      <category>pytorch</category>
      <category>query</category>
      <category>Source</category>
      <category>source sequence length</category>
      <category>target sequence length</category>
      <category>targget</category>
      <category>어텐션</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/973</guid>
      <comments>https://deep-learning-study.tistory.com/973#entry973comment</comments>
      <pubDate>Wed, 27 Jul 2022 20:23:31 +0900</pubDate>
    </item>
    <item>
      <title>[PyTorch] Tensor.retain_grad()</title>
      <link>https://deep-learning-study.tistory.com/972</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a.reatain_grad()를 통해 gradient가 사라지는 것을 예방할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산그래프에서 leaf node가 아닌 tensor의 gradient는 계산 후 날라가는데, retain_grad를 통해 날라가지 않고 붙잡을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.paperspace.com/pytorch-hooks-gradient-clipping-debugging/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.paperspace.com/pytorch-hooks-gradient-clipping-debugging/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658231201214&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Debugging and Visualisation in PyTorch using Hooks&quot; data-og-description=&quot;In this post, we cover debugging and Visualisation in PyTorch. We go over PyTorch hooks and how to use them to debug our backpass, visualise activations and modify gradients.&quot; data-og-host=&quot;blog.paperspace.com&quot; data-og-source-url=&quot;https://blog.paperspace.com/pytorch-hooks-gradient-clipping-debugging/&quot; data-og-url=&quot;https://blog.paperspace.com/pytorch-hooks-gradient-clipping-debugging/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cCwf31/hyO8SYSNrE/jQKfsdVhIpxicQuSbnLVKk/img.jpg?width=1000&amp;amp;height=793&amp;amp;face=0_0_1000_793,https://scrap.kakaocdn.net/dn/Qm0zi/hyO8ZX2mmp/W0QTPrKbfUmtVGPsoskdck/img.jpg?width=1000&amp;amp;height=793&amp;amp;face=0_0_1000_793&quot;&gt;&lt;a href=&quot;https://blog.paperspace.com/pytorch-hooks-gradient-clipping-debugging/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.paperspace.com/pytorch-hooks-gradient-clipping-debugging/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cCwf31/hyO8SYSNrE/jQKfsdVhIpxicQuSbnLVKk/img.jpg?width=1000&amp;amp;height=793&amp;amp;face=0_0_1000_793,https://scrap.kakaocdn.net/dn/Qm0zi/hyO8ZX2mmp/W0QTPrKbfUmtVGPsoskdck/img.jpg?width=1000&amp;amp;height=793&amp;amp;face=0_0_1000_793');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Debugging and Visualisation in PyTorch using Hooks&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;In this post, we cover debugging and Visualisation in PyTorch. We go over PyTorch hooks and how to use them to debug our backpass, visualise activations and modify gradients.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.paperspace.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>Grad</category>
      <category>gradients</category>
      <category>pytorch</category>
      <category>retain_grad</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/972</guid>
      <comments>https://deep-learning-study.tistory.com/972#entry972comment</comments>
      <pubDate>Tue, 19 Jul 2022 19:39:00 +0900</pubDate>
    </item>
    <item>
      <title>[PyTorch] register_hook을 사용하여 Transformer 내부의 Attention matrix(Torch.Tensor)의 gradient 받아오기</title>
      <link>https://deep-learning-study.tistory.com/971</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;register_hook을&amp;nbsp;사용하여&amp;nbsp;Transformer&amp;nbsp;내부의&amp;nbsp;Attention&amp;nbsp;matrix(Torch.Tensor)의&amp;nbsp;gradient&amp;nbsp;받아오기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델의 파라미터에 대한 grad가 아닌, Tensor object에 대한 grad는 계산만하고 날라가버린다. 즉, loss.backward()를 통해 backpropagation을 진행하면 중간 연산에 필요한 Tensor 변수의 gradient는 .grad로 저장이 안되고 계산이 끝나면 날라간다는 말이다. 따라서 Tensor object에 register_hook 함수로 gradient를 한번 붙잡아야 한다. 붙잡는다는 말은 gradient가 계산되었을 때, 날라가도록 두는게 아니라 다른 변수에 저장해야 한다는 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 중간 연산의 Tensor object에 가해지는 gradient값이 필요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transformer의 Query와 Key의 행렬곱을 통해 attention matrix를 얻는데, backpropagation과정에서 attention matrix에 대한 gradient를 얻는 방법을 공유하려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transformer는 Torch 내부 class인 MultiheadAttention을 사용하여 구현되는데, 이 내부 코드를 수정해줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Torch 내부 코드를 수정하기가 껄끄러우면, MultiheadAttention class와 이 class가 실행되기 위해 필요한 함수들을 따로 utils.py로 옮겨서 utils.MultiheadAttention class로 Transformer 구조를 변경해주면 된다. 즉, Torch의 class를 사용하는게 아니라 Torch의 class와 동일하지만, util에서 class를 꺼내서 사용하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Torch의 MultiheadAttention class를 살펴보면 F.multi_head_attention_forward 함수가 실행되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F.multi_head_attention_forward 내부에는 _scaled_dot_product_attention 함수를 통해 attention matrix가 계산된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;attention matrix가 계산되는 함수 내부까지 내려가서 attention matrix에 register_hook을 걸어줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657785786934&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# _scaled_dot_product_attention 함수 내부
B, Nt, E = q.shape
q = q / math.sqrt(E)
# (B, Nt, E) x (B, E, Ns) -&amp;gt; (B, Nt, Ns)
attn = torch.bmm(q, k.transpose(-2, -1))
self.save_attn_map(attn) # modified
if attn_mask is not None:
    attn += attn_mask
attn = softmax(attn, dim=-1)
if dropout_p &amp;gt; 0.0:
    attn = dropout(attn, p=dropout_p)
# (B, Nt, Ns) x (B, Ns, E) -&amp;gt; (B, Nt, E)
output = torch.bmm(attn, v)

gradient_hook = attn.register_hook(self.save_attn_gradient) 

def save_attn_gradient(self, gradient): # modified
    gradient = gradient.view(self.bsz, self.num_heads, self.tgt_len, self.src_len)
    gradient = gradient.sum(dim=1) / self.num_heads
    self.attention_map_gradients = gradient&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Torch.Tensor 변수에 register_hook을 걸어두면 gradient 값만을 받아올 수 있다. gradient값을 받아와서 self.attention_map_gradients에 gradient 값을 저장하는 함수를 register_hook에 넣어줬당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;self 인자를 사용하려면 class 내부에 _scaled_dot_product_attention 함수가 존재해야 하는데, Torch 내부 함수는 class 내부에 함수가 구현되지 않아서 나는 util.py 폴더에 Multi_head_attention class 내부에 _scaled_dot_product_attention 함수를 넣어줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 attention map도 받아오는게 필요해서 다음의 함수도 class 내부에 넣어줬고, attention map과 attention map의 gradient를 받아오는 함수도 class 내부에 넣어줬당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657786395289&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    def save_attn_map(self, attn):
        attn = attn.view(self.bsz, self.num_heads, self.tgt_len, self.src_len)
        attn = attn.sum(dim=1) / self.num_heads
        self.attention_map = attn

    def get_attn_map(self):
        return self.attention_map

    def get_attn_gradients(self):
        return self.attention_map_gradients&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 어떻게 attention map와 attention map의 gradient를 받아오냐면, Transformer 모델의 Multi_head_attention class에 접근해서 get_attn_map과 get_attn_gradients 함수를 실행해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;attention_map 정보는 forward를 통해 저장되고, attention_map의 gradient는 loss.backward를 실행하면 Multi_head_attention class 내부의 self.attention_map_gradient 변수에 gradient가 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657786786805&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for blk in clip_model.model.transformer.resblocks:
    cam = blk.attn.get_attn_map()
    gradients = blk.attn.get_attn_gradients()
    # gradients = blk.get_attn_gradients()
    print(cam.shape)
    print(gradients.shape)
    break&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드&lt;/p&gt;
&lt;pre id=&quot;code_1657786483289&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MHA(Module):
    r&quot;&quot;&quot;Allows the model to jointly attend to information
    from different representation subspaces.
    See `Attention Is All You Need &amp;lt;https://arxiv.org/abs/1706.03762&amp;gt;`_.

    .. math::
        \text{MultiHead}(Q, K, V) = \text{Concat}(head_1,\dots,head_h)W^O

    where :math:`head_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)`.

    Args:
        embed_dim: Total dimension of the model.
        num_heads: Number of parallel attention heads. Note that ``embed_dim`` will be split
            across ``num_heads`` (i.e. each head will have dimension ``embed_dim // num_heads``).
        dropout: Dropout probability on ``attn_output_weights``. Default: ``0.0`` (no dropout).
        bias: If specified, adds bias to input / output projection layers. Default: ``True``.
        add_bias_kv: If specified, adds bias to the key and value sequences at dim=0. Default: ``False``.
        add_zero_attn: If specified, adds a new batch of zeros to the key and value sequences at dim=1.
            Default: ``False``.
        kdim: Total number of features for keys. Default: ``None`` (uses ``kdim=embed_dim``).
        vdim: Total number of features for values. Default: ``None`` (uses ``vdim=embed_dim``).
        batch_first: If ``True``, then the input and output tensors are provided
            as (batch, seq, feature). Default: ``False`` (seq, batch, feature).

    Examples::

        &amp;gt;&amp;gt;&amp;gt; multihead_attn = nn.MultiheadAttention(embed_dim, num_heads)
        &amp;gt;&amp;gt;&amp;gt; attn_output, attn_output_weights = multihead_attn(query, key, value)
    &quot;&quot;&quot;
    __constants__ = ['batch_first']
    bias_k: Optional[torch.Tensor]
    bias_v: Optional[torch.Tensor]

    def __init__(self, embed_dim, num_heads, dropout=0., bias=True, add_bias_kv=False, add_zero_attn=False,
                 kdim=None, vdim=None, batch_first=False, device=None, dtype=None) -&amp;gt; None:
        factory_kwargs = {'device': device, 'dtype': dtype}
        super(MHA, self).__init__()
        self.embed_dim = embed_dim
        self.kdim = kdim if kdim is not None else embed_dim
        self.vdim = vdim if vdim is not None else embed_dim
        self._qkv_same_embed_dim = self.kdim == embed_dim and self.vdim == embed_dim

        self.num_heads = num_heads
        self.dropout = dropout
        self.batch_first = batch_first
        self.head_dim = embed_dim // num_heads
        assert self.head_dim * num_heads == self.embed_dim, &quot;embed_dim must be divisible by num_heads&quot;

        if self._qkv_same_embed_dim is False:
            self.q_proj_weight = Parameter(torch.empty((embed_dim, embed_dim), **factory_kwargs))
            self.k_proj_weight = Parameter(torch.empty((embed_dim, self.kdim), **factory_kwargs))
            self.v_proj_weight = Parameter(torch.empty((embed_dim, self.vdim), **factory_kwargs))
            self.register_parameter('in_proj_weight', None)
        else:
            self.in_proj_weight = Parameter(torch.empty((3 * embed_dim, embed_dim), **factory_kwargs))
            self.register_parameter('q_proj_weight', None)
            self.register_parameter('k_proj_weight', None)
            self.register_parameter('v_proj_weight', None)

        if bias:
            self.in_proj_bias = Parameter(torch.empty(3 * embed_dim, **factory_kwargs))
        else:
            self.register_parameter('in_proj_bias', None)
        self.out_proj = NonDynamicallyQuantizableLinear(embed_dim, embed_dim, bias=bias, **factory_kwargs)

        if add_bias_kv:
            self.bias_k = Parameter(torch.empty((1, 1, embed_dim), **factory_kwargs))
            self.bias_v = Parameter(torch.empty((1, 1, embed_dim), **factory_kwargs))
        else:
            self.bias_k = self.bias_v = None

        self.add_zero_attn = add_zero_attn

        self._reset_parameters()

        self.attention_map = None
        self.attention_map_gradients = None

    def _reset_parameters(self):
        if self._qkv_same_embed_dim:
            xavier_uniform_(self.in_proj_weight)
        else:
            xavier_uniform_(self.q_proj_weight)
            xavier_uniform_(self.k_proj_weight)
            xavier_uniform_(self.v_proj_weight)

        if self.in_proj_bias is not None:
            constant_(self.in_proj_bias, 0.)
            constant_(self.out_proj.bias, 0.)
        if self.bias_k is not None:
            xavier_normal_(self.bias_k)
        if self.bias_v is not None:
            xavier_normal_(self.bias_v)

    def __setstate__(self, state):
        # Support loading old MultiheadAttention checkpoints generated by v1.1.0
        if '_qkv_same_embed_dim' not in state:
            state['_qkv_same_embed_dim'] = True

        super(MHA, self).__setstate__(state)

    def forward(self, query: Tensor, key: Tensor, value: Tensor, key_padding_mask: Optional[Tensor] = None,
                need_weights: bool = True, attn_mask: Optional[Tensor] = None) -&amp;gt; Tuple[Tensor, Optional[Tensor]]:
        r&quot;&quot;&quot;
    Args:
        query: Query embeddings of shape :math:`(L, N, E_q)` when ``batch_first=False`` or :math:`(N, L, E_q)`
            when ``batch_first=True``, where :math:`L` is the target sequence length, :math:`N` is the batch size,
            and :math:`E_q` is the query embedding dimension ``embed_dim``. Queries are compared against
            key-value pairs to produce the output. See &quot;Attention Is All You Need&quot; for more details.
        key: Key embeddings of shape :math:`(S, N, E_k)` when ``batch_first=False`` or :math:`(N, S, E_k)` when
            ``batch_first=True``, where :math:`S` is the source sequence length, :math:`N` is the batch size, and
            :math:`E_k` is the key embedding dimension ``kdim``. See &quot;Attention Is All You Need&quot; for more details.
        value: Value embeddings of shape :math:`(S, N, E_v)` when ``batch_first=False`` or :math:`(N, S, E_v)` when
            ``batch_first=True``, where :math:`S` is the source sequence length, :math:`N` is the batch size, and
            :math:`E_v` is the value embedding dimension ``vdim``. See &quot;Attention Is All You Need&quot; for more details.
        key_padding_mask: If specified, a mask of shape :math:`(N, S)` indicating which elements within ``key``
            to ignore for the purpose of attention (i.e. treat as &quot;padding&quot;). Binary and byte masks are supported.
            For a binary mask, a ``True`` value indicates that the corresponding ``key`` value will be ignored for
            the purpose of attention. For a byte mask, a non-zero value indicates that the corresponding ``key``
            value will be ignored.
        need_weights: If specified, returns ``attn_output_weights`` in addition to ``attn_outputs``.
            Default: ``True``.
        attn_mask: If specified, a 2D or 3D mask preventing attention to certain positions. Must be of shape
            :math:`(L, S)` or :math:`(N\cdot\text{num\_heads}, L, S)`, where :math:`N` is the batch size,
            :math:`L` is the target sequence length, and :math:`S` is the source sequence length. A 2D mask will be
            broadcasted across the batch while a 3D mask allows for a different mask for each entry in the batch.
            Binary, byte, and float masks are supported. For a binary mask, a ``True`` value indicates that the
            corresponding position is not allowed to attend. For a byte mask, a non-zero value indicates that the
            corresponding position is not allowed to attend. For a float mask, the mask values will be added to
            the attention weight.

    Outputs:
        - **attn_output** - Attention outputs of shape :math:`(L, N, E)` when ``batch_first=False`` or
          :math:`(N, L, E)` when ``batch_first=True``, where :math:`L` is the target sequence length, :math:`N` is
          the batch size, and :math:`E` is the embedding dimension ``embed_dim``.
        - **attn_output_weights** - Attention output weights of shape :math:`(N, L, S)`, where :math:`N` is the batch
          size, :math:`L` is the target sequence length, and :math:`S` is the source sequence length. Only returned
          when ``need_weights=True``.
        &quot;&quot;&quot;
        if self.batch_first:
            query, key, value = [x.transpose(1, 0) for x in (query, key, value)]

        if not self._qkv_same_embed_dim:
            attn_output, attn_output_weights = self.multi_head_attention_forward(
                query, key, value, self.embed_dim, self.num_heads,
                self.in_proj_weight, self.in_proj_bias,
                self.bias_k, self.bias_v, self.add_zero_attn,
                self.dropout, self.out_proj.weight, self.out_proj.bias,
                training=self.training,
                key_padding_mask=key_padding_mask, need_weights=need_weights,
                attn_mask=attn_mask, use_separate_proj_weight=True,
                q_proj_weight=self.q_proj_weight, k_proj_weight=self.k_proj_weight,
                v_proj_weight=self.v_proj_weight)
        else:
            attn_output, attn_output_weights = self.multi_head_attention_forward(
                query, key, value, self.embed_dim, self.num_heads,
                self.in_proj_weight, self.in_proj_bias,
                self.bias_k, self.bias_v, self.add_zero_attn,
                self.dropout, self.out_proj.weight, self.out_proj.bias,
                training=self.training,
                key_padding_mask=key_padding_mask, need_weights=need_weights,
                attn_mask=attn_mask)
        if self.batch_first:
            return attn_output.transpose(1, 0), attn_output_weights
        else:
            return attn_output, attn_output_weights


    def multi_head_attention_forward(self,
        query: Tensor,
        key: Tensor,
        value: Tensor,
        embed_dim_to_check: int,
        num_heads: int,
        in_proj_weight: Tensor,
        in_proj_bias: Optional[Tensor],
        bias_k: Optional[Tensor],
        bias_v: Optional[Tensor],
        add_zero_attn: bool,
        dropout_p: float,
        out_proj_weight: Tensor,
        out_proj_bias: Optional[Tensor],
        training: bool = True,
        key_padding_mask: Optional[Tensor] = None,
        need_weights: bool = True,
        attn_mask: Optional[Tensor] = None,
        use_separate_proj_weight: bool = False,
        q_proj_weight: Optional[Tensor] = None,
        k_proj_weight: Optional[Tensor] = None,
        v_proj_weight: Optional[Tensor] = None,
        static_k: Optional[Tensor] = None,
        static_v: Optional[Tensor] = None,
    ) -&amp;gt; Tuple[Tensor, Optional[Tensor]]:

        r&quot;&quot;&quot;
        Args:
            query, key, value: map a query and a set of key-value pairs to an output.
                See &quot;Attention Is All You Need&quot; for more details.
            embed_dim_to_check: total dimension of the model.
            num_heads: parallel attention heads.
            in_proj_weight, in_proj_bias: input projection weight and bias.
            bias_k, bias_v: bias of the key and value sequences to be added at dim=0.
            add_zero_attn: add a new batch of zeros to the key and
                           value sequences at dim=1.
            dropout_p: probability of an element to be zeroed.
            out_proj_weight, out_proj_bias: the output projection weight and bias.
            training: apply dropout if is ``True``.
            key_padding_mask: if provided, specified padding elements in the key will
                be ignored by the attention. This is an binary mask. When the value is True,
                the corresponding value on the attention layer will be filled with -inf.
            need_weights: output attn_output_weights.
            attn_mask: 2D or 3D mask that prevents attention to certain positions. A 2D mask will be broadcasted for all
                the batches while a 3D mask allows to specify a different mask for the entries of each batch.
            use_separate_proj_weight: the function accept the proj. weights for query, key,
                and value in different forms. If false, in_proj_weight will be used, which is
                a combination of q_proj_weight, k_proj_weight, v_proj_weight.
            q_proj_weight, k_proj_weight, v_proj_weight, in_proj_bias: input projection weight and bias.
            static_k, static_v: static key and value used for attention operators.


        Shape:
            Inputs:
            - query: :math:`(L, N, E)` where L is the target sequence length, N is the batch size, E is
              the embedding dimension.
            - key: :math:`(S, N, E)`, where S is the source sequence length, N is the batch size, E is
              the embedding dimension.
            - value: :math:`(S, N, E)` where S is the source sequence length, N is the batch size, E is
              the embedding dimension.
            - key_padding_mask: :math:`(N, S)` where N is the batch size, S is the source sequence length.
              If a ByteTensor is provided, the non-zero positions will be ignored while the zero positions
              will be unchanged. If a BoolTensor is provided, the positions with the
              value of ``True`` will be ignored while the position with the value of ``False`` will be unchanged.
            - attn_mask: 2D mask :math:`(L, S)` where L is the target sequence length, S is the source sequence length.
              3D mask :math:`(N*num_heads, L, S)` where N is the batch size, L is the target sequence length,
              S is the source sequence length. attn_mask ensures that position i is allowed to attend the unmasked
              positions. If a ByteTensor is provided, the non-zero positions are not allowed to attend
              while the zero positions will be unchanged. If a BoolTensor is provided, positions with ``True``
              are not allowed to attend while ``False`` values will be unchanged. If a FloatTensor
              is provided, it will be added to the attention weight.
            - static_k: :math:`(N*num_heads, S, E/num_heads)`, where S is the source sequence length,
              N is the batch size, E is the embedding dimension. E/num_heads is the head dimension.
            - static_v: :math:`(N*num_heads, S, E/num_heads)`, where S is the source sequence length,
              N is the batch size, E is the embedding dimension. E/num_heads is the head dimension.

            Outputs:
            - attn_output: :math:`(L, N, E)` where L is the target sequence length, N is the batch size,
              E is the embedding dimension.
            - attn_output_weights: :math:`(N, L, S)` where N is the batch size,
              L is the target sequence length, S is the source sequence length.
        &quot;&quot;&quot;
        # set up shape vars
        tgt_len, bsz, embed_dim = query.shape
        self.tgt_len, self.bsz, self.embed_dim = tgt_len, bsz, embed_dim

        src_len, _, _ = key.shape
        self.src_len = src_len

        assert embed_dim == embed_dim_to_check, \
            f&quot;was expecting embedding dimension of {embed_dim_to_check}, but got {embed_dim}&quot;
        if isinstance(embed_dim, torch.Tensor):
            # embed_dim can be a tensor when JIT tracing
            head_dim = embed_dim.div(num_heads, rounding_mode='trunc')
        else:
            head_dim = embed_dim // num_heads
        assert head_dim * num_heads == embed_dim, f&quot;embed_dim {embed_dim} not divisible by num_heads {num_heads}&quot;
        if use_separate_proj_weight:
            # allow MHA to have different embedding dimensions when separate projection weights are used
            assert key.shape[:2] == value.shape[:2], \
                f&quot;key's sequence and batch dims {key.shape[:2]} do not match value's {value.shape[:2]}&quot;
        else:
            assert key.shape == value.shape, f&quot;key shape {key.shape} does not match value shape {value.shape}&quot;

        #
        # compute in-projection
        #
        if not use_separate_proj_weight:
            q, k, v = _in_projection_packed(query, key, value, in_proj_weight, in_proj_bias)
        else:
            assert q_proj_weight is not None, &quot;use_separate_proj_weight is True but q_proj_weight is None&quot;
            assert k_proj_weight is not None, &quot;use_separate_proj_weight is True but k_proj_weight is None&quot;
            assert v_proj_weight is not None, &quot;use_separate_proj_weight is True but v_proj_weight is None&quot;
            if in_proj_bias is None:
                b_q = b_k = b_v = None
            else:
                b_q, b_k, b_v = in_proj_bias.chunk(3)
            q, k, v = _in_projection(query, key, value, q_proj_weight, k_proj_weight, v_proj_weight, b_q, b_k, b_v)

        # prep attention mask
        if attn_mask is not None:
            if attn_mask.dtype == torch.uint8:
                warnings.warn(&quot;Byte tensor for attn_mask in nn.MultiheadAttention is deprecated. Use bool tensor instead.&quot;)
                attn_mask = attn_mask.to(torch.bool)
            else:
                assert attn_mask.is_floating_point() or attn_mask.dtype == torch.bool, \
                    f&quot;Only float, byte, and bool types are supported for attn_mask, not {attn_mask.dtype}&quot;
            # ensure attn_mask's dim is 3
            if attn_mask.dim() == 2:
                correct_2d_size = (tgt_len, src_len)
                if attn_mask.shape != correct_2d_size:
                    raise RuntimeError(f&quot;The shape of the 2D attn_mask is {attn_mask.shape}, but should be {correct_2d_size}.&quot;)
                attn_mask = attn_mask.unsqueeze(0)
            elif attn_mask.dim() == 3:
                correct_3d_size = (bsz * num_heads, tgt_len, src_len)
                if attn_mask.shape != correct_3d_size:
                    raise RuntimeError(f&quot;The shape of the 3D attn_mask is {attn_mask.shape}, but should be {correct_3d_size}.&quot;)
            else:
                raise RuntimeError(f&quot;attn_mask's dimension {attn_mask.dim()} is not supported&quot;)

        # prep key padding mask
        if key_padding_mask is not None and key_padding_mask.dtype == torch.uint8:
            warnings.warn(&quot;Byte tensor for key_padding_mask in nn.MultiheadAttention is deprecated. Use bool tensor instead.&quot;)
            key_padding_mask = key_padding_mask.to(torch.bool)

        # add bias along batch dimension (currently second)
        if bias_k is not None and bias_v is not None:
            assert static_k is None, &quot;bias cannot be added to static key.&quot;
            assert static_v is None, &quot;bias cannot be added to static value.&quot;
            k = torch.cat([k, bias_k.repeat(1, bsz, 1)])
            v = torch.cat([v, bias_v.repeat(1, bsz, 1)])
            if attn_mask is not None:
                attn_mask = pad(attn_mask, (0, 1))
            if key_padding_mask is not None:
                key_padding_mask = pad(key_padding_mask, (0, 1))
        else:
            assert bias_k is None
            assert bias_v is None

        #
        # reshape q, k, v for multihead attention and make em batch first
        #
        q = q.contiguous().view(tgt_len, bsz * num_heads, head_dim).transpose(0, 1)
        if static_k is None:
            k = k.contiguous().view(k.shape[0], bsz * num_heads, head_dim).transpose(0, 1)
        else:
            # TODO finish disentangling control flow so we don't do in-projections when statics are passed
            assert static_k.size(0) == bsz * num_heads, \
                f&quot;expecting static_k.size(0) of {bsz * num_heads}, but got {static_k.size(0)}&quot;
            assert static_k.size(2) == head_dim, \
                f&quot;expecting static_k.size(2) of {head_dim}, but got {static_k.size(2)}&quot;
            k = static_k
        if static_v is None:
            v = v.contiguous().view(v.shape[0], bsz * num_heads, head_dim).transpose(0, 1)
        else:
            # TODO finish disentangling control flow so we don't do in-projections when statics are passed
            assert static_v.size(0) == bsz * num_heads, \
                f&quot;expecting static_v.size(0) of {bsz * num_heads}, but got {static_v.size(0)}&quot;
            assert static_v.size(2) == head_dim, \
                f&quot;expecting static_v.size(2) of {head_dim}, but got {static_v.size(2)}&quot;
            v = static_v

        # add zero attention along batch dimension (now first)
        if add_zero_attn:
            zero_attn_shape = (bsz * num_heads, 1, head_dim)
            k = torch.cat([k, torch.zeros(zero_attn_shape, dtype=k.dtype, device=k.device)], dim=1)
            v = torch.cat([v, torch.zeros(zero_attn_shape, dtype=v.dtype, device=v.device)], dim=1)
            if attn_mask is not None:
                attn_mask = pad(attn_mask, (0, 1))
            if key_padding_mask is not None:
                key_padding_mask = pad(key_padding_mask, (0, 1))

        # update source sequence length after adjustments
        src_len = k.size(1)

        # merge key padding and attention masks
        if key_padding_mask is not None:
            assert key_padding_mask.shape == (bsz, src_len), \
                f&quot;expecting key_padding_mask shape of {(bsz, src_len)}, but got {key_padding_mask.shape}&quot;
            key_padding_mask = key_padding_mask.view(bsz, 1, 1, src_len).   \
                expand(-1, num_heads, -1, -1).reshape(bsz * num_heads, 1, src_len)
            if attn_mask is None:
                attn_mask = key_padding_mask
            elif attn_mask.dtype == torch.bool:
                attn_mask = attn_mask.logical_or(key_padding_mask)
            else:
                attn_mask = attn_mask.masked_fill(key_padding_mask, float(&quot;-inf&quot;))

        # convert mask to float
        if attn_mask is not None and attn_mask.dtype == torch.bool:
            new_attn_mask = torch.zeros_like(attn_mask, dtype=torch.float)
            new_attn_mask.masked_fill_(attn_mask, float(&quot;-inf&quot;))
            attn_mask = new_attn_mask

        # adjust dropout probability
        if not training:
            dropout_p = 0.0

        #
        # (deep breath) calculate attention and out projection
        #
        attn_output, attn_output_weights = self._scaled_dot_product_attention(q, k, v, attn_mask, dropout_p)
        attn_output = attn_output.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim)
        attn_output = linear(attn_output, out_proj_weight, out_proj_bias)

        if need_weights:
            # average attention weights over heads
            attn_output_weights = attn_output_weights.view(bsz, num_heads, tgt_len, src_len)

            return attn_output, attn_output_weights.sum(dim=1) / num_heads
        else:
            return attn_output, None

    def _scaled_dot_product_attention(self,
            q: Tensor,
            k: Tensor,
            v: Tensor,
            attn_mask: Optional[Tensor] = None,
            dropout_p: float = 0.0,
    ) -&amp;gt; Tuple[Tensor, Tensor]:
        r&quot;&quot;&quot;
        Computes scaled dot product attention on query, key and value tensors, using
        an optional attention mask if passed, and applying dropout if a probability
        greater than 0.0 is specified.
        Returns a tensor pair containing attended values and attention weights.

        Args:
            q, k, v: query, key and value tensors. See Shape section for shape details.
            attn_mask: optional tensor containing mask values to be added to calculated
                attention. May be 2D or 3D; see Shape section for details.
            dropout_p: dropout probability. If greater than 0.0, dropout is applied.

        Shape:
            - q: :math:`(B, Nt, E)` where B is batch size, Nt is the target sequence length,
                and E is embedding dimension.
            - key: :math:`(B, Ns, E)` where B is batch size, Ns is the source sequence length,
                and E is embedding dimension.
            - value: :math:`(B, Ns, E)` where B is batch size, Ns is the source sequence length,
                and E is embedding dimension.
            - attn_mask: either a 3D tensor of shape :math:`(B, Nt, Ns)` or a 2D tensor of
                shape :math:`(Nt, Ns)`.

            - Output: attention values have shape :math:`(B, Nt, E)`; attention weights
                have shape :math:`(B, Nt, Ns)`
        &quot;&quot;&quot;


        B, Nt, E = q.shape
        q = q / math.sqrt(E)
        # (B, Nt, E) x (B, E, Ns) -&amp;gt; (B, Nt, Ns)
        attn = torch.bmm(q, k.transpose(-2, -1))
        self.save_attn_map(attn) # modified
        if attn_mask is not None:
            attn += attn_mask
        attn = softmax(attn, dim=-1)
        if dropout_p &amp;gt; 0.0:
            attn = dropout(attn, p=dropout_p)
        # (B, Nt, Ns) x (B, Ns, E) -&amp;gt; (B, Nt, E)
        output = torch.bmm(attn, v)

        gradient_hook = attn.register_hook(self.save_attn_gradient) # modified
        # print(attn_gradients)

        # print(attn_gradients, 'attn_gradients')
        # print(attn.grad, ' attn.grad')
        # print(attn_gradients, 'attn_gradients')

        return output, attn

    def save_attn_gradient(self, gradient): # modified
        gradient = gradient.view(self.bsz, self.num_heads, self.tgt_len, self.src_len)
        gradient = gradient.sum(dim=1) / self.num_heads
        self.attention_map_gradients = gradient

    def save_attn_map(self, attn):
        attn = attn.view(self.bsz, self.num_heads, self.tgt_len, self.src_len)
        attn = attn.sum(dim=1) / self.num_heads
        self.attention_map = attn

    def get_attn_map(self):
        return self.attention_map

    def get_attn_gradients(self):
        return self.attention_map_gradients


def _in_projection_packed(
    q: Tensor,
    k: Tensor,
    v: Tensor,
    w: Tensor,
    b: Optional[Tensor] = None,
) -&amp;gt; List[Tensor]:
    r&quot;&quot;&quot;
    Performs the in-projection step of the attention operation, using packed weights.
    Output is a triple containing projection tensors for query, key and value.

    Args:
        q, k, v: query, key and value tensors to be projected. For self-attention,
            these are typically the same tensor; for encoder-decoder attention,
            k and v are typically the same tensor. (We take advantage of these
            identities for performance if they are present.) Regardless, q, k and v
            must share a common embedding dimension; otherwise their shapes may vary.
        w: projection weights for q, k and v, packed into a single tensor. Weights
            are packed along dimension 0, in q, k, v order.
        b: optional projection biases for q, k and v, packed into a single tensor
            in q, k, v order.

    Shape:
        Inputs:
        - q: :math:`(..., E)` where E is the embedding dimension
        - k: :math:`(..., E)` where E is the embedding dimension
        - v: :math:`(..., E)` where E is the embedding dimension
        - w: :math:`(E * 3, E)` where E is the embedding dimension
        - b: :math:`E * 3` where E is the embedding dimension

        Output:
        - in output list :math:`[q', k', v']`, each output tensor will have the
            same shape as the corresponding input tensor.
    &quot;&quot;&quot;
    E = q.size(-1)
    if k is v:
        if q is k:
            # self-attention
            return linear(q, w, b).chunk(3, dim=-1)
        else:
            # encoder-decoder attention
            w_q, w_kv = w.split([E, E * 2])
            if b is None:
                b_q = b_kv = None
            else:
                b_q, b_kv = b.split([E, E * 2])
            return (linear(q, w_q, b_q),) + linear(k, w_kv, b_kv).chunk(2, dim=-1)
    else:
        w_q, w_k, w_v = w.chunk(3)
        if b is None:
            b_q = b_k = b_v = None
        else:
            b_q, b_k, b_v = b.chunk(3)
        return linear(q, w_q, b_q), linear(k, w_k, b_k), linear(v, w_v, b_v)


def _in_projection(
    q: Tensor,
    k: Tensor,
    v: Tensor,
    w_q: Tensor,
    w_k: Tensor,
    w_v: Tensor,
    b_q: Optional[Tensor] = None,
    b_k: Optional[Tensor] = None,
    b_v: Optional[Tensor] = None,
) -&amp;gt; Tuple[Tensor, Tensor, Tensor]:
    r&quot;&quot;&quot;
    Performs the in-projection step of the attention operation. This is simply
    a triple of linear projections, with shape constraints on the weights which
    ensure embedding dimension uniformity in the projected outputs.
    Output is a triple containing projection tensors for query, key and value.

    Args:
        q, k, v: query, key and value tensors to be projected.
        w_q, w_k, w_v: weights for q, k and v, respectively.
        b_q, b_k, b_v: optional biases for q, k and v, respectively.

    Shape:
        Inputs:
        - q: :math:`(Qdims..., Eq)` where Eq is the query embedding dimension and Qdims are any
            number of leading dimensions.
        - k: :math:`(Kdims..., Ek)` where Ek is the key embedding dimension and Kdims are any
            number of leading dimensions.
        - v: :math:`(Vdims..., Ev)` where Ev is the value embedding dimension and Vdims are any
            number of leading dimensions.
        - w_q: :math:`(Eq, Eq)`
        - w_k: :math:`(Eq, Ek)`
        - w_v: :math:`(Eq, Ev)`
        - b_q: :math:`(Eq)`
        - b_k: :math:`(Eq)`
        - b_v: :math:`(Eq)`

        Output: in output triple :math:`(q', k', v')`,
         - q': :math:`[Qdims..., Eq]`
         - k': :math:`[Kdims..., Eq]`
         - v': :math:`[Vdims..., Eq]`

    &quot;&quot;&quot;
    Eq, Ek, Ev = q.size(-1), k.size(-1), v.size(-1)
    assert w_q.shape == (Eq, Eq), f&quot;expecting query weights shape of {(Eq, Eq)}, but got {w_q.shape}&quot;
    assert w_k.shape == (Eq, Ek), f&quot;expecting key weights shape of {(Eq, Ek)}, but got {w_k.shape}&quot;
    assert w_v.shape == (Eq, Ev), f&quot;expecting value weights shape of {(Eq, Ev)}, but got {w_v.shape}&quot;
    assert b_q is None or b_q.shape == (Eq,), f&quot;expecting query bias shape of {(Eq,)}, but got {b_q.shape}&quot;
    assert b_k is None or b_k.shape == (Eq,), f&quot;expecting key bias shape of {(Eq,)}, but got {b_k.shape}&quot;
    assert b_v is None or b_v.shape == (Eq,), f&quot;expecting value bias shape of {(Eq,)}, but got {b_v.shape}&quot;
    return linear(q, w_q, b_q), linear(k, w_k, b_k), linear(v, w_v, b_v)

def linear(input: Tensor, weight: Tensor, bias: Optional[Tensor] = None) -&amp;gt; Tensor:
    r&quot;&quot;&quot;
    Applies a linear transformation to the incoming data: :math:`y = xA^T + b`.

    This operator supports :ref:`TensorFloat32&amp;lt;tf32_on_ampere&amp;gt;`.

    Shape:

        - Input: :math:`(N, *, in\_features)` N is the batch size, `*` means any number of
          additional dimensions
        - Weight: :math:`(out\_features, in\_features)`
        - Bias: :math:`(out\_features)`
        - Output: :math:`(N, *, out\_features)`
    &quot;&quot;&quot;
    if has_torch_function_variadic(input, weight, bias):
        return handle_torch_function(linear, (input, weight, bias), input, weight, bias=bias)
    return torch._C._nn.linear(input, weight, bias)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>attention</category>
      <category>gradient</category>
      <category>gradients</category>
      <category>multi_head_attention</category>
      <category>object</category>
      <category>pytorch</category>
      <category>register_hook</category>
      <category>TENSOR</category>
      <category>Transformer</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/971</guid>
      <comments>https://deep-learning-study.tistory.com/971#entry971comment</comments>
      <pubDate>Thu, 14 Jul 2022 17:27:27 +0900</pubDate>
    </item>
    <item>
      <title>[Pytorch] Sementation mask 시각화 하기</title>
      <link>https://deep-learning-study.tistory.com/970</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이미지를 segmentation 모델로 전달하여 pred를 얻었다고 가정하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1656243096370&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for image, target in data_loader:
    pred_masks = model(image) # [N, H, W], dtype= Tensor.bool&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 pred_masks를 matplotlib를 사용하여 시각화 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, pred_masks, target, image를 동일한 사이즈로 resize 해줘야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안되어있는 경우 resize 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1656243279962&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import torchvision.transforms.functional as TF

h, w = image.shape[2], image.shape[3]
pred_masks = TF.resize(pred_masks, (h, w)).type(torch.bool) # [N, H, W]
target = TF.resize(target, {h, w)).type(torch.bool) # [N, H, W]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시각화 함수를 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 경우에는 sentence와 iou도 함께 존재하는데요. 이 값까지 함께 시각화 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연구에 필요한 코드를 짜고나서 블로그에 업로드하기 때문에, 보시는 분들은 불필요한 코드가 많다고 느끼실 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1656243366775&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def show_result(image, target, preds, sentences, ious, args, height, width, opacity=0.5):
    img = image.squeeze().cpu().numpy().transpose(1,2,0) # [3, 480, 480] -&amp;gt; [480, 480, 3]
    target = target.squeeze().cpu().numpy().astype(bool) # [1, H, W] -&amp;gt; [H, W]
    ious = [iou.cpu().numpy() for iou in ious]
    preds = [pred.squeeze(0).cpu().numpy().astype(bool) for pred in preds]
    

    mean = ([0.485, 0.456, 0.406])
    std = ([0.229, 0.224, 0.225])

    # re-nomalize
    for c, (mean_c, std_c) in enumerate(zip(mean, std)):
        img[:,:,c] *= std_c
        img[:,:,c] += mean_c

    color = np.array(ImageColor.getrgb('red'), dtype=np.uint8) / 255# tuple

    gt = copy.copy(img)
    # apply mask
    for c in range(3):
        gt[:,:,c] = np.where(target == 1,
                             gt[:,:,c] * opacity + (1 - opacity) * color[c],
                             gt[:,:,c])


    fig = plt.figure(figsize=(30,10),constrained_layout=True)
    specs = gridspec.GridSpec(nrows=2, ncols= len(sentences) + 1)
    ax1 = fig.add_subplot(specs[0,0])
    ax1.set_title(f'mean_iou: {np.mean(ious):.2f} \n Image', fontsize=25)
    ax1.axis('off')
    ax1.imshow(img)

    ax2 = fig.add_subplot(specs[0,1])
    ax2.set_title('GT', fontsize=20)
    ax2.axis('off')
    ax2.imshow(gt)

    count = 0
    for pred, sentence, iou in zip(preds, sentences, ious):
        mask_seg = copy.copy(img)

        for c in range(3):
            mask_seg[:,:,c] = np.where(pred == 1,
                                       mask_seg[:,:,c] * opacity + (1 - opacity) * color[c],
                                       mask_seg[:,:,c])

        ax = fig.add_subplot(specs[1, count])
        ax.set_title(f'IoU: {iou:.2f} \n {sentence}', fontsize=25)
        ax.axis('off')
        ax.imshow(mask_seg)

        count += 1

    os.makedirs(f'./show_result/{args.dataset}_{args.split}_{args.clip_model}_{height}x{width}/', exist_ok=True)
    show_dir = f'./show_result/{args.dataset}_{args.split}_{args.clip_model}_{height}x{width}/M{np.mean(ious):.2f}_H{np.max(ious):.2f}_L{np.min(ious):.2f}_{sentence}.jpg'


    plt.savefig(show_dir)
    plt.show()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1656243431428&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;show_result(imgs, target, result_segs, sentence_raw, this_ious, args, Height, Width)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgTRO4/btrFKHfRnd0/fP1Bt3sPuKpMFRddhEb3xK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgTRO4/btrFKHfRnd0/fP1Bt3sPuKpMFRddhEb3xK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgTRO4/btrFKHfRnd0/fP1Bt3sPuKpMFRddhEb3xK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgTRO4%2FbtrFKHfRnd0%2FfP1Bt3sPuKpMFRddhEb3xK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;924&quot; height=&quot;391&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>mask</category>
      <category>matplotlib</category>
      <category>pytorch</category>
      <category>segmentation</category>
      <category>segmentation mask visualization</category>
      <category>visualization</category>
      <category>시각화</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/970</guid>
      <comments>https://deep-learning-study.tistory.com/970#entry970comment</comments>
      <pubDate>Sun, 26 Jun 2022 20:40:42 +0900</pubDate>
    </item>
    <item>
      <title>파이참에서 원격 주피터 노트북 사용하기</title>
      <link>https://deep-learning-study.tistory.com/969</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;파이참으로 원격 서버의 interpreter를 사용하여 주피터 노트북 사용하는 방법을 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 local에 ipynb 파일을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ipynb 파일을 실행하면 상단에 interpreter를 설정할 수 있는 옵션이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;99&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0bbsj/btrFGOfetBx/fLptzlYsNtRx5qKBctbgLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0bbsj/btrFGOfetBx/fLptzlYsNtRx5qKBctbgLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0bbsj/btrFGOfetBx/fLptzlYsNtRx5qKBctbgLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0bbsj%2FbtrFGOfetBx%2FfLptzlYsNtRx5qKBctbgLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;738&quot; height=&quot;99&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;99&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 옵션으로 interpreter를 설정하면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Jupyter&amp;nbsp;server&amp;nbsp;process&amp;nbsp;failed&amp;nbsp;to&amp;nbsp;start&amp;nbsp;Illegal&amp;nbsp;char&amp;nbsp;:&amp;gt;&amp;nbsp;at&amp;nbsp;index&amp;nbsp;4&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;41&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n8n25/btrFKHUe0jl/9dgA3CjrKOHWkzpZM9rhYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n8n25/btrFKHUe0jl/9dgA3CjrKOHWkzpZM9rhYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n8n25/btrFKHUe0jl/9dgA3CjrKOHWkzpZM9rhYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn8n25%2FbtrFKHUe0jl%2F9dgA3CjrKOHWkzpZM9rhYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;41&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;41&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;configured server 로 설정을 해줘야 하는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원격 서버에서 jupyter notebook을 실행 후 생성된 주소와 토큰을 configured server에 입력해주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zd8mF/btrFIeSLHs9/vSO2F9tFMlruiDi5KnV44K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zd8mF/btrFIeSLHs9/vSO2F9tFMlruiDi5KnV44K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zd8mF/btrFIeSLHs9/vSO2F9tFMlruiDi5KnV44K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzd8mF%2FbtrFIeSLHs9%2FvSO2F9tFMlruiDi5KnV44K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;694&quot; height=&quot;125&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;127.0.0.1 부분을 원격 서버의 ip로 설정해주어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/기타 코딩</category>
      <category>jupyter</category>
      <category>Jupyter server process failed to start Illegal char :&amp;gt; at index 4</category>
      <category>Notebook</category>
      <category>pycharm</category>
      <category>Remote</category>
      <category>Server</category>
      <category>노트북</category>
      <category>원격서버</category>
      <category>주피터</category>
      <category>파이참</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/969</guid>
      <comments>https://deep-learning-study.tistory.com/969#entry969comment</comments>
      <pubDate>Sun, 26 Jun 2022 16:30:26 +0900</pubDate>
    </item>
    <item>
      <title>[Python] list()와 []의 차이점</title>
      <link>https://deep-learning-study.tistory.com/968</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;numpy.array 타입을 가진 변수 a가 있다고 가정하겠습니다.&lt;br /&gt;type(a) = np.array&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;list(a)는 np.array type을 지닌 a를 list type으로 변경합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[a]는 list[np.array] 처럼 np.array를 list로 감쌉니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/기타 코딩</category>
      <category>list</category>
      <category>list 차이점</category>
      <category>Python</category>
      <category>[]</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/968</guid>
      <comments>https://deep-learning-study.tistory.com/968#entry968comment</comments>
      <pubDate>Thu, 16 Jun 2022 01:55:25 +0900</pubDate>
    </item>
    <item>
      <title>Selenium을 사용해서 백준 유저가 푼 문제 크롤링 하기</title>
      <link>https://deep-learning-study.tistory.com/967</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 환경에서 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 실행하여 크롬 드라이버를 설치합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1655303563650&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apt install chromium-chromedriver&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 사이트에서 유저가 푼 문제를 받아오는 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1655303584965&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def get_solved_problem(name='chleodnr3'):
    options = webdriver.ChromeOptions()
    options.add_argument(&quot;headless&quot;)

    # apt install chromium-chromedriver

    name = 'chleodnr3'
    driver = webdriver.Chrome(options=options)
    driver.get(&quot;https://www.acmicpc.net/user/{}&quot;.format(name))
    element = driver.find_element(By.CLASS_NAME, 'problem-list')

    problems = element.text
    problems = problems.split(' ')
    problems = list(map(int, problems))
    return problems&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 함수를 호출하면 유저가 푼 문제를 list[int] 형태로 반환합니다.&lt;/p&gt;</description>
      <category>Python/기타 코딩</category>
      <category>Crawling</category>
      <category>Selenium</category>
      <category>문제</category>
      <category>백준</category>
      <category>셀레니움</category>
      <category>크롤링</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/967</guid>
      <comments>https://deep-learning-study.tistory.com/967#entry967comment</comments>
      <pubDate>Wed, 15 Jun 2022 23:35:27 +0900</pubDate>
    </item>
    <item>
      <title>파이참 한국어에서 영어로 설정하기</title>
      <link>https://deep-learning-study.tistory.com/966</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;파이참 버전 업데이트를 하니 자동으로 한국어팩이 설치되어 한국어 파이참이 적용되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영어 파이참을 오래 써왔던 터라 오히려 한국어 버전이 불편했는데 이번 기회에 한국어에서 영어로 변경해보고 방법까지 공유하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;714&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GuBva/btrEAzP8jES/PNicEfjii7PYqfH4szl6tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GuBva/btrEAzP8jES/PNicEfjii7PYqfH4szl6tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GuBva/btrEAzP8jES/PNicEfjii7PYqfH4szl6tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGuBva%2FbtrEAzP8jES%2FPNicEfjii7PYqfH4szl6tk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;991&quot; height=&quot;714&quot; data-origin-width=&quot;991&quot; data-origin-height=&quot;714&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setting에서 plugins에 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 있는 installed(설치됨) 탭에 들어가면 한국어 언어팩을 볼 수 있는데, 체크를 풀어주고 apply를 누르면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/기타 코딩</category>
      <category>English</category>
      <category>Korean</category>
      <category>pycharm</category>
      <category>영어</category>
      <category>파이참</category>
      <category>한국</category>
      <category>한국어 언어 팩</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/966</guid>
      <comments>https://deep-learning-study.tistory.com/966#entry966comment</comments>
      <pubDate>Sun, 12 Jun 2022 17:52:00 +0900</pubDate>
    </item>
    <item>
      <title>파이참 버전 업데이트</title>
      <link>https://deep-learning-study.tistory.com/965</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이참 버전 업데이트 하는 방법을 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;50&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1c9vm/btrEuESD6aY/dU7pZK4nVt4iCqupj5XjG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1c9vm/btrEuESD6aY/dU7pZK4nVt4iCqupj5XjG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1c9vm/btrEuESD6aY/dU7pZK4nVt4iCqupj5XjG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1c9vm%2FbtrEuESD6aY%2FdU7pZK4nVt4iCqupj5XjG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;50&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;50&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상위 도구 바에서 Help를 누른 후 Check for Updates를 선택하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;21년도 버전을 사용하다가, 22년도 버전을 사용하려는 이유는 원격 서버에 있는 .py 파일을 간단하게 새로고침 할 수 있는 기능이 있기 때문이다 ㅎㅎ&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/기타 코딩</category>
      <category>pycharm</category>
      <category>Update</category>
      <category>Version</category>
      <category>버전</category>
      <category>업데이트</category>
      <category>파이참</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/965</guid>
      <comments>https://deep-learning-study.tistory.com/965#entry965comment</comments>
      <pubDate>Sun, 12 Jun 2022 17:49:42 +0900</pubDate>
    </item>
    <item>
      <title>[Pytorch] List를 Tensor로 변경하기. torch.stack</title>
      <link>https://deep-learning-study.tistory.com/964</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;list에 tensor가 담겨져 있는 경우, list를 없애고 torch.tensor로 바꾸는 방법은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653228740517&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# segm_result = list[tensor]
segm_result = torch.stack(segm_result, dim=0)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>list</category>
      <category>TENSOR</category>
      <category>torch.stack</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/964</guid>
      <comments>https://deep-learning-study.tistory.com/964#entry964comment</comments>
      <pubDate>Sun, 22 May 2022 23:14:10 +0900</pubDate>
    </item>
    <item>
      <title>[PyTorch] 학습 progress bar 설정하기</title>
      <link>https://deep-learning-study.tistory.com/963</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;학습시에 진행과정, 경과시간, 예상시간을 확인하고 싶은 경우, 사용가능한 함수가 mmcv에 구현되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1652795926698&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import mmcv

prog_bar = mmcv.ProgressBar(len(dataset))

for i, data in enumerate(data_loader):
	...
    
    for _ in range(batch_size):
    	prog_bar.update()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvxhk4/btrCpWnb5gg/QlC9V55KQyhIvlGowAcsB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvxhk4/btrCpWnb5gg/QlC9V55KQyhIvlGowAcsB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvxhk4/btrCpWnb5gg/QlC9V55KQyhIvlGowAcsB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbvxhk4%2FbtrCpWnb5gg%2FQlC9V55KQyhIvlGowAcsB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;808&quot; height=&quot;37&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/PyTorch 공부</category>
      <category>mmcv</category>
      <category>Progress bar</category>
      <category>pytorch</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/963</guid>
      <comments>https://deep-learning-study.tistory.com/963#entry963comment</comments>
      <pubDate>Tue, 17 May 2022 23:14:17 +0900</pubDate>
    </item>
    <item>
      <title>[논문 읽기] Open-World Entity Segmentation(2021)</title>
      <link>https://deep-learning-study.tistory.com/962</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Open-World&amp;nbsp;Entity&amp;nbsp;Segmentation&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2107.14228&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://arxiv.org/abs/2107.14228&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646377982261&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Open-World Entity Segmentation&quot; data-og-description=&quot;We introduce a new image segmentation task, called Entity Segmentation (ES), which aims to segment all visual entities (objects and stuffs) in an image without predicting their semantic labels. By removing the need of class label prediction, the models tra&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2107.14228&quot; data-og-url=&quot;https://arxiv.org/abs/2107.14228v2&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gHwnV/hyNB1ilFH1/GnnBNoisRsZxgnvGEj3tck/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2107.14228&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2107.14228&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gHwnV/hyNB1ilFH1/GnnBNoisRsZxgnvGEj3tck/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Open-World Entity Segmentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;We introduce a new image segmentation task, called Entity Segmentation (ES), which aims to segment all visual entities (objects and stuffs) in an image without predicting their semantic labels. By removing the need of class label prediction, the models tra&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;class agnostic 하게 segmentation 하는 모델이다. entity를 segment 하는데, entity는 stuff와 thing 모두를 포함한다. class-agnostic한 segmentation을 하므로 class prediction에 신경쓸 필요가 없다. 따라서 class-specific하게 학습된 모델보다 localization 능력이 향상된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5jmEQ/btru8uQ7N30/aaejSNS0UlqLVc8KJsWuuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5jmEQ/btru8uQ7N30/aaejSNS0UlqLVc8KJsWuuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5jmEQ/btru8uQ7N30/aaejSNS0UlqLVc8KJsWuuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5jmEQ%2Fbtru8uQ7N30%2FaaejSNS0UlqLVc8KJsWuuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;692&quot; height=&quot;208&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;208&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;FCOS의 center-based representation과 CondInst의 generate kernel 방식을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/esauO6/btru7ssuTu8/BLs9fVIdAG5KXO3C9KIyGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/esauO6/btru7ssuTu8/BLs9fVIdAG5KXO3C9KIyGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/esauO6/btru7ssuTu8/BLs9fVIdAG5KXO3C9KIyGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FesauO6%2Fbtru7ssuTu8%2FBLs9fVIdAG5KXO3C9KIyGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1314&quot; height=&quot;600&quot; data-origin-width=&quot;1314&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;FPN에 부착된 head는 kernel, entityness, centerness, locaization 을 출력한다. localization은 바운딩박스를 생성하기 위함이고 추후에 NMS를 사용하여 output을 정제하기 위함이다. entityness와 centerness는 probability map이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;논문에서 제안하는 방식은 global kernel bank를 사용하여 conv weight 를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; entity들이 공통적으로 지니고 있는 property와 entity 사이에 서로 다른 property를 추출하기 위해 dynamic weight와 static weight를 생성한다. 생성된 weight들을 순열방식으로 7개의 path를 만들어서 training에 활용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;inference는 dynamic weight로만 이루어진 7번 path만을 사용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;또 overlab suppression 방법을 제안한다. 모델이 예측한 mask가 overlap 될 수 있는데 이를 억제하는 역할이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v2uN7/btru2ox7LXl/QkGVQqA037I3fu1sKhozsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v2uN7/btru2ox7LXl/QkGVQqA037I3fu1sKhozsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v2uN7/btru2ox7LXl/QkGVQqA037I3fu1sKhozsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv2uN7%2Fbtru2ox7LXl%2FQkGVQqA037I3fu1sKhozsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;424&quot; height=&quot;98&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;98&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;7번 path에 존재하는 3개의 weight를 mask feature map에 적용하여 평균낸 값을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;48&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9BGZi/btru0vwXNYp/DkD2Ifcc8ED2JNnT49kiLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9BGZi/btru0vwXNYp/DkD2Ifcc8ED2JNnT49kiLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9BGZi/btru0vwXNYp/DkD2Ifcc8ED2JNnT49kiLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9BGZi%2Fbtru0vwXNYp%2FDkD2Ifcc8ED2JNnT49kiLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;346&quot; height=&quot;48&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;48&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;또 학습시에도 loss를 가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GZuw1/btru9qHBfFp/sxDcosvJzmYDDPmfGyFc5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GZuw1/btru9qHBfFp/sxDcosvJzmYDDPmfGyFc5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GZuw1/btru9qHBfFp/sxDcosvJzmYDDPmfGyFc5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGZuw1%2Fbtru9qHBfFp%2FsxDcosvJzmYDDPmfGyFc5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;648&quot; height=&quot;522&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 읽기/Segmentation</category>
      <category>Open-World Entity Segmentation</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/962</guid>
      <comments>https://deep-learning-study.tistory.com/962#entry962comment</comments>
      <pubDate>Fri, 4 Mar 2022 16:34:03 +0900</pubDate>
    </item>
    <item>
      <title>[논문 읽기] CondInst(2020), Conditional Convolutions for Instance Segmentation</title>
      <link>https://deep-learning-study.tistory.com/961</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Conditional&amp;nbsp;Convolutions&amp;nbsp;for&amp;nbsp;Instance&amp;nbsp;Segmentation&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2003.05664&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://arxiv.org/abs/2003.05664&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646377705731&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Conditional Convolutions for Instance Segmentation&quot; data-og-description=&quot;We propose a simple yet effective instance segmentation framework, termed CondInst (conditional convolutions for instance segmentation). Top-performing instance segmentation methods such as Mask R-CNN rely on ROI operations (typically ROIPool or ROIAlign) &quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2003.05664&quot; data-og-url=&quot;https://arxiv.org/abs/2003.05664v4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/hL38O/hyNAQ3Nf5t/MfFDfRsOqk61It8kYcsUpk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2003.05664&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2003.05664&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/hL38O/hyNAQ3Nf5t/MfFDfRsOqk61It8kYcsUpk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Conditional Convolutions for Instance Segmentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;We propose a simple yet effective instance segmentation framework, termed CondInst (conditional convolutions for instance segmentation). Top-performing instance segmentation methods such as Mask R-CNN rely on ROI operations (typically ROIPool or ROIAlign)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SsPMr/btruVYfAjq9/vfUCQZZPVGeBRAY5PRVEhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SsPMr/btruVYfAjq9/vfUCQZZPVGeBRAY5PRVEhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SsPMr/btruVYfAjq9/vfUCQZZPVGeBRAY5PRVEhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSsPMr%2FbtruVYfAjq9%2FvfUCQZZPVGeBRAY5PRVEhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;774&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;FPN으로 추출한 feature map에 1x1 conv weight, bias를 생성하는 head를 부착한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;생성한 weight는 pixel wise하게 생성되므로 instance aware한 정보를 지니고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 weight를 Mask head로 사용하여 mask를 추출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;955&quot; data-origin-height=&quot;663&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsKMIf/btru1cdAZAY/5azTB2yqlJXar2z8MOs8hK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsKMIf/btru1cdAZAY/5azTB2yqlJXar2z8MOs8hK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsKMIf/btru1cdAZAY/5azTB2yqlJXar2z8MOs8hK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsKMIf%2Fbtru1cdAZAY%2F5azTB2yqlJXar2z8MOs8hK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;955&quot; height=&quot;663&quot; data-origin-width=&quot;955&quot; data-origin-height=&quot;663&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 읽기/Segmentation</category>
      <category>Conditional Convolutions for Instance Segmentation]</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/961</guid>
      <comments>https://deep-learning-study.tistory.com/961#entry961comment</comments>
      <pubDate>Fri, 4 Mar 2022 16:10:09 +0900</pubDate>
    </item>
    <item>
      <title>[논문 읽기] CaSP, Class agnostic Semi-Supervised Pretraining for Detection and Segmentation</title>
      <link>https://deep-learning-study.tistory.com/960</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CaSP,&amp;nbsp;Class&amp;nbsp;agnostic&amp;nbsp;Semi-Supervised&amp;nbsp;Pretraining&amp;nbsp;for&amp;nbsp;Detection&amp;nbsp;and&amp;nbsp;Segmentation&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2112.04966&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://arxiv.org/abs/2112.04966&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1646206114933&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;CaSP: Class-agnostic Semi-Supervised Pretraining for Detection and Segmentation&quot; data-og-description=&quot;To improve instance-level detection/segmentation performance, existing self-supervised and semi-supervised methods extract either very task-unrelated or very task-specific training signals from unlabeled data. We argue that these two approaches, at the two&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2112.04966&quot; data-og-url=&quot;https://arxiv.org/abs/2112.04966v1&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jpzda/hyNzSAqC7x/68gkbNT3rAOi0krcnDkPcK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2112.04966&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2112.04966&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jpzda/hyNzSAqC7x/68gkbNT3rAOi0krcnDkPcK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CaSP: Class-agnostic Semi-Supervised Pretraining for Detection and Segmentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;To improve instance-level detection/segmentation performance, existing self-supervised and semi-supervised methods extract either very task-unrelated or very task-specific training signals from unlabeled data. We argue that these two approaches, at the two&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;semi seg or detection 논문.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;기존의 semi 는 labeled data와 unlabeled data를 joint하여 학습시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/44fP2/btruwJwdDam/gzjDXNLiKosHvuDZ9zuq91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/44fP2/btruwJwdDam/gzjDXNLiKosHvuDZ9zuq91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/44fP2/btruwJwdDam/gzjDXNLiKosHvuDZ9zuq91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F44fP2%2FbtruwJwdDam%2FgzjDXNLiKosHvuDZ9zuq91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;516&quot; height=&quot;529&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;529&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 논문은 class agnoistic unlabeled data로 pre-training 한뒤에 labeled data로 fine-tuning을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;516&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zcWRz/btruTiqivyR/QUWzurCy069FzgtW9CzcOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zcWRz/btruTiqivyR/QUWzurCy069FzgtW9CzcOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zcWRz/btruTiqivyR/QUWzurCy069FzgtW9CzcOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzcWRz%2FbtruTiqivyR%2FQUWzurCy069FzgtW9CzcOK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1054&quot; height=&quot;516&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;516&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위 논문은 3가지 process가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) Early pretraining&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;detection dataset에서 class 정보를 제거하고 class-agnoistic한 data로 detector를 학습시킨다. localization만 집중하기 때문에 localization 성능이 class-specific data로 학습 시킨 것 보다 agnoistic 한게 더 높게 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) Late pretraining&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;229&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCm5Aq/btruMoL5Y3S/7FyIXjaBKIdFXqR7grGAZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCm5Aq/btruMoL5Y3S/7FyIXjaBKIdFXqR7grGAZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCm5Aq/btruMoL5Y3S/7FyIXjaBKIdFXqR7grGAZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCm5Aq%2FbtruMoL5Y3S%2F7FyIXjaBKIdFXqR7grGAZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;522&quot; height=&quot;229&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;229&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;(1)로 학습한 모델로 unlabeled data로부터 pseudo label을 생성해 target detector를 학습시킨다. 역시 class agnoistic하게.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) fine-tuning&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이제 target detector를 down-stream dataset에 class 정보와 함께 학습시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUrJLf/btruWkgCZbU/Le1uCdrNEybiQb1jgz6fN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUrJLf/btruWkgCZbU/Le1uCdrNEybiQb1jgz6fN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUrJLf/btruWkgCZbU/Le1uCdrNEybiQb1jgz6fN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUrJLf%2FbtruWkgCZbU%2FLe1uCdrNEybiQb1jgz6fN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;524&quot; height=&quot;428&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;849&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSaRlw/btruPblcLkX/VHDKIjafi0kf8K2cKXlSIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSaRlw/btruPblcLkX/VHDKIjafi0kf8K2cKXlSIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSaRlw/btruPblcLkX/VHDKIjafi0kf8K2cKXlSIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSaRlw%2FbtruPblcLkX%2FVHDKIjafi0kf8K2cKXlSIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;521&quot; height=&quot;849&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;849&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1646206634721&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - Seonghoon-Yu/AI_Paper_Review: 까먹으면 다시 보려고 정리합니다.&quot; data-og-description=&quot;까먹으면 다시 보려고 정리합니다. Contribute to Seonghoon-Yu/AI_Paper_Review development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Seonghoon-Yu/AI_Paper_Review&quot; data-og-url=&quot;https://github.com/Seonghoon-Yu/AI_Paper_Review&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fqv1h/hyNzMfUENX/7nvuSzpvx78wMwAvsa8k7K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/Seonghoon-Yu/AI_Paper_Review&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Seonghoon-Yu/AI_Paper_Review&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fqv1h/hyNzMfUENX/7nvuSzpvx78wMwAvsa8k7K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - Seonghoon-Yu/AI_Paper_Review: 까먹으면 다시 보려고 정리합니다.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;까먹으면 다시 보려고 정리합니다. Contribute to Seonghoon-Yu/AI_Paper_Review development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>논문 읽기/Semi-Supervised</category>
      <category>casp</category>
      <category>class agnoistic semi-supervised pretraining for detection and segmentation</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/960</guid>
      <comments>https://deep-learning-study.tistory.com/960#entry960comment</comments>
      <pubDate>Wed, 2 Mar 2022 16:37:33 +0900</pubDate>
    </item>
    <item>
      <title>[python] 파이썬 패키지, 모듈 저장 위치 확인하기</title>
      <link>https://deep-learning-study.tistory.com/959</link>
      <description>&lt;pre id=&quot;code_1645727611491&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import clip
import inspect

print(inspect.getfile(clip))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;43&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwBT5I/btrueyHAcTu/G4XOMzjvIUOwJD6zWj5Xg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwBT5I/btrueyHAcTu/G4XOMzjvIUOwJD6zWj5Xg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwBT5I/btrueyHAcTu/G4XOMzjvIUOwJD6zWj5Xg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwBT5I%2FbtrueyHAcTu%2FG4XOMzjvIUOwJD6zWj5Xg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;526&quot; height=&quot;43&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;43&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Python/기타 코딩</category>
      <category>inspect</category>
      <category>라이브러리</category>
      <category>모듈</category>
      <category>저장위치</category>
      <category>파이썬</category>
      <category>패키지 저장위치</category>
      <author>AI 꿈나무</author>
      <guid isPermaLink="true">https://deep-learning-study.tistory.com/959</guid>
      <comments>https://deep-learning-study.tistory.com/959#entry959comment</comments>
      <pubDate>Fri, 25 Feb 2022 03:34:00 +0900</pubDate>
    </item>
  </channel>
</rss>