<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>u_jinju.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 19 Oct 2022 07:44:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>u_jinju.log</title>
            <url>https://images.velog.io/images/u_jinju/profile/c6c04a0f-e21a-47a2-9750-d7fc8b747c93/캡처.PNG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. u_jinju.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/u_jinju" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[docker] docker 명령어 정리 ]]></title>
            <link>https://velog.io/@u_jinju/docker-docker-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@u_jinju/docker-docker-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 19 Oct 2022 07:44:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>회사 내에서 학습시키기위해 도커를 사용하여서 서버사용하는데 정리가 필요해서 적어봄.  </p>
</blockquote>
<h1 id="docker">Docker?</h1>
<p>컨테이너 기반의 오픈소스 가상화 플랫폼</p>
<h1 id="image">Image</h1>
<ul>
<li>서비스 운영에 필요한 서버 프로그램, 소스코드 및 라이브러리, 컴파일된 실행파일 묶는 형태</li>
<li>회사 문서에 보면 &quot;붕어빵을 찍어내는 빵판&quot;과 같은 의미</li>
</ul>
<h1 id="container">Container</h1>
<ul>
<li>이미지를 실행한 상태, 응용프로그램의 종속성과 함께 응용프로그램 자체를 패캐징 or 캡슐화하여 격리된 공간에서 프로세스를 동작시키는 기술</li>
<li>회사 문서에 보면 &quot;붕어빵 판에서 찍어낸 붕어빵&quot;과 같은 의미</li>
</ul>
<h1 id="명령어">명령어</h1>
<ul>
<li>내가 서버 내에서 사용하는 명령어만 정리함</li>
</ul>
<h2 id="image-가져오기">image 가져오기</h2>
<p>방식은 두가지가 존재함. </p>
<ol>
<li>npg 를 사용</li>
<li>pull 사용</li>
</ol>
<h3 id="pull-하는-법">pull 하는 법</h3>
<p><a href="https://hub.docker.com/">docker hub</a> 에서 원하는 환경을 pull 하면 됨. 
나 같은 경우는 pytorch/ cuda 11버전 / cudnn 을 원했음.</p>
<p>[pytorch/cuda11/cudnn8] (<a href="https://hub.docker.com/layers/pytorch/pytorch/1.8.1-cuda11.1-cudnn8-devel/images/sha256-024af183411f136373a83f9a0e5d1a02fb11acb1b52fdcf4d73601912d0f09b1?context=explore)%EC%97%90">https://hub.docker.com/layers/pytorch/pytorch/1.8.1-cuda11.1-cudnn8-devel/images/sha256-024af183411f136373a83f9a0e5d1a02fb11acb1b52fdcf4d73601912d0f09b1?context=explore)에</a> 맞는 docker image를 찾고 pull 해주면됨. </p>
<pre><code>sudo docker pull pytorch/pytorch:1.8.1-cuda11.1-cudnn8-devel</code></pre><h3 id="image-확인">image 확인</h3>
<pre><code>sudo docker images</code></pre><h3 id="container-실행">container 실행</h3>
<pre><code>sudo docker run --gpus all -it -d -v (마운트할 폴더) -p 8097:8097 --ipc=host --name (container 이름설정) (image id) /bin/bash</code></pre><p>예를 들어서, </p>
<pre><code>sudo docker run --gpus all -it -d -v /media/hdd/jinju/shared:/media/hdd/jinju/shared -v /media/hdd/jinju/data:/media/hdd/jinju/data -p 8097:8097 --ipc=host --name jj-pytorch 7afd9b52a068 /bin/bash</code></pre><p>여기서 port는 tensorboard 사용하기 위해서 사용함. 
port를 설정해야 학습진행사항 확인할 수 있는 tensorboard 가능함.</p>
<h3 id="container-실행확인">container 실행확인</h3>
<p>현재 실행된 container 확인</p>
<pre><code>sudo docker ps</code></pre><p>전체 container 뭐가 있는지 확인</p>
<pre><code>sudo docker ps -a</code></pre><h3 id="container-들어가기">container 들어가기</h3>
<pre><code>sudo docker exec -it (container name) /bin/bash/</code></pre><p>예를 들어</p>
<pre><code>sudo docker exec -it jj-pytorch /bin/bash/</code></pre><p>각 파라미터들은 무엇을 의미하는지는 각자가 알아보면 좋을 것 같다. 
docker 개념이 어려웠었는데 몇번 사용하다보니 감을 잡았다. 
정리하니 더 확실히 좋다. </p>
<h1 id="reference">Reference</h1>
<p><a href="https://hoon93.tistory.com/48">https://hoon93.tistory.com/48</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[pyinstaller] This application failed to start because it could not find or load the Qt platform plugin "windows" in "". / pyqt5 exe파일 배포시 error (에러해결)]]></title>
            <link>https://velog.io/@u_jinju/pyinstaller-This-application-failed-to-start-because-it-could-not-find-or-load-the-Qt-platform-plugin-windows-in-.-%EC%97%90%EB%9F%AC%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@u_jinju/pyinstaller-This-application-failed-to-start-because-it-could-not-find-or-load-the-Qt-platform-plugin-windows-in-.-%EC%97%90%EB%9F%AC%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Wed, 30 Mar 2022 15:06:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>아.. 회사에서 pyqt로 간단한 gui tool만들어서 exe파일로 배포를 하는데 하루종일 이 에러때문에 시간을 날렸다. 하.. 온갖 구글링에서 나온 이유들 다 해봤는데 안되서 나는 내가 해결한 방법 작성하도록 하겠다 ㅠㅠ</p>
</blockquote>
<h1 id="개발환경">개발환경</h1>
<p>우선 개발환경은 window환경이고 pycharm에서 Python3를 사용하여 pyqt5를 설치하고 개발을 하였다. </p>
<h1 id="pyinstaller">pyinstaller</h1>
<p>pyinstaller로 exe파일을 만드는데 자꾸 이와 같은 에러가 났다. </p>
<blockquote>
<p>This application failed to start because it could not find or load the Qt platform plugin &quot;windows&quot; in &quot;&quot;.</p>
</blockquote>
<p><img src="https://images.velog.io/images/u_jinju/post/34d9ad10-86f0-4b37-8ace-f46a20f58bf6/image.png" alt=""></p>
<p>그래서 환경변수에 다음과 같이 넣어보기도 하고 했는데 <strong>안됨</strong>
<img src="https://images.velog.io/images/u_jinju/post/0ffa8130-eca8-4e86-aa46-483abe9e16c5/image.png" alt=""></p>
<p>구글링을 통한 방법들은 다음과 같았다. </p>
<ol>
<li><p>환경 변수로 pyqt5 폴더안에 plugin 폴더가 잇는데 그 안에 platforms 폴더 속 qwindows.dll 파일이 있는 해당 Path를 추가하는 것. --&gt; 응 안됨</p>
</li>
<li><p>qwindows.dll파일을 exe파일이 생성된 dist파일에 platforms 폴더에 넣어서 넣고, pyqt5를 설치한 bin파일 속에 있는 libEGL.dll를 넣는 것. --&gt; 당연 안됨.</p>
</li>
<li><p><a href="http://www.dependencywalker.com">Dependency Walker</a> (exe file or dll file 빠진거 찾아주는거임) 를 사용해서 exe파일 안에 어떤 dll이 빠졌는지 확인해보기 --&gt; 그 결과 <strong>&quot;api-ms-win-core *.dll&quot;</strong> 파일이 죄다 없었음. 
<img src="https://images.velog.io/images/u_jinju/post/385df6cb-3a34-4d02-9ba7-82ae6ccb5a3b/image.png" alt="">
이 파일은 C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x64 파일 경로에 들어가면 있음!</p>
</li>
</ol>
<p>그래서 exe파일이 생성된 dist파일에 해당 애들을 다 넣어줬는데 안됨~!</p>
<h1 id="해결방법">해결방법</h1>
<p>하.. exe파일을 만들다보면 cmd창에 로그가 찍히는데 맨첫번째 로그에 pyinstaller 버전이 나오고 그다음에 python3 버전이 나옴. 내 컴퓨터는 anaconda2를 사용하여 있어서 python2가 디폴트로 빌드가 되는 것인지.. pyinstaller는 pip3로 install해서 3의 4.1 버전이였고 python2로 빌드를 하고 있었다...!</p>
<p>난 pycharm에서 python3로 pyqt5를 사용하고 있었는데..(pyqt5는 python3에서 지원가능함..) 그래서 당연 안됐던 것. 근데 왜 저런 윈도우 플로그 어쩌고 문제가 나는진 모름..</p>
<p>그래서 python3가 설치되어 있는 경로로 가서 해당 명령어를 사용하여 빌드했더니 ㅠㅠ 너무잘됨...</p>
<blockquote>
<p>python3가 있는 경로: C:\Users\owner\AppData\Local\Programs\Python\Python38\Scripts</p>
</blockquote>
<pre><code class="language-bash">.\pyinstaller.exe --onedir --clean --hidden-import PyQt5 -p [dll파일이 있는 경로] [exe파일만들고자하는 파일이름].py</code></pre>
<p>--onedir: 하나의 dir로 만드는 거
--hidden-import: exe파일을 만드는데 PyQt5가 modulenotfound여서 이럴경우 없는 모듈을 치면 나옴 단, pip3 install pyqt5를 했는데도 안됐을 경우! 추가적으로, PyQt5.sip 도 없다고 나오는 경우도 있다는데 난 아니였음. 해당사항도 마찬가지로 똑같이 넣으면됨. 
--p: 이건 위에서 window관련 dll파일이 없다고 나와서 3번에 있는 폴더에서 dll파일만 복사해서 따로 폴더만들어주고 해당 폴더 경로를 넣어줌. </p>
<p>그랬더니 만들어졌다!!! 예~</p>
<p>후 하다가 나처럼 고생하는사람이 많을 것 같아서 적었다 ㅠㅠ</p>
<p>결국은 python버전과 pyinstaller 버전이 똑같아야한다는 사실이다..!!!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문 리뷰] SSD: Single Shot MultiBox Detector ]]></title>
            <link>https://velog.io/@u_jinju/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-SSD-Single-Shot-MultiBox-Detector</link>
            <guid>https://velog.io/@u_jinju/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-SSD-Single-Shot-MultiBox-Detector</guid>
            <pubDate>Thu, 09 Dec 2021 06:44:52 GMT</pubDate>
            <description><![CDATA[<h1 id="작성계기">작성계기</h1>
<p>회사에서 논문을 읽고 있는데, 화요일마다 리뷰시간이 있어서 공부겸 다시 정리 </p>
<h1 id="abstract">Abstract</h1>
<ol>
<li>multiple feature map을 사용해서 output 공간을 여러개로 나눈다.</li>
<li>각 feature map을 여러 비율과 스케율로 default box를 생성하고 모델을 통해서 계산된 좌표와 class score을 생성한 default box를 통해 최종 bbox를 생성한다.</li>
<li>2-stage의 Faster-RCNN의 성능을 가지면서 1-stage의 YOLO와 같이 속도가 빠르다고 말한다.
즉, 이 논문은 1 stagy의 detector! </li>
</ol>
<h1 id="introduce">Introduce</h1>
<p>아래와 같이 간추려 설명함.</p>
<ol>
<li>이전 state-of-the art보다 (YOLO) 속도가 빠르고, region proposal과 pooling (Faster-RCNN)의 성능이 빠르다고 한다.</li>
<li>SSD는 feature map에 적용된 small conv를 사용하여 고정된 default bbox set을 통해 category score과 box offset을 예측한다.</li>
<li>high detection accuracy를 위해서 가로 세로 비율, scale이 서로 다른 feature map을 제공한다.</li>
<li>time, input size 등 다 실험했고 PASCAL VOC, COCO, ILSVRC에서도 데이터 성능비교 결과 제일 좋다.</li>
</ol>
<h1 id="the-single-shot-detector-ssd">The Single Shot Detector (SSD)</h1>
<p><img src="https://images.velog.io/images/u_jinju/post/5cc802b7-16c5-4654-ae9c-892295b60344/image.png" alt=""></p>
<p>SSD는 위 그림 (a)에서 처럼 학습을 위해 각 물체에 대한 input image와 GT가 필요하다.
(b) 각 다른 scale을 가진 feature map에 대하여 각 다른 비율을 가진 default box로 평가한다.
(c) 각 default box 통해, 각 물체 category에 대한 shape offset과 confidence를 예측할 수 있다.</p>
<h2 id="21-model">2.1 model</h2>
<blockquote>
<p>The SSD approach is based on a feed-forward convolutional network that produces a fixed-size collection of bounding boxes and scores for the presence of object class instances in those boxes, followed by a non-maximum suppression step to produce the final detections. </p>
</blockquote>
<p>여기서 그렇게 중요한건 아니지만.. &quot;<a href="https://wikidocs.net/24987">feed-forwad</a>&quot;라는 말이 뭔지 몰라서 찾아보았다.(딥러닝을 배우는 중이라서 개념이 그렇게 완전히 잡혀있진 않음 ㅠㅠ) 
대강 입력층에서 1개이상의 은닉층이 존재하여 출력층으로 전개되는 신경망을 의미한다. (그냥 딥러닝 아니야? 라고 말할수있지만, Recrruent nerual network라고 부르는 RNN에서는 출력층의 값이 은닉층으로 다시 들어가는 경우도 존재하기 때문에 나눈다고 함)</p>
<p>anyway!</p>
<p><img src="https://images.velog.io/images/u_jinju/post/27e38d58-bf4d-418f-a6e0-b0d006f0626c/image.png" alt="">
모델은 위와 같다. </p>
<p>VGG-16 network 모델을 가져와서 FC layer를 제외한 conv7까지를 base network로 사용한다.
이 conv4_3에서 38x38x512크기의 feature map을 뽑고, conv7에서 19x19x1024 뽑음. 이 과정 포함하여 이후 layer에서 뽑는 feature map들은 output가 직결되어 있고 layer가 지날수록 size가 감소한다.</p>
<p>그래서 총 6개의 feature map을 뽑음.
좀 더 자세히 말하자면, 38x38x512, 19x19x1024x 10x10x512, 5x5x256, 3x3x256, 1x1x256** 총 6개의 다양한 scale이 존재하는 feature map** 뽑는다.
따라서, 각 scale이 다른 feature map에 해당하는 default box를 적용한 경우 default box의 수는 <strong>(38x38x4)+(19x19x6)+(10x10x6)+(5x5x6)+(3x3x4)+(1x1x4)= 8732개</strong>가 나오게 된다. 
또한, 최종 예측을 위해서 feature map 추출 후에 3x3(stride=1, padding=1) conv 연산을 수행한다. </p>
<h3 id="default-boxes-and-aspect-ratios">Default boxes and aspect ratios</h3>
<p>(여기는 진짜 이해하는데 어려웠다.. 아직도 이해 좀 안가는 부분이 있어서 미팅 후에 정리되면 다시 정리올리겠음)</p>
<p>여기서 위의 모델 구조를 보면 <strong>classifier: conv: 3x3x(4x(classes+4))</strong> 이런것을 볼 수가 있다. 각 feature map의 cell마다 default box를 생성하는데, 이 때 default bbox를 $k$, 예측하려는 class의 수를 $c$라 할 때, output feature map의 채널 수는 $(c+4)k$ 로 결과를 뽑는다. 따라서 $m\times n$의 feature map의 output channel 수는 $mnk(c+4)$ 이다. 
좀 더 설명하자면, 각 feature map의 cell마다 default box를 생성하고 각 box마다 4개의 offset과 class score가 존재하는 것. </p>
<p>예를 들어, 첫번째 feature map인 38x38x512를 보면, m=38, n= 38이고 이 해당 feature map에서는 default bbox를 4개를 사용하였다. 따라서 k=4이다. 또한, PASCAL VOC의 class는 20개이고, background까지 포함하여 c=21라 한다면 conv연산을 한 output feature map의 크기는 38x38x4x(21+4) 이다.</p>
<h2 id="22-training">2.2 Training</h2>
<h3 id="matching-strategy">Matching strategy</h3>
<blockquote>
<p>We begin by matching each groud truth box to the dfault box with the best jaccard overlap. Unlike MultiBox, we then match default boxes to any groudn truth with jaccard overlap higher than a thershold(0.5). This simplifies the learning problem, allowing the network to predict high scores for multiple overlapping default boxes rather than requiring it to pick only the one with maximum overlap.</p>
</blockquote>
<p>Training을 하기위해, 위에서 언급한 default box와 학습할 대상을 결정하기 위해서 default box가 어떤 ground truth 와 대응되는지를 알아야한다. 
이를 위해서 default box와 ground truth 간의 jaccard overlap를 사용하는데, 여기서 jaccard overlap은 우리가 잘 알고 있는 IoU(Interset of Union)과 같다.</p>
<p>default box와 ground box간의 jaccard overlap의 threshold가 0.5이상인 Box는 positive로, 그 미만인 box들은 negative가 된다. </p>
<p>여기서 이 이후에 <strong>hard negative mining</strong>이 나오게 된다. 
matching step 이후에, default box 대부분이 positive sample 수보다 negative sample 수가 더 많기 때문에 학습을 하는데 Positive와 negative사이의 상당한 불균형이 일어난다고 한다. 그 이유는 전반적인 이미지 내에 사물보다 배경(background)가 많기 때문에 높은 confindence loss를 가진 sample를 추가하는 <strong>hard negative mining</strong>을 사용한다. 본 논문에서는 positive와 negative 사이의 비율을 1:3으로 둔다한다. </p>
<h3 id="training-objective">Training objective</h3>
<p><img src="https://images.velog.io/images/u_jinju/post/01069689-f9e9-4cfb-99b6-6ec94436ba4e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] 손글씨 숫자 인식     from dataset.mnist import load_mnist 해결]]></title>
            <link>https://velog.io/@u_jinju/DL-%EC%86%90%EA%B8%80%EC%94%A8-%EC%88%AB%EC%9E%90-%EC%9D%B8%EC%8B%9D-from-dataset.mnist-import-loadmnist-%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@u_jinju/DL-%EC%86%90%EA%B8%80%EC%94%A8-%EC%88%AB%EC%9E%90-%EC%9D%B8%EC%8B%9D-from-dataset.mnist-import-loadmnist-%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Sun, 28 Nov 2021 05:42:50 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-bash">Traceback (most recent call last):
  File &quot;/Users/yujinju/Documents/Deep Learning from scratch/ch3/MNIST_dataset.py&quot;, line 3, in &lt;module&gt;
    from dataset.mnist import load_mnist
ModuleNotFoundError: No module named &#39;dataset&#39;</code></pre>
<p>오잉.. 책 따라서 코드 실행시켜보면 부모디렉토리를 못찾길래 절대경로로 해줬더니</p>
<pre><code class="language-bash">base) yujinju@yujinjuui-MacBook-Pro Deep Learning from scratch %  cd &quot;/Users/yujinju/Documents/Deep Learning from scratch&quot; ; /usr/bin/env /Users/yujinju/opt/anaconda3/bin/python /Users/yujinju/.vscode/extensions/ms-python.python-2021.11.1422169775/pythonFiles/lib/python/debugpy/launcher 58465 -- &quot;/Users/yujinju/Documents/Deep Learning from scratch/ch3/MNIST_dataset.py&quot; 
(60000, 784)
(60000,)
(10000, 784)
(10000,)</code></pre>
<p>너무 잘된다.</p>
<h2 id="에러해결">에러해결</h2>
<p>만약 같은 에러가 난다면 <strong>절대경로</strong>로 하십쇼 !</p>
<pre><code class="language-python">import sys, os
sys.path.append(&quot;/Users/yujinju/Desktop/deeplearning_from_scratch-master&quot;)
from dataset.mnist import load_mnist

(x_train, t_train), (x_test, t_test) = \
    load_mnist(flatten=True, normalize=False)

print(x_train.shape)
print(t_train.shape)
print(x_test.shape)
print(t_test.shape)</code></pre>
<p>아! 그리고 코드저장소는 
<a href="https://github.com/youbeebee/deeplearning_from_scratch">밑바닥부터 시작하는 딥러닝 github</a> 여기에 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] 손글씨 숫자 인식]]></title>
            <link>https://velog.io/@u_jinju/DL-%EC%86%90%EA%B8%80%EC%94%A8-%EC%88%AB%EC%9E%90-%EC%9D%B8%EC%8B%9D</link>
            <guid>https://velog.io/@u_jinju/DL-%EC%86%90%EA%B8%80%EC%94%A8-%EC%88%AB%EC%9E%90-%EC%9D%B8%EC%8B%9D</guid>
            <pubDate>Sun, 28 Nov 2021 05:39:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이번에는 이미 학습된 매개변수를 사용하여 학습 과정을 생략하고, 추론 과정만 구현
