How to get Stochastic Gradient Descent result in contour plot - python

import numpy as np
from matplotlib import pyplot as plt
xk = np.linspace(-1,1,100)
yk= 2 * xk + 3 + np.random.rand(len(xk))
x1,x2 = np.meshgrid(xk,yk)
F = (x1 - 2) ** 2 + 2 * (x2 - 3) ** 2
fig=plt.figure()
surf = fig.add_subplot(1,1,1, projection='3d')
surf.plot_surface(x1,x2,F)
surf.contour(x1,x2,F)
fig, surf=plt.subplots()
plt.contour(x1, x2, F, 20)
m = 0
c = 0
learning_rate=0.01
I think my problem to get the correct result is from here, but I cant find where is the problem
for k in range(10):
shuffel_index=np.random.permutation(len(xk))
xk = xk[shuffel_index]
yk = yk[shuffel_index]
for i in range(len(xk)):
grad_m = - 2 * xk[i] * (yk[i] - (np.dot(m,xk[i]) + c))
grad_c = - 2 * (yk[i] - (np.dot(m,xk[i])+c))
m = m - learning_rate * grad_m
c = c - learning_rate * grad_c
surf.plot(np.array([xk[0], yk[0]]),np.array([xk[1], yk[1]]),'ko-')
if (k != 10 or i != len(xk)):
surf.plot(np.array([xk[0], yk[0]]),np.array([xk[1], yk[1]]),'ko-')
plt.show()
This is my result for the above code
And I wish to get the result like I do for gradient descent algorithm. The example of my gradient descent result.
May I know where is my error?

Related

Gradient descent in matlab work but in python not work

Matlab version
For the contour plotting
[x1,x2\] = meshgrid(-30:0.5:30, -30:0.5:30);
F = (x1-2).^2 + 2\*(x2 - 3).^2;
figure;
surf(x1,x2,F);
hold on;
contour(x1,x2,F);
figure;
contour(x1,x2,F,20);
hold on;
For initialize the value of the matrix and vector
A = [1 0; 0 2];
AT = A';
b = [4; 12];
Nit = 100; % no of iteration of our GD
tol = 1e-5; % error tolerance
lr = 0.2; % learning rate
xk = [-20;-20\]; % initial x value
noIterations = 1;
gradErr = [];
The looping for the gradient descent
for k =1:Nit
x_old = xk;
xk = xk - lr*AT*(A*xk - b); % Main GD step
gradErr(k) = norm(AT*(A*xk-b),'fro');
if gradErr(k) < tol
break;
end
plot([x_old(1) xk(1)],[x_old(2) xk(2)],'ko-')
noIterations = noIterations + 1;
end
Python version
Contour plotting part
import numpy as np
import matplotlib.pyplot as plt
x1,x2 = np.meshgrid(np.arange(- 30,30+0.5,0.5),np.arange(- 30,30+0.5,0.5))
F = (x1 - 2) ** 2 + 2 * (x2 - 3) ** 2
fig=plt.figure()
surf=fig.gca(projection='3d')
surf.plot_surface(x1,x2,F)
surf.contour(x1,x2,F)
plt.show()
fig,surf=plt.subplots()
plt.contour(x1,x2,F,20)
plt.show()
Initialize the value of the matrix and vector
A = np.array([[1,0],[0,2]])
AT = np.transpose(A)
b = np.array([[4],[12]])
Nit = 100
tol = 1e-05
lr = 0.2
xk = np.array([[-10],[-10]])
noIterations = 1
gradErr = []
Main problem is here where the looping has the bug cause it cant run the coding
for k in range(Nit):
x_old = xk
xk = xk - lr*np.matmul(AT,np.matmul(A,xk - b))
gradErr[k] = np.linalg.norm(AT * (A * xk - b),'fro')
if gradErr[k] < tol:
break
plt.plot(np.array([x_old(1),xk(1)]),np.array([x_old(2),xk(2)]),'ko-')
noIterations = noIterations + 1
May I know what is the problem for my python version in the looping part cant work but in matlab version is work well?
To access k-th element of gradErr, it has to be pre-assign a positive length. In your case, it is initialized as an empty list, which is the cause of IndexError. A simple fix is to use gradErr=np.zeros(Nit) Full code after making proper modification is the following:
import numpy as np
import matplotlib.pyplot as plt
x1,x2 = np.meshgrid(np.arange(-30, 30+0.5, 0.5), np.arange(-30, 30+0.5, 0.5))
F = (x1 - 2) ** 2 + 2 * (x2 - 3) ** 2
fig=plt.figure()
surf = fig.add_subplot(1, 1, 1, projection='3d')
surf.plot_surface(x1,x2,F)
surf.contour(x1,x2,F)
plt.show()
fig, surf=plt.subplots()
plt.contour(x1, x2, F, 20)
plt.show()
A = np.array([[1,0], [0,2]])
AT = np.transpose(A)
b = np.array([[4], [12]])
Nit = 100
tol = 1e-05
lr = 0.2
xk = np.array([[-10], [-10]])
noIterations = 1
gradErr = np.zeros(Nit)
for k in range(Nit):
x_old = xk
xk = xk - lr * np.matmul(AT, np.matmul(A, xk - b))
gradErr[k] = np.linalg.norm(AT * (A * xk - b),'fro')
if gradErr[k] < tol:
break
plt.plot(np.array([x_old[0], xk[0]]),np.array([x_old[1], xk[1]]),'ko-')
noIterations = noIterations + 1

