```python
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import scipy as sp
import scipy.stats
import statsmodels.api as sm
import statsmodels.formula.api as smf

import seaborn as sns
from scipy.optimize import minimize
```

# <font face="gotham" color="purple"> Simple Linear Regression</font>

This is a simple linear regression model as in every textbooks
$$
Y_i=\beta_1+\beta_2X_i+u_i
$$
where $Y$ is **dependent variable**, $X$ is **independent variable** and $u$ is **disturbance term**. $\beta_1$ and $\beta_2$ are unknown parameters that we are aiming to estimate by feeding the data in the model. Without disturbance term, the model is simple a function of a straight line in $\mathbb{R}^2$, such as
$$
Y = 2 + 3X
$$


```python
X = np.linspace(1, 10, 10)
Y = 2 + 3*X
fig, ax = plt.subplots(figsize = (7, 7))
ax.plot(X, Y)
ax.scatter(X, Y, c ='r')
ax.grid()
ax.set_title('$Y=2+3x$')
ax.set_xlim(0, 10)
ax.set_ylim(0, 40)
plt.show()
```

There are five reasons justified that we need a disturbance term:

<i>1. omission of independent variables</i><br>
<i>2. aggregation of variables</i><br>
<i>3. model misspecification</i><br>
<i>4. function misspecification, eg. should be nonlinear rather than linear</i><br>
<i>5. measurement error</i>
    

The second one means that if we intend to aggregate the variable to a macro level, for instance every family has a consumption function, but aggregation on a national level causes discrepancies which contribute to the disturbance term.

The third and forth one will be discussed in details in later chapter.

The fifth one includes all types of error, man-made or natural. 

# <font face="gotham" color="purple"> Odinary Least Squares</font>

**Odinary Least Squares** is the most common estimation technique used in basic econometrics, it is popular due to its _simplicity_ and _transparency_. You'll be able to derive the whole estimation process by hand-calculation, all steps will have _closed-form expression_.

Let's dive in our first plot.


```python
beta1 = 2
beta2 = 3

X = np.linspace(1, 10, 10)
u = 5 * np.random.randn(10)

Y = beta1 + beta2*X + u

Y_hat = 2 + 3*X
fig, ax = plt.subplots(figsize = (7, 7))

for i in range(len(Y)):
    dot_fit_values = [X[i], X[i]]
    dot_org_values = [Y[i], Y_hat[i]]
    ax.plot(dot_fit_values, dot_org_values, linestyle = '--', color = 'red', label = 'residual')

ax.plot(X, Y_hat)
ax.scatter(X, Y_hat, c = 'k')
ax.scatter(X, Y, c ='r')
ax.grid()
ax.set_title('$\hat Y =2+3X$')
plt.show()
```

We have plotted a fitted line onto $10$ observations (red dots) which was generated by $Y_i = 2+3X_i+5u_i$, where $u_i \sim N(0, 1)$. For easy demonstration, say we have a 'perfect' estimator that provides
$$
b_1 = 2\\
b_2 = 3
$$
where $b_1$ and $b_2$ are estimates, in contrast $\beta_1$ and $\beta_2$ are model parameters.

Therefore we can plot a fitted line (blue line) $\hat{Y} = 2+3X$. The red dashed line is the difference of $Y_i$ and $\hat{Y}_i$, we officially call it **residual**, denoted as $e_i$.
$$
e_i = Y_i - \hat{Y}_i = Y_i - b_1-b_2X_i
$$
The OLS algorithm is aiming find the estimates of $\beta_1$ and $\beta_2$ such that
$$
\text{min}RSS=\sum_{i=1}^n e^2_i 
$$
where $RSS$ is the **residual sum of squares**. 

To minimise the $RSS$, we simply take _partial derivatives_ w.r.t. $b_2$ and $b_1$ respectively. The results are the OLS estimators of simple linear regression, which are 
\begin{align}
b_2 &=\frac{\sum_{i=1}^n(X_i-\bar{X})(Y_i-\bar{Y})}{\sum^n_{i=1}(X_i-\bar{X})^2}=\frac{\text{Cov}(X, Y)}{\text{Var}(X)}\\
b_1 &= \bar{Y}-b_2\bar{X}
\end{align}

With these formulae in mind, let's perform a serious OLS estimation. Considering possible repetitive use of OLS in this tutorial, we will write a class for OLS. 


```python
class S_OLS:
    '''Create instances with S_OLS(X, Y), where X and Y are data array.'''
    def __init__(self, X, Y):
        self.X = X
        self.Y = Y
        
    def ols(self):
        '''Estimate the data with OLS method, and return b1 and b2.'''
        cov_mat = np.cov(self.X, self.Y)
        self.b2 = cov_mat[0, 1]/cov_mat[0, 0]
        self.b1 = np.mean(self.Y) - self.b2*np.mean(self.X)
        self.Y_hat = self.b1 + self.b2*self.X
        print('b1 estimate: {:.4f}'.format(self.b1))
        print('b2 estimate: {:.4f}'.format(self.b2))
        return self.Y_hat, self.b2, self.b1
    
    def simul_plot(self, beta1, beta2):
        '''Plot scatter plot and fitted line with ols_plot(self, beta1, beta2), 
        beta1 and beta2 are parameters of data generation process.'''
        fig, ax = plt.subplots(figsize = (7, 7))
        for i in range(len(Y)):
            dot_fit_values = [self.X[i], self.X[i]]
            dot_org_values = [self.Y[i], self.Y_hat[i]]
            ax.plot(dot_fit_values, dot_org_values, linestyle = '--', color = 'red')
        ax.scatter(self.X, self.Y_hat, c = 'k')
        ax.scatter(self.X, self.Y, c ='r')
        ax.plot(self.X, self.Y_hat, label = '$b_1$= {:.2f}, $b_2$={:.2f}'.format(b1, b2))
        ax.grid()
        ax.set_title('$\hat Y ={:.2f}+{:.2f}X$'.format(b1, b2))
        Y_hat_perfect = beta1 + beta2*X
        ax.plot(X, Y_hat_perfect, label = r'$\beta_1=2, \beta_2=3$')
        ax.legend()
        plt.show()
        
    def ols_plot(self, xlabel, ylabel):
        self.xlabel = xlabel
        self.ylabel = ylabel
        fig, ax = plt.subplots(figsize = (7, 7))
        ax.scatter(self.X, self.Y_hat, c = 'k')
        ax.scatter(self.X, self.Y, c ='r')
        ax.plot(self.X, self.Y_hat, label = '$b_1$= {:.2f}, $b_2$={:.2f}'.format(self.b1, self.b2))
        ax.grid()
        ax.set_title('$\hat Y ={:.2f}+{:.2f}X$'.format(self.b1, self.b2))
        ax.set_xlabel(self.xlabel)
        ax.set_ylabel(self.ylabel)
        
    def r_sq(self):
        '''Calculate coefficient of determination and correlation of Y and Yhat'''
        self.ESS = np.var(self.Y_hat)
        self.RSS = np.var(self.Y-self.Y_hat)
        self.R_sq = self.ESS/self.RSS
        return self.ESS, self.RSS, self.R_sq

```


