'''
Matrix Decomposition on TensorFlow
Author: Rowel Atienza
Project: https://github.com/roatienza/Deep-Learning-Experiments
'''
# On command line: python decomposition.py
# Prerequisite: tensorflow (see tensorflow.org)

from __future__ import print_function

import tensorflow as tf
import numpy as np
import numpy.linalg as la

print("Tensorflow version: " + tf.__version__)
# Real symmetric matrix S of rank 2
S = tf.constant([ [1.,2.], [2.,1.] ])
print("S = ")
print(S.eval(session=tf.Session()))

# Eigen Decomposition - for square symmetric matrices only
# self_adjoint_eig works only bec symmetric matrix is equal to its self adjoint
# otherwise, use np.linalg.eig
e,Q = tf.self_adjoint_eig(S)
# Diagonal matrix made of eigenvalues of S
V = tf.diag(e)
# S_ = S since S = Q*V*tran(Q) for real symmetric matrix
S_ = tf.matmul(Q,tf.matmul(V,Q))
print("S_ = S = ")
print(S_.eval(session=tf.Session()))

# SVD decomposition
d, U, V1 = tf.svd(S, full_matrices=True, compute_uv=True)
# U and V1 are orthogonal matrices; I must be therefore an identity matrix
I = tf.matmul(U,tf.transpose(V1))
print("I = ")
print(I.eval(session=tf.Session()))
D = tf.diag(d)
# S_ = S since S = U*D*tran(V1)
print("S_ = S = ")
S_ = tf.matmul(U,tf.matmul(D,tf.transpose(V1)))
print(S_.eval(session=tf.Session()))

# Moore-Penrose pseudoinverse
# For non-square matrices, padding of m-n zero columns needed (see linear_inv.y)
D = tf.transpose(tf.diag(np.reciprocal(d)))
print("pseudo_inv(S) = ")
S_ = tf.matmul(V1,tf.matmul(D,tf.transpose(U)))
print(S_.eval(session=tf.Session()))

# inverse of S BUT applicable to non-singular square matrices only
print("inv(S) = ")
print(tf.matrix_inverse(S).eval(session=tf.Session()))


import math
import numpy
from numpy.linalg import svd

A = [
    [-1, 3, -1],
    [-3, 5, -1],
    [-3, 3, 1]
]

U, singularValues, V = svd(A)
#NOTE: svd(movieRatings) outputs some part1,part2,part3, so the equal sign is assigned to all terms, U singularValues, and V, not just V alone
#this defines U as output 1, singularValues as output 2, V as output 3
#V is the main
Lambda=singularValues

print "The singular values are: ", singularValues #This gives U as an output when you run the file so you can see the SVD stuff works

r= 0*numpy.ndarray(shape=(len(U),len(V)))
for i in range(len(Lambda)):
    r[i][i]= abs(Lambda[i])

print "Here's the SVD Lambda matrix: ", numpy.matrix(r)

#print r[0][2], " ---> Test if that's definitionally equiv to zero: ", r[0][2] == 0

#print numpy.ndarray.tolist(numpy.matrix(r))

#print "U is: ", U
#print "V is: ", V

#print numpy.dot(U,numpy.transpose(V))
print "=====================================^^^SVD stuff^^^====================================="

eigenVals, eigVecs = numpy.linalg.eig(A)

print eigenVals
print len(eigenVals)
diagonalizedForm= 0.0*numpy.ndarray(shape=(len(eigenVals),len(eigenVals)))
for i in range(len(eigenVals)):
    diagonalizedForm[i][i]= abs(eigenVals[i])

#print diagonalizedForm
print "Here's the diagonalized form of the matrix: ", numpy.matrix(diagonalizedForm)
#numpy.ndarray.tolist( numpy.matrix(diagonalizedForm) )

print numpy.zeros( (3,3) ) #gives 3 by 3 matrix of all zeros, important for defns


#https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit?usp=sharing
#(Pretrained word2vec model link)
import gensim
from gensim.models import word2vec
from gensim.models import KeyedVectors
from sklearn.metrics.pairwise import cosine_similarity

word_vectors = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin',binary=True)
v_apple = word_vectors["apple"]
v_mango = word_vectors["india"]

print(v_apple.shape)
print(v_mango.shape)

cosine_similarity([v_mango],[v_apple])

import numpy as np
#1. Find the Odd One Out

def odd_one_out(words):
    """Accepts a list of words and returns the odd word"""

    # Generate all word embeddings for the given list
    all_word_vectors = [word_vectors[w] for w in words]
    avg_vector = np.mean(all_word_vectors,axis=0)
    print(avg_vector.shape)

    #Iterate over every word and find similarity
    odd_one_out = None
    min_similarity = 1.0 #Very high value

    for w in words:
        sim = cosine_similarity([word_vectors[w]],[avg_vector])
        if sim < min_similarity:
            min_similarity = sim
            odd_one_out = w

        print("Similairy btw %s and avg vector is %.2f"%(w,sim))

    return odd_one_out

input_1 = ["apple","mango","juice","party","orange"]
input_2 = ["music","dance","sleep","dancer","food"]
input_3  = ["match","player","football","cricket","dancer"]
input_4 = ["india","paris","russia","france","germany"]

odd_one_out(input_1)
odd_one_out(input_2)
odd_one_out(input_3)
odd_one_out(input_4)

#2. Word Analogies Task
#In the word analogy task, we complete the sentence "a is to b as c is to __". An example is 'man is to woman as king is to queen' . In detail, we are trying to find a word d, such that the associated word vectors ea,eb,ec,ed are related in the following manner: eb−ea≈ed−ec. We will measure the similarity between eb−ea and ed−ec using cosine similarity.
#Word2Vec
"""
man -> woman ::    prince -> princess
italy -> italian ::    spain -> spanish
india -> delhi ::  japan -> tokyo
man -> woman ::    boy -> girl
small -> smaller ::    large -> larger

Try it out
man -> coder :: woman -> ______?
"""

type(word_vectors.vocab)

word_vectors["man"].shape

def predict_word(a,b,c,word_vectors):
    """Accepts a triad of words, a,b,c and returns d such that a is to b : c is to d"""
    a,b,c = a.lower(),b.lower(),c.lower()

    # similarity |b-a| = |d-c| should be max
    max_similarity = -100

    d = None

    words = word_vectors.vocab.keys()

    wa,wb,wc = word_vectors[a],word_vectors[b],word_vectors[c]

    #to find d s.t similarity(|b-a|,|d-c|) should be max

    for w in words:
        if w in [a,b,c]:
            continue

        wv = word_vectors[w]
        sim = cosine_similarity([wb-wa],[wv-wc])

        if sim > max_similarity:
            max_similarity = sim
            d = w

    return d

triad_2 = ("man","woman","prince")
predict_word(*triad_2,word_vectors)

#Method 2
#Using the Most Similar Method

word_vectors.most_similar(positive=['woman', 'king'], negative=['man'], topn=1)


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_csv('height_weight.csv',usecols=['height','weight'])

#Co-Variance - Checking variance of one column with respect to another
#It has both variance and correlation combined into 1 matrix
#           (       a,a         a,b  )
#          (    Var         Var       )
#   Cov = (                            )
#          (       b,a         b,b    )
#           (   Var         Var     )
print(data.head())
print()

"""
print("Incorrect covariance")
covariance = np.cov(data)
print(covariance) #this expects each row and column to be a different variable
"""
print()
print()
#correct it by transposing or rowvar=False
covariance = np.cov(data.T) # or covariance = np.cov(data,rowvar=False)
print("Covariance")
print(covariance)
print()
print()
print("Covariance")
covariance_pandas = data.cov()
print(covariance_pandas)
print()
print()

#CORRELATION formula
#https://www.thoughtco.com/how-to-calculate-the-correlation-coefficient-3126228
#np.corrcoef or pd.DataFrame.corr
#Value of correlation goes from -1 to 1
# 1 = one variable goes up other does too
# -1 = One variable going up and other going down

corref = np.corrcoef(data.T)
print("Correlation")
print(corref)
print()
print("Pandas Correlation")
print()
print(data.corr())
# If variable can be derived from one another they are correlated


from math import sqrt

import pytest

import numpy as np

from directional_clustering.clustering import kmeans_initialize
from directional_clustering.clustering import centroids_associate
from directional_clustering.clustering import centroids_estimate
from directional_clustering.clustering import distance_cosine

from directional_clustering.clustering.kmeans.operations import rows_norm
from directional_clustering.clustering.kmeans.operations import rows_squared_norm

# ==============================================================================
# Tests
# ==============================================================================

def test_rows_norm(random_array):
    """
    Checks that the squared norm is calculated along the right axis.
    """
    random_norm = rows_norm(random_array).reshape(-1,)

    manual_norm = [random_array[0, 0]**2 + random_array[0, 1]**2,
                   random_array[1, 0]**2 + random_array[1, 1]**2]
    manual_norm = [sqrt(i) for i in manual_norm]

    assert np.allclose(random_norm, manual_norm), (random_norm, manual_norm)

def test_rows_norm_shape(random_array):
    """
    Checks that the squared norm is calculated along the right axis.
    """
    random_norm = rows_norm(random_array)
    assert random_norm.shape == (random_array.shape[0], 1)

def test_rows_squared_norm(random_array):
    """
    Checks that the squared norm is calculated along the right axis.
    """
    random_norm = rows_squared_norm(random_array).reshape(-1,)

    manual_norm = [random_array[0, 0] ** 2 + random_array[0, 1]**2,
                   random_array[1, 0] ** 2 + random_array[1, 1]**2]

    assert np.allclose(random_norm, manual_norm), (random_norm, manual_norm)

@pytest.mark.parametrize("size", list(range(1, 2)))
def test_kmeans_initialize_size(random_array, size):
    """
    Checks that the number of examples produced is correct.
    """
    seeds = kmeans_initialize(random_array, size)
    assert seeds.shape[0] == size

