function rbm = rbmtrain(rbm, x, opts)
%assert断言函数,满足则返回值为1,继续执行接下来的程序
%不满足返回值为0则终止执行程序,将引号之中的提示输出
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;%这里当为104*4/13时值为8
assert(rem(numbatches, 1) == 0, 'numbatches not integer');
for i = 1 : opts.numepochs
kk = randperm(m);
err = 0;
for l = 1 : numbatches%这里是对比散度算法,用于更新参数。CD_K算法选的K值是1
batch = x(kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize), :);
v1 = batch;%13*4
h1 = sigmrnd(repmat(rbm.c', opts.batchsize, 1) + v1 * rbm.W');%输出值为0/1但是这里的输出太随机了一点,可以设置变化
%size(sigmrnd(repmat(rbm.c', opts.batchsize, 1) + v1 * rbm.W'))大小为8个13*100
%size(v1 * rbm.W')/13*100
%size(repmat(rbm.c', opts.batchsize, 1))
%size(repmat(rbm.c', opts.batchsize, 1)+v1 * rbm.W')
%这里面一次性把所有的参数初始化,没有将其通过循环在大的程序里面跑是没问题的,这里你要仔细学习人家这种编程思想,非常有益处
v2 = sigmrnd(repmat(rbm.b', opts.batchsize, 1) + h1 * rbm.W);
h2 = sigm(repmat(rbm.c', opts.batchsize, 1) + v2 * rbm.W');
%v2以及h2都是反推一下,即这里面的RBM微调就在这里
c1 = h1' * v1;
c2 = h2' * v2;
rbm.vW = rbm.momentum * rbm.vW + rbm.alpha * (c1 - c2) / opts.batchsize;%这里momentum(动量调整梯度设置为0.6了,要看清楚意义之后调一下)
rbm.vb = rbm.momentum * rbm.vb + rbm.alpha * sum(v1 - v2)' / opts.batchsize;
rbm.vc = rbm.momentum * rbm.vc + rbm.alpha * sum(h1 - h2)' / opts.batchsize;
rbm.W = rbm.W + rbm.vW;
rbm.b = rbm.b + rbm.vb;
rbm.c = rbm.c + rbm.vc;
err = err + sum(sum((v1 - v2) .^ 2)) / opts.batchsize;%编程的时候记得编写每一步的时候,都要知道结果,这样才方便我们验证
%因为有8个样本所以这里是八次计算,8个矩阵
end
disp(['epoch ' num2str(i) '/' num2str(opts.numepochs) '. Average reconstruction error is: ' num2str(err / numbatches)]);
%这里的逻辑是这样的,在每一次训练(numpoches)之中按照每个样本抽取batchsizes个个体,总共抽取numbatches个随机样本
end
end