이 추론 과정을 신경망의 순전파(forward propagation)이라고도 한다.</p>
</blockquote>
<h2 id="minist-dataset">MINIST dataset</h2>
<p>MINIST 데이터셋은 손글씨 숫자 이미지 집합으로, 기계학습 분야세어 유명한 데이터셋이다. 
0부터 9까지의 숫자이미지로 구성되어있다. 훈련 이미지(train set)가 60000장, 시험 이미지(test set)은 10000장 준비되어 있다. 일반적으로 이 훈련 이미지들을 사용하여 모델을 학습하고, 학습한 모델로 시험 이미지들을 얼마나 정확하게 분류하는지를 평가한다.</p>
<h3 id="코드">코드</h3>
<pre><code class="language-python">import sys, os
sys.path.append(&quot;/Users/yujinju/Desktop/deeplearning_from_scratch-master&quot;)
from dataset.mnist import load_mnist

(x_train, t_train), (x_test, t_test) = \
    load_mnist(flatten=True, normalize=False)

print(x_train.shape)
print(t_train.shape)
print(x_test.shape)
print(t_test.shape)</code></pre>
<p>사실 여기서 os.pardir 부모 디렉토리를 못찾아서 나는 dataset이 들어있는 부모 경로의 절대경로를 넣어줬다. 그랬더니 너무 잘됨 <a href="https://velog.io/@u_jinju/DL-%EC%86%90%EA%B8%80%EC%94%A8-%EC%88%AB%EC%9E%90-%EC%9D%B8%EC%8B%9D-from-dataset.mnist-import-loadmnist-%ED%95%B4%EA%B2%B0">해결방법</a> 여기에도 적어두었으니 참고하시길</p>
<p>여기서 load_mnist함수는 읽은 MNIST 데이터를 &quot;(훈련 이미지, 훈련 레이블), (시험 이미지, 시험 레이블)&quot; 형식으로 반환한다. 인수로는 normalize, flatten, one_hot_label 세 가지를 설정할 수 있다. 세 인수는 모두 bool 값!</p>
<ul>
<li>normalize: 입력 이미지의 픽셀값을 0.0<del>1.0 사이의 값으로 정규화할지를 정함
false로 설정하면 입력 이미지의 픽셀은 원래 값 그대로 0</del>255 사이의 값을 유지한다.</li>
<li>flatten: 입력 이미지를 평탄하게, 즉 1차원 배열로 만들지를 정한다. 
false로 설정하면 입력 이미지를 1x28x28의 3차원의 배열로, true로 설정하면 784개를 1차원배열로 저장</li>
<li>one_hot_label: 원-핫 인코딩(one-hot encoding) 형태로 저장할지를 정한다. 
원-핫 인코딩이란, [0,0,1,0,0,0,0,0,0]처럼 정답을 뜻하는 원소만 1이고(hot) 나머지는 모두 0인 배열을 의미한다. 
false면 7이나 2와 같은 숫자 형태의 레이블을 저장하고, true일 때는 레이블을 원-핫 인코딩하여 저장한다.</li>
</ul>
<blockquote>
<p><img src="https://images.velog.io/images/u_jinju/post/ee34ecfd-b40c-4171-9fe2-d40457a50397/image.png" alt="">
파이썬에는 pickle 이라는 편리한 기능이 있다. 이는 프로그램 실행 중에 특정 객체를 파일로 저장하는 기능이다. 저장해둔 pickle파일을 로드하면 해당 당시의 객체를 즉시 복원할 수 있다. MNIST 데이터셋을 읽는 load_mnist()함수에서도 (2번째 이후의 읽기 시) pickle 이용한다. pickle 덕분에 MNIST 데이터를 순식간에 준비할 수 있다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] 항등함수와 소프트맥스 함수 구현하기]]></title>
            <link>https://velog.io/@u_jinju/DL-%ED%95%AD%EB%93%B1%ED%95%A8%EC%88%98%EC%99%80-%EC%86%8C%ED%94%84%ED%8A%B8%EB%A7%A5%EC%8A%A4-%ED%95%A8%EC%88%98-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@u_jinju/DL-%ED%95%AD%EB%93%B1%ED%95%A8%EC%88%98%EC%99%80-%EC%86%8C%ED%94%84%ED%8A%B8%EB%A7%A5%EC%8A%A4-%ED%95%A8%EC%88%98-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 25 Nov 2021 13:06:08 GMT</pubDate>
            <description><![CDATA[<h2 id="항등-함수-identity-function">항등 함수 (identity function)</h2>
<p>항등함수는 입력을 그대로 출력한다. 입력과 출력이 항상 같다는 뜻의 항등이다.</p>
<h2 id="소프트맥스-함수-softmax-function">소프트맥스 함수 (softmax function)</h2>
<p>분류에서 사용하는 소프트맥스 함수의 식은 다음과 같다.
<img src="https://images.velog.io/images/u_jinju/post/2acbbe82-2b60-4198-ba66-2b1a30deee90/image.png" alt=""></p>
<ul>
<li>exp(x): 지수함수</li>
<li>n: 출력층의 뉴런 수</li>
<li>$y_k$: 그 중 k번째 출력</li>
<li>분자는 입력신호 $a_k$의 지수함수, 분모는 모든 입력 신호의 지수 함수의 합으로 구성</li>
</ul>
<h3 id="코드-오버플로우">코드 (오버플로우)</h3>
<pre><code class="language-python">def softmax(a):
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a

    return y</code></pre>
<h3 id="구현시-주의점">구현시 주의점</h3>
<p>컴퓨터로 계산할 때 결함이 존재한다. 그 이유는 <strong>오버플로우</strong> 문제! 소프트맥스 함수는 지수 함수를 사용하는데, 지수 함수란 것이 쉽게 아주 큰 값을 내뱉기 때문에 예를 들면 $e^{20}$은 20000이 넘고, $e^{100}$은 0이 40개 넘는 큰값이 되기도 한다. 이런 큰 값끼리 나눗셈을 하는 경우에는 결과 수치가 불안정해진다. </p>
<p>따라서 이 문제를 해결한 소프트맥스 수식은 다음과 같다. </p>
<p><img src="https://images.velog.io/images/u_jinju/post/cf944335-0e81-4e9d-9335-a7e0541d2ffc/image.png" alt=""></p>
<p>첫 번째 변형에서는 C라는 임의의 정수를 분자와 분모 양쪽에 곱한다. 그다음으로 C를 지수함수 exp() 안으로 옮겨 $log^C$로 만든다. 마지막으로 $log^C$를 $C&#39;$라는 새로운 기호로 바꾼다.</p>
<blockquote>
<p><img src="https://images.velog.io/images/u_jinju/post/6e09f254-bf5f-4e61-9f57-5849beab77fe/image.png" alt="">
두번째 식에서 변환과정이 위와 같다! 지수, 로그 공식을 통해 저렇게 됨 </p>
</blockquote>
<p>위 식은 소프트맥스의 지수 함수를 계산할 때 어떤 정수를 더해도 결과는 바뀌지 않는다는 것이다. </p>
<h3 id="코드-오버플로우-방지">코드 (오버플로우 방지)</h3>
<pre><code class="language-python">def softmax(a):
    c = np.max(a) # overflow 방지를위한 변수
    exp_a = np.exp(a - c) # overflow 대책 
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a

    return y</code></pre>
<p>그냥 구하면 nan이 출력됨 </p>
<h3 id="소프트맥스-함수의-특징">소프트맥스 함수의 특징</h3>
<pre><code class="language-python">a = np.array([0.3, 2.9, 4.0])
y = softmax(a)
print(y)

print(np.sum(y))</code></pre>
<pre><code>[0.01821127 0.24519181 0.73659691]
1.0</code></pre><p><strong>소프트맥스 함수의 출력은 0에서 1.0 사이의 실수</strong>이다. 또, <strong>소프트맥스 함수 출력의 총합은 1이다</strong>. 출력 총합이 1이 된다는 점은 소프트맥스 함수의 중요한 성질이다.
이 성질로 인해 소프트맥스 함수의 출력을 &#39;확률&#39;로 해석할 수 있다.</p>
<p>위의 출력으로 y[0]의 확률은 0.018(1.8%), y[1]의 확률은 0.245(24.5%), y[2]의 확률은 0.737(73.7%)로 해석할 수 있다. 이 결과 확률들로부터 &#39;2번째 원소의 확률이 가장 높으니 답은 2번째 클래스다&#39; 라고 할 수 있다. </p>
<p><strong>소프트 맥스 함수를 적용해도 각 원소의 대소 관계를 변하지 않는다.</strong> 이 는 지수 함수 y=exp(x)가 단조 증가 함수이기 때문읻. a의 원소들 사이의 대소 관계가 y의 원소들 사이의 대소 관계로 그대로 이어진다. 예를 들어 a에서 가장 큰 원소가 2번째 원소이고, y의 가장 큰 원소도 2번째 원소라는 것. </p>
<blockquote>
<p>추론 단계에서는 출력층의 소프트맥스 함수를 생략하는 것이 일반적이지만, 신경망을 학습시킬 때는 출력층에서 소프트맥스 함수를 사용한다. </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] 3층 신경망 구현하기]]></title>
            <link>https://velog.io/@u_jinju/DL-3%EC%B8%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@u_jinju/DL-3%EC%B8%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 24 Nov 2021 12:44:16 GMT</pubDate>
            <description><![CDATA[<h2 id="표기법">표기법</h2>
<p> <img src="https://images.velog.io/images/u_jinju/post/351bb166-60f3-48ef-97f5-1d358a3e83a0/image.png" alt="">
 <img src="https://images.velog.io/images/u_jinju/post/3abc2f77-e1f4-4fdb-992c-b2b2f8551194/IMG_27C879EDE6CF-1.jpeg" alt=""></p>
<p> 위 그림에서처럼 </p>
<ul>
<li>가중치와 은닉층 뉴런의 오른쪽 위에는 (1)이 붙어있다. 
이는 1층의 가중치, 1층의 뉴런임을 뜻한다.</li>
<li>가중치의 오른쪽 아래의 두 숫자는 차례로 다음 층 뉴런과 앞 층 뉴런의 인덱스 번호이다.
$w^{(1)}_{1 \ 2}$ 의 의미는 앞층의 2번째 뉴런($x_2$)에서 다음층의 1번째 뉴런($a^{(1)}_1$)향할 때의 가중치라는 뜻이다. </li>
<li>인덱스 번호는 &#39;다음층 번호, 앞 층 번호&#39;로 순서를 적는다.<ul>
<li>그러나 간혹 다른 자료를 볼 때 순서가 다른 경우 존재! </li>
</ul>
</li>
</ul>
<h2 id="각-층의-신호-전달-구현하기">각 층의 신호 전달 구현하기</h2>
<p><img src="https://images.velog.io/images/u_jinju/post/d8d00dbb-5d94-489c-93cb-6c28f7e3ef31/IMG_EE39E15394BD-1.jpeg" alt=""></p>
<p>위 그림에서 편향(bias)를 뜻하는 뉴런인 1이 추가되었다. 편향은 오른쪽 아래 인덱스가 하나 밖에 없다! 그 이유는 앞 층의 편향 뉴런(뉴런 1)이 하나뿐이기 때문!</p>
<p>$a^{(1)}<em>1$을 수식으로 나타내면 다음과 같다.
$a^{(1)}_1 = w^{(1)}</em>{1 \ 1} + w^{(1)}_{1 \ 2} + b^{(1)}_1$
==
간소화 한다면 다음과 같다.
$A^{(1)} = XW^{(1)} + B^{(1)}$ 
==</p>
<h3 id="코드">코드</h3>
<pre><code class="language-python">import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def identity_function(x):
    return x

X = np.array([1.0, 0.5])
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B1 = np.array([0.1, 0.2, 0.3])

print(W1.shape) #2 x 3
print(X.shape)  #1 x 2
print(B1.shape) #1 x 3

A1 = np.dot(X, W1) + B1
Z1 = sigmoid(A1) # 1층 + sigmoid 
print(Z1) #1 x 3

W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]]) 
B2 = np.array([0.1, 0.2]) 

