์•ˆ๋…•ํ•˜์„ธ์š” Oneclick AI ์ž…๋‹ˆ๋‹ค!!
์˜ค๋Š˜์€, CNN ๋ชจ๋ธ์— ๋Œ€ํ•ด์„œ ๊นŠ๊ฒŒ ์•Œ์•„๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณผ๊นŒ ํ•ฉ๋‹ˆ๋‹ค.

๋”ฅ๋Ÿฌ๋‹์— ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ ์ด์œ ๊ฐ€ ๋ฐ”๋กœ CNN์˜ ํ•ฉ์„ฑ๊ณฑ ์‹ ๊ฒฝ๋ง (Convolutional Neural Network, CNN) ๋•๋ถ„์ธ๋ฐ์š”, ์˜ค๋Š˜์€ ์ด ์‹ ๊ฒฝ๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€, CNN์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์ง„ ์†์˜ ์ˆซ์ž๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.


๋ชฉ์ฐจ

  1. CNN ํ•ต์‹ฌ ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ
    • ์™œ ์ด๋ฏธ์ง€์— CNN์„ ์‚ฌ์šฉํ• ๊นŒ?
    • CNN์˜ ํ•ต์‹ฌ : ์ง€์—ญ ์ˆ˜์šฉ ์˜์—ญ๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ 
    • CNN์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ
  2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ
    • keras๋กœ ๊ตฌํ˜„ํ•œ CNN ๋ชจ๋ธ ์•„ํ‚คํ…์ณ
    • model.summary()๋กœ ๊ตฌ์กฐ ํ™•์ธํ•˜๊ธฐ
  3. ์ง์ ‘ CNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ
    • 1๋‹จ๊ณ„ : ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ
    • 2๋‹จ๊ณ„ : ๋ชจ๋ธ ์ปดํŒŒ์ผ
    • 3๋‹จ๊ณ„ : ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€
    • 4๋‹จ๊ณ„ : ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅํ•˜๊ธฐ
    • 5๋‹จ๊ณ„ : ๋ชจ๋ธ ์‚ฌ์šฉํ•˜๊ธฐ
  4. ๋‚˜๋งŒ์˜ CNN ๋ชจ๋ธ ๋งŒ๋“ค์–ด๋ณด๊ธฐ
    • ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹
    • ๋ชจ๋ธ ๊ตฌ์กฐ ๋ณ€๊ฒฝํ•˜๊ธฐ
    • ์ „์ดํ•™์Šต์œผ๋กœ ์„ฑ๋Šฅ ๊ทน๋Œ€ํ™” ํ•˜๊ธฐ
  5. ๊ฒฐ๋ก 

1. CNN ํ•ต์‹ฌ์›๋ฆฌ ํŒŒ์•…ํ•˜๊ธฐ

๋“ค์–ด๊ฐ€๊ธฐ ์•ž์„œ, CNN ์ด ์–ด๋–ค ์›๋ฆฌ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€ ๋จผ์ € ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์™œ ์ด๋ฏธ์ง€์— CNN์„ ์‚ฌ์šฉํ• ๊นŒ?? ๋‹จ์ˆœํ•œ ์‹ ๊ฒฝ๋ง(Fully Connected Layer)์— ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅํ•˜๋ ค๋ฉด, 2์ฐจ์›์ธ ์ด๋ฏธ์ง€๋ฅผ 1์ฐจ์›์˜ ๊ธด ๋ฐ์ดํ„ฐ๋กœ ํŽผ์น˜๋Š” ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ ๊ณผ์ •์ด ๊ผญ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
์ด ๊ณผ์ •์—์„œ ํ”ฝ์…€ ๊ฐ„์˜ ๊ณต๊ฐ„์ ์ธ ์ •๋ณด๊ฐ€ ์ „๋ถ€ ํŒŒ๊ดด๋ฉ๋‹ˆ๋‹ค.
์ด๋Š” ์–ด๋–ค ํ”ฝ์…€์ด ์„œ๋กœ ์ด์›ƒํ•ด ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์–ด์ ธ์„œ ๋ˆˆ์ด ์ฝ” ์˜†์— ์žˆ๋‹ค๋Š” ์œ„์น˜์ •๋ณด ๊ฐ™์€ ๋‚ด์šฉ์ด ๊ฐ€๋ผ์ € ๋ฒ„๋ฆฐ๋‹ค๋Š” ์˜๋ฏธ ์ž…๋‹ˆ๋‹ค.
CNN์€ ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ธ๊ฐ„์˜ ์‹œ์‹ ๊ฒฝ ๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฐฉํ•˜์—ฌ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

