Simon Funk vs. Matlabs SVDS - matlab

I want to build an recommender system using Simon Funks' algorithm.
The idea is to first construct the model offline in Matlab to perform some evaluation on the results to what number of features (or dimensions) gives the best performance.
I have a matrix with users x items, where the rating '0' means that the user has not given a rating for that item.
So far I have tried to implement Simon Funks' algorithm in Matlab (see source-code) below, but it performs really (!) bad. By accident I found Matlab's SVDS function to fill the empty ratings and it actually performs better and faster then my Simon Funks' function
Could someone tell me what could be cause of this? Or tell me what stupid mistake I have made in Matlab function? :P
function ratings = simon_funk(original_ratings, dimensions) % To construct a complete rating matrix
% See: http://www.timelydevelopment.com/demos/NetflixPrize.aspx
% Variables
global max_features; max_features = dimensions;
global init; init = 0.1;
min_epochs = 2;
max_epochs = 16;
min_improvement = 0.001;
lrate = 0.01;
k = 0.015;
respondent_count = size(original_ratings, 1);
item_count = size(original_ratings, 2);
rating_count = 0;
data = [];
for r=1:respondent_count
for i=1:item_count
rating = original_ratings(r,i);
if(rating > 0)
data = [data; [r, i, rating, 0]];
rating_count = rating_count + 1;
end
end
end
% Now data contain all ratings in the form [user_id, item_id, rating, cache (default 0)]
ratings = zeros(respondent_count, item_count);
global item_features; item_features = zeros(max_features, item_count);
global respondent_features; respondent_features = zeros(max_features, respondent_count);
% Init
item_features(:,:) = init;
respondent_features(:,:) = init;
% CalcFeatures
rmse_last = 2.0;
rmse = 2.0;
for f=1:max_features
for e=1:max_epochs
sq = 0;
rmse_last = rmse;
for r=1:rating_count
% for i=1:item_count
respondent = data(r,1);
item = data(r,2);
rating = data(r,3);
% Predict rating
p = simon_funk_predict_rating(data(r,:), f, 1);
err = (1.0 * rating - p);
sq = sq + err*err;
rf = respondent_features(f,respondent);
mf = item_features(f, item);
% Cross-train the features
respondent_features(f, respondent) = respondent_features(f,respondent) + (lrate * (err * mf - k * rf));
item_features(f, item) = item_features(f, item) + (lrate * (err * rf - k * mf));
% end
end
rmse = sqrt(sq/rating_count);
%if (e >= min_epochs && rmse > (rmse_last - min_improvement))
if ((e >= min_epochs) && ((rmse_last - rmse) < min_improvement))
break;
end
end
% Caching
for r=1:rating_count
data(r, 4) = simon_funk_predict_rating(data(r,:), f, 0);
end
end
% return new ratings set
for r=1:respondent_count
for i=1:item_count
sum = 1;
for f=1:max_features
sum = sum + item_features(f,i) * respondent_features(f,r);
if(sum > 10)
% sum = 10;
end
if(sum < 1)
% sum = 1;
end
end
ratings(r,i) = sum;
end
end
And the function to predict an individual rating:
function sum = simon_funk_predict_rating(rating, f, bTrailing)
global item_features;
global respondent_features;
global max_features;
global init;
respondent = rating(1,1);
item = rating(1,2);
cache_value = rating(1,4);
sum = 1;
if(cache_value > 0)
sum = cache_value;
end
sum = sum + (item_features(f,item) * respondent_features(f,respondent));
if (sum > 10)
%sum = 10;
end
if (sum < 1)
%sum = 1;
end
if (bTrailing == 1)
sum = sum + (max_features - f - 1) * (init * init);
if (sum > 10)
sum = 10;
end
if (sum < 1)
sum = 1;
end
end
Thank you very much!

Related

Berlekamp Massey Algorithm for BCH simplified binary version

