CS231N-Lecture4 Backpropagation&Neural Network

一、概述 上一集结束之后,学到了score function,可以用SVM或者Softmax计算loss,可以在loss中增加regularization来获取更加合理的W,并且最后可以用Analytic Gradient(微积分)的方式计算loss function相对于W的gradient来更新W。如下图。 这一集讲了如何使用链式法则来反向传播gradients,来更新W和b,这个gradients反向传播的过程叫做Backpropagation。 Backpropagation之后,进入了Neural Network的介绍。 二、Backpropagation Computational Graph 在计算gradient并进行backpropagate(bp)的时候,借助computational graphs(cg)可以让整个过程更加清晰(对于新手来说更是这样)。在学习的起步阶段,可以借助它来理解bp的原理。但是当神经网络复杂了之后,再转换成cg看起来就很头疼了。就像这样。 tensorboard是cg可视化的一个很强大的工具。 一个computational graph是对整个神经网络的直观图形表述。 上图中,每一个矩形代表着input x和W;每一个圆代表着一个操作;箭头指明了元素在这个神经网络中的流向,从输入开始,一直到最终的loss输出。 其中,圆被称为一个门gate。数据每流经一个门,都会经过相应的数学变换。 bp如何实现 上图已经完成了forward pass的过程,输入从左到右,经过+,*,得到结果f。 上图中有三个输入,x,y,z;一个+ gate q;一个* gate f;最后得到输出f = 12。 红色框中,是+这个操作相对于x,y的求导; 蓝色框中,是*这个操作相对于+,z的求导; bp的过程,就是将运算顺序倒过来,从cg的最右端开始,利用链式法则(Chain Rule),依次将所有前面已经计算的到的导数,和当前元素的导数相乘,就是当前元素的gradient。 从最右端开始,f相对于自身的导数是1。如下图: 继续往左运算,遇到了* gate;这个门的算式就是f = qz,蓝色框中的算式。 要求出z的gradient,就是将之前已经计算出的gradient df / df = 1,与z本身的gradient相乘,即(df / df) * (df / dz)。 先求f相对于z的导数,df / dz = q;…

CategoriesML

CS231N-Lecture3 Loss Functions and Optimization

一、概述 在上一讲中,Andrej总结说在没有loss function的情况下,我们在用肉眼观察哪些分数是好的,哪些分数是坏的,如下图。 图中,cat的预测分数不是很好,2.9的分数比一些分数高,但是比deer,dog等的低;car的预测分数则很好,比所有其他分数都高;而frog的预测分数糟透了,比大部分的分数都要低。 这个lecture中讲的是用loss function来量化分数的好坏,并用optimizer来优化W和b,使loss最小化。 二、Loss Functions 下面介绍了两种loss function,SVM Cost和Softmax Cost(Cross-entropy cost)。 Multiclass SVM Cost 将所有不正确类型的分数和正确类型的分数的差 + 1之后的值,和0取最大值,最后将这些最大值相加,就是SVM Cost。 1) SVM Cost如何计算 下图是三个示例,具体展示SVM Cost是如何计算的。 视频中对为什么+1作了一些解释,但是不是很明白。还需要体会一下。1可以理解为是一个安全阀值。由于W可以初始化成大一些或者小一些,这是随机的。因此最终的预测分数也可以或大或小,因为W的缘故。这个1可能也是为了增加随机性而加上去的。Andrej说,选择1而是任意的,也就是说,你可以+2,+100,都是可以的,但是不能是0,和负数,这个也还不是很明白,有待体会。但是可能就像learning rate一样,太大了模型就不能和训练数据拟合了。这个1也可以想象成可以调整的hyper parameter,虽然最后Andrej说了这个不是hyper parameter… 在真正使用中,loss的值应该是将三个类型的loss相加,然后取平均值。 在上图中,也就是说,这一组W和b,作用在input image上之后,通过SVM Cost得到了一个loss值,这个值是4.6。 问题:为什么不能让j = yi?(j,和yi是svm cost公式中的两个脚标,上面的图片中有)因为如果j = yi,sj – syi = 0,max之后得到1,那么最终的loss都会+1,增大了的loss的数值。问题:loss的最大最小值可以是多少?最大值是无穷大,最小值是0。问题:如果W在初始化的时候都是很小的值,那么所有类型的score都约等于0,在上图的情况下,loss是多少?loss是2;通用的公式是,第一次计算出来的loss应该是预测类型的个数 – 1。我们应该用这个规律来检查W初始化了之后,神经网络第一次的运行是否正确。在只有三个类型的例子中,如果初始化了之后,第一次计算得到的loss大致上在2左右,那么说明一切基本正常,至少没有很大问题;但是如果这个数值大大偏离了2,那就要检查一下网络中会有很大的问题。 Hinge Loss and Squared Hinge Loss 上图中,上一个公式被称作Hinge Loss,相应的,下面一个就是Squared Hinge Loss。这两个计算loss的方法可以被理解成是一个hyper…

