Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Poojan ml patch 1 #32

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions basis_function_approximation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
## This includes implementation of approximation of polynomial and trigonometric functions using basis functions in C++.

Both are interactive programs where user can specify the corresponding functions or use default polynomial/trigonometric functions for the analysis.


[poly_function_fit](https://github.com/Poojan-ml/Algorithms/blob/Poojan-ml-patch-1/basis_function_approximation/poly_function_fit.cpp) approximates a user given polynomial by using polynomial basis function.

**How do this work?**

In the implementation , a choice is being given to user to give any polynomial as input and we generate **200** random data points(**_x_**) and evaluate the
value of user specified polynomial on those points(**_y_**). And using the polynomial basis function, coefficients of the polynomial are computed using the least square regression on polynomial basis function φ.


**How to compile this?**

`g++ poly_function_fit.cpp basis_functions.cpp matrix_functions.cpp`


[trig_function_fit](https://github.com/Poojan-ml/Algorithms/blob/Poojan-ml-patch-1/basis_function_approximation/trig_function_fit.cpp) approximates a user given trigonometric using fourier basis function.

**How do this work?**

In the implementation , a choice is being given to user to give Trigonometric function as input and we generate **500** random data points(**_x_**) and evaluate the
value of user specified Trigonometric function on those points(**_y_**). And using the fourier basis function, coefficients of the trigonometric terms are computed using the least square regression on Fourier basis function φ.

**How to compile this?**

`g++ trig_function_fit.cpp basis_functions.cpp matrix_functions.cpp`

Both of these work very well and almost(slight difference due to the noise) approximates the real target function with **_least_** mean square error.

Here are the snaps of sample examples for both.

![](https://github.com/Poojan-ml/Algorithms/blob/Poojan-ml-patch-1/basis_function_approximation/poly_snap.PNG?raw=true)

![](https://github.com/Poojan-ml/Algorithms/blob/Poojan-ml-patch-1/basis_function_approximation/trigo_snap.PNG?raw=true)



109 changes: 109 additions & 0 deletions basis_function_approximation/basis_functions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include<bits/stdc++.h>
#include "basis_functions.h"
using namespace std;
#define PI 3.14159265
vector<double> polynomial_basis(double x,int n)
{
/*
Computes the polynomial basis function and returns a vector comprised of monomials upto degree (n-1)
Φ(x) = [x^(n-1),x^(n-2),...,x,1]

Args:
x - 1-dimensional data point(Scalar)
n - degree of polynomial - (Scalar)

Returns:
Polynomial Basis function - (n) dimensional vector
*/
vector<double> basis(n, 0);
double q = 1;
for(int i = 0; i < n; i++)
{
basis[n - 1 - i] = q;
q *= (x);
}
return basis;
}
vector<double> rbf_basis(double x,vector<double>&myu, double sigma)
{
/*
Compute the RBF basis function
Φ(x) = [exp(-||x-μ_1||^2/(2*σ^2)),exp(-||x-μ_2||^2/(2*σ^2)),..,exp(-||x-μ_n||^2/(2*σ^2))]

Args:
x - 1-dimensional data point
myu - a list of n different myus (n-dimensional vector)
sigma - the sigma parameter of gaussian function (scalar)

Returns:
RBF Basis function - (n) dimensional vector
*/
if(sigma==0)
{
throw runtime_error("sigma can't be zero");
}
int n = myu.size();
double dif,factor=((-2)*sigma*sigma);
vector<double> basis(n);
for(int i = 0; i < n; i++)
{
dif = (x - myu[i]);
basis[i] = exp((dif * dif)/factor);
}
return basis;
}

double sigmoid(double x)
{
//Returns the value of the sigmoid function on x.
return 1/(1+exp(-x));
}
vector<double> sigmoid_basis(double x,vector<double>&myu, double sigma)
{
/*
Computes the sigmoid basis function
Φ(x) = [sigmoid((x-μ_1)/σ),sigmoid((x-μ_2)/σ),...sigmoid((x-μ_n)/σ)]

Args:
x - 1-dimensional data point
myu - a list of n different myus (n-dimensional vector)
sigma - the sigma parameter of sigmoid function (scalar)
Returns:
Sigmoid Basis function - (n) dimensional vector
*/
if(sigma==0)
{
throw runtime_error("sigma can't be zero");
}
int n = myu.size();
vector<double> basis(n);
for(int i = 0; i < n; i++)
{
basis[i] = sigmoid((x - myu[i])/ sigma);
}
return basis;
}

vector <double> fourier_basis(double x, int n)
{
/*
Computes the fourier basis function and returns a vector comprised of sins and coses
Φ(x) = [1,sin(2*π*x),cos(2*π*x),sin(4*π*x),cos(4*π*x),...,sin(2*π*n*x),cos(2*π*n*x)]

Args:
x - 1-dimensional data point(Scalar)
n - degree - (Scalar)

Returns:
Fourier Basis function - (2n+1) dimensional vector
*/
vector <double> basis;
basis.reserve(2*n+1);
basis.push_back(1.0);
for(int i = 1; i <= n; i++)
{
basis.push_back(sin(2*PI*i*x));
basis.push_back(cos(2*PI*i*x));
}
return basis;
}
10 changes: 10 additions & 0 deletions basis_function_approximation/basis_functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
std::vector<double> polynomial_basis(double x,int n);
std::vector<double> rbf_basis(double x,std::vector<double>&myu, double sigma);
double sigmoid(double x);
std::vector<double> sigmoid_basis(double x,std::vector<double>&myu, double sigma);
std::vector <double> fourier_basis(double x, int n);
double mother_wavelet(double x);
std::vector <double> wavelet_basis(double x, int m_low, int m_high, int j_low, int j_high);
double spline_aux(double x, double k);
std::vector <double> spline_basis(double x, int n);

179 changes: 179 additions & 0 deletions basis_function_approximation/matrix_functions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#include<bits/stdc++.h>
#include "matrix_functions.h"
using namespace std;

double getDeterminant(vector<vector<double>> a)
{
if(a.size() != a[0].size())
{
throw runtime_error("Matrix must be square");
}
int d = a.size();
if(d == 0)
{
return 1;
}
if(d == 1)
{
return a[0][0];
}
if(d == 2)
{
return a[0][0] * a[1][1] - a[0][1] * a[1][0];
}
double ans = 0;
int sign = 1;
for(int i = 0; i < d; i++)
{
vector<vector<double>> subVect(d - 1, vector<double> (d - 1));
for(int m = 1; m < d; m++)
{
int z = 0;
for(int n = 0; n < d; n++)
{
if(n != i)
{
subVect[m-1][z] = a[m][n];
z++;
}
}
}
ans = ans + sign * a[0][i] * getDeterminant(subVect);
sign = -sign;//As sign changes with consecutive cofactors
}

return ans;
}

vector<vector<double>> getTranspose(vector<vector<double>> a)
{
vector<vector<double>> ans(a[0].size(), vector<double> (a.size()));
for(int i = 0; i < a.size(); i++)
{
for(int j = 0; j < a[0].size(); j++)
{
ans[j][i] = a[i][j];
}
}
return ans;
}

vector<vector<double>> getCofactor(const vector<vector<double>> a)
{
if(a.size() != a[0].size())
{
throw runtime_error("Matrix must be square");
}
vector<vector<double>> solution(a.size(), vector<double> (a.size()));
vector<vector<double>> subVect(a.size() - 1, vector<double> (a.size() - 1));

for(int i = 0; i < a.size(); i++)
{
for(int j = 0; j < a[0].size(); j++)
{
int p = 0;
for(int x = 0; x < a.size(); x++)
{
if(x == i) {
continue;
}
int q = 0;

for(int y = 0; y < a.size(); y++)
{
if(y == j) {
continue;
}

subVect[p][q] = a[x][y];
q++;
}
p++;
}
solution[i][j] = pow(-1, i + j) * getDeterminant(subVect);
}
}
return solution;
}

vector<vector<double>> getInverse(vector<vector<double>> a)
{
if(getDeterminant(a) == 0)
{
throw runtime_error("Determinant is 0");
}
double d = getDeterminant(a);
vector<vector<double>> ans(a.size(), vector<double> (a.size()));
for(int i = 0; i < a.size(); i++)
{
for(int j = 0; j < a.size(); j++)
{
ans[i][j] = a[i][j];
}
}

ans = getTranspose(getCofactor(ans));

for(int i = 0; i < a.size(); i++)
{
for(int j = 0; j < a.size(); j++)
{
ans[i][j] /= d;
}
}
return ans;
}



void printMatrix(vector<vector<double>> a)
{
for(int i = 0; i < a.size(); i++)
{
for(int j = 0; j < a[0].size(); j++)
{
cout << a[i][j] << " ";
}
cout << "\n";
}
}



vector<vector<double>> matrix_mult(vector<vector<double>>a,vector<vector<double>>b)
{
int r1 = a.size(),c1 = a[0].size();
int r2 = b.size(),c2 = b[0].size();
vector<vector<double>>ans(r1,vector<double>(c2,0.0));
for(int i = 0; i < r1; i++)
{
for(int j = 0; j < c2; j++)
{
for(int k = 0; k < c1; k++)
{
ans[i][j] += (a[i][k] * b[k][j]) ;
}
}
}
return ans;
}

vector<vector<double>> fit(vector<vector<double>>phi,vector<double>y)
{
int m = phi.size(),n = phi[0].size();
vector<vector<double>> phi_T = getTranspose(phi);
vector<vector<double>> q = matrix_mult(phi_T,phi);
vector<vector<double>> q_inv = getInverse(q);
vector<vector<double>> s = matrix_mult(q_inv,phi_T);
vector<vector<double>> y_T(y.size());
// Constructing y_T as vector<vector<double>> in order to use in matrix_mult(matrix multiplication)
for(int i=0;i<y.size();i++)
{
vector<double> v(1, y[i]);
y_T[i] = (v);
}
return matrix_mult(s, y_T);
}



8 changes: 8 additions & 0 deletions basis_function_approximation/matrix_functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using namespace std;
double getDeterminant(vector<vector<double>> a);
vector<vector<double>> getTranspose(vector<vector<double>> a);
vector<vector<double>> getCofactor(const vector<vector<double>> a);
vector<vector<double>> getInverse(vector<vector<double>> a);
void printMatrix(vector<vector<double>> a);
vector<vector<double>> matrix_mult(vector<vector<double>>a,vector<vector<double>>b);
vector<vector<double>> fit(vector<vector<double>>phi,vector<double>y);
Loading