<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Data-Science</title>
        <link>https://velog.io/</link>
        <description>Hi. Hello World.</description>
        <lastBuildDate>Thu, 07 Oct 2021 04:57:15 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Data-Science</title>
            <url>https://images.velog.io/images/robert-lee/profile/d5f2bf6a-5549-42a2-a02b-d7beb4691d02/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Data-Science. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/robert-lee" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Tensorflow Keras] Multi-Class Classification 을 구현해보자.]]></title>
            <link>https://velog.io/@robert-lee/Tensorflow-Keras-Multi-Class-Classification-%EC%9D%84-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@robert-lee/Tensorflow-Keras-Multi-Class-Classification-%EC%9D%84-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Thu, 07 Oct 2021 04:57:15 GMT</pubDate>
            <description><![CDATA[<h3 id="🔊-내용">🔊 내용</h3>
<p>우리는 캐글 동물 데이터를 바탕으로 <strong>Multi-Class Classification</strong> 를 실습한다.</p>
<p>모델 구현을 위해 <strong>다섯 단계를 진행한다.</strong></p>
<blockquote>
<p>🌑 데이터셋 다운로드
🌓 이미지와 레이블 불러오기
🌕 전처리와 데이터 분할
🌗 모델 생성과 학습
🌑 신규 이미지 예측</p>
</blockquote>
<br>

<h3 id="💾-데이터셋">💾 데이터셋</h3>
<ul>
<li><p><strong>animal image dataset</strong> <a href="https://www.kaggle.com/ashishsaxena2209/animal-image-datasetdog-cat-and-panda">&lt;링크&gt;</a></p>
<ul>
<li><code>panda</code></li>
<li><code>cat</code></li>
<li><code>dog</code></li>
</ul>
</li>
</ul>
<br>

<h3 id="🥕-환경">🥕 환경</h3>
<ul>
<li><code>python 3.7</code></li>
<li><code>tensorflow 2.6</code></li>
<li><code>keras 2.6</code></li>
<li><code>colab</code></li>
</ul>
<br>

<h3 id="📁-프로젝트">📁 프로젝트</h3>
<pre><code>├── animals
│   ├── panda [1,000 entries]
│   ├── dogs  [1,000 entries]
│   └── cats  [1,000 entries]
├── images
│   ├── panda.jpg
│   ├── dog.jpg
│   └── cat.jpg
└── model.ipynb</code></pre><br>

<h3 id="🌑-데이터셋-다운로드">🌑 데이터셋 다운로드</h3>
<p><a href="https://www.kaggle.com/ashishsaxena2209/animal-image-datasetdog-cat-and-panda">링크</a>를 통해 동물 이미지 데이터셋을 다운받는다.</p>
<p>압축을 풀어주면 <strong><code>animals/</code></strong> 그리고 <strong><code>images/</code></strong> 폴더를 볼 수 있다.</p>
<ul>
<li><strong><code>animals/</code></strong> 폴더는 훈련 데이터셋 <strong><code>images/</code></strong> 는 테스트셋을 의미한다.</li>
</ul>
<br>

<p>또한 우리의 목적은 <strong>&lt;panda, dogs, cats&gt;</strong> 중 하나의 클래스로 예측하는 것이며</p>
<p>각각의 이미지에 대한 클래스는 상위 폴더 이름이 될 것이다.</p>
<br>

<p>마지막으로 <strong>📁 프로젝트</strong>를 참고하여 디렉토리를 구성하자.</p>
<blockquote>
<p>❝ 이제 소스를 작성할 준비가 끝났다. ❞</p>
</blockquote>
<br>

<p><strong><code>model.ipynb</code></strong> 에 차근히 코딩을 해보자. </p>
<br>

<h3 id="🌓-이미지와-레이블-불러오기">🌓 이미지와 레이블 불러오기</h3>
<p>먼저 <strong><code>animals/</code></strong> 디렉토리 내 전체 이미지 개수를 확인해보자.</p>
<blockquote>
<p>❝ 여러가지 방법이 있겠지만 손쉬운 방법이 있다. ❞</p>
</blockquote>
<p><strong><code>imutils.paths.list_images()</code></strong> 사용하면 된다.</p>
<p>이미지 <strong><code>3,000 장</code></strong> 존재하면 성공이다.</p>
<br>

<p>이제 파일 경로를 <strong>image_paths</strong> 변수에 담아보자.</p>
<pre><code class="language-python">from imutils import paths

search_dir = &quot;animals&quot;

image_paths = sorted(
    list(paths.list_images(search_dir))
)

print(&quot;&gt;&gt;&gt; image count =&quot;, len(image_paths))</code></pre>
<pre><code>&gt;&gt;&gt; image count = 3000</code></pre><br>

<p><strong>image_paths</strong> 에 담긴 각각의 이미지 경로 하나씩 불러온다.</p>
<p>그리고 이미지는 <strong>images</strong> 에 저장하고 레이블은 <strong>labels</strong> 변수에 담는다.</p>
<blockquote>
<p>❝ 각각의 이미지에 대한 레이블은 어디 있을까 ? ❞ </p>
</blockquote>
<p>❝ <strong>폴더 이름을</strong> 잘라내어 <strong>레이블로 만든다.</strong> ❞</p>
<br>

<p>이해를 돕기 위해 이미지와 레이블 파트로 나뉘어 설명한다.</p>
<p>우선 실제 이미지 경로를 하나씩 꺼내어</p>
<p>해당 경로 이미지를 <strong><code>cv2.imread()</code></strong> 통해 불러온다.</p>
<p>그리고 <strong><code>cv2.resize()</code></strong> 로 크기를 균일하게 변경한다.</p>
<blockquote>
<p>❝ 이미지 크기가 각기 다르기 때문이다. ❞ </p>
</blockquote>
<p>마지막으로 이를 <strong>images</strong> 리스트에 순차적으로 담아준다.</p>
<br>

<p>레이블 생성도 마찬가지로 이미지 경로가 필요하다.</p>
<pre><code class="language-python">print(image_path)</code></pre>
<pre><code>&gt;&gt;&gt; data/animals/panda/panda_01000.jpg</code></pre><p>우리가 필요한 부분은 <strong>panda/</strong> 이며 <strong><code>.split()</code></strong> 으로 잘라주면 된다.</p>
<p>또한 <strong><code>os.path.sep</code></strong> 를 이용하면 구분자를 손쉽게 찾아낼 수 있으므로</p>
<p>뒤에서 두번째 위치 <strong><code>[-2]</code></strong> 를 찾아낸다.</p>
<p>마지막으로 <strong>labels</strong> 에 저장한다.</p>
<pre><code class="language-python">import os
import cv2
from tqdm import tqdm

image_dim = (180, 180, 3)

images = []
labels = []
for image_path in tqdm(image_paths):
    image = cv2.imread(image_path)

    image = cv2.resize(
        image, (image_dim[1], image_dim[0])
    )
    images.append(image)

    label = image_path.split(os.path.sep)[-2]
    labels.append([label])

    print(&quot;&gt;&gt;&gt; images count =&quot;, len(images))
</code></pre>
<pre><code>100%|██████████| 3000/3000 [10:44&lt;00:00,  4.65it/s]
&gt;&gt;&gt; images count = 3000</code></pre><br>

<h3 id="🌕-전처리와-데이터-분할">🌕 전처리와 데이터 분할</h3>
<p>전처리는 두가지 작업을 할 예정이다.</p>
<p>첫째로 이미지 값을 <strong>0 에서 1 사이의 값으로 변환한다.</strong> </p>
<blockquote>
<p>❝ 그렇다. 스케일링 작업이다. ❞ </p>
</blockquote>
<br>

<p>둘째는 <strong>One-Hot Encoding</strong> 작업이다. </p>
<p>현재 레이블은 <strong>panda, dogs 또는 cats</strong> 이다.</p>
<blockquote>
<p>❝ 컴퓨터가 읽을 수 있는 형태로 바꿔주자. ❞ </p>
</blockquote>
<p><strong><code>sklearn.preprocessing.MultiLabelBinarizer()</code></strong> 사용하여 원핫 인코딩을 할 수 있다.</p>
<br>

<table>
<thead>
<tr>
<th>Label Name</th>
<th>One-Hot Encoding</th>
</tr>
</thead>
<tbody><tr>
<td><strong>panda</strong></td>
<td><strong>[1, 0, 0]</strong></td>
</tr>
<tr>
<td><strong>dogs</strong></td>
<td><strong>[0, 1, 0]</strong></td>
</tr>
<tr>
<td><strong>cats</strong></td>
<td><strong>[0, 0, 1]</strong></td>
</tr>
</tbody></table>
<br>

<pre><code class="language-python">import numpy as np
from sklearn.preprocessing import MultiLabelBinarizer

images = np.array(images, dtype=&#39;float32&#39;) / 255.0
labels = np.array(labels)

mlb = MultiLabelBinarizer()
enc_labels = mlb.fit_transform(labels)

print(&quot;&gt;&gt;&gt; classes name =&quot;, mlb.classes_)</code></pre>
<pre><code>&gt;&gt;&gt; classes name = [&#39;cats&#39; &#39;dogs&#39; &#39;panda&#39;]</code></pre><br>

<p>이제 데이터를 분할해보자.</p>
<p><strong><code>sklearn.model_selection.train_test_split()</code></strong> 으로 데이터 분할을 한다.</p>
<p><strong>Train 데이터</strong> <strong><code>80%</code></strong> 그리고 <strong>Test 데이터</strong> <strong><code>20%</code></strong> 를 사용하고자 한다.</p>
<pre><code class="language-python">from sklearn.model_selection import train_test_split

seed = 47

(x_train, x_test, y_train, y_test) = train_test_split(
    images, enc_labels, test_size=0.2, random_state=seed
)
print(&quot;&gt;&gt; train test shape = {} {}&quot;.format(
    x_train.shape, y_train.shape)
)</code></pre>
<br>

<h3 id="🌗-모델-생성과-학습">🌗 모델 생성과 학습</h3>
<p><strong>모델은 VGGNet 을 참고</strong>하여 컨볼루션 크기와 네트워크 깊이를 조절하였다.</p>
<p>여기서 주의할 점은 <strong>마지막 출력을 Soft-Max</strong> 로 한다는 점이다.</p>
<ul>
<li><strong><code>tensorflow.keras.layers.Activation(&#39;softmax&#39;)</code></strong></li>
</ul>
<p>기억해두자.</p>
<p><strong>Multi-Class Classification 의 마지막 출력은 Soft-Max 이다.</strong></p>
<blockquote>
<p>❝ 출력을 Soft-Max 로 안하는 코드도 있던데 ? ❞ </p>
</blockquote>
<p>구현 방법에 차이로 틀린 건 아니다.</p>
<br>

<p>그러나 <strong>Binary</strong>, <strong>Multi-Class</strong>, <strong>Multi-Label</strong> 모두</p>
<p>마지막 출력 함수가 다르기에 하나의 포맷을 추천한다.</p>
<br>

<p>위 물음은 하단 모델 컴파일 부분에서 설명하겠다.</p>
<pre><code class="language-python">from tensorflow.keras import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, BatchNormalization
from tensorflow.keras.layers import Activation, Flatten, Dropout, Dense

class Classifier:
    def build(width, height, depth, classes):
        model = Sequential()
        input_shape = (height, width, depth)

        model.add(Conv2D(32, (3, 3), padding=&#39;same&#39;, input_shape=input_shape))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization(axis=-1))
        model.add(MaxPooling2D(pool_size=(3, 3)))
        model.add(Dropout(0.25))

        model.add(Conv2D(64, (3, 3), padding=&#39;same&#39;))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization(axis=-1))
        model.add(Conv2D(64, (3, 3), padding=&#39;same&#39;))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization(axis=-1))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))

        model.add(Conv2D(128, (3, 3), padding=&#39;same&#39;))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization(axis=-1))
        model.add(Conv2D(128, (3, 3), padding=&#39;same&#39;))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization(axis=-1))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))

        model.add(Conv2D(256, (3, 3), padding=&#39;same&#39;))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization(axis=-1))
        model.add(Conv2D(256, (3, 3), padding=&#39;same&#39;))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization(axis=-1))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.25))

        model.add(Flatten())
        model.add(Dense(2048))
        model.add(Activation(&#39;relu&#39;))
        model.add(BatchNormalization())
        model.add(Dropout(0.5))

        model.add(Dense(classes))
        model.add(Activation(&#39;softmax&#39;))
        return model

model = Classifier.build(
    width=image_dim[1], height=image_dim[0], depth=image_dim[2],
    classes=len(mlb.classes_)
)</code></pre>
<br>

<p>이제 모델을 컴파일 해보자.</p>
<p><strong>optimizer</strong> 에 <strong><code>tensorflow.keras.optimizers</code></strong> 을 사용하면</p>
<p>학습률 등을 디테일하게 조절할 수 있다.</p>
<br>

<p>이제 <strong>Loss Function</strong> 에 대해 이야기 해보자.</p>
<p>위에서 마지막 출력을 <strong>Soft-Max</strong> 로 안하는 경우도 있다고 했다.</p>
<p>그런 경우에는 <strong><code>CategoricalCrossentropy(from_logits=True)</code></strong> 으로 변경하면 된다.</p>
<p>그럼 <strong>Cross-Entropy</strong> 를 계산함에 있어 다르게 동작한다고 한다.</p>
<blockquote>
<p>❝ 결과의 차이는 없어보인다. ❞</p>
</blockquote>
<p>다만 <strong>Tensorflow</strong> 공식 홈페이지에서는</p>
<p><strong><code>from_logits=True</code></strong> 방식이 <strong>Numerical stable</strong> 하다고 한다.</p>
<pre><code class="language-python">from tensorflow.keras.losses import CategoricalCrossentropy
from tensorflow.keras.optimizers import Adam

batch_size = 32
epoch = 200
learning_rate = 1e-3
decay = learning_rate / epoch

optimizer = Adam(
    learning_rate=learning_rate,
    decay=decay
)

loss = CategoricalCrossentropy(from_logits=False)

model.compile(
    loss=loss,
    optimizer=optimizer,
    metrics=[&#39;accuracy&#39;]
)</code></pre>
<br>

<blockquote>
<p>❝ 이제 거의 다 왔다. 힘내자. ❞</p>
</blockquote>
<p>우리는 작은 이미지로 학습을 시키려한다. </p>
<p>따라서 데이터를 증강시키도록 한다.</p>
<p><strong>Kera</strong> 에 <strong><code>ImageDataGenerator()</code></strong> 함수를 이용하도록 하자.</p>
<ul>
<li>회전과 위치 변경 등으로 이미지 복제</li>
</ul>
<pre><code>from tensorflow.keras.preprocessing.image import ImageDataGenerator

aug = ImageDataGenerator(
    rotation_range=25, width_shift_range=0.1, height_shift_range=0.1, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode=&#39;nearest&#39;
)</code></pre><br>

<blockquote>
<p>❝ 드디어 모델 학습 과정이다. ❞</p>
</blockquote>
<p>이 과정에서 <strong>GPU 를 사용했다.</strong></p>
<p>그리고 <strong><code>.fit_generator()</code></strong> 으로 데이터를 증강하여 학습시킨다.</p>
<pre><code>history = model.fit_generator(
    aug.flow(
        x_train, y_train, batch_size=batch_size
    ),
    validation_data=(x_test, y_test),
    steps_per_epoch=len(x_train) // batch_size,
    epochs=epoch, verbose=1
)</code></pre><pre><code>Epoch 1/200
75/75 [==============================] - 40s 113ms/step - loss: 1.5247 - accuracy: 0.5562 - val_loss: 3.1929 - val_accuracy: 0.3150
Epoch 2/200
75/75 [==============================] - 8s 102ms/step - loss: 0.9905 - accuracy: 0.6021 - val_loss: 1.8746 - val_accuracy: 0.3500
Epoch 3/200
75/75 [==============================] - 8s 102ms/step - loss: 0.9192 - accuracy: 0.6221 - val_loss: 3.2068 - val_accuracy: 0.3500
Epoch 4/200
75/75 [==============================] - 8s 102ms/step - loss: 0.8743 - accuracy: 0.6292 - val_loss: 1.3691 - val_accuracy: 0.3967
Epoch 5/200
75/75 [==============================] - 8s 102ms/step - loss: 0.7978 - accuracy: 0.6508 - val_loss: 1.2389 - val_accuracy: 0.4250
Epoch 6/200
75/75 [==============================] - 8s 102ms/step - loss: 0.7651 - accuracy: 0.6629 - val_loss: 2.1172 - val_accuracy: 0.4283
Epoch 7/200
75/75 [==============================] - 8s 103ms/step - loss: 0.7412 - accuracy: 0.6696 - val_loss: 0.7568 - val_accuracy: 0.6783
...................................................................................................................................
Epoch 197/200
75/75 [==============================] - 8s 105ms/step - loss: 0.0873 - accuracy: 0.9725 - val_loss: 0.6421 - val_accuracy: 0.8567
Epoch 198/200
75/75 [==============================] - 8s 106ms/step - loss: 0.0817 - accuracy: 0.9708 - val_loss: 0.6350 - val_accuracy: 0.8217
Epoch 199/200
75/75 [==============================] - 8s 108ms/step - loss: 0.0875 - accuracy: 0.9712 - val_loss: 0.5505 - val_accuracy: 0.8600
Epoch 200/200
75/75 [==============================] - 8s 108ms/step - loss: 0.0623 - accuracy: 0.9779 - val_loss: 0.4870 - val_accuracy: 0.8850</code></pre><p>우리 모델의 <strong>Loss 와 Accuracy</strong> 를 눈으로 확인해보자.</p>
<p><img src="https://images.velog.io/images/robert-lee/post/b9681c9d-6d5b-43ef-8b78-8ef532fb1973/image.png" alt=""></p>
<h3 id="🌑-신규-이미지-예측">🌑 신규 이미지 예측</h3>
<p>동일한 방법으로 <strong><code>images/</code></strong> 디렉토리의 파일 경로를 읽는다.</p>
<pre><code class="language-python">test_image_paths = sorted(
    list(
        paths.list_images(&quot;images/&quot;)
    )
)
print(&quot;&gt;&gt;&gt; test image path =&quot;, test_image_paths)</code></pre>
<pre><code>&gt;&gt;&gt; test image path = [&#39;images/cat.jpg&#39;, &#39;images/dog.jpg&#39;, &#39;images/panda.jpg&#39;]</code></pre><br>

<p>이미지와 예측 레이블을 각각 출력해보자.</p>
<pre><code class="language-python">print(&quot;&gt;&gt;&gt; class index =&quot;,  mlb.classes_)

for image_path in test_image_paths:
    test_image = cv2.imread(image_path)

    test_image = cv2.resize(
        test_image, (96, 96)
    )
    cv2_imshow(test_image)

    test_image = test_image.astype(&quot;float&quot;) / 255.0
    test_image = np.expand_dims(test_image, axis=0)

    proba = model.predict(test_image)[0]
    print(
        np.round(proba, 3)
    )
    idx = np.argmax(proba)
    print(&quot;&gt;&gt;&gt; predict class =&quot;, mlb.classes_[idx])</code></pre>
<pre><code>&gt;&gt;&gt; class index = [&#39;cats&#39; &#39;dogs&#39; &#39;panda&#39;]</code></pre><figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/350b1e81-063f-4882-aa3a-c7297c9065c1/cat.jpg"
       style="width: 30%; height: 30%; margin:0px left">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
  </figcaption>
</figure>

<pre><code>[0.091 0.875 0.034]
&gt;&gt;&gt; predict class = dogs</code></pre><figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/e993a550-37a6-4ee5-97d1-8192e375099d/image.png"
       style="width: 30%; height: 30%; margin:0px left">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
  </figcaption>
</figure>

<pre><code>[0.001 0.999 0.   ]
&gt;&gt;&gt; predict class = dogs</code></pre><figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/e108eec0-0bdd-4a02-9674-dc640752d3b9/image.png"
       style="width: 30%; height: 30%; margin:0px left">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
  </figcaption>
</figure>

<pre><code>[0.      0.     1.]
&gt;&gt;&gt; predict class = panda</code></pre><br>

<p>오늘 우리는 <strong>Multi-Class Classification</strong> 을 코드로 살펴보았다.</p>
<p>이제 그만 알아보자.</p>
<br>

<p>다음 포스트에서는 <strong>Multi-Label Classification</strong> 을 알아보자.</p>
<h3 id="🍀-참고">🍀 참고</h3>
<ul>
<li><a href="https://medium.com/analytics-vidhya/vggnet-architecture-explained-e5c7318aa5b6">VGGNET Architecture</a></li>
<li><a href="https://github.com/space-owner/Deep-Learning/blob/main/Multi%20Class%20Classification%20with%20Animals.ipynb">Multi-Class Clasification with Animals</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Deep Learning] Classification 모델의 종류를 살펴보자.]]></title>
            <link>https://velog.io/@robert-lee/Deep-Learning-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%B6%84%EB%A5%98-%EC%A2%85%EB%A5%98%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@robert-lee/Deep-Learning-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%B6%84%EB%A5%98-%EC%A2%85%EB%A5%98%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Tue, 05 Oct 2021 07:23:31 GMT</pubDate>
            <description><![CDATA[<h3 id="🔊-목차">🔊 목차</h3>
<p>본격적인 분류 모델 이해에 앞서 <strong>Classification</strong> 종류에 대해 알아보자.</p>
<p>이 글은 모델 설계에 도움이 될 것이다.</p>
<ul>
<li>Binary Classification</li>
<li>Multi-Class Classification</li>
<li>Multi-Label Classification</li>
</ul>
<br>

<h3 id="😃-분류-모델의-이해">😃 분류 모델의 이해</h3>
<p>우리는 목적에 따라 분류 모델을 설계해야 한다.</p>
<p>분류 모델은 크게 세가지로 나뉜다.</p>
<ul>
<li><p><strong>Binary Classification</strong></p>
</li>
<li><p><strong>Multi-Class Classification</strong></p>
</li>
<li><p><strong>Multi-Label Classification</strong></p>
</li>
</ul>
<p>위 모델들 구현시에 통계적 이론에 차이가 존재한다.</p>
<br>

<p>즉 우리는 목적에 맞는 <strong>Classification</strong> 을 찾고</p>
<p>그에 알맞은 이론을 구현해야 할 것이다.</p>
<br>

<p>더불어 이 글에서는 이미지 분류 모델을 중심으로 설명할 예정이지만</p>
<p>분류 문제는 이미지 분야에 한정되어 있는 건 아니다.</p>
<blockquote>
<p>❝ 캐글의 타이타닉 생존자 예측 대회에 대해 들어본 적이 있는가 ? ❞</p>
</blockquote>
<p>이는 둘 중 하나로 예측하는 이진 분류 <code>Binary Classification</code> 를 다룬다.</p>
<br>

<p>이를 통해 우리는 알 수 있다.</p>
<blockquote>
<p>❝ Binary / Multi-Class / Multi-Label 분류는 머신러닝에서도 사용될 수 있는 개념이다. ❞</p>
</blockquote>
<br>

<p>이제 각각 모델의 <strong>Use-Case</strong> 를 살펴보도록 하자.</p>
<br>

<h3 id="⭐-binary-classification">⭐ Binary Classification</h3>
<blockquote>
<p>❝ 고양이와 강아지 사진을 분류할 수 있을까 ? ❞</p>
</blockquote>
<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/ef9c0956-ef43-472a-9ab8-182a483ecf0b/68747470733a2f2f6d69726f2e6d656469756d2e636f6d2f6d61782f313833382f312a6f4233533579484868766f75674a6b50587563386f672e676966.gif"
       style="width: 60%; height: 60%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - flixstock.com
  </figcaption>
</figure>

<br>

<p>우리는 위 물음에 <strong>Yes</strong> 라고 말할 수 있다. </p>
<p>왜냐하면 두가지 중 하나로 예측하기 위한 모델이 존재하기 때문이다.</p>
<br>

<p><strong>Binary Classification</strong> 은 예측 범위 <code>Class</code> 가 두가지인 경우에 사용된다.</p>
<p>그렇다면 우리가 수집한 훈련 데이터셋의 <strong>Class</strong> 도 반드시 <code>2</code> 개여야 한다.</p>
<br>

<pre><code>훈련 데이터셋 = {
    이미지 1 : &#39;고양이&#39;,
    이미지 2 : &#39;강아지&#39;,
    이미지 3 : &#39;강아지&#39;,
}</code></pre><p>우리는 <strong>&lt;고양이, 강아지&gt;</strong> 훈련 데이터셋으로 모델을 학습시켰다.</p>
<p>그리고 <code>호랑이</code> 이미지를 넣어 예측을 해보자.</p>
<blockquote>
<p>❝ 어떤 결과가 나올까 ? ❞</p>
</blockquote>
<p>우리는 <strong>❝ 호랑이야. ❞</strong> 라고 예측을 하거나</p>
<p><strong>❝ 고양이와 강아지가 아니다. ❞</strong> 로 예측하길 바랄 것이다.</p>
<br>

<p>아쉽게도 <strong>&lt;고양이 또는 강아지&gt; 중 하나로 예측</strong>을 한다.</p>
<p><strong>무조건 둘 중에 하나</strong>로 예측을 한다.</p>
<blockquote>
<p>❝ 그럼 왜 사용하는 거야 ? ❞</p>
</blockquote>
<p>우리 주변에는 생각보다 둘 중에 하나인 경우가 많다.</p>
<p>아래 예시를 보자 :</p>
<ul>
<li>적격 - 부적격</li>
<li>합격 - 불합격</li>
<li>스팸 - 햄</li>
<li>고양이 - 고양이가 아닌 것</li>
</ul>
<blockquote>
<p>❝ 그래서 특별히 이진 분류가 있다. ❞</p>
</blockquote>
<p>그치만 <strong>&lt;고양이, 강아지, 호랑이&gt;</strong> 중 하나로 분류를 하고 싶다면</p>
<p><strong>Multi-Class Classification</strong> 모델을 구현해야 한다.</p>
<br>

<h3 id="⚡-multi-class-classification">⚡ Multi-Class Classification</h3>
<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/524ca4c3-d358-4685-81e0-e719b971f8f4/%EA%B7%B8%EB%A6%BC1.png"
       style="width: 90%; height: 90%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - national geographic
  </figcaption>
</figure>


<blockquote>
<p>❝ 고양이, 강아지, 호랑이 중에 하나로 분류를 하고 싶다. ❞</p>
</blockquote>
<p>또는</p>
<blockquote>
<p>❝ 고양이, 강아지, 호랑이, 사자, 돼지 중에 하나로 분류를 하고 싶다. ❞</p>
</blockquote>
<p>첫번째는 <code>3</code> 개의 <strong>Class</strong> 로 둘째는 <code>5</code> 개의 <strong>Class</strong> 로 분류하고 싶은 경우이다.</p>
<br>

<p>즉 <strong>Multi-Class Classification</strong> 는 분류하고자 하는 <strong>Class</strong> 가 <code>3</code> 개 이상인 경우에 사용한다.</p>
<br>

<blockquote>
<p>❝ Multi-Class 분류에서 데이터셋은 어떻게 구성해야 할까 ? ❞</p>
</blockquote>
<p>만약 <strong>&lt;강아지, 고양이, 호랑이&gt;</strong> 분류 모델을 만들고 싶다면</p>
<pre><code>훈련 데이터셋 = {
    이미지 1 : &#39;고양이&#39;,
    이미지 2 : &#39;강아지&#39;,
    이미지 3 : &#39;호랑이&#39;,
    이미지 4 : &#39;고양이&#39;,
    이미지 5 : &#39;강아지&#39;,
    이미지 6 : &#39;호랑이&#39;
}</code></pre><p><strong>&lt;강아지, 고양이, 호랑이&gt;</strong> 사진을 <code>1:1:1</code> 로 수집하면 되고</p>
<p><strong>&lt;강아지, 고양이, 호랑이&gt;</strong> 에 대해서는 틀림없이 좋은 성능을 낼 것이다.</p>
<br>

<p>그러나 문득 이런 생각이 든다.</p>
<blockquote>
<p>❝ 한장의 사진에 고양이와 강아지가 같이 있다면 ? ❞</p>
</blockquote>
<p>이런 질문은 대답하기가 쉽지 않다.</p>
<blockquote>
<p>❝ 둘 중 하나로 나오지 않을까 ? ❞</p>
</blockquote>
<p>이 때 우리는 <strong>Multi-Label Classification</strong> 을 하면 된다.</p>
<br>

<h3 id="🌞-multi-label-classification">🌞 Multi-Label Classification</h3>
<p><strong>Multi-Class</strong> 와 <strong>Multi-Label</strong> 은 이름도 비슷하다.</p>
<blockquote>
<p>❝ 굳이 모델을 나눈 이유가 있을까? ❞</p>
</blockquote>
<p>우리는 다음과 같은 애매한 상황에 처할 수 있다.</p>
<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/8d0b923f-f814-47d2-a94c-e4211fad8ea2/image.png"
       style="width: 60%; height: 60%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - petbacker.com
  </figcaption>
</figure>

<blockquote>
<p>❝ 한장의 사진에 고양이와 강아지가 있다. ❞</p>
</blockquote>
<p>그리고 <strong>&lt;고양이와 강아지&gt;</strong> <code>2</code> 개로 예측하고 싶다.</p>
<p>이때 <strong>Multi-Label Classification</strong> 을 이용하면 된다.</p>
<br>

<p>다시 말해 <strong>Multi-Class</strong> 에서는 한장의 사진은 무조건 하나의 <strong>Class</strong> 로 예측되고</p>
<p><strong>Multi-Class</strong> 는 두가지 이상의 <strong>Class</strong> 로 예측될 수 있다.</p>
<br>

<p>다만 <strong>&lt;고양이와 강아지&gt;</strong> 를 예측하기 위해서는</p>
<p>기존의 <strong>&lt;고양이, 강아지, 호랑이&gt;</strong> 훈련 데이터셋에</p>
<p><strong>&lt;고양이와 강아지&gt;</strong> 사진을 합쳐서</p>
<p><strong>Multi-Label Classification</strong> 에 학습시켜야 한다.</p>
<br>

<p>다음 포스트에서 <strong>Classification</strong> 설계 방법을 차근히 알아보도록 하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tensorflow Keras] MaxPooling 과 Average Pooling 을 살펴보자.]]></title>
            <link>https://velog.io/@robert-lee/Tensorflow-MaxPooling-%EA%B3%BC-Average-Pooling-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94</link>
            <guid>https://velog.io/@robert-lee/Tensorflow-MaxPooling-%EA%B3%BC-Average-Pooling-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94</guid>
            <pubDate>Tue, 05 Oct 2021 01:52:24 GMT</pubDate>
            <description><![CDATA[<h3 id="🔊-목차">🔊 목차</h3>
<ul>
<li>레이어 개념을 비교 설명하며 활용에 대해 이야기한다.<ul>
<li>Max Pooling 과 Average Pooling</li>
<li>Flatten 과 Global Pooling</li>
</ul>
</li>
</ul>
<br/>

<h3 id="😊-레이어-개념-비교-설명">😊 레이어 개념 비교 설명</h3>
<p>우리는 앞서 이미지 분류를 위한 기본적인 레이어에 대해 살펴보았다.</p>
<p>여기서 우리는 더 깊은 이해를 위해 자료를 찾을 것이고</p>
<p>폴링 <code>Pool Layer</code> 에는 적어도 두가지 존재하는 것을 알게 된다.</p>
<blockquote>
<p>❝ Max Pooling 과 Average Pooling 을 볼 수 있다. ❞</p>
</blockquote>
<br/>

<p>여기서 찾아보면</p>
<blockquote>
<p>❝ Global Average Pooling 을 볼 수 있을 거다. ❞</p>
</blockquote>
<br/>

<p>같은 레이어 <code>Layer</code> 지만 개념과 목적이 다른</p>
<p>다소 혼란스러운 개념에 대해 이야기 해보고자 한다.</p>
<br/>

<h3 id="🔨-max-pooling-vs-average-pooling">🔨 Max Pooling vs Average Pooling</h3>
<p>먼저 폴링 <code>Pooling Layer</code> 의 목적은 최적화 파라미터 개수를 줄이기 위함이다.</p>
<p>그러나 우리는 목적에 따라 폴링을 두가지 형태로 구현할 수 있다.</p>
<ul>
<li><p><code>Max Pooling</code></p>
</li>
<li><p><code>Average Pooling</code></p>
</li>
</ul>
<br/>

<p>최대값 <code>Max</code> 을 활용하면 가장 두드러지는 특징을 찾을 수 있다고 했다.</p>
<blockquote>
<p>❝ 그렇다. 최대값이라는 개념을 활용한다면 특징을 잘 찾아낼 수 있다. ❞</p>
</blockquote>
<br/>

<p>반대로 평균 <code>Average</code> 은 덜 중요한 요소를 포함할 수 있다.</p>
<blockquote>
<p>❝ 그럼에도 왜 사용하는 것일까 ? 왜냐하면 분산을 사용할 수 있기 때문이다. ❞</p>
</blockquote>
<br/>

<p>평균과 분산 개념을 활용하여 물체 위치를 보다 쉽게 파악할 수 있기 때문이다.</p>
<p>따라서 우리는 객체 탐지 <code>Object Detection</code> 분야에서 <code>Average Pooling</code> 을 효과적으로 활용할 수 있다.</p>
<br/>

<h3 id="🔧-flatten-vs-global-pooling">🔧 Flatten vs Global Pooling</h3>
<p><code>Flatten</code> 은 다차원 데이터를 <code>1</code> 차원 데이터로 변경하는 역할을 한다고 했다.</p>
<blockquote>
<p>❝ 그렇다면 Global Pooling 과 Flatten 어떤 연관성이 있을까 ? ❞</p>
</blockquote>
<br/>

<p>우선 <code>Global Pooling</code> 은 <code>Pooling</code> 과 달리 사진 한장을 하나의 숫자로 출력할 수 있다.</p>
<p>따라서 <code>Flatten</code> 의 출력과 <code>Global Pooling</code> 출력은 비슷하다.</p>
<p>다만 <code>Max</code> 또는 <code>Average</code> 개념을 포함시킬 수 있으며 출력 길이가 다른 특징이 있다.</p>
<br/>

<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/50589afd-614b-4a8a-986d-666a70d57dbf/fa7bbebf-aae1-45b8-a03c-4f44dbd43185.png"
       style="width: 60%; height: 60%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - www.researchgate.net/globalmaxpooling
  </figcaption>
</figure>

<br/>

<p>또한 Global Average Pooling 은 이미지 설명에도 활용되며</p>
<p><code>Flatten</code> 에 비해 성능이 좋다고 알려져있다.</p>
<br/>

<p>한줄로 정리하자면</p>
<blockquote>
<p>❝ Global Average Pooling <GAP> 과 Flatten 은 같은 일을 하며 GAP 를 적용하면 성능 향상을 기대할 수 있다. ❞</p>
</blockquote>
<br/>

<p>이제 우리는 해당 개념에 대해 간단히 알아보았다.</p>
<p>추후 포스트에서 구현과 함께 보다 자세히 알아보도록 하자.</p>
<br/>  

<p>다음 포스트에서는 본격적으로 이미지 분류를 살펴볼 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tensorflow Keras] 레이어를 구현해보자.]]></title>
            <link>https://velog.io/@robert-lee/Tensorflow-%EB%A0%88%EC%9D%B4%EC%96%B4%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@robert-lee/Tensorflow-%EB%A0%88%EC%9D%B4%EC%96%B4%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Tue, 05 Oct 2021 01:19:25 GMT</pubDate>
            <description><![CDATA[<h3 id="🔊-목차">🔊 목차</h3>
<ul>
<li>기본 레이어 개념을 이해하고 구현해본다.<ul>
<li>컨볼루션 <code>Conv Layer</code></li>
<li>플래튼 <code>Flatten Layer</code></li>
<li>폴링 <code>Pooling Layer</code></li>
</ul>
</li>
</ul>
<br/>

<h3 id="🥕-환경">🥕 환경</h3>
<ul>
<li><code>파이썬 3.7</code></li>
<li><code>텐서플로우 2.6</code></li>
<li><code>케라스 2.6</code></li>
</ul>
<br/>

<h3 id="😐-기본-레이어-이해">😐 기본 레이어 이해</h3>
<p>우리는 앞서 딥러닝과 뉴럴 네트워크의 차이를 알아보았다.</p>
<p>그리고 뉴럴 네트워크 구현 최소 단위인 레이어 <code>Layer</code> 가 필요하다고 했다.</p>
<p>여기서는 <code>Conv Layer</code>  <code>Pooling Layer</code>  <code>Flatten Layer</code> 를 다뤄보도록 하겠다.</p>
<blockquote>
<p>❝ 해당 개념은 링크의 동영상을 보는 것을 추천한다. ❞</p>
</blockquote>
<br/>

<h3 id="🏅-conv-layer-링크">🏅 Conv Layer <a href="https://opentutorials.org/module/5268/29788">&lt;링크&gt;</a></h3>
<p>우리가 이미지 분류를 잘하려면 특징 Feautre 을 잘 파악해야 할 것이다.</p>
<blockquote>
<p>❝ 뉴럴 네트워크에서 이미지 특징을 어떻게 뽑아낼 수 있을까 ? ❞</p>
</blockquote>
<br/>

<p>그에 대한 대답으로</p>
<blockquote>
<p>❝ Conv Layer 의 필터를 사용하면 된다. ❞</p>
</blockquote>
<br/>

<p>컨볼루션망 <code>CNN, Convolutional Neural Network</code> 을 들어본 경험이 있다면</p>
<p>이미지 분류를 잘하는 모델로 기억할 것이다.</p>
<blockquote>
<p>❝ 그렇다. 이미지를 잘 분류하려면 Conv Layer 가 필요하다. ❞</p>
</blockquote>
<br/>

<p>컨볼루션 <code>Conv Layer</code> 에는 필터 <code>Filter</code> 와 커널 <code>Kernel</code> 개념이 존재한다. </p>
<blockquote>
<p>❝ 필터란 몇개의 특징으로 출력을 만들어 낼 것인가 ? 를 의미한다. ❞</p>
</blockquote>
<br/>

<p>즉 해당 이미지를 판단하기 위해 가장 좋은 특징맵 <code>Feature Map</code>  <code>N</code> 개를 찾아낸다.</p>
<br/>

<p>또한 특징맵을 한개를 만들어가는 과정에서 커널 Kernel 개념이 사용된다.</p>
<p>이미지 크기가 <code>5 by 5</code> 이고  커널 크기가 <code>3 또는 (3, 3)</code> 인 그림을 살펴보자.</p>
<br/>

<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/fddfb941-38c6-41f9-9bb4-445cb3549c13/7850f825-7fa5-4554-83b0-e246d8acee62.gif"
       style="width: 50%; height: 50%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - jjeongil.tistory.com
  </figcaption>
</figure>

<br/>

<p>고정된 커널 크기에 따라 곱셈 연산을 하고 이를 모두 더한값을 기록한다.</p>
<br/>

<p>이제 tf.keras.layers.Conv2D() 이용하여 3 = (3, 3)  커널로 이루어진 32 개의 필터를 만들어보자.</p>
<pre><code class="language-python">import tensorflow as tf

input_layer = tf.keras.layers.Input(
    shape=(200, 200, 3), name=&#39;input_layer&#39;
)

conv_layer = tf.keras.layers.Conv2D(
    filters=32, kernel_size=(3, 3), activation=&#39;relu&#39;, name=&#39;conv_layer&#39;
)(input_layer)

output_layer = tf.keras.layers.Dense(
    units=2, activation=&#39;softmax&#39;, name=&#39;output_layer&#39;
)(conv_layer)

model = tf.keras.models.Model(input_layer, output_layer)

model.summary()</code></pre>
<pre><code>_________________________________________________________________
Layer (type)               Output Shape                  Param # 
=================================================================
input_layer (InputLayer)   [(None, 200, 200, 3)]               0 
_________________________________________________________________
conv_layer (Conv2D)        (None, 198, 198, 32)              896 
_________________________________________________________________
output_layer (Dense)       (None, 198, 198, 2)                66
=================================================================
Total params: 962                                                
Trainable params: 962                                            
Non-trainable params: 0                                          
_________________________________________________________________
</code></pre><p>그리고 다음과 같은 특징맵 <code>Feature Map</code> 을 얻을 수 있을 것이다.</p>
<p>여기서 특징맵은 <code>200 - (3 - 1) by 200 - (3 - 1)</code> 의 크기로 <code>32</code> 개가 출력된다.</p>
<p>한장의 사진은 <code>(1, 200, 200, 3)</code> 크기로 컨볼루션에 입력되어 <code>(32, 198, 198, 3)</code> 크기로 출력된다.</p>
<br/>

<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/74db8b55-f9e4-480d-938a-0b19c88f9400/image.png"
       style="width: 50%; height: 50%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - ricardodeazambuja.com/deep_learning
  </figcaption>
</figure>

<br/>
<br/>


<h3 id="🥈-flatten-layer-링크">🥈 Flatten Layer <a href="https://opentutorials.org/module/5268/29787">&lt;링크&gt;</a></h3>
<p>먼저 플래튼 <code>Flatten</code> 의 사전적 의미는 다음과 같다.</p>
<blockquote>
<p><strong>flatten</strong> [ˈflætn]</p>
</blockquote>
<ol>
<li>(동사) 납작 [반반] 해지다, 납작하게 [반반하게] 만들다
옥스퍼드 영한사전</li>
</ol>
<br/>

<p>플래튼을 사용하는 이유는 단순하다.</p>
<br/>

<p>우리는 &lt;강아지, 고양이&gt; 이미지 분류 <code>Classification</code> 를 할 예정이라면</p>
<p><code>1</code> 차원 배열로 출력해야 한다. &lt;두개 값으로 나와야 한다.&gt;</p>
<blockquote>
<p>❝ 이미지 1 의 예측값 예시 = [ 강아지 확률, 고양이 확률 ] = [ 90 % , 10 % ] ❞</p>
</blockquote>
<br/>

<p>그러나 우리는 <code>3</code> 차원 이상 배열 <code>Tensor</code> 을 이용해 특징을 찾아가고 있다.</p>
<p>그러므로 플래튼이 없다면 <code>3</code> 차원으로 출력이 될 것이다.</p>
<br/>

<p>다음 그림의 출력 <code>Output Shape</code> 을 살펴보자.</p>
<pre><code>_________________________________________________________________
Layer (type)               Output Shape                  Param # 
=================================================================
input_layer (InputLayer)   [(None, 200, 200, 3)]               0 
_________________________________________________________________
conv_layer (Conv2D)        (None, 198, 198, 32)              896 
_________________________________________________________________
output_layer (Dense)       (None, 198, 198, 2)                66 
=================================================================
</code></pre><br/>

<p>자 이제 텐서플로우 <code>tf.keras.layers.Flatten()</code> 을 통해 일자로 평평하게 만들어보자.</p>
<p>단순 <code>1</code> 차원 배열 <code>Array</code> 로 만드는 것이므로 파라미터는 필요 없다.</p>
<pre><code class="language-python">import tensorflow as tf

input_layer = tf.keras.layers.Input(
    shape=(200, 200, 3), name=&#39;input_layer&#39;
)

conv_layer = tf.keras.layers.Conv2D(
    filters=32, kernel_size=(3, 3), activation=&#39;relu&#39;, name=&#39;conv_layer&#39;
)(input_layer)

faltten_layer = tf.keras.layers.Flatten(name=&#39;flatten_layer&#39;)(conv_layer)

output_layer = tf.keras.layers.Dense(
    units=2, activation=&#39;softmax&#39;, name=&#39;output_layer&#39;
)(faltten_layer)

model = tf.keras.models.Model(input_layer, output_layer)

model.summary()</code></pre>
<pre><code>_________________________________________________________________
Layer (type)               Output Shape                  Param # 
=================================================================
input_layer (InputLayer)   [(None, 200, 200, 3)]               0 
_________________________________________________________________
flatten_layer (Flatten)    (None, 1254528)                     0 
_________________________________________________________________
conv_layer (Conv2D)        (None, 198, 198, 32)              896 
_________________________________________________________________
output_layer (Dense)       (None, 2)                     2509058 
=================================================================
Total params: 2,509,954                                          
Trainable params: 2,509,954                                      
Non-trainable params: 0                                          
_________________________________________________________________</code></pre><br/>

<p>즉 플래튼을 적용하면 정상적으로 &lt;강아지, 고양이&gt; <code>= [0.9, 0.1]</code> 또는 </p>
<p>&lt;강아지, 고양이, 호랑이&gt; <code>= [0.9, 0.0, 0.1]</code>  출력이 가능하다.</p>
<br/>

<h3 id="🥉-pooling-layer-링크">🥉 Pooling Layer <a href="https://opentutorials.org/module/5268/29791">&lt;링크&gt;</a></h3>
<p>마지막으로 살펴볼 레이어는 풀링 <code>Pooling Layer</code> 이다.</p>
<p>풀링은 <code>Sub Sampling</code> 으로 불리며 이미지 데이터를 작은 크기로 줄여주는 역할을 한다.</p>
<br/>

<p>풀링에는 대표적으로 <code>Max Pooling Layer</code> 와 <code>Average Pooling Layer</code> 있다.</p>
<p>다음 그림은 <code>Max Pooling Layer</code> 을 나타내며 풀링 크기 <code>Pooling Size</code> 가 <code>(2, 2)</code> 이다.</p>
<br/>

<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/3313cde8-859c-49ad-9fb3-aef997a8ddab/627c98b2-5b73-4051-ab65-d3ea8584332e.gif"
       style="width: 50%; height: 50%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - medium.com/parva.shah808
  </figcaption>
</figure>

<br/>


<p><code>Max Pooling</code> 풀링 크기에 마춰 해당 픽셀 중 가장 큰 값을 기록한다.</p>
<blockquote>
<p>❝ 다시 말해 Max Pooling 을 사용하면 가장 두드러진 특징만을 기록할 수 있다. ❞</p>
</blockquote>
<br/>

<blockquote>
<p>❝ 그렇다면 Average Pooling 의 특징은 무엇일까 ? 고민해보고 이포스트 하단을 읽어보자. ❞</p>
</blockquote>
<br/>

<p>그리고 문득 아래와 같은 질문을 할 수 있다.</p>
<blockquote>
<p>❝ 이미지 데이터를 작은 크기로 만들 필요가 있을까 ? 왜 그래야만 하는거지 ? ❞</p>
</blockquote>
<br/>

<p>우리는 컨볼루션 <code>Conv Layer</code> 를 바탕으로 이미지 특징을 찾아내고</p>
<p>플래튼 <code>Flatten Layer</code> 으로 일자로 만든 뒤에 확률 형태로 출력을 하였다.</p>
<p>풀링이 없는 뉴럴 네트워크를 구성해도 되지만 </p>
<p>최적화 해야되는 파라미터 <code>Parameter</code> 개수가 많아질 것이다.</p>
<blockquote>
<p>❝ 파라미터가 많다는 의미 오버피팅, 학습시간 등 문제를 야기한다는 뜻이다. ❞</p>
</blockquote>
<p>만약 풀링 <code>Pooling</code> 이 없다면</p>
<p>아래 그림과 같이 <code>2,509,954</code> 개의 파라미터를 찾아야 된다.</p>
<pre><code>_________________________________________________________________
Layer (type)               Output Shape                  Param # 
=================================================================
input_layer (InputLayer)   [(None, 200, 200, 3)]               0 
_________________________________________________________________
conv_layer (Conv2D)        (None, 198, 198, 32)              896 
_________________________________________________________________
flatten_layer (Flatten)    (None, 1254528)                     0 
_________________________________________________________________
output_layer (Dense)       (None, 2)                     2509058 
=================================================================
Total params: 2,509,954                                          
Trainable params: 2,509,954                                      
Non-trainable params: 0                                          
_________________________________________________________________</code></pre><p>그래서 우리는 파라미터를 줄이기 위해 <code>Pooling</code> 을 한다.</p>
<p>그리고 <code>Pooling Layer</code> 는 <code>conv_layer</code> 다음에 위치하는 것이 일반적이다.</p>
<p>특징을 찾은 이후에 풀링으로 이미지 크기를 줄인다.</p>
<br/>

<p>이제 <code>tf.keras.layers.MaxPool2D()</code> 를 바탕으로 <code>Pooling Layer</code> 를 구현해보자.</p>
<pre><code class="language-python">import tensorflow as tf

input_layer = tf.keras.layers.Input(
    shape=(200, 200, 3), name=&#39;input_layer&#39;
)

conv_layer = tf.keras.layers.Conv2D(
    filters=32, kernel_size=(3, 3), activation=&#39;relu&#39;, name=&#39;conv_layer&#39;
)(input_layer)

pool_layer = tf.keras.layers.MaxPool2D(
    pool_size=(3, 3), name=&#39;pool_layer&#39;
)(conv_layer)

faltten_layer = tf.keras.layers.Flatten(name=&#39;flatten_layer&#39;)(pool_layer)

output_layer = tf.keras.layers.Dense(
    units=2, activation=&#39;softmax&#39;, name=&#39;output_layer&#39;
)(faltten_layer)

model = tf.keras.models.Model(input_layer, output_layer)

model.summary()</code></pre>
<pre><code>_________________________________________________________________
Layer (type)               Output Shape                  Param # 
=================================================================
input_layer (InputLayer)   [(None, 200, 200, 3)]               0 
_________________________________________________________________
conv_layer (Conv2D)        (None, 198, 198, 32)              896 
_________________________________________________________________
pool_layer (MaxPooling2D)  (None, 66, 66, 32)                  0 
_________________________________________________________________
flatten_layer (Flatten)    (None, 139392)                      0 
_________________________________________________________________
output_layer (Dense)       (None, 2)                      278786 
=================================================================
Total params: 279,682                                            
Trainable params: 279,682                                        
Non-trainable params: 0                                          
_________________________________________________________________</code></pre><br/>

<p>위 결과와 같이 풀링 <code>Pooling Layer</code> 를 적용하면 </p>
<p><code>279,682</code> 개 파라미터를 최적화 시키면 된다.</p>
<p>만약 풀링이 없다면 <code>2,509,954</code> 파라미터를 찾아야 될 것이다.</p>
<br/>

<p>추가로 FC 레이어 <code>Fully Connected Layer</code> 에 대해 알아보자.</p>
<blockquote>
<p>❝ FC 레이어는 일렬로 펴진 층과 모든 노드가 연결된 구간을 이야기한다. ❞</p>
</blockquote>
<br/>

<p>지금 우리가 만든 모델에도 FC 레이어가 존재한다.</p>
<p>일자로 평평하게 만든 플래튼 <code>Flatten Layer</code> 과 마지막 출력을 위한 <code>Dense Layer</code> 합친 구간을 말한다.</p>
<br/>

<p>또한 뉴럴 네트워크 깊이에 따라 플래튼과 출력 사이에 한개 이상 <code>Dense Layer</code> 를 위치시킬 수 있다.</p>
<p>통상적으로 이 부분을 은닉층 <code>Hidden Layer</code> 이라 부르는 것 같다.</p>
<br/>

<p>이제 우리는 레이어에 대해 간략하게 이해를 하였다.</p>
<p>그러나 막상 레이어를 사용 시에 고려해야할 점들이 존재한다.</p>
<p>예를 들어 다음과 같은 질문이 될 수 있다.</p>
<blockquote>
<p>❝ Max Pooling 과 Average Pooling 중에 어떤것을 사용하여야 하는가 ? ❞</p>
</blockquote>
<p>다음 포스트에서는 몇가지 레이어 <code>Layer</code> 를 비교해 보고자 한다.</p>
<br/>

<h3 id="🍀-참고">🍀 참고</h3>
<ul>
<li><a href="https://opentutorials.org/module/5268/29788">오픈 튜토리얼</a></li>
<li><a href="https://www.tensorflow.org/tutorials">텐서플로우 튜토리얼</a></li>
<li><a href="https://www.tensorflow.org/api_docs/">텐서플로우 API 문서</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Deep Learning] 딥러닝과 뉴럴 네트워크의 관계를 알아보자.]]></title>
            <link>https://velog.io/@robert-lee/Data-Science-%EB%94%A5%EB%9F%AC%EB%8B%9D%EA%B3%BC-%EB%89%B4%EB%9F%B4-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EB%8A%94-%EB%AC%B4%EC%8A%A8-%EA%B4%80%EA%B3%84%EC%9D%BC%EA%B9%8C</link>
            <guid>https://velog.io/@robert-lee/Data-Science-%EB%94%A5%EB%9F%AC%EB%8B%9D%EA%B3%BC-%EB%89%B4%EB%9F%B4-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EB%8A%94-%EB%AC%B4%EC%8A%A8-%EA%B4%80%EA%B3%84%EC%9D%BC%EA%B9%8C</guid>
            <pubDate>Tue, 05 Oct 2021 00:35:16 GMT</pubDate>
            <description><![CDATA[<h3 id="🔊-목차">🔊 목차</h3>
<ul>
<li>프로그래밍과 딥러닝 차이를 알아본다.</li>
<li>딥러닝과 뉴럴 네트워크 관계를 살펴본다.</li>
</ul>
<br/>

<h3 id="😃-프로그래밍과-딥러닝의-차이">😃 프로그래밍과 딥러닝의 차이</h3>
<p>들어가기 앞서 로직과 딥러닝의 차이를 살펴보고자 한다. </p>
<p>프로그램과 딥러닝 모두 입력값, 출력값 그리고 로직을 가지고 있지만 결과물이 다르다.</p>
<p>그림이 다소 생소할 수도 있지만 아래 그림을 살펴보자.</p>
<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/f3f6ebfd-40bb-47c2-9045-6f1b2a115069/9d52c4b1-b131-43a9-85bc-405832fb9680.png"
       style="width: 50%; height: 50%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - futurice.com
  </figcaption>
</figure>
<br/>

<p>우리는 이해를 돕기 위해 프로그램 로직 <code>Program</code> 을 하나의 수식 <code>y = 2x + 1</code> 이라고 가정해보자.</p>
<p>만약 프로그램 개발중이라면, 요구사항에 마추어 출력값 <code>y, Result</code> 를 얻는 것이 목적이다.</p>
<p>이를 위해 입력값 <code>x, Input</code>  을 사용하여 수식 <code>program, 2x + 1</code> 을 구현한다.</p>
<br/>

<p>딥러닝의 경우 수식 <code>program, 2x + 1</code>  를 얻는 것이 목적이다. </p>
<p>여기서 우리는 입력값 <code>Input</code> 과 출력값 <code>Result</code> 을 이용하게 된다.</p>
<br/>

<p>이 때 아래와 같은 질문이 나올 수 있다.</p>
<blockquote>
<p>❝ 프로그램은 수식을 구현한다면 딥러닝은 대체 무엇을 구현하는 것일까 ? ❞</p>
</blockquote>
<p>사실 딥러닝에서 얻을 수 있는 프로그램 <code>program</code> 은 무수히 많다.</p>
<blockquote>
<p>❝ 무슨 말이냐고 ? ❞</p>
</blockquote>
<br/>

<p>데이터 <code>(x, y) : (1, 3), (2, 5)</code> 가 존재한다면 완전한 수식 <code>2x + 1</code> 을 만들 수 있다.</p>
<p>여기서 데이터를 추가로 수집하여 데이터 <code>(x, y) : (1, 3), (2, 5), (3, 8)</code> 가 될 수 있다.</p>
<p>그럼 무수히 많은 수식이 나올 수 밖에 없다.</p>
<blockquote>
<p>❝ 왜나하면 해가 없기 때문이다. ❞</p>
</blockquote>
<br/>

<p>즉, 우리는 가장 작은 오차를 가진 수식을 얻으려 할 것이고 이를 얻기 위한 방법을 구현한다.</p>
<br/>

<p>그리고 코드를 실행시켜주면</p>
<blockquote>
<p>❝ 이를 학습시킨다. 라고 표현한다. ❞</p>
</blockquote>
<br/>

<p>더불어 얻게된 수식을 통해 출력값을 얻는 행위를</p>
<blockquote>
<p>❝ 예측한다. 라고 표현한다. ❞</p>
</blockquote>
<br/>

<h3 id="😀-딥러닝과-뉴럴-네트워크-관계">😀 딥러닝과 뉴럴 네트워크 관계</h3>
<p>예전에는 딥러닝 알고리즘 <code>Argorithm</code> 이라고도 표현했다.</p>
<p>하지만 근래 들어 알고리즘 보다는 모델 <code>Model</code> 이라고 부른다.</p>
<br/>

<p>본론으로 들어와서 딥러닝 모델은 예측이 가능한 형태를 말하며</p>
<p>뉴럴 네트워크 <code>Neural Network</code> 를 학습시킨 결과물이라 생각하면 된다.</p>
<blockquote>
<p>❝ 그럼 뉴럴 네트워크는 어떤 모습일까 ? ❞</p>
</blockquote>
<br/>

<p>그래서 익숙한 그림을 준비했다.</p>
<br/>

<figure style="display:block; text-align:center;">
  <img src="https://images.velog.io/images/robert-lee/post/157035ba-2218-4b82-8d59-5e759959eec4/image.png"
       style="width: 50%; height: 50%; margin:0px auto">
  <figcaption style="text-align:center; font-size:15px; color:#808080">
    출처 - www.researchgate.net
  </figcaption>
</figure>

<br/>

<p>먼저 입력층 <code>Input Layer</code> 과 출력층 <code>Output Layer</code> 은 우리가 미리 정해 놓을 수 있다.</p>
<br/>

<p>우리는 &lt;강아지, 고양이&gt; 이미지를 각각 <code>200 by 200</code> 크기로 <code>500</code> 장 수집했다.</p>
<p>그럼 입력층은 <code>200 by 200</code> 로 받아줘야 할 것이다.</p>
<p>나는 특별하니까 <code>500 by 500</code> 으로 받으려한다면</p>
<blockquote>
<p>❝ 눈으로 직접 에러를 확인할 수 있을 것이다. ❞</p>
</blockquote>
<br/>

<p>또한 두가지 이미지를 학습했기 때문에 &lt;강아지, 고양이&gt; 중에 하나로 예측된다.</p>
<p>따라서 출력층은 2 개의 값을 뱉어낼 수 있도록 만든다.</p>
<br/>

<p>우리는 다시 한번 똑똑한 질문을 할 수 있다.</p>
<blockquote>
<p>❝ 호랑이 이미지를 넣는다면 ? ❞</p>
</blockquote>
<br/>

<p>조심스럽게 답해본다.</p>
<blockquote>
<p>❝ 고양이가 아닐까 ? 호랑이는 고양이과 동물이니까. ❞</p>
</blockquote>
<br/>

<p>위와 같이 안타깝게도 둘 중 하나로만 답을 한다.</p>
<p>자세한 내용은 이후 포스팅에서 다룰 예정이다.</p>
<br/>

<p>마지막으로 단일 또는 다수의 은닉층 <code>Input Layer</code> 은 다양하게 구성될 수 있다.</p>
<blockquote>
<p>❝ 마치 어릴적 조립 설명서 없이 빌딩을 만드는 것 처럼 말이다. 우리는 논리적이니까. ❞</p>
</blockquote>
<br/>

<p>이 때 사용되는 구성 요소에는 <code>Conv Layer</code>  <code>Pooling Layer</code>  <code>Flatten Layer</code>  <code>Dense Layer</code> 가 있다.</p>
<br/>

<p>우리는 위와 같은 모든 구성 요소를 합쳐 뉴럴 네트워크라 부른다. </p>
<br/>

<p>정리해보면 딥러닝 예측 모델을 만들기 위해서는 뉴럴 네트워크가 필요하다.</p>
<blockquote>
<p>❝ 그럼 뉴럴 네트워크를 만들기 위해서는 무엇을 또 만들어야 하지 ? ❞</p>
</blockquote>
<br/>

<p>자주 반복되는 단어인 레이어 <code>Layer</code> 를 만들면 된다.</p>
<blockquote>
<p>❝ 숲을 만들기 위해 나무를 심어야 하듯이 레이어는 나무와 같다. ❞</p>
</blockquote>
<br/>

<p>다음으로레이어에 대해 차근차근 알아보자.</p>
]]></description>
        </item>
    </channel>
</rss>