```python
X = np.random.randn(10)
Y = np.random.randn(10)
np.corrcoef(X, Y)
```




    array([[ 1.        , -0.12628739],
           [-0.12628739,  1.        ]])




```python
s_ols = S_OLS(X, Y)
Y_hat, b2, b1 = s_ols.ols()
```

    b1 estimate: -0.1137
    b2 estimate: -0.1228


A convenient function ```np.polyfit``` of curve fitting could verify our results.


```python
np.polyfit(X, Y, 1)
```




    array([-0.12282449, -0.11372037])



The plot the fitted line $b_1+b_2X$, original line $\beta_1+\beta_2X$ and observations.


```python
s_ols.ols_plot('X', 'Y')
```

From the estimation result and graph above, we can notice $b_1$ and $b_2$ are close to true paramters $\beta_1$ and $\beta_2$,  nevertheless minor discrepancies present, this is absolute normal in estimation, no estimation techniques can guarantee a perfect estimation result. 

# <font face="gotham" color="purple"> Interpretation of Estimates</font>

We will check on a real dataset to understand some basic princicples of interpreting estimates. The dataset has $25$ Chinese cities with average house ¥/$m^2$ and average annual disposable income in 2020. 

Load the data with Pandas.


```python
df = pd.read_excel('Basic_Econometrics_practice_data.xlsx', sheet_name = 'CN_Cities_house_price'); df.head()
```




<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>cities</th>
      <th>house_price</th>
      <th>salary</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>Shenzhen</td>
      <td>87957</td>
      <td>64878</td>
    </tr>
    <tr>
      <th>1</th>
      <td>Beijing</td>
      <td>64721</td>
      <td>69434</td>
    </tr>
    <tr>
      <th>2</th>
      <td>Shanghai</td>
      <td>59072</td>
      <td>72232</td>
    </tr>
    <tr>
      <th>3</th>
      <td>Xiamen</td>
      <td>49803</td>
      <td>58140</td>
    </tr>
    <tr>
      <th>4</th>
      <td>Guangzhou</td>
      <td>39851</td>
      <td>68304</td>
    </tr>
  </tbody>
</table>
</div>



Estimate parameters with OLS algorithm.


```python
s_ols_house_income = S_OLS(df['salary'], df['house_price'])
Y_hat, b2, b1 = s_ols_house_income.ols()
```

    b1 estimate: -29181.1698
    b2 estimate: 1.1010


Plot the observation and regression line.


```python
s_ols_house_income.ols_plot('Disposable Income', 'House Price')
```

$b_2$ can be interpreted literally as the graph shows, as disposable income increases $1$ yuan (Chinese currency unit), the house price increases $1.1$ yuan. 

As for $b_1$ we can't interpret that if the disposable income is zero, the house price is $-29181$ yuan, it doesn't make any sense. The basic principle of interpreting $b_1$ is to check if it has a plausible meaning when independent variable equals zero. If no sensible meaning, you don't need to interpret it.

# <font face="gotham" color="purple"> Important Results of OLS</font>

Some features of OLS could provide us some insight of internal mechanism of the algorithm. 

The **first** one is 
$$
\bar{e}=0
$$
It is true because
$$
\bar{e}=\bar{Y}-b_1-b_2\bar{X}=\bar{Y}-(\bar{Y}-b_2\bar{X})-b_2\bar{X}=0
$$
holds. We can demonstrate numerically with the variables that we have defined in house price example.


```python
e = df['house_price'] - Y_hat
np.mean(e) 
```




    7.275957614183426e-13



It is not theoretically zero due to some numerical round-off errors, but we treat it as zero.

The **second** feature is 
$$
\bar{\hat{Y}}=\bar{Y}
$$


```python
print('Mean of Y hat: {}'.format(np.mean(Y_hat)))
print('Mean of Y: {}'.format(np.mean(df['house_price'])))
```

    Mean of Y hat: 30218.879999999994
    Mean of Y: 30218.88


The **third** and **forth** features are
$$
\sum_i^n X_ie_i=0\\
\sum_i^n \hat{Y}_ie_i=0
$$

This can be shown by using a _dot product_ function. 


```python
print(np.dot(df['salary'],e))
print(np.dot(Y_hat,e))
```

    5.364418029785156e-07
    -3.0174851417541504e-07


Actually, lots of econometric theory can be conveniently derived by linear algebra, if you are curious about details and have solid linear algebra skills, you can study my advanced econometric theory lecture notes. For instance, in linear algebra, covariance has a geometric interpretation
$$
\text{Cov}(X, Y)=x\cdot y= ||x||||y||\cos{\theta}
$$
where $x$ and $y$ are vectors in $\mathbb{R}^n$. If dot product equals zero, geometrically these two vectors are perpendicular, denote as $x\perp y$. Therefore the third and forth features are equivalent to
$$
\text{Cov}(X, e)=0\\
\text{Cov}(\hat{Y}, e)=0
$$
i.e. $x\perp e$ and $\hat{y} \perp e$. Traditionally, the vectors are denoted as lower case letters.

# <font face="gotham" color="purple"> Variance of Decomposition</font>

**Variance of decomposition** is based on analysis of variance (ANOVA), if you don't know what ANOVA is meant for, <a href='https://github.com/MacroAnalyst/Basic_Statistics_With_Python/blob/main/Chapter%205%20-%20Analysis%20of%20Variance%20and%20Chi-Squared%20Test.ipynb'>check here</a>. We know that any observation can be decomposed as a fitted value and a residual
$$
Y_i = \hat{Y}_i+e_i
$$
Take variance on both sides
$$
\text{Var}(Y)=\text{Var}(\hat{Y}+e)=\operatorname{Var}(\hat{Y})+\operatorname{Var}(e)+ \underbrace{2 \operatorname{Cov}(\hat{Y}, e)}_{=0}
$$
Or in the explicit form
$$
\frac{1}{n} \sum_{i=1}^{n}\left(Y_{i}-\bar{Y}\right)^{2}=\frac{1}{n} \sum_{i=1}^{n}\left(\hat{Y}_{i}-\overline{\hat{Y}}\right)^{2}+\frac{1}{n} \sum_{i=1}^{n}\left(e_{i}-\bar{e}\right)^{2}
$$

Use the OLS features, i.e. $\bar{\hat{Y}}=\bar{Y}$ and $\bar{e}=0$, the equation simplifies into
$$
\underbrace{\sum_{i=1}^{n}\left(Y_{i}-\bar{Y}\right)^{2}}_{TSS}=\underbrace{\sum_{i=1}^{n}\left(\hat{Y}_{i}-\bar{Y}\right)^{2}}_{ESS}+\underbrace{\sum_{i=1}^{n} e_{i}^{2}}_{RSS}
$$
where $TSS$ means **total sum of squares**, $ESS$ means **explained sum of squares**.

# <font face="gotham" color="purple"> Coefficient of Determination</font>

