Assign variable in pytorch - gpu

I'd like to know if it is possble to the following code, but now using pytorch, where dtype = torch.cuda.FloatTensor. There's the code straight python (using numpy): Basically I want to get the value of x that produces the min value of fitness.
import numpy as np
import random as rand
xmax, xmin = 5, -5
pop = 30
x = (xmax-xmin)*rand.random(pop,1)
y = x**2
[minz, indexmin] = np.amin(y), np.argmin(y)
best = x[indexmin]
This is my attempt to do it:
import torch
dtype = torch.cuda.FloatTensor
def fit (x):
return x**2
def main():
pop = 30
xmax, xmin = 5, -5
x = (xmax-xmin)*torch.rand(pop, 1).type(dtype)+xmin
y = fit(x)
[miny, indexmin] = torch.min(y,0)
best = x[indexmin]
main()
The last part where I define the variable best as the value of x with index equal to indexmin it doesn't work. What am I doing wrong here.
The following messenge appears: RuntimeError:
expecting vector of indices at /opt/conda/conda-bld/pytorch_1501971235237/work/pytorch-0.1.12/torch/lib/THC/generic/THCTensorIndex.cu:405

You can simply do as follows.
import torch
dtype = torch.cuda.FloatTensor
def main():
pop, xmax, xmin = 30, 5, -5
x = (xmax-xmin)*torch.rand(pop, 1).type(dtype)+xmin
y = torch.pow(x, 2)
[miny, indexmin] = y.min(0)
best = x.squeeze()[indexmin] # squeeze x to make it 1d
main()

Related

Lambdify a function in two variables and plot a surface

I have a function f(x,y) where t is a parameter. I'm trying to plot the function where t = 1 for x and y values ranging from -5 to 5. The plot doesn't render.
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook
C = sv.CoordSys3D("")
x, y, z = C.base_scalars()
t = sp.symbols("t")
f = sp.sin(2*sp.pi*t)*sp.exp(-(x-3*sp.sin(sp.pi*t))**2 -(y-3*sp.cos(sp.pi*t))**2)
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(projection='3d')
X = np.linspace(-5,5,100)
Y = np.linspace(-5,5,100)
xvals, yvals = np.meshgrid(X,Y)
zvals = sp.lambdify((x,y),f.subs(t,1),"numpy")(xvals,yvals)
ax.plot_surface(xvals,yvals,zvals)
plt.show()
I get an error 'int' object has no attribute 'ndim' which I don't know how to solve.
The problem is that when you execute f.subs(t,1) it returns a number (zero in this case). So, f=0 is the expression that you are going to lambdify. Let's see the function generated by lambdify:
import inspect
print(inspect.getsource(sp.lambdify((x,y),f.subs(t,1),"numpy")))
# def _lambdifygenerated(Dummy_25, Dummy_24):
# return 0
So, no matter the values and shape of xvals and yvals, that numerical function will always return 0, which is an integer number.
However, ax.plot_surface requires zvals to have the same shape as xvals or yval. Luckily, we can easily fix that with a simple if statement:
import sympy as sp
import sympy.vector as sv
import numpy as np
import matplotlib.pyplot as plt
C = sv.CoordSys3D("")
x, y, z = C.base_scalars()
t = sp.symbols("t")
f = sp.sin(2*sp.pi*t)*sp.exp(-(x-3*sp.sin(sp.pi*t))**2 -(y-3*sp.cos(sp.pi*t))**2)
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(projection='3d')
X = np.linspace(-5,5,100)
Y = np.linspace(-5,5,100)
xvals, yvals = np.meshgrid(X,Y)
zvals = sp.lambdify((x,y),f.subs(t,1),"numpy")(xvals,yvals)
# if zvals is just a number, create a proper matrix
if not isinstance(zvals, np.ndarray):
zvals = zvals * np.ones_like(xvals)
ax.plot_surface(xvals,yvals,zvals)
plt.show()
The fact that this doesn't render is bug in lambdify that it doesn't work well for constant expressions.
Your real problem though is that the expression you are trying to plot is just zero:
In [5]: f
Out[5]:
2 2
- (x_ - 3⋅sin(π⋅t)) - (y_ - 3⋅cos(π⋅t))
ℯ ⋅sin(2⋅π⋅t)
In [6]: f.subs(t, 1)
Out[6]: 0

plotting a graph of a sequence and get a dimension error

