天天看点

Logistic Regression---自我实现和学习笔记

Logistic Regression

最近在Github上学习机器学习,主要是在黄海广博士的项目下学习吴恩达的机器学习教程,做下笔记。

如有需要:链接自取(click)

预测函数 Predict Function

分类问题中的y值只有0或1,所以当使用线性回归在做分类问题时,y值就会超过或者低于1,这显然不是我们想要的。

Logistic Regression---自我实现和学习笔记

所以预测函数需要一些约束(约束感觉有点奇妙),这里就引入了逻辑(sigmod)函数g(z),如下。

h θ ( X ) = g ( θ T X ) = 1 1 + e − θ T X h_\theta(X)=g(\theta^TX)=\frac{1}{1+e^{-\theta^TX}} hθ​(X)=g(θTX)=1+e−θTX1​

g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z}} g(z)=1+e−z1​

Logistic Regression---自我实现和学习笔记

数学分析:

上面为该函数的图像保证了预测值在0到1之间。

h θ ( X ) > = 0.5 → θ T X > = 0 → h_\theta(X)>=0.5\to\theta^TX>=0\to hθ​(X)>=0.5→θTX>=0→预测y为1。

h θ ( X ) < 0.5 → θ T X < 0 → h_\theta(X)<0.5\to\theta^TX<0\to hθ​(X)<0.5→θTX<0→预测y为0。

代码分析:

def sigmod(z):
	return 1/(1+np.exp(-z))
           

同时这也是和线性回归非常不同的一点,逻辑回归的公式和线性回归的公式十分相像,但是基本的预测函数是不同的。

判定边界 Decision Boundary

假设只有两个特征,他们的分布如下图所示:

Logistic Regression---自我实现和学习笔记

模型为 θ T X = θ 0 + θ 1 x 1 + θ 2 x 2 \theta^TX=\theta_0+\theta_1x_1+\theta_2x_2 θTX=θ0​+θ1​x1​+θ2​x2​,可知 θ T X = 0 \theta^TX=0 θTX=0是一条分界线,上面预测为1,下面预测为0。

Logistic Regression---自我实现和学习笔记

这里需要弄清楚的就是,判定边界并不是数据的特征,而是这个预测函数,这个模型的特征,为什么这么说呢?因为如果建立模型的时候,不再是这个模型(二次,三次都可以),判定边界就会随之改变。

代价函数 Cost Function

逻辑函数的代价函数:

J ( θ ) = 1 m ∑ i = 1 m C o s t ( h θ ( x ( i ) ) − y ( i ) ) J(\theta)=\frac{1}{m}\sum_{i=1}^mCost(h_\theta(x^{(i)})-y^{(i)}) J(θ)=m1​∑i=1m​Cost(hθ​(x(i))−y(i))

C o s t ( h θ ( x ) , y ) = − y log ⁡ ( h θ ( x ) ) − ( 1 − y ) log ⁡ ( 1 − h θ ( x ) ) Cost(h_\theta(x),y)=-y\log(h_\theta(x))-(1-y)\log(1-h_\theta(x)) Cost(hθ​(x),y)=−ylog(hθ​(x))−(1−y)log(1−hθ​(x))

Cost函数图

Logistic Regression---自我实现和学习笔记

数学分析:

当y=1,然而预测值接近0时,你所需要付出的代价就非常大;

同理,可理解其他的。

代码分析:

def Cost(theta,X,y):
	theta=np.matrix(theta.values)
	X=np.matrix(X.values)
	y=np.matrix(y.values)
	first=np.multiply(-y,np.log(sigmod(theta.[email protected])))
	second=np.multiply((1-y),np.log(1-sigmod(theta.[email protected])))
	#这里都是矩阵计算,first和second相当于将每个训练元组的Cost算了出来,并且
	#列成一列矩阵,而np.sum()就当于数学公式中的自动求和。
	return np.sum(first-second)/len(X)
           

梯度下降 Gradient Descent

正如前面所说逻辑回归和线性回归公式大部分看上去是相同的,比如这里梯度下降的最后简化公式。

Repeat{

θ j : = θ j − α ∂ ∂ θ j J ( θ ) = θ j − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \theta_j:=\theta_j-\alpha\frac{\partial}{\partial\theta_j}J(\theta)=\theta_j-\alpha\frac{1}{m}\sum_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)} θj​:=θj​−α∂θj​∂​J(θ)=θj​−αm1​∑i=1m​(hθ​(x(i))−y(i))xj(i)​

}

数据分析:

这与线性回归的理解相同,也是一步一步的去找到最优解。

代码分析:

def gradient(theta,X,y):
	#这里只是在算J(θ)的梯度
	theta=np.matrix(theta.values)
	X=np.matrix(X.values)
	y=np.matrix(y.values)
	
	parameters=int(theta.ravel().shape[1])
	grad=np.zeros(parameters)
	error=sigmod(X*theta.T)-y
	
	for i in range(parameters):
		term=np.multiply(error,X[:,i])
		grad[i]=np.sum(term)/len(X)
	#自动求和在除以m就好了
	return grad
           
