본문 바로가기
[파이썬]/딥러닝

[딥러닝] 딥러닝 모델과 가중치 저장, 로드 및 예측수행

by sung min_Kim 2024. 1. 6.


 이번 글에서는 "딥러닝 모델과 가중치를 저장하고 로드하는 이유와 그 방법, 그리고 로드한 모델에 대한 예측 수행"에 대한 내용들을 살펴보려 한다. 
차례와 사용 툴 및 라이브러리는 아래와 같다.

 [차례]
 첫 번째, 가중치와 모델을 저장하고 불러오는 이유
 두 번째, 모델의 가중치 저장 및 불러오기
 세 번째, 모델 전체 저장 및 불러오기
 네 번째, 불러온 모델에 대한 예측 수행
 
 [사용 툴]

- Jupyter notebook(웹 기반 대화형 코딩 환경)
 
 [사용 라이브러리 및 모듈]

  • 연산 라이브러리: numpy

  • 딥러닝 라이브러리 및 모델: TensorFlow
    - tensorflow.keras: 사용자 친화적 인터페이스를 제공하는 TensorFlow의 고수준 API

 


가중치와 모델을 저장하고 불러오는 이유



 딥러닝 모델을 개발할 때, 모델을 저장하고 불러오는 기능은 매우 중요하다. 이 기능을 사용하면, 훈련된 모델을 재사용할 수 있고, 훈련 중인 모델의 상태를 보존하여 다른 환경으로 이전하는 것이 가능하다. 

 또한, 훈련 과정 중에 발생할 수 있는 예기치 않은 중단, 예를 들어 시스템의 오류나 사용자의 의도적 중단 등에 대비하여, 케라스는 'ModelCheckpoint' 콜백을 통해 주기적으로 모델의 가중치를 자동으로 저장할 수 있는 기능을 제공한다.

 이렇게 저장된 가중치는 훈련 과정을 나중에 다시 시작할 때 불러와서 사용할 수 있으며, 이 과정은 일반적으로 에러 없이 진행된다. 훈련을 재개할 때는 저장된 가중치를 이전에 훈련시킨 모델과 동일한 구조의 모델에 로드하여 훈련을 계속 진행할 수 있다.

 중요한 점은, 가중치를 저장하거나 불러올 때 모델의 구조가 일치해야 에러가 발생하지 않는다는 것이다. 모델의 구조가 변경되었다면, 적절히 수정된 구조에 맞게 가중치를 로드해야 한다. 따라서, 항상 모델의 구조와 가중치를 체계적으로 관리하는 것이 필수적이다.

 


모델의 가중치 저장 및 불러오기



1. 가중치 저장 및 불러오기
 1.1 가중치 저장하기


 모델을 훈련시킨 후, 'save_weights' 함수를 사용하여 모델의 가중치만을 저장할 수 있다. 이 방법은 모델 구조는 저장하지 않기 때문에, 가중치를 로드할 때 같은 구조의 모델이 필요하다. 저장 시 사용되는 확장자는 보통 '.h5'를 사용한다.

 '.h5' 확장자는 HDF5 파일 포맷을 나타낸다. HDF5는 대용량의 숫자 데이터(소수점 포함)를 효율적으로 저장하고 액세스 할 수 있는 기능을 제공하며, 데이터셋, 그룹, 속성 등의 복잡한 데이터 구조를 지원한다.

 단, 저장 경로의 폴더가 존재하지 않을 경우에는 에러를 유발하기 때문에, 저장하기 전에 폴더의 유무를 미리 확인하도록 하자.

model.save_weights("./model/model_weights.h5")

 

모델의 가중치 저장

 

1.2 가중치 불러오기

 
 저장된 가중치를 다시 불러오기 위해서는 'load_weights' 함수를 사용한다. 가중치를 로드하기 전에 저장 당시와 동일한 구조의 모델을 먼저 구성해야 한다. 가중치를 모델에 적용한 후에는, 모델을 바로 예측에 활용할 수 있다.

### 저장할 때와 동일한 구조의 모델 생성
model_weight = model_fn(keras.layers.Dropout(0.3))
model_weight.summary()

### 가중치 불러오기(적용하기)
model_weight.load_weights("./model/model_weights.h5")

 

가중치 저장 시 사용한 모델의 구조

 

가중치 로드 시 사용한 모델의 구조

 


모델 전체 저장 및 불러오기



1. 모델 저장 및 불러오기
1.1 모델 저장하기


 save 함수를 사용하면 모델의 구조, 가중치, 훈련 설정, 및 옵티마이저 상태까지 한 번에 저장할 수 있다. 이 방법은 모델을 완전히 재사용할 때 매우 유용하다.

model.save("./model/model_all.h5")

 

모델 전체 저장

 

1.2 모델 불러오기


 load_model 함수를 사용하면, save 함수로 저장된 모델 전체를 불러올 수 있다. 이 함수는 모델의 구조와 가중치뿐만 아니라, 컴파일 정보까지 함께 로드한다. 로드한 이후에는, 바로 예측으로 사용이 가능하다.

model_all = keras.models.load_model("./model/model_all.h5")
model_all.summary()

 

모델 불러오기

 


불러온 모델에 대한 예측 수행

 