I'm trying to create a plot in Python to illustrate how my sequence changes as n grows. I get a dimension error. How can I fix this?
My code:
import matplotlib.pyplot as plt
import numpy as np
x = np.zeros(101)
x[0] = 0
for n in range(0, 101):
x[n] = x[n-1] - n
if x[n] < 0:
x[n] = x[n-1] + n
y = set(x)
print(y)
i = np.linspace(0, 100)
plt.plot(y, i, 'g')
Error:
ValueError: x and y must have same first dimension, but have shapes (1,) and (50,)
The problem is you are using plt.plot with a set and because of that its saying first dimension has shape (1,). The x-argument in plt.plot should be a array-like or scalar you can read more in the documentation so you can convert it to a list:
y = list(set(x))
Also you need to make sure that the for each value in y there is a corresponding value in i (y and i need to be the same shape). So you need to set np.linspace to return len(y) values:
i = np.linspace(0, 100, len(y))
The code:
import matplotlib.pyplot as plt
import numpy as np
x = np.zeros(101)
x[0] = 0
for n in range(0,101):
x[n] = x[n-1] - n
if x[n]<0:
x[n] = x[n-1] + n
y = list(set(x))
i = np.linspace(0, 100, len(y))
plt.plot(y, i,'g')
plt.show()
Output:

Assign torch.cuda.FloatTensor

I'd like to know how can I do the following code, but now using pytorch,
where dtype = torch.cuda.FloatTensor. There's the code straight python (using numpy):
import numpy as np
import random as rand
xmax, xmin = 5, -5
pop = 30
x = (xmax-xmin)*rand.random(pop,1)
y = x**2
[minz, indexmin] = np.amin(y), np.argmin(y)
best = x[indexmin]
This is my attempt to do it:
import torch
dtype = torch.cuda.FloatTensor
def fit (position):
return position**2
def main():
pop = 30
xmax, xmin = 5, -5
x= (xmax-xmin)*torch.rand(pop, 1).type(dtype)+xmin
y = fit(x)
[miny, indexmin] = torch.min(y,0)
best = x[indexmin]
print(best)
The last part where I define the variable best as the value of x with index equal to indexmin it doesn't work. What am I doing wrong here.
The following messenge appears:
RuntimeError: expecting vector of indices at /opt/conda/conda-bld/pytorch_1501971235237/work/pytorch-0.1.12/torch/lib/THC/generic/THCTensorIndex.cu:405
The above code works fine in pytorch 0.2. Let me analyze your code so that you can identify the problem.
x= (xmax-xmin)*torch.rand(pop, 1).type(dtype)+xmin
y = fit(x)
Here, x and y is a 2d tensor of shape 30x1. In the next line:
[miny, indexmin] = torch.min(y,0)
The returned tensor miny is a 2d tensor of shape 30x1 and indexmin is a 1d tensor of size 1. So, when you execute:
best = x[indexmin]
It (probably) gives error (in old pytorch version) because x is a 2d tensor of shape 30x1 and indexmin is a 1d tensor of size 1. To resolve this error, you can simply do:
best = x.squeeze()[indexmin] # x.squeeze() returns a 1d tensor of size `30`
Please note, a 2d tensor of shape 30x1 is same as a 1d tensor of size 30. So, you can modify your program as follows.
import torch
dtype = torch.cuda.FloatTensor
def main():
pop, xmax, xmin = 30, 5, -5
x= (xmax-xmin)*torch.rand(pop).type(dtype)+xmin
y = torch.pow(x, 2)
minz, indexmin = y.min(0)
best = x[indexmin]
print(best)
main()

getting matplotlib radar plot with pandas

