2019-09-28 12:43:55 duxinshuxiaobian 阅读数 1099
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    40550 人正在学习 去看看 唐宇迪

全文共4431字,预计学习时长9分钟

深度学习是目前在实际数据科学应用中最流行的模型之一。从图像到文本,再到语音/音乐等领域,它都是一个有效的模型。随着使用量的上升,快速且可扩展地实现深度学习变得至关重要。Tensorflow等深度学习平台的兴起可以帮助简化开发人员的实现方式。

在本文中,我们将学习深度学习的工作原理,并熟悉相关术语,例如反向传播和批量大小。我们将实现一个简单的深度学习模型 - 从理论到scratch实现 - 使用python预定义输入和输出,然后使用Keras和Tensorflow等深度学习平台实现相同的模型。

我们使用Keras和Tensorflow 1.x和2.0编写了这个简单的深度学习模型,该模型具有三种不同级别的复杂性和易编码性。

Scratch的深度学习实现

一个简单的多层感知器有4个输入神经元,隐含层有3个神经元,输出层有1个神经元。我们有三个输入数据样本,用表示,三个期望输出数据样本,用表示。因此,每个输入数据样本都有4个特征。

# Inputs and outputs of the neural net:import numpy as
 npX=np.array([[1.0, 0.0, 1.0, 0.0],[1.0, 0.0, 1.0, 1.0],[0.0, 1.0, 0.0, 
1.0]])yt=np.array([[1.0],[1.0],[0.0]])

该神经网络有4个输入神经元,1个隐含层有3个神经元,输出层有1个神经元

图中 x(m)是X的1个样本,h(m)是x(m) 输入的隐含层输出,Wi和Wh为权重。

神经网络(NN)的目标是为给定输入获得权重和偏差,NN提供期望输出。但是,我们事先并不知道什么是适当的权重和偏差,因此我们需要更新权重和偏差,使得NN、和期望的的输出之间的误差最小化。这种用迭代的方式最小化误差过程称为神经网络训练。

假设隐含层和输出层的激活函数都是sigmoid函数。因此,

神经网络的权值大小、偏差以及输入和输出之间的关系

其中,激活函数是sigmoid函数,m是第m个数据样本, yp(m) 是NN输出。

衡量NN输出与期望输出之间差异的误差函数可以用数学方式表示为:

神经网络所定义的误差是平方误差

上述NN的伪代码总结如下:

用于神经网络训练的伪代码

通过伪代码得出,我们需要计算误差(E)相对于参数(权重和偏差)的偏导数。利用微积分中的链式法则,表示如下:

误差函数对权重的导数

在此我们有两种方式可以用来更新反向路径中的权重和偏差(反向路径指更新权重和偏差,从而最小化误差):

1. 使用训练数据的全部个样本

2. 使用一个样本或一簇样本

第一种方式的批量大小是。如果第二种方式使用一个样本来更新参数,则其批量大小是1。因此批量大小代表用于更新权重和偏差的数据样本数量。

从上述神经网络的实现可以得出,关于参数的误差梯度是按符号计算的,其中具有不同的批量大小。

如上述例子所示,基于scratch创建简单的深度学习模型,方法十分复杂。下一节将介绍如何通过深度学习框架实现可扩展且简单的模型。

Keras、Tensorflow 1.x及2.0的深度学习实现

在上一节中,我们运用链式法则计算了误差梯度参数。这不是一种简单或可扩展的方法。同时,我们会在每次迭代时评估偏导数,因此,尽管偏导数的值很重要,但不需要梯度符号。此时Keras和Tensorflow等深度学习框架可以发挥其作用。深度学习框架使用AutoDiff方法对部分梯度进行数值计算。如果你对AutoDiff不熟悉,那么StackExchange就是一个很好的例子。AutoDiff将复杂表达式分解为一组原始表达式,即最多由一个函数调用组成的表达式。由于已知每个单独表达式的区分规则,因此可以以有效的方式计算最终结果。

我们在Keras、Tensorflow 1.x和Tensorflow 2.0中实现了三个不同级别的NN模型:

1. 高级(Keras和Tensorflow 2.0):

高级Tensorflow 2.0,批量大小1

https://github.com/miladtoutounchian/Deep-Learning-/blob/master/TF_v2_HighLevel_batchsize1_train_on_batch.py

2. 中级(Tensorflow 1.x和2.0):

中级Tensorflow 1.x,批量大小1,

https://github.com/miladtoutounchian/Deep-Learning-/blob/master/TF_v1_MediumLevel_batchsize1.py

中级Tensorflow 1.x,批量大小N,

https://github.com/miladtoutounchian/Deep-Learning-/blob/master/TF_v1_MediumLevel_batchsizeN.py

中级Tensorflow 2.0,批量大小1,

https://github.com/miladtoutounchian/Deep-Learning-/blob/master/TF_v2_MediumLevel_batchsize1.py

中级Tensorflow 2.0,批量大小N

https://github.com/miladtoutounchian/Deep-Learning-/blob/master/TF_v2_MediumLevel_batchsizeN.py

3. 初级(Tensorflow 1.x):

初级Tensorflow 1.x,批量大小N

https://github.com/miladtoutounchian/Deep-Learning-/blob/master/TF_v1_LowLevel_batchsizeN.py

代码片段:

在高级实现中,基于model.train_on_batch运用keras和Tensorflow v 2.0实现模型:

