这几天做UFLDL稀疏自编码器单元作业,到梯度计算步骤,总得不到正确结果。郁闷。回头看这个翻译,没有公式,读起来几乎没什么用。今天补一补。
斯坦福的UFLDL是系统学习深度学习内容、弄清其知识结构的好地方,其中练习对理解概念、增强技能非常有帮助。(http://deeplearning.stanford.edu/wiki/index.php/UFLDL_Tutorial)
向那些翻译了其中大部分内容的自愿者致敬!有了中文翻译,终于可以一目十行地浏览,而不是十目一行地钻研深度学习了。
不知什么原因,各单元的练习部分都没有翻译,我正好在学,就把自己做的事贡献出来,为通过这些练习进入深度学习领域的人提供一点儿方便。不确切之处请包涵。
尽量采用UFLDL网站上已有中文翻译格式,但贴到这里很难保持原貌。最主要的就是图片和公式太烦人,一个mathtype符号就得当图片贴一次,看来一会儿是帖不完了。
练习:稀疏自编码器
From Ufldl
Jump to: navigation, search
内容
1下载相关阅读材料
2稀疏自编码器实现
2.1第一步:生成训练集
2.2第二步:稀疏自编码器目标函数
2.3第三步:梯度检验
2.4第四步:训练稀疏自编码器
2.5第五步:可视化
3 结果
下载相关阅读资料
sparseae_reading.pdf :
http://nlp.stanford.edu/~socherr/sparseAutoencoder_2011new.pdf
sparseae_exercise.pdf:
http://www.stanford.edu/class/cs294a/cs294a_2011-assignment.pdf
(SeamusWEI说明:第一个文件与UFLDL网站稀疏自编码器单元的网上教程差不多,参考UFLDL网上教程,特别是对应中文翻译内容即可;第二个文件是作业布置,其主要内容就是这里所翻译部分。所以下不下载这两个文件无所谓。但有一点要注意,下文中所说的讲义节次编号,都是针对sparseae_reading.pdf文件中的节次而言的,不是网站上顺序。网站上没有内容的章节编号。)
稀疏自编码器实现
在这一组问题中,你要实现稀疏自编码器算法,说明它怎么能发现边角是自然图像的一种良好表示(图像由Bruno Olshausen提供)。稀疏自编码器算法见本课程网上讲义描述。
在sparseae_exercise.zip文件中,用Matlab提供了一些开始代码(下载地址:http://ufldl.stanford.edu/wiki/resources/sparseae_exercise.zip)。你要在该文件中注有“YOUR CODE HERE”的位置写你的代码。你得完成下列文件:
sampleIMAGES.m
sparseAutoencoderCost.m
computeNumericalGradient.m
训练函数train.m中的开始代码说明了这些函数怎么用。
(SeamusWEI说明:该zip文件大小为10.9MB,解压后为20.2MB,含54个文件,主要是各种matlab程序文件,最大的是图像文件IMAGES,20MB)。
软件说明:所提供.zip文件包括一个子目录minFunc,用第三方软件实现L-BFGS,依照CCA(创新共同署名许可证)授权非商用目的使用。如果要将该软件用于商业目的,可以下载使用另一个函数(fminlbfgs),能达到同样目的,但在这个练习中运行速度慢三倍(所以不怎么推荐)。可在下面的fminblfgs_details网页读到更多相关内容
http://deeplearning.stanford.edu/wiki/index.php/Fminlbfgs_Details
第一步:生成训练集
第一步是生成一个训练集。要得到单个训练样本x,从10幅图像中随机挑出一幅,再从挑出图像中随机采样一个8x8图像块,把图像块转换成64维向量得到一个训练样本(按行序或者列序组织向量无所谓),训练样本。
完成sampleIMAGES.m代码。所写代码应采样10000个图像块,保存为64x10000矩阵。
要确信所写代码奏效,运行train.m里面“Step 1”中代码。其结果应该是画出数据集里200个随机样本块。
实现提示:运行所写的sampleImages()时,所需时间应不多于5秒。要是运行时间超过30秒,可能是因为你不小心,在每次挑选随机图像时,复制了整个512x512大小的图像。把一个512x512的图像复制10000次,会让你的实现效率极低。虽然在这个练习中,这不会明显降低代码运行速度(因为只有10000个样本),但是,当在本节后面扩展到一百万个或更多样本时,这就会明显降低代码运行速度。请实现sampleIMAGES,别在每次需要剪切一个8x8图像块时,复制整个512x512图像。
第二步:稀疏自编码器目标函数
运行代码,计算稀疏自编码器代价函数(讲义第三部分),以及 相应于不同参数的对应导数。激活函数采用sigmoid函数:。在这里实际就是完成sparseAutoencoderCost.m中代码。
稀疏自编码器用矩阵,向量参数化。不过,为了后续标记方便,我们要把所有这些参数“展开”为一个很长的参数向量,其中共有个元素。参数组与参数向量之间转换的代码已经提供在开始代码中。
实现提示:目标函数包括三项,对应着平方误差项、权值衰减项、稀疏性惩罚项。你怎么实现都行,不过为了调试方便,建议先只用平方误差项实现代价函数和导数计算(反向传导),这对应着参数设置;并实现下一部分的梯度检验方法先证实这一代码正确。只有在相应于平方误差项的目标函数和导数计算证实奏效后,再添加代码计算权值衰减项和稀疏性惩罚项,以及它们相应的导数。
第三步:梯度检验
按照讲义2.3节内容实现梯度检验,即完成computeNumericalGradient.m。请按照讲义上描述,取。
我们还在checkNumericalGradient.m中提供了代码,供你测试自己程序。这个代码定义了一个简单的二次函数,形式为,在点上进行评估。它能让你证实你的数值方法梯度估值很接近实际梯度(解析计算得到的梯度值)。
用checkNumericalGradient.m确认正确后,用sparseAutoencoderCost.m确认导数计算正确。细节参考train.m中的Steps 3。极力劝戒:在证实导数计算正确之前,不要进入下一步。
实现提示:调试代码时,在小的模型和小的训练集上执行梯度检验,例如只用10个训练样本和1-2个隐藏单元,可加快速度。
第四步:训练稀疏自编码器
有了计算及其导数的代码,我们已经准备好了相对于的参数最小化,并由此训练稀疏自编码器。
我们采用L-BFGS算法,用一个包含在开始代码中称为minFunc的函数提供给你(代码由Mark Schmidt提供)。(就这个作业而言,你只要用默认参数调用minFunc函数即可,不必知道L-BFGS怎么实现)。我们已在train.m中提供了调用minFunc的代码(Step 4)。minFunc函数假设要优化的参数是一个长参数向量,所以在把参数传递给它时,采用参数向量而非参数组。
我们要训练的是一个有64个输入单元、25个隐单元以及64个输出单元的稀疏自编码器。在开始代码中,已提供了一个函数来初始化参数,把偏置初始化为0,权值初始化为从区间均匀得到的随机数。其中是扇入数(进入一个节点的输入数),是输出数(一个节点上的输出单元数)。
(SeamusWEI说明:网站上原文似有不妥,把、都说成fan-in,但却给出不同的括号中说明。疑一个是fan-in,一个是fan-out, 。。。)
所提供各种参数(等)的取值应该可用,不过也尽可以用不同的参数设置。
实现提示:一旦你有了正确计算导数的后向传导实现(用第三步的梯度检验验证),现在要用它与L_BFGS一起优化,要确保不在每一个步骤上都进行梯度检验。后向传导可相当有效地计算的导数,要是你画蛇添足地在每一步以数值方法计算梯度,会显著地放慢程序速度。
第五步:可视化
训练自编码器之后,用display_network.m显示所学权值(train.m,Step 5)。执行“print–djpeg weights.jpg”,把图像用文件名“weights.jpg”保存(与代码一起交作业)。
结果
要成功完成这个作业,你得展示你的稀疏编码器算法学到了一个边角检测器集合。例如,下面是我们得到的图像。
我们的实现在一个快速计算机上用了约5分钟。假使你需要尝试多种实现或不同的参数值,确保留给调试和做实验足够时间。
通过对比,下面还给出一些来自我们认为不成功的实现的图像(不是编程实现有问题,就是参数调谐得很差)。