## 1. 선형 연립방정식을 활용한 예측모델

선형 연립방정식의 문제를 해결하는 것은 선형 예측모델의 가중치 벡터를 구하는 것과 같습니다.

$$
\begin{align}
\begin{matrix}
x_{11} w_1 & + \;& x_{12} w_2   &\; + \cdots + \;& x_{1N} w_N &\; = \;& y_1 \\
x_{21} w_1 & + \;& x_{22} w_2   &\; + \cdots + \;& x_{2N} w_N &\; = \;& y_2 \\
\vdots\;\;\; &   & \vdots\;\;\; &                & \vdots\;\;\; &     & \;\vdots \\
x_{N1} w_1 & + \;& x_{N2} w_2   &\; + \cdots + \;& x_{NN} w_N &\; = \;& y_N \\
\end{matrix}
\end{align}
$$

위의 식은 선형 연립방정식입니다. 이는 N개의 목표값(y)을 출력하는 함수의 집합으로도 볼 수 있습니다. 

여기서 x는 목표값을 예측하는 데 활용될 데이터를 나타냅니다. 여기서 필요한 것은, x라는 데이터(input)을 받으면 합리적인 목표값(y)를 출력해내는 함수를 만들어내는 것입니다. 

그리고 결국, 이 함수는 아래와 같은 행렬과 벡터의 연산으로 나타낼 수 있습니다.


$$
\begin{align}
Xw = y
\end{align}
$$


input(x, 데이터)과 output(y, 예측값)을 이어주는 관계를 나타내는 모델을 찾아야 합니다. 이를 위해 우리가 찾아야 하는 것은 최적의 $w$ 입니다.

$w$는 특징행렬(X)의 역행렬을 통해 다음과 같이 구할 수 있습니다.


$$ 
\begin{align}
w = X^{-1} y  
\end{align}
$$

## 2. 선형 연립방정식을 활용한 예측모델 : 예제 (보스턴 집값 예측모델 생성)


Python의 패키지 중 하나인 scikit-learn 패키지는 머신러닝을 공부하다보면 적어도 한 번쯤은 들어보셨을만큼, 유명하고, 또 그 만큼 유용한 패키지입니다. scikit-learn은 다양한 데이터셋을 제공하기도 하는 데, 그 중 보스턴 집값과 다양한 feature를 묶어놓은 데이터셋을 제공합니다.

앞에서 간단히 살펴본 선형 연립방정식을 활용해, 보스턴 집값을 예측하는 모델을 만들어보려 합니다.

보스턴 집값 문제를 선형 예측모델 $Ax=\hat{b}$ 로 놓고, 가중치 벡터 $x$ 를 구해, 예측모델을 완성해보겠습니다.

문제를 간단히 하기 위해, 입력 데이터를 범죄율(CRIM), 공기 오염도(NOX), 방의 개수(RM), 오래된 정도(AGE)의 4종류로 제한해서 진행해보겠습니다.


```python
from sklearn.datasets import load_boston
boston = load_boston()
X = boston.data
y = boston.target
print(boston.DESCR)
```

    .. _boston_dataset:
    
    Boston house prices dataset
    ---------------------------
    
    **Data Set Characteristics:**  
    
        :Number of Instances: 506 
    
        :Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target.
    
        :Attribute Information (in order):
            - CRIM     per capita crime rate by town
            - ZN       proportion of residential land zoned for lots over 25,000 sq.ft.
            - INDUS    proportion of non-retail business acres per town
            - CHAS     Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
            - NOX      nitric oxides concentration (parts per 10 million)
            - RM       average number of rooms per dwelling
            - AGE      proportion of owner-occupied units built prior to 1940
            - DIS      weighted distances to five Boston employment centres
            - RAD      index of accessibility to radial highways
            - TAX      full-value property-tax rate per $10,000
            - PTRATIO  pupil-teacher ratio by town
            - B        1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
            - LSTAT    % lower status of the population
            - MEDV     Median value of owner-occupied homes in $1000's
    
        :Missing Attribute Values: None
    
        :Creator: Harrison, D. and Rubinfeld, D.L.
    
    This is a copy of UCI ML housing dataset.
    https://archive.ics.uci.edu/ml/machine-learning-databases/housing/
    
    
    This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University.
    
    The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonic
    prices and the demand for clean air', J. Environ. Economics & Management,
    vol.5, 81-102, 1978.   Used in Belsley, Kuh & Welsch, 'Regression diagnostics
    ...', Wiley, 1980.   N.B. Various transformations are used in the table on
    pages 244-261 of the latter.
    
    The Boston house-price data has been used in many machine learning papers that address regression
    problems.   
         
    .. topic:: References
    
       - Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and Sources of Collinearity', Wiley, 1980. 244-261.
       - Quinlan,R. (1993). Combining Instance-Based and Model-Based Learning. In Proceedings on the Tenth International Conference of Machine Learning, 236-243, University of Massachusetts, Amherst. Morgan Kaufmann.
    


