DeepLearning

VGG pretrained模型地址: http://www.vlfeat.org/matconvnet/pretrained/ 下载地址: http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-19.mat 不过我用的这个beta版本的不太一样,地址 http://www.vlfeat.org/matconvnet/models/beta16/imagenet-vgg-verydeep-19.mat 但是分析过程是一样的 今天在玩Stanford CS20SI公开课里的一个神经网络style_transfer小模型的时候,用到了vgg pretrained模型,然而,代码里获取weight和bias是这么写的: W = vgg_layers[0][layer][0][0][2][0][0] b = vgg_layers[0][layer][0][0][2][0][1] 摔!这也没注释,完全看不懂啊! 虽然可以查到vgg的模型信息(下面有个layer configuration的SVG图),可是对应不上这些索引啊! 于是把模型下载下来,在ipython里一步一步解析: 首先,导入scipy.io包: import scipy.io 然后,用loadmat载入模型(载入matlab文件格式的方法): vgg = scipy.io.loadmat(‘imagenet-vgg-verydeep-19.mat’) 接下来就是探索格式了: 首先,看一下导入后的模型类型: […]

随着TensorFlow学习的深入,有许多细节不得不注意,Stanford的tensorflow公开课就讲解了很多细节,记录于此,以供参考。 tf.constant()和tf.Variable(),为什么constant是小写,Variable是大写?因为constant是个op(操作节点),而Variable是个class(类)。 Variable的initialize其实就是assign初始值,所以,当定义一个Variable时,如果紧跟了一个assign操作,其实是不用initialize的,例如W = tf.Variable(10), assign_op = W.assign(100), 我们可以直接sess.run(assign_op)而不用sess.run(tf.global_variables_initializer())。详见源码,其中有一句是:self._initializer_op = state_ops.assign(self._variable, self._initial_value, validate_shape=validate_shape).op。注意,类似tf.Variable.assign_add(), tf.Variable.assign_sub()之类的方法仍然要求对变量进行initialize,因为这些操作依赖Variable的初始值。 constant是定义在graph(图)中的,而Variable是和Session绑定的。也就是说,在tensorboard中可视化graph时,可以看到constant但是看不到variable,且不同的session可以维护一个variable的不同值,例如sess1 = tf.Session(), sess2 = tf.Session(), sess1.run(W.assign(10)), sess2.run(W.assign(20)) 用另一个Variable初始化一个Variable时,要注意使用initialized_value()方法,例如W = tf.Variable(tf.truncated_normal([10,10])), U = tf.Variable(W2)是错误的,因为U使用W去初始化,在U初始化的时候,W很可能还没有初始化(TensorFlow的分布式,并行运行的特点所导致),因此,正确写法是W = tf.Variable(tf.truncated_normal([10,10])), […]

不得不说,archlinux真的是开发人员友好的…当然前提是能够接受足够新的软件环境(gcc都7.1.1了…) 安装Nvidia驱动,cuda,cudnn,配置环境变量一条命令搞定: # pacman -S nvidia cuda cudnn 对,你没有看错,就是一条命令,而且以后升级也是,交给系统,完全无忧。 如果不从源码编译的话,直接pip install tensorflow-gpu就好了,That‘s it! 如果从源码编译,请安装bazel,也是一条命令: # pacman -S bazel 然后参照官方教程编译安装即可。 比Ubuntu简单几个数量级:)

