How do I average elements of a matrix according to an identity matrix? - matlab

I have a 333x1 vector of values ('data') and each of the cells in the vector correspond to a range of 1 of 13 subcategories. The identities of each of these subcategories are stored in a separate identity matrix ('id'). I'd like to calculate the sum of the values within the original data matrix that have a similar identity.
e.g. pretending for this example that 'data' and 'id' are 8x1 vectors
data = [1;1;1;0;0;0;1;1]
id = [1;2;1;2;3;3;1;3]
sum of id 1: 1 + 0 + 1 + 0 + 0 + 0 + 1 + 0 = 3
sum of id 2: 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 = 1
sum of id 3: 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 = 1
I'm sure that there is a really easy fix for this, however I can't seem to work it out.
Thanks for your time
Mac

A simple solution would be:
numCategories = 13;
totals = zeros(numCategories,1);
for idnum = 1:numCategories
totals(idnum) = sum((id==idnum).*data);
end
EDIT: As knedlsepp pointed out in the comments, the accumarray function accomplishes exactly what the above code does in one line.
accumarray(id,data);

Related

Determine how many times a specific value occurs around each element of a matrix

I am writing a program that is a Game of Thrones Game similar to minesweeper. The user is asked for the size of the kingdom and depending on the size has a certain amount of knights. I create a matrix (size by size) of zeros to pre-allocate and assign the same amount of kings as there are knights to random places in the matrix. I now have made a new function that i call in the main script that i want to iterate through the matrix and assign new values to each element based on how many kings are in the neighboring spots for example:
_ 1 2 3 4 5 6 7 8
1 * 1 1 1 1 0 0 0
2 1 2 2 * 2 2 1 1
3 1 2 * 3 * 2 * 1
4 * 3 1 2 1 2 1 1
5 * 2 0 0 0 0 0 0
6 1 0 0 1 1 2 1 1
7 1 1 1 1 * 2 * 1
8 1 * 1 1 1 2 1 1
The problem is I really do not know how to actually count the neighboring kings and change the values in my matrix. I have started with some for loops for the sides but i am not sure how to proceed. The main scrips and the function are bellow Thank you!
Main Script:
clear all;close all;clc;
%display menu of options to play gam or exit
choice = menu('Choose an option', 'Exit Program', 'Start New Game');
%choise 1 is to exit the program
while choice ~= 1
switch choice
case 0
disp('Error - please choose one of the options.')
choice = menu('Choose an option', 'Exit Program', 'Start New Game');
%choice two is to start a new game
case 2
disp('Welcome to the GAME of THRONES!');
name = input('State your name, Your Grace: ','s');
size = input(['How vast is your Kindom ', name , ' your Grace?: ']);
Kings = floor((size^2)/6);
A = [name, ' Your Grace, you have ' num2str(Kings), ' Knights left to defeat ' num2str(Kings), ' Kings'];
disp(A);
game_choices = menu('Choose an option','Show the Kingdoms','Enter a new Coordinat');
switch game_choices
case 1 %Show the board
mymat = zeros(size);%matrix of users size
Kr=randsample(size^2,Kings);%vector of random positions for the kings
for i= 1:Kings
mymat([Kr(i)])=999;%put kings into mat of zeros in there random assignments
end
makeBoard(size);
%cell array game board
case 2 %enter a new coordinate
end
end
choice = menu('Choose an option', 'Exit Program', 'Start New Game');
end
Function i do not know how to write:
function [ mymatG ] = countTheKings( mymat )
%this function counts the kings and puts the numbers where they should be
%should have 2 for loops
for i = 1:size
for j = 1:size
%top
mymat(1,j)=
%bottom
mymat(size,j)=
%left side
mymat(i,1)=
%right side
mymat(i,size)=
end
A classic way to count the number of neighbors is to use convolution. 2D Convolution, in the discrete world, shifts a matrix ("kernel") over a bigger matrix and for each shift, the overlap is computed. The overlap is defined as the sum of the element-wise multiplication of the kernel and the data underneath of it. The resulting value is then used to replace the value that the kernel is centered on.
We can design the kernel to "detect" neighbors. We want it to have ones in spots that you consider to be neighbors and zeros in spots that you don't consider to be neighbors. This would probably look like this if you don't want your kings to consider themselves a neighbor.
1 1 1
1 0 1
1 1 1
This matrix will be centered at every point on your board and element-wise multiplication with the board will be performed and all elements will be summed up.
For example, if this was centered at the following data
1 2 3
4 5 6
7 8 9
It would be processed as:
(1 * 1) + (2 * 1) + (3 * 1) + (4 * 1) + (5 * 0) + (6 * 1) + (7 * 1) + (8 * 1) + (9 * 1)
1 + 2 + 3 + 4 + 0 + 6 + 7 + 8 + 9
40
So we can also use convolution of this "kernel" to count the number of 1's in a binary matrix.
So for this data
1 0 1
0 0 0
1 0 0
When we apply our kernel to this we get
(1 * 1) + (0 * 1) + (1 * 1) + (0 * 1) + (0 * 0) + (0 * 1) + (1 * 1) + (0 * 1) + (0 * 1)
1 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0
3
If you imagine that the binary data we applied this kernel to was 1 where there is a king and 0 where there isn't, this is the number of kings that surround a given element.
So what we can do is take the kernel from the beginning of our question, and create a binary matrix that is 1's where there is a king and 0's otherwise. The result will be the size of your board and the values will be the number of neighboring kings.
kernel = [1 1 1;
1 0 1;
1 1 1];
mymat = [9 0 0 0 0 0 0 0
0 0 0 9 0 0 0 0
0 0 9 0 9 0 9 0
9 0 0 0 0 0 0 0
9 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 9 0 9 0
0 9 0 0 0 0 0 0];
isKing = mymat == 9;
nKingNeighbors = conv2(double(isKing), kernel, 'same');
%// 0 1 1 1 1 0 0 0
%// 1 2 2 2 2 2 1 1
%// 1 2 1 3 1 2 0 1
%// 1 3 1 2 1 2 1 1
%// 1 2 0 0 0 0 0 0
%// 1 1 0 1 1 2 1 1
%// 1 1 1 1 0 2 0 1
%// 1 0 1 1 1 2 1 1
If you didn't want to consider diagonal entries to be neighbors you could simply change your kernel to be.
0 1 0
1 0 1
0 1 0
So if we take this back to your example, we could write your countTheKings function as
function mymatG = countTheKings(mymat)
kernel = [1 1 1
1 0 1
1 1 1];
mymatG = conv2(double(mymat == 999), kernel, 'same');
end
Here is an animation showing what the 2D convolution is actually doing. The kernel is shown in red and you can see the values of nKingNeighbors being filled in as the kernel is shifted over the image.

