Implementing a Neural Network in Matlab/Octave - matlab
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.
Related
How to create this particular fractal pattern in MATLAB?
I need to make an array of zeros and ones in this particular fractal pattern: 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 1 0 1 0 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 The actual array should be 100 x 100. The pattern should start from the middle (x,y) coordinate, and expand to look like the pattern (using loops). So far, I have only managed to make a pattern that looks like a '+' sign. I am not sure how to continue it. This is my code so far: n = zeros(16); % using 16x16 array for practice x = length(n)/2; y = length(n)/2; z = length(n) - 1; xso = length(n)/2; % x axis south movement xno = length(n)/2; % x axis north movement yea = length(n)/2; % y axis east movement ywe = length(n)/2; % y axis west movement for i = 1:1:z newyea = move('east', x, yea); n(x, newyea) = 1; yea = newyea; newywe = move('west', x, ywe); n(x, newywe) = 1; ywe = newywe; newxso = move('south', xso, y); n(newxso, y) = 1; xso = newxso; newxno = move('north', xno, y); n(newxno, y) = 1; xno = newxno; end I also have a user defined function: function newval = move(dir, x, y) switch dir case 'east' newval = y + 1; case 'west' newval = y - 1; case 'south' newval = x + 1; case 'north' newval = x - 1; end
Since there were no restrictions given on the appearance of the loop, I would propose the below solution. But, before, let's have a look at your given example: Either you should restrict the desired dimension d to be odd, i.e. d = 11, 13, 15, ... or you should specify, how the pattern should be continued in case of an even dimension d, like here d = 12. For my solution, I decided to rely on the dimension d to be odd. Here's the code: d = 15; % Dimension A = zeros(d); % Initialize output array A c = (d + 1) / 2; % Calculate center index (row, column) A(:, c) = 1; % Add: Cross A(c, :) = 1; J = 0; % Auxiliary index for I = (c+2):2:d % For every second row (or column) from center to border J = J + 1; l = 4 * J - 1; % Calculate length of line to draw s = c - (l-1)/2; % Calculate start point of line e = c + (l-1)/2; % Calculate end point of line A(I, s:e) = 1; % Add: "South" line A(s:e, I) = 1; % Add: "East" line A(c - 2*J, s:e) = 1; % Add: "North" line A(s:e, c - 2*J) = 1; % Add: "West" line end figure(1); % Show image imagesc(A); Output for d = 15 (to compare to given example): Output for d = 99: Hope that helps! If you have some more stricter limitations on the for loop, let me/us know. Then, I will try to modify my code accordingly.
Matlab algorithm for obtain the original numbers of a sum of random numbers
Have 8 people in a room seated in a round table and each of them chose a random number and sum with the number of the people in his right and left side. The results are bring to you in order where people was in the table, how you can obtain the original number what each one chose? Lower_rand_limit = 1; Upper_rand_Limit = 100; Number_of_colums = 8; Number_of_lines = 1; Random_matrix = randi([Lower_rand_limit Upper_rand_Limit], Number_of_lines, Number_of_colums) Sum_matrix = zeros(Number_of_lines, Number_of_colums); for i = 1:Number_of_colums if i == 1 Sum_matrix(Number_of_lines, i) = Random_matrix(Number_of_lines, Number_of_colums) + Random_matrix(Number_of_lines, i) + Random_matrix(Number_of_lines, i + 1); elseif i == Number_of_colums Sum_matrix(Number_of_lines, i) = Random_matrix(Number_of_lines, Number_of_colums- 1) + Random_matrix(Number_of_lines, Number_of_colums) + Random_matrix(Number_of_lines, 1); else Sum_matrix(Number_of_lines, i) = Random_matrix(Number_of_lines, i - 1) + Random_matrix(Number_of_lines, i) + Random_matrix(Number_of_lines, i + 1); end end Sum_matrix Now only whit the Sum_matrix how can i obtain the original Randon_matrix? Thanks to the answear of nikaltipar it's working now, for who want see the entire code he it's here: Lower_rand_limit = 1; Upper_rand_Limit = 100; Number_of_colums = 1; Number_of_lines = 8; Random_matrix = randi([Lower_rand_limit Upper_rand_Limit], Number_of_lines, Number_of_colums) Sum_matrix = zeros(Number_of_lines, Number_of_colums); for i = 1:Number_of_lines if i == 1 Sum_matrix(i, 1) = Random_matrix(Number_of_lines, 1) + Random_matrix(i, 1) + Random_matrix(i + 1, 1); elseif i == Number_of_lines Sum_matrix(i, 1) = Random_matrix(Number_of_lines - 1, 1) + Random_matrix(Number_of_lines, 1) + Random_matrix(1, 1); else Sum_matrix(i, 1) = Random_matrix(i - 1, 1) + Random_matrix(i, 1) + Random_matrix(i + 1, 1); end end Sum_matrix A = [1 1 0 0 0 0 0 1; 1 1 1 0 0 0 0 0; 0 1 1 1 0 0 0 0; 0 0 1 1 1 0 0 0; 0 0 0 1 1 1 0 0; 0 0 0 0 1 1 1 0; 0 0 0 0 0 1 1 1; 1 0 0 0 0 0 1 1]; Result_matrix = A\Sum_matrix; Result_matrix
Something like this? function [ x ] = original_numbers( b ) A = [1 1 0 0 0 0 0 1; 1 1 1 0 0 0 0 0; 0 1 1 1 0 0 0 0; 0 0 1 1 1 0 0 0; 0 0 0 1 1 1 0 0; 0 0 0 0 1 1 1 0; 0 0 0 0 0 1 1 1; 1 0 0 0 0 0 1 1]; x = A\b; end You provide b which is a column vector with the sums as you have described, and the output x consists of the original number the people in the table came up with. e.g b = [1; 2; 3; 4; 5; 6; 7; 8]; original_numbers(b) ans = 3 -2 1 4 -1 2 5 0
How to create a diamond filled with one in the middle of a matrix?
I know the code below : N = 5; assert(N>1 && mod(N,2)==1); A = zeros(N); % diamond mask N2 = fix(N/2); [I,J] = meshgrid(-N2:N2); mask = (abs(I) + abs(J)) == N2; % fill with zeros A(mask) = 1; which transforms matrix A to this: A= 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 0 But I want the diamond to be filled with 1. What should I do?
Here's a vectorized approach using bsxfun - Nh = (N+1)/2; range_vec = [1:Nh Nh-1:-1:1]; out = bsxfun(#plus,range_vec(:),range_vec) > Nh Sample runs - 1) N = 5 : out = 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 2) N = 9 : out = 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0
You can use tril and flip functions: mat = tril(ones(N), round((N-1)/2)) - tril(ones(N), round((-N-1)/2)); out = mat & flip(mat) Odd values of N: % N = 5; out = 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0 Even values of N: % N = 4; out = 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0
What you need is to return a 1 or a 0 based on the Manhattan distance from each array location to the center of your diamond N = 5; assert(N>1 && mod(N,2)==1); A = false(N); [m, n] = size(A); %dimensions of A X = floor([m, n]/2); %floored division gives integer indices of center of array x = X(1); y = X(2); radius = m/2; %half the height gives the radius for a = 1 : m for b = 1 : n A(a,b) = abs(a-x)+abs(b-y) <= radius; %test if manhatten distance <= radius end end This naturally will need editing to suit your particular case... In particular, the center of your diamond can realistically be placed anywhere by modifying x, y, and the radius can be either smaller or larger than half the width of the array if you so choose.
Just add a for loop and fill all diagonals: N = 5; assert(N>1 && mod(N,2)==1); A = zeros(N); % diamond mask N2 = fix(N/2); [I,J] = meshgrid(-N2:N2); for id = 0:N2 A((abs(I) + abs(J)) == id) = 1; end
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.
How do I average elements of a matrix according to an identity matrix?
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);