TL;DR:有同学反应资源太多不知道从何看起,或者有点基础了想快速上手,因此就直接把几个比较好的教程放在这里,后面的内容作为参考。 Stanford的CS 20SI课程,专门针对TensorFlow的课程,Tensorflow for Deep Learning Research 两本书籍:TensorFlow Machine Learning Cookbook以及TensorFlow for Machine Intelligence,这两本网络均有pdf版本,请自行搜索。 Udacity公开课,深度学习 第一篇学习之路写于2016年6月份,时过境迁,特别是深度学习这个日新月异的领域,隔了那么久,不得不说已经有些过时了,并且随着学习的深入,越发觉得之前的学习之路过于笼统,加之TensorFlow发布了1.0正式版,因此整理一下,再次写一篇。这次在内容的结构上将会大体分为三种,首先是公共基础部分,这个无需多解释。另外,一个是偏向应用性质的快节奏(fast peace),针对不想也没必要深入了解理论知识希望尽快应用的人群,另一种是偏向研究性质的人群(hard way),针对例如研究生之类希望深入理论知识的人群。当然,hard way的前提是fast peace。但是写法上,并没有分别写,因为某种意义上这两种是相互包含的,分开写会显得冗长与重复,因此采用粗体标记提示特定部分是属于哪一种。 0. 不是前提的前提–英语阅读【公共基础】:需要有扎实的英语阅读能力,其实与其说扎实,不如说是能沉下心看英语。其实我最开始看这些大段英文文档的时候,我是拒绝的,后来发现真的,这是绕不过去的坎,再后来坚持背英语单词(推荐扇贝单词)加上耐着性子读好了很多。至于原因,为什么读英文,那是因为不仅很多优秀的文档有且仅有英文的,更是很多国内的开发者也会用英文写。而且,如果对于做学术的人,那么英语作为通用语言更是要熟练掌握。但是我尽量每个部分教程都给出一份中文的,尽量保证在不想看英文的情况下也有不错的指导。 1. 翻墙【公共基础】:这是个不是技术的技术,TensorFlow毕竟出自Google,官方文档访问不是很稳定,而且Google搜索的结果要比Baidu好很多(学术,代码,外文类,这是有目共睹的)。有些免费一键翻墙的软件比如Lantern,打不开就这个(在releases中下载对应操作系统版本),或者赛风。高级一点的是Shadowsocks,这个不同于前面的一键翻墙工具,需要自己配置服务器或者购买配置好的服务。 在这里插一句,本来是不想说这些的,有推销嫌疑,但是有很多人文这个问题,有哪些推荐的梯子。我是用的是Digitalocean(这是我的推荐链接 ,使用的话你我都可以获得奖励)搭建服务器,很稳定,$5(约35人民币)一个月,1T流量(肯定是用不完的,好像超了也不收费),在服务器上跑了一个shadowsocks的服务端外加这个wordpress的博客。网上有很多搭建教程。或者如果想省事,可以与我合租,服务器已经搭建好了,简单配置即可。可以发我Gmail,在网站的About页面有。p.s. 几人合租就几分之一$5,无额外费用,程序员纯纯的友谊你懂的:) 2. Github【公共基础】:这是个开源程序的网站,Linux内核就在这个网站托管。Github的核心是Git,一种版本控制系统,已经逐渐取代SVN。这个网站托管了很多高质量的或者说世界顶尖的开源项目,比如TensorFlow。学习一下这个网站如何使用,注册个账号,学习一下Git的使用方法。这个网站有自己的tutorial和guide。而且后期自己的项目管理多半也会用到git,所以,早点学习肯定是有好处的。 【fast […]

TensorBoard Embedding 实战

TensorBoard是TensorFlow自带的一个训练可视化工具,可以实现对训练过程中的tensor量监控,常见的包括loss,accuracy等等,同时也可以对权重值W,偏置值b等绘制histogram(不过这个不是传统意义上的histogram,开发组也在着手让这个histogram变得更直观),r0.12版本中添加了新功能embedding,随着r1.0的释出,embedding也越发成熟,但是官网的教程确实让新手一头雾水,几番搜索后,发现了一份不错的示例代码,但是这其中还是有些比较隐晦的概念,因此这篇博客针对对mnist的embedding进行讲解。 预备知识: 1. 什么是embedding,首先,可以看看wiki的定义,其实简而言之,embedding就是一个“保持结构的单射”,保持结构是指不改变原始数据的结构信息(比如几何结构,mnist图像的内在结构),单射是指一一映射,这样就很好理解什么叫对mnist进行embedding,也就是对mnist原始图像进行一个“保持结构的单射变换”,使得一个图像这种非结构型数据易于处理(分类),如果对词嵌入很熟悉的话,就很好理解了,词嵌入也是一种embedding,把词映射到了实数空间。 2. 什么是sprite image,首先看一下w3schools的定义,这个其实在网页和游戏里比较常用,就是把很多零碎的小图片拼接成一张大图片,要用到相应图片的时候就去大图片上截取。例如,1024张mnist图像拼接的sprite image是这样的: 接下来我就先说一下TensorBoard Embedding的基本思想,基本代码操作,然后给出完整代码以及用到的资源。(请先阅读上面给出的官方教程,有很多概念需要了解,例如sprite image以及labels文件的内容,组织方式等。) TensorBoard Embedding的基本思想就是embedding+sprite image。首先,输入(例如mnist图像以及对应的标签)经过模型(例如卷积神经网络)得到输出(一个对图像重表示的tensor),这个输出的tensor其实就可以看做对一个mnist输入的embedding(1.由图像结构计算出的。2.每个图像有且仅有一个对应的输出tensor),那么,我们就可以利用这个embedding对原始的mnist图像进行分类,可视化处理。随后,指定sprite image的路径以及对应的labels的路径,利用给出的labels去把输出的tensor绑定到对应的sprite image区块的图像。这么说有点绕,举个例子:mnist的有监督训练,网络模型接收了一个mnist图像“7”以及对应这个图像的标签“7”,经过模型,得到输出tensor “t”,那么TensorBoard就会去给定的labels文件里寻找“7”这个标签,然后找到“7”这个标签对应的sprite image中的区块(行优先),绑定到tensor “t”上,这样,对tensor进行可视化的时候就可以显示绑定的image,达到对image进行分类可视化的效果。 实现的关键代码是(解释详见注释): config = tf.contrib.tensorboard.plugins.projector.ProjectorConfig() embedding_config = config.embeddings.add() # embedding是一个tf变量 embedding_config.tensor_name = […]