Though $ESS$ is called 'explained' part, it might be entirely wrong due to misspecification of model. That being said, we still need a quantitative indicator that tells us how much the model is able to 'explain' the behaviour of the dependent variables. 

The **coefficient of determination** is most intuitive indicator
$$
R^2 = \frac{ESS}{TSS}=\frac{\sum_{i=1}^{n}\left(\hat{Y}_{i}-\bar{Y}\right)^{2}}{\sum_{i=1}^{n}\left(Y_{i}-\bar{Y}\right)^{2}}
$$

We have written a ```r_sq()``` method in the ```S_OLS``` class.


```python
ess, rss, r_sq = s_ols_house_income.r_sq()
print(r_sq)
```

    0.5744603125471682


It means the disposable income can explain $57\%$ of house price variation. Furthermore, 
$$
R^2 = \frac{TSS - RSS}{TSS}=1-\frac{RSS}{TSS}
$$
it is clear that minimise $RSS$ is equivalent to maximise $R^2$.

Alternatively, the $R^2$ can be shown its relationship with correlation coefficient $r_{Y, \hat{Y}}$.

$$
\begin{aligned}
r_{Y, \hat{Y}} &=\frac{\operatorname{Cov}(Y, \hat{Y})}{\sqrt{\operatorname{Var}(Y) \operatorname{Var}(\hat{Y})}}=\frac{\operatorname{Cov}([\hat{Y}+e], \hat{Y})}{\sqrt{\operatorname{Var}(Y) \operatorname{Var}(\hat{Y})}}=\frac{\operatorname{Cov}(\hat{Y}, \hat{Y})+\operatorname{Cov}(e, \hat{Y})}{\sqrt{\operatorname{Var}(Y) \operatorname{Var}(\hat{Y})}}=\frac{\operatorname{Var}(\hat{Y})}{\sqrt{\operatorname{Var}(Y) \operatorname{Var}(\hat{Y})}} \\
&=\frac{\sqrt{\operatorname{Var}(\hat{Y}) \operatorname{Var}(\hat{Y})}}{\sqrt{\operatorname{Var}(Y) \operatorname{Var}(\hat{Y})}}=\sqrt{\frac{\operatorname{Var}(\hat{Y})}{\operatorname{Var}(Y)}}=\sqrt{R^{2}}
\end{aligned}
$$

# <font face="gotham" color="purple"> Gauss-Markov Conditions</font>

In order to achieve the best estimation by OLS, the disturbance term ideally has to satisfy four conditions which are called **Gauss-Markov Conditions**. Provided that all G-M conditions satisfied, OLS is the preferred over all other estimators, because mathematically it is proved to be the **Best Linear Unbiased Estimator** (BLUE). This conclusion is called **Gauss-Markov Theorem**.

1. $E(u_i|X_i)=0$
2. $E(u_i^2|X_i)= \sigma^2$ for all $i$, **homoscedasticity**
3. $\text{Cov}(u_i, u_j)=0, \quad i\neq j$, no **autocorrelation**.
4. $\text{Cov}(X_i, u_i)=0$, assuming $X_i$ is non-stochastic.

In addition to G-M conditions, we also assume normality of disturbance term, i.e. $u_i\sim N(0, \sigma^2_u)$, which is guaranteed by _Central Limit Theorem_.

In practice, almost impossible to have all conditions satisfied simultaneously or even one perfectly, but we must be aware of severity of violations, because any violation of G-M condition will compromise the quality of estimation results. And identifying which condition is violated could also lead us to corresponding remedies.

# <font face="gotham" color="purple"> Random Components of Regression Coefficients</font>

According to the OLS formula of $b_2$
$$
b_{2}=\frac{\operatorname{Cov}(X, Y)}{\operatorname{Var}(X)}
$$

Plug in $Y=\beta_1+\beta_2X+u$:
$$
b_{2}=\frac{\operatorname{Cov}(X, Y)}{\operatorname{Var}(X)}=\frac{\operatorname{Cov}(X, \beta_1+\beta_2X+u)}{\operatorname{Var}(X)}
$$

The covariance operation rules come in handy
$$
\operatorname{Cov}(X, \beta_1+\beta_2X+u)=\operatorname{Cov}\left(X, \beta_{1}\right)+\operatorname{Cov}\left(X, \beta_{2} X\right)+\operatorname{Cov}(X, u)
$$

where $\operatorname{Cov}\left(X, \beta_{1}\right)=0$, and $\operatorname{Cov}\left(X, \beta_{2} X\right)=\beta_2 \operatorname{Var}(X)$, therefore
$$
b_{2}=\frac{\operatorname{Cov}(X, Y)}{\operatorname{Var}(X)}=\beta_{2}+\frac{\operatorname{Cov}(X, u)}{\operatorname{Var}(X)}
$$

If $u$ perfectly uncorrelated with $X$ as in G-M condition, the second term should be $0$. However that rarely happens, so the $b_2$ and $\beta_2$ will always have certain level of discrepancy. And note that we can't decompose $b_2$ in practice, because we don't know the true value of $\beta_2$.

And also note that there are two ways to improve the accuracy of $b_2$, either lower the correlation of $X$ and $u$ or increase the variance of $X$.

## <font face="gotham" color="purple"> A Simulated Illustration</font>

We want to perform a Monte Carlo simulation to show the sampling distribution of $b_1$ and $b_2$. First, we write a simple class for OLS Monte Carlo experiment. 

We can set $\beta_1$, $\beta_2$, $N$ and $a_u$ for initialisation. The model is simply
$$
Y_i=\beta_1+\beta_2X_i +a_uu_i, \qquad i\in(1, n),\qquad u_i\sim N(0,1)
$$


```python
class OLS_Monte_Carlo:
    def __init__(self, beta1, beta2, N, u_scaler):
        '''Input beta1, beta2, sample size, scaler of disturbance'''
        self.beta1 = beta1
        self.beta2 = beta2
        self.u_scaler = u_scaler
        self.N = N
        self.X = self.N*np.random.rand(self.N) # generate N random X's in the range of (0, N)
        
    def ols(self):
        '''Estimate the data with OLS method, and return b1 and b2.'''
        self.u = self.u_scaler*np.random.randn(self.N)
        self.Y = self.beta1 + self.beta2*self.X + self.u
        cov_mat = np.cov(self.X, self.Y)
        self.b2 = cov_mat[0, 1]/cov_mat[0, 0]
        self.b1 = np.mean(self.Y) - self.b2*np.mean(self.X)
        return self.b2, self.b1
```

Instantiate the OLS Monte Carlo object with $\beta_1=2$, $\beta_2=3$, $n=10$ and $a_u=1$, then run $10000$ times of simulations, each time with a different set of $u$. All estimated $b_1$ and $b_2$ are collected in their arrays.


```python
ols_mt = OLS_Monte_Carlo(beta1=2, beta2=3, N=10, u_scaler=1)
b2_array, b1_array = [], []
for i in range(10000):
    b2, b1 = ols_mt.ols()
    b2_array.append(b2)
    b1_array.append(b1)
b2_mean = np.mean(b2)
b1_mean = np.mean(b1)
```

