Electra는 전기를 이용한 알고리즘 학습을 위한 모델 중 하나로, GPT (Generative Pre-trained Transformer)와 같은 대형 언어 모델의 일종. Electra는 Google이 2020년에 발표한 모델로, 기존의 언어 모델과는 약간 다른 접근 방식을 채택.
초기 언어 모델로, 문장의 단어를 나열한 순서를 기반으로 다음 단어를 예측하는 통계적인 방법을 사용.
주어진 문맥에서 고정된 개수의 연속된 단어를 고려하는데, 이를 N-gram이라고 함. 예를 들어, bigram은 두 단어의 연속이며 trigram은 세 단어의 연속임. 예를 들어서 문장 An adorable little boy is spreading smiles이 있을 때, 각 n에 대해서 n-gram을 전부 구해보면 다음과 같음.
unigrams : an, adorable, little, boy, is, spreading, smiles
bigrams : an adorable, adorable little, little boy, boy is, is spreading, spreading smiles
trigrams : an adorable little, adorable little boy, little boy is, boy is spreading, is spreading smiles
4-grams : an adorable little boy, adorable little boy is, little boy is spreading, boy is spreading smiles
🤔 n-gram을 통한 언어 모델에서는 다음에 나올 단어의 예측은 오직 n-1개의 단어에만 의존
예: An adorable little boy is spreading ___
bigrams 예측 : is spreading 만 가지고 예측 👉 갖고 있는 100개의 corpus에서 is spreading 다음에 joy가 온 경우가 10번, smile이 온 경우가 20번이라면 joy의 확률은 10%, smile의 확률은 20%임. 따라서 확률적으로 smile이 올 것이라 예측함
🤬 전체 문장을 판단하지 못하기 때문에 정확성이 떨어짐. n이 작으면 "is spreading"처럼 작은 문맥에서는 정확성이 높아지지만, 문장 전체의 의미를 이해하는 데 어려움이 있을 수 있음. 반대로 n이 크면 "an adorable little boy is spreading"처럼 큰 문맥에서는 전체적인 의미를 파악할 수 있지만, 해당 n-gram을 훈련 데이터에서 찾기 어렵고 모델의 크기가 커짐
def generate_ngrams(text, n):
words = text.split()
ngrams = [tuple(words[i:i+n]) for i in range(len(words)-n+1)]
return ngrams
# 예시
text_example = "An adorable little boy is spreading joy."
n_value = 2 # bigram 예시
result = generate_ngrams(text_example, n_value)
print(f"{n_value}-gram 결과: {result}")
# 결과
2-gram 결과: [('An', 'adorable'), ('adorable', 'little'), ('little', 'boy'), ('boy', 'is'), ('is', 'spreading'), ('spreading', 'joy.')]
고정된 확률을 할당하고, 각 단어를 모두 독립된 단어로 취급, 따로 훈련 필요없이 데이터셋이 주어지면 확률 확인
Markov 모델(시퀀스 데이터에서 현재 상태가 이전의 일정한 유한한 과거 상태에만 의존한다고 가정하는 확률 모델)과 같은 통계적 기법이 도입. 여전히 단어 간의 확률적 관계를 모델링하며, 훈련 데이터의 확률 분포를 기반으로 문장 생성이나 다음 단어 예측을 수행.
😎 Markov model의 핵심은 현재의 observation이 바로 이전의 state에 의해서만 결정된다는 것. 한 상태(state)의 확률은 단지 그 이전 상태에만 의존한다는 것이 마코프 체인의 핵심.
🪄 마르코프 성질(Markov property) : 과거와 현재 상태가 주어졌을 때의 미래 상태의 조건부 확률 분포가 과거 상태와는 독립적으로 현재 상태에 의해서만 결정

