본문 바로가기
AI

[강의뼈대] minst cnn v2

by wildOjisan 2025. 7. 5.

이제부터 이미지 분류기 AI를 해볼건데, 우리가 직접 모델을 만들거에요.
어제까진 우리가 scikit 으로 간단한 숫자로 된 AI를 해봤어요.
scikit 인공지능들 모델들은 cpu에서도 돌아간다는 장점이 있지만,
숫자화된 데이터밖에 처리 못해요.

 

  • scikit은 숫자 데이터 (ex: 테이블 형태 데이터)에 강점
  • TensorFlow/Keras는 이미지, 오디오처럼 고차원 데이터 처리에 강점

이 부분을 한 문장 더 덧붙이면 좋겠어요:

“그래서 scikit-learn으로는 CNN 같은 복잡한 이미지 분류는 잘 못하고, TensorFlow/Keras를 써야 합니다.”



이번에는 tensorflow, keras 라는 프레임워크를 이용해서 이미지 분류를 해볼건데,
간단한 모델을 만들어 볼거에요.

모델 만드는걸 왜하지? 그거 시간낭비 아니야? 라고 생각하실수 있는데,
간단한 모델을 만들어 봄으로써 왜 사람들이 모델 만드는걸 기피 하는지,
왜 모델 연구하는 사람들이 인기가 없는지 알수도 있고,
또 모델을 만들면 컴퓨터가 어떻게 생각하는지 체험할 수 있다

 

 

그리고 재가 클래스 초반에 이런말 했던거 기억 나시나요?

 

이미지 분석은 실제 많이 쓰입니다.
의학에서 쓰이고, 해충 모니터링 쪽에서도 쓰입니다

 

 

그럼 이렇게 생각할수 있어요

"GPT 쓰면 되는데 왜 굳이 이런거 배워요?"

 

재가 클래스 초반에 했던만 기억 나시나요?

gpt 연동해서 서비스 만들었는데 회사에서 정책을 바꾼다

 

이러면 내가 회사에서 서비스 하고있는 사업이 다 날라가는 거에요

 

내가 모델을 빌드해서 돌릴수 있는것도 필요해요


--------------------------------------------------------------------------------------------

 

 

(x_train, y_train), (x_test, y_test) = mnist.load_data()

plt.figure(figsize=(15, 5))  # 가로_인치, 세로_인치. 디자인 선택

# For each digit (0 to 9)
for digit in range(10):
    # Get indices of images with this digit
    indices = (y_train == digit).nonzero()[0][:3]  # first 3 samples

    # Show each of the 3 samples
    for row in range(3):
        plt.subplot(3, 10, row * 10 + digit + 1)
        plt.imshow(x_train[indices[row]], cmap='gray')
        plt.title(f"{digit}" if row == 0 else "")
        plt.axis('off')

plt.suptitle("3 Samples per Digit (0~9)", fontsize=16)
plt.tight_layout()
plt.show()


AI를 학습시키려면 데이터가 있어야되죠?
근데 데이터를 이미 가져왔어요.

응? 난 데이터를 준비한적이 없는데? 라는 의문이 드시죠?
mnist 라는 모듈을 만든 사람이 AI 학습에 쓰라고 이미 만들어놓은 데이터가 있어요.
그게 
(x_train, y_train), (x_test, y_test) = mnist.load_data()
이 코드에요.

 

 

  • x_train: 학습에 쓸 이미지 6만 장
  • y_train: 각 이미지에 해당하는 숫자 라벨
  • x_test: 테스트에 쓸 이미지 1만 장
  • y_test: 테스트 이미지 라벨



그러면 이게 뭔 데이터인지 볼까요?

plt.figure(figsize=(15, 5))  # 가로_인치, 세로_인치. 디자인 선택

# For each digit (0 to 9)
for digit in range(10):
    # Get indices of images with this digit
    indices = (y_train == digit).nonzero()[0][:3]  # first 3 samples

    # Show each of the 3 samples
    for row in range(3):
        plt.subplot(3, 10, row * 10 + digit + 1)
        plt.imshow(x_train[indices[row]], cmap='gray')
        plt.title(f"{digit}" if row == 0 else "")
        plt.axis('off')

plt.suptitle("3 Samples per Digit (0~9)", fontsize=16)
plt.tight_layout()
plt.show()