Plot the histogram and the mean of estimates. Not difficult to notice that the mean of the $b_1$ and $b_2$ are very close to 'true values'.


```python
fig, ax = plt.subplots(nrows = 2, ncols = 1,figsize=(9, 9))
ax[0].hist(b1_array, bins = 50)
ax[0].axvline(b1_mean, color = 'salmon', label = r'$\bar{b}_1$=%f'% b1_mean)
ax[0].legend()

ax[1].hist(b2_array, bins = 50)
ax[1].axvline(b2_mean, color = 'salmon', label = r'$\bar{b}_2$=%f'% b2_mean)
ax[1].legend()
plt.show()
```

Now we try again with a larger disturbance scaler $a_u = 2$ and keep rest parameters unchanged.


```python
ols_mt = OLS_Monte_Carlo(beta1=2, beta2=3, N=10, u_scaler=2)
b2_array, b1_array = [], []
for i in range(10000):
    b2, b1 = ols_mt.ols()
    b2_array.append(b2)
    b1_array.append(b1)
b2_mean = np.mean(b2)
b1_mean = np.mean(b1)

fig, ax = plt.subplots(nrows = 2, ncols = 1,figsize=(9, 9))
ax[0].hist(b1_array, bins = 50)
ax[0].axvline(b1_mean, color = 'salmon', label = r'$\bar{b}_1$=%f'% b1_mean)
ax[0].legend()

ax[1].hist(b2_array, bins = 50)
ax[1].axvline(b2_mean, color = 'salmon', label = r'$\bar{b}_2$=%f'% b2_mean)
ax[1].legend()
plt.show()
```

Though the histogram has been scaled as seemingly identical as above, but pay attention to the $x$-axis and vertical line. Apparently the variance of $u$ affects the accuracy of estimates, i.e. the variance of sampling distribution of $b_1$ and $b_2$.

It's straightforward to see why this happens from the formula
$$
b_{2}=\beta_{2}+\frac{\operatorname{Cov}(X, a_uu)}{\operatorname{Var}(X)}=\beta_{2}+a_u\frac{\operatorname{Cov}(X, u)}{\operatorname{Var}(X)}
$$

We know from statistics course the increase sample is always doing good for quality of estimates, thus we dial it up to $N=100$, rest are unchanged.


```python
ols_mt = OLS_Monte_Carlo(beta1=2, beta2=3, N=100, u_scaler=2)
b2_array, b1_array = [], []
for i in range(10000):
    b2, b1 = ols_mt.ols()
    b2_array.append(b2)
    b1_array.append(b1)
b2_mean = np.mean(b2)
b1_mean = np.mean(b1)

fig, ax = plt.subplots(nrows = 2, ncols = 1,figsize=(9, 9))
ax[0].hist(b1_array, bins = 50)
ax[0].axvline(b1_mean, color = 'salmon', label = r'$\bar{b}_1$=%f'% b1_mean)
ax[0].legend()

ax[1].hist(b2_array, bins = 50)
ax[1].axvline(b2_mean, color = 'salmon', label = r'$\bar{b}_2$=%f'% b2_mean)
ax[1].legend()
plt.show()
```
Notice how we have improved the accuracy of estimates, pay attention to $x$-axis that the sample distributions are tremendously concentrated than previous runs.
# <font face="gotham" color="purple"> Statistical Features of Estimates</font>

After a visial exam of sample distributions, now we can formally discuss the statistical features of estimator.

## <font face="gotham" color="purple"> Unbiased of Estimator</font>

If an estimator is biased, we rarely perform any estimation with it, unless you have no choices which is also rare. But how to prove unbiasness of an estimator? 

The _rule of thumb_ is to take expectation on both sides of estimator. Here is the OLS example.
$$
E\left(b_{2}\right)=E\left[\beta_{2}+\frac{\operatorname{Cov}(X, u)}{\operatorname{Var}(X)}\right]=\beta_{2}+E\left[\frac{\operatorname{Cov}(X, u)}{\operatorname{Var}(X)}\right]=\beta_2+\frac{E[\operatorname{Cov}(X, u)]}{E[\operatorname{Var}(X)]}
$$
To show $E[\operatorname{Cov}(X, u)]=0$, rewrite covariance in explicit form
$$
E[\operatorname{Cov}(X, u)]=\frac{1}{n} \sum_{i=1}^{n}\left(X_{i}-\bar{X}\right) E\left(u_{i}-\bar{u}\right)=0
$$
Therefore
$$
E\left(b_{2}\right)=\beta_{2}
$$
Again take expectation on $b_1$, immediately we get
$$
E(b_1) = E(\bar{Y})-E(b_2)E(\bar{X})= E(\bar{Y})-\beta_2\bar{X}=\beta_1
$$
where we used $E(\bar{Y})=\beta_{1}+\beta_{2} \bar{X}$.

## <font face="gotham" color="purple"> Precision of Estimator</font>

If we know the variance of disturbance term, the population variance of $b_1$ and $b_2$ can be derived
$$
\sigma_{b_{1}}^{2}=\frac{\sigma_{u}^{2}}{n}\left[1+\frac{\bar{X}^{2}}{\operatorname{Var}(X)}\right]\\\sigma_{b_{2}}^{2}=\frac{\sigma_{u}^{2}}{n \operatorname{Var}(X)}
$$
Though we will never really know $\sigma_{u}$, the formulae provide the intuition how the variance of coefficients are determined. 

In the visual example of last section, we have seen that the larger $\sigma_{u}$ causes larger $\sigma_{b_{1}}^{2}$ and $\sigma_{b_{2}}^{2}$, here the formulae also present the relation. 

And there are two ways to contract the variance of $b_1$ and $b_2$, one is increasing sample size $n$, the other is increasing $\operatorname{Var}(X)$.

In practice, we substitute $\sigma_{u}^{2}$ by its unbiased estimator
$$
s_{u}^{2}=\frac{n}{n-2} \operatorname{Var}(e)
$$

where $\operatorname{Var}(e)$ is the sample variance of residuals. The term $\frac{n}{n-2}$ is for upscaling variance, because generally residuals are smaller than disturbance term, this is determined by its mathematical nature. You will get a very clear linear algebraic view in advanced econometric theory. 

After plug-in we get the _standard error_ of $b_1$ and $b_2$
$$
\text { s.e. }\left(b_{1}\right)=\sqrt{\frac{s_{u}^{2}}{n}\left[1+\frac{\bar{X}^{2}}{\operatorname{Var}(X)}\right]}\\
\text { s.e. }\left(b_{2}\right)=\sqrt{\frac{s_{u}^{2}}{n \operatorname{Var}(X)}}
$$
The stardard error is used when we are referring to the _standard deviation of sampling distribution of estimates_, specifically in econometric term, regression coefficients.

# <font face="gotham" color="purple"> Hypothesis Testing and $t$-Test</font>

Essentially, hypothesis testing in econometrics is the same as statistics. We propose a theory and test against data collected by experiment or sampling. 

