Understanding pytorch autograd - pytorch

I am trying to understand how pytorch autograd works. If I have functions y = 2x and z = y**2, if I do normal differentiation, I get dz/dx at x = 1 as 8 (dz/dx = dz/dy * dy/dx = 2y*2 = 2(2x)*2 = 8x). Or, z = (2x)**2 = 4x^2 and dz/dx = 8x, so at x = 1, it is 8.
If I do the same with pytorch autograd, I get 4
x = torch.ones(1,requires_grad=True)
y = 2*x
z = y**2
x.backward(z)
print(x.grad)
which prints
tensor([4.])
where am I going wrong?

You're using Tensor.backward wrong. To get the result you asked for you should use
x = torch.ones(1,requires_grad=True)
y = 2*x
z = y**2
z.backward() # <-- fixed
print(x.grad)
The call to z.backward() invokes the back-propagation algorithm, starting at z and working back to each leaf node in the computation graph. In this case x is the only leaf node. After calling z.backward() the computation graph is reset and the .grad member of each leaf node is updated with the gradient of z with respect to the leaf node (in this case dz/dx).
What's actually happening in your original code? Well, what you've done is apply back-propagation starting at x. With no arguments x.backward() would simply result in x.grad being set to 1 since dx/dx = 1. The additional argument (gradient) is effectively a scale to apply to the resulting gradient. In this case z=4 so you get x.grad = z * dx/dx = 4 * 1 = 4. If interested, you can check out this for more information on what the gradient argument does.

If you still have some confusion on autograd in pytorch, Please refer this:
This will be basic xor gate representation
import numpy as np
import torch.nn.functional as F
inputs = torch.tensor(
[
[0, 0],
[0, 1],
[1, 0],
[1, 1]
]
)
outputs = torch.tensor(
[
0,
1,
1,
0
],
)
weights = torch.randn(1, 2)
weights.requires_grad = True #set it as true for gradient computation
bias = torch.randn(1, requires_grad=True) #set it as true for gradient computation
preds = F.linear(inputs, weights, bias) #create a basic linear model
loss = (outputs - preds).mean()
loss.backward()
print(weights.grad) # this will print your weights

Related

How to compute the distance of data points to decision boundary when using the EllipticEnvelope of sklearn?

How can I compute the euclidean distance to the boundary decision of the EllipticEnvelope? Here is my code :
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.covariance import EllipticEnvelope
from sklearn.model_selection import train_test_split
feature, output = "temperature", "consumption"
data = pd.DataFrame(np.random.normal(0,15, size=(2355,2)), columns=[feature, output])
X = data[[feature, output]]
X_train, X_test = train_test_split(X, shuffle=True, train_size=0.8)
model = EllipticEnvelope(contamination=0.18)
model.fit(X_train)
# extract the model predictions
y_pred = pd.Series(model.predict(X), index=X.index, name="anomaly")
# define the meshgrid : X = (u,v).T
u_min, u_max = X_train.iloc[:, 0].min() - 1.5, X_train.iloc[:, 0].max() + 1.5
v_min, v_max = X_train.iloc[:, 1].min() - 1.5, X_train.iloc[:, 1].max() + 1.5
n_points = 500
u = np.linspace(u_min, u_max, n_points)
v = np.linspace(v_min, v_max, n_points)
U, V = np.meshgrid(u, v)
# evaluate the decision function on the meshgrid
W = model.decision_function(np.c_[U.ravel(), V.ravel()])
W = W.reshape(U.shape)
plt.figure(figsize=(20,6))
a = plt.contour(U, V, W, levels=[0], linewidths=2, colors="black")
b = plt.scatter(X.loc[y_pred == 1].iloc[:, 0], X.loc[y_pred == 1].iloc[:, 1], c="yellowgreen", edgecolors='k')
c = plt.scatter(X.loc[y_pred == -1].iloc[:, 0], X.loc[y_pred == -1].iloc[:, 1], c="tomato", edgecolors='k')
plt.legend([a.collections[0], b, c], ['learned frontier', 'regular observations', 'abnormal observations'], bbox_to_anchor=(1.05, 1))
plt.axis('tight')
plt.show()
Edits
I am able to get the decision boundary points using the following code. Now, the problem can be solved by computing numerically the distance.
for item in a.collections:
for i in item.get_paths():
v = i.vertices
x = v[:, 0]
y = v[:, 1]
I have an obvious solution. Getting all data points d and compute the euclidean distance between d and e=(x,y). But, it is a brute-force technique.. :D I will continue my research !
Another solution would be to fit an ellipse and compute the distance using the formula described by #epiliam there : https://math.stackexchange.com/questions/3670465/calculate-distance-from-point-to-ellipse-edge
I will provide one solution tomorrow based on the brute-force. It seems to work well for small dataset (n_rows < 10000). I did not test for larger ones.

Why numpy treats really small numbers as zeros?

I'm working on an optimization task. consider "sphere benchmark function" in two dimensions.
import numpy as np
x = y = 0
X = np.array([x, y])
cost = np.sum(X**2)
print(cost) # zero
The cost of function would be zero where x and y are zero. however consider this example:
import numpy as np
X = np.array([-6.5333928195191023e-163, 2.7628829205465545e-163])
Y = X**2 # [0, 0]
cost = np.sum(Y) # zero
print(cost) # zero
The cost shouldn't be zero, but it is. Is there anyway to fix this issue?
Normal floating point precision will truncate your numbers to zero. If you really want to use values so small you can do:
X = np.array([-6.5333928195191023e-163, 2.7628829205465545e-163], dtype=np.longdouble)
Y = X**2 # [0, 0]
cost = np.sum(Y) # zero
print(cost) # zero
>> 5.0318743766791623303e-325