CNN์˜ ํ•ต์‹ฌ ์•„์ด๋””์–ด
์ด๊ฒƒ์ด ๋ฐ”๋กœ ์ง€์—ญ์  ์ˆ˜์šฉ์˜์—ญ๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ  ์ž…๋‹ˆ๋‹ค.

  • ์ง€์—ญ์  ์ˆ˜์šฉ ์˜์—ญ(Local Receptive Fields)
    ์‹ ๊ฒฝ๋ง์˜ ๊ฐ ๋‰ด๋Ÿฐ์ด ์ด๋ฏธ์ง€ ์ „์ฒด๊ฐ€ ์•„๋‹Œ, ์ž‘์€ ์ผ๋ถ€์—๋งŒ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
    ์ด๋Š” ์ „์ฒด ํ”ฝ์…€์— ๋Œ€ํ•ด์„œ๊ฐ€ ์•„๋‹Œ ์˜ˆ์‹œ๋ฅผ ๋“ค๋ฉด 3 * 3 ํ”ฝ์…€์—๋งŒ ์ ์šฉ๋˜๋Š” ๋ฐฉ์‹์ธ๋ฐ์š”, ์ด๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์€ ์ด๋ฏธ์ง€์˜ ์ „์ฒด ๋งฅ๋ฝ๋ณด๋‹ค ์„ , ๋ชจ์„œ๋ฆฌ, ์งˆ๊ฐ๊ณผ ๊ฐ™์€ ์ง€์—ญ์ ์ธ ํŒจํ„ด์„ ๋จผ์ € ํ•™์Šตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ (Parameter Sharing) CNN์€ ์ด๋ฏธ์ง€ ์ „์ฒด๋ฅผ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด์„œ ์Šค์บ”ํ•˜๋Š” ๋А๋‚Œ์œผ๋กœ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.
    ๋”ฐ๋ผ์„œ, ํ•œ๋ฒˆ ์ด๋ฏธ์ง€์˜ ํŠน์ง•์„ ํ•™์Šตํ•˜๋ฉด, ์ด๋ฏธ์ง€์˜ ๋ชจ๋“  ์œ„์น˜์—์„œ ํ•ด๋‹น ํŠน์ง•์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ์ด๋ฅผ ํ†ตํ•ด์„œ ํ•™์Šตํ•  ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜๋ฅผ ๋งŽ์ด ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

CNN์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ ์•ž์„  ์•„์ด๋””์–ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, CNN์€ ๋‹ค์Œ 3๊ฐ€์ง€์˜ ๊ณ„์ธต์„ ์กฐํ•ฉํ•ด์„œ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  • ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต (Convolutional Layer) ํ•™์Šต ๊ฐ€๋Šฅํ•œ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฏธ์ง€์˜ ํŠน์ง•์„ ์ถ”์ถœํ•ด ๋ƒ…๋‹ˆ๋‹ค.
    edge, corner ๋“ฑ์„ ์ถ”์ถœํ•˜์—ฌ ์–ป๋Š” ๊ฒฐ๊ณผ๋ฌผ์„ ํŠน์ง• ๋งต(Feature Map) ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

  • ํ’€๋ง ๊ณ„์ธต (Pooling Layer) ์•ž์„œ ๋งŒ๋“  ๋งต์˜ ํฌ๊ธฐ๋ฅผ ์ค„์ด๋Š” ์š”์•ฝ๋‹จ๊ณ„ ์ž…๋‹ˆ๋‹ค.
    ์ตœ๋Œ€ ํ’€๋ง(Max Pooling)์€ ํŠน์ • ์˜์—ญํ—ค์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŠน์ง•(๊ฐ€์žฅ ํฐ ๊ฐ’)๋งŒ ๋‚จ๊ฒจ ๊ณ„์‚ฐ๋Ÿ‰์„ ์ค„์ด๊ณ , ๋ชจ๋ธ์ด ํŠน์ง•์˜ ๋ฏธ์„ธํ•œ ์œ„์น˜ ๋ณ€ํ™”์— ๋œ ๋ฏผ๊ฐํ•ด ํ•˜๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  • ์™„์ „ ์—ฐ๊ฒฐ ๊ณ„์ธต (Dense Layer) ์ถ”์ถœ๋œ ํŠน์ง•๋“ค์„ ์ข…ํ•ฉํ•˜์—ฌ ์ตœ์ข…์ ์œผ๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์–ด๋–ค ํด๋ž˜์Šค์— ์†ํ•˜๋Š”์ง€ ๋ถ„๋ฅ˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.


2. ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ†ตํ•œ ๋‚ด๋ถ€ ์ฝ”๋“œ ๋“ค์—ฌ๋‹ค ๋ณด๊ธฐ

์ด์ œ, ์•ž์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ, ์‹ค์ œ TensorFlow Keras ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์‹ค๊ฐํ•ด ๋ด…์‹œ๋‹ค.
๋‹ค์Œ์€, Keras๋กœ ๊ตฌํ˜„ํ•œ CNN ๋ชจ๋ธ ์•„ํ‚คํ…์ณ ์ž…๋‹ˆ๋‹ค.

import tensorflow as tf
from tensorflow import keras

# ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜ ์ •์˜
model = keras.Sequential([
    # Input: (28, 28, 1) ์ด๋ฏธ์ง€
    # ์ฒซ ๋ฒˆ์งธ Conv-Pool ๋ธ”๋ก
    keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1)),
    keras.layers.MaxPooling2D(pool_size=(2, 2)),
    
    # ๋‘ ๋ฒˆ์งธ Conv-Pool ๋ธ”๋ก
    keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
    keras.layers.MaxPooling2D(pool_size=(2, 2)),
    
    # ๋ถ„๋ฅ˜๊ธฐ(Classifier)
    keras.layers.Flatten(),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(10, activation="softmax"),
])

์ด์ œ, ์•ž์„œ ์„ค๋ช…ํ–ˆ๋˜ ์ด๋ก ์ด ์ด ์ฝ”๋“œ์— ์–ด๋–ป๊ฒŒ ๋…น์•„์žˆ๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.

  • ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต(Conv2D)
keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1))

์ด ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ, ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต์„ ํ˜•์„ฑ, ๋‹ค์Œ ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ง€์—ญ ์ˆ˜์šฉ์˜์—ญ

kernel_size(3, 3)์„ ํ†ตํ•ด์„œ ์ด๋ฏธ์ง€ ์ „์ฒด๊ฐ€ ์•„๋‹Œ 3 * 3 ํฌ๊ธฐ์˜ ์ž‘์€ ์˜์—ญ๋งŒ ๋ณด๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค.
์ด๋ ‡๊ฒŒ, ์ง€์—ญ์  ์ˆ˜์šฉ์˜์—ญ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค

  1. ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ 

Conv2D ๊ณ„์ธต์€ 32๊ฐœ์˜ ํ•„ํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
3 * 3ํ•„ํ„ฐ๋Š” ๊ณ ์œ ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ(๊ฐ€์ค‘์น˜)์„ธํŠธ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์ด ํ•„ํ„ฐ ํ•˜๋‚˜๊ฐ€ ์ด๋ฏธ์ง€ ์ „์ฒด๋ฅผ ์Šค์บ”ํ•ฉ๋‹ˆ๋‹ค.
๋งŒ์•ฝ, ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ ๊ฐ€ ์—†๋‹ค๋ฉด, ๊ฐ 3 * 3 ์œ„์น˜๋งˆ๋‹ค ๋ณ„๋„์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฏ€๋กœ ํฌ๊ธฐ๊ฐ€ ์—„์ฒญ ์ปค์ง‘๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ, ํŒŒ๋ผ๋ฏธํ„ฐ ๊ณต์œ  ๋•๋ถ„์—, ์ด ๊ฒฝ์šฐ์—์„œ (3 * 3 * 1 +1) * 32 = 320 ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋งŒ์œผ๋กœ ์ด๋ฏธ์ง€ ์ „์ฒด์˜ ํŠน์ง•์„ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ’€๋ง ๊ณ„์ธต(MaxPooling2D)
keras.layers.MaxPooling2D(pool_size=(2, 2))