def test_kmeans_initialize_belongs(random_array):
    """
    Tests whether seeds exist in the array.
    """
    seed = kmeans_initialize(random_array, 1)
    assert seed in random_array

def test_kmeans_initialize_bad_k(random_array):
    """
    Produces more clusters than entries in the random array.
    """
    n, d = random_array.shape
    with pytest.raises(AssertionError):
        kmeans_initialize(random_array, n+1)

def test_centroids_associate_cosine(cosine_array, cosine_centroids):
    """
    Assigns labels to three vectors based on two redundant centroids.
    """
    _, closest = centroids_associate(cosine_array,
                                     cosine_centroids,
                                     distance_cosine)

    assert np.allclose(closest, np.array([0, 1, 1])), closest

def test_centroids_estimate_cosine(cosine_array):
    """
    Re-estimates two new centroids based on redundant association.
    """
    assoc = np.array([0, 1, 1])
    new_centroids = centroids_estimate(cosine_array, 2, assoc)
    assert np.allclose(new_centroids, np.array([[1.0, 0.0], [0.5, 1.0]]))


import numpy as np
from si.util.scale import StandardScaler

class PCA:

    def __init__(self, ncomponents = 2, using = "svd"):
        # ncomponents must be int
        if ncomponents > 0 and isinstance(ncomponents, int):
            self.ncomponents = round(ncomponents)
        else:
            raise Exception("Number of components must be non negative and an integer")
        self.type = using

    def transform(self, dataset):
        scaled = StandardScaler().fit_transform(dataset).X.T       # scale the features/standardize data

        # using numpy.linalg.svd:
        if self.type.lower()  == "svd":
            self.u, self.s, self.vh = np.linalg.svd(scaled)
        else:
            self.cov_matrix = np.cov(scaled)                       # covariance matrix
            # s are eigenvalues, u are eigenvectors
            self.s, self.u = np.linalg.eig(self.cov_matrix)        # Compute the eigenvalues and eigenvectors
        self.idx = np.argsort(self.s)[::-1]                        # sort the indexes (descending order)
        self.eigen_val =  self.s[self.idx]                         # reorganize by index
        self.eigen_vect = self.u[:, self.idx]                      # reorganize eigen vectors by column index

        self.sub_set_vect = self.eigen_vect[:, :self.ncomponents]  # ordered vectors with principal components
        return scaled.T.dot(self.sub_set_vect)                     # features scaled . vetores proprios ordenados

    def variance_explained(self):
        # find the explained variance
        sum_ = np.sum(self.eigen_val)
        percentage = [i / sum_ * 100 for i in self.eigen_val]       # percentagem da var explicada valor próprio / soma dos valores próprios * 100
        return np.array(percentage)

    def fit_transform(self, dataset):
        trans = self.transform(dataset)
        exp = self.variance_explained()
        return trans, exp


# Various Wind Calculations
#   Change wind speed and direction to U and V components
#   Change U and V components to direction
#   Change U and V components to speed
#   Calculate the angle between two vecors [u1,v1] and [u2,v2]

import numpy as np

def wind_spddir_to_uv(wspd,wdir):
    """
    calculated the u and v wind components from wind speed and direction
    Input:
        wspd: wind speed
        wdir: wind direction
    Output:
        u: u wind component
        v: v wind component
    """

    rad = 4.0*np.arctan(1)/180.
    u = -wspd*np.sin(rad*wdir)
    v = -wspd*np.cos(rad*wdir)

    return u,v

def wind_uv_to_dir(U,V):
    """
    Calculates the wind direction from the u and v component of wind.
    Takes into account the wind direction coordinates is different than the
    trig unit circle coordinate. If the wind directin is 360 then returns zero
    (by %360)
    Inputs:
      U = west/east direction (wind from the west is positive, from the east is negative)
      V = south/noth direction (wind from the south is positive, from the north is negative)
    """
    WDIR= (270-np.rad2deg(np.arctan2(V,U)))%360
    return WDIR

def wind_uv_to_spd(U,V):
    """
    Calculates the wind speed from the u and v wind components
    Inputs:
      U = west/east direction (wind from the west is positive, from the east is negative)
      V = south/noth direction (wind from the south is positive, from the north is negative)
    """
    WSPD = np.sqrt(np.square(U)+np.square(V))
    return WSPD

# Below is used for calculing the angle between two wind vectors
def unit_vector(vector):
    """ Returns the unit vector of the vector.  """
    return vector / np.linalg.norm(vector)

def angle_between(v1, v2):
    """
    Calcualates the angle between two wind vecotrs. Utilizes the cos equation:
                cos(theta) = (u dot v)/(magnitude(u) dot magnitude(v))

    Input:
        v1 = vector 1. A numpy array, list, or tuple with
             u in the first index and v in the second --> vector1 = [u1,v1]
        v2 = vector 2. A numpy array, list, or tuple with
             u in the first index and v in the second --> vector2 = [u2,v2]
    Output:
    Returns the angle in radians between vectors 'v1' and 'v2'::
            >>> angle_between((1, 0, 0), (0, 1, 0))
            1.5707963267948966
            >>> angle_between((1, 0, 0), (1, 0, 0))
            0.0
            >>> angle_between((1, 0, 0), (-1, 0, 0))
            3.141592653589793
    """
    v1_u = unit_vector(v1)
    v2_u = unit_vector(v2)
    angle = np.arccos(np.dot(v1_u, v2_u))
    if np.isnan(angle):
        if (v1_u == v2_u).all():
            return np.rad2deg(0.0)
        else:
            return np.rad2deg(np.pi)
    return np.rad2deg(angle)

#--- Example -----------------------------------------------------------------#
if __name__ == "__main__":
    u = np.array([1,5,-9])
    v = np.array([-1,-2,5])

    vector1 = [u[0],v[0]]
    vector2 = [u[1],v[1]]
    vector3 = [u[2],v[2]]

    print "U component: ", u
    print "V component: ", v
    print "Wind Directions: ", wind_uv_to_dir(u,v)
    print "Wind Speeds: ", wind_uv_to_spd(u,v)
    print ""
    print "Angle between vector 1 and 2: ", angle_between(vector1,vector2)
    print "Angle between vector 2 and 3: ", angle_between(vector2,vector3)


from numpy import linspace, sin, pi, absolute
from numpy.fft import rfft, rfftfreq
import matplotlib.pyplot as plt

# Sampling rate
fs = 100  # Hz
# the total lenght of the wave
length = 1  # 2 second
N = int(fs * length)
# time
t = linspace(0, length, num=N, endpoint=False)

# Generate a sinusoid at frequency f
f = 10  # Hz
a = 5*sin(2 * pi * f * t)
# generate a composite waveform which has 2 different frequencies
#f2 = 30  # Hz
#a = 2* sin(2 * pi * f * t) + 2/3*sin(2 * pi * f2 * t)

# Plot signal, showing how endpoints wrap from one chunk to the next
plt.subplot(2, 1, 1)
plt.plot(t, a, '.-')
plt.plot(1, 1, 'r.')  # first sample of next chunk
plt.margins(0.1, 0.1)
plt.xlabel('Time [s]')
plt.axhline()
plt.axvline()
plt.axvline(x=1/f, c='r', marker=".")

# Use RFFT to get the amplitude of the one-sided spectrum
ampl = 1/N * absolute(rfft(a))
# RFFT frequency bins
freqs = rfftfreq(N, 1/fs)
# Plot spectrum
plt.subplot(2, 1, 2)
plt.stem(freqs, ampl)
plt.margins(0.1, 0.1)
plt.xlabel('Frequency [Hz]')
plt.tight_layout()
plt.show()

# Question 1:
# think about how to plot sum of two sine waveform
#

# Solution:
# uncomment Line 17&18, change f and f2 to get different results


# Objective is to predict blood pressure from age & weight.
# R-sq values are calcualted for all combination of inputs (age only, weight only & both)
# Data is from:
# http://college.cengage.com/mathematics/brase/understandable_statistics/7e/students/datasets/mlr/frames/mlr02.html

# The data (X1, X2, X3) are for each patient.
# X0 = systolic blood pressure
# X1 = age in years
# X2 = weight in pounds

# Code Flow:
    # 1. Import all relevant libraries.
    # 2. Load the dataset using pandas (X - input/feature, Y - output/target).
    # 3. Plot the generated data understand the trend.
    # 4. Create input features for all combinations.
    # 5. get_r2 function defintion that calculates weights, predictions & final r-sq values.
    # 6. Print results for all cases.

# 1. Imports
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 2. Load dataset:
df = pd.read_excel('mlr02.xls')
X = df.as_matrix()

# 3. Plot the data to understand the trends:
plt.figure(1)
plt.scatter(X[:,1],X[:,0])
plt.xlabel('Age')
plt.ylabel('Systolic Blood Pressure')
plt.title('Blood pressure vs. Age')

plt.figure(2)
plt.scatter(X[:,2],X[:,0])
plt.xlabel('Weight (pounds)')
plt.ylabel('Systolic Blood Pressure')
plt.title('Blood pressure vs. Weight (pounds)')

# 4. Create input features for all combinations:
df['ones'] = 1

Y = df['X1']
X = df[['X2','X3','ones']]
X2only = df[['X2','ones']]
X3only = df[['X3','ones']]

# 5. Function definition that calcualtes weights, predictions & R-sq values:
def get_r2(X,Y):
    w = np.linalg.solve(np.dot(X.T,X),np.dot(X.T,Y))
    Yhat = np.dot(X,w)
    # R-sq:
    d1 = Y - Yhat
    d2 = Y - Y.mean()
    r2 = 1 - d1.dot(d1)/d2.dot(d2)

    return r2

# 6. Print results:
print('the r-squared for x2 only is:',get_r2(X2only,Y))
print('the r-squared for x3 only is:',get_r2(X3only,Y))
print('the r-squared for x2 & x3 only is:',get_r2(X,Y))

