From 75329a2e9b745997f164988e6e77ef9674327aff Mon Sep 17 00:00:00 2001 From: Jose Pablo Alberto Andreotti Date: Thu, 21 Nov 2013 15:57:32 -0300 Subject: [PATCH 1/6] Rebase. --- .travis.yml | 8 + CAE/caeexamples.m | 4 +- CNN/cnnsetup.m | 1 + CONTRIBUTING.md | 20 + DBN/rbmtrain.m | 3 +- NN/nnapplygrads.m | 2 +- NN/nnchecknumgrad.m | 4 +- NN/nntrain.m | 16 +- NN/nnupdatefigures.m | 23 +- README.md | 68 +--- README_header.md | 5 +- tests/runalltests.m | 8 +- tests/test_example_CNN.m | 4 + tests/test_example_DBN.m | 4 +- tests/test_example_NN.m | 22 +- tests/test_example_SAE.m | 35 +- ...est_nn_gradients_are_numerically_correct.m | 4 +- util/visualize.m | 6 +- util/xunit/+xunit/+utils/Contents.m | 24 -- util/xunit/+xunit/+utils/arrayToString.m | 96 ----- util/xunit/+xunit/+utils/compareFloats.m | 128 ------- util/xunit/+xunit/+utils/comparisonMessage.m | 33 -- util/xunit/+xunit/+utils/containsRegexp.m | 17 - util/xunit/+xunit/+utils/generateDoc.m | 14 - util/xunit/+xunit/+utils/isAlmostEqual.m | 46 --- util/xunit/+xunit/+utils/isSetUpString.m | 12 - util/xunit/+xunit/+utils/isTearDownString.m | 12 - util/xunit/+xunit/+utils/isTestCaseSubclass.m | 39 -- util/xunit/+xunit/+utils/isTestString.m | 15 - .../+xunit/+utils/parseFloatAssertInputs.m | 56 --- util/xunit/+xunit/+utils/stringToCellArray.m | 14 - util/xunit/CommandWindowTestRunDisplay.m | 30 -- util/xunit/Contents.m | 33 -- util/xunit/FunctionHandleTestCase.m | 154 -------- util/xunit/TestCase.m | 103 ------ util/xunit/TestCaseInDir.m | 30 -- util/xunit/TestCaseWithAddPath.m | 53 --- util/xunit/TestComponent.m | 59 --- util/xunit/TestComponentInDir.m | 58 --- util/xunit/TestRunDisplay.m | 258 ------------- util/xunit/TestRunLogger.m | 104 ------ util/xunit/TestRunMonitor.m | 35 -- util/xunit/TestSuite.m | 342 ------------------ util/xunit/TestSuiteInDir.m | 50 --- util/xunit/VerboseTestRunDisplay.m | 112 ------ util/xunit/assertElementsAlmostEqual.m | 61 ---- util/xunit/assertEqual.m | 43 --- util/xunit/assertExceptionThrown.m | 53 --- util/xunit/assertFalse.m | 31 -- util/xunit/assertFilesEqual.m | 68 ---- util/xunit/assertTrue.m | 33 -- util/xunit/assertVectorsAlmostEqual.m | 59 --- util/xunit/info.xml | 28 -- util/xunit/initTestSuite.m | 58 --- util/xunit/runtests.m | 160 -------- 55 files changed, 95 insertions(+), 2663 deletions(-) create mode 100644 .travis.yml create mode 100644 CONTRIBUTING.md delete mode 100644 util/xunit/+xunit/+utils/Contents.m delete mode 100644 util/xunit/+xunit/+utils/arrayToString.m delete mode 100644 util/xunit/+xunit/+utils/compareFloats.m delete mode 100644 util/xunit/+xunit/+utils/comparisonMessage.m delete mode 100644 util/xunit/+xunit/+utils/containsRegexp.m delete mode 100644 util/xunit/+xunit/+utils/generateDoc.m delete mode 100644 util/xunit/+xunit/+utils/isAlmostEqual.m delete mode 100644 util/xunit/+xunit/+utils/isSetUpString.m delete mode 100644 util/xunit/+xunit/+utils/isTearDownString.m delete mode 100644 util/xunit/+xunit/+utils/isTestCaseSubclass.m delete mode 100644 util/xunit/+xunit/+utils/isTestString.m delete mode 100644 util/xunit/+xunit/+utils/parseFloatAssertInputs.m delete mode 100644 util/xunit/+xunit/+utils/stringToCellArray.m delete mode 100644 util/xunit/CommandWindowTestRunDisplay.m delete mode 100644 util/xunit/Contents.m delete mode 100644 util/xunit/FunctionHandleTestCase.m delete mode 100644 util/xunit/TestCase.m delete mode 100644 util/xunit/TestCaseInDir.m delete mode 100644 util/xunit/TestCaseWithAddPath.m delete mode 100644 util/xunit/TestComponent.m delete mode 100644 util/xunit/TestComponentInDir.m delete mode 100644 util/xunit/TestRunDisplay.m delete mode 100644 util/xunit/TestRunLogger.m delete mode 100644 util/xunit/TestRunMonitor.m delete mode 100644 util/xunit/TestSuite.m delete mode 100644 util/xunit/TestSuiteInDir.m delete mode 100644 util/xunit/VerboseTestRunDisplay.m delete mode 100644 util/xunit/assertElementsAlmostEqual.m delete mode 100644 util/xunit/assertEqual.m delete mode 100644 util/xunit/assertExceptionThrown.m delete mode 100644 util/xunit/assertFalse.m delete mode 100644 util/xunit/assertFilesEqual.m delete mode 100644 util/xunit/assertTrue.m delete mode 100644 util/xunit/assertVectorsAlmostEqual.m delete mode 100644 util/xunit/info.xml delete mode 100644 util/xunit/initTestSuite.m delete mode 100644 util/xunit/runtests.m diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c88ffd8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +before_script: + - sudo apt-get install octave + +script: + - sh -c "octave tests/runalltests.m" + +notifications: + email: false diff --git a/CAE/caeexamples.m b/CAE/caeexamples.m index 65a188f..5be328e 100644 --- a/CAE/caeexamples.m +++ b/CAE/caeexamples.m @@ -1,6 +1,6 @@ %% mnist data clear all; close all; clc; -load ../data/mnist_uint8; +load mnist_uint8; x = cell(100, 1); N = 600; for i = 1 : 100 @@ -29,4 +29,4 @@ mm = cae.ok{1}{i}(1,:,:); ff(i,:) = mm(:); end; -figure;visualize(ff',1) +figure;visualize(ff') diff --git a/CNN/cnnsetup.m b/CNN/cnnsetup.m index 6d6b002..b1f6079 100644 --- a/CNN/cnnsetup.m +++ b/CNN/cnnsetup.m @@ -1,4 +1,5 @@ function net = cnnsetup(net, x, y) + assert(exist('OCTAVE_VERSION')==0, 'CNNs does not work with Octave as there is a bug in the implementation of convolution in octave. See: http://savannah.gnu.org/bugs/?39314'); inputmaps = 1; mapsize = size(squeeze(x(:, :, 1))); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5d92ac3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,20 @@ +Thank you so much for wanting to give back to the toolbox. Here's some info on how to contribute: + +#General: + +Don't bunch up changes, e.g. if you have bug-fixes, new features and style changes, rather make 3 seperate pull requests. + +Ensure that you introduce tests/examples for any new functionality + +# Guide +1. Fork repository +2. Create a new branch, e.g. `checkout -b my-stuff` +3. Commit and push your changes to that branch +4. Make sure that the test works (!) (see known errors) +5. Create a pull request +6. I accept your pull request + + + + + diff --git a/DBN/rbmtrain.m b/DBN/rbmtrain.m index 6787ffb..77e6ad3 100644 --- a/DBN/rbmtrain.m +++ b/DBN/rbmtrain.m @@ -1,5 +1,6 @@ function rbm = rbmtrain(rbm, x, opts) assert(isfloat(x), 'x must be a float'); + assert(all(x>=0) && all(x<=1), "all data in x must be in [0:1]"); m = size(x, 1); numbatches = m / opts.batchsize; @@ -14,7 +15,7 @@ v1 = batch; h1 = sigmrnd(repmat(rbm.c', opts.batchsize, 1) + v1 * rbm.W'); v2 = sigmrnd(repmat(rbm.b', opts.batchsize, 1) + h1 * rbm.W); - h2 = sigmrnd(repmat(rbm.c', opts.batchsize, 1) + v2 * rbm.W'); + h2 = sigm(repmat(rbm.c', opts.batchsize, 1) + v2 * rbm.W'); c1 = h1' * v1; c2 = h2' * v2; diff --git a/NN/nnapplygrads.m b/NN/nnapplygrads.m index 1584e85..781163b 100644 --- a/NN/nnapplygrads.m +++ b/NN/nnapplygrads.m @@ -5,7 +5,7 @@ for i = 1 : (nn.n - 1) if(nn.weightPenaltyL2>0) - dW = nn.dW{i} + nn.weightPenaltyL2 * nn.W{i}; + dW = nn.dW{i} + nn.weightPenaltyL2 * [zeros(size(nn.W{i},1),1) nn.W{i}(:,2:end)]; else dW = nn.dW{i}; end diff --git a/NN/nnchecknumgrad.m b/NN/nnchecknumgrad.m index a9ada01..f6f983f 100644 --- a/NN/nnchecknumgrad.m +++ b/NN/nnchecknumgrad.m @@ -8,9 +8,9 @@ function nnchecknumgrad(nn, x, y) nn_m = nn; nn_p = nn; nn_m.W{l}(i, j) = nn.W{l}(i, j) - epsilon; nn_p.W{l}(i, j) = nn.W{l}(i, j) + epsilon; - rng(0); + rand('state',0) nn_m = nnff(nn_m, x, y); - rng(0); + rand('state',0) nn_p = nnff(nn_p, x, y); dW = (nn_p.L - nn_m.L) / (2 * epsilon); e = abs(dW - nn.dW{l}(i, j)); diff --git a/NN/nntrain.m b/NN/nntrain.m index a0d31dd..af844a6 100644 --- a/NN/nntrain.m +++ b/NN/nntrain.m @@ -58,17 +58,19 @@ end t = toc; - + + if opts.validation == 1 + loss = nneval(nn, loss, train_x, train_y, val_x, val_y); + str_perf = sprintf('; Full-batch train mse = %f, val mse = %f', loss.train.e(end), loss.val.e(end)); + else + loss = nneval(nn, loss, train_x, train_y); + str_perf = sprintf('; Full-batch train err = %f', loss.train.e(end)); + end if ishandle(fhandle) - if opts.validation == 1 - loss = nneval(nn, loss, train_x, train_y, val_x, val_y); - else - loss = nneval(nn, loss, train_x, train_y); - end nnupdatefigures(nn, fhandle, loss, opts, i); end - disp(['epoch ' num2str(i) '/' num2str(opts.numepochs) '. Took ' num2str(t) ' seconds' '. Mean squared error on training set is ' num2str(mean(L((n-numbatches):(n-1))))]); + disp(['epoch ' num2str(i) '/' num2str(opts.numepochs) '. Took ' num2str(t) ' seconds' '. Mini-batch mean squared error on training set is ' num2str(mean(L((n-numbatches):(n-1)))) str_perf]); nn.learningRate = nn.learningRate * nn.scaling_learningRate; end end diff --git a/NN/nnupdatefigures.m b/NN/nnupdatefigures.m index c4b9509..fdcc775 100644 --- a/NN/nnupdatefigures.m +++ b/NN/nnupdatefigures.m @@ -43,12 +43,6 @@ function nnupdatefigures(nn,fhandle,L,opts,i) legend(p1, M,'Location','NorthEast'); set(p1, 'Xlim',[0,opts.numepochs + 1]) - if i ==2 % speeds up plotting by factor of ~2 - set(gca,'LegendColorbarListeners',[]); - setappdata(gca,'LegendColorbarManualSpace',1); - setappdata(gca,'LegendColorbarReclaimSpace',1); - end - p2 = subplot(1,2,2); plot(plot_x,plot_yfrac); xlabel('Number of epochs'); ylabel('Misclassification rate'); @@ -56,27 +50,14 @@ function nnupdatefigures(nn,fhandle,L,opts,i) legend(p2, M,'Location','NorthEast'); set(p2, 'Xlim',[0,opts.numepochs + 1]) - if i ==2 % speeds up plotting by factor of ~2 - set(gca,'LegendColorbarListeners',[]); - setappdata(gca,'LegendColorbarManualSpace',1); - setappdata(gca,'LegendColorbarReclaimSpace',1); - end - else p = plot(plot_x,plot_ye); xlabel('Number of epochs'); ylabel('Error');title('Error'); legend(p, M,'Location','NorthEast'); set(gca, 'Xlim',[0,opts.numepochs + 1]) - - if i ==2 % speeds up plotting by factor of ~2 - set(gca,'LegendColorbarListeners',[]); - setappdata(gca,'LegendColorbarManualSpace',1); - setappdata(gca,'LegendColorbarReclaimSpace',1); - - end - + end drawnow; end -end \ No newline at end of file +end diff --git a/README.md b/README.md index 80cfe9b..441e153 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + DeepLearnToolbox ================ @@ -53,9 +54,12 @@ Setup 1. Download. 2. addpath(genpath('DeepLearnToolbox')); -Everything is work in progress +Known errors ------------------------------ +`test_cnn_gradients_are_numerically_correct` fails on Octave because of a bug in Octave's convn implementation. See http://savannah.gnu.org/bugs/?39314 + +`test_example_CNN` fails in Octave for the same reason. Example: Deep Belief Network --------------------- ```matlab @@ -69,7 +73,7 @@ train_y = double(train_y); test_y = double(test_y); %% ex1 train a 100 hidden unit RBM and visualize its weights -rng(0); +rand('state',0) dbn.sizes = [100]; opts.numepochs = 1; opts.batchsize = 100; @@ -80,7 +84,7 @@ dbn = dbntrain(dbn, train_x, opts); figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights %% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NN -rng(0); +rand('state',0) %train dbn dbn.sizes = [100 100]; opts.numepochs = 1; @@ -119,7 +123,7 @@ test_y = double(test_y); %% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN % Setup and train a stacked denoising autoencoder (SDAE) -rng(0); +rand('state',0) sae = saesetup([784 100]); sae.ae{1}.activation_function = 'sigm'; sae.ae{1}.learningRate = 1; @@ -142,39 +146,6 @@ nn = nntrain(nn, train_x, train_y, opts); [er, bad] = nntest(nn, test_x, test_y); assert(er < 0.16, 'Too big error'); -%% ex2 train a 100-100 hidden unit SDAE and use it to initialize a FFNN -% Setup and train a stacked denoising autoencoder (SDAE) -rng(0); -sae = saesetup([784 100 100]); -sae.ae{1}.activation_function = 'sigm'; -sae.ae{1}.learningRate = 1; -sae.ae{1}.inputZeroMaskedFraction = 0.5; - -sae.ae{2}.activation_function = 'sigm'; -sae.ae{2}.learningRate = 1; -sae.ae{2}.inputZeroMaskedFraction = 0.5; - -opts.numepochs = 1; -opts.batchsize = 100; -sae = saetrain(sae, train_x, opts); -visualize(sae.ae{1}.W{1}(:,2:end)') - -% Use the SDAE to initialize a FFNN -nn = nnsetup([784 100 100 10]); -nn.activation_function = 'sigm'; -nn.learningRate = 1; - -%add pretrained weights -nn.W{1} = sae.ae{1}.W{1}; -nn.W{2} = sae.ae{2}.W{1}; - -% Train the FFNN -opts.numepochs = 1; -opts.batchsize = 100; -nn = nntrain(nn, train_x, train_y, opts); -[er, bad] = nntest(nn, test_x, test_y); -assert(er < 0.1, 'Too big error'); - ``` @@ -193,7 +164,7 @@ test_y = double(test_y'); %% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% error -rng(0) +rand('state',0) cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer @@ -236,7 +207,7 @@ test_y = double(test_y); test_x = normalize(test_x, mu, sigma); %% ex1 vanilla neural net -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); opts.numepochs = 1; % Number of full sweeps through data opts.batchsize = 100; % Take a mean gradient step over this many samples @@ -246,16 +217,8 @@ opts.batchsize = 100; % Take a mean gradient step over this many samples assert(er < 0.08, 'Too big error'); -% Make an artificial one and verify that we can predict it -x = zeros(1,28,28); -x(:, 14:15, 6:22) = 1; -x = reshape(x,1,28^2); -figure; visualize(x'); -predicted = nnpredict(nn,x)-1; - -assert(predicted == 1); %% ex2 neural net with L2 weight decay -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); nn.weightPenaltyL2 = 1e-4; % L2 weight decay @@ -269,7 +232,7 @@ assert(er < 0.1, 'Too big error'); %% ex3 neural net with dropout -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); nn.dropoutFraction = 0.5; % Dropout fraction @@ -282,7 +245,7 @@ nn = nntrain(nn, train_x, train_y, opts); assert(er < 0.1, 'Too big error'); %% ex4 neural net with sigmoid activation function -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); nn.activation_function = 'sigm'; % Sigmoid activation function @@ -296,7 +259,7 @@ nn = nntrain(nn, train_x, train_y, opts); assert(er < 0.1, 'Too big error'); %% ex5 plotting functionality -rng(0); +rand('state',0) nn = nnsetup([784 20 10]); opts.numepochs = 5; % Number of full sweeps through data nn.output = 'softmax'; % use softmax output @@ -315,7 +278,7 @@ tx = train_x(10001:end,:); vy = train_y(1:10000,:); ty = train_y(10001:end,:); -rng(0); +rand('state',0) nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax output opts.numepochs = 5; % Number of full sweeps through data @@ -325,6 +288,7 @@ nn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validati [er, bad] = nntest(nn, test_x, test_y); assert(er < 0.1, 'Too big error'); + ``` diff --git a/README_header.md b/README_header.md index 7ba03ae..91afe41 100644 --- a/README_header.md +++ b/README_header.md @@ -53,6 +53,9 @@ Setup 1. Download. 2. addpath(genpath('DeepLearnToolbox')); -Everything is work in progress +Known errors ------------------------------ +`test_cnn_gradients_are_numerically_correct` fails on Octave because of a bug in Octave's convn implementation. See http://savannah.gnu.org/bugs/?39314 + +`test_example_CNN` fails in Octave for the same reason. diff --git a/tests/runalltests.m b/tests/runalltests.m index 72ea2eb..a2ee47f 100644 --- a/tests/runalltests.m +++ b/tests/runalltests.m @@ -1,2 +1,8 @@ clear all; close all; clc; -runtests \ No newline at end of file + +addpath(genpath('.')); +dirlist = dir('tests/test_*'); +for i = 1:length(dirlist) + name = dirlist(i).name(1:end-2); + feval(name) +end diff --git a/tests/test_example_CNN.m b/tests/test_example_CNN.m index 6e3bfcb..954ded1 100644 --- a/tests/test_example_CNN.m +++ b/tests/test_example_CNN.m @@ -9,10 +9,14 @@ %% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% error +<<<<<<< HEAD if !isOctave() rng(0) end +======= +rand('state',0) +>>>>>>> upstream/master cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer diff --git a/tests/test_example_DBN.m b/tests/test_example_DBN.m index fd70e98..f5a5e6f 100644 --- a/tests/test_example_DBN.m +++ b/tests/test_example_DBN.m @@ -7,7 +7,7 @@ test_y = double(test_y); %% ex1 train a 100 hidden unit RBM and visualize its weights -rng(0); +rand('state',0) dbn.sizes = [100]; opts.numepochs = 1; opts.batchsize = 100; @@ -18,7 +18,7 @@ figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights %% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NN -rng(0); +rand('state',0) %train dbn dbn.sizes = [100 100]; opts.numepochs = 1; diff --git a/tests/test_example_NN.m b/tests/test_example_NN.m index 54ce079..c254ee7 100644 --- a/tests/test_example_NN.m +++ b/tests/test_example_NN.m @@ -11,7 +11,7 @@ test_x = normalize(test_x, mu, sigma); %% ex1 vanilla neural net -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); opts.numepochs = 1; % Number of full sweeps through data opts.batchsize = 100; % Take a mean gradient step over this many samples @@ -21,16 +21,8 @@ assert(er < 0.08, 'Too big error'); -% Make an artificial one and verify that we can predict it -x = zeros(1,28,28); -x(:, 14:15, 6:22) = 1; -x = reshape(x,1,28^2); -figure; visualize(x'); -predicted = nnpredict(nn,x)-1; - -assert(predicted == 1); %% ex2 neural net with L2 weight decay -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); nn.weightPenaltyL2 = 1e-4; % L2 weight decay @@ -44,7 +36,7 @@ %% ex3 neural net with dropout -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); nn.dropoutFraction = 0.5; % Dropout fraction @@ -57,7 +49,7 @@ assert(er < 0.1, 'Too big error'); %% ex4 neural net with sigmoid activation function -rng(0); +rand('state',0) nn = nnsetup([784 100 10]); nn.activation_function = 'sigm'; % Sigmoid activation function @@ -71,7 +63,7 @@ assert(er < 0.1, 'Too big error'); %% ex5 plotting functionality -rng(0); +rand('state',0) nn = nnsetup([784 20 10]); opts.numepochs = 5; % Number of full sweeps through data nn.output = 'softmax'; % use softmax output @@ -90,7 +82,7 @@ vy = train_y(1:10000,:); ty = train_y(10001:end,:); -rng(0); +rand('state',0) nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax output opts.numepochs = 5; % Number of full sweeps through data @@ -99,4 +91,4 @@ nn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally) [er, bad] = nntest(nn, test_x, test_y); -assert(er < 0.1, 'Too big error'); \ No newline at end of file +assert(er < 0.1, 'Too big error'); diff --git a/tests/test_example_SAE.m b/tests/test_example_SAE.m index b772d30..eed8a5c 100644 --- a/tests/test_example_SAE.m +++ b/tests/test_example_SAE.m @@ -8,7 +8,7 @@ %% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN % Setup and train a stacked denoising autoencoder (SDAE) -rng(0); +rand('state',0) sae = saesetup([784 100]); sae.ae{1}.activation_function = 'sigm'; sae.ae{1}.learningRate = 1; @@ -30,36 +30,3 @@ nn = nntrain(nn, train_x, train_y, opts); [er, bad] = nntest(nn, test_x, test_y); assert(er < 0.16, 'Too big error'); - -%% ex2 train a 100-100 hidden unit SDAE and use it to initialize a FFNN -% Setup and train a stacked denoising autoencoder (SDAE) -rng(0); -sae = saesetup([784 100 100]); -sae.ae{1}.activation_function = 'sigm'; -sae.ae{1}.learningRate = 1; -sae.ae{1}.inputZeroMaskedFraction = 0.5; - -sae.ae{2}.activation_function = 'sigm'; -sae.ae{2}.learningRate = 1; -sae.ae{2}.inputZeroMaskedFraction = 0.5; - -opts.numepochs = 1; -opts.batchsize = 100; -sae = saetrain(sae, train_x, opts); -visualize(sae.ae{1}.W{1}(:,2:end)') - -% Use the SDAE to initialize a FFNN -nn = nnsetup([784 100 100 10]); -nn.activation_function = 'sigm'; -nn.learningRate = 1; - -%add pretrained weights -nn.W{1} = sae.ae{1}.W{1}; -nn.W{2} = sae.ae{2}.W{1}; - -% Train the FFNN -opts.numepochs = 1; -opts.batchsize = 100; -nn = nntrain(nn, train_x, train_y, opts); -[er, bad] = nntest(nn, test_x, test_y); -assert(er < 0.1, 'Too big error'); diff --git a/tests/test_nn_gradients_are_numerically_correct.m b/tests/test_nn_gradients_are_numerically_correct.m index 721bf65..2b6df89 100644 --- a/tests/test_nn_gradients_are_numerically_correct.m +++ b/tests/test_nn_gradients_are_numerically_correct.m @@ -17,10 +17,10 @@ nn.output = output{1}; nn.dropoutFraction = dropoutFraction{1}; - rng(0) + rand('state',0) nn = nnff(nn, batch_x, y); nn = nnbp(nn); nnchecknumgrad(nn, batch_x, y); end end -end \ No newline at end of file +end diff --git a/util/visualize.m b/util/visualize.m index aec84ce..8739767 100644 --- a/util/visualize.m +++ b/util/visualize.m @@ -43,5 +43,9 @@ if nargout==1 r=a; else - imshow(a, [mm(1) mm(2)]); + + imagesc(a, [mm(1) mm(2)]); + axis equal + colormap gray + end diff --git a/util/xunit/+xunit/+utils/Contents.m b/util/xunit/+xunit/+utils/Contents.m deleted file mode 100644 index 7b0f017..0000000 --- a/util/xunit/+xunit/+utils/Contents.m +++ /dev/null @@ -1,24 +0,0 @@ -% UTILS Utility package for MATLAB xUnit Test Framework -% -% Array Comparison -% compareFloats - Compare floating-point arrays using tolerance -% -% Test Case Discovery Functions -% isTestCaseSubclass - True for name of TestCase subclass -% -% String Functions -% arrayToString - Convert array to string for display -% comparisonMessage - Assertion message string for comparing two arrays -% containsRegexp - True if string contains regular expression -% isSetUpString - True for string that looks like a setup function -% isTearDownString - True for string that looks like teardown function -% isTestString - True for string that looks like a test function -% stringToCellArray - Convert string to cell array of strings -% -% Miscellaneous Functions -% generateDoc - Publish test scripts in mtest/doc -% parseFloatAssertInputs - Common input-parsing logic for several functions - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - diff --git a/util/xunit/+xunit/+utils/arrayToString.m b/util/xunit/+xunit/+utils/arrayToString.m deleted file mode 100644 index 87bad51..0000000 --- a/util/xunit/+xunit/+utils/arrayToString.m +++ /dev/null @@ -1,96 +0,0 @@ -function s = arrayToString(A) -%arrayToString Convert array to string for display. -% S = arrayToString(A) converts the array A into a string suitable for -% including in assertion messages. Small arrays are converted using disp(A). -% Large arrays are displayed similar to the way structure field values display -% using disp. - -% Steven L. Eddins -% Copyright 2009 The MathWorks, Inc. - -if isTooBigToDisp(A) - s = dispAsStructField(A); -else - s = dispAsArray(A); -end - -%=============================================================================== -function tf = isTooBigToDisp(A) -% Use a heuristic to determine if the array is to convert to a string using -% disp. The heuristic is based on the size of the array in bytes, as reported -% by the whos function. - -whos_output = whos('A'); -byte_threshold = 1000; -tf = whos_output.bytes > byte_threshold; - -%=============================================================================== -function s = dispAsArray(A) -% Convert A to a string using disp. Remove leading and trailing blank lines. - -s = evalc('disp(A)'); -if isempty(s) - % disp displays nothing for some kinds of empty arrays. - s = dispAsStructField(A); -else - s = postprocessDisp(s); -end - -%=============================================================================== -function s = dispAsStructField(A) -% Convert A to a string using structure field display. - -b.A = A; -s = evalc('disp(b)'); -s = postprocessStructDisp(s); - -%=============================================================================== -function out = postprocessDisp(in) -% Remove leading and trailing blank lines from input string. Don't include a -% newline at the end. - -lines = xunit.utils.stringToCellArray(in); - -% Remove leading blank lines. -lines = removeLeadingBlankLines(lines); - -% Remove trailing blank lines. -while ~isempty(lines) && isBlankLine(lines{end}) - lines(end) = []; -end - -% Convert cell of strings to single string with newlines. Don't put a newline -% at the end. -out = sprintf('%s\n', lines{1:end-1}); -out = [out, lines{end}]; - -%=============================================================================== -function out = postprocessStructDisp(in) -% Return the portion of the display string to the right of the colon in the -% output of the first structure field. Input is a string. - -lines = xunit.utils.stringToCellArray(in); - -% Remove leading blank lines -lines = removeLeadingBlankLines(lines); - -line = lines{1}; -idx = find(line == ':'); -out = line((idx+2):end); % struct fields display with blank space following colon - -%=============================================================================== -function out = removeLeadingBlankLines(in) -% Input and output are cell arrays of strings. - -out = in; -while ~isempty(out) && isBlankLine(out{1}) - out(1) = []; -end - -%=============================================================================== -function tf = isBlankLine(line) -% Input is a string. - -tf = all(isspace(line)); - - diff --git a/util/xunit/+xunit/+utils/compareFloats.m b/util/xunit/+xunit/+utils/compareFloats.m deleted file mode 100644 index f4ec111..0000000 --- a/util/xunit/+xunit/+utils/compareFloats.m +++ /dev/null @@ -1,128 +0,0 @@ -function result = compareFloats(varargin) -%compareFloats Compare floating-point arrays using tolerance. -% result = compareFloats(A, B, compare_type, tol_type, tol, floor_tol) -% compares the floating-point arrays A and B using a tolerance. compare_type -% is either 'elementwise' or 'vector'. tol_type is either 'relative' or -% 'absolute'. tol and floor_tol are the scalar tolerance values. -% -% There are four different tolerance tests used, depending on the comparison -% type and the tolerance type: -% -% 1. Comparison type: 'elementwise' Tolerance type: 'relative' -% -% all( abs(A(:) - B(:)) <= tol * max(abs(A(:)), abs(B(:))) + floor_tol ) -% -% 2. Comparison type: 'elementwise' Tolerance type: 'absolute' -% -% all( abs(A(:) - B(:) <= tol ) -% -% 3. Comparison type: 'vector' Tolerance type: 'relative' -% -% norm(A(:) - B(:) <= tol * max(norm(A(:)), norm(B(:))) + floor_tol -% -% 4. Comparison type: 'vector' Tolerance type: 'absolute' -% -% norm(A(:) - B(:)) <= tol -% -% Note that floor_tol is not used when the tolerance type is 'absolute'. -% -% compare_type, tol_type, tol, and floor_tol are all optional inputs. The -% default value for compare_type is 'elementwise'. The default value for -% tol_type is 'relative'. If both A and B are double, then the default value -% for tol is sqrt(eps), and the default value for floor_tol is eps. If either -% A or B is single, then the default value for tol is sqrt(eps('single')), and -% the default value for floor_tol is eps('single'). -% -% If A or B is complex, then the tolerance test is applied independently to -% the real and imaginary parts. -% -% For elementwise comparisons, compareFloats returns true for two elements -% that are both NaN, or for two infinite elements that have the same sign. -% For vector comparisons, compareFloats returns false if any input elements -% are infinite or NaN. - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -if nargin >= 3 - % compare_type specified. Grab it and then use parseFloatAssertInputs to - % process the remaining input arguments. - compare_type = varargin{3}; - varargin(3) = []; - if isempty(strcmp(compare_type, {'elementwise', 'vector'})) - error('compareFloats:unrecognizedCompareType', ... - 'COMPARE_TYPE must be ''elementwise'' or ''vector''.'); - end -else - compare_type = 'elementwise'; -end - -params = xunit.utils.parseFloatAssertInputs(varargin{:}); - -A = params.A(:); -B = params.B(:); - -switch compare_type - case 'elementwise' - magFcn = @abs; - - case 'vector' - magFcn = @norm; - - otherwise - error('compareFloats:unrecognizedCompareType', ... - 'COMPARE_TYPE must be ''elementwise'' or ''vector''.'); -end - -switch params.ToleranceType - case 'relative' - coreCompareFcn = @(A, B) magFcn(A - B) <= ... - params.Tolerance * max(magFcn(A), magFcn(B)) + ... - params.FloorTolerance; - - case 'absolute' - coreCompareFcn = @(A, B) magFcn(A - B) <= params.Tolerance; - - otherwise - error('compareFloats:unrecognizedToleranceType', ... - 'TOL_TYPE must be ''relative'' or ''absolute''.'); -end - -if strcmp(compare_type, 'elementwise') - compareFcn = @(A, B) ( coreCompareFcn(A, B) | bothNaN(A, B) | sameSignInfs(A, B) ) & ... - ~oppositeSignInfs(A, B) & ... - ~finiteAndInfinite(A, B); -else - compareFcn = @(A, B) coreCompareFcn(A, B) & ... - isfinite(magFcn(A)) & ... - isfinite(magFcn(B)); -end - -if isreal(A) && isreal(B) - result = compareFcn(A, B); -else - result = compareFcn(real(A), real(B)) & compareFcn(imag(A), imag(B)); -end - -result = all(result); - -%=============================================================================== -function out = bothNaN(A, B) - -out = isnan(A) & isnan(B); - -%=============================================================================== -function out = oppositeSignInfs(A, B) - -out = isinf(A) & isinf(B) & (sign(A) ~= sign(B)); - -%=============================================================================== -function out = sameSignInfs(A, B) - -out = isinf(A) & isinf(B) & (sign(A) == sign(B)); - -%=============================================================================== -function out = finiteAndInfinite(A, B) - -out = xor(isinf(A), isinf(B)); - diff --git a/util/xunit/+xunit/+utils/comparisonMessage.m b/util/xunit/+xunit/+utils/comparisonMessage.m deleted file mode 100644 index 68e9a52..0000000 --- a/util/xunit/+xunit/+utils/comparisonMessage.m +++ /dev/null @@ -1,33 +0,0 @@ -function msg = comparisonMessage(user_message, assertion_message, A, B) -%comparisonMessage Generate assertion message when comparing two arrays. -% msg = comparisonMessage(user_message, assertion_message, A, B) returns a -% string appropriate to use in a call to throw inside an assertion function -% that compares two arrays A and B. -% -% The string returned has the following form: -% -% -% -% -% First input: -% -% -% Second input: -% -% -% user_message can be the empty string, '', in which case user_message is -% skipped. - -% Steven L. Eddins -% Copyright 2009 The MathWorks, Inc. - -msg = sprintf('%s\n\n%s\n%s\n\n%s\n%s', ... - assertion_message, ... - 'First input:', ... - xunit.utils.arrayToString(A), ... - 'Second input:', ... - xunit.utils.arrayToString(B)); - -if ~isempty(user_message) - msg = sprintf('%s\n%s', user_message, msg); -end diff --git a/util/xunit/+xunit/+utils/containsRegexp.m b/util/xunit/+xunit/+utils/containsRegexp.m deleted file mode 100644 index efbc51b..0000000 --- a/util/xunit/+xunit/+utils/containsRegexp.m +++ /dev/null @@ -1,17 +0,0 @@ -function tf = containsRegexp(str, exp) -%containsRegexp True if string contains regular expression -% TF = containsRegexp(str, exp) returns true if the string str contains the -% regular expression exp. If str is a cell array of strings, then -% containsRegexp tests each string in the cell array, returning the results in -% a logical array with the same size as str. - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -% Convert to canonical input form: A cell array of strings. -if ~iscell(str) - str = {str}; -end - -matches = regexp(str, exp); -tf = ~cellfun('isempty', matches); diff --git a/util/xunit/+xunit/+utils/generateDoc.m b/util/xunit/+xunit/+utils/generateDoc.m deleted file mode 100644 index 6a9959a..0000000 --- a/util/xunit/+xunit/+utils/generateDoc.m +++ /dev/null @@ -1,14 +0,0 @@ -function generateDoc -%generateDoc Publish the example scripts in the doc directory - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -doc_dir = fullfile(fileparts(which('runtests')), '..', 'doc'); -addpath(doc_dir); -cd(doc_dir) -mfiles = dir('*.m'); -for k = 1:numel(mfiles) - publish(mfiles(k).name); - cd(doc_dir) -end diff --git a/util/xunit/+xunit/+utils/isAlmostEqual.m b/util/xunit/+xunit/+utils/isAlmostEqual.m deleted file mode 100644 index 7ad4393..0000000 --- a/util/xunit/+xunit/+utils/isAlmostEqual.m +++ /dev/null @@ -1,46 +0,0 @@ -function same = isAlmostEqual(A, B, reltol) -%isAlmostEqual Equality test using relative tolerance -% same = isAlmostEqual(A, B, reltol), for two floating-point arrays A and B, -% tests A and B for equality using the specified relative tolerance. -% isAlmostEqual returns true if the following relationship is satisfied for -% all values in A and B: -% -% abs(A - B) ./ max(abs(A), abs(B)) <= reltol -% -% same = isAlmostEqual(A, B) uses the following value for the relative -% tolerance: -% -% 100 * max(eps(class(A)), eps(class(B))) -% -% If either A or B is not a floating-point array, then isAlmostEqual returns -% the result of isequal(A, B). - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -if ~isfloat(A) || ~isfloat(B) - same = isequal(A, B); - return -end - -if nargin < 3 - reltol = 100 * max(eps(class(A)), eps(class(B))); -end - -if ~isequal(size(A), size(B)) - same = false; - return -end - -A = A(:); -B = B(:); - -delta = abs(A - B) ./ max(max(abs(A), abs(B)), 1); - -% Some floating-point values require special handling. -delta((A == 0) & (B == 0)) = 0; -delta(isnan(A) & isnan(B)) = 0; -delta((A == Inf) & (B == Inf)) = 0; -delta((A == -Inf) & (B == -Inf)) = 0; - -same = all(delta <= reltol); diff --git a/util/xunit/+xunit/+utils/isSetUpString.m b/util/xunit/+xunit/+utils/isSetUpString.m deleted file mode 100644 index e3204fb..0000000 --- a/util/xunit/+xunit/+utils/isSetUpString.m +++ /dev/null @@ -1,12 +0,0 @@ -function tf = isSetUpString(str) -%isSetUpString True if string looks like the name of a setup function -% tf = isSetUpString(str) returns true if the string str looks like the name -% of a setup function. If str is a cell array of strings, then isSetUpString -% tests each string in the cell array, returning the results in a logical -% array with the same size as str. - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -setup_exp = '^[sS]et[uU]p'; -tf = xunit.utils.containsRegexp(str, setup_exp); diff --git a/util/xunit/+xunit/+utils/isTearDownString.m b/util/xunit/+xunit/+utils/isTearDownString.m deleted file mode 100644 index 6077a81..0000000 --- a/util/xunit/+xunit/+utils/isTearDownString.m +++ /dev/null @@ -1,12 +0,0 @@ -function tf = isTearDownString(str) -%isTearDownString True if string looks like the name of a teardown function -% tf = isTearDownString(str) returns true if the string str looks like the -% name of a teardown function. If str is a cell array of strings, then -% isTearDownString tests each string in the cell array, returning the results -% in a logical array with the same size as str. - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -setup_exp = '^[tT]ear[dD]own'; -tf = xunit.utils.containsRegexp(str, setup_exp); diff --git a/util/xunit/+xunit/+utils/isTestCaseSubclass.m b/util/xunit/+xunit/+utils/isTestCaseSubclass.m deleted file mode 100644 index 4df0c7f..0000000 --- a/util/xunit/+xunit/+utils/isTestCaseSubclass.m +++ /dev/null @@ -1,39 +0,0 @@ -function tf = isTestCaseSubclass(name) -%isTestCaseSubclass True for name of a TestCase subclass -% tf = isTestCaseSubclass(name) returns true if the string name is the name of -% a TestCase subclass on the MATLAB path. - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -tf = false; - -class_meta = meta.class.fromName(name); -if isempty(class_meta) - % Not the name of a class - return; -end - -if strcmp(class_meta.Name, 'TestCase') - tf = true; -else - tf = isMetaTestCaseSubclass(class_meta); -end - -function tf = isMetaTestCaseSubclass(class_meta) - -tf = false; - -if strcmp(class_meta.Name, 'TestCase') - tf = true; -else - % Invoke function recursively on parent classes. - super_classes = class_meta.SuperClasses; - for k = 1:numel(super_classes) - if isMetaTestCaseSubclass(super_classes{k}) - tf = true; - break; - end - end -end - diff --git a/util/xunit/+xunit/+utils/isTestString.m b/util/xunit/+xunit/+utils/isTestString.m deleted file mode 100644 index e7053d4..0000000 --- a/util/xunit/+xunit/+utils/isTestString.m +++ /dev/null @@ -1,15 +0,0 @@ -function tf = isTestString(str) -%isTestString True if string looks like the name of a test -% tf = isTestString(str) returns true if the string str looks like the name of -% a test. If str is a cell array of strings, then isTestString tests each -% string in the cell array, returning the results in a logical array with the -% same size as str. - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -test_at_beginning = '^[tT]est'; -test_at_end = '[tT]est$'; - -tf = xunit.utils.containsRegexp(str, test_at_beginning) | ... - xunit.utils.containsRegexp(str, test_at_end); diff --git a/util/xunit/+xunit/+utils/parseFloatAssertInputs.m b/util/xunit/+xunit/+utils/parseFloatAssertInputs.m deleted file mode 100644 index b36366e..0000000 --- a/util/xunit/+xunit/+utils/parseFloatAssertInputs.m +++ /dev/null @@ -1,56 +0,0 @@ -function params = parseFloatAssertInputs(varargin) -%parseFloatAssertInputs Parse inputs for floating-point assertion functions. -% params = parseFloatAssertInputs(varargin) parses the input arguments for -% assertElementsAlmostEqual, assertVectorsAlmostEqual, and compareFcn. It -% returns a parameter struct containing the fields: -% -% A B Message ToleranceType Tolerance FloorTolerance - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -error(nargchk(2, 6, nargin, 'struct')); - -params = struct('A', {[]}, 'B', {[]}, 'ToleranceType', {[]}, ... - 'Tolerance', {[]}, 'FloorTolerance', {[]}, 'Message', {''}); - -% The first two input arguments are always A and B. -params.A = varargin{1}; -params.B = varargin{2}; -varargin(1:2) = []; - -% If the last argument is a message string, process it and remove it from the list. -if (numel(varargin) >= 1) && ischar(varargin{end}) && ... - ~any(strcmp(varargin{end}, {'relative', 'absolute'})) - params.Message = varargin{end}; - varargin(end) = []; -else - params.Message = ''; -end - -try - epsilon = max(eps(class(params.A)), eps(class(params.B))); -catch - epsilon = eps; -end - -if numel(varargin) < 3 - % floor_tol not specified; set default. - params.FloorTolerance = sqrt(epsilon); -else - params.FloorTolerance = varargin{3}; -end - -if numel(varargin) < 2 - % tol not specified; set default. - params.Tolerance = sqrt(epsilon); -else - params.Tolerance = varargin{2}; -end - -if numel(varargin) < 1 - % tol_type not specified; set default. - params.ToleranceType = 'relative'; -else - params.ToleranceType = varargin{1}; -end diff --git a/util/xunit/+xunit/+utils/stringToCellArray.m b/util/xunit/+xunit/+utils/stringToCellArray.m deleted file mode 100644 index e2025aa..0000000 --- a/util/xunit/+xunit/+utils/stringToCellArray.m +++ /dev/null @@ -1,14 +0,0 @@ -function c = stringToCellArray(s) -%stringToCellArray Convert string with newlines to cell array of strings. -% C = stringToCellArray(S) converts the input string S to a cell array of -% strings, breaking up S at new lines. - -% Steven L. Eddins -% Copyright 2009 The MathWorks, Inc. - -if isempty(s) - c = cell(0, 1); -else - c = textscan(s, '%s', 'Delimiter', '\n', 'Whitespace', ''); - c = c{1}; -end diff --git a/util/xunit/CommandWindowTestRunDisplay.m b/util/xunit/CommandWindowTestRunDisplay.m deleted file mode 100644 index 0167631..0000000 --- a/util/xunit/CommandWindowTestRunDisplay.m +++ /dev/null @@ -1,30 +0,0 @@ -classdef CommandWindowTestRunDisplay < TestRunDisplay - %CommandWindowTestRunDisplay Print test suite execution results to Command Window. - % CommandWindowTestRunDisplay is a subclass of TestRunMonitor. If a - % CommandWindowTestRunDisplay object is passed to the run method of a - % TestComponent, such as a TestSuite or a TestCase, it will print information - % to the Command Window as the test run proceeds. - % - % CommandWindowTestRunDisplay methods: - % testComponentStarted - Update Command Window display - % testComponentFinished - Update Command Window display - % testCaseFailure - Log test failure information - % testCaseError - Log test error information - % - % CommandWindowTestRunDisplay properties: - % TestCaseCount - Number of test cases executed - % Faults - Struct array of test fault info - % - % See also TestRunLogger, TestRunMonitor, TestSuite - - % Steven L. Eddins - % Copyright 2008-2010 The MathWorks, Inc. - - methods - function self = CommandWindowTestRunDisplay - self = self@TestRunDisplay(1); - end - end - -end - diff --git a/util/xunit/Contents.m b/util/xunit/Contents.m deleted file mode 100644 index 79b2579..0000000 --- a/util/xunit/Contents.m +++ /dev/null @@ -1,33 +0,0 @@ -% MATLAB xUnit Test Framework -% Version 3.1 (R2010b) 19-Nov-2010 -% -% Running Unit Tests -% runtests - Run unit tests -% -% Writing Unit Tests -% assertElementsAlmostEqual - Assert floating-point array elements almost equal -% assertEqual - Assert that inputs are equal -% assertFilesEqual - Assert that two files have the same content -% assertExceptionThrown - Assert that specified exception is thrown -% assertFalse - Assert that input condition is false -% assertTrue - Assert that input condition is true -% assertVectorsAlmostEqual - Assert floating-point vectors almost equal in norm sense -% initTestSuite - Utility script used for subfunction-based tests -% -% Framework Classes -% CommandWindowTestRunDisplay - Print test suite results to command window -% FunctionHandleTestCase - Test case based on a function handle -% TestCase - Class defining interface for test cases -% TestCaseInDir - Test case requiring temporary directory change -% TestCaseWithAddPath - Test case requiring temporary path modification -% TestComponent - Abstract base class for TestCase and TestSuite -% TestComponentInDir - Test component requiring temporary directory change -% TestLogger - Collect data (silently) from running test suite -% TestRunDisplay - Print test suite execution results -% TestRunMonitor - Abstract base class for monitoring test suite -% TestSuite - Collection of TestComponent objects -% TestSuiteInDir - Test suite requiring temporary directory change -% %VerboseTestRunDisplay - Print test suite execution results - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. \ No newline at end of file diff --git a/util/xunit/FunctionHandleTestCase.m b/util/xunit/FunctionHandleTestCase.m deleted file mode 100644 index 7f8028c..0000000 --- a/util/xunit/FunctionHandleTestCase.m +++ /dev/null @@ -1,154 +0,0 @@ -classdef FunctionHandleTestCase < TestCase -%FunctionHandleTestCase Test case based on a function handle -% FunctionHandleTestCase is a TestCase subclass. It defines a test case object -% that executes by running a function handle instead of by running a method of -% the TestCase subclass. -% -% FunctionHandleTestCase methods: -% FunctionHandleTestCase - Constructor -% runTestCase - Run function handle test -% setUp - Run test-fixture setup function -% tearDown - Run test-fixture teardown function -% -% FunctionHandleTestCase properties: -% TestFcn - Function handle of test function -% SetupFcn - Function handle of setup function -% TeardownFcn - Function handle of teardown function -% TestData - Data needed by test function or teardown function -% -% See also TestCase, TestSuite - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - - properties (SetAccess = protected, GetAccess = protected, Hidden = true) - %TestFcn - Function handle of test function - % If SetupFcn has one or more output arguments, then TestFcn is - % called with this syntax: - % - % TestFcn(data) - % - % where data is the return value from SetupFcn. Otherwise, TestFcn is - % called with no input and no output arguments. - TestFcn; - - %SetupFcn - Function handle of setup function - % If SetupFcn has one or more output arguments, then SetupFcn is - % called with this syntax: - % - % data = SetupFcn() - % - % and data will be saved in the TestData property. Otherwise, SetupFcn - % is called with no input and no output arguments. - SetupFcn; - - %TeardownFcn - Function handle of teardown function - % If SetupFcn has one or more output arguments, then TeardownFcn is - % called with this syntax: - % - % TeardownFcn(data) - % - % were data is the return value from SetupFcn. Otherwise, TeardownFcn - % is called with no input and no output arguments. - TeardownFcn; - - %TestData - Data needed by test function or teardown function. - TestData; - end - - methods - function self = FunctionHandleTestCase(testFcn, setupFcn, teardownFcn) - %FunctionHandleTestCase Constructor - % FunctionHandleTestCase(testFcn, setupFcn, teardownFcn) creates a - % TestCase object that executes by running the function handle - % TestFcn. setupFcn is a function handle that will be executed - % before testFcn, and teardownFcn is a function handle that will - % be executed after TestFcn. Either setupFcn or teardownFcn can - % be empty. - % - % If setupFcn is function handle that has one output argument, - % then the three test functions will be called using these - % syntaxes: - % - % testData = setupFcn(); - % testFcn(testData); - % teardownFcn(testData); - % - % Otherwise, the three test functions are all called with no input - % arguments: - % - % setupFcn(); - % TestFcn(); - % teardownFcn(); - - % Call the base class constructor. Give it the name of the - % FunctionHandleTestCase method that executes TestFcn. - self = self@TestCase('runTestCase'); - - self.TestFcn = testFcn; - self.SetupFcn = setupFcn; - self.TeardownFcn = teardownFcn; - - % Determine the name and M-file location of the function handle. - functionHandleInfo = functions(testFcn); - self.Name = functionHandleInfo.function; - if strcmp(functionHandleInfo.type, 'anonymous') - % Anonymous function handles don't have an M-file location. - self.Location = ''; - else - self.Location = functionHandleInfo.file; - end - end - - function runTestCase(self) - %runTestCase Run function handle test - % test_case.run() calls the test function handle. If a nonempty - % SetupFcn was provided and it has at least one output argument, - % pass self.TestData to the test function. Otherwise, call the - % test function with no input arguments. - if ~isempty(self.SetupFcn) && nargout(self.SetupFcn) > 0 - self.TestFcn(self.TestData); - else - self.TestFcn(); - end - end - - function setUp(self) - %setUp Run test-fixture setup function - % If a nonempty SetupFcn was provided, run it. If the SetupFcn - % has at least one output argument, capture the first output - % argument in instance data (TestData). - if ~isempty(self.SetupFcn) - if nargout(self.SetupFcn) > 0 - if nargout(self.SetupFcn) > 1 - message = sprintf(['A test fixture setup function returns more than one output argument. ', ... - 'The test harness only calls the setup function with one output argument. ', ... - 'Return a struct or a cell array from your setup function if you need to bundle several parts together.', ... - '\nTest name: %s\nTest location: %s'], ... - self.Name, self.Location); - warning('xunit:FunctionHandleTestCase:TooManySetupOutputs', ... - '%s', message); - end - self.TestData = self.SetupFcn(); - else - self.SetupFcn(); - end - end - end - - function tearDown(self) - %tearDown Run test-fixture teardown function - % If a nonempty TeardownFcn was provided, run it. If there is - % TestData (the output of the SetupFcn), then pass it to - % TeardownFcn. Otherwise, call TeardownFcn with no input - % arguments. - if ~isempty(self.TeardownFcn) - if ~isempty(self.SetupFcn) && (nargout(self.SetupFcn) > 0) - self.TeardownFcn(self.TestData); - else - self.TeardownFcn(); - end - end - end - end -end \ No newline at end of file diff --git a/util/xunit/TestCase.m b/util/xunit/TestCase.m deleted file mode 100644 index 8b09ff8..0000000 --- a/util/xunit/TestCase.m +++ /dev/null @@ -1,103 +0,0 @@ -%TestCase Class defining interface for test cases -% The TestCase class defines an individual test case. -% -% Normally a test writer will create their own test class that is a subclass -% of TestCase. Each instance of the TestCase subclass that gets created will -% be associated with a single test method. -% -% If a test fixture is needed, override the setUp() and tearDown() methods. -% -% TestSuite(subclass_name), where subclass_name is the name of a TestCase -% subclass, creates a test suite containing one TestCase instance per test -% method contained in the subclass. -% -% A simpler test-writing alternative to use subfunction-based M-file tests. -% See the MATLAB xUnit documentation. -% -% TestCase methods: -% TestCase - Constructor -% run - Execute the test case -% -% TestCase properties: -% Location - Location of M-file containing the test case -% Name - Name of test case -% -% See also TestComponent, TestSuite - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -classdef TestCase < TestComponent - - properties - MethodName - end - - methods - function self = TestCase(testMethod) - %TestCase Constructor - % TestCase(methodName) constructs a TestCase object using the - % specified testMethod (a string). - - self.MethodName = testMethod; - self.Name = testMethod; - self.Location = which(class(self)); - end - - function did_pass = run(self, monitor) - %run Execute the test case - % test_case.run(monitor) calls the TestCase object's setUp() - % method, then the test method, then the tearDown() method. - % observer is a TestRunObserver object. The testStarted(), - % testFailure(), testError(), and testFinished() methods of - % observer are called at the appropriate times. monitor is a - % TestRunMonitor object. Typically it is either a TestRunLogger - % subclass or a CommandWindowTestRunDisplay subclass. - % - % test_case.run() automatically uses a - % CommandWindowTestRunDisplay object in order to print test - % suite execution information to the Command Window. - - if nargin < 2 - monitor = CommandWindowTestRunDisplay(); - end - - did_pass = true; - monitor.testComponentStarted(self); - - try - self.setUp(); - f = str2func(self.MethodName); - - try - % Call the test method. - f(self); - catch failureException - monitor.testCaseFailure(self, failureException); - did_pass = false; - end - - self.tearDown(); - - catch errorException - monitor.testCaseError(self, errorException); - did_pass = false; - end - - monitor.testComponentFinished(self, did_pass); - end - - function num = numTestCases(self) - num = 1; - end - - function print(self, numLeadingBlanks) - if nargin < 2 - numLeadingBlanks = 0; - end - fprintf('%s%s\n', blanks(numLeadingBlanks), self.Name); - end - - end - -end diff --git a/util/xunit/TestCaseInDir.m b/util/xunit/TestCaseInDir.m deleted file mode 100644 index 8c80f2a..0000000 --- a/util/xunit/TestCaseInDir.m +++ /dev/null @@ -1,30 +0,0 @@ -%TestCaseInDir Test case requiring temporary directory change -% The TestCaseInDir class defines a test case that has to be run by first -% changing to a specified directory. -% -% The setUp method adds the starting directory to the path and then uses cd to -% change into the specified directory. The tearDown method restores the -% original path and directory. -% -% TestCaseInDir is used by MATLAB xUnit's own test suite in order to test itself. -% -% TestCaseInDir methods: -% TestCaseInDir - Constructor -% -% See also TestCase, TestCaseWithAddPath, TestComponent - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -classdef TestCaseInDir < TestCase & TestComponentInDir - - methods - function self = TestCaseInDir(methodName, testDirectory) - %TestCaseInDir Constructor - % TestCaseInDir(testName, testDirectory) constructs a test case - % using the specified name and located in the specified directory. - self = self@TestCase(methodName); - self = self@TestComponentInDir(testDirectory); - end - end -end diff --git a/util/xunit/TestCaseWithAddPath.m b/util/xunit/TestCaseWithAddPath.m deleted file mode 100644 index 0f0e9f6..0000000 --- a/util/xunit/TestCaseWithAddPath.m +++ /dev/null @@ -1,53 +0,0 @@ -%TestCaseInDir Test case requiring temporary path modification -% The TestCaseInDir class defines a test case that has to be run by first -% adding a specific directory to the path. -% -% The setUp method adds the directory to the path, and the tearDown method -% restores the original path. -% -% TestCaseWithAddPath is used by MATLAB xUnit's own test suite in order to test -% itself. -% -% TestCaseWithAddPath methods: -% TestCaseWithAddPath - Constructor -% setUp - Add test directory to MATLAB path -% tearDown - Restore original MATLAB path -% -% See also TestCase, TestCaseInDir - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -classdef TestCaseWithAddPath < TestCase - properties (SetAccess = private, GetAccess = private) - %TestDirectory - Directory to be added to the path - TestDirectory - - %OriginalPath - Path prior to adding the test directory - OriginalPath - end - - methods - function self = TestCaseWithAddPath(methodName, testDirectory) - %TestCaseInDir Constructor - % TestCaseInDir(testName, testDirectory) constructs a test case - % using the specified name and located in the specified directory. - self = self@TestCase(methodName); - self.TestDirectory = testDirectory; - end - - function setUp(self) - %setUp Add test directory to MATLAB path. - % test_case.setUp() saves the current path in the OriginalPath - % property and then adds the TestDirectory to the MATLAB path. - self.OriginalPath = path; - addpath(self.TestDirectory); - end - - function tearDown(self) - %tearDown Restore original MATLAB path - % test_case.tearDown() restores the saved MATLAB path. - path(self.OriginalPath); - end - end -end diff --git a/util/xunit/TestComponent.m b/util/xunit/TestComponent.m deleted file mode 100644 index e68b5b5..0000000 --- a/util/xunit/TestComponent.m +++ /dev/null @@ -1,59 +0,0 @@ -classdef TestComponent < handle -%TestComponent Abstract base class for TestCase and TestSuite -% -% TestComponent methods: -% run - Run all test cases in test component -% print - Display summary of test component to Command Window -% numTestCases - Number of test cases in test component -% setUp - Initialize test fixture -% tearDown - Clean up text fixture -% -% TestComponent properties: -% Name - Name of test component -% Location - Directory where test component is defined -% -% See TestCase, TestSuite - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - - properties - Name = ''; - Location = ''; - end - - properties (Access = 'protected') - PrintIndentationSize = 4 - end - - methods (Abstract) - print() - %print Display summary of test component to Command Window - % obj.print() displays information about the test component to the - % Command Window. - - run() - %run Execute test cases - % obj.run() executes all the test cases in the test component - - numTestCases() - %numTestCases Number of test cases in test component - end - - methods - function setUp(self) - %setUp Set up test fixture - % test_component.setUp() is called at the beginning of the run() - % method. Test writers can override setUp if necessary to - % initialize a test fixture. - end - - function tearDown(self) - %tearDown Tear down test fixture - % test_component.tearDown() is at the end of the method. Test - % writers can override tearDown if necessary to clean up a test - % fixture. - end - - end -end \ No newline at end of file diff --git a/util/xunit/TestComponentInDir.m b/util/xunit/TestComponentInDir.m deleted file mode 100644 index d1193c6..0000000 --- a/util/xunit/TestComponentInDir.m +++ /dev/null @@ -1,58 +0,0 @@ -%TestComponentInDir Test component requiring temporary directory change -% The TestComponentInDir class defines a test component that has to be run by -% first changing to a specified directory. -% -% The setUp method adds the starting directory to the path and then uses cd to -% change into the specified directory. The tearDown method restores the -% original path and directory. -% -% TestComponentInDir methods: -% TestComponentInDir - Constructor -% setUp - Add test directory to MATLAB path -% tearDown - Restore original MATLAB path -% -% See also TestComponent - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -classdef TestComponentInDir < TestComponent - properties (SetAccess = private, GetAccess = protected) - %TestDirectory - Directory to change to in the test fixture - TestDirectory - - %OriginalPath - Path prior to adding the starting directory - OriginalPath - - %OriginalDirectory - Starting directory - OriginalDirectory - end - - methods - function self = TestComponentInDir(testDirectory) - %TestCaseInDir Constructor - % TestCaseInDir(testName, testDirectory) constructs a test case - % using the specified name and located in the specified directory. - self.TestDirectory = testDirectory; - end - - function setUp(self) - %setUp Add test directory to MATLAB path - % test_case.setUp() saves the current directory in the - % OriginalDirectory property, saves the current path in the - % OriginalPath property, and then uses cd to change into the test - % directory. - self.OriginalDirectory = pwd; - self.OriginalPath = path; - addpath(pwd); - cd(self.TestDirectory); - end - - function tearDown(self) - %tearDown Restore original MATLAB path and directory - % test_case.tearDown() restores the original path and directory. - cd(self.OriginalDirectory); - path(self.OriginalPath); - end - end -end diff --git a/util/xunit/TestRunDisplay.m b/util/xunit/TestRunDisplay.m deleted file mode 100644 index 57ae200..0000000 --- a/util/xunit/TestRunDisplay.m +++ /dev/null @@ -1,258 +0,0 @@ -classdef TestRunDisplay < TestRunMonitor -%TestRunDisplay Print test suite execution results. -% TestRunDisplay is a subclass of TestRunMonitor. If a TestRunDisplay -% object is passed to the run method of a TestComponent, such as a -% TestSuite or a TestCase, it will print information to the Command -% Window (or specified file handle) as the test run proceeds. -% -% TestRunDisplay methods: -% testComponentStarted - Update Command Window display -% testComponentFinished - Update Command Window display -% testCaseFailure - Log test failure information -% testCaseError - Log test error information -% -% TestRunDisplay properties: -% TestCaseCount - Number of test cases executed -% Faults - Struct array of test fault info -% -% See also TestRunLogger, TestRunMonitor, TestSuite - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - - properties (SetAccess = private) - %TestCaseCount - Number of test cases executed - TestCaseCount - - %Faults - Struct array of test fault info - % Faults is a struct array with these fields: - % Type - either 'failure' or 'error' - % TestCase - the TestCase object that suffered the fault - % Exception - the MException thrown when the fault occurred - Faults = struct('Type', {}, 'TestCase', {}, 'Exception', {}); - - end - - properties (SetAccess = private, GetAccess = private) - %InitialTic - Out of tic at beginning of test run - InitialTic - - %InitialComponent First test component executed - % InitialComponent is set to the first test component executed in the - % test run. This component is saved so that the end of the test run - % can be identified. - InitialComponent = [] - - end - - properties (Access = protected) - %FileHandle - Handle used by fprintf for displaying results. - % Default value of 1 displays to Command Window. - FileHandle = 1 - end - - - methods - function self = TestRunDisplay(output) - if nargin > 0 - if ischar(output) - self.FileHandle = fopen(output, 'w'); - if self.FileHandle < 0 - error('xunit:TestRunDisplay:FileOpenError', ... - 'Could not open file "%s" for writing.', ... - filename); - end - else - self.FileHandle = output; - end - end - end - - function testComponentStarted(self, component) - %testComponentStarted Update Command Window display - % If the InitialComponent property is not yet set, - % obj.testComponentStarted(component) sets the property and calls - % obj.testRunStarted(component). - - if isempty(self.InitialComponent) - self.InitialComponent = component; - self.testRunStarted(component); - end - end - - function testComponentFinished(self, component, did_pass) - %testComponentFinished Update Command Window display - % If component is a TestCase object, then - % obj.testComponentFinished(component, did_pass) prints pass/fail - % information to the Command Window. - % - % If component is the InitialComponent, then - % obj.testRunFinished(did_pass) is called. - - if isa(component, 'TestCase') - self.TestCaseCount = self.TestCaseCount + 1; - if did_pass - fprintf(self.FileHandle, '.'); - else - fprintf(self.FileHandle, 'F'); - end - line_length = 20; - if mod(self.TestCaseCount, line_length) == 0 - fprintf(self.FileHandle, '\n'); - end - end - - if isequal(component, self.InitialComponent) - self.testRunFinished(did_pass); - end - end - - function testCaseFailure(self, test_case, failure_exception) - %testCaseFailure Log test failure information - % obj.testCaseFailure(test_case, failure_exception) logs the test - % case failure information. - - self.logFault('failure', test_case, ... - failure_exception); - end - - function testCaseError(self, test_case, error_exception) - %testCaseError Log test error information - % obj.testCaseError(test_case, error_exception) logs the test - % case error information. - - self.logFault('error', test_case, ... - error_exception); - end - - end - - methods (Access = protected) - function testRunStarted(self, component) - %testRunStarted Update Command Window display - % obj.testRunStarted(component) displays information about the test - % run to the Command Window. - - self.InitialTic = tic; - self.TestCaseCount = 0; - num_cases = component.numTestCases(); - if num_cases == 1 - str = 'case'; - else - str = 'cases'; - end - fprintf(self.FileHandle, 'Starting test run with %d test %s.\n', ... - num_cases, str); - end - - function testRunFinished(self, did_pass) - %testRunFinished Update Command Window display - % obj.testRunFinished(component) displays information about the test - % run results, including any test failures, to the Command Window. - - if did_pass - result = 'PASSED'; - else - result = 'FAILED'; - end - - fprintf(self.FileHandle, '\n%s in %.3f seconds.\n', result, toc(self.InitialTic)); - - self.displayFaults(); - end - - - - function logFault(self, type, test_case, exception) - %logFault Log test fault information - % obj.logFault(type, test_case, exception) logs test fault - % information. type is either 'failure' or 'error'. test_case is a - % TestCase object. exception is an MException object. - - self.Faults(end + 1).Type = type; - self.Faults(end).TestCase = test_case; - self.Faults(end).Exception = exception; - end - - function displayFaults(self) - %displayFaults Display test fault info to Command Window - % obj.displayFaults() displays a summary of each test failure and - % test error to the command window. - for k = 1:numel(self.Faults) - faultData = self.Faults(k); - if strcmp(faultData.Type, 'failure') - str = 'Failure'; - else - str = 'Error'; - end - fprintf(self.FileHandle, '\n===== Test Case %s =====\nLocation: %s\nName: %s\n\n', str, ... - faultData.TestCase.Location, faultData.TestCase.Name); - displayStack(filterStack(faultData.Exception.stack), ... - self.FileHandle); - fprintf(self.FileHandle, '\n%s\n', faultData.Exception.message); - - fprintf(self.FileHandle, '\n'); - end - end - - end - -end - -function displayStack(stack, file_handle) -%displayStack Display stack trace from MException instance -% displayStack(stack) prints information about an exception stack to the -% command window. - -for k = 1:numel(stack) - filename = stack(k).file; - linenumber = stack(k).line; - href = sprintf('matlab: opentoline(''%s'',%d)', filename, linenumber); - fprintf(file_handle, '%s at line %d\n', filename, href, linenumber); -end -end - -function new_stack = filterStack(stack) -%filterStack Remove unmeaningful stack trace calls -% new_stack = filterStack(stack) removes from the input stack trace calls -% that are framework functions and methods that are not likely to be -% meaningful to the user. - -% Testing stack traces follow this common pattern: -% -% 1. The first function call in the trace is often one of the assert functions -% in the framework directory. This is useful to see. -% -% 2. The next function calls are in the user-written test functions/methods and -% the user-written code under test. These calls are useful to see. -% -% 3. The final set of function calls are methods in the various framework -% classes. There are usually several of these calls, which clutter up the -% stack display without being that useful. -% -% The pattern above suggests the following stack filtering strategy: Once the -% stack trace has left the framework directory, do not follow the stack trace back -% into the framework directory. - -mtest_directory = fileparts(which('runtests')); -last_keeper = numel(stack); -have_left_mtest_directory = false; -for k = 1:numel(stack) - directory = fileparts(stack(k).file); - if have_left_mtest_directory - if strcmp(directory, mtest_directory) - % Stack trace has reentered mtest directory. - last_keeper = k - 1; - break; - end - else - if ~strcmp(directory, mtest_directory) - have_left_mtest_directory = true; - end - end -end - -new_stack = stack(1:last_keeper); - -end - diff --git a/util/xunit/TestRunLogger.m b/util/xunit/TestRunLogger.m deleted file mode 100644 index 2a82978..0000000 --- a/util/xunit/TestRunLogger.m +++ /dev/null @@ -1,104 +0,0 @@ -%TestRunLogger Collect data (silently) from running test suite -% TestRunLogger is a subclass of TestRunMonitor uses to collect information -% from an executing test component (either a test case or a test suite). -% It maintains a record of event notifications received, as well as any test -% failures or test errors. -% -% TestRunLogger methods: -% testComponentStarted - Log test component started -% testComponentFinished - Log test component finished -% testCaseFailure - Log test case failure -% testCaseError - Log test case error -% -% TestRunLogger properties: -% Log - Cell array of test notification strings -% NumFailures - Number of test failures during execution -% NumErrors - Number of test errors during execution -% NumTestCases - Total number of test cases executed -% Faults - Struct array of test fault information -% -% See also CommandWindowTestRunDisplay, TestRunMonitor, TestSuite - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -classdef TestRunLogger < TestRunMonitor - - properties (SetAccess = protected) - %Log Cell array of test notification strings - % Test notification strings include 'TestRunStarted', - % 'TestRunFinished', 'TestComponentStarted', 'TestComponentFinished', - % 'TestCaseFailure', and 'TestCaseError'. - Log - - %NumFailures Number of test failures during execution - NumFailures = 0 - - %NumErrors Number of test errors during execution - NumErrors = 0 - - %NumTestCases Total number of test cases executed - NumTestCases = 0 - - %Faults Struct array of test fault information - % Faults is a struct array with the fields Type, TestCase, and - % Exception. Type is either 'failure' or 'error'. TestCase is the - % test case object that triggered the fault. Exception is the - % MException object thrown during the fault. - Faults = struct('Type', {}, 'TestCase', {}, 'Exception', {}); - end - - properties (SetAccess = private, GetAccess = private) - InitialTestComponent = [] - end - - methods - - function testComponentStarted(self, component) - if isempty(self.InitialTestComponent) - self.InitialTestComponent = component; - self.appendToLog('TestRunStarted'); - end - - self.appendToLog('TestComponentStarted'); - - if isa(component, 'TestCase') - self.NumTestCases = self.NumTestCases + 1; - end - end - - function testComponentFinished(self, component, did_pass) - self.appendToLog('TestComponentFinished'); - - if isequal(component, self.InitialTestComponent) - self.appendToLog('TestRunFinished'); - end - end - - function testCaseFailure(self, test_case, failure_exception) - self.appendToLog('TestCaseFailure'); - self.NumFailures = self.NumFailures + 1; - self.logFault('failure', test_case, ... - failure_exception); - end - - function testCaseError(self, test_case, error_exception) - self.appendToLog('TestCaseError'); - self.NumErrors = self.NumErrors + 1; - self.logFault('error', test_case, ... - error_exception); - end - end - - methods (Access = private) - function appendToLog(self, item) - self.Log{end+1} = item; - end - - function logFault(self, type, test_case, exception) - self.Faults(end + 1).Type = type; - self.Faults(end).TestCase = test_case; - self.Faults(end).Exception = exception; - end - end -end diff --git a/util/xunit/TestRunMonitor.m b/util/xunit/TestRunMonitor.m deleted file mode 100644 index 4af7490..0000000 --- a/util/xunit/TestRunMonitor.m +++ /dev/null @@ -1,35 +0,0 @@ -%TestRunMonitor Abstract base class for monitoring a running test suite -% The abstract TestRunMonitor class defines an object that can observe and -% record the results of running a test suite. The run() method of a -% TestComponent object takes a TestRunMonitor object as an input argument. -% -% Different test suite logging or reporting functionality can be achieved by -% subclassing TestRunMonitor. For example, see the TestRunLogger and the -% CommandWindowTestRunDisplay classes. -% -% TestRunMonitor methods: -% TestRunMonitor - Constructor -% testComponentStarted - Called at beginning of test component run -% testComponentFinished - Called when test component run finished -% testCaseFailure - Called when a test case fails -% testCaseError - Called when a test case causes an error -% -% See also CommandWindowTestRunDisplay, TestRunLogger, TestCase, TestSuite - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -classdef TestRunMonitor < handle - - methods (Abstract) - - testComponentStarted(self, component) - - testComponentFinished(self, component, did_pass) - - testCaseFailure(self, test_case, failure_exception) - - testCaseError(self, test_case, error_exception) - - end -end diff --git a/util/xunit/TestSuite.m b/util/xunit/TestSuite.m deleted file mode 100644 index a55d919..0000000 --- a/util/xunit/TestSuite.m +++ /dev/null @@ -1,342 +0,0 @@ -%TestSuite Collection of TestComponent objects -% The TestSuite class defines a collection of TestComponent objects. -% -% TestSuite methods: -% TestSuite - Constructor -% add - Add test component to test suite -% print - Display test suite summary to Command Window -% run - Run the test suite -% keepMatchingTestCase - Keep only the named test component -% fromName - Construct test suite from directory or MATLAB function file name -% fromTestCaseClassName - Construct test suite from TestCase class name -% fromPackageName - Construct test suite from package name -% fromPwd - Construct test suite from present directory -% -% TestSuite properties: -% TestComponents - Cell array of TestComponent objects -% -% Examples -% -------- -% Run all the test cases in the SampleTests1 class. Display test suite -% progress and a summary of results in the Command Window. -% -% TestSuite('SampleTests1').run() -% -% Construct a test suite from all test components found in the current -% directory. -% -% suite = TestSuite.fromPwd(); -% -% Construct a test suite from all test components found in the package -% 'mytool.tests'. (Note that the "+" character at the beginning of the package -% folder name on disk is not part of the package name.) -% -% suite = TestSuite.fromPackageName('mytool.tests'); -% -% Run all the test cases in the SampleTests class. Display no output to the -% Command Window. Upon completion, query the number of test failures and test -% errors. -% -% logger = TestRunLogger(); -% TestSuite('SampleTests1').run(logger); -% numFailures = logger.NumFailures -% numErrors = logger.NumErrors -% -% See also CommandWindowTestRunDisplay, TestCase, TestComponent, TestRunLogger - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -classdef TestSuite < TestComponent - - properties (SetAccess = protected) - TestComponents = {}; - end - - methods - - function self = TestSuite(name) - %TestSuite Constructor - % suite = TestSuite constructs an empty test suite. suite = - % TestSuite(name) constructs a test suite by searching for test - % cases defined in an M-file with the specified name. - - if nargin >= 1 - self = TestSuite.fromName(name); - end - end - - function did_pass_out = run(self, monitor) - %run Execute test cases in test suite - % did_pass = suite.run() executes all test cases in the test - % suite, returning a logical value indicating whether or not all - % test cases passed. - - if nargin < 2 - monitor = CommandWindowTestRunDisplay(); - end - - monitor.testComponentStarted(self); - did_pass = true; - - self.setUp(); - - for k = 1:numel(self.TestComponents) - this_component_passed = self.TestComponents{k}.run(monitor); - did_pass = did_pass && this_component_passed; - end - - self.tearDown(); - - monitor.testComponentFinished(self, did_pass); - - if nargout > 0 - did_pass_out = did_pass; - end - end - - function num = numTestCases(self) - %numTestCases Number of test cases in test suite - - num = 0; - for k = 1:numel(self.TestComponents) - component_k = self.TestComponents{k}; - num = num + component_k.numTestCases(); - end - end - - function print(self, numLeadingBlanks) - %print Display test suite summary to Command Window - % test_suite.print() displays a summary of the test suite to the - % Command Window. - - if nargin < 2 - numLeadingBlanks = 0; - end - fprintf('%s%s\n', blanks(numLeadingBlanks), self.Name); - for k = 1:numel(self.TestComponents) - self.TestComponents{k}.print(numLeadingBlanks + ... - self.PrintIndentationSize); - end - end - - function add(self, component) - %add Add test component to test suite - % test_suite.add(component) adds the TestComponent object to the - % test suite. - - if iscell(component) - self.TestComponents((1:numel(component)) + end) = component; - else - self.TestComponents{end + 1} = component; - end - end - - function keepMatchingTestCase(self, name) - %keepMatchingTestCase Keep only the named test component - % test_suite.keepMatchingTestCase(name) keeps only the test - % component with a matching name and discards the rest. - - idx = []; - for k = 1:numel(self.TestComponents) - if strcmp(self.TestComponents{k}.Name, name) - idx = k; - break; - end - end - if isempty(idx) - self.TestComponents = {}; - else - self.TestComponents = self.TestComponents(idx); - end - end - - end - - methods (Static) - function suite = fromTestCaseClassName(class_name) - %fromTestCaseClassName Construct test suite from TestCase class name - % suite = TestSuite.fromTestCaseClassName(name) constructs a - % TestSuite object from the name of a TestCase subclass. - - if ~xunit.utils.isTestCaseSubclass(class_name) - error('xunit:fromTestCaseClassName', ... - 'Input string "%s" is not the name of a TestCase class.', ... - class_name); - end - - suite = TestSuite; - suite.Name = class_name; - suite.Location = which(class_name); - - methods = getClassMethods(class_name); - for k = 1:numel(methods) - if methodIsConstructor(methods{k}) - continue - end - - method_name = methods{k}.Name; - if xunit.utils.isTestString(method_name) - suite.add(feval(class_name, method_name)); - end - end - - end - - function suite = fromName(name) - %fromName Construct test suite from M-file name - % test_suite = TestSuite.fromName(name) constructs a TestSuite - % object from an M-file with the given name. The name can be of a - % directory, a TestCase subclass, or an M-file containing a simple - % test or containing subfunction-based tests. - % - % Optionally, name can contain a colon (':') followed by filter - % string. The filter string is used to select a particular named - % test case. For example, TestSuite.fromName('MyTests:testA') - % constructs a TestSuite object containing only the test case - % named 'testA' found in the TestCase subclass MyTests. - - if isdir(name) - suite = TestSuiteInDir(name); - suite.gatherTestCases(); - return; - end - - [name, filter_string] = strtok(name, ':'); - if ~isempty(filter_string) - filter_string = filter_string(2:end); - end - - if xunit.utils.isTestCaseSubclass(name) - suite = TestSuite.fromTestCaseClassName(name); - - elseif ~isempty(meta.class.fromName(name)) - % Input is the name of a class that is not a TestCase subclass. - % Return an empty test suite. - suite = TestSuite(); - suite.Name = name; - - elseif isPackage(name) - suite = TestSuite.fromPackageName(name); - - else - - try - if nargout(name) == 0 - suite = TestSuite(); - suite.Name = name; - suite.add(FunctionHandleTestCase(str2func(name), [], [])); - suite.Location = which(name); - - else - suite = feval(name); - if ~isa(suite, 'TestSuite') - error('Function did not return a TestSuite object.'); - end - end - - catch - % Ordinary function does not appear to contain tests. - % Return an empty test suite. - suite = TestSuite(); - suite.Name = name; - end - end - - if ~isempty(filter_string) - suite.keepMatchingTestCase(filter_string); - end - end - - function test_suite = fromPwd() - %fromPwd Construct test suite from present directory - % test_suite = TestSuite.fromPwd() constructs a TestSuite object - % from all the test components in the present working directory. - % all TestCase subclasses will be found, as well as simple and - % subfunction-based M-file tests beginning with the string 'test' - % or 'Test'. - - test_suite = TestSuite(); - test_suite.Name = pwd; - test_suite.Location = pwd; - - mfiles = dir(fullfile('.', '*.m')); - for k = 1:numel(mfiles) - [path, name] = fileparts(mfiles(k).name); - if xunit.utils.isTestCaseSubclass(name) - test_suite.add(TestSuite.fromTestCaseClassName(name)); - elseif xunit.utils.isTestString(name) - suite_k = TestSuite.fromName(name); - if ~isempty(suite_k.TestComponents) - test_suite.add(suite_k); - end - end - end - end - - function test_suite = fromPackageName(name) - %fromPackageName Construct test suite from package name - % test_suite = TestSuite.fromPackageName(name) constructs a - % TestSuite object from all the test components found in the - % specified package. - - package_info = meta.package.fromName(name); - if isempty(package_info) - error('xunit:fromPackageName:invalidName', ... - 'Input string "%s" is not the name of a package.', ... - name); - end - test_suite = TestSuite(); - test_suite.Name = name; - test_suite.Location = 'Package'; - - for k = 1:numel(package_info.Packages) - pkg_name = package_info.Packages{k}.Name; - pkg_suite = TestSuite.fromPackageName(pkg_name); - if ~isempty(pkg_suite.TestComponents) - test_suite.add(TestSuite.fromPackageName(pkg_name)); - end - end - - class_names = cell(1, numel(package_info.Classes)); - for k = 1:numel(package_info.Classes) - class_name = package_info.Classes{k}.Name; - class_names{k} = class_name; - if xunit.utils.isTestCaseSubclass(class_name) - test_suite.add(TestSuite.fromTestCaseClassName(class_name)); - end - end - - for k = 1:numel(package_info.Functions) - function_name = package_info.Functions{k}.Name; - if xunit.utils.isTestString(function_name) - full_function_name = [package_info.Name '.' package_info.Functions{k}.Name]; - if ~ismember(full_function_name, class_names) - suite_k = TestSuite.fromName(full_function_name); - if ~isempty(suite_k.TestComponents) - test_suite.add(suite_k); - end - end - end - end - end - end -end - -function tf = isPackage(name) -tf = ~isempty(meta.package.fromName(name)); -end - -function methods = getClassMethods(class_name) -class_meta = meta.class.fromName(class_name); -methods = class_meta.Methods; -end - -function result = methodIsConstructor(method) -method_name = method.Name; -if ~isempty(method.DefiningClass.ContainingPackage) - method_name = [method.DefiningClass.ContainingPackage.Name, '.', ... - method_name]; -end -result = strcmp(method_name, method.DefiningClass.Name); -end diff --git a/util/xunit/TestSuiteInDir.m b/util/xunit/TestSuiteInDir.m deleted file mode 100644 index e83ef5e..0000000 --- a/util/xunit/TestSuiteInDir.m +++ /dev/null @@ -1,50 +0,0 @@ -%TestSuiteInDir Test suite requiring temporary directory change -% The TestSuiteInDir class defines a test suite that has to be run by first -% changing to a specified directory. -% -% The setUp method adds the starting directory to the path and then uses cd to -% change into the specified directory. The tearDown method restores the -% original path and directory. -% -% TestSuiteInDir methods: -% TestSuiteInDir - Constructor -% gatherTestCases - Add test cases found in the target directory -% -% See also TestSuite - -% Steven L. Eddins -% Copyright 2009 The MathWorks, Inc. - -classdef TestSuiteInDir < TestSuite & TestComponentInDir - - methods - function self = TestSuiteInDir(testDirectory) - %TestCaseInDir Constructor - % TestCaseInDir(testName, testDirectory) constructs a test case - % using the specified name and located in the specified directory. - self = self@TestComponentInDir(testDirectory); - - if strcmp(testDirectory, '.') - self.Name = pwd; - self.Location = pwd; - else - [pathstr, name] = fileparts(testDirectory); - self.Name = name; - self.Location = testDirectory; - end - end - - function gatherTestCases(self) - %gatherTestCases Add test cases found in the target directory - % suite.gatherTestCases() automaticall finds all the test cases in - % the directory specified in the constructor call and adds them to - % the suite. - current_dir = pwd; - c = onCleanup(@() cd(current_dir)); - - cd(self.TestDirectory); - tmp = TestSuite.fromPwd(); - self.TestComponents = tmp.TestComponents; - end - end -end diff --git a/util/xunit/VerboseTestRunDisplay.m b/util/xunit/VerboseTestRunDisplay.m deleted file mode 100644 index 18e85b1..0000000 --- a/util/xunit/VerboseTestRunDisplay.m +++ /dev/null @@ -1,112 +0,0 @@ -classdef VerboseTestRunDisplay < TestRunDisplay -%VerboseTestRunDisplay Print test suite execution results. -% VerboseTestRunDisplay is a subclass of -% TestRunDisplay. It supports the -verbose option of runtests. -% -% Overriddent methods: -% testComponentStarted - Update Command Window display -% testComponentFinished - Update Command Window display -% testRunFinished - Update Command Window display at end of run -% -% See also TestRunDisplay, TestRunLogger, TestRunMonitor, TestSuite - -% Steven L. Eddins -% Copyright 2010 The MathWorks, Inc. - - properties (SetAccess = private, GetAccess = private) - TicStack = uint64([]) - end - - methods - function self = VerboseTestRunDisplay(output) - if nargin < 1 - output = 1; - end - - self = self@TestRunDisplay(output); - end - - function testComponentStarted(self, component) - %testComponentStarted Update Command Window display - - self.pushTic(); - - if ~isa(component, 'TestCase') - fprintf(self.FileHandle, '\n'); - end - - fprintf(self.FileHandle, '%s%s', self.indentationSpaces(), component.Name); - - if ~isa(component, 'TestCase') - fprintf(self.FileHandle, '\n'); - else - fprintf(self.FileHandle, ' %s ', self.leaderDots(component.Name)); - end - end - - function testComponentFinished(self, component, did_pass) - %testComponentFinished Update Command Window display - - if ~isa(component, 'TestCase') - fprintf(self.FileHandle, '%s%s %s ', self.indentationSpaces(), component.Name, ... - self.leaderDots(component.Name)); - end - - component_run_time = toc(self.popTic()); - - if did_pass - fprintf(self.FileHandle, 'passed in %12.6f seconds\n', component_run_time); - else - fprintf(self.FileHandle, 'FAILED in %12.6f seconds\n', component_run_time); - end - - if ~isa(component, 'TestCase') - fprintf(self.FileHandle, '\n'); - end - - if isempty(self.TicStack) - self.testRunFinished(); - end - - end - - end - - methods (Access = protected) - function testRunFinished(self) - %testRunFinished Update Command Window display - % obj.testRunFinished(component) displays information about the test - % run results, including any test failures, to the Command - % Window. - - self.displayFaults(); - end - end - - methods (Access = private) - function pushTic(self) - self.TicStack(end+1) = tic; - end - - function t1 = popTic(self) - t1 = self.TicStack(end); - self.TicStack(end) = []; - end - - function str = indentationSpaces(self) - str = repmat(' ', 1, self.numIndentationSpaces()); - end - - function n = numIndentationSpaces(self) - indent_level = numel(self.TicStack) - 1; - n = 3 * indent_level; - end - - function str = leaderDots(self, name) - num_dots = max(0, 60 - self.numIndentationSpaces() - numel(name)); - str = repmat('.', 1, num_dots); - end - - end - -end diff --git a/util/xunit/assertElementsAlmostEqual.m b/util/xunit/assertElementsAlmostEqual.m deleted file mode 100644 index 3ac2ba6..0000000 --- a/util/xunit/assertElementsAlmostEqual.m +++ /dev/null @@ -1,61 +0,0 @@ -function assertElementsAlmostEqual(varargin) -%assertElementsAlmostEqual Assert floating-point array elements almost equal. -% assertElementsAlmostEqual(A, B, tol_type, tol, floor_tol) asserts that all -% elements of floating-point arrays A and B are equal within some tolerance. -% tol_type can be 'relative' or 'absolute'. tol and floor_tol are scalar -% tolerance values. -% -% If the tolerance type is 'relative', then the tolerance test used is: -% -% all( abs(A(:) - B(:)) <= tol * max(abs(A(:)), abs(B(:))) + floor_tol ) -% -% If the tolerance type is 'absolute', then the tolerance test used is: -% -% all( abs(A(:) - B(:)) <= tol ) -% -% tol_type, tol, and floor_tol are all optional. The default value for -% tol_type is 'relative'. If both A and B are double, then the default value -% for tol and floor_tol is sqrt(eps). If either A or B is single, then the -% default value for tol and floor_tol is sqrt(eps('single')). -% -% If A or B is complex, then the tolerance test is applied independently to -% the real and imaginary parts. -% -% Corresponding elements in A and B that are both NaN, or are both infinite -% with the same sign, are considered to pass the tolerance test. -% -% assertElementsAlmostEqual(A, B, ..., msg) prepends the string msg to the -% output message if A and B fail the tolerance test. - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -params = xunit.utils.parseFloatAssertInputs(varargin{:}); - -if ~isequal(size(params.A), size(params.B)) - message = xunit.utils.comparisonMessage(params.Message, ... - 'Inputs are not the same size.', ... - params.A, params.B); - throwAsCaller(MException('assertElementsAlmostEqual:sizeMismatch', ... - '%s', message)); -end - -if ~(isfloat(params.A) && isfloat(params.B)) - message = xunit.utils.comparisonMessage(params.Message, ... - 'Inputs are not both floating-point.', ... - params.A, params.B); - throwAsCaller(MException('assertElementsAlmostEqual:notFloat', ... - '%s', message)); -end - -if ~xunit.utils.compareFloats(params.A, params.B, 'elementwise', ... - params.ToleranceType, params.Tolerance, params.FloorTolerance) - - tolerance_message = sprintf('Input elements are not all equal within %s tolerance: %g', ... - params.ToleranceType, params.Tolerance); - message = xunit.utils.comparisonMessage(params.Message, tolerance_message, ... - params.A, params.B); - - throwAsCaller(MException('assertElementsAlmostEqual:tolExceeded', ... - '%s', message)); -end diff --git a/util/xunit/assertEqual.m b/util/xunit/assertEqual.m deleted file mode 100644 index 72349cd..0000000 --- a/util/xunit/assertEqual.m +++ /dev/null @@ -1,43 +0,0 @@ -function assertEqual(A, B, custom_message) -%assertEqual Assert that inputs are equal -% assertEqual(A, B) throws an exception if A and B are not equal. A and B -% must have the same class and sparsity to be considered equal. -% -% assertEqual(A, B, MESSAGE) prepends the string MESSAGE to the assertion -% message if A and B are not equal. -% -% Examples -% -------- -% % This call returns silently. -% assertEqual([1 NaN 2], [1 NaN 2]); -% -% % This call throws an error. -% assertEqual({'A', 'B', 'C'}, {'A', 'foo', 'C'}); -% -% See also assertElementsAlmostEqual, assertVectorsAlmostEqual - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -if nargin < 3 - custom_message = ''; -end - -if ~ (issparse(A) == issparse(B)) - message = xunit.utils.comparisonMessage(custom_message, ... - 'One input is sparse and the other is not.', A, B); - throwAsCaller(MException('assertEqual:sparsityNotEqual', '%s', message)); -end - -if ~strcmp(class(A), class(B)) - message = xunit.utils.comparisonMessage(custom_message, ... - 'The inputs differ in class.', A, B); - throwAsCaller(MException('assertEqual:classNotEqual', '%s', message)); -end - -if ~isequalwithequalnans(A, B) - message = xunit.utils.comparisonMessage(custom_message, ... - 'Inputs are not equal.', A, B); - throwAsCaller(MException('assertEqual:nonEqual', '%s', message)); -end - diff --git a/util/xunit/assertExceptionThrown.m b/util/xunit/assertExceptionThrown.m deleted file mode 100644 index bbe6b72..0000000 --- a/util/xunit/assertExceptionThrown.m +++ /dev/null @@ -1,53 +0,0 @@ -function assertExceptionThrown(f, expectedId, custom_message) -%assertExceptionThrown Assert that specified exception is thrown -% assertExceptionThrown(F, expectedId) calls the function handle F with no -% input arguments. If the result is a thrown exception whose identifier is -% expectedId, then assertExceptionThrown returns silently. If no exception is -% thrown, then assertExceptionThrown throws an exception with identifier equal -% to 'assertExceptionThrown:noException'. If a different exception is thrown, -% then assertExceptionThrown throws an exception identifier equal to -% 'assertExceptionThrown:wrongException'. -% -% assertExceptionThrown(F, expectedId, msg) prepends the string msg to the -% assertion message. -% -% Example -% ------- -% % This call returns silently. -% f = @() error('a:b:c', 'error message'); -% assertExceptionThrown(f, 'a:b:c'); -% -% % This call returns silently. -% assertExceptionThrown(@() sin, 'MATLAB:minrhs'); -% -% % This call throws an error because calling sin(pi) does not error. -% assertExceptionThrown(@() sin(pi), 'MATLAB:foo'); - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -noException = false; -try - f(); - noException = true; - -catch exception - if ~strcmp(exception.identifier, expectedId) - message = sprintf('Expected exception %s but got exception %s.', ... - expectedId, exception.identifier); - if nargin >= 3 - message = sprintf('%s\n%s', custom_message, message); - end - throwAsCaller(MException('assertExceptionThrown:wrongException', ... - '%s', message)); - end -end - -if noException - message = sprintf('Expected exception "%s", but none thrown.', ... - expectedId); - if nargin >= 3 - message = sprintf('%s\n%s', custom_message, message); - end - throwAsCaller(MException('assertExceptionThrown:noException', '%s', message)); -end diff --git a/util/xunit/assertFalse.m b/util/xunit/assertFalse.m deleted file mode 100644 index 7bc3e84..0000000 --- a/util/xunit/assertFalse.m +++ /dev/null @@ -1,31 +0,0 @@ -function assertFalse(condition, message) -%assertFalse Assert that input condition is false -% assertFalse(CONDITION, MESSAGE) throws an exception containing the string -% MESSAGE if CONDITION is not false. -% -% MESSAGE is optional. -% -% Examples -% -------- -% assertFalse(isreal(sqrt(-1))) -% -% assertFalse(isreal(sqrt(-1)), ... -% 'Expected isreal(sqrt(-1)) to be false.') -% -% See also assertTrue - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -if nargin < 2 - message = 'Asserted condition is not false.'; -end - -if ~isscalar(condition) || ~islogical(condition) - throwAsCaller(MException('assertFalse:invalidCondition', ... - 'CONDITION must be a scalar logical value.')); -end - -if condition - throwAsCaller(MException('assertFalse:trueCondition', '%s', message)); -end diff --git a/util/xunit/assertFilesEqual.m b/util/xunit/assertFilesEqual.m deleted file mode 100644 index d1cfc51..0000000 --- a/util/xunit/assertFilesEqual.m +++ /dev/null @@ -1,68 +0,0 @@ -function assertFilesEqual(filename1, filename2, user_message) -%assertFilesEqual Assert that files contain the same contents. -% assertFilesEqual(filename1, filename2) throws an exception if the two -% specified files do not contain the same contents. -% -% assertFilesEqual(filename1, filename2, message) prepends the specified -% message string to the assertion message. - -% Steven L. Eddins -% Copyright 2009-2010 The MathWorks, Inc. - -if nargin < 3 - user_message = ''; -end - -fid1 = fopen(filename1, 'r'); -if (fid1 < 0) - message = sprintf('%s\nCould not open file for reading: %s', ... - user_message, filename1); - throwAsCaller(MException('assertFilesEqual:readFailure', ... - '%s', message)); -else - c1 = onCleanup(@() fclose(fid1)); -end - -fid2 = fopen(filename2, 'r'); -if (fid2 < 0) - message = sprintf('%s\nCould not open file for reading: %s', ... - user_message, filename2); - throwAsCaller(MException('assertFilesEqual:readFailure', '%s', message)); -else - c2 = onCleanup(@() fclose(fid2)); -end - -block_size = 100000; -num_blocks = 0; -done = false; -while ~done - block_from_file1 = fread(fid1, block_size, '*uint8'); - block_from_file2 = fread(fid2, block_size, '*uint8'); - - if numel(block_from_file1) ~= numel(block_from_file2) - fseek(fid1, 0, 'eof'); - fseek(fid2, 0, 'eof'); - message = sprintf('The two files are not the same size. File "%s" has %d bytes and file "%s" has %d bytes', ... - filename1, ftell(fid1), filename2, ftell(fid2)); - if ~isempty(user_message) - message = sprintf('%s\n%s', user_message, message); - end - throwAsCaller(MException('assertFilesEqual:sizeMismatch', '%s', message)); - end - - if ~isequal(block_from_file1, block_from_file2) - first_difference_in_block = find(block_from_file1 ~= block_from_file2); - first_difference = num_blocks * block_size + first_difference_in_block; - - message = sprintf('Files are not equal. First difference is at byte %d, where file "%s" contains 0x%X and file "%s" contains 0x%X', ... - first_difference, filename1, block_from_file1(first_difference_in_block), ... - filename2, block_from_file2(first_difference_in_block)); - if ~isempty(user_message) - message = sprintf('%s\n%s', user_message, message); - end - throwAsCaller(MException('assertFilesEqual:valuesDiffer', '%s', message)); - end - - done = numel(block_from_file1) < block_size; - num_blocks = num_blocks + 1; -end \ No newline at end of file diff --git a/util/xunit/assertTrue.m b/util/xunit/assertTrue.m deleted file mode 100644 index 52787a6..0000000 --- a/util/xunit/assertTrue.m +++ /dev/null @@ -1,33 +0,0 @@ -function assertTrue(condition, message) -%assertTrue Assert that input condition is true -% assertTrue(CONDITION, MESSAGE) throws an exception containing the string -% MESSAGE if CONDITION is not true. -% -% MESSAGE is optional. -% -% Examples -% -------- -% % This call returns silently. -% assertTrue(rand < 1, 'Expected output of rand to be less than 1') -% -% % This call throws an error. -% assertTrue(sum(sum(magic(3))) == 0, ... -% 'Expected sum of elements of magic(3) to be 0') -% -% See also assertEqual, assertFalse - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -if nargin < 2 - message = 'Asserted condition is not true.'; -end - -if ~isscalar(condition) || ~islogical(condition) - throwAsCaller(MException('assertTrue:invalidCondition', ... - 'CONDITION must be a scalar logical value.')); -end - -if ~condition - throwAsCaller(MException('assertTrue:falseCondition', '%s', message)); -end diff --git a/util/xunit/assertVectorsAlmostEqual.m b/util/xunit/assertVectorsAlmostEqual.m deleted file mode 100644 index e4f1034..0000000 --- a/util/xunit/assertVectorsAlmostEqual.m +++ /dev/null @@ -1,59 +0,0 @@ -function assertVectorsAlmostEqual(varargin) -%assertVectorsAlmostEqual Assert floating-point vectors almost equal in norm sense. -% assertVectorsAlmostEqual(A, B, tol_type, tol, floor_tol) asserts that the -% vectors A and B are equal, in the L2-norm sense and within some tolerance. -% tol_type can be 'relative' or 'absolute'. tol and floor_tol are scalar -% tolerance values. -% -% If the tolerance type is 'relative', then the tolerance test used is: -% -% all( norm(A - B) <= tol * max(norm(A), norm(B)) + floor_tol ) -% -% If the tolerance type is 'absolute', then the tolerance test used is: -% -% all( norm(A - B) <= tol ) -% -% tol_type, tol, and floor_tol are all optional. The default value for -% tol_type is 'relative'. If both A and B are double, then the default value -% for tol and floor_tol is sqrt(eps). If either A or B is single, then the -% default value for tol and floor_tol is sqrt(eps('single')). -% -% If A or B is complex, then the tolerance test is applied independently to -% the real and imaginary parts. -% -% Any infinite or NaN element of A or B will cause an assertion failure. -% -% assertVectorsAlmostEqual(A, B, ..., msg) prepends the string msg to the -% assertion message if A and B fail the tolerance test. - -% Steven L. Eddins -% Copyright 2008-2010 The MathWorks, Inc. - -params = xunit.utils.parseFloatAssertInputs(varargin{:}); - -if ~isequal(size(params.A), size(params.B)) - message = xunit.utils.comparisonMessage(params.Message, ... - 'Inputs are not the same size.', ... - params.A, params.B); - throwAsCaller(MException('assertVectorsAlmostEqual:sizeMismatch', ... - '%s', message)); -end - -if ~(isfloat(params.A) && isfloat(params.B)) - message = xunit.utils.comparisonMessage(params.Message, ... - 'Inputs are not both floating-point.', ... - params.A, params.B); - throwAsCaller(MException('assertVectorsAlmostEqual:notFloat', ... - '%s', message)); -end - -if ~xunit.utils.compareFloats(params.A, params.B, 'vector', ... - params.ToleranceType, params.Tolerance, params.FloorTolerance) - - tolerance_message = sprintf('Inputs are not equal within %s vector tolerance: %g', ... - params.ToleranceType, params.Tolerance); - message = xunit.utils.comparisonMessage(params.Message, tolerance_message, ... - params.A, params.B); - throwAsCaller(MException('assertVectorsAlmostEqual:tolExceeded', ... - '%s', message)); -end diff --git a/util/xunit/info.xml b/util/xunit/info.xml deleted file mode 100644 index 046189b..0000000 --- a/util/xunit/info.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - -R2009a -MATLAB xUnit Test Framework -Other -$toolbox/matlab/icons/matlabicon.gif -../doc/ - - - - - -doc xunit -$toolbox/matlab/icons/book_mat.gif - - - - -web http://www.mathworks.com/matlabcentral/fileexchange/22846 -browser; -$toolbox/matlab/icons/webicon.gif - - - - - diff --git a/util/xunit/initTestSuite.m b/util/xunit/initTestSuite.m deleted file mode 100644 index 9af3f7f..0000000 --- a/util/xunit/initTestSuite.m +++ /dev/null @@ -1,58 +0,0 @@ -%findSubfunctionTests Utility script used for subfunction-based tests -% This file is a script that is called at the top of M-files containing -% subfunction-based tests. -% -% The top of a typical M-file using this script looks like this: -% -% function test_suite = testFeatureA -% -% findSubfunctionTests; -% -% IMPORTANT NOTE -% -------------- -% The output variable name for an M-file using this script must be test_suite. - -% Steven L. Eddins -% Copyright 2008-2009 The MathWorks, Inc. - -[ST,I] = dbstack('-completenames'); -caller_name = ST(I + 1).name; -caller_file = ST(I + 1).file; -subFcns = which('-subfun', caller_file); - -setup_fcn_name = subFcns(xunit.utils.isSetUpString(subFcns)); -if numel(setup_fcn_name) > 1 - error('findSubfunctionTests:tooManySetupFcns', ... - 'Found more than one setup subfunction.') -elseif isempty(setup_fcn_name) - setup_fcn = []; -else - setup_fcn = str2func(setup_fcn_name{1}); -end - -teardown_fcn_name = subFcns(xunit.utils.isTearDownString(subFcns)); -if numel(teardown_fcn_name) > 1 - error('findSubfunctionTests:tooManyTeardownFcns', ... - 'Found more than one teardown subfunction.') -elseif isempty(teardown_fcn_name) - teardown_fcn = []; -else - teardown_fcn = str2func(teardown_fcn_name{1}); -end - -test_fcns = cellfun(@str2func, subFcns(xunit.utils.isTestString(subFcns)), ... - 'UniformOutput', false); - -suite = TestSuite; -suite.Name = caller_name; -suite.Location = which(caller_file); -for k = 1:numel(test_fcns) - suite.add(FunctionHandleTestCase(test_fcns{k}, setup_fcn, teardown_fcn)); -end - -if nargout > 0 - test_suite = suite; -else - suite.run(); -end - diff --git a/util/xunit/runtests.m b/util/xunit/runtests.m deleted file mode 100644 index 74a2414..0000000 --- a/util/xunit/runtests.m +++ /dev/null @@ -1,160 +0,0 @@ -function out = runtests(varargin) -%runtests Run unit tests -% runtests runs all the test cases that can be found in the current directory -% and summarizes the results in the Command Window. -% -% Test cases can be found in the following places in the current directory: -% -% * An M-file function whose name starts or ends with "test" or -% "Test" and that returns no output arguments. -% -% * An M-file function whose name starts or ends with "test" or -% "Test" and that contains subfunction tests and uses the -% initTestSuite script to return a TestSuite object. -% -% * An M-file defining a subclass of TestCase. -% -% runtests(dirname) runs all the test cases found in the specified directory. -% -% runtests(packagename) runs all the test cases found in the specified -% package. (This option requires R2009a or later). -% -% runtests(mfilename) runs test cases found in the specified function or class -% name. The function or class needs to be in the current directory or on the -% MATLAB path. -% -% runtests('mfilename:testname') runs the specific test case named 'testname' -% found in the function or class 'name'. -% -% Multiple directories or file names can be specified by passing multiple -% names to runtests, as in runtests(name1, name2, ...) or -% runtests({name1, name2, ...}, ...) -% -% runtests(..., '-verbose') displays the name and result, result, and time -% taken for each test case to the Command Window. -% -% runtests(..., '-logfile', filename) directs the output of runtests to -% the specified log file instead of to the Command Window. -% -% out = runtests(...) returns a logical value that is true if all the -% tests passed. -% -% Examples -% -------- -% Find and run all the test cases in the current directory. -% -% runtests -% -% Find and run all the test cases in the current directory. Display more -% detailed information to the Command Window as the test cases are run. -% -% runtests -verbose -% -% Save verbose runtests output to a log file. -% -% runtests -verbose -logfile my_test_log.txt -% -% Find and run all the test cases contained in the M-file myfunc. -% -% runtests myfunc -% -% Find and run all the test cases contained in the TestCase subclass -% MyTestCase. -% -% runtests MyTestCase -% -% Run the test case named 'testFeature' contained in the M-file myfunc. -% -% runtests myfunc:testFeature -% -% Run all the tests in a specific directory. -% -% runtests c:\Work\MyProject\tests -% -% Run all the tests in two directories. -% -% runtests c:\Work\MyProject\tests c:\Work\Book\tests - -% Steven L. Eddins -% Copyright 2009-2010 The MathWorks, Inc. - -verbose = false; -logfile = ''; -if nargin < 1 - suite = TestSuite.fromPwd(); -else - [name_list, verbose, logfile] = getInputNames(varargin{:}); - if numel(name_list) == 0 - suite = TestSuite.fromPwd(); - elseif numel(name_list) == 1 - suite = TestSuite.fromName(name_list{1}); - else - suite = TestSuite(); - for k = 1:numel(name_list) - suite.add(TestSuite.fromName(name_list{k})); - end - end -end - -if isempty(suite.TestComponents) - error('xunit:runtests:noTestCasesFound', 'No test cases found.'); -end - -if isempty(logfile) - logfile_handle = 1; % File handle corresponding to Command Window -else - logfile_handle = fopen(logfile, 'w'); - if logfile_handle < 0 - error('xunit:runtests:FileOpenFailed', ... - 'Could not open "%s" for writing.', logfile); - else - cleanup = onCleanup(@() fclose(logfile_handle)); - end -end - -fprintf(logfile_handle, 'Test suite: %s\n', suite.Name); -if ~strcmp(suite.Name, suite.Location) - fprintf(logfile_handle, 'Test suite location: %s\n', suite.Location); -end -fprintf(logfile_handle, '%s\n\n', datestr(now)); - -if verbose - monitor = VerboseTestRunDisplay(logfile_handle); -else - monitor = TestRunDisplay(logfile_handle); -end -did_pass = suite.run(monitor); - -if nargout > 0 - out = did_pass; -end - -function [name_list, verbose, logfile] = getInputNames(varargin) -name_list = {}; -verbose = false; -logfile = ''; -k = 1; -while k <= numel(varargin) - arg = varargin{k}; - if iscell(arg) - name_list = [name_list; arg]; - elseif ~isempty(arg) && (arg(1) == '-') - if strcmp(arg, '-verbose') - verbose = true; - elseif strcmp(arg, '-logfile') - if k == numel(varargin) - error('xunit:runtests:MissingLogfile', ... - 'The option -logfile must be followed by a filename.'); - else - logfile = varargin{k+1}; - k = k + 1; - end - else - warning('runtests:unrecognizedOption', 'Unrecognized option: %s', arg); - end - else - name_list{end+1} = arg; - end - k = k + 1; -end - From 3fed6e014bfc975591dd13bd6fc96b178483c54d Mon Sep 17 00:00:00 2001 From: Jose Pablo Alberto Andreotti Date: Mon, 2 Dec 2013 18:00:02 -0300 Subject: [PATCH 2/6] After rebasing upstream/master. --- .travis.yml | 6 +- CNN/cnnavg.m | 15 --- CNN/cnnbp.m | 7 +- CNN/cnncopy.m | 18 ---- CNN/cnnnumgradcheck.m | 6 -- CNN/cnnsetup.m | 1 - CNN/cnntrain.m | 26 +++-- CNN/convadd.m | 8 -- CNN/convn_valid.m | 20 +--- CNN/convnfft.m | 221 --------------------------------------- CNN/custom_convn.m | 29 ----- CNN/eh.m | 5 - CNN/process_batch.m | 40 ------- DBN/rbmtrain.m | 2 +- data/generate_mfcc.m | 87 --------------- data/readhtk.m | 15 --- tests/test_example_CNN.m | 15 ++- 17 files changed, 37 insertions(+), 484 deletions(-) delete mode 100644 CNN/cnnavg.m delete mode 100644 CNN/cnncopy.m delete mode 100644 CNN/convadd.m delete mode 100644 CNN/convnfft.m delete mode 100644 CNN/custom_convn.m delete mode 100644 CNN/eh.m delete mode 100644 CNN/process_batch.m delete mode 100644 data/generate_mfcc.m delete mode 100644 data/readhtk.m diff --git a/.travis.yml b/.travis.yml index c88ffd8..45ed2a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,8 @@ before_script: - - sudo apt-get install octave - + - sudo apt-add-repository ppa:octave/stable --yes + - sudo apt-get update -y + - sudo apt-get install octave -y + - sudo apt-get install liboctave-dev -y script: - sh -c "octave tests/runalltests.m" diff --git a/CNN/cnnavg.m b/CNN/cnnavg.m deleted file mode 100644 index 96823bb..0000000 --- a/CNN/cnnavg.m +++ /dev/null @@ -1,15 +0,0 @@ -function avgnet = cnnavg(avgnet, net) - for l = 2 : numel(net.layers) - if strcmp(net.layers{l}.type, 'c') - for j = 1 : numel(net.layers{l}.a) - for ii = 1 : numel(net.layers{l - 1}.a) - avgnet.layers{l}.k{ii}{j} = (avgnet.layers{l}.k{ii}{j} + net.layers{l}.k{ii}{j})/2; - end - avgnet.layers{l}.b{j} = avgnet.layers{l}.b{j} + net.layers{l}.b{j}; - end - end - end - - avgnet.ffW = (avgnet.ffW + net.ffW)/2; - avgnet.ffb = (avgnet.ffb + net.ffb)/2 ; -end \ No newline at end of file diff --git a/CNN/cnnbp.m b/CNN/cnnbp.m index b0b563d..09028a2 100644 --- a/CNN/cnnbp.m +++ b/CNN/cnnbp.m @@ -41,7 +41,12 @@ if strcmp(net.layers{l}.type, 'c') for j = 1 : numel(net.layers{l}.a) for i = 1 : numel(net.layers{l - 1}.a) - net.layers{l}.dk{i}{j} = custom_convn(flipall(net.layers{l - 1}.a{i}), net.layers{l}.d{j}, 'valid') / size(net.layers{l}.d{j}, 3); + %ugly if, until convn() is fixed in Octave. + if(isOctave()) + net.layers{l}.dk{i}{j} = convn_valid(flipall(net.layers{l - 1}.a{i}), net.layers{l}.d{j}) / size(net.layers{l}.d{j}, 3); + else + net.layers{l}.dk{i}{j} = convn(flipall(net.layers{l - 1}.a{i}), net.layers{l}.d{j}, 'valid') / size(net.layers{l}.d{j}, 3); + end end net.layers{l}.db{j} = sum(net.layers{l}.d{j}(:)) / size(net.layers{l}.d{j}, 3); end diff --git a/CNN/cnncopy.m b/CNN/cnncopy.m deleted file mode 100644 index 3742afc..0000000 --- a/CNN/cnncopy.m +++ /dev/null @@ -1,18 +0,0 @@ -function cpnet = cnncopy(cpnet, net) - - - - for l = 2 : numel(net.layers) - if strcmp(net.layers{l}.type, 'c') - for j = 1 : numel(net.layers{l}.a) - for ii = 1 : numel(net.layers{l - 1}.a) - cpnet.layers{l}.k{ii}{j} = net.layers{l}.k{ii}{j}; - end - cpnet.layers{l}.b{j} = net.layers{l}.b{j}; - end - end - end - - cpnet.ffW = net.ffW; - cpnet.ffb = net.ffb; -end \ No newline at end of file diff --git a/CNN/cnnnumgradcheck.m b/CNN/cnnnumgradcheck.m index a06bec1..665262a 100644 --- a/CNN/cnnnumgradcheck.m +++ b/CNN/cnnnumgradcheck.m @@ -11,8 +11,6 @@ function cnnnumgradcheck(net, x, y) d = (net_p.L - net_m.L) / (2 * epsilon); e = abs(d - net.dffb(j)); if e > er - e - d / net.dffb(j) error('numerical gradient checking failed'); end end @@ -27,8 +25,6 @@ function cnnnumgradcheck(net, x, y) d = (net_p.L - net_m.L) / (2 * epsilon); e = abs(d - net.dffW(i, u)); if e > er - e - d / net.ffW(i, u) error('numerical gradient checking failed'); end end @@ -45,8 +41,6 @@ function cnnnumgradcheck(net, x, y) d = (net_p.L - net_m.L) / (2 * epsilon); e = abs(d - net.layers{l}.db{j}); if e > er - e - d / net.layers{l}.db{j} error('numerical gradient checking failed'); end for i = 1 : numel(net.layers{l - 1}.a) diff --git a/CNN/cnnsetup.m b/CNN/cnnsetup.m index b1f6079..6d6b002 100644 --- a/CNN/cnnsetup.m +++ b/CNN/cnnsetup.m @@ -1,5 +1,4 @@ function net = cnnsetup(net, x, y) - assert(exist('OCTAVE_VERSION')==0, 'CNNs does not work with Octave as there is a bug in the implementation of convolution in octave. See: http://savannah.gnu.org/bugs/?39314'); inputmaps = 1; mapsize = size(squeeze(x(:, :, 1))); diff --git a/CNN/cnntrain.m b/CNN/cnntrain.m index fe43f02..33fe40b 100644 --- a/CNN/cnntrain.m +++ b/CNN/cnntrain.m @@ -1,29 +1,27 @@ - function net = cnntrain(net, x, y, opts) m = size(x, 3); numbatches = m / opts.batchsize; if rem(numbatches, 1) ~= 0 error('numbatches not integer'); end - net.rL = []; for i = 1 : opts.numepochs disp(['epoch ' num2str(i) '/' num2str(opts.numepochs)]); tic; kk = randperm(m); - %how many processes? - numWorkers = 4 - pids = 0:numWorkers-1; - starts = pids * numbatches / numWorkers - - %process starts - turn = 0; + for l = 1 : numbatches + batch_x = x(:, :, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize)); + batch_y = y(:, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize)); - pararrayfun(numWorkers, - @(starts, pids)process_batch(x, y, kk, net, turn, starts, (numbatches/numWorkers), pids, numWorkers, opts), - starts, - pids, - "ErrorHandler" , @eh); + net = cnnff(net, batch_x); + net = cnnbp(net, batch_y); + net = cnnapplygrads(net, opts); + if isempty(net.rL) + net.rL(1) = net.L; + end + net.rL(end + 1) = 0.99 * net.rL(end) + 0.01 * net.L; + end toc; end + end diff --git a/CNN/convadd.m b/CNN/convadd.m deleted file mode 100644 index 8e6c47d..0000000 --- a/CNN/convadd.m +++ /dev/null @@ -1,8 +0,0 @@ - %a is the image, k the kernel, o the output, i is the index. -function result = convadd(a, k, m, pid, chunkSize) - init = pid*chunkSize + 1; - result = zeros(m, m); - for i=init:init+chunkSize -1 - result += conv2D(a(:,:, i), k(:,:, i)); - end -end diff --git a/CNN/convn_valid.m b/CNN/convn_valid.m index bf9b8e1..85447bf 100644 --- a/CNN/convn_valid.m +++ b/CNN/convn_valid.m @@ -2,22 +2,10 @@ %equivalent to convn(A,B, 'valid') function result = convn_valid(A, B) - m = size(A, 1) - size(B, 1) + 1; - numWorkers = 2; - - function retcode = eh(error) - a = error - retcode = zeros(25, 1); + result = zeros(m, m); + B = flipdim(B,3); + for j=1:size(A, 3) + result += conv2(A(:,:,j),B(:,:,j), 'valid'); end - - %each worker will write its output to specific part of the output - chunkSize = size(A,3)/numWorkers; - result = pararrayfun(numWorkers, @(i)convadd(A, B, m, i, chunkSize), 0:numWorkers-1, "ErrorHandler" , @eh); - - for j=m:numWorkers*m:m - result(:,1:m) += result(:,j+1:j+m); - end - - result = result(1:m,1:m); end \ No newline at end of file diff --git a/CNN/convnfft.m b/CNN/convnfft.m deleted file mode 100644 index 98b5f1d..0000000 --- a/CNN/convnfft.m +++ /dev/null @@ -1,221 +0,0 @@ -function A = convnfft(A, B, shape, dims, options) -% CONVNFFT FFT-BASED N-dimensional convolution. -% C = CONVNFFT(A, B) performs the N-dimensional convolution of -% matrices A and B. If nak = size(A,k) and nbk = size(B,k), then -% size(C,k) = max([nak+nbk-1,nak,nbk]); -% -% C = CONVNFFT(A, B, SHAPE) controls the size of the answer C: -% 'full' - (default) returns the full N-D convolution -% 'same' - returns the central part of the convolution that -% is the same size as A. -% 'valid' - returns only the part of the result that can be -% computed without assuming zero-padded arrays. -% size(C,k) = max([nak-max(0,nbk-1)],0). -% -% C = CONVNFFT(..., SHAPE, DIMS) with DIMS is vector of dimensions where -% the convolution will be carried out. By default DIMS is -% [1:max(ndims(A),ndims(B))] (all dimensions). A and B must have the -% same lengths on other dimensions. -% C = CONVNFFT(..., SHAPE, DIMS, GPU) -% GPU is boolean flag, see next -% -% C = CONVNFFT(..., SHAPE, DIMS, OPTIONS) -% -% OPTIONS is structure with following optional fields -% - 'GPU', boolean. If GPU is TRUE Jacket/GPU FFT engine will be used -% By default GPU is FALSE. -% - 'Power2Flag', boolean. If it is TRUE, use FFT with length rounded -% to the next power-two. It is faster but requires more memory. -% Default value is TRUE. -% -% Class support for inputs A,B: -% float: double, single -% -% METHOD: CONVNFFT uses Fourier transform (FT) convolution theorem, i.e. -% FT of the convolution is equal to the product of the FTs of the -% input functions. -% In 1-D, the complexity is O((na+nb)*log(na+nb)), where na/nb are -% respectively the lengths of A and B. -% -% Usage recommendation: -% In 1D, this function is faster than CONV for nA, nB > 1000. -% In 2D, this function is faster than CONV2 for nA, nB > 20. -% In 3D, this function is faster than CONVN for nA, nB > 5. -% -% See also conv, conv2, convn. -% -% Author: Bruno Luong -% History: -% Original: 21-Jun-2009 -% 23-Jun-2009: correct bug when ndims(A) return zeros - return -end - -power2flag = getoption(options, 'Power2Flag', true); -if power2flag - % faster FFT if the dimension is power of 2 - lfftfun = @(l) 2^nextpow2(l); -else - % slower, but smaller temporary arrays - lfftfun = @(l) l; -end - -if GPU % GPU/Jacket FFT - if strcmp(classA,'single') - A = gsingle(A); - else - A = gdouble(A); - end - if strcmp(classB,'single') - B = gsingle(B); - else - B = gdouble(B); - end - % Do the FFT - subs(1:ndims(A)) = {':'}; - for dim=dims - m = size(A,dim); - n = size(B,dim); - % compute the FFT length - l = lfftfun(m+n-1); - % We need to swap dimensions because GPU FFT works along the - % first dimension - if dim~=1 % do the work when only required - swap = 1:nd; - swap([1 dim]) = swap([dim 1]); - A = permute(A, swap); - B = permute(B, swap); - end - A = fft(A,l); - B = fft(B,l); - subs{dim} = ifun(m,n); - end -else % Matlab FFT - % Do the FFT - subs(1:ndims(A)) = {':'}; - for dim=dims - m = size(A,dim); - n = size(B,dim); - % compute the FFT length - l = lfftfun(m+n-1); - A = fft(A,l,dim); - B = fft(B,l,dim); - subs{dim} = ifun(m,n); - end -end - -if GPU - A = A.*B; - clear B -else - % inplace product to save 1/3 of the memory - % Modified by Alberto Andreotti(albertoandreotti@gmail.com) - %inplaceprod(A,B); - A(:) = A(:).*B(:); -end - -% Back to the non-Fourier space -if GPU % GPU/Jacket FFT - for dim=dims(end:-1:1) % reverse loop - A = ifft(A,[]); - % Swap back the dimensions - if dim~=1 % do the work when only required - swap = 1:nd; - swap([1 dim]) = swap([dim 1]); - A = permute(A, swap); - end - end -else % Matlab IFFT - for dim=dims - A = ifft(A,[],dim); - end -end - -% Truncate the results -if ABreal - % Make sure the result is real - A = real(A(subs{:})); -else - A = A(subs{:}); -end - -% GPU/Jacket -if GPU - % Cast the type back - if strcmp(class(A),'gsingle') - A = single(A); - else - A = double(A); - end -end - -end % convnfft - - -%% Get defaut option -function value = getoption(options, name, defaultvalue) -% function value = getoption(options, name, defaultvalue) - value = defaultvalue; - fields = fieldnames(options); - found = strcmpi(name,fields); - if any(found) - i = find(found,1,'first'); - if ~isempty(options.(fields{i})) - value = options.(fields{i}); - end - end -end diff --git a/CNN/custom_convn.m b/CNN/custom_convn.m deleted file mode 100644 index 76d978d..0000000 --- a/CNN/custom_convn.m +++ /dev/null @@ -1,29 +0,0 @@ -% This function is used to choose between different implementations of the convn function -% according to the platform. -% This is mainly useful for overcoming an Octave's bug in convn(), https://savannah.gnu.org/bugs/?39314 -% parameters: x is the chunk of the image/samples, k is the kernel. - -function result = custom_convn(x, k, convmode) - - %FFT works with batchsize>50, but still really slow, about 10000 seconds. It should produce an error near 0.18. - %this convnfft is taken from http://www.mathworks.com/matlabcentral/fileexchange/24504-fft-based-convolution. - if exist('convmode') && strcmp(convmode, 'fft') - result = convnfft(x,k, 'valid'); - return - end - - %the 'valid' version of convolution has problems in Octave, use 'same' instead. - if isOctave() - %Alternative to convnftt, use for small batch size ~ 5, will give 2676.56 seconds, otherwise it will explode(too long running time). - start = size(x,1) - size(k,1); - fin = 2*start; - %note: if x and k have not the same size in the third dimension, middle could be a range. - middle = floor(size(x,3)/2) + 1; - result = convn (x, k, "same")(start:fin, start:fin, middle); - else - %we're running matlab - result = convn(x, k, 'valid'); - end - -end - diff --git a/CNN/eh.m b/CNN/eh.m deleted file mode 100644 index faea508..0000000 --- a/CNN/eh.m +++ /dev/null @@ -1,5 +0,0 @@ -%here goes what to put in the output when the function fails. -function retcode = eh(err) - a = err - retcode = zeros(26,1).+255; -end \ No newline at end of file diff --git a/CNN/process_batch.m b/CNN/process_batch.m deleted file mode 100644 index 62318b3..0000000 --- a/CNN/process_batch.m +++ /dev/null @@ -1,40 +0,0 @@ -%l is the batch number -function process_batch(x, y, kk, global_net, turn, start, numbatches, pid, numWorkers, opts) - net.p = 0; - net.rL = []; - inited = 0; - - net.layers = { - struct('type', 'i') %input layer - struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer - struct('type', 's', 'scale', 2) %sub sampling layer - struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer - struct('type', 's', 'scale', 2) %subsampling layer - }; - - for l = start + 1 : start + numbatches - 3 - %batch_x = x(:, :, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize)); - %batch_y = y(:, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize)); - - net = cnnff(net, x(:, :, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize))); - net = cnnbp(net, y(:, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize))); - net = cnnapplygrads(net, opts); - - if inited == 0 - net = cnncopy(net, global_net); - inited = 1; - end - - if isempty(net.rL) - net.rL(1) = net.L; - end - net.rL(end + 1) = 0.99 * net.rL(end) + 0.01 * net.L; - - %If we cannot update our results keep going to the next batch - if turn == pid - global_net = cnnavg(global_net, net); - net = cnncopy(net, global_net); - turn = mod((turn + 1), numWorkers) - end - end -end \ No newline at end of file diff --git a/DBN/rbmtrain.m b/DBN/rbmtrain.m index 77e6ad3..39aca0b 100644 --- a/DBN/rbmtrain.m +++ b/DBN/rbmtrain.m @@ -1,6 +1,6 @@ function rbm = rbmtrain(rbm, x, opts) assert(isfloat(x), 'x must be a float'); - assert(all(x>=0) && all(x<=1), "all data in x must be in [0:1]"); + assert(all(x(:)>=0) && all(x(:)<=1), 'all data in x must be in [0:1]'); m = size(x, 1); numbatches = m / opts.batchsize; diff --git a/data/generate_mfcc.m b/data/generate_mfcc.m deleted file mode 100644 index 5e2e052..0000000 --- a/data/generate_mfcc.m +++ /dev/null @@ -1,87 +0,0 @@ -%this script will crawl the MFCC data from VoxForge to generate the en_de_it.mat file -%containing MFCCs for the three languages english, deutsch and italian. -%this file assumes VoiceBox is in your Octave/Matlab's path. - -en_endpoint = 'http://www.repository.voxforge1.org/downloads/SpeechCorpus/Trunk/Audio/MFCC/8kHz_16bit/MFCC_0_D/'; -de_endpoint = 'http://www.repository.voxforge1.org/downloads/de/Trunk/Audio/MFCC/8kHz_16bit/MFCC_0_D/'; -it_endpoint = 'http://www.repository.voxforge1.org/downloads/it/Trunk/Audio/MFCC/8kHz_16bit/MFCC_0_D/'; -<<<<<<< HEAD -endpoint = it_endpoint; -limit = 1500; -======= -endpoint = en_endpoint; ->>>>>>> c4cc2e620e82e17e56aa44a67402c178ed13742d - -flist = urlread(endpoint); - -[s,e] = regexp(flist, ">([a-zA-Z0-9]*-[a-zA-Z0-9]*)+\.tgz<"); -%truncate the amount of data to be crawled -<<<<<<< HEAD -s = s(1:min(limit, size(s,2))); -e = e(1:min(limit, size(s,2))); - -confirm_recursive_rmdir(0) -filename = "it.mat"; -======= -s = s(1:1500); -e = e(1:1500); - -confirm_recursive_rmdir(0) -filename = 'en_de_it.mat'; ->>>>>>> c4cc2e620e82e17e56aa44a67402c178ed13742d - -function data = fetch_data(flist, endpoint, anfang, ende, id) - %print(int2str(id)); - %at each step fetch a file from the corpus - currfile = flist(anfang + 1: ende - 1); - currdir = strcat("temp", int2str(id)); - - mkdir(currdir);cd(currdir); - data = zeros(26, 1); - status = urlwrite(strcat(endpoint, currfile), currfile); - - read_size = 0; - %Unzip the mfc files to temp dir and add them to the dataset. - %TODO: only working in Linux?. - untar(currfile); cd(currfile(1:end-4)); cd mfc; - mfcs = ls("*.mfc"); - for j=1:size(mfcs,1) - [d,fp,dt,tc,t]=readhtk(strtrim(mfcs(j, :))); - %check if this file contains mfccs. - if dt!=6 - continue - else - %read_size = read_size + size(d, 1); - data = [data, d']; - end - end - cd ../../.. - rmdir(currdir, "s"); -end -<<<<<<< HEAD - -======= ->>>>>>> c4cc2e620e82e17e56aa44a67402c178ed13742d -%here goes what to put in the output when the function fails. -function retcode = eh(error) - a = error - retcode = zeros(26,1).+255; -end - - -mfccs = pararrayfun(numWorkers = 30, -<<<<<<< HEAD - @(anfang, ende, id)fetch_data(flist, endpoint, anfang, ende, id), %currying with anonym funct - s, e, 1:size(s,2), %parameters for the function - "ErrorHandler" , @eh); - -read_size = size(mfccs) -save("-mat4-binary", filename, "mfccs"); -======= - @(anfang, ende, id)fetch_data(flist, endpoint, anfang, ende, id), - s, e, 1:size(s,2), - "ErrorHandler" , @eh); - -read_size = size(mfccs) -save("-mat4-binary" ,filename, mfccs); ->>>>>>> c4cc2e620e82e17e56aa44a67402c178ed13742d diff --git a/data/readhtk.m b/data/readhtk.m deleted file mode 100644 index b758d4d..0000000 --- a/data/readhtk.m +++ /dev/null @@ -1,15 +0,0 @@ -function [d,fp,dt,tc,t]=readhtk(file) -% READHTK routine is part of the VOICEBOX: -% a MATLAB toolbox for speech processing -% by Mike Brookes. It has not been included -% here due to licensing issues. Visit: -% http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html -% to find out more about the VOICEBOX toolbox. -% Please remember to remove this file, -% once you install the VOICEBOX toolbox. - - -error( sprintf('To use this routine you will have to download \nand install the VOICEBOX toolbox from: \nhttp://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html\nPlease remember to remove the placeholder file once you install the VOICEBOX toolbox.') ); - - -% EOF diff --git a/tests/test_example_CNN.m b/tests/test_example_CNN.m index 376e968..6a41380 100644 --- a/tests/test_example_CNN.m +++ b/tests/test_example_CNN.m @@ -11,6 +11,7 @@ %With 100 epochs you'll get around 1.2% error <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD if !isOctave() rng(0) end @@ -21,6 +22,11 @@ ======= rand('state',0) >>>>>>> 202808a737e3904d01e0b4e6fca82e0d5f51963c +======= + +rand('state',0) + +>>>>>>> upstream/master cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer @@ -31,15 +37,14 @@ opts.alpha = 1; -opts.batchsize = 250; -opts.numepochs = 1; +opts.batchsize = 200; +opts.numepochs = 7; cnn = cnnsetup(cnn, train_x, train_y); cnn = cnntrain(cnn, train_x, train_y, opts); [er, bad] = cnntest(cnn, test_x, test_y); -er + %plot mean squared error -%figure; plot(cnn.rL); -er +figure; plot(cnn.rL); assert(er<0.12, 'Too big error'); From 5d4361083c70f4dd547bcd55db2ac9f94ca72b58 Mon Sep 17 00:00:00 2001 From: Jose Pablo Alberto Andreotti Date: Mon, 2 Dec 2013 20:32:35 -0300 Subject: [PATCH 3/6] Changes in dimensions so TDNN can be built. --- CNN/cnnbp.m | 4 +++- CNN/cnnff.m | 7 +++++-- CNN/cnnsetup.m | 2 +- ...st_cnn_gradients_are_numerically_correct.m | 4 ++-- tests/test_example_CNN.m | 20 ++----------------- 5 files changed, 13 insertions(+), 24 deletions(-) diff --git a/CNN/cnnbp.m b/CNN/cnnbp.m index 09028a2..c9cd86c 100644 --- a/CNN/cnnbp.m +++ b/CNN/cnnbp.m @@ -23,7 +23,9 @@ for l = (n - 1) : -1 : 1 if strcmp(net.layers{l}.type, 'c') for j = 1 : numel(net.layers{l}.a) - net.layers{l}.d{j} = net.layers{l}.a{j} .* (1 - net.layers{l}.a{j}) .* (expand(net.layers{l + 1}.d{j}, [net.layers{l + 1}.scale net.layers{l + 1}.scale 1]) / net.layers{l + 1}.scale ^ 2); + xscale = net.layers{l + 1}.xscale; + yscale = net.layers{l + 1}.yscale; + net.layers{l}.d{j} = net.layers{l}.a{j} .* (1 - net.layers{l}.a{j}) .* (expand(net.layers{l + 1}.d{j}, [xscale yscale 1]) / (xscale*yscale)); end elseif strcmp(net.layers{l}.type, 's') for i = 1 : numel(net.layers{l}.a) diff --git a/CNN/cnnff.m b/CNN/cnnff.m index b9b6bc5..82de533 100644 --- a/CNN/cnnff.m +++ b/CNN/cnnff.m @@ -21,8 +21,11 @@ elseif strcmp(net.layers{l}.type, 's') % downsample for j = 1 : inputmaps - z = convn(net.layers{l - 1}.a{j}, ones(net.layers{l}.scale) / (net.layers{l}.scale ^ 2), 'valid'); % !! replace with variable - net.layers{l}.a{j} = z(1 : net.layers{l}.scale : end, 1 : net.layers{l}.scale : end, :); + xscale = net.layers{l}.xscale; + yscale = net.layers{l}.yscale; + + z = convn(net.layers{l - 1}.a{j}, ones(xscale, yscale) / (xscale*yscale), 'valid'); % !! replace with variable + net.layers{l}.a{j} = z(1 : xscale : end, 1 : yscale : end, :); end end end diff --git a/CNN/cnnsetup.m b/CNN/cnnsetup.m index 6d6b002..f3841fc 100644 --- a/CNN/cnnsetup.m +++ b/CNN/cnnsetup.m @@ -4,7 +4,7 @@ for l = 1 : numel(net.layers) % layer if strcmp(net.layers{l}.type, 's') - mapsize = mapsize / net.layers{l}.scale; + mapsize = [mapsize(1)/net.layers{l}.xscale, mapsize(2)/net.layers{l}.yscale]; assert(all(floor(mapsize)==mapsize), ['Layer ' num2str(l) ' size must be integer. Actual: ' num2str(mapsize)]); for j = 1 : inputmaps net.layers{l}.b{j} = 0; diff --git a/tests/test_cnn_gradients_are_numerically_correct.m b/tests/test_cnn_gradients_are_numerically_correct.m index 2391ae1..c5af4eb 100644 --- a/tests/test_cnn_gradients_are_numerically_correct.m +++ b/tests/test_cnn_gradients_are_numerically_correct.m @@ -4,9 +4,9 @@ cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 2, 'kernelsize', 5) %convolution layer - struct('type', 's', 'scale', 2) %sub sampling layer + struct('type', 's', 'xscale', 2, 'yscale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 2, 'kernelsize', 5) %convolution layer - struct('type', 's', 'scale', 2) %subsampling layer + struct('type', 's', 'xscale', 2, 'yscale', 2) %subsampling layer }; cnn = cnnsetup(cnn, batch_x, batch_y); diff --git a/tests/test_example_CNN.m b/tests/test_example_CNN.m index 6a41380..8183ddd 100644 --- a/tests/test_example_CNN.m +++ b/tests/test_example_CNN.m @@ -9,33 +9,17 @@ %% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% error -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -if !isOctave() -rng(0) -end - -======= -rand('state',0) ->>>>>>> upstream/master -======= -rand('state',0) ->>>>>>> 202808a737e3904d01e0b4e6fca82e0d5f51963c -======= rand('state',0) ->>>>>>> upstream/master cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer - struct('type', 's', 'scale', 2) %sub sampling layer + struct('type', 's', 'xscale', 2, 'yscale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer - struct('type', 's', 'scale', 2) %subsampling layer + struct('type', 's', 'xscale', 2, 'yscale', 2) %subsampling layer }; - opts.alpha = 1; opts.batchsize = 200; opts.numepochs = 7; From 9879c3bdb7b7ddf12f6effd237557d57f06e42b5 Mon Sep 17 00:00:00 2001 From: Jose Pablo Alberto Andreotti Date: Mon, 2 Dec 2013 20:55:08 -0300 Subject: [PATCH 4/6] Changed deploy script to please CI system. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 45ed2a2..569a873 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ before_script: - sudo apt-add-repository ppa:octave/stable --yes - sudo apt-get update -y - - sudo apt-get install octave -y + - sudo apt-get install octave --force-yes - sudo apt-get install liboctave-dev -y script: - sh -c "octave tests/runalltests.m" From 13abd70c5e0b39f3b81fcb49fad7e80f5396e089 Mon Sep 17 00:00:00 2001 From: Jose Pablo Alberto Andreotti Date: Tue, 3 Dec 2013 10:55:10 -0300 Subject: [PATCH 5/6] Small change in CNN. Moved the averaging filter definition from cnnff to cnnsetup. Now it is computed only once, during the net setup. --- CNN/cnnff.m | 7 ++----- CNN/cnnsetup.m | 7 +++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CNN/cnnff.m b/CNN/cnnff.m index 82de533..1db260d 100644 --- a/CNN/cnnff.m +++ b/CNN/cnnff.m @@ -21,11 +21,8 @@ elseif strcmp(net.layers{l}.type, 's') % downsample for j = 1 : inputmaps - xscale = net.layers{l}.xscale; - yscale = net.layers{l}.yscale; - - z = convn(net.layers{l - 1}.a{j}, ones(xscale, yscale) / (xscale*yscale), 'valid'); % !! replace with variable - net.layers{l}.a{j} = z(1 : xscale : end, 1 : yscale : end, :); + z = convn(net.layers{l - 1}.a{j}, net.layers{l}.meanFilter, 'valid'); + net.layers{l}.a{j} = z(1 : net.layers{l}.xscale : end, 1 : net.layers{l}.yscale : end, :); end end end diff --git a/CNN/cnnsetup.m b/CNN/cnnsetup.m index f3841fc..2169653 100644 --- a/CNN/cnnsetup.m +++ b/CNN/cnnsetup.m @@ -1,14 +1,17 @@ function net = cnnsetup(net, x, y) inputmaps = 1; mapsize = size(squeeze(x(:, :, 1))); - - for l = 1 : numel(net.layers) % layer + + for l = 1 : numel(net.layers) % layer if strcmp(net.layers{l}.type, 's') mapsize = [mapsize(1)/net.layers{l}.xscale, mapsize(2)/net.layers{l}.yscale]; assert(all(floor(mapsize)==mapsize), ['Layer ' num2str(l) ' size must be integer. Actual: ' num2str(mapsize)]); for j = 1 : inputmaps net.layers{l}.b{j} = 0; end + %these are the subsampling filters for each layer + net.layers{l}.meanFilter = ones(net.layers{l}.xscale, net.layers{l}.yscale) / (net.layers{l}.xscale*net.layers{l}.yscale); + end if strcmp(net.layers{l}.type, 'c') mapsize = mapsize - net.layers{l}.kernelsize + 1; From 7e5d7ce1ff161b06a2e027475c3a6b46f20d66a3 Mon Sep 17 00:00:00 2001 From: Jose Pablo Alberto Andreotti Date: Sat, 7 Dec 2013 00:19:18 -0300 Subject: [PATCH 6/6] Work in progress for nonsquared kernels. --- ...test_cnn_gradients_are_numerically_correct.m | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_cnn_gradients_are_numerically_correct.m b/tests/test_cnn_gradients_are_numerically_correct.m index c5af4eb..4cb06f9 100644 --- a/tests/test_cnn_gradients_are_numerically_correct.m +++ b/tests/test_cnn_gradients_are_numerically_correct.m @@ -1,4 +1,5 @@ function test_cnn_gradients_are_numerically_correct +%squared average kernels batch_x = rand(28,28,5); batch_y = rand(10,5); cnn.layers = { @@ -10,6 +11,22 @@ }; cnn = cnnsetup(cnn, batch_x, batch_y); +cnn = cnnff(cnn, batch_x); +cnn = cnnbp(cnn, batch_y); +cnnnumgradcheck(cnn, batch_x, batch_y); + +%non squared average kernels +batch_x = rand(28,600,5); +batch_y = rand(10,5); +cnn.layers = { + struct('type', 'i') %input layer + struct('type', 'c', 'outputmaps', 2, 'kernelsize', 5) %convolution layer + struct('type', 's', 'xscale', 2, 'yscale', 2) %sub sampling layer + struct('type', 'c', 'outputmaps', 2, 'kernelsize', 5) %convolution layer + struct('type', 's', 'xscale', 2, 'yscale', 2) %subsampling layer +}; +cnn = cnnsetup(cnn, batch_x, batch_y); + cnn = cnnff(cnn, batch_x); cnn = cnnbp(cnn, batch_y); cnnnumgradcheck(cnn, batch_x, batch_y); \ No newline at end of file