# High-Level implementation of the neural net
 in Tensorflow:model.compile(loss=mse,optimizer=optimizer)for _ in
 range(2000):for step, (x, y) in enumerate(zip(X_data,
 y_data)):model.train_on_batch(np.array([x]), np.array([y]))

在Tensorflow 1.x的中级实现中,定义如下:

E = tf.reduce_sum(tf.pow(ypred - Y, 2))optimizer =
 tf.train.GradientDescentOptimizer(0.1)grads =
 optimizer.compute_gradients(E, [W_h, b_h, W_o, b_o])updates =
 optimizer.apply_gradients(grads)

以此确保在for循环中更新需要更新的变量。在中级实现中,梯度及其更新在for循环外部进行定义,内部则为迭代更新。在Tensorflow v 2.x的中级实现中,使用如下:

# Medium-Level implementation of the neural net in Tensorflow#

 In for_loop

with tf.GradientTape() as tape:   x =
 tf.convert_to_tensor(np.array([x]), dtype=tf.float64)   y =
 tf.convert_to_tensor(np.array([y]), dtype=tf.float64)   ypred =
 model(x)   loss = mse(y, ypred)gradients = tape.gradient(loss,
 model.trainable_weights)optimizer.apply_gradients(zip(gradients,model.t
rainable_weights))

在初级实现中,分别更新每个权重和偏差。在Tensorflow v 1.x初级实现中,定义如下:

# Low-Level implementation of the neural net in Tensorflow:E =
 tf.reduce_sum(tf.pow(ypred - Y, 2))dE_dW_h = tf.gradients(E, [W_h])
[0]dE_db_h = tf.gradients(E, [b_h])[0]dE_dW_o = tf.gradients(E, [W_o])
[0]dE_db_o = tf.gradients(E, [b_o])[0]# In for_loop:evaluated_dE_dW_h =
 sess.run(dE_dW_h,                 feed_dict={W_h: W_h_i, b_h: b_h_i,
 W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})            W_h_i =
 W_h_i - 0.1 * evaluated_dE_dW_h            evaluated_dE_db_h = 
sess.run(dE_db_h,                             feed_dict={W_h: W_h_i,
 b_h: b_h_i, W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})
            b_h_i = b_h_i - 0.1 * evaluated_dE_db_h            evaluated_dE_dW_o
 = sess.run(dE_dW_o,                             feed_dict={W_h: W_h_i,
 b_h: b_h_i, W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})
            W_o_i = W_o_i - 0.1 * evaluated_dE_dW_o            evaluated_dE_db_o
 = sess.run(dE_db_o,                            feed_dict={W_h: W_h_i, b_h: b_h_i, 
W_o: W_o_i, b_o: b_o_i, X: X_data.T, Y: y_data.T})    
        b_o_i = b_o_i - 0.1 * evaluated_dE_db_o

如初级实现所述,开发人员可以更好地控制数值运算和计算的每一步。

上述所示,在Scratch的深度学习实现中,即便只是通过使用梯度符号计算建立一个简单的深度学习模型来更新权重和偏差并不是一种简单或可扩展的方法。而使用用于更新权重和偏差的稳定数值梯度计算AutoDiff,深度学习框架可以加速此进程。

留言 点赞 关注

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)

2017-09-27 00:00:00 FnqTyr45 阅读数 2137
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    40550 人正在学习 去看看 唐宇迪


以撩妹为例,5分钟让你秒懂深度学习!

今天,面对 AI 如此重要的江湖地位,深度学习作为重要的一个研究分支,几乎出现在当下所有热门的 AI 应用领域,其中包含语义理解、图像识别、语音识别,自然语言处理等等,更有人认为当前的人工智能等同于深度学习领域。


如果在这个人工智能的时代,作为一个有理想抱负的程序员,或者学生、爱好者,不懂深度学习这个超热的话题,似乎已经跟时代脱节了。



但是,深度学习对数学的要求,包括微积分、线性代数和概率论与数理统计等,让大部分的有理想抱负青年踟蹰前行。那么问题来了,理解深度学习,到底需不需要这些知识?


关于深度学习,网上的资料很多,不过大部分都不太适合初学者。杨老师总结了几个原因:


深度学习确实需要一定的数学基础。如果不用深入浅出地方法讲,有些读者就会有畏难的情绪,因而容易过早地放弃。


中国人或美国人写的书籍或文章,普遍比较难。


深度学习所需要的数学基础并没有想象中的那么难,只需要知道导数和相关的函数概念即可。假如你高等数学也没学过,很好,这篇文章其实是想让文科生也能看懂,只需要学过初中数学。


不必有畏难的情绪,我比较推崇李书福的精神,在一次电视采访中,李书福说:谁说中国人不能造汽车?造汽车有啥难的,不就是四个轮子加两排沙发嘛。当然,他这个结论有失偏颇,不过精神可嘉。


“王小二卖猪”解读深度学习之导数

导数是什么?


无非就是变化率,比如:王小二今年卖了 100 头猪,去年卖了 90 头,前年卖了 80 头。。。变化率或者增长率是什么?每年增长 10 头猪,多简单。


这里需要注意有个时间变量—年。王小二卖猪的增长率是 10头/年,也就是说,导数是 10。


函数 y = f(x) = 10x + 30,这里我们假设王小二第一年卖了 30 头,以后每年增长 10 头,x代表时间(年),y代表猪的头数。