1.Linear Regression/1.Code - Using Theory/3.Blood Pressure Prediction.py


from sklearn.preprocessing import PolynomialFeatures
import numpy as np
X = np.array(
    [258.0, 270.0, 294.0, 320.0, 342.0,
    368.0, 396.0, 446.0, 480.0, 586.0]
)[:, np.newaxis]
y = np.array(
    [236.4, 234.4, 252.8, 298.6, 314.2,
    342.2, 360.8, 368.0, 391.2, 390.8]
)
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
pr = LinearRegression()
quadratic = PolynomialFeatures(degree=2)
X_quad = quadratic.fit_transform(X)

lr.fit(X, y)
X_fit = np.arange(250, 600, 10)[:, np.newaxis]
y_lin_fit = lr.predict(X_fit)

pr.fit(X_quad, y)
y_quad_fit = pr.predict(quadratic.fit_transform(X_fit))

import matplotlib.pyplot as plt
plt.scatter(X, y, label='training points')
plt.plot(X_fit, y_lin_fit, label='linear fit', linestyle='--')
plt.plot(X_fit, y_quad_fit, label='quadratic fit')
plt.legend(loc='upper left')
plt.show()

from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score
y_lin_pred = lr.predict(X)
y_quad_pred = pr.predict(X_quad)
print('Training MSE linear: %.3f, quadratic: %.3f' % (
    mean_squared_error(y, y_lin_pred), mean_squared_error(y, y_quad_pred)
))
print('Training R^2 linear: %.3f, quadratic: %.3f' % (
    r2_score(y, y_lin_pred), r2_score(y, y_quad_pred)
))


"""
円周率
"""

def pi(digit: int) -> str:
	from sympy import N, atan
	return str(N("((12 * atan(1/49)) + (32 * atan(1/57)) - (5 * atan(1/239)) + (12 * atan(1/110443))) * 4", digit))

if __name__ == "__main__":
	digit = 10000
	print(pi(digit))


#https://github.com/QuantConnect/Tutorials/blob/master
from math import log, sqrt, exp, pi
from scipy.stats import norm

class BsmModel:

    def __init__(self, option_type, price, strike, interest_rate, expiry, volatility, dividend_yield=0):
        self.s = price  # Underlying asset price
        self.k = strike  # Option strike K
        self.r = interest_rate  # Continuous risk fee rate
        self.q = dividend_yield  # Dividend continuous rate
        self.T = expiry  # time to expiry (year)
        self.sigma = volatility  # Underlying volatility
        self.type = option_type # option type "p" put option "c" call option

    def n(self, d):
        # cumulative probability distribution function of standard normal distribution
        return norm.cdf(d)

    def dn(self, d):
        # the first order derivative of n(d)
        return norm.pdf(d)

    def d1(self):
        d1 = (log(self.s / self.k) + (self.r - self.q + self.sigma ** 2 * 0.5) * self.T) / (self.sigma * sqrt(self.T))
        return d1

    def d2(self):
        d2 = (log(self.s / self.k) + (self.r - self.q - self.sigma ** 2 * 0.5) * self.T) / (self.sigma * sqrt(self.T))
        return d2

    def bsm_price(self):
        d1 = self.d1()
        d2 = d1 - self.sigma * sqrt(self.T)
        if self.type == 'c':
            price = exp(-self.r*self.T) * (self.s * exp((self.r - self.q)*self.T) * self.n(d1) - self.k * self.n(d2))
            return price
        elif self.type == 'p':
            price = exp(-self.r*self.T) * (self.k * self.n(-d2) - (self.s * exp((self.r - self.q)*self.T) * self.n(-d1)))
            return price
        else:
            print("option type can only be c or p")

a = BsmModel('c', 42, 35, 0.1, 90.0/365, 0.2)
price = a.bsm_price()


import numpy as np
import matplotlib.pyplot as plt

def gaussian(x, mean, std):
    std2 = np.power(std, 2)
    return (1 / np.sqrt(2* np.pi * std2)) * np.exp(-.5 * (x - mean)**2 / std2)

if __name__ == "__main__":
    gauss_1 = gaussian(10, 8, 2) # 0.12098536225957168
    gauss_2 = gaussian(10, 10, 2) # 0.19947114020071635

    print("Gauss(10, 8, 2): {}".format(gauss_1))
    print("Gauss(10, 10, 2): {}".format(gauss_2))

    # 標準高斯分佈
    mean = 0
    variance = 1
    std = np.sqrt(variance)

    # Plot between -10 and 10 with .001 steps.
    x = np.arange(-5, 5, 0.001)
    gauss = []
    for i in x:
        gauss.append(gaussian(i, mean, std))
    gauss = np.array(gauss)

    plt.plot(x, gauss)
    plt.show()

Sensor Fusion and Tracking/Kalman Filters/Gaussian/gaussian.py


import numpy as np
import numpy.linalg as linalg
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def center_data(raw_data):
	'''
	Given raw_data as numpy array, where a row
	is an observation. Return centered data

	Input: raw_data (numpy array)
	Returns: centered_data (numpy array)
	'''

	col_mean = raw_data.mean(axis=0)
	centered_data = raw_data - col_mean
	return centered_data

def graph_data3D(data, fig_name):

	fig = plt.figure()

	ax = fig.add_subplot(111, projection='3d')

	color_list = ['r', 'g', 'b', 'y']

	for c in range(4):
		b = data[:,-1] == c
		x0 = data[:, 0][b]
		x1 = data[:, 1][b]
		x2 = data[:, 2][b]

		ax.scatter(x0, x1, x2, color=color_list[c])

	plt.savefig(fig_name)

def graph_data2D(data, groups, fig_name):

	color_list = ['r', 'g', 'b', 'y']

	for c in range(4):
		b = groups == c
		x0 = data[:, 0][b]
		x1 = data[:, 1][b]

		plt.scatter(x0, x1, color=color_list[c])

	plt.xlim((data[:,0].min(), data[:,0].max()))
	plt.ylim((data[:,1].min(), data[:,1].max()))
	plt.savefig(fig_name)

def do_pca(data, comp_num):
	'''
	Return original data mapped
	to first comp_num of princ components

	Inputs:
		- data: (numpy array)
		- comp_num: (int) of prin comp
	Returns:
		- proj_data: (numpy array) of projected data
	'''

	centered_data = center_data(data)
	var_cov = centered_data.T @ centered_data * (1/centered_data.shape[0])

	# note: e_vecs will have COLUMNs as the corresponding eigenvectors
	# note: the e_vecs are already normalized, per documentation
	e_vals, e_vecs = linalg.eig(var_cov)

	e_ordering = np.argsort(e_vals)[::-1]
	e_basis = e_vecs[e_ordering][:, 0:comp_num]

	coeff = centered_data @ e_basis

	return coeff

def do_LLE(data, out_dim, k):
	'''
	Does local linear embedding with k nearest neighbors
	Each ROW in data is an observation
	'''

	# Loop over each observation in the data
	N = data.shape[0]

	w_matrix = np.zeros( (N, N) )

	w_dict = {}

	for i in range(N):

		# Calculate the weights for that observation i
		cur_obs = data[i,:]
		local_data = data - cur_obs
		local_distances = linalg.norm(local_data, axis=1)
		assert local_distances.shape == (N,)

		ordering = np.argsort(local_distances)
		assert ordering[0] == i
		k_nn_indices = ordering[1:k+1]

		neighborhood = local_data[k_nn_indices]

		# create the local Gram matrix
		K_i = neighborhood @ neighborhood.T
		ones = np.ones((k,1))

		# Solve for w_i matrix and normalize
		w_i = linalg.inv(K_i) @ ones
		w_i = w_i / linalg.norm(w_i, axis=0)

		# we need to input the KNN w_i avlues into w_matrix
		#print("{} NN of pt {} are:".format(k, cur_obs))
		for j in range(k):
			neighbor_index = k_nn_indices[j]
			neighbor_weight = w_i[j]
			w_matrix[i,neighbor_index] = neighbor_weight
			#print("\t pt {}".format(data[neighbor_index,:]))

	# Construct matrix M from the sparse w_matrix
	n_I = np.identity(N)
	M = (n_I - w_matrix).T @ (n_I - w_matrix)

	e_vals, e_vecs = linalg.eigh(M)
	proj = e_vecs[:, 1:1+out_dim]

	return proj

def do_iso(data, k, proj_dim):

	N = data.shape[0]

	# step1: calcualte the pairwise distances
	pairwise_distances = np.empty( (N,N) )
	for i in range(N):
		for j in range(N):
			x_i = data[i,:]
			x_j = data[j,:]
			diff = x_i - x_j
			norm_diff = linalg.norm(diff)
			pairwise_distances[i,j] = norm_diff

	# step2: calculate the nearest neighbors for each column
	dist_w_inf = np.full( (N,N), np.inf)

	for i in range(N):
		dist_i = pairwise_distances[:,i]
		ordered_indices = np.argsort(dist_i)

		knn_indices = ordered_indices[0:k+1]
		dist_w_inf[knn_indices, i] = pairwise_distances[knn_indices, i]

	# step3: compute shortest path
	# Apply Floyd-Warshall algorithm
	short_path_dist = dist_w_inf
	for k in range(N):
		for i in range(N):
			for j in range(N):

				if short_path_dist[i,j] > short_path_dist[i,k] + short_path_dist[k,j]:
					short_path_dist[i,j] = short_path_dist[i,k] + short_path_dist[k,j]

	# Do eigen decomp on shortest paths
	e_vals, e_vecs = linalg.eigh(short_path_dist)
	flipped_e_vals = np.flip(e_vals, axis=0)
	flipped_e_vecs = np.flip(e_vecs, axis=1)

	# step4: now that the eigens are sorted largest>smallest take first p, take sq.root
	flipped_e_vals[proj_dim:] = 0
	lambda_sqrt = np.sqrt(flipped_e_vals)

	# step5: construct diagonal matrix
	diag_lambda = np.diagflat(lambda_sqrt)
	y_matrix = (flipped_e_vecs @ diag_lambda).T

	return pairwise_distances, dist_w_inf, short_path_dist, y_matrix

