Spaces:
Paused
Paused
File size: 8,996 Bytes
ee6e328 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
<!--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`λ‘ λ¨μ΄μ§λλ€.
μ΄λ λ μ’μ μ μμΌ λΏλ§ μλλΌ μνμ€ νλ₯ μ μ€μ μλ νκ· λΆν΄μ λ κ°κΉμ΄ λ°©μμΌλ‘ κ³μ°λ©λλ€. |