CategoriesML

CS231N-Lecture2 Image Classification Pipline

图片分类概述 一、概述 这一课标题是Image Classification Pip-line,大概就是讲了图片分类的整个框架流程。看完之后确实对于卷积网络底层是如何对图片进行分类的有了再进一步的认识,感觉又清晰了一些。 点击这里下载CS231N的所有课件PDF 图片是如何被分类的 图片分类用人类语言来描述大致就是将一个图片,通过某种方式,映射到一个标签上的过程。 图片分类的挑战 1) 语义层面 计算机只认识0和1,如何让计算机认识每张图片并进行分类,首要的就是把图片变成数字。 对于人类来说这为理解增加了难度。每张非黑白图片都会被转化程一个长 x 高 x 深的矩阵;例如一张300 * 100像素的图片,会转换成一个300 x 100 x 3的矩阵,作为分类器的输入,然后进一步通过数学计算,完成分类。 例子中的深度3表示表示彩色图片的色彩通道RGB。 2) 图片的明暗 这张图片中有两只猫,左边一只光线很暗,右边一只光线明亮。 必须让分类器对像素的敏感程度做出相应理想的反应,才能完成图中两只猫的识别。 3) 物体的不同形态或姿势 图片里都是猫,但是姿势各异。需要调整分类器对不同的姿势做出理想的反应,并成功将图片分类为猫也是挑战之一。 4) 遮挡 对于人类来说,虽然被遮挡了,但是我们一眼可以确认图片里的是猫。对于分类器来说,这是一个巨大的挑战。 分类器需要要根据图片中仅有一些特征,做出正确的反应并分类图片。 5) 背景融合 背景颜色和猫咪的颜色相差无几,意味着每个像素的矩阵数值十分接近。分类器要成功从很相近的数值中分辨出图片中的猫同样是很艰巨的任务。 另外,对于其他生活中的实际例子来说,例如排序,我们可以写一个冒泡算法,但是对于图片分类这样抽象的问题,是没有固定的算法可言的。 我们需要用到分类器,以及之后会涉及的神经网络,卷积神经网络的支持,来完成这项任务。 二、分类方法 K—NN分类 NN分类器 NN(Nearest Neighbors)分类通过计算目标与训练数据的距离来确定目标属于哪个分类的算法。 NN中有两种计算距离的方式; 课程中用python构建了一个简单的NN分类器: 红框中的代码就是在计算目标点与每一个训练数据的距离,并将最近的距离设置到Ypred中保存; NN分类器的弊端在于,测试的时候,效率很低。因为要将目标图片的每一行数据,和训练数据的所有行进行对比来计算最小距离。复杂度是线性上升的。 但是在图片分类任务中,我们最关心的是测试(应用)阶段的效率。因此后面会说到,不会用NN分类器来分类图片,而会使用在测试阶段效率很高的卷积网络来执行分类任务。 K-NN分类 K-NN分类和NN分类有点不同,NN分类中需要将目标图片的数据和所有训练数据进行对比,而K-NN中,只需要和临近的K个数据进行对比。 上图中,的NN classifier(中间的图片),在蓝色区域的左下角,有一小块的绿色区域,里面又一个绿色的点。这片区域被标成了绿色,是因为如果有任意点落在那个绿色区域里面,这个绿色的点将会是离这个点最近的点,因此这个落下的点会被标记成绿色。 KNN…

CategoriesML

Tensorflow-0-带GPU支持的安装与校验