보스턴 집값 데이터의 간략한 소개입니다. 카네기 멜론 대학교로부터 데이터가 수집되었다고 하네요. 

데이터는 실수형 / 범주형(categorical) 데이터가 섞여있습니다. 데이터의 index는 506개라고 하네요. Missing value는 없다고 합니다. :)

그럼 데이터를 실제로 출력해서 살펴보겠습니다.


```python
X.shape
```




    (506, 13)



역시, 데이터는 13개의 feature를 대상으로 506개의 index를 갖고 있습니다. 저희는 이 중 4개의 feature만을 대상으로 간략히 조사해보려 하기에, 이를 따로 추출해내야 합니다.

"범죄율(CRIM) : 0, 공기 오염도(NOX) : 4, 방의 개수(RM) : 5, 오래된 정도(AGE) : 6" 이 4가지를 추출해서 특징행렬 $A$ 를 구성하겠습니다.


```python
A = X[:,[0,4,5,6]]
```


```python
# 특징행렬 A를 시각적으로 표현하기 위해 A_라는 별도의 객체를 만들어 데이터프레임으로 나타낸 것입니다.

A_ = pd.DataFrame(A,columns = ['crim','nox','rm','age'])
A_.describe()
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>crim</th>
      <th>nox</th>
      <th>rm</th>
      <th>age</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>count</th>
      <td>506.000000</td>
      <td>506.000000</td>
      <td>506.000000</td>
      <td>506.000000</td>
    </tr>
    <tr>
      <th>mean</th>
      <td>3.613524</td>
      <td>0.554695</td>
      <td>6.284634</td>
      <td>68.574901</td>
    </tr>
    <tr>
      <th>std</th>
      <td>8.601545</td>
      <td>0.115878</td>
      <td>0.702617</td>
      <td>28.148861</td>
    </tr>
    <tr>
      <th>min</th>
      <td>0.006320</td>
      <td>0.385000</td>
      <td>3.561000</td>
      <td>2.900000</td>
    </tr>
    <tr>
      <th>25%</th>
      <td>0.082045</td>
      <td>0.449000</td>
      <td>5.885500</td>
      <td>45.025000</td>
    </tr>
    <tr>
      <th>50%</th>
      <td>0.256510</td>
      <td>0.538000</td>
      <td>6.208500</td>
      <td>77.500000</td>
    </tr>
    <tr>
      <th>75%</th>
      <td>3.677083</td>
      <td>0.624000</td>
      <td>6.623500</td>
      <td>94.075000</td>
    </tr>
    <tr>
      <th>max</th>
      <td>88.976200</td>
      <td>0.871000</td>
      <td>8.780000</td>
      <td>100.000000</td>
    </tr>
  </tbody>
</table>
</div>



다음은 저희의 목표값인 집값 데이터를 벡터 b로 구성하겠습니다.


```python
b = boston.target
b.shape
```




    (506,)



그럼 이제 $Ax=\hat{b}$ 의 x(가중치 벡터)를 구하기 위해, 선형 연립방정식을 풀어보겠습니다. 저희는 $A$ 와 $b$를 구했으니까요!

다만,,, 저희는 지금 sqaure matrix가 아닌 A를 보고 있습니다. 따라서, **A의 역행렬을 구할 수 없습니다.**
역행렬은 기본적으로 square matrix인 경우에만 정확히 구할 수 있기 때문이죠! (물론, approximate approach로 psuedo inverse 가 있기는 하지만, 이후에 다시 살펴보겠습니다.)

따라서, 아직 살펴보진 않았지만, 최소자승문제를 활용한 풀이를 먼저 진행하고 다시 역행렬을 활용해 가중치 벡터($x$)를 찾는 연습을 다시 해보겠습니다.


아직 살펴보진 않았지만, 최소자승문제(Least square problem)의 해결은 지금과 같이 정확한 solution(가중치 벡터 $x$)을 찾을 수 없을 때 활용하는 가장 대표적인 방법입니다. 가장 $x$와 **가까운** solution set을 찾아보자는 접근입니다. 보다 자세히는 추후에 다시 살펴보기로 하겠습니다! : )


### 2_1. Least square problem

Least square problem 해결은 Numpy에서 제공하는 메서드를 활용하겠습니다.

`lstsq()` 메서드는 Least square problem 해결을 위한 코드입니다.


```python
x, resid, rank, s = np.linalg.lstsq(A, b)
```

자 그럼, 우리가 찾고자 했던 solution(x, 가중치벡터)가 어떻게 나왔는지 살펴보겠습니다.


```python
for i in range(4):
    print("{}의 가중치 : {}".format(A_.columns[i],x[i]))
