KT AIVLE School/[TIL] AIVLE School 당일 복습

[TIL] [KT AIVLE School] 에이블스쿨 DX 트랙 10주차 2일. 딥러닝 심화(1). 딥러닝 기반 언어모델(LLM) 활용

guoyee94 2024. 11. 5. 17:36

 

오늘부터는 딥 러닝 모델링보다는 활용으로 주안점이 옮겨 간다.

 

 

 

언어 모델 LLM

 

딥 러닝을 바탕으로 만들어진 언어 모델을 LLM(Large Language Model)이라고 한다.

 

LLM은 수천억~수조 개의 파라미터를 바탕으로 텍스트를 학습하여, 

각종 언어적 상호작용을 할 수 있는 모델이다.

 

대표주자로는 그 유명한 ChatGPT나 colab의  Gemini같은 것들이 있다.

 

이런 LLM은 사실 최근까지 꽤 치명적인 단점을 가지고 있었고,

불과 수 개월 전부터 이런 단점들을 극복할 방법들이 등장하기 시작했다.

 

따라서 오늘은 LLM의 특징, 한계, 극복방안에 대해 알아본다.

 

 

 

 

 

 


 

 

 

 

 

 

LLM의 등장

 

NLP(Natural Language Processing)란 컴퓨터로 하여금

인간의 언어를 이해할 수 있도록 처리하는 절차이다.

 

일반적으로 NLP는 다음과 같은 범위로 나뉜다.

문장 분류
  리뷰 등의 긍정/부정, 수신한 이메일의 스팸 여부 등을 구분한다.

개체 인식(NER)
  사람, 위치, 조직 등을 올바르게 인식해야 언어 작용이 가능하다.
  변수나 클래스를 정의해야 코드가 제대로 작동하는 원리.

문장 생성
  언어 모델이라면 당연히 할 줄 알아야겠지?

텍스트 번역, 요약
  적절한 번역이 이루어지지 않으면 의미가 완전히 잘못 전달되기에,
  개인적으로 아주 중요하다고 생각한다.

 

NLP는 오랜 기간동안 RNN 기반으로 진행되어 왔다.

 

텍스트는 순차적인 데이터이기에,

순차 데이터에 강점이 있는 RNN이 유효하다고 판단되어 왔기 때문이다.

 

하지만 RNN은 명확한 단점을 가지고 있었다.

장기 의존성 문제
RNN은 긴 문장 안에서, 서로 먼 정보를 기억하기 어려웠다.
따라서 문장이 길어질수록, 앞부분 정보를 재활용하는 데 어려움이 있었다.

병렬 처리의 어려움
RNN은 순차적으로 데이터를 처리해야 해서, GPU 같은 하드웨어에서 병렬 처리가 어려웠다.
이는 계산 속도를 떨어뜨리는 요인이 되었다.

 

이같은 문제점은 모델의 확장성을 본질적인 수준에서 저해한다.

 

따라서 이때까지의 NLP는 소위 말하는 '천장'이 있는 분야였다.

 


 

 

 

그러다 2017년, "Attention Is All You Need"라는 논문에서 Transformer가 등장했다.

 

Transformer는 완전히 새로운 언어 모델 구조로,

순차적인 데이터 처리가 필요 없는데다 모든 단어를 한꺼번에 처리할 수 있었다.

 

RNN의 한계를 단숨에 극복한 것이다.

 

Transformer의 핵심 기술은 'Self Attention'이다.

Self Attention

각 단어가 문장의 모든 다른 단어에 대한 연관성을 평가하는 메커니즘이다.
하나의 단어를 Querry, Key, Value로 분류하는데, 각각은 다음의 정보를 탐색한다.

Querry 다른 단어와 어떤 관계가 있는지
Key 다른 단어와 얼마나 관계가 있는지
Value 단어가 나타내는 실제 정보
다른 단어와 많은 연관을 가지고 있는 단어라면,
그것은 문맥적으로 중요한 단어라는 말이다.

따라서 Querry와 Key를 바탕으로, 각 단어의 Value에는 가중치가 부과된다.

이를 통해 단어의 문맥적 중요도를 정렬하고, 문맥을 고려한 벡터가 완성되는 것이다.

 

Transformer는 그야말로 게임 체인저였다.

 

RNN의 확장성 문제를 해결하면서 천장을 깨부순 셈이니까.

 

이로 인해 전 인류적이라고 할 정도의 대규모의 학습이 가능해졌고,

현대 LLM 탄생의 동력이 되었다.

 

 

 

 

 

 

 


 

 

 

 

 

 

Transformer 활용

 

Transformer는 일반적으로 pipeline을 통해서 사용한다.

from transformers import pipeline

 

이런 식으로.

 

