Matlab cconv and circular convolution - matlab

My goal is to use Matlab to verify circular convolution calculations. I try to do this using cconv.
However, Matlab does not give the same answer to problems I know the answer for. Why?
An example is the circular convolution modulo 4 between [1, 2, 4, 5, 6] and [7, 8, 9, 3] as can be found in this paper by Abassi
According to the paper the answer is: [112, 91, 71, 88, 124].
But according to Matlab it is: [131, 127, 122, 106].
a = [1,2,4,5,6]
b = [7,8,9,3]
y = cconv(a,b,4)
ans =
131 127 122 106
What do I do wrong here?

y = cconv(a,b,5)
the 3rd argument is 5 not 4 for what the paper describes

The matlab code used in the Abbasi paper is written in the end :
A=fft(a);
B=fft(b);
y=ifft(A.*B);
I don't know why you use cconv if this doese the work.

Related

Matlab resample time series for specific times, rather than frequencies

I have the following problem in Matlab:
I have a time series which looks like this:
size(ts) = (n,2); % with n being the number of samples, the first column is the time, the second the value.
Let's say I have:
ts(:,1) = [0, 10, 20, 30, 40];
ts(:,2) = [1, 3, 10, 6, 11];
I would like to resample the signal above to get the interpolated values at different times. Say:
ts(:,1) = [0, 1, 3, 15, 40];
ts(:,2) = ???
I had a look at the Matlab functions for signal processing but they are all only relevant for regular sampling at various frequencies.
Is there a built in function which would give me the above, or do I have to compute the linear interpolation for each new desired time manually? If so, do you have a recommendation to do this efficiently using vecotrized code (just started Matlab a month ago so still 100% at ease with this and relying on for loops a lot still).
For a bit of context, I'm using a finite difference scheme in series to investigate a problem. The output of one FD scheme is fed into the following. Due to the nature of my problem, I have to change the time stepping from one FD to the next, and my time steps can be irregular.
Thanks.
Since your data are 1-D you can use interp1 to perform the interpolation. The code would work as follow:
ts = [0, 10, 20, 30, 40; % Time/step number
1, 3, 10, 6, 11]; % Values
resampled_steps = [0, 1, 3, 15, 40]; % Time for which we want resample
resampled_values = interp1(ts(1, :), ts(2, :), resampled_step);
% Put everything in an array to match initial format
ts_resampled = [resampled_steps; resampled_values];
Or you can alternatively, following the same idea:
ts = [0, 10, 20, 30, 40; % Time/step number
1, 3, 10, 6, 11]; % Values
% Create resample array
ts_resampled = zeros(size(ts));
ts_resampled(1, :) = [0, 1, 3, 15, 40];
% Interpolate
ts_resampled(2, :) = interp1(ts(1, :), ts(2, :), ts_resampled(1, :));
You can even choose the interpolation method you want, by passing a string to the interp1 function. The methods are listed here
Note that this only work if you re-sample with time stamps within your original scope. If you want them outside you have to tell the function how to extrapolate using the key word 'extrap'. Detail here

Translating np.einsum() to MATLAB

