#
트랜스포머로 무엇을 할 수 있나요?

이번 장에서는 트랜스포머(Transformer) 모델을 사용해 무엇을 할 수 있는지 같이 살펴보고, 🤗 Transformers 라이브러리 툴의 첫 사용을 `pipeline()` 함수와 함께 시작하겠습니다.

> 👀 오른쪽 상단에 Open in Colab 버튼이 보이시나요? 버튼을 클릭하면 이번 장에서 사용한 모든 코드 샘플들을 Google Colab notebook을 통해 열 수 있습니다. 이런 버튼을 예제 코드를 포함하는 모든 단원에서 발견하실 수 있습니다.

> 로컬 환경에서 예제 코드를 실행하려면 setup을 살펴보세요.

##
트랜스포머는 어디에나 있어요!

트랜스포머 모델은 이전 단원에서 언급한 작업과 같은 모든 NLP 문제를 해결하기 위해 사용됩니다. 아래와 같이 Hugging Face와 트랜스포머 모델을 이용하고 다시 모델을 공유하여 커뮤니티에 기여하는 많은 기업과 기관이 있습니다:

🤗 Transformers 라이브러리는 이렇게 공유한 모델을 사용하고 구축하는 기능들을 제공합니다. Model Hub에서는 모두가 다운로드 받아 쓸 수 있는 수 천 개의 사전 학습된 모델들이 여러분을 기다리고 있습니다. 여러분만의 모델을 Hub에 업로드하는 것 또한 가능합니다!

> ⚠️ The Hugging Face Hub에는 트랜스포머 모델만 있지 않아요. 누구든지 어떠한 종류의 모델이나 데이터를 공유할 수 있습니다! Create a huggingface.co 링크에서 계정을 만들고 모든 기능을 사용해보세요!

트랜스포머 모델 안에서 무슨 일이 벌어지는지 알아보기 전에, 트랜스포머가 NLP 문제 해결에 어떻게 사용되는지 몇 가지 흥미로운 예시들을 살펴보겠습니다.

##
파이프라인으로 작업하기

🤗 Transformers 라이브러리의 가장 기본 객체는 `pipeline()` 함수입니다. 이 함수는 모델에 있어서 필수 과정인 전처리와 후처리 과정을 모델과 연결하고, 우리가 바로 어떠한 텍스트 입력을 넣든 원하는 답을 얻을 수 있도록 합니다:

    from transformers import pipeline

    classifier = pipeline("sentiment-analysis")
    classifier("I've been waiting for a HuggingFace course my whole life.")

    [{'label': 'POSITIVE', 'score': 0.9598047137260437}]

아래와 같이 여러 문장을 함께 넣을 수도 있습니다!

    classifier(
        ["I've been waiting for a HuggingFace course my whole life.", "I hate this so much!"]
    )

    [{'label': 'POSITIVE', 'score': 0.9598047137260437},
     {'label': 'NEGATIVE', 'score': 0.9994558095932007}]

기본적으로 이 파이프라인은 영어 감정 분석에 미세 조정(fine-tune)된 사전 학습 모델을 선택하여 넣게 됩니다. 여기서 `classifier` 객체를 생성할 때 모델이 다운로드 되며 캐싱(caching)이 이루어지때문에, 재실행 시에는 캐싱된 모델을 사용하게 되어 모델을 다시 다운로드 하지 않습니다.

텍스트를 파이프라인에 넣을 때 다음과 같은 세 가지 주요 과정을 거칩니다:

1. 텍스트가 모델이 이해할 수 있는 형태로 전처리 과정을 거칩니다.
2. 전처리된 입력이 모델 입력으로 들어갑니다.
3. 모델의 예측값이 후처리를 거쳐, 사람이 이해할 수 있는 형태로 반환됩니다.

현재까지 사용할 수 있는 파이프라인(available pipelines)은 다음과 같습니다:

- `feature-extraction` : 특징 추출 (텍스트에 대한 벡터 표현 추출)
- `fill-mask` : 마스크 채우기
- `ner` : 개체명 인식 (named entity recognition)
- `question-answering` : 질의 응답
- `sentiment-analysis` : 감정 분석
- `summarization` : 요약
- `text-generation` : 텍스트 생성
- `translation` : 번역
- `zero-shot-classification` : 제로샷 분류

이 중 몇 가지를 같이 살펴보도록 하겠습니다!

