diff --git a/assets/css/custom.css b/assets/css/custom.css index 44c0f501..b206634b 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -12,8 +12,8 @@ body:is(html[class~="dark"] *) { } .dark .highlight { - /* Background .bg { color:#cdd6f4;background-color:#1e1e2e; } - /* PreWrapper .chroma { color:#cdd6f4;background-color:#1e1e2e; } */ + /* Background */ .bg { color:#cdd6f4;background-color:#1e1e2e; } + /* PreWrapper */ .chroma { color:#cdd6f4;background-color:#1e1e2e; } /* Other */ .chroma .x { } /* Error */ .chroma .err { color:#f38ba8 } /* CodeLine */ .chroma .cl { } @@ -101,8 +101,8 @@ body:is(html[class~="dark"] *) { } .highlight { - /* Background .bg { color:#272822;background-color:#fafafa; } - /* PreWrapper .chroma { color:#272822;background-color:#fafafa; } + /* Background */ .bg { color:#272822;background-color:#f3f3f3; } + /* PreWrapper */ .chroma { color:#272822;background-color:#f3f3f3; } /* Other .chroma .x { } */ /* Error */ .chroma .err { color:#960050;background-color:#1e0010 } /* CodeLine .chroma .cl { } */ diff --git a/content/english/docs/guides/distributed_training_with_jax/_index.md b/content/english/docs/guides/distributed_training_with_jax/_index.md index 6490427e..2ba9aacb 100644 --- a/content/english/docs/guides/distributed_training_with_jax/_index.md +++ b/content/english/docs/guides/distributed_training_with_jax/_index.md @@ -123,7 +123,9 @@ In practice, the process of synchronously updating the weights of the model repl To do single-host, multi-device synchronous training with a Keras model, you would use the `jax.sharding` features. Here's how it works: - We first create a device mesh using `mesh_utils.create_device_mesh`. -- We use `jax.sharding.Mesh`, `jax.sharding.NamedSharding` and `jax.sharding.PartitionSpec` to define how to partition JAX arrays. - We specify that we want to replicate the model and optimizer variables across all devices by using a spec with no axis. - We specify that we want to shard the data across devices by using a spec that splits along the batch dimension. +- We use `jax.sharding.Mesh`, `jax.sharding.NamedSharding` and `jax.sharding.PartitionSpec` to define how to partition JAX arrays. + - We specify that we want to replicate the model and optimizer variables across all devices by using a spec with no axis. + - We specify that we want to shard the data across devices by using a spec that splits along the batch dimension. - We use `jax.device_put` to replicate the model and optimizer variables across devices. This happens once at the beginning. - In the training loop, for each batch that we process, we use `jax.device_put` to split the batch across devices before invoking the train step. diff --git a/content/english/docs/guides/distributed_training_with_tensorflow/_index.md b/content/english/docs/guides/distributed_training_with_tensorflow/_index.md index 8c4018b0..1af6fedc 100644 --- a/content/english/docs/guides/distributed_training_with_tensorflow/_index.md +++ b/content/english/docs/guides/distributed_training_with_tensorflow/_index.md @@ -231,7 +231,7 @@ Restoring from ./ckpt/ckpt-1.keras {{% /details %}} -## [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) performance tips +## [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) performance tips {#tfdata} When doing distributed training, the efficiency with which you load data can often become critical. Here are a few tips to make sure your [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) pipelines run as fast as possible. diff --git a/content/english/docs/guides/distributed_training_with_torch/_index.md b/content/english/docs/guides/distributed_training_with_torch/_index.md index 1645e5ca..5febfca8 100644 --- a/content/english/docs/guides/distributed_training_with_torch/_index.md +++ b/content/english/docs/guides/distributed_training_with_torch/_index.md @@ -146,7 +146,11 @@ In practice, the process of synchronously updating the weights of the model repl To do single-host, multi-device synchronous training with a Keras model, you would use the `torch.nn.parallel.DistributedDataParallel` module wrapper. Here's how it works: - We use `torch.multiprocessing.start_processes` to start multiple Python processes, one per device. Each process will run the `per_device_launch_fn` function. -- The `per_device_launch_fn` function does the following: - It uses `torch.distributed.init_process_group` and `torch.cuda.set_device` to configure the device to be used for that process. - It uses `torch.utils.data.distributed.DistributedSampler` and `torch.utils.data.DataLoader` to turn our data into a distributed data loader. - It also uses `torch.nn.parallel.DistributedDataParallel` to turn our model into a distributed PyTorch module. - It then calls the `train_model` function. +- The `per_device_launch_fn` function does the following: + - It uses `torch.distributed.init_process_group` and `torch.cuda.set_device` to configure the device to be used for that process. + - It uses `torch.utils.data.distributed.DistributedSampler` and `torch.utils.data.DataLoader` to turn our data into a distributed data loader. + - It also uses `torch.nn.parallel.DistributedDataParallel` to turn our model into a distributed PyTorch module. + - It then calls the `train_model` function. - The `train_model` function will then run in each process, with the model using a separate device in each process. Here's the flow, where each step is split into its own utility function: diff --git a/content/english/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md b/content/english/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md index e60eae6a..9ef970d0 100644 --- a/content/english/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md +++ b/content/english/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md @@ -8,7 +8,7 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -**Authors:** [fchollet](https://twitter.com/fchollet), [lukewood](https://twitter.com/luke_wood_ml), [divamgupta](https://github.com/divamgupta) +**{{< t f_author >}}** [fchollet](https://twitter.com/fchollet), [lukewood](https://twitter.com/luke_wood_ml), [divamgupta](https://github.com/divamgupta) **{{< t f_date_created >}}** 2022/09/25 **{{< t f_last_modified >}}** 2022/09/25 **{{< t f_description >}}** Generate new images using KerasCV's Stable Diffusion model. diff --git a/content/english/docs/guides/keras_tuner/custom_tuner/_index.md b/content/english/docs/guides/keras_tuner/custom_tuner/_index.md index 7e6b8c86..120c9cc7 100644 --- a/content/english/docs/guides/keras_tuner/custom_tuner/_index.md +++ b/content/english/docs/guides/keras_tuner/custom_tuner/_index.md @@ -8,7 +8,7 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Tom O'Malley, Haifeng Jin +**{{< t f_author >}}** Tom O'Malley, Haifeng Jin **{{< t f_date_created >}}** 2019/10/28 **{{< t f_last_modified >}}** 2022/01/12 **{{< t f_description >}}** Use `HyperModel.fit()` to tune training hyperparameters (such as batch size). diff --git a/content/english/docs/guides/keras_tuner/distributed_tuning/_index.md b/content/english/docs/guides/keras_tuner/distributed_tuning/_index.md index 0e6d2c2e..acd92885 100644 --- a/content/english/docs/guides/keras_tuner/distributed_tuning/_index.md +++ b/content/english/docs/guides/keras_tuner/distributed_tuning/_index.md @@ -8,7 +8,7 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Tom O'Malley, Haifeng Jin +**{{< t f_author >}}** Tom O'Malley, Haifeng Jin **{{< t f_date_created >}}** 2019/10/24 **{{< t f_last_modified >}}** 2021/06/02 **{{< t f_description >}}** Tuning the hyperparameters of the models with multiple GPUs and multiple machines. @@ -60,7 +60,7 @@ export KERASTUNER_ORACLE_PORT="8000" python run_tuning.py ``` -### Data parallelism with [`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute) +### Data parallelism with [`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute) {#tfdistribute} KerasTuner also supports data parallelism via [tf.distribute](https://www.tensorflow.org/tutorials/distribute/keras). Data parallelism and distributed tuning can be combined. For example, if you have 10 workers with 4 GPUs on each worker, you can run 10 parallel trials with each trial training on 4 GPUs by using [tf.distribute.MirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy). You can also run each trial on TPUs via [tf.distribute.TPUStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/experimental/TPUStrategy). Currently [tf.distribute.MultiWorkerMirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/experimental/MultiWorkerMirroredStrategy) is not supported, but support for this is on the roadmap. diff --git a/content/english/docs/guides/keras_tuner/failed_trials/_index.md b/content/english/docs/guides/keras_tuner/failed_trials/_index.md index ef11f4f0..5a95f61a 100644 --- a/content/english/docs/guides/keras_tuner/failed_trials/_index.md +++ b/content/english/docs/guides/keras_tuner/failed_trials/_index.md @@ -8,7 +8,7 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -**Authors:** Haifeng Jin +**{{< t f_author >}}** Haifeng Jin **{{< t f_date_created >}}** 2023/02/28 **{{< t f_last_modified >}}** 2023/02/28 **{{< t f_description >}}** The basics of fault tolerance configurations in KerasTuner. diff --git a/content/english/docs/guides/keras_tuner/tailor_the_search_space/_index.md b/content/english/docs/guides/keras_tuner/tailor_the_search_space/_index.md index 308247a7..ea331206 100644 --- a/content/english/docs/guides/keras_tuner/tailor_the_search_space/_index.md +++ b/content/english/docs/guides/keras_tuner/tailor_the_search_space/_index.md @@ -8,7 +8,7 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -**Authors:** Luca Invernizzi, James Long, Francois Chollet, Tom O'Malley, Haifeng Jin +**{{< t f_author >}}** Luca Invernizzi, James Long, Francois Chollet, Tom O'Malley, Haifeng Jin **{{< t f_date_created >}}** 2019/05/31 **{{< t f_last_modified >}}** 2021/10/27 **{{< t f_description >}}** Tune a subset of the hyperparameters without changing the hypermodel. diff --git a/content/english/docs/guides/making_new_layers_and_models_via_subclassing/_index.md b/content/english/docs/guides/making_new_layers_and_models_via_subclassing/_index.md index 81cf1bad..42e09be5 100644 --- a/content/english/docs/guides/making_new_layers_and_models_via_subclassing/_index.md +++ b/content/english/docs/guides/making_new_layers_and_models_via_subclassing/_index.md @@ -244,7 +244,7 @@ All layers you've seen so far in this guide work with all Keras backends. The `keras.ops` namespace gives you access to: - The NumPy API, e.g. `ops.matmul`, `ops.sum`, `ops.reshape`, `ops.stack`, etc. -- Neural networks-specific APIs such as `ops.softmax`, `ops`.conv`,`ops.binary_crossentropy`,`ops.relu\`, etc. +- Neural networks-specific APIs such as `ops.softmax`, `ops.conv`, `ops.binary_crossentropy`, `ops.relu`, etc. You can also use backend-native APIs in your layers (such as [`tf.nn`](https://www.tensorflow.org/api_docs/python/tf/nn) functions), but if you do this, then your layer will only be usable with the backend in question. For instance, you could write the following JAX-specific layer using `jax.numpy`: diff --git a/content/english/docs/guides/migrating_to_keras_3/_index.md b/content/english/docs/guides/migrating_to_keras_3/_index.md index 001aed3e..130656fc 100644 --- a/content/english/docs/guides/migrating_to_keras_3/_index.md +++ b/content/english/docs/guides/migrating_to_keras_3/_index.md @@ -751,7 +751,12 @@ Your models may include a custom `train_step()` or `test_step()` method, which r In some cases, you might be able to simply override the `Model.compute_loss()` method and make it fully backend-agnostic, instead of overriding `train_step()`. Here's an example of a layer with a custom `compute_loss()` method which works across JAX, TensorFlow, and PyTorch: -`class MyModel(keras.Model): def compute_loss(self, x=None, y=None, y_pred=None, sample_weight=None): loss = keras.ops.sum(keras.losses.mean_squared_error(y, y_pred, sample_weight)) return loss` +```python +class MyModel(keras.Model): + def compute_loss(self, x=None, y=None, y_pred=None, sample_weight=None): + loss = keras.ops.sum(keras.losses.mean_squared_error(y, y_pred, sample_weight)) + return loss +``` If you need to modify the optimization mechanism itself, beyond the loss computation, then you will need to override `train_step()`, and implement one `train_step` method per backend, like below. diff --git a/content/english/docs/guides/serialization_and_saving/_index.md b/content/english/docs/guides/serialization_and_saving/_index.md index 57956cb9..79345f99 100644 --- a/content/english/docs/guides/serialization_and_saving/_index.md +++ b/content/english/docs/guides/serialization_and_saving/_index.md @@ -8,7 +8,7 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Neel Kovelamudi, Francois Chollet +**{{< t f_author >}}** Neel Kovelamudi, Francois Chollet **{{< t f_date_created >}}** 2023/06/14 **{{< t f_last_modified >}}** 2023/06/30 **{{< t f_description >}}** Complete guide to saving, serializing, and exporting models. diff --git a/content/english/docs/guides/training_with_built_in_methods/_index.md b/content/english/docs/guides/training_with_built_in_methods/_index.md index 22d19f9f..f9c534a0 100644 --- a/content/english/docs/guides/training_with_built_in_methods/_index.md +++ b/content/english/docs/guides/training_with_built_in_methods/_index.md @@ -502,7 +502,7 @@ model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1) {{% /details %}} -## Training & evaluation using [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) Datasets +## Training & evaluation using [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) Datasets {#tfdata} In the past few paragraphs, you've seen how to handle losses, metrics, and optimizers, and you've seen how to use the `validation_data` and `validation_split` arguments in `fit()`, when your data is passed as NumPy arrays. diff --git a/content/english/docs/guides/transfer_learning/_index.md b/content/english/docs/guides/transfer_learning/_index.md index dbe07af2..41ac1e25 100644 --- a/content/english/docs/guides/transfer_learning/_index.md +++ b/content/english/docs/guides/transfer_learning/_index.md @@ -78,8 +78,6 @@ non_trainable_weights: 0 {{% /details %}} -## Available guides - In general, all weights are trainable weights. The only built-in layer that has non-trainable weights is the `BatchNormalization` layer. It uses non-trainable weights to keep track of the mean and variance of its inputs during training. To learn how to use non-trainable weights in your own custom layers, see the [guide to writing new layers from scratch]({{< relref "/docs/guides/making_new_layers_and_models_via_subclassing" >}}). **Example: the `BatchNormalization` layer has 2 trainable weights and 2 non-trainable weights** diff --git a/content/english/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md b/content/english/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md index 2ee4a6fb..80975b10 100644 --- a/content/english/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md +++ b/content/english/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md @@ -399,7 +399,7 @@ Time taken: 43.49s {{% /details %}} -## Speeding-up your training step with [`tf.function`](https://www.tensorflow.org/api_docs/python/tf/function) +## Speeding-up your training step with [`tf.function`](https://www.tensorflow.org/api_docs/python/tf/function) {#tffunction} The default runtime in TensorFlow is eager execution. As such, our training loop above executes eagerly. diff --git a/content/english/docs/guides/writing_your_own_callbacks/_index.md b/content/english/docs/guides/writing_your_own_callbacks/_index.md index 530512ed..e2663acb 100644 --- a/content/english/docs/guides/writing_your_own_callbacks/_index.md +++ b/content/english/docs/guides/writing_your_own_callbacks/_index.md @@ -8,7 +8,7 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Rick Chao, Francois Chollet +**{{< t f_author >}}** Rick Chao, Francois Chollet **{{< t f_date_created >}}** 2019/03/20 **{{< t f_last_modified >}}** 2023/06/25 **{{< t f_description >}}** Complete guide to writing new Keras callbacks. diff --git a/content/korean/docs/guides/custom_train_step_in_jax/_index.md b/content/korean/docs/guides/custom_train_step_in_jax/_index.md index 8e581def..4ffd68c7 100644 --- a/content/korean/docs/guides/custom_train_step_in_jax/_index.md +++ b/content/korean/docs/guides/custom_train_step_in_jax/_index.md @@ -1,6 +1,6 @@ --- -title: Customizing what happens in `fit()` with JAX -linkTitle: Customizing fit() with Jax +title: JAX에서의 `fit()` 동작을 커스터마이즈 +linkTitle: JAX fit() 커스터마이즈 toc: true weight: 5 type: docs @@ -11,35 +11,47 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2023/06/27 **{{< t f_last_modified >}}** 2023/06/27 -**{{< t f_description >}}** Overriding the training step of the Model class with JAX. +**{{< t f_description >}}** JAX를 사용하여 모델 클래스의 트레이닝 단계를 재정의. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/custom_train_step_in_jax.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/custom_train_step_in_jax.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -When you're doing supervised learning, you can use `fit()` and everything works smoothly. +지도 학습을 할 때는 `fit()`을 사용하면, 모든 것이 매끄럽게 작동합니다. -When you need to take control of every little detail, you can write your own training loop entirely from scratch. +하지만 모든 세부 사항을 완전히 제어해야 할 경우, +처음부터 끝까지 직접 당신만의 트레이닝 루프를 작성할 수 있습니다. -But what if you need a custom training algorithm, but you still want to benefit from the convenient features of `fit()`, such as callbacks, built-in distribution support, or step fusing? +그렇지만 커스텀 트레이닝 알고리즘이 필요하면서도, +콜백, 빌트인 분산 지원, 스텝 퓨징(step fusing)과 같은, +`fit()`의 편리한 기능을 그대로 활용하고 싶다면 어떻게 해야 할까요? -A core principle of Keras is **progressive disclosure of complexity**. You should always be able to get into lower-level workflows in a gradual way. You shouldn't fall off a cliff if the high-level functionality doesn't exactly match your use case. You should be able to gain more control over the small details while retaining a commensurate amount of high-level convenience. +Keras의 핵심 원칙 중 하나는 **점진적인 복잡성 공개**입니다. +항상 점진적으로 더 낮은 레벨의 워크플로로 진입할 수 있어야 합니다. +높은 레벨의 기능이 정확히 사용 사례에 맞지 않더라도, 갑작스럽게 어려움에 부딪혀서는 안 됩니다. +높은 레벨의 편리함을 유지하면서, 작은 세부 사항에 대한 제어 권한을 더 많이 가질 수 있어야 합니다. -When you need to customize what `fit()` does, you should **override the training step function of the `Model` class**. This is the function that is called by `fit()` for every batch of data. You will then be able to call `fit()` as usual – and it will be running your own learning algorithm. +`fit()`이 수행하는 작업을 커스터마이즈해야 할 때는, +**`Model` 클래스의 트레이닝 스텝 함수를 재정의해야** 합니다. +이 함수는 `fit()`이 각 데이터 배치마다 호출하는 함수입니다. +이렇게 하면, 평소와 같이 `fit()`을 호출할 수 있으며, +그 안에서 사용자가 정의한 트레이닝 알고리즘이 실행됩니다. -Note that this pattern does not prevent you from building models with the Functional API. You can do this whether you're building `Sequential` models, Functional API models, or subclassed models. +이 패턴은 함수형 API로 모델을 만드는 것을 방해하지 않는다는 점에 주의하세요. +`Sequential` 모델, Functional API 모델, +또는 서브클래싱한 모델을 만들 때도 이 방법을 사용할 수 있습니다. -Let's see how that works. +이제 그 방법을 살펴보겠습니다. -## Setup +## 셋업 {#setup} ```python import os -# This guide can only be run with the JAX backend. +# 이 가이드는 JAX 백엔드에서만 실행할 수 있습니다. os.environ["KERAS_BACKEND"] = "jax" import jax @@ -47,19 +59,22 @@ import keras import numpy as np ``` -## A first simple example +## 첫 번째 간단한 예제 {#a-first-simple-example} -Let's start from a simple example: +간단한 예제부터 시작해봅시다: -- We create a new class that subclasses [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). -- We implement a fully-stateless `compute_loss_and_updates()` method to compute the loss as well as the updated values for the non-trainable variables of the model. Internally, it calls `stateless_call()` and the built-in `compute_loss()`. -- We implement a fully-stateless `train_step()` method to compute current metric values (including the loss) as well as updated values for the trainable variables, the optimizer variables, and the metric variables. +- [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})을 서브클래싱하는 새로운 클래스를 만듭니다. +- 손실을 계산하고 모델의 트레이닝 가능하지 않은 변수의 업데이트된 값을 계산하는, + 완전히 상태가 없는(fully-stateless) `compute_loss_and_updates()` 메서드를 구현합니다. + 내부적으로는, `stateless_call()`과 빌트인 `compute_loss()`를 호출합니다. +- 현재의 메트릭 값(손실 포함)과 트레이닝 가능한 변수, 옵티마이저 변수, 메트릭 변수의 업데이트된 값을 계산하기 위한, + 완전히 상태가 없는(fully-stateless) `train_step()` 메서드를 구현합니다. -Note that you can also take into account the `sample_weight` argument by: +또한 `sample_weight` 인자를 다음과 같은 방법으로 고려할 수 있습니다: -- Unpacking the data as `x, y, sample_weight = data` -- Passing `sample_weight` to `compute_loss()` -- Passing `sample_weight` alongside `y` and `y_pred` to metrics in `stateless_update_state()` +- 데이터를 `x, y, sample_weight = data`로 언패킹하기 +- `sample_weight`를 `compute_loss()`에 전달하기 +- `sample_weight`를 `y`와 `y_pred`와 함께 `stateless_update_state()`의 메트릭에 전달하기 ```python class CustomModel(keras.Model): @@ -89,10 +104,10 @@ class CustomModel(keras.Model): ) = state x, y = data - # Get the gradient function. + # 그래디언트 함수 가져오기 grad_fn = jax.value_and_grad(self.compute_loss_and_updates, has_aux=True) - # Compute the gradients. + # 그래디언트를 계산합니다. (loss, (y_pred, non_trainable_variables)), grads = grad_fn( trainable_variables, non_trainable_variables, @@ -101,7 +116,7 @@ class CustomModel(keras.Model): training=True, ) - # Update trainable variables and optimizer variables. + # 트레이닝 가능한 변수와 옵티마이저 변수를 업데이트합니다. ( trainable_variables, optimizer_variables, @@ -109,7 +124,7 @@ class CustomModel(keras.Model): optimizer_variables, grads, trainable_variables ) - # Update metrics. + # 메트릭을 업데이트합니다. new_metrics_vars = [] logs = {} for metric in self.metrics: @@ -125,7 +140,7 @@ class CustomModel(keras.Model): logs[metric.name] = metric.stateless_result(this_metric_vars) new_metrics_vars += this_metric_vars - # Return metric logs and updated state variables. + # 메트릭 로그와 업데이트된 상태 변수를 반환합니다. state = ( trainable_variables, non_trainable_variables, @@ -135,16 +150,16 @@ class CustomModel(keras.Model): return logs, state ``` -Let's try this out: +이제 시도해봅시다: ```python -# Construct and compile an instance of CustomModel +# `CustomModel` 인스턴스를 생성하고 컴파일합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(optimizer="adam", loss="mse", metrics=["mae"]) -# Just use `fit` as usual +# 평소처럼 `fit`을 사용하세요. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.fit(x, y, epochs=3) @@ -165,11 +180,13 @@ Epoch 3/3 {{% /details %}} -## Going lower-level +## 더 낮은 레벨로 내려가기 {#going-lower-level} -Naturally, you could just skip passing a loss function in `compile()`, and instead do everything _manually_ in `train_step`. Likewise for metrics. +물론, `compile()`에서 손실 함수를 전달하지 않고, +대신 `train_step`에서 모든 작업을 _수동으로_ 수행할 수도 있습니다. +메트릭도 마찬가지입니다. -Here's a lower-level example, that only uses `compile()` to configure the optimizer: +다음은 옵티마이저를 설정하기 위해서만 `compile()`을 사용하는, 더 낮은 레벨의 예제입니다: ```python class CustomModel(keras.Model): @@ -205,10 +222,10 @@ class CustomModel(keras.Model): ) = state x, y = data - # Get the gradient function. + # 그래디언트 함수를 가져옵니다. grad_fn = jax.value_and_grad(self.compute_loss_and_updates, has_aux=True) - # Compute the gradients. + # 그래디언트를 계산합니다. (loss, (y_pred, non_trainable_variables)), grads = grad_fn( trainable_variables, non_trainable_variables, @@ -217,7 +234,7 @@ class CustomModel(keras.Model): training=True, ) - # Update trainable variables and optimizer variables. + # 트레이닝 가능한 변수와 옵티마이저 변수를 업데이트합니다. ( trainable_variables, optimizer_variables, @@ -225,7 +242,7 @@ class CustomModel(keras.Model): optimizer_variables, grads, trainable_variables ) - # Update metrics. + # 메트릭을 업데이트합니다. loss_tracker_vars = metrics_variables[: len(self.loss_tracker.variables)] mae_metric_vars = metrics_variables[len(self.loss_tracker.variables) :] @@ -244,7 +261,7 @@ class CustomModel(keras.Model): new_metrics_vars = loss_tracker_vars + mae_metric_vars - # Return metric logs and updated state variables. + # 메트릭 로그와 업데이트된 상태 변수를 반환합니다. state = ( trainable_variables, non_trainable_variables, @@ -255,21 +272,21 @@ class CustomModel(keras.Model): @property def metrics(self): - # We list our `Metric` objects here so that `reset_states()` can be - # called automatically at the start of each epoch - # or at the start of `evaluate()`. + # `Metric` 객체들을 여기에 나열하여, + # 각 에포크의 시작이나 `evaluate()`의 시작 시에, + # `reset_states()`가 자동으로 호출될 수 있도록 합니다. return [self.loss_tracker, self.mae_metric] -# Construct an instance of CustomModel +# `CustomModel` 인스턴스를 생성하고 컴파일합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) -# We don't pass a loss or metrics here. +# 여기에서는 손실 함수나 메트릭을 전달하지 않습니다. model.compile(optimizer="adam") -# Just use `fit` as usual -- you can use callbacks, etc. +# 평소처럼 `fit`을 사용하세요 — 콜백 등을 사용할 수 있습니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.fit(x, y, epochs=5) @@ -294,14 +311,16 @@ Epoch 5/5 {{% /details %}} -## Providing your own evaluation step +## 당신만의 평가 스텝 제공 {#providing-your-own-evaluation-step} -What if you want to do the same for calls to `model.evaluate()`? Then you would override `test_step` in exactly the same way. Here's what it looks like: +`model.evaluate()` 호출에 대해서도 동일한 작업을 수행하고 싶다면 어떻게 해야 할까요? +그러면 정확히 같은 방식으로 `test_step`을 재정의하면 됩니다. +다음은 그 예시입니다: ```python class CustomModel(keras.Model): def test_step(self, state, data): - # Unpack the data. + # 데이터를 언패킹합니다. x, y = data ( trainable_variables, @@ -309,7 +328,7 @@ class CustomModel(keras.Model): metrics_variables, ) = state - # Compute predictions and loss. + # 예측값과 손실을 계산합니다. y_pred, non_trainable_variables = self.stateless_call( trainable_variables, non_trainable_variables, @@ -318,7 +337,7 @@ class CustomModel(keras.Model): ) loss = self.compute_loss(x, y, y_pred) - # Update metrics. + # 메트릭을 업데이트합니다. new_metrics_vars = [] for metric in self.metrics: this_metric_vars = metrics_variables[ @@ -333,7 +352,7 @@ class CustomModel(keras.Model): logs = metric.stateless_result(this_metric_vars) new_metrics_vars += this_metric_vars - # Return metric logs and updated state variables. + # 메트릭 로그와 업데이트된 상태 변수를 반환합니다. state = ( trainable_variables, non_trainable_variables, @@ -342,13 +361,13 @@ class CustomModel(keras.Model): return logs, state -# Construct an instance of CustomModel +# `CustomModel` 인스턴스를 생성합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(loss="mse", metrics=["mae"]) -# Evaluate with our custom test_step +# 커스텀 `test_step`으로 평가합니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.evaluate(x, y) @@ -364,4 +383,4 @@ model.evaluate(x, y) {{% /details %}} -That's it! +이것으로 끝입니다! diff --git a/content/korean/docs/guides/custom_train_step_in_tensorflow/_index.md b/content/korean/docs/guides/custom_train_step_in_tensorflow/_index.md index 653b7386..74c21875 100644 --- a/content/korean/docs/guides/custom_train_step_in_tensorflow/_index.md +++ b/content/korean/docs/guides/custom_train_step_in_tensorflow/_index.md @@ -1,6 +1,6 @@ --- -title: Customizing what happens in `fit()` with TensorFlow -linkTitle: Customizing fit() with TensorFlow +title: TensorFlow에서의 `fit()` 동작을 커스터마이즈 +linkTitle: TensorFlow fit() 커스터마이즈 toc: true weight: 6 type: docs @@ -11,35 +11,47 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2020/04/15 **{{< t f_last_modified >}}** 2023/06/27 -**{{< t f_description >}}** Overriding the training step of the Model class with TensorFlow. +**{{< t f_description >}}** TensorFlow에서 `Model` 클래스의 트레이닝 스텝을 재정의. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/custom_train_step_in_tensorflow.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/custom_train_step_in_tensorflow.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -When you're doing supervised learning, you can use `fit()` and everything works smoothly. +지도 학습을 할 때는 `fit()`을 사용하면, 모든 것이 매끄럽게 작동합니다. -When you need to take control of every little detail, you can write your own training loop entirely from scratch. +하지만 모든 세부 사항을 완전히 제어해야 할 경우, +처음부터 끝까지 직접 당신만의 트레이닝 루프를 작성할 수 있습니다. -But what if you need a custom training algorithm, but you still want to benefit from the convenient features of `fit()`, such as callbacks, built-in distribution support, or step fusing? +그렇지만 커스텀 트레이닝 알고리즘이 필요하면서도, +콜백, 빌트인 분산 지원, 스텝 퓨징(step fusing)과 같은, +`fit()`의 편리한 기능을 그대로 활용하고 싶다면 어떻게 해야 할까요? -A core principle of Keras is **progressive disclosure of complexity**. You should always be able to get into lower-level workflows in a gradual way. You shouldn't fall off a cliff if the high-level functionality doesn't exactly match your use case. You should be able to gain more control over the small details while retaining a commensurate amount of high-level convenience. +Keras의 핵심 원칙 중 하나는 **점진적인 복잡성 공개**입니다. +항상 점진적으로 더 낮은 레벨의 워크플로로 진입할 수 있어야 합니다. +높은 레벨의 기능이 정확히 사용 사례에 맞지 않더라도, 갑작스럽게 어려움에 부딪혀서는 안 됩니다. +높은 레벨의 편리함을 유지하면서, 작은 세부 사항에 대한 제어 권한을 더 많이 가질 수 있어야 합니다. -When you need to customize what `fit()` does, you should **override the training step function of the `Model` class**. This is the function that is called by `fit()` for every batch of data. You will then be able to call `fit()` as usual – and it will be running your own learning algorithm. +`fit()`이 수행하는 작업을 커스터마이즈해야 할 때는, +**`Model` 클래스의 트레이닝 스텝 함수를 재정의해야** 합니다. +이 함수는 `fit()`이 각 데이터 배치마다 호출하는 함수입니다. +이렇게 하면, 평소와 같이 `fit()`을 호출할 수 있으며, +그 안에서 사용자가 정의한 트레이닝 알고리즘이 실행됩니다. -Note that this pattern does not prevent you from building models with the Functional API. You can do this whether you're building `Sequential` models, Functional API models, or subclassed models. +이 패턴은 함수형 API로 모델을 만드는 것을 방해하지 않는다는 점에 주의하세요. +`Sequential` 모델, Functional API 모델, +또는 서브클래싱한 모델을 만들 때도 이 방법을 사용할 수 있습니다. -Let's see how that works. +이제 그 방법을 살펴보겠습니다. -## Setup +## 셋업 {#setup} ```python import os -# This guide can only be run with the TF backend. +# 이 가이드는 TF 백엔드에서만 실행할 수 있습니다. os.environ["KERAS_BACKEND"] = "tensorflow" import tensorflow as tf @@ -48,64 +60,70 @@ from keras import layers import numpy as np ``` -## A first simple example +## 첫 번째 간단한 예제 {#a-first-simple-example} -Let's start from a simple example: +간단한 예제부터 시작해봅시다: -- We create a new class that subclasses [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). -- We just override the method `train_step(self, data)`. -- We return a dictionary mapping metric names (including the loss) to their current value. +- [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})을 서브클래싱하는 새로운 클래스를 만듭니다. +- `train_step(self, data)` 메서드만 재정의합니다. +- 메트릭 이름(손실을 포함한)과 현재 값의 매핑을 반환하는 딕셔너리를 리턴합니다. -The input argument `data` is what gets passed to fit as training data: +입력 인자 `data`는 `fit`에 트레이닝 데이터로 전달되는 것입니다: -- If you pass NumPy arrays, by calling `fit(x, y, ...)`, then `data` will be the tuple `(x, y)` -- If you pass a [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset), by calling `fit(dataset, ...)`, then `data` will be what gets yielded by `dataset` at each batch. +- `fit(x, y, ...)`를 호출하면서 NumPy 배열을 전달하면, `data`는 튜플 `(x, y)`가 됩니다. +- [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset)을 `fit(dataset, ...)`으로 호출하면서 전달하면, + `data`는 각 배치에서 `dataset`이 생성하는 값이 됩니다. -In the body of the `train_step()` method, we implement a regular training update, similar to what you are already familiar with. Importantly, **we compute the loss via `self.compute_loss()`**, which wraps the loss(es) function(s) that were passed to `compile()`. +`train_step()` 메서드의 본문에서는, +이미 익숙한 일반적인 트레이닝 업데이트를 구현합니다. +중요한 것은, **`self.compute_loss()`를 통해 손실을 계산**하는 것입니다. +이 메서드는 `compile()`에 전달된 손실(들)의 함수(들)을 래핑합니다. -Similarly, we call `metric.update_state(y, y_pred)` on metrics from `self.metrics`, to update the state of the metrics that were passed in `compile()`, and we query results from `self.metrics` at the end to retrieve their current value. +마찬가지로, `self.metrics`에서 메트릭에 대해 `metric.update_state(y, y_pred)`를 호출하여, +`compile()`에 전달된 메트릭의 상태를 업데이트하고, +마지막에는 `self.metrics`에서 결과를 쿼리하여 현재 값을 가져옵니다. ```python class CustomModel(keras.Model): def train_step(self, data): - # Unpack the data. Its structure depends on your model and - # on what you pass to `fit()`. + # 데이터를 언패킹합니다. + # 데이터의 구조는 모델과 `fit()`에 전달하는 값에 따라 다릅니다. x, y = data with tf.GradientTape() as tape: - y_pred = self(x, training=True) # Forward pass - # Compute the loss value - # (the loss function is configured in `compile()`) + y_pred = self(x, training=True) # 순전파 + # 손실 값을 계산합니다. + # (손실 함수는 `compile()`에서 설정됩니다) loss = self.compute_loss(y=y, y_pred=y_pred) - # Compute gradients + # 그래디언트를 계산합니다. trainable_vars = self.trainable_variables gradients = tape.gradient(loss, trainable_vars) - # Update weights + # 가중치를 업데이트합니다. self.optimizer.apply(gradients, trainable_vars) - # Update metrics (includes the metric that tracks the loss) + # 메트릭을 업데이트합니다. (손실을 추적하는 메트릭 포함) for metric in self.metrics: if metric.name == "loss": metric.update_state(loss) else: metric.update_state(y, y_pred) - # Return a dict mapping metric names to current value + # 메트릭 이름을 현재 값에 매핑하는 딕셔너리를 반환합니다. return {m.name: m.result() for m in self.metrics} ``` -Let's try this out: +이제 이것을 시도해봅시다: ```python -# Construct and compile an instance of CustomModel +# `CustomModel` 인스턴스를 생성하고 컴파일합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(optimizer="adam", loss="mse", metrics=["mae"]) -# Just use `fit` as usual +# 평소처럼 `fit`을 사용하세요. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.fit(x, y, epochs=3) @@ -129,15 +147,27 @@ I0000 00:00:1699222602.443035 1 device_compiler.h:187] Compiled cluster us {{% /details %}} -## Going lower-level +## 더 낮은 레벨로 내려가기 {#going-lower-level} -Naturally, you could just skip passing a loss function in `compile()`, and instead do everything _manually_ in `train_step`. Likewise for metrics. +물론, `compile()`에서 손실 함수를 전달하지 않고, +대신 모든 것을 `train_step`에서 _수동으로_ 수행할 수 있습니다. +메트릭도 마찬가지입니다. -Here's a lower-level example, that only uses `compile()` to configure the optimizer: +다음은 옵티마이저를 설정하기 위해서만 `compile()`을 사용하는, +더 낮은 레벨의 예제입니다: -- We start by creating `Metric` instances to track our loss and a MAE score (in `__init__()`). -- We implement a custom `train_step()` that updates the state of these metrics (by calling `update_state()` on them), then query them (via `result()`) to return their current average value, to be displayed by the progress bar and to be pass to any callback. -- Note that we would need to call `reset_states()` on our metrics between each epoch! Otherwise calling `result()` would return an average since the start of training, whereas we usually work with per-epoch averages. Thankfully, the framework can do that for us: just list any metric you want to reset in the `metrics` property of the model. The model will call `reset_states()` on any object listed here at the beginning of each `fit()` epoch or at the beginning of a call to `evaluate()`. +- 먼저, 손실과 MAE 점수를 추적하기 위해, `Metric` 인스턴스를 생성합니다. (`__init__()`에서) +- 그런 다음, 이들 메트릭의 상태를 업데이트(그들에 대해 메트릭의 `update_state()` 호출함으로써)한 후, + 현재 평균 값을 반환하기 위해 `result()`를 통해 이를 쿼리하는, + 커스텀 `train_step()`을 구현합니다. + 이렇게 반환된 값은 진행 표시줄에 표시되거나 콜백에 전달됩니다. +- 각 에포크마다 메트릭의 `reset_states()`를 호출해야 한다는 점에 유의하세요! + 그렇지 않으면, `result()`를 호출할 때, + 에포크 시작 시점이 아닌 트레이닝 시작 이후의 평균을 반환하게 됩니다. + 보통 우리는 에포크별 평균을 사용합니다. + 다행히도, 프레임워크가 이를 처리해줍니다: 모델의 `metrics` 속성에 초기화하려는 메트릭을 나열하기만 하면 됩니다. + 모델은 `fit()` 에포크의 시작 시점이나 `evaluate()` 호출의 시작 시점에, + 여기에 나열된 모든 객체에 대해 `reset_states()`를 호출합니다. ```python class CustomModel(keras.Model): @@ -151,18 +181,18 @@ class CustomModel(keras.Model): x, y = data with tf.GradientTape() as tape: - y_pred = self(x, training=True) # Forward pass - # Compute our own loss + y_pred = self(x, training=True) # 순전파 + # 우리만의 손실을 계산합니다. loss = self.loss_fn(y, y_pred) - # Compute gradients + # 그래디언트를 계산합니다. trainable_vars = self.trainable_variables gradients = tape.gradient(loss, trainable_vars) - # Update weights + # 가중치를 업데이트합니다. self.optimizer.apply(gradients, trainable_vars) - # Compute our own metrics + # 우리만의 메트릭을 계산합니다. self.loss_tracker.update_state(loss) self.mae_metric.update_state(y, y_pred) return { @@ -172,21 +202,21 @@ class CustomModel(keras.Model): @property def metrics(self): - # We list our `Metric` objects here so that `reset_states()` can be - # called automatically at the start of each epoch - # or at the start of `evaluate()`. + # 각 에포크의 시작 시점이나 `evaluate()`의 시작 시점에, + # `reset_states()`가 자동으로 호출될 수 있도록, + # `Metric` 객체를 여기에 나열합니다. return [self.loss_tracker, self.mae_metric] -# Construct an instance of CustomModel +# `CustomModel` 인스턴스를 생성하고 컴파일합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) -# We don't pass a loss or metrics here. +# 여기에서는 손실 함수나 메트릭을 전달하지 않습니다. model.compile(optimizer="adam") -# Just use `fit` as usual -- you can use callbacks, etc. +# 평소처럼 `fit`을 사용하세요 — 콜백 등을 사용할 수 있습니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.fit(x, y, epochs=5) @@ -211,19 +241,23 @@ Epoch 5/5 {{% /details %}} -## Supporting `sample_weight` & `class_weight` +## `sample_weight` & `class_weight` 지원 {#supporting-sampleweight-and-classweight} -You may have noticed that our first basic example didn't make any mention of sample weighting. If you want to support the `fit()` arguments `sample_weight` and `class_weight`, you'd simply do the following: +첫 번째 기본 예제에서, 샘플 가중치에 대한 언급이 없었다는 것을 눈치채셨을 겁니다. +`sample_weight`와 `class_weight` 같은 `fit()` 인자를 지원하고 싶다면, +다음과 같이 간단히 할 수 있습니다: -- Unpack `sample_weight` from the `data` argument -- Pass it to `compute_loss` & `update_state` (of course, you could also just apply it manually if you don't rely on `compile()` for losses & metrics) -- That's it. +- `data` 인자에서 `sample_weight`를 언팩합니다. +- `compute_loss`와 `update_state`에 이를 전달합니다. + (물론, 손실 및 메트릭에 대해 `compile()`을 사용하지 않는다면, + 이를 수동으로 적용할 수도 있습니다) +- 그게 전부입니다. ```python class CustomModel(keras.Model): def train_step(self, data): - # Unpack the data. Its structure depends on your model and - # on what you pass to `fit()`. + # 데이터를 언팩합니다. + # 데이터의 구조는 모델과 `fit()`에 전달하는 값에 따라 달라집니다. if len(data) == 3: x, y, sample_weight = data else: @@ -231,42 +265,42 @@ class CustomModel(keras.Model): x, y = data with tf.GradientTape() as tape: - y_pred = self(x, training=True) # Forward pass - # Compute the loss value. - # The loss function is configured in `compile()`. + y_pred = self(x, training=True) # 순전파 + # 손실 값을 계산합니다. + # (손실 함수는 `compile()`에서 설정됩니다) loss = self.compute_loss( y=y, y_pred=y_pred, sample_weight=sample_weight, ) - # Compute gradients + # 그래디언트를 계산합니다. trainable_vars = self.trainable_variables gradients = tape.gradient(loss, trainable_vars) - # Update weights + # 가중치를 업데이트합니다. self.optimizer.apply(gradients, trainable_vars) - # Update the metrics. - # Metrics are configured in `compile()`. + # 메트릭을 업데이트합니다. + # 메트릭은 `compile()`에서 설정됩니다. for metric in self.metrics: if metric.name == "loss": metric.update_state(loss) else: metric.update_state(y, y_pred, sample_weight=sample_weight) - # Return a dict mapping metric names to current value. - # Note that it will include the loss (tracked in self.metrics). + # 메트릭 이름을 현재 값에 매핑하는 딕셔너리를 반환합니다. + # 여기에는 손실(`self.metrics`에서 추적된)이 포함된다는 점에 유의하세요. return {m.name: m.result() for m in self.metrics} -# Construct and compile an instance of CustomModel +# `CustomModel` 인스턴스를 생성하고 컴파일합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(optimizer="adam", loss="mse", metrics=["mae"]) -# You can now use sample_weight argument +# 이제 `sample_weight` 인자를 사용할 수 있습니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) sw = np.random.random((1000, 1)) @@ -288,37 +322,39 @@ Epoch 3/3 {{% /details %}} -## Providing your own evaluation step +## 당신만의 평가 스텝 제공 {#providing-your-own-evaluation-step} -What if you want to do the same for calls to `model.evaluate()`? Then you would override `test_step` in exactly the same way. Here's what it looks like: +`model.evaluate()` 호출에 대해서도 동일한 작업을 수행하고 싶다면 어떻게 해야 할까요? +그러면 정확히 같은 방식으로 `test_step`을 재정의하면 됩니다. +예시는 다음과 같습니다: ```python class CustomModel(keras.Model): def test_step(self, data): - # Unpack the data + # 데이터를 언팩합니다. x, y = data - # Compute predictions + # 예측값을 계산합니다. y_pred = self(x, training=False) - # Updates the metrics tracking the loss + # 손실을 추적하는 메트릭을 업데이트합니다. loss = self.compute_loss(y=y, y_pred=y_pred) - # Update the metrics. + # 메트릭을 업데이트합니다. for metric in self.metrics: if metric.name == "loss": metric.update_state(loss) else: metric.update_state(y, y_pred) - # Return a dict mapping metric names to current value. - # Note that it will include the loss (tracked in self.metrics). + # 메트릭 이름을 현재 값에 매핑하는 딕셔너리를 반환합니다. + # 여기에는 손실(`self.metrics`에서 추적된)이 포함된다는 점에 유의하세요. return {m.name: m.result() for m in self.metrics} -# Construct an instance of CustomModel +# `CustomModel` 인스턴스를 생성하고 컴파일합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(loss="mse", metrics=["mae"]) -# Evaluate with our custom test_step +# 커스텀 `test_step`으로 평가합니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.evaluate(x, y) @@ -334,19 +370,19 @@ model.evaluate(x, y) {{% /details %}} -## Wrapping up: an end-to-end GAN example +## 마무리: 엔드투엔드 GAN 예제 {#wrapping-up-an-end-to-end-gan-example} -Let's walk through an end-to-end example that leverages everything you just learned. +방금 배운 모든 것을 활용하는 엔드 투 엔드 예제를 함께 살펴보겠습니다. -Let's consider: +다음의 경우를 고려해봅시다: -- A generator network meant to generate 28x28x1 images. -- A discriminator network meant to classify 28x28x1 images into two classes ("fake" and "real"). -- One optimizer for each. -- A loss function to train the discriminator. +- 28x28x1 이미지를 생성하는 생성자(generator) 네트워크. +- 28x28x1 이미지를 두 개의 클래스("가짜"와 "진짜")로 분류하는 판별자(discriminator) 네트워크. +- 각 네트워크에 대한 옵티마이저. +- 판별자를 트레이닝하기 위한 손실 함수. ```python -# Create the discriminator +# 판별자를 생성합니다. discriminator = keras.Sequential( [ keras.Input(shape=(28, 28, 1)), @@ -360,12 +396,12 @@ discriminator = keras.Sequential( name="discriminator", ) -# Create the generator +# 생성자를 생성합니다. latent_dim = 128 generator = keras.Sequential( [ keras.Input(shape=(latent_dim,)), - # We want to generate 128 coefficients to reshape into a 7x7x128 map + # 7x7x128 맵으로 reshape 할 128개의 계수를 생성하려고 합니다. layers.Dense(7 * 7 * 128), layers.LeakyReLU(negative_slope=0.2), layers.Reshape((7, 7, 128)), @@ -379,7 +415,9 @@ generator = keras.Sequential( ) ``` -Here's a feature-complete GAN class, overriding `compile()` to use its own signature, and implementing the entire GAN algorithm in 17 lines in `train_step`: +여기 `compile()`을 자체 시그니처로 재정의하고, +`train_step`에서 17줄로 전체 GAN 알고리즘을 구현한, +기능 완성형(feature-complete) GAN 클래스가 있습니다: ```python class GAN(keras.Model): @@ -405,51 +443,51 @@ class GAN(keras.Model): def train_step(self, real_images): if isinstance(real_images, tuple): real_images = real_images[0] - # Sample random points in the latent space + # 잠재 공간에서 랜덤 포인트를 샘플링합니다. batch_size = tf.shape(real_images)[0] random_latent_vectors = keras.random.normal( shape=(batch_size, self.latent_dim), seed=self.seed_generator ) - # Decode them to fake images + # 그것들을 가짜 이미지로 디코딩합니다. generated_images = self.generator(random_latent_vectors) - # Combine them with real images + # 그것들을 진짜 이미지와 결합합니다. combined_images = tf.concat([generated_images, real_images], axis=0) - # Assemble labels discriminating real from fake images + # 진짜 이미지와 가짜 이미지를 구분하는 레이블을 구성합니다. labels = tf.concat( [tf.ones((batch_size, 1)), tf.zeros((batch_size, 1))], axis=0 ) - # Add random noise to the labels - important trick! + # 레이블에 랜덤 노이즈를 추가합니다 - 중요한 트릭입니다! labels += 0.05 * keras.random.uniform( tf.shape(labels), seed=self.seed_generator ) - # Train the discriminator + # 판별자를 트레이닝합니다. with tf.GradientTape() as tape: predictions = self.discriminator(combined_images) d_loss = self.loss_fn(labels, predictions) grads = tape.gradient(d_loss, self.discriminator.trainable_weights) self.d_optimizer.apply(grads, self.discriminator.trainable_weights) - # Sample random points in the latent space + # 잠재 공간에서 랜덤 포인트를 샘플링합니다. random_latent_vectors = keras.random.normal( shape=(batch_size, self.latent_dim), seed=self.seed_generator ) - # Assemble labels that say "all real images" + # '모두 진짜 이미지(all real images)'라는 레이블을 구성합니다. misleading_labels = tf.zeros((batch_size, 1)) - # Train the generator (note that we should *not* update the weights - # of the discriminator)! + # 생성자를 트레이닝합니다! + # (판별자의 가중치는 *업데이트하지 않아야* 한다는 점에 유의하세요) with tf.GradientTape() as tape: predictions = self.discriminator(self.generator(random_latent_vectors)) g_loss = self.loss_fn(misleading_labels, predictions) grads = tape.gradient(g_loss, self.generator.trainable_weights) self.g_optimizer.apply(grads, self.generator.trainable_weights) - # Update metrics and return their value. + # 메트릭을 업데이트하고 그 값을 반환합니다. self.d_loss_tracker.update_state(d_loss) self.g_loss_tracker.update_state(g_loss) return { @@ -458,10 +496,10 @@ class GAN(keras.Model): } ``` -Let's test-drive it: +시험해봅시다: ```python -# Prepare the dataset. We use both the training & test MNIST digits. +# 데이터셋을 준비합니다. 트레이닝 및 테스트 모두 MNIST 숫자 데이터를 사용합니다. batch_size = 64 (x_train, _), (x_test, _) = keras.datasets.mnist.load_data() all_digits = np.concatenate([x_train, x_test]) @@ -477,8 +515,9 @@ gan.compile( loss_fn=keras.losses.BinaryCrossentropy(from_logits=True), ) -# To limit the execution time, we only train on 100 batches. You can train on -# the entire dataset. You will need about 20 epochs to get nice results. +# 실행 시간을 제한하기 위해 100개의 배치에서만 트레이닝합니다. +# 전체 데이터셋으로 트레이닝할 수도 있습니다. +# 좋은 결과를 얻으려면 약 20 에포크가 필요합니다. gan.fit(dataset.take(100), epochs=1) ``` @@ -492,4 +531,4 @@ gan.fit(dataset.take(100), epochs=1) {{% /details %}} -The ideas behind deep learning are simple, so why should their implementation be painful? +딥러닝의 아이디어는 간단한데, 왜 구현은 어려워야 할까요? diff --git a/content/korean/docs/guides/custom_train_step_in_torch/_index.md b/content/korean/docs/guides/custom_train_step_in_torch/_index.md index fbdab1c6..bfa10b5f 100644 --- a/content/korean/docs/guides/custom_train_step_in_torch/_index.md +++ b/content/korean/docs/guides/custom_train_step_in_torch/_index.md @@ -1,6 +1,6 @@ --- -title: Customizing what happens in `fit()` with PyTorch -linkTitle: Customizing fit() with PyTorch +title: PyTorch에서의 `fit()` 동작을 커스터마이즈 +linkTitle: PyTorch fit() 커스터마이즈 toc: true weight: 7 type: docs @@ -11,35 +11,47 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2023/06/27 **{{< t f_last_modified >}}** 2024/08/01 -**{{< t f_description >}}** Overriding the training step of the Model class with PyTorch. +**{{< t f_description >}}** PyTorch에서 `Model` 클래스의 트레이닝 스텝을 재정의. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/custom_train_step_in_torch.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/custom_train_step_in_torch.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -When you're doing supervised learning, you can use `fit()` and everything works smoothly. +지도 학습을 할 때는 `fit()`을 사용하면, 모든 것이 매끄럽게 작동합니다. -When you need to take control of every little detail, you can write your own training loop entirely from scratch. +하지만 모든 세부 사항을 완전히 제어해야 할 경우, +처음부터 끝까지 직접 당신만의 트레이닝 루프를 작성할 수 있습니다. -But what if you need a custom training algorithm, but you still want to benefit from the convenient features of `fit()`, such as callbacks, built-in distribution support, or step fusing? +그렇지만 커스텀 트레이닝 알고리즘이 필요하면서도, +콜백, 빌트인 분산 지원, 스텝 퓨징(step fusing)과 같은, +`fit()`의 편리한 기능을 그대로 활용하고 싶다면 어떻게 해야 할까요? -A core principle of Keras is **progressive disclosure of complexity**. You should always be able to get into lower-level workflows in a gradual way. You shouldn't fall off a cliff if the high-level functionality doesn't exactly match your use case. You should be able to gain more control over the small details while retaining a commensurate amount of high-level convenience. +Keras의 핵심 원칙 중 하나는 **점진적인 복잡성 공개**입니다. +항상 점진적으로 더 낮은 레벨의 워크플로로 진입할 수 있어야 합니다. +높은 레벨의 기능이 정확히 사용 사례에 맞지 않더라도, 갑작스럽게 어려움에 부딪혀서는 안 됩니다. +높은 레벨의 편리함을 유지하면서, 작은 세부 사항에 대한 제어 권한을 더 많이 가질 수 있어야 합니다. -When you need to customize what `fit()` does, you should **override the training step function of the `Model` class**. This is the function that is called by `fit()` for every batch of data. You will then be able to call `fit()` as usual – and it will be running your own learning algorithm. +`fit()`이 수행하는 작업을 커스터마이즈해야 할 때는, +**`Model` 클래스의 트레이닝 스텝 함수를 재정의해야** 합니다. +이 함수는 `fit()`이 각 데이터 배치마다 호출하는 함수입니다. +이렇게 하면, 평소와 같이 `fit()`을 호출할 수 있으며, +그 안에서 사용자가 정의한 트레이닝 알고리즘이 실행됩니다. -Note that this pattern does not prevent you from building models with the Functional API. You can do this whether you're building `Sequential` models, Functional API models, or subclassed models. +이 패턴은 함수형 API로 모델을 만드는 것을 방해하지 않는다는 점에 주의하세요. +`Sequential` 모델, Functional API 모델, +또는 서브클래싱한 모델을 만들 때도 이 방법을 사용할 수 있습니다. -Let's see how that works. +이제 그 방법을 살펴보겠습니다. -## Setup +## 셋업 {#setup} ```python import os -# This guide can only be run with the torch backend. +# 이 가이드는 torch 백엔드에서만 실행할 수 있습니다. os.environ["KERAS_BACKEND"] = "torch" import torch @@ -48,71 +60,77 @@ from keras import layers import numpy as np ``` -## A first simple example +## 첫 번째 간단한 예제 {#a-first-simple-example} -Let's start from a simple example: +간단한 예제부터 시작해봅시다: -- We create a new class that subclasses [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). -- We just override the method `train_step(self, data)`. -- We return a dictionary mapping metric names (including the loss) to their current value. +- [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})를 서브클래싱하는 새로운 클래스를 생성합니다. +- 메서드 `train_step(self, data)`만 오버라이드합니다. +- 메트릭 이름(손실을 포함하여)을 현재 값에 매핑하는 딕셔너리를 반환합니다. -The input argument `data` is what gets passed to fit as training data: +입력 인자 `data`는 트레이닝 데이터로서 `fit`에 전달되는 것입니다: -- If you pass NumPy arrays, by calling `fit(x, y, ...)`, then `data` will be the tuple `(x, y)` -- If you pass a `torch.utils.data.DataLoader` or a [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset), by calling `fit(dataset, ...)`, then `data` will be what gets yielded by `dataset` at each batch. +- `fit(x, y, ...)`를 호출하여 NumPy 배열을 전달하면, + `data`는 튜플 `(x, y)`가 됩니다. +- `fit(dataset, ...)`를 호출하여 `torch.utils.data.DataLoader` 또는 [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset)를 전달하면, + `data`는 각 배치마다 `dataset`에 의해 생성(yielded)되는 것입니다. -In the body of the `train_step()` method, we implement a regular training update, similar to what you are already familiar with. Importantly, **we compute the loss via `self.compute_loss()`**, which wraps the loss(es) function(s) that were passed to `compile()`. +`train_step()` 메서드의 본문에서, 여러분이 이미 익숙한 일반적인 트레이닝 업데이트를 구현합니다. +중요한 점은, **`self.compute_loss()`를 통해 손실을 계산한다는 것**인데, +이는 `compile()`에 전달된 손실 함수들을 래핑하고 있습니다. -Similarly, we call `metric.update_state(y, y_pred)` on metrics from `self.metrics`, to update the state of the metrics that were passed in `compile()`, and we query results from `self.metrics` at the end to retrieve their current value. +마찬가지로, `self.metrics`로부터의 메트릭에 대해 `metric.update_state(y, y_pred)`를 호출하여, +`compile()`에 전달된 메트릭의 상태를 업데이트하고, +마지막에 `self.metrics`에서 결과를 조회하여 현재 값을 가져옵니다. ```python class CustomModel(keras.Model): def train_step(self, data): - # Unpack the data. Its structure depends on your model and - # on what you pass to `fit()`. + # 데이터를 언팩합니다. + # 그 구조는 모델과 `fit()`에 전달한 것에 따라 달라집니다. x, y = data - # Call torch.nn.Module.zero_grad() to clear the leftover gradients - # for the weights from the previous train step. + # 이전 트레이닝 스텝에서 남은 가중치의 그래디언트를 지우기 위해 + # torch.nn.Module.zero_grad()를 호출합니다. self.zero_grad() - # Compute loss + # 손실 계산 y_pred = self(x, training=True) # Forward pass loss = self.compute_loss(y=y, y_pred=y_pred) - # Call torch.Tensor.backward() on the loss to compute gradients - # for the weights. + # 손실에 대해 torch.Tensor.backward()를 호출하여 + # 가중치의 그래디언트를 계산합니다. loss.backward() trainable_weights = [v for v in self.trainable_weights] gradients = [v.value.grad for v in trainable_weights] - # Update weights + # 가중치 업데이트 with torch.no_grad(): self.optimizer.apply(gradients, trainable_weights) - # Update metrics (includes the metric that tracks the loss) + # 메트릭 업데이트 (손실을 추적하는 메트릭 포함) for metric in self.metrics: if metric.name == "loss": metric.update_state(loss) else: metric.update_state(y, y_pred) - # Return a dict mapping metric names to current value - # Note that it will include the loss (tracked in self.metrics). + # 메트릭 이름을 현재 값에 매핑하는 딕셔너리를 반환합니다. + # 이는 손실을 포함한다는 점에 유의하세요. (self.metrics에서 추적됨) return {m.name: m.result() for m in self.metrics} ``` -Let's try this out: +이것을 시도해봅시다: ```python -# Construct and compile an instance of CustomModel +# CustomModel의 인스턴스를 생성하고 컴파일합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(optimizer="adam", loss="mse", metrics=["mae"]) -# Just use `fit` as usual +# 평소처럼 `fit`을 사용합니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.fit(x, y, epochs=3) @@ -133,15 +151,26 @@ Epoch 3/3 {{% /details %}} -## Going lower-level +## 더 낮은 레벨로 내려가기 {#going-lower-level} -Naturally, you could just skip passing a loss function in `compile()`, and instead do everything _manually_ in `train_step`. Likewise for metrics. +당연히, `compile()`에서 손실 함수를 전달하지 않고, +대신 `train_step`에서 모든 작업을 _수동으로_ 처리할 수 있습니다. +메트릭도 마찬가지입니다. -Here's a lower-level example, that only uses `compile()` to configure the optimizer: +다음은 옵티마이저 설정만을 위해 `compile()`을 사용하는, 더 낮은 레벨의 예제입니다: -- We start by creating `Metric` instances to track our loss and a MAE score (in `__init__()`). -- We implement a custom `train_step()` that updates the state of these metrics (by calling `update_state()` on them), then query them (via `result()`) to return their current average value, to be displayed by the progress bar and to be pass to any callback. -- Note that we would need to call `reset_states()` on our metrics between each epoch! Otherwise calling `result()` would return an average since the start of training, whereas we usually work with per-epoch averages. Thankfully, the framework can do that for us: just list any metric you want to reset in the `metrics` property of the model. The model will call `reset_states()` on any object listed here at the beginning of each `fit()` epoch or at the beginning of a call to `evaluate()`. +- `__init__()`에서, 손실과 MAE 점수를 추적하기 위한 `Metric` 인스턴스를 만듭니다. +- 이 메트릭들의 상태를 (메트릭에 대해 `update_state()` 호출함으로써) 업데이트하는, + 커스텀 `train_step()`을 구현하고, + 그런 다음 진행률 표시줄에 표시하거나 콜백으로 전달하기 위해, + 현재 평균 값을 반환하도록 `result()`를 통해 조회합니다. +- 각 에포크 사이에 메트릭에 대해 `reset_states()`를 호출해야 한다는 점을 유의하세요! + 그렇지 않으면, `result()`를 호출하면 트레이닝 시작 이후의 평균이 반환되는데, + 우리는 일반적으로 에포크별 평균을 사용합니다. + 다행히도 프레임워크는 이를 자동으로 처리해줍니다: + 모델의 `metrics` 속성에 초기화하려는 메트릭을 나열하기만 하면 됩니다. + 모델은 각 `fit()` 에포크의 시작 시 또는 `evaluate()` 호출의 시작 시에, + 여기에 나열된 모든 객체에 대해 `reset_states()`를 호출합니다. ```python class CustomModel(keras.Model): @@ -154,26 +183,26 @@ class CustomModel(keras.Model): def train_step(self, data): x, y = data - # Call torch.nn.Module.zero_grad() to clear the leftover gradients - # for the weights from the previous train step. + # 이전 트레이닝 스텝에서 남은 가중치의 그래디언트를 지우기 위해 + # torch.nn.Module.zero_grad()를 호출합니다. self.zero_grad() - # Compute loss - y_pred = self(x, training=True) # Forward pass + # 손실 계산 + y_pred = self(x, training=True) # 순전파 loss = self.loss_fn(y, y_pred) - # Call torch.Tensor.backward() on the loss to compute gradients - # for the weights. + # 손실에 대해 torch.Tensor.backward()를 호출하여 가중치의 + # 그래디언트를 계산합니다. loss.backward() trainable_weights = [v for v in self.trainable_weights] gradients = [v.value.grad for v in trainable_weights] - # Update weights + # 가중치 업데이트 with torch.no_grad(): self.optimizer.apply(gradients, trainable_weights) - # Compute our own metrics + # 자체 메트릭 계산 self.loss_tracker.update_state(loss) self.mae_metric.update_state(y, y_pred) return { @@ -183,21 +212,21 @@ class CustomModel(keras.Model): @property def metrics(self): - # We list our `Metric` objects here so that `reset_states()` can be - # called automatically at the start of each epoch - # or at the start of `evaluate()`. + # 여기에 `Metric` 객체를 나열하여, + # 각 에포크의 시작 시 또는 `evaluate()`의 시작 시, + # 자동으로 `reset_states()`가 호출되도록 합니다. return [self.loss_tracker, self.mae_metric] -# Construct an instance of CustomModel +# CustomModel의 인스턴스 생성 inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) -# We don't pass a loss or metrics here. +# 여기서 손실이나 메트릭을 전달하지 않습니다. model.compile(optimizer="adam") -# Just use `fit` as usual -- you can use callbacks, etc. +# 평소처럼 `fit`을 사용합니다 -- 콜백 등을 사용할 수 있습니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.fit(x, y, epochs=5) @@ -222,67 +251,70 @@ Epoch 5/5 {{% /details %}} -## Supporting `sample_weight` & `class_weight` +## `sample_weight` & `class_weight` 지원 {#supporting-sampleweight-and-classweight} -You may have noticed that our first basic example didn't make any mention of sample weighting. If you want to support the `fit()` arguments `sample_weight` and `class_weight`, you'd simply do the following: +첫 번째 기본 예제에서 샘플 가중치에 대해 언급하지 않은 것을 눈치채셨을 겁니다. +`sample_weight`와 `class_weight`를 `fit()` 인자로 지원하려면, +간단히 다음과 같이 하면 됩니다: -- Unpack `sample_weight` from the `data` argument -- Pass it to `compute_loss` & `update_state` (of course, you could also just apply it manually if you don't rely on `compile()` for losses & metrics) -- That's it. +- `data` 인자에서 `sample_weight`를 언팩합니다. +- `compute_loss`와 `update_state`에 이를 전달합니다. + (물론, 손실 및 메트릭에 대해 `compile()`을 사용하지 않는다면, 수동으로 적용할 수도 있습니다.) +- 끝입니다. ```python class CustomModel(keras.Model): def train_step(self, data): - # Unpack the data. Its structure depends on your model and - # on what you pass to `fit()`. + # 데이터를 언팩합니다. 그 구조는 모델과 + # `fit()`에 전달한 것에 따라 달라집니다. if len(data) == 3: x, y, sample_weight = data else: sample_weight = None x, y = data - # Call torch.nn.Module.zero_grad() to clear the leftover gradients - # for the weights from the previous train step. + # 이전 트레이닝 스텝에서 남은 가중치의 그래디언트를 지우기 위해 + # torch.nn.Module.zero_grad()를 호출합니다. self.zero_grad() - # Compute loss - y_pred = self(x, training=True) # Forward pass + # 손실 계산 + y_pred = self(x, training=True) # 순전파 loss = self.compute_loss( y=y, y_pred=y_pred, sample_weight=sample_weight, ) - # Call torch.Tensor.backward() on the loss to compute gradients - # for the weights. + # 손실에 대해 torch.Tensor.backward()를 호출하여, + # 가중치의 그래디언트를 계산합니다. loss.backward() trainable_weights = [v for v in self.trainable_weights] gradients = [v.value.grad for v in trainable_weights] - # Update weights + # 가중치 업데이트 with torch.no_grad(): self.optimizer.apply(gradients, trainable_weights) - # Update metrics (includes the metric that tracks the loss) + # 메트릭 업데이트 (손실을 추적하는 메트릭 포함) for metric in self.metrics: if metric.name == "loss": metric.update_state(loss) else: metric.update_state(y, y_pred, sample_weight=sample_weight) - # Return a dict mapping metric names to current value - # Note that it will include the loss (tracked in self.metrics). + # 메트릭 이름을 현재 값에 매핑하는 딕셔너리를 반환합니다. + # 이는 손실을 포함한다는 점에 유의하세요. (self.metrics에서 추적됨) return {m.name: m.result() for m in self.metrics} -# Construct and compile an instance of CustomModel +# CustomModel의 인스턴스를 생성하고 컴파일합니다 inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(optimizer="adam", loss="mse", metrics=["mae"]) -# You can now use sample_weight argument +# 이제 sample_weight 인자를 사용할 수 있습니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) sw = np.random.random((1000, 1)) @@ -304,37 +336,39 @@ Epoch 3/3 {{% /details %}} -## Providing your own evaluation step +## 당신만의 평가 스텝 제공 {#providing-your-own-evaluation-step} -What if you want to do the same for calls to `model.evaluate()`? Then you would override `test_step` in exactly the same way. Here's what it looks like: +`model.evaluate()` 호출에 대해서도 동일한 작업을 하고 싶다면 어떻게 해야 할까요? +그런 경우, `test_step`을 정확히 동일한 방식으로 오버라이드하면 됩니다. +다음은 그 예시입니다: ```python class CustomModel(keras.Model): def test_step(self, data): - # Unpack the data + # 데이터를 언팩합니다 x, y = data - # Compute predictions + # 예측값 계산 y_pred = self(x, training=False) - # Updates the metrics tracking the loss + # 손실을 추적하는 메트릭을 업데이트합니다. loss = self.compute_loss(y=y, y_pred=y_pred) - # Update the metrics. + # 메트릭을 업데이트합니다. for metric in self.metrics: if metric.name == "loss": metric.update_state(loss) else: metric.update_state(y, y_pred) - # Return a dict mapping metric names to current value. - # Note that it will include the loss (tracked in self.metrics). + # 메트릭 이름을 현재 값에 매핑하는 딕셔너리를 반환합니다. + # 이는 손실을 포함한다는 점에 유의하세요. (self.metrics에서 추적됨) return {m.name: m.result() for m in self.metrics} -# Construct an instance of CustomModel +# CustomModel의 인스턴스를 생성합니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = CustomModel(inputs, outputs) model.compile(loss="mse", metrics=["mae"]) -# Evaluate with our custom test_step +# 우리의 커스텀 test_step으로 평가합니다. x = np.random.random((1000, 32)) y = np.random.random((1000, 1)) model.evaluate(x, y) @@ -353,19 +387,19 @@ model.evaluate(x, y) {{% /details %}} -## Wrapping up: an end-to-end GAN example +## 마무리: 엔드투엔드 GAN 예제 {#wrapping-up-an-end-to-end-gan-example} -Let's walk through an end-to-end example that leverages everything you just learned. +엔드투엔드 예제를 통해 지금까지 배운 모든 것을 활용해 봅시다. -Let's consider: +다음과 같은 구성 요소를 고려하겠습니다: -- A generator network meant to generate 28x28x1 images. -- A discriminator network meant to classify 28x28x1 images into two classes ("fake" and "real"). -- One optimizer for each. -- A loss function to train the discriminator. +- 28x28x1 이미지를 생성하는 생성자 네트워크 +- 28x28x1 이미지를 두 개의 클래스("가짜"와 "진짜")로 분류하는 판별자 네트워크 +- 각각에 대한 옵티마이저 하나 +- 판별자를 트레이닝하기 위한 손실 함수 ```python -# Create the discriminator +# 판별자 생성 discriminator = keras.Sequential( [ keras.Input(shape=(28, 28, 1)), @@ -379,12 +413,12 @@ discriminator = keras.Sequential( name="discriminator", ) -# Create the generator +# 생성자 생성 latent_dim = 128 generator = keras.Sequential( [ keras.Input(shape=(latent_dim,)), - # We want to generate 128 coefficients to reshape into a 7x7x128 map + # 7x7x128 맵으로 reshape 하기 위해 128개의 계수를 생성합니다. layers.Dense(7 * 7 * 128), layers.LeakyReLU(negative_slope=0.2), layers.Reshape((7, 7, 128)), @@ -398,7 +432,9 @@ generator = keras.Sequential( ) ``` -Here's a feature-complete GAN class, overriding `compile()` to use its own signature, and implementing the entire GAN algorithm in 17 lines in `train_step`: +여기에는 `compile()`을 자신의 시그니처로 사용하고, +`train_step`에서 전체 GAN 알고리즘을 17줄로 구현한, +기능이 완전한(feature-complete) GAN 클래스가 있습니다: ```python class GAN(keras.Model): @@ -426,20 +462,20 @@ class GAN(keras.Model): device = "cuda" if torch.cuda.is_available() else "cpu" if isinstance(real_images, tuple) or isinstance(real_images, list): real_images = real_images[0] - # Sample random points in the latent space + # 잠재 공간에서 랜덤 포인트 샘플링 batch_size = real_images.shape[0] random_latent_vectors = keras.random.normal( shape=(batch_size, self.latent_dim), seed=self.seed_generator ) - # Decode them to fake images + # 가짜 이미지를 생성합니다. generated_images = self.generator(random_latent_vectors) - # Combine them with real images + # 이를 진짜 이미지와 결합합니다. real_images = torch.tensor(real_images, device=device) combined_images = torch.concat([generated_images, real_images], axis=0) - # Assemble labels discriminating real from fake images + # 진짜와 가짜 이미지를 구분하는 레이블을 조합합니다. labels = torch.concat( [ torch.ones((batch_size, 1), device=device), @@ -447,10 +483,10 @@ class GAN(keras.Model): ], axis=0, ) - # Add random noise to the labels - important trick! + # 레이블에 랜덤 노이즈를 추가합니다. - 중요한 트릭입니다! labels += 0.05 * keras.random.uniform(labels.shape, seed=self.seed_generator) - # Train the discriminator + # 판별자를 트레이닝합니다. self.zero_grad() predictions = self.discriminator(combined_images) d_loss = self.loss_fn(labels, predictions) @@ -459,16 +495,16 @@ class GAN(keras.Model): with torch.no_grad(): self.d_optimizer.apply(grads, self.discriminator.trainable_weights) - # Sample random points in the latent space + # 잠재 공간에서 랜덤 포인트 샘플링 random_latent_vectors = keras.random.normal( shape=(batch_size, self.latent_dim), seed=self.seed_generator ) - # Assemble labels that say "all real images" + # "모든 진짜 이미지 (all real images)"라고 말하는 레이블을 조합합니다. misleading_labels = torch.zeros((batch_size, 1), device=device) - # Train the generator (note that we should *not* update the weights - # of the discriminator)! + # 생성자를 트레이닝합니다. + # (판별자의 가중치를 업데이트하면 안됩니다) self.zero_grad() predictions = self.discriminator(self.generator(random_latent_vectors)) g_loss = self.loss_fn(misleading_labels, predictions) @@ -477,7 +513,7 @@ class GAN(keras.Model): with torch.no_grad(): self.g_optimizer.apply(grads, self.generator.trainable_weights) - # Update metrics and return their value. + # 메트릭을 업데이트하고 그 값을 반환합니다. self.d_loss_tracker.update_state(d_loss) self.g_loss_tracker.update_state(g_loss) return { @@ -486,21 +522,21 @@ class GAN(keras.Model): } ``` -Let's test-drive it: +이를 테스트해봅시다: ```python -# Prepare the dataset. We use both the training & test MNIST digits. +# 데이터셋을 준비합니다. 우리는 MNIST 숫자의 트레이닝과 테스트 데이터를 모두 사용합니다. batch_size = 64 (x_train, _), (x_test, _) = keras.datasets.mnist.load_data() all_digits = np.concatenate([x_train, x_test]) all_digits = all_digits.astype("float32") / 255.0 all_digits = np.reshape(all_digits, (-1, 28, 28, 1)) -# Create a TensorDataset +# TensorDataset 생성 dataset = torch.utils.data.TensorDataset( torch.from_numpy(all_digits), torch.from_numpy(all_digits) ) -# Create a DataLoader +# DataLoader 생성 dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True) gan = GAN(discriminator=discriminator, generator=generator, latent_dim=latent_dim) @@ -522,4 +558,4 @@ gan.fit(dataloader, epochs=1) {{% /details %}} -The ideas behind deep learning are simple, so why should their implementation be painful? +딥러닝의 기본 개념은 간단한데, 왜 그 구현은 고통스러워야 할까요? diff --git a/content/korean/docs/guides/customizing_saving_and_serialization/_index.md b/content/korean/docs/guides/customizing_saving_and_serialization/_index.md index 246d73f9..d1385c64 100644 --- a/content/korean/docs/guides/customizing_saving_and_serialization/_index.md +++ b/content/korean/docs/guides/customizing_saving_and_serialization/_index.md @@ -1,6 +1,6 @@ --- -title: Customizing Saving and Serialization -linkTitle: Customizing saving & serialization +title: 저장 및 직렬화 커스터마이징 +linkTitle: 커스텀 저장 및 직렬화 toc: true weight: 12 type: docs @@ -11,34 +11,36 @@ type: docs **{{< t f_author >}}** Neel Kovelamudi **{{< t f_date_created >}}** 2023/03/15 **{{< t f_last_modified >}}** 2023/03/15 -**{{< t f_description >}}** A more advanced guide on customizing saving for your layers and models. +**{{< t f_description >}}** 레이어와 모델을 위한 저장 커스터마이징에 대한 고급 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/customizing_saving_and_serialization.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/customizing_saving_and_serialization.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -This guide covers advanced methods that can be customized in Keras saving. For most users, the methods outlined in the primary [Serialize, save, and export guide]({{< relref "/docs/guides/serialization_and_saving" >}}) are sufficient. +이 가이드는 Keras 저장 방식에서 커스터마이징할 수 있는 고급 방법을 다룹니다. +대부분의 사용자에게는, 기본 ({{< titledRelref "/docs/guides/serialization_and_saving" >}}) 가이드에서 +설명된 방법으로 충분할 것입니다. -### APIs +### APIs {#apis} -We will cover the following APIs: +우리는 다음 API들을 다룰 것입니다: -- `save_assets()` and `load_assets()` -- `save_own_variables()` and `load_own_variables()` -- `get_build_config()` and `build_from_config()` -- `get_compile_config()` and `compile_from_config()` +- `save_assets()` 및 `load_assets()` +- `save_own_variables()` 및 `load_own_variables()` +- `get_build_config()` 및 `build_from_config()` +- `get_compile_config()` 및 `compile_from_config()` -When restoring a model, these get executed in the following order: +모델을 복원할 때, 다음 순서로 실행됩니다: - `build_from_config()` - `compile_from_config()` - `load_own_variables()` - `load_assets()` -## Setup +## 셋업 {#setup} ```python import os @@ -46,13 +48,17 @@ import numpy as np import keras ``` -## State saving customization +## 상태 저장 커스터마이즈 {#state-saving-customization} -These methods determine how the state of your model's layers is saved when calling `model.save()`. You can override them to take full control of the state saving process. +이 메서드들은 `model.save()`를 호출할 때 모델 레이어의 상태가 어떻게 저장되는지를 결정합니다. +이 메서드들을 재정의하여 상태 저장 프로세스를 완전히 제어할 수 있습니다. -### `save_own_variables()` and `load_own_variables()` +### `save_own_variables()` 및 `load_own_variables()` {#save_own_variables-and-load_own_variables} -These methods save and load the state variables of the layer when `model.save()` and `keras.models.load_model()` are called, respectively. By default, the state variables saved and loaded are the weights of the layer (both trainable and non-trainable). Here is the default implementation of `save_own_variables()`: +이 메서드들은 각각 `model.save()` 및 `keras.models.load_model()`가 호출될 때, +레이어의 상태 변수를 저장하고 로드합니다. +기본적으로, 저장 및 로드되는 상태 변수는 레이어의 가중치(트레이닝 가능한 것과 트레이닝 불가능한 것 모두)입니다. +다음은 `save_own_variables()`의 기본 구현입니다: ```python def save_own_variables(self, store): @@ -61,9 +67,10 @@ def save_own_variables(self, store): store[f"{i}"] = v.numpy() ``` -The store used by these methods is a dictionary that can be populated with the layer variables. Let's take a look at an example customizing this. +이 메서드에서 사용되는 저장소는 레이어 변수로 채울 수 있는 딕셔너리입니다. +커스터마이징한 예시를 살펴보겠습니다. -**Example:** +**예시:** ```python @keras.utils.register_keras_serializable(package="my_custom_package") @@ -76,17 +83,17 @@ class LayerWithCustomVariable(keras.layers.Dense): def save_own_variables(self, store): super().save_own_variables(store) - # Stores the value of the variable upon saving + # 저장 시 변수 값을 저장합니다. store["variables"] = self.my_variable.numpy() def load_own_variables(self, store): - # Assigns the value of the variable upon loading + # 로드 시 변수 값을 할당합니다. self.my_variable.assign(store["variables"]) - # Load the remaining weights + # 나머지 가중치를 로드합니다. for i, v in enumerate(self.weights): v.assign(store[f"{i}"]) - # Note: You must specify how all variables (including layer weights) - # are loaded in `load_own_variables.` + # 참고: `load_own_variables`에서는 모든 변수(레이어 가중치 포함)를 + # 어떻게 로드할지 명시해야 합니다. def call(self, inputs): dense_out = super().call(inputs) @@ -117,15 +124,16 @@ np.testing.assert_allclose( {{% /details %}} -### `save_assets()` and `load_assets()` +### `save_assets()` 및 `load_assets()` {#save_assets-and-load_assets} -These methods can be added to your model class definition to store and load any additional information that your model needs. +이 메서드들은 모델 클래스 정의에 추가하여, 모델이 필요한 추가 정보를 저장하고 로드할 수 있게 합니다. -For example, NLP domain layers such as TextVectorization layers and IndexLookup layers may need to store their associated vocabulary (or lookup table) in a text file upon saving. +예를 들어, NLP 도메인의 레이어인 `TextVectorization` 레이어나 +`IndexLookup` 레이어는 저장 시 연관된 어휘(또는 조회 테이블)를 텍스트 파일에 저장할 필요가 있습니다. -Let's take at the basics of this workflow with a simple file `assets.txt`. +이 워크플로의 기본 개념을 간단한 파일 `assets.txt`를 사용하여 살펴보겠습니다. -**Example:** +**예시:** ```python @keras.saving.register_keras_serializable(package="my_custom_package") @@ -135,12 +143,12 @@ class LayerWithCustomAssets(keras.layers.Dense): self.vocab = vocab def save_assets(self, inner_path): - # Writes the vocab (sentence) to text file at save time. + # 저장 시 어휘(문장)를 텍스트 파일에 작성합니다. with open(os.path.join(inner_path, "vocabulary.txt"), "w") as f: f.write(self.vocab) def load_assets(self, inner_path): - # Reads the vocab (sentence) from text file at load time. + # 로드 시 어휘(문장)를 텍스트 파일에서 읽어옵니다. with open(os.path.join(inner_path, "vocabulary.txt"), "r") as f: text = f.read() self.vocab = text.replace("", "little") @@ -161,15 +169,17 @@ np.testing.assert_string_equal( ) ``` -## `build` and `compile` saving customization +## `build` 및 `compile` 저장 커스터마이즈 {#build-and-compile-saving-customization} -### `get_build_config()` and `build_from_config()` +### `get_build_config()` 및 `build_from_config()` {#get_build_config-and-build_from_config} -These methods work together to save the layer's built states and restore them upon loading. +이 메서드들은 레이어의 빌드 상태를 저장하고, 로드할 때 이를 복원하기 위해 함께 작동합니다. -By default, this only includes a build config dictionary with the layer's input shape, but overriding these methods can be used to include further Variables and Lookup Tables that can be useful to restore for your built model. +기본적으로는 레이어의 입력 형태를 포함하는 빌드 구성 딕셔너리만 포함되지만, +이 메서드들을 재정의하여 추가 변수 및 조회 테이블을 포함시킬 수 있으며, +이는 빌드된 모델을 복원하는 데 유용할 수 있습니다. -**Example:** +**예시:** ```python @keras.saving.register_keras_serializable(package="my_custom_package") @@ -185,9 +195,9 @@ class LayerWithCustomBuild(keras.layers.Layer): return dict(units=self.units, **super().get_config()) def build(self, input_shape, layer_init): - # Note the overriding of `build()` to add an extra argument. - # Therefore, we will need to manually call build with `layer_init` argument - # before the first execution of `call()`. + # `build()`를 재정의하여 추가 인자를 받습니다. + # 따라서, `call()`을 처음 실행하기 전에 + # `layer_init` 인자로 수동으로 `build()`를 호출해야 합니다. super().build(input_shape) self._input_shape = input_shape self.w = self.add_weight( @@ -206,11 +216,11 @@ class LayerWithCustomBuild(keras.layers.Layer): build_config = { "layer_init": self.layer_init, "input_shape": self._input_shape, - } # Stores our initializer for `build()` + } # `build()`의 이니셜라이저 값을 저장합니다. return build_config def build_from_config(self, config): - # Calls `build()` with the parameters at loading time + # 로드 시 `build()`를 해당 매개변수로 호출합니다. self.build(config["input_shape"], config["layer_init"]) @@ -234,15 +244,17 @@ np.testing.assert_equal(restored_model.layers[0].layer_init, "random_normal") np.testing.assert_equal(restored_model.built, True) ``` -### `get_compile_config()` and `compile_from_config()` +### `get_compile_config()` 및 `compile_from_config()` {#get_compile_config-and-compile_from_config} -These methods work together to save the information with which the model was compiled (optimizers, losses, etc.) and restore and re-compile the model with this information. +이 메서드들은 모델이 컴파일된 정보(옵티마이저, 손실 함수 등)를 저장하고, +이를 복원하여 다시 컴파일할 때 함께 작동합니다. -Overriding these methods can be useful for compiling the restored model with custom optimizers, custom losses, etc., as these will need to be deserialized prior to calling `model.compile` in `compile_from_config()`. +이 메서드를 재정의하면, 커스텀 옵티마이저나 커스텀 손실 함수 등을 사용하여 복원된 모델을 컴파일할 수 있습니다. +이러한 커스텀 항목들은 `compile_from_config()`에서 `model.compile`을 호출하기 전에 역직렬화가 필요합니다. -Let's take a look at an example of this. +예시를 살펴보겠습니다. -**Example:** +**예시:** ```python @keras.saving.register_keras_serializable(package="my_custom_package") @@ -276,7 +288,7 @@ class ModelWithCustomCompile(keras.Model): self.loss_metrics = metrics def get_compile_config(self): - # These parameters will be serialized at saving time. + # 이러한 매개변수는 저장 시 직렬화됩니다. return { "model_optimizer": self.model_optimizer, "loss_fn": self.loss_fn, @@ -284,12 +296,12 @@ class ModelWithCustomCompile(keras.Model): } def compile_from_config(self, config): - # Deserializes the compile parameters (important, since many are custom) + # 컴파일 매개변수의 역직렬화 (중요: 커스텀 항목이 많기 때문) optimizer = keras.utils.deserialize_keras_object(config["model_optimizer"]) loss_fn = keras.utils.deserialize_keras_object(config["loss_fn"]) metrics = keras.utils.deserialize_keras_object(config["metric"]) - # Calls compile with the deserialized parameters + # 역직렬화된 매개변수로 컴파일을 호출합니다. self.compile(optimizer=optimizer, loss_fn=loss_fn, metrics=metrics) @@ -320,11 +332,12 @@ np.testing.assert_equal(model.loss_metrics, restored_model.loss_metrics) {{% /details %}} -## Conclusion +## 결론 {#conclusion} -Using the methods learned in this tutorial allows for a wide variety of use cases, allowing the saving and loading of complex models with exotic assets and state elements. To recap: +이 튜토리얼에서 배운 메서드를 사용하면 다양한 사용 사례에 적용할 수 있으며, +복잡한 모델을 포함한 특이한 자산 및 상태 요소를 저장하고 로드할 수 있습니다. 요약하자면: -- `save_own_variables` and `load_own_variables` determine how your states are saved and loaded. -- `save_assets` and `load_assets` can be added to store and load any additional information your model needs. -- `get_build_config` and `build_from_config` save and restore the model's built states. -- `get_compile_config` and `compile_from_config` save and restore the model's compiled states. +- `save_own_variables`와 `load_own_variables`는 상태가 어떻게 저장되고 로드되는지를 결정합니다. +- `save_assets`와 `load_assets`는 모델이 필요로 하는 추가 정보를 저장하고 로드하는 데 사용할 수 있습니다. +- `get_build_config`와 `build_from_config`는 모델의 빌드 상태를 저장하고 복원합니다. +- `get_compile_config`와 `compile_from_config`는 모델의 컴파일된 상태를 저장하고 복원합니다. diff --git a/content/korean/docs/guides/distributed_training_with_jax/_index.md b/content/korean/docs/guides/distributed_training_with_jax/_index.md index 6490427e..5cae88d0 100644 --- a/content/korean/docs/guides/distributed_training_with_jax/_index.md +++ b/content/korean/docs/guides/distributed_training_with_jax/_index.md @@ -1,6 +1,6 @@ --- -title: Multi-GPU distributed training with JAX -linkTitle: Distributed training with Jax +title: JAX로 멀티 GPU 분산 트레이닝하기 +linkTitle: JAX 분산 트레이닝 toc: true weight: 15 type: docs @@ -11,28 +11,38 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2023/07/11 **{{< t f_last_modified >}}** 2023/07/11 -**{{< t f_description >}}** Guide to multi-GPU/TPU training for Keras models with JAX. +**{{< t f_description >}}** JAX를 사용한 Keras 모델의 멀티 GPU/TPU 트레이닝 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/distributed_training_with_jax.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/distributed_training_with_jax.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -There are generally two ways to distribute computation across multiple devices: +일반적으로 여러 장치에 연산을 분산시키는 방법에는 두 가지가 있습니다: -**Data parallelism**, where a single model gets replicated on multiple devices or multiple machines. Each of them processes different batches of data, then they merge their results. There exist many variants of this setup, that differ in how the different model replicas merge results, in whether they stay in sync at every batch or whether they are more loosely coupled, etc. +- **데이터 병렬 처리** + - **데이터 병렬 처리**에서는 하나의 모델이 여러 장치나 여러 머신에 복제됩니다. + - 각 장치는 서로 다른 배치의 데이터를 처리한 후, 결과를 병합합니다. + - 이 설정에는 다양한 변형이 있으며, 서로 다른 모델 복제본이 결과를 병합하는 방식이나, + 각 배치마다 동기화되는지 여부 등에 차이가 있습니다. +- **모델 병렬 처리** + - **모델 병렬 처리**에서는 하나의 모델의 다른 부분이 서로 다른 장치에서 실행되어, 하나의 데이터 배치를 함께 처리합니다. + - 이는 여러 가지 브랜치를 특징으로 하는 자연스럽게 병렬화된 아키텍처를 가진 모델에 가장 적합합니다. -**Model parallelism**, where different parts of a single model run on different devices, processing a single batch of data together. This works best with models that have a naturally-parallel architecture, such as models that feature multiple branches. +이 가이드는 데이터 병렬 처리, 특히 **동기식 데이터 병렬 처리**에 중점을 둡니다. +여기서 모델의 서로 다른 복제본은 각 배치를 처리한 후 동기화됩니다. +동기화는 모델의 수렴 동작을 단일 장치에서의 트레이닝과 동일하게 유지시킵니다. -This guide focuses on data parallelism, in particular **synchronous data parallelism**, where the different replicas of the model stay in sync after each batch they process. Synchronicity keeps the model convergence behavior identical to what you would see for single-device training. +구체적으로, 이 가이드는 최소한의 코드 변경으로 `jax.sharding` API를 사용하여, +Keras 모델을 여러 GPU 또는 TPU(일반적으로 2개에서 16개)를 사용하여, 단일 머신에서 트레이닝하는 방법을 설명합니다. +(단일 호스트, 다중 장치 트레이닝) 이는 연구자들과 소규모 산업 워크플로우에서 가장 흔한 설정입니다. -Specifically, this guide teaches you how to use `jax.sharding` APIs to train Keras models, with minimal changes to your code, on multiple GPUs or TPUS (typically 2 to 16) installed on a single machine (single host, multi-device training). This is the most common setup for researchers and small-scale industry workflows. +## 셋업 {#setup} -## Setup - -Let's start by defining the function that creates the model that we will train, and the function that creates the dataset we will train on (MNIST in this case). +먼저 트레이닝할 모델을 생성하는 함수와, +트레이닝에 사용할 데이터셋을 생성하는 함수를 정의해봅시다. (이 경우 MNIST 데이터셋을 사용) ```python import os @@ -51,7 +61,7 @@ from jax.sharding import PartitionSpec as P def get_model(): - # Make a simple convnet with batch normalization and dropout. + # 배치 정규화 및 드롭아웃을 포함한 간단한 컨볼루션 신경망을 만듭니다. inputs = keras.Input(shape=(28, 28, 1)) x = keras.layers.Rescaling(1.0 / 255.0)(inputs) x = keras.layers.Conv2D(filters=12, kernel_size=3, padding="same", use_bias=False)( @@ -85,52 +95,64 @@ def get_model(): def get_datasets(): - # Load the data and split it between train and test sets + # 데이터를 로드하고, 트레이닝 및 테스트 세트로 나눕니다. (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() - # Scale images to the [0, 1] range + # 이미지를 [0, 1] 범위로 스케일링합니다. x_train = x_train.astype("float32") x_test = x_test.astype("float32") - # Make sure images have shape (28, 28, 1) + # 이미지가 (28, 28, 1) 형태를 갖추도록 만듭니다. x_train = np.expand_dims(x_train, -1) x_test = np.expand_dims(x_test, -1) print("x_train shape:", x_train.shape) print(x_train.shape[0], "train samples") print(x_test.shape[0], "test samples") - # Create TF Datasets + # TF 데이터셋 생성 train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train)) eval_data = tf.data.Dataset.from_tensor_slices((x_test, y_test)) return train_data, eval_data ``` -## Single-host, multi-device synchronous training +## 단일 호스트, 다중 장치 동기화 트레이닝 {#single-host-multi-device-synchronous-training} -In this setup, you have one machine with several GPUs or TPUs on it (typically 2 to 16). Each device will run a copy of your model (called a **replica**). For simplicity, in what follows, we'll assume we're dealing with 8 GPUs, at no loss of generality. +이 설정에서는, 하나의 머신에 여러 개의 GPU 또는 TPU가 있습니다. (일반적으로 2~16개) +각 장치에서 모델의 복사본(**레플리카**)이 실행됩니다. +간단히 설명하기 위해, 다음 내용에서는 8개의 GPU를 사용하는 것으로 가정하겠습니다. 이는 일반성을 잃지 않습니다.​ -**How it works** +**작동 방식** -At each step of training: +트레이닝의 각 단계에서: -- The current batch of data (called **global batch**) is split into 8 different sub-batches (called **local batches**). For instance, if the global batch has 512 samples, each of the 8 local batches will have 64 samples. -- Each of the 8 replicas independently processes a local batch: they run a forward pass, then a backward pass, outputting the gradient of the weights with respect to the loss of the model on the local batch. -- The weight updates originating from local gradients are efficiently merged across the 8 replicas. Because this is done at the end of every step, the replicas always stay in sync. +- **글로벌 배치**라고 불리는, 현재 배치 데이터가 8개의 서로 다른 **로컬 배치**로 나뉩니다. + 예를 들어, 글로벌 배치가 512개의 샘플을 포함하면, 각 로컬 배치는 64개의 샘플을 가집니다. +- 8개의 레플리카는 각각 로컬 배치를 독립적으로 처리합니다: + 순방향 전파 후 역전파를 수행하고, 로컬 배치에서 모델의 손실에 따른 가중치 그래디언트를 출력합니다. +- 로컬 그래디언트에서 발생한 가중치 업데이트는 8개의 레플리카 전반에서 효율적으로 병합됩니다. + 이는 각 단계가 끝날 때마다 이루어지므로, 레플리카는 항상 동기 상태를 유지합니다. -In practice, the process of synchronously updating the weights of the model replicas is handled at the level of each individual weight variable. This is done through a using a `jax.sharding.NamedSharding` that is configured to replicate the variables. +실제로, 모델 레플리카의 가중치를 동기화하는 과정은 각 개별 가중치 변수 레벨에서 처리됩니다. +이는 `jax.sharding.NamedSharding`을 사용하여, 변수들을 복제하는 방식으로 이루어집니다. -**How to use it** +**사용 방법** -To do single-host, multi-device synchronous training with a Keras model, you would use the `jax.sharding` features. Here's how it works: +Keras 모델로 단일 호스트, 다중 장치 동기 트레이닝을 수행하려면, +`jax.sharding` 기능을 사용합니다. 사용 방법은 다음과 같습니다: -- We first create a device mesh using `mesh_utils.create_device_mesh`. -- We use `jax.sharding.Mesh`, `jax.sharding.NamedSharding` and `jax.sharding.PartitionSpec` to define how to partition JAX arrays. - We specify that we want to replicate the model and optimizer variables across all devices by using a spec with no axis. - We specify that we want to shard the data across devices by using a spec that splits along the batch dimension. -- We use `jax.device_put` to replicate the model and optimizer variables across devices. This happens once at the beginning. -- In the training loop, for each batch that we process, we use `jax.device_put` to split the batch across devices before invoking the train step. +- 먼저 `mesh_utils.create_device_mesh`를 사용해, 장치 메쉬를 생성합니다. +- `jax.sharding.Mesh`, `jax.sharding.NamedSharding` 및 `jax.sharding.PartitionSpec`을 사용하여, + JAX 배열을 어떻게 분할할지 정의합니다. + - 모델과 옵티마이저 변수를 모든 장치에 복제하려면, 축이 없는 사양(a spec with no axis)을 사용합니다. + - 데이터를 장치 간에 샤딩하려면, 배치 차원을 따라 분할하는 사양을 사용합니다. +- `jax.device_put`을 사용해 모델과 옵티마이저 변수를 장치 전반에 복제합니다. + 이는 처음에 한 번만 수행됩니다. +- 트레이닝 루프에서는 각 배치를 처리할 때, + `jax.device_put`을 사용해 배치를 장치 전반에 분할한 후 트레이닝 단계를 호출합니다. -Here's the flow, where each step is split into its own utility function: +다음은 각 단계를 유틸리티 함수로 분할한 흐름입니다: ```python -# Config +# 설정 num_epochs = 2 batch_size = 64 @@ -141,14 +163,14 @@ model = get_model() optimizer = keras.optimizers.Adam(1e-3) loss = keras.losses.SparseCategoricalCrossentropy(from_logits=True) -# Initialize all state with .build() +# 모든 상태를 .build()로 초기화 (one_batch, one_batch_labels) = next(iter(train_data)) model.build(one_batch) optimizer.build(model.trainable_variables) -# This is the loss function that will be differentiated. -# Keras provides a pure functional forward pass: model.stateless_call +# 이 함수는 미분될 손실 함수입니다. +# Keras는 순수한 함수형 순방향 전파를 제공합니다: model.stateless_call def compute_loss(trainable_variables, non_trainable_variables, x, y): y_pred, updated_non_trainable_variables = model.stateless_call( trainable_variables, non_trainable_variables, x, training=True @@ -157,11 +179,11 @@ def compute_loss(trainable_variables, non_trainable_variables, x, y): return loss_value, updated_non_trainable_variables -# Function to compute gradients +# 그래디언트 계산 함수 compute_gradients = jax.value_and_grad(compute_loss, has_aux=True) -# Training step, Keras provides a pure functional optimizer.stateless_apply +# 트레이닝 스텝, Keras는 순수 함수형 optimizer.stateless_apply를 제공합니다 @jax.jit def train_step(train_state, x, y): trainable_variables, non_trainable_variables, optimizer_variables = train_state @@ -180,21 +202,21 @@ def train_step(train_state, x, y): ) -# Replicate the model and optimizer variable on all devices +# 모델과 옵티마이저 변수를 모든 장치에 복제 def get_replicated_train_state(devices): - # All variables will be replicated on all devices + # 모든 변수는 모든 장치에서 복제됩니다. var_mesh = Mesh(devices, axis_names=("_")) - # In NamedSharding, axes not mentioned are replicated (all axes here) + # NamedSharding에서, 언급되지 않은 축은 복제됩니다. (여기서는 모든 축) var_replication = NamedSharding(var_mesh, P()) - # Apply the distribution settings to the model variables + # 모델 변수에 분산 설정 적용 trainable_variables = jax.device_put(model.trainable_variables, var_replication) non_trainable_variables = jax.device_put( model.non_trainable_variables, var_replication ) optimizer_variables = jax.device_put(optimizer.variables, var_replication) - # Combine all state in a tuple + # 모든 상태를 하나의 튜플로 결합 return (trainable_variables, non_trainable_variables, optimizer_variables) @@ -202,16 +224,16 @@ num_devices = len(jax.local_devices()) print(f"Running on {num_devices} devices: {jax.local_devices()}") devices = mesh_utils.create_device_mesh((num_devices,)) -# Data will be split along the batch axis -data_mesh = Mesh(devices, axis_names=("batch",)) # naming axes of the mesh +# 데이터는 배치 축을 따라 분할됩니다. +data_mesh = Mesh(devices, axis_names=("batch",)) # 메쉬 축의 이름 지정 data_sharding = NamedSharding( data_mesh, P( "batch", ), -) # naming axes of the sharded partition +) # 샤딩된 파티션의 축 이름 지정 -# Display data sharding +# 데이터 샤딩 표시 x, y = next(iter(train_data)) sharded_x = jax.device_put(x.numpy(), data_sharding) print("Data sharding") @@ -219,7 +241,7 @@ jax.debug.visualize_array_sharding(jax.numpy.reshape(sharded_x, [-1, 28 * 28])) train_state = get_replicated_train_state(devices) -# Custom training loop +# 커스텀 트레이닝 루프 for epoch in range(num_epochs): data_iter = iter(train_data) for data in data_iter: @@ -228,7 +250,7 @@ for epoch in range(num_epochs): loss_value, train_state = train_step(train_state, sharded_x, y.numpy()) print("Epoch", epoch, "loss:", loss_value) -# Post-processing model state update to write them back into the model +# 모델 상태 업데이트 후 모델에 다시 기록 trainable_variables, non_trainable_variables, optimizer_variables = train_state for variable, value in zip(model.trainable_variables, trainable_variables): variable.assign(value) @@ -262,4 +284,4 @@ Epoch 1 loss: 0.23666474 {{% /details %}} -That's it! +이제 끝입니다! diff --git a/content/korean/docs/guides/distributed_training_with_tensorflow/_index.md b/content/korean/docs/guides/distributed_training_with_tensorflow/_index.md index 8c4018b0..55ff372d 100644 --- a/content/korean/docs/guides/distributed_training_with_tensorflow/_index.md +++ b/content/korean/docs/guides/distributed_training_with_tensorflow/_index.md @@ -1,6 +1,6 @@ --- -title: Multi-GPU distributed training with TensorFlow -linkTitle: Distributed training with TensorFlow +title: TensorFlow로 멀티 GPU 분산 트레이닝하기 +linkTitle: TensorFlow 분산 트레이닝 toc: true weight: 16 type: docs @@ -11,26 +11,37 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2020/04/28 **{{< t f_last_modified >}}** 2023/06/29 -**{{< t f_description >}}** Guide to multi-GPU training for Keras models with TensorFlow. +**{{< t f_description >}}** TensorFlow로 Keras 모델을 사용하여, 멀티 GPU 트레이닝을 진행하는 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/distributed_training_with_tensorflow.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/distributed_training_with_tensorflow.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -There are generally two ways to distribute computation across multiple devices: +일반적으로 여러 디바이스에 계산을 분산시키는 방법에는 두 가지가 있습니다: -**Data parallelism**, where a single model gets replicated on multiple devices or multiple machines. Each of them processes different batches of data, then they merge their results. There exist many variants of this setup, that differ in how the different model replicas merge results, in whether they stay in sync at every batch or whether they are more loosely coupled, etc. +- **데이터 병렬 처리** + - **데이터 병렬 처리**에서는 하나의 모델이 여러 장치나 여러 머신에 복제됩니다. + - 각 장치는 서로 다른 배치의 데이터를 처리한 후, 결과를 병합합니다. + - 이 설정에는 다양한 변형이 있으며, 서로 다른 모델 복제본이 결과를 병합하는 방식이나, + 각 배치마다 동기화되는지 여부 등에 차이가 있습니다. +- **모델 병렬 처리** + - **모델 병렬 처리**에서는 하나의 모델의 다른 부분이 서로 다른 장치에서 실행되어, 하나의 데이터 배치를 함께 처리합니다. + - 이는 여러 가지 브랜치를 특징으로 하는 자연스럽게 병렬화된 아키텍처를 가진 모델에 가장 적합합니다. -**Model parallelism**, where different parts of a single model run on different devices, processing a single batch of data together. This works best with models that have a naturally-parallel architecture, such as models that feature multiple branches. +이 가이드는 데이터 병렬 처리, 특히 **동기식 데이터 병렬 처리**에 중점을 둡니다. +여기서 모델의 서로 다른 복제본은 각 배치를 처리한 후 동기화됩니다. +동기화는 모델의 수렴 동작을 단일 장치에서의 트레이닝과 동일하게 유지시킵니다. -This guide focuses on data parallelism, in particular **synchronous data parallelism**, where the different replicas of the model stay in sync after each batch they process. Synchronicity keeps the model convergence behavior identical to what you would see for single-device training. +특히, 이 가이드는 TensorFlow의 +[`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute) API를 사용하여, +여러 GPU(보통 2~16개)를 사용하는 동기식 데이터 병렬 처리 방식으로 Keras 모델을 트레이닝하는 방법을 다룹니다. +최소한의 코드 수정으로 여러 GPU가 설치된 단일 머신(단일 호스트, 멀티 디바이스 트레이닝)에서 트레이닝할 수 있습니다. +이는 연구자와 소규모 산업 워크플로우에서 가장 일반적으로 사용되는 설정입니다. -Specifically, this guide teaches you how to use the [`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute) API to train Keras models on multiple GPUs, with minimal changes to your code, on multiple GPUs (typically 2 to 16) installed on a single machine (single host, multi-device training). This is the most common setup for researchers and small-scale industry workflows. - -## Setup +## 셋업 {#setup} ```python import os @@ -41,56 +52,70 @@ import tensorflow as tf import keras ``` -## Single-host, multi-device synchronous training +## 단일 호스트, 다중 장치 동기 트레이닝 {#single-host-multi-device-synchronous-training} -In this setup, you have one machine with several GPUs on it (typically 2 to 16). Each device will run a copy of your model (called a **replica**). For simplicity, in what follows, we'll assume we're dealing with 8 GPUs, at no loss of generality. +이 설정에서는, 여러 개의 GPU가 있는 하나의 머신(일반적으로 2~16개의 GPU)에서 트레이닝을 진행합니다. +각 디바이스는 **복제본(replica)**이라고 불리는 모델의 사본을 실행합니다. +간단히 설명하기 위해, 다음 내용에서는 8개의 GPU를 사용하는 것으로 가정하겠습니다. 이는 일반성을 잃지 않습니다.​ -**How it works** +**작동 방식** -At each step of training: +트레이닝의 각 단계에서: -- The current batch of data (called **global batch**) is split into 8 different sub-batches (called **local batches**). For instance, if the global batch has 512 samples, each of the 8 local batches will have 64 samples. -- Each of the 8 replicas independently processes a local batch: they run a forward pass, then a backward pass, outputting the gradient of the weights with respect to the loss of the model on the local batch. -- The weight updates originating from local gradients are efficiently merged across the 8 replicas. Because this is done at the end of every step, the replicas always stay in sync. +- 현재 데이터 배치(**글로벌 배치**)는 8개의 서로 다른 하위 배치(**로컬 배치**)로 나뉩니다. + 예를 들어, 글로벌 배치에 512개의 샘플이 있으면, 8개의 로컬 배치 각각에는 64개의 샘플이 포함됩니다. +- 8개의 복제본 각각은 로컬 배치를 독립적으로 처리합니다: + 순전파를 실행한 후 역전파를 수행하여 모델 손실에 대한 가중치의 그래디언트를 출력합니다. +- 로컬 그래디언트로부터 발생한 가중치 업데이트는 8개의 복제본 간에 효율적으로 병합됩니다. + 이 병합은 각 스텝이 끝날 때 이루어지기 때문에, 복제본은 항상 동기화된 상태를 유지합니다. -In practice, the process of synchronously updating the weights of the model replicas is handled at the level of each individual weight variable. This is done through a **mirrored variable** object. +실제로, 모델 복제본의 가중치를 동기화하는 과정은 각 개별 가중치 변수 레벨에서 처리됩니다. +이는 **미러드 변수(mirrored variable)** 객체를 통해 이루어집니다. -**How to use it** +**사용 방법** -To do single-host, multi-device synchronous training with a Keras model, you would use the [`tf.distribute.MirroredStrategy` API](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy). Here's how it works: +Keras 모델로 단일 호스트, 멀티 디바이스 동기 트레이닝을 수행하려면, +[`tf.distribute.MirroredStrategy` API](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy)를 사용하면 됩니다. +작동 방식은 다음과 같습니다: -- Instantiate a `MirroredStrategy`, optionally configuring which specific devices you want to use (by default the strategy will use all GPUs available). -- Use the strategy object to open a scope, and within this scope, create all the Keras objects you need that contain variables. Typically, that means **creating & compiling the model** inside the distribution scope. In some cases, the first call to `fit()` may also create variables, so it's a good idea to put your `fit()` call in the scope as well. -- Train the model via `fit()` as usual. +- `MirroredStrategy`를 인스턴스화하고, + 선택적으로 사용할 특정 디바이스를 구성할 수 있습니다. + (기본적으로는 사용 가능한 모든 GPU를 사용합니다) +- strategy 객체를 사용해 scope를 열고, 이 scope 내에서 변수를 포함하는 모든 Keras 객체를 생성합니다. + 일반적으로, **모델 생성 및 컴파일**은 분산 scope 내에서 이루어져야 합니다. + 일부 경우에는, `fit()` 호출 시에도 변수가 생성될 수 있으므로, + `fit()` 호출도 scope 내에서 이루어지도록 하는 것이 좋습니다. +- `fit()`을 통해 모델을 트레이닝합니다. -Importantly, we recommend that you use [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) objects to load data in a multi-device or distributed workflow. +중요한 점으로, 멀티 디바이스 또는 분산 워크플로에서 데이터를 로드하려면, +[`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) 객체를 사용하는 것을 권장합니다. -Schematically, it looks like this: +대략적인 흐름은 다음과 같습니다: ```python -# Create a MirroredStrategy. +# MirroredStrategy 생성 strategy = tf.distribute.MirroredStrategy() print('Number of devices: {}'.format(strategy.num_replicas_in_sync)) -# Open a strategy scope. +# strategy scope 열기 with strategy.scope(): - # Everything that creates variables should be under the strategy scope. - # In general this is only model construction & `compile()`. + # 변수를 생성하는 모든 작업은 strategy scope 내에서 이루어져야 합니다. + # 일반적으로 모델 생성 및 `compile()`입니다. model = Model(...) model.compile(...) - # Train the model on all available devices. + # 사용 가능한 모든 디바이스에서 모델 트레이닝 model.fit(train_dataset, validation_data=val_dataset, ...) - # Test the model on all available devices. + # 사용 가능한 모든 디바이스에서 모델 평가 model.evaluate(test_dataset) ``` -Here's a simple end-to-end runnable example: +다음은 실행 가능한 간단한 엔드투엔드 예제입니다: ```python def get_compiled_model(): - # Make a simple 2-layer densely-connected neural network. + # 간단한 2 레이어 Dense 신경망을 만듭니다. inputs = keras.Input(shape=(784,)) x = keras.layers.Dense(256, activation="relu")(inputs) x = keras.layers.Dense(256, activation="relu")(x) @@ -108,16 +133,16 @@ def get_dataset(): batch_size = 32 num_val_samples = 10000 - # Return the MNIST dataset in the form of a [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset). + # [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) 형식으로 MNIST 데이터셋을 반환합니다. (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() - # Preprocess the data (these are Numpy arrays) + # 데이터를 전처리합니다. (이들은 Numpy 배열입니다) x_train = x_train.reshape(-1, 784).astype("float32") / 255 x_test = x_test.reshape(-1, 784).astype("float32") / 255 y_train = y_train.astype("float32") y_test = y_test.astype("float32") - # Reserve num_val_samples samples for validation + # num_val_samples 샘플을 검증용으로 예약합니다. x_val = x_train[-num_val_samples:] y_val = y_train[-num_val_samples:] x_train = x_train[:-num_val_samples] @@ -129,21 +154,21 @@ def get_dataset(): ) -# Create a MirroredStrategy. +# MirroredStrategy를 생성합니다. strategy = tf.distribute.MirroredStrategy() print("Number of devices: {}".format(strategy.num_replicas_in_sync)) -# Open a strategy scope. +# strategy scope를 엽니다. with strategy.scope(): - # Everything that creates variables should be under the strategy scope. - # In general this is only model construction & `compile()`. + # 변수를 생성하는 모든 작업은 strategy scope 내에서 이루어져야 합니다. + # 일반적으로 모델 생성 및 `compile()`입니다. model = get_compiled_model() - # Train the model on all available devices. + # 사용 가능한 모든 디바이스에서 모델을 트레이닝합니다. train_dataset, val_dataset, test_dataset = get_dataset() model.fit(train_dataset, epochs=2, validation_data=val_dataset) - # Test the model on all available devices. + # 사용 가능한 모든 디바이스에서 모델을 테스트합니다. model.evaluate(test_dataset) ``` @@ -161,22 +186,25 @@ Epoch 2/2 {{% /details %}} -## Using callbacks to ensure fault tolerance +## 콜백을 사용하여 장애 복원력(fault tolerance) 보장하기 {#using-callbacks-to-ensure-fault-tolerance} -When using distributed training, you should always make sure you have a strategy to recover from failure (fault tolerance). The simplest way to handle this is to pass `ModelCheckpoint` callback to `fit()`, to save your model at regular intervals (e.g. every 100 batches or every epoch). You can then restart training from your saved model. +분산 트레이닝을 사용할 때, 항상 장애 복원력을 위한 전략을 세워야 합니다. +가장 간단한 방법은 `ModelCheckpoint` 콜백을 `fit()`에 전달하여, +일정 간격마다 모델을 저장하는 것입니다. (예: 매 100 배치마다 또는 매 에포크마다) +이렇게 하면, 저장된 모델에서 트레이닝을 재시작할 수 있습니다. -Here's a simple example: +다음은 간단한 예시입니다: ```python -# Prepare a directory to store all the checkpoints. +# 체크포인트를 저장할 디렉토리를 준비합니다. checkpoint_dir = "./ckpt" if not os.path.exists(checkpoint_dir): os.makedirs(checkpoint_dir) def make_or_restore_model(): - # Either restore the latest model, or create a fresh one - # if there is no checkpoint available. + # 체크포인트가 있으면 최신 모델을 복원하고, + # 체크포인트가 없으면 새로운 모델을 생성합니다. checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)] if checkpoints: latest_checkpoint = max(checkpoints, key=os.path.getctime) @@ -187,16 +215,16 @@ def make_or_restore_model(): def run_training(epochs=1): - # Create a MirroredStrategy. + # MirroredStrategy를 생성합니다. strategy = tf.distribute.MirroredStrategy() - # Open a strategy scope and create/restore the model + # strategy scope를 열고 모델을 생성하거나 복원합니다. with strategy.scope(): model = make_or_restore_model() callbacks = [ - # This callback saves a SavedModel every epoch - # We include the current epoch in the folder name. + # 이 콜백은 매 에포크마다 SavedModel을 저장합니다. + # 현재 에포크를 폴더 이름에 포함시킵니다. keras.callbacks.ModelCheckpoint( filepath=checkpoint_dir + "/ckpt-{epoch}.keras", save_freq="epoch", @@ -211,10 +239,10 @@ def run_training(epochs=1): ) -# Running the first time creates the model +# 처음 실행 시 모델을 생성합니다. run_training(epochs=1) -# Calling the same function again will resume from where we left off +# 같은 함수를 다시 호출하면 이전 상태에서 재개합니다. run_training(epochs=1) ``` @@ -231,26 +259,36 @@ Restoring from ./ckpt/ckpt-1.keras {{% /details %}} -## [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) performance tips +## [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) 성능 팁 {#tfdata} -When doing distributed training, the efficiency with which you load data can often become critical. Here are a few tips to make sure your [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) pipelines run as fast as possible. +분산 트레이닝을 수행할 때, 데이터를 로드하는 효율성이 매우 중요해질 수 있습니다. +[`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) +파이프라인을 가능한 한 빠르게 실행하는 몇 가지 팁을 소개합니다. -**Note about dataset batching** +**데이터셋 배치에 대한 주의사항** -When creating your dataset, make sure it is batched with the global batch size. For instance, if each of your 8 GPUs is capable of running a batch of 64 samples, you call use a global batch size of 512. +데이터셋을 생성할 때, 글로벌 배치 크기로 배치되었는지 확인하세요. +예를 들어, 8개의 GPU 각각이 64개의 샘플로 구성된 배치를 실행할 수 있는 경우, +글로벌 배치 크기는 512로 설정합니다. -**Calling `dataset.cache()`** +**`dataset.cache()` 호출** -If you call `.cache()` on a dataset, its data will be cached after running through the first iteration over the data. Every subsequent iteration will use the cached data. The cache can be in memory (default) or to a local file you specify. +데이터셋에서 `.cache()`를 호출하면, 첫 번째 반복 이후 데이터가 캐시됩니다. +이후 모든 반복에서는 캐시된 데이터를 사용하게 됩니다. +캐시는 기본적으로 메모리에 저장되며, 또는 사용자가 지정한 로컬 파일에 저장할 수 있습니다. -This can improve performance when: +이 방법은 다음과 같은 경우, 성능을 향상시킬 수 있습니다: -- Your data is not expected to change from iteration to iteration -- You are reading data from a remote distributed filesystem -- You are reading data from local disk, but your data would fit in memory and your workflow is significantly IO-bound (e.g. reading & decoding image files). +- 데이터가 반복마다 변경되지 않는 경우 +- 데이터를 원격 분산 파일 시스템에서 읽어오는 경우 +- 데이터를 로컬 디스크에서 읽어오고, 데이터가 메모리에 fit하며, + 워크플로우가 주로 IO 바운드인 경우 (예: 이미지 파일 읽기 및 디코딩) -**Calling `dataset.prefetch(buffer_size)`** +**`dataset.prefetch(buffer_size)` 호출** -You should almost always call `.prefetch(buffer_size)` after creating a dataset. It means your data pipeline will run asynchronously from your model, with new samples being preprocessed and stored in a buffer while the current batch samples are used to train the model. The next batch will be prefetched in GPU memory by the time the current batch is over. +데이터셋을 생성한 후에는 거의 항상 `.prefetch(buffer_size)`를 호출하는 것이 좋습니다. +이 방법은 데이터 파이프라인이 모델과 비동기적으로 실행되도록 하여, +현재 배치가 트레이닝되는 동안 다음 배치의 샘플을 미리 처리하고 버퍼에 저장합니다. +현재 배치가 완료될 때쯤이면 다음 배치가 GPU 메모리로 미리 로드됩니다. -That's it! +이것이 전부입니다! diff --git a/content/korean/docs/guides/distributed_training_with_torch/_index.md b/content/korean/docs/guides/distributed_training_with_torch/_index.md index 1645e5ca..cc9bbcf1 100644 --- a/content/korean/docs/guides/distributed_training_with_torch/_index.md +++ b/content/korean/docs/guides/distributed_training_with_torch/_index.md @@ -1,6 +1,6 @@ --- -title: Multi-GPU distributed training with PyTorch -linkTitle: Distributed training with PyTorch +title: PyTorch로 멀티 GPU 분산 트레이닝하기 +linkTitle: PyTorch 분산 트레이닝 toc: true weight: 17 type: docs @@ -11,28 +11,39 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2023/06/29 **{{< t f_last_modified >}}** 2023/06/29 -**{{< t f_description >}}** Guide to multi-GPU training for Keras models with PyTorch. +**{{< t f_description >}}** PyTorch로 Keras 모델을 사용하여, 멀티 GPU 트레이닝을 진행하는 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/distributed_training_with_torch.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/distributed_training_with_torch.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -There are generally two ways to distribute computation across multiple devices: +일반적으로 여러 디바이스에 계산을 분산시키는 방법에는 두 가지가 있습니다: -**Data parallelism**, where a single model gets replicated on multiple devices or multiple machines. Each of them processes different batches of data, then they merge their results. There exist many variants of this setup, that differ in how the different model replicas merge results, in whether they stay in sync at every batch or whether they are more loosely coupled, etc. +- **데이터 병렬 처리** + - **데이터 병렬 처리**에서는 하나의 모델이 여러 장치나 여러 머신에 복제됩니다. + - 각 장치는 서로 다른 배치의 데이터를 처리한 후, 결과를 병합합니다. + - 이 설정에는 다양한 변형이 있으며, 서로 다른 모델 복제본이 결과를 병합하는 방식이나, + 각 배치마다 동기화되는지 여부 등에 차이가 있습니다. +- **모델 병렬 처리** + - **모델 병렬 처리**에서는 하나의 모델의 다른 부분이 서로 다른 장치에서 실행되어, 하나의 데이터 배치를 함께 처리합니다. + - 이는 여러 가지 브랜치를 특징으로 하는 자연스럽게 병렬화된 아키텍처를 가진 모델에 가장 적합합니다. -**Model parallelism**, where different parts of a single model run on different devices, processing a single batch of data together. This works best with models that have a naturally-parallel architecture, such as models that feature multiple branches. +이 가이드는 데이터 병렬 처리, 특히 **동기식 데이터 병렬 처리**에 중점을 둡니다. +여기서 모델의 서로 다른 복제본은 각 배치를 처리한 후 동기화됩니다. +동기화는 모델의 수렴 동작을 단일 장치에서의 트레이닝과 동일하게 유지시킵니다. -This guide focuses on data parallelism, in particular **synchronous data parallelism**, where the different replicas of the model stay in sync after each batch they process. Synchronicity keeps the model convergence behavior identical to what you would see for single-device training. +특히, 이 가이드는 PyTorch의 `DistributedDataParallel` 모듈 래퍼를 사용하여, +Keras를 여러 GPU(일반적으로 2~16개)에서 트레이닝하는 방법을 가르칩니다. +이 설정은 단일 머신에 설치된 여러 GPU를 사용하는 싱글 호스트, 멀티 디바이스 트레이닝으로, +연구자들과 소규모 산업 워크플로우에서 가장 일반적으로 사용됩니다. -Specifically, this guide teaches you how to use PyTorch's `DistributedDataParallel` module wrapper to train Keras, with minimal changes to your code, on multiple GPUs (typically 2 to 16) installed on a single machine (single host, multi-device training). This is the most common setup for researchers and small-scale industry workflows. +## 셋업 {#setup} -## Setup - -Let's start by defining the function that creates the model that we will train, and the function that creates the dataset we will train on (MNIST in this case). +먼저, 우리가 트레이닝할 모델을 생성하는 함수와, +트레이닝할 데이터셋(MNIST)을 생성하는 함수를 정의해봅시다. ```python import os @@ -45,7 +56,7 @@ import keras def get_model(): - # Make a simple convnet with batch normalization and dropout. + # 배치 정규화와 드롭아웃이 포함된, 간단한 컨브넷(convnet)을 만듭니다. inputs = keras.Input(shape=(28, 28, 1)) x = keras.layers.Rescaling(1.0 / 255.0)(inputs) x = keras.layers.Conv2D(filters=12, kernel_size=3, padding="same", use_bias=False)( @@ -79,25 +90,25 @@ def get_model(): def get_dataset(): - # Load the data and split it between train and test sets + # 데이터를 불러오고, 트레이닝과 테스트 세트로 나눕니다. (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() - # Scale images to the [0, 1] range + # 이미지를 [0, 1] 범위로 스케일링합니다. x_train = x_train.astype("float32") x_test = x_test.astype("float32") - # Make sure images have shape (28, 28, 1) + # 이미지가 (28, 28, 1) shape을 가지도록 합니다. x_train = np.expand_dims(x_train, -1) x_test = np.expand_dims(x_test, -1) print("x_train shape:", x_train.shape) - # Create a TensorDataset + # TensorDataset을 생성합니다. dataset = torch.utils.data.TensorDataset( torch.from_numpy(x_train), torch.from_numpy(y_train) ) return dataset ``` -Next, let's define a simple PyTorch training loop that targets a GPU (note the calls to `.cuda()`). +이제 GPU를 대상으로 하는 간단한 PyTorch 트레이닝 루프를 정의해보겠습니다. (`.cuda()` 호출에 주목하세요) ```python def train_model(model, dataloader, num_epochs, optimizer, loss_fn): @@ -108,11 +119,11 @@ def train_model(model, dataloader, num_epochs, optimizer, loss_fn): inputs = inputs.cuda(non_blocking=True) targets = targets.cuda(non_blocking=True) - # Forward pass + # 순방향 패스 (Forward pass) outputs = model(inputs) loss = loss_fn(outputs, targets) - # Backward and optimize + # 역방향 패스 및 최적화 (Backward and optimize) optimizer.zero_grad() loss.backward() optimizer.step() @@ -120,39 +131,54 @@ def train_model(model, dataloader, num_epochs, optimizer, loss_fn): running_loss += loss.item() running_loss_count += 1 - # Print loss statistics + # 손실 통계 출력 print( f"Epoch {epoch + 1}/{num_epochs}, " f"Loss: {running_loss / running_loss_count}" ) ``` -## Single-host, multi-device synchronous training +## 단일 호스트, 다중 장치 동기 트레이닝 {#single-host-multi-device-synchronous-training} -In this setup, you have one machine with several GPUs on it (typically 2 to 16). Each device will run a copy of your model (called a **replica**). For simplicity, in what follows, we'll assume we're dealing with 8 GPUs, at no loss of generality. +이 설정에서는, 여러 개의 GPU가 있는 하나의 머신(일반적으로 2~16개의 GPU)에서 트레이닝을 진행합니다. +각 디바이스는 **복제본(replica)**이라고 불리는 모델의 사본을 실행합니다. +간단히 설명하기 위해, 다음 내용에서는 8개의 GPU를 사용하는 것으로 가정하겠습니다. 이는 일반성을 잃지 않습니다.​ -**How it works** +**작동 방식** -At each step of training: +트레이닝의 각 단계에서: -- The current batch of data (called **global batch**) is split into 8 different sub-batches (called **local batches**). For instance, if the global batch has 512 samples, each of the 8 local batches will have 64 samples. -- Each of the 8 replicas independently processes a local batch: they run a forward pass, then a backward pass, outputting the gradient of the weights with respect to the loss of the model on the local batch. -- The weight updates originating from local gradients are efficiently merged across the 8 replicas. Because this is done at the end of every step, the replicas always stay in sync. +- 현재 데이터 배치(**글로벌 배치**)는 8개의 서로 다른 하위 배치(**로컬 배치**)로 나뉩니다. + 예를 들어, 글로벌 배치에 512개의 샘플이 있으면, 8개의 로컬 배치 각각에는 64개의 샘플이 포함됩니다. +- 8개의 복제본 각각은 로컬 배치를 독립적으로 처리합니다: + 순전파를 실행한 후, 역전파를 수행하여, 모델 손실에 대한 가중치의 그래디언트를 출력합니다. +- 로컬 그래디언트로부터 발생한 가중치 업데이트는 8개의 복제본 간에 효율적으로 병합됩니다. + 이 병합은 각 스텝이 끝날 때 이루어지기 때문에, 복제본은 항상 동기화된 상태를 유지합니다. -In practice, the process of synchronously updating the weights of the model replicas is handled at the level of each individual weight variable. This is done through a **mirrored variable** object. +실제로, 모델 레플리카의 가중치를 동기적으로 업데이트하는 과정은 각 개별 가중치 변수 레벨에서 처리됩니다. +이는 **미러드 변수(mirrored variable)** 객체를 통해 이루어집니다. -**How to use it** +**사용 방법** -To do single-host, multi-device synchronous training with a Keras model, you would use the `torch.nn.parallel.DistributedDataParallel` module wrapper. Here's how it works: +단일 호스트에서 여러 장치로 동기식 트레이닝을 수행하려면, +`torch.nn.parallel.DistributedDataParallel` 모듈 래퍼를 사용합니다. 아래는 그 동작 방식입니다: -- We use `torch.multiprocessing.start_processes` to start multiple Python processes, one per device. Each process will run the `per_device_launch_fn` function. -- The `per_device_launch_fn` function does the following: - It uses `torch.distributed.init_process_group` and `torch.cuda.set_device` to configure the device to be used for that process. - It uses `torch.utils.data.distributed.DistributedSampler` and `torch.utils.data.DataLoader` to turn our data into a distributed data loader. - It also uses `torch.nn.parallel.DistributedDataParallel` to turn our model into a distributed PyTorch module. - It then calls the `train_model` function. -- The `train_model` function will then run in each process, with the model using a separate device in each process. +- `torch.multiprocessing.start_processes`를 사용하여 장치별로 하나의 프로세스를 시작합니다. + 각 프로세스는 `per_device_launch_fn` 함수를 실행합니다. +- `per_device_launch_fn` 함수는 다음과 같은 작업을 수행합니다: + - `torch.distributed.init_process_group`과 `torch.cuda.set_device`를 사용하여, + 해당 프로세스에서 사용할 장치를 설정합니다. + - `torch.utils.data.distributed.DistributedSampler`와 `torch.utils.data.DataLoader`를 사용하여, + 데이터를 분산 데이터 로더로 변환합니다. + - `torch.nn.parallel.DistributedDataParallel`을 사용하여, + 모델을 분산된 PyTorch 모듈로 변환합니다. + - 그런 다음 `train_model` 함수를 호출합니다. +- `train_model` 함수는 각 프로세스에서 실행되며, 각 프로세스에서 모델은 별도의 장치를 사용합니다. -Here's the flow, where each step is split into its own utility function: +다음은 각 단계를 유틸리티 함수로 나눈 흐름입니다: ```python -# Config +# 설정 num_gpu = torch.cuda.device_count() num_epochs = 2 batch_size = 64 @@ -160,7 +186,7 @@ print(f"Running on {num_gpu} GPUs") def setup_device(current_gpu_index, num_gpus): - # Device setup + # 장치 설정 os.environ["MASTER_ADDR"] = "localhost" os.environ["MASTER_PORT"] = "56492" device = torch.device("cuda:{}".format(current_gpu_index)) @@ -194,22 +220,22 @@ def prepare_dataloader(dataset, current_gpu_index, num_gpus, batch_size): def per_device_launch_fn(current_gpu_index, num_gpu): - # Setup the process groups + # 프로세스 그룹 설정 setup_device(current_gpu_index, num_gpu) dataset = get_dataset() model = get_model() - # prepare the dataloader + # 데이터 로더 준비 dataloader = prepare_dataloader(dataset, current_gpu_index, num_gpu, batch_size) - # Instantiate the torch optimizer + # torch 옵티마이저 생성 optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) - # Instantiate the torch loss function + # torch 손실 함수 생성 loss_fn = torch.nn.CrossEntropyLoss() - # Put model on device + # 모델을 장치에 배치 model = model.to(current_gpu_index) ddp_model = torch.nn.parallel.DistributedDataParallel( model, device_ids=[current_gpu_index], output_device=current_gpu_index @@ -231,11 +257,11 @@ Running on 0 GPUs {{% /details %}} -Time to start multiple processes: +멀티 프로세스를 시작하는 시간입니다: ```python if __name__ == "__main__": - # We use the "fork" method rather than "spawn" to support notebooks + # notebooks을 지원하기 위해, "spawn" 대신 "fork" 방식을 사용합니다. torch.multiprocessing.start_processes( per_device_launch_fn, args=(num_gpu,), @@ -245,4 +271,4 @@ if __name__ == "__main__": ) ``` -That's it! +이제 끝났습니다! diff --git a/content/korean/docs/guides/distribution/_index.md b/content/korean/docs/guides/distribution/_index.md index 90218809..791815e2 100644 --- a/content/korean/docs/guides/distribution/_index.md +++ b/content/korean/docs/guides/distribution/_index.md @@ -1,6 +1,6 @@ --- -title: Distributed training with Keras 3 -linkTitle: Distributed training with Keras 3 +title: Keras 3으로 분산 트레이닝하기 +linkTitle: Keras 3 분산 트레이닝 toc: true weight: 18 type: docs @@ -11,85 +11,111 @@ type: docs **{{< t f_author >}}** [Qianli Zhu](https://github.com/qlzh727) **{{< t f_date_created >}}** 2023/11/07 **{{< t f_last_modified >}}** 2023/11/07 -**{{< t f_description >}}** Complete guide to the distribution API for multi-backend Keras. +**{{< t f_description >}}** 멀티 백엔드 Keras를 위한 분산 API에 대한 완벽 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/distribution.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/distribution.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -The Keras distribution API is a new interface designed to facilitate distributed deep learning across a variety of backends like JAX, TensorFlow and PyTorch. This powerful API introduces a suite of tools enabling data and model parallelism, allowing for efficient scaling of deep learning models on multiple accelerators and hosts. Whether leveraging the power of GPUs or TPUs, the API provides a streamlined approach to initializing distributed environments, defining device meshes, and orchestrating the layout of tensors across computational resources. Through classes like `DataParallel` and `ModelParallel`, it abstracts the complexity involved in parallel computation, making it easier for developers to accelerate their machine learning workflows. +Keras 분산 API는 JAX, TensorFlow, PyTorch와 같은 +다양한 백엔드에서 분산 딥러닝을 용이하게 하기 위해 설계된 새로운 인터페이스입니다. +이 강력한 API는 데이터 및 모델 병렬 처리를 가능하게 하는 도구 모음을 제공하며, +여러 가속기 및 호스트에서 딥러닝 모델을 효율적으로 확장할 수 있습니다. +GPU나 TPU의 성능을 활용하든, API는 +분산 환경 초기화, 디바이스 메시 정의, 텐서의 계산 리소스 간 레이아웃 조정을 위한 간소화된 접근 방식을 제공합니다. +`DataParallel` 및 `ModelParallel`과 같은 클래스를 통해, +병렬 계산의 복잡성을 추상화하여, +개발자가 기계 학습 워크플로우를 가속화하는 것을 보다 쉽게 만듭니다. -## How it works +## 작동 방식 {#how-it-works} -The Keras distribution API provides a global programming model that allows developers to compose applications that operate on tensors in a global context (as if working with a single device) while automatically managing distribution across many devices. The API leverages the underlying framework (e.g. JAX) to distribute the program and tensors according to the sharding directives through a procedure called single program, multiple data (SPMD) expansion. +Keras 분산 API는 글로벌 프로그래밍 모델을 제공하여, +개발자가 마치 단일 장치에서 작업하는 것처럼, +글로벌 컨텍스트에서 텐서 연산을 구성할 수 있게 합니다. +이 과정에서 API는 여러 장치에 걸쳐 분산을 자동으로 관리합니다. +API는 기본 프레임워크(JAX 등)를 활용하여, +프로그램과 텐서를 샤딩 지시어(sharding directives)에 따라 분산시키며, +이 과정을 단일 프로그램 다중 데이터(SPMD, single program, multiple data) 확장이라고 합니다. -By decoupling the application from sharding directives, the API enables running the same application on a single device, multiple devices, or even multiple clients, while preserving its global semantics. +응용 프로그램을 샤딩 지시어와 분리함으로써, +API는 동일한 응용 프로그램을 단일 장치, 다중 장치 또는 여러 클라이언트에서 실행할 수 있도록 하며, +글로벌 시맨틱을 유지합니다. -## Setup +## 셋업 {#setup} ```python import os -# The distribution API is only implemented for the JAX backend for now. +# 분산 API는 현재 JAX 백엔드에서만 구현되어 있습니다. os.environ["KERAS_BACKEND"] = "jax" import keras from keras import layers import jax import numpy as np -from tensorflow import data as tf_data # For dataset input. +from tensorflow import data as tf_data # 데이터셋 입력을 위한 모듈. ``` -## `DeviceMesh` and `TensorLayout` +## `DeviceMesh` 및 `TensorLayout` {#devicemesh-and-tensorlayout} -The [`keras.distribution.DeviceMesh`]({{< relref "/docs/api/distribution/layout_map#devicemesh-class" >}}) class in Keras distribution API represents a cluster of computational devices configured for distributed computation. It aligns with similar concepts in [`jax.sharding.Mesh`](https://jax.readthedocs.io/en/latest/jax.sharding.html#jax.sharding.Mesh) and [`tf.dtensor.Mesh`](https://www.tensorflow.org/api_docs/python/tf/experimental/dtensor/Mesh), where it's used to map the physical devices to a logical mesh structure. +Keras 분산 API의 [`keras.distribution.DeviceMesh`]({{< relref "/docs/api/distribution/layout_map#devicemesh-class" >}}) 클래스는 분산 계산을 위해 구성된, 컴퓨팅 장치 클러스터를 나타냅니다. +이는 [`jax.sharding.Mesh`](https://jax.readthedocs.io/en/latest/jax.sharding.html#jax.sharding.Mesh) 및 [`tf.dtensor.Mesh`](https://www.tensorflow.org/api_docs/python/tf/experimental/dtensor/Mesh)와 유사한 개념으로, +물리적 장치를 논리적 메쉬 구조에 매핑하는 데 사용됩니다. -The `TensorLayout` class then specifies how tensors are distributed across the `DeviceMesh`, detailing the sharding of tensors along specified axes that correspond to the names of the axes in the `DeviceMesh`. +그 후 `TensorLayout` 클래스는 지정된 축을 따라 +텐서가 어떻게 `DeviceMesh`에 분산되는지 명시하며, +이 축들은 `DeviceMesh`의 축 이름과 일치합니다. -You can find more detailed concept explainers in the [TensorFlow DTensor guide](https://www.tensorflow.org/guide/dtensor_overview#dtensors_model_of_distributed_tensors). +더 자세한 개념 설명은, [TensorFlow DTensor 가이드](https://www.tensorflow.org/guide/dtensor_overview#dtensors_model_of_distributed_tensors)에서 확인할 수 있습니다. ```python -# Retrieve the local available gpu devices. -devices = jax.devices("gpu") # Assume it has 8 local GPUs. +# 로컬에서 사용 가능한 GPU 장치를 검색합니다. +devices = jax.devices("gpu") # 8개의 로컬 GPU가 있다고 가정합니다. -# Define a 2x4 device mesh with data and model parallel axes +# 데이터 및 모델 병렬 축을 가진 2x4 장치 메쉬를 정의합니다. mesh = keras.distribution.DeviceMesh( shape=(2, 4), axis_names=["data", "model"], devices=devices ) -# A 2D layout, which describes how a tensor is distributed across the -# mesh. The layout can be visualized as a 2D grid with "model" as rows and -# "data" as columns, and it is a [4, 2] grid when it mapped to the physical -# devices on the mesh. +# 텐서가 메쉬에 어떻게 분산되는지 설명하는 2D 레이아웃. +# 레이아웃은 "model"을 행으로, "data"를 열로 하는 2D 그리드로 시각화할 수 있으며, +# 물리적 장치에 매핑될 때 [4, 2] 그리드입니다. layout_2d = keras.distribution.TensorLayout(axes=("model", "data"), device_mesh=mesh) -# A 4D layout which could be used for data parallel of a image input. +# 이미지 입력의 데이터 병렬에 사용할 수 있는 4D 레이아웃. replicated_layout_4d = keras.distribution.TensorLayout( axes=("data", None, None, None), device_mesh=mesh ) ``` -## Distribution +## `Distribution` {#distribution} -The `Distribution` class in Keras serves as a foundational abstract class designed for developing custom distribution strategies. It encapsulates the core logic needed to distribute a model's variables, input data, and intermediate computations across a device mesh. As an end user, you won't have to interact directly with this class, but its subclasses like `DataParallel` or `ModelParallel`. +Keras의 `Distribution` 클래스는 커스텀 분산 전략을 개발하기 위한 기초적인 추상 클래스입니다. +이 클래스는 장치 메쉬(device mesh)에 걸쳐 +모델의 변수, 입력 데이터 및 중간 계산을 분산하는 핵심 로직을 캡슐화합니다. +일반 사용자로서는 이 클래스를 직접 사용할 필요가 없으며, +대신 `DataParallel` 또는 `ModelParallel`과 같은 하위 클래스를 사용하게 됩니다. -## DataParallel +## `DataParallel` {#dataparallel} -The `DataParallel` class in the Keras distribution API is designed for the data parallelism strategy in distributed training, where the model weights are replicated across all devices in the `DeviceMesh`, and each device processes a portion of the input data. +`DataParallel` 클래스는 Keras 분산 API에서 +분산 트레이닝의 데이터 병렬 처리를 위한 전략으로 설계되었으며, +`DeviceMesh` 내 모든 장치에 걸쳐 모델 가중치가 복제되고, +각 장치가 입력 데이터의 일부를 처리하는 방식입니다. -Here is a sample usage of this class. +다음은 `DataParallel` 클래스를 사용하는 예시입니다. ```python -# Create DataParallel with list of devices. -# As a shortcut, the devices can be skipped, -# and Keras will detect all local available devices. -# E.g. data_parallel = DataParallel() +# 장치 목록을 사용하여 DataParallel 생성. +# shortcut으로서 장치 목록을 생략하면, +# Keras가 모든 로컬 가용 장치를 자동으로 감지합니다. +# 예: data_parallel = DataParallel() data_parallel = keras.distribution.DataParallel(devices=devices) -# Or you can choose to create DataParallel with a 1D `DeviceMesh`. +# 또는 1D `DeviceMesh`로 DataParallel을 생성할 수 있습니다. mesh_1d = keras.distribution.DeviceMesh( shape=(8,), axis_names=["data"], devices=devices ) @@ -99,15 +125,15 @@ inputs = np.random.normal(size=(128, 28, 28, 1)) labels = np.random.normal(size=(128, 10)) dataset = tf_data.Dataset.from_tensor_slices((inputs, labels)).batch(16) -# Set the global distribution. +# 글로벌 분산 설정. keras.distribution.set_distribution(data_parallel) -# Note that all the model weights from here on are replicated to -# all the devices of the `DeviceMesh`. This includes the RNG -# state, optimizer states, metrics, etc. The dataset fed into `model.fit` or -# `model.evaluate` will be split evenly on the batch dimension, and sent to -# all the devices. You don't have to do any manual aggregration of losses, -# since all the computation happens in a global context. +# 여기서부터 모든 모델 가중치는 `DeviceMesh`의 모든 장치에 복제됩니다. +# 여기에는 RNG 상태, 옵티마이저 상태, 메트릭 등이 포함됩니다. +# `model.fit` 또는 `model.evaluate`에 입력되는 데이터셋은, +# 배치 차원에서 고르게 분할되어 모든 장치로 전달됩니다. +# 수동으로 손실을 집계할 필요가 없습니다. +# 모든 계산은 전역 컨텍스트에서 수행됩니다. inputs = layers.Input(shape=(28, 28, 1)) y = layers.Flatten()(inputs) y = layers.Dense(units=200, use_bias=False, activation="relu")(y) @@ -136,28 +162,43 @@ Epoch 3/3 {{% /details %}} -## `ModelParallel` and `LayoutMap` +## `ModelParallel` 및 `LayoutMap` {#modelparallel-and-layoutmap} -`ModelParallel` will be mostly useful when model weights are too large to fit on a single accelerator. This setting allows you to spit your model weights or activation tensors across all the devices on the `DeviceMesh`, and enable the horizontal scaling for the large models. +`ModelParallel`은 모델 가중치가 단일 가속기에 맞지 않을 때 유용하게 사용됩니다. +이 설정을 통해 모델 가중치나 활성화 텐서를 `DeviceMesh`의 모든 장치에 분산하여, +대규모 모델을 수평적으로 확장할 수 있습니다. -Unlike the `DataParallel` model where all weights are fully replicated, the weights layout under `ModelParallel` usually need some customization for best performances. We introduce `LayoutMap` to let you specify the `TensorLayout` for any weights and intermediate tensors from global perspective. +`DataParallel` 모델에서는 모든 가중치가 완전히 복제되지만, +`ModelParallel`에서는 최적의 성능을 위해 가중치 레이아웃을 커스터마이즈해야 할 때가 많습니다. +이를 위해 `LayoutMap`을 사용하여, +글로벌 관점에서 모든 가중치와 중간 텐서에 대해, `TensorLayout`을 지정할 수 있습니다. -`LayoutMap` is a dict-like object that maps a string to `TensorLayout` instances. It behaves differently from a normal Python dict in that the string key is treated as a regex when retrieving the value. The class allows you to define the naming schema of `TensorLayout` and then retrieve the corresponding `TensorLayout` instance. Typically, the key used to query is the `variable.path` attribute, which is the identifier of the variable. As a shortcut, a tuple or list of axis names is also allowed when inserting a value, and it will be converted to `TensorLayout`. +`LayoutMap`은 문자열을 `TensorLayout` 인스턴스와 매핑하는 dict와 유사한 객체입니다. +일반적인 Python dict와 달리, 문자열 키는 값을 검색할 때 정규식으로 처리됩니다. +이 클래스는 `TensorLayout`의 명명 규칙을 정의하고, +해당하는 `TensorLayout` 인스턴스를 검색할 수 있도록 합니다. +일반적으로, 검색에 사용되는 키는 변수의 식별자인 `variable.path` 속성입니다. +shortcut으로서, 튜플이나 축 이름 목록도 값 삽입 시 허용되며, +자동으로 `TensorLayout`으로 변환됩니다. -The `LayoutMap` can also optionally contain a `DeviceMesh` to populate the `TensorLayout.device_mesh` if it is not set. When retrieving a layout with a key, and if there isn't an exact match, all existing keys in the layout map will be treated as regex and matched against the input key again. If there are multiple matches, a `ValueError` is raised. If no matches are found, `None` is returned. +`LayoutMap`은 선택적으로 `DeviceMesh`를 포함하여, +`TensorLayout.device_mesh`를 설정하지 않았을 때, 자동으로 이를 채울 수 있습니다. +키가 정확히 일치하지 않으면, 기존 키들이 정규식으로 간주되어 입력 키와 다시 비교됩니다. +다수의 매치가 있을 경우 `ValueError`가 발생하고, 매치가 없으면 `None`을 반환합니다. ```python mesh_2d = keras.distribution.DeviceMesh( shape=(2, 4), axis_names=["data", "model"], devices=devices ) layout_map = keras.distribution.LayoutMap(mesh_2d) -# The rule below means that for any weights that match with d1/kernel, it -# will be sharded with model dimensions (4 devices), same for the d1/bias. -# All other weights will be fully replicated. + +# 아래 규칙은 d1/kernel에 매치되는 모든 가중치가 모델 차원(4개의 장치)으로 +# 분할된다는 의미입니다. d1/bias도 동일하게 설정됩니다. +# 그 외의 모든 가중치는 완전히 복제됩니다. layout_map["d1/kernel"] = (None, "model") layout_map["d1/bias"] = ("model",) -# You can also set the layout for the layer output like +# 레이어 출력의 레이아웃도 설정할 수 있습니다. layout_map["d2/output"] = ("data", None) model_parallel = keras.distribution.ModelParallel(layout_map, batch_dim_name="data") @@ -171,8 +212,7 @@ y = layers.Dropout(0.4)(y) y = layers.Dense(units=10, activation="softmax", name="d2")(y) model = keras.Model(inputs=inputs, outputs=y) -# The data will be sharded across the "data" dimension of the method, which -# has 2 devices. +# 데이터는 2개의 장치가 있는 "data" 차원으로 분할됩니다. model.compile(loss="mse") model.fit(dataset, epochs=3) model.evaluate(dataset) @@ -199,7 +239,8 @@ Epoch 3/3 {{% /details %}} -It is also easy to change the mesh structure to tune the computation between more data parallel or model parallel. You can do this by adjusting the shape of the mesh. And no changes are needed for any other code. +메시 구조를 변경하여 더 많은 데이터 병렬 처리나 모델 병렬 처리 간의 계산을 조정하는 것도 쉽습니다. +메시의 shape을 조정함으로써 이를 할 수 있습니다. 다른 코드에 대한 변경은 필요하지 않습니다. ```python full_data_parallel_mesh = keras.distribution.DeviceMesh( @@ -216,10 +257,10 @@ full_model_parallel_mesh = keras.distribution.DeviceMesh( ) ``` -### Further reading +### 추가 자료 {#further-reading} -1. [JAX Distributed arrays and automatic parallelization](https://jax.readthedocs.io/en/latest/notebooks/Distributed_arrays_and_automatic_parallelization.html) -2. [JAX sharding module](https://jax.readthedocs.io/en/latest/jax.sharding.html) -3. [TensorFlow Distributed training with DTensors](https://www.tensorflow.org/tutorials/distribute/dtensor_ml_tutorial) -4. [TensorFlow DTensor concepts](https://www.tensorflow.org/guide/dtensor_overview) -5. [Using DTensors with tf.keras](https://www.tensorflow.org/tutorials/distribute/dtensor_keras_tutorial) +1. [JAX 분산 배열 및 자동 병렬화](https://jax.readthedocs.io/en/latest/notebooks/Distributed_arrays_and_automatic_parallelization.html) +2. [JAX sharding 모듈](https://jax.readthedocs.io/en/latest/jax.sharding.html) +3. [TensorFlow DTensors를 사용한 분산 트레이닝](https://www.tensorflow.org/tutorials/distribute/dtensor_ml_tutorial) +4. [TensorFlow DTensor 개념](https://www.tensorflow.org/guide/dtensor_overview) +5. [tf.keras로 DTensors 사용하기](https://www.tensorflow.org/tutorials/distribute/dtensor_keras_tutorial) diff --git a/content/korean/docs/guides/keras_cv/_index.md b/content/korean/docs/guides/keras_cv/_index.md index 107d3d8f..1ab710ba 100644 --- a/content/korean/docs/guides/keras_cv/_index.md +++ b/content/korean/docs/guides/keras_cv/_index.md @@ -8,14 +8,8 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -These guides cover the [KerasCV]({{< relref "/docs/keras_cv" >}}) library. +이 가이드에서는 [KerasCV]({{< relref "/docs/keras_cv" >}}) 라이브러리에 대해 설명합니다. -## Available guides +## 모든 컨텐츠 -- [Use KerasCV to assemble object detection pipelines]({{< relref "/docs/guides/keras_cv/object_detection_keras_cv" >}}) -- [Use KerasCV to train powerful image classifiers.]({{< relref "/docs/guides/keras_cv/classification_with_keras_cv" >}}) -- [CutMix, MixUp, and RandAugment image augmentation with KerasCV]({{< relref "/docs/guides/keras_cv/cut_mix_mix_up_and_rand_augment" >}}) -- [High-performance image generation using Stable Diffusion in KerasCV]({{< relref "/docs/guides/keras_cv/generate_images_with_stable_diffusion" >}}) -- [Custom Image Augmentations with BaseImageAugmentationLayer]({{< relref "/docs/guides/keras_cv/custom_image_augmentations" >}}) -- [Semantic Segmentation with KerasCV]({{< relref "/docs/guides/keras_cv/semantic_segmentation_deeplab_v3_plus" >}}) -- [Segment Anything in KerasCV]({{< relref "/docs/guides/keras_cv/segment_anything_in_keras_cv" >}}) +{{< default-section-cards-list-recursive >}} diff --git a/content/korean/docs/guides/keras_cv/classification_with_keras_cv/_index.md b/content/korean/docs/guides/keras_cv/classification_with_keras_cv/_index.md index 979d9dee..43550ce5 100644 --- a/content/korean/docs/guides/keras_cv/classification_with_keras_cv/_index.md +++ b/content/korean/docs/guides/keras_cv/classification_with_keras_cv/_index.md @@ -1,6 +1,6 @@ --- -title: Classification with KerasCV -linkTitle: Use KerasCV to train powerful image classifiers. +title: KerasCV를 사용하여 강력한 이미지 분류기를 트레이닝 +linkTitle: KerasCV로 분류 toc: true weight: 2 type: docs @@ -11,30 +11,37 @@ type: docs **{{< t f_author >}}** [lukewood](https://lukewood.xyz) **{{< t f_date_created >}}** 03/28/2023 **{{< t f_last_modified >}}** 03/28/2023 -**{{< t f_description >}}** Use KerasCV to train powerful image classifiers. +**{{< t f_description >}}** KerasCV를 사용하여 강력한 이미지 분류기를 트레이닝하세요. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_cv/classification_with_keras_cv.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_cv/classification_with_keras_cv.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -Classification is the process of predicting a categorical label for a given input image. While classification is a relatively straightforward computer vision task, modern approaches still are built of several complex components. Luckily, KerasCV provides APIs to construct commonly used components. +분류는 주어진 입력 이미지에 대한 카테고리형 레이블을 예측하는 프로세스입니다. +분류는 비교적 간단한 컴퓨터 비전 작업이지만, +최신 접근 방식은 여전히 ​​여러 복잡한 구성 요소로 구성되어 있습니다. +다행히도, KerasCV는 일반적으로 사용되는 구성 요소를 구성하는 API를 제공합니다. -This guide demonstrates KerasCV's modular approach to solving image classification problems at three levels of complexity: +이 가이드는 세 가지 레벨의 복잡성에서, +이미지 분류 문제를 해결하는 KerasCV의 모듈식 접근 방식을 보여줍니다. -- Inference with a pretrained classifier -- Fine-tuning a pretrained backbone -- Training a image classifier from scratch +- 사전 트레이닝된 분류기를 사용한 추론 +- 사전 트레이닝된 백본 미세 조정 +- 처음부터 이미지 분류기 트레이닝 -KerasCV uses Keras 3 to work with any of TensorFlow, PyTorch or Jax. In the guide below, we will use the `jax` backend. This guide runs in TensorFlow or PyTorch backends with zero changes, simply update the `KERAS_BACKEND` below. +KerasCV는 Keras 3를 사용하여 TensorFlow, PyTorch 또는 Jax로 작동합니다. +아래 가이드에서는 `jax` 백엔드를 사용합니다. +이 가이드는 변경 사항 없이 TensorFlow 또는 PyTorch 백엔드에서 실행되므로, +아래의 `KERAS_BACKEND`를 업데이트하기만 하면 됩니다. -We use Professor Keras, the official Keras mascot, as a visual reference for the complexity of the material: +공식 Keras 마스코트인 Professor Keras를 자료의 복잡성에 대한 시각적 참조로 사용합니다. ![png](/images/keras-hub/getting_started_guide/prof_keras_evolution.png) ```python !pip install -q --upgrade keras-cv -!pip install -q --upgrade keras # Upgrade to Keras 3. +!pip install -q --upgrade keras # Keras 3으로 업그레이드하세요. ``` ```python @@ -55,20 +62,29 @@ from keras import metrics import keras_cv -# Import tensorflow for [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) and its preprocessing functions +# [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) 및 +# 해당 전처리 함수를 위해 tensorflow를 import 합니다. import tensorflow as tf import tensorflow_datasets as tfds ``` -## Inference with a pretrained classifier +## 사전 트레이닝된 분류기를 사용한 추론 {#inference-with-a-pretrained-classifier} ![png](/images/keras-hub/getting_started_guide/prof_keras_beginner.png) -Let's get started with the simplest KerasCV API: a pretrained classifier. In this example, we will construct a classifier that was pretrained on the ImageNet dataset. We'll use this model to solve the age old "Cat or Dog" problem. +가장 간단한 KerasCV API인 사전 트레이닝된 분류기로 시작해 보겠습니다. +이 예에서는, ImageNet 데이터 세트에 대해 사전 트레이닝된 분류기를 구성합니다. +이 모델을 사용하여 오래된 "Cat or Dog" 문제를 해결합니다. -The highest level module in KerasCV is a _task_. A _task_ is a [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}) consisting of a (generally pretrained) backbone model and task-specific layers. Here's an example using [`keras_cv.models.ImageClassifier`]({{< relref "/docs/api/keras_cv/models/tasks/image_classifier#imageclassifier-class" >}}) with an EfficientNetV2B0 Backbone. +KerasCV의 가장 높은 레벨의 모듈은 _task_ 입니다. +_task_ 는 (일반적으로 사전 트레이닝된) 백본 모델과 작업별 레이어로 구성된 +[`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})입니다. +다음은 EfficientNetV2B0 백본과 함께 [`keras_cv.models.ImageClassifier`]({{< relref "/docs/api/keras_cv/models/tasks/image_classifier#imageclassifier-class" >}})를 사용하는 예입니다. -EfficientNetV2B0 is a great starting model when constructing an image classification pipeline. This architecture manages to achieve high accuracy, while using a parameter count of 7M. If an EfficientNetV2B0 is not powerful enough for the task you are hoping to solve, be sure to check out [KerasCV's other available Backbones](https://github.com/keras-team/keras-cv/tree/master/keras_cv/models/backbones)! +EfficientNetV2B0은 이미지 분류 파이프라인을 구성할 때 좋은 시작 모델입니다. +이 아키텍처는 7M의 매개변수 수를 사용하면서도 높은 정확도를 달성합니다. +EfficientNetV2B0가 해결하고자 하는 작업에 충분히 강력하지 않다면, +[KerasCV의 다른 사용 가능한 백본](https://github.com/keras-team/keras-cv/tree/master/keras_cv/models/backbones)을 확인하세요! ```python classifier = keras_cv.models.ImageClassifier.from_preset( @@ -76,9 +92,12 @@ classifier = keras_cv.models.ImageClassifier.from_preset( ) ``` -You may notice a small deviation from the old `keras.applications` API; where you would construct the class with `EfficientNetV2B0(weights="imagenet")`. While the old API was great for classification, it did not scale effectively to other use cases that required complex architectures, like object detection and semantic segmentation. +이전 `keras.applications` API에서 약간 차이가 있음을 알 수 있습니다. +이전 API에서는 `EfficientNetV2B0(weights="imagenet")`로 클래스를 구성했습니다. +이전 API는 분류에 매우 좋았지만, 객체 감지 및 시맨틱 세그멘테이션과 같이, +복잡한 아키텍처가 필요한 다른 사용 사례에는 효과적으로 확장되지 않았습니다. -Now that our classifier is built, let's apply it to this cute cat picture! +이제 분류기가 구축되었으니, 이 귀여운 고양이 사진에 적용해 보겠습니다! ```python filepath = keras.utils.get_file(origin="https://i.imgur.com/9i63gLN.jpg") @@ -91,7 +110,7 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_7_0.png) -Next, let's get some predictions from our classifier: +다음으로, 분류기로부터 몇 가지 예측을 얻어 보겠습니다. ```python predictions = classifier.predict(np.expand_dims(image, axis=0)) @@ -105,13 +124,17 @@ predictions = classifier.predict(np.expand_dims(image, axis=0)) {{% /details %}} -Predictions come in the form of softmax-ed category rankings. We can find the index of the top classes using a simple argsort function: +예측은 소프트맥스된 카테고리 순위의 형태로 제공됩니다. +간단한 argsort 함수를 사용하여, 상위 클래스의 인덱스를 찾을 수 있습니다. ```python top_classes = predictions[0].argsort(axis=-1) ``` -In order to decode the class mappings, we can construct a mapping from category indices to ImageNet class names. For convenience, I've stored the ImageNet class mapping in a GitHub gist. Let's download and load it now. +클래스 매핑을 디코딩하기 위해, +카테고리 인덱스에서 ImageNet 클래스 이름으로 매핑을 구성할 수 있습니다. +편의상, ImageNet 클래스 매핑을 GitHub gist에 저장했습니다. +지금 다운로드하여 로드해 보겠습니다. ```python classes = keras.utils.get_file( @@ -130,7 +153,7 @@ Downloading data from https://gist.githubusercontent.com/LukeWood/62eebcd5c5c4a4 {{% /details %}} -Now we can simply look up the class names via index: +이제 우리는 인덱스를 통해 간단히 클래스 이름을 조회할 수 있습니다. ```python top_two = [classes[str(i)] for i in top_classes[-2:]] @@ -145,17 +168,28 @@ Top two classes are: ['Egyptian cat', 'velvet'] {{% /details %}} -Great! Both of these appear to be correct! However, one of the classes is "Velvet". We're trying to classify Cats VS Dogs. We don't care about the velvet blanket! +좋습니다! 둘 다 맞는 것 같습니다! +하지만 클래스 중 하나는 "Velvet"입니다. +우리는 Cats VS Dogs를 분류하려고 합니다. +벨벳 담요는 신경 쓰지 않습니다! -Ideally, we'd have a classifier that only performs computation to determine if an image is a cat or a dog, and has all of its resources dedicated to this task. This can be solved by fine tuning our own classifier. +이상적으로는, 이미지가 고양이인지 개인지 판별하기 위한 계산만 수행하고, +모든 리소스를 이 작업에 전념하는 분류기를 갖게 될 것입니다. +이는 우리 자신의 분류기를 미세 조정하여 해결할 수 있습니다. -## Fine tuning a pretrained classifier +## 사전 트레이닝된 분류기 미세 조정 {#fine-tuning-a-pretrained-classifier} ![png](/images/keras-hub/getting_started_guide/prof_keras_intermediate.png) -When labeled images specific to our task are available, fine-tuning a custom classifier can improve performance. If we want to train a Cats vs Dogs Classifier, using explicitly labeled Cat vs Dog data should perform better than the generic classifier! For many tasks, no relevant pretrained model will be available (e.g., categorizing images specific to your application). +작업에 특화된 레이블이 지정된 이미지가 있는 경우, +커스텀 분류기를 미세 조정하면 성능이 향상될 수 있습니다. +Cats vs Dogs 분류기를 트레이닝하려면, +명시적으로 레이블이 지정된 Cat vs Dog 데이터를 사용하면, +일반 분류기보다 성능이 더 좋아야 합니다! +많은 작업의 경우, 관련 사전 트레이닝된 모델을 사용할 수 없습니다. +(예: 당신의 애플리케이션에 특화된 이미지 분류) -First, let's get started by loading some data: +먼저 데이터를 로드하여 시작해 보겠습니다. ```python BATCH_SIZE = 32 @@ -176,13 +210,12 @@ resizing = keras_cv.layers.Resizing( def preprocess_inputs(image, label): image = tf.cast(image, tf.float32) - # Staticly resize images as we only iterate the dataset once. + # 데이터 세트를 한 번만 반복하므로 이미지 크기를 정적으로 조정합니다. return resizing(image), tf.one_hot(label, num_classes) -# Shuffle the dataset to increase diversity of batches. -# 10*BATCH_SIZE follows the assumption that bigger machines can handle bigger -# shuffle buffers. +# 배치의 다양성을 높이기 위해 데이터 세트를 셔플합니다. +# 10*BATCH_SIZE는 더 큰 머신이 더 큰 셔플 버퍼를 처리할 수 있다는 가정을 따릅니다. train_dataset = train_dataset.shuffle( 10 * BATCH_SIZE, reshuffle_each_iteration=True ).map(preprocess_inputs, num_parallel_calls=AUTOTUNE) @@ -196,11 +229,15 @@ keras_cv.visualization.plot_image_gallery(images, value_range=(0, 255)) ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_17_1.png) -Meow! +야옹! -Next let's construct our model. The use of imagenet in the preset name indicates that the backbone was pretrained on the ImageNet dataset. Pretrained backbones extract more information from our labeled examples by leveraging patterns extracted from potentially much larger datasets. +다음으로 모델을 구성해 보겠습니다. +사전 설정 이름에 imagenet을 사용한 것은, +백본이 ImageNet 데이터 세트에 대해 사전 트레이닝되었음을 나타냅니다. +사전 트레이닝된 백본은 잠재적으로 훨씬 더 큰 데이터 세트에서 추출한 패턴을 활용하여, +레이블이 지정된 예제에서 더 많은 정보를 추출합니다. -Next lets put together our classifier: +다음으로 분류기를 구성해 보겠습니다. ```python model = keras_cv.models.ImageClassifier.from_preset( @@ -222,7 +259,8 @@ Downloading data from https://storage.googleapis.com/keras-cv/models/efficientne {{% /details %}} -Here our classifier is just a simple [`keras.Sequential`]({{< relref "/docs/api/models/sequential#sequential-class" >}}). All that is left to do is call `model.fit()`: +여기서 우리의 분류기는 단순한 [`keras.Sequential`]({{< relref "/docs/api/models/sequential#sequential-class" >}})입니다. +남은 것은 `model.fit()`를 호출하는 것뿐입니다. ```python model.fit(train_dataset) @@ -287,7 +325,7 @@ Corrupt JPEG data: 228 extraneous bytes before marker 0xd9 {{% /details %}} -Let's look at how our model performs after the fine tuning: +미세 조정 후 모델이 어떻게 수행되는지 살펴보겠습니다. ```python predictions = model.predict(np.expand_dims(image, axis=0)) @@ -305,19 +343,24 @@ Top class is: cat {{% /details %}} -Awesome - looks like the model correctly classified the image. +훌륭하네요. 모델이 이미지를 올바르게 분류한 것 같습니다. -## Train a Classifier from Scratch +## 처음부터 분류기 트레이닝 {#train-a-classifier-from-scratch} ![png](/images/keras-hub/getting_started_guide/prof_keras_advanced.png) -Now that we've gotten our hands dirty with classification, let's take on one last task: training a classification model from scratch! A standard benchmark for image classification is the ImageNet dataset, however due to licensing constraints we will use the CalTech 101 image classification dataset in this tutorial. While we use the simpler CalTech 101 dataset in this guide, the same training template may be used on ImageNet to achieve near state-of-the-art scores. +이제 분류에 대해 자세히 알아보았으니, 마지막 과제를 하나 해보겠습니다. +분류 모델을 처음부터 트레이닝하는 것입니다! +이미지 분류의 표준 벤치마크는 ImageNet 데이터 세트이지만, +라이선스 제약으로 인해 이 튜토리얼에서는 CalTech 101 이미지 분류 데이터 세트를 사용합니다. +이 가이드에서는 더 간단한 CalTech 101 데이터 세트를 사용하지만, +ImageNet에서는 동일한 트레이닝 템플릿을 사용하여 최신 수준에 가까운 점수를 얻을 수 있습니다. -Let's start out by tackling data loading: +데이터 로딩부터 시작해 보겠습니다. ```python NUM_CLASSES = 101 -# Change epochs to 100~ to fully train. +# 완전히 트레이닝하려면 에포크를 100~로 변경하세요. EPOCHS = 1 @@ -343,7 +386,8 @@ train_ds = train_ds.shuffle(BATCH_SIZE * 16) {{% /details %}} -The CalTech101 dataset has different sizes for every image, so we use the `ragged_batch()` API to batch them together while maintaining each individual image's shape information. +CalTech101 데이터 세트는 각 이미지의 크기가 다르기 때문에, +`ragged_batch()` API를 사용하여 각 개별 이미지의 모양 정보를 유지하면서 이를 배치 처리합니다. ```python train_ds = train_ds.ragged_batch(BATCH_SIZE) @@ -364,15 +408,29 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_28_0.png) -### Data Augmentation +### 데이터 보강 {#data-augmentation} -In our previous finetuning example, we performed a static resizing operation and did not utilize any image augmentation. This is because a single pass over the training set was sufficient to achieve decent results. When training to solve a more difficult task, you'll want to include data augmentation in your data pipeline. +이전 미세 조정 예제에서, 정적 크기 조정 작업을 수행했으며 이미지 보강을 활용하지 않았습니다. +그 이유는 트레이닝 세트에 대한 단일 패스로 적절한 결과를 얻기에 충분했기 때문입니다. +더 어려운 작업을 해결하기 위해, 트레이닝할 때는 데이터 파이프라인에 데이터 보강을 포함해야 합니다. -Data augmentation is a technique to make your model robust to changes in input data such as lighting, cropping, and orientation. KerasCV includes some of the most useful augmentations in the `keras_cv.layers` API. Creating an optimal pipeline of augmentations is an art, but in this section of the guide we'll offer some tips on best practices for classification. +데이터 보강은 조명(lighting), 자르기(cropping), 방향(orientation)과 같은, +입력 데이터의 변경에 대해 모델을 견고하게 만드는 기술입니다. +KerasCV에는 `keras_cv.layers` API에서 가장 유용한 보강 중 일부가 포함되어 있습니다. +보강의 최적 파이프라인을 만드는 것은 예술이지만, +이 가이드의 이 섹션에서는 분류에 대한 모범 사례에 대한 몇 가지 팁을 제공합니다. -One caveat to be aware of with image data augmentation is that you must be careful to not shift your augmented data distribution too far from the original data distribution. The goal is to prevent overfitting and increase generalization, but samples that lie completely out of the data distribution simply add noise to the training process. +이미지 데이터 보강에 주의해야 할 한 가지 주의 사항은, +보강된 데이터 분포를 원래 데이터 분포에서 너무 멀리 옮기지 않도록 주의해야 한다는 것입니다. +목표는 과적합을 방지하고 일반화를 증가시키는 것이지만, +데이터 분포에서 완전히 벗어난 샘플은 단순히 트레이닝 과정에 노이즈를 추가합니다. -The first augmentation we'll use is `RandomFlip`. This augmentation behaves more or less how you'd expect: it either flips the image or not. While this augmentation is useful in CalTech101 and ImageNet, it should be noted that it should not be used on tasks where the data distribution is not vertical mirror invariant. An example of a dataset where this occurs is MNIST hand written digits. Flipping a `6` over the vertical axis will make the digit appear more like a `7` than a `6`, but the label will still show a `6`. +사용할 첫 번째 보강은 `RandomFlip`입니다. 이 보강은 예상한 대로 동작합니다. +즉, 이미지를 뒤집거나 뒤집지 않습니다. +이 보강은 CalTech101 및 ImageNet에서 유용하지만, +데이터 분포가 수직 거울 불변이 아닌 작업에는 사용해서는 안 됩니다. +이런 일이 발생하는 데이터 세트의 예로는 MNIST 손으로 쓴 숫자가 있습니다. +수직 축에서 `6`을 뒤집으면, 숫자가 `6`보다는 `7`처럼 보이지만, 레이블에는 여전히 `6`이 표시됩니다. ```python random_flip = keras_cv.layers.RandomFlip() @@ -390,13 +448,24 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_30_0.png) -Half of the images have been flipped! +이미지의 절반이 뒤집혔습니다! -The next augmentation we'll use is `RandomCropAndResize`. This operation selects a random subset of the image, then resizes it to the provided target size. By using this augmentation, we force our classifier to become spatially invariant. Additionally, this layer accepts an `aspect_ratio_factor` which can be used to distort the aspect ratio of the image. While this can improve model performance, it should be used with caution. It is very easy for an aspect ratio distortion to shift a sample too far from the original training set's data distribution. Remember - the goal of data augmentation is to produce more training samples that align with the data distribution of your training set! +우리가 사용할 다음 보강은 `RandomCropAndResize`입니다. +이 작업은 이미지의 무작위 하위 집합을 선택한 다음, 제공된 대상 크기로 크기를 조정합니다. +이 보강을 사용하면, 분류기가 공간적으로 불변이 되도록 강제합니다. +또한 이 레이어는 이미지의 종횡비를 왜곡하는 데 사용할 수 있는 `aspect_ratio_factor`를 허용합니다. +이렇게 하면, 모델 성능이 향상될 수 있지만 주의해서 사용해야 합니다. +종횡비 왜곡으로 인해 샘플이 원래 트레이닝 세트의 데이터 분포에서 너무 멀리 이동하기 쉽습니다. 기억하세요. +데이터 보강의 목표는 트레이닝 세트의 데이터 분포와 일치하는 더 많은 트레이닝 샘플을 생성하는 것입니다! -`RandomCropAndResize` also can handle [`tf.RaggedTensor`](https://www.tensorflow.org/api_docs/python/tf/RaggedTensor) inputs. In the CalTech101 image dataset images come in a wide variety of sizes. As such they cannot easily be batched together into a dense training batch. Luckily, `RandomCropAndResize` handles the Ragged -> Dense conversion process for you! +`RandomCropAndResize`는 또한 +[`tf.RaggedTensor`](https://www.tensorflow.org/api_docs/python/tf/RaggedTensor) +입력을 처리할 수 있습니다. +CalTech101 이미지 데이터 세트에서 이미지는 다양한 크기로 제공됩니다. +따라서, 밀집된 트레이닝 배치로 쉽게 배치할 수 없습니다. +다행히도 `RandomCropAndResize`가 Ragged -> Dense 변환 프로세스를 처리합니다! -Let's add a `RandomCropAndResize` to our set of augmentations: +보강 세트에 `RandomCropAndResize`를 추가해 보겠습니다. ```python crop_and_resize = keras_cv.layers.RandomCropAndResize( @@ -418,11 +487,21 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_32_0.png) -Great! We are now working with a batch of dense images. Next up, lets include some spatial and color-based jitter to our training set. This will allow us to produce a classifier that is robust to lighting flickers, shadows, and more. +좋습니다! 이제 dense 이미지 배치로 작업합니다. +다음으로, 트레이닝 세트에 공간(spatial) 및 색상 기반 지터(color-based jitter)를 포함하겠습니다. +그러면, 조명 깜빡임, 그림자 등에 견고한 분류기를 생성할 수 있습니다. -There are limitless ways to augment an image by altering color and spatial features, but perhaps the most battle tested technique is [`RandAugment`](https://arxiv.org/abs/1909.13719). `RandAugment` is actually a set of 10 different augmentations: `AutoContrast`, `Equalize`, `Solarize`, `RandomColorJitter`, `RandomContrast`, `RandomBrightness`, `ShearX`, `ShearY`, `TranslateX` and `TranslateY`. At inference time, `num_augmentations` augmenters are sampled for each image, and random magnitude factors are sampled for each. These augmentations are then applied sequentially. +색상과 공간적 특징을 변경하여 이미지를 보강하는 방법은 무한하지만, +아마도 가장 실전에서 검증된 기술은 [`RandAugment`](https://arxiv.org/abs/1909.13719)일 것입니다. +`RandAugment`는 실제로 10가지 다른 보강 세트입니다. +`AutoContrast`, `Equalize`, `Solarize`, `RandomColorJitter`, `RandomContrast`, `RandomBrightness`, `ShearX`, `ShearY`, `TranslateX` 및 `TranslateY`. +추론 시에 각 이미지에 대해 `num_augmentations` 보강기를 샘플링하고, +각 이미지에 대해 무작위 크기 요소를 샘플링합니다. +그런 다음, 이러한 보강을 순차적으로 적용합니다. -KerasCV makes tuning these parameters easy using the `augmentations_per_image` and `magnitude` parameters! Let's take it for a spin: +KerasCV는 `augmentations_per_image` 및 `magnitude` 매개변수를 사용하여, +이러한 매개변수를 쉽게 조정할 수 있도록 합니다! +한 번 돌려봅시다: ```python rand_augment = keras_cv.layers.RandAugment( @@ -446,9 +525,13 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_34_0.png) -Looks great; but we're not done yet! What if an image is missing one critical feature of a class? For example, what if a leaf is blocking the view of a cat's ear, but our classifier learned to classify cats simply by observing their ears? +훌륭해 보이지만 아직 끝나지 않았습니다! +이미지에 클래스의 중요한 특징 하나가 없다면 어떨까요? +예를 들어, 잎이 고양이 귀를 가리고 있지만, +분류기가 고양이의 귀를 관찰하여 고양이를 분류하는 법을 배웠다면 어떨까요? -One easy approach to tackling this is to use `RandomCutout`, which randomly strips out a sub-section of the image: +이 문제를 해결하는 쉬운 방법 중 하나는 `RandomCutout`을 사용하는 것입니다. +이 방법은 이미지의 하위 섹션을 무작위로 제거합니다. ```python random_cutout = keras_cv.layers.RandomCutout(width_factor=0.4, height_factor=0.4) @@ -463,15 +546,20 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_36_16.png) -While this tackles the problem reasonably well, it can cause the classifier to develop responses to borders between features and black pixel areas caused by the cutout. +이 방법은 문제를 비교적 잘 해결하지만, +분류기가 잘린 부분에 의해 발생한 특징과 검은색 픽셀 영역 사이의 경계에 대한 반응을 개발하게 할 수 있습니다. -[`CutMix`](https://arxiv.org/abs/1905.04899) solves the same issue by using a more complex (and more effective) technique. Instead of replacing the cut-out areas with black pixels, `CutMix` replaces these regions with regions of other images sampled from within your training set! Following this replacement, the image's classification label is updated to be a blend of the original and mixed image's class label. +[`CutMix`](https://arxiv.org/abs/1905.04899)는 +더 복잡하고 효과적인 기술을 사용하여 같은 문제를 해결합니다. +잘린 부분을 검은색 픽셀로 대체하는 대신, +`CutMix`는 이러한 영역을 트레이닝 세트 내에서 샘플링한 다른 이미지의 영역으로 대체합니다! +이 대체에 따라, 이미지의 분류 레이블이 원본과 혼합된 이미지의 클래스 레이블을 혼합하여 업데이트됩니다. -What does this look like in practice? Let's check it out: +실제로는 어떻게 보일까요? 확인해 보겠습니다. ```python cut_mix = keras_cv.layers.CutMix() -# CutMix needs to modify both images and labels +# CutMix는 이미지와 레이블을 모두 수정해야 합니다. inputs = {"images": image_batch, "labels": label_batch} keras_cv.visualization.plot_image_gallery( @@ -485,17 +573,21 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_38_0.png) -Let's hold off from adding it to our augmenter for a minute - more on that soon! +보강기에 추가하는 것을 잠시 미룹시다. 곧 자세히 설명하겠습니다! -Next, let's look into `MixUp()`. Unfortunately, while `MixUp()` has been empirically shown to _substantially_ improve both the robustness and the generalization of the trained model, it is not well-understood why such improvement occurs... but a little alchemy never hurt anyone! +다음으로, `MixUp()`을 살펴보겠습니다. +안타깝게도, `MixUp()`은 경험적으로 트레이닝된 모델의 견고성과 일반화를 _상당히_ 개선하는 것으로 나타났지만, +왜 이런 개선이 일어나는지는 잘 이해되지 않았습니다... +하지만 약간의 연금술은 누구에게도 해가 되지 않았습니다! -`MixUp()` works by sampling two images from a batch, then proceeding to literally blend together their pixel intensities as well as their classification labels. +`MixUp()`은 배치에서 두 개의 이미지를 샘플링한 다음, +문자 그대로 픽셀 강도와 분류 레이블을 함께 혼합하여 작동합니다. -Let's see it in action: +실제로 작동하는 모습을 살펴보겠습니다. ```python mix_up = keras_cv.layers.MixUp() -# MixUp needs to modify both images and labels +# MixUp은 이미지와 레이블을 모두 수정해야 합니다. inputs = {"images": image_batch, "labels": label_batch} keras_cv.visualization.plot_image_gallery( @@ -509,16 +601,18 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_40_0.png) -If you look closely, you'll see that the images have been blended together. +자세히 보면, 이미지가 혼합된 것을 볼 수 있습니다. -Instead of applying `CutMix()` and `MixUp()` to every image, we instead pick one or the other to apply to each batch. This can be expressed using `keras_cv.layers.RandomChoice()` +모든 이미지에 `CutMix()`와 `MixUp()`을 적용하는 대신, +각 배치에 적용할 하나를 선택합니다. +이는 `keras_cv.layers.RandomChoice()`를 사용하여 표현할 수 있습니다. ```python cut_mix_or_mix_up = keras_cv.layers.RandomChoice([cut_mix, mix_up], batchwise=True) augmenters += [cut_mix_or_mix_up] ``` -Now let's apply our final augmenter to the training data: +이제 최종 보강기를 트레이닝 데이터에 적용해 보겠습니다. ```python def create_augmenter_fn(augmenters): @@ -545,7 +639,9 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_44_0.png) -We also need to resize our evaluation set to get dense batches of the image size expected by our model. We use the deterministic [`keras_cv.layers.Resizing`]({{< relref "/docs/api/keras_cv/layers/preprocessing/resizing#resizing-class" >}}) in this case to avoid adding noise to our evaluation metric. +또한 모델에서 기대하는 이미지 크기의 dense 배치를 얻기 위해, 평가 세트의 크기를 조정해야 합니다. +이 경우 결정론적(deterministic) [`keras_cv.layers.Resizing`]({{< relref "/docs/api/keras_cv/layers/preprocessing/resizing#resizing-class" >}})을 사용하여, +평가 메트릭에 노이즈를 추가하는 것을 방지합니다. ```python inference_resizing = keras_cv.layers.Resizing( @@ -565,7 +661,8 @@ keras_cv.visualization.plot_image_gallery( ![png](/images/guides/keras_cv/classification_with_keras_cv/classification_with_keras_cv_46_0.png) -Finally, lets unpackage our datasets and prepare to pass them to `model.fit()`, which accepts a tuple of `(images, labels)`. +마지막으로, 데이터세트를 언팩하고, +이를 `(images, labels)` 튜플을 받는 `model.fit()`에 전달할 준비를 합시다. ```python def unpackage_dict(inputs): @@ -576,11 +673,13 @@ train_ds = train_ds.map(unpackage_dict, num_parallel_calls=tf.data.AUTOTUNE) eval_ds = eval_ds.map(unpackage_dict, num_parallel_calls=tf.data.AUTOTUNE) ``` -Data augmentation is by far the hardest piece of training a modern classifier. Congratulations on making it this far! +데이터 보강은 현대 분류기를 트레이닝하는 데 가장 어려운 부분입니다. 여기까지 온 것을 축하합니다! -### Optimizer Tuning +### 옵티마이저 튜닝 {#optimizer-tuning} -To achieve optimal performance, we need to use a learning rate schedule instead of a single learning rate. While we won't go into detail on the Cosine decay with warmup schedule used here, [you can read more about it here](https://scorrea92.medium.com/cosine-learning-rate-decay-e8b50aa455b). +최적의 성능을 달성하려면, 단일 학습률 대신 학습률 스케쥴을 사용해야 합니다. +여기서 사용된 워밍업 스케쥴을 사용한 코사인 감쇠에 대해서는 자세히 설명하지 않겠지만, +[여기에서 자세히 읽을 수 있습니다](https://scorrea92.medium.com/cosine-learning-rate-decay-e8b50aa455b). ```python def lr_warmup_cosine_decay( @@ -591,7 +690,7 @@ def lr_warmup_cosine_decay( start_lr=0.0, target_lr=1e-2, ): - # Cosine decay + # 코사인 감쇠 learning_rate = ( 0.5 * target_lr @@ -644,9 +743,9 @@ class WarmUpCosineDecay(schedules.LearningRateSchedule): ![WarmUpCosineDecay schedule](/images/guides/keras_cv/classification_with_keras_cv/YCr5pII.png) -The schedule looks a as we expect. +스케쥴은 예상대로 보입니다. -Next let's construct this optimizer: +다음으로 이 옵티마이저를 구성해 보겠습니다. ```python total_images = 9000 @@ -667,7 +766,10 @@ optimizer = optimizers.SGD( ) ``` -At long last, we can now build our model and call `fit()`! `keras_cv.models.EfficientNetV2B0Backbone()` is a convenience alias for `keras_cv.models.EfficientNetV2Backbone.from_preset('efficientnetv2_b0')`. Note that this preset does not come with any pretrained weights. +마침내, 우리는 이제 모델을 빌드하고 `fit()`를 호출할 수 있습니다! +`keras_cv.models.EfficientNetV2B0Backbone()`은 +`keras_cv.models.EfficientNetV2Backbone.from_preset('efficientnetv2_b0')`의 편의 별칭(convenience alias)입니다. +이 사전 설정에는 사전 트레이닝된 가중치가 제공되지 않습니다. ```python backbone = keras_cv.models.EfficientNetV2B0Backbone() @@ -681,13 +783,15 @@ model = keras.Sequential( ) ``` -Since the labels produced by MixUp() and CutMix() are somewhat artificial, we employ label smoothing to prevent the model from overfitting to artifacts of this augmentation process. +MixUp()과 CutMix()로 생성된 레이블은 어느 정도 인위적이기 때문에, +이 보강 과정의 아티팩트로 인해 모델이 과적합되는 것을 방지하기 위해, +레이블 평활화(label smoothing)를 사용합니다. ```python loss = losses.CategoricalCrossentropy(label_smoothing=0.1) ``` -Let's compile our model: +모델을 컴파일해 보겠습니다. ```python model.compile( @@ -700,7 +804,7 @@ model.compile( ) ``` -and finally call fit(). +마지막으로 fit()을 호출합니다. ```python model.fit( @@ -720,14 +824,24 @@ model.fit( {{% /details %}} -Congratulations! You now know how to train a powerful image classifier from scratch in KerasCV. Depending on the availability of labeled data for your application, training from scratch may or may not be more powerful than using transfer learning in addition to the data augmentations discussed above. For smaller datasets, pretrained models generally produce high accuracy and faster convergence. +축하합니다! 이제 KerasCV에서 강력한 이미지 분류기를 처음부터 트레이닝하는 방법을 알게 되었습니다. +애플리케이션에 레이블이 지정된 데이터의 가용성에 따라, +처음부터 트레이닝하는 것이 위에서 설명한 데이터 보강 외에도 전이 학습을 사용하는 것보다 +더 강력할 수도 있고 그렇지 않을 수도 있습니다. +더 작은 데이터 세트의 경우, 사전 트레이닝된 모델은 일반적으로 높은 정확도와 더 빠른 수렴을 생성합니다. -## Conclusions +## 결론 {#conclusions} -While image classification is perhaps the simplest problem in computer vision, the modern landscape has numerous complex components. Luckily, KerasCV offers robust, production-grade APIs to make assembling most of these components possible in one line of code. Through the use of KerasCV's `ImageClassifier` API, pretrained weights, and KerasCV data augmentations you can assemble everything you need to train a powerful classifier in a few hundred lines of code! +이미지 분류는 아마도 컴퓨터 비전에서 가장 간단한 문제일지 몰라도, +현대적 환경에는 복잡한 구성 요소가 많이 있습니다. +다행히도, KerasCV는 이러한 구성 요소의 대부분을, +한 줄의 코드로 조립할 수 있는 강력한 프로덕션 등급 API를 제공합니다. +KerasCV의 `ImageClassifier` API, 사전 트레이닝된 가중치, +KerasCV 데이터 보강을 사용하면, +몇 백 줄의 코드로 강력한 분류기를 트레이닝하는 데 필요한 모든 것을 조립할 수 있습니다! -As a follow up exercise, give the following a try: +후속 연습으로 다음을 시도해 보세요. -- Fine tune a KerasCV classifier on your own dataset -- Learn more about [KerasCV's data augmentations]({{< relref "/docs/guides/keras_cv/cut_mix_mix_up_and_rand_augment" >}}) -- Check out how we train our models on [ImageNet](https://github.com/keras-team/keras-cv/blob/master/examples/training/classification/imagenet/basic_training.py) +- 자신의 데이터 세트에 대해 KerasCV 분류기를 미세 조정합니다. +- [KerasCV의 데이터 보강]({{< relref "/docs/guides/keras_cv/cut_mix_mix_up_and_rand_augment" >}})에 대해 자세히 알아보세요. +- [ImageNet](https://github.com/keras-team/keras-cv/blob/master/examples/training/classification/imagenet/basic_training.py)에서 모델을 트레이닝하는 방법을 확인하세요. diff --git a/content/korean/docs/guides/keras_cv/custom_image_augmentations/_index.md b/content/korean/docs/guides/keras_cv/custom_image_augmentations/_index.md index 277a4015..6427f28f 100644 --- a/content/korean/docs/guides/keras_cv/custom_image_augmentations/_index.md +++ b/content/korean/docs/guides/keras_cv/custom_image_augmentations/_index.md @@ -1,6 +1,6 @@ --- -title: Custom Image Augmentations with BaseImageAugmentationLayer -linkTitle: Custom Image Augmentations with BaseImageAugmentationLayer +title: BaseImageAugmentationLayer를 사용한 커스텀 이미지 보강 +linkTitle: KerasCV로 이미지 보강 toc: true weight: 5 type: docs @@ -11,24 +11,32 @@ type: docs **{{< t f_author >}}** [lukewood](https://twitter.com/luke_wood_ml) **{{< t f_date_created >}}** 2022/04/26 **{{< t f_last_modified >}}** 2023/11/29 -**{{< t f_description >}}** Use BaseImageAugmentationLayer to implement custom data augmentations. +**{{< t f_description >}}** BaseImageAugmentationLayer를 사용하여, 커스텀 데이터 보강을 구현합니다. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_cv/custom_image_augmentations.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_cv/custom_image_augmentations.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Overview +## 개요 {#overview} -Data augmentation is an integral part of training any robust computer vision model. While KerasCV offers a plethora of prebuild high quality data augmentation techniques, you may still want to implement your own custom technique. KerasCV offers a helpful base class for writing data augmentation layers: `BaseImageAugmentationLayer`. Any augmentation layer built with `BaseImageAugmentationLayer` will automatically be compatible with the KerasCV `RandomAugmentationPipeline` class. +데이터 보강은 강력한 컴퓨터 비전 모델을 트레이닝하는 데 필수적인 부분입니다. +KerasCV는 다양한 사전 빌드된 고품질 데이터 보강 기술을 제공하지만, +여전히 커스텀 기술을 구현하고 싶을 수 있습니다. +KerasCV는 데이터 보강 레이어를 작성하는 데 유용한 기본 클래스인, +`BaseImageAugmentationLayer`를 제공합니다. +`BaseImageAugmentationLayer`로 빌드된 모든 보강 레이어는, +자동으로 KerasCV `RandomAugmentationPipeline` 클래스와 호환됩니다. -This guide will show you how to implement your own custom augmentation layers using `BaseImageAugmentationLayer`. As an example, we will implement a layer that tints all images blue. +이 가이드에서는 `BaseImageAugmentationLayer`를 사용하여, +커스텀 보강 레이어를 구현하는 방법을 보여줍니다. +예를 들어 모든 이미지를 파란색으로 칠하는(tints) 레이어를 구현합니다. -Currently, KerasCV's preprocessing layers only support the TensorFlow backend with Keras 3. +현재, KerasCV의 전처리 레이어는 Keras 3이 있는 TensorFlow 백엔드만 지원합니다. ```python !pip install -q --upgrade keras-cv -!pip install -q --upgrade keras # Upgrade to Keras 3 +!pip install -q --upgrade keras # Keras 3로 업그레이드. ``` ```python @@ -43,7 +51,7 @@ import keras_cv import matplotlib.pyplot as plt ``` -First, let's implement some helper functions for visualization and some transformations. +먼저, 시각화와 몇 가지 변환을 위한 몇 가지 도우미 함수를 구현해 보겠습니다. ```python def imshow(img): @@ -79,36 +87,48 @@ def parse_factor(param, min_value=0.0, max_value=1.0, seed=None): return keras_cv.core.UniformFactorSampler(param[0], param[1], seed=seed) ``` -## BaseImageAugmentationLayer Introduction +## BaseImageAugmentationLayer 소개 {#baseimageaugmentationlayer-introduction} -Image augmentation should operate on a sample-wise basis; not batch-wise. This is a common mistake many machine learning practitioners make when implementing custom techniques. `BaseImageAugmentation` offers a set of clean abstractions to make implementing image augmentation techniques on a sample wise basis much easier. This is done by allowing the end user to override an `augment_image()` method and then performing automatic vectorization under the hood. +이미지 보강은 배치 단위가 아닌 샘플 단위로 작동해야 합니다. +이는 많은 머신 러닝 실무자가 커스텀 기술을 구현할 때 저지르는 일반적인 실수입니다. +`BaseImageAugmentation`은 이미지 보강 기술을 샘플 단위로 구현하는 것을 훨씬 더 쉽게 만드는, +일련의 깔끔한 추상화를 제공합니다. +이는 최종 사용자가 `augment_image()` 메서드를 재정의한 다음, +후드 아래에서(under the hood) 자동 벡터화를 수행하여 수행됩니다. -Most augmentation techniques also must sample from one or more random distributions. KerasCV offers an abstraction to make random sampling end user configurable: the `FactorSampler` API. +대부분의 보강 기술은 또한 하나 이상의 랜덤 분포에서 샘플링해야 합니다. +KerasCV는 랜덤 샘플링을 최종 사용자가 구성할 수 있도록 하는 추상화인, +`FactorSampler` API를 제공합니다. -Finally, many augmentation techniques requires some information about the pixel values present in the input images. KerasCV offers the `value_range` API to simplify the handling of this. +마지막으로, 많은 보강 기술에는 입력 이미지에 있는 픽셀 값에 대한 정보가 필요합니다. +KerasCV는 이를 처리하는 것을 단순화하기 위해, `value_range` API를 제공합니다. -In our example, we will use the `FactorSampler` API, the `value_range` API, and `BaseImageAugmentationLayer` to implement a robust, configurable, and correct `RandomBlueTint` layer. +이 예에서는, `FactorSampler` API, +`value_range` API, `BaseImageAugmentationLayer`를 사용하여, +견고하고 구성 가능하며 올바른 `RandomBlueTint` 레이어를 구현합니다. -## Overriding `augment_image()` +## `augment_image()` 오버라이드 {#overriding-augment_image} -Let's start off with the minimum: +최소한의 것부터 시작합시다: ```python class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): def augment_image(self, image, *args, transformation=None, **kwargs): - # image is of shape (height, width, channels) + # 이미지는 (height, width, channels)의 모양을 가지고 있습니다. [*others, blue] = ops.unstack(image, axis=-1) blue = ops.clip(blue + 100, 0.0, 255.0) return ops.stack([*others, blue], axis=-1) ``` -Our layer overrides `BaseImageAugmentationLayer.augment_image()`. This method is used to augment images given to the layer. By default, using `BaseImageAugmentationLayer` gives you a few nice features for free: +레이어는 `BaseImageAugmentationLayer.augment_image()`를 오버라이드합니다. +이 메서드는 레이어에 제공된 이미지를 보강하는데 사용됩니다. +기본적으로, `BaseImageAugmentationLayer`를 사용하면 몇 가지 멋진 기능을 무료로 사용할 수 있습니다. -- support for unbatched inputs (HWC Tensor) -- support for batched inputs (BHWC Tensor) -- automatic vectorization on batched inputs (more information on this in automatic vectorization performance) +- 배치되지 않은(unbatched) 입력 지원(HWC Tensor) +- 배치된(batched) 입력 지원(BHWC Tensor) +- 배치된(batched) 입력에 대한 자동 벡터화(자동 벡터화 성능에서 이에 대한 자세한 정보) -Let's check out the result. First, let's download a sample image: +결과를 확인해 보겠습니다. 먼저 샘플 이미지를 다운로드해 보겠습니다. ```python SIZE = (300, 300) @@ -131,7 +151,7 @@ Downloading data from https://i.imgur.com/Bvro0YD.png ![png](/images/guides/keras_cv/custom_image_augmentations/custom_image_augmentations_9_1.png) -Next, let's augment it and visualize the result: +다음으로, 이를 보강하여 결과를 시각화해 보겠습니다. ```python layer = RandomBlueTint() @@ -141,7 +161,7 @@ imshow(ops.convert_to_numpy(augmented)) ![png](/images/guides/keras_cv/custom_image_augmentations/custom_image_augmentations_11_0.png) -Looks great! We can also call our layer on batched inputs: +멋지네요! 배치된 입력(batched inputs)에 대한 레이어를 호출할 수도 있습니다. ```python layer = RandomBlueTint() @@ -151,26 +171,27 @@ imshow(ops.convert_to_numpy(augmented)[0]) ![png](/images/guides/keras_cv/custom_image_augmentations/custom_image_augmentations_13_0.png) -## Adding Random Behavior with the `FactorSampler` API. +## `FactorSampler` API를 사용하여 랜덤 동작 추가{#adding-random-behavior-with-the-factorsampler-api} -Usually an image augmentation technique should not do the same thing on every invocation of the layer's `__call__` method. KerasCV offers the `FactorSampler` API to allow users to provide configurable random distributions. +일반적으로 이미지 보강 기술은, +레이어의 `__call__` 메서드를 호출할 때마다 동일한 작업을 수행해서는 안됩니다. +KerasCV는 사용자가 구성 가능한 랜덤 분포를 제공할 수 있도록, +`FactorSampler` API를 제공합니다. ```python class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): - """RandomBlueTint randomly applies a blue tint to images. + """RandomBlueTint는 이미지에 랜덤으로 파란색 색조를 적용합니다. Args: - factor: A tuple of two floats, a single float or a - `keras_cv.FactorSampler`. `factor` controls the extent to which the - image is blue shifted. `factor=0.0` makes this layer perform a no-op - operation, while a value of 1.0 uses the degenerated result entirely. - Values between 0 and 1 result in linear interpolation between the original - image and a fully blue image. - Values should be between `0.0` and `1.0`. If a tuple is used, a `factor` is - sampled between the two values for every image augmented. If a single float - is used, a value between `0.0` and the passed float is sampled. In order to - ensure the value is always the same, please pass a tuple with two identical - floats: `(0.5, 0.5)`. + factor: 두 개의 float 튜플, 단일 float 또는 `keras_cv.FactorSampler`. + `factor`는 이미지가 파란색으로 이동하는(blue shifted) 정도를 제어합니다. + `factor=0.0`은 이 레이어가 no-op 연산을 수행하게 하고, + 값 1.0은 퇴화된 결과(degenerated result)를 완전히 사용합니다. + 0과 1 사이의 값은 원본 이미지와 완전히 파란색 이미지 사이에 선형 보간을 수행합니다. + 값은 `0.0`과 `1.0` 사이여야 합니다. + 튜플을 사용하는 경우, `factor`는 보강된 모든 이미지에 대해 두 값 사이에서 샘플링됩니다. + 단일 float를 사용하는 경우, `0.0`과 전달된 float 사이의 값이 샘플링됩니다. + 값이 항상 동일하도록 하려면, 두 개의 동일한 float가 있는 튜플 `(0.5, 0.5)`를 전달하세요. """ def __init__(self, factor, **kwargs): @@ -184,7 +205,8 @@ class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): return ops.stack([*others, blue], axis=-1) ``` -Now, we can configure the random behavior of ou `RandomBlueTint` layer. We can give it a range of values to sample from: +이제, 우리는 RandomBlueTint 레이어의 랜덤 동작을 구성할 수 있습니다. +우리는 샘플링할 값 범위를 제공할 수 있습니다: ```python many_elephants = ops.repeat(ops.expand_dims(elephants, axis=0), 9, axis=0) @@ -195,9 +217,9 @@ gallery_show(ops.convert_to_numpy(augmented)) ![png](/images/guides/keras_cv/custom_image_augmentations/custom_image_augmentations_17_0.png) -Each image is augmented differently with a random factor sampled from the range `(0, 0.5)`. +각 이미지는 `(0, 0.5)` 범위에서, 샘플링된 랜덤 인자로 다르게 보강됩니다. -We can also configure the layer to draw from a normal distribution: +정규 분포에서 그리도록 레이어를 구성할 수도 있습니다. ```python many_elephants = ops.repeat(ops.expand_dims(elephants, axis=0), 9, axis=0) @@ -211,32 +233,39 @@ gallery_show(ops.convert_to_numpy(augmented)) ![png](/images/guides/keras_cv/custom_image_augmentations/custom_image_augmentations_19_0.png) -As you can see, the augmentations now are drawn from a normal distributions. There are various types of `FactorSamplers` including `UniformFactorSampler`, `NormalFactorSampler`, and `ConstantFactorSampler`. You can also implement you own. +보시다시피, 보강은 이제 정규 분포에서 추출되었습니다. +`UniformFactorSampler`, `NormalFactorSampler`, +`ConstantFactorSampler`를 포함한, +다양한 타입의 `FactorSampler`가 있습니다. 직접 구현할 수도 있습니다. -## Overriding `get_random_transformation()` +## `get_random_transformation()` 오버라이드 {#overriding-get_random_transformation} -Now, suppose that your layer impacts the prediction targets: whether they are bounding boxes, classification labels, or regression targets. Your layer will need to have information about what augmentations are taken on the image when augmenting the label. Luckily, `BaseImageAugmentationLayer` was designed with this in mind. +이제, 레이어가 예측 대상에 영향을 미친다고 가정해 보겠습니다. +경계 상자, 분류 레이블 또는 회귀 대상인지 여부입니다. +레이어에는 레이블을 보강할 때, 이미지에서 어떤 보강이 수행되는지에 대한 정보가 있어야 합니다. +다행히도, `BaseImageAugmentationLayer`는 이를 염두에 두고 설계되었습니다. -To handle this issue, `BaseImageAugmentationLayer` has an overridable `get_random_transformation()` method alongside with `augment_label()`, `augment_target()` and `augment_bounding_boxes()`. `augment_segmentation_map()` and others will be added in the future. +이 문제를 처리하기 위해, `BaseImageAugmentationLayer`에는 +`augment_label()`, `augment_target()` 및 `augment_bounding_boxes()`와 함께, +재정의 가능한 `get_random_transformation()` 메서드가 있습니다. +`augment_segmentation_map()` 및 기타 메서드는 나중에 추가됩니다. -Let's add this to our layer. +이것을 레이어에 추가해 보겠습니다. ```python class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): - """RandomBlueTint randomly applies a blue tint to images. + """RandomBlueTint는 이미지에 랜덤으로 파란색 색조를 적용합니다. Args: - factor: A tuple of two floats, a single float or a - `keras_cv.FactorSampler`. `factor` controls the extent to which the - image is blue shifted. `factor=0.0` makes this layer perform a no-op - operation, while a value of 1.0 uses the degenerated result entirely. - Values between 0 and 1 result in linear interpolation between the original - image and a fully blue image. - Values should be between `0.0` and `1.0`. If a tuple is used, a `factor` is - sampled between the two values for every image augmented. If a single float - is used, a value between `0.0` and the passed float is sampled. In order to - ensure the value is always the same, please pass a tuple with two identical - floats: `(0.5, 0.5)`. + factor: 두 개의 float 튜플, 단일 float 또는 `keras_cv.FactorSampler`. + `factor`는 이미지가 파란색으로 이동하는(blue shifted) 정도를 제어합니다. + `factor=0.0`은 이 레이어가 no-op 연산을 수행하게 하고, + 값 1.0은 퇴화된 결과(degenerated result)를 완전히 사용합니다. + 0과 1 사이의 값은 원본 이미지와 완전히 파란색 이미지 사이에 선형 보간을 수행합니다. + 값은 `0.0`과 `1.0` 사이여야 합니다. + 튜플을 사용하는 경우, `factor`는 보강된 모든 이미지에 대해 두 값 사이에서 샘플링됩니다. + 단일 float를 사용하는 경우, `0.0`과 전달된 float 사이의 값이 샘플링됩니다. + 값이 항상 동일하도록 하려면, 두 개의 동일한 float가 있는 튜플 `(0.5, 0.5)`를 전달하세요. """ def __init__(self, factor, **kwargs): @@ -244,7 +273,7 @@ class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): self.factor = parse_factor(factor) def get_random_transformation(self, **kwargs): - # kwargs holds {"images": image, "labels": label, etc...} + # kwargs는 {"images": 이미지, "labels": 라벨 등}을 보유합니다. return self.factor() * 255 def augment_image(self, image, transformation=None, **kwargs): @@ -253,35 +282,35 @@ class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): return ops.stack([*others, blue], axis=-1) def augment_label(self, label, transformation=None, **kwargs): - # you can use transformation somehow if you want + ## 원한다면 어떻게든 변형을 사용할 수 있습니다 if transformation > 100: - # i.e. maybe class 2 corresponds to blue images + # 즉, 클래스 2는 파란색 이미지에 해당할 수 있습니다. return 2.0 return label def augment_bounding_boxes(self, bounding_boxes, transformation=None, **kwargs): - # you can also perform no-op augmentations on label types to support them in - # your pipeline. + # 파이프라인에서 레이블 타입을 지원하기 위해, no-op 보강을 수행할 수도 있습니다. return bounding_boxes ``` -To make use of these new methods, you will need to feed your inputs in with a dictionary maintaining a mapping from images to targets. +이러한 새로운 메서드를 사용하려면, +이미지에서 타겟으로의 매핑을 유지하는 딕셔너리를 사용하여 입력을 공급해야 합니다. -As of now, KerasCV supports the following label types: +현재 KerasCV는 다음 레이블 타입을 지원합니다. -- labels via `augment_label()`. -- bounding_boxes via `augment_bounding_boxes()`. +- `augment_label()`를 통한 labels. +- `augment_bounding_boxes()`를 통한 bounding_boxes. -In order to use augmention layers alongside your prediction targets, you must package your inputs as follows: +예측 타겟과 함께 보강 레이어를 사용하려면, 다음과 같이 입력을 패키징해야 합니다. ```python labels = ops.array([[1, 0]]) inputs = {"images": ops.convert_to_tensor(elephants), "labels": labels} ``` -Now if we call our layer on the inputs: +이제 입력에 대한 레이어를 호출하면 다음과 같습니다. ```python layer = RandomBlueTint(factor=(0.6, 0.6)) @@ -297,13 +326,18 @@ print(augmented["labels"]) {{% /details %}} -Both the inputs and labels are augmented. Note how when `transformation` is > 100 the label is modified to contain 2.0 as specified in the layer above. +입력과 레이블이 모두 보강됩니다. +`transformation`이 > 100일 때, +레이블이 위의 레이어에서 지정된 대로 2.0을 포함하도록 수정되는 방식에 유의하세요. -## `value_range` support +## `value_range` 지원 {#value_range-support} -Imagine you are using your new augmentation layer in many pipelines. Some pipelines have values in the range `[0, 255]`, some pipelines have normalized their images to the range `[-1, 1]`, and some use a value range of `[0, 1]`. +여러 파이프라인에서 새로운 보강 레이어를 사용하고 있다고 상상해 보세요. +일부 파이프라인은 `[0, 255]` 범위의 값을 가지고 있고, +일부 파이프라인은 이미지를 `[-1, 1]` 범위로 정규화했으며, +일부는 `[0, 1]`의 값 범위를 사용합니다. -If a user calls your layer with an image in value range `[0, 1]`, the outputs will be nonsense! +사용자가 값 범위 `[0, 1]`의 이미지로 레이어를 호출하면, 출력이 말도 안 됩니다! ```python layer = RandomBlueTint(factor=(0.1, 0.1)) @@ -331,30 +365,27 @@ min and max after augmentation: 0.0 26.488235 ![png](/images/guides/keras_cv/custom_image_augmentations/custom_image_augmentations_27_2.png) -Note that this is an incredibly weak augmentation! Factor is only set to 0.1. +이것은 매우 약한 보강이라는 점에 유의하세요! Factor는 0.1로만 설정됩니다. -Let's resolve this issue with KerasCV's `value_range` API. +KerasCV의 `value_range` API로 이 문제를 해결해 보겠습니다. ```python class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): - """RandomBlueTint randomly applies a blue tint to images. + """RandomBlueTint는 이미지에 랜덤으로 파란색 색조를 적용합니다. Args: - value_range: value_range: a tuple or a list of two elements. The first value - represents the lower bound for values in passed images, the second represents - the upper bound. Images passed to the layer should have values within - `value_range`. - factor: A tuple of two floats, a single float or a - `keras_cv.FactorSampler`. `factor` controls the extent to which the - image is blue shifted. `factor=0.0` makes this layer perform a no-op - operation, while a value of 1.0 uses the degenerated result entirely. - Values between 0 and 1 result in linear interpolation between the original - image and a fully blue image. - Values should be between `0.0` and `1.0`. If a tuple is used, a `factor` is - sampled between the two values for every image augmented. If a single float - is used, a value between `0.0` and the passed float is sampled. In order to - ensure the value is always the same, please pass a tuple with two identical - floats: `(0.5, 0.5)`. + value_range: 튜플 또는 두 요소의 리스트. + 첫 번째 값은 전달된 이미지의 값에 대한 하한을 나타내고, 두 번째 값은 상한을 나타냅니다. + 레이어에 전달된 이미지는 `value_range` 내의 값을 가져야 합니다. + factor:두 개의 float 튜플, 단일 float 또는 `keras_cv.FactorSampler`. + `factor`는 이미지가 파란색으로 이동하는(blue shifted) 정도를 제어합니다. + `factor=0.0`은 이 레이어가 no-op 연산을 수행하게 하고, + 값 1.0은 퇴화된 결과(degenerated result)를 완전히 사용합니다. + 0과 1 사이의 값은 원본 이미지와 완전히 파란색 이미지 사이에 선형 보간을 수행합니다. + 값은 `0.0`과 `1.0` 사이여야 합니다. + 튜플을 사용하는 경우, `factor`는 보강된 모든 이미지에 대해 두 값 사이에서 샘플링됩니다. + 단일 float를 사용하는 경우, `0.0`과 전달된 float 사이의 값이 샘플링됩니다. + 값이 항상 동일하도록 하려면, 두 개의 동일한 float가 있는 튜플 `(0.5, 0.5)`를 전달하세요. """ def __init__(self, value_range, factor, **kwargs): @@ -363,7 +394,7 @@ class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): self.factor = parse_factor(factor) def get_random_transformation(self, **kwargs): - # kwargs holds {"images": image, "labels": label, etc...} + # kwargs는 {"images": 이미지, "labels": 라벨 등}을 보유합니다. return self.factor() * 255 def augment_image(self, image, transformation=None, **kwargs): @@ -375,17 +406,16 @@ class RandomBlueTint(keras_cv.layers.BaseImageAugmentationLayer): return result def augment_label(self, label, transformation=None, **kwargs): - # you can use transformation somehow if you want + # 원한다면 어떻게든 변형을 사용할 수 있습니다 if transformation > 100: - # i.e. maybe class 2 corresponds to blue images + # 즉, 클래스 2는 파란색 이미지에 해당할 수 있습니다. return 2.0 return label def augment_bounding_boxes(self, bounding_boxes, transformation=None, **kwargs): - # you can also perform no-op augmentations on label types to support them in - # your pipeline. + # 파이프라인에서 레이블 타입을 지원하기 위해, no-op 보강을 수행할 수도 있습니다. return bounding_boxes @@ -412,52 +442,68 @@ min and max after augmentation: 0.0 1.0 ![png](/images/guides/keras_cv/custom_image_augmentations/custom_image_augmentations_29_1.png) -Now our elephants are only slgihtly blue tinted. This is the expected behavior when using a factor of `0.1`. Great! +이제 코끼리는 약간 푸른빛을 띠고 있습니다. +이것은 `0.1`의 인수를 사용할 때 예상되는 동작입니다. 훌륭합니다! -Now users can configure the layer to support any value range they may need. Note that only layers that interact with color information should use the value range API. Many augmentation techniques, such as `RandomRotation` will not need this. +이제 사용자는 필요한 모든 값 범위를 지원하도록 레이어를 구성할 수 있습니다. +색상 정보와 상호 작용하는 레이어만 값 범위 API를 사용해야 합니다. +`RandomRotation`과 같은 많은 보강 기술은 이것이 필요하지 않습니다. -## Auto vectorization performance +## 자동 벡터화 성능 {#auto-vectorization-performance} -If you are wondering: +만약 당신이 다음의 것이 궁금하다면: -> Does implementing my augmentations on an sample-wise basis carry performance implications? +> 샘플 기준으로(sample-wise) 보강을 구현하면 성능에 영향을 미칠까요? -You are not alone! +여러분만 그런 것은 아닙니다! -Luckily, I have performed extensive analysis on the performance of automatic vectorization, manual vectorization, and unvectorized implementations. In this benchmark, I implemented a RandomCutout layer using auto vectorization, no auto vectorization and manual vectorization. All of these were benchmarked inside of an `@tf.function` annotation. They were also each benchmarked with the `jit_compile` argument. +다행히도, 저는 자동 벡터화, 수동 벡터화 및 벡터화되지 않은 구현의 성능에 대한 광범위한 분석을 수행했습니다. +이 벤치마크에서 자동 벡터화, 자동 벡터화 없음 및 수동 벡터화를 사용하여, +RandomCutout 레이어를 구현했습니다. +이 모든 것은 `@tf.function` 주석 내에서 벤치마크되었습니다. +또한 각각 `jit_compile` 인수로 벤치마크되었습니다. -The following chart shows the results of this benchmark: +다음 차트는 이 벤치마크의 결과를 보여줍니다. ![Auto Vectorization Performance Chart](/images/guides/keras_cv/custom_image_augmentations/NeNhDoi.png) -_The primary takeaway should be that the difference between manual vectorization and automatic vectorization is marginal!_ +_가장 중요한 점은 수동 벡터화와 자동 벡터화의 차이가 미미하다는 것입니다!_ -Please note that Eager mode performance will be drastically different. +Eager 모드 성능은 크게 다를 것입니다. -## Common gotchas +## 일반적인 함정 {#common-gotchas} -Some layers are not able to be automatically vectorizated. An example of this is [GridMask](https://tinyurl.com/ffb5zzf7). +일부 레이어는 자동으로 벡터화할 수 없습니다. +이에 대한 예는 [GridMask](https://tinyurl.com/ffb5zzf7)입니다. -If you receive an error when invoking your layer, try adding the following to your constructor: +레이어를 호출할 때 오류가 발생하면, 다음을 생성자에 추가해 보세요. ```python class UnVectorizable(keras_cv.layers.BaseImageAugmentationLayer): def __init__(self, **kwargs): super().__init__(**kwargs) - # this disables BaseImageAugmentationLayer's Auto Vectorization + # 이렇게 하면 BaseImageAugmentationLayer의 자동 벡터화가 비활성화됩니다. self.auto_vectorize = False ``` -Additionally, be sure to accept `**kwargs` to your `augment_*` methods to ensure forwards compatibility. KerasCV will add additional label types in the future, and if you do not include a `**kwargs` argument your augmentation layers will not be forward compatible. +또한, 전방 호환성(forwards compatibility)을 보장하기 위해 +`augment_*` 메서드에 `**kwargs`를 허용해야 합니다. +KerasCV는 향후 추가 레이블 타입을 추가할 예정이며, +`**kwargs` 인수를 포함하지 않으면 보강 레이어가 전방 호환되지 않습니다. -## Conclusion and next steps +## 결론 및 다음 단계 {#conclusion-and-next-steps} -KerasCV offers a standard set of APIs to streamline the process of implementing your own data augmentation techniques. These include `BaseImageAugmentationLayer`, the `FactorSampler` API and the `value_range` API. +KerasCV는 자체 데이터 보강 기술을 구현하는 과정을 간소화하는 표준 API 세트를 제공합니다. +여기에는 `BaseImageAugmentationLayer`, `FactorSampler` API 및 `value_range` API가 포함됩니다. -We used these APIs to implement a highly configurable `RandomBlueTint` layer. This layer can take inputs as standalone images, a dictionary with keys of `"images"` and labels, inputs that are unbatched, or inputs that are batched. Inputs may be in any value range, and the random distribution used to sample the tint values is end user configurable. +이러한 API를 사용하여 구성 가능성이 높은 `RandomBlueTint` 레이어를 구현했습니다. +이 레이어는 독립 실행형 이미지, `"images"` 키와 레이블이 있는 딕셔너리, +배치화되지(unbatched) 않은 입력 또는 배치된(batched) 입력으로 입력을 받을 수 있습니다. +입력은 모든 값 범위에 있을 수 있으며, +색조(tint) 값을 샘플링하는 데 사용되는 랜덤 분포는 최종 사용자가 구성할 수 있습니다. -As a follow up exercises you can: +후속 연습으로 다음을 수행할 수 있습니다. -- implement your own data augmentation technique using `BaseImageAugmentationLayer` -- [contribute an augmentation layer to KerasCV](https://github.com/keras-team/keras-cv) -- [read through the existing KerasCV augmentation layers](https://tinyurl.com/4txy4m3t) +- `BaseImageAugmentationLayer`를 사용하여, 자체 데이터 보강 기법 구현 +- [KerasCV에 보강 레이어 기여](https://github.com/keras-team/keras-cv) +- [기존 KerasCV 보강 레이어 읽기](https://tinyurl.com/4txy4m3t) diff --git a/content/korean/docs/guides/keras_cv/cut_mix_mix_up_and_rand_augment/_index.md b/content/korean/docs/guides/keras_cv/cut_mix_mix_up_and_rand_augment/_index.md index 928b8710..04462fca 100644 --- a/content/korean/docs/guides/keras_cv/cut_mix_mix_up_and_rand_augment/_index.md +++ b/content/korean/docs/guides/keras_cv/cut_mix_mix_up_and_rand_augment/_index.md @@ -1,6 +1,6 @@ --- -title: CutMix, MixUp, and RandAugment image augmentation with KerasCV -linkTitle: CutMix, MixUp, and RandAugment image augmentation with KerasCV +title: KerasCV로 CutMix, MixUp 및 RandAugment 이미지 보강 +linkTitle: KerasCV로 이미지 보강 toc: true weight: 3 type: docs @@ -11,31 +11,42 @@ type: docs **{{< t f_author >}}** [lukewood](https://twitter.com/luke_wood_ml) **{{< t f_date_created >}}** 2022/04/08 **{{< t f_last_modified >}}** 2022/04/08 -**{{< t f_description >}}** Use KerasCV to augment images with CutMix, MixUp, RandAugment, and more. +**{{< t f_description >}}** KerasCV를 사용하여 CutMix, MixUp, RandAugment 등을 통해 이미지를 보강합니다. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_cv/cut_mix_mix_up_and_rand_augment.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_cv/cut_mix_mix_up_and_rand_augment.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Overview +## 개요 {#overview} -KerasCV makes it easy to assemble state-of-the-art, industry-grade data augmentation pipelines for image classification and object detection tasks. KerasCV offers a wide suite of preprocessing layers implementing common data augmentation techniques. +KerasCV를 사용하면, 이미지 분류 및 객체 감지 작업을 위한, +최첨단 산업 등급 데이터 보강 파이프라인을 쉽게 조립할 수 있습니다. +KerasCV는 일반적인 데이터 보강 기술을 구현하는 광범위한 전처리 레이어를 제공합니다. -Perhaps three of the most useful layers are [`keras_cv.layers.CutMix`]({{< relref "/docs/api/keras_cv/layers/augmentation/cut_mix#cutmix-class" >}}), [`keras_cv.layers.MixUp`]({{< relref "/docs/api/keras_cv/layers/augmentation/mix_up#mixup-class" >}}), and [`keras_cv.layers.RandAugment`]({{< relref "/docs/api/keras_cv/layers/augmentation/rand_augment#randaugment-class" >}}). These layers are used in nearly all state-of-the-art image classification pipelines. +아마도 가장 유용한 레이어 중 세 가지는 +[`keras_cv.layers.CutMix`]({{< relref "/docs/api/keras_cv/layers/augmentation/cut_mix#cutmix-class" >}}), +[`keras_cv.layers.MixUp`]({{< relref "/docs/api/keras_cv/layers/augmentation/mix_up#mixup-class" >}}), +[`keras_cv.layers.RandAugment`]({{< relref "/docs/api/keras_cv/layers/augmentation/rand_augment#randaugment-class" >}})일 것입니다. +이러한 레이어는 거의 모든 최첨단 이미지 분류 파이프라인에서 사용됩니다. -This guide will show you how to compose these layers into your own data augmentation pipeline for image classification tasks. This guide will also walk you through the process of customizing a KerasCV data augmentation pipeline. +이 가이드에서는 이미지 분류 작업을 위한, +자체 데이터 보강 파이프라인으로 이러한 레이어를 구성하는 방법을 보여줍니다. +이 가이드에서는 KerasCV 데이터 보강 파이프라인을 커스터마이즈하는 프로세스도 안내합니다. -## Imports & setup +## Imports & 셋업 {#imports-setup} -KerasCV uses Keras 3 to work with any of TensorFlow, PyTorch or Jax. In the guide below, we will use the `jax` backend. This guide runs in TensorFlow or PyTorch backends with zero changes, simply update the `KERAS_BACKEND` below. +KerasCV는 Keras 3을 사용하여 TensorFlow, PyTorch 또는 Jax 중 하나와 함께 작업합니다. +아래 가이드에서는 `jax` 백엔드를 사용합니다. +이 가이드는 변경 사항 없이 TensorFlow 또는 PyTorch 백엔드에서 실행되므로, +아래의 `KERAS_BACKEND`를 업데이트하기만 하면 됩니다. ```python !pip install -q --upgrade keras-cv -!pip install -q --upgrade keras # Upgrade to Keras 3. +!pip install -q --upgrade keras # Keras 3으로 업그레이드하세요. ``` -We begin by importing all required packages: +먼저 필요한 모든 패키지를 import 합니다. ```python import os @@ -44,18 +55,20 @@ os.environ["KERAS_BACKEND"] = "jax" # @param ["tensorflow", "jax", "torch"] import matplotlib.pyplot as plt -# Import tensorflow for [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) and its preprocessing map functions +# [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) 및 +# 해당 전처리 맵 함수에 대한 tensorflow import import tensorflow as tf import tensorflow_datasets as tfds import keras import keras_cv ``` -## Data loading +## 데이터 로딩 {#data-loading} -This guide uses the [102 Category Flower Dataset](https://www.robots.ox.ac.uk/~vgg/data/flowers/102/) for demonstration purposes. +이 가이드에서는 데모 목적으로, +[102 Category Flower Dataset](https://www.robots.ox.ac.uk/~vgg/data/flowers/102/)을 사용합니다. -To get started, we first load the dataset: +시작하려면, 먼저 데이터 세트를 로드합니다. ```python BATCH_SIZE = 32 @@ -75,7 +88,9 @@ val_steps_per_epoch = dataset_info.splits["test"].num_examples // BATCH_SIZE {{% /details %}} -Next, we resize the images to a constant size, `(224, 224)`, and one-hot encode the labels. Please note that [`keras_cv.layers.CutMix`]({{< relref "/docs/api/keras_cv/layers/augmentation/cut_mix#cutmix-class" >}}) and [`keras_cv.layers.MixUp`]({{< relref "/docs/api/keras_cv/layers/augmentation/mix_up#mixup-class" >}}) expect targets to be one-hot encoded. This is because they modify the values of the targets in a way that is not possible with a sparse label representation. +다음으로, 이미지를 constant 크기인 `(224, 224)`로 조정하고, 레이블을 원핫 인코딩합니다. +[`keras_cv.layers.CutMix`]({{< relref "/docs/api/keras_cv/layers/augmentation/cut_mix#cutmix-class" >}})와 [`keras_cv.layers.MixUp`]({{< relref "/docs/api/keras_cv/layers/augmentation/mix_up#mixup-class" >}})은 대상이 원핫 인코딩되기를 기대합니다. +이는 희소(sparse) 레이블 표현으로는 불가능한 방식으로, 대상의 값을 수정하기 때문입니다. ```python IMAGE_SIZE = (224, 224) @@ -108,7 +123,7 @@ def load_dataset(split="train"): train_dataset = load_dataset() ``` -Let's inspect some samples from our dataset: +데이터 세트에서 몇 가지 샘플을 살펴보겠습니다. ```python def visualize_dataset(dataset, title): @@ -126,23 +141,27 @@ visualize_dataset(train_dataset, title="Before Augmentation") ![png](/images/guides/keras_cv/cut_mix_mix_up_and_rand_augment/cut_mix_mix_up_and_rand_augment_11_0.png) -Great! Now we can move onto the augmentation step. +좋아요! 이제 보강 단계로 넘어갈 수 있습니다. -## RandAugment +## RandAugment {#randaugment} -[RandAugment](https://arxiv.org/abs/1909.13719) has been shown to provide improved image classification results across numerous datasets. It performs a standard set of augmentations on an image. +[RandAugment](https://arxiv.org/abs/1909.13719)는 수많은 데이터 세트에서, +향상된 이미지 분류 결과를 제공하는 것으로 나타났습니다. +이미지에 표준 보강 세트를 수행합니다. -To use RandAugment in KerasCV, you need to provide a few values: +KerasCV에서 RandAugment를 사용하려면, 몇 가지 값을 제공해야 합니다. -- `value_range` describes the range of values covered in your images -- `magnitude` is a value between 0 and 1, describing the strength of the perturbations applied -- `augmentations_per_image` is an integer telling the layer how many augmentations to apply to each individual image -- (Optional) `magnitude_stddev` allows `magnitude` to be randomly sampled from a distribution with a standard deviation of `magnitude_stddev` -- (Optional) `rate` indicates the probability to apply the augmentation applied at each layer. +- `value_range`는 이미지에서 다루는 값의 범위를 설명합니다. +- `magnitude`는 0과 1 사이의 값으로, 적용되는 섭동(perturbations)의 강도를 설명합니다. +- `augmentations_per_image`는 각 개별 이미지에 적용할 보강 수를 레이어에 알려주는 정수입니다. +- (선택 사항) `magnitude_stddev`는 표준 편차가 `magnitude_stddev`인 분포에서, + `magnitude`를 무작위로 샘플링할 수 있도록 합니다. +- (선택 사항) `rate`는 각 레이어에, 적용된 보강을 적용할 확률을 나타냅니다. -You can read more about these parameters in the [`RandAugment` API documentation]({{< relref "/docs/api/keras_cv/layers/augmentation/rand_augment" >}}). +이러한 매개변수에 대한 자세한 내용은, +[`RandAugment` API 문서]({{< relref "/docs/api/keras_cv/layers/augmentation/rand_augment" >}})에서 확인할 수 있습니다. -Let's use KerasCV's RandAugment implementation. +KerasCV의 RandAugment 구현을 사용해 보겠습니다. ```python rand_augment = keras_cv.layers.RandAugment( @@ -162,7 +181,7 @@ def apply_rand_augment(inputs): train_dataset = load_dataset().map(apply_rand_augment, num_parallel_calls=AUTOTUNE) ``` -Finally, let's inspect some of the results: +마지막으로, 몇 가지 결과를 살펴보겠습니다. ```python visualize_dataset(train_dataset, title="After RandAugment") @@ -170,16 +189,25 @@ visualize_dataset(train_dataset, title="After RandAugment") ![png](/images/guides/keras_cv/cut_mix_mix_up_and_rand_augment/cut_mix_mix_up_and_rand_augment_17_0.png) -Try tweaking the magnitude settings to see a wider variety of results. +더 다양한 결과를 보려면, `magnitude` 설정을 조정해 보세요. -## CutMix and MixUp: generate high-quality inter-class examples +## CutMix 및 MixUp: 고품질 클래스(inter-class) 간 예제 생성 {#cutmix-and-mixup-generate-high-quality-inter-class-examples} -`CutMix` and `MixUp` allow us to produce inter-class examples. `CutMix` randomly cuts out portions of one image and places them over another, and `MixUp` interpolates the pixel values between two images. Both of these prevent the model from overfitting the training distribution and improve the likelihood that the model can generalize to out of distribution examples. Additionally, `CutMix` prevents your model from over-relying on any particular feature to perform its classifications. You can read more about these techniques in their respective papers: +`CutMix`와 `MixUp`을 사용하면 클래스 간(inter-class) 예제를 생성할 수 있습니다. +`CutMix`는 한 이미지의 일부를 무작위로 잘라내어 다른 이미지 위에 놓고, +`MixUp`은 두 이미지 사이의 픽셀 값을 보간합니다. +이 두 가지 모두 모델이 트레이닝 분포에 과적합되는 것을 방지하고, +모델이 분포 밖 예제로 일반화할 가능성을 높입니다. +또한 `CutMix`는 모델이 분류를 수행하기 위해, +특정 기능에 지나치게 의존하는 것을 방지합니다. +이러한 기술에 대한 자세한 내용은 해당 논문에서 확인할 수 있습니다. -- [CutMix: Train Strong Classifiers](https://arxiv.org/abs/1905.04899) -- [MixUp: Beyond Empirical Risk Minimization](https://arxiv.org/abs/1710.09412) +- [CutMix: 강력한 분류기 트레이닝](https://arxiv.org/abs/1905.04899) +- [MixUp: 경험적 위험 최소화를 넘어](https://arxiv.org/abs/1710.09412) -In this example, we will use `CutMix` and `MixUp` independently in a manually created preprocessing pipeline. In most state of the art pipelines images are randomly augmented by either `CutMix`, `MixUp`, or neither. The function below implements both. +이 예에서는, 수동으로 만든 전처리 파이프라인에서, `CutMix`와 `MixUp`을 독립적으로 사용합니다. +대부분 최신 파이프라인에서 이미지는 `CutMix`, `MixUp` 또는 둘 다 아닌 것으로 무작위로 보강됩니다. +아래 함수는 둘 다 구현합니다. ```python cut_mix = keras_cv.layers.CutMix() @@ -199,17 +227,26 @@ visualize_dataset(train_dataset, title="After CutMix and MixUp") ![png](/images/guides/keras_cv/cut_mix_mix_up_and_rand_augment/cut_mix_mix_up_and_rand_augment_20_0.png) -Great! Looks like we have successfully added `CutMix` and `MixUp` to our preprocessing pipeline. +좋습니다! `CutMix`와 `MixUp`을 전처리 파이프라인에 성공적으로 추가한 것 같습니다. -## Customizing your augmentation pipeline +## 보강 파이프라인 커스터마이즈 {#customizing-your-augmentation-pipeline} -Perhaps you want to exclude an augmentation from `RandAugment`, or perhaps you want to include the [`keras_cv.layers.GridMask`]({{< relref "/docs/api/keras_cv/layers/augmentation/grid_mask#gridmask-class" >}}) as an option alongside the default `RandAugment` augmentations. +아마도 `RandAugment`에서 보강을 제외하거나, +기본 `RandAugment` 보강과 함께 옵션으로 +[`keras_cv.layers.GridMask`]({{< relref "/docs/api/keras_cv/layers/augmentation/grid_mask#gridmask-class" >}})를 포함하고 싶을 것입니다. -KerasCV allows you to construct production grade custom data augmentation pipelines using the [`keras_cv.layers.RandomAugmentationPipeline`]({{< relref "/docs/api/keras_cv/layers/augmentation/random_augmentation_pipeline#randomaugmentationpipeline-class" >}}) layer. This class operates similarly to `RandAugment`; selecting a random layer to apply to each image `augmentations_per_image` times. `RandAugment` can be thought of as a specific case of `RandomAugmentationPipeline`. In fact, our `RandAugment` implementation inherits from `RandomAugmentationPipeline` internally. +KerasCV를 사용하면, [`keras_cv.layers.RandomAugmentationPipeline`]({{< relref "/docs/api/keras_cv/layers/augmentation/random_augmentation_pipeline#randomaugmentationpipeline-class" >}}) 레이어를 사용하여, 프로덕션 등급의 커스텀 데이터 보강 파이프라인을 구성할 수 있습니다. +이 클래스는 `RandAugment`와 유사하게 작동합니다. +각 이미지에 적용할 임의의 레이어를 `augmentations_per_image` 번 선택합니다. +`RandAugment`는 `RandomAugmentationPipeline`의 특수 케이스로 생각할 수 있습니다. +사실, 우리의 `RandAugment` 구현은 내부적으로 `RandomAugmentationPipeline`을 상속합니다. -In this example, we will create a custom `RandomAugmentationPipeline` by removing `RandomRotation` layers from the standard `RandAugment` policy, and substitute a `GridMask` layer in its place. +이 예에서, 우리는 표준 `RandAugment` 정책에서 `RandomRotation` 레이어를 제거하고, +그 자리에 `GridMask` 레이어를 대체하여, +커스텀 `RandomAugmentationPipeline`을 만들 것입니다. -As a first step, let's use the helper method `RandAugment.get_standard_policy()` to create a base pipeline. +첫 번째 단계로, 헬퍼 메서드 `RandAugment.get_standard_policy()`를 사용하여, +베이스 파이프라인을 만들어 보겠습니다. ```python layers = keras_cv.layers.RandAugment.get_standard_policy( @@ -217,7 +254,7 @@ layers = keras_cv.layers.RandAugment.get_standard_policy( ) ``` -First, let's filter out `RandomRotation` layers +먼저 `RandomRotation` 레이어를 필터링해 보겠습니다. ```python layers = [ @@ -225,13 +262,13 @@ layers = [ ] ``` -Next, let's add [`keras_cv.layers.GridMask`]({{< relref "/docs/api/keras_cv/layers/augmentation/grid_mask#gridmask-class" >}}) to our layers: +다음으로, 레이어에 [`keras_cv.layers.GridMask`]({{< relref "/docs/api/keras_cv/layers/augmentation/grid_mask#gridmask-class" >}})를 추가해 보겠습니다. ```python layers = layers + [keras_cv.layers.GridMask()] ``` -Finally, we can put together our pipeline +마지막으로, 우리는 파이프라인을 구성할 수 있습니다. ```python pipeline = keras_cv.layers.RandomAugmentationPipeline( @@ -244,7 +281,7 @@ def apply_pipeline(inputs): return inputs ``` -Let's check out the results! +결과를 확인해보죠! ```python train_dataset = load_dataset().map(apply_pipeline, num_parallel_calls=AUTOTUNE) @@ -253,7 +290,8 @@ visualize_dataset(train_dataset, title="After custom pipeline") ![png](/images/guides/keras_cv/cut_mix_mix_up_and_rand_augment/cut_mix_mix_up_and_rand_augment_32_0.png) -Awesome! As you can see, no images were randomly rotated. You can customize the pipeline however you like: +굉장하네요! 보시다시피, 이미지는 무작위로 회전되지 않았습니다. +파이프라인을 원하는 대로 커스터마이즈할 수 있습니다. ```python pipeline = keras_cv.layers.RandomAugmentationPipeline( @@ -262,7 +300,7 @@ pipeline = keras_cv.layers.RandomAugmentationPipeline( ) ``` -This pipeline will either apply `GrayScale` or GridMask: +이 파이프라인은 `GrayScale` 또는 GridMask를 적용합니다. ```python train_dataset = load_dataset().map(apply_pipeline, num_parallel_calls=AUTOTUNE) @@ -271,11 +309,13 @@ visualize_dataset(train_dataset, title="After custom pipeline") ![png](/images/guides/keras_cv/cut_mix_mix_up_and_rand_augment/cut_mix_mix_up_and_rand_augment_36_0.png) -Looks great! You can use `RandomAugmentationPipeline` however you want. +멋지네요! `RandomAugmentationPipeline`을 원하는 대로 사용할 수 있습니다. -## Training a CNN +## CNN 트레이닝 {#training-a-cnn} -As a final exercise, let's take some of these layers for a spin. In this section, we will use `CutMix`, `MixUp`, and `RandAugment` to train a state of the art `ResNet50` image classifier on the Oxford flowers dataset. +마지막 연습으로, 이러한 레이어 중 일부를 돌려보겠습니다. +이 섹션에서는 `CutMix`, `MixUp`, `RandAugment`를 사용하여, +Oxford flowers 데이터세트에 대해 최첨단 `ResNet50` 이미지 분류기를 학습합니다. ```python def preprocess_for_model(inputs): @@ -303,7 +343,9 @@ test_dataset = test_dataset.prefetch(AUTOTUNE) ![png](/images/guides/keras_cv/cut_mix_mix_up_and_rand_augment/cut_mix_mix_up_and_rand_augment_39_0.png) -Next we should create a the model itself. Notice that we use `label_smoothing=0.1` in the loss function. When using `MixUp`, label smoothing is _highly_ recommended. +다음으로 모델 자체를 만들어야 합니다. +손실 함수에서 `label_smoothing=0.1`을 사용한다는 점에 유의하세요. +`MixUp`을 사용할 때는 레이블 스무딩(label smoothing)을 _강력히_ 권장합니다. ```python input_shape = IMAGE_SIZE + (3,) @@ -321,7 +363,7 @@ def get_model(): return model ``` -Finally we train the model: +마지막으로 모델을 트레이닝합니다. ```python model = get_model() @@ -342,14 +384,18 @@ model.fit( {{% /details %}} -## Conclusion & next steps +## 결론 및 다음 단계 {#conclusion-next-steps} -That's all it takes to assemble state of the art image augmentation pipeliens with KerasCV! +이것이 KerasCV로 최첨단 이미지 보강 파이프라인을 조립하는 데 필요한 모든 것입니다! -As an additional exercise for readers, you can: +독자를 위한 추가 연습으로 다음을 수행할 수 있습니다. -- Perform a hyper parameter search over the RandAugment parameters to improve the classifier accuracy -- Substitute the Oxford Flowers dataset with your own dataset -- Experiment with custom `RandomAugmentationPipeline` objects. +- RandAugment 매개변수에 대한 하이퍼파라미터 검색을 수행하여, 분류기 정확도를 개선합니다. +- Oxford Flowers 데이터 세트를 당신의 고유 데이터 세트로 대체합니다. +- 커스텀 `RandomAugmentationPipeline` 객체로 실험합니다. -Currently, between Keras core and KerasCV there are [_28 image augmentation layers_]({{< relref "/docs/api/keras_cv/layers/preprocessing" >}})! Each of these can be used independently, or in a pipeline. Check them out, and if you find an augmentation techniques you need is missing please file a [GitHub issue on KerasCV](https://github.com/keras-team/keras-cv/issues). +현재, Keras 코어와 KerasCV 사이에는 +[_28개의 이미지 보강 레이어_]({{< relref "/docs/api/keras_cv/layers/preprocessing" >}})가 있습니다! +각각은 독립적으로 또는 파이프라인에서 사용할 수 있습니다. +확인하고 필요한 보강 기술이 누락된 경우, +[KerasCV의 GitHub 이슈](https://github.com/keras-team/keras-cv/issues)를 제출하세요. diff --git a/content/korean/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md b/content/korean/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md index e60eae6a..704021e2 100644 --- a/content/korean/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md +++ b/content/korean/docs/guides/keras_cv/generate_images_with_stable_diffusion/_index.md @@ -1,6 +1,6 @@ --- -title: High-performance image generation using Stable Diffusion in KerasCV -linkTitle: High-performance image generation using Stable Diffusion in KerasCV +title: KerasCV에서 Stable Diffusion을 사용한 고성능 이미지 생성 +linkTitle: KerasCV로 이미지 생성 toc: true weight: 4 type: docs @@ -8,31 +8,42 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -**Authors:** [fchollet](https://twitter.com/fchollet), [lukewood](https://twitter.com/luke_wood_ml), [divamgupta](https://github.com/divamgupta) +**{{< t f_author >}}** [fchollet](https://twitter.com/fchollet), [lukewood](https://twitter.com/luke_wood_ml), [divamgupta](https://github.com/divamgupta) **{{< t f_date_created >}}** 2022/09/25 **{{< t f_last_modified >}}** 2022/09/25 -**{{< t f_description >}}** Generate new images using KerasCV's Stable Diffusion model. +**{{< t f_description >}}** KerasCV의 Stable Diffusion 모델을 사용하여 새로운 이미지를 생성합니다. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_cv/generate_images_with_stable_diffusion.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_cv/generate_images_with_stable_diffusion.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Overview +## 개요 {#overview} -In this guide, we will show how to generate novel images based on a text prompt using the KerasCV implementation of [stability.ai](https://stability.ai/)'s text-to-image model, [Stable Diffusion](https://github.com/CompVis/stable-diffusion). +이 가이드에서는, [stability.ai](https://stability.ai/)의 텍스트-이미지 모델인 +[Stable Diffusion](https://github.com/CompVis/stable-diffusion)의 KerasCV 구현을 사용하여, +텍스트 프롬프트를 기반으로 새로운 이미지를 생성하는 방법을 보여줍니다. -Stable Diffusion is a powerful, open-source text-to-image generation model. While there exist multiple open-source implementations that allow you to easily create images from textual prompts, KerasCV's offers a few distinct advantages. These include [XLA compilation](https://www.tensorflow.org/xla) and [mixed precision](https://www.tensorflow.org/guide/mixed_precision) support, which together achieve state-of-the-art generation speed. +Stable Diffusion은 강력한 오픈소스 텍스트-이미지 생성 모델입니다. +텍스트 프롬프트에서 이미지를 쉽게 생성할 수 있는 오픈소스 구현이 여러 개 있지만, +KerasCV는 몇 가지 뚜렷한 이점을 제공합니다. +여기에는 [XLA 컴파일](https://www.tensorflow.org/xla)과 +[혼합 정밀도](https://www.tensorflow.org/guide/mixed_precision) 지원이 포함되며, +이를 통해 최첨단 생성 속도를 달성합니다. -In this guide, we will explore KerasCV's Stable Diffusion implementation, show how to use these powerful performance boosts, and explore the performance benefits that they offer. +이 가이드에서는, KerasCV의 Stable Diffusion 구현을 살펴보고, +이러한 강력한 성능 향상을 사용하는 방법을 보여주고, +이러한 향상이 제공하는 성능 이점을 살펴보겠습니다. -**Note:** To run this guide on the `torch` backend, please set `jit_compile=False` everywhere. XLA compilation for Stable Diffusion does not currently work with torch. +**참고:** `torch` 백엔드에서 이 가이드를 실행하려면, +모든 곳에서 `jit_compile=False`를 설정하세요. +Stable Diffusion을 위한 XLA 컴파일은 현재 torch에서 작동하지 않습니다. -To get started, let's install a few dependencies and sort out some imports: +시작하려면, 몇 가지 종속성을 설치하고 몇 가지 import를 정리하겠습니다. ```python !pip install -q --upgrade keras-cv -!pip install -q --upgrade keras # Upgrade to Keras 3. +!pip install -q --upgrade keras # Keras 3으로 업그레이드. ``` ```python @@ -42,13 +53,14 @@ import keras import matplotlib.pyplot as plt ``` -## Introduction +## 소개 {#introduction} -Unlike most tutorials, where we first explain a topic then show how to implement it, with text-to-image generation it is easier to show instead of tell. +(먼저 주제를 설명한 다음 구현 방법을 보여주는) 대부분 튜토리얼과 달리, +텍스트-이미지 생성은 말하기보다는 보여주기가 더 쉽습니다. -Check out the power of `keras_cv.models.StableDiffusion()`. +`keras_cv.models.StableDiffusion()`의 힘을 확인해 보세요. -First, we construct a model: +먼저 모델을 구성합니다. ```python model = keras_cv.models.StableDiffusion( @@ -64,7 +76,7 @@ By using this model checkpoint, you acknowledge that its usage is subject to the {{% /details %}} -Next, we give it a prompt: +다음으로, 프롬프트를 제공합니다. ```python images = model.text_to_image("photograph of an astronaut riding a horse", batch_size=3) @@ -91,9 +103,9 @@ plot_images(images) ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_7_1.png) -Pretty incredible! +꽤 놀랍네요! -But that's not all this model can do. Let's try a more complex prompt: +하지만 이 모델이 할 수 있는 일은 그게 전부가 아닙니다. 좀 더 복잡한 프롬프트를 시도해 보겠습니다. ```python images = model.text_to_image( @@ -115,87 +127,128 @@ plot_images(images) ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_9_1.png) -The possibilities are literally endless (or at least extend to the boundaries of Stable Diffusion's latent manifold). +가능성은 문자 그대로 무한(또는 적어도 Stable Diffusion의 잠재 매니폴드의 경계까지 확장됩니다)합니다. -## Wait, how does this even work? +## 잠깐, 이게 어떻게 작동하는 걸까요? {#wait-how-does-this-even-work} -Unlike what you might expect at this point, Stable Diffusion doesn't actually run on magic. It's a kind of "latent diffusion model". Let's dig into what that means. +이 시점에서 예상할 수 있는 것과 달리, +Stable Diffusion은 실제로 마법으로 실행되지 않습니다. +일종의 "잠재적 확산 모델"입니다. +그것이 무슨 뜻인지 살펴보겠습니다. -You may be familiar with the idea of _super-resolution_: it's possible to train a deep learning model to _denoise_ an input image – and thereby turn it into a higher-resolution version. The deep learning model doesn't do this by magically recovering the information that's missing from the noisy, low-resolution input – rather, the model uses its training data distribution to hallucinate the visual details that would be most likely given the input. To learn more about super-resolution, you can check out the following Keras.io tutorials: +_super-resolution_ 이라는 개념에 익숙할 수 있습니다. +딥러닝 모델을 트레이닝하여, 입력 이미지의 _노이즈 제거(denoise)_ 를 수행하고, +이를 통해 고해상도 버전으로 변환할 수 있습니다. +딥러닝 모델은 노이즈가 많고 해상도가 낮은 입력에서, 누락된 정보를 마법처럼 복구하여 이를 수행하지 않습니다. +대신 모델은 트레이닝 데이터 분포를 사용하여 입력이 주어졌을 때, 가장 가능성이 높은 시각적 세부 사항을 환각합니다. +super-resolution에 대해 자세히 알아보려면, 다음 Keras.io 튜토리얼을 확인하세요. -- [Image Super-Resolution using an Efficient Sub-Pixel CNN]({{< relref "/docs/examples/vision/super_resolution_sub_pixel" >}}) -- [Enhanced Deep Residual Networks for single-image super-resolution]({{< relref "/docs/examples/vision/edsr" >}}) +- [효율적인 서브픽셀 CNN을 사용한 이미지 super-resolution]({{< relref "/docs/examples/vision/super_resolution_sub_pixel" >}}) +- [단일 이미지 super-resolution를 위한 향상된 딥 Residual 네트워크]({{< relref "/docs/examples/vision/edsr" >}}) ![Super-resolution](/images/guides/keras_cv/generate_images_with_stable_diffusion/M0XdqOo.png) -When you push this idea to the limit, you may start asking – what if we just run such a model on pure noise? The model would then "denoise the noise" and start hallucinating a brand new image. By repeating the process multiple times, you can get turn a small patch of noise into an increasingly clear and high-resolution artificial picture. +이 아이디어를 한계까지 밀고 나가면, +그냥 순수한 노이즈에 그런 모델을 실행하면 어떨까 하고 생각하게 될 수 있습니다. +그러면, 모델은 "노이즈를 제거하고" 완전히 새로운 이미지를 환각하기 시작할 것입니다. +이 과정을 여러 번 반복하면, 작은 노이즈 패치를 점점 더 선명하고 고해상도의 인공적인 그림으로 바꿀 수 있습니다. -This is the key idea of latent diffusion, proposed in [High-Resolution Image Synthesis with Latent Diffusion Models](https://arxiv.org/abs/2112.10752) in 2020. To understand diffusion in depth, you can check the Keras.io tutorial [Denoising Diffusion Implicit Models]({{< relref "/docs/examples/generative/ddim" >}}). +이것은 2020년 [잠재 확산(Latent Diffusion) 모델을 사용한 고해상도 이미지 합성](https://arxiv.org/abs/2112.10752)에서 제안된, 잠재 확산의 핵심 아이디어입니다. +확산을 심층적으로 이해하려면, +Keras.io 튜토리얼 [Diffusion 암묵적 모델 노이즈 제거]({{< relref "/docs/examples/generative/ddim" >}})를 확인할 수 있습니다. ![Denoising diffusion](/images/guides/keras_cv/generate_images_with_stable_diffusion/FSCKtZq.gif) -Now, to go from latent diffusion to a text-to-image system, you still need to add one key feature: the ability to control the generated visual contents via prompt keywords. This is done via "conditioning", a classic deep learning technique which consists of concatenating to the noise patch a vector that represents a bit of text, then training the model on a dataset of {image: caption} pairs. +이제, 잠재 확산에서 텍스트-이미지 시스템으로 전환하려면, 여전히 하나의 핵심 기능을 추가해야 합니다. +프롬프트 키워드를 통해 생성된 시각적 콘텐츠를 제어하는 ​​기능입니다. +이는 "컨디셔닝(conditioning)"을 통해 수행됩니다. +이는 노이즈 패치에 텍스트 조각을 나타내는 벡터를 연결(concatenating)한 다음, +{image: caption} 쌍의 데이터 세트에 대해 모델을 트레이닝하는, 고전적인 딥러닝 기술입니다. -This gives rise to the Stable Diffusion architecture. Stable Diffusion consists of three parts: +이를 통해, Stable Diffusion 아키텍처가 탄생했습니다. Stable Diffusion은 세 부분으로 구성됩니다. -- A text encoder, which turns your prompt into a latent vector. -- A diffusion model, which repeatedly "denoises" a 64x64 latent image patch. -- A decoder, which turns the final 64x64 latent patch into a higher-resolution 512x512 image. +- 텍스트 인코더 + - 프롬프트를 잠재 벡터로 변환하는 텍스트 인코더. +- 확산 모델 + - 64x64 잠재 이미지 패치를 반복적으로 "노이즈 제거"하는 확산 모델. +- 디코더 + - 최종 64x64 잠재 패치를 고해상도 512x512 이미지로 변환하는 디코더. -First, your text prompt gets projected into a latent vector space by the text encoder, which is simply a pretrained, frozen language model. Then that prompt vector is concatenated to a randomly generated noise patch, which is repeatedly "denoised" by the diffusion model over a series of "steps" (the more steps you run the clearer and nicer your image will be – the default value is 50 steps). +먼저, 텍스트 프롬프트는 텍스트 인코더에 의해 잠재 벡터 공간에 프로젝션됩니다. +텍스트 인코더는 단순히 사전 트레이닝된, 동결된 언어 모델입니다. +그런 다음, 해당 프롬프트 벡터는 무작위로 생성된 노이즈 패치에 연결(concatenated)되고, +이는 일련의 "단계"에 걸쳐 확산 모델에 의해 반복적으로 "노이즈 제거"됩니다. +(단계를 많이 실행할수록 이미지가 더 선명하고 좋아집니다. 기본값은 50 단계입니다) -Finally, the 64x64 latent image is sent through the decoder to properly render it in high resolution. +마지막으로, 64x64 잠재 이미지는 디코더를 통해 전송되어, 고해상도로 적절하게 렌더링됩니다. ![The Stable Diffusion architecture](/images/guides/keras_cv/generate_images_with_stable_diffusion/2uC8rYJ.png) -All-in-all, it's a pretty simple system – the Keras implementation fits in four files that represent less than 500 lines of code in total: +전반적으로 매우 간단한 시스템입니다. +Keras 구현은 총 500줄 미만의 코드를 나타내는 4개의 파일에 들어맞습니다. - [text_encoder.py](https://github.com/keras-team/keras-cv/blob/master/keras_cv/models/stable_diffusion/text_encoder.py): 87 LOC - [diffusion_model.py](https://github.com/keras-team/keras-cv/blob/master/keras_cv/models/stable_diffusion/diffusion_model.py): 181 LOC - [decoder.py](https://github.com/keras-team/keras-cv/blob/master/keras_cv/models/stable_diffusion/decoder.py): 86 LOC - [stable_diffusion.py](https://github.com/keras-team/keras-cv/blob/master/keras_cv/models/stable_diffusion/stable_diffusion.py): 106 LOC -But this relatively simple system starts looking like magic once you train on billions of pictures and their captions. As Feynman said about the universe: _"It's not complicated, it's just a lot of it!"_ +하지만 이 비교적 간단한 시스템은 수십억 개의 사진과 캡션으로 트레이닝하면 마법처럼 보이기 시작합니다. +파인만이 우주에 대해 말했듯이: _"복잡하지 않아, 그저 양이 많을 뿐이야!"_ -## Perks of KerasCV +## KerasCV의 장점 {#perks-of-kerascv} -With several implementations of Stable Diffusion publicly available why should you use [`keras_cv.models.StableDiffusion`]({{< relref "/docs/api/keras_cv/models/tasks/stable_diffusion#stablediffusion-class" >}})? +여러 가지 Stable Diffusion 구현이 공개적으로 제공되고 있는데, +왜 [`keras_cv.models.StableDiffusion`]({{< relref "/docs/api/keras_cv/models/tasks/stable_diffusion#stablediffusion-class" >}})을 사용해야 할까요? -Aside from the easy-to-use API, KerasCV's Stable Diffusion model comes with some powerful advantages, including: +사용하기 쉬운 API 외에도, KerasCV의 Stable Diffusion 모델은 다음과 같은 강력한 장점을 제공합니다. -- Graph mode execution -- XLA compilation through `jit_compile=True` -- Support for mixed precision computation +- 그래프 모드 실행 +- `jit_compile=True`를 통한 XLA 컴파일 +- 혼합 정밀도 계산 지원 -When these are combined, the KerasCV Stable Diffusion model runs orders of magnitude faster than naive implementations. This section shows how to enable all of these features, and the resulting performance gain yielded from using them. +이러한 기능을 결합하면, KerasCV Stable Diffusion 모델은 naive 구현보다 훨씬 빠르게 실행됩니다. +이 섹션에서는 이러한 모든 기능을 활성화하는 방법과, +이를 사용하여 얻은 성능 향상을 보여줍니다. -For the purposes of comparison, we ran benchmarks comparing the runtime of the [HuggingFace diffusers](https://github.com/huggingface/diffusers) implementation of Stable Diffusion against the KerasCV implementation. Both implementations were tasked to generate 3 images with a step count of 50 for each image. In this benchmark, we used a Tesla T4 GPU. +비교를 위해, Stable Diffusion의 +[HuggingFace 디퓨저](https://github.com/huggingface/diffusers) 구현의 +런타임을 KerasCV 구현과 비교하는 벤치마크를 실행했습니다. +두 구현 모두 각 이미지에 대해 50단계의 스텝 카운트로 3개의 이미지를 생성하도록 했습니다. +이 벤치마크에서는, Tesla T4 GPU를 사용했습니다. -[All of our benchmarks are open source on GitHub, and may be re-run on Colab to reproduce the results.](https://github.com/LukeWood/stable-diffusion-performance-benchmarks) The results from the benchmark are displayed in the table below: +[모든 벤치마크는 GitHub에서 오픈 소스이며, Colab에서 다시 실행하여 결과를 재현할 수 있습니다](https://github.com/LukeWood/stable-diffusion-performance-benchmarks). +벤치마크의 결과는 아래 표에 표시됩니다. -| GPU | Model | Runtime | +| GPU | 모델 | 실행 시간 | | ---------- | ---------------------- | ---------- | | Tesla T4 | KerasCV (Warm Start) | **28.97s** | | Tesla T4 | diffusers (Warm Start) | 41.33s | | Tesla V100 | KerasCV (Warm Start) | **12.45** | | Tesla V100 | diffusers (Warm Start) | 12.72 | -30% improvement in execution time on the Tesla T4!. While the improvement is much lower on the V100, we generally expect the results of the benchmark to consistently favor the KerasCV across all NVIDIA GPUs. +Tesla T4에서 실행 시간이 30% 향상되었습니다! +V100에서는 개선 폭이 훨씬 낮지만, +일반적으로 벤치마크 결과는 모든 NVIDIA GPU에 걸쳐 KerasCV를 일관되게 선호할 것으로 예상합니다. -For the sake of completeness, both cold-start and warm-start generation times are reported. Cold-start execution time includes the one-time cost of model creation and compilation, and is therefore negligible in a production environment (where you would reuse the same model instance many times). Regardless, here are the cold-start numbers: +완전성을 위해, 콜드 스타트와 웜 스타트 생성 시간을 모두 보고합니다. +콜드 스타트 ​​실행 시간에는 모델 생성 및 컴파일의 일회성 비용이 포함되므로, +프로덕션 환경(동일한 모델 인스턴스를 여러 번 재사용하는 환경)에서는 무시할 수 있습니다. +그럼에도 불구하고, 콜드 스타트의 ​​숫자는 다음과 같습니다. -| GPU | Model | Runtime | -| ---------- | ---------------------- | ------- | -| Tesla T4 | KerasCV (Cold Start) | 83.47s | -| Tesla T4 | diffusers (Cold Start) | 46.27s | -| Tesla V100 | KerasCV (Cold Start) | 76.43 | -| Tesla V100 | diffusers (Cold Start) | 13.90 | +| GPU | 모델 | 실행 시간 | +| ---------- | ---------------------- | --------- | +| Tesla T4 | KerasCV (Cold Start) | 83.47s | +| Tesla T4 | diffusers (Cold Start) | 46.27s | +| Tesla V100 | KerasCV (Cold Start) | 76.43 | +| Tesla V100 | diffusers (Cold Start) | 13.90 | -While the runtime results from running this guide may vary, in our testing the KerasCV implementation of Stable Diffusion is significantly faster than its PyTorch counterpart. This may be largely attributed to XLA compilation. +이 가이드를 실행한 런타임 결과는 다양할 수 있지만, +우리의 테스트에서 KerasCV의 Stable Diffusion 구현은 PyTorch 대응 제품보다 상당히 빠릅니다. +이는 주로 XLA 컴파일 때문일 수 있습니다. -**Note: The performance benefits of each optimization can vary significantly between hardware setups.** +**참고: 각 최적화의 성능 이점은 하드웨어 설정에 따라 상당히 다를 수 있습니다.** -To get started, let's first benchmark our unoptimized model: +시작하려면, 먼저 최적화되지 않은 모델을 벤치마킹해 보겠습니다. ```python benchmark_result = [] @@ -223,17 +276,21 @@ Standard model: 10.57 seconds ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_13_1.png) -### Mixed precision +### 혼합 정밀도 (Mixed precision) {#mixed-precision} -"Mixed precision" consists of performing computation using `float16` precision, while storing weights in the `float32` format. This is done to take advantage of the fact that `float16` operations are backed by significantly faster kernels than their `float32` counterparts on modern NVIDIA GPUs. +"혼합 정밀도"는 `float32` 형식으로 가중치를 저장하는 동안, +`float16` 정밀도를 사용하여 계산을 수행하는 것으로 구성됩니다. +이는 `float16` 연산이 최신 NVIDIA GPU에서 `float32` 대응 연산보다, +훨씬 빠른 커널에 의해 지원된다는 사실을 이용하기 위해 수행됩니다. -Enabling mixed precision computation in Keras (and therefore for [`keras_cv.models.StableDiffusion`]({{< relref "/docs/api/keras_cv/models/tasks/stable_diffusion#stablediffusion-class" >}}) is as simple as calling: +Keras에서 혼합 정밀도 계산을 활성화하는 것(따라서 [`keras_cv.models.StableDiffusion`]({{< relref "/docs/api/keras_cv/models/tasks/stable_diffusion#stablediffusion-class" >}}))은, +다음을 호출하는 것만큼 간단합니다. ```python keras.mixed_precision.set_global_policy("mixed_float16") ``` -That's all. Out of the box - it just works. +그게 전부입니다. 상자에서 꺼내자마자, 바로 작동합니다. ```python model = keras_cv.models.StableDiffusion(jit_compile=False) @@ -255,10 +312,12 @@ Variable dtype: float32 {{% /details %}} -As you can see, the model constructed above now uses mixed precision computation; leveraging the speed of `float16` operations for computation, while storing variables in `float32` precision. +위에서 구성한 모델은, 이제 혼합 정밀도 계산을 사용합니다. +즉, 계산을 위해 `float16` 연산의 속도를 활용하는 동시에, +`float32` 정밀도로 변수를 저장합니다. ```python -# Warm up model to run graph tracing before benchmarking. +# 벤치마킹을 하기 전에, 그래프 추적을 실행하기 위해 모델을 워밍업합니다. model.text_to_image("warming up the model", batch_size=3) start = time.time() @@ -288,19 +347,22 @@ Mixed precision model: 6.65 seconds ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_19_1.png) -### XLA Compilation +### XLA 컴파일 {#xla-compilation} -TensorFlow and JAX come with the [XLA: Accelerated Linear Algebra](https://www.tensorflow.org/xla) compiler built-in. [`keras_cv.models.StableDiffusion`]({{< relref "/docs/api/keras_cv/models/tasks/stable_diffusion#stablediffusion-class" >}}) supports a `jit_compile` argument out of the box. Setting this argument to `True` enables XLA compilation, resulting in a significant speed-up. +TensorFlow와 JAX에는 [XLA: Accelerated Linear Algebra](https://www.tensorflow.org/xla) 컴파일러가 기본 제공됩니다. +[`keras_cv.models.StableDiffusion`]({{< relref "/docs/api/keras_cv/models/tasks/stable_diffusion#stablediffusion-class" >}})는 기본적으로 `jit_compile` 인수를 지원합니다. +이 인수를 `True`로 설정하면, XLA 컴파일이 활성화되어 속도가 상당히 향상됩니다. -Let's use this below: +아래에서 이것을 사용해 보겠습니다. ```python -# Set back to the default for benchmarking purposes. +# 벤치마킹 목적으로 기본값으로 되돌립니다. keras.mixed_precision.set_global_policy("float32") model = keras_cv.models.StableDiffusion(jit_compile=True) -# Before we benchmark the model, we run inference once to make sure the TensorFlow -# graph has already been traced. +# 모델을 벤치마킹하기 전에, +# 추론을 한 번 실행하여, +# TensorFlow 그래프가 이미 추적되었는지 확인합니다. images = model.text_to_image("An avocado armchair", batch_size=3) plot_images(images) ``` @@ -316,7 +378,7 @@ By using this model checkpoint, you acknowledge that its usage is subject to the ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_21_1.png) -Let's benchmark our XLA model: +XLA 모델을 벤치마킹해 보겠습니다. ```python start = time.time() @@ -343,13 +405,14 @@ With XLA: 10.63 seconds ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_23_1.png) -On an A100 GPU, we get about a 2x speedup. Fantastic! +A100 GPU에서는, 약 2배의 속도 향상을 얻습니다. 환상적이죠! -## Putting it all together +## 모두 합치기 {#putting-it-all-together} -So, how do you assemble the world's most performant stable diffusion inference pipeline (as of September 2022). +그렇다면, (2022년 9월 기준으로) 세계에서 가장 성능이 뛰어난, +stable diffusion 추론 파이프라인을 어떻게 조립합니까? -With these two lines of code: +다음 두 줄의 코드면 됩니다: ```python keras.mixed_precision.set_global_policy("mixed_float16") @@ -364,10 +427,10 @@ By using this model checkpoint, you acknowledge that its usage is subject to the {{% /details %}} -And to use it... +그리고 그것을 사용하려면... ```python -# Let's make sure to warm up the model +# 모델을 워밍업하는 것을 잊지 마세요. images = model.text_to_image( "Teddy bears conducting machine learning research", batch_size=3, @@ -385,7 +448,7 @@ plot_images(images) ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_28_1.png) -Exactly how fast is it? Let's find out! +정확히 얼마나 빠른가요? 알아보죠! ```python start = time.time() @@ -413,7 +476,7 @@ XLA + mixed precision: 6.66 seconds ![png](/images/guides/keras_cv/generate_images_with_stable_diffusion/generate_images_with_stable_diffusion_30_1.png) -Let's check out the results: +결과를 확인해 보겠습니다. ```python print("{:<22} {:<22}".format("Model", "Runtime")) @@ -434,14 +497,21 @@ XLA + Mixed Precision 6.659237861633301 {{% /details %}} -It only took our fully-optimized model four seconds to generate three novel images from a text prompt on an A100 GPU. +완전히 최적화된 모델은, +A100 GPU에서 텍스트 프롬프트로부터 세 개의 새로운 이미지를 생성하는 데 불과 4초가 걸렸습니다. -## Conclusions +## 결론 {#conclusions} -KerasCV offers a state-of-the-art implementation of Stable Diffusion – and through the use of XLA and mixed precision, it delivers the fastest Stable Diffusion pipeline available as of September 2022. +KerasCV는 Stable Diffusion의 최첨단 구현을 제공하며, +XLA와 혼합 정밀도를 사용하여, +(2022년 9월 현재) 사용 가능한 가장 빠른 Stable Diffusion 파이프라인을 제공합니다. -Normally, at the end of a keras.io tutorial we leave you with some future directions to continue in to learn. This time, we leave you with one idea: +일반적으로, keras.io 튜토리얼의 마지막에 학습을 계속할 수 있는 몇 가지 향후 지침을 제공합니다. +이번에는 한 가지 아이디어를 제공합니다. -**Go run your own prompts through the model! It is an absolute blast!** +**모델에서 직접 프롬프트를 실행해 보세요! 정말 최고예요!** -If you have your own NVIDIA GPU, or a M1 MacBookPro, you can also run the model locally on your machine. (Note that when running on a M1 MacBookPro, you should not enable mixed precision, as it is not yet well supported by Apple's Metal runtime.) +NVIDIA GPU나 M1 MacBookPro가 있는 경우, +머신에서 로컬로 모델을 실행할 수도 있습니다. +(M1 MacBookPro에서 실행할 때는 아직 Apple의 Metal 런타임에서 잘 지원되지 않으므로, +혼합 정밀도를 활성화해서는 안 됩니다.) diff --git a/content/korean/docs/guides/keras_cv/object_detection_keras_cv/_index.md b/content/korean/docs/guides/keras_cv/object_detection_keras_cv/_index.md index 1c611afb..8abd1ac5 100644 --- a/content/korean/docs/guides/keras_cv/object_detection_keras_cv/_index.md +++ b/content/korean/docs/guides/keras_cv/object_detection_keras_cv/_index.md @@ -1,6 +1,6 @@ --- -title: Object Detection with KerasCV -linkTitle: Use KerasCV to assemble object detection pipelines +title: KerasCV를 사용하여 객체 감지 파이프라인 조립 +linkTitle: KerasCV로 객체 감지 toc: true weight: 1 type: docs @@ -11,20 +11,23 @@ type: docs **{{< t f_author >}}** [lukewood](https://twitter.com/luke_wood_ml), Ian Stenbit, Tirth Patel **{{< t f_date_created >}}** 2023/04/08 **{{< t f_last_modified >}}** 2023/08/10 -**{{< t f_description >}}** Train an object detection model with KerasCV. +**{{< t f_description >}}** KerasCV를 사용하여 객체 감지 모델을 트레이닝. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_cv/object_detection_keras_cv.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_cv/object_detection_keras_cv.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -KerasCV offers a complete set of production grade APIs to solve object detection problems. These APIs include object-detection-specific data augmentation techniques, Keras native COCO metrics, bounding box format conversion utilities, visualization tools, pretrained object detection models, and everything you need to train your own state of the art object detection models! +KerasCV는 객체 감지 문제를 해결하기 위한 완전한 프로덕션 등급 API 세트를 제공합니다. +이러한 API에는 객체 감지 특화 데이터 보강 기술, Keras 네이티브 COCO 메트릭, +바운딩 박스 형식 변환 유틸리티, 시각화 도구, 사전 트레이닝된 객체 감지 모델, +그리고 최첨단 객체 감지 모델을 스스로 트레이닝하는 데 필요한 모든 것이 포함됩니다! -Let's give KerasCV's object detection API a spin. +KerasCV의 객체 감지 API를 한 번 사용해 보겠습니다. ```python !pip install -q --upgrade keras-cv -!pip install -q --upgrade keras # Upgrade to Keras 3. +!pip install -q --upgrade keras # Keras 3로 업그레이드. ``` ```python @@ -43,45 +46,57 @@ from keras_cv import visualization import tqdm ``` -## Object detection introduction +## 객체 감지 소개 {#object-detection-introduction} -Object detection is the process of identifying, classifying, and localizing objects within a given image. Typically, your inputs are images, and your labels are bounding boxes with optional class labels. Object detection can be thought of as an extension of classification, however instead of one class label for the image, you must detect and localize an arbitrary number of classes. +객체 감지는 주어진 이미지 내에서 객체를 식별, 분류 및 지역화하는 프로세스입니다. +일반적으로, 입력은 이미지이고, 레이블은 선택적 클래스 레이블이 있는 경계 상자입니다. +객체 감지는 분류의 확장으로 생각할 수 있지만, +이미지에 대한 하나의 클래스 레이블 대신, +임의의 수의 클래스를 감지하고 지역화해야 합니다. -**For example:** +**예:** ![png](/images/guides/keras_cv/object_detection_keras_cv/8xSEbQD.png) -The data for the above image may look something like this: +위 이미지의 데이터는 다음과 같습니다. ```python image = [height, width, 3] bounding_boxes = { - "classes": [0], # 0 is an arbitrary class ID representing "cat" + "classes": [0], # 0은 "cat"을 나타내는 임의의 클래스 ID입니다. "boxes": [[0.25, 0.4, .15, .1]] - # bounding box is in "rel_xywh" format - # so 0.25 represents the start of the bounding box 25% of - # the way across the image. - # The .15 represents that the width is 15% of the image width. + # 경계 상자는 "rel_xywh" 형식이므로, + # 0.25는 이미지 전체 길이의 25% 지점에서 경계 상자의 시작을 나타냅니다. + # .15는 너비가 이미지 너비의 15%임을 나타냅니다. } ``` -Since the inception of [_You Only Look Once_](https://arxiv.org/abs/1506.02640) (aka YOLO), object detection has primarily been solved using deep learning. Most deep learning architectures do this by cleverly framing the object detection problem as a combination of many small classification problems and many regression problems. +[_You Only Look Once_](https://arxiv.org/abs/1506.02640)(일명 YOLO)가 시작된 이래로, +객체 감지는 주로 딥러닝을 사용하여 해결되었습니다. +대부분의 딥러닝 아키텍처는 객체 감지 문제를, +여러 작은 분류 문제와 여러 회귀 문제의 조합으로 교묘하게 구성하여 이를 수행합니다. -More specifically, this is done by generating many anchor boxes of varying shapes and sizes across the input images and assigning them each a class label, as well as `x`, `y`, `width` and `height` offsets. The model is trained to predict the class labels of each box, as well as the `x`, `y`, `width`, and `height` offsets of each box that is predicted to be an object. +더 구체적으로, 이는 입력 이미지에서 다양한 모양과 크기의 앵커 상자를 여러 개 생성하고, +각각에 클래스 레이블과 `x`, `y`, `width` 및 `height` 오프셋을 할당하여 수행됩니다. +모델은 각 상자의 클래스 레이블과, +객체로 예측되는 각 상자의 `x`, `y`, `width` 및 `height` 오프셋을 예측하도록 트레이닝됩니다. -**Visualization of some sample anchor boxes**: +**일부 샘플 앵커 상자(anchor boxes)의 시각화**: ![jpg](/images/guides/keras_cv/object_detection_keras_cv/cJIuiK9.jpg) -Objection detection is a technically complex problem but luckily we offer a bulletproof approach to getting great results. Let's do this! +객체 감지는 기술적으로 복잡한 문제이지만, +다행히도 우리는 훌륭한 결과를 얻기 위한 확실한 방법을 제공합니다. +시작해 봅시다! -## Perform detections with a pretrained model +## 사전 트레이닝된 모델로 감지 수행 {#perform-detections-with-a-pretrained-model} ![png](/images/keras-hub/getting_started_guide/prof_keras_beginner.png) -The highest level API in the KerasCV Object Detection API is the `keras_cv.models` API. This API includes fully pretrained object detection models, such as [`keras_cv.models.YOLOV8Detector`]({{< relref "/docs/api/keras_cv/models/tasks/yolo_v8_detector#yolov8detector-class" >}}). +KerasCV 객체 감지 API에서 가장 높은 레벨의 API는 `keras_cv.models` API입니다. +이 API에는 [`keras_cv.models.YOLOV8Detector`]({{< relref "/docs/api/keras_cv/models/tasks/yolo_v8_detector#yolov8detector-class" >}})와 같은 완전히 사전 트레이닝된 객체 감지 모델이 포함됩니다. -Let's get started by constructing a YOLOV8Detector pretrained on the `pascalvoc` dataset. +`pascalvoc` 데이터 세트에 대해 사전 트레이닝된 YOLOV8Detector를 구성하여 시작해 보겠습니다. ```python pretrained_model = keras_cv.models.YOLOV8Detector.from_preset( @@ -89,9 +104,9 @@ pretrained_model = keras_cv.models.YOLOV8Detector.from_preset( ) ``` -Notice the `bounding_box_format` argument? +`bounding_box_format` 인수를 주목하세요? -Recall in the section above, the format of bounding boxes: +위 섹션에서, 경계 상자의 형식을 떠올려 보세요. ```python bounding_boxes = { @@ -100,23 +115,34 @@ bounding_boxes = { } ``` -This argument describes _exactly_ what format the values in the `"boxes"` field of the label dictionary take in your pipeline. For example, a box in `xywh` format with its top left corner at the coordinates (100, 100) with a width of 55 and a height of 70 would be represented by: +이 인수는 파이프라인에서 레이블 딕셔너리의 `"boxes"` 필드에 있는 값이 취하는 형식을 _정확히_ 설명합니다. +예를 들어, 왼쪽 위 모서리가 좌표(100, 100)에 있고 너비가 55, 높이가 70인, +`xywh` 형식의 상자는 다음과 같이 표현됩니다. ```python [100, 100, 55, 75] ``` -or equivalently in `xyxy` format: +또는 동등하게 `xyxy` 형식으로 표현하면 다음과 같습니다: ```python [100, 100, 155, 175] ``` -While this may seem simple, it is a critical piece of the KerasCV object detection API! Every component that processes bounding boxes requires a `bounding_box_format` argument. You can read more about KerasCV bounding box formats [in the API docs]({{< relref "/docs/api/keras_cv/bounding_box/formats" >}}). +간단해 보일 수 있지만, KerasCV 객체 감지 API의 중요한 부분입니다! +경계 상자를 처리하는 모든 구성 요소에는 `bounding_box_format` 인수가 필요합니다. +KerasCV 경계 상자 형식에 대한 자세한 내용은, +[API 문서]({{< relref "/docs/api/keras_cv/bounding_box/formats" >}})에서 확인할 수 있습니다. -This is done because there is no one correct format for bounding boxes! Components in different pipelines expect different formats, and so by requiring them to be specified we ensure that our components remain readable, reusable, and clear. Box format conversion bugs are perhaps the most common bug surface in object detection pipelines - by requiring this parameter we mitigate against these bugs (especially when combining code from many sources). +경계 상자에 대한 올바른 형식이 없기 때문에 이렇게 합니다! +다른 파이프라인의 구성 요소는 다른 형식을 기대하므로, +형식을 지정하도록 요구함으로써, +구성 요소가 읽기 쉽고 재사용 가능하며 명확하게 유지되도록 합니다. +상자 형식 변환 버그는 아마도 객체 감지 파이프라인에서 가장 흔한 버그 표면일 것입니다. +이 매개변수를 요구함으로써 이러한 버그를 완화합니다. +(특히 여러 소스의 코드를 결합할 때) -Next let's load an image: +다음으로 이미지를 로드해 보겠습니다. ```python filepath = keras.utils.get_file(origin="https://i.imgur.com/gCNcJJI.jpg") @@ -136,15 +162,24 @@ visualization.plot_image_gallery( ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_8_1.png) -To use the `YOLOV8Detector` architecture with a ResNet50 backbone, you'll need to resize your image to a size that is divisible by 64. This is to ensure compatibility with the number of downscaling operations done by the convolution layers in the ResNet. +ResNet50 백본과 함께 `YOLOV8Detector` 아키텍처를 사용하려면, +이미지 크기를 64로 나누어 떨어지는 크기로 조정해야 합니다. +이는 ResNet의 컨볼루션 레이어에서 수행되는, +다운스케일링 연산 수와의 호환성을 보장하기 위한 것입니다. -If the resize operation distorts the input's aspect ratio, the model will perform signficantly poorer. For the pretrained `"yolo_v8_m_pascalvoc"` preset we are using, the final `MeanAveragePrecision` on the `pascalvoc/2012` evaluation set drops to `0.15` from `0.38` when using a naive resizing operation. +크기 조정 연산으로 인해 입력의 종횡비가 왜곡되면, 모델의 성능이 상당히 떨어집니다. +사용 중인 사전 트레이닝된 `"yolo_v8_m_pascalvoc"` 사전 설정의 경우, +naive 크기 조정 연산을 사용할 때, +`pascalvoc/2012` 평가 세트에 대한 최종 `MeanAveragePrecision`이 `0.38`에서 `0.15`로 떨어집니다. -Additionally, if you crop to preserve the aspect ratio as you do in classification your model may entirely miss some bounding boxes. As such, when running inference on an object detection model we recommend the use of padding to the desired size, while resizing the longest size to match the aspect ratio. +또한, 분류에서처럼 종횡비를 유지하기 위해 자르면, 모델에서 일부 경계 상자가 완전히 누락될 수 있습니다. +따라서, 객체 감지 모델에서 추론을 실행할 때는, 원하는 크기로 패딩을 사용하는 동시에, +가장 긴 크기를 종횡비에 맞게 크기를 조정하는 것이 좋습니다. -KerasCV makes resizing properly easy; simply pass `pad_to_aspect_ratio=True` to a [`keras_cv.layers.Resizing`]({{< relref "/docs/api/keras_cv/layers/preprocessing/resizing#resizing-class" >}}) layer. +KerasCV는 크기 조절을 제대로 쉽게 만듭니다. +간단히 `pad_to_aspect_ratio=True`를 [`keras_cv.layers.Resizing`]({{< relref "/docs/api/keras_cv/layers/preprocessing/resizing#resizing-class" >}}) 레이어에 전달하면 됩니다. -This can be implemented in one line of code: +이는 한 줄의 코드로 구현할 수 있습니다. ```python inference_resizing = keras_cv.layers.Resizing( @@ -152,13 +187,15 @@ inference_resizing = keras_cv.layers.Resizing( ) ``` -This can be used as our inference preprocessing pipeline: +이는 추론 전처리 파이프라인으로 사용할 수 있습니다. ```python image_batch = inference_resizing([image]) ``` -`keras_cv.visualization.plot_bounding_box_gallery()` supports a `class_mapping` parameter to highlight what class each box was assigned to. Let's assemble a class mapping now. +`keras_cv.visualization.plot_bounding_box_gallery()`는, +각 상자가 어떤 클래스에 할당되었는지 강조하기 위한 `class_mapping` 매개변수를 지원합니다. +이제 클래스 매핑을 조립해 보겠습니다. ```python class_ids = [ @@ -187,11 +224,12 @@ class_ids = [ class_mapping = dict(zip(range(len(class_ids)), class_ids)) ``` -Just like any other [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}) you can predict bounding boxes using the `model.predict()` API. +다른 [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})과 마찬가지로, +`model.predict()` API를 사용하여 경계 상자를 예측할 수 있습니다. ```python y_pred = pretrained_model.predict(image_batch) -# y_pred is a bounding box Tensor: +# y_pred는 바운딩 박스 텐서입니다. # {"classes": ..., boxes": ...} visualization.plot_bounding_box_gallery( image_batch, @@ -218,14 +256,20 @@ visualization.plot_bounding_box_gallery( ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_16_2.png) -In order to support this easy and intuitive inference workflow, KerasCV performs non-max suppression inside of the `YOLOV8Detector` class. Non-max suppression is a traditional computing algorithm that solves the problem of a model detecting multiple boxes for the same object. +이 간편하고 직관적인 추론 워크플로를 지원하기 위해, +KerasCV는 `YOLOV8Detector` 클래스 내부에서 비최대 억제(Non-max suppression)를 수행합니다. +Non-max 억제는 모델이 동일한 객체에 대해, +여러 상자를 감지하는 문제를 해결하는 기존 컴퓨팅 알고리즘입니다. -Non-max suppression is a highly configurable algorithm, and in most cases you will want to customize the settings of your model's non-max suppression operation. This can be done by overriding to the `prediction_decoder` argument. +Non-max 억제는 구성 가능성이 매우 높은 알고리즘이며, +대부분의 경우 모델의 Non-max 억제 연산 설정을 커스터마이즈하고 싶을 것입니다. +이는 `prediction_decoder` 인수를 재정의하여 수행할 수 있습니다. -To show this concept off, let's temporarily disable non-max suppression on our YOLOV8Detector. This can be done by writing to the `prediction_decoder` attribute. +이 개념을 보여주기 위해, YOLOV8Detector에서 Non-max 억제를 일시적으로 비활성화해 보겠습니다. +이는 `prediction_decoder` 속성에 작성하여 수행할 수 있습니다. ```python -# The following NonMaxSuppression layer is equivalent to disabling the operation +# 다음 NonMaxSuppression 레이어는 연산을 비활성화하는 것과 동일합니다. prediction_decoder = keras_cv.layers.NonMaxSuppression( bounding_box_format="xywh", from_logits=True, @@ -264,17 +308,20 @@ visualization.plot_bounding_box_gallery( ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_18_2.png) -Next, let's re-configure `keras_cv.layers.NonMaxSuppression` for our use case! In this case, we will tune the `iou_threshold` to `0.2`, and the `confidence_threshold` to `0.7`. +다음으로, 우리의 사용 사례에 맞게 `keras_cv.layers.NonMaxSuppression`을 재구성해 보겠습니다! +이 경우 `iou_threshold`를 `0.2`로, `confidence_threshold`를 `0.7`로 조정합니다. -Raising the `confidence_threshold` will cause the model to only output boxes that have a higher confidence score. `iou_threshold` controls the threshold of intersection over union (IoU) that two boxes must have in order for one to be pruned out. [More information on these parameters may be found in the TensorFlow API docs](https://www.tensorflow.org/api_docs/python/tf/image/combined_non_max_suppression) +`confidence_threshold`를 높이면, 모델이 신뢰 점수가 더 높은 상자만 출력합니다. +`iou_threshold`는 두 상자가 하나를 잘라내기 위해 가져야 하는 교집합(IoU)에 대한 임계값을 제어합니다. +[이러한 매개변수에 대한 자세한 내용은 TensorFlow API 문서](https://www.tensorflow.org/api_docs/python/tf/image/combined_non_max_suppression)에서 확인할 수 있습니다. ```python prediction_decoder = keras_cv.layers.NonMaxSuppression( bounding_box_format="xywh", from_logits=True, - # Decrease the required threshold to make predictions get pruned out + # 예측이 가지치기(pruned out)되도록 필요한 임계값을 낮추세요 iou_threshold=0.2, - # Tune confidence threshold for predictions to pass NMS + # NMS를 통과하기 위한 예측 신뢰도 임계값 조정 confidence_threshold=0.7, ) pretrained_model = keras_cv.models.YOLOV8Detector.from_preset( @@ -309,39 +356,52 @@ visualization.plot_bounding_box_gallery( ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_20_2.png) -That looks a lot better! +훨씬 좋아 보이네요! -## Train a custom object detection model +## 커스텀 객체 감지 모델 트레이닝 {#train-a-custom-object-detection-model} ![png](/images/keras-hub/getting_started_guide/prof_keras_advanced.png) -Whether you're an object detection amateur or a well seasoned veteran, assembling an object detection pipeline from scratch is a massive undertaking. Luckily, all KerasCV object detection APIs are built as modular components. Whether you need a complete pipeline, just an object detection model, or even just a conversion utility to transform your boxes from `xywh` format to `xyxy`, KerasCV has you covered. +객체 감지 아마추어이든 노련한 베테랑이든, 객체 감지 파이프라인을 처음부터 조립하는 것은 엄청난 작업입니다. +다행히도, 모든 KerasCV 객체 감지 API는 모듈식 구성 요소로 빌드됩니다. +완전한 파이프라인이 필요하든, 객체 감지 모델만 필요하든, +심지어 상자를 `xywh` 형식에서 `xyxy` 형식으로 변환하는 변환 유틸리티만 필요하든, KerasCV가 해결해 드립니다. -In this guide, we'll assemble a full training pipeline for a KerasCV object detection model. This includes data loading, augmentation, metric evaluation, and inference! +이 가이드에서는 KerasCV 객체 감지 모델을 위한 전체 트레이닝 파이프라인을 조립합니다. +여기에는 데이터 로딩, 보강, 메트릭 평가 및 추론이 포함됩니다! -To get started, let's sort out all of our imports and define global configuration parameters. +시작하려면, 모든 import를 정리하고, 글로벌 구성 매개변수를 정의해 보겠습니다. ```python BATCH_SIZE = 4 ``` -## Data loading +## 데이터 로딩 {#data-loading} -To get started, let's discuss data loading and bounding box formatting. KerasCV has a predefined format for bounding boxes. To comply with this, you should package your bounding boxes into a dictionary matching the specification below: +시작하기 위해, 데이터 로딩과 바운딩 박스 포맷팅에 대해 논의해 보겠습니다. +KerasCV에는 바운딩 박스에 대한 사전 정의된 포맷이 있습니다. +이를 준수하려면, 바운딩 박스를 아래 사양과 일치하는 딕셔너리에 패키징해야 합니다. ```python bounding_boxes = { - # num_boxes may be a Ragged dimension + # num_boxes는 Ragged 차원일 수 있습니다. 'boxes': Tensor(shape=[batch, num_boxes, 4]), 'classes': Tensor(shape=[batch, num_boxes]) } ``` -`bounding_boxes['boxes']` contains the coordinates of your bounding box in a KerasCV supported `bounding_box_format`. KerasCV requires a `bounding_box_format` argument in all components that process bounding boxes. This is done to maximize your ability to plug and play individual components into their object detection pipelines, as well as to make code self-documenting across object detection pipelines. +`bounding_boxes['boxes']`에는 KerasCV에서 지원하는 +`bounding_box_format`에서 바운딩 박스의 좌표가 포함됩니다. +KerasCV는 바운딩 박스를 처리하는 모든 구성 요소에서 `bounding_box_format` 인수가 필요합니다. +이는 개별 구성 요소를 객체 감지 파이프라인에 플러그 앤 플레이하는 기능을 극대화하고, +객체 감지 파이프라인에서 코드를 자체 문서화하기 위해 수행됩니다. -To match the KerasCV API style, it is recommended that when writing a custom data loader, you also support a `bounding_box_format` argument. This makes it clear to those invoking your data loader what format the bounding boxes are in. In this example, we format our boxes to `xywh` format. +KerasCV API 스타일과 일치하도록, 커스텀 데이터 로더를 작성할 때, +`bounding_box_format` 인수도 지원하는 것이 좋습니다. +이렇게 하면, 데이터 로더를 호출하는 사람에게 바운딩 박스의 형식이 무엇인지 명확하게 알 수 있습니다. +이 예에서는, 상자를 `xywh` 형식으로 포맷합니다. -For example: +예를 들어: ```python train_ds, ds_info = your_data_loader.load( @@ -349,11 +409,14 @@ train_ds, ds_info = your_data_loader.load( ) ``` -This clearly yields bounding boxes in the format `xywh`. You can read more about KerasCV bounding box formats [in the API docs]({{< relref "/docs/api/keras_cv/bounding_box/formats" >}}). +이렇게 하면 `xywh` 형식의 경계 상자가 명확하게 생성됩니다. +KerasCV 경계 상자 형식에 대한 자세한 내용은, +[API 문서]({{< relref "/docs/api/keras_cv/bounding_box/formats" >}})에서 확인할 수 있습니다. -Our data comes loaded into the format `{"images": images, "bounding_boxes": bounding_boxes}`. This format is supported in all KerasCV preprocessing components. +데이터는 `{"images": images, "bounding_boxes": bounding_boxes}` 형식으로 로드됩니다. +이 형식은 모든 KerasCV 전처리 구성 요소에서 지원됩니다. -Let's load some data and verify that the data looks as we expect it to. +데이터를 로드하고 데이터가 예상대로 표시되는지 확인해 보겠습니다. ```python def visualize_dataset(inputs, value_range, rows, cols, bounding_box_format): @@ -404,18 +467,25 @@ eval_ds = load_pascal_voc(split="test", dataset="voc/2007", bounding_box_format= train_ds = train_ds.shuffle(BATCH_SIZE * 4) ``` -Next, let's batch our data. +다음으로, 데이터를 배치화 해보겠습니다. -In KerasCV object detection tasks it is recommended that users use ragged batches of inputs. This is due to the fact that images may be of different sizes in PascalVOC, as well as the fact that there may be different numbers of bounding boxes per image. +KerasCV 객체 감지 작업에서는 사용자가 입력의 불규칙 배치(ragged batches)를 사용하는 것이 좋습니다. +이는 PascalVOC에서 이미지 크기가 다를 수 있고, +이미지당 경계 상자의 수가 다를 수 있기 때문입니다. -To construct a ragged dataset in a [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) pipeline, you can use the `ragged_batch()` method. +[`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) 파이프라인에서, +불규칙 데이터 세트를 구성하려면, `ragged_batch()` 메서드를 사용할 수 있습니다. ```python train_ds = train_ds.ragged_batch(BATCH_SIZE, drop_remainder=True) eval_ds = eval_ds.ragged_batch(BATCH_SIZE, drop_remainder=True) ``` -Let's make sure our dataset is following the format KerasCV expects. By using the `visualize_dataset()` function, you can visually verify that your data is in the format that KerasCV expects. If the bounding boxes are not visible or are visible in the wrong locations that is a sign that your data is mis-formatted. +데이터 세트가 KerasCV에서 기대하는 형식을 따르고 있는지 확인해 보겠습니다. +`visualize_dataset()` 함수를 사용하면, +데이터가 KerasCV에서 기대하는 형식인지 시각적으로 확인할 수 있습니다. +경계 상자가 보이지 않거나 잘못된 위치에 보이는 경우, +데이터 형식이 잘못되었다는 신호입니다. ```python visualize_dataset( @@ -425,7 +495,7 @@ visualize_dataset( ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_28_0.png) -And for the eval set: +평가 세트의 경우: ```python visualize_dataset( @@ -434,21 +504,27 @@ visualize_dataset( value_range=(0, 255), rows=2, cols=2, - # If you are not running your experiment on a local machine, you can also - # make `visualize_dataset()` dump the plot to a file using `path`: + # 로컬 머신에서 실험을 실행하지 않는 경우, + # `path`를 사용하여 `visualize_dataset()`가 플롯을 파일에 덤프하도록 할 수도 있습니다. # path="eval.png" ) ``` ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_30_0.png) -Looks like everything is structured as expected. Now we can move on to constructing our data augmentation pipeline. +모든 것이 예상대로 구조화된 것 같습니다. +이제 데이터 보강 파이프라인을 구축할 수 있습니다. -## Data augmentation +## 데이터 보강 {#data-augmentation} -One of the most challenging tasks when constructing object detection pipelines is data augmentation. Image augmentation techniques must be aware of the underlying bounding boxes, and must update them accordingly. +객체 감지 파이프라인을 구축할 때 가장 어려운 작업 중 하나는 데이터 보강입니다. +이미지 보강 기술은 기본 바운딩 박스를 인식하고, 이에 따라 업데이트해야 합니다. -Luckily, KerasCV natively supports bounding box augmentation with its extensive library of [data augmentation layers]({{< relref "/docs/api/keras_cv/layers/preprocessing" >}}). The code below loads the Pascal VOC dataset, and performs on-the-fly, bounding-box-friendly data augmentation inside a [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) pipeline. +다행히도, KerasCV는 광범위한 [데이터 보강 레이어]({{< relref "/docs/api/keras_cv/layers/preprocessing" >}}) 라이브러리를 통해, +바운딩 박스 보강을 기본적으로 지원합니다. +아래 코드는 Pascal VOC 데이터 세트를 로드하고, +[`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) 파이프라인 내에서, +즉석에서 바운딩 박스 친화적인 데이터 보강을 수행합니다. ```python augmenters = [ @@ -478,7 +554,10 @@ visualize_dataset( ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_32_0.png) -Great! We now have a bounding-box-friendly data augmentation pipeline. Let's format our evaluation dataset to match. Instead of using `JitteredResize`, let's use the deterministic `keras_cv.layers.Resizing()` layer. +좋습니다! 이제 바운딩 박스 친화적인 데이터 보강 파이프라인이 있습니다. +평가 데이터 세트를 일치하도록 포맷해 보겠습니다. +`JitteredResize`를 사용하는 대신, +결정론적(deterministic) `keras_cv.layers.Resizing()` 레이어를 사용해 보겠습니다. ```python inference_resizing = keras_cv.layers.Resizing( @@ -487,7 +566,9 @@ inference_resizing = keras_cv.layers.Resizing( eval_ds = eval_ds.map(inference_resizing, num_parallel_calls=tf_data.AUTOTUNE) ``` -Due to the fact that the resize operation differs between the train dataset, which uses `JitteredResize()` to resize images, and the inference dataset, which uses `layers.Resizing(pad_to_aspect_ratio=True)`, it is good practice to visualize both datasets: +`JitteredResize()`를 사용하여 이미지 크기를 조정하는 트레이닝 데이터 세트와, +`layers.Resizing(pad_to_aspect_ratio=True)`를 사용하는 추론 데이터 세트 간의, +크기 조정 작업이 다르기 때문에 두 데이터 세트를 모두 시각화하는 것이 좋습니다. ```python visualize_dataset( @@ -497,7 +578,9 @@ visualize_dataset( ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_36_0.png) -Finally, let's unpackage our inputs from the preprocessing dictionary, and prepare to feed the inputs into our model. In order to be TPU compatible, bounding box Tensors need to be `Dense` instead of `Ragged`. +마지막으로, 전처리 딕셔너리로부터 입력을 언팩하고, +입력을 모델에 공급할 준비를 합시다. +TPU와 호환되기 위해, 바운딩 박스 텐서는 `Ragged` 대신 `Dense`여야 합니다. ```python def dict_to_tuple(inputs): @@ -513,29 +596,36 @@ train_ds = train_ds.prefetch(tf_data.AUTOTUNE) eval_ds = eval_ds.prefetch(tf_data.AUTOTUNE) ``` -### Optimizer +### 옵티마이저 {#optimizer} -In this guide, we use a standard SGD optimizer and rely on the [`keras.callbacks.ReduceLROnPlateau`]({{< relref "/docs/api/callbacks/reduce_lr_on_plateau#reducelronplateau-class" >}}) callback to reduce the learning rate. +이 가이드에서는, 표준 SGD 옵티마이저를 사용하고, +[`keras.callbacks.ReduceLROnPlateau`]({{< relref "/docs/api/callbacks/reduce_lr_on_plateau#reducelronplateau-class" >}}) 콜백을 사용하여 학습률을 줄입니다. -You will always want to include a `global_clipnorm` when training object detection models. This is to remedy exploding gradient problems that frequently occur when training object detection models. +객체 감지 모델을 트레이닝할 때는 항상 `global_clipnorm`을 포함해야 합니다. +이는 객체 감지 모델을 트레이닝할 때 자주 발생하는 폭발하는 그래디언트 문제를 해결하기 위한 것입니다. ```python base_lr = 0.005 -# including a global_clipnorm is extremely important in object detection tasks +# global_clipnorm을 포함하는 것은 객체 감지 작업에서 매우 중요합니다. optimizer = keras.optimizers.SGD( learning_rate=base_lr, momentum=0.9, global_clipnorm=10.0 ) ``` -To achieve the best results on your dataset, you'll likely want to hand craft a `PiecewiseConstantDecay` learning rate schedule. While `PiecewiseConstantDecay` schedules tend to perform better, they don't translate between problems. +데이터 세트에서 최상의 결과를 얻으려면, +`PiecewiseConstantDecay` 학습률 스케쥴을 직접 만들어야 할 것입니다. +`PiecewiseConstantDecay` 스케쥴은 더 나은 성능을 보이는 경향이 있지만, 문제 간에 변환되지 않습니다. -### Loss functions +### 손실 함수 {#loss-functions} -You may not be familiar with the `"ciou"` loss. While not common in other models, this loss is sometimes used in the object detection world. +`"ciou"` 손실에 익숙하지 않을 수도 있습니다. +다른 모델에서는 흔하지 않지만, 이 손실은 때때로 객체 감지 세계에서 사용됩니다. -In short, ["Complete IoU"](https://arxiv.org/abs/1911.08287) is a flavour of the Intersection over Union loss and is used due to its convergence properties. +간단히 말해서, ["Complete IoU"](https://arxiv.org/abs/1911.08287)는, +Intersection over Union 손실의 한 종류이며, 수렴 속성 때문에 사용됩니다. -In KerasCV, you can use this loss simply by passing the string `"ciou"` to `compile()`. We also use standard binary crossentropy loss for the class head. +KerasCV에서, 이 손실은 `"ciou"` 문자열을 `compile()`에 전달하기만 하면 사용할 수 있습니다. +또한 클래스 헤드에 표준 이진 교차 엔트로피 손실을 사용합니다. ```python pretrained_model.compile( @@ -544,9 +634,15 @@ pretrained_model.compile( ) ``` -### Metric evaluation +### 메트릭 평가 {#metric-evaluation} -The most popular object detection metrics are COCO metrics, which were published alongside the MSCOCO dataset. KerasCV provides an easy-to-use suite of COCO metrics under the `keras_cv.callbacks.PyCOCOCallback` symbol. Note that we use a Keras callback instead of a Keras metric to compute COCO metrics. This is because computing COCO metrics requires storing all of a model's predictions for the entire evaluation dataset in memory at once, which is impractical to do during training time. +가장 인기 있는 객체 감지 메트릭은 MSCOCO 데이터 세트와 함께 게시된 COCO 메트릭입니다. +KerasCV는 `keras_cv.callbacks.PyCOCOCallback` 심볼 아래에 사용하기 쉬운 +COCO 메트릭 모음을 제공합니다. +COCO 메트릭을 계산하기 위해 Keras 메트릭 대신 Keras 콜백을 사용한다는 점에 유의하세요. +COCO 메트릭을 계산하려면, +전체 평가 데이터 세트에 대한 모델의 모든 예측을 한 번에 메모리에 저장해야 하기 때문이며, +이는 트레이닝 시에는 실행하기 어렵습니다. ```python coco_metrics_callback = keras_cv.callbacks.PyCOCOCallback( @@ -554,35 +650,41 @@ coco_metrics_callback = keras_cv.callbacks.PyCOCOCallback( ) ``` -Our data pipeline is now complete! We can now move on to model creation and training. +이제 데이터 파이프라인이 완료되었습니다! +이제 모델 생성 및 트레이닝으로 넘어갈 수 있습니다. -## Model creation +## 모델 생성 {#model-creation} -Next, let's use the KerasCV API to construct an untrained YOLOV8Detector model. In this tutorial we use a pretrained ResNet50 backbone from the imagenet dataset. +다음으로, KerasCV API를 사용하여 트레이닝되지 않은 YOLOV8Detector 모델을 구성해 보겠습니다. +이 튜토리얼에서는 imagenet 데이터세트에서 사전 트레이닝된 ResNet50 백본을 사용합니다. -KerasCV makes it easy to construct a `YOLOV8Detector` with any of the KerasCV backbones. Simply use one of the presets for the architecture you'd like! +KerasCV를 사용하면 모든 KerasCV 백본으로 `YOLOV8Detector`를 쉽게 구성할 수 있습니다. +원하는 아키텍처에 대한 사전 설정 중 하나를 사용하기만 하면 됩니다! -For example: +예를 들어: ```python model = keras_cv.models.YOLOV8Detector.from_preset( "resnet50_imagenet", - # For more info on supported bounding box formats, visit + # 지원되는 바운딩 박스 형식에 대한 자세한 내용은 다음을 방문하세요. # https://keras.io/api/keras_cv/bounding_box/ bounding_box_format="xywh", num_classes=20, ) ``` -That is all it takes to construct a KerasCV YOLOv8. The YOLOv8 accepts tuples of dense image Tensors and bounding box dictionaries to `fit()` and `train_on_batch()` +이것이 KerasCV YOLOv8을 구성하는 데 필요한 전부입니다. +YOLOv8은 `fit()` 및 `train_on_batch()`에 대한 +dense 이미지 텐서와 바운딩 박스 사전의 튜플을 허용합니다. -This matches what we have constructed in our input pipeline above. +이것은 위의 입력 파이프라인에서 구성한 것과 일치합니다. -## Training our model +## 모델 트레이닝 {#training-our-model} -All that is left to do is train our model. KerasCV object detection models follow the standard Keras workflow, leveraging `compile()` and `fit()`. +남은 일은 모델을 트레이닝하는 것입니다. +KerasCV 객체 감지 모델은 표준 Keras 워크플로를 따르며, `compile()` 및 `fit()`를 활용합니다. -Let's compile our model: +모델을 컴파일해 보겠습니다. ```python model.compile( @@ -592,12 +694,13 @@ model.compile( ) ``` -If you want to fully train the model, remove `.take(20)` from all dataset references (below and in the initialization of the metrics callback). +모델을 완전히 트레이닝시키려면, +모든 데이터 세트 참조(아래 및 메트릭 콜백 초기화 부분)에서 `.take(20)`을 제거하세요. ```python model.fit( train_ds.take(20), - # Run for 10-35~ epochs to achieve good scores. + # 좋은 점수를 얻으려면 10-35~ 에포크를 실행하세요. epochs=1, callbacks=[coco_metrics_callback], ) @@ -635,11 +738,13 @@ DONE (t=0.07s). {{% /details %}} -## Inference and plotting results +## 추론 및 결과 플로팅 {#inference-and-plotting-results} -KerasCV makes object detection inference simple. `model.predict(images)` returns a tensor of bounding boxes. By default, `YOLOV8Detector.predict()` will perform a non max suppression operation for you. +KerasCV는 객체 감지 추론을 간단하게 만듭니다. +`model.predict(images)`는 경계 상자의 텐서를 반환합니다. +기본적으로, `YOLOV8Detector.predict()`는 non max 억제 연산을 수행합니다. -In this section, we will use a `keras_cv` provided preset: +이 섹션에서는, `keras_cv`에서 제공하는 사전 설정을 사용합니다. ```python model = keras_cv.models.YOLOV8Detector.from_preset( @@ -647,7 +752,7 @@ model = keras_cv.models.YOLOV8Detector.from_preset( ) ``` -Next, for convenience we construct a dataset with larger batches: +다음으로, 편의상 더 큰 배치를 포함하는 데이터 세트를 구성합니다. ```python visualization_ds = eval_ds.unbatch() @@ -655,7 +760,7 @@ visualization_ds = visualization_ds.ragged_batch(16) visualization_ds = visualization_ds.shuffle(8) ``` -Let's create a simple function to plot our inferences: +추론 결과를 그래프로 표시하는 간단한 함수를 만들어 보겠습니다. ```python def visualize_detections(model, dataset, bounding_box_format): @@ -676,7 +781,7 @@ def visualize_detections(model, dataset, bounding_box_format): ) ``` -You may need to configure your NonMaxSuppression operation to achieve visually appealing results. +시각적으로 매력적인 결과를 얻으려면, NonMaxSuppression 연산을 구성해야 할 수도 있습니다. ```python model.prediction_decoder = keras_cv.layers.NonMaxSuppression( @@ -699,7 +804,10 @@ visualize_detections(model, dataset=visualization_ds, bounding_box_format="xywh" ![png](/images/guides/keras_cv/object_detection_keras_cv/object_detection_keras_cv_60_1.png) -Awesome! One final helpful pattern to be aware of is to visualize detections in a [`keras.callbacks.Callback`]({{< relref "/docs/api/callbacks/base_callback#callback-class" >}}) to monitor training: +대단합니다! +마지막으로 알아두어야 할 유용한 패턴은 +[`keras.callbacks.Callback`]({{< relref "/docs/api/callbacks/base_callback#callback-class" >}})에서 +감지를 시각화하여 트레이닝을 모니터링하는 것입니다. ```python class VisualizeDetections(keras.callbacks.Callback): @@ -709,19 +817,23 @@ class VisualizeDetections(keras.callbacks.Callback): ) ``` -## Takeaways and next steps +## 주요 내용 및 다음 단계 {#takeaways-and-next-steps} -KerasCV makes it easy to construct state-of-the-art object detection pipelines. In this guide, we started off by writing a data loader using the KerasCV bounding box specification. Following this, we assembled a production grade data augmentation pipeline using KerasCV preprocessing layers in <50 lines of code. +KerasCV를 사용하면 최첨단 객체 감지 파이프라인을 쉽게 구축할 수 있습니다. +이 가이드에서는, KerasCV 바운딩 박스 사양을 사용하여, 데이터 로더를 작성하는 것으로 시작했습니다. +이어서 50줄 미만의 코드로 KerasCV 전처리 레이어를 사용하여, +프로덕션 등급 데이터 보강 파이프라인을 조립했습니다. -KerasCV object detection components can be used independently, but also have deep integration with each other. KerasCV makes authoring production grade bounding box augmentation, model training, visualization, and metric evaluation easy. +KerasCV 객체 감지 구성 요소는 독립적으로 사용할 수 있지만, 서로 긴밀하게 통합되어 있습니다. +KerasCV를 사용하면 프로덕션 등급 바운딩 박스 보강, 모델 트레이닝, 시각화 및 메트릭 평가를 쉽게 작성할 수 있습니다. -Some follow up exercises for the reader: +독자를 위한 몇 가지 후속 연습: -- add additional augmentation techniques to improve model performance -- tune the hyperparameters and data augmentation used to produce high quality results -- train an object detection model on your own dataset +- 모델 성능을 개선하기 위한 추가 보강 기술 추가 +- 고품질 결과를 생성하는 데 사용되는 하이퍼파라미터 및 데이터 보강 조정 +- 자체 데이터 세트에서 객체 감지 모델 트레이닝 -One last fun code snippet to showcase the power of KerasCV's API! +KerasCV API의 힘을 보여주는 마지막 재미있는 코드 조각! ```python stable_diffusion = keras_cv.models.StableDiffusionV2(512, 512) diff --git a/content/korean/docs/guides/keras_cv/segment_anything_in_keras_cv/_index.md b/content/korean/docs/guides/keras_cv/segment_anything_in_keras_cv/_index.md index 9073e592..1706bb20 100644 --- a/content/korean/docs/guides/keras_cv/segment_anything_in_keras_cv/_index.md +++ b/content/korean/docs/guides/keras_cv/segment_anything_in_keras_cv/_index.md @@ -1,6 +1,6 @@ --- -title: Segment Anything in KerasCV! -linkTitle: Segment Anything in KerasCV +title: KerasCV의 Segment Anything +linkTitle: KerasCV의 Segment Anything toc: true weight: 7 type: docs @@ -11,20 +11,27 @@ type: docs **{{< t f_author >}}** Tirth Patel, Ian Stenbit **{{< t f_date_created >}}** 2023/12/04 **{{< t f_last_modified >}}** 2023/12/19 -**{{< t f_description >}}** Segment anything using text, box, and points prompts in KerasCV. +**{{< t f_description >}}** KerasCV에서, 텍스트, 상자, 포인트 프롬프트를 사용한 Segment Anything. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_cv/segment_anything_in_keras_cv.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_cv/segment_anything_in_keras_cv.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Overview +## 개요 {#overview} -The Segment Anything Model (SAM) produces high quality object masks from input prompts such as points or boxes, and it can be used to generate masks for all objects in an image. It has been trained on a [dataset](https://segment-anything.com/dataset/index.html) of 11 million images and 1.1 billion masks, and has strong zero-shot performance on a variety of segmentation tasks. +Segment Anything Model(SAM)은 점이나 상자와 같은 입력 프롬프트에서 고품질 객체 마스크를 생성하며, +이미지의 모든 객체에 대한 마스크를 생성하는 데 사용할 수 있습니다. +1,100만 개의 이미지와 11억 개의 마스크로 구성된 +[데이터 세트](https://segment-anything.com/dataset/index.html)에 대해 트레이닝되었으며, +다양한 세그멘테이션 작업에서 강력한 제로샷 성능을 보입니다. -In this guide, we will show how to use KerasCV's implementation of the [Segment Anything Model](https://github.com/facebookresearch/segment-anything) and show how powerful TensorFlow's and JAX's performance boost is. +이 가이드에서는, KerasCV의 +[Segment Anything Model](https://github.com/facebookresearch/segment-anything) +구현을 사용하는 방법과, +TensorFlow와 JAX의 성능 향상이 얼마나 강력한지 보여드리겠습니다. -First, let's get all our dependencies and images for our demo. +먼저 데모를 위한 모든 종속성과 이미지를 가져오겠습니다. ```python !pip install -Uq keras-cv @@ -35,9 +42,9 @@ First, let's get all our dependencies and images for our demo. !wget -q https://raw.githubusercontent.com/facebookresearch/segment-anything/main/notebooks/images/truck.jpg ``` -## Choose your backend +## 백엔드 선택 {#choose-your-backend} -With Keras 3, you can choose to use your favorite backend! +Keras 3를 사용하면, 원하는 백엔드를 선택할 수 있습니다! ```python import os @@ -52,9 +59,9 @@ from keras import ops import keras_cv ``` -## Helper functions +## 헬퍼 함수 {#helper-functions} -Let's define some helper functions for visulazing the images, prompts, and the segmentation results. +이미지, 프롬프트, 세그멘테이션 결과를 시각화하기 위한, 몇 가지 헬퍼 함수를 정의해 보겠습니다. ```python def show_mask(mask, ax, random_color=False): @@ -100,7 +107,7 @@ def show_box(box, ax): def inference_resizing(image, pad=True): - # Compute Preprocess Shape + # 전처리 모양 계산 image = ops.cast(image, dtype="float32") old_h, old_w = image.shape[0], image.shape[1] scale = 1024 * 1.0 / max(old_h, old_w) @@ -108,10 +115,10 @@ def inference_resizing(image, pad=True): new_w = old_w * scale preprocess_shape = int(new_h + 0.5), int(new_w + 0.5) - # Resize the image + # 이미지 크기 조절 image = ops.image.resize(image[None, ...], preprocess_shape)[0] - # Pad the shorter side + # 짧은 쪽을 패딩합니다. if pad: pixel_mean = ops.array([123.675, 116.28, 103.53]) pixel_std = ops.array([58.395, 57.12, 57.375]) @@ -120,47 +127,79 @@ def inference_resizing(image, pad=True): pad_h = 1024 - h pad_w = 1024 - w image = ops.pad(image, [(0, pad_h), (0, pad_w), (0, 0)]) - # KerasCV now rescales the images and normalizes them. - # Just unnormalize such that when KerasCV normalizes them - # again, the padded values map to 0. + # KerasCV는 이제 이미지를 재조정(rescales)하고 정규화합니다. + # KerasCV가 다시 정규화(normalizes)할 때, + # 패딩된 값이 0으로 매핑되도록, 정규화를 해제(unnormalize)합니다. image = image * pixel_std + pixel_mean return image ``` -## Get the pretrained SAM model +## 사전 트레이닝된 SAM 모델 얻기 {#get-the-pretrained-sam-model} -We can initialize a trained SAM model using KerasCV's `from_preset` factory method. Here, we use the huge ViT backbone trained on the SA-1B dataset (`sam_huge_sa1b`) for high-quality segmentation masks. You can also use one of the `sam_large_sa1b` or `sam_base_sa1b` for better performance (at the cost of decreasing quality of segmentation masks). +KerasCV의 `from_preset` 팩토리 메서드를 사용하여, +트레이닝된 SAM 모델을 초기화할 수 있습니다. +여기서는 고품질 세그먼테이션 마스크를 위해, +SA-1B 데이터 세트(`sam_huge_sa1b`)에 대해 트레이닝된 거대한 ViT 백본을 사용합니다. +더 나은 성능을 위해, +`sam_large_sa1b` 또는 `sam_base_sa1b` 중 하나를 사용할 수도 있습니다. +(세그먼테이션 마스크의 품질이 떨어지는 대가로) ```python model = keras_cv.models.SegmentAnythingModel.from_preset("sam_huge_sa1b") ``` -## Understanding Prompts - -Segment Anything allows prompting an image using points, boxes, and masks: - -1. Point prompts are the most basic of all: the model tries to guess the object given a point on an image. The point can either be a foreground point (i.e. the desired segmentation mask contains the point in it) or a backround point (i.e. the point lies outside the desired mask). -2. Another way to prompt the model is using boxes. Given a bounding box, the model tries to segment the object contained in it. -3. Finally, the model can also be prompted using a mask itself. This is useful, for instance, to refine the borders of a previously predicted or known segmentation mask. - -What makes the model incredibly powerful is the ability to combine the prompts above. Point, box, and mask prompts can be combined in several different ways to achieve the best result. - -Let's see the semantics of passing these prompts to the Segment Anything model in KerasCV. Input to the SAM model is a dictionary with keys: - -1. `"images"`: A batch of images to segment. Must be of shape `(B, 1024, 1024, 3)`. -2. `"points"`: A batch of point prompts. Each point is an `(x, y)` coordinate originating from the top-left corner of the image. In other works, each point is of the form `(r, c)` where `r` and `c` are the row and column of the pixel in the image. Must be of shape `(B, N, 2)`. -3. `"labels"`: A batch of labels for the given points. `1` represents foreground points and `0` represents background points. Must be of shape `(B, N)`. -4. `"boxes"`: A batch of boxes. Note that the model only accepts one box per batch. Hence, the expected shape is `(B, 1, 2, 2)`. Each box is a collection of 2 points: the top left corner and the bottom right corner of the box. The points here follow the same semantics as the point prompts. Here the `1` in the second dimension represents the presence of box prompts. If the box prompts are missing, a placeholder input of shape `(B, 0, 2, 2)` must be passed. -5. `"masks"`: A batch of masks. Just like box prompts, only one mask prompt per image is allowed. The shape of the input mask must be `(B, 1, 256, 256, 1)` if they are present and `(B, 0, 256, 256, 1)` for missing mask prompt. - -Placeholder prompts are only required when calling the model directly (i.e. `model(...)`). When calling the `predict` method, missing prompts can be omitted from the input dictionary. - -## Point prompts - -First, let's segment an image using point prompts. We load the image and resize it to shape `(1024, 1024)`, the image size the pretrained SAM model expects. +## 프롬프트 이해하기 {#understanding-prompts} + +Segment Anything은 포인트, 상자, 마스크를 사용하여 이미지를 프롬프트할 수 있습니다. + +1. 포인트 프롬프트는 가장 기본적인 프롬프트입니다. + 모델은 이미지의 포인트가 주어졌을 때 객체를 추측하려고 합니다. + 포인트는 전경 포인트(즉, 원하는 세그멘테이션 마스크에 포인트가 포함됨)이거나, + 배경 포인트(즉, 포인트가 원하는 마스크 밖에 있음)일 수 있습니다. +2. 모델을 프롬프트하는 또다른 방법은 상자를 사용하는 것입니다. + 경계 상자가 주어졌을 때, 모델은 그 안에 포함된 객체를 세그멘테이션하려고 합니다. +3. 마지막으로, 마스크 자체를 사용하여 모델을 프롬프트할 수도 있습니다. + 예를 들어, 이는 이전에 예측되거나 알려진 세그멘테이션 마스크의 테두리를 정제하는 데 유용합니다. + +모델을 엄청나게 강력하게 만드는 것은, 위의 프롬프트를 결합할 수 있는 기능입니다. +포인트, 상자, 마스크 프롬프트는 여러 가지 다른 방법으로 결합하여, 최상의 결과를 얻을 수 있습니다. + +KerasCV에서 Segment Anything 모델에 이러한 프롬프트를 전달하는 시맨틱을 살펴보겠습니다. +SAM 모델의 입력은 키가 있는 딕셔너리입니다. + +1. `"images"`: 세그멘테이션할 이미지 배치입니다. + - `(B, 1024, 1024, 3)` 모양이어야 합니다. +2. `"points"`: 포인트 프롬프트 배치입니다. + - 각 포인트는 이미지의 왼쪽 상단 모서리에서 시작하는 `(x, y)` 좌표입니다. + - 다른 작업에서, 각 포인트는 `(r, c)` 형태이며, 여기서 `r`과 `c`는 이미지의 픽셀의 행과 열입니다. + - `(B, N, 2)` 모양이어야 합니다. +3. `"labels"`: 주어진 포인트에 대한 레이블 배치입니다. + - `1`은 전경 포인트를 나타내고, `0`은 배경 포인트를 나타냅니다. + - `(B, N)` 모양이어야 합니다. +4. `"boxes"`: 상자 배치입니다. + - 모델은 배치당 하나의 상자만 허용합니다. + - 따라서, 예상되는 모양은 `(B, 1, 2, 2)`입니다. + - 각 상자는 상자의 왼쪽 상단 모서리와 오른쪽 하단 모서리인 2개의 포인트의 모음입니다. + - 여기의 포인트는 포인트 프롬프트와 동일한 의미를 따릅니다. + - 여기서 2차원의 `1`은 상자 프롬프트의 존재를 나타냅니다. + - 상자 프롬프트가 없는 경우, `(B, 0, 2, 2)` 모양의 플레이스홀더 입력을 전달해야 합니다. +5. `"masks"`: 마스크 배치입니다. + - 상자 프롬프트와 마찬가지로, 이미지당 마스크 프롬프트는 하나만 허용됩니다. + - 입력 마스크의 모양은 있는 경우, `(B, 1, 256, 256, 1)`이고 + - 마스크 프롬프트가 없는 경우, `(B, 0, 256, 256, 1)`이어야 합니다. + +플레이스홀더 프롬프트는 모델을 직접 호출할 때만 필요합니다. (예: `model(...)`) +`predict` 메서드를 호출할 때, 누락된 프롬프트를 입력 딕셔너리에서 생략할 수 있습니다. + +## 포인트 프롬프트 {#point-prompts} + +먼저, 포인트 프롬프트를 사용하여 이미지를 세그멘테이션해 보겠습니다. +이미지를 로드하고 크기를 조정하여, +사전 트레이닝된 SAM 모델이 예상하는 이미지 크기인, +`(1024, 1024)` 모양으로 만듭니다. ```python -# Load our image +# 이미지를 로드합니다. image = np.array(keras.utils.load_img("truck.jpg")) image = inference_resizing(image) @@ -172,10 +211,11 @@ plt.show() ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_11_0.png) -Next, we will define the point on the object we want to segment. Let's try to segment the truck's window pane at coordinates `(284, 213)`. +다음으로, 세그멘테이션하고자 하는 객체의 포인트를 정의합니다. +트럭의 창문 유리창을 좌표 `(284, 213)`에서 세그멘테이션해 보겠습니다. ```python -# Define the input point prompt +# 입력 포인트 프롬프트 정의 input_point = np.array([[284, 213.5]]) input_label = np.array([1]) @@ -188,9 +228,13 @@ plt.show() ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_13_0.png) -Now let's call the `predict` method of our model to get the segmentation masks. +이제, 모델의 `predict` 메서드를 호출하여, 세그멘테이션 마스크를 구해 보겠습니다. -**Note**: We don't call the model directly (`model(...)`) since placeholder prompts are required to do so. Missing prompts are handled automatically by the predict method so we call it instead. Also, when no box prompts are present, the points and labels need to be padded with a zero point prompt and `-1` label prompt respectively. The cell below demonstrates how this works. +**참고**: 플레이스홀더 프롬프트가 필요하기 때문에, 모델을 직접 호출하지 않습니다. (`model(...)`) +누락된 프롬프트는 predict 메서드에서 자동으로 처리하므로, 대신 호출합니다. +또한, 상자 프롬프트가 없는 경우, +포인트와 레이블은 각각 ​​0 포인트 프롬프트와 `-1` 레이블 프롬프트로 패딩해야 합니다. +아래 셀은 이것이 어떻게 작동하는지 보여줍니다. ```python outputs = model.predict( @@ -214,15 +258,24 @@ outputs = model.predict( {{% /details %}} -`SegmentAnythingModel.predict` returns two outputs. First are logits (segmentation masks) of shape `(1, 4, 256, 256)` and the other are the IoU confidence scores (of shape `(1, 4)`) for each mask predicted. The pretrained SAM model predicts four masks: the first is the best mask the model could come up with for the given prompts, and the other 3 are the alternative masks which can be used in case the best prediction doesn't contain the desired object. The user can choose whichever mask they prefer. +`SegmentAnythingModel.predict`는 두 개의 출력을 반환합니다. + +- 첫 번째는 `(1, 4, 256, 256)` 모양의 로짓(세그멘테이션 마스크)이고, +- 다른 하나는 예측된 각 마스크에 대한 IoU 신뢰도 점수(IoU confidence scores, `(1, 4)` 모양)입니다. + +사전 트레이닝된 SAM 모델은 네 개의 마스크를 예측합니다. + +- 첫 번째는 모델이 주어진 프롬프트에 대해 생각해 낼 수 있는 최상의 마스크이고, +- 다른 세 개는 최상의 예측에 원하는 개체가 포함되지 않은 경우, 사용할 수 있는 대체 마스크입니다. + +사용자는 원하는 마스크를 선택할 수 있습니다. -Let's visualize the masks returned by the model! +모델에서 반환된 마스크를 시각화해 보겠습니다! ```python -# Resize the mask to our image shape i.e. (1024, 1024) +# 마스크 크기를 이미지 모양(1024, 1024)으로 조정합니다. mask = inference_resizing(outputs["masks"][0][0][..., None], pad=False)[..., 0] -# Convert the logits to a numpy array -# and convert the logits to a boolean mask +# 로짓을 numpy 배열로 변환하고, 로짓을 boolean 마스크로 변환합니다. mask = ops.convert_to_numpy(mask) > 0.0 iou_score = ops.convert_to_numpy(outputs["iou_pred"][0][0]) @@ -237,9 +290,11 @@ plt.show() ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_17_0.png) -As expected, the model returns a segmentation mask for the truck's window pane. But, our point prompt can also mean a range of other things. For example, another possible mask that contains our point is just the right side of the window pane or the whole truck. +예상대로, 모델은 트럭의 창 유리창에 대한 세그멘테이션 마스크를 반환합니다. +하지만, 우리의 포인트 프롬프트는 다른 여러 가지를 의미할 수도 있습니다. +예를 들어, 우리의 포인트를 포함하는 또다른 가능한 마스크는 창 유리창의 오른쪽 또는 전체 트럭입니다. -Let's also visualize the other masks the model has predicted. +모델이 예측한 다른 마스크도 시각화해 보겠습니다. ```python fig, ax = plt.subplots(1, 3, figsize=(20, 60)) @@ -258,14 +313,18 @@ plt.show() ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_20_0.png) -Nice! SAM was able to capture the ambiguity of our point prompt and also returned other possible segmentation masks. +훌륭합니다! +SAM은 우리의 포인트 프롬프트의 모호성을 포착할 수 있었고, +다른 가능한 세그먼테이션 마스크도 반환했습니다. -## Box Prompts +## 상자 프롬프트 {#box-prompts} -Now, let's see how we can prompt the model using boxes. The box is specified using two points, the top-left corner and the bottom-right corner of the bounding box in xyxy format. Let's prompt the model using a bounding box around the left front tyre of the truck. +이제 상자를 사용하여, 모델을 프롬프트하는 방법을 살펴보겠습니다. +상자는 두 점, 즉 xyxy 형식의 경계 상자의 왼쪽 상단 모서리와 오른쪽 하단 모서리를 사용하여 지정합니다. +트럭의 왼쪽 앞 타이어 주위에 경계 상자를 사용하여, 모델을 프롬프트해 보겠습니다. ```python -# Let's specify the box +# 상자를 지정해 봅시다. input_box = np.array([[240, 340], [400, 500]]) outputs = model.predict( @@ -292,16 +351,16 @@ plt.show() ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_23_1.png) -Boom! The model perfectly segments out the left front tyre in our bounding box. +붐! 이 모델은 경계 상자에서 왼쪽 앞 타이어를 완벽하게 세그멘테이션합니다. -## Combining prompts +## 프롬프트 결합 {#combining-prompts} -To get the true potential of the model out, let's combine box and point prompts and see what the model does. +모델의 진정한 잠재력을 끌어내기 위해, 상자와 포인트의 프롬프트를 결합하고, 모델의 기능을 살펴보겠습니다. ```python -# Let's specify the box +# 상자를 지정해 봅시다. input_box = np.array([[240, 340], [400, 500]]) -# Let's specify the point and mark it background +# 포인트를 지정하고, 배경으로 표시해 보겠습니다. input_point = np.array([[325, 425]]) input_label = np.array([0]) @@ -335,21 +394,24 @@ plt.show() ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_25_1.png) -Voila! The model understood that the object we wanted to exclude from our mask was the rim of the tyre. +짠! 모델은 우리가 마스크에서 제외하려는 대상이 타이어의 림이라는 것을 이해했습니다. -## Text prompts +## 텍스트 프롬프트 {#text-prompts} -Finally, let's see how text prompts can be used along with KerasCV's `SegmentAnythingModel`. +마지막으로, KerasCV의 `SegmentAnythingModel`과 함께 텍스트 프롬프트를 사용하는 방법을 살펴보겠습니다. -For this demo, we will use the [offical Grounding DINO model](https://github.com/IDEA-Research/GroundingDINO). Grounding DINO is a model that takes as input a `(image, text)` pair and generates a bounding box around the object in the `image` described by the `text`. You can refer to the [paper](https://arxiv.org/abs/2303.05499) for more details on the implementation of the model. +이 데모에서는 [공식 Grounding DINO 모델](https://github.com/IDEA-Research/GroundingDINO)을 사용합니다. +Grounding DINO는 `(image, text)` 쌍을 입력으로 받고, +`text`로 설명된 `image`의 객체 주위에 경계 상자를 생성하는 모델입니다. +모델 구현에 대한 자세한 내용은 [논문](https://arxiv.org/abs/2303.05499)을 참조하세요. -For this part of the demo, we will need to install the `groundingdino` package from source: +이 데모의 이 부분에서는, 소스에서 `groundingdino` 패키지를 설치해야 합니다. ```shell pip install -U git+https://github.com/IDEA-Research/GroundingDINO.git ``` -Then, we can install the pretrained model's weights and config: +그런 다음, 사전 트레이닝된 모델의 가중치와 구성을 설치할 수 있습니다. ```python !wget -q https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth @@ -376,7 +438,7 @@ final text_encoder_type: bert-base-uncased {{% /details %}} -Let's load an image of a dog for this part! +이 부분에서는 개 이미지를 불러오겠습니다! ```python filepath = keras.utils.get_file( @@ -401,12 +463,16 @@ Clipping input data to the valid range for imshow with RGB data ([0..1] for floa ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_30_1.png) -We first predict the bounding box of the object we want to segment using the Grounding DINO model. Then, we prompt the SAM model using the bounding box to get the segmentation mask. +먼저 Grounding DINO 모델을 사용하여, +세그멘테이션하려는 객체의 바운딩 박스를 예측합니다. +그런 다음, 바운딩 박스를 사용하여 SAM 모델을 프롬프트하여, +세그멘테이션 마스크를 얻습니다. -Let's try to segment out the harness of the dog. Change the image and text below to segment whatever you want using text from your image! +개의 하네스를 세그멘테이션해 보겠습니다. +아래의 이미지와 텍스트를 변경하여, 이미지의 텍스트를 사용하여 원하는 대로 세그멘테이션하세요! ```python -# Let's predict the bounding box for the harness of the dog +# 개의 하네스에 대한 경계 상자를 예측해 봅시다. boxes = grounding_dino.predict_with_caption(image.astype(np.uint8), "harness") boxes = np.array(boxes[0].xyxy) @@ -434,9 +500,12 @@ outputs = model.predict( {{% /details %}} -And that's it! We got a segmentation mask for our text prompt using the combination of Gounding DINO + SAM! This is a very powerful technique to combine different models to expand the applications! +그리고 그게 전부입니다! +Gounding DINO + SAM의 조합을 사용하여, +텍스트 프롬프트에 대한 세그멘테이션 마스크를 얻었습니다! +이것은 다양한 모델을 결합하여 응용 프로그램을 확장하는 매우 강력한 기술입니다! -Let's visualize the results. +결과를 시각화해 보겠습니다. ```python plt.figure(figsize=(10, 10)) @@ -462,19 +531,20 @@ Clipping input data to the valid range for imshow with RGB data ([0..1] for floa ![png](/images/guides/keras_cv/segment_anything_in_keras_cv/segment_anything_in_keras_cv_34_1.png) -## Optimizing SAM +## SAM 최적화 {#optimizing-sam} -You can use `mixed_float16` or `bfloat16` dtype policies to gain huge speedups and memory optimizations at releatively low precision loss. +`mixed_float16` 또는 `bfloat16` dtype 정책을 사용하면, +상대적으로 낮은 정밀도 손실로 엄청난 속도 향상과 메모리 최적화를 얻을 수 있습니다. ```python -# Load our image +# 이미지를 로드합니다. image = np.array(keras.utils.load_img("truck.jpg")) image = inference_resizing(image) -# Specify the prompt +# 프롬프트를 지정합니다. input_box = np.array([[240, 340], [400, 500]]) -# Let's first see how fast the model is with float32 dtype +# 먼저 float32 dtype을 사용할 때, 모델이 얼마나 빠른지 살펴보겠습니다. time_taken = timeit.repeat( 'model.predict({"images": image[np.newaxis, ...], "boxes": input_box[np.newaxis, np.newaxis, ...]}, verbose=False)', repeat=3, @@ -483,7 +553,7 @@ time_taken = timeit.repeat( ) print(f"Time taken with float32 dtype: {min(time_taken) / 3:.10f}s") -# Set the dtype policy in Keras +# Keras에서 dtype 정책 설정 keras.mixed_precision.set_global_policy("mixed_float16") model = keras_cv.models.SegmentAnythingModel.from_preset("sam_huge_sa1b") @@ -506,14 +576,18 @@ Time taken with float16 dtype: 0.1586400040s {{% /details %}} -Here's a comparison of KerasCV's implementation with the original PyTorch implementation! +KerasCV 구현과 원본 PyTorch 구현을 비교한 것은 다음과 같습니다! ![benchmark](/images/guides/keras_cv/segment_anything_in_keras_cv/benchmark.png) -The script used to generate the benchmarks is present [here](https://github.com/tirthasheshpatel/segment_anything_keras/blob/main/Segment_Anything_Benchmarks.ipynb). +벤치마크를 생성하는데 사용된 스크립트는 [여기](https://github.com/tirthasheshpatel/segment_anything_keras/blob/main/Segment_Anything_Benchmarks.ipynb)에 있습니다. -## Conclusion +## 결론 {#conclusion} -KerasCV's `SegmentAnythingModel` supports a variety of applications and, with the help of Keras 3, enables running the model on TensorFlow, JAX, and PyTorch! With the help of XLA in JAX and TensorFlow, the model runs several times faster than the original implementation. Moreover, using Keras's mixed precision support helps optimize memory use and computation time with just one line of code! +KerasCV의 `SegmentAnythingModel`은 다양한 애플리케이션을 지원하고, +Keras 3의 도움으로 TensorFlow, JAX, PyTorch에서 모델을 실행할 수 있습니다! +JAX와 TensorFlow의 XLA의 도움으로, 모델은 원래 구현보다 몇 배 더 빠르게 실행됩니다. +게다가 Keras의 혼합 정밀도 지원을 사용하면, +단 한 줄의 코드로 메모리 사용과 계산 시간을 최적화하는 데 도움이 됩니다! -For more advanced uses, check out the [Automatic Mask Generator demo](https://github.com/tirthasheshpatel/segment_anything_keras/blob/main/Segment_Anything_Automatic_Mask_Generator_Demo.ipynb). +더 고급 사용 사례는 [자동 마스크 생성기 데모](https://github.com/tirthasheshpatel/segment_anything_keras/blob/main/Segment_Anything_Automatic_Mask_Generator_Demo.ipynb)를 확인하세요. diff --git a/content/korean/docs/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/_index.md b/content/korean/docs/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/_index.md index e967f08a..d183ec5b 100644 --- a/content/korean/docs/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/_index.md +++ b/content/korean/docs/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/_index.md @@ -1,6 +1,6 @@ --- -title: Semantic Segmentation with KerasCV -linkTitle: Semantic Segmentation with KerasCV +title: KerasCV로 시맨틱 세그멘테이션 +linkTitle: KerasCV로 시맨틱 세그멘테이션 toc: true weight: 6 type: docs @@ -11,7 +11,7 @@ type: docs **{{< t f_author >}}** [Divyashree Sreepathihalli](https://github.com/divyashreepathihalli), [Ian Stenbit](https://github.com/ianstenbit) **{{< t f_date_created >}}** 2023/08/22 **{{< t f_last_modified >}}** 2023/08/24 -**{{< t f_description >}}** Train and use DeepLabv3+ segmentation model with KerasCV. +**{{< t f_description >}}** KerasCV를 사용하여 DeepLabv3+ 세그멘테이션 모델을 트레이닝하고 사용합니다. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_cv/semantic_segmentation_deeplab_v3_plus.ipynb" title="Colab" tag="Colab" tagType="warning">}} @@ -20,34 +20,43 @@ type: docs ![png](/images/keras-hub/getting_started_guide/prof_keras_intermediate.png) -## Background +## 배경 {#background} -Semantic segmentation is a type of computer vision task that involves assigning a class label such as person, bike, or background to each individual pixel of an image, effectively dividing the image into regions that correspond to different fobject classes or categories. +시맨틱 세그멘테이션은 사람, 자전거 또는 배경과 같은 클래스 레이블을 이미지의 각 픽셀에 할당하여, +이미지를 서로 다른 객체 클래스나 범주에 해당하는 영역으로, +효과적으로 분할하는 일종의 컴퓨터 비전 작업입니다. ![png](/images/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/1*z6ch-2BliDGLIHpOPFY_Sw.png) -KerasCV offers the DeepLabv3+ model developed by Google for semantic segmentation. This guide demonstrates how to finetune and use DeepLabv3+ model for image semantic segmentaion with KerasCV. Its architecture that combines atrous convolutions, contextual information aggregation, and powerful backbones to achieve accurate and detailed semantic segmentation. The DeepLabv3+ model has been shown to achieve state-of-the-art results on a variety of image segmentation benchmarks. +KerasCV는 시맨틱 세그멘테이션을 위해 Google에서 개발한 DeepLabv3+ 모델을 제공합니다. +이 가이드는 KerasCV를 사용하여 이미지 시맨틱 세그멘테이션을 위해, +DeepLabv3+ 모델을 미세 조정하고 사용하는 방법을 보여줍니다. +아트러스(atrous) 컨볼루션, 문맥 정보 집계(contextual information aggregation) 및 +강력한 백본을 결합하여 정확하고 자세한 시맨틱 세그멘테이션을 달성하는 아키텍처입니다. +DeepLabv3+ 모델은 다양한 이미지 세그멘테이션 벤치마크에서 최첨단 결과를 달성하는 것으로 나타났습니다. -### References +### 참조 {#references} -[Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation](https://arxiv.org/abs/1802.02611) -[Rethinking Atrous Convolution for Semantic Image Segmentation](https://arxiv.org/abs/1706.05587) +- [시맨틱 이미지 세그멘테이션을 위한, Atrous Separable 컨볼루션을 갖춘 인코더-디코더](https://arxiv.org/abs/1802.02611) +- [시맨틱 이미지 세그멘테이션을 위한, Atrous 컨볼루션 재고](https://arxiv.org/abs/1706.05587) -## Setup and Imports +## 셋업 및 import {#setup-and-imports} -Let's install the dependencies and import the necessary modules. +종속성을 설치하고 필요한 모듈을 import 해 보겠습니다. -To run this tutorial, you will need to install the following packages: +이 튜토리얼을 실행하려면, 다음 패키지를 설치해야 합니다. - `keras-cv` - `keras-core` ```python !pip install -q --upgrade keras-cv -!pip install -q --upgrade keras # Upgrade to Keras 3. +!pip install -q --upgrade keras # Keras 3로 업그레이드. ``` -After installing `keras-core` and `keras-cv`, set the backend for `keras-core`. This guide can be run with any backend (Tensorflow, JAX, PyTorch). +`keras-core`와 `keras-cv`를 설치한 후, +`keras-core`에 대한 백엔드를 설정합니다. +이 가이드는 모든 백엔드(Tensorflow, JAX, PyTorch)에서 실행할 수 있습니다. ```python import os @@ -65,11 +74,14 @@ import numpy as np from keras_cv.datasets.pascal_voc.segmentation import load as load_voc ``` -## Perform semantic segmentation with a pretrained DeepLabv3+ model +## 사전 트레이닝된 DeepLabv3+ 모델을 사용하여 시맨틱 세그멘테이션 수행 {#perform-semantic-segmentation-with-a-pretrained-deeplabv3-model} -The highest level API in the KerasCV semantic segmentation API is the `keras_cv.models` API. This API includes fully pretrained semantic segmentation models, such as [`keras_cv.models.DeepLabV3Plus`]({{< relref "/docs/api/keras_cv/models/tasks/deeplab_v3_segmentation#deeplabv3plus-class" >}}). +KerasCV 시맨틱 세그멘테이션 API에서 가장 높은 레벨의 API는 `keras_cv.models` API입니다. +이 API에는, +[`keras_cv.models.DeepLabV3Plus`]({{< relref "/docs/api/keras_cv/models/tasks/deeplab_v3_segmentation#deeplabv3plus-class" >}})와 같은, +완전히 사전 트레이닝된된 시맨틱 세그멘테이션 모델이 포함됩니다. -Let's get started by constructing a DeepLabv3+ pretrained on the pascalvoc dataset. +pascalvoc 데이터 세트에 대해 사전 트레이닝된 DeepLabv3+를 구성하여 시작해 보겠습니다. ```python model = keras_cv.models.DeepLabV3Plus.from_preset( @@ -79,7 +91,7 @@ model = keras_cv.models.DeepLabV3Plus.from_preset( ) ``` -Let us visualize the results of this pretrained model +이 사전 트레이닝된 모델의 결과를 시각화해 보겠습니다. ```python filepath = keras.utils.get_file(origin="https://i.imgur.com/gCNcJJI.jpg") @@ -103,24 +115,31 @@ keras_cv.visualization.plot_segmentation_mask_gallery( ![png](/images/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/semantic_segmentation_deeplab_v3_plus_9_0.png) -## Train a custom semantic segmentation model +## 커스텀 시맨틱 세그멘테이션 모델 트레이닝 {#train-a-custom-semantic-segmentation-model} -In this guide, we'll assemble a full training pipeline for a KerasCV DeepLabV3 semantic segmentation model. This includes data loading, augmentation, training, metric evaluation, and inference! +이 가이드에서는, KerasCV DeepLabV3 시맨틱 세그멘테이션 모델을 위한, +전체 트레이닝 파이프라인을 조립합니다. +여기에는 데이터 로딩, 보강, 트레이닝, 메트릭 평가 및 추론이 포함됩니다! -## Download the data +## 데이터 다운로드 {#download-the-data} -We download [Pascal VOC dataset](https://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/semantic_contours/benchmark.tgz) with KerasCV datasets and split them into train dataset `train_ds` and `eval_ds`. +KerasCV 데이터세트와 함께 [Pascal VOC 데이터세트](https://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/semantic_contours/benchmark.tgz)를 다운로드하고, +이를 트레이닝 데이터세트 `train_ds`와 `eval_ds`로 분할합니다. ```python train_ds = load_voc(split="sbd_train") eval_ds = load_voc(split="sbd_eval") ``` -## Preprocess the data +## 데이터 전처리 {#preprocess-the-data} -The `preprocess_tfds_inputs` utility function preprocesses the inputs to a dictionary of `images` and `segmentation_masks`. The images and segmentation masks are resized to 512x512. The resulting dataset is then batched into groups of 4 image and segmentation mask pairs. +`preprocess_tfds_inputs` 유틸리티 함수는, +`images`와 `segmentation_masks` 딕셔너리에 대한 입력을 전처리합니다. +이미지와 세그먼테이션 마스크는 512x512로 크기가 조정됩니다. +그런 다음, 결과 데이터 세트는 4개의 이미지와 세그먼테이션 마스크 쌍으로 구성된 그룹으로 배치됩니다. -A batch of this preprocessed input training data can be visualized using the `keras_cv.visualization.plot_segmentation_mask_gallery` function. This function takes a batch of images and segmentation masks as input and displays them in a grid. +이 전처리된 입력 트레이닝 데이터의 배치는 `keras_cv.visualization.plot_segmentation_mask_gallery` 함수를 사용하여 시각화할 수 있습니다. +이 함수는 이미지와 세그먼테이션 마스크의 배치를 입력으로 사용하여 그리드에 표시합니다. ```python def preprocess_tfds_inputs(inputs): @@ -141,7 +160,7 @@ batch = train_ds.take(1).get_single_element() keras_cv.visualization.plot_segmentation_mask_gallery( batch["images"], value_range=(0, 255), - num_classes=21, # The number of classes for the oxford iiit pet dataset. The VOC dataset also includes 1 class for the background. + num_classes=21, # Oxford iiit pet 데이터세트의 클래스 수. VOC 데이터세트에는 배경에 대한 클래스 1개도 포함됩니다. y_true=batch["segmentation_masks"], scale=3, rows=2, @@ -151,15 +170,18 @@ keras_cv.visualization.plot_segmentation_mask_gallery( ![png](/images/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/semantic_segmentation_deeplab_v3_plus_14_0.png) -The preprocessing is applied to the evaluation dataset `eval_ds`. +전처리는 평가 데이터 세트 `eval_ds`에 적용됩니다. ```python eval_ds = preprocess_tfds_inputs(eval_ds) ``` -## Data Augmentation +## 데이터 보강 {#data-augmentation} -KerasCV provides a variety of image augmentation options. In this example, we will use the `RandomFlip` augmentation to augment the training dataset. The `RandomFlip` augmentation randomly flips the images in the training dataset horizontally or vertically. This can help to improve the model's robustness to changes in the orientation of the objects in the images. +KerasCV는 다양한 이미지 보강 옵션을 제공합니다. +이 예에서는 `RandomFlip` 보강을 사용하여, 트레이닝 데이터 세트를 보강합니다. +`RandomFlip` 보강은 트레이닝 데이터 세트의 이미지를 수평 또는 수직으로 랜덤으로 뒤집습니다. +이는 이미지의 객체 방향 변화에 대한 모델의 견고성을 개선하는 데 도움이 될 수 있습니다. ```python train_ds = train_ds.map(keras_cv.layers.RandomFlip()) @@ -178,11 +200,20 @@ keras_cv.visualization.plot_segmentation_mask_gallery( ![png](/images/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/semantic_segmentation_deeplab_v3_plus_18_0.png) -## Model Configuration +## 모델 구성 {#model-configuration} -Please feel free to modify the configurations for model training and note how the training results changes. This is an great exercise to get a better understanding of the training pipeline. +모델 트레이닝을 위한 구성을 자유롭게 수정하고, 트레이닝 결과가 어떻게 변경되는지 확인하세요. +이것은 트레이닝 파이프라인을 더 잘 이해하는 데 좋은 연습입니다. -The learning rate schedule is used by the optimizer to calculate the learning rate for each epoch. The optimizer then uses the learning rate to update the weights of the model. In this case, the learning rate schedule uses a cosine decay function. A cosine decay function starts high and then decreases over time, eventually reaching zero. The cardinality of the VOC dataset is 2124 with a batch size of 4. The dataset cardinality is important for learning rate decay because it determines how many steps the model will train for. The initial learning rate is proportional to 0.007 and the decay steps are 2124. This means that the learning rate will start at `INITIAL_LR` and then decrease to zero over 2124 steps. +학습률 스케쥴은 옵티마이저에서 각 에포크에 대한 학습률을 계산하는 데 사용됩니다. +그런 다음, 옵티마이저에서 학습률을 사용하여 모델의 가중치를 업데이트합니다. +이 경우, 학습률 스케쥴은 코사인 감쇠(cosine decay) 함수를 사용합니다. +코사인 감쇠 함수는 높은 곳에서 시작한 다음, 시간이 지남에 따라 감소하여 결국 0에 도달합니다. +VOC 데이터 세트의 cardinality는 2124이고 배치 크기는 4입니다. +데이터 세트 cardinality는 모델이 학습할 단계 수를 결정하기 때문에, +학습률 감쇠(learning rate decay)에 중요합니다. +초기 학습률은 0.007에 비례하고, 감소 단계는 2124입니다. +즉, 학습률은 `INITIAL_LR`에서 시작한 다음, 2124단계에 걸쳐 0으로 감소합니다. ![png](/images/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/learning_rate_schedule.png) @@ -197,7 +228,11 @@ learning_rate = keras.optimizers.schedules.CosineDecay( ) ``` -We instantiate a DeepLabV3+ model with a ResNet50 backbone pretrained on ImageNet classification: `resnet50_v2_imagenet` pre-trained weights will be used as the backbone feature extractor for the DeepLabV3Plus model. The `num_classes` parameter specifies the number of classes that the model will be trained to segment. +ImageNet 분류에 대해 사전 트레이닝된 ResNet50 백본을 사용하여, +DeepLabV3+ 모델을 인스턴스화합니다. +사전 트레이닝된 가중치 `resnet50_v2_imagenet`은 +DeepLabV3Plus 모델의 백본 특성 추출기로 사용됩니다. +`num_classes` 매개변수는 모델이 세그멘테이션하도록 트레이닝될 클래스 수를 지정합니다. ```python model = keras_cv.models.DeepLabV3Plus.from_preset( @@ -214,17 +249,31 @@ Downloading data from https://storage.googleapis.com/keras-cv/models/resnet50v2/ {{% /details %}} -## Compile the model +## 모델 컴파일 {#compile-the-model} -The model.compile() function sets up the training process for the model. It defines the - optimization algorithm - Stochastic Gradient Descent (SGD) - the loss function - categorical cross-entropy - the evaluation metrics - Mean IoU and categorical accuracy +`model.compile()` 함수는 모델의 트레이닝 프로세스를 설정합니다. -Semantic segmentation evaluation metrics: +이는 다음을 정의합니다. -Mean Intersection over Union (MeanIoU): MeanIoU measures how well a semantic segmentation model accurately identifies and delineates different objects or regions in an image. It calculates the overlap between predicted and actual object boundaries, providing a score between 0 and 1, where 1 represents a perfect match. +- 옵티마이저 알고리즘 +- 확률적 경사 하강법(SGD) +- 손실 함수 +- 카테고리 교차 엔트로피 +- 평가 지표 +- 평균 IoU 및 카테고리 정확도 -Categorical Accuracy: Categorical Accuracy measures the proportion of correctly classified pixels in an image. It gives a simple percentage indicating how accurately the model predicts the categories of pixels in the entire image. +시맨틱 세그멘테이션 평가 지표: -In essence, MeanIoU emphasizes the accuracy of identifying specific object boundaries, while Categorical Accuracy gives a broad overview of overall pixel-level correctness. +- 평균 교집합(MeanIoU, Mean Intersection over Union): + MeanIoU는 시맨틱 세그멘테이션 모델이 이미지에서, + 다른 객체나 영역을 얼마나 정확하게 식별하고 구분하는지 측정합니다. + 예측된 객체 경계와 실제 객체 경계 사이의 중첩을 계산하여, + 0~1 사이의 점수를 제공하며, 1은 완벽한 일치를 나타냅니다. +- 카테고리 정확도: 카테고리 정확도는 이미지에서 올바르게 분류된 픽셀의 비율을 측정합니다. + 모델이 전체 이미지에서 픽셀 카테고리를 얼마나 정확하게 예측하는지를 나타내는 간단한 백분율을 제공합니다. + +본질적으로 MeanIoU는 특정 객체 경계를 식별하는 정확도를 강조하는 반면, +카테고리 정확도는 전반적인 픽셀 레벨의 정확성에 대한 광범위한 개요를 제공합니다. ```python model.compile( @@ -280,7 +329,9 @@ Model: "deep_lab_v3_plus_1" {{% /details %}} -The utility function `dict_to_tuple` effectively transforms the dictionaries of training and validation datasets into tuples of images and one-hot encoded segmentation masks, which is used during training and evaluation of the DeepLabv3+ model. +유틸리티 함수 `dict_to_tuple`은 트레이닝 및 검증 데이터 세트의 딕셔너리를, +이미지와 원핫 인코딩된 세그멘테이션 마스크의 튜플로 효과적으로 변환합니다. +이 변환은 DeepLabv3+ 모델의 트레이닝 및 평가 중에 사용됩니다. ```python def dict_to_tuple(x): @@ -312,9 +363,10 @@ model.fit(train_ds, validation_data=eval_ds, epochs=EPOCHS) {{% /details %}} -## Predictions with trained model +## 트레이닝된 모델을 사용한 예측 {#predictions-with-trained-model} -Now that the model training of DeepLabv3+ has completed, let's test it by making predications on a few sample images. +이제 DeepLabv3+의 모델 트레이닝이 완료되었으므로, +몇 개의 샘플 이미지에 대한 예측을 통해 테스트해 보겠습니다. ```python test_ds = load_voc(split="sbd_eval") @@ -340,9 +392,14 @@ keras_cv.visualization.plot_segmentation_mask_gallery( ![png](/images/guides/keras_cv/semantic_segmentation_deeplab_v3_plus/semantic_segmentation_deeplab_v3_plus_28_0.png) -Here are some additional tips for using the KerasCV DeepLabv3+ model: - -- The model can be trained on a variety of datasets, including the COCO dataset, the PASCAL VOC dataset, and the Cityscapes dataset. -- The model can be fine-tuned on a custom dataset to improve its performance on a specific task. -- The model can be used to perform real-time inference on images. -- Also, try out KerasCV's SegFormer model `keras_cv.models.segmentation.SegFormer`. The SegFormer model is a newer model that has been shown to achieve state-of-the-art results on a variety of image segmentation benchmarks. It is based on the Swin Transformer architecture, and it is more efficient and accurate than previous image segmentation models. +KerasCV DeepLabv3+ 모델을 사용하기 위한 몇 가지 추가 팁은 다음과 같습니다. + +- 모델은 COCO 데이터 세트, PASCAL VOC 데이터 세트, Cityscapes 데이터 세트를 포함한, + 다양한 데이터 세트에 대해 트레이닝될 수 있습니다. +- 모델은 커스텀 데이터 세트에 대해 미세 조정하여, 특정 작업에서 성능을 개선할 수 있습니다. +- 모델은 이미지에 대해 실시간 추론을 수행하는 데 사용할 수 있습니다. +- 또한 KerasCV의 SegFormer 모델 `keras_cv.models.segmentation.SegFormer`를 사용해 보세요. + SegFormer 모델은 다양한 이미지 세그멘테이션 벤치마크에서, + 최첨단 결과를 달성하는 것으로 나타난 새로운 모델입니다. + Swin Transformer 아키텍처를 기반으로 하며, + 이전 이미지 세그멘테이션 모델보다 효율적이고 정확합니다. diff --git a/content/korean/docs/guides/keras_hub/_index.md b/content/korean/docs/guides/keras_hub/_index.md index 23e06478..185cefe9 100644 --- a/content/korean/docs/guides/keras_hub/_index.md +++ b/content/korean/docs/guides/keras_hub/_index.md @@ -8,14 +8,8 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -These guides cover the [KerasHub]({{< relref "/docs/keras_hub" >}}) library. +이 가이드에서는 [KerasHub]({{< relref "/docs/keras_hub" >}}) 라이브러리에 대해 설명합니다. -## Available guides +## 모든 컨텐츠 -- [Getting Started with KerasHub]({{< relref "/docs/guides/keras_hub/getting_started" >}}) -- [Semantic Segmentation with KerasHub]({{< relref "/docs/guides/keras_hub/semantic_segmentation_deeplab_v3" >}}) -- [Pretraining a Transformer from scratch with KerasHub]({{< relref "/docs/guides/keras_hub/transformer_pretraining" >}}) -- [Uploading Models with KerasHub]({{< relref "/docs/guides/keras_hub/upload" >}}) -- [Classification with KerasHub]({{< relref "/docs/guides/keras_hub/classification_with_keras_hub" >}}) -- [Segment Anything in KerasHub]({{< relref "/docs/guides/keras_hub/segment_anything_in_keras_hub" >}}) -- [Stable Diffusion 3 in KerasHub]({{< relref "/docs/guides/keras_hub/stable_diffusion_3_in_keras_hub" >}}) +{{< default-section-cards-list-recursive >}} diff --git a/content/korean/docs/guides/keras_hub/getting_started/_index.md b/content/korean/docs/guides/keras_hub/getting_started/_index.md index d920049f..0ed6bae2 100644 --- a/content/korean/docs/guides/keras_hub/getting_started/_index.md +++ b/content/korean/docs/guides/keras_hub/getting_started/_index.md @@ -1,6 +1,6 @@ --- -title: Getting Started with KerasHub -linkTitle: Getting Started with KerasHub +title: KerasHub 시작하기 +linkTitle: KerasHub 시작하기 toc: true weight: 1 type: docs @@ -11,7 +11,7 @@ type: docs **{{< t f_author >}}** [Matthew Watson](https://github.com/mattdangerw/), [Jonathan Bischof](https://github.com/jbischof) **{{< t f_date_created >}}** 2022/12/15 **{{< t f_last_modified >}}** 2024/10/17 -**{{< t f_description >}}** An introduction to the KerasHub API. +**{{< t f_description >}}** KerasHub API에 대한 소개입니다. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_hub/getting_started.ipynb" title="Colab" tag="Colab" tagType="warning">}} @@ -28,7 +28,7 @@ This guide is meant to be an accessible introduction to the entire library. We w As always, we'll keep our Keras guides focused on real-world code examples. You can play with the code here at any time by clicking the Colab link at the top of the guide. -## Installation and Setup +## Installation and Setup {#installation-and-setup} To begin, let's install keras-hub. The library is available on PyPI, so we can simply install it with pip. @@ -53,7 +53,7 @@ Lastly, we need to do some extra setup to access the models used in this guide. 2. Generate an Kaggle API key by going to [Kaggle settings](https://www.kaggle.com/settings) and clicking "Create New Token" button under the "API" section. 3. Inside your colab notebook, click on the key icon on the left hand toolbar. Add two secrets: `KAGGLE_USERNAME` with your username, and `KAGGLE_KEY` with the API key you just created. Make these secrets visible to the notebook you are running. -## API Quickstart +## API Quickstart {#api-quickstart} Before we begin, let's take a look at the key classes we will use in the KerasHub library. @@ -90,7 +90,7 @@ The figure below shows how all these core classes interact. Arrow indicate compo ![png](/images/guides/keras_hub/getting_started/class-diagram.png.png) -## Classify an image +## Classify an image {#classify-an-image} ![png](/images/keras-hub/getting_started_guide/prof_keras_beginner.png) @@ -228,7 +228,7 @@ Model: "res_net_image_classifier" {{% /details %}} -## Generate text with an LLM +## Generate text with an LLM {#generate-text-with-an-llm} ![png](/images/keras-hub/getting_started_guide/prof_keras_intermediate.png) @@ -466,7 +466,7 @@ Let's free up the memory from our large Gemma model before we jump to the next s del causal_lm ``` -## Fine-tune and publish an image classifier +## Fine-tune and publish an image classifier {#fine-tune-and-publish-an-image-classifier} ![png](/images/keras-hub/getting_started_guide/prof_keras_advanced.png) @@ -671,7 +671,7 @@ Let's delete this model to free up memory before we move on to our final example del image_classifier ``` -## Building a custom text classifier +## Building a custom text classifier {#building-a-custom-text-classifier} ![png](/images/keras-hub/getting_started_guide/prof_keras_expert.png) @@ -942,7 +942,7 @@ We are able to achieve over ~93% accuracy on the movie review sentiment classifi Taken together, the `backbone` and `tokenizer` we created in this example allowed us access the full power of pretrained Gemma checkpoints, without restricting what we could do with them. This is a central aim of the KerasHub API. Simple workflows should be easy, and as you go deeper, you gain access to a deeply customizable set of building blocks. -## Going further +## Going further {#going-further} This is just scratching the surface of what you can do with the KerasHub. diff --git a/content/korean/docs/guides/keras_nlp/_index.md b/content/korean/docs/guides/keras_nlp/_index.md index 6bbdc5c3..e267741e 100644 --- a/content/korean/docs/guides/keras_nlp/_index.md +++ b/content/korean/docs/guides/keras_nlp/_index.md @@ -8,10 +8,8 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -These guides cover the [KerasNLP]({{< relref "/docs/keras_nlp" >}}) library. +이 가이드에서는 [KerasNLP]({{< relref "/docs/keras_nlp" >}}) 라이브러리에 대해 설명합니다. -## Available guides +## 모든 컨텐츠 -- [Getting Started with KerasNLP]({{< relref "/docs/guides/keras_nlp/getting_started" >}}) -- [Pretraining a Transformer from scratch with KerasNLP]({{< relref "/docs/guides/keras_nlp/transformer_pretraining" >}}) -- [Uploading Models with KerasNLP]({{< relref "/docs/guides/keras_nlp/upload" >}}) +{{< default-section-cards-list-recursive >}} diff --git a/content/korean/docs/guides/keras_nlp/getting_started/_index.md b/content/korean/docs/guides/keras_nlp/getting_started/_index.md index 76564e16..2d9b5aa4 100644 --- a/content/korean/docs/guides/keras_nlp/getting_started/_index.md +++ b/content/korean/docs/guides/keras_nlp/getting_started/_index.md @@ -1,6 +1,6 @@ --- -title: Getting Started with KerasNLP -linkTitle: Getting Started with KerasNLP +title: KerasNLP 시작하기 +linkTitle: KerasNLP 시작하기 toc: true weight: 1 type: docs @@ -11,90 +11,121 @@ type: docs **{{< t f_author >}}** [Jonathan Bischof](https://github.com/jbischof) **{{< t f_date_created >}}** 2022/12/15 **{{< t f_last_modified >}}** 2023/07/01 -**{{< t f_description >}}** An introduction to the KerasNLP API. +**{{< t f_description >}}** KerasNLP API에 대한 소개입니다. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_nlp/getting_started.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_nlp/getting_started.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -KerasNLP is a natural language processing library that supports users through their entire development cycle. Our workflows are built from modular components that have state-of-the-art preset weights and architectures when used out-of-the-box and are easily customizable when more control is needed. +KerasNLP는 전체 개발 주기를 지원하는 자연어 처리 라이브러리입니다. +우리의 워크플로우는 모듈형 구성 요소로 이루어져 있으며, +최첨단 사전 트레이닝된 가중치와 아키텍처를 제공하며, +사용자 필요에 따라 쉽게 커스터마이즈할 수 있습니다. -This library is an extension of the core Keras API; all high-level modules are [`Layers`]({{< relref "/docs/api/layers" >}}) or [`Models`]({{< relref "/docs/api/models" >}}). If you are familiar with Keras, congratulations! You already understand most of KerasNLP. +이 라이브러리는 코어 Keras API의 확장입니다. +모든 높은 레벨 모듈은 [`Layers`]({{< relref "/docs/api/layers" >}}) 또는 [`Models`]({{< relref "/docs/api/models" >}})입니다. +Keras에 익숙하다면, 축하합니다! 이미 대부분의 KerasNLP를 이해하고 있는 것입니다. -KerasNLP uses Keras 3 to work with any of TensorFlow, Pytorch and Jax. In the guide below, we will use the `jax` backend for training our models, and [tf.data](https://www.tensorflow.org/guide/data) for efficiently running our input preprocessing. But feel free to mix things up! This guide runs in TensorFlow or PyTorch backends with zero changes, simply update the `KERAS_BACKEND` below. +KerasNLP는 Keras 3를 사용하여, TensorFlow, Pytorch, Jax와 함께 작동합니다. +아래 가이드에서는, 모델 트레이닝을 위해 `jax` 백엔드를 사용하고, +입력 전처리를 효율적으로 처리하기 위해, [tf.data](https://www.tensorflow.org/guide/data)를 사용합니다. +하지만, 자유롭게 다른 것을 사용해도 됩니다! +이 가이드는 백엔드를 TensorFlow 또는 PyTorch로 바꿔도 아무런 변경 없이 실행됩니다. +아래 `KERAS_BACKEND`를 업데이트하기만 하면 됩니다. -This guide demonstrates our modular approach using a sentiment analysis example at six levels of complexity: +이 가이드는 감정 분석 예제를 통해, 모듈식 접근 방식을 여섯 가지 복잡도 레벨에서 보여줍니다: -- Inference with a pretrained classifier -- Fine tuning a pretrained backbone -- Fine tuning with user-controlled preprocessing -- Fine tuning a custom model -- Pretraining a backbone model -- Build and train your own transformer from scratch +- 사전 트레이닝된 분류기를 사용한 추론 +- 사전 트레이닝된 백본을 미세 조정 +- 사용자 제어 전처리로 미세 조정 +- 커스텀 모델을 미세 조정 +- 백본 모델을 사전 트레이닝 +- 처음부터 직접 트랜스포머 모델 빌드 및 트레이닝 -Throughout our guide, we use Professor Keras, the official Keras mascot, as a visual reference for the complexity of the material: +가이드 전체에서, 우리는 Keras 공식 마스코트인 Keras 교수(Professor Keras)를 시각적 참조로 사용하여 자료의 복잡성을 설명합니다: ![drawing](/images/keras-hub/getting_started_guide/prof_keras_evolution.png) ```python !pip install -q --upgrade keras-nlp -!pip install -q --upgrade keras # Upgrade to Keras 3. +!pip install -q --upgrade keras # Keras 3로 업그레이드. ``` ```python import os -os.environ["KERAS_BACKEND"] = "jax" # or "tensorflow" or "torch" +os.environ["KERAS_BACKEND"] = "jax" # 또는 "tensorflow", "torch" import keras_nlp import keras -# Use mixed precision to speed up all training in this guide. +# 이 가이드에서 모든 트레이닝을 가속화하기 위해 혼합 정밀도 사용. keras.mixed_precision.set_global_policy("mixed_float16") ``` -## API quickstart +## API 빠른 시작 {#api-quickstart} -Our highest level API is `keras_nlp.models`. These symbols cover the complete user journey of converting strings to tokens, tokens to dense features, and dense features to task-specific output. For each `XX` architecture (e.g., `Bert`), we offer the following modules: +가장 높은 레벨의 API는 `keras_nlp.models`입니다. +이 심볼들은 문자열을 토큰으로, 토큰을 dense 특성으로, +그리고 dense 특성을 작업별 출력으로 변환하는 전체 과정을 다룹니다. +각 `XX` 아키텍처(예: `Bert`)에 대해, 다음 모듈을 제공합니다: - **Tokenizer**: `keras_nlp.models.XXTokenizer` - - **What it does**: Converts strings to sequences of token ids. - - **Why it's important**: The raw bytes of a string are too high dimensional to be useful features so we first map them to a small number of tokens, for example `"The quick brown fox"` to `["the", "qu", "##ick", "br", "##own", "fox"]`. - - **Inherits from**: [`keras.layers.Layer`]({{< relref "/docs/api/layers/base_layer#layer-class" >}}). + + - **기능**: 문자열을 토큰 ID 시퀀스로 변환합니다. + - **중요성**: 문자열의 raw 바이트는 유용한 특성으로 사용되기엔 차원이 너무 높으므로, + 먼저 작은 수의 토큰으로 매핑합니다. + 예를 들어, `"The quick brown fox"`는 `["the", "qu", "##ick", "br", "##own", "fox"]`로 변환됩니다. + - **상속받는 클래스**: [`keras.layers.Layer`]({{< relref "/docs/api/layers/base_layer#layer-class" >}}). + - **Preprocessor**: `keras_nlp.models.XXPreprocessor` - - **What it does**: Converts strings to a dictionary of preprocessed tensors consumed by the backbone, starting with tokenization. - - **Why it's important**: Each model uses special tokens and extra tensors to understand the input such as delimiting input segments and identifying padding tokens. Padding each sequence to the same length improves computational efficiency. - - **Has a**: `XXTokenizer`. - - **Inherits from**: [`keras.layers.Layer`]({{< relref "/docs/api/layers/base_layer#layer-class" >}}). + + - **기능**: 문자열을 토큰화로 시작하여, 백본이 사용할 수 있는 전처리된, 텐서 딕셔너리로 변환합니다. + - **중요성**: 각 모델은 입력을 이해하기 위해, 구분 기호 토큰과 같은 특수 토큰 및 추가 텐서를 사용합니다. + 예를 들어 입력 세그먼트를 구분하거나, 패딩 토큰을 식별하는 기능이 포함됩니다. + 모든 시퀀스를 동일한 길이로 패딩하면, 계산 효율성이 높아집니다. + - **구성 요소**: `XXTokenizer`. + - **상속받는 클래스**: [`keras.layers.Layer`]({{< relref "/docs/api/layers/base_layer#layer-class" >}}). + - **Backbone**: `keras_nlp.models.XXBackbone` - - **What it does**: Converts preprocessed tensors to dense features. _Does not handle strings; call the preprocessor first._ - - **Why it's important**: The backbone distills the input tokens into dense features that can be used in downstream tasks. It is generally pretrained on a language modeling task using massive amounts of unlabeled data. Transferring this information to a new task is a major breakthrough in modern NLP. - - **Inherits from**: [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). -- **Task**: e.g., `keras_nlp.models.XXClassifier` - - **What it does**: Converts strings to task-specific output (e.g., classification probabilities). - - **Why it's important**: Task models combine string preprocessing and the backbone model with task-specific `Layers` to solve a problem such as sentence classification, token classification, or text generation. The additional `Layers` must be fine-tuned on labeled data. - - **Has a**: `XXBackbone` and `XXPreprocessor`. - - **Inherits from**: [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). -Here is the modular hierarchy for `BertClassifier` (all relationships are compositional): + - **기능**: 전처리된 텐서를 dense 특성으로 변환합니다. _문자열 처리는 하지 않으므로, 먼저 전처리기를 호출해야 합니다._ + - **중요성**: 백본은 입력 토큰을 dense 특성으로 압축하여, 후속 작업에 사용할 수 있도록 합니다. + 백본 모델은 일반적으로 대량의 비지도 학습 데이터를 사용하여, 언어 모델링 작업으로 사전 트레이닝된 것입니다. + 이러한 정보를 새로운 작업에 전이하는 것은 현대 NLP에서 중요한 돌파구입니다. + - **상속받는 클래스**: [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). + +- **Task**: 예를 들어, `keras_nlp.models.XXClassifier` + + - **기능**: 문자열을 작업별 출력(예: 분류 확률)으로 변환합니다. + - **중요성**: 작업 모델은 문자열 전처리와 백본 모델을 작업별 `Layers`와 결합하여, + 문장 분류, 토큰 분류, 텍스트 생성 등의 문제를 해결합니다. + 추가된 `Layers`는 라벨이 지정된 데이터를 사용하여 미세 조정해야 합니다. + - **구성 요소**: `XXBackbone`과 `XXPreprocessor`. + - **상속받는 클래스**: [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). + +다음은 `BertClassifier`의 모듈 계층 구조입니다(모든 관계는 구성적 관계입니다): ![drawing](/images/guides/keras_nlp/getting_started/class_diagram.png) -All modules can be used independently and have a `from_preset()` method in addition to the standard constructor that instantiates the class with **preset** architecture and weights (see examples below). +모든 모듈은 독립적으로 사용할 수 있으며, **사전 설정**된 아키텍처와 가중치로 클래스를 인스턴스화하는, +`from_preset()` 메서드를 갖고 있습니다. (아래 예 참조) -## Data +## 데이터 {#data} -We will use a running example of sentiment analysis of IMDB movie reviews. In this task, we use the text to predict whether the review was positive (`label = 1`) or negative (`label = 0`). +우리는 IMDB 영화 리뷰의 감정 분석 예시를 사용합니다. +이 작업에서는 텍스트를 사용하여 리뷰가 긍정적(`label = 1`)인지 부정적(`label = 0`)인지를 예측합니다. -We load the data using [`keras.utils.text_dataset_from_directory`]({{< relref "/docs/api/data_loading/text#text_dataset_from_directory-function" >}}), which utilizes the powerful [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) format for examples. +데이터는 [`keras.utils.text_dataset_from_directory`]({{< relref "/docs/api/data_loading/text#text_dataset_from_directory-function" >}})를 사용하여 로드되며, +이는 강력한 [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) 형식을 이용합니다. ```python !curl -O https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz !tar -xf aclImdb_v1.tar.gz -!# Remove unsupervised examples +!# 비지도 학습 예제 제거 !rm -r aclImdb/train/unsup ``` @@ -109,8 +140,8 @@ imdb_test = keras.utils.text_dataset_from_directory( batch_size=BATCH_SIZE, ) -# Inspect first review -# Format is (review text tensor, label tensor) +# 첫 번째 리뷰 확인 +# 형식은 (리뷰 텍스트 텐서, 라벨 텐서) print(imdb_train.unbatch().take(1).get_single_element()) ``` @@ -128,17 +159,23 @@ Found 25000 files belonging to 2 classes. {{% /details %}} -## Inference with a pretrained classifier +## 사전 트레이닝된 분류기로 추론하기 {#inference-with-a-pretrained-classifier} ![drawing](/images/keras-hub/getting_started_guide/prof_keras_beginner.png) -The highest level module in KerasNLP is a **task**. A **task** is a [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}) consisting of a (generally pretrained) **backbone** model and task-specific layers. Here's an example using `keras_nlp.models.BertClassifier`. +KerasNLP에서 가장 높은 레벨의 모듈은 **태스크**입니다. +**태스크**는 (일반적으로 사전 트레이닝된) **백본** 모델과 +태스크 특화 레이어들로 구성된 +[`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})입니다. +다음은 `keras_nlp.models.BertClassifier`를 사용하는 예시입니다. -**Note**: Outputs are the logits per class (e.g., `[0, 0]` is 50% chance of positive). The output is \[negative, positive\] for binary classification. +**참고**: 출력은 클래스별 로짓입니다. +(예: `[0, 0]`은 긍정일 확률이 50%임을 나타냅니다) +출력은 이진 분류의 경우 \[negative, positive\]입니다. ```python classifier = keras_nlp.models.BertClassifier.from_preset("bert_tiny_en_uncased_sst2") -# Note: batched inputs expected so must wrap string in iterable +# 참고: 배치 입력이 필요하므로, 문자열을 iterable로 래핑해야 합니다. classifier.predict(["I love modular workflows in keras-nlp!"]) ``` @@ -152,13 +189,24 @@ array([[-1.539, 1.543]], dtype=float16) {{% /details %}} -All **tasks** have a `from_preset` method that constructs a [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}) instance with preset preprocessing, architecture and weights. This means that we can pass raw strings in any format accepted by a [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}) and get output specific to our task. +모든 **태스크**에는 사전 설정된 전처리, 아키텍처 및 가중치로 +[`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}) +인스턴스를 생성하는 `from_preset` 메서드가 있습니다. +이는 우리가 [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})에서 허용하는 모든 형식의 raw 문자열을 전달하고, 태스크에 맞는 출력 값을 받을 수 있음을 의미합니다. -This particular **preset** is a `"bert_tiny_uncased_en"` **backbone** fine-tuned on `sst2`, another movie review sentiment analysis (this time from Rotten Tomatoes). We use the `tiny` architecture for demo purposes, but larger models are recommended for SoTA performance. For all the task-specific presets available for `BertClassifier`, see our keras.io [models page]({{< relref "/docs/api/keras_nlp/models" >}}). +이 특정 **프리셋**은 `"bert_tiny_uncased_en"` **백본**을 `sst2`로 파인 튜닝한 모델로, +이는 Rotten Tomatoes 영화 리뷰 감성 분석을 수행한 모델입니다. +데모에서는 `tiny` 아키텍처를 사용하지만, 더 큰 모델을 사용하면 최신 성능(SoTA)을 얻을 수 있습니다. +`BertClassifier`에 사용 가능한 모든 태스크별 프리셋은, +[models 페이지]({{< relref "/docs/api/keras_nlp/models" >}})에서 확인할 수 있습니다. -Let's evaluate our classifier on the IMDB dataset. You will note we don't need to call [`keras.Model.compile`]({{< relref "/docs/api/models/model_training_apis#compile-method" >}}) here. All **task** models like `BertClassifier` ship with compilation defaults, meaning we can just call [`keras.Model.evaluate`]({{< relref "/docs/api/models/model_training_apis#evaluate-method" >}}) directly. You can always call compile as normal to override these defaults (e.g. to add new metrics). +이제 IMDB 데이터셋에서 분류기를 평가해 봅시다. +여기서 [`keras.Model.compile`]({{< relref "/docs/api/models/model_training_apis#compile-method" >}})를 호출할 필요는 없습니다. +`BertClassifier`와 같은 모든 **태스크** 모델은 기본적으로 컴파일된 상태로 제공되므로, +[`keras.Model.evaluate`]({{< relref "/docs/api/models/model_training_apis#evaluate-method" >}})를 바로 호출할 수 있습니다. +물론, 원한다면 새로운 메트릭을 추가하기 위해, 일반적인 컴파일 방식을 사용할 수 있습니다. -The output below is \[loss, accuracy\], +출력 값은 \[loss, accuracy\]입니다. ```python classifier.evaluate(imdb_test) @@ -174,17 +222,27 @@ classifier.evaluate(imdb_test) {{% /details %}} -Our result is 78% accuracy without training anything. Not bad! +결과는 78%의 정확도로, 아무런 트레이닝 없이 이 정도 성능을 얻었습니다. 나쁘지 않네요! -## Fine tuning a pretrained BERT backbone +## 사전 트레이닝된 BERT 백본 파인 튜닝 {#fine-tuning-a-pretrained-bert-backbone} ![drawing](/images/keras-hub/getting_started_guide/prof_keras_intermediate.png) -When labeled text specific to our task is available, fine-tuning a custom classifier can improve performance. If we want to predict IMDB review sentiment, using IMDB data should perform better than Rotten Tomatoes data! And for many tasks, no relevant pretrained model will be available (e.g., categorizing customer reviews). +태스크에 맞는 라벨링된 텍스트가 있으면, 커스텀 분류기를 파인 튜닝하여 성능을 향상시킬 수 있습니다. +IMDB 리뷰 감성을 예측하려면, +Rotten Tomatoes 데이터보다 IMDB 데이터를 사용하는 것이 더 나은 성능을 낼 것입니다. +또한, 많은 태스크에서 관련 사전 트레이닝된 모델이 없을 수도 있습니다. (예: 고객 리뷰 분류(categorizing)) -The workflow for fine-tuning is almost identical to above, except that we request a **preset** for the **backbone**\-only model rather than the entire classifier. When passed a **backbone** **preset**, a **task** `Model` will randomly initialize all task-specific layers in preparation for training. For all the **backbone** presets available for `BertClassifier`, see our keras.io [models page]({{< relref "/docs/api/keras_nlp/models" >}}). +파인 튜닝의 워크플로우는 위와 거의 동일하지만, +전체 분류기 대신 **백본** 전용 **프리셋**을 요청하는 차이만 있습니다. +**백본** **프리셋**이 전달되면, +**태스크** `Model`은 태스크에 맞는 레이어들을 무작위로 초기화하고 트레이닝 준비를 합니다. +`BertClassifier`에 사용 가능한 모든 **백본** 프리셋은, +[models 페이지]({{< relref "/docs/api/keras_nlp/models" >}})에서 확인할 수 있습니다. -To train your classifier, use [`keras.Model.fit`]({{< relref "/docs/api/models/model_training_apis#fit-method" >}}) as with any other [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}}). As with our inference example, we can rely on the compilation defaults for the **task** and skip [`keras.Model.compile`]({{< relref "/docs/api/models/model_training_apis#compile-method" >}}). As preprocessing is included, we again pass the raw data. +분류기를 트레이닝하려면, 다른 [`keras.Model`]({{< relref "/docs/api/models/model#model-class" >}})처럼 [`keras.Model.fit`]({{< relref "/docs/api/models/model_training_apis#fit-method" >}})를 사용하면 됩니다. +위에서와 마찬가지로 **태스크**에 대해, [`keras.Model.compile`]({{< relref "/docs/api/models/model_training_apis#compile-method" >}})을 스킵하고, 컴파일 기본값을 사용할 수 있습니다. +전처리가 포함되어 있으므로, raw 데이터를 바로 전달할 수 있습니다. ```python classifier = keras_nlp.models.BertClassifier.from_preset( @@ -208,23 +266,36 @@ classifier.fit( {{% /details %}} -Here we see a significant lift in validation accuracy (0.78 -> 0.87) with a single epoch of training even though the IMDB dataset is much smaller than `sst2`. +여기서는 한 번의 트레이닝만으로 검증 정확도가 0.78에서 0.87로 크게 상승하는 것을 볼 수 있습니다. +IMDB 데이터셋이 `sst2`보다 훨씬 작음에도 불구하고 말이죠. -## Fine tuning with user-controlled preprocessing +## 사용자 제어 전처리로 파인 튜닝 {#fine-tuning-with-user-controlled-preprocessing} ![drawing](/images/keras-hub/getting_started_guide/prof_keras_advanced.png) -For some advanced training scenarios, users might prefer direct control over preprocessing. For large datasets, examples can be preprocessed in advance and saved to disk or preprocessed by a separate worker pool using [`tf.data.experimental.service`](https://www.tensorflow.org/api_docs/python/tf/data/experimental/service). In other cases, custom preprocessing is needed to handle the inputs. +일부 고급 트레이닝 시나리오에서는, 사용자가 전처리를 직접 제어하기를 원할 수 있습니다. +대규모 데이터셋의 경우, 예제를 미리 전처리하여 디스크에 저장하거나, +[`tf.data.experimental.service`](https://www.tensorflow.org/api_docs/python/tf/data/experimental/service)를 사용하여 별도의 작업자 풀에서 전처리할 수 있습니다. +또는, 입력을 다루기 위해 커스텀 전처리가 필요한 경우도 있습니다. -Pass `preprocessor=None` to the constructor of a **task** `Model` to skip automatic preprocessing or pass a custom `BertPreprocessor` instead. +**태스크** `Model` 생성자에 `preprocessor=None`을 전달하여 자동 전처리를 건너뛰거나, +대신 커스텀 `BertPreprocessor`를 전달할 수 있습니다. -### Separate preprocessing from the same preset +### 동일한 프리셋에서 전처리 분리하기 {#separate-preprocessing-from-the-same-preset} -Each model architecture has a parallel **preprocessor** `Layer` with its own `from_preset` constructor. Using the same **preset** for this `Layer` will return the matching **preprocessor** as the **task**. +각 모델 아키텍처에는 자체 `from_preset` 생성자가 있는, 병렬 **전처리** `Layer`가 있습니다. +이 `Layer`에 대해 동일한 **프리셋**을 사용하면, **태스크**와 일치하는 **전처리**를 반환합니다. -In this workflow we train the model over three epochs using `tf.data.Dataset.cache()`, which computes the preprocessing once and caches the result before fitting begins. +이 워크플로우에서는 `tf.data.Dataset.cache()`를 사용하여, +fit 시작 전에 전처리를 한 번만 계산하고 그 결과를 캐시한 다음, +3번의 에포크 동안 모델을 트레이닝합니다. -**Note:** we can use [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) for preprocessing while running on the Jax or PyTorch backend. The input dataset will automatically be converted to backend native tensor types during fit. In fact, given the efficiency of [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) for running preprocessing, this is good practice on all backends. +**참고:** [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data)를 사용하여, +Jax 또는 PyTorch 백엔드에서 전처리를 실행할 수 있습니다. +입력 데이터셋은 트레이닝 중에 백엔드 네이티브 텐서 타입으로 자동 변환됩니다. +실제로 [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data)의 +전처리 효율성을 고려할 때, +모든 백엔드에서 이를 사용하는 것이 좋은 관행입니다. ```python import tensorflow as tf @@ -234,11 +305,12 @@ preprocessor = keras_nlp.models.BertPreprocessor.from_preset( sequence_length=512, ) -# Apply the preprocessor to every sample of train and test data using `map()`. -# [`tf.data.AUTOTUNE`](https://www.tensorflow.org/api_docs/python/tf/data/AUTOTUNE) and `prefetch()` are options to tune performance, see -# https://www.tensorflow.org/guide/data_performance for details. +# 전처리를 `map()`을 사용해, 트레이닝 및 테스트 데이터의 각 샘플에 적용합니다. +# 성능을 조정하려면 [`tf.data.AUTOTUNE`](https://www.tensorflow.org/api_docs/python/tf/data/AUTOTUNE)과 +# `prefetch()` 옵션을 사용할 수 있습니다. +# 성능 세부 사항은 https://www.tensorflow.org/guide/data_performance에서 확인하세요. -# Note: only call `cache()` if you training data fits in CPU memory! +# 참고: `cache()`는 트레이닝 데이터가 CPU 메모리에 맞는 경우에만 호출하세요! imdb_train_cached = ( imdb_train.map(preprocessor, tf.data.AUTOTUNE).cache().prefetch(tf.data.AUTOTUNE) ) @@ -271,31 +343,39 @@ Epoch 3/3 {{% /details %}} -After three epochs, our validation accuracy has only increased to 0.88. This is both a function of the small size of our dataset and our model. To exceed 90% accuracy, try larger **presets** such as `"bert_base_en_uncased"`. For all the **backbone** presets available for `BertClassifier`, see our keras.io [models page]({{< relref "/docs/api/keras_nlp/models" >}}). +세 번의 에포크 후, 우리의 검증 정확도는 0.88로 증가했습니다. +이는 데이터셋의 크기와 모델의 크기에 의해 결정됩니다. +90% 이상의 정확도를 달성하려면, `"bert_base_en_uncased"`와 같은 더 큰 **프리셋**을 시도해 보세요. +사용 가능한 모든 **백본** 프리셋은, +keras.io [모델 페이지]({{< relref "/docs/api/keras_nlp/models" >}})에서 확인할 수 있습니다. -### Custom preprocessing +### 커스텀 전처리 {#custom-preprocessing} -In cases where custom preprocessing is required, we offer direct access to the `Tokenizer` class that maps raw strings to tokens. It also has a `from_preset()` constructor to get the vocabulary matching pretraining. +커스텀 전처리가 필요한 경우, raw 문자열을 토큰으로 매핑하는 `Tokenizer` 클래스를 직접 사용할 수 있습니다. +이 클래스에는 사전 트레이닝과 일치하는 어휘를 얻기 위한, `from_preset()` 생성자가 있습니다. -**Note:** `BertTokenizer` does not pad sequences by default, so the output is ragged (each sequence has varying length). The `MultiSegmentPacker` below handles padding these ragged sequences to dense tensor types (e.g. [`tf.Tensor`](https://www.tensorflow.org/api_docs/python/tf/Tensor) or `torch.Tensor`). +**참고:** `BertTokenizer`는 기본적으로 시퀀스를 패딩하지 않으므로, +출력은 길이가 가변적인 형식으로 나타납니다. +아래의 `MultiSegmentPacker`는 이러한 가변 길이 시퀀스를 +dense 텐서 타입([`tf.Tensor`](https://www.tensorflow.org/api_docs/python/tf/Tensor) +또는 `torch.Tensor`)으로 패딩 처리합니다. ```python tokenizer = keras_nlp.models.BertTokenizer.from_preset("bert_tiny_en_uncased") tokenizer(["I love modular workflows!", "Libraries over frameworks!"]) -# Write your own packer or use one of our `Layers` +# 직접 패커를 작성하거나 `Layers` 중 하나를 사용할 수 있습니다. packer = keras_nlp.layers.MultiSegmentPacker( start_value=tokenizer.cls_token_id, end_value=tokenizer.sep_token_id, - # Note: This cannot be longer than the preset's `sequence_length`, and there - # is no check for a custom preprocessor! + # 참고: 이 값은 프리셋의 `sequence_length`보다 길 수 없으며, + # 커스텀 전처리기에는 이를 확인하는 과정이 없습니다! sequence_length=64, ) -# This function that takes a text sample `x` and its -# corresponding label `y` as input and converts the -# text into a format suitable for input into a BERT model. +# 이 함수는 텍스트 샘플 `x`와 해당 레이블 `y`를 입력받아, +# 텍스트를 BERT 모델에 적합한 형식으로 변환합니다. def preprocessor(x, y): token_ids, segment_ids = packer(tokenizer(x)) x = { @@ -313,7 +393,7 @@ imdb_test_preprocessed = imdb_test.map(preprocessor, tf.data.AUTOTUNE).prefetch( tf.data.AUTOTUNE ) -# Preprocessed example +# 전처리된 예시 출력 print(imdb_train_preprocessed.unbatch().take(1).get_single_element()) ``` @@ -345,17 +425,24 @@ array([ True, True, True, True, True, True, True, True, True, {{% /details %}} -## Fine tuning with a custom model +## 커스텀 모델을 사용한 파인 튜닝 {#fine-tuning-with-a-custom-model} ![drawing](/images/keras-hub/getting_started_guide/prof_keras_advanced.png) -For more advanced applications, an appropriate **task** `Model` may not be available. In this case, we provide direct access to the **backbone** `Model`, which has its own `from_preset` constructor and can be composed with custom `Layer`s. Detailed examples can be found at our [transfer learning guide]({{< relref "/docs/guides/transfer_learning" >}}). +더 고급 응용 프로그램의 경우, 적절한 **태스크** `Model`이 제공되지 않을 수 있습니다. +이 경우, 커스텀 `Layer`와 함께 사용할 수 있는 **백본** `Model`에 직접 액세스할 수 있으며, +이는 자체 `from_preset` 생성자를 가지고 있습니다. +자세한 예시는 [전이 학습 가이드]({{< relref "/docs/guides/transfer_learning" >}})에서 확인할 수 있습니다. -A **backbone** `Model` does not include automatic preprocessing but can be paired with a matching **preprocessor** using the same **preset** as shown in the previous workflow. +**백본** `Model`은 자동 전처리를 포함하지 않지만, +이전 워크플로우에서 보여준 것처럼, +동일한 **프리셋**을 사용하는 일치하는 **전처리기**와 함께 사용할 수 있습니다. -In this workflow, we experiment with freezing our backbone model and adding two trainable transformer layers to adapt to the new input. +이번 워크플로우에서는, 백본 모델을 동결하고, 새로운 입력에 맞게, +두 개의 트레이닝 가능한 트랜스포머 레이어를 추가하여 실험합니다. -**Note**: We can ignore the warning about gradients for the `pooled_dense` layer because we are using BERT's sequence output. +**참고**: 우리는 BERT의 시퀀스 출력을 사용하고 있으므로, +`pooled_dense` 레이어에 대한 경고를 무시할 수 있습니다. ```python preprocessor = keras_nlp.models.BertPreprocessor.from_preset("bert_tiny_en_uncased") @@ -377,7 +464,7 @@ for _ in range(2): intermediate_dim=512, dropout=0.1, )(sequence) -# Use [CLS] token output to classify +# [CLS] 토큰 출력을 사용하여 분류 outputs = keras.layers.Dense(2)(sequence[:, backbone.cls_token_index, :]) model = keras.Model(inputs, outputs) @@ -444,25 +531,38 @@ Epoch 3/3 {{% /details %}} -This model achieves reasonable accuracy despite having only 10% of the trainable parameters of our `BertClassifier` model. Each training step takes about 1/3 of the time—even accounting for cached preprocessing. +이 모델은 `BertClassifier` 모델에 비해 트레이닝 가능한 파라미터 수가 10%밖에 되지 않지만, +상당히 좋은 정확도를 달성합니다. +캐시된 전처리를 감안해도, 각 트레이닝 단계가 약 1/3의 시간을 소요합니다. -## Pretraining a backbone model +## 백본 모델 사전 트레이닝 {#pretraining-a-backbone-model} ![drawing](/images/keras-hub/getting_started_guide/prof_keras_expert.png) -Do you have access to large unlabeled datasets in your domain? Are they around the same size as used to train popular backbones such as BERT, RoBERTa, or GPT2 (XX+ GiB)? If so, you might benefit from domain-specific pretraining of your own backbone models. +당신의 도메인에서, 대규모 라벨이 없는 데이터셋에 접근할 수 있나요? +이러한 데이터셋의 크기가 BERT, RoBERTa 또는 GPT2와 같은 +유명한 백본 모델을 트레이닝시키는 데 사용된 데이터와 유사한 크기(XX+ GiB)인가요? +만약 그렇다면, 도메인에 특화된 사전 트레이닝을 통해 자체 백본 모델을 학습하는 것이 도움이 될 수 있습니다. -NLP models are generally pretrained on a language modeling task, predicting masked words given the visible words in an input sentence. For example, given the input `"The fox [MASK] over the [MASK] dog"`, the model might be asked to predict `["jumped", "lazy"]`. The lower layers of this model are then packaged as a **backbone** to be combined with layers relating to a new task. +NLP 모델은 일반적으로 언어 모델링 작업을 통해 사전 트레이닝되며, +이는 입력 문장에 보이는 단어를 기준으로 가려진 단어를 예측하는 방식입니다. +예를 들어, `"The fox [MASK] over the [MASK] dog"`라는 입력에서, +모델은 `["jumped", "lazy"]`를 예측해야 합니다. +이 모델의 하위 레이어는 **백본**으로 패키징되어, 새로운 작업과 관련된 레이어와 결합됩니다. -The KerasNLP library offers SoTA **backbones** and **tokenizers** to be trained from scratch without presets. +KerasNLP 라이브러리는 SoTA **백본**과 **토크나이저**를 프리셋 없이 처음부터 트레이닝할 수 있도록 지원합니다. -In this workflow, we pretrain a BERT **backbone** using our IMDB review text. We skip the "next sentence prediction" (NSP) loss because it adds significant complexity to the data processing and was dropped by later models like RoBERTa. See our e2e [Transformer pretraining]({{< relref "/docs/guides/keras_nlp/transformer_pretraining/#pretraining" >}}) for step-by-step details on how to replicate the original paper. +이번 워크플로우에서는, IMDB 리뷰 텍스트를 사용하여 BERT **백본**을 사전 학습합니다. +데이터 처리 복잡성을 줄이기 위해, "next sentence prediction" (NSP) 손실을 생략하였으며, +이는 RoBERTa와 같은 이후 모델에서도 제외되었습니다. +자세한 내용은 원본 논문을 복제하는 단계별 가이드를 제공하는, +[Transformer 사전 트레이닝]({{< relref "/docs/guides/keras_nlp/transformer_pretraining/#pretraining" >}})을 참조하세요. -### Preprocessing +### 전처리 {#preprocessing} ```python -# All BERT `en` models have the same vocabulary, so reuse preprocessor from -# "bert_tiny_en_uncased" +# 모든 BERT `en` 모델들은 동일한 어휘집을 사용하므로, +# "bert_tiny_en_uncased"의 전처리기를 재사용합니다. preprocessor = keras_nlp.models.BertPreprocessor.from_preset( "bert_tiny_en_uncased", sequence_length=256, @@ -470,7 +570,7 @@ preprocessor = keras_nlp.models.BertPreprocessor.from_preset( packer = preprocessor.packer tokenizer = preprocessor.tokenizer -# keras.Layer to replace some input tokens with the "[MASK]" token +# 일부 입력 토큰을 "[MASK]" 토큰으로 교체하는 keras.Layer masker = keras_nlp.layers.MaskedLMMaskGenerator( vocabulary_size=tokenizer.vocabulary_size(), mask_selection_rate=0.25, @@ -485,8 +585,8 @@ masker = keras_nlp.layers.MaskedLMMaskGenerator( def preprocess(inputs, label): inputs = preprocessor(inputs) masked_inputs = masker(inputs["token_ids"]) - # Split the masking layer outputs into a (features, labels, and weights) - # tuple that we can use with keras.Model.fit(). + # 마스킹 레이어 출력을 (features, labels, weights)로 분리하여 + # keras.Model.fit()에서 사용할 수 있도록 합니다. features = { "token_ids": masked_inputs["token_ids"], "segment_ids": inputs["segment_ids"], @@ -505,7 +605,7 @@ pretrain_val_ds = imdb_test.map( preprocess, num_parallel_calls=tf.data.AUTOTUNE ).prefetch(tf.data.AUTOTUNE) -# Tokens with ID 103 are "masked" +# ID 103은 "masked"된 토큰입니다. print(pretrain_ds.unbatch().take(1).get_single_element()) ``` @@ -604,10 +704,10 @@ array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., {{% /details %}} -### Pretraining model +### 사전 트레이닝 모델 {#pretraining-model} ```python -# BERT backbone +# BERT 백본 모델 backbone = keras_nlp.models.BertBackbone( vocabulary_size=tokenizer.vocabulary_size(), num_layers=2, @@ -616,7 +716,7 @@ backbone = keras_nlp.models.BertBackbone( intermediate_dim=512, ) -# Language modeling head +# 언어 모델링 헤드 mlm_head = keras_nlp.layers.MaskedLMHead( token_embedding=backbone.token_embedding, ) @@ -628,15 +728,15 @@ inputs = { "mask_positions": keras.Input(shape=(None,), dtype=tf.int32, name="mask_positions"), } -# Encoded token sequence +# 인코딩된 토큰 시퀀스 sequence = backbone(inputs)["sequence_output"] -# Predict an output word for each masked input token. -# We use the input token embedding to project from our encoded vectors to -# vocabulary logits, which has been shown to improve training efficiency. +# 각 마스킹된 입력 토큰에 대해 출력 단어 예측. +# 입력 토큰 임베딩을 사용해 인코딩된 벡터에서 어휘 로짓으로 프로젝션합니다. +# 이는 트레이닝 효율성을 향상시키는 것으로 알려져 있습니다. outputs = mlm_head(sequence, mask_positions=inputs["mask_positions"]) -# Define and compile our pretraining model. +# 사전 트레이닝 모델 정의 및 컴파일 pretraining_model = keras.Model(inputs, outputs) pretraining_model.summary() pretraining_model.compile( @@ -646,11 +746,11 @@ pretraining_model.compile( jit_compile=True, ) -# Pretrain on IMDB dataset +# IMDB 데이터셋으로 사전 트레이닝 진행 pretraining_model.fit( pretrain_ds, validation_data=pretrain_val_ds, - epochs=3, # Increase to 6 for higher accuracy + epochs=3, # 더 높은 정확도를 위해 6으로 증가 가능 ) ``` @@ -699,17 +799,27 @@ Epoch 3/3 {{% /details %}} -After pretraining save your `backbone` submodel to use in a new task! +사전 트레이닝 후, `backbone` 서브모델을 저장하여 새로운 작업에 사용하세요! -## Build and train your own transformer from scratch +## 처음부터 직접 트랜스포머 빌드 및 트레이닝 {#build-and-train-your-own-transformer-from-scratch} ![drawing](/images/keras-hub/getting_started_guide/prof_keras_expert.png) -Want to implement a novel transformer architecture? The KerasNLP library offers all the low-level modules used to build SoTA architectures in our `models` API. This includes the `keras_nlp.tokenizers` API which allows you to train your own subword tokenizer using `WordPieceTokenizer`, `BytePairTokenizer`, or `SentencePieceTokenizer`. +새로운 트랜스포머 아키텍처를 구현하고 싶으신가요? +KerasNLP 라이브러리는 SoTA(최첨단) 아키텍처를 구축하는 데 사용되는, +모든 낮은 레벨 모듈을 `models` API에 제공합니다. +여기에는 `keras_nlp.tokenizers` API가 포함되어 있어, +`WordPieceTokenizer`, `BytePairTokenizer`, 또는 `SentencePieceTokenizer`를 사용하여, +직접 서브워드 토크나이저를 트레이닝할 수 있습니다. -In this workflow, we train a custom tokenizer on the IMDB data and design a backbone with custom transformer architecture. For simplicity, we then train directly on the classification task. Interested in more details? We wrote an entire guide to pretraining and finetuning a custom transformer on [keras.io]({{< relref "/docs/guides/keras_nlp/transformer_pretraining" >}}), +이 워크플로우에서는, IMDB 데이터에 대해 커스텀 토크나이저를 트레이닝하고, +커스텀 트랜스포머 아키텍처로 백본을 설계합니다. +간단하게 하기 위해, 바로 분류 작업에 대해 트레이닝을 진행합니다. +더 자세한 내용이 궁금하신가요? +커스텀 트랜스포머를 프리트레이닝하고 파인튜닝하는 전체 가이드를, +[keras.io]({{< relref "/docs/guides/keras_nlp/transformer_pretraining" >}})에 작성했습니다. -### Train custom vocabulary from IMDB data +### IMDB 데이터에서 커스텀 어휘 트레이닝 {#train-custom-vocabulary-from-imdb-data} ```python vocab = keras_nlp.tokenizers.compute_word_piece_vocabulary( @@ -727,7 +837,7 @@ tokenizer = keras_nlp.tokenizers.WordPieceTokenizer( ) ``` -### Preprocess data with a custom tokenizer +### 커스텀 토크나이저로 데이터 전처리 {#preprocess-data-with-a-custom-tokenizer} ```python packer = keras_nlp.layers.StartEndPacker( @@ -819,7 +929,7 @@ array([ 1, 102, 11, 61, 43, 771, 16, 340, 916, {{% /details %}} -### Design a tiny transformer +### 작은 트랜스포머 설계 {#design-a-tiny-transformer} ```python token_id_input = keras.Input( @@ -837,7 +947,7 @@ outputs = keras_nlp.layers.TransformerEncoder( intermediate_dim=128, dropout=0.1, )(outputs) -# Use "[START]" token to classify +# "[START]" 토큰을 사용하여 분류 outputs = keras.layers.Dense(2)(outputs[:, 0, :]) model = keras.Model( inputs=token_id_input, @@ -873,7 +983,7 @@ Model: "functional_5" {{% /details %}} -### Train the transformer directly on the classification objective +### 트랜스포머를 직접 분류 목표(objective)에 맞춰 트레이닝 {#train-the-transformer-directly-on-the-classification-objective} ```python model.compile( @@ -904,4 +1014,7 @@ Epoch 3/3 {{% /details %}} -Excitingly, our custom classifier is similar to the performance of fine-tuning `"bert_tiny_en_uncased"`! To see the advantages of pretraining and exceed 90% accuracy we would need to use larger **presets** such as `"bert_base_en_uncased"`. +흥미롭게도, 우리가 설계한 커스텀 분류기는 `"bert_tiny_en_uncased"`를 미세 조정한 성능과 비슷합니다! +90% 이상의 정확도를 달성하고, +사전 트레이닝의 장점을 보기 위해서는 `"bert_base_en_uncased"`와 같은, +더 큰 **프리셋**을 사용해야 합니다. diff --git a/content/korean/docs/guides/keras_nlp/transformer_pretraining/_index.md b/content/korean/docs/guides/keras_nlp/transformer_pretraining/_index.md index 66926b28..f573ce18 100644 --- a/content/korean/docs/guides/keras_nlp/transformer_pretraining/_index.md +++ b/content/korean/docs/guides/keras_nlp/transformer_pretraining/_index.md @@ -1,6 +1,6 @@ --- -title: Pretraining a Transformer from scratch with KerasNLP -linkTitle: Pretraining a Transformer from scratch with KerasNLP +title: KerasNLP로 처음부터 트랜스포머 사전 트레이닝 +linkTitle: 트랜스포머 사전 트레이닝 toc: true weight: 2 type: docs @@ -11,34 +11,38 @@ type: docs **{{< t f_author >}}** [Matthew Watson](https://github.com/mattdangerw/) **{{< t f_date_created >}}** 2022/04/18 **{{< t f_last_modified >}}** 2023/07/15 -**{{< t f_description >}}** Use KerasNLP to train a Transformer model from scratch. +**{{< t f_description >}}** KerasNLP를 사용하여 처음부터 트랜스포머 모델을 트레이닝하는 방법. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_nlp/transformer_pretraining.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_nlp/transformer_pretraining.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -KerasNLP aims to make it easy to build state-of-the-art text processing models. In this guide, we will show how library components simplify pretraining and fine-tuning a Transformer model from scratch. +KerasNLP는 최신 텍스트 처리 모델을 쉽게 구축할 수 있도록 설계되었습니다. +이 가이드에서는, 라이브러리 구성 요소가 처음부터 트랜스포머 모델을 사전 트레이닝하고, +미세 조정하는 과정을 얼마나 간소화하는지 보여줍니다. -This guide is broken into three parts: +이 가이드는 세 가지 부분으로 나누어져 있습니다: -1. _Setup_, task definition, and establishing a baseline. -2. _Pretraining_ a Transformer model. -3. _Fine-tuning_ the Transformer model on our classification task. +1. _셋업_, 작업 정의 및 베이스라인 설정. +2. 트랜스포머 모델 _사전 트레이닝_. +3. 분류 작업에 대한 트랜스포머 모델 _미세 조정_. -## Setup +## 셋업 {#setup} -The following guide uses Keras 3 to work in any of `tensorflow`, `jax` or `torch`. We select the `jax` backend below, which will give us a particularly fast train step below, but feel free to mix it up. +다음 가이드는 `tensorflow`, `jax` 또는 `torch`에서 작동하는 Keras 3을 사용합니다. +아래에서는 특히 빠른 트레이닝 단계를 제공하는 `jax` 백엔드를 선택했지만, +다른 백엔드도 자유롭게 사용할 수 있습니다. ```python !pip install -q --upgrade keras-nlp -!pip install -q --upgrade keras # Upgrade to Keras 3. +!pip install -q --upgrade keras # Keras 3으로 업그레이드. ``` ```python import os -os.environ["KERAS_BACKEND"] = "jax" # or "tensorflow" or "torch" +os.environ["KERAS_BACKEND"] = "jax" # 또는 "tensorflow" 또는 "torch" import keras_nlp @@ -46,45 +50,49 @@ import tensorflow as tf import keras ``` -Next up, we can download two datasets. +다음으로, 두 개의 데이터셋을 다운로드합니다. -- [SST-2](https://paperswithcode.com/sota/sentiment-analysis-on-sst-2-binary) a text classification dataset and our "end goal". This dataset is often used to benchmark language models. -- [WikiText-103](https://paperswithcode.com/dataset/wikitext-103): A medium sized collection of featured articles from English Wikipedia, which we will use for pretraining. +- [SST-2](https://paperswithcode.com/sota/sentiment-analysis-on-sst-2-binary): + - 텍스트 분류 데이터셋으로, 우리의 "최종 목표"입니다. + - 이 데이터셋은 종종 언어 모델의 성능을 벤치마킹하는 데 사용됩니다. +- [WikiText-103](https://paperswithcode.com/dataset/wikitext-103): + - 영어 위키피디아의 주요 기사로 구성된 중간 크기의 컬렉션으로, 사전 트레이닝에 사용할 것입니다. -Finally, we will download a WordPiece vocabulary, to do sub-word tokenization later on in this guide. +마지막으로, 이 가이드 후반에서 사용할 서브워드 토크나이징(sub-word tokenization)을 위해 +WordPiece 어휘를 다운로드합니다. ```python -# Download pretraining data. +# 사전 트레이닝 데이터 다운로드. keras.utils.get_file( origin="https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-raw-v1.zip", extract=True, ) wiki_dir = os.path.expanduser("~/.keras/datasets/wikitext-103-raw/") -# Download finetuning data. +# 미세 조정 데이터 다운로드. keras.utils.get_file( origin="https://dl.fbaipublicfiles.com/glue/data/SST-2.zip", extract=True, ) sst_dir = os.path.expanduser("~/.keras/datasets/SST-2/") -# Download vocabulary data. +# 어휘 데이터 다운로드. vocab_file = keras.utils.get_file( origin="https://storage.googleapis.com/tensorflow/keras-nlp/examples/bert/bert_vocab_uncased.txt", ) ``` -Next, we define some hyperparameters we will use during training. +다음으로, 트레이닝 중에 사용할 하이퍼파라미터를 정의합니다. ```python -# Preprocessing params. +# 전처리 파라미터. PRETRAINING_BATCH_SIZE = 128 FINETUNING_BATCH_SIZE = 32 SEQ_LENGTH = 128 MASK_RATE = 0.25 PREDICTIONS_PER_SEQ = 32 -# Model params. +# 모델 파라미터. NUM_LAYERS = 3 MODEL_DIM = 256 INTERMEDIATE_DIM = 512 @@ -92,19 +100,20 @@ NUM_HEADS = 4 DROPOUT = 0.1 NORM_EPSILON = 1e-5 -# Training params. +# 트레이닝 파라미터. PRETRAINING_LEARNING_RATE = 5e-4 PRETRAINING_EPOCHS = 8 FINETUNING_LEARNING_RATE = 5e-5 FINETUNING_EPOCHS = 3 ``` -### Load data +### 데이터 로드 {#load-data} -We load our data with [tf.data](https://www.tensorflow.org/guide/data), which will allow us to define input pipelines for tokenizing and preprocessing text. +[tf.data](https://www.tensorflow.org/guide/data)를 사용하여 데이터를 로드합니다. +이를 통해 텍스트를 토큰화하고 전처리하는 입력 파이프라인을 정의할 수 있습니다. ```python -# Load SST-2. +# SST-2 데이터 로드. sst_train_ds = tf.data.experimental.CsvDataset( sst_dir + "train.tsv", [tf.string, tf.int32], header=True, field_delim="\t" ).batch(FINETUNING_BATCH_SIZE) @@ -112,7 +121,7 @@ sst_val_ds = tf.data.experimental.CsvDataset( sst_dir + "dev.tsv", [tf.string, tf.int32], header=True, field_delim="\t" ).batch(FINETUNING_BATCH_SIZE) -# Load wikitext-103 and filter out short lines. +# wikitext-103 데이터 로드 및 짧은 줄 필터링. wiki_train_ds = ( tf.data.TextLineDataset(wiki_dir + "wiki.train.raw") .filter(lambda x: tf.strings.length(x) > 100) @@ -124,7 +133,7 @@ wiki_val_ds = ( .batch(PRETRAINING_BATCH_SIZE) ) -# Take a peak at the sst-2 dataset. +# sst-2 데이터셋을 살펴봅니다. print(sst_train_ds.unbatch().batch(4).take(1).get_single_element()) ``` @@ -141,17 +150,22 @@ array([b'hide new secretions from the parental units ', {{% /details %}} -You can see that our `SST-2` dataset contains relatively short snippets of movie review text. Our goal is to predict the sentiment of the snippet. A label of 1 indicates positive sentiment, and a label of 0 negative sentiment. +`SST-2` 데이터셋에는 영화 리뷰 텍스트의 짧은 문장이 포함되어 있습니다. +우리의 목표는 해당 문장의 감정을 예측하는 것입니다. +레이블이 1이면 긍정적인 감정을, 0이면 부정적인 감정을 나타냅니다. -### Establish a baseline +### 베이스라인 설정 {#establish-a-baseline} -As a first step, we will establish a baseline of good performance. We don't actually need KerasNLP for this, we can just use core Keras layers. +첫 번째 단계로, 좋은 성능의 베이스라인을 설정합니다. +이 과정에서는 KerasNLP가 필요하지 않으며, 기본적인 Keras 레이어만으로도 가능합니다. -We will train a simple bag-of-words model, where we learn a positive or negative weight for each word in our vocabulary. A sample's score is simply the sum of the weights of all words that are present in the sample. +간단한 bag-of-words 모델을 트레이닝할 것입니다. +이 모델은 우리의 어휘에서 각 단어에 대해 긍정 또는 부정 가중치를 학습합니다. +샘플의 점수는 해당 샘플에 포함된 모든 단어의 가중치 합계로 계산됩니다. ```python -# This layer will turn our input sentence into a list of 1s and 0s the same size -# our vocabulary, indicating whether a word is present in absent. +# 이 레이어는 입력 문장을 어휘 크기와 같은 크기의 1과 0 리스트로 변환합니다. +# 이 리스트는 단어가 존재하거나 존재하지 않음을 나타냅니다. multi_hot_layer = keras.layers.TextVectorization( max_tokens=4000, output_mode="multi_hot" ) @@ -159,8 +173,7 @@ multi_hot_layer.adapt(sst_train_ds.map(lambda x, y: x)) multi_hot_ds = sst_train_ds.map(lambda x, y: (multi_hot_layer(x), y)) multi_hot_val_ds = sst_val_ds.map(lambda x, y: (multi_hot_layer(x), y)) -# We then learn a linear regression over that layer, and that's our entire -# baseline model! +# 그런 다음 이 레이어에 대해 선형 회귀를 학습합니다. 이것이 베이스라인 모델입니다! inputs = keras.Input(shape=(4000,), dtype="int32") outputs = keras.layers.Dense(1, activation="sigmoid")(inputs) @@ -188,48 +201,73 @@ Epoch 5/5 {{% /details %}} -A bag-of-words approach can be a fast and surprisingly powerful, especially when input examples contain a large number of words. With shorter sequences, it can hit a performance ceiling. +Bag-of-words 접근 방식은 입력 예제가 많은 단어를 포함할 때, +빠르고 놀라울 정도로 강력할 수 있습니다. +그러나 짧은 시퀀스의 경우, 성능에 한계가 있을 수 있습니다. -To do better, we would like to build a model that can evaluate words _in context_. Instead of evaluating each word in a void, we need to use the information contained in the _entire ordered sequence_ of our input. +더 나은 성능을 위해, 우리는 단어를 _문맥_ 내에서 평가할 수 있는 모델을 빌드하고 싶습니다. +각 단어를 개별적으로 평가하는 대신, +입력의 _전체 순서 있는 시퀀스(entire ordered sequence)_ 에서 포함된 정보를 사용해야 합니다. -This runs us into a problem. `SST-2` is very small dataset, and there's simply not enough example text to attempt to build a larger, more parameterized model that can learn on a sequence. We would quickly start to overfit and memorize our training set, without any increase in our ability to generalize to unseen examples. +이 경우, `SST-2`는 매우 작은 데이터셋이므로, +시퀀스를 학습할 수 있는 더 큰 파라미터 모델을 구축하기에는, 예제 텍스트가 부족합니다. +트레이닝 데이터셋을 외워버리게 될 위험이 있으며, 새로운 예제에 대한 일반화 능력은 향상되지 않습니다. -Enter **pretraining**, which will allow us to learn on a larger corpus, and transfer our knowledge to the `SST-2` task. And enter **KerasNLP**, which will allow us to pretrain a particularly powerful model, the Transformer, with ease. +이때 **사전 트레이닝**을 사용하면, 더 큰 코퍼스에 대해 학습하고, +그 지식을 `SST-2` 작업에 적용할 수 있습니다. +그리고 **KerasNLP**를 사용하면, +강력한 모델인 트랜스포머를 손쉽게 사전 트레이닝할 수 있습니다. -## Pretraining +## 사전 트레이닝 {#pretraining} -To beat our baseline, we will leverage the `WikiText103` dataset, an unlabeled collection of Wikipedia articles that is much bigger than `SST-2`. +베이스라인을 뛰어넘기 위해, 우리는 `WikiText103` 데이터셋을 활용할 것입니다. +이 데이터셋은 `SST-2`보다 훨씬 큰 비지도 학습 Wikipedia 기사 모음입니다. -We are going to train a _transformer_, a highly expressive model which will learn to embed each word in our input as a low dimensional vector. Our wikipedia dataset has no labels, so we will use an unsupervised training objective called the _Masked Language Modeling_ (MaskedLM) objective. +우리는 _트랜스포머_ 를 트레이닝할 것입니다. +이 모델은 우리의 입력에서 각 단어를 저차원 벡터로 임베딩하는 것을 학습하는, 고도의 표현력이 있는 모델입니다. +Wikipedia 데이터셋에는 레이블이 없기 때문에, +_Masked Language Modeling_ (MaskedLM)이라는 비지도 트레이닝 목표를 사용할 것입니다. -Essentially, we will be playing a big game of "guess the missing word". For each input sample we will obscure 25% of our input data, and train our model to predict the parts we covered up. +본질적으로, 우리는 "숨겨진 단어 맞추기"라는 큰 게임을 할 것입니다. +각 입력 샘플에서 입력 데이터의 25%를 가리고, 그 부분을 예측하도록 모델을 트레이닝할 것입니다. -### Preprocess data for the MaskedLM task +### MaskedLM 작업을 위한 데이터 전처리 {#preprocess-data-for-the-maskedlm-task} -Our text preprocessing for the MaskedLM task will occur in two stages. +MaskedLM 작업을 위한 텍스트 전처리는 두 단계로 이루어집니다. -1. Tokenize input text into integer sequences of token ids. -2. Mask certain positions in our input to predict on. +1. 입력 텍스트를 정수 토큰 ID 시퀀스로 토큰화합니다. +2. 예측할 입력의 일부 위치를 마스킹합니다. -To tokenize, we can use a [`keras_nlp.tokenizers.Tokenizer`]({{< relref "/docs/api/keras_nlp/tokenizers/tokenizer#tokenizer-class" >}}) – the KerasNLP building block for transforming text into sequences of integer token ids. +토큰화를 위해, 우리는 텍스트를 정수 토큰 ID 시퀀스로 변환하는 KerasNLP의 빌딩 블록인, +[`keras_nlp.tokenizers.Tokenizer`]({{< relref "/docs/api/keras_nlp/tokenizers/tokenizer#tokenizer-class" >}})를 사용할 수 있습니다. -In particular, we will use [`keras_nlp.tokenizers.WordPieceTokenizer`]({{< relref "/docs/api/keras_nlp/tokenizers/word_piece_tokenizer#wordpiecetokenizer-class" >}}) which does _sub-word_ tokenization. Sub-word tokenization is popular when training models on large text corpora. Essentially, it allows our model to learn from uncommon words, while not requiring a massive vocabulary of every word in our training set. +특히, 우리는 _서브워드(sub-word)_ 토큰화를 수행하는 [`keras_nlp.tokenizers.WordPieceTokenizer`]({{< relref "/docs/api/keras_nlp/tokenizers/word_piece_tokenizer#wordpiecetokenizer-class" >}})를 사용할 것입니다. +서브워드 토큰화는 큰 텍스트 코퍼스에 대해 모델을 트레이닝할 때 널리 사용됩니다. +본질적으로, 이 방식은 모델이 드문 단어에서 학습할 수 있도록 하면서도, +우리의 트레이닝 세트에서 모든 단어를 포함하는 큰 어휘집을 필요로 하지 않게 합니다. -The second thing we need to do is mask our input for the MaskedLM task. To do this, we can use [`keras_nlp.layers.MaskedLMMaskGenerator`]({{< relref "/docs/api/keras_nlp/preprocessing_layers/masked_lm_mask_generator#maskedlmmaskgenerator-class" >}}), which will randomly select a set of tokens in each input and mask them out. +두 번째로 필요한 것은 MaskedLM 작업을 위해 입력을 마스킹하는 것입니다. +이를 위해 [`keras_nlp.layers.MaskedLMMaskGenerator`]({{< relref "/docs/api/keras_nlp/preprocessing_layers/masked_lm_mask_generator#maskedlmmaskgenerator-class" >}})를 사용할 수 있으며, +이는 각 입력에서 랜덤으로 선택된 토큰 세트를 마스킹합니다. -The tokenizer and the masking layer can both be used inside a call to [tf.data.Dataset.map](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#map). We can use [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) to efficiently pre-compute each batch on the CPU, while our GPU or TPU works on training with the batch that came before. Because our masking layer will choose new words to mask each time, each epoch over our dataset will give us a totally new set of labels to train on. +토크나이저와 마스킹 레이어는 모두 [tf.data.Dataset.map](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#map) 호출 내에서 사용할 수 있습니다. +우리는 [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data)를 사용하여 +CPU에서 각 배치를 미리 계산하고, +그 전에 GPU 또는 TPU가 트레이닝을 진행할 수 있도록 할 수 있습니다. +마스킹 레이어는 각 에포크마다 새로운 단어 세트를 마스킹하므로, +데이터셋을 순회할 때마다 완전히 새로운 레이블 세트를 트레이닝할 수 있게 됩니다. ```python -# Setting sequence_length will trim or pad the token outputs to shape -# (batch_size, SEQ_LENGTH). +# sequence_length를 설정하면, +# 토큰 출력을 (batch_size, SEQ_LENGTH) 모양으로 자르거나(trim) 패딩합니다. tokenizer = keras_nlp.tokenizers.WordPieceTokenizer( vocabulary=vocab_file, sequence_length=SEQ_LENGTH, lowercase=True, strip_accents=True, ) -# Setting mask_selection_length will trim or pad the mask outputs to shape -# (batch_size, PREDICTIONS_PER_SEQ). +# mask_selection_length를 설정하면, +# 마스크 출력을 (batch_size, PREDICTIONS_PER_SEQ) 형태로 자르거나(trim) 패딩합니다. masker = keras_nlp.layers.MaskedLMMaskGenerator( vocabulary_size=tokenizer.vocabulary_size(), mask_selection_rate=MASK_RATE, @@ -241,8 +279,8 @@ masker = keras_nlp.layers.MaskedLMMaskGenerator( def preprocess(inputs): inputs = tokenizer(inputs) outputs = masker(inputs) - # Split the masking layer outputs into a (features, labels, and weights) - # tuple that we can use with keras.Model.fit(). + # 마스킹 레이어 출력을 keras.Model.fit()에서 사용할 수 있는 + # (features, labels, and weights) 튜플로 분리합니다. features = { "token_ids": outputs["token_ids"], "mask_positions": outputs["mask_positions"], @@ -252,7 +290,7 @@ def preprocess(inputs): return features, labels, weights -# We use prefetch() to pre-compute preprocessed batches on the fly on the CPU. +# prefetch()를 사용하여 CPU에서 전처리된 배치를 실시간으로 미리 계산합니다. pretrain_ds = wiki_train_ds.map( preprocess, num_parallel_calls=tf.data.AUTOTUNE ).prefetch(tf.data.AUTOTUNE) @@ -260,8 +298,8 @@ pretrain_val_ds = wiki_val_ds.map( preprocess, num_parallel_calls=tf.data.AUTOTUNE ).prefetch(tf.data.AUTOTUNE) -# Preview a single input example. -# The masks will change each time you run the cell. +# 단일 입력 예시 미리보기 +# 마스크는 셀을 실행할 때마다 변경됩니다. print(pretrain_val_ds.take(1).get_single_element()) ``` @@ -301,31 +339,40 @@ array([[1., 1., 1., ..., 1., 1., 1.], {{% /details %}} -The above block sorts our dataset into a `(features, labels, weights)` tuple, which can be passed directly to `keras.Model.fit()`. +위 코드 블록은 `(features, labels, weights)` 튜플로 데이터셋을 정리하여, +`keras.Model.fit()`에 직접 전달할 수 있습니다. -We have two features: +우리는 두 가지 특징을 가지고 있습니다: -1. `"token_ids"`, where some tokens have been replaced with our mask token id. -2. `"mask_positions"`, which keeps track of which tokens we masked out. +1. `"token_ids"`: 일부 토큰이 마스크 토큰 ID로 대체된 토큰들입니다. +2. `"mask_positions"`: 마스킹된 토큰의 위치를 추적하는 역할을 합니다. -Our labels are simply the ids we masked out. +레이블은 마스킹된 토큰의 ID입니다. -Because not all sequences will have the same number of masks, we also keep a `sample_weight` tensor, which removes padded labels from our loss function by giving them zero weight. +모든 시퀀스에 동일한 수의 마스크가 있는 것은 아니기 때문에, +`sample_weight` 텐서를 사용하여, +패딩된 레이블을 손실 함수에서 제외하기 위해 가중치를 0으로 설정합니다. -### Create the Transformer encoder +### 트랜스포머 인코더 생성 {#create-the-transformer-encoder} -KerasNLP provides all the building blocks to quickly build a Transformer encoder. +KerasNLP는 트랜스포머 인코더를 빠르게 빌드할 수 있는 모든 빌딩 블록을 제공합니다. -We use [`keras_nlp.layers.TokenAndPositionEmbedding`]({{< relref "/docs/api/keras_nlp/modeling_layers/token_and_position_embedding#tokenandpositionembedding-class" >}}) to first embed our input token ids. This layer simultaneously learns two embeddings – one for words in a sentence and another for integer positions in a sentence. The output embedding is simply the sum of the two. +우리는 [`keras_nlp.layers.TokenAndPositionEmbedding`]({{< relref "/docs/api/keras_nlp/modeling_layers/token_and_position_embedding#tokenandpositionembedding-class" >}})를 사용하여, 입력 토큰 ID를 처음에 임베딩합니다. +이 레이어는 (문장의 단어와 문장의 정수 위치를 위한) 두 가지 임베딩을 동시에 학습합니다. +출력 임베딩은 이 두 가지 임베딩의 합으로 제공됩니다. -Then we can add a series of [`keras_nlp.layers.TransformerEncoder`]({{< relref "/docs/api/keras_nlp/modeling_layers/transformer_encoder#transformerencoder-class" >}}) layers. These are the bread and butter of the Transformer model, using an attention mechanism to attend to different parts of the input sentence, followed by a multi-layer perceptron block. +그런 다음, 여러 개의 [`keras_nlp.layers.TransformerEncoder`]({{< relref "/docs/api/keras_nlp/modeling_layers/transformer_encoder#transformerencoder-class" >}}) 레이어를 추가할 수 있습니다. +이 레이어들은 트랜스포머 모델의 핵심으로, +입력 문장의 다른 부분을 주의(attend)하게 하는 어텐션 메커니즘과, 그 뒤의 멀티 레이어 퍼셉트론 블록을 사용합니다. -The output of this model will be a encoded vector per input token id. Unlike the bag-of-words model we used as a baseline, this model will embed each token accounting for the context in which it appeared. +이 모델의 출력은 입력 토큰 ID마다 인코딩된 벡터가 됩니다. +우리가 기준 성능으로 사용했던 bag-of-words 모델과 달리, +이 모델은 각 토큰을 해당 문맥에 맞게 임베딩합니다. ```python inputs = keras.Input(shape=(SEQ_LENGTH,), dtype="int32") -# Embed our tokens with a positional embedding. +# 위치 임베딩을 사용해 토큰을 임베딩합니다. embedding_layer = keras_nlp.layers.TokenAndPositionEmbedding( vocabulary_size=tokenizer.vocabulary_size(), sequence_length=SEQ_LENGTH, @@ -333,11 +380,11 @@ embedding_layer = keras_nlp.layers.TokenAndPositionEmbedding( ) outputs = embedding_layer(inputs) -# Apply layer normalization and dropout to the embedding. +# 임베딩에 레이어 정규화와 드롭아웃을 적용합니다. outputs = keras.layers.LayerNormalization(epsilon=NORM_EPSILON)(outputs) outputs = keras.layers.Dropout(rate=DROPOUT)(outputs) -# Add a number of encoder blocks +# 여러 개의 인코더 블록을 추가합니다. for i in range(NUM_LAYERS): outputs = keras_nlp.layers.TransformerEncoder( intermediate_dim=INTERMEDIATE_DIM, @@ -383,16 +430,24 @@ Model: "functional_3" {{% /details %}} -### Pretrain the Transformer +### 트랜스포머 사전 트레이닝 {#pretrain-the-transformer} -You can think of the `encoder_model` as it's own modular unit, it is the piece of our model that we are really interested in for our downstream task. However we still need to set up the encoder to train on the MaskedLM task; to do that we attach a [`keras_nlp.layers.MaskedLMHead`]({{< relref "/docs/api/keras_nlp/modeling_layers/masked_lm_head#maskedlmhead-class" >}}). +`encoder_model`을 독립된 모듈 단위로 생각할 수 있습니다. +이는 후속 작업에서 우리가 관심을 갖는 모델의 주요 부분입니다. +그러나 여전히 MaskedLM 작업에 대해 트레이닝할 수 있도록 설정해야 합니다. +이를 위해 [`keras_nlp.layers.MaskedLMHead`]({{< relref "/docs/api/keras_nlp/modeling_layers/masked_lm_head#maskedlmhead-class" >}})를 연결합니다. -This layer will take as one input the token encodings, and as another the positions we masked out in the original input. It will gather the token encodings we masked, and transform them back in predictions over our entire vocabulary. +이 레이어는 하나의 입력으로 토큰 인코딩을, +다른 입력으로는 원본 입력에서 마스킹된 위치를 받습니다. +이 레이어는 마스킹된 토큰 인코딩을 수집하고, 이를 전체 어휘에 대한 예측으로 변환합니다. -With that, we are ready to compile and run pretraining. If you are running this in a Colab, note that this will take about an hour. Training Transformer is famously compute intensive, so even this relatively small Transformer will take some time. +이제 컴파일하고 사전 트레이닝을 실행할 준비가 되었습니다. +Colab에서 실행하는 경우, 약 한 시간이 소요될 수 있습니다. +트랜스포머 모델 트레이닝은 매우 많은 계산 리소스를 요구하는 작업으로, +상대적으로 작은 이 트랜스포머 모델도 시간이 꽤 걸릴 것입니다. ```python -# Create the pretraining model by attaching a masked language model head. +# 마스킹된 언어 모델 헤드를 연결하여 사전 트레이닝된 모델을 만듭니다. inputs = { "token_ids": keras.Input(shape=(SEQ_LENGTH,), dtype="int32", name="token_ids"), "mask_positions": keras.Input( @@ -400,18 +455,18 @@ inputs = { ), } -# Encode the tokens. +# 토큰을 인코딩합니다. encoded_tokens = encoder_model(inputs["token_ids"]) -# Predict an output word for each masked input token. -# We use the input token embedding to project from our encoded vectors to -# vocabulary logits, which has been shown to improve training efficiency. +# 마스크된 입력 토큰마다 출력 단어를 예측합니다. +# 입력 토큰 임베딩을 사용하여 인코딩된 벡터를 어휘 로짓으로 변환하는 것은, +# 트레이닝 효율성을 높이는 것으로 알려져 있습니다. outputs = keras_nlp.layers.MaskedLMHead( token_embedding=embedding_layer.token_embedding, activation="softmax", )(encoded_tokens, mask_positions=inputs["mask_positions"]) -# Define and compile our pretraining model. +# 사전 트레이닝 모델을 정의하고 컴파일합니다. pretraining_model = keras.Model(inputs, outputs) pretraining_model.compile( loss="sparse_categorical_crossentropy", @@ -420,14 +475,14 @@ pretraining_model.compile( jit_compile=True, ) -# Pretrain the model on our wiki text dataset. +# wiki 텍스트 데이터셋으로 모델을 사전 트레이닝합니다. pretraining_model.fit( pretrain_ds, validation_data=pretrain_val_ds, epochs=PRETRAINING_EPOCHS, ) -# Save this base model for further finetuning. +# 이후의 미세 조정을 위해 이 베이스 모델을 저장합니다. encoder_model.save("encoder_model.keras") ``` @@ -454,20 +509,23 @@ Epoch 8/8 {{% /details %}} -## Fine-tuning +## 미세 조정 {#fine-tuning} -After pretraining, we can now fine-tune our model on the `SST-2` dataset. We can leverage the ability of the encoder we build to predict on words in context to boost our performance on the downstream task. +사전 트레이닝 후, 이제 `SST-2` 데이터셋에서 모델을 미세 조정할 수 있습니다. +우리가 빌드한 인코더의 문맥에서 단어를 예측하는 능력을 활용하여, +다운스트림 작업에서 성능을 향상시킬 수 있습니다. -### Preprocess data for classification +### 분류를 위한 데이터 전처리 {#preprocess-data-for-classification} -Preprocessing for fine-tuning is much simpler than for our pretraining MaskedLM task. We just tokenize our input sentences and we are ready for training! +미세 조정을 위한 전처리는 사전 학습 MaskedLM 작업에 비해 훨씬 간단합니다. +입력 문장을 토큰화하면 바로 트레이닝할 준비가 됩니다! ```python def preprocess(sentences, labels): return tokenizer(sentences), labels -# We use prefetch() to pre-compute preprocessed batches on the fly on our CPU. +# prefetch()를 사용하여 CPU에서 전처리된 배치를 실시간으로 미리 계산합니다. finetune_ds = sst_train_ds.map( preprocess, num_parallel_calls=tf.data.AUTOTUNE ).prefetch(tf.data.AUTOTUNE) @@ -475,7 +533,7 @@ finetune_val_ds = sst_val_ds.map( preprocess, num_parallel_calls=tf.data.AUTOTUNE ).prefetch(tf.data.AUTOTUNE) -# Preview a single input example. +# 단일 입력 예제를 미리 확인합니다. print(finetune_val_ds.take(1).get_single_element()) ``` @@ -496,25 +554,28 @@ array([1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, {{% /details %}} -### Fine-tune the Transformer +### 트랜스포머 미세 조정 {#fine-tune-the-transformer} -To go from our encoded token output to a classification prediction, we need to attach another "head" to our Transformer model. We can afford to be simple here. We pool the encoded tokens together, and use a single dense layer to make a prediction. +인코딩된 토큰 출력을 분류 예측으로 전환하려면, +트랜스포머 모델에 또 다른 "헤드"를 붙여야 합니다. +여기서는 간단하게 접근할 수 있습니다. +인코딩된 토큰을 풀링한 후, 단일 dense 레이어를 사용하여 예측을 수행합니다. ```python -# Reload the encoder model from disk so we can restart fine-tuning from scratch. +# 디스크에서 인코더 모델을 다시 로드하여 처음부터 미세 조정을 시작합니다. encoder_model = keras.models.load_model("encoder_model.keras", compile=False) -# Take as input the tokenized input. +# 토큰화된 입력을 입력으로 받습니다. inputs = keras.Input(shape=(SEQ_LENGTH,), dtype="int32") -# Encode and pool the tokens. +# 토큰을 인코딩하고 풀링합니다. encoded_tokens = encoder_model(inputs) pooled_tokens = keras.layers.GlobalAveragePooling1D()(encoded_tokens[0]) -# Predict an output label. +# 출력 레이블을 예측합니다. outputs = keras.layers.Dense(1, activation="sigmoid")(pooled_tokens) -# Define and compile our fine-tuning model. +# 미세 조정 모델을 정의하고 컴파일합니다. finetuning_model = keras.Model(inputs, outputs) finetuning_model.compile( loss="binary_crossentropy", @@ -522,7 +583,7 @@ finetuning_model.compile( metrics=["accuracy"], ) -# Finetune the model for the SST-2 task. +# SST-2 작업에 대해 모델을 미세 조정합니다. finetuning_model.fit( finetune_ds, validation_data=finetune_val_ds, @@ -545,6 +606,13 @@ Epoch 3/3 {{% /details %}} -Pretraining was enough to boost our performance to 84%, and this is hardly the ceiling for Transformer models. You may have noticed during pretraining that our validation performance was still steadily increasing. Our model is still significantly undertrained. Training for more epochs, training a large Transformer, and training on more unlabeled text would all continue to boost performance significantly. +사전 트레이닝 만으로도 성능을 84%까지 끌어올렸으며, 이는 트랜스포머 모델의 성능 한계와는 거리가 멉니다. +사전 트레이닝 과정에서 검증 성능이 지속적으로 증가하는 것을 확인했을 것입니다. +모델은 여전히 충분히 트레이닝되지 않았습니다. +더 많은 에포크로 트레이닝하거나, 더 큰 트랜스포머 모델을 트레이닝하거나, +더 많은 레이블이 없는 텍스트에 대해 트레이닝하면 성능이 크게 향상될 것입니다. -One of the key goals of KerasNLP is to provide a modular approach to NLP model building. We have shown one approach to building a Transformer here, but KerasNLP supports an ever growing array of components for preprocessing text and building models. We hope it makes it easier to experiment on solutions to your natural language problems. +KerasNLP의 주요 목표 중 하나는 NLP 모델 빌드에 있어 모듈화된 접근 방식을 제공하는 것입니다. +이 예시에서는 트랜스포머를 구축하는 하나의 방법을 보여주었지만, +KerasNLP는 텍스트 전처리와 모델 구축을 위한 다양한 구성 요소들을 계속해서 지원하고 있습니다. +여러분이 자연어 처리 문제에 대한 솔루션을 실험하는 데 있어 더 쉽게 접근할 수 있도록 돕기를 바랍니다. diff --git a/content/korean/docs/guides/keras_nlp/upload/_index.md b/content/korean/docs/guides/keras_nlp/upload/_index.md index 06e9f222..c5f5c03c 100644 --- a/content/korean/docs/guides/keras_nlp/upload/_index.md +++ b/content/korean/docs/guides/keras_nlp/upload/_index.md @@ -1,6 +1,6 @@ --- -title: Uploading Models with KerasNLP -linkTitle: Uploading Models with KerasNLP +title: KerasNLP로 모델 업로드 +linkTitle: KerasNLP로 모델 업로드 toc: true weight: 3 type: docs @@ -11,22 +11,27 @@ type: docs **{{< t f_author >}}** [Samaneh Saadat](https://github.com/SamanehSaadat/), [Matthew Watson](https://github.com/mattdangerw/) **{{< t f_date_created >}}** 2024/04/29 **{{< t f_last_modified >}}** 2024/04/29 -**{{< t f_description >}}** An introduction on how to upload a fine-tuned KerasNLP model to model hubs. +**{{< t f_description >}}** 미세 조정된 KerasNLP 모델을 모델 허브에 업로드하는 방법에 대한 소개. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_nlp/upload.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_nlp/upload.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -Fine-tuning a machine learning model can yield impressive results for specific tasks. Uploading your fine-tuned model to a model hub allows you to share it with the broader community. By sharing your models, you'll enhance accessibility for other researchers and developers, making your contributions an integral part of the machine learning landscape. This can also streamline the integration of your model into real-world applications. +머신 러닝 모델을 특정 작업에 맞게 파인 튜닝하면 인상적인 결과를 얻을 수 있습니다. +파인 튜닝된 모델을 모델 허브에 업로드하면 더 넓은 커뮤니티와 공유할 수 있으며, +이를 통해 다른 연구자들과 개발자들이 접근성을 높일 수 있습니다. +또한, 이를 통해 실세계 애플리케이션에 모델을 통합하는 과정이 간소화될 수 있습니다. -This guide walks you through how to upload your fine-tuned models to popular model hubs such as [Kaggle Models](https://www.kaggle.com/models) and [Hugging Face Hub](https://huggingface.co/models). +이 가이드에서는 파인 튜닝된 모델을 [Kaggle Models](https://www.kaggle.com/models)와 +[Hugging Face Hub](https://huggingface.co/models)와 같은 인기 있는 모델 허브에 업로드하는 방법을 설명합니다. -## Setup +## 셋업 {#setup} -Let's start by installing and importing all the libraries we need. We use KerasNLP for this guide. +우선 필요한 라이브러리를 설치하고 import 합니다. +이 가이드에서는 KerasNLP를 사용합니다. ```python !pip install -q --upgrade keras-nlp huggingface-hub kagglehub @@ -40,9 +45,9 @@ os.environ["KERAS_BACKEND"] = "jax" import keras_nlp ``` -## Data +## 데이터 {#data} -We can use the IMDB reviews dataset for this guide. Let's load the dataset from `tensorflow_dataset`. +이 가이드에서는 IMDB 리뷰 데이터셋을 사용합니다. `tensorflow_dataset`에서 데이터셋을 불러옵니다. ```python import tensorflow_datasets as tfds @@ -55,19 +60,24 @@ imdb_train, imdb_test = tfds.load( ) ``` -We only use a small subset of the training samples to make the guide run faster. However, if you need a higher quality model, consider using a larger number of training samples. +가이드 실행 속도를 높이기 위해 트레이닝 샘플 중 일부만 사용합니다. +하지만, 더 높은 품질의 모델이 필요하다면, 더 많은 트레이닝 샘플을 사용하는 것이 좋습니다. ```python imdb_train = imdb_train.take(100) ``` -## Task Upload +## 작업 업로드 {#task-upload} -A [`keras_nlp.models.Task`]({{< relref "/docs/api/keras_nlp/base_classes/task#task-class" >}}), wraps a [`keras_nlp.models.Backbone`]({{< relref "/docs/api/keras_nlp/base_classes/backbone#backbone-class" >}}) and a [`keras_nlp.models.Preprocessor`]({{< relref "/docs/api/keras_nlp/base_classes/preprocessor#preprocessor-class" >}}) to create a model that can be directly used for training, fine-tuning, and prediction for a given text problem. In this section, we explain how to create a `Task`, fine-tune and upload it to a model hub. +[`keras_nlp.models.Task`]({{< relref "/docs/api/keras_nlp/base_classes/task#task-class" >}})는 [`keras_nlp.models.Backbone`]({{< relref "/docs/api/keras_nlp/base_classes/backbone#backbone-class" >}})과 [`keras_nlp.models.Preprocessor`]({{< relref "/docs/api/keras_nlp/base_classes/preprocessor#preprocessor-class" >}})를 결합하여, +텍스트 문제에 대해 직접 트레이닝, 파인 튜닝 및 예측에 사용할 수 있는 모델을 생성합니다. +이 섹션에서는, `Task`를 생성하고, 파인 튜닝하여 모델 허브에 업로드하는 방법을 설명합니다. -### Load Model +### 모델 로드 {#load-model} -If you want to build a Causal LM based on a base model, simply call [`keras_nlp.models.CausalLM.from_preset`]({{< relref "/docs/api/keras_nlp/base_classes/causal_lm#from_preset-method" >}}) and pass a built-in preset identifier. +베이스 모델을 기반으로 Causal LM을 구축하려면, +[`keras_nlp.models.CausalLM.from_preset`]({{< relref "/docs/api/keras_nlp/base_classes/causal_lm#from_preset-method" >}})를 호출하고, +미리 설정된 식별자(built-in preset identifier)를 전달하면 됩니다. ```python causal_lm = keras_nlp.models.CausalLM.from_preset("gpt2_base_en") @@ -83,15 +93,16 @@ Downloading from https://www.kaggle.com/api/v1/models/keras/gpt2/keras/gpt2_base {{% /details %}} -### Fine-tune Model +### 모델 미세 조정 {#fine-tune-model} -After loading the model, you can call `.fit()` on the model to fine-tune it. Here, we fine-tune the model on the IMDB reviews which makes the model movie domain-specific. +모델을 불러온 후, `.fit()`을 호출하여 파인 튜닝할 수 있습니다. +여기에서는 IMDB 리뷰에 모델을 파인 튜닝하여 모델을 영화 도메인에 맞게 최적화합니다. ```python -# Drop labels and keep the review text only for the Causal LM. +# Causal LM을 위해 레이블을 제거하고 리뷰 텍스트만 유지합니다. imdb_train_reviews = imdb_train.map(lambda x, y: x) -# Fine-tune the Causal LM. +# Causal LM을 파인 튜닝합니다. causal_lm.fit(imdb_train_reviews) ``` @@ -103,16 +114,16 @@ causal_lm.fit(imdb_train_reviews) {{% /details %}} -### Save the Model Locally +### 모델을 로컬에 저장하기 {#save-the-model-locally} -To upload a model, you need to first save the model locally using `save_to_preset`. +모델을 업로드하려면, 먼저 `save_to_preset`을 사용하여 모델을 로컬에 저장해야 합니다. ```python preset_dir = "./gpt2_imdb" causal_lm.save_to_preset(preset_dir) ``` -Let's see the saved files. +저장된 파일을 확인해 봅시다. ```python os.listdir(preset_dir) @@ -132,30 +143,43 @@ os.listdir(preset_dir) {{% /details %}} -#### Load a Locally Saved Model +#### 로컬에 저장된 모델 불러오기 {#load-a-locally-saved-model} -A model that is saved to a local preset can be loaded using `from_preset`. What you save in, is what you get back out. +로컬에 저장된 프리셋 모델은 `from_preset`을 사용하여 불러올 수 있습니다. +저장된 그대로 불러올 수 있습니다. ```python causal_lm = keras_nlp.models.CausalLM.from_preset(preset_dir) ``` -You can also load the [`keras_nlp.models.Backbone`]({{< relref "/docs/api/keras_nlp/base_classes/backbone#backbone-class" >}}) and `keras_nlp.models.Tokenizer` objects from this preset directory. Note that these objects are equivalent to `causal_lm.backbone` and `causal_lm.preprocessor.tokenizer` above. +또한 [`keras_nlp.models.Backbone`]({{< relref "/docs/api/keras_nlp/base_classes/backbone#backbone-class" >}}) 및 `keras_nlp.models.Tokenizer` 객체를 +프리셋 디렉토리에서 불러올 수 있습니다. +이 객체들은 위에서 사용한 `causal_lm.backbone` 및 +`causal_lm.preprocessor.tokenizer`와 동일합니다. ```python backbone = keras_nlp.models.Backbone.from_preset(preset_dir) tokenizer = keras_nlp.models.Tokenizer.from_preset(preset_dir) ``` -### Upload the Model to a Model Hub +### 모델 허브에 모델 업로드 {#upload-the-model-to-a-model-hub} -After saving a preset to a directory, this directory can be uploaded to a model hub such as Kaggle or Hugging Face directly from the KerasNLP library. To upload the model to Kaggle, the URI must start with `kaggle://` and to upload to Hugging Face, it should start with `hf://`. +프리셋을 디렉토리에 저장한 후, +이 디렉토리는 KerasNLP 라이브러리를 통해 +Kaggle 또는 Hugging Face와 같은 모델 허브에 직접 업로드할 수 있습니다. +Kaggle에 모델을 업로드하려면 URI가 `kaggle://`로 시작해야 하고, +Hugging Face에 업로드하려면 `hf://`로 시작해야 합니다. -#### Upload to Kaggle +#### Kaggle에 업로드 {#upload-to-kaggle} -To upload a model to Kaggle, first, we need to authenticate with Kaggle. This can in one of the following ways: 1. Set environment variables `KAGGLE_USERNAME` and `KAGGLE_KEY`. 2. Provide a local `~/.kaggle/kaggle.json`. 3. Call `kagglehub.login()`. +Kaggle에 모델을 업로드하려면 먼저 Kaggle에 인증해야 합니다. +다음 중 하나의 방법을 사용할 수 있습니다: -Let's make sure we are logged in before continuing. +1. 환경 변수 `KAGGLE_USERNAME`과 `KAGGLE_KEY`를 설정합니다. +2. 로컬에 `~/.kaggle/kaggle.json` 파일을 제공합니다. +3. `kagglehub.login()`을 호출합니다. + +계속하기 전에 로그인 상태를 확인해 봅시다. ```python import kagglehub @@ -164,9 +188,12 @@ if "KAGGLE_USERNAME" not in os.environ or "KAGGLE_KEY" not in os.environ: kagglehub.login() ``` -To upload a model we can use `keras_nlp.upload_preset(uri, preset_dir)` API where `uri` has the format of `kaggle:////Keras/` for uploading to Kaggle and `preset_dir` is the directory that the model is saved in. +모델을 업로드하려면 `keras_nlp.upload_preset(uri, preset_dir)` API를 사용할 수 있으며, +Kaggle에 업로드할 경우 `uri`의 형식은 +`kaggle:////Keras/`입니다. +`preset_dir`은 모델이 저장된 디렉토리입니다. -Running the following uploads the model that is saved in `preset_dir` to Kaggle: +다음 명령을 실행하면 `preset_dir`에 저장된 모델을 Kaggle에 업로드할 수 있습니다: ```python kaggle_username = kagglehub.whoami()["username"] @@ -191,11 +218,15 @@ Your model instance version has been created. {{% /details %}} -#### Upload to Hugging Face +#### Hugging Face에 업로드 {#upload-to-hugging-face} + +Hugging Face에 모델을 업로드하려면 먼저 Hugging Face에 인증해야 합니다. +다음 중 하나의 방법을 사용할 수 있습니다: -To upload a model to Hugging Face, first, we need to authenticate with Hugging Face. This can in one of the following ways: 1. Set environment variables `HF_USERNAME` and `HF_TOKEN`. 2. Call `huggingface_hub.notebook_login()`. +1. 환경 변수 `HF_USERNAME`과 `HF_TOKEN`을 설정합니다. +2. `huggingface_hub.notebook_login()`을 호출합니다. -Let's make sure we are logged in before coninuing. +계속하기 전에 로그인 상태를 확인해 봅시다. ```python import huggingface_hub @@ -204,9 +235,11 @@ if "HF_USERNAME" not in os.environ or "HF_TOKEN" not in os.environ: huggingface_hub.notebook_login() ``` -`keras_nlp.upload_preset(uri, preset_dir)` can be used to upload a model to Hugging Face if `uri` has the format of `kaggle:///`. +`keras_nlp.upload_preset(uri, preset_dir)`는 +Hugging Face에 모델을 업로드할 때 사용할 수 있으며, +이 경우 `uri` 형식은 `hf:///`입니다. -Running the following uploads the model that is saved in `preset_dir` to Hugging Face: +다음 명령을 실행하면 `preset_dir`에 저장된 모델을 Hugging Face에 업로드할 수 있습니다: ```python hf_username = huggingface_hub.whoami()["name"] @@ -214,9 +247,9 @@ hf_uri = f"hf://{hf_username}/gpt2_imdb" keras_nlp.upload_preset(hf_uri, preset_dir) ``` -### Load a User Uploaded Model +### 사용자가 업로드한 모델 불러오기 {#load-a-user-uploaded-model} -After verifying that the model is uploaded to Kaggle, we can load the model by calling `from_preset`. +Kaggle에 모델이 업로드된 것을 확인한 후, `from_preset`을 호출하여 모델을 불러올 수 있습니다. ```python causal_lm = keras_nlp.models.CausalLM.from_preset( @@ -224,30 +257,32 @@ causal_lm = keras_nlp.models.CausalLM.from_preset( ) ``` -We can also load the model uploaded to Hugging Face by calling `from_preset`. +Hugging Face에 업로드된 모델도 `from_preset`을 호출하여 불러올 수 있습니다. ```python causal_lm = keras_nlp.models.CausalLM.from_preset(f"hf://{hf_username}/gpt2_imdb") ``` -## Classifier Upload +## 분류기 업로드 {#classifier-upload} -Uploading a classifier model is similar to Causal LM upload. To upload the fine-tuned model, first, the model should be saved to a local directory using `save_to_preset` API and then it can be uploaded via [`keras_nlp.upload_preset`]({{< relref "/docs/api/keras_nlp/base_classes/upload_preset#upload_preset-function" >}}). +분류기 모델 업로드는 Causal LM 업로드와 유사합니다. +미세 조정된 모델을 업로드하려면, 먼저 `save_to_preset` API를 사용하여 모델을 로컬 디렉토리에 저장한 후, +[`keras_nlp.upload_preset`]({{< relref "/docs/api/keras_nlp/base_classes/upload_preset#upload_preset-function" >}})를 통해 업로드할 수 있습니다. ```python -# Load the base model. +# 베이스 모델 로드. classifier = keras_nlp.models.Classifier.from_preset( "bert_tiny_en_uncased", num_classes=2 ) -# Fine-tune the classifier. +# 분류기 미세 조정. classifier.fit(imdb_train) -# Save the model to a local preset directory. +# 로컬 프리셋 디렉토리에 모델 저장. preset_dir = "./bert_tiny_imdb" classifier.save_to_preset(preset_dir) -# Upload to Kaggle. +# Kaggle에 업로드. keras_nlp.upload_preset( f"kaggle://{kaggle_username}/bert/keras/bert_tiny_imdb", preset_dir ) @@ -274,7 +309,7 @@ Your model instance version has been created. {{% /details %}} -After verifying that the model is uploaded to Kaggle, we can load the model by calling `from_preset`. +모델이 Kaggle에 업로드된 것을 확인한 후, `from_preset`을 호출하여 모델을 불러올 수 있습니다. ```python classifier = keras_nlp.models.Classifier.from_preset( diff --git a/content/korean/docs/guides/keras_tuner/_index.md b/content/korean/docs/guides/keras_tuner/_index.md index fd7acb5d..53f8c621 100644 --- a/content/korean/docs/guides/keras_tuner/_index.md +++ b/content/korean/docs/guides/keras_tuner/_index.md @@ -1,6 +1,6 @@ --- -title: Hyperparameter Tuning -linkTitle: Hyperparameter Tuning +title: 하이퍼파라미터 튜닝 +linkTitle: 하이퍼파라미터 튜닝 toc: true weight: 20 type: docs @@ -8,13 +8,8 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -These guides cover KerasTuner best practices. +이 가이드들은 KerasTuner의 모범 사례를 다룹니다. -## Available guides +## 모든 컨텐츠 -- [Getting started with KerasTuner]({{< relref "/docs/guides/keras_tuner/getting_started" >}}) -- [Distributed hyperparameter tuning with KerasTuner]({{< relref "/docs/guides/keras_tuner/distributed_tuning" >}}) -- [Tune hyperparameters in your custom training loop]({{< relref "/docs/guides/keras_tuner/custom_tuner" >}}) -- [Visualize the hyperparameter tuning process]({{< relref "/docs/guides/keras_tuner/visualize_tuning" >}}) -- [Handling failed trials in KerasTuner]({{< relref "/docs/guides/keras_tuner/failed_trials" >}}) -- [Tailor the search space]({{< relref "/docs/guides/keras_tuner/tailor_the_search_space" >}}) +{{< default-section-cards-list-recursive >}} diff --git a/content/korean/docs/guides/keras_tuner/custom_tuner/_index.md b/content/korean/docs/guides/keras_tuner/custom_tuner/_index.md index 7e6b8c86..2d85f215 100644 --- a/content/korean/docs/guides/keras_tuner/custom_tuner/_index.md +++ b/content/korean/docs/guides/keras_tuner/custom_tuner/_index.md @@ -1,6 +1,6 @@ --- -title: Tune hyperparameters in your custom training loop -linkTitle: Tune hyperparameters in your custom training loop +title: 당신의 커스텀 트레이닝 루프에서 하이퍼파라미터 튜닝 +linkTitle: 트레이닝 하이퍼파라미터 튜닝 toc: true weight: 3 type: docs @@ -8,10 +8,10 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Tom O'Malley, Haifeng Jin +**{{< t f_author >}}** Tom O'Malley, Haifeng Jin **{{< t f_date_created >}}** 2019/10/28 **{{< t f_last_modified >}}** 2022/01/12 -**{{< t f_description >}}** Use `HyperModel.fit()` to tune training hyperparameters (such as batch size). +**{{< t f_description >}}** `HyperModel.fit()`을 사용하여 트레이닝 하이퍼파라미터(예: 배치 크기)를 튜닝합니다. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_tuner/custom_tuner.ipynb" title="Colab" tag="Colab" tagType="warning">}} @@ -22,20 +22,27 @@ type: docs !pip install keras-tuner -q ``` -## Introduction +## 소개 {#introduction} -The `HyperModel` class in KerasTuner provides a convenient way to define your search space in a reusable object. You can override `HyperModel.build()` to define and hypertune the model itself. To hypertune the training process (e.g. by selecting the proper batch size, number of training epochs, or data augmentation setup), you can override `HyperModel.fit()`, where you can access: +KerasTuner의 `HyperModel` 클래스는 재사용 가능한 객체에서 검색 공간을 정의하는 편리한 방법을 제공합니다. +`HyperModel.build()`를 재정의하여 모델 자체를 정의하고 하이퍼튜닝할 수 있습니다. +트레이닝 과정에서 하이퍼튜닝을 하려면(예: 적절한 배치 크기, 트레이닝 에포크 수 또는 데이터 보강 설정을 선택하여), +`HyperModel.fit()`을 재정의하여 다음에 접근할 수 있습니다. -- The `hp` object, which is an instance of [`keras_tuner.HyperParameters`]({{< relref "/docs/api/keras_tuner/hyperparameters#hyperparameters-class" >}}) -- The model built by `HyperModel.build()` +- `hp` 객체: [`keras_tuner.HyperParameters`]({{< relref "/docs/api/keras_tuner/hyperparameters#hyperparameters-class" >}})의 인스턴스 +- `HyperModel.build()`에 의해 빌드된 모델 -A basic example is shown in the "tune model training" section of [Getting Started with KerasTuner]({{< relref "/docs/guides/keras_tuner/getting_started/#tune-model-training" >}}). +기본 예시는 [KerasTuner 시작하기의 "모델 트레이닝 튜닝하기" 섹션]({{< relref "/docs/guides/keras_tuner/getting_started/#tune-model-training" >}})에서 확인할 수 있습니다. -## Tuning the custom training loop +## 커스텀 트레이닝 루프 튜닝 {#tuning-the-custom-training-loop} -In this guide, we will subclass the `HyperModel` class and write a custom training loop by overriding `HyperModel.fit()`. For how to write a custom training loop with Keras, you can refer to the guide [Writing a training loop from scratch]({{< relref "/docs/guides/writing_a_custom_training_loop_in_tensorflow" >}}). +이 가이드에서는, `HyperModel` 클래스를 서브클래싱하고 `HyperModel.fit()`을 재정의하여, +커스텀 트레이닝 루프를 작성합니다. +Keras에서 커스텀 트레이닝 루프를 작성하는 방법은, +{{< titledRelref "/docs/guides/writing_a_custom_training_loop_in_tensorflow" >}} 가이드를 참조하십시오. -First, we import the libraries we need, and we create datasets for training and validation. Here, we just use some random data for demonstration purposes. +먼저 필요한 라이브러리를 import 하고, 트레이닝 및 검증용 데이터셋을 생성합니다. +여기서는 시연 목적으로 랜덤 데이터를 사용합니다. ```python import keras_tuner @@ -50,34 +57,47 @@ x_val = np.random.rand(1000, 28, 28, 1) y_val = np.random.randint(0, 10, (1000, 1)) ``` -Then, we subclass the `HyperModel` class as `MyHyperModel`. In `MyHyperModel.build()`, we build a simple Keras model to do image classification for 10 different classes. `MyHyperModel.fit()` accepts several arguments. Its signature is shown below: +그런다음, `MyHyperModel`로 `HyperModel` 클래스를 서브클래싱합니다. +`MyHyperModel.build()`에서는 10개의 다른 클래스를 분류하기 위한 간단한 Keras 모델을 빌드합니다. +`MyHyperModel.fit()`은 여러 인수를 수락합니다. 그 시그니처는 아래와 같습니다. ```python def fit(self, hp, model, x, y, validation_data, callbacks=None, **kwargs): ``` -- The `hp` argument is for defining the hyperparameters. -- The `model` argument is the model returned by `MyHyperModel.build()`. -- `x`, `y`, and `validation_data` are all custom-defined arguments. We will pass our data to them by calling `tuner.search(x=x, y=y, validation_data=(x_val, y_val))` later. You can define any number of them and give custom names. -- The `callbacks` argument was intended to be used with `model.fit()`. KerasTuner put some helpful Keras callbacks in it, for example, the callback for checkpointing the model at its best epoch. +- `hp` 인수는 하이퍼파라미터를 정의하는 데 사용됩니다. +- `model` 인수는 `MyHyperModel.build()`에서 반환된 모델입니다. +- `x`, `y`, 및 `validation_data`는 모두 커스텀 정의된 인수입니다. + 나중에 `tuner.search(x=x, y=y, validation_data=(x_val, y_val))`를 호출하여, + 데이터를 이들에게 전달할 것입니다. + 원하는 만큼 인수를 정의하고, 커스텀 이름을 부여할 수 있습니다. +- `callbacks` 인수는 `model.fit()`과 함께 사용되도록 의도되었습니다. + KerasTuner는 체크포인팅(모델의 최상의 에포크에서 모델 저장)과 같은 유용한 Keras 콜백을 제공합니다. -We will manually call the callbacks in the custom training loop. Before we can call them, we need to assign our model to them with the following code so that they have access to the model for checkpointing. +우리는 커스텀 트레이닝 루프에서 콜백을 수동으로 호출할 것입니다. +콜백을 호출하기 전에, 다음 코드를 통해 모델을 할당해야 체크포인팅을 위해 콜백에서 모델에 액세스할 수 있습니다. ```python for callback in callbacks: callback.model = model ``` -In this example, we only called the `on_epoch_end()` method of the callbacks to help us checkpoint the model. You may also call other callback methods if needed. If you don't need to save the model, you don't need to use the callbacks. +이 예에서는, 모델을 체크포인팅하기 위해 콜백의 `on_epoch_end()` 메서드만 호출했습니다. +필요에 따라, 다른 콜백 메서드도 호출할 수 있습니다. +모델을 저장할 필요가 없다면, 콜백을 사용할 필요는 없습니다. -In the custom training loop, we tune the batch size of the dataset as we wrap the NumPy data into a [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset). Note that you can tune any preprocessing steps here as well. We also tune the learning rate of the optimizer. +커스텀 트레이닝 루프에서는, `tf.data.Dataset`으로 NumPy 데이터를 래핑할 때 데이터셋의 배치 크기를 튜닝합니다. +이 단계에서 다른 전처리 단계를 튜닝할 수도 있습니다. +또한 옵티마이저의 학습률도 튜닝합니다. -We will use the validation loss as the evaluation metric for the model. To compute the mean validation loss, we will use `keras.metrics.Mean()`, which averages the validation loss across the batches. We need to return the validation loss for the tuner to make a record. +우리는 검증 손실을 모델 평가 지표로 사용할 것입니다. +배치마다 검증 손실을 평균화하기 위해, `keras.metrics.Mean()`을 사용합니다. +튜너가 기록을 남기기 위해 검증 손실 값을 반환해야 합니다. ```python class MyHyperModel(keras_tuner.HyperModel): def build(self, hp): - """Builds a convolutional model.""" + """컨볼루션 모델을 빌드합니다.""" inputs = keras.Input(shape=(28, 28, 1)) x = keras.layers.Flatten()(inputs) x = keras.layers.Dense( @@ -87,7 +107,7 @@ class MyHyperModel(keras_tuner.HyperModel): return keras.Model(inputs=inputs, outputs=outputs) def fit(self, hp, model, x, y, validation_data, callbacks=None, **kwargs): - # Convert the datasets to tf.data.Dataset. + # 데이터셋을 tf.data.Dataset으로 변환합니다. batch_size = hp.Int("batch_size", 32, 128, step=32, default=64) train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch( batch_size @@ -96,69 +116,72 @@ class MyHyperModel(keras_tuner.HyperModel): batch_size ) - # Define the optimizer. + # 옵티마이저 정의. optimizer = keras.optimizers.Adam( hp.Float("learning_rate", 1e-4, 1e-2, sampling="log", default=1e-3) ) loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True) - # The metric to track validation loss. + # 검증 손실을 추적할 메트릭. epoch_loss_metric = keras.metrics.Mean() - # Function to run the train step. + # 트레이닝 단계를 실행하는 함수. @tf.function def run_train_step(images, labels): with tf.GradientTape() as tape: logits = model(images) loss = loss_fn(labels, logits) - # Add any regularization losses. + # 정규화 손실 추가. if model.losses: loss += tf.math.add_n(model.losses) gradients = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(gradients, model.trainable_variables)) - # Function to run the validation step. + # 검증 단계를 실행하는 함수. @tf.function def run_val_step(images, labels): logits = model(images) loss = loss_fn(labels, logits) - # Update the metric. + # 메트릭 업데이트. epoch_loss_metric.update_state(loss) - # Assign the model to the callbacks. + # 모델을 콜백에 할당합니다. for callback in callbacks: callback.set_model(model) - # Record the best validation loss value + # 최상의 검증 손실 값을 기록. best_epoch_loss = float("inf") - # The custom training loop. + # 커스텀 트레이닝 루프. for epoch in range(2): print(f"Epoch: {epoch}") - # Iterate the training data to run the training step. + # 트레이닝 데이터를 반복하면서, 트레이닝 단계를 실행. for images, labels in train_ds: run_train_step(images, labels) - # Iterate the validation data to run the validation step. + # 검증 데이터를 반복하면서, 검증 단계를 실행. for images, labels in validation_data: run_val_step(images, labels) - # Calling the callbacks after epoch. + # 에포크가 끝난 후 콜백 호출. epoch_loss = float(epoch_loss_metric.result().numpy()) for callback in callbacks: - # The "my_metric" is the objective passed to the tuner. + # "my_metric"은 튜너에 전달된 objective 입니다. callback.on_epoch_end(epoch, logs={"my_metric": epoch_loss}) epoch_loss_metric.reset_state() print(f"Epoch loss: {epoch_loss}") best_epoch_loss = min(best_epoch_loss, epoch_loss) - # Return the evaluation metric value. + # 평가 메트릭 값을 반환. return best_epoch_loss ``` -Now, we can initialize the tuner. Here, we use `Objective("my_metric", "min")` as our metric to be minimized. The objective name should be consistent with the one you use as the key in the `logs` passed to the 'on_epoch_end()' method of the callbacks. The callbacks need to use this value in the `logs` to find the best epoch to checkpoint the model. +이제 튜너를 초기화할 수 있습니다. +여기에서는, 최소화할 메트릭으로 `Objective("my_metric", "min")`을 사용합니다. +목표 이름은 콜백의 `on_epoch_end()` 메서드에 전달된 `logs`에서 사용하는 키와 일치해야 합니다. +콜백은 `logs`의 이 값을 사용하여 최상의 에포크를 찾아 모델을 체크포인팅합니다. ```python tuner = keras_tuner.RandomSearch( @@ -171,7 +194,7 @@ tuner = keras_tuner.RandomSearch( ) ``` -We start the search by passing the arguments we defined in the signature of `MyHyperModel.fit()` to `tuner.search()`. +`MyHyperModel.fit()`의 서명에서 정의한 인수를 `tuner.search()`에 전달하여 검색을 시작합니다. ```python tuner.search(x=x_train, y=y_train, validation_data=(x_val, y_val)) @@ -191,7 +214,7 @@ Total elapsed time: 00h 00m 04s {{% /details %}} -Finally, we can retrieve the results. +마지막으로, 결과를 검색할 수 있습니다. ```python best_hps = tuner.get_best_hyperparameters()[0] @@ -227,6 +250,10 @@ Model: "functional_1" {{% /details %}} -In summary, to tune the hyperparameters in your custom training loop, you just override `HyperModel.fit()` to train the model and return the evaluation results. With the provided callbacks, you can easily save the trained models at their best epochs and load the best models later. +요약하자면, 커스텀 트레이닝 루프에서 하이퍼파라미터를 튜닝하려면, +`HyperModel.fit()`을 오버라이드하여 모델을 트레이닝하고 평가 결과를 반환하면 됩니다. +제공된 콜백을 사용하면, 최상의 에포크에서 트레이닝된 모델을 쉽게 저장하고, +나중에 최상의 모델을 로드할 수 있습니다. -To find out more about the basics of KerasTuner, please see [Getting Started with KerasTuner]({{< relref "/docs/guides/keras_tuner/getting_started" >}}). +KerasTuner의 기본 사항에 대해 자세히 알아보려면, +[KerasTuner로 시작하기]({{< relref "/docs/guides/keras_tuner/getting_started" >}})를 참조하세요. diff --git a/content/korean/docs/guides/keras_tuner/distributed_tuning/_index.md b/content/korean/docs/guides/keras_tuner/distributed_tuning/_index.md index 0e6d2c2e..ab850d82 100644 --- a/content/korean/docs/guides/keras_tuner/distributed_tuning/_index.md +++ b/content/korean/docs/guides/keras_tuner/distributed_tuning/_index.md @@ -1,6 +1,6 @@ --- -title: Distributed hyperparameter tuning -linkTitle: Distributed hyperparameter tuning with KerasTuner +title: KerasTuner로 분산 하이퍼파라미터 튜닝 +linkTitle: 분산 하이퍼파라미터 튜닝 toc: true weight: 2 type: docs @@ -8,10 +8,10 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Tom O'Malley, Haifeng Jin +**{{< t f_author >}}** Tom O'Malley, Haifeng Jin **{{< t f_date_created >}}** 2019/10/24 **{{< t f_last_modified >}}** 2021/06/02 -**{{< t f_description >}}** Tuning the hyperparameters of the models with multiple GPUs and multiple machines. +**{{< t f_description >}}** 모델의 하이퍼파라미터를 다중 GPU 및 다중 머신에서 튜닝하기. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_tuner/distributed_tuning.ipynb" title="Colab" tag="Colab" tagType="warning">}} @@ -22,27 +22,40 @@ type: docs !pip install keras-tuner -q ``` -## Introduction +## 소개 {#introduction} -KerasTuner makes it easy to perform distributed hyperparameter search. No changes to your code are needed to scale up from running single-threaded locally to running on dozens or hundreds of workers in parallel. Distributed KerasTuner uses a chief-worker model. The chief runs a service to which the workers report results and query for the hyperparameters to try next. The chief should be run on a single-threaded CPU instance (or alternatively as a separate process on one of the workers). +KerasTuner는 분산된 하이퍼파라미터 검색을 쉽게 수행할 수 있도록 해줍니다. +코드를 변경하지 않고도 로컬에서 단일 스레드로 실행하는 것에서, +수십 또는 수백 개의 작업자(worker)에서 병렬로 실행하는 것으로 확장할 수 있습니다. +분산된 KerasTuner는 chief-worker 모델을 사용합니다. +Chief는 서비스 역할을 하며, +worker들은 결과를 보고하고 다음으로 시도할 하이퍼파라미터를 요청합니다. +Chief는 단일 스레드 CPU 인스턴스에서 실행해야 하며, +대안적으로는 worker 중 하나에서 별도의 프로세스로 실행할 수 있습니다. -### Configuring distributed mode +### 분산 모드 구성 {#configuring-distributed-mode} -Configuring distributed mode for KerasTuner only requires setting three environment variables: +KerasTuner의 분산 모드를 구성하려면, 세 가지 환경 변수를 설정하기만 하면 됩니다: -**KERASTUNER_TUNER_ID**: This should be set to "chief" for the chief process. Other workers should be passed a unique ID (by convention, "tuner0", "tuner1", etc). +- **KERASTUNER_TUNER_ID**: + - Chief 프로세스에는 "chief"로 설정해야 합니다. + - 다른 worker에는 고유한 ID가 부여되어야 합니다. (관례적으로 "tuner0", "tuner1" 등) +- **KERASTUNER_ORACLE_IP**: + - Chief 서비스가 실행될 IP 주소 또는 호스트명을 설정합니다. + - 모든 worker는 이 주소를 resolve하고 접근할 수 있어야 합니다. +- **KERASTUNER_ORACLE_PORT**: -**KERASTUNER_ORACLE_IP**: The IP address or hostname that the chief service should run on. All workers should be able to resolve and access this address. + - Chief 서비스가 실행될 포트를 설정합니다. + - 이 포트는 다른 worker들이 접근할 수 있는 포트여야 하며, 자유롭게 선택할 수 있습니다. + - 인스턴스들은 [gRPC](https://www.grpc.io) 프로토콜을 통해 통신합니다. -**KERASTUNER_ORACLE_PORT**: The port that the chief service should run on. This can be freely chosen, but must be a port that is accessible to the other workers. Instances communicate via the [gRPC](https://www.grpc.io) protocol. +모든 worker에서 동일한 코드를 실행할 수 있습니다. 분산 모드와 관련된 추가 고려 사항은 다음과 같습니다: -The same code can be run on all workers. Additional considerations for distributed mode are: +- 모든 worker는 결과를 기록할 수 있는 중앙화된 파일 시스템에 접근할 수 있어야 합니다. +- 모든 worker는 튜닝에 필요한 트레이닝 및 검증 데이터를 사용할 수 있어야 합니다. +- 내결함성을 지원하기 위해, `overwrite`는 `Tuner.__init__`에서 `False`로 유지해야 합니다. (기본값은 `False`입니다) -- All workers should have access to a centralized file system to which they can write their results. -- All workers should be able to access the necessary training and validation data needed for tuning. -- To support fault-tolerance, `overwrite` should be kept as `False` in `Tuner.__init__` (`False` is the default). - -Example bash script for chief service (sample code for `run_tuning.py` at bottom of page): +Chief 서비스에 대한 예시 bash 스크립트 (`run_tuning.py`의 샘플 코드 하단 참고): ```shell export KERASTUNER_TUNER_ID="chief" @@ -51,7 +64,7 @@ export KERASTUNER_ORACLE_PORT="8000" python run_tuning.py ``` -Example bash script for worker: +worker들에 대한 예시 bash 스크립트: ```shell export KERASTUNER_TUNER_ID="tuner0" @@ -60,13 +73,26 @@ export KERASTUNER_ORACLE_PORT="8000" python run_tuning.py ``` -### Data parallelism with [`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute) +### [`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute)로 데이터 병렬 처리 {#tfdistribute} -KerasTuner also supports data parallelism via [tf.distribute](https://www.tensorflow.org/tutorials/distribute/keras). Data parallelism and distributed tuning can be combined. For example, if you have 10 workers with 4 GPUs on each worker, you can run 10 parallel trials with each trial training on 4 GPUs by using [tf.distribute.MirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy). You can also run each trial on TPUs via [tf.distribute.TPUStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/experimental/TPUStrategy). Currently [tf.distribute.MultiWorkerMirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/experimental/MultiWorkerMirroredStrategy) is not supported, but support for this is on the roadmap. +KerasTuner는 [tf.distribute](https://www.tensorflow.org/tutorials/distribute/keras)를 통해, +데이터 병렬 처리도 지원합니다. +데이터 병렬 처리와 분산 튜닝을 결합할 수 있습니다. +예를 들어, 4개의 GPU가 있는 10개의 worker가 있을 때, +각 worker가 4개의 GPU에서 학습하는 10개의 병렬 실험을 실행할 수 있으며, +이때 [tf.distribute.MirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy)를 사용할 수 있습니다. +또한 [tf.distribute.TPUStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/experimental/TPUStrategy)를 사용하여, +각 실험을 TPU에서 실행할 수 있습니다. +현재 [tf.distribute.MultiWorkerMirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/experimental/MultiWorkerMirroredStrategy)는 지원되지 않지만, +향후 지원할 예정입니다. -### Example code +### 예제 코드 {#example-code} -When the environment variables described above are set, the example below will run distributed tuning and use data parallelism within each trial via [`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute). The example loads MNIST from `tensorflow_datasets` and uses [Hyperband](https://arxiv.org/abs/1603.06560) for the hyperparameter search. +아래 환경 변수가 설정된 상태에서, 아래 예시는 분산 튜닝을 실행하고, +각 실험에서 [`tf.distribute`](https://www.tensorflow.org/api_docs/python/tf/distribute)를 사용하여, +데이터 병렬 처리를 진행합니다. +이 예시는 `tensorflow_datasets`에서 MNIST를 로드하고, +[Hyperband](https://arxiv.org/abs/1603.06560)를 사용하여 하이퍼파라미터 검색을 수행합니다. ```python import keras @@ -76,7 +102,7 @@ import numpy as np def build_model(hp): - """Builds a convolutional model.""" + """컨볼루션 모델을 빌드합니다.""" inputs = keras.Input(shape=(28, 28, 1)) x = inputs for i in range(hp.Int("conv_layers", 1, 3, default=3)): @@ -124,7 +150,7 @@ tuner = keras_tuner.Hyperband( (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() -# Reshape the images to have the channel dimension. +# 이미지의 채널 차원을 가지도록, 이미지를 reshape 합니다. x_train = (x_train.reshape(x_train.shape + (1,)) / 255.0)[:1000] y_train = y_train.astype(np.int64)[:1000] x_test = (x_test.reshape(x_test.shape + (1,)) / 255.0)[:100] diff --git a/content/korean/docs/guides/keras_tuner/failed_trials/_index.md b/content/korean/docs/guides/keras_tuner/failed_trials/_index.md index ef11f4f0..9772973f 100644 --- a/content/korean/docs/guides/keras_tuner/failed_trials/_index.md +++ b/content/korean/docs/guides/keras_tuner/failed_trials/_index.md @@ -1,6 +1,6 @@ --- -title: Handling failed trials in KerasTuner -linkTitle: Handling failed trials in KerasTuner +title: KerasTuner에서 실패한 시도 처리 +linkTitle: 실패한 시도 처리 toc: true weight: 5 type: docs @@ -8,27 +8,29 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -**Authors:** Haifeng Jin +**{{< t f_author >}}** Haifeng Jin **{{< t f_date_created >}}** 2023/02/28 **{{< t f_last_modified >}}** 2023/02/28 -**{{< t f_description >}}** The basics of fault tolerance configurations in KerasTuner. +**{{< t f_description >}}** KerasTuner의 장애 허용(fault tolerance) 구성의 기본 사항. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_tuner/failed_trials.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/keras_tuner/failed_trials.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -A KerasTuner program may take a long time to run since each model may take a long time to train. We do not want the program to fail just because some trials failed randomly. +KerasTuner 프로그램은 각 모델의 트레이닝 시간이 오래 걸릴 수 있기 때문에, +실행 시간이 길어질 수 있습니다. +일부 시도가 랜덤하게 실패한다고 해서, 프로그램이 중단되지 않도록 처리해야 합니다. -In this guide, we will show how to handle the failed trials in KerasTuner, including: +이 가이드에서는 KerasTuner에서 실패한 시도를 처리하는 방법을 설명합니다. 다음 내용을 포함합니다: -- How to tolerate the failed trials during the search -- How to mark a trial as failed during building and evaluating the model -- How to terminate the search by raising a `FatalError` +- 탐색 중 실패한 시도를 허용(tolerate)하는 방법 +- 모델을 빌드하고 평가하는 동안, 시도를 실패로 표시하는 방법 +- `FatalError`를 발생시켜 탐색을 중단하는 방법 -## Setup +## 셋업 {#setup} ```python !pip install keras-tuner -q @@ -41,26 +43,37 @@ import keras_tuner import numpy as np ``` -## Tolerate failed trials +## 실패한 시도 허용하기(Tolerate) {#tolerate-failed-trials} -We will use the `max_retries_per_trial` and `max_consecutive_failed_trials` arguments when initializing the tuners. +우리는 튜너를 초기화할 때 `max_retries_per_trial` 및 +`max_consecutive_failed_trials` 인수를 사용할 것입니다. -`max_retries_per_trial` controls the maximum number of retries to run if a trial keeps failing. For example, if it is set to 3, the trial may run 4 times (1 failed run + 3 failed retries) before it is finally marked as failed. The default value of `max_retries_per_trial` is 0. +`max_retries_per_trial`은 시도가 계속 실패할 때, +최대 몇 번 다시 시도할지를 제어합니다. +예를 들어, 값이 3으로 설정되면, +시도는 총 4번(1번 실패한 실행 + 3번의 재시도)이 실행된 후에, +최종적으로 실패로 표시됩니다. 기본 값은 0입니다. -`max_consecutive_failed_trials` controls how many consecutive failed trials (failed trial here refers to a trial that failed all of its retries) occur before terminating the search. For example, if it is set to 3 and Trial 2, Trial 3, and Trial 4 all failed, the search would be terminated. However, if it is set to 3 and only Trial 2, Trial 3, Trial 5, and Trial 6 fail, the search would not be terminated since the failed trials are not consecutive. The default value of `max_consecutive_failed_trials` is 3. +`max_consecutive_failed_trials`은 연속해서 실패한 시도가 몇 번 발생해야, +탐색이 중단될지를 제어합니다. +예를 들어, 값이 3으로 설정되어 있고, +시도 2, 3, 4가 모두 실패하면 탐색이 중단됩니다. +그러나 값이 3으로 설정되어 있고, 시도 2, 3, 5, 6이 실패하더라도, +연속적으로 실패한 것이 아니기 때문에 탐색이 중단되지 않습니다. +`max_consecutive_failed_trials`의 기본 값은 3입니다. -The following code shows how these two arguments work in action. +다음 코드는 이 두 가지 인수가 실제로 어떻게 작동하는지를 보여줍니다. -- We define a search space with 2 hyperparameters for the number of units in the 2 dense layers. -- When their product is larger than 800, we raise a `ValueError` for the model too large. +- 2개의 dense 레이어에서 유닛 수에 대한 2개의 하이퍼파라미터로 탐색 공간을 정의합니다. +- 두 레이어의 유닛 곱이 800을 초과하면, 모델이 너무 크다는 `ValueError`를 발생시킵니다. ```python def build_model(hp): - # Define the 2 hyperparameters for the units in dense layers + # Dense 레이어의 유닛에 대한 2개의 하이퍼파라미터 정의 units_1 = hp.Int("units_1", 10, 40, step=10) units_2 = hp.Int("units_2", 10, 30, step=10) - # Define the model + # 모델 정의 model = keras.Sequential( [ layers.Dense(units=units_1, input_shape=(20,)), @@ -70,18 +83,18 @@ def build_model(hp): ) model.compile(loss="mse") - # Raise an error when the model is too large + # 모델이 너무 클 경우 오류 발생 num_params = model.count_params() if num_params > 1200: raise ValueError(f"Model too large! It contains {num_params} params.") return model ``` -We set up the tuner as follows. +튜너를 다음과 같이 설정합니다. -- We set `max_retries_per_trial=3`. -- We set `max_consecutive_failed_trials=8`. -- We use `GridSearch` to enumerate all hyperparameter value combinations. +- `max_retries_per_trial=3`으로 설정합니다. +- `max_consecutive_failed_trials=8`로 설정합니다. +- 모든 하이퍼파라미터 값 조합을 열거하기 위해, `GridSearch`를 사용합니다. ```python tuner = keras_tuner.GridSearch( @@ -92,7 +105,7 @@ tuner = keras_tuner.GridSearch( max_consecutive_failed_trials=8, ) -# Use random data to train the model. +# 랜덤 데이터를 사용하여 모델을 트레이닝합니다. tuner.search( x=np.random.rand(100, 20), y=np.random.rand(100, 1), @@ -103,7 +116,7 @@ tuner.search( epochs=10, ) -# Print the results. +# 결과를 출력합니다. tuner.results_summary() ``` @@ -249,21 +262,27 @@ ValueError: Model too large! It contains 1261 params. {{% /details %}} -## Mark a trial as failed +## 실패한 시도로 표시하기 {#mark-a-trial-as-failed} -When the model is too large, we do not need to retry it. No matter how many times we try with the same hyperparameters, it is always too large. +모델이 너무 클 때는 재시도할 필요가 없습니다. +같은 하이퍼파라미터로 몇 번을 시도하더라도, 항상 너무 큰 모델이 될 것입니다. -We can set `max_retries_per_trial=0` to do it. However, it will not retry no matter what errors are raised while we may still want to retry for other unexpected errors. Is there a way to better handle this situation? +이를 처리하기 위해 `max_retries_per_trial=0`으로 설정할 수 있지만, +이 경우 어떤 오류가 발생하더라도 재시도를 하지 않습니다. +우리는 여전히 예기치 않은 오류에 대해서는 재시도를 원할 수도 있습니다. +이 상황을 더 잘 처리할 방법이 있을까요? -We can raise the `FailedTrialError` to skip the retries. Whenever, this error is raised, the trial would not be retried. The retries will still run when other errors occur. An example is shown as follows. +우리는 `FailedTrialError`를 발생시켜 재시도를 건너뛸 수 있습니다. +이 오류가 발생하면 해당 시도는 재시도되지 않습니다. +다른 오류가 발생할 경우에는 여전히 재시도가 실행됩니다. 다음은 그 예시입니다. ```python def build_model(hp): - # Define the 2 hyperparameters for the units in dense layers + # Dense 레이어에서 사용할 유닛 수에 대한 2개의 하이퍼파라미터 정의 units_1 = hp.Int("units_1", 10, 40, step=10) units_2 = hp.Int("units_2", 10, 30, step=10) - # Define the model + # 모델 정의 model = keras.Sequential( [ layers.Dense(units=units_1, input_shape=(20,)), @@ -273,16 +292,16 @@ def build_model(hp): ) model.compile(loss="mse") - # Raise an error when the model is too large + # 모델이 너무 클 경우 오류 발생 num_params = model.count_params() if num_params > 1200: - # When this error is raised, it skips the retries. + # 이 오류가 발생하면 재시도를 건너뜁니다. raise keras_tuner.errors.FailedTrialError( f"Model too large! It contains {num_params} params." ) return model - +# 튜너 설정 tuner = keras_tuner.GridSearch( hypermodel=build_model, objective="val_loss", @@ -291,7 +310,7 @@ tuner = keras_tuner.GridSearch( max_consecutive_failed_trials=8, ) -# Use random data to train the model. +# 랜덤 데이터를 사용하여 모델을 트레이닝합니다. tuner.search( x=np.random.rand(100, 20), y=np.random.rand(100, 1), @@ -302,7 +321,7 @@ tuner.search( epochs=10, ) -# Print the results. +# 결과를 출력합니다. tuner.results_summary() ``` @@ -448,19 +467,22 @@ keras_tuner.src.errors.FailedTrialError: Model too large! It contains 1261 param {{% /details %}} -## Terminate the search programmatically +## 검색을 프로그래밍 방식으로 중단하기 {#terminate-the-search-programmatically} -When there is a bug in the code we should terminate the search immediately and fix the bug. You can terminate the search programmatically when your defined conditions are met. Raising a `FatalError` (or its subclasses `FatalValueError`, `FatalTypeError`, or `FatalRuntimeError`) will terminate the search regardless of the `max_consecutive_failed_trials` argument. +코드에 버그가 있을 경우 즉시 검색을 중단하고 버그를 수정해야 합니다. +정의된 조건이 충족되었을 때, 검색을 프로그래밍 방식으로 중단할 수 있습니다. +`FatalError` (또는 그 하위 클래스인 `FatalValueError`, `FatalTypeError`, `FatalRuntimeError`)를 발생시키면, +`max_consecutive_failed_trials` 인수와 상관없이 검색이 중단됩니다. -Following is an example to terminate the search when the model is too large. +다음은 모델이 너무 클 때 검색을 중단하는 예시입니다. ```python def build_model(hp): - # Define the 2 hyperparameters for the units in dense layers + # Dense 레이어에서 사용할 유닛 수에 대한 2개의 하이퍼파라미터 정의 units_1 = hp.Int("units_1", 10, 40, step=10) units_2 = hp.Int("units_2", 10, 30, step=10) - # Define the model + # 모델 정의 model = keras.Sequential( [ layers.Dense(units=units_1, input_shape=(20,)), @@ -470,10 +492,10 @@ def build_model(hp): ) model.compile(loss="mse") - # Raise an error when the model is too large + # 모델이 너무 클 경우 오류 발생 num_params = model.count_params() if num_params > 1200: - # When this error is raised, the search is terminated. + # 이 오류가 발생하면 검색이 중단됩니다. raise keras_tuner.errors.FatalError( f"Model too large! It contains {num_params} params." ) @@ -489,7 +511,7 @@ tuner = keras_tuner.GridSearch( ) try: - # Use random data to train the model. + # 랜덤 데이터를 사용하여 모델을 트레이닝합니다. tuner.search( x=np.random.rand(100, 20), y=np.random.rand(100, 1), @@ -531,11 +553,11 @@ The search is terminated. {{% /details %}} -## Takeaways +## 주요 내용 정리 {#takeaways} -In this guide, you learn how to handle failed trials in KerasTuner: +이 가이드에서는, KerasTuner에서 실패한 실험을 처리하는 방법을 배웠습니다: -- Use `max_retries_per_trial` to specify the number of retries for a failed trial. -- Use `max_consecutive_failed_trials` to specify the maximum consecutive failed trials to tolerate. -- Raise `FailedTrialError` to directly mark a trial as failed and skip the retries. -- Raise `FatalError`, `FatalValueError`, `FatalTypeError`, `FatalRuntimeError` to terminate the search immediately. +- `max_retries_per_trial`을 사용하여, 실패한 실험에 대한 재시도 횟수를 지정합니다. +- `max_consecutive_failed_trials`을 사용하여, 허용할 수 있는 최대 연속 실패 실험 횟수를 지정합니다. +- `FailedTrialError`를 발생시켜, 실험을 실패로 바로 표시하고, 재시도를 건너뜁니다. +- `FatalError`, `FatalValueError`, `FatalTypeError`, `FatalRuntimeError`를 발생시켜, 검색을 즉시 종료합니다. diff --git a/content/korean/docs/guides/keras_tuner/getting_started/_index.md b/content/korean/docs/guides/keras_tuner/getting_started/_index.md index 955b92a3..e6185add 100644 --- a/content/korean/docs/guides/keras_tuner/getting_started/_index.md +++ b/content/korean/docs/guides/keras_tuner/getting_started/_index.md @@ -1,6 +1,6 @@ --- -title: Getting started with KerasTuner -linkTitle: Getting started with KerasTuner +title: KerasTuner 시작하기 +linkTitle: KerasTuner 시작하기 toc: true weight: 1 type: docs @@ -8,10 +8,10 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Luca Invernizzi, James Long, Francois Chollet, Tom O'Malley, Haifeng Jin +**{{< t f_author >}}** Luca Invernizzi, James Long, Francois Chollet, Tom O'Malley, Haifeng Jin **{{< t f_date_created >}}** 2019/05/31 **{{< t f_last_modified >}}** 2021/10/27 -**{{< t f_description >}}** The basics of using KerasTuner to tune model hyperparameters. +**{{< t f_description >}}** 모델 하이퍼파라미터 튜닝을 위한 KerasTuner 사용 기본 사항. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_tuner/getting_started.ipynb" title="Colab" tag="Colab" tagType="warning">}} @@ -22,17 +22,26 @@ type: docs !pip install keras-tuner -q ``` -## Introduction +## 소개 {#introduction} -KerasTuner is a general-purpose hyperparameter tuning library. It has strong integration with Keras workflows, but it isn't limited to them: you could use it to tune scikit-learn models, or anything else. In this tutorial, you will see how to tune model architecture, training process, and data preprocessing steps with KerasTuner. Let's start from a simple example. +KerasTuner는 범용 하이퍼파라미터 튜닝 라이브러리입니다. +Keras 워크플로우와의 강력한 통합을 제공하지만, 이에 국한되지 않습니다. +scikit-learn 모델을 튜닝하거나 다른 작업에도 사용할 수 있습니다. +이 튜토리얼에서는 KerasTuner를 사용하여 +모델 아키텍처, 트레이닝 과정 및 데이터 전처리 단계를 튜닝하는 방법을 배울 것입니다. +간단한 예제부터 시작해봅시다. -## Tune the model architecture +## 모델 아키텍처 튜닝 {#tune-the-model-architecture} -The first thing we need to do is writing a function, which returns a compiled Keras model. It takes an argument `hp` for defining the hyperparameters while building the model. +먼저, 컴파일된 Keras 모델을 반환하는 함수를 작성해야 합니다. +이 함수는 모델을 빌드할 때 하이퍼파라미터를 정의하기 위한 `hp` 인자를 받습니다. -### Define the search space +### 검색 공간 정의 {#define-the-search-space} -In the following code example, we define a Keras model with two `Dense` layers. We want to tune the number of units in the first `Dense` layer. We just define an integer hyperparameter with `hp.Int('units', min_value=32, max_value=512, step=32)`, whose range is from 32 to 512 inclusive. When sampling from it, the minimum step for walking through the interval is 32. +다음 코드 예제에서는, 두 개의 `Dense` 레이어로 구성된 Keras 모델을 정의합니다. +첫 번째 `Dense` 레이어의 유닛 수를 튜닝하려고 합니다. +이를 위해 `hp.Int('units', min_value=32, max_value=512, step=32)`로 정수형 하이퍼파라미터를 정의합니다. +이 하이퍼파라미터는 32에서 512까지의 범위를 가지며, 샘플링할 때 최소 단위는 32입니다. ```python import keras @@ -44,7 +53,7 @@ def build_model(hp): model.add(layers.Flatten()) model.add( layers.Dense( - # Define the hyperparameter. + # 하이퍼파라미터 정의 units=hp.Int("units", min_value=32, max_value=512, step=32), activation="relu", ) @@ -58,7 +67,7 @@ def build_model(hp): return model ``` -You can quickly test if the model builds successfully. +모델이 성공적으로 빌드되는지 빠르게 테스트할 수 있습니다. ```python import keras_tuner @@ -74,7 +83,10 @@ build_model(keras_tuner.HyperParameters()) {{% /details %}} -There are many other types of hyperparameters as well. We can define multiple hyperparameters in the function. In the following code, we tune whether to use a `Dropout` layer with `hp.Boolean()`, tune which activation function to use with `hp.Choice()`, tune the learning rate of the optimizer with `hp.Float()`. +여러 타입의 하이퍼파라미터를 정의할 수도 있습니다. +다음 코드에서는 `Dropout` 레이어를 사용할지 여부를 `hp.Boolean()`으로 튜닝하고, +활성화 함수는 `hp.Choice()`로 선택하며, +옵티마이저의 학습률은 `hp.Float()`로 튜닝합니다. ```python def build_model(hp): @@ -82,17 +94,17 @@ def build_model(hp): model.add(layers.Flatten()) model.add( layers.Dense( - # Tune number of units. + # 유닛 수 튜닝. units=hp.Int("units", min_value=32, max_value=512, step=32), - # Tune the activation function to use. + # 사용할 활성화 함수 튜닝. activation=hp.Choice("activation", ["relu", "tanh"]), ) ) - # Tune whether to use dropout. + # 드롭아웃 사용 여부 튜닝. if hp.Boolean("dropout"): model.add(layers.Dropout(rate=0.25)) model.add(layers.Dense(10, activation="softmax")) - # Define the optimizer learning rate as a hyperparameter. + # 옵티마이저 학습률을 하이퍼파라미터로 정의. learning_rate = hp.Float("lr", min_value=1e-4, max_value=1e-2, sampling="log") model.compile( optimizer=keras.optimizers.Adam(learning_rate=learning_rate), @@ -113,7 +125,10 @@ build_model(keras_tuner.HyperParameters()) {{% /details %}} -As shown below, the hyperparameters are actual values. In fact, they are just functions returning actual values. For example, `hp.Int()` returns an `int` value. Therefore, you can put them into variables, for loops, or if conditions. +아래에 보이는 것처럼, 하이퍼파라미터는 실제 값입니다. +사실, 이는 실제 값을 반환하는 함수일 뿐입니다. +예를 들어, `hp.Int()`는 `int` 값을 반환합니다. +따라서, 이를 변수, for 루프, 또는 if 조건문에 넣을 수 있습니다. ```python hp = keras_tuner.HyperParameters() @@ -128,7 +143,7 @@ print(hp.Int("units", min_value=32, max_value=512, step=32)) {{% /details %}} -You can also define the hyperparameters in advance and keep your Keras code in a separate function. +하이퍼파라미터를 미리 정의하고 Keras 코드를 별도의 함수에 둘 수도 있습니다. ```python def call_existing_code(units, activation, dropout, lr): @@ -151,7 +166,7 @@ def build_model(hp): activation = hp.Choice("activation", ["relu", "tanh"]) dropout = hp.Boolean("dropout") lr = hp.Float("lr", min_value=1e-4, max_value=1e-2, sampling="log") - # call existing model-building code with the hyperparameter values. + # 하이퍼파라미터 값을 사용하여 기존 모델 빌드 코드를 호출합니다. model = call_existing_code( units=units, activation=activation, dropout=dropout, lr=lr ) @@ -169,19 +184,28 @@ build_model(keras_tuner.HyperParameters()) {{% /details %}} -Each of the hyperparameters is uniquely identified by its name (the first argument). To tune the number of units in different `Dense` layers separately as different hyperparameters, we give them different names as `f"units_{i}"`. +각 하이퍼파라미터는 이름(첫 번째 인자)으로 고유하게 식별됩니다. +서로 다른 `Dense` 레이어에서 유닛 수를 별도의 하이퍼파라미터로 조정하려면, +그들에게 `f"units_{i}"`와 같이 다른 이름을 부여하면 됩니다. -Notably, this is also an example of creating conditional hyperparameters. There are many hyperparameters specifying the number of units in the `Dense` layers. The number of such hyperparameters is decided by the number of layers, which is also a hyperparameter. Therefore, the total number of hyperparameters used may be different from trial to trial. Some hyperparameter is only used when a certain condition is satisfied. For example, `units_3` is only used when `num_layers` is larger than 3. With KerasTuner, you can easily define such hyperparameters dynamically while creating the model. +또한, 이는 조건부 하이퍼파라미터를 생성하는 예시이기도 합니다. +`Dense` 레이어에서 유닛 수를 지정하는 많은 하이퍼파라미터가 존재하며, +이러한 하이퍼파라미터의 수는 레이어 수에 따라 달라집니다. +레이어 수 자체도 하나의 하이퍼파라미터이기 때문에, +전체 하이퍼파라미터 수는 시도할 때마다 다를 수 있습니다. +어떤 하이퍼파라미터는 특정 조건이 충족될 때만 사용됩니다. +예를 들어, `units_3`는 `num_layers`가 3보다 클 때만 사용됩니다. +KerasTuner를 사용하면, 모델을 생성하는 동안 이러한 하이퍼파라미터를 동적으로 쉽게 정의할 수 있습니다. ```python def build_model(hp): model = keras.Sequential() model.add(layers.Flatten()) - # Tune the number of layers. + # 레이어 수를 튜닝합니다. for i in range(hp.Int("num_layers", 1, 3)): model.add( layers.Dense( - # Tune number of units separately. + # 각 레이어의 유닛 수를 개별적으로 튜닝합니다. units=hp.Int(f"units_{i}", min_value=32, max_value=512, step=32), activation=hp.Choice("activation", ["relu", "tanh"]), ) @@ -209,19 +233,29 @@ build_model(keras_tuner.HyperParameters()) {{% /details %}} -### Start the search - -After defining the search space, we need to select a tuner class to run the search. You may choose from `RandomSearch`, `BayesianOptimization` and `Hyperband`, which correspond to different tuning algorithms. Here we use `RandomSearch` as an example. - -To initialize the tuner, we need to specify several arguments in the initializer. - -- `hypermodel`. The model-building function, which is `build_model` in our case. -- `objective`. The name of the objective to optimize (whether to minimize or maximize is automatically inferred for built-in metrics). We will introduce how to use custom metrics later in this tutorial. -- `max_trials`. The total number of trials to run during the search. -- `executions_per_trial`. The number of models that should be built and fit for each trial. Different trials have different hyperparameter values. The executions within the same trial have the same hyperparameter values. The purpose of having multiple executions per trial is to reduce results variance and therefore be able to more accurately assess the performance of a model. If you want to get results faster, you could set `executions_per_trial=1` (single round of training for each model configuration). -- `overwrite`. Control whether to overwrite the previous results in the same directory or resume the previous search instead. Here we set `overwrite=True` to start a new search and ignore any previous results. -- `directory`. A path to a directory for storing the search results. -- `project_name`. The name of the sub-directory in the `directory`. +### 검색 시작하기 {#start-the-search} + +탐색 공간을 정의한 후, 탐색을 실행할 튜너 클래스를 선택해야 합니다. +`RandomSearch`, `BayesianOptimization`, `Hyperband` 중 하나를 선택할 수 있으며, +이는 각각 다른 튜닝 알고리즘에 해당합니다. +여기서는 `RandomSearch`를 예로 사용합니다. + +튜너를 초기화하려면, 이니셜라이저에서 여러 인자를 지정해야 합니다. + +- `hypermodel`. 모델을 빌드하는 함수로, 여기서는 `build_model`이 해당됩니다. +- `objective`. 최적화할 목표의 이름입니다. (빌트인 지표의 경우, 최소화 또는 최대화 여부는 자동으로 추론됩니다) + 이 튜토리얼 후반부에서 커스텀 지표를 사용하는 방법을 소개할 예정입니다. +- `max_trials`. 탐색 중 실행할 총 실험 횟수입니다. +- `executions_per_trial`. 각 실험에서 구축되고 fit 되어야 하는 모델의 수입니다. + 서로 다른 실험은 서로 다른 하이퍼파라미터 값을 가집니다. + 동일한 실험 내에서는 동일한 하이퍼파라미터 값을 가집니다. + 각 실험에서 여러 번 실행하는 목적은 결과의 분산을 줄여 모델의 성능을 더 정확하게 평가할 수 있도록 하기 위함입니다. + 더 빠르게 결과를 얻고 싶다면, `executions_per_trial=1`로 설정할 수 있습니다. + (각 모델 구성에 대해 한 번의 트레이닝 라운드만 실행) +- `overwrite`. 동일한 디렉토리에서 이전 결과를 덮어쓸지 아니면 이전 탐색을 다시 시작할지를 제어합니다. + 여기서는 `overwrite=True`로 설정하여 새 탐색을 시작하고 이전 결과를 무시합니다. +- `directory`. 탐색 결과를 저장할 디렉토리 경로입니다. +- `project_name`. `directory` 내에 저장할 하위 디렉토리의 이름입니다. ```python tuner = keras_tuner.RandomSearch( @@ -235,7 +269,7 @@ tuner = keras_tuner.RandomSearch( ) ``` -You can print a summary of the search space: +탐색 공간 요약을 출력할 수 있습니다: ```python tuner.search_space_summary() @@ -260,7 +294,7 @@ lr (Float) {{% /details %}} -Before starting the search, let's prepare the MNIST dataset. +탐색을 시작하기 전에, MNIST 데이터셋을 준비합니다. ```python import keras @@ -283,7 +317,9 @@ y_val = keras.utils.to_categorical(y_val, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) ``` -Then, start the search for the best hyperparameter configuration. All the arguments passed to `search` is passed to `model.fit()` in each execution. Remember to pass `validation_data` to evaluate the model. +그런 다음, 최적의 하이퍼파라미터 구성을 탐색합니다. +`search`에 전달된 모든 인자는 각 실행에서 `model.fit()`에 전달됩니다. +모델을 평가하기 위해 `validation_data`를 반드시 전달해야 합니다. ```python tuner.search(x_train, y_train, epochs=2, validation_data=(x_val, y_val)) @@ -303,14 +339,19 @@ Total elapsed time: 00h 00m 40s {{% /details %}} -During the `search`, the model-building function is called with different hyperparameter values in different trial. In each trial, the tuner would generate a new set of hyperparameter values to build the model. The model is then fit and evaluated. The metrics are recorded. The tuner progressively explores the space and finally finds a good set of hyperparameter values. +`search`가 진행되는 동안, +모델 빌드 함수는 서로 다른 실험에서 서로 다른 하이퍼파라미터 값으로 호출됩니다. +각 실험에서 튜너는 새로운 하이퍼파라미터 값을 생성하여 모델을 빌드합니다. +그런 다음 모델을 fit하고 평가합니다. 이때 메트릭이 기록됩니다. +튜너는 탐색 공간을 점진적으로 탐색하며, 결국 좋은 하이퍼파라미터 값을 찾습니다. -### Query the results +### 결과 조회 {#query-the-results} -When search is over, you can retrieve the best model(s). The model is saved at its best performing epoch evaluated on the `validation_data`. +탐색이 완료되면, 최적의 모델을 검색할 수 있습니다. +모델은 `validation_data`에 대해 평가한 결과 가장 성능이 좋은 에포크에서 저장됩니다. ```python -# Get the top 2 models. +# 상위 2개의 모델을 가져옵니다. models = tuner.get_best_models(num_models=2) best_model = models[0] best_model.summary() @@ -349,7 +390,7 @@ Model: "sequential" {{% /details %}} -You can also print a summary of the search results. +탐색 결과 요약을 출력할 수도 있습니다. ```python tuner.results_summary() @@ -402,20 +443,22 @@ Score: 0.9606499969959259 {{% /details %}} -You will find detailed logs, checkpoints, etc, in the folder `my_dir/helloworld`, i.e. `directory/project_name`. +`my_dir/helloworld` 폴더, 즉 `directory/project_name`에 자세한 로그, 체크포인트 등을 찾을 수 있습니다. -You can also visualize the tuning results using TensorBoard and HParams plugin. For more information, please following [this link]({{< relref "/docs/guides/keras_tuner/visualize_tuning" >}}). +또한, TensorBoard와 HParams 플러그인을 사용하여 튜닝 결과를 시각화할 수 있습니다. +자세한 내용은 {{< titledRelref "/docs/guides/keras_tuner/visualize_tuning" >}} 가이드를 참고하세요. -### Retrain the model +### 모델 재트레이닝 {#retrain-the-model} -If you want to train the model with the entire dataset, you may retrieve the best hyperparameters and retrain the model by yourself. +전체 데이터셋을 사용하여 모델을 다시 트레이닝하고 싶다면, +최적의 하이퍼파라미터를 검색해 스스로 직접 모델을 재트레이닝할 수 있습니다. ```python -# Get the top 2 hyperparameters. +# 최적의 2개의 하이퍼파라미터를 가져옵니다. best_hps = tuner.get_best_hyperparameters(5) -# Build the model with the best hp. +# 최적의 하이퍼파라미터로 모델을 빌드합니다. model = build_model(best_hps[0]) -# Fit with the entire dataset. +# 전체 데이터셋으로 트레이닝합니다. x_all = np.concatenate((x_train, x_val)) y_all = np.concatenate((y_train, y_val)) model.fit(x=x_all, y=y_all, epochs=1) @@ -592,19 +635,28 @@ model.fit(x=x_all, y=y_all, epochs=1) {{% /details %}} -## Tune model training +## 모델 트레이닝 튜닝 {#tune-model-training} -To tune the model building process, we need to subclass the `HyperModel` class, which also makes it easy to share and reuse hypermodels. +모델 빌딩 프로세스를 튜닝하려면, `HyperModel` 클래스를 서브클래싱해야 합니다. +이를 통해 하이퍼모델을 쉽게 공유하고 재사용할 수 있습니다. -We need to override `HyperModel.build()` and `HyperModel.fit()` to tune the model building and training process respectively. A `HyperModel.build()` method is the same as the model-building function, which creates a Keras model using the hyperparameters and returns it. +모델 빌딩과 트레이닝 프로세스를 각각 튜닝하려면, +`HyperModel.build()`와 `HyperModel.fit()`을 오버라이드해야 합니다. +`HyperModel.build()` 메서드는 하이퍼파라미터를 사용하여, +Keras 모델을 생성하고 반환하는 모델 빌딩 함수와 동일합니다. -In `HyperModel.fit()`, you can access the model returned by `HyperModel.build()`,`hp` and all the arguments passed to `search()`. You need to train the model and return the training history. +`HyperModel.fit()`에서는, `HyperModel.build()`에서 반환된 모델, `hp`, +그리고 `search()`에 전달된 모든 인자에 접근할 수 있습니다. +모델을 트레이닝한 후 트레이닝 히스토리를 반환해야 합니다. -In the following code, we will tune the `shuffle` argument in `model.fit()`. +다음 코드에서는, `model.fit()`에서 `shuffle` 인자를 튜닝합니다. -It is generally not needed to tune the number of epochs because a built-in callback is passed to `model.fit()` to save the model at its best epoch evaluated by the `validation_data`. +일반적으로 에포크 수를 튜닝할 필요는 없습니다. +왜냐하면 `model.fit()`에 내장된 콜백이 전달되어, +`validation_data`로 평가된 가장 좋은 에포크에서 모델을 저장하기 때문입니다. -> **Note**: The `**kwargs` should always be passed to `model.fit()` because it contains the callbacks for model saving and tensorboard plugins. +> **참고**: `**kwargs`는 항상 `model.fit()`에 전달되어야 합니다. +> 여기에는 모델 저장 및 TensorBoard 플러그인을 위한 콜백이 포함되어 있기 때문입니다. ```python class MyHyperModel(keras_tuner.HyperModel): @@ -628,13 +680,13 @@ class MyHyperModel(keras_tuner.HyperModel): def fit(self, hp, model, *args, **kwargs): return model.fit( *args, - # Tune whether to shuffle the data in each epoch. + # 각 에포크에서 데이터를 셔플할지 여부를 튜닝. shuffle=hp.Boolean("shuffle"), **kwargs, ) ``` -Again, we can do a quick check to see if the code works correctly. +다시 한 번, 코드를 빠르게 확인하여 제대로 작동하는지 확인할 수 있습니다. ```python hp = keras_tuner.HyperParameters() @@ -659,9 +711,13 @@ hypermodel.fit(hp, model, np.random.rand(100, 28, 28), np.random.rand(100, 10)) {{% /details %}} -## Tune data preprocessing +## 데이터 전처리 튜닝 {#tune-data-preprocessing} -To tune data preprocessing, we just add an additional step in `HyperModel.fit()`, where we can access the dataset from the arguments. In the following code, we tune whether to normalize the data before training the model. This time we explicitly put `x` and `y` in the function signature because we need to use them. +데이터 전처리를 튜닝하려면, `HyperModel.fit()`에서, +인수로부터 데이터셋에 접근할 수 있도록, 추가적인 단계만 넣으면 됩니다. +다음 코드에서는, 트레이닝 전에 데이터를 정규화할지 여부를 튜닝합니다. +이번에는 `x`와 `y`를 함수 시그니처에 명시적으로 넣었는데, +이는 우리가 이 값들을 사용해야 하기 때문입니다. ```python class MyHyperModel(keras_tuner.HyperModel): @@ -688,7 +744,7 @@ class MyHyperModel(keras_tuner.HyperModel): return model.fit( x, y, - # Tune whether to shuffle the data in each epoch. + # 각 에포크에서 데이터를 셔플할지 여부를 튜닝. shuffle=hp.Boolean("shuffle"), **kwargs, ) @@ -716,7 +772,12 @@ hypermodel.fit(hp, model, np.random.rand(100, 28, 28), np.random.rand(100, 10)) {{% /details %}} -If a hyperparameter is used both in `build()` and `fit()`, you can define it in `build()` and use `hp.get(hp_name)` to retrieve it in `fit()`. We use the image size as an example. It is both used as the input shape in `build()`, and used by data prerprocessing step to crop the images in `fit()`. +하이퍼파라미터가 `build()`와 `fit()` 모두에서 사용되는 경우, +`build()`에서 정의하고 `hp.get(hp_name)`을 사용하여, +`fit()`에서 해당 값을 가져올 수 있습니다. +이미지 크기를 예로 들어보겠습니다. +이 값은 `build()`에서 입력 크기로 사용되며, +`fit()`의 데이터 전처리 단계에서 이미지를 자를 때 사용됩니다. ```python class MyHyperModel(keras_tuner.HyperModel): @@ -749,7 +810,7 @@ class MyHyperModel(keras_tuner.HyperModel): return model.fit( cropped_x, y, - # Tune whether to shuffle the data in each epoch. + # 각 에포크에서 데이터를 셔플할지 여부를 튜닝. shuffle=hp.Boolean("shuffle"), validation_data=validation_data, **kwargs, @@ -782,9 +843,9 @@ Total elapsed time: 00h 00m 13s {{% /details %}} -### Retrain the model +### 모델 재트레이닝 {#retrain-the-model} -Using `HyperModel` also allows you to retrain the best model by yourself. +`HyperModel`을 사용하면 최적의 모델을 직접 재트레이닝할 수도 있습니다. ```python hypermodel = MyHyperModel() @@ -895,25 +956,35 @@ hypermodel.fit(best_hp, model, x_all, y_all, epochs=1) {{% /details %}} -## Specify the tuning objective - -In all previous examples, we all just used validation accuracy (`"val_accuracy"`) as the tuning objective to select the best model. Actually, you can use any metric as the objective. The most commonly used metric is `"val_loss"`, which is the validation loss. +## 튜닝 목표 지정 {#specify-the-tuning-objective} -### Built-in metric as the objective +지금까지의 모든 예제에서는 검증 정확도(`"val_accuracy"`)를 사용하여 최적의 모델을 선택했습니다. +사실, 튜닝 목표로 사용할 수 있는 메트릭은 무엇이든 가능합니다. +가장 일반적으로 사용되는 메트릭은 검증 손실인 `"val_loss"`입니다. -There are many other built-in metrics in Keras you can use as the objective. Here is [a list of the built-in metrics]({{< relref "/docs/api/metrics" >}}). +### 빌트인 메트릭을 목표로 사용 {#built-in-metric-as-the-objective} -To use a built-in metric as the objective, you need to follow these steps: +Keras에는 목표로 사용할 수 있는 빌트인 메트릭이 많이 있습니다. +[빌트인 메트릭 리스트]({{< relref "/docs/api/metrics" >}})를 참조하세요. -- Compile the model with the the built-in metric. For example, you want to use `MeanAbsoluteError()`. You need to compile the model with `metrics=[MeanAbsoluteError()]`. You may also use its name string instead: `metrics=["mean_absolute_error"]`. The name string of the metric is always the snake case of the class name. +빌트인 메트릭을 목표로 사용하려면, 다음 단계를 따르세요: -- Identify the objective name string. The name string of the objective is always in the format of `f"val_{metric_name_string}"`. For example, the objective name string of mean squared error evaluated on the validation data should be `"val_mean_absolute_error"`. +- 모델을 내장 메트릭으로 컴파일하세요. + 예를 들어, `MeanAbsoluteError()`를 사용하려면, + `metrics=[MeanAbsoluteError()]`로 모델을 컴파일해야 합니다. + 또한 해당 메트릭의 이름 문자열을 사용할 수도 있습니다: `metrics=["mean_absolute_error"]`. + 메트릭의 이름 문자열은 항상 클래스 이름을 스네이크 케이스로 변환한 형식입니다. +- 목표 이름 문자열을 식별하세요. + 목표 이름 문자열은 항상 `f"val_{metric_name_string}"` 형식입니다. + 예를 들어, 검증 데이터에 대해 평가한 평균 절대 오차의 목표 이름 문자열은 `"val_mean_absolute_error"`가 됩니다. +- 이를 [`keras_tuner.Objective`]({{< relref "/docs/api/keras_tuner/tuners/objective#objective-class" >}})로 래핑하세요. + 일반적으로 목표를 [`keras_tuner.Objective`]({{< relref "/docs/api/keras_tuner/tuners/objective#objective-class" >}}) 객체로 래핑해서 목표를 최적화할 방향을 지정해야 합니다. + 예를 들어, 평균 절대 오차를 최소화하려면, + `keras_tuner.Objective("val_mean_absolute_error", "min")`을 사용할 수 있습니다. + 방향은 `"min"` 또는 `"max"` 중 하나여야 합니다. +- 튜너에 래핑된 목표를 전달하세요. -- Wrap it into [`keras_tuner.Objective`]({{< relref "/docs/api/keras_tuner/tuners/objective#objective-class" >}}). We usually need to wrap the objective into a [`keras_tuner.Objective`]({{< relref "/docs/api/keras_tuner/tuners/objective#objective-class" >}}) object to specify the direction to optimize the objective. For example, we want to minimize the mean squared error, we can use `keras_tuner.Objective("val_mean_absolute_error", "min")`. The direction should be either `"min"` or `"max"`. - -- Pass the wrapped objective to the tuner. - -You can see the following barebone code example. +다음은 최소한의 코드 예시입니다. ```python def build_regressor(hp): @@ -926,7 +997,7 @@ def build_regressor(hp): model.compile( optimizer="adam", loss="mean_squared_error", - # Objective is one of the metrics. + # 목표는 메트릭 중 하나입니다. metrics=[keras.metrics.MeanAbsoluteError()], ) return model @@ -934,8 +1005,8 @@ def build_regressor(hp): tuner = keras_tuner.RandomSearch( hypermodel=build_regressor, - # The objective name and direction. - # Name is the f"val_{snake_case_metric_class_name}". + # 목표 이름과 방향. + # 이름은 f"val_{snake_case_metric_class_name}" 형식입니다. objective=keras_tuner.Objective("val_mean_absolute_error", direction="min"), max_trials=3, overwrite=True, @@ -991,11 +1062,22 @@ Score: 0.5005304217338562 {{% /details %}} -### Custom metric as the objective +### 커스텀 메트릭을 목표로 사용 {#custom-metric-as-the-objective} + +커스텀 메트릭을 구현하여 하이퍼파라미터 탐색의 목표로 사용할 수 있습니다. +여기서는 예시로 평균 제곱 오차(MSE)를 사용하겠습니다. +먼저, [`keras.metrics.Metric`]({{< relref "/docs/api/metrics/base_metric#metric-class" >}})를 서브클래싱하여 MSE 메트릭을 구현합니다. +`super().__init__()`의 `name` 인수를 사용해 메트릭의 이름을 지정하는 것을 잊지 마세요. +이 이름은 나중에 사용됩니다. -You may implement your own metric and use it as the hyperparameter search objective. Here, we use mean squared error (MSE) as an example. First, we implement the MSE metric by subclassing [`keras.metrics.Metric`]({{< relref "/docs/api/metrics/base_metric#metric-class" >}}). Remember to give a name to your metric using the `name` argument of `super().__init__()`, which will be used later. Note: MSE is actually a build-in metric, which can be imported with [`keras.metrics.MeanSquaredError`]({{< relref "/docs/api/metrics/regression_metrics#meansquarederror-class" >}}). This is just an example to show how to use a custom metric as the hyperparameter search objective. +참고로, MSE는 사실 빌트인 메트릭이며, +[`keras.metrics.MeanSquaredError`]({{< relref "/docs/api/metrics/regression_metrics#meansquarederror-class" >}})를 통해 import 할 수 있습니다. +이 예시는 커스텀 메트릭을 하이퍼파라미터 탐색 목표로 사용하는 방법을 보여줍니다. -For more information about implementing custom metrics, please see [this tutorial]({{< relref "/docs/api/metrics/#creating-custom-metrics" >}}). If you would like a metric with a different function signature than `update_state(y_true, y_pred, sample_weight)`, you can override the `train_step()` method of your model following [this tutorial]({{< relref "/docs/guides/custom_train_step_in_tensorflow/#going-lower-level" >}}). +커스텀 메트릭을 구현하는 방법에 대한 자세한 내용은 [이 튜토리얼]({{< relref "/docs/api/metrics/#creating-custom-metrics" >}})을 참조하세요. +만약 `update_state(y_true, y_pred, sample_weight)`와는 다른 함수 시그니처를 사용하는 메트릭을 만들고자 한다면, +[이 튜토리얼]({{< relref "/docs/guides/custom_train_step_in_tensorflow/#going-lower-level" >}})를 따라, +`train_step()` 메서드를 재정의할 수 있습니다. ```python from keras import ops @@ -1003,7 +1085,7 @@ from keras import ops class CustomMetric(keras.metrics.Metric): def __init__(self, **kwargs): - # Specify the name of the metric as "custom_metric". + # 메트릭 이름을 "custom_metric"으로 지정합니다. super().__init__(name="custom_metric", **kwargs) self.sum = self.add_weight(name="sum", initializer="zeros") self.count = self.add_weight(name="count", dtype="int32", initializer="zeros") @@ -1026,7 +1108,7 @@ class CustomMetric(keras.metrics.Metric): self.count.assign(0) ``` -Run the search with the custom objective. +커스텀 목표로 검색을 실행합니다. ```python def build_regressor(hp): @@ -1039,7 +1121,7 @@ def build_regressor(hp): model.compile( optimizer="adam", loss="mean_squared_error", - # Put custom metric into the metrics. + # 커스텀 메트릭을 metrics에 추가합니다. metrics=[CustomMetric()], ) return model @@ -1047,7 +1129,7 @@ def build_regressor(hp): tuner = keras_tuner.RandomSearch( hypermodel=build_regressor, - # Specify the name and direction of the objective. + # 목표의 이름과 방향을 지정합니다. objective=keras_tuner.Objective("val_custom_metric", direction="min"), max_trials=3, overwrite=True, @@ -1103,7 +1185,12 @@ Score: 0.4656866192817688 {{% /details %}} -If your custom objective is hard to put into a custom metric, you can also evaluate the model by yourself in `HyperModel.fit()` and return the objective value. The objective value would be minimized by default. In this case, you don't need to specify the `objective` when initializing the tuner. However, in this case, the metric value will not be tracked in the Keras logs by only KerasTuner logs. Therefore, these values would not be displayed by any TensorBoard view using the Keras metrics. +커스텀 목표를 커스텀 메트릭으로 표현하기 어려운 경우, +`HyperModel.fit()`에서 직접 모델을 평가하고 목표 값을 반환할 수도 있습니다. +이 경우 목표 값은 기본적으로 최소화됩니다. +이러한 경우, 튜너를 초기화할 때 `objective`를 지정할 필요가 없습니다. +그러나, 이 경우 메트릭 값은 Keras 로그에서 추적되지 않으며, KerasTuner 로그에만 기록됩니다. +따라서, 이 값들은 Keras 메트릭을 사용하는 TensorBoard 뷰에서 표시되지 않습니다. ```python class HyperRegressor(keras_tuner.HyperModel): @@ -1124,14 +1211,14 @@ class HyperRegressor(keras_tuner.HyperModel): model.fit(x, y, **kwargs) x_val, y_val = validation_data y_pred = model.predict(x_val) - # Return a single float to minimize. + # 최소화할 단일 float 값을 반환합니다. return np.mean(np.abs(y_pred - y_val)) tuner = keras_tuner.RandomSearch( hypermodel=HyperRegressor(), - # No objective to specify. - # Objective is the return value of `HyperModel.fit()`. + # 목표를 지정할 필요가 없습니다. + # 목표는 `HyperModel.fit()`의 반환 값입니다. max_trials=3, overwrite=True, directory="my_dir", @@ -1185,7 +1272,11 @@ Score: 0.6571611521766413 {{% /details %}} -If you have multiple metrics to track in KerasTuner, but only use one of them as the objective, you can return a dictionary, whose keys are the metric names and the values are the metrics values, for example, return `{"metric_a": 1.0, "metric_b", 2.0}`. Use one of the keys as the objective name, for example, `keras_tuner.Objective("metric_a", "min")`. +KerasTuner에서 여러 메트릭을 추적하면서 그중 하나만 목표로 사용할 경우, +메트릭 이름을 키로 하고 메트릭 값을 값으로 하는 딕셔너리를 반환할 수 있습니다. +예를 들어, `{"metric_a": 1.0, "metric_b": 2.0}`을 반환하고, +키 중 하나를 목표 이름으로 사용할 수 있습니다. +예를 들어, `keras_tuner.Objective("metric_a", "min")`와 같이 설정합니다. ```python class HyperRegressor(keras_tuner.HyperModel): @@ -1206,7 +1297,7 @@ class HyperRegressor(keras_tuner.HyperModel): model.fit(x, y, **kwargs) x_val, y_val = validation_data y_pred = model.predict(x_val) - # Return a dictionary of metrics for KerasTuner to track. + # KerasTuner가 추적할 메트릭 딕셔너리를 반환합니다. return { "metric_a": -np.mean(np.abs(y_pred - y_val)), "metric_b": np.mean(np.square(y_pred - y_val)), @@ -1215,8 +1306,8 @@ class HyperRegressor(keras_tuner.HyperModel): tuner = keras_tuner.RandomSearch( hypermodel=HyperRegressor(), - # Objective is one of the keys. - # Maximize the negative MAE, equivalent to minimize MAE. + # 목표는 딕셔너리의 키 중 하나입니다. + # 음의 MAE를 최대화, 즉 MAE를 최소화합니다. objective=keras_tuner.Objective("metric_a", "max"), max_trials=3, overwrite=True, @@ -1271,35 +1362,40 @@ Score: -0.46081380465766364 {{% /details %}} -## Tune end-to-end workflows +## 엔드투엔드 워크플로우 튜닝 {#tune-end-to-end-workflows} -In some cases, it is hard to align your code into build and fit functions. You can also keep your end-to-end workflow in one place by overriding `Tuner.run_trial()`, which gives you full control of a trial. You can see it as a black-box optimizer for anything. +일부 경우에는, 코드를 빌드 및 fit 함수로 정렬하는 것이 어려울 수 있습니다. +이 경우 `Tuner.run_trial()`을 재정의하여 엔드투엔드 워크플로우를 한곳에 유지할 수 있으며, +이를 통해 트라이얼을 완전히 제어할 수 있습니다. +이를 일종의 블랙박스 옵티마이저로 간주할 수 있습니다. -### Tune any function +### 어떤 함수이든 튜닝 {#tune-any-function} -For example, you can find a value of `x`, which minimizes `f(x)=x*x+1`. In the following code, we just define `x` as a hyperparameter, and return `f(x)` as the objective value. The `hypermodel` and `objective` argument for initializing the tuner can be omitted. +예를 들어, `f(x)=x*x+1`을 최소화하는 `x` 값을 찾을 수 있습니다. +아래 코드에서는 `x`를 하이퍼파라미터로 정의하고, `f(x)`를 목표 값으로 반환합니다. +튜너를 초기화할 때, `hypermodel`과 `objective` 인수는 생략할 수 있습니다. ```python class MyTuner(keras_tuner.RandomSearch): def run_trial(self, trial, *args, **kwargs): - # Get the hp from trial. + # 트라이얼에서 hp 가져오기 hp = trial.hyperparameters - # Define "x" as a hyperparameter. + # "x"를 하이퍼파라미터로 정의 x = hp.Float("x", min_value=-1.0, max_value=1.0) - # Return the objective value to minimize. + # 최소화할 목표 값 반환 return x * x + 1 tuner = MyTuner( - # No hypermodel or objective specified. + # hypermodel이나 objective를 지정하지 않음 max_trials=20, overwrite=True, directory="my_dir", project_name="tune_anything", ) -# No need to pass anything to search() -# unless you use them in run_trial(). +# run_trial()에서 사용하지 않으면, +# search()에 아무것도 전달할 필요 없음 tuner.search() print(tuner.get_best_hyperparameters()[0].get("x")) ``` @@ -1319,20 +1415,24 @@ Total elapsed time: 00h 00m 00s {{% /details %}} -### Keep Keras code separate +### Keras 코드 분리 유지 {#keep-keras-code-separate} -You can keep all your Keras code unchanged and use KerasTuner to tune it. It is useful if you cannot modify the Keras code for some reason. +Keras 코드를 변경하지 않고 그대로 유지하면서 KerasTuner를 사용하여 튜닝할 수 있습니다. +Keras 코드를 수정할 수 없는 경우에 유용합니다. -It also gives you more flexibility. You don't have to separate the model building and training code apart. However, this workflow would not help you save the model or connect with the TensorBoard plugins. +이 방식은 더 많은 유연성을 제공합니다. +모델 빌드 및 트레이닝 코드를 따로 분리할 필요가 없습니다. +그러나, 이 워크플로우는 모델 저장이나 TensorBoard 플러그인과의 연결을 제공하지는 않습니다. -To save the model, you can use `trial.trial_id`, which is a string to uniquely identify a trial, to construct different paths to save the models from different trials. +모델을 저장하려면, 각 트라이얼을 고유하게 식별하는 문자열인 `trial.trial_id`를 사용하여, +서로 다른 경로를 구성해 각 트라이얼에서 생성된 모델을 저장할 수 있습니다. ```python import os def keras_code(units, optimizer, saving_path): - # Build model + # 모델 빌드 model = keras.Sequential( [ layers.Dense(units=units, activation="relu"), @@ -1344,21 +1444,20 @@ def keras_code(units, optimizer, saving_path): loss="mean_squared_error", ) - # Prepare data + # 데이터 준비 x_train = np.random.rand(100, 10) y_train = np.random.rand(100, 1) x_val = np.random.rand(20, 10) y_val = np.random.rand(20, 1) - # Train & eval model + # 모델 트레이닝 및 평가 model.fit(x_train, y_train) - # Save model + # 모델 저장 model.save(saving_path) - # Return a single float as the objective value. - # You may also return a dictionary - # of {metric_name: metric_value}. + # 목표 값으로 단일 float를 반환. + # {metric_name: metric_value} 형식의 딕셔너리를 반환할 수도 있습니다. y_pred = model.predict(x_val) return np.mean(np.abs(y_pred - y_val)) @@ -1380,7 +1479,7 @@ tuner = MyTuner( project_name="keep_code_separate", ) tuner.search() -# Retraining the model +# 모델 재트레이닝 best_hp = tuner.get_best_hyperparameters()[0] keras_code(**best_hp.values, saving_path="/tmp/best_model.keras") ``` @@ -1423,11 +1522,11 @@ Total elapsed time: 00h 00m 03s {{% /details %}} -## KerasTuner includes pre-made tunable applications: HyperResNet and HyperXception +## KerasTuner에는 사전 제작된 튜닝 가능한 애플리케이션 HyperResNet 및 HyperXception이 포함되어 있습니다. {#kerastuner-includes-pre-made-tunable-applications-hyperresnet-and-hyperxception} -These are ready-to-use hypermodels for computer vision. +이들은 컴퓨터 비전을 위한 즉시 사용 가능한 하이퍼모델입니다. -They come pre-compiled with `loss="categorical_crossentropy"` and `metrics=["accuracy"]`. +이 모델들은 `loss="categorical_crossentropy"`와 `metrics=["accuracy"]`로 사전 컴파일되어 있습니다. ```python from keras_tuner.applications import HyperResNet diff --git a/content/korean/docs/guides/keras_tuner/tailor_the_search_space/_index.md b/content/korean/docs/guides/keras_tuner/tailor_the_search_space/_index.md index 308247a7..6bad533f 100644 --- a/content/korean/docs/guides/keras_tuner/tailor_the_search_space/_index.md +++ b/content/korean/docs/guides/keras_tuner/tailor_the_search_space/_index.md @@ -1,6 +1,6 @@ --- -title: Tailor the search space -linkTitle: Tailor the search space +title: 검색 공간 맞춤 설정 +linkTitle: 검색 공간 맞춤 설정 toc: true weight: 6 type: docs @@ -8,10 +8,10 @@ type: docs {{< keras/original checkedAt="2024-11-19" >}} -**Authors:** Luca Invernizzi, James Long, Francois Chollet, Tom O'Malley, Haifeng Jin +**{{< t f_author >}}** Luca Invernizzi, James Long, Francois Chollet, Tom O'Malley, Haifeng Jin **{{< t f_date_created >}}** 2019/05/31 **{{< t f_last_modified >}}** 2021/10/27 -**{{< t f_description >}}** Tune a subset of the hyperparameters without changing the hypermodel. +**{{< t f_description >}}** 하이퍼모델을 변경하지 않고, 하이퍼파라미터의 일부만 튜닝하기. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_tuner/tailor_the_search_space.ipynb" title="Colab" tag="Colab" tagType="warning">}} @@ -22,21 +22,27 @@ type: docs !pip install keras-tuner -q ``` -In this guide, we will show how to tailor the search space without changing the `HyperModel` code directly. For example, you can only tune some of the hyperparameters and keep the rest fixed, or you can override the compile arguments, like `optimizer`, `loss`, and `metrics`. +이 가이드에서는, `HyperModel` 코드를 직접 변경하지 않고, 검색 공간을 맞춤 설정하는 방법을 보여줍니다. +예를 들어, 일부 하이퍼파라미터만 튜닝하고 나머지는 고정하거나, +`optimizer`, `loss`, `metrics`와 같은 컴파일 인수를 재정의할 수 있습니다. -## The default value of a hyperparameter +## 하이퍼파라미터의 기본값 {#the-default-value-of-a-hyperparameter} -Before we tailor the search space, it is important to know that every hyperparameter has a default value. This default value is used as the hyperparameter value when not tuning it during our tailoring the search space. +검색 공간을 맞춤 설정하기 전에, +모든 하이퍼파라미터에는 기본값이 있다는 것을 알아야 합니다. +이 기본값은 검색 공간을 맞춤 설정할 때, +해당 하이퍼파라미터를 튜닝하지 않는 경우에 사용됩니다. -Whenever you register a hyperparameter, you can use the `default` argument to specify a default value: +하이퍼파라미터를 등록할 때 `default` 인수를 사용하여, 기본값을 지정할 수 있습니다. ```python hp.Int("units", min_value=32, max_value=128, step=32, default=64) ``` -If you don't, hyperparameters always have a default default (for `Int`, it is equal to `min_value`). +기본값을 지정하지 않으면, 하이퍼파라미터에는 기본값이 자동으로 지정됩니다. +(`Int`의 경우 `min_value`와 동일한 값) -In the following model-building function, we specified the default value for the `units` hyperparameter as 64. +다음 모델 빌딩 함수에서, `units` 하이퍼파라미터의 기본값을 64로 지정했습니다. ```python import keras @@ -66,25 +72,30 @@ def build_model(hp): return model ``` -We will reuse this search space in the rest of the tutorial by overriding the hyperparameters without defining a new search space. +우리는 튜토리얼의 나머지 부분에서 새로운 검색 공간을 정의하지 않고, +하이퍼파라미터를 재정의하여 이 검색 공간을 재사용할 것입니다. -## Search a few and fix the rest +## 일부만 검색하고 나머지는 고정 {#search-a-few-and-fix-the-rest} -If you have an existing hypermodel, and you want to search over only a few hyperparameters, and keep the rest fixed, you don't have to change the code in the model-building function or the `HyperModel`. You can pass a `HyperParameters` to the `hyperparameters` argument to the tuner constructor with all the hyperparameters you want to tune. Specify `tune_new_entries=False` to prevent it from tuning other hyperparameters, the default value of which would be used. +기존의 하이퍼모델이 있고, 일부 하이퍼파라미터만 검색하고 나머지는 고정하고 싶다면, +모델 빌딩 함수나 `HyperModel` 코드에서 변경할 필요가 없습니다. +튜너 생성자에서 `hyperparameters` 인수로 검색하려는 모든 하이퍼파라미터를 포함한, +`HyperParameters` 객체를 전달할 수 있습니다. +다른 하이퍼파라미터의 튜닝을 방지하려면, `tune_new_entries=False`를 지정하여, +나머지 하이퍼파라미터는 기본값을 사용하도록 설정합니다. -In the following example, we only tune the `learning_rate` hyperparameter, and changed its type and value ranges. +다음 예시에서 우리는 `learning_rate` 하이퍼파라미터만 튜닝하며, 그 타입과 값 범위를 변경했습니다. ```python hp = keras_tuner.HyperParameters() -# This will override the `learning_rate` parameter with your -# own selection of choices +# `learning_rate` 파라미터를 사용자가 선택한 값으로 재정의 hp.Float("learning_rate", min_value=1e-4, max_value=1e-2, sampling="log") tuner = keras_tuner.RandomSearch( hypermodel=build_model, hyperparameters=hp, - # Prevents unlisted parameters from being tuned + # 나열되지 않은 파라미터는 튜닝하지 않음 tune_new_entries=False, objective="val_accuracy", max_trials=3, @@ -93,13 +104,13 @@ tuner = keras_tuner.RandomSearch( project_name="search_a_few", ) -# Generate random data +# 랜덤 데이터 생성 x_train = np.random.rand(100, 28, 28, 1) y_train = np.random.randint(0, 10, (100, 1)) x_val = np.random.rand(20, 28, 28, 1) y_val = np.random.randint(0, 10, (20, 1)) -# Run the search +# 검색 실행 tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val)) ``` @@ -117,7 +128,7 @@ Total elapsed time: 00h 00m 03s {{% /details %}} -If you summarize the search space, you will see only one hyperparameter. +하이퍼파라미터 검색 공간을 요약하면, 단 하나의 하이퍼파라미터만 볼 수 있습니다. ```python tuner.search_space_summary() @@ -134,11 +145,14 @@ learning_rate (Float) {{% /details %}} -## Fix a few and tune the rest +## 일부를 고정하고 나머지를 튜닝 {#fix-a-few-and-tune-the-rest} -In the example above we showed how to tune only a few hyperparameters and keep the rest fixed. You can also do the reverse: only fix a few hyperparameters and tune all the rest. +위 예시에서는 일부 하이퍼파라미터만 튜닝하고 나머지는 고정하는 방법을 보여주었습니다. +반대로, 일부 하이퍼파라미터만 고정하고 나머지를 모두 튜닝할 수도 있습니다. -In the following example, we fixed the value of the `learning_rate` hyperparameter. Pass a `hyperparameters` argument with a `Fixed` entry (or any number of `Fixed` entries). Also remember to specify `tune_new_entries=True`, which allows us to tune the rest of the hyperparameters. +다음 예시에서는 `learning_rate` 하이퍼파라미터의 값을 고정했습니다. +`Fixed` 항목을 포함한 `hyperparameters` 인수를 전달하고, +`tune_new_entries=True`로 설정하여 나머지 하이퍼파라미터를 튜닝할 수 있습니다. ```python hp = keras_tuner.HyperParameters() @@ -172,7 +186,8 @@ Total elapsed time: 00h 00m 03s {{% /details %}} -If you summarize the search space, you will see the `learning_rate` is marked as fixed, and the rest of the hyperparameters are being tuned. +검색 공간을 요약하면, `learning_rate`는 고정된 것으로 표시되고, +나머지 하이퍼파라미터는 튜닝되고 있음을 확인할 수 있습니다. ```python tuner.search_space_summary() @@ -193,9 +208,10 @@ dropout (Boolean) {{% /details %}} -## Overriding compilation arguments +## 컴파일 인수 재정의 {#overriding-compilation-arguments} -If you have a hypermodel for which you want to change the existing optimizer, loss, or metrics, you can do so by passing these arguments to the tuner constructor: +기존 하이퍼모델에서 옵티마이저, 손실 함수, 또는 메트릭스를 변경하고 싶다면, +이러한 인수를 튜너 생성자에 전달하여 변경할 수 있습니다. ```python tuner = keras_tuner.RandomSearch( @@ -229,7 +245,7 @@ Total elapsed time: 00h 00m 04s {{% /details %}} -If you get the best model, you can see the loss function has changed to MSE. +최상의 모델을 얻으면, 손실 함수가 MSE로 변경된 것을 확인할 수 있습니다. ```python tuner.get_best_models()[0].loss @@ -246,27 +262,34 @@ tuner.get_best_models()[0].loss {{% /details %}} -## Tailor the search space of pre-build HyperModels +## 미리 빌드된 하이퍼모델의 검색 공간 맞춤 설정 {#tailor-the-search-space-of-pre-build-hypermodels} -You can also use these techniques with the pre-build models in KerasTuner, like `HyperResNet` or `HyperXception`. However, to see what hyperparameters are in these pre-build `HyperModel`s, you will have to read the source code. +이 기술은 KerasTuner의 `HyperResNet`이나 `HyperXception`과 같은 +미리 빌드된 모델에서도 사용할 수 있습니다. +그러나, 이러한 미리 빌드된 `HyperModel`에서 +어떤 하이퍼파라미터가 있는지 확인하려면, 소스 코드를 읽어야 합니다. -In the following example, we only tune the `learning_rate` of `HyperXception` and fixed all the rest of the hyperparameters. Because the default loss of `HyperXception` is `categorical_crossentropy`, which expect the labels to be one-hot encoded, which doesn't match our raw integer label data, we need to change it by overriding the `loss` in the compile args to `sparse_categorical_crossentropy`. +다음 예시에서는, `HyperXception`의 `learning_rate`만 튜닝하고, +나머지 하이퍼파라미터는 모두 고정했습니다. +`HyperXception`의 기본 손실 함수는 `categorical_crossentropy`인데, +이는 라벨이 원-핫 인코딩된 데이터를 기대합니다. +우리의 정수형 라벨 데이터와 맞지 않으므로, +컴파일 인수에서 `loss`를 `sparse_categorical_crossentropy`로 재정의해야 합니다. ```python hypermodel = keras_tuner.applications.HyperXception(input_shape=(28, 28, 1), classes=10) hp = keras_tuner.HyperParameters() -# This will override the `learning_rate` parameter with your -# own selection of choices +# `learning_rate` 파라미터를 사용자가 선택한 값으로 재정의 hp.Choice("learning_rate", values=[1e-2, 1e-3, 1e-4]) tuner = keras_tuner.RandomSearch( hypermodel, hyperparameters=hp, - # Prevents unlisted parameters from being tuned + # 나열되지 않은 파라미터는 튜닝하지 않음 tune_new_entries=False, - # Override the loss. + # 손실 함수 재정의 loss="sparse_categorical_crossentropy", metrics=["accuracy"], objective="val_accuracy", @@ -276,7 +299,7 @@ tuner = keras_tuner.RandomSearch( project_name="helloworld", ) -# Run the search +# 검색 실행 tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val)) tuner.search_space_summary() ``` diff --git a/content/korean/docs/guides/keras_tuner/visualize_tuning/_index.md b/content/korean/docs/guides/keras_tuner/visualize_tuning/_index.md index c8a6d2e6..3041728f 100644 --- a/content/korean/docs/guides/keras_tuner/visualize_tuning/_index.md +++ b/content/korean/docs/guides/keras_tuner/visualize_tuning/_index.md @@ -1,6 +1,6 @@ --- -title: Visualize the hyperparameter tuning process -linkTitle: Visualize the hyperparameter tuning process +title: 하이퍼파라미터 튜닝 과정 시각화 +linkTitle: 튜닝 과정 시각화 toc: true weight: 4 type: docs @@ -11,7 +11,7 @@ type: docs **{{< t f_author >}}** Haifeng Jin **{{< t f_date_created >}}** 2021/06/25 **{{< t f_last_modified >}}** 2021/06/05 -**{{< t f_description >}}** Using TensorBoard to visualize the hyperparameter tuning process in KerasTuner. +**{{< t f_description >}}** TensorBoard 사용하여, KerasTuner에서 하이퍼파라미터 튜닝 과정을 시각화. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/keras_tuner/visualize_tuning.ipynb" title="Colab" tag="Colab" tagType="warning">}} @@ -22,15 +22,24 @@ type: docs !pip install keras-tuner -q ``` -## Introduction +## 소개 {#introduction} -KerasTuner prints the logs to screen including the values of the hyperparameters in each trial for the user to monitor the progress. However, reading the logs is not intuitive enough to sense the influences of hyperparameters have on the results, Therefore, we provide a method to visualize the hyperparameter values and the corresponding evaluation results with interactive figures using TensorBoard. +KerasTuner는 각 시도에서 하이퍼파라미터의 값을 포함한 로그를 화면에 출력하여, +사용자가 진행 상황을 모니터링할 수 있게 합니다. +그러나 로그만 읽는 것은 하이퍼파라미터가 결과에 미치는 영향을 직관적으로 이해하기에 충분하지 않을 수 있습니다. +따라서, TensorBoard를 사용하여 상호작용 가능한 그림을 통해, +하이퍼파라미터 값과 해당 평가 결과를 시각화하는 방법을 제공합니다. -[TensorBoard](https://www.tensorflow.org/tensorboard) is a useful tool for visualizing the machine learning experiments. It can monitor the losses and metrics during the model training and visualize the model architectures. Running KerasTuner with TensorBoard will give you additional features for visualizing hyperparameter tuning results using its HParams plugin. +[TensorBoard](https://www.tensorflow.org/tensorboard)는 +머신 러닝 실험을 시각화하는 데 유용한 도구입니다. +모델 트레이닝 중 손실과 메트릭을 모니터링하고 모델 아키텍처를 시각화할 수 있습니다. +KerasTuner를 TensorBoard와 함께 사용하면, +HParams 플러그인을 통해 하이퍼파라미터 튜닝 결과를 시각화하는 추가 기능을 제공받을 수 있습니다. -We will use a simple example of tuning a model for the MNIST image classification dataset to show how to use KerasTuner with TensorBoard. +여기서는 KerasTuner와 TensorBoard를 사용하는 방법을 보여주기 위해, +MNIST 이미지 분류 데이터셋을 튜닝하는 간단한 예를 사용합니다. -The first step is to download and format the data. +첫 번째 단계는 데이터를 다운로드하고 형식을 지정하는 것입니다. ```python import numpy as np @@ -39,13 +48,13 @@ import keras from keras import layers (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() -# Normalize the pixel values to the range of [0, 1]. +# 픽셀 값을 [0, 1] 범위로 정규화합니다. x_train = x_train.astype("float32") / 255 x_test = x_test.astype("float32") / 255 -# Add the channel dimension to the images. +# 이미지에 채널 차원을 추가합니다. x_train = np.expand_dims(x_train, -1) x_test = np.expand_dims(x_test, -1) -# Print the shapes of the data. +# 데이터의 모양을 출력합니다. print(x_train.shape) print(y_train.shape) print(x_test.shape) @@ -63,26 +72,28 @@ print(y_test.shape) {{% /details %}} -Then, we write a `build_model` function to build the model with hyperparameters and return the model. The hyperparameters include the type of model to use (multi-layer perceptron or convolutional neural network), the number of layers, the number of units or filters, whether to use dropout. +그런 다음, `build_model` 함수를 작성하여, +하이퍼파라미터와 함께 모델을 빌드하고 해당 모델을 반환합니다. +하이퍼파라미터에는 사용할 모델 타입(다층 퍼셉트론(MLP) 또는 컨볼루션 신경망(CNN)), +레이어 수, 유닛 또는 필터의 수, 드롭아웃 사용 여부가 포함됩니다. ```python def build_model(hp): inputs = keras.Input(shape=(28, 28, 1)) - # Model type can be MLP or CNN. + # 모델 타입은 MLP 또는 CNN일 수 있습니다. model_type = hp.Choice("model_type", ["mlp", "cnn"]) x = inputs if model_type == "mlp": x = layers.Flatten()(x) - # Number of layers of the MLP is a hyperparameter. + # MLP의 레이어 수는 하이퍼파라미터입니다. for i in range(hp.Int("mlp_layers", 1, 3)): - # Number of units of each layer are - # different hyperparameters with different names. + # 각 레이어의 유닛 수는, 다른 이름을 가진 하이퍼파라미터입니다. x = layers.Dense( units=hp.Int(f"units_{i}", 32, 128, step=32), activation="relu", )(x) else: - # Number of layers of the CNN is also a hyperparameter. + # CNN의 레이어 수도 하이퍼파라미터입니다. for i in range(hp.Int("cnn_layers", 1, 3)): x = layers.Conv2D( hp.Int(f"filters_{i}", 32, 128, step=32), @@ -92,16 +103,15 @@ def build_model(hp): x = layers.MaxPooling2D(pool_size=(2, 2))(x) x = layers.Flatten()(x) - # A hyperparamter for whether to use dropout layer. + # 드롭아웃 레이어를 사용할지 여부는 하이퍼파라미터입니다. if hp.Boolean("dropout"): x = layers.Dropout(0.5)(x) - # The last layer contains 10 units, - # which is the same as the number of classes. + # 마지막 레이어는 10개의 유닛을 포함하며, 이는 클래스 수와 동일합니다. outputs = layers.Dense(units=10, activation="softmax")(x) model = keras.Model(inputs=inputs, outputs=outputs) - # Compile the model. + # 모델을 컴파일합니다. model.compile( loss="sparse_categorical_crossentropy", metrics=["accuracy"], @@ -110,20 +120,20 @@ def build_model(hp): return model ``` -We can do a quick test of the models to check if it build successfully for both CNN and MLP. +CNN과 MLP 모두에 대해 모델이 성공적으로 빌드되는지 확인하기 위해 빠르게 테스트할 수 있습니다. ```python -# Initialize the `HyperParameters` and set the values. +# `HyperParameters`를 초기화하고 값을 설정합니다. hp = keras_tuner.HyperParameters() hp.values["model_type"] = "cnn" -# Build the model using the `HyperParameters`. +# `HyperParameters`를 사용하여 모델을 빌드합니다. model = build_model(hp) -# Test if the model runs with our data. +# 모델이 데이터에서 실행되는지 테스트합니다. model(x_train[:100]) -# Print a summary of the model. +# 모델의 요약을 출력합니다. model.summary() -# Do the same for MLP model. +# MLP 모델에 대해서도 동일하게 실행합니다. hp.values["model_type"] = "mlp" model = build_model(hp) model(x_train[:100]) @@ -169,21 +179,24 @@ Model: "functional_3" {{% /details %}} -Initialize the `RandomSearch` tuner with 10 trials and using validation accuracy as the metric for selecting models. +`RandomSearch` 튜너를 10번의 시도와 함께 초기화하고, +모델 선택을 위한 지표로 검증 정확도(`val_accuracy`)를 사용합니다. ```python tuner = keras_tuner.RandomSearch( build_model, max_trials=10, - # Do not resume the previous search in the same directory. + # 같은 디렉토리에서 이전 검색을 다시 시작하지 않도록 설정합니다. overwrite=True, objective="val_accuracy", - # Set a directory to store the intermediate results. + # 중간 결과를 저장할 디렉토리를 설정합니다. directory="/tmp/tb", ) ``` -Start the search by calling `tuner.search(...)`. To use TensorBoard, we need to pass a [`keras.callbacks.TensorBoard`]({{< relref "/docs/api/callbacks/tensorboard#tensorboard-class" >}}) instance to the callbacks. +`tuner.search(...)`를 호출하여 하이퍼파라미터 검색을 시작합니다. +TensorBoard를 사용하려면, +콜백에 [`keras.callbacks.TensorBoard`]({{< relref "/docs/api/callbacks/tensorboard#tensorboard-class" >}}) 인스턴스를 전달해야 합니다. ```python tuner.search( @@ -191,8 +204,8 @@ tuner.search( y_train, validation_split=0.2, epochs=2, - # Use the TensorBoard callback. - # The logs will be write to "/tmp/tb_logs". + # TensorBoard 콜백을 사용합니다. + # 로그는 "/tmp/tb_logs"에 기록됩니다. callbacks=[keras.callbacks.TensorBoard("/tmp/tb_logs")], ) ``` @@ -211,7 +224,7 @@ Total elapsed time: 00h 08m 32s {{% /details %}} -If running in Colab, the following two commands will show you the TensorBoard inside Colab. +Colab에서 실행 중인 경우, 아래 두 명령어로 TensorBoard를 Colab 내부에서 확인할 수 있습니다. ```python %load_ext tensorboard @@ -219,25 +232,38 @@ If running in Colab, the following two commands will show you the TensorBoard in %tensorboard --logdir /tmp/tb_logs ``` -You have access to all the common features of the TensorBoard. For example, you can view the loss and metrics curves and visualize the computational graph of the models in different trials. +모든 일반적인 TensorBoard 기능을 사용할 수 있습니다. +예를 들어, 손실과 메트릭 곡선을 확인하거나, +다양한 시도에서 생성된 모델의 계산 그래프를 시각화할 수 있습니다. ![Loss and metrics curves](/images/guides/keras_tuner/visualize_tuning/ShulDtI.png) ![Computational graphs](/images/guides/keras_tuner/visualize_tuning/8sRiT1I.png) -In addition to these features, we also have a HParams tab, in which there are three views. In the table view, you can view the 10 different trials in a table with the different hyperparameter values and evaluation metrics. +이 기능 외에도 HParams 탭이 있으며, 여기에는 세 가지 뷰가 제공됩니다. +테이블 뷰에서는, 서로 다른 하이퍼파라미터 값과 평가 메트릭을 포함한, +10개의 서로 다른 시도를 테이블 형식으로 확인할 수 있습니다. ![Table view](/images/guides/keras_tuner/visualize_tuning/OMcQdOw.png) -On the left side, you can specify the filters for certain hyperparameters. For example, you can specify to only view the MLP models without the dropout layer and with 1 to 2 dense layers. +왼쪽에서, 특정 하이퍼파라미터에 대한 필터를 지정할 수 있습니다. +예를 들어, 드롭아웃 레이어가 없는 MLP 모델만 표시하고, +1~2개의 dense 레이어를 가진 모델만 선택할 수 있습니다. ![Filtered table view](/images/guides/keras_tuner/visualize_tuning/yZpfaxN.png) -Besides the table view, it also provides two other views, parallel coordinates view and scatter plot matrix view. They are just different visualization methods for the same data. You can still use the panel on the left to filter the results. +테이블 뷰 외에도, +평행 좌표 뷰(parallel coordinates view)와 +산점도 행렬 뷰(scatter plot matrix view)라는 +두 가지 추가 뷰를 제공합니다. +동일한 데이터를 다른 방식으로 시각화한 것입니다. +왼쪽 패널을 사용하여 결과를 필터링할 수 있습니다. -In the parallel coordinates view, each colored line is a trial. The axes are the hyperparameters and evaluation metrics. +평행 좌표 뷰에서는, 각 색상이 다른 시도를 나타냅니다. +축은 하이퍼파라미터와 평가 메트릭을 나타냅니다. ![Parallel coordinates view](/images/guides/keras_tuner/visualize_tuning/PJ7HQUQ.png) -In the scatter plot matrix view, each dot is a trial. The plots are projections of the trials on planes with different hyperparameter and metrics as the axes. +산점도 행렬 뷰에서는, 각 점이 하나의 시도를 나타냅니다. +이 뷰는 하이퍼파라미터와 메트릭을 축으로 하는 평면에 시도 결과를 프로젝션한 것입니다. ![Scatter plot matrix view](/images/guides/keras_tuner/visualize_tuning/zjPjh6o.png) diff --git a/content/korean/docs/guides/making_new_layers_and_models_via_subclassing/_index.md b/content/korean/docs/guides/making_new_layers_and_models_via_subclassing/_index.md index 81cf1bad..3f2696c1 100644 --- a/content/korean/docs/guides/making_new_layers_and_models_via_subclassing/_index.md +++ b/content/korean/docs/guides/making_new_layers_and_models_via_subclassing/_index.md @@ -1,5 +1,6 @@ --- -title: Making new layers and models via subclassing +title: 서브클래싱을 통해 새로운 레이어와 모델 만들기 +linkTitle: 서브클래싱 레이어 및 모델 toc: true weight: 3 type: docs @@ -10,30 +11,31 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2019/03/01 **{{< t f_last_modified >}}** 2023/06/25 -**{{< t f_description >}}** Complete guide to writing `Layer` and `Model` objects from scratch. +**{{< t f_description >}}** `Layer`와 `Model` 객체를 처음부터 작성하는 방법에 대한 완벽 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/making_new_layers_and_models_via_subclassing.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/making_new_layers_and_models_via_subclassing.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -This guide will cover everything you need to know to build your own subclassed layers and models. In particular, you'll learn about the following features: +이 가이드에서는 자체 서브클래싱된 레이어와 모델을 빌드하는 데 필요한 모든 내용을 다룹니다. +특히, 다음 기능에 대해 알아봅니다. -- The `Layer` class -- The `add_weight()` method -- Trainable and non-trainable weights -- The `build()` method -- Making sure your layers can be used with any backend -- The `add_loss()` method -- The `training` argument in `call()` -- The `mask` argument in `call()` -- Making sure your layers can be serialized +- `Layer` 클래스 +- `add_weight()` 메서드 +- 트레이닝 가능한 가중치와 트레이닝 불가능한 가중치 +- `build()` 메서드 +- 레이어를 모든 백엔드에서 사용할 수 있는지 확인 +- `add_loss()` 메서드 +- `call()`의 `training` 인수 +- `call()`의 `mask` 인수 +- 레이어를 직렬화할 수 있는지 확인 -Let's dive in. +자세히 알아보겠습니다. -## Setup +## 셋업 {#setup} ```python import numpy as np @@ -42,11 +44,13 @@ from keras import ops from keras import layers ``` -## The `Layer` class: the combination of state (weights) and some computation +## `Layer` 클래스: 상태(가중치)와 일부 계산의 조합 {#the-layer-class-the-combination-of-state-weights-and-some-computation} -One of the central abstractions in Keras is the `Layer` class. A layer encapsulates both a state (the layer's "weights") and a transformation from inputs to outputs (a "call", the layer's forward pass). +Keras의 중심 추상화 중 하나는 `Layer` 클래스입니다. +레이어는 상태(레이어의 "가중치")와 입력에서 출력으로의 변환(레이어의 포워드 패스인 "호출")을 모두 캡슐화합니다. -Here's a densely-connected layer. It has two state variables: the variables `w` and `b`. +다음은 밀집 연결(densely-connected) 레이어입니다. +여기에는 두 개의 상태 변수가 있습니다. 변수 `w`와 `b`입니다. ```python class Linear(keras.layers.Layer): @@ -63,7 +67,7 @@ class Linear(keras.layers.Layer): return ops.matmul(inputs, self.w) + self.b ``` -You would use a layer by calling it on some tensor input(s), much like a Python function. +(Python 함수처럼) 텐서 입력에 대해 호출하여 레이어를 사용합니다. ```python x = ops.ones((2, 2)) @@ -81,17 +85,18 @@ print(y) {{% /details %}} -Note that the weights `w` and `b` are automatically tracked by the layer upon being set as layer attributes: +가중치 `w`와 `b`는 레이어 속성으로 설정되면, 레이어에서 자동으로 추적됩니다. ```python assert linear_layer.weights == [linear_layer.w, linear_layer.b] ``` -## Layers can have non-trainable weights +## 레이어는 트레이닝 불가능한 가중치를 가질 수 있습니다. {#layers-can-have-non-trainable-weights} -Besides trainable weights, you can add non-trainable weights to a layer as well. Such weights are meant not to be taken into account during backpropagation, when you are training the layer. +트레이닝 가능한 가중치 외에도, 레이어에 트레이닝 불가능한 가중치를 추가할 수 있습니다. +이러한 가중치는, 레이어를 트레이닝할 때, 역전파 중에 고려되지 않아야 합니다. -Here's how to add and use a non-trainable weight: +트레이닝 불가능한 가중치를 추가하고 사용하는 방법은 다음과 같습니다. ```python class ComputeSum(keras.layers.Layer): @@ -123,13 +128,13 @@ print(y.numpy()) {{% /details %}} -It's part of `layer.weights`, but it gets categorized as a non-trainable weight: +이는 `layer.weights`의 일부이지만, 트레이닝 불가능한 가중치로 분류됩니다. ```python print("weights:", len(my_sum.weights)) print("non-trainable weights:", len(my_sum.non_trainable_weights)) -# It's not included in the trainable weights: +# 트레이닝 가능한 가중치에 포함되지 않습니다. print("trainable_weights:", my_sum.trainable_weights) ``` @@ -143,9 +148,10 @@ trainable_weights: [] {{% /details %}} -## Best practice: deferring weight creation until the shape of the inputs is known +## 모범 사례: 입력 모양이 알려질 때까지, 가중치 생성을 연기합니다. {#best-practice-deferring-weight-creation-until-the-shape-of-the-inputs-is-known} -Our `Linear` layer above took an `input_dim` argument that was used to compute the shape of the weights `w` and `b` in `__init__()`: +우리의 `Linear` 레이어는, `__init__()`에서 가중치 `w`와 `b`의 모양을 계산하는 데 사용된, +`input_dim` 인수를 사용했습니다. ```python class Linear(keras.layers.Layer): @@ -162,9 +168,12 @@ class Linear(keras.layers.Layer): return ops.matmul(inputs, self.w) + self.b ``` -In many cases, you may not know in advance the size of your inputs, and you would like to lazily create weights when that value becomes known, some time after instantiating the layer. +많은 경우, 입력 크기를 미리 알 수 없으며, +레이어를 인스턴스화한 얼마간 이후, 해당 값이 알려질 때, +지연하여(lazily) 가중치를 생성하고 싶을 것입니다. -In the Keras API, we recommend creating layer weights in the `build(self, inputs_shape)` method of your layer. Like this: +Keras API에서, 레이어의 `build(self, inputs_shape)` 메서드에서 레이어 가중치를 생성하는 것이 좋습니다. +다음과 같이 합니다. ```python class Linear(keras.layers.Layer): @@ -186,23 +195,28 @@ class Linear(keras.layers.Layer): return ops.matmul(inputs, self.w) + self.b ``` -The `__call__()` method of your layer will automatically run build the first time it is called. You now have a layer that's lazy and thus easier to use: +레이어의 `__call__()` 메서드는 처음 호출될 때 자동으로 빌드를 실행합니다. +이제 지연되고(lazy), 사용하기 쉬운 레이어가 생겼습니다. ```python -# At instantiation, we don't know on what inputs this is going to get called +# 인스턴스화 시, 이것이 어떤 입력에 대해 호출될지 알 수 없습니다. linear_layer = Linear(32) -# The layer's weights are created dynamically the first time the layer is called +# 레이어의 가중치는 레이어가 처음 호출될 때 동적으로 생성됩니다. y = linear_layer(x) ``` -Implementing `build()` separately as shown above nicely separates creating weights only once from using weights in every call. +위에 표시된 것처럼 `build()`를 별도로 구현하면, +가중치를 한 번만 생성하는 것과, +모든 호출에서 가중치를 사용하는 것을 깔끔하게 분리할 수 있습니다. -## Layers are recursively composable +## 레이어는 재귀적으로 구성 가능합니다. {#layers-are-recursively-composable} -If you assign a Layer instance as an attribute of another Layer, the outer layer will start tracking the weights created by the inner layer. +Layer 인스턴스를 다른 Layer의 속성으로 할당하면, +외부 레이어는 내부 레이어에서 생성된 가중치를 추적하기 시작합니다. -We recommend creating such sublayers in the `__init__()` method and leave it to the first `__call__()` to trigger building their weights. +우리는 `__init__()` 메서드에서 이러한 하위 레이어를 생성하고, +첫 번째 `__call__()`에서 그들의 가중치를 빌드하도록 트리거하는 것을 권장합니다. ```python class MLPBlock(keras.layers.Layer): @@ -221,7 +235,7 @@ class MLPBlock(keras.layers.Layer): mlp = MLPBlock() -y = mlp(ops.ones(shape=(3, 64))) # The first call to the `mlp` will create the weights +y = mlp(ops.ones(shape=(3, 64))) # `mlp`에 대한 첫 번째 호출은 가중치를 생성합니다. print("weights:", len(mlp.weights)) print("trainable weights:", len(mlp.trainable_weights)) ``` @@ -235,18 +249,21 @@ trainable weights: 6 {{% /details %}} -## Backend-agnostic layers and backend-specific layers +## 백엔드에 독립적인 레이어와 백엔드에 특화된 레이어 {#backend-agnostic-layers-and-backend-specific-layers} -As long as a layer only uses APIs from the `keras.ops` namespace (or other Keras namespaces such as `keras.activations`, `keras.random`, or `keras.layers`), then it can be used with any backend – TensorFlow, JAX, or PyTorch. +레이어가 `keras.ops` 네임스페이스(또는 `keras.activations`, `keras.random` 또는 `keras.layers`와 같은 그 외 Keras 네임스페이스)의 API만 사용하는 한, +TensorFlow, JAX 또는 PyTorch와 같은 모든 백엔드에서 사용할 수 있습니다. -All layers you've seen so far in this guide work with all Keras backends. +이 가이드에서 지금까지 본 모든 레이어는 모든 Keras 백엔드에서 작동합니다. -The `keras.ops` namespace gives you access to: +`keras.ops` 네임스페이스는 다음에 대한 액세스를 제공합니다. -- The NumPy API, e.g. `ops.matmul`, `ops.sum`, `ops.reshape`, `ops.stack`, etc. -- Neural networks-specific APIs such as `ops.softmax`, `ops`.conv`,`ops.binary_crossentropy`,`ops.relu\`, etc. +- NumPy API, 예: `ops.matmul`, `ops.sum`, `ops.reshape`, `ops.stack` 등 +- `ops.softmax`, `ops.conv`, `ops.binary_crossentropy`, `ops.relu` 등과 같은 신경망 전용 API -You can also use backend-native APIs in your layers (such as [`tf.nn`](https://www.tensorflow.org/api_docs/python/tf/nn) functions), but if you do this, then your layer will only be usable with the backend in question. For instance, you could write the following JAX-specific layer using `jax.numpy`: +레이어에서 백엔드 네이티브 API(예: [`tf.nn`](https://www.tensorflow.org/api_docs/python/tf/nn) 함수)를 사용할 수도 있지만, +이렇게 하면 레이어는 해당 백엔드에서만 사용할 수 있습니다. +예를 들어, `jax.numpy`를 사용하여 다음과 같은 JAX 전용 레이어를 작성할 수 있습니다. ```python import jax @@ -258,7 +275,7 @@ class Linear(keras.layers.Layer): return jax.numpy.matmul(inputs, self.w) + self.b ``` -This would be the equivalent TensorFlow-specific layer: +이것은 동등한 TensorFlow 전용 레이어 입니다. ```python import tensorflow as tf @@ -270,7 +287,7 @@ class Linear(keras.layers.Layer): return tf.matmul(inputs, self.w) + self.b ``` -And this would be the equivalent PyTorch-specific layer: +그리고 이것은 동등한 PyTorch 전용 레이어 입니다: ```python import torch @@ -282,14 +299,17 @@ class Linear(keras.layers.Layer): return torch.matmul(inputs, self.w) + self.b ``` -Because cross-backend compatibility is a tremendously useful property, we strongly recommend that you seek to always make your layers backend-agnostic by leveraging only Keras APIs. +크로스 백엔드 호환성은 매우 유용한 속성이므로, +Keras API만 활용하여 레이어를 항상 백엔드에 독립적으로 만드는 것이 좋습니다. -## The `add_loss()` method +## `add_loss()` 메서드 {#the-addloss-method} -When writing the `call()` method of a layer, you can create loss tensors that you will want to use later, when writing your training loop. This is doable by calling `self.add_loss(value)`: +레이어의 `call()` 메서드를 작성할 때, +나중에 트레이닝 루프를 작성할 때, 사용하고 싶은 손실 텐서를 만들 수 있습니다. +`self.add_loss(value)`를 호출하면 가능합니다. ```python -# A layer that creates an activity regularization loss +# 활동 정규화 손실(activity regularization loss)을 생성하는 레이어 class ActivityRegularizationLayer(keras.layers.Layer): def __init__(self, rate=1e-2): super().__init__() @@ -300,7 +320,9 @@ class ActivityRegularizationLayer(keras.layers.Layer): return inputs ``` -These losses (including those created by any inner layer) can be retrieved via `layer.losses`. This property is reset at the start of every `__call__()` to the top-level layer, so that `layer.losses` always contains the loss values created during the last forward pass. +이러한 손실(내부 레이어에서 생성된 손실 포함)은 `layer.losses`를 통해 검색할 수 있습니다. +이 속성은 최상위 레이어에 대한 모든 `__call__()` 시작 시 재설정되므로, +`layer.losses`는 항상 마지막 전방 패스(forward pass) 중에 생성된 손실 값을 포함합니다. ```python class OuterLayer(keras.layers.Layer): @@ -313,17 +335,17 @@ class OuterLayer(keras.layers.Layer): layer = OuterLayer() -assert len(layer.losses) == 0 # No losses yet since the layer has never been called +assert len(layer.losses) == 0 # 레이어가 호출된 적이 없으므로 아직 손실이 없습니다. _ = layer(ops.zeros((1, 1))) -assert len(layer.losses) == 1 # We created one loss value +assert len(layer.losses) == 1 # 우리는 하나의 손실 값을 생성했습니다. -# `layer.losses` gets reset at the start of each __call__ +# `layer.losses`는 각 `__call__` 시작 시 재설정됩니다. _ = layer(ops.zeros((1, 1))) -assert len(layer.losses) == 1 # This is the loss created during the call above +assert len(layer.losses) == 1 # 이는 위의 호출 중에 발생한 손실입니다. ``` -In addition, the `loss` property also contains regularization losses created for the weights of any inner layer: +또한, `loss` 속성에는 내부 레이어의 가중치에 대해 생성된 정규화 손실도 포함됩니다. ```python class OuterLayerWithKernelRegularizer(keras.layers.Layer): @@ -340,8 +362,8 @@ class OuterLayerWithKernelRegularizer(keras.layers.Layer): layer = OuterLayerWithKernelRegularizer() _ = layer(ops.zeros((1, 1))) -# This is `1e-3 * sum(layer.dense.kernel ** 2)`, -# created by the `kernel_regularizer` above. +# 이는 위의 `kernel_regularizer`에 의해 생성된, +# `1e-3 * sum(layer.dense.kernel ** 2)`입니다. print(layer.losses) ``` @@ -353,23 +375,22 @@ print(layer.losses) {{% /details %}} -These losses are meant to be taken into account when writing custom training loops. +이러한 손실은 커스텀 트레이닝 루프를 작성할 때 고려해야 합니다. -They also work seamlessly with `fit()` (they get automatically summed and added to the main loss, if any): +또한 `fit()`와 원활하게 작동합니다. (있는 경우, 자동으로 합산되어 메인 손실에 추가됩니다.): ```python inputs = keras.Input(shape=(3,)) outputs = ActivityRegularizationLayer()(inputs) model = keras.Model(inputs, outputs) -# If there is a loss passed in `compile`, the regularization -# losses get added to it +# `compile`에 손실이 전달된 손실이 있으면, 정규화 손실에 합산되어 추가됩니다. model.compile(optimizer="adam", loss="mse") model.fit(np.random.random((2, 3)), np.random.random((2, 3))) -# It's also possible not to pass any loss in `compile`, -# since the model already has a loss to minimize, via the `add_loss` -# call during the forward pass! +# 모델에는 이미 최소화해야 할 손실이 있으므로, +# 전방 전달(forward pass) 중 `add_loss` 호출을 통해, +# `compile`에서 아무런 손실도 전달하지 않는 것도 가능합니다! model.compile(optimizer="adam") model.fit(np.random.random((2, 3)), np.random.random((2, 3))) ``` @@ -385,9 +406,10 @@ model.fit(np.random.random((2, 3)), np.random.random((2, 3))) {{% /details %}} -## You can optionally enable serialization on your layers +## 선택적으로 레이어에서 직렬화를 활성화할 수 있습니다. {#you-can-optionally-enable-serialization-on-your-layers} -If you need your custom layers to be serializable as part of a [Functional model]({{< relref "/docs/guides/functional_api" >}}), you can optionally implement a `get_config()` method: +커스텀 레이어를 [함수형 모델]({{< relref "/docs/guides/functional_api" >}})의 일부로 직렬화할 필요가 있는 경우, +선택적으로 `get_config()` 메서드를 구현할 수 있습니다. ```python class Linear(keras.layers.Layer): @@ -412,7 +434,7 @@ class Linear(keras.layers.Layer): return {"units": self.units} -# Now you can recreate the layer from its config: +# 이제 config에서 레이어를 다시 생성할 수 있습니다. layer = Linear(64) config = layer.get_config() print(config) @@ -427,7 +449,8 @@ new_layer = Linear.from_config(config) {{% /details %}} -Note that the `__init__()` method of the base `Layer` class takes some keyword arguments, in particular a `name` and a `dtype`. It's good practice to pass these arguments to the parent class in `__init__()` and to include them in the layer config: +베이스 `Layer` 클래스의 `__init__()` 메서드는 일부 키워드 인수, 특히 `name`과 `dtype`을 취합니다. +이러한 인수를 `__init__()`에서 부모 클래스에 전달하고, 레이어 config에 포함하는 것이 좋습니다. ```python class Linear(keras.layers.Layer): @@ -468,20 +491,26 @@ new_layer = Linear.from_config(config) {{% /details %}} -If you need more flexibility when deserializing the layer from its config, you can also override the `from_config()` class method. This is the base implementation of `from_config()`: +레이어를 config에서 역직렬화할 때 더 많은 유연성이 필요한 경우, +`from_config()` 클래스 메서드를 재정의할 수도 있습니다. +이것은 `from_config()`의 베이스 구현입니다. ```python def from_config(cls, config): return cls(**config) ``` -To learn more about serialization and saving, see the complete [guide to saving and serializing models]({{< relref "/docs/guides/serialization_and_saving" >}}). +직렬화 및 저장에 대해 자세히 알아보려면, +{{< titledRelref "/docs/guides/serialization_and_saving" >}} 가이드를 참조하세요. -## Privileged `training` argument in the `call()` method +## `call()` 메서드의 특권(Privileged) `training` 인수 {#privileged-training-argument-in-the-call-method} -Some layers, in particular the `BatchNormalization` layer and the `Dropout` layer, have different behaviors during training and inference. For such layers, it is standard practice to expose a `training` (boolean) argument in the `call()` method. +일부 레이어, 특히 `BatchNormalization` 레이어와 `Dropout` 레이어는, +트레이닝 및 추론 중에 서로 다른 동작을 합니다. +이러한 레이어의 경우, `call()` 메서드에서 `training`(boolean) 인수를 노출하는 것이 표준 관행입니다. -By exposing this argument in `call()`, you enable the built-in training and evaluation loops (e.g. `fit()`) to correctly use the layer in training and inference. +`call()`에서 이 인수를 노출하면, 빌트인 트레이닝 및 평가 루프(예: `fit()`)가, +트레이닝 및 추론에서 레이어를 올바르게 사용할 수 있습니다. ```python class CustomDropout(keras.layers.Layer): @@ -498,33 +527,44 @@ class CustomDropout(keras.layers.Layer): return inputs ``` -## Privileged `mask` argument in the `call()` method +## `call()` 메서드의 특권 `mask` 인수 {#privileged-mask-argument-in-the-call-method} -The other privileged argument supported by `call()` is the `mask` argument. +`call()`에서 지원하는 다른 특권 인수는 `mask` 인수입니다. -You will find it in all Keras RNN layers. A mask is a boolean tensor (one boolean value per timestep in the input) used to skip certain input timesteps when processing timeseries data. +모든 Keras RNN 레이어에서 찾을 수 있습니다. +마스크는 boolean 텐서(입력의 타임스텝당 하나의 boolean 값)로, +시계열 데이터를 처리할 때 특정 입력 타임스텝을 건너뛰는 데 사용됩니다. -Keras will automatically pass the correct `mask` argument to `__call__()` for layers that support it, when a mask is generated by a prior layer. Mask-generating layers are the `Embedding` layer configured with `mask_zero=True`, and the `Masking` layer. +Keras는, 이전(prior) 레이어에서 마스크가 생성될 때, +이를 지원하는 레이어에 대해 올바른 `mask` 인수를 `__call__()`에 자동으로 전달합니다. +마스크를 생성하는 레이어는 `mask_zero=True`로 구성된 `Embedding` 레이어와 `Masking` 레이어입니다. -## The `Model` class +## `Model` 클래스 {#the-model-class} -In general, you will use the `Layer` class to define inner computation blocks, and will use the `Model` class to define the outer model – the object you will train. +일반적으로, `Layer` 클래스를 사용하여 내부 계산 블록을 정의하고, +`Model` 클래스를 사용하여 외부 모델(트레이닝할 객체)을 정의합니다. -For instance, in a ResNet50 model, you would have several ResNet blocks subclassing `Layer`, and a single `Model` encompassing the entire ResNet50 network. +예를 들어, ResNet50 모델에서는, `Layer`를 하위 클래스화하는 여러 ResNet 블록과, +전체 ResNet50 네트워크를 포괄하는 단일 `Model`이 있습니다. -The `Model` class has the same API as `Layer`, with the following differences: +`Model` 클래스는 `Layer`와 동일한 API를 사용하지만, 다음과 같은 차이점이 있습니다. -- It exposes built-in training, evaluation, and prediction loops (`model.fit()`, `model.evaluate()`, `model.predict()`). -- It exposes the list of its inner layers, via the `model.layers` property. -- It exposes saving and serialization APIs (`save()`, `save_weights()`...) +- 빌트인 트레이닝, 평가 및 예측 루프(`model.fit()`, `model.evaluate()`, `model.predict()`)를 노출합니다. +- `model.layers` 속성을 통해, 내부 레이어 리스트를 노출합니다. +- 저장 및 직렬화 API(`save()`, `save_weights()`...)를 노출합니다. -Effectively, the `Layer` class corresponds to what we refer to in the literature as a "layer" (as in "convolution layer" or "recurrent layer") or as a "block" (as in "ResNet block" or "Inception block"). +실제로, `Layer` 클래스는 문헌에서 +"레이어"(예: "컨볼루션 레이어" 또는 "recurrent 레이어") 또는 +"블록"(예: "ResNet 블록" 또는 "Inception 블록")이라고 하는 것과 일치합니다. -Meanwhile, the `Model` class corresponds to what is referred to in the literature as a "model" (as in "deep learning model") or as a "network" (as in "deep neural network"). +한편, `Model` 클래스는 문헌에서 "모델"(예: "딥러닝 모델") 또는 "네트워크"(예: "딥 신경망(신경 네트워크)")라고 하는 것에 해당합니다. -So if you're wondering, "should I use the `Layer` class or the `Model` class?", ask yourself: will I need to call `fit()` on it? Will I need to call `save()` on it? If so, go with `Model`. If not (either because your class is just a block in a bigger system, or because you are writing training & saving code yourself), use `Layer`. +따라서, "`Layer` 클래스나 `Model` 클래스를 사용해야 할까?"라는 것이 궁금하다면 스스로에게 물어보세요. +`fit()`를 호출해야 할까요? `save()`를 호출해야 할까요? 그렇다면 `Model`을 사용하세요. +그렇지 않다면(클래스가 더 큰 시스템의 블록이거나 직접 트레이닝 및 저장 코드를 작성하고 있기 때문) `Layer`를 사용하세요. -For instance, we could take our mini-resnet example above, and use it to build a `Model` that we could train with `fit()`, and that we could save with `save_weights()`: +예를 들어, 위의 mini-resnet 예제를 가져와, `fit()`로 트레이닝하고, +`save_weights()`로 저장할 수 있는 `Model`을 빌드할 수 있습니다. ```python class ResNet(keras.Model): @@ -549,23 +589,30 @@ resnet.fit(dataset, epochs=10) resnet.save(filepath.keras) ``` -## Putting it all together: an end-to-end example +## 모두 합치기: 엔드투엔드 예시 {#putting-it-all-together-an-end-to-end-example} -Here's what you've learned so far: +지금까지 배운 내용은 다음과 같습니다. -- A `Layer` encapsulate a state (created in `__init__()` or `build()`) and some computation (defined in `call()`). -- Layers can be recursively nested to create new, bigger computation blocks. -- Layers are backend-agnostic as long as they only use Keras APIs. You can use backend-native APIs (such as `jax.numpy`, `torch.nn` or [`tf.nn`](https://www.tensorflow.org/api_docs/python/tf/nn)), but then your layer will only be usable with that specific backend. -- Layers can create and track losses (typically regularization losses) via `add_loss()`. -- The outer container, the thing you want to train, is a `Model`. A `Model` is just like a `Layer`, but with added training and serialization utilities. +- `Layer`는 상태(`__init__()` 또는 `build()`에서 생성)와 일부 계산(`call()`에서 정의)을 캡슐화합니다. +- 레이어는 재귀적으로 중첩되어, 새롭고 더 큰 계산 블록을 만들 수 있습니다. +- 레이어는 Keras API만 사용하는 한 백엔드에 구애받지 않습니다. + 백엔드 네이티브 API(예: `jax.numpy`, `torch.nn` 또는 [`tf.nn`](https://www.tensorflow.org/api_docs/python/tf/nn))를 사용할 수 있지만, 그러면 레이어는 해당 특정 백엔드에서만 사용할 수 있습니다. +- 레이어는 `add_loss()`를 통해 손실(일반적으로 정규화 손실)을 생성하고 추적할 수 있습니다. +- 외부 컨테이너, 즉 트레이닝하려는 것은 `Model`입니다. + `Model`은 `Layer`와 같지만 트레이닝 및 직렬화 유틸리티가 추가되었습니다. -Let's put all of these things together into an end-to-end example: we're going to implement a Variational AutoEncoder (VAE) in a backend-agnostic fashion – so that it runs the same with TensorFlow, JAX, and PyTorch. We'll train it on MNIST digits. +이 모든 것을 엔드투엔드 예제로 모아 보겠습니다. +백엔드에 독립적인 방식으로 Variational AutoEncoder(VAE)를 구현하여, +TensorFlow, JAX, PyTorch에서 동일하게 실행되도록 하겠습니다. +MNIST 숫자에 대해 트레이닝 할 것입니다. -Our VAE will be a subclass of `Model`, built as a nested composition of layers that subclass `Layer`. It will feature a regularization loss (KL divergence). +VAE는 `Model`의 서브클래스이며, +`Layer`를 서브클래스하는 레이어의 중첩된 구성으로 구축됩니다. +정규화 손실(KL 발산)이 특징입니다. ```python class Sampling(layers.Layer): - """Uses (z_mean, z_log_var) to sample z, the vector encoding a digit.""" + """(z_mean, z_log_var)를 사용하여 숫자를 인코딩하는 벡터 z를 샘플링합니다.""" def __init__(self, **kwargs): super().__init__(**kwargs) @@ -580,7 +627,7 @@ class Sampling(layers.Layer): class Encoder(layers.Layer): - """Maps MNIST digits to a triplet (z_mean, z_log_var, z).""" + """MNIST 숫자를 삼중항(z_mean, z_log_var, z)으로 매핑합니다.""" def __init__(self, latent_dim=32, intermediate_dim=64, name="encoder", **kwargs): super().__init__(name=name, **kwargs) @@ -598,7 +645,7 @@ class Encoder(layers.Layer): class Decoder(layers.Layer): - """Converts z, the encoded digit vector, back into a readable digit.""" + """인코딩된 숫자 벡터 z를 다시 읽을 수 있는 숫자로 변환합니다.""" def __init__(self, original_dim, intermediate_dim=64, name="decoder", **kwargs): super().__init__(name=name, **kwargs) @@ -611,7 +658,7 @@ class Decoder(layers.Layer): class VariationalAutoEncoder(keras.Model): - """Combines the encoder and decoder into an end-to-end model for training.""" + """인코더와 디코더를 엔드투엔드 모델로 결합하여 트레이닝을 수행합니다.""" def __init__( self, @@ -629,7 +676,7 @@ class VariationalAutoEncoder(keras.Model): def call(self, inputs): z_mean, z_log_var, z = self.encoder(inputs) reconstructed = self.decoder(z) - # Add KL divergence regularization loss. + # KL 발산 정규화 손실을 추가합니다. kl_loss = -0.5 * ops.mean( z_log_var - ops.square(z_mean) - ops.exp(z_log_var) + 1 ) @@ -637,7 +684,7 @@ class VariationalAutoEncoder(keras.Model): return reconstructed ``` -Let's train it on MNIST using the `fit()` API: +`fit()` API를 사용하여 MNIST에 대해 트레이닝해 보겠습니다. ```python (x_train, _), _ = keras.datasets.mnist.load_data() diff --git a/content/korean/docs/guides/migrating_to_keras_3/_index.md b/content/korean/docs/guides/migrating_to_keras_3/_index.md index 001aed3e..0bbcc14d 100644 --- a/content/korean/docs/guides/migrating_to_keras_3/_index.md +++ b/content/korean/docs/guides/migrating_to_keras_3/_index.md @@ -1,6 +1,6 @@ --- -title: Migrating Keras 2 code to multi-backend Keras 3 -linkTitle: Migrating Keras 2 code to Keras 3 +title: Keras 2 코드를 멀티 백엔드 Keras 3로 마이그레이션 +linkTitle: Keras 3으로 마이그레이션 toc: true weight: 19 type: docs @@ -11,27 +11,35 @@ type: docs **{{< t f_author >}}** [Divyashree Sreepathihalli](https://github.com/divyashreepathihalli) **{{< t f_date_created >}}** 2023/10/23 **{{< t f_last_modified >}}** 2023/10/30 -**{{< t f_description >}}** Instructions & troubleshooting for migrating your Keras 2 code to multi-backend Keras 3. +**{{< t f_description >}}** Keras 2 코드를 멀티 백엔드 Keras 3로 마이그레이션하기 위한 지침 및 문제 해결. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/migrating_to_keras_3.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/migrating_to_keras_3.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -This guide will help you migrate TensorFlow-only Keras 2 code to multi-backend Keras 3 code. The overhead for the migration is minimal. Once you have migrated, you can run Keras workflows on top of either JAX, TensorFlow, or PyTorch. +이 가이드는 TensorFlow 전용 Keras 2 코드를 멀티 백엔드 Keras 3 코드로 마이그레이션하는 데 도움이 됩니다. +마이그레이션에 필요한 작업은 최소화되며, +마이그레이션 후에는 Keras 워크플로를 JAX, TensorFlow 또는 PyTorch 위에서 실행할 수 있습니다. -This guide has two parts: +이 가이드는 두 부분으로 구성되어 있습니다: -1. Migrating your legacy Keras 2 code to Keras 3, running on top of the TensorFlow backend. This is generally very easy, though there are minor issues to be mindful of, that we will go over in detail. -2. Further migrating your Keras 3 + TensorFlow code to multi-backend Keras 3, so that it can run on JAX and PyTorch. +1. TensorFlow 백엔드에서 실행되는 Keras 3로 기존 Keras 2 코드를 마이그레이션합니다. + 이 과정은 대체로 매우 쉽지만, 주의해야 할 몇 가지 사소한 문제가 있습니다. + 이를 자세히 설명하겠습니다. +2. Keras 3 + TensorFlow 코드를 추가로 마이그레이션하여, + 다중 백엔드 Keras 3로 전환해 JAX 및 PyTorch에서도 실행 가능하도록 합니다. -Let's get started. +시작해봅시다. -## Setup +## 셋업 {#setup} -First, lets install `keras-nightly`. +먼저, `keras-nightly`를 설치합시다. -This example uses the TensorFlow backend (`os.environ["KERAS_BACKEND"] = "tensorflow"`). After you've migrated your code, you can change the `"tensorflow"` string to `"jax"` or `"torch"` and click "Restart runtime" in Colab, and your code will run on the JAX or PyTorch backend. +이 예제는 TensorFlow 백엔드를 사용합니다. +(`os.environ["KERAS_BACKEND"] = "tensorflow"`) +코드를 마이그레이션한 후에는, `"tensorflow"` 문자열을 `"jax"` 또는 `"torch"`로 변경하고, +Colab에서 "Restart runtime"을 클릭하면, 코드가 JAX 또는 PyTorch 백엔드에서 실행됩니다. ```python !pip install -q keras-nightly @@ -56,30 +64,40 @@ import numpy as np {{% /details %}} -## Going from Keras 2 to Keras 3 with the TensorFlow backend +## Keras 2에서 TensorFlow 백엔드를 사용하는 Keras 3으로 마이그레이션 {#going-from-keras-2-to-keras-3-with-the-tensorflow-backend} -First, replace your imports: +먼저, import를 변경하세요: -1. Replace `from tensorflow import keras` to `import keras` -2. Replace `from tensorflow.keras import xyz` (e.g. `from tensorflow.keras import layers`) to `from keras import xyz` (e.g. `from keras import layers`) -3. Replace [`tf.keras.*`](https://www.tensorflow.org/api_docs/python/tf/keras/*) to `keras.*` +1. `from tensorflow import keras`를 `import keras`로 변경하세요. +2. `from tensorflow.keras import xyz` (예: `from tensorflow.keras import layers`)를 + `from keras import xyz` (예: `from keras import layers`)로 변경하세요. +3. [`tf.keras.*`](https://www.tensorflow.org/api_docs/python/tf/keras/*)을 `keras.*`로 변경하세요. -Next, start running your tests. Most of the time, your code will execute on Keras 3 just fine. All issues you might encounter are detailed below, with their fixes. +이제 테스트를 실행해보세요. +대부분의 경우, 코드는 Keras 3에서 잘 실행될 것입니다. +만약 문제가 발생하면, 아래에 자세히 설명된 문제 해결 방법을 참고하세요. -### `jit_compile` is set to `True` by default on GPU. +### `jit_compile`이 GPU에서 기본적으로 `True`로 설정됩니다. {#jit_compile-is-set-to-true-by-default-on-gpu} -The default value of the `jit_compile` argument to the `Model` constructor has been set to `True` on GPU in Keras 3. This means that models will be compiled with Just-In-Time (JIT) compilation by default on GPU. +Keras 3에서 `Model` 생성자의 `jit_compile` 인수의 기본값이 GPU에서 `True`로 설정됩니다. +이는 모델이 기본적으로 GPU에서 JIT(Just-In-Time) 컴파일로 컴파일된다는 의미입니다. -JIT compilation can improve the performance of some models. However, it may not work with all TensorFlow operations. If you are using a custom model or layer and you see an XLA-related error, you may need to set the `jit_compile` argument to `False`. Here is a list of [known issues](https://www.tensorflow.org/xla/known_issues) encountered when using XLA with TensorFlow. In addition to these issues, there are some ops that are not supported by XLA. +JIT 컴파일은 일부 모델의 성능을 향상시킬 수 있습니다. +하지만 모든 TensorFlow 연산에서 작동하지 않을 수 있습니다. +커스텀 모델이나 레이어를 사용 중이고 XLA 관련 오류가 발생하면, +`jit_compile` 인수를 `False`로 설정해야 할 수 있습니다. +TensorFlow에서 XLA를 사용할 때 발생할 수 있는 +[알려진 문제](https://www.tensorflow.org/xla/known_issues)를 참조하세요. +또한 XLA에서 지원되지 않는 일부 연산도 있습니다. -The error message you could encounter would be as follows: +발생할 수 있는 오류 메시지는 다음과 같습니다: ```plain Detected unsupported operations when trying to compile graph __inference_one_step_on_data_125[] on XLA_GPU_JIT ``` -For example, the following snippet of code will reproduce the above error: +예를 들어, 아래 코드 스니펫은 위 오류를 재현할 수 있습니다: ```python class MyModel(keras.Model): @@ -97,7 +115,10 @@ subclass_model.compile(optimizer="sgd", loss="mse") subclass_model.predict(x_train) ``` -**How to fix it:** set `jit_compile=False` in `model.compile(..., jit_compile=False)`, or set the `jit_compile` attribute to `False`, like this: +**해결 방법:** + +`model.compile(..., jit_compile=False)`에서 `jit_compile=False`로 설정하거나, +`jit_compile` 속성을 다음과 같이 `False`로 설정하세요: ```python class MyModel(keras.Model): @@ -105,7 +126,7 @@ class MyModel(keras.Model): super().__init__(*args, **kwargs) def call(self, inputs): - # tf.strings ops aren't support by XLA + # tf.strings 연산은 XLA에서 지원되지 않음 string_input = tf.strings.as_string(inputs) return tf.strings.to_number(string_input) @@ -127,11 +148,11 @@ array([[1., 2., 3.], {{% /details %}} -### Saving a model in the TF SavedModel format +### TF SavedModel 형식으로 모델 저장하기 {#saving-a-model-in-the-tf-savedmodel-format} -Saving to the TF SavedModel format via `model.save()` is no longer supported in Keras 3. +Keras 3에서는 `model.save()`를 통해 TF SavedModel 형식으로 저장하는 기능이 더 이상 지원되지 않습니다. -The error message you could encounter would be as follows: +발생할 수 있는 오류 메시지는 다음과 같습니다: ```console >>> model.save("mymodel") @@ -141,7 +162,7 @@ for the native Keras format (recommended) or a `.h5` extension. Use TFLite/TFServing/etc. Received: filepath=saved_model. ``` -The following snippet of code will reproduce the above error: +다음 코드 스니펫은 위 오류를 재현할 수 있습니다: ```python sequential_model = keras.Sequential([ @@ -150,7 +171,9 @@ sequential_model = keras.Sequential([ sequential_model.save("saved_model") ``` -**How to fix it:** use `model.export(filepath)` instead of `model.save(filepath)` +**해결 방법:** + +`model.save(filepath)` 대신 `model.export(filepath)`를 사용하세요. ```python sequential_model = keras.Sequential([keras.layers.Dense(2)]) @@ -180,9 +203,11 @@ Captures: {{% /details %}} -### Loading a TF SavedModel +### TF SavedModel 로드하기 {#loading-a-tf-savedmodel} -Loading a TF SavedModel file via `keras.models.load_model()` is no longer supported If you try to use `keras.models.load_model()` with a TF SavedModel, you will get the following error: +Keras 3에서는 `keras.models.load_model()`을 사용하여 +TF SavedModel 파일을 로드하는 기능이 더 이상 지원되지 않습니다. +`keras.models.load_model()`을 사용하려고 하면 다음과 같은 오류가 발생합니다: ```plain ValueError: File format not supported: filepath=saved_model. Keras 3 only supports V3 @@ -193,13 +218,18 @@ TensorFlow SavedModel as an inference-only layer in Keras 3, use `call_endpoint` might have a different name). ``` -The following snippet of code will reproduce the above error: +다음 코드 스니펫은 위 오류를 재현할 수 있습니다: ```python keras.models.load_model("saved_model") ``` -**How to fix it:** Use `keras.layers.TFSMLayer(filepath, call_endpoint="serving_default")` to reload a TF SavedModel as a Keras layer. This is not limited to SavedModels that originate from Keras – it will work with any SavedModel, e.g. TF-Hub models. +**해결 방법:** + +TF SavedModel을 Keras 레이어로 다시 로드하려면, +`keras.layers.TFSMLayer(filepath, call_endpoint="serving_default")`를 사용하세요. +이는 Keras에서 생성된 SavedModel에만 국한되지 않으며, +TF-Hub 모델을 포함한 모든 SavedModel에 대해 작동합니다. ```python keras.layers.TFSMLayer("saved_model", call_endpoint="serving_default") @@ -213,11 +243,12 @@ keras.layers.TFSMLayer("saved_model", call_endpoint="serving_default") {{% /details %}} -### Using deeply nested inputs in Functional Models +### Functional 모델에서 깊게 중첩된 입력 사용하기 {#using-deeply-nested-inputs-in-functional-models} -`Model()` can no longer be passed deeply nested inputs/outputs (nested more than 1 level deep, e.g. lists of lists of tensors). +Keras 3에서는 `Model()`에 깊게 중첩된 +입력/출력(예: 텐서의 리스트 안에 리스트처럼, 1단계 이상 중첩된 구조)을 전달할 수 없습니다. -You would encounter errors as follows: +이를 시도하면 다음과 같은 오류가 발생할 수 있습니다: ```plain ValueError: When providing `inputs` as a dict, all values in the dict must be @@ -227,7 +258,7 @@ sparse=None, name=bar>}} including invalid value {'baz': } of type ``` -The following snippet of code will reproduce the above error: +다음 코드 스니펫은 위 오류를 재현할 수 있습니다: ```python inputs = { @@ -240,7 +271,9 @@ outputs = inputs["foo"] + inputs["bar"]["baz"] keras.Model(inputs, outputs) ``` -**How to fix it:** replace nested input with either dicts, lists, and tuples of input tensors. +**해결 방법:** + +중첩된 입력을 사전(dict), 리스트(list), 또는 튜플(tuple) 형태의 입력 텐서로 교체하세요. ```python inputs = { @@ -259,11 +292,14 @@ keras.Model(inputs, outputs) {{% /details %}} -### TF autograph +### TF 오토그래프 {#tf-autograph} -In Keras 2, TF autograph is enabled by default on the `call()` method of custom layers. In Keras 3, it is not. This means you may have to use cond ops if you're using control flow, or alternatively you can decorate your `call()` method with `@tf.function`. +Keras 2에서는, 커스텀 레이어의 `call()` 메서드에 대해 TF Autograph가 기본적으로 활성화되어 있었습니다. +그러나 Keras 3에서는 활성화되지 않습니다. +즉, 제어 흐름을 사용하는 경우 `cond` 연산을 사용해야 하거나, +대안으로 `call()` 메서드를 `@tf.function`으로 데코레이트해야 합니다. -You would encounter an error as follows: +다음과 같은 오류가 발생할 수 있습니다: ```plain OperatorNotAllowedInGraphError: Exception encountered when calling MyCustomLayer.call(). @@ -277,7 +313,7 @@ Here is a [link for more information](https://github.com/tensorflow/tensorflow/b erence/limitations.md#access-to-source-code). ``` -The following snippet of code will reproduce the above error: +다음 코드 스니펫은 위 오류를 재현할 수 있습니다: ```python class MyCustomLayer(keras.layers.Layer): @@ -296,7 +332,9 @@ model.compile(optimizer="adam", loss="mse") model.predict(data) ``` -**How to fix it:** decorate your `call()` method with `@tf.function` +**해결 방법:** + +`call()` 메서드를 `@tf.function`으로 데코레이트하세요. ```python class MyCustomLayer(keras.layers.Layer): @@ -327,11 +365,14 @@ array([[0.59727275, 1.9986179 , 1.5514829 ], {{% /details %}} -### Calling TF ops with a `KerasTensor` +### `KerasTensor`로 TF 연산 호출 {#calling-tf-ops-with-a-kerastensor} -Using a TF op on a Keras tensor during functional model construction is disallowed: "A KerasTensor cannot be used as input to a TensorFlow function". +Functional 모델을 구성할 때, +Keras 텐서에서 TF 연산을 사용하는 것은 허용되지 않습니다: +"A KerasTensor cannot be used as input to a TensorFlow function" +(KerasTensor는 TensorFlow 함수의 입력으로 사용할 수 없습니다). -The error you would encounter would be as follows: +다음과 같은 오류가 발생할 수 있습니다: ```plain ValueError: A KerasTensor cannot be used as input to a TensorFlow function. A KerasTensor @@ -340,14 +381,16 @@ models or Keras Functions. You can only use it as input to a Keras layer or a Ke operation (from the namespaces `keras.layers` and `keras.operations`). ``` -The following snippet of code will reproduce the error: +다음 코드 스니펫은 이 오류를 재현할 수 있습니다: ```python input = keras.layers.Input([2, 2, 1]) tf.squeeze(input) ``` -**How to fix it:** use an equivalent op from `keras.ops`. +**해결 방법:** + +`keras.ops`에서 동등한 연산을 사용하세요. ```python input = keras.layers.Input([2, 2, 1]) @@ -362,17 +405,24 @@ keras.ops.squeeze(input) {{% /details %}} -### Multi-output model `evaluate()` +### 다중 출력 모델 `evaluate()` {#multi-output-model-evaluate} -The `evaluate()` method of a multi-output model no longer returns individual output losses separately. Instead, you should utilize the `metrics` argument in the `compile()` method to keep track of these losses. +The following snippet of code will reproduce the above behavior: -When dealing with multiple named outputs, such as output_a and output_b, the legacy [`tf.keras`](https://www.tensorflow.org/api_docs/python/tf/keras) would include \_loss, \_loss, and similar entries in metrics. However, in keras 3.0, these entries are not automatically added to metrics. They must be explicitly provided in the metrics list for each individual output. +다중 출력 모델의 `evaluate()` 메서드는 더 이상 개별 출력 손실을 따로 반환하지 않습니다. +대신, 각 손실을 추적하려면, `compile()` 메서드에서 `metrics` 인수를 명시적으로 사용해야 합니다. -The following snippet of code will reproduce the above behavior: +`output_a`와 `output_b`와 같은 여러 명명된 출력을 다룰 때, +이전 [`tf.keras`](https://www.tensorflow.org/api_docs/python/tf/keras)에서는 +`_loss` 및 메트릭에서 유사한 항목이 자동으로 추가되었으나, +Keras 3.0에서는, 이러한 항목이 자동으로 메트릭에 추가되지 않습니다. +각 출력에 대해 개별적으로 메트릭 목록에 명시해야 합니다. + +다음 코드 스니펫은 이러한 동작을 재현합니다: ```python from keras import layers -# A functional model with multiple outputs +# 여러 출력이 있는 functional 모델 inputs = layers.Input(shape=(10,)) x1 = layers.Dense(5, activation='relu')(inputs) x2 = layers.Dense(5, activation='relu')(x1) @@ -380,7 +430,7 @@ output_1 = layers.Dense(5, activation='softmax', name="output_1")(x1) output_2 = layers.Dense(5, activation='softmax', name="output_2")(x2) model = keras.Model(inputs=inputs, outputs=[output_1, output_2]) model.compile(optimizer='adam', loss='categorical_crossentropy') -# dummy data +# 임의의 데이터 x_test = np.random.uniform(size=[10, 10]) y_test = np.random.uniform(size=[10, 5]) @@ -390,13 +440,13 @@ model.evaluate(x_test, y_test) ```python from keras import layers -# A functional model with multiple outputs +# 여러 출력이 있는 functional 모델 inputs = layers.Input(shape=(10,)) x1 = layers.Dense(5, activation="relu")(inputs) x2 = layers.Dense(5, activation="relu")(x1) output_1 = layers.Dense(5, activation="softmax", name="output_1")(x1) output_2 = layers.Dense(5, activation="softmax", name="output_2")(x2) -# dummy data +# 임의의 데이터 x_test = np.random.uniform(size=[10, 10]) y_test = np.random.uniform(size=[10, 5]) multi_output_model = keras.Model(inputs=inputs, outputs=[output_1, output_2]) @@ -418,9 +468,13 @@ multi_output_model.evaluate(x_test, y_test) {{% /details %}} -### TensorFlow variables tracking +### TensorFlow 변수 추적 {#tensorflow-variables-tracking} -Setting a [`tf.Variable`](https://www.tensorflow.org/api_docs/python/tf/Variable) as an attribute of a Keras 3 layer or model will not automatically track the variable, unlike in Keras 2. The following snippet of code will show that the [`tf.Variables`](https://www.tensorflow.org/api_docs/python/tf/Variables) are not being tracked. +Keras 2와 달리, Keras 3 레이어나 모델의 속성으로 +[`tf.Variable`](https://www.tensorflow.org/api_docs/python/tf/Variable)을 설정해도 +변수가 자동으로 추적되지 않습니다. +아래 코드 스니펫은 [`tf.Variables`](https://www.tensorflow.org/api_docs/python/tf/Variables)가 +추적되지 않는 예시를 보여줍니다. ```python class MyCustomLayer(keras.layers.Layer): @@ -442,19 +496,23 @@ data = np.random.uniform(size=[3, 3]) model = keras.models.Sequential([layer]) model.compile(optimizer="adam", loss="mse") model.predict(data) -# The model does not have any trainable variables +# 모델에 트레이닝 가능한 변수가 없습니다. for layer in model.layers: print(layer.trainable_variables) ``` -You will see the following warning: +다음과 같은 경고를 볼 수 있습니다: ```plain UserWarning: The model does not have any trainable weights. warnings.warn("The model does not have any trainable weights.") ``` -**How to fix it:** use `self.add_weight()` method or opt for a `keras.Variable` instead. If you are currently using [`tf.variable`](https://www.tensorflow.org/api_docs/python/tf/variable), you can switch to `keras.Variable`. +**해결 방법:** + +`self.add_weight()` 메서드를 사용하거나, `keras.Variable`을 사용하는 것을 권장합니다. +현재 [`tf.variable`](https://www.tensorflow.org/api_docs/python/tf/variable)을 사용하고 있다면, +`keras.Variable`로 전환할 수 있습니다. ```python class MyCustomLayer(keras.layers.Layer): @@ -484,7 +542,7 @@ data = np.random.uniform(size=[3, 3]) model = keras.models.Sequential([layer]) model.compile(optimizer="adam", loss="mse") model.predict(data) -# Verify that the variables are now being tracked +# 변수가 이제 추적되는지 확인하세요. for layer in model.layers: print(layer.trainable_variables) ``` @@ -498,13 +556,16 @@ for layer in model.layers: {{% /details %}} -### `None` entries in nested `call()` arguments +### 중첩된 `call()` 메서드의 인자에 있는 `None` 항목 {#none-entries-in-nested-call-arguments} -`None` entries are not allowed as part of nested (e.g. list/tuples) tensor arguments in `Layer.call()`, nor as part of `call()`'s nested return values. +`Layer.call()` 메서드의 중첩된 (예: 리스트/튜플) 텐서 인자에서 `None` 항목은 허용되지 않으며, +`call()` 메서드의 중첩된 반환 값에서도 `None`이 허용되지 않습니다. -If the `None` in the argument is intentional and serves a specific purpose, ensure that the argument is optional and structure it as a separate parameter. For example, consider defining the `call` method with optional argument. +인자에 있는 `None`이 의도적이고 특정 목적을 가진 경우, +해당 인자를 선택적 인자로 처리하고 별도의 매개변수로 구조화해야 합니다. +예를 들어, `call` 메서드를 선택적 인자로 정의하는 것을 고려할 수 있습니다. -The following snippet of code will reproduce the error. +아래 코드 스니펫은 이 오류를 재현할 수 있습니다. ```python class CustomLayer(keras.layers.Layer): @@ -528,9 +589,9 @@ inputs = { layer(inputs) ``` -**How to fix it:** +**해결 방법:** -**Solution 1:** Replace `None` with a value, like this: +**해결책 1:** `None`을 값으로 대체합니다. 예를 들어: ```python class CustomLayer(keras.layers.Layer): @@ -561,7 +622,9 @@ layer(inputs) {{% /details %}} -**Solution 2:** Define the call method with an optional argument. Here is an example of this fix: +**해결책 2:** + +선택적 인자를 사용하여 call 메서드를 정의합니다. 다음은 이 수정의 예시입니다: ```python class CustomLayer(keras.layers.Layer): @@ -588,13 +651,21 @@ layer(foo, baz=baz) {{% /details %}} -### State-building issues +### 상태 생성 문제 {#state-building-issues} -Keras 3 is significantly stricter than Keras 2 about when state (e.g. numerical weight variables) can be created. Keras 3 wants all state to be created before the model can be trained. This is a requirement for using JAX (whereas TensorFlow was very lenient about state creation timing). +Keras 3는 상태(예: 수치 가중치 변수)가 생성되는 시점에 대해 Keras 2보다 훨씬 엄격합니다. +Keras 3는 모델이 트레이닝되기 전에 모든 상태가 생성되기를 원합니다. +이는 JAX를 사용하는 데 필수적인 요구 사항이며, +TensorFlow는 상태 생성 시점에 대해 매우 관대했습니다. -Keras layers should create their state either in their constructor (`__init__()` method) or in their `build()` method. They should avoid creating state in `call()`. +Keras 레이어는 상태를 생성자(`__init__()` 메서드)나 `build()` 메서드에서 생성해야 합니다. +`call()` 메서드에서 상태를 생성하는 것은 피해야 합니다. -If you ignore this recommendation and create state in `call()` anyway (e.g. by calling a previously unbuilt layer), then Keras will attempt to build the layer automatically by calling the `call()` method on symbolic inputs before training. However, this attempt at automatic state creation may fail in certain cases. This will cause an error that looks like like this: +이 권장 사항을 무시하고 `call()`에서 상태를 생성하는 경우(예: 아직 빌드되지 않은 레이어를 호출하는 경우), +그러면 Keras는 트레이닝 전에 `call()` 메서드를 상징적 입력(symbolic inputs)에 대해 호출하여, +레이어를 자동으로 빌드하려고 시도할 것입니다. +그러나 이 자동 상태 생성 시도가 특정 경우에는 실패할 수 있으며, +이로 인해 다음과 같은 오류가 발생할 수 있습니다: ```plain Layer 'frame_position_embedding' looks like it has unbuilt state, @@ -609,7 +680,7 @@ It should create all variables used by the layer (e.g. by calling `layer.build()` on all its children layers). ``` -You could reproduce this error with the following layer, when used with the JAX backend: +아래와 같은 레이어를, JAX 백엔드로 사용할 때, 이 오류를 재현할 수 있습니다: ```python class PositionalEmbedding(keras.layers.Layer): @@ -629,7 +700,16 @@ class PositionalEmbedding(keras.layers.Layer): return inputs + embedded_positions ``` -**How to fix it:** Do exactly what the error message asks. First, try to run the layer eagerly to see if the `call()` method is in fact correct (note: if it was working in Keras 2, then it is correct and does not need to be changed). If it is indeed correct, then you should implement a `build(self, input_shape)` method that creates all of the layer's state, including the state of sublayers. Here's the fix as applied for the layer above (note the `build()` method): +**해결 방법:** + +오류 메시지가 요청하는 대로 수행하세요. +먼저, 레이어를 즉시 실행(eagerly) 모드로 실행하여, +`call()` 메서드가 실제로 올바른지 확인하십시오. +(참고: Keras 2에서 정상적으로 작동했다면, `call()` 메서드는 올바르며 수정할 필요가 없습니다) +`call()` 메서드가 올바른 경우, +`build(self, input_shape)` 메서드를 구현하여 모든 레이어의 상태를 생성해야 합니다. +여기에는 하위 레이어의 상태도 포함됩니다. +다음은 위 레이어에 적용된 수정 사항입니다(`build()` 메서드를 참고하세요): ```python class PositionalEmbedding(keras.layers.Layer): @@ -652,38 +732,60 @@ class PositionalEmbedding(keras.layers.Layer): return inputs + embedded_positions ``` -### Removed features +### 제거된 기능 {#removed-features} -A small number of legacy features with very low usage were removed from Keras 3 as a cleanup measure: +Keras 3에서 사용 빈도가 매우 낮은 몇 가지 레거시 기능이 정리 차원에서 제거되었습니다: -- `keras.layers.ThresholdedReLU` is removed. Instead, you can simply use the `ReLU` layer with the argument `threshold`. -- Symbolic `Layer.add_loss()`: Symbolic `add_loss()` is removed (you can still use `add_loss()` inside the `call()` method of a layer/model). -- Locally connected layers (`LocallyConnected1D`, `LocallyConnected2D` are removed due to very low usage. To use locally connected layers, copy the layer implementation into your own codebase. -- `keras.layers.experimental.RandomFourierFeatures` is removed due to very low usage. To use it, copy the layer implementation into your own codebase. -- Removed layer attributes: Layer attributes `metrics`, `dynamic` are removed. `metrics` is still available on the `Model` class. -- The `constants` and `time_major` arguments in RNN layers are removed. The `constants` argument was a remnant of Theano and had very low usage. The `time_major` argument also had very low usage. -- `reset_metrics` argument: The `reset_metrics` argument is removed from `model.*_on_batch()` methods. This argument had very low usage. -- The `keras.constraints.RadialConstraint` object is removed. This object had very low usage. +- `keras.layers.ThresholdedReLU`가 제거되었습니다. + - 대신, `ReLU` 레이어에서 `threshold` 인수를 사용하면 됩니다. +- Symbolic `Layer.add_loss()`. + - Symbolic `add_loss()`는 제거되었습니다. + (여전히 레이어/모델의 `call()` 메서드 내에서 `add_loss()`를 사용할 수 있습니다) +- Locally connected 레이어 (`LocallyConnected1D`, `LocallyConnected2D`)는 매우 낮은 사용 빈도로 인해 제거되었습니다. + - 로컬로 연결된 레이어를 사용하려면, 레이어 구현을 코드베이스에 복사하여 사용하세요. +- `keras.layers.experimental.RandomFourierFeatures`는 매우 낮은 사용 빈도로 인해 제거되었습니다. + - 이를 사용하려면, 레이어 구현을 코드베이스에 복사하여 사용하세요. +- 제거된 레이어 속성: + - `metrics`, `dynamic` 속성이 제거되었습니다. + - `metrics`는 여전히 `Model` 클래스에서 사용할 수 있습니다. +- RNN 레이어의 `constants` 및 `time_major` 인수가 제거되었습니다. + - `constants` 인수는 Theano의 유산이었으며 사용 빈도가 매우 낮았습니다. + - `time_major` 인수도 사용 빈도가 매우 낮았습니다. +- `reset_metrics` 인수: + - `reset_metrics` 인수가 `model.*_on_batch()` 메서드에서 제거되었습니다. + - 이 인수는 사용 빈도가 매우 낮았습니다. +- `keras.constraints.RadialConstraint` 객체가 제거되었습니다. + - 이 객체는 사용 빈도가 매우 낮았습니다. -## Transitioning to backend-agnostic Keras 3 +## 백엔드에 독립적인 Keras 3로의 전환 {#transitioning-to-backend-agnostic-keras-3} -Keras 3 code with the TensorFlow backend will work with native TensorFlow APIs. However, if you want your code to be backend-agnostic, you will need to: +TensorFlow 백엔드를 사용하는 Keras 3 코드는 기본적으로 TensorFlow API와 함께 작동합니다. +그러나 코드가 백엔드에 독립적이게 하려면, 다음을 수행해야 합니다: -- Replace all of the [`tf.*`](https://www.tensorflow.org/api_docs/python/tf/*) API calls with their equivalent Keras APIs. -- Convert your custom `train_step`/`test_step` methods to a multi-framework implementation. -- Make sure you're using stateless `keras.random` ops correctly in your layers. +- 모든 [`tf.*`](https://www.tensorflow.org/api_docs/python/tf/*) API 호출을, + 해당하는 Keras API로 교체합니다. +- 커스텀 `train_step`/`test_step` 메서드를 멀티 프레임워크 구현으로 변환합니다. +- 레이어에서 stateless `keras.random` 연산자를 올바르게 사용하는지 확인합니다. -Let's go over each point in detail. +각 포인트를 자세히 살펴보겠습니다. -### Switching to Keras ops +### Keras 연산자로 전환하기 {#switching-to-keras-ops} -In many cases, this is the only thing you need to do to start being able to run your custom layers and metrics with JAX and PyTorch: replace any [`tf.*`](https://www.tensorflow.org/api_docs/python/tf/*), [`tf.math*`](https://www.tensorflow.org/api_docs/python/tf/math*), [`tf.linalg.*`](https://www.tensorflow.org/api_docs/python/tf/linalg/*), etc. with `keras.ops.*`. Most TF ops should be consistent with Keras 3. If the names different, they will be highlighted in this guide. +많은 경우, JAX와 PyTorch에서 커스텀 레이어와 메트릭을 실행할 수 있게 하려면 해야 할 유일한 일은 +[`tf.*`](https://www.tensorflow.org/api_docs/python/tf/*), +[`tf.math*`](https://www.tensorflow.org/api_docs/python/tf/math*), +[`tf.linalg.*`](https://www.tensorflow.org/api_docs/python/tf/linalg/*) 등의 호출을, +`keras.ops.*`로 교체하는 것입니다. +대부분의 TensorFlow 연산자는 Keras 3와 일치해야 합니다. +이름이 다른 경우, 이 가이드에서 강조하여 설명할 것입니다. -#### NumPy ops +#### NumPy ops {#numpy-ops} -Keras implements the NumPy API as part of `keras.ops`. +Keras는 `keras.ops`의 일부로 NumPy API를 구현합니다. -The table below only lists a small subset of TensorFlow and Keras ops; ops not listed are usually named the same in both frameworks (e.g. `reshape`, `matmul`, `cast`, etc.) +아래 표는 TensorFlow와 Keras의 연산자 중 일부분만 나열한 것입니다. +표에 나열되지 않은 연산자는, 두 프레임워크에서 동일한 이름을 사용하는 경우가 많습니다. +(예: `reshape`, `matmul`, `cast` 등) | TensorFlow | Keras 3.0 | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | @@ -722,44 +824,60 @@ The table below only lists a small subset of TensorFlow and Keras ops; ops not l | [`tf.gather_nd`](https://www.tensorflow.org/api_docs/python/tf/gather_nd) | [`keras.ops.take_along_axis`]({{< relref "/docs/api/ops/numpy#take_along_axis-function" >}}) | | [`tf.math.reduce_variance`](https://www.tensorflow.org/api_docs/python/tf/math/reduce_variance) | [`keras.ops.var`]({{< relref "/docs/api/ops/numpy#var-function" >}}) | -#### Others ops - -| TensorFlow | Keras 3.0 | -| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| [`tf.nn.sigmoid_cross_entropy_with_logits`](https://www.tensorflow.org/api_docs/python/tf/nn/sigmoid_cross_entropy_with_logits) | [`keras.ops.binary_crossentropy`]({{< relref "/docs/api/ops/nn#binary_crossentropy-function" >}}) (mind the `from_logits` argument) | -| [`tf.nn.sparse_softmax_cross_entropy_with_logits`](https://www.tensorflow.org/api_docs/python/tf/nn/sparse_softmax_cross_entropy_with_logits) | [`keras.ops.sparse_categorical_crossentropy`]({{< relref "/docs/api/ops/nn#sparse_categorical_crossentropy-function" >}}) (mind the `from_logits` argument) | -| [`tf.nn.sparse_softmax_cross_entropy_with_logits`](https://www.tensorflow.org/api_docs/python/tf/nn/sparse_softmax_cross_entropy_with_logits) | `keras.ops.categorical_crossentropy(target, output, from_logits=False, axis=-1)` | -| [`tf.nn.conv1d`](https://www.tensorflow.org/api_docs/python/tf/nn/conv1d), [`tf.nn.conv2d`](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d), [`tf.nn.conv3d`](https://www.tensorflow.org/api_docs/python/tf/nn/conv3d), [`tf.nn.convolution`](https://www.tensorflow.org/api_docs/python/tf/nn/convolution) | [`keras.ops.conv`]({{< relref "/docs/api/ops/nn#conv-function" >}}) | -| [`tf.nn.conv_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv_transpose), [`tf.nn.conv1d_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv1d_transpose), [`tf.nn.conv2d_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d_transpose), [`tf.nn.conv3d_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv3d_transpose) | [`keras.ops.conv_transpose`]({{< relref "/docs/api/ops/nn#conv_transpose-function" >}}) | -| [`tf.nn.depthwise_conv2d`](https://www.tensorflow.org/api_docs/python/tf/nn/depthwise_conv2d) | [`keras.ops.depthwise_conv`]({{< relref "/docs/api/ops/nn#depthwise_conv-function" >}}) | -| [`tf.nn.separable_conv2d`](https://www.tensorflow.org/api_docs/python/tf/nn/separable_conv2d) | [`keras.ops.separable_conv`]({{< relref "/docs/api/ops/nn#separable_conv-function" >}}) | -| [`tf.nn.batch_normalization`](https://www.tensorflow.org/api_docs/python/tf/nn/batch_normalization) | No direct equivalent; use [`keras.layers.BatchNormalization`]({{< relref "/docs/api/layers/normalization_layers/batch_normalization#batchnormalization-class" >}}) | -| [`tf.nn.dropout`](https://www.tensorflow.org/api_docs/python/tf/nn/dropout) | [`keras.random.dropout`]({{< relref "/docs/api/random/random_ops#dropout-function" >}}) | -| [`tf.nn.embedding_lookup`](https://www.tensorflow.org/api_docs/python/tf/nn/embedding_lookup) | [`keras.ops.take`]({{< relref "/docs/api/ops/numpy#take-function" >}}) | -| [`tf.nn.l2_normalize`](https://www.tensorflow.org/api_docs/python/tf/nn/l2_normalize) | [`keras.utils.normalize`]({{< relref "/docs/api/utils/python_utils#normalize-function" >}}) (not an op) | -| `x.numpy` | [`keras.ops.convert_to_numpy`]({{< relref "/docs/api/ops/core#convert_to_numpy-function" >}}) | -| [`tf.scatter_nd_update`](https://www.tensorflow.org/api_docs/python/tf/scatter_nd_update) | [`keras.ops.scatter_update`]({{< relref "/docs/api/ops/core#scatter_update-function" >}}) | -| [`tf.tensor_scatter_nd_update`](https://www.tensorflow.org/api_docs/python/tf/tensor_scatter_nd_update) | [`keras.ops.slice_update`]({{< relref "/docs/api/ops/core#slice_update-function" >}}) | -| [`tf.signal.fft2d`](https://www.tensorflow.org/api_docs/python/tf/signal/fft2d) | [`keras.ops.fft2`]({{< relref "/docs/api/ops/fft#fft2-function" >}}) | -| [`tf.signal.inverse_stft`](https://www.tensorflow.org/api_docs/python/tf/signal/inverse_stft) | [`keras.ops.istft`]({{< relref "/docs/api/ops/fft#istft-function" >}}) | -| [`tf.image.crop_to_bounding_box`](https://www.tensorflow.org/api_docs/python/tf/image/crop_to_bounding_box) | [`keras.ops.image.crop_images`]({{< relref "/docs/api/ops/image#crop_images-function" >}}) | -| [`tf.image.pad_to_bounding_box`](https://www.tensorflow.org/api_docs/python/tf/image/pad_to_bounding_box) | [`keras.ops.image.pad_images`]({{< relref "/docs/api/ops/image#pad_images-function" >}}) | - -### Custom `train_step()` methods - -Your models may include a custom `train_step()` or `test_step()` method, which rely on TensorFlow-only APIs – for instance, your `train_step()` method may leverage TensorFlow's [`tf.GradientTape`](https://www.tensorflow.org/api_docs/python/tf/GradientTape). To convert such models to run on JAX or PyTorch, you will have a write a different `train_step()` implementation for each backend you want to support. +#### 기타 ops {#others-ops} + +| TensorFlow | Keras 3.0 | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`tf.nn.sigmoid_cross_entropy_with_logits`](https://www.tensorflow.org/api_docs/python/tf/nn/sigmoid_cross_entropy_with_logits) | [`keras.ops.binary_crossentropy`]({{< relref "/docs/api/ops/nn#binary_crossentropy-function" >}}) (`from_logits` 인자에 유의하세요) | +| [`tf.nn.sparse_softmax_cross_entropy_with_logits`](https://www.tensorflow.org/api_docs/python/tf/nn/sparse_softmax_cross_entropy_with_logits) | [`keras.ops.sparse_categorical_crossentropy`]({{< relref "/docs/api/ops/nn#sparse_categorical_crossentropy-function" >}}) (`from_logits` 인자에 유의하세요) | +| [`tf.nn.sparse_softmax_cross_entropy_with_logits`](https://www.tensorflow.org/api_docs/python/tf/nn/sparse_softmax_cross_entropy_with_logits) | `keras.ops.categorical_crossentropy(target, output, from_logits=False, axis=-1)` | +| [`tf.nn.conv1d`](https://www.tensorflow.org/api_docs/python/tf/nn/conv1d), [`tf.nn.conv2d`](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d), [`tf.nn.conv3d`](https://www.tensorflow.org/api_docs/python/tf/nn/conv3d), [`tf.nn.convolution`](https://www.tensorflow.org/api_docs/python/tf/nn/convolution) | [`keras.ops.conv`]({{< relref "/docs/api/ops/nn#conv-function" >}}) | +| [`tf.nn.conv_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv_transpose), [`tf.nn.conv1d_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv1d_transpose), [`tf.nn.conv2d_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d_transpose), [`tf.nn.conv3d_transpose`](https://www.tensorflow.org/api_docs/python/tf/nn/conv3d_transpose) | [`keras.ops.conv_transpose`]({{< relref "/docs/api/ops/nn#conv_transpose-function" >}}) | +| [`tf.nn.depthwise_conv2d`](https://www.tensorflow.org/api_docs/python/tf/nn/depthwise_conv2d) | [`keras.ops.depthwise_conv`]({{< relref "/docs/api/ops/nn#depthwise_conv-function" >}}) | +| [`tf.nn.separable_conv2d`](https://www.tensorflow.org/api_docs/python/tf/nn/separable_conv2d) | [`keras.ops.separable_conv`]({{< relref "/docs/api/ops/nn#separable_conv-function" >}}) | +| [`tf.nn.batch_normalization`](https://www.tensorflow.org/api_docs/python/tf/nn/batch_normalization) | 직접적으로 동등한 것은 없습니다. 대신 [`keras.layers.BatchNormalization`]({{< relref "/docs/api/layers/normalization_layers/batch_normalization#batchnormalization-class" >}})를 사용하세요. | +| [`tf.nn.dropout`](https://www.tensorflow.org/api_docs/python/tf/nn/dropout) | [`keras.random.dropout`]({{< relref "/docs/api/random/random_ops#dropout-function" >}}) | +| [`tf.nn.embedding_lookup`](https://www.tensorflow.org/api_docs/python/tf/nn/embedding_lookup) | [`keras.ops.take`]({{< relref "/docs/api/ops/numpy#take-function" >}}) | +| [`tf.nn.l2_normalize`](https://www.tensorflow.org/api_docs/python/tf/nn/l2_normalize) | [`keras.utils.normalize`]({{< relref "/docs/api/utils/python_utils#normalize-function" >}}) (op 아님) | +| `x.numpy` | [`keras.ops.convert_to_numpy`]({{< relref "/docs/api/ops/core#convert_to_numpy-function" >}}) | +| [`tf.scatter_nd_update`](https://www.tensorflow.org/api_docs/python/tf/scatter_nd_update) | [`keras.ops.scatter_update`]({{< relref "/docs/api/ops/core#scatter_update-function" >}}) | +| [`tf.tensor_scatter_nd_update`](https://www.tensorflow.org/api_docs/python/tf/tensor_scatter_nd_update) | [`keras.ops.slice_update`]({{< relref "/docs/api/ops/core#slice_update-function" >}}) | +| [`tf.signal.fft2d`](https://www.tensorflow.org/api_docs/python/tf/signal/fft2d) | [`keras.ops.fft2`]({{< relref "/docs/api/ops/fft#fft2-function" >}}) | +| [`tf.signal.inverse_stft`](https://www.tensorflow.org/api_docs/python/tf/signal/inverse_stft) | [`keras.ops.istft`]({{< relref "/docs/api/ops/fft#istft-function" >}}) | +| [`tf.image.crop_to_bounding_box`](https://www.tensorflow.org/api_docs/python/tf/image/crop_to_bounding_box) | [`keras.ops.image.crop_images`]({{< relref "/docs/api/ops/image#crop_images-function" >}}) | +| [`tf.image.pad_to_bounding_box`](https://www.tensorflow.org/api_docs/python/tf/image/pad_to_bounding_box) | [`keras.ops.image.pad_images`]({{< relref "/docs/api/ops/image#pad_images-function" >}}) | + +### 커스텀 `train_step()` 메서드 {#custom-train_step-methods} + +당신의 모델에는 TensorFlow 전용 API를 사용하는 +커스텀 `train_step()` 또는 `test_step()` 메서드가 포함될 수 있습니다. +예를 들어, `train_step()` 메서드는 TensorFlow의 +[`tf.GradientTape`](https://www.tensorflow.org/api_docs/python/tf/GradientTape)를 사용할 수 있습니다. +이러한 모델을 JAX 또는 PyTorch에서 실행할 수 있도록 변환하려면, +지원하려는 각 백엔드에 맞는 별도의 `train_step()` 구현을 작성해야 합니다. + +일부 경우에는, `train_step()`을 재정의하는 대신, `Model.compute_loss()` 메서드를 재정의하여, +백엔드에 구애받지 않는 방식으로 만들 수 있습니다. +다음은 JAX, TensorFlow 및 PyTorch에서 작동하는, +커스텀 `compute_loss()` 메서드를 포함한 레이어의 예입니다: -In some cases, you might be able to simply override the `Model.compute_loss()` method and make it fully backend-agnostic, instead of overriding `train_step()`. Here's an example of a layer with a custom `compute_loss()` method which works across JAX, TensorFlow, and PyTorch: - -`class MyModel(keras.Model): def compute_loss(self, x=None, y=None, y_pred=None, sample_weight=None): loss = keras.ops.sum(keras.losses.mean_squared_error(y, y_pred, sample_weight)) return loss` +```python +class MyModel(keras.Model): + def compute_loss(self, x=None, y=None, y_pred=None, sample_weight=None): + loss = keras.ops.sum(keras.losses.mean_squared_error(y, y_pred, sample_weight)) + return loss +``` -If you need to modify the optimization mechanism itself, beyond the loss computation, then you will need to override `train_step()`, and implement one `train_step` method per backend, like below. +최적화 메커니즘 자체를 수정해야 한다면, +손실 계산을 넘어 `train_step()`을 재정의해야 하며, +백엔드마다 하나씩 `train_step` 메서드를 구현해야 합니다. +아래 예시와 같이 구현할 수 있습니다. -See the following guides for details on how each backend should be handled: +각 백엔드를 처리하는 방법에 대한 자세한 내용은 다음 가이드를 참조하십시오: -- [Customizing what happens in `fit()` with JAX]({{< relref "/docs/guides/custom_train_step_in_jax" >}}) -- [Customizing what happens in `fit()` with TensorFlow]({{< relref "/docs/guides/custom_train_step_in_tensorflow" >}}) -- [Customizing what happens in `fit()` with PyTorch]({{< relref "/docs/guides/custom_train_step_in_torch" >}}) +- {{< titledRelref "/docs/guides/custom_train_step_in_jax" >}} +- {{< titledRelref "/docs/guides/custom_train_step_in_tensorflow" >}} +- {{< titledRelref "/docs/guides/custom_train_step_in_torch" >}} ```python class MyModel(keras.Model): @@ -772,25 +890,27 @@ class MyModel(keras.Model): return self._torch_train_step(*args, **kwargs) def _jax_train_step(self, state, data): - pass # See guide: keras.io/guides/custom_train_step_in_jax/ + pass # 가이드를 참고하세요: keras.io/guides/custom_train_step_in_jax/ def _tensorflow_train_step(self, data): - pass # See guide: keras.io/guides/custom_train_step_in_tensorflow/ + pass # 가이드를 참고하세요: keras.io/guides/custom_train_step_in_tensorflow/ def _torch_train_step(self, data): - pass # See guide: keras.io/guides/custom_train_step_in_torch/ + pass # 가이드를 참고하세요: keras.io/guides/custom_train_step_in_torch/ ``` -### RNG-using layers +### RNG를 사용하는 레이어 {#rng-using-layers} -Keras 3 has a new `keras.random` namespace, containing: +Keras 3에는 새로운 `keras.random` 네임스페이스가 추가되었으며, 다음과 같은 기능들이 포함되어 있습니다: - [`keras.random.normal`]({{< relref "/docs/api/random/random_ops#normal-function" >}}) - [`keras.random.uniform`]({{< relref "/docs/api/random/random_ops#uniform-function" >}}) - [`keras.random.shuffle`]({{< relref "/docs/api/random/random_ops#shuffle-function" >}}) -- etc. +- 등. -These operations are **stateless**, which means that if you pass a `seed` argument, they will return the same result every time. Like this: +이 연산들은 **stateless**하며, 이는 `seed` 인자를 전달하면, +매번 동일한 결과를 반환한다는 것을 의미합니다. +예를 들어: ```python print(keras.random.normal(shape=(), seed=123)) @@ -806,7 +926,7 @@ tf.Tensor(0.7832616, shape=(), dtype=float32) {{% /details %}} -Crucially, this differs from the behavior of stateful [`tf.random`](https://www.tensorflow.org/api_docs/python/tf/random) ops: +이 점은 stateful [`tf.random`](https://www.tensorflow.org/api_docs/python/tf/random) 연산과 다릅니다: ```python print(tf.random.normal(shape=(), seed=123)) @@ -822,9 +942,14 @@ tf.Tensor(-0.6386405, shape=(), dtype=float32) {{% /details %}} -When you write a RNG-using layer, such as a custom dropout layer, you are going to want to use a different seed value at layer call. However, you cannot just increment a Python integer and pass it, because while this would work fine when executed eagerly, it would not work as expected when using compilation (which is available with JAX, TensorFlow, and PyTorch). When compiling the layer, the first Python integer seed value seen by the layer would be hardcoded into the compiled graph. +RNG를 사용하는 레이어를 작성하는 경우, 호출 시마다 다른 시드 값을 사용하고 싶을 것입니다. +그러나, Python 정수를 그냥 증가시켜 전달하는 것은 적절하지 않습니다. +이는 eager 실행 시에는 문제가 없지만, +JAX, TensorFlow, PyTorch에서 지원하는 컴파일을 사용할 경우, 예상대로 작동하지 않기 때문입니다. +레이어가 처음으로 본 Python 정수 시드 값이 컴파일된 그래프에 하드코딩될 수 있습니다. -To address this, you should pass as the `seed` argument an instance of a stateful [`keras.random.SeedGenerator`]({{< relref "/docs/api/random/seed_generator#seedgenerator-class" >}})object, like this: +이를 해결하기 위해, +seed 인자로 stateful [`keras.random.SeedGenerator`]({{< relref "/docs/api/random/seed_generator#seedgenerator-class" >}}) 객체를 전달해야 합니다. 예를 들어: ```python seed_generator = keras.random.SeedGenerator(1337) @@ -841,7 +966,7 @@ tf.Tensor(0.8211102, shape=(), dtype=float32) {{% /details %}} -So when writing a RNG using layer, you would use the following pattern: +따라서 RNG를 사용하는 레이어를 작성할 때는, 다음 패턴을 사용해야 합니다: ```python class RandomNoiseLayer(keras.layers.Layer): @@ -857,4 +982,5 @@ class RandomNoiseLayer(keras.layers.Layer): return inputs + noise ``` -Such a layer is safe to use in any setting – in eager execution or in a compiled model. Each layer call will be using a different seed value, as expected. +이렇게 작성된 레이어는 eager 실행 또는 컴파일된 모델 어느 환경에서도 안전하게 사용할 수 있습니다. +레이어 호출 시마다 예상대로 다른 시드 값을 사용하게 됩니다. diff --git a/content/korean/docs/guides/sequential_model/_index.md b/content/korean/docs/guides/sequential_model/_index.md index 383fe57c..882acd5b 100644 --- a/content/korean/docs/guides/sequential_model/_index.md +++ b/content/korean/docs/guides/sequential_model/_index.md @@ -17,7 +17,7 @@ type: docs {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/sequential_model.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Setup {#setup} +## 셋업 {#setup} ```python import keras @@ -25,14 +25,16 @@ from keras import layers from keras import ops ``` -## When to use a Sequential model {#when-to-use-a-sequential-model} +## Sequential 모델을 사용하는 경우 {#when-to-use-a-sequential-model} -A `Sequential` model is appropriate for **a plain stack of layers** where each layer has **exactly one input tensor and one output tensor**. +`Sequential` 모델은 각 레이어에 +**정확히 하나의 입력 텐서와 하나의 출력 텐서**가 있는 +**레이어들의 일반 스택**에 적합합니다. -Schematically, the following `Sequential` model: +개략적으로, 다음의 `Sequential` 모델을 봅시다. ```python -# Define Sequential model with 3 layers +# 3개의 레이어로 Sequential 모델 정의 model = keras.Sequential( [ layers.Dense(2, activation="relu", name="layer1"), @@ -40,34 +42,34 @@ model = keras.Sequential( layers.Dense(4, name="layer3"), ] ) -# Call model on a test input +# 테스트 입력에 대해 모델 호출 x = ops.ones((3, 3)) y = model(x) ``` -is equivalent to this function: +이 함수형 모델과 동일합니다: ```python -# Create 3 layers +# 3개의 레이어를 만듭니다 layer1 = layers.Dense(2, activation="relu", name="layer1") layer2 = layers.Dense(3, activation="relu", name="layer2") layer3 = layers.Dense(4, name="layer3") -# Call layers on a test input +# 테스트 입력에 대해 레이어 호출 x = ops.ones((3, 3)) y = layer3(layer2(layer1(x))) ``` -A Sequential model is **not appropriate** when: +Sequential 모델은 다음과 같은 경우, **적절하지 않습니다**. -- Your model has multiple inputs or multiple outputs -- Any of your layers has multiple inputs or multiple outputs -- You need to do layer sharing -- You want non-linear topology (e.g. a residual connection, a multi-branch model) +- 모델에 여러 입력 또는 여러 출력이 있는 경우 +- 레이어들 중 어떤 것에 여러 입력 또는 여러 출력이 있는 경우 +- 레이어 공유가 필요한 경우 +- 비선형 토폴로지(예: residual 연결, 다중 분기 모델)가 필요한 경우 -## Creating a Sequential model {#creating-a-sequential-model} +## Sequential 모델 생성 {#creating-a-sequential-model} -You can create a Sequential model by passing a list of layers to the Sequential constructor: +Sequential 생성자에 레이어 리스트를 전달하여 Sequential 모델을 생성할 수 있습니다. ```python model = keras.Sequential( @@ -79,7 +81,7 @@ model = keras.Sequential( ) ``` -Its layers are accessible via the `layers` attribute: +레이어는 `layers` 속성을 통해 접근할 수 있습니다. ```python model.layers @@ -95,7 +97,7 @@ model.layers {{% /details %}} -You can also create a Sequential model incrementally via the `add()` method: +`add()` 메서드를 통해 Sequential 모델을 증분 방식(incrementally)으로 생성할 수도 있습니다. ```python model = keras.Sequential() @@ -104,7 +106,8 @@ model.add(layers.Dense(3, activation="relu")) model.add(layers.Dense(4)) ``` -Note that there's also a corresponding `pop()` method to remove layers: a Sequential model behaves very much like a list of layers. +레이어를 제거하는 `pop()` 메서드도 있습니다. +Sequential 모델은 레이어 리스트와 매우 비슷하게 동작합니다. ```python model.pop() @@ -119,7 +122,8 @@ print(len(model.layers)) # 2 {{% /details %}} -Also note that the Sequential constructor accepts a `name` argument, just like any layer or model in Keras. This is useful to annotate TensorBoard graphs with semantically meaningful names. +또한 Sequential 생성자는 (Keras의 모든 레이어나 모델과 마찬가지로) `name` 인수를 허용합니다. +이는 의미적으로(semantically) 의미 있는(meaningful) 이름으로 TensorBoard 그래프에 어노테이션 하기에 유용합니다. ```python model = keras.Sequential(name="my_sequential") @@ -128,13 +132,14 @@ model.add(layers.Dense(3, activation="relu", name="layer2")) model.add(layers.Dense(4, name="layer3")) ``` -## Specifying the input shape in advance {#specifying-the-input-shape-in-advance} +## 입력 모양을 미리 지정 {#specifying-the-input-shape-in-advance} -Generally, all layers in Keras need to know the shape of their inputs in order to be able to create their weights. So when you create a layer like this, initially, it has no weights: +일반적으로, Keras의 모든 레이어는 가중치를 생성하기 위해 입력의 모양을 알아야 합니다. +따라서 이와 같은 레이어를 만들면, 처음에는 가중치가 없습니다. ```python layer = layers.Dense(3) -layer.weights # Empty +layer.weights # 비어 있음 ``` {{% details title="{{< t f_result >}}" closed="true" %}} @@ -145,13 +150,14 @@ layer.weights # Empty {{% /details %}} -It creates its weights the first time it is called on an input, since the shape of the weights depends on the shape of the inputs: +입력에 대해 처음 호출될 때 가중치를 생성합니다. +가중치의 모양은 입력의 모양에 따라 달라지기 때문입니다. ```python -# Call layer on a test input +# 테스트 입력에 대한 레이어 호출 x = ops.ones((1, 4)) y = layer(x) -layer.weights # Now it has weights, of shape (4, 3) and (3,) +layer.weights # 이제 (4, 3) 및 (3,) 모양의 가중치가 있습니다. ``` {{% details title="{{< t f_result >}}" closed="true" %}} @@ -163,7 +169,10 @@ layer.weights # Now it has weights, of shape (4, 3) and (3,) {{% /details %}} -Naturally, this also applies to Sequential models. When you instantiate a Sequential model without an input shape, it isn't "built": it has no weights (and calling `model.weights` results in an error stating just this). The weights are created when the model first sees some input data: +당연히, 이는 Sequential 모델에도 적용됩니다. +입력 모양 없이 Sequential 모델을 인스턴스화하면, "빌드"되지 않습니다. +가중치가 없습니다. (그리고 `model.weights`를 호출하면 이 오류만 발생합니다) +가중치는 모델이 처음 입력 데이터를 볼 때 생성됩니다. ```python model = keras.Sequential( @@ -172,15 +181,15 @@ model = keras.Sequential( layers.Dense(3, activation="relu"), layers.Dense(4), ] -) # No weights at this stage! +) # 이 단계에서는 가중치가 없습니다! -# At this point, you can't do this: +# 이 시점에서는, 다음을 수행할 수 없습니다. # model.weights -# You also can't do this: +# 다음 역시도 할 수 없습니다. # model.summary() -# Call the model on a test input +# 테스트 입력에 대해 모델 호출 x = ops.ones((1, 4)) y = model(x) print("Number of weights after calling the model:", len(model.weights)) # 6 @@ -194,7 +203,7 @@ Number of weights after calling the model: 6 {{% /details %}} -Once a model is "built", you can call its `summary()` method to display its contents: +모델이 "빌드"되면, `summary()` 메서드를 호출하여 내용을 표시할 수 있습니다. ```python model.summary() @@ -220,7 +229,9 @@ Model: "sequential_3" {{% /details %}} -However, it can be very useful when building a Sequential model incrementally to be able to display the summary of the model so far, including the current output shape. In this case, you should start your model by passing an `Input` object to your model, so that it knows its input shape from the start: +그러나, Sequential 모델을 점진적으로(incrementally) 빌드할 때, +지금까지의 모델 요약을 현재 출력 모양을 포함하여 표시할 수 있다면 매우 유용할 수 있습니다. +이 경우, `Input` 객체를 모델에 전달하여 모델을 시작해야 하며, 이렇게 하면 처음부터 입력 모양을 알 수 있습니다. ```python model = keras.Sequential() @@ -246,7 +257,7 @@ Model: "sequential_4" {{% /details %}} -Note that the `Input` object is not displayed as part of `model.layers`, since it isn't a layer: +`Input` 객체는 레이어가 아니기 때문에, `model.layers`의 일부로 표시되지 않습니다. ```python model.layers @@ -260,26 +271,31 @@ model.layers {{% /details %}} -Models built with a predefined input shape like this always have weights (even before seeing any data) and always have a defined output shape. +이와 같이 미리 정의된 입력 모양으로 빌드된 모델은, +항상 가중치를 갖고(데이터를 보기 전에도) 항상 정의된 출력 모양을 갖습니다. -In general, it's a recommended best practice to always specify the input shape of a Sequential model in advance if you know what it is. +일반적으로, Sequential 모델의 입력 모양을 알고 있다면, +항상 미리 지정하는 것이 권장되는 모범 사례입니다. -## A common debugging workflow: `add()` + `summary()` {#a-common-debugging-workflow-add-summary} +## 일반적인 디버깅 워크플로: `add()` + `summary()` {#a-common-debugging-workflow-add-summary} -When building a new Sequential architecture, it's useful to incrementally stack layers with `add()` and frequently print model summaries. For instance, this enables you to monitor how a stack of `Conv2D` and `MaxPooling2D` layers is downsampling image feature maps: +새로운 Sequential 아키텍처를 빌드할 때, +`add()`로 레이어를 점진적으로 쌓고(incrementally stack) 모델 요약을 자주 출력하는 것이 유용합니다. +예를 들어, 이를 통해 `Conv2D` 및 `MaxPooling2D` 레이어의 스택이, +이미지 특성 맵을 다운샘플링하는 방식을 모니터링할 수 있습니다. ```python model = keras.Sequential() -model.add(keras.Input(shape=(250, 250, 3))) # 250x250 RGB images +model.add(keras.Input(shape=(250, 250, 3))) # 250x250 RGB 이미지 model.add(layers.Conv2D(32, 5, strides=2, activation="relu")) model.add(layers.Conv2D(32, 3, activation="relu")) model.add(layers.MaxPooling2D(3)) -# Can you guess what the current output shape is at this point? Probably not. -# Let's just print it: +# 이 시점에서 현재 출력 모양이 무엇인지 추측할 수 있나요? 아마도 아닐 겁니다. +# 그냥 출력해 봅시다: model.summary() -# The answer was: (40, 40, 32), so we can keep downsampling... +# 답은 (40, 40, 32)입니다. 따라서 계속해서 다운샘플링할 수 있습니다. model.add(layers.Conv2D(32, 3, activation="relu")) model.add(layers.Conv2D(32, 3, activation="relu")) @@ -288,13 +304,13 @@ model.add(layers.Conv2D(32, 3, activation="relu")) model.add(layers.Conv2D(32, 3, activation="relu")) model.add(layers.MaxPooling2D(2)) -# And now? +# 그리고 지금은? model.summary() -# Now that we have 4x4 feature maps, time to apply global max pooling. +# 이제 4x4 특성 맵이 있으므로, 글로벌 최대 풀링을 적용할 시간입니다. model.add(layers.GlobalMaxPooling2D()) -# Finally, we add a classification layer. +# 마지막으로, 분류 레이어를 추가합니다. model.add(layers.Dense(10)) ``` @@ -343,18 +359,24 @@ Model: "sequential_5" {{% /details %}} -Very practical, right? +매우 실용적이죠? -## What to do once you have a model {#what-to-do-once-you-have-a-model} +## 모델이 생기면 무엇을 해야 하나요? {#what-to-do-once-you-have-a-model} -Once your model architecture is ready, you will want to: +모델 아키텍처가 준비되면 다음을 수행해야 합니다. -- Train your model, evaluate it, and run inference. See our [guide to training & evaluation with the built-in loops]({{< relref "/docs/guides/training_with_built_in_methods" >}}). -- Save your model to disk and restore it. See our [guide to serialization & saving]({{< relref "/docs/guides/serialization_and_saving" >}}). +- 모델을 트레이닝하고, 평가하고, 추론을 실행합니다. + {{< titledRelref "/docs/guides/training_with_built_in_methods" >}} 가이드를 참조하세요. +- 모델을 디스크에 저장하고 복원합니다. + {{< titledRelref "/docs/guides/serialization_and_saving" >}} 가이드를 참조하세요. -## Feature extraction with a Sequential model {#feature-extraction-with-a-sequential-model} +## Sequential 모델을 사용한 특성 추출 {#feature-extraction-with-a-sequential-model} -Once a Sequential model has been built, it behaves like a [Functional API model]({{< relref "/docs/guides/functional_api" >}}). This means that every layer has an `input` and `output` attribute. These attributes can be used to do neat things, like quickly creating a model that extracts the outputs of all intermediate layers in a Sequential model: +Sequential 모델이 빌드되면, +{{< titledRelref "/docs/guides/functional_api" >}} 모델처럼 동작합니다. +즉, 모든 레이어에 `input` 및 `output` 속성이 있습니다. +이러한 속성을 사용하면, Sequential 모델에서 모든 중간 레이어의 출력을 추출하는 모델을 빠르게 만드는 것과 같은, +멋진 작업을 수행할 수 있습니다. ```python initial_model = keras.Sequential( @@ -370,12 +392,12 @@ feature_extractor = keras.Model( outputs=[layer.output for layer in initial_model.layers], ) -# Call feature extractor on test input. +# 테스트 입력에 대해 feature_extractor를 호출합니다. x = ops.ones((1, 250, 250, 3)) features = feature_extractor(x) ``` -Here's a similar example that only extract features from one layer: +한 레이어에서만 특성을 추출하는 유사한 예는 다음과 같습니다. ```python initial_model = keras.Sequential( @@ -390,18 +412,22 @@ feature_extractor = keras.Model( inputs=initial_model.inputs, outputs=initial_model.get_layer(name="my_intermediate_layer").output, ) -# Call feature extractor on test input. +# 테스트 입력에 대해 feature_extractor를 호출합니다. x = ops.ones((1, 250, 250, 3)) features = feature_extractor(x) ``` -## Transfer learning with a Sequential model {#transfer-learning-with-a-sequential-model} +## Sequential 모델을 사용한 전이 학습 {#transfer-learning-with-a-sequential-model} -Transfer learning consists of freezing the bottom layers in a model and only training the top layers. If you aren't familiar with it, make sure to read our [guide to transfer learning]({{< relref "/docs/guides/transfer_learning" >}}). +전이 학습은 모델의 하위 레이어를 동결하고, 상위 레이어만 트레이닝하는 것으로 구성됩니다. +익숙하지 않은 경우, {{< titledRelref "/docs/guides/transfer_learning" >}} 가이드를 읽어보세요. -Here are two common transfer learning blueprint involving Sequential models. +다음은 Sequential 모델과 관련된 두 가지 일반적인 전이 학습 청사진입니다. -First, let's say that you have a Sequential model, and you want to freeze all layers except the last one. In this case, you would simply iterate over `model.layers` and set `layer.trainable = False` on each layer, except the last one. Like this: +먼저, Sequential 모델이 있고, 마지막 레이어를 제외한 모든 레이어를 동결하려고 한다고 가정해 보겠습니다. +이 경우, `model.layers`에 걸쳐 반복하고, +마지막 레이어를 제외한 모든 레이어에 `layer.trainable = False`를 설정하면 됩니다. +다음과 같습니다. ```python model = keras.Sequential([ @@ -412,46 +438,47 @@ model = keras.Sequential([ layers.Dense(10), ]) -# Presumably you would want to first load pre-trained weights. +# 아마도 먼저 사전 트레이닝된 가중치를 로드하고 싶을 것입니다. model.load_weights(...) -# Freeze all layers except the last one. +# 마지막 레이어를 제외한 모든 레이어를 동결합니다. for layer in model.layers[:-1]: layer.trainable = False -# Recompile and train (this will only update the weights of the last layer). +# 다시 컴파일하고 트레이닝시킵니다. (이렇게 하면 마지막 레이어의 가중치만 업데이트됩니다) model.compile(...) model.fit(...) ``` -Another common blueprint is to use a Sequential model to stack a pre-trained model and some freshly initialized classification layers. Like this: +또다른 일반적인 청사진은 Sequential 모델을 사용하여, +사전 트레이닝된 모델과 새로 초기화된 분류 레이어를 쌓는 것입니다. 다음과 같습니다. ```python -# Load a convolutional base with pre-trained weights +# 사전 트레이닝된 가중치를 사용하여, 컨볼루션 베이스 불러오기 base_model = keras.applications.Xception( weights='imagenet', include_top=False, pooling='avg') -# Freeze the base model +# 베이스 모델 동결 base_model.trainable = False -# Use a Sequential model to add a trainable classifier on top +# Sequential 모델을 사용하여, 상단에(on top) 트레이닝 가능한 분류기를 추가합니다. model = keras.Sequential([ base_model, layers.Dense(1000), ]) -# Compile & train +# 컴파일 & 트레이닝 model.compile(...) model.fit(...) ``` -If you do transfer learning, you will probably find yourself frequently using these two patterns. +전이 학습을 한다면, 아마도 이 두 패턴을 자주 사용하게 될 것입니다. -That's about all you need to know about Sequential models! +Sequential 모델에 대해 알아야 할 것은 이것뿐입니다! -To find out more about building models in Keras, see: +Keras에서 모델을 빌드하는 방법에 대한 자세한 내용은, 다음을 참조하세요. -- [Guide to the Functional API]({{< relref "/docs/guides/functional_api" >}}) -- [Guide to making new Layers & Models via subclassing]({{< relref "/docs/guides/making_new_layers_and_models_via_subclassing" >}}) +- {{< titledRelref "/docs/guides/functional_api" >}} 가이드 +- {{< titledRelref "/docs/guides/making_new_layers_and_models_via_subclassing" >}} 가이드 diff --git a/content/korean/docs/guides/serialization_and_saving/_index.md b/content/korean/docs/guides/serialization_and_saving/_index.md index 57956cb9..f3f44d3a 100644 --- a/content/korean/docs/guides/serialization_and_saving/_index.md +++ b/content/korean/docs/guides/serialization_and_saving/_index.md @@ -1,6 +1,6 @@ --- -title: Save, serialize, and export models -linkTitle: Serialization & Saving +title: 모델 저장, 직렬화 및 export +linkTitle: 직렬화 & 저장 toc: true weight: 11 type: docs @@ -8,53 +8,54 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Neel Kovelamudi, Francois Chollet +**{{< t f_author >}}** Neel Kovelamudi, Francois Chollet **{{< t f_date_created >}}** 2023/06/14 **{{< t f_last_modified >}}** 2023/06/30 -**{{< t f_description >}}** Complete guide to saving, serializing, and exporting models. +**{{< t f_description >}}** 모델 저장, 직렬화 및 export에 대한 완벽 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/serialization_and_saving.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/serialization_and_saving.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -A Keras model consists of multiple components: +Keras 모델은 여러 구성 요소로 이루어져 있습니다: -- The architecture, or configuration, which specifies what layers the model contain, and how they're connected. -- A set of weights values (the "state of the model"). -- An optimizer (defined by compiling the model). -- A set of losses and metrics (defined by compiling the model). +- 아키텍처 또는 설정: 모델에 포함된 레이어와 이들이 어떻게 연결되는지를 정의합니다. +- 가중치 값 세트 ("모델의 상태"). +- 옵티마이저 (모델을 컴파일할 때 정의됨). +- 손실 함수 및 메트릭 세트 (모델을 컴파일할 때 정의됨). -The Keras API saves all of these pieces together in a unified format, marked by the `.keras` extension. This is a zip archive consisting of the following: +Keras API는 이러한 모든 요소를 하나의 통합된 형식으로 저장하며, `.keras` 확장자로 표시됩니다. +이 형식은 다음을 포함하는 zip 아카이브입니다: -- A JSON-based configuration file (config.json): Records of model, layer, and other trackables' configuration. -- A H5-based state file, such as `model.weights.h5` (for the whole model), with directory keys for layers and their weights. -- A metadata file in JSON, storing things such as the current Keras version. +- JSON 기반 설정 파일 (`config.json`): 모델, 레이어 및 기타 추적 가능한 객체들의 설정을 기록합니다. +- H5 기반 상태 파일 (예: `model.weights.h5`): 레이어와 그 가중치에 대한 디렉터리 키를 포함하는 전체 모델 상태 파일. +- JSON 형식의 메타데이터 파일: 현재 Keras 버전과 같은 정보를 저장합니다. -Let's take a look at how this works. +이제 이것이 어떻게 작동하는지 살펴보겠습니다. -## How to save and load a model +## 모델 저장 및 로드 방법 {#how-to-save-and-load-a-model} -If you only have 10 seconds to read this guide, here's what you need to know. +이 가이드를 읽을 시간이 10초밖에 없다면, 다음 내용을 숙지하세요. -**Saving a Keras model:** +**Keras 모델 저장:** ```python -model = ... # Get model (Sequential, Functional Model, or Model subclass) -model.save('path/to/location.keras') # The file needs to end with the .keras extension +model = ... # 모델을 가져옵니다 (Sequential, Functional Model, 또는 Model 서브클래스) +model.save('path/to/location.keras') # 파일은 .keras 확장자로 끝나야 합니다. ``` -**Loading the model back:** +**모델 다시 로드:** ```python model = keras.models.load_model('path/to/location.keras') ``` -Now, let's look at the details. +이제 세부 사항을 살펴보겠습니다. -## Setup +## 셋업 {#setup} ```python import numpy as np @@ -62,26 +63,28 @@ import keras from keras import ops ``` -## Saving +## 저장 {#saving} -This section is about saving an entire model to a single file. The file will include: +이 섹션은 전체 모델을 하나의 파일로 저장하는 방법에 대한 내용입니다. 이 파일에는 다음이 포함됩니다: -- The model's architecture/config -- The model's weight values (which were learned during training) -- The model's compilation information (if `compile()` was called) -- The optimizer and its state, if any (this enables you to restart training where you left) +- 모델의 아키텍처/구성 +- 모델의 가중치 값 (트레이닝 중 학습된 값) +- 모델의 컴파일 정보 (만약 `compile()`이 호출되었다면) +- 옵티마이저 및 그 상태(있을 경우, 트레이닝을 중단했던 지점에서 다시 시작할 수 있도록 해줌) -#### APIs +#### APIs {#apis} -You can save a model with `model.save()` or `keras.models.save_model()` (which is equivalent). You can load it back with `keras.models.load_model()`. +`model.save()` 또는 `keras.models.save_model()`을 사용해, +모델을 저장할 수 있습니다. (둘은 동일합니다) +`keras.models.load_model()`을 사용해 다시 로드할 수 있습니다. -The only supported format in Keras 3 is the "Keras v3" format, which uses the `.keras` extension. +Keras 3에서 지원되는 유일한 형식은 ".keras" 확장자를 사용하는 "Keras v3" 형식입니다. -**Example:** +**예제:** ```python def get_model(): - # Create a simple model. + # 간단한 모델을 만듭니다. inputs = keras.Input(shape=(32,)) outputs = keras.layers.Dense(1)(inputs) model = keras.Model(inputs, outputs) @@ -91,18 +94,19 @@ def get_model(): model = get_model() -# Train the model. +# 모델을 트레이닝합니다. test_input = np.random.random((128, 32)) test_target = np.random.random((128, 1)) model.fit(test_input, test_target) -# Calling `save('my_model.keras')` creates a zip archive `my_model.keras`. +# `save('my_model.keras')`를 호출하면, +# `my_model.keras`라는 zip 아카이브가 생성됩니다. model.save("my_model.keras") -# It can be used to reconstruct the model identically. +# 동일하게 모델을 재구성할 수 있습니다. reconstructed_model = keras.models.load_model("my_model.keras") -# Let's check: +# 확인해봅시다: np.testing.assert_allclose( model.predict(test_input), reconstructed_model.predict(test_input) ) @@ -118,13 +122,17 @@ np.testing.assert_allclose( {{% /details %}} -### Custom objects +### 커스텀 객체 {#custom-objects} -This section covers the basic workflows for handling custom layers, functions, and models in Keras saving and reloading. +이 섹션에서는 Keras에서 커스텀 레이어, 함수, 모델을 저장하고 다시 불러오는 기본적인 워크플로를 다룹니다. -When saving a model that includes custom objects, such as a subclassed Layer, you **must** define a `get_config()` method on the object class. If the arguments passed to the constructor (`__init__()` method) of the custom object aren't Python objects (anything other than base types like ints, strings, etc.), then you **must** also explicitly deserialize these arguments in the `from_config()` class method. +커스텀 객체(서브클래스된 레이어 등)를 포함하는 모델을 저장할 때, +객체 클래스에 `get_config()` 메서드를 **반드시** 정의해야 합니다. +만약 커스텀 객체의 생성자(`__init__()` 메서드)에 전달된 인자가 +기본 타입(정수, 문자열 등)이 아닌 Python 객체라면, +`from_config()` 클래스 메서드에서 이러한 인자들을 명시적으로 **반드시** 역직렬화해야 합니다. -Like this: +예시는 다음과 같습니다: ```python class CustomLayer(keras.layers.Layer): @@ -149,32 +157,39 @@ class CustomLayer(keras.layers.Layer): return cls(sublayer, **config) ``` -Please see the [Defining the config methods section](#config_methods) for more details and examples. +자세한 내용과 예시는 [config 메서드 정의 섹션](#config_methods)을 참조하세요. -The saved `.keras` file is lightweight and does not store the Python code for custom objects. Therefore, to reload the model, `load_model` requires access to the definition of any custom objects used through one of the following methods: +저장된 `.keras` 파일은 경량화되어 있으며, +커스텀 객체에 대한 Python 코드를 저장하지 않습니다. +따라서, 모델을 다시 로드하려면, +`load_model`이 다음 중 하나의 방법을 통해 사용된, +커스텀 객체의 정의에 접근할 수 있어야 합니다: -1. Registering custom objects **(preferred)**, -2. Passing custom objects directly when loading, or -3. Using a custom object scope +1. 커스텀 객체를 등록 **(권장 방법)**, +2. 로드할 때 커스텀 객체를 직접 전달, 또는 +3. 커스텀 객체 scope를 사용하는 방법 -Below are examples of each workflow: +다음은 각각의 워크플로 예시입니다: -#### Registering custom objects (**preferred**) +#### 커스텀 객체 등록 (**권장 방법**) {#registering-custom-objects-preferred} -This is the preferred method, as custom object registration greatly simplifies saving and loading code. Adding the `@keras.saving.register_keras_serializable` decorator to the class definition of a custom object registers the object globally in a master list, allowing Keras to recognize the object when loading the model. +이 방법은 권장되는 방법입니다. +커스텀 객체 등록은 저장 및 로드 코드를 크게 단순화합니다. +커스텀 객체의 클래스 정의에 `@keras.saving.register_keras_serializable` 데코레이터를 추가하면, +해당 객체가 전역적으로 마스터 리스트에 등록되어, +Keras가 모델을 로드할 때 객체를 인식할 수 있습니다. -Let's create a custom model involving both a custom layer and a custom activation function to demonstrate this. +이를 설명하기 위해 커스텀 레이어와 커스텀 활성화 함수를 포함한, 커스텀 모델을 만들어보겠습니다. -**Example:** +**예제:** ```python -# Clear all previously registered custom objects +# 이전에 등록된 모든 커스텀 객체를 지웁니다. keras.saving.get_custom_objects().clear() -# Upon registration, you can optionally specify a package or a name. -# If left blank, the package defaults to `Custom` and the name defaults to -# the class name. +# 등록할 때 패키지나 이름을 선택적으로 지정할 수 있습니다. +# 지정하지 않으면 패키지는 `Custom`, 이름은 클래스 이름으로 설정됩니다. @keras.saving.register_keras_serializable(package="MyLayers") class CustomLayer(keras.layers.Layer): def __init__(self, factor): @@ -193,7 +208,7 @@ def custom_fn(x): return x**2 -# Create the model. +# 모델을 만듭니다. def get_model(): inputs = keras.Input(shape=(4,)) mid = CustomLayer(0.5)(inputs) @@ -203,7 +218,7 @@ def get_model(): return model -# Train the model. +# 모델을 트레이닝합니다. def train_model(model): input = np.random.random((4, 4)) target = np.random.random((4, 1)) @@ -218,10 +233,10 @@ model = get_model() model = train_model(model) model.save("custom_model.keras") -# Now, we can simply load without worrying about our custom objects. +# 이제, 커스텀 객체에 대해 걱정할 필요 없이 간단히 로드할 수 있습니다. reconstructed_model = keras.models.load_model("custom_model.keras") -# Let's check: +# 확인해봅시다: np.testing.assert_allclose( model.predict(test_input), reconstructed_model.predict(test_input) ) @@ -237,23 +252,23 @@ np.testing.assert_allclose( {{% /details %}} -#### Passing custom objects to `load_model()` +#### `load_model()`에 커스텀 객체 전달 {#passing-custom-objects-to-loadmodel} ```python model = get_model() model = train_model(model) -# Calling `save('my_model.keras')` creates a zip archive `my_model.keras`. +# `save('my_model.keras')`를 호출하면, `my_model.keras`라는 zip 아카이브가 생성됩니다. model.save("custom_model.keras") -# Upon loading, pass a dict containing the custom objects used in the -# `custom_objects` argument of `keras.models.load_model()`. +# 로드할 때 `keras.models.load_model()`의 `custom_objects` 인자로 +# 사용된 커스텀 객체를 포함하는 딕셔너리를 전달합니다. reconstructed_model = keras.models.load_model( "custom_model.keras", custom_objects={"CustomLayer": CustomLayer, "custom_fn": custom_fn}, ) -# Let's check: +# 확인해봅시다: np.testing.assert_allclose( model.predict(test_input), reconstructed_model.predict(test_input) ) @@ -269,25 +284,26 @@ np.testing.assert_allclose( {{% /details %}} -#### Using a custom object scope +#### 커스텀 객체 scope를 사용 {#using-a-custom-object-scope} -Any code within the custom object scope will be able to recognize the custom objects passed to the scope argument. Therefore, loading the model within the scope will allow the loading of our custom objects. +커스텀 객체 scope 내의 코드는 scope 인자로 전달된 커스텀 객체를 인식할 수 있습니다. +따라서, 모델을 해당 scope 내에서 로드하면 커스텀 객체도 함께 로드할 수 있습니다. -**Example:** +**예제:** ```python model = get_model() model = train_model(model) model.save("custom_model.keras") -# Pass the custom objects dictionary to a custom object scope and place -# the `keras.models.load_model()` call within the scope. +# 커스텀 객체 딕셔너리를 커스텀 객체 scope에 전달하고, +# `keras.models.load_model()` 호출을 해당 scope 내에 배치합니다. custom_objects = {"CustomLayer": CustomLayer, "custom_fn": custom_fn} with keras.saving.custom_object_scope(custom_objects): reconstructed_model = keras.models.load_model("custom_model.keras") -# Let's check: +# 확인해봅시다: np.testing.assert_allclose( model.predict(test_input), reconstructed_model.predict(test_input) ) @@ -303,35 +319,45 @@ np.testing.assert_allclose( {{% /details %}} -### Model serialization +### 모델 직렬화 {#model-serialization} -This section is about saving only the model's configuration, without its state. The model's configuration (or architecture) specifies what layers the model contains, and how these layers are connected. If you have the configuration of a model, then the model can be created with a freshly initialized state (no weights or compilation information). +이 섹션은 모델의 상태 없이 모델의 구성만 저장하는 방법에 대한 내용입니다. +모델의 구성(또는 아키텍처)은 모델이 어떤 레이어를 포함하고 있으며, +이 레이어들이 어떻게 연결되어 있는지를 명시합니다. +모델의 구성을 가지고 있다면, +가중치나 컴파일 정보 없이 새롭게 초기화된 상태로 모델을 생성할 수 있습니다. -#### APIs +#### APIs {#apis} -The following serialization APIs are available: +다음과 같은 직렬화 API를 사용할 수 있습니다: -- `keras.models.clone_model(model)`: make a (randomly initialized) copy of a model. -- `get_config()` and `cls.from_config()`: retrieve the configuration of a layer or model, and recreate a model instance from its config, respectively. -- `keras.models.model_to_json()` and `keras.models.model_from_json()`: similar, but as JSON strings. -- `keras.saving.serialize_keras_object()`: retrieve the configuration any arbitrary Keras object. -- `keras.saving.deserialize_keras_object()`: recreate an object instance from its configuration. +- `keras.models.clone_model(model)`: 모델의 (랜덤하게 초기화된) 복사본을 생성합니다. +- `get_config()` 및 `cls.from_config()`: 레이어 또는 모델의 구성을 검색오고, 해당 구성으로 모델 인스턴스를 재생성합니다. +- `keras.models.model_to_json()` 및 `keras.models.model_from_json()`: 유사하지만, JSON 문자열로 처리됩니다. +- `keras.saving.serialize_keras_object()`: 임의의 Keras 객체 구성을 검색합니다. +- `keras.saving.deserialize_keras_object()`: 객체의 구성으로부터 인스턴스를 재생성합니다. -#### In-memory model cloning +#### 메모리 내에서 모델 복제 {#in-memory-model-cloning} -You can do in-memory cloning of a model via `keras.models.clone_model()`. This is equivalent to getting the config then recreating the model from its config (so it does not preserve compilation information or layer weights values). +`keras.models.clone_model()`을 사용하여 메모리 내에서 모델을 복제할 수 있습니다. +이는 config를 가져온 다음 해당 config에서 모델을 재생성하는 것과 동일하며, +컴파일 정보나 레이어 가중치 값은 유지되지 않습니다. -**Example:** +**예제:** ```python new_model = keras.models.clone_model(model) ``` -#### `get_config()` and `from_config()` +#### `get_config()` 및 `from_config()` {#getconfig-and-fromconfig} -Calling `model.get_config()` or `layer.get_config()` will return a Python dict containing the configuration of the model or layer, respectively. You should define `get_config()` to contain arguments needed for the `__init__()` method of the model or layer. At loading time, the `from_config(config)` method will then call `__init__()` with these arguments to reconstruct the model or layer. +`model.get_config()` 또는 `layer.get_config()`을 호출하면, +각각 모델 또는 레이어의 구성을 포함한 Python 딕셔너리가 반환됩니다. +모델이나 레이어의 `__init__()` 메서드에 필요한 인자를 `get_config()`에 정의해야 합니다. +로딩 시, `from_config(config)` 메서드가 이러한 인자들과 함께, +`__init__()`을 호출하여 모델 또는 레이어를 재구성합니다. -**Layer example:** +**레이어 예시:** ```python layer = keras.layers.Dense(3, activation="relu") @@ -347,13 +373,13 @@ print(layer_config) {{% /details %}} -Now let's reconstruct the layer using the `from_config()` method: +이제 `from_config()` 메서드를 사용하여 레이어를 재구성해봅시다: ```python new_layer = keras.layers.Dense.from_config(layer_config) ``` -**Sequential model example:** +**Sequential 모델 예시:** ```python model = keras.Sequential([keras.Input((32,)), keras.layers.Dense(1)]) @@ -361,7 +387,7 @@ config = model.get_config() new_model = keras.Sequential.from_config(config) ``` -**Functional model example:** +**Functional 모델 예시:** ```python inputs = keras.Input((32,)) @@ -371,11 +397,13 @@ config = model.get_config() new_model = keras.Model.from_config(config) ``` -#### `to_json()` and `keras.models.model_from_json()` +#### `to_json()` 및 `keras.models.model_from_json()` {#tojson-and-kerasmodelsmodelfromjson} -This is similar to `get_config` / `from_config`, except it turns the model into a JSON string, which can then be loaded without the original model class. It is also specific to models, it isn't meant for layers. +이것은 `get_config` / `from_config`과 유사하지만, +모델을 JSON 문자열로 변환하여 원본 모델 클래스 없이도 로드할 수 있습니다. +또한, 이는 모델에만 적용되며 레이어에는 사용되지 않습니다. -**Example:** +**예제:** ```python model = keras.Sequential([keras.Input((32,)), keras.layers.Dense(1)]) @@ -383,11 +411,14 @@ json_config = model.to_json() new_model = keras.models.model_from_json(json_config) ``` -#### Arbitrary object serialization and deserialization +#### 임의 객체 직렬화 및 역직렬화 {#arbitrary-object-serialization-and-deserialization} -The `keras.saving.serialize_keras_object()` and `keras.saving.deserialize_keras_object()` APIs are general-purpose APIs that can be used to serialize or deserialize any Keras object and any custom object. It is at the foundation of saving model architecture and is behind all `serialize()`/`deserialize()` calls in keras. +`keras.saving.serialize_keras_object()` 및 `keras.saving.deserialize_keras_object()` API는 +Keras 객체와 커스텀 객체를 직렬화하거나 역직렬화할 수 있는 범용 API입니다. +이는 모델 아키텍처 저장의 기반이 되며, +Keras 내의 모든 `serialize()`/`deserialize()` 호출의 배경에 있습니다. -**Example**: +**예제**: ```python my_reg = keras.regularizers.L1(0.005) @@ -403,36 +434,37 @@ print(config) {{% /details %}} -Note the serialization format containing all the necessary information for proper reconstruction: +올바르게 재구성하기 위한, 모든 필수 정보를 포함하는 직렬화 형식을 확인하세요: -- `module` containing the name of the Keras module or other identifying module the object comes from -- `class_name` containing the name of the object's class. -- `config` with all the information needed to reconstruct the object -- `registered_name` for custom objects. See [here](#custom_object_serialization). +- `module`: 객체가 속한 Keras 모듈 또는 기타 식별 모듈의 이름을 포함 +- `class_name`: 객체 클래스의 이름을 포함 +- `config`: 객체를 재구성하는 데 필요한 모든 정보 +- `registered_name`: 커스텀 객체의 경우. [여기](#custom_object_serialization)를 참조하세요. -Now we can reconstruct the regularizer. +이제 정규화기(regularizer)를 재구성할 수 있습니다. ```python new_reg = keras.saving.deserialize_keras_object(config) ``` -### Model weights saving +### 모델 가중치 저장 {#model-weights-saving} -You can choose to only save & load a model's weights. This can be useful if: +모델의 가중치만 저장하고 로드하는 것도 선택할 수 있습니다. +이는 다음과 같은 경우에 유용할 수 있습니다: -- You only need the model for inference: in this case you won't need to restart training, so you don't need the compilation information or optimizer state. -- You are doing transfer learning: in this case you will be training a new model reusing the state of a prior model, so you don't need the compilation information of the prior model. +- 모델을 추론에만 사용할 경우: 이 경우 트레이닝을 다시 시작할 필요가 없으므로, 컴파일 정보나 옵티마이저 상태가 필요하지 않습니다. +- 전이 학습을 할 경우: 이전 모델의 상태를 재사용하여 새 모델을 트레이닝하려는 경우, 이전 모델의 컴파일 정보는 필요하지 않습니다. -#### APIs for in-memory weight transfer +#### 메모리 내에서 가중치 전송을 위한 API {#apis-for-in-memory-weight-transfer} -Weights can be copied between different objects by using `get_weights()` and `set_weights()`: +`get_weights()`와 `set_weights()`를 사용하여, 다른 객체 간에 가중치를 복사할 수 있습니다: -- `keras.layers.Layer.get_weights()`: Returns a list of NumPy arrays of weight values. -- `keras.layers.Layer.set_weights(weights)`: Sets the model weights to the values provided (as NumPy arrays). +- `keras.layers.Layer.get_weights()`: 가중치 값을 NumPy 배열 목록으로 반환합니다. +- `keras.layers.Layer.set_weights(weights)`: 제공된 NumPy 배열로 모델의 가중치를 설정합니다. -Examples: +예제: -**_Transferring weights from one layer to another, in memory_** +**_메모리 내에서, 한 레이어에서 다른 레이어로 가중치 전송_** ```python def create_layer(): @@ -444,14 +476,14 @@ def create_layer(): layer_1 = create_layer() layer_2 = create_layer() -# Copy weights from layer 1 to layer 2 +# 레이어 1에서 레이어 2로 가중치 복사 layer_2.set_weights(layer_1.get_weights()) ``` -**_Transferring weights from one model to another model with a compatible architecture, in memory_** +**_메모리 내에서, 호환되는 아키텍처를 가진 두 모델 간에 가중치 전송_** ```python -# Create a simple functional model +# 간단한 Functional 모델 생성 inputs = keras.Input(shape=(784,), name="digits") x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs) x = keras.layers.Dense(64, activation="relu", name="dense_2")(x) @@ -459,7 +491,7 @@ outputs = keras.layers.Dense(10, name="predictions")(x) functional_model = keras.Model(inputs=inputs, outputs=outputs, name="3_layer_mlp") -# Define a subclassed model with the same architecture +# 동일한 아키텍처를 가진 서브클래스된 모델 정의 class SubclassedModel(keras.Model): def __init__(self, output_dim, name=None): super().__init__(name=name) @@ -479,10 +511,10 @@ class SubclassedModel(keras.Model): subclassed_model = SubclassedModel(10) -# Call the subclassed model once to create the weights. +# 서브클래스된 모델을 한 번 호출하여 가중치를 생성합니다. subclassed_model(np.ones((1, 784))) -# Copy weights from functional_model to subclassed_model. +# functional_model에서 subclassed_model로 가중치를 복사합니다. subclassed_model.set_weights(functional_model.get_weights()) assert len(functional_model.weights) == len(subclassed_model.weights) @@ -490,9 +522,10 @@ for a, b in zip(functional_model.weights, subclassed_model.weights): np.testing.assert_allclose(a.numpy(), b.numpy()) ``` -**_The case of stateless layers_** +**_stateless 레이어의 경우_** -Because stateless layers do not change the order or number of weights, models can have compatible architectures even if there are extra/missing stateless layers. +stateless 레이어는 가중치의 순서나 수를 변경하지 않기 때문에, +stateless 레이어가 추가되거나 빠지더라도(extra/missing) 모델은 호환되는 아키텍처를 가질 수 있습니다. ```python inputs = keras.Input(shape=(784,), name="digits") @@ -505,7 +538,7 @@ inputs = keras.Input(shape=(784,), name="digits") x = keras.layers.Dense(64, activation="relu", name="dense_1")(inputs) x = keras.layers.Dense(64, activation="relu", name="dense_2")(x) -# Add a dropout layer, which does not contain any weights. +# 가중치를 포함하지 않는, 드롭아웃 레이어를 추가합니다. x = keras.layers.Dropout(0.5)(x) outputs = keras.layers.Dense(10, name="predictions")(x) functional_model_with_dropout = keras.Model( @@ -515,14 +548,15 @@ functional_model_with_dropout = keras.Model( functional_model_with_dropout.set_weights(functional_model.get_weights()) ``` -#### APIs for saving weights to disk & loading them back +#### 가중치를 디스크에 저장하고 다시 로드하는 API {#apis-for-saving-weights-to-disk-and-loading-them-back} -Weights can be saved to disk by calling `model.save_weights(filepath)`. The filename should end in `.weights.h5`. +`model.save_weights(filepath)`을 호출하여, 가중치를 디스크에 저장할 수 있습니다. +파일 이름은 `.weights.h5`로 끝나야 합니다. -**Example:** +**예제:** ```python -# Runnable example +# 실행 가능한 예시 sequential_model = keras.Sequential( [ keras.Input(shape=(784,), name="digits"), @@ -535,7 +569,8 @@ sequential_model.save_weights("my_model.weights.h5") sequential_model.load_weights("my_model.weights.h5") ``` -Note that changing `layer.trainable` may result in a different `layer.weights` ordering when the model contains nested layers. +모델에 중첩된 레이어가 있을 경우, +`layer.trainable`을 변경하면 `layer.weights`의 순서가 달라질 수 있습니다. ```python class NestedDenseLayer(keras.layers.Layer): @@ -577,11 +612,13 @@ variable ordering changed: False {{% /details %}} -##### **Transfer learning example** +##### **전이 학습 예시** {#transfer-learning-example} -When loading pretrained weights from a weights file, it is recommended to load the weights into the original checkpointed model, and then extract the desired weights/layers into a new model. +사전 트레이닝된 가중치를 가중치 파일에서 로드할 때는, +원래 체크포인트된 모델에 가중치를 로드한 후, +원하는 가중치/레이어를 새로운 모델에 추출하는 것이 좋습니다. -**Example:** +**예제:** ```python def create_functional_model(): @@ -595,11 +632,11 @@ def create_functional_model(): functional_model = create_functional_model() functional_model.save_weights("pretrained.weights.h5") -# In a separate program: +# 별도의 프로그램에서: pretrained_model = create_functional_model() pretrained_model.load_weights("pretrained.weights.h5") -# Create a new model by extracting layers from the original model: +# 원본 모델에서 레이어를 추출하여, 새로운 모델을 생성합니다: extracted_layers = pretrained_model.layers[:-1] extracted_layers.append(keras.layers.Dense(5, name="dense_3")) model = keras.Sequential(extracted_layers) @@ -626,18 +663,24 @@ Model: "sequential_4" {{% /details %}} -### Appendix: Handling custom objects +### 부록: 커스텀 객체 다루기 {#appendix-handling-custom-objects} -#### Defining the config methods {#config_methods} +#### config 메서드 정의 {#config_methods} -Specifications: +명세: -- `get_config()` should return a JSON-serializable dictionary in order to be compatible with the Keras architecture- and model-saving APIs. -- `from_config(config)` (a `classmethod`) should return a new layer or model object that is created from the config. The default implementation returns `cls(**config)`. +- `get_config()`은 + Keras 아키텍처 및 모델 저장 API와 호환되기 위해, JSON 직렬화가 가능한 딕셔너리를 반환해야 합니다. +- `from_config(config)` (`classmethod`)은 + config에서 생성된 새로운 레이어 또는 모델 객체를 반환해야 합니다. + 기본 구현은 `cls(**config)`을 반환합니다. -**NOTE**: If all your constructor arguments are already serializable, e.g. strings and ints, or non-custom Keras objects, overriding `from_config` is not necessary. However, for more complex objects such as layers or models passed to `__init__`, deserialization must be handled explicitly either in `__init__` itself or overriding the `from_config()` method. +**참고**: 모든 생성자 인자가 이미 직렬화 가능하다면, 예: 문자열, 정수, 또는 커스텀 Keras 객체가 아니라면, +`from_config`를 재정의할 필요가 없습니다. +그러나, `__init__`에 전달된 레이어 또는 모델과 같은 더 복잡한 객체에 대해서는, +`__init__` 자체에서 역직렬화를 명시적으로 처리하거나 `from_config()` 메서드를 재정의해야 합니다. -**Example:** +**예제:** ```python @keras.saving.register_keras_serializable(package="MyLayers", name="KernelMult") @@ -659,7 +702,7 @@ class MyDense(keras.layers.Layer): def get_config(self): config = super().get_config() - # Update the config with the custom layer's parameters + # 커스텀 레이어의 매개변수로 config를 업데이트합니다. config.update( { "units": self.hidden_units, @@ -704,13 +747,17 @@ print(new_layer) {{% /details %}} -Note that overriding `from_config` is unnecessary above for `MyDense` because `hidden_units`, `kernel_initializer`, and `kernel_regularizer` are ints, strings, and a built-in Keras object, respectively. This means that the default `from_config` implementation of `cls(**config)` will work as intended. +위의 `MyDense`에서는 `from_config`를 재정의할 필요가 없다는 점에 유의하세요. +왜냐하면 `hidden_units`, `kernel_initializer`, 그리고 `kernel_regularizer`가 +각각 정수, 문자열, 그리고 빌트인 Keras 객체이기 때문입니다. +이는 기본 `from_config` 구현인 `cls(**config)`가 의도한 대로 작동한다는 것을 의미합니다. -For more complex objects, such as layers and models passed to `__init__`, for example, you must explicitly deserialize these objects. Let's take a look at an example of a model where a `from_config` override is necessary. +`__init__`에 전달되는 레이어나 모델과 같은, 더 복잡한 객체에 대해서는 명시적으로 해당 객체를 역직렬화해야 합니다. +`from_config` 재정의가 필요한 모델의 예시를 살펴보겠습니다. -###### Registration example {#registration_example} + -**Example:** +**예제:** ```python @keras.saving.register_keras_serializable(package="ComplexModels") @@ -735,7 +782,8 @@ class CustomModel(keras.layers.Layer): @classmethod def from_config(cls, config): - # Note that you can also use [`keras.saving.deserialize_keras_object`](/api/models/model_saving_apis/serialization_utils#deserializekerasobject-function) here + # 여기서 [`keras.saving.deserialize_keras_object`](/api/models/model_saving_apis/serialization_utils#deserializekerasobject-function) + # 를 사용할 수도 있습니다. config["first_layer"] = keras.layers.deserialize(config["first_layer"]) config["second_layer"] = keras.layers.deserialize(config["second_layer"]) return cls(**config) @@ -744,7 +792,7 @@ class CustomModel(keras.layers.Layer): return self.first_layer(self.second_layer(inputs)) -# Let's make our first layer the custom layer from the previous example (MyDense) +# 첫 번째 레이어로 이전 예시에서 만든 커스텀 레이어 (MyDense)를 사용합니다. inputs = keras.Input((32,)) outputs = CustomModel(first_layer=layer)(inputs) model = keras.Model(inputs, outputs) @@ -753,13 +801,15 @@ config = model.get_config() new_model = keras.Model.from_config(config) ``` -#### How custom objects are serialized {#custom_object_serialization} +#### 커스텀 객체가 직렬화되는 방식 {#custom_object_serialization} -The serialization format has a special key for custom objects registered via `@keras.saving.register_keras_serializable`. This `registered_name` key allows for easy retrieval at loading/deserialization time while also allowing users to add custom naming. +직렬화 형식에는 `@keras.saving.register_keras_serializable`로 등록된 커스텀 객체에 대한 특별한 키가 있습니다. +이 `registered_name` 키는 로딩/역직렬화 시 Keras 마스터 리스트에서 쉽게 검색할 수 있도록 하며, +사용자들이 커스텀 이름을 추가할 수 있도록 합니다. -Let's take a look at the config from serializing the custom layer `MyDense` we defined above. +위에서 정의한 커스텀 레이어 `MyDense`를 직렬화한 후의 구성을 살펴보겠습니다. -**Example**: +**예제**: ```python layer = MyDense( @@ -779,8 +829,11 @@ print(config) {{% /details %}} -As shown, the `registered_name` key contains the lookup information for the Keras master list, including the package `MyLayers` and the custom name `KernelMult` that we gave in the `@keras.saving.register_keras_serializable` decorator. Take a look again at the custom class definition/registration [here](#registration_example). +보시다시피, `registered_name` 키에는 Keras 마스터 리스트의 조회 정보를 포함하고 있으며, +`MyLayers`라는 패키지와 `@keras.saving.register_keras_serializable` 데코레이터에서 지정한 커스텀 이름 `KernelMult`가 포함되어 있습니다. +커스텀 클래스 정의/등록에 대해서는 다시 [여기](#registration_example)를 참조하세요. -Note that the `class_name` key contains the original name of the class, allowing for proper re-initialization in `from_config`. +`class_name` 키는 클래스의 원본 이름을 포함하여, `from_config`에서 적절한 재초기화를 가능하게 합니다. -Additionally, note that the `module` key is `None` since this is a custom object. +또한, `module` 키가 `None`인 것을 주목하세요. +이는 커스텀 객체이기 때문입니다. diff --git a/content/korean/docs/guides/training_with_built_in_methods/_index.md b/content/korean/docs/guides/training_with_built_in_methods/_index.md index 22d19f9f..2c4a101f 100644 --- a/content/korean/docs/guides/training_with_built_in_methods/_index.md +++ b/content/korean/docs/guides/training_with_built_in_methods/_index.md @@ -1,5 +1,6 @@ --- -title: Training & evaluation with the built-in methods +title: 빌트인 메서드를 사용한 트레이닝 및 평가 +linkTitle: 빌트인 메서드로 트레이닝 및 평가 toc: true weight: 4 type: docs @@ -10,17 +11,17 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2019/03/01 **{{< t f_last_modified >}}** 2023/06/25 -**{{< t f_description >}}** Complete guide to training & evaluation with `fit()` and `evaluate()`. +**{{< t f_description >}}** `fit()` 및 `evaluate()`를 활용한 트레이닝 및 평가에 대한 완벽 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/training_with_built_in_methods.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/training_with_built_in_methods.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Setup +## 셋업 {#setup} ```python -# We import torch & TF so as to use torch Dataloaders & tf.data.Datasets. +# torch Dataloader와 tf.data.Datasets를 사용하기 위해 torch와 TF를 import 합니다. import torch import tensorflow as tf @@ -31,36 +32,44 @@ from keras import layers from keras import ops ``` -## Introduction +## 소개 {#introduction} -This guide covers training, evaluation, and prediction (inference) models when using built-in APIs for training & validation (such as `Model.fit()`, `Model.evaluate()` and `Model.predict()`). +이 가이드는 트레이닝 및 검증을 위한 +빌트인 API(예: `Model.fit()`, `Model.evaluate()` 및 `Model.predict()`)를 사용할 때, +트레이닝, 평가 및 예측(추론) 모델을 다룹니다. -If you are interested in leveraging `fit()` while specifying your own training step function, see the guides on customizing what happens in `fit()`: +`fit()`를 활용하면서 자체 트레이닝 스텝 함수를 지정하는 데 관심이 있다면, +`fit()`에서 발생하는 것을 커스터마이즈하는 방법에 대한 가이드를 참조하세요. -- [Writing a custom train step with TensorFlow]({{< relref "/docs/guides/custom_train_step_in_tensorflow" >}}) -- [Writing a custom train step with JAX]({{< relref "/docs/guides/custom_train_step_in_jax" >}}) -- [Writing a custom train step with PyTorch]({{< relref "/docs/guides/custom_train_step_in_torch" >}}) +- [TensorFlow로 커스텀 트레이닝 스텝 작성]({{< relref "/docs/guides/custom_train_step_in_tensorflow" >}}) +- [JAX로 커스텀 트레이닝 스텝 작성]({{< relref "/docs/guides/custom_train_step_in_jax" >}}) +- [PyTorch로 커스텀 트레이닝 스텝 작성]({{< relref "/docs/guides/custom_train_step_in_torch" >}}) -If you are interested in writing your own training & evaluation loops from scratch, see the guides on writing training loops: +자체 트레이닝 및 평가 루프를 처음부터 작성하는 데 관심이 있다면, 트레이닝 루프 작성에 대한 가이드를 참조하세요. -- [Writing a training loop with TensorFlow]({{< relref "/docs/guides/writing_a_custom_training_loop_in_tensorflow" >}}) -- [Writing a training loop with JAX]({{< relref "/docs/guides/writing_a_custom_training_loop_in_jax" >}}) -- [Writing a training loop with PyTorch]({{< relref "/docs/guides/writing_a_custom_training_loop_in_torch" >}}) +- [TensorFlow로 트레이닝 루프 작성]({{< relref "/docs/guides/writing_a_custom_training_loop_in_tensorflow" >}}) +- [JAX로 트레이닝 루프 작성]({{< relref "/docs/guides/writing_a_custom_training_loop_in_jax" >}}) +- [PyTorch로 트레이닝 루프 작성]({{< relref "/docs/guides/writing_a_custom_training_loop_in_torch" >}}) -In general, whether you are using built-in loops or writing your own, model training & evaluation works strictly in the same way across every kind of Keras model – Sequential models, models built with the Functional API, and models written from scratch via model subclassing. +일반적으로, 빌트인 루프를 사용하든 직접 작성하든, 모델 트레이닝 및 평가는, +모든 종류의 Keras 모델(Sequential 모델, 함수형 API로 빌드한 모델, 모델 서브클래싱을 통해 처음부터 작성한 모델)에서, +엄격하게 동일한 방식으로 작동합니다. -## API overview: a first end-to-end example +## API 개요: 첫 번째 엔드투엔드 예시 {#api-overview-a-first-end-to-end-example} -When passing data to the built-in training loops of a model, you should either use: +모델의 빌트인 트레이닝 루프에 데이터를 전달할 때, 다음을 사용해야 합니다. -- NumPy arrays (if your data is small and fits in memory) -- Subclasses of [`keras.utils.PyDataset`]({{< relref "/docs/api/utils/python_utils#pydataset-class" >}}) -- [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) objects -- PyTorch `DataLoader` instances +- NumPy 배열(데이터가 작고 메모리에 맞는 경우) +- [`keras.utils.PyDataset`]({{< relref "/docs/api/utils/python_utils#pydataset-class" >}})의 하위 클래스 +- [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) 객체 +- PyTorch `DataLoader` 인스턴스 -In the next few paragraphs, we'll use the MNIST dataset as NumPy arrays, in order to demonstrate how to use optimizers, losses, and metrics. Afterwards, we'll take a close look at each of the other options. +다음 몇 단락에서는, +MNIST 데이터 세트를 NumPy 배열로 사용하여 옵티마이저, 손실 및 메트릭을 사용하는 방법을 설명합니다. +그런 다음, 다른 옵션을 자세히 살펴보겠습니다. -Let's consider the following model (here, we build in with the Functional API, but it could be a Sequential model or a subclassed model as well): +다음 모델을 고려해 보겠습니다. +(여기서는 Functional API로 빌드하지만 Sequential 모델이거나 서브 클래스로된 모델일 수도 있습니다) ```python inputs = keras.Input(shape=(784,), name="digits") @@ -71,44 +80,46 @@ outputs = layers.Dense(10, activation="softmax", name="predictions")(x) model = keras.Model(inputs=inputs, outputs=outputs) ``` -Here's what the typical end-to-end workflow looks like, consisting of: +다음은 일반적인 엔드투엔드 워크플로우의 모습이며, 다음으로 구성됩니다. -- Training -- Validation on a holdout set generated from the original training data -- Evaluation on the test data +- 트레이닝 +- 원본 트레이닝 데이터로부터 생성된 홀드아웃 세트에 대한 검증 +- 테스트 데이터에 대한 평가 -We'll use MNIST data for this example. +이 예제에서는 MNIST 데이터를 사용합니다. ```python (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() -# Preprocess the data (these are NumPy arrays) +# 데이터 전처리(NumPy 배열) x_train = x_train.reshape(60000, 784).astype("float32") / 255 x_test = x_test.reshape(10000, 784).astype("float32") / 255 y_train = y_train.astype("float32") y_test = y_test.astype("float32") -# Reserve 10,000 samples for validation +# 검증을 위해 10,000개의 샘플을 예약합니다. x_val = x_train[-10000:] y_val = y_train[-10000:] x_train = x_train[:-10000] y_train = y_train[:-10000] ``` -We specify the training configuration (optimizer, loss, metrics): +트레이닝 구성(옵티마이저, 손실, 메트릭)을 지정합니다. ```python model.compile( - optimizer=keras.optimizers.RMSprop(), # Optimizer - # Loss function to minimize + optimizer=keras.optimizers.RMSprop(), # 옵티마이저 + # 최소화할 손실 함수 loss=keras.losses.SparseCategoricalCrossentropy(), - # List of metrics to monitor + # 모니터링할 메트릭 목록 metrics=[keras.metrics.SparseCategoricalAccuracy()], ) ``` -We call `fit()`, which will train the model by slicing the data into "batches" of size `batch_size`, and repeatedly iterating over the entire dataset for a given number of `epochs`. +`fit()`를 호출하는데, +이 함수는 데이터를 `batch_size` 크기의 "배치"로 나누어 모델을 트레이닝하고, +주어진 횟수의 `epoch` 동안 전체 데이터 세트에 걸쳐 반복적으로 반복(repeatedly iterating)합니다. ```python print("Fit model on training data") @@ -117,9 +128,7 @@ history = model.fit( y_train, batch_size=64, epochs=2, - # We pass some validation for - # monitoring validation loss and metrics - # at the end of each epoch + # 각 에포크의 끝에서 검증 손실 및 메트릭을 모니터링하기 위한 일부 검증 데이터를 전달합니다. validation_data=(x_val, y_val), ) ``` @@ -136,7 +145,7 @@ Epoch 2/2 {{% /details %}} -The returned `history` object holds a record of the loss values and metric values during training: +반환된 `history` 객체는 트레이닝 중의 손실 값과 메트릭 값의 기록을 보관합니다. ```python print(history.history) @@ -150,16 +159,15 @@ print(history.history) {{% /details %}} -We evaluate the model on the test data via `evaluate()`: +`evaluate()`를 통해, 테스트 데이터에 대해 모델을 평가합니다. ```python -# Evaluate the model on the test data using `evaluate` +# `evaluate`를 사용하여 테스트 데이터에 대해 모델을 평가합니다. print("Evaluate on test data") results = model.evaluate(x_test, y_test, batch_size=128) print("test loss, test acc:", results) -# Generate predictions (probabilities -- the output of the last layer) -# on new data using `predict` +# `predict`를 사용하여, 새 데이터에 대한 예측(확률 -- 마지막 레이어의 출력)을 생성합니다. print("Generate predictions for 3 samples") predictions = model.predict(x_test[:3]) print("predictions shape:", predictions.shape) @@ -178,13 +186,14 @@ predictions shape: (3, 10) {{% /details %}} -Now, let's review each piece of this workflow in detail. +이제, 이 워크플로의 각 부분을 자세히 살펴보겠습니다. -## The `compile()` method: specifying a loss, metrics, and an optimizer +## `compile()` 메서드: 손실, 메트릭 및 옵티마이저 지정 {#the-compile-method-specifying-a-loss-metrics-and-an-optimizer} -To train a model with `fit()`, you need to specify a loss function, an optimizer, and optionally, some metrics to monitor. +`fit()`로 모델을 트레이닝하려면, 손실 함수, 옵티마이저, +그리고 선택적으로 모니터링할 몇 가지 메트릭을 지정해야 합니다. -You pass these to the model as arguments to the `compile()` method: +다음을 `compile()` 메서드의 인수로 모델에 전달합니다. ```python model.compile( @@ -194,11 +203,14 @@ model.compile( ) ``` -The `metrics` argument should be a list – your model can have any number of metrics. +`metrics` 인수는 목록이어야 합니다. 모델은 원하는 수의 메트릭을 가질 수 있습니다. -If your model has multiple outputs, you can specify different losses and metrics for each output, and you can modulate the contribution of each output to the total loss of the model. You will find more details about this in the **Passing data to multi-input, multi-output models** section. +모델에 여러 출력이 있는 경우, 각 출력에 대해 다른 손실과 메트릭을 지정할 수 있으며, +각 출력이 모델의 총 손실에 기여하는 정도를 조절할 수 있습니다. +이에 대한 자세한 내용은 **다중 입력, 다중 출력 모델에 데이터 전달** 섹션에서 확인할 수 있습니다. -Note that if you're satisfied with the default settings, in many cases the optimizer, loss, and metrics can be specified via string identifiers as a shortcut: +기본 설정에 만족하는 경우, +많은 케이스에서 옵티마이저, 손실 및 메트릭을 단축어로 문자열 식별자를 통해 지정할 수 있습니다. ```python model.compile( @@ -208,7 +220,8 @@ model.compile( ) ``` -For later reuse, let's put our model definition and compile step in functions; we will call them several times across different examples in this guide. +나중에 재사용할 수 있도록, 모델 정의와 컴파일 단계를 함수에 넣겠습니다. +이 가이드의 여러 예제에서 이러한 함수를 여러 번 호출하겠습니다. ```python def get_uncompiled_model(): @@ -230,36 +243,38 @@ def get_compiled_model(): return model ``` -### Many built-in optimizers, losses, and metrics are available +### 다양한 빌트인 옵티마이저, 손실 및 메트릭을 사용할 수 있습니다. {#many-built-in-optimizers-losses-and-metrics-are-available} -In general, you won't have to create your own losses, metrics, or optimizers from scratch, because what you need is likely to be already part of the Keras API: +일반적으로, 처음부터 직접 손실, 메트릭 또는 옵티마이저를 만들 필요가 없습니다. +필요한 것이 이미 Keras API에 포함되어 있을 가능성이 높기 때문입니다. -Optimizers: +옵티마이저: -- `SGD()` (with or without momentum) +- `SGD()` (모멘텀 포함 또는 미포함) - `RMSprop()` - `Adam()` -- etc. +- 등 -Losses: +손실: - `MeanSquaredError()` - `KLDivergence()` - `CosineSimilarity()` -- etc. +- 등 -Metrics: +메트릭: - `AUC()` - `Precision()` - `Recall()` -- etc. +- 등 -### Custom losses +### 커스텀 손실 {#custom-losses} -If you need to create a custom loss, Keras provides three ways to do so. +커스텀 손실을 만들어야 하는 경우, Keras는 세 가지 방법을 제공합니다. -The first method involves creating a function that accepts inputs `y_true` and `y_pred`. The following example shows a loss function that computes the mean squared error between the real data and the predictions: +첫 번째 방법은 입력 `y_true` 및 `y_pred`를 받는 함수를 만드는 것입니다. +다음 예는 실제 데이터와 예측 간의 평균 제곱 오차를 계산하는 손실 함수를 보여줍니다. ```python def custom_mean_squared_error(y_true, y_pred): @@ -269,7 +284,7 @@ def custom_mean_squared_error(y_true, y_pred): model = get_uncompiled_model() model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error) -# We need to one-hot encode the labels to use MSE +# MSE를 사용하려면 레이블을 원핫 인코딩해야 합니다. y_train_one_hot = ops.one_hot(y_train, num_classes=10) model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1) ``` @@ -284,14 +299,20 @@ model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1) {{% /details %}} -If you need a loss function that takes in parameters beside `y_true` and `y_pred`, you can subclass the [`keras.losses.Loss`]({{< relref "/docs/api/losses#loss-class" >}}) class and implement the following two methods: +`y_true`와 `y_pred` 외의 매개변수를 사용하는 손실 함수가 필요한 경우, +[`keras.losses.Loss`]({{< relref "/docs/api/losses#loss-class" >}}) 클래스를 서브 클래스하고, +다음 두 가지 메서드를 구현합니다. -- `__init__(self)`: accept parameters to pass during the call of your loss function -- `call(self, y_true, y_pred)`: use the targets (y_true) and the model predictions (y_pred) to compute the model's loss +- `__init__(self)`: 손실 함수 호출 중에 전달할 매개변수를 받습니다. +- `call(self, y_true, y_pred)`: 대상(y_true)과 모델 예측(y_pred)을 사용하여, 모델의 손실을 계산합니다. -Let's say you want to use mean squared error, but with an added term that will de-incentivize prediction values far from 0.5 (we assume that the categorical targets are one-hot encoded and take values between 0 and 1). This creates an incentive for the model not to be too confident, which may help reduce overfitting (we won't know if it works until we try!). +평균 제곱 오차를 사용하려고 하지만, 예측 값이 0.5에서 멀어지는 것을 억제하는 추가 항을 사용하려고 한다고 가정해 보겠습니다. +(카테고리 대상이 원핫 인코딩되고, 0과 1 사이의 값을 사용한다고 가정) +이렇게 하면, 모델이 너무 확신하지 않도록 하는 인센티브가 생겨, +과적합을 줄이는 데 도움이 될 수 있습니다. +(시도해보기 전까지는 작동하는지 알 수 없습니다!) -Here's how you would do it: +방법은 다음과 같습니다. ```python class CustomMSE(keras.losses.Loss): @@ -322,18 +343,23 @@ model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1) {{% /details %}} -### Custom metrics +### 커스텀 메트릭 {#custom-metrics} -If you need a metric that isn't part of the API, you can easily create custom metrics by subclassing the [`keras.metrics.Metric`]({{< relref "/docs/api/metrics/base_metric#metric-class" >}}) class. You will need to implement 4 methods: +API에 속하지 않는 메트릭이 필요한 경우, +[`keras.metrics.Metric`]({{< relref "/docs/api/metrics/base_metric#metric-class" >}}) 클래스를 서브클래싱하여, +커스텀 메트릭을 쉽게 만들 수 있습니다. +4가지 메서드를 구현해야 합니다. -- `__init__(self)`, in which you will create state variables for your metric. -- `update_state(self, y_true, y_pred, sample_weight=None)`, which uses the targets y_true and the model predictions y_pred to update the state variables. -- `result(self)`, which uses the state variables to compute the final results. -- `reset_state(self)`, which reinitializes the state of the metric. +- `__init__(self)`: 메트릭의 상태 변수를 만듭니다. +- `update_state(self, y_true, y_pred, sample_weight=None)`: 대상 y_true와 모델 예측 y_pred를 사용하여, 상태 변수를 업데이트합니다. +- `result(self)`: 상태 변수를 사용하여, 최종 결과를 계산합니다. +- `reset_state(self)`: 메트릭의 상태를 다시 초기화합니다. -State update and results computation are kept separate (in `update_state()` and `result()`, respectively) because in some cases, the results computation might be very expensive and would only be done periodically. +상태 업데이트와 결과 계산은 별도로 유지됩니다. (각각 `update_state()`와 `result()`에서) +어떤 경우에는 결과 계산이 매우 비용이 많이 들고, 주기적으로만 수행될 수 있기 때문입니다. -Here's a simple example showing how to implement a `CategoricalTruePositives` metric that counts how many samples were correctly classified as belonging to a given class: +다음은 주어진 클래스에 속하는 것으로 올바르게 분류된 샘플 수를 세는, +`CategoricalTruePositives` 메트릭을 구현하는 방법을 보여주는 간단한 예입니다. ```python class CategoricalTruePositives(keras.metrics.Metric): @@ -356,7 +382,7 @@ class CategoricalTruePositives(keras.metrics.Metric): return self.true_positives.value def reset_state(self): - # The state of the metric will be reset at the start of each epoch. + # 각 에포크가 시작될 때마다, 메트릭 상태가 재설정됩니다. self.true_positives.assign(0.0) @@ -384,23 +410,30 @@ Epoch 3/3 {{% /details %}} -### Handling losses and metrics that don't fit the standard signature +### 표준 서명에 맞지 않는 손실 및 메트릭 다루기 {#handling-losses-and-metrics-that-dont-fit-the-standard-signature} -The overwhelming majority of losses and metrics can be computed from `y_true` and `y_pred`, where `y_pred` is an output of your model – but not all of them. For instance, a regularization loss may only require the activation of a layer (there are no targets in this case), and this activation may not be a model output. +손실과 메트릭의 압도적 다수는 `y_true`와 `y_pred`에서 계산할 수 있습니다. +여기서 `y_pred`는 모델의 출력이지만, 전부는 아닙니다. +예를 들어, 정규화 손실은 레이어 활성화만 필요할 수 있습니다. (이 경우 타겟이 없음) +이 활성화는 모델 출력이 아닐 수 있습니다. -In such cases, you can call `self.add_loss(loss_value)` from inside the call method of a custom layer. Losses added in this way get added to the "main" loss during training (the one passed to `compile()`). Here's a simple example that adds activity regularization (note that activity regularization is built-in in all Keras layers – this layer is just for the sake of providing a concrete example): +이러한 경우, 커스텀 레이어의 call 메서드 내부에서 `self.add_loss(loss_value)`를 호출할 수 있습니다. +이런 방식으로 추가된 손실은 트레이닝 중에 "메인" 손실(`compile()`에 전달된 손실)에 추가됩니다. +다음은 activity 정규화를 추가하는 간단한 예입니다. +(activity 정규화는 모든 Keras 레이어에 빌트인되어 있음에 유의하세요. +이 레이어는 구체적인 예를 제공하기 위한 것입니다) ```python class ActivityRegularizationLayer(layers.Layer): def call(self, inputs): self.add_loss(ops.sum(inputs) * 0.1) - return inputs # Pass-through layer. + return inputs # Pass-through 레이어. inputs = keras.Input(shape=(784,), name="digits") x = layers.Dense(64, activation="relu", name="dense_1")(inputs) -# Insert activity regularization as a layer +# activity 정규화를 레이어로 삽입 x = ActivityRegularizationLayer()(x) x = layers.Dense(64, activation="relu", name="dense_2")(x) @@ -412,8 +445,7 @@ model.compile( loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True), ) -# The displayed loss will be much higher than before -# due to the regularization component. +# 정규화 구성 요소로 인해, 표시되는 손실은 이전보다 훨씬 높아질 것입니다. model.fit(x_train, y_train, batch_size=64, epochs=1) ``` @@ -427,9 +459,12 @@ model.fit(x_train, y_train, batch_size=64, epochs=1) {{% /details %}} -Note that when you pass losses via `add_loss()`, it becomes possible to call `compile()` without a loss function, since the model already has a loss to minimize. +`add_loss()`를 통해 손실을 전달할 때, +모델에 이미 최소화해야 할 손실이 있으므로, +손실 함수 없이 `compile()`을 호출할 수 있습니다. -Consider the following `LogisticEndpoint` layer: it takes as inputs targets & logits, and it tracks a crossentropy loss via `add_loss()`. +다음의 `LogisticEndpoint` 레이어를 고려해 보세요. +대상과 로짓을 입력으로 받고, `add_loss()`를 통해 교차 엔트로피 손실을 추적합니다. ```python class LogisticEndpoint(keras.layers.Layer): @@ -438,16 +473,16 @@ class LogisticEndpoint(keras.layers.Layer): self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True) def call(self, targets, logits, sample_weights=None): - # Compute the training-time loss value and add it - # to the layer using `self.add_loss()`. + # 트레이닝 시간 손실 값을 계산하고, + # `self.add_loss()`를 사용하여 레이어에 추가합니다. loss = self.loss_fn(targets, logits, sample_weights) self.add_loss(loss) - # Return the inference-time prediction tensor (for `.predict()`). + # 추론 시간 예측 텐서를 반환합니다. (`.predict()`를 위해) return ops.softmax(logits) ``` -You can use it in a model with two inputs (input data & targets), compiled without a `loss` argument, like this: +다음과 같이, `loss` 인수 없이 컴파일된, 두 개의 입력(입력 데이터 및 대상)이 있는 모델에서 사용할 수 있습니다. ```python inputs = keras.Input(shape=(3,), name="inputs") @@ -456,7 +491,7 @@ logits = keras.layers.Dense(10)(inputs) predictions = LogisticEndpoint(name="predictions")(targets, logits) model = keras.Model(inputs=[inputs, targets], outputs=predictions) -model.compile(optimizer="adam") # No loss argument! +model.compile(optimizer="adam") # 손실 인수가 없습니다! data = { "inputs": np.random.random((3, 3)), @@ -475,17 +510,24 @@ model.fit(data) {{% /details %}} -For more information about training multi-input models, see the section **Passing data to multi-input, multi-output models**. +다중 입력 모델을 트레이닝하는 방법에 대한 자세한 내용은, +**다중 입력, 다중 출력 모델에 데이터 전달** 섹션을 참조하세요. -### Automatically setting apart a validation holdout set +### 검증 홀드아웃 세트를 자동으로 분리하는 설정 {#automatically-setting-apart-a-validation-holdout-set} -In the first end-to-end example you saw, we used the `validation_data` argument to pass a tuple of NumPy arrays `(x_val, y_val)` to the model for evaluating a validation loss and validation metrics at the end of each epoch. +첫 번째 엔드투엔드 예제에서, `validation_data` 인수를 사용하여, +각 에포크의 끝에서 검증 손실과 검증 메트릭을 평가하기 위해, +NumPy 배열 `(x_val, y_val)`의 튜플을 모델에 전달했습니다. -Here's another option: the argument `validation_split` allows you to automatically reserve part of your training data for validation. The argument value represents the fraction of the data to be reserved for validation, so it should be set to a number higher than 0 and lower than 1. For instance, `validation_split=0.2` means "use 20% of the data for validation", and `validation_split=0.6` means "use 60% of the data for validation". +또 다른 옵션은 다음과 같습니다. +`validation_split` 인수를 사용하면 검증을 위해, 자동으로 트레이닝 데이터의 일부를 예약할 수 있습니다. +인수 값은 검증을 위해 예약할 데이터의 비율을 나타내므로, 0보다 크고 1보다 작은 숫자로 설정해야 합니다. +예를 들어, `validation_split=0.2`는 "검증에 데이터의 20% 사용"을 의미하고, +`validation_split=0.6`은 "검증에 데이터의 60% 사용"을 의미합니다. -The way the validation is computed is by taking the last x% samples of the arrays received by the `fit()` call, before any shuffling. +검증을 계산하는 방법은, 셔플링 전에 `fit()` 호출에서 수신한 배열의 마지막 x% 샘플을 가져오는 것입니다. -Note that you can only use `validation_split` when training with NumPy data. +NumPy 데이터로 트레이닝할 때만, `validation_split`을 사용할 수 있습니다. ```python model = get_compiled_model() @@ -502,34 +544,38 @@ model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1) {{% /details %}} -## Training & evaluation using [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) Datasets +## [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) 데이터 세트를 사용한 트레이닝 및 평가 {#tfdata} -In the past few paragraphs, you've seen how to handle losses, metrics, and optimizers, and you've seen how to use the `validation_data` and `validation_split` arguments in `fit()`, when your data is passed as NumPy arrays. +지난 몇 단락에서, 손실, 메트릭, 옵티마이저를 처리하는 방법을 살펴보았고, +데이터가 NumPy 배열로 전달될 때, +`fit()`에서 `validation_data` 및 `validation_split` 인수를 사용하는 방법을 살펴보았습니다. -Another option is to use an iterator-like, such as a [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset), a PyTorch `DataLoader`, or a Keras `PyDataset`. Let's take look at the former. +또다른 옵션은 [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset), PyTorch `DataLoader` 또는 Keras `PyDataset`와 같은, +iterator와 유사한 것을 사용하는 것입니다. `tf.data.Dataset`를 살펴보겠습니다. -The [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) API is a set of utilities in TensorFlow 2.0 for loading and preprocessing data in a way that's fast and scalable. For a complete guide about creating `Datasets`, see the [tf.data documentation](https://www.tensorflow.org/guide/data). +[`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) API는 빠르고 확장 가능한 방식으로 데이터를 로드하고 사전 처리하기 위한 TensorFlow 2.0의 유틸리티 세트입니다. +`Datasets` 생성에 대한 전체 가이드는 [tf.data 문서](https://www.tensorflow.org/guide/data)를 참조하세요. -**You can use [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) to train your Keras models regardless of the backend you're using – whether it's JAX, PyTorch, or TensorFlow.** You can pass a `Dataset` instance directly to the methods `fit()`, `evaluate()`, and `predict()`: +**JAX, PyTorch 또는 TensorFlow 등 사용하는 백엔드에 관계없이 [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data)를 사용하여 Keras 모델을 트레이닝할 수 있습니다.** +`Dataset` 인스턴스를 `fit()`, `evaluate()` 및 `predict()` 메서드에 직접 전달할 수 있습니다. ```python model = get_compiled_model() -# First, let's create a training Dataset instance. -# For the sake of our example, we'll use the same MNIST data as before. +# 먼저, 트레이닝 데이터셋 인스턴스를 만들어 보겠습니다. +# 예를 들어, 이전과 동일한 MNIST 데이터를 사용하겠습니다. train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) -# Shuffle and slice the dataset. +# 데이터 세트를 셔플하고, 분할합니다. train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64) -# Now we get a test dataset. +# 이제 테스트 데이터 세트를 얻습니다. test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)) test_dataset = test_dataset.batch(64) -# Since the dataset already takes care of batching, -# we don't pass a `batch_size` argument. +# 데이터 세트가 이미 배치를 처리하므로, `batch_size` 인수를 전달하지 않습니다. model.fit(train_dataset, epochs=3) -# You can also evaluate or predict on a dataset. +# 데이터 세트에 대해 평가하거나 예측할 수도 있습니다. print("Evaluate") result = model.evaluate(test_dataset) dict(zip(model.metrics_names, result)) @@ -552,18 +598,21 @@ Evaluate {{% /details %}} -Note that the Dataset is reset at the end of each epoch, so it can be reused of the next epoch. +각 에포크가 끝나면 Dataset이 재설정되므로, 다음 에포크에서 재사용할 수 있습니다. -If you want to run training only on a specific number of batches from this Dataset, you can pass the `steps_per_epoch` argument, which specifies how many training steps the model should run using this Dataset before moving on to the next epoch. +이 Dataset에서 특정 수의 배치에 대해서만 트레이닝을 실행하려면, +`steps_per_epoch` 인수를 전달할 수 있습니다. +이 인수는 다음 에포크로 넘어가기 전에 +이 Dataset을 사용하여 모델이 실행해야 하는 트레이닝 단계 수를 지정합니다. ```python model = get_compiled_model() -# Prepare the training dataset +# 트레이닝 데이터 세트 준비 train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64) -# Only use the 100 batches per epoch (that's 64 * 100 samples) +# 에포크당 100개 배치만 사용하세요. (64 * 100개 샘플) model.fit(train_dataset, epochs=3, steps_per_epoch=100) ``` @@ -582,16 +631,16 @@ Epoch 3/3 {{% /details %}} -You can also pass a `Dataset` instance as the `validation_data` argument in `fit()`: +`fit()`에서 `validation_data` 인수로 `Dataset` 인스턴스를 전달할 수도 있습니다. ```python model = get_compiled_model() -# Prepare the training dataset +# 트레이닝 데이터 세트 준비 train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64) -# Prepare the validation dataset +# 검증 데이터 세트 준비 val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val)) val_dataset = val_dataset.batch(64) @@ -608,26 +657,29 @@ model.fit(train_dataset, epochs=1, validation_data=val_dataset) {{% /details %}} -At the end of each epoch, the model will iterate over the validation dataset and compute the validation loss and validation metrics. +각 에포크가 끝나면, 모델은 검증 데이터 세트에 걸쳐 반복하고, 검증 손실과 검증 메트릭을 계산합니다. -If you want to run validation only on a specific number of batches from this dataset, you can pass the `validation_steps` argument, which specifies how many validation steps the model should run with the validation dataset before interrupting validation and moving on to the next epoch: +이 데이터 세트에서 특정 수의 배치에 대해서만 검증을 실행하려면, +`validation_steps` 인수를 전달할 수 있습니다. +이 인수는 검증을 중단하고 다음 에포크로 넘어가기 전에, +모델이 검증 데이터 세트로 실행해야 하는 검증 단계 수를 지정합니다. ```python model = get_compiled_model() -# Prepare the training dataset +# 트레이닝 데이터 세트 준비 train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64) -# Prepare the validation dataset +# 검증 데이터 세트 준비 val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val)) val_dataset = val_dataset.batch(64) model.fit( train_dataset, epochs=1, - # Only run validation using the first 10 batches of the dataset - # using the `validation_steps` argument + # `validation_steps` 인수를 사용하여, + # 데이터 세트의 처음 10개 배치만 사용하여 검증을 실행합니다. validation_data=val_dataset, validation_steps=10, ) @@ -643,25 +695,30 @@ model.fit( {{% /details %}} -Note that the validation dataset will be reset after each use (so that you will always be evaluating on the same samples from epoch to epoch). +검증 데이터 세트는 각 사용 후 재설정되므로, +항상 에포크마다 동일한 샘플에 대해 평가하게 됩니다. -The argument `validation_split` (generating a holdout set from the training data) is not supported when training from `Dataset` objects, since this feature requires the ability to index the samples of the datasets, which is not possible in general with the `Dataset` API. +`Dataset` 객체로부터 트레이닝할 때는 +(트레이닝 데이터에서 홀드아웃 세트를 생성하는) `validation_split` 인수가 지원되지 않습니다. +이 기능은 데이터 세트의 샘플을 인덱싱할 수 있는 기능이 필요하지만, +일반적으로 `Dataset` API에서는 불가능합니다. -## Training & evaluation using `PyDataset` instances +## `PyDataset` 인스턴스를 사용한 트레이닝 및 평가 {#training-and-evaluation-using-pydataset-instances} -[`keras.utils.PyDataset`]({{< relref "/docs/api/utils/python_utils#pydataset-class" >}}) is a utility that you can subclass to obtain a Python generator with two important properties: +[`keras.utils.PyDataset`]({{< relref "/docs/api/utils/python_utils#pydataset-class" >}})는 두 가지 중요한 속성이 있는 Python generator를 얻기 위해 서브클래싱할 수 있는 유틸리티입니다. -- It works well with multiprocessing. -- It can be shuffled (e.g. when passing `shuffle=True` in `fit()`). +- 멀티프로세싱과 잘 작동합니다. +- 셔플링할 수 있습니다. (예: `fit()`에서 `shuffle=True`를 전달할 때) -A `PyDataset` must implement two methods: +`PyDataset`은 두 가지 메서드를 구현해야 합니다. - `__getitem__` - `__len__` -The method `__getitem__` should return a complete batch. If you want to modify your dataset between epochs, you may implement `on_epoch_end`. +`__getitem__` 메서드는 전체 배치를 반환해야 합니다. +에포크 사이에 데이터 세트를 수정하려면, `on_epoch_end`를 구현할 수 있습니다. -Here's a quick example: +간단한 예는 다음과 같습니다. ```python class ExamplePyDataset(keras.utils.PyDataset): @@ -684,7 +741,10 @@ train_py_dataset = ExamplePyDataset(x_train, y_train, batch_size=32) val_py_dataset = ExamplePyDataset(x_val, y_val, batch_size=32) ``` -To fit the model, pass the dataset instead as the `x` argument (no need for a `y` argument since the dataset includes the targets), and pass the validation dataset as the `validation_data` argument. And no need for the `batch_size` argument, since the dataset is already batched! +모델을 fit하려면, 대신 데이터 세트를 `x` 인수로 전달합니다. +(데이터 세트에 타겟이 포함되어 있으므로, `y` 인수는 필요 없음) +그리고, 검증 데이터 세트를 `validation_data` 인수로 전달합니다. +그리고 데이터 세트가 이미 배치되었으므로, `batch_size` 인수는 필요 없습니다! ```python model = get_compiled_model() @@ -701,7 +761,7 @@ model.fit(train_py_dataset, batch_size=64, validation_data=val_py_dataset, epoch {{% /details %}} -Evaluating the model is just as easy: +모델을 평가하는 것도 마찬가지로 쉽습니다. ```python model.evaluate(val_py_dataset) @@ -717,15 +777,22 @@ model.evaluate(val_py_dataset) {{% /details %}} -Importantly, `PyDataset` objects support three common constructor arguments that handle the parallel processing configuration: +중요한 점은, `PyDataset` 객체가 병렬 처리 구성을 처리하는 세 가지 일반적인 생성자 인수를 지원한다는 것입니다. -- `workers`: Number of workers to use in multithreading or multiprocessing. Typically, you'd set it to the number of cores on your CPU. -- `use_multiprocessing`: Whether to use Python multiprocessing for parallelism. Setting this to `True` means that your dataset will be replicated in multiple forked processes. This is necessary to gain compute-level (rather than I/O level) benefits from parallelism. However it can only be set to `True` if your dataset can be safely pickled. -- `max_queue_size`: Maximum number of batches to keep in the queue when iterating over the dataset in a multithreaded or multipricessed setting. You can reduce this value to reduce the CPU memory consumption of your dataset. It defaults to 10. +- `workers`: 멀티스레딩 또는 멀티프로세싱에서 사용할 워커 수입니다. 일반적으로, CPU의 코어 수로 설정합니다. +- `use_multiprocessing`: 병렬 처리를 위해 Python 멀티프로세싱을 사용할지 여부입니다. + 이를 `True`로 설정하면, 데이터 세트가 여러 개의 포크된 프로세스에서 복제됩니다. + 이는 병렬 처리에서 I/O 레벨이 아닌 컴퓨팅 레벨의 이점을 얻는 데 필요합니다. + 그러나, 데이터 세트를 안전하게 피클링(pickled)할 수 있는 경우에만, `True`로 설정할 수 있습니다. +- `max_queue_size`: 멀티스레드 또는 multipricessed 설정에서 데이터 세트에 걸쳐 반복할 때, + 대기열에 보관할 최대 배치 수입니다. + 이 값을 줄여, 데이터 세트의 CPU 메모리 사용량을 줄일 수 있습니다. 기본값은 10입니다. -By default, multiprocessing is disabled (`use_multiprocessing=False`) and only one thread is used. You should make sure to only turn on `use_multiprocessing` if your code is running inside a Python `if __name__ == "__main__":` block in order to avoid issues. +기본적으로, 멀티프로세싱은 비활성화되어 있으며(`use_multiprocessing=False`) 스레드가 하나만 사용됩니다. +문제가 발생하지 않도록, Python `if __name__ == "__main__":` 블록 내부에서 코드가 실행되는 경우에만, +`use_multiprocessing`을 켜야 합니다. -Here's a 4-thread, non-multiprocessed example: +다음은 4스레드, 멀티프로세스되지 않은 예입니다. ```python train_py_dataset = ExamplePyDataset(x_train, y_train, batch_size=32, workers=4) @@ -745,11 +812,15 @@ model.fit(train_py_dataset, batch_size=64, validation_data=val_py_dataset, epoch {{% /details %}} -## Training & evaluation using PyTorch `DataLoader` objects +## PyTorch `DataLoader` 객체를 사용한 트레이닝 및 평가 {#training-and-evaluation-using-pytorch-dataloader-objects} -All built-in training and evaluation APIs are also compatible with `torch.utils.data.Dataset` and `torch.utils.data.DataLoader` objects – regardless of whether you're using the PyTorch backend, or the JAX or TensorFlow backends. Let's take a look at a simple example. +모든 빌트인 트레이닝 및 평가 API는 +`torch.utils.data.Dataset` 및 `torch.utils.data.DataLoader` 객체와도 호환됩니다. +PyTorch 백엔드나 JAX 또는 TensorFlow 백엔드를 사용하든 상관없습니다. 간단한 예를 살펴보겠습니다. -Unlike `PyDataset` which are batch-centric, PyTorch `Dataset` objects are sample-centric: the `__len__` method returns the number of samples, and the `__getitem__` method returns a specific sample. +배치 중심(batch-centric)인 `PyDataset`과 달리, +PyTorch `Dataset` 객체는 샘플 중심(sample-centric)입니다. +`__len__` 메서드는 샘플 수를 반환하고, `__getitem__` 메서드는 특정 샘플을 반환합니다. ```python class ExampleTorchDataset(torch.utils.data.Dataset): @@ -768,7 +839,7 @@ train_torch_dataset = ExampleTorchDataset(x_train, y_train) val_torch_dataset = ExampleTorchDataset(x_val, y_val) ``` -To use a PyTorch Dataset, you need to wrap it into a `Dataloader` which takes care of batching and shuffling: +PyTorch Dataset을 사용하려면, 배치 및 셔플링을 처리하는 `Dataloader`로 래핑해야 합니다. ```python train_dataloader = torch.utils.data.DataLoader( @@ -779,7 +850,7 @@ val_dataloader = torch.utils.data.DataLoader( ) ``` -Now you can use them in the Keras API just like any other iterator: +이제 다른 iterator와 마찬가지로, Keras API에서 이를 사용할 수 있습니다. ```python model = get_compiled_model() @@ -798,22 +869,27 @@ model.evaluate(val_dataloader) {{% /details %}} -## Using sample weighting and class weighting +## 샘플 가중치와 클래스 가중치 사용 {#using-sample-weighting-and-class-weighting} -With the default settings the weight of a sample is decided by its frequency in the dataset. There are two methods to weight the data, independent of sample frequency: +기본 설정으로, 샘플의 가중치는 데이터 세트에서의 빈도에 따라 결정됩니다. +샘플 빈도와 독립적으로, 데이터에 가중치를 부여하는 방법은 두 가지가 있습니다. -- Class weights -- Sample weights +- 클래스 가중치 +- 샘플 가중치 -### Class weights +### 클래스 가중치 {#class-weights} -This is set by passing a dictionary to the `class_weight` argument to `Model.fit()`. This dictionary maps class indices to the weight that should be used for samples belonging to this class. +이것은 `Model.fit()`에 `class_weight` 인수에 딕셔너리를 전달하여 설정합니다. +이 딕셔너리는 클래스 인덱스를 이 클래스에 속하는 샘플에 사용해야 하는 가중치에 매핑합니다. -This can be used to balance classes without resampling, or to train a model that gives more importance to a particular class. +이것은 리샘플링 없이 클래스를 균형 있게 조정하거나, +특정 클래스에 더 많은 중요성을 부여하는 모델을 트레이닝하는 데 사용할 수 있습니다. -For instance, if class "0" is half as represented as class "1" in your data, you could use `Model.fit(..., class_weight={0: 1., 1: 0.5})`. +예를 들어, 데이터에서 클래스 "0"이 클래스 "1"의 절반으로 표현된 경우, +`Model.fit(..., class_weight={0: 1., 1: 0.5})`를 사용할 수 있습니다. -Here's a NumPy example where we use class weights or sample weights to give more importance to the correct classification of class #5 (which is the digit "5" in the MNIST dataset). +다음은 클래스 가중치 또는 샘플 가중치를 사용하여, +클래스 #5(MNIST 데이터 세트의 숫자 "5")의 올바른 분류에 더 많은 중요성을 부여하는 NumPy 예제입니다. ```python class_weight = { @@ -822,8 +898,8 @@ class_weight = { 2: 1.0, 3: 1.0, 4: 1.0, - # Set weight "2" for class "5", - # making this class 2x more important + # 클래스 "5"에 대해 가중치 "2"를 설정하여, + # 이 클래스를 2배 더 중요하게 만듭니다. 5: 2.0, 6: 1.0, 7: 1.0, @@ -847,16 +923,19 @@ Fit with class weight {{% /details %}} -### Sample weights +### 샘플 가중치 {#sample-weights} -For fine grained control, or if you are not building a classifier, you can use "sample weights". +세밀한 제어를 위해, 또는 분류기를 빌드하지 않는 경우, "샘플 가중치"를 사용할 수 있습니다. -- When training from NumPy data: Pass the `sample_weight` argument to `Model.fit()`. -- When training from [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) or any other sort of iterator: Yield `(input_batch, label_batch, sample_weight_batch)` tuples. +- NumPy 데이터에서 트레이닝하는 경우: `Model.fit()`에 `sample_weight` 인수를 전달합니다. +- [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data) 또는 다른 종류의 iterator에서 트레이닝하는 경우: `(input_batch, label_batch, sample_weight_batch)` 튜플을 생성(Yield)합니다. -A "sample weights" array is an array of numbers that specify how much weight each sample in a batch should have in computing the total loss. It is commonly used in imbalanced classification problems (the idea being to give more weight to rarely-seen classes). +"샘플 가중치" 배열은, 배치의 각 샘플이 총 손실을 계산할 때, 가져야 하는 가중치를 지정하는 숫자 배열입니다. +불균형 분류 문제에서 일반적으로 사용됩니다. (드물게 보이는 클래스에 더 많은 가중치를 부여하는 것이 목표) -When the weights used are ones and zeros, the array can be used as a _mask_ for the loss function (entirely discarding the contribution of certain samples to the total loss). +사용된 가중치가 1과 0인 경우, +배열을 손실 함수의 _마스크_ 로 사용할 수 있습니다. +(전체 손실에 대한 특정 샘플의 기여도를 완전히 무시) ```python sample_weight = np.ones(shape=(len(y_train),)) @@ -878,17 +957,17 @@ Fit with sample weight {{% /details %}} -Here's a matching `Dataset` example: +다음은 일치하는 `Dataset` 예입니다. ```python sample_weight = np.ones(shape=(len(y_train),)) sample_weight[y_train == 5] = 2.0 -# Create a Dataset that includes sample weights -# (3rd element in the return tuple). +# 샘플 가중치를 포함하는 Dataset를 만듭니다. +# (반환 튜플의 3번째 요소). train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight)) -# Shuffle and slice the dataset. +# 데이터 세트를 셔플하고, 슬라이스 합니다. train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64) model = get_compiled_model() @@ -905,11 +984,17 @@ model.fit(train_dataset, epochs=1) {{% /details %}} -## Passing data to multi-input, multi-output models +## 다중 입력, 다중 출력 모델에 데이터 전달 {#passing-data-to-multi-input-multi-output-models} -In the previous examples, we were considering a model with a single input (a tensor of shape `(764,)`) and a single output (a prediction tensor of shape `(10,)`). But what about models that have multiple inputs or outputs? +이전 예에서, 우리는 단일 입력(`(764,)` 모양의 텐서)과 +단일 출력(`(10,)` 모양의 예측 텐서)을 갖는 모델을 고려했습니다. +하지만 여러 입력 또는 출력이 있는 모델은 어떨까요? -Consider the following model, which has an image input of shape `(32, 32, 3)` (that's `(height, width, channels)`) and a time series input of shape `(None, 10)` (that's `(timesteps, features)`). Our model will have two outputs computed from the combination of these inputs: a "score" (of shape `(1,)`) and a probability distribution over five classes (of shape `(5,)`). +다음 모델을 고려해 보겠습니다. +여기에는 `(32, 32, 3)` 모양의 이미지 입력(`(height, width, channels)`)과 +`(None, 10)` 모양의 시계열 입력(`(timesteps, features)`)이 있습니다. +이 모델은 이러한 입력의 조합에서 계산된 두 가지 출력을 갖습니다. +즉, "점수"(`(1,)` 모양)와 5개 클래스에 대한 확률 분포(`(5,)` 모양)입니다. ```python image_input = keras.Input(shape=(32, 32, 3), name="img_input") @@ -931,7 +1016,9 @@ model = keras.Model( ) ``` -Let's plot this model, so you can clearly see what we're doing here (note that the shapes shown in the plot are batch shapes, rather than per-sample shapes). +이 모델을 플롯해보면, +여기서 무엇을 하고 있는지 명확하게 볼 수 있을 것입니다. +(플롯에 표시된 모양은 샘플별 모양이 아니라 배치 모양입니다) ```python keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True) @@ -939,7 +1026,8 @@ keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=Tr ![png](/images/guides/training_with_built_in_methods/training_with_built_in_methods_73_0.png) -At compilation time, we can specify different losses to different outputs, by passing the loss functions as a list: +컴파일 시에, 손실 함수를 목록으로 전달하여, +다양한 출력에 대해 다양한 손실을 지정할 수 있습니다. ```python model.compile( @@ -951,9 +1039,9 @@ model.compile( ) ``` -If we only passed a single loss function to the model, the same loss function would be applied to every output (which is not appropriate here). +모델에 단일 손실 함수만 전달하면, 모든 출력에 동일한 손실 함수가 적용됩니다. (여기서는 적합하지 않음) -Likewise for metrics: +메트릭의 경우도 마찬가지입니다. ```python model.compile( @@ -972,7 +1060,7 @@ model.compile( ) ``` -Since we gave names to our output layers, we could also specify per-output losses and metrics via a dict: +출력 레이어에 이름을 지정했으므로, dict를 통해 출력당 손실과 메트릭을 지정할 수도 있습니다. ```python model.compile( @@ -991,9 +1079,10 @@ model.compile( ) ``` -We recommend the use of explicit names and dicts if you have more than 2 outputs. +출력이 2개 이상인 경우, 명시적 이름과 dict을 사용하는 것이 좋습니다. -It's possible to give different weights to different output-specific losses (for instance, one might wish to privilege the "score" loss in our example, by giving to 2x the importance of the class loss), using the `loss_weights` argument: +`loss_weights` 인수를 사용하여, 다양한 출력별 손실에 다른 가중치를 부여할 수 있습니다. +(예: 클래스 손실보다 중요도를 2배로 부여하여, 예시에서 "score" 손실에 특권을 부여할 수 있음) ```python model.compile( @@ -1013,23 +1102,27 @@ model.compile( ) ``` -You could also choose not to compute a loss for certain outputs, if these outputs are meant for prediction but not for training: +예측을 위한 출력이지만 트레이닝을 위한 출력이 아닌 경우, +특정 출력에 대한 손실을 계산하지 않도록 선택할 수도 있습니다. ```python -# List loss version +# 리스트 손실 버전 model.compile( optimizer=keras.optimizers.RMSprop(1e-3), loss=[None, keras.losses.CategoricalCrossentropy()], ) -# Or dict loss version +# 또는 dict 손실 버전 model.compile( optimizer=keras.optimizers.RMSprop(1e-3), loss={"class_output": keras.losses.CategoricalCrossentropy()}, ) ``` -Passing data to a multi-input or multi-output model in `fit()` works in a similar way as specifying a loss function in compile: you can pass **lists of NumPy arrays** (with 1:1 mapping to the outputs that received a loss function) or **dicts mapping output names to NumPy arrays**. +`fit()`에서 다중 입력 또는 다중 출력 모델에 데이터를 전달하는 것은, +compile에서 손실 함수를 지정하는 것과 비슷한 방식으로 작동합니다. +**NumPy 배열의 목록**(손실 함수를 받은 출력과 1:1로 매핑)을 전달하거나, +**출력 이름을 NumPy 배열에 매핑하는 dict**를 전달할 수 있습니다. ```python model.compile( @@ -1040,16 +1133,16 @@ model.compile( ], ) -# Generate dummy NumPy data +# 더미 NumPy 데이터 생성 img_data = np.random.random_sample(size=(100, 32, 32, 3)) ts_data = np.random.random_sample(size=(100, 20, 10)) score_targets = np.random.random_sample(size=(100, 1)) class_targets = np.random.random_sample(size=(100, 5)) -# Fit on lists +# 리스트에 대해 fit model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1) -# Alternatively, fit on dicts +# 또는, dict에 대해 fit model.fit( {"img_input": img_data, "ts_input": ts_data}, {"score_output": score_targets, "class_output": class_targets}, @@ -1069,7 +1162,8 @@ model.fit( {{% /details %}} -Here's the `Dataset` use case: similarly as what we did for NumPy arrays, the `Dataset` should return a tuple of dicts. +`Dataset`의 사용 사례는 다음과 같습니다. +NumPy 배열에서 한 것과 비슷하게, `Dataset`은 dict 튜플을 반환해야 합니다. ```python train_dataset = tf.data.Dataset.from_tensor_slices( @@ -1093,29 +1187,30 @@ model.fit(train_dataset, epochs=1) {{% /details %}} -## Using callbacks +## 콜백 사용 {#using-callbacks} -Callbacks in Keras are objects that are called at different points during training (at the start of an epoch, at the end of a batch, at the end of an epoch, etc.). They can be used to implement certain behaviors, such as: +Keras의 콜백은 트레이닝 중 여러 지점(에포크 시작 시, 배치 종료 시, 에포크 종료 시 등)에서 호출되는 객체입니다. +다음과 같은 특정 동작을 구현하는 데 사용할 수 있습니다. -- Doing validation at different points during training (beyond the built-in per-epoch validation) -- Checkpointing the model at regular intervals or when it exceeds a certain accuracy threshold -- Changing the learning rate of the model when training seems to be plateauing -- Doing fine-tuning of the top layers when training seems to be plateauing -- Sending email or instant message notifications when training ends or where a certain performance threshold is exceeded -- Etc. +- 트레이닝 중 여러 지점에서 검증 수행 (빌트인 에포크 당 검증 외) +- 정기적으로 또는 특정 정확도 임계값을 초과할 때 모델에 체크포인트 지정 +- 트레이닝이 정체(plateauing)되는 듯할 때, 모델의 학습률 변경 +- 트레이닝이 정체되는 듯할 때, 최상위 레이어 미세 조정 +- 트레이닝이 종료되거나 특정 성능 임계값을 초과할 때, 이메일 또는 인스턴트 메시지 알림 전송 +- 기타 -Callbacks can be passed as a list to your call to `fit()`: +콜백은 `fit()` 호출에 목록으로 전달할 수 있습니다. ```python model = get_compiled_model() callbacks = [ keras.callbacks.EarlyStopping( - # Stop training when `val_loss` is no longer improving + # `val_loss`가 더 이상 개선되지 않을 때 트레이닝 중단 monitor="val_loss", - # "no longer improving" being defined as "no better than 1e-2 less" + # "개선되지 않음"은 "1e-2 이상 개선되지 않음"을 의미 min_delta=1e-2, - # "no longer improving" being further defined as "for at least 2 epochs" + # "개선되지 않음"은 "최소 2 에포크 동안 유지"될 때로 정의 patience=2, verbose=1, ) @@ -1154,25 +1249,26 @@ Epoch 7: early stopping {{% /details %}} -### Many built-in callbacks are available +### 다양한 빌트인 콜백을 사용할 수 있습니다. {#many-built-in-callbacks-are-available} -There are many built-in callbacks already available in Keras, such as: +Keras에는 이미 다음과 같은 많은 빌트인 콜백이 있습니다. -- `ModelCheckpoint`: Periodically save the model. -- `EarlyStopping`: Stop training when training is no longer improving the validation metrics. -- `TensorBoard`: periodically write model logs that can be visualized in [TensorBoard](https://www.tensorflow.org/tensorboard) (more details in the section "Visualization"). -- `CSVLogger`: streams loss and metrics data to a CSV file. -- etc. +- `ModelCheckpoint`: 주기적으로 모델을 저장합니다. +- `EarlyStopping`: 트레이닝이 더 이상 검증 메트릭을 개선하지 못할 때, 트레이닝을 중지합니다. +- `TensorBoard`: 주기적으로 [TensorBoard](https://www.tensorflow.org/tensorboard)에서 시각화할 수 있는 모델 로그를 작성합니다. (자세한 내용은 "시각화" 섹션 참조) +- `CSVLogger`: 손실 및 메트릭 데이터를 CSV 파일로 스트리밍합니다. +- 기타 -See the [callbacks documentation]({{< relref "/docs/api/callbacks" >}}) for the complete list. +전체 목록은 [콜백 문서]({{< relref "/docs/api/callbacks" >}})를 참조하세요. -### Writing your own callback +### 자신만의 콜백 작성하기 {#writing-your-own-callback} -You can create a custom callback by extending the base class [`keras.callbacks.Callback`]({{< relref "/docs/api/callbacks/base_callback#callback-class" >}}). A callback has access to its associated model through the class property `self.model`. +베이스 클래스 [`keras.callbacks.Callback`]({{< relref "/docs/api/callbacks/base_callback#callback-class" >}})를 확장하여, 커스텀 콜백을 만들 수 있습니다. +콜백은 클래스 속성 `self.model`을 통해, 연관된 모델에 액세스할 수 있습니다. -Make sure to read the [complete guide to writing custom callbacks]({{< relref "/docs/guides/writing_your_own_callbacks" >}}). +[커스텀 콜백 작성에 대한 전체 가이드]({{< relref "/docs/guides/writing_your_own_callbacks" >}})를 읽어보세요. -Here's a simple example saving a list of per-batch loss values during training: +다음은 트레이닝 중, 배치별 손실 값 목록을 저장하는 간단한 예입니다. ```python class LossHistory(keras.callbacks.Callback): @@ -1183,24 +1279,24 @@ class LossHistory(keras.callbacks.Callback): self.per_batch_losses.append(logs.get("loss")) ``` -## Checkpointing models +## 모델 체크포인팅 {#checkpointing-models} -When you're training model on relatively large datasets, it's crucial to save checkpoints of your model at frequent intervals. +비교적 큰 데이터 세트에 대해 모델을 트레이닝할 때는, +모델의 체크포인트를 빈번한 간격으로 저장하는 것이 중요합니다. -The easiest way to achieve this is with the `ModelCheckpoint` callback: +이를 달성하는 가장 쉬운 방법은 `ModelCheckpoint` 콜백을 사용하는 것입니다. ```python model = get_compiled_model() callbacks = [ keras.callbacks.ModelCheckpoint( - # Path where to save the model - # The two parameters below mean that we will overwrite - # the current checkpoint if and only if - # the `val_loss` score has improved. - # The saved model name will include the current epoch. + # 모델을 저장할 경로 + # 아래 두 매개변수는 `val_loss` 점수가 개선된 경우에만, + # 현재 체크포인트를 덮어쓴다는 것을 의미합니다. + # 저장된 모델 이름에는 현재 에포크가 포함됩니다. filepath="mymodel_{epoch}.keras", - save_best_only=True, # Only save a model if `val_loss` has improved. + save_best_only=True, # `val_loss`가 개선된 경우에만 모델을 저장합니다. monitor="val_loss", verbose=1, ) @@ -1232,18 +1328,21 @@ Epoch 2: val_loss improved from 0.22393 to 0.16868, saving model to mymodel_2.ke {{% /details %}} -The `ModelCheckpoint` callback can be used to implement fault-tolerance: the ability to restart training from the last saved state of the model in case training gets randomly interrupted. Here's a basic example: +`ModelCheckpoint` 콜백은 결함 허용성(fault-tolerance)을 구현하는 데 사용할 수 있습니다. +즉, 트레이닝이 무작위로 중단되는 경우, +모델의 마지막 저장된 상태에서 트레이닝을 다시 시작하는 기능입니다. +다음은 기본적인 예입니다. ```python -# Prepare a directory to store all the checkpoints. +# 모든 체크포인트를 저장할 디렉토리를 준비합니다. checkpoint_dir = "./ckpt" if not os.path.exists(checkpoint_dir): os.makedirs(checkpoint_dir) def make_or_restore_model(): - # Either restore the latest model, or create a fresh one - # if there is no checkpoint available. + # 최신 모델을 복원하거나, + # 체크포인트를 사용할 수 없는 경우 새 모델을 만듭니다. checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)] if checkpoints: latest_checkpoint = max(checkpoints, key=os.path.getctime) @@ -1255,8 +1354,8 @@ def make_or_restore_model(): model = make_or_restore_model() callbacks = [ - # This callback saves the model every 100 batches. - # We include the training loss in the saved model name. + # 이 콜백은 매 100 배치마다 모델을 저장합니다. + # 저장된 모델 이름에 트레이닝 손실을 포함합니다. keras.callbacks.ModelCheckpoint( filepath=checkpoint_dir + "/model-loss={loss:.2f}.keras", save_freq=100 ) @@ -1275,19 +1374,23 @@ Creating a new model {{% /details %}} -You call also write your own callback for saving and restoring models. +모델을 저장하고 복원하기 위한 콜백을 직접 작성합니다. -For a complete guide on serialization and saving, see the [guide to saving and serializing Models]({{< relref "/docs/guides/serialization_and_saving" >}}). +직렬화 및 저장에 대한 전체 가이드는 +[모델 저장 및 직렬화 가이드]({{< relref "/docs/guides/serialization_and_saving" >}})를 참조하세요. -## Using learning rate schedules +## 학습률 스케쥴 사용 {#using-learning-rate-schedules} -A common pattern when training deep learning models is to gradually reduce the learning as training progresses. This is generally known as "learning rate decay". +딥러닝 모델을 트레이닝할 때, 일반적인 패턴은 트레이닝이 진행됨에 따라 학습을 점진적으로 줄이는 것입니다. +이를 일반적으로 "학습률 감쇠(learning rate decay)"라고 합니다. -The learning decay schedule could be static (fixed in advance, as a function of the current epoch or the current batch index), or dynamic (responding to the current behavior of the model, in particular the validation loss). +학습 감쇠 스케쥴은 정적(현재 에포크 또는 현재 배치 인덱스의 함수로 미리 고정)이거나, +동적(특히 검증 손실과 같은 모델의 현재 동작에 대응)일 수 있습니다. -### Passing a schedule to an optimizer +### 스케줄을 옵티마이저에 전달 {#passing-a-schedule-to-an-optimizer} -You can easily use a static learning rate decay schedule by passing a schedule object as the `learning_rate` argument in your optimizer: +옵티마이저에서 `learning_rate` 인수로 스케쥴 객체를 전달하여, +정적 학습률 감쇠 스케쥴을 쉽게 사용할 수 있습니다. ```python initial_learning_rate = 0.1 @@ -1298,41 +1401,47 @@ lr_schedule = keras.optimizers.schedules.ExponentialDecay( optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule) ``` -Several built-in schedules are available: `ExponentialDecay`, `PiecewiseConstantDecay`, `PolynomialDecay`, and `InverseTimeDecay`. +여러 가지 빌트인 스케줄을 사용할 수 있습니다: +`ExponentialDecay`, `PiecewiseConstantDecay`, `PolynomialDecay`, `InverseTimeDecay`. -### Using callbacks to implement a dynamic learning rate schedule +### 콜백을 사용하여 동적 학습률 스케쥴 구현 {#using-callbacks-to-implement-a-dynamic-learning-rate-schedule} -A dynamic learning rate schedule (for instance, decreasing the learning rate when the validation loss is no longer improving) cannot be achieved with these schedule objects, since the optimizer does not have access to validation metrics. +이러한 스케줄 객체로는 동적 학습률 스케줄(예: 검증 손실이 더 이상 개선되지 않을 때, 학습률 감소)을 달성할 수 없습니다. +옵티마이저가 검증 메트릭에 액세스할 수 없기 때문입니다. -However, callbacks do have access to all metrics, including validation metrics! You can thus achieve this pattern by using a callback that modifies the current learning rate on the optimizer. In fact, this is even built-in as the `ReduceLROnPlateau` callback. +그러나, 콜백은 검증 메트릭을 포함한 모든 메트릭에 액세스할 수 있습니다! +따라서, 옵티마이저에서 현재 학습률을 수정하는 콜백을 사용하여, 이 패턴을 달성할 수 있습니다. +사실, 이것은 `ReduceLROnPlateau` 콜백으로 빌트인되어 있습니다. -## Visualizing loss and metrics during training with TensorBoard +## TensorBoard로 트레이닝하는 동안 손실 및 메트릭 시각화 {#visualizing-loss-and-metrics-during-training-with-tensorboard} -The best way to keep an eye on your model during training is to use [TensorBoard](https://www.tensorflow.org/tensorboard) – a browser-based application that you can run locally that provides you with: +트레이닝하는 동안 모델을 주시하는 가장 좋은 방법은 +[TensorBoard](https://www.tensorflow.org/tensorboard)를 사용하는 것입니다. +로컬에서 실행할 수 있는 브라우저 기반 애플리케이션으로 다음을 제공합니다. -- Live plots of the loss and metrics for training and evaluation -- (optionally) Visualizations of the histograms of your layer activations -- (optionally) 3D visualizations of the embedding spaces learned by your `Embedding` layers +- 트레이닝 및 평가에 대한 손실 및 메트릭의 라이브 플롯 +- (선택 사항) 레이어 활성화의 히스토그램 시각화 +- (선택 사항) `Embedding` 레이어에서 학습한 임베딩 공간의 3D 시각화 -If you have installed TensorFlow with pip, you should be able to launch TensorBoard from the command line: +pip로 TensorFlow를 설치한 경우, 명령줄에서 TensorBoard를 시작할 수 있어야 합니다. ```console $ tensorboard --logdir=/full_path_to_your_logs ``` -### Using the TensorBoard callback +### TensorBoard 콜백 사용 {#using-the-tensorboard-callback} -The easiest way to use TensorBoard with a Keras model and the `fit()` method is the `TensorBoard` callback. +Keras 모델과 `fit()` 메서드로 TensorBoard를 사용하는 가장 쉬운 방법은 `TensorBoard` 콜백입니다. -In the simplest case, just specify where you want the callback to write logs, and you're good to go: +가장 간단한 케이스로, 콜백이 로그를 쓸 위치를 지정하기만 하면 됩니다. ```python keras.callbacks.TensorBoard( log_dir="/full_path_to_your_logs", - histogram_freq=0, # How often to log histogram visualizations - embeddings_freq=0, # How often to log embedding visualizations + histogram_freq=0, # 히스토그램 시각화를 기록하는 빈도 + embeddings_freq=0, # 임베딩 시각화를 기록하는 빈도 update_freq="epoch", -) # How often to write logs (default: once per epoch) +) # 로그를 작성하는 빈도(기본값: 에포크당 한 번) ``` {{% details title="{{< t f_result >}}" closed="true" %}} @@ -1343,4 +1452,4 @@ keras.callbacks.TensorBoard( {{% /details %}} -For more information, see the [documentation for the `TensorBoard` callback]({{< relref "/docs/api/callbacks/tensorboard" >}}). +자세한 내용은 [`TensorBoard` 콜백에 대한 문서]({{< relref "/docs/api/callbacks/tensorboard" >}})를 참조하세요. diff --git a/content/korean/docs/guides/transfer_learning/_index.md b/content/korean/docs/guides/transfer_learning/_index.md index dbe07af2..b6c7334d 100644 --- a/content/korean/docs/guides/transfer_learning/_index.md +++ b/content/korean/docs/guides/transfer_learning/_index.md @@ -1,6 +1,6 @@ --- -title: Transfer learning & fine-tuning -linkTitle: Transfer learning & fine-tuning +title: 전이 학습 및 미세 조정 +linkTitle: 전이 학습 및 미세 조정 toc: true weight: 14 type: docs @@ -11,14 +11,14 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2020/04/15 **{{< t f_last_modified >}}** 2023/06/25 -**{{< t f_description >}}** Complete guide to transfer learning & fine-tuning in Keras. +**{{< t f_description >}}** Keras의 전이 학습 및 미세 조정에 대한 완벽 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/transfer_learning.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/transfer_learning.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Setup +## 셋업 {#setup} ```python import numpy as np @@ -28,40 +28,50 @@ import tensorflow_datasets as tfds import matplotlib.pyplot as plt ``` -## Introduction +## 소개 {#introduction} -**Transfer learning** consists of taking features learned on one problem, and leveraging them on a new, similar problem. For instance, features from a model that has learned to identify racoons may be useful to kick-start a model meant to identify tanukis. +**전이 학습(Transfer learning)** 은 한 문제에서 학습된 특성을 새로운, 유사한 문제에 활용하는 것을 말합니다. +예를 들어, 라쿤을 식별하는 모델에서 학습된 특성은 너구리(tanuki)를 식별하려는 모델을 시작하는 데 유용할 수 있습니다. -Transfer learning is usually done for tasks where your dataset has too little data to train a full-scale model from scratch. +전이 학습은 보통 데이터셋이 부족하여, 처음부터 완전한 모델을 트레이닝하기 어려운 작업에 사용됩니다. -The most common incarnation of transfer learning in the context of deep learning is the following workflow: +딥러닝에서 전이 학습의 가장 일반적인 형태는 다음과 같은 워크플로입니다: -1. Take layers from a previously trained model. -2. Freeze them, so as to avoid destroying any of the information they contain during future training rounds. -3. Add some new, trainable layers on top of the frozen layers. They will learn to turn the old features into predictions on a new dataset. -4. Train the new layers on your dataset. +1. 이전에 트레이닝된 모델의 레이어를 가져옵니다. +2. 그 레이어들을 동결(freeze)하여, 이후 트레이닝 라운드에서 해당 정보가 파괴되지 않도록 합니다. +3. 동결된 레이어 위에 새로운 트레이닝 가능한 레이어를 추가합니다. + 이 레이어들은 기존의 특징을 새로운 데이터셋에 대한 예측으로 변환하는 것을 학습합니다. +4. 새로운 레이어들을 데이터셋에 맞게 트레이닝합니다. -A last, optional step, is **fine-tuning**, which consists of unfreezing the entire model you obtained above (or part of it), and re-training it on the new data with a very low learning rate. This can potentially achieve meaningful improvements, by incrementally adapting the pretrained features to the new data. +마지막으로 선택적으로 할 수 있는 단계는 **미세 조정(fine-tuning)** 입니다. +이는 위에서 얻은 전체 모델(또는 그 일부)을 동결 해제(unfreeze)하고, +매우 낮은 학습률로 새로운 데이터에 대해 다시 트레이닝하는 것을 말합니다. +이렇게 하면 사전 트레이닝된 특징을 새로운 데이터에 맞게 점진적으로 적응시켜 유의미한 개선을 이룰 수 있습니다. -First, we will go over the Keras `trainable` API in detail, which underlies most transfer learning & fine-tuning workflows. +먼저, 대부분의 전이 학습 및 미세 조정 워크플로를 기반으로 하는 +Keras의 `trainable` API를 자세히 살펴보겠습니다. -Then, we'll demonstrate the typical workflow by taking a model pretrained on the ImageNet dataset, and retraining it on the Kaggle "cats vs dogs" classification dataset. +그런 다음, ImageNet 데이터셋에서 사전 트레이닝된 모델을 가져와, +Kaggle의 "cats vs dogs" 분류 데이터셋에서 다시 트레이닝하는 일반적인 워크플로를 시연하겠습니다. -This is adapted from [Deep Learning with Python](https://www.manning.com/books/deep-learning-with-python) and the 2016 blog post ["building powerful image classification models using very little data"](https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html). +이 내용은 [Deep Learning with Python](https://www.manning.com/books/deep-learning-with-python) 및 +2016년 블로그 게시물 ["아주 적은 데이터로 강력한 이미지 분류 모델 만들기"](https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html)에서 각색되었습니다. -## Freezing layers: understanding the `trainable` attribute +## 레이어 동결: `trainable` 속성 이해하기 {#freezing-layers-understanding-the-trainable-attribute} -Layers & models have three weight attributes: +레이어 및 모델에는 세 가지 가중치 속성이 있습니다: -- `weights` is the list of all weights variables of the layer. -- `trainable_weights` is the list of those that are meant to be updated (via gradient descent) to minimize the loss during training. -- `non_trainable_weights` is the list of those that aren't meant to be trained. Typically they are updated by the model during the forward pass. +- `weights`는 레이어의 모든 가중치 변수를 포함한 리스트입니다. +- `trainable_weights`는 트레이닝 중 손실을 최소화하기 위해, + (경사 하강법을 통해) 업데이트될 가중치들의 리스트입니다. +- `non_trainable_weights`는 트레이닝되지 않도록 설정된 가중치들의 리스트입니다. + 일반적으로 이는 모델이 순방향 패스(forward pass)를 수행할 때 업데이트됩니다. -**Example: the `Dense` layer has 2 trainable weights (kernel & bias)** +**예시: `Dense` 레이어는 2개의 트레이닝 가능한 가중치(kernel 및 bias)를 가집니다.** ```python layer = keras.layers.Dense(3) -layer.build((None, 4)) # Create the weights +layer.build((None, 4)) # 가중치 생성 print("weights:", len(layer.weights)) print("trainable_weights:", len(layer.trainable_weights)) @@ -78,15 +88,17 @@ non_trainable_weights: 0 {{% /details %}} -## Available guides +일반적으로, 모든 가중치는 트레이닝 가능한 가중치입니다. +유일하게 빌트인 레이어 중 트레이닝 불가능한 가중치를 가진 레이어는 `BatchNormalization` 레이어입니다. +이 레이어는 트레이닝 중 입력의 평균과 분산을 추적하기 위해, 트레이닝 불가능한 가중치를 사용합니다. +커스텀 레이어에서 트레이닝 불가능한 가중치를 사용하는 방법을 배우려면, +{{< titledRelref "/docs/guides/making_new_layers_and_models_via_subclassing" >}} 가이드를 참고하세요. -In general, all weights are trainable weights. The only built-in layer that has non-trainable weights is the `BatchNormalization` layer. It uses non-trainable weights to keep track of the mean and variance of its inputs during training. To learn how to use non-trainable weights in your own custom layers, see the [guide to writing new layers from scratch]({{< relref "/docs/guides/making_new_layers_and_models_via_subclassing" >}}). - -**Example: the `BatchNormalization` layer has 2 trainable weights and 2 non-trainable weights** +**예시: `BatchNormalization` 레이어는 2개의 트레이닝 가능한 가중치와 2개의 트레이닝 불가능한 가중치를 가집니다.** ```python layer = keras.layers.BatchNormalization() -layer.build((None, 4)) # Create the weights +layer.build((None, 4)) # 가중치 생성 print("weights:", len(layer.weights)) print("trainable_weights:", len(layer.trainable_weights)) @@ -103,14 +115,19 @@ non_trainable_weights: 2 {{% /details %}} -Layers & models also feature a boolean attribute `trainable`. Its value can be changed. Setting `layer.trainable` to `False` moves all the layer's weights from trainable to non-trainable. This is called "freezing" the layer: the state of a frozen layer won't be updated during training (either when training with `fit()` or when training with any custom loop that relies on `trainable_weights` to apply gradient updates). +레이어와 모델에는 `trainable`이라는 boolean 속성이 있습니다. 이 값은 변경할 수 있습니다. +`layer.trainable`을 `False`로 설정하면, +해당 레이어의 모든 가중치가 트레이닝 가능한 상태에서 트레이닝 불가능한 상태로 이동합니다. +이를 "레이어 동결(freezing)"이라고 하며, 동결된 레이어의 상태는 트레이닝 중에 업데이트되지 않습니다. +(`fit()`을 사용한 트레이닝이든, +`trainable_weights`에 의존하여 그래디언트 업데이트를 적용하는 커스텀 루프에서든 마찬가지입니다) -**Example: setting `trainable` to `False`** +**예시: `trainable`을 `False`로 설정** ```python layer = keras.layers.Dense(3) -layer.build((None, 4)) # Create the weights -layer.trainable = False # Freeze the layer +layer.build((None, 4)) # 가중치 생성 +layer.trainable = False # 레이어 동결 print("weights:", len(layer.weights)) print("trainable_weights:", len(layer.trainable_weights)) @@ -127,25 +144,26 @@ non_trainable_weights: 2 {{% /details %}} -When a trainable weight becomes non-trainable, its value is no longer updated during training. +트레이닝 가능한 가중치가 트레이닝 불가능한 가중치로 바뀌면, +해당 가중치의 값은 더 이상 트레이닝 중에 업데이트되지 않습니다. ```python -# Make a model with 2 layers +# 두 개의 레이어로 모델을 만듭니다. layer1 = keras.layers.Dense(3, activation="relu") layer2 = keras.layers.Dense(3, activation="sigmoid") model = keras.Sequential([keras.Input(shape=(3,)), layer1, layer2]) -# Freeze the first layer +# 첫 번째 레이어를 동결합니다. layer1.trainable = False -# Keep a copy of the weights of layer1 for later reference +# 나중에 참조할 수 있도록 `layer1`의 가중치를 복사해둡니다. initial_layer1_weights_values = layer1.get_weights() -# Train the model +# 모델을 트레이닝합니다. model.compile(optimizer="adam", loss="mse") model.fit(np.random.random((2, 3)), np.random.random((2, 3))) -# Check that the weights of layer1 have not changed during training +# 트레이닝 중에 `layer1`의 가중치가 변경되지 않았는지 확인합니다. final_layer1_weights_values = layer1.get_weights() np.testing.assert_allclose( initial_layer1_weights_values[0], final_layer1_weights_values[0] @@ -163,13 +181,16 @@ np.testing.assert_allclose( {{% /details %}} -Do not confuse the `layer.trainable` attribute with the argument `training` in `layer.__call__()` (which controls whether the layer should run its forward pass in inference mode or training mode). For more information, see the [Keras FAQ]({{< relref "/docs/getting_started/faq/#whats-the-difference-between-the-training-argument-in-call-and-the-trainable-attribute" >}}). +`layer.trainable` 속성과 `layer.__call__()`의 인자 `training`을 혼동하지 마세요. +(`training` 인자는 레이어가 추론 모드 또는 트레이닝 모드에서 순방향 패스를 실행할지 여부를 제어합니다.) +자세한 내용은 [Keras FAQ]({{< relref "/docs/getting_started/faq/#whats-the-difference-between-the-training-argument-in-call-and-the-trainable-attribute" >}})를 참고하세요. -## Recursive setting of the `trainable` attribute +## `trainable` 속성의 재귀적 설정 {#recursive-setting-of-the-trainable-attribute} -If you set `trainable = False` on a model or on any layer that has sublayers, all children layers become non-trainable as well. +모델이나 서브레이어를 가진 레이어에서 `trainable = False`로 설정하면, +모든 하위 레이어도 트레이닝 불가능한 상태가 됩니다. -**Example:** +**예시:** ```python inner_model = keras.Sequential( @@ -188,64 +209,70 @@ model = keras.Sequential( ] ) -model.trainable = False # Freeze the outer model +model.trainable = False # 바깥 모델을 동결합니다. -assert inner_model.trainable == False # All layers in `model` are now frozen -assert inner_model.layers[0].trainable == False # `trainable` is propagated recursively +assert inner_model.trainable == False # 이제 `model`의 모든 레이어가 동결되었습니다. +assert inner_model.layers[0].trainable == False # `trainable`이 재귀적으로 전파됩니다. ``` -## The typical transfer-learning workflow +## 일반적인 전이 학습 워크플로 {#the-typical-transfer-learning-workflow} -This leads us to how a typical transfer learning workflow can be implemented in Keras: +이제 Keras에서 전이 학습 워크플로를 구현하는 일반적인 방법에 대해 알아보겠습니다: -1. Instantiate a base model and load pre-trained weights into it. -2. Freeze all layers in the base model by setting `trainable = False`. -3. Create a new model on top of the output of one (or several) layers from the base model. -4. Train your new model on your new dataset. +1. 베이스 모델을 인스턴스화하고, 사전 트레이닝된 가중치를 로드합니다. +2. `trainable = False`로 설정하여, 베이스 모델의 모든 레이어를 동결합니다. +3. 베이스 모델 위에 한 개 이상의 레이어 출력을 만들어 새로운 모델을 만듭니다. +4. 새로운 데이터셋으로 새 모델을 트레이닝합니다. -Note that an alternative, more lightweight workflow could also be: +또한, 더 가벼운 워크플로는 다음과 같이 할 수도 있습니다: -1. Instantiate a base model and load pre-trained weights into it. -2. Run your new dataset through it and record the output of one (or several) layers from the base model. This is called **feature extraction**. -3. Use that output as input data for a new, smaller model. +1. 베이스 모델을 인스턴스화하고, 사전 트레이닝된 가중치를 로드합니다. +2. 새로운 데이터셋을 통해 베이스 모델을 실행하고, 베이스 모델의 한 개 이상의 레이어 출력을 기록합니다. + 이를 **특성 추출**이라고 합니다. +3. 그 출력을 새로운, 더 작은 모델의 입력 데이터로 사용합니다. -A key advantage of that second workflow is that you only run the base model once on your data, rather than once per epoch of training. So it's a lot faster & cheaper. +이 두 번째 워크플로의 주요 장점은 데이터를 사용할 때 베이스 모델을 한 번만 실행하면 되므로, +에포크마다 베이스 모델을 실행하지 않아도 되기 때문에, 훨씬 빠르고 비용이 저렴하다는 점입니다. -An issue with that second workflow, though, is that it doesn't allow you to dynamically modify the input data of your new model during training, which is required when doing data augmentation, for instance. Transfer learning is typically used for tasks when your new dataset has too little data to train a full-scale model from scratch, and in such scenarios data augmentation is very important. So in what follows, we will focus on the first workflow. +그러나 두 번째 워크플로의 단점은, 트레이닝 중에 새 모델의 입력 데이터를 동적으로 수정할 수 없다는 점입니다. +예를 들어, 데이터 보강을 할 때는 이것이 필요합니다. +전이 학습은 일반적으로 새로운 데이터셋이 부족하여, +처음부터 대규모 모델을 트레이닝할 수 없을 때 사용되며, +이러한 상황에서 데이터 보강은 매우 중요합니다. +따라서, 아래에서는 첫 번째 워크플로에 초점을 맞추겠습니다. -Here's what the first workflow looks like in Keras: +다음은 Keras에서 첫 번째 워크플로가 어떻게 보이는지입니다: -First, instantiate a base model with pre-trained weights. +먼저, 사전 트레이닝된 가중치로 기본 모델을 인스턴스화합니다. ```python base_model = keras.applications.Xception( - weights='imagenet', # Load weights pre-trained on ImageNet. + weights='imagenet', # ImageNet에서 사전 트레이닝된 가중치 로드. input_shape=(150, 150, 3), - include_top=False) # Do not include the ImageNet classifier at the top. + include_top=False) # ImageNet 분류기를 상단에 포함하지 않음. ``` -Then, freeze the base model. +그런 다음, 베이스 모델을 동결합니다. ```python base_model.trainable = False ``` -Create a new model on top. +상단에 새로운 모델을 생성합니다. ```python inputs = keras.Input(shape=(150, 150, 3)) -# We make sure that the base_model is running in inference mode here, -# by passing `training=False`. This is important for fine-tuning, as you will -# learn in a few paragraphs. +# 여기서 베이스 모델이 추론 모드로 실행되도록, `training=False`를 전달합니다. +# 이는 미세 조정을 할 때 매우 중요합니다. 이 부분은 이후에 다룰 예정입니다. x = base_model(inputs, training=False) -# Convert features of shape `base_model.output_shape[1:]` to vectors +# `base_model.output_shape[1:]` 형태의 특성을 벡터로 변환합니다. x = keras.layers.GlobalAveragePooling2D()(x) -# A Dense classifier with a single unit (binary classification) +# 단일 유닛을 가진 Dense 분류기 (이진 분류) outputs = keras.layers.Dense(1)(x) model = keras.Model(inputs, outputs) ``` -Train the model on new data. +새로운 데이터로 모델을 트레이닝합니다. ```python model.compile(optimizer=keras.optimizers.Adam(), @@ -254,65 +281,94 @@ model.compile(optimizer=keras.optimizers.Adam(), model.fit(new_dataset, epochs=20, callbacks=..., validation_data=...) ``` -## Fine-tuning +## 미세 조정 {#fine-tuning} -Once your model has converged on the new data, you can try to unfreeze all or part of the base model and retrain the whole model end-to-end with a very low learning rate. +모델이 새로운 데이터에 대해 수렴한 후, 베이스 모델의 전체 또는 일부를 동결 해제하고, +매우 낮은 학습률로 전체 모델을 엔드투엔드로 다시 트레이닝할 수 있습니다. -This is an optional last step that can potentially give you incremental improvements. It could also potentially lead to quick overfitting – keep that in mind. +이 단계는 선택적인 마지막 단계로, 점진적인 개선을 얻을 수 있습니다. +하지만, 과적합이 빠르게 발생할 수도 있다는 점을 유의해야 합니다. -It is critical to only do this step _after_ the model with frozen layers has been trained to convergence. If you mix randomly-initialized trainable layers with trainable layers that hold pre-trained features, the randomly-initialized layers will cause very large gradient updates during training, which will destroy your pre-trained features. +모델의 동결된 레이어가 수렴된 _후에만_ 이 단계를 수행하는 것이 중요합니다. +무작위로 초기화된 트레이닝 가능한 레이어와 사전 트레이닝된 특성을 보유한 트레이닝 가능한 레이어를 섞으면, +무작위로 초기화된 레이어가 트레이닝 중에 매우 큰 그래디언트 업데이트를 유발해, +사전 트레이닝된 특성을 파괴할 수 있습니다. -It's also critical to use a very low learning rate at this stage, because you are training a much larger model than in the first round of training, on a dataset that is typically very small. As a result, you are at risk of overfitting very quickly if you apply large weight updates. Here, you only want to readapt the pretrained weights in an incremental way. +또한, 이 단계에서 매우 낮은 학습률을 사용하는 것이 중요합니다. +이는 첫 번째 라운드의 트레이닝보다 훨씬 큰 모델을, 일반적으로 매우 작은 데이터셋으로 트레이닝하기 때문입니다. +그 결과, 큰 가중치 업데이트를 적용하면 매우 빠르게 과적합될 위험이 있습니다. +여기서는 사전 트레이닝된 가중치를 점진적으로 재적응시키고자 하는 것입니다. -This is how to implement fine-tuning of the whole base model: +다음은 전체 베이스 모델의 미세 조정을 구현하는 방법입니다: ```python -# Unfreeze the base model +# 베이스 모델의 동결 해제 base_model.trainable = True -# It's important to recompile your model after you make any changes -# to the `trainable` attribute of any inner layer, so that your changes -# are take into account +# `trainable` 속성을 변경한 후에는 모델을 다시 컴파일하는 것이 중요합니다. +# 이렇게 해야 변경 사항이 반영됩니다. model.compile(optimizer=keras.optimizers.Adam(1e-5), # Very low learning rate loss=keras.losses.BinaryCrossentropy(from_logits=True), metrics=[keras.metrics.BinaryAccuracy()]) -# Train end-to-end. Be careful to stop before you overfit! +# 엔드투엔드로 트레이닝. 과적합이 발생하기 전에 주의해서 멈추세요! model.fit(new_dataset, epochs=10, callbacks=..., validation_data=...) ``` -**Important note about `compile()` and `trainable`** +**`compile()`과 `trainable`에 대한 중요한 참고 사항** -Calling `compile()` on a model is meant to "freeze" the behavior of that model. This implies that the `trainable` attribute values at the time the model is compiled should be preserved throughout the lifetime of that model, until `compile` is called again. Hence, if you change any `trainable` value, make sure to call `compile()` again on your model for your changes to be taken into account. +모델에서 `compile()`을 호출하면, 그 모델의 동작이 "동결(freeze)"됩니다. +즉, 모델이 컴파일될 때의 `trainable` 속성 값이 이후, +다시 `compile`이 호출되기 전까지 유지됩니다. +따라서, 어떤 `trainable` 값을 변경한 경우, +변경 사항이 반영되도록 모델에서 `compile()`을 다시 호출해야 합니다. -**Important notes about `BatchNormalization` layer** +**`BatchNormalization` 레이어에 대한 중요한 참고 사항** -Many image models contain `BatchNormalization` layers. That layer is a special case on every imaginable count. Here are a few things to keep in mind. +많은 이미지 모델에는 `BatchNormalization` 레이어가 포함되어 있습니다. +이 레이어는 모든 면에서 특별한 경우에 해당합니다. +다음 몇 가지 사항을 염두에 두어야 합니다. -- `BatchNormalization` contains 2 non-trainable weights that get updated during training. These are the variables tracking the mean and variance of the inputs. -- When you set `bn_layer.trainable = False`, the `BatchNormalization` layer will run in inference mode, and will not update its mean & variance statistics. This is not the case for other layers in general, as [weight trainability & inference/training modes are two orthogonal concepts]({{< relref "/docs/getting_started/faq/#whats-the-difference-between-the-training-argument-in-call-and-the-trainable-attribute" >}}). But the two are tied in the case of the `BatchNormalization` layer. -- When you unfreeze a model that contains `BatchNormalization` layers in order to do fine-tuning, you should keep the `BatchNormalization` layers in inference mode by passing `training=False` when calling the base model. Otherwise the updates applied to the non-trainable weights will suddenly destroy what the model has learned. +- `BatchNormalization`은 트레이닝 중에 업데이트되는 2개의 트레이닝 불가능한 가중치를 포함합니다. + 이는 입력의 평균과 분산을 추적하는 변수들입니다. +- `bn_layer.trainable = False`로 설정하면, `BatchNormalization` 레이어는 추론 모드에서 실행되며, + 평균과 분산 통계를 업데이트하지 않습니다. + 이는 일반적인 다른 레이어에서는 해당되지 않습니다. + [가중치의 트레이닝 가능 여부와 추론/트레이닝 모드는 서로 독립적인 개념]({{< relref "/docs/getting_started/faq/#whats-the-difference-between-the-training-argument-in-call-and-the-trainable-attribute" >}})이지만, + `BatchNormalization` 레이어에서는 이 둘이 연결되어 있습니다. +- 미세 조정을 위해 `BatchNormalization` 레이어가 포함된 모델을 동결 해제하는 경우, + 베이스 모델을 호출할 때 `training=False`를 전달하여, + `BatchNormalization` 레이어가 추론 모드에서 유지되도록 해야 합니다. + 그렇지 않으면, 트레이닝 불가능한 가중치에 적용된 업데이트가 모델이 학습한 내용을 갑자기 파괴할 수 있습니다. -You'll see this pattern in action in the end-to-end example at the end of this guide. +이 가이드 끝부분의 엔드투엔드 예제에서, 이 패턴이 실제로 어떻게 작동하는지 확인할 수 있습니다. -## An end-to-end example: fine-tuning an image classification model on a cats vs. dogs dataset +## 엔드투엔드 예시: cats vs. dogs 데이터셋에 대해 이미지 분류 모델 미세 조정 {#an-end-to-end-example-fine-tuning-an-image-classification-model-on-a-cats-vs-dogs-dataset} -To solidify these concepts, let's walk you through a concrete end-to-end transfer learning & fine-tuning example. We will load the Xception model, pre-trained on ImageNet, and use it on the Kaggle "cats vs. dogs" classification dataset. +이 개념들을 더 확실히 하기 위해, 구체적인 엔드투엔드 전이 학습 및 미세 조정 예제를 살펴보겠습니다. +우리는 ImageNet에서 사전 트레이닝된 Xception 모델을 로드한 후, +Kaggle의 "cats vs. dogs" 분류 데이터셋에서 사용할 것입니다. -### Getting the data +### 데이터 가져오기 {#getting-the-data} -First, let's fetch the cats vs. dogs dataset using TFDS. If you have your own dataset, you'll probably want to use the utility [`keras.utils.image_dataset_from_directory`]({{< relref "/docs/api/data_loading/image#image_dataset_from_directory-function" >}}) to generate similar labeled dataset objects from a set of images on disk filed into class-specific folders. +먼저, TFDS를 사용하여 cats vs. dogs 데이터셋을 가져오겠습니다. +여러분이 직접 데이터셋을 가지고 있다면, +[`keras.utils.image_dataset_from_directory`]({{< relref "/docs/api/data_loading/image#image_dataset_from_directory-function" >}}) 유틸리티를 사용하여, +디스크에 클래스별 폴더로 나누어진 이미지 집합에서 유사한 라벨링된 데이터셋 객체를 생성할 수 있습니다. -Transfer learning is most useful when working with very small datasets. To keep our dataset small, we will use 40% of the original training data (25,000 images) for training, 10% for validation, and 10% for testing. +전이 학습은 매우 작은 데이터셋을 다룰 때 가장 유용합니다. +데이터셋을 작게 유지하기 위해, +원래의 트레이닝 데이터(25,000개의 이미지) 중 40%를 트레이닝에 사용하고, +10%는 검증, 10%는 테스트에 사용할 것입니다. ```python tfds.disable_progress_bar() train_ds, validation_ds, test_ds = tfds.load( "cats_vs_dogs", - # Reserve 10% for validation and 10% for test + # 10%를 검증, 10%를 테스트로 예약 split=["train[:40%]", "train[40%:50%]", "train[50%:60%]"], - as_supervised=True, # Include labels + as_supervised=True, # 라벨 포함 ) print(f"Number of training samples: {train_ds.cardinality()}") @@ -335,7 +391,7 @@ Number of test samples: 2326 {{% /details %}} -These are the first 9 images in the training dataset – as you can see, they're all different sizes. +다음은 트레이닝 데이터셋에 있는 첫 9개의 이미지입니다. 보시다시피, 모두 크기가 다릅니다. ```python plt.figure(figsize=(10, 10)) @@ -348,20 +404,30 @@ for i, (image, label) in enumerate(train_ds.take(9)): ![png](/images/guides/transfer_learning/transfer_learning_21_0.png) -We can also see that label 1 is "dog" and label 0 is "cat". +또한, 라벨 1은 "개"이고 라벨 0은 "고양이"인 것을 알 수 있습니다. -### Standardizing the data +### 데이터 표준화 {#standardizing-the-data} -Our raw images have a variety of sizes. In addition, each pixel consists of 3 integer values between 0 and 255 (RGB level values). This isn't a great fit for feeding a neural network. We need to do 2 things: +원본 이미지들은 다양한 크기를 가지고 있습니다. +또한, 각 픽셀은 0에서 255 사이의 3개의 정수 값으로 이루어져 있습니다. (RGB 값) +이는 신경망에 적합한 입력 형태가 아닙니다. 우리는 두 가지 작업을 수행해야 합니다: -- Standardize to a fixed image size. We pick 150x150. -- Normalize pixel values between -1 and 1. We'll do this using a `Normalization` layer as part of the model itself. +- 고정된 이미지 크기로 표준화합니다. 150x150을 선택합니다. +- 픽셀 값을 -1에서 1 사이로 정규화합니다. 이를 위해 `Normalization` 레이어를 모델의 일부로 사용할 것입니다. -In general, it's a good practice to develop models that take raw data as input, as opposed to models that take already-preprocessed data. The reason being that, if your model expects preprocessed data, any time you export your model to use it elsewhere (in a web browser, in a mobile app), you'll need to reimplement the exact same preprocessing pipeline. This gets very tricky very quickly. So we should do the least possible amount of preprocessing before hitting the model. +일반적으로, 이미 전처리된 데이터를 입력으로 사용하는 모델보다는, +raw 데이터를 입력으로 받는 모델을 개발하는 것이 좋습니다. +그 이유는, 모델이 전처리된 데이터를 기대할 경우, +모델을 다른 환경(예: 웹 브라우저, 모바일 앱)에서 사용할 때마다, +동일한 전처리 파이프라인을 다시 구현해야 하기 때문입니다. +이는 매우 까다로워질 수 있습니다. +따라서, 모델에 입력하기 전에 가능한 한 적은 양의 전처리만 수행하는 것이 좋습니다. -Here, we'll do image resizing in the data pipeline (because a deep neural network can only process contiguous batches of data), and we'll do the input value scaling as part of the model, when we create it. +여기서는 데이터 파이프라인에서 이미지 크기 조정을 수행할 것입니다. +(딥러닝 신경망은 연속적인 데이터 배치만 처리할 수 있기 때문입니다) +그리고 입력 값 스케일링은 모델을 만들 때 모델의 일부로 수행할 것입니다. -Let's resize images to 150x150: +이미지를 150x150 크기로 조정해봅시다: ```python resize_fn = keras.layers.Resizing(150, 150) @@ -371,9 +437,13 @@ validation_ds = validation_ds.map(lambda x, y: (resize_fn(x), y)) test_ds = test_ds.map(lambda x, y: (resize_fn(x), y)) ``` -### Using random data augmentation +### 랜덤 데이터 보강 사용 {#using-random-data-augmentation} -When you don't have a large image dataset, it's a good practice to artificially introduce sample diversity by applying random yet realistic transformations to the training images, such as random horizontal flipping or small random rotations. This helps expose the model to different aspects of the training data while slowing down overfitting. +대규모 이미지 데이터셋이 없을 때, +트레이닝 이미지에 랜덤하지만 현실적인 변환을 적용하여, +인위적으로 샘플 다양성을 도입하는 것이 좋습니다. +예를 들어, 랜덤한 가로 뒤집기나 작은 각도의 랜덤 회전을 적용할 수 있습니다. +이렇게 하면 모델이 트레이닝 데이터의 다양한 측면에 노출되면서 과적합을 늦출 수 있습니다. ```python augmentation_layers = [ @@ -391,7 +461,7 @@ def data_augmentation(x): train_ds = train_ds.map(lambda x, y: (data_augmentation(x), y)) ``` -Let's batch the data and use prefetching to optimize loading speed. +데이터를 배치로 처리하고, 로딩 속도를 최적화하기 위해 prefetching을 사용해봅시다. ```python from tensorflow import data as tf_data @@ -403,7 +473,7 @@ validation_ds = validation_ds.batch(batch_size).prefetch(tf_data.AUTOTUNE).cache test_ds = test_ds.batch(batch_size).prefetch(tf_data.AUTOTUNE).cache() ``` -Let's visualize what the first image of the first batch looks like after various random transformations: +첫 번째 배치의 첫 번째 이미지가 다양한 랜덤 변환을 거친 후 어떻게 보이는지 시각화해봅시다: ```python for images, labels in train_ds.take(1): @@ -419,41 +489,43 @@ for images, labels in train_ds.take(1): ![png](/images/guides/transfer_learning/transfer_learning_30_0.png) -## Build a model +## 모델 빌드 {#build-a-model} -Now let's built a model that follows the blueprint we've explained earlier. +이제 이전에 설명한 설계도를 따르는 모델을 빌드해봅시다. -Note that: +참고 사항: -- We add a `Rescaling` layer to scale input values (initially in the `[0, 255]` range) to the `[-1, 1]` range. -- We add a `Dropout` layer before the classification layer, for regularization. -- We make sure to pass `training=False` when calling the base model, so that it runs in inference mode, so that batchnorm statistics don't get updated even after we unfreeze the base model for fine-tuning. +- 입력 값을 `[0, 255]` 범위에서 `[-1, 1]` 범위로 스케일링하기 위해, `Rescaling` 레이어를 추가합니다. +- 정규화를 위해, 분류 레이어 앞에 `Dropout` 레이어를 추가합니다. +- 베이스 모델을 호출할 때 `training=False`를 전달하여, 배치 정규화 통계가 업데이트되지 않도록, + 추론 모드에서 실행되도록 해야 합니다. + 미세 조정을 위해 베이스 모델을 동결 해제한 후에도, 이 설정을 유지합니다. ```python base_model = keras.applications.Xception( - weights="imagenet", # Load weights pre-trained on ImageNet. + weights="imagenet", # ImageNet에서 사전 트레이닝된 가중치 로드. input_shape=(150, 150, 3), include_top=False, -) # Do not include the ImageNet classifier at the top. +) # 상단에 ImageNet 분류기를 포함하지 않음. -# Freeze the base_model +# `base_model` 동결 base_model.trainable = False -# Create new model on top +# 상단에 새 모델 생성 inputs = keras.Input(shape=(150, 150, 3)) -# Pre-trained Xception weights requires that input be scaled -# from (0, 255) to a range of (-1., +1.), the rescaling layer -# outputs: `(inputs * scale) + offset` +# 사전 트레이닝된 Xception 가중치는 입력이 (0, 255) 범위에서 +# (-1., +1.) 범위로 스케일링되어야 합니다. +# Rescaling 레이어의 출력은: `(inputs * scale) + offset`입니다. scale_layer = keras.layers.Rescaling(scale=1 / 127.5, offset=-1) x = scale_layer(inputs) -# The base model contains batchnorm layers. We want to keep them in inference mode -# when we unfreeze the base model for fine-tuning, so we make sure that the -# base_model is running in inference mode here. +# 베이스 모델에 배치 정규화 레이어가 포함되어 있습니다. +# 미세 조정을 위해 베이스 모델을 동결 해제할 때도 추론 모드에서 유지되도록 +# base_model이 여기서 추론 모드로 실행되게 합니다. x = base_model(x, training=False) x = keras.layers.GlobalAveragePooling2D()(x) -x = keras.layers.Dropout(0.2)(x) # Regularize with dropout +x = keras.layers.Dropout(0.2)(x) # Dropout으로 정규화 outputs = keras.layers.Dense(1)(x) model = keras.Model(inputs, outputs) @@ -492,7 +564,7 @@ Model: "functional_4" {{% /details %}} -## Train the top layer +## 상단 레이어 트레이닝 {#train-the-top-layer} ```python model.compile( @@ -540,18 +612,21 @@ Epoch 2/2 {{% /details %}} -## Do a round of fine-tuning of the entire model +## 전체 모델의 미세 조정 단계 {#do-a-round-of-fine-tuning-of-the-entire-model} -Finally, let's unfreeze the base model and train the entire model end-to-end with a low learning rate. +마지막으로, 베이스 모델의 동결을 해제하고, 낮은 학습률로 엔드투엔드로 전체 모델을 트레이닝합니다. -Importantly, although the base model becomes trainable, it is still running in inference mode since we passed `training=False` when calling it when we built the model. This means that the batch normalization layers inside won't update their batch statistics. If they did, they would wreck havoc on the representations learned by the model so far. +중요한 점은, 베이스 모델이 트레이닝 가능해지더라도, +모델을 빌드할 때 `training=False`를 전달했기 때문에 여전히 추론 모드로 실행된다는 것입니다. +이는 내부의 배치 정규화 레이어들이 배치 통계를 업데이트하지 않음을 의미합니다. +만약 업데이트된다면, 지금까지 모델이 학습한 표현에 큰 혼란을 일으킬 것입니다. ```python -# Unfreeze the base_model. Note that it keeps running in inference mode -# since we passed `training=False` when calling it. This means that -# the batchnorm layers will not update their batch statistics. -# This prevents the batchnorm layers from undoing all the training -# we've done so far. +# base_model의 동결 해제. +# 모델을 호출할 때 `training=False`를 전달했으므로 +# 여전히 추론 모드로 실행됩니다. +# 즉, 배치 정규화 레이어는 배치 통계를 +# 업데이트하지 않으며, 이는 지금까지의 트레이닝을 무효화하는 것을 방지합니다. base_model.trainable = True model.summary(show_trainable=True) @@ -601,7 +676,7 @@ Fitting the end-to-end model {{% /details %}} -After 10 epochs, fine-tuning gains us a nice improvement here. Let's evaluate the model on the test dataset: +10 에포크 후, 미세 조정을 통해 성능이 상당히 개선되었습니다. 이제 테스트 데이터셋에서 모델을 평가해봅시다: ```python print("Test dataset evaluation") diff --git a/content/korean/docs/guides/writing_a_custom_training_loop_in_jax/_index.md b/content/korean/docs/guides/writing_a_custom_training_loop_in_jax/_index.md index 856bf72b..73c5e410 100644 --- a/content/korean/docs/guides/writing_a_custom_training_loop_in_jax/_index.md +++ b/content/korean/docs/guides/writing_a_custom_training_loop_in_jax/_index.md @@ -1,6 +1,6 @@ --- -title: Writing a training loop from scratch in JAX -linkTitle: Writing a custom training loop in JAX +title: JAX에서 처음부터 트레이닝 루프 작성하기 +linkTitle: JAX 트레이닝 루프 toc: true weight: 8 type: docs @@ -11,49 +11,54 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2023/06/25 **{{< t f_last_modified >}}** 2023/06/25 -**{{< t f_description >}}** Writing low-level training & evaluation loops in JAX. +**{{< t f_description >}}** JAX에서 낮은 레벨 트레이닝 및 평가 루프 작성하기. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/writing_a_custom_training_loop_in_jax.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/writing_a_custom_training_loop_in_jax.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Setup +## 셋업 {#setup} ```python import os -# This guide can only be run with the jax backend. +# 이 가이드는 jax 백엔드에서만 실행할 수 있습니다. os.environ["KERAS_BACKEND"] = "jax" import jax -# We import TF so we can use tf.data. +# tf.data를 사용하기 위해 TF를 임포트합니다. import tensorflow as tf import keras import numpy as np ``` -## Introduction +## 소개 {#introduction} -Keras provides default training and evaluation loops, `fit()` and `evaluate()`. Their usage is covered in the guide [Training & evaluation with the built-in methods]({{< relref "/docs/guides/training_with_built_in_methods" >}}). +Keras는 기본 트레이닝 및 평가 루프인 `fit()`과 `evaluate()`를 제공합니다. +이것들의 사용 방법은 {{< titledRelref "/docs/guides/training_with_built_in_methods" >}} 가이드에서 다룹니다. -If you want to customize the learning algorithm of your model while still leveraging the convenience of `fit()` (for instance, to train a GAN using `fit()`), you can subclass the `Model` class and implement your own `train_step()` method, which is called repeatedly during `fit()`. +모델의 학습 알고리즘을 커스터마이즈하면서도 `fit()`의 편리함을 활용하고 싶다면 +(예를 들어, `fit()`을 사용해 GAN을 트레이닝하려는 경우), +`Model` 클래스를 서브클래싱하고, +`fit()` 동안 반복적으로 호출되는 자체 `train_step()` 메서드를 구현할 수 있습니다. -Now, if you want very low-level control over training & evaluation, you should write your own training & evaluation loops from scratch. This is what this guide is about. +이제, 트레이닝 및 평가에 대해 매우 낮은 레벨의 제어를 원한다면, +처음부터 직접 트레이닝 및 평가 루프를 작성해야 합니다. 이 가이드는 그것에 관한 것입니다. -## A first end-to-end example +## 첫 번째 엔드투엔드 예제 {#a-first-end-to-end-example} -To write a custom training loop, we need the following ingredients: +커스텀 트레이닝 루프를 작성하려면, 다음이 필요합니다: -- A model to train, of course. -- An optimizer. You could either use an optimizer from `keras.optimizers`, or one from the `optax` package. -- A loss function. -- A dataset. The standard in the JAX ecosystem is to load data via [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data), so that's what we'll use. +- 트레이닝할 모델. +- 옵티마이저. `keras.optimizers`의 옵티마이저를 사용하거나, `optax` 패키지에서 사용할 수 있습니다. +- 손실 함수. +- 데이터셋. JAX 생태계의 표준은 [`tf.data`](https://www.tensorflow.org/api_docs/python/tf/data)를 통해 데이터를 로드하는 것이므로, 이를 사용할 것입니다. -Let's line them up. +이제 하나씩 설정해 보겠습니다. -First, let's get the model and the MNIST dataset: +먼저, 모델과 MNIST 데이터셋을 가져옵니다: ```python def get_model(): @@ -67,7 +72,7 @@ def get_model(): model = get_model() -# Prepare the training dataset. +# 트레이닝 데이터셋 준비. batch_size = 32 (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() x_train = np.reshape(x_train, (-1, 784)).astype("float32") @@ -75,38 +80,42 @@ x_test = np.reshape(x_test, (-1, 784)).astype("float32") y_train = keras.utils.to_categorical(y_train) y_test = keras.utils.to_categorical(y_test) -# Reserve 10,000 samples for validation. +# 검증을 위해 10,000개의 샘플을 예약합니다. x_val = x_train[-10000:] y_val = y_train[-10000:] x_train = x_train[:-10000] y_train = y_train[:-10000] -# Prepare the training dataset. +# 트레이닝 데이터셋 준비. train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = train_dataset.shuffle(buffer_size=1024).batch(batch_size) -# Prepare the validation dataset. +# 검증 데이터셋 준비. val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val)) val_dataset = val_dataset.batch(batch_size) ``` -Next, here's the loss function and the optimizer. We'll use a Keras optimizer in this case. +다음으로, 손실 함수와 옵티마이저를 설정합니다. 이번에는 Keras 옵티마이저를 사용합니다. ```python -# Instantiate a loss function. +# 손실 함수 인스턴스화. loss_fn = keras.losses.CategoricalCrossentropy(from_logits=True) -# Instantiate an optimizer. +# 옵티마이저 인스턴스화. optimizer = keras.optimizers.Adam(learning_rate=1e-3) ``` -### Getting gradients in JAX +### JAX에서 그래디언트 얻기 {#getting-gradients-in-jax} -Let's train our model using mini-batch gradient with a custom training loop. +커스텀 트레이닝 루프를 사용하여, 미니 배치 그래디언트로 모델을 트레이닝해봅시다. -In JAX, gradients are computed via _metaprogramming_: you call the `jax.grad` (or `jax.value_and_grad` on a function in order to create a gradient-computing function for that first function. +JAX에서는 *메타프로그래밍(metaprogramming)*을 통해 그래디언트를 계산합니다. +`jax.grad` (또는 `jax.value_and_grad`)를 함수에 호출하여, +그 함수에 대한 그래디언트 계산 함수를 생성합니다. -So the first thing we need is a function that returns the loss value. That's the function we'll use to generate the gradient function. Something like this: +따라서 먼저 필요한 것은 손실 값을 반환하는 함수입니다. +이 함수를 사용하여 그래디언트 함수를 생성할 것입니다. +다음과 같은 형태입니다: ```python def compute_loss(x, y): @@ -114,25 +123,32 @@ def compute_loss(x, y): return loss ``` -Once you have such a function, you can compute gradients via metaprogramming as such: +이와 같은 함수를 갖게 되면, 메타프로그래밍을 통해 다음과 같이 그래디언트를 계산할 수 있습니다: ```python grad_fn = jax.grad(compute_loss) grads = grad_fn(x, y) ``` -Typically, you don't just want to get the gradient values, you also want to get the loss value. You can do this by using `jax.value_and_grad` instead of `jax.grad`: +일반적으로는, 단순히 그래디언트 값만 얻는 것이 아니라 손실 값도 함께 얻고자 합니다. +이를 위해 `jax.grad` 대신 `jax.value_and_grad`를 사용할 수 있습니다: ```python grad_fn = jax.value_and_grad(compute_loss) loss, grads = grad_fn(x, y) ``` -### JAX computation is purely stateless +### JAX 계산은 순수하게 stateless입니다. {#jax-computation-is-purely-stateless} -In JAX, everything must be a stateless function – so our loss computation function must be stateless as well. That means that all Keras variables (e.g. weight tensors) must be passed as function inputs, and any variable that has been updated during the forward pass must be returned as function output. The function have no side effect. +JAX에서는, 모든 것이 stateless 함수여야 하므로, 손실 계산 함수도 stateless여야 합니다. +이는 모든 Keras 변수(예: 가중치 텐서)를 함수의 입력으로 전달해야 하며, +순전파 동안 업데이트된 모든 변수를 함수의 출력으로 반환해야 함을 의미합니다. +함수는 부수 효과가 없어야 합니다. -During the forward pass, the non-trainable variables of a Keras model might get updated. These variables could be, for instance, RNG seed state variables or BatchNormalization statistics. We're going to need to return those. So we need something like this: +순전파 동안, Keras 모델의 비트레이닝 변수는 업데이트될 수 있습니다. +이러한 변수는 예를 들어 RNG 시드 상태 변수나 BatchNormalization 통계일 수 있습니다. +우리는 이러한 변수들을 반환해야 합니다. +따라서 다음과 같은 함수가 필요합니다: ```python def compute_loss_and_updates(trainable_variables, non_trainable_variables, x, y): @@ -140,7 +156,10 @@ def compute_loss_and_updates(trainable_variables, non_trainable_variables, x, y) return loss, non_trainable_variables ``` -Once you have such a function, you can get the gradient function by specifying `has_aux` in `value_and_grad`: it tells JAX that the loss computation function returns more outputs than just the loss. Note that the loss should always be the first output. +이러한 함수를 갖게 되면, +`value_and_grad`에서 `has_aux`를 지정하여 그래디언트 함수를 얻을 수 있습니다. +이는 JAX에 손실 계산 함수가 손실 외에도 더 많은 출력을 반환한다고 알려줍니다. +손실은 항상 첫 번째 출력이어야 한다는 점에 유의하세요. ```python grad_fn = jax.value_and_grad(compute_loss_and_updates, has_aux=True) @@ -149,7 +168,12 @@ grad_fn = jax.value_and_grad(compute_loss_and_updates, has_aux=True) ) ``` -Now that we have established the basics, let's implement this `compute_loss_and_updates` function. Keras models have a `stateless_call` method which will come in handy here. It works just like `model.__call__`, but it requires you to explicitly pass the value of all the variables in the model, and it returns not just the `__call__` outputs but also the (potentially updated) non-trainable variables. +이제 기본 사항을 정립했으니, `compute_loss_and_updates` 함수를 구현해봅시다. +Keras 모델에는 `stateless_call` 메서드가 있는데, +이 메서드는 여기서 유용하게 사용할 수 있습니다. +`model.__call__`과 비슷하게 작동하지만, +모델의 모든 변수 값을 명시적으로 전달해야 하며, +`__call__` 출력뿐만 아니라 (잠재적으로 업데이트된) 트레이닝 불가능한(non-trainable) 변수도 반환합니다. ```python def compute_loss_and_updates(trainable_variables, non_trainable_variables, x, y): @@ -160,20 +184,28 @@ def compute_loss_and_updates(trainable_variables, non_trainable_variables, x, y) return loss, non_trainable_variables ``` -Let's get the gradient function: +그래디언트 함수를 구해봅시다: ```python grad_fn = jax.value_and_grad(compute_loss_and_updates, has_aux=True) ``` -### The training step function +### 트레이닝 스텝 함수 {#the-training-step-function} -Next, let's implement the end-to-end training step, the function that will both run the forward pass, compute the loss, compute the gradients, but also use the optimizer to update the trainable variables. This function also needs to be stateless, so it will get as input a `state` tuple that includes every state element we're going to use: +다음으로, 엔드투엔드 트레이닝 스텝을 구현해봅시다. +이 함수는 순전파를 실행하고, 손실을 계산하고, 그래디언트를 계산하며, +옵티마이저를 사용하여 트레이닝 가능한 변수를 업데이트하는 역할을 합니다. +이 함수도 stateless여야 하므로, +우리가 사용할 모든 상태 요소를 포함하는 `state` 튜플을 입력으로 받아야 합니다: -- `trainable_variables` and `non_trainable_variables`: the model's variables. -- `optimizer_variables`: the optimizer's state variables, such as momentum accumulators. +- `trainable_variables` 및 `non_trainable_variables`: 모델의 변수들. +- `optimizer_variables`: 옵티마이저의 상태 변수들, 예를 들어 모멘텀 누적기(momentum accumulators)와 같은 것들. -To update the trainable variables, we use the optimizer's stateless method `stateless_apply`. It's equivalent to `optimizer.apply()`, but it requires always passing `trainable_variables` and `optimizer_variables`. It returns both the updated trainable variables and the updated optimizer_variables. +트레이닝 가능한 변수를 업데이트하기 위해, +옵티마이저의 stateless 메서드인 `stateless_apply`를 사용합니다. +이는 `optimizer.apply()`와 동등하지만, +항상 `trainable_variables`와 `optimizer_variables`를 전달해야 합니다. +이는 업데이트된 `trainable_variables`와 업데이트된 `optimizer_variables`를 반환합니다. ```python def train_step(state, data): @@ -185,7 +217,7 @@ def train_step(state, data): trainable_variables, optimizer_variables = optimizer.stateless_apply( optimizer_variables, grads, trainable_variables ) - # Return updated state + # 업데이트된 상태 반환 return loss, ( trainable_variables, non_trainable_variables, @@ -193,11 +225,20 @@ def train_step(state, data): ) ``` -### Make it fast with `jax.jit` +### `jax.jit` 빠르게 하기 {#make-it-fast-with-jaxjit} -By default, JAX operations run eagerly, just like in TensorFlow eager mode and PyTorch eager mode. And just like TensorFlow eager mode and PyTorch eager mode, it's pretty slow – eager mode is better used as a debugging environment, not as a way to do any actual work. So let's make our `train_step` fast by compiling it. +기본적으로 JAX 연산은 TensorFlow eager 모드와 PyTorch eager 모드처럼, 즉시(eagerly) 실행됩니다. +그리고, TensorFlow eager 모드와 PyTorch eager 모드처럼 꽤 느립니다. +즉시 실행(eager) 모드는 디버깅 환경으로 더 적합하며, +실제 작업을 수행하는 방법으로는 적합하지 않습니다. +따라서, `train_step`을 컴파일하여 빠르게 만들어봅시다. -When you have a stateless JAX function, you can compile it to XLA via the `@jax.jit` decorator. It will get traced during its first execution, and in subsequent executions you will be executing the traced graph (this is just like `@tf.function(jit_compile=True)`. Let's try it: +stateless JAX 함수가 있는 경우, +`@jax.jit` 데코레이터를 통해 이를 XLA로 컴파일할 수 있습니다. +첫 번째 실행 시 함수가 추적되고, +이후 실행에서는 추적된 그래프를 실행하게 됩니다. +(이는 `@tf.function(jit_compile=True)`와 유사합니다) +시도해 봅시다: ```python @jax.jit @@ -210,7 +251,7 @@ def train_step(state, data): trainable_variables, optimizer_variables = optimizer.stateless_apply( optimizer_variables, grads, trainable_variables ) - # Return updated state + # 업데이트된 상태 반환 return loss, ( trainable_variables, non_trainable_variables, @@ -218,15 +259,20 @@ def train_step(state, data): ) ``` -We're now ready to train our model. The training loop itself is trivial: we just repeatedly call `loss, state = train_step(state, data)`. +이제 모델을 트레이닝할 준비가 되었습니다. +트레이닝 루프 자체는 간단합니다: +`loss, state = train_step(state, data)`를 반복적으로 호출하기만 하면 됩니다. -Note: +참고: -- We convert the TF tensors yielded by the [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) to NumPy before passing them to our JAX function. -- All variables must be built beforehand: the model must be built and the optimizer must be built. Since we're using a Functional API model, it's already built, but if it were a subclassed model you'd need to call it on a batch of data to build it. +- [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset)에서 + 생성된(yielded) TF 텐서를 JAX 함수에 전달하기 전에 NumPy로 변환합니다. +- 모든 변수는 사전에 빌드되어야 합니다: 모델은 빌드되어야 하고, 옵티마이저도 빌드되어야 합니다. + 우리가 사용하는 것은 Functional API 모델이므로 이미 빌드되어 있지만, + 만약 서브클래스화된 모델이라면 데이터를 하나의 배치에 대해 호출하여 빌드해야 합니다. ```python -# Build optimizer variables. +# 옵티마이저 변수 빌드 optimizer.build(model.trainable_variables) trainable_variables = model.trainable_variables @@ -234,11 +280,11 @@ non_trainable_variables = model.non_trainable_variables optimizer_variables = optimizer.variables state = trainable_variables, non_trainable_variables, optimizer_variables -# Training loop +# 트레이닝 루프 for step, data in enumerate(train_dataset): data = (data[0].numpy(), data[1].numpy()) loss, state = train_step(state, data) - # Log every 100 batches. + # 100 배치마다 로그 출력 if step % 100 == 0: print(f"Training loss (for 1 batch) at step {step}: {float(loss):.4f}") print(f"Seen so far: {(step + 1) * batch_size} samples") @@ -283,9 +329,13 @@ Seen so far: 48032 samples {{% /details %}} -A key thing to notice here is that the loop is entirely stateless – the variables attached to the model (`model.weights`) are never getting updated during the loop. Their new values are only stored in the `state` tuple. That means that at some point, before saving the model, you should be attaching the new variable values back to the model. +여기서 주목해야 할 중요한 점은 루프가 완전히 stateless하다는 것입니다. +모델에 첨부된 변수들(`model.weights`)은 루프 동안 절대 업데이트되지 않습니다. +변수의 새로운 값은 오직 `state` 튜플에만 저장됩니다. +이는 모델을 저장하기 전에, 새로운 변수 값을 다시 모델에 연결해야 한다는 것을 의미합니다. -Just call `variable.assign(new_value)` on each model variable you want to update: +업데이트하려는 각 모델 변수에 대해, +`variable.assign(new_value)`를 호출하기만 하면 됩니다: ```python trainable_variables, non_trainable_variables, optimizer_variables = state @@ -295,30 +345,36 @@ for variable, value in zip(model.non_trainable_variables, non_trainable_variable variable.assign(value) ``` -## Low-level handling of metrics +## 메트릭의 낮은 레벨 다루기 {#low-level-handling-of-metrics} -Let's add metrics monitoring to this basic training loop. +이 기본 트레이닝 루프에 메트릭 모니터링을 추가해 봅시다. -You can readily reuse built-in Keras metrics (or custom ones you wrote) in such training loops written from scratch. Here's the flow: +이렇게 처음부터 작성한 트레이닝 루프에서도 +빌트인 Keras 메트릭(또는 사용자가 작성한 커스텀 메트릭)을 쉽게 재사용할 수 있습니다. +흐름은 다음과 같습니다: -- Instantiate the metric at the start of the loop -- Include `metric_variables` in the `train_step` arguments and `compute_loss_and_updates` arguments. -- Call `metric.stateless_update_state()` in the `compute_loss_and_updates` function. It's equivalent to `update_state()` – only stateless. -- When you need to display the current value of the metric, outside the `train_step` (in the eager scope), attach the new metric variable values to the metric object and vall `metric.result()`. -- Call `metric.reset_state()` when you need to clear the state of the metric (typically at the end of an epoch) +- 루프 시작 시 메트릭을 인스턴스화합니다. +- `train_step` 인자와 `compute_loss_and_updates` 인자에 `metric_variables`를 포함시킵니다. +- `compute_loss_and_updates` 함수에서 `metric.stateless_update_state()`를 호출합니다. + 이는 `update_state()`와 같은 역할을 하지만, stateless인 것만 다릅니다. +- `train_step` 외부 (즉시 실행 범위(eager scope))에서 메트릭의 현재 값을 표시해야 할 때, + 새로운 메트릭 변수 값을 메트릭 객체에 연결하고, `metric.result()`를 호출합니다. +- 메트릭의 상태를 초기화해야 할 때(일반적으로 에포크가 끝날 때), + `metric.reset_state()`를 호출합니다. -Let's use this knowledge to compute `CategoricalAccuracy` on training and validation data at the end of training: +이 지식을 사용하여 트레이닝이 끝날 때, +트레이닝 및 검증 데이터에 대한 `CategoricalAccuracy`를 계산해 보겠습니다: ```python -# Get a fresh model +# 새로운 모델 가져오기 model = get_model() -# Instantiate an optimizer to train the model. +# 모델을 트레이닝할 옵티마이저 인스턴스화 optimizer = keras.optimizers.Adam(learning_rate=1e-3) -# Instantiate a loss function. +# 손실 함수 인스턴스화 loss_fn = keras.losses.CategoricalCrossentropy(from_logits=True) -# Prepare the metrics. +# 메트릭 준비 train_acc_metric = keras.metrics.CategoricalAccuracy() val_acc_metric = keras.metrics.CategoricalAccuracy() @@ -354,7 +410,7 @@ def train_step(state, data): trainable_variables, optimizer_variables = optimizer.stateless_apply( optimizer_variables, grads, trainable_variables ) - # Return updated state + # 업데이트된 상태 반환 return loss, ( trainable_variables, non_trainable_variables, @@ -363,7 +419,7 @@ def train_step(state, data): ) ``` -We'll also prepare an evaluation step function: +평가 스텝 함수도 준비해 보겠습니다: ```python @jax.jit @@ -384,10 +440,10 @@ def eval_step(state, data): ) ``` -Here are our loops: +다음은 우리의 루프입니다: ```python -# Build optimizer variables. +# 옵티마이저 변수 빌드 optimizer.build(model.trainable_variables) trainable_variables = model.trainable_variables @@ -401,11 +457,11 @@ state = ( metric_variables, ) -# Training loop +# 트레이닝 루프 for step, data in enumerate(train_dataset): data = (data[0].numpy(), data[1].numpy()) loss, state = train_step(state, data) - # Log every 100 batches. + # 100 배치마다 로그 출력 if step % 100 == 0: print(f"Training loss (for 1 batch) at step {step}: {float(loss):.4f}") _, _, _, metric_variables = state @@ -423,11 +479,11 @@ metric_variables = val_acc_metric.variables ) = state state = trainable_variables, non_trainable_variables, metric_variables -# Eval loop +# 평가 루프 for step, data in enumerate(val_dataset): data = (data[0].numpy(), data[1].numpy()) loss, state = eval_step(state, data) - # Log every 100 batches. + # 100 배치마다 로그 출력 if step % 100 == 0: print(f"Validation loss (for 1 batch) at step {step}: {float(loss):.4f}") _, _, metric_variables = state @@ -504,13 +560,17 @@ Seen so far: 9632 samples {{% /details %}} -## Low-level handling of losses tracked by the model +## 모델이 추적하는 손실의 낮은 레벨 다루기 {#low-level-handling-of-losses-tracked-by-the-model} -Layers & models recursively track any losses created during the forward pass by layers that call `self.add_loss(value)`. The resulting list of scalar loss values are available via the property `model.losses` at the end of the forward pass. +레이어와 모델은 순전파 중, +`self.add_loss(value)`를 호출하는 레이어에 의해 생성된 모든 손실을 재귀적으로 추적합니다. +그 결과 생성된 스칼라 손실 값들의 목록은, +순전파가 끝난 후 `model.losses` 속성을 통해 확인할 수 있습니다. -If you want to be using these loss components, you should sum them and add them to the main loss in your training step. +이러한 손실 요소들을 사용하고 싶다면, +이를 합산하여 트레이닝 스텝의 메인 손실에 추가해야 합니다. -Consider this layer, that creates an activity regularization loss: +활동 정규화 손실을 생성하는 다음 레이어를 고려해 보세요: ```python class ActivityRegularizationLayer(keras.layers.Layer): @@ -519,12 +579,12 @@ class ActivityRegularizationLayer(keras.layers.Layer): return inputs ``` -Let's build a really simple model that uses it: +간단한 모델을 빌드해봅시다: ```python inputs = keras.Input(shape=(784,), name="digits") x = keras.layers.Dense(64, activation="relu")(inputs) -# Insert activity regularization as a layer +# activity 정규화 레이어를 추가합니다. x = ActivityRegularizationLayer()(x) x = keras.layers.Dense(64, activation="relu")(x) outputs = keras.layers.Dense(10, name="predictions")(x) @@ -532,10 +592,10 @@ outputs = keras.layers.Dense(10, name="predictions")(x) model = keras.Model(inputs=inputs, outputs=outputs) ``` -Here's what our `compute_loss_and_updates` function should look like now: +다음은 `compute_loss_and_updates` 함수가 어떻게 생겨야 하는지 보여줍니다: -- Pass `return_losses=True` to `model.stateless_call()`. -- Sum the resulting `losses` and add them to the main loss. +- `model.stateless_call()`에 `return_losses=True`를 전달합니다. +- 결과로 생성된 `losses`를 합산하여, 메인 손실에 추가합니다. ```python def compute_loss_and_updates( @@ -553,4 +613,4 @@ def compute_loss_and_updates( return loss, non_trainable_variables, metric_variables ``` -That's it! +이것으로 끝입니다! diff --git a/content/korean/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md b/content/korean/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md index 2ee4a6fb..0f68cc9a 100644 --- a/content/korean/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md +++ b/content/korean/docs/guides/writing_a_custom_training_loop_in_tensorflow/_index.md @@ -1,6 +1,6 @@ --- -title: Writing a training loop from scratch in TensorFlow -linkTitle: Writing a custom training loop in TensorFlow +title: TensorFlow에서 처음부터 트레이닝 루프 작성하기 +linkTitle: TensorFlow 트레이닝 루프 toc: true weight: 9 type: docs @@ -11,20 +11,20 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2019/03/01 **{{< t f_last_modified >}}** 2023/06/25 -**{{< t f_description >}}** Writing low-level training & evaluation loops in TensorFlow. +**{{< t f_description >}}** TensorFlow에서 낮은 레벨 트레이닝 및 평가 루프 작성하기. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/writing_a_custom_training_loop_in_tensorflow.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/writing_a_custom_training_loop_in_tensorflow.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Setup +## 셋업 {#setup} ```python import time import os -# This guide can only be run with the TensorFlow backend. +# 이 가이드는 TensorFlow 백엔드에서만 실행할 수 있습니다. os.environ["KERAS_BACKEND"] = "tensorflow" import tensorflow as tf @@ -32,17 +32,23 @@ import keras import numpy as np ``` -## Introduction +## 소개 {#introduction} -Keras provides default training and evaluation loops, `fit()` and `evaluate()`. Their usage is covered in the guide [Training & evaluation with the built-in methods]({{< relref "/docs/guides/training_with_built_in_methods/" >}}). +Keras는 기본 트레이닝 및 평가 루프인 `fit()`과 `evaluate()`를 제공합니다. +이러한 사용 방법은 {{< titledRelref "/docs/guides/training_with_built_in_methods/" >}} 가이드에서 다룹니다. -If you want to customize the learning algorithm of your model while still leveraging the convenience of `fit()` (for instance, to train a GAN using `fit()`), you can subclass the `Model` class and implement your own `train_step()` method, which is called repeatedly during `fit()`. +모델의 학습 알고리즘을 커스터마이즈하면서도 `fit()`의 편리함을 활용하고 싶다면 +(예를 들어, `fit()`을 사용해 GAN을 트레이닝하려는 경우), +`Model` 클래스를 서브클래싱하고, +`fit()` 동안 반복적으로 호출되는 자체 `train_step()` 메서드를 구현할 수 있습니다. -Now, if you want very low-level control over training & evaluation, you should write your own training & evaluation loops from scratch. This is what this guide is about. +이제, 트레이닝 및 평가에 대해 매우 낮은 레벨의 제어를 원한다면, +처음부터 직접 트레이닝 및 평가 루프를 작성해야 합니다. +이 가이드는 그것에 관한 것입니다. -## A first end-to-end example +## 첫 번째 엔드투엔드 예제 {#a-first-end-to-end-example} -Let's consider a simple MNIST model: +간단한 MNIST 모델을 살펴봅시다: ```python def get_model(): @@ -57,76 +63,78 @@ def get_model(): model = get_model() ``` -Let's train it using mini-batch gradient with a custom training loop. +커스텀 트레이닝 루프를 사용하여, 미니 배치 그래디언트로 모델을 트레이닝해 봅시다. -First, we're going to need an optimizer, a loss function, and a dataset: +먼저, 옵티마이저, 손실 함수, 데이터셋이 필요합니다: ```python -# Instantiate an optimizer. +# 옵티마이저 인스턴스화 optimizer = keras.optimizers.Adam(learning_rate=1e-3) -# Instantiate a loss function. +# 손실 함수 인스턴스화 loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True) -# Prepare the training dataset. +# 트레이닝 데이터셋 준비 batch_size = 32 (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() x_train = np.reshape(x_train, (-1, 784)) x_test = np.reshape(x_test, (-1, 784)) -# Reserve 10,000 samples for validation. +# 검증을 위해 10,000개의 샘플을 예약합니다. x_val = x_train[-10000:] y_val = y_train[-10000:] x_train = x_train[:-10000] y_train = y_train[:-10000] -# Prepare the training dataset. +# 트레이닝 데이터셋 준비 train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = train_dataset.shuffle(buffer_size=1024).batch(batch_size) -# Prepare the validation dataset. +# 검증 데이터셋 준비 val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val)) val_dataset = val_dataset.batch(batch_size) ``` -Calling a model inside a `GradientTape` scope enables you to retrieve the gradients of the trainable weights of the layer with respect to a loss value. Using an optimizer instance, you can use these gradients to update these variables (which you can retrieve using `model.trainable_weights`). +`GradientTape` scope 내에서 모델을 호출하면, +손실 값에 대해 레이어의 트레이닝 가능한 가중치의 그래디언트를 가져올 수 있습니다. +옵티마이저 인스턴스를 사용하여, +이 그래디언트를 사용해 (`model.trainable_weights`로 가져온) 이러한 변수를 +업데이트할 수 있습니다. -Here's our training loop, step by step: +다음은 단계별 트레이닝 루프입니다: -- We open a `for` loop that iterates over epochs -- For each epoch, we open a `for` loop that iterates over the dataset, in batches -- For each batch, we open a `GradientTape()` scope -- Inside this scope, we call the model (forward pass) and compute the loss -- Outside the scope, we retrieve the gradients of the weights of the model with regard to the loss -- Finally, we use the optimizer to update the weights of the model based on the gradients +- 에포크를 반복하는 `for` 루프를 엽니다. +- 각 에포크에 대해, 데이터셋을 배치 단위로 반복하는 `for` 루프를 엽니다. +- 각 배치에 대해, `GradientTape()` scope를 엽니다. +- 이 scope 내에서, 모델을 호출(순전파)하고 손실을 계산합니다. +- scope 외부에서, 손실에 대한 모델 가중치의 그래디언트를 가져옵니다. +- 마지막으로, 옵티마이저를 사용해 그래디언트를 기반으로 모델의 가중치를 업데이트합니다. ```python epochs = 3 for epoch in range(epochs): print(f"\nStart of epoch {epoch}") - # Iterate over the batches of the dataset. + # 데이터셋의 배치에 걸쳐 반복합니다. for step, (x_batch_train, y_batch_train) in enumerate(train_dataset): - # Open a GradientTape to record the operations run - # during the forward pass, which enables auto-differentiation. + # 순전파 동안 실행된 연산을 기록하기 위해, GradientTape를 엽니다. + # 이를 통해 자동 미분이 가능합니다. with tf.GradientTape() as tape: - # Run the forward pass of the layer. - # The operations that the layer applies - # to its inputs are going to be recorded - # on the GradientTape. - logits = model(x_batch_train, training=True) # Logits for this minibatch + # 레이어의 순전파를 실행합니다. + # 레이어가 입력에 적용하는 연산은 GradientTape에 기록됩니다. + logits = model(x_batch_train, training=True) # 이 미니배치에 대한 로짓 - # Compute the loss value for this minibatch. + # 이 미니배치에 대한 손실 값을 계산합니다. loss_value = loss_fn(y_batch_train, logits) - # Use the gradient tape to automatically retrieve - # the gradients of the trainable variables with respect to the loss. + # 그레디언트 테이프를 사용해 손실에 대한 + # 트레이닝 가능한 변수의 그래디언트를 자동으로 가져옵니다. grads = tape.gradient(loss_value, model.trainable_weights) - # Run one step of gradient descent by updating - # the value of the variables to minimize the loss. + # 그래디언트 하강법의 한 단계를 실행하여 + # 손실을 최소화하기 위해 변수의 값을 업데이트합니다. optimizer.apply(grads, model.trainable_weights) - # Log every 100 batches. + # 100 배치마다 로그를 출력합니다. if step % 100 == 0: print( f"Training loss (for 1 batch) at step {step}: {float(loss_value):.4f}" @@ -246,34 +254,38 @@ Seen so far: 48032 samples {{% /details %}} -## Low-level handling of metrics +## 메트릭의 낮은 레벨 다루기 {#low-level-handling-of-metrics} -Let's add metrics monitoring to this basic loop. +이 기본 루프에 메트릭 모니터링을 추가해 봅시다. -You can readily reuse the built-in metrics (or custom ones you wrote) in such training loops written from scratch. Here's the flow: +이렇게 처음부터 작성한 트레이닝 루프에서도, +빌트인 메트릭(또는 당신이 작성한 커스텀 메트릭)을 쉽게 재사용할 수 있습니다. +흐름은 다음과 같습니다: -- Instantiate the metric at the start of the loop -- Call `metric.update_state()` after each batch -- Call `metric.result()` when you need to display the current value of the metric -- Call `metric.reset_state()` when you need to clear the state of the metric (typically at the end of an epoch) +- 루프 시작 시 메트릭을 인스턴스화합니다. +- 각 배치 후에 `metric.update_state()`를 호출합니다. +- 메트릭의 현재 값을 표시해야 할 때, `metric.result()`를 호출합니다. +- 메트릭의 상태를 초기화해야 할 때(일반적으로 에포크가 끝날 때), + `metric.reset_state()`를 호출합니다. -Let's use this knowledge to compute `SparseCategoricalAccuracy` on training and validation data at the end of each epoch: +이 지식을 사용하여, +각 에포크가 끝날 때 트레이닝 및 검증 데이터에 대한 `SparseCategoricalAccuracy`를 계산해 보겠습니다: ```python -# Get a fresh model +# 새로운 모델 가져오기 model = get_model() -# Instantiate an optimizer to train the model. +# 모델을 트레이닝할 옵티마이저 인스턴스화 optimizer = keras.optimizers.Adam(learning_rate=1e-3) -# Instantiate a loss function. +# 손실 함수 인스턴스화 loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True) -# Prepare the metrics. +# 메트릭 준비 train_acc_metric = keras.metrics.SparseCategoricalAccuracy() val_acc_metric = keras.metrics.SparseCategoricalAccuracy() ``` -Here's our training & evaluation loop: +트레이닝 및 평가 루프는 다음과 같습니다. ```python epochs = 2 @@ -281,7 +293,7 @@ for epoch in range(epochs): print(f"\nStart of epoch {epoch}") start_time = time.time() - # Iterate over the batches of the dataset. + # 데이터셋의 배치에 걸쳐 반복합니다. for step, (x_batch_train, y_batch_train) in enumerate(train_dataset): with tf.GradientTape() as tape: logits = model(x_batch_train, training=True) @@ -289,27 +301,27 @@ for epoch in range(epochs): grads = tape.gradient(loss_value, model.trainable_weights) optimizer.apply(grads, model.trainable_weights) - # Update training metric. + # 트레이닝 메트릭 업데이트. train_acc_metric.update_state(y_batch_train, logits) - # Log every 100 batches. + # 100 배치마다 로그를 출력합니다. if step % 100 == 0: print( f"Training loss (for 1 batch) at step {step}: {float(loss_value):.4f}" ) print(f"Seen so far: {(step + 1) * batch_size} samples") - # Display metrics at the end of each epoch. + # 각 에포크가 끝날 때 메트릭을 표시합니다. train_acc = train_acc_metric.result() print(f"Training acc over epoch: {float(train_acc):.4f}") - # Reset training metrics at the end of each epoch + # 각 에포크가 끝날 때 트레이닝 메트릭을 초기화합니다. train_acc_metric.reset_state() - # Run a validation loop at the end of each epoch. + # 각 에포크가 끝날 때 검증 루프를 실행합니다. for x_batch_val, y_batch_val in val_dataset: val_logits = model(x_batch_val, training=False) - # Update val metrics + # 검증 메트릭 업데이트 val_acc_metric.update_state(y_batch_val, val_logits) val_acc = val_acc_metric.result() val_acc_metric.reset_state() @@ -399,13 +411,18 @@ Time taken: 43.49s {{% /details %}} -## Speeding-up your training step with [`tf.function`](https://www.tensorflow.org/api_docs/python/tf/function) +## [`tf.function`](https://www.tensorflow.org/api_docs/python/tf/function)으로 트레이닝 스텝 속도 향상시키기 {#tffunction} -The default runtime in TensorFlow is eager execution. As such, our training loop above executes eagerly. +TensorFlow의 기본 런타임은 즉시 실행 모드(eager execution)입니다. +따라서, 위의 트레이닝 루프는 즉시(eagerly) 실행됩니다. -This is great for debugging, but graph compilation has a definite performance advantage. Describing your computation as a static graph enables the framework to apply global performance optimizations. This is impossible when the framework is constrained to greedily execute one operation after another, with no knowledge of what comes next. +이는 디버깅에 유용하지만, 그래프 컴파일은 명확한 성능상의 이점을 가지고 있습니다. +계산을 정적 그래프로 설명하면, 프레임워크가 전역 성능 최적화를 적용할 수 있습니다. +프레임워크가 무엇이 다음에 올지 모르는 채로, +하나의 연산을 욕심껏 실행해야 하는 경우에는 불가능합니다. -You can compile into a static graph any function that takes tensors as input. Just add a `@tf.function` decorator on it, like this: +텐서를 입력으로 받는 모든 함수는 정적 그래프로 컴파일할 수 있습니다. +다음과 같이 `@tf.function` 데코레이터를 추가하기만 하면 됩니다: ```python @tf.function @@ -419,7 +436,7 @@ def train_step(x, y): return loss_value ``` -Let's do the same with the evaluation step: +평가 스텝에서도 동일한 작업을 해봅시다: ```python @tf.function @@ -428,7 +445,7 @@ def test_step(x, y): val_acc_metric.update_state(y, val_logits) ``` -Now, let's re-run our training loop with this compiled training step: +이제, 컴파일된 트레이닝 스텝을 사용하여 트레이닝 루프를 다시 실행해 봅시다: ```python epochs = 2 @@ -436,25 +453,25 @@ for epoch in range(epochs): print(f"\nStart of epoch {epoch}") start_time = time.time() - # Iterate over the batches of the dataset. + # 데이터셋의 배치에 걸쳐 반복합니다. for step, (x_batch_train, y_batch_train) in enumerate(train_dataset): loss_value = train_step(x_batch_train, y_batch_train) - # Log every 100 batches. + # 100 배치마다 로그를 출력합니다. if step % 100 == 0: print( f"Training loss (for 1 batch) at step {step}: {float(loss_value):.4f}" ) print(f"Seen so far: {(step + 1) * batch_size} samples") - # Display metrics at the end of each epoch. + # 각 에포크가 끝날 때 메트릭을 표시합니다. train_acc = train_acc_metric.result() print(f"Training acc over epoch: {float(train_acc):.4f}") - # Reset training metrics at the end of each epoch + # 각 에포크가 끝날 때 트레이닝 메트릭을 초기화합니다. train_acc_metric.reset_state() - # Run a validation loop at the end of each epoch. + # 각 에포크가 끝날 때 검증 루프를 실행합니다. for x_batch_val, y_batch_val in val_dataset: test_step(x_batch_val, y_batch_val) @@ -548,13 +565,16 @@ Time taken: 3.17s Much faster, isn't it? -## Low-level handling of losses tracked by the model +## 모델이 추적하는 손실의 낮은 레벨 다루기 {#low-level-handling-of-losses-tracked-by-the-model} -Layers & models recursively track any losses created during the forward pass by layers that call `self.add_loss(value)`. The resulting list of scalar loss values are available via the property `model.losses` at the end of the forward pass. +레이어와 모델은 순전파 중 `self.add_loss(value)`를 호출하는 레이어에 의해 생성된 모든 손실을 재귀적으로 추적합니다. +그 결과로 생성된 스칼라 손실 값들의 목록은 순전파가 끝난 후, +`model.losses` 속성을 통해 확인할 수 있습니다. -If you want to be using these loss components, you should sum them and add them to the main loss in your training step. +이러한 손실 요소들을 사용하고 싶다면, +이를 합산하여 트레이닝 스텝의 메인 손실에 추가해야 합니다. -Consider this layer, that creates an activity regularization loss: +다음은 활동 정규화 손실을 생성하는 레이어입니다: ```python class ActivityRegularizationLayer(keras.layers.Layer): @@ -563,12 +583,12 @@ class ActivityRegularizationLayer(keras.layers.Layer): return inputs ``` -Let's build a really simple model that uses it: +간단한 모델을 만들어 사용해 봅시다: ```python inputs = keras.Input(shape=(784,), name="digits") x = keras.layers.Dense(64, activation="relu")(inputs) -# Insert activity regularization as a layer +# activity 정규화 레이어 삽입 x = ActivityRegularizationLayer()(x) x = keras.layers.Dense(64, activation="relu")(x) outputs = keras.layers.Dense(10, name="predictions")(x) @@ -576,7 +596,7 @@ outputs = keras.layers.Dense(10, name="predictions")(x) model = keras.Model(inputs=inputs, outputs=outputs) ``` -Here's what our training step should look like now: +현재의 트레이닝 스텝은 다음과 같이 생겼습니다: ```python @tf.function @@ -584,7 +604,7 @@ def train_step(x, y): with tf.GradientTape() as tape: logits = model(x, training=True) loss_value = loss_fn(y, logits) - # Add any extra losses created during the forward pass. + # 순전파 동안 생성된 추가 손실을 더합니다. loss_value += sum(model.losses) grads = tape.gradient(loss_value, model.trainable_weights) optimizer.apply(grads, model.trainable_weights) @@ -592,27 +612,40 @@ def train_step(x, y): return loss_value ``` -## Summary +## 요약 {#summary} -Now you know everything there is to know about using built-in training loops and writing your own from scratch. +이제 빌트인 트레이닝 루프를 사용하는 방법과, +직접 작성하는 방법에 대해 알아야 할 모든 것을 알게 되었습니다. -To conclude, here's a simple end-to-end example that ties together everything you've learned in this guide: a DCGAN trained on MNIST digits. +마지막으로, 이 가이드에서 배운 모든 내용을 결합한 간단한 엔드투엔드 예제를 소개합니다: +MNIST 숫자에 대해 트레이닝된 DCGAN입니다. -## End-to-end example: a GAN training loop from scratch +## 엔드투엔드 예제: 처음부터 작성하는 GAN 트레이닝 루프 {#end-to-end-example-a-gan-training-loop-from-scratch} -You may be familiar with Generative Adversarial Networks (GANs). GANs can generate new images that look almost real, by learning the latent distribution of a training dataset of images (the "latent space" of the images). +생성적 적대 신경망(Generative Adversarial Networks, GANs)에 대해 들어본 적이 있을 것입니다. +GANs는 이미지의 트레이닝 데이터셋(이미지의 "잠재 공간")의 잠재 분포를 학습하여, +거의 실제처럼 보이는 새로운 이미지를 생성할 수 있습니다. -A GAN is made of two parts: a "generator" model that maps points in the latent space to points in image space, a "discriminator" model, a classifier that can tell the difference between real images (from the training dataset) and fake images (the output of the generator network). +GAN은 두 부분으로 구성됩니다: +잠재 공간의 점을 이미지 공간의 점으로 매핑하는 "생성자(generator)" 모델과, +실제 이미지(트레이닝 데이터셋에서 가져옴)와 가짜 이미지(생성기 네트워크의 출력)를 구분할 수 있는 분류기인 "판별자(discriminator)" 모델입니다. -A GAN training loop looks like this: +GAN의 트레이닝 루프는 다음과 같은 형태입니다: -1. Train the discriminator. - Sample a batch of random points in the latent space. - Turn the points into fake images via the "generator" model. - Get a batch of real images and combine them with the generated images. - Train the "discriminator" model to classify generated vs. real images. +1. 판별자 트레이닝: + - 잠재 공간에서 랜덤 포인트의 배치를 샘플링합니다. + - "생성자" 모델을 통해, 포인트을 가짜 이미지로 변환합니다. + - 실제 이미지의 배치를 얻고, 생성된 이미지와 결합합니다. + - "판별자" 모델을 트레이닝하여, 생성된 이미지와 실제 이미지를 분류합니다. +2. 생성자 트레이닝: + - 잠재 공간에서 랜덤 포인트를 샘플링합니다. + - "생성자" 네트워크를 통해 포인트를 가짜 이미지로 변환합니다. + - 실제 이미지의 배치를 얻고, 생성된 이미지와 결합합니다. + - "생성자" 모델을 트레이닝하여, 판별자를 "속이고" 가짜 이미지를 실제 이미지로 분류하게 만듭니다. -2. Train the generator. - Sample random points in the latent space. - Turn the points into fake images via the "generator" network. - Get a batch of real images and combine them with the generated images. - Train the "generator" model to "fool" the discriminator and classify the fake images as real. +GAN의 작동 방식에 대한 훨씬 더 자세한 개요는 [Deep Learning with Python](https://www.manning.com/books/deep-learning-with-python)을 참조하세요. -For a much more detailed overview of how GANs works, see [Deep Learning with Python](https://www.manning.com/books/deep-learning-with-python). - -Let's implement this training loop. First, create the discriminator meant to classify fake vs real digits: +이제 이 트레이닝 루프를 구현해 봅시다. 먼저, 가짜 숫자와 실제 숫자를 분류할 판별자를 생성합니다: ```python discriminator = keras.Sequential( @@ -657,7 +690,8 @@ Model: "discriminator" {{% /details %}} -Then let's create a generator network, that turns latent vectors into outputs of shape `(28, 28, 1)` (representing MNIST digits): +다음으로, 잠재 벡터를 `(28, 28, 1)` 모양의 출력(즉, MNIST 숫자)을 생성하는, +생성자 네트워크를 만들어 봅시다: ```python latent_dim = 128 @@ -665,7 +699,7 @@ latent_dim = 128 generator = keras.Sequential( [ keras.Input(shape=(latent_dim,)), - # We want to generate 128 coefficients to reshape into a 7x7x128 map + # 7x7x128 맵으로 reshape 하기 위해 128개의 계수를 생성합니다. keras.layers.Dense(7 * 7 * 128), keras.layers.LeakyReLU(negative_slope=0.2), keras.layers.Reshape((7, 7, 128)), @@ -679,47 +713,48 @@ generator = keras.Sequential( ) ``` -Here's the key bit: the training loop. As you can see it is quite straightforward. The training step function only takes 17 lines. +다음은 트레이닝 루프의 핵심 부분입니다. +보시다시피, 매우 간단합니다. 트레이닝 스텝 함수는 단 17줄로 구성되어 있습니다. ```python -# Instantiate one optimizer for the discriminator and another for the generator. +# 생성자와 생성자를 위한 옵티마이저 각각을 인스턴스화합니다. d_optimizer = keras.optimizers.Adam(learning_rate=0.0003) g_optimizer = keras.optimizers.Adam(learning_rate=0.0004) -# Instantiate a loss function. +# 손실 함수를 인스턴스화합니다. loss_fn = keras.losses.BinaryCrossentropy(from_logits=True) @tf.function def train_step(real_images): - # Sample random points in the latent space + # 잠재 공간에서 랜덤한 포인트를 샘플링합니다. random_latent_vectors = tf.random.normal(shape=(batch_size, latent_dim)) - # Decode them to fake images + # 샘플을 가짜 이미지로 디코딩합니다. generated_images = generator(random_latent_vectors) - # Combine them with real images + # 가짜 이미지와 실제 이미지를 결합합니다. combined_images = tf.concat([generated_images, real_images], axis=0) - # Assemble labels discriminating real from fake images + # 가짜 이미지와 실제 이미지를 구분하는 레이블을 조립합니다. labels = tf.concat( [tf.ones((batch_size, 1)), tf.zeros((real_images.shape[0], 1))], axis=0 ) - # Add random noise to the labels - important trick! + # 레이블에 랜덤 노이즈를 추가합니다 - 중요한 트릭입니다! labels += 0.05 * tf.random.uniform(labels.shape) - # Train the discriminator + # 판별자를 트레이닝합니다. with tf.GradientTape() as tape: predictions = discriminator(combined_images) d_loss = loss_fn(labels, predictions) grads = tape.gradient(d_loss, discriminator.trainable_weights) d_optimizer.apply(grads, discriminator.trainable_weights) - # Sample random points in the latent space + # 잠재 공간에서 랜덤한 포인트를 샘플링합니다. random_latent_vectors = tf.random.normal(shape=(batch_size, latent_dim)) - # Assemble labels that say "all real images" + # "모든 이미지는 진짜 (all real images)"라고 말하는 레이블을 조립합니다. misleading_labels = tf.zeros((batch_size, 1)) - # Train the generator (note that we should *not* update the weights - # of the discriminator)! + # 생성자를 트레이닝합니다. + # (여기서 판별자의 가중치는 *절대로* 업데이트하면 안 됩니다)! with tf.GradientTape() as tape: predictions = discriminator(generator(random_latent_vectors)) g_loss = loss_fn(misleading_labels, predictions) @@ -728,12 +763,12 @@ def train_step(real_images): return d_loss, g_loss, generated_images ``` -Let's train our GAN, by repeatedly calling `train_step` on batches of images. +이제 이미지 배치에 대해 `train_step`을 반복적으로 호출하여 우리의 GAN을 트레이닝해봅시다. -Since our discriminator and generator are convnets, you're going to want to run this code on a GPU. +판별자와 생성자가 컨볼루션 신경망이기 때문에, 이 코드를 GPU에서 실행하는 것이 좋습니다. ```python -# Prepare the dataset. We use both the training & test MNIST digits. +# 데이터셋 준비. 트레이닝 및 테스트 MNIST 숫자를 모두 사용합니다. batch_size = 64 (x_train, _), (x_test, _) = keras.datasets.mnist.load_data() all_digits = np.concatenate([x_train, x_test]) @@ -742,28 +777,28 @@ all_digits = np.reshape(all_digits, (-1, 28, 28, 1)) dataset = tf.data.Dataset.from_tensor_slices(all_digits) dataset = dataset.shuffle(buffer_size=1024).batch(batch_size) -epochs = 1 # In practice you need at least 20 epochs to generate nice digits. +epochs = 1 # 실제로는 멋진 숫자를 생성하려면 최소 20 에포크가 필요합니다. save_dir = "./" for epoch in range(epochs): print(f"\nStart epoch {epoch}") for step, real_images in enumerate(dataset): - # Train the discriminator & generator on one batch of real images. + # 한 배치의 실제 이미지에 대해 판별기 및 생성기를 트레이닝합니다. d_loss, g_loss, generated_images = train_step(real_images) - # Logging. + # 로깅. if step % 100 == 0: - # Print metrics + # 메트릭 출력 print(f"discriminator loss at step {step}: {d_loss:.2f}") print(f"adversarial loss at step {step}: {g_loss:.2f}") - # Save one generated image + # 생성된 이미지 중 하나를 저장합니다. img = keras.utils.array_to_img(generated_images[0] * 255.0, scale=False) img.save(os.path.join(save_dir, f"generated_img_{step}.png")) - # To limit execution time we stop after 10 steps. - # Remove the lines below to actually train the model! + # 실행 시간을 제한하기 위해 10 스텝 후에 중지합니다. + # 실제로 모델을 트레이닝하려면, 아래의 줄을 제거하세요! if step > 10: break ``` @@ -778,4 +813,4 @@ adversarial loss at step 0: 0.69 {{% /details %}} -That's it! You'll get nice-looking fake MNIST digits after just ~30s of training on the Colab GPU. +이제 끝났습니다! Colab GPU에서 약 30초 동안 트레이닝한 후, 멋진 가짜 MNIST 숫자를 얻을 수 있습니다. diff --git a/content/korean/docs/guides/writing_a_custom_training_loop_in_torch/_index.md b/content/korean/docs/guides/writing_a_custom_training_loop_in_torch/_index.md index bb832acc..5928c51f 100644 --- a/content/korean/docs/guides/writing_a_custom_training_loop_in_torch/_index.md +++ b/content/korean/docs/guides/writing_a_custom_training_loop_in_torch/_index.md @@ -1,6 +1,6 @@ --- -title: Writing a training loop from scratch in PyTorch -linkTitle: Writing a custom training loop in PyTorch +title: PyTorch에서 처음부터 트레이닝 루프 작성하기 +linkTitle: PyTorch 트레이닝 루프 toc: true weight: 10 type: docs @@ -11,19 +11,19 @@ type: docs **{{< t f_author >}}** [fchollet](https://twitter.com/fchollet) **{{< t f_date_created >}}** 2023/06/25 **{{< t f_last_modified >}}** 2023/06/25 -**{{< t f_description >}}** Writing low-level training & evaluation loops in PyTorch. +**{{< t f_description >}}** PyTorch에서 낮은 레벨 트레이닝 및 평가 루프 작성하기. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/writing_a_custom_training_loop_in_torch.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/writing_a_custom_training_loop_in_torch.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Setup +## 셋업 {#setup} ```python import os -# This guide can only be run with the torch backend. +# 이 가이드는 torch 백엔드에서만 실행할 수 있습니다. os.environ["KERAS_BACKEND"] = "torch" import torch @@ -31,29 +31,39 @@ import keras import numpy as np ``` -## Introduction +## 소개 {#introduction} -Keras provides default training and evaluation loops, `fit()` and `evaluate()`. Their usage is covered in the guide [Training & evaluation with the built-in methods]({{< relref "/docs/guides/training_with_built_in_methods" >}}). +Keras는 `fit()`과 `evaluate()`라는 기본 트레이닝 및 평가 루프를 제공합니다. +이들의 사용법은 ({{< titledRelref "/docs/guides/training_with_built_in_methods" >}}) 가이드에서 다룹니다. -If you want to customize the learning algorithm of your model while still leveraging the convenience of `fit()` (for instance, to train a GAN using `fit()`), you can subclass the `Model` class and implement your own `train_step()` method, which is called repeatedly during `fit()`. +모델의 학습 알고리즘을 커스터마이즈하면서도 `fit()`의 편리함을 활용하고 싶다면 +(예를 들어, `fit()`을 사용해 GAN을 트레이닝하려는 경우), +`Model` 클래스를 서브클래싱하고, +`fit()` 동안 반복적으로 호출되는 `train_step()` 메서드를 직접 구현할 수 있습니다. -Now, if you want very low-level control over training & evaluation, you should write your own training & evaluation loops from scratch. This is what this guide is about. +이제, 트레이닝 및 평가를 아주 낮은 레벨에서 제어하려면, +처음부터 직접 트레이닝 및 평가 루프를 작성해야 합니다. +이 가이드는 바로 이러한 방법에 대해 설명합니다. -## A first end-to-end example +## 첫 번째 엔드투엔드 예제 {#a-first-end-to-end-example} -To write a custom training loop, we need the following ingredients: +커스텀 트레이닝 루프를 작성하려면, 다음과 같은 요소들이 필요합니다: -- A model to train, of course. -- An optimizer. You could either use a `keras.optimizers` optimizer, or a native PyTorch optimizer from `torch.optim`. -- A loss function. You could either use a `keras.losses` loss, or a native PyTorch loss from `torch.nn`. -- A dataset. You could use any format: a [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset), a PyTorch `DataLoader`, a Python generator, etc. +- 물론, 트레이닝할 모델. +- 옵티마이저. + - `keras.optimizers`의 옵티마이저나 `torch.optim`의 파이토치 네이티브 옵티마이저 중 하나를 사용할 수 있습니다. +- 손실 함수. + - `keras.losses`의 손실 함수나 `torch.nn`의 파이토치 네이티브 손실 함수를 사용할 수 있습니다. +- 데이터셋. + - [`tf.data.Dataset`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset), 파이토치 `DataLoader`, 파이썬 생성기 등 어떤 형식도 사용할 수 있습니다. -Let's line them up. We'll use torch-native objects in each case – except, of course, for the Keras model. +이 요소들을 정리해보겠습니다. +각 경우에 대해 파이토치 네이티브 객체를 사용할 것입니다 — 단, 물론 Keras 모델은 제외하고요. -First, let's get the model and the MNIST dataset: +먼저, 모델과 MNIST 데이터셋을 가져와 보겠습니다: ```python -# Let's consider a simple MNIST model +# 간단한 MNIST 모델을 고려해 봅시다. def get_model(): inputs = keras.Input(shape=(784,), name="digits") x1 = keras.layers.Dense(64, activation="relu")(inputs) @@ -63,8 +73,8 @@ def get_model(): return model -# Create load up the MNIST dataset and put it in a torch DataLoader -# Prepare the training dataset. +# MNIST 데이터셋을 로드하고 이를 파이토치 DataLoader에 넣습니다 +# 트레이닝 데이터셋을 준비합니다. batch_size = 32 (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() x_train = np.reshape(x_train, (-1, 784)).astype("float32") @@ -72,13 +82,13 @@ x_test = np.reshape(x_test, (-1, 784)).astype("float32") y_train = keras.utils.to_categorical(y_train) y_test = keras.utils.to_categorical(y_test) -# Reserve 10,000 samples for validation. +# 10,000개의 샘플을 검증용으로 예약합니다. x_val = x_train[-10000:] y_val = y_train[-10000:] x_train = x_train[:-10000] y_train = y_train[:-10000] -# Create torch Datasets +# 파이토치 Datasets 생성 train_dataset = torch.utils.data.TensorDataset( torch.from_numpy(x_train), torch.from_numpy(y_train) ) @@ -86,7 +96,7 @@ val_dataset = torch.utils.data.TensorDataset( torch.from_numpy(x_val), torch.from_numpy(y_val) ) -# Create DataLoaders for the Datasets +# Datasets을 위한 DataLoaders 생성 train_dataloader = torch.utils.data.DataLoader( train_dataset, batch_size=batch_size, shuffle=True ) @@ -95,46 +105,52 @@ val_dataloader = torch.utils.data.DataLoader( ) ``` -Next, here's our PyTorch optimizer and our PyTorch loss function: +다음은 PyTorch 옵티마이저와 PyTorch 손실 함수입니다: ```python -# Instantiate a torch optimizer +# 파이토치 옵티마이저 인스턴스화 model = get_model() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) -# Instantiate a torch loss function +# 파이토치 손실 함수 인스턴스화 loss_fn = torch.nn.CrossEntropyLoss() ``` -Let's train our model using mini-batch gradient with a custom training loop. +이제 커스텀 트레이닝 루프를 사용하여, 미니 배치 그래디언트로 모델을 트레이닝해봅시다. -Calling `loss.backward()` on a loss tensor triggers backpropagation. Once that's done, your optimizer is magically aware of the gradients for each variable and can update its variables, which is done via `optimizer.step()`. Tensors, variables, optimizers are all interconnected to one another via hidden global state. Also, don't forget to call `model.zero_grad()` before `loss.backward()`, or you won't get the right gradients for your variables. +손실 텐서에 대해 `loss.backward()`를 호출하면 역전파가 실행됩니다. +이것이 완료되면, 당신의 옵티마이저는 각 변수에 대한 그래디언트를 마술처럼 알 수 있고, +이를 통해 `optimizer.step()`를 사용하여 변수들을 업데이트할 수 있습니다. +텐서, 변수, 옵티마이저는 모두 숨겨진 전역 상태를 통해 서로 연결되어 있습니다. +또한 `loss.backward()`를 호출하기 전에, +`model.zero_grad()`를 호출하는 것을 잊지 마세요. +그렇지 않으면, 변수에 대한 올바른 그래디언트를 얻을 수 없습니다. -Here's our training loop, step by step: +다음은 단계별로 설명한, 트레이닝 루프입니다: -- We open a `for` loop that iterates over epochs -- For each epoch, we open a `for` loop that iterates over the dataset, in batches -- For each batch, we call the model on the input data to retrieve the predictions, then we use them to compute a loss value -- We call `loss.backward()` to -- Outside the scope, we retrieve the gradients of the weights of the model with regard to the loss -- Finally, we use the optimizer to update the weights of the model based on the gradients +- 에포크를 반복하는 `for` 루프를 엽니다. +- 각 에포크마다, 데이터셋을 배치 단위로 반복하는 `for` 루프를 엽니다. +- 각 배치마다, 입력 데이터를 모델에 전달하여 예측값을 얻은 다음, 이를 사용해 손실 값을 계산합니다. +- `loss.backward()`를 호출합니다. +- scope 바깥에서, 손실에 대한 모델 가중치의 그래디언트를 가져옵니다. +- 마지막으로, 옵티마이저를 사용하여 그래디언트를 기반으로 모델의 가중치를 업데이트합니다. ```python epochs = 3 for epoch in range(epochs): for step, (inputs, targets) in enumerate(train_dataloader): - # Forward pass + # 순전파 (Forward pass) logits = model(inputs) loss = loss_fn(logits, targets) - # Backward pass + # 역전파 (Backward pass) model.zero_grad() loss.backward() - # Optimizer variable updates + # 옵티마이저 변수 업데이트 optimizer.step() - # Log every 100 batches. + # # 100개 배치마다 로그 출력. if step % 100 == 0: print( f"Training loss (for 1 batch) at step {step}: {loss.detach().numpy():.4f}" @@ -245,14 +261,17 @@ Seen so far: 48032 samples {{% /details %}} -As an alternative, let's look at what the loop looks like when using a Keras optimizer and a Keras loss function. +다른 방법으로, Keras 옵티마이저와 Keras 손실 함수를 사용할 때의 루프가 어떻게 보이는지 살펴보겠습니다. -Important differences: +중요한 차이점: -- You retrieve the gradients for the variables via `v.value.grad`, called on each trainable variable. -- You update your variables via `optimizer.apply()`, which must be called in a `torch.no_grad()` scope. +- 각 트레이닝 가능한 변수에 대해 호출되는, `v.value.grad`를 통해 변수의 그래디언트를 검색합니다. +- `optimizer.apply()`를 통해 변수들을 업데이트하는데, 이는 반드시 `torch.no_grad()` scope 내에서 호출되어야 합니다. -**Also, a big gotcha:** while all NumPy/TensorFlow/JAX/Keras APIs as well as Python `unittest` APIs use the argument order convention `fn(y_true, y_pred)` (reference values first, predicted values second), PyTorch actually uses `fn(y_pred, y_true)` for its losses. So make sure to invert the order of `logits` and `targets`. +**또한 중요한 주의사항:** NumPy/TensorFlow/JAX/Keras API뿐만 아니라 Python의 `unittest` API는 모두, +`fn(y_true, y_pred)` (참고값이 먼저, 예측값이 두 번째) 순서의 인자 순서를 사용하지만, +PyTorch는 실제로 손실에 대해 `fn(y_pred, y_true)` 순서를 사용합니다. +따라서, `logits`와 `targets`의 순서를 바꿔야 합니다. ```python model = get_model() @@ -262,24 +281,24 @@ loss_fn = keras.losses.CategoricalCrossentropy(from_logits=True) for epoch in range(epochs): print(f"\nStart of epoch {epoch}") for step, (inputs, targets) in enumerate(train_dataloader): - # Forward pass + # 순전파 (Forward pass) logits = model(inputs) loss = loss_fn(targets, logits) - # Backward pass + # 역전파 (Backward pass) model.zero_grad() trainable_weights = [v for v in model.trainable_weights] - # Call torch.Tensor.backward() on the loss to compute gradients - # for the weights. + # 손실에 대해 torch.Tensor.backward()를 호출하여 + # 가중치에 대한 그래디언트를 계산합니다. loss.backward() gradients = [v.value.grad for v in trainable_weights] - # Update weights + # 가중치 업데이트 with torch.no_grad(): optimizer.apply(gradients, trainable_weights) - # Log every 100 batches. + # 100개 배치마다 로그 출력. if step % 100 == 0: print( f"Training loss (for 1 batch) at step {step}: {loss.detach().numpy():.4f}" @@ -399,77 +418,80 @@ Seen so far: 48032 samples {{% /details %}} -## Low-level handling of metrics +## 메트릭의 낮은 레벨 다루기 {#low-level-handling-of-metrics} -Let's add metrics monitoring to this basic training loop. +이 기본 트레이닝 루프에 메트릭 모니터링을 추가해봅시다. -You can readily reuse built-in Keras metrics (or custom ones you wrote) in such training loops written from scratch. Here's the flow: +이와 같이 처음부터 작성한 트레이닝 루프에서, +Keras의 빌트인 메트릭(또는 직접 작성한 커스텀 메트릭)을 쉽게 재사용할 수 있습니다. +흐름은 다음과 같습니다: -- Instantiate the metric at the start of the loop -- Call `metric.update_state()` after each batch -- Call `metric.result()` when you need to display the current value of the metric -- Call `metric.reset_state()` when you need to clear the state of the metric (typically at the end of an epoch) +- 루프 시작 시 메트릭 인스턴스화 +- 각 배치 후 `metric.update_state()` 호출 +- 메트릭의 현재 값을 표시해야 할 때, `metric.result()` 호출 +- 메트릭의 상태를 초기화해야 할 때(일반적으로 에포크가 끝날 때), `metric.reset_state()` 호출 -Let's use this knowledge to compute `CategoricalAccuracy` on training and validation data at the end of each epoch: +이 지식을 사용하여 각 에포크가 끝날 때, +트레이닝 및 검증 데이터에 대해 `CategoricalAccuracy`를 계산해봅시다: ```python -# Get a fresh model +# 새로운 모델 가져오기 model = get_model() -# Instantiate an optimizer to train the model. +# 모델을 트레이닝할 옵티마이저 인스턴스화. optimizer = keras.optimizers.Adam(learning_rate=1e-3) -# Instantiate a loss function. +# 손실 함수 인스턴스화. loss_fn = keras.losses.CategoricalCrossentropy(from_logits=True) -# Prepare the metrics. +# 메트릭 준비. train_acc_metric = keras.metrics.CategoricalAccuracy() val_acc_metric = keras.metrics.CategoricalAccuracy() ``` -Here's our training & evaluation loop: +다음은 우리의 트레이닝 및 평가 루프입니다: ```python for epoch in range(epochs): print(f"\nStart of epoch {epoch}") for step, (inputs, targets) in enumerate(train_dataloader): - # Forward pass + # 순전파 (Forward pass) logits = model(inputs) loss = loss_fn(targets, logits) - # Backward pass + # 역전파 (Backward pass) model.zero_grad() trainable_weights = [v for v in model.trainable_weights] - # Call torch.Tensor.backward() on the loss to compute gradients - # for the weights. + # 손실에 대해 torch.Tensor.backward()를 호출하여 + # 가중치에 대한 그래디언트를 계산합니다. loss.backward() gradients = [v.value.grad for v in trainable_weights] - # Update weights + # 가중치 업데이트 with torch.no_grad(): optimizer.apply(gradients, trainable_weights) - # Update training metric. + # 트레이닝 메트릭 업데이트. train_acc_metric.update_state(targets, logits) - # Log every 100 batches. + # 100개 배치마다 로그 출력. if step % 100 == 0: print( f"Training loss (for 1 batch) at step {step}: {loss.detach().numpy():.4f}" ) print(f"Seen so far: {(step + 1) * batch_size} samples") - # Display metrics at the end of each epoch. + # 각 에포크가 끝날 때 메트릭 표시. train_acc = train_acc_metric.result() print(f"Training acc over epoch: {float(train_acc):.4f}") - # Reset training metrics at the end of each epoch + # 각 에포크가 끝날 때 트레이닝 메트릭 초기화 train_acc_metric.reset_state() - # Run a validation loop at the end of each epoch. + # 각 에포크가 끝날 때 검증 루프 실행. for x_batch_val, y_batch_val in val_dataloader: val_logits = model(x_batch_val, training=False) - # Update val metrics + # 검증 메트릭 업데이트 val_acc_metric.update_state(y_batch_val, val_logits) val_acc = val_acc_metric.result() val_acc_metric.reset_state() @@ -594,13 +616,14 @@ Validation acc: 0.9356 {{% /details %}} -## Low-level handling of losses tracked by the model +## 모델에 의해 추적되는 손실의 낮은 레벨 다루기 {#low-level-handling-of-losses-tracked-by-the-model} -Layers & models recursively track any losses created during the forward pass by layers that call `self.add_loss(value)`. The resulting list of scalar loss values are available via the property `model.losses` at the end of the forward pass. +레이어와 모델은 순전파 중 `self.add_loss(value)`를 호출하는 레이어에 의해 생성된 모든 손실을 재귀적으로 추적합니다. +이렇게 생성된 스칼라 손실 값 목록은 순전파가 끝날 때 `model.losses` 속성을 통해 확인할 수 있습니다. -If you want to be using these loss components, you should sum them and add them to the main loss in your training step. +이러한 손실 구성 요소를 사용하려면, 이를 합산하여 트레이닝 스텝에서 메인 손실에 추가해야 합니다. -Consider this layer, that creates an activity regularization loss: +다음은 activity 정규화 손실을 생성하는 레이어를 고려해봅시다: ```python class ActivityRegularizationLayer(keras.layers.Layer): @@ -609,12 +632,12 @@ class ActivityRegularizationLayer(keras.layers.Layer): return inputs ``` -Let's build a really simple model that uses it: +이 레이어를 사용하는 정말 간단한 모델을 만들어 봅시다: ```python inputs = keras.Input(shape=(784,), name="digits") x = keras.layers.Dense(64, activation="relu")(inputs) -# Insert activity regularization as a layer +# 레이어로서 activity 정규화 삽입 x = ActivityRegularizationLayer()(x) x = keras.layers.Dense(64, activation="relu")(x) outputs = keras.layers.Dense(10, name="predictions")(x) @@ -622,64 +645,64 @@ outputs = keras.layers.Dense(10, name="predictions")(x) model = keras.Model(inputs=inputs, outputs=outputs) ``` -Here's what our training loop should look like now: +이제 우리의 트레이닝 루프는 다음과 같이 되어야 합니다: ```python -# Get a fresh model +# 새로운 모델 가져오기 model = get_model() -# Instantiate an optimizer to train the model. +# 모델을 트레이닝할 옵티마이저 인스턴스화. optimizer = keras.optimizers.Adam(learning_rate=1e-3) -# Instantiate a loss function. +# 손실 함수 인스턴스화. loss_fn = keras.losses.CategoricalCrossentropy(from_logits=True) -# Prepare the metrics. +# 메트릭 준비. train_acc_metric = keras.metrics.CategoricalAccuracy() val_acc_metric = keras.metrics.CategoricalAccuracy() for epoch in range(epochs): print(f"\nStart of epoch {epoch}") for step, (inputs, targets) in enumerate(train_dataloader): - # Forward pass + # 순전파 (Forward pass) logits = model(inputs) loss = loss_fn(targets, logits) if model.losses: loss = loss + torch.sum(*model.losses) - # Backward pass + # 역전파 (Backward pass) model.zero_grad() trainable_weights = [v for v in model.trainable_weights] - # Call torch.Tensor.backward() on the loss to compute gradients - # for the weights. + # 손실에 대해 torch.Tensor.backward()를 호출하여 + # 가중치에 대한 그래디언트를 계산합니다. loss.backward() gradients = [v.value.grad for v in trainable_weights] - # Update weights + # 가중치 업데이트 with torch.no_grad(): optimizer.apply(gradients, trainable_weights) - # Update training metric. + # 트레이닝 메트릭 업데이트. train_acc_metric.update_state(targets, logits) - # Log every 100 batches. + # 100개 배치마다 로그 출력. if step % 100 == 0: print( f"Training loss (for 1 batch) at step {step}: {loss.detach().numpy():.4f}" ) print(f"Seen so far: {(step + 1) * batch_size} samples") - # Display metrics at the end of each epoch. + # 각 에포크가 끝날 때 메트릭 표시. train_acc = train_acc_metric.result() print(f"Training acc over epoch: {float(train_acc):.4f}") - # Reset training metrics at the end of each epoch + # 각 에포크가 끝날 때 트레이닝 메트릭 초기화 train_acc_metric.reset_state() - # Run a validation loop at the end of each epoch. + # 각 에포크가 끝날 때 검증 루프 실행. for x_batch_val, y_batch_val in val_dataloader: val_logits = model(x_batch_val, training=False) - # Update val metrics + # 검증 메트릭 업데이트 val_acc_metric.update_state(y_batch_val, val_logits) val_acc = val_acc_metric.result() val_acc_metric.reset_state() @@ -804,4 +827,4 @@ Validation acc: 0.9200 {{% /details %}} -That's it! +이것으로 끝입니다! diff --git a/content/korean/docs/guides/writing_your_own_callbacks/_index.md b/content/korean/docs/guides/writing_your_own_callbacks/_index.md index 530512ed..d66ca3b5 100644 --- a/content/korean/docs/guides/writing_your_own_callbacks/_index.md +++ b/content/korean/docs/guides/writing_your_own_callbacks/_index.md @@ -1,6 +1,6 @@ --- -title: Writing your own callbacks -linkTitle: Writing your own callbacks +title: 당신만의 커스텀 콜백 작성하기 +linkTitle: 커스텀 콜백 작성 toc: true weight: 13 type: docs @@ -8,77 +8,85 @@ type: docs {{< keras/original checkedAt="2024-11-18" >}} -**Authors:** Rick Chao, Francois Chollet +**{{< t f_author >}}** Rick Chao, Francois Chollet **{{< t f_date_created >}}** 2019/03/20 **{{< t f_last_modified >}}** 2023/06/25 -**{{< t f_description >}}** Complete guide to writing new Keras callbacks. +**{{< t f_description >}}** Keras에서 새로운 콜백을 작성하는 완벽 가이드. {{< cards cols="2" >}} {{< card link="https://colab.research.google.com/github/keras-team/keras-io/blob/master/guides/ipynb/writing_your_own_callbacks.ipynb" title="Colab" tag="Colab" tagType="warning">}} {{< card link="https://github.com/keras-team/keras-io/blob/master/guides/writing_your_own_callbacks.py" title="GitHub" tag="GitHub">}} {{< /cards >}} -## Introduction +## 소개 {#introduction} -A callback is a powerful tool to customize the behavior of a Keras model during training, evaluation, or inference. Examples include [`keras.callbacks.TensorBoard`]({{< relref "/docs/api/callbacks/tensorboard#tensorboard-class" >}}) to visualize training progress and results with TensorBoard, or [`keras.callbacks.ModelCheckpoint`]({{< relref "/docs/api/callbacks/model_checkpoint#modelcheckpoint-class" >}}) to periodically save your model during training. +콜백은 Keras 모델의 트레이닝, 평가, 또는 추론 중에 동작을 커스터마이즈할 수 있는 강력한 도구입니다. +예를 들어, [`keras.callbacks.TensorBoard`]({{< relref "/docs/api/callbacks/tensorboard#tensorboard-class" >}})는 TensorBoard로 트레이닝 진행 상황과 결과를 시각화하고, +[`keras.callbacks.ModelCheckpoint`]({{< relref "/docs/api/callbacks/model_checkpoint#modelcheckpoint-class" >}})는 트레이닝 중 주기적으로 모델을 저장합니다. -In this guide, you will learn what a Keras callback is, what it can do, and how you can build your own. We provide a few demos of simple callback applications to get you started. +이 가이드에서는 Keras 콜백이 무엇인지, 무엇을 할 수 있는지, +그리고 어떻게 직접 콜백을 작성할 수 있는지 배우게 됩니다. +간단한 콜백 애플리케이션의 예시를 제공하여 시작할 수 있도록 도와드립니다. -## Setup +## 셋업 {#setup} ```python import numpy as np import keras ``` -## Keras callbacks overview +## Keras 콜백 개요 {#keras-callbacks-overview} -All callbacks subclass the [`keras.callbacks.Callback`]({{< relref "/docs/api/callbacks/base_callback#callback-class" >}}) class, and override a set of methods called at various stages of training, testing, and predicting. Callbacks are useful to get a view on internal states and statistics of the model during training. +모든 콜백은 [`keras.callbacks.Callback`]({{< relref "/docs/api/callbacks/base_callback#callback-class" >}}) 클래스를 서브클래싱하며, +트레이닝, 테스트, 예측의 다양한 단계에서 호출되는 일련의 메서드를 오버라이드합니다. +콜백은 트레이닝 중에 모델의 내부 상태와 통계를 확인하는데 유용합니다. -You can pass a list of callbacks (as the keyword argument `callbacks`) to the following model methods: +다음 모델 메서드에 `callbacks`라는 키워드 인자로 콜백 리스트를 전달할 수 있습니다: - `keras.Model.fit()` - `keras.Model.evaluate()` - `keras.Model.predict()` -## An overview of callback methods +## 콜백 메서드 개요 {#an-overview-of-callback-methods} -### Global methods +### Global 메서드 {#global-methods} -#### `on_(train|test|predict)_begin(self, logs=None)` +#### `on_(train|test|predict)_begin(self, logs=None)` {#on_traintestpredict_beginself-logsnone} -Called at the beginning of `fit`/`evaluate`/`predict`. +`fit`/`evaluate`/`predict` 시작 시 호출됩니다. -#### `on_(train|test|predict)_end(self, logs=None)` +#### `on_(train|test|predict)_end(self, logs=None)` {#on_traintestpredict_endself-logsnone} -Called at the end of `fit`/`evaluate`/`predict`. +`fit`/`evaluate`/`predict` 종료 시 호출됩니다. -### Batch-level methods for training/testing/predicting +### 트레이닝/테스트/예측을 위한 배치 레벨 메서드 {#batch-level-methods-for-trainingtestingpredicting} -#### `on_(train|test|predict)_batch_begin(self, batch, logs=None)` +#### `on_(train|test|predict)_batch_begin(self, batch, logs=None)` {#on_traintestpredict_batch_beginself-batch-logsnone} -Called right before processing a batch during training/testing/predicting. +트레이닝/테스트/예측 중 배치 처리를 시작하기 직전에 호출됩니다. -#### `on_(train|test|predict)_batch_end(self, batch, logs=None)` +#### `on_(train|test|predict)_batch_end(self, batch, logs=None)` {#on_traintestpredict_batch_endself-batch-logsnone} -Called at the end of training/testing/predicting a batch. Within this method, `logs` is a dict containing the metrics results. +배치 트레이닝/테스트/예측이 완료된 후 호출됩니다. +이 메서드 내에서 `logs`는 메트릭 결과를 포함하는 딕셔너리입니다. -### Epoch-level methods (training only) +### 에포크 레벨 메서드 (트레이닝 전용) {#epoch-level-methods-training-only} -#### `on_epoch_begin(self, epoch, logs=None)` +#### `on_epoch_begin(self, epoch, logs=None)` {#on_epoch_beginself-epoch-logsnone} -Called at the beginning of an epoch during training. +트레이닝 중 에포크가 시작될 때 호출됩니다. -#### `on_epoch_end(self, epoch, logs=None)` +#### `on_epoch_end(self, epoch, logs=None)` {#on_epoch_endself-epoch-logsnone} -Called at the end of an epoch during training. +트레이닝 중 에포크가 끝날 때 호출됩니다. -## A basic example +## 기본 예제 {#a-basic-example} -Let's take a look at a concrete example. To get started, let's import tensorflow and define a simple Sequential Keras model: +구체적인 예시를 살펴보겠습니다. +먼저, TensorFlow를 임포트하고 간단한 Sequential Keras 모델을 정의해봅시다: ```python -# Define the Keras model to add callbacks to +# 콜백을 추가할 Keras 모델 정의 def get_model(): model = keras.Sequential() model.add(keras.layers.Dense(1)) @@ -90,28 +98,28 @@ def get_model(): return model ``` -Then, load the MNIST data for training and testing from Keras datasets API: +그런 다음, Keras 데이터셋 API를 사용하여 트레이닝 및 테스트용 MNIST 데이터를 로드합니다: ```python -# Load example MNIST data and pre-process it +# 예시 MNIST 데이터를 로드하고 전처리합니다. (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() x_train = x_train.reshape(-1, 784).astype("float32") / 255.0 x_test = x_test.reshape(-1, 784).astype("float32") / 255.0 -# Limit the data to 1000 samples +# 데이터를 1000개의 샘플로 제한합니다. x_train = x_train[:1000] y_train = y_train[:1000] x_test = x_test[:1000] y_test = y_test[:1000] ``` -Now, define a simple custom callback that logs: +이제, 다음을 로그하는 간단한 커스텀 콜백을 정의해봅시다: -- When `fit`/`evaluate`/`predict` starts & ends -- When each epoch starts & ends -- When each training batch starts & ends -- When each evaluation (test) batch starts & ends -- When each inference (prediction) batch starts & ends +- `fit`/`evaluate`/`predict`가 시작하고 끝날 때 +- 각 에포크가 시작하고 끝날 때 +- 각 트레이닝 배치가 시작하고 끝날 때 +- 각 평가(테스트) 배치가 시작하고 끝날 때 +- 각 추론(예측) 배치가 시작하고 끝날 때 ```python class CustomCallback(keras.callbacks.Callback): @@ -172,7 +180,7 @@ class CustomCallback(keras.callbacks.Callback): print("...Predicting: end of batch {}; got log keys: {}".format(batch, keys)) ``` -Let's try it out: +한번 실행해봅시다: ```python model = get_model() @@ -259,9 +267,10 @@ Stop predicting; got log keys: [] {{% /details %}} -### Usage of `logs` dict +### `logs` 딕셔너리의 사용 {#usage-of-logs-dict} -The `logs` dict contains the loss value, and all the metrics at the end of a batch or epoch. Example includes the loss and mean absolute error. +`logs` 딕셔너리는 배치나 에포크가 끝날 때 손실 값과 모든 메트릭을 포함합니다. +예시로는 손실 값과 평균 절대 오차(mean absolute error)가 있습니다. ```python class LossAndErrorPrintingCallback(keras.callbacks.Callback): @@ -336,50 +345,54 @@ Up to batch 7, the average loss is 4.72. {{% /details %}} -## Usage of `self.model` attribute +## `self.model` 속성의 사용 {#usage-of-selfmodel-attribute} -In addition to receiving log information when one of their methods is called, callbacks have access to the model associated with the current round of training/evaluation/inference: `self.model`. +메서드가 호출될 때 로그 정보를 받는 것 외에도, +콜백은 현재 트레이닝/평가/추론 라운드와 연결된 모델인 `self.model`에 접근할 수 있습니다. -Here are a few of the things you can do with `self.model` in a callback: +콜백에서 `self.model`을 사용하여 할 수 있는 몇 가지 예는 다음과 같습니다: -- Set `self.model.stop_training = True` to immediately interrupt training. -- Mutate hyperparameters of the optimizer (available as `self.model.optimizer`), such as `self.model.optimizer.learning_rate`. -- Save the model at period intervals. -- Record the output of `model.predict()` on a few test samples at the end of each epoch, to use as a sanity check during training. -- Extract visualizations of intermediate features at the end of each epoch, to monitor what the model is learning over time. -- etc. +- `self.model.stop_training = True`를 설정하여, 트레이닝을 즉시 중단할 수 있습니다. +- 옵티마이저(`self.model.optimizer`로 사용가능)의 하이퍼파라미터를 변경할 수 있습니다. (예: `self.model.optimizer.learning_rate`) +- 주기적으로 모델을 저장할 수 있습니다. +- 에포크가 끝날 때 몇 가지 테스트 샘플에 대해 `model.predict()`의 출력을 기록하여, 트레이닝 중 검증(sanity check)할 수 있습니다. +- 에포크가 끝날 때 중간 특성의 시각화를 추출하여, 시간에 걸쳐 모델이 학습하는 내용을 모니터링할 수 있습니다. +- 기타 등등. -Let's see this in action in a couple of examples. +몇 가지 예시를 통해 이를 실제로 확인해보겠습니다. -## Examples of Keras callback applications +## Keras 콜백 애플리케이션 예시 {#examples-of-keras-callback-applications} -### Early stopping at minimum loss +### 최소 손실에서의 조기 종료 {#early-stopping-at-minimum-loss} -This first example shows the creation of a `Callback` that stops training when the minimum of loss has been reached, by setting the attribute `self.model.stop_training` (boolean). Optionally, you can provide an argument `patience` to specify how many epochs we should wait before stopping after having reached a local minimum. +첫 번째 예시는 손실의 최소값에 도달하면 트레이닝을 중지하는 `Callback`을 생성하는 방법을 보여줍니다. +이때 `self.model.stop_training` (boolean) 속성을 설정합니다. +선택적으로, `patience`라는 인자를 제공하여 로컬 최소값에 도달한 후, +몇 에포크 동안 대기한 뒤 트레이닝을 중지할지 지정할 수 있습니다. -[`keras.callbacks.EarlyStopping`]({{< relref "/docs/api/callbacks/early_stopping#earlystopping-class" >}}) provides a more complete and general implementation. +[`keras.callbacks.EarlyStopping`]({{< relref "/docs/api/callbacks/early_stopping#earlystopping-class" >}})는 더 완전하고 일반적인 구현을 제공합니다. ```python class EarlyStoppingAtMinLoss(keras.callbacks.Callback): - """Stop training when the loss is at its min, i.e. the loss stops decreasing. + """손실이 최소값에 도달하면 트레이닝을 중지합니다, 즉 손실이 더 이상 감소하지 않을 때. Arguments: - patience: Number of epochs to wait after min has been hit. After this - number of no improvement, training stops. + patience: 최소값에 도달한 후 대기할 에포크 수. + 개선되지 않은 상태에서 지정된 에포크 수가 지나면, 트레이닝이 중지됩니다. """ def __init__(self, patience=0): super().__init__() self.patience = patience - # best_weights to store the weights at which the minimum loss occurs. + # 최소 손실이 발생한 지점에서의 가중치를 저장하기 위한 best_weights. self.best_weights = None def on_train_begin(self, logs=None): - # The number of epoch it has waited when loss is no longer minimum. + # 손실이 더 이상 최소가 아닐 때 기다린 에포크 수. self.wait = 0 - # The epoch the training stops at. + # 트레이닝이 중지되는 에포크. self.stopped_epoch = 0 - # Initialize the best as infinity. + # 초기값을 무한대로 설정. self.best = np.inf def on_epoch_end(self, epoch, logs=None): @@ -387,7 +400,7 @@ class EarlyStoppingAtMinLoss(keras.callbacks.Callback): if np.less(current, self.best): self.best = current self.wait = 0 - # Record the best weights if current results is better (less). + # 현재 결과가 더 좋으면(작으면) 최상의 가중치를 기록합니다. self.best_weights = self.model.get_weights() else: self.wait += 1 @@ -475,20 +488,18 @@ Epoch 3: early stopping {{% /details %}} -### Learning rate scheduling +### 학습률 스케줄링 {#learning-rate-scheduling} -In this example, we show how a custom Callback can be used to dynamically change the learning rate of the optimizer during the course of training. +이 예시에서는, 커스텀 콜백을 사용하여 트레이닝 과정에서 옵티마이저의 학습률을 동적으로 변경하는 방법을 보여줍니다. -See `callbacks.LearningRateScheduler` for a more general implementations. +일반적인 구현을 위해서는 `callbacks.LearningRateScheduler`를 참고하세요. ```python class CustomLearningRateScheduler(keras.callbacks.Callback): - """Learning rate scheduler which sets the learning rate according to schedule. + """스케줄에 따라 학습률을 설정하는 학습률 스케줄러. Arguments: - schedule: a function that takes an epoch index - (integer, indexed from 0) and current learning rate - as inputs and returns a new learning rate as output (float). + schedule: 에포크 인덱스(정수, 0부터 시작)와 현재 학습률을 입력으로 받아 새로운 학습률(float)을 출력으로 반환하는 함수. """ def __init__(self, schedule): @@ -498,17 +509,17 @@ class CustomLearningRateScheduler(keras.callbacks.Callback): def on_epoch_begin(self, epoch, logs=None): if not hasattr(self.model.optimizer, "learning_rate"): raise ValueError('Optimizer must have a "learning_rate" attribute.') - # Get the current learning rate from model's optimizer. + # 모델의 옵티마이저에서 현재 학습률을 가져옵니다. lr = self.model.optimizer.learning_rate - # Call schedule function to get the scheduled learning rate. + # 스케줄 함수 호출하여 스케줄된 학습률을 가져옵니다. scheduled_lr = self.schedule(epoch, lr) - # Set the value back to the optimizer before this epoch starts + # 이 에포크가 시작되기 전에 옵티마이저에 값 설정. self.model.optimizer.learning_rate = scheduled_lr print(f"\nEpoch {epoch}: Learning rate is {float(np.array(scheduled_lr))}.") LR_SCHEDULE = [ - # (epoch to start, learning rate) tuples + # (시작 할 에포크, 학습률) 튜플 (3, 0.05), (6, 0.01), (9, 0.005), @@ -517,7 +528,7 @@ LR_SCHEDULE = [ def lr_schedule(epoch, lr): - """Helper function to retrieve the scheduled learning rate based on epoch.""" + """에포크에 기반하여 스케줄된 학습률을 가져오는 헬퍼 함수.""" if epoch < LR_SCHEDULE[0][0] or epoch > LR_SCHEDULE[-1][0]: return lr for i in range(len(LR_SCHEDULE)): @@ -861,6 +872,7 @@ The average loss for epoch 14 is 11.50 and mean absolute error is 2.06. {{% /details %}} -### Built-in Keras callbacks +### Keras 내장 콜백 {#built-in-keras-callbacks} -Be sure to check out the existing Keras callbacks by reading the [API docs]({{< relref "/docs/api/callbacks" >}}). Applications include logging to CSV, saving the model, visualizing metrics in TensorBoard, and a lot more! +현재 제공하는 Keras 콜백들을 확인하려면 [API 문서]({{< relref "/docs/api/callbacks" >}})를 참고하세요. +애플리케이션에는 CSV에 로그 기록, 모델 저장, TensorBoard에서 메트릭 시각화 등 다양한 기능이 포함됩니다! diff --git a/paste-extension/vscode-extension.js b/paste-extension/vscode-extension.js index 9d8fdd0e..80f5fcc0 100644 --- a/paste-extension/vscode-extension.js +++ b/paste-extension/vscode-extension.js @@ -128,10 +128,14 @@ function isInsideCodeBlock(lines, currentIndex) { } function generateSlug(text) { + // 1. 특정 기호를 우선적으로 제거 또는 변환 + text = text.replace(/\|/g, ""); // `|`를 제거 + text = text.replace(/&/g, ""); // `&`를 제거 + return slugify(text, { lower: true, - remove: /[*+~.()'"!:@?/\\^`<>{}\[\]%&=]/g, - strict: true, + remove: /[^\w\s_-]/g, // `_`, `-`, 공백, 알파벳, 숫자만 허용 + strict: false, }); }