当然,这是增长率固定的情形,而现实生活中,很多时候,变化量也不是固定的,也就是说增长率不是恒定的。


比如,函数可能是这样: y = f(x) = 5x² + 30,这里 x 和 y 依然代表的是时间和头数,不过增长率变了,怎么算这个增长率,我们回头再讲。或者你干脆记住几个求导的公式也可以。



深度学习还有一个重要的数学概念:偏导数


偏导数的偏怎么理解?偏头疼的偏,还是我不让你导,你偏要导?


都不是,我们还以王小二卖猪为例,刚才我们讲到,x 变量是时间(年),可是卖出去的猪,不光跟时间有关啊,随着业务的增长,王小二不仅扩大了养猪场,还雇了很多员工一起养猪。


所以方程式又变了:y = f(x) = 5x₁² + 8x₂ + 35x₃ + 30


这里 x₂ 代表面积,x₃ 代表员工数,当然 x₁ 还是时间。


以撩妹为例,解读深度学习之“偏导数”


偏导数是什么


偏导数无非就是多个变量的时候,针对某个变量的变化率。在上面的公式里,如果针对 x₃ 求偏导数,也就是说,员工对于猪的增长率贡献有多大。


或者说,随着(每个)员工的增长,猪增加了多少,这里等于 35—每增加一个员工,就多卖出去 35 头猪。


计算偏导数的时候,其他变量都可以看成常量,这点很重要,常量的变化率为 0,所以导数为 0,所以就剩对 35x₃ 求导数,等于 35。对于 x₂ 求偏导,也是类似的。


求偏导,我们用一个符号表示:比如 y / x₃ 就表示 y 对 x₃ 求偏导。



废话半天,这些跟深度学习到底有啥关系?当然有关系,深度学习是采用神经网络,用于解决线性不可分的问题。


这里我主要讲讲数学与深度学习的关系。先给大家看几张图:

图1:所谓深度学习,就是具有很多个隐层的神经网络

图2:单输出的时候,怎么求偏导数

图3:多输出的时候,怎么求偏导数


后面两张图是日本人写的关于深度学习的书里面的两张图片。所谓入力层,出力层,中间层,分别对应于中文的:输入层,输出层,和隐层。


大家不要被这几张图吓着,其实很简单,就以撩妹为例。男女恋爱我们大致可以分为三个阶段:


初恋期。相当于深度学习的输入层。别人吸引你,肯定是有很多因素,比如:身高,身材,脸蛋,学历,性格等等,这些都是输入层的参数,对每个人来说权重可能都不一样。


热恋期。我们就让它对应隐层吧!这个期间,双方各种磨合,柴米油盐酱醋茶。


稳定期。对应输出层,是否合适,就看磨合得咋样了。大家都知道,磨合很重要,怎么磨合呢?就是不断学习训练和修正的过程!


比如女朋友喜欢草莓蛋糕,你买了蓝莓的,她的反馈是 negative,你下次就别买了蓝莓,改草莓了。


看完这个,有些小伙可能要开始对自己女友调参了。有点不放心,所以补充一下。撩妹和深度学习一样,既要防止欠拟合,也要防止过拟合。


所谓欠拟合,对深度学习而言,就是训练得不够,数据不足,就好比,你撩妹经验不足。要做到拟合,送花当然是最基本的,还需要提高其他方面,比如,提高自身说话的幽默感等。这里需要提一点,欠拟合固然不好,但过拟合就更不合适了。


过拟合跟欠拟合相反,一方面,如果过拟合,她会觉得你有陈冠希老师的潜质,更重要的是,每个人情况不一样,就像深度学习一样,训练集效果很好,但测试集不行!


就撩妹而言,她会觉得你受前任(训练集)影响很大,这是大忌!如果给她这个印象,你以后有的烦了,切记切记!


深度学习也是一个不断磨合的过程,刚开始定义一个标准参数(这些是经验值,就好比情人节和生日必须送花一样),然后不断地修正,得出图 1 每个节点间的权重。


为什么要这样磨合?试想一下,我们假设深度学习是一个小孩,我们怎么教他看图识字?


肯定得先把图片给他看,并且告诉他正确的答案,需要很多图片,不断地教他,训练他,这个训练的过程,其实就类似于求解神经网络权重的过程。以后测试的时候,你只要给他图片,他就知道图里面有什么了。


所以训练集,其实就是给小孩看带有正确答案的图片,对于深度学习而言,训练集就是用来求解神经网络的权重,最后形成模型;而测试集,就是用来验证模型的准确度。


对于已经训练好的模型,如下图所示,权重(w1,w2…)都已知。

图4

图5


像上面这样,从左至右容易算出来。但反过来,测试集有图片,也有预期的正确答案,要反过来求 w1,w2……,怎么办?

怎么求偏导数?


绕了半天,终于该求偏导出场了。目前的情况是:


我们假定一个神经网络已经定义好,比如有多少层,每层有多少个节点,也有默认的权重和激活函数等。输入(图像)确定的情况下,只有调整参数才能改变输出的值。怎么调整,怎么磨合?


每个参数都有一个默认值,我们就对每个参数加上一定的数值∆,然后看看结果如何?如果参数调大,差距也变大,那就得减小∆,因为我们的目标是要让差距变小;反之亦然。


所以为了把参数调整到最佳,我们需要了解误差对每个参数的变化率,这不就是求误差对于该参数的偏导数吗?