How to rewrite the depth to normal map code using tensorflow keras for bath of inputs?

Here is my python code to convert the depth map (256,256,1) to normal map (256,256,3) for single input. I want to rewrite the code in tensorflow keras for batch of predicted depth.
zy, zx = np.gradient(d_im)
# You may also consider using Sobel to get a joint Gaussian smoothing and differentation
# to reduce noise
zx = cv2.Sobel(d_im, cv2.CV_64F, 1, 0, ksize=5)
zy = cv2.Sobel(d_im, cv2.CV_64F, 0, 1, ksize=5)
normal = np.dstack((-zx, -zy, np.ones_like(d_im)))
n = np.linalg.norm(normal, axis=2)
normal[:, :, 0] /= n
normal[:, :, 1] /= n
normal[:, :, 2] /= n
# offset and rescale values to be in 0-255
normal += 1
normal /= 2
normal *= 255
cv2.imwrite("normal2.png", normal[:, :, ::-1])
Here d_im is the depth numpy array of above mentioned shape and normal2.png is the 3 channel image of normal values calculated from the depth map.
I solved it:
def depth_to_normal(y_pred):
zy, zx = tf.image.image_gradients(y_pred)
normal_ori = tf.concat([-zx, -zy, tf.ones_like(y_pred)], 3)
new_normal = tf.square(zx) + tf.square(zy) + 1
normal = normal_ori/new_normal
normal += 1
normal /= 2
return normal

Ransac ground plane segmentation for lidar data

I want to use the ransac algorithm to segment the ground plane lidar rings, I use the python-pcl to do that, but I got the false results as the pictures showed below.
As we known, the lidar data has many rings of the ground plane, it can't find the right plane of the ground, but it found the plane above the ground. The reason I can guess is that maybe the ground of lidar is very sparse, and the plane above the ground has the points numbers more than the ground, so the algorithm find the false results. The code can be list as below:
seg = point_cloud.make_segmenter()
seg.set_optimize_coefficients(True)
seg.set_model_type(pcl.SACMODEL_PLANE)
seg.set_method_type(pcl.SAC_RANSAC)
seg.set_distance_threshold(0.1)
indices, model = seg.segment()
It's uncertain whether is the problem I guessed, so if anyone met the problem before, please tell me. And I don't know how to solve the problem, there is few information about the lidar rings segmentation, does anyone know how to solve it?
And is there other methods to do the lidar ground segmentation which I can get the code?
enter image description here
Try this -
from mpl_toolkits.mplot3d.axes3d import *
import matplotlib.pyplot as plt
from sklearn import linear_model
fig = plt.figure("Pointcloud")
ax = Axes3D(fig)
ax.grid = True
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
xyz = get_points()# here xyz is a 3d numpy array
if xyz.size > 10:
XY = xyz[:, :2]
Z = xyz[:, 2]
ransac = linear_model.RANSACRegressor(residual_threshold=0.01)
ransac.fit(XY, Z)
inlier_mask = ransac.inlier_mask_
outlier_mask = np.logical_not(inlier_mask)
inliers = np.zeros(shape=(len(inlier_mask), 3))
outliers = np.zeros(shape=(len(outlier_mask), 3))
a, b = ransac.estimator_.coef_
d = ransac.estimator_.intercept_
for i in range(len(inlier_mask)):
if not outlier_mask[i]:
inliers[i] = xyz[i]
else:
outliers[i] = xyz[i]
min_x = np.amin(inliers[:, 0])
max_x = np.amax(inliers[:, 0])
min_y = np.amin(inliers[:, 1])
max_y = np.amax(inliers[:, 1])
x = np.linspace(min_x, max_x)
y = np.linspace(min_y, max_y)
X, Y = np.meshgrid(x, y)
Z = a * X + b * Y + d
AA = ax.plot_surface(X, Y, Z, cmap='binary', rstride=1, cstride=1,
alpha=1.0)
BB = ax.scatter(outliers[:, 0], outliers[:, 1], outliers[:, 2],c='k', s
=1)
CC = ax.scatter(inliers[:, 0], inliers[:, 1], inliers[:, 2], c='green',
s=1)
plt.show()
Or please provide your dataset.Also play around with the ransac parameters

How to get a theano function to return the an array of the same length as another tensor variable

I am really new to Theano, and I am just trying to figure out some basic functionality. I have a tensor variable x, and i would like the functio to return a tensor variable y of the same shape, but filled with value 0.2. I am not sure how to define y.
For example if x = [1,2,3,4,5], then I would like y = [0,2, 0,2, 0,2, 0,2, 0.2]
from theano import tensor, function
y = tensor.dmatrix('y')
masked_array = function([x],y)
There's probably a dozen different ways to do this and which is best will depend on the context: how this piece of code/functionality fits into the wider program.
Here's one approach:
import theano
import theano.tensor as tt
x = tt.vector()
y = tt.ones_like(x) * 0.2
f = theano.function([x], outputs=y)
print f([1, 2, 3, 4, 5])

Resources