I am trying to follow Lin, Costello's explanation of the simplified BM algorithm for the binary case in page 210 of chapter 6 with no success on finding the error locator polynomial.
I'm trying to implement it in MATLAB like this:
function [locator_polynom] = compute_error_locator(syndrome, t, m, field, alpha_powers)
%
% Initial conditions for the BM algorithm
polynom_length = 2*t;
syndrome = [syndrome; zeros(3, 1)];
% Delta matrix storing the powers of alpha in the corresponding place
delta_rho = uint32(zeros(polynom_length, 1)); delta_rho(1)=1;
delta_next = uint32(zeros(polynom_length, 1));
% Premilimnary values
n_max = uint32(2^m - 1);
% Initialize step mu = 1
delta_next(1) = 1; delta_next(2) = syndrome(1); % 1 + S1*X
% The discrepancy is stored in polynomial representation as uint32 numbers
value = gf_mul_elements(delta_next(2), syndrome(2), field, alpha_powers, n_max);
discrepancy_next = bitxor(syndrome(3), value);
% The degree of the locator polynomial
locator_degree_rho = 0;
locator_degree_next = 1;
% Update all values
locator_polynom = delta_next;
delta_current = delta_next;
discrepancy_rho = syndrome(1);
discrepancy_current = discrepancy_next;
locator_degree_current = locator_degree_next;
rho = 0; % The row with the maximum value of 2mu - l starts at 1
for i = 1:t % Only the even steps are needed (so make t out of 2*t)
if discrepancy_current ~= 0
% Compute the correction factor
correction_factor = uint32(zeros(polynom_length, 1));
x_exponent = 2*(i - rho);
if (discrepancy_current == 1 || discrepancy_rho == 1)
d_mu_times_rho = discrepancy_current * discrepancy_rho;
else
alpha_discrepancy_mu = alpha_powers(discrepancy_current);
alpha_discrepancy_rho = alpha_powers(discrepancy_rho);
alpha_inver_discrepancy_rho = n_max - alpha_discrepancy_rho;
% The alpha power for dmu * drho^-1 is
alpha_d_mu_times_rho = alpha_discrepancy_mu + alpha_inver_discrepancy_rho;
% Equivalent to aux mod(2^m - 1)
alpha_d_mu_times_rho = alpha_d_mu_times_rho - ...
n_max * uint32(alpha_d_mu_times_rho > n_max);
d_mu_times_rho = field(alpha_d_mu_times_rho);
end
correction_factor(x_exponent+1) = d_mu_times_rho;
correction_factor = gf_mul_polynoms(correction_factor,...
delta_rho,...
field, alpha_powers, n_max);
% Finally we add the correction factor to get the new delta
delta_next = bitxor(delta_current, correction_factor(1:polynom_length));
% Update used data
l = polynom_length;
while delta_next(l) == 0 && l>0
l = l - 1;
end
locator_degree_next = l-1;
% Update previous maximum if the degree is higher than recorded
if (2*i - locator_degree_current) > (2*rho - locator_degree_rho)
locator_degree_rho = locator_degree_current;
delta_rho = delta_current;
discrepancy_rho = discrepancy_current;
rho = i;
end
else
% If the discrepancy is 0, the locator polynomial for this step
% is passed to the next one. It satifies all newtons' equations
% until now.
delta_next = delta_current;
end
% Compute the discrepancy for the next step
syndrome_start_index = 2 * i + 3;
discrepancy_next = syndrome(syndrome_start_index); % First value
for k = 1:locator_degree_next
value = gf_mul_elements(delta_next(k + 1), ...
syndrome(syndrome_start_index - k), ...
field, alpha_powers, n_max);
discrepancy_next = bitxor(discrepancy_next, value);
end
% Update all values
locator_polynom = delta_next;
delta_current = delta_next;
discrepancy_current = discrepancy_next;
locator_degree_current = locator_degree_next;
end
end
I'm trying to see what's wrong but I can't. It works for the examples in the book, but not always. As an aside, to compute the discrepancy S_2mu+3 is needed, but when I have only 24 syndrome coefficients how is it computed on step 11 where 2*11 + 3 is 25?
Thanks in advance!
It turns out the code is ok. I made a different implementation from Error Correction and Coding. Mathematical Methods and gives the same result. My problem is at the Chien Search.
Code for the interested:
function [c] = compute_error_locator_v2(syndrome, m, field, alpha_powers)
%
% Initial conditions for the BM algorithm
% Premilimnary values
N = length(syndrome);
n_max = uint32(2^m - 1);
polynom_length = N/2 + 1;
L = 0; % The curent length of the LFSR
% The current connection polynomial
c = uint32(zeros(polynom_length, 1)); c(1) = 1;
% The connection polynomial before last length change
p = uint32(zeros(polynom_length, 1)); p(1) = 1;
l = 1; % l is k - m, the amount of shift in update
dm = 1; % The previous discrepancy
for k = 1:2:N % For k = 1 to N in steps of 2
% ========= Compute discrepancy ==========
d = syndrome(k);
for i = 1:L
aux = gf_mul_elements(c(i+1), syndrome(k-i), field, alpha_powers, n_max);
d = bitxor(d, aux);
end
if d == 0 % No change in polynomial
l = l + 1;
else
% ======== Update c ========
t = c;
% Compute the correction factor
correction_factor = uint32(zeros(polynom_length, 1));
% This is d * dm^-1
dd_sum = modulo(alpha_powers(d) + n_max - alpha_powers(dm), n_max);
for i = 0:polynom_length - 1
if p(i+1) ~= 0
% Here we compute d*d^-1*p(x_i)
ddp_sum = modulo(dd_sum + alpha_powers(p(i+1)), n_max);
if ddp_sum == 0
correction_factor(i + l + 1) = 1;
else
correction_factor(i + l + 1) = field(ddp_sum);
end
end
end
% Finally we add the correction factor to get the new locator
c = bitxor(c, correction_factor);
if (2*L >= k) % No length change in update
l = l + 1;
else
p = t;
L = k - L;
dm = d;
l = 1;
end
end
l = l + 1;
end
end
The code comes from this implementation of the Massey algorithm