if __name__ == "__main__":

	# Load data
	orig_data = np.loadtxt('data/3Ddata.txt')
	orig_data[:, 3] = orig_data[:, 3] - 1
	data_3d = orig_data[:,0:3]
	centered_data = center_data(data_3d)

	var_cov = centered_data.T @ centered_data * (1/centered_data.shape[0])

	# A: Do pca
	pca_coeff = do_pca(data_3d, 2)
	graph_data3D(orig_data, "3d_data.png")
	plt.clf()
	graph_data2D(pca_coeff, orig_data[:,-1], "pca.png")
	plt.clf()

	# B: do ISOMAP
	pairwise_distances, dist_w_inf, short_path_dist, y_matrix  = do_iso(data_3d, 10, 2)
	y0 = y_matrix[0,:]
	y1 = y_matrix[1,:]
	group = orig_data[:,-1]

	color_list = ['r', 'g', 'b', 'y']

	for c in range(4):
		b = group == c

		plt.scatter(y0[b], y1[b], color=color_list[c])
	plt.savefig('isomap.png')
	plt.clf()

	# C: do LLE
	lle_proj = do_LLE(data_3d, 2, 10)
	graph_data2D(lle_proj, orig_data[:,-1], "lle.png")
	plt.clf()


from typing import Tuple, Optional

import numpy as np
import scipy.stats
import matplotlib.pyplot as plt

def beta_a_b_from_mode_concentration(mode: float, concentration: float) -> Tuple[float, float]:
	"""
	Computes the shape parameters, alpha and beta, of a beta distribution given its mode and concentration.

	Parameters
	----------
	mode : float
		The mode of the distribution
	concentration : float
		The concentration of the distribution

	Returns
	-------
	out: tuple of floats
		alpha and beta parameters

	"""

	return mode*(concentration - 2.) + 1., (1-mode)*(concentration - 2.) + 1.

def beta_mode_concentration_from_a_b(a: float, b: float) -> Tuple[float, float]:
	"""
	Computes the mode and concentration of a beta distribution from its shape parameters, alpha and beta.

	Parameters
	----------
	a : float
		alpha parameter
	b : float
		beta parameter

	Returns
	-------
	out: tuple of floats
		Mode and concentration

	"""

	assert a > 1 and b > 1
	return (a - 1.) / (a + b - 2.), a + b

def plot_beta(
		a: Optional[float] = None, b: Optional[float] = None, mode: Optional[float] = None,
		concentration: Optional[float] = None) -> None:
	"""
	Plots a beta distribution.

	Parameters
	----------
	a : float, optional
		alpha parameter
	b : float, optional
		beta parameter
	mode : float, optional
		Mode
	concentration : float, optional
		Concentration

	"""

	if mode and concentration:

		a, b = beta_a_b_from_mode_concentration(mode, concentration)

	elif a and b:

		# it's fine
		pass

	else:

		raise Exception('either `a` and `b` or `mode` and `concentration` must be passed')

	x = np.linspace(scipy.stats.beta.ppf(0.01, a, b), scipy.stats.beta.ppf(0.99, a, b), 100)

	plt.figure()
	plt.plot(x, scipy.stats.beta.pdf(x, a, b), 'r-', lw=5, alpha=0.6, label='beta pdf')

def gamma_shape_rate_from_mode_sd(mode: float, sd: float) -> Tuple[float, float]:
	"""
	Returns the shape and rate parameters of a gamma distribution from its mode and standard deviation.

	Parameters
	----------
	mode : float
		Mode
	sd : float
		Standard deviation

	Returns
	-------
	out: tuple of floats
		Shape and rate

	"""

	r = (mode + np.sqrt(mode**2 + 4*sd**2)) / (2*sd**2)
	s = 1 + mode * r

	return s, r

def plot_gamma(mode: float, sd: float) -> None:
	"""
	Plots a gamma distribution.

	Parameters
	----------
	mode : float
		Mode
	sd : float
		Standard deviation

	"""

	shape, rate = gamma_shape_rate_from_mode_sd(mode, sd)

	# the scale is the inverse of the rate
	scale = 1./rate

	x = np.linspace(scipy.stats.gamma.ppf(0.01, a=shape, scale=scale), scipy.stats.gamma.ppf(0.99, a=shape, scale=scale))

	plt.figure()
	plt.plot(x, scipy.stats.gamma.pdf(x, a=shape, scale=scale), 'r-', lw=5, alpha=0.6, label='gamma pdf')

def plot_half_cauchy(scale: float) -> None:
	"""
	Plot a half-cauchy distribution.

	Parameters
	----------
	scale : float
		Scale

	"""

	x = np.linspace(scipy.stats.halfcauchy.ppf(0.01, scale=scale), scipy.stats.halfcauchy.ppf(0.99, scale=scale), 100)

	plt.figure()
	plt.plot(x, scipy.stats.halfcauchy.pdf(x, scale=scale), 'r-', lw=5, alpha=0.6, label='Half-Cauchy pdf')


# Project 1 Main - Computational Physics
# Hunter Phillips

# This program allows the user to input n, a, b, and c to solve
# Poisson's equation in a single dimension by turning it into a matrix.
# using Gaussian Jordan Elimination, Specialized Tridiagonal, and LU Decomposition
# Benchmarks and error calculations are also performed.

import sys
import numpy as nmp
from solver import *

# part b
def part_b(n, a_i, b_i, c_i):
    a = nmp.full(n+2, a_i, dtype=nmp.float64)
    b = nmp.full(n+2, b_i, dtype=nmp.float64)
    c = nmp.full(n+2, c_i, dtype=nmp.float64)
    x, v = general(f_function, a, b, c, n)
    return x, v

# part c
def part_c(n, a_i, b_i, c_i):
    a = nmp.full(n+2, a_i, dtype=nmp.float64)
    b = nmp.full(n+2, b_i, dtype=nmp.float64)
    c = nmp.full(n+2, c_i, dtype=nmp.float64)
    x, v = tridiag(f_function, a, b, c, n)
    return x, v

# part d
def part_d(n, a_i, b_i, c_i):
    a = nmp.full(n+2, a_i, dtype=nmp.float64)
    b = nmp.full(n+2, b_i, dtype=nmp.float64)
    c = nmp.full(n+2, c_i, dtype=nmp.float64)
    x, v = tridiag(f_function, a, b, c, n)
    u = u_function(x)
    eps_i = nmp.log10(abs((v[1:-1]-u[1:-1])/u[1:-1])) # strip the last and first parts of matrix
    eps = nmp.max(eps_i)
    return n, eps

# part e
def part_e(n, a_i, b_i, c_i):
    a = a_i
    b = b_i
    c = c_i
    x, v = LU(f_function, a, b, c, n)
    return  x, v

# benchmarks
def benchmarking(n, a_i, b_i, c_i):

    a = nmp.full(n+2, a_i, dtype=nmp.float64) # have to get that accuracy
    b = nmp.full(n+2, b_i, dtype=nmp.float64)
    c = nmp.full(n+2, c_i, dtype=nmp.float64)

    start_time = time.time() # in the future I would like to add more complex timing analysis
    x, v = general(f_function, a, b, c, n)
    end_time = time.time()
    general_time = end_time - start_time

    start_time = time.time()
    x, v = tridiag(f_function, a, b, c, n)
    end_time = time.time()
    tridiag_time = end_time - start_time

    a = a_i
    b = b_i
    c = c_i

    LU_time = 0. # preallocation

    if (n <= 10000):
        start_time = time.time()
        x, v = LU(f_function, a, b, c, n)
        end_time = time.time()
        LU_time = end_time - start_time

    return general_time, tridiag_time, LU_time

if __name__ == "__main__":

    print('This program allows the user to input n (for n x n matrix), a, b, and c to solve\nPoisson\'s equation in a single dimension by turning it into a matrix\nusing Gaussian Jordan Elimination, Specialized Tridiagonal, and LU Decomposition\nBenchmarks and error calculations are also performed.\n\n')

    # get user input
    n_i = int(raw_input('Please input the size n of your desired matrix: '))
    a_i = int(raw_input('Please input the value of a for your desired matrix: '))
    b_i = int(raw_input('Please input the value of b for your desired matrix: '))
    c_i = int(raw_input('Please input the value of c for your desired matrix: '))

    print('\nGeneral Algorithm')
    b_x, b_v = part_b(n_i, a_i, b_i, c_i)
    print(b_x)
    print(b_v)

    print('\nSpecialized Tridiagonal Algorithm')
    c_x, c_v = part_c(n_i, a_i, b_i, c_i)
    print(c_x)
    print(c_v)

    print('\nRelative Error')
    n, eps = part_d(n_i, a_i, b_i, c_i)
    print('n = ' + str(n))
    print('error = ' + str(eps))

    print('\nLinear Decomposition Algorithm')
    e_x, e_v = part_e(n_i, a_i, b_i, c_i)
    print(e_x)
    print(e_v)

    general_time, tridiag_time, LU_time = benchmarking(n_i, a_i, b_i, c_i)
    print('\nGeneral Algorithm Time to Execute')
    print(general_time)
    print('\nSpecialized Tridiagonal Algorithm Time to Execute')
    print(tridiag_time)
    print('\nLU Decomposition Time to Execute')
    print(LU_time)
    print('\n\n')