That being said, in econometrics, we mainly investigate if the linear relation between independent and dependent variables is plausible, so we rarely test a specific null hypothesis such that $\beta_2 = 2$, but rather $\beta_2 =0$. Therefore
$$
H_0: \beta_1 = 0, \beta_2 =0\\
H_1: \beta_1 \neq 0, \beta_2 \neq 0 
$$

Let's reproduce the house price example. We have the estimates, but we would like to investigate how reliable the results are. Reliability hinges on relativity, that means even if the absolute value of estimates are small, such as $.1$, as long as the standard error are smaller enough, such as $.01$, we can safely conclude a rejection of null hyphothesis without hesitation. 

$t$-statisc of $b_1$ and $b_2$ are 
$$
\frac{b_1-\beta_1^0}{s.e.(b_1)}\qquad\frac{b_2-\beta_2^0}{s.e.(b_2)}
$$
where $\beta^0$ is null hypothesis. 

Generally, statistics are intuitive to interpret, it measures how many standard deviations (with known $\sigma$) or standard errors (with unknown $\sigma$) away from the null hypothesis. The further way, the stronger evidence supporting the rejection of null hypothesis. 


```python
df = pd.read_excel('Basic_Econometrics_practice_data.xlsx', sheet_name = 'CN_Cities_house_price')
s_ols_house_income = S_OLS(df['salary'], df['house_price'])
Y_hat, b2, b1 = s_ols_house_income.ols()
s_ols_house_income.ols_plot('Disposable Income', 'House Price')
resid = df['house_price'] - Y_hat
```

Compute $t$-statistic as in formulae


```python
n = len(df['house_price'])
s_u_sqr = n/(n-2)*np.var(resid)

std_err_b1 = np.sqrt(s_u_sqr/n*(1+np.mean(df['salary'])**2/np.var(df['salary'])))
std_err_b2 = np.sqrt(s_u_sqr/(n*np.var(df['salary'])))

t_b1 = b1/std_err_b1
t_b2 = b2/std_err_b2
print('t_b1:{:.4f}'.format(t_b1))
print('t_b2:{:.4f}'.format(t_b2))
```

    t_b1:-1.7580
    t_b2:3.6349


Seems both $t$'s are far away from null hypothesis $\beta^0=0$, but how far is real far? Unless we have a quantitative criterion, the interpretations won't sound objective. 

That's why we have **significant level** (denoted as $\alpha$) as the decisive criterion. The common levels is $5\%$ and $1\%$. If $t$ falls on the right of **critical value** of $t$ at $5\%$, we can conclude a rejection of null hypothesis.
$$
t > t_{.05}
$$
However in econometrics two-side test is more common, then rejection rules of $\alpha=.05$ are
$$
t<t_{-.025} \text{ and }t > t_{.025}
$$
Critical value of $t$-distribution is obtained by ```sp.stats.t.ppf```, and the shape of $t$-distribution approximate to normal distribution as degree of freedom raise.

The two-side test $t$-statistic is


```python
t_crit = sp.stats.t.ppf(.975, df = n-1); t_crit
```




    2.0638985616280205



Therefore we conclude a rejections of $\beta_2=0$ ($t_{b_2}>t_{crit}$) but fail to reject $\beta_1=0$ ($t_{b_1}<t_{crit}$). 

The $b_1=1.1010$ is interpreted that every $1$ yuan increment of disposable income is accompanied by raising $1.1010$ yuan on house price.

In contrast, $b_0= -29181.16$ can't be interpreted that if every family has $0$ disposable income, the house price will be $-29181.16$, because it doesn't have any logical or economic sense. So the rule of thumb for interpretation of constant term: _it's unnecessary to interpret constant coefficient if the it has no logical sense_.

<div style="background-color:Bisque; color:DarkBlue; padding:30px;">
<i><b>Side note of $t$-distribution</b><br>
Here below is a figure for refreshing $t$-statistics, we set $\alpha=.05$. The first axes demonstrates how $t$-statistic changes as degree of freedom raises, the second shows that $t$-distribution approximates normal distribution indefinitely with rising degree of freedom.</i>
<\div>


```python
degree_frd = np.arange(1, 50, 1)
t_array = sp.stats.t.ppf(.975, df=degree_frd)
fig, ax = plt.subplots(nrows=2, ncols=1,figsize=(14,12))
ax[0].plot(degree_frd, t_array)
ax[0].set_xlim([0, 20])
ax[0].set_xlabel('degree of freedom')
ax[0].set_ylabel('critical value of $t$-statistic')
ax[0].set_title('The Change of $t$-statistic As d.o.f. Increases')
x = np.linspace(-3, 3, len(degree_frd))
for i in range(len(degree_frd)):
    t_pdf = sp.stats.t.pdf(x, degree_frd[i], loc=0, scale=1) #pdf(x, df, loc=0, scale=1)
    if i % 8 == 0: 
        ax[1].plot(x, t_pdf, label = 't-Distribution with d.o.f. = {}'.format(i))
    else:
        ax[1].plot(x, t_pdf)
ax[1].set_title('The Shape of $t$-Distribution Approximate Normal Distribution As d.o.f. Increases')
ax[1].legend()
plt.show()
```

# <font face="gotham" color="purple"> $p$-Values</font>

Personally, I myself prefer to $p$-values. It is more informative than $t$-statistic, $p$-value gives the probability of obtaining corresponding $t$-statistic if null hypothesis is true, which is exactly the probability of **type I error**. 

With proper use of ```sp.stats.t.cdf```, we can access $p$-value conveniently. 


```python
1 - sp.stats.t.cdf(t_b2, df=n) # because t_b2 is positive, so p-value should be deducted from 1, if negative then without
```




    0.0006284669089313688



$p$-value tells that if null hypothesis is true, the probability of obtaining $t_{b_2}=3.6349$ or even higher is merely $0.0006$. That means, very unlikely the null hypothesis is true, we can safely reject null hypothesis with a tiny probability of Type I error.

Medical researches conventionally uses $p$-value, econometrics tend to use estimates with standard error bracketed below. But they just different ways of expressing the same ideas, pick based on your preference unless you don't are writing an economic paper. 

<div style="background-color:Bisque; color:DarkBlue; padding:30px;">
<i><b>Side note of Type I and II Error</b><br>
The blue shaded area are genuinely generated by null distribution, however they are too distant (i.e. $2\sigma$ away) from the mean ($0$ in this example), and they are mistakenly rejected, this is what we call <b>Type I Error</b>.
<br>
<br>
The orange shaded area are actually generated by alternative distribution, however they are in the adjacent area of mean of null hypothesis, so we failed to reject they, but wrongly. And this is called <b>Type II Error</b>.
<br>
<br>
As you can see from the chart, if null distribution and alternative are far away from each other, the probability of both type of errors diminish to trivial. </i>
</div>


```python
from plot_material import type12_error
type12_error()
```

# <font face="gotham" color="purple"> Confidence Interval </font>

Why bother with confidence interval if we have hypothesis testing?

If you have a theory that house price has a certain linear relationship with disposable income, you test theory with model, this is called _hypothesis testing_. But what if you don't have a theory yet, and runs the regression, you are wondering how confident these estimates can represent the true parameters, the range that you feel confident is called **confidence interval**.