#直接调用函数在寻找最有模型参数
import scipy.optimize as opt
res=opt.fmin_tnc(func=cost,x0=theta,fprime=gradient,args=(X,y))
           

Scipy优化算法 fmin_tnc

Scipy优化算法简介(click)

fmin_tnc()适用于有约束(再次提到)的多元函数问题,提供梯度信息,使用截断牛顿法。

最常使用的参数 介绍
func 优化的目标函数
x0 初值
fprime 提供优化函数func的梯度函数,不然优化函数func必须返回函数值和梯度,或者设置approx_grad=True
approx_grad 如果设置为True,会给出近似梯度
args 元组,是传递给优化函数的参数
返回值 介绍
x 数组,返回优化问题的目标值(模型参数)
nfeval 整数,目标优化函数被调用的次数
rc Ruturn Code

多类别分类 Multiclass Classification

当y可以等于1,2,3…时,就需要多类别分类,只需要将一种情况看作1,另外其他的所有情况都看作0作为一次 h θ ( 1 ) ( X ) h_\theta^{(1)}(X) hθ(1)​(X)就可以了,然后还会存在更多的 h θ ( 2 ) ( X ) h_\theta^{(2)}(X) hθ(2)​(X)等等。

Logistic Regression---自我实现和学习笔记

取 m a x ( h θ ( i ) ( X ) ) max(h_\theta^{(i)}(X)) max(hθ(i)​(X))的最大的i,将其分为i类。

正则化 Regularization

正则化是为了防止出现过拟合的问题,也就是说避免让判定边界都十分接近每一个点(overfitting or high varance),所以我们需要加上一个惩罚系数λ。

Logistic Regression---自我实现和学习笔记

代价函数:

J ( θ ) = 1 2 m [ ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 + ∑ j = 1 n θ j 2 ] = 1 m ∑ i = 1 m C o s t ( h θ ( x ( i ) ) ) + 1 2 m ∑ j = 1 n θ j 2 J(\theta)=\frac{1}{2m}[\sum_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})^2+\sum_{j=1}^n\theta_j^2]=\frac{1}{m}\sum_{i=1}^mCost(h_\theta(x^{(i)}))+\frac{1}{2m}\sum_{j=1}^n\theta_j^2 J(θ)=2m1​[∑i=1m​(hθ​(x(i))−y(i))2+∑j=1n​θj2​]=m1​∑i=1m​Cost(hθ​(x(i)))+2m1​∑j=1n​θj2​

梯度下降:

这里有一个约定,不惩罚系数 θ 0 \theta_0 θ0​

同时惩罚系数不能过大,不然就只剩 θ 0 \theta_0 θ0​了

Repeat until convergence{

θ 0 : = θ 0 − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x 0 ( i ) \theta_0:=\theta_0-\alpha\frac{1}{m}\sum_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})x_0^{(i)} θ0​:=θ0​−αm1​∑i=1m​(hθ​(x(i))−y(i))x0(i)​

θ j : = θ j − α [ 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x 0 ( i ) + λ m θ j ] \theta_j:=\theta_j-\alpha[\frac{1}{m}\sum_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})x_0^{(i)}+\frac{\lambda}{m}\theta_j] θj​:=θj​−α[m1​∑i=1m​(hθ​(x(i))−y(i))x0(i)​+mλ​θj​]

}

代码分析:

def Cost(theta,X,y,learningRate):
	theta=np.matrix(theta.values)
	X=np.matrix(X.values)
	y=np.matrix(y.values)
	first=np.multiply(-y,np.log(sigmod(theta.[email protected])))
	second=np.multiply((1-y),np.log(1-sigmod(theta.[email protected]))) 
	reg=(learningRate/(2*len(X))*np.sum(np.power(theta[:,1:theta.shape[1]],2))
	#注意这里的theta的范围
	return np.sum(first-second)/len(X)+reg
           
def gradientReg(theta,X,y,learningRate):
	#这里只是在算J(θ)的梯度
	theta=np.matrix(theta.values)
	X=np.matrix(X.values)
	y=np.matrix(y.values)
	
	parameters=int(theta.ravel().shape[1])
	grad=np.zeros(parameters)
	error=sigmod(X*theta.T)-y
	
	for i in range(parameters):
		term=np.multiply(error,X[:,i])
		grad[i]=np.sum(term)/len(X)
		if i!=0:
			grad[i]+=learningRate/len(X)*theta[:,i]
			
	return grad
	#同时拥有了目标优化函数和梯度函数就可使用上述的优化方法了。
           

sklearn.linear_model.LogisticRegression

学习链接(click)