"""
Animated example of Newton-Raphson method for finding roots

MIT License

Copyright (c) 2021 Luiz Gustavo da Rocha Charamba

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import animation

def f(x):
  return x**6/6 - 3*x**4 - 2*x**3/3 + 27*x**2/2 + 18*x - 30

def d_f(x):
  return x**5 - 12*x**3 -2*x**2 + 27*x + 18

def newton_raphson(x):
    return x - f(x) / d_f(x)

x = 5.0#-6.5#-6.0

d = {"x" : [x], "f(x)": [f(x)]}
nr_X = []
nr_Y = []
iterations = 200
for i in range(0, iterations):
  x = newton_raphson(x)
  d["x"].append(x)
  nr_X.append(x)
  d["f(x)"].append(f(x))
  nr_Y.append(f(x))

print("Iterations: ", len(nr_X))
print(pd.DataFrame(d, columns=['x', 'f(x)']))

X = []
Y = []
left_limit = -5
right_limit = 5
step_sample = 0.01

for x in np.arange(left_limit, right_limit, step_sample):
    y = f(x)
    X.append(x)
    Y.append(y)

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(-5,5), ylim=(-70, 1000))
f_line, = ax.plot([],[]) #ax.plot(X, Y)
root_line, = ax.plot([],[], color='r', marker='o') #ax.plot(nr_X, nr_Y, color='r', marker='o')

# initialization function: plot the background of each frame
def init():
    f_line.set_data([], [])
    root_line.set_data([], [])

    return f_line, root_line,

def animate(i):
    f_line.set_data(X, Y)
    root_line.set_data(np.array(nr_X[:i]), np.array(nr_Y[:i]))
    return f_line, root_line

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=200, blit=True)

plt.show()


#!/usr/bin/python3
import sympy
import math
from prettytable import PrettyTable
x = sympy.Symbol('x')
ln = sympy.ln

f = x * ln(x) - x
g = x-f/f.diff(x)
tol = 0.1
xa = 2.5
table = PrettyTable()

iters = []
funcG = []
funcF = []
errorTot = []
deriv = []

def newton(tol,xa,niter):
    fx = f.evalf().subs({x:xa})
    funcF.append("%e" % (fx))
    error = tol+1
    errorTot.append("")
    funcG.append((xa))
    deriv.append(f.diff(x).evalf().subs({x:xa}))
    iters.append(0)
    cont = 0
    while(fx != 0 and error > tol and cont < niter):
        xn = g.evalf().subs({x:xa}).evalf()
        funcG.append((xn))
        deriv.append(f.diff(x).evalf().subs({x:xn}).evalf())
        fx = f.evalf().subs({x:xn}).evalf()
        funcF.append("%e" % (fx))
        error = abs(xn-xa)
        errorTot.append("%e" % (error/xn))
        xa = xn
        cont = cont +1
        iters.append(cont)
    if ( fx == 0):
        print(str(xa)+" es raiz")
    elif (error < tol):
        print(str(xa)+" es una aproximacion ")
    else:
        print("El metodo fracasó")
    table.add_column("n",iters)
    table.add_column("xn",funcG)
    table.add_column("f(xn)",funcF)
    table.add_column("f'(xn)",deriv)
    table.add_column("error",errorTot)
    print(table)

newton(tol,xa,200)


# -*- coding: utf-8 -*-
"""
@author: salimt
"""
#Problem 2: R^2
#10/10 points (graded)
#After we create some regression models, we also want to be able to evaluate our models to figure out how well each model represents our data, and tell good models from poorly fitting ones. One way to evaluate how well the model describes the data is computing the model's R^2 value. R^2 provides a measure of how well the total variation of samples is explained by the model.
#
#Implement the function r_squared. This function will take in:
#
#list, y, that represents the y-coordinates of the original data samples
#estimated, which is a corresponding list of y-coordinates estimated from the regression model
#This function should return the computed R^2 value. You can compute R^2 as follows, where  is the estimated y value for the i-th data point (i.e. predicted by the regression),  is the y value for the ith data point, and  is the mean of the original data samples.
#
#
#If you are still confused about R^2 , its wikipedia(https://en.wikipedia.org/wiki/Coefficient_of_determination) page has a good explanation about its use/how to calculate it.
#
#Note: If you want to use numpy arrays, you should import numpy as np and use np.METHOD_NAME in your code. Unfortunately, pylab does not work with the grader.
#
##Problem 2
#
def r_squared(y, estimated):
    """
    Calculate the R-squared error term.
    Args:
        y: list with length N, representing the y-coords of N sample points
        estimated: a list of values estimated by the regression model
    Returns:
        a float for the R-squared error term
    """
    import numpy

    error = ((numpy.array(estimated) - numpy.array(y))**2).sum()
    meanError = error/len(y)
#    return round(1 - (meanError/numpy.var(y)), 4)
    return 1 - (meanError/numpy.var(y))

#print(r_squared([32.0, 42.0, 31.3, 22.0, 33.0], [32.3, 42.1, 31.2, 22.1, 34.0])) #0.9944


# -*- coding: utf-8 -*-
# Imports all the necessary libraries
"""This application approximates the PI value based on a Monte Carlo Simulation.
It asks for input from the user regarding on number of darts thrown."""
import math
import random
import numpy as np
import matplotlib.pyplot as plt

def gen_circle(radius=1, center_x=0, center_y=0, res=50):
    """Returns the points of coordinates [x,y] which lie on the circle
    with the radius radius and with the center specified at center = [x,y],
    with the resolution res"""
    xcord = [center_x + radius * math.cos(tht) for \
         tht in np.linspace(0, 2 * math.pi, res)]
    ycord = [center_y + radius * math.sin(tht) for \
         tht in np.linspace(0, 2 * math.pi, res)]
    return [xcord, ycord]

def gen_square(center_x=0, center_y=0, edge=2):
    """Returns the vertices of a square in [x,y] coordinates, which is centered
    at the center=[x,y] and with the edge length equal to edge"""
    vertices_x = [center_x + edge/2, center_x - \
                  edge/2, center_x - edge/2, center_x + edge/2]
    vertices_y = [center_y + edge/2, center_y + \
                  edge/2, center_y - edge/2, center_y - edge/2]
    vertices = [vertices_x, vertices_y]
    return vertices

PLAY = True
APPROX_PI_LIST = list()
NUM_DARTS_LIST = list()

while PLAY:
    #Insert the number of darts to be thrown
    NUM_DARTS = int( \
            input('Please insert the number of darts that you want to throw\n'))
    NUM_DARTS_LIST.append(NUM_DARTS)

    CIRC_DARTS = {'x':list(), 'y':list()}
    SQUARE_DARTS = {'x':list(), 'y':list()}

    CIRC_HITS = 0
    SQUARE_HITS = 0

    for dart in range(NUM_DARTS):
        x_dart = random.random() * 2 - 1
        y_dart = random.random() * 2 - 1

        if(x_dart**2 + y_dart**2)**(1/2) > 1:
            SQUARE_HITS += 1
            SQUARE_DARTS['x'].append(x_dart)
            SQUARE_DARTS['y'].append(y_dart)

        elif(x_dart**2 + y_dart**2)**(1/2) <= 1:
            CIRC_HITS += 1
            CIRC_DARTS['x'].append(x_dart)
            CIRC_DARTS['y'].append(y_dart)

        else:
            pass

    APPROX_PI = 4 * CIRC_HITS/NUM_DARTS #THE APPROXIMATED VALUE OF PI
    APPROX_PI_LIST.append(APPROX_PI)

    #Plots the darts thrown in a new figure
    plt.figure(figsize=(10, 10))

    #Plots the square
    plt.fill(gen_square()[0], gen_square()[1], fill=False)

    #Plots the circle
    plt.plot(gen_circle()[0], gen_circle()[1], 'g-')

    #Plots the darts which landed on the darts board
    plt.plot(CIRC_DARTS['x'], CIRC_DARTS['y'], 'go')

    #Plots the darts which landed outside the darts board and inside the square
    plt.plot(SQUARE_DARTS['x'], SQUARE_DARTS['y'], 'ro')

    #Sets a title to the plot
    plt.title('Approximated Pi value: {:6.4f} ==> Darts thrown: {:d}'.format( \
            APPROX_PI, NUM_DARTS), {'fontsize':20})

    #Turning off hte tick labels for the plots
    plt.xticks([])
    plt.yticks([])

    print("\nYour darts Monte Carlo method approximative value of PI is:",
          " {}\n\nThat's {} off from the actual value of PI\n".format(\
            APPROX_PI, abs(math.pi - APPROX_PI)))
    print('\nCircle hit {} times and square hit {} times'.format(\
          CIRC_HITS, SQUARE_HITS))

    QUESTION_STRING = 'Do you want to trow darts again Y/N?. \
    To see all the plots press N\n'
    CONTINUE_PLAY = input(QUESTION_STRING)
    if CONTINUE_PLAY == 'Y':
        PLAY = True
    elif CONTINUE_PLAY == 'N':
        PLAY = False
        print('\nThank you for playing the game,',
              ' have a look at all the plots generated\n')
        print('\nThe previous results are:\n')

        for piVal, dart in zip(APPROX_PI_LIST, NUM_DARTS_LIST):
            print(f'Approximated Pi value: {piVal:4} ',
                  f'==> Darts thrown: {dart:4}')


import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

mu_params = [-1,0,1]
sd_params = [0.5,1,1.5]
x=np.linspace(-7,7,100)

f,ax=plt.subplots(len(mu_params),len(sd_params),sharex=True,
                  sharey=True)
for i in range(len(mu_params)):
    for j in range(len(sd_params)):
        mu = mu_params[i]
        sd = sd_params[j]
        y = stats.norm(mu,sd).pdf(x)
        ax[i,j].plot(x,y)
        ax[i,j].plot(0,0,
                     label = f"$\\mu$ = {mu:3.2f}\n$\\sigma$ = {sd:3.2f}",alpha=0)
        ax[i,j].legend(fontsize=12)
ax[2,1].set_xlabel('$x$',fontsize=16)
ax[1,0].set_ylabel('$pdf(x)$',fontsize=16)
plt.tight_layout()
plt.show()


"""Module for solution to
https://www.codewars.com/kata/ad2070-help-lorimar-troubleshoot-his-robots-ultrasonic-distance-analysis."""

from numpy import mean, var
from math import sqrt

