Este projeto pretende ser uma reimplementação limpa e concisa do GPT-2. A implementação do modelo, contida em src/model.rs
, tem menos de 300 linhas de código. Embora este tenha sido um exercício divertido principalmente para fins educacionais (meus), ele demonstra a utilidade do Rust and Burn no domínio do aprendizado de máquina: todo o projeto é compilado em um único binário, tornando a implantação relativamente simples.
No momento, apenas um tokenizador de nível de personagem é suportado, portanto, os pesos oficiais que exigem um tokenizador BPE ainda não podem ser usados. No entanto, para se divertir, você pode experimentar o pequeno modelo de brinquedo que treinei (ver inferência).
O projeto também inclui uma CLI simples para treinamento e inferência.
Usage: gpt-burn <COMMAND>
Commands:
run Generate text using a pre-trained model
train Train a new model
Você pode instalar gpt-burn
com Nix:
nix run github:felix-andreas/gpt-burn
Ou instale com cargo
:
cargo install --git https://github.com/felix-andreas/gpt-burn
Alternativamente, clone o repositório e construa a partir do código-fonte:
nix develop # optional
cargo run --release
Se você não usa Nix e está em uma distribuição baseada em Ubuntu, você precisa instalar estas dependências adicionais:
apt install pkg-config libssl-dev libvulkan1 mesa-vulkan-drivers vulkan-tools
Treinei um modelo de brinquedo com um tokenizador de nível de personagem no corpus alemão da Wikipedia para 20.000 lotes (tamanho de lote de 128) com os seguintes parâmetros:
Parâmetro | Valor |
---|---|
parâmetros | 83 milhões |
comprimento do contexto | 128 |
n_layers | 12 |
n_heads | 12 |
d_model | 768 |
Você pode baixá-lo aqui e extraí-lo depois. Ou faça as duas coisas em um único comando:
curl -s ' https://drive.usercontent.google.com/download?id=1GGLaPnmPQ8Z2B9vJQoI6-K128X9LJKG0&export=download&confirm=t ' | tar xzf -
Em seguida, execute o modelo:
gpt-burn run ./model_83M
Você deverá ver algo assim:
So wurden bis 1977 679 nachhaltige Wörgler Torbauten vorgeworfen, die Einwohnerzahl Sirkes bestand 2015 bis 1998.
Sie war trotz weniger als 10.000 ausgedehnter Größen wahrscheinlich auf folgende Breitenauflagen mit 932 km.
2016 wurden rund 145 Händen nach Deutschland geladen.
Outras opções de linha de comando são:
Usage: gpt-burn run [OPTIONS] <MODEL_PATH>
Arguments:
<MODEL_PATH>
Options:
-p, --prompt <PROMPT>
-n, --n-new-tokens <N_NEW_TOKENS> [default: 1000]
-s, --seed <SEED> [default: 0]
Para treinar seu próprio modelo, execute:
gpt-burn train --context-length 128 --n-layers 12 --n-heads 12 --d-model 768 --batch-size 128 --learning-rate 0.0003 --seed 0 --text-corpus ./corpus.txt
Importante
Certifique-se de que corpus.txt
seja um arquivo de texto codificado em utf-8!
Você pode passar a maioria dos hiperparâmetros como uma opção de linha de comando:
Usage: gpt-burn train [OPTIONS]
Options:
-o, --output-path <PATH>
-c, --context-length <CONTEXT_LENGTH> [default: 64]
-d, --d-model <D_MODEL> [default: 64]
-l, --n-layers <N_LAYERS> [default: 2]
-h, --n-heads <N_HEADS> [default: 2]
-n, --n-steps <N_STEPS> [default: 50]
-b, --batch-size <BATCH_SIZE> [default: 32]
-r, --learning-rate <LEARNING_RATE> [default: 0.003]
-s, --seed <SEED> [default: 0]
-t, --text-corpus <TEXT_CORPUS> [default: .data/corpus.txt]
-m, --n-mega-bytes <N_MEGA_BYTES> Only use first <n> megabytes of dataset for training
-x, --no-save Don't save trained model (useful for debugging)
O modelo pode ser usado com diferentes tokenizadores por meio da característica Tokenizer
. Abaixo você vê como a seguinte frase
Albert Einstein war ein schweizerisch-US-amerikanischer theoretischer Physiker deutscher Herkunft.
é codificado pelos diferentes tokenizers.
O CharTokenizer
divide cada caractere em um token separado:
Tokens: ["A", "l", "b", "e", "r", "t", " ", "E", "i", "n", "s", "t", "e", "i", "n", " ", "w", "a", "r", " ", "e", "i", "n", " ", "s", "c", "h", "w", "e", "i", "z", "e", "r", "i", "s", "c", "h", "-", "U", "S", "-", "a", "m", "e", "r", "i", "k", "a", "n", "i", "s", "c", "h", "e", "r", " ", "t", "h", "e", "o", "r", "e", "t", "i", "s", "c", "h", "e", "r", " ", "P", "h", "y", "s", "i", "k", "e", "r", " ", "d", "e", "u", "t", "s", "c", "h", "e", "r", " ", "H", "e", "r", "k", "u", "n", "f", "t", "."]
Values: [28, 13, 3, 6, 19, 21, 1, 32, 10, 15, 20, 21, 6, 10, 15, 1, 24, 2, 19, 1, 6, 10, 15, 1, 20, 4, 9, 24, 6, 10, 27, 6, 19, 10, 20, 4, 9, 66, 48, 46, 66, 2, 14, 6, 19, 10, 12, 2, 15, 10, 20, 4, 9, 6, 19, 1, 21, 9, 6, 16, 19, 6, 21, 10, 20, 4, 9, 6, 19, 1, 43, 9, 26, 20, 10, 12, 6, 19, 1, 5, 6, 22, 21, 20, 4, 9, 6, 19, 1, 35, 6, 19, 12, 22, 15, 7, 21, 67]
O SimpleVowelTokenizer
divide as palavras antes da próxima vogal se o pedaço tiver mais de três caracteres, criando um resultado semelhante a sílabas:
Tokens: ["Albert", " ", "Einst", "ein", " ", "war", " ", "ein", " ", "schw", "eizer", "isch", "-", "US", "-", "amer", "ikan", "isch", "er", " ", "theor", "etisch", "er", " ", "Phys", "iker", " ", "deutsch", "er", " ", "Herk", "unft"]
Values: [2, 0, 3, 9, 0, 19, 0, 9, 0, 16, 10, 15, 1, 6, 1, 7, 13, 15, 11, 0, 17, 12, 11, 0, 5, 14, 0, 8, 11, 0, 4, 18]