These two procedures complementing each other, that's why we see them often reported together.

Recall the rejection rules are
$$
\frac{b-\beta}{\text { s.e. }\left(b\right)}>t_{\text {crit }} \quad \text { or } \quad \frac{b-\beta}{\text { s.e. }\left(b\right)}<-t_{\text {crit }}
$$
If we slight rearrange and join them, we get the confidence interval
$$
b-\text { s.e. }\left(b\right) \times t_{\text {crit }} \leq \beta\leq b+\text { s.e. }\left(b\right) \times t_{\text {crit }}
$$
The higher significance level, the smaller $\alpha$ is, the larger confidence interval (because of larger $t_{crit}$). For example, if the significance level is $\alpha=.05$, then confidence level is $0.95$.

Here's the confidence interval ($95\%$) of our house price example.


```python
t_crit = sp.stats.t.ppf(.975, df = n-1)
print('C.I. of b1: [{}, {}]'.format(b1-t_crit*std_err_b1, b1+t_crit*std_err_b1))
print('C.I. of b2: [{}, {}]'.format(b2-t_crit*std_err_b2, b2+t_crit*std_err_b2))
```

    C.I. of b1: [-63439.54567466995, 5077.206045321876]
    C.I. of b2: [0.4758472405690619, 1.7261233292171854]


There are $95\%$ chances the true parameter $\beta$ will 'fall' in this confidence interval.

# <font face="gotham" color="purple"> One-Tailed vs Two-Tailed Test </font>

So far we have been discussing about two-tailed test, but there are scenarios that one-tailed test make more sense. In our house price example, some practitioners would prefer to test the theory or common sense: _disposable income would not have negative effects on house price_. The alternative would be that _disposable income would have either no effect or positive effects on house price_.

Thus the one-tailed test hypotheses are
$$
H_0: \beta_2<0\\
H_1: \beta_2\geq 0
$$
In one-tailed test, we don't split $\alpha$ anymore since there is only one side, that means the critical value will be smaller, easier to reject null hypothesis. 

Here is $t_{crit}$ of $\alpha=5\%$. However, these are conventional rules, if you still prefer $2.5\%$ on one-side, feel free to do so. Especially you have a very significant $t$-statistic, such as $10$, one-tailed or two-tailed won't really matter. 


```python
t_crit_oneside = sp.stats.t.ppf(.95, df = n-1); t_crit_oneside
```




    1.7108820799094275



So here the rule of thumb for one-tailed test.

<div style="background-color:Bisque; color:DarkBlue; padding:30px;">
<i><b>Rules of Thumb for One-Tailed Test</b><br>
1. If the theory or common sense supports one side test, e.g. household consumption increases as disposable incomes increase.<br>
2. If two-tailed test failed to reject, but one-tailed reject, you can report one-tailed test results if the first rule satisfied too.
</div>

# <font face="gotham" color="purple"> $F$-test</font>

$F$-test is based on _Analysis of Variance_ (ANOVA), the goal is to test **multiple restrictions** on the regression model. In simple linear regression model, the **joint hypothesis** is usually
\begin{align}
H_0&: \beta_1 = 0,\qquad\beta_2=0\\
H_1&: \text{One or more restrictions does not hold}
\end{align}

once you have ANOVA done, $F$-statistic is an natural byproduct.
$$
F=\frac{E S S /(k-1)}{R S S /(n-k)}
$$
where $k$ is the number of number of parameters in the regression model, here in simple regression model $k=2$ and $n$ is the sample size.

You might have doubt now: why aren't we using same old $t$-tests such that
$$
H_0: b_1=0 \qquad H_0: b_2=0 \qquad \\
H_1: b_1\neq0 \qquad H_1: b_2\neq0\qquad\\
$$

Apparently, the number of $t$-tests will be as large as ${k \choose 2} $ where $k$ is the number of parameters. If there are $5$ parameters, then we have to test ${5 \choose 2}=10$ pairs. With $95\%$ confidence level, $10$ $t$-tests would cut back confidence level dramatically to $95\%^{10}=59.8\%$, which also means the probability of _type I_ error would be around $40\%$.

We have user-defined functions written in the OLS class, so $F$-statistic is 


```python
f_stat = (ess/(2-1))/(rss/(len(df['salary'])-2))
print('F-statistic is {:.4f}.'.format(f_stat))
```

    F-statistic is 13.2126.



```python
p_value = 1 - sp.stats.f.cdf(f_stat, 1, len(df['salary'])-2) # sp.stats.f.cdf(df on nominator, df on denom) 
print('p-value is {:.4f}.'.format(p_value))
```

    p-value is 0.0014.


To explore further, we can even prove that in simple linear regression $F$ are the just the square of $t$.

<div style="background-color:Bisque; color:DarkBlue; padding:30px;">
<i><b>$F$-statistic and $t$-statistic</b><br>
Here's the proof that $F$ and $t$ are connected
$$
F=\frac{R^{2}}{\left(1-R^{2}\right) /(n-2)}=\frac{\frac{\operatorname{Var}(\hat{Y})}{\operatorname{Var}(Y)}}{\left\{1-\frac{\operatorname{Var}(\hat{Y})}{\operatorname{Var}(Y)}\right\} /(n-2)}\\
=\frac{\frac{\operatorname{Var}(\hat{Y})}{\operatorname{Var}(Y)}}{\left\{\frac{\operatorname{Var}(Y)-\operatorname{Var}(\hat{Y})}{\operatorname{Var}(Y)}\right\} /(n-2)}=\frac{\operatorname{Var}(\hat{Y})}{\operatorname{Var}(e) /(n-2)}\\
=\frac{\operatorname{Var}\left(b_{1}+b_{2} X\right)}{\left\{\frac{1}{n} \sum_{i=1}^{n} e_{i}^{2}\right\} /(n-2)}=\frac{b_{2}^{2} \operatorname{Var}(X)}{\frac{1}{n} s_{u}^{2}}=\frac{b_{2}^{2}}{\frac{s_{u}^{2}}{n \operatorname{Var}(X)}}=\frac{b_{2}^{2}}{\left[\operatorname{s.e.} \left(b_{2}\right)\right]^{2}}=t^{2}
$$
</div>

<div style="background-color:Bisque; color:DarkBlue; padding:30px;">
<i><b>$F$-statistic and $R^2$</b><br>
$F$-statistic is a different angle of evaluating the goodness of fit, it can be shown that $F$ and $R^2$ are closely connected, divide both nominator and denominator by $TSS$:
$$
F=\frac{(E S S / T S S) /(k-1)}{(R S S / T S S) /(n-k)}=\frac{R^{2} /(k-1)}{\left(1-R^{2}\right) /(n-k)}
$$
We prefer to $F$ for hypothesis test, it's because critical value of $F$ is straightforward, and critical value of $R^2$ has to be calculated based on $F_{crit}$:
$$
R_{\mathrm{crit}}^{2}=\frac{(k-1) F_{\mathrm{crit}}}{(k-1) F_{\text {crit }}+(n-k)}
$$
</div>