##
제로샷 분류(Zero-shot classification)

레이블이 없는 텍스트를 분류하는 더 까다로운 과제부터 시작하겠습니다. 텍스트에 레이블을 다는 것은 시간이 많이 소요되고 도메인 지식이 필요하기 때문에 이러한 작업은 실제 프로젝트에서 아주 흔한 상황입니다. 이러한 상황에서 `zero-shot-classification` 파이프라인은 매우 유용합니다. 제로샷 파이프라인은 사전 학습된 모델에 의존하지 않고도 분류 작업에 사용할 레이블을 특정할 수 있도록 합니다. 위의 예시에서 모델이 긍정(positive)과 부정(negative)의 두 레이블을 분류하는 샘플을 살펴보았는데, 제로샷 파이프라인을 통해서는 어떠한 레이블 세트에 대해서도 분류 작업을 수행할 수 있습니다.

    from transformers import pipeline

    classifier = pipeline("zero-shot-classification")
    classifier(
        "This is a course about the Transformers library",
        candidate_labels=["education", "politics", "business"],
    )

    {'sequence': 'This is a course about the Transformers library',
     'labels': ['education', 'business', 'politics'],
     'scores': [0.8445963859558105, 0.111976258456707, 0.043427448719739914]}

이러한 파이프라인이 제로샷(zero-shot)이라 불리는 이유는 여러분의 데이터에 맞춰 미세 조정(fine-tune)하지 않고도 바로 작업에 사용할 수 있기 때문입니다. 제로샷은 여러분이 원하는 어떠한 분류 레이블에 대해서도 확률 점수를 즉시 반환합니다.

> ✏️ 직접 해보기! 여러분이 직접 작성한 시퀀스와 레이블을 사용해 모델이 어떻게 동작하는지 확인해보세요.

##
텍스트 생성(Text generation)

지금부터 파이프라인을 사용해 텍스트를 생성하는 방법을 알아보겠습니다. 여기서의 핵심은 프롬트를 모델에 제공하면 모델이 나머지 텍스트를 생성하여 이를 자동으로 완성하는 것입니다. 이는 스마트폰의 텍스트 자동 완성 기능과 유사합니다. 텍스트 생성에는 랜덤하게 결과를 생성하는 과정이 포함되어 있어서 여러분이 아래와 같이 동일하게 입력을 넣어도 매번 다른 결과가 나올 수 있습니다.

    from transformers import pipeline

    generator = pipeline("text-generation")
    generator("In this course, we will teach you how to")

    [{'generated_text': 'In this course, we will teach you how to understand and use '
                        'data flow and data interchange when handling user data. We '
                        'will be working with one or more of the most commonly used '
                        'data flows — data flows of various types, as seen by the '
                        'HTTP'}]

`num_return_sequences`라는 인자(argument)를 통해 몇 개의 서로 다른 출력 결과를 생성할지 정할 수 있고, `max_length` 인자를 통해 출력 텍스트의 총 길이를 설정할 수 있습니다.

> ✏️ 직접 해보기! `num_return_sequences` 와 `max_length` 인자를 설정해 15개의 단어를 가진 서로 다른 두 개의 문장을 출력해보세요.

##
파이프라인에 Hub의 모델 적용하기

지금까지 예제들은 해당 작업에 대해 기본 모델들을 사용했지만, 특정 모델을 Hub에서 선택해 텍스트 생성과 같은 특정 작업에 대한 파이프라인에서도 사용할 수 있습니다. Model Hub 페이지의 화면 왼쪽에 태그를 클릭하여 태그명에 해당하는 작업을 지원하는 모델을 확인할 수 있습니다. 이 때, 다음과 같은 페이지로 이동하게 됩니다.

함께 `distilgpt2` 모델을 사용해보겠습니다! 위 예제에서 사용한 파이프라인에서 모델을 아래와 같이 로드 할 수 있습니다:

    from transformers import pipeline

    generator = pipeline("text-generation", model="distilgpt2")
    generator(
        "In this course, we will teach you how to",
        max_length=30,
        num_return_sequences=2,
    )

    [{'generated_text': 'In this course, we will teach you how to manipulate the world and '
                        'move your mental and physical capabilities to your advantage.'},
     {'generated_text': 'In this course, we will teach you how to become an expert and '
                        'practice realtime, and with a hands on experience on both real '
                        'time and real'}]