def sensor_analysis(sensor_data):
    """Return a tuple with the mean and standard deviation of the distance
    variables rounded to four decimal places. The variance should be computed
    using the formula for samples (dividing by N-1)."""
    distances = [data[1] for data in sensor_data]
    avg = round(mean(distances), 4)
    variance = round(var(distances, ddof=1), 4)
    stddev = round(sqrt(variance), 4)
    return (avg, stddev)


from sympy import symbols, sqrt, solve
from scipy.signal.wavelets import cascade
import matplotlib.pyplot as plt
import numpy as np
import utilities.wavelet as wv

def compute_A3_filter_coefficeints():

    h = symbols('h0 h1 h2 h3 h4 h5')

    # Filter Equations
    eq1 = sum(v**2 for v in h) - 1
    eq2 = sum([h[i-2]*h[i] for i in range(2, len(h))])
    eq3 = sum(h) - sqrt(2)

    # A(3) Equations
    eq4 = sum([(-1)**i*h[i] for i in range(0, len(h))])
    eq5 = sum([(-1)**i*(-i)*h[i] for i in range(0, len(h))])
    eq6 = sum([(-1)**i*i**2*h[i] for i in range(0, len(h))])

    solutions = solve([eq1, eq2, eq3, eq4, eq5, eq6], *h)
    print solutions

def plot_A3_symbol(show=True):
    h = [0.332670552950083, 0.806891509311093, 0.459877502118492, -
         0.135011020010255, -0.0854412738820267, 0.0352262918857095]

    # Compute Symbol
    P, f = wv.compute_symbol(h)

    plt.figure(1)

    # Plot Symbol
    t = np.linspace(0, 1, 200)
    plt.plot(t, [abs(P.subs(f, v).evalf()) for v in t])
    plt.xlabel('f')
    plt.ylabel('abs(P)')
    plt.title('Symbol P(f)')

    if show:
        plt.show()

def plot_A3_scaling_function_and_wavelet(show=True):
    h = [0.332670552950083, 0.806891509311093, 0.459877502118492, -
         0.135011020010255, -0.0854412738820267, 0.0352262918857095]

    plt.figure(2)

    t, phi, psi = cascade(h)
    plt.subplot(1,2,1)
    plt.plot(t, phi)
    plt.xlabel('t')
    plt.ylabel('phi')
    plt.title('scaling function')

    plt.subplot(1,2,2)
    plt.plot(t, psi)
    plt.xlabel('t')
    plt.ylabel('psi')
    plt.title('mother wavelet')

    if show:
        plt.show()

if __name__ == "__main__":
    plot_A3_symbol(show=False)
    plot_A3_scaling_function_and_wavelet()


import numpy as np
import matplotlib.pyplot as plt

# linear function
def linear(m, b, x):
    return m * x + b

# Sum of Squared Errors
def sse(m: float, b: float, x: np.ndarray, y: np.ndarray) -> float:
    guess = linear(m, b, x)
    actual = y

    return sum((actual - guess) ** 2) / 2

# partial derivative of sse() w.r.t 'm'
def dm_sse(m: float, b: float, x: np.ndarray, y: np.ndarray):
    return sum(-x * (y - linear(m, b, x)))

# partial derivative of sse() w.r.t 'b'
def db_sse(m: float, b: float, x: np.ndarray, y: np.ndarray):
    return sum(-(y - linear(m, b, x)))

X: np.ndarray = np.linspace(0, 20, 30)
Y: np.ndarray = X + np.random.random(30) * 5 - 10

M = 0.0  # slope
B = 0.0  # intercept

# higher learning rate might cause uncontrolled bouncing & will not converge
learning_rate = 0.0001

# Gradient descent until Squared error is below 35
while sse(M, B, X, Y) > 35:
    M -= dm_sse(M, B, X, Y) * learning_rate
    B -= db_sse(M, B, X, Y) * learning_rate

print(M, B, sse(M, B, X, Y))

fitted_x = np.linspace(0, 20, 30)
fitted_y = linear(M, B, fitted_x)

plt.plot(fitted_x, fitted_y)
plt.scatter(X, Y)
plt.show()


"""
Utility functions for testing different search
algorithms implemented in this skill.
"""
import signal
import numpy as np

from functools import wraps

class LossFunctions:
    """
    Loss functions to evaluate the performance
    of search algorithms. All methods available in
    this class take numpy arrays as input.

    Methods
    -------
    mape:
        Mean averaged percentage error.
    rmse:
        Root mean squared error.
    mse:
        Mean squared error.
    """
    @staticmethod
    def mape(A, B):
        """
        Calculates the mean absolute persentage error
        from two series. Original solution from:

            https://stats.stackexchange.com/questions/58391/\
                mean-absolute-percentage-error-mape-in-scikit-learn

        Parameters
        ----------
        A, B: numpy.array
            Numpy arrays with the same length with the
            two objects representing the results (A)
            and test data (B).

        Returns
        -------
        float
            Floating number in the domain [0, 1].
        """
        #
        #  Let's add 1 to all values
        #  to avoid division by zero.
        #
        A += 0.000000000001
        B += 0.000000000001
        return np.round(np.mean(np.abs(A - B) / A) * 100, 2)

    @staticmethod
    def rmse(A, B):
        """
        Calculates the root mean square error from
        two series. Original solution from:

            https://stackoverflow.com/questions/16774849\
                /mean-squared-error-in-numpy

        Parameters
        ----------
        A, B: numpy.array
            Numpy arrays with the same length with the
            two objects representing the results (A)
            and test data (B).

        Returns
        -------
        float
            Floating number in the same domain
            of the original data.
        """
        return np.round(np.sqrt(np.square(np.subtract(A, B)).mean()), 2)

    @staticmethod
    def mse(A, B):
        """
        Calculates the mean square error from
        two series. Original solution from:

            https://stackoverflow.com/questions/16774849\
                /mean-squared-error-in-numpy

        Parameters
        ----------
        A, B: numpy.array
            Numpy arrays with the same length with the
            two objects representing the results (A)
            and test data (B).

        Returns
        -------
        float
            Floating number in the squared domain
            of the original data.
        """
        return np.round(np.square(np.subtract(A, B)).mean(), 2)


# Implementing Newton Raphson method in Python
# Author: Syed Haseeb Shah (github.com/QuantumNovice)
# The Newton-Raphson method (also known as Newton's method) is a way to
# quickly find a good approximation for the root of a real-valued function

from decimal import Decimal
from math import *  # noqa: F401, F403
from sympy import diff

def newton_raphson(func: str, a: int, precision: int=10 ** -10) -> float:
    """ Finds root from the point 'a' onwards by Newton-Raphson method
    >>> newton_raphson("sin(x)", 2)
    3.1415926536808043
    >>> newton_raphson("x**2 - 5*x +2", 0.4)
    0.4384471871911695
    >>> newton_raphson("x**2 - 5", 0.1)
    2.23606797749979
    >>> newton_raphson("log(x)- 1", 2)
    2.718281828458938
    """
    x = a
    while True:
        x = Decimal(x) - (Decimal(eval(func)) / Decimal(eval(str(diff(func)))))
        # This number dictates the accuracy of the answer
        if abs(eval(func)) < precision:
            return float(x)

# Let's Execute
if __name__ == "__main__":
    # Find root of trigonometric function
    # Find value of pi
    print(f"The root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}")
    # Find root of polynomial
    print(f"The root of x**2 - 5*x + 2 = 0 is {newton_raphson('x**2 - 5*x + 2', 0.4)}")
    # Find Square Root of 5
    print(f"The root of log(x) - 1 = 0 is {newton_raphson('log(x) - 1', 2)}")
    # Exponential Roots
    print(f"The root of exp(x) - 1 = 0 is {newton_raphson('exp(x) - 1', 0)}")


# Illustrate the powr method for computing largest eigenvector

import numpy as np
from numpy.linalg import norm

np.random.seed(0)

def power_method(A, max_iter=100, tol=1e-5):
    n = np.shape(A)[0]
    u = np.random.rand(n)
    converged = False
    iter = 0
    while (not converged) and (iter < max_iter):
        old_u = u
        u = np.dot(A, u)
        u = u / norm(u)
        lam = np.dot(u, np.dot(A, u))
        converged = (norm(u - old_u) < tol)
        iter += 1
    return lam, u

X = np.random.randn(10, 5)
A = np.dot(X.T, X)
lam, u = power_method(A)

evals, evecs = np.linalg.eig(A)
idx = np.argsort(np.abs(evals))[::-1] # largest first
evals = evals[idx]
evecs = evecs[:,idx]

tol = 1e-3
assert np.allclose(evecs[:,0], u, tol)
assert np.allclose(evals[0], lam, tol)


import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
from numba import jit

def moving_averages(x, half_window):
    x = np.append(np.array([x[0]]*half_window), x)
    x = np.append(x, np.array([x[-1]]*half_window))
    cumsum = np.cumsum(np.insert(x, 0, 0))
    window = half_window * 2
    ma = (cumsum[window:-1] - cumsum[:-window-1]) / window
    return ma

@jit
def approx(coeffs, t, period = 1.0):
    dim = int((coeffs.size - 1) / 2)
    a0 = coeffs[0]
    a = coeffs[1:dim+1]
    b = coeffs[dim+1:2*dim+1]
    tt = 2 * np.pi / period * np.arange(1, dim+1) * np.ones((t.size, dim)) * t.reshape((t.size,1))
    res = a0 + np.sum(a * np.sin(tt), axis = 1) + np.sum(b * np.cos(tt), axis = 1)
    # res = a0 \
    #       + sum(map(lambda i : a[i] * np.sin(2 * np.pi * (i+1) / period * t), range(0,dim))) \
    #       + sum(map(lambda i : b[i] * np.cos(2 * np.pi * (i+1) / period * t), range(0,dim)))
    return res

