added codes

This commit is contained in:
mhjensen
2019-11-17 22:22:03 +01:00
parent 3623cd187b
commit e8967bfd3f
6 changed files with 4773 additions and 0 deletions
+590
View File
@@ -0,0 +1,590 @@
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.ticker import LinearLocator, FormatStrFormatter
from matplotlib import cm
import numpy as np
from scipy import linalg
import matplotlib.pyplot as plt
import time
# Variance
def var(f_model):
n = np.size(f_model)
f_model_mean = np.sum(f_model)/n
#f_model_mean = np.mean(f_model)
return np.sum((f_model-f_model_mean)**2)/n
#================================================================================================================
# Bias
def bias(f_true,f_model):
n = np.size(f_model)
#f_model_mean = np.sum(f_model)/n
f_model_mean = np.mean(f_model)
return np.sum((f_true-f_model_mean)**2)/n
#================================================================================================================
# MSE
def MSE(f_true,f_model):
n = np.size(f_model)
return np.sum((f_true-f_model)**2)/n
#================================================================================================================
# Extra term
def extra_term(f_true,f_model):
n = np.size(f_model)
f_model_mean = np.mean(f_model)
return 2.0/n*np.sum((f_model_mean-f_true)*(f_model-f_model_mean))
#================================================================================================================
# SVD invert
def SVDinv(A):
''' Takes as input a numpy matrix A and returns inv(A) based on singular value decomposition (SVD).
SVD is numerically more stable (at least in our case) than the inversion algorithms provided by
numpy and scipy.linalg at the cost of being slower.
'''
U, s, VT = linalg.svd(A)
D = np.zeros((len(U),len(VT)))
for i in range(0,len(VT)):
D[i,i]=s[i]
UT = np.transpose(U); V = np.transpose(VT); invD = np.linalg.inv(D)
return np.matmul(V,np.matmul(invD,UT))
#================================================================================================================
# R2 score
def R2(x_true,x_predict):
n = np.size(x_true)
x_avg = np.sum(x_true)/n
enumerator = np.sum ((x_true-x_predict)**2)
denominator = np.sum((x_true-x_avg)**2)
return 1.0 - enumerator/denominator
#================================================================================================================
## Mean
#def mean(x):
# n = np.size(x)
# x_avg = np.sum(x)/n
# return x_avg
#================================================================================================================
# get sub-entries of matrix A
def get_subset(A,indices):
'''given an indexing set "indices", return the vector consisting of
entries A[i,j] where (i,j) is an entry in indices.'''
N = len(indices)
B = np.zeros(N)
for k in range(0,N):
i = indices[k][0]
j = indices[k][1]
B[k] = A[j,i]
return B
#============================================================================================================================
class k_cross_validation:
'''An k-cross validation object is initialized by passing to it data of the type linreg,
and a paritition of the data. The class function R2 calculates the mean R2 scores
of test and training data for the given model. The function MSE calculates the mean MSE, bias,
variance and error terms of the test data for the given model. These quantities are stored
as self variables.'''
def __init__(self, data, partition,*args):
self.data = data; self.partition = partition; self.args = args;
#f = data.f; X = data.X; z = data.z; correspondence = data.correspondence;
self.k = len(partition)
self.test_R2, self.test_var, self.test_bias, self.test_MSE, self.test_extra_terms = 0, 0, 0, 0, 0
self.train_R2 = 0
#self.train_var, self.train_bias, self.train_MSE, self.train_extra_terms = 0, 0, 0, 0
def R2(self):
data = self.data
f = data.f; X = data.X; z = data.z; correspondence = data.correspondence; partition = self.partition
k = self.k
args = self.args
test_R2, train_R2 = 0, 0
for i, test_data in enumerate(partition):
train_data = [x for j,x in enumerate(partition) if j!=i]
train_data = sum(train_data, [])
beta = data.get_beta(X[train_data],z[train_data],*args)
freg = data.model(beta)
test_data = [correspondence[j] for j in test_data]
train_data = [correspondence[j] for j in train_data]
# test errors:
ftest = get_subset(f,test_data); fregtest = get_subset(freg,test_data)
test_R2 += R2(ftest,fregtest)
#training errors:
ftrain = get_subset(f,train_data); fregtrain = get_subset(freg,train_data)
train_R2 += R2(ftrain,fregtrain)
# self variables
self.test_R2 = test_R2/k
self.train_R2 = train_R2/k
def MSE(self):
data = self.data
f = data.f; X = data.X; z = data.z; correspondence = data.correspondence; partition = self.partition
k = self.k
args = self.args
test_var, test_bias, test_MSE, test_extra_terms = 0, 0, 0, 0
#train_var, train_bias, train_MSE, train_extra_terms = 0, 0, 0, 0
for i, test_data in enumerate(partition):
train_data = [x for j,x in enumerate(partition) if j!=i]
train_data = sum(train_data, [])
beta = data.get_beta(X[train_data],z[train_data],*args)
freg = data.model(beta)
test_data = [correspondence[j] for j in test_data]
# train_data = [correspondence[j] for j in train_data]
# test errors:
ftest = get_subset(f,test_data); fregtest = get_subset(freg,test_data)
test_var += var(fregtest)
test_bias += bias(ftest,fregtest)
test_MSE += MSE(ftest,fregtest)
test_extra_terms += extra_term(ftest,fregtest)
##training errors:
#ftrain = get_subset(f,train_data); fregtrain = get_subset(freg,train_data)
#train_var += var(fregtrain)
#train_bias += bias(ftrain,fregtrain)
#train_MSE += MSE(ftrain,fregtrain)
#train_extra_terms += extra_term(ftrain,fregtrain)
# self variables
self.test_var = test_var/k
self.test_bias = test_bias/k
self.test_MSE = test_MSE/k
self.test_extra_terms = test_extra_terms/k
#self.train_var = train_var/k
#self.train_bias = train_bias/k
#self.train_MSE = train_MSE/k
#self.train_extra_terms = train_extra_terms/k
#================================================================================================================
class regdata:
def __init__(self, f, degree):
# initializing variables
m = len(f[0,:]); n = len(f); mn = m*n;
x = np.linspace(0, 1, m); y = np.linspace(0, 1, n); z = np.zeros(mn); xy = np.zeros((mn,2));
# initializing some self variables
self.f = f; self.degree = degree; self.xm, self.ym = np.meshgrid(x,y); self.n=n;self.m=m; self.mn = mn; self.correspondence = []
# Making a sequence xy containing the pairs (x_i,y_j) for i,j=0,...,n, and a sequence z with matching pairs z_ij = f(x_i, y_j)
counter = 0
for i in range(0,m):
for j in range(0,n):
z[counter]=f[j,i] #wtf
xy[counter,:] = [x[i],y[j]]
self.correspondence.append([i,j]) #Saves the 1-1 correspondence: {counter} <-> {(i,j)} for later
counter+=1
self.z = z
# Make X
number_basis_elts=int((degree+2)*(degree+1)/2) #(degree+1)th triangular number (number of basis elements for R[x,y] of degree <= degree)
X = np.zeros((mn,number_basis_elts))
powers = []
for i in range(0,mn):
counter = 0
for j in range(0,degree+1):
k = 0
while j+k <= degree:
xi = xy[i,0]
yi = xy[i,1]
X[i,counter]= (xi**j)*(yi**k)
powers.append([j , k])
k+=1
counter+=1
self.X = X
self.powers = powers
self.number_basis_elts = number_basis_elts
self.invXTX = linalg.inv(np.matmul(np.transpose(X),X))
# Regression
def get_reg(self, *args):
'''Returns the polynomial fit as a numpy array. If *args is empty the fit is based on an ordinary least square.
If *args contains a number LAMBDA, then the fit is found using Ridge for the given bias LAMBDA. If *args contains
two numbers LAMBDA and epsilon, then the fit is found using lasso. See the function " __get_beta" for more details.'''
X=self.X; z=self.z #relabeling self variables
beta = self.get_beta(X,z,*args) #obtaining beta
reg = self.model(beta) #obtaining model from coefficients beta
return reg
# Get beta (given X and z)
def get_beta(self, X, z,*args):
'''Returns coefficients for a given beta as a numpy array, found using either ordinary least square,
Ridge or Lasso regression depending on the arguments. If *args is empty, then beta is found using
ordinary least square. If *args contains a number it will be treated as a bias LAMBDA for a Ridge regression.
If *args contains two numbers, then the first will count as a LAMBDA and the second as a tolerance epsilon.
In this case beta is found using a shooting algorithm that runs until it converges up to the set tolerance.
'''
XT = np.transpose(X)
beta = np.matmul(XT,X)
if len(args) >= 1: #Ridge parameter LAMBDA
LAMBDA = args[0]
beta[np.diag_indices_from(beta)]+=LAMBDA
beta = SVDinv(beta)
beta = np.matmul(beta,XT)
beta = np.matmul(beta,z)
#Shooting algorithm for Lasso
if len(args)>=2:
epsilon = args[1]
D = self.number_basis_elts
ints = np.arange(0,D,1)
beta_old = 0.0
while np.linalg.norm(beta-beta_old)>=epsilon:
beta_old = np.copy(beta)
for j in range(0,D):
aj = 2*np.sum(X[:,j]**2)
no_j = ints[np.arange(D)!=j]
cj = 2*np.sum(np.multiply(X[:,j],(z-np.matmul(X[:,no_j],beta[no_j]))))
if cj<-LAMBDA:
beta[j]=(cj+LAMBDA)/aj
elif cj > LAMBDA:
beta[j]=(cj-LAMBDA)/aj
else:
beta[j]=0.0
return beta
# Get model given beta
def model(self,beta):
'''Returns heigh values based on the coefficients beta as a matrix
that matches the grid xm, ym. The degree of the polynomial equals self.degree.
'''
xm = self.xm; ym = self.ym; degree = self.degree #relabeling self variables
s=0
counter = 0
# loop that adds terms of the form beta*x^j*y^k such that j+k<=5
for j in range(0,degree + 1):
k = 0
while j+k <= degree:
s+= beta[counter]*(xm**j)*(ym**k)
counter +=1
k+=1
return s
def get_data_partition(self,k):
''' Creates a random partition of k (almost) equally sized parts of the array
{1,2,...,mn}. This can be used to make training/testing data.
'''
mn = self.mn; correspondence = self.correspondence
indices = np.arange(mn)
indices_shuffle = np.arange(mn)
np.random.shuffle(indices_shuffle)
partition = []
for step in range(0,k):
part = list(indices_shuffle[step:mn:k])
#part = [correspondence[i] for i in part]
partition.append(part)
return partition
def bootstrap_step(self, samplesize, *args):
'''Finds and returns the coefficient that determines a model (ols, Ridge or Lasso),
depending on args*.
'''
mn = self.mn; X = self.X; z = self.z; #relabeling self variables
integers = np.random.randint(low=0, high=mn-1, size=samplesize)
znew = z[integers]
Xnew = X[integers,:]
betanew = self.get_beta(Xnew,znew,*args)
return betanew
# Variance/ covariance matrix
def var_covar_matrix(self,reg):
''' Returns the variance/covariance matrix for beta based on the given data.
This matrix is derived from a statistical viewpoint, where one assumes beta to
have a normal distribution.
'''
p = self.number_basis_elts; invXTX = self.invXTX; N = self.mn; f = self.f # Relabeling self variables
sigma2=1.0/(N-p-1)*np.sum((f-reg)*(f-reg))
return sigma2*invXTX # OBS! Based on matrix inversion. Inaccurate for N,p>>0.
#================================================================================================================
def plot_3D(f,plottitle):
''' Simple function to create 3d plot of the given data f,
with plotitle.
'''
m = len(f[0,:]); n = len(f);
x = np.linspace(0, 1, m)
y = np.linspace(0, 1, n);
xm, ym = np.meshgrid(x,y)
# Plot f
fig = plt.figure()
ax = fig.gca(projection="3d")
surf = ax.plot_surface(xm, ym, f, cmap=cm.coolwarm, linewidth=0, antialiased=False)
# Customize the z axis.
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter("%.02f"))
ax.text2D(0.05, 0.95, plottitle, transform=ax.transAxes)
ax.view_init(30, 60)
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show(block=False)
#================================================================================================================
def numerical_error(data,LAMBDA):
'''Rough numerical analysis of matrix inversions for this problem. Comparison of error and time usage
of SVD (singular values decomposition) for matrix inversion against scipy.linalg inversion algorithm.
Printing results to terminal.
'''
return_items = []
degree = data.degree; m = data.m; n = data.n
# Study numerical error and time for SVD
print("Polynomial fit of FrankeFunction in x, y of degree ", degree," with grid size ", (m,n)," analysis:")
print("")
X = data.X; XT = np.transpose(X); XTX = np.matmul(XT,X) #Obtaining XTX
start_time = time.time() # start meassuring time
inv_XTX = linalg.inv(XTX) # inversion using scipi.linalg
end_time = time.time()
print("Inverting XTX without SVD", "--- %s seconds ---" % (end_time - start_time)); return_items.append(end_time - start_time)
inv_XTX_ = np.copy(inv_XTX) # storing inversion of XTX for later
start_time = time.time()
inv_XTX = SVDinv(XTX)
end_time = time.time()
print("Inverting XTX with SVD", "--- %s seconds ---" % (end_time - start_time)); return_items.append(end_time - start_time)
print(' ')
I_approx_ = np.matmul(inv_XTX_,XTX); # approximate I (no SVD)
I = np.identity(len(I_approx_)); # obtaining analytical I
output = np.linalg.norm(I_approx_-I)
print("|(X^TX)^-1(X^TX)-I| = ",output, " (no SVD)"); return_items.append(output)
I_approx = np.matmul(inv_XTX,XTX) # approximate I (SVD)
output = np.linalg.norm(I_approx-I)
print("|(X^TX)^-1(X^TX)-I| = ",np.linalg.norm(I_approx-I), " (SVD)"); return_items.append(output)
XTX[np.diag_indices_from(XTX)]+=LAMBDA
inv_XTX = linalg.inv(XTX)
I_approx_ = np.matmul(inv_XTX,XTX) # approximate I (no SVD)
output = np.linalg.norm(I_approx_-I)
print("|(X^TX + I LAMBDA)^-1(X^TX + I LAMBDA)-I| = ",output , ", LAMBDA = ", LAMBDA, " (no SVD)"); return_items.append(output)
inv_XTX = SVDinv(XTX)
I_approx = np.matmul(inv_XTX,XTX)
output = np.linalg.norm(I_approx-I)
print("|(X^TX + I LAMBDA)^-1(X^TX + I LAMBDA)-I| = ",output, ", LAMBDA = ", LAMBDA, " (SVD)"); return_items.append(output)
print(' ')
return return_items
#================================================================================================================
def plot_R2_scores(data,Nstart,Nstop,name, epsilon = 0.001):
''' This function makes a plot of the R2 scores vs Lambda of the different regression methods,
for a given dataset.'''
degree = data.degree; f = data.f # obtaining class data
N = Nstop-Nstart # number of lambdas
lambdas = np.zeros(N)
R2_ols = np.zeros(N)
R2_Ridge = np.zeros(N)
R2_Lasso = np.zeros(N)
for i in range(0,N):
LAMBDA = 10**(Nstart+i)
lambdas[i]=LAMBDA
R2_ols[i]=R2(f, data.get_reg())
R2_Ridge[i]=R2(f, data.get_reg(LAMBDA))
R2_Lasso[i]=R2(f, data.get_reg(LAMBDA,epsilon))
print("Completed lambda: ", LAMBDA, " Completion: {:.1%}".format(float(i)/(N-1)))
plotitle = '$R^2$ score of degree {} polynomial fit on {}'.format(degree,name)
plt.figure()
plt.plot(np.log10(lambdas),R2_ols)
plt.plot(np.log10(lambdas),R2_Ridge)
plt.plot(np.log10(lambdas),R2_Lasso,'--')
plt.axis([Nstart, N+Nstart-1, 0, 1])
plt.xlabel('log $\lambda$')
plt.ylabel('$R^2$ score')
plt.legend(('Ordinary least square','Ridge','Lasso'))
plt.title(plotitle)
plt.grid(True)
plt.show(block=False)
#================================================================================================================
def plot_R2_scores_k_cross_validation(data,Nstart,Nstop,k,name, epsilon = 0.001):
''' This function makes a plot of the R2 scores vs LAMBDA of the best iteration from a k-fold cross validation on
the data set from the given data. Best in the sense that the fit had the highest R2 score on testing data. The same
partition of the data set is used for each lambda, and each time we select the best training data on which we base the model.
See "k_cross_validation" for more details.'''
degree = data.degree; f = data.f # obtaining class data
N = Nstop-Nstart # number of lambdas
# Comparing R2 scores, regression with fixed degree, variable LAMBDA
lambdas = np.zeros(N)
partition = data.get_data_partition(k)
kval = k_cross_validation(data,partition)
kval.R2()
R2_Lasso_test_data = np.zeros(N)
R2_Lasso_training_data = np.zeros(N)
R2_Ridge_test_data = np.zeros(N)
R2_Ridge_training_data = np.zeros(N)
# OLS R2 score
R2score_ols_test, R2score_ols_train = kval.test_R2, kval.train_R2
R2_ols_test_data = np.ones(N)*R2score_ols_test
R2_ols_training_data = np.ones(N)*R2score_ols_train
for i in range(0,N):
LAMBDA = 10**(Nstart+i)
lambdas[i]=LAMBDA
kval = k_cross_validation(data,partition,LAMBDA)
kval.R2()
# Ridge R2 score
R2score_ridge_test, R2score_ridge_train = kval.test_R2, kval.train_R2
R2_Ridge_test_data[i] = R2score_ridge_test
R2_Ridge_training_data[i] = R2score_ridge_train
kval = k_cross_validation(data,partition,LAMBDA,epsilon)
kval.R2()
# Lasso R2 score
R2score_lasso_test, R2score_lasso_train = kval.test_R2, kval.train_R2
R2_Lasso_test_data[i] = R2score_lasso_test
R2_Lasso_training_data[i] = R2score_lasso_train
print("Completed lambda: ", LAMBDA, " Completion: {:.1%}".format(float(i)/(N-1)))
plotitle = '$R^2$ scores of degree {} polynomial fit on {}, $k=${}'.format(degree,name,k)
plt.figure()
plt.plot(np.log10(lambdas),R2_ols_test_data)
plt.plot(np.log10(lambdas),R2_ols_training_data,'--')
plt.plot(np.log10(lambdas),R2_Ridge_test_data)
plt.plot(np.log10(lambdas),R2_Ridge_training_data,'--')
plt.plot(np.log10(lambdas),R2_Lasso_test_data)
plt.plot(np.log10(lambdas),R2_Lasso_training_data,'--')
plt.axis([Nstart, Nstart+N-2, 0, 1])
plt.xlabel('log $\lambda$')
plt.ylabel('$R^2$ score')
if (np.amax(R2_ols_test_data)> 0 and np.amax(R2_ols_training_data)> 0):
plt.legend(('OLS: test data', 'OLS: training data','Ridge: test data', 'Ridge: training data','Lasso: test data', 'Lasso: training data'))
elif (np.amax(R2_ols_test_data)<= 0 and np.amax(R2_ols_training_data)> 0):
plt.legend(('OLS: test data (negative)', 'OLS: training data','Ridge: test data', 'Ridge: training data','Lasso: test data', 'Lasso: training data'))
elif (np.amax(R2_ols_test_data)> 0 and np.amax(R2_ols_training_data)<= 0):
plt.legend(('OLS: test data', 'OLS: training data (negative)','Ridge: test data', 'Ridge: training data','Lasso: test data', 'Lasso: training data'))
elif (np.amax(R2_ols_test_data)<= 0 and np.amax(R2_ols_training_data)<= 0):
plt.legend(('OLS: test data (negative)', 'OLS: training data (negative)','Ridge: test data', 'Ridge: training data','Lasso: test data', 'Lasso: training data'))
plt.title(plotitle)
plt.grid(True)
plt.show(block=False)
#return ols_best, ridge_best, lasso_best
#================================================================================================================
def plot_R2_complexity(degstart,degend,degstep,f,name, LAMBDA = 0.00001, epsilon = 0.001):
''' Comparing R2 scores, regression with fixed LAMBDA, variable degree as well as variance and Bias
Plotting the result.
'''
degrees = np.arange(degstart,degend+1,degstep)
N = len(degrees)
R2_ols, R2_Ridge, R2_Lasso = np.zeros(N), np.zeros(N), np.zeros(N)
for i, degree in enumerate(degrees):
data_f = regdata(f,degree)
R2_ols[i]=R2(f, data_f.get_reg())
R2_Ridge[i]=R2(f, data_f.get_reg(LAMBDA))
R2_Lasso[i]=R2(f, data_f.get_reg(LAMBDA,epsilon))
print("Completed degree: ", degree, " Completion: {:.1%}".format(float(i)/(N-1)))
plotitle = '$R^2$ score of polynomial fit on {} with $\lambda=${}'.format(name,LAMBDA)
plt.figure()
plt.plot(degrees,R2_ols)
plt.plot(degrees,R2_Ridge)
plt.plot(degrees,R2_Lasso,'--')
plt.xlabel('degree of fitting polynomial')
plt.ylabel('$R^2$ score')
plt.axis([degstart,degend, 0, 1])
plt.legend(('Ordinary least square','Ridge','Lasso'))
plt.title(plotitle)
plt.grid(True)
plt.show(block=False)
#================================================================================================================
def plot_MSE_variance(degstart, degend, degstep, f, LAMBDA = 0.01, epsilon = 0.001, k=10):
# Comparing MSE, bias, variance and additional terms as function of complexity.
degrees = np.arange(degstart,degend+1,degstep)
N = len(degrees)
data = regdata(f,5)
fvar = np.zeros(N); fbias = np.zeros(N); fMSE = np.zeros(N); fextra_terms = np.zeros(N)
# function for plotting
def makeplot(methodname, *args, partition = None):
print(methodname)
for i, degree in enumerate(degrees):
data = regdata(f,degree)
if partition == None:
freg = data.get_reg(*args)
fvar[i], fbias[i], fMSE[i], fextra_terms[i] = var(freg), bias(f,freg), MSE(f,freg), extra_term(f,freg)
else:
kval = k_cross_validation(data, partition, *args)
kval.MSE()
fvar[i] = kval.test_var
fbias[i] = kval.test_bias
fMSE[i] = kval.test_MSE
fextra_terms[i] =kval.test_extra_terms
#fvar[i], fbias[i], fMSE[i], fextra_terms[i], train_var, train_bias, train_MSE, train_extra_terms
print("Completed degree: ", degree, " Completion: {:.1%}".format(float(degree-degstart)/(degend-degstart)))
plt.figure()
plt.plot(degrees, fvar)
plt.plot(degrees, fbias)
plt.plot(degrees, fMSE,'--')
plt.plot(degrees, fextra_terms)
plt.xlabel('degree')
plt.ylabel('Variance, bias, and MSE')
plt.legend(('Variance','Bias','MSE','Additional term'))
plt.grid(True)
plt.show(block=False)
#It is a good idea to comment out the plots that you dont need
## Ordinary least square plot
#makeplot("Ordinary least squares")
#plt.title("Error of ordinary least squares")
## Ridge plot
#makeplot("Ridge regression",LAMBDA)
#plt.title("Error of Ridge regression, $\lambda=${}".format(LAMBDA))
## Lasso plot
#makeplot("Lasso regression",LAMBDA,epsilon)
#plt.title("Error of lasso regression, $\lambda=${}".format(LAMBDA))
# k-cross validation
partition_ = data.get_data_partition(k)
# Ordinary least square plot
# makeplot("Ordinary least squares {}-fold cross validation".format(k), partition = partition_)
# plt.title("Error OLS using {}-fold cross validation".format(k))
## Ridge plot
#makeplot("Ridge regression {}-fold cross validation".format(k), LAMBDA, partition=partition_)
#plt.title("Error Ridge using {}-fold cross validation, $\lambda=${}".format(k,LAMBDA))
# Lasso plot
makeplot("Lasso regression {}-fold cross validation".format(k), LAMBDA, epsilon, partition_)
plt.title("Error Lasso using {}-fold cross validation, $\lambda=${}".format(k,LAMBDA))
+51
View File
@@ -0,0 +1,51 @@
# Importing functions from folder with common functions for project 1
import sys
sys.path.append('../functions')
from functions import *
from regression import OLS
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import Ridge as OLS_sklearn
# Making meshgrid of datapoints and compute Franke's function
n = 3
N = 1000
x = np.sort(np.random.uniform(0, 1, N))
y = np.sort(np.random.uniform(0, 1, N))
x_mesh_, y_mesh_ = np.meshgrid(x,y)
z = FrankeFunction(x_mesh_, y_mesh_)
# Add noise
z_noise = z + np.random.normal(scale = 1, size = (N,N))
# Perform regression
X = create_X(x_mesh_, y_mesh_, n=n)
model = OLS()
beta = model.fit(X, z_noise, ret=True)
# Perform regression with Scikit learn using ridge with alpha = 0
# Because of inconsistencies in linear_regression
model2 = OLS_sklearn(alpha = 0, fit_intercept = False)
model2.fit(X, np.ravel(z_noise))
# Print beta-values of the two models
print('============================')
print('Calculated beta-values:', beta)
print('Scikit-learn beta-values:', model2.coef_)
# Create best-fit matrix for plotting
x_r = np.linspace(0,1,N)
y_r = np.linspace(0,1,N)
x_mesh, y_mesh = np.meshgrid(x,y)
X_r = create_X(x_mesh, y_mesh, n=n)
# Predict
z_reg = (model.predict(X_r)).reshape((N,N))
plot_surface(x_mesh, y_mesh, z_reg, "OLS regression")
print('============================ \n')
print("MSE: %.5f" %MSE(z, z_reg))
print("R2_Score: %.5f" %R2_Score(z, z_reg))
File diff suppressed because one or more lines are too long
+188
View File
@@ -0,0 +1,188 @@
import sys
import numpy as np
from matplotlib import cm
"""
A file for all common functions used in project 1
"""
def FrankeFunction(x,y):
term1 = 0.75*np.exp(-(0.25*(9*x-2)**2) - 0.25*((9*y-2)**2))
term2 = 0.75*np.exp(-((9*x+1)**2)/49.0 - 0.1*(9*y+1))
term3 = 0.5*np.exp(-(9*x-7)**2/4.0 - 0.25*((9*y-3)**2))
term4 = -0.2*np.exp(-(9*x-4)**2 - (9*y-7)**2)
return term1 + term2 + term3 + term4
def MSE(y, y_tilde):
"""
Function for computing mean squared error.
Input is y: analytical solution, y_tilde: computed solution.
"""
return np.sum((y-y_tilde)**2)/y.size
def R2_Score(y, y_tilde):
"""
Function for computing the R2 score.
Input is y: analytical solution, y_tilde: computed solution.
"""
return 1 - np.sum((y[:-2]-y_tilde[:-2])**2)/np.sum((y[:-2]-np.average(y))**2)
def create_X(x, y, n = 5):
"""
Function for creating a X-matrix with rows [1, x, y, x^2, xy, xy^2 , etc.]
Input is x and y mesh or raveled mesh, keyword agruments n is the degree of the polinomial you want to fit.
"""
if len(x.shape) > 1:
x = np.ravel(x)
y = np.ravel(y)
N = len(x)
l = int((n+1)*(n+2)/2) # Number of elements in beta
X = np.ones((N,l))
for i in range(1,n+1):
q = int((i)*(i+1)/2)
for k in range(i+1):
X[:,q+k] = (x**(i-k))*(y**k)
return X
def plot_surface(x, y, z, title = "", show = False, cmap=cm.coolwarm, figsize = None):
"""
Function to plot surfaces of z, given an x and y.
Input: x, y, z (NxN'Modeler' matrices), and a title (string)
"""
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.ticker import LinearLocator, FormatStrFormatter
if figsize:
fig = plt.figure(figsize = figsize)
else:
fig = plt.figure()
ax = fig.gca(projection='3d')
# Plot the surface.of the best fit
surf = ax.plot_surface(x, y, z, cmap=cmap,
linewidth=0, antialiased=False)
# Customize the z axis automatically
z_min = np.min(z)
z_min = z_min*1.01 if z_min < 0 else z_min*.99
z_max = np.max(z)
z_max = z_max*1.01 if z_max > 0 else z_max*.99
ax.set_zlim(z_min, z_max)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
ax.view_init(azim=20,elev=45)
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
ax.set_title(title)
if show:
plt.show()
return fig, ax ,surf
def train_test_data(x_,y_,z_,i):
"""
Takes in x,y and z arrays, and a array with random indesies iself.
returns learning arrays for x, y and z with (N-len(i)) dimetions
and test data with length (len(i))
"""
x_learn=np.delete(x_,i)
y_learn=np.delete(y_,i)
z_learn=np.delete(z_,i)
x_test=np.take(x_,i)
y_test=np.take(y_,i)
z_test=np.take(z_,i)
return x_learn,y_learn,z_learn,x_test,y_test,z_test
def K_fold(x,y,z,k,alpha,model,m=5, ret_std = False):
"""Function to who calculate the average MSE and R2 using k-fold.
Takes in x,y and z varibles for a dataset, k number of folds, alpha and which method beta shall use. (OLS,Ridge or Lasso)
Returns average MSE and average R2"""
print(m)
if len(x.shape) > 1:
x = np.ravel(x)
y = np.ravel(y)
z = np.ravel(z)
n=len(x)
n_k=int(n/k)
if n_k*k!=n:
print("k needs to be a multiple of ", n,k)
i=np.arange(n)
np.random.shuffle(i)
MSE_=0
R2_=0
Variance_=0
Bias_=0
betas = np.zeros((k,int((m+1)*(m+2)/2)))
for t in range(k):
x_,y_,z_,x_test,y_test,z_test=train_test_data(x,y,z,i[t*n_k:(t+1)*n_k])
X= create_X(x_,y_,n=m)
X_test= create_X(x_test,y_test,n=m)
model.fit(X,z_)
betas[t] = model.beta
z_predict=model.predict(X_test)
MSE_+=MSE(z_test,z_predict)
R2_+=R2_Score(z_test,z_predict)
Bias_+=bias(z_test,z_predict)
Variance_+=variance(z_predict)
return (MSE_/k, R2_/k, Bias_/k, Variance_/k, np.std(betas, axis = 0), np.mean(betas, axis = 0))
def variance(y_tilde):
"""
Calculates the variance of the predicted values y_tilde.
"""
return np.sum((y_tilde - np.mean(y_tilde))**2)/np.size(y_tilde)
def bias(y, y_tilde):
"""
Calculates the bias of the predicted values y_tilde compared to
the actual data y.
"""
return np.sum((y - np.mean(y_tilde))**2)/np.size(y_tilde)
def update_progress(job_title, progress):
"""
Shows the progress of an for-loop.
"""
length = 20 # modify this to change the length
block = int(round(length*progress))
msg = "\r{0}: [{1}] {2}%".format(job_title, "#"*block + "-"*(length-block), round(progress*100, 2))
if progress >= 1: msg += " DONE\r\n"
sys.stdout.write(msg)
sys.stdout.flush()
def savefigure(name, figure = "gcf"):
"""
Function for saving figures as a .tex-file for easier integration with latex.
"""
try:
from matplotlib2tikz import save as tikz_save
tikz_save(name.replace(" ", "_") + ".tex", figure = figure, figureheight='\\figureheight', figurewidth='\\figurewidth')
except ImportError:
print("Please install matplotlib2tikz to save figure as a .tex-file.")
import matplotlib.pyplot as plt
if figure == "gcf":
plt.savefig(name+".pdf")
else:
fig.savefig(name+".pdf")
@@ -0,0 +1,81 @@
import scipy as scipy
import scipy.special as special
import numpy as np
import itertools as it
from pandas import *
import matplotlib.pylab as plt
from scipy.integrate import ode
import time
def unique_rows(a):
a = np.ascontiguousarray(a)
unique_a = np.unique(a.view([('', a.dtype)]*a.shape[1]))
return unique_a.view(a.dtype).reshape((unique_a.shape[0], a.shape[1]))
def hamiltonian(n_pairs,n_basis,delta,g):
"""
n_pairs - Number of electron pairs
n_basis - Number of spacial basis states
"""
n_SD = int(special.binom(n_basis,n_pairs))
print("n = ", n_SD)
H_mat = np.zeros((n_SD,n_SD))
S = stateMatrix(n_pairs,n_basis)
for row in range(n_SD):
bra = S[row,:]
for col in range(n_SD):
ket = S[col,:]
if np.sum(np.equal(bra,ket)) == bra.shape:
H_mat[row,col] += 2*delta*np.sum(bra - 1) - 0.5*g*n_pairs
if n_pairs - np.intersect1d(bra,ket).shape[0] == 1:
H_mat[row,col] += -0.5*g
return(H_mat)
def stateMatrix(n_pairs,n_basis):
L = []
states = range(1,n_basis+1)
for perm in it.permutations(states,n_pairs):
L.append(perm)
L = np.array(L)
L.sort(axis=1)
L = unique_rows(L)
return(L)
g = 0.5
H = hamiltonian(4,8,1,g)
print("Hamiltonian calculated")
A = H
x = np.zeros(A.shape[0])
x[0] = 1
def f(t,x):
return(-(x.T@x)*A@x + (x.T@A@x)*x)
r = ode(f)
r.set_initial_value(x,0) #langsos algorithm
t1=10
dt=0.1
start = time.time()
while r.successful() and r.t < t1:
r.integrate(r.t+dt)
end = time.time()
print("RNN eig: ",r.y.T@A@r.y/(r.y.T@r.y))
print("calculation time with RNN: ", end - start)
start = time.time()
eigvals, eigvecs = np.linalg.eig(H)
end = time.time()
print("numpy eig: ",np.sort(eigvals))
print("calculation time with numpy eig: ", end - start)
File diff suppressed because it is too large Load Diff