回归 : 用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归。
逻辑回归: 是一种适用于二分类(非0即1)的分类算法
根据现有数据对分类边界线建立回归公式,以此进行分类。
目标:找到最佳拟合参数集
例如:下图所示,在一个平面中存在2个类别的数据,红色为:1,蓝色为0
此时画一条直线,平面上的点将被为两个部分,而我们所要求的就是这一条直线方程
假设这条直线方程为w0+w1*x1+w2*x2=0
,而平面中的点是已知的,如:(x1, x2)=(1.0 , 0.6),带入该方程中,得w0+w1*1.0+w2*0.6=z
,若z>0,则在直线的上方,若z<0,类别1,则在直线的下方,类别0
问题即为:求一个最佳的的w0,w1,w2
,使分类器尽可能地准确
数据处理过程中,通常会对原数据加入一个特征值1,原数据(x1,x2)=>(1,x1,x2)=(1, 1.0 ,0.6)
此时点向量为 x T = [ x 0 x 1 x 2 ] = [ 1.0 1.0 0.6 ] \begin{aligned} \mathbf{ x^{T}}&=\begin{bmatrix}x_{0}&x_{1}&x_{2}\\\end{bmatrix}\\ &=\begin{bmatrix}1.0&1.0&0.6\\\end{bmatrix} \end{aligned} xT=[x0x1x2]=[1.01.00.6]
参数w0,w1,w2为
w T = [ w 0 w 1 w 2 ] \begin{aligned} \mathbf{ w^{T}} &=\begin{bmatrix}w_{0}&w_{1}&w_{2}\end{bmatrix} \end{aligned} wT=[w0w1w2]
此时方程为
z = w 0 ∗ 1.0 + w 1 ∗ x 1 + w 2 ∗ x 2 = w 0 ∗ 1.0 + w 1 ∗ 1.0 + w 2 ∗ 0.6 = w T x ( 向 量 相 乘 ) \begin{aligned} z&=w_{0}*1.0+w_{1}*x_{1}+w_{2}*x_{2} \\ &=w_{0}*1.0+w_{1}*1.0+w_{2}*0.6\\ &=\mathbf{w^{T}}\mathbf{x} {(向量相乘)} \end{aligned} z=w0∗1.0+w1∗x1+w2∗x2=w0∗1.0+w1∗1.0+w2∗0.6=wTx(向量相乘)
存在一个点(x1,x2,…xn), n为特征值的个数,对应的向量为
x T = [ x 0 x 1 x 2 . . . x n ] = [ 1 x 1 x 2 . . . x n ] \begin{aligned} \mathbf{ x^{T}}&=\begin{bmatrix}x_{0}&x_{1}&x_{2}&...&x_{n}\\\end{bmatrix}\\ &=\begin{bmatrix}1&x_{1}&x_{2}&...&x_{n}\\\end{bmatrix} \end{aligned} xT=[x0x1x2...xn]=[1x1x2...xn]
参数为:
w T = [ w 0 w 1 w 2 . . . w n ] \begin{aligned} \mathbf{ w^{T}} &=\begin{bmatrix}w_{0}&w_{1}&w_{2}&...&w_{n}\end{bmatrix} \end{aligned} wT=[w0w1w2...wn]
因此:
z = w 0 ∗ 1 + w 1 ∗ x 1 + w 2 ∗ x 2 + . . . + w n ∗ x n = w T x \begin{aligned} z&=w_{0}*1+w_{1}*x_{1}+w_{2}*x_{2} +...+w_{n}*x_{n}\\ &=\mathbf{w^{T}} \mathbf{x} \end{aligned} z=w0∗1+w1∗x1+w2∗x2+...+wn∗xn=wTx
Sigmoid
函数具体公式如下所示:
h ( x ) = 1 1 + e − x h(x)=\frac{1}{1+e^{-x} } h(x)=1+e−x1
函数图像如图所示:
当x>0
时,1>Sigmoid(x)>0.5
当x<0
时,0
当x=0
时,Sigmoid(x)=0.5
因为:
z = w 0 ∗ 1 + w 1 ∗ x 1 + w 2 ∗ x 2 + . . . + w n ∗ x n = w T x \begin{aligned} z&=w_{0}*1+w_{1}*x_{1}+w_{2}*x_{2} +...+w_{n}*x_{n}\\ &=\mathbf{w^{T}} \mathbf{x} \end{aligned} z=w0∗1+w1∗x1+w2∗x2+...+wn∗xn=wTx
将
z
代入Sigmoid
函数中,进而得到一个范围在0~1 之间的数值。
h ( w T x ) = 1 1 + e − w T x h(\mathbf{w^{T}} \mathbf{x} )=\frac{1}{1+e^{-\mathbf{w^{T}} \mathbf{x} } } h(wTx)=1+e−wTx1
大于0.5的数据被分入1
类,小于0.5即被归入0
类。
对Sigmoid
函数求导,将在后面的推导中用到:
h ′ ( x ) = d 1 1 + e − x d x = h ( x ) ( 1 − h ( x ) ) \begin{aligned} h ^{'}(x) & = \frac{d{\frac{1}{1+e^{-x} }}}{d{x}}\\ &=h(x)(1-h(x)) \end{aligned} h′(x)=dxd1+e−x1=h(x)(1−h(x))
通过sigmoid
函数 ,输出的值 p= h ( w T x ) h(\mathbf{w^{T}} \mathbf{x} ) h(wTx)
p的值表示结果为1
的概率,1-p则表示结果为0
的概率**
在一个数据集中(m表示样本数,n表示特征值个数):
x = [ x 10 x 20 . . . x m 0 x 11 x 21 . . . x m 1 . . . x 1 n x 2 n . . . x m n ] \mathbf{x}=\begin{bmatrix} x_{10}&x_{20}&...&x_{m0}\\ x_{11}&x_{21}&...&x_{m1}\\ ...\\ x_{1n}&x_{2n}&...&x_{mn} \end{bmatrix} x=⎣⎢⎢⎡x10x11...x1nx20x21x2n.........xm0xm1xmn⎦⎥⎥⎤,则任意一个输入向量 x i = [ x i 0 x i 1 . . . x i n ] \mathbf{x_{i}}=\begin{bmatrix}x_{i0}\\x_{i1}\\...\\x_{in}\end{bmatrix} xi=⎣⎢⎢⎡xi0xi1...xin⎦⎥⎥⎤
分类结果为类别1和类别0的概率分别为
P i ( y = 1 ∣ x i ) = h ( w T x i ) ( 当 该 类 别 标 签 y = 1 时 ) P i ( y = 0 ∣ x i ) = 1 − h ( w T x i ) ( 当 该 类 别 标 签 y = 0 时 ) \begin{aligned} P_{i}(y & = 1| \mathbf{x_{i}}) = h(\mathbf{w^{T}} \mathbf{x_{i}} ){(当该类别标签 y=1时)}\\ P_{i}(y & = 0| \mathbf{x_{i}}) = 1-h(\mathbf{w^{T}} \mathbf{x_{i}} ){(当该类别标签 y=0时)} \end{aligned} Pi(yPi(y=1∣xi)=h(wTxi)(当该类别标签y=1时)=0∣xi)=1−h(wTxi)(当该类别标签y=0时)
对以上式子进行合并,得到
P i ( y i ∣ x i ) = ( h ( w T x i ) ) y i ∗ ( 1 − h ( w T x i ) ) ( 1 − y i ) \begin{aligned} P_{i}(y_{i}|\mathbf{x_{i}})=(h(\mathbf{w^{T}}\mathbf{x_{i}}))^{y_{i}}*(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))^{(1-y_{i})} \end{aligned} Pi(yi∣xi)=(h(wTxi))yi∗(1−h(wTxi))(1−yi)
构建似然函数:若训练样本相互独立,则似然函数为:
L ( w ) = ∏ i = 1 m P i ( y i ∣ x i ) = ∏ i = 1 m ( h ( w T x i ) ) y i ∗ ( 1 − h ( w T x i ) ) ( 1 − y i ) \begin{aligned} L(\mathbf{w})&=\prod_{i= 1}^{m} P_{i}(y_{i}|\mathbf{x_{i}})\\ &=\prod_{i= 1}^{m}(h(\mathbf{w^{T}}\mathbf{x_{i}}))^{y_{i}}*(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))^{(1-y_{i})} \end{aligned} L(w)=i=1∏mPi(yi∣xi)=i=1∏m(h(wTxi))yi∗(1−h(wTxi))(1−yi)
对似然函数进行一个转换,两边取log,将乘法运算转换为加法运算:
l n L ( w ) = ∑ i = 1 m y i ln h ( w T x i ) + ( 1 − y i ) l n ( 1 − h ( w T x i ) ) = l ( w ) \begin{aligned} ln_{}{L(\mathbf{w})}&=\sum_{i=1}^{m}{y_{i}}\ln_{}{h(\mathbf{w^{T}}\mathbf{x_{i}})} +{(1-y_{i})}ln_{}{(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))}\\&=l(\mathbf{w}) \end{aligned} lnL(w)=i=1∑myilnh(wTxi)+(1−yi)ln(1−h(wTxi))=l(w)
似然函数是一种关于统计模型中的参数的函数,表示模型参数中的似然性,可以理解为条件概率的逆反
以盒子中抓黑白球为例:
比如个一盒子中只有黑色
和白色
两种球,但不知道他们的数量是多少
现在从中抓10次(每次都放回),得到了3次黑球,7次白球。
假设取到黑球
的概率为P
,则取到白球
的概率为1-P
则 构建似然函数为
L ( P ) = P 3 ∗ ( 1 − P ) 7 L(P)=P^3*(1-P)^7 L(P)=P3∗(1−P)7
此时,若存在一个参数值P
, 即抓到黑球的概率,使得它的函数值L(P)
达到最大的话,那么这个值P
就是最为合理
的参数值。
一般对L(P)
进行求导,令导数为0
,求得P
所取的值
同理在逻辑回归中,也是二分类问题,当存在
w
使得L(w)
取最大值时,那么此时的w
即为合适
的值,在当前问题中, w = [ w 0 , w 1 , w 2 , . . . , w n ] w=[w_{0}, w_{1}, w_{2}, ... , w_{n}] w=[w0,w1,w2,...,wn]是一个n+1
维的向量,即参数值
似然函数为:
l ( w ) = ∑ i = 1 m y i ln h ( w T x i ) + ( 1 − y i ) l n ( 1 − h ( w T x i ) ) \begin{aligned} l(\mathbf{w})&=\sum_{i=1}^{m}{y_{i}}\ln_{}{h(\mathbf{w^{T}}\mathbf{x_{i}})} +{(1-y_{i})}ln_{}{(1-h(\mathbf{w^{T}}\mathbf{x_{i}}))} \end{aligned} l(w)=i=1∑myilnh(wTxi)+(1−yi)ln(1−h(wTxi))
l ( w ) l(\mathbf{w}) l(w)求最大值,使用梯度上升。
梯度:
一般来说,梯度可以定义为一个函数的全部偏导数
构成的向量
指向函数值增长最快的方向
梯度上升:沿着增长最快的方向,移动 α \alpha α 的步长,迭代公式如下
w = w + α ∇ f \large w=w+\alpha \nabla {f} w=w+α∇f
即求 l ( w ) l(\mathbf{w}) l(w)的梯度, 需分别对对 w i w_{i} wi求偏导
∇ f = [ ∂ l ( w ) ∂ w 0 ∂ l ( w ) ∂ w 1 ∂ l ( w ) ∂ w 2 . . . ∂ l ( w ) ∂ w n ] \large \nabla {f}=\begin{bmatrix} \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{0}}\\ \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{1}}\\ \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{2}}\\ ...\\ \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{n}}\\ \end{bmatrix} ∇f=⎣⎢⎢⎢⎢⎢⎢⎢⎡∂w0∂l(w)∂w1∂l(w)∂w2∂l(w)...∂wn∂l(w)⎦⎥⎥⎥⎥⎥⎥⎥⎤
对以上公式进行拆分,拿出一个来看
∂ l ( w ) ∂ w 0 = ∑ i = 1 m ∂ h ( w T x i ) ∂ w 0 ( y i h ( w T x i ) + 1 − y i 1 − h ( w T x i ) ) {\large \begin{aligned} \frac{\partial l(\mathbf{w})}{\partial w_{0}} &=\sum_{i=1}^{m} \frac{\partial\mathrm h(\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{0}}(\frac{y_{i}}{h(\mathbf{w^{T}x_{i}})} +\frac{1-y_{i}}{1-h(\mathbf{w^{T}x_{i}})}) \end{aligned}} ∂w0∂l(w)=i=1∑m∂w0∂h(wTxi)(h(wTxi)yi+1−h(wTxi)1−yi)
其中
∵ h ′ ( x ) = d h ( x ) d x = h ( x ) ( 1 − h ( x ) ) ∴ ∂ h ( w T x i ) ∂ w 0 = h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ ∂ ( w T x i ) ∂ w 0 = . . . ∗ ∂ ( w 0 x 0 + w 1 x 1 + . . . + w n x n ) ∂ w 0 = . . . ∗ x 0 = h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ x 0 . . . . 以 此 类 推 ∴ ∂ h ( w T x i ) ∂ w j = h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ x j ( x j = 第 j 个 特 征 值 ) {\large \begin{aligned} &\because h^{'}(x) =\frac{\mathrm{d} h(x)}{\mathrm{d} x} = h(x)(1-h(x))\\\\ &\therefore \frac{\partial\mathrm h(\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{0}} = h(\mathbf{w^{T}x_{i}})(1-h(\mathbf{w^{T}x_{i}})) *\frac{\partial\mathrm (\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{0}}\\&=...*\frac{\partial\mathrm (w_{0}x_{0}+w_{1}x_{1}+...+w_{n}x_{n})}{\partial\mathrm w_{0}}\\&=...* x_{0}\\ &=h(\mathbf{w^{T}x_{i}})(1-h(\mathbf{w^{T}x_{i}}))*x_{0}\\\\&....{以此类推}\\ &\therefore \frac{\partial\mathrm h(\mathbf{w^{T}x_{i}})}{\partial\mathrm w_{j}}=h(\mathbf{w^{T}x_{i}})(1-h(\mathbf{w^{T}x_{i}}))*x_{j}{(x_{j}=第j个特征值)} \end{aligned}} ∵h′(x)=dxdh(x)=h(x)(1−h(x))∴∂w0∂h(wTxi)=h(wTxi)(1−h(wTxi))∗∂w0∂(wTxi)=...∗∂w0∂(w0x0+w1x1+...+wnxn)=...∗x0=h(wTxi)(1−h(wTxi))∗x0....以此类推∴∂wj∂h(wTxi)=h(wTxi)(1−h(wTxi))∗xj(xj=第j个特征值)
代入原方程中得
∂ l ( w ) ∂ w 0 = ∑ i = 1 m ( h ( w T x i ) ( 1 − h ( w T x i ) ) ∗ x 0 ) ( y i h ( w T x i ) + 1 − y i 1 − h ( w T x i ) ) 整 理 得 = ∑ i = 1 m ( y i − h ( w T x i ) ) x i 0 {\large \begin{aligned} \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{0}}&=\sum_{i=1}^{m}(h(\mathbf{w^{T}x_{i}}) (1-h(\mathbf{w^{T}x_{i}}))*x_{0})(\frac{y_{i}}{h(\mathbf{w^{T}x_{i}})} +\frac{1-y_{i}}{1-h(\mathbf{w^{T}x_{i}})})\\{整理得}\\ &=\sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0} \end{aligned}} ∂w0∂l(w)整理得=i=1∑m(h(wTxi)(1−h(wTxi))∗x0)(h(wTxi)yi+1−h(wTxi)1−yi)=i=1∑m(yi−h(wTxi))xi0
所以:
∂ l ( w ) ∂ w j = ∑ i = 1 m ( y i − h ( w T x i ) ) x i j ( x i j = 第 i 个 样 本 的 第 j 个 特 征 值 ) {\large \begin{aligned} \frac{\partial\mathrm l(\mathbf{w})}{\partial\mathrm w_{j}}&=\sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{ij}{(x_{ij}=第i个样本的第j个特征值)} \end{aligned}} ∂wj∂l(w)=i=1∑m(yi−h(wTxi))xij(xij=第i个样本的第j个特征值)
梯度可以表示为:
∇ f = 1 m [ ∑ i = 1 m ( y i − h ( w T x i ) ) x i 0 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 1 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 2 . . . . . . ∑ i = 1 m ( y i − h ( w T x i ) ) x i n ] \large \nabla {f}=\frac{1}{m} \begin{bmatrix} \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i1}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i2}\\ ......\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{in}\\ \end{bmatrix} ∇f=m1⎣⎢⎢⎢⎢⎢⎢⎡∑i=1m(yi−h(wTxi))xi0∑i=1m(yi−h(wTxi))xi1∑i=1m(yi−h(wTxi))xi2......∑i=1m(yi−h(wTxi))xin⎦⎥⎥⎥⎥⎥⎥⎤
梯度上升算法的迭代过程: α \alpha α 为步长
w = w + α ∇ f = [ w 0 w 1 w 2 . . . w n ] + α 1 m [ ∑ i = 1 m ( y i − h ( w T x i ) ) x i 0 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 1 ∑ i = 1 m ( y i − h ( w T x i ) ) x i 2 . . . . . . ∑ i = 1 m ( y i − h ( w T x i ) ) x i n ] \begin{aligned} \mathbf{w} &=\mathbf{w} +\alpha \nabla f\\\\&=\begin{bmatrix} w_{0}\\ w_{1}\\ w_{2}\\...\\w_{n} \end{bmatrix}+\alpha \frac{1}{m}\begin{bmatrix} \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i1}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i2}\\ ......\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{in}\\ \end{bmatrix} \end{aligned} w=w+α∇f=⎣⎢⎢⎢⎢⎡w0w1w2...wn⎦⎥⎥⎥⎥⎤+αm1⎣⎢⎢⎢⎢⎡∑i=1m(yi−h(wTxi))xi0∑i=1m(yi−h(wTxi))xi1∑i=1m(yi−h(wTxi))xi2......∑i=1m(yi−h(wTxi))xin⎦⎥⎥⎥⎥⎤
经过上述不断迭代的过程,最终得到一个合适的 w \mathbf{w} w参数
当数据量达到上亿或更多数据以后,梯度上升算法中的矩阵乘法等操作显然耗时将上升到非常高的程度
他通过随机取数据集中的部分数据,来代表整体数据集,从而实现对数据样本集的缩小,达到减少计算量,降低算法时间复杂度的目的。
import numpy as np
import matplotlib.pyplot as plt
from random import randint
def sigmoid(in_x):
"""
对列向量中的每个元素都执行一次sigmoid(x)函数
:param in_x: 输入列向量
:return: 函数值,列向量
样例输入:
[[0],
[1],
[2]]
样例输出:
[[sigmoid(0)],
[sigmoid(1)],
[sigmoid(2)]]
"""
if in_x.any() >= 0:
return 1.0/(1+np.exp(-in_x))
else:
return float(np.exp(in_x))/(1+np.exp(in_x))
def autoNorm(dataMat):
"""
对数据进行归一化
:param dataMat: 数据集
:return: 数据集(归一化后)
"""
minVals=np.min(dataMat, axis=0)
maxVals=np.max(dataMat, axis=0)
ranges=maxVals-minVals
normDataSet=dataMat-minVals
normDataSet=normDataSet/ranges#[0,1]
return normDataSet
def load_data(filename):
"""
从文件中加载数据
:param filename:文件名称/路径
:return: 数据集矩阵,数据类别标签向量
"""
data_mat=[]
data_labels=[]
w0=[]
with open(filename,'r') as fr:
for line in fr:
currline=line.strip().split('\t')
w0.append(1.0)
data_mat.append(list(map(float, currline[:-1])))
data_labels.append(float(currline[-1]))
data_mat=autoNorm(np.mat(data_mat))
data_mat=np.insert(data_mat, 0, values=np.mat(w0), axis=1)
return data_mat, np.mat(data_labels).T
def get_weight_0(in_data_mat, in_data_labels, alph=0.01, r=500):
"""
梯度上升算法
:param in_data_mat: 输入训练集
:param in_data_labels: 训练集标签
:param alph: 移动步长
:param r: 迭代多少次
:return: w参数向量
"""
shape=in_data_mat.shape
weights = np.ones((shape[1], 1))
for i in range(r):
h_wx=sigmoid(in_data_mat*weights)
err=in_data_labels-h_wx
weights=weights+alph*in_data_mat.T*err
return weights
def get_weight_1(in_data_mat, in_data_labels, c=0.01, r=50):
"""
随机梯度上升(优化)
:param in_data_mat: 输入训练集
:param in_data_labels: 训练集标签
:param c: 移动步长
:param r: 迭代多少次
:return: w参数向量
"""
shape=in_data_mat.shape
weights = np.ones((shape[1], 1))
for j in range(r):
index_list = list(range(shape[0]))
for i in range(shape[0]):
ran_num=randint(0, len(index_list)-1)
index =index_list[ran_num]
alph=4/(1.0+j+i)+c
h_wx=float(sigmoid(in_data_mat[index]*weights))
err=in_data_labels[index]-h_wx
weights=weights+(alph*err*in_data_mat[index]).T
del index_list[ran_num]
return weights
def plot_fig(weights, in_data_mat, in_data_labels):
"""
画出点集和所求的直线
:param weights: w参数向量
:param in_data_mat: 训练数据集
:param in_data_labels: 训练集标签
:return: None
"""
size=in_data_mat.shape[0]
for i in range(size):
if int(in_data_labels[i]) == 0:
plt.scatter(in_data_mat[i, 1], in_data_mat[i, 2], color='r', linewidth=5, marker='.')
else:
plt.scatter(in_data_mat[i, 1], in_data_mat[i, 2], color='b', linewidth=5, marker='.')
weights=list(map(float, np.array(weights)))
y=-(weights[0]+weights[1]*in_data_mat[:, 1])/weights[2]
plt.plot(in_data_mat[:, 1], y, linewidth=5, linestyle='solid')
plt.xlabel('x1')
plt.ylabel('x2')
plt.show()
def example_test():
"""
测试函数
:return:None
"""
data_mat, data_labels=load_data('testSet.txt')
weights=get_weight_0(data_mat, data_labels)
plot_fig(weights, data_mat, data_labels)
example_test()