Why hessian is 0 when I expend vector to calculate? - python

Loss Function:
L = (XW-t)**2
t: means target value
w: weights, which is [w1, w2]
x: input, which is [x1, x2]
Therefore, L = (-t + w1x1 + w2x2)**2
I try to get Hessian function of it, which should be positive proved by others.
But I get the following result:
(-t + w1*x1 + w2*x2)**2
first grad:
(2*x1*(-t + w1*x1 + w2*x2),)
(2*x2*(-t + w1*x1 + w2*x2),)
Hessian:
[2*x1**2, 2*x1*x2]
[2*x1*x2, 2*x2**2]
Value: 0
Anyone knows why the value is 0?
Here is the code:
import numpy as np
from sympy import *
x1, x2, w1, w2, t = symbols("x1 x2 w1 w2 t")
# inp = Matrix(1, 2, [u, i])
# w = Matrix(2, 1, [w1, w2])
e1 = x1*w1 + x2*w2
# e2 = u*w3 + i*w4
# e3 = e1*w5 + e2*w6
L = (e1-t)**2
print("loss function: ", L)
all_symbols = [w1, w2]
first_diff = []
second_diff = []
for symbol in all_symbols:
first_diff.append(diff(L, symbol))
temp_diff = []
for symbol in all_symbols:
temp_diff.append(expand(diff(first_diff[-1], symbol)))
second_diff.append(temp_diff)
print("\nfirst grad:")
for function in zip(first_diff):
print(function)
print("\nHessian: ")
for elem in second_diff:
print(elem)
Hessian = Matrix(second_diff)
# print(Hessian)
print("\nValue: ", Hessian.det())

Related

How to minimize a value of a function by changing function parameters?

import numpy as np
x = np.array([1,2,3,4,5,6,7])
f1= np.array([1,2,3,4,5,6,7])
f2= np.array([1,2,3,4,5,6,7])
def func(w1,w2,x,f1,f2):
w1=1-w2
return np.std(x/(w1*f1+w2*f2))
i need my code to minimize func(w1,w2,x,f1,f2) by changing w1 and w2 then give me w1 and w2 values. w1 + w2 should be equal to 1.
Something like this might be what you need:
x = np.random.randint(1, 10, 7)
f1 = np.random.randint(1, 10, 7)
f2 = np.random.randint(1, 10, 7)
def func(w, x, f1, f2): # no need to pass w1 and w2 separately
return np.std(x / (w[0] * f1 + (1 - w[0]) * f2))
res = scipy.optimize.minimize(func, x0=[0.5], args=(x, f1, f2), bounds=[(0, 1)])
w1 = res.x[0]
w2 = 1 - w1
print("Optimal weights are", w1, w2)

Vectorizing a Vector-Valued Function