파이프라인 함수화 되어 있어서 굉장히 편리한데,

기초 문법은 다음과 같다.

객체명 = pipeline(task = '작업명칭', model = '모델')

 

세상 간단한 문법이다.

 

저렇게 선언해놓고 나면, '객체명(매개변수)'를 입력하여 즉각 실행할 수 있다.

 

위 문법에 사용가능한 것들은 다음과 같다.

 

<task>

- sentiment-analysis: 텍스트의 감정을 분석하여 긍정, 부정 등으로 분류
- zero-shot-classification: 사전 학습된 클래스 없이 텍스트를 특정 범주로 분류
- summarization: 긴 텍스트를 요약
- translation: 텍스트를 한 언어에서 다른 언어로 번역하는 작업
- text-generation: 주어진 텍스트의 맥락에 따라 자연스럽게 이어지는 문장을 생성
- feature-extraction: 텍스트에서 의미 있는 특징을 추출하여 벡터 형식으로 변환
- fill-mask: 문장에서 일부 단어가 가려졌을 때, 문맥에 맞는 단어를 예측하여 채우는 작업
- ner (Named Entity Recognition, 개체 명 인식): 텍스트에서 이름, 장소, 날짜와 같은 개체를 식별
- question-answering: 주어진 질문에 대해 텍스트에서 적절한 답변을 찾아내는 작업

 

<model> 고마워요 GPT

모델은 정말 종류가 많다.
외울 건 아니지만 최대한 여러 종류를 기록해 둔다.
수업때 쓴 것은 밑줄 처리.

- BERT (Bidirectional Encoder Representations from Transformers): 양방향으로 문맥을 이해해 텍스트 분류, 질문 응답 등 다양한 NLP 작업에 강력한 성능을 보이는 모델
ex) bert-base-uncased, bert-large-cased, bert-base-multilingual-cased, bert-base-german-cased

- GPT (Generative Pretrained Transformer): 텍스트 생성에 특화된 모델로, 자연스러운 언어 생성 작업에 널리 사용됨
ex) gpt2, gpt2-medium, gpt3-davinci, gpt-neo-2.7B

- RoBERTa (A Robustly Optimized BERT Approach): BERT의 확장판으로, 더 많은 데이터를 활용하여 성능을 개선한 모델
ex) roberta-base, roberta-large, xlm-roberta-base, xlm-roberta-large

- DistilBERT: BERT를 경량화하여 더 빠른 성능을 제공하는 모델로, 실시간 애플리케이션에 적합함
ex) distilbert-base-uncased, distilbert-base-cased, distilbert-base-multilingual-cased

- XLNet: BERT의 한계를 보완한 모델로, 순환 방식의 훈련을 통해 문맥 이해를 강화한 모델
ex) xlnet-base-cased, xlnet-large-cased

- T5 (Text-To-Text Transfer Transformer): 모든 NLP 작업을 텍스트 입력과 텍스트 출력으로 통일해 다루는 모델로, 다양한 작업에 유연하게 사용될 수 있음
ex) t5-small, t5-base, t5-large, t5-3b, t5-11b

- ALBERT (A Lite BERT): BERT의 경량화 버전으로, 메모리 효율성을 높이고 속도를 개선한 모델
ex) albert-base-v2, albert-large-v2, albert-xlarge-v2

- Electra: 훈련 시 '마스킹' 대신 '오류 검출' 방식을 사용해 학습 효율성을 높인 모델
ex) google/electra-small-discriminator, google/electra-base-discriminator, google/electra-large-discriminator

- Bart (Bidirectional and Auto-Regressive Transformers): 인코더-디코더 구조를 사용해 텍스트 생성, 요약 등에서 성능을 발휘하는 모델
ex) facebook/bart-base, facebook/bart-large, facebook/bart-large-mnli

 

모든 task과 model을 살펴보려면 커뮤니티 'Hugging Face'에서 확인할 수 있다.

 

https://huggingface.co

 

 

이곳은 LLM을 다루기 위한 필수적 장소라고 볼 수 있는데,

모델이나 task를 확인할 수 있고, 모델마다 세부 명세가 다르기 때문이다.

 

그래서 모델 업로더의 코멘트를 많이 참고해야 한다.

 

task나 language 등으로 필터링해서 다양한 모델을 사용할 수 있다.

 

 

 

 

업로더가 모델의 사용법이나 파이프라인 등을 명세해놓는다.

 

 

 

 

 

 

 


 

 

 

 

 

 

 

언어 모델링의 절차

 

언어 모델링을 위한 전처리 과정. 언어모델의 매개변수로 들어갈 문자열은 이 과정을 거쳐야 한다.

 

 

우리는 언어 모델링의 절차를 이해하기 위해

