What does std(A, 0, 3) mean? - matlab

I am running the following code in which I am generating ten 4 x 4 matrix with random values.
A = zeros(4,4,10);
for idx = 1:size(A,3)
A(:,:,idx) = [1 2 3 4; 5 6 7 8; 9 10 11 12; 0 0 0 1].*randn(4,4)
end
X = std(A, 0, 3)
X = std(A, 0, 1) gives the standard deviation of each column and
X = std(A, 0, 2) gives the standard deviation of each row.
What does X = std(A, 0, 3) give?
I am getting a 4x4 matrix value answer as follows
4.0479 2.7137 1.8706 1.2579
4.9812 9.0766 7.2079 4.1866
1.0548 2.7205 3.3140 3.8712
0 0 0 0.8496

The X = std(A, 0, 3) is the standard deviation across the third dimension.
The 0 argument is the degrees of freedom for the bias normalization. In this case the denominator is N-1
If you use 1, it’s going to be N
From the documentation:
w — Weight
0 (default) | 1 | vector
Weight, specified as one of these values:
0 — Normalize by N-1, where N is the number of observations. If there is only one observation, then the weight is 1.
1 — Normalize by N.
Vector made up of nonnegative scalar weights corresponding to the dimension of A along which the standard deviation is calculated.

Related

How to reduce coefficients to their lowest possible integers using Matlab - Balancing Chemical Equations

