matrix multiplication result value range - matlab

Here is the initial question:
About the output value range of LeGall 5/3 wavelet
Today I found actually the transform can be seen as a matrix multiplication. It is easy to calculate the wavelet coefficients as a matrix (in order to estimate the value, all the Rounded down action is ignored which will not affect the estimation of the max value).
The 1st level of DWT2 has two steps which is to perform the LeGall 5/3 filter on two directions. If we see the I as the input 8*8 matrix and A as the wavelet coefficients matrix.
For the horizontal direction:
output1 = I.A
Then the vertical direction is calculated:
In fact, it can be represented as output2 = output1'.A (use the transpose of output1 to multiply A again) which will get the transpose of the result we want.
Transpose the output2.
output_lvl1 = output2' = (output1'.A)' = ((I.A)'.A)' = (A'.I'.A)'=A'.I.A (I put details here to make it clear without the math symbol...)
And the 2nd level of the wavelet is only performed at the LL area which is the output_lvl1(1:4,1:4). And basically the process is the same (let the coefficients matrix represented as B).
Here is the coefficients of the matrix A and B based on my calculation (hope it is correct...)
A = [0.75 -0.125 0 0 -0.5 0 0 0;
0.5 0.25 0 0 1 0 0 0;
-0.25 0.75 -0.125 0 -0.5 -0.5 0 0;
0 0.25 0.25 0 0 1 0 0;
0 -0.125 0.75 -0.125 0 -0.5 -0.5 0
0 0 0.25 0.25 0 0 1 0;
0 0 -0.125 0.625 0 0 -0.5 -1;
0 0 0 0.25 0 0 0 1];
B = [0.75 -0.125 -0.5 0;
0.5 0.25 1 0;
-0.25 0.75 -0.5 -1;
0 0.125 0 1];
And now the question became:
1. if we know A and the range of Input(matrix I) which is -128 to +127, what is the value range of output_lvl1 = A'.I.A?
if we use the output_lvl1(1:4,1:4) as input I2, what is value range of B'.I2.B?
I really need some math help here. Thank you in advance.

Well finally I found a way to solve this.
SymPy lib is what I really need.
As the max value could only be possible in results of B'.I2.B. So a program will do this.
from sympy import *
def calcu_max(strin):
x=0
strin1 = str(strin).replace('*',' ').replace('+',' ').replace('-',' ')
strin1 = strin1.split(' ')
for ele in strin1:
if '[' in ele or ']' in ele or ele =='':
continue
x = x + float(ele)
return x
DWT1 = Matrix(8, 8, [0.75, -0.125, 0, 0,-0.5, 0, 0, 0, 0.5, 0.25, 0, 0, 1, 0, 0, 0, -0.25, 0.75, -0.125, 0, -0.5, -0.5, 0, 0, 0, 0.25, 0.25, 0, 0, 1, 0, 0, 0,-0.125, 0.75, -0.125, 0, -0.5, -0.5, 0, 0, 0, 0.25, 0.25, 0, 0, 1, 0, 0, 0, -0.125, 0.625, 0, 0, -0.5, -1, 0, 0, 0, 0.25, 0, 0, 0, 1])
Input1 = MatrixSymbol('A',8,8)
DWT1_t = Transpose(DWT1)
output_lvl1_1d = DWT1_t*Input1
output_lvl1_2d = output_lvl1_1d* DWT1
#print 'output_lvl1_2d[0,0]: '
#print simplify(output_lvl1_2d[0,0])
#bulit 2nd lvl input from the lvl1 output (1:4,1:4)
input_lvl2 = output_lvl1_2d[0:4,0:4]
DWT2 = Matrix(4, 4, [0.75, -0.125, -0.5, 0, 0.5, 0.25, 1, 0, -0.25, 0.75, -0.5, -1, 0, 0.125, 0, 1])
DWT2_t = Transpose(DWT2)
output_lvl2_1d = DWT2_t*input_lvl2
output_lvl2_2d = output_lvl2_1d * DWT2
#Lvl 2 calculate max
max_lvl2 = zeros(4,4)
for i in range(4):
for j in range(4):
max_lvl2[i,j]=128.0*calcu_max(simplify(output_lvl2_2d[i,j]))
print str(i)+' '+str(j)+' '+str(max_lvl2[i,j])
#print max_lvl2[i,j]
print max_lvl2
Well, here is the result (putting all possible max values in one matrix, and min values are correspondingly negative):
[338.000000000000, 266.500000000000, 468.000000000000, 468.000000000000],
[266.500000000000, 210.125000000000, 369.000000000000, 369.000000000000],
[468.000000000000, 369.000000000000, 648.000000000000, 648.000000000000],
[468.000000000000, 369.000000000000, 648.000000000000, 648.000000000000]
Then 648 is what I am looking for.

