From 623ed5166833e01904ee48030d56614dc8ce8634 Mon Sep 17 00:00:00 2001 From: Morten Hjorth-Jensen Date: Mon, 4 Oct 2021 20:48:46 +0200 Subject: [PATCH] cleaning up typos --- .../2021/Project1/html/._Project1-bs000.html | 12 +- .../2021/Project1/html/Project1-bs.html | 12 +- doc/Projects/2021/Project1/html/Project1.html | 12 +- .../2021/Project1/ipynb/Project1.ipynb | 13 +- .../Project1/ipynb/ipynb-Project1-src.tar.gz | Bin 193 -> 193 bytes doc/Projects/2021/Project1/pdf/Project1.p.tex | 13 +- doc/Projects/2021/Project1/pdf/Project1.pdf | Bin 248253 -> 248127 bytes doc/Projects/2021/Project1/pdf/Project1.tex | 13 +- .../Projects/2021/Project1/Project1.do.txt | 11 +- doc/src/week37/programs/LinearReg.py | 270 ++++++++++++++++++ 10 files changed, 315 insertions(+), 41 deletions(-) create mode 100644 doc/src/week37/programs/LinearReg.py diff --git a/doc/Projects/2021/Project1/html/._Project1-bs000.html b/doc/Projects/2021/Project1/html/._Project1-bs000.html index 46957ed0a..8fe85fccd 100644 --- a/doc/Projects/2021/Project1/html/._Project1-bs000.html +++ b/doc/Projects/2021/Project1/html/._Project1-bs000.html @@ -168,7 +168,7 @@ MathJax.Hub.Config({
University of Oslo, Norway

-

Sep 14, 2021

+

Oct 4, 2021


@@ -284,21 +284,21 @@ analysis using polynomials in \( x \) and \( y \) up to fifth order. Find the confidence intervals of the parameters (estimators) \( \beta \) by computing their variances, evaluate the Mean Squared error (MSE) -$$ MSE(\hat{y},\hat{\tilde{y}}) = \frac{1}{n} +$$ MSE(\boldsymbol{y},\tilde{\boldsymbol{y}}) = \frac{1}{n} \sum_{i=0}^{n-1}(y_i-\tilde{y}_i)^2, $$

-and the \( R^2 \) score function. If \( \tilde{\hat{y}}_i \) is the predicted +and the \( R^2 \) score function. If \( \tilde{\boldsymbol{y}}_i \) is the predicted value of the \( i-th \) sample and \( y_i \) is the corresponding true value, then the score \( R^2 \) is defined as $$ -R^2(\hat{y}, \tilde{\hat{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, +R^2(\boldsymbol{y}, \tilde{\boldsymbol{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, $$

-where we have defined the mean value of \( \hat{y} \) as +where we have defined the mean value of \( \boldsymbol{y} \) as $$ \bar{y} = \frac{1}{n} \sum_{i=0}^{n - 1} y_i. @@ -406,7 +406,7 @@ Note also that when you calculate the bias, in all applications you don't know t The aim here is to write your own code for another widely popular resampling technique, the so-called cross-validation method. Again, before you start with cross-validation approach, you should scale your -data. +data if you think this is needed.

Implement the \( k \)-fold cross-validation algorithm (write your own diff --git a/doc/Projects/2021/Project1/html/Project1-bs.html b/doc/Projects/2021/Project1/html/Project1-bs.html index 46957ed0a..8fe85fccd 100644 --- a/doc/Projects/2021/Project1/html/Project1-bs.html +++ b/doc/Projects/2021/Project1/html/Project1-bs.html @@ -168,7 +168,7 @@ MathJax.Hub.Config({

University of Oslo, Norway

-

Sep 14, 2021

+

Oct 4, 2021


@@ -284,21 +284,21 @@ analysis using polynomials in \( x \) and \( y \) up to fifth order. Find the confidence intervals of the parameters (estimators) \( \beta \) by computing their variances, evaluate the Mean Squared error (MSE) -$$ MSE(\hat{y},\hat{\tilde{y}}) = \frac{1}{n} +$$ MSE(\boldsymbol{y},\tilde{\boldsymbol{y}}) = \frac{1}{n} \sum_{i=0}^{n-1}(y_i-\tilde{y}_i)^2, $$

-and the \( R^2 \) score function. If \( \tilde{\hat{y}}_i \) is the predicted +and the \( R^2 \) score function. If \( \tilde{\boldsymbol{y}}_i \) is the predicted value of the \( i-th \) sample and \( y_i \) is the corresponding true value, then the score \( R^2 \) is defined as $$ -R^2(\hat{y}, \tilde{\hat{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, +R^2(\boldsymbol{y}, \tilde{\boldsymbol{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, $$

-where we have defined the mean value of \( \hat{y} \) as +where we have defined the mean value of \( \boldsymbol{y} \) as $$ \bar{y} = \frac{1}{n} \sum_{i=0}^{n - 1} y_i. @@ -406,7 +406,7 @@ Note also that when you calculate the bias, in all applications you don't know t The aim here is to write your own code for another widely popular resampling technique, the so-called cross-validation method. Again, before you start with cross-validation approach, you should scale your -data. +data if you think this is needed.

Implement the \( k \)-fold cross-validation algorithm (write your own diff --git a/doc/Projects/2021/Project1/html/Project1.html b/doc/Projects/2021/Project1/html/Project1.html index 545df6ab9..405e39681 100644 --- a/doc/Projects/2021/Project1/html/Project1.html +++ b/doc/Projects/2021/Project1/html/Project1.html @@ -126,7 +126,7 @@ MathJax.Hub.Config({

University of Oslo, Norway

-

Sep 14, 2021

+

Oct 4, 2021


Regression analysis and resampling methods

@@ -240,21 +240,21 @@ analysis using polynomials in \( x \) and \( y \) up to fifth order. Find the confidence intervals of the parameters (estimators) \( \beta \) by computing their variances, evaluate the Mean Squared error (MSE) -$$ MSE(\hat{y},\hat{\tilde{y}}) = \frac{1}{n} +$$ MSE(\boldsymbol{y},\tilde{\boldsymbol{y}}) = \frac{1}{n} \sum_{i=0}^{n-1}(y_i-\tilde{y}_i)^2, $$

-and the \( R^2 \) score function. If \( \tilde{\hat{y}}_i \) is the predicted +and the \( R^2 \) score function. If \( \tilde{\boldsymbol{y}}_i \) is the predicted value of the \( i-th \) sample and \( y_i \) is the corresponding true value, then the score \( R^2 \) is defined as $$ -R^2(\hat{y}, \tilde{\hat{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, +R^2(\boldsymbol{y}, \tilde{\boldsymbol{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, $$

-where we have defined the mean value of \( \hat{y} \) as +where we have defined the mean value of \( \boldsymbol{y} \) as $$ \bar{y} = \frac{1}{n} \sum_{i=0}^{n - 1} y_i. @@ -362,7 +362,7 @@ Note also that when you calculate the bias, in all applications you don't know t The aim here is to write your own code for another widely popular resampling technique, the so-called cross-validation method. Again, before you start with cross-validation approach, you should scale your -data. +data if you think this is needed.

Implement the \( k \)-fold cross-validation algorithm (write your own diff --git a/doc/Projects/2021/Project1/ipynb/Project1.ipynb b/doc/Projects/2021/Project1/ipynb/Project1.ipynb index b32c902df..7bd009df3 100644 --- a/doc/Projects/2021/Project1/ipynb/Project1.ipynb +++ b/doc/Projects/2021/Project1/ipynb/Project1.ipynb @@ -10,7 +10,7 @@ " \n", "**[Data Analysis and Machine Learning FYS-STK3155/FYS4155](http://www.uio.no/studier/emner/matnat/fys/FYS3155/index-eng.html)**, University of Oslo, Norway\n", "\n", - "Date: **Sep 14, 2021**\n", + "Date: **Oct 4, 2021**\n", "\n", "## Regression analysis and resampling methods\n", "\n", @@ -149,7 +149,7 @@ "metadata": {}, "source": [ "$$\n", - "MSE(\\hat{y},\\hat{\\tilde{y}}) = \\frac{1}{n}\n", + "MSE(\\boldsymbol{y},\\tilde{\\boldsymbol{y}}) = \\frac{1}{n}\n", "\\sum_{i=0}^{n-1}(y_i-\\tilde{y}_i)^2,\n", "$$" ] @@ -158,7 +158,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "and the $R^2$ score function. If $\\tilde{\\hat{y}}_i$ is the predicted\n", + "and the $R^2$ score function. If $\\tilde{\\boldsymbol{y}}_i$ is the predicted\n", "value of the $i-th$ sample and $y_i$ is the corresponding true value,\n", "then the score $R^2$ is defined as" ] @@ -168,7 +168,7 @@ "metadata": {}, "source": [ "$$\n", - "R^2(\\hat{y}, \\tilde{\\hat{y}}) = 1 - \\frac{\\sum_{i=0}^{n - 1} (y_i - \\tilde{y}_i)^2}{\\sum_{i=0}^{n - 1} (y_i - \\bar{y})^2},\n", + "R^2(\\boldsymbol{y}, \\tilde{\\boldsymbol{y}}) = 1 - \\frac{\\sum_{i=0}^{n - 1} (y_i - \\tilde{y}_i)^2}{\\sum_{i=0}^{n - 1} (y_i - \\bar{y})^2},\n", "$$" ] }, @@ -176,7 +176,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "where we have defined the mean value of $\\hat{y}$ as" + "where we have defined the mean value of $\\boldsymbol{y}$ as" ] }, { @@ -200,6 +200,7 @@ "sure you have installed it). This function is called\n", "$train\\_test\\_split$. **You should present a critical discussion of why and how you have scaled or not scaled the data**.\n", "\n", + "\n", "It is normal in essentially all Machine Learning studies to split the\n", "data in a training set and a test set (eventually also an additional\n", "validation set). There\n", @@ -311,7 +312,7 @@ "The aim here is to write your own code for another widely popular\n", "resampling technique, the so-called cross-validation method. Again,\n", "before you start with cross-validation approach, you should scale your\n", - "data.\n", + "data if you think this is needed.\n", "\n", "Implement the $k$-fold cross-validation algorithm (write your own\n", "code) and evaluate again the MSE function resulting\n", diff --git a/doc/Projects/2021/Project1/ipynb/ipynb-Project1-src.tar.gz b/doc/Projects/2021/Project1/ipynb/ipynb-Project1-src.tar.gz index 3d71f4bd32d835ba2a28e126ba945a04bb4aae70..36579028d51d51acbd4d115db348eab96ebf6d5a 100644 GIT binary patch literal 193 zcmV;y06za8iwFRLOj}_91MSbv3c@f92k@Qu6nTQt&aOKPdhj3&@dY~9xlY&2wgdO} z?gR9sco`z}cli?%LUP!yH~Vem?k-piA%rsqW2QWrlEia8p)>``Xv{g|F`+={Dv8qo z$Z{vWbk+$ooYGXa)K=B?r71Y900;m8|1eis literal 193 zcmV;y06za8iwFRq20>u}1MSbv3W7io2XN0m#XNz`>Z<1;4;=!DUSQ2N*K*f(SID=| z52#boMIzYW<0@RKEh=muFp vskoV%p!uyAngf#qu(A|ZD9NsVr`1`r)&%~q-*FtralZ5boCzrF00;m8;V4?= diff --git a/doc/Projects/2021/Project1/pdf/Project1.p.tex b/doc/Projects/2021/Project1/pdf/Project1.p.tex index a544ac850..2654c2293 100644 --- a/doc/Projects/2021/Project1/pdf/Project1.p.tex +++ b/doc/Projects/2021/Project1/pdf/Project1.p.tex @@ -132,7 +132,7 @@ Project 1 on Machine Learning, deadline October 4, 2021 % --- begin date --- \begin{center} -Sep 14, 2021 +Oct 4, 2021 \end{center} % --- end date --- @@ -242,19 +242,19 @@ analysis using polynomials in $x$ and $y$ up to fifth order. Find the \href{{https://en.wikipedia.org/wiki/Confidence_interval}}{confidence intervals} of the parameters (estimators) $\beta$ by computing their variances, evaluate the Mean Squared error (MSE) -\[ MSE(\hat{y},\hat{\tilde{y}}) = \frac{1}{n} +\[ MSE(\bm{y},\tilde{\bm{y}}) = \frac{1}{n} \sum_{i=0}^{n-1}(y_i-\tilde{y}_i)^2, \] -and the $R^2$ score function. If $\tilde{\hat{y}}_i$ is the predicted +and the $R^2$ score function. If $\tilde{\bm{y}}_i$ is the predicted value of the $i-th$ sample and $y_i$ is the corresponding true value, then the score $R^2$ is defined as \[ -R^2(\hat{y}, \tilde{\hat{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, +R^2(\bm{y}, \tilde{\bm{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, \] -where we have defined the mean value of $\hat{y}$ as +where we have defined the mean value of $\bm{y}$ as \[ \bar{y} = \frac{1}{n} \sum_{i=0}^{n - 1} y_i. @@ -268,6 +268,7 @@ splitting training data provided by the library \textbf{Scikit-Learn} (make sure you have installed it). This function is called $train\_test\_split$. \textbf{You should present a critical discussion of why and how you have scaled or not scaled the data}. + It is normal in essentially all Machine Learning studies to split the data in a training set and a test set (eventually also an additional validation set). There @@ -345,7 +346,7 @@ Note also that when you calculate the bias, in all applications you don't know t The aim here is to write your own code for another widely popular resampling technique, the so-called cross-validation method. Again, before you start with cross-validation approach, you should scale your -data. +data if you think this is needed. Implement the $k$-fold cross-validation algorithm (write your own code) and evaluate again the MSE function resulting diff --git a/doc/Projects/2021/Project1/pdf/Project1.pdf b/doc/Projects/2021/Project1/pdf/Project1.pdf index 647a3f09f0b43b360bc865ca440f0ec9ab818857..356eefbf96f4811d1cb75d2cc9efd22d8f637a8d 100644 GIT binary patch delta 32384 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 aM$WFD&SvH?%&Z)&Y>Y5uWMT^9F#ikaUWgq4 delta 32442 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 AT>t<8 diff --git a/doc/Projects/2021/Project1/pdf/Project1.tex b/doc/Projects/2021/Project1/pdf/Project1.tex index 5d8fbc2d9..63a62b2e2 100644 --- a/doc/Projects/2021/Project1/pdf/Project1.tex +++ b/doc/Projects/2021/Project1/pdf/Project1.tex @@ -102,7 +102,7 @@ Project 1 on Machine Learning, deadline October 4, 2021 % --- begin date --- \begin{center} -Sep 14, 2021 +Oct 4, 2021 \end{center} % --- end date --- @@ -212,19 +212,19 @@ analysis using polynomials in $x$ and $y$ up to fifth order. Find the \href{{https://en.wikipedia.org/wiki/Confidence_interval}}{confidence intervals} of the parameters (estimators) $\beta$ by computing their variances, evaluate the Mean Squared error (MSE) -\[ MSE(\hat{y},\hat{\tilde{y}}) = \frac{1}{n} +\[ MSE(\bm{y},\tilde{\bm{y}}) = \frac{1}{n} \sum_{i=0}^{n-1}(y_i-\tilde{y}_i)^2, \] -and the $R^2$ score function. If $\tilde{\hat{y}}_i$ is the predicted +and the $R^2$ score function. If $\tilde{\bm{y}}_i$ is the predicted value of the $i-th$ sample and $y_i$ is the corresponding true value, then the score $R^2$ is defined as \[ -R^2(\hat{y}, \tilde{\hat{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, +R^2(\bm{y}, \tilde{\bm{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, \] -where we have defined the mean value of $\hat{y}$ as +where we have defined the mean value of $\bm{y}$ as \[ \bar{y} = \frac{1}{n} \sum_{i=0}^{n - 1} y_i. @@ -238,6 +238,7 @@ splitting training data provided by the library \textbf{Scikit-Learn} (make sure you have installed it). This function is called $train\_test\_split$. \textbf{You should present a critical discussion of why and how you have scaled or not scaled the data}. + It is normal in essentially all Machine Learning studies to split the data in a training set and a test set (eventually also an additional validation set). There @@ -315,7 +316,7 @@ Note also that when you calculate the bias, in all applications you don't know t The aim here is to write your own code for another widely popular resampling technique, the so-called cross-validation method. Again, before you start with cross-validation approach, you should scale your -data. +data if you think this is needed. Implement the $k$-fold cross-validation algorithm (write your own code) and evaluate again the MSE function resulting diff --git a/doc/src/Projects/2021/Project1/Project1.do.txt b/doc/src/Projects/2021/Project1/Project1.do.txt index 5c161ece0..4d373f296 100644 --- a/doc/src/Projects/2021/Project1/Project1.do.txt +++ b/doc/src/Projects/2021/Project1/Project1.do.txt @@ -111,22 +111,22 @@ analysis using polynomials in $x$ and $y$ up to fifth order. Find the variances, evaluate the Mean Squared error (MSE) !bt -\[ MSE(\hat{y},\hat{\tilde{y}}) = \frac{1}{n} +\[ MSE(\bm{y},\tilde{\bm{y}}) = \frac{1}{n} \sum_{i=0}^{n-1}(y_i-\tilde{y}_i)^2, \] !et -and the $R^2$ score function. If $\tilde{\hat{y}}_i$ is the predicted +and the $R^2$ score function. If $\tilde{\bm{y}}_i$ is the predicted value of the $i-th$ sample and $y_i$ is the corresponding true value, then the score $R^2$ is defined as !bt \[ -R^2(\hat{y}, \tilde{\hat{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, +R^2(\bm{y}, \tilde{\bm{y}}) = 1 - \frac{\sum_{i=0}^{n - 1} (y_i - \tilde{y}_i)^2}{\sum_{i=0}^{n - 1} (y_i - \bar{y})^2}, \] !et -where we have defined the mean value of $\hat{y}$ as +where we have defined the mean value of $\bm{y}$ as !bt \[ @@ -142,6 +142,7 @@ splitting training data provided by the library _Scikit-Learn_ (make sure you have installed it). This function is called $train\_test\_split$. _You should present a critical discussion of why and how you have scaled or not scaled the data_. + It is normal in essentially all Machine Learning studies to split the data in a training set and a test set (eventually also an additional validation set). There @@ -228,7 +229,7 @@ Note also that when you calculate the bias, in all applications you don't know t The aim here is to write your own code for another widely popular resampling technique, the so-called cross-validation method. Again, before you start with cross-validation approach, you should scale your -data. +data if you think this is needed. Implement the $k$-fold cross-validation algorithm (write your own code) and evaluate again the MSE function resulting diff --git a/doc/src/week37/programs/LinearReg.py b/doc/src/week37/programs/LinearReg.py new file mode 100644 index 000000000..be84e77f5 --- /dev/null +++ b/doc/src/week37/programs/LinearReg.py @@ -0,0 +1,270 @@ +import numpy as np +from sklearn import linear_model, metrics +from sklearn.model_selection import train_test_split + +class linregOwn: + """ + A class of linear regressions. Perform ordinarly least squares (OLS) and Ridge regression manually. Lasso + is performed using scikit-learn functionality. + """ + def __init__(self, method = 'ols'): + """ + Constructor + + Determines the method used in the fitting + + Arguments: + method: string type. Accepts either 'ols', 'ridge' or 'lasso'. + + """ + self.method = method + self.yHat = None + self.X = None + self.y = None + self.beta = None + + self._MSE = None + self._R2 = None + self._betaVariance = None + self.lambda_ = None + + def fit(self, X_train, y_train, lambda_ = 0): + """ + Performs the fit of OLS, Ridge or Lasso, depending on the argument provided initially. + + Arguments: + X_train: Covariate matrix of the train data set, i.e. design matrix of + the shape m x p where m is the number of rows and p is the number of columns + (i.e. p is the complexity parameter). + y_train: Outcome variable, 1D numpy array + lambda_: float type. Shrinkage parameter for ridge and lasso methods. The higher value, higher shrinkage. + lambda_ is set to 0 for the OLS regression + + """ + self.X_train = X_train + self.y_train = y_train + self.lambda_ = lambda_ + if self.method == 'ols': + self._olsFit(X_train, y_train) + if self.method == 'ridge': + self._ridgeFit(X_train, y_train, lambda_) + if self.method == 'lasso': + self._lassoFitSKL(X_train, y_train, lambda_) + return self.beta + + def _olsFit(self, X_train, y_train): + """ + Performs the ordinary least squares (OLS) fit on the provided data using singular value decomposition(SVD). + + + Arguments: + + X_train: Covariate matrix of the train data set, i.e. design matrix of + the shape m x p where m is the number of rows and p is the number of columns + (i.e. p is the complexity parameter). + y_train: Outcome variable, 1D numpy array + + Returns: + beta : numpy.array + The beta parameters from the performed fit + """ + self.X_train = X_train + self.y_test = y_train + U, S, VT = np.linalg.svd(self.X_train, full_matrices=True) + S_inverse = np.zeros(shape=self.X_train.shape) + ##S is a vector, with shape of the number of columns + S_inverse[:S.shape[0], :S.shape[0]] = np.diag(1/S) + self.beta = np.dot(VT.T, np.dot(S_inverse.T, np.dot(U.T, self.y_train))) + #self.beta = np.linalg.inv(np.dot(X.T,X)).dot(X.T, y) + + def _ridgeFit(self, X_train, y_train, lambda_): + """ + Performs the ridge regression fit + + Arguments: + X_train: Covariate matrix of the train data set, design matrix of + the shape m x p (m_train_rows, p_columns). + y_train: Outcome variable, 1D numpy array, dimension m x 1 + lambda_: Integer type. The shrinkage parameter + + Returns: + beta : numpy.array + The beta parameters from the performed fit + """ + self.X_train = X_train + self.y_train = y_train + self.lambda_ = lambda_ + self.beta = np.dot(np.linalg.inv(np.dot(X_train.T,X_train) + self.lambda_ * np.eye(X_train.shape[1])), np.dot(X_train.T,y_train)) + + def _lassoFitSKL(self, X_train, y_train, lambda_): + """ + Performs lasso fit using scikit-learn functionality. + + Arguments: + X_train: Covariate matrix of the train data set, design matrix of + the shape m x p (m_train_datapoints, p_parameters). + y_train: Outcome variable, 1D numpy array, dimension m x 1 + lambda_: Integer type. The shrinkage parameter + + Returns: + self.beta : numpy.array + The beta parameters from the performed fit + """ + self.regression = linear_model.Lasso(fit_intercept=True, max_iter=1000000, alpha=self.lambda_) + self.regression.fit(X_train,y_train) + self.beta = self.regression.coef_ + self.beta[0] = self.regression.intercept_ + + def predict(self, X_test): + """ + Performs prediction of the fitted model on the provided test data set. + + Arguments: + X_test: Design matrix, covariate matrix, dimension k x p (k_test_rows, p_columns) + + Returns: self.yHat + numpy 1D array, prediction values of dimension k x p + """ + self.X_test = X_test + self._predictOwntest(X_test) + return self.yHat + + def _predictOwntest(self, X_test): + """ + Performs manual prediction of the given model on the train data. + """ + self.X_test = X_test + self.yHat = np.dot(self.X_test, self.beta) + + def MSE(self, y_test): + """ + Calculates the mean squared error (MSE) manually after the fit and prediction have been implemented. + + Arguments: + y_test: Outcome variable, 1D numpy array, dimension k x 1 (k_test_rows, 1_column) + + Returns: self._MSE + The mean squared error of the predicted model + """ + self.y_test = y_test + if self.yHat is None : + self._predictOwntest(X_test) + N = self.yHat.size + self._MSE = (np.sum((self.y_test - self.yHat)**2))/N + return self._MSE + + def R2(self, y_test): + """ + Calculates R2 score manually after the fit and prediction have been implemented. + + Arguments: + y_test: Outcome variable, 1D numpy array, dimension k x 1 (k_test_rows, 1_column) + + Returns: self._R2 + The R2 score of the predicted model + """ + self.y_test = y_test + if self.yHat is None: + self._predictOwntest(X_test) + yMean = (1.0 / self.y_test.size) * np.sum(self.y_test) + self._R2 = 1.0 - np.sum((self.y_test - self.yHat)**2) / np.sum((self.y_test - yMean)**2) + return self._R2 + + def CI(self, y_test): + """ + Calculates confidence intervals manually after the fit and prediction have been implemented. + + Arguments: + y_test: Outcome variable, 1D numpy array, dimension k x 1 (k_test_rows, 1_column) + + Returns: var, Lower, Upper + Variance, Lower and Upper bounds of the confidence intervals for the parameter self.beta + """ + self.y_test = y_test + if self.yHat is None: + self._predictOwntest(X_test) + sigma2 = np.sum(((self.y_test - self.yHat)**2))/(self.y_test.size - self.beta.size) + var = np.diag(np.linalg.inv(np.dot(self.X_test.T, self.X_test))) * sigma2 + Lower = self.beta - 1.96*np.sqrt(var) + Upper = self.beta + 1.96*np.sqrt(var) + return var, Lower, Upper + + + + + + ###Implementation through scikitlearn +class linregSKL: + def __init__(self, method = 'ols'): + """ + A class of linear regressions. Perform ordinarly least squares (OLS) and Ridge and Lasso + using scikit-learn functionality. + + """ + self.method = method + self.yHat = None + self.X = None + self.y = None + self.beta = None + + self._MSE = None + self._R2 = None + self._betaVariance = None + + + def fit(self, X_train, y_train, lambda_ = 0): + self.X_train = X_train + self.y_train = y_train + if self.method == 'ols': + self._olsSKLfit(X_train, y_train) + if self.method == 'ridge': + self._sklRidgeFit(X_train, y_train, lambda_) + if self.method == 'lasso': + self._SKLlassoFit(X_train, y_train, lambda_) + return self.beta + + def _olsSKLfit(self, X_train, y_train): + self.X_train = X_train + self.y_train = y_train + ##We already have standardized data from design matrix + self.ols = linear_model.LinearRegression().fit(self.X_train, self.y_train) + self.beta = self.ols.coef_ + self.beta[0] = self.ols.intercept_ + + def _SKLlassoFit(self, X_train, y_train, lambda_): + self.regression = linear_model.Lasso(fit_intercept=True, max_iter=100000, alpha=self.lambda_) + self.regression.fit(X_train,y_train) + self.beta = self.regression.coef_ + self.beta[0] = self.regression.intercept_ + + def _sklRidgeFit(self, X_train, y_train, lambda_): + self.regression = linear_model.Ridge(fit_intercept=True, alpha=self.lambda_) + self.regression.fit(X,y) + self.beta = self.regression.coef_ + self.beta[0] = self.regression.intercept_ + + def predict(self, X_test): + self.X_test = X_test + if self.method == 'ols': + self._sklPredict(X_test) + return self.yHat + + def _sklPredict(self, X_test): + self.X_test = X_test + ## Since our data contains 1-s, we should subtract intercept, since scikit learn additionally + ##generates the 1-s + self.yHat = self.ols.predict(self.X_test) - self.beta[0] + + def MSE(self, y_test): + self.y_test = y_test + if self.yHat is None : + self._sklPredict(X_test) + self._MSE = metrics.mean_squared_error(self.y_test, self.yHat) + return self._MSE + + def R2(self, y_test): + self.y_test = y_test + if self.yHat is None : + self._sklPredict() + self._R2 = metrics.r2_score(self.y_test, self.yHat) + return self._R2 \ No newline at end of file