print(Z1.shape) #1 x 3
print(W2.shape) #3 x 2
print(B2.shape) #1 x 2

A2 = np.dot(Z1, W2) + B2 
Z2 = sigmoid(A2) # 2층 + sigmoid
print(Z2) # 1 x 2

W3 = np.array([[0.1, 0.3], [0.2, 0.4]])
B3 = np.array([0.1, 0.2])

print(Z2.shape) # 1 x 2
print(W3.shape) # 2 x 2
print(B3.shape) # 1 x 2

A3 = np.dot(Z2, W3) + B3
Y = identity_function(A3) # Y = A3, # 1 x 2
print(Y)</code></pre>
<h4 id="출력">출력</h4>
<pre><code>(2, 3)
(2,)
(3,)
[0.57444252 0.66818777 0.75026011]
(3,)
(3, 2)
(2,)
[0.62624937 0.7710107 ]
(2,)
(2, 2)
(2,)
[0.31682708 0.69627909]</code></pre><p>마지막에 항등 함수인 identity_function()을 정의하고, 이를 출력층의 활성화 함수로 이용을 한다. <strong>항등 함수는 입력을 그대로 출력하는 함수이다.</strong> 
여기서 굳이 항등함수를 정의할 필요는 없지만, 흐름과 통일하기 위해 구현하였다고 한다.</p>
<blockquote>
<p>출력층의 활성화 함수는 풀고자 하는 문제의 성질에 맞게 정합니다. 예를 들어 <strong>회귀에는 항등 함수, 2클래스 분류에는 시그모이드 함수, 다중 클래스 분류에는 소프트맥스 함수를 사용하는 것이 일반적</strong>입니다.</p>
</blockquote>
<h2 id="구현-정리">구현 정리</h2>
<pre><code class="language-python">import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def identity_function(x):
    return x

