Machine learning
Spring 2026
The definition of “machine learning” is inchoate and is often context specific. We use the term to describe (i) a diverse collection of high-dimensional models for statistical prediction, combined with (ii) so-called “regularization” methods for model selection and mitigation of overfit and (iii) efficient algorithms for searching among a vast number of potential model specifications. (Gu et al. 2020)
Challenges (Israel, Kelly, Moskowitz, 2019)
And…
Familiarize yourself with the paper “Empirical Asset Pricing via Machine Learning” by Gu et al. (2020)
comparative analysis of machine learning methods for the canonical problem of measuring asset risk premiums
“We demonstrate large economic gains to investors using machine learning forecasts, in some cases doubling the performance of leading regression-based strategies from the literature.”
Your task:
\[E_t\left(r_{i, t+1}\right) = g^\star(x_{i, t}) \overset{??}{=} \beta'x_{i,t} \]
Biased estimators?
where \(\varepsilon\) is the vector of residuals and \(\sigma_\varepsilon^2\) is the variance of the error term
OLS in a prediction context
Assume the model \[ y = f(x) + \varepsilon, \quad \varepsilon \sim (0, \sigma_\varepsilon^2) \]
\(\hat\beta^\text{ols}\) has a host of well-known properties (Gauss-Markov)
But: Can we choose \(\hat f(x)\) to fit future observations well?
MSPE depends on the model as follows: \[\begin{aligned} E(\hat{\varepsilon}^2)&=E((y-\hat{f}(\textbf{x}))^2)=E((f(\textbf{x})+\varepsilon-\hat{f}(\textbf{x}))^2)\\ &= \underbrace{E((f(\textbf{x})-\hat{f}(\textbf{x}))^2)}_{\text{total quadratic error}}+\underbrace{E(\varepsilon^2)}_{\text{irreducible error}} \\ &= E\left(\hat{f}(\textbf{x})^2\right)+E\left(f(\textbf{x})^2\right)-2E\left(f(\textbf{x})\hat{f}(\textbf{x})\right)+\sigma_\varepsilon^2\\ &=E\left(\hat{f}(\textbf{x})^2\right)+f(\textbf{x})^2-2f(\textbf{x})E\left(\hat{f}(\textbf{x})\right)+\sigma_\varepsilon^2\\ &=\underbrace{\text{Var}\left(\hat{f}(\textbf{x})\right)}_{\text{variance of model}}+ \underbrace{E\left((f(\textbf{x})-\hat{f}(\textbf{x}))\right)^2}_{\text{squared bias}} +\sigma_\varepsilon^2 \end{aligned}\]
A biased estimator with small variance may have a lower MSPE than an unbiased estimator
\[ \begin{aligned} \hat\beta^\text{ridge} &= \left(D + \lambda I\right)^{-1}X'y\\ &= \left(D + \lambda I\right)^{-1}DD^{-1}X'y\\ &= \left(D\left(I + \lambda D^{-1}\right)\right)^{-1}D\hat\beta^\text{ols}\\ &= \left(I + \lambda D^{-1}\right)^{-1}D^{-1}D\hat\beta^\text{ols} = \left(I + \lambda D^{-1}\right)^{-1}\hat\beta^\text{ols} \end{aligned} \] - \(\hat\beta^\text{ridge}\) is biased because \(E(\hat\beta^\text{ridge} - \beta) \neq 0\) for \(\lambda\neq0\) - But at the same time (under homoscedastic error terms) \[\text{Var}(\hat\beta^\text{ridge}) = \sigma_\varepsilon^2 \left(D + \lambda I\right)^{-1}X'X\left(D + \lambda I\right)^{-1}\] - You can show that \(\text{Var}(\hat\beta^\text{ridge}) \leq \text{Var}(\hat\beta^\text{ols})\) - Trade-off between bias and variance of the estimator!
Data for case study: macroeconomic predictors from the paper “A Comprehensive Look at The Empirical Performance of Equity Premium Prediction” (Goyal, 2008)
Monthly variables that have been suggested as good predictors for the equity premium: Dividend Price Ratio, Earnings Price Ratio, Stock Variance, Net Equity Expansion, Treasury Bill rate, and inflation
Monthly Fama-French 3-factor returns (market, small-minus-big, and high-minus-low book-to-market valuation sorts)
Monthly q-factor returns from Hou, Xue, and Zhang (2015)
Monthly portfolio returns from 10 different industries according to the definition from Kenneth French’s homepage
The regression specification is \[\underbrace{r_{i, t}}_{\text{industry } i} = \gamma_{i, 0} + \gamma_{i, 1} \underbrace{x_{t-1}}_{\text{macro} \times \text{factor}} + \varepsilon_t\]
Package glmnet fits generalized linear models via penalized maximum likelihood
Exercise: Implement Ridge on your own before using glmnet
\[\hat\beta^\text{Lasso} = \arg\min_\beta \left(Y - X\beta\right)'\left(Y - X\beta\right)\text{ s.t. } \sum\limits_{k=1}^K|\beta_k| < c(\lambda).\]
glmnet)glmnetRidge can be interpreted as a Bayesian posterior mean with a Normal prior on \(\beta\)
Lasso can be interpreted as a Bayesian posterior mean with a Laplace prior on \(\beta\) \[ \beta^\text{Ridge} \propto \exp\left(-\frac{\lambda\beta^2}{\sigma}\right) \qquad \beta^\text{Lasso} \propto \frac{\lambda}{2\sigma}\exp\left(-\frac{\lambda|\beta|}{\sigma}\right) \]
Next step: Elastic net (Zhou & Hastie, 2005) combines \(L_1\) and \(L_2\) penalization
Encourages a grouping effect, where strongly correlated predictors tend to be in or out of the model together. \[\hat\beta^\text{EN} = \arg\min_\beta \left(Y - X\beta\right)'\left(Y - X\beta\right) + \lambda(1-\rho)\sum\limits_{k=1}^K|\beta_k| +\frac{1}{2}\lambda\rho\sum\limits_{k=1}^K\beta_k^2\]
Goal: find an algorithm that produces predictors \(\hat{y}\) for an outcome \(y\) that minimizes the mean squared prediction error: \[ \mbox{MSPE} = \mbox{E}\left( \frac{1}{N}\sum_{i=1}^N (\hat{y}_i - y_i)^2 \right) \]
We can only estimate the MSPE: \[ \hat{\mbox{MSPE}} = \frac{1}{N}\sum_{i=1}^N \left(\hat{y}_i - y_i\right)^2 \]
Cross-validation is a technique that permits us to alleviate both these problems
Think of the true MSPE as the average of many apparent errors obtained by applying the algorithm to \(B\) new random samples of the data, none of them used to train the algorithm \[ \frac{1}{B} \sum_{b=1}^B \frac{1}{N}\sum_{i=1}^N \left(\hat{y}_i^b - y_i^b\right)^2 \]
Idea: randomly generate smaller datasets that are not used for training and instead used to estimate the true error
Recall: The goal is to choose hyperparameters \(\lambda\) to obtain the smallest MSPE
Fit the model in the training set, then compute the apparent error on the independent set \[ \hat{\mbox{MSPE}}_b(\lambda) = \frac{1}{M}\sum_{i=1}^M \left(\hat{y}_i^b(\lambda) - y_i^b\right)^2 \]
Take \(K\) samples to reduce the variance of the estimate
In K-cross validation, we randomly split the observations into \(K\) non-overlapping sets:
Repeat the calculation above for each of these sets \(b=1,\dots,K\) and obtain \(\hat{\mbox{MSPE}}_1(\lambda),\dots, \hat{\mbox{MSPE}}_K(\lambda)\) and compute the average \[ \hat{\mbox{MSPE}}(\lambda) = \frac{1}{K} \sum_{b=1}^K \hat{\mbox{MSPE}}_b(\lambda) \]
final step: select the \(\lambda\) that minimizes the MSPE
Considerations for selecting \(K\)
Two alternatives that respect the time ordering:
tidymodels example later): time_series_cv() and TimeSeriesSplit() handle this automaticallyconditional on a level of complexity, pick the best in-sample loss-minimizing function \[ \min \sum\limits_{i=1}^nL\left(f(x_i),y_i\right)\text{ over } f\in\mathcal{F}\text{ subject to } R(f) \leq c \]
estimate the optimal level of complexity \(c\) using empirical tuning (cross-validation)
tidymodels and scikit-learnflowchart LR A(Recipe) --> C(Model) C --> D(Tuning) F(Data splits) --> D D --> E(Selection)
recipe and transformers)workflow and pipeline)recipe)mutate is key: recipes defer transformations until fitting, which avoids data leakagerec <- recipe(ret_excess ~ ., data = training(split)) |>
step_rm(date) |> # remove date variable
step_interact(terms = ~ contains("factor"):contains("macro")) |> # interaction terms
step_normalize(all_predictors()) |> # scale to unit standard deviation
step_center(ret_excess , skip = TRUE) # demean variablesrecipe) stepstidymodelslm_model contains the definition of our model with all required information.set_engine("glmnet") indicates the API character of the tidymodels workflow: Under the hood, the package glmnet is doing the heavy lifting, while linear_reg provides a unified framework to collect the inputsmixture to get Ridge, or replace linear_reg with a neural network) without changing the rest of the workflowworkflow ends with combining everything necessary for the (serious) data science workflow: a recipe and a model. So now we are ready to use fit.tidymodels: Define model and embed in pipelineFit method to compute parameter estimatesdata_folds = TimeSeriesSplit(
n_splits=n_splits,
test_size=assessment_months,
max_train_size=initial_years * length_of_year
)
params = {
"regressor__alpha": alphas,
"regressor__l1_ratio": (0.0, 0.5, 1)
}
finder = GridSearchCV(
lm_pipeline,
param_grid=params,
scoring="neg_root_mean_squared_error",
cv=data_folds
)
finder = finder.fit(
data_manufacturing, data_manufacturing.get("ret_excess")
)We partition the predictor space into \(J\) non-overlapping regions, \(R_1, R_2, \ldots, R_J\)
For any predictor \(x\) that falls within region \(R_j\) we estimate \(f(x)\) with the average of the training observations \(y_i\) for which the associated predictor \(x_i\) is also in \(R_j\)
Once we select a partition \(\mathbf{x}\) to split to create the new partitions, we find a predictor \(j\) and value \(s\) that define two new partitions, which we will call \(R_1(j,s)\) and \(R_2(j,s)\), that split our observations in the current partition by asking if \(x_j\) is bigger than \(s\): \[ R_1(j,s) = \{\mathbf{x} \mid x_j < s\} \mbox{ and } R_2(j,s) = \{\mathbf{x} \mid x_j \geq s\} \]
To pick \(j\) and \(s\), we find the pair that minimizes the residual sum of square (RSS): \[ \sum_{i:\, x_i \in R_1(j,s)} (y_i - \hat{y}_{R_1})^2 + \sum_{i:\, x_i \in R_2(j,s)} (y_i - \hat{y}_{R_2})^2 \]
Note: We do not scale by \(\#R_k(j, s)\)
Discussion: What are the hyperparameter decisions?
Growing a forest
Three major takeaways from the biological neuron
Each neuron applies a nonlinear “activation function” \(f\) to its aggregated signal before sending its output to the next layer \[x_k^l = f\left(\theta^k_{0} + \sum\limits_{j = 1}^{N ^l}z_j\theta_{l,j}^k\right)\]
Easiest case: \(f(x) = \alpha + \beta x\) resembles linear regression
Typical activation functions are sigmoid (\(f(x) = (1+e^{-x})^{-1}\)) or ReLu (\(f(x) = max(x, 0)\))
Plenty of decisions
\[\Delta \vec{w} = r\cdot\left(\frac{\partial P}{\partial w_0},\frac{\partial P}{\partial w_1}, ... ,\frac{\partial P}{\partial w_q}\right)\]
torch provides a helpful interface to create and train a deep neural network| Architecture | Strength | Financial application |
|---|---|---|
| Recurrent networks (LSTM, GRU) | Model sequential dependencies | Return prediction with time-varying parameters |
| Autoencoders | Unsupervised latent factor discovery | Latent asset pricing factors (Gu, Kelly & Xiu 2021) |
| Convolutional networks (CNN) | Exploit local spatial structure | Price chart pattern recognition (Jiang et al. 2022) |
| Transformers / Attention | Capture long-range dependencies, process text | Earnings calls, SEC filings, news sentiment |
| Generative adversarial networks (GAN) | Learn the data-generating process | SDF estimation (Chen, Pelger & Zhu 2024) |
Hyperparameter tuning - Consult the Online Appendix
| Method | Idea | Scope |
|---|---|---|
| Permutation importance | Shuffle one predictor, measure \(R^2\) drop | Any model |
| Partial dependence plots | Vary one predictor, average predictions over all others | Any model |
| Shapley values (SHAP) | Game-theoretic attribution of each predictor’s marginal contribution | Any model |
| Lasso / Elastic Net | Built-in: zero coefficients = excluded predictors | Linear models |
| Approach | Example | Key idea |
|---|---|---|
| Pure prediction | Gu et al. (2020) | Minimize MSPE for \(E(r_{i,t+1})\) |
| SDF estimation | Chen, Pelger & Zhu (2024) | Learn the stochastic discount factor \(m_{t+1}\) such that \(E(m_{t+1} r_{i,t+1}) = 0\) |
| Latent factors | Kelly, Pruitt & Su (2019); Gu, Kelly & Xiu (2021) | Estimate factor loadings as functions of characteristics |
Recall: The value of a call option for a non-dividend-paying underlying stock in terms of the Black–Scholes parameters is: \[ \begin{aligned} C(S_t, t) &= N(d_1)S_t - N(d_2)Ke^{-r(T - t)} \\ d_1 &= \frac{1}{\sigma\sqrt{T - t}}\left[\ln\left(\frac{S_t}{K}\right) + \left(r + \frac{\sigma^2}{2}\right)(T - t)\right] \\ d_2 &= d_1 - \sigma\sqrt{T - t} \\ \end{aligned} \]
\(V\) is the price of the option as a function of stock price \(S\) and time \(t\), \(r\) is the risk-free interest rate, and \(\sigma\) is the volatility of the stock. \(N(\cdot)\) is the standard normal cumulative distribution function.
Can machine learning methods learn the Black-Scholes equation after observing different specifications and corresponding prices?
Start with simulated data
T), risk-free rate (r), volatility (sigma), the strike price (K), and current stock price (S)