이게 데이터가 대체 어떻게 생겨먹은지 matplot 을 이용해서 봅시다

아래 코드를 실행하면 0부터 9까지 숫자 이미지가 3장씩 나옵니다.

 

 

 

-----------------------------------------------------------------------------------------------

 

 

자, 여러분
뭐 이미지 가져왔네요 박수~~ 👏👏👏

이제 이 이미지를 컴퓨터가 계산할 수 있게 숫자로 변환해야 하는데요.

보통은:

  • 사진 파일을 불러오면 jpg나 png 같은 형태로 저장됩니다.
  • 이걸 numpy라는 “숫자 배열”로 바꿔줘야 딥러닝에 쓸 수 있어요.

그런데, 여기서 중요한 포인트!

MNIST 데이터셋을 만든 박사님들이 이미 다 numpy로 바꿔놨어요.

그래서 우리는 이미지가 numpy인지 아닌지 고민할 필요가 없습니다.
우리가 받은 x_train, x_test는 이미 이런 상태예요:

  • x_train.shape: (60000, 28, 28)
    • 6만 개 이미지
    • 각 이미지는 28x28 숫자
  • type(x_train): <class 'numpy.ndarray'>

즉, 이건 그냥 숫자가 쭈욱 들어있는 덩어리예요.
(이미 "컴퓨터가 바로 계산할 수 있게" 준비 완료!)

 

그러면 뭐 앞으로도 numpy 화 안한단 거란 소리에요?
아니요, 추후에 있을 예제에선 할건데, 지금은 모델 만든 다는게 뭔지 모르니깐 이밎 numpy 된걸로 시작 하자 이거에요

 

 

 

-----------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

자, 데이터가 준비됐으면 이제 AI를 학습시킬 모델이 필요하죠?

우리가 지금까지는 누가 만들어둔 모델을 갖다 쓰는 방식으로 해봤어요.
예를 들어 scikit-learn에서 RandomForestClassifier() 같은 걸 불러오면 이미 완성된 모델 뼈대를 쓰는 거였죠.

그런데 이번에는 다릅니다.

우리가 직접 모델을 처음부터 조립해서 만들어볼 거예요.


여기서 중요한 코드:

model = Sequential()
 

이게 뭘까요?

🏗️ 공장에 비유하면

  • model = Sequential()
    👉 “AI 공장을 지을 땅을 준비하는 거예요.”
    • 지금은 아무 기계도 없고, 벽도 없습니다.
    • 그냥 “여기다 공장을 짓겠다” 선언만 한 상태예요.

이렇게 빈 모델을 만든 다음에
한 층씩 기계를 넣고,
벨트를 깔고,
조립 라인을 연결하는 작업을 할 거예요.

예를 들어:

  • 첫 번째 층: 이미지 특징을 찾아주는 기계
  • 두 번째 층: 중요한 특징을 모아주는 기계
  • 마지막 층: 어떤 숫자인지 판단하는 기계

이런 식으로 여러 층을 차례로 쌓아야 모델이 완성됩니다.


💡 왜 ‘Sequential’인가?

이름이 Sequential(순차적) 인 이유:

층을 하나씩 순서대로 쌓는다

  • 앞에 있는 층에서 나온 결과가
  • 뒤에 있는 층으로 차례차례 흘러가요

 

 

 

-------------------------------------------------------------------------------------------------------------------------------------

 

 

 

자, 이제 모델에 첫 번째 기계를 설치할 거예요.

model.add(Conv2D(32, kernel_size=(3, 3), strides=(1, 1), padding='same',
                 activation='relu', input_shape=(28, 28, 1)))

 

와...뭔가 복잡해 보이죠? 걱정 마세요. 하나씩 풀어볼게요.


🧐 이게 뭐냐면?

Conv2D이미지를 분석하는 돋보기라고 생각하면 돼요.

  • 이미지를 작은 구역으로 잘라서
  • 그 구역에 어떤 특징이 있는지 찾아내요.

🔍 돋보기 예시

여기서 kernel_size=(3,3) 이라는 건:

3x3 크기의 돋보기를 만든다는 뜻이에요.

  • 가로 3칸, 세로 3칸
  • 총 9칸짜리 창으로 이미지를 들여다봅니다.

이 돋보기가 이미지를 한 칸씩, 한 칸씩 움직이면서 조사해요.