only size-1 arrays can be converted to Python scalars: Trying to plot circular orbit with equation of. circle

I'm relatively new to python so forgive me for any nonsense in my code. I am trying to program a circular orbit of a planet (I just used the mass of Uranus and the Sun) in python using equations from my Classical Mechanics textbook (John R. Taylor's Classical Mechanics). I figured I could just use the equations and graph a function, y, that equals the equations of a circle with c_squared being the radius and x being an array of values being used to plot the circle. Let me know how I can improve the code or I am even going in the right direction.
...
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
import math
fig = plt.figure()
ax = fig.add_subplot()
m_uranus = 8.681 * 10**(25)
m_sun = 1.989 * 10 **(30)
G = 6.67430 * 10**(-11)
mu = (m_uranus * m_sun)/(m_uranus + m_sun)
l = (1.7 * 10**(42)) * 1000 * 24 * 60 * 60
ang_squared = l ** 2
c = (ang_squared)/(G * m_uranus * m_sun * mu)
c_squared = c**2
print(m_sun, mu, m_uranus, ang_squared, c)
x = np.arange(-100, 100, 1)
y = math.sqrt(c_squared - x)
plt.plot(x, y)
plt.show()
...
As mentioned by #JohanC, use numpy np.sqrt() instead of math.sqrt() will fix your error, here the fix with (unnecessary libraries removed):
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot()
m_uranus = 8.681 * 10 ** 25
m_sun = 1.989 * 10 ** 30
G = 6.67430 * 10 ** (-11)
mu = (m_uranus * m_sun) / (m_uranus + m_sun)
l = (1.7 * 10 ** 42) * 1000 * 24 * 60 * 60
ang_squared = l ** 2
c = ang_squared / (G * m_uranus * m_sun * mu)
c_squared = c ** 2
print(m_sun, mu, m_uranus, ang_squared, c)
x = np.arange(-100, 100, 1)
y = np.sqrt(c_squared - x)
plt.plot(x, y)
plt.show()
Hope, this will help you by!

I want to have the pendulum blob in my double pendulum