这里有两个点:一个是激活函数,主要是为了让整个网络具有非线性特征。我们前面也提到了,很多情况下,线性函数没办法对输入进行适当的分类(很多情况下识别主要是做分类)。


那么就要让网络学出来一个非线性函数,这里就需要激活函数,因为它本身就是非线性的,所以让整个网络也具有了非线性特征。


另外,激活函数也让每个节点的输出值在一个可控的范围内,计算也方便。


貌似这样解释还是很不通俗,其实还可以用撩妹来打比方:女生都不喜欢白开水一样的日子,因为这是线性的,生活中当然需要一些浪漫情怀了,这个激活函数嘛,我感觉类似于生活中的小浪漫,小惊喜。


相处的每个阶段,需要时不时激活一下,制造点小浪漫,小惊喜。比如,一般女生见了可爱的小杯子,瓷器之类都迈不开步子,那就在她生日的时候送一个特别样式,让她感动得想哭。


前面讲到男人要幽默,这是为了让她笑,适当的时候还要让她激动得哭。一哭一笑,多整几个回合,她就离不开你了。因为你的非线性特征太强了。


当然,过犹不及,小惊喜也不是越多越好,但完全没有就成白开水了。就好比每个 layer 都可以加激活函数,当然,不见得每层都要加激活函数,但完全没有,那是不行的。


关键是怎么求偏导。图 2 和图 3 分别给了推导的方法,其实很简单,从右至左挨个求偏导就可以。相邻层的求偏导很简单,因为是线性的,所以偏导数其实就是参数本身嘛,就跟求解 x₃ 的偏导类似。然后把各个偏导相乘就可以了。


这里有两个点:一个是激活函数,其实激活函数也没啥,就是为了让每个节点的输出都在 0 到 1 的区间,这样好算账,所以在结果上面再做了一层映射,都是一对一的。


由于激活函数的存在,在求偏导的时候,也要把它算进去,激活函数,一般用 sigmoid,也可以用 Relu 等。激活函数的求导其实也非常简单:


求导: f'(x)=f(x)*[1-f(x)]


这个方面,有时间可以翻看一下高数,如果没时间,直接记住就行了。至于 Relu,那就更简单了,就是 f(x) 当 x<0 的时候 y 等于 0,其他时候,y 等于 x。


当然,你也可以定义你自己的 Relu 函数,比如 x 大于等于 0 的时候,y 等于 0.01x,也可以。

什么是学习系数?


另一个是学习系数,为什么叫学习系数?


刚才我们上面讲到∆增量,到底每次增加多少合适?是不是等同于偏导数(变化率)?


经验告诉我们,需要乘以一个百分比,这个就是学习系数,而且,随着训练的深入,这个系数是可以变的。


当然,还有一些很重要的基本知识,比如 SGD(随机梯度下降),mini batch 和 epoch(用于训练集的选择)。


上面描述的内容,主要是关于怎么调整参数,属于初级阶段。上面也提到,在调参之前,都有默认的网络模型和参数,如何定义最初始的模型和参数?就需要进一步深入了解。


不过,对于一般做工程而言,只需要在默认的网络上调参就可以,相当于使用算法;对于学者和科学家而言,他们会发明算法,这有很大的难度。向他们致敬!


End.

来源:数盟


--------------------

黎曼,欧拉,傅里叶竟每每被提及!神秘的群里竟然反复出现应数、建模、数统!里面究竟隐藏着什么秘密?来来来——算法与数学之美数学粉丝群成立啦!

下方高能!!!

数学粉丝qq群号:602146986 。

微信群请扫描下方二维码!

算法数学之美微信公众号欢迎赐稿

稿件涉及数学、物理、算法、计算机、编程等相关领域。

稿件一经采用,我们将奉上稿酬。

投稿邮箱:math_alg@163.com

2019-08-19 15:35:35 duxinshuxiaobian 阅读数 113
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    40550 人正在学习 去看看 唐宇迪

全文共2617字,预计学习时长5分钟

可解释性仍是现代深度学习应用中最严峻的挑战之一。随着计算模型和深度学习研究领域不断进展,如今可建立包含数千隐藏神经层和上千万神经元的复杂模型。尽管在深度神经网络模型上取得巨大进步似乎还算简单,但理解这些模型的创建和推理过程仍是一大难题。最近,Google Brain团队发布了一篇文章,提出通过使用一种叫做概念激活向量的方法从新角度理解深度学习模型的可解释性。

传送门:https://arxiv.org/pdf/1711.11279.pdf?source=post_page---------------------------

可解释性VS准确性

要理解概念激活向量技术,必须先理解深度学习模型中普遍存在的可解释性难题。就目前的深度学习技术而言,保证模型准确性和人为解释模型实现原理之间一直存在阻力。可解释性-准确性之间的矛盾在于能够完成复杂任务和真正理解任务如何完成之间的差别。平衡好准确性和可解释性的关系,也就相当于理解了知识VS控制,性能VS可靠度,效率VS简洁性之间的矛盾。

应该注重取得最好结果还是注重理解结果产生的过程?在任何深度学习场景中,数据科学家都需要考虑这一问题。许多深度学习技术本身十分复杂,即便大多数情况下都得到了准确的最终结果,人们却很难对其进行解释。如果用图表来表示一些广为人知的深度学习模型中准确性和可解释性的关系,将得到如下结果:

深度学习模型的可解释性不是一个简单的概念,应从多个层次看待:

 