@jit
def approx_scalar(coeffs, t):
    dim = int((coeffs.size - 1) / 2)
    a0 = coeffs[0]
    a = coeffs[1:dim+1]
    b = coeffs[dim+1:2*dim+1]
    tt = 2 * np.pi * np.arange(1, dim+1) * t
    res = a0 + np.sum(a * np.sin(tt)) + np.sum(b * np.cos(tt))
    # res = a0 \
    #       + sum(map(lambda i : a[i] * np.sin(2 * np.pi * (i+1) / period * t), range(0,dim))) \
    #       + sum(map(lambda i : b[i] * np.cos(2 * np.pi * (i+1) / period * t), range(0,dim)))
    return res

class approximation():
    def __init__(self, label, points, values, ma_halfwindow, min_degree, max_degree):
        self.label = label
        self.points = points
        self.values = values
        self.ma_halfwindow = ma_halfwindow
        self.ma = moving_averages(self.values, self.ma_halfwindow)
        self.min_degree = min_degree
        self.max_degree = max_degree
        self.coeffs = []
        self.rmses = []
        for i in range(self.min_degree, self.max_degree+1):
            p0 = np.array([1.0]*(2*i+1))
            result = optimize.leastsq(lambda p: approx(p, self.points) - self.values, p0)
            rmse = np.mean((approx(result[0], self.points) - self.values)**2)
            self.coeffs.append(np.array(result[0]))
            self.rmses.append(rmse)

    def plot_all(self):
        fig, ax1 = plt.subplots()
        ax1.set_ylabel(self.label)
        ax1.scatter(self.points, self.values, color='red', label='values', marker='.')
        ax1.plot(self.points, self.ma, color='red', label='moving average')
        for p in self.coeffs:
            ax1.plot(self.points, approx(p, self.points), label=f'approx of degree {(p.size - 1) / 2}')
        ax1.legend(loc='upper center')
        fig.tight_layout()
        plt.show()

    def plot_rmses(self):
        fig, ax1 = plt.subplots()
        ax1.plot(range(self.min_degree, self.max_degree+1), self.rmses)
        fig.tight_layout()
        plt.show()


"""
# !/usr/bin/env python
# -*- coding: utf-8 -*-
@Time        : 2022/3/26 11:56
@File        : softmax.py
"""

import numpy as np

# Write a function that takes as input a list of numbers, and returns
# the list of values given by the softmax function.
def softmax(L):
    """
    softmax
    """
    exPL = np.exp(L)
    sumExpL = sum(exPL)

    result = []
    for i in exPL:
        result.append(i * 1.0/sumExpL)
    return result

# Note: The function np.divide can also be used here, as follows:
# def softmax(L):
#     expL = np.exp(L)
#     return np.divide (expL, expL.sum())

udacity-program_self_driving_car_engineer_v1.0/part01-computer vision and deep learning/module03-deep learning/lesson01-introduction to neural networks/exercise03-softmax/softmax.py


import numpy as np

def pol2cart(rho, phi):
    """
    Transform from polar to cart coordinates
    :param rho: distance to origin
    :param phi: angle (rad)
    :return: x, y
    """
    x = rho * np.cos(phi)
    y = rho * np.sin(phi)
    return x, y

def cart2pol(x, y):
    """
    Transform from cart to polar coordinates
    :param x: x
    :param y: y
    :return: rho, phi (rad)
    """
    rho = (x * x + y * y) ** 0.5
    phi = np.arctan2(y, x)
    return rho, phi

def pol2cart_ramap(rho, phi):
    """
    Transform from polar to cart under RAMap coordinates
    :param rho: distance to origin
    :param phi: angle (rad) under RAMap coordinates
    :return: x, y
    """
    x = rho * np.sin(phi)
    y = rho * np.cos(phi)
    return x, y

def cart2pol_ramap(x, y):
    """
    Transform from cart to polar under RAMap coordinates
    :param x: x
    :param y: y
    :return: rho, phi (rad) under RAMap coordinates
    """
    rho = (x * x + y * y) ** 0.5
    phi = np.arctan2(x, y)
    return rho, phi


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Feb  8 21:45:48 2019

@author: alankar
"""
import numpy as np
import os

def trapezoidal(func, a, b, n,*args):
    h = float(b - a) / n
    s = 0.0
    s += func(a,*args)/2.0
    for i in range(1, n):
        s += func(a + i*h,*args)
    s += func(b,*args)/2.0
    return s * h

def romberg(func, a, b, n,verbose,*args): #approximation error of order 2n
    file = open('Romberg Triangle.txt','a')
    h = float(b - a)
    T = np.zeros((n+1,n+1))
    if verbose: file.write('Romberg Triangular matrix: N = %d\n'%n)
    for j in range(1,n+1):
        T[j,1] = (h/2)*(func(a,*args)+2*np.sum(func(a+np.arange(h,int(2**(j-1))*h,h),*args))+func(b,*args)) #Comp Trapz
        if verbose: file.write('%f  '%T[j,1])
        for k in range(2,j+1):
            T[j,k] = T[j,k-1]+(T[j,k-1]-T[j-1,k-1])/(4**(k-1)-1) #Richardson Extrp
            if verbose: file.write('%f  '%T[j,k])
        if verbose: file.write('\n')
        h/=2
    if verbose: file.write('\n\n')
    if verbose: file.close()
    return T[n,n]

f = lambda x:np.sin(np.sqrt(100*x))**2

tol = 1e-6

n = 1
I_old = 0
I_new = trapezoidal(f,0,1,n)

print('TRAPEZOIDAL INTEGRATION (ADAPTIVE):')
while (abs(I_new-I_old)>tol):
    n *= 2
    print('Slices = %d'%n)
    I_old = I_new
    I_new = trapezoidal(f,0,1,n)
    print('I = %.7f'%I_new)
    print('Fractional error estimate: %e'%abs((I_new-I_old)/I_new))

n = 1
I_old = 0
I_new = romberg(f,0,1,n,True)
os.remove('Romberg Triangle.txt')

print('\n\nROMBERG INTEGRATION:')
while (abs(I_new-I_old)>tol):
    n *= 2
    print('Slices = %d'%n)
    I_old = I_new
    I_new = romberg(f,0,1,n,True)
    print('I = %.7f'%I_new)
    print('Fractional error estimate: %e'%abs((I_new-I_old)/I_new))

"""
Output:

TRAPEZOIDAL INTEGRATION (ADAPTIVE):
Slices = 2
I = 0.3252319
Fractional error estimate: 5.450032e-01
Slices = 4
I = 0.5122829
Fractional error estimate: 3.651322e-01
Slices = 8
I = 0.4029974
Fractional error estimate: 2.711814e-01
Slices = 16
I = 0.4301034
Fractional error estimate: 6.302188e-02
Slices = 32
I = 0.4484147
Fractional error estimate: 4.083563e-02
Slices = 64
I = 0.4539129
Fractional error estimate: 1.211304e-02
Slices = 128
I = 0.4553485
Fractional error estimate: 3.152691e-03
Slices = 256
I = 0.4557113
Fractional error estimate: 7.960349e-04
Slices = 512
I = 0.4558022
Fractional error estimate: 1.995014e-04
Slices = 1024
I = 0.4558249
Fractional error estimate: 4.990618e-05
Slices = 2048
I = 0.4558306
Fractional error estimate: 1.247847e-05
Slices = 4096
I = 0.4558321
Fractional error estimate: 3.119738e-06
Slices = 8192
I = 0.4558324
Fractional error estimate: 7.799420e-07

