The Case for Co-Designing Model Architectures with Hardware
The Case for Co-Designing Model Architectures with Hardware
link : https://arxiv.org/pdf/2401.14489
✲ Introduction
딥러닝 모델을 설계할 때 GPU 구조의 영향을 간과하는 경우가 많으며 모델을 하드웨어에 더 적합하게 수정하면 학습 및 추론 능력을 향상시킬 수 있다고 제안하는 논문이다. 이를 위해 Transformer 성능을 극대화하기 위한 가이드라인을 제공한다. 이 가이드라인은 다양한 하이퍼파라미터가 GPU의 기본 계산 커널의 효율성에 미치는 영향을 고려하여 작성되었다고 한다. GEMM(General Matrix Multiplication) 최적화의 기본 원리를 사용해 Transformer 모델의 개별 부분을 최적화하는 것을 보여준다. 하드웨어 세부사항이 딥러닝 연구에서 일반적인 생각보다 훨씬 중요하다는 것 또한 강조한다. 궁극적으로 현대 GPU 구조를 면밀히 고려해 Transformer 모델의 성능 튜닝을 단순화하려고 한다.
위 그림에서 보듯, 거의 동일한 수의 파라미터를 가진 모델임에도 모델 shape이 다르면 실행 시간에서 큰 차이가 날 수 있다. GPT-3 (2.7B)에 의해 정의된 "standard architecture"은 OPT, GPT-Neo, Cerebras-GPT, RedpajamaINCITE, Pythia 등의 모델에서 사용되었다. 안타깝게도 Transformer 아키텍처를 최적으로 형상화하는 방법에 대한 지식은 널리 알려져 있지 않으며 이로 인해 사람들은 종종 최적이지 않은 설계 결정을 내린다. 이 문제는 연구자들이 더 깔끔한 성능 비교를 위해 다른 논문에서 사용된 하이퍼파라미터를 의도적으로 복사하는 경향이 있어 이러한 비최적적 선택들이 표준으로 고착되는 현상으로 악화되었다. 위 그림에서 볼 수 있듯 GPT3(2.7B) 모델은 모델 shape을 조금만 조정해도 기존 구조보다 20%빠르게 학습할 수 있다는 것을 보여준다.
우리의 분석은 General Matrix Multiplications(GEMMs)이 현대 딥러닝에서 매우 중요한 역할을 한다는 사실을 기반으로 한다(attention layers or linear layers, convolutions).
Transformer 모델은 위 그림처럼 GEMM 커널이 중, 대형 모델의 latency에서 69.3%와 94.9%를 차지한다. 따라서 GEMM의 성능을 이해하는 것은 end-to-end model 실행 성능을 이해하는 데 매우 중요하고 모델 크기가 커질수록 중요하다.
병렬 구조 때문에 GPU는 GEMM에 적합한 하드웨어 플랫폼이다. 그러나 이러한 GEMM의 관찰된 처리량은 행렬 크기에 따라 달라지고, 이는 계산이 GPU의 execution units (Streaming Multiprocessor, SMs)에 어떻게 매핑되는지 의해 결전된다. 따라서 GPU의 효율성은 모델의 depth & with에 민감하고 계산 효율성, SM 활용도, 커널 선택, 그리고 텐서 코어와 더 느린 CUDA 코어의 사용에 영향을 미친다. 이런 요소들을 고려해 GPU에서좋은 성능을 낼 수 있도록 어떻게 최적화 할 수 있는지 알아보겠다.
많은 논문들이 GPU에서 성능 최적화를 이야기하지만, GPU의 속성(tensor cores, tiling, wave quantization, etc.)이 모델 학습에 미치는 근본적 영향을 간과하는 경향이 있다. 이로 인해 많은 DL 학습 그룹이 비슷한 모델 사이즈 세팅을 가지고 있는 것을 발견하였다. 저자들은 이 최적화 결과를 GPU의 기본적 원리 관점에서 설명하고 이를 효율적인 트랜스포머 학습과 추론을 위한 간결한 최적화 가이드로 집약할 것이다.
*Contributions
Transformer를 GEMM으로 매핑해 Transformer 각 구성 요소가 비효율적인 차원을 사용하면 어떻게 성능 저하가 되는지 보여준다.
GPU의 성능 요소를 하나의 문서로 정리하고 최적의 GEMM 차원을 선택하는 방법을 설명한다.
Transformer이 효율적인 GEMM으로 구성되도록 하는 규칙을 정의한다.
✲ Background
‣ A. GPU Kernels
GEMM에서 A가 $m \times k$ 행렬이고 B가 $k \times n$ 행렬이면 행렬곱셈 AB는 간단한 GEMM이다. 이를 일반화하면 $\alpha A B + \beta C$가 되고 fully connected layers forward pass에서 weight matrix는 A가 되고 input activations은 B가 된다. $\alpha$와 $\beta$는 일반적으로 1,0 이지만 skip connection을 추가할 때와 같은 특정 시나리오에서는 1일 수 있다.
행렬-행렬 곱셈은 많은 과학, 공학적 응용프로그램에서 기본적 연산으로 특히 딥러닝 분야에서 중요하다. 이는 많은 계산 자원을 필요로하는 연산이므로 이를 해결하기 위한 GEMM 연산을 최적화하는 다양한 알고리즘과 계산 기법들이 개발되었다. Batch Matrix-Matrix(BMM) 곱셈 커널과 같은 행렬 곱셈 변형($C_i = \alpha A_i B_i + \beta C_i , i = 1, ... N$)도 도입되어 어텐션 같은 특정 DL 연산 처리량을 개선하고 있다.
‣ B. NVIDIA GEMM Implementation and Peformance Factors
Nvidia GPU는 출력 행렬을 영역이나 타일로 나누고, 이를 GPU의 사용 가능한 SM(Streaming Multiprocessor) 중 하나에 스케줄링 한다 (ex. A100에는 108의 SM이 있음). 각 타일 또는 스레드 블록은 텐서 코어(*행렬 곱셈 덧셈을 한 번의 사이클로 고속 처리할 수 있는 하드웨어 유닛)에서 처리되고 텐서 코어는 빠른 텐서 연산을 위해 Nvidia가 도입한 기술이다. 이 텐서 코어는 적절한 차원을 가진 GEMM에서만 사용할 수 있다. GEMM 차원 $m, k, n$이 V100 GPU의 경우 16바이트 배수, A100의 경우 128바이트 배수일 때 가장 효율적으로 활용된다(fp16일 경우 8, 64 배수). 만약 이 차원 크기를 맞출 수 없다면 2바이트 배수보다 큰 배수로 성능 개선하려고 시도한다.
행렬 연산에서 작은 블록으로 나누고 이 작은 블록을 타일(Tiles)이라고 한다. 타일을 GPU의 SM이 병렬로 작업을 분담해 성능을 최적화 하고, 스레드 블록(Thread Block)은 병렬 연산을 할 수 있는 최소 작업 단위를 의미한다. 각 스레드 블록은 하나의 타일을 처리한다. 그리고 커널(Kernel)은 GPU에서 실행되는 연산 단위이다. GEMM 연산을 처리하는 커널은 여러 타일 크기를 선택할 수 있다. 이때 각 타일 크기는 GPU 아키텍처의 최적화된 크기와 맞춰야 성능이 좋다(ex. V100, 16 x 16, 32 x 32.. ).
하지만 이때 GEMM, 즉 행렬의 크기가 타일 크기와 정확히 나누어 떨어지지 않으면 계산낭비 및 타일 양자화 (Tile Quantization) 문제가 발생한다. 예를 들어, 행렬 크기가 1025 * 1025 이고 타일 크기가 16 * 16 이라면 완전히 채워진 64개의 타일이 필요하고 추가로 1개의 타일이 더 필요하다. 이 1개의 타일은 1 * 1의 완전한 타일(1025번째 행과 열)을 제외한 나머지 15 * 15 에 대해 불필요한 연산이 이루어져 성능 저하를 초래한다. 타일 양자화라는 뜻은, 정해진 특정 값으로 나뉘어진다는 의미로 타일 크기에 맞춰 출력이 이산적인 값이라는 것이다. 즉, 출력 결과가 타일 단위로 처리되어 각 타일이 특정 크기 (ex. 16*16)로 맞춰져서 계산되고 타일에 맞는 연산만 이루어진다는 뜻이다. 이렇게 타일 양자화가 발생하면 실제로 필요한 데이터 뿐 아니라 불필요한 부분까지 연산을 진행해야 하므로 GPU 계산 리소스가 낭비된다. 타일 블록 내 일부 스레드는 실제로 연산을 수행할 필요가 없는데도 실행하게되고, 이러한 낭비가 블록 단위로 누적된다. 이로 인해 전체 연산 시간이 증가하고 처리량(throughput)이 감소한다.
그리고 또다른 양자화 효과로 웨이브 양자화(Wave quantization)이 있다. 스레드 블록이 SM에 할당될 때 한번에 108개의 스레드 블록만 할당할 수 있다. 예를 들어 109개의 스레드 블록을 할당한다면, 두 번의 라운드 또는 "wave"로 스레드 블록이 GPU에 할당된다. 첫 번째 wave에는 108개의 스레드 블록이 있고 두 번째 wave에는 1개의 스레드 블록만이 포함된다. 두 번째 wave는 첫 번째 wave와 거의 같은 latency를 가지지만, 유효한 계산은 아주 작은 비율에 불과하다. 행렬 크기가 커짐에 따라 마지막 또는 tail wave가 커진다. 처리량(throughput)은 증가하다, 새로운 wave가 필요하면 다시 감소하게 된다. 이처럼 전체 스레드 블록 수가 SM 개수롸 나누어 떨어지지 않은 경우에 발생하는 문제이고 타일 양자화와 비슷하게 불필요한 연산이 발생하게 된다.
‣ C. Transformer Models
이 연구에서는 주로 GPT-2로 대중화된 디코더 전용 트랜스포머 구조를 살펴본다. 대부분의 결론은 인코더 전용 모델에도 적용될 수 있으나 인코더-디코더 모델에는 이들간 전환 방식 때문에 적용되지 않는다.
초기에는 raw input tokens가 v * h 크기의 임베딩 테이블에 입력된다. 이 토큰 임베딩은 크기 s * h인 positional embedding과 결합된다. 임베딩 계층에서 나온 출력은 트랜스포머 블록의 입력의 크기가 되며 s * b * h인 3D 텐서이다. 트랜스포머의 각 layer는 self-attention block과 attention heads로 구성되며, 그 뒤에는 2-layer multi-layer MLP로 이어져 hidden size를 4h로 확장 한 후 다시 h로 축소한다. 각 트랜스포머 계층의 입력 및 출력 크기는 일관되게 s * b * h로 유지된다. 마지막 트랜스포머 레이어에서 나온 최종 출력은 vocab 차원으로 다시 projection되어 cross-entropy를 계산하는 데 사용된다.
Transformer 각 layer는 다음과 같은 Matrix Multiplication Operators로 구성된다.
- Attention Key, Value, Query transformation:
이는 하나의 행렬 곱셈으로 표현할 수 있고 $(b \cdot s, h) \cdot (h, \frac{3h}{t})$, 출력 크기는 $(b \cdot s, \frac{3h}{t})$이다. - Attention score computation:
batched matrix multiplications, BMM이 $b \cdot a / t$ 번 수행되고 각 곱셈의 크기는 $(s, \frac{h}{a}) \cdot (\frac{h}{a}, s)$이며 출력의 크기는 $(\frac{b \cdot a}{t}, s, s)$이다. - Attention over value computation:
$\frac{b \cdot a }{t}$ 번 배치된 행렬 곱셈이 수행되고 각 곱셈의 크기는 $(s,s) \cdot (s, \frac{h}{a})$이다. 출력의 크기는 $(\frac{b \cdot a}{t}, s, \frac{h}{a})$이다. - Post-attention linear projection:
하나의 행렬 곱셈으로 크기는 $(b \cdot s, \frac{h}{t} \cdot (\frac{h}{t}, h)$이며 출력의 크기는 $(b \cdot s, h)$이다. - Matrix multiplications in MLP block of size $( b \cdot s, h) \times (h, \frac{4h}{t}) $ and $(b \cdot s, \frac{4h}{t}) \times (\frac{4h}{t}, h)$. Ouputs are of size $(b\cdot s, \frac{4h}{t})$ and $(b \cdot s, h)$.
따라서 트랜스포머의 총 파라미터는 다음 공식을 사용해 계산할 수 있다.
$$ P = 12 h^2 L + 13 h L + (v+s)h. \ L \text{: Number of transformer layers}$$
이 값은 일반적으로 $P=12 h^2 L$로 근사되고 하위 차수 항들은 생략된다. 여기서 우리는 multi-head attention block에서 projection 가중 차원이 $h/a$인 것으로 가정한다(이는 Megatron, GPT-NeoX 같은 기존 구현의 기본 설정이다). 학습을 위한 forward pass를 수행하는 데 필요한 총 계산 작업 수는 아래와 같다.
$$ 24 b s h^2 + 4 b s^2 h = 24s h^2 (1 + \frac{s}{6h}) $$
그리고 해당 논문에서는 여러 GPU를 사용하는 방식, 즉 병렬화에 대한 논의는 주제로 다루지 않는다. 하나의 GPU에서 모델을 계산하는 과정에 집중한다. 예를 들어 t-way tensor 병렬화인 경우 hidden size가 h이고 GPU 갯수가 t이면, 실제로 한 GPU당 처리하는 hidden size는 h/t이다.
✲ GEMM Results
GEMM 크기가 커질수록 연산은 Compute-bound 되고 메모리 효율성이 높아지고, GEMM은 작은 행렬에서는 Memory-bound이다.
Memory-bound라는 것은 프로세서(GPU, CPU)가 작업을 처리하는데 메모리 속도나 대역폭이 병목되어 성능이 제한되는 상황을 의미한다. 처리할 데이터가 많지만 그 데이터를 프로세서가 메모리에서 가져오고 저장하는 속도가 충분히 빠르지 않아 연산 성능이 제한되는 경우이다. 즉, 데이터를 메모리에서 가져오는 속도가 연산 처리 속도보다 느려서 결국 메모리가 병목되는 것이다.
Compute-bound라는 것은 행렬의 크기가 커지면 연산에 필요한 계산량이 많아져 memory-bound의 메모리에서 데이터를 읽고 쓰는 속도가 더이상 제한적이지 않다는 의미이다. 즉, 데이터를 읽은 후 수행해야 할 계산이 더 중요해 메모리에서 데이터를 읽어오는 속도는 크게 중요하지 않다는 것이다.
그림 5의 (a)를 보면 행렬 크기가 커짐에 따라 연산의 처리량(teraFLOP/s)이 비례하여 증가하는 것을 볼 수 있다. 행렬 크기가 작을 때는 메모리에서 데이터를 가져오는 속도가 더 중요한 병목 요소로 작용한다는 뜻이다. 따라서 wave 양자화로 인한 비효율성도 GEMM 크기가 특정 임계값보다 클 때 성능 저하의 요인이 된다. 그림 5의 (b)를 보면 이 wave 양자화의 영향을 명확하게 확인할 수 있다. GEMM 크기가 충분히 커지면 파이토치에서 자동으로 타일 크기를 선택해 양자화 효과를 줄일 수 있다. 그림 5의 (c)에서는 파이토치는 GEMM 병렬화 개선 효과와 파형 양자화로 인한 비효율성을 잘 조절해 처리량을 향상시키는 것을 볼 수 있다. 이로 인해 wave 양자화의 악영향이 줄어들게 된다.
✲Transformer Results
위에서 살펴본 GEMM 결과는 Transformer에 그대로 적용된다. 트랜스포머를 일련의 GEMM으로 이해하는 것이다.
각 Attention head는 자신만의 key, query, value matrix를 가지고 독립적인 행렬곱셈 연산을 수행한다. 따라서 헤드의 수만큼 행렬 곱셈의 연산 수가 배로 증가한다. head가 8이면 행렬 곱셈(MM) 연산 수는 8배 증가한다.
그리고 각 MM도 마찬가지로 Attention head 수에 따라 달라진다. 1개의 head만 있을 때보다 8개의 head가 있다면 각 head는 원래보다 작은 크기의 행렬을 처리하게 된다. 각 헤드가 수행하는 연산 크기는 전체 크기를 헤드 수로 나눈 작은 행렬이 된다.
그림 7은 attention score와 value에 대한 계산에서 사용되는 BMM의 처리량에 헤드 수와 hidden size가 미치는 영향을 보여준다. Nvidia tensor core는 A100 GPU에서 m, n, k 차원이 128바이트의 배수일 때 더 효율적이다 (fp16의 경우 64바이트 배수). 만약 이렇게 조정할 수 없다면 더 큰 2의 거듭제곱의 배수인 크기를 사용하는 것이 더 나은 성능을 보인다.
그림 8, 9 실험에서는 hidden size(h)와 head 수(a)를 줄이면 GEMM의 효율성이 향상됨을 보여준다. a가 감소하면 h/a가 증가하여 이 두 GEMM은 Memory-bound 상태가 되기 때문이다. 그림 9를 보면 wave 양자화 효과가 나타날 때마다 peak and valley 형태로 TFlops가 저하되는 것을 볼 수 있다.
그림 11을 보면 모델 사이즈가 커질수록 GEMM 연산 최적화가 중요하다는 것을 알 수 있으며 attention block QKV transformation과 MLP 블록이 가장 빈번한 GEMM임을 알 수 있다.
‣ Analysis
따라서 NVIDA GPU에서 GEMM을 효율적으로 실행하기 위한 요구사항은 아래와 같다.
- Tensor Core Requirement
GEMM의 내 외부 차원이 128바이트(fp16은 64)로 나누어 떨어지도록 해야 한다. - Tile Quantization
가장 효율적인 타일 크기를 사용하려면 output matrix가 128 * 256 으로 나누어 떨어지도록 해야한다. - Wave Quantization
Output matrix이 나누어 떨어지는 블록의 수가 Streaming Multiprocessors(SMs)의 수(80 for V100, 108 for A100, 144 for H100)로 나누어 떨어지도록 해야한다.
Tile quantization은 사용자가 관찰하기 어려운 경우가 많지만(더 큰 크기의 문제를 처리할 때와 비슷한 시간으로 실행되는 것으로 확인), Wave quantization은 쉽게 관찰할 수 있다. X * Y 행렬이 있고 t1 * t2 타일이 있다면 다음을 만족하면 wave quantization 비효율성이 발생하지 않는다.
Pytorch는 여러 종류의 타일 크기를 사용할 수 있지만, wave quantization에서 불완전한 Tile에 대한 성능 저하를 자동으로 최적화하지는 못한다. 즉, 타일 크기를 최적화하면 연산이 빨라지긴 하지만 wave quantization 때문에 모든 경우 완벽한 최적화는 어렵고 Pytorch는 이러한 기능이 부족하다.
따라서 Transformer에서 최상의 성능을 보장하려면 다음을 확인해야 한다.
a: attention head 수, h: hidden size, t: 텐서 병렬 수
- Vocabulary size는 64로 나누어 떨어져야 한다.
- micro batch크기 b는 가능한 커야 한다.
- $b \cdot s, \frac{h}{a}, \frac{h}{t}$는 2의 거듭제겁으로 나누어 떨어져야 하며, 64를 넘는 크기는 더 이상 성능 향상에 도움되지 않는다.
- $(b \cdot a) / t$는 정수여야 한다.
- t 는 가능한 작아야 한다. (gpu간 로드 밸런싱과 통신 비용 때문에)
그리고 micro batch b가 2의 거듭제곱으로 나누어질 필요가 없는 이유는, 시퀀스 길이 s가 이미 큰 2의 거듭제곱이기 때문이다. 그리고 파이프라인 병렬화를 사용하여 학습하는 것이 최적인지 여부는 컴퓨팅 설정의 세부사항에 따라 달라진다. 특히 노드 간 연결 속도와 대역폭이 중요한 요소이다. 모든 경우에 레이어 수는 파이프라인 병렬 단계(모델 연산을 여러 gpu나 노드에 나눠 수행하는 각각의 처리 구간) 수로 나누어 떨어지는 것이 최적이다. 예를 들어 레이어 수가 12고 gpu 수가 4개면 각 gpu는 3개의 레이어를 맡게 되지만 레이어 수가 13개라면 3,3,3,4 처럼 각 단계 마다 맡는 레이어 수가 달라진다.
GPT-3(2.7B)에서 hidden size 2560이며 attention head 수는 32라서 2560/32=80으로 64배수가 되지 못한다. 따라서 히든을 4096으로 늘리거나 헤드 수를 20으로 줄일 수 있는데 히든 사잊르르 늘리면 파라미터 수가 2배가 되므로 헤드 수를 줄인다. 작은 모델의 경우 FlashAttention v2를 사용하여 이러한 영향을 완화하거나 그림 10처럼 saturation point에 가능한 빨리 도달하도록 h를 최대한 증가시키는 것을 추천한다.
Decoder only 구조는 대체로 표준화 되어있으며(GPT-2기반), 최근 연구에서 몇 가지 아키텍처 수정이 인기를 끌고 있다.
1. Parallel Layers
기존에는 attention과 mlp를 순차적으로 계산했다. $y = x + \text{MLP(Norm(}x + \text{Attn(Norm(}x))))$
이제는 Transformer 블록을 병렬적으로 정의한다. $y = x + \text{MLP(Norm(}x)) + \text{Attn(Norm(}x))$
실제로 두 브랜치가 동시에 계산되는 것은 아니고, 이 정의로 인한 속도 향상은 MLP와 Attn 블록을 하나의 커널로 융합하여 달성된다.
2. Alternative Positional Embeddings
기존 pointwise operations 기반 위치 임베딩에서 최근에는 Rotary, ALiBi 임베딩이 더 인기를 끌고 있다. Rotary, ALiBi 임베딩에 필요한 GEMM연산이 조금 더 느리지만 이 임베딩이 가져오는 모델 정확도 향상은 일반적으로 그만한 가치가 있다고여겨진다. 최근에는 로터리 임베딩용 맞춤형 커널이 도입되어 비용을 더 줄일 수 있었다.
3. Flash Attention
LLM에 널리 사용되는 혁신적인 Attention Kernel이다. 위 그림에서 볼 수 있듯 Flashattention은 Roofline Model을 따른다. Roofline 모델이란 HW 성능 한계와 알고리즘의 효율성으로 시각적으로 나타내는 의미를 말한다. 따라서 Flashattention을 사용할 때 어텐션 연산의 성능이 어느 지점에서 성능 한계에 도달한다는 의미이고, h를 가능한 크게 키우는 것이 가장 효율적인 방법이라는 단순한 결론이 도출되게 한다.
Parallel Layers, Alternative Positional Embeddings, Flash Attention은 해당 논문의 분석에 미치는 영향이 거의 없다. 하지만 SwiGLU와 8h/3 MLPs는 좀 다르다.
4. SwiGLU와 8h/3 MLPs
SwiGLU는 MLP블록에 3개의 matrix를 포함하게 된다. MLP 블록의 총 파라미터 수를 유지하기 위해서는 SwiGLU에서 $d_{ff}=8/3 \cdot h$를 사용하는 대신 $d_{ff}=4 \cdot h$를 사용하는 것을 제안한다. 해당 논문에서 최적으 GEMM 성능을 찾기 위한 h를 찾는 방법을 따랐다면 8/3는 모든 정렬을 깨트리기 때문에 MLP블록의 성능을 훨씬 느리게 만들 수 있다.
여기서 8/3은 단순한 제안일 뿐이며 이 값이 최적은 아니다. Llama2를 보면 7B의 경우는 11008/4096 = 2.6875라는 계수를 사용하고 있으며, 이는 8/3 = 2.667에 상당히 가깝다. 그리고 70B는 28672/8192 = 3.5 계수를 사용하고 있다. 이는 SwiGLU를 사용하지 않는 Transformer보다 더 큰 파라미터를 가지게 한다. 이처럼 h를 이미 잘 선택했다면 성능을 극대화할 수 있는 다른 계수를 찾아볼 수 있다.
추가적으로 GPU노드 수에 따른 하이퍼파라미터에 대해서도 이야기한다. 일반적으로 데이터 센터는 8개의 GPU를 노드에 장착하지만, Summit 슈퍼컴퓨터와 같은 일부 시스템에서는 6개의 GPU를 사용한다. 이 경우, 텐서 병렬화가 GPU 수와 같을 때 가장 효율적인 방식이지만, 6-GPU 노드에서는 성능 최적화에 문제가 발생할 수 있다. 8-GPU에서 사용되는 모델 아키텍처는 6-GPU 노드에서 구현이 불가능하거나 비효율적일 수 있으며, 이를 해결하기 위한 방법이 있다면, 다른 GPU 설정에서 배포 시 문제가 발생할 수 있다. 따라서 프리트레이닝을 최적화할 것인지, 아니면 파인튜닝이나 추론에 더 적합한 하이퍼파라미터를 선택할 것인지에 대한 신중한 결정이 필요하다고 한다.
'인공지능 AI' 카테고리의 다른 글
당신이 좋아할만한 콘텐츠
-
[CS25 6강] DeepMind's Perceiver and Perceiver IO: new data family 2023.07.28
-
[CS25 5강] Mixture of Experts (MoE) paradigm and the Switch Transformer 2023.07.22
-
[RL] Is Conditional Generative Modeling All You Need For Decision-Making?(Decision-Diffuser) 2023.06.11
-
[RL] Behavior Transformers: Cloning k modes with one stone 2023.05.23
소중한 공감 감사합니다