要想如上图所示,实现各层面的可解释性,需要一些基本构件。谷歌研究人员在最近发表的文章中列出了他们认为实现可解释性所需的一些基本要素。

谷歌对可解释性的根本原则做出如下解释:

-明白隐藏层的作用:深度学习模型中的许多原理都是在隐藏层中实现的。宏观了解各个隐藏层功能对解释深度学习模型而言至关重要。

-明白节点激活方式:可解释性的关键不是理解单个神经元在网络中的功能,而在于明白相同空间位置中互相联系的各组神经元之间的作用。在拆分神经网络之时,对相互关联的神经元分组将有助于理解该网络的功能。

-明白概念形成过程:了解深度神经中枢网络形成自身概念进而得出最终结果的过程是建立可解释性的另一关键。

以上原则是谷歌最新概念激活向量技术的理论基础。

概念激活向量

根据上文所述,实现可解释性的一个根本方法是根据深度学习模型考虑的输入特征描述其预测过程。一个典型案例是逻辑回归分类,其中系数权重通常被解释为每个特征的重要性。然而,许多深度学习模型基于如像素值之类的参数特征进行操作,这些特征和人类易于理解的高级概念不相对应。此外,一个模型的内部值(如神经中枢激活)似乎也是无法理解的。尽管此类技术能有效测量特定像素区域的重要性,它们却无法与更高级的概念相关联。

概念激活向量的核心原理在于测量模型输出结果中的概念关联性。某一概念的概念激活向量指该概念一组示例的值(如激活)的向量。谷歌研究团队在发布的论文中概述了一种名为概念激活向量测试(TCAV)的新型线性可解释性方法。该方法使用方向导数来量化模型预测对概念激活向量学习的基础高级概念的敏感性。从概念上讲,概念激活向量测试有四个目标:

-可行性:使用者几乎无需具备深度学习知识

-定制性:适配于任何概念(如性别等)且不仅限于训练时使用的概念

-内嵌可读性:无需深度学习模型再次训练或优化。

-全球定量:可使用单个定量度量来解释整类或整组示例,而非解释单一数据输入。

为实现上述目标,概念激活向量测试方法分为三个基本步骤:

1)定义模型的相关概念。

2)理解这些概念预测结果的敏感性。

3)推断各概念对各模型预测类相对重要性,做出全局定量解释。

概念激活向量测试方法的第一步是定义一个感兴趣的概念(概念激活向量).概念激活向量测试通过选择一组代表该概念的例子或者找到一个标有概念的独立数据集来实现这一步。训练线性分类器区分概念示例和任何层中的示例所产生的激活结果,从而使概念激活向量得到学习。

第二步是生成一个概念激活向量测试分数,用于量化预测特定概念的敏感性。要实现这一步骤,可通过使用定向导数来衡量机器学习预测对神经激活层概念方向输入变化的敏感性。

最后一步是评估所学习概念激活向量的全局相关性,以避免依赖不相关的概念激活向量。毕竟,概念激活向量测试技术的一个缺陷是有可能学习无意义的概念激活向量。再者,使用随机选择的一组图像也能产生概念激活向量。基于这样一个随机概念进行的测试毫无意义。为解决这一问题,概念激活向量测试引入了一项统计显着性检验,可以根据随机次数的训练运行来评估概念激活向量,通常为500次。该办法的依据在于有意义的概念激活向量测试分数在训练运行中会表现一致。

概念激活向量测试实际应用

Google Brain团队进行了几项实验来评估与其他可解释性方法相比概念激活向量测试的效率。在最著名的一次测试中,该团队使用了一个显着图,试图通过预测标题或图像的相关性以理解出租车这一概念。显着图的输出结果如下所示:

Google Brain团队使用这些图像作为测试数据集,在Amazon Mechanical Turk上对50人进行了实验。每个工作人员执行针对单个模型的一系列六个任务(3个对象类x 2种显着图类型)。任务顺序随机。每项任务中,工作人员首先看到四个图像及其相应的显着性掩模。然后评估他们认为图像对模型的重要程度(10分制)、标题对模型的重要性(10分制),以及他们对答案的自信程度(5分制)。共评估60个独特的图像(120个独特的显着图)。

实验实况显示,图像概念比标题概念更相关。然而,观察显着性图时,人们认为标题概念更重要(0%噪声标签的模型),或认为两者并无差异(100%噪声标签的模型)。相比之下,概念激活向量测试结果正确地表明图像概念更重要。

概念激活向量测试是最近几年来实现神经网络可解释性的最新方式之一。可以在GitHub上获取这项先进技术的代码,未来这项技术的一些想法也将被主流深度学习框架采用。

传送门:https://github.com/tensorflow/tcav?source=post_page---------------------------

算法的公平性也可以量化?试试这三个指标吧

留言 点赞 关注

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)

2018-01-14 14:08:39 xbinworld 阅读数 24498
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    40550 人正在学习 去看看 唐宇迪

前面大概有2年时间,利用业余时间断断续续写了一个机器学习方法系列,和深度学习方法系列,还有一个三十分钟理解系列(一些趣味知识);新的一年开始了,今年给自己定的学习目标——以补齐基础理论为重点,研究一些基础课题;同时逐步继续写上述三个系列的文章。

最近越来越多的研究工作聚焦研究多层神经网络的原理,本质,我相信深度学习并不是无法掌控的“炼金术”,而是真真实实有理论保证的理论体系;

