逻辑回归原理分析

1 逻辑回归

前面介绍的线性回归处理的因变量都是数值型区间变量,建立的模型描述是因变量的期望与自变量之间的线性关系。
(1.1) z = θ T x + b z = \theta^Tx+b\tag{1.1} z=θTx+b(1.1)

而在采用回归模型分析实际问题中,可能我们的期待输出值并不是一个连续值,而是离散值,比如判断一封邮件是否为垃圾邮件,这时输出就只有1(垃圾邮件)或者0(正常邮件),这时我们怎么处理呢?
我们可以通过一个函数将预测值f(x)转换为0/1值,这样就可以实现分类判别了。最理想的转换函数就是"单位阶跃函数"(unit-step function)
(1.2) y = { 0 , z &lt; 0 0.5 , z = 0 1 , z &gt; 0 y = \begin{cases} 0,&amp;z&lt;0\\ 0.5,&amp;z=0\\ 1,&amp;z&gt;0\\\tag{1.2} \end{cases} y=0,0.5,1,z<0z=0z>0(1.2)

但是单位阶跃函数并不连续,即不可导,于是我们希望找到能在一定程度上近似单位阶跃函数的替代函数,且希望它单调可微,sigmoid函数就是这样的一个替代函数。
(1.3) g ( z ) = 1 1 + e − z g(z) = \frac{1}{1+e^{-z}} \tag{1.3} g(z)=1+ez1(1.3)
sigmoid函数的导数如式1,4所示
(1.4) g ′ ( z ) = ( 1 1 + e − z ) = g ( z ) ∗ ( 1 − g ( z ) ) \begin{aligned} g^{&#x27;}(z) &amp;= \left(\frac{1}{1+e^{-z}}\right)\\ &amp;=g(z)*(1-g(z))\\\tag{1.4} \end{aligned} g(z)=(1+ez1)=g(z)(1g(z))(1.4)

sigmoid函数的图像为
sigmoid函数图像
由上图可以看出,sigmoid函数将z值转化为一个接近0或1的y值,并且其输出值在z=0附件变换很陡,将式1.1代入1.3中,可得
(1.5) h θ = g ( θ T x ) = 1 1 + e − ( θ T x + b ) h_\theta = g(\theta^T x) = \frac{1}{1+e^{-(\theta^Tx + b)}}\tag{1.5} hθ=g(θTx)=1+e(θTx+b)1(1.5)

下面我们来看如何确定式1.5中的 θ \theta θ和b,假设我们在做一个二分类任务,则y=1的概率可设为 h θ h_\theta hθ,则y=0的概率就为 1 − h θ 1-h_\theta 1hθ
(1.6) P ( y = 1 ∣ x ; θ ) = h θ ( x ) P(y=1|x;\theta) = h_\theta (x)\tag{1.6} P(y=1x;θ)=hθ(x)(1.6)

(1.7) P ( y = 0 ∣ x ; θ ) = 1 − h θ ( x ) P(y=0|x;\theta) = 1 - h_\theta (x)\tag{1.7} P(y=0x;θ)=1hθ(x)(1.7)

(1.8) 整合: P ( y ∣ x ; θ ) = ( h θ ( x ) ) y ( 1 − h θ ( x ) ) 1 − y \text{整合:}P(y|x;\theta) = (h_\theta (x))^y(1-h_\theta (x))^{1-y}\tag{1.8} 整合:P(yx;θ)=(hθ(x))y(1hθ(x))1y(1.8)

此时我们即可得到我们的似然函数
(1.9) L ( θ ) = ∏ i − 1 m ( h θ ( x ( i ) ) ) y ( i ) ( 1 − h θ ( x ( i ) ) ) 1 − y ( i ) L(\theta) = \prod_{i-1}^m (h_\theta (x^{(i)}))^{y^{(i)}}(1-h_\theta (x^{(i)}))^{1-y^{(i)}}\tag{1.9} L(θ)=i1m(hθ(x(i)))y(i)(1hθ(x(i)))1y(i)(1.9)
先两边同时取log再化简
(1.10) l ( θ ) = l o g L ( θ ) = ∑ i = 1 m ( y i l o g h θ ( x i ) + ( 1 − y i ) l o g ( 1 − h θ ( x i ) ) ) l(\theta) = logL(\theta) = \sum_{i=1}^m (y_ilogh_\theta (x_i) +(1-y_i)log(1-h_\theta (x_i))) \tag{1.10} l(θ)=logL(θ)=i=1m(yiloghθ(xi)+(1yi)log(1hθ(xi)))(1.10)

就跟我们在之前线性回归里面一样,我们要取得最大似然,也就是最大化 l ( θ ) l(\theta) l(θ),不过考虑到我们会用梯度下降法来求解,所以我们引入
(1.11) J ( θ ) = − 1 m l ( θ ) J(\theta) = -\frac{1}{m} l(\theta) \tag{1.11} J(θ)=m1l(θ)(1.11)

此时我们的任务就变为用梯度下降法来最小化 J ( θ ) J(\theta) J(θ),跟之前线性回归一样,我们对其进行求导
(1.12) δ δ ( θ j ) = − 1 m ∑ i = 1 m ( y i 1 h θ ( x i ) δ δ ( θ i ) h θ ( x i ) − ( 1 − y i ) 1 1 − h θ ( x i ) δ δ ( θ i ) h θ ( x i ) ) = − 1 m ∑ i = 1 m ( y i 1 g ( θ T x i ) − ( 1 − y i ) 1 1 − g ( θ T x i ) ) g ( θ T x i ) ( 1 − g ( θ T x i ) ) δ δ ( θ i ) θ T x i = 1 m ∑ i = 1 m ( h θ ( x i ) − y i ) x i j \begin{aligned} \frac{\delta}{\delta_(\theta_j)} &amp;= -\frac{1}{m} \sum_{i=1}^m \left(y_i\frac{1}{h_\theta (x_i)}\frac{\delta}{\delta _(\theta_i)}h_\theta(x_i) - (1-y_i)\frac{1}{1-h_\theta (x_i)}\frac{\delta}{\delta _(\theta_i)}h_\theta(x_i)\right)\\ &amp;=-\frac{1}{m} \sum_{i=1}^m \left(y_i\frac{1}{g{(\theta^Tx_i)}} - (1-y_i)\frac{1}{1-g(\theta^T x_i)}\right)g(\theta ^Tx_i)(1 - g(\theta ^Tx_i))\frac{\delta}{\delta _(\theta_i)}\theta^Tx_i\\ &amp;=\frac{1}{m}\sum_{i=1}^m(h_\theta(x_i)-y_i)x_i^j\\\tag{1.12} \end{aligned} δ(θj)δ=m1i=1m(yihθ(xi)1δ(θi)δhθ(xi)(1yi)1hθ(xi)1δ(θi)δhθ(xi))=m1i=1m(yig(θTxi)1(1yi)1g(θTxi)1)g(θTxi)(1g(θTxi))δ(θi)δθTxi=m1i=1m(hθ(xi)yi)xij(1.12)

得到 J ( θ ) J(\theta) J(θ) 的导数后,我们即可利用梯度下降法去更新参数了
(1.13) θ j = θ j − α 1 m ∑ i = 1 m ( h θ ( x i ) − y i ) x i j \theta_j = \theta_j - \alpha\frac{1}{m}\sum_{i=1}^m(h_\theta(x_i)-y_i)x_i^j\tag{1.13} θj=θjαm1i=1m(hθ(xi)yi)xij(1.13)

2 算法实现

#sigmoid函数实现
def sigmoid(self,x):
		return 1.0/(1+np.exp(-x))
#使用批量梯度下降算法
def train(self,X,Y,learningRate=1e-3,numIters=1000,reg=0.0,verbose=False):
		m,n = X.shape
		n = np.shape(X)[1]   #特征个数
		#权值初始化
		if self.w == None:
			self.w = np.ones((n,1))
		lossHistory = []
		for i in range(numIters):
			h = self.sigmoid(X.dot(self.w))
			loss = h-Y
			lossHistory.append(np.sum(loss))
			#更新参数
			self.w = self.w - learningRate*X.T.dot(loss)
			if verbose and i%100 == 0:
				print("迭代次数:%d/%d  loss: %f"%(i,numIters,np.sum(loss)))
		return lossHistory
#预测函数
def predict(self,X):
		return np.mat([1 if x >= 0.5 else 0 for x in self.sigmoid(X.dot(self.w))])

核心函数均实现后开始进行测试
首先加载数据

def load_data():
    #加载iris数据
	data = datasets.load_iris()
	#给数据加上一行偏置
	offset = np.ones(100)
	feature_data = data['data'][:100]
	feature_data = np.insert(feature_data, 0, values=offset, axis=1)
	label_data = data['target'][:100].reshape((-1,1))

	#80个数据作为训练集 20个作为测试集
	trainX = feature_data[:40]
	trainX = np.concatenate((trainX, feature_data[50:90]))
	trainY = label_data[:40]
	trainY = np.concatenate((trainY, label_data[50:90]))

	testX = feature_data[40:50]
	testX = np.concatenate((testX, feature_data[90:100]))
	testY = label_data[40:50]
	testY = np.concatenate((testY, label_data[90:100]))

	return trainX,trainY,testX,testY
print("-----------1.load_data-----------")
	trainX,trainY,testX,testY = load_data()
	print("-----------2.training-----------")
	model = logisticRegression()
	lossHistory = model.train(trainX,trainY,learningRate=1e-3,verbose=True,numIters=1000)
	ax = plt.subplot(111)
	ax.plot(lossHistory)
	ax.set_xlabel('Iterations ')
	ax.set_ylabel('Cost')

	#验证集测试
	predY = model.predict(testX)
	print("验证集正确率: %f"%((predY.T==testY).mean()))

训练过程如下图所示
训练过程
使用验证集进行测试时,因为数据量本身很小,而且不同类别数据分的很开,很轻松就得到了100%的正确率

代码点此获取GitHub

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值