I am trying to go a step further by creating a radar plot like this question states. I using the same source code that the previous question was using, except I'm trying to implement this using pandas dataframe and pivot tables.
import numpy as np
import pandas as pd
from StringIO import StringIO
import matplotlib.pyplot as plt
from matplotlib.projections.polar import PolarAxes
from matplotlib.projections import register_projection
def radar_factory(num_vars, frame='circle'):
"""Create a radar chart with `num_vars` axes."""
# calculate evenly-spaced axis angles
theta = 2 * np.pi * np.linspace(0, 1 - 1. / num_vars, num_vars)
# rotate theta such that the first axis is at the top
theta += np.pi / 2
def draw_poly_frame(self, x0, y0, r):
# TODO: use transforms to convert (x, y) to (r, theta)
verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
return plt.Polygon(verts, closed=True, edgecolor='k')
def draw_circle_frame(self, x0, y0, r):
return plt.Circle((x0, y0), r)
frame_dict = {'polygon': draw_poly_frame, 'circle': draw_circle_frame}
if frame not in frame_dict:
raise ValueError, 'unknown value for `frame`: %s' % frame
class RadarAxes(PolarAxes):
"""Class for creating a radar chart (a.k.a. a spider or star chart)
http://en.wikipedia.org/wiki/Radar_chart
"""
name = 'radar'
# use 1 line segment to connect specified points
RESOLUTION = 1
# define draw_frame method
draw_frame = frame_dict[frame]
def fill(self, *args, **kwargs):
"""Override fill so that line is closed by default"""
closed = kwargs.pop('closed', True)
return super(RadarAxes, self).fill(closed=closed, *args, **kwargs)
def plot(self, *args, **kwargs):
"""Override plot so that line is closed by default"""
lines = super(RadarAxes, self).plot(*args, **kwargs)
for line in lines:
self._close_line(line)
def _close_line(self, line):
x, y = line.get_data()
# FIXME: markers at x[0], y[0] get doubled-up
if x[0] != x[-1]:
x = np.concatenate((x, [x[0]]))
y = np.concatenate((y, [y[0]]))
line.set_data(x, y)
def set_varlabels(self, labels):
self.set_thetagrids(theta * 180 / np.pi, labels)
def _gen_axes_patch(self):
x0, y0 = (0.5, 0.5)
r = 0.5
return self.draw_frame(x0, y0, r)
register_projection(RadarAxes)
return theta
def day_radar_plot(df):
fig = plt.figure(figsize=(6,6))
#adjust spacing around the subplots
fig.subplots_adjust(wspace=0.25,hspace=0.20,top=0.85,bottom=0.05)
ldo,rup = 0.1,0.8 #leftdown and right up normalized
ax = fig.add_axes([ldo,ldo,rup,rup],polar=True)
N = len(df['Group1'].unique())
theta = radar_factory(N)
polar_df = pd.DataFrame(df.groupby([df['Group1'],df['Type'],df['Vote']]).size())
polar_df.columns = ['Count']
radii = polar_df['Count'].get_values()
names = polar_df.index.get_values()
#get the number of unique colors needed
num_colors_needed = len(names)
#Create the list of unique colors needed for red and blue shades
Rcolors = []
Gcolors = []
for i in range(num_colors_needed):
ri=1-(float(i)/float(num_colors_needed))
gi=0.
bi=0.
Rcolors.append((ri,gi,bi))
for i in range(num_colors_needed):
ri=0.
gi=1-(float(i)/float(num_colors_needed))
bi=0.
Gcolors.append((ri,gi,bi))
from_x = np.linspace(0,0.95,num_colors_needed)
to_x = from_x + 0.05
i = 0
for d,f,R,G in zip(radii,polar_df.index,Rcolors,Gcolors):
i = i+1
if f[2].lower() == 'no':
ax.plot(theta,d,color=R)
ax.fill(theta,d,facecolor=R,alpha=0.25)
#this is where I think i have the issue
ax.axvspan(from_x[i],to_x[i],color=R)
elif f[2].lower() == 'yes':
ax.plot(theta,d,color=G)
ax.fill(theta,d,facecolor=G,alpha=0.25)
#this is where I think i have the issue
ax.axvspan(from_x[i],to_x[i],color=G)
plt.show()
So, let's say I have this StringIO that has a list of Group1 voting either yes or no and they are from a numbered type..these numbers are arbitrary in labeling but just as an example..
fakefile = StringIO("""\
Group1,Type,Vote
James,7,YES\nRachael,7,YES\nChris,2,YES\nRachael,9,NO
Chris,2,YES\nChris,7,NO\nRachael,9,NO\nJames,2,NO
James,7,NO\nJames,9,YES\nRachael,9,NO
Chris,2,YES\nChris,2,YES\nRachael,7,NO
Rachael,7,YES\nJames,9,YES\nJames,9,NO
Rachael,2,NO\nChris,2,YES\nRachael,7,YES
Rachael,9,NO\nChris,9,NO\nJames,7,NO
James,2,YES\nChris,2,NO\nRachael,9,YES
Rachael,9,YES\nRachael,2,NO\nChris,7,YES
James,7,YES\nChris,9,NO\nRachael,9,NO\n
Chris,9,YES
""")
record = pd.read_csv(fakefile, header=0)
day_radar_plot(record)
The error I get is Value Error: x and y must have same first dimension.
As I indicated in my script, I thought I had a solution for it but apparently I'm going by it the wrong way. Does anyone have any advice or guidance?
Since I'm completely lost in what you are trying to do, I will simply provide a solution on how to draw a radar chart from the given data.
It will answer the question how often have people voted Yes or No.
import pandas as pd
import numpy as np
from StringIO import StringIO
import matplotlib.pyplot as plt
fakefile = StringIO("""\
Group1,Type,Vote
James,7,YES\nRachael,7,YES\nChris,2,YES\nRachael,9,NO
Chris,2,YES\nChris,7,NO\nRachael,9,NO\nJames,2,NO
James,7,NO\nJames,9,YES\nRachael,9,NO
Chris,2,YES\nChris,2,YES\nRachael,7,NO
Rachael,7,YES\nJames,9,YES\nJames,9,NO
Rachael,2,NO\nChris,2,YES\nRachael,7,YES
Rachael,9,NO\nChris,9,NO\nJames,7,NO
James,2,YES\nChris,2,NO\nRachael,9,YES
Rachael,9,YES\nRachael,2,NO\nChris,7,YES
James,7,YES\nChris,9,NO\nRachael,9,NO\n
Chris,9,YES""")
df = pd.read_csv(fakefile, header=0)
df["cnt"] = np.ones(len(df))
pt = pd.pivot_table(df, values='cnt', index=['Group1'],
columns=['Vote'], aggfunc=np.sum)
fig = plt.figure()
ax = fig.add_subplot(111, projection="polar")
theta = np.arange(len(pt))/float(len(pt))*2.*np.pi
l1, = ax.plot(theta, pt["YES"], color="C2", marker="o", label="YES")
l2, = ax.plot(theta, pt["NO"], color="C3", marker="o", label="NO")
def _closeline(line):
x, y = line.get_data()
x = np.concatenate((x, [x[0]]))
y = np.concatenate((y, [y[0]]))
line.set_data(x, y)
[_closeline(l) for l in [l1,l2]]
ax.set_xticks(theta)
ax.set_xticklabels(pt.index)
plt.legend()
plt.title("How often have people votes Yes or No?")
plt.show()

