1.二分类(Binary Classification)
逻辑回归(logistic regression)是一个用于二分类的算法.同样的,我们从一个问题说起,加入你有一张图片作为输入,比如这只猫,如果识别这张图片为猫,则输出标签1作为结果;如果识别不是猫,则输出标签0为结果,现在我们用y来表示输出的结果标签,如下图所示.
通常在计算机中,为了保存一张图片,需要保存三个矩阵,分别对应图片中的红、绿、蓝三种颜色通道,如果你的图片大小为64*64像素,那么你就有三个规模为64*64的矩阵,分别对于图片中红、绿、蓝三种像素的强度值.
此时,为了把这些像素值放到一个特征向量中,我们需要把这些像素值提取出来,然后放如一个特征向量x.如果图片的大小为64*64像素,那么向量x的总维度将会是64*64*3,这是三给像素矩阵中像素的总量.在这个例子中结果为12,288.现在我们用 nx=12,288来表示输入特征向量x的维度.所以在二分类问题中,我们的目标就是学习得到一个分类器,他以图片的特征向量作为输入,然后预测输出结果y为1还是0,也就是预测图片是否有猫.
以下是符号定义:
x:表示一个nx维数据为输入数据,维度为(nx,1);
y:表示输出结果,取值为(0,1);;
(x(i),y(i)):表示第i组数据,可能是训练数据,也可能是测试数据;
X=[x(1),x(2),...,x(m)]:表示所有的训练数据集的输入值,放在一个nx*m的矩阵中,其中m表示样本数目;
Y=[y(1),y(2),...,y(m)]:表示所有训练数据集的输出值,维度为1*m.
python中的shape命令可以很好的用于显示矩阵的规模,即X.shape等于(nx,m),表示这是一个规模为nx乘以m的矩阵;Y.shape等于(1,m),表示这是一个规模为1乘以m的矩阵.
2.逻辑回归(Logistic Regression)
本节我们主要介绍逻辑回归的假设函数(Hypothesis Function).
对于二元分类问题来讲,给定一个输入特征向量X,他可能对应一张图片,现在你想识别这张图片看它是否是一只猫,你想要一个算法能够输出预测,你只能称之为y^,也就是你对实际值 y的估计.换句话说,如果X是表示一张图片(有或没有猫),其实y^就是告诉你这是一张猫的图片的概率有多大。X是表示一个nx维的向量,即相对于有nx个特征的特征向量。我们用w来表示逻辑回归的参数,这也还是一个nx为向量(因为实际上是特征权重,维度和特征向量相同),参数里面还有b,这是一个实数(表示偏差 )。所以给出输入x以及参数w和b之后,我么怎么样产生输出预测值y^,我们通常使用这个公式:。
这个时候我们会得到一个关于输入x的线性函数,但是对于二元分类问题来讲,你是想让y^的值处于0到1之间。而wTx+b的值是从正无穷到 负无穷的数,对于想要的到在0到1之间的概率是没有意义的,所以我们将得到的结果y^放入到sigmoid函数中,将线性函数转变成非线性函数。下面是sigmoid函数的图像和函数:
图像:
函数:
3.逻辑回归的代价函数(Logistic Regression Cost Function)
为什么需要代价函数:为了训练逻辑回归模型w和参数b,我们需要一个代价函数,通过训练代价函数来得到参数w和参数b,在这里我们在回顾一下逻辑回归的输出函数:
为了让模型通过学习调整参数,你需要给予一个m样本的训练集,这会让你在训练集上找到参数w和参数b,来得到你的输出。对训练集的预测值,我们将它写成y^,我们更加希望它接近训练集中的y值。
损失函数又叫做误差函数,是用来衡量算法的运行情况,Loss function:L(y,y^)。
我们通常用这个L称为的损失函数来衡量预测值和实际值有多接近。在逻辑回归中用到的损失函数是:
为什么要使用这个函数作为逻辑损失函数呢?为了更好的理解这个损失函数怎么起作用,我们举两个例子:
在深度学习这门课中有很多的函数效果和现在的这个类似,就是如果y等于1,我们就尽可能让y^变大,如果y等于0,我们就尽可能让y^变大。
同时,我们需要注意的是:损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何,为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函数,算法的代价函数是对m个样本函数求和然后除以m(公式如下):
损失函数只适用与像这个单个训练样本,而代价函数是参数的总代价,所以在训练逻辑回归模型时候,我们需要找到合适的w和b,来让代价函数J的总代价最低。
4.梯度下降法(Gradient Descent)
梯度下降法用来在你的测试集上,通过最小代价 函数J(w,b)来训练参数w和b,如下图所示:
接下来我们对梯度下降法进行形象化说明:
在这个图中,曲面的高度就是J(w,b)在某一点的函数值,我们需要做的就是找到使得代价函数J(w,b)函数值的最小值,对应的参数w和b。
由于逻辑回归的代价函数的特性,我们必须要定义代价函数J(w,b)为凸函数。
初始化w和恶b,可以采用随机初始化的方法,找图像上的任意一点,因为函数是凸函数,所以无论在哪里初始化,应该达到同一点或大致相同的点。
朝最陡的下坡方向走一步,不断的迭代,直到走到全局最优解或接近全局最优解的地方,最终通过以上的方法我们可以找到全局的最优解,也就是代价函数J(w,b)这个凸函数的最小值点。
梯度下降法的细节化说明(仅有一个参数)
假定代价函数J(w)只有一个参数w,即用 一维曲线代替多维曲线,迭代就是不断重复做下图的公式:
:=表示更新参数,a表示学习率(Learing rate),用来控制步长(step),即向下走一步的长度就是函数J(w)对w求导,在代码中我们会使用dw表示这个结果,对于导数更加形象化的理解就是斜率。假设我们一如图点为初始化点,该点的斜率的符号是正的,即,所以接下来会向左走一步。整个梯度下降法的迭代过程就是不断地向左走,直至逼近最小值点。
假设我们一如下图点为初始化点,该点的斜率的符号是负的,即,所以接下来会向右走一步。整个梯度下降法的迭代过程就是不断地向右走,即朝着最小值点方向走。
当有两个参数也是同样地效果,公式如下:
5.逻辑回归中的梯度下降(Logistics Regression Gradient Descent)
我们可以通过计算偏导数来实现逻辑回归的梯度下降算法。这个算法的关键点就是几个重要公式,用来实现逻辑回归梯度下降算法,下面我们举例说明。
假设样本只有两个特征x1和x2,为了计算z,我们需要输入参数w1、w2和b,除此之外还有特征值x1和x2,所以z的计算公式为:z=w1x1+w2x2+b 。
如图:在这个公式的外侧画上长方形,然后计算:,最后计算损失函数。所以为了使得逻辑回归中的最小代价函数L(a,y),我们需要做的仅仅是修改参数w和b的值。
因为我们想要计算出的代价函数L(a,y)的导数,首先我们需要反向计算出代价函数关于a的导数,在写代码的时候我们只需要用da来表示对代价函数求关于a的导数。最终我们求得:
现在我们已经计算出了da,也就是最终输出结果的导数,此时我们可以在反向一步求出dz,也就是代价函数L关于z的导数:,现在进行最后一步反向推导,也就是计算w和b变化对代价函数L的影响,可以用:
这三个公式表示,更进一步化简可得:dw1=x1*dz,dw2=x2*dz,db=dz。
最后我们总结一下单个样本的梯度下降算法中参数更新一次的步骤:使用公式dz=(a-y)计算出dz,使用dw1=x1*dz计算dw1,dw2=x2*dz计算dw2,db=dz来计算db,然后更新w1=w1-adw1,w2=w2-dw2和b=b-db。
那么对于m个训练样本我们应该怎么做呢?
首先,我们需要时刻记住损失函数J(w,b)的定义:,然后我们把上面的公式具体带入到算法当中,我们初始化J=0,dw1=0,dw2=0,db=0
代码流程:
J=0;dw1=0;dw2=0;db=0;
for i = 1 to m
z(i) = wx(i)+b;
a(i) = sigmoid(z(i));
J += -[y(i)log(a(i))+(1-y(i))log(1-a(i));
dz(i) = a(i)-y(i);
dw1 += x1(i)dz(i);
dw2 += x2(i)dz(i);
db += dz(i);
J/= m;
dw1/= m;
dw2/= m;
db/= m;
w=w-alpha*dw
b=b-alpha*db
以上是我们使用for循环来实现算法,实际上,在深度学习算法中使用for循环是一种比较低效的方法,因为通常数据集的大小会很大,,而此时如果使用循环的话必然会 有很大的代价,所以我们用向量化的方法来取代for循环,其实就是线性代数中的向量的内积,具体我们看下面的例子:
for代码:
for i in range(n_x)
z+=w[i]*x[i]
z+=b
向量化代码:
z=np.dot(w,x)+b
最后让我们来表示用伪代码来完成向量化的logistic回归的梯度输出(Vectorizing Logistic Regression‘s Gradient):
Z=wTX+b=np.dot(ww.T,X)+b
A=g(Z)
dZ=A-Y
dw=1/m * X * dZT
db=1/m *np.sum(dZ)
w=w- a*dw
b=b- a*db
tips:如果你想要生成一个1行五列的数组,使用a= np.random. randn(5,1)而不是a=np.random.randn(5),我们也可以很简单的应用a.shape来实现检测。