Related

Neural Network Recognising in Scilab

I try to run this example, which uses ANN Toolbox for Scilab
https://burubaxair.wordpress.com/2014/03/12/artificial-neural-networks-in-scilab/
This is code:
T = [
1 1 1 1 1
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
]';
U = [
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
0 1 1 1 0
]';
N = [35 10 2];
W = ann_FF_init(N);
x = [1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
0, 1, 1, 1, 0]';
t_t = [1 0]';
t_u = [0 1]';
t = [t_t, t_u];
lp = [0.01, 1e-4];
epochs = 3000;
W = ann_FF_Std_batch(x,t,N,W,lp,epochs);
y = ann_FF_run(x,N,W)
disp(y)
But i receive an error:
-->exec('D:\Учёба\Задачи\Recognition.sce', -1)
!--error 15
Подматрица задана некорректно (Submatrix is incorrect).
at line 37 of function ann_FF_grad_BP called by :
at line 25 of function ann_FF_Std_batch called by :
W = ann_FF_Std_batch(x,t,N,W,lp,epochs);
at line 33 of exec file called by :
exec('D:\Учёба\Задачи\Recognition.sce', -1)
An error may be in T and U matrix, but i don't understand why. Could you tell be what i do wrong? Thank you!
You've made 2 errors in your code:
You should not mix testing and training sets.
Testing input must be a single column.
Your first error was x = [ 1.... ] because it contained a single image, whereas you specified in N that you had two output neurons.
As stated in the example, you should have x = [T,U];
Your second error was to give x as a test to ann_FF_run. This function takes test input as a single column. But since you trained your NN with x just before it was a 5x7 matrix. Just change it to a column vector.
Here a corrected and commented code :
T = [...
1 1 1 1 1 ...
0 0 1 0 0 ...
0 0 1 0 0 ...
0 0 1 0 0 ...
0 0 1 0 0 ...
0 0 1 0 0 ...
0 0 1 0 0 ...
]';
U = [...
1 0 0 0 1 ...
1 0 0 0 1 ...
1 0 0 0 1 ...
1 0 0 0 1 ...
1 0 0 0 1 ...
1 0 0 0 1 ...
0 1 1 1 0 ...
]';
// setting the traing set of two image
xtrain = [T,U];
// so each image as 35 pixels so N(1) is 35
// and we have two images so N($) is 2
N = [35 10 2];
// training the NN
W = ann_FF_init(N);
// The expected response for T : 1 for T, 0 for U
t_t = [1 0]';
// The expected response for T : 1 for T, 0 for U
t_u = [0 1]';
// the overall response
t = [t_t, t_u];
// some parameters
lp = [0.01, 1e-4];
epochs = 3000;
// getting the weight of the trained NN
W = ann_FF_Std_batch(xtrain,t,N,W,lp,epochs);
// testing the traing set.
y = ann_FF_run(xtrain,N,W)
disp('Testing the traing set')
disp(y) //should get something close to t ~ [1 0 ; 0 1]
// testing a distord U
xtest1 = matrix([1, 0, 0, 0, 1;
1, 1, 0, 0, 1;
1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
1, 0, 0, 0, 1;
0, 1, 1, 1, 1]',-1,1);
y = ann_FF_run(xtest1,N,W)
disp('Testing a distored U')
disp(y) //should get something close to t_u ~ [0 1]
//testing something different from T and U. should get nothing
xtest2 = matrix([1, 0, 0, 0, 1;
1, 1, 0, 0, 1;
1, 0, 1, 0, 1;
1, 0, 1, 0, 1;
0, 0, 1, 1, 1;
0, 0, 1, 0, 1;
0, 1, 1, 1, 1]',-1,1);
y = ann_FF_run(xtest2,N,W)
disp('Testing something neither T nor U')
disp(y)
and the output from scilab's console
Testing the traing set
0.8538757 0.1075397
0.1393287 0.8957439
Testing a distored U
0.1078667
0.9007755
Testing something neither T nor U
0.3433933
0.6306797

Set precision an element in Matlab matrix

I want to set precision for all element of a matrix. Below is what I did:
>>A
A =
0 1.0000 0 0 0 0
-137.0830 0 0 0 0 0
0 0 0 1.0000 0 0
365.5546 0 0 0 0 0
0 0 0 0 0 1.0000
365.5546 0 0 0 0 0
>> vpa(A,2)
ans =
[ 0, 1.0, 0, 0, 0, 0]
[ -144.0, 0, 0, 0, 0, 0]
[ 0, 0, 0, 1.0, 0, 0]
[ 377.0, 0, 0, 0, 0, 0]
[ 0, 0, 0, 0, 0, 1.0]
[ 377.0, 0, 0, 0, 0, 0]
The result is not my desire, it should be:
-137.08, 365.55, 365.55 in the first column.
Please help to suggest me how to get it.
Thank you so much!
You are not using vpa correctly. From the docs:
vpa(x,d) uses at least d significant digits
Nota that it says at least. That is why you still get 377 when you only asked for 2 significant digits.
It seems that you don't know what significant digits are. From Wikipedia:
The significant figures of a number are digits that carry meaning
contributing to its measurement resolution. This includes all digits
except:
All leading zeros;
Trailing zeros when they are merely placeholders to indicate the scale of the number (exact rules are explained at identifying
significant figures); and
Spurious digits introduced, for example, by calculations carried out to greater precision than that of the original data, or measurements
reported to a greater precision than the equipment supports.
So you want this
>> vpa(365.5546, 5)
ans =
365.55
Now, to be consistent, you need to find out what is the maximum of your matrix and compute the desired number of significant digits from there.
max_number = floor(log10(max(abs(A(:))+1)) + 1);
decimals = 2;
vpa(A, max_number + decimals)
Here, max_number is the maximum number of integer digits that your matrix has, and decimals is the number of decimal places that you want to have.
The second input to vpa is the number of significant digits which is not the same as the number of values after the radix point. The number -137.08 actually has five signficant digits so you'll want to use a second input of 5
vpa(A, 5)
% [ 0, 1.0, 0, 0, 0, 0]
% [ -137.08, 0, 0, 0, 0, 0]
% [ 0, 0, 0, 1.0, 0, 0]
% [ 365.55, 0, 0, 0, 0, 0]
% [ 0, 0, 0, 0, 0, 1.0]
% [ 365.55, 0, 0, 0, 0, 0]
vpa(x,d) :
d is significant digits, not decimal places.
pvalue = vpa(-137.0830);
twopvalue = vpa(-137.0830,2);
% pvalue = -137.08299999999999840838427189738
% twopvalue = -144.0
If you want to get -137.08, 365.55, 365.55 in the first column. You can use roundn(A,-2)
roundn(A,-2)
ans =
0 1.0000 0 0 0 0
-137.0800 0 0 0 0 0
0 0 0 1.0000 0 0
365.5500 0 0 0 0 0
0 0 0 0 0 1.0000
365.5500 0 0 0 0 0

Multiple Array pattern matching

Let's say i have an array:
A = [0, -2, 0, 0, -3, 0, -1, 0];
And I want to see if it can fit any of the patterns below:
B = [1, 1, 1 , 0, 0 , 0 , 0, 0,];
C= [1, 1, 0 , 1, 0 , 0 , 0, 0,]
D= [0, 1, 0 , 1, 0 , 1 , 0, 0];
Where 1 means that the number is unique and 0 means that the number remains the same until another 1 is met but is different from the number before.. Here are some examples:
[-3, -2, -1, 0, 0, 0, 0, 0]; --- A matches B.
[-3, -2, -1, -1, 0, 0, 0, 0]; -- This matches C
[-3, -3, 3, 3, -2, -2, 0, 0]; -- This matches D
Is there any Matlab function for this or must I think up my own way? Any advice, I am very new to Matlab.
There is something wrong about your rule, you seem to treat 0 as a special case (i.e. it is not a number or something).
you could just do something like this:
A=[-3, -2, -1, -1, 0, 0, 0, 0];
[ia ib] = unique(A);
R = zeros(1,8);
R(ib) = 1
>> R =
1 1 0 1 0 0 0 1
and match this, this is assuming that you treat 0 as a number just as you state in the rule.
If you wanted 0 to be special case, you need to :
A=[-3, -2, -1, -1, 0, 0, 0, 0];
[ia ib] = unique(A);
ib(ia==0)=[];
R = zeros(1,8);
R(ib) = 1
>> R =
1 1 0 1 0 0 0 0
and simply match this vector to your B,C,D etc. The second method matches your desired answer, but does not match the rule you state. The first method matches the rule you state but not your desired output.
=============EDIT============
I am on 2010b and some time along the time line, the way unique works changed, you now need to add legacy if you are using any version above 2012b.
Sorry I forgot to mention this:
just change it to :
[ia ib] = unique(A,'legacy');
and it should work fine.

MATLAB matrix range assignment

Is it possible to assign ranges to a matrix.
If you consider the below zeros matrix as a 'grid' for plotting:
R = zeros(5,8);
R =
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
So can you treat this matrix as a grid so each x-axis zero can considered as a range? for example R(5,1) is a range 0-0.1 seconds. R(5,2) is a range 0.1-0.2 seconds etc.
Can the range idea also be applied to the columns?
The purpose for this is so I can read cell array data I have already organised into ranges into the zeros matrix to produce a 2d histogram.
Assume you have the times tt and the datavalues val, where val(i) contains the datavalue for time tt(i). In your example you would have
tt = [0.02, 0.22, 0.15, 0.08, 0.27, 0.09];
val = [0.5, 1.4, 2.5, 0.6 , 0.8, 0.3 ];
Now you need vectors that represent the time and data ranges that you want (increasing), for example
trange = [0, 0.1, 0.2, 0.3, Inf];
valrange = [0, 1, 2, 3, Inf];
Now you create a matrix of the right size
R = zeros(length(valrange), length(trange));
You can fill the matrix up easily just by looping over all times you have
for i=1:length(tt)
%// We consider the pair tt(i), val(i)
%// First find out, in which time range tt(i) lies:
tind = find(trange > tt(i), 1, 'first');
%// Now find out, in which value range val(i) lies:
valind = find(valrange > val(i), 1, 'first');
%// Now we increase the corresponding matrix entry
R(valind,tind) = R(valind,tind) + 1;
end
Note that the first column corresponds to the time range between -Inf to trange(1) and the last column to the range between trange(end-1) and trange(end)==Inf. Simliary for the first and last row.
I'm not sure if I understand your question.
If you ask, whether it is possible to assign a vector, e.g. a = [1;2;3], to be a column in some matrix R = zeros(3, 5), then this can be achieved by
R(:, 1) = a;
R(:, 2) = [4;5;6];

how to interpret 8 neighbors as follows

i would like to find 8 neighbors. In an algorithm it is written as
int Nx[] = {-1, 1, 0, 0, -1, -1, 1, 1}; //8-neighbors
int Ny[] = {0, 0, -1, 1, 1, -1, 1, -1};
how 3*3 matrix is interpreted like this?
These are relative x- and y- coordinates. It becomes clearer if you convert this to coordinate pairs:
x y neighbour
----------------------
-1 0 left
1 0 right
0 -1 bottom
0 1 top
-1 1 left-top
-1 -1 left-bottom
1 1 right-top
1 -1 right-bottom