> For the complete documentation index, see [llms.txt](https://ai-society-1.gitbook.io/ai-society/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ai-society-1.gitbook.io/ai-society/3..md).

# 3. 단순 선형 회귀

## 3. 단순 선형 회귀

선형 회귀란 **종속변수 y**와 **한 개 이상의 독립변수 X**와의 **선형 상관 관계**를 모델링하는 것.

이 때, **독립변수 X가 한 개라면, 단순 선형 회귀**라고 한다.

그렇다면,

**독립변수 x에 대해 종속변수 y값을 표현하는 모델**을 만든다는 것.

쉽게 표현하면, x값이 있을 때 y는 얼마인가? (단, y는 x에 영향을 받는 값이다.)

![img](https://online.stat.psu.edu/stat500/sites/stat500/files/inline-images/500-l9-ht-wt-ex-1.png)\
**몸무게에 대하여 키를 예측하는 선형 회귀 모델**.

**파란점**이 실제 **data**, **빨간 선**이 **모델이 예측한 값**이다.

#### 잠깐만요, 이 예측이 더 좋은 예측아닌가요?

![img](https://i.ibb.co/ZHC6Z7V/image.png)

이게 훨씬 더 **데이터를 잘 표현**하는데, 이게 더 **잘 학습된 모델**이 아닌가요?

정답을 말해주자면, **틀렸다**.

이건 **학습이 잘못된** 모델이다!

### 어째서 학습이 잘못됐다고 하는가?

이전 강에서 봤듯,

우리는 **모델**이 **추측**을 잘 하기를 기대한다. 그래서 **학습**을 한다.

위 모델은 **기존 데이터**는 잘 추측하겠지만, 새로운 데이터를 주면 **추측에 실패할 확률이 높다**.

위의 키와 몸무게 분석을 예시로 들어보자면,

키가 큰데, 몸무게가 매우 가벼운 사람이 있을 수 있고,\
키가 작은데, 몸무게가 매우 무거운 사람이 있을 수 있다.

이런 **특이 데이터**가 일부 존재할 수 있다!

그래서 **처음 보는 데이터도 얼추 맞추기**를 원한다면,

**특이 데이터**가 있을 수 있으니 **기존에 알고있는 data**에 너무 **fitting(학습)하지 말고** 적당히 해야한다!

![img](https://i.ibb.co/Nxgsv92/image.png)

이게 잘 fitting(학습)된 모델이다.

현재 **data에 대해서 살짝 오차**가 있지만,

**처음보는 데이터**여도 **얼추 맞출 수 있을 것**이다!

![img](https://i.ibb.co/qD6q3zB/image.png)

너무 적게 학습한 것도 당연히 나쁩니다.

#### 우리의 목표는, 대부분의 경우에 적은 오차를 가치는 모델을 만드는 것.

### 이름이 왜 선형회귀인가?

여기서의 회귀란, **평균으로의 회귀**를 의미한다.

이는 아래와 같이 이해할 수 있다.

![img](https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Standard_deviation_diagram.svg/langko-420px-Standard_deviation_diagram.svg.png)

이는 정규분포 곡선이다.

**대부분 평균**에 몰려있고, 평균에서 멀어질수록 확률은 급감한다.

그래서 **적절한 추측**을 하기 위해서, **평균으로의 회귀**를 하여 추측하겠다는 뜻.

그러면, **특이값이 존재하더라도 영향을 덜 받을 것**이다.

**이는 오차가 줄어든다는 뜻이며, 우리가 바라는 것**이다!

**선형이란, 파라미터의 관계가 선형**이라는 것!

### Quiz 1.

X = \[1, 2, 3]일 때,

Y = \[3, 5, 7]이다.

X = 4일 때, Y의 값은 얼마인가?

정답은 **9**이다.

### Quiz 2.

왜 9인가?

어떻게 **y = 2x + 1**의 관계를 알아냈는가?

**무의식 중에, \* 2**를 해봤을 것이다.

그랬을 때, **1 차이가 난다는 사실을 인지** 했을 것이고,

최종적으로 **y = 2x + 1**이라고 판단을 내렸을 것이다.

이를 다시 해석하면,

1. 초기값 x를 설정하여 테스트 한다.
2. 정답에 가까워 지는 방향으로 x를 수정.
3. 수정된 x를 이용하여 다시 테스트.
4. 정답에 맞을 때 까지 2 \~ 3번 과정을 반복한다.

**모델도 똑같은 과정을 거쳐 학습을 한다!**

### 선형회귀 학습 과정

$$
X = \[1, 2, 3]
$$

$$
Y = \[3, 5, 7]
$$

#### 가설 함수 (Hypothesis function)

우리의 예측은, 직선 형태이다. 즉 **기울기**와 **절편** 두가지 값이 필요하다.

$$
H(W,b) = Wx + b
$$

우리의 목표는 W=2, b=1 이다.

## 1번 과정, 가설 초기화

먼저, 1번 과정이다, 일단 **아무거나 넣고 테스트** 한다.

초기 값,

$$
W=1, b=0
$$

$$
y = x
$$

가 된다.

![img](https://i.ibb.co/YP1hC7P/desmos-graph-1.png)

이제 2번과정이다, 정답에 가까워 지는 방향으로 W와 b를 수정할 차례.

**잠깐, 정답에 가까워지는 방향이란 무엇인가?**

예측값과 실제값의 차이, 오차.

**즉, 오차가 줄어드는 방향으로 W와 b를 수정**해야한다.

#### 오차 계산 함수(Cost function)

$$
Cost(W, b) = {1 \over m} \times \Sigma\_{i=1}^{m}(W\_{x\_{i}}+b-y\_{i})^{2}
$$

$$
W\_{x\_{i}}+b
$$

는 우리의 예측값이다!

보기 편하게 하기 위해서, 예측값을 $\hat{y\_{i}}$ 이라 표기한다.

$$
Cost(W, b) = {1 \over m} \times \Sigma\_{i=1}^{m}(\hat{y\_{i}}-y\_{i})^{2}
$$

오차 제곱의 평균. **이 수치를 0에 가깝게 줄여야 한다!**

외 제곱 오차를 사용하는지는 수업 마지막에 추가설명이 있습니다.

#### W에 대한 오차 그래프

![img](https://i.ibb.co/QfpLbjF/desmos-graph-3.png)

W가 2일 때가 정답이므로, 2에서 오차값이 젤 작아야 한다.

또한 2에서 멀어질 수록 오차가 커지기 때문에 **볼록 함수 형태**가 된다.

**즉, 기울기가 0이 되는 지점이 최소 오차값**.

![img](https://i.ibb.co/NygV1CH/desmos-graph-4.png)

초기값이 녹색점 또는 파란점이라 하자.

어느 쪽으로 이동해야 최소 오차가 되는가?

**기울기가 0인 지점으로 이동해야 최소 오차**가 된다.

## 2번 과정. 기울기가 0인 지점을 찾는 법. 경사하강법(Gradient descent)

![img](https://i.ibb.co/D7QJBFz/desmos-graph-4.png)

기울기가 **0인 지점보다 값이 작으면, 기울기가 음수**일 것이다.

기울기가 **0인 지점보다 값이 작으면, 양의 방향으로 갱신**해야 한다.

기울기가 **0인 지점보다 값이 크면, 기울기가 양수**일 것이다.

기울기가 **0인 지점보다 값이 크면, 음의 방향으로 갱신**해야 한다.

#### 즉, 기울기의 반대 방향으로 값을 갱신하면, 무조건 오차가 줄어든다.

#### 이를 경사 하강법(Gradient descent)라고 한다.

**다시 흐름을 정리 해 보자.**

1번 과정. 초기값 설정,

2번 과정. 테스트 후 X값 갱신.

3번 과정. 다시 테스트

4번 과정. 충족할때까지 2 \~ 3번 과정의 반복.

**경사 하강법을 이용하여 X값 갱신을 시킬 수 있게 되었다.**

## 3번 과정. 테스트와 업데이트의 반복

우린 W와 b이 두가지를 업데이트 해야한다.

그럼 W에 대한 Cost-function과 b에 대한 Cost-function을 따로따로 구하고,

**각각 경사하강법을 적용하여 W와 b를 최적화 해야한다.**

X축을 W로 한 Cost-function와, X축을 b로한 Cost-function이 필요하다.\
이를 각 W-그래프, b-그래프라 임시로 칭한다.

기울기의 반대 방향으로 가면 된다고 했는데, 기울기는 미분이다.

W-그래프에서 기울기에 영향을 주는 X축이 W인데 수식은 $W\_{x\_{i}}+b$ 이다.

b-그래프에서 기울기에 영향을 주는 X축이 b인데 수식은 $W\_{x\_{i}}+b$ 이다.

그래서 **편미분을 이용하여 기울기를 구한다.**

$$
W의 기울기 = {\partial\ Cost(W, b) \over \partial\ W}
$$

$$
b의 기울기 = {\partial\ Cost(W, b) \over \partial\ b}
$$

즉, 경사하강법을 이용한 W, b값의 조정은 아래와 같다.\
a는, 갱신되는 크기를 조절하기 위한 상수이다. (learning-rate)

$$
W = W - \alpha{\partial\ Cost(W, b) \over \partial\ W}
$$

$$
b = b - \alpha{\partial\ Cost(W, b) \over \partial\ b}
$$

**위의 수식을 반복하여, 오차가 최적화 될 떄까지 반복하고,**

**결국에 W와 b값을 얻게되어, 선형 회귀 모델이 완성된다.**

## 부록

#### 잠깐, 왜 오차의 평균이 아니라 오차 제곱의 평균인가요?

오차에 부호가 있으면 안되기 떄문입니다!

![img](https://i.ibb.co/qDdcynm/desmos-graph-2.png)

초록색 선이 **우리가 기대하는 모델의 예측**이다.

파란색 선도 오차가 0이다. **+1 오차와 -1 오차가 있어 오차의 합이 0**이 된다..

**부호는 없애야 한다!**

#### 부호를 없애는 방법, (절댓값 Vs 제곱)

**MAE(Mean Absolute Error)**

절대 오차의 평균.

![img](https://i.ibb.co/TWNDtyj/mae.png)

절댓값을 사용하여 Cost-function을 계산하면, **고정적인 크기 만큼 이동**하게 된다.

**한 번에 많이 움직이면, 기울기가 0인 최소 오차지점을 넘어갈 수도 있다.**

**MSE(Mean Suquared Error)**

제곱 오차의 평균

![img](https://i.ibb.co/JHLjL7j/mse.png)

절댓값과 제곱 **둘 다 부호를 없앤다는 공통점**이 있다.

그럼 **차이점은, 제곱을하냐 안하냐** 차이이다.

**제곱은 값을 극대화 시키는 특성**이 있다.

$$
{0.1}^{2}=0.01
$$

$$
{10}^{2}=100
$$

위의 수식에서 볼 수 있듯이,

**작은 값을 더욱 작게하고, 큰 값을 더욱 크게하는 극대화 특성**을 가진다.

즉, 기울기가 0인지점(최소 오차지점)에 갈수록 조금씩 갱신을 하게 된다는 것이며,

이는 **기울기가 0인지점(최소 오차지점)을 지나칠 가능성을 줄인다**.

**그래서 주로 MSE를 사용하지만, MAE가 더 좋을 때도 있다는 점!**

## Python으로 복습하는 단순 선형 회귀

```python
!pip install numpy
```

```
Collecting numpy
  Using cached numpy-1.24.2-cp311-cp311-win_amd64.whl (14.8 MB)
Installing collected packages: numpy
Successfully installed numpy-1.24.2



[notice] A new release of pip available: 22.3.1 -> 23.0.1
[notice] To update, run: python.exe -m pip install --upgrade pip
```

```python
import numpy as np

x_train = np.array([1., 2., 3., 4., 5., 6.])
y_train = np.array([9., 16., 23., 30., 37., 44.])

W = 0.0
b = 0.0

n_data = len(x_train)

epochs = 5000
learning_rate = 0.01

for i in range(epochs):
    hypothesis = x_train * W + b
    cost = np.sum((hypothesis - y_train) ** 2) / n_data
    gradient_w = np.sum((W * x_train - y_train + b) * 2 * x_train) / n_data
    gradient_b = np.sum((W * x_train - y_train + b) * 2) / n_data

    W -= learning_rate * gradient_w
    b -= learning_rate * gradient_b

    if i % 100 == 0:
        print('Epoch ({:10d}/{:10d}) cost: {:10f}, W: {:10f}, b:{:10f}'.format(i, epochs, cost, W, b))

print('W: {:10f}'.format(W))
print('b: {:10f}'.format(b))
print('result : ')
print(x_train * W + b)
```

```
Epoch (         0/      5000) cost: 845.166667, W:   2.263333, b:  0.530000
Epoch (       100/      5000) cost:   0.011092, W:   7.055875, b:  1.760787
Epoch (       200/      5000) cost:   0.005339, W:   7.038765, b:  1.834041
Epoch (       300/      5000) cost:   0.002570, W:   7.026894, b:  1.884862
Epoch (       400/      5000) cost:   0.001237, W:   7.018658, b:  1.920121
Epoch (       500/      5000) cost:   0.000595, W:   7.012945, b:  1.944582
Epoch (       600/      5000) cost:   0.000287, W:   7.008981, b:  1.961552
Epoch (       700/      5000) cost:   0.000138, W:   7.006230, b:  1.973326
Epoch (       800/      5000) cost:   0.000066, W:   7.004323, b:  1.981494
Epoch (       900/      5000) cost:   0.000032, W:   7.002999, b:  1.987161
Epoch (      1000/      5000) cost:   0.000015, W:   7.002081, b:  1.991093
Epoch (      1100/      5000) cost:   0.000007, W:   7.001443, b:  1.993820
Epoch (      1200/      5000) cost:   0.000004, W:   7.001001, b:  1.995713
Epoch (      1300/      5000) cost:   0.000002, W:   7.000695, b:  1.997026
Epoch (      1400/      5000) cost:   0.000001, W:   7.000482, b:  1.997936
Epoch (      1500/      5000) cost:   0.000000, W:   7.000334, b:  1.998568
Epoch (      1600/      5000) cost:   0.000000, W:   7.000232, b:  1.999007
Epoch (      1700/      5000) cost:   0.000000, W:   7.000161, b:  1.999311
Epoch (      1800/      5000) cost:   0.000000, W:   7.000112, b:  1.999522
Epoch (      1900/      5000) cost:   0.000000, W:   7.000077, b:  1.999668
Epoch (      2000/      5000) cost:   0.000000, W:   7.000054, b:  1.999770
Epoch (      2100/      5000) cost:   0.000000, W:   7.000037, b:  1.999840
Epoch (      2200/      5000) cost:   0.000000, W:   7.000026, b:  1.999889
Epoch (      2300/      5000) cost:   0.000000, W:   7.000018, b:  1.999923
Epoch (      2400/      5000) cost:   0.000000, W:   7.000012, b:  1.999947
Epoch (      2500/      5000) cost:   0.000000, W:   7.000009, b:  1.999963
Epoch (      2600/      5000) cost:   0.000000, W:   7.000006, b:  1.999974
Epoch (      2700/      5000) cost:   0.000000, W:   7.000004, b:  1.999982
Epoch (      2800/      5000) cost:   0.000000, W:   7.000003, b:  1.999988
Epoch (      2900/      5000) cost:   0.000000, W:   7.000002, b:  1.999991
Epoch (      3000/      5000) cost:   0.000000, W:   7.000001, b:  1.999994
Epoch (      3100/      5000) cost:   0.000000, W:   7.000001, b:  1.999996
Epoch (      3200/      5000) cost:   0.000000, W:   7.000001, b:  1.999997
Epoch (      3300/      5000) cost:   0.000000, W:   7.000000, b:  1.999998
Epoch (      3400/      5000) cost:   0.000000, W:   7.000000, b:  1.999999
Epoch (      3500/      5000) cost:   0.000000, W:   7.000000, b:  1.999999
Epoch (      3600/      5000) cost:   0.000000, W:   7.000000, b:  1.999999
Epoch (      3700/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      3800/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      3900/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4000/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4100/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4200/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4300/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4400/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4500/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4600/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4700/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4800/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
Epoch (      4900/      5000) cost:   0.000000, W:   7.000000, b:  2.000000
W:   7.000000
b:   2.000000
result : 
[ 9. 16. 23. 30. 37. 44.]
```
