2.1 二分分类
-定义:对某个事件或者事物进行“是”或者“否”的判断,即可表示为如“0”和“1”两种数据形式。
-数学定义:
对某个事件的结果y进行判断
y∈{0,1}.
需要有一个期望值,使得:
0⩽⩽1.
最后根据期望值hθ(x)与0.5的大小,输出结果
引用文献:https://blog.csdn.net/mathlxj/article/details/81490288
-例子:对一张猫的图片判断是否是猫。
具体的判断方法为:利用图片中的各个像素点的三原色(红、绿、蓝)的亮度值来表示图片的特征,并且将这些亮度值转换为n维特征向量作为算法的输入值,最后利用逻辑回归(logistic回归)算法等各种算法判断出是否为猫的图片,最后给出对应的结果。
简单点说,分析图片三原色亮度值 → 获取特征向量作为输入 → logistic回归算法进行运算 → 输出判断结果
-常用符号:
符号 | 含义 | 作用 |
---|---|---|
x | nx维特征向量 | 常用于表示图片的特征 |
或 | 输入特征向量维度 | |
y | 预测结果 | 二分类中用0或1表示结果 |
(x,y) | 一个单独的样本 | 训练集的一个成员 |
一个训练集中的第i个样本 | 区分训练集中的每个样本 | |
m或者m_train | 训练集样本个数 | |
大写X表示训练集中所有样本的输入特征向量的矩阵集合 | m列nx行,作为输入矩阵 | |
训练集样本预期值矩阵 | 1*m矩阵 | |
sigmoid()函数对于样本i计算值 | 常用于表示样本i的计算值 | |
表示第i层卷积层的参数W的特征向量 | 常用于sigmoid()函数的计算 | |
对样本输入的预测向量 | ||
损失函数 |
需要注意,矩阵X不能用特征向量横向集合而成,即不能写成如下形式:
(错误)
-多类分类:本质上是在二分分类上的拓展,讲判断结果分成了更多的部分。例如,识别水果的种类是苹果还是西瓜,或者是香蕉。
2.2-2.3 logistic回归和损失函数
-定义:利于一定的参数,对特征向量进行一定的计算,从而得出判断结果。
-相关函数:
1.线性回归:
a. 函数形式: y = ;
T为转置符,交换特征向量的行和列。
b. 参数:w,b
w和b参数常相互独立的进行分开分析(在后面的求导中也是分开求导以及分别改变和优化自身的值)
c. y范围 :大于(0,1)
由于这个范围大于(0,1),并不符合当前判断正误的场景(即0或者1的场景)。所以为了保证y的值在0和1的范围内,需要使用sigmoid()函数将y转化到0到1的范围内。
为了容易区分,将线性函数的输出值y改为z,即 z = wx + b,并且将z作为sigmoid(z)函数的输入。
2.sigmoid函数:
a. 表达式:
b.函数图像:
当z越大,y的值越接近于1,当z越小,y的值越接近于0。
3.损失函数:
a.定义:对当前输出y和训练样本的预期值之间的误差的计算,进而用于修正函数的各种参数(如前面线性回归中的w和z)。
损失函数也常被称为误差函数。
损失函数的计算结果越小说明参数越准确。
b.常见的损失函数:
是训练样本的预期值,y是计算值。
该损失函数不常用,因为可能会出现多个局部最低值(例如sin函数),不利于梯度下降法对参数的修正。
该函数为常用的损失函数。
当预期值为1,即=1,化简得 ,要使的值尽可能的小,则需要使得 尽可能的大,即y要尽可能的大,因为小于等于1,所以当无限逼近1时,损失函数输出值越小,模型准确率越高。
同理,当预期值为0,即=0,化简得 ,要使的值尽可能的小,则需要使得 尽可能的大,即要尽可能的小,因为大于等于0,所以当无限逼近0时,损失函数输出值越小,模型准确率越高。
4.成本函数
a.定义:即一个训练集中所有样本的损失函数输出值的平均值,用于衡量当前模型的参数的准确性。平均值越小,参数越准确。
b.公式:
2.4 梯度下降法
a.定义:通过对参数(如w,b)进行求导,用于训练模型中的各种参数(如线性回归的w和b参数),从而达到成本函数值的最低点(也就是函数图像的最低点)。
b.函数图像:
在图中,x和y轴分别为需要训练的参数w和b(参数越多时维数越高),z轴为J(w,b)的值
c.具体操作方式:
在logistic回归当中参数进行任意初始化后,进行一次logistic回归计算,并且计算出当前J(w,b)的公式和值,并且分别对公式进行关于不同参数的导数,进而求出斜率最低的方向,即再图像中为当前点最陡的方向,再向这个方向移动一定的距离(这个距离按照学习率,也就是步长决定),具体的移动方法就是使用变化函数改变参数的值,也就是对参数进行优化,并且不断重复上述过程,从而达到最优点(损失函数最低点)。
d.变化函数:(以参数w为例):
为更新w的值
为学习率,代表着步长,控制着每次迭代的移动长度,学习率越大,步长越大
:为J进行关于w的导数,后面常用直接表示
e.过程图示:
2.5.1 导数
导数定义
一、导数第一定义
设函数 y = f(x) 在点 x0 的某个邻域内有定义,当自变量x 在 x0 处有增量△x ( x0 + △x 也在该邻域内 ) 时相应地函数取得增量 △y = f(x0 + △x) - f(x0) 如果 △y 与 △x 之比当 △x→0 时极限存在则称函数 y = f(x) 在点 x0 处可导,并称这个极限值为函数 y = f(x) 在点 x0 处的导数记为 f'(x0) ,即导数第一定义。
二、导数第二定义
设函数 y = f(x) 在点 x0 的某个邻域内有定义当自变量x 在 x0 处有变化 △x ( x - x0 也在该邻域内 ) 时相应地函数变化 △y = f(x) - f(x0) 如果 △y 与 △x 之比当 △x→0 时极限存在则称函数 y = f(x) 在点 x0 处可导并称这个极限值为函数 y = f(x) 在点 x0 处的导数记为 f'(x0) ,即导数第二定义。
几何意义
函数y=fx在x0点的导数f'x0的几何意义表示函数曲线在P0[x导数的几何意义0fx0] 点的切线斜率。
导数的几何意义是该函数曲线在这一点上的切线斜率。
导数计算公式
这里将列举六类基本初等函数的导数:
1.常函数即常数y=c(c为常数) y'=0
2.幂函数y=xn,y'=n*x(n-1)(n∈R)
基本导数公式3指数函数y=ax,y'=ax * lna
4对数函数y=logaX,y'=1/(xlna) (a>0且a≠1,x>0)
5.三角函数
(1)正弦函数y=(sinx y'=cosx
(2)余弦函数y=cosx y'=-sinx
(3)正切函数y=(tanx y'=1/(cosx)^2
(4)余切函数y=cotx y'=-1/(sinx)^2
6.反三角函数
(1)反正弦函数y=arcsinx y'=1/√1-x^2
(2)反余弦函数y=arccosx y'=-1/√1-x^2
(3)反正切函数y=arctanx y'=1/(1+x^2)
(4)反余切函数y=arccotx y'=-1/(1+x^2)
偏导数
在数学中,一个多变量的函数的偏导数,就是它关于其中一个变量的导数而保持其他变量恒定(相对于全导数,在其中所有变量都允许变化。
偏导数几何意义
表示固定面上一点的切线斜率。
偏导数 f'x(x0,y0) 表示固定面上一点对 x 轴的切线斜率;偏导数 f'y(x0,y0) 表示固定面上一点对 y 轴的切线斜率。
高阶偏导数:如果二元函数 z=f(x,y) 的偏导数 f'x(x,y) 与 f'y(x,y) 仍然可导,那么这两个偏导函数的偏导数称为 z=f(x,y) 的二阶偏导数。二元函数的二阶偏导数有四个:f"xx,f"xy,f"yx,f"yy。
注意:
f"xy与f"yx的区别在于:前者是先对 x 求偏导,然后将所得的偏导函数再对 y 求偏导;后者是先对 y 求偏导再对 x 求偏导。当 f"xy 与 f"yx 都连续时,求导的结果与先后次序无关。
2.5.2 链式法则
复合函数对自变量的导数等于已知函数对中间变量的导数乘以中间变量对自变量的导数--称为链式法则。
链式法则(chain rule)是微积分中的求导法则,用以求一个复合函数的导数。所谓的复合函数,是指以一个函数作为另一个函数的自变量。如设f(x)=3x,g(x)=x+3,g(f(x))就是一个复合函数,并且g′(f(x))=3。若h(x)=f(g(x)),则h'(x)=f'(g(x))g'(x)。
链式法则用文字描述,就是“由两个函数凑起来的复合函数,其导数等于里边函数代入外边函数的值之导数,乘以里边函数的导数。
2.6.1 计算图
计算图是用箭头画出来的,从左到右的计算。以下会以具体函数J=3(a+bc)为例。
如图所示,先计算出bc的数值,并将其存在变量u中,之后计算a+u,并将其存在变量v中,之后计算3*v,计算结果即为变量J 的数值。从左到右,箭头表示出了计算的顺序。
2.6.2 计算图的导数运算
那么如何计算J的导数呢?如图中所示:
结合链式法则,从最右侧算起,dJ/dv=3,故dJ=3dv。dJ/da=dJ/dvdv/da=31=3;这个过程其实就是反向传播。那dJ/du是多少呢?根据链式法则,从图中右侧向左计算,dJ/du=dJ/dvdv/du=31=3。同理可知,dJ/db=dJ/dvdv/dudu/db=31c=6;dJ/dc=dJ/dvdv/dudu/dc=313=9。
2.7.1 logistic回归中的梯度下降法
logistic回归的公式如下图所示,只考虑单个样本的情况,损失函数为L(a,y),a是logistic回归的输出,y为样本的基本真值标签值,该样本的偏导数流程图如下图所示。
假设样本只有两个特征值x1和x2,为了计算Z,我们需要输入参数w1和w2和b,在logistic回归中,我们要做的就是变换参数w和b的值,来最小化损失函数。首先,我们需要向前一步,先计算损失函数的导数,计算函数L关于a的导数,在代码中,只需要使用da来表示这个变量;之后,再向后一步,计算dz,dz是损失函数关于z的导数,向后传播的最后一步,w和b需要如何变化,关于b的求导:db=dz=a-y。因此,关于单个样本的梯度下降法,所需要做的就是使用这个计算公式计算dz,然后计算dw1、dw2、db,然后更新w1为w1减去学习率乘以dw1;更新w2为w2减去学习率乘以dw2;更新b为b减去学习率乘以db,这就是单个样本实例的一次梯度更新步骤。
2.8.1向量化
向量化代码示例
import numpy as np
a=np.array([1,2,3,4])
import time
a=np.random.rand(1000000)
b=np.random.rand(1000000)
tic=time.time()
c=np.dot(a,b)
toc=time.time()
print("Vectorized version:"+str(1000*(toc-tic))+"ms")
c=0
tic=time.time()
for i in range(1000000):
c+=a[i]*b[i]
toc=time.time()
print (c)
print("for loop:"+str(1000*(toc-tic))+"ms")
结果如下
向量化作用
相比于显式的for循环,向量化可以大大缩短数据的运算时间,得到同样的结果,使用for循环所花费时间是将代码向量化后运行时间的近300倍
GPU和CPU的对比
GPU为图像处理单元,CPU为中央处理器。两者都有并行化指令,有时称为SIMD指令(单指令多数据流),这能够让python使用其中的内置函数(可以去掉显式for循环的函数,如:numpy),GPU更为擅长运用SIMD指令,但CPU也同样可以实现。
2.8.2向量化代码示例
v和u都为n维向量,若要实现如下转化
在不使用for循环的条件下,使用向量化
代码如下
import numpy as np
from numpy import *
b = zeros((5, 2)) # 先创建102的一个数组,里面元素都为0
a = matrix(b) # 转化为102的矩阵
print(a)
u = zeros((5,2))
m = matrix(u)
u=exp(a)
print(u)
结果如下:
2.8.3初步向量化logistic函数
若用如下程序计算logistic回归导数
该程序实际包含两个for循环,第一个for循环即第二行的“for”,第二个for循环。在程序中,为以下的这一部分
即如果特征不止2个,有n个的话,则需重复执行该步骤n次
现用向量化的方法去掉第二个for循环,
将dw通过转化为初始值为0的n*1维的向量
则原程序中的部分可取缔。
原程序的
可以用代替。
原程序的
可以用代替。
以此去掉了第二个for循环,通过向量化的方法,使程序得到了初步的简化。
高效计算激活函数
已知函数和,可以利用向量的方法对数据进行高效计算
首先,将所有训练样本(m个n维的向量)横向堆叠得到一个n*m的矩阵X,以此作为训练输入
其中,X矩阵如下
为第一个训练样本的向量,依此类推
再定义一个1*m的矩阵Z,如下
定义1*m矩阵如下
定义矩阵A如下
则高效计算得出:
在python中的操作
调用numpy库,定义向量和矩阵后,使用z=np.dot(w.T,x+b)语句进行计算,其中python自动将b扩展为1*m的向量(python的“广播”)
调用sigmoid函数,由计算.....
2.8.4高度向量化logistic
定义X矩阵如下
定义矩阵Y如下
定义矩阵A如下
定义矩阵dz如下
有.....
则高度向量化后,程序如下
在python中,调用numpy库(np)
则矩阵Z可用一行代码
Z计算得出
db可用一行代码
计算得出
2.9.1 关于python / numpy向量的说明
默认以下的向量指的是np.array,直译是数组,但是在神经网络的项目中称为向量是更符合的。以下将对其的一些概念做介绍。
轴(axis)
对于array.shape形如 (a, b, c, ...) 的数组,a是其第0轴,b是第1轴,以此类推。数轴简单,但这些轴有什么意思?
对于shape为 (x, y) 的array,0轴就是行的轴,遍历该轴可以遍历所有行;1轴是列的轴,遍历该列可以遍历所有列。但是为什么是这样?
a[x][y]我们都懂,是访问数组a的第x行,第y列。那么轴的概念就在于,搭建一个坐标系(二维的是xOy坐标系),可以用坐标轴上的数表示数组的任意一个数。在这里,x就是a[x][y]在0轴的位置,y是在1轴的位置。那么自然而然0轴对应的是行号的轴,1轴对应的是列号的轴。对于有更多轴(秩更高)的数组来说这样解释同样是合适的。
了解了轴的概念之后,那就应该也了解函数np.sum中参数axis的含义了:沿着(遍历)某一个轴进行求和。对于其他含义该参数的函数来说,也是遍历该轴的意思。
维数(dimension / dim)
我曾经在入门的时候遇到了这样一个难题:
一个博主说 np.zeros((1000,))是获得一个1000维的向量。
我当时就懵了,1000维?一张图片才3维,就算所有图片叠在一起也才4维,为什么要1000维?后来才知道此维非彼维:“维”指的是一个轴的“大小”(取值范围),而不是接下来要讲的秩的含义。对“维”的误解主要出自我们一般称a[][] 为二维数组,b[][][]为三维数组之类的说法。不过在真正了解维数/dim的定义之后就基本不会再有误解了。
秩(rank)
在一些论文中,可能会出现这个单词。而且如果用的是翻译软件进行阅读,很有可能被翻译为其他东西而影响阅读,故特地标明了对应的英文rank。
秩指的是一个向量的轴的数量。秩0是单个数字,秩1是[]向量,秩2是[][]向量,以此类推。
或许有的同学在学线性代数时学过秩这个概念,不过又是此秩非彼秩。
示例代码
a = np.array([[1, 2],
[3, 4],
[5, 6]]
)
b = np.sum(a, axis=0)
# b is [9, 12]
c = np.sum(a, axis=1)
# c is [3, 7, 11]
你可能也发现了一个细节:sum之后降秩了。如果不想这么做,可以传多一个参数keepdims
b = np.sum(a, axis=0, keepdims=True)
# b shape (1, 2)
这样就可以避免可能由于降秩而带来的bug。
2.9.2 Python中的广播
Python中的广播(broadcasting),是一种自动将“低秩”向量拓展到高秩向量,以便与高秩向量进行逐元素运算(+-*/)的机制。
a = 3
b = np.array([[1, 2],
[3, 4],
[5, 6]]
)
c = b + a
# c = a + b 结果也一致
print(c)
# c is [[4, 5], [6, 7], [8, 9]]
值得注意的是,这个“低秩”并不一定是真正的低秩。
广播机制的规则
- 假设低秩向量shape为(a, b),高秩向量shape为(a, b, c, d, ...)或(..., c, d, a, b)。即高秩向量shape的最前面或者最后面“包含”低秩向量的shape,则可以进行广播。
- 两个同秩向量,若对应的部分轴(不要求连续)的维数相等,且维数不同的轴,其中一个向量(不一定总是同一个向量)的维数为1,则可以进行广播。
- 单个实数x(秩0),可以和任意向量广播。
广播可以理解为通过复制操作,将低维的轴的维数增加到和高秩向量一致。
示例代码
a = np.zeros((3, 4))
b = np.zeros((1, 2, 3, 4))
t = a + b # 可以广播
c = np.zeros((3, 4, 5, 6, 7))
t = a - c # 可以广播
d = np.zeros((1, 2, 3, 4, 5, 6))
t = a * d # 不可以广播
e = np.random.randn(1, 1, 2, 1, 4, 1)
f = np.random.randn(7, 6, 2, 3, 4, 8)
t = e / f # 可以广播
g = np.random.randn(5, 6, 1, 3, 1, 8)
t = e + g # 可以广播
2.9.3 Jupyter / Ipython笔记本快速指南
本文参考了Jupyter Notebook介绍、安装及使用教程,提取了其中的一部分,适用于只是想快速运行python代码、验证自己的想法的同学。如果想了解过多细节,可以参考原文。
安装
介绍两种安装方式,分别对应到安装了anaconda和万能的场合
方法一
安装了anaconda的话,常规来说自带Jupyter。如果没有,尝试如下指令:
conda install jupyter notebook
方法二
只要你安装了python(版本支持前提下)就能安装的方法(win10):
打开cmd(不知道如何打开可以搜索),输入
pip install jupyter
一般来说,会自动安装到目录:...\Python\Python36\Scripts\ 。
具体安装到了哪,要看你的python安装到了哪。然后此时你可以按照下一步运行jupyter;如果提示没有这个命令,则是环境变量的问题,解决办法:
- 右键我的电脑->属性->高级系统设置->环境变量
- 双击第一个窗口 用户变量 下的Path->新建
- 将jupyter安装的目录 “...\Python\Python36\Scripts” 复制到此处。连点ok。完成。
打开运行
打开cmd,输入 jupyter notebook,回车。然后顺利的话会弹出一个游览器,先别急着关掉cmd,关掉的话你的jupyter也会一起“关掉”的。
点击右边的new->python3 ,然后会打开/跳转一个新页面,于是就可以愉快滴快速验证代码啦!
简单的使用教程
一开始只有一个 In[] ,你可以输入代码,回车键输入下一行,并且一个In可以视为一个“块”,在执行时是一个块一个块执行的。
输入代码之后如果想要运行,用 shift+enter(回车)即可。然后回到刚刚提到的块问题,如果你后面的块依赖前面的块的代码,那么在修改前面的块的代码之后,需要将“受到牵连”的所有块重新执行,才能将结果更新到后面的块,否则输出是不会自动改变的。
在运行之后,有时候会有输出块 Out[] ,有时候没有。这个取决于该块中最后一句代码是否有返回值,有则显示返回值内容,否则不显示任何东西。对于print显示的内容,将在块正下方的空白处显示,而不是在 Out[] 中显示。
2.9.4 logistic损失函数的解释
首先,要知道我们的logistic回归在做什么:“拟合”一个函数,该函数对于输入图形x,给出概率p(y|x),其中p(y|x)是图中有猫的概率。
那这个函数可以写成:
a, y=1
1-a, y=0
其中a是logistic回归的输出,也即y-hat(y帽),y的预测值。
更进一步,可以写成:
那么我们的任务就成了找出一组权值w和偏置b,使得p(y|x)最大。有没有让你想起来最大似然估计?没错,就是差不多的任务。那么对数似然函数可以写作:
我们目标就是让上面的那个函数取最大值。再加个负号,改为取最小值:
于是,我们的损失函数(loss)就定义为了上式。
似然和概率
既然提到了最大似然估计,那就提提似然和概率的区别:
简单来讲,似然与概率分别是针对不同内容的估计和近似。概率(密度)表达给定θ下样本X=x的可能性,而似然表达了给定样本X=x下参数θ=θ1(相对于另外的参数取值θ2而言)为真实值的可能性