How to drop connecting lines where the function is discontinuous

I'm plotting some functions that have several discontinuities. Each function is given as a list. I want to connect points with lines only where the function is continuous.
Here is a simplified example of what plot is doing.
x=linspace(0,1,100)
y=zeros(100)
y[x<0.5] = x[x<0.5]
y[x>=0.5] = 1 + x[x>=0.5]
plot(x, y, '-o')
There is a discontinuity at x=0.5, but plot connects all points with lines regardless.
My functions are different of course. They typically have several discontinuities in different places. The criterion for the discontinuity is simple. Say, if the function jumps by more than 0.5, I assume it is discontinuous at that point.
Is there an option in plot to tell it to drop the connecting lines between the points where the function is discontinuous? I recall being able to do that easily with gnuplot.
use nan to break the line into multiple segments:
import numpy as np
from pylab import *
x=linspace(0,1,100)
y=zeros(100)
y[x<0.5] = x[x<0.5]
y[x>=0.5] = 1 + x[x>=0.5]
pos = np.where(np.abs(np.diff(y)) >= 0.5)[0]
x[pos] = np.nan
y[pos] = np.nan
plot(x, y, '-o')
Edit:
to insert nan at discontinuities:
pos = np.where(np.abs(np.diff(y)) >= 0.5)[0]+1
x = np.insert(x, pos, np.nan)
y = np.insert(y, pos, np.nan)
Here is my suggestion for plotting tan(x):
import matplotlib.pyplot as plt
from math import *
x_lim = 3*pi/2
y_lim = 5
n = 1000
X = []
Y = []
Z = []
for i in range(0,2*n):
x = -x_lim + i*x_lim/n
y = tan(x)
if y<y_lim and y>-y_lim:
X.append(x)
Y.append(y)
else:
if len(X)>0 and len(Y)>0:
Z.append([X,Y])
del X,Y
X = []
Y = []
for i in range(0, len(Z)):
plt.plot(Z[i][0],Z[i][1])
plt.grid(True)
plt.show()