In this code I want to have animation something like this. But I dont want the other pendulums that come into picture later. Just the initial one. Currently this is my output. This is the image after the animation completes. In the animation, I want to have a ball(blob) which plots the red lines and another one which plots the green lines.
import numpy as np
from numpy import cos, sin, arange, pi
import matplotlib.pyplot as plt
import matplotlib.animation as animation
h = 0.0002 #the change in runge kutta
figsize = 6
dpi = 1000
N = 200000 # iterations
L1=1 #length 1
L2=1.5 #lenth 2
m1=50 #mass of bob 1
m2=1 #mass of bob2
g = 9.81#gravity
theta_01 = (np.pi/180)*90
theta_02 = (np.pi/180)*60
w_1 = 0
w_2 = 0
# dw/dt function oft theta 1
def funcdwdt1(theta1,theta2,w1,w2):
cos12 = cos(theta1 - theta2)#for wrirting the main equation in less complex manner
sin12 = sin(theta1 - theta2)
sin1 = sin(theta1)
sin2 = sin(theta2)
denom = cos12**2*m2 - m1 - m2
ans = ( L1*m2*cos12*sin12*w1**2 + L2*m2*sin12*w2**2
- m2*g*cos12*sin2 + (m1 + m2)*g*sin1)/(L1*denom)
return ans
# dw/dt function oft thetas 2
def funcdwdt2(theta2,theta1,w1,w2):
cos12 = cos(theta1 - theta2)
sin12 = sin(theta1 - theta2)
sin1 = sin(theta1)
sin2 = sin(theta2)
denom = cos12**2*m2 - m1 - m2
ans2 = -( L2*m2*cos12*sin12*w2**2 + L1*(m1 + m2)*sin12*w1**2
+ (m1 + m2)*g*sin1*cos12 - (m1 + m2)*g*sin2 )/(L2*denom)
return ans2
# d0/dt function for theta 1
def funcd0dt1(w0):
return w0
# d0/dt function for theta 2
def funcd0dt2(w0):
return w0
X1= []
X2= []
Y1= []
Y2= []
def func(w1,w2, theta1,theta2):
for i in range(N):
k1a = h * funcd0dt1(w1) # gives theta1
k1b = h * funcdwdt1(theta1,theta2,w1,w2) # gives omega1
k1c = h * funcd0dt2(w2) # gives theta2
k1d = h * funcdwdt2(theta2,theta1,w1,w2) # gives omega2
k2a = h * funcd0dt1(w1 + (0.5 * k1b))
k2b = h * funcdwdt1(theta1 + (0.5 * k1a),theta2,w1,w2)
k2c = h * funcd0dt2(w2 + (0.5 * k1d))
k2d = h * funcdwdt2(theta2 + (0.5 * k1c),theta1,w1,w2)
k3a = h * funcd0dt1(w1 + (0.5 * k2b))
k3b = h * funcdwdt1(theta1 + (0.5 * k2a),theta2,w1,w2)
k3c = h * funcd0dt2(w2 + (0.5 * k2d))
k3d = h * funcdwdt2(theta2 + (0.5 * k2c),theta1,w1,w2)
k4a = h * funcd0dt1(w1 + k3b)
k4b = h * funcdwdt1(theta1 + k3a,theta2,w1,w2)
k4c = h * funcd0dt2(w2 + k3d)
k4d = h * funcdwdt2(theta2 + k3c,theta1,w1,w2)
#addidng the vakue aftyer the iterartions
theta1 += 1 / 6 * (k1a + 2 * k2a + 2 * k3a + k4a)
w1 +=1 / 6 * (k1b + 2 * k2b + 2 * k3b + k4b)
theta2 += + 1 / 6 * (k1c + 2 * k2c + 2 * k3c + k4c)
w2 += 1 / 6 * (k1d + 2 * k2d + 2 * k3d + k4d)
x1 = L1 * sin(theta1)
y1 = -L1 * cos(theta1)
x2 = x1 + L2 * sin(theta2)
y2 = y1 - L2 * cos(theta2)
X1.append(x1)
X2.append(x2)
Y1.append(y1)
Y2.append(y2)
return x1,y1,x2,y2
print(func(w_1, w_2, theta_01, theta_02))
fig, ax = plt.subplots()
l1, = ax.plot([], [])
l2, = ax.plot([],[])
ax.set(xlim=(-3, 3), ylim=(-2,2))
def animate(i):
l1.set_data(X1[:i], Y2[:i])
l2.set_data(X2[:i], Y2[:i])
return l1,l2,
ani = animation.FuncAnimation(fig, animate, interval = 5, frames=len(X1))
# plt.show()
ani.save('save.mp4', writer='ffmpeg')
Just add another line
l3, = ax.plot([],[], '-ob', lw=2, ms=8)
and in the animate function set its values to
l3.set_data([0,X1[i],X2[i]], [0,Y1[i],Y2[i]])
Adapt line-width and marker-size as necessary. This should draw filled circles at the pendulum positions and the origin with lines connecting them.
You should use Y1 in the l1 data. With a total pendulum length of 2.5, the vertical limits are too small. It is sufficient to use
h = 0.005 #the change in runge kutta
N = 5000 # iterations
to get an animation with realistic speed. Or combine several RK4 steps for each frame. For minimum error you can use h=1e-3, smaller step sizes only lead to the accumulation of floating point errors dominating the method error.

Adding the output of one graph to another graph