์•ž์„  ํ•ฉ์„ฑ๊ณฑ ๊ณ„์ธต์ด ์ƒ์„ฑํ•œ ํŠน์ง•๋งต์„ 2* 2 ํฌ๊ธฐ์˜ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ์˜์—ญ์—์„œ ๊ฐ€์žฅ ํฐ ๊ฐ’๋งŒ ๋‚จ๊ธฐ๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด ๋งต ํฌ๊ธฐ๊ฐ€ ์ ˆ๋ฐ˜์œผ๋กœ ์ค„์–ด๋“œ๋Š” ๋‹ค์šด ์ƒ˜ํ”Œ๋ง์ด ์ผ์–ด๋‚˜๊ณ , ๊ณ„์‚ฐ ํšจ์œจ์„ฑ์ด ๋†’์•„์ ธ ๋ชจ๋ธ ํ•™์Šต์ด ๋” ๊ฐ€๋ฒผ์›Œ ์ง‘๋‹ˆ๋‹ค.

  • ์™„์ „ ์—ฐ๊ฒฐ ๊ณ„์ธต(Dense Layer)
keras.layers.Flatten()
keras.layers.Dense(10, activation="softmax")

์ตœ์ข… ๋ถ„๋ฅ˜๊ธฐ ์ด๋ฉฐ, ์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต ์ž…๋‹ˆ๋‹ค.

  1. keras.layers.Flatten()

์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต์€ 1์ฐจ์› ๋ฐฑํ„ฐ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—, Flastten ๊ณ„์ธต์ด ๋จผ์ € ๋“ค์–ด์™€ 2์ฐจ์› ํ˜•ํƒœ์˜ ํŠน์ง• ๋งต์„ ํ•œ ์ค„๋กœ ํŽผ์ณ์ค๋‹ˆ๋‹ค.

  1. keras.layers.Dense(10, activation="softmax")

์ด ์ฝ”๋“œ๊ฐ€ ์™„์ „์—ฐ๊ฒฐ๊ณ„์ธต์ด๋ฉฐ, ๋ณดํ†ต Dense Layer ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
ํŠน์ง•๋ฐฑํ„ฐ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ 10๊ฐœ์˜ ํด๋ž˜์Šค ์ค‘ ์–ด๋А ํด๋ž˜์Šค์— ํ• ๋‹นํ• ์ง€ ์ตœ์ข…์ ์œผ๋กœ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
activation="softmax"๋Š” ๊ฐ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์˜ˆ์ธก๊ฐ’์„ 0 ๊ณผ 1 ์‚ฌ์ด์˜ ํ™•๋ฅ ๊ฐ’์œผ๋กœ ํ•˜๊ฒŒ ํ•˜์—ฌ ๋ชจ๋“  ํ™•๋ฅ ์˜ ํ•ฉ์ด 1์ด ๋˜๋„๋ก ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.


3. ์ง์ ‘ CNN ๊ตฌํ˜„ํ•ด ๋ณด๊ธฐ

์ด์ œ, ์ง์ ‘ CNN ํ•™์Šต ์ฝ”๋“œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ๊ตฌํ˜„ํ•ด ๋ด…์‹œ๋‹ค.

1๋‹จ๊ณ„. ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ฐ ์ „์ฒ˜๋ฆฌ
๋ชจ๋ธ์ด ํ•™์Šตํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ค๋‹ˆ๋‹ค.
์ด๋ฒˆ์—”, ์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š” MNIST ์†๊ธ€์”จ ์ˆซ์ž ๋ฐ์ดํ„ฐ์…‹์„ ๊ฐ€์ ธ์™€ ์ ์ ˆํ•œ ํ˜•ํƒœ๋กœ ์ „์ฒ˜๋ฆฌ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

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

# Keras ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด MNIST ๋ฐ์ดํ„ฐ์…‹์„ ์†์‰ฝ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# ์ •๊ทœํ™”: ํ”ฝ์…€ ๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ 0~255์—์„œ 0~1 ์‚ฌ์ด๋กœ ์กฐ์ •ํ•˜์—ฌ ํ•™์Šต ์•ˆ์ •์„ฑ ๋ฐ ์†๋„๋ฅผ ๋†’์ž…๋‹ˆ๋‹ค.
x_train = x_train.astype("float32") / 255.0
x_test = x_test.astype("float32") / 255.0

