Spaces:
Paused
Paused
File size: 12,388 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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
<!--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
β οΈ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
rendered properly in your Markdown viewer.
-->
# μ΄λ»κ² μ¬μ©μ μ μ νμ΄νλΌμΈμ μμ±νλμ? [[how-to-create-a-custom-pipeline]]
μ΄ κ°μ΄λμμλ μ¬μ©μ μ μ νμ΄νλΌμΈμ μ΄λ»κ² μμ±νκ³ [νλΈ](hf.co/models)μ 곡μ νκ±°λ π€ Transformers λΌμ΄λΈλ¬λ¦¬μ μΆκ°νλ λ°©λ²μ μ΄ν΄λ³΄κ² μ΅λλ€.
λ¨Όμ νμ΄νλΌμΈμ΄ μμ©ν μ μλ μμ μ
λ ₯μ κ²°μ ν΄μΌ ν©λλ€.
λ¬Έμμ΄, μμ λ°μ΄νΈ, λμ
λ리 λλ κ°μ₯ μνλ μ
λ ₯μΌ κ°λ₯μ±μ΄ λμ κ²μ΄λ©΄ 무μμ΄λ κ°λ₯ν©λλ€.
μ΄ μ
λ ₯μ κ°λ₯ν ν μμν Python νμμΌλ‘ μ μ§ν΄μΌ (JSONμ ν΅ν΄ λ€λ₯Έ μΈμ΄μλ) νΈνμ±μ΄ μ’μμ§λλ€.
μ΄κ²μ΄ μ μ²λ¦¬(`preprocess`) νμ΄νλΌμΈμ μ
λ ₯(`inputs`)μ΄ λ κ²μ
λλ€.
κ·Έλ° λ€μ `outputs`λ₯Ό μ μνμΈμ.
`inputs`μ κ°μ μ μ±
μ λ°λ₯΄κ³ , κ°λ¨ν μλ‘ μ’μ΅λλ€.
μ΄κ²μ΄ νμ²λ¦¬(`postprocess`) λ©μλμ μΆλ ₯μ΄ λ κ²μ
λλ€.
λ¨Όμ 4κ°μ λ©μλ(`preprocess`, `_forward`, `postprocess` λ° `_sanitize_parameters`)λ₯Ό ꡬννκΈ° μν΄ κΈ°λ³Έ ν΄λμ€ `Pipeline`μ μμνμ¬ μμν©λλ€.
```python
from transformers import Pipeline
class MyPipeline(Pipeline):
def _sanitize_parameters(self, **kwargs):
preprocess_kwargs = {}
if "maybe_arg" in kwargs:
preprocess_kwargs["maybe_arg"] = kwargs["maybe_arg"]
return preprocess_kwargs, {}, {}
def preprocess(self, inputs, maybe_arg=2):
model_input = Tensor(inputs["input_ids"])
return {"model_input": model_input}
def _forward(self, model_inputs):
# model_inputs == {"model_input": model_input}
outputs = self.model(**model_inputs)
# Maybe {"logits": Tensor(...)}
return outputs
def postprocess(self, model_outputs):
best_class = model_outputs["logits"].softmax(-1)
return best_class
```
μ΄ λΆν ꡬ쑰λ CPU/GPUμ λν λΉκ΅μ μνν μ§μμ μ 곡νλ λμμ, λ€λ₯Έ μ€λ λμμ CPUμ λν μ¬μ /μ¬ν μ²λ¦¬λ₯Ό μνν μ μκ² μ§μνλ κ²μ
λλ€.
`preprocess`λ μλ μ μλ μ
λ ₯μ κ°μ Έμ λͺ¨λΈμ 곡κΈν μ μλ νμμΌλ‘ λ³νν©λλ€.
λ λ§μ μ 보λ₯Ό ν¬ν¨ν μ μμΌλ©° μΌλ°μ μΌλ‘ `Dict` ννμ
λλ€.
`_forward`λ ꡬν μΈλΆ μ¬νμ΄λ©° μ§μ νΈμΆν μ μμ΅λλ€.
`forward`λ μμ μ₯μΉμμ λͺ¨λ κ²μ΄ μλνλμ§ νμΈνκΈ° μν μμ μ₯μΉκ° ν¬ν¨λμ΄ μμ΄ μ νΈλλ νΈμΆ λ©μλμ
λλ€.
μ€μ λͺ¨λΈκ³Ό κ΄λ ¨λ κ²μ `_forward` λ©μλμ μνλ©°, λλ¨Έμ§λ μ μ²λ¦¬/νμ²λ¦¬ κ³Όμ μ μμ΅λλ€.
`postprocess` λ©μλλ `_forward`μ μΆλ ₯μ κ°μ Έμ μ΄μ μ κ²°μ ν μ΅μ’
μΆλ ₯ νμμΌλ‘ λ³νν©λλ€.
`_sanitize_parameters`λ μ΄κΈ°ν μκ°μ `pipeline(...., maybe_arg=4)`μ΄λ νΈμΆ μκ°μ `pipe = pipeline(...); output = pipe(...., maybe_arg=4)`κ³Ό κ°μ΄, μ¬μ©μκ° μνλ κ²½μ° μΈμ λ μ§ λ§€κ°λ³μλ₯Ό μ λ¬ν μ μλλ‘ νμ©ν©λλ€.
`_sanitize_parameters`μ λ°ν κ°μ `preprocess`, `_forward`, `postprocess`μ μ§μ μ λ¬λλ 3κ°μ kwargs λμ
λ리μ
λλ€.
νΈμΆμκ° μΆκ° 맀κ°λ³μλ‘ νΈμΆνμ§ μμλ€λ©΄ μ무κ²λ μ±μ°μ§ λ§μμμ€.
μ΄λ κ² νλ©΄ νμ λ "μμ°μ€λ¬μ΄" ν¨μ μ μμ κΈ°λ³Έ μΈμλ₯Ό μ μ§ν μ μμ΅λλ€.
λΆλ₯ μμ
μμ `top_k` 맀κ°λ³μκ° λνμ μΈ μμ
λλ€.
```python
>>> pipe = pipeline("my-new-task")
>>> pipe("This is a test")
[{"label": "1-star", "score": 0.8}, {"label": "2-star", "score": 0.1}, {"label": "3-star", "score": 0.05}
{"label": "4-star", "score": 0.025}, {"label": "5-star", "score": 0.025}]
>>> pipe("This is a test", top_k=2)
[{"label": "1-star", "score": 0.8}, {"label": "2-star", "score": 0.1}]
```
μ΄λ₯Ό λ¬μ±νκΈ° μν΄ μ°λ¦¬λ `postprocess` λ©μλλ₯Ό κΈ°λ³Έ 맀κ°λ³μμΈ `5`λ‘ μ
λ°μ΄νΈνκ³ `_sanitize_parameters`λ₯Ό μμ νμ¬ μ΄ μ 맀κ°λ³μλ₯Ό νμ©ν©λλ€.
```python
def postprocess(self, model_outputs, top_k=5):
best_class = model_outputs["logits"].softmax(-1)
# top_kλ₯Ό μ²λ¦¬νλ λ‘μ§ μΆκ°
return best_class
def _sanitize_parameters(self, **kwargs):
preprocess_kwargs = {}
if "maybe_arg" in kwargs:
preprocess_kwargs["maybe_arg"] = kwargs["maybe_arg"]
postprocess_kwargs = {}
if "top_k" in kwargs:
postprocess_kwargs["top_k"] = kwargs["top_k"]
return preprocess_kwargs, {}, postprocess_kwargs
```
μ
/μΆλ ₯μ κ°λ₯ν ν κ°λ¨νκ³ μμ ν JSON μ§λ ¬ν κ°λ₯ν νμμΌλ‘ μ μ§νλ €κ³ λ
Έλ ₯νμμμ€.
μ΄λ κ² νλ©΄ μ¬μ©μκ° μλ‘μ΄ μ’
λ₯μ κ°μ²΄λ₯Ό μ΄ν΄νμ§ μκ³ λ νμ΄νλΌμΈμ μ½κ² μ¬μ©ν μ μμ΅λλ€.
λν μ¬μ© μ©μ΄μ±μ μν΄ μ¬λ¬ κ°μ§ μ νμ μΈμ(μ€λμ€ νμΌμ νμΌ μ΄λ¦, URL λλ μμν λ°μ΄νΈμΌ μ μμ)λ₯Ό μ§μνλ κ²μ΄ λΉκ΅μ μΌλ°μ μ
λλ€.
## μ§μλλ μμ
λͺ©λ‘μ μΆκ°νκΈ° [[adding-it-to-the-list-of-supported-tasks]]
`new-task`λ₯Ό μ§μλλ μμ
λͺ©λ‘μ λ±λ‘νλ €λ©΄ `PIPELINE_REGISTRY`μ μΆκ°ν΄μΌ ν©λλ€:
```python
from transformers.pipelines import PIPELINE_REGISTRY
PIPELINE_REGISTRY.register_pipeline(
"new-task",
pipeline_class=MyPipeline,
pt_model=AutoModelForSequenceClassification,
)
```
μνλ κ²½μ° κΈ°λ³Έ λͺ¨λΈμ μ§μ ν μ μμΌλ©°, μ΄ κ²½μ° νΉμ κ°μ (λΆκΈ° μ΄λ¦ λλ μ»€λ° ν΄μμΌ μ μμ, μ¬κΈ°μλ "abcdef")κ³Ό νμ
μ ν¨κ» κ°μ ΈμμΌ ν©λλ€:
```python
PIPELINE_REGISTRY.register_pipeline(
"new-task",
pipeline_class=MyPipeline,
pt_model=AutoModelForSequenceClassification,
default={"pt": ("user/awesome_model", "abcdef")},
type="text", # νμ¬ μ§μ μ ν: text, audio, image, multimodal
)
```
## Hubμ νμ΄νλΌμΈ 곡μ νκΈ° [[share-your-pipeline-on-the-hub]]
Hubμ μ¬μ©μ μ μ νμ΄νλΌμΈμ 곡μ νλ €λ©΄ `Pipeline` νμ ν΄λμ€μ μ¬μ©μ μ μ μ½λλ₯Ό Python νμΌμ μ μ₯νκΈ°λ§ νλ©΄ λ©λλ€.
μλ₯Ό λ€μ΄, λ€μκ³Ό κ°μ΄ λ¬Έμ₯ μ λΆλ₯λ₯Ό μν μ¬μ©μ μ μ νμ΄νλΌμΈμ μ¬μ©νλ€κ³ κ°μ ν΄ λ³΄κ² μ΅λλ€:
```py
import numpy as np
from transformers import Pipeline
def softmax(outputs):
maxes = np.max(outputs, axis=-1, keepdims=True)
shifted_exp = np.exp(outputs - maxes)
return shifted_exp / shifted_exp.sum(axis=-1, keepdims=True)
class PairClassificationPipeline(Pipeline):
def _sanitize_parameters(self, **kwargs):
preprocess_kwargs = {}
if "second_text" in kwargs:
preprocess_kwargs["second_text"] = kwargs["second_text"]
return preprocess_kwargs, {}, {}
def preprocess(self, text, second_text=None):
return self.tokenizer(text, text_pair=second_text, return_tensors=self.framework)
def _forward(self, model_inputs):
return self.model(**model_inputs)
def postprocess(self, model_outputs):
logits = model_outputs.logits[0].numpy()
probabilities = softmax(logits)
best_class = np.argmax(probabilities)
label = self.model.config.id2label[best_class]
score = probabilities[best_class].item()
logits = logits.tolist()
return {"label": label, "score": score, "logits": logits}
```
ꡬνμ νλ μμν¬μ ꡬμ λ°μ§ μμΌλ©°, PyTorchμ TensorFlow λͺ¨λΈμ λν΄ μλν©λλ€.
μ΄λ₯Ό `pair_classification.py`λΌλ νμΌμ μ μ₯ν κ²½μ°, λ€μκ³Ό κ°μ΄ κ°μ Έμ€κ³ λ±λ‘ν μ μμ΅λλ€:
```py
from pair_classification import PairClassificationPipeline
from transformers.pipelines import PIPELINE_REGISTRY
from transformers import AutoModelForSequenceClassification, TFAutoModelForSequenceClassification
PIPELINE_REGISTRY.register_pipeline(
"pair-classification",
pipeline_class=PairClassificationPipeline,
pt_model=AutoModelForSequenceClassification,
tf_model=TFAutoModelForSequenceClassification,
)
```
μ΄ μμ
μ΄ μλ£λλ©΄ μ¬μ νλ ¨λ λͺ¨λΈκ³Ό ν¨κ» μ¬μ©ν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, `sgugger/finetuned-bert-mrpc`μ MRPC λ°μ΄ν° μΈνΈμμ λ―ΈμΈ μ‘°μ λμ΄ λ¬Έμ₯ μμ ν¨λ¬νλ μ΄μ¦μΈμ§ μλμ§λ₯Ό λΆλ₯ν©λλ€.
```py
from transformers import pipeline
classifier = pipeline("pair-classification", model="sgugger/finetuned-bert-mrpc")
```
κ·Έλ° λ€μ `Repository`μ `save_pretrained` λ©μλλ₯Ό μ¬μ©νμ¬ νλΈμ 곡μ ν μ μμ΅λλ€:
```py
from huggingface_hub import Repository
repo = Repository("test-dynamic-pipeline", clone_from="{your_username}/test-dynamic-pipeline")
classifier.save_pretrained("test-dynamic-pipeline")
repo.push_to_hub()
```
μ΄λ κ² νλ©΄ "test-dynamic-pipeline" ν΄λ λ΄μ `PairClassificationPipeline`μ μ μν νμΌμ΄ 볡μ¬λλ©°, νμ΄νλΌμΈμ λͺ¨λΈκ³Ό ν ν¬λμ΄μ λ μ μ₯ν ν, `{your_username}/test-dynamic-pipeline` μ μ₯μμ μλ λͺ¨λ κ²μ νΈμν©λλ€.
μ΄νμλ `trust_remote_code=True` μ΅μ
λ§ μ 곡νλ©΄ λꡬλ μ¬μ©ν μ μμ΅λλ€.
```py
from transformers import pipeline
classifier = pipeline(model="{your_username}/test-dynamic-pipeline", trust_remote_code=True)
```
## π€ Transformersμ νμ΄νλΌμΈ μΆκ°νκΈ° [[add-the-pipeline-to-transformers]]
π€ Transformersμ μ¬μ©μ μ μ νμ΄νλΌμΈμ κΈ°μ¬νλ €λ©΄, `pipelines` νμ λͺ¨λμ μ¬μ©μ μ μ νμ΄νλΌμΈ μ½λμ ν¨κ» μ λͺ¨λμ μΆκ°ν λ€μ, `pipelines/__init__.py`μμ μ μλ μμ
λͺ©λ‘μ μΆκ°ν΄μΌ ν©λλ€.
κ·Έλ° λ€μ ν
μ€νΈλ₯Ό μΆκ°ν΄μΌ ν©λλ€.
`tests/test_pipelines_MY_PIPELINE.py`λΌλ μ νμΌμ λ§λ€κ³ λ€λ₯Έ ν
μ€νΈμ μμ λ₯Ό ν¨κ» μμ±ν©λλ€.
`run_pipeline_test` ν¨μλ λ§€μ° μΌλ°μ μ΄λ©°, `model_mapping` λ° `tf_model_mapping`μμ μ μλ κ°λ₯ν λͺ¨λ μν€ν
μ²μ μμ 무μμ λͺ¨λΈμμ μ€νλ©λλ€.
μ΄λ ν₯ν νΈνμ±μ ν
μ€νΈνλ λ° λ§€μ° μ€μνλ©°, λκ΅°κ° `XXXForQuestionAnswering`μ μν μ λͺ¨λΈμ μΆκ°νλ©΄ νμ΄νλΌμΈ ν
μ€νΈκ° ν΄λΉ λͺ¨λΈμμ μ€νμ μλνλ€λ μλ―Έμ
λλ€.
λͺ¨λΈμ΄ 무μμμ΄κΈ° λλ¬Έμ μ€μ κ°μ νμΈνλ κ²μ λΆκ°λ₯νλ―λ‘, λ¨μν νμ΄νλΌμΈ μΆλ ₯ `TYPE`κ³Ό μΌμΉμν€κΈ° μν λμ°λ―Έ `ANY`κ° μμ΅λλ€.
λν 2κ°(μ΄μμ μΌλ‘λ 4κ°)μ ν
μ€νΈλ₯Ό ꡬνν΄μΌ ν©λλ€.
- `test_small_model_pt`: μ΄ νμ΄νλΌμΈμ λν μμ λͺ¨λΈ 1κ°λ₯Ό μ μ(κ²°κ³Όκ° μλ―Έ μμ΄λ μκ΄μμ)νκ³ νμ΄νλΌμΈ μΆλ ₯μ ν
μ€νΈν©λλ€.
κ²°κ³Όλ `test_small_model_tf`μ λμΌν΄μΌ ν©λλ€.
- `test_small_model_tf`: μ΄ νμ΄νλΌμΈμ λν μμ λͺ¨λΈ 1κ°λ₯Ό μ μ(κ²°κ³Όκ° μλ―Έ μμ΄λ μκ΄μμ)νκ³ νμ΄νλΌμΈ μΆλ ₯μ ν
μ€νΈν©λλ€.
κ²°κ³Όλ `test_small_model_pt`μ λμΌν΄μΌ ν©λλ€.
- `test_large_model_pt`(`μ νμ¬ν`): κ²°κ³Όκ° μλ―Έ μμ κ²μΌλ‘ μμλλ μ€μ νμ΄νλΌμΈμμ νμ΄νλΌμΈμ ν
μ€νΈν©λλ€.
μ΄λ¬ν ν
μ€νΈλ μλκ° λ리λ―λ‘ μ΄λ₯Ό νμν΄μΌ ν©λλ€.
μ¬κΈ°μμ λͺ©νλ νμ΄νλΌμΈμ 보μ¬μ£Όκ³ ν₯ν 릴리μ¦μμμ λ³νκ° μλμ§ νμΈνλ κ²μ
λλ€.
- `test_large_model_tf`(`μ νμ¬ν`): κ²°κ³Όκ° μλ―Έ μμ κ²μΌλ‘ μμλλ μ€μ νμ΄νλΌμΈμμ νμ΄νλΌμΈμ ν
μ€νΈν©λλ€.
μ΄λ¬ν ν
μ€νΈλ μλκ° λ리λ―λ‘ μ΄λ₯Ό νμν΄μΌ ν©λλ€.
μ¬κΈ°μμ λͺ©νλ νμ΄νλΌμΈμ 보μ¬μ£Όκ³ ν₯ν 릴리μ¦μμμ λ³νκ° μλμ§ νμΈνλ κ²μ
λλ€.
|