Spaces:
Paused
Paused
<!--Copyright 2020 The HuggingFace Team. All rights reserved. | |
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | |
the License. You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | |
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | |
specific language governing permissions and limitations under the License. | |
--> | |
# κ³ μ κΈΈμ΄ λͺ¨λΈμ ννλ μν°(Perplexity)[[perplexity-of-fixedlength-models]] | |
[[open-in-colab]] | |
ννλ μν°(Perplexity, PPL)λ κ°μ₯ μΌλ°μ μΈ μΈμ΄ λͺ¨λΈ νκ°μ§ν μ€ νλμ λλ€. | |
μμΈν μμ보기 μ μ μ΄ νκ°μ§νλ κ³ μ μ μΈ μΈμ΄ λͺ¨λΈ(μκΈ°νκ· λλ μΈκ³Όμ μΈμ΄ λͺ¨λΈμ΄λΌκ³ λ ν¨)μλ§ μ μ©λλ©° BERTμ κ°μ λ§μ€νΉλ μΈμ΄ λͺ¨λΈμλ μ μ μ©νμ§ μμ΅λλ€ (BERTλ [summary of the models](../en/model_summary) λ¬Έμλ₯Ό μ°Έκ³ νμΈμ). | |
ννλ μν°λ μνμ€μ μμ λ‘κ·Έ μ°λ(negative log-likelihood, NLL) κ°μ νκ· μ μ§μ(exponentiate)λ₯Ό μ·¨ν κ°μΌλ‘ μ μλ©λλ€. | |
ν ν°νλ μνμ€ \\(X = (x_0, x_1, \dots, x_t)\\) κ° μμ λ, \\(X\\) μ ννλ μν°λ μλ μμκ³Ό κ°μ΄ ꡬν μ μμ΅λλ€. | |
$$\text{PPL}(X) = \exp \left\{ {-\frac{1}{t}\sum_i^t \log p_\theta (x_i|x_{<i}) } \right\}$$ | |
\\(\log p_\theta (x_i|x_{<i})\\) λ λͺ¨λΈμ iλ²μ§Έ μ΄μ κΉμ§ ν ν°μ΄ μ£Όμ΄μ‘μ λ iλ²μ§Έ ν ν°μ λ‘κ·Έ μ°λκ°μ λλ€. | |
μ§κ΄μ μΌλ‘ λ§λμΉμμ μ§μ λ ν ν° μ§ν©μ κ· μΌνκ² μμΈ‘νλ λͺ¨λΈμ λ₯λ ₯μ λν νκ°λ‘ μκ°ν μ μμ΅λλ€. | |
μ€μν μ μ ν ν°ν κ³Όμ μ΄ λͺ¨λΈμ ννλ μν°μ μ§μ μ μΈ μν₯μ λ―ΈμΉλ―λ‘ μλ‘ λ€λ₯Έ λͺ¨λΈμ λΉκ΅ν λ νμ μ΄λ₯Ό κ³ λ €ν΄μΌ ν©λλ€. | |
μ΄λ λ°μ΄ν°μ λͺ¨λΈ μμΈ‘ κ°μ cross-entropy κ°μ μ§μλ₯Ό μ·¨ν κ²κ³Ό λμΌν©λλ€. | |
ννλ μν°μ λ¬ΈμλΉ λΉνΈ μ(BPC) λ° λ°μ΄ν° μμΆκ³Όμ κ΄κ³μ λν΄ λ μ§κ΄μ μΈ μ΄ν΄λ₯Ό μνμ λ€λ©΄ λ€μ κΈ | |
[fantastic blog post on The Gradient](https://thegradient.pub/understanding-evaluation-metrics-for-language-models/)μ νμΈνμΈμ. | |
## κ³ μ κΈΈμ΄ λͺ¨λΈμ ννλ μν°(PPL) κ³μ°νκΈ°[[calculating-ppl-with-fixedlength-models]] | |
λͺ¨λΈμ 컨ν μ€νΈ ν¬κΈ°κ° μ ν΄μ Έμμ§ μλ€λ©΄, | |
μλμ κ°μ΄ μνμ€λ₯Ό μλ νκ·μ μΌλ‘ λΆν΄νκ³ κ° λ¨κ³μμ μ ν νλ μ 체 μνμ€λ₯Ό μ‘°κ±΄λΆ νλ₯ μ λ£μ΄ λͺ¨λΈμ ννλ μν°λ₯Ό κ³μ°ν κ²μ λλ€. | |
<img width="600" alt="Full decomposition of a sequence with unlimited context length" src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/ppl_full.gif"/> | |
κ·Έλ¬λ λͺ¨λΈμ κ·Όμ¬μΉλ₯Ό ꡬν λλ μΌλ°μ μΌλ‘ λͺ¨λΈμ΄ μ²λ¦¬ν μ μλ ν ν° μμ μ νμ΄ μμ΅λλ€. | |
μλ₯Ό λ€μ΄, κ°μ₯ ν° λ²μ μ [GPT-2](model_doc/gpt2)λ ν ν°μ κΈΈμ΄κ° 1024λ‘ κ³ μ λμ΄ μμ΅λλ€. | |
λ°λΌμ \\(t\\) κ° 1024λ³΄λ€ ν° κ²½μ°μ \\(p_\theta(x_t|x_{<t})\\) μ κ³μ°ν μ μμ΅λλ€. | |
λμ μνμ€λ μΌλ°μ μΌλ‘ λͺ¨λΈμ μ΅λ μ λ ₯ ν¬κΈ°μ λμΌν κΈΈμ΄λ κ°μ§λ λΆλΆ μνμ€λ‘ μͺΌκ°λλ€. | |
λ§μ½ λͺ¨λΈμ μ΅λ μ λ ₯ κΈΈμ΄κ° \\(k\\) λΌλ©΄, | |
ν ν° \\(x_t\\) μ μ°λ κ°μ κ³μ°ν λ μ΄μ ν ν°μ λͺ¨λ μ¬μ©νμ§ μκ³ , \\(k-1\\) ν ν°κΉμ§ μ¬μ©ν΄ λλ΅μ μΈ μ°λ κ°μ μΆμ ν©λλ€. | |
λͺ¨λΈμ μνμ€μ λν ννλ μν°λ₯Ό κ³μ°ν λ, | |
μμνμ§λ§ μ°¨μ μ± μ μνμ€λ₯Ό μ²ν¬λ‘ μͺΌκ°κ³ λΆν΄λ κ° λΆλΆμ λ‘κ·Έ μ°λ κ°μ λ 립μ μΌλ‘ ν©μ°νλ κ²μ λλ€. | |
<img width="600" alt="Suboptimal PPL not taking advantage of full available context" src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/ppl_chunked.gif"/> | |
μ΄ λ°©λ²μ κ° λΆλΆμ ννλ μν°λ₯Ό ν λ²μ ν¬μλ ν¨μ€λ‘ κ³μ°ν μ μμ΄ λΉ λ₯΄μ§λ§ μΌλ°μ μΌλ‘ λ λμ(λ λμ) PPLμ μ°μΆν©λλ€. | |
μλνλ©΄ λλΆλΆμ μμΈ‘ λ¨κ³μμ λͺ¨λΈμ 컨ν μ€νΈκ° μ κΈ° λλ¬Έμ λλ€. | |
λμ , κ³ μ κΈΈμ΄ λͺ¨λΈμ PPLμ μ¬λΌμ΄λ© μλμ° μ λ΅μΌλ‘ νκ°ν΄μΌ ν©λλ€. | |
μ΄ μ λ΅μλ 컨ν μ€νΈ μλμ°μ λ°λ³΅μ μΌλ‘ μ¬λΌμ΄λ©ν΄ λͺ¨λΈμ΄ κ° μμΈ‘μ μνν λ λ λ§μ 컨ν μ€νΈλ₯Ό κ°λλ‘ νλ μμ μ΄ ν¬ν¨λ©λλ€. | |
<img width="600" alt="Sliding window PPL taking advantage of all available context" src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/ppl_sliding.gif"/> | |
μ΄λ μνμ€ νλ₯ μ μ€μ λΆν΄μ λ κ°κΉμ΄ κ·Όμ¬μΉμ΄λ©° μΌλ°μ μΌλ‘ λ μ 리ν μ μλ₯Ό μ°μΆν©λλ€. | |
λ¨μ μ λ§λμΉμ κ° ν ν°μ λν΄ λ³λμ ν¬μλ ν¨μ€κ° νμνλ€λ κ²μ λλ€. | |
νμ€μ μΌλ‘ μ’μ μ μΆ©μμ ν λ²μ ν ν ν°μ© μ¬λΌμ΄λ©νλ κ²μ΄ μλλΌ λ ν° κ°κ²©μΌλ‘ 컨ν μ€νΈλ₯Ό μ΄λνλ μ€νΈλΌμ΄λκ° μ μ©λ μ¬λΌμ΄λ© μλμ°μ μ¬μ©νλ κ²μ λλ€. | |
μ΄λ κ² νλ©΄ κ³μ°μ ν¨μ¬ λ λΉ λ₯΄κ² μ§ννλ©΄μλ λͺ¨λΈμ κ° λ¨κ³μμ μμΈ‘μ μνν μ μλ κΈ΄ 컨ν μ€νΈλ₯Ό μ 곡ν μ μμ΅λλ€. | |
## μμ : π€ Transformersμμ GPT-2λ‘ ννλ μν°(perplexity) κ³μ°νκΈ°[[example-calculating-perplexity-with-gpt2-in-transformers]] | |
μ΄μ GPT-2λ‘ μμ κ³Όμ μ μμ°ν΄ λ³΄κ² μ΅λλ€. | |
```python | |
from transformers import GPT2LMHeadModel, GPT2TokenizerFast | |
device = "cuda" | |
model_id = "gpt2-large" | |
model = GPT2LMHeadModel.from_pretrained(model_id).to(device) | |
tokenizer = GPT2TokenizerFast.from_pretrained(model_id) | |
``` | |
WikiText-2 λ°μ΄ν° μΈνΈλ₯Ό κ°μ Έμ€κ³ λͺ κ°μ§ μ¬λΌμ΄λ© μλμ° μ λ΅μ μ¬μ©ν΄ ννλ μν°λ₯Ό κ³μ°ν΄λ³΄κ² μ΅λλ€. | |
μ΄ λ°μ΄ν° μΈνΈλ ν¬κΈ°κ° μκ³ ν¬μλ ν¨μ€ ν λ²λ§ μννκΈ° λλ¬Έμ μ 체 λ°μ΄ν° μΈνΈλ₯Ό λ©λͺ¨λ¦¬μ κ°μ Έμ€κ³ μΈμ½λ©ν μ μμ΅λλ€. | |
```python | |
from datasets import load_dataset | |
test = load_dataset("wikitext", "wikitext-2-raw-v1", split="test") | |
encodings = tokenizer("\n\n".join(test["text"]), return_tensors="pt") | |
``` | |
π€ Transformersλ₯Ό μ¬μ©νλ©΄ λͺ¨λΈμ `labels`λ‘ `input_ids`λ₯Ό μ λ¬ν΄ κ° ν ν°μ λν νκ· μμ μ°λ κ°μ μμ€λ‘ λ°νν μ μμ΅λλ€. | |
νμ§λ§ μ¬λΌμ΄λ© μλμ° λ°©μμ μ¬μ©νλ©΄ κ° λ°λ³΅λ§λ€ λͺ¨λΈμ μ λ¬νλ ν ν°μ΄ κ²ΉμΉ©λλ€. | |
컨ν μ€νΈλ‘ μ²λ¦¬νλ ν ν°μ λν λ‘κ·Έ μ°λ κ°μ΄ μμ€μ ν¬ν¨λλ κ²μ μνμ§ μκΈ° λλ¬Έμ μ΄λ¬ν ν ν°μ `input_ids`λ₯Ό `-100`μΌλ‘ μ€μ νμ¬ λ¬΄μν μ μμ΅λλ€. | |
λ€μμ μ€νΈλΌμ΄λ(stride)λ₯Ό `512`λ‘ μ¬μ©ν μμμ λλ€. | |
μ¦, λͺ¨λΈμ΄ ν ν ν°μ μ‘°κ±΄λΆ μ°λ κ°μ κ³μ°ν λ 컨ν μ€νΈμ μ΅μν 512κ°μ ν ν°μ΄ ν¬ν¨λμ΄μλ€λ μλ―Έμ λλ€ (ν΄λΉ ν ν° μμ 512κ°μ ν ν°μ΄ μλ κ²½μ°). | |
```python | |
import torch | |
from tqdm import tqdm | |
max_length = model.config.n_positions | |
stride = 512 | |
seq_len = encodings.input_ids.size(1) | |
nlls = [] | |
prev_end_loc = 0 | |
for begin_loc in tqdm(range(0, seq_len, stride)): | |
end_loc = min(begin_loc + max_length, seq_len) | |
trg_len = end_loc - prev_end_loc # λ§μ§λ§ 루νμ μ€νΈλΌμ΄λ κ°κ³Ό λ€λ₯Ό μ μμ | |
input_ids = encodings.input_ids[:, begin_loc:end_loc].to(device) | |
target_ids = input_ids.clone() | |
target_ids[:, :-trg_len] = -100 | |
with torch.no_grad(): | |
outputs = model(input_ids, labels=target_ids) | |
# μμ€μ λͺ¨λ μ ν¨ν λ μ΄λΈμ λν νκ· κ°μ ꡬνλ κ΅μ°¨ μνΈλ‘νΌ(cross entropy)λ‘ κ³μ°λ©λλ€. | |
# λμ΄λΈ λ² μ΄μ§μ λͺ¨λΈμ λ΄λΆμ μΌλ‘ λ μ΄λΈμ μΌμͺ½μΌλ‘ 1κ°μ© λ°κΈ° λλ¬Έμ, (νμΌ - 1)κ° λ§νΌμ λ μ΄λΈμ λν΄ μμ€μ κ³μ°ν©λλ€. | |
neg_log_likelihood = outputs.loss | |
nlls.append(neg_log_likelihood) | |
prev_end_loc = end_loc | |
if end_loc == seq_len: | |
break | |
ppl = torch.exp(torch.stack(nlls).mean()) | |
``` | |
μ€νΈλΌμ΄λλ₯Ό μ΅λ μ λ ₯ κΈΈμ΄μ λμΌνκ² μ€μ νλ©΄ μμμ μ€λͺ ν μ°¨μ μ± μΈ λΉμ¬λΌμ΄λ© μλμ° μ λ΅κ³Ό λμΌν©λλ€. | |
μΌλ°μ μΌλ‘ μ€νΈλΌμ΄λκ° μμμλ‘ λͺ¨λΈμ΄ κ° μμΈ‘μ ν λ λ λ§μ 컨ν μ€νΈλ₯Ό λ³Ό μ μκ² λμ΄ ννλ μν° κ°μ΄ μ’μμ§λλ€. | |
μμ κ³μ°μ ν ν°μ΄ κ²ΉμΉμ§ μλλ‘ `stride = 1024`λ‘ μ€μ νλ©΄ PPLμ `19.44`λ‘ GPT-2 λ Όλ¬Έμμ λ³΄κ³ λ `19.93`κ³Ό κ±°μ λμΌν©λλ€. | |
`stride = 512`λ‘ μ¬λΌμ΄λ© μλμ° μ λ΅μ μ¬μ©νλ©΄ PPLμ `16.45`λ‘ λ¨μ΄μ§λλ€. | |
μ΄λ λ μ’μ μ μμΌ λΏλ§ μλλΌ μνμ€ νλ₯ μ μ€μ μλ νκ· λΆν΄μ λ κ°κΉμ΄ λ°©μμΌλ‘ κ³μ°λ©λλ€. |