I have the following function:
def h_Y1(X, theta):
EF = X[0]
FF = X[1]
j = X[-2]
k = X[-1]
W = X[2:-2]
Sigma = theta[0]
sigma_xi2 = theta[1]
gamma_alpha = theta[2]
gamma_z = np.array(theta[3:])
gW = gamma_z # W
eps1 = EF - gamma_alpha * gW
if j == k:
eps2 = FF - (gamma_alpha**2)*gW - gW*sigma_xi2 - Sigma
eps3 = 0
else:
eps2 = 0
eps3 = FF - (gamma_alpha**2)*gW
h1 = [eps1 * Wk for Wk in W]
h2 = [eps2 * Wk for Wk in W]
h3 = [eps3 * Wk for Wk in W]
return np.concatenate([h1, h2, h3])
I need to execute the function for a range of values, which are stored in gmmarray. Specifically, I'd like the function to be run for each row of gmmarray as the function argument X, for a fixed theta.
I'm currently doing this using the following code:
import numpy as np
theta = [0.01, 1, 1, 0, 0]
gmmarray = np.random.random((1120451, 6))
test = np.apply_along_axis(h_Y1, 1, gmmarray, theta = init)
However, this is slow - it takes around 19 seconds. I tried vectorizing the function as follows:
Vh_Y1 = np.vectorize(h_Y1, signature = '(n),(j)->(i)')
test1 = Vh_Y1(gmmarray, init)
However, this still takes 16 seconds. Am I doing something wrong here or is there a way to speed things up further?
Thanks so much!
You can pass the full gmmarray as the X parameter. Then, instead of looping through each row of gmmarray, you can use vectorized operations on its columns.
Something like this:
def h_Y1_vectorized(X, theta):
EF, FF, W, j, k = np.hsplit(X, [1,2,4,5]) # Column vectors (except W)
Sigma, sigma_xi2, gamma_alpha, *gamma_z = theta
gW = (W # gamma_z)[:, None] # Ensure column vector
ga_gW = gamma_alpha * gW
FF_ga2gW = FF - gamma_alpha * ga_gW
eps1 = EF - ga_gW
j_equal_k = j == k
eps2 = np.where(j_equal_k, FF_ga2gW - gW * sigma_xi2 - Sigma, 0)
eps3 = np.where(j_equal_k, 0, FF_ga2gW)
h1 = eps1 * W
h2 = eps2 * W
h3 = eps3 * W
return np.hstack([h1, h2, h3])
Calling
>>> h_Y1_vectorized(gmmarray, theta)
produces the same result with roughly a 100x speed increase.

why these 2 python lists have different len's?

I have written the following code for adaptive step size RungeKutta RK 4th order integration method.
import numpy as np
import os
import matplotlib
from matplotlib import pyplot as plt
rhs_of_diff_Eq_str = "3 * t ** 2"
def first_derivative(t, y): # the first derivative of the function y(t)
first_derivative_value = 3 * t ** 2
return first_derivative_value
time_interval_lowerlimit = 0.0
time_interval_upperlimit = 1.0
dt = 0.01
ts = []
y = 0. # initial condition
t = 0. # initial condition
ys_step = ys_halfstep = ys_doublestep = ys = []
dy_min = 0.01
dy_max = 0.1
dt_min = 0.0001
y_tol = 0.0001
no_of_iterations = 0
while(t < 1):
no_of_iterations += 1
# for timestep = dt
k1 = first_derivative(t, y)
k2 = first_derivative(t + dt/2. , y + (dt/2.)*k1)
k3 = first_derivative(t + dt/2. , y + (dt/2.)*k2)
k4 = first_derivative(t + dt , y + dt *k3)
y_step = y + (dt/6.) * (k1 + 2*k2 + 2*k3 + k4)
ys_step.append(y_step) # for plotting y vs t, at the end of the script, after integration has finished
# for timestep = dt / 2
k1 = first_derivative(t, y)
k2 = first_derivative(t + dt/4. , y + (dt/4.)*k1)
k3 = first_derivative(t + dt/4. , y + (dt/4.)*k2)
k4 = first_derivative(t + dt/2. , y + (dt/2.)*k3)
y_halfstep = y + (dt/12.) * (k1 + 2*k2 + 2*k3 + k4)
ys_halfstep.append(y_halfstep)
# for timestep = dt * 2
k1 = first_derivative(t, y)
k2 = first_derivative(t + dt , y + dt * k1)
k3 = first_derivative(t + dt , y + dt * k2)
k4 = first_derivative(t + 2.*dt, y + 2.*dt * k3)
y_doublestep = y + (dt/3.) * (k1 + 2*k2 + 2*k3 + k4)
ys_doublestep.append(y_doublestep)
if (abs(y_step) <= y_tol): # fix the timestep to dt_min because otherwise we divide by 0 in comparisons below
if (dt != dt_min):
dt = dt_min
new_y = y_step
else: # can modify the timestep if needed
if ( (abs(y_step) > y_tol) and ( (abs(y_step - y_halfstep)/abs(y_step)) > dy_max ) ): # error is too large
dt = dt / 2.
new_y = y_halfstep
else:
if ( (abs(y_step) > y_tol) and ( (abs(y_step - y_doublestep)/abs(y_step)) < dy_min ) ) : # error too small, can increase dt
dt = 2. * dt
new_y = y_doublestep
else: # timestep is just right! keep it as it is and return y_step (i.e. the y-value computed using timestep = dt)
new_y = y_step
y = new_y
# print("y is :")
# print(y)
# print(len(y)) # error, object of type 'float' has no len()
ys.append(y)
# print("t is: ")
# print(t)
ts.append(t)
t += dt
print(len(ys)) #
print(len(ts)) #
print("no of iterations: ")
print(no_of_iterations)
plt.figure()
plt.plot(ts, ys, label='y values', color='red')
plt.xlabel('t')
plt.ylabel('y')
plt.title("RK4 adaptive step-size integration for dy/dt = f(y,t) \n" + "f(y,t) = " + rhs_of_diff_Eq_str)
plt.savefig("RK4_adaptive_step_size_results.pdf", bbox_inches='tight')
This results in error at the plotting instructions due to the 2 lists ts and ys having different number of elements.
I have been looking at the code for a while now and I don't see the reason why the ys always have 4 times the number of elements in the list ts after the script exits from the while-loop.
Can you please help me, maybe it's something obvious?
Thanks
The issues stile happen from this line ys_step = ys_halfstep = ys_doublestep = ys = [], there is a created four list but all refers the same memories and when you append the element one of that list it stile append the all that lists.
You can only change the as following:
ys_step = []
ys_halfstep = []
ys_doublestep = []
ys = []
it will worked.

How can I fix this error: TypeError: cannot unpack non-iterable int object

I'm getting TypeError: cannot unpack non-iterable int object in the line S, I, R = y of the function. I thought saving y as a matrix ([730, 3]) would solve this, it did not.
def SIRmodel(y,t):
S, I, R = y
return ([-alpha*S*I,alpha*S*I-beta*I,beta*I])
I call it below:
alpha=mygetrand(cdf,0,0.4,1.e-16)
beta = 1/11
t = np.linspace(0,730,1001) #two year time period
pop = 350000000 #population size
med_capacity = 250000
y=np.array([730,3])
x0=0
x1=0.4
def get_trajectory():
infec0 = pop*0.00001 #the initial infected
Iinit = (infec0/pop) #initial infected rate
Sinit = (pop - infec0)/pop #susceptable population
Rinit = 0
sol = rk4sys(SIRmodel,[Sinit,Iinit,Rinit],x0, x1)
hosp = np.zeros(3) #array of hospitalized
perc = [0.05, 0.1, 0.2]
return(sol)
sol = get_trajectory()
plt.plot(t,pop*sol[:,1],'r-',[0,730],[med_capacity,med_capacity],'b:');
#print(pop*soln[:,1])
The problem here is at the call sol = rk4sys(SIRmodel,[Sinit,Iinit,Rinit],x0, x1)
My rk4 is
def rk4sys(f, init, x0, x1):
h=(x0-x1)/730
vx = np.zeros(shape=(730,1))
vy = np.zeros(shape=(731,3))
vx[0] = x = x0 #pythonified assignment statements
vy[0,:] = y = init
for i in range(1, 730 + 1): #runge-kutta loop
k1 = f(x, y)
k2 = f(x + 0.5 * h, y + 0.5 * h* k1)
k3 = f(x + 0.5 * h, y + 0.5 * h* k2)
k4 = f(x + h, y + h* k3)
vx[i] = x = x0 + i * h
vy[i,:] = y = y + h*(k1 + k2 + k2 + k3 + k3 + k4) / 6.
return vx, vy
Swap the t and y values in the SIRmodel call
def SIRmodel(t,y):

Quadratic formula find value for x1 and x2 given an equation

Given a nested list l containing coefficient values, I'm trying to calculate the quadratic formula to find zeros of x, denoted as x1,x2. I have a for loop that loops through this list and gives me the value for a,b and c from the nested list:
import math as m
l = [[1,2,1],[9,12,4],[1,-7,0],[1,2,-3]]#nested list
for x in l:
q = x[1]*x[1]-4*x[0]*x[2] #b*b - 4*a*c
q_sr = m.sqrt(q)#root of q
x1 = (-x[1] + q_sr)/(2*x[0])#[1]=b and [0]=a
x2 = (-x[1] - q_sr)/(2*x[0])#[1]=b and [0]=a
eq = x[0]**2 + 2*x[1] + 1*x[2] #equation that im trying to get the x1 and x2
print("a verdier: ", x[0])
print("b verdier: ", x[1])
print("c verdier: ", x[2])
print("x1 verdier: ", x1)
print("x2 verdier: ", x2)
Here, x[0],x[1] and x[2] are the corresponding positions in the list l, e.g., 0 = a, 1=b and 2=c. This all works and i get the right values for x1 and x2.
I'm having trouble calculating the zeroes (x1, x2). How do I calculate these values?
The complex math module is great for things like this.
import cmath
def quadratic(a, b, c):
d = float(b**2 - 4*a*c)
x1 = ((-b)-cmath.sqrt(d))/(2*a)
x2 = ((-b)+cmath.sqrt(d))/(2*a)
return [x.real if (x.imag == 0.0) else x for x in [x1, x2]]
For fun
class Quadratic:
def __init__(self, a, b, c):
self.a, self.b, self.c = a, b, c
self.d = float(self.b ** 2 - 4*self.a*self.c)
self.x1 = ((-b)-cmath.sqrt(self.d))/(2*a)
self.x2 = ((-b)+cmath.sqrt(self.d))/(2*a)
#property
def solution(self):
return [x.real if x.imag == 0.0 else x for x in [self.x1, self.x2]]
def __str__(self):
return "X1 = {}, X2 = {}".format(*self.solution)
myList = [[1, 2, 1], [9, 12, 4], [1, -7, 0], [1, 2, -3]]
for _ in myList:
print Quadratic(*_)
Here is a modified and commented version of you code that should help you understand what you did.
from math import sqrt
coef_list = [[1,2,1],[9,12,4],[1,-7,0],[1,2,-3]]
# This following "for loop" will compute solutions x1 and x2
# for any quadratic equation summarized in your coef_list. In your
# coef_list you have the following equations:
# y(x) = 1*x^2 + 2*x + 1
# y(x) = 9*x^2 + 12*x + 4
# ...
# y(x) = 1*x^2 + 2*x -3
for coef in coef_list:
a, b, c = coef # extract a, b and c from the inner lists
q = b**2 - 4*a*c
# In case q > 0 you have two solutions
if q > 0:
q_sqrt = sqrt(q)
x1 = (-b + q_sqrt)/(2*a)#[1]=b and [0]=a
x2 = (-b - q_sqrt)/(2*a)#[1]=b and [0]=a
# In case q = 0 you have only one solution
elif q == 0:
x1 = -b/(2*a)
x2 = x1
# In case q < 0 you have no real solution
else:
raise ValueError("q is negative.")
# print at all iteration of the loop to have solutions for every
# equation in given in coef_list
print "x1 = ", x1
print "x2 = ", x2
print "a = ", a, ", b = ", b, "and c = ",c
print "-----"
# You don't need the next line since the equation you are trying to solve is
# is defined in coef_list at line 0 (i.e. coef_list[0])
#eq = x[0]**2 + 2*x[1] + 1*x[2] #equation that im trying to get the x1 and x2

Categories