💡 그러면 뭘 찾나요?

컴퓨터는 사람처럼 "여기 숫자 2 있네!" 라고 못해요.
대신:

  • 선의 굵기
  • 곡선의 각도
  • 밝은 부분과 어두운 부분의 경계
    이런 걸 찾아냅니다.

이걸 **“특징”**이라고 부릅니다.


🧮 32라는 숫자의 의미

Conv2D(32, ...) 라는 건 이렇게 말하는 거예요:

“이 돋보기를 32개 만들어서
같은 이미지를 각각 다른 관점으로 살펴보겠다.”

그래서 하나의 이미지에서 32가지 다른 특징을 뽑아냅니다.

이 32개를 전문 용어로 필터라고도 부릅니다.
(필터=돋보기=특징 찾는 눈)


⚙️ input_shape=(28,28,1)

  • 이 모델에 처음 들어오는 이미지의 크기와 모양을 알려줘야 돼요.
    • 28 x 28 크기
    • 1은 “흑백”이라는 뜻입니다.
      • 컬러는 보통 (28,28,3)이에요.

 

자, 우리가 Conv2D(32, ...) 이렇게 하면
컴퓨터는 하나의 이미지를 32개 버전으로 바꿔서 저장합니다.

예를 들어:

  • 첫 번째 버전은 곡선을 잘 드러나게 하는 이미지
  • 두 번째 버전은 경계를 잘 보여주는 이미지
  • 세 번째 버전은 밝기 차이를 더 부각하는 이미지
  • 이렇게 32가지 방식으로 해석한 결과를 만듭니다.

그래서 Conv2D는 단순히 "이미지를 줄인다"가 아니라,

여러 가지 눈으로 이미지를 보는 과정이에요.


🔥 "그럼 5000 넣으면?"

예를 들어:

Conv2D(5000, kernel_size=(3,3), ...)
 

이렇게 하면:

  • 돋보기를 5000개 만들어요.
  • 각 돋보기는 다른 방식으로 이미지를 해석합니다.

결과적으로:

  • 한 장의 이미지를 넣으면
  • 내부적으로 5000개의 특징 이미지가 만들어져요.

🧠 중요한 포인트

여기서 “특징”이라는 개념은
사람이 “아, 이건 곡선!” 하고 바로 알아보는 것과 달라요.

컴퓨터가 찾는 특징은:

  • 곡선, 직선 같은 단순한 것뿐 아니라
  • 수학적으로 복잡하게 조합된 패턴
  • 사람은 보면서 “이게 뭐지?” 싶을 정도의 무늬

이런 것들도 포함됩니다.

 

자, 이제 activation='relu' 이 부분을 볼게요.

이건 무슨 뜻이냐면:

“이 층에서 계산된 숫자들을 이렇게 변형해서 다음으로 넘겨라”

라고 컴퓨터한테 알려주는 거예요.


🧠 왜 변형을 해요?

모델은 이미지를 보고

  • 선이 있나?
  • 밝은 부분이 있나?
    이런 걸 숫자로 계산합니다.

근데 이 숫자가:

  • 음수(-)일 수도 있고
  • 0일 수도 있고
  • 양수(+)일 수도 있어요.

🪄 ReLU는 뭐하냐?

ReLU는 간단하게 말하면:

0보다 작은 값은 다 0으로 만들고, 0보다 큰 값은 그대로 두는 기능

즉:

  • -5 → 0
  • -0.1 → 0
  • 3 → 3
  • 10 → 10

이렇게 바꿔줍니다.


🤔 왜 이런 걸 써요?

ReLU를 쓰면:

  • 계산이 훨씬 빨라지고
  • 음수 때문에 학습이 꼬이는 문제를 줄여줘요.
  • “활성화 함수”라고 부르는데,
    이건 모델이 더 잘 배우게 도와주는 필터 같은 역할을 합니다.

 

 

---------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

 

🙋 왜 크기를 줄여요?

사람 입장에서 생각해봅시다.

  • 사진을 줄이면 화나죠?
    • “화질 왜 떨어뜨려요?!”
    • “얼굴 잘 안 보이는데?!”
  • 근데 컴퓨터는 다릅니다.