本篇打算摘录整理一些最最基本的数据知识,包括线性代数,矩阵求导,凸函数等,一方面便于自己平时查用,一方面也给读者想入门的有一个初步的介绍。

1.线性代数

线性代数作为数学中的一个重要的分支,我感觉是一般人学习机器学习或者深度学习算法的必备知识,作为博主这样的CS出身的工科生,学了线性代数、微积分、概率论这些基础课程,平时也就够用了,再复杂的一些数学分支涉及的很少。(这一部分摘录自[1],加上我自己的一些理解)

1.1 标量,向量,矩阵和张量

  • 标量(scalar):一个标量就是一个单独的数。用斜体表示标量,如 sR.
  • 向量(vector):一个向量是一列数,我们用粗体的小写名称表示向量。比如
    x,将向量x 写成方括号包含的纵柱:

    x=x1x2xn

  • 矩阵(matrix):矩阵是二维数组,我们通常赋予矩阵粗体大写变量名称,比如
    A​ 。如果一个矩阵高度是m​,宽度是n​,那么说ARm×n 。一个矩阵可以表示如下:

A=[x11x21x12x22]

  • 张量(tensor):某些情况下,我们会讨论不止维坐标的数组。如果一组数组中的元素分布在若干维坐标的规则网络中,就将其称为张量。用A​ 表示,如张量中坐标为(i,j,k)​的元素记作Ai,j,k

  • 转置(transpose):矩阵的转置是以对角线为轴的镜像,这条从左上角到右下角的对角线称为主对角线(main diagonal)。将矩阵A的转置表示为AT。定义如下: (A)i,j=Aj,i

A=x11x21x31x12x22x32A=[x11x21x21x22x31x32]

1.2 矩阵和向量相乘

  • 矩阵乘法:矩阵运算中最重要的操作之一。两个矩阵A和B 的矩阵乘积(matrix product)是第三个矩阵C 。矩阵乘法中A 的列必须和 B的行数相同。即如果矩阵 A的形状是 m×n,矩阵B的形状是 n×p,那么矩阵 C的形状就是 m×p。即

    C=A×B
    具体的地,其中的乘法操作定义为

    Ci,j=kAi,kBk,j
    矩阵乘积服从分配律,结合律,但是矩阵乘法没有交换律,

A(B+C)=AB+ACA(BC)=(AB)CABBA

  • 点积(dot product)两个相同维数的向量x和y的点积可看作是矩阵乘积 xTy

  • 矩阵乘积的转置 (向量也是一种特殊的矩阵)

    (AB)=BAxy=(xy)=yx

1.3 单位矩阵和逆矩阵
矩阵A的矩阵逆被记作 A1,被定义为如下形式:

A1A=AA1=InInA=A

线性无关(linearly independent): 如果一组向量中的任意一个向量都不能表示成其他向量的线性组合,那么这组向量被称之为线性无关。要想使矩阵可逆,首先必须矩阵是一个方阵(square),即 m=n,其次,所有的列向量都是线性无关的。一个列向量线性相关的方阵被称为 奇异的(singular)。

1.4 范数
需要衡量一个向量的大小,在机器学习中,我们使用称为范数(norm)的函数来衡量向量大小,形式上, Lp范数如下[5]:

||x||p=(i|xi|p)1ppR,p1

范数是将向量映射到非负值的函数。直观上来说,向量 x的范数就是衡量从原点到 x的距离。更严格来说,范数满足下列性质的函数:
f(x)=0x=0f(x+y)f(x)+f(y)αR,f(αx)=|α|f(x)

当 p=2时, L2被称作欧几里得范数(Euclidean norm)。它表示从原点出发到向量x确定的点的欧几里得距离。L2范数常被用来衡量向量的大小,因为它便于求导计算(如对向量中每个元素的导数只取决于对应的元素,但是它也有缺陷,即它在原点附近增长得十分缓慢),可以简单用点积xTx来计算。

当p=1时,称为L1范数,是向量元素绝对值之和;

当p=0时,上面的定义没有包含,称为0范数,定义为向量非零元素的数量

max范数(max norm):这个范数表示向量中具有最大幅度得元素的绝对值,用L范数表示,形式为:

||x||=max|xi|

两个向量的点积(dot product)也可以用范数来表示。具体地
xy=||x||2||y||2cosθ

矩阵的范数(matrix norm)具体请参考[6],最常用的就是 Frobenius norm

||A||F=(ij|aij|2)1/2

1.5 特殊类型的矩阵和向量

  • 对角矩阵 (diagonal matrix) 只在主对角线上含有非零元素,其它位置都是零。矩阵D是对角矩阵,当且仅当 ∀i≠j,Di,j=0,用 diag(v)表示一个对角元素由向量v中元素给定的对角矩。对称(symmetric) 矩阵是任意转置和自己相等的矩阵: A=A.

  • 单位向量(unit vector) 是具有单位范数(unit norm) 的向量:||x||2=1

  • 正交矩阵(orthonormal matrix) 是指行向量是标准正交的,列向量是标准正交的方阵:
    如果xy=0,那么向量 x和向量 y互相正交(orthogonal)。如果两个向量都有非零范数,那么表示这两个向量之间的夹角是90度。在Rn 中,至多有n个范数非零向量互相正交。如果这些向量不仅互相正交,并且范数都为1那么我们称它们是标准正交(orthonormal) 。
    AA=AA=IA1=A

    所以正交矩阵受到关注是因为求逆计算代价小。

