반응형
선형 회귀란 말 그대로, 어떤 임의의 데이터 집합 $S$에 대해 직선과 데이터간의 차이가 최소인 일차 함수 직선을 찾는 과정입니다. 예를 들어, $y=3x + 7$과 같은 일차 함수가 데이터 $S$의 추세등을 잘 표현해 주는 그래프가 될 수 있습니다.
다중 선형 회귀란 한 데이터에 정보가 여러개이고, $x_i$가 서로 독립적인 데이터일때, (예를 들어, 기상 시간과 아침에 씻는 시간 등) $y$와 데이터간의 오차가 최소인 $y = w_1 x_1 + w_2 x_2 + \cdots + w_n x_n$의 꼴로 표현되는 방정식을 찾는 것을 의미합니다.
비선형 회귀란 어떤 한 데이터에 대해서 선형 회귀에서 표현할 수 없는 $n$차 다항함수와 같은 곡선을 찾는 과정을 의미합니다. 이때의 회귀 곡선은 $y = a_0 + a_1 x + a_2 x^2 + \cdots + a_n x^n$꼴로 표현됩니다.
다음은 선형 회귀를 구현해보는 코드입니다.
import torch
from torch import optim
x = torch.FloatTensor([
[1], [2], [3], [4], [5], [6], [7], [8], [9], [10],
[11], [12], [13], [14], [15], [16], [17], [18], [19], [20],
[21], [22], [23], [24], [25], [26], [27], [28], [29], [30]
])
y = torch.FloatTensor([
[0.94], [1.98], [2.88], [3.92], [3.96], [4.55], [5.64], [6.3], [7.44], [9.1],
[8.46], [9.5], [10.67], [11.16], [14], [11.83], [14.4], [14.25], [16.2], [16.32],
[17.46], [19.8], [18], [21.34], [22], [22.5], [24.57], [26.04], [21.6], [28.8]
])
위 코드는 $x = 1, 2, \cdots, 30$에 대해서 각각 $y = 0.94, 1.98, \cdots, 28.8$이라는 데이터를 각각 x, y변수에 저장한 코드입니다.
이제 여러가지 방법으로 모델을 만드는 방법 중 몇 가지를 소개하겠습니다.
weight = torch.zeros(1, requires_grad=True)
bias = torch.zeros(1, requires_grad=True)
learning_rate = 0.001
optimzer = optim.SGD([weight, bias], lr = learning_rate)
for epoch in range(10000):
hypothesis = x * weight + bias
cost = torch.mean((hypothesis - y)**2)
optimzer.zero_grad()
cost.backward()
optimzer.step()
if((epoch+1)%1000==0):
print(f'Weight : {weight.item():.3f}, Bias : {bias.item():.3f}')
- 위 코드는 처음에 *weight, bias 값을 원소가 1개인 영벡터로 초기화합니다. **learning_rate는 0.001로 설정해주었습니다.
* ) weight, bias는 $y = ax + b$에서 각각 $a$, $b$의 값을 의미합니다.
** ) learning_rate에 관한 설명은 나중에 설명하겠습니다. - hypothesis는 가설을 의미합니다. 가설이란 구축한 모델이 어떤 입력값에 대해 예측한 값이라고 보면 큰 문제가 없을 것 같습니다.
- cost는 torch.mean() 함수를 이용해서 계산하는데, 이 값은 MSE(Mean Squared Error)을 계산합니다.
이때 ***MSE는 특정 데이터와 곡선간의 데이터의 값을 계산할 때 아래와 같은 식으로 계산됩니다.
$$\displaystyle MSE(W, b) = \frac{1}{n} \sum_{i \in S} (\hat{y_i} - y_i)$$
*** ) https://haru101.tistory.com/25 - $\hat{y_i}$는 모델이 $i$번째 데이터에 대해 예측한 값, $y_i$는 $i$번째 데이터의 실젯값(정답)이라고 생각하시면 됩니다.
- optimizer는 SGD(Stochastic Gradient Descent, 확률적 경사 하강법) parameter로 최적화할 값과 learning_rate를 받아 최적화할 값들을 확률적 경사 하강법을 통해 조정합니다.
- zero_grad() : SGD는 미분을 통해 가중치나 편향값을 정하는데, 구조상 계산시에 += 연산으로 이전 값에 더해집니다. 따라서 0으로 초기화 하여 = 연산으로 바꿔주는 효과를 얻습니다.
- step() : 계산된 미분값을 이용해 아까 parameter에 최적화할 값들을 조정합니다.
- cost.backward()를 통해 cost 값을 이용하여 다음에 적용할 가중치나 편향값을 계산합니다.
코드를 실행해보면 다음과 같은 결과를 얻을 수 있습니다.
Weight : 0.879, Bias : -0.433
Weight : 0.879, Bias : -0.434
Weight : 0.879, Bias : -0.435
Weight : 0.879, Bias : -0.435
Weight : 0.879, Bias : -0.436
Weight : 0.879, Bias : -0.436
Weight : 0.879, Bias : -0.436
Weight : 0.879, Bias : -0.436
Weight : 0.879, Bias : -0.436
Weight : 0.879, Bias : -0.436
다음으로는 신경망 패키지(nn)를 이용하여 모델을 구축하는 방법으로 코드를 설명하겠습니다.
from torch import nn
model = nn.Linear(1, 1, bias=True, device="cuda")
criterion = nn.MSELoss()
learning_rate = 0.001
optimizer = optim.SGD(model.parameters(), lr = learning_rate)
for epoch in range(10000):
hypothesis = model(x.to("cuda"))
cost = criterion(hypothesis, y.to("cuda"))
optimizer.zero_grad()
cost.backward()
optimizer.step()
if((epoch+1) % 1000 == 0):
print(f"Epoch : {epoch+1:4d}, Model : {list(model.parameters())}, Cost : {cost:.3f}")
- 위 코드는 처음에 있는 nn.Linear를 통해 파라미터를 받아 모델을 구축합니다.
(파이토치 공식 문서 발췌) (in_features, out_features, bias, device, dtype)순으로 파라미터를 받는데, 각각의 파라미터는 다음을 의미합니다.- in_features : 입력받는 데이터의 차원 수입니다.
- out_features : 출력할 값의 차원 수입니다.
- in_features의 벡터를 선형변환하여 out_features의 차원으로 변환합니다.
- bias : 편향을 가지게 할 건지를 선택하는 파라미터입니다. (True, False)
- device : 파이토치는 cpu, gpu연산을 지원하는데, gpu연산을 사용할 지, cpu연산을 사용할 지 결정하는 파라미터입니다.
- cuda를 사용하는 경우 다음 코드로 device 변수를 저장해 device=device로 간편하게 설정할 수 있습니다.
device = "cuda" if torch.cuda.is_available() else "cpu"
- criterion은 오차함수를 정의하는 부분으로, nn에 있는 MSELoss()를 이용해 선언합니다. (평균 제곱 오차)
- 이전에 hypothesis($\hat y$)는 수식적으로 계산했지만 신경망 패키지를 이용했으므로 model(x)를 통해 데이터를 그냥 넣어주면 hypothesis값이 나오게 됩니다.
- 추가적으로, x.to("cuda")는 x가 cpu전용 텐서이기 때문에 이를 gpu연산을 통해 더 빠르게 계산하고자 gpu전용 텐서로 변환하는 기능입니다.
- criterion은 2가지 파라미터를 받는데, MSELoss는 제곱이기 때문에 순서와 상관없이 $\hat y$와 $y$를 차례대로 넣어주면 됩니다. 이를 통해 criterion은 오차값을 반환합니다.
반응형
'AI' 카테고리의 다른 글
| [자연어처리] 2. 쿼리(Query), 키(Key), 값(Value) (0) | 2024.09.18 |
|---|---|
| [자연어처리] 1. 토큰화(Tokenization) (0) | 2024.09.13 |
| [AI - 1] 오차 함수 - 오차를 계산하자 (0) | 2024.01.20 |