Implementing a Neural Network in Matlab/Octave

I am trying to solve the problem http://postimg.org/image/4bmfha8m7/
I am having trouble in implementing the weight matrix for the 36 inputs.
I have a 3 neuron hidden layer.
I use the backpropagation algorithm to learn.
What I have tried so far is:
% Sigmoid Function Definition
function [result] = sigmoid(x)
result = 1.0 ./ (1.0 + exp(-x));
end
% Inputs
input = [1 1 0 1 1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0;
0 0 0 0 1 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1;
0 0 0 0 0 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0 0 0 0;
0 0 0 0 1 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1];
% Desired outputs
output = [1;1;1;1];
% Initializing the bias (Bias or threshold are the same thing, essential for learning, to translate the curve)
% Also, the first column of the weight matrix is the weight of the bias values
bias = [-1 -1 -1 -1];
% Learning coefficient
coeff = 1.0;
% Number of learning iterations
iterations = 100;
disp('No. Of Learning Iterations = ');
disp(iterations);
% Initial weights
weights = ones(36,36);
% Main Algorithm Begins
for i = 1:iterations
out = zeros(4,1);
numIn = length (input(:,1));
for j = 1:numIn
% 1st neuron in the hidden layer
H1 = bias(1,1)*weights(1,1) + input(j,1)*weights(1,2) + input(j,2)*weights(1,3) + input(j,3)*weights(1,4)+ input(j,4)*weights(1,5) + input(j,5)*weights(1,6) + input(j,6)*weights(1,7)
+ input(j,7)*weights(1,8) + input(j,8)*weights(1,9) + input(j,9)*weights(1,10)+ input(j,10)*weights(1,11) + input(j,11)*weights(1,12) + input(j,12)*weights(1,13)
+ input(j,13)*weights(1,14) + input(j,14)*weights(1,15) + input(j,15)*weights(1,16)+ input(j,16)*weights(1,17) + input(j,17)*weights(1,18) + input(j,18)*weights(1,19)
+ input(j,19)*weights(1,20) + input(j,20)*weights(1,21) + input(j,21)*weights(1,22)+ input(j,22)*weights(1,23) + input(j,23)*weights(1,24) + input(j,24)*weights(1,25)
+ input(j,25)*weights(1,26) + input(j,26)*weights(1,27) + input(j,27)*weights(1,28)+ input(j,28)*weights(1,29) + input(j,29)*weights(1,30) + input(j,30)*weights(1,31)
+ input(j,31)*weights(1,32) + input(j,32)*weights(1,33) + input(j,33)*weights(1,34)+ input(j,34)*weights(1,35) + input(j,35)*weights(1,36)
x2(1) = sigmoid(H1);
% 2nd neuron in the hidden layer
H2 = bias(1,2)*weights(2,1) + input(j,1)*weights(2,2) + input(j,2)*weights(2,3) + input(j,3)*weights(2,4)+ input(j,4)*weights(2,5) + input(j,5)*weights(2,6) + input(j,6)*weights(2,7)
+ input(j,7)*weights(2,8) + input(j,8)*weights(2,9) + input(j,9)*weights(2,10)+ input(j,10)*weights(2,11) + input(j,11)*weights(2,12) + input(j,12)*weights(2,13)
+ input(j,13)*weights(2,14) + input(j,14)*weights(2,15) + input(j,15)*weights(2,16)+ input(j,16)*weights(2,17) + input(j,17)*weights(2,18) + input(j,18)*weights(2,19)
+ input(j,19)*weights(2,20) + input(j,20)*weights(2,21) + input(j,21)*weights(2,22)+ input(j,22)*weights(2,23) + input(j,23)*weights(2,24) + input(j,24)*weights(2,25)
+ input(j,25)*weights(2,26) + input(j,26)*weights(2,27) + input(j,27)*weights(2,28)+ input(j,28)*weights(2,29) + input(j,29)*weights(2,30) + input(j,30)*weights(2,31)
+ input(j,31)*weights(2,32) + input(j,32)*weights(2,33) + input(j,33)*weights(2,34)+ input(j,34)*weights(2,35) + input(j,35)*weights(2,36)
x2(2) = sigmoid(H2);
% 3rd neuron in the hidden layer
H3 = bias(1,3)*weights(3,1) + input(j,1)*weights(3,2) + input(j,2)*weights(3,3) + input(j,3)*weights(3,4)+ input(j,4)*weights(3,5) + input(j,5)*weights(3,6) + input(j,6)*weights(3,7)
+ input(j,7)*weights(3,8) + input(j,8)*weights(3,9) + input(j,9)*weights(3,10)+ input(j,10)*weights(3,11) + input(j,11)*weights(3,12) + input(j,12)*weights(3,13)
+ input(j,13)*weights(3,14) + input(j,14)*weights(3,15) + input(j,15)*weights(3,16)+ input(j,16)*weights(3,17) + input(j,17)*weights(3,18) + input(j,18)*weights(3,19)
+ input(j,19)*weights(3,20) + input(j,20)*weights(3,21) + input(j,21)*weights(3,22)+ input(j,22)*weights(3,23) + input(j,23)*weights(3,24) + input(j,24)*weights(3,25)
+ input(j,25)*weights(3,26) + input(j,26)*weights(3,27) + input(j,27)*weights(3,28)+ input(j,28)*weights(3,29) + input(j,29)*weights(3,30) + input(j,30)*weights(3,31)
+ input(j,31)*weights(3,32) + input(j,32)*weights(3,33) + input(j,33)*weights(3,34)+ input(j,34)*weights(3,35) + input(j,35)*weights(3,36)
x2(3) = sigmoid(H3);
% Output layer
x3_1 = bias(1,4)*weights(4,1) + x2(1)*weights(4,2) + x2(2)*weights(4,3) + x2(3)*weights(4,4);
out(j) = sigmoid(x3_1);
% Adjust delta values of weights
% For output layer: delta(wi) = xi*delta,
% delta = (1-actual output)*(desired output - actual output)
delta3_1 = out(j)*(1-out(j))*(output(j)-out(j));
% Propagate the delta backwards into hidden layers
delta2_1 = x2(1)*(1-x2(1))*weights(3,2)*delta3_1;
delta2_2 = x2(2)*(1-x2(2))*weights(3,3)*delta3_1;
delta2_3 = x2(3)*(1-x2(3))*weights(3,4)*delta3_1;
% Add weight changes to original weights and then use the new weights.
% delta weight = coeff*x*delta
for k = 1:4
if k == 1 % Bias cases
weights(1,k) = weights(1,k) + coeff*bias(1,1)*delta2_1;
weights(2,k) = weights(2,k) + coeff*bias(1,2)*delta2_2;
weights(3,k) = weights(3,k) + coeff*bias(1,3)*delta2_3;
weights(4,k) = weights(4,k) + coeff*bias(1,4)*delta3_1;
else % When k=2 or 3 input cases to neurons
weights(1,k) = weights(1,k) + coeff*input(j,1)*delta2_1;
weights(2,k) = weights(2,k) + coeff*input(j,2)*delta2_2;
weights(3,k) = weights(3,k) + coeff*input(j,3)*delta2_3;
weights(4,k) = weights(4,k) + coeff*x2(k-1)*delta3_1;
end
end
end
end
disp('For the Input');
disp(input);
disp('Output Is');
disp(out);
disp('Test Case: For the Input');
input = [1 1 0 1 1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0];
For me the problem is the labeling, I can't see where do you have the output
Output (1,1,1,1)? What do you mean. Perhaps I miss something but for me there are two ways of labeling a multiclass clasification one is with a label directly (0 for A, 1 for B, 3 for C...) and expanding it after or directly expanded like A=1,0,0,0 = [1,0,0,0;0,1,0,0;0,0,1,0;0,0,0,1]
The way that you make operations is very easy to make a mistakes, take a look to matlab/octave matrix operations, it's very powerful and could simplify everything a lot.

