11# -*- coding: utf-8 -*-
22"""
3- Model ensembling
3+ 모델 앙상블
44================
5+ 번역 : `조형서 <https://github.com/ChoHyoungSeo/>`_
56
6- This tutorial illustrates how to vectorize model ensembling using ``torch.vmap``.
7+ 본 튜토리얼에서는 ``torch.vmap`` 을 활용하여 모델 앙상블을 벡터화하는 방법을 설명합니다 .
78
8- What is model ensembling ?
9+ 모델 앙상블이란 ?
910-------------------------
10- Model ensembling combines the predictions from multiple models together.
11- Traditionally this is done by running each model on some inputs separately
12- and then combining the predictions. However, if you're running models with
13- the same architecture, then it may be possible to combine them together
14- using ``torch.vmap``. ``vmap`` is a function transform that maps functions across
15- dimensions of the input tensors. One of its use cases is eliminating
16- for-loops and speeding them up through vectorization.
11+ 모델 앙상블은 여러 모델의 예측값을 함께 결합하는 것을 의미합니다.
12+ 일반적으로 이 작업은 일부 입력값에 대해 각 모델을 개별적으로 실행한 다음 예측을 결합하는 방식으로 실행됩니다.
13+ 하지만 동일한 아키텍처로 모델을 실행하는 경우, ``torch.vmap`` 을 활용하여 함께 결합할 수 있습니다.
14+ ``vmap`` 은 입력 tensor의 여러 차원에 걸쳐 함수를 매핑하는 함수 변환입니다. 이 함수의
15+ 사용 사례 중 하나는 for 문을 제거하고 벡터화를 통해 속도를 높이는 것입니다.
1716
18- Let's demonstrate how to do this using an ensemble of simple MLPs .
17+ 간단한 MLP 앙상블을 활용하여 이를 수행하는 방법을 살펴보겠습니다 .
1918
2019.. note::
2120
22- This tutorial requires PyTorch 2.0.0 or later .
21+ 본 튜토리얼에서는 파이토치 2.0.0 이상의 버전이 필요합니다 .
2322"""
2423
2524import torch
2625import torch .nn as nn
2726import torch .nn .functional as F
2827torch .manual_seed (0 )
2928
30- # Here's a simple MLP
29+ # 다음은 간단한 MLP 입니다.
3130class SimpleMLP (nn .Module ):
3231 def __init__ (self ):
3332 super (SimpleMLP , self ).__init__ ()
@@ -45,10 +44,9 @@ def forward(self, x):
4544 return x
4645
4746######################################################################
48- # Let’s generate a batch of dummy data and pretend that we’re working with
49- # an MNIST dataset. Thus, the dummy images are 28 by 28, and we have a
50- # minibatch of size 64. Furthermore, lets say we want to combine the predictions
51- # from 10 different models.
47+ # 더미 데이터를 생성하고 MNIST 데이터 셋으로 작업한다고 가정해 보겠습니다.
48+ # 따라서 이미지는 28x28 사이즈이며 미니 배치 크기는 64입니다.
49+ # 더 나아가 10개의 서로 다른 모델에서 나온 예측값을 결합하고 싶다고 가정해 보겠습니다.
5250
5351device = 'cuda'
5452num_models = 10
@@ -59,100 +57,95 @@ def forward(self, x):
5957models = [SimpleMLP ().to (device ) for _ in range (num_models )]
6058
6159######################################################################
62- # We have a couple of options for generating predictions. Maybe we want to
63- # give each model a different randomized minibatch of data. Alternatively,
64- # maybe we want to run the same minibatch of data through each model (e.g .
65- # if we were testing the effect of different model initializations).
60+ # 예측값을 생성하는 데는 몇 가지 옵션이 있습니다.
61+ # 각각의 모델에 다른 무작위 미니 배치 데이터를 줄 수 있고
62+ # 각각의 모델에 동일한 미니 배치의 데이터를 줄 수 있습니다 .
63+ # (예를 들어, 다른 모델 초기값의 영향을 테스트할 경우)
6664
6765######################################################################
68- # Option 1: different minibatch for each model
66+ # 옵션 1: 각각의 모델에 다른 미니 배치를 주는 경우
6967
7068minibatches = data [:num_models ]
7169predictions_diff_minibatch_loop = [model (minibatch ) for model , minibatch in zip (models , minibatches )]
7270
7371######################################################################
74- # Option 2: Same minibatch
72+ # 옵션 2: 같은 미니 배치를 주는 경우
7573
7674minibatch = data [0 ]
7775predictions2 = [model (minibatch ) for model in models ]
7876
7977######################################################################
80- # Using ``vmap`` to vectorize the ensemble
78+ # ``vmap`` 을 활용하여 앙상블 벡터화하기
8179# ------------------------------------
8280#
83- # Let's use ``vmap`` to speed up the for-loop. We must first prepare the models
84- # for use with ``vmap``.
81+ # ``vmap`` 을 사용하여 for 문의 속도를 높여보겠습니다. 먼저 ``vmap`` 과 함께 사용할 모델을 준비해야 합니다.
8582#
86- # First, let’s combine the states of the model together by stacking each
87- # parameter. For example, ``model[i].fc1.weight`` has shape ``[784, 128]``; we are
88- # going to stack the ``.fc1.weight`` of each of the 10 models to produce a big
89- # weight of shape ``[10, 784, 128]``.
9083#
91- # PyTorch offers the ``torch.func.stack_module_state`` convenience function to do
92- # this.
84+ # 먼저, 각 매개변수를 쌓아 모델의 상태를 결합해 보겠습니다.
85+ # 예를 들어, ``model[i].fc1.weight`` 의 shape은 ``[784, 128]`` 입니다.
86+ # 이 10개의 모델 각각에 대해 ``.fc1.weight`` 를 쌓아 ``[10, 784, 128]`` shape의 큰 가중치를 생성할 수 있습니다.
87+ #
88+ # 파이토치에서는 이를 위해 ``torch.func.stack_module_state`` 라는 함수를 제공하고 있습니다.
89+ #
9390from torch .func import stack_module_state
9491
9592params , buffers = stack_module_state (models )
9693
9794######################################################################
98- # Next, we need to define a function to ``vmap`` over. The function should,
99- # given parameters and buffers and inputs, run the model using those
100- # parameters, buffers, and inputs. We'll use ``torch.func.functional_call``
101- # to help out:
95+ # 다음으로, ``vmap`` 에 대한 함수를 정의해야 합니다. 이 함수는 파라미터, 버퍼, 입력값이 주어지면 모델을 실행합니다.
96+ # 여기서는 ``torch.func.functional_call`` 을 활용하겠습니다.
10297
10398from torch .func import functional_call
10499import copy
105100
106- # Construct a "stateless" version of one of the models. It is "stateless" in
107- # the sense that the parameters are meta Tensors and do not have storage .
101+ # 모델 중 하나의 "stateless" 버전을 구축합니다.
102+ # "stateless"는 매개변수가 메타 tensor이며 저장소가 없다는 것을 의미합니다 .
108103base_model = copy .deepcopy (models [0 ])
109104base_model = base_model .to ('meta' )
110105
111106def fmodel (params , buffers , x ):
112107 return functional_call (base_model , (params , buffers ), (x ,))
113108
114109######################################################################
115- # Option 1: get predictions using a different minibatch for each model .
110+ # 옵션 1: 각 모델에 대해 서로 다른 미니 배치를 활용하여 예측합니다 .
116111#
117- # By default, ``vmap`` maps a function across the first dimension of all inputs to
118- # the passed-in function. After using ``stack_module_state``, each of
119- # the ``params`` and buffers have an additional dimension of size 'num_models' at
120- # the front, and minibatches has a dimension of size 'num_models'.
112+ # 기본적으로, ``vmap`` 은 모든 입력의 첫 번째 차원에 걸쳐 함수에 매핑합니다.
113+ # ``stack_module_state`` 를 사용하면 각 ``params`` 와 버퍼는 앞쪽에 'num_models'
114+ # 크기의 추가 차원을 가지며, 미니 배치는 'num_models' 크기가 됩니다.
121115
122- print ([p .size (0 ) for p in params .values ()]) # show the leading 'num_models' dimension
116+ print ([p .size (0 ) for p in params .values ()]) # 선행 'num_models' 차원 표시
123117
124- assert minibatches .shape == (num_models , 64 , 1 , 28 , 28 ) # verify minibatch has leading dimension of size 'num_models'
118+ assert minibatches .shape == (num_models , 64 , 1 , 28 , 28 ) # 미니 배치의 선행 차원이 'num_models' 크기인지 확인합니다.
125119
126120from torch import vmap
127121
128122predictions1_vmap = vmap (fmodel )(params , buffers , minibatches )
129123
130- # verify the ``vmap`` predictions match the
124+ # ``vmap`` 예측이 맞는지 확인합니다.
131125assert torch .allclose (predictions1_vmap , torch .stack (predictions_diff_minibatch_loop ), atol = 1e-3 , rtol = 1e-5 )
132126
133127######################################################################
134- # Option 2: get predictions using the same minibatch of data .
128+ # 옵션 2: 동일한 미니 배치 데이터를 활용하여 예측합니다 .
135129#
136- # ``vmap`` has an ``in_dims`` argument that specifies which dimensions to map over .
137- # By using ``None``, we tell ``vmap`` we want the same minibatch to apply for all of
138- # the 10 models .
130+ # ``vmap`` 에는 매핑할 차원을 지정하는 ``in_dims`` 라는 인자가 있습니다 .
131+ # ``None`` 을 사용하면 10개 모델에 모두 동일한 미니 배치를 적용하도록
132+ # ``vmap`` 에 알려줄 수 있습니다 .
139133
140134predictions2_vmap = vmap (fmodel , in_dims = (0 , 0 , None ))(params , buffers , minibatch )
141135
142136assert torch .allclose (predictions2_vmap , torch .stack (predictions2 ), atol = 1e-3 , rtol = 1e-5 )
143137
144138######################################################################
145- # A quick note: there are limitations around what types of functions can be
146- # transformed by ``vmap``. The best functions to transform are ones that are pure
147- # functions: a function where the outputs are only determined by the inputs
148- # that have no side effects (e.g. mutation). ``vmap`` is unable to handle mutation
149- # of arbitrary Python data structures, but it is able to handle many in-place
150- # PyTorch operations.
139+ # 참고 사항: ``vmap`` 으로 변환할 수 있는 함수 유형에는 제한이 있습니다.
140+ # 변환하기에 가장 좋은 함수는 입력값에 의해서만 출력이 결정되고
141+ # 다른 부작용 (예. 변이) 이 없는 순수 함수(pure function) 입니다.
142+ # ``vmap`` 은 임의의 변이된 파이썬 자료구조는 처리할 수 없지만,
143+ # 다양한 내장된 파이토치 연산은 처리할 수 있습니다.
151144
152145######################################################################
153- # Performance
146+ # 성능
154147# -----------
155- # Curious about performance numbers? Here's how the numbers look .
148+ # 성능 수치가 궁금하신가요? 수치는 다음과 같습니다 .
156149
157150from torch .utils .benchmark import Timer
158151without_vmap = Timer (
@@ -165,11 +158,9 @@ def fmodel(params, buffers, x):
165158print (f'Predictions with vmap { with_vmap .timeit (100 )} ' )
166159
167160######################################################################
168- # There's a large speedup using ``vmap``!
161+ # ``vmap`` 을 사용하면 속도가 크게 향상됩니다 !
169162#
170- # In general, vectorization with ``vmap`` should be faster than running a function
171- # in a for-loop and competitive with manual batching. There are some exceptions
172- # though, like if we haven’t implemented the ``vmap`` rule for a particular
173- # operation or if the underlying kernels weren’t optimized for older hardware
174- # (GPUs). If you see any of these cases, please let us know by opening an issue
175- # on GitHub.
163+ # 일반적으로, ``vmap`` 을 사용한 벡터화는 for 문에서 함수를 실행하는 것보다
164+ # 빠르며 수동 일괄 처리와 비슷한 속도를 냅니다. 하지만 특정 연산에 대해 ``vmap`` 규칙을
165+ # 구현하지 않았거나 기본 커널이 구형 하드웨어(GPUs)에 최적화되지 않은 경우와 같이
166+ # 몇 가지 예외가 있습니다. 이러한 경우가 발견되면, GitHub에 이슈를 생성해서 알려주시기 바랍니다.
0 commit comments