# ์ฑ„๋„ ์ฐจ์› ์ถ”๊ฐ€: ํ‘๋ฐฑ ์ด๋ฏธ์ง€(์ฑ„๋„ 1)์˜ ์ฐจ์›์„ ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)

# ๋ ˆ์ด๋ธ” ์›-ํ•ซ ์ธ์ฝ”๋”ฉ: ์ˆซ์ž '5'๋ฅผ [0,0,0,0,0,1,0,0,0,0] ํ˜•ํƒœ์˜ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
num_classes = 10
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

2๋‹จ๊ณ„. ๋ชจ๋ธ ์ปดํŒŒ์ผ
๋ชจ๋ธ ์•„ํ‚คํ…์ณ๋ฅผ ์ •์˜ํ•˜๊ณ  ๋ชจ๋ธ์„ ์–ด๋–ป๊ฒŒ ํ•™์Šต์‹œํ‚ฌ์ง€์— ๋Œ€ํ•ด ์ •ํ•ฉ๋‹ˆ๋‹ค.

model = keras.Sequential([
    keras.Input(shape=(28, 28, 1)),  # ์ž…๋ ฅ ๋ ˆ์ด์–ด
    layers.Conv2D(32, kernel_size=(3, 3), activation="relu"),
    layers.MaxPooling2D(pool_size=(2, 2)),
    layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
    layers.MaxPooling2D(pool_size=(2, 2)),
    layers.Flatten(),
    layers.Dropout(0.5),
    layers.Dense(num_classes, activation="softmax")
])

model.compile(
    # ์†์‹ค ํ•จ์ˆ˜(Loss Function): ๋ชจ๋ธ์˜ ์˜ˆ์ธก์ด ์ •๋‹ต๊ณผ ์–ผ๋งˆ๋‚˜ ๋‹ค๋ฅธ์ง€ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.
    loss="categorical_crossentropy",
    # ์˜ตํ‹ฐ๋งˆ์ด์ €(Optimizer): ์†์‹ค์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
    optimizer="adam",
    # ํ‰๊ฐ€์ง€ํ‘œ(Metrics): ํ›ˆ๋ จ ๊ณผ์ •์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ง€ํ‘œ๋กœ, ์ •ํ™•๋„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    metrics=["accuracy"]
)

3๋‹จ๊ณ„. ๋ชจ๋ธ ํ•™์Šต ๋ฐ ํ‰๊ฐ€
model.fit()ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ ํ•™์Šต์„ ์‹œ์ž‘ํ•˜๊ณ , ํ•™์Šต์ด ๋๋‚œ ํ›„ model.evaluate()๋กœ ์ตœ์ข… ์„ฑ๋Šฅ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

batch_size = 128
epochs = 15

# ๋ชจ๋ธ ํ•™์Šต ์‹คํ–‰
history = model.fit(
    x_train, y_train,
    batch_size=batch_size,
    epochs=epochs,
    validation_data=(x_test, y_test)
)

# ํ•™์Šต ์™„๋ฃŒ ํ›„ ์ตœ์ข… ์„ฑ๋Šฅ ํ‰๊ฐ€
score = model.evaluate(x_test, y_test, verbose=0)
print(f"\nTest loss: {score[0]:.4f}")
print(f"Test accuracy: {score[1]:.4f}")

4๋‹จ๊ณ„. ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅํ•˜๊ธฐ ๋ชจ๋ธ์„ ์ €์žฅํ•˜๊ณ , ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

# ๋ชจ๋ธ์˜ ๊ตฌ์กฐ, ๊ฐ€์ค‘์น˜, ํ•™์Šต ์„ค์ •์„ ๋ชจ๋‘ '.keras' ํŒŒ์ผ ํ•˜๋‚˜์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
model.save("my_keras_model.keras")
print("\nModel saved to my_keras_model.keras")