sum of continuous values in matlab

I need to calculate the following in matlab.
EDIT EDIT: I alway have a 16 x 3 matrix. 16 rows and 3 columns.
The 3 columns represent R,G,B and the 16 rows represent points. From 1-16.
An example matrix looks like this:
1 1 1
-1 0 0
0 0 1
1 0 0
-1 0 0
1 0 -1
1 1 1
1 1 1
0 0 0
-1 0 1
1 0 0
0 0 1
1 0 1
0 0 0
0 0 0
1 0 1
Now I need to know are there 11 coherently rows which have min. 1 value ~= 0 in each column?
In the above example the first 8 rows and the last row have in each column min 1 value and are coherently. So this 9 rows are the max coherently rows without a complete zero row between.
Sry that my first post wasn't correct.
I've do that with a really poor for-solution. Is there a faster way (vectorized) to do that?
for i=1:16
for j=0:16
if i+j > 16
value = (i+j)-16;
else
value = i+j;
end
if table(value,1) ~= 0 || table(value,2) ~= 0 || table(value,3) ~= 0
equal = equal + 1;
if equal >= 11
copy(y,x) = 1;
equal = 0;
break;
end
else
equal = 0;
end
end
end
end
And the 16 points are circular. This min the first point and the last point connect.
Thanks for help and sry for the confusing.
This counts the number of coherent rows with at least one none-zero entry without circularity:
B = ~(A==0);
idx = find(sum(B,2) == 0);
result = max([idx;size(A,1)+1] - [0;idx]) - 1;
Now you can check whether result is bigger than 11.
Another way would be:
B = ~(A==0);
C = bwconncomp(sum(B,2)>0);
num = cellfun(#numel,C.PixelIdxList);
result = max(num);
EDIT 2: To account for circularity, i.e. rows at the beginning and the end should be counted as coherent, you could do
B = ~(A==0);
idx = find(sum(B,2) == 0);
result = max([idx;size(A,1)+idx;size(A,1)+1] - [0;idx;size(A,1)+idx]) - 1;
EDIT: I edited the result-line in the first solution according to Knedlsepp's comments.
This is a somewhat clunky solution, but it should give a solution at least if the matrix isn't too big. If you call your matrix m try the following line of code:
log2(max([cumprod(2*logical(m),2),ones(size(m,1),1)],[],2))
I hope this helps!
EDIT:
Now that it is clear what is ment by the question, here's an answer that should work:
find(~[m(:,1)|m(:,2)|m(:,3);0],1)-1 >= 11

Calculate percentage of zeros and ones in my vector?

I've already have my vector and number of zeros and ones with this code:
u=[1 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0]
transitions=(find(u~=[u(2:end), u(end)+1]));
value=u(transitions)
transitions(2:end)=transitions(2:end)-transitions(1:end-1)
i get this
value =
1 0 1 0 1 0
transitions =
5 3 2 7 5 3
Now, please if someone could help me and explain how I can get percentage of ones and percentage of zeros in my vector (all together, and by each value).
Thank You very much.
If I understand you correctly it is very simple:
p1=sum(u)./numel(u); % is the percentage of ones
p2=1-p1; % is the percentage of zeros
Matlab has even this spesific function called tabulate that creates a frequency table just for that:
tabulate(u)
Value Count Percent
0 13 52.00%
1 12 48.00%
This is just psuedocode so it'll need to be translated, but here's a potential solution:
total = 0;
total_ones = 0;
total_zeroes = 0;
for(i=0; i<transitions.length; i++){
total += transitions[i];
if(value[i] == 0)
total_zeroes += transitions[i];
else
total_ones += transitions[i];
}
print("Percent Zeroes: " + (total_zeroes/total)*100);
print("Percent Ones: " + (total_ones/total)*100);
#To print each group's percent it'd be along the lines of the following:
for(i=0; i<transitions.length; i++){
print("Percent of total comprised of this group: " + (transitions[i]/total)*100)
}

Effiicient ways to count a streak of consecutive integers in MATLAB

Say I have a vector containing only logical values, such as
V = [1 0 1 0 1 1 1 1 0 0]
I would like to write a function in MATLAB which returns a 'streak' vector S for V, where S(i) represents the number of consecutive 1s in V up to but not including V(i). For the example above, the streak vector would be
S = [0 1 0 1 0 1 2 3 4 0]
Given that I have to do this for a very large matrix, I would very much appreciate any solution that is vectorized / efficient.
This should do the trick:
S = zeros(size(V));
for i=2:length(V)
if(V(i-1)==1)
S(i) = 1 + S(i-1);
end
end
The complexity is only O(n), which I guess should be good enough.
For your sample input:
V = [1 0 1 0 1 1 1 1 0 0];
S = zeros(size(V));
for i=2:length(V)
if(V(i-1)==1)
S(i) = 1 + S(i-1);
end
end
display(V);
display(S);
The result would be:
V =
1 0 1 0 1 1 1 1 0 0
S =
0 1 0 1 0 1 2 3 4 0
You could also do it completely vectorized with a couple intermediate steps:
V = [1 0 1 0 1 1 1 1 0 0];
Sall = cumsum(V);
stopidx = find(diff(V)==-1)+1;
V2=V;
V2(stopidx) = -Sall(stopidx)+[0 Sall(stopidx(1:end-1))];
S2 = cumsum(V2);
S = [0 S2(1:end-1)];
Afaik the only thing that can take a while is the find call; you can't use logical indexing everywhere and bypass the find call, because you need the absolute indices.
It's outside the box - but have you considered using text functions? Since strings are just vectors for Matlab it should be easy to use them.
Regexp contains some nice functions for finding repeated values.