컴퓨터는 이미지를 숫자 표로 보고 있어요.
숫자가 많다는 건:

  • 데이터가 많아진다는 뜻
  • 계산할 게 늘어난다는 뜻

그래서 컴퓨터는 큰 이미지를 주면 이렇게 생각합니다:

“으악... 숫자 너무 많아... 힘들어...”

😂 (여기서 학생들이 빵 터집니다.)


🧠 또 한 가지 중요한 이유

컴퓨터는 바보예요.
픽셀 하나하나에 너무 집착합니다.

예를 들어:

  • 회색1
  • 회색2
  • 회색3
  • 회색4
  • 회색5

사람이 보면 “그냥 다 회색”인데,
컴퓨터는:

“아냐! 얘네 다 달라!!”

이렇게 쓸데없는 구분을 하려고 해요.


🧽 그래서 MaxPooling은 뭐하냐?

이 과정을 거치면:

  • 비슷한 값들은 하나로 묶어주고
  • 덜 중요한 정보를 버리고
  • 크기를 줄여서 계산을 빠르게 합니다.

✅ 요약

MaxPooling은
이미지 크기를 줄이고, 불필요한 숫자 집착을 줄여주는 청소기 역할입니다.

 

 

 

 

-----------------------------------------------------------------------------------------------------------------

 

 

 

자, 모델에 또 뭔가를 추가합니다.

 

model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))

 

“어라? 또 Conv2D 나오고 또 MaxPooling 나오네요?”

맞아요. 이번에는 이전에 나온 특징들을 더 자세히 분석하려고 하는 거예요.


🔍 이번 Conv2D는 뭐가 다르냐?

첫 번째 Conv2D는:

  • “가장 기본적인 특징”을 찾았어요.
    • 모서리
    • 밝기 변화

두 번째 Conv2D는:

  • “첫 번째에서 찾아낸 특징들을 조합해서 더 복잡한 특징”을 찾아냅니다.
    • 예를 들어 숫자의 구부러진 모양
    • 여러 선이 교차하는 부분
    • 특정 패턴

🧐 64개의 돋보기?

이번에는:

“돋보기를 64개 만들어서, 64가지 다른 방식으로 이미지를 해석해라.”

라고 말하는 겁니다.

그래서:

  • 이전 층에서는 32개의 이미지가 나왔고
  • 이번 층에서는 각 이미지를 다시 64가지 특징으로 변환

즉, 점점 더 많은 정보를 뽑아내는 겁니다.


✂️ 그리고 또 줄인다?

맞아요.
MaxPooling2D(pool_size=(2,2))

“이제 다시 크기를 반으로 줄여라.”

계속 줄이는 이유:

  • 이미지가 커지면 계산이 느려져요.
  • 특징만 남기고 나머지 정보는 과감히 버리는 게 좋아요.
  • 크기를 줄여야 다음 단계(Dense 층)에서 다루기 쉽습니다.

요약
이 두 줄은 이렇게 해석하면 됩니다:

“첫 번째 돋보기에서 나온 특징들을 더 자세히 파고들어라(64가지 돋보기).
그리고 그걸 다시 반으로 줄여서 중요한 것만 남겨라.”


이렇게 층을 여러 번 쌓는 이유는:

간단한 특징 → 복잡한 특징 → 더 복잡한 특징

점점 더 고급스러운 정보를 찾아내기 위해서입니다.

 

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

🪄 Flatten 층

먼저 Flatten() 부터 볼게요.

model.add(Flatten())
 

이건 무슨 뜻이냐면:

“지금까지 여러 층에서 만들어진 특징 이미지들을
쫙 펴서 하나의 긴 줄로 만들겠다.”


🤔 왜 펴요?

지금까지 MaxPooling까지 거치면서 데이터 모양이 이렇게 되어 있어요:

(높이, 너비, 채널 수)
 

예를 들어:

  • 높이 = 7
  • 너비 = 7
  • 채널 = 64

이런 모양이죠.

그런데 Dense 층으로 보내려면:

css
복사편집
[숫자, 숫자, 숫자, 숫자, ....]

이렇게 일렬로 된 벡터여야 합니다.

Flatten은 쉽게 말해:

“그림판을 다 잘라서 한 줄로 쭉 이어붙여라.”

하는 역할이에요.


✅ 요약

Flatten = 이미지 데이터를 일렬 숫자 리스트로 바꾸는 층