def init_network():
    network = {}
    network[&#39;W1&#39;] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    network[&#39;b1&#39;] = np.array([0.1, 0.2, 0.3])
    network[&#39;W2&#39;] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
    network[&#39;b2&#39;] = np.array([0.1, 0.2])
    network[&#39;W3&#39;] = np.array([[0.1, 0.3], [0.2, 0.4]])
    network[&#39;b3&#39;] = np.array([0.1, 0.2])

    return network

def forward(network, x):
    W1, W2, W3 = network[&#39;W1&#39;], network[&#39;W2&#39;], network[&#39;W3&#39;]
    b1, b2, b3 = network[&#39;b1&#39;], network[&#39;b2&#39;], network[&#39;b3&#39;]

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = identity_function(a3)

    return y

network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y) </code></pre>
<h4 id="출력-1">출력</h4>
<pre><code>[0.31682708 0.69627909]</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] 다차원 배열의 계산]]></title>
            <link>https://velog.io/@u_jinju/DL-%EB%8B%A4%EC%B0%A8%EC%9B%90-%EB%B0%B0%EC%97%B4%EC%9D%98-%EA%B3%84%EC%82%B0</link>
            <guid>https://velog.io/@u_jinju/DL-%EB%8B%A4%EC%B0%A8%EC%9B%90-%EB%B0%B0%EC%97%B4%EC%9D%98-%EA%B3%84%EC%82%B0</guid>
            <pubDate>Wed, 24 Nov 2021 11:51:06 GMT</pubDate>
            <description><![CDATA[<h2 id="다차원-배열">다차원 배열</h2>
<p>다차원 배열도 그 기본은 &#39;<strong>숫자의 집합</strong>&#39;</p>
<h3 id="1차원-배열-코드">1차원 배열 코드</h3>
<pre><code class="language-python">A = np.array([1,2,3,4,5])
print(A)
print(np.ndim(A))
print(A.shape)
print(A.shape[0])</code></pre>
<h4 id="출력">출력</h4>
<pre><code>[1 2 3 4 5]
1
(5,)
5</code></pre><h3 id="2차원-배열-코드">2차원 배열 코드</h3>
<pre><code class="language-python">B = np.array([[1,2], [2,3], [3,4]])
print(B)
print(np.ndim(B))
print(B.shape)</code></pre>
<h4 id="출력-1">출력</h4>
<pre><code>[[1 2]
 [2 3]
 [3 4]]
2
(3, 2)</code></pre><p>차원의 수는 np.ndim()함수로 알 수 있고, 배열의 ㅎ여상은 인스턴스 변수인 shape으로 알 수 있다. 
1차원 배열에서 shape이 튜플로 반환하는 것은 다차원 배열일 때와 통일된 형태로 결과를 반환하기 위한 것임을 기억!</p>
<p>2차원 배열 코드는 3x2 행렬로 가로방향을 &#39;<strong>행</strong>&#39; 세로방향을 &#39;<strong>열</strong>&#39; 이라함 </p>
<h3 id="행렬-곱">행렬 곱</h3>
<pre><code class="language-python">A = np.array([[1,2], [3,4]])
print(A.shape)
B = np.array([[5,6], [7,8]])
print(B.shape)
print(np.dot(A, B))</code></pre>
<p>numpy의 np.dot()함수를 통해 두 행렬의 곱을 할 수 있다.
np.dot()은 입력이 1차원 배열이면 벡터를, 2차원 배열이면 행렬 곱을 계산한다.
여기서 주의해야 할 점은 np.dot(A,B)와 np.dot(B,A)의 값이 다르다는 점!</p>
<p>행렬 곱을 할 때 &#39;행렬의 형상&#39;에 주의해야한다. 행렬 A의 1번째 차원의 원소 수(열수)와 행렬 B의 0번째 차원의 원소 수(행 수)가 같아야한다.
그렇지 않은 경우 오류를 출력한다.</p>
<h3 id="신경망에서의-곱">신경망에서의 곱</h3>
<pre><code class="language-python">X = np.array([1, 2])
print(X.shape)
W = np.array([[1,3,5], [2,4,6]])
print(W.shape)
Y = np.dot(X, W)
print(Y)</code></pre>
<p>X와 W의 형상이 같아 행렬 곱셈 연산 후 Y를 통해 결과값을 얻었다.
np.dot()함수를 사용면 이처럼 단번에 결과(Y)를 얻을 수 있지만, 이를 사용하지 않고, Y의 원소가 100이든 1000이라면 그 수만큼 하나씩 계산을 하게된다.(for문 사용해서 한 원소씩 돌아가며 계산..)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] ReLU 함수]]></title>
            <link>https://velog.io/@u_jinju/DL-ReLU-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@u_jinju/DL-ReLU-%ED%95%A8%EC%88%98</guid>
            <pubDate>Wed, 24 Nov 2021 11:17:09 GMT</pubDate>
            <description><![CDATA[<h2 id="relu-function">ReLU function</h2>
<p>ReLU는 최근에 주로 사용하게 된 활성함수의 하나!
입력이 0이 넘으면 그 입력을 그대로 출력하고, 0이하면 0을 출력하는 함수이다.
(sigmoid는 신경망 분야에서 오래전부터 이용했던 함수)</p>
<p>수식은 다음과 같이 나타낼 수 있다.</p>
<h3 id="수식">수식</h3>
<p>$h(x) = \begin{cases} x &amp; (x &gt; 0) \ 0  &amp; (x \le 0) \end{cases}$</p>
<h3 id="구현">구현</h3>
<pre><code class="language-python">def relu(x):
    return np.maximum(0, x)</code></pre>
<p>numpy의 maximum을 사용해서 두 입력 중 큰 값을 선택해 반환하는 함수이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] sigmoid vs step function]]></title>
            <link>https://velog.io/@u_jinju/DL-sigmoid-vs-step-function</link>
            <guid>https://velog.io/@u_jinju/DL-sigmoid-vs-step-function</guid>
            <pubDate>Tue, 23 Nov 2021 13:13:31 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이전 내용 참고
<a href="https://velog.io/@u_jinju/DL-%ED%99%9C%EC%84%B1%ED%95%A8%EC%88%98">https://velog.io/@u_jinju/DL-활성함수</a></p>
</blockquote>
<p>앞선에 작성했던 sigmoid와 step function 의 차이를 알아보려한다.</p>
<h2 id="매끄러움">매끄러움</h2>
<p>제일 큰 것은 &#39;매끄러움&#39;의 차이.
sigmoid는 곡선을 띄는 방면, step function은 각이져있다.
따라서 sigmoid는 0.731, 0.808 .. 등의 실수가 나온반면 계단함수는 0 또는 1이다. 
그러나, 신경망에서는 sigmoid와 같은 연속적인 실수를 다룬다</p>
<p>그렇다면, 공통점은 무엇일까?</p>
<h2 id="큰-관점에서-보면-둘은-같은-모양">큰 관점에서 보면 둘은 같은 모양</h2>
<p>둘 다 입력이 작을 때의 출력은 0에 가깝고(혹은 0), 입력이 커지면 출력이 1에 가까워지는(혹은 1) 구조인 것.
step, sigmoid는 입력이 중요하면 큰 값을 출력하고 중요하지 않으면 작은 값을 출력한다.</p>
<h2 id="비선형-구조">비선형 구조</h2>
<p>계단함수와 sigmoid함수의 가장 큰 공통점은 <strong>비선형 구조</strong>라는 것
비선형 구조는 1개의 직선이 되지 않는 즉 선형이 아닌 함수</p>
<p>신경망에서는 비선형 구조를 사용해야하는데 그 이유는 선형구조를 사용하면 층을 깊게하는 의미가 없어지기 때문이다. </p>
<p>선형함수인 h(x) = cx를 활성함수로 3층 네트워크를 만들게되면, y(x) = h(h(h(x)))가 되고 y(x) = c * c * c * x처럼 곱셈을 세번 수행하지만, 실은 y(x) = ax (a = $c^3$)과 같은 의미이기 때문이다.
따라서 은닉층이 없는 네트워크로 표현할 수 있기 때문에 비선형함수를 사용해야한다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] 활성함수(Activation Function)]]></title>
            <link>https://velog.io/@u_jinju/DL-%ED%99%9C%EC%84%B1%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@u_jinju/DL-%ED%99%9C%EC%84%B1%ED%95%A8%EC%88%98</guid>
            <pubDate>Tue, 23 Nov 2021 13:06:58 GMT</pubDate>
            <description><![CDATA[<h2 id="활성화-함수">활성화 함수</h2>
<p>입력 신호의 총합을 출력 신호로 변환하는 함수
즉, 이름 그대로 활성화 함수는 입력 신호의 총합이 활성화를 일으키는지를 정하는 역할을 한다.</p>
<h3 id="sigmoid-함수">sigmoid 함수</h3>
<p>$h(x) = \frac{1}{1+e^{-x}}$</p>
<p>위 식은 sigmoid를 식으로 나타낸 식이다.</p>
<p>$h(x) = \begin{cases} 0 &amp; \text{if x} \le 0 \ 1 &amp; \text{if x &gt; 0}\end{cases}$</p>
<p>위와 같이 x가 0일때 0, x가 0보다 클 때 1로 반환되는 함수이다.</p>
<h3 id="계단함수-그래프-그려보기">계단함수 그래프 그려보기</h3>
<p>책에서 나와있는 sigmoid 함수를 numpy와 matplot을 사용하여 그린 코드는 다음과 같다</p>
<pre><code class="language-python">import numpy as np
import matplotlib.pylab as plt

def step_function(x):
    return np.array(x &gt; 0, dtype=np.int)

x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()</code></pre>
<p>여기서 arange(-5.0, 5.0, 0.1)은 -5.0에서 5.0까지 0.1씩 x 좌표값의 배열을 만드는 것을 의미한다. 따라서, [-5.0, -4.9, ..., 4.9] 의 배열이 만들어진다.</p>
<p>step_function을 통해서 x의 값들이 계산 후에 다시 배열로 만들어 돌려준다.
결과는 다음과 같다.</p>
<h3 id="결과">결과</h3>
<p><img src="https://images.velog.io/images/u_jinju/post/5e4b787e-7cb1-4fc6-8698-34f3592a2c10/image.png" alt=""></p>
<h3 id="sigmoid-함수-구현">sigmoid 함수 구현</h3>
<pre><code class="language-python">import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

x = np.array([-1.0, 1.0, 2.0])
print(sigmoid(x))</code></pre>
<h3 id="결과-1">결과</h3>
<pre><code>[0.26894142 0.73105858 0.88079708]</code></pre><p>여기서 계산이 잘 된 이유는 Numpy의 &#39;broadcast&#39;때문! 
numpy와 scalar의 계산을 할 수 있었던 것은 numpy 배열의 원소 각각이 스칼라값의 연산으로 바꿔 수행했다.</p>
<p>예를들면, </p>
<pre><code class="language-python">t = np.array([1.0, 2.0, 3.0])
print(1.0 + t)
print(1.0 / t)


[2. 3. 4.]
[1.         0.5        0.33333333]</code></pre>
<p>위에서 numpy 배열로 되어 있는 float 각 원소들이 scalar값인 1.0과 +와 /로 각각 연산되어 numpy 배열의 형태로 계산후 출력이 이루어졌다. 
이와 같은 것을 <strong>브로드캐스트</strong> 라고 한다! </p>
<p>따라서 sigmoid의 </p>
<pre><code class="language-python">1/(1 + np.exp(-x))</code></pre>
<p>에서도 넘파이 배열의 각 원소에 연산을 수행한 결과이다.</p>
<h3 id="sigmoid-함수-그래프-그리기">sigmoid 함수 그래프 그리기</h3>
<pre><code class="language-python">import numpy as np
import matplotlib.pylab as plt

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()</code></pre>
<h3 id="결과-2">결과</h3>
<p><img src="https://images.velog.io/images/u_jinju/post/51870db0-a44e-4a59-a919-933a5ddb1723/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[python] numpy 함수 astype() ]]></title>
            <link>https://velog.io/@u_jinju/python-numpy-%ED%95%A8%EC%88%98-astype</link>
            <guid>https://velog.io/@u_jinju/python-numpy-%ED%95%A8%EC%88%98-astype</guid>
            <pubDate>Tue, 23 Nov 2021 12:47:34 GMT</pubDate>
            <description><![CDATA[<h2 id="astype-함수">astype() 함수</h2>
<p>numpy배열의 자료형을 변환해주는 함수</p>
<h3 id="예시">예시</h3>
<pre><code class="language-python">y1 = np.array([-1.0, 2.0, 3.0])
y2 = y1.astype(np.int)

print(y1)
print(y2)</code></pre>
<h3 id="출력">출력</h3>
<pre><code class="language-bash">[-1.  2.  3.]
[-1  2  3]</code></pre>
<p><img src="https://images.velog.io/images/u_jinju/post/cb3b45e8-5b96-4a7d-a62f-5b1f6cbeaf37/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] 퍼셉트론 간단 정리]]></title>
            <link>https://velog.io/@u_jinju/DL-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0-%EA%B0%84%EB%8B%A8-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@u_jinju/DL-%ED%8D%BC%EC%85%89%ED%8A%B8%EB%A1%A0-%EA%B0%84%EB%8B%A8-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 23 Nov 2021 11:59:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>chaper 2까지의 정리 (p.62)</p>
</blockquote>
<h2 id="정리">정리</h2>
<ul>
<li>퍼셉트론은 입출력을 갖춘 알고리즘이다. 입력을 주면 정해진 규칙에 따른 값을 출력한다.</li>
<li>퍼셉트론에서는 &#39;가중치&#39;와 &#39;편향&#39;을 매개변수로 설정한다.</li>
<li>퍼셉트론으로 AND, OR 게이트 등의 논리 회로를 표현할 수 있다.</li>
<li>XOR 게이트는 단층 퍼셉트론으로는 표현할 수 없다.</li>
<li>2층 퍼셉트론을 이용하면 XOR 게이트를 표현할 수 있다.</li>
<li>단층 퍼센트론은 직선형 영역만 표현할 수 있고, 다층 퍼센트론은 비선형 영역도 표현할 수 있다. </li>
<li>다층 퍼센트론은 (이론상) 컴퓨터를 표현할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] AND / NAND / OR 가중치 편향 구현]]></title>
            <link>https://velog.io/@u_jinju/DL-AND-NAND-OR-%EA%B0%80%EC%A4%91%EC%B9%98-%ED%8E%B8%ED%96%A5-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@u_jinju/DL-AND-NAND-OR-%EA%B0%80%EC%A4%91%EC%B9%98-%ED%8E%B8%ED%96%A5-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Sat, 30 Oct 2021 05:23:29 GMT</pubDate>
            <description><![CDATA[<h2 id="작성계기">작성계기</h2>
<p>밑바닥부터 시작하는 딥러닝1 책을 공부하면서 (개인 책이 아니기 때문에) 메모할 내용들을 여기에 적기위해서 작성 
내용은 퍼셉트론(2장) 부분을 공부 중에 있음</p>
<h2 id="가중치와-편향">가중치와 편향</h2>
<h3 id="가중치-weight">가중치 (weight)</h3>
<p>w1, w2라고 하는 가중치는 각 입력 신호가 결과에 주는 영향력(중요도)을 조절하는 매개변수</p>
<h3 id="편향bias">편향(bias)</h3>
<p>뉴런이 얼마나 쉽게 활성화하느냐를 조정하는 매개변수</p>
<h2 id="and-게이트">AND 게이트</h2>
<pre><code class="language-python">def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.7
    tmp = np.sum(w*x) + b
    if tmp &lt;= 0:
        return 0
    else:
        return 1

print(AND(0, 0))
print(AND(0, 1))
print(AND(1, 0))
print(AND(1, 1))</code></pre>
<h2 id="nand-게이트">NAND 게이트</h2>
<pre><code class="language-python">def NAND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([-0.5, -0.5])
    b = 0.7
    tmp = np.sum(w*x) + b
    if tmp &lt;= 0:
        return 0
    else:
        return 1

print(NAND(0, 0))
print(NAND(0, 1))
print(NAND(1, 0))
print(NAND(1, 1))</code></pre>
<h2 id="or-게이트">OR 게이트</h2>
<pre><code class="language-python">def OR(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.2
    tmp = np.sum(w*x) + b
    if tmp &lt;= 0:
        return 0
    else:
        return 1

print(OR(0, 0))
print(OR(0, 1))
print(OR(1, 0))
print(OR(1, 1))</code></pre>
<h2 id="퍼셉트론-한계">퍼셉트론 한계</h2>
<h3 id="xor-게이트">XOR 게이트</h3>
<p><img src="https://images.velog.io/images/u_jinju/post/c4ad8383-6356-4336-b960-5b87ce1c937d/image.png" alt="">
XOR은 위 그래프처럼 x1과 x2 중 하나가 1일 때만 1을 출력하는데 이것을 퍼센트론으로 나타내는 것은 불가능하다. </p>
<p><img src="https://images.velog.io/images/u_jinju/post/a141bebf-1e8e-4faf-b0c7-f6e3ec5e730e/image.png" alt="">
위 그림은 OR 게이트를 시각화 해낸 그림이다. 
초록색으로 색칠된 삼각형은 출력이 1일 때, 노란색 원형은 0을 출력할 때인데 이것을 빨간색 선과 같이 <strong>선형적</strong>으로 영역을 나눌 수 있다. </p>
<p>반면 XOR은,
<img src="https://images.velog.io/images/u_jinju/post/5ef6ac7f-7b41-4efe-b1ac-d88047087b94/image.png" alt="">
똑같이 초록색으로 색칠된 삼각형은 출력 1을 의미하고, 노란색 원형은 0을 출력할 때인데 직선으로 나누는 것은 불가능하고 빨간색 점선으로 <strong>비선형</strong> 형태로 나눌 수가 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] flatten() 함수]]></title>
            <link>https://velog.io/@u_jinju/Python-flatten-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@u_jinju/Python-flatten-%ED%95%A8%EC%88%98</guid>
            <pubDate>Sat, 30 Oct 2021 02:37:53 GMT</pubDate>
            <description><![CDATA[<h2 id="flatten-함수">flatten() 함수</h2>
<p>flatten은 numpy에서 제공하는 다차원 배열 공간을 1차원으로 <strong>평탄화</strong>해주는 함수이다.</p>
<h3 id="예시">예시</h3>
<pre><code class="language-python">X = np.array([[51, 55], [14, 19], [0, 4]])
X = X.flatten() # 1차원 배열로 변환 (평탄화)
print(X)</code></pre>
<h3 id="결과">결과</h3>
<pre><code class="language-bash">[51 55 14 19 0 4]</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] rstrip() / lstrip() / strip() 함수]]></title>
            <link>https://velog.io/@u_jinju/Python-rstrip-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@u_jinju/Python-rstrip-%ED%95%A8%EC%88%98</guid>
            <pubDate>Thu, 28 Oct 2021 09:36:03 GMT</pubDate>
            <description><![CDATA[<h2 id="rstrip-함수">rstrip() 함수</h2>
<p>지정된 문자열의 끝을 삭제하는 함수이다. 
default는 공백이다. </p>
<h3 id="예시">예시</h3>
<pre><code class="language-python">str1 = &quot;Hi, Nice to meet you.   &quot;
print(str1.rstrip())

str2 = &quot;  Hi, Nice to meet you.asdf&quot;
print(str2.rstrip(asdf))</code></pre>
<h3 id="출력">출력</h3>
<pre><code class="language-bash">Hi, Nice to meet you. # 오른쪽 space 칸들 사라짐
  Hi, Nice to meet you. #오른쪽 &quot;asdf&quot; 문자</code></pre>
<h2 id="lstrip-함수">lstrip() 함수</h2>
<p>지정된 문자열의 왼쪽을 삭제하는 함수이다.
dafault는 공백이다. </p>
<h3 id="예시-1">예시</h3>
<pre><code class="language-python">str1 = &quot;   hello&quot;
print(str1.lstrip())

str1 = &quot;asdfhello&quot;
print(str1.lstrip(asdf))</code></pre>
<h3 id="출력-1">출력</h3>
<pre><code class="language-bash">hello #왼쪽 공백 지워짐
hello #왼쪽 asdf 지워짐
</code></pre>
<h2 id="strip-함수">strip() 함수</h2>
<p>지정된 문자열의 왼쪽끝과 오른쪽 끝을 삭제하는 함수
default는 공백이다.</p>
<h3 id="예시-2">예시</h3>
<pre><code class="language-python">str1 = &quot;   hello   &quot;
print(str1)</code></pre>
<h3 id="출력-2">출력</h3>
<pre><code class="language-bash">hello</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CV] Scale-Invariant Feature Transform (SIFT)]]></title>
            <link>https://velog.io/@u_jinju/CV-Scale-Invariant-Feature-Transform-SIFT</link>
            <guid>https://velog.io/@u_jinju/CV-Scale-Invariant-Feature-Transform-SIFT</guid>
            <pubDate>Wed, 18 Aug 2021 13:16:36 GMT</pubDate>
            <description><![CDATA[<h2 id="들어가면서">들어가면서</h2>
<p>Edge, corner, blob을 배우면서 corner를 detection 할 수 있는 알고리즘 중 Harris corner detection을 배웠었다. Harris corner detection의 경우 rotation invarian(불변) 즉 한 이미지를 오른쪽으로 회전해서 corner를 detection했을 경우에도 corner를 인식할 수 있었지만 scale을 작게 했을 경우에는 corner라고 검출이 안되기 때문이다. </p>
<h2 id="sift-알고리즘-순서도">SIFT 알고리즘 순서도</h2>
<p><img src="https://images.velog.io/images/u_jinju/post/840d8daa-48a8-4ea5-99bf-9d5c83c805c9/image.png" alt=""></p>
<p>SIFT 알고리즘 순서도는 위 그림과 같다. 
위 순서에 따라 알고리즘을 설명을 해보겠다!</p>
<h2 id="sift-알고리즘">SIFT 알고리즘</h2>
<h3 id="1-scale-space-extrema-detection">1. Scale-space extrema detection</h3>
<p>이 과정은 scale과 orientation(회전) 에 invarient(불변) 할 거라 추측되는 Interest point들을 검출하는 과정이다. </p>
<p>지난 포스팅에 적은 Laplacian of Gaussian(LoG)와 같은 개념으로 나오는 Difference of Gaussian(DoG)을 사용하여 검출을 한다. </p>
<blockquote>
<p>Difference of Gaussian (DoG)
말 그대로 가우시안의 차이를 계산한다. 서로 다른 $\sigma$를 가지는 가우시안 커널의 차를 이용한다. 그렇다면 가우시안 커널의 차는 무엇일까? 가우시안 커널의 차는 LoG의 근사값을 의미한다. </p>
</blockquote>
<p><img src="https://images.velog.io/images/u_jinju/post/36f3d2ca-0c82-4cbd-bdcf-27dcb37c7e54/image.png" alt=""></p>
<p>위 그림과 같이, Scale에 불변하기 위해서 $\sigma$값을 다르게 해서 각 이미지에 대해서 가우시안 피라미드를 생성한 후에 DoG를 구한다. 
DoG를 구한 것을 토대로 극점인 부분들은 feature point의 후보자로 잡아준다. 
DoG의 상위와 하위 층까지 모두 합쳐서 주변 26개보다 크거나 모두 작을 때만 특징점 후보자로 검출을 한다. 
이 때, 특징점을 Scale별로 구하게 되기 때문에 target 물체가 작아져도 인식할 수 있는 장점이 있음</p>
<h3 id="2-keypoint-localization">2. Keypoint Localization</h3>
<p>테일러 급수를 사용해서 더 정확한 extrema(극점)을 찾는다. 
찾은 후에 테일러 급수를 사용해서 interpolation 방법을 통해 해당 점의 값을 구하고 feature point의 후보자 중에서 정확하지 않는 feature point를 제거한다.</p>
<h3 id="3-orientation-assignment">3. Orientation Assignment</h3>
<p><img src="https://images.velog.io/images/u_jinju/post/b97b21c6-792b-4652-b023-6273f0a723bf/image.png" alt=""></p>
<p>주요한 방향을 할당해주는 단계이다. 
특징점 주변으로 16x16 영역 할당한 후에 가우시안 블러링 적용하면 특징점 주변의 영역에 대한 gradient의 방향 크기가 결정된다.
이를 구하면 orientation histogram을 형성하고 이 중에 가장 값이 큰 것을 해당 orientation으로 결정한다. 
이 때, 물체가 회전해도 orientation 정보가 있기 때문에 인식할 수 있다는 장점이 존재한다. </p>
<h3 id="4-keypoint-descriptor">4. Keypoint Descriptor</h3>
<p><img src="https://images.velog.io/images/u_jinju/post/77fe7d63-5d24-40ce-a0ee-3763c8aa8b57/image.png" alt="">
각 특징점 마다 descriptor를 생성해주는 단계이다. 
Gaussian weight function을 활용해서 생성해주고, 16x16 pixel의 영역을 할당하여 image gradients를 구하고 window 크기의 1/2의 값을 gaussian weighted function에 곱해준다. </p>
<p>+추가적으로)
histogram을 그려줄 때는 orientation 값을 뺀 다음에 descriptor가 회전에 불변하도록 만들어준다. 
객체 인식할 때 DB의 각 특징점의 descriptor를 가지고 인식할 물체 영상의 descriptor와 비교를 하게 된다. 
비슷하면 데이터가 비슷하게 나오고 이 거리는 유클리드 거리 계산식을 사용한다. </p>
<p>$$\theta(x, y) = tan^{-1}(\frac{G(x+1, y)-G(x-1, y)}{G(x, y+1)-G(x, y-1)})$$</p>
<h2 id="출처">출처</h2>
<p>SIFT 알고리즘 순서도 image: <a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=laonple&amp;logNo=220879911249">https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=laonple&amp;logNo=220879911249</a>
SIFT: <a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=laonple&amp;logNo=220879911249">https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=laonple&amp;logNo=220879911249</a>
<a href="https://hello-stella.tistory.com/21">https://hello-stella.tistory.com/21</a>
DoG: <a href="https://sunshower76.github.io/cv(computervision)/2020/03/23/Laplacian-of-Gaussian(LoG)-&amp;-Difference-of-Gaussian(DoG)/">https://sunshower76.github.io/cv(computervision)/2020/03/23/Laplacian-of-Gaussian(LoG)-&amp;-Difference-of-Gaussian(DoG)/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CV] Blob Detection]]></title>
            <link>https://velog.io/@u_jinju/CV-Blob-Detection</link>
            <guid>https://velog.io/@u_jinju/CV-Blob-Detection</guid>
            <pubDate>Wed, 18 Aug 2021 12:10:54 GMT</pubDate>
            <description><![CDATA[<h2 id="blob이란">Blob이란?</h2>
<p>Blob은 이미지 내에서 주변보다 더 밝거나 어두운 영역을 의미한다.</p>
<p>지난 포스팅에 이어서 corner detection을 하기 위해서는 Harris Corner Detection을 사용하여 corner를 검출하였고, 이번엔 Blob을 어떻게 검출할 수 있는지 알아보겠다. </p>
<h2 id="blob-detection">Blob Detection</h2>
<p>Blob을 검출하기 위해서는 Image 내에서 Significant한 변화를 특정 구간에서 찾을 수 있는 방법이 필요하다. </p>
<p>Edge를 검출할 때 Gaussian을 미분하였는데, Blob을 검출할 때는 Gaussian을 미분한 미분 값인 Laplacian Gaussian 방법을 사용한다. </p>
<p>즉, Edge는 밝기의 gradient(변화)를 구하고 Blob은 밝기 Gradient의 Gradient을 구하는 것! 그렇다면 밝기 변화의 변화를 구하는 것이다. </p>
<p><img src="https://images.velog.io/images/u_jinju/post/7b6cebd7-c153-4fbc-b2ba-e0b1df0c4e2b/image.png" alt=""></p>
<p>위의 그림과 같이 그래프화하면 위 그림과 같이 볼록한 모양을 볼 수 있다. 그래프에서 볼록 튀어나온 부분이 blob의 영역이다. </p>
<p>Laplacian Gaussian의 식은 다음과 같다. </p>
<p>$$\triangledown^2 G = \frac{\partial^2 G}{\partial x^2} + \frac{\partial^2 G}{\partial y^2}$$</p>
<p>$$G(x, y, \sigma) = \frac{1}{2\pi\sigma^2} exp(-\frac{x^2+y^2}{2\sigma^2})$$</p>
<p>$$\triangledown^2G(x, y, \sigma) = \frac{(x^2+y^-2\sigma^2)}{\sigma^4}G(x, y, \sigma)$$</p>
<p>Laplacian의 문제는 분모가 4승이기 때문에 $\sigma$ 가 커질수록 값이 매우작아진다. 그렇기 때문에 scale normalize를 하고 그 식은 다음과 같다.</p>
<p>$$\triangledown_{norm}G = \sigma^2 \triangledown^2G$$</p>
<p>기존 Laplacian of Gaussian 식에 $\sigma$를 곱하여 다양한 크기의 blob을 detection할 수 있다. </p>
<p>그러나, Laplacian of Gaussian의 방법은 계산량이 많기 때문에 이 문제를 해결한 Scale-Invariant Feature Transform (SIFT)를 다음 포스팅에 다루어 보겠다. </p>
<h2 id="출처">출처</h2>
<p>blob image:<a href="https://laurent-duval.blogspot.com/2014/09/cours-radial-basis-functions.html">https://laurent-duval.blogspot.com/2014/09/cours-radial-basis-functions.html</a>
blob detection: <a href="https://wewinserv.tistory.com/85">https://wewinserv.tistory.com/85</a>
Multiple View Geometry in Computer vision (second edit)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CV] Harris Corner Detector]]></title>
            <link>https://velog.io/@u_jinju/CV-Harris-Corner-Detector</link>
            <guid>https://velog.io/@u_jinju/CV-Harris-Corner-Detector</guid>
            <pubDate>Mon, 16 Aug 2021 07:20:22 GMT</pubDate>
            <description><![CDATA[<h2 id="harris-corner-detector">Harris Corner Detector</h2>
<p>Harris의 corner detector의 기본원리는 다음과 같다. 
<img src="https://images.velog.io/images/u_jinju/post/8754e50f-089f-458f-a222-19363fe67ce1/image.png" alt="[1] 기본 원리"></p>
<p>위 그림 처럼 한 pixel을 중심에 놓고 작은 윈도우(window)를 설정한다. </p>
<p>$$E(u, v) = \sigma_{x_k, y_k \in W} \begin{bmatrix}I(x_k + u, y_k + v) - I(x_k, y_k)\end{bmatrix}^2$$</p>
<p>그런 다음 이 윈도우를 위 식과 같이 x축 방향으로 u만큼, y축 방향으로 v만큼 이동하고 윈도우 내의 픽셀 값들의 차이의 제곱의 합을 구한다. 이 식이 얼마나 픽셀이 이동했는지를 계산해주는 것</p>
<p>만약 corner라면, x, y축 방향 모두 많이 변화하여 E의 값이 커서 corner라고 인식</p>
<p>$$E(u, v) \approx \sum{(x_k, y_k) \in W} (\frac{\partial I}{\partial x}u)^2 + (\frac{\partial I}{\partial y}v)^2 + 2\frac{\partial I}{\partial x}\frac{\partial I}{\partial y}uv$$</p>
<p>테일러 공식으로 식을 이와 같이 확장할 수 있고 정리하면 
$$E(u, v) = \begin{bmatrix}u \quad v \end{bmatrix} \begin{bmatrix} \sum \frac{\partial I}{\partial x}^2 \quad \sum \frac{\partial I}{\partial x}\frac{\partial I}{\partial y} \ \sum \frac{\partial I}{\partial x}\frac{\partial I}{\partial y} \quad \sum \frac{\partial I}{\partial y}^2\end{bmatrix} \begin{bmatrix} u \ v \end{bmatrix}$$
와 같이 됨 </p>
<p>2x2 행렬을 M이라 부르고, eigen-decomposition을 하면 2개의 eigen value와 vector를 얻을 수 있는데 두 개의 eigen value 중에 더 큰 eigen value값과 연결된 eigen vector로 이미지의 변화가 가장 큼</p>
<p><img src="https://images.velog.io/images/u_jinju/post/4fe4221d-7c34-4e72-a480-7a729b1aadf9/image.png" alt=""></p>
<p>만약 두 방향으로 변화가 크면 corner 하나의 eigen value가 작고 또다른 value가 크다면 edge, 둘 다 0에 가까우면 flat으로 둠
2D 이미지의 경우에는 x, y값이 있기 때문에 2x2 matrix 나옴 그리고 rank가 2이기 때문에 eigen value 2개 밖에 나오지 않는다. (3D면 3개)</p>
<p>추가로, eigen value와 vector로 R을 사용해서 하는 방식도 있다.
<img src="https://images.velog.io/images/u_jinju/post/3f480adb-6ccd-4f1e-93c6-839588643671/image.png" alt=""></p>
<p>식을 통해서 eigen decompostion을 통해서 두 eigen value와 vector가 나왔을 때, 
두 eigen value의 곱과 두 eigen value의 합을 제곱하고 알파를 곱한 값을 뺀 값 R이 0에 가까우면f lat 0보다 작으면 edge 0보다 크면 corner로 인식한다.</p>
<h2 id="출처">출처</h2>
<p>[1] <a href="https://bskyvision.com/668">https://bskyvision.com/668</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CV] Edges and Corners]]></title>
            <link>https://velog.io/@u_jinju/CV-Edges-and-Corners</link>
            <guid>https://velog.io/@u_jinju/CV-Edges-and-Corners</guid>
            <pubDate>Thu, 12 Aug 2021 07:31:04 GMT</pubDate>
            <description><![CDATA[<h2 id="good-visual-feature의-조건은-무엇일까">Good visual feature의 조건은 무엇일까?</h2>
<ol>
<li>Repeatability
같은 이미지에 같은 사람이 다른 행동을 취하여도 같은 사람이라고 인식을 할 수 있어야 한다.</li>
<li>Saliency
원하는 위치에 feature가 존재해야한다.</li>
<li>Locality
이미지에서 작은 영역이여야 한다.
(모든 영역을 다 feature라고 할 수 없기 때문에)</li>
</ol>
<h3 id="aperture-problem">Aperture problem</h3>
<p>이미지에서의 영역이 일정한 값을 가지고 있으면 움직임이 있더라도 별다른 정보를 얻을 수 없는 문제를 뜻한다.
ex. openCV 함수 중 optical flow()함수가 있는데 이 함수는 object의 움직임을 tracking 하는 함수로 많이 사용됨 이와 같이 현재 frame과 다음 frame의 pixel값으로 비교하여 문제를 해결하는 경우 일정한 값을 가지고 경우에는 정보를 얻을 수 없다는 것!</p>
<h2 id="feature-detection">Feature Detection</h2>
<p>이미지 내에서 intersting 한 part를 찾는 것을 의미 </p>
<p>그렇다면 Interest Point dectection은 무엇일까?</p>
<ol>
<li>이미지 영역 내에서 잘 정의된 position이여야 한다.</li>
<li>rech information contents를 가지고 있어야 한다.</li>
<li>이미지 내에서 consistent 해야하고 제어가능 해야한다.</li>
<li>scale이 기준이 되어야 한다.</li>
</ol>
<h3 id="intereset-points-의-예시들">intereset points 의 예시들</h3>
<ul>
<li>edges</li>
<li>corners</li>
<li>blobs</li>
<li>etc
<img src="https://images.velog.io/images/u_jinju/post/22bda676-d887-4d9b-a0fe-4c73c1a653fa/image.png" alt=""></li>
</ul>
<h2 id="edge-란-무엇일까">Edge 란 무엇일까?</h2>
<p><img src="https://images.velog.io/images/u_jinju/post/e2707934-c25f-4dcc-896b-e717d6af8a1b/image.png" alt=""></p>
<p>위 그림과 같이 한 방향에서 변화가 급격한 점을 말한다. 
image는 pixel로 이루어져있는데 pixel의 값이 갑자기 확 커지거나 작아지는 구간을 의미</p>
<h3 id="magnitude-of-gradient">magnitude of gradient</h3>
<p>gradient는 기울기, 증감, 변화도, 즉, 변화하는 정도를 나타낸다.</p>
<p>$$\triangledown I =\begin{bmatrix}g_x\g_y\end{bmatrix}\begin{bmatrix}\frac{\partial I}{\partial x}\ \frac{\partial I}{\partial y}\end{bmatrix}$$</p>
<p>gradient의 계산 수식은 위와 같음</p>
<p>$g_x$는 수평방향의 변화를 의미하고, $g_y$는 수직방향으로 변화를 나타냄 
$(x, y)$ 에서 수평방향, 수직방향으로 얼마나 변화했는지는 나타냄 </p>
<p>$M(x, y) = \sqrt{g_x^2+g_y^2}$   : gradient magnitude</p>
<p>$\alpha(x, y)=tan^{-1}$$\begin{bmatrix}\frac{g_y}{g_x}\end{bmatrix}$ :gradient 방향</p>
<h2 id="corner란-무엇일까">Corner란 무엇일까?</h2>
<p><img src="https://images.velog.io/images/u_jinju/post/57996bd0-4575-44d0-97eb-b13badc921d7/image.png" alt="">
코너는 두 edge의 intersection 이라 하며, 두 방향 이상에서 변화가 급격한 점을 말한다. </p>
<h2 id="출처">출처</h2>
<p>edge img: <a href="https://sss20-02.tistory.com/29">https://sss20-02.tistory.com/29</a>
corner img: <a href="https://bskyvision.com/668">https://bskyvision.com/668</a></p>
]]></description>
        </item>
    </channel>
</rss>