마르코프 모델의 두 가지 요소:
전이 확률 (Transition Probability):
출력 확률 (Output Probability 또는 Emission Probability):
상태 (States): 맑음 (Sunny), 흐림 (Cloudy), 비 (Rainy) 세 가지 날씨 상태를 가정.
전이 확률 (Transition Probabilities): 현재 날씨 상태에서 다음 날씨 상태로의 전이
출력 확률 (Output Probabilities):
이러한 확률은 각 날씨 상태에서 특정 관찰이 나타날 확률을 나타냄. 예를 들어, 맑은 날씨에서 '선글라스'를 발견할 확률은 0.8.
import random
def build_markov_model(text, order=1): # # order를 지정하지 않은 경우, 기본값 1
words = text.split() # 문자열을 특정 구분자를 기준으로 나누어 리스트로 반환
model = {}
# 주어진 텍스트로부터 마르코프 모델 생성
for i in range(len(words) - order):
state = tuple(words[i:i + order]) # 현재 상태를 정의 (튜플로 변환하여 사용)
next_word = words[i + order] # 다음 단어를 가져옴
if state not in model: # model은 마르코프 모델을 나타내는 딕셔너리
model[state] = []
model[state].append(next_word)
return model
def generate_text(model, length=10, start=None):
if start is None:
start = random.choice(list(model.keys())) # 시작 상태를 무작위로 선택
current_state = start
generated_text = list(start) #새로운 단어가 추가될 때마다 편리하게 처리하기 위해 list 사용
# 주어진 길이 만큼의 새로운 문장 생성
for _ in range(length - len(start)): # _은 반복 변수이지만 특별히 사용되지 않는 변수를 나타냄
next_word = random.choice(model.get(current_state, [""])) # 다음 단어를 무작위로 선택
generated_text.append(next_word)
current_state = tuple(generated_text[-order:]) # 현재 상태 업데이트
return ' '.join(generated_text) # ' '은 각 단어 사이에 삽입될 문자열
# 예시 텍스트
example_text = "The quick brown fox jumps over the lazy dog."
# 2차 마르코프 모델 생성
markov_model = build_markov_model(example_text, order=2)
# 새로운 문장 생성
generated_sentence = generate_text(markov_model, length=10)
print(generated_sentence)
# 신경망 모델
import torch.nn as nn
class FeedforwardNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(FeedforwardNN, self).__init__()
self.layer1 = nn.Linear(input_size, hidden_size)
self.layer2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = self.layer1(x)
x = torch.relu(x)
x = self.layer2(x)
return x
import torch
import torch.nn as nn
# RNN 모델 정의
class SimpleRNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(SimpleRNN, self).__init__() # 파이썬에서 사용되는 내장 함수로, 상위 클래스의 메서드를 호출하는데 사용
self.hidden_size = hidden_size
# 입력에서 은닉 상태로 가는 선형 변환
self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
# 은닉 상태에서 출력으로 가는 선형 변환
self.i2o = nn.Linear(input_size + hidden_size, output_size)
# 활성화 함수 (여기서는 tanh를 사용)
self.tanh = nn.Tanh() # -1에서 1 사이의 값으로 압축하는 비선형 함수
def forward(self, input, hidden):
# 입력과 은닉 상태를 결합
combined = torch.cat((input, hidden), 1) #PyTorch에서 제공하는 텐서를 결합(concatenate)하는 함수
# 1: 차원을 나타내며, 여기서는 두 텐서를 가로로 결합하도록 지정함
# 입력과 은닉 상태를 고려한 새로운 은닉 상태 계산
hidden = self.i2h(combined)
hidden = self.tanh(hidden)
# 새로운 은닉 상태를 사용하여 출력 계산
output = self.i2o(combined)
return output, hidden
# 입력, 은닉 상태, 출력의 크기 정의
input_size = 3
hidden_size = 4
output_size = 2
# 모델 생성
rnn = SimpleRNN(input_size, hidden_size, output_size)
# 예제 입력과 초기 은닉 상태 생성
input_tensor = torch.tensor([1.0, 2.0, 3.0], dtype=torch.float32)
hidden_tensor = torch.zeros(hidden_size, dtype=torch.float32)
# 순방향 전파 수행
output_tensor, new_hidden_tensor = rnn(input_tensor, hidden_tensor)
# 결과 출력
print("Input:", input_tensor)
print("Output:", output_tensor)
print("New Hidden State:", new_hidden_tensor)
신경망 모델:
- 피드포워드(Feedforward) 구조: 입력이 출력 방향으로만 흐르는 구조. 즉, 입력층에서 출력층으로의 단방향 전파.
- 순서 정보 처리 불가능: 각 입력은 독립적으로 처리되며, 순서 정보가 고려 x. 예를 들어, 문장의 단어 순서를 고려하지 않고 개별 단어를 처리.
- 고정된 크기의 입력과 출력: 주어진 입력 크기와 출력 크기가 고정.
순환 신경망(RNN) 모델:
- 순환 구조: RNN은 이전 단계의 출력이 현재 단계의 입력으로 사용되는 순환 구조. 이로써 시퀀스 데이터의 처리가 가능.
- 순서 정보 고려: RNN은 시퀀스 데이터에서 각 단계의 입력에 대한 순서 정보를 고려. 예를 들어, 문장에서 단어의 순서를 인식하고 이전 단어의 정보를 활용.
- 가변적인 크기의 입력과 출력: 시퀀스 길이에 따라 가변적인 크기의 입력과 출력.
참고한 자료들