🏢 Dense 층

이제 Dense 층을 추가합니다.

model.add(Dense(128, activation='relu'))
 

이건 CNN에서 뽑아낸 특징들을 바탕으로 실제 판단을 내리는 단계입니다.

Dense는 “완전히 연결된 층”이라고 해서:

  • 일렬로 나열된 숫자들을
  • 여러 개의 노드(뉴런)에 다 연결해서
  • 더 복잡한 패턴을 배우게 해요.

✨ 쉽게 비유하면?

  • 지금까지는 사진을 돋보기로 여러 번 훑어서
    • “여기 선이 있어요”
    • “여기 구부러진 부분 있어요”
    • “여기 밝은 점 있어요”
      이런 식으로 정보를 수집했어요.
  • Dense 층은 이제 그 정보를 종합해서
    • “이건 숫자 3이다!”
    • “이건 숫자 7이다!”
      라고 판단하는 단계입니다.

🤖 Dense 층의 숫자

Dense(128)은 이렇게 말하는 거예요:

“128개의 똑똑한 뉴런을 써서 정보를 분석해라.”

각 뉴런은 조금씩 다른 방식으로 데이터를 해석해서,
최종적으로 더 정확한 결론을 내리게 도와줍니다.


🧠 마지막 출력층

마지막에 또 Dense 층이 하나 더 있습니다.

model.add(Dense(10, activation='softmax'))
 

이 층은:

  • 숫자 0~9 중 어떤 숫자인지 확률을 출력합니다.
  • “softmax”는 각 숫자에 대한 “이게 맞을 확률”을 계산해서
    합이 1이 되도록 만듭니다.

예를 들어:

[0.02, 0.05, 0.01, 0.90, 0.01, 0.00, 0.00, 0.00, 0.00, 0.01]
 

이렇게 나오면:

  • “이 이미지는 숫자 3일 확률이 90%입니다.”

라고 컴퓨터가 판단합니다.


✅ 전체 요약
1️⃣ Conv2D: 돋보기로 특징 찾기
2️⃣ MaxPooling: 이미지 줄이고 데이터 줄이기
3️⃣ Flatten: 2차원 이미지를 1차원 벡터로 펴기
4️⃣ Dense(128): 특징을 종합해서 분석하기
5️⃣ Dense(10, softmax): 최종 숫자 예측하기

 

 

 

-----------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

자, 우리가 이렇게 쓰면:

Dense(5000)
 

무슨 뜻일까요?

“5000개의 똑똑한 뉴런을 만들어서 데이터를 분석해라.”

라고 하는 거예요.


🤔 그럼 뉴런 숫자를 크게 하면 더 똑똑할까?

그렇게만 되면 참 좋겠지만... 현실은 다릅니다.

뉴런 숫자를 무조건 크게 하면:

  • 모델이 너무 복잡해져서 학습이 잘 안 될 수도 있고
  • 컴퓨터 메모리가 왕창 차지되고
  • 오히려 성능이 떨어지는 경우도 많아요.

그래서 적당한 숫자를 쓰는 게 중요합니다.
보통 128, 256, 512 정도가 많이 쓰여요.


요약

“숫자만 크게 한다고 모델이 더 똑똑해지는 건 아니다.”


🧠 activation=’relu’ vs activation=’softmax’

여기서 많은 분들이 헷갈립니다.


Dense 층에서는:

  • activation='relu': 학습할 때 많이 쓰는 방식
    • 음수 값을 0으로 바꾸고
    • 양수 값은 그대로 둡니다.
    • 특징을 더 잘 구분하도록 도와줍니다.
  • activation='softmax': 최종 판단할 때 쓰는 방식
    • “어떤 숫자일지 확률”을 계산해서
    • 결과가 0~1 사이 값으로 나오게 합니다.
    • 결과 확률의 합이 1이 되도록 자동으로 맞춥니다.

그런데 어떤 분들이 물어봐요:

“Conv2D에서도 activation='relu' 쓴다면서요?
거기선 음수를 없앤다 그러고...
Dense에서는 학습 모드라고 그러고...
왜 말이 다 달라요???”

좋은 질문이에요.


핵심 이유