언어 태그를 클릭하여 해당 언어를 지원하고 생성하는 모델을 보다 구체적으로 검색할 수 있습니다. Model Hub에는 다양한 언어를 처리하는 다국어 모델의 체크포인트(모델의 파라미터 값) 또한 포함하고 있습니다.

모델을 클릭하면 온라인상에서 바로 사용 가능한 위젯을 확인할 수 있고, 이를 통해 모델을 직접 다운로드 받기 전에 모델의 기능을 빠르게 테스트 해볼 수 있습니다.

> ✏️ 직접 해보기! 영어를 제외한 다른 언어를 생성하는 모델을 검색해보세요. 위젯을 자유롭게 다뤄 보시고 파이프라인을 사용해보세요!

###
추론(Inference) API

모든 모델들은 Hugging Face 웹사이트에서 제공하는 추론 API를 통해 여러분의 브라우저상에서 직접 테스트할 수 있습니다. 이 페이지 링크로 접속해 직접 작성하신 텍스트를 입력하시면 모델의 입력 데이터를 처리 결과를 확인할 수 있습니다.

위젯을 구동하는 추론 API는 간편한 워크플로우를 가능하게 하는 유료 버전의 제품으로도 이용 가능합니다. 자세한 사항은 가격 정책 페이지를 참고해주세요.

##
마스크 채우기(Mask filling)

다음으로 사용해볼 파이프라인은 마스크 채우기(`fill-mask`)입니다. 이 작업의 핵심 아이디어는 주어진 텍스트의 빈칸을 채우기입니다:

    from transformers import pipeline

    unmasker = pipeline("fill-mask")
    unmasker("This course will teach you all about <mask> models.", top_k=2)

    [{'sequence': 'This course will teach you all about mathematical models.',
      'score': 0.19619831442832947,
      'token': 30412,
      'token_str': ' mathematical'},
     {'sequence': 'This course will teach you all about computational models.',
      'score': 0.04052725434303284,
      'token': 38163,
      'token_str': ' computational'}]

상위 몇 개의 높은 확률을 띠는 토큰을 출력할지 `top_k` 인자를 통해 조절합니다. 여기서 모델이 특이한 `<mask>` 단어를 채우는 것을 주목하세요. 이를 마스크 토큰(mask token)이라고 부릅니다. 다른 마스크 채우기 모델들은 다른 형태의 마스크 토큰을 사용할 수 있기 때문에 다른 모델을 탐색할 때 항상 해당 모델의 마스크 단어가 무엇인지 확인해야 합니다. 위젯에서 사용되는 마스크 단어를 보고 이를 확인할 수 있습니다.

> ✏️ 직접 해보기! Hub에서 `bert-base-cased`를 검색해 보고 추론 API 위젯을 통해 모델의 마스크 단어가 무엇인지 확인해 보세요. 이 모델이 위의 `pipeline` 예제에서 사용한 문장에 대해 어떻게 예측하나요?

##
개체명 인식(Named entity recognition)

모델이 입력 텍스트의 어느 부분이 사람, 장소, 기관 등과 같은 개체에 해당하는지 찾는 작업을 개체명 인식(NER)이라고 합니다. 예제를 통해 확인해 봅시다:

    from transformers import pipeline

    ner = pipeline("ner", grouped_entities=True)
    ner("My name is Sylvain and I work at Hugging Face in Brooklyn.")

    [{'entity_group': 'PER', 'score': 0.99816, 'word': 'Sylvain', 'start': 11, 'end': 18},
     {'entity_group': 'ORG', 'score': 0.97960, 'word': 'Hugging Face', 'start': 33, 'end': 45},
     {'entity_group': 'LOC', 'score': 0.99321, 'word': 'Brooklyn', 'start': 49, 'end': 57}
    ]

모델이 정확하게 Sylvain을 사람(PER)으로, Hugging Face를 기관(ORG)으로, Brooklyn을 장소(LOC)으로 예측했네요!

파이프라인을 생성하는 함수에 `grouped_entities=True` 옵션을 전달하면 파이프라인이 같은 개체에 해당하는 문장 부분을 다시 그룹화합니다. 이 옵션을 설정하면 모델은 여러 단어로 구성된 단어임에도 “Hugging”과 “Face”를 하나의 기관으로 정확히 분류하게 됩니다. 다음 챕터에서도 확인하겠지만, 놀랍게도 전처리 과정에서 각 단어들은 더 작은 부분으로 쪼개집니다. 예를 들어 `Sylvain` 이라는 단어는 `S`, `##yl`, `##va`, `##in` 이렇게 네 조각으로 쪼개집니다. 후처리 단계에서 파이프라인은 이 조각들을 멋지게 재그룹화합니다.