์œ„ ๋‹จ๊ณ„๋ฅผ ์ „๋ถ€ ์ˆ˜ํ–‰ํ•œ ๋ชจ๋ธ์ด ์ง€๊ธˆ ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋“ค์–ด์žˆ๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ์ด์–ด์„œ, ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด ๋ณผ ๋–„, ์œ„ ์ฝ”๋“œ๋ฅผ์€ ์ง์ ‘ ์‹คํ–‰ํ•˜์ง€ ๋ง๊ณ , ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ฃผ์„ธ์š”!
๋งŒ์ผ, ์œ„ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ง์ ‘ ๋”ฅ๋Ÿฌ๋‹์„ ์‹œ์ผญ๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด, Files์˜ train.py๋ฅผ ์‹คํ–‰์‹œ์ผœ ์ฃผ์„ธ์š”!

5๋‹จ๊ณ„. ๋ชจ๋ธ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ ์•ž์„  ๋‹จ๊ณ„๋“ค์„ ๊ฑฐ์ณ ์™„์„ฑํ•œ ๋ชจ๋ธ์ด ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ํŽ˜์ด์ง€์— ์˜ฌ๋ผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด์ œ, ์ด ํ—ˆ๊น…ํŽ˜์ด์Šค ํŽ˜์ด์ง€์˜ ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์™€์„œ, ์ง์ ‘ ์‚ฌ์šฉํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
Files์˜ test.py๋ฅผ ์‹คํ–‰์‹œ์ผœ ๋ณด์„ธ์š”!! ์ง์ ‘ ์ค€๋น„ํ•œ ์ˆซ์ž ์†๊ธ€์”จ๋ฅผ ๋ชจ๋ธ์— ์ž…๋ ฅ์œผ๋กœ ๋„ฃ์œผ๋ฉด, ๊ทธ ์ˆซ์ž๊ฐ€ ์–ด๋–ค ์ˆซ์ž์ธ์ง€ ๋งž์ถฐ์ค„ ๊ฒ๋‹ˆ๋‹ค!!
์ฝ”๋“œ ์‹คํ–‰์„ ์œ„ํ•ด์„œ, ์ด ์ข…์†์„ฑ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
cmd ์ฐฝ์„ ์—ด๊ณ , ์ด ์ฝ”๋“œ๋ฅผ ๋„ฃ๊ณ  ์‹คํ–‰ํ•˜์—ฌ ๋จผ์ € ์ข…์†์„ฑ์„ ๋ฐ›์•„์ฃผ์„ธ์š”

pip install tensorflow huggingface_hub Pillow numpy

4. ๋‚˜๋งŒ์˜ CNN ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ

์ด์ œ, ์„ฑ๋Šฅ์„ ๋” ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•ด, ๋˜ ์›ํ•˜๋Š” ๋ชฉ์ ์— ๋งž๊ฒŒ ๋ชจ๋ธ์„ ์ˆ˜์ •ํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค.

  • ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” batch_size, epochs, ์˜ตํ‹ฐ๋‚˜์ด์ €์˜ leaarning_rate๋“ฑ์„ ์กฐํ•ฉํ•˜์—ฌ ์ตœ์ ํ™” ํ•ฉ๋‹ˆ๋‹ค.
    ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๊ฑด๋“œ๋ ค์„œ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
# ์˜ˆ: Adam ์˜ตํ‹ฐ๋งˆ์ด์ €์˜ ํ•™์Šต๋ฅ (learning_rate)์„ ์ง์ ‘ ์„ค์ •
optimizer = keras.optimizers.Adam(learning_rate=0.001)
model.compile(loss="categorical_crossentropy", optimizer=optimizer, metrics=["accuracy"])
  • ๋ชจ๋ธ ๊ตฌ์กฐ ๋ณ€๊ฒฝ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์„ ์œ„ํ•ด์„œ, Conv2D-MaxPooling2D ๋ธ”๋ก์„ ๋” ๊นŠ๊ฒŒ, Conv2D ๊ณ„์ธต์˜ ํ•„ํ„ฐ ์ˆ˜๋ฅผ ๋Š˜๋ ค ๋” ํ’๋ถ€ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
