2025.04.03
Part.11 텐서플로
Chapter 04. Modeling
- 05_subClass 모델링
- 06_subClass 모델링 ResNet 구현
SubClass 모델링
모델이란 것은 Input을 Output으로 만들어주는 수식, 함수이다.
해당 기능을 수행하는 두 가지 클래스가 tf.keras.layers.Layer 와 tf.keras.layers.Model 클래스이다.
두 가지 모두 연산을 추상화하는 것으로 동일한 역할을 하지만, tf.keras.layers.Model 클래스의 경우 모델을 저장하는 기능과 fit( ) 함수를 사용할 수 있다는 점에서 차이가 있다.
코드로 구현
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(7777)
tf.random.set_seed(7777)
Linear Regression을 Layer로 만들기
class LinearRegression(tf.keras.layers.Layer):
def __init__ (self, units) :
super(LinearRegression, self).__init__()
self.units = units
def build(self, input_shape):
self.w = self.add_weight(
shape=(input_shape[-1], self.units), #feature 개수, 마지막이 라벨인 형태 데이터셋
initializer = 'random_normal',
trainable = True
)
self.b = tf.Variable(0.0)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
가상데이터 만들어서 학습진행 해보기
W_true = np.array([3., 2., 4., 1.]).reshape(4, 1)
B_true = np.array([1.])
X = tf.random.normal((500, 4))
noise = tf.random.normal((500, 1))
y = np.matmul(X, W_true) + B_true + noise
opt = tf.keras.optimizers.SGD(learning_rate=0.03)
linear_layer = LinearRegression(1)
for epoch in range(100):
with tf.GradientTape() as tape:
y_hat = linear_layer(X)
loss = tf.reduce_mean(tf.square(y-y_hat))
grads = tape.gradient(loss, linear_layer.trainable_weights)
opt.apply_gradients(zip(grads, linear_layer.trainable_weights))
if epoch % 10 == 0:
print("epoch : {} | loss : {}".format(epoch, loss))
================================================================================
epoch : 0 | loss : 29.14101219177246
epoch : 10 | loss : 9.565739631652832
epoch : 20 | loss : 3.5630762577056885
epoch : 30 | loss : 1.7035540342330933
epoch : 40 | loss : 1.1216130256652832
epoch : 50 | loss : 0.9376567006111145
epoch : 60 | loss : 0.8789352774620056
epoch : 70 | loss : 0.8600139617919922
epoch : 80 | loss : 0.853861927986145
epoch : 90 | loss : 0.8518450260162354
print("학습된 가중치: ", linear_layer.w.numpy())
print("학습된 편향: ", linear_layer.b.numpy())
===============================================
>>
학습된 가중치: [[2.963016 ]
[1.9774277]
[3.9616776]
[1.0476018]]
학습된 편향: 0.8913154
SubClass로 ResNet 구현
import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Input, Dense, Conv2D, Flatten, Add, MaxPool2D
## Residual Block - Layer 구현
class ResidualBlock(tf.keras.layers.Layer): #tf.keras.layers.Layer 기능 상속
def __init__(self, filters=32, filter_match=False):
super(ResidualBlock, self).__init__() # 상속 레이어 내부 초기화
self.conv1 = Conv2D(filters, kernel_size=1, padding='same', activation='relu')
self.conv2 = Conv2D(filters, kernel_size=3, padding='same', activation='relu')
self.conv3 = Conv2D(filters, kernel_size=1, padding='same', activation='relu')
self.add = Add()
self.filters = filters
self.filter_match = filter_match
if filter_match:
self.conv_ext = Conv2D(filters, kernel_size=1, padding='same')
def call(self, inputs):
net1 = self.conv1(inputs)
net2 = self.conv2(net1)
net3 = self.conv3(net2)
if self.filter_match:
res = self.add([self.conv_ext(inputs), net3])
else:
res = self.add([inputs, net3])
return res
class ResNet(tf.keras.Model):
def __init__(self, num_classes):
super(ResNet, self).__init__()
self.conv1 = Conv2D(32, kernel_size=3, strides=2, padding='same', activation='relu')
self.maxp1 = MaxPool2D()
self.block1 = ResidualBlock(64, True)
# filter 개수 = 64, In/Out filter size 맞추기위한 True
self.block2 = ResidualBlock(64)
self.maxp2 = MaxPool2D()
self.flat = Flatten()
self.dense = Dense(num_classes)
def call(self, inputs):
x = self.conv1(inputs)
x = self.maxp1(x)
x = self.block1(x)
x = self.block2(x)
x = self.maxp2(x)
x = self.flat(x)
return self.dense(x)
ResNet Layer를 구성하는데 있어서 이전보다 훨씬 더 코드가 간단해진 것을 알 수 있다.
학습
model = ResNet(10)
이전과 같이 cifar10 데이터를 불러와서 학습해본다.
일단 이전 시간에는 DataLoader() 클래스 및 함수생성을 통해 바로 데이터를 불러오고, 전처리 및 학습하기를 진행했는데, 우선 이번에는 CIFAR 10이라는 데이터는 무슨 데이터가 저장되어 있는지 확인하고 나머지 전처리 및 학습을 진행한다.
(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()
X_train[1].shape
======================
>> (32, 32, 3)
cifar10_labels = {
0: "airplane",
1: "automobile",
2: "bird",
3: "cat",
4: "deer",
5: "dog",
6: "frog",
7: "horse",
8: "ship",
9: "truck"
}
plt.figure(figsize=(6, 7))
for i in range(9):
plt.subplot(3, 3, i+1)
plt.imshow(X_train[i])
plt.title(f"Label : {cifar10_labels[int(y_train[i])]}")
plt.axis('off')
plt.tight_layout()
plt.show()
위와 같이 사진데이터(컬러, 따라서 마지막 채널은 3)가 저장되어 있는 것을 알 수 있다.
이제 학습진행 한다.
## dataloader
class DataLoader():
def __init__(self):
(self.train_X, self.train_y), (self.test_X, self.test_y) = tf.keras.datasets.cifar10.load_data()
def validation_pixel_scale(self, x):
return 255 >= x.max() and 0 <= x.min()
def scale(self, x):
return (x/255.0).astype(np.float32)
def preprocess_dataset(self, dataset):
feature, target = dataset
validation_x = np.array([x for x in feature if self.validation_pixel_scale(x)])
validation_y = np.array([y for x, y in zip(feature, target) if self.validation_pixel_scale(x)])
scaled_x = np.array([self.scale(x) for x in validation_x])
one_hot_encoding_y = np.array([tf.keras.utils.to_categorical(y, num_classes=10) for y in validation_y])
return scaled_x, np.squeeze(one_hot_encoding_y, axis=1)
def get_train_dataset(self):
return self.preprocess_dataset((self.train_X, self.train_y))
def get_test_datasets(self):
return self.preprocess_dataset((self.test_X, self.test_y))
lr = 0.003
opt = tf.keras.optimizers.Adam(lr)
loss = tf.keras.losses.categorical_crossentropy
model.compile(optimizer=opt, loss=loss, metrics=['accuracy'])
hist = model.fit(train_X, train_y, epochs=40, batch_size=128, validation_data=(test_X, test_y))
plt.figure(figsize=(14, 8))
plt.subplot(121)
plt.plot(hist.history['accuracy'], lw=3)
plt.title('accuracy')
plt.grid("True")
plt.subplot(122)
plt.plot(hist.history['val_accuracy'], lw=3)
plt.title('val_accuracy')
plt.grid("True")
plt.show()
서서히 0.9에 수렴하려고 하는 것이 확인된다.
'Bootcamp_zerobase > Tensorflow' 카테고리의 다른 글
Evaluation : Tensorboard 및 모델의 Save, Load (0) | 2025.04.16 |
---|---|
Model 학습 : 텐서플로 모델학습 (fit( ) vs Training Logic) (0) | 2025.04.13 |
Functional Modeling : Functional API 및 간단한 ResNet 구현 (0) | 2025.04.03 |
CNN (VGGNet) #1 (0) | 2025.04.01 |
Tensorflow #3 : 딥러닝의 흐름, 간단한 Model 학습 (1) | 2025.03.31 |