“각 함수가 다르기 때문이에요.”

  • Conv2D, Dense, MaxPooling2D 전부 역할과 내부 기능이 다릅니다.
  • activation 옵션은 “이 층에서 출력값을 어떻게 바꿀 거냐”만 정하는 겁니다.
  • relu 자체는 같은 방식으로 동작하지만, 그 층이 하는 역할이 달라요.
    • Conv2D: 이미지 특징 뽑기
    • Dense: 숫자 종합 판단

📢 비유

activation 함수는 요리의 “양념” 같은 거예요.

  • 같은 고추장을 써도:
    • 찌개에 넣으면 찌개 맛이 나고
    • 볶음에 넣으면 볶음 맛이 나는 것처럼
  • 같은 relu를 써도
    • Conv2D에 쓰면 “이미지 특징”이 나오고
    • Dense에 쓰면 “숫자 판단”이 나옵니다.

결론 요약
1️⃣ Dense(5000): 숫자가 커진다고 무조건 좋진 않다.
2️⃣ activation='relu': 음수 없애고 학습 쉽게 한다.
3️⃣ activation='softmax': 최종 결과를 확률로 만든다.
4️⃣ 각 층마다 역할과 내부 동작 방식이 다르다.

 

 

 

 

----------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

자, 이제 우리가 CNN 모델을 한 층 한 층 다 쌓았습니다.

이제 뭐 해야 되죠?
바로 학습(Training) 단계로 넘어갑니다.


🏋️ 학습 코드

history = model.fit(x_train, y_train,
                    validation_data=(x_test, y_test),
                    epochs=20,
                    batch_size=100)

이 코드 많이 봤죠?
model.fit() 이게 바로:

“모델아, 네가 똑똑해질 때까지 열심히 공부해라!”

라고 명령하는 코드입니다.


⚙️ 옵션 해석

  • x_train, y_train
    학습에 쓸 데이터와 정답
  • validation_data=(x_test, y_test)
    중간중간에 “잘 배우고 있나?” 확인용 테스트 데이터
  • epochs=20
    총 20번 반복해서 공부하기
  • batch_size=100
    한 번에 100개씩 데이터 묶어서 공부하기

💾 결과 저장

학습이 끝나면, 결과가 history에 뿅 하고 담깁니다.

이 안에는:

  • 매 epoch마다의 손실(loss)
  • 정확도(accuracy)
  • 검증 데이터 성능(validation loss, validation accuracy)

이런 데이터들이 다 들어 있어요.

나중에 그래프로 학습 과정을 그릴 때 이걸 씁니다.


🗃️ 모델 저장

그리고 이렇게 학습이 끝난 모델은 파일로 저장할 수 있어요.

final_model_name = f"my_mnist_{final_acc_percent}acc_{final_loss_percent}loss.h5"
model.save(final_model_name)

 

이건 뭐냐면:

“내가 땀 흘려서 공부시킨 모델을 하드에 저장해놔라.”

하는 거예요.

이렇게 저장하면:

  • 나중에 다시 불러와서 예측에 사용할 수 있고
  • 다른 사람에게 배포할 수도 있어요.

요약
1️⃣ model.fit() → 모델이 데이터 보고 학습
2️⃣ history → 학습 과정 기록
3️⃣ model.save() → 학습된 모델 파일로 저장


이제 진짜 AI가 스스로 손글씨 숫자를 구분할 수 있는 똑똑이 모델이 완성됐습니다! 🎉

 

 

 

 

 

전체 Colab 예측 코드

from keras.models import load_model
from google.colab import files
from PIL import Image
import numpy as np

# 1. 모델 불러오기
model_path = '/content/my_mnist_XXacc_XXloss.h5'
model = load_model(model_path)
print("모델 불러오기 완료!")

# 2. 사용자 이미지 업로드
uploaded = files.upload()
filename = list(uploaded.keys())[0]

# 3. 이미지 전처리
img = Image.open(filename).convert('L')
img = img.resize((28,28))
img_array = np.array(img)
img_array = img_array.astype('float32') / 255.0
input_data = img_array.reshape(1,28,28,1)

# 4. 예측
pred = model.predict(input_data)
predicted_class = np.argmax(pred)

print(f"예측 결과: 이 이미지는 '{predicted_class}' 숫자입니다!")

 

 

 

 

------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

여러분, 여기서 꼭 기억하셔야 할 게 하나 있어요.