1.6 特征分解
许多数学对象可以通过将它们分解成多个组成部分,或者找到它们的一些属性而被更好地理解,这些属性是通用的,而不是由我们选择表示它们的方式引起的。就像我们可以通过分解质因数来发现一些关于整数的真实性质,我们也可以通过分解矩阵来获取一些矩阵表示成数组元素时不明显的函数性质。

特征分解(eigendecomposition) 是使用最广的矩阵分解之一,即我们将矩阵分解成一组特征向量和特征值。方阵A的特征向量(eigenvector)是指与A相乘后相当于对该向量进行缩放的非零向量v:

Av=λv

标量λ被称为这个特征向量对应的特征值(eigenvalue);如果v是A的特征向量,那么任何放缩后的向量sv,sR,s0也是A的特征向量并且其与v 有相同的特征值。所以我们通常只考虑单位特征向量。

假设矩阵A有n个线性无关的特征向量{v1,v2,...,vn},对应的特征值是{λ1,λ2,...,λn},我们将特征向量连成一个矩阵,使得每一列是一个特征向量:

V={v1,v2,...,vn}
类似地,特征值连成一个向量:
λ=[λ1,λ2,...,λn]

因此A的特征分解(eigen-decomposition)可以记作

A=Vdiag(λ)V1

上面我们构建具体特定的特征值和特征向量,能够使我们在目标方向上延伸空间。我们也常常希望将矩阵分解(decompose) 成特征值和特征向量。这样可以帮助我们分析矩阵的特定性质,就像质因数分解有助于我们理解整数。

并不是所有的方阵都可以被对角化,这里主要考虑对称矩阵(A=AT)的特征分解。如果一个对称矩阵的特征值都不相同,则其相应的所有特征向量正交

VVT=VTV=I

A=VΛVT=[v1,v2,,vn]λ1λnvT1vT2vTn=i=1nλivivTi

其中V是A的特征向量组成的正交矩阵,Λ是对角矩阵。因为V是正交矩阵,所以可以将A看作是沿方向vi延展λi倍的空间。如下图所示:
这里写图片描述

1.7 矩阵的迹
矩阵的迹定义是矩阵对角元素的和:

Tr(A)=iAi,i

标量的迹是它本身:a=Tr(a)。迹运算因为很多原因而受到关注。若不使用求和符号,有些矩阵运算很难描述,而通过矩阵乘法和迹运算符号,可以进行清楚地表示。例如,迹运算提供了另一种描述矩阵Frobenius 范数的方式:

||A||F=Tr(AA)

用迹运算表示式,使我们可以用很多有用的性质来操纵表示式。例如迹运算在转置下是不变的:

Tr(A)=Tr(A)

矩阵乘积的迹可以按顺序调换矩阵的位置:

Tr(ABC)=Tr(BCA)=Tr(CAB)

1.8 二次型(Quadratic Form)
给定矩阵ARm×n,函数

xTAx=xixjaij

被称为二次型。如果对于所有xRn,有xTAx0,则为半正定矩阵,此时λ(A)0.如果对于所有xRn,有xTAx>0,则为正定矩阵,此时λ(A)>0.

2. 矩阵求导, 凸函数

下一篇特别写一下求导,以及凸优化的基本概念,这些都是机器学习基本的知识。本篇就到这里。

未完待续…

[1] http://blog.csdn.net/u010976453/article/details/54342895
[2] http://blog.csdn.net/u010976453/article/details/78482502
[3] http://blog.csdn.net/u010976453/article/details/54381248
[4] Jacobian矩阵和Hessian矩阵 http://jacoxu.com/jacobian%e7%9f%a9%e9%98%b5%e5%92%8chessian%e7%9f%a9%e9%98%b5/
[5] https://en.wikipedia.org/wiki/Norm_(mathematics)
[6] https://en.wikipedia.org/wiki/Matrix_norm
[7] 机器学习中的线性代数之矩阵求导 http://blog.csdn.net/u010976453/article/details/54381248
[8] 牛顿法与Hessian矩阵http://blog.csdn.net/linolzhang/article/details/60151623

2019-05-18 23:08:19 LXYTSOS 阅读数 214
  • 机器学习&深度学习系统实战!

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程内容涉及回归算法原理推导、决策树与随机森林、实战样本不均衡数据解决方案、支持向量机、Xgboost集成算法、神经网络基础、神经网络整体架构、卷积神经网络、深度学习框架--Tensorflow实战、案例实战--验证码识别、案例实战--人脸检测。 专属会员卡优惠链接:http://edu.csdn.net/lecturer/1079

    40550 人正在学习 去看看 唐宇迪

人工智能深度学习、机器学习 公众号:机器工匠

机器工匠

学习目标:

  • 理解Pytorch 的 Tensor库,以及神经网络。
  • 训练一个简单的图像分类网络。

假设已经了解numpy的基本用法,并确保已经安装好torch和torchvision。

什么是Pytorch

Pytorch是一个基于Python的科学计算包,用于以下两个目的:

  1. 代替NumPy,使用GPU的加速能力。
  2. 用于提供最大灵活性和速度的深度学习研究平台。

张量(Tensors)

张量与NumPy的数组类似,但是张量可以用在GPU上用来加速计算。

现在我们用Pytorch构造一个未经初始化的5×3的矩阵:

x = torch.empty(5, 3)
print(x)

结果:

tensor([[0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 0.0000e+00, 0.0000e+00],
        [0.0000e+00, 7.6231e-43, 0.0000e+00],
        [0.0000e+00, 2.9966e+32, 0.0000e+00]])

构造一个随机初始化的矩阵:

x = torch.rand(5, 3)
print(x)

结果:

tensor([[0.4140, 0.7152, 0.0888],
        [0.6878, 0.9607, 0.2579],
        [0.0088, 0.5816, 0.1782],
        [0.3815, 0.6752, 0.9996],
        [0.4057, 0.3032, 0.8977]])

用0初始化矩阵,并且数据类型为long:

x = torch.zeros(5, 3, dtype=torch.long)
print(x)

结果:

tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])

直接从数据中构造张量:

x = torch.tensor([5.5, 3])
print(x)

结果:

tensor([5.5000, 3.0000])

从现有tensor构造另外一个tensor,这会重用输入tensor的一些属性,比如数据类型,除非用户指定另外的值。

x = x.new_ones(5, 3, dtype=torch.double)      # new_* 方法接收tensor大小参数
print(x)

x = torch.randn_like(x, dtype=torch.float)    # 重载数据类型!
print(x)                                      # 结果有相同的大小

结果:

tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 0.6743, -0.3788,  0.7561],
        [-0.7612, -1.6943, -1.2451],
        [ 0.6169, -1.1207, -1.1664],
        [ 0.4309,  1.3055, -0.0481],
        [ 0.7891, -1.7696,  1.4875]])

获取tensor的大小:

print(x.size())

结果:

torch.Size([5, 3])

注意:torch.Size实际上是一个tuple,因此它支持所有的tuple操作。

操作(Operations)

操作有许多种语法,下面将展示操作的几种语法。

加法:语法一

y = torch.rand(5, 3)
print(x + y)

结果:

tensor([[1.2953, 0.3779, 0.9404],
        [0.8671, 0.5968, 0.7860],
        [1.3698, 1.2983, 1.1537],
        [0.3706, 0.6296, 0.7085],
        [0.8819, 0.8260, 0.9962]])

加法:语法二

print(torch.add(x, y))

结果:

tensor([[1.2953, 0.3779, 0.9404],
        [0.8671, 0.5968, 0.7860],
        [1.3698, 1.2983, 1.1537],
        [0.3706, 0.6296, 0.7085],
        [0.8819, 0.8260, 0.9962]])

加法:将结果存入另外一个tensor

result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)

结果:

tensor([[1.2953, 0.3779, 0.9404],
        [0.8671, 0.5968, 0.7860],
        [1.3698, 1.2983, 1.1537],
        [0.3706, 0.6296, 0.7085],
        [0.8819, 0.8260, 0.9962]])

加法:in-place(在被加数上加上加数,因此会改变被加数的值)

# 把x加在y上
y.add_(x)
print(y)

结果:

tensor([[1.2953, 0.3779, 0.9404],
        [0.8671, 0.5968, 0.7860],
        [1.3698, 1.2983, 1.1537],
        [0.3706, 0.6296, 0.7085],
        [0.8819, 0.8260, 0.9962]])

注意:任何带有下划线(_)的操作,都会改变tensor的值,比如x.copy_(y)x.t_() 都会改变x的值。

在tensor上还可以尽情使用类似NumPy的索引方法:

print(x[:, 1])

结果:

tensor([0.1801, 0.1028, 0.7038, 0.3089, 0.1738])

使用torch.view来改变tensor大小:

x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  # -1表示这个维度的数值通过其他维度推算而出
print(x.size(), y.size(), z.size())

结果:

torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

如果tensor中只有1个值,那么通过.item()可以取得:

x = torch.randn(1)
print(x)
print(x.item())

结果:

tensor([0.3665])
0.36647817492485046

对接NumPy

下面介绍Torch Tensor 和 NumPy之间如何相互转换。
Torch Tensor和NumPy会共享数据底层的内存存储位置,所以修改其中一个也会改变另外一个的值。

Torch Tensor转成NumPy数组:

a = torch.ones(5)
print(a)

结果:

tensor([1., 1., 1., 1., 1.])
b = a.numpy()
print(b)

结果:

[1. 1. 1. 1. 1.]

现在我们改变tensor中的值,看看NumPy数组中的值是什么:

a.add_(1)
print(a)
print(b)

结果:

tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]

从结果可以看出,在tensor上加上了1,由它转成的NumPy数组上的数值也随之修改了。

NumPy数组转Torch Tensor

和上面一样,由NumPy数组生成的Tensor,如果修改了数组的值,对应的Tensor也会随之修改:

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)

结果:

[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)

CPU上的Tensor,除类型为CharTensor之外,都能和NumPy互转。

CUDA Tensors

通过.to方法可以将tensor移到任何CUDA设备上:

# 如果支持CUDA设备
# 使用 ``torch.device`` 将tensor移入或移出GPU
if torch.cuda.is_available():
    device = torch.device("cuda")          # CUDA设备对象
    y = torch.ones_like(x, device=device)  # 直接在GPU上创建
    x = x.to(device)                       # 或者使用 ``.to("cuda")``将tensor放到GPU上
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # ``.to`` 也能同时修改数据类型!

结果:

tensor([-0.7816], device='cuda:0')
tensor([-0.7816], dtype=torch.float64)

机器工匠

深度学习

阅读数 7

没有更多推荐了,返回首页