看完了TensorFlow官网的两份白皮书后,产生了阅读源码的念头,不过,git clone下来以后,仅从代码大小上就可以看出TF的体量之大,源码绝不是一己之力一时半会能够理解的。几番搜索,发现网上关于源码阅读的教程确实是很少,这里有一份不错的,这里还有google group里的讨论,为了方便墙内读者阅读,引用于此: core/ contains the main C++ code and runtimes. core/ops/ contains the “signatures” of the operations core/kernels/ contains the “implementations” of the operations (including CPU and CUDA kernels) […]

在Android端使用TensorFlow

本篇文章中软件的下载需要科学上网支持。 主要参考资料为这篇文章,但是原文章涉及的TF版本已经过旧,有些小坑,例如android工程几个项目文件的修改,已经完全不同了。 TensorFlow的一个很突出的优势是跨平台,但是这方面的资料还比较少。 不过最近随着1.0版本的发布,文档的逐渐完善,在移动端的应用也越来越都多,并且官方增加了两个demo。其实应用在移动端还是比较容易的,只是因为官方的文档还是太省略,并且如果没有前两篇(1,2)的铺垫知识,看起来容易一头雾水。还有一个复杂的地方是,如果需要自定义app需要用到一些Android编程的知识,并且Google的Bazel编译工具也实在是太小众了。鉴于这些坑,将项目的心得分享记录于此,以供参考,节省大家的时间。 通过前两篇博客(1,2),我们通过重新训练获得了权重值文件(retrained_graph.pb)和标签文件(retrained_labels.txt),利用这两个文件和官方给的demo代码,就可以简单实现在移动端(因为我手上只有Android设备,因此仅针对Android)的实时识别。 编译Android端的app需要用到Android的SDK与NDK,首先下载这两个工具集。不过我推荐先下载Android Studio,使用Android Studio管理SDK与NDK,这样下载,管理和升级比较方便,而且毕竟以后可能还要调整demo,要用到Android的开发IDE。下载过程就不详细描述了,Android开发者网站有很详细的步骤。 有了SDK与NDK后,就可以着手利用我们重训练的权重值文件与标签编译app了。首先,需要告诉TensorFlow SDK与NDK的路径。浏览至tensorflow目录,打开WORKSPACE文件,在文件第10行左右,会看到以下代码: # Uncomment and update the paths in these entries to build the Android demo. #android_sdk_repository( # name = “androidsdk”, # […]

