How to solve logistic regression using gradient Descent? - artificial-intelligence

I was solving a exercise of a online course form coursera on machine learning. The problem statement is :
Suppose that a high school has a dataset representing 40 students who were admitted to college and 40 students who were not admitted. Each ( x(i), y(i) ) training example contains a student's score on two standardized exams and a label of whether the student was admitted.
Our task is to build a binary classification model that estimates college admission chances based on a student's scores on two exams. In the training data,
a. The first column of your x array represents all Test 1 scores, and the second column represents all Test 2 scores.
b. The y vector uses '1' to label a student who was admitted and '0' to label a student who was not admitted.
I have solved it by using predefined function named fminunc. Now , i am solving it by using gradient descent but my graph of cost vs number of iteration is not conversing i.e cost function value is not decreasing with number of iteration . My theta value is also not matching with the answer that should i get.
theta value that i got :
[-0.085260 0.047703 -0.022851]
theta value that i should get (answer) :
[-16.38 0.1483 0.1589]
My source code :
clear ; close all; clc
x = load('/home/utlesh/Downloads/ex4x.txt');
y = load('/home/utlesh/Downloads/ex4y.txt');
theta = [0,0,0];
alpha = 0.00002;
a = [0,0,0];
m = size(x,1);
x = [ones(m,1) x];
n = size(x,2);
y_hyp = y*ones(1,n);
for kk = 1:100000
hyposis = 1./(1 + exp(-(x*theta')));
x_hyp = hyposis*ones(1,n);
theta = theta - alpha*1/m*sum((x_hyp - y_hyp).*x);
a(kk,:) = theta ;
end
cost = [0];
for kk = 1:100000
h = 1./(1 + exp(-(x*a(kk,:)')));
cost(kk,:) = sum(-y .* log(h) - (1 - y) .* log(1 - h));
end
x_axis = [0];
for kk = 1:100000
x_axis(kk,:) = kk;
end
plot(x_axis,cost);
The graph that i got looks like that of 1/x;
Please tell me where i am doing mistake . If there is anything that i misunderstood please let me know .

What I can see missing is the usage of learning rate and weights. The weights can be adjusted in two modes online and batch.
The weights should be randomly assigned values between [-0.01,0.01]. I did an exercise as a part of my HW during my Master's. Below is the snippet:
assign values to weights between [-0.01,0.01] i.e. no. of weight values will be, no. of features + 1:
weights = -.01 + 0.02 * rand(3,1);
learnRate = 0.001;
Here running the code for set number of iterations: (It converged in 100 iterations also).
while iter < 100
old_output = new_output;
delta = zeros(cols-1,1);
for t = 1:rows
input = 0;
for j = 1:cols-1
input = input + weights(j) * numericdata(t,j);
end
new_output(t) = (1 ./ (1 + exp(-input)));
for j = 1:cols-1
delta(j) = delta(j) + (numericdata(t,4)-new_output(t)) * numericdata(t,j);
end
end
#Adjusting weights (Batch Mode):
for j=1:cols-1
weights(j) = weights(j) + learnRate * (delta(j));
end
error = abs(numericdata(:,4) - new_output);
errorStr(i) = (error(:));
error = 0;
iter = iter + 1;
i = i + 1;
end
Also, I had a talk with my professor, while studying it. He said, if the dataset given has the property to converge then you will see that when you randomly run it for different number of iterations.

Related

I am having trouble getting my function to provide its output in a matrix

I want to plot the log of a variable Dl which depends on a variable z with respect to log(z). I'm trying to do this for z = 1:100 but it returns only 1 number for Dl.
% Log(Dl) versus Log(Redshift)
m = 1;
d = 0;
z = linspace(1,100,1);
Dl = zeros(1,100);
for z = 1:100
[Dl,Da] = Cosmological(m,d,z);
end
y = log(Dl);
x = log(1:100);
plot(x,y)
apologies for any silly or useless lines of code I'm very new to programming. The function cosmological that I called for is written as follows (but there are no errors so may not be necessary, I'm posting just in case):
function [Dl,Da] = Cosmological(m,d,z)
f = #(x)1./((1+x).*((m.*(1+z)-m+d.*((1+x).^(-2))-d+1).^(.5)));
q = integral(f,0,z); % Integral part equations for Dl
if m+d==1 % flat universe condition
Dl=c/H0.*(1+z)*q;
elseif m+d<1 %positive spatial curvature universe condition
Dl=c/H0*(1-m-d)^(-1/2)*(1+z)*sinh((1-m-d)^.5).*q;
else % negative spatial curvature universe condition
Dl=c/H0*(1-m-d)^(-1/2)*(1+z)*sin((1-m-d)^.5).*q;
end
Da = Dl/(1+z)^2; %Angular diameter distance function
end
First, these line is not needed, you assign z with 1:100 in the loop:
z = linspace(1,100,1);
You get only one value because your loop saves only the last value. You should index Dl with z like this (and probably also Da):
for z = 1:100
[Dl(z),Da] = Cosmological(m,d,z);
end

Connecting random points in MATLAB without intersecting lines

I need help with solving this problem. I have randomly generated points (example on Picture #1) and I want to connect them with lines (example on Picture #2). Lines can't be intersected and after connection, the connected points should look like an irregular area.
%Generating random points
xn = randi([3 7],1,10);
yn = randi([3 6],1,10);
%Generated points
xn = [6,3,7,7,6,6,6,4,6,3];
yn = [5,3,4,3,3,6,5,4,6,3];
Picture #1:
Result should be like this:
Picture #2:
Any idea how to solve this?
I suppose for the general case it can be very difficult to come up with a solution. But, assuming your points are scattered "nicely" there is quite a simple solution.
If you sort your points according to the angle above the x axis of the vector connecting the point and the center of the point cloud then:
P = [xn;yn]; %// group the points as columns in a matrix
c = mean(P,2); %// center point relative to which you compute the angles
d = bsxfun(#minus, P, c ); %// vectors connecting the central point and the dots
th = atan2(d(2,:),d(1,:)); %// angle above x axis
[st si] = sort(th);
sP = P(:,si); %// sorting the points
And that's about it. To plot the result:
sP = [sP sP(:,1)]; %// add the first point again to close the polygon
figure;plot( sP(1,:), sP(2,:), 'x-');axis([0 10 0 10]);
This algorithm will fail if several points has the same angle w.r.t the center of the point cloud.
An example with 20 random points:
P = rand(2,50);
You could adapt the code from another answer I gave for generating random simple polygons of an arbitrary number of sides. The difference here is you already have your set of points chosen and thus implicitly the number of sides you want (i.e. the same as the number of unique points). Here's what the code would look like:
xn = [6,3,7,7,6,6,6,4,6,3]; % Sample x points
yn = [5,3,4,3,3,6,5,4,6,3]; % Sample y points
[~, index] = unique([xn.' yn.'], 'rows', 'stable'); % Get the unique pairs of points
x = xn(index).';
y = yn(index).';
numSides = numel(index);
dt = DelaunayTri(x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
while numEdges ~= numSides
if numEdges > numSides
triIndex = vertexAttachments(dt, boundaryEdges(:,1));
triIndex = triIndex(randperm(numel(triIndex)));
keep = (cellfun('size', triIndex, 2) ~= 1);
end
if (numEdges < numSides) || all(keep)
triIndex = edgeAttachments(dt, boundaryEdges);
triIndex = triIndex(randperm(numel(triIndex)));
triPoints = dt([triIndex{:}], :);
keep = all(ismember(triPoints, boundaryEdges(:,1)), 2);
end
if all(keep)
warning('Couldn''t achieve desired number of sides!');
break
end
triPoints = dt.Triangulation;
triPoints(triIndex{find(~keep, 1)}, :) = [];
dt = TriRep(triPoints, x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
end
boundaryEdges = [boundaryEdges(:,1); boundaryEdges(1,1)];
x = dt.X(boundaryEdges, 1);
y = dt.X(boundaryEdges, 2);
And here's the resulting polygon:
patch(x,y,'w');
hold on;
plot(x,y,'r*');
axis([0 10 0 10]);
Two things to note:
Some sets of points (like the ones you chose here) will not have a unique solution. Notice how my code connected the top 4 points in a slightly different way than you did.
I made use of the TriRep and DelaunayTri classes, both of which may be removed in future MATLAB releases in favor of the delaunayTriangulation class.

Store values from a time series function in an array using a for loop in R

I am working with Bank of America time series data for stock prices. I am trying to store the forecasted value for a specific step ahead (in this case 1:20 steps) in an array. I then need to subtract each value of the array from each value of the test array. Then I have to square each value of the array, sum all the squared values of the array, then divide by N (N = number of steps forecasted ahead).
I have the following so far. Also, the quantmod and fpp libraries are needed for this.
---------Bank of America----------
library(quantmod)
library(fpp)
BAC = getSymbols('BAC',from='2009-01-02',to='2014-10-15',auto.assign=FALSE)
BAC.adj = BAC$BAC.Adjusted
BAC.daily=dailyReturn(BAC.adj,type='log')
test = tail(BAC.daily, n = 20)
train = head(BAC.daily, n = 1437)
Trying to write a function to forecast, extract requisite value (point forecast for time i), then store it in an array where I can perform operations on that array (i.e. - add, multiply, exponentiate, sum the values of the array)
MSE = function(N){
for(i in 1:(N)){
x = forecast(model1, h = i)
y = x$mean
w = as.matrix(as.double(as.matrix(unclass(y))))
p = array(test[i,]-w[i,])
}
}
and we also have:
model1 = Arima(train, order = c(0,2,0))
MSE = function(N){
result = vector("list", length = (N))
for(i in 1:(N)){
x = forecast(model1, h = i)
point_forecast = as.double(as.matrix(unclass(x$mean)))
result[i] = point_forecast
}
result = as.matrix(do.call(cbind, result))
}
Neither of these functions have worked so far. When I run the MSE function, I get the following errors:
> MSE(20)
There were 19 warnings (use warnings() to see them)
> warnings()
Warning messages:
1: In result[i] = point_forecast :
number of items to replace is not a multiple of replacement length
2: In result[i] = point_forecast :
number of items to replace is not a multiple of replacement length
3: In result[i] = point_forecast :
number of items to replace is not a multiple of replacement length
4: In result[i] = point_forecast :
When I run MSE2 function, I get the following ouput:
MSE2(20)
[1] -0.15824
When putting a print statement inside, it printed out 'p' as a singular number, just like above (even though that had been run for i = 20). The x,y, and w variable in the MSE2 function act as vectors as far as storing the output, so I do not understand why p does not as well.
I appreciate any help in this matter, thank you.
Sincerely,
Mitchell Healy
Your question has two MSE functions: one in the first code block and one in the second code block.
Also, library(forecast) is needed to run Arima and forecast.
My understanding of what you are trying to do in the first paragraph is to compute the 20-step ahead forecast error. That is, what is the error in forecasts from model1 20 days ahead, based on your test data. This can be done in the code below:
model1 <- Arima(train, order = c(0,2,0))
y_fcst<-forecast(model1,h=20)$mean
errors<-as.vector(y_fcst)-as.vector(test)
MSE.fcst<-mean(errors^2)
However, I'm not sure what you're trying to do here: an ARIMA(0,2,0) model is simply modelling the differences in returns as a random walk. That is, this model just differences the returns twice and assumes this twice-differenced data is white noise. There's no parameters other than $\sigma^2$ being estimated.
Rob Hyndman has a blog post covering computing errors from rolling forecasts.
My solution to finding the MSE is below. I used log adjusted daily return data from Bank of America gathered through quantmod. Then I subsetted the data (which had length 1457) into training[1:1437] and testing[1438:1457].
The solution is:
forc = function(N){
forecast = matrix(data = NA, nrow = (N) )
for(i in 1:N){
fit = Arima(BAC.adj[(1+(i-1)):(1437+(i-1))], order = c(0,0,4))
x = forecast(fit, h = 1)
forecast[i,] = as.numeric(x$mean)
}
error = test - forecast
error_squared = error^2
sum_error_squared = sum(error_squared)
MSE = sum_error_squared/N
MSE
}

Matlab Error A(I) = B

I am currently looking at Binomial Option Pricing. I have written the code below, which works fine, when you enter the variables in one at a time. However, entering each set of values is very tedious, and I need to be able to analyse a large set of data. I have created arrays for each of the variables. But, I keep getting the error; A(I) = B, the number of elements in B must equal I. The function is shown below.
function C = BinC(S0,K,r,sig,T,N);
% PURPOSE:
% To return the value of a European call option using the Binomial method
%-------------------------------------------------------------------------
% INPUTS:
% S0 - The initial price of the underlying asset
% K - The strike price
% r - The risk free rate of return, expressed as a decimal
% sig - The volatility of the underlying asset, expressed as a decimal
% T - The time to maturity, expressed as a decimal
% N - The number of steps
%-------------------------------------------------------------------------
dt = T/N;
u = exp(sig*sqrt(dt));
d = 1/u;
p = (exp(r*dt) - d)/(u - d);
S = zeros(N+1,1);
% Price of underlying asset at time T
for n = 1:N+1
S(n) = S0*(d^(N+1-n))*(u^(n-1));
end
% Price of Option at time T
for n = 1:N+1
C(n) = max(S(n)- K, 0);
end
% Backtrack to get option price at time 0
for i = N:-1:1
for n = 1:i
C(n) = exp(-r*dt)*(p*C(n+1) + (1-p)*C(n));
end
end
disp(C(1))
After importing my data, I entered this in to the command window.
for i=1:20
w(i)= BinC(S0(i),K(i),r(i),sig(i),T(i),N(i));
end
When I enter w, all I get back is w = []. I have no idea how I can make A(I) = B. I apologise, if this is a very silly question, but I am new to Matlab and in need of help. Thanks
Your function computes an entire vector C, but displays only C(1). This display is deceptive: it makes you think the function is returning a scalar, but it's not: it's returning the entire vector C, which you try to store into a scalar location.
The solution is simple: Change your function definition to this (rename the output variable):
function out = BinC(S0,K,r,sig,T,N);
Then at the last line of the function, remove the disp, and replace it with
out = C(1);
To verify all of this (compare with your non-working example), try calling it by itself at the command line, and examine the output.

Random Number generation with probability in matlab [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to simulate an information source with alphabet "a,b,c,d" with the respective probabilities of 0.1, 0.5, 0.2, 0.2. I do not know how to do it using MATLAB. Help is most appreciated.
You could first create an array containing the relative numbers of each character defined by their relative probabilities.
First set the max # of samples for any letter; doesn't have to be the same as the # of rand samples (later below):
maxSamplesEach = 100;
Define the data for the problem:
strings = ['a' 'b' 'c' 'd'];
probabilty = [0.1 0.5 0.2 0.2];
Construct a sample space weighted by relative probabilities:
count = 0;
for k = 1:size(strings,2)
for i = 1:probabilty(k)*maxSamplesEach
count = count+1;
totalSampleSpace(count) = strings(k);
end
end
Now define a range for the random numbers:
min = 1;
max = count;
Now generate a 100 random numbers from a uniform distribution from the range defined above:
N = 100;
randomSelections = round(min + (max-min).*rand(1,N));
Now here are your random samples taken from the distribution:
randomSamples = totalSampleSpace(randomSelections);
Next just count them up:
for k = 1:size(strings,2)
indices = [];
indices = find(randomSamples == strings(k));
disp(['Count samples for ', strings(k),' = ', num2str(size(indices,2))]);
end
Keep in mind that these results are statistical in nature so its highly unlikely that you will get the same relative contributions each time.
Example output:
Count samples for a = 11
Count samples for b = 49
Count samples for c = 19
Count samples for d = 21
you could do something as simple as follows. Simply create a large random vector using rand, this will create values between 0 and 1 with a uniform probability. So if you want a number to have a 10 percent chance of occurring you give it a range of 0.1, typically 0 to 0.1. You can then add more ranges to these same numbers to get what you want.
vals =rand(1,10000);
letters = cell(size(vals));
[letters{vals<0.1}] = deal ('a');
[letters{vals > 0.1 & vals <= 0.6}] = deal ('b');
[letters{vals > 0.6 & vals <= 0.8}] = deal ('c');
[letters{vals > 0.8 & vals <= 1}] = deal ('d');
The above code will return a 10000 character letter array with the described percentages.
Or you can do this dynamically as follows:
vals =rand(1,10000);
output= cell(size(vals));
letters2use = {'a','b','c','d'};
percentages = [0.1,0.5,0.2,0.2];
lowerBounds = [0,cumsum(percentages(1:end-1))];
upperBounds = cumsum(percentages);
for i = 1:numel(percentages)
[output{vals > lowerBounds(i) & vals <= upperBounds(i)}] = deal(letters2use{i}) ;
end
UPDATE
The above code has no guarantee of a certain number of occurrences of each letter, however the following does. Since from your comment it seems you need exactly a certain number of each the following code should do that by randomly assigning letters around
numElements = 10000;
letters2use = {'a','b','c','d'};
percentages = [0.1,0.5,0.2,0.2];
numEach = round(percentages*numElements);
while sum(numEach) < numElements
[~,idx] = max(mod(percentages*numElements,1));
numEach(idx) = numEach(idx) + 1;
end
while sum(numEach) > numElements
[~,idx] = min(mod(percentages*numElements,1));
numEach(idx) = numEach(idx) - 1;
end
indices = randperm(numElements);
output = cell(size(indices));
lower = [0,cumsum(numEach(1:end-1))]+1;
upper = cumsum(numEach);
for i = 1:numel(lower)
[output{indices(lower(i):upper(i))}] = deal(letters2use{i});
end
output

Resources