시계열 문제
시계열 분석이란 시간에 따라 변하는 데이터를 사용하여 추이를 분석하는 것
ARIMA 모델
SARIMAX Results
==============================================================================
Dep. Variable: Sales No. Observations: 36
Model: ARIMA(5, 1, 0) Log Likelihood -199.651
Date: Tue, 22 Aug 2023 AIC 411.302
Time: 08:02:02 BIC 420.634
Sample: 01-01-1991 HQIC 414.523
- 12-01-1993
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 -0.8788 0.227 -3.876 0.000 -1.323 -0.434
ar.L2 -0.2787 0.232 -1.203 0.229 -0.733 0.176
ar.L3 -0.0076 0.270 -0.028 0.978 -0.536 0.521
ar.L4 0.3483 0.294 1.185 0.236 -0.228 0.924
ar.L5 0.3772 0.207 1.826 0.068 -0.028 0.782
sigma2 5049.2115 1540.731 3.277 0.001 2029.435 8068.988
===================================================================================
Ljung-Box (L1) (Q): 0.39 Jarque-Bera (JB): 1.60
Prob(Q): 0.53 Prob(JB): 0.45
Heteroskedasticity (H): 1.43 Skew: 0.38
Prob(H) (two-sided): 0.54 Kurtosis: 2.28
===================================================================================
- Sales를 종속변수로 가지고 있음
- ARIMA 모델 사용
- P>|z| : 통계적으로 유의미한지 평가할 떄 사용 (작을 수록 유의미)
- JB 잔차의 정규성 평가
- Hetero skedasticity 이상값 검정
RNN
RNN(Recurrent Neural Network)은 시간적으로 연속성이 있는 데이터를 처리하려고 고안된
인공 신경망
RNN이 기존 네트워크와 다른 점은 ‘기억(memory)’을 갖는다는 것
RNN은 외부 입력과 자신의 이전 상태를 받아서 갱신
출력 유형
1대1
1대다: 이미지 캡션
다대1: 감성 분석기
다대다: 언어 자동 번역기
동기화 다대다: 문장에서 다음에 나올 단어를 예측하는 언어 모델, 즉 프레임 수준의 비디오 분류
RNN은 셀 개념 숙지 (nn.RNNCell)
window 크기가 3개면 cell 3개가 1개 단위가 됨
3개를 input으로 넣고 4번째의 값을 예측
RNN 계층과 셀
RNN 셀은 하나의 단계(time step)만 처리
nn.RNNCell: SimpleRNN 계층에 대응되는 RNN 셀
nn.GRUCell: GRU 계층에 대응되는 GRU 셀
nn.LSTMCell: LSTM 계층에 대응되는 LSTM 셀
RNN의 활용 분야: 자연어 처리, 손글씨, 센서 데이터 등 시계열 데이터 처리
- 입력 x 가 들어와서 y가 출력되는 구조
- xt-1에서 ht-1을 얻고 다음 단계에서 ht-1과 xt를 사용하여 과거 정보와 현재 정보를 모두 반영
- ht와 xt+1의 정보를 이용하여 과거와 현재 정보를 반복해서 반영
- RNN의 오차(E)는 심층 신경망에서 전방향(feedforward) 학습과 달리 각 단계(t)마다 오차를 측정
- RNN에서 역전파는 BPTT(BackPropagation Through Time)를 이용하여 모든 단계마다 처음부터 끝까지 역전파
- 오차를 이용하여 Wxh, Whh, Why 및 바이어스를 업데이트
- BPTT는 vanishing gradient problem이 발생
- 기울기 소멸 문제를 보완하기 위해 오차를 몇 단계까지만 전파시키는 생략된-BPTT(truncated BPTT)를 사용할 수도 있고, 근본적으로는 LSTM 및 GRU를 많이 사용
start = time.time()
TEXT = torchtext.legacy.data.Field(lower=True, fix_length=200, batch_first=False)
LABEL = torchtext.legacy.data.Field(sequential=False)
batch_first: 신경망에 입력되는 텐서의 첫 번째 차원 값이 배치 크기(batch_size)가 되도록 함
# False
([seq_len, batch_size, hidden_size])
# [시퀀스 길이, 배치 크기, 은닉층의 뉴런 개수]
# True
([batch_size, seq_len, hidden_size])
# [배치 크기, 시퀀스 길이, 은닉층의 뉴런 개수]
RNN 셀 구현
TEXT.build_vocab(train_data, max_size=10000, min_freq=10, vectors=None)
LABEL.build_vocab(train_data)
print(f"Unique tokens in TEXT vocabulary: {len(TEXT.vocab)}")
print(f"Unique tokens in LABEL vocabulary: {len(LABEL.vocab)}")
- build_vocab(훈련 데이터셋, max_size=단어 집합의 크기로 단어 집합에 포함되는 어휘 수,
- min_freq=훈련 데이터셋에서 특정 단어의 최소 등장 횟수-10개 이상있는 단어만 추가,
- vectors=임베딩 벡터)
class RNNCell_Encoder(nn.Module):
def __init__(self, input_dim, hidden_size):
super(RNNCell_Encoder, self).__init__()
self.rnn = nn.RNNCell(input_dim, hidden_size)
def forward(self, inputs): #------ inputs는 입력 시퀀스로 (시퀀스 길이, 배치, 임베딩(seq,batch, embedding))의 형태를 갖습니다.
bz = inputs.shape[1] #------ 배치를 가져옵니다.
ht = torch.zeros((bz, hidden_size)).to(device)# ------ 배치와 은닉층 뉴런의 크기를 0으로 초기화
for word in inputs:
ht = self.rnn(word, ht) #------ ②
return ht
def training(epoch, model, trainloader, validloader):
correct = 0
total = 0
running_loss = 0
model.train()
for b in trainloader:
x, y = b.text, b.label
x, y = x.to(device), y.to(device)
y_pred = model(x)
loss = loss_fn(y_pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
with torch.no_grad():
y_pred = torch.argmax(y_pred, dim=1)
correct += (y_pred == y).sum().item()
total += y.size(0)
running_loss += loss.item()
epoch_loss = running_loss / len(trainloader.dataset)
epoch_acc = correct / total
valid_correct = 0
valid_total = 0
valid_running_loss = 0
model.eval()
with torch.no_grad():
for b in validloader:
x, y = b.text, b.label
x, y = x.to(device), y.to(device)
y_pred = model(x)
loss = loss_fn(y_pred, y)
y_pred = torch.argmax(y_pred, dim=1)
valid_correct += (y_pred == y).sum().item()
valid_total += y.size(0)
valid_running_loss += loss.item()
epoch_valid_loss = valid_running_loss / len(validloader.dataset)
epoch_valid_acc = valid_correct / valid_total
print('epoch: ', epoch,
'loss: ', round(epoch_loss, 3),
'accuracy:', round(epoch_acc, 3),
'valid_loss: ', round(epoch_valid_loss, 3),
'valid_accuracy:', round(epoch_valid_acc, 3)
)
return epoch_loss, epoch_acc, epoch_valid_loss, epoch_valid_acc
- model.train() : train 모드로 변경하면 dropout 기능 활성화됨
- with torch.no_grad(): 기울기 계산 끄기
- y_pred = torch.argmax(y_pred, dim=1) 최대값의 인덱스 반환
- valid_correct += (y_pred == y).sum().item() 맞은 수 더하기
- model.eval(): evaluation 모드로 변경
RNN 계층 네트워크
모델
class BasicRNN(nn.Module):
def __init__(self, n_layers, hidden_dim, n_vocab, embed_dim, n_classes, dropout_p = 0.2):
super(BasicRNN, self).__init__()
self.n_layers = n_layers
self.embed = nn.Embedding(n_vocab, embed_dim)
self.hidden_dim = hidden_dim
self.dropout = nn.Dropout(dropout_p)
self.rnn = nn.RNN(embed_dim, self.hidden_dim, num_layers = self.n_layers, batch_first = True)
self.out = nn.Linear(self.hidden_dim, n_classes)
def forward(self, x):
x = self.embed(x)
h_0 = self._init_state(batch_size = x.size(0))
x, _ = self.rnn(x, h_0)
h_t = x[:, -1, :]
self.dropout(h_t)
logit = torch.sigmoid(self.out(h_t))
return logit
def _init_state(self, batch_size = 1):
weight = next(self.parameters()).data
return weight.new(self.n_layers, batch_size, self.hidden_dim).zero_()
-
dropout 일부 뉴런을 비활성화
-
nn.RNN()
-
nn.Linear()에서 선형구조로 변환하여 최종 출력
-
forward 네트워크의 순전파 진행
-
임베딩: 단어를 숫자로 변경
-
logit: 완전연결상태를 입력값으로 받아서 sigmoid를 적용하여 예측 logit을 반환
-
logit은 2진분류에서 출력값(0, 1)으로 사건이 일어날 확률
loss, optimizer 세팅
model = BasicRNN(n_layers = 1, hidden_dim = 256, n_vocab = vocab_size, embed_dim = 128, n_classes = n_classes, dropout_p = 0.5)
model.to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)
학습
def train(model, optimizer, train_iter):
model.train()
for b, batch in enumerate(train_iter):
x, y = batch.text.to(device), batch.label.to(device)
y.data.sub_(1)
optimizer.zero_grad()
logit = model(x)
loss = F.cross_entropy(logit, y)
loss.backward()
optimizer.step()
if b % 50 == 0:
print("Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}".format(e,
b * len(x),
len(train_iter.dataset),
100. * b / len(train_iter),
loss.item()))
- y.data.sub_(1) 레이블 값을 1씩 감소 시켜서 덮어쓰기
- 앞에서 IMDB의 레이블의 경우 긍정은 2, 부정은 1의 값을 갖는다고 했음
- y.data에서 1을 뺀다는 것은 레이블 값을 0과 1로 변환하겠다는 의미
def evaluate(model, val_iter):
model.eval()
corrects, total, total_loss = 0, 0, 0
for batch in val_iter:
x, y = batch.text.to(device), batch.label.to(device)
y.data.sub_(1)
logit = model(x)
loss = F.cross_entropy(logit, y, reduction = "sum")
total += y.size(0)
total_loss += loss.item()
corrects += (logit.max(1)[1].view(y.size()).data == y.data).sum()
avg_loss = total_loss / len(val_iter.dataset)
avg_accuracy = corrects / total
return avg_loss, avg_accuracy
- evaluate 모드로 바꿔서 dropout 해제
- 맞은 수, 전체, 손실값을 0으로 초기화
- val_iter에서 배치만큼 돌림
- 장치에서 x, y 값 가져오기
- inplace 연산을하여 레이블 값을 0,1로 변환
- 모델에 집어넣어서 logit 값구함
- cross entropy loss를 구하는데 (logit과 y의 차이) sum은 모든 오차값을 합한다는 뜻
- total은 배치에서 전체 누적
- loss item은 손실값을 계속 누적
- logit.max(1)[1] => 최댓값의 인덱싱
- view()는 텐서를 y.size()로 reshape
- 텐서끼리 비교해서 맞은 개수만큼 sum()함
'Education > ICT AI 중급' 카테고리의 다른 글
4주차_17 필기 (LSTM) (0) | 2023.10.15 |
---|---|
4주차_15 필기 (ResNet) (0) | 2023.10.15 |
4주차_14 필기 (VGGNet) (0) | 2023.10.15 |
3주차_13 필기 (LeNet, Alexnet) (0) | 2023.10.15 |
3주차_12 필기 (전이학습) (1) | 2023.10.15 |