about summary refs log tree commit diff
path: root/sourcecodes/parameter_learning/kfoldCrossValid.m
diff options
context:
space:
mode:
Diffstat (limited to 'sourcecodes/parameter_learning/kfoldCrossValid.m')
-rw-r--r--sourcecodes/parameter_learning/kfoldCrossValid.m322
1 files changed, 322 insertions, 0 deletions
diff --git a/sourcecodes/parameter_learning/kfoldCrossValid.m b/sourcecodes/parameter_learning/kfoldCrossValid.m
new file mode 100644
index 00000000..6306c511
--- /dev/null
+++ b/sourcecodes/parameter_learning/kfoldCrossValid.m
@@ -0,0 +1,322 @@
+function kfoldCrossValid(pre,predict_label,nfolds)
+% This function will peform k-fold cross-validation.
+% This requires the specification of the name of the variable
+%   that you want to predict and the number of folds that the
+%   data should be divided into.
+
+nfolds = uint8(str2num(nfolds));
+
+sfile=strcat(pre,'structure_input.txt');
+dfile=strcat(pre,'continuous_input.txt');
+nnodefile=strcat(pre,'nnode.txt');
+fnnode = fopen(nnodefile,'r');
+nnodes = fscanf(fnnode,'%d');
+
+Std_flag=true;
+[labels,cases,bnet]=readInput(dfile,sfile,nnodes,Std_flag);
+
+for i=1:nnodes
+    if strcmp(labels(i),predict_label)
+       predict_node = i;
+    end
+end
+
+predict_cases = bnet.node_sizes(predict_node);
+
+ncases = size(cases,2);
+
+kfold_index = kfold_bin(ncases,nfolds);
+
+if predict_cases == 1
+	kfoldCV_continuous(pre,predict_label,nnodes,labels,cases,bnet,predict_node,predict_cases,nfolds,kfold_index);
+else
+	kfoldCV_discrete(pre,predict_label,nnodes,labels,cases,bnet,predict_node,predict_cases,nfolds,kfold_index);
+endif
+
+
+end
+
+
+function kfoldCV_continuous(pre,predict_label,nnodes,labels,cases,bnet,predict_node,predict_cases,nfolds,kfold_index)
+
+ncases = size(cases,2);
+
+%%Read in original means and standard deviations to report output as
+%% untransformed values.
+means_orig=cell(1,nnodes);
+stdevs_orig=cell(1,nnodes);
+labels_orig=cell(1,nnodes);
+%Read in original means and standard deviations
+mapfile = strcat(pre,'map.txt');
+fmap = fopen(mapfile,'r');
+for i=1:nnodes
+    buffer = fgetl(mapfile);
+    temp = cell(1,3);
+    for j=1:3
+        [next,buffer] = strtok(buffer);
+	temp{j} = next;
+    end
+    labels_orig{i} = temp{1};
+    means_orig{i} = str2num(temp{3});
+    stdevs_orig{i} = str2num(temp{2});
+end
+fclose(fmap);
+%Need to map the means and stdevs to the correct labels
+means = cell(1,nnodes);
+stdevs = cell(1,nnodes);
+for i = 1:nnodes
+    for j = 1:nnodes
+       if strcmp(labels{i},labels_orig{j})
+          means{i} = means_orig{j};
+          stdevs{i} = stdevs_orig{j};
+          break
+       end
+    end
+end
+
+kfoldPredictions=zeros(size(cases,2),2);
+
+
+%t=cputime;
+%First get predictions
+for i =1:nfolds
+%  i
+  test_flag = false(ncases,1);
+  for j=1:ncases
+    if kfold_index(j) == i
+         test_flag(j) = true;
+    end
+  end
+ trainData = cases(:,~test_flag);
+ testData = cases(:,test_flag);
+ temp_index = zeros(size(testData,2),1);
+ temp = 1;
+ for j=1:ncases
+    if kfold_index(j) == i
+       temp_index(temp) = j;
+       temp = temp + 1;
+    end
+ end
+ [bnet] = parameterLearning(bnet,trainData);
+ for j=1:size(testData,2)
+  evidence = testData(:,j);
+  evidence{predict_node} = {};
+  engine = jtree_inf_engine(bnet);
+  [engine,loglik] = enter_evidence(engine,evidence);
+  predict = marginal_nodes(engine,predict_node);
+  adj_mu = predict.mu*stdevs{predict_node}+means{predict_node};
+  adj_sigma = stdevs{predict_node}*predict.Sigma;
+  kfoldPredictions(temp_index(j),1) = adj_mu;
+  kfoldPredictions(temp_index(j),2) = adj_sigma;
+ end
+end
+%e=cputime-t;
+
+
+%Open output file.
+filename = strcat(pre,'kfoldCV.txt');
+fileID = fopen(filename,'w');
+
+fprintf(fileID,'Variable that was predicted: %s\n\n',predict_label);
+
+%Calculate RMSEP (root mean square error of prediction) and q^2
+%First, calculate TSS (total sum of squares) and
+%  PRESS (sum of squares of prediction errors)
+average = mean(cell2mat(cases'))(predict_node);
+%undo standardization
+average = average*stdevs{predict_node}+means{predict_node};
+tss = 0;
+press = 0;
+case_adj=zeros(size(cases,2),1);
+for i =1:ncases
+	case_adj(i) = cases{predict_node,i}*stdevs{predict_node}+means{predict_node};
+	tss = (case_adj(i)-average)^2 + tss;
+	press = (kfoldPredictions(i,1)-case_adj(i))^2 + press;
+end
+rmsep = sqrt(press/ncases);
+q_squared = 1 - press/tss;
+
+%% Print rmseq and q^2
+fprintf(fileID,'RMS error of predictions: %6.4f\n',rmsep);
+fprintf(fileID,'Q^2 of predictions: %6.4f\n\n',q_squared);
+
+
+%%Print the predictions
+fprintf(fileID,'Predicted mean and standard deviation for each case:\n');
+fprintf(fileID,'CaseRow\tFoldNumber\tActualValue\tPredictionMean\tPredictionStDev\n');
+for i = 1:ncases
+     fprintf(fileID,'%i\t%i\t%6.4f\t',i,kfold_index(i),case_adj(i));
+     fprintf(fileID,'%6.4f\t%6.4f\n',kfoldPredictions(i,:));
+end
+
+end
+
+
+function kfoldCV_discrete(pre,predict_label,nnodes,labels,cases,bnet,predict_node,predict_cases,nfolds,kfold_index)
+
+ncases = size(cases,2);
+
+%This next section just gets the original names of the levels.
+% so they can be written to the output file.
+%%Get the maximum_number of states so array will be big enough
+%%Add 1 because the input includes the node name
+max_states = max(bnet.node_sizes) + 1;
+disc_nodes = size(bnet.dnodes,2);
+
+%%Get mapping of discrete levels.
+levelfile = strcat(pre,'nlevels.txt');
+flevels = fopen(levelfile,'r');
+levels = cell(disc_nodes,max_states);
+ndisc_nodes = 0;
+for i=1:disc_nodes
+    ndisc_nodes = ndisc_nodes + 1;
+    buffer = fgetl(flevels);
+     for j = 1:max_states
+       [next,buffer] = strtok(buffer);
+       if j == 1
+          levels{i,j} = next;
+       else
+          levels{i,j} = next;
+       end
+       if length(buffer) < 1
+        break
+       end
+     end
+end
+
+pred_levels = cell(1,predict_cases);
+for i = 1:disc_nodes
+   if strcmp(levels{i,1},predict_label);
+	for j = 1:predict_cases
+	    pred_levels{j} = levels{i,j+1};
+	end
+        break
+   end
+end
+
+kfoldPredictions=zeros(size(cases,2),predict_cases);
+
+%t=cputime;
+%First get kfold CV predictions
+for i =1:nfolds
+  test_flag = false(ncases,1);
+  for j=1:ncases
+     if kfold_index(j) == i
+         test_flag(j) = true;
+     end
+  end
+  trainData = cases(:,~test_flag);
+  testData = cases(:,test_flag);
+  temp_index = zeros(size(testData,2),1);
+  temp = 1;
+  for j =1:ncases
+      if kfold_index(j) == i
+         temp_index(temp) = j;
+         temp = temp + 1;
+      end
+  end
+  [bnet] = parameterLearning(bnet,trainData);
+  for j = 1:size(testData,2)
+    evidence = testData(:,j);
+    evidence{predict_node} = {};
+    engine = jtree_inf_engine(bnet);
+    [engine,loglik] = enter_evidence(engine,evidence);
+    predict = marginal_nodes(engine,predict_node);
+    for k = 1:predict_cases
+	kfoldPredictions(temp_index(j),k) = predict.T(k);
+    end
+  end
+end
+%e=cputime-t;
+
+%Now compare with actual outcomes
+%actual_states = zeros(1,predict_cases);
+%for i=1:ncases
+%    for j = 1:predict_cases
+%	if cell2mat(cases(predict_node,i)) == j
+%           actual_states(j) = actual_states(j) + 1;
+%	end
+%    end
+%end
+
+pred_states = zeros(1,ncases);
+
+for i=1:ncases
+    max_state = 1;
+    for j = 2:predict_cases
+       if kfoldPredictions(i,j) > kfoldPredictions(i,max_state)
+           max_state = j;
+	end
+    end
+    pred_states(i) = max_state;
+end
+
+correct = 0;
+for i=1:ncases
+    if pred_states(i) == cell2mat(cases(predict_node,i))
+	correct = correct + 1;
+    end
+end
+
+accuracy = correct/ncases;
+
+%Open output file.
+filename = strcat(pre,'kfoldCV.txt');
+fileID = fopen(filename,'w');
+
+fprintf(fileID,'Variable that was predicted: %s\n\n',predict_label);
+
+
+%%Print the accuracy
+fprintf(fileID,'Fraction of accurate predictions: %6.4f\n\n',accuracy);
+
+%%Print the predictions
+fprintf(fileID,'Predicted likelihood of each state for each case:\n');
+fprintf(fileID,'%s\t%s\t%s\t','CaseRow','FoldNumber','ActualState');
+fprintf(fileID,'%s\t',pred_levels{1:end-1});
+fprintf(fileID,'%s\n',pred_levels{end});
+for i = 1:ncases
+     fprintf(fileID,'%i\t%i\t',i,kfold_index(i));
+     case_level = pred_levels{cases{predict_node,i}};
+     fprintf(fileID,'%s\t',case_level);
+     fprintf(fileID,'%6.4f\t',kfoldPredictions(i,1:end-1));
+     fprintf(fileID,'%6.4f\n',kfoldPredictions(i,end));
+end
+
+end
+
+
+function [kfold_index] = kfold_bin(ncases,nfolds);
+%This returns indexes for the different cases to separate data into folds.
+
+%Get array with random permutation of the number of cases
+p = randperm(ncases);
+
+base_size = idivide(ncases,nfolds);
+remainder = rem(ncases,nfolds);
+
+kfold_index = zeros(ncases,1);
+group = 1;
+count = 0;
+for i=1:ncases
+    count = count + 1;
+    kfold_index(p(i)) = group;
+%Need to do some checks if groups cannot be exactly equally sized
+%If you have already added an extra member to the group, go to next group
+    if count > base_size
+       count = 0;
+       group = group + 1;
+%If you have filled the group, check if an extra is needed
+     elseif count == base_size
+       if remainder > 0
+         remainder = remainder - 1;
+       else
+         count = 0;
+         group = group + 1;
+       end
+     end
+end
+
+
+end
+