model = keras.Sequential([
    keras.layers.Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(28, 28, 1)),
    keras.layers.MaxPooling2D(pool_size=(2, 2)),
    # ๋ธ”๋ก ์ถ”๊ฐ€!
    keras.layers.Conv2D(64, kernel_size=(3, 3), activation="relu"),
    keras.layers.MaxPooling2D(pool_size=(2, 2)),
    # ํ•„ํ„ฐ ์ˆ˜๋ฅผ ๋Š˜๋ฆฐ ๋ธ”๋ก ์ถ”๊ฐ€!
    keras.layers.Conv2D(128, kernel_size=(3, 3), activation="relu"),
    keras.layers.MaxPooling2D(pool_size=(2, 2)),

    keras.layers.Flatten(),
    keras.layers.Dense(128, activation='relu'), # Dense ์ธต ์ถ”๊ฐ€
    keras.layers.Dropout(0.5),
    keras.layers.Dense(10, activation="softmax"),
])
  • ์ „์ดํ•™์Šต ์•„์ฃผ ํฐ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ํ•™์Šต๋œ ์ด๋ฏธ ๊ฐ•๋ ฅํ•œ ๋ชจ๋ธ์„ ๊ฐ€์ ธ์™€, ๊ทธ ๋ชจ๋ธ์ด ํ•™์Šตํ•œ ์ด๋ฏธ์ง€ ํŠน์ง•์ถ”์ถœ๋Šฅ๋ ฅ๋งŒ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์ž…๋‹ˆ๋‹ค.
    ์ ์€ ๋ฐ์ดํ„ฐ๋กœ๋„ ๋†’์€ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
# Keras์—์„œ ์ œ๊ณตํ•˜๋Š” ์‚ฌ์ „ ํ•™์Šต๋œ VGG16 ๋ชจ๋ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ (๋ถ„๋ฅ˜๊ธฐ๋Š” ์ œ์™ธ)
base_model = keras.applications.VGG16(
    weights='imagenet',  # ImageNet์œผ๋กœ ์‚ฌ์ „ ํ•™์Šต๋œ ๊ฐ€์ค‘์น˜ ์‚ฌ์šฉ
    include_top=False,   # ๋ถ„๋ฅ˜๊ธฐ(Dense ์ธต)๋Š” ์ œ์™ธ
    input_shape=(32, 32, 3) # VGG16์€ ์ตœ์†Œ 32x32 ์ปฌ๋Ÿฌ ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Œ
)

# ๋ถˆ๋Ÿฌ์˜จ ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋Š” ๊ณ ์ •(freeze)
base_model.trainable = False

# ์ƒˆ๋กœ์šด ๋ถ„๋ฅ˜๊ธฐ ์ถ”๊ฐ€
model = keras.Sequential([
    base_model,
    keras.layers.Flatten(),
    keras.layers.Dense(256, activation='relu'),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(10, activation='softmax') # ๋‚˜์˜ ๋ฌธ์ œ์— ๋งž๋Š” ์ถœ๋ ฅ์ธต
])

# ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ ๋ถ„๋ฅ˜๊ธฐ ๋ถ€๋ถ„๋งŒ ํ•™์Šต
model.compile(...)
model.fit(...)

5. ๊ฒฐ๋ก 

์˜ค๋Š˜์€, ์ด๋ ‡๊ฒŒ CNN ๋ชจ๋ธ์— ๋Œ€ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.
์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์— ํŠนํ™”๋œ CNN์€ ๋‚˜์ค‘์— ํŠธ๋žœ์Šคํฌ๋จธ ๋ชจ๋ธ์ด ๋‚˜์˜ค๋ฉด์„œ Vit๋ผ๋Š” ๋ชจ๋ธ์ด ๋งŒ๋“ค์–ด์ง€๋Š”๋ฐ ํฐ ๊ธฐ์—ฌ๋ฅผ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์ด๋ ‡๋“ฏ ๊ทผ๋ณธ ๋„˜์น˜๋Š” CNN ๋งŽ์ด ์‚ฌ๋ž‘ํ•ด ์ฃผ์„ธ์š”!!
๋‹ค์Œ์—๋Š” RNN๋ชจ๋ธ๋กœ ๋Œ์•„์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค
์˜ค๋Š˜๋„ ์ข‹์€ํ•˜๋ฃจ ๋ณด๋‚ด์„ธ์šฉ!!

Downloads last month
35
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support