<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코드 한줄</title>
    <link>https://roadcom.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 3 Aug 2026 18:49:20 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>기루광</managingEditor>
    <image>
      <title>코드 한줄</title>
      <url>https://t1.daumcdn.net/cfile/tistory/21760B3359439CBD3F</url>
      <link>https://roadcom.tistory.com</link>
    </image>
    <item>
      <title>Tensorflow Serving vs Flask REST API</title>
      <link>https://roadcom.tistory.com/107</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;Tensorflow serving 을 이용하기 전에는 flask 를 이용하여 REST API 를 만들어 microservice를 진행하는 것을 당연하게 생각했었습니다. python 의 overhead&amp;nbsp; 줄이기 위해 C++/golang 등 다른 framework 를 써야 된다는 것을 알았지만, 큰 영향이 없겠다 싶어 고민하지 않았던 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&quot;TensorFlow Serving is a flexible, high-performance serving system for machine learning models, designed for production environments.&quot; &amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;&lt;a href=&quot;https://github.com/tensorflow/serving&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/tensorflow/serving&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;Tensorflow serving은 유연하고, 고성능 서빙 시스템으로 프로덕션 환경에 맞게 디자인 되었다고 되어있는데 그럼 flask REST API 와 속도차이가 얼마나 나는지 궁금해서 비교해 보았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;우선 Tensorflow Serving 경우 REST API 방식과 gRPC 방식 2가지를 모두 지원하고 있습니다. (gRPC 내용은 추가 필요)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. Flask REST API&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. REST API [ &lt;span&gt;Tensorflow Serving ]&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. gRPC API [Tensorflow Serving]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;# 우선 심플한 CNN toy 모델을 학습해서 모델을 저장해놓고 이를 비교 검증을 진행 하도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;간단히 Colab 을 통해서 학습을 진행하였습니다. 해당 모델 파일을 다운로드 받아 압축을 푼 후 적당한 위치에 저장합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(아래는 Colab 실제 코드입니다.) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/dJ8s75/btro6bXO2ZY/bG89qyU0pQJVgSisRykjNK/tf_model_mnist.tar.gz?attach=1&amp;amp;knm=tfile.gz&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;tf_model_mnist.tar.gz&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.55MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;## Toy Model CNN

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train/255.0, x_test/255.0

x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)

