Unsupervised Feature Learning and Deep Learning(UFLDL) Exercise 代码实现

最近开始了解深度学习的东西,看到国内研究者翻译的斯坦福大学的深度学习的历程,觉得很不错,就按照学习例程学习,一步一步完成后面的练习。这个练习安排的很合理,得按顺序完成,跳跃着做可能会遇到一定的麻烦。我在完成中也遇到不少的麻烦,不过还是慢慢克服了,越往后程序对计算机的配置要求越高,需要的内存也越大。下面是我完成这些例程中一些关键性的代码,觉得有用的可以参考一下,建议大家先自己动手写,如果实在是遇到困难了,可以参考一下我写的代码,由于本人编程能力也很一般,代码优化做得也很差,只供参考而已。


Exercise1: Sparase AutoEncoder

这个练习比较关键,基本上后面许多练习都依赖于这个练习的代码,所以首先得完成好这个练习。这个练习需要补充3个地方的代码。我这里只列出其中最关键的一个地方的代码,也就是sparseAutoencoderCost.m这个文件。
函数的目的是首先代价的计算以及梯度的计算,具体的实现如下:
A1 = data;
Y = data;
z2 = W1 * data + repmat(b1,1,m);
A2 = sigmoid(z2);
z3 = W2 * A2 + repmat(b2,1,m);
A3 = sigmoid(z3);

rho_hat = mean(A2,2); % 隐层每个神经元的平均激活度 hiddenSize*1