I would like to find a way to translate and add the bottom graph (from y = -20 to 0) onto the above graph (from y = 0-20) so that the final domain is between y = 0 to 20:
However, I am finding problems doing it, as the graph I used to draw the bottom graph (R12) has already a negative input, thus it will not show up on the positive y-axis. Here is my code:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
N = 1001
lower = 0
upper = 20
u = np.linspace(lower, upper, N)
t1a, t3a = np.meshgrid(u,-u)
t1, t3 = np.meshgrid(u,u)
omega = 10
delta = 5
tau = 2
mu = 1
t2 = 0.1
def g(t):
return delta * (omega ** 2) * (tau ** 2) * ((np.e ** (-t/tau))+(t/tau)-1)
R12 = 1 * (mu ** 4) * (np.e **(-1j * omega * (t3a-(t1a)))) * (np.e ** (-g(t1a)+g(t2)-g(t3a)-g(t1a+t2)-g(t2+t3a)+g(t1a+t2+t3a)))
R45 = 1 * (mu ** 4) * (np.e ** (-1j * omega * (t3+t1))) * (np.e ** (-g(t1)-g(t2)-g(t3)+g(t1+t2)+g(t2+t3)-g(t1+t2+t3)))
R12_fft = np.fft.fftshift((np.fft.fft2((R12)))) / np.sqrt(len(R12))
R45_fft = np.fft.fftshift((np.fft.fft2((R45)))) / np.sqrt(len(R45))
R_pure = (R12_fft + R45_fft)
plt.contourf(t1a,t3a,R12_fft, cmap = 'seismic')
plt.contourf(t1,t3,R45_fft, cmap = 'seismic')
plt.xlabel('${\omega}_{3}$', fontsize = 24)
plt.ylabel('${\omega}_{1}$', fontsize = 24)
plt.xlim(-20, 20)
plt.ylim(-20, 20)
plt.gca().set_aspect('equal', adjustable='box')
plt.colorbar()
plt.show()
As an example, if I try to do the simple adding:
plt.contourf(t1,t3,R_pure, cmap = 'seismic')
it basically gives me back the same shape of the graph. What I would like instead is superimposing the bottom graph onto the top and adding the output together. Is there any way I can achieve this? Thank you!
I feel like it's a bit too dumb, so it's probably wrong.
R_pure = (R12_fft + abs(R45_fft))

solve_ivp returning different outcome of odeint?

I am trying to solve a simple ODE so as to understand the new API of Scipy.
I wrote a routine for Runge Kutta of order 4 to write it and confirmed it with the old API odeint and it matched beautifully. But now that I am trying to get around the solve_ivp, it seems that is not working. What am I getting wrong?
import numpy as np
from matplotlib import pyplot as plt
from scipy.integrate import solve_ivp, odeint
import time
freq = np.arange(1, 10000, 100)
def g(q, t):
return -q ** 3 + np.sin(t)
a = 0
b = 10
npoints = 100
h = (b - a) / npoints
t = np.arange(a, b, h)
output1 = np.zeros(t.shape)
x = 0
for i in range(len(t)):
output1[i] = x
k1 = h * g(x, t[i])
k2 = h * g(x + 0.5 * k1, t[i] + 0.5 * h)
k3 = h * g(x + 0.5 * k2, t[i] + 0.5 * h)
k4 = h * g(x + k3, t[i] + 0.5 * h)
x = x + 1 / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
# ---------------Solving using odeint (old API)---------------#
y1_odeint = odeint(g, 0, t)
#---------------Solving using new API-------------#
y2=solve_ivp(g,(a,b),[0],t_eval=t)
# --------------------Representação gráfica--------------------------#
fig = plt.figure()
ax = fig.add_subplot(121)
ax1=fig.add_subplot(122)
ax.plot(t, output1,label="my own")
ax.plot(t,y1_odeint,label="odeint")
ax.plot(y2.t,np.squeeze(y2.y),label="new API")
ax.legend()
ax.set_title("Output")
ax1.plot(t,output1-np.squeeze(y1_odeint),label="|odeint-my own|")
ax1.legend()
plt.tight_layout()
plt.show()
Take another look at the docstring for solve_ivp. It expects the first argument of g to be t. By default, odeint uses the opposite convention. If you have a recent version of scipy, you can tell odeint that the first argument is t by giving it the argument tfirst=True.

Categories

Resources