I am having trouble understanding the documentation of np.einsum(). How are subscripts interpreted?
I am trying to write np.einsum('a...c,b...c', Y, conj(Y)) where Y is a matrix of shape C, F, T on the original python. Also, due to previous implementation differences my MATLAB Y is of size [F, T, C].
What does 'a...c,b...c' index in each component? I am confused.
How do I write the same instructions in MATLAB?
Quoting from the einsum documentation page:
To enable and control broadcasting, use an ellipsis. Default NumPy-style broadcasting is done by adding an ellipsis to the left of each term, like np.einsum('...ii->...i', a). To take the trace along the first and last axes, you can do np.einsum('i...i', a), or to do a matrix-matrix product with the left-most indices instead of rightmost, one can do np.einsum('ij...,jk...->ik...', a, b).
Later, an example is given:
>>> a = np.arange(25).reshape(5,5)
>>> np.einsum('...j->...', a)
array([ 10, 35, 60, 85, 110])
The equivalent MATLAB code to this example would be:
>> a = reshape(0:24, [5,5]).';
>> sum(a,2).'
ans =
10 35 60 85 110
Several things to note:
The ellipsis operator (...) should not be understood as "range", but as "whatever needs to be there".
"Broadcasting" refers to automatic replication of an array along the relevant dimension so that the mathematical operation is defined. This is a feature that exists in MATLAB since R2016b (called "implicit expansion").
You may notice several transpose operations (.') in the MATLAB equivalent. This is because numpy arrays are row-major while MATLAB array are column-major. Practically, while the underlying data has the same sequential order, a numpy array appears transposed compared to MATLAB. The transpositions were done so that arrays appear the same in intermediate stages.
Another example from these docs is:
>>> a = np.arange(6).reshape((3,2))
>>> b = np.arange(12).reshape((4,3))
>>> np.einsum('ki,jk->ij', a, b)
array([[10, 28, 46, 64],
[13, 40, 67, 94]])
>>> np.einsum('ki,...k->i...', a, b)
array([[10, 28, 46, 64],
[13, 40, 67, 94]])
>>> np.einsum('k...,jk', a, b)
array([[10, 28, 46, 64],
[13, 40, 67, 94]])
Which can be written as follows in MATLAB:
A = reshape(0:5, [2 3]).';
B = reshape(0:11, [3 4]).';
A.' * B.'
permute(sum( permute(A, [3 1 2]) .* B,2), [3 1 2])
shiftdim(sum( shiftdim(A, -1) .* B, 2), 2)
Several things to note:
When going from np.einsum('ki,jk->ij', a, b) to np.einsum('ki,...k->i...', a, b) you can see that the j-th dimension is replaced with .... The fact that both these examples have a -> in them, means it's in explicit mode.
When going from np.einsum('ki,jk->ij', a, b) to np.einsum('k...,jk', a, b), you can see that now the i-th dimension is replaced with .... The omission of ->...j simply demonstrates implicit mode (where the output dimensions are ordered alphabetically).

xgboost linear regression (gblinear) wrong predictions

I am using the python xgboost library, and I am unable to get a simple working example using the gblinear booster:
M = np.array([
[1, 2],
[2, 4],
[3, 6],
[4, 8],
[5, 10],
[6, 12],
])
xg_reg = xgb.XGBRegressor(objective ='reg:linear', booster='gblinear')
X, y = M[:, :-1], M[:, -1]
xg_reg.fit(X,y)
plt.scatter(range(-5, 20), [xg_reg.predict([i]) for i in range(-5, 20)])
plt.scatter(M[:,0], M[:,-1])
plt.show()
Predictions are in blue, and real data in orange
Am I missing something?
I think the issue is that the model does not converge to the optimum with the configuration and the amount of data that you have chosen. GBM's do not use the boosting model to fit the target directly, but rather to fit the gradient and then to add a fraction of the prediction (fraction is equal to the learning rate) to the prediction from the previous step.
So the obvious ways to improve are: increase the learning rate, increase the number of iterations, increase the data size.
For example, this variant of your code gives already a better prediction:
X = np.expand_dims(range(1,7), axis=1)
y = 2*X
# note increased learning rate!
xg_reg = xgb.XGBRegressor(objective ='reg:linear', booster='gblinear', learning_rate=1)
xg_reg.fit(X, y, verbose=20, eval_set=[(X,y)])
plt.scatter(range(-5, 20), [xg_reg.predict([i]) for i in range(-5, 20)], label='prediction')
plt.scatter(X[:20,:], y[:20], label='target')
plt.legend()
plt.show()
This leads to the metric value of 0.872 on the training data (i've added evaluation in the fit function to see how does it change). This is further reduced to ~0.1, if you increase the number of samples from 7 to 70.

Matlabs xcorr function in c

I am using the function
in = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
lag = 8;
out = xcorr(in, lag)
it produces the output:
out = [175,000000000000, 238,000000000000, 308, 384, 465, 550, 638, 728, 819, 728, 638, 550, 465, 384, 308, 238, 175,000000000000];
I do not understand from Matlabs documentation how to get those values. Is there any kind of formula that I can use for that?
In general matlab documentation put the formulas in a chapter named More about, look at this chapter to understand which formula matlab implements.
This is the link to the More about chapter of the xcorr function.
https://it.mathworks.com/help/signal/ref/xcorr.html#bubr0h6
For greater clarity look at this code:
in = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
lag = 8;
N = length(in);
correlation = zeros(2*lag,1);
for m = -8:8
correlation(m+8+1) = sum(in.*[zeros(1,abs(m)) in(1:N-abs(m))]);
end
where sum(in.*[zeros(1,abs(m)) in(1:N-abs(m))]); computes the sum of the product beetween in and its shifted version. To compute the shifted version of in simply padding the first m elements with zero and the N-m element are in(1:N-m). I've used the abs because the lag m is either negative or positive.
Try the code and also print [zeros(1,abs(m)) in(1:N-abs(m))] for various value of m to understand better how look the shifted version of the vector.
For homework: why we use [zeros(1,abs(m)) in(1:N-abs(m))] and not [zeros(1,abs(m)) in(1:N)]?
P.s in this case you are calculating the autocorrelation, so the y vector is x.
For more details about the theory check the Reference chapter to see which books matlab refers.

Matlab "for loop" to create a matrix

I have a fairly large vector named blender. I have extracted n elements for which blender is greater than x (irrelevant). Now my difficulty is the following:
I am trying to create a (21 x n) matrix with each element of blender plus 10 things before, and the 10 things after.
element=find(blender >= 120);
I have been trying variations of the following:
for i=element(1:end)
Matrix(i)= Matrix(blender(i-10:i+10));
end
then I want to plot one column of the matrix at the time when I hit Enter.
This second part I can figure out later, but I would appreciate some help making the Matrix
Thanks
First, you can use "logical indexing" of your array, which uses a logical expression do address your vector. With blender = [2, 302, 35, 199, 781, 312, 8], it could look like this:
>> b_hi = blender(blender>=120)
b_hi =
302 199 781 312
Second, you can concatenate arrays like in b_padded = [1, 2, b_hi, 3, 4]. If b_hi was a column vector, you'd use semicolons instead of commas.
Third, there is a function reshape that allows you to turn the resulting vector into a matrix. doc reshape will tell you details. For example, to turn b_padded into a 2-by-4 matrix,
>> b_matrix = reshape(b_padded, 4, 2)
b_matrix =
1 302 781 3
2 199 312 4
will do. This means you can do all of the job without any for-loop. Note that transposing the result of reshape(b_padded, 2, 4) will give you the other possible 2-by-4 matrix. You obtain the transpose of a matrix A by A'. You will find out which one you want.
You need to create a new matrix, and use two indices so that Matlab knows it is assigning to a column in a 2D matrix.
NewMatrix = zeros(21, length(element));
for i = 1:length(element)
k = element(i);
NewMatrix(:,i)= Matrix(blender(k-10:k+10));
end