```

    crim의 가중치 : -0.1839836056341421
    nox의 가중치 : -19.396230746735444
    rm의 가중치 : 5.673593152217298
    age의 가중치 : -0.022788798368235375


음... 간단히 해석해보자면,

범죄율, 공기오염도, 연식이 높을 수록 집값은 떨어지는 반비례 관계를 갖는 다는 것을 확인할 수 있습니다. 반면, 방의 갯수는 많을 수록 집값이 높다는 것 을 볼 수 있네요!

보통의 상식과 부합하는 결과입니다! :) 아마도 Least square method가 문제를 어느정도 맞게 해결해낸 것 같습니다!

### 2_2. Solve the systems of linear equations using inverse matrix

이번에는 역행렬을 통해 solution(x, 가중치벡터)를 구해보겠습니다! 
저희가 정의했던 문제는 바로 $Ax=\hat{b}$ 였었죠.

그런데, 문제가 있습니다. 역행렬은 square matrix에서만 존재합니다. 따라서, 저희는 A를 바꿔줘야 합니다. 바로, 정방행렬(square matrix)로 말이죠!


앞에서 최소자승법으로 풀때의 행렬 A는 row가 column에 비해 매우 긴 skinny matrix였죠!


```python
A.shape
```




    (506, 4)



이제 저희는 A를 다시 square matrix로 변환해주겠습니다 !


```python
A = A[:4]
```


```python
A.shape
```




    (4, 4)



그리고 b도 마찬가지로 4개의 component로 변환하겠습니다. 그래야 $(4x4) @ (4x1) = (4x1)$ 이 될테니까요!


```python
b = b[:4]
b.shape
```




    (4,)



그리고 이제 $x = A^{-1}b$ 를 풀기 위해, A의 역행렬을 구하고 x를 구해보겠습니다.


```python
A_inv = np.linalg.inv(A)
```


```python
x = A_inv@b
for i in range(4):
    print("{}의 가중치 : {}".format(A_.columns[i],x[i]))
```

    crim의 가중치 : -312.710043270391
    nox의 가중치 : -115.19394234554954
    rm의 가중치 : 14.4996465318047
    age의 가중치 : -0.1132593173503273


음.. 앞에서 506개의 데이터를 대상으로 찾아낸 가중치와 조금 다릅니다.
물론 비례/반비례 관계는 같지만... 가중치의 값이 매우 큽니다. 아무래도 506개의 데이터를 대상으로 찾은 모델보다는 다소 부정확하고, 매우 경직된(?)것이라 생각해볼 수 있을 것 같습니다!

저희는 Least square method, inverse matrix를 통해 가중치벡터를 찾아보았습니다. 머신러닝과 딥러닝은 이러한 연립방정식의 가중치를 찾는 다양한 방법들의 집합입니다. 앞으로 기회가 된다면, 이러한 다양한 방법들을 함께 본다면 좋겠네요! :)

5458d4acce6f014dc2d0abbb91aab6df9ff01086
ipynb
Jupyter Notebook
1.Study/2. with computer/1.Math_code/5. Mathematics for Machine Learning/2. Linear Algebra_3_2. Solving Systems of Linear Equations.ipynb
jskim0406/Study
07b559b95f8f658303ee53114107ae35940a6080
MIT
1.Study/2. with computer/1.Math_code/5. Mathematics for Machine Learning/2. Linear Algebra_3_2. Solving Systems of Linear Equations.ipynb
jskim0406/Study
07b559b95f8f658303ee53114107ae35940a6080
MIT
1.Study/2. with computer/1.Math_code/5. Mathematics for Machine Learning/2. Linear Algebra_3_2. Solving Systems of Linear Equations.ipynb
jskim0406/Study
07b559b95f8f658303ee53114107ae35940a6080
MIT
Qwen/Qwen-72B
1. YES
2. YES