ROMBERG INTEGRATION:
Slices = 2
I = 0.3843160
Fractional error estimate: 6.149537e-01
Slices = 4
I = 0.3489739
Fractional error estimate: 1.012746e-01
Slices = 8
I = 0.4558325
Fractional error estimate: 2.344253e-01
Slices = 16
I = 0.4558325
Fractional error estimate: 8.931689e-12
"""


#Find Delannoy Numbers

def getDelannoyArray(n=5):
    colk = [k for k in range(n+1)]
    a=[[ 1 if(j==0 or i==0) else 0 for j in colk] for i in colk]
    a[1][1]=3
    for i in range(1,n+1):
        for j in range(1,n+1):
            a[i][j] = a[i-1][j]+a[i-1][j-1]+a[i][j-1]

    return a

#Delannoy Sequence from array
def DelannoySequenceFT(n=5,returni=False):
    a = getDelannoyArray(n)
    b = [[a[i][j] for j in range(len(a[i])) if(i==j) ][0] for i in range(len(a))]
    if(returni):
        return b
    else:
        print(b)

#Delannoy Sequence from array (method 2)
def DelannoySequenceFT2(n=5,returni=False):
    colk = [k for k in range(n+1)]
    a=[[ 1 if(j==0 or i==0) else 0 for j in colk] for i in colk]
    a[1][1]=3
    b=[]
    for i in range(1,n+1):
        for j in range(1,n+1):
            if(1==1):
                a[i][j] = a[i-1][j]+a[i-1][j-1]+a[i][j-1]
                if(i==j):
                    b.append(a[i][j])
            else:
                continue
    return b

#Central numbers from Delannoy Sequence
def DelannoySequence(n=5,returni=False,roundt=True):
    from sympy import Integer as mmmint
    from sympy import Float as mmmfloat
    a = [1,3]
    for i in range(2,n+2):
        b = (3*(2*i-1)*a[i-1]-(i-1)*a[i-2])/i
        if(roundt==True):
            b = mmmint(b)
        else:
            b = mmmfloat(b)
        a.append(b)
        if(not returni):
            print(b,end=", ")
    if(returni):
        return a[:n]

def DelannoArray(countt=10):
    s = getDelannoyArray(countt)
    r = range(len(s))
    from pandas import DataFrame as mmpd
    df=mmpd(s, columns=r, index=r)
    df=df.rename_axis(columns="n/k")
    return df

#getDelannoyArray()
#DelannoArray()
#DelannoySequenceFT2(2000) # 3.26 s
#DelannoySequenceFT(2000) #3.12 s
#DelannoySequence(2000) #387 ms


#-*-conding:utf-8-*-

import numpy as np
from math import exp, sqrt, log
import random
from scipy.stats.distributions import norm

'''
Parameters:
s0 = initial stock price
k = strike price
r = risk-less short rate
sig = volatility of stock value
dt = t/T = time to maturity
m = the number of path nodes
n = the number of simulation
'''

def black_scholes_model(s0, k, r, sig, dt):
    d1 = (log(s0 / k) + (r + sig ** 2 / 2) * dt) / (sig * sqrt(dt))
    d2 = d1 - sig * sqrt(dt)
    call_bs = s0 * exp(-r * dt) * norm.cdf(d1) - k * exp(-r * dt) * norm.cdf(d2)
    put_bs = k * exp(-r * dt) * norm.cdf(-d2) - s0 * exp(-r * dt) * norm.cdf(-d1)
    return {'call_BS': call_bs, 'put_BS': put_bs}

def monte_carlo_simulation(s0, k, r, sig, dt, m, n):
    list_1 = []  # call option value list
    list_2 = []  # put option value list
    delta_t = dt / m  # length of time interval

    for i in range(0, n):
        path = [s0]
        for j in range(0, m):
            path.append(path[-1] * exp((r - 0.5 * sig ** 2) * delta_t + (sig * sqrt(delta_t) * random.gauss(0, 1))))

        put_value = max(k - path[-1], 0)
        call_value = max(path[-1] - k, 0)
        list_2.append(put_value)
        list_1.append(call_value)
    p = np.average(list_2)
    c = np.average(list_1)
    return {'call_MC': c, 'put_MC': p}

'''
trial:
a = black_scholes_model(5200, 5200, 0.03, 0.25, 0.08)
b = monte_carlo_simulation(5200, 5200, 0.03, 0.25, 0.08, 20, 2000000)

print(a)
print(b)
'''


# Create a numpy array from the weight_lb list with the correct units. Multiply by 0.453592 to go from pounds to kilograms.
# Store the resulting numpy array as np_weight_kg.
# Use np_height_m and np_weight_kg to calculate the BMI of each player.
# Use the following equation:
# BMI = weight(kg) / height (m3)
# save the resulting numpy array as bmi
# Print out bmi.
# height and weight are available as regular lists

# Import numpy
import numpy as np

# Create array from height_in with metric units: np_height_m
np_height_m = np.array(height_in) * 0.0254

# Create array from weight_lb with metric units: np_weight_kg
np_weight_kg = np.array(weight_lb) * 0.453592

# Calculate the BMI: bmi
bmi = np_weight_kg / np_height_m ** 2

# Print out bmi
print(bmi)

01-introduction to python for data science/04-numpy/baseball-players-bmi.py


import numpy as np
from sklearn import linear_model
from sklearn import datasets

class Perceptron():
    def __init__(self,model='prime',max_iter=1000,lamb=10**-2):
        self.model=model
        self.max_iter=max_iter
        self.lamb=lamb

    def train(self,X_train,y_train):
        self.X_train=X_train
        self.y_train=y_train
        train_no,feature_no=X_train.shape
        W=np.zeros((feature_no,1))
        alpha=np.zeros((train_no,1))
        b=0
        flag=True
        iter_no=0
        while flag:
            iter_no+=1
            flag=False
            for i in range(train_no):
                if self.model=='dual':
                    W=np.zeros((feature_no,1))
                    for j in range(train_no):
                        W+=alpha[j]*y_train[j]*X_train[j].reshape(feature_no,1)
                    if y_train[i]*(X_train[i].dot(W)+b)<=0:
                        alpha[i]=alpha[i]+self.lamb
                        b=b+self.lamb*y_train[i]
                        flag=True
                        break
                if self.model=='prime':
                    if y_train[i]*(X_train[i].dot(W)+b)<=0:
                        W=W+self.lamb*y_train[i]*X_train[i].reshape(feature_no,1)
                        b=b+self.lamb*y_train[i]
                        flag=True
                        break

            if iter_no>self.max_iter:
                break
        self.W=W
        self.b=b
        self.alpha=alpha

    def predict(self,X_test):
        train_no,feature_no=self.X_train.shape
        if self.model=='prime':
            y_pred=np.sign(X_test.dot(self.W)+self.b)
        if self.model=='dual':
            W=np.zeros((feature_no,1))
            for j in range(train_no):
                W+=self.alpha[j]*self.y_train[j]*self.X_train[j].reshape(feature_no,1)
            y_pred=np.sign(X_test.dot(W)+self.b)
        return y_pred.ravel()

if __name__=='__main__':
#    X_train=np.array([[3,3],[4,3],[1,1]])
#    y_train=np.array([1,1,-1])
#    X_test=np.array([[100,100],[99,99]])

    index=np.random.permutation(150)
    iris=datasets.load_iris()
    X_train=iris['data'][:,(2,3)]
    y_train=(iris['target']==2).astype(np.float64)
    y_train[y_train==0]=-1
    y_train_1=y_train
    X_test=X_train
    X_train=X_train[index]
    y_train=y_train[index]

    model=Perceptron(model='prime',max_iter=10**3,lamb=10**-4)
    model.train(X_train,y_train)
    y_pred=model.predict(X_test)
    print('Perceptron',y_pred)
    print(sum(y_pred==y_train_1))

    model=linear_model.Perceptron()
    model.fit(X_train,y_train)
    y_pred=model.predict(X_test)
    print('sklearn',y_pred)
    print(sum(y_pred==y_train_1))

Supervised Machine Learning Algorithms/Perceptron.py


## Worksheet 1

import numpy as np
import numpy.linalg as la

# The first worksheet covers basic topics in linear algebra. There is also a basic question on nonlinear root-finding.

#### Answer Coding Question 3

def MatrixConditionCheck(A, MaxConditionNumber = 10.0):
    """Check the condition number of a matrix.
    Only write output to screen if the condition number is too high.
    Should return something, really."""

    ConditionNumber = la.cond(A)
    if ConditionNumber > MaxConditionNumber:
        print("The condition number of the matrix\n{0}\n"\
              "is too large (i.e., it is {1:.4} which is larger"\
              " than {2:.4}).\n".\
              format(A, ConditionNumber, MaxConditionNumber))

#### Answer Coding Question 4

def bisection(f, interval, tolerance = 1.e-10):
    """General bisection method for a function f of one variable.
    There must be at least one root within the interval.
    Default tolerance (width of the interval) is 1e-10."""

    assert len(interval) == 2

    # Get the endpoints of the interval
    [x_min, x_max] = interval

    # Values at the ends of the domain
    f_min = f(x_min)
    f_max = f(x_max)

    # Check that at least one root lies within the interval
    assert(f_min * f_max < 0.0)

    # The loop
    x_c = (x_min + x_max) / 2.0
    f_c = f(x_c)
    iteration = 0
    while ((x_max - x_min > tolerance) and \
               (np.abs(f_c) > tolerance) and \
               (iteration < 100)):
        iteration = iteration+1
        if f_min * f_c < 0.0:
            x_max = x_c
            f_max = f_c
        else:
            x_min = x_c
            f_min = f_c
        x_c = (x_min + x_max) / 2.0
        f_c = f(x_c)

    print("The root is approximately {0} where "\
          "f is {1:.4} (tolerance {2:.4})".format(x_c, f_c, tolerance))
    return x_c

# Now define the function whose root is to be found
def fn_worksheet1_q4(x):
    """Simple function defined in question, f(x) = tan(x) - exp(-x)."""

    return np.tan(x) - np.exp(-x)


import numpy as np
from numpy import newaxis
# Several arrays can be stacked together along different axes
print("<---- vstack and hstack ---->")
a = np.floor(10*np.random.random((2,2)))
b = np.floor(10*np.random.random((2,2)))
print("Array a : ",a)
print("Array b : ",b)

print("Vertical stack : ",np.vstack((a,b)))
print("Horizontal stack : ",np.hstack((a,b)))

# The function column_stack stacks 1D arrays as columns into a 2D array. It is equivalent to
# hstack only for 2D arrays
print("<---- column stack ---->")
print("Column stack : ",np.column_stack((a,b)))
a = np.array([2.,3.])
b = np.array([4.,5.])
# returns a 2D array
print("column stack on 1-D array : ",np.column_stack((a,b)))
# the result is different
print("hstack on 1-D array : ",np.hstack((a,b)))
# this allows to have a 2D columns vector
print("newaxis : ",a[:,newaxis])
print("column stack with newaxis : ",np.column_stack((a[:,newaxis],b[:,newaxis])))
print("hstack with newaxis : ",np.column_stack((a[:,newaxis],b[:,newaxis])))
# row stack
print("<---- rowstack ---->")
print("row stack using ma.row_stack : ",np.ma.row_stack((a,b)))

print("<---- dstack ---->")
# dstack : Stack arrays in sequence depth wise (along third axis).
a = np.array((1,2,3))
b = np.array((2,3,4))
print("1-D dstack : ",np.ma.dstack((a,b)))
a = np.array([[1],[2],[3]])
b = np.array([[2],[3],[4]])
print("2-D dstack : ",np.dstack((a,b)))

print("<---- stack ---->")
# Join a sequence of arrays along a new axis.
# The axis parameter specifies the index of the new axis in the dimensions of the result.
# For example, if axis=0 it will be the first dimension and if axis=-1 it will be the last dimension.
arrays = [np.random.randn(3, 4) for _ in range(10)]
print("stack with axis-0 : ",np.stack(arrays, axis=0).shape)
print("stack with axis-1 : ",np.stack(arrays, axis=1).shape)
print("stack with axis-(-1) : ",np.stack(arrays, axis=-1).shape)
a = np.array([1, 2, 3])
b = np.array([2, 3, 4])
print("1-D array stack : ",np.stack((a, b)))
print("1-D stack ith axis (-1) : ",np.stack((a, b), axis=-1))