일종의 전처리 과정이라고 할 수 있는 TokenizeEmbedding에 대해 이해해야 한다.

 

(단, Transformer 이후부터는 Embedding이 전처리가 아니라 모델 안에서 처리된다.)

 

 

 


 

 

 

Encoding이라고 되어 있는 부분이 Tokenize이다.

Tokenize

문자 그대로 입력받은 값을 토큰으로 만드는 것이다.
입력받은 값은? 문자열.
이것을 토큰으로 만드려면 2단계가 필요하다.

1. 문자열을 적절하게 나누어 토큰으로 만든다.(문자, 단어, 형태소, subword 등)
  - 우리말은 형태소로 쪼개는 게 일반적이다. ex) 먹어치우다 = 먹- + -어 + 치우- + -다
  - Google에서는 subward 방식을 선호한다. ex) extension = ex- + tens + -ion

2. 각 토큰(텍스트)을 모델이 이해가능한 토큰(숫자)로 매핑한다.
  - 이 매핑의 근거가 되는 일종의 사전을 Vocab(어휘집)이라고 한다.
  - Vocab은 일반적으로 이미 만들어져 있는 것을 쓴다.

이 두 단계를 Tokenize라고 한다.
이 과정을 거치면, 아직 문맥은 고려되지 않았으나 입력 문자들이 나뉘어 있는 상태다.

 

※ 사실 2단계 이후에 padding과 attention mask를 설정하는 과정도 있다.

padding은 모델에서 요구하는 길이를 맞추기 위해 입력값에 더미를 집어넣는거고,

attention mask는 패딩을 식별해 주어 모델이 건너뛰도록 만든다.

 

 


 

Embedding을 통해 단순하던 토큰이 고차원 데이터로 바뀐다.

Embedding

Tokenize를 거치면 각 언어에 맞는 인덱스가 할당되어 있다고 했지.

문제는 이걸로는 문맥적 의미를 나타낼 수 없다.(동음어 등의 문제)
따라서 이 토큰들을 머신이 이해하는 형태로 바꾸어 주면서,
문맥적 특징들을 표기해야 한다. (= 단순 음운이 아닌, 맥락적 의미요소가 추가되어야 한다.)

토큰을, 보다 많은 정보를 가진 고차원 벡터로 바꾸는거지.

이 원리는 딥 러닝이고,
머신이 알아서 각 벡터의 가중치를 조절한다.

기존에는 Word2Vec, FastText같은 메커니즘이 쓰였으나,
Transformer의 등장 이후 평정된 상태.

그도 그럴 것이, 애초에 위에서 본 Self Attention
각 단어(토큰)을 주변 단어(맥락)와 비교해서 가중치를 메기는 거였으니까.

사실상 Embedding과 똑같은 것 아닌가? 아닐수도 있다.

아 그리고 위에도 적었지만, Transformer부터는 Embedding이 전처리가 아니라,
모델 안에서 처리되는 방식이다.

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

LLM의 한계

 

이렇게 RNN을 극복한 transformer는 일견 무적처럼 보이는데,

사실 이로부터 만들어진 LLM한계가 있다.

 

현세대 ChatGPT는 이 문제를 해결했으니,

문제 확인을 위해 OpenAI의 API 키를 발급받아 구세대 GPT를 불러와 보자.

API
클라이언트와 서버를 이어주는 인터페이스.
활용하기 위해서 Key + 요청 양식 + 응답 양식이 갖추어져야 한다.

본 포스팅에서는 KT에서 에이블러들에게 지급해 준 API를 사용한다.
import pandas as pd
import numpy as np
import os
import openai
from openai import OpenAI

def ask_chatgpt1(question):
    # api key 지정
    client = OpenAI()  # OpenAI에서 발급받은 API 키

    # # API를 사용하여 'gpt-3.5-turbo' 모델로부터 응답을 생성합니다.
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},  # 기본 역할 부여
            {"role": "user", "content": question},                          # 질문
        ]
    )

    return response.choices[0].message.content

 

 

이렇게 불러온 모델에게 적절한 질문을 해 보면....

?? 네이놈

 

GPT 3-5까지 많이 제기되었던 문제점이 여기서 나온다.

 

위에서 호출한 모델(gpt-3.5-turbo)은 2021년까지의 정보만이 학습된 모델이다.

그래서 롤드컵 우승팀을 담원으로 알고 있다.

 

다시말해, 언어모델은 학습하지 못한 지식에 대해 전혀 대답할 수 없다는 한계가 있다.

 

이것을 극복하기 위해 고안된 것이 Fine Tunning RAG이다.

 

그리하여 내일은 LangChain을 이용한 RAGFine Tunning을 맛볼 예정.