- 훈련 데이터(입력 텐서, 출력 텐서) 정의
import numpy as np import tensorflow as tf # 별칭: tf from tensorflow.keras import layers # Layer 클래스들을 제공하는 모듈 from tensorflow import keras # keras 내부 dataset 사용 (train_image, train_label), (test_image, test_label) = keras.datasets.mnist.load_data() # data set의 형태, (data 갯수, height, width)
- Layer로 이루어진 네트워크 구조 정의
- Sequential 방식: 순서대로 쌓아올린 네트워크로 이뤄진 모델을 생성하는 방식
- Functional API 방식: 다양한 구조의 네트워크로 이뤄진 모델을 생성하는 방식
- Subclass 방식: 네트워크를 정의하는 클래스를 구현
- 구조 정의하면서 activation 함수도 정의
- unit마다 가중치 연산 이후 activation 함수 이용 후에 출력되기 때문에 이 때 정의
model = keras.Sequential() # Sequential(순차) 방식으로 모델 생성 # input Layer model.add(keras.layers.InputLayer((28,28))) # model.add(레이어 객체) # hidden Layer model.add(keras.layers.Flatten()) # 큰 의미 X, 밑에 layer들이 중요 model.add(keras.layers.Dense(256, activation='relu')) # unit 256개 model.add(keras.layers.Dense(128, activation='relu')) # unit 128개 # 여기서 unit = hidden layer의 node수 # 3. Output Layer 추가, 출력하고자 하는 결과 형태에 따라 unit 수 정함 model.add(keras.layers.Dense(10, activation='softmax')) # 모델 구조 확인 model.summary() # Output Shape = (데이터의 개수, 1차원 배열 개수) # ex) (None, 784), data 1개당 783개인 1차원 배열로 구성
- 모델 Compile(컴파일, 학습할 수 있는 상태로 만들어주는 작업)
- 모델 학습에 필요한 손실함수(Loss Function), 최적화기법(Optimizer, parameter update), 학습과정을 모니터링할 평가지표(Metrics) 선정
model.compile(optimizer='adam', # 최적화 함수, 여긴 adam이라는 알고리즘 사용, 웬만하면 adam 사용 loss='categorical_crossentropy', # loss함수 : cross-entropy metrics=['accuracy']) # 추가 평가지표 - 정확도
- 선정한 평가지표를 기준으로 평가 기준에 따라 Data 전처리
# one hot encdoing y_train = keras.utils.to_categorical(train_label)
- 원활한 학습 위해 Data 전철
# Feature scaling X_train = train_image.astype(np.float32) X_train /= 255.0
- 학습, 훈련
- 학습 데이터를 이용해 모델 학습
hist = model.fit(X_train, y_train, # input, output data epochs=10, # 전체 Train dataset을 몇번 반복해서 학습시킬지 정의, 1번 학습 = 1 epochs batch_size=100, # Train dataset을 학습시키는 단위로 한번에 지정한 개수(100)씩 끊어서 학습 # 100개 학습하고 검증, parameter 수정, 100개 학습, 검증, 수정 반복 # 여기서 한번 학습, 검증 수정하는 과정을 1 step이라 한다 validation_split=0.3 ) # hist에 history에 손실 함수 결과, 평가지표 결과 모두 저장된다 # hist.history['loss'], hist.history['val_loss'] # hist.history['accuracy'], hist.history['val_accuracy']
- 모델 그래프 시각화
from tensorflow.keras.utils import plot_model # to_file : 이용해 파일로 저장하면서 model의 형태 간략하게 볼 수 있다 plot_model(model, to_file='model_shapes.png', show_shapes=True)
- 평가
- test data set으로 평가
test_loss, test_acc = model.evaluate(X_test, y_test)
- 새로운 데이터 추론
predict(예측할 data의 feature) # 이용해 추론 # ex) result = model.predict(new_image)
- boston dataset 이용
- imort
import numpy as np import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers
- Data load
# data load (train_X, train_y), (test_X, test_y) = keras.datasets.boston_housing.load_data()
- hyperparameter 및 변수 선언
- 한곳에 몰아서 선언하는 것이 좋다
# hyperparameter LEARNING_RATE = 0.001 # 학습률 N_EPOCHS = 200 # epoch수 : train dataset 몇번 학습할지 횟수 N_BATCHS = 32 # batch size : 1 step당 몇개의 data를 학습할지(2의 거듭제곱한 값) # 사용할 변수를 미리 선언, 하이퍼파라미터 X N_TRAIN = train_X.shape[0] # train data의 개수 N_TEST = test_X.shape[0] # test data의 개수
- Data 전처리
- MLP는 선형모델을 기반으로 하므로 Feature Scaling
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_train = scaler.fit_transform(train_X) X_test = scaler.transform(test_X)
- Data set 생성
- val dataset 생략
# shuffle(N_TRAIN) : 입력 데이터의 개수를 입력했으므로 완전 셔플 # batch : remainder = True, 매번 같은 갯수로 학습하기 위해 train_dataset = tf.data.Dataset.from_tensor_slices((X_train, train_y))\ .shuffle(N_TRAIN)\ .batch(N_BATCHS, drop_remainder=True) # test set의 경우 굳이 섞을 필요 X test_dataset = tf.data.Dataset.from_tensor_slices((X_test, test_y)).batch(N_BATCHS)
- 모델 구현
- 모델 구조 함수
def create_housing_model(): model = keras.Sequential() # input layer 설정 2가지(여기서는 후자 사용) # 1. input layer를 별도로 지정 - model.add(Layers.InputLayer((13,))) InputLayer 생성 => Feature shape 을 지정 # 2. 첫번째 hidden layer추가하면서 input_shape 속성에 Feature에 shape을 지정 # hidden layer 추가 # DenseLayer : units = unit의 개수 # DenseLayer의 unit수는 점점 개수를 줄여나간다(관례적으로) model.add(layers.Dense(units=128, activation='relu', input_shape=(13,))) # 위에 설정 2번으로 input + hidden 경우라 보면된다 model.add(layers.Dense(units=64, activation='relu')) model.add(layers.Dense(units=32, activation='relu')) model.add(layers.Dense(units=16, activation='relu')) # output layer 추가 # 회귀문제에 대한 output layer - units : 추론한 결과값(정답)에 개수에 맞춘다 - 집값 1개 = unit 1개, activation = None : 지정하지않음 model.add(layers.Dense(units=1)) return model
- 모델 생성 및 컴파일
# 모델 생성 model = create_housing_model() # 모델 컴파일 model.compile(optimizer=keras.optimizers.Adam(learning_rate=LEARNING_RATE), loss='mse') # 모델 구조 확인 model.summary()
- 모델 학습
hist = model.fit(train_dataset, # train dataset(tf.data - batch+shuffle) - (X,y) epochs=N_EPOCHS, # epoch 수 validation_data=test_dataset) # validation dataset(tf.data) 제공 (X,y) # val set 없는 경우 train set으로만 loss 측정 # Dataset을 이용해서 학습할 경우 validation_split을 사용할 수 없다 # hist.history에 loss, val_loss 기록
- 모델 평가
loss = model.evaluate(test_dataset) print(loss, np.sqrt(loss))
- 모델 추론(새로운 데이터 이용)
pred = housing_model.predict(new_data)
- 모델 저장
model.save('models/boston_hosing_model')
- 모델 불러오기
housing_model = keras.models.load_model('models/boston_hosing_model') # 파일로 저장된 모델 불러옴
- Fashion MNIST Dataset 이용
- Data load 및 분리
import numpy as np import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers (train_image, train_label), (test_image, test_label) = keras.datasets.fashion_mnist.load_data()
- val data set 분리
from sklearn.model_selection import train_test_split train_image, val_image, train_label, val_label = train_test_split(train_image, train_label, test_size=0.2, stratify=train_label, random_state=0)
- hyperparameter 정의
LEARNING_RATE = 0.001 N_EPOCHS = 20 N_BATCHS = 100 # 각 데이터셋의 데이터 개수를 변수에 저장 N_TRAIN = train_image.shape[0] N_VAL = val_image.shape[0] N_TEST = test_image.shape[0]
- Data encoding
- label이 10개인 Data이므로 각 class별로 확률을 출력하도록 구현하기 위해 ohe실시
y_train = keras.utils.to_categorical(train_label) y_val = keras.utils.to_categorical(val_label) y_test = keras.utils.to_categorical(test_label)
- Data scaling
- map보다는 직접 나누는게 효율적
# 방법 1, 밑에처럼 직접 나눔 X_train = train_image.astype(np.float32) # /255 X_val = val_image.astype(np.float32) X_test = test_image.astype(np.float32) # 방법2, map 함수 사용 train_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))\ .map(lambda x, y : (x/255, y))\ .shuffle(N_TRAIN)\ .batch(N_BATCHS, drop_remainder=True) # 검증과 test의 경우 shuffle 필요 X val_dataset = tf.data.Dataset.from_tensor_slices((X_val, y_val)).map(lambda x, y:(x/255, y)).batch(N_BATCHS) test_dataset = tf.data.Dataset.from_tensor_slices((X_test, y_test)).map(lambda x, y:(x/255, y)).batch(N_BATCHS)
- 모델 함수 정의
def create_fashionmnist_model(): model = keras.Sequential() # Hidden Layer # 1. Flatten + input_shape을 지정해서 InputLayer를 추가 # model.add(Layers.InputLayer((28,28))) 밑에 Flatten 사용 함수와는 다른 방법 model.add(layers.Flatten(input_shape=(28,28))) # 입력데이터의 shape이 다차원 배열인 경우 1차원 배열로 변환 # (28,28) ==> (744), DenseLayer의 입력은 1차원이여야기에 # 다차원배열형태로 들어간 경우 내적을 할 때 데이터가 분산(행별로 unit에 들어감)되서 학습되는 경우 발생 # 하나의 입력이 여러 개의 입력으로 취급되어 여러 출력이 나와버리는 상황 발생(하나의 입력이 들어가고 하나의 출력이 나와야됨) model.add(layers.Dense(units=256, activation='relu')) model.add(layers.Dense(units=128, activation='relu')) model.add(layers.Dense(units=64, activation='relu')) # output layer : 다중분류, unit 수 = class 개수(여기서는 class 10개이므로), 각 unit이 class별 확률 출력, activation 함수 : softmax model.add(layers.Dense(units=10, activation='softmax')) return model
- 모델 생성 및 컴파일 확인
model = create_fashionmnist_model() # 컴파일 # 다중분류 : Loss = categorical_crossentropy(log loss) model.compile(optimizer=keras.optimizers.Adam(learning_rate=LEARNING_RATE), loss='categorical_crossentropy', metrics=['accuracy']) # 평가지표 : accuracy 추가(loss와 accuracy 두개를 검증/평가지표로 확인) # 모델 확인 model.summary()
- 모델 학습 및 평가
# 학습 hist = model.fit(train_dataset, epochs=N_EPOCHS, validation_data=val_dataset) # 평가 loss, accuracy = model.evaluate(test_dataset)
- 새로운 데이터 적용
- class가 10개인 경우의 분류이므로 모델 평가 결과를 10개의 class를 ndarray로 저장했던 형태의 index와 매칭시켜 출력해야한다
- 위스콘신 유방암 데이터셋 이용
- 다중 분류와의 차이점은 출력을 1개에 대한 경우로 할지 여러 개의 경우로 할지
- output layer의 activation function softmax, sigmoid 차이
- model loss 측정 categorical_corossentropy, binary_crossentropy 차이
- 두가지 방법
- pos일 확률을 출력
- pos와 neg일 확률 모두 출력, 다중 분류 처리방식으로 해결해야한다