Poisson PDE solver on a disked shaped domain with finite difference method using matlab

For my studies I had to write a PDE solver for the Poisson equation on a disc shaped domain using the finite difference method.
I already passed the Lab exercise. There is one issue in my code I couldn't fix. Function fun1 with the boundary value problem gun2 is somehow oscillating at the boundary. When I use fun2 everything seems fine...
Both functions use at the boundary gun2. What is the problem?
function z = fun1(x,y)
r = sqrt(x.^2+y.^2);
z = zeros(size(x));
if( r < 0.25)
z = -10^8*exp(1./(r.^2-1/16));
end
end
function z = fun2(x,y)
z = 100*sin(2*pi*x).*sin(2*pi*y);
end
function z = gun2(x,y)
z = x.^2+y.^2;
end
function [u,A] = poisson2(funame,guname,M)
if nargin < 3
M = 50;
end
%Mesh Grid Generation
h = 2/(M + 1);
x = -1:h:1;
y = -1:h:1;
[X,Y] = meshgrid(x,y);
CI = ((X.^2 +Y.^2) < 1);
%Boundary Elements
Sum= zeros(size(CI));
%Sum over the neighbours
for i = -1:1
Sum = Sum + circshift(CI,[i,0]) + circshift(CI,[0,i]) ;
end
%if sum of neighbours larger 3 -> inner note!
CI = (Sum > 3);
%else boundary
CB = (Sum < 3 & Sum ~= 0);
Sum= zeros(size(CI));
%Sum over the boundary neighbour nodes....
for i = -1:1
Sum = Sum + circshift(CB,[i,0]) + circshift(CB,[0,i]);
end
%If the sum is equal 2 -> Diagonal boundary
CB = CB + (Sum == 2 & CB == 0 & CI == 0);
%Converting X Y to polar coordinates
Phi = atan(Y./X);
%Converting Phi R back to cartesian coordinates, only at the boundarys
for j = 1:M+2
for i = 1:M+2
if (CB(i,j)~=0)
if j > (M+2)/2
sig = 1;
else
sig = -1;
end
X(i,j) = sig*1*cos(Phi(i,j));
Y(i,j) = sig*1*sin(Phi(i,j));
end
end
end
%Numberize the internal notes u1,u2,......,un
CI = CI.*reshape(cumsum(CI(:)),size(CI));
%Number of internal notes
Ni = nnz(CI);
f = zeros(Ni,1);
k = 1;
A = spalloc(Ni,Ni,5*Ni);
%Create matix A!
for j=2:M+1
for i =2:M+1
if(CI(i,j) ~= 0)
hN = h;hS = h; hW = h; hE = h;
f(k) = fun(X(i,j),Y(i,j));
if(CB(i+1,j) ~= 0)
hN = abs(1-sqrt(X(i,j)^2+Y(i,j)^2));
f(k) = f(k) + gun(X(i,j),Y(i+1,j))*2/(hN^2+hN*h);
A(k,CI(i-1,j)) = -2/(h^2+h*hN);
else
if(CB(i-1,j) ~= 0) %in negative y is a boundry
hS = abs(1-sqrt(X(i,j)^2+Y(i,j)^2));
f(k) = f(k) + gun(X(i,j),Y(i-1,j))*2/(hS^2+h*hS);
A(k,CI(i+1,j)) = -2/(h^2+h*hS);
else
A(k,CI(i-1,j)) = -1/h^2;
A(k,CI(i+1,j)) = -1/h^2;
end
end
if(CB(i,j+1) ~= 0)
hE = abs(1-sqrt(X(i,j)^2+Y(i,j)^2));
f(k) = f(k) + gun(X(i,j+1),Y(i,j))*2/(hE^2+hE*h);
A(k,CI(i,j-1)) = -2/(h^2+h*hE);
else
if(CB(i,j-1) ~= 0)
hW = abs(1-sqrt(X(i,j)^2+Y(i,j)^2));
f(k) = f(k) + gun(X(i,j-1),Y(i,j))*2/(hW^2+h*hW);
A(k,CI(i,j+1)) = -2/(h^2+h*hW);
else
A(k,CI(i,j-1)) = -1/h^2;
A(k,CI(i,j+1)) = -1/h^2;
end
end
A(k,k) = (2/(hE*hW)+2/(hN*hS));
k = k + 1;
end
end
end
%Solve linear system
u = A\f;
U = zeros(M+2,M+2);
p = 1;
%re-arange u
for j = 1:M+2
for i = 1:M+2
if ( CI(i,j) ~= 0)
U(i,j) = u(p);
p = p+1;
else
if ( CB(i,j) ~= 0)
U(i,j) = gun(X(i,j),Y(i,j));
else
U(i,j) = NaN;
end
end
end
end
surf(X,Y,U);
end
I'm keeping this answer short for now, but may extend when the question contains more info.
My first guess is that what you are seeing is just numerical errors. Looking at the scales of the two graphs, the peaks in the first graph are relatively small compared to the signal in the second graph. Maybe there is a similar issue in the second that is just not visible because the signal is much bigger. You could try to increase the number of nodes and observe what happens with the result.
You should always expect to see numerical errors in such simulations. It's only a matter of trying to get their magnitude as small as possible (or as small as needed).