Tensorflow-0-带GPU支持的安装与校验 零. 回顾与概述 这篇文章详细介绍了Tensorflow的安装和校验安装是否成功的教程,涵盖了在Ubuntu 16.04环境下GPU支持安装和非GPU支持的安装以及校验。 系统概览: Ubuntu 16.04 64位 NVIDIA GTX 770M 内容概览: 根据NVIDIA官方文档安装CUDA-Toolkit 校验CUDA安装是否成功 根据Tensorflow官方文档安装Tensorflow(GPU支持) 校验Tensorflow安装是否成功 原版文档很长,这篇文章给使用Ubuntu的朋友们提供一下便利! 一. Tensorflow入门资源推荐 我的第一份Tensorflow入门,给大家介绍一下,是Youtube里周莫烦的Tensorflow基础教程,翻墙点击这里带你去看! 下面好评很多,很基础,现在20集的样子,大家可以订阅,并且希望他能持续更新。 二. Tensorflow安装 首先请翻墙; 点击进入Tensofrflow官网Linux安装页。进入页面之后就会看到安装选择,可以安装非GPU支持的TF(Tensorflow以下简称TF)和GPU支持的TF,我们这边选择安装GPU支持的TF; 检查系统软件硬件是否符合NVIDIA要求; 完整的安装前检查如下: 检查系统GPU是否处于CUDA支持列表 通过 lspci | grep -i nvidia 来查看系统GPU型号;如果没有输入,请先运行update-pciids,然后再次运行上一个命令; 并且到 CUDA支持的GPU列表 查看系统GPU是否处于支持列表; 检查当前Linux版本处于CUDA支持列表 通过 uname -m && cat /etc/*release 来查看Linux版本; CUDA-8支持的Linux版本 检查系统安装了gcc 通过 gcc –version 来查看系统是否安装gcc;如果报错,请安装相应的开发工具包; 检查系统是否安装内核头文件,以及必要的开发工具包; 通过…

CategoriesML

AndroidStudio导入库文件

今来看看Android Studio怎么使用第三方库~网上找了很多教程貌似都有问题,自己尝试了一下,简单易行,亲测有效~ 第一步:准备好Android Studio格式的库文件 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BUeL3azw-1587400315304)(http://img.blog.csdn.net/20150916073333627)] 这是一个SlidingMenu的库文件,点击这里下载SlidingMenu;大家可以下载来做测试~如果是Eclipse出身的库,还不知道该怎么办,以后遇到再说吧~ 第二步:在项目内点击File -> New -> Import Module导入模块 然后选择第三方库的根目录 如果已经包含这个模块,会出现感叹号后面的提示,第一次肯定没有啦~ 这时,切换到Project视图,就能看到库文件已经导入了~ 第三步:修改库文件的build.gradle文件 这个是自己应用的build.gradle文件内容 我们要保证compoleSdkVersion,buildToolsVersion,minSdkVersion,targetSdkVersion在app和导入的库文件中都一致~ 下面是修改之后的库文件里的build.gradle~ 第四步:在Project视图下找到工程的build.gradle文件,替换库文件的classpath 将文件中的classpath ‘com.android.tools.build:gradle:1.3.0’一行,复制到库文件的gradle文件中,替换相应的classpath行,保证一致~ 第五步:这个不是通用步骤(可忽略) SlidingMenu中使用的是android.util.FloatMath类,导入的时候会报错;原因是这个类已经过时了,建议使用java.lang.Math类~只需要找到相应的错误,将FloatMath替换成Math类即可~ 第六步:设置项目依赖关系 以添加Module dependency的形式,关联库文件;然后Clean一下Project~ SlidingMenu就等着你折腾了~ 这样看来,Android Studio中导入第三方库的过程应该都大同小异吧~

Android事件处理机制轻量级源码分析

正确理解Android中的事件分发和拦截机制,对于在多个ViewGroup和View嵌套以及自定义控件的时候能够正常处理用户行为至关重要。 如果要把源码一行一行看,研究事件处理机制就要到天荒地老了。这是为什么这篇博客叫轻量级源码分析,简单易懂。屏蔽掉了冗长的无需太过关心的源码,把握一下几行重点,其实事件处理就可以有一定的了解了。这篇博文就是根据源码一步一步走了一下事件处理的流程,分模块来看应该思路应该会比较清晰一点~ 事件分发和拦截101 开始之前首先明确一下,在源码当中,理解事件分发,关注一下dispatchTouchEvent()方法;理解事件拦截,再多关注一个onInterceptTouchEvent()方法即可~ 还有噢,dispatchTouchEvent()方法返回true表示响应全部事件,而返回false则表示只响应第一个事件,忽略后续的事件~onInterceptTouchEvent()方法返回true表示拦截事件,子View不会接收到该事件;返回false表示不拦截事件,向子View传递该事件,让子View尝试处理~ 哟西~ Let`s hacking… 一、View的事件处理机制 View中的事件分发对于本身可以被点击和不可被点击的View有些许不同~ 1. View的事件分发之不可被点击的View 先看一个小示例哟~这一小段代码中有两个控件,一个ImageView,一个Button,这两个控件最终都是继承View的,就用这两个控件来阐述一下View的事件处理机制 这一小段代码,还是粘上来吧~ 先说一说本身不可被点击的ImageView~这里给imageView添加一个onTouchListener,我们看看在return false的情况下,单击一次,打印了几次输出信息~ 运行之后发现输出了imageView eventAction = 0。由于一次单击包括按下和抬起两个操作(0表示按下的操作,1表示抬起的操作),因此从这个现象可以看出,抬起的操作在这个情况下没有被监测到。想知道为什么,就来看看源码咯~ ImageView是继承View的(继承了dispatchTouchEvent()方法),所以应该到View的源码中查看一下dispatchTouchEvent()(我们要关注的就是这个方法嘛)方法,看看View是怎么进行事件分发的(就知道ImageView是怎么处理事件的了)。过滤了不必要的代码之后,应该关注的代码如下: dispatchTouchEvent()方法 View的dispatchTouchEvent()方法中,这个if语句的意思是说,如果mOnTouchListener 引用不为空,并且当前要接收事件的控件(此处就是这个IamgeView)处于可用状态(只要不设置setEnable = false,这个条件是始终成立的,所以后面就不说这个条件了),并且mOnTouchListener这个引用的onTouch方法返回了true,那么整个dispatchTouchEvent()就返回true,否则返回onTouchEvent(event)方法执行的结果。 那么ImageView被点击之后,是否执行了if语句呢?下面来判断一下if中的条件该ImageView是否满足~ 所以呢,此时的ImageView是不会执行dispatchTouchEvent()方法中的if语句块的,而会执行其所继承的onTouchEvent(event)方法,并返回相应的布尔结果。 到这里,还无法得知为什么ImageView上的抬起事件没有被监测到。那就来看看这个onTouchEvent(event)方法到底干了什么。这个方法代码超长的,哈哈,轻量级源码如下: onTouchEvent()方法 这里又有一个if语句块,这个if说,如果你这个接收事件的控件可以被点击,或者可以被长点击,那么就执行if中的逻辑,然后返回true,否则整个方法返回false。那就来看看我们的ImageView是否满足条件咯~ 然后再回到dispatchTouchEvent()方法,既然此时的ImageView不能执行if中的代码,而onTouchEvent()方法又返回了false,所以整个dispatchTouchEvent()就返回了false。根据文章开头所说dispatchTouchEvent()返回true和false的意义得知,这个单击事件整体只有按下会被处理,所以就只会打印一次输出信息咯~ 如果想让ImageView同时响应按下和抬起的事件,该怎么办呢?有两个方式: 2. View的事件分发之可以被点击的View 接下来就说说Button这个东西~ 在同样的环境下,同样地为Button添加了一个触摸事件监听器,在onTouch()方法中返回了false;运行之后,输出了Button eventAction = 0和Button eventAction = 1。这里同样返回false,为什么就能打印两次信息,为什么Button的整个单击事件可以被完全监测呢? 原因就在于Button本身是可以被点击的;在其他条件都相同的情况下,Button本身可以被点击的属性,可以让其执行onTouchEvent()方法中的if语句 onTouchEvent()方法 从而返回true;进而dispatchTouchEvent()方法返回true,单击事件的按下和抬起都会被监测~ 3. onClick()、onTouch()和onTouchEvent的调用顺序 上面一点很好理解。那进一步,如果也给Button再来一个setOnClickListener()呢?就像这样 在onTouch()方法返回false的情况下,还会打印”button onclick”的信息吗? 运行之后发现,”button onclick”的信息在Button eventAction =…

Android Studio最新版本(1.3)JNI开发流程总结

JNI应该是Android开发人员的标配了~从Eclipse转到Android Studio有好多东西就必须重新学习。网上已有的对于Android Studio JNI开发的博文貌似都有些问题,在最新版本的Studio一些步骤已经无法使用。花了些时间重新整理了一下整个JNI开发的流程。环境:Android Studio 1.3.2;MackBook Pro 第一步:如果还没有在Studio中下载NDK的话,打开项目结构,然后点击Android NDK location一栏下面的Download NDK,开始下载NDK(需要翻墙) 下载完成之后,Studio自动帮我们安装;之后会自动将项目默认结构设置中的NDK位置(Close Project -> Configure -> Project Defaults -> Project Structure -> Android NDK location)设置到当前NDK的安装位置。 第二步:配置完NDK环境,就可以开始写本地方法了。先在MainActivity中添加一个本地方法 第三步:点击Build -> Make Project,生成项目的字节码文件(至此,这些步骤跟已有的没有什么区别) 第四步:生成头文件这一步有些不同。其他博文上要求在Terminal中切换到main目录,然后输入javah -d jni ….. <包名.类名>一大堆命令,但是发现这个命令无法使用,会有如下报错 这里说没有制定classes文件,所以就试试用其他方法生成头文件。在控制台(在项目根目录)输入: 这样,在java目录下,会生成一个.h头文件 第五步:在main文件夹下,新建一个jni文件夹,然后将刚生成的头文件拷贝到该文件夹中 第六步:创建C代码,这个例子就是完成点击按钮,调用本地方法,然后输出C代码中的一个字符串到控制台 第七步:在jni文件夹加入Android.mk文件和Application.mk文件 第八步:在MainActivity中加载模块 第九步:/app/build.gradle的defaultConfig中加入ndk配置;moduleName的值就是Android.mk中LOCAL_MODULE的值 如果是通过第一步Studio自动安装的NDK的话,那么项目的local.properties中会自动加上ndk的路径;如果没有,请务必手动添加 如果这个时候编译整个工程,会报出 这样的错误;这里只要根据提示,在gradle.properties中加入”android.useDeprecatedNdk=true”即可 然后重新编译,即可成功部署。

Android Studio导入aidl

用到aidl了,把这点小经验写上来分享一下~过程很简单的咯~看图~ 第一步:切换到Project视图(这样更容易操作一点) 第二步:在main文件夹上右键创建一个新的aidl文件夹 第三步:右键aidl文件夹创建aidl文件所需的包名 注意保证包名和文件的包名一致~ 第四步:将aidl文件拷入对应包中 第五步:Rebuild工程 工程要Rebuild一下,才能正常使用aidl文件~

Android Studio从SVN检出代码

ADT已经不受宠爱了, 安卓开发者要速速转向谷歌的亲儿子Android Studio. 这篇文章讨论一下如何使用Android Studio从SVN检出代码. PS: 前提是svn中现存代码是基于Android Studio的. 如何导入Eclipse代码, 请参阅 Eclipse项目的导入 开始吧~~ 第一步: 在欢迎页面选择 Check out project from Version Control (如果已经开启了一个项目, 选择File –> Close Project关闭就能看到欢迎页面啦~) 第二步: 选择Subversion 第三步: 选择SVN仓库 (如果还没有SVN仓库, 点击绿色的+添加服务器SVN仓库的地址即可) 选择仓库之后, 点击Checkout 第四步: 选择检出到的目的地文件夹 放哪就随便大家咯~ 选择完目的地文件夹, 点击OK 第五步: 选择导出文件夹位置 Destination一栏, 务必选择带有项目名称的选项; 如果不带项目名称文件夹检出, 就会把项目文件夹下的子文件夹丢到检出目录中, 这样项目一多就不是事儿啦~ Depth中选择infinity, 这个选项就是原先Eclipse当中Recursive的意思 其他选项使用默认就好, 然后点击OK 第六步: 选择JDK版本 根据个人情况进行选择~ 电脑上是1.8的版本, 就选择1.8咯~ 选择完毕点击OK…

Ubuntu 14.04安装Broadcom BCM4352网卡驱动

Linux下的驱动是个那么小小的问题, 就算是Ubuntu这种有着强大驱动支持的衍生版本, 也不免漏掉支持一些”奇葩”硬件~自己给新入手的XPS13安装了Ubuntu 14.04 发现Broadcom BCM4352无线网卡不受内核支持. 此处省略一万字所做出的尝试, 为有意自己在XPS安装Ubuntu的各位献上最终解决方案… 最终解决方案… 只有两步… PS: 该方法经验证在Ubuntu 14.04 Trusty下有效~ 不保证在其他环境下有效~ 进行以下步骤前, 先确保Ubuntu 14.04系统安装无误~ 开始! 第一步,下载dkms_2.2.0.3-2ubuntu3_all.deb依赖包(请酌情下载最新版本);下载broadcom-sta-dkms_6.30.223.248-3_all.deb网卡驱动, 保存到Downloads目录 第二步, 在命令行执行 cd Downloadssudo dpkg -i dkms_2.2.0.3-2ubuntu3_all.debsudo dpkg -i broadcom-sta-dkms_6.30.223.248-3_all.deb 请先安装dkms, 这样才能让broadcom驱动模块被动态编译进现有内核. Voila! 两步走完之后, 就能看到右上角任务栏出现了无线图标, 选择无线网络加入即可~ 血与泪啊, 这两步花了两天的时间…