class CNN(tf.keras.Model):
    def __init__(self):
        super(CNN, self).__init__()
        # 28,28,1
        self.layer1 = tf.keras.Sequential(
            [layers.Conv2D(32, kernel_size=3, 
                           padding='same',activation='relu'),
             layers.MaxPool2D(pool_size=(2,2), strides=2, padding='same')])
        # 14,14,32
        self.layer2 = tf.keras.Sequential(
            [layers.Conv2D(64, kernel_size=3, 
                           padding='same',activation='relu'),
             layers.MaxPool2D(pool_size=(2,2), strides=2, padding='same')])
        # 7,7,64
        self.flatten = layers.Flatten()
        self.fc = layers.Dense(10)

    def call(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = self.flatten(out)
        return self.fc(out)
        
## * from_logits=True - softmax 수행하기 전의 값을 사용 ##
criterion = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
optimizer = tf.keras.optimizers.Adam()
tf_model = CNN()
tf_model.compile(loss=criterion, optimizer=optimizer)

train_epochs =20
batch_size = 1024
model_path = 'tf_cnn_model'
version = '1'
save_path = f'{model_path}/{version}'

tf_model.fit(x_train, y_train, batch_size=batch_size, epochs=train_epochs)

pred_y = tf_model.predict(x_test, batch_size=batch_size)
accuracy = np.sum(np.argmax(pred_y, axis=1) == y_test)/len(y_test)
print(f'accuracy : {accuracy:&amp;gt;.4f}')

tf.keras.models.save_model(tf_model, save_path)
#!tar -zcvf tf_cnn_model.tar.gz tf_cnn_model

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;다음 해야 할일은 tenserflow serving 을 실행할 차례인데, docker 로 이미지를 다운로드 받아&amp;nbsp; docker 실행 시 몇가지 설정을 추가로 해주셔야 합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기본적인 docker 사용법 및 옵션은 아래 사이트를 보시면 친절하고 자세히 설명되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://subicura.com/2017/01/19/docker-guide-for-beginners-2.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;초보를 위한 도커 안내서 - 설치하고 컨테이너 실행하기&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다음은 자주 사용하는 옵션들입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;옵션설명&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-d&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;detached mode 흔히 말하는 백그라운드 모드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-p&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;호스트와 컨테이너의 포트를 연결 (포워딩)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-v&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;호스트와 컨테이너의 디렉토리를 연결 (마운트)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-e&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨테이너 내에서 사용할 환경변수 설정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ndash;name&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨테이너 이름 설정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ndash;rm&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프로세스 종료시 컨테이너 자동 제거&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-it&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;-i와 -t를 동시에 사용한 것으로 터미널 입력을 위한 옵션&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;ndash;link&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컨테이너 연결 [컨테이너명:별칭]&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# Download the TensorFlow Serving Docker image and repo
docker pull tensorflow/serving

# Run Tensorflow Serving(docker)
docker run -t --rm -p 8500:8500 -p 8501:8501 \
    -v &quot;/home/roadcom/workspace/models/tf_cnn_model:/models/mnist_model&quot; \
    -e MODEL_NAME=mnist_model \
    tensorflow/serving &amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결과:&amp;nbsp; gRPC(TF) &amp;gt; REST(TF) &amp;gt;&amp;gt; Flask &amp;gt; Flask+gunicorn 순으로 나타납니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Tenserflwo&amp;nbsp; Serving이 왜 중요한지를 보여주는 차이입니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실험 방법은 mnist test set 을 동일하게 로딩 후 요청 - 응답 간 10 회 반복 값입니다. 오래된 로컬 컴퓨터라 속도가 빠르지는 않지만, 표준편차가 낮은 것을 보아 비교에는 큰 문제가 없을 것같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 63px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Metric&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;gRPC (TF)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;REST (TF)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Flask&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #2780d4; color: #ffffff; font-family: 'Noto Serif KR';&quot;&gt;Flask+gunicorn&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AVG (s)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;color: #5733b1;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;0.983&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1.624&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;9.088&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;9.394&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;STD (s)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;color: #5733b1;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;0.011&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;0.021&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;0.378&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 21px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;0.348&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당 코드는 아래 github 에 공유드립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://github.com/elentail/Serving.git&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/elentail/Serving.git&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;참조 :&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;초보를 위한 도커 안내서 - 설치하고 컨테이너 실행하기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(&lt;a href=&quot;https://subicura.com/2017/01/19/docker-guide-for-beginners-2.html&quot;&gt;https://subicura.com/2017/01/19/docker-guide-for-beginners-2.html&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;</description>
      <category>프로그래밍/tensorflow</category>
      <category>flask serving</category>
      <category>gPRC</category>
      <category>tensorflow serving</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/107</guid>
      <comments>https://roadcom.tistory.com/107#entry107comment</comments>
      <pubDate>Tue, 28 Dec 2021 01:08:32 +0900</pubDate>
    </item>
    <item>
      <title>Buffer overflow 란?</title>
      <link>https://roadcom.tistory.com/106</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Buffer overflow 란,&amp;nbsp; 고정된 메모리 버퍼를 넘어서 접근해야 되지 않을 주소, 메모리 공간까지 넘어가 그 곳의 정보를 수정하거나 덮어쓰게 되는 것입니다.&amp;nbsp; 덮어쓰는 내용을 특정 코드를 실행하도록 덮어 씌우는 공격이 바로 buffer overflow 공격입니다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;먼저 메모리 Stack 에 대한 내용을 알아야 될 것 같아 간단히 그림을 그려봅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;Process&amp;nbsp;Memory &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;heap &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;malloc,&amp;nbsp;new&amp;nbsp;할당&amp;nbsp;동적&amp;nbsp;데이터&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;stack &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;전역 변수, 콜Stack(함수 파라미터 / 리턴 어드레스)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;data(global variabels)&lt;br /&gt;-&amp;nbsp;uninitialized&amp;nbsp;data&lt;br /&gt;-&amp;nbsp;initialized&amp;nbsp;data&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;code(or text)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;프로그램 기계어 코드가 올라가는 영역&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우리가 실행하는 Process 의 메모리 구조를 보면 1개의 Process는 1개의 stack 과 1개 이상의 heap을 가질 수 있습니다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BOF(Buffer Over Flow) 공격은 여기에서 stack 영역 중 Return Address 를 변경하여 메모리 내 특정 코드가 실행되도록 하는 공격 방법입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1093&quot; data-origin-height=&quot;716&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UQRW5/btroRK8Ibfs/InmTUnMCnBWCNKc0baxezK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UQRW5/btroRK8Ibfs/InmTUnMCnBWCNKc0baxezK/img.png&quot; data-alt=&quot;&amp;amp;amp;amp;lt;메모리 구조&amp;amp;amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UQRW5/btroRK8Ibfs/InmTUnMCnBWCNKc0baxezK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUQRW5%2FbtroRK8Ibfs%2FInmTUnMCnBWCNKc0baxezK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1093&quot; height=&quot;716&quot; data-origin-width=&quot;1093&quot; data-origin-height=&quot;716&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;amp;amp;lt;메모리 구조&amp;amp;amp;gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;실제 buffer overflow를 하기위해서는 scanf, strcpy, strcat 등 메모리를 조작하는 모든 함수를 통해서 가능합니다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결론 부터 말씀드리면 *_s 함수를 통하면 buffer over flow 가 일어날 수 있는 일들을 원천 차단할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;&amp;nbsp;코드를 예로 들어 자세히 설명 드리면 sniper() 함수를 전혀 실행될 수 없지만, 이를 실행 할 수있도록 메모리를 변조해보도록 하겠습니다. 아래 코드는 단순히 subroutine 을 실행하고 subroutine 안에서 scanf 를 통해 입력받고 종료되는 코드입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

int buf[4];
// 특정 메모리에 올라온 함수를 실행하는 방법
void sniper() {
	system(&quot;dir&quot;);
}

void subroutine(int param) {
	// buffer overflow 공격 지점
	scanf(&quot;%s&quot;, buf);
}

int main() {
	printf(&quot;SNIPER ADDRESS=[Ox%p]\n&quot;, sniper);
	subroutine(4);

	return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;Windows 에서 수행하기위해 Visual Studio&amp;nbsp; 의 디버그-창-디스어셈블리 를 체크하고, subroutine 함수 수행 전 break point 를 지정하여 레지스터창을 이용하면 아래와 같이 어셈블리 코드를 확인 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbYrau/btroVk2bGHs/3IKjnEie4TiSC1mWZEHX30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbYrau/btroVk2bGHs/3IKjnEie4TiSC1mWZEHX30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbYrau/btroVk2bGHs/3IKjnEie4TiSC1mWZEHX30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbYrau%2FbtroVk2bGHs%2F3IKjnEie4TiSC1mWZEHX30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;680&quot; height=&quot;274&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;여기서 중요한 것은 레지스터 창의 ESP(Stack Pointer)의 주소를 디버그-창-메모리 를 이용하여 step 별로 함수에 진입하는 상태를 보면 먼저 파라미터 4를 stack 넣고, 그 다음 함수가 끝나고 돌아올 주소 즉, return address 를 stack 에 넣는 다는 것을 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;Buffo overflow 공격은 바로 stack 에 있는 return address를 변경하여 원하는 함수를 실행하여 공격하는게 목표 입니다. 간단히 return address를 원하는 함수 (sniper 함수 주소)로 변경하면 어떤 일이&amp;nbsp; 생기는지 확인 해 보도록 하겠습니다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FuGQn/btroVkVpcxl/zdc2aT8iut3ClsrInu2pBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FuGQn/btroVkVpcxl/zdc2aT8iut3ClsrInu2pBK/img.png&quot; data-alt=&quot;Stack 내 Return Address 변경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FuGQn/btroVkVpcxl/zdc2aT8iut3ClsrInu2pBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFuGQn%2FbtroVkVpcxl%2Fzdc2aT8iut3ClsrInu2pBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;986&quot; height=&quot;298&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Stack 내 Return Address 변경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;함수가 정상적으로 종료되지는 않았지만, system(&quot;dir&quot;) 이란 sniper 함수가 수행되었음을 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coguB7/btro13d2tgl/9lCNR4BYc7FKth252q0dL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coguB7/btro13d2tgl/9lCNR4BYc7FKth252q0dL1/img.png&quot; data-alt=&quot;최종 dir cmd 가 실행되는 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coguB7/btro13d2tgl/9lCNR4BYc7FKth252q0dL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoguB7%2Fbtro13d2tgl%2F9lCNR4BYc7FKth252q0dL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;595&quot; height=&quot;248&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;최종 dir cmd 가 실행되는 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 남은 일은 buffer overflow 를 통해 return address 를 특정함수 (sniper ) 주소로 바꾸는 일만 남게 되었습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/106</guid>
      <comments>https://roadcom.tistory.com/106#entry106comment</comments>
      <pubDate>Mon, 27 Dec 2021 00:34:32 +0900</pubDate>
    </item>
    <item>
      <title>Digital watermarking (네이버웹툰 캡처 추적) #1</title>
      <link>https://roadcom.tistory.com/104</link>
      <description>&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;월요일 부터 금요일 까지 잠자기 전에 나를 인도해주는 네이버 웹툰을 보다가 문뜩&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;경고문을 보고는 어..이게 캡처가 된다고 ? 하면서 스마트폰 캡처를 했는데 정말 가능하긴 하네요,&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;우리 열심히 밤낮없이 일하시는 작가님들 저작권을 어떻게 보호한다는 거지 라는 막연한생각에 한번 간단히 찾아봤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;간단히 찾아 본 Frequency Method 방식 으로 3개가 있네요.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Attack 방법에 대해서 일반적으로 알려진 방법을 사용해보도&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하겠습니다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아래 알고리즘들에 대해서 문뜩 필살기처럼 회피할 아이디어가 번뜩이지만, 조용히 테스트만 해보도록 하겠습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 첫 번째 이야기를 진행하겠습니다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Serif KR';&quot;&gt;DWT-DCT 알고리즘을 통한 watermarking 이미지 embedding - extraction 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Frequency Method ]&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&amp;nbsp; DWT-DCT&amp;nbsp; (첫번째 시리즈)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;- DWT-DCT-SVD&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;- DWT-DCT-SIFT&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;[ Deep Learning GAN Method]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://github.com/ShieldMnt/invisible-watermark#rivagan-experimental&quot;&gt;&lt;b&gt;rivaGan&lt;/b&gt;&lt;/a&gt;: encoder/decoder model with Attention mechanism + embed watermark bits into vector.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;[ 검색 ] 역시 구글링 첫 번째 논문에 DWT-DCT image watermarking 이 나오네요&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;[ 결론 ] 여러분 함부로 캡처하지 마세요. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7; font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;(Crop 에 취약하지만, 여러분 2007년 나온겁니다.!! 해결책이 있겠죠)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-color: #259ce0; border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; line-height: 1.1; font-family: 'Nanum Gothic'; vertical-align: baseline; position: relative; border-radius: 4px;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;145&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kTTFp/btreKxpNV9v/EVm2WDDlL5lk5rOMP501a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kTTFp/btreKxpNV9v/EVm2WDDlL5lk5rOMP501a1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kTTFp/btreKxpNV9v/EVm2WDDlL5lk5rOMP501a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkTTFp%2FbtreKxpNV9v%2FEVm2WDDlL5lk5rOMP501a1%2Fimg.png&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;145&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Combined DWT-DCT Digital Image Watermarking (2007)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Abstract: The proliferation of digitized media due to the rapid growth of networked multimedia systems, has created an urgent need for copyright enforcement technologies that can protect copyright ownership of multimedia objects. Digital image watermarking is one such technology that has been developed to protect digital images from illegal manipulations. In particular, digital image watermarking algorithms which are based on the discrete wavelet transform have been widely recognized to be more prevalent than others. This is due to the wavelets' excellent spatial localization, frequency spread, and multi-resolution characteristics, which are similar to the theoretical models of the human visual system. In this paper, we describe an imperceptible and a robust combined DWT-DCT digital image watermarking algorithm. The algorithm watermarks a given digital image using a combination of the Discrete Wavelet Transform (DWT) and the Discrete Cosine Transform (DCT). Performance evaluation results show that combining the two transforms improved the performance of the watermarking algorithms that are based solely on the DWT transform.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;참고로 2007년에 나온 논문인데 인용수가 많은 걸 보고 이거구나 하는 생각에 한번 개략적인 컨셉만 보고 따라해봤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;u&gt;&lt;b&gt;(** 지금이 2021년,, 14년전 에 나온 논문입니다.)&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정확히 전부를 이해하기 위해서는 DCT, DWT 라는 transform 에 대해서 이해를 해야 되는데 추후 업데이트를 해서 자세히 써보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;discrete cosine transform (DCT)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;discrete wavelet transform (DWT)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;준비1. watermark 이미지&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;(실제로 사용 프로그램에서는 watermark 이미지를 직접 쓰는일이 없고 암호화/복호화를 통해서 여러분이 추출을 시도해보려고 해도 힘들도록 만들어져 있습니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;104&quot; data-origin-height=&quot;34&quot; data-filename=&quot;watermark.jpg&quot; width=&quot;297&quot; height=&quot;97&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blAg78/btreJhuMnxR/ADCcdXhS4DzqkaYHze619K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blAg78/btreJhuMnxR/ADCcdXhS4DzqkaYHze619K/img.jpg&quot; data-alt=&quot;Watermark Image&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blAg78/btreJhuMnxR/ADCcdXhS4DzqkaYHze619K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblAg78%2FbtreJhuMnxR%2FADCcdXhS4DzqkaYHze619K%2Fimg.jpg&quot; data-origin-width=&quot;104&quot; data-origin-height=&quot;34&quot; data-filename=&quot;watermark.jpg&quot; width=&quot;297&quot; height=&quot;97&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Watermark Image&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;준비2. 샘플 이미지&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;680&quot; data-filename=&quot;sample.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZAukI/btreLLulPj4/b4gPfOIPpEkPghn47hOU91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZAukI/btreLLulPj4/b4gPfOIPpEkPghn47hOU91/img.png&quot; data-alt=&quot;Sample Image&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZAukI/btreLLulPj4/b4gPfOIPpEkPghn47hOU91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZAukI%2FbtreLLulPj4%2Fb4gPfOIPpEkPghn47hOU91%2Fimg.png&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;680&quot; data-filename=&quot;sample.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Sample Image&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;Embedding&amp;nbsp; 과정&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;461&quot; data-filename=&quot;embedding_procedure.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/43boR/btreLKvryLR/6gk7chk1nKBnp2qyIM0dlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/43boR/btreLKvryLR/6gk7chk1nKBnp2qyIM0dlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/43boR/btreLKvryLR/6gk7chk1nKBnp2qyIM0dlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F43boR%2FbtreLKvryLR%2F6gk7chk1nKBnp2qyIM0dlK%2Fimg.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;461&quot; data-filename=&quot;embedding_procedure.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;손쉽게 말하면 DWT 를 통해 얻어진 이미지에 watermark 이미지를 잘 녹여내고 이를 다시 Inverse DWT를 통하면 원본 이미지와 비슷하면서도 watermark 를 뽑아 낼 수 있는 그림이 완성이 됩니다.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;Extraction 과정&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;477&quot; data-filename=&quot;extract_procedure.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TvkSR/btreKmvh9gb/7m4wNkzJlARYLHDHNn9rM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TvkSR/btreKmvh9gb/7m4wNkzJlARYLHDHNn9rM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TvkSR/btreKmvh9gb/7m4wNkzJlARYLHDHNn9rM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTvkSR%2FbtreKmvh9gb%2F7m4wNkzJlARYLHDHNn9rM1%2Fimg.png&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;477&quot; data-filename=&quot;extract_procedure.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Embedding 이미지가 오염되거나 변경, 변화가 생겨도 이를 잘 변환하면 원래의 watermark 이미지를 뽑아 낼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결론적으로 DWT-DCT 알고리즘 경우 crop /&amp;nbsp; affine transform 에 취약하네요. 그외 공격에는 그럭저럭 괜찮습니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;(추출된 watermark 이미지 경우 아래처럼 노이즈가 섞여 있어서 이를 다시 denoising 하기 위한 딥러닝 모델을 통해 digital 로 바꾸는 무언가를 할 필요가 있을 것 같네요. - &lt;b&gt;기회가 되면 이것도 다루겠습니다.&lt;/b&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 136px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Attack&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Image&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;Extraction(watermark)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Embedding (Initial)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/egC9LQ/btrfXHSjON4/6zjaL2N7kCXTVoNKnggof1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/egC9LQ/btrfXHSjON4/6zjaL2N7kCXTVoNKnggof1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/egC9LQ/btrfXHSjON4/6zjaL2N7kCXTVoNKnggof1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FegC9LQ%2FbtrfXHSjON4%2F6zjaL2N7kCXTVoNKnggof1%2Fimg.jpg&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sP3E9/btrfU5GEvuH/RUYMTVvhni6iTkbVoN7YBK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sP3E9/btrfU5GEvuH/RUYMTVvhni6iTkbVoN7YBK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sP3E9/btrfU5GEvuH/RUYMTVvhni6iTkbVoN7YBK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsP3E9%2FbtrfU5GEvuH%2FRUYMTVvhni6iTkbVoN7YBK%2Fimg.jpg&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Gaussian Blur&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXXsm6/btrfWMNBpDY/p8hmX1kSYzUQlrfuKk6P0K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXXsm6/btrfWMNBpDY/p8hmX1kSYzUQlrfuKk6P0K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXXsm6/btrfWMNBpDY/p8hmX1kSYzUQlrfuKk6P0K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXXsm6%2FbtrfWMNBpDY%2Fp8hmX1kSYzUQlrfuKk6P0K%2Fimg.jpg&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdYnKO/btrfVqDKmPY/ypSsBeTysa5aILDkWyjQJ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdYnKO/btrfVqDKmPY/ypSsBeTysa5aILDkWyjQJ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdYnKO/btrfVqDKmPY/ypSsBeTysa5aILDkWyjQJ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdYnKO%2FbtrfVqDKmPY%2FypSsBeTysa5aILDkWyjQJ1%2Fimg.jpg&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Histogram Equalization&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtI1J4/btrf7zTsNbN/4JZB3HlbCbgnPx0NU1uW1K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtI1J4/btrf7zTsNbN/4JZB3HlbCbgnPx0NU1uW1K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtI1J4/btrf7zTsNbN/4JZB3HlbCbgnPx0NU1uW1K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdtI1J4%2Fbtrf7zTsNbN%2F4JZB3HlbCbgnPx0NU1uW1K%2Fimg.jpg&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mKv7e/btrfXzmXrz6/2AvmZit3gdlV3R56Hs8kZk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mKv7e/btrfXzmXrz6/2AvmZit3gdlV3R56Hs8kZk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mKv7e/btrfXzmXrz6/2AvmZit3gdlV3R56Hs8kZk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmKv7e%2FbtrfXzmXrz6%2F2AvmZit3gdlV3R56Hs8kZk%2Fimg.jpg&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Rotation (Left 90)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uw79w/btrfWNlo16q/M8kzTiQ29hRw47bazzTbi0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uw79w/btrfWNlo16q/M8kzTiQ29hRw47bazzTbi0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uw79w/btrfWNlo16q/M8kzTiQ29hRw47bazzTbi0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuw79w%2FbtrfWNlo16q%2FM8kzTiQ29hRw47bazzTbi0%2Fimg.jpg&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6J6PX/btrf5iqU4ib/XKTLYp8CDkg21mFUjzT1J0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6J6PX/btrf5iqU4ib/XKTLYp8CDkg21mFUjzT1J0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6J6PX/btrf5iqU4ib/XKTLYp8CDkg21mFUjzT1J0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6J6PX%2Fbtrf5iqU4ib%2FXKTLYp8CDkg21mFUjzT1J0%2Fimg.jpg&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Rotation (Right 90)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CprM9/btrf1h0mrIn/7xLFVawWkMclKhGRirpw50/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CprM9/btrf1h0mrIn/7xLFVawWkMclKhGRirpw50/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CprM9/btrf1h0mrIn/7xLFVawWkMclKhGRirpw50/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCprM9%2Fbtrf1h0mrIn%2F7xLFVawWkMclKhGRirpw50%2Fimg.jpg&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wD64e/btrfZqDf5Us/NG3xjrdBz9mHmZYB3VrEhk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wD64e/btrfZqDf5Us/NG3xjrdBz9mHmZYB3VrEhk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wD64e/btrfZqDf5Us/NG3xjrdBz9mHmZYB3VrEhk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwD64e%2FbtrfZqDf5Us%2FNG3xjrdBz9mHmZYB3VrEhk%2Fimg.jpg&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Random Noise (&lt;span style=&quot;color: #202124;&quot;&gt;&amp;plusmn; 10&lt;/span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cs0SDs/btrf7ALBfJ8/dKkMj2O4ERk9y0c2vG4pXK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cs0SDs/btrf7ALBfJ8/dKkMj2O4ERk9y0c2vG4pXK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cs0SDs/btrf7ALBfJ8/dKkMj2O4ERk9y0c2vG4pXK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcs0SDs%2Fbtrf7ALBfJ8%2FdKkMj2O4ERk9y0c2vG4pXK%2Fimg.jpg&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;2048&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAQLi5/btrfVtOtvO0/zOhSKV52OLVViXGUl6qRGk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAQLi5/btrfVtOtvO0/zOhSKV52OLVViXGUl6qRGk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAQLi5/btrfVtOtvO0/zOhSKV52OLVViXGUl6qRGk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAQLi5%2FbtrfVtOtvO0%2FzOhSKV52OLVViXGUl6qRGk%2Fimg.jpg&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 24.9612%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Resize&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1638&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A0rUx/btrfU6lenU0/FrHHDZUK9D7QpMScdw9Bn0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A0rUx/btrfU6lenU0/FrHHDZUK9D7QpMScdw9Bn0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A0rUx/btrfU6lenU0/FrHHDZUK9D7QpMScdw9Bn0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA0rUx%2FbtrfU6lenU0%2FFrHHDZUK9D7QpMScdw9Bn0%2Fimg.jpg&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1638&quot; data-filename=&quot;img (1).jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhAyI4/btrf1ikEhGO/8AkLPw65cdMZi46g5TRmdK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhAyI4/btrf1ikEhGO/8AkLPw65cdMZi46g5TRmdK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhAyI4/btrf1ikEhGO/8AkLPw65cdMZi46g5TRmdK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhAyI4%2Fbtrf1ikEhGO%2F8AkLPw65cdMZi46g5TRmdK%2Fimg.jpg&quot; data-origin-width=&quot;128&quot; data-origin-height=&quot;128&quot; data-filename=&quot;img.jpg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Python code&lt;/span&gt; &lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;아래 2개의 함수는 상황에 따라 조정을 해야되서 기존에서 수정을 진행하도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;_ebmed_logic&lt;/li&gt;
&lt;li&gt;_extract_logic&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;# https://github.com/diptamath/DWT-DCT-Digital-Image-Watermarking
# https://thescipub.com/pdf/jcssp.2007.740.746.pdf

import os
import cv2

import pywt
import numpy as np
from scipy.fftpack import dct, idct

import matplotlib.pyplot as plt


class WaterMark(object):
    &quot;&quot;&quot;
    
    &quot;&quot;&quot;
    def __init__(self, img_shape=2048, mark_shape=128, level=1):
        self.img_shape = img_shape
        self.mark_shape = mark_shape
        self.level = level
        self.kernel = 8
        self.model = 'haar'
        
    def __repr__(self):
        return f'version 0.0.1'
    
    def _load(self, img_path: str, size: int):
        img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
        img = img.astype(np.float32)/255.0
        
        # size x size
        img = cv2.resize(img, (size, size), interpolation=cv2.INTER_CUBIC)
        return img
    
    def _dct_transform(self, img, inverse=False):
        
        h, w = img.shape[:2]
        buffer = np.zeros_like(img)
        trans_func = idct if inverse else dct
        
        for r in range(0, h, self.kernel):
            for c in range(0, w, self.kernel):
                subpixels = img[r:r+self.kernel, c:c+self.kernel]
                buffer[r:r+self.kernel, c:c+self.kernel] = trans_func(
                    trans_func(subpixels.T, norm=&quot;ortho&quot;).T, norm=&quot;ortho&quot;)
        return buffer
  
        
    
    def _embed_logic(self, mark, img):
        &quot;&quot;&quot;
        // TODO: Implementation your logic
        &quot;&quot;&quot;        
        return img        
        
    
    def embedding(self, img_path: str, mark_path: str):
        img = self._load(img_path, self.img_shape)
        mark =  self._load(mark_path, self.mark_shape)
        
        # [cAn, (cHn, cVn, cDn)
        coeffs = pywt.wavedec2(img, self.model, level=self.level)
        
        dct_cAn = self._dct_transform(coeffs[0])
        dct_cAn = self._embed_logic(mark, dct_cAn)
        coeffs[0] = self._dct_transform(dct_cAn, inverse=True)
                
        embed_img = pywt.waverec2(coeffs, self.model)
        embed_img = cv2.normalize(embed_img, None, 0, 255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)
        return embed_img
    
    def extract(self, img_path: str):
        img = self._load(img_path, self.img_shape)
        
        # [cAn, (cHn, cVn, cDn)
        coeffs = pywt.wavedec2(img, self.model, level=self.level)        
        dct_cAn = self._dct_transform(coeffs[0])
        mark_img = self._extract_logic(dct_cAn)
        mark_img = cv2.normalize(mark_img, None, 0, 255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)
        return mark_img
    
        
    def _extract_logic(self, img):
        &quot;&quot;&quot;
        // TODO: Implementation your logic
        &quot;&quot;&quot;
        return mark_img
    
if __name__ == '__main__':
    wm = WaterMark()
    img = wm.embedding('sample_2048.jpg', 'watermark.jpg')
    cv2.imwrite('sample_embed.jpg', img)

    mark = wm.extract('sample_embed.jpg')
    cv2.imwrite('extract_mark.jpg', mark)
    
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;yellow&quot; style=&quot;box-sizing: border-box; margin: 0px; padding: 0.5em; border: 1px solid #baa900; font-variant-numeric: inherit; font-stretch: inherit; font-size: 16px; line-height: 1.75rem; font-family: 'Nanum Gothic'; vertical-align: baseline; border-radius: 4px; background-color: #fffdeb;&quot;&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 0px; padding: 0.5em; border: 0px; font-style: inherit; font-variant: inherit; font-stretch: inherit; font-size: 1rem; line-height: 1.75rem; vertical-align: baseline;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;box-sizing: border-box; margin: 0px; padding: 0px; border: 0px; font-stretch: normal; font-size: 1.33333em; line-height: 0.75em; font-family: FontAwesome; vertical-align: -15%; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased;&quot; class=&quot;fa fa-check fa-lg&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic'; font-size: 12pt;&quot;&gt;&amp;nbsp;Distortion Image [ Next ,, 못잡을 것 같지 ? ]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;과연 모든 화질을 포기하고 캡쳐를 했을 때 피할 수 있을까요 ? Hint 이미지에 특징점은 쉽게 바뀌지 않아요&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;686&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czNbb1/btreJZ7WMwd/04NFXoJ73TkuOdDnlYZyg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czNbb1/btreJZ7WMwd/04NFXoJ73TkuOdDnlYZyg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czNbb1/btreJZ7WMwd/04NFXoJ73TkuOdDnlYZyg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczNbb1%2FbtreJZ7WMwd%2F04NFXoJ73TkuOdDnlYZyg0%2Fimg.png&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;686&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;참고&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/diptamath/DWT-DCT-Digital-Image-Watermarking&quot;&gt;https://github.com/diptamath/DWT-DCT-Digital-Image-Watermarking&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;figure id=&quot;og_1631292611861&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - diptamath/DWT-DCT-Digital-Image-Watermarking: A digital image watermarking algorithm based on combining two transforms;&quot; data-og-description=&quot;A digital image watermarking algorithm based on combining two transforms; DWT and DCT. - GitHub - diptamath/DWT-DCT-Digital-Image-Watermarking: A digital image watermarking algorithm based on combi...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/diptamath/DWT-DCT-Digital-Image-Watermarking&quot; data-og-url=&quot;https://github.com/diptamath/DWT-DCT-Digital-Image-Watermarking&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gD9pz/hyLy0fgjgX/e084hLJZGoamZsWOOeuOV0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/diptamath/DWT-DCT-Digital-Image-Watermarking&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/diptamath/DWT-DCT-Digital-Image-Watermarking&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gD9pz/hyLy0fgjgX/e084hLJZGoamZsWOOeuOV0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - diptamath/DWT-DCT-Digital-Image-Watermarking: A digital image watermarking algorithm based on combining two transforms;&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A digital image watermarking algorithm based on combining two transforms; DWT and DCT. - GitHub - diptamath/DWT-DCT-Digital-Image-Watermarking: A digital image watermarking algorithm based on combi...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>영상처리</category>
      <category>Digital watermarking</category>
      <category>DWT-DCT</category>
      <category>네이버웹툰</category>
      <category>캡처방지</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/104</guid>
      <comments>https://roadcom.tistory.com/104#entry104comment</comments>
      <pubDate>Sat, 11 Sep 2021 01:33:39 +0900</pubDate>
    </item>
    <item>
      <title>Minimum Volume Enclosing Ellipsoid</title>
      <link>https://roadcom.tistory.com/102</link>
      <description>&lt;p&gt;&lt;span&gt;1 &lt;a href=&quot;http://stackoverflow.com/questions/1768197/bounding-ellipse/1768440#1768440&quot;&gt;http://stackoverflow.com/questions/1768197/bounding-ellipse/1768440#1768440&lt;/a&gt; (stack)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;2 &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.116.7691&quot;&gt;http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.116.7691&lt;/a&gt; (document)&lt;/p&gt;
&lt;p&gt;3 &lt;a href=&quot;https://gist.github.com/Gabriel-p/4ddd31422a88e7cdf953&quot;&gt;https://gist.github.com/Gabriel-p/4ddd31422a88e7cdf953&lt;/a&gt; (python mvee code)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$ {(x_i -c)}^TE{(x_i -c)} \leq 1 \hspace{10mm} i=1,...,m $&lt;/p&gt;
&lt;p&gt;$Vol(\varepsilon) = {v_0 \over \sqrt{det(E)}} = v_0 det(E^{-1})^{1 \over 2}$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;document 를 참조하면 center form 을 이용하여 convex function 으로 변환 후 이를 이용하여&lt;/p&gt;
&lt;p&gt;Largrange dual problem 을 가정하여 최적화를 진행하는 방식입니다. 세부 수식은 2 document 를 참조하셔야 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;result.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;465&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A1yXg/btqSLHGQGLU/kYHUlUEQwIhnIt7Qha0Yk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A1yXg/btqSLHGQGLU/kYHUlUEQwIhnIt7Qha0Yk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A1yXg/btqSLHGQGLU/kYHUlUEQwIhnIt7Qha0Yk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA1yXg%2FbtqSLHGQGLU%2FkYHUlUEQwIhnIt7Qha0Yk1%2Fimg.png&quot; data-filename=&quot;result.png&quot; data-origin-width=&quot;827&quot; data-origin-height=&quot;465&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;

import numpy as np
import numpy.linalg as la
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse

import cv2

def mvee(points, tol = 0.01):
    &quot;&quot;&quot;
    Finds the ellipse equation in &quot;center form&quot;
    (x-c).T * A * (x-c) = 1
    &quot;&quot;&quot;
    N, d = points.shape
    Q = np.column_stack((points, np.ones(N))).T
    err = tol+1.0
    u = np.ones(N)/N
    while err &amp;gt; tol:
        # assert u.sum() == 1 # invariant
        X = np.dot(np.dot(Q, np.diag(u)), Q.T)
        M = np.diag(np.dot(np.dot(Q.T, la.inv(X)), Q))
        jdx = np.argmax(M)
        step_size = (M[jdx]-d-1.0)/((d+1)*(M[jdx]-1.0))
        new_u = (1-step_size)*u
        new_u[jdx] += step_size
        err = la.norm(new_u-u)
        u = new_u
    c = np.dot(u,points)        
    A = la.inv(np.dot(np.dot(points.T, np.diag(u)), points)
               - np.multiply.outer(c,c))/d
    return A, c

img = cv2.imread('/home/roadcom/Downloads/partial_ellipse.jpeg', cv2.IMREAD_GRAYSCALE)

ret, th = cv2.threshold(img,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)

conts, _ = cv2.findContours(th,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

# max bloc filter
max_blob_id = np.argmax([cv2.contourArea(p) for p in conts])

A, centroid = mvee(np.squeeze(conts[max_blob_id]))
U, D, V = la.svd(A)

# x, y radii.
rx, ry = 1./np.sqrt(D)
major, minor = max(rx,ry), min(rx,ry)
    
cxy = tuple(np.int0(centroid))
aixs = tuple(np.int0([major, minor]))

arcsin = -1. * np.rad2deg(np.arcsin(V[0][0]))
arccos = np.rad2deg(np.arccos(V[0][1]))

# Orientation angle (with respect to the x axis counterclockwise).
alpha = arccos if arcsin &amp;gt; 0. else -1. * arccos

rst_img = cv2.ellipse(img.copy(), cxy, aixs, alpha, 0, 360,(255,255,255),3)
B, G, R = cv2.split(rst_img) 
matplot_img = cv2.merge([R,G,B])

fig, axs = plt.subplots(1,2, figsize=(16,8))
axs[0].imshow(img, interpolation='quadric')
axs[0].set_title('Origin[B,G,R]')
axs[0].axis('off')

axs[1].imshow(matplot_img, interpolation='quadric')
axs[1].set_title('MVEE')
axs[1].axis('off')

&lt;/code&gt;&lt;/pre&gt;</description>
      <category>영상처리</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/102</guid>
      <comments>https://roadcom.tistory.com/102#entry102comment</comments>
      <pubDate>Fri, 23 Oct 2020 22:57:31 +0900</pubDate>
    </item>
    <item>
      <title>[keras] GAN 이해 및 구현</title>
      <link>https://roadcom.tistory.com/97</link>
      <description>&lt;p&gt;Generative Adversarial Network&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;■ minimax problem&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;$\underset{G}{min}\, \underset{D}{max} V(D, G)&amp;nbsp; = \mathbb{E}_{x \sim P_{\text{data}}(x)} \big[ \log D(x) \big] + \mathbb{E}_{z \sim P_{z}(z)} \big[ \log (1-D(G(z)) \big]$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ Discriminator&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;$maximize\quad J^{(D)}=&amp;nbsp;&amp;nbsp;\mathbb{E}_{x \sim P_{\text{data}}(x)} \big[ \log D(x) \big] + \mathbb{E}_{z \sim P_{z}(z)} \big[ \log (1-D(G(z)) \big]$&lt;/p&gt;
&lt;p&gt;$\frac{1}{N}\sum_{i=1}^{N}{&amp;nbsp;y^{i}\,log(\hat{y_{i}})&amp;nbsp;+&amp;nbsp;(1-y^{i})\,log(1-&amp;nbsp;\hat{y_{i}})}&amp;nbsp; &lt;br /&gt;=&amp;nbsp;-H(p,&amp;nbsp;D)$&lt;/p&gt;
&lt;p&gt;$minimize\quad&amp;nbsp;&amp;nbsp;H(p,D)&amp;nbsp;=&amp;nbsp;-&amp;nbsp;\frac{1}{N}\sum_{i=1}^{N}{&amp;nbsp;y^{i}\,log(\hat{y_{i}})&amp;nbsp;+&amp;nbsp;(1-y^{i})\,log(1-&amp;nbsp;\hat{y_{i}})}$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■ Generator&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;$minimize\quad J^{(G)} = \mathbb{E}_{z \sim P_{z}(z)} \big[ \log (1-D(G(z)) \big]$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;[ heuristic method ]&lt;/blockquote&gt;
&lt;p&gt;학습 초반, discriminator 의 학습이 훨씬 빨리 되기 때문에, D(G(z)) 의 값은 대부분 0에 가까워지게 됩니다.&lt;/p&gt;
&lt;p&gt;즉, gradient vanishing 이 발생하게 됩니다.&lt;/p&gt;
&lt;p&gt;$\nabla_{\theta_{g}} \frac{1}{m} \sum_{i=1}^{m}\log(1-D(G(z^{i})))\nabla_{\theta_{g}}&amp;nbsp;\frac{1}{m}&amp;nbsp;\sum_{i=1}^{m}\log(1-D(G(z^{i})))\approx&amp;nbsp;0$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이를 해결하고자 다음의 방법이 많이 사용됩니다.&lt;/p&gt;
&lt;p&gt;$maximize\quad&amp;nbsp;J^{(G)}&amp;nbsp;=&amp;nbsp;\mathbb{E}_{z&amp;nbsp;\sim&amp;nbsp;P_{z}(z)}&amp;nbsp;\Big[\log&amp;nbsp;D(G(z))\Big]$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A4Hv1/btqBkqipTiP/RXtAKVsYBdl9xle6Nr4Cf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A4Hv1/btqBkqipTiP/RXtAKVsYBdl9xle6Nr4Cf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A4Hv1/btqBkqipTiP/RXtAKVsYBdl9xle6Nr4Cf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA4Hv1%2FbtqBkqipTiP%2FRXtAKVsYBdl9xle6Nr4Cf0%2Fimg.png&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;596&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;참조&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b&quot;&gt;https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1579432483652&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;GAN &amp;mdash; Why it is so hard to train Generative Adversarial Networks!&quot; data-og-description=&quot;It is easier to recognize a Monet&amp;rsquo;s painting than drawing one. Generative models (creating data) are considered much harder comparing with&amp;hellip;&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b&quot; data-og-url=&quot;https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fIhtT/hyEC2dBRrB/lemN6NnOrjkMkBKpVzQhd1/img.jpg?width=1200&amp;amp;height=717&amp;amp;face=0_0_1200_717,https://scrap.kakaocdn.net/dn/Dp6KC/hyECXpQSnq/H1iGQZlSepROk4t7AsOVGK/img.jpg?width=60&amp;amp;height=27&amp;amp;face=0_0_60_27,https://scrap.kakaocdn.net/dn/GbHeb/hyEEMAdnid/83AdVtW2Z9lfA7k6yByro0/img.jpg?width=60&amp;amp;height=35&amp;amp;face=0_0_60_35&quot;&gt;&lt;a href=&quot;https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fIhtT/hyEC2dBRrB/lemN6NnOrjkMkBKpVzQhd1/img.jpg?width=1200&amp;amp;height=717&amp;amp;face=0_0_1200_717,https://scrap.kakaocdn.net/dn/Dp6KC/hyECXpQSnq/H1iGQZlSepROk4t7AsOVGK/img.jpg?width=60&amp;amp;height=27&amp;amp;face=0_0_60_27,https://scrap.kakaocdn.net/dn/GbHeb/hyEEMAdnid/83AdVtW2Z9lfA7k6yByro0/img.jpg?width=60&amp;amp;height=35&amp;amp;face=0_0_60_35');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;GAN &amp;mdash; Why it is so hard to train Generative Adversarial Networks!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;It is easier to recognize a Monet&amp;rsquo;s painting than drawing one. Generative models (creating data) are considered much harder comparing with&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>딥러닝</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/97</guid>
      <comments>https://roadcom.tistory.com/97#entry97comment</comments>
      <pubDate>Sun, 19 Jan 2020 19:22:21 +0900</pubDate>
    </item>
    <item>
      <title>[keras] ResNet (residual block)</title>
      <link>https://roadcom.tistory.com/95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;■&amp;nbsp; Degradation 문제&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Deep Residual Learning for Image Recognition 논문을 보면 시작은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;56-layer를 사용하면 이론적으로 더 error 가 낮아야 하지만, 20-layer 보다 더 높은 값을 나타내고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 다시말하면 layer가 깊어질수록 overfitting 의 문제가 아닌, training error 가 증가한다는 말로&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크가 학습이 잘 진행이 되지 않는다는 것을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;resnet_training_test_error.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;217&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHZE3n/btqA8jpxNA3/NM0BaRnESVTpnTkpFsVJgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHZE3n/btqA8jpxNA3/NM0BaRnESVTpnTkpFsVJgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHZE3n/btqA8jpxNA3/NM0BaRnESVTpnTkpFsVJgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHZE3n%2FbtqA8jpxNA3%2FNM0BaRnESVTpnTkpFsVJgK%2Fimg.png&quot; data-filename=&quot;resnet_training_test_error.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;217&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■&amp;nbsp; Shortcut connection (skip connection)&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Degradation 문제를 해결하기 위해 논문에서 제안한 방법이 shutcut connection 이란 방법으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gradient 를 유지할 수 있도록 shorcut을 만든 다는 것이 핵심입니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;284&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LIczC/btqA8iRHkon/XF3seHjDOlsAkvs2nrVSW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LIczC/btqA8iRHkon/XF3seHjDOlsAkvs2nrVSW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LIczC/btqA8iRHkon/XF3seHjDOlsAkvs2nrVSW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLIczC%2FbtqA8iRHkon%2FXF3seHjDOlsAkvs2nrVSW1%2Fimg.png&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;284&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$y_{l} = h(x_l) + F(x_l, W_l) \qquad h:identity mapping,\quad x: input $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$x_{l+1}&amp;nbsp;=&amp;nbsp;f(y_{l})&amp;nbsp;\qquad&amp;nbsp;x_{l+1}:output,&amp;nbsp;\quad&amp;nbsp;f:&amp;nbsp;activation&amp;nbsp;function$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: 12pt; box-sizing: border-box; margin: 0px; padding: 0.125em 0.25em; border: 1px solid #999999; font-stretch: inherit; line-height: inherit; vertical-align: baseline; background-color: #f5f5f5; border-radius: 4px;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;일반화&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$x_{l+2}&amp;nbsp;=&amp;nbsp;x_{l+1}&amp;nbsp;+&amp;nbsp;F(x_{l+1},&amp;nbsp;W_{l+1})&amp;nbsp;=&amp;nbsp;x_{l}&amp;nbsp;+&amp;nbsp;F(x_{l},&amp;nbsp;W_{l})&amp;nbsp;+&amp;nbsp;F(x_{l+1},W_{l+1})=&amp;nbsp;x_l+&amp;nbsp;\dots&amp;nbsp;+$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$x_{L}&amp;nbsp;=&amp;nbsp;x_{l}&amp;nbsp;+&amp;nbsp;\sum_{i=1}^{L-1}F(x_i,W_i)$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: 12pt; box-sizing: border-box; margin: 0px; padding: 0.125em 0.25em; border: 1px solid #999999; font-stretch: inherit; line-height: inherit; vertical-align: baseline; background-color: #f5f5f5; border-radius: 4px;&quot;&gt; 역전파(Back propagation)&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$\frac{\partial&amp;nbsp;\varepsilon&amp;nbsp;}{\partial&amp;nbsp;x_l}&amp;nbsp;=&amp;nbsp;\frac{\partial&amp;nbsp;\varepsilon&amp;nbsp;}{\partial&amp;nbsp;x_L}&amp;nbsp;\frac{\partial&amp;nbsp;x_L&amp;nbsp;}{\partial&amp;nbsp;x_l}&amp;nbsp;=&amp;nbsp;\frac{\partial&amp;nbsp;\varepsilon&amp;nbsp;}{\partial&amp;nbsp;x_L}&amp;nbsp;(1&amp;nbsp;+&amp;nbsp;\frac{\partial}{\partial&amp;nbsp;x_l}\sum_{i=1}^{L-1}F(x_i,W_i))$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ (1 + \frac{\partial}{\partial x_l}\sum_{i=1}^{L-1}F(x_i,W_i)) $ 왼쪽 항과 오른쪽 항으로 구분되게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mini batch 로 진행된다고 가정하면 실제 오른쪽 항이 전부 -1을 만족하는 경우가 거의 없기에 Gradient 값이 유지됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■&amp;nbsp; Identity Block / Convolutional Block&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr style=&quot;margin: 20px auto 0px; border: none; cursor: pointer !important; z-index: 1; font-size: 0px; line-height: 0; background: url('../image/divider-line.svg') center -208px / 200px 420px repeat-x; height: 2px; padding: 21px 0px; color: #333333; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: 12pt; box-sizing: border-box; margin: 0px; padding: 0.125em 0.25em; border: 1px solid #999999; font-stretch: inherit; line-height: inherit; vertical-align: baseline; background-color: #f5f5f5; border-radius: 4px;&quot;&gt;&lt;span&gt; Identity Block &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shortcut 의 channel 과 main path 의 channel 이 일치할 경우 단순 add 연산만 진행하는 블록을 identity block 이라고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;residual_block.png&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;312&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PhCBs/btqA4zOcyyg/kzoPSCgt9K1krcw3faatvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PhCBs/btqA4zOcyyg/kzoPSCgt9K1krcw3faatvK/img.png&quot; data-alt=&quot;Identity Block&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PhCBs/btqA4zOcyyg/kzoPSCgt9K1krcw3faatvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPhCBs%2FbtqA4zOcyyg%2FkzoPSCgt9K1krcw3faatvK%2Fimg.png&quot; data-filename=&quot;residual_block.png&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;312&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Identity Block&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: 12pt; box-sizing: border-box; margin: 0px; padding: 0.125em 0.25em; border: 1px solid #999999; font-stretch: inherit; line-height: inherit; vertical-align: baseline; background-color: #f5f5f5; border-radius: 4px;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Convolution Block&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shortcut 의 channel 과 main path 의 channel 이 다를 경우 shortcut path 를 적절히 변환해주는 작업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, projection 을 통해 channel 을 맞춰주는 작업이(projection shortcut) 추가되기에 이를 convolution block 이라고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;convolution_block.png&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;382&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yDNEu/btqA57jiiSS/KqC1WNIyo3Kr1Ykjj92S50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yDNEu/btqA57jiiSS/KqC1WNIyo3Kr1Ykjj92S50/img.png&quot; data-alt=&quot;Convoltional Block&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yDNEu/btqA57jiiSS/KqC1WNIyo3Kr1Ykjj92S50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyDNEu%2FbtqA57jiiSS%2FKqC1WNIyo3Kr1Ykjj92S50%2Fimg.png&quot; data-filename=&quot;convolution_block.png&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;382&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Convoltional Block&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: 12pt; box-sizing: border-box; margin: 0px; padding: 0.125em 0.25em; border: 1px solid #999999; font-stretch: inherit; line-height: inherit; vertical-align: baseline; background-color: #f5f5f5; border-radius: 4px;&quot;&gt;&lt;span&gt;&lt;span&gt; Resnet-50 Structure&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;resnet_50.png&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;284&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVLhWc/btqA2VjViK4/Mk9K0AyVhprf6HiI4JK0UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVLhWc/btqA2VjViK4/Mk9K0AyVhprf6HiI4JK0UK/img.png&quot; data-alt=&quot;Total Structure of ResNet-50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVLhWc/btqA2VjViK4/Mk9K0AyVhprf6HiI4JK0UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVLhWc%2FbtqA2VjViK4%2FMk9K0AyVhprf6HiI4JK0UK%2Fimg.png&quot; data-filename=&quot;resnet_50.png&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;284&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Total Structure of ResNet-50&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 그림 출처: &lt;a href=&quot;https://github.com/YBIGTA/DeepNLP-Study/wiki/Day-02-Paper-Review:-ResNet&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/YBIGTA/DeepNLP-Study/wiki/Day-02-Paper-Review:-ResNet&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://arxiv.org/pdf/1512.03385.pdf&quot;&gt;https://arxiv.org/pdf/1512.03385.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;■&amp;nbsp; Residual Block (Keras)&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre class=&quot;llvm&quot;&gt;&lt;code&gt;
from keras import layers

def residual_block(x, filters_in, filters_out, k_size):
    shortcut = x
    x = layers.Conv2D(filters_in, kernel_size=(1, 1), strides=(1, 1), padding=&quot;same&quot;)(x)
    x = layers.BatchNormalization()(x)
    x = layers.LeakyReLU()(x)
    
    x = layers.Conv2D(filters_in, kernel_size=(k_size, k_size), strides=(1, 1), padding=&quot;same&quot;)(x)
    x = layers.BatchNormalization()(x)
    x = layers.LeakyReLU()(x)    
    
    x = layers.Conv2D(filters_out, kernel_size=(1, 1), strides=(1, 1), padding=&quot;same&quot;)(x)
    x = layers.BatchNormalization()(x)
    
    shortcut_channel = x.shape.as_list()[-1]
    
    if shortcut_channel != filters_out:
        shortcut = layers.Conv2D(filters_out, kernel_size=(1, 1), strides=(1, 1), padding=&quot;same&quot;)(shortcut)
        
    x = layers.Add()([x, shortcut])
    return layers.LeakyReLU()(x)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>딥러닝</category>
      <category>keras</category>
      <category>Residual Block</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/95</guid>
      <comments>https://roadcom.tistory.com/95#entry95comment</comments>
      <pubDate>Sun, 12 Jan 2020 13:22:46 +0900</pubDate>
    </item>
    <item>
      <title>[python] asyncio, aiohttp web crawling</title>
      <link>https://roadcom.tistory.com/94</link>
      <description>&lt;p&gt;asyncio 와 asiohttp 에 대한 자세한 내용은 구글을 검색을 통해 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;single thread 를 활용한 비동기 프로그래밍 이라고 생각하시면 될 것 같습니다.&lt;/p&gt;
&lt;p&gt;I/O Bound 와 CPU Bound 라는 개념 또한 나오는데 Synchronous(동기) 방식을 사용하면 I/O Bound 성능에 따라서&lt;/p&gt;
&lt;p&gt;프로그램의 속도에 아주 큰 영향을 미치게 됩니다.&lt;/p&gt;
&lt;p&gt;(asyncio 에 대해서 추후 정리하도록 하겠습니다.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;동기 방식을 이용하여 간단히 네이버 금융을 통해서 삼성전자의 주식을 50페이지 정도 조회하게 되면&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1.797 s 의 시간이 소요 됩니다.&lt;/p&gt;
&lt;pre class=&quot;xl&quot;&gt;&lt;code&gt;import requests
import time


url = 'https://finance.naver.com/item/sise_day.nhn?code={code}&amp;amp;page={page}'


def sync_fetch():
    res = [requests.get(url.format(code='005930', page=i))
           for i in range(1, 50)]
    return res


if __name__ == '__main__':

    start = time.time()
    sync_fetch()
    end = time.time()
    print(f&quot;elapsed time = {end - start}s&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;elapsed time = 1.797 &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;비동기 프로그래밍을 통해 똑같은 방식으로 대략 14배 이상이 빨리지는 성능을 얻을 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import aiohttp
import asyncio
import time


async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()


async def main():
    async with aiohttp.ClientSession() as session:

        url = 'https://finance.naver.com/item/sise_day.nhn?code={code}&amp;amp;page={page}'
        futures = [asyncio.ensure_future(fetch(session, url.format(code='005930', page=i)))
                   for i in range(1, 50)]
        res = await asyncio.gather(*futures)
        return res

if __name__ == '__main__':

    loop = asyncio.get_event_loop()
    start = time.time()
    result = loop.run_until_complete(main())
    end = time.time()
    print(f&quot;elapsed time = {end - start}s&quot;)
    loop.close()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;elapsed time = 0.124&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍/python</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/94</guid>
      <comments>https://roadcom.tistory.com/94#entry94comment</comments>
      <pubDate>Mon, 6 Jan 2020 23:42:31 +0900</pubDate>
    </item>
    <item>
      <title>[수정 중] Feature selection</title>
      <link>https://roadcom.tistory.com/88</link>
      <description>&lt;p&gt;ML 과 DL 에서 feature selection 을 이용하는 알고리즘과 해당 내용에 대해서 써볼 예정입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Autoencoder&lt;/p&gt;
&lt;p&gt;Random forest&lt;/p&gt;
&lt;p&gt;PCA&lt;/p&gt;
&lt;p&gt;Machine Learning&lt;/p&gt;
&lt;p&gt;- Filter Method&lt;/p&gt;
&lt;p&gt;&amp;nbsp; (통계 테스트)&lt;/p&gt;
&lt;p&gt;- Wrapper Method&lt;/p&gt;
&lt;p&gt;&amp;nbsp; (Forward Selection, Backward Elimination, Recursive Feature Elimination)&lt;/p&gt;
&lt;p&gt;- Embedded Method&lt;/p&gt;
&lt;p&gt;&amp;nbsp; (LASSO, RIDGE)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;[참고]&amp;nbsp;&lt;a style=&quot;color: #ffffff;&quot; href=&quot;https://sherry-data.tistory.com/12&quot;&gt;https://sherry-data.tistory.com/12&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/88</guid>
      <comments>https://roadcom.tistory.com/88#entry88comment</comments>
      <pubDate>Sat, 3 Aug 2019 23:39:35 +0900</pubDate>
    </item>
    <item>
      <title>Backpropagation 예제 및 구현</title>
      <link>https://roadcom.tistory.com/87</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;150&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGeG46/btqw86gV8r8/DkIs61sNK4RveAUbdOfq81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGeG46/btqw86gV8r8/DkIs61sNK4RveAUbdOfq81/img.png&quot; data-alt=&quot;Reference 오카타니 타카유키, 『딥러닝 제대로 시작하기』, jpub(2016), p58~p63&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGeG46/btqw86gV8r8/DkIs61sNK4RveAUbdOfq81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGeG46%2Fbtqw86gV8r8%2FDkIs61sNK4RveAUbdOfq81%2Fimg.png&quot; width=&quot;150&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Reference 오카타니 타카유키, 『딥러닝 제대로 시작하기』, jpub(2016), p58~p63&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 책을 읽고 코드로 구현하기에 적합하도록 수식을 변경하여 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;keras, tensorflow 등의 라이브러리 없이 numpy 행렬 연산을 통해 직접 feed forward, back propagation 을 구현하여 학습을 할 수 있도록 코드를 구현했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OohQE/btqw1vWztmi/dhnjKgoFZTKfTh8OFCpsV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OohQE/btqw1vWztmi/dhnjKgoFZTKfTh8OFCpsV0/img.png&quot; data-alt=&quot;일반 적인 Perceptron 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OohQE/btqw1vWztmi/dhnjKgoFZTKfTh8OFCpsV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOohQE%2Fbtqw1vWztmi%2FdhnjKgoFZTKfTh8OFCpsV0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;일반 적인 Perceptron 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Perceptron&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;다수의 입력을 받아서 모두 더한 뒤 특정한 함수를 통과시켜 얻은 결과는 아래와 같이 정리할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ u = \sum_{i=1}^{3}{w_i \cdot a_i} + b $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ z = f(u) $&amp;nbsp; f : activation function&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Multiple Layer Perceptron&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;■ 다층 layer를 가지는 퍼셉트론을 도식화 하면 아래와 같은 그림으로 표현 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nXPzc/btqw1tYN34q/jLg5hrUWzSuTIxp6WhF8Ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nXPzc/btqw1tYN34q/jLg5hrUWzSuTIxp6WhF8Ok/img.png&quot; data-alt=&quot;Multiple Layer Perceptron&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nXPzc/btqw1tYN34q/jLg5hrUWzSuTIxp6WhF8Ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnXPzc%2Fbtqw1tYN34q%2FjLg5hrUWzSuTIxp6WhF8Ok%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Multiple Layer Perceptron&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 진행에 앞서 혼동이 되지 않도록 수식에 대해 정의를 하고 넘어가겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ u_{j}^{(l)} $&amp;nbsp; &amp;rarr;&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;l - layer 의 j-th 노드 (&lt;span style=&quot;color: #333333;&quot;&gt;활성함수를 통과 전&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;$ z_{j}^{(l)} $&amp;nbsp; &amp;rarr;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;l - layer 의 j-th 노드 (&lt;span style=&quot;color: #333333;&quot;&gt;활성함수를 통과 후&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;$ w_{ij}^{(l)} $&amp;nbsp; &amp;rarr; (l-1) layer 의 i-th 노드 에서 (l) layer 의 j-th 노드로 가는 가중치&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;$u_{i}^{(l-1)}&amp;nbsp;=&amp;nbsp;z_{i}^{(l-1)}$&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp; &amp;rarr; 입력층 노드는 활성함수가 없음&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;$u_{k}^{(l+1)}&amp;nbsp;=&amp;nbsp;z_{k}^{(l+1)}$&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&amp;rarr; 출력층 노드는 활성함수가 없음&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Feed forward&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞 방향으로 나가는 결과 값을 계산하는 것은 아래처럼 쉽게 계산이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$&amp;nbsp;u_k&amp;nbsp;=&amp;nbsp;\sum_{j=1}^{3}{&amp;nbsp;w_{jk}^{(l+1)}z_{j}^{l}&amp;nbsp;+&amp;nbsp;b_{k}^{(l+1)}&amp;nbsp;}&amp;nbsp;=&amp;nbsp;\sum_{j=0}^{3}{w_{jk}^{(l+1)}z_{j}^{(l)}&amp;nbsp;}&amp;nbsp;=&amp;nbsp;\sum_{j=0}^{3}{w_{jk}^{(l+1)}f(u_{j}^{(l)})&amp;nbsp;}&amp;nbsp;\leftarrow&amp;nbsp;w_{0k}^{l+1}=b_k^{l+1}&amp;nbsp;,&amp;nbsp;z_0^{l}=1&amp;nbsp; $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Back-propagation&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 weight 들을 학습하기 위해 gradient descent 방식으로 업데이트 하는 과정이 간단하지 않아&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 정리 하고자 아래와 같이 수식을 다시 정리해 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서의 E (loss function)은 간단히 mse 로 정의하고 진행하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ E = \sum_{k=1}^{3} {(y_k - d_k)}^2 $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;${\large {\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial w_{jk}^{(l+1)}}&amp;nbsp;=&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l+1)}}\cdot&amp;nbsp;{\partial&amp;nbsp;u_{j}^{(l+1)}&amp;nbsp;\over&amp;nbsp;\partial w_{jk}^{(l+1)}}{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial w_{jk}^{(l+1)}}&amp;nbsp;=&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l+1)}}\cdot&amp;nbsp;{\partial&amp;nbsp;u_{j}^{(l+1)}&amp;nbsp;\over&amp;nbsp;\partial w_{jk}^{(l+1)}}&amp;nbsp;=&amp;nbsp;(y_k&amp;nbsp;-d_k)\cdot{\partial&amp;nbsp;\sum_j{w_{jk}^{(l+1)}&amp;nbsp;\cdot&amp;nbsp;&amp;nbsp;{z_j^{(l)}}&amp;nbsp;}&amp;nbsp;\over&amp;nbsp;\partial w_{jk}^{(l+1)}} &lt;br /&gt;=&amp;nbsp;(y_k&amp;nbsp;-d_k)\cdot&amp;nbsp;&amp;nbsp;{z_j^{(l)}} &lt;br /&gt;}$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ \begin{align*}{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;w_{ij}^{(l)}}&amp;nbsp;&amp;amp;&amp;nbsp;=&amp;nbsp;&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}}&amp;nbsp;{\partial&amp;nbsp;u_{j}^{(l)}&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;w_{ij}^{(l)}}&amp;nbsp;=&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}}&amp;nbsp;\cdot&amp;nbsp;z_i^{l-1}&amp;nbsp;=&amp;nbsp;{\sum_{k=0}^{3}{&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{k}^{(l+1)}}&amp;nbsp;{\partial&amp;nbsp;u_{k}^{(l+1)}&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}}&amp;nbsp;}&amp;nbsp;}&amp;nbsp;\cdot&amp;nbsp;z_i^{l-1}&amp;nbsp;&amp;nbsp;\\&amp;nbsp;&amp;amp;&amp;nbsp;=&amp;nbsp; &lt;br /&gt;\left&amp;nbsp;(&amp;nbsp;&amp;nbsp;f'(u_j^{l})&amp;nbsp;\sum_{k}{w_{jk}^{(l+1)}(u_k^{(l+1)}&amp;nbsp;-&amp;nbsp;d_k)}\right&amp;nbsp;)z_i^{(l-1)}&amp;nbsp;\end{align*} $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$\begin{align*}&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;w_{ij}^{(l)}}&amp;nbsp;=&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}}{\&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;w_{ij}^{(l)}}&amp;nbsp;=\delta_{j}^{(l)}{\&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;w_{ij}^{(l)}}&amp;nbsp;\quad&amp;nbsp;\leftarrow&amp;nbsp;\quad&amp;nbsp;{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}}&amp;nbsp;=&amp;nbsp;\delta_{j}^{(l)}&amp;nbsp;\end{align*}$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;$ \begin{align*} {\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}} &amp;amp; =&amp;nbsp;\sum_{k}{{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{k}^{(l+1)}}&amp;nbsp; &lt;br /&gt;{\partial&amp;nbsp;u_{k}^{(l+1)}&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{j}^{(l)}}&amp;nbsp;}&amp;nbsp;=&amp;nbsp;\sum_{k}{{\partial&amp;nbsp;E&amp;nbsp;\over&amp;nbsp;\partial&amp;nbsp;u_{k}^{(l+1)}}&amp;nbsp;\cdot &lt;br /&gt;\left&amp;nbsp;(&amp;nbsp;w_{jk}^{(l+1)}&amp;nbsp;f'(u_j^{(l)})\right&amp;nbsp;)} \\ &amp;amp; =&amp;nbsp;\sum_{k}{\delta_k^{(l+1)}\left&amp;nbsp;(&amp;nbsp;w_{jk}^{(l+1)}&amp;nbsp;f'(u_j^{(l)})\right&amp;nbsp;)}&amp;nbsp;\quad l=2,&amp;nbsp;3,\dots&amp;nbsp;,L-1 \end{align*} $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 것은 &lt;span style=&quot;color: #333333;&quot;&gt;델타 함수가 출력층에서 멀어져도 출력층을 이용하여 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;전파되는 양을 수식으로 정의할 수 있게 되었습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$\delta_{j}^{(l)}=\sum_{k}{\delta_k^{(l+1)}\left&amp;nbsp;(&amp;nbsp;w_{jk}^{(l+1)}&amp;nbsp;f'(u_j^{(l)})\right&amp;nbsp;)}$&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Back-propagation matrix form&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;
import numpy as np
import matplotlib.pyplot as plt

class MLP(object):
    &quot;&quot;&quot;
    Using Keras and tensorflow, it is easy to learn. 
    However, it is implemented by using only numpy for feed forward and back propagation.

    Args:
        layers : [xs_dim, node, ... , node, out_dim]    

    mr.xeros@gmail.com [roadk]
    &quot;&quot;&quot;
    
    @staticmethod
    def sigmoid(x):
        return 1/(1+np.power(np.e, -x))

    @staticmethod
    def identity(x):
        return x

    @staticmethod
    def inv_sig(x):
        tmp = MLP.sigmoid(x)
        return tmp*(1-tmp)

    def __init__(self, **kwargs):


        self.layers = kwargs['layers']
        self.activate = [MLP.identity]
        self.weights = [1]
        self.bias = [0]
        self.lr = 0.002

        for i in range(1, len(self.layers)):
            self.weights.append(np.random.normal(0, 0.5, (self.layers[i-1],self.layers[i])))
            self.bias.append(np.random.normal(0, 0.5, self.layers[i]))

            if i != len(self.layers) -1:
                self.activate.append(MLP.sigmoid)
            else:
                self.activate.append(MLP.identity)

    def feed_forward(self, xs):

        self.U = [xs]
        self.Z = [xs]

        for i in range(1, len(self.layers)):
            u = self.Z[i-1].dot(self.weights[i]) + self.bias[i]
            z = self.activate[i](u)
            self.U.append(u)
            self.Z.append(z)

        return self.Z[-1]


    def back_propagate(self, xs, ys):

        pred_ys = self.feed_forward(xs)
        self.D = []

        for i in reversed(range(1,len(self.layers))):
            if i == len(self.layers) - 1:
                d = pred_ys - ys
            else:
                d = self.inv_sig(self.U[i])*(self.D[-1].dot(self.weights[i+1].T))

            dW = self.Z[i-1].T.dot(d)
            db = np.sum(d, axis=0)

            self.weights[i] -= self.lr*dW
            self.bias[i] -= self.lr*db

            self.D.append(d)
        return

    def evaluate(self, xs, ys):
        pred_ys = self.feed_forward(xs)
        d = pred_ys - ys
        return np.mean(np.sqrt(d**2))
    

if __name__ == '__main__':
    
    model = MLP(layers=[1,5,5,5,1])
    
    train_x = np.linspace(-5,5,100)
    train_y = np.sin(train_x)

    xs = train_x.reshape(-1,1)
    ys = train_y.reshape(-1,1)

    pred_ys = model.feed_forward(xs)

    for i in range(50000):
        model.back_propagate(xs, ys)

        if (i+1) % 5000 == 0:
            error = model.evaluate(xs, ys)
            print('ITER={:05d}, RMSE={:.4f}'.format(i+1, error))
            
    pred_ys = model.feed_forward(xs)
    
    plt.plot(xs.ravel(), pred_ys.ravel(), label='prediction')
    plt.plot(xs.ravel(), train_y.ravel(), label='original')
    plt.legend()    
            
        
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Naive Gradient descent 와 sigmoid 를 사용하였고, numpy 사용하여 weights 들을 학습한 결과를 보면&amp;nbsp; 어느정도 학습이 된 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lHbQz/btqxdScmyDH/ojCXBDlXaAYvOEI2DdURZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lHbQz/btqxdScmyDH/ojCXBDlXaAYvOEI2DdURZ0/img.png&quot; data-alt=&quot;Numpy 만 사용하여 학습한 결과&amp;amp;amp;nbsp;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lHbQz/btqxdScmyDH/ojCXBDlXaAYvOEI2DdURZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlHbQz%2FbtqxdScmyDH%2FojCXBDlXaAYvOEI2DdURZ0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Numpy 만 사용하여 학습한 결과&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <category>backpropagation</category>
      <category>implementation</category>
      <category>numpy</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/87</guid>
      <comments>https://roadcom.tistory.com/87#entry87comment</comments>
      <pubDate>Thu, 25 Jul 2019 23:00:37 +0900</pubDate>
    </item>
    <item>
      <title>[keras] vae spectrum generator</title>
      <link>https://roadcom.tistory.com/84</link>
      <description>&lt;p&gt;* Variational Autoencoder&lt;/p&gt;
&lt;p&gt;생성 모델 중 VAE 정리 진행 중 (영상 대신 1d 시그널&amp;nbsp; 생성 모델)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csW5yt/btqxfdAmWLz/AaCvkIdszHGLap4gedFBQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csW5yt/btqxfdAmWLz/AaCvkIdszHGLap4gedFBQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csW5yt/btqxfdAmWLz/AaCvkIdszHGLap4gedFBQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsW5yt%2FbtqxfdAmWLz%2FAaCvkIdszHGLap4gedFBQK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;# coding: utf-8

# In[1]:


import os
import keras
import numpy as np
import matplotlib.pyplot as plt

import tensorflow as tf


# In[2]:


def sinosoidal(v):
    
    fix_wave = np.arange(100)
    
    return (fix_wave**0.2)*np.sin(0.3*fix_wave + v) + v


# In[3]:


spectrum_y = np.random.normal(size=(1000,1),scale= 0.5)
spectrum_x = np.vstack([sinosoidal(i[0]) for i in spectrum_y])

xmean,xstd = spectrum_x.mean(), spectrum_x.std()
ymean,ystd = spectrum_y.mean(), spectrum_y.std()

stdz_x = (spectrum_x - xmean)/xstd
stdz_y = (spectrum_y - ymean)/ystd

total_size = len(stdz_x)
rand_idx = np.random.permutation(total_size)

x_train = stdz_x[rand_idx][:int(0.7*total_size)]
x_valid = stdz_x[rand_idx][int(0.7*total_size):int(0.8*total_size)]
x_test =  stdz_x[rand_idx][int(0.8*total_size):]


# In[4]:


for i in stdz_x:
    plt.plot(i)


# In[ ]:


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from keras.layers import Lambda, Input, Dense
from keras.models import Model
from keras.datasets import mnist
from keras.losses import mse, binary_crossentropy
from keras.utils import plot_model
from keras import backend as K

import numpy as np
import matplotlib.pyplot as plt
import argparse
import os


# reparameterization trick
# instead of sampling from Q(z|X), sample epsilon = N(0,I)
# z = z_mean + sqrt(var) * epsilon
def sampling(args):
    &quot;&quot;&quot;Reparameterization trick by sampling from an isotropic unit Gaussian.
    # Arguments
        args (tensor): mean and log of variance of Q(z|X)
    # Returns
        z (tensor): sampled latent vector
    &quot;&quot;&quot;

    z_mean, z_log_var = args
    batch = K.shape(z_mean)[0]
    dim = K.int_shape(z_mean)[1]
    # by default, random_normal has mean = 0 and std = 1.0
    epsilon = K.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon


def plot_results(models,
                 data,
                 batch_size=128,
                 model_name=&quot;vae_mnist&quot;):
    &quot;&quot;&quot;Plots labels and MNIST digits as a function of the 2D latent vector
    # Arguments
        models (tuple): encoder and decoder models
        data (tuple): test data and label
        batch_size (int): prediction batch size
        model_name (string): which model is using this function
    &quot;&quot;&quot;

    encoder, decoder = models
    x_test, y_test = data
    os.makedirs(model_name, exist_ok=True)

    filename = os.path.join(model_name, &quot;vae_mean.png&quot;)
    # display a 2D plot of the digit classes in the latent space
    z_mean, _, _ = encoder.predict(x_test,
                                   batch_size=batch_size)


    for i, yi in enumerate(grid_y):
        for j, xi in enumerate(grid_x):
            z_sample = np.array([[xi, yi]])
            x_decoded = decoder.predict(z_sample)
            digit = x_decoded[0].reshape(digit_size, digit_size)
            figure[i * digit_size: (i + 1) * digit_size,
                   j * digit_size: (j + 1) * digit_size] = digit



# MNIST dataset


print(spectrum_x.shape, spectrum_y.shape)


original_dim = spectrum_x.shape[1]


# network parameters
input_shape = (original_dim, )
intermediate_dim = 3
batch_size = 64
latent_dim = 2
epochs = 5000

# VAE model = encoder + decoder
# build encoder model
inputs = Input(shape=input_shape, name='encoder_input')
x = Dense(intermediate_dim, activation='relu')(inputs)
z_mean = Dense(latent_dim, name='z_mean')(x)
z_log_var = Dense(latent_dim, name='z_log_var')(x)

# use reparameterization trick to push the sampling out as input
# note that &quot;output_shape&quot; isn't necessary with the TensorFlow backend
z = Lambda(sampling, output_shape=(latent_dim,), name='z')([z_mean, z_log_var])

# instantiate encoder model
encoder = Model(inputs, [z_mean, z_log_var, z], name='encoder')
encoder.summary()
plot_model(encoder, to_file='vae_mlp_encoder.png', show_shapes=True)

# build decoder model
latent_inputs = Input(shape=(latent_dim,), name='z_sampling')
x = Dense(intermediate_dim, activation='relu')(latent_inputs)
# outputs = Dense(original_dim, activation='sigmoid')(x)
outputs = Dense(original_dim)(x)

# instantiate decoder model
decoder = Model(latent_inputs, outputs, name='decoder')
decoder.summary()
plot_model(decoder, to_file='vae_mlp_decoder.png', show_shapes=True)

# instantiate VAE model
outputs = decoder(encoder(inputs)[2])
vae = Model(inputs, outputs, name='vae_mlp')


models = (encoder, decoder)
reconstruction_loss = mse(inputs, outputs)

reconstruction_loss *= original_dim
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')
vae.summary()
plot_model(vae,to_file='vae_mlp.png',show_shapes=True)

vae.fit(x_train, epochs=epochs, batch_size=batch_size, validation_data=(x_test, None), verbose=1)
vae.save_weights('vae_mlp_mnist.h5')
# plot_results(models, data, batch_size=batch_size, model_name=&quot;vae_mlp&quot;)


# In[26]:


x_decoded = decoder.predict(np.random.random((1000,2))*3)


# In[27]:


for i in x_decoded:
    plt.plot(i)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt; Origin spectrum&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;output_png output_subarea &quot;&gt;&lt;img src=&quot;data:image/png;base64,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&quot; /&gt;&lt;/div&gt;
&lt;p&gt;&lt;span&gt; VAE generator spectrum&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;output_png output_subarea &quot;&gt;&lt;img src=&quot;data:image/png;base64,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&quot; /&gt;&lt;/div&gt;</description>
      <category>딥러닝</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/84</guid>
      <comments>https://roadcom.tistory.com/84#entry84comment</comments>
      <pubDate>Sat, 27 Apr 2019 12:37:31 +0900</pubDate>
    </item>
    <item>
      <title>Retriever 프로젝트</title>
      <link>https://roadcom.tistory.com/58</link>
      <description>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;시스템 인터페이스 관련 일들을 진행하다 보면,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;생산자(Producer)로 부터 오는 정보를 이용하여 소비자(Consumer) 로 바로 넘겨주지 못하고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;대부분 오는 정보를 이용하여&amp;nbsp;무언가를 덧붙이고 수정하여&amp;nbsp;넘겨주게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;그래서 agent 를 만들어서 필요한 정보들을 파싱하고 더 필요한 파일들을 모아서&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;소비자(Consumer)가 쓰기 편한 형태로 제공합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;이런 작업을 하는 agent 를 retriever 라고 사냥개 이름에 빚대서&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;생산자로 부터 넘어온 데이터를 이용하여 원하는 정보들을 잘 물어오는 agent 를 만들어보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;언어 : C++&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;DB : MySQL&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;Message Queue : RabbitMQ&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;코드는 아래 Git을 통해서 통해서 업데이트 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;a href=&quot;https://github.com/elentail/BGMs/branches&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;https://github.com/elentail/BGMs/branches&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/992D36335A22B10B15&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F992D36335A22B10B15&quot; width=&quot;700&quot; height=&quot;548&quot; filename=&quot;Retriever.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;진행사항은 대략적으로 아래 업데이트 하도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;1.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 16px; color: rgb(0, 0, 0);&quot;&gt;Message Queue 설치 (RabbitMQ server)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px; color: rgb(0, 0, 0);&quot;&gt;&amp;nbsp;작업을 분배하는 message server 는 아래 설치과정을 보시면 알겠지만, 단 10 분이면&amp;nbsp; 설치 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;
&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;


Last login: Tue Dec  5 20:49:45 2017 from 175.115.214.213

#1.  rabbitmq-server  설치
roadking@gcloud:~$ sudo apt install rabbitmq-server -y
[sudo] password for roadking: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  linux-headers-4.10.0-37
...

#2.  rabbitmq-server  상태 확인(active)
roadking@gclouds:~$ sudo systemctl status rabbitmq-server
● rabbitmq-server.service - RabbitMQ Messaging Server
   Loaded: loaded (/lib/systemd/system/rabbitmq-server.service; enabled; vendor 
   Active: active (running) since Tue 2017-12-05 20:55:06 UTC; 3min 9s ago
 Main PID: 18165 (rabbitmq-server)
   CGroup: /system.slice/rabbitmq-server.service
           ├─18165 /bin/sh /usr/sbin/rabbitmq-server
           ├─18182 /bin/sh -e /usr/lib/rabbitmq/bin/rabbitmq-server
           ├─18243 /usr/lib/erlang/erts-7.3/bin/epmd -daemon
           ├─18301 /usr/lib/erlang/erts-7.3/bin/beam.smp -W w -A 64 -P 1048576 -
           ├─18418 inet_gethost 4
           └─18419 inet_gethost 4

Dec 05 20:55:04 gclouds systemd[1]: Starting RabbitMQ Messaging Server...
Dec 05 20:55:05 gclouds rabbitmq[18166]: Waiting for rabbit@gclouds ...
Dec 05 20:55:05 gclouds rabbitmq[18166]: pid is 18182 ...
Dec 05 20:55:06 gclouds systemd[1]: Started RabbitMQ Messaging Server.

#3.  관리용 플러그인 설치
roadking@gclouds:~$ sudo rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
  mochiweb
  webmachine
  rabbitmq_web_dispatch
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management

Applying plugin configuration to rabbit@gclouds... started 6 plugins.

#4.  관리용 플러그인 설치로 해당 서비스 재시작
roadking@gclouds:~$ sudo systemctl restart rabbitmq-server

#5.  luffy/onepiece 로 관리용 계정 생성
roadking@gclouds:~$ sudo rabbitmqctl add_user luffy onepiece
Creating user &quot;luffy&quot; ...

#6.  해당 계정을 관리자(administrator) 로 설정
roadking@gclouds:~$ sudo rabbitmqctl set_user_tags luffy administrator
Setting tags for user &quot;luffy&quot; to [administrator] ...
roadking@gclouds:~$ 

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot;&gt;&amp;nbsp;[ R&lt;/span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;abbitMQ Server - 관리 페이지 접속&amp;nbsp; http://IP:15672 , luffy/onepiece]&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993FD5335A270F7236&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993FD5335A270F7236&quot; width=&quot;700&quot; height=&quot;451&quot; filename=&quot;rabbitMQ.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;2. DB 설치(MySQL)&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;
#1.  mysql 서버 설치
roadking@gclouds:~$ sudo apt  install mysql-server

#2. mysql 서버 상태 확인
roadking@gclouds:~$ systemctl status mysql
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2017-12-05 21:41:00 UTC; 2min 18s ago
 Main PID: 23166 (mysqld)
   CGroup: /system.slice/mysql.service
           └─23166 /usr/sbin/mysqld

#3. mysql 서버 접속
roadking@gclouds:~$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.20-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql&gt; 


&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;2. DB 설치(MySQL&lt;/span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;2. DB 설치(MySQL&lt;/span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;2. DB 설치(MySQL&lt;/span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/58</guid>
      <comments>https://roadcom.tistory.com/58#entry58comment</comments>
      <pubDate>Sat, 2 Dec 2017 23:01:14 +0900</pubDate>
    </item>
    <item>
      <title>[ Lagrange multiplier ] 두 타원 간의 최소거리</title>
      <link>https://roadcom.tistory.com/57</link>
      <description>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;* shortest path, Lagrange multiplier, constrained optimization&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;* 라그랑주 승수법&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;이 번주 너무 바쁜 핑계로 후배에게 한가지 일을 시켰습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;
&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&quot; 영상에서 두 blob 간에 최소거리를 측정하는 모듈을 만들어서 줘 &quot;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;
&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;후회를 시키지않는 똑똑한 후배는 역시 해당 모듈을 뚝딱 만들어서 보내줬습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;
&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;
&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;그런데 한가지 단점이 보이기 시작했네요, 속도가 너무 느린 것 같아요.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;
&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;
&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;두 blob 의 중심을 이용하여 외각선을 추려서&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;해당 p&lt;/span&gt;oint to point 비교로 최소 거리를 측정하여&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이중 for 문으로 $O(n^2)$ 가 나와 버리는 단점이 생겼네요,,,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이러한&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;command&quot; style=&quot;font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: 12pt; box-sizing: border-box; margin: 0px; padding: 0.125em 0.25em; border: 1px solid rgb(153, 153, 153); font-stretch: inherit; line-height: inherit; vertical-align: baseline; background-color: rgb(245, 245, 245); border-radius: 4px;&quot;&gt;&amp;nbsp;속도 문제점&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;때문에 numerical method 방식으로 문제를 풀어 볼 수는 없을까요?&lt;/span&gt;&lt;/p&gt;&lt;h2 style=&quot;box-sizing: border-box; margin: 1.75em 0px 10px; padding: 0.5em 0px 0.5em 0.25em; border-width: 0px 0px 0px 0.3em; border-top-style: initial; border-right-style: initial; border-bottom-style: initial; border-left-style: solid; border-color: rgb(37, 156, 224); border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; font-size: 1.8rem; line-height: 1.1; font-family: &amp;quot;Nanum Gothic&amp;quot;; vertical-align: baseline; position: relative; border-radius: 4px;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; color: rgb(0, 0, 0);&quot;&gt;제한 조건이 있는 최적화 문제&lt;/span&gt;&lt;/h2&gt;&lt;ul style=&quot;box-sizing: border-box; margin-top: 0px; margin-bottom: 10px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt;&quot;&gt;라그랑주 승수법(L&lt;/span&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;agrange multiplier)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt;&quot;&gt;수식으로 표시할 수 있는 제한조건의 최적화 문제는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: 700; color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt;&quot;&gt;라그랑주 승수법(Lagrange multiplier)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt;&quot;&gt;을 사용하여 최적화 할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face=&quot;Helvetica Neue, Helvetica, Arial, sans-serif&quot;&gt;&lt;span style=&quot;font-size: 12pt; font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; color: rgb(0, 0, 0);&quot;&gt;위키피디아 (&lt;/span&gt;&lt;/font&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;https://en.wikipedia.org/wiki/Lagrange_multiplier) 에 나와 있는 내용처럼&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: sans-serif; font-size: 12pt;&quot;&gt;제약된 문제를 제약이 없는 문제로 바꿔서 풀 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: sans-serif; font-size: 12pt;&quot;&gt;우선 아래와 같이 최적화 함수와 제한 조건을 정의 합니다. 제한 조건의 등호에 유의 하셔야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: sans-serif; font-size: 12pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;최적화 하려는 함수&amp;nbsp; $f(x,y)$&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;제한 조건&amp;nbsp; $g(x,y) = 0$&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;f, g &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;1차 편미분에 대해 연속이라 가정하면, 새로운 변수&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(34, 34, 34); font-family: &amp;quot;Nimbus Roman No9 L&amp;quot;, &amp;quot;Times New Roman&amp;quot;, Times, serif; font-size: 16.52px; white-space: nowrap;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;λ(Lagrange multiplier)&amp;nbsp; 도입하여&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(34, 34, 34); font-family: sans-serif; font-size: 14px;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;Lagrange&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt; white-space: nowrap;&quot;&gt;&amp;nbsp;function 정의 할 수 있습니다. 단순히 2개 함수를 하나의 표현식으로 나타낼 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;$&amp;nbsp;\mathcal{L}(x,y,\lambda) = f(x,y) -\lambda \cdot g(x,y)$&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;[ General case ]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;$ \mathcal{L}(x_1,\cdots,x_n,\lambda_1,\cdots,\lambda_M) = f(x_1,\cdots,x_n) - \sum_{k=1}^M \lambda_kg_k(x_1,\cdots,x_n) $&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;위키피디아에서 설명한 것처럼&amp;nbsp; g=0 의 둘레를 돌다 보면 f 와 평행해 보이는 곳이 나타날 것인데, 이러한 지점들이 minma, maxima 중에 하나가 될 것입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;이 의미를 잘 해석해보면 2가지로 해석이 되는데&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;1. f, g 두 함수가 평행해 지는 곳&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;2. f 함수 자체가 변하지 않아 g=0 의 둘레 어느 곳이든 똑같아 보이는 현상&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;$ \nabla_{x,y,z} \mathcal{L}(x,y,\lambda) = 0 \iff&amp;nbsp; \begin{cases} \nabla_{x,y}f(x,y)=\lambda\nabla_{x,y}g(x,y), \\ g(x,y)=0, \end{cases}$&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;[ General case ]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;$ \nabla_{x_1,\cdots,x_n,\lambda_1,\cdots,\lambda_M} \mathcal{L}(x_1,\cdots,x_n,\lambda_1,\cdots,\lambda_M) = 0 \iff&amp;nbsp; \begin{cases} \nabla f(\mathbf{x}) -\sum_{k=1}^M \lambda_k g_k(\mathbf{x}) , \\ g_1(\mathbf{x})=\cdots=g_M(\mathbf{x}) = 0, \end{cases}$&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;위 수식에서 변수 n + M&amp;nbsp; 식이 n + M 가 존재하기 때문에 충분히 풀 수가 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;다들 아시겠지만&amp;nbsp;gradient 의 결과는 vector 나오기 때문에 n x 1 의 column vector 로&amp;nbsp;&amp;nbsp; n 개의 등식이 존재합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;(g1= ... = gM = 0&amp;nbsp; 여기서 M 개, gradient f&amp;nbsp; = lambda g 에서&amp;nbsp; n 개)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;설명을 위해 머나먼 길을 돌아온 것 같네요 ^^&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; margin: 1.5em 0px 10px; padding: 0.4em 0px 0.4em 0.25em; border-width: 0px 0px 0px 0.25em; border-top-style: initial; border-right-style: initial; border-bottom-style: initial; border-left-style: solid; border-color: rgb(37, 156, 224); border-image: initial; font-variant-numeric: inherit; font-stretch: inherit; font-size: 1.6rem; line-height: 1.1; font-family: &amp;quot;Nanum Gothic&amp;quot;; vertical-align: baseline; position: relative; border-radius: 4px;&quot;&gt;&amp;nbsp;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 14pt; color: rgb(0, 0, 0);&quot;&gt;Lagrange multiplier 를 이용한 최적화 문제&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;yellow&quot; style=&quot;box-sizing: border-box; margin: 0px; padding: 0.5em; border: 1px solid rgb(186, 169, 0); font-variant-numeric: inherit; font-stretch: inherit; font-size: 16px; line-height: 1.75rem; font-family: &amp;quot;Nanum Gothic&amp;quot;; vertical-align: baseline; border-radius: 4px; background-color: rgb(255, 253, 235);&quot;&gt;&lt;p style=&quot;box-sizing: border-box; margin: 0px; padding: 0.5em; border: 0px; font-style: inherit; font-variant: inherit; font-stretch: inherit; font-size: 1rem; line-height: 1.75rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;box-sizing: border-box; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-stretch: inherit; font-size: inherit; line-height: inherit; font-family: inherit; vertical-align: baseline;&quot;&gt;&lt;span class=&quot;fa fa-check fa-lg&quot; style=&quot;box-sizing: border-box; margin: 0px; padding: 0px; border: 0px; font-stretch: normal; font-size: 1.33333em; line-height: 0.75em; font-family: FontAwesome; vertical-align: -15%; display: inline-block; text-rendering: auto; -webkit-font-smoothing: antialiased;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 12pt;&quot;&gt;&amp;nbsp;문제&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;box-sizing: border-box; margin: 0px; padding: 0.5em; border: 0px; font-style: inherit; font-variant: inherit; font-stretch: inherit; font-size: 1rem; line-height: 1.75rem; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;두 타원의 최소거리를 구하려고 합니다. 물론 각 점들은 타원 1과 타원 2 안에 있는 후보 중 어느 2개의 점입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;b&gt;최적화 함수&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;$d^2 = [(x_1 -x_2)^2 + (y_1 - y_2)^2].$&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;&lt;b&gt;제한 조건&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;$g(x_1,y_1)=a_1&amp;nbsp;x_1^2 + b _1y_1^2 + c_1 x _1y_1 + d_1 x_1 + e _1y_1 + f_1 =0.$&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;$g(x_2,y_2)=a_2 x_2^2 + b _2y_2^2 + c_2 x _2y_2 + d_2 x_2 + e _2y_2 + f_2 =0.$&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;[ 원본 영상 - 손으로 그려서 조잡합니다...]&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/995CDD335A19116906&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F995CDD335A19116906&quot; width=&quot;700&quot; height=&quot;524&quot; filename=&quot;blobs.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;[ 두 타원(blob) 간의 최소 거리 ]&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9911C2335A1AD8DD2B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9911C2335A1AD8DD2B&quot; width=&quot;700&quot; height=&quot;524&quot; filename=&quot;shorted.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;코드&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
#!/usr/bin/env python

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import


import cv2
import numpy as np
import os,re,sys,argparse

import scipy.optimize as sp

def fit_rotated_ellipse(data):

    &quot;&quot;&quot;
    Least Square Mean 방식으로 타원 피팅
    model -&amp;gt; ax^2 + by^2 + cxy + dx + ey + f = 0 
    &quot;&quot;&quot;
    xs = data[:,0].reshape(-1,1) 
    ys = data[:,1].reshape(-1,1)

    J = np.mat( np.hstack((xs*ys,ys**2,xs, ys, np.ones_like(xs,dtype=np.float))) )
    Y = np.mat(-1*xs**2)
    P= (J.T * J).I * J.T * Y

    a = 1.0; b= P[0,0]; c= P[1,0]; d = P[2,0]; e= P[3,0]; f=P[4,0];

    return np.array([a,b,c,d,e,f])


def find_shorted_ellipses(contours,img_path):

    &quot;&quot;&quot;
    opencv 에서 제공하는 fitEllipse 함수와
    실제 어느정도 차이가 나는지 확인을 할 수 있도록
    fitEllipse 함수를 통해서 타원을 그려보겠습니다.
    &quot;&quot;&quot;

    ellipse1 = cv2.fitEllipse(contours[0])
    ellipse2 = cv2.fitEllipse(contours[1])


    e1 = fit_rotated_ellipse(contours[0].reshape(-1,2))
    e2 = fit_rotated_ellipse(contours[1].reshape(-1,2))


    # subject
    distance2e = lambda x : (x[0]-x[2])**2 + (x[1]-x[3])**2


    # constraint equation 1
    e1const = lambda x : \
            e1[0]*(x[0]**2) + e1[1]*(x[0]*x[1]) + \
            e1[2]*(x[1]**2) + e1[3]*x[0] + e1[4]*x[1] + e1[5]


    # constraint equation 2
    e2const = lambda x : \
            e2[0]*(x[2]**2) + e2[1]*(x[2]*x[3]) + \
            e2[2]*(x[3]**2) + e2[3]*x[2] + e2[4]*x[3] + e2[5]

    rst = sp.fmin_slsqp(distance2e,np.array([450,600,550,200]),eqcons=[e1const,e2const])
    print(rst)

    src = cv2.imread(img_path,cv2.IMREAD_COLOR)
    cv2.ellipse(src,ellipse1,(200,30,30),2)
    cv2.ellipse(src,ellipse2,(200,30,30),2)
    cv2.line(src,(int(rst[0]),int(rst[1])),(int(rst[2]),int(rst[3])),(20,250,20),3)
    cv2.imwrite('shorted.jpg',src)



    return

def find_contours(img_path):
    &quot;&quot;&quot;
    img_path : 입력 이미지 path
    return : 2 개의 타원의 외각선을 찾아 retrun [외각선1,외각선2]
    &quot;&quot;&quot;

    src = cv2.imread(img_path,cv2.IMREAD_GRAYSCALE)

    h, w = src.shape[:2]
    mask = np.zeros((h+2, w+2), np.uint8)

    _,thv = cv2.threshold(src,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    cv2.floodFill(thv,mask,(w-1,h-1),0)

    ret_contours= []

    _,cts,_= cv2.findContours(thv.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for con in cts:
        p = len(con)
        a = cv2.contourArea(con)
        if(a &amp;gt; 2000 and (1.0-p**2)/(4.0*np.pi*a) &amp;lt; 0.1):
            ret_contours.append(con)

    return ret_contours


if __name__ == '__main__':

    &quot;&quot;&quot;
    usage&amp;gt; python  two_ellipse.py --img_path=...
    &quot;&quot;&quot;
    parser = argparse.ArgumentParser()
    parser.add_argument(&quot;--img_path&quot;,help=&quot;the image path&quot;)
    if(len(sys.argv) != 2):
        parser.print_help()
        parser.exit()

    args = parser.parse_args()
    cons = find_contours(args.img_path)
    find_shorted_ellipses(cons,args.img_path)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;[ 참고 ]&lt;/p&gt;
&lt;p&gt;Fabian, how to calculate minimum distance between two arbitrary ellipses in 2d,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;MATHEMATICS,&lt;a href=&quot;https://math.stackexchange.com/questions/193722/how-to-calculate-minimum-distance-between-two-arbitrary-ellipses-in-2d&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;LINK&lt;/a&gt;&amp;nbsp;[2012.9.10]&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;데이터 사이언스 스쿨, 제한조건이 있는 최적화 문제. 2017-06-09, &lt;a href=&quot;https://datascienceschool.net/view-notebook/0c66f1810445488baf19cac79305793b/#제한조건이-있는-최적화-문제&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;LINK&lt;/a&gt;&lt;/p&gt;</description>
      <category>영상처리</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/57</guid>
      <comments>https://roadcom.tistory.com/57#entry57comment</comments>
      <pubDate>Fri, 24 Nov 2017 23:07:02 +0900</pubDate>
    </item>
    <item>
      <title>[ slim ] model-inception</title>
      <link>https://roadcom.tistory.com/49</link>
      <description>&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;** 정리 중&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;기존에도 TF Slim 을 통해서 4개 그룹 (병아리, 매, 비둘기, 참새) 에 대해서 잠깐 포스팅을 한 적이 있는데,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;따라하시기에 내용이 부족하여 진행한 내용에 대해서 세부적으로 코드 및 진행 내용에 대해서 다시 포스팅 올립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;code -&amp;nbsp;https://github.com/elentail/tensortuto.git&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;Web scraping 을 통해 dataset 구성&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;최신 tf-slim 설치&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;set 을 tf record format 으로 변환&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;Train set 을 통해 model 학습&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;Validation set을 통해 model validation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 0, 0);&quot;&gt;Test set을 통해 학습된 model 평가&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt; color: rgb(0, 0, 0);&quot;&gt;1.Preparing dataset&lt;/span&gt;&lt;/h2&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;크롤링 (web scraping) 을 통해 4개의 그룹에 대해서 dataset 을 구성&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(제가 사용한 데이터를 제공하고 싶지만, 아쉽게도 이부분은 얼마 걸리지 않으니 모아보셔야 됩니다.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;이미지는&amp;nbsp;Train 252, Validation 64 개 사용&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(birds_photos 폴더 밑에 4개의 폴더를 생성하고 해당 이미지를 저장)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Test 이미지는 평가를 위해 다른 폴더에 저장&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(최종 평가시, 파일 이름을 통해 결과 내용을 보여주기 위해 파일 이름을 test_{class_num} 형식으로 저장)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 691px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/999FC83359E3679517&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F999FC83359E3679517&quot; width=&quot;691&quot; height=&quot;234&quot; filename=&quot;folder_tree.png&quot; filemime=&quot;image/png&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99669B3359E3679506&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99669B3359E3679506&quot; width=&quot;700&quot; height=&quot;702&quot; filename=&quot;test_set.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: square; padding-left: 20px; color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;&quot;&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;h2 style=&quot;display: block; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;2. Installing latest TF Slim&lt;/span&gt;&lt;/h2&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;git clone&amp;nbsp; https://github.com/tensorflow/models/&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;

## 참조 tfrecord 저장 및 로딩
## http://www.machinelearninguru.com/deep_learning/tensortuto/basics/tfrecord/tfrecord.html 

## git clone
roadking@rhinoceros:~/workspace$ git clone https://github.com/tensorflow/models/
Cloning into 'models'...
remote: Counting objects: 7608, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 7608 (delta 0), reused 2 (delta 0), pack-reused 7602
Receiving objects: 100% (7608/7608), 157.89 MiB | 264.00 KiB/s, done.
Resolving deltas: 100% (4111/4111), done.
Checking connectivity... done.


# slim folder 로 이동
roadking@rhinoceros:~/workspace$ cd models/research/slim/

roadking@rhinoceros:~/workspace/models/research/slim$ ll
total 160
drwxrwxr-x  7 roadking roadking  4096 10월  9 00:03 ./
drwxrwxr-x 37 roadking roadking  4096 10월  9 00:03 ../
-rw-rw-r--  1 roadking roadking  9842 10월  9 00:03 BUILD
drwxrwxr-x  2 roadking roadking  4096 10월  9 00:03 datasets/
drwxrwxr-x  2 roadking roadking  4096 10월  9 00:03 deployment/
-rw-rw-r--  1 roadking roadking  2306 10월  9 00:03 download_and_convert_data.py
-rw-rw-r--  1 roadking roadking  6666 10월  9 00:03 eval_image_classifier.py
-rw-rw-r--  1 roadking roadking  4658 10월  9 00:03 export_inference_graph.py
-rw-rw-r--  1 roadking roadking  1397 10월  9 00:03 export_inference_graph_test.py
-rw-rw-r--  1 roadking roadking     0 10월  9 00:03 __init__.py
drwxrwxr-x  2 roadking roadking  4096 10월  9 00:03 nets/
drwxrwxr-x  2 roadking roadking  4096 10월  9 00:03 preprocessing/
-rw-rw-r--  1 roadking roadking 24026 10월  9 00:03 README.md
drwxrwxr-x  2 roadking roadking  4096 10월  9 00:03 scripts/
-rw-rw-r--  1 roadking roadking   231 10월  9 00:03 setup.py
-rw-rw-r--  1 roadking roadking 46294 10월  9 00:03 slim_walkthrough.ipynb
-rw-rw-r--  1 roadking roadking 20014 10월  9 00:03 train_image_classifier.py
-rw-rw-r--  1 roadking roadking     0 10월  9 00:03 WORKSPACE


# download_and_convert_data.py [./]
# -- download flowers.tgz
# -- extract flowers.tgz
# -- split validation and train set
# -- convert jpeg  to tf.record format
# -- make labels

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;3. Converting dataset to string format&lt;/span&gt;&lt;/h2&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;tf.gfile.FastGFile&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;- File I/O wrappers without thread locking.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;소스에서는 download_and_convert_data.py 를 통해 url 을 통해 dataset 을 다운로드 후,&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;FastGFile 을 통해 이미지를 string 으로 바로 읽은 후, serialized 객체로 저장하고 있습니다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;download_and_convert_data.py 에 들어있는 FastGFile 을&amp;nbsp; 그래프로 구성하여 실행하고 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;위와 같이 구성하면 thread 로 동작하여 속도가 빠르지만, 저는 단일 thread 로 opencv 를 통해&amp;nbsp; 읽도록 조금 변경했습니다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;git clone https://github.com/elentail/tensortuto.git 를 통해 아래 코드를 내려 받으실 수 있습니다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;[ 신규 코드 ]&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;converter.py - 단순히 해당 폴더와 이미지를 파싱하여 string 객체로 저장, label 파싱&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;label_image.py - test 이미지 평가시에 사용하기 위해 작성한 코드&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(102, 0, 255);&quot;&gt;[ 기존 코드 활용 ]&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;birds.py - datasets/flowers.py 파일과 동일 , class 수와 train, validation 수만 변경&amp;nbsp; datasets 로 복사&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;dataset_factory.py - datasets/dataset_factory.py 파일과 동일, birds 한줄 추가 datasets 로 복사 or 수정&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;

# git clone custom my source,,
# download_andconvert_data 의 역할을 convert.py 로 구성해 봤습니다.
# 아래 github 내 converter.py 참조

roadking@rhinoceros:~/workspace$ git clone https://github.com/elentail/tensortuto.git

roadking@rhinoceros:~/workspace/tensortuto/slim_example$ ll

total 28
drwxrwxr-x 2 roadking roadking 4096 10월 15 21:55 ./
drwxrwxr-x 7 roadking roadking 4096 10월 14 12:58 ../
-rw-rw-r-- 1 roadking roadking 3237 10월 15 21:20 birds.py  #copy to research/slim/datasets /
-rw-rw-r-- 1 roadking roadking 5287 10월 15 21:55 converter.py
-rw-rw-r-- 1 roadking roadking 1966 10월 15 21:22 dataset_factory.py #copy to research/slim/datasets /
-rw-rw-r-- 1 roadking roadking 2969 10월 15 21:22 label_image.py #copy to research/slim/

roadking@rhinoceros:~/workspace/tensortuto/slim_example$ python converter.py \
    --dataset_name=birds \
    --dataset_dir=/home/roadking/Downloads/birds_photos \
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;converter.py&amp;nbsp; 수행 후 아래와 같이 train, validation, labels 3개의 파일이 신규로 생성됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 671px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99F6343359E367951A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99F6343359E367951A&quot; width=&quot;671&quot; height=&quot;326&quot; filename=&quot;converter.png&quot; filemime=&quot;image/png&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;clear: none; float: none; text-align: center;&quot;&gt;&lt;b&gt;[ birds.py ]&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;clear: none; float: none; text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 424px; width: 424px; height: 289px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99E10A3359E4B83D20&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99E10A3359E4B83D20&quot; width=&quot;424&quot; height=&quot;289&quot; filename=&quot;convert_py.png&quot; filemime=&quot;image/png&quot; style=&quot;width: 424px; height: 289px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;clear: none; float: none; text-align: center;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;clear: none; float: none; text-align: center;&quot;&gt;&lt;b&gt;[ dataset_factory.py ]&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;clear: none; float: none; text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 424px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99053D3359E4B83D09&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99053D3359E4B83D09&quot; width=&quot;424&quot; height=&quot;290&quot; filename=&quot;data_util.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: square; padding-left: 20px; color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;&quot;&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;h2 style=&quot;display: block; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;4. Training pre-trained model&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;; font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;; font-size: 16px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;checkpoint_exclude_scopes&lt;/div&gt;&lt;div&gt;trainable_scopes&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;

## XX dataset or checkpoint prefix path,,
roadking@rhinoceros:~/workspace/models/research/slim$ TRAIN_DIR=XX/inception_train_1015
roadking@rhinoceros:~/workspace/models/research/slim$ DATASET_DIR=XX/bird_photos
roadking@rhinoceros:~/workspace/models/research/slim$ CHECKPOINT_PATH=XX/inception_v3_model/inception_v3.ckpt
roadking@rhinoceros:~/workspace/models/research/slim$ python train_image_classifier.py \
    --train_dir=${TRAIN_DIR} \
    --dataset_dir=${DATASET_DIR} \
    --dataset_name=birds \
    --dataset_split_name=train \
    --model_name=inception_v3 \
    --checkpoint_path=${CHECKPOINT_PATH} \
    --checkpoint_exclude_scopes=InceptionV3/Logits,InceptionV3/AuxLogits \
    --trainable_scopes=InceptionV3/Logits,InceptionV3/AuxLogits \
    --max_number_of_steps=1000 \
    --save_summaries_secs=600 \
    --save_interval_secs=300 \

...
INFO:tensortuto:Recording summary at step 1.
INFO:tensortuto:global step 10: loss = 1.8428 (0.774 sec/step)
INFO:tensortuto:global step 20: loss = 1.0923 (0.758 sec/step)
INFO:tensortuto:global step 30: loss = 1.1633 (0.777 sec/step)
INFO:tensortuto:global step 40: loss = 0.9142 (0.770 sec/step)
...
INFO:tensorflow:global step 990: loss = 0.3254 (0.767 sec/step)
INFO:tensorflow:global step 1000: loss = 0.3830 (0.769 sec/step)
INFO:tensorflow:Stopping Training.
INFO:tensorflow:Finished training! Saving model to disk.



roadking@rhinoceros:~/workspace/tf-slim/research/slim$ python eval_image_classifier.py \
    --alsologtostderr \
    --checkpoint_path=${TRAIN_DIR} \
    --dataset_dir=${DATASET_DIR} \
    --dataset_name=birds \
    --dataset_split_name=validation \
    --model_name=inception_v3 \
    --batch_size=16
...
ance gains if more memory is available.
INFO:tensorflow:Evaluation [1/4]
INFO:tensorflow:Evaluation [2/4]
INFO:tensorflow:Evaluation [3/4]
INFO:tensorflow:Evaluation [4/4]
2017-10-15 22:22:40.743307: I tensorflow/core/kernels/logging_ops.cc:79] eval/Recall_5[1]
2017-10-15 22:22:40.743451: I tensorflow/core/kernels/logging_ops.cc:79] eval/Accuracy[0.984375]
INFO:tensorflow:Finished evaluation at 2017-10-15-13:22:40



roadking@rhinoceros:~/workspace/tf-slim/research/slim$ python label_image.py \
&amp;gt; --model_name=inception_v3 \
&amp;gt; --model_path=${TRAIN_DIR}/model.ckpt-1000 \
&amp;gt; --data_path=/home/roadking/Downloads/test_images \
&amp;gt; --label_path=${DATASET_DIR}/labels.txt \

&amp;gt; 
=============================================
==== DATA RESULT (confusion matrix)  ========
name			pigeon	chick	sparrow	hawk
test_hawk4.jpg		0	0	0	1
test_chick1.jpg		0	1	0	0
test_hawk2.jpg		0	0	0	1
test_chick4.jpg		0	0.99	0	0.01
test_pigeon2.jpg 	0.9	0	0.09	0
test_hawk1.jpg		0.91	0	0.04	0.05
test_chick2.jpg		0.03	0.96	0	0.01
test_sparrow2.jpg	0	0	1	0
test_sparrow1.jpg	0	0	1	0
test_pigeon4.jpg	0.94	0	0.05	0
test_chick3.jpg		0	1	0	0
test_sparrow3.jpg	0	0	1	0
test_sparrow4.jpg	0	0	1	0
test_pigeon3.jpg	0.99	0	0.01	0
test_pigeon1.jpg	0.12	0	0.88	0
test_hawk3.jpg		0	0	0	1

roadking@rhinoceros:~/workspace/tf-slim/research/slim$ &lt;/code&gt;&lt;/pre&gt;&lt;p style=&quot;font-family: &amp;quot;Liberation Sans&amp;quot;; font-size: x-small;&quot;&gt;&lt;/p&gt;&lt;table cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;font-family: &amp;quot;Liberation Sans&amp;quot;; font-size: x-small; width: 662px;&quot; width=&quot;662&quot;&gt;&lt;colgroup span=&quot;2&quot; width=&quot;85&quot;&gt;&lt;/colgroup&gt;&lt;colgroup width=&quot;117&quot;&gt;&lt;/colgroup&gt;&lt;colgroup width=&quot;108&quot;&gt;&lt;/colgroup&gt;&lt;colgroup width=&quot;106&quot;&gt;&lt;/colgroup&gt;&lt;colgroup width=&quot;123&quot;&gt;&lt;/colgroup&gt;&lt;colgroup width=&quot;85&quot;&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td height=&quot;17&quot; align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; color: rgb(255, 255, 255); background-color: rgb(0, 0, 0); border-width: 1px; border-style: solid; border-color: rgb(0, 0, 0) rgb(217, 217, 217) rgb(0, 0, 0) rgb(0, 0, 0); height: 19px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; color: rgb(255, 255, 255); background-color: rgb(0, 0, 0); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); height: 19px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td colspan=&quot;4&quot; align=&quot;center&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; color: rgb(255, 255, 255); background-color: rgb(0, 0, 0); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); height: 19px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(255, 255, 255);&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt;&quot;&gt;Model&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; color: rgb(255, 255, 255); background-color: rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); width: 46px; height: 19px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td height=&quot;17&quot; align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); border-left: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;TEST_CHICK&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;_TEST_HAWK&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;TEST_PIGEON&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;TEST_SPARROW&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;RECALL&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td rowspan=&quot;4&quot; height=&quot;68&quot; align=&quot;center&quot; valign=&quot;middle&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 72px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); border-left: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;Human&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 17px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;CHICK&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;4&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 17px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;4&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 17px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 17px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 17px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;1&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(217, 217, 217); height: 17px; color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 18px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;HAWK&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;1&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 18px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;3&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 18px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;3&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 18px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); height: 18px; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0.75&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(217, 217, 217); height: 18px; color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0.75&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;PIGEON&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;3&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;3&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;1&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: transparent; border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0.75&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0.75&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;SPARROW&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;4&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(230, 230, 230); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;4&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;1&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; height: 18px; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td height=&quot;17&quot; align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); border-left: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;PRECISION&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0.8&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0.8&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;1&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;1&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0.8&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0.8&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td height=&quot;17&quot; align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); border-left: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(217, 217, 217); color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td height=&quot;17&quot; align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;ACCURACY&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;right&quot; sdval=&quot;0.875&quot; sdnum=&quot;1033;&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; color: rgb(0, 0, 0);&quot;&gt;0.875&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(217, 217, 217); border-bottom: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;td align=&quot;left&quot; style=&quot;font-size: x-small; font-family: &amp;quot;Liberation Sans&amp;quot;; background-color: rgb(255, 216, 216); border-right: 1px solid rgb(0, 0, 0); border-bottom: 1px solid rgb(0, 0, 0); color: rgb(0, 0, 0); width: 46px;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 0.5;&quot;&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/tensorflow</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/49</guid>
      <comments>https://roadcom.tistory.com/49#entry49comment</comments>
      <pubDate>Mon, 9 Oct 2017 00:40:08 +0900</pubDate>
    </item>
    <item>
      <title>[ intro ] google cloud platform</title>
      <link>https://roadcom.tistory.com/39</link>
      <description>&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;pre class=&quot;tw-data-text tw-ta tw-text-small&quot; data-placeholder=&quot;번역&quot; id=&quot;tw-target-text&quot; data-fulltext=&quot;&quot; dir=&quot;ltr&quot; style=&quot;max-height: 999999px; background-color: rgb(255, 255, 255); border: none; padding: 0px 0.14em 0px 0px; position: relative; margin-top: 0px; margin-bottom: 0px; resize: none; font-family: inherit; overflow: hidden; width: 328px; white-space: pre-wrap; word-wrap: break-word; color: rgb(33, 33, 33); height: 40px; font-size: 16px !important; line-height: 20px !important;&quot;&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;* The following describes how to use Google Cloud Platform.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;구글 클라우드 플랫폼에 대해서 설치 및 간단한 이용방법 위주로 설명을 진행하겠습니다.&lt;br /&gt;클라우드 플랫폼에서는 VM 구성 및 gpu, cpu 저렴한&amp;nbsp; 가격으로 이용할 수 있습니다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;https://cloud.google.com/ 에 접속하시게 되면 try it free 라는 문구와 함께&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1년 동안 유지되는 $ 300 무료 크레딧을 제공 해주고 있습니다. 저도 이 무료 크레딧으로&amp;nbsp; 진행하고 있습니다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;카드 결재 창이 중간에 나오지만, 무료 크레딧 소진 후 자동 진행되지 않음으로 우선 안심하시고 등록 하셔도 됩니다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h2 style=&quot;margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;1.Google Cloud Platform 가입&lt;/span&gt;&lt;/h2&gt;&lt;div style=&quot;margin: 0px; padding: 0px; outline: none; color: rgb(102, 102, 102); font-family: &amp;quot;Nanum Gothic&amp;quot;, &amp;quot;Noto Sans&amp;quot;, &amp;quot;Noto Sans KR&amp;quot;, sans-serif; font-size: 14px;&quot;&gt;&amp;nbsp;https://cloud.google.com&lt;/div&gt;&lt;div style=&quot;margin: 0px; padding: 0px; outline: none; color: rgb(102, 102, 102); font-family: &amp;quot;Nanum Gothic&amp;quot;, &amp;quot;Noto Sans&amp;quot;, &amp;quot;Noto Sans KR&amp;quot;, sans-serif; font-size: 14px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;img exif=&quot;{}&quot; id=&quot;tx_entry_91025_&quot; class=&quot;txc-image&quot; src=&quot;https://t1.daumcdn.net/cfile/tistory/99B1C73359CF4D5B31&quot; width=&quot;700&quot; height=&quot;469&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;가입이 완료되면 아래와 같이 Google Cloud Platform&amp;nbsp; 왼쪽 상단에 크렛딧 과 무료 기간이 나타나게 됩니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;저는 이미 가입이 되어 있는 상태라서 약간 다르게 나타나고 있습니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;Cloud platform 을 사용하는 목적이 여러 경우가 있지만,&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;저의 경우 집의 컴퓨터가 너무 좋지 않아서 training 용도의 마땅한 컴퓨팅 자원이 없어서 사용해보려고 합니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;img exif=&quot;{}&quot; id=&quot;tx_entry_54790_&quot; class=&quot;txc-image&quot; src=&quot;https://t1.daumcdn.net/cfile/tistory/99FEF83359CF510935&quot; width=&quot;700&quot; height=&quot;669&quot;&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;2. Project 생성&lt;/span&gt;&lt;/h2&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;클라우드 사용을 위해서는 프로젝트 생성을 우선 진행하셔야 됩니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;저는 임의로 rk-learning 이란 프로젝트로 만들어 보겠습니다.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;img exif=&quot;{}&quot; id=&quot;tx_entry_67141_&quot; class=&quot;txc-image&quot; src=&quot;https://t1.daumcdn.net/cfile/tistory/99CB1A3359CF51093A&quot; width=&quot;700&quot; height=&quot;648&quot;&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;3. VM 인스턴스 생성&lt;/span&gt;&lt;/h2&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;한 번 생성하게 되면 해당 인스턴스는 수정이 안됩니다. 물론 삭제하시고 새로 만드시면 상관 없습니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;CPU 2개,&amp;nbsp;HDD 10 GB, OS 는 가장 무난한 우분투 16.04 LTS 로 해당 인스턴스를 생성하겠습니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;여기서 만드는 순간 부터 요금이 나가기 때문에, 무료 크레딧이긴 하지만,&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;예상 비용이 얼마나 되는지는 꼭 한번 확인 하시기 바랍니다.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;잘못하시면 금방 소진될 수도 있어요&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;img exif=&quot;{}&quot; id=&quot;tx_entry_26839_&quot; class=&quot;txc-image&quot; src=&quot;https://t1.daumcdn.net/cfile/tistory/99CC1B3359CF510906&quot; width=&quot;700&quot; height=&quot;646&quot;&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;4. VM 인스턴스 시작&lt;/span&gt;&lt;/h2&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;디스크와 CPU 를 할당 받긴 하였지만, 크게 사용하지 않으시고 테스트만 해보신다면,&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;사용 후 인스턴스를 정지 상태로 해 놓으시는 것이 조금은, 크레딧을 덜 소진하는 방법일 듯 싶네요&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none; margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;인스턴스를&amp;nbsp;시작하게&amp;nbsp;되면 외부 IP 가 할당이 됩니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;저는 브라우저 창에서 SSH 로 접속해서 제가 자주 사용하는 user 로 사용자 추가를 해보도록 하겠습니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99801E3359CF5B4730&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99801E3359CF5B4730&quot; width=&quot;700&quot; height=&quot;268&quot; filename=&quot;vm_ip.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99B4233359CF5C422A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99B4233359CF5C422A&quot; width=&quot;700&quot; height=&quot;296&quot; filename=&quot;ssh_browser.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;-&amp;nbsp; 브라우저 창에서 열기&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;: 간단하게 제가 자주 사용하는 계정을 추가하였습니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 524px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99D6B33359CF5B471F&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99D6B33359CF5B471F&quot; width=&quot;524&quot; height=&quot;316&quot; filename=&quot;brower_shell.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;margin: 24px auto 16px; padding: 0px 0px 0.3em; outline: none; font-size: 26px; line-height: 1.25; box-sizing: border-box; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;5. SSH 를 통한 접속&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;다들 아시겠지만, 웹을 통해서 사용할 일은 거의 없단걸 아시꺼에요.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;주로 local 환경의 쉘을 통해 접속할 일이 대부분이기 때문에 SSH 등록을 통해서 간단하게 해당 VM에 접속 해보겠습니다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;순서는 아래와 같이 진행하시면 됩니다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. ssh-key -t rsa -f &amp;lt;SAVE_PATH&amp;gt;&amp;nbsp;-C &amp;lt;USER_NAME&amp;gt;&lt;/div&gt;&lt;div&gt;2. 생성된 public 키를 메타데이터 - SSH키 에 등록&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3. ssh -i &amp;lt;PRIVATE_KEY&amp;gt; USER_NAME@VM_외부_IP&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;* SSH 공개키는 웹에서 등록해주셔야 합니다.&lt;/div&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;img exif=&quot;{}&quot; id=&quot;tx_entry_20161_&quot; class=&quot;txc-image&quot; src=&quot;https://t1.daumcdn.net/cfile/tistory/99FE7F3359CF510923&quot; width=&quot;700&quot; height=&quot;493&quot;&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;* 로컬 환경에서 SSH 를 통해 VM 에 접속&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;- 아래 보시면 username 과 hostname 이 동일하게 보 일 수 있으나 phantoms 가 VM 인스턴스 입니다.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 648px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99FEC53359CF5B4805&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99FEC53359CF5B4805&quot; width=&quot;648&quot; height=&quot;796&quot; filename=&quot;ssh_login.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/tensorflow</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/39</guid>
      <comments>https://roadcom.tistory.com/39#entry39comment</comments>
      <pubDate>Mon, 25 Sep 2017 01:44:10 +0900</pubDate>
    </item>
    <item>
      <title>[ CNN ] inception-v3 (tf slim )</title>
      <link>https://roadcom.tistory.com/37</link>
      <description>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;*&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: rgb(255, 255, 255); font-family: inherit; font-size: 16px; white-space: pre-wrap;&quot;&gt;Here is an example of using google inception v3 model with tf.slim&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(33, 33, 33); font-family: inherit; font-size: 16px; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;TF-Slim 기존의 복잡한 모델을 조금 더 쉽게 정의하고 학습 하기위해 새롭게 나온 API 라고 합니다.&lt;/p&gt;
&lt;p&gt;아래 TF-Slim 에 포함되어 있는 CNN 중에 Inception V4 에 대해서 어떻게 사용하는지 설명을 드리고자 합니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;목표는 V4 &amp;nbsp;모델이었지만 컴퓨팅 자원의 한계로 V3 로 수정하였습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h1 style=&quot;box-sizing: border-box; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;; margin-top: 0px !important;&quot;&gt;TensorFlow-Slim image classification model library&lt;/h1&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;* https://github.com/tensorflow/models/tree/master/slim&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;table class=&quot;txc-table&quot; width=&quot;534&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; style=&quot;border: none; border-collapse: collapse; width: 534px;&quot; 맑은=&quot;&quot; 고딕&quot;,=&quot;&quot; sans-serif;font-size:13px&quot;=&quot;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-width: 1px; border-style: solid; border-color: rgb(95, 142, 239) rgb(209, 223, 250) rgb(95, 142, 239) rgb(95, 142, 239); background-color: rgb(95, 142, 239); color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt; Model&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(95, 142, 239); border-right: 1px solid rgb(209, 223, 250); border-top: 1px solid rgb(95, 142, 239); background-color: rgb(95, 142, 239); color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Top 1 &lt;br /&gt;Accuracy (%)&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(95, 142, 239); border-right: 1px solid rgb(95, 142, 239); border-top: 1px solid rgb(95, 142, 239); background-color: rgb(95, 142, 239); color: rgb(255, 255, 255);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Top 5 &lt;br /&gt;Accuracy (%)&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;Inception V1&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;69.8&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;89.6&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;Inception V2&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;73.9&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;91.8&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;Inception V3&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;78&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;93.9&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;Inception V4&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;80.2&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;95.2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;Inception-ResNet-v2&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;80.4&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;95.3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;ResNet V1 50&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;75.2&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;92.2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;ResNet V1 101&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;76.4&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;92.9&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;ResNet V1 152&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;76.8&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;93.2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;ResNet V2 50^&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;75.6&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;92.8&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;ResNet V2 101^&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(209, 223, 250); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;77&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(209, 223, 250); border-right: 1px solid rgb(95, 142, 239); background-color: transparent; color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;93.7&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 213px; height: 24px; border-bottom: 1px solid rgb(95, 142, 239); border-right: 1px solid rgb(209, 223, 250); border-left: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p&gt;&amp;nbsp;ResNet V2 152^&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 125px; height: 24px; border-bottom: 1px solid rgb(95, 142, 239); border-right: 1px solid rgb(209, 223, 250); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;77.8&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 202px; height: 24px; border-bottom: 1px solid rgb(95, 142, 239); border-right: 1px solid rgb(95, 142, 239); background-color: rgb(239, 239, 255); color: rgb(0, 0, 0);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;94.1&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;설치부터 dataset 을 만들고training 와 최종 evaluation 까지 전체 방향에 대해서 수행해 볼 수 있도록&amp;nbsp;&lt;/p&gt;
&lt;p&gt;설명드리겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Linux 환경에 익숙하지 않으신 분들 위해서 windows 에서 해당 프로젝트를 진행 해보겠습니다.&lt;/p&gt;
&lt;p&gt;물론 python 3.6 + tensorflow 1.0▲ 버전은 필수로 설치되어야 있어야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;1.Installing the TF-slim image models library&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&amp;nbsp;github 에서 필요한 model 및 tf-slim 라이브러리를 clone 하도록 하겠습니다.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal; color: rgb(36, 41, 46);&quot;&gt;&lt;p&gt;git clone https://github.com/tensorflow/models/&lt;/p&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 634px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9960DE3359BBC61410&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9960DE3359BBC61410&quot; width=&quot;634&quot; height=&quot;512&quot; filename=&quot;git_clone_model.png&quot; filemime=&quot;image/png&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h1 style=&quot;box-sizing: border-box; margin: 24px 0px 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;2.Preparing the datasets&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;기본적으로 데이터 set은 cifar10, flowers, mnist , imagenet 등을 자동으로 다운로드 받을 수 있지만 ,&lt;/p&gt;
&lt;p&gt;자신만의 데이터를 활용하는 방법을 알려드리기 구글에서 새 이미지를 모아봤습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre style=&quot;padding: 16px; background-color: rgb(246, 248, 250); box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 3px; word-break: normal; color: rgb(36, 41, 46);&quot;&gt;&lt;p&gt;download_and_convert_data.py # 데이터셋 (병아리, 매, 비둘기, 참새 4종 ) &lt;/p&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 160px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99E5543359BBC82F2B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99E5543359BBC82F2B&quot; width=&quot;160&quot; height=&quot;160&quot; filename=&quot;chick.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 239px; width: 239px; height: 160px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99E3913359BBC82F0E&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99E3913359BBC82F0E&quot; width=&quot;239&quot; height=&quot;160&quot; filename=&quot;hawk.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;width: 239px; height: 160px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 238px; width: 238px; height: 160px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99BD703359BBC82F17&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99BD703359BBC82F17&quot; width=&quot;238&quot; height=&quot;160&quot; filename=&quot;pigeon.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;width: 238px; height: 160px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 240px; width: 240px; height: 160px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/999BC33359BBC82F13&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F999BC33359BBC82F13&quot; width=&quot;240&quot; height=&quot;160&quot; filename=&quot;sparrow.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;width: 240px; height: 160px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 476px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9914023359BBC6E001&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9914023359BBC6E001&quot; width=&quot;476&quot; height=&quot;362&quot; filename=&quot;preapre_dataset.PNG&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&amp;nbsp;3.Converting to TFRecord format&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;dataset 이 로컬에 저장되어 있다보니 slim 에 있는 예제대로 수행이 어려워 아래 몇가지 수정 사항이 생기네요&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div&gt;&lt;pre style=&quot;padding: 16px; background-color: rgb(246, 248, 250); box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 3px; word-break: normal; color: rgb(36, 41, 46);&quot;&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; font-size: 10pt; white-space: normal;&quot;&gt;* datasets/download_and_convert_birds.py &amp;nbsp;#추가&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 10pt; color: rgb(0, 0, 0); font-family: &amp;quot;맑은 고딕&amp;quot;, sans-serif; white-space: normal;&quot;&gt;* download_and_convert_data.py &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# 수정&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;margin-left: 4em;&quot;&gt;&amp;lt;수정 내용 &amp;gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 620px; width: 620px; height: 500px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99F3BE3359BBDBBE29&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99F3BE3359BBDBBE29&quot; width=&quot;620&quot; height=&quot;500&quot; filename=&quot;download_and_convert_data.png&quot; filemime=&quot;image/png&quot; style=&quot;width: 620px; height: 500px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt; 추가 되어야 할 파일 &amp;gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 620px; width: 620px; height: 760px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99BED73359BBDBBE15&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99BED73359BBDBBE15&quot; width=&quot;620&quot; height=&quot;760&quot; filename=&quot;download_and_convert_birds.png&quot; filemime=&quot;image/png&quot; style=&quot;width: 620px; height: 760px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;python download_and_convert_data.py ^
  --dataset_name=birds ^
  --dataset_dir=D:\tmp\birds
&lt;/code&gt;&lt;/pre&gt;

&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 634px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9949A63359BBDD100E&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9949A63359BBDD100E&quot; width=&quot;634&quot; height=&quot;512&quot; filename=&quot;convert_script.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h1 style=&quot;box-sizing: border-box; margin: 24px 0px 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;Training a model from scratch.&lt;/h1&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 13px;&quot;&gt;컴퓨터 자원의 한계로 이부분은 넘어가고 기존 만들어진 모델을 fine-tuning 해 보도록 하겠습니다,&lt;/span&gt;&lt;/p&gt;&lt;h1 style=&quot;box-sizing: border-box; margin: 24px 0px 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;4.Fine-tuning a model from an existing checkpoint&lt;/h1&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal; color: rgb(36, 41, 46);&quot;&gt;&lt;p&gt;python train_image_classifier.py \
    --train_dir=&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;${TRAIN_DIR}&lt;/span&gt; \
    --dataset_dir=&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;${DATASET_DIR}&lt;/span&gt; \
    --dataset_name=flowers \
    --dataset_split_name=train \
    --model_name=inception_v3 \
    --checkpoint_path=&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;${CHECKPOINT_PATH}&lt;/span&gt; \
    --checkpoint_exclude_scopes=InceptionV3/Logits,InceptionV3/AuxLogits \
    --trainable_scopes=InceptionV3/Logits,InceptionV3/AuxLogits \
    --max_number_of_steps=2100 \
&lt;span style=&quot;font-size: 13.6px;&quot;&gt;    --save_summaries_secs=600 \
&lt;/span&gt;&lt;span style=&quot;font-size: 13.6px;&quot;&gt;    --save_interval_secs=300 \
&lt;/span&gt;&lt;span style=&quot;font-size: 13.6px;&quot;&gt;    --batch_size=32   #resource exhausted error 시 size 를 줄여주세요&lt;/span&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 664px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9962E13359BFD30423&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9962E13359BFD30423&quot; width=&quot;664&quot; height=&quot;512&quot; filename=&quot;train_script_inceptionv3.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 669px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99FE483359BFD30436&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99FE483359BFD30436&quot; width=&quot;669&quot; height=&quot;512&quot; filename=&quot;train_script_inceptionv3_2.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h1 style=&quot;box-sizing: border-box; margin: 24px 0px 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;5.Evaluating performance of a model&lt;/h1&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre style=&quot;box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal; color: rgb(36, 41, 46);&quot;&gt;&lt;p&gt;python eval_image_classifier.py \
    --alsologtostderr \
    --checkpoint_path=&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;${CHECKPOINT_FILE}&lt;/span&gt; \
    --dataset_dir=&lt;span class=&quot;pl-smi&quot; style=&quot;box-sizing: border-box;&quot;&gt;${DATASET_DIR}&lt;/span&gt; \
    --dataset_name=imagenet \
    --dataset_split_name=validation \
    --model_name=inception_v3 \
    --batch_size=16  ## GPU 가 한참 지난 750 Ti 라서 batch size 를 키우면 할당이 안되네요&lt;/p&gt;&lt;/pre&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 668px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9971B73359BFD14811&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9971B73359BFD14811&quot; width=&quot;668&quot; height=&quot;898&quot; filename=&quot;eval_script_inceptionv3.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h1 style=&quot;box-sizing: border-box; margin: 24px 0px 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom: 1px solid rgb(234, 236, 239); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;;&quot;&gt;6.Test sample&amp;nbsp;images from trained model&lt;/h1&gt;&lt;pre style=&quot;padding: 16px; background-color: rgb(246, 248, 250); box-sizing: border-box; font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; word-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 3px; word-break: normal; color: rgb(36, 41, 46);&quot;&gt;&lt;p&gt;label_image.py sciprt # 특정 폴더 이미지를 해당 모델로 테스트&lt;/p&gt;&lt;/pre&gt;



&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;

import glob
import os,re,sys
import argparse
import importlib
import cv2

import tensorflow as tf
from preprocessing import inception_preprocessing

slim = tf.contrib.slim

# prefix image size
image_size = 299

def run(args):
	data_path = args.data_path
	label_path = args.label_path

	model_path = args.model_path
	model_name = args.model_name
	model_scope = model_name +'_arg_scope'
	
	inception = importlib.import_module('nets.'+model_name)


	with tf.Graph().as_default():
		with slim.arg_scope(getattr(inception,model_scope)()):


			files = glob.glob(data_path+os.path.sep+&quot;*.jpg&quot;)
			file_list = list()

			for idx,f in enumerate(files):
				f_string = tf.gfile.FastGFile(f, 'rb').read()
				test_img = tf.image.decode_jpeg(f_string, channels=3)
				processed_image = inception_preprocessing.preprocess_image(test_img, image_size, image_size, is_training=False)
				#processed_images = tf.expand_dims(processed_image, 0)
				file_list.append(os.path.basename(f))
				if(idx == 0):
					processed_images = [processed_image]
				else:
					processed_images.append(processed_image)

			processed_images = tf.stack(processed_images,axis=0)

			with open(label_path,'r') as rdata:
				names = dict()
				for row in rdata:
					strip_row = row.strip()
					split_row = strip_row.split(&quot;:&quot;)
					if(len(split_row) == 2):
						names[int(split_row[0])]=split_row[1]


			logits, _ = getattr(inception,model_name)(processed_images, num_classes=4, is_training=False)
			probabilities = tf.nn.softmax(logits)

			init_fn = slim.assign_from_checkpoint_fn(model_path, slim.get_model_variables('InceptionV3'))

			with tf.Session() as sess:
				init_fn(sess)

				np_image, probabilities = sess.run([processed_images, probabilities])

				print(&quot;\n========  DATA RESULT  =======\n&quot;)
				print(&quot;filename\t&quot;+&quot;\t&quot;.join(names.values()))

				for idx,iter in enumerate(probabilities):
					print(file_list[idx]+'\t' +'\t'.join([str(round(i,2)) for i in iter]))
				

if __name__ == '__main__':

	parser = argparse.ArgumentParser()
	parser.add_argument(&quot;--data_path&quot;,help=&quot;the path to test images&quot;)
	parser.add_argument(&quot;--model_path&quot;)
	parser.add_argument(&quot;--model_name&quot;)
	parser.add_argument(&quot;--label_path&quot;)
	if(len(sys.argv) != 5):
		parser.print_help()
		parser.exit()
	args = parser.parse_args()
	run(args)


&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;label 코드를 활용하여 아래 최종 confusion matrix를 구해봤습니다.&lt;/p&gt;&lt;p&gt;전체 학습 보다는&amp;nbsp;&lt;span style=&quot;background-color: rgb(246, 248, 250); color: rgb(36, 41, 46); font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 13.6px;&quot;&gt;--trainable_scopes=InceptionV3/Logits,InceptionV3/AuxLogits&amp;nbsp;&lt;/span&gt;&amp;nbsp;에서 설정했듯이&lt;/p&gt;&lt;p&gt;Logits 와 AuxLogits layter 만 학습을 진행했는데 생각보다 꽤 괜찮은 결과가 나온 것 같습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 633px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9916153359BFCBCF1A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9916153359BFCBCF1A&quot; width=&quot;633&quot; height=&quot;662&quot; filename=&quot;label_script_result.png&quot; filemime=&quot;image/png&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/tensorflow</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/37</guid>
      <comments>https://roadcom.tistory.com/37#entry37comment</comments>
      <pubDate>Wed, 13 Sep 2017 16:49:23 +0900</pubDate>
    </item>
    <item>
      <title>[ MLP ] neural network regression</title>
      <link>https://roadcom.tistory.com/36</link>
      <description>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;*&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: rgb(255, 255, 255); font-family: inherit; font-size: 16px; white-space: pre-wrap;&quot;&gt;This is an example of regression of the sin function with MLP&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(255, 255, 255); font-family: inherit; font-size: 16px; white-space: pre-wrap;&quot;&gt;(Multi-layer perceptron)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(33, 33, 33); font-family: inherit; font-size: 16px; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;요즘 주변에서는 많이 사용하는 neural network 통해서&amp;nbsp;&lt;/p&gt;&lt;p&gt;regression을 할 수는 없을까라는 잡생각이 들어서 간단하게 만들어 봤습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;주어진 범위만&amp;nbsp;벗어나면 맞지도 않는 것을 왜하지 라고 하시는 답을 아시는 분도 계시겠지만,&amp;nbsp;&lt;/p&gt;&lt;p&gt;심심풀이로 간단하게 정리하고 만든 내용 공유 차원에서 적어 나가겠습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;아래 처럼 최종 출력단을 SUM 으로 하여서 알고 있는 답과 비교하면서 학습을 진행하도록 만들었습니다.&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;cost function 으로는 least square method 방식으로 $\sum_{k=1}^N (predict - correct)^2$&lt;span style=&quot;color: rgb(106, 115, 125); font-family: SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, Menlo, Courier, monospace; font-size: 10pt; white-space: pre;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;로 정하였고,&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;activation function 을 relu 로 하여서 training 을 시도해봤습니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99FD5B3359AEAA9702&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99FD5B3359AEAA9702&quot; width=&quot;700&quot; height=&quot;418&quot; filename=&quot;nn_model.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;■&lt;/span&gt; $sin(x)$ 함수&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9998133359B1480B1A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9998133359B1480B1A&quot; width=&quot;640&quot; height=&quot;478&quot; filename=&quot;nn_sin.png&quot; filemime=&quot;image/png&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;■&lt;/span&gt;&amp;nbsp;$sin(x)$ neural network regression - relu&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99DFE73359B14B8E27&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99DFE73359B14B8E27&quot; width=&quot;640&quot; height=&quot;478&quot; filename=&quot;nn_sin_relu.png&quot; filemime=&quot;image/png&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;처음 하고난 결과는 두둥,,, 뭔가 어설프고 이상한게 보이시죠.&lt;/p&gt;&lt;p&gt;여기에서 제가 한가지 깜빡 했던, 아니 오해했던 내용이 있었네요,&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;neural network 에서 sigmoid, tanh 함수들은 무조건 사용하지 말고, relu 를 쓰라고 머릿속에 암기되어 있어&lt;/p&gt;&lt;p&gt;regression 문제까지 relu 를 써버렸네요,.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;regression 의 특성상 부드럽게 중간 중간을 채워주는 무엇인가가 필요한데,&lt;/p&gt;&lt;p&gt;relu 함수는 그렇게 부드러운 아이는 아니란걸 깜빡했습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;b&gt;regression &lt;/b&gt;vs &lt;b&gt;classification&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;다시 relu 함수를 tanh 나 sigmoid 로 변경해서 training 을 시도했습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;역시 예상이 맞았습니다. 부드러운 activation 함수로 바꾸고 나니, 한결 모양이 깔끔해졌습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;■&lt;/span&gt;&amp;nbsp;$sin(x)$ neural network regression - tanh&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px; width: 700px; height: 511px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9933183359B147DE13&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9933183359B147DE13&quot; width=&quot;700&quot; height=&quot;511&quot; filename=&quot;nn_sin_fit.png&quot; filemime=&quot;image/png&quot; style=&quot;width: 700px; height: 511px;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;모델로 함수를 쓰지않고, neural network 쓰다보니 역시 학습하지 않은 범위를 넘어가 버리면&lt;/p&gt;&lt;p&gt;값들이 산으로 가버렸네요&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;supervised learning&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;아래는 제가 간략하게 구현한 코드 입니다.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
# python version 3.6.2
# tensorflow version 1.3.0

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt


def make_model(X,layer_shape,**kwargs):

	atv_enum = {'tanh':tf.nn.tanh,'relu':tf.nn.relu,'sigmoid':tf.nn.sigmoid}
	atv_fun = active_type[atv_enum[type]] if 'atv_type' in kwargs else atv_enum['tanh']

	layer = tf.multiply(X,1)
	for idx,size in enumerate(layer_shape[:-1]):
		W = tf.Variable(tf.random_normal([size,layer_shape[idx+1]]))
		b = tf.Variable(tf.random_normal([layer_shape[idx+1]]))
		layer = tf.add(tf.matmul(layer,W),b)

		if(idx != len(layer_shape)-2):
			layer = atv_fun(layer)

	return layer


if __name__ == '__main__':
	x_data = np.linspace(-2*np.pi,2*np.pi, 100).reshape(-1,1)
	y_data = np.sin(x_data)

		
	X = tf.placeholder(tf.float32,name='X')
	Y = tf.placeholder(tf.float32,name='Y')

	# activation function 으로 tanh 사용하였습니다.
	# neural network 구성은 1,5,5,1 로 구성하였습니다.
	model = make_model(X,[1,5,5,1])

	# leat square method 로 cost 함수 정의하였습니다.
	cost = tf.reduce_mean(tf.square(model - Y))
	train_op  = tf.train.AdamOptimizer(learning_rate=0.02).minimize(cost)

	init = tf.global_variables_initializer()
	with tf.Session() as sess:
		sess.run(init)

		for step in range(20000):
			error,_ = sess.run([cost,train_op],feed_dict={X:x_data,Y:y_data})
			if(step % 100 == 0):
				print(step,error)

		# 테스트 데이터를 -4 pi ~ 4 pi 로 구간을 넓혔습니다.
		tx_data = np.linspace(-4*np.pi,4*np.pi, 100).reshape(-1,1)
		predict = sess.run(model,feed_dict={X:tx_data})
		plt.plot(tx_data.flatten(),predict.flatten(),'ro')

		
	plt.plot(x_data.flatten(),y_data.flatten())
	plt.show()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/tensorflow</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/36</guid>
      <comments>https://roadcom.tistory.com/36#entry36comment</comments>
      <pubDate>Mon, 4 Sep 2017 22:13:52 +0900</pubDate>
    </item>
    <item>
      <title>[ RANSAC ] 타원 피팅 (fit ellipse using ransac)</title>
      <link>https://roadcom.tistory.com/33</link>
      <description>&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;또 등장하는 제 마우스 패드와 선물 받은 큐브를 통해서&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;가려진 타원을 어떻게 복원할지에 대해서 설명을 드리고자 합니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;일반적으로 circle 과 기존의 ellipse fitting 으로는 아래 마우스 패드의 외각선을 추출해 진행해보면 이상한 결과를 얻을 수 있습니다. 물론,, 아래 마우스 패드의 외각선 정보에 이상한 그림이 겹쳐져 잘못된 정보를 포함해 버렸기 때문이죠 ^^&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;* fit ellipse using RANSAC (random sample consensu)&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99AEE43359832A1A21&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99AEE43359832A1A21&quot; width=&quot;700&quot; height=&quot;525&quot; filename=&quot;out.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;RANSAC(random sample consensu) 이란 ?&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;그림의 마우스 패드를 검출 하려고 보면&amp;nbsp;외각선 정보에 큐브 외각선이 겹쳐 나타나게 됩니다.&amp;nbsp;&amp;nbsp;어떻게 하면 이 잘못된 정보 (outlier) 를 제외하고 피팅을 진행 할 수 있을까요? RANSAC은 데이터 집합 중에 일정확률을 가지고 샘플을 추려서 모델에 맞춰보고 해당 샘플 중에 가장 데이터 집합을 많이 대변하는 모델을 추려내는 작업이라고 생각할 수 있습니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;* 말로 설명하려니 어렵네요. 아래 한번 RANSAC 에 대한 접근 방법을 보시면 바로 이해하실 수 있습니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;모델 : &amp;nbsp;타원(rotated ellipse)&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;데이터 : &amp;nbsp;마우스 패드 외각선(Inlier) 와 큐브 외각선(outlier)이&amp;nbsp;포함된 외각선 집합&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;1. 일정 확률을 가지고 DATA 집합에서 임의 추출 진행&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;2. 추출진 sample 을 통해서 모델을 예측&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;3. 예측 모델에서 어느정도의 offset 범위 안에 들어오는 기존보다 클 경우, 해당 (x,y) 값들을 저장&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;4. 1 - 3 을 N 번 반복 수행&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;5. 최종 저장된 (X,Y) 값을 통해서 fitting 진행&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
import cv2
import os,re,sys
import numpy as np


def fit_rotated_ellipse_ransac(data,iter=30,sample_num=10,offset=80.0):

	count_max = 0
	effective_sample = None

	for i in range(iter):
		sample = np.random.choice(len(data), sample_num, replace=False)

		xs = data[sample][:,0].reshape(-1,1)
		ys = data[sample][:,1].reshape(-1,1)

		J = np.mat( np.hstack((xs*ys,ys**2,xs, ys, np.ones_like(xs,dtype=np.float))) )
		Y = np.mat(-1*xs**2)
		P= (J.T * J).I * J.T * Y

		# fitter a*x**2 + b*x*y + c*y**2 + d*x + e*y + f = 0
		a = 1.0; b= P[0,0]; c= P[1,0]; d = P[2,0]; e= P[3,0]; f=P[4,0];
		ellipse_model = lambda x,y : a*x**2 + b*x*y + c*y**2 + d*x + e*y + f

		# threshold 
		ran_sample = np.array([[x,y] for (x,y) in data if np.abs(ellipse_model(x,y)) &amp;lt; offset ])

		if(len(ran_sample) &amp;gt; count_max):
			count_max = len(ran_sample) 
			effective_sample = ran_sample

	return fit_rotated_ellipse(effective_sample)


def fit_rotated_ellipse(data):

	xs = data[:,0].reshape(-1,1) 
	ys = data[:,1].reshape(-1,1)

	J = np.mat( np.hstack((xs*ys,ys**2,xs, ys, np.ones_like(xs,dtype=np.float))) )
	Y = np.mat(-1*xs**2)
	P= (J.T * J).I * J.T * Y

	a = 1.0; b= P[0,0]; c= P[1,0]; d = P[2,0]; e= P[3,0]; f=P[4,0];
	theta = 0.5* np.arctan(b/(a-c))  
	
	cx = (2*c*d - b*e)/(b**2-4*a*c)
	cy = (2*a*e - b*d)/(b**2-4*a*c)

	cu = a*cx**2 + b*cx*cy + c*cy**2 -f
	w= np.sqrt(cu/(a*np.cos(theta)**2 + b* np.cos(theta)*np.sin(theta) + c*np.sin(theta)**2))
	h= np.sqrt(cu/(a*np.sin(theta)**2 - b* np.cos(theta)*np.sin(theta) + c*np.cos(theta)**2))

	ellipse_model = lambda x,y : a*x**2 + b*x*y + c*y**2 + d*x + e*y + f

	error_sum = np.sum([ellipse_model(x,y) for x,y in data])
	print('fitting error = %.3f' % (error_sum))

	return (cx,cy,w,h,theta)

def main(img_path):

	color_list = [(238,0,0),(0,252,124),(142,56,142),(10,20,0),(245,245,245)]

	src = cv2.imread(img_path, cv2.IMREAD_COLOR)
	gray = cv2.cvtColor(src,cv2.COLOR_RGB2GRAY)
	retv, th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU) 

	color_th = cv2.cvtColor(th,cv2.COLOR_GRAY2RGB)

	_, contours , _ = cv2.findContours(th,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
	zeros = np.zeros(np.shape(th),dtype=np.uint8)

	for con in contours:
		approx = cv2.approxPolyDP(con, 0.01 * cv2.arcLength(con,True),True)
		area = cv2.contourArea(con)
		if(len(approx) &amp;gt; 10 and area &amp;gt; 30000):

			# fit ellipse
			cx,cy,w,h,theta = fit_rotated_ellipse(con.reshape(-1,2))
			cv2.ellipse(src,(int(cx),int(cy)),(int(w),int(h)),theta*180.0/np.pi,0.0,360.0,color_list[2],2)

			# fit ellipse using ransac
			cx,cy,w,h,theta = fit_rotated_ellipse_ransac(con.reshape(-1,2))
			cv2.ellipse(src,(int(cx),int(cy)),(int(w),int(h)),theta*180.0/np.pi,0.0,360.0,color_list[0],2)

	cv2.imwrite('out.jpg',src)

if __name__ == '__main__':
	if(len(sys.argv) != 2):
		print('usage : {0} &amp;lt;image_abs_path&amp;gt;'.format(sys.argv[0]))
		exit(0)
	main(sys.argv[1])

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>영상처리</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/33</guid>
      <comments>https://roadcom.tistory.com/33#entry33comment</comments>
      <pubDate>Thu, 3 Aug 2017 22:52:57 +0900</pubDate>
    </item>
    <item>
      <title>[ 최소자승법 ] 원, 타원 측정</title>
      <link>https://roadcom.tistory.com/30</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;b&gt;* 이글은 다크프로그래머 님의 - [최소자승법의 이해] 를&amp;nbsp;읽고 필요한 부분을 정리&amp;nbsp;및 제가 아는 내용을 추가하였습니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14.6667px;&quot;&gt;&lt;a href=&quot;http://darkpgmr.tistory.com/56&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;http://darkpgmr.tistory.com/56&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;** Least Square Method, fit ellipse, fit circle, python opencv&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;가끔 영상을 보면서 원과 타원에 대해서 어떠한 정보를 얻어야 될 때가 있습니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;외각선 정보보다, 몇개의 파라미터 값(중심, 사이즈 ...)만 알면 표현이 훨씬 간단할 뿐만 아니라&amp;nbsp;각 물체(원, 타원, 사각) 간의 관계 표현할 때 이만큼 좋은 정보가 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;그럼 세부적으로 중심, 지름, 장축, 단축 등 이런 정보들은 어떻게 얻을 수 있을 까요?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;이럴 때 많이 사용하는 방식이 피팅(fitting)을 사용해서 원의 방정식 또는 타원의 방정식에 얻어진 외각선( x,y 위치 정보)에 데이터가 얼마나 잘 맞는지 넣어보면서 파라미터(장축,단축, 중심) 를 찾는 방향으로 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14.6667px;&quot;&gt;영상내 어떤 둥그런 물체(object) 를 필터링 해서 크기가 얼마인지 알고 싶을 때,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14.6667px;&quot;&gt;제가 아끼는 마우스패드가 쇼파 위에 이쁘게 놓여있네요, 이럴 때 이 마우스 패드의 중심과 크기를 알려고 하면 간단히 opencv 의&amp;nbsp;fitEllipse 함수를 사용해도 큰 문제는 없지만, 기본 개념부터 구현해 보았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14.6667px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14pt; color: rgb(0, 0, 0);&quot;&gt;□&lt;/span&gt;&lt;span style=&quot;font-size: 14pt; color: rgb(0, 0, 0);&quot;&gt;원의 방정식&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;답을 찾아가는 방법으로 pesudo inverse 방식을 쓰려고 양함수( f(x,y) = z) 모델을 이용하여 수식을 정리하면 아래와 같이 a,b,c 라는 파라미터를 구할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;$$ \begin{matrix} { (x-x_1)^2 } + &amp;nbsp;{ (y-y_1)^2 &amp;nbsp;} &amp;amp;=&amp;amp; r^2 \\ \\ &amp;nbsp;\Rightarrow x^2+y^2 -2ax - 2by + a^2 + b^2 - r^2 &amp;amp;=&amp;amp; 0 \\ \\ \Rightarrow x^2+y^2 -2ax - 2by + c = 0 &amp;amp;,&amp;amp; c = a^2 + b^2 - r^2 \\ \\ \Rightarrow &amp;nbsp;-2ax - 2by + c &amp;amp;=&amp;amp; -x^2-y^2 \end{matrix} $$&lt;/p&gt;
&lt;p&gt;$$ \begin{matrix} \begin{bmatrix} -2x_1&amp;amp; -2y_1&amp;amp; 1\\ \vdots&amp;amp; \vdots&amp;amp;\vdots &amp;nbsp;\\ -2x_n&amp;amp; -2y_n&amp;amp; 1 \end{bmatrix} &amp;nbsp;\begin{bmatrix} a \\ b \\ c \end{bmatrix} &amp;nbsp;= \begin{bmatrix} -x_1^2-y_1^2 \\ \vdots \\ -x_n^2-y_n^2 \end{bmatrix} \\ &amp;nbsp;\\ &amp;nbsp;J =\begin{bmatrix} -2x_1&amp;amp; -2y_1&amp;amp; 1 \\ \vdots&amp;amp; \vdots&amp;amp;\vdots &amp;nbsp;\\ -2x_n&amp;amp; -2y_n&amp;amp; 1 \end{bmatrix}, X = \begin{bmatrix} a \\ b \\ c \end{bmatrix}, Y = \begin{bmatrix} -x_1^2-y_1^2 \\ \vdots \\ -x_n^2-y_n^2 \end{bmatrix} \\ \\ J X = Y \\ &amp;nbsp;X = {(J^T J)}^{-1} J^T Y \\ \\ \end{matrix} $$&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14pt; color: rgb(0, 0, 0);&quot;&gt;□ 타원의 방정식&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;중심이 0,0 위치에서의 타원의 방정식&lt;/p&gt;
&lt;p&gt;$$ \Large&amp;nbsp;\begin{matrix}{ x^2 \over w^2 } +&amp;nbsp;&amp;nbsp;{ y^2 \over h^2 } = 1&amp;nbsp; \end{matrix} $$&amp;nbsp;&lt;/p&gt;
&lt;p&gt;원은 회전된 경우(rotated) 문제 없지만, 타원의 경우는 중요하기 때문엥&amp;nbsp;이를 방정식에 반영 해주어야 합니다.&lt;/p&gt;
&lt;p&gt;접근 방법을&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;1. roatated ellipse (회전이 되어 있는 타원)&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;2. rotated ellipse 의 회전 각도를 반대로 적용하여&amp;nbsp;타원의 방정식 폼에 맞게 수정&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;3. 타원의 중심이 이동 할 수 있음으로 타원의 방정식에 반영&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;CCW 로 회전이 되어 있다는 가정하에 &amp;nbsp;복원을 위해 CW 방향으로 회전 변환을 적용하겠습니다.&lt;/p&gt;
&lt;p&gt;$$ \begin{matrix} &amp;nbsp;&amp;nbsp;\begin{bmatrix} x' \\ y'&amp;nbsp;\end{bmatrix} &amp;nbsp;= \begin{bmatrix} cos(\theta) &amp;amp; sin(\theta) \\ -sin(\theta) &amp;amp; cos(\theta) \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} \\ \\ \Rightarrow x' = cos(\theta)x + sin(\theta)y \\ \Rightarrow y' = -sin(\theta)x + cos(\theta)y&amp;nbsp;\end{matrix} $$&amp;nbsp;&lt;/p&gt;
&lt;p&gt;최종적으로 x1,y1 의 중심에 회전이 반영된 방정식입니다.&lt;/p&gt;&lt;p&gt;$$&amp;nbsp;{ (x − x_1 )^2 \over a^2 } +&amp;nbsp; { (y − y_1 )^2 \over b^2} =&amp;nbsp;1 \\&amp;nbsp;&amp;nbsp;{ [cos(\theta)x&amp;nbsp; + sin(\theta)y − x_1 ]^2 \over a^2 } +&amp;nbsp; { [−sin(\theta)x + cos(\theta)y −y_1]^2 \over b^2} = 1&amp;nbsp;$$&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;위 수식을 풀어서 계수를 정리하면 다음과 같습니다.&amp;nbsp; 여기에&amp;nbsp;&lt;/span&gt;간단하게 회전각도에 대해서만 유도를 해보면&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;&amp;nbsp;추가된 내용&lt;/span&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;$$&amp;nbsp; x^2[b^2cos^2(\theta) + a^2sin^2(\theta)] + xy[2b^2sin(\theta)cos(\theta) − 2a^2sin(\theta)cos(\theta)] +y^2[b^2sin^2(\theta)+a^2cos^2(\theta)] +\cdots = a^2b^2 \\ \\ c_1 x^2 + c_2 xy +c_3 y^2 +c_4 x + c_5 y + c6 = 0 $$&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;$$ \begin{array}{l} { c2 \over (c1 − c3) } = { 2b^2sin\theta cos\theta − 2a^2sin\theta cos\theta \over b^2cos^2\theta + a^2sin^2\theta −&amp;nbsp; b^2cos^2\theta −&amp;nbsp; a^2sin^2\theta} = {2sin\theta cos\theta(b^2 − a^2) \over(cos^2\theta − sin^2\theta)(b^2 − a^2)}&amp;nbsp; \\ = { 2sin\theta cos\theta \over cos^2\theta \; sin^2\theta} = { sin2\theta \over cos 2\theta } = tan2\theta \\ \therefore \theta = {1 \over 2} tan^{−1}({c2 \over {c1 − c3}}) \end{array}$$&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;아래 코드에 시간이 되시는 분들은 한번 생각해서 유도 해보시면 큰 도움이 되실 것 같아요.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;$$ \begin{matrix} &amp;nbsp;ax^2 + bxy + cy^2 + dx + ey + f &amp;amp;=&amp;amp; 0 \\ \\ \Rightarrow&amp;nbsp;x^2 + b'xy + c'y^2 + d'x + e'y + f' &amp;amp;=&amp;amp; 0 &amp;nbsp;\end{matrix} \tag{ Dividing by a} $$&lt;/p&gt;
&lt;p&gt;$$\begin{matrix} &amp;nbsp;\begin{bmatrix} x_1y_1&amp;amp; {y_1}^2 &amp;amp; x_1 &amp;amp; y_1 &amp;amp; 1 \\ \\ \vdots &amp;amp; \vdots &amp;amp; \vdots &amp;amp; \vdots &amp;amp; \vdots \\ x_ny_n&amp;amp; {y_n}^2 &amp;amp; x_n &amp;amp; y_n &amp;amp; 1 \end{bmatrix} \begin{bmatrix} b'\\ c'\\ d'\\ e'\\ &amp;nbsp;f' \end{bmatrix} &amp;amp;=&amp;amp; \begin{bmatrix} - {x_1}^2\\ \vdots \\ -{x_n}^2 \end{bmatrix} \\ \end{matrix} &amp;nbsp;\tag{ explicit function form, y=f(x,y)} $$&lt;/p&gt;
&lt;p&gt;$$ \begin{matrix}&amp;nbsp;J X &amp;amp;=&amp;amp; Y&amp;nbsp;\\ X &amp;amp;=&amp;amp; {(J^T J)}^{-1} J^T Y&amp;nbsp;\end{matrix} \tag{Pesudo inver }$$&lt;/p&gt;
&lt;p&gt;$$ \Large \begin{matrix} &amp;nbsp; \theta = { 1 \over 2&amp;nbsp;} \tan^{-1}( { b \over a-c }) &amp;nbsp;\\ c_x = { &amp;nbsp;2cd - be \over b^2 - 4ac&amp;nbsp;} \\ c_y&amp;nbsp;= { &amp;nbsp;2ae- bd&amp;nbsp;\over b^2 - 4ac&amp;nbsp;} \\ &amp;nbsp;w = \sqrt{ {ac_x^2 + bc_xc_y+ cc_y^2 -f \over a \cos^2\theta + b\cos\theta\sin\theta + c\sin^2\theta&amp;nbsp;} } &amp;nbsp;\\ h&amp;nbsp;= \sqrt{ {ac_x^2 + bc_xc_y+ cc_y^2 -f \over a \sin^2\theta -&amp;nbsp;b\cos\theta\sin\theta + c\cos^2\theta&amp;nbsp;}&amp;nbsp;} &amp;nbsp;\end{matrix} $$&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14.6667px;&quot;&gt;노랑색의 경우 원으로 피팅한 결과 입니다. 당연히 LSM(Least Square Method)&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 14.6667px;&quot;&gt;방식으로 맞추다 보니 전체의 모양이 반영이 안되었네요, 파랑색의 경우는 타원의 피팅한 결과 입니다. fitEllipse 함수와 거의 유사하게 나오는 것을 확인 하 실 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14.6667px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 300px; width: 300px; height: 400px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/25AD47335973751832&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F25AD47335973751832&quot; width=&quot;300&quot; height=&quot;400&quot; filename=&quot;mouse_pad.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;width: 300px; height: 400px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 300px; width: 300px; height: 400px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/23752E335973752F35&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F23752E335973752F35&quot; width=&quot;300&quot; height=&quot;400&quot; filename=&quot;out.jpg&quot; filemime=&quot;image/jpeg&quot; style=&quot;width: 300px; height: 400px;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
#dependency opencv-python 3.2 
#python version 3.6

import cv2
import os,re,sys
import numpy as np


def fit_circle(data):
	#data [[x1,y],[x2,y2]...]
	xs = data[:,0].reshape(-1,1) 
	ys = data[:,1].reshape(-1,1)

	J = np.mat(np.hstack((-2 * xs,-2 * ys,np.ones_like(xs,dtype=np.float))))
	Y = np.mat(-xs ** 2 - ys ** 2)	
	X = (J.T * J).I * J.T * Y

	cx = X[0,0]
	cy = X[1,0]
	c = X[2,0]
	r = np.sqrt(cx ** 2 + cy ** 2 - c)
	return (cx,cy,r)



def fit_rotated_ellipse(data):

	xs = data[:,0].reshape(-1,1) 
	ys = data[:,1].reshape(-1,1)

	J = np.mat( np.hstack((xs*ys,ys**2,xs, ys, np.ones_like(xs,dtype=np.float))) )
	Y = np.mat(-1*xs**2)
	P= (J.T * J).I * J.T * Y

	a = 1.0; b= P[0,0]; c= P[1,0]; d = P[2,0]; e= P[3,0]; f=P[4,0];
        # To do implementation
        #a,b,c,d,e,f 를 통해 theta, 중심(cx,cy) , 장축(major), 단축(minor) 등을 뽑아 낼 수 있어요

	theta = 0.5* np.arctan(b/(a-c))  
	cx = (2*c*d - b*e)/(b**2-4*a*c)
	cy = (2*a*e - b*d)/(b**2-4*a*c)
	cu = a*cx**2 + b*cx*cy + c*cy**2 -f
	w= np.sqrt(cu/(a*np.cos(theta)**2 + b* np.cos(theta)*np.sin(theta) + c*np.sin(theta)**2))
	h= np.sqrt(cu/(a*np.sin(theta)**2 - b* np.cos(theta)*np.sin(theta) + c*np.cos(theta)**2))

	return (cx,cy,w,h,theta)

def main(img_path):

	color_list = [(238,0,0),(0,252,124),(142,56,142)]

	src = cv2.imread(img_path, cv2.IMREAD_COLOR)
	gray = cv2.cvtColor(src,cv2.COLOR_RGB2GRAY)
	retv, th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU) 
	_, contours , _ = cv2.findContours(th,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

	for con in contours:
		approx = cv2.approxPolyDP(con, 0.01 * cv2.arcLength(con,True),True)
		area = cv2.contourArea(con)
		if(len(approx) &amp;gt; 10 and area &amp;gt; 30000):

			a,b,r = fit_circle(con.reshape(-1,2))
			#cv2.drawContours(src,[con],0,color_list[2],2)
			cv2.circle(src,(int(a),int(b)),int(r),color_list[1])
			cx,cy,w,h,theta = fit_rotated_ellipse(con.reshape(-1,2))
			cv2.ellipse(src,(int(cx),int(cy)),(int(w),int(h)),theta*180.0/np.pi,0.0,360.0,color_list[0],2)

	cv2.imwrite('out.jpg',src)

if __name__ == '__main__':
	if(len(sys.argv) != 2):
		print('usage : {0} &amp;lt; image_abs_path &amp;gt;'.format(sys.argv[0]))
		exit(0)
	main(sys.argv[1])
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>영상처리</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/30</guid>
      <comments>https://roadcom.tistory.com/30#entry30comment</comments>
      <pubDate>Sun, 23 Jul 2017 00:50:53 +0900</pubDate>
    </item>
    <item>
      <title>[ 개발, 설계 ] 실시간 처리 시스템  기본구조</title>
      <link>https://roadcom.tistory.com/29</link>
      <description>&lt;p&gt;* ERD : DA#&lt;/p&gt;&lt;p&gt;* Message Queue : RabbitMQ&lt;/p&gt;&lt;p&gt;* WEB/WAS / DB : Spring Boot / ORACLE&lt;/p&gt;&lt;p&gt;* Application : JAVA or C++&amp;nbsp;&lt;/p&gt;&lt;p&gt;* Statistic : elastic search&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;아이템이 딱히 없지만, 실시간으로 요청 처리 및 분석 통계 관련된 시스템을 기본부터 설계하여 개발 할 예정입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/29</guid>
      <comments>https://roadcom.tistory.com/29#entry29comment</comments>
      <pubDate>Sat, 1 Jul 2017 02:10:34 +0900</pubDate>
    </item>
    <item>
      <title>[ 기본 ] Neural network - feed forward</title>
      <link>https://roadcom.tistory.com/28</link>
      <description>&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;안녕하세요 비오는 장마철에 다시 뵙네요!!&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;neuron network &amp;nbsp;중 한 개의 노드를 perceptron 이라고 부릅니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;입력으로 x1, x2, x3 가 주어졌을 때 &amp;nbsp;이를 이용해서 output 을 나타내는 대표적인 non-linear 모델의 핵심 내용입니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;perceptron 이 모여서 한 개의 layer를 구성하고 layer 들이 모이면 흔히들 말하는 multi-layer perceptron 이라고 부르는 neural network이 구성됩니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;그 핵심은 물론 perceptron 이겠죠??&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/275F30435959FEFC15&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F275F30435959FEFC15&quot; width=&quot;700&quot; height=&quot;312&quot; filename=&quot;percentron.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;neuron 이 동작하는 원리를 따라서 만들었다고 인공신경(perceptron) 이라고 붙었을 만큼, 동작 원리는 비슷합니다.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;우선 x1,x2,x3 라는 입력값이 들어왓을 때 각각의 가중치(w1,w2,w3) 가 곱혀져 값이 나옵니다.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;여기서 한가지 생각을 해봅시다. 바늘에 찔렸을 때와 모기가 물렸을 때, 느끼는 정도는 당연히 다르겠죠?&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;모기에 물렸을 때 분명히 민감한 사람들은 느껴지겠지만, 대부분은 물렸는지도 모르고 지나갈 것입니다.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;과연 입력값이 너무 작아서 우리가 느끼지 못하는 것일까요?&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;입력값이 너무 작으면 아예, 출력값으로 아무것도 전달하지 않는 무언가가 있기 때문입니다.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;방금 말한 &amp;nbsp;넘어온 값을 threshold 에 따라 무언가를 동작시킬지 말지 하는 함수들을 activation function 이라고 부릅니다.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;이를 표현한 것이 &amp;nbsp;$z=f(u)$ 입니다.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;종류는 많지만, 우선적으로 아래 sigmoid, tanh, ReLu(rectified linear Unit) &amp;nbsp;3가지 정도만 있다면 이해하셔도 무방합니다.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;activation function&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;- sigmoid&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;- tanh&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;-ReLu&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;
	
	
	&lt;style type=&quot;text/css&quot;&gt;
		body,div,table,thead,tbody,tfoot,tr,th,td,p { font-family:&quot;Liberation Sans&quot;; font-size:x-small }
		a.comment-indicator:hover + comment { background:#ffd; position:absolute; display:block; border:1px solid black; padding:0.5em;  } 
		a.comment-indicator { background:red; display:inline-block; border:1px solid black; width:0.5em; height:0.5em;  } 
		comment { display:none;  } 
	&lt;/style&gt;
	



&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;table class=&quot;txc-table&quot; width=&quot;664&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; style=&quot;border:none;border-collapse:collapse;;font-family:&quot; liberation=&quot;&quot; sans&quot;;font-size:10px&quot;=&quot;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;width: 221px; height: 24px; border-width: 1px; border-style: solid; border-color: rgb(255, 255, 255); color: rgb(255, 255, 255); background-color: rgb(95, 142, 239);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-size: 10pt;&quot;&gt;&amp;nbsp;category&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 24px; border-bottom: 1px solid rgb(255, 255, 255); border-right: 1px solid rgb(255, 255, 255); border-top: 1px solid rgb(255, 255, 255); color: rgb(255, 255, 255); background-color: rgb(95, 142, 239);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-size: 10pt;&quot;&gt;&lt;b&gt;&amp;nbsp;output(activation function)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 24px; border-bottom: 1px solid rgb(255, 255, 255); border-right: 1px solid rgb(95, 142, 239); border-top: 1px solid rgb(255, 255, 255); color: rgb(255, 255, 255); background-color: rgb(95, 142, 239);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-size: 10pt;&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0); font-size: 10pt;&quot;&gt;or function&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 221px; height: 21px; border-bottom: 1px solid rgb(255, 255, 255); border-right: 1px solid rgb(255, 255, 255); border-left: 1px solid rgb(255, 255, 255); color: rgb(255, 255, 255); background-color: rgb(95, 142, 239);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;regression&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 21px; border-bottom: none; border-right: none; color: rgb(0, 0, 0); background-color: transparent;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;identity mapping&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 21px; border-bottom: none; border-right: 1px solid rgb(95, 142, 239); color: rgb(0, 0, 0); background-color: transparent;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;least square method&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 221px; height: 24px; border-bottom: 1px solid rgb(255, 255, 255); border-right: 1px solid rgb(255, 255, 255); border-left: 1px solid rgb(255, 255, 255); color: rgb(255, 255, 255); background-color: rgb(95, 142, 239);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;binarization&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 24px; border-bottom: none; border-right: none; color: rgb(0, 0, 0); background-color: transparent;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;logistic&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 24px; border-bottom: none; border-right: 1px solid rgb(95, 142, 239); color: rgb(0, 0, 0); background-color: transparent;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;cross-entrophy&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width: 221px; height: 24px; border-bottom: 1px solid rgb(255, 255, 255); border-right: 1px solid rgb(255, 255, 255); border-left: 1px solid rgb(255, 255, 255); color: rgb(255, 255, 255); background-color: rgb(95, 142, 239);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;classification&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 24px; border-bottom: 1px solid rgb(95, 142, 239); border-right: none; color: rgb(0, 0, 0); background-color: transparent;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;soft-max&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 221px; height: 24px; border-bottom: 1px solid rgb(95, 142, 239); border-right: 1px solid rgb(95, 142, 239); color: rgb(0, 0, 0); background-color: transparent;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;cross-entrophy&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/28</guid>
      <comments>https://roadcom.tistory.com/28#entry28comment</comments>
      <pubDate>Fri, 30 Jun 2017 22:00:30 +0900</pubDate>
    </item>
    <item>
      <title>[ 과제 2 ] Gauss-Newton Method</title>
      <link>https://roadcom.tistory.com/26</link>
      <description>&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;똑똑한 후배에게 Gradient descent 를 설명해 주었더니, learning rate 구현을 빼먹어서 error function 이 발산하는 쪽으로 가버렸네요..&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;최적화 방법 중에 그럼, learning rate 없이 할 수 있는 방법을 없을 까요?&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;*Gauss-Newton Method 설명을 위해서 Newton's Method 에 대한 설명이 필수적이라, 먼저 간략히 설명 뒤에 Gauss-Newton Method에 진행하겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;h1 id=&quot;firstHeading&quot; class=&quot;firstHeading&quot; lang=&quot;en&quot; style=&quot;background: none; font-weight: normal; margin: 0px 0px 0.25em; overflow: visible; padding: 0px; border-bottom: 1px solid rgb(162, 169, 177); font-size: 1.8em; line-height: 1.3; font-family: &amp;quot;Linux Libertine&amp;quot;, Georgia, Times, serif;&quot;&gt;Newton's method&lt;/h1&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Wikipedia :&amp;nbsp;https://en.wikipedia.org/wiki/Newton%27s_method&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&amp;nbsp;- 임의의 시작점에서 함수의 미분을 이용하여 1차 식으로 근사하여 0과 만나는 다음의 x 값으로 x를 업데이트 진행하는 방식입니다. 아래 보시면 gradient descent 와 다르게 learning rate(=step size) 가 보이지 않는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;$f : [ a , b] &amp;nbsp;\rightarrow \mathbb{R} $ &amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p&gt;a,b 범위 안에서 미분가능한 함수&amp;nbsp;$f(x) = 0$ 근을 반복적인 방법을 통해&amp;nbsp;찾는 과정 입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;기울기 $f'(x_1)$ 와 한 점 $(x_1,f(x_1))$ 만 알고 있다면 아래와 같이 다음 $x$ 값을 업데이트 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;
$$
\begin{matrix}
f'(x_1) , \quad [ x_1, f(x_1) ] &amp;amp;\rightarrow&amp;amp; f'(x_1)(x-x_1) - f(x_1) = 0 \\
x &amp;amp;=&amp;amp; x_1 - { f(x_1) \over f'(x_1) } 
\end{matrix}
$$
&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 673px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2112FA45594E065409&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2112FA45594E065409&quot; width=&quot;673&quot; height=&quot;480&quot; filename=&quot;NewtonIteration_Ani.gif&quot; filemime=&quot;image/gif&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;우리가 원하는 오차함수가 운이 좋게 E(x) = 0 이란 값이 나올 수 있지만, 현실적으로 E(x) = 0 이란 값이 나올 수 없는 경우가 더 많습니다. least square method 방법으로 &amp;nbsp;오차함수를 정의 했기 때문에, 잠깐 생각을 바꿔서 미분값이 0이 되는 경우를 찾으면, 이는 분명히 최소, 최대 일 경우 둘중에 한가지로 생각해 볼 수있습니다. 여기에 더해서 오차함수의 특성상 최대값이 나오는 형태가 어려움으로 대부분 최소로 생각을 정리 해볼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;다시 한번 설명 드리면&lt;b&gt; E(x) = 0 의 경우가 존재 하지 않을 수 &lt;/b&gt;있기 때문에, &lt;b&gt;E'(x) = 0 으로 문제를 바꿔서 수식을 정리&lt;/b&gt;한 것이 아래 내용입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;
$$ 
\begin{matrix}
x_{t+1} &amp;amp;=&amp;amp; &amp;amp;x_t&amp;amp;- &amp;amp;{ E'(x_t) \over E''( x_t) }&amp;amp; \\
\rightarrow \boldsymbol{ p_{t+1} } &amp;amp;=&amp;amp; &amp;amp;\boldsymbol{ p_t }&amp;amp; -  &amp;amp;H_E(\boldsymbol{ p_t })^{-1} \nabla E(\boldsymbol{ p_t })&amp;amp; \\
\end{matrix}
$$&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 332px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2519E349594E175E23&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2519E349594E175E23&quot; width=&quot;332&quot; height=&quot;481&quot; filename=&quot;error_function2.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;한 단계 더 나아가 matrix 형태로 수식을 정리하면 Gradient, Jacobian 에 이어서 Hessian 이란 무시무시한 놈이 나타납니다. Hessian 의 경우, 2차 미분이라고 간단히 생각을 정리하고 넘어가도록 하겠습니다. Hessian 을 직접 구하지 않고 근사하는 방식이 바로 Gauss-Newton Method 방식이죠!!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;저희가 구현할 내용도 바로 이&amp;nbsp;&amp;nbsp;Gauss-Newton Method 입니다. 여기까지 왜 Gauss-Newton-Method가 필요한지 설명을 드렸는데,, Hessian 구하기가 그렇게 쉽지 않기 때문이죠!!&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h1 id=&quot;firstHeading&quot; class=&quot;firstHeading&quot; lang=&quot;en&quot; style=&quot;background: none; font-weight: normal; margin: 0px 0px 0.25em; overflow: visible; padding: 0px; border-bottom: 1px solid rgb(162, 169, 177); font-size: 1.8em; line-height: 1.3; font-family: &amp;quot;Linux Libertine&amp;quot;, Georgia, Times, serif;&quot;&gt;Gauss-Newton method&lt;/h1&gt;&lt;p&gt;- 접근 방법은 taylor series 를 통해 residual 을 1차 미분 까지만 전개하여 근사화 하여 이를 통해서 파라미터를 업데이트 하겠다는방법이다. 아래 우선 수식을 먼저 공유드리고 세부적인 내용인 차후 업데이트 하도록 하겠습니다. 관심 있으신 분들은 아래 파라미터 업데이트 방식 간단히 python 코드로 구현 해보시기 바랍니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;여기서의 핵심은 &amp;nbsp;Hessian 연산을 피하기 위해 테일러 급수 를 통해서 residual 을 근사화하고 이를 통해서 파라미터를 업데이트를 진행하겠다는 방향입니다. 이부분만은 꼭 기억해두시 바래요.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;
$$

\begin{matrix}
\text{Taylor series} \\
 f(x) &amp;amp;=&amp;amp; &amp;nbsp;f(a) + f'(a)(x-a) +{ f''(a)&amp;nbsp;\over 2! }(x-a)^2 \cdots &amp;nbsp;{ &amp;nbsp;f^{(n)}(a) \over n! }(x-a)^n&amp;nbsp; &amp;amp;=&amp;amp; &amp;nbsp;\sum_{n=0}^\infty { f^{(n)}(x-a) \over&amp;nbsp;n!}(x-a)^n  \\
\text{approximation} \\
\boldsymbol{r}(\boldsymbol{p}) &amp;amp;\approx&amp;amp; \boldsymbol{r}(\boldsymbol{p_t}) + J_r(\boldsymbol{p_t}) \boldsymbol{r}(\boldsymbol{p - p_t}) \\
\end{matrix} 
$$
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;
$$
\large
\begin{matrix}
E(\boldsymbol{p}) = \sum_{i=1}^n {  [y_i - f(x_i,\boldsymbol{p})) ] }^2 = \sum_{i=1}^n {r_i}^2 = \boldsymbol{r^T r} \\ \\ \\
{ \partial E(\boldsymbol{p}) \over \partial \boldsymbol{p} } = { \partial \boldsymbol{r^T r} \over \partial \boldsymbol{p} } = 2\boldsymbol{r^T} { \partial \boldsymbol{r} \over \partial  \boldsymbol{p} } \\ \\ \\
\therefore \boldsymbol{p_{t+1}} = \boldsymbol{p_t} -  (J_r^T(\boldsymbol{p_t})J_r(\boldsymbol{p_t}) )^{-1}J_r^T(\boldsymbol{p_t})\boldsymbol{r(p_t)} 
\end{matrix}
$$
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;**아래 코드를 한번 구현해 보시면 생각이 정리 될 수 있어요&lt;/p&gt;&lt;p&gt;- &amp;nbsp;그림을 보시면 단 1번의 iteration &amp;nbsp;으로 아래와 답에 유사하게 나왔습니다. 엄청나죠,,!!&lt;/p&gt;&lt;p&gt;&amp;nbsp; (기존 naive gradient descent 또는 momentum 에 비교해도 수렴이 확실히 빠르네요)&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/25166C36595682CA3A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F25166C36595682CA3A&quot; width=&quot;640&quot; height=&quot;480&quot; filename=&quot;error_gaussnewton.png&quot; filemime=&quot;image/png&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
import numpy as np
import numdifftools as nd
import matplotlib.pyplot as plt

def optimizer_gauss_newton(xdata,ydata,max_iter,epsilon=0.0):

    aidx = 0;
    f, axarr = plt.subplots(2,2)
    axarr[0,0].plot(xdata,ydata,'ro')
    axarr[0,0].set_title('original')

    #model 2th-polynomial: ax^2 + bx +c
    #pt = np.random.rand(3,1)
    pt = np.zeros((3,1))

    r_fun = lambda p:(ydata -(p[0,0]*xdata**2+p[1,0]*xdata+p[2,0]))
    Jrp = nd.Jacobian(r_fun)

    for i in range(1,max_iter):
        r = ydata -(pt[0,0]*xdata**2+pt[1,0]*xdata+pt[2,0])

        pt = pt - np.dot(np.linalg.pinv(Jrp(pt)),r)
        error = np.sum(np.absolute(r))
        if(i%1 == 0 or i == max_iter -1):
            print('iter=[{0}], error={1}'.format(i,round(error,4)))
            aidx +=1
            axarr[int(aidx/2),aidx%2].plot(xdata,ydata,'ro')
            axarr[int(aidx/2),aidx%2].plot(xdata,pt[0,0]*xdata**2+pt[1,0]*xdata+pt[2,0])
            axarr[int(aidx/2),aidx%2].set_title('iter[{0}]'.format(i))
    print(pt)
    plt.setp([a.get_xticklabels() for a in axarr[0, :]], visible=False)
    plt.setp([a.get_yticklabels() for a in axarr[:, 1]], visible=False)
    plt.show()

if __name__ == '__main__':
    xdata = np.reshape(np.arange(0,1,0.1),(-1,1))
    ydata = 2.1*xdata**2 -1.5*xdata + 0.5
    optimizer_gauss_newton(xdata,ydata,4)

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/26</guid>
      <comments>https://roadcom.tistory.com/26#entry26comment</comments>
      <pubDate>Sat, 24 Jun 2017 13:37:28 +0900</pubDate>
    </item>
    <item>
      <title>함수 최적화 - Gradient Descent 에 대해서</title>
      <link>https://roadcom.tistory.com/23</link>
      <description>&lt;div&gt;&lt;span style=&quot;font-size: 14pt; color: rgb(9, 0, 255);&quot;&gt;Gradient Descent 방법 중 업데이트 시 데이터를 사용하는 기준에 따른 분류&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Batch Gradient Descent&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Stochastic Gradient Descent&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Mini-batch Gradient Descent&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;
$$
\large
\begin{matrix} \\&amp;nbsp;\vec p_{t+1} = \vec p_t - \lambda \nabla E(\vec p_t) \tag {1} 
\end{matrix} \\ \\
\lambda \text{   :  learning rate } 
$$&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;우선 Batch 경우는 $\vec p_{t+1}$ 업데이트를 할때 주어진 학습 데이터를 전부 사용하여 진행하기 때문에 방향에 대해서는 정확할 수 있지만, 계산량 면에서는 너무 많을 수 있습니다. 다음 경우로 Stochastic 경우는 하나의 데이터 $( x_i , y_i )$ 를 이용하여 업데이트를 진행하기 때문에 속도면에서는 빠를 순 있지만, 정확하지 않을 수도 있습니다. 따라서 현재 가장 많이 사용하는 Mini-Batch 는 전체 학습 데이터 &amp;nbsp;중 임의로 N 개의 sample을 추려서 N 개의 데이터를 통해 업데이틀 진행하기 때문에, Batch 와 Stochastic 을 합쳐 놓았다고 생각 하시면 될 것 같아요.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;제가 사용할 예제는 학습 데이터가 많지 않기 때문에 Batch Gradient Descent 위주로 설명하면서 진행하도록 할께요.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: rgb(9, 0, 255); font-size: 18.6667px;&quot;&gt;Gradient Descent Algorithm 종류&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Naive Gradient Descent&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Momentum&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Nestrov Gradient&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Adagrad&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Adadelta&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;RMSprop&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Adam&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;Naive Gradient Descent&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; : 식 1로 정의가 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;Momentum&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;관성이라는 말이 딱 들어 맞을 것 같습니다. 이전 업데이트에서 parameter 값이 최적화를 통해 가고 있는 방향에 대해서, 즉 이전 업데이트시 가고 있는 방향에 대한 가중치를 주면서, 진행하는 방식입니다. 느낌이 와닿지 않으면, 관성이란 말을 까먹으시면 안됩니다. 제가 지금 전력으로 달리다가 갑자기 뒤로 돌면, 달리던 방향으로 넘어가겠죠..?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;
$$
\large
\begin{matrix}
\vec m_t &amp;amp;=&amp;amp; \gamma \vec m_{t-1} + \nabla E(\vec p_t) \\ 
\vec p_{t+1} &amp;amp;=&amp;amp; \vec p_t - \vec m_t   \tag {2} 
\end{matrix} \\ \\ \\ \gamma \text{   :  momentum rate } 
$$&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
import numpy as np
import numdifftools as nd
import matplotlib.pyplot as plt


def optimizer_momentum(xdata,ydata,learning_rate,max_iter,momentum=0.9):

       # implementation moment gradient


&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;동일한 learning rate 로 Gradient descent 와 momentum 결과를 살펴 볼까요? 아래 그림을 보시면, momentum 알고리즘을 왜 사용해야 되는지 알 수 있어요, 단순한 gradient descent 보다 수렴속도가 엄청나네요!!&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;lt; Gradient Descent &amp;nbsp;: iteration &amp;gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/267DFA4B59468E1804&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F267DFA4B59468E1804&quot; width=&quot;640&quot; height=&quot;480&quot; filename=&quot;iter_result.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&amp;lt; Momentum&amp;nbsp; : iteration&amp;nbsp;&amp;gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px; width: 640px; height: 480px;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/236B474B59468E1822&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F236B474B59468E1822&quot; width=&quot;640&quot; height=&quot;480&quot; filename=&quot;iter_momentum.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;width: 640px; height: 480px;&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;Adagrad &amp;nbsp;( Adaptive Gradient )&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;- 업데이트 컨셉을 많이 최적화 된 parameter 는 learning rate 를 줄이고 최적화가 덜 된 parameter 들은 learning rate 를 더 높게 가져가 보는건 어떨 까요?, 최적화가 많이 되고 안되었다는 기준은 무엇인지 고민할 필요가 있어 보이네요,, 파라미터가 초기값에서&amp;nbsp;많이 변했다면 ,이 값은 최적화가 더 되었다고 생각해보는 컨셉이 Adagrad 의 핵심 &amp;nbsp;입니다. 아래 수식을 보면 parameter 마다 learning rate 이 다르다는 것이 보이시죠? 한가지 아쉬운 점이 있다면 $g_1 , g_2, \cdots , g_m&amp;nbsp;$&amp;nbsp;값이 항상 커지는 방향이라는 거죠,, 한 번 이를 통해서 학습을 진행 해보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;
$$
\large
\begin{matrix}\
\vec g_t &amp;amp;=&amp;amp; \vec g_{t-1} + \nabla E(\vec p_t) \odot \nabla E(\vec p_t) &amp;amp;=&amp;amp; \begin{bmatrix} g_1 \\ g_2 \\ \vdots \\ g_m \end{bmatrix}\\ \\ \\
\vec p_{t+1} &amp;amp;=&amp;amp; \vec p_t - { \lambda \over \sqrt{ \vec g_t + \epsilon } } \odot \nabla E(\vec p_t) 
&amp;amp;=&amp;amp; \vec p_t -  \lambda \begin{bmatrix} { 1 \over \sqrt {g_1 + \epsilon } } \\  {1 \over \sqrt {g_2 + \epsilon } } \\ \vdots \\ {1 \over \sqrt {g_m + \epsilon } } \end{bmatrix} \odot \nabla E(\vec p_t) 
\end{matrix} \\ \\ \\ \odot&amp;nbsp;\text{  : element wise multiplication } \quad \lambda \text{ : learning rate} \quad&amp;nbsp;\epsilon \ &amp;nbsp;: \ 10^{-4} \sim 10^{-8}&amp;nbsp; $$&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/23</guid>
      <comments>https://roadcom.tistory.com/23#entry23comment</comments>
      <pubDate>Sun, 18 Jun 2017 11:54:04 +0900</pubDate>
    </item>
    <item>
      <title>[ 과제 1 ] Gradient Descent</title>
      <link>https://roadcom.tistory.com/22</link>
      <description>&lt;div style=&quot;text-align: left;&quot;&gt;써먹을 일 없다고 내려두었던 내용들이 누군가에게 도움이 된다면,&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;Linear regression 에 대해서는 closed-form 인 pseudo inverse 존재하기 때문에 대부분은 gradient descent 방식을 시도 조차 하지 않습니다. 하지만, nonlinear 로 넘어가면 꽤나 간단하면서 직관적인 최적화 방법이기 때문에 많이 사용하고 있습니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;제가 이번에 다룰 내용은 polynomial 함수 (y = ax^2 + bx + c), 2차 함수에 대해서 gradient descent 방법을 통해 최적화 하는 방법을 다루도록 하겠습니다. 시작에 앞서 기초적인 내용과 수식을 설명 드리겠습니다.&lt;/p&gt;&lt;p style=&quot;clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;clear: none; float: none; text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 346px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/26643F3959440E252D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F26643F3959440E252D&quot; width=&quot;346&quot; height=&quot;100&quot; filename=&quot;definition.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;수식 전개에 앞서서 저랑 약속 한개만&amp;nbsp;할께요,&amp;nbsp;모든 벡터는 열벡터 이고 위와 같이 열벡터를 볼드체로 표시하도록 하겠습니다. 혼동하지 마세요~&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;회사 선배가 갑자기 와서 저에게 데이터를 던져주고 &amp;nbsp;입력으로 말도 안되는 데이터를 주고&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;&quot;입력이 들어가면 출력이 이런데, &lt;/span&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;함수를 찾아서 알려줘, 그런데 예전에 &amp;nbsp;이게 2차 함수였던 것 같은데,,&quot;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&amp;nbsp;모든 힌트가 다 나온 것 같습니다. 주어진 데이터를 관찰 데이터 라고 가정하면&amp;nbsp;입력값과 출력값 pair 가 n 개 주었졌을 것이고 가정으로는 2차 polynomial 함수 라는 것도 알 수 있었네요. 이를 통해서 오차함수 를 구하면 위와&amp;nbsp;같이 matrix form 까지 전개가 가능합니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/21351E3959440E2526&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F21351E3959440E2526&quot; width=&quot;700&quot; height=&quot;244&quot; filename=&quot;baseinfo.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;이번 주제가 바로 gradient descent 방식을 통한 함수 최적화 라고 말씀드렸죠??&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;최적화 방법으로 gradient descent 방식을 사용하려면, &amp;nbsp;Gradient 와 Jacobian 이란 이상한 용어와 마주해야 됩니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;둘다 정말 간단히 설명 드리면, 미분입니다. Gradient 경우는 multi-variable scalar 함수 에 대해서 각 variable 로 미분을 한 것이고 Jacobian 의 경우는 이를 한단계 더 확장한 multi-variable vector 함수에 대한 미분이라고 생각하시면 됩니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;다 잊어도 상관없지만, 정말 중요한 것은 둘다 미분이란 것입니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;아래와 같이 Gradient Descent 방법을 통해서 파라미터를 업데이 해보도록 하겠습니다.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;사용코드는 python 을 통해서 전개 하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;예전에 , 후배에게 이 내용을 설명해줄 때 넌지시 Jacobian 은 내가 코딩해줄께 라고 생색을 냈는데,&amp;nbsp;실제 linear regression 에 대한 Jacobian 은 나중에 아시면 너무 쉽습니다. 아니. 큰 의미가 없다고 봐도,,,&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2620E43A594420F01B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2620E43A594420F01B&quot; width=&quot;700&quot; height=&quot;399&quot; filename=&quot;gradient_descent.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&amp;nbsp;학습 데이터&amp;nbsp;에 대해서 Gradient Descent 방식을 통해서&amp;nbsp;예측 값이&amp;nbsp;점점 다가가는 것을 확인 할 수 있습니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;아래 python 코드를 완성해 보시면 충분히 어렵지 않다는 것을 알 수 있습니다. Gradient descent&amp;nbsp;을 사용해서 $f(x) = ax^2 + bx +c$ 를 학습해 보는 코드입니다.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 640px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2139EF5059442CC319&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2139EF5059442CC319&quot; width=&quot;640&quot; height=&quot;480&quot; filename=&quot;iter_result.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
#!/home/roadking/anaconda3/bin/python
import numpy as np
import numdifftools as nd
import matplotlib.pyplot as plt


def optimizer_gradient(xdata,ydata,learning_rate,max_iter,epsilon=0.0):

    aidx = 0;
    f, axarr = plt.subplots(2,2)
    axarr[0,0].plot(xdata,ydata,'ro')
    axarr[0,0].set_title('original')

    #model 2th-polynomial: ax^2 + bx +c
    #pt = np.random.rand(3,1)
    pt = np.zeros((3,1))

    r_fun = lambda p:(ydata -(p[0,0]*xdata**2+p[1,0]*xdata+p[2,0]))
    Jrp = nd.Jacobian(r_fun)

    for i in range(1,max_iter):
        r = ydata -(pt[0,0]*xdata**2+pt[1,0]*xdata+pt[2,0])
        pt = pt - 2*learning_rate*np.transpose(Jrp(pt)).dot(r)
        error = np.sum(np.absolute(r))
        if(i%500 == 0 or i == max_iter -1):
            print('iter=[{0}], error={1}'.format(i,round(error,4)))
            aidx +=1
            axarr[int(aidx/2),aidx%2].plot(xdata,ydata,'ro')
            axarr[int(aidx/2),aidx%2].plot(xdata,pt[0,0]*xdata**2+pt[1,0]*xdata+pt[2,0])
            axarr[int(aidx/2),aidx%2].set_title('iter[{0}]'.format(i))
    print(pt)
    plt.setp([a.get_xticklabels() for a in axarr[0, :]], visible=False)
    plt.setp([a.get_yticklabels() for a in axarr[:, 1]], visible=False)
    plt.show()

if __name__ == '__main__':
    xdata = np.reshape(np.arange(0,1,0.1),(-1,1))
    ydata = 2.1*xdata**2 -1.5*xdata + 0.5
    optimizer_gradient(xdata,ydata,0.05,1500)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/22</guid>
      <comments>https://roadcom.tistory.com/22#entry22comment</comments>
      <pubDate>Fri, 16 Jun 2017 16:59:17 +0900</pubDate>
    </item>
    <item>
      <title>머신러닝 기초</title>
      <link>https://roadcom.tistory.com/20</link>
      <description>&lt;p&gt;요즘은 어느 곳이든 머신 러닝이라는 말을 많이 사용합니다.&lt;/p&gt;&lt;p&gt;더 나아가 딥러닝이란 말도 사용하는데 정말 머신러닝이 무엇을까요?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;대부분 사람은 아래 x와 그 결과가 나온 표를 보고는 f(10) 이 무엇이 될지 단박에 알아 냅니다.&lt;/p&gt;&lt;p&gt;어떻게 이런 일이 일어나고 있는 것일까요?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. 입력과 출력의 데이터를 쭈욱 본다.&lt;/p&gt;&lt;p&gt;2. 출력에 연관된 함수(모델)을 몇가지 생각해본다.&lt;/p&gt;&lt;p&gt;3. 잘 들어맞는 함수를 찾아낸다.&lt;/p&gt;&lt;p&gt;4. 그 함수에 최종 10 값을 넣어 그 결과를 도출한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/274F0F35591C57242A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F274F0F35591C57242A&quot; width=&quot;700&quot; height=&quot;270&quot; filename=&quot;ML_basic.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;위 예를 가지고 용어를 정리해보도록 하겠습니다.&lt;/p&gt;&lt;p&gt;정답지가 주어져 있는 경우를 supervised 그렇지 않은 경우를 unsupervised &amp;nbsp;라고 합니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;unsupervised 우선 논외로 하고 위에처럼 정답지 데이터가 주어진 경우를 머신러닝에서는 supervised learning 이라고 합니다. 회사에서 많이 사용하는 엑셀에서의 추세선을 그리는 자체가 바로 supervised learning 이라고 말할 수 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. 입력과 출력의 데이터를 쭈욱 본다. --- train data&lt;/p&gt;&lt;p&gt;2. 출력에 연관된 함수(모델)을 몇가지 생각해본다. -- exponential&amp;nbsp;, power ?&amp;nbsp;&lt;/p&gt;&lt;p&gt;3. 잘 들어맞는 함수를 찾아낸다. -- &amp;nbsp;power 가 더 잘 맞네? &amp;nbsp;y=x^2&lt;/p&gt;&lt;p&gt;4. 그 함수에 최종 10 값을 넣어 그 결과를 도출한다. &amp;nbsp;- &amp;nbsp;10^2 = 100&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/231D2C38591C596009&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F231D2C38591C596009&quot; width=&quot;700&quot; height=&quot;354&quot; filename=&quot;excel_regression.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;저희는 이미 실생활 뿐만 아니라 엑셀을 통해 많은 머신러닝을 이뤄내고 있었네요,,&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 650px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/25431D37591C5A9008&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F25431D37591C5A9008&quot; width=&quot;650&quot; height=&quot;474&quot; filename=&quot;excel_regression_2.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;이제 조금 더 머신러닝에 맞는 용어로 바꿔서 설명 하도록 하겠습니다.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. 입력과 출력의 데이터 - train data ( 관찰된 데이터, 최종 함수를 찾기&amp;nbsp;위해 우리에게 주어진 값&amp;nbsp;)&lt;/p&gt;&lt;p&gt;2. 함수(모델) - &amp;nbsp;(크게 보면 classification /regression 모델로 분류가능 한데, 주어진건 regression(함수) 모델 )&lt;/p&gt;&lt;p&gt;3. 잘 들어맞는 함수를 찾아낸다. - (찾는 방법 fitting, optimization, 잘들어 맞는지&amp;nbsp;cost,error,residual)&lt;/p&gt;&lt;p&gt;4. 결과를 예측 (prediction) &amp;nbsp;- &amp;nbsp;10^2 = 100&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;주어진 train data 를 통해서 분류하는 모델(classification) 또는 함수모델(regression) 인지 결정하여 모델을 가정(hypothesis) 합니다. &amp;nbsp;주어진 train data를 통해서 hypothesis 가 맞는지 하나씩 넣어보면서 hypothesis 값과 train data 들간의 차이를 계산합니다(cost, error, residual ...). 이과정을 통해서 hypothesis 의 파라미터( y =a x^2, a:parameter) 를 바꿔가면서 hypothesis 와 train data 의 차이가 최소가 되는 파라미터를 선정하게 됩니다. 이를 통해 최종 결정된 함수에 우리가 원하는 결과를 prediction 할 수 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>머신러닝</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/20</guid>
      <comments>https://roadcom.tistory.com/20#entry20comment</comments>
      <pubDate>Wed, 17 May 2017 23:25:07 +0900</pubDate>
    </item>
    <item>
      <title>Spring boot 사전준비</title>
      <link>https://roadcom.tistory.com/19</link>
      <description>&lt;p&gt;Web 을 하기에 여러종류의 있지만, Java 계열의 spring boot 에 대해서 포스트를 진행하도록 하겠습니다.&lt;/p&gt;&lt;p&gt;우선 가장 중요한 것은 개발 환경을 잘 구성하는 것 입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;1. Eclipse.org 접속 - Download&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/213F163A591C4EB20B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F213F163A591C4EB20B&quot; width=&quot;700&quot; height=&quot;301&quot; filename=&quot;eclipse_1.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;2. Download Packages - 설치파일로 받고 싶은신 분은 바로 Download 64 Bit 로 설치하시면 됩니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;(제 경우는 binary 실행파일로 설치하고 하는 경우 입니다.)&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 307px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2313173A591C4EB322&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2313173A591C4EB322&quot; width=&quot;307&quot; height=&quot;263&quot; filename=&quot;eclipse_2.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;3. eclipse-jee-neon-*.zip 파일을 다운로드 하여 적당한 곳에 압축을 풀고 eclipse 실행&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2413193A591C4EB337&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2413193A591C4EB337&quot; width=&quot;700&quot; height=&quot;167&quot; filename=&quot;eclipse_3.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;4. eclipse market place 에서 Spring 으로 검색하셔서 Spring IDE 최신 버전을 인스톨&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 512px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2745CA3A591C4EB409&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2745CA3A591C4EB409&quot; width=&quot;512&quot; height=&quot;561&quot; filename=&quot;eclipse_4.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;5. New Project 에서 Spring Spring Starter 프로젝트를 추가&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;6. Type 의 경우 메이븐과 Gradle 중 원하는 build tool에 맞게 아래 정보를 작성&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 544px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2329323A591C4EB514&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2329323A591C4EB514&quot; width=&quot;544&quot; height=&quot;764&quot; filename=&quot;eclipse_5.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;7. 단순 DB 연동을 제외하고 Web 과 View 를 구성하기 위해 Thymeleaf 와 Web을 선택하여 생성&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 541px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2423A43A591C4EB50A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2423A43A591C4EB50A&quot; width=&quot;541&quot; height=&quot;674&quot; filename=&quot;eclipse_6.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;8. 최종 프로젝트 생성 후 explorer&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 320px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2755823A591C4EB604&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2755823A591C4EB604&quot; width=&quot;320&quot; height=&quot;290&quot; filename=&quot;eclipse_7.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;* static: css, js, fonts 등 정적 요소 위치&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;* template : thyemleaf 에서 실행될 html 이 위치하게될 장소&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;* build.gradle : gradle 용 build 설정 파일 (maven 경우 pom.xml 로 생성됨)&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Spring</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/19</guid>
      <comments>https://roadcom.tistory.com/19#entry19comment</comments>
      <pubDate>Wed, 17 May 2017 22:30:03 +0900</pubDate>
    </item>
    <item>
      <title>행렬 연산 (Matrix C)</title>
      <link>https://roadcom.tistory.com/17</link>
      <description>&lt;p&gt;이 내용은 다크 프로그래머님의&amp;nbsp;&lt;a href=&quot;http://darkpgmr.tistory.com/141&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;http://darkpgmr.tistory.com/141&lt;/span&gt;&lt;/a&gt;&amp;nbsp; (벡터 미분과 행렬 미분) 내용을 보고 내용을 정리 한 수준입니다. 다크 프로그래머님의 내용과 같이 추가로&amp;nbsp;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Matrix_calculus&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;https://en.wikipedia.org/wiki/Matrix_calculus&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Matrix_calculus&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/a&gt;위키피디아 내용도 참조하였습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;학부 시절에 배웠던 gradient 가 머신러닝을 하면서 이렇게 와 닿을 줄 몰랐습니다. x1, x2, x3 독립 변수를 가지는 f(x) 에 대하여 gradient 를 취하면 각 독립변수에 대한 미분 값을 구할 수 있습니다. ( 스칼라 미분을 벡터로 확장). 다음에 배우겠지만, vector 를 vector 로 미분하게 되면 jacobian 까지 확장 될 수 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 445px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/26484139590F320340&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F26484139590F320340&quot; width=&quot;445&quot; height=&quot;168&quot; filename=&quot;gradient.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 341px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/24218333590F3A1C1D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F24218333590F3A1C1D&quot; width=&quot;341&quot; height=&quot;189&quot; filename=&quot;jacobian.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;이제 추가로 matrix(행렬)과 vector, scala 에 대해서 일반적인 미분식을 사용하면 아래와 같이 정리 할 수 있습니다.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;다크프로그래님의 말씀처럼, 정리하는 폼에 따라서 Numerator-layout notation(분자 우선 표현),&amp;nbsp;Denominator-layout notation(분모 우선 표현) 2가지 종류에 따라서 numerator 은&amp;nbsp;행벡터로 , denominator 는 열벡터로 표현 할 수 있습니다.단순 표시하는 notation 에 따라 표현식이 달라질 수 있으나, 결과적으로 transpose 를 하면 서로 같은 내용이라는 걸 알 수 있습니다. 저도 혼동이 안가고자 모든 표현을 numerator 분자우선 표현으로 식을 정리하도록 하겠습니다.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;* 볼드체 경우는 열벡터 (column vector)&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;* 대문자 경우는 행렬 (matrix)&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;table class=&quot;txc-table&quot; width=&quot;664&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; style=&quot;border:none;border-collapse:collapse;;font-family:&quot; 맑은=&quot;&quot; 고딕&quot;,=&quot;&quot; sans-serif;font-size:13px&quot;=&quot;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;width: 166px; height: 40px; border-width: 1px; border-style: solid; border-color: rgb(204, 204, 204);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 166px; height: 40px; border-bottom: 1px solid rgb(204, 204, 204); border-right: 1px solid rgb(204, 204, 204); border-top: 1px solid rgb(204, 204, 204);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;Scala y&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 166px; height: 40px; border-bottom: 1px solid rgb(204, 204, 204); border-right: 1px solid rgb(204, 204, 204); border-top: 1px solid rgb(204, 204, 204);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;Vector y (size m)&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width: 166px; height: 40px; border-bottom: 1px solid rgb(204, 204, 204); border-right: 1px solid rgb(204, 204, 204); border-top: 1px solid rgb(204, 204, 204);&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;Matrix Y&amp;nbsp;(size m x n)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;Scala x&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 44px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/251D1B34590F373E0F&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F251D1B34590F373E0F&quot; width=&quot;44&quot; height=&quot;61&quot; filename=&quot;sbs.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 45px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2230EF39590F36B807&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2230EF39590F36B807&quot; width=&quot;45&quot; height=&quot;56&quot; filename=&quot;vbs.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 43px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/22304D39590F36B607&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F22304D39590F36B607&quot; width=&quot;43&quot; height=&quot;60&quot; filename=&quot;mbs.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;Vector x (size n)&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 40px; text-align: center;; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/253C4639590F36B71A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F253C4639590F36B71A&quot; width=&quot;40&quot; height=&quot;62&quot; filename=&quot;sbv.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;text-align: center;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 49px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/247CB03B590F36FA37&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F247CB03B590F36FA37&quot; width=&quot;49&quot; height=&quot;67&quot; filename=&quot;vbv.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;Matrix X (size m x n)&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 42px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2257F339590F36B72F&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2257F339590F36B72F&quot; width=&quot;42&quot; height=&quot;67&quot; filename=&quot;sbm.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td style=&quot;width:166;height:24;border-bottom:1px solid #ccc;border-right:1px solid #ccc;;&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 445px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/25224B445916D6C407&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F25224B445916D6C407&quot; width=&quot;445&quot; height=&quot;875&quot; filename=&quot;derivative.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/17</guid>
      <comments>https://roadcom.tistory.com/17#entry17comment</comments>
      <pubDate>Mon, 8 May 2017 00:09:06 +0900</pubDate>
    </item>
    <item>
      <title>Visitor pattern (c++)</title>
      <link>https://roadcom.tistory.com/16</link>
      <description>&lt;p&gt;Visitor pattern 은 객체 내부에 있는 알고리즘을 분리 시키는 패턴입니다. 알고리즘을 분리시켜 놓으면 구조를 수정하지 않아도 새로운 기능(알고리즘)을 만들기 쉽기 때문입니다. 저도 공부하면서 와닿지 않는 패턴이었고, 다른 분들도 이해하기 어려운 패턴 중에 하나라고 말씀드리고 싶습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;제가 살고 있는 아파트를 말씀드리면, 소독하시는 여사님, 물건을 배달해주시는 택배기사님, 술한잔 하러 놀러오는 친구들이 찾아옵니다.&amp;nbsp;이 뜬금없는 한 문장에 visitor pattern 의 핵심 내용이 들어있습니다. 아파트라는 정해진 구조(structure)에 &amp;nbsp;많을 일들을 해 주시는 분(visitor)이 오셔서, 문을 열어주면(accept) 많은 일들을 할 수 있게합니다.(algorithm, operation)&lt;/p&gt;&lt;p&gt;오늘 저녁 새로 생긴 치킨집에 배달 시켜서 새로운 맛을 느껴봐야 겠네요.&lt;br /&gt;(* 신규 visitor 생성 으로 새로운 기능&amp;nbsp;추가)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;lt; Visitor Pattern &amp;gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2723AF3A590EEDED11&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2723AF3A590EEDED11&quot; width=&quot;700&quot; height=&quot;298&quot; filename=&quot;visitor_pattern2.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;그런데 과연 이 패턴을 언제 어떻게 사용해야 될까요?&amp;nbsp;&lt;/p&gt;&lt;p&gt;File System을 보게되면 정해진 구조(file,directory)로 이루어져 있습니다. 중요한 파일을&amp;nbsp;백업(압축)하려면 하위 디렉토리 node로 옮겨가면서 파일들을 압축해야 합니다. 뿐만 아니라 검색도 같은 방식으로 정해진 구조를 방문 후 검색이란 알고리즘만 추가하면 가능할 것 같습니다. 아래 예를 가지고 실제 코드로 구현해 보도록 하겠습니다.(진행)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;lt; 파일 시스템에 적용된 Visitor Pattern &amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/24428637590EEEEB06&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F24428637590EEEEB06&quot; width=&quot;700&quot; height=&quot;299&quot; filename=&quot;visitor_pattern3.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Design pattern(C++)</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/16</guid>
      <comments>https://roadcom.tistory.com/16#entry16comment</comments>
      <pubDate>Sun, 7 May 2017 19:01:22 +0900</pubDate>
    </item>
    <item>
      <title>Strategy pattern (c++)</title>
      <link>https://roadcom.tistory.com/15</link>
      <description>&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;Strategy Pattern 의 컨셉은 어떤 전략(algorithm or&amp;nbsp;strategy) 을 추상화 하여 전략을 쉽게 변경하는데 의미를 둘 수 있습니다. 대부분 이런 말을 하면 크게 와닿지가 않아서 디자인 패턴의 최고 할 수 있는 스타크래프트 게임에 비유해서 말하곤 합니다.&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/27629445590C026D10&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F27629445590C026D10&quot; width=&quot;700&quot; height=&quot;287&quot; filename=&quot;strategy_uml.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;어떤 유닛이든 기본적으로 전략(algorithm, strategy)를 공통으로 뽑아보면, 여러개가 있지만 우선적으로 움직이거나 공격할 수 있는 공통 전략을 추출할 수있습니다.&amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/216FE149590C11632C&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F216FE149590C11632C&quot; width=&quot;700&quot; height=&quot;452&quot; filename=&quot;strategy_uml2.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Design pattern(C++)</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/15</guid>
      <comments>https://roadcom.tistory.com/15#entry15comment</comments>
      <pubDate>Fri, 5 May 2017 14:50:29 +0900</pubDate>
    </item>
    <item>
      <title>Spring boot 공부중</title>
      <link>https://roadcom.tistory.com/13</link>
      <description>&lt;p&gt;웹이라고는 html, css, javascript 가 어떤 의미인지도 몰랐던 시절에 무조건 웹을 개발하라고 해서 무턱대고 만들었던 기억이 엊그제 같습니다. 혼자 구글과 싸움을 벌이면서 온갖 xml 이 넘쳐나던 spring mvc, 지금 생각해봐도 개발자의 능력보다는 구글링의 스킬만 키우면 엄청나겠구나! 를 느끼게 합니다. 머신러닝 관련해서 한 동안&amp;nbsp;C++ 사용해와서 기억속에서 지워져 가는 웹을 되살림겸, xml 에 지쳐서 spring boot 로 간단하게 만들었던 prototype 을 통해서 웹에 대해서 포스팅 하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;lt;소스코드 : github &amp;gt;&lt;/p&gt;&lt;p&gt;https://github.com/elentail/springboot.git (spring boot 1.3.1 버전 &amp;nbsp;-- &amp;gt; 1.5 로 전환 예정)&lt;/p&gt;&lt;p&gt;* angularjs, bootstrap, google chart etc ... (front-end library 사용)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;** 저도 기억이 가물가물해서 하나씩 내용을 보면서 정리하도록 하겠습니다.&lt;/p&gt;&lt;p&gt;@Configuration : 자바 기반 설정임을 알려주는 annotation&lt;/p&gt;&lt;p&gt;@EnableAutoConfiguration : &amp;nbsp;sub-package에 있는 @Entity 클래스들을 scan&lt;/p&gt;&lt;p&gt;@ComponentScan : xml의 &amp;lt;context:component-scan&amp;gt;&lt;/p&gt;&lt;p&gt;--&amp;gt; @SpringBootApplication&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;** view resolver&lt;/p&gt;&lt;p&gt;JSP&lt;/p&gt;&lt;p&gt;thymeleaf&lt;/p&gt;&lt;p&gt;velocity -- deprecated (spring boot 1.5)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;* Spring boot web&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Dispatcher Servlet : 클라이언트로 부터 오는 신호는 무조건 dispatcher를 최우선으로 진행&lt;/p&gt;&lt;p&gt;Handler Mapper : 흔히 말하는 GET,DELETE,POST,PUT 등 뿐만 아니라 URI&amp;nbsp;REST &amp;nbsp;처리하는 모듈&lt;/p&gt;&lt;p&gt;Controller : Mapper를 통해 들어온 request 를 어떻게 처리할지 결정하는 모듈&lt;/p&gt;&lt;p&gt;Model : Custom model을 만들 수 있고 또는, DB를 붙여 정보를 가져올 수 있도록 하는 모듈&lt;/p&gt;&lt;p&gt;View Resolver : 어떤 dialect 를 사용할지 결정(JSP, thymeleaf, groovy ... )&lt;/p&gt;&lt;p&gt;View : 최종 클라이언트로 전송되는 html 형태의 view&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 700px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2414FF40591C53E512&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2414FF40591C53E512&quot; width=&quot;700&quot; height=&quot;336&quot; filename=&quot;Spring_boot_mvc.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;아래 내용 또한 공부해서 시간이 되는데로 업데이트 예정입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;* Spring actor&lt;/p&gt;&lt;p&gt;* Spring cache&lt;/p&gt;&lt;p&gt;* Spring validation&lt;/p&gt;&lt;p&gt;* Spring batch&lt;/p&gt;&lt;p&gt;* Spring scheduler&lt;/p&gt;&lt;p&gt;* Spring mongodb&lt;/p&gt;&lt;p&gt;* Spring security&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Spring</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/13</guid>
      <comments>https://roadcom.tistory.com/13#entry13comment</comments>
      <pubDate>Mon, 1 May 2017 17:48:48 +0900</pubDate>
    </item>
    <item>
      <title>선형회귀(linear regression)-최소자승법</title>
      <link>https://roadcom.tistory.com/8</link>
      <description>&lt;p&gt;이글은 순수하게 다크프로그래머 님의 기계학습 중&amp;nbsp;&lt;/p&gt;&lt;p&gt;함수 최정확 기법정리 부분을 인용하여,&amp;nbsp;내용은 정리한 수준입니다.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://darkpgmr.tistory.com/142&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;http://darkpgmr.tistory.com/142&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;*residual 이 최소가 되는 일반적인 최소자승법
&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 525px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/251E9F43590771730C&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F251E9F43590771730C&quot; width=&quot;525&quot; height=&quot;340&quot; filename=&quot;수식1.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;* parameter 에 linear 한 모델의 경우 아래와 같이 수식 유도 가능합니다. -&amp;gt; Ap&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 399px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/271BD243590771730C&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F271BD243590771730C&quot; width=&quot;399&quot; height=&quot;170&quot; filename=&quot;수식3.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;* 선형회귀(linear-regression) 경우 pseudo inverse 를 통해&amp;nbsp;특정해를 구할 수 있습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 398px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/2508DA43590771730D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F2508DA43590771730D&quot; width=&quot;398&quot; height=&quot;190&quot; filename=&quot;수식2.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;*일반적인 해를 구하는 방식으로 아래 4가지 방식에 대해서 추가 설명 드리겠습니다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;1. Gradient Descent&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;2. Newton-raphson&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;3. Gauss-Newton&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;4. Levenberg_marquardt&lt;/span&gt;&lt;/p&gt;</description>
      <category>머신러닝/기초</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/8</guid>
      <comments>https://roadcom.tistory.com/8#entry8comment</comments>
      <pubDate>Wed, 26 Apr 2017 23:18:10 +0900</pubDate>
    </item>
    <item>
      <title>Singleton pattern (c++)</title>
      <link>https://roadcom.tistory.com/7</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-size: 14pt;&quot;&gt;싱글톤 패턴(Singleton Pattern)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;객체를 사용할 때 매번 생성하지 않고 딱 한 번의 생성을 통해 이를 재활용 하는 패턴입니다.&lt;/p&gt;
&lt;p&gt;객체 생성 횟수를 줄여서 메모리를 절약가능하긴 하지만, 요즘과 같이 메모리가 넘쳐나는 시대에 크게 와닿지 않습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;다른 이유는 없을까요? 다들 사무실에서 프린터를 사용해본 경험이 있을 것 입니다. 네트워크로 연결해서 여러사람들이 쓸 수 있게 연결되어 있습니다. 어떻게 사용되는지 자세하세 살펴 볼까요&lt;/p&gt;
&lt;br /&gt;
&lt;p style=&quot;margin-left: 4em;&quot;&gt;사용자1&lt;/p&gt;&lt;br /&gt;
&lt;p style=&quot;margin-left: 4em;&quot;&gt;사용자2&lt;/p&gt;&lt;br /&gt;
&lt;p style=&quot;margin-left: 4em;&quot;&gt;사용자3 &amp;nbsp;&amp;nbsp;----▷ TCP/IP &amp;nbsp;&amp;nbsp;----▷&amp;nbsp;프린터(요청된 작업 한개를 출력)&lt;/p&gt;&lt;br /&gt;
&lt;p style=&quot;margin-left: 4em;&quot;&gt;&amp;nbsp;&amp;nbsp;...&lt;/p&gt;&lt;br /&gt;
&lt;p style=&quot;margin-left: 4em;&quot;&gt;사용자 N&lt;/p&gt;
&lt;br /&gt;


&lt;p&gt;프린터는 사용자1, 2, 3 으로부터 작업을 언제든지 받을 수 있습니다. 사용자1이 요청하자마자 사용자2 가 다른 작업을 요청하면 똑똑한 프린터는 작업큐&amp;nbsp;라는 공간을 만들어서 순차적으로 처리를 합니다. 그럼 이런 큐를&amp;nbsp;2개 이상이 생성한다면 다들 글자 한줄 짜리 프린트&amp;nbsp;물을 받아 볼지도 모릅니다. 보통은 시스템 자원관리, 정보 등을 관리하는 thread pool, work pool, connection pool 은 싱클톤패턴을 사용하고 있답니다.&lt;/p&gt;
&lt;br /&gt;&lt;br /&gt;


&lt;pre&gt;&lt;code class=&quot;cpp&quot;&gt;
&lt;br /&gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;

class singleton
{

	// 포인터를 통해 딱 한개의 instance 를 관리
	static singleton* _instance;
	singleton() {};

public:
	// c++11 style : copy constructor 호출 되지 못하도록
	singleton(const singleton&amp;amp; other) = delete;
	// singleton 객체 생성
	static singleton* get_instance()
	{
		if (_instance == nullptr)
		{
			_instance = new singleton();
		}
		return _instance;
	}

	// singletone 객체 해제
	static void release_instance() {
		if (_instance) {
			delete _instance;
			_instance = nullptr;
		}
	}
};
// 기본 _instance 값을 nullptr 로 설정
singleton* singleton::_instance = nullptr;

int main()
{
	singleton* instance = singleton::get_instance();
	instance-&amp;gt;release_instance();
	return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;p&gt;아 이제 완성이 되었네요. 정말로 이제 singleton 객체를 통해 pool 관리도 하고 멋진 일들을 해낼 수 있다고 믿는 순간, 한가지 의문이 생깁니다. 사용자1, 2가 동시에 생성해달라고 하면 어떤 일이 일어 날까요? singleton 객체가 2번이나 생성 될 수 있어 알지 못하게 memory leakage 가 발생해 버립니다. 몇 백번쯤이야 상관없지만 수십만번 된다고 하면 끔찍일이 생기겠네요.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;thread-safe singleton 을 한번 만들어보겠습니다. c++11 로 넘어오면서 많인 기능들이 생겼는데 그중 한개가 #include &amp;lt;mutex&amp;gt;에 들어있는 mutex 입니다. 이를 통해 손쉽게 thread 동기화가 가능합니다.&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;cpp&quot;&gt;
&lt;br /&gt;&lt;br /&gt;
#include &amp;lt;mutex&amp;gt;
class singleton
{

	static singleton* _instance;
	// thread safe 보장하려면 mutex가 필요해
	static std::mutex _mutex;
	singleton() {};

public:
	singleton(const singleton&amp;amp; other) = delete;
	static singleton* get_instance()
	{
		if (_instance == nullptr)
		{
			// lock 을 걸면 다른 thread는 기다려요
			_mutex.lock();
			_instance = new singleton();
			_mutex.unlock();
			// unlock 을 하면 이제 thread가 작업해요
		}
		return _instance;
	}

	static void release_instance() {
		if (_instance) {
			delete _instance;
			_instance = nullptr;
		}
	}
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;요즘 대부분은 lock, unlock 이 아닌 동일한 기능을 하는 std::lock_guard 를 사용하고 있습니다.&lt;br /&gt;-- 참조 : http://en.cppreference.com/w/cpp/thread/lock_guard&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;간단히 &amp;nbsp; thread 2개를 생성해서 singletone 객체를 생성하는 코드를 구성해 보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;cpp&quot;&gt;
&lt;br /&gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;mutex&amp;gt;

#include &amp;lt;thread&amp;gt;

class singleton
{
	static singleton* _instance;
	static std::mutex _mutex;
	singleton() {};

public:
	singleton(const singleton&amp;amp; other) = delete;
	static singleton* get_instance()
	{
		std::lock_guard&amp;lt;std::mutex&amp;gt; lock(_mutex);
		if (_instance == nullptr)
		{
			//_mutex.lock();
			_instance = new singleton();
			//_mutex.unlock()
			std::cout &amp;lt;&amp;lt; &quot;한번만 실행됩니다.&quot; &amp;lt;&amp;lt; std::endl;
		}
		return _instance;
	}

	static void release_instance() {
		if (_instance) {
			delete _instance;
			_instance = nullptr;
		}
	}
};
//http://en.cppreference.com/w/cpp/language/static 참조
std::mutex singleton::_mutex;
singleton* singleton::_instance = nullptr;


void make_instance_with_thread(singleton* ptr)
{
	ptr = singleton::get_instance();
}

int main()
{
	singleton* instance;
	std::thread t1(make_instance_with_thread, instance);
	std::thread t2(make_instance_with_thread, instance);
	
	t1.join(); t2.join();
	instance-&amp;gt;release_instance();
	return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Design pattern(C++)</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/7</guid>
      <comments>https://roadcom.tistory.com/7#entry7comment</comments>
      <pubDate>Wed, 26 Apr 2017 23:06:35 +0900</pubDate>
    </item>
    <item>
      <title>iterator (c++)</title>
      <link>https://roadcom.tistory.com/4</link>
      <description>&lt;p&gt;&lt;b&gt;iterator : 컨테이너에 저장된 원소를 순회하고 접근하는 일반화된 방법을 제공합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;iterator 를 말할때 항상 빠지지 않는 내용이 container&amp;nbsp;입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;**반복자&lt;br /&gt;임의의 컨테이너의 알고리즘을 몰라도 순회를 이어주는 매개&amp;nbsp;역할을 합니다.&lt;/p&gt;

&lt;p&gt;즉, vector, linkedlist 유사한 컨테이너임에도 물리적 자료구조가 전혀 다른 container로 순회하는 방법이 아주 다릅니다. 이렇게 제 각각인 container 들에 대해 순회 방법을 일반화하기 위해 STL 에서 사용하는 개념이 바로 반복자 입니다.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;custom container 를 구현한다고 했을 때, 가장 많이 사용하는 방법이&amp;nbsp;std::iterator를 상속받아 inner class로 구현하는 방식 입니다. 우선 custom container 를 구현하여 iteration 순회 및 c++11 의 range based for loop 가 동작하도록 구현해보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;cpp&quot;&gt;
&lt;br /&gt;&lt;br /&gt;
// custom container with inner iterator class
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;algorithm&amp;gt;


template&amp;lt;class T&amp;gt;
class rkvector
{
	int _size = 0;
	T* _buffer = nullptr;

public:
	/*
	template&amp;lt;
		class Category,
		class T,
		class Distance = std::ptrdiff_t,(depressed c++17)
		class Pointer = T*,
		class Reference = T&amp;amp;
	&amp;gt; struct iterator;
	*/

	// inner iterator class
	class iterator : std::iterator&amp;lt;std::input_iterator_tag, T&amp;gt;
	{
		T* _ptr;
	public:
		explicit iterator(T* ptr) :_ptr(ptr) {}
		// ++ 연산자 경우 직접적인 값이 아니라 iterator 를 반환
		// * 연산자를 통해서만 직접적인 값을 반환

		iterator&amp;amp; operator++() { ++_ptr; return (*this); }
		iterator operator++(int) { iterator retval = *this; ++_ptr; return retval; }

		reference operator*() { return *_ptr; }
		bool operator==(iterator other) const { return _ptr == other._ptr; }
		bool operator!=(iterator other) const { return _ptr != other._ptr; }
	};


	// 생성자
	rkvector() {}
	rkvector(int size)
	{
		if (_buffer == nullptr)
		{
			std::cout &amp;lt;&amp;lt; &quot;dynamic allocate&quot; &amp;lt;&amp;lt; std::endl;
			_buffer = new T[size];

			// T()  &amp;lt;-어떤 의미 일까요?
			std::fill(_buffer, _buffer + size, T());
			_size = size;
		}
	}

	// 소멸자
	~rkvector()
	{
		if (_size &amp;gt; 1)
			delete _buffer;
		else
			delete[] _buffer;
	}


	int size() const
	{
		return _size;
	}

	T operator[](int index) const
	{
		return _buffer[index];
	}

	iterator begin()
	{
		return iterator(_buffer);
	}
	iterator end()
	{
		return iterator(_buffer + _size);
	}

	void fill(T&amp;amp;&amp;amp; val)
	{
		for (int i = 0; i &amp;lt; _size;++i)
			_buffer[i] = val;
	}
};

int main()
{
	rkvector&amp;lt;int&amp;gt; vec(5);
	vec.fill(20);
	
	for (rkvector&amp;lt;int&amp;gt;::iterator it = vec.begin(); it != vec.end(); ++it)
	{
		std::cout &amp;lt;&amp;lt; *it &amp;lt;&amp;lt; std::endl;
	}
	std::cout &amp;lt;&amp;lt; &quot;C++11 range based for loop&quot; &amp;lt;&amp;lt; std::endl;
	for (int element : vec)
	{
		std::cout &amp;lt;&amp;lt; element &amp;lt;&amp;lt; std::endl;
	}
	return 0;
}
// road
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;STL vector 의 iterator 가 위와 같이 구현이 가능합니다.&lt;/p&gt;
&lt;p&gt;C++11 ragne based for loop 가 지원됨에 따라서 바로 for( : ) 문을 통해서도 순회가 가능하게 바뀌었습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;gt;&amp;gt; 출력 값&lt;/p&gt;
&lt;p&gt;dynamic allocate&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;C++11 range based for loop&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;
&lt;p&gt;20&lt;/p&gt;</description>
      <category>프로그래밍/Design pattern(C++)</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/4</guid>
      <comments>https://roadcom.tistory.com/4#entry4comment</comments>
      <pubDate>Mon, 24 Apr 2017 22:09:21 +0900</pubDate>
    </item>
    <item>
      <title>Design Patterns</title>
      <link>https://roadcom.tistory.com/2</link>
      <description>&lt;p&gt;보통 디자인 패턴은 크게 보면 아래 3가지 그룹이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;5월 한달간 아래 내용에 대해서 천천히 정리를 하도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1. Creational Patterns ( 객체 생성에 관여하는 pattern)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;1. Abstract Factory&amp;nbsp;&lt;/li&gt;&lt;li&gt;2. Builder&lt;/li&gt;&lt;li&gt;3. Factory Method&lt;/li&gt;&lt;li&gt;4. Prototype&lt;/li&gt;&lt;li&gt;5. Singleton :&amp;nbsp;&lt;a href=&quot;http://roadcom.tistory.com/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;http://roadcom.tistory.com/7&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p style=&quot;margin-left: 4em;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2. Structural Patterns ( class 관계 및 구조를 표현하는 pattern)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;1. Adaptor&lt;/li&gt;&lt;li&gt;2. Bridge&lt;/li&gt;&lt;li&gt;3. Composite&lt;/li&gt;&lt;li&gt;4. Decorator&lt;/li&gt;&lt;li&gt;5. Facade&lt;/li&gt;&lt;li&gt;6. Flyweight&lt;/li&gt;&lt;li&gt;7. Proxy&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p style=&quot;margin-left: 2em;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;3. Behavioral Patterns ( 어떤 행동에 집중하는 pattern)&lt;/b&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;ul style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;1. Mediator&lt;/li&gt;&lt;li&gt;2. Memento&lt;/li&gt;&lt;li&gt;3. Interpreter&lt;/li&gt;&lt;li&gt;4. Iterator &amp;nbsp;:&amp;nbsp;&lt;a href=&quot;http://roadcom.tistory.com/4&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;http://roadcom.tistory.com/4&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;5. Chain of Responsibility&lt;/li&gt;&lt;li&gt;6. Command&lt;/li&gt;&lt;li&gt;7. State&lt;/li&gt;&lt;li&gt;8. Strategy :&amp;nbsp;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;&lt;/span&gt;&lt;a href=&quot;http://roadcom.tistory.com/15&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;http://roadcom.tistory.com/15&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;9. Observer&lt;/li&gt;&lt;li&gt;10. Template Method&lt;/li&gt;&lt;li&gt;11. Visitor :&amp;nbsp;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;&lt;/span&gt;&lt;a href=&quot;http://roadcom.tistory.com/16&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;&lt;span style=&quot;color: rgb(9, 0, 255);&quot;&gt;http://roadcom.tistory.com/16&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Design pattern(C++)</category>
      <author>기루광</author>
      <guid isPermaLink="true">https://roadcom.tistory.com/2</guid>
      <comments>https://roadcom.tistory.com/2#entry2comment</comments>
      <pubDate>Sun, 23 Apr 2017 23:02:27 +0900</pubDate>
    </item>
  </channel>
</rss>