<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>현경이의 삽질기록</title>
    <description>삽질 2년차, 구글링 박사가 되었다
</description>
    <link>http://hyunkyung12.github.io/</link>
    <atom:link href="http://hyunkyung12.github.io/rss" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 11 Sep 2019 18:00:11 +0900</pubDate>
    <lastBuildDate>Wed, 11 Sep 2019 18:00:11 +0900</lastBuildDate>
    <generator>Jekyll v3.8.5</generator>
    
      <item>
        <title>[딥러닝 모델을 사용한 서버 배포하기 #3] Flask로 서버 개발하기</title>
        <description>&lt;h1 id=&quot;keras모델을-사용하는-flask서버-개발하기&quot;&gt;Keras모델을 사용하는 Flask서버 개발하기&lt;/h1&gt;

&lt;p&gt;앞의 포스팅에서 Tensorflow 모델을 Keras 모델로 바꾸어 사용하는 방법을 알아보았습니다.&lt;/p&gt;

&lt;p&gt;이제는 이 Keras 모델을 사용해 어떻게 서버를 만드는지 알아보도록 하겠습니다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Flask의 기본 개념에 대한 내용은 생략합니다. 기본 개념은 &lt;a href=&quot;http://flask.palletsprojects.com/en/1.1.x/&quot;&gt;공식문서&lt;/a&gt;를 참고하세요!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;미리보기)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/flask-server.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;만들 서버의 모습입니다! 간단한 UI와 &lt;del&gt;멋있는 사진&lt;/del&gt; 결과를 볼 수 있습니다! &lt;br /&gt;입력으로 이미지의 URL을 받아 Keras 모델을 사용해 결과물을 얻고, 그 결과를 웹 화면에 보여주는 방식입니다.&lt;/p&gt;

&lt;p&gt;순서는&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;flask 코드 작성&lt;/li&gt;
  &lt;li&gt;json 값을 이용해 html 화면에 결과 띄우기&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;로 진행하겠습니다.&lt;/p&gt;

&lt;h3 id=&quot;flask-코드-작성&quot;&gt;flask 코드 작성&lt;/h3&gt;

&lt;p&gt;우선은 &lt;code class=&quot;highlighter-rouge&quot;&gt;app.py &lt;/code&gt; 파일을 작성합니다. (flask를 실행할 파일)&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@app.route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'index.html'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;main 함수에서는 index 페이지만 보여주도록 합니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@app.route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# 1. url을 입력으로 받아서&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'url'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;c&quot;&gt;# 2. url을 이미지로 변환한 후&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_to_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# 3. Keras 모델의 input으로 사용&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;result_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# 4. json 형태로 리턴&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;result_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
						&lt;span class=&quot;s&quot;&gt;'url'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
						&lt;span class=&quot;s&quot;&gt;'result'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encode_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
					  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이번에는 실제로 모델을 사용하는 함수를 작성하겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 이미지의 url을 입력으로 받음&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;request.args.get('url')&lt;/code&gt; 이라고 하면, &lt;code class=&quot;highlighter-rouge&quot;&gt;/model?url=&lt;/code&gt; 뒤에 들어가는 url값을 가져옵니다.&lt;br /&gt;예를들어 /model?url=http://zum.com/ 이라는 입력이 들어오면 url 변수에는 ‘http://zum.com’ 이 들어갑니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. 이미지의 url을 이미지 배열로 변환&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;url_to_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;resp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urlopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asarray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytearray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;uint8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imdecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IMREAD_COLOR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;url을 읽어 array로 변환하고, 3차원 형태의 이미지 배열로 다시한번 변환하는 코드 입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. 이미지 배열을 모델의 input으로 사용해 모델 테스트&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;model.py&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'./model_complete.h5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'tf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'./model_weights.h5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_make_predict_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# predict 할 때 매번 쓰기 위해 사용하는 함수&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;predict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	
	&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'temp.png'&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imwrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드는 &lt;code class=&quot;highlighter-rouge&quot;&gt;model.py&lt;/code&gt;에 작성한 내용입니다. Flask에서 일반적으로 route를 가진 함수가 아니면 다른 파일로 분리해 작성하는 방식을 사용하기 때문에, 따로 분리해서 작성했습니다.&lt;/p&gt;

&lt;p&gt;여기서 중요한 두 가지가 있는데, 첫번째로 중요한 것은 &lt;code class=&quot;highlighter-rouge&quot;&gt;model.py&lt;/code&gt; 안에서 모델을 로드한다는 점입니다!&lt;br /&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;model.py&lt;/code&gt; 내에서 모델을 로드하면, &lt;code class=&quot;highlighter-rouge&quot;&gt;app.py&lt;/code&gt; 실행 시 맨 위에서 &lt;code class=&quot;highlighter-rouge&quot;&gt;model.py&lt;/code&gt;를 한번만 부르기 때문에 앱 실행동안 &lt;strong&gt;한번만&lt;/strong&gt; 모델을 로드할 수 있습니다.&lt;/p&gt;

&lt;p&gt;만약 &lt;code class=&quot;highlighter-rouge&quot;&gt;app.py&lt;/code&gt;내의 라우트를 가진 함수들 내에서 모델을 로드하면, 함수를 매번 호출할 때 마다 모델 파일을 읽기 때문에 매우 비효율적인 앱이 될 것입니다.&lt;/p&gt;

&lt;p&gt;두 번째로는 &lt;code class=&quot;highlighter-rouge&quot;&gt;model._make_predict_function()&lt;/code&gt; 부분입니다. &lt;br /&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;model.predict()&lt;/code&gt;를 하기 전에 호출을 해야 predict를 정상적으로 할 수 있습니다.&lt;br /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;정확한 사용 이유는 공식 문서에도 잘 나와있지 않습니다. Keras github Issue들에도 여러 질문이 있지만, 아직 명확한 답변은 나와있지 않습니다. 답변이 추가되면 수정하겠습니다!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. 결과를 json 형태로 리턴&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;result_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;'url'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;'result'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encode_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;매번 이미지 결과를 얻어서 이미지로 저장을 하면 저장공간 상의 문제가 될 수도 있어, &lt;code class=&quot;highlighter-rouge&quot;&gt;encode_image&lt;/code&gt;라는 함수 내에서 이미지를 인코딩 한 후 인코딩 값만 리턴하고 파일은 삭제하도록 구현을 했습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;json&lt;/code&gt;형식으로 리턴을 하면 서버에서 UI 없이 라우트로만 요청을 보내도 결과를 볼 수 있고, html에서 json형식의 결과를 사용하기 쉽다는 장점이 있습니다.&lt;/p&gt;

&lt;p&gt;이제 서버개발은 모두 끝났습니다!&lt;br /&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;python app.py&lt;/code&gt; 를 실행한 후 &lt;code class=&quot;highlighter-rouge&quot;&gt;/model?url=[url주소]&lt;/code&gt; 를 입력하게 되면 json 형식의 결과를 볼 수 있습니다!~~~!~!&lt;/p&gt;

&lt;p&gt;하지만 좀 더 편리하게 사용하기 위해 간단한 UI까지 개발해보도록 하겠습니다!&lt;/p&gt;

&lt;h3 id=&quot;2-json-값을-이용해-html-화면에-결과-띄우기&quot;&gt;2. json 값을 이용해 html 화면에 결과 띄우기&lt;/h3&gt;

&lt;p&gt;우선 flask에서 html 파일을 사용하기 위해서는 정해진 디렉토리 규칙이 있습니다.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;app.py
model.py
templates
	- index.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이런식으로 templates 폴더 내에 html 파일을 넣어주면 별다른 경로 지정 없이 flask가 html파일을 읽을 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;viewport&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;VIP&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;saliency map을 구할 이미지의 URL을 입력하세요&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'url'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;button&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;submit&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;table&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;result&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://code.jquery.com/jquery-3.4.1.js&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;integrity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;crossorigin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anonymous&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
 

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;

	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
	&amp;lt;tr&amp;gt;
		&amp;lt;td&amp;gt;&amp;lt;img class=&quot;crop-result&quot; src=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;gt;&amp;lt;/td&amp;gt;
		&amp;lt;td&amp;gt;&amp;lt;img class=&quot;crop-result&quot; src=&quot;data:image/png;base64, &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;gt;&amp;lt;/td&amp;gt;
	&amp;lt;/tr&amp;gt;
	`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

			&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'form.url'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
			&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

			&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/model'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'GET'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
					&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
					&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#result'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
					&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

			&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이게 전부입니다..! easy..!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. input tag로 입력값 받기&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'url'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;button&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;submit&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

			&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'form.url'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;input tag에 &lt;code class=&quot;highlighter-rouge&quot;&gt;name='url'&lt;/code&gt;속성을 주었고, form tag의 기본 method는 GET방식이므로, input에 값을 넘겨주면 &lt;code class=&quot;highlighter-rouge&quot;&gt;?url=값&lt;/code&gt; 으로 넘어가게 됩니다. &lt;br /&gt;이 때 값이 넘어가는 시점은 submit 버튼을 누를 때 입니다. 따라서 submit 버튼을 클릭할 때 처리 함수가 작동하도록 하면 됩니다.&lt;br /&gt;script 태그 내의 input 변수에 &lt;code class=&quot;highlighter-rouge&quot;&gt;?url=값&lt;/code&gt; 까지 넘어간 상태 입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. 입력받은 값으로 요청 보내기&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/model'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'GET'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 앞에서 flask로 작성한 함수에 요청을 보낼 차례 입니다.&lt;/p&gt;

&lt;p&gt;ajax 형식에 맞게 작성만 하면 됩니다. 어떤 url로 보낼 것인지, 어떤 데이터를 보낼 것인지, 어떤 방식으로 보낼것인지 정의합니다.&lt;br /&gt;위와 같이 작성하게 되면 &lt;code class=&quot;highlighter-rouge&quot;&gt;/model?url=input 값&lt;/code&gt; 형태로 요청이 넘어갑니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. 요청을 보낸 결과를 받아 파싱해서 뿌리기&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#result'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;	
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;요청을 보낸 결과를 json 형식으로 정의해 놓았기 때문에 &lt;code class=&quot;highlighter-rouge&quot;&gt;JSON.parse&lt;/code&gt; 로 쉽게 값을 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;여기서 한 가지 봐야할 것은 json 형태의 array를 mapping 해서 사용하는 부분입니다.&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;table&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;result&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/table&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
    &amp;lt;tr&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;img class=&quot;crop-result&quot; src=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;img class=&quot;crop-result&quot; src=&quot;data:image/png;base64, &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;mapping 시 사용한 Result라는 상수는 script의 윗 부분에서 정의했습니다.&lt;br /&gt;이 상수 내에서는 json에서 사용하는 key값을 간단히 사용할 수 있습니다.&lt;br /&gt; 안에 사용할 key 값들을 나열해주고, ${ … }로 값을 사용해주면 됩니다!&lt;/p&gt;

&lt;p&gt;그럼 이제 정말 끝입니다! (고양이 사진도 가능합니다!)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/cute.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Wed, 11 Sep 2019 15:38:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2019/09/11/flask_keras/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2019/09/11/flask_keras/</guid>
        
        <category>deep_learning</category>
        
        <category>flask</category>
        
        
      </item>
    
      <item>
        <title>[딥러닝 모델을 사용한 서버 배포하기 #2] Tensorflow모델을 Keras로 바꾸기</title>
        <description>&lt;h1 id=&quot;tensorflow로-작성된-코드를-keras로-바꾸기&quot;&gt;Tensorflow로 작성된 코드를 Keras로 바꾸기&lt;/h1&gt;

&lt;p&gt;앞에서 설명한 논문의 코드는 Tensorflow로 구현된 것이었습니다.&lt;/p&gt;

&lt;p&gt;하지만 배치단위로 처리하는 코드였기 때문에 실시간으로 한 개씩 처리에는 적합하지 않았고,&lt;br /&gt;배치마다 그래프를 다시 읽어야 하는 방식으로 구현되어 있었습니다.&lt;/p&gt;

&lt;p&gt;그래서 Tensorflow로 된 코드를 Keras로 바꾸고, 그래프는 실행시 한번만 읽을 수 있도록 로직을 수정하기로 했습니다!&lt;/p&gt;

&lt;h3 id=&quot;1-코드-바꾸기&quot;&gt;1. 코드 바꾸기&lt;/h3&gt;

&lt;p&gt;레이어 부분의 코드를 바꾸는 일은 어렵지 않습니다.&lt;br /&gt;tensorflow에서 지원하는 layer들은 대부분 Keras에도 있기 때문에 함수명과 인자만 잘 맞춰주면 됩니다.&lt;/p&gt;

&lt;p&gt;예를 들어 아래 tensorflow 코드는&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;layer01&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conv2d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;same&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;conv1/conv1_1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;layer02&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conv2d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layer01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;same&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;conv1/conv1_2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;layer03&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_pooling2d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layer02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                  &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Keras로 이렇게 변환하면 됩니다. (Keras의 layer 작성 방식 중 &lt;code class=&quot;highlighter-rouge&quot;&gt;Functional API&lt;/code&gt;를 사용했습니다.)&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;keras.layers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Conv2D&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;keras.layers.pooling&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MaxPooling2D&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Conv2D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kernel_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
           &lt;span class=&quot;n&quot;&gt;strides&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'same'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'relu'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'conv1/conv1_1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
           &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img_input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Conv2D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kernel_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
           &lt;span class=&quot;n&quot;&gt;strides&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'same'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'relu'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'conv1/conv1_2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
           &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MaxPooling2D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pool_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strides&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; 
                 &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pool1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'valid'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                 &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;여기서 &lt;code class=&quot;highlighter-rouge&quot;&gt;data_format&lt;/code&gt; 인자는 GPU 사용시 쓰이는 인자 입니다.&lt;/p&gt;

&lt;p&gt;기본적으로 tensor는 (num, w, h, channel) 순서로 구성되어 있고, 그렇기 때문에 &lt;code class=&quot;highlighter-rouge&quot;&gt;data_format&lt;/code&gt;의 디폴트값은 &lt;code class=&quot;highlighter-rouge&quot;&gt;data_format='channel_last'&lt;/code&gt; 입니다.&lt;br /&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;data_format='channel_first'&lt;/code&gt; 라고 하면 tensor의 순서가 (channel, num, w, h)로 변경되고, GPU 연산을 위해서는 반드시 명시해 주어야 하는 인자 입니다.&lt;/p&gt;

&lt;p&gt;문제는 tensorflow는 layer 중간에 tensor를 처리하는 함수를 넣을 수 있지만, Keras는 layer를 쌓아가는 형태이기 때문에 별도의 처리함수를 사용할 수 없다는 점이었습니다.&lt;/p&gt;

&lt;p&gt;예를들어&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;branch5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reduce_mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                         &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dims_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                         &lt;span class=&quot;n&quot;&gt;keepdims&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;branch5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conv2d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;branch5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;valid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                           &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aspp/conv1_5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;tensorflow에서는 tensor처리 후 layer를 사용할 수 있지만, Keras에서는 사용할 수 없습니다.&lt;br /&gt;Keras에서 이런 방식을 사용하려면 첫번째 branch5도 layer 형태여야 합니다.&lt;/p&gt;

&lt;p&gt;Keras에서는 &lt;a href=&quot;https://keras.io/layers/core/&quot;&gt;Lambda&lt;/a&gt; 라는 layer를 지원하고 있습니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Lambda를 이용하면 tensor처리한 것을 layer형태로 만들어 다음 layer에 적용할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;keras&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backend&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;keras.layers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Conv2D&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;branch5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                                       &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dims_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                                       &lt;span class=&quot;n&quot;&gt;keepdims&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoder_output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;branch5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Conv2D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kernel_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                 &lt;span class=&quot;n&quot;&gt;strides&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'valid'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'relu'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'aspp/conv1_5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                 &lt;span class=&quot;n&quot;&gt;data_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_data_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;branch5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이렇게 하면 tensorflow에서 사용하는 여러 처리 함수들도 쉽게 불러와서 쓸 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#tensorflow&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resize_bilinear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dims_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;factor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dims_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;factor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#Keras&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resize_bilinear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
													  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dims_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;factor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 														&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dims_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;factor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-weight-파일-바꾸기&quot;&gt;2. Weight 파일 바꾸기&lt;/h3&gt;

&lt;p&gt;사용한 &lt;a href=&quot;https://github.com/alexanderkroner/saliency&quot;&gt;딥러닝 모델&lt;/a&gt;의 깃허브는 &lt;code class=&quot;highlighter-rouge&quot;&gt;.pb&lt;/code&gt; 형태의 weight 파일을 제공하고 있습니다. &lt;br /&gt;하지만 이 파일을 Keras의 &lt;code class=&quot;highlighter-rouge&quot;&gt;load_model&lt;/code&gt; 로 읽으면 에러가 나는데, &lt;code class=&quot;highlighter-rouge&quot;&gt;load_model&lt;/code&gt;은 &lt;code class=&quot;highlighter-rouge&quot;&gt;.h5&lt;/code&gt; 형태의 파일만 지원하기 때문입니다. (&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/models/load_model&quot;&gt;공식 문서 참고&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;즉, Keras를 사용하기 위해서는 &lt;code class=&quot;highlighter-rouge&quot;&gt;.h5&lt;/code&gt; 형태의 weight 파일이 필요합니다. 가장 좋은 방법은 1번에서 새로 작성한 모델 구조로 다시 학습을 시켜 &lt;code class=&quot;highlighter-rouge&quot;&gt;.h5&lt;/code&gt; 파일을 만드는 것인데, &lt;del&gt;시간도 자원도 부족합니다,,, 기브미GPU,,,&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;그래서 최대한 &lt;code class=&quot;highlighter-rouge&quot;&gt;.pb&lt;/code&gt; 파일을 사용해보기로 했습니다!&lt;/p&gt;

&lt;p&gt;전체적인 과정은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Keras로 작성한 모델을 저장 후 불러옴&lt;/li&gt;
  &lt;li&gt;Keras로 작성한 모델 구조 (초기화 시 랜덤으로 들어간 weight 값을 포함)에서 변수명과 weight 값을 가져옴&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;.pb&lt;/code&gt; 파일을 읽어 그래프 구조를 파싱&lt;/li&gt;
  &lt;li&gt;그래프의 노드 이름과 Keras 모델의 레이어 이름을 짝으로 비교해 weight를 저장&lt;/li&gt;
  &lt;li&gt;1번에서 저장한 모델 구조에 3번에서 얻은 weight를 넣음&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keras로 작성한 모델을 저장 후 불러옵니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tensorflow&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'model_structure_gpu.h5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model_structure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'model_structure_gpu.h5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'tf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;.pb&lt;/code&gt; 파일의 그래프 노드들의 이름과 비교하기 위해 Keras 모델의 레이어 이름을 저장합니다.&lt;br /&gt;또한 그래프 노드에서 weight값을 가져와 저장하기 위해 랜덤으로 초기화된 weight값들도 저장합니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;target_model_variable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model_structure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weights&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# 모델의 레이어 이름&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;target_model_weights&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model_structure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# 모델의 weight들&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;.pb&lt;/code&gt;파일을 읽어 그래프들을 노드단위로 파싱합니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tensorflow&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tensorflow.python.platform&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gfile&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;GRAPH_PB_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'./model_salicon_gpu.pb'&lt;/span&gt; 

&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gfile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FastGFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GRAPH_PB_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'rb'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;graph_def&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GraphDef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;graph_def&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParseFromString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sess&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;as_default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;import_graph_def&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph_def&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;graph_nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph_def&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그리고 노드 중 속성이 상수인 노드 (= weight) 만 불러옵니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;wts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph_nodes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Const'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# weight만 불러옴&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;weight 노드들의 이름과 Keras 모델의 레이어 이름들을 비교하면서, 이름이 같으면 초기화된 weight 값이 있던 부분에 weight 노드의 weight 값을 넣어줍니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tensorflow.python.framework&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor_util&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 노드명이 일치하면 weight를 바꿔줌&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_model_variable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;target_model_weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor_util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MakeNdarray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[:-2] 로 슬라이싱 해 비교한 이유는 여기서 &lt;code class=&quot;highlighter-rouge&quot;&gt;.pb&lt;/code&gt; 파일의 노드 이름은 &lt;code class=&quot;highlighter-rouge&quot;&gt;aspp/conv1_2/kernel&lt;/code&gt; 형식이고, Keras 레이어 이름은 &lt;code class=&quot;highlighter-rouge&quot;&gt;aspp/conv1_2/kernel:0&lt;/code&gt; 형식이기 때문입니다.&lt;/p&gt;

&lt;p&gt;이제 다했습니다! 마지막으로  &lt;code class=&quot;highlighter-rouge&quot;&gt;set_weights&lt;/code&gt; 함수를 이용해 방금 만든 weight를 처음 모델에 적용해주면 됩니다!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;model_structure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_model_weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 테스트를 위해 모델을 저장하고 불러오기만 하면 됩니다!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tensorflow&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;model_structure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'model_weights_gpu.h5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model_gpu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'model_structure_gpu.h5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;custom_objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'tf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model_gpu&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'model_weights_gpu.h5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;여기서 &lt;code class=&quot;highlighter-rouge&quot;&gt;custom_objects&lt;/code&gt; 옵션으로 Lambda 레이어에서 사용한 라이브러리들을 작성해야만 정상적으로 모델을 불러올 수 있습니다.&lt;/p&gt;

&lt;p&gt;테스트 결과 &lt;code class=&quot;highlighter-rouge&quot;&gt;.pb&lt;/code&gt; 파일로 얻은 결과물과 동일한 결과물을 얻을 수 있었습니다!&lt;br /&gt;약간 미련한 짓으로 보일수도 있겠지만,,, 다시 학습할 시간과 자원을 아꼈습니다,,! 시간은 금이니까요~ 다들 아껴쓰시길 바라며 포스팅 마무리하겠습니다!&lt;/p&gt;
</description>
        <pubDate>Wed, 11 Sep 2019 13:40:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2019/09/11/tf2keras_1/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2019/09/11/tf2keras_1/</guid>
        
        <category>deep_learning</category>
        
        
      </item>
    
      <item>
        <title>[딥러닝 모델을 사용한 서버 배포하기 #1] 어떤 모델을 사용할까</title>
        <description>&lt;p&gt;딥러닝 모델을 사용해 서버 배포하기 첫번째는 어떤 모델을 사용할까에 관한 내용입니다!&lt;/p&gt;

&lt;p&gt;이번에 제가 사용해 본 모델은 &lt;strong&gt;Saliency map&lt;/strong&gt;을 딥러닝으로 예측하는 모델입니다.&lt;br /&gt;
saliency map 예측 관련 &lt;a href=&quot;http://saliency.mit.edu/results_mit300.html&quot;&gt;벤치마크&lt;/a&gt;를 비교해 놓은 사이트가 있는데,&lt;br /&gt;
저는 여기서 python으로 구현된 모델들 중 &lt;strong&gt;MSI-Net&lt;/strong&gt;을 사용했습니다.&lt;/p&gt;

&lt;p&gt;이번 포스팅에서는 &lt;strong&gt;MSI-Net&lt;/strong&gt;논문의 내용을 리뷰하면서 어떤 모델인지 살펴보겠습니다.&lt;/p&gt;

&lt;h1 id=&quot;contextual-encoder-decoder-network-for-visual-saliency-prediction&quot;&gt;Contextual Encoder-Decoder Network for Visual Saliency Prediction&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;논문 주소 : &lt;a href=&quot;https://arxiv.org/pdf/1902.06634.pdf&quot;&gt;https://arxiv.org/pdf/1902.06634.pdf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;깃헙 주소 : &lt;a href=&quot;https://github.com/alexanderkroner/saliency&quot;&gt;https://github.com/alexanderkroner/saliency&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;saliency-map이란&quot;&gt;Saliency map이란&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/files/saliency-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;사람이 어떤 장면을 봤을 때 집중해서 보게되는 부분을 시각화한 것&lt;/p&gt;

&lt;p&gt;처음에는 밝기차이, 색상차이 등의 low level feature를 이용했다면, 최근의 연구에서는 CNN등의 모델을 통해 다양한 feature를 이용하고 있음&lt;/p&gt;

&lt;h3 id=&quot;모델-구조&quot;&gt;모델 구조&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/files/sailency-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;크게 Encoder, ASPP, Decoder 세 부분으로 나뉨&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encoder :&lt;/strong&gt; 기본적으로 VGG16 구조를 사용하고, 몇 가지의 수정사항을 추가&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Dilation Convolution Layer 사용&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/files/saliency-3.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;기본 Convolution 연산은 필터크기와 동일한 시야 (receptive field)를 가지는데 비해,&lt;/p&gt;

    &lt;p&gt;Dilation Convolution 연산은 같은 연산비용 대비 더 넓은 시야를 가짐&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;pre-trained 된 VGG16모델을 사용할 때 파라미터 수가 동일하기 때문에 그대로 사용할 수 있음&lt;/li&gt;
      &lt;li&gt;논문에서는 위의 사진과 같이 rate=2 인 필터를 사용했으며, 3&lt;em&gt;3 필터이지만 5&lt;/em&gt;5와 거의 유사한 영역을 봄&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;del&gt;선행 연구에서 Saliency Map에는 Dilation Convolution이 좋다고 해서 사용…&lt;/del&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;dl&gt;
      &lt;dt&gt;Pooling layer들을 concat한 값을 최종 결과로 사용&lt;/dt&gt;
      &lt;dd&gt;
        &lt;p&gt;각각 다른 level에서의 pooling layer 값들은 공간적 특징을 보존하므로,&lt;/p&gt;
      &lt;/dd&gt;
    &lt;/dl&gt;

    &lt;p&gt;w*h 차원이 같은 마지막 세 pooling layer들을 concat해서 공간적 특징을 보존하는 activation map 생성&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;모델 구조에서 첫 번째 pooling layer의 shape는 (?, w, h, 256) 이고,&lt;/p&gt;

        &lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; 두 번째와 세 번째 pooling layer의 shape는 (?, w, h, 512) 이므로 
    
 axis=3 기준으로 concat했을 때 최종 (?, w, h, 1280) 인 activation map 생성
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ASPP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DeepLab  V2 (Segmentation 모델) 에서 제안된 방법&lt;/p&gt;

&lt;p&gt;갯수는 같고 파라미터 (rate, size, padding)가 다른 여러 필터를 적용한 후 concat 해 사용&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/saliency-4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;논문에서는 총 5개 종류의 필터 종류를 사용
    &lt;ul&gt;
      &lt;li&gt;각 필터를 거친 결과는 (?, w, h, 256) 이고 5개를 concat 하므로 (?, w, h, 256*5)&lt;/li&gt;
      &lt;li&gt;최종 출력은 (?, w, h, 256) 이어야 하므로 concat 결과에 마지막으로 필터 256개를 사용하는 1*1 convolution 연산을 해줌&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Decoder&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;원본 이미지와 같은 크기의 Saliency map을 생성하기 위해 convolution + upsampling&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;bilinear로 upsampling&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/files/saliency-5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;​&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/files/saliency-6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;앞에서 2&lt;em&gt;2 pooling 을 세 번 했으므로 upsampling+convolution도 2&lt;/em&gt;2 로 세 번 해주면 됨&lt;/li&gt;
  &lt;li&gt;upsampling 결과를 128 → 64 → 32 → 1 개의 필터로 convolution 하며 최종 saliency map 생성&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;학습하기&quot;&gt;학습하기&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Encoder는 ImageNet 과 Places2로 pre-train된 VGG16구조를 사용
    &lt;ul&gt;
      &lt;li&gt;ImageNet : 1000개의 클래스로 구성된 물체 이미지 데이터셋
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://gist.github.com/aaronpolhamus/964a4411c0906315deb9f4a3723aac57&quot;&gt;https://gist.github.com/aaronpolhamus/964a4411c0906315deb9f4a3723aac57&lt;/a&gt; (클래스목록)&lt;/li&gt;
          &lt;li&gt;이미지 + 이미지의 클래스 정보 로 구성&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Places2 : 400개의 클래스로 구성된 장소 이미지 데이터셋
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://github.com/metalbubble/places_devkit&quot;&gt;https://github.com/metalbubble/places_devkit&lt;/a&gt; (클래스목록)&lt;/li&gt;
          &lt;li&gt;이미지 + 이미지의 클래스 정보 로 구성&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;ASPP와 Decoder weight는 Xavier 초기화를 사용&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://reniew.github.io/13/&quot;&gt;https://reniew.github.io/13/&lt;/a&gt; (Xavier 초기화 설명)&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;Loss는 KL Divergence 를 사용&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/files/saliency-7.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;saliency map 을 분포 예측이라고 생각&lt;/li&gt;
  &lt;li&gt;Q는 target 분포, P는 예측 분포, i는 각 픽셀의 인덱스&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;학습 데이터 셋은 세 가지&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;MIT1003 : 실내, 실외 풍경 데이터 300개&lt;/li&gt;
  &lt;li&gt;CAT2000 : 20개 카테고리 (예술작품, 만화 등 ..) 데이터 4000개
    &lt;ul&gt;
      &lt;li&gt;이미지 + 이미지의 saliency 정보 (matrix)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;SALICON : COCO 이미지 중 160개 카테고리에 대해
    &lt;ul&gt;
      &lt;li&gt;이미지 + 이미지의 saliency annotation 정보 (json)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;한계점&quot;&gt;한계점&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/files/saliency-8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;(a) 어두운 얼굴 (b) 작은 글씨 (c) 사진 내 사람들의 시선 (d) low-level의  대비되는 feature 을 잘 못 찾음&lt;/p&gt;

</description>
        <pubDate>Wed, 11 Sep 2019 11:20:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2019/09/11/saliency_map/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2019/09/11/saliency_map/</guid>
        
        <category>deep_learning</category>
        
        
      </item>
    
      <item>
        <title>[최신 정보검색론] 정보검색평가</title>
        <description>&lt;h1 id=&quot;chapter-8-정보-검색-평가&quot;&gt;Chapter 8 정보 검색 평가&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;이 글은 &lt;a href=&quot;https://nlp.stanford.edu/IR-book/pdf/irbookonlinereading.pdf&quot;&gt;최신 정보검색론&lt;/a&gt; 을 읽고 정리 한 내용입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;정보 검색 시스템은 문헌 검색, 문서 분류 등의 작업으로 구성됩니다. Chapter 8 에서는 이 작업들의 평가 척도를 알아보겠습니다.&lt;/p&gt;

&lt;h3 id=&quot;81-순위-없는-검색-집합의-평가&quot;&gt;8.1 순위 없는 검색 집합의 평가&lt;/h3&gt;

&lt;h4 id=&quot;1-정확률과-재현율&quot;&gt;1) 정확률과 재현율&lt;/h4&gt;

&lt;p&gt;시스템의 유효성을 측정하는 지표에는 크게 &lt;strong&gt;정확률(Precision)&lt;/strong&gt; 과 &lt;strong&gt;재현율(Recall)&lt;/strong&gt;이 있습니다.&lt;/p&gt;

&lt;p&gt;쉽게 설명하자면 정확률은 &lt;strong&gt;검색된 것 중에 적합하게 검색 된 것&lt;/strong&gt;의 비율이고, 재현율은 &lt;strong&gt;적합한 것 중에 검색된 것&lt;/strong&gt;을 의미합니다.&lt;/p&gt;

&lt;p&gt;분할표로 나타내면 아래와 같습니다.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt; &lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;적합&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;부적합&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;검색&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;긍정 정답(tp)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;긍정 오류(fp)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;미검색&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;부정 오류(fn)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;부정 정답(tn)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;여기서 Precision 은 tp/(tp+fp) 이고, Recall 은 tp/(tp+fn) 이라고 정의할 수 있습니다.&lt;/p&gt;

&lt;p&gt;일반적으로 쓰는 Accuracy 는 (tp+tn)/전체 인데, 이것은 정보 검색 모델에는 적합하지 않습니다. 대부분 tp 보다는 tn 이 많게 때문에 틀린것을 틀리다고 분류해도 Accuracy 전체는 올라가기 때문입니다.&lt;/p&gt;

&lt;p&gt;이런 경우 처럼, tp와 tn 의 균형이 매우 불균형 한 경우 Accuracy 대신에 F-Score 라는 개념을 사용합니다.&lt;/p&gt;

&lt;h4 id=&quot;2-f-score&quot;&gt;2) F-Score&lt;/h4&gt;

&lt;p&gt;F-Score 는 &lt;strong&gt;Precision과 Recall 을 적절히 고려&lt;/strong&gt;해 사용하는 지표입니다. Precision 과 Recall 의 조화 평균을 사용합니다.  조화 평균을 사용함으로써 Precision 과 Recall 의 크기의 불균형을 조절할 수 있습니다.&lt;/p&gt;

&lt;p&gt;$ F = \frac{ (\beta^2 + 1) P R}{\beta^2P + R}$ 식에서 $ \beta $ 는 그 불균형을 얼마나 조절할까에 대한 파라미터 입니다. 보통은 $ \beta = 1 $ , 즉 P와 R에 동일한 가중치를 주는 값을 많이 쓰고, 이것을 &lt;strong&gt;F1-Score&lt;/strong&gt; 라고 부릅니다.&lt;/p&gt;

&lt;h3 id=&quot;82-순위-검색-결과의-평가&quot;&gt;8.2 순위 검색 결과의 평가&lt;/h3&gt;

&lt;p&gt;위에서 살펴본 내용들은 순위가 없는 집합 기반의 평가 척도입니다. 다시말해 검색결과가 적합/부적합 인 것에 대한 평가만 가능합니다. &lt;strong&gt;얼마나&lt;/strong&gt; 적합/부적합 한지를 평가하려면 (순위가 있으면) 새로운 척도가 필요합니다.&lt;/p&gt;

&lt;h4 id=&quot;1-평균-정확률map&quot;&gt;1) 평균 정확률(MAP)&lt;/h4&gt;

&lt;p&gt;얼마나 적합한지 평가하기 위해서 가장 간단한 방법은 상위 k개에 대해서만 평가하는 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MAP&lt;/strong&gt; 는 이름 그대로 평균적인 정확률을 보여줍니다. 한 쿼리에 대한 적합 문헌 집합들 중 k 개를 선정해 평균을 낸 것을 그 쿼리에 대한 정확률로 보는 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;주의)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;순위 검색을 위해서도 결국은 Precision과 Recall 개념을 사용하게 됩니다. 하지만 이 둘은 trade-off 가 있기 때문에 Recall 을 일정수준에 고정시킨 후, 그 수준에서의 최고 Precision 값을 찾는것이 좋습니다.&lt;/p&gt;

&lt;p&gt;Precision 과  Recall 이  trade-off 관계인것이 이해가 가지 않는다면 &lt;a href=&quot;https://sumniya.tistory.com/26&quot;&gt;여기&lt;/a&gt; 를 참고해주세요.&lt;/p&gt;

&lt;h3 id=&quot;83-시스템-품질과-사용자-유용도&quot;&gt;8.3 시스템 품질과 사용자 유용도&lt;/h3&gt;

&lt;h4 id=&quot;1-시스템-문제&quot;&gt;1) 시스템 문제&lt;/h4&gt;

&lt;p&gt;시스템 자체의 평가를 위해서는 다양한 기준들이 있습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;색인 속도&lt;/li&gt;
  &lt;li&gt;검색 속도&lt;/li&gt;
  &lt;li&gt;복잡한 쿼리의 처리&lt;/li&gt;
  &lt;li&gt;컬렉션의 크기&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;대부분의 기준들은 수치적으로 측정이 가능하기 때문에, 비교적 평가를 명확하게 할 수 있습니다.&lt;/p&gt;

&lt;h4 id=&quot;2-사용자-유용도&quot;&gt;2) 사용자 유용도&lt;/h4&gt;

&lt;p&gt;사용자의 유용도의 측정은 목적에 따라 조금씩 다를 수 있습니다. 일반적인 검색엔진에 대한 유용도는 재방문률로 측정할 수 있고, 다른 검색엔진 대비 방문률도 유용도의 척도가 될 수 있습니다.&lt;/p&gt;

&lt;h4 id=&quot;3-배치된-시스템의-정제&quot;&gt;3) 배치된 시스템의 정제&lt;/h4&gt;

&lt;p&gt;시스템을 업데이트 하고싶다면, 기존 시스템 대비 사용자의 만족도가 높은지를 알 수 있어야 합니다.&lt;/p&gt;

&lt;p&gt;가장 일반적으로는 &lt;strong&gt;A/B 테스트&lt;/strong&gt; 를 사용합니다. 기존 시스템과 제안 시스템에 한 가지의 차이를 두고 사용량을 조사하는 것입니다.&lt;/p&gt;

&lt;p&gt;사용량을 조사하는 방법에는 최상위 결과나 첫 페이지의 결과를 얼마나 클릭했는지 분석하기 등이 있습니다. 이런 방법을 &lt;strong&gt;클릭 로그 분석&lt;/strong&gt;, &lt;strong&gt;클릭 스트림 마이닝&lt;/strong&gt; 이라고 합니다.&lt;/p&gt;

</description>
        <pubDate>Fri, 12 Apr 2019 13:50:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2019/04/12/metric/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2019/04/12/metric/</guid>
        
        <category>machine_learning</category>
        
        <category>search_engine</category>
        
        
      </item>
    
      <item>
        <title>[최신 정보검색론] 지지 벡터 기계와 기계 학습</title>
        <description>&lt;h1 id=&quot;chapter-15-지지-벡터-기계와-기계-학습&quot;&gt;Chapter 15 지지 벡터 기계와 기계 학습&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;이 글은 &lt;a href=&quot;https://nlp.stanford.edu/IR-book/pdf/irbookonlinereading.pdf&quot;&gt;최신 정보검색론&lt;/a&gt; 을 읽고 정리 한 내용입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Chapter 15 에서는 분류 모델 중 하나인 지지 벡터 기계 &lt;strong&gt;(SVM)&lt;/strong&gt; 에 대해 알아보겠습니다.&lt;/p&gt;

&lt;p&gt;SVM 의 기본적인 아이디어는 &lt;strong&gt;두 범주의 경계를 가장 넓게 하는 경계&lt;/strong&gt;를 찾는 것 입니다. 주로 2-Class 분류에 많이 쓰이며, 필요에 따라 회귀나 다범주 분류에도 쓰입니다.&lt;/p&gt;

&lt;h3 id=&quot;151-선형-분류-문제&quot;&gt;15.1 선형 분류 문제&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/files/SVM basic.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;선형분류란 위의 별과 동그라미 자료를 구분하는 선을 찾는 문제로 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt;A 와 B 가 둘 다 선형 분류인데, 이 중 어떤 선이 더 좋은 분류기일까요?&lt;/p&gt;

&lt;p&gt;답은 B입니다. SVM 은 두 범주의 경계를 가장 넓게, 즉 가장  확실하게 분류하는 분류기를 찾는 것이 목적이기 때문입니다.&lt;/p&gt;

&lt;p&gt;여기서 분류기를 결정하는 점 (노란색으로 표시된 점) 을 &lt;strong&gt;Support Vector&lt;/strong&gt; 라고 합니다.&lt;/p&gt;

&lt;h3 id=&quot;152-svm-의-확장&quot;&gt;15.2 SVM 의 확장&lt;/h3&gt;

&lt;h4 id=&quot;1-soft-margin-svm&quot;&gt;1) soft margin SVM&lt;/h4&gt;

&lt;p&gt;SVM 분류기는  B’ 나 B’’ 선 바깥쪽으로 어떠한 데이터가 추가되어도 분류기가 바뀌지 않습니다. Support Vector 만이 분류기를 결정하기 때문입니다.&lt;/p&gt;

&lt;p&gt;문제는 B’ 와 B’’ 사이나 근처에 데이터가 추가되는 경우입니다. 그 사이에 데이터가 추가되면 분류기가 바뀔 수도 있고, 만약의 경우 이상치가 들어온다면 이상치에 의해 분류기가 결정될 수 있기 때문입니다.&lt;/p&gt;

&lt;p&gt;이런 이상치에 대비하기 위해서 우리는 보다 유연한 모델이 필요합니다. 선형 SVM 모델 보다 이상치에 유연한 모델을 &lt;strong&gt;soft margin&lt;/strong&gt;모델 이라고 합니다. (수식은 뒤에서 설명하겠습니다.)&lt;/p&gt;

&lt;p&gt;앞의 기본 SVM 모델 (hard margin) 에서 파라미터 $C$를 추가하면 soft margin 모델을 고려할 수 있는데, 이 $C$값에 따라 이상치를 얼마나 허용할 지 결정하게 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/soft margin SVM.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;$C$ 값이 작을수록 이상치를 많이 허용하고, $C$ 값이 클수록 이상치를 적게 허용합니다.  즉, $C$ 가 작을수록 과소적합, $C$ 가 클수록 과대적합이 될 위험이 높기 때문에 적절한 파라미터 값을 찾는 과정이 필요합니다.&lt;/p&gt;

&lt;h3 id=&quot;2-비선형-svm&quot;&gt;2) 비선형 SVM&lt;/h3&gt;

&lt;p&gt;이제까지는 선형 SVM 모델만 보았습니다. 하지만 실제 데이터에서는 아무리 선형으로 분류하려고 해도 되지 않는 경우가 더 많습니다. 이런 경우에도 우리는 &lt;strong&gt;커널&lt;/strong&gt; 이라는 개념을 통해 선형 분류기를 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/non linear SVM.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;좌측의 Input Space 에서는 선형 분류기를 사용할 수 없지만, 차원을 높여 우측의 모양으로 만들어 선형 분류기 (초평면) 을 정의할 수 있습니다.&lt;/p&gt;

&lt;p&gt;이처럼 저차원 공간을 고차원 공간으로 사상하는 방법을 &lt;strong&gt;커널&lt;/strong&gt; 이라고 합니다.&lt;/p&gt;

&lt;p&gt;이 커널에는 많은 종류가 있지만, 많이 사용하는 &lt;strong&gt;가우시안 RBF 커널&lt;/strong&gt;의 개념에 대해서 주로 설명을 하겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/RBF 커널.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;RBF 커널은 &lt;strong&gt;gamma&lt;/strong&gt; 를 파라미터로 사용합니다. 위의 그림은 gamma 값에 따른 RBF 커널의 표준편차 를 나타냅니다. gamma 가 클수록 표준편차가 작습니다. 즉, gamma가 클수록 한 데이터 포인터들이 영향력을 행사하는 거리가 짧아지는 반면, gamma가 낮을수록 커진다고 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt;soft margin SVM 모델에 RBF 커널을 사용한다고 하면, C와 gamma 총 두 개의 파라미터를 최적화 하는 작업이 필요합니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/RBF gamma and C.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;C 값이 커질수록 이상치를 적게 허용 하고 있는 것을 확인할 수 있고, gamma 값이 커질수록 경계가 더 구체적으로 변하는 것을 확인할 수 있습니다. 이러한 성질들을 고려해 적절한 파라미터를 정하는 것이 중요합니다.&lt;/p&gt;

&lt;h3 id=&quot;-수식&quot;&gt;+) 수식&lt;/h3&gt;

&lt;p&gt;수식적으로 분류기를 구하면 다음과 같습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/svm demonstration.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;초평면의 절편을 $b​$, 초평면에 직교하는 법선 벡터 (가중치 벡터) 를 $ \vec{w}  ​$ 라고 하면, 초평면 상의 모든 점 $\vec{x}​$는&lt;/p&gt;

&lt;p&gt;$\vec{w}^T\vec{x} = -b​$를 만족합니다.&lt;/p&gt;

</description>
        <pubDate>Thu, 11 Apr 2019 17:30:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2019/04/11/SVM/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2019/04/11/SVM/</guid>
        
        <category>machine_learning</category>
        
        <category>search_engine</category>
        
        
      </item>
    
      <item>
        <title>[최신 정보검색론] 점수 계산, 용어 가중치, 벡터 공간 모델</title>
        <description>&lt;h1 id=&quot;chapter-6-점수-계산-용어-가중치-벡터-공간-모델&quot;&gt;Chapter 6. 점수 계산, 용어 가중치, 벡터 공간 모델&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;이 글은 &lt;a href=&quot;https://nlp.stanford.edu/IR-book/pdf/irbookonlinereading.pdf&quot;&gt;최신 정보검색론&lt;/a&gt; 을 읽고 정리 한 내용입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Boolean 질의로 매칭되는 문헌들을 찾았을 때, 그 문헌들에 점수를 부여해 순서를 정하는 과정이 필요합니다.&lt;/p&gt;

&lt;p&gt;Chapter 6 에서는 그 방법들에 대해 다루겠습니다.&lt;/p&gt;

&lt;h3 id=&quot;61-인수-색인과-구역-색인&quot;&gt;6.1 인수 색인과 구역 색인&lt;/h3&gt;

&lt;p&gt;문헌은 용어 뿐 아니라 &lt;strong&gt;메타 데이터&lt;/strong&gt; 를 포함한 구조입니다. 메타 데이터란 저자, 제목, 출판일 등 문헌의 기본 정보를 의미합니다.&lt;/p&gt;

&lt;p&gt;검색 결과에 점수를 부여할 때, 이 메타 데이터를 활용할 수 있습니다. 메타 데이터 중 값이 작은것을 &lt;strong&gt;필드&lt;/strong&gt;, 값이 비교적 큰 것을 &lt;strong&gt;구역&lt;/strong&gt;이라고 하는데 주로 구역에 대해 살펴보겠습니다.&lt;/p&gt;

&lt;h4 id=&quot;1-가중치-구역-점수-계산&quot;&gt;1) 가중치 구역 점수 계산&lt;/h4&gt;

&lt;p&gt;메타 데이터의 각 구역에 &lt;strong&gt;가중치&lt;/strong&gt;를 부여해 매칭 정도를 계산하면, 점수를 매길 수 있는 형태가 됩니다.&lt;/p&gt;

&lt;p&gt;예를 들어,&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;문헌 ID&lt;/th&gt;
      &lt;th&gt;저자&lt;/th&gt;
      &lt;th&gt;제목&lt;/th&gt;
      &lt;th&gt;본문&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1&lt;/td&gt;
      &lt;td&gt;현경&lt;/td&gt;
      &lt;td&gt;고양이 좋아&lt;/td&gt;
      &lt;td&gt;고양이가 최고야&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2&lt;/td&gt;
      &lt;td&gt;고양이&lt;/td&gt;
      &lt;td&gt;고양이가 좋아하는 것&lt;/td&gt;
      &lt;td&gt;츄르가 최고야&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;위의 자료에서 저자, 제목, 본문에 각각 가중치 $ 0.2 , 0.3, 0.5​$ 를 부여한다고 합시다.&lt;/p&gt;

&lt;p&gt;쿼리가 ‘고양이’ 일 때, 문헌 1의 점수는 $ 0.2 * 0 + 0.3 * 1 + 0.5*1 = 0.8 $ 이고, 문헌 2의 점수는 $ 0.5 $ 입니다.&lt;/p&gt;

&lt;p&gt;두 문헌 모두 ‘고양이’ 라는 단어를 두번씩 포함하지만, 본문에 가중치를 높게 주었기 때문에 문헌1의 점수가 더 높습니다.&lt;/p&gt;

&lt;p&gt;이렇게 더 중요하다고 생각하는 구역에 가중치를 높게 줌으로써 순위를 정할 수 있었습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;그렇다면 이 가중치는 어떻게 구할까요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;위의 예제처럼 값을 지정해 사용할 수도 있지만, 일반적으로는 최적의 값을 찾기 위해 &lt;strong&gt;학습&lt;/strong&gt; 을 합니다.&lt;/p&gt;

&lt;p&gt;학습을 위한 데이터셋은 보통 (질의 q, 문헌 d, 적합성여부) 로 구성 됩니다. 가중치는 g 입니다.&lt;/p&gt;

&lt;p&gt;제목(T)와 본문(B)에 대한 가중치를 구하는 경우를 생각해 보면,&lt;/p&gt;

&lt;p&gt;$ score(d_j, q_j) = g * s_T(d_j, q_j) + (1-g) * s_B(d_j, q_j) ​$ 인 식을 생각할 수 있습니다.&lt;/p&gt;

&lt;p&gt;모든 구역에 대한 가중치 합은 1이고, $ s_T $와 $ s_B $는 각각 쿼리와 제목,본문의 일치 여부에 대한 Boolean값입니다.&lt;/p&gt;

&lt;p&gt;이 score 값을 데이터셋의 적합성 여부와 비교해, 다음과 같이 오차함수를 정의할 수 있습니다.&lt;/p&gt;

&lt;p&gt;$ \epsilon(d_j, q_j) = (r(d_j, q_j) - score(d_j, q_j))^2 $&lt;/p&gt;

&lt;p&gt;그렇다면 총 오류는 모든 데이터 쌍에 대한 $ \epsilon ​$ 값의 합이 됩니다.&lt;/p&gt;

&lt;p&gt;결과적으로, &lt;strong&gt;총 오류를 최소로 만드는 가중치 g의 값을 찾는 것&lt;/strong&gt;이 최적의 가중치를 찾는 것임을 알 수 있습니다.&lt;/p&gt;

&lt;p&gt;이 문제는 g 에 대한 이차식이 최소가 되는 점, 즉 &lt;strong&gt;미분해서 0이 되는 점&lt;/strong&gt;을 찾으면 되는 문제입니다.&lt;/p&gt;

&lt;h3 id=&quot;62-용어-빈도와-가중치&quot;&gt;6.2 용어 빈도와 가중치&lt;/h3&gt;

&lt;p&gt;1) 에서는 구역에 가중치를 부여했다면, 2)에서는 &lt;strong&gt;문헌 내 용어&lt;/strong&gt;에 가중치를 부여합니다.&lt;/p&gt;

&lt;p&gt;문헌1과 2에 동일한 단어가 있는데, 그 단어의 중요성이 문헌1보다 2에서 크다면 문헌2의 단어에 높은 점수를 주는 것입니다. 즉, 문헌에서 중요한 단어를 포함하는지를 살펴보는 것입니다.&lt;/p&gt;

&lt;p&gt;이 절에서는 빈도 관련 용어가 많이 나오기 때문에 용어를 정리해 보겠습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;용어 빈도 (tf) : 문헌 d 내에서 용어 t의 빈도&lt;/li&gt;
  &lt;li&gt;문헌 빈도 (df) : 컬렉션 c 내에서 용어 t를 포함하는 문헌의 수&lt;/li&gt;
  &lt;li&gt;역문헌 빈도 (idf) : $ log(\frac {N} {df}) ​$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;용어에 가중치를 주는 가장 간단한 방법은 문헌 내 용어의 빈도 (&lt;strong&gt;tf&lt;/strong&gt;) 를 세는 것 입니다.&lt;/p&gt;

&lt;p&gt;하지만 이 방법은 문제가 있습니다. 예를 들어 고양이 서적 관련 컬렉션에서 용어 ‘고양이 화장실’를 찾는 경우를 생각해봅시다.  &lt;del&gt;너무 극단적이네요…&lt;/del&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;문헌 1&lt;/th&gt;
      &lt;th&gt;문헌 2&lt;/th&gt;
      &lt;th&gt;문헌 3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;고양이 … 고양이 … 고양이 … 고양이 … 고양이&lt;/td&gt;
      &lt;td&gt;고양이 고양이 화장실&lt;/td&gt;
      &lt;td&gt;화장실&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;문헌 1 에서 고양이의 빈도는 5, 문헌 2 에서 고양이의 빈도는 2 이므로 빈도 수만 생각해본다면 ‘고양이 화장실’의 검색결과는 문헌 1로 잘못 나오게 됩니다.&lt;/p&gt;

&lt;p&gt;고양이 서적 관련 컬렉션에서는 모든 문헌이 대체적으로 ‘고양이’를 많이 포함하고 있기 때문에 ‘고양이’보다는 ‘화장실’에 집중하는 것이 좋습니다. 그러기 위해서는 ‘고양이’의 많은 빈도를 조절해 중요도를 낮추어 주어야 합니다.&lt;/p&gt;

&lt;p&gt;빈도 조절을 위해 컬렉션 내에서 ‘고양이’를 포함하는 문헌의 수 (&lt;strong&gt;df&lt;/strong&gt;) 를 세어줍니다. 위의 예에서는 2 입니다.&lt;/p&gt;

&lt;p&gt;‘고양이’를 포함하는 문헌이 많을 수록 그 용어를 덜 중요하게 보고 싶기 때문에, 전체 문헌 수 (N) 를 df 로 나누어 줍니다. 이 값을 역문헌 빈도 (&lt;strong&gt;idf&lt;/strong&gt;) 라고 하고,  $ idf = log(\frac {N} {df}) ​$ 로 정의해 줍니다. (log 는 계산량을 줄이기 위해 사용합니다.)&lt;/p&gt;

&lt;p&gt;이제 빈도 조절까지 완료했으므로, tf 와 idf를 결합한 &lt;strong&gt;tf-idf&lt;/strong&gt; 를 문헌 내 용어의 가중치로 사용할 것이며, 식은 $ {tf-idf}&lt;em&gt;{t,d}  = tf&lt;/em&gt;{t,d} * idf_t$ 입니다.&lt;/p&gt;

&lt;p&gt;결과적으로 tf-idf 값은&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;적은 수의 문헌에 용어 t가 많이 있으면 가장 높은 값을 가짐&lt;/li&gt;
  &lt;li&gt;문헌들에 그 용어가 적게 있으면 적은 값을 가짐&lt;/li&gt;
  &lt;li&gt;모든 문헌 안에 용어가 존재할 경우 가장 낮은 값을 가짐&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;으로 생각할 수 있겠습니다.&lt;/p&gt;

&lt;h3 id=&quot;63-점수-계산을-위한-벡터-공간-모델&quot;&gt;6.3 점수 계산을 위한 벡터 공간 모델&lt;/h3&gt;

&lt;p&gt;위에서는 문헌을 용어들의 집합으로 생각했습니다. 이번 절에서는 문헌을 &lt;strong&gt;벡터 공간&lt;/strong&gt; 안에 있는것으로 생각해 보겠습니다.&lt;/p&gt;

</description>
        <pubDate>Thu, 11 Apr 2019 13:50:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2019/04/11/tfidf/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2019/04/11/tfidf/</guid>
        
        <category>machine_learning</category>
        
        <category>search_engine</category>
        
        
      </item>
    
      <item>
        <title>[Sorting #6] Quick Sort</title>
        <description>&lt;h1 id=&quot;quick-sort&quot;&gt;Quick Sort&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;http://interactivepython.org/runestone/static/pythonds/index.html&quot;&gt;Problem Solving with Algorithms and Data Structures using Python&lt;/a&gt; 을 공부하고 정리한 내용입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;quick sort 는 추가적인 메모리 사용 없이 &lt;code class=&quot;highlighter-rouge&quot;&gt;Divide and Conquer&lt;/code&gt; 를 사용할 수 있습니다.&lt;br /&gt;&lt;strong&gt;pivot&lt;/strong&gt; 을 이용해 divide 될 지점을 찾아주는 것이 핵심입니다.&lt;/p&gt;

&lt;p&gt;그림으로 예를 들어 설명해보겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/firstsplit.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이 리스트에서 첫번째 pivot 을 54 라고 합시다.&lt;br /&gt;( pivot 을 정하는 방법은 여러가지가 있지만, 예제에서는 첫번째 원소를 pivot 으로 하는 방법을 선택하고 있습니다.)&lt;/p&gt;

&lt;p&gt;이제 이 pivot 을 기준으로 하고, 나머지 리스트 에 대해 &lt;strong&gt;leftmartk&lt;/strong&gt; 와 &lt;strong&gt;rightmark&lt;/strong&gt; 를 정합니다.&lt;br /&gt;leftmark 와 rightmark 는 서로의 방향으로 한 칸씩 이동을 하는데&lt;br /&gt;leftmark &amp;gt; pivot 이고 rightmark &amp;lt; pivot 인 시점에서 두 값을 swap 합니다.&lt;/p&gt;

&lt;p&gt;이런 과정을 거치면서 leftmark 와 rightmark 를 이동하다 보면 둘이 교차하는 지점을 찾을 수 있는데,&lt;br /&gt;그 지점에서 rightmark 의 값과 pivot 의 값을 swap 해 줍니다.&lt;br /&gt;( 아래 그림에서는 31과 54 를 swap 해 주어야 합니다. )&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/partitionA.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이렇게 한 pivot 에 대해 완료하고 나면 리스트를 분할할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/partitionB.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이미 정렬이 된 pivot 인 54 를 기준으로 앞과 뒤의 원소들로 리스트를 분할합니다.&lt;br /&gt;각 리스트에 대해 다시 quicksort 를 실행해 주면 정렬이 완료됩니다.&lt;/p&gt;

&lt;h3 id=&quot;구현하기&quot;&gt;구현하기&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;pivot , leftmark, rightmark 를 정해 한번의 quick sort 과정을 거치기&lt;/li&gt;
  &lt;li&gt;분할된 리스트에 대해 quicksort 하기&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;del&gt;quicksort 를 재귀로 계속 하면 좋을것 같은데, base case 가 무엇일지 잘 생각이 안나 일단은 구현한 대로 포스팅 합니다..ㅠ&lt;/del&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;quickSort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;quickSortHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;quickSortHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;splitpoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;quickSortHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;splitpoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;quickSortHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;splitpoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pivotvalue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pivotvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pivotvalue&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightmark&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;분석하기&quot;&gt;분석하기&lt;/h3&gt;

&lt;p&gt;길이가 $n$ 인 리스트에 대해, 파티션이 항상 리스트의 중간에 있다면 binary search 와 마찬가지로 $\log n$ 만큼의 시간이 소요됩니다.&lt;br /&gt;또한 분할지점을 찾기 위해 pivot 과 값을 비교하는 과정은 최대 $n$ 만큼 소요되므로 Quick Sort 는 $O(n\log n)$  인 알고리즘 입니다.   $n-1$ 개의 값을 피벗과 비교해야 합니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Merge Sort 와 실행시간은 비슷하지만, 추가적인 메모리를 필요로 하지 않는다는 장점이 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 파티션이 왼쪽이나 오른쪽으로 치우쳐 있는 경우에는 문제가 될 수 있습니다. &lt;br /&gt;예를 들어 파티션이 계속해서 맨 앞쪽에 나온다고 하면 의미없는 분할을 계속 해야 하기 때문입니다.&lt;br /&gt;이 경우 길이가 $n$ 인 리스트를 처음 분할 했을 때  $0$ , $n-1$  인 리스트로 분할이 되고 그 다음에는 $0$, $n-2$  인 리스트 로 분할이 됩니다.&lt;br /&gt;즉 worst case 의 실행시간은 $O(n^{2})$ 이 되어버립니다.&lt;/p&gt;

&lt;p&gt;위와 같은 worst case 는 항상 pivot 을 맨 앞의 원소로 할 때에 발생합니다.&lt;br /&gt;이를 해결하기 위해 pivot 을 결정하는 많은 방법들이 존재합니다.&lt;br /&gt;그 중 &lt;code class=&quot;highlighter-rouge&quot;&gt;median of three&lt;/code&gt; 라는 방법이 있는데, 리스트의 처음,중간,끝 값 중 중위수를 pivot 으로 사용하는 방법입니다.&lt;br /&gt;리스트가 어느 정도 정렬되어 있을 때 &lt;code class=&quot;highlighter-rouge&quot;&gt;median of three&lt;/code&gt; 를 사용하면 리스트가 거의 반으로 분할 되기 때문에 유용합니다.&lt;/p&gt;
</description>
        <pubDate>Thu, 29 Nov 2018 12:45:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2018/11/29/quicksort/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2018/11/29/quicksort/</guid>
        
        <category>algorithm</category>
        
        <category>sorting</category>
        
        
      </item>
    
      <item>
        <title>[Sorting #5] Merge Sort</title>
        <description>&lt;h1 id=&quot;merge-sort&quot;&gt;Merge Sort&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;http://interactivepython.org/runestone/static/pythonds/index.html&quot;&gt;Problem Solving with Algorithms and Data Structures using Python&lt;/a&gt; 을 공부하고 정리한 내용입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;sorting 알고리즘의 성능을 높이기 위해 &lt;code class=&quot;highlighter-rouge&quot;&gt;Dived and Conquer&lt;/code&gt; 전략을 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;Merge Sort 는 리스트를 재귀적으로 두개로 나누어 정렬 후 정렬된 부분들을 다시 합치는 방식입니다.&lt;br /&gt;base case는 merge 를 수행하는 부분이 되겠고, 그 조건은 리스트의 값이 하나 이하일 경우 입니다.&lt;/p&gt;

&lt;p&gt;그림으로 예를 들어보겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/mergesortA.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 그림은 Merge Sort 를 위해 리스트를 분할하는 과정을 나타냅니다.&lt;br /&gt;리스트의 원소가 하나 이하가 될 때 까지 계속 분할하는 것을 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt;이렇게 분할된 리스트는&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/mergesortB.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위와같이 다시 합치는 과정을 거치게 되는데, 이 때 합치는 과정은 정렬된 부분에서 가장 작은 값을 원래 리스트의 맨 앞으로 가져오는 형식으로 진행됩니다.&lt;/p&gt;

&lt;h3 id=&quot;구현하기&quot;&gt;구현하기&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;길이가 1 이하가 될 때 까지 입력리스트를 반으로 나누기 (Python 의 slicing 방법을 사용)&lt;/li&gt;
  &lt;li&gt;반으로 나눈 리스트에 대해 각각 mergerSort 하기&lt;/li&gt;
  &lt;li&gt;입력리스트, 왼쪽리스트, 오른쪽리스트 의 값을 비교하며 가장 작은 값부터 앞쪽에 넣어주기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mergeSort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Splitting {}'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;leftList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rightList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;mergeSort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mergeSort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;originIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Mergeing {}'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;실행결과를 보면, 재귀적으로 구현되었기 때문에 왼쪽리스트부터 base case 까지 나눈 후 merge 하고&lt;br /&gt;그 다음에 오른쪽리스트를 merge 하고 있는것을 확인할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mergeSort([54,26,93,17,77,31,44,55,20])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Splitting [54, 26, 93, 17, 77, 31, 44, 55, 20]
Splitting [54, 26, 93, 17]
Splitting [54, 26]
Splitting [54]
Splitting [26]
Mergeing [26, 54]
Splitting [93, 17]
Splitting [93]
Splitting [17]
Mergeing [17, 93]
Mergeing [17, 26, 54, 93]
Splitting [77, 31, 44, 55, 20]
Splitting [77, 31]
Splitting [77]
Splitting [31]
Mergeing [31, 77]
Splitting [44, 55, 20]
Splitting [44]
Splitting [55, 20]
Splitting [55]
Splitting [20]
Mergeing [20, 55]
Mergeing [20, 44, 55]
Mergeing [20, 31, 44, 55, 77]
Mergeing [17, 20, 26, 31, 44, 54, 55, 77, 93]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;분석하기&quot;&gt;분석하기&lt;/h3&gt;

&lt;p&gt;Merge Sort 는 크게 두 가지의 과정으로 나뉘므로, 각 과정에 대해 생각해 볼 필요가 있습니다.&lt;/p&gt;

&lt;p&gt;먼저 Split 의 과정을 생각해보면 Binary Search 와 같은 과정임을 알 수 있습니다.&lt;br /&gt;n개의 값을 반으로 나눠가는 과정을 생각해 보면,&lt;br /&gt;첫번째 과정을 거쳤을 때에는 $\frac {n}{2}$, 두번째는 $\frac {n}{4}$ , … , $k$ 번째에는 $\frac {n}{2^k}$ 개의 값이 남는 것을 알 수 있습니다.&lt;br /&gt;우리는 $\frac {n}{2^k}$ (맨 마지막으로 남은 원소의 수) 가 1인 경우까지 split 하는 것이기 때문에,  $\frac {n}{2^k} = 1$ 인 k 를 계산하면 됩니다. &lt;br /&gt;$k=\log n$ 이므로 반으로 나눠가는 과정의 실행 시간은 $O(\log n)$ 만큼이 걸리는 것을 알 수 있습니다.&lt;/p&gt;

&lt;p&gt;다음으로 Merge 의 과정은 각 값당 최대 n 번의 비교를 거쳐야 하기 때문에 $n$ 만큼의 시간이 걸립니다.&lt;/p&gt;

&lt;p&gt;그래서 Merge Sort 알고리즘은 $O(n\log n)$ 알고리즘 입니다.&lt;/p&gt;

&lt;h4 id=&quot;추가중&quot;&gt;추가중&lt;/h4&gt;

&lt;p&gt;그런데 slicing 방법의 실행시간은 무시해도 되는걸까 하는 의문이 생겼습니다. &lt;br /&gt;검색결과 slicing 은 $k$ 개의 slicing 을 할 때에 $O(k)$  만큼의 실행시간이 필요하다고 합니다.&lt;/p&gt;

&lt;p&gt;Merge Sort 의 이론적인 분석시간인 $O(n\log n)$ 을 맞춰주기 위해서는 이 slicing 방법을 제거해야 합니다.&lt;/p&gt;

</description>
        <pubDate>Thu, 29 Nov 2018 10:30:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2018/11/29/mergesort/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2018/11/29/mergesort/</guid>
        
        <category>algorithm</category>
        
        <category>sorting</category>
        
        
      </item>
    
      <item>
        <title>[Sorting #4] Shell Sort</title>
        <description>&lt;h1 id=&quot;shell-sort&quot;&gt;Shell Sort&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;http://interactivepython.org/runestone/static/pythonds/index.html&quot;&gt;Problem Solving with Algorithms and Data Structures using Python&lt;/a&gt; 을 공부하고 정리한 내용입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;shell sort 는 조금 생소할 수도 있는 소팅 방법입니다.&lt;br /&gt;insertion sort 방식을 조금 개선한 방법인데, insertion sort 가 두 연속된 sublist 로 나누어 정렬하는 방식이었다면&lt;br /&gt;shell sort 는 &lt;strong&gt;일정 gap 을 가진 sublist 로 나누어 정렬&lt;/strong&gt;하는 방식입니다.&lt;/p&gt;

&lt;p&gt;그림을 보면서 설명하겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/shellsortA.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이 그림은 gap 이 2 인 sublist 로 나누어 정렬한 예시입니다.&lt;br /&gt;그림처럼 일정한 gap 만큼 떨어진 값들을 하나의 sublist 로 묶어서 생각해 정렬하면 됩니다.&lt;/p&gt;

&lt;p&gt;각 sublist 를 정렬한 후 의 그림은 다음과 같습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/shellsortB.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;각 sublist 를 정렬했지만 전체 리스트에서 보았을 때 정렬이 완료되지 않은것을 알 수 있습니다.&lt;br /&gt;이때는 2를 반으로 나눈 1을 gap 으로 가지는 sublist 를 만들어 다시 정렬합니다.&lt;/p&gt;

&lt;h3 id=&quot;구현하기&quot;&gt;구현하기&lt;/h3&gt;

</description>
        <pubDate>Wed, 28 Nov 2018 15:00:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2018/11/28/shellsort/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2018/11/28/shellsort/</guid>
        
        <category>algorithm</category>
        
        <category>sorting</category>
        
        
      </item>
    
      <item>
        <title>[Sorting #3] Insertion Sort</title>
        <description>&lt;h1 id=&quot;insertion-sort&quot;&gt;Insertion Sort&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;http://interactivepython.org/runestone/static/pythonds/index.html&quot;&gt;Problem Solving with Algorithms and Data Structures using Python&lt;/a&gt; 을 공부하고 정리한 내용입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;insertion sort 는 한 리스트 내에서 &lt;strong&gt;두 부분으로 리스트&lt;/strong&gt;를 나누고, 뒤의 리스트의 값들을 하나씩 앞의 리스트에 정렬해서 넣는 방식입니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;결론부터 말하자면 &lt;code class=&quot;highlighter-rouge&quot;&gt;bubble sort&lt;/code&gt; 와 마찬가지로 성능이 좋지 않은 방법입니다.&lt;/p&gt;

&lt;p&gt;그림으로 예를 들어보겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/insertionsort.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;편의상 앞의 list 를 &lt;code class=&quot;highlighter-rouge&quot;&gt;sorted sublist&lt;/code&gt; , 뒤의 list 를 &lt;code class=&quot;highlighter-rouge&quot;&gt;unsorted sublist&lt;/code&gt; 라고 이름붙여 보겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;unsorted sublist&lt;/code&gt; 에 있는 값들을 차례로 &lt;code class=&quot;highlighter-rouge&quot;&gt;sorted sublist&lt;/code&gt; 로 가져오는데, 이 때 가져오는 값과 sorted sublist 의 값을 하나씩 비교하며 삽입합니다.&lt;/p&gt;

&lt;p&gt;위의 그림에서 31 을 sorted sublist 에 삽입하는 과정을 자세히 보겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://interactivepython.org/runestone/static/pythonds/_images/insertionpass.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;31 과 sorted sublist 의 값을 비교하며 31 보다 작은 값이 나올 때 까지 계속 shift 하는 것을 볼 수 있습니다.&lt;br /&gt;early stop rule 이 없다고 가정했을 때 한 원소를 삽입하기 위해 검사해야 하는 횟수는 최대 $n-1$ 번 입니다.&lt;/p&gt;

&lt;h3 id=&quot;구현하기&quot;&gt;구현하기&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;현재 값, 현재 인덱스 저장&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;sorted sublist&lt;/code&gt; 와 비교 후 shift&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;insertionSort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tempValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; tempValue : {}'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tempValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tempValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'shift {} -&amp;gt; {}'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tempIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tempValue&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alist&lt;/span&gt;

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

&lt;p&gt;shift 하면서 찾은 인덱스에 현재 값을 넣어주면 됩니다.&lt;/p&gt;

&lt;p&gt;위의 코드를 실행한 결과는 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;insertionSort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;54&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;93&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;77&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;55&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
tempValue : 54

tempValue : 26
shift 54 -&amp;gt; 26

tempValue : 93

tempValue : 17
shift 93 -&amp;gt; 17
shift 54 -&amp;gt; 93
shift 26 -&amp;gt; 54

tempValue : 77
shift 93 -&amp;gt; 77

tempValue : 31
shift 93 -&amp;gt; 31
shift 77 -&amp;gt; 93
shift 54 -&amp;gt; 77

tempValue : 44
shift 93 -&amp;gt; 44
shift 77 -&amp;gt; 93
shift 54 -&amp;gt; 77

tempValue : 55
shift 93 -&amp;gt; 55
shift 77 -&amp;gt; 93

tempValue : 20
shift 93 -&amp;gt; 20
shift 77 -&amp;gt; 93
shift 55 -&amp;gt; 77
shift 54 -&amp;gt; 55
shift 44 -&amp;gt; 54
shift 31 -&amp;gt; 44
shift 26 -&amp;gt; 31
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;분석하기&quot;&gt;분석하기&lt;/h3&gt;

&lt;p&gt;worst case 의 경우는 완전 역순으로 정렬된 리스트가 들어오는 경우입니다.&lt;br /&gt;이 경우 최대 $n-1$ 번의 비교를 하게 되고, bubble sort 와 마찬가지로 $\frac{1}{2}n^{2} + \frac{1}{2}n - n$ 의 연산을 하게 됩니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;따라서 $O(n^{2})$ 만큼 시간이 걸린다고 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt;bubble sort 와 차이점은 swap 이 아닌 shift 연산을 한다는 것입니다. &lt;br /&gt;shift 연산은 swap 보다 가벼운 연산이기 때문에 bubble sort 보다는 좀 더 나은 알고리즘으로 볼 수 있습니다.&lt;/p&gt;

</description>
        <pubDate>Tue, 27 Nov 2018 15:00:00 +0900</pubDate>
        <link>http://hyunkyung12.github.io/2018/11/27/insertionsort/</link>
        <guid isPermaLink="true">http://hyunkyung12.github.io/2018/11/27/insertionsort/</guid>
        
        <category>algorithm</category>
        
        <category>sorting</category>
        
        
      </item>
    
  </channel>
</rss>
