因变量多分类logistic回归分析,多分类logistic回归分析结果解读
目录
二元分类
逻辑回归
价值函数
梯度下降
逻辑回归中的梯度下降
…向量化…
Python代码
二元分类
二元分类是监督学习中分类问题的基本应用。一般来说,监督学习意味着训练集具有正确的标签。比如你要根据房子的大小、卧室数量等特征来预测房价,你的训练集除了要有房子的特征,还要有这些房子的实际成交价格。监督学习的对立面是无监督学习。在无监督学习中,训练集没有被正确标记。这就好比你把一大堆数据扔给计算机,让计算机学习找出有用的信息。监督学习主要分为回归和分类两类模型。二元分类在生活中有很多应用。比如你收到一封邮件,要不要判断是不是垃圾邮件?或者说在银行的业务中,银行是否需要判断是否给某个客户贷款?这是一个二进制分类的图像识别的例子。
假设你有一张图片作为输入,你想识别这张图片是不是猫?如果是猫,输出1,否则输出0,输出结果用y表示。
所以首先你要知道图片在电脑里是怎么表现的。
在图像计算机中,像素存储为数据矩阵,最简单的图像是单通道灰度图像,其中每个位置(x,y)对应一个灰度值。
如果是彩色RGB图像,那么计算机需要保存三个独立的矩阵,分别对应图像在红、绿、蓝颜色通道中的像素。如果输入图像是6464像素,则有三个6464矩阵,它们对应于图像中红色、绿色和蓝色像素的强度。
把所有的像素值拿出来放入特征向量X来表示这张图片。上图中的换算方法是X为(255,131.194 202,然后是绿色通道255 134.94,最后是蓝色通道255 134.142).如果图片是64x64,那么向量X的总维数就是64x64x3,也就是12288。用于表示输入特征向量x的维度。
在这个二元分类问题中,目标是训练一个分类器。分类器以特征向量X为输入,然后输出这张图片是1还是0(即是否是猫)。
让我们从一些象征性的解释开始:
(x,y)代表一个训练样本,x是维度的特征向量,y是标签(0或1)。
m表示训练集中训练样本的数量,表示第一个训练样本。
矩阵维数为x m,代表所有训练样本的特征向量x,每列代表一个训练样本的特征向量。
表示维度为1 x m的矩阵,此矩阵表示所有训练样本的标签,每列表示一个训练样本的标签。
Logistic回归
为了解决二元分类问题,下面将介绍logistic回归。通常用来监督一个学习问题的输出标签是0还是1,也就是二元分类问题。下图是logistic回归算法的结构图示例,其中除以255是数据预处理步骤,这只是对我们的训练集进行浓缩和标准化。
逻辑回归实际上是一个非常小的神经网络。我们把它当作每张照片的输入向量X,然后我们需要给出预测值A,也就是我们需要找到一个好的关系,使我们的预测值尽可能接近实际标签。Logistic回归需要通过正向传播和反向传播来学习参数(即学习一个关系)。从输入X到给出预测值的过程称为前向传播,而由预测值由后向前推导W和B的过程称为后向传播。
对于一张图片,在转换成特征向量X输入算法后,我们期待算法告诉我们这张图片是不是猫。算法通常会给出一个预测值A,这个值通常是一个概率值,表示图片为正的概率(即1)。为了决定预测结果是正还是负,我们通常需要设置一个阈值。任何大于这个阈值的都是正的;否则为负。
设logistic回归的参数为W,其维数等于输入特征向量的维数,即W为一维向量,而B为实数。
那么,给定输入X和参数W,B,我们如何计算预测值A?如果我们计算a=,也就是w是x的线性函数,其实你这么做,其实是在用线性回归算法,这不是一个好的二分类算法。这里给出一个非正式的证明。直观来说,你期望算法的输出A是一个概率,表示这个图是1的概率,所以A应该在0到1之间,但实际上可能是负值或者远大于1的值,不符合我们的要求。所以我们可以对线性回归的值使用另一层激活函数,设函数的图形如下:
直观的我们可以看到函数的取值范围是0~1,所以我们的预测值A总是在(0,1)之间。
在logistic回归中,我们需要做的是根据训练集训练参数W和B的值,使我们的预测输出A尽可能接近真实的标签值Y。这样,当给定一张超帅饼干的图片时,我们就可以根据参数W和B计算出A,从而预测这张超帅饼干的图片是不是猫?
成本函数为了训练logistic回归的参数W和B,需要定义一个
成本函数
。在定义代价函数之前,我们需要定义
损失函数(Loss function),
损失函数,它衡量单个样本的预测值与实际标签值之间的误差。为了度量误差,我们可以将损失函数定义为我们熟悉的平方误差函数。结果表明,我们可以这样做,但在逻辑回归中,我们通常不这样做。因为使用平方差函数会使下面的优化问题非凸(此处未证明),直观上,这将导致我们最后得到很多局部最优解,使得梯度下降法等优化算法无法找到全局最优值。平方误差函数似乎是一个不错的选择,但是如果使用的话,优化算法就不好用了。
在logistic回归中,定义的损失函数是,010-59,000,它的作用类似于平方误差函数,它会把问题变成一个凸优化问题,让我们得到全局最优值,而不会陷入局部最优问题。
直观理解这个损失函数为什么起作用?首先,我们希望误差函数越小越好,因为这说明我们的预测是准确的。
当y=1时,由于第二项为0,损失函数变成,所以我们希望它越小越好,所以应该越大越好,也就是A应该越大越好,但是A是用函数得到的,也就是A最多不超过1。也就是说,当实际标签y=1时,我们希望预测值A尽可能接近1,满足我们的要求。
如果y=0,第一项变成0,那么损失函数就是,我们希望它越小越好,也就是越大越好,所以这就使得A越小越好,A的最小值不超过0。因此,当实际标签为0时,我们希望预测值A尽可能接近0。
我们来看看成本函数。损失函数度量单个样本的性能,而成本函数度量所有训练样本的性能。下面是成本函数的定义。
梯度下降为了从训练集中学习参数W和B,我们需要使用一种优化算法,梯度下降法就是优化算法之一。我们很容易认为,我们得到的最终W和B必须使代价函数J(w,B)尽可能小。
上图是代价函数关于参数W,B的曲面图,实际中W可以更高维,但这里为了方便作图,W和B是实数,曲面的高度代表J(w,B)在某一点的值。梯度下降法需要做的就是找到某个点,使得J(w,b)的函数值最小。可以看出,这个代价函数呈现碗状,实际上是一个凸函数,它只有一个全局最优值。凸函数的这一性质是logistic回归使用上述代价函数j的重要原因。
我们要做的就是随机初始化W和B,然后用下面的公式不断更新W和B的值。其中表示学习速率,它控制更新速率。
为了更直观的解释这个更新后的公式在做什么,先假设没有B参数,只有W参数,然后画一个J(w)关于W参数的函数图像。
一般来说,导数就是斜率。假设初始W在右边,因为导数为正,更新后的公式会使J(w)向左移动,直到最低点。如果在左边初始化,由于导数为负,J(w)会一直向右移动,直到最低点。
逻辑回归中的梯度下降
为了找到使J(w,b)最小的w和b的值,我们需要求J(w,b)对w和b的导数,为了便于理解,导数的计算是从单个训练样本的损失函数中推导出来的。
首先我们从上一步开始计算到上一步,也就是计算损失函数L对a的导数。
然后向前迈一步。
然后向前算。
以上是单个样本实例的渐变更新步骤。如果熟悉链导数,可以验证上面的公式是否正确。
但是在logistic回归中,我们的训练样本不止一个,而是很多个,那么我们来看看如何通过梯度下降来更新M个训练样本。
因为J(w,b)函数是损失函数之和的平均值,所以成本函数J(w,b)对w,b的导数也应该是上面推导的公式之和的平均值。
根据上面三个计算导数的公式,似乎需要写一个两层的循环。第一层遍历每个训练样本,第二层遍历所有W个参数进行累加。但是在应用深度学习算法时,在代码中显示使用周期的效率很低,尤其是在数据量很大的情况下。为了避免不必要的显示循环,我们需要使用矢量化。
…向量化…
上图是求向量内积的例子。可以看出矢量化速度快了很多。这一点在数据量大的时候会更加明显。
前向传播求Z时,如果用非向量化实现,需要依次求解以下方程,直到第m个训练样本。
为了使用矢量化,我们将使用初始矩阵X,其中X是维数为x m的矩阵,W是x 1的向量。
然后,W的转置乘以X矩阵。根据矩阵乘法,获得1xm矩阵,加上1xm B向量。你会发现这个矩阵Z其实就是上面公式的实现。
实际上,A是从每个训练样本获得的A的水平叠加,
以上是正向传播的矢量化过程。让我们看看反向传播是如何矢量化的。
Dz表示成本函数J(w,b)对z的导数。
同样的想法,这些Z是水平堆叠的。
接下来,我们需要对每个W参数和B参数的求导进行矢量化。
DZ实际上是每个训练样本的B的导数之和,所以在python中,可以用来求db。
Dw,如果这个公式的展开实际上是
它代表第I个训练样本的第j个特征。上面的结果是一个NX1的矩阵,每一行其实都是对的导数。I是1对nx。
大蟒代码将数组作为npdef sigmoid(z)导入:""函数‘’a=1/(1np。exp(-z))返回adef initialize _ parameters(dim): 初始化w和b参数dim: w的维度,在符号逻辑的回归中也等于输入特征的数量 w=np.random.randn(dim,1) b=0 return w,bdef propagate(w,b,X,Y): 正向和反向传播x:训练集的特征向量形状为(数量px*数量px*3,m)数量像素表示图像的尺寸,m表示训练样本的个数y:训练集的标签形状为(100万)成本:物流回归的成本函数dw:成本函数对w的导数数据库:成本函数对b的导数 m=X . shape[1]A=sigmoid(NP。dot(w . T,X)b)成本=-1/m * NP。sum(Y * NP。log(A)(1-Y)* NP。log(1-A))dw=1/m * NP。点(X,A-Y).t)db=1/m * NP。总和(A-Y)成本=NP。squeeze(cost)grads={ dw :dw, db:db} return grads,costdef optimize(w,b,X,Y,num_iterations,learning_rate,print_cost=False): 梯度下降算法迭代次数:迭代次数(梯度下降的次数)学习_速率:学习率成本记录迭代过程中的代价函数值,用来绘图,便于判断梯度下降是否正确 范围内I的costs=[](num _ iterations):grads,cost=propagate(w,b,x,y)dw=grads[ dw ]db=grads[ db ]w=w-learning _ rate * dw b=b-learning _ rate * db如果i0==0:costs。append(cost)if print _ cost and I % 100==0:print( cost after iteration % I:% f %(I,cost)) params={w:w, b :b } grads={ db :db } return params,grads,costsdef predict(w,b,X): 根据训练得到的w,b进行预测 m=X . shape[1]A=sigmoid(NP。dot(w . T,X) b) Y_prediction=np.zeros((1,m))for I in range(m):Y _ prediction[0,i]=A[0,I]0.5 return Y _ prediction def model(X _ train,Y_train,X_test,Y_test,num_iterations=2000,learning_rate=0.5,print_cost=False): 整合每个函数x _火车训练集的特征向量y _火车训练集的标签x _测试测试集样本的特征向量y _测试测试集样本的标签 w,b=initialize _ parameters(X _ train。shape[0])parameters,grads,costs=optimize(w,b,X _ train,Y_train,num_iterations,learning_rate,print _ cost)w=parameters[ w ]b=parameters[ b ]Y _ prediction _ train=predict(w,b,X _ train)Y_prediction_test=predict(w,b,X_test) d={costs: costs, Y _ prediction _ test, Y _ prediction _ train :Y _ train