본문 바로가기
A.I./TensorFlow

Keras 3 문서) About Keras 3

by 채소장사 2024. 9. 13.

Keras 3에 대하여

  • 원문 : About Keras 3
  • 케라스는 파이썬(Python)으로 작성된 딥러닝 API다.
    • 딥러닝을 위한 프로그램을 작성할 수 있는 고수준(high-level) API로서의 케라스는, 실제 실행되는 저수준(low-level) 프레임워크를 선택할 수 있다. (실행 백엔드 - JAX, TensorFlow, PyTorch)
  • 케라스의 특징은 다음과 같다.
    • 단순하다(Simple).
      • 그렇지만, 중요한 정보를 생략하거나 과도하게 단순화되어 있지는 않다.(not simplistic)
      • 따라서, 개발자는 중요한 문제에 초점을 맞출 수 있다.
    • 유연하다(Flexible).
      • 케라스는 점진적으로 복잡도를 높여가는 원칙을 적용한다.
      • 단순한 작업은 쉽고 빨라야하며, 더 나아간 복잡한 작업은 이미 배운 사항들로부터 구성할 수 있다.
    • 강력하다(Powerful).
      • 케라스는 산업 현장에서 쓰일 수 있는 성능과 확장성을 가진다.
      • 그래서 NASA, 유투브, Waymo와 같은 기업에서 사용되고 있다.

멀티 프레임워크 딥러닝 API

  • 다양한 프레임워크에서 사용될 수 있는 API로서, (앞서 언급한) JAX, TensorFlow, PyTorch 등의 프레임워크에서 실행될 수 있는 모듈을 케라스로 개발할 수 있다.
  • 언제나 당신이 학습한 모델의 최고의 성능을 얻을 수 있다.
    • 케라스의 벤치마크 실험 결과에 따르면, 일반적으로 JAX최고의 훈련(training) 및 추론(inference) 성능을 GPU, TPU, CPU의 하드웨어에서 보였다.
    • 그러나 이런 성능 결과는 모델마다 달라질 수 있으며,예를 들어 XLA를 사용하지 않은 텐서플로(non-XLA TensorFlow) 모델이 때때로 GPU에서 JAX보다 더 빠른 성능을 보이기도 하였다.
      참고) XLA(Accelerated Linear Algebra) : 머신러닝 성능 최적화를 위한 오픈소스 컴파일러
    • 코드를 고칠 필요 없이 모델이 최고 성능을 보일 수 있는 실행 백엔드를 동적으로 선택할 수 있다는 사실은 케라스를 통해 항상 가장 효율적으로 모델을 훈련하고 서빙할 수 있다는 것을 뜻한다.
  • 모델이 활용할 수 있는 딥러닝 생태계의 지평을 극대화 할 수 있다.
    • 케라스 모델은 Pytorch의 Module이나 JAX의 stateless function을 통해 생성될 수 있고(instantiated), TensorFlow의 SavedModel 포맷으로 저장되어 출력될 수 있다.
    • 즉, 케라스로 작성한 모델을 파이토치의 패키지 생태계로 사용하고, 텐서플로의 개발 및 서빙 도구화 결합할 수 있고, JAX로서 TPU를 통한 대규모 훈련을 시킬 수도 있다.
  • 오픈 소스 모델을 배포할 때, 훨씬 많은 사람들이 사용하게 할 수 있다.
    • 사전 훈련된 모델을 배포할 때, 케라스로 실행된 경우 사용자가 어떤 프레임워크를 사용하는 지에 관계없이 즉시 사용할 수 있다.
    • 즉, 해당 사용자의 프레임워크 사용에 제한을 받지 않는다.
  • 어떤 학습 데이터의 형태도 활용할 수 있다.
    • 케라스의 메소드인 fit(), evaluate(), predict()는 (텐서플로의) tf.data.Dataset 객체나 (파이토치의) DataLoader 객체 뿐만 아니라 넘파이 배열, Pandas의 데이터프레임과도 사용될 수 있다.

Keras 처음 사용해보기

  • 케라스의 핵심 데이터 구조는 layersmodels다.
  • 가장 단순한 형태의 모델은 레이어가 선형으로 쌓인 Sequential 모델이다.
  • 복잡한 구조의 모델을 구성하기 위해서는 케라스의 functional API를 사용하여 임의의 레이어 그래프를 만들거나, 서브 클래싱(subclassing)을 통해 모델을 바닥부터 직접 만들어야 한다.

선형(Sequential) 모델의 선언

import keras

model = keras.Sequential()

레이어를 쌓을 때에는 .add() 함수를 사용한다.

from keras import layers

model.add(layers.Dense(units=64, activation='relu'))
model.add(layers.Dense(units=10, activation='softmax'))

모델 작성이 끝나면, .compile() 함수를 통해 학습과정을 설정(configure)할 수 있다.

model.compile(loss='categorical_crossentroy',
		optimizer='sgd',
		metrics=['accuracy'])

필요하다면 옵티마이저(optimizer)에 대해 추가로 설정할 수 있다. 케라스의 철학은 간단한 것은 간단한 대로 두면서, 필요할 때는 사용자가 완전히 각 요소를 조정할 수 있게 하는 것이다. (서브클래싱으로 작성된 원본 코드에서도 수정을 통해 쉽게 확장할 수 있다.)

model.compile(loss=keras.losses.categorical_crossentropy,
	optimizer=keras.optimizers.SGD(learning_rate=0.01, momentum=0.9, nesterov=True)

이제 학습데이터를 배치로 구성하여, 반복적으로 훈련할 수 있다.

model.fit(x_train, y_train, epochs=5, batch_size=32)

테스트 데이터셋에서 손실과 평가 메트릭을 평가할 수 있다.

loss_and_metrics = model.evaluate(x_test, y_test, batch_size=128)

또는 새로운 입력 데이터에 대하여 예측할 수 있다.

classes = model.predict(x_test, batch_size=128)

위의 방식이 케라스를 사용하는 가장 기본적인 방법이다.


한편, 케라스는 매우 유연한 프레임워크로서 최신 연구 아이디어를 구현하기에도 적합하다. 아래의 커스텀 레이어로 구성된 예제는 여러 프레임워크 백엔드에서 실행될 수 있다.

import keras
from keras import ops

class TokenAndPositionEmbedding(keras.layer):
	def __init__(self, max_length, vocab_size, embed_dim):
            super().__init__()
            self.token_embed = self.add_weight(
                        shape=(vocab_size, embed_dim),
                        initializer="random_uniform",
                        trainable=True)
            self.position_embed = self.add_weight(
                        shape=(max_length, embed_dim),
                        initializer="random_uniform",
                        trainable=True)
            
	def call(self, token_ids):
    	    length = token_idx.shape[-1]
            positions = ops.range(0, length, dtype="int32")
            positions_vectors = ops.take(self.position_embed, positions, axis=0)

            token_ids = ops.cast(token_ids, dtype="int32")
            token_vectors = ops.take(self.token_embed, token_ids, axis=0)

            embed = token_vectors + positions_vectors

            power_sum = ops.sum(ops.square(embed), axis=-1, keepdims=True)
            return embed / ops.sqrt(ops.maximum(power_sum, 1e-7))

댓글