> ✏️ 직접 해보기! Model Hub에서 영어 품사 태깅(part-of-speech tagging, 줄여서 POS)이 가능한 모델을 찾아보세요. 이 모델이 위의 예시 문장으로 무엇을 예측하나요?

##
질의 응답(Question-answering)

질의 응답(`question-answering`) 파이프라인은 주어진 지문(context)의 정보를 활용하여 질문에 대한 답을 하는 태스크입니다:

    from transformers import pipeline

    question_answerer = pipeline("question-answering")
    question_answerer(
        question="Where do I work?",
        context="My name is Sylvain and I work at Hugging Face in Brooklyn",
    )

    {'score': 0.6385916471481323, 'start': 33, 'end': 45, 'answer': 'Hugging Face'}

본 파이프라인은 답을 새롭게 생성하는 방식이 아닌, 주어진 지문 내에서 정답을 추출하는 방식임을 잘 기억하세요.

##
요약(Summarization)

요약(Summarization)은 참조 텍스트의 모든(혹은 대부분의) 중요한 특징을 그대로 유지한 채 텍스트를 짧게 줄이는 작업입니다. 아래 예제를 확인하세요:

    from transformers import pipeline

    summarizer = pipeline("summarization")
    summarizer(
        """
        America has changed dramatically during recent years. Not only has the number of
        graduates in traditional engineering disciplines such as mechanical, civil,
        electrical, chemical, and aeronautical engineering declined, but in most of
        the premier American universities engineering curricula now concentrate on
        and encourage largely the study of engineering science. As a result, there
        are declining offerings in engineering subjects dealing with infrastructure,
        the environment, and related issues, and greater concentration on high
        technology subjects, largely supporting increasingly complex scientific
        developments. While the latter is important, it should not be at the expense
        of more traditional engineering.

        Rapidly developing economies such as China and India, as well as other
        industrial countries in Europe and Asia, continue to encourage and advance
        the teaching of engineering. Both China and India, respectively, graduate
        six and eight times as many traditional engineers as does the United States.
        Other industrial countries at minimum maintain their output, while America
        suffers an increasingly serious decline in the number of engineering graduates
        and a lack of well-educated engineers.
    """
    )

    [{'summary_text': ' America has changed dramatically during recent years . The '
                      'number of engineering graduates in the U.S. has declined in '
                      'traditional engineering disciplines such as mechanical, civil '
                      ', electrical, chemical, and aeronautical engineering . Rapidly '
                      'developing economies such as China and India, as well as other '
                      'industrial countries in Europe and Asia, continue to encourage '
                      'and advance engineering .'}]

텍스트 생성에서와 마찬가지로 `max_length` 와 `min_length` 를 미리 설정할 수 있습니다.

##
번역(Translation)

번역(Translation)의 경우 `"translation_en_to_fr"` 와 같이 태스크명에 해당하는 언어 쌍을 넣어준다면 기본 모델을 사용할 수 있지만, 더 간단하게 Model Hub에서 원하는 모델을 선택해 사용하는 방법이 있습니다. 아래에서는 프랑스어에서 영어로 번역을 시도해 보겠습니다:

    from transformers import pipeline

    translator = pipeline("translation", model="Helsinki-NLP/opus-mt-fr-en")
    translator("Ce cours est produit par Hugging Face.")

    [{'translation_text': 'This course is produced by Hugging Face.'}]

텍스트 생성 및 요약에서와 마찬가지로, `max_length` 혹은 `min_length` 를 지정하여 결과를 출력할 수 있습니다.

> ✏️ 직접 해보기! 다른 언어를 지원하는 번역 모델을 검색해보고 위의 문장을 몇 가지 다른 언어들로 번역해 봅시다.

지금까지 보여드린 파이프라인들은 대부분 특정 작업을 위해 프로그래밍된 데모용 파이프라인으로, 여러 태스크를 동시에 지원하지는 않습니다. 다음 단원에서는 `pipeline()` 함수 내부를 살펴보고 그 동작 방식을 직접 설계하는 방법에 대해 다루겠습니다.

Update on GitHub