本篇文章中软件的下载需要科学上网支持。 主要参考资料为这篇文章,主要步骤相同,对参数,细节做了说明。 一般来讲,深度学习的模型训练需要消耗大量的计算资源,例如Google的Inception模型,使用了8张K40显卡训练了两周,普通开发者一般没有这样强大的计算资源支撑。但是迁移学习提供了捷径,通过重训练已训练模型的最后几层,就可以将模型用于自定义图像的分类。TF提供了用于重训练的工具集。 因此,在尝试自己搭建模型并训练模型之前,应首先尝试使用重训练模型方法,这样的好处是可以先快速评估至少可以达到的准确率,对以后的模型建立,优化提供基线(baseline)。 并且,重训练生成的权重值文件可以用于TF移动端app,移动端app直接加载训练好的权重值,通过摄像头实时识别,这将在下篇博客中讲解。 这次项目中使用的是基金会提供的视网膜病变图像,数据集比较小,只有不到400张,依然达到了不错的准确率(测试集80%左右),本教程中,以开源数据集为例做示范。 开源数据集下载地址: http://download.tensorflow.org/example_images/flower_photos.tgz 首先,下载数据集 $ curl -O http://download.tensorflow.org/example_images/flower_photos.tgz 解压到某一目录下,比如~/Downloads/flower,可以看到,flower_photos文件夹中有5个分类,在重训练过程中,TF提供的工具集会将这五个分类文件夹的名称作为类别标签,因此,若需要修改分类标签,应在这里修改文件夹的名称。 上篇博客讲解了如何从源码安装TF(是本篇博客的基础)。 首先,浏览至源码目录顶层,例如: $ cd ~/tensorflow 然后执行重训练Python程序(这里的参数仅仅是示例,可直接打开源码文件,底部有所有参数以及参数说明,可用于进一步调参使用),注意路径替换为自己的路径: python3 tensorflow/examples/image_retraining/retrain.py \ –bottleneck_dir=/home/hp/Downloads/flower/bottlenecks \ –model_dir=/home/hp/Downloads/flower/inception \ –output_graph=/home/hp/Downloads/flower/retrained_graph.pb \ –output_labels=/home/hp/Downloads/flower/retrained_labels.txt […]

  今天(2017年2月15日),TensorFlow 1.0正式发布,这意味着TF已经可以真正作为生产环境的主力Framework了!向所有开发者致敬! 本篇文章中软件的下载需要科学上网支持。主要参考资料为tensorflow的官方说明文档。 本想在一月份就把近期做的一个有关医疗图像识别的项目以博客的形式记录下来,然而一直拖到现在……计划写一个小系列吧,把配置过程,尝试过的方法分开记录于此。就从从源码安装开始吧。 由于本项目用到了重训练inception和生成Android端app,这个过程需要使用TensorFlow中的一些二进制工具软件,仅仅使用pip安装Python包是不够的,因此,需要通过源码安装TF。并且,通过源码安装可以获得最大性能,可以开启CPU高级指令集(例如sse,avx)的支持。由于我使用的计算机配置的是AMD显卡,并且当时没有OpenCL支持,因此不涉及GPU版本,但步骤都是相似的,配合查阅官方文档很容易安装GPU版本。我使用的操作系统为Ubuntu 16.04(当时TF的版本是0.11,但是写这篇博客的时候1.0已经发布,因此我就以1.0版本为基础复现项目,在写作过程中我尽量每一步都使用1.0版本复现,防止造成困扰) 首先从github clone项目并checkout到1.0版本: $ git clone https://github.com/tensorflow/tensorflow $ cd tensorflow $ git checkout r1.0 安装编译工具Bazel: 首先安装JDK8: $ sudo add-apt-repository ppa:webupd8team/java $ sudo apt-get update […]

结合TensorFlow PlayGround的简单神经网络原理解释

