about summary refs log tree commit diff
path: root/sourcecodes/parameter_learning/kfoldCrossValid.m
diff options
context:
space:
mode:
authorziejd22018-09-13 23:59:20 -0500
committerziejd22018-09-13 23:59:20 -0500
commite3f7237ffcb19f19db3b68777b5a94b89e07f66a (patch)
tree554a8013776ebeae3e2976074020c09c2d1af8b0 /sourcecodes/parameter_learning/kfoldCrossValid.m
parenta7eb61ff7a09f39bee67014bf24b8919eaccfc19 (diff)
downloadBNW-e3f7237ffcb19f19db3b68777b5a94b89e07f66a.tar.gz
New parameter learning options
The main change here is in the parameter learning methods.  The parameters that are learned at first (i.e., if there is no evidence) are the distributions that are found directly in the data. I had to create or significantly modify several BNT files for this.

If there is evidence, the parameters are learned using a Dirichlet prior. This only required a couple of small changes to the BNW parameter learning files.
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
+