# <font face="gotham" color="purple">Regression vs Correlation</font>

Here is the message for all beginner that misinterpret regression relationship as causation.

<div style="background-color:Bisque; color:DarkBlue; padding:30px;">
<i><b>Does Regression Imply Causation</b><br>

It's tempting to interpret regression result as causality, but it's not. <b>Regression only implies a statistical relationship</b>, the independent variables may or may not be the cause of dependent variables, sometimes we know thanks to theories, sometimes we don't.
    
For instance, researches found that parents with higher education tend to have healthier children, but this is hardly a causality. Perhaps higher education parents are in general wealthier, they can afford decent medical packages. Or they spend time with their kids on sports and dining. We can form some hypothesis, but not a definite causality based on one regression.
</div>

But regressions do resemble the correlation to some extent

<div style="background-color:Bisque; color:DarkBlue; padding:30px;">
<i><b>Does Regression Imply Correlation</b><br>
From formula of $b_2$
$$
b_2 =\frac{\text{Cov}(X, Y)}{\text{Var}(X)}
$$
We can see the regression indeed has a component of correlation (covariance in the formula), but it's normalised by variance (i.e. $\sigma_X\sigma_X$) rather than $\sigma_X\sigma_Y$. To compare with correlation coefficient of $X$ and $Y$ 
$$
\rho_{XY}=\frac{\text{Cov}(X, Y)}{\sigma_X\sigma_Y}
$$
We can see one important difference is that regression coefficient does not treat both variables symmetrically, but correlation coefficient does. Joining two formulae, we have a different view of the coefficient.<br><br>
$$
b_2=\frac{\rho_{XY}\sigma_X\sigma_Y}{\text{Var}(X)}= \frac{\rho_{XY}\sigma_X\sigma_Y}{\sigma_X\sigma_X}=\rho_{XY}\frac{\sigma_Y}{\sigma_X}
$$
    
Besides that, the purpose of these two techniques are different, regression are mainly predicting dependent variables behaviours, but correlation are mainly summarising the direction and strength among two or more variables. 
</div>

Maybe a chart can share insight of their relationship. All data are simulated by $u\sim N(0, 1)$. It's easy to notice the smaller correlation implies a smaller slope coefficient in terms of absolute value. And larger disturbance term also implies lower correlation coefficient. 


```python
from plot_material import reg_corr_plot
reg_corr_plot()
```

# <font face="gotham" color="purple"> Joint Confidence Region</font>

**Joint confidence region** are the joint distribution of regression coefficients, it is theoretically an ellipse. It shows the distributed location of the coefficient pair. 

Here is a Monte Carlo simulation, we set $\beta_1 = 3$, $\beta_2 = 4$ and $u\sim N(0, 10)$, run $1000$ times then plot the estimates.


```python
beta1, beta2 = 3, 4
beta1_array, beta2_array = [], []
for i in range(1000):
    u = 10*np.random.randn(30)
    X2 = np.linspace(10, 100, 30)
    Y = beta1 + beta2*X2 + u

    df = pd.DataFrame([Y, X2]).transpose()
    df.columns = ['Y', 'X2']

    X_inde = df['X2']
    Y = df['Y']

    X_inde = sm.add_constant(X_inde)

    model = sm.OLS(Y, X_inde).fit()
    beta1_array.append(model.params[0])
    beta2_array.append(model.params[1])

fig, ax = plt.subplots(figsize = (10, 10))
ax.grid()
for i in range(1000):
    ax.scatter(beta1_array[i], beta2_array[i]) # no need for a loop, i just want different colors
ax.set_xlabel(r'$\beta_1$')
ax.set_ylabel(r'$\beta_2$')
plt.show()
```

But why the joint distribution of coefficient has an elliptic shape? If you take a look at any linear regression plot, it wouldn't be difficult to notice that the high slope coefficient $\beta_2$ would cause low the intercept coefficient $\beta_1$, this is a geometric feature of linear regression model.

And from the plot, we can see the range of $\beta_1$ is much larger than $\beta_2$ and even include $0$, especial the data points are far away from $0$, $\beta_1$ can have erratic results, that's also the reason we don't expect to interpret $\beta_1$ most of time.

# <font face="gotham" color="purple"> Stochastic Regressors</font>

One of G-M condition is $\text{Cov}(X_i, u_i)=0$, assuming $X_i$ is non-stochastic. But we commonly encounters that $X_i$ is stochastic, for instance you sample $10$ family's annual income, you have no clue on how much they are earning eventually, therefore assuming they are stochastic would be more appropriate. 

If $X_i$ is stochastic and distributed independently of $u_i$, it guarantees that $\text{Cov}(X_i, u_i)=0$, but not vice versa.

# <font face="gotham" color="purple"> Maximum Likelihood Estimation</font>

In more advanced level of econometric research, **maximum likelihood estimation**(MLE) is used more often than OLS. The reason is that MLE is more flexible on assumption of disturbance term, i.e. not assuming the normality of the disturbance term. But it requires you to have an assumption of certain distribution, it can be exponential or gamma distribution or whatever. 

We will provide two examples to illustrate the philosophy of MLE, one is to estimate simple linear regression with MLE and the other is to estimate a mean of an exponential distribution.

## <font face="gotham" color="purple"> MLE for Simple Linear Regression </font>

Once you have a dataset, you should know the data are just observations of random variables. For instance, you are about to collect $100$ family's annual income data for year 2021, each family's income is essentially a random variable, hence it follows some distribution, it can be normal distribution or skewed gamma distribution. 

Once the data is collected, the observances are done. Each data point, i.e. $Y_1, Y_2, ..., Y_n$ is just single realization of its distribution, the joint distribution of all random variables is
$$
f\left(Y_{1}, Y_{2}, \ldots, Y_{n}\right)
$$
We assume a simple linear regression $Y_{i}=\beta_{1}+\beta_{2} X_{i}+u_{i}$ model to explain $Y$, then the joint distribution is conditional
$$
f\left(Y_{1}, Y_{2}, \ldots, Y_{n} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right)
$$
We also assume each family's income is independent of rest, then joint distribution equals the product of all distributions.
$$
\begin{aligned}
&f\left(Y_{1}, Y_{2}, \ldots, Y_{n} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right)=f\left(Y_{1} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right) f\left(Y_{2} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right) \cdots f\left(Y_{n} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right) =\prod_{i=0}^nf\left(Y_{i} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right)
\end{aligned}
$$

Now we need to ask ourselves, what distribution does $Y$ follow? It's the same as asking what's the distribution of $u$? It's reasonable to assume $u$ follow normal distribution, so are $Y$'s.
$$
f(Y_i)= \frac{1}{\sigma \sqrt{2\pi}}e^{-\frac{1}{2}\frac{[Y_i-E(Y_i)]^2}{\sigma^2}}=\frac{1}{\sigma \sqrt{2\pi}}e^{-\frac{1}{2}\frac{[Y_i-\beta_1-\beta_2X_i]^2}{\sigma^2}}
$$