很多人把机器学习(或者说本篇文章的重点:神经网络)看成“黑技术”、“黑魔法”,其实不然,所有的机器学习无外乎就是找到从输入到输入的最佳拟合函数,只是各种不同的机器学习技术得到的拟合函数方法、效果不同因此适用情景不同罢了。那么今天我们就结合TensorFlow的Playground来具体讲解一下,神经网络是如何去拟合输入和输出之间的目标函数的。好的,系好安全带,要发车了:) PlayGround是一个图形化用于教学目的的简单神经网络在线演示、实验的平台,非常强大地可视化了神经网络的训练过程。不得不说做出这个演示系统的人不仅对神经网络的见解深刻,更是找到了可视化的有力方法。建议使用的时候把右下角的discretize output(离散化输出)选上,不去让系统自动平滑,这样本质看的更清楚。我们首先简单的讲一下这个PlayGround。第一块也就是最上面一行是训练参数,保持默认即可,这个我们不去做过多解释和介绍。因为这涉及到更深层次的神经网络知识,远非一篇简短的blog可以解释清楚,而且本篇文章的重点也是从intuitive(直觉化,直观化)方式讲解基本原理。想要了解更多的内容,请参见我写的另一篇教程:新手向的TensorFlow学习之路(Learning paths)。第二块就是下面的内容,从左到右是dataset(数据集)选择,feature(特征)选择,hidden layers(隐含层)选择和output(输出)。 研究一个未知事物的时候,我们习惯于也应该从最简单的情况开始讨论,那么对于神经网络,什么是简单的情况?当然是神经元的数目越少越好,这样我们才能从繁杂的现象中理清关系。首先我们选择dataset中的第二行第一个,也就是Gaussian,然后feature选择x1,x2,点击hedden layers的减号去掉所有的隐含层,这样我们就得到的简单的模型,这个模型简单到只有两个神经元!就像这样:   接下来,我们点击第一行的Run开始训练。这个模型应该几秒钟就训练完成了。而且效果非常好,可以清晰的看出dataset已经被明显地按照颜色划分成了两块。你可能会觉得,What!!发生了什么!!别急,我们接着看。 这时把鼠标hover(悬停)在x1或者x2上,你会看到这样的划分: 对,这就是第一个feature,竖着“切一刀”!同样,第二个也是“切一刀”,不过是横着罢了。这样简单的“切一刀”就能解决问题吗?显然不能,所以这时时候weight(权重)就是上场了。weight就是来协调每个“切一刀”切多少的,把每个简单的动作联合起来,共同去解决问题。也就是说:每个神经元都是“傻傻的”只会一件事情,然后通过weight去组合协调,完成一件复杂的任务!多说无益。我们更进一步看看吧。 我们再把鼠标hover到那个连接x1,x2到output的线条上,这时你会看到“Weight is xxx”的字样,点击线条我们是可以修改那个xxx数值的。那我们就试着修改那个xxx吧!首先,把x1的weight改成0,你应该会看到这样的画面:   这不就是x2嘛!是不是有点感觉了?如果x2的weight是0那么应该和x1一样吧?那就来试试自己的猜想,点击第一行的reset(重置)后run重新训练,再试着把x2的weight改成0。这次发现,不出所料,果真是自己猜想的那样~这次我们把x1,x2的weight都改成1,当然如果你开心,可以都改成100:)你会发现,一条完美的对角线平分了dataset,把dataset分成了两个部分。就像这样: 这意味着什么?这意味着两点:1.weight确实是各个feature的加权值,是一个去协调各个feature的量,weight(x1)=weight(x2)的时候,x1,x2同等重要,导致平分天下;2.学习/训练的过程不过是去寻找选择最优weight的过程,如果“人眼”能一眼看出weight,就像这个简单的数据集,我们大可去手工输入weight,同样可以达到一样甚至更好的效果!这正验证了之前的结论:每个神经元都是“傻傻的”只会一件事情,然后通过weight去组合协调,完成一件复杂的任务!两个神经元尚且如此,想象一个拥有成千上万乃至上亿神经元的系统(比如人脑),完全不用奇怪这个系统可以完成及其复杂的任务! 现在可以尝试不同的dataset,再多加几个hidden layers,感受一下简单的神经元通过weight组合协调完成分类任务的强大。推荐试一下这个组合:dataset选择第一行第二个Exclusive or,feature只选择一个,就是第五个x1x2,然后hidden layers为0,也就是没有隐含层。然后再试一下用其他的feature去训练,对比感受一下feature的选择对结果的巨大影响。 讲到这里,应该对神经网络的基本原理有了朦胧的认识的,但这是远远不够的,还有很多都没有讲(好吧,主要是比较懒:)),比如feature,multiple output,activition function等等,感兴趣可以参见Michael Nielsen的这一讲,可视化地证明了神经网络对任意函数的拟合能力,非常精彩。阅读过程中可以结合PlayGround去理解。 如果您觉得作者的博客对您有用,不妨鼓励作者一下,作者将会更加努力写出高质量博客。