Consider a Matlab matrix B which lists all possible unordered pairs (without repetitions) from [1 2 ... n]. For example, if n=4,
B=[1 2;
1 3;
1 4;
2 3;
2 4;
3 4]
Note that B has size n(n-1)/2 x 2
I want to take a random draw of m rows from B and store them in a matrix C. Continuing the example above, I could do that as
m=2;
C=B(randi([1 size(B,1)],m,1),:);
However, in my actual case, n=371293. Hence, I cannot create B and, then, run the code above to obtain C. This is because storing B would require a huge amount of memory.
Could you advise on how I could proceed to create C, without having to first store B? Comments on a different question suggest to
Draw at random m integers between 1 and n(n-1)/2.
I=randi([1 n*(n-1)/2],m,1);
Use ind2sub to obtain C.
Here, I'm struggling to implement the second step.
Thanks to the comments below, I wrote this
n=4;
m=10;
coord=NaN(m,2);
R= randi([1 n^2],m,1);
for i=1:m
[cr, cc]=ind2sub([n,n],R(i));
if cr>cc
coord(i,1)=cc;
coord(i,2)=cr;
elseif cr<cc
coord(i,1)=cr;
coord(i,2)=cc;
end
end
coord(any(isnan(coord),2),:) = []; %delete NaN rows from coord
I guess there are more efficient ways to implement the same thing.
You can use the function named myind2ind in this post to take random rows of all possible unordered pairs without generating all of them.
function [R , C] = myind2ind(ii, N)
jj = N * (N - 1) / 2 + 1 - ii;
r = (1 + sqrt(8 * jj)) / 2;
R = N -floor(r);
idx_first = (floor(r + 1) .* floor(r)) / 2;
C = idx_first-jj + R + 1;
end
I=randi([1 n*(n-1)/2],m,1);
[C1 C2] = myind2ind (I, n);
If you look at the odds, for i=1:n-1, the number of combinations where the first value is equal to i is (n-i) and the total number of cominations is n*(n-1)/2. You can use this law to generate the first column of C. The values of the second column of C can then be generated randomly as integers uniformly distributed in the range [i+1, n]. Here is a code that performs the desired tasks:
clc; clear all; close all;
% Parameters
n = 371293; m = 10;
% Generation of C
R = rand(m,1);
C = zeros(m,2);
s = 0;
t = n*(n-1)/2;
for i=1:n-1
if (i<n-1)
ind_i = R>=s/t & R<(s+n-i)/t;
else % To avoid rounding errors for n>>1, we impose (s+n-i)=t at the last iteration (R<(s+n-i)/t=1 always true)
ind_i = R>=s/t;
end
C(ind_i,1) = i;
C(ind_i,2) = randi([i+1,n],sum(ind_i),1);
s = s+n-i;
end
% Display
C
Output:
C =
84333 266452
46609 223000
176395 328914
84865 94391
104444 227034
221905 302546
227497 335959
188486 344305
164789 266497
153603 354932
Good luck!
below is my code to perform jacobi iterations to solve Ax=b.
I try this code on the matrix A =[4 -1 1; 4 -8 1; -2 1 5] and b=[7 -21 15].
and x is a first guess 1 x 3 vector. Are not these dimensions correct? It gives me the error in the code that calculates: r = b - x*A
and M\(x*N + b)
What am I missing?!? how do I fix this? please help!
function [x, error, iter, flag] = jacobi(A, x, b, maxiter, tol)
%implement jacobi iterations
%[x, error, iter, flag] = jacobi(A, x, b, maxiter, tol)
%jacobi.m solves the linear system Ax=b using the Jacobi iteration
%
%
%INPUT A the matrix of the system Ax=b
% x the first guess vector Ax=b
% b the vector in the system
% maxiter the maximum number of iteration to perform
% tol the tolerance
%
%OUTPUT x the solution vector
% error error norm
% niter the number of iterations it took
% flag indicates whether a solution was found. 0 means there was a
% solution and 1 means there was not a solution
iter = 0;
flag = 0;
bnrm2 = norm(b);
if (bnrm2 == 0)
bnrm2 = 1.0;
end
r = b - x*A;
error = norm(r) / bnrm2;
if (error<tol)
return;
end
[m,n] = size(A);
M = diag(diag(A));
N = diag(diag(A)) - A;
for iter = 1:maxiter,
oldx = x;
x = M\(x*N + b);
error = norm(x - oldx) / norm(x);
if (error <= tol)
break;
end
end
if (error > tol)
flag = 1;
end
Since, in the code, you're solving what I'll call (not sure if it's proper since I never do it) the left-multiply problem, the operator and order of matrices are, in some sense, reversed.
If you were solving the problem A*x = b with the residual r = b - A*x (i.e., x and b are column vectors), you would perform right-vector multiplies and left-matrix divides. Therefore, the update line in the loop would be
x = M \ (N*x + b);
Conversely, if you were solving the problem x*A = b with the residual r = b - x*A (i.e., x and b are row vectors), you would perform left-vector multiplies and right-matrix divides. Therefore, the update line in the loop would be
x = (x*N + b) / M;
Note that \ resolves to the function mldivide and / resolves to mrdivide. There is no function distinction for the multiply.
It appears your current updater mixes the two, which is bad news bears for dimension matching.
I need to create arbitrary perpendicular vector n with components (a, b, c) to another known vector k with components (x,y,z).
The following code creates arbitrary vector n, but I need random numbers for components in the range [-inf, inf] how can I acheive that? (because otherwise vector components created may not exceed some value in given case 10^11 ) Or maybe concept "arbitrary vector" does not require that?
function [a,b,c] = randomOrghogonalVector(x,y,z)
a = 0;
b = 0;
c = 0;
randomDistr = rand * 10^11 * 2 - 10^11; % issue 1
% excluding trivial solution
if x == 0 && y == 0 && z ==0
a = NaN; b = a; c = a;
else
if z ~=0
a = randomDistr;
b = randomDistr;
c = - (x * a + b * y ) / z;
else
if z == 0 && x ~= 0
c = randomDistr;
b = randomDistr;
a = - (z * c + b * y ) / x;
else
if z == 0 && x == 0 && y ~= 0
c = randomDistr;
a = randomDistr;
b = - (z * c + a * x ) / y;
end
end
end
end
The easiest solution I see is to first find a random vector that is orthogonal to your original vector, and then give it a random length. In Matlab, this can be done by defining the following function
function [a, b, c] = orthoVector(x, y, z)
xin = [x;y;z];
e = xin;
while ((e'*xin)==xin'*xin)
e = 2.*rand(3,1)-1;
end
xout = cross(xin, e);
xout = 1.0/(rand()) * xout;
a = xout(1);
b = xout(2);
c = xout(3);
end
Line-by-line, here's what I'm doing:
you asked for this format [a,b,c] = f(x,y,z). I would recommend using function xout = orthoVector(xin), which would make this code even shorter.
Since Matlab handles vectors best as vectors, I'm creating vector xin.
e will be one random vector, different from xin used to compute the orthogonal vector. Since we're dealing with random vectors, we initialize it to be equal to xin.
For this algorithm to work, we need to make sure that e and xin are pointing in different directions. Until this is the case...
...create a new random vector e. Note that rand will give values between 0 and 1. Thus, each component of e will be between -1 and 1.
Ok, if we end, e and xin are pointing in different directions
Our vector xout will be orthogonal to xin and e.
Let's multiply vector xout by a random number between 1 and "very large"
a is first component of xout
b is second component of xout
c is third component of xout
all done.
Optional: if you want to have very large vectors, you could replace line 8 by
xout = exp(1./rand())/(rand()) * xout;
This will give you a very large spread of values.
Hope this helps, cheers!
Suppose we are given a training dataset {yᵢ, xᵢ}, for i = 1, ..., n, where yᵢ can either be -1 or 1 and xᵢ can be e.g. a 2D or 3D point.
In general, when the input points are linearly separable, the SVM model can be defined as follows
min 1/2*||w||²
w,b
subject to the constraints (for i = 1, ..., n)
yᵢ*(w*xᵢ - b) >= 1
This is often called the hard-margin SVM model, which is thus a constrained minimization problem, where the unknowns are w and b. We can also omit 1/2 in the function to be minimized, given it's just a constant.
Now, the documentation about Matlab's quadprog states
x = quadprog(H, f, A, b) minimizes 1/2*x'*H*x + f'*x subject to the restrictions A*x ≤ b. A is a matrix of doubles, and b is a vector of doubles.
We can implement the hard-margin SVM model using quadprog function, to get the weight vector w, as follows
H becomes an identity matrix.
f' becomes a zeros matrix.
A is the left-hand side of the constraints
b is equal to -1 because the original constraint had >= 1, it becomes <= -1 when we multiply with -1 on both sides.
Now, I am trying to implement a soft-margin SVM model. The minimization equation here is
min (1/2)*||w||² + C*(∑ ζᵢ)
w,b
subject to the constraints (for i = 1, ..., n)
yᵢ*(w*xᵢ - b) >= 1 - ζᵢ
such that ζᵢ >= 0, where ∑ is the summation symbol, ζᵢ = max(0, 1 - yᵢ*(w*xᵢ - b)) and C is a hyper-parameter.
How can this optimization problem be solved using the Matlab's quadprog function? It's not clear to me how the equation should be mapped to the parameters of the quadprog function.
The "primal" form of the soft-margin SVM model (i.e. the definition above) can be converted to a "dual" form. I did that, and I am able to get the Lagrange variable values (in the dual form). However, I would like to know if I can use quadprog to solve directly the primal form without needing to convert it to the dual form.
I don't see how it can be a problem. Let z be our vector of (2n + 1) variables:
z = (w, eps, b)
Then, H becomes diagonal matrix with first n values on the diagonal equal to 1 and the last n + 1 set to zero:
H = diag([ones(1, n), zeros(1, n + 1)])
Vector f can be expressed as:
f = [zeros(1, n), C * ones(1, n), 0]'
First set of constrains becomes:
Aineq = [A1, eye(n), zeros(n, 1)]
bineq = ones(n, 1)
where A1 is a the same matrix as in primal form.
Second set of constraints becomes lower bounds:
lb = (inf(n, 1), zeros(n, 1), inf(n, 1))
Then you can call MATLAB:
z = quadprog(H, f, Aineq, bineq, [], [], lb);
P.S. I can be mistaken in some small details, but the general idea is right.
I wanted to clarify #vharavy answer because you could get lost while trying to deduce what 'n' means in his code. Here is my version according to his answer and SVM wikipedia article. I assume we have a file named "test.dat" which holds coordinates of test points and their class membership in the last column.
Example content of "test.dat" with 3D points:
-3,-3,-2,-1
-1,3,2,1
5,4,1,1
1,1,1,1
-2,5,4,1
6,0,1,1
-5,-5,-3,-1
0,-6,1,-1
-7,-2,-2,-1
Here is the code:
data = readtable("test.dat");
tableSize = size(data);
numOfPoints = tableSize(1);
dimension = tableSize(2) - 1;
PointsCoords = data(:, 1:dimension);
PointsSide = data.(dimension+1);
C = 0.5; %can be changed
n = dimension;
m = numOfPoints; %can be also interpretet as number of constraints
%z = [w, eps, b]; number of variables in 'z' is equal to n + m + 1
H = diag([ones(1, n), zeros(1, m + 1)]);
f = [zeros(1, n), C * ones(1, m), 0];
Aineq = [-diag(PointsSide)*table2array(PointsCoords), -eye(m), PointsSide];
bineq = -ones(m, 1);
lb = [-inf(1, n), zeros(1, m), -inf];
z = quadprog(H, f, Aineq, bineq, [], [], lb);
If let z = (w; w0; eps)T be a the long vector with n+1+m elements.(m the number of points)
Then,
H= diag([ones(1,n),zeros(1,m+1)]).
f = [zeros(1; n + 1); ones(1;m)]
The inequality constraints can be specified as :
A = -diag(y)[X; ones(m; 1); zeroes(m;m)] -[zeros(m,n+1),eye(m)],
where X is the n x m input matrix in the primal form.Out of the 2 parts for A, the first part is for w0 and the second part is for eps.
b = ones(m,1)
The equality constraints :
Aeq = zeros(1,n+1 +m)
beq = 0
Bounds:
lb = [-inf*ones(n+1,1); zeros(m,1)]
ub = [inf*ones(n+1+m,1)]
Now, z=quadprog(H,f,A,b,Aeq,beq,lb,ub)
Complete code. The idea is the same as above.
n = size(X,1);
m = size(X,2);
H = diag([ones(1, m), zeros(1, n + 1)]);
f = [zeros(1,m+1) c*ones(1,n)]';
p = diag(Y) * X;
A = -[p Y eye(n)];
B = -ones(n,1);
lb = [-inf * ones(m+1,1) ;zeros(n,1)];
z = quadprog(H,f,A,B,[],[],lb);
w = z(1:m,:);
b = z(m+1:m+1,:);
eps = z(m+2:m+n+1,:);
I am trying to generate a matrix in matlab which I will use to solve a polynomial regression formula.
Here is how I am trying to generate the matrix:
I have an input vector X containing N elements and an integer d. d is the integer to know how many times we will add a new column to the matrix we are trying to generate int he following way.
N = [X^d X^{d-1} ... X^2 X O]
O is a vector of same length as X with all 1's.
Everytime d > 2 it does not work.
Can you see any errors in my code (i am new to matlab):
function [ PR ] = PolyRegress( X, Y, d )
O = ones(length(X), 1)
N = [X O]
for j = 2:d
tmp = power(X, j)
N = [tmp N]
end
%TO DO: compute PR
end
It looks like the matlab function vander already does what you want to do.
The VANDER function will only generate powers of the vector upto d = length(X)-1. For a more general solution, you can use the BSXFUN function (works with any value of d):
N = bsxfun(#power, X(:), d:-1:0)
Example:
>> X = (1:.5:2);
>> d = 5;
>> N = bsxfun(#power, X(:), d:-1:0)
N =
1 1 1 1 1 1
7.5938 5.0625 3.375 2.25 1.5 1
32 16 8 4 2 1
I'm not sure if this is the order you want, but it can be easily reversed: use 0:d instead of d:-1:0...