This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
MATLAB: how to normalize/denormalize a vector to range [-1;1]
Hi, just started using Matlab and I would like to know how to rescale the data in a matrix.
I have a matrix of N rows by M columns and want to rescale the data in the columns to be between -1 and 1.
Each column contains values that vary in scale from say 0 - 10,000 to some that are between 0 and 1, the reason I want to normalise to between -1 and 1 as these values will be used in a Neural Network as input values for a transform function that is sine based.
Neither of the previous answers are correct. This is what you need to do:
[rows,~]=size(A);%# A is your matrix
colMax=max(abs(A),[],1);%# take max absolute value to account for negative numbers
normalizedA=A./repmat(colMax,rows,1);
The matrix normalizedA will have values between -1 and 1.
Example:
A=randn(4)
A =
-1.0689 0.3252 -0.1022 -0.8649
-0.8095 -0.7549 -0.2414 -0.0301
-2.9443 1.3703 0.3192 -0.1649
1.4384 -1.7115 0.3129 0.6277
normalizedA =
-0.3630 0.1900 -0.3203 -1.0000
-0.2749 -0.4411 -0.7564 -0.0347
-1.0000 0.8006 1.0000 -0.1906
0.4885 -1.0000 0.9801 0.7258
A simple solution would use simple logic. Assuming that you mean to scale EACH column independently, do this:
Subtract off the column minimum for each column.
Scale the column maximum to be 2.
Subtract 1.
Clearly this will result in the min for each column to be -1, the max will be 1. Code to do so is simple enough.
A = randn(5,4) % some random example data
A =
0.70127 0.20378 0.4085 0.83125
0.64984 -0.90414 0.67386 1.2022
1.6843 -1.6584 -0.31735 -1.8981
-1.3898 -0.89092 -0.23122 -1.2075
0.72904 -0.095776 0.67517 0.28613
Now, perform the steps above to A.
A = bsxfun(#minus,A,min(A,[],1));
A = bsxfun(#times,A,2./max(A,[],1));
A = A - 1
A =
0.36043 1 0.46264 0.76071
0.32697 -0.18989 0.99735 1
1 -1 -1 -1
-1 -0.1757 -0.82646 -0.55446
0.3785 0.67828 1 0.40905
[m, n] = size(normalizedMatrix)
normalizedMatrix*2-ones(m,n)
Related
I have a matrix suppX in Matlab with size GxN and a matrix A with size MxN. I would like your help to construct a matrix Xresponse with size GxM with Xresponse(g,m)=1 if the row A(m,:) is equal to the row suppX(g,:) and zero otherwise.
Let me explain better with an example.
suppX=[1 2 3 4;
5 6 7 8;
9 10 11 12]; %GxN
A=[1 2 3 4;
1 2 3 4;
9 10 11 12;
1 2 3 4]; %MxN
Xresponse=[1 1 0 1;
0 0 0 0;
0 0 1 0]; %GxM
I have written a code that does what I want.
Xresponsemy=zeros(size(suppX,1), size(A,1));
for x=1:size(suppX,1)
Xresponsemy(x,:)=ismember(A, suppX(x,:), 'rows').';
end
My code uses a loop. I would like to avoid this because in my real case this piece of code is part of another big loop. Do you have suggestions without looping?
One way to do this would be to treat each matrix as vectors in N dimensional space and you can find the L2 norm (or the Euclidean distance) of each vector. After, check if the distance is 0. If it is, then you have a match. Specifically, you can create a matrix such that element (i,j) in this matrix calculates the distance between row i in one matrix to row j in the other matrix.
You can treat your problem by modifying the distance matrix that results from this problem such that 1 means the two vectors completely similar and 0 otherwise.
This post should be of interest: Efficiently compute pairwise squared Euclidean distance in Matlab.
I would specifically look at the answer by Shai Bagon that uses matrix multiplication and broadcasting. You would then modify it so that you find distances that would be equal to 0:
nA = sum(A.^2, 2); % norm of A's elements
nB = sum(suppX.^2, 2); % norm of B's elements
Xresponse = bsxfun(#plus, nB, nA.') - 2 * suppX * A.';
Xresponse = Xresponse == 0;
We get:
Xresponse =
3×4 logical array
1 1 0 1
0 0 0 0
0 0 1 0
Note on floating-point efficiency
Because you are using ismember in your implementation, it's implicit to me that you expect all values to be integer. In this case, you can very much compare directly with the zero distance without loss of accuracy. If you intend to move to floating-point, you should always compare with some small threshold instead of 0, like Xresponse = Xresponse <= 1e-10; or something to that effect. I don't believe that is needed for your scenario.
Here's an alternative to #rayryeng's answer: reduce each row of the two matrices to a unique identifier using the third output of unique with the 'rows' input flag, and then compare the identifiers with singleton expansion (broadcast) using bsxfun:
[~, ~, w] = unique([A; suppX], 'rows');
Xresponse = bsxfun(#eq, w(1:size(A,1)).', w(size(A,1)+1:end));
I have a matrix X with 3 columns. For the porous of the question X=randn(5,3).
I want to normalize the columns of X S.T. each column will have a 0 mean and a 1 std. I was using the following code:
X=(X-mean(X))./std(X);
I am getting an std of 1. My mean, however, is a very small value close to 0 but not essential 0. I tried playing a bit with the numbers to find an explanation:
X=1:15;
X=reshape(X,[5 3]);
mean(X-mean(X));
Which gives me 0 value for each column.
X=1:15;
X=reshape(X,[5 3]);
mean((X-mean(X))./std(X));
Which does not. But 0/anything is still 0. what am I missing?
Why am I not getting 0 values?
Are the values I am getting good enough for a pre-clustering algorithm normalization?
Here is a version that does what I think you're trying to do... you need to replicate the matrix because X-mean(X) isn't valid (if you're using the standard implementation)-- you can't subtract a 1x3 from a 5x3.
r = 5; c = 3;
X=randn(r,c);
Xm=repmat(mean(X),r,1);
Xstd = repmat(std(X),r,1);
Xn = (X-Xm)./Xstd;
mean(Xn)
std(Xn)
For me this prints out
ans =
1.0e-16 *
-0.6661 0 0.4441
ans =
1.0000 1.0000 1.0000
Which seems like exactly what you're looking for... note the 1e-16 multiplier on the mean values... this is essentially 0, with some floating point error.
I have two matrices.
mcaps which is a double 1698 x 2
index_g which is a logical 1698 x 2
When using the line of code below I get the error message that Index exceeds matrix dimensions. I don't see how this is the case though?
tsp = nansum(mcaps(index_g==1, :));
Update
Sorry I should have mentioned that I need the sum of each column in the mcaps vector
** Example of data **
mcaps index_g
5 6 0 0
4 3 0 0
6 5 1 1
4 6 0 1
8 7 0 0
There are two problems here. I missed one. Original answer is below.
What I missed is that when you use the logical index in this way, you are picking out elements of the matrix that may have different numbers of elements in each column, so MATLAB can't return a well formed matrix back to nansum, and so returns a vector. To get around this, use the fact that 0 + anything = 0
% create a mask of values you don't want to sum. Note that since
% index_g is already logical, you don't have to test equal to 1.
mask = ~index_g & isnan(mcaps)
% create a temporary variable
mcaps_to_sum = mcaps;
% change all of the values that you don't want to sum to zero
mcaps_to_sum(mask) = 0;
% do the sum
sum(mcaps_to_sum,1);
This is basically all that the nansum function does internally, is to set all of the NaN values to zero and then call the sum function.
index_g == 1 returns a 1698 x 2 logical matrix, but then you add in an extra dimension with the colon. To sum the columns, use the optional dim input. You want:
tsp = nansum(mcaps(index_g == 1),1);
This question already has an answer here:
How do I generate a random vector (0,1) with a known probability in MATLAB
(1 answer)
Closed 7 years ago.
For example, how to randomly generate a 1-by-12 matrix that contains 8 0s and 4 1s?
Like this matrix [1 0 0 1 0 0 0 1 0 0 1 0]
And if I generate again, it returns a different matrix [0 0 1 0 0 1 1 0 1 0 0 0]
Create a vector that starts with the desired number of 1s followed by the desired number of 0s and the use randperm to shuffle it around:
n = 8;
m = 4;
M = [ones(m,1), zeros(n,1)];
M = M(randperm(numel(M)))
Or you can do it slightly differently: http://www.mathworks.com/matlabcentral/answers/83289-how-can-i-create-a-random-binary-matrix-with-a-specified-number-of-1-s-and-0-s
You can make a vector containing 12 zeros and use randsample to pick four numbers that you make one:
a = zeros(1,12);
a(randsample(12,4)) = 1;
Note: This requires the 'Statistics and Machine Learning Toolbox'.
If you do not have this, you will not be able to use randsample.
This one may work as well.
x = zeros(12,1);
tmp = rand(12,1);
[~,ind] = sort(tmp);
x(ind(1:4)) = 1;
Not sure if is better than the other examples, but it is one way to do it. I would say it is a similar solution as the one by fhdrsdg, but this one does not requires statistics toolbox. It mat also be possible that this solution may not have the same elegance as matlabs solutions may have though and randsample have more features than this example.
This question already has answers here:
Vector norm of an array of vectors in MATLAB
(4 answers)
Closed 5 years ago.
I have an input matrix that has 3 rows and 1000 columns. Each column represents and x, y, z variable. I want to find the magnitude of each column and store that in an output matrix that has 1 row and 1000 columns.
This is my current attempt but it doesn't seem to be working:
output(1,:) = norm(input(3,:));
my input matrix looks like:
x1, x2,...,x1000
y1, y2,...,y1000
z1, z2,...,z1000
I want my output matrix to look like:
[magnitude(x1,y1,z1), magnitude(x2,y2,z2),...,magnitude(x1000,y1000,z1000)]
Any help would be greatly appreciated.
norm(input(3,:)) will give you the norm of the 1000 elements of the third row.
Easy solution is to just run a for loop.
output = zeros(1,1000); %Preallocate space
for i = 1:length(output)
output(i) = norm(input(:, i));
end
MATLAB's norm function only works for single vectors. Let A be the name of the matrix which columns you want to find the norm to. Then this command does the job:
norm_A = sqrt(sum(A.*A));
Here is an example:
>> A = [1:5; 1:5; 1:5]
A =
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
>> norm_A = sqrt(sum(A.*A))
norm_A =
1.7321 3.4641 5.1962 6.9282 8.6603