1. 모델 예측
1.1 심층신경망(DNN) 모델 예측


 predict 함수를 사용하여, 불러온 심층신경망 모델에 대한 예측을 수행한다. 이는 모델이 학습한 패턴을 기반으로 새로운 데이터(검증 데이터)에 대한 예측을 하는 것이며, 학습된 패턴이 새로운 상황에 얼마나 잘 적용되는지를 검증하는 과정이다.

pred_data = model_all.predict(val_scaled)
pred_data[0]

 

각각의 데이터 샘플이 클래스에 속할 확률


 모델의 예측 결과를 살펴보면, 각 클래스(종속변수)에 속할 확률이 리스트 형태로 출력된 것을 볼 수 있다. 이 리스트에서 각 값은 데이터셋의 한 행, 즉 하나의 샘플이 특정 클래스(ex. 모자, 청바지 등)에 속할 확률을 나타내며, 이때의 인덱스 번호는 각 클래스의 고유 레이블과 일대일 매핑된다.

 가장 주목할 만한 점은, 리스트 내에서 '9.9996603e-01'이라는 가장 큰 확률 값이 인덱스 '8'에 위치해 있다는 것이다. 이는 모델이 해당 샘플이 클래스 '8'에 속할 확률을 약 99.996%로 예측하고 있다는 것을 나타내기 때문이다.

1.2 예측값과 실제값 비교


 앞선 분석을 바탕으로, pred_data의 첫 번째 데이터 샘플에 대한 예측에서 가장 높은 확률을 나타난 클래스는 '8'번임을 확인하였다. 이 예측이 실제로 클래스 8번에 속할 확률이 '99%' 이상인지를 검증하기 위해, 모델의 예측값과 실제 레이블인 val_target과 비교해 보려 한다.

 넘파이에서 제공하는 'argmax' 함수는 넘파이 배열의 각 요소 중 최댓값인 인덱스를 반환한다. 이 값을 기반으로 실제 레이블과 일치하는지를 확인함으로써 모델의 예측 정확도를 검증할 수 있다.

np.argmax(pred_data[0]), val_target[0]


 출력된 결과 '(8, 8)'는 모델의 예측이 정확했음을 보여준다. 이는 모델이 첫 번째 데이터 샘플(이미지)을 분석하고, 그 결과 해당 샘플이 8번 클래스(ex. 바지)에 속한다고 예측했음을 나타낸다. 이를 통해, 모델이 샘플에 대한 분류를 정확히 수행했다는 것을 알 수 있다.  

1.3 모든 예측 결과에 대한 인덱스 추출


  모델이 예측한 값들을 기반으로, 각 데이터 샘플에 대해 가장 높은 확률을 보이는 클래스(종속변수) 레이블을 확인하기 위해, 최대 확률값을 가진 인덱스를 추출하려 한다. 이 작업은 모델이 각 샘플을 어떤 클래스로 분류했는지를 파악하고, 실제 레이블과 얼마나 일치하는지를 평가하는 데 도움을 준다.

 argmax 함수에 'pred_data'와 'axis=1'을 인자로 전달함으로써, pred_data 배열의 각 행(각 데이터 샘플에 대한 예측 확률)에서 가장 큰 값(가장 높은 예측 확률을 가진 클래스)의 인덱스를 찾아서 배열로 반환한다. 

val_pred = np.argmax(pred_data, axis=1)
val_pred

예측 결과 중, 레이블에 속할 확률이 가장 높은 인덱스

 

val_target

실제 클래스 레이블을 나타내는 인덱스

 

1.4 예측값과 실제값의 일치도 분석


 모델의 예측 정확도를 더욱 면밀히 평가하기 위해, 예측된 값(val_pred)과 실제 레이블(val_target) 사이의 일치 여부를 살펴보려 한다. 이를 위해 '==' 연산자(동등 비교 연산자)를 활용하여 각 예측값이 실제 레이블과 일치하는지를 비교한다.

 이 비교 작업은 불리언 배열을 반환하는데, 넘파이는 'True'를 정수 '1'로, 'False'를 정수 '0'으로 해석하기 때문에, 넘파이의 sum 함수를 사용하면 이 불리언 배열에서 'True'의 총 개수, 즉 정확한 예측의 수를 쉽게 계산할 수 있다.

 일치율은 일치하는 예측의 개수를 전체 데이터 샘플의 수로 나눈 값으로 계산되며, 이는 모델이 얼마나 많은 샘플을 정확하게 분류했는지를 나타낸다. 반면, 불일치율을 예측이 틀린 경우의 수를 전체 샘플 수로 나눈 값으로, 모델이 잘못 분류한 샘플의 비율을 보여준다.

# 일치 개수
match = np.sum(val_pred == val_target)
 
# 불일치 개수
miss_match = np.sum(val_pred != val_target)

# 일치율
match_rate = match / len(val_target)

# 불일치율
miss_match_rate = miss_match / len(val_target)

match, miss_match, match_rate, miss_match_rate

 출력된 결과에 따르면, 이 모델은 총 12,000개의 데이터 샘플 중 약 88%에 해당하는 10,546개를 정확하게 분류해 냈다는 것을 알 수 있다. 반면에 잘못 분류된 샘플의 수는 1,454개로, 전체의 약 12%를 차지하는 것으로 나타났다.

 이를 통해 이 모델은 대체로 높은 정확도를 가지고 있지만, 다소 아쉬운 성능을 보이며, 예측 성능을 개선하기 위한 추가적인 방법들을 고려해야 할 필요가 있을 것으로 보인다.