794 KiB
794 KiB
In [1]:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import seaborn as sns
import scipy.linalg as scl
from sklearn.model_selection import train_test_split
import sklearn.linear_model as skl
import tqdm
%matplotlib inline
sns.set(color_codes=True)
cmap_args=dict(vmin=-1., vmax=1., cmap='seismic')In [2]:
L = 40
n = int(1e4)
spins = np.random.choice([-1, 1], size=(n, L))
J = 1.0
energies = np.zeros(n)
for i in range(n):
energies[i] = - J * np.dot(spins[i], np.roll(spins[i], 1))In [3]:
X = np.zeros((n, L ** 2))
for i in range(n):
X[i] = np.outer(spins[i], spins[i]).ravel()In [4]:
y = energies
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.96)
X_train_own = np.concatenate(
(np.ones(len(X_train))[:, np.newaxis], X_train),
axis=1
)
X_test_own = np.concatenate(
(np.ones(len(X_test))[:, np.newaxis], X_test),
axis=1
)In [5]:
def get_ols_weights_naive(x: np.ndarray, y: np.ndarray) -> np.ndarray:
return scl.inv(x.T @ x) @ (x.T @ y)In [6]:
omega = get_ols_weights_naive(X_train_own, y_train)[0;31m---------------------------------------------------------------------------[0m
[0;31mLinAlgError[0m Traceback (most recent call last)
[0;32m<ipython-input-6-a21f2381e9a7>[0m in [0;36m<module>[0;34m()[0m
[0;32m----> 1[0;31m [0momega[0m [0;34m=[0m [0mget_ols_weights_naive[0m[0;34m([0m[0mX_train_own[0m[0;34m,[0m [0my_train[0m[0;34m)[0m[0;34m[0m[0m
[0m
[0;32m<ipython-input-5-92b155609649>[0m in [0;36mget_ols_weights_naive[0;34m(x, y)[0m
[1;32m 1[0m [0;32mdef[0m [0mget_ols_weights_naive[0m[0;34m([0m[0mx[0m[0;34m:[0m [0mnp[0m[0;34m.[0m[0mndarray[0m[0;34m,[0m [0my[0m[0;34m:[0m [0mnp[0m[0;34m.[0m[0mndarray[0m[0;34m)[0m [0;34m->[0m [0mnp[0m[0;34m.[0m[0mndarray[0m[0;34m:[0m[0;34m[0m[0m
[0;32m----> 2[0;31m [0;32mreturn[0m [0mscl[0m[0;34m.[0m[0minv[0m[0;34m([0m[0mx[0m[0;34m.[0m[0mT[0m [0;34m@[0m [0mx[0m[0;34m)[0m [0;34m@[0m [0;34m([0m[0mx[0m[0;34m.[0m[0mT[0m [0;34m@[0m [0my[0m[0;34m)[0m[0;34m[0m[0m
[0m
[0;32m/Users/Schoyen/anaconda3/lib/python3.6/site-packages/scipy/linalg/basic.py[0m in [0;36minv[0;34m(a, overwrite_a, check_finite)[0m
[1;32m 817[0m [0minv_a[0m[0;34m,[0m [0minfo[0m [0;34m=[0m [0mgetri[0m[0;34m([0m[0mlu[0m[0;34m,[0m [0mpiv[0m[0;34m,[0m [0mlwork[0m[0;34m=[0m[0mlwork[0m[0;34m,[0m [0moverwrite_lu[0m[0;34m=[0m[0;36m1[0m[0;34m)[0m[0;34m[0m[0m
[1;32m 818[0m [0;32mif[0m [0minfo[0m [0;34m>[0m [0;36m0[0m[0;34m:[0m[0;34m[0m[0m
[0;32m--> 819[0;31m [0;32mraise[0m [0mLinAlgError[0m[0;34m([0m[0;34m"singular matrix"[0m[0;34m)[0m[0;34m[0m[0m
[0m[1;32m 820[0m [0;32mif[0m [0minfo[0m [0;34m<[0m [0;36m0[0m[0;34m:[0m[0;34m[0m[0m
[1;32m 821[0m raise ValueError('illegal value in %d-th argument of internal '
[0;31mLinAlgError[0m: singular matrixIn [7]:
def get_ols_weights(x: np.ndarray, y: np.ndarray) -> np.ndarray:
u, s, v = scl.svd(x)
return v.T @ scl.pinv(scl.diagsvd(s, u.shape[0], v.shape[0])) @ u.T @ yIn [8]:
omega = get_ols_weights(X_train_own,y_train)In [9]:
clf = skl.LinearRegression().fit(X_train, y_train)In [10]:
J_own = omega[1:].reshape(L, L)
J_sk = clf.coef_.reshape(L, L)In [11]:
fig = plt.figure(figsize=(20, 14))
im = plt.imshow(J_own, **cmap_args)
plt.title("Home-made OLS", fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
cb = fig.colorbar(im)
cb.ax.set_yticklabels(cb.ax.get_yticklabels(), fontsize=18)
fig = plt.figure(figsize=(20, 14))
im = plt.imshow(J_sk, **cmap_args)
plt.title("LinearRegression from Scikit-learn", fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
cb = fig.colorbar(im)
cb.ax.set_yticklabels(cb.ax.get_yticklabels(), fontsize=18)
plt.show()In [12]:
def get_ridge_weights(x: np.ndarray, y: np.ndarray, _lambda: float) -> np.ndarray:
return x.T @ y @ scl.inv(
x.T @ x + np.eye(x.shape[1], x.shape[1]) * _lambda
)In [13]:
_lambda = 0.1In [14]:
omega_ridge = get_ridge_weights(X_train_own, y_train, np.array([_lambda]))In [15]:
clf_ridge = skl.Ridge(alpha=_lambda).fit(X_train, y_train)In [16]:
J_ridge_own = omega_ridge[1:].reshape(L, L)
J_ridge_sk = clf_ridge.coef_.reshape(L, L)In [17]:
fig = plt.figure(figsize=(20, 14))
im = plt.imshow(J_ridge_own, **cmap_args)
plt.title("Home-made ridge regression", fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
cb = fig.colorbar(im)
cb.ax.set_yticklabels(cb.ax.get_yticklabels(), fontsize=18)
fig = plt.figure(figsize=(20, 14))
im = plt.imshow(J_ridge_sk, **cmap_args)
plt.title("Ridge from Scikit-learn", fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
cb = fig.colorbar(im)
cb.ax.set_yticklabels(cb.ax.get_yticklabels(), fontsize=18)
plt.show()In [18]:
clf_lasso = skl.Lasso(alpha=_lambda).fit(X_train, y_train)
J_lasso_sk = clf_lasso.coef_.reshape(L, L)In [19]:
fig = plt.figure(figsize=(20, 14))
im = plt.imshow(J_lasso_sk, **cmap_args)
plt.title("Lasso from Scikit-learn", fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
cb = fig.colorbar(im)
cb.ax.set_yticklabels(cb.ax.get_yticklabels(), fontsize=18)
plt.show()In [20]:
def r_squared(y, y_hat):
return 1 - np.sum((y - y_hat) ** 2) / np.sum((y - np.mean(y_hat)) ** 2)In [21]:
y_hat = clf.predict(X_test)
r_test = r_squared(y_test, y_hat)
sk_r_test = clf.score(X_test, y_test)
assert abs(r_test - sk_r_test) < 1e-2In [22]:
lambdas = np.logspace(-4, 5, 10)
train_errors = {
"ols_own": np.zeros(lambdas.size),
"ols_sk": np.zeros(lambdas.size),
"ridge_own": np.zeros(lambdas.size),
"ridge_sk": np.zeros(lambdas.size),
"lasso_sk": np.zeros(lambdas.size)
}
test_errors = {
"ols_own": np.zeros(lambdas.size),
"ols_sk": np.zeros(lambdas.size),
"ridge_own": np.zeros(lambdas.size),
"ridge_sk": np.zeros(lambdas.size),
"lasso_sk": np.zeros(lambdas.size)
}
plot_counter = 1
fig = plt.figure(figsize=(32, 54))
for i, _lambda in enumerate(tqdm.tqdm(lambdas)):
omega = get_ols_weights(X_train_own, y_train)
y_hat_train = X_train_own @ omega
y_hat_test = X_test_own @ omega
train_errors["ols_own"][i] = r_squared(y_train, y_hat_train)
test_errors["ols_own"][i] = r_squared(y_test, y_hat_test)
plt.subplot(10, 5, plot_counter)
plt.imshow(omega[1:].reshape(L, L), **cmap_args)
plt.title("Home made OLS")
plot_counter += 1
omega = get_ridge_weights(X_train_own, y_train, _lambda)
y_hat_train = X_train_own @ omega
y_hat_test = X_test_own @ omega
train_errors["ridge_own"][i] = r_squared(y_train, y_hat_train)
test_errors["ridge_own"][i] = r_squared(y_test, y_hat_test)
plt.subplot(10, 5, plot_counter)
plt.imshow(omega[1:].reshape(L, L), **cmap_args)
plt.title(r"Home made ridge, $\lambda = %.4f$" % _lambda)
plot_counter += 1
for key, method in zip(
["ols_sk", "ridge_sk", "lasso_sk"],
[skl.LinearRegression(), skl.Ridge(alpha=_lambda), skl.Lasso(alpha=_lambda)]
):
method = method.fit(X_train, y_train)
train_errors[key][i] = method.score(X_train, y_train)
test_errors[key][i] = method.score(X_test, y_test)
omega = method.coef_.reshape(L, L)
plt.subplot(10, 5, plot_counter)
plt.imshow(omega, **cmap_args)
plt.title(r"%s, $\lambda = %.4f$" % (key, _lambda))
plot_counter += 1
plt.show()0%| | 0/10 [00:00<?, ?it/s]/Users/Schoyen/anaconda3/lib/python3.6/site-packages/sklearn/linear_model/coordinate_descent.py:491: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Fitting data with very small alpha may cause precision problems. ConvergenceWarning) 100%|██████████| 10/10 [00:19<00:00, 1.91s/it]
In [23]:
fig = plt.figure(figsize=(20, 14))
colors = {
"ols_own": "b",
"ridge_own": "g",
"ols_sk": "r",
"ridge_sk": "y",
"lasso_sk": "c"
}
for key in train_errors:
plt.semilogx(
lambdas,
train_errors[key],
colors[key],
label="Train {0}".format(key),
linewidth=4.0
)
for key in test_errors:
plt.semilogx(
lambdas,
test_errors[key],
colors[key] + "--",
label="Test {0}".format(key),
linewidth=4.0
)
#plt.semilogx(lambdas, train_errors["ols_own"], label="Train (OLS own)")
#plt.semilogx(lambdas, test_errors["ols_own"], label="Test (OLS own)")
plt.legend(loc="best", fontsize=18)
plt.xlabel(r"$\lambda$", fontsize=18)
plt.ylabel(r"$R^2$", fontsize=18)
plt.tick_params(labelsize=18)
plt.show()