* 2021년 8월부로 코드는 더 이상 유지되지 않습니다. 계속해서 이용하고 싶은 사람들을 위해 이곳에 보관 형태로 보존되어 있습니다.
? 1T 아니면 내 친구들을 깨뜨릴까요?
mesh-tensorflow 라이브러리를 사용하여 모델 및 데이터 병렬 GPT3 유사 모델을 구현합니다.
사전 훈련된 모델을 가지고 놀러 오셨다면 HuggingFace Transformer 통합을 사용해 보시기를 적극 권장합니다.
훈련 및 추론은 공식적으로 TPU에서 지원되며 GPU에서도 작동합니다. 이 저장소는 GPU 관련 저장소인 GPT-NeoX로 초점을 이동함에 따라 (대부분) 보관됩니다.
GPT-3에서 제공하는 기능 외에도 다음과 같은 기능도 제공합니다.
NB, neo는 기술적으로 200B+ 매개변수에서 훈련 단계를 실행할 수 있지만 이러한 규모에서는 매우 비효율적입니다. 이는 무엇보다도 많은 GPU를 사용할 수 있게 되었다는 사실과 함께 개발을 GPT-NeoX로 전환하게 만들었습니다.
2021년 3월 21일 업데이트:
The Pile에서 훈련된 두 개의 사전 훈련된 GPT-Neo 모델을 출시하게 된 것을 자랑스럽게 생각합니다. 가중치와 구성은 the-eye.eu에서 무료로 다운로드할 수 있습니다.
1.3B: https://mystic.the-eye.eu/public/AI/gptneo-release/GPT3_XL/
2.7B: https://mystic.the-eye.eu/public/AI/gptneo-release/GPT3_2-7B/
이러한 설정 방법에 대한 자세한 내용은 Colab 노트북을 참조하거나 나머지 추가 정보를 읽어보세요.
모델 및 크기 | 더미 BPB | 더미PPL | 위키텍스트 PPL | 람바다 PPL | 람바다 Acc | 위노그란데 | 헬라스와그 |
---|---|---|---|---|---|---|---|
GPT-네오 125M | ----- | ----- | 32.285 | 30.266 | 37.36% | 50.43% | 28.67% |
GPT-3 125M | ----- | ----- | ----- | 18.6 | 42.7% | 52.0% | 33.7% |
GPT-네오 350M | ----- | ----- | 22.5657 | 13.876 | 47.27% | 51.14% | 32.16% |
GPT-3 350M | ----- | ----- | ----- | 9.09 | 54.3% | 52.1% | 43.6% |
GPT-3 에이다 | 0.9631 | ----- | ----- | 9.954 | 51.60% | 52.90% | 35.93% |
GPT-네오 1.3B | 0.7527 | 6.159 | 13.10 | 7,498 | 57.23% | 55.01% | 38.66% |
GPT-3 1.3B | ----- | ----- | ----- | 5.44 | 63.6% | 58.7% | 54.7% |
GPT-2 1.5B | 1.0468 | ----- | 17.48 | 10.634 | 51.21% | 59.40% | 40.03% |
GPT-네오 2.7B | 0.7165 | 5.646 | 11.39 | 5.626 | 62.22% | 56.50% | 42.73% |
GPT-3 2.7B | ----- | ----- | ----- | 4.60 | 67.1% | 62.3% | 62.8% |
모델 및 크기 | MathQA | PubMedQA | 피카 |
---|---|---|---|
GPT-네오 125M | 22.78% | 55.10% | 63.06% |
GPT-3 125M | ----- | ----- | 64.6% |
GPT-네오 350M | 23.45% | 53.80% | 65.07% |
GPT-3 350M | ----- | ----- | 70.2% |
GPT-3 에이다 | 24.29% | 52.80% | 68.88% |
GPT-네오 1.3B | 24.05% | 54.40% | 71.11% |
GPT-3 1.3B | ----- | ----- | 75.1% |
GPT-2 1.5B | 23.64% | 58.33% | 70.78% |
GPT-네오 2.7B | 24.72% | 57.54% | 72.14% |
GPT-3 2.7B | ----- | ----- | 75.6% |
참고: 모든 평가는 평가 도구를 사용하여 수행되었습니다. GPT-2 및 GPT-3에 대한 일부 결과는 해당 논문에 보고된 값과 일치하지 않습니다. 우리는 현재 그 이유를 조사하고 있으며, 평가 하네스에 대한 피드백과 추가 테스트에 크게 감사하겠습니다.
git clone https://github.com/EleutherAI/GPTNeo
cd GPTNeo
pip3 install -r requirements.txt
Google Cloud Platform에 가입하고 저장소 버킷을 만듭니다.
Google 버킷 및 TPU에 연결하고 pip로 요구 사항을 설치할 수 있도록 ctpu up --vm-only
사용하여 Google 셸( https://ssh.cloud.google.com/
)을 통해 VM을 만듭니다(위 참조). .
Google colab은 tpu-v8s를 무료로 제공합니다. 이는 모델을 최대 GPT3XL(1.5B 매개변수) 크기까지 미세 조정하는 데 충분합니다. 예시 Colab 노트북을 실행하려면 클릭하세요.
더 자세한 지침을 보려면 아래 교육 가이드를 살펴보세요.
GPU에서 로컬로 GPTNeo를 훈련하도록 선택할 수도 있습니다. 이렇게 하려면 위의 Google 클라우드 설정 단계를 생략하고 리포지토리를 로컬에서 git clone하면 됩니다. 아래 교육 가이드를 실행한 다음 main.py를 실행할 때 tpu
플래그를 생략하고 대신 GPU ID를 전달하면 됩니다.
참고: 일부 사용자는 MTF가 GPU를 인식하는 데 어려움을 겪고 있다고 보고했습니다. 문제를 해결하는 방법에 대한 자세한 내용과 지침은 여기를 참조하세요.
훈련된 모델이 있거나 사전 훈련된 모델 중 하나를 다운로드한 후에는 --predict
플래그를 켜고 main.py 스크립트를 실행하는 것만큼 간단하게 텍스트를 생성할 수 있습니다. 다음과 같이 --prompt
플래그를 사용하여 프롬프트 txt 파일의 경로를 전달할 수 있습니다.
python3 main.py --predict --prompt < example_prompt.txt > --tpu < tpu_name > --model < config_name >
또는 GPU를 사용하는 경우:
python3 main.py --predict --prompt < example_prompt.txt > --gpu_ids < device:GPU:0 device:GPU: 1> --model < config_name >
Huggingface의 사전 훈련된 GPT2 토크나이저를 당사 리포지토리(아래 지침 제공)와 함께 사용하는 것이 좋습니다. 그러나 다양한 어휘 크기로 모델을 훈련하려는 경우 다음과 같이 자체 토크나이저를 훈련할 수 있는 기능을 제공합니다.
python data/train_tokenizer.py
--base_dir ./path/to/your/txt/files
--output_dir ./output/path
--file_type txt
--vocab_size 50257
# if it succeeded, you should see the message
# 'tokenizer saved at ./output/path/byte-level-bpe.tokenizer.json'
훈련만 테스트하고 싶다면 이 단계를 건너뛰고 다음과 같은 일부 더미 데이터를 다운로드할 수 있습니다.
wget https://storage.googleapis.com/connors-datasets/bundestag/bundestag_0.tfrecords
그런 다음 데이터를 버킷에 복사하거나, GPU를 사용하는 경우 로컬 디렉터리에 복사합니다.
gsutil cp bundestag_0.tfrecords gs://<your bucket>/
자체 데이터를 사용하여 훈련하는 경우 data/create_tfrecords.py
스크립트를 사용하여 텍스트 데이터를 tfrecords로 인코딩할 수 있습니다.
데이터는 여러 개의 일반 .txt 파일 형식(파일당 하나의 문서)이거나 lm_dataformat에서 지원하는 형식이어야 합니다.
매개변수 없이 스크립트를 실행하면 모든 옵션에 대한 도움말을 볼 수 있습니다.
문서 모드 에서 tfrecords의 각 예는 하나의(가변 크기) 문서입니다. 이는 documents_fixed
및 documents_random
샘플링 모드와 함께 사용됩니다(자세한 내용은 매개변수 참조 섹션 참조). 문서 모드가 기본 모드입니다.
아래 명령은 gpt2 토크나이저를 사용하여 base_dir 에서 허용되는 형식의 모든 파일을 토큰화하고 이를 output_dir 에 저장합니다.
python3 create_tfrecords.py --mode documents --input_dir <base> --name <name> --output_dir <output> --use_gpt2_tokenizer --minimum_size <min>
input_dir
: 데이터가 있는 폴더를 정의합니다. 스크립트는 이 폴더에 있는 모든 파일을 인코딩합니다.name
: 출력 파일의 이름은 name_i.tfrecords
입니다. 여기서 i는 파일 번호입니다.output_dir
: tfrecord를 저장할 위치use_gpt2_tokenizer
: 사전 훈련된 HuggingFace GPT2 토크나이저를 사용할지 여부. 이 경우 구분 기호는 [50256]으로 설정됩니다.encoder_path
: 사전 학습된 gpt2 토크나이저를 사용하지 않는 경우 이 플래그를 사용하여 생성된 토크나이저 json에 대한 경로를 제공합니다.separator
: 목록 형식으로 작성되며 문서 사이에 삽입할 구분 기호 토큰(예: "[0]")입니다. 인코더에 따라 다릅니다.minimum_size
: 문서가 가져야 하는 최소 크기(토큰 단위)입니다. 그렇지 않으면 폐기됩니다. 이것이 나중에 stitch
매개변수를 결정하는 것입니다. stitch * minimum_size
항상 n_ctx
보다 크거나 같아야 합니다(자세한 내용은 매개변수 참조 섹션을 참조하세요). 모델에서 데이터세트를 사용하려면 먼저 해당 데이터세트를 ./configs/dataset_configs
폴더에 등록해야 합니다. 먼저 확장명이 .json
인 파일 이름을 선택하세요. 해당 파일 이름은 데이터세트 식별 역할을 합니다. 구성은 다음과 같은 방식으로 작성되어야 합니다.
사전 학습된 gpt2 토크나이저를 사용하여 인코딩된 데이터세트가 있는 경우 다음과 같이 지정할 수 있습니다.
{
"n_vocab" : 50257 ,
"path" : " gs://neo-datasets/openwebtext-documents/openwebtext_*.tfrecords " ,
"eval_path" : " gs://neo-datasets/openwebtext-documents/openwebtext_*.tfrecords " ,
"tokenizer_is_pretrained" : true ,
"tokenizer_path" : " gpt2 "
}
또는 다음과 같이 사용자 정의 토크나이저를 교육한 경우:
{
"n_vocab" : 32768 ,
"path" : " ./path/to/your/*.tfrecords " ,
"eval_path" : " ./path/to/your/eval/*.tfrecords " ,
"tokenizer_path" : " ./path/to/your/byte-level-bpe.tokenizer.json "
}
마지막으로 모델 구성에서 위에서 생성한 파일 이름을 datasets
배열에 추가합니다.
<dataset id>
는 위에서 생성한 .json
을 제외한 파일 이름입니다.
"datasets": [[<dataset id>, <stitch>, <datatype>, <weight>]] # datasets key defines at run time how each dataset is processed for training
데이터세트를 설정한 후 /configs
에서 적합한 구성을 찾으세요.
여기서는 GPT3-XL 크기의 모델을 예로 사용하지만 ./configs
에는 더 많은 모델이 있으며, 모두 사용 가능한 구성 섹션에 간략한 요약이 있습니다.
위에서 설명한 대로 데이터 세트 ID를 편집하고, 쓰기 액세스 권한이 있는 클라우드 버킷(또는 GPU를 사용하는 경우 로컬 경로)을 가리키도록 model_path
(로그 및 체크포인트가 저장되는 위치)를 편집하기만 하면 됩니다.
{
"n_head" : 32 ,
"n_vocab" : 50257 ,
"embed_dropout" : 0.1 ,
"lr" : 0.0002 ,
"lr_decay" : " cosine " ,
"warmup_steps" : 3000 ,
"beta1" : 0.9 ,
"beta2" : 0.95 ,
"epsilon" : 1e-8 ,
"opt_name" : " adam " ,
"weight_decay" : 0.1 ,
"train_batch_size" : 512 ,
"attn_dropout" : 0.1 ,
"train_steps" : 286150 ,
"eval_steps" : 0 ,
"predict_steps" : 1 ,
"res_dropout" : 0.1 ,
"eval_batch_size" : 128 ,
"predict_batch_size" : 1 ,
"iterations" : 2500 ,
"n_embd" : 2048 ,
"datasets" : [[ " your_dataset_name " , 25 , " documents_random " , 1.0 ]],
"model_path" : " gs://neo-models/GPT3_XL " ,
"n_ctx" : 2048 ,
"n_layer" : 24 ,
"scale_by_depth" : true ,
"scale_by_in" : false ,
"attention_types" : [[[ " global " ], 24 ]],
"mesh_shape" : " x:128,y:2 " ,
"layout" : " batch:x,memory_length:y,embd:y " ,
"activation_function" : " gelu " ,
"recompute_grad" : true ,
"gradient_clipping" : 1.0 ,
"tokens_per_mb_per_replica" : 2048
}
python3 main.py --model <your_config_name> --steps_per_checkpoint <n> --tpu <tpu-name>
tpu
: 사용할 TPU의 이름입니다.steps_per_checkpoint
: 체크포인트를 저장하는 단계의 빈도입니다.--auto_layout
및 --auto_layout_and_mesh_shape
(선택 사항): 교육을 비활성화하고 대신 메모리 효율적인 layout
(및 mesh_shape
)을 자동 생성합니다.gpu_ids
: GPU를 사용하여 훈련하는 경우 tpu
플래그를 생략하고 GPU의 ID를 전달합니다. 아래 예에서는 공백으로 구분된 장치 ID를 지정하여 3개의 GPU를 훈련합니다. python3 main.py --model <your_config_name> --steps_per_checkpoint <n> --gpu_ids <device:GPU:0 device:GPU:1>
여러 모델 크기를 사용할 수 있지만 일부 구성에는 대형 TPU가 필요하며 더 작은 시스템이나 GPU에서 실행하려면 조정이 필요합니다. 다음은 configs 디렉터리의 각 모델에 대한 간단한 가이드입니다.
TODO
Sacred는 실험을 추적하는 데 도움이 되며 텐서보드보다 작업하기가 훨씬 좋습니다.
설정하려면:
Docker 및 Docker-compose 설치
docker-compose up
실행
사용하려면:
model_dir에 메트릭 로그가 없는지 확인하세요(기존 실행의 연속이라고 가정하는 텐서보드에 대한 메트릭 항목을 트립합니다). gsutil rm -r ...
사용하여 모델 디렉토리를 삭제할 수 있습니다.
python3 run_experiment.py --tpu sometpuhere --model someconfig.json
옵션을 실행합니다. 옵션은 main.py
와 동일합니다.
Omniboard 개요를 보려면 http://server_ip_goes_here:8081/로 이동하세요. 텐서보드를 보고 싶다면 스크립트가 하나를 회전시켜 자동으로 포트를 할당합니다. 스크립트는 로그 상단 근처에 텐서보드 포트를 인쇄해야 합니다.
특정 구성 파일의 데이터 세트로 인해 혼란스러운 경우 단일 명령으로 최소 및 최대 토큰 ID를 쉽게 확인할 수 있습니다. 이는 모델의 어휘 크기가 최소한 최대 토큰 ID만큼 큰지 확인하는 데 유용합니다. 범위를 벗어난 인덱스가 있는 행렬을 수집하려고 하면 Tensorflow에서 오류가 발생하지 않으므로 어휘 크기가 충분히 큰지 확인해야 합니다.
python main --model {config_name} --check_dataset
대규모 GPT를 훈련할 수 있을 뿐만 아니라 이 저장소를 사용하면 마스크된 언어 모델링(BERT, RoBERTa)을 쉽게 수행할 수도 있습니다. 그렇게 하려면 두 가지 추가 단계를 수행해야 합니다.
데이터 세트를 토큰화할 때 [mask]
토큰에 대한 특수 ID를 예약해야 합니다.
구성에서 두 개의 추가 필드를 정의해야 합니다.
"mlm_training" : true , # must be set to true
"mlm_mask_id" : < mask id > # the mask id that you reserved from above
이것이 MLM 목표를 사용하여 모델을 훈련하는 데 필요한 전부이며 올바르게 인코딩한 모든 유형의 데이터에 적합합니다. 다른 관련 하이퍼파라미터를 조정하려면 계속해서 읽어보세요.
"mlm_cls_token_id" : < cls token id > , # auto append specified CLS token id on the left
"mlm_mask_prob" : 0.15 , # the probability of masking a token, defaults to 15%
"mlm_same_token_prob" : 0.10 , # probability of keeping the token the same, defaults to 10%
"mlm_random_token_prob" : 0.10 , # probability of tokens that are replaced with random tokens, 10% was recommended by the BERT paper
"mlm_mask_ignore_ids" : [ < cls token > , < sep token > ] # ignore masking other special tokens, if any
/configs
에서 유효한 구성을 선택하고 필요에 따라 매개변수를 조정합니다.
n_heads
: 주의 헤드 수입니다.n_embd
: 히든 레이어의 크기는 n_heads
로 나눌 수 있어야 합니다.n_vocab
: 어휘 크기.embed_dropout
, res_dropout
, attn_dropout
: 단어 임베딩/잔차/주의에 대한 드롭아웃 확률lr
: 학습률warmup_steps
: 전체 학습률에 도달하기 전의 단계 수( 0
에서 lr
까지 선형 램프).lr_decay
: cosine
또는 linear
.opt_name
: adam
또는 adafactor
.beta1
, beta2
및 epsilon
: adam
최적화 매개변수.beta1
, ada_epsilon1
및 ada_epsilon2
: adafactor
최적화 프로그램 매개변수.weight_decay
: 체중 감소 매개변수, 존재하지 않는 경우 체중 감소가 사용되지 않습니다(Adam에 대한 체중 감소 수정이 사용됨)(기본값: 0.01)(선택 사항).train_batch_size
: 훈련 중 배치 크기입니다.train_steps
: 훈련 단계(배치) 수, 현재 대략 1세대로 설정됩니다(데이터 세트의 총 토큰 수 / 배치당 토큰 수(= train_batch_size
/ n_ctx
)).eval_steps
: 각 평가에 대해 실행할 단계 수입니다. 평가하지 않으려면 0
으로 설정합니다. 즉, 모든 체크포인트 후에 모델은 eval_steps
에 대해 테스트됩니다.iterations
: TPU에 대기 중인 단계 수는 steps_per_checkpoint
보다 작아야 합니다. (기본값: 500)datasets
: 사용할 tfrecords 데이터세트 목록입니다. 각 데이터세트는 [train glob , eval glob, stitch, sampling_mode, weight]
매개변수가 포함된 목록입니다. 따라서 단일 데이터세트의 경우(이중 목록 참고): [["bundestag_*.tfrecords", "", 10, "random_sample", 1.0]]
dataset_id
: ./configs/dataset_configs
에 있는 데이터 세트 구성 파일의 이름stitch
: sampling_mode
random_sample
사용하면 입력 파이프라인은 이 양의 텍스트를 하나로 샘플링하여 샘플링합니다. stitch * minimum_document_length >= n_ctx
되도록 스티치를 선택해야 합니다.sampling_mode
: chunks
(tfrecord는 올바른 길이로 전처리되어 순차적으로 읽음) 또는 documents_random
(문서의 stitch
양이 연결된 다음 n_ctx
청크가 무작위로 서브샘플링됨)weights
: 이 데이터세트가 다른 데이터세트와 비교되어야 하는 상대적 가중치입니다.model
: 훈련할 모델입니다. 현재는 GPT
만 지원되며 GPT가 없으면 기본값으로 설정됩니다.model_path
: 모델 체크포인트 및 로그를 저장하기 위한 Google 스토리지 버킷 위치(또는 GPU를 사용하는 경우 로컬 경로)입니다.n_ctx
: 컨텍스트 창의 크기입니다. 기본값은 2048입니다.n_layer
: 모델의 레이어(블록) 수입니다.scale_by_depth
: true인 경우 레이어의 가중치 초기화는 GPT2 논문에서와 같이 깊이에 따라 크기가 조정됩니다.scale_by_in
: true인 경우 레이어의 가중치 초기화는 GPT2 논문에서와 같이 입력 수에 따라 크기가 조정됩니다.mesh_shape
: 메시는 mesh-tensorflow 라이브러리에서 병렬 처리에 사용되는 명명된 차원을 가진 프로세서의 n차원 배열입니다. 각 Tensor는 레이아웃에 따라 메시 차원에 균등하게 분할됩니다(아래 참조). 'mesh_shape'는 이 배열의 모양이며 프로세서 수와 동일해야 합니다. 예를 들어 v3-128 TPU의 경우 "mesh_shape": "x:16,y:8"입니다.layout
: Tensor는 각 프로세서에 하나의 슬라이스로 메시에 배치됩니다. 텐서 "레이아웃"은 텐서의 어느 차원이 메시의 어느 차원에 걸쳐 (균등하게) 분할되는지를 지정하는 주입식 부분 맵입니다. 텐서의 어떤 차원도 메시의 두 차원으로 분할될 수 없으며, 텐서의 두 차원도 메시의 동일한 차원으로 분할될 수 없습니다. 사용자는 (텐서-차원-이름, 메쉬-차원-이름) 쌍의 형태로 레이아웃 규칙의 전역 세트를 정의합니다. 일치하는 규칙이 있는 경우 텐서의 차원은 메시의 차원으로 분할됩니다(예: 위의 예에서는 mesh_shape: "layout":"batch:x,heads:y").activation_function
: selu
(자체 정규화) 또는 gelu
(OA에서 사용), 피드포워드 전달에 사용되는 활성화 함수입니다. (기본값: gelu)attention_types
: [[["attention_type"], n_layers]] 형식의 목록으로 각 레이어에 대한 주의 유형입니다. 예를 들어 12개 레이어 네트의 경우 [[["global"], 12]] 또는 [[["local"], 10], [["global"], 2]]입니다.linear
, global
, local
또는 none
중에서 선택하세요. 우리는 global
과 linear
의 50/50 혼합이 잘 작동한다는 것을 발견했습니다. none
보다 효율적인 PAR Transformer 모델을 위해 피드포워드 전용 레이어를 생성할 수 없습니다.precision
: float32
또는 bfloat16
.tokens_per_mb_per_replica
: None이 아닌 경우 배치를 tokens_per_mb_per_replica
토큰을 포함하는 더 작은 마이크로 배치로 분할하여 OOM을 방지합니다. 그라데이션은 로컬로 누적되고 한 번 감소됩니다. 중요: 여기서 mb는 메가바이트가 아닌 미니배치 를 나타냅니다.전문가의 혼합
moe_layers
: 전문가 레이어 혼합을 추가할 레이어 번호 목록입니다. 예: [2,4,6,8,10,12]
. 우리는 두 개의 self-attention 레이어마다 잘 작동하는 moe 레이어를 실험적으로 발견했습니다.moe_params
: moe 레이어에 전달할 추가 kwargs 사전입니다. 예 {"moe_dropout_rate": 0.0 }
실험적 기능
axial_pos_emb_
: true인 경우 [축 위치 임베딩](https://arxiv.org/abs/1912.12180.mlp_glu
: true인 경우 피드포워드 레이어의 게이트 선형 단위 변형을 사용합니다.scalenorm
: true인 경우 layernorm 대신 scalenorm을 사용합니다.rezero
: true인 경우 layernorm 대신 rezero를 사용합니다.num_mem_kv
: All-Attention Paper의 메모리/키 값을 추가합니다. Param은 원하는 mem/key 값의 개수를 가진 int입니다.macaron
: true인 경우 - 각 레이어 블록에 마카롱 변환기를 사용합니다. GPT-Neo가 작업에 도움이 되었다고 생각하시면 이 저장소를 다음과 같이 인용하실 수 있습니다.
@software{gpt-neo,
author = {Black, Sid and
Gao, Leo and
Wang, Phil and
Leahy, Connor and
Biderman, Stella},
title = {{GPT-Neo: Large Scale Autoregressive Language
Modeling with Mesh-Tensorflow}},
month = mar,
year = 2021,
note = {{If you use this software, please cite it using
these metadata.}},
publisher = {Zenodo},
version = {1.0},
doi = {10.5281/zenodo.5297715},
url = {https://doi.org/10.5281/zenodo.5297715}
}
버전 번호는 사용 중인 버전 번호로 바꿔야 하며 연도는 프로젝트의 오픈 소스 릴리스에 해당합니다.
Pile에서 훈련된 GPT-Neo 모델을 인용하는 데 특별히 관심이 있는 경우 다음 항목도 인용해 주시면 감사하겠습니다.
@article{gao2020pile,
title={The Pile: An 800GB Dataset of Diverse Text for Language Modeling},
author={Gao, Leo and Biderman, Stella and Black, Sid and Golding, Laurence and Hoppe, Travis and Foster, Charles and Phang, Jason and He, Horace and Thite, Anish and Nabeshima, Noa and others},
journal={arXiv preprint arXiv:2101.00027},
year={2020}
}