Then the joint distribution is the product of this PDF function
$$
\prod_{i=0}^nf\left(Y_{i} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right)=\frac{1}{\sigma^{n}(\sqrt{2 \pi})^{n}} e^{-\frac{1}{2} \sum \frac{\left(Y_{i}-\beta_{1}-\beta_{2} X_{i}\right)^{2}}{\sigma^{2}}}
$$

Once we have joint distribution function, in a frequentist view, the observed data is generated by this distribution with certain parameters, in this case $\beta_1, \beta_2$ and $\sigma^2$. So the fundamental the questions are what those parameters are? How to find them?

We give a name to the join distribution function above - **likelihood function**, which means how likely a set of parameters can generate a set of data. We denote likelihood function as $LF(\beta_1, \beta_2, \sigma^2)$.

The MLE, as its name indicates, is to estimate the parameters that in such manner that the probability of generating $Y$'s is the highest. 

To derive a analytical solution, usually we use log form likelihood function
$$
\ln{LF}=\ln{\prod_{i=0}^nf\left(Y_{i} \mid \beta_{1}+\beta_{2} X_{i}, \sigma^{2}\right)} =-\frac{n}{2} \ln \sigma^{2}-\frac{n}{2} \ln (2 \pi)-\frac{1}{2} \sum \frac{\left(Y_{i}-\beta_{1}-\beta_{2} X_{i}\right)^{2}}{\sigma^{2}}
$$

Take derivative with respect to $\beta_1$, $\beta_2$ and $\sigma^2$ and equal them to $0$ will yield the **maximum likelihood estimators** for simple linear regression with assumption of normally distributed disturbance term
\begin{align}
b_2 &= \frac{\sum_{i=1}^n (X_i - \bar{X})(Y_i-\bar{Y})}{\sum_{i=1}^n(X_i-\bar{X})^2}=\frac{\text{Cov}(X, Y)}{\text{Var}(X)}\\
b_1 &= \bar{Y}-\beta_2\bar{X}\\
s^2 &= \frac{1}{n} \sum_{i=1}^{n}\left(Y_{i}-\left(b_{0}+b_{1} X_{i}\right)\right)^{2} = \frac{1}{n}\sum_{i=1}^n e_i^2
\end{align}

MLE $b_1$ and $b_2$ are exactly the same as OLS estimators, only the $s^2$ differs from OLS estimator $s^2 = \frac{\sum e^2_i}{n-2}$. The MLE $s^2$ is biased in small sample, but _consistent_ as sample size increases.

We'll experiment with MLE with simulated data. Generate a data for OLS estimation and print the estimated coefficients.


```python
N = 100
X = np.linspace(0, 20, N)
u = np.random.normal(loc = 0, scale = 10, size = N)

beta1, beta2 = 2, 3
Y = beta1 + beta2*X + u
df = pd.DataFrame({'Y':Y, 'X':X})

X = df['X']
Y = df['Y']

X = sm.add_constant(X) # adding a constant

model = sm.OLS(Y, X).fit() 

print_model = model.summary()
model.params
```




    const    1.616445
    X        3.077071
    dtype: float64



Estimated standard deviation of disturbance term. 


```python
np.sqrt(np.sum(model.resid**2)/(N-2))
```




    10.680968046974376



```statsmodel``` library doesn't have a direct api for maximum likelihood estimation, but we can construct it with ```Scipy```'s ```minimize``` function, so we define a negative log likelihood. The reason of negative function is because ```Scipy``` has only ```minimize``` function.


```python
def neg_log_likelihood(params):
    intercept, beta, std_dev = params[0], params[1], params[2]
    Yhat = intercept + beta*X 
    negLL = -np.sum(sp.stats.norm.logpdf(Y, loc=Yhat, scale=std_dev)) # negative log-likelihood
    return(negLL)
```


```python
init_value = np.array([1,1,1])
results = minimize(neg_log_likelihood, init_value, method = 'Nelder-Mead', options={'disp': True}) # options={'disp': True} is not a must
```

Print the relevant results.


```python
resultsdf = pd.DataFrame({'coef':results['x']})
resultsdf.index=['Intercept','Slope','Sigma']   
resultsdf
```

As you can see the intercept and slope coefficients are the same as OLS, but $\hat{\sigma}$ is underestimated as the theory tells.

## <font face="gotham" color="purple"> MLE for Exponential Distribution </font>

MLE is more general than OLS, it can estimate any parameters as long as you know or assume the distribution, this example we will give an explicit function form for an exponential function. 

Consider 
$$
f(Y_i; \theta) = \theta e^{-\theta Y_i}
$$
The joint distribution (likelihood function) is 
$$
\prod_{i=1}^n f(Y_i; \theta) = \theta^ n  e^{-\theta \sum Y_i}
$$
Log likelihood function is
$$
\ln \prod_{i=1}^n f(Y_i; \theta) = n\ln{\theta} - \theta \sum_{i=1}^n Y_i
$$

Take derivative with respect to $\theta$
$$
\frac{\partial LF}{\partial \theta} = \frac{n}{\theta}-\sum_{i=1}^n Y_i = 0
$$

The result is 
$$
\hat{\theta} = \frac{n}{n \bar{Y}} = \frac{1}{\bar{Y}}
$$

The estimated parameter $\hat{\theta}$ is the reciprocal of mean of $Y_i$.

# <font face="gotham" color="purple">Statsmodels Library </font>

Fortunately, we don't need to program our own toolbox for estimations, ```statsmodels``` library will be our main tool from now on, all the codes are self-explanatory unless it requires further clarification.

The estimation results are reported in as in Stata or Eview, there is a test run below. 


```python
X = df['salary']
Y = df['house_price']

X = sm.add_constant(X) # adding a constant

model = sm.OLS(Y, X).fit()

print_model = model.summary()
print(print_model)
```

However, you might see some people using $R$-style formula such as
```Y ~ X + Z```, which produces the same results.


```python
df = pd.read_excel('Basic_Econometrics_practice_data.xlsx', sheet_name = 'CN_Cities_house_price')
df.head()

model = smf.ols(formula='house_price ~ salary', data=df)
results = model.fit()
print(results.summary())
```


```python

```

8f000ddd37b0b17ad88bb0565773ecad771b21bf
ipynb
Jupyter Notebook
1. Simple Linear Regression.ipynb
MacroAnalyst/Basic_Econometrics_With_Python
38ba2f99fabf9edb176a54fa688ae65bdcd120cb
MIT
2021-07-19T07:13:25.000Z
2022-03-28T19:50:07.000Z
1. Simple Linear Regression.ipynb
MacroAnalyst/Basic_Econometrics_With_Python
38ba2f99fabf9edb176a54fa688ae65bdcd120cb
MIT
1. Simple Linear Regression.ipynb
MacroAnalyst/Basic_Econometrics_With_Python
38ba2f99fabf9edb176a54fa688ae65bdcd120cb
MIT
2021-11-17T16:07:56.000Z
2022-03-24T22:40:53.000Z
Qwen/Qwen-72B
1. YES
2. YES