Is the Gabor filter implementation and frequency response in matlab correct?

I am trying to implement the Gabor filter in matlab as exactly on the formular (Real part) at
Wikipedia and StackOverflow, also shown here and also plot the frequency response. I have the code below.
Is this implementation and the responses generated correct?
If not, any help would be appreciated.
function gbImg = gaborFilter()
a = 512; b = 512;
delta = 7/3;
yeta = 1;
lambda = 7;
theta.zero = 0; theta.fortyfive = pi/4; theta.ninety = pi/2;
theta.onethirtyfive = (3*pi)/4;
xprime = #(x,y,tetat) ((x * cos(tetat)) + (y* sin(tetat)));
yprime = #(x,y,tetat) (-(x * sin(tetat)) + (y* cos(tetat)));
count = 1;
for th = fieldnames(theta)'
for i=1:19
for j=1:19
h_gb.(th{1})(i,j) = exp(-(xprime(i,j,theta.(th{1}))^2 + (yeta^2 * yprime(i,j,theta.(th{1}))^2))/(2*delta^2) ) * cos(((2*pi*xprime(i,j,theta.(th{1})))/lambda)+pi/2); % + theta.(th{1}));
end
end
[gbImg.(th{1}),fx,fy] = freqz2(h_gb.(th{1}),a,b);
[Fx,Fy] = meshgrid(fx,fy);
figure(count);
mesh(Fx,Fy,abs(gbImg.(th{1})));
count = count +1;
end
end

Smallest integer greater than or equal to harmonic series of input

I'm working on the following problem:
I realize my code is a bit off, but I want to create a for loop that will determine whether or not the integer x (the input value) is at least less than or equal to the sum of a harmonic series.
Here is what I have so far:
function n =one_per_n(x)
if x > 10000
n = -1;
end
total = 0;
i = 0;
for i = 1:10000
if x >= total
n = ceil(total);
else
total = (1/i) + total;
end
end
I've added my attempt at a while loop. I realize it's wrong, but any help would be appreciated.
function n =one_per_n(x)
if x > 10000
n = -1;
end
total = 0;
i = 0;
for i = 1:10000
while total <= x
total = (1/i) + total;
end
end
n = total;
you don't need to use some loops:
function n = one_per_n(x)
lim = min(10000,exp(x));
value = cumsum(1./(1:lim));
n = find(value >= x,1);
if isempty(n)
n = -1;
end
A while loop is a better option in this case I think
function [total, n] = one_per_n(x)
% This is a good initial check, good work
if x > 10000
n = -1;
return;
end
% Initialize the variables
total = 0;
n = 0;
% While not finished
while (total < x)
% Number of terms
n = n + 1;
total = total + 1/n;
end
end

Store an unknown number of vectors into a cell array

How to store all the vectors s into a cell array, so that I can use it later. the number of vectors s is not specific, it depends on the condition while sigma > sigma_min. Can anyone help me?
A_pinv = A'* inv(A * A');
s = A_pinv * X
sigma = 2*max(abs(s));
sigma_min = 0.0001;
sigma_decrease_factor = 0.5;
while sigma>sigma_min
for i = 1:L
delta = s.*exp(-abs(s).^2/sigma^2);
s = s - 0.5*delta;
s = s - A_pinv*(A*s - X);
end
sigma = sigma * sigma_decrease_factor;
end
I haven't tested it, but I think it will work,
count = 0;
Data = {};
while sigma>sigma_min
count = count + 1;
for i = 1:L
delta = s.*exp(-abs(s).^2/sigma^2);
s = s - 0.5*delta;
s = s - A_pinv*(A*s - X);
end
Data{count} = s;
sigma = sigma * sigma_decrease_factor;
end