Matlab enforce variable accuracy - matlab

I have two double arrays that are of equal size but one always has the following format:
A1 = 0.0756 0.0368 0.0124 0.0024 0.0002 0.0000 0.0000
while the other one is:
A2 = 0.0797 0.0368 0.0120 0.0024 0.0004 0 0
I want to enforce the last two elements to be of the same accuracy, that is be 0.0000 instead of 0. Trying the naïve approach of A2(7) = 0.0000 does not work, although A2(7) = A1(7) does the trick.
How can I archive this a bit more cleverly?

Careful! I think you will find the A1(7) == 0 returns false.
What exactly do you mean by the same accuracy? Internally matlab uses the same precision for every element of both of your arrays (they're all doubles). It is just displaying them differently.
Try the following commands:
A1(7);
format long g
A1(7);
and I think you'll find that in fact A1(7) isn't 0 and furthermore is also accurate to far more than the 4 decimal points you are seeing.
So the question is, do you actually want to round off to 4 decimal places? Or do you just want to display up to 4 decimal places? I image you want the latter, so have a look at sprintf

The numbers actually already have the desired precision. If you want you can print them with any amount of digits you like (Though typically only about the first fourteen will be significant).
For this you can use the various print commands, however if you want to change the default way numbers are displayed, your simple options are quite limited.
Check help format for the things you can choose from.
If you always want to show a minmum number of decimals, I believe your only choice is:
format shorteng

Related

Round off Numbers

I have matrix 100*100 (row*column) and it contains numbers like 0.00051,0.00052,0.00056 and so on. I tried to round off these numbers but the problem is
using round(X) will only give "0". I want to round off numbers so,
0.00051 become 0.0005
0.00052 become 0.0005
0.00056 become 0.0006
Thanks
This exact question is asked on MATLAB Central here, and answered by Roger Stafford:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/169196?requestedDomain=www.mathworks.com
To steal his answer for your convenience:
To actually alter the number n to the nearest four place decimal, do:
m = 4; % Number of significant decimals
k = floor(log10(abs(n)))-m+1;
n2 = round(n/10^k)*10^k;
Alternatively, you could get roundn(x,n) off the Matlab file exchange and do roundn(x,-4).
http://www.mathworks.com/matlabcentral/fileexchange/37067-roundn-x-n--returns-x-rounded-to-n-digits
And now for the simple solution, suggested by Mohamed: use round(x,4), as per the Matlab documentation.
http://www.mathworks.com/help/matlab/ref/round.html
This is all one quick google search away. Please do research in the future.

How do I make linspace work for small numbers?

I am trying to use linspace in Matlab for small numbers, e.g. from 0.00003 to 0.1.
However, if I do this, the first number/bin is not 0.00003, but 0, which does not give me an equal distribution:
linspace(0.00003,0.1,10)
ans =
0.0000 0.0111 0.0222 0.0334 0.0445 0.0556 0.0667 0.0778 0.0889 0.1000
I realized that if I start with 0.0003 or larger then it works, but how can I make it work for smaller numbers?
This is purely due to the way that the MATLAB command window is displaying your data.
The default way that numbers are displayed is the short format which the documentation states is:
Short, fixed-decimal format with 4 digits after the decimal point
Your first data point doesn't have a non-zero digit until the 5th digit after the decimal point so it simply shows up as 0.0000.
Try changing the display format to something that will show more significant digits. You can do this using format.
format long g
Also, in the future, if you actually want to check that something is behaving as you expect, do an explicit check by value not just by trusting what shows up in the command window.
limit = 0.000003
data = linsapce(limit, 0.1, 10);
% Check that the first datapoint is "equal" to what you expect
assert(abs(data(1) - limit) < eps)

Using Torch's ClassNLLCriterion

I am currently using Torch and just trying to get a simple neural network program running. Each one of my inputs has 3 attributes and the output is supposed to be a classification between the numbers 1 and 7. I've extracted my data from a CSV file and have put it into 2 Tensors (1 with the inputs and 1 with the outputs). The data is in this format.
**Data**
1914 1993 2386
1909 1990 2300
.....
1912 1989 2200
[torch.DoubleTensor of size 99999x3]
**Class**
1
1
2
.....
7
[torch.DoubleTensor of size 99999]
For the model I'm using to train the network, I simply have
model = nn.Sequential()
model:add(nn.Linear(3, 7))
model:add(nn.LogSoftMax())
criterion = nn.ClassNLLCriterion()
And this is the code I have to train the network
for int i = 1, 10 do
prediction = model:forward(data)
loss = criterion:forward(prediction, class)
model:zeroGradParameters()
grad = criterion:backward(prediction, class)
model:backward(data, grad)
model:updateParameters(.1)
end
In my test data tensor, I have formatted it in the same way as I formatted the test data (Tensor of 99999x3). I want the program to give me a prediction of what the classification would be when I run this line.
print (model:forward(test_data))
However, I am getting negative numbers (which shouldn't happen with ClassNLLCriterion?) and the sums of the probabilities are not adding to 0. My doubt is that I have either not formatted the data correctly or that I wasn't able to perform the training process correctly. If anyone could help me figure out what the issue is, I'd be very grateful.
Thank you!
The reason why you cannot see the prediction yields on the layer model:add(nn.LogSoftMax()) which implements the log function, that's why you have negative values (they are not probabilities). As an example, to get the probabilities back you should do:
model = nn.Sequential()
model:add(nn.Linear(3, 7));
model:add(nn.LogSoftMax());
criterion = nn.ClassNLLCriterion();
data = torch.Tensor{1914, 1993 , 2386}
print (model:forward(data):exp())
>> 0.0000
0.0000
1.0000
0.0000
0.0000
0.0000
0.0000 [torch.DoubleTensor of size 7]
Sorry for the late answer.
Here is what I currently use which maybe the wrong way of using classnllcriterion but atleast it will get you somewhere to understanding it.
Make the targets to be either
(7,1,1,1,1,1,1) <--First class representation
.......
(1,1,1,1,1,1,7) <--Last class representation
or
(1,1,1,1,1,1,1) <--First class representation
.......
(7,7,7,7,7,7,7) <--Last class representation
I figured it's much easier to train the last representation as targets, but I have a feeling we should use the first one instead.
EDIT: I've just found out that classnllcriterion only accepts a scalars as targets, hence using the above is wrong!
You should instead use either
1 .. 7 as target values, either just 1 or just 7.
That's

Matlab gives wrong answer on mod(), isequal(), floor() function with a vector parameter

I am using matlab to solve a mixed integer programming, after I obtain a solution from linprog, I want to evaluate whether they are all integers(x is n dimensions), but I cannot figure out a way to do this.
All the functions, such as mod(x,1) == 0, isequal(x,floor(x)) will give a wrong anwser.
More strange is, if you manually input a vector with the same parameter, it will turn out to be right.
The result is shown: (all the x here is obtained from the result of linprog). Anyone can help with this or bring out some other useful way to evaluate this?
K>> x
x =
7.0000
1.0000
K>> mod(x,1)
ans =
0.0000
1.0000
K>> x
x =
6.0000
3.0000
K>> isequal(x,floor(x))
ans =
0
What seems to be an integral 1 coming from linprog, actually is a floating point number very close to 1, but not equal to it. It's just that you (by default) cannot tell the difference by outputting the number in MATLAB. See this Question about comparing floating point values. Also, see the MATLAB manual page about display format of numbers.
By default, MATLAB displays numbers using format short:
format sets the display of floating-point numeric values to the default display format, which is the short fixed decimal format. This format displays 5-digit scaled, fixed-point values.
So, 1 – 1e–10 would be displayed as 1 even though it is not equal to 1. Likewise, mod(1 – 1e–10, 1) would be displayed as 1, even though it really is 1 – 1e–10.
If you manually set x to its displayed representation, all the less significant digits are truncated, “strangely” giving you the expected results.
Check x after typing the command format long.

Sort array in MATLAB

I have a one-column array that I would like to sort in descending order. The array has values ranging from 0 to approximately 10^14. When I sort the array with
sorted = sort(A,'descend')
and try to look at the ten largest values, I find that
sorted(1:10)
gives me
1.0e+14 *
5.1093
0.0000
0.0000
0.0000
etc... -- Displaying these first few, large entries tells me that there's only one non-zero element, which isn't true.
However, if I skip the first couple of entries, which are far greater than the rest of the array elements, I get
sorted(8:10) =
2.9754
2.4182
2.0799
Why does displaying these first few large array elements cause all others to be displayed as zero?
The first number in your list is a scale factor that multiplies the entire array that follows. Because of the difference in magnitude of the elements, you will need to play with the format settings. Try
format long
or
format long e
to see a better representation
You may find sprintf or num2str more useful for printing numbers at arbitrary precision.
See this related SO question.
Relevant Matlab docs:
http://www.mathworks.com/help/techdoc/ref/format.html
http://www.mathworks.com/help/techdoc/ref/num2str.html
http://www.mathworks.com/help/techdoc/ref/sprintf.html
They're displayed as zero because they are essentially zero when compared to the first element (that is, they're much much smaller than 10^14). But even if they're displayed as zero, they are NOT zero. Try typing in sorted(3): the result shouldn't be zero. (Edit: you already showed this above).
It's basically an issue of precision. Typing format long might also make this clearer.