지금까지 우리가 써본 것들은:

  • Keras라는 프레임워크에서
  • Sequential(), Conv2D(), Dense() 같은
    아주 기본적이고 대표적인 함수들입니다.

하지만 현실에서는:

  • 다른 프레임워크 (예: PyTorch, TensorFlow, MXNet 등)
  • 다른 함수와 계층 (예: ResNet, Inception, Transformer 등)
  • 또 다른 이름과 동작 방식

이렇게 수십, 수백 가지 다른 도구들이 있어요.


🤔 그래서 어떻게 해야 할까?

새로운 모델을 만들려면 단순히 코드만 바꾸는 게 아니라:

✅ 어떤 프레임워크를 쓸지 결정하고
✅ 거기서 제공하는 모듈과 함수의 특징을 분석하고
✅ 내가 만들고자 하는 목적에 맞게 조합과 실험을 반복해야 합니다.


예를 들어:

  • PyTorch에는 Keras와 함수 이름도 다르고 쓰는 방식도 달라요.
  • 어떤 함수는 “relu” 대신 “leaky_relu”를 쓰기도 합니다.
  • 다른 프레임워크에서는 pooling 방식조차 이름이 다르게 나옵니다.

요약

“지금 배운 것만이 전부가 아니고,
다른 도구, 다른 함수는 전부 다 이름과 성질이 다르다.”


그래서 여러분이 나중에 신규 모델을 만들거나 논문에 나오는 구조를 구현할 때는:

  • 어떤 모듈이 필요한지 조사하고
  • 사용법 문서를 꼼꼼히 읽고
  • 여러 번 실험하면서
    내 프로젝트에 맞는 방식을 찾아야 해요.

이 과정을 많이 겪어봐야

“아, 모델 만드는 게 이렇게 복잡하구나.”
하는 걸 몸으로 이해하게 됩니다.

 

 

여러분, 지금까지 배운 모델들은 CNN 계열이에요.

  • Conv2D(돋보기)로 특징을 찾고
  • MaxPooling으로 줄이고
  • Dense로 예측하고

이런 전통적인 이미지 분류 방식이죠.


그런데 꼭 이런 방식만 있는 건 아니에요.

✅ 예를 들어, 최근에 나온 Vision Transformer (ViT) 같은 모델은

“아예 Conv2D를 안 쓰고, Transformer라는 방식을 이미지에 적용”합니다.

이 방식은 사람이 이미지를 볼 때 중요한 부분에만 집중하는 것과 비슷하게 동작합니다.


🧠 이런 아이디어는 어디서 나올까요?

이게 바로 모델 연구 분야입니다.

모델 연구자들은 이렇게 고민해요:

1️⃣ 이미지를 볼 때,

“컴퓨터는 어떤 규칙으로 특징을 찾아야 하지?”

2️⃣ 이 과정을

“사람이 생각하는 방식으로 바꿔볼 수 없을까?”

3️⃣ 그러면 이 아이디어를

“수학식으로 표현하면 어떻게 될까?”

4️⃣ 이 수학식을

“파이썬 함수로 만들면 어떻게 짜야 하지?”

이런 과정을 수없이 반복해서 새로운 모델을 만듭니다.


예를 들어 ViT 모델은 이렇게 했어요:

  • CNN 대신 Self-Attention(자기 주의) 라는 수학 방식을 이미지에 적용
  • 작은 패치 단위로 이미지를 나눠서 처리
  • 더 유연하게 특징을 파악

요약

이미지 분류라고 해서 무조건 “특징 찾아서 줄이고”만 하는 건 아니다.

다른 방식으로도 분류할 수 있고,
이런 새로운 아이디어를 연구하고,
수학으로 표현하고,
코드로 만드는 게 모델 연구 분야다.


📢 마무리

여러분이 나중에 이쪽 분야에 관심이 생기면,

  • 논문을 읽고
  • 수식과 알고리즘을 분석하고
  • 새로운 모델을 구현해보는
    이런 “모델 연구”도 도전할 수 있어요.

'AI' 카테고리의 다른 글

VIT 원리  (0) 2025.07.09
파인튜닝 기본적인 골격  (1) 2025.07.09
[VGG16] 뼈대 강의  (0) 2025.07.08
[코드] 트랜스포머 vit 파인튜닝  (1) 2025.07.01
트랜스포머 finetuning  (0) 2025.06.29