I am attempting to develop a Matlab program to balance chemical equations. I am able to balance them via solving a system of linear equations. Currently my output is a column vector with the coefficients.
My problem is that I need to return the smallest integer values of these coefficients. For example, if [10, 20, 30] was returned. I want [1, 2, 3] to be returned.
What is the best way to accomplish this?
I want this program to be fully autonomous once it is fed a matrix with the linear system. Thus I can not play around with the values, I need to automate this from the code. Thanks!
% Chemical Equation in Matrix Form
Chem = [1 0 0 -1 0 0 0; 1 0 1 0 0 -3 0; 0 2 0 0 -1 0 0; 0 10 0 0 0 -1 0; 0 35 4 -4 0 12 1; 0 0 2 -1 -3 0 2]
%set x4 = 1 then Chem(:, 4) = b and
b = Chem(:, 4); % Arbitrarily set x4 = 1 and set its column equal to b
Chem(:,4) = [] % Delete the x4 column from Chem and shift over
g = 1; % Initialize variable for LCM
x = Chem\b % This is equivalent to the reduced row echelon form of
% Chem | b
% Below is my sad attempt at factoring the values, I divide by the smallest decimal to raise all the values to numbers greater than or equal to 1
for n = 1:numel(x)
g = x(n)*g
M = -min(abs(x))
y = x./M
end
I want code that will take some vector with coefficients, and return an equivalent coefficient vector with the lowest possible integer coefficients. Thanks!
I was able to find a solution without using integer programming. I converted the non-integer values to rational expressions, and used a built-in matlab function to extract the denominator of each of these expressions. I then used a built in matlab function to find the least common multiples of these values. Finally, I multiplied the least common multiple by the matrix to find my answer coefficients.
% Chemical Equation in Matrix Form
clear, clc
% Enter chemical equation as a linear system in matrix form as Chem
Chem = [1 0 0 -1 0 0 0; 1 0 1 0 0 -3 0; 0 2 0 0 -1 0 0; 0 10 0 0 0 -1 0; 0 35 4 -4 0 -12 -1; 0 0 2 -1 -3 0 -2];
% row reduce the system
C = rref(Chem);
% parametrize the system by setting the last variable xend (e.g. x7) = 1
x = [C(:,end);1];
% extract numerator and denominator from the rational expressions of these
% values
[N,D] = rat(x);
% take the least common multiple of the first pair, set this to the
% variable least
least = lcm(D(1),D(2));
% loop through taking the lcm of the previous values with the next value
% through x
for n = 3:numel(x)
least = lcm(least,D(n));
end
% give answer as column vector with the coefficients (now factored to their
% lowest possible integers
coeff = abs(least.*x)

fmincon - too many constraints - MATLAB

Suppose I have a fmincon function. As we know from matlab documentation we can impose linear and nonlinear constraints.
Suppose now I have a function of 3 parameters to optimize.
And I want 3 of them to be greater than 0 and 1 of them to be greater than -1 I would need 4 constraints but I get an error.
Simple example (working code):
A=eye(4)
A(4,4)=-1;
b=100*ones(4,1)
b(4,1)=+1
fun = #(x)100*(x(2)-x(1)^2)^2 + (1-x(1))^2+x(3);
fmincon(fun,[0,0,0],A,b)
The error is
Error using fmincon (line 287)
A must have 3 column(s).
It is strange that A can only have n constraints (that you could add with non linear)
Thanks
Your function fun expects exactly three inputs, i.e. the vector x will always be 3x1. So your starting point must be a 3x1 vector, not 4x1. The fmincon function allows you to specify any number of linear constraints of the form Ax ≤ b. Here, the Ax is a matrix multiplication: each column in A corresponds to one of the dimensions of x, thus A has to have exactly three columns. The number of rows can be any arbitrary number - though of course b will have to have the same dimension!
Small example: if you have the inequality 3*x + 4*y - z ≤ 1, then the first row of A is [3, 4, -1]. And the first entry of b is 1. Now, let's make up an additional constraint, e.g. y ≤ 4, so you have to add a row [0, 1, 0] to A and 4 to b. Your matrices are
A = [3, 4, -1;
0, 1, 0];
b = [1; 4];
In your case, you want more conditions than variables. You can do that by calling eye with two parameters: number of rows and number of columns:
>> A = eye(4, 3);
A =
1 0 0
0 1 0
0 0 1
0 0 0
and manually add the last constraint:
A(4,:) = [0, 0, -1];
To implement the constraint, that all parameters have to be greater than 0, and z has to be smaller than 1, you can create your matrices as follows:
A = -eye(4, 3);
A(4,:) = [0, 0, 1];
b = [zeros(3,1); 1];
i.e. the equations are:
-1 * x ≤ 0, which equals x ≥ 0
-1 * y ≤ 0, which equals y ≥ 0
-1 * z ≤ 0, which equals z ≥ 0
z ≤ 1
now, you can use fmincon:
>>fmincon(fun, zeros(3,1), A, b);
ans =
1.0000
1.0000
0.0000
Instead of treating the the two absolute constraints as 4 separate linear constrains why not treat them as a 2 nonlinear constrains specifically. x^2 < 9 ?

Finding the column index for the 1 in each row of a matrix

I have the following matrix in Matlab:
M = [0 0 1
1 0 0
0 1 0
1 0 0
0 0 1];
Each row has exactly one 1. How can I (without looping) determine a column vector so that the first element is a 2 if there is a 1 in the second column, the second element is a 3 for a one in the third column etc.? The above example should turn into:
M = [ 3
1
2
1
3];
You can actually solve this with simple matrix multiplication.
result = M * (1:size(M, 2)).';
3
1
2
1
3
This works by multiplying your M x 3 matrix with a 3 x 1 array where the elements of the 3x1 are simply [1; 2; 3]. Briefly, for each row of M, element-wise multiplication is performed with the 3 x 1 array. Only the 1's in the row of M will yield anything in the result. Then the result of this element-wise multiplication is summed. Because you only have one "1" per row, the result is going to be the column index where that 1 is located.
So for example for the first row of M.
element_wise_multiplication = [0 0 1] .* [1 2 3]
[0, 0, 3]
sum(element_wise_multiplication)
3
Update
Based on the solutions provided by #reyryeng and #Luis below, I decided to run a comparison to see how the performance of the various methods compared.
To setup the test matrix (M) I created a matrix of the form specified in the original question and varied the number of rows. Which column had the 1 was chosen randomly using randi([1 nCols], size(M, 1)). Execution times were analyzed using timeit.
When run using M of type double (MATLAB's default) you get the following execution times.
If M is a logical, then the matrix multiplication takes a hit due to the fact that it has to be converted to a numerical type prior to matrix multiplication, whereas the other two have a bit of a performance improvement.
Here is the test code that I used.
sizes = round(linspace(100, 100000, 100));
times = zeros(numel(sizes), 3);
for k = 1:numel(sizes)
M = generateM(sizes(k));
times(k,1) = timeit(#()M * (1:size(M, 2)).');
M = generateM(sizes(k));
times(k,2) = timeit(#()max(M, [], 2), 2);
M = generateM(sizes(k));
times(k,3) = timeit(#()find(M.'), 2);
end
figure
plot(range, times / 1000);
legend({'Multiplication', 'Max', 'Find'})
xlabel('Number of rows in M')
ylabel('Execution Time (ms)')
function M = generateM(nRows)
M = zeros(nRows, 3);
col = randi([1 size(M, 2)], 1, size(M, 1));
M(sub2ind(size(M), 1:numel(col), col)) = 1;
end
You can also abuse find and observe the row positions of the transpose of M. You have to transpose the matrix first as find operates in column major order:
M = [0 0 1
1 0 0
0 1 0
1 0 0
0 0 1];
[out,~] = find(M.');
Not sure if this is faster than matrix multiplication though.
Yet another approach: use the second output of max:
[~, result] = max(M.', [], 1);
Or, as suggested by #rayryeng, use max along the second dimension instead of transposing M:
[~, result] = max(M, [], 2);
For
M = [0 0 1
1 0 0
0 1 0
1 0 0
0 0 1];
this gives
result =
3 1 2 1 3
If M contains more than one 1 in a given row, this will give the index of the first such 1.

Feature mapping using multi-variable polynomial

Consider we have a data-matrix of data points and we are interested to map those data points into a higher dimensional feature space. We can do this by using d-degree polynomials. Thus for a sequence of data points the new data-matrix is
I have studied a relevant script (Andrew Ng. online course) that make such a transform for 2-dimensional data points to a higher feature space. However, I could not figure out a way to generalize in arbitrary higher dimensional samples, . Here is the code:
d = 6;
m = size(D,1);
new = ones(m);
for k = 1:d
for l = 0:k
new(:, end+1) = (x1.^(k-l)).*(x2.^l);
end
end
Can we vectorize this code? Also given a data-matrix could you please suggest a way on how we can transform data points of arbitrary dimension to a higher one using a d-dimensional polynomial?
PS: A generalization of d-dimensional data points would be very helpful.
This solution can handle k variables and generate all the terms of a degree d polynomial where k and d are non-negative integers. Most of the code length is due to the combinatoric complexity of generating all the terms of a degree d polynomial in k variables.
It takes an n_obs by k data matrix X where n_obs is the number of observations and k is the number of variables.
Helper function
This function generates all possible rows such that every entry is a non-negative integer and the row sums to a positive integer:
the row [0, 1, 3, 0, 1] corresponds to (x1^0)*(x1^1)*(x2^3)*(x4^0)*(x5^1)
The function (which almost certainly could be written more efficiently) is:
function result = mg_sums(n_numbers, d)
if(n_numbers<=1)
result = d;
else
result = zeros(0, n_numbers);
for(i = d:-1:0)
rc = mg_sums(n_numbers - 1, d - i);
result = [result; i * ones(size(rc,1), 1), rc];
end
end
Initialization code
n_obs = 1000; % number observations
n_vars = 3; % number of variables
max_degree = 4; % order of polynomial
X = rand(n_obs, n_vars); % generate random, strictly positive data
stacked = zeros(0, n_vars); %this will collect all the coefficients...
for(d = 1:max_degree) % for degree 1 polynomial to degree 'order'
stacked = [stacked; mg_sums(n_vars, d)];
end
Final Step: Method 1
newX = zeros(size(X,1), size(stacked,1));
for(i = 1:size(stacked,1))
accumulator = ones(n_obs, 1);
for(j = 1:n_vars)
accumulator = accumulator .* X(:,j).^stacked(i,j);
end
newX(:,i) = accumulator;
end
Use either method 1 or method 2.
Final Step: Method 2 (requires all data in data matrix X is strictly positive (The problem is that if you have 0 elements, the -inf doesn't propagate properly when you call the matrix algebra routines.)
newX = real(exp(log(X) * stacked')); % multiplying log of data matrix by the
% matrix of all possible exponent combinations
% effectively raises terms to powers and multiplies them!
Example Run
X = [2, 3, 5];
max_degree = 3;
The stacked matrix and the polynomial term it represents are:
1 0 0 x1 2
0 1 0 x2 3
0 0 1 x3 5
2 0 0 x1.^2 4
1 1 0 x1.*x2 6
1 0 1 x1.*x3 10
0 2 0 x2.^2 9
0 1 1 x2.*x3 15
0 0 2 x3.^2 25
3 0 0 x1.^3 8
2 1 0 x1.^2.*x2 12
2 0 1 x1.^2.*x3 20
1 2 0 x1.*x2.^2 18
1 1 1 x1.*x2.*x3 30
1 0 2 x1.*x3.^2 50
0 3 0 x2.^3 27
0 2 1 x2.^2.*x3 45
0 1 2 x2.*x3.^2 75
0 0 3 x3.^3 125
If data matrix X is [2, 3, 5] this correctly generates:
newX = [2, 3, 5, 4, 6, 10, 9, 15, 25, 8, 12, 20, 18, 30, 50, 27, 45, 75, 125];
Where the 1st column is x1, 2nd is x2, 3rd is x3, 4th is x1.^2, 5th is x1.*x2 etc...

finding the minimum between 3 numbers

How can I find the smallest number among three that is non zero.
I tried introducing a very small number eps = 1e-6 (my numbers are either zero or clearly larger than eps) and doing tests between min(x,eps), min(y,eps) etc. I didn't get anything. Is there a way to do that with a function?
If the numbers are all stored in a vector x you could do the following:
x = [1 0 2 0 3 0 4];
y = min(x(x>0));
This is based on your statement that
numbers are either zero or clearly larger than eps
If you mean larger in magnitude and you want to accept non-zero negative values you could use:
x = [1 0 -2 0 3 0 4];
y = min(x(x~=0));
Note that this will return the most negative number when negative numbers are present, rather than the number with the smallest non-zero magnitude. To get the number with the smallest non-zero magnitude, you could use:
x = [1 0 -2 0 3 0 4];
xnonzero = x(x~=0);
[~,idx] = min(abs(xnonzero));
y = xnonzero(idx);
It doesn't seem very elegant. There is probably a more direct way.
numbers = [1 3 4 -2 1 0];
answer = min(numbers(numbers>0));
answer == 1