I would like to implement the following regression function with theano scan as an expression to compute delta coefficients. However, I can't figure out how to pass the previous inputs into the current step.
where is a delta coefficient at time computed in terms of the corresponding static coefficients to . The value of is set using the configuration parameter DELTAWINDOW. The same formula is applied to the delta coefficients to obtain acceleration coefficients except that in this case the window size is set by ACCWINDOW. Since equation 5.16 relies on past and future speech parameter values, some modification is needed at the beginning and end of the speech. The default behaviour is to replicate the first or last vector as needed to fill the regression window.
The DELTAWINDOW I am using is 9, and the input is a matrix eg:
[[1,1,1,1,1,1,1,1,1],
[2,2,2,2,2,2,2,2,2],
[3,3,3,3,3,3,3,3,3],
[4,4,4,4,4,4,4,4,4]]
The reference material can be found at this link
An attempt at creating a theano expression for this.
import numpy as np
import theano
import theano.tensor as T
def delta_theta(theta, curr_delta, t, THETA, Y):
"""
compute a delta theta component at delta time step t
:param theta: current time step theta component
:param curr_delta: current accumulated delta_t
:param t: current delta_t to be computed
:param THETA: window size
:param Y: input sequence
:return: delta theta component for time step t
"""
# accumulator is shaped (1, no_features), transpose to perform column wise element operations
temp = curr_delta.T
d_theta = theta * (Y[:, THETA + t + theta] - Y[:, THETA + t - theta]) / (2 * theta * theta)
temp += d_theta
temp = temp.astype('float32')
curr_delta = temp.T
return curr_delta
def delta_t(t, THETA, Y):
"""
compute delta at time step t
:param t: time step
:param THETA: window size
:param Y: sequence in shape (number_of_features, time_step)
:return: delta coefficient at time step t
"""
theta = T.arange(1, THETA + 1, dtype='int32')
results, _ = theano.scan(delta_theta, outputs_info=T.zeros_like(Y),
sequences=theta, non_sequences=[t, THETA, Y])
# only interested in the final results, discard the intermediate values
final_results = results[-1]
return final_results
def delta_coeff(A, theta):
"""
compute delta coefficients given a sequence.
:param A: input sequence in shape (time_step, number_of_features)
:param theta: window size
:return: delta coefficients for the input sequence
"""
# transpose and repeat
X = A.T
Y = T.concatenate([T.extra_ops.repeat(X[:, 0], theta).reshape((X.shape[0], theta)),
X, T.extra_ops.repeat(X[:, -1], theta).reshape((X.shape[0], theta))], axis=1)
results, _ = theano.scan(delta_t, sequences=[T.arange(0, X.shape[1], dtype='int32')], non_sequences=[theta, Y])
# transpose the results back to shape (time_step, number_of_features)
return results[:, :, -1].reshape(A.shape)
def main():
"""
test runner, computes delta for an array of sequences
:return: None
"""
A = T.tensor3('A', dtype='float32')
theta = T.iscalar('theta')
# compute delta coefficients for multiple sequences
results, updates = theano.scan(delta_coeff, sequences=A, non_sequences=theta)
compute_deltas = theano.function([A, theta], outputs=results, updates=updates)
seqs = np.array([[[1, 2, 3, 4, 5],
[10, 12, 13, 14, 15],
[300, 1, 23, 56, 22]],
[[1, 1, 1, 1, 1],
[1, 1, 100, 1, 1],
[1, 1, 1, 1, 1]]], dtype='float32')
res = compute_deltas(seqs, 1)
print(res)
if __name__ == '__main__':
main()
If there are any mistakes, please point them out, thank you!
Related
In the following curve, I would like to extend the measurements beyond x=1 in order to have a better estimate of the green curve compared to red line.
Note: I do not have the analytical form of the function but only x, y data sets in the range (0, 1).
Is there any package in python in order to extrapolate a curve beyond some value given that we have the interpolated form of the curve?
Here is my attempt assuming a linear drop:
from scipy.interpolate import interp1d
import numpy as np
CURVE_CUT_INDEX = #the index corresponding to x=1 in the x array
def extrapolator_function(x_vals, y_vals, x_list):
interpolator = interp1d(x_vals, y_vals, kind='cubic')
x_1 = x_vals[-1]
y_1 = interpolator(x_1)
y_grad, x_grad = (np.gradient(y_vals, np.arange(y_vals.size)),
np.gradient(x_vals, np.arange(x_vals.size)))
slope = np.divide(y_grad, x_grad, out=np.zeros_like(y_grad), where=x_grad != 0)[-1]
x_out = x_list[CURVE_CUT_INDEX + 1:]
y_pred = np.array([slope * (x-x_1) + y_1 for x in x_out])
return x_vals, y_vals, x_out, y_pred
def plotter(ax, x_list, y_list):
x_vals, y_vals = x_list[0:CURVE_CUT_INDEX + 1], y_list(x_list)[0:CURVE_CUT_INDEX + 1]
x_vals, y_vals, x_out, y_pred = extrapolator_function(x_vals, y_vals, x_list)
return ax.plot(x_vals, y_vals, 'g-', x_out, y_pred, 'r-', alpha=1, lw=2)
which will result in the following extrapolation scheme (which is not what I want).
I want to rotate all the images in my Dataset with a random degree between [0,180]. If I compose a transformation function and pass my images to this function in the __getitem__ function of my Dataset class. Does this mean:
every single image is randomly rotated?
images in each batch get rotated with an identical degree but this degree randomly changes across batches (calls)?
I would appreciate it if you could clarify this for me.
In mapped datasets, __getitem__ is used to select a single element from the dataset.
The way random transformations work in PyTorch/Torchvision is they apply a unique random transformation each time the transform is called. This means:
Every single image in your dataset is indeed randomly rotated but not by the same amount.
Additionally images in a batch get different transformations. In other words, elements in the batch won't share the same transformation parameters.
Here is a minimal example with a dummy dataset:
class D(Dataset):
def __init__(self, n):
super().__init__()
self.n = n
self.transforms = T.Lambda(lambda x: x*randint(0,10))
def __len__(self):
return self.n
def __getitem__(self, index):
x = self.transforms(index)
return x
Here you can see the random transformer inter and intra batches:
>>> dl = DataLoader(D(10), batch_size=2)
>>> for i, x in enumerate(dl):
... print(f'batch {i}: elements {2*i} and {2*i+1} = {x.tolist()}')
batch 0: elements 0 and 1 = [0, 2]
batch 1: elements 2 and 3 = [14, 27]
batch 2: elements 4 and 5 = [32, 40]
batch 3: elements 6 and 7 = [60, 0]
batch 4: elements 8 and 9 = [80, 27]
I am trying to make every point above 25.2 a Gaussian peak with the width of 2 on the x axis.
enter image description here
not so sure how to generate the Gaussian curves in python.
Full example of how to generate a Gaussian distribution, for an arbitrary number of axis and number of center locations. It requires the packages matplotlib, scipy and numpy.
The module can be controlled by:
dim for the number of dimensions (axis).
fwhm full width half maximum (estimates the width of the Gaussian distribution.)
centers a np.array or list of the indices, that are the center(s) of the Gaussian distribution.
import matplotlib.cm as mpl_cm
import matplotlib.colors as mpl_colors
import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial.distance import cdist
class Gaussian:
def __init__(self, size):
self.size = size
self.center = np.array(self.size) / 2
self.axis = self._calculate_axis()
def _calculate_axis(self):
"""
Generate a list of rows, columns over multiple axis.
Example:
Input: size=(5, 3)
Output: [array([0, 1, 2, 3, 4]), array([[0], [1], [2]])]
"""
axis = [np.arange(size).reshape(-1, *np.ones(idx, dtype=np.uint8))
for idx, size in enumerate(self.size)]
return axis
def update_size(self, size):
""" Update the size and calculate new centers and axis. """
self.size = size
self.center = np.array(self.size) / 2
self.axis = self._calculate_axis()
def create(self, dim=1, fwhm=3, center=None):
""" Generate a gaussian distribution on the center of a certain width. """
center = center if center is not None else self.center[:dim]
distance = sum((ax - ax_center) ** 2 for ax_center, ax in zip(center, self.axis))
distribution = np.exp(-4 * np.log(2) * distance / fwhm ** 2)
return distribution
def creates(self, dim=2, fwhm=3, centers: np.ndarray = (None,)):
""" Combines multiple gaussian distributions based on multiple centers. """
centers = np.array(centers).T
indices = np.indices(self.size).reshape(dim, -1).T
distance = np.min(cdist(indices, centers, metric='euclidean'), axis=1)
distance = np.power(distance.reshape(self.size), 2)
distribution = np.exp(-4 * np.log(2) * distance / fwhm ** 2)
return distribution
#staticmethod
def plot(distribution, show=True):
""" Plotter, in case you do not know the dimensions of your distribution, or want the same interface. """
if len(distribution.shape) == 1:
return Gaussian.plot1d(distribution, show)
if len(distribution.shape) == 2:
return Gaussian.plot2d(distribution, show)
if len(distribution.shape) == 3:
return Gaussian.plot3d(distribution, show)
raise ValueError(f"Trying to plot {len(distribution.shape)}-dimensional data, "
f"Only 1D, 2D, and 3D distributions are valid.")
#staticmethod
def plot1d(distribution, show=True, vmin=None, vmax=None, cmap=None):
norm = mpl_colors.Normalize(
vmin=vmin if vmin is not None else distribution.min(),
vmax=vmax if vmin is not None else distribution.max()
)
cmap = mpl_cm.ScalarMappable(norm=norm, cmap=cmap or mpl_cm.get_cmap('jet'))
cmap.set_array(distribution)
c = [cmap.to_rgba(value) for value in distribution] # defines the color
fig, ax = plt.subplots()
ax.scatter(np.arange(len(distribution)), distribution, c=c)
fig.colorbar(cmap)
if show: plt.show()
return fig
#staticmethod
def plot2d(distribution, show=True):
fig, ax = plt.subplots()
img = ax.imshow(distribution, cmap='jet')
fig.colorbar(img)
if show: plt.show()
return fig
#staticmethod
def plot3d(distribution, show=True):
m, n, c = distribution.shape
x, y, z = np.mgrid[:m, :n, :c]
out = np.column_stack((x.ravel(), y.ravel(), z.ravel(), distribution.ravel()))
x, y, z, values = np.array(list(zip(*out)))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Standalone colorbar, directly creating colorbar on fig results in strange artifacts.
img = ax.scatter([0, 0], [0, 0], [0, 0], c=[0, 1], cmap=mpl_cm.get_cmap('jet'))
img.set_visible = False
fig.colorbar(img)
ax.scatter(x, y, z, c=values, cmap=mpl_cm.get_cmap('jet'))
if show: plt.show()
return fig
Example
gaussian = Gaussian(size=(20,))
dist = gaussian.create(dim=1, centers=(1,)
gaussian.plot1d(dist, show=True)
Your problem
In order to get a solution that fits your question, the following code would work:
import numpy as np
arr = np.random.randint(0, 28, (25,))
gaussian = Gaussian(size=arr.shape)
centers = np.where(arr > 25.2)
distribution = gaussian.creates(dim=len(arr.shape), fwhm=2, centers=centers)
gaussian.plot(distribution, show=True)
For this the centers are determined by the condition arr > 25.2. Note that if there are no values, the next lines will crash. In order to get a width of 2 the value fwhm is put on 2, but you can alter this until you get the width that you want, or use Finding the full width half maximum of a peak.
I have found a few posts on the subject here, but most of them did not have a useful answer.
I have a 3D NumPy dataset [images number, x, y] in which the probability that the pixel belongs to a class is stored as a float (0-1). I would like to correct the wrong segmented pixels (with high performance).
The probabilities are part of a movie in which objects are moving from right to left and possibly back again. The basic idea is that I fit the pixels with a Gaussian function or comparable function and look at around 15-30 images ( [i-15 : i+15 ,x, y] ). It is very probable that if the previous 5 pixels and the following 5 pixels are classified in this class, this pixel also belongs to this class.
To illustrate my problem I add a sample code, the results were calculated without the usage of numba:
from scipy.optimize import curve_fit
from scipy import exp
import numpy as np
from numba import jit
#jit
def fit(size_of_array, outputAI, correct_output):
x = range(size_of_array[0])
for i in range(size_of_array[1]):
for k in range(size_of_array[2]):
args, cov = curve_fit(gaus, x, outputAI[:, i, k])
correct_output[2, i, k] = gaus(2, *args)
return correct_output
#jit
def gaus(x, a, x0, sigma):
return a*exp(-(x-x0)**2/(2*sigma**2))
if __name__ == '__main__':
# output_AI = [imageNr, x, y] example 5, 2, 2
# At position [2][1][1] is the error, the pixels before and after were classified to the class but not this pixel.
# The objects do not move in such a speed, so the probability should be corrected.
outputAI = np.array([[[0.1, 0], [0, 0]], [[0.8, 0.3], [0, 0.2]], [[1, 0.1], [0, 0.2]],
[[0.1, 0.3], [0, 0.2]], [[0.8, 0.3], [0, 0.2]]])
correct_output = np.zeros(outputAI.shape)
# I correct now in this example only all pixels in image 3, in the code a loop runs over the whole 3D array and
# corrects every image and every pixel separately
size_of_array = outputAI.shape
correct_output = fit(size_of_array, outputAI, correct_output)
# numba error: Compilation is falling back to object mode WITH looplifting enabled because Function "fit" failed
# type inference due to: Untyped global name 'curve_fit': cannot determine Numba type of <class 'function'>
print(correct_output[2])
# [[9.88432346e-01 2.10068763e-01]
# [6.02428922e-20 2.07921125e-01]]
# The wrong pixel at position [0][0] was corrected from 0.2 to almost 1, the others are still not assigned
# to the class.
Unfortunately numba does NOT work. I always get the following error:
Compilation is falling back to object mode WITH looplifting enabled because Function "fit" failed type inference due to: Untyped global name 'curve_fit': cannot determine Numba type of <class 'function'>
** ------------------------------------------------------------------------**
Update 04.08.2020
Currently I have this solution for my problem in mind. But I am open for further suggestions.
from scipy.optimize import curve_fit
from scipy import exp
import numpy as np
import time
def fit_without_scipy(input):
x = range(input.size)
x0 = outputAI[i].argmax()
a = input.max()
var = (input - input.mean())**2
return a * np.exp(-(x - x0) ** 2 / (2 * var.mean()))
def fit(input):
x = range(len(input))
try:
args, cov = curve_fit(gaus, x, outputAI[i])
return gaus(x, *args)
except:
return input
def gaus(x, a, x0, sigma):
return a * exp(-(x - x0) ** 2 / (2 * sigma ** 2))
if __name__ == '__main__':
nr = 31
N = 100000
x = np.linspace(0, 30, nr)
outputAI = np.zeros((N, nr))
correct_output = outputAI.copy()
correct_output_numba = outputAI.copy()
perfekt_result = outputAI.copy()
for i in range(N):
perfekt_result[i] = gaus(x, np.random.random(), np.random.randint(-N, 2*N), np.random.random() * np.random.randint(0, 100))
outputAI[i] = perfekt_result[i] + np.random.normal(0, 0.5, nr)
start = time.time()
for i in range(N):
correct_output[i] = fit(outputAI[i])
print("Time with scipy: " + str(time.time() - start))
start = time.time()
for i in range(N):
correct_output_numba[i] = fit_without_scipy(outputAI[i])
print("Time without scipy: " + str(time.time() - start))
for i in range(N):
correct_output[i] = abs(correct_output[i] - perfekt_result[i])
correct_output_numba[i] = abs(correct_output_numba[i] - perfekt_result[i])
print("Mean deviation with scipy: " + str(correct_output.mean()))
print("Mean deviation without scipy: " + str(correct_output_numba.mean()))
Output [with nr = 31 and N = 100000]:
Time with scipy: 193.27853846549988 secs
Time without scipy: 2.782526969909668 secs
Mean deviation with scipy: 0.03508043754489116
Mean deviation without scipy: 0.0419951370808896
In the next step I would try to speed up the code even more with numba. Currently this does not work because of the argmax function.
Curve_fit eventually calls into either least_squares (pure python) or leastsq (C extension). You have three options:
figure out how to make numba-jitted code talk to a C extension which powers leastsq
extract relevant parts of least_squares and numba.jit them
implement the LowLevelCallable support for least_squares or minimize.
None of these is easy. OTOH all of these would be interesting to a wider audience if successful.
I'm trying to do a multi linear regression algorithm . My data has two features (size of the house in the first column, number of bedrooms in the second column) and here is the head of my data set (the third column is the price of the house):
[[2.10400e+03 3.00000e+00 3.99900e+05]
[1.60000e+03 3.00000e+00 3.29900e+05]
[2.40000e+03 3.00000e+00 3.69000e+05]
[1.41600e+03 2.00000e+00 2.32000e+05]
[3.00000e+03 4.00000e+00 5.39900e+05]]
I wrote the following algorithm to compute the cost :
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
data = np.loadtxt('data2.txt', delimiter=',')
y_data = list()
for i in range(len(data)):
y_data.append(data[i][2])
#Convert our list to numpy arrays
y_data = np.asarray(y_data)
x_data = data[:, 0:2]
#applying feature scaling
for i in range(len(x_data)):
#Size of the house
x_data[i][0] = (x_data[i][0] - np.mean(x_data[:, 0])) / np.std(x_data[:, 0])
#Number of rooms
x_data[i][1] = (x_data[i][1] - np.mean(x_data[:, 1])) / np.std(x_data[:, 1])
#Adding a column of ones to our data
x_data = np.c_[np.ones(len(x_data)), x_data]
def cost(x, y, theta):
m = len(x)
predictions = np.arange(97).reshape(97, 1)
for i in range(len(x)):
predictions[i] = (x[i] * theta).sum()
sqrErrors = (np.subtract(predictions, y)) ** 2
return (1 / ( 2 * m)) * sqrErrors.sum()
theta = [[0],
[0],
[0]
]
The cost functions returns a value of 6361101029137.691 and when i run the gradient descent it gets larger. So what's the problem and how can i fix it please? Thanks