API (Application Programming Interface)
서로 다른 소프트웨어, 즉 프로그램이 대화하는 통로라고 할 수 있다. 이 소프트웨어에는 인공지능뿐만 아니라 다양한 많은 소프트웨어가 포함돼있다. 따라서 API 개념을 잘 익히면, 인공지능 활용뿐만 아니라 다른 기능들도 편하게 활용할 수 있을 것이다.
API를 좀 더 전문적으로 설명하면, 소프트웨어 어플리케이션의 상호작용을 정의하는 인터페이스라고 할 수 있다. 두 개 이상의 소프트웨어 구성요소가 서로 통신하고, 기능을 공유할 수 있게 규칙과 프로토컬을 제공해준다. 이를 사용하면, 개발자는 복잡한 시스템을 효율적으로 구축할 수 있고, 재사용 가능한 코드를 작성할 수 있다. 또, 다양한 서비스와 통합할 수 있다는 것이 가장 큰 특징 중 하나다. 우리는 이미 제공되는 서비스에 API를 사용하는 것뿐만 아니라, 우리가 만든 서비스를 API로 제공할 수도 있다.
API가 어떻게 동작하는지 알아보자. API 서비스를 제공하는 서버와 이를 이용하는 클라이언트가 있다. 이 둘이 요청과 응답을 서로 주고받는 방식으로 동작한다.
예를 들어, 음성인식 서비스를 제공하는 API를 호출하면, 자동으로 그 프로그램에 요청이 전달되고, 다시 한 번 결과를 처리해서 우리에게는 출력값이 전달된다. 인공지능 서비스의 API는 누구나 손쉽게 편한 서비스를 자신만의 서비스로 바꿀 수 있게 도와준다. 그러나 세부적으로 조정하거나 모델 자체를 수할 수 있는 깃허브와 달리, API는 통신이기때문에 남이 모델을 다 가지고 있으므로 세부적인 조정이 힘들다. 즉, 코드 자체를 직접 건드리는 정도의 유연함은 불가능하다.
API 사용 시 주의할 점에 대해 알아보자.
사용 방법이 버전
에 따라 다를 수 있고, 고성능의 모델들은 호출할 때마다 특정 비용이 청구된다. API를 사용할 때는 키를 발급받는데, 이 키를 관리하는 게 중요하다. 이 키는 절대로 공개하면 안 된다. 키가 공개되면 과금 폭탄을 맞을 수도 있다.
활용 방법에 대해 알아보자.
어떤 기업이나 개인이 제공하는 서비스가 API의 형태로 제공되고 있다면 활용할 수 있다. 텍스트 생성 API인 ChatGPT만 해도 사용 방법이 여러 가지다. 웹에 접속하거나, transformer library처럼 모델을 불러오거나, AIP를 통해 자신만의 챗봇 시스템을 만들 수도 있다.
즉, 하나의 서비스만으로도 여러 방법으로 사용할 수 있다. 그 방법 중 하나가 API이고, 이는 소스코드 상에서 서비스를 활용할 수 있으므로 유용하다.
이외에도 음성 합성 API(ElevenLabs), 컴퓨터 비전 API(Google Vision AI), 음성 인식 API(Google Cloud Speech-to-Text), 번역 API(DeepL) 등 다양한 API가 있다. 인공지능을 제외하고도 다양한 API가 존재한다.
API 활용의 장점은 손쉽게 사용할 수 있고, 개발이 빠르며, 프로그램의 확장성이 좋다는 것이다.
단점은 비용 문제가 있고, 커스터마이징에 제한이 있으며, 해당 서비스가 중단되거나 변경될 때 문제가 발생하게 되는 의존성 문제가 있다.
API를 사용할 때의 팁을 살펴보자. 사용법과 제한사항에 대한 공식 문서
를 항상 읽어야 한다. 서비스의 API마다 사용 방식이 다를 수 있고, 어떤 기능들이 제공되는시 상세하게 적혀 있다. API 키
를 신중하게 관리해야 한다. 키가 노출되면 과금이 청구되거나, 보안 문제가 발생할 수 있기 때문에 소스코드에 직접적으로 키를 포함해서는 안 된다. 다른 파일에서 불러오거나 환경 변수를 통해 관리하는 게 좋다. 마지막으로, 실험적으로 만들 때는 무료 할당량
을 적절하게 활용하자.
PyTorch를 활용해 Transformer 모델 구현하기
PyTorch는 사용하기 쉽고, 모델의 구조를 유연하게 작성할 수 있는 딥러닝 프레임워크다. 그래서 학습, 모델 구현, 검증 단계를 쉽게 작성할 수 있다. 우리가 직접 모델을 만드는 것이 좋을 수도 있겠지만, 유명한 혹은 패키지나 프레임워크에서 사전 제공되는 이미 공개된 모델들의 성능이 더 좋을 수도 있다. 특이한 모델을 만들어야 하거나 특이한 데이터를 사용해야 하는 경우에는 직접 개인이 모델을 만드는 것이 더 좋을 수도 있다.
인공지능 분야에서 굉장히 중요한 모델 중 하나가 Transformer 모델이다. 이는 자연어 처리에서 굉장히 뛰어난 성능을 보이는 모델로, 최근에 나오는 대부분의 언어형 모델들의 기반이다. 내부적으로는 encoder, decoder, Attention 등 다양한 기능들이 포함돼있다. Transformer 모델을 불러와보자.
import torch
import torch.nn as nn
from torch.nn import Transformer
코드 설명은 아래와 같다.
`import torch`로 PyTorch 라이브러리를 불러온다. PyTorch는 딥러닝 모델을 구성하고 학습하는 데 필요한 다양한 기능을 제공한다.
`import torch.nn as nn`로 PyTorch의 신경망 관련 모듈인 torch.nn을 nn이라는 이름으로 가져온다. 이 모듈에는 다양한 신경망 계층과 손실 함수가 포함되어 있어 모델을 구성하는 데 유용하다.
`from torch.nn import Transformer`로 PyTorch에서 제공하는 Transformer 모델을 직접 불러온다. Transformer는 시퀀스 데이터를 학습하는 데 자주 사용하는 모델이다. 자연어 처리(NLP)와 시계열 데이터 분석에 주로 사용되며, "Self-Attention" 메커니즘을 활용해 멀리 떨어진 단어 간의 관계도 잘 학습할 수 있다.
model = Transformer(d_model=512, nhead=8, num_encoder_layers=6, num_decoder_layers=6)
위 코드에서 사용된 용어에 대해 알아보자.
d_model은 단어의 임베딩 차원수를 나타낸다.nhead는 Multihead Attention의 헤드 수를 나타낸다. encoder와 decoder layer 수는 어느 정도 레이어로 디코더 레이어와 인코더 레이어를 형성할 지를 정하는 부분이다.
이제 학습 단계를 살펴보자. 이 단계에서는 먼저 옵티마이저를 설정해야 한다.
optimizer = torch.optim.Adam(model.parameters(), lr = 0.0001)
일반적으로 transformer처럼 파라미터가 많고 깊고 복잡한 모델일수록 learning rate(러닝 레이트)를 작게 설정하는 경우가 많다. 파라미터가 너무 많기 때문에, 초기 학습 단계에서 큰 러닝레이트(lr)를 사용하면 학습이 불안정해지기 때문이다. 특히 어텐션 메커니즘처럼 중요한 요소에서 과도한 업데이트가 발생할 수도 있다. 그리고 transformer는 고차원이고 복잡한 표현을 학습하기 때문에 학습 후반부에서 lr을 작게 조정해서 미세조정을 하는 게 더 좋다.
그런 다음 학습 기준을 설정한다. 실습에서는 CrossEntropy를 사용했다.
criterion = nn.CrossEntropyLoss()
이제 모델 학습 단계다. epoch를 설정하고, optimizer를 통해 그래디언트를 초기화하고 학습을 진행한다.
for epoch in range(num_epochs):
optimizer.zero_grad()
output = model(src, tgt)
loss = criterion(output, tgt_labels)
loss.backward()
optimizer.step()
이렇게 직접 구현하는 것도 좋지만 우리는 AI 활용을 배우고 있기 때문에 활용을 통해 다시 실습해보자. 먼저, 아래의 코드를 통해 두 가지 패키지를 설치해보자.
!pip install sentencepiece sacremoses
모델에 의존성이 있는 경우가 있어서, 필요한 경우 패키지를 설치해야 하기 때문이다.
model = torch.hub.load('huggingface/pytorch-transformers', 'modelForCausalLM', 'gpt2')
tokenizer = torch.hub.load('huggingface/pytorch-transformers', 'tokenizer', 'gpt2')
위의 코드를 통해 우리는 GPT 모델에 해당하는 모델들을 가져올 수 있다. GPT는 Transformer의 decoder 부분만을 활용한다고 생각하면 된다. 이 모델은 주로 텍스트 생성을 목적으로 설계돼있다. 사전 학습 단계에서 대량의 데이터 패턴을 학습하게 돼있어서 미세 조정 단계에서 특정 작업에 맞춰 모델을 최적화할 수 있다.
input_text를 만들고, 토큰화를 진행하자. tokenizer에 encode를 불러와서 input_text를 전달하고, return_tensors의 종류를 지정하자.
input_text = "Once upon a time"
input_ids = tokenizer.encode(input_text, return_tensors='pt')
이제 만들어낸 토큰화된 입력을 통해 output을 생성해보자.
output = model.generate(input_ids, max_length = 50, num_return_sequences = 1)
이 output은 사람이 알아들을 수 없는 말이기에 그대로 사용할 수 없다. 따라서 tokenizer를 통해 사람이 알아들을 수 있는 말로 바꿔줘야 한다.
tokenizer.decode(output[0], skip_special_tokens=True)
그러면 출력 결과가 'Once upon a time, the world was a place of great beauty and great danger. The world was a place of great danger, and the world was a place of great danger. The world was a place of great danger, and the world was a' 이렇게 나오게 된다.
우리가 직접 모델을 구현할 때의 문제점에 대해 살펴보자.
대형 모델의 학습이 힘들다. Transformer 모델은 특히 방대한 양의 데이터가 필요하고, 학습 시간이 매우 길며, GPU 메모리도 매우 커야한다. 복잡한 모델은 직접 만들기 어렵다. 일일이 모델에 대한 연구를 하나하나 수행해야 하기 때문에 구현도 디자인도 어렵다. 하이퍼파라미터 튜닝에 대해서도 실험과 시간이 많이 필요하다. 사전 학습된 모델 활용에 한계가 있다. 사전 학습된 모델들은 맞춤화가 어려우며, 미세 조정이나 추가 학습을 위한 추가 비용이 들 수도 있다.
극복 방법에 대해 알아보자. 클라우드 서비스를 활용하거나, 사전 학습된 모델을 적절히 활용하거나, 경량화 모델을 사용하는 등의 방법이 있다. 그러나 첫째는 비용이 들고, 둘째는 우리가 특이한 주제를 다룰 때 제공되지 않을 가능성이 높고, 셋째는 경량화긴 하지만 학습 시간이 오래 걸릴 수 있다.
강의 외부에서 추가로 알게 된 내용
- 다중 할당
파이썬에서는 여러 변수를 한꺼번에 할당할 수 있다. 리스트나 튜플 같은 순서가 있는 데이터를 활용해 각 요소를 변수에 차례대로 할당하는 방식이다. 아래의 예시 코드를 참고하자.
a, b, c = [1, 2, 3]
# 이렇게 하면 a에는 1, b에는 2, c에는 3이 할당된다.
x, operator, y, _, z = q.split() # 수식을 각 부분으로 나누기
# q.split()을 사용하여 각 수식을 x, operator, y, _, z로 분리한다.
# _는 = 기호로, 이후 계산에 필요 없으므로 변수로 저장하지 않은 것이다.