%backpropagation
for i = 1:m             
    
    a1 = A1(:,i);
    
    a2 = A2(:,i);
    
    a3 = A3(:,i);
    
    y = Y(:,i);                 % 原始输入向量
    
    cost = cost + 1/2 * norm(y - a3, 2)^2;   % 计算代价
    
    delta_3 = -(y - a3) .* (a3 .* (1 - a3));
    
    delta_2 = (W2'* delta_3 + beta *(-sparsityParam ./rho_hat + (1 - sparsityParam) ./(1 - rho_hat))) .* (a2 .* (1 - a2));
    
    W1grad = W1grad + delta_2 * a1';
    b1grad = b1grad + delta_2;
    W2grad = W2grad + delta_3 * a2';
    b2grad = b2grad + delta_3;
end
% 计算梯度
W1grad = 1/m * W1grad + lambda * W1;
W2grad = 1/m * W2grad + lambda * W2;
b1grad = 1/m * b1grad;
b2grad = 1/m * b2grad;


%计算KL
KL = 0;
for i = 1:hiddenSize
    KL = KL + sparsityParam * log(sparsityParam/rho_hat(i)) + (1 - sparsityParam) * log((1 - sparsityParam)/(1 - rho_hat(i)));
end

%计算代价
cost = 1/m * cost + lambda/2 * (sum(sum(W1.^2)) + sum(sum(W2.^2))) + beta * KL;</span>

注意:自己实现的时候一定要按照练习提示一步一步来,基本上可以搞定的,还有,我这个实现其实不是最开始的代码,这里面参杂了一部分练习2的代码,不过练习2基本上是完全优化了上面的代码,去掉了所有影响运行效率的for循环,但是带来的问题是程序的内存开销也相应增大了很多,所以这点得注意,不然会报out of memory的错误。


Exercise2:Vectorization

这个练习我个人觉得很重要,它交给我们如何将for循环尽量改写为向量或矩阵运算的方式,对程序运行速度有大幅的提升。这里的代码是对Exercise1的重新实现:
z2 = W1 * data + repmat(b1,1,m);
a2 = sigmoid(z2);
z3 = W2 * a2 + repmat(b2,1,m);
a3 = sigmoid(z3);

rho_hat = mean(a2,2); % 隐层每个神经元的平均激活度 hiddenSize*1
a1 = data;
y = data;

cost = 1/2*sum(sum((y - a3).^2));
delta_3 = -(y - a3) .* (a3 .* (1 - a3));
sparsity_data = (-sparsityParam ./rho_hat + (1 - sparsityParam) ./(1 - rho_hat));
delta_2 = (W2'* delta_3 + beta * repmat(sparsity_data,1,m)) .* (a2 .* (1 - a2));
W1grad = delta_2 * a1';
b1grad = sum(delta_2,2);
W2grad = delta_3 * a2';
b2grad = sum(delta_3,2);

W1grad = 1/m * W1grad + lambda * W1;
W2grad = 1/m * W2grad + lambda * W2;
b1grad = 1/m * b1grad;
b2grad = 1/m * b2grad;

% 计算KL
KL = sparsityParam * log(sparsityParam./rho_hat) + (1 - sparsityParam) * log((1 - sparsityParam)./(1 - rho_hat));
KL = sum(KL);

cost = 1/m * cost + lambda/2 * (sum(sum(W1.^2)) + sum(sum(W2.^2))) + beta * KL;

可以看到,没有使用for循环,同样实现了上述的功能。

Exercise3:PCA and Whitening

这个例子和上面的关系不大,其实也不是很难,对PCA有所了解的话实现上该练习完全不在话下。这里面有点需要注意的是对2D图像进行PCA压缩重构的时候,需要用到U和V,而不是只用U就可以,大家可以简单的检查一下矩阵的维度就很容易发现这点。所以下面就只列出重构图像的代码:
k = 0; % Set k accordingly
lambda = 0;
for i = 1:size(x,1)
    lambda = lambda + S(i,i);
    if lambda/trace(S) >= 0.96
        k = i;
        break;
    end
end
xHat = U(:,1:k) * V(:,1:k)' * x;

Exercise4:Softmax Regression

softmax 回归是Logistic 回归的推广,也是机器学习中常用的分类器。这个实现起来不是很难,但是我们刚刚完成了Exercise2,就得用向量话的方式实现,活学活用嘛,这样也可以逐步锻炼自己的编程习惯。
x = data;
k = numClasses;
m = numCases;
out = exp(theta * x);
S = sum(exp(theta * x),1);

thetagrad = (groundTruth - out ./ repmat(S,k,1)) * x';
thetagrad = -1/m * thetagrad + lambda * theta;

cost = sum(sum(groundTruth .* log(out./repmat(S,k,1))));
cost = -1/m * cost + lambda/2 * sum(sum(theta.^2));

大家看到,是不是和简洁,而且速度很快。所以要多培养哦!

Exercise5:Self-Taught Learning

这个练习基本上是对前面练习结果的一个重用,没什么难度,所以说不能跳着做,得按顺序一步步完成比较好。

Exercise6:Implement Deep Learning Networks for Digital Classification

这个练习可以算的上是自己的第一个真正意义上的深度学习程序,采用了两个自动编码器隐层和一个softmax预测层,其中难点在于实现有监督的调优过程。下面是stackedAECost.m的实现。
k = numClasses;

W1 = stack{1}.w;
b1 = stack{1}.b;
W2 = stack{2}.w;
b2 = stack{2}.b;

output_1 = sigmoid(W1 * data + repmat(b1,1,M));     % 计算第一隐层特征输出
output_2 = sigmoid(W2 * output_1 + repmat(b2,1,M)); % 计算第二隐层特征输出


out = exp(softmaxTheta * output_2);                        % 计算分类器输出
S = sum(exp(softmaxTheta * output_2),1);

% 计算softmax的梯度
softmaxThetaGrad = (groundTruth - out ./ repmat(S,k,1)) * output_2';
softmaxThetaGrad = -1/M * softmaxThetaGrad + lambda * softmaxTheta;

cost = sum(sum(groundTruth .* log(out./repmat(S,k,1))));
cost = -1/M * cost + lambda/2 * sum(sum(softmaxTheta.^2));


% 计算autoEncoder的梯度
delta_4 = -(groundTruth - out ./ repmat(S,k,1));
delta_3 = (softmaxTheta' * delta_4).* (output_2 .* (1 - output_2));
delta_2 = (W2'* delta_3) .* (output_1 .* (1 - output_1));
% delta_1 = (W1' * delta_2) .* (data .* (1 - data));

stackgrad{1}.w = 1/M * delta_2 * data';
stackgrad{1}.b = 1/M * sum(delta_2,2);
stackgrad{2}.w = 1/M * delta_3 * output_1';
stackgrad{2}.b = 1/M * sum(delta_3,2);

注意,由于这个程序使用了两个自动编码器层,所以训练时间是比较长的(配置高的电脑大概也得30min,运行内存最好有8G,不然也可能会报out of memory 的错误。

Exercise7:Linear Decoders with Autoencoders

这个练习和上一个练习基本上是相同的,就是把上个练习中第二个自动编码器的激励函数从sigmoid 换成了线性的,其他的没什么大的变化。

Exercise8:Convolution and Pooling

卷积神经网络在处理自然图像的时候有很大的优势,图像可以直接输入网络而不需要做向量化拉直。这个练习需要用到上个练习中的结果,练习中有提示,所以在做这个练习的时候最好先完成上面的练习。这里面需要实现的是cnnConvolve.m这个文件。注意我在其中有些没有按照他的提示做,但是效果是相同的。
% 计算特征卷积模板
AllFeatures = (W * ZCAWhite)';   % 400 * 192;
convFeatures = reshape(AllFeatures,8,8,3,numFeatures);

% --------------------------------------------------------

convolvedFeatures = zeros(numFeatures, numImages, imageDim - patchDim + 1, imageDim - patchDim + 1);
for imageNum = 1:numImages
  for featureNum = 1:numFeatures

    % convolution of image with feature matrix for each channel
    convolvedImage = zeros(imageDim - patchDim + 1, imageDim - patchDim + 1);
    for channel = 1:imageChannels

      % Obtain the feature (patchDim x patchDim) needed during the convolution
      % ---- YOUR CODE HERE ----
%       feature = zeros(8,8); % You should replace this
      
      feature = squeeze(convFeatures(:,:,channel,featureNum));
      
      % ------------------------

      % Flip the feature matrix because of the definition of convolution, as explained later
      %feature = flipud(fliplr(squeeze(feature)));
      feature = rot90(feature,2);
      
      % Obtain the image
      im = squeeze(images(:, :, channel, imageNum));

      % Convolve "feature" with "im", adding the result to convolvedImage
      % be sure to do a 'valid' convolution
      % ---- YOUR CODE HERE ----
      convolvedImage = convolvedImage + conv2(im,feature,'valid');
      
      % ------------------------

    end
    
    % Subtract the bias unit (correcting for the mean subtraction as well)
    % Then, apply the sigmoid function to get the hidden activation
    % ---- YOUR CODE HERE ----
    bias = b - W*ZCAWhite*meanPatch;
    convolvedImage = sigmoid(convolvedImage + repmat(bias(featureNum),imageDim - patchDim + 1, imageDim - patchDim + 1) );
    
    
    % ------------------------
    
    % The convolved feature is the sum of the convolved values for all channels
    convolvedFeatures(featureNum, imageNum, :, :) = convolvedImage;
  end
end


end

function y = sigmoid(x)
    y = 1 ./ (1 + exp(-x));
end

以上给出的代码是我个人认为比较关键的地方,当然要想让程序跑起来,还得实现其他的地方。所以大家如果在完成这些练习遇到困难实在不知道如何解决的时候可以参考我上面给出的关键代码。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值