<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>the_huistle.log</title>
        <link>https://velog.io/</link>
        <description>hi</description>
        <lastBuildDate>Sat, 12 Jun 2021 08:10:51 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>the_huistle.log</title>
            <url>https://images.velog.io/images/the_huistle/profile/4ed82d87-0df9-4f5e-a35d-23794c8395b4/sehui2.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. the_huistle.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/the_huistle" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[RISE] 14주차 활동내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-14%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-14%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Sat, 12 Jun 2021 08:10:51 GMT</pubDate>
            <description><![CDATA[<h2 id="png-파일-업로드시-발생하는-오류-해결">.png 파일 업로드시 발생하는 오류 해결</h2>
<p></br></br></p>
<h3 id="png파일-업로드">.png파일 업로드</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/9e621673-b1a0-4d82-91f0-2c7c7dd3fcc8/%EC%BA%A1%EC%B2%981.PNG" alt=""></p>
<h3 id="filenotfounderror-발생">FileNotFoundError 발생</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/2017f5bd-0edf-4ea7-8b6f-34917bfc2d7d/%EC%BA%A1%EC%B2%983.PNG" alt=""></p>
<p><img src="https://images.velog.io/images/the_huistle/post/f4e06fbb-ae36-4667-90f9-0d9ea4eec957/%EC%BA%A1%EC%B2%984.PNG" alt=""></p>
<p></br></br></p>
<h3 id="uploadpy-수정">upload.py 수정</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/2b79b8be-89a0-4795-81e2-8997a786aedd/%EC%BA%A1%EC%B2%985.PNG" alt=""></p>
<pre><code class="language-python">from flask import Flask, render_template, request
from predict_food2 import predict_food

app = Flask(__name__)

@app.route(&#39;/upload&#39;)
def basic():
    return render_template(&quot;upload.html&quot;)

@app.route(&#39;/predict&#39;, methods=[&#39;POST&#39;])
def predict():
    f = request.files[&#39;file&#39;]
    Path = &quot;./&quot;
    f.save(Path+f.filename)
    result = predict_food(f.filename)

    # formatting the results as a JSON-serializable structure:
    output = {&#39;result&#39;: [result]}

    return output

if __name__ == &#39;__main__&#39;:
    app.run(debug=True)</code></pre>
<h3 id="수정-후-결과">수정 후 결과</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/88a8b212-55ac-4939-9b97-163d73b71b96/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 13주차 활동내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-13%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99</link>
            <guid>https://velog.io/@the_huistle/RISE-13%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99</guid>
            <pubDate>Mon, 31 May 2021 04:55:52 GMT</pubDate>
            <description><![CDATA[<h2 id="예측-결과-웹에-띄우기">예측 결과 웹에 띄우기</h2>
<p></br></br></p>
<p>모델을 불러와서 예측하는 코드를 다른 파일로 분리시켰다.</p>
<p><strong>predict_food.py</strong></p>
<pre><code class="language-python">from tensorflow import keras
from tensorflow.keras.preprocessing import image
from tensorflow.keras.optimizers import *
import tensorflow.keras.applications.resnet50 as resnet50

import os
os.environ[&#39;KMP_DUPLICATE_LIB_OK&#39;] = &#39;True&#39;



def predict_food(fname):
    img = image.load_img(fname, target_size=(224, 224))
    x = image.img_to_array(img)

    import numpy as np
    img = np.expand_dims(x, axis=0)
    img = resnet50.preprocess_input(img)

    model = keras.models.load_model(&quot;my_model_2.h5&quot;)
    optimizer = Adam(lr=0.00001)
    model.compile(loss=&#39;categorical_crossentropy&#39;,
                  optimizer=optimizer,
                  metrics=[&#39;accuracy&#39;])

    class_names = [&#39;Chinese&#39;, &#39;Japanese&#39;, &#39;Korean&#39;]
    classes = np.argmax(model.predict(img), axis=-1)
    result = [class_names[i] for i in classes]
    print(result)

    return result[0]

if __name__ == &#39;__main__&#39;:
    file_name = &#39;test_image3.jpg&#39;
    results = predict_food(file_name)
    print(results)</code></pre>
<p></br></br></p>
<p>실행 결과:
<img src="https://images.velog.io/images/the_huistle/post/b21ce947-1cc5-44fc-93b2-5d0e0615c040/%EC%BA%A1%EC%B2%981-1.png" alt=""></p>
<p></br></br></br></br>
<strong>upload.py</strong></p>
<pre><code class="language-python">from flask import Flask, render_template, request
from predict_food2 import predict_food

app = Flask(__name__)

@app.route(&#39;/upload&#39;)
def basic():
    return render_template(&quot;upload.html&quot;)

@app.route(&#39;/predict&#39;, methods=[&#39;POST&#39;])
def predict():
    f = request.files[&#39;file&#39;]
    # Path = &quot;./&quot;
    # f.save(Path+f.filename)
    result = predict_food(f.filename)

    # formatting the results as a JSON-serializable structure:
    output = {&#39;result&#39;: [result]}

    return output

# def post():
#     value = request.form[&#39;input&#39;]
#     return render_template(&#39;default.html&#39;, name=value)

if __name__ == &#39;__main__&#39;:
    app.run(debug=True)</code></pre>
<p></br></br></p>
<p>flask구동 후 실행 결과:</p>
<p><img src="https://images.velog.io/images/the_huistle/post/821ced09-e01a-4764-a1f5-962ee0330d86/%EC%BA%A1%EC%B2%983.PNG" alt=""></p>
<p><img src="https://images.velog.io/images/the_huistle/post/8e1a9ecd-bd88-48c2-8f77-170ffac22c1e/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
<p></br></br></br></p>
<h3 id="참고">[참고]</h3>
<p><a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=shino1025&amp;logNo=221361074139">[Flask 입문] 파일 업로드 하기</a></p>
<p><a href="https://thedatafrog.com/en/articles/deploy-deep-learning-model-flask-restful/">Deploy a Deep Learning Model with Flask RESTful</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 12주차 활동내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-12%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-12%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Mon, 24 May 2021 13:00:34 GMT</pubDate>
            <description><![CDATA[<h2 id="github-pages-사용하기">GitHub Pages 사용하기</h2>
</br>

<h3 id="1-해당-레포지토리---setting---pages">1. 해당 레포지토리 - Setting - Pages</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/c702e3c3-1f45-4b84-aba1-86d7fc05807a/%EC%BA%A1%EC%B2%983.PNG" alt=""></p>
<p></br></br></p>
<h3 id="2-source-none---main">2. Source: None -&gt; main</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/39d2e375-faa0-4d24-83db-17f8a78a41e2/%EC%BA%A1%EC%B2%984.PNG" alt=""></p>
<p><img src="https://images.velog.io/images/the_huistle/post/99aa8428-167c-402d-aff7-d3aba2cb5157/%EC%BA%A1%EC%B2%981.PNG" alt=""></p>
<p></br></br></p>
<p><strong>페이지 접속 결과:</strong>
<img src="https://images.velog.io/images/the_huistle/post/5888c708-7cfd-4fea-a83a-5b577e50cf7f/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
<p></br></br></br></br></p>
<h2 id="restful-api서버-만들기">RESTful API서버 만들기</h2>
</br>

<h3 id="1-가상환경에-pip-install-flask-restful로-설치">1. 가상환경에 pip install Flask-RESTful로 설치</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/d9fbef17-35b8-41d7-9523-5b1c250b0d8a/%EC%BA%A1%EC%B2%985.PNG" alt=""></p>
<h3 id="2-이름과-이메일주소를-담아서-호출하면-그값을-그대로-보여주는-기능-예제">2. 이름과 이메일주소를 담아서 호출하면 그값을 그대로 보여주는 기능 예제</h3>
<pre><code class="language-python">from flask import Flask
from flask_restful import Resource, Api
from flask_restful import reqparse

app = Flask(__name__)
api = Api(app)
class RegistUser(Resource):
    def post(self):
        # 파싱
        parser = reqparse.RequestParser()
        parser.add_argument(&#39;name&#39;, type=str)
        parser.add_argument(&#39;email&#39;, type=str)
        args = parser.parse_args()

        # 파싱한 데이터 변수에 저장
        name = args[&#39;name&#39;]
        email = args[&#39;email&#39;]


        return {&#39;name&#39;: name , &#39;email&#39; : email}

api.add_resource(RegistUser, &#39;/user&#39;)

if __name__ == &#39;__main__&#39;:
    app.run(debug=True)
</code></pre>
<p></br></br></br></br></p>
<h3 id="출처">[출처]</h3>
<p><a href="https://cholol.tistory.com/421">Flask(python) 사용해서 RESTful api서버 만들기</a>
<a href="https://www.slideshare.net/arload/flask-restful-api">Flask로 Restful API 서버 만들기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 11주차 활동내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-11%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-11%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Tue, 18 May 2021 08:31:38 GMT</pubDate>
            <description><![CDATA[<h3 id="모델-개선-결과">모델 개선 결과</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/4409c026-d185-41d5-b7c2-a3be38153286/%EC%BA%A1%EC%B2%981.PNG" alt=""></p>
</br>

<h3 id="flask에서-저장한-모델-불러와서-예측하기">Flask에서 저장한 모델 불러와서 예측하기</h3>
</br>

<p>colab에서 예측해본 결과:</p>
<p><img src="https://images.velog.io/images/the_huistle/post/ec682cbe-3732-445b-b814-ecdfdb632015/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
<p></br></br></p>
<p>colab 코드:</p>
<pre><code class="language-python">from google.colab import drive
drive.mount(&#39;/content/drive&#39;)

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.optimizers import *
import cv2

Path = &quot;./drive/MyDrive/&quot;
model = keras.models.load_model(Path+&quot;my_model_2.h5&quot;)

optimizer = Adam(lr=0.00001)
model.compile(loss=&#39;categorical_crossentropy&#39;,
              optimizer=optimizer,
              metrics=[&#39;accuracy&#39;])

test_data = Path+&quot;.jpg&quot;
class_names = [&#39;Chinese&#39;, &#39;Japanese&#39;, &#39;Korean&#39;]


img = cv2.imread(Path+&#39;test_image4.jpg&#39;)
img = cv2.resize(img,(224,224))
img = np.reshape(img,[1,224,224,3])

classes = np.argmax(model.predict(img), axis = -1)
print(classes)
names = [class_names[i] for i in classes]
print(names)</code></pre>
<p></br></br></p>
<p>flask 코드:</p>
<pre><code class="language-python">from flask import Flask, render_template, request
import numpy as np

from tensorflow import keras
from tensorflow.keras.optimizers import *
import cv2

app = Flask(__name__)

@app.route(&#39;/&#39;)
def basic():
    return render_template(&quot;upload.html&quot;)

@app.route(&#39;/predict&#39;, methods=[&#39;POST&#39;])
def predict():
    f = request.files[&#39;file&#39;]
    Path = &quot;./&quot;
    f.save(Path+f.filename)
    model = keras.models.load_model(Path + &quot;my_model_2.h5&quot;)
    optimizer = Adam(lr=0.00001)
    model.compile(loss=&#39;categorical_crossentropy&#39;,
                  optimizer=optimizer,
                  metrics=[&#39;accuracy&#39;])

    test_data = Path + &quot;.jpg&quot;
    class_names = [&#39;Chinese&#39;, &#39;Japanese&#39;, &#39;Korean&#39;]

    img = cv2.imread(Path + &#39;test_image4.jpg&#39;)
    img = cv2.resize(img, (224, 224))
    img = np.reshape(img, [1, 224, 224, 3])

    classes = np.argmax(model.predict(img), axis=-1)
    print(classes)
    names = [class_names[i] for i in classes]
    print(names)

def post():
    value = request.form[&#39;input&#39;]
    return render_template(&#39;default.html&#39;, name=value)

if __name__ == &#39;__main__&#39;:
    app.run(debug=True)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 10주차 활동내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-10%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-10%EC%A3%BC%EC%B0%A8-%ED%99%9C%EB%8F%99%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Sun, 09 May 2021 04:52:14 GMT</pubDate>
            <description><![CDATA[<h3 id="flask-웹-서버에서-저장한-모델-불러오기">Flask 웹 서버에서 저장한 모델 불러오기</h3>
<pre><code class="language-python">import flask
from flask import Flask, request, render_template
import numpy as np
from scipy import misc
from keras.models import load_model

app = Flask(__name__)

# 메인 페이지 라우팅
@app.route(&quot;/&quot;)
@app.route(&quot;/index&quot;)
def index():
    return flask.render_template(&#39;index.html&#39;)

# 데이터 예측 처리
@app.route(&quot;/predict&quot;, methods=[&#39;POST&#39;])
def make_predecion():
    if request.method == &#39;POST&#39;:
        # 업로드 파일 처리 분기
        file = request.files[&#39;image&#39;]
        if not file:
            return render_template(&#39;index.html&#39;, label=&quot;No Files&quot;)

        # 이미지 픽셀 정보 읽기
        # 알파 채널 값 제거 후 1차원 Reshape
        img = misc.imread(file)
        img = img[:, :, :3]
        img = img.reshape(1, -1)

        # 입력 받은 이미지 예측
        prediction = model. predict(img)

        label = str(np.squeeze(prediction))

        # 결과 리턴
        return render_template(&#39;index.html&#39;, label=label)

if __name__ == &#39;__main__&#39;:
    # 모델 로드
    model = load_model(&#39;my_model1.h5&#39;)
    app.run(host=&#39;0.0.0.0&#39;, port=8000, debug=True)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 9주차 수행내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-9%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-9%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Sun, 02 May 2021 12:04:18 GMT</pubDate>
            <description><![CDATA[<h3 id="1-flask-서버-구현을-위한-환경-설정">1. Flask 서버 구현을 위한 환경 설정</h3>
<h4 id="1-anaconda-가상환경-생성">1) anaconda 가상환경 생성</h4>
<p><img src="https://images.velog.io/images/the_huistle/post/c176a7d8-dbc8-4c9a-9685-e16215c15d9c/%EC%BA%A1%EC%B2%981.PNG" alt=""></p>
<p><img src="https://images.velog.io/images/the_huistle/post/47ae27ba-488e-4d91-b2f0-d5b7859b8cd8/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
<h4 id="2-pip-install-flask">2) pip install flask</h4>
<p><img src="https://images.velog.io/images/the_huistle/post/4f75fa16-6fed-4d7d-afb3-b082cdedc166/%EC%BA%A1%EC%B2%983.PNG" alt=""></p>
<p></br></br></br></p>
<h3 id="2-flask-예제-실행">2. Flask 예제 실행</h3>
<pre><code class="language-python">from flask import Flask, escape, request

app = Flask(__name__)

@app.route(&#39;/&#39;)
def hello():
    name = request.args.get(&quot;name&quot;, &quot;World&quot;)
    return f&#39;Hello, {escape(name)}!&#39;

if __name__ == &quot;__main__&quot;:
    app.run(host=&quot;0.0.0.0&quot;, port=5000)

</code></pre>
<p><img src="https://images.velog.io/images/the_huistle/post/355b44de-faec-4e16-b69e-49aacfea635c/%EC%BA%A1%EC%B2%985.PNG" alt=""></p>
<p><img src="https://images.velog.io/images/the_huistle/post/adc3e76f-a143-445d-8f42-04dd4b58b622/%EC%BA%A1%EC%B2%984.PNG" alt=""></p>
<p></br></br></br></p>
<h3 id="flask-웹서버-구현">Flask 웹서버 구현</h3>
<p>Flask를 활용하여 간단하게 웹 서버를 구축하고자 한다면 크게 다음과 같은 3가지가 필요하다.</p>
<ul>
<li><p>Flask 클래스의 인스턴스 생성</p>
</li>
<li><p>route() 데코레이터를 이용한 URL 처리 함수 지정</p>
</li>
<li><p>Flask 인스턴스에 호스트 주소, 포트 넘버를 지정한 후 run() 함수 호출</p>
</li>
</ul>
<p></br></br></p>
<h3 id="3-flask-파일-업로드-구현">3. Flask 파일 업로드 구현</h3>
<p>사용자가 이미지 파일을 올리기 위해 필요한 파일 업로드를 구현해보았다.
<code>upload.html</code></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;body&gt;
        &lt;form action = &quot;http://localhost:5000/fileUpload&quot; method = &quot;POST&quot;
            enctype = &quot;multipart/form-data&quot;&gt;
            &lt;input type = &quot;file&quot; name = &quot;file&quot; /&gt;
            &lt;input type = &quot;submit&quot;/&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p></br></br></p>
<p><code>fild_upload.py</code></p>
<pre><code class="language-python">from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
app = Flask(__name__)

# 업로드 HTML 렌더링
@app.route(&#39;/upload&#39;)
def render_file():
    return render_template(&#39;upload.html&#39;)

# 파일 업로드 처리
@app.route(&#39;/fileUpload&#39;, methods = [&#39;GET&#39;, &#39;POST&#39;])
def upload_file():
    if request.method == &#39;POST&#39;:
        f = request.files[&#39;file&#39;]
        # 저장할 경로 + 파일명
        f.save(secure_filename(f.filename))
        return &#39;uploads 디렉토리 -&gt; 파일 업로드 성공!&#39;

if __name__ == &#39;__main__&#39;:
    # 서버 실행
    app.run(debug = True)</code></pre>
<p><img src="https://images.velog.io/images/the_huistle/post/37818f6a-5066-4bee-87c0-b3327772fc76/%EC%BA%A1%EC%B2%986.PNG" alt=""></p>
<h3 id="참고">[참고]</h3>
<p><a href="https://haruhiism.tistory.com/82">Python과 Flask를 활용한 웹 서버 구축</a>
<a href="https://statssy.github.io/dev/2020/09/03/flask_upload/">[기초] Flask 파일 업로드 하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 7주차 수행내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-7%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-7%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Tue, 20 Apr 2021 11:14:41 GMT</pubDate>
            <description><![CDATA[<p>저번 학습 결과를 통해 overfitting이 발생하는 것을 확인하였고, 어떻게 개선하면 좋을까 고민해보았다. 그리고 내가 사용한 함수나 방법들에 대해 다시 제대로 알아보았다.</p>
<p>대용량의 ImageNet데이터를 이용하여 사전학습된 분류모델 ResNet50을 불러와서 사용하였는데, 이러한 학습방법을 전이학습(Transfer Learning)이라고 한다.</p>
<p></br></br></p>
<h3 id="전이학습-이란">전이학습 이란?</h3>
<ul>
<li>전이학습이란 딥러닝을 feature extractor로만 사용하고 그렇게 추출한 특징을 가지고 다른 모델을 학습하는 것</li>
<li>기존의 만들어진 모델을 사용하여 새로운 모델을 만들시 학습을 빠르게 하며, 예측을 더 높이는 방법</li>
<li>일반적으로 VGG,ResNet,gooGleNet등 이미 이러한 사전에 학습이 완료된 모델(Pre-Training Model)을 가지고 우리가 원하는 학습에 미세 조정 즉, 작은변화를 이용하여 학습시키는 방법이 Transfer Learning이다. </li>
<li>이미학습된 weight들을 transfer(전송)하여 자신의 model에 맞게 학습을 시키는 방법</li>
<li>신경망의 이러한 재학습 과정을 세부 조정(fine-tuning)이라 부름</li>
<li>실제로 CNN을 구축하는 경우 대부분 처음부터 (random initialization) 학습하지는 않는다. </li>
<li>ImageNet과 같은 대형 데이터셋을 사용해서 pretrain된 ConvNet을 사용한다. </li>
</ul>
<p></br></br></p>
<h3 id="전이학습-방법">전이학습 방법</h3>
<ol>
<li>Feature extraction</li>
<li>pre-trained model을 모델 구조를 이용</li>
<li>다른 레이어를 고정시키고 일부분 layer를 조정</li>
</ol>
<h3 id="keras-사전학습된-모델-종류">keras 사전학습된 모델 종류</h3>
<ol>
<li>VGG</li>
<li>ResNet</li>
<li>MobileNet</li>
</ol>
<p></br></br></p>
<h3 id="정확도-높이는-방법">정확도 높이는 방법</h3>
<ol>
<li>가중치 초기화 방법 바꾸기</li>
<li>learning rate/batch size를 조절하기</li>
</ol>
<p></br></br></p>
<h3 id="참고">[참고]</h3>
<p><a href="https://m.blog.naver.com/nanotoly/221497821754">딥러닝 정확도 높이기</a>
<a href="https://www.tensorflow.org/tutorials/images/transfer_learning?hl=ko">사전 학습된 ConvNet을 이용한 전이 학습
</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 6주차 수행내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-6%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-6%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Wed, 14 Apr 2021 11:16:25 GMT</pubDate>
            <description><![CDATA[<h3 id="1-구글-드라이브-마운트">1. 구글 드라이브 마운트</h3>
<pre><code class="language-python">from google.colab import drive
drive.mount(&#39;/content/drive&#39;)</code></pre>
</br>

<h3 id="2-이미지-데이터-로드">2. 이미지 데이터 로드</h3>
<p>데이터 불러와서 히스토그램 그리는 부분까지는 저번에 한 과정과 같다. </p>
<pre><code class="language-python">import os
import shutil
import glob
import cv2
import numpy as np
import pandas as pd

import tensorflow as tf
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.applications import *
from tensorflow.keras.callbacks import *
from tensorflow.keras.initializers import *
from tensorflow.keras.preprocessing.image import ImageDataGenerator

Path = &quot;./drive/MyDrive/Colab Notebooks/datasets/Dishes/&quot;
cuisines = [&#39;Chinese&#39;, &#39;Japanese&#39;, &#39;Korean&#39;]

images = []
label = []
for dish in cuisines:
    #print(os.path.exists(&#39;/content/drive&#39;))
    food = os.listdir(Path+dish)
    for i in food:
        images.append(dish+&#39;_&#39;+i)
        label.append(dish)

df = pd.DataFrame(list(zip(images, label)), columns=[&#39;Image&#39;, &#39;Cuisine&#39;])
df.Cuisine.unique()

df.Cuisine.hist()</code></pre>
</br>

<p><strong>결과:</strong>
<img src="https://images.velog.io/images/the_huistle/post/5019ec8e-ac28-422b-94f0-351529f00112/%EC%BA%A1%EC%B2%9810.PNG" alt=""></p>
<p></br></br></p>
<h3 id="3-훈련-데이터-검증-데이터-생성">3. 훈련 데이터, 검증 데이터 생성</h3>
<pre><code class="language-python"># Augment data
batch_size = 64
train_input_shape = (224, 224, 3)
n_classes = 3

train_datagen = ImageDataGenerator(validation_split=0.2,
                                   rescale=1./255.,
                                   rotation_range=15,
                                   shear_range=0.1,
                                   zoom_range=0.5
                                  )

train_generator = train_datagen.flow_from_directory(directory=Path,
                                                    class_mode=&#39;categorical&#39;,
                                                    target_size=train_input_shape[0:2],
                                                    batch_size=batch_size,
                                                    subset=&quot;training&quot;,
                                                    shuffle=True,
                                                    classes=df.Cuisine.unique().tolist()
                                                   )

valid_generator = train_datagen.flow_from_directory(directory=Path,
                                                    class_mode=&#39;categorical&#39;,
                                                    target_size=train_input_shape[0:2],
                                                    batch_size=batch_size,
                                                    subset=&quot;validation&quot;,
                                                    shuffle=True,
                                                    classes=df.Cuisine.unique().tolist()
                                                   )

STEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size
STEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size</code></pre>
<blockquote>
<p><strong>ImageDataGenerator</strong>를 사용할 경우 여러 함수를 통해 이미지 로드 및 이미지 증식을 할 수 있다. 파라미터 설정을 통해 이미지 증식 방식에 대해 정해줄 수 있다. </br>
<strong>flow_from_directory</strong>는 이미지를 불러올 때 폴더명에 맞춰 자동으로 labelling을 해준다. flow_from_directory() 함수의 주요 파라미터는 다음과 같다.</br>
첫번재 파라미터 : 이미지 경로.
target_size : 패치 이미지 크기. 폴더에 있는 원본 이미지 크기가 다르더라도 target_size에 지정된 크기로 자동 조절됨.
batch_size : 배치 크기.
class_mode : 분류 방식.
categorical : 2D one-hot 부호화된 라벨이 반환됨.
binary : 1D 이진 라벨이 반환됨.
sparse : 1D 정수 라벨이 반환됨.
None : 라벨이 반환되지 않는다.</p>
</blockquote>
<p>본 실습에서는 이미지 크기를 224 x 224로 하였으니 target_size도 (224, 224)로 설정하였다. 다중 클래스 문제이므로 class_mode는 ‘categorical’로 지정하였다. 그리고 제네레이터는 훈련용과 검증용으로 두 개를 만들었다.</p>
<p></br></br></p>
<h3 id="4-imagenet에-사전-훈련된-모델-resnet-50-사용하기">4. imagenet에 사전 훈련된 모델 ResNet 50 사용하기</h3>
<pre><code class="language-python">base_model = ResNet50(weights=&#39;imagenet&#39;, include_top=False, input_shape=train_input_shape)

for layer in base_model.layers:
    layer.trainable = True

X = base_model.output
X = Flatten()(X)

X = Dense(512, kernel_initializer=&#39;he_uniform&#39;)(X)
X = Dropout(0.4)(X)
X = BatchNormalization()(X)
X = Activation(&#39;relu&#39;)(X)

X = Dense(128, kernel_initializer=&#39;he_uniform&#39;)(X)
X = Dropout(0.4)(X)
X = BatchNormalization()(X)
X = Activation(&#39;relu&#39;)(X)

X = Dense(16, kernel_initializer=&#39;he_uniform&#39;)(X)
X = Dropout(0.4)(X)
X = BatchNormalization()(X)
X = Activation(&#39;relu&#39;)(X)

output = Dense(n_classes, activation=&#39;softmax&#39;)(X)

model = Model(inputs=base_model.input, outputs=output)</code></pre>
</br>

<p>Adam을 이용하여 최적화한다.</p>
<pre><code class="language-python">optimizer = Adam(lr=0.00001)
model.compile(loss=&#39;categorical_crossentropy&#39;,
              optimizer=optimizer, 
              metrics=[&#39;accuracy&#39;])</code></pre>
<p></br></br></p>
<h3 id="5-모델-훈련시키기">5. 모델 훈련시키기</h3>
<p>가중치 고정..
한 번 더 훈련시킴.</p>
<pre><code class="language-python">n_epoch = 50
early_stop = EarlyStopping(monitor=&#39;val_loss&#39;, patience=20, verbose=1, 
                           mode=&#39;auto&#39;, restore_best_weights=True)
reduce_lr = ReduceLROnPlateau(monitor=&#39;val_loss&#39;, factor=0.1, patience=5, 
                              verbose=1, mode=&#39;auto&#39;)


# Train the model - all layers
history1 = model.fit_generator(generator=train_generator, steps_per_epoch=STEP_SIZE_TRAIN,
                              validation_data=valid_generator, validation_steps=STEP_SIZE_VALID,
                              epochs=n_epoch,
                              shuffle=True,
                              verbose=1,
                              callbacks=[reduce_lr],
                              use_multiprocessing=False,
                              workers=4
                             )

# Freeze core ResNet layers and train again 
for layer in model.layers[-6:]:
   layer.trainable = False

for layer in model.layers:
    layer.trainable = True

optimizer = Adam(lr=0.00001)

model.compile(loss=&#39;categorical_crossentropy&#39;,
              optimizer=optimizer, 
              metrics=[&#39;accuracy&#39;])</code></pre>
<p><strong>결과:</strong>
<img src="https://images.velog.io/images/the_huistle/post/f70e3924-7562-47a3-b793-fbb4aa28013c/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
<pre><code class="language-python">n_epoch = 50
history2 = model.fit_generator(generator=train_generator, steps_per_epoch=STEP_SIZE_TRAIN,
                              validation_data=valid_generator, validation_steps=STEP_SIZE_VALID,
                              epochs=n_epoch,
                              shuffle=True,
                              verbose=1,
                              callbacks=[reduce_lr, early_stop],
                              use_multiprocessing=False,
                              workers=4                             
                              )</code></pre>
<p><strong>결과:</strong>
<img src="https://images.velog.io/images/the_huistle/post/0514f2cd-fa0f-4a82-b515-9d9a81b00786/%EC%BA%A1%EC%B2%983.PNG" alt=""></p>
<p></br></br></p>
<pre><code class="language-python"># Merge history1 and history2
history = {}
history[&#39;loss&#39;] = history1.history[&#39;loss&#39;] + history2.history[&#39;loss&#39;]
history[&#39;acc&#39;] = history1.history[&#39;accuracy&#39;] + history2.history[&#39;accuracy&#39;]
history[&#39;val_loss&#39;] = history1.history[&#39;val_loss&#39;] + history2.history[&#39;val_loss&#39;]
history[&#39;val_acc&#39;] = history1.history[&#39;val_accuracy&#39;] + history2.history[&#39;val_accuracy&#39;]
history[&#39;lr&#39;] = history1.history[&#39;lr&#39;] + history2.history[&#39;lr&#39;]</code></pre>
<p></br></br></p>
<h3 id="6-훈련-그래프-그리기">6. 훈련 그래프 그리기</h3>
<pre><code class="language-python"># Plot the training graph
import matplotlib.pyplot as plt
def plot_training(history):
    acc = history[&#39;acc&#39;]
    val_acc = history[&#39;val_acc&#39;]
    loss = history[&#39;loss&#39;]
    val_loss = history[&#39;val_loss&#39;]
    epochs = range(len(acc))

    fig, axes = plt.subplots(1, 2, figsize=(15,5))

    axes[0].plot(epochs, acc, &#39;r-&#39;, label=&#39;Training Accuracy&#39;)
    axes[0].plot(epochs, val_acc, &#39;b--&#39;, label=&#39;Validation Accuracy&#39;)
    axes[0].set_title(&#39;Training and Validation Accuracy&#39;)
    axes[0].legend(loc=&#39;best&#39;)

    axes[1].plot(epochs, loss, &#39;r-&#39;, label=&#39;Training Loss&#39;)
    axes[1].plot(epochs, val_loss, &#39;b--&#39;, label=&#39;Validation Loss&#39;)
    axes[1].set_title(&#39;Training and Validation Loss&#39;)
    axes[1].legend(loc=&#39;best&#39;)

    plt.show()

plot_training(history)</code></pre>
<p><img src="https://images.velog.io/images/the_huistle/post/26a88815-898f-4277-9d12-cbeb9f3c9864/%EC%BA%A1%EC%B2%985.PNG" alt=""></p>
<p></br></br></p>
<h3 id="7-훈련시킨-모델로-예측하기">7. 훈련시킨 모델로 예측하기</h3>
<pre><code class="language-python"># Prediction accuracy on train data
score = model.evaluate_generator(train_generator)
print(&quot;Prediction accuracy on train data =&quot;, score[1])

# Prediction accuracy on CV data
score = model.evaluate_generator(valid_generator)
print(&quot;Prediction accuracy on CV data =&quot;, score[1])</code></pre>
<p><img src="https://images.velog.io/images/the_huistle/post/31698acb-8cc5-405a-9e53-327f3d4904c2/%EC%BA%A1%EC%B2%9813.PNG" alt=""></p>
</br>

<p><strong>Confusion Matrix 그리기</strong></p>
<pre><code class="language-python">from sklearn.metrics import *
import seaborn as sns

tick_labels = df.Cuisine.unique().tolist()

def showClassficationReport_Generator(model, valid_generator, STEP_SIZE_VALID):
    # Loop on each generator batch and predict
    y_pred, y_true = [], []
    for i in range(STEP_SIZE_VALID):
        (X,y) = next(valid_generator)
        y_pred.append(model.predict(X))
        y_true.append(y)

    # Create a flat list for y_true and y_pred
    y_pred = [subresult for result in y_pred for subresult in result]
    y_true = [subresult for result in y_true for subresult in result]

    # Update Truth vector based on argmax
    y_true = np.argmax(y_true, axis=1)
    y_true = np.asarray(y_true).ravel()

    # Update Prediction vector based on argmax
    y_pred = np.argmax(y_pred, axis=1)
    y_pred = np.asarray(y_pred).ravel()

    # Confusion Matrix
    fig, ax = plt.subplots(figsize=(10,10))
    conf_matrix = confusion_matrix(y_true, y_pred, labels=np.arange(n_classes))
    conf_matrix = conf_matrix/np.sum(conf_matrix, axis=1)
    sns.heatmap(conf_matrix, annot=True, fmt=&quot;.2f&quot;, square=True, cbar=False, 
                cmap=plt.cm.jet, xticklabels=tick_labels, yticklabels=tick_labels,
                ax=ax)
    ax.set_ylabel(&#39;Actual&#39;)
    ax.set_xlabel(&#39;Predicted&#39;)
    ax.set_title(&#39;Confusion Matrix&#39;)
    plt.show()

    print(&#39;Classification Report:&#39;)
    print(classification_report(y_true, y_pred, labels=np.arange(n_classes), target_names=df.Cuisine.unique().tolist()))

showClassficationReport_Generator(model, valid_generator, STEP_SIZE_VALID)</code></pre>
<p><img src="https://images.velog.io/images/the_huistle/post/fca6bbe3-b3a7-4667-8bed-e51a0f917479/%EC%BA%A1%EC%B2%989.PNG" alt=""></p>
<p><img src="https://images.velog.io/images/the_huistle/post/71fa4c33-ee14-424d-aa64-7f086b0c278c/%EC%BA%A1%EC%B2%988.PNG" alt=""></p>
<p></br></br></p>
<h3 id="resnet-50">[ResNet 50]</h3>
<p>ResNet-50은 50개 계층으로 구성된 컨벌루션 신경망이다. ImageNet 데이터베이스의 1백만 개가 넘는 영상에 대해 훈련된 신경망의 사전 훈련된 버전을 불러올 수 있습니다. 사전 훈련된 신경망은 영상을 키보드, 마우스, 연필, 각종 동물 등 1,000가지 사물 범주로 분류할 수 있다. 그 결과 이 신경망은 다양한 영상을 대표하는 다양한 특징을 학습했고 신경망의 영상 입력 크기는 224×224이다.</p>
<p></br></br></p>
<h3 id="분류-모델-성능-평가-지표">[분류 모델 성능 평가 지표]</h3>
</br>

<ul>
<li>Confusion Matrix</li>
</ul>
<p><img src="https://images.velog.io/images/the_huistle/post/9d24302f-59cf-4181-a560-b3ececde613c/%EC%BA%A1%EC%B2%9811.PNG" alt=""></p>
<p><strong>True Positive (TP)</strong> : 정답은 True이고, 분류 결과도 True인 것 (정답)
<strong>False Positive (FP)</strong>: 정답은 False이고, 분류 결과는 True인 것 (오답)
<strong>False Negative (FN)</strong>: 정답은 True이고, 분류 결과는 False인 것 (오답)
<strong>True Negative (TN)</strong>: 정답은 False이고, 분류 결과도 False인 것 (정답)</p>
</br>

<p><img src="https://images.velog.io/images/the_huistle/post/e9c33825-02ee-4419-a825-1f9f90235b85/%EC%BA%A1%EC%B2%9812.PNG" alt=""></p>
<ul>
<li><p>Precision(정밀도)
모델이 True라고 한 것 중에 실제 정답이 True인 것 (모델의 관점)</p>
</li>
<li><p>Recall(재현율)
실제 정답이 True인 것 중에 모델이 True라고 한 것 (데이터의 관점)</p>
</li>
<li><p>F1 Score
Precision과 Recall의 조화평균</p>
</li>
<li><p>Accuracy(정확도)
실제 True를 모델이 True라고 예측한것 + 실제 False를 모델이 False라고 예측한 것의 비율</p>
</li>
</ul>
<p></br></br></p>
<h3 id="참고">[참고]</h3>
<p><a href="https://minimin2.tistory.com/128">[딥러닝] 분류 모델의 성능평가 방법</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 5주차 수행내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-5%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-5%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Thu, 08 Apr 2021 11:31:17 GMT</pubDate>
            <description><![CDATA[<h2 id="데이터-수집-및-전처리-2">데이터 수집 및 전처리 2</h2>
<p></br></br></br></p>
<h3 id="1-구글-이미지-크롤링하기">1. 구글 이미지 크롤링하기</h3>
<p>jupyter notebook에서 BeautifulSoup과 selenium의 크롬 웹드라이버를 사용하여 구글에 음식 키워드로 검색하였을 때 나오는 음식이미지들을 추가로 300개씩 저장하였다. 그리고 관련이 없는 이미지를 직접 제거해준다.
</br></p>
<pre><code class="language-python">import urllib.request
from urllib.request import urlopen
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.common import exceptions

search_name = [&quot;된장찌개&quot;, &quot;명란젓&quot;, 
               &quot;당고&quot;, &quot;오코노미야끼&quot;, &quot;우메보시&quot;, &quot;스키야키&quot;,
               &quot;훠궈&quot;, &quot;동파육&quot;, &quot;월병&quot;, &quot;마파두부&quot;, &quot;쟈오즈&quot;, &quot;빠오즈&quot;, &quot;만터우&quot;, &quot;홍샤오로우&quot;, &quot;베이징카오야&quot;]
count = 200


driver = webdriver.Chrome(r&quot;C:\Users\seenw\Downloads\chromedriver_win32\chromedriver.exe&quot;)

img_count = len(driver.find_elements_by_tag_name(&quot;img&quot;))
driver.implicitly_wait(2)

for j in range(len(search_name)):
    url = &quot;https://www.google.com/search?q=&quot; + str(search_name[j]) + &quot;&amp;hl=ko&amp;tbm=isch&quot;
    driver.get(url)
    folder = &quot;C:/Users/seenw/OneDrive - inu.ac.kr/2021_4학년1학기/RISE/4주차/archive/Dishes/추가하기/&quot; +search_name[j]+ &quot;/&quot;
    for i in range(count):
        img = driver.find_elements_by_tag_name(&quot;img&quot;)[i]
        img.screenshot(folder + str(3000*j+i)+ &quot;.png&quot;)


driver.close()</code></pre>
<p></br></br></p>
<p><strong>이미지 저장한 폴더들:</strong>
<img src="https://images.velog.io/images/the_huistle/post/98e82a5b-fc69-4fa1-926d-da505f60ac1d/%EC%BA%A1%EC%B2%981.PNG" alt=""></p>
</br>

<p><strong>크롤링 과정:</strong>
<img src="https://images.velog.io/images/the_huistle/post/b5f36467-1201-4f34-bdca-1bf57bf311d1/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
<p></br></br></br></br></p>
<h3 id="2-구글-클라우드에-업데이트">2. 구글 클라우드에 업데이트</h3>
<p><img src="https://images.velog.io/images/the_huistle/post/eeda83c3-498b-46c3-a02d-f3e3c56b4b6d/%EC%BA%A1%EC%B2%983.PNG" alt=""></p>
<p></br></br></br></br></p>
<h3 id="3-데이터-확인-및-전처리">3. 데이터 확인 및 전처리</h3>
<p>지난 번에 사용한 코드를 이용하여 데이터가 추가된 것을 확인하고 ImageDataGenerator를 이용하여 데이터 전처리까지 해준다.
<strong>결과1:</strong>
<img src="https://images.velog.io/images/the_huistle/post/d6f46a83-1aeb-4cdb-a778-c9c133f87809/%EC%BA%A1%EC%B2%984.PNG" alt="">
<strong>결과2:</strong>
<img src="https://images.velog.io/images/the_huistle/post/f9057d2c-a258-451f-89bf-c62d24f3a3b9/%EC%BA%A1%EC%B2%985.PNG" alt=""></p>
<p></br></br></br></br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 4주차 수행내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-4%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@the_huistle/RISE-4%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Thu, 01 Apr 2021 07:08:39 GMT</pubDate>
            <description><![CDATA[<h2 id="데이터-수집-및-전처리1">데이터 수집 및 전처리1</h2>
</br>

<h4 id="주제-한국-중국-일본의-전통-음식-분류하기">주제: 한국, 중국, 일본의 전통 음식 분류하기</h4>
<ul>
<li>kaggle 데이터 <a href="https://www.kaggle.com/abhijeetbhilare/world-cuisines">&#39;Traditional Food around the world&#39;</a> 활용</li>
<li>추가로 구글에서 이미지 데이터 수집할 예정이다.</li>
</ul>
<blockquote>
<p>주제 선정 이유: 최근 음식, 의복, 풍속 등 우리 문화에 대해 분쟁이 많은데 인정할건 인정하고 서로의 문화를 존중하는 사회가 되었으면 좋겠다고 생각했다. 그래서 우리 나라의 전통 음식뿐 아니라 주변 국가인 중국과 일본의 전통 음식에 대해서도 제대로 파악하며 훈련시킬 데이터셋을 확인할 예정이다.</p>
</blockquote>
<p></br></br></br></p>
<h4 id="0-데이터-직접-확인-및-제거">0. 데이터 직접 확인 및 제거</h4>
<p>kaggle의 원본 데이터셋에는 미국, 인도, 유럽의 음식 이미지 훈련 데이터도 있지만 이번 프로젝트에서는 제외시켰다. 그리고 음식과 관련이 없거나, 음식을 만드는 과정의 하나인 이미지 들을 직접 확인하며 제거하였다.
<img src="https://images.velog.io/images/the_huistle/post/2798a33b-1d6e-4a5c-a117-55af99274070/%EC%BA%A1%EC%B2%986.PNG" alt=""></p>
<p>아래의 음식 종류들은 전통 음식의 의미를 뚜렷이 하기 위해 직접 확인하면서 적어보았다.</p>
<p><strong>한국:</strong> 김밥, 족발, 국밥, 보쌈, 불고기, 잡채, 치맥(치킨과 맥주), 곱창전골, 곱창, 구절판, 양념치킨, 골뱅이 소면, 닭갈비, 갈비, 비빔밥, 전, 감자탕, 추어탕, 삼겹살, 파전, 해물파전, 물냉면, 비빔냉면, 선지해장국, 등뼈해장국, 짜장면, 김치(배추김치, 깍두기, 동치미, 콩국수, 식혜, 낚지볶음, 설렁탕, 뻥튀기, 소떡소떡, 떡볶이, 쌈, 삼계탕, 순두부찌개, 간장게장, 순대, 숙대국밥, </p>
<p>데이터 추가 필요: 구절판, 된장찌개, 명란젓</p>
</br>

<p><strong>일본:</strong> 메론빵, 초코소라빵, 미소된장국, 오코노미야끼, 오니기리, 낫또, 라멘, 스시, 샤브샤브, 메밀소바, 와사비, 타코야끼, 타마고야끼(계란말이), 텐동, 새우튀김, 두부, 야끼소바, 돈코츠(돈가스), 유부초밥, 단팥빵, 꼬치, 장어, 한라봉, 우동 등</p>
<p>데이터 추가 필요: 우동, 다른 종류 음식
데이터 삭제 필요: 명란젓</p>
</br>

<p><strong>중국:</strong> 차슈, 꽃빵, 차단(장조림), 완자, 탄탄면, 짜장면, 대나무 잎밥, 만두, 피단 등</p>
<p></br></br></br></p>
<h4 id="1-데이터-구글-클라우드에-업로드">1. 데이터 구글 클라우드에 업로드</h4>
<p><img src="https://images.velog.io/images/the_huistle/post/fb3f25c9-a2a9-4966-94fd-5373b4d94a67/%EC%BA%A1%EC%B2%982.PNG" alt=""></p>
<p></br></br></br></p>
<h4 id="2-colab에서-데이터-불러오기">2. Colab에서 데이터 불러오기</h4>
<blockquote>
<p><strong>필수!!</strong> colab에서 구글드라이브 마운트 해주기
<img src="https://images.velog.io/images/the_huistle/post/6773fdbd-008e-421c-81b9-268bf86a3b76/%EC%BA%A1%EC%B2%984.PNG" alt=""></p>
</blockquote>
<pre><code class="language-python">import os
import shutil
import glob
import cv2
import numpy as np
import pandas as pd

import tensorflow as tf
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.applications import *
from tensorflow.keras.callbacks import *
from tensorflow.keras.initializers import *
from tensorflow.keras.preprocessing.image import ImageDataGenerator

Path = &quot;./drive/MyDrive/Colab Notebooks/datasets/Dishes/&quot;
cuisines = [&#39;Chinese&#39;, &#39;Japanese&#39;, &#39;Korean&#39;]

images = []
label = []
for dish in cuisines:
    #print(os.path.exists(&#39;/content/drive&#39;))
    food = os.listdir(Path+dish)
    for i in food:
        images.append(dish+&#39;_&#39;+i)
        label.append(dish)

df = pd.DataFrame(list(zip(images, label)), columns=[&#39;Image&#39;, &#39;Cuisine&#39;])
df.Cuisine.unique()</code></pre>
<p>출력: <code>array([&#39;Chinese&#39;, &#39;Japanese&#39;, &#39;Korean&#39;], dtype=object)</code></p>
<p></br></br></p>
<pre><code class="language-python">df.Cuisine.hist()</code></pre>
<p>출력:
<img src="https://images.velog.io/images/the_huistle/post/574d25fa-38f8-4050-9958-c9b8b8c1ca88/%EC%BA%A1%EC%B2%985.PNG" alt=""></p>
<p>데이터 증강시키기</p>
<pre><code class="language-python"># Augment data
batch_size = 64
train_input_shape = (224, 224, 3)
n_classes = 3

train_datagen = ImageDataGenerator(validation_split=0.2,
                                   rescale=1./255.,
                                   rotation_range=15,
                                   #width_shift_range=0.5,
                                   #height_shift_range=0.5,
                                   shear_range=0.1,
                                   zoom_range=0.5,
                                   #horizontal_flip=True,
                                   #vertical_flip=True,
                                  )

train_generator = train_datagen.flow_from_directory(directory=Path,
                                                    class_mode=&#39;categorical&#39;,
                                                    target_size=train_input_shape[0:2],
                                                    batch_size=batch_size,
                                                    subset=&quot;training&quot;,
                                                    shuffle=True,
                                                    classes=df.Cuisine.unique().tolist()
                                                   )

valid_generator = train_datagen.flow_from_directory(directory=Path,
                                                    class_mode=&#39;categorical&#39;,
                                                    target_size=train_input_shape[0:2],
                                                    batch_size=batch_size,
                                                    subset=&quot;validation&quot;,
                                                    shuffle=True,
                                                    classes=df.Cuisine.unique().tolist()
                                                   )

STEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size
STEP_SIZE_VALID = valid_generator.n//valid_generator.batch_size
print(&quot;Total number of batches =&quot;, STEP_SIZE_TRAIN, &quot;and&quot;, STEP_SIZE_VALID)</code></pre>
</br>

<p>출력: 
<code>Found 5981 images belonging to 3 classes.</code>
<code>Found 1495 images belonging to 3 classes.</code>
<code>Total number of batches = 93 and 23</code></p>
<p></br></br></br></p>
<h3 id="참고">[참고]</h3>
<p><a href="https://www.kaggle.com/abhijeetbhilare/food-classification-using-resnet">Food Classification using Resnet</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 3주차 수행내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-3%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-3%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Thu, 25 Mar 2021 07:03:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>CNN 실습 예제 따라하기</p>
</blockquote>
<ol>
<li>MNIST 이미지 분류</li>
<li>개, 고양이 이미지 분류 (generator사용)</li>
</ol>
<p></br></br></p>
<h2 id="실습1-mnist-이미지-분류">실습1. MNIST 이미지 분류</h2>
</br>

<h3 id="1-1-간단한-컨브넷-만들기">1-1. 간단한 컨브넷 만들기</h3>
<ul>
<li>ConvNet은 (image_height, image_width, image_channels) 크기의 입력텐서를 사용한다.</li>
<li>이 예제에서 MNIST 이미지 포맷인 (28,28,1)크기의 입력을 처리하도록 ConvNet을 설정해야 하므로 첫 번째 층의 매개변수로 input_shpe(28,28,1)을 전달한다.</li>
<li>Conv2D와 MaxPooling2D층의 출력은 (height, width, channels) 크기의 3D텐서이다. 높이(height)와 너비(width)는 네트워크가 깊어질수록 작아지는 경향이 있다. 채널(channels)의 수는 Conv2D층에 전달된 첫 번째 매개변수에 의해 조절된다.</li>
</ul>
<pre><code class="language-python">from keras import layers
from keras import models

model = models.Sequential()
model.add(layers.Conv2D(32, (3,3), activation=&#39;relu&#39;, input_shape=(28,28,1)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64,(3,3), activation=&#39;relu&#39;))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64,(3,3), activation=&#39;relu&#39;))

model.summary()</code></pre>
</br>

<p><strong>실행결과:</strong></p>
<pre><code class="language-python">Model: &quot;sequential&quot;
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 3, 3, 64)          36928     
=================================================================
Total params: 55,744
Trainable params: 55,744
Non-trainable params: 0
_________________________________________________________________</code></pre>
<p></br></br></p>
<h3 id="1-2-컨브넷-위에-분류기-추가하기">1-2. 컨브넷 위에 분류기 추가하기</h3>
<ul>
<li>위 단계에서 마지막 층의 (3,3,64)크기인 출력 텐서를 완전 연결 네트워크에 주입한다.</li>
<li>완전 연결 네트워크는 Dense층을 쌓은 &#39;분류기&#39;이다.</li>
<li>이 분류기는 1D벡터를 처리하는데, 이전 층의 출력이 3D텐서이므로, 3D출력을 1D텐서로 펼쳐야 한다. &gt;&gt; Flatten</li>
<li>그 다음에 몇 개의 Dense층을 추가한다.</li>
<li>10개의 클래스(숫자 0~9)를 분류하기 위해 마지막 층의 출력 크기를 10으로 하고, softmax활성화함수를 사용한다.</li>
</ul>
<pre><code class="language-python">model.add(layers.Flatten()) # (3,3,64)출력이 (576,)벡터로 펼쳐진 후 Dense층에 주입된다.
model.add(layers.Dense(64, activation=&#39;relu&#39;))
model.add(layers.Dense(10, activation=&#39;softmax&#39;))

model.summary()</code></pre>
</br>

<p><strong>실행결과:</strong></p>
<pre><code class="language-python">Model: &quot;sequential&quot;
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 3, 3, 64)          36928     
_________________________________________________________________
flatten (Flatten)            (None, 576)               0         
_________________________________________________________________
dense (Dense)                (None, 64)                36928     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                650       
=================================================================
Total params: 93,322
Trainable params: 93,322
Non-trainable params: 0
_________________________________________________________________</code></pre>
<p></br></br></p>
<h3 id="1-3-mnist-이미지에-컨브넷-훈련하기">1-3. MNIST 이미지에 컨브넷 훈련하기</h3>
<pre><code class="language-python">from keras.datasets import mnist
from keras.utils import to_categorical

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype(&#39;float32&#39;) / 255

test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype(&#39;float32&#39;) / 255

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

model.compile(optimizer=&#39;rmsprop&#39;,
             loss=&#39;categorical_crossentropy&#39;,
             metrics=[&#39;accuracy&#39;])
model.fit(train_images, train_labels, epochs=5, batch_size=64)</code></pre>
</br>

<p><strong>실행결과:</strong></p>
<pre><code class="language-python">Epoch 1/5
938/938 [==============================] - 51s 54ms/step - loss: 0.0068 - accuracy: 0.9981
Epoch 2/5
938/938 [==============================] - 50s 54ms/step - loss: 0.0061 - accuracy: 0.9984
Epoch 3/5
938/938 [==============================] - 50s 54ms/step - loss: 0.0031 - accuracy: 0.9991
Epoch 4/5
938/938 [==============================] - 50s 54ms/step - loss: 0.0033 - accuracy: 0.9990
Epoch 5/5
938/938 [==============================] - 50s 54ms/step - loss: 0.0024 - accuracy: 0.9993
&lt;tensorflow.python.keras.callbacks.History at 0x7fe333f65090&gt;</code></pre>
<p></br></br></p>
<pre><code class="language-python">test_loss, test_acc = model.evaluate(test_images, test_labels)
test_acc</code></pre>
<p><strong>실행결과:</strong></p>
<pre><code class="language-python">313/313 [==============================] - 3s 10ms/step - loss: 0.0517 - accuracy: 0.9924
0.9923999905586243</code></pre>
<p></br></br></br></br></p>
<hr>
<p></br></br></br></br></p>
<h2 id="실습2-개-고양이-이미지-분류-데이터증식">실습2. 개, 고양이 이미지 분류 (데이터증식)</h2>
<p>kaggle의 dogs vs. cats데이터를 사용한다.</p>
<h3 id="2-1-훈련-검증-테스트-폴더로-이미지-복사하기">2-1. 훈련, 검증, 테스트 폴더로 이미지 복사하기</h3>
<p>원래라면 코드를 통해 이미지를 복사하면 되는데 이 코드가 원하는대로 실행되려면 구글드라이브에 이미지파일을 모두 압축해제 해놓아야 한다. 하지만 몇 차례 시도한 결과 3시간에 30퍼의 진행률을 보이며 도저히 2만개가 넘는 이미지를 모두 압축해제 할 수 있을 것 같지 않았다.
그래서 로컬에 압축해제 하고, 직접 구글 드라이브로 개 or 고양이 이미지를 0<del>999번까지는 train, 1000</del>1499까지는 validation, 1500~1999까지는 test폴더에 드래그로 옮겨주니 훨씬 빨리 복사할 수 있었다. 여러 시행착오를 겪고 성공한거라 폴더 안의 이미지 수가 딱 떨어지진 않는다.ㅜㅜ </p>
<pre><code class="language-python">import os, shutil

original_dataset_dir = &#39;./drive/MyDrive/Colab Notebooks/datasets/cats_and_dogs/train&#39;

base_dir = &#39;./drive/MyDrive/Colab Notebooks/datasets/cats_and_dogs_small&#39;
os.makedirs(base_dir)

train_dir = os.path.join(base_dir, &#39;train&#39;)
os.mkdir(train_dir)
validation_dir = os.path.join(base_dir, &#39;validation&#39;)
os.mkdir(validation_dir)
test_dir = os.path.join(base_dir, &#39;test&#39;)
os.mkdir(test_dir)

train_cats_dir = os.path.join(train_dir, &#39;cats&#39;)
os.mkdir(train_cats_dir)

train_dogs_dir = os.path.join(train_dir, &#39;dogs&#39;)
os.mkdir(train_dogs_dir)

validation_cats_dir = os.path.join(validation_dir, &#39;cats&#39;)
os.mkdir(validation_cats_dir)

validation_dogs_dir = os.path.join(validation_dir, &#39;dogs&#39;)
os.mkdir(validation_dogs_dir)

test_cats_dir = os.path.join(test_dir, &#39;cats&#39;)
os.mkdir(test_cats_dir)

test_dogs_dir = os.path.join(test_dir, &#39;dogs&#39;)
os.mkdir(test_dogs_dir)

# fnames = [&#39;cat.{}.jpg&#39;.format(i) for i in range(1000)]
# for fname in fnames:
#   try:
#     src = os.path.join(original_dataset_dir, fname)
#     dst = os.path.join(train_cats_dir, fname)
#     shutil.copyfile(src, dst)
#   except FileNotFoundError:
#     pass

# fnames = [&#39;cat.{}.jpg&#39;.format(i) for i in range(1000, 1500)]
# for fname in fnames:
#   src = os.path.join(original_dataset_dir, fname)
#   dst = os.path.join(validation_cats_dir, fname)
#   shutil.copyfile(src, dst)

# fnames = [&#39;cat.{}.jpg&#39;.format(i) for i in range(1500, 2000)]
# for fname in fnames:
#   try:
#     src = os.path.join(original_dataset_dir, fname)
#     dst = os.path.join(test_cats_dir, fname)
#     shutil.copyfile(src, dst)
#   except FileNotFoundError:
#     pass

# fnames = [&#39;dog.{}.jpg&#39;.format(i) for i in range(1000)]
# for fname in fnames:
#   try:
#     src = os.path.join(original_dataset_dir, fname)
#     dst = os.path.join(train_dogs_dir, fname)
#     shutil.copyfile(src, dst)
#   except FileNotFoundError:
#     pass

# fnames = [&#39;dog.{}.jpg&#39;.format(i) for i in range(1000, 1500)]
# for fname in fnames:
#   try:
#     src = os.path.join(original_dataset_dir, fname)
#     dst = os.path.join(validation_dogs_dir, fname)
#     shutil.copyfile(src, dst)
#   except FileNotFoundError:
#     pass

# fnames = [&#39;dog.{}.jpg&#39;.format(i) for i in range(1500, 2000)]
# for fname in fnames:
#   try:
#     src = os.path.join(original_dataset_dir, fname)
#     dst = os.path.join(test_dogs_dir, fname)
#     shutil.copyfile(src, dst)
#   except FileNotFoundError:
#     pass

print(&#39;훈련용 고양이 이미지 전체 개수: &#39;, len(os.listdir(train_cats_dir)))
print(&#39;훈련용 강아지 이미지 전체 개수: &#39;, len(os.listdir(train_dogs_dir)))
print(&#39;검증용 고양이 이미지 전체 개수: &#39;, len(os.listdir(validation_cats_dir)))
print(&#39;검증용 강아지 이미지 전체 개수: &#39;, len(os.listdir(validation_dogs_dir)))
print(&#39;테스트용 고양이 이미지 전체 개수: &#39;, len(os.listdir(test_cats_dir)))
print(&#39;테스트용 강아지 이미지 전체 개수: &#39;, len(os.listdir(test_dogs_dir)))</code></pre>
<p><strong>실행결과:</strong></p>
<pre><code class="language-python">훈련용 고양이 이미지 전체 개수:  1076
훈련용 강아지 이미지 전체 개수:  1020
검증용 고양이 이미지 전체 개수:  500
검증용 강아지 이미지 전체 개수:  501
테스트용 고양이 이미지 전체 개수:  500
테스트용 강아지 이미지 전체 개수:  508</code></pre>
<p></br></br></p>
<h3 id="2-2-강아지-vs-고양이-분류를-위한-소규모-컨브넷-만들기">2-2. 강아지 vs. 고양이 분류를 위한 소규모 컨브넷 만들기</h3>
<pre><code class="language-python">from keras import layers
from keras import models

model = models.Sequential()
model.add(layers.Conv2D(32, (3,3), activation=&#39;relu&#39;, input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64, (3,3), activation=&#39;relu&#39;))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128, (3,3), activation=&#39;relu&#39;))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128, (3,3), activation=&#39;relu&#39;))
model.add(layers.MaxPooling2D((2,2)))

model.add(layers.Flatten())
model.add(layers.Dense(512, activation=&#39;relu&#39;))
model.add(layers.Dense(1, activation=&#39;sigmoid&#39;))

model.summary()</code></pre>
</br>

<p><strong>실행결과:</strong></p>
<pre><code class="language-python">Model: &quot;sequential&quot;
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 148, 148, 32)      896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 74, 74, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 72, 72, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 36, 36, 64)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 34, 34, 128)       73856     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 17, 17, 128)       0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 15, 15, 128)       147584    
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 7, 7, 128)         0         
_________________________________________________________________
flatten (Flatten)            (None, 6272)              0         
_________________________________________________________________
dense (Dense)                (None, 512)               3211776   
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 513       
=================================================================
Total params: 3,453,121
Trainable params: 3,453,121
Non-trainable params: 0
_________________________________________________________________</code></pre>
<p></br></br></p>
<h3 id="2-3-모델의-훈련-설정하기">2-3. 모델의 훈련 설정하기</h3>
<pre><code class="language-python">from keras import optimizers

model.compile(loss=&#39;binary_crossentropy&#39;,
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=[&#39;acc&#39;])</code></pre>
<p></br></br></p>
<h3 id="2-4-imagedatagenerator를-사용하여-디렉터리에서-이미지-읽기">2-4. ImageDataGenerator를 사용하여 디렉터리에서 이미지 읽기</h3>
<pre><code class="language-python">from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(150, 150),
    batch_size=20,
    class_mode=&#39;binary&#39;)

validation_generator = test_datagen.flow_from_directory(
    validation_dir,
    target_size=(150, 150),
    batch_size=20,
    class_mode=&#39;binary&#39;
)


for data_batch, labels_batch in train_generator:
  print(&#39;배치 데이터 크기: &#39;, data_batch.shape)
  print(&#39;배치 레이블 크기: &#39;, labels_batch.shape)
  break</code></pre>
<p><strong>실행결과:</strong></p>
<pre><code class="language-python">Found 2096 images belonging to 2 classes.
Found 1001 images belonging to 2 classes.
배치 데이터 크기:  (20, 150, 150, 3)
배치 레이블 크기:  (20,)</code></pre>
<p></br></br></p>
<h3 id="2-5-배치-제너레이터를-사용하여-모델-훈련하기">2-5. 배치 제너레이터를 사용하여 모델 훈련하기</h3>
<pre><code class="language-python">history = model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs=30,
    validation_data=validation_generator,
    validation_steps=50)</code></pre>
<p><strong>실행결과:</strong></p>
<pre><code class="language-python">Epoch 1/30
100/100 [==============================] - 113s 1s/step - loss: 0.6904 - acc: 0.5291 - val_loss: 0.6770 - val_acc: 0.5390
Epoch 2/30
100/100 [==============================] - 113s 1s/step - loss: 0.6569 - acc: 0.6027 - val_loss: 0.6716 - val_acc: 0.5586
Epoch 3/30
100/100 [==============================] - 123s 1s/step - loss: 0.6124 - acc: 0.6573 - val_loss: 0.7135 - val_acc: 0.6351
.
.
.
Epoch 28/30
100/100 [==============================] - 112s 1s/step - loss: 0.0892 - acc: 0.9694 - val_loss: 1.0027 - val_acc: 0.7278
Epoch 29/30
100/100 [==============================] - 112s 1s/step - loss: 0.0811 - acc: 0.9729 - val_loss: 1.8023 - val_acc: 0.7227
Epoch 30/30
100/100 [==============================] - 113s 1s/step - loss: 0.0632 - acc: 0.9840 - val_loss: 1.2665 - val_acc: 0.7319</code></pre>
</br>

<h3 id="2-6-모델-저장하기">2-6. 모델 저장하기</h3>
<pre><code class="language-python">model.save(&#39;cats_and_dogs_small_1.h5&#39;)</code></pre>
<p></br></br></p>
<h3 id="2-7-훈련의-정확도와-손실그래프-그리기">2-7. 훈련의 정확도와 손실그래프 그리기</h3>
<pre><code class="language-python">import matplotlib.pyplot as plt

acc = history.history[&#39;acc&#39;]
val_acc = history.history[&#39;val_acc&#39;]
loss = history.history[&#39;loss&#39;]
val_loss = history.history[&#39;val_loss&#39;]

epochs = range(1, len(acc) + 1)

plt.plot(epochs, acc, &#39;bo&#39;, label=&#39;Training acc&#39;)
plt.plot(epochs, val_acc, &#39;b&#39;, label=&#39;Validation acc&#39;)
plt.title(&#39;Training and validation accuracy&#39;)
plt.legend()

plt.figure()

plt.plot(epochs, loss, &#39;bo&#39;, label=&#39;Training loss&#39;)
plt.plot(epochs, val_loss, &#39;b&#39;, label=&#39;Validation loss&#39;)
plt.title(&#39;Training and validation loss&#39;)
plt.legend()

plt.show()</code></pre>
</br>

<p><strong>실행결과:</strong>
<img src="https://images.velog.io/images/the_huistle/post/e50cceaf-3245-4474-827a-57a981c0f2ee/%EC%8B%A4%EC%8A%B52-1.PNG" alt=""></p>
<p></br></br></p>
<h3 id="2-8-imagedatagenerator를-사용하여-데이터-증식-설정하기">2-8. ImageDataGenerator를 사용하여 데이터 증식 설정하기</h3>
<pre><code class="language-python">datagen = ImageDataGenerator(
    rotation_range=20,
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.1,
    zoom_range=0.1,
    horizontal_flip=True,
    fill_mode=&#39;nearest&#39;
)</code></pre>
<p></br></br></p>
<h3 id="2-9-랜덤하게-증식된-훈련-이미지-그리기">2-9. 랜덤하게 증식된 훈련 이미지 그리기</h3>
<pre><code class="language-python">from keras.preprocessing import image

fnames = sorted([os.path.join(train_cats_dir, fname) for
                 fname in os.listdir(train_cats_dir)])

img_path = fnames[3]

img = image.load_img(img_path, target_size=(150,150))

x = image.img_to_array(img)
x = x.reshape((1,) + x.shape)

i=0
for batch in datagen.flow(x, batch_size=1):
  plt.figure(i)
  imgplot = plt.imshow(image.array_to_img(batch[0]))
  i+=1
  if i % 4 == 0:
    break
plt.show()</code></pre>
</br>

<p><strong>실행결과:</strong>
<img src="https://images.velog.io/images/the_huistle/post/488bb5ce-d005-41a1-8202-0e869ac48cca/%EC%8B%A4%EC%8A%B52-2.PNG" alt=""> <img src="https://images.velog.io/images/the_huistle/post/40a76c09-53e1-4872-96ed-6d896e715c54/%EC%8B%A4%EC%8A%B52-3.PNG" alt=""></p>
<p></br></br></br></br></p>
<hr>
<p></br></br></br></br></p>
<h3 id="2-10-드롭아웃을-포함한-새로운-컨브넷-정의하기">2-10. 드롭아웃을 포함한 새로운 컨브넷 정의하기</h3>
<pre><code class="language-python">from keras import layers
from keras import models
from keras import optimizers

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation=&#39;relu&#39;, input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation=&#39;relu&#39;))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation=&#39;relu&#39;))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation=&#39;relu&#39;))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(512, activation=&#39;relu&#39;))
model.add(layers.Dense(1, activation=&#39;sigmoid&#39;))

model.compile(loss=&#39;binary_crossentropy&#39;,
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=[&#39;acc&#39;])</code></pre>
<p></br></br></br></p>
<h3 id="2-11-데이터-증식-제너레이터를-사용하여-컨브넷-훈련하기">2-11. 데이터 증식 제너레이터를 사용하여 컨브넷 훈련하기</h3>
<pre><code class="language-python">from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,)


test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(150, 150),
    batch_size=32,
    class_mode=&#39;binary&#39;)

validation_generator = test_datagen.flow_from_directory(
    validation_dir,
    target_size=(150, 150),
    batch_size=32,
    class_mode=&#39;binary&#39;)

history = model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs=100,
    validation_data=validation_generator,
    validation_steps=50)</code></pre>
<p><strong>실행결과:</strong></p>
<pre><code class="language-python">Found 2096 images belonging to 2 classes.
Found 1001 images belonging to 2 classes.
Epoch 1/100
100/100 [==============================] - 684s 7s/step - loss: 0.6893 - acc: 0.5377 - val_loss: 0.6676 - val_acc: 0.5789
Epoch 2/100
100/100 [==============================] - 30s 301ms/step - loss: 0.6807 - acc: 0.5634 - val_loss: 0.6159 - val_acc: 0.5914
Epoch 3/100
100/100 [==============================] - 30s 295ms/step - loss: 0.6577 - acc: 0.6016 - val_loss: 0.6913 - val_acc: 0.6189
Epoch 4/100
100/100 [==============================] - 30s 300ms/step - loss: 0.6411 - acc: 0.6363 - val_loss: 0.6605 - val_acc: 0.6190
Epoch 5/100
100/100 [==============================] - 29s 292ms/step - loss: 0.6259 - acc: 0.6395 - val_loss: 0.7564 - val_acc: 0.6728
.
.
.
Epoch 95/100
100/100 [==============================] - 28s 285ms/step - loss: 0.3313 - acc: 0.8546 - val_loss: 0.2591 - val_acc: 0.8192
Epoch 96/100
100/100 [==============================] - 31s 310ms/step - loss: 0.3347 - acc: 0.8540 - val_loss: 0.2464 - val_acc: 0.8224
Epoch 97/100
100/100 [==============================] - 28s 280ms/step - loss: 0.3273 - acc: 0.8532 - val_loss: 0.2781 - val_acc: 0.8497
Epoch 98/100
100/100 [==============================] - 32s 317ms/step - loss: 0.3148 - acc: 0.8643 - val_loss: 0.4643 - val_acc: 0.8121
Epoch 99/100
100/100 [==============================] - 29s 294ms/step - loss: 0.3310 - acc: 0.8554 - val_loss: 0.4055 - val_acc: 0.8256
Epoch 100/100
100/100 [==============================] - 30s 297ms/step - loss: 0.3175 - acc: 0.8527 - val_loss: 0.3398 - val_acc: 0.8301</code></pre>
</br>

<h3 id="코드-5-15-모델-저장하기">코드 5-15. 모델 저장하기</h3>
<pre><code class="language-python">model.save(&#39;cats_and_dogs_small_2.h5&#39;)</code></pre>
<p></br></br></br></p>
<h2 id="참고">[참고]</h2>
<p><strong>케라스 창시자에게 배우는 딥러닝</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RISE] 2주차 수행내용]]></title>
            <link>https://velog.io/@the_huistle/RISE-2%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</link>
            <guid>https://velog.io/@the_huistle/RISE-2%EC%A3%BC%EC%B0%A8-%EC%88%98%ED%96%89%EB%82%B4%EC%9A%A9</guid>
            <pubDate>Thu, 18 Mar 2021 07:39:03 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>** CNN study **</p>
</blockquote>
<ul>
<li>CNN이란?</li>
<li>Convolution 연산</li>
<li>CNN의 구성요소</li>
<li>CNN의 매개변수 설정</li>
</ul>
<br/>

<h2 id="cnn-convolutional-neural-network">CNN (Convolutional Neural Network)</h2>
<br/>

<h3 id="cnn이란">CNN이란?</h3>
<p><strong>Convolution(합성곱) 연산을 사용하여 데이터에서 유용한 정보를 추출하는 인공신경망이다.</strong></p>
<p>이전의 이미지 인식은 2차원의 이미지데이터를 1차원 배열로 변환하여 입력했다면, CNN은 2차원 데이터로 입력 가능하여 <strong>이미지의 공간정보를 유지</strong>한채 학습을 하게되는 모델이다.
따라서, 이 신경망은 이미지 및 오디오 데이터에 가장 적합하다.</p>
<p>CNN의 핵심아이디어는 이미지 전체를 보는 것이 아니라 부분을 보는 것이다. 이 ‘부분’을 보도록 하는 것을 <strong>filter</strong>라고 한다. <strong>filter 파라미터는 CNN에서 학습의 대상이다.</strong>
filter는 이미지의 특징을 찾아내기 위한 공용 파라미터이다. CNN에서 filter와 kernel은 같은 의미이다. filter는 일반적으로 (4, 4)이나 (3, 3)과 같은 정사각 행렬로 정의된다.</p>
<p><u>입력 이미지는 Convolution layer를 통과할 때 <strong>feature map</strong>이라고 하는 여러 개의 출력이미지를 생성한다.</u> (Convolution Layer에 유입되는 입력 데이터에는 1 개 이상의 filter가 적용된다. 1개 filter는 feature map의 채널이 되므로, Convolution Layer에 n개의 필터가 적용된다면 출력 데이터는 n개의 채널을 갖게 된다.)
<br/><br/></p>
<blockquote>
<h3 id="채널-channel">채널 (channel)</h3>
<p>이미지 픽셀 하나하나는 실수이다. <u>컬러 이미지는 각 픽셀을 RGB 3개의 실수로 표현한 3차원 데이터이므로 3개의 채널로 구성된다.</u> 반면에 흑백 명암만을 표현하는 <u>흑백 이미지는 2차원 데이터로 1개 채널로 구성된다.</u>
높이가 39 픽셀이고 폭이 31 픽셀인 컬러 사진 데이터의 shape은 (39, 31, 3)이고, 높이가 39픽셀이고 폭이 31픽셀인 흑백 사진 데이터의 shape은 (39, 31, 1)이다.
<img src="https://images.velog.io/images/the_huistle/post/a07cc1a3-7f65-4b2c-839e-dd03ad5da257/channel.jpg" alt=""></p>
</blockquote>
<p><br/><br/><br/><br/></p>
<hr>
<p><br/><br/><br/><br/></p>
<h3 id="convolution합성곱-연산">Convolution(합성곱) 연산</h3>
<p>Convolution의 수학적 정의는 &#39;하나의 함수와 또 다른 함수를 반전 이동한 값을 곱한 다음, 구간에 대해 적분하여 새로운 함수를 구하는 수학 연산자&#39;이다.</p>
<p>정의나 식만으로는 잘 이해가 되지 않아서 <strong>이미지데이터로부터 filter를 거쳐 feature map을 만들어내는 것</strong>을 convolution연산으로 이해하였다.</p>
<p>아래 예시는 shape이 (5,5)인 2차원 입력데이터를 1개의 filter로 합성곱 연산을 수행하는 과정이다. <strong>stride</strong>란 filter의 이동 간격을 의미하는데, 이 때의 stride는 1이다.</p>
<p><img src="https://images.velog.io/images/the_huistle/post/c5bf1816-1ee1-4c5a-9170-0aa6218861d4/Convolution_schematic.gif" alt=""></p>
<br/>

<p>아래 그림은 또다른 예시이다.
입력 데이터를 (3, 3) 크기의 filter로 Convolution(합성곱)하는 과정이다.</p>
<p><img src="https://images.velog.io/images/the_huistle/post/7a5cbb4f-d2d5-4ee1-bf5e-ad7e903ad913/conv.png" alt="">
<br/>
입력 데이터가 여러 채널을 가질 경우, 입력 데이터를 filter가 지정된 간격(stride)으로 순회하며 <strong>채널별로 Convolution(합성곱)을 하고 모든 채널(컬러의 경우 3개)의 합성곱의 합을 feature map으로 만든다.</strong> 입력 데이터는 채널 수와 상관없이 filter 별로 1개의 feature map이 만들어 진다.</p>
<p><img src="https://images.velog.io/images/the_huistle/post/f85f140e-b8c7-46aa-a76f-340cbbf43f56/conv2.jpg" alt=""></p>
<blockquote>
<h3 id="패딩-padding">패딩 (Padding)</h3>
<p> Convolution Layer에서 filter와 stride의 작용으로 feature map 크기는 입력데이터 보다 작아진다. Convolution Layer의 출력 데이터가 줄어드는 것을 방지하는 방법이 패딩(Padding)입니다. <strong>패딩은 입력 데이터의 외각에 지정된 픽셀만큼 특정 값으로 채워 넣는 것을 의미합니다.</strong> 보통 패딩 값으로 0으로 채워 넣는 <u>Zero Padding</u>을 수행한다.<br/> 패딩을 통해서 Convolution Layer의 출력 데이터의 사이즈를 조절하는 기능 외에도, 외곽을 “0”값으로 둘러싸는 특징으로부터 인공 신경망이 이미지의 외곽을 인식하는 학습 효과도 있습니다.</p>
</blockquote>
<p><br/><br/><br/><br/></p>
<hr>
<p><br/><br/><br/><br/></p>
<h3 id="cnn의-구성요소">CNN의 구성요소</h3>
<blockquote>
<ol>
<li>Convolution Layer</li>
<li>ReLU Layer</li>
<li>Pooling Layer</li>
<li>Fully Connected Layer</li>
<li>Loss Layer (Softmax Layer)</li>
</ol>
</blockquote>
<p>CNN은 Convolution Layer와 Max Pooling Layer를 반복적으로 stack을 쌓는 <strong>특징 추출(Feature Extraction) 부분</strong>과 Fully Connected Layer를 구성하고 마지막 출력층에 Softmax를 적용한 <strong>분류 부분</strong>으로 나뉜다.</p>
<p><img src="https://images.velog.io/images/the_huistle/post/5242bde7-40c7-4d49-a789-16e2688408f8/CNN%EA%B5%AC%EC%A1%B02.png" alt=""></p>
<h4 id="1-convolution-layer">1. Convolution Layer</h4>
<p>하나의 Convolution Layer는 Convolution 처리와 Activation function으로 이루어져 있다. 여기서 활성화 함수를 사용하는 이유는 선형함수인 convolution에 비선형성을 추가하기 위해서이다.</p>
<p>첫 Convolution layer의 출력 feature map은 edge 및 색 구성 변화와 같은 기본 특징을 검출하는 것을 학습할 수 있다. 제 2 Convolution layer는 정사각형, 원 및 다른 기하학적 구조와 같은 약간 더 복잡한 특징을 검출할 수 있다.</p>
<br/>

<h4 id="2-relu-layer">2. ReLU Layer</h4>
<p>ReLU는 <code>f(x)=max(0,x)</code>인 활성화함수이다. 이를 통해 feature map에서 음수를 효과적으로 제거 할 수 있다. 사실 Convolution Layer에서 언급한 Activaton function이 이 ReLU 활성화함수를 의미한다. 여러 가지를 참고해서 정리하다 보니 약간 헷갈릴 수 있는데, ReLU Layer는 Convolution Layer와 따로 구분해서 볼 필요는 없는 것 같다.</p>
<br/>

<h4 id="3-pooling-layer">3. Pooling Layer</h4>
<p>이미지의 크기를 계속 유지한 채 FC(Fully Connected) Layer로 가게 된다면 연산량이 기하급수적으로 늘 것이다. <strong>적당히 크기도 줄이고, 특정 feature를 강조</strong>할 수 있어야 하는데 그 역할을 Pooling Layer에서 하게 된다.</p>
<p>Pooling Layer는 Convolution Layer와 비교하여 다음과 같은 특징이 있다.</p>
<ul>
<li>학습대상 파라미터가 없음</li>
<li>Pooling Layer를 통과하면 행렬의 크기가 감소함</li>
<li>Pooling Layer를 통한 채널 수 변경이 없음</li>
</ul>
<blockquote>
<h3 id="풀링-pooling">풀링 (Pooling)</h3>
<p><strong>Pooling은 각 결과값(feature map)의 차원을 축소해 주는 것을 목적으로 한다.</strong> 연관성이 낮은 부분을 제거하여 각 결과값의 크기를 줄이는 과정이다.<br/>
<img src="https://images.velog.io/images/the_huistle/post/c4b3cf32-ef31-43c7-858b-73d618760834/pooling.png" alt="">
Pooling에는 대표적인 방법으로 Max pooling과 Average pooling이 있다. 위 이미지와 같이 Pool의 크기가 2x2인 경우 2x2크기의 <strong>matrix에서 최댓값(max)이나 평균값(average)를 가져와 결과값의 크기를 반으로 줄여준다.</strong> <br/>
CNN에서는 주로 Max Pooling을 사용하는데, 이는 뉴런이 가장 큰 신호에 반응하는 것과 유사하다고 한다. Max Pooling을 함으로써 <strong>노이즈가 감소하고 속도가 빨라지며 영상의 분별력이 좋아지는 효과가 있다.</strong></p>
</blockquote>
<br/>

<h4 id="4-fully-connected-layer-완전연결계층-dense-layer">4. Fully Connected Layer (완전연결계층, Dense Layer)</h4>
<p>여러 번의 convolution과 max pooling layer를 하고 나면, Fully Connected Layer를 통해 고난도의 추론을 할 수 있게 된다. 완전연결계층의 뉴런은 이전 계층의 모든 activation에 연결된다.</p>
<p>Fully Connected Layer을 적용하기 이전에 Pooling한 결과인 다차원의 데이터를 쭉 펼쳐 1차원의 벡터데이터로 변환해주는 Flatten (or Vectorization)의 과정이 필요하다.</p>
<br/>




<h4 id="5-loss-layer-softmax-layer">5. Loss Layer (Softmax Layer)</h4>
<p><strong>Loss Layer는 훈련이 예측(출력) 레이블과 실제 레이블 간의 편차에 페널티를주는 방식을 지정하며, 일반적으로 신경망의 최종 계층이다.</strong> 각기 다른 작업에 적합한 다양한 손실 함수를 사용할 수 있다.</p>
<p>CNN에서는 분류 문제에 적합한 <strong>Softmax</strong> 손실함수를 사용한다.</p>
<p><br/><br/><br/><br/></p>
<hr>
<p><br/><br/><br/><br/></p>
<h3 id="cnn-매개변수-설정">CNN 매개변수 설정</h3>
<p>CNN의 Convolution Layer에서 하이퍼파라미터는 다음과 같다.</p>
<ul>
<li><p><strong>Convolution Filter의 개수</strong></p>
<ul>
<li>각 Layer에서의 연산시간을 비교적 일정하게 유지하며 시스템의 균형을 맞추는 것이 좋다. 보통 Pooling Layer를 거치면 1/4로 출력이 줄어들기 때문에 Convolution Layer의 결과인 Feature Map의 개수를 4배정도 증가시키면 된다.</li>
</ul>
</li>
<li><p><strong>Filter의 크기</strong></p>
<ul>
<li>작은 필터를 여러 개 중첩하면 원하는 특징을 더 돋보이게하면서 연산량을 줄일 수 있다. 요즘 대부분의 CNN은 3x3 size를 중첩해서 사용한다고 한다.</li>
</ul>
</li>
<li><p><strong>Padding여부</strong></p>
<ul>
<li>Padding은 Convolution을 수행하기 전, 입력 데이터 주변을 특정 픽셀 값으로 채워 늘리는 것이므로, <u>Padding을 사용하게 되면 입력 이미지의 크기를 줄이지 않을 수 있습니다.</u></li>
</ul>
</li>
<li><p><strong>Stride</strong></p>
<ul>
<li>Stride는 Filter의 이동 간격을 조절하는 파라미터이다. <u>이 값이 커지게 되면 결과 데이터의 사이즈가 작아지게 된다.</u></li>
</ul>
</li>
</ul>
<br/>




<p>CNN은 Filter의 크기, Stride, Padding과 Pooling 크기로 출력 데이터 크기를 조절하고, filter의 개수로 출력 데이터의 채널을 결정합니다.</p>
<blockquote>
<h4 id="convolution-layer-출력데이터-크기">Convolution Layer 출력데이터 크기</h4>
<p>입력 데이터에 대한 filter의 크기와 Stride에 따라서 Feature Map 크기가 결정된다.</p>
</blockquote>
<ul>
<li>입력 데이터 높이: H</li>
<li>입력 데이터 폭: W</li>
<li>filter 높이: FH</li>
<li>filter 폭: FW</li>
<li>Stride: S</li>
<li>Padding 크기: P
<img src="https://images.velog.io/images/the_huistle/post/c3948c2e-9224-40fb-88d9-eac256573973/conv%EC%B6%9C%EB%A0%A5%EB%8D%B0%EC%9D%B4%ED%84%B0.PNG" alt="">
식의 결과는 자연수가 되어야 한다. 또한 Convolution Layer 다음에 Pooling Layer가 온다면, <strong>Feature Map의 행과 열의 크기는 Pooling 크기의 배수여야 한다.</strong> 만약 Pooling 사이즈가 (3, 3)이라면 위 식의 결과는 자연수이고 3의 배수여야 합니다. <strong>이 조건을 만족하도록 Filter의 크기, Stride, Pooling 크기 및 Padding 크기를 조절해야 한다.</strong></li>
</ul>
<blockquote>
<h4 id="pooling-layer-출력데이터-크기">Pooling Layer 출력데이터 크기</h4>
<p>Pooling Layer에서 일반적인 Pooling 크기는 정사각형이므로, Pooling 크기를 Stride와 같은 크기로 만들어서 모든 요소가 한번씩 Pooling되도록 만든다. <strong>입력 데이터의 행 크기와 열 크기는 Pooling 크기의 배수여야 한다.</strong> 
<img src="https://images.velog.io/images/the_huistle/post/e085e266-9496-43f1-b45a-5dcea7191e3f/conv%EC%B6%9C%EB%A0%A5%EB%8D%B0%EC%9D%B4%ED%84%B02.PNG" alt="">
결과적으로 <strong>Pooling Layer의 출력 데이터의 크기는 행과 열의 크기를 Pooling 크기로 나눈 몫과 같다.</strong> Pooling 크기가 (2, 2)라면 출력 데이터 크기는 입력 데이터의 행과 열 크기를 2로 나눈 몫이다. pooling 크기가 (3, 3)이라면 입력데이터의 행과 크기를 3으로 나눈 몫이 된다.</p>
</blockquote>
<p><br/><br/><br/></p>
<h2 id="참고">[참고]</h2>
<p><a href="https://hobinjeong.medium.com/cnn-convolutional-neural-network-9f600dd3b395">CNN(Convolutional Neural Network)이란?</a>
<a href="http://taewan.kim/post/cnn/">CNN, Convolutional Neural Network 요약</a>
<a href="https://en.wikipedia.org/wiki/Convolutional_neural_network">Convolutional neural network From Wikipedia</a>
<a href="https://halfundecided.medium.com/%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-cnn-convolutional-neural-networks-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-836869f88375">[딥러닝/머신러닝] CNN(Convolutional Neural Networks) 쉽게 이해하기</a></p>
<p><br/><br/><br/></p>
<blockquote>
<p>3주차에는 keras를 이용한 CNN 예제를 실습할 예정이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[마크다운 및 태그 활용하는 블로그 작성법]]></title>
            <link>https://velog.io/@the_huistle/%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4-%EB%B0%8F-%ED%83%9C%EA%B7%B8%ED%99%9C%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%9E%91%EC%84%B1%EB%B2%95</link>
            <guid>https://velog.io/@the_huistle/%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4-%EB%B0%8F-%ED%83%9C%EA%B7%B8%ED%99%9C%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%9E%91%EC%84%B1%EB%B2%95</guid>
            <pubDate>Thu, 18 Mar 2021 05:47:29 GMT</pubDate>
            <description><![CDATA[<p><br/><br/></p>
<h2 id="1-제목">1. 제목</h2>
<p>&#39;#&#39;를 사용한다.</p>
<blockquote>
<p>h1(# 1개) ~ h6(# 6개)
크기: h1 &gt; h2 &gt; h3 ... &gt; h6</p>
</blockquote>
<br/>

<h2 id="2-줄바꿈">2. 줄바꿈</h2>
<p><code>&lt;br/&gt;</code>사용</p>
<blockquote>
<p><code>&lt;br/&gt;</code>로 여러 번 줄바꿈 가능.</p>
</blockquote>
<br/>

<h2 id="3-목록">3. 목록</h2>
<p><code>1. 2. 3.</code> 또는 <code>*, +, -</code>로 목록 생성 가능</p>
<blockquote>
<p>목록에서 <code>[ ]</code> 또는 <code>[x]</code>를 사용하면 체크박스를 만들 수 있다.</p>
</blockquote>
<ol>
<li><input disabled="" type="checkbox"> ㄱㄱ</li>
</ol>
<ul>
<li><input disabled="" type="checkbox"> ㄴㄴ</li>
<li><input checked="" disabled="" type="checkbox"> ㄷㄷ</li>
</ul>
<br/>

<h2 id="4-글자-효과">4. 글자 효과</h2>
<h4 id="4-1-굵게-기울게-취소선-밑줄">4-1. 굵게, 기울게, 취소선, 밑줄</h4>
<p><code>__굵게__</code> <code>**굵게**</code>
<code>_기울게_</code> <code>*기울게*</code>
<code>~~취소선~~</code>
<code>&lt;u&gt;밑줄&lt;/u&gt;</code>
<br/></p>
<p><strong>굵게</strong> <strong>굵게</strong>
<em>기울게</em> <em>기울게</em>
<del>취소선</del>
<u>밑줄</u>
<br/></p>
<h4 id="4-2-글자-색상">4-2. 글자 색상</h4>
<p>span 태그를 이용해서 색상을 바꿀 수 있다.
색상은 영어나 rbg값 등으로 설정가능하다.</p>
<p><code>&lt;span style=&quot;color:red&quot;&gt;빨강&lt;/span&gt;</code>
<code>&lt;span style=&quot;color:rgb(25,200,200)&quot;&gt;color:rgb(25,200,200)&lt;/span&gt;</code>
<br/>
<span style="color:red">빨강</span>
<span style="color:rgb(25,200,200)">rgb(25,200,200)</span>
<br/></p>
<h2 id="5-인용문">5. 인용문</h2>
<p><code>&gt;</code> 사용</p>
<blockquote>
<blockquote>
<blockquote>
<p><code>&gt;</code> 여러 번 사용 가능</p>
</blockquote>
</blockquote>
</blockquote>
<p><br/><br/></p>
<h2 id="6-코드-작성">6. 코드 작성</h2>
<h4 id="6-1-인라인-코드">6-1. 인라인 코드</h4>
<p><code>``</code> 사용 (작은 따옴표 아님!)</p>
<h4 id="6-2-코드-블럭">6-2. 코드 블럭</h4>
<p>여러 줄의 코드를 쓸 때는
<code>``` ```</code> 사용</p>
<blockquote>
<p><code>```python ```</code>과 같이 사용하면 python 문법에 맞게 나타난다.</p>
</blockquote>
<pre><code class="language-python">sum=0
for i in range(10):
    sum+=i
print(sum)</code></pre>
<p><br/><br/></p>
<h2 id="7-링크">7. 링크</h2>
<p><code>[링크별명](url)</code> 또는 <code>&lt;url&gt;</code>을 이용하면 다음과 같이 뜬다.
<a href="naver.com">네이버</a></p>
<p><a href="https://www.google.co.kr/">https://www.google.co.kr/</a></p>
<p><br/><br/></p>
<h2 id="8-구분선">8. 구분선</h2>
<p><code>***</code> 또는 <code>---</code> 또는 <code>___</code>을 사용</p>
<hr>
<hr>
<hr>
<p><br/><br/></p>
<h2 id="9-표">9. 표</h2>
<p><code>|항목1|항목2|항목3|</code>
<code>|-||-||-|</code>
<code>|내용1|내용2|내용3|</code></p>
<blockquote>
<p>두 번째 줄에서 <code>|:-|</code>는 왼쪽 정렬, <code>|:-:|</code>는 가운데 정렬, <code>|-:|</code>는 오른쪽 정렬로 각 열을 정렬한다.</p>
</blockquote>
<table>
<thead>
<tr>
<th align="left">ㄱ</th>
<th align="center">ㄴ</th>
<th align="right">ㄷ</th>
</tr>
</thead>
<tbody><tr>
<td align="left">ㅇ</td>
<td align="center">ㅇ</td>
<td align="right">ㅇ</td>
</tr>
<tr>
<td align="left">ㅇ</td>
<td align="center">ㅇ</td>
<td align="right">ㅇ</td>
</tr>
</tbody></table>
<p><br/><br/><br/></p>
<h2 id="10-이모지-사용">10. 이모지 사용</h2>
<h4 id="10-1-단축키-사용">10-1. 단축키 사용</h4>
<p>윈도우: <code>윈도우키</code> + <code>.(마침표)</code></p>
<h4 id="10-2-링크에서-복사해오기">10-2. 링크에서 복사해오기</h4>
<p><a href="https://kr.piliapp.com/twitter-symbols/">https://kr.piliapp.com/twitter-symbols/</a></p>
<p><br/><br/></p>
<h2 id="참고">[참고]</h2>
<p><a href="https://velog.io/@yuuuye/velog-%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4MarkDown-%EC%9E%91%EC%84%B1%EB%B2%95">velog 마크다운(markdown) 작성법</a>
<a href="https://cizz3007.github.io/%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4/%EB%AC%B8%EB%B2%95/markdown/2018/04/08/markdown/">마크다운 문법 공부</a></p>
]]></description>
        </item>
    </channel>
</rss>