欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

机器学习之逻辑回归-逻辑回归的原理及python代码实现

程序员文章站 2022-03-22 14:58:04
逻辑回归1.功能做二分类(1/0)任务,并给出相应概率是否是 逻辑回归讲的是分类问题二分类可以扩展到多分类问题2.灵感过程1.做分类问题从简单的二分类开始2.标签是(1/0)3.可使用最简单的单位阶跃函数u(t)={1,z>00.5,z=00,z<0u(t)=\left\{\begin{matrix} 1,z>0 \\ 0.5,z=0\\ 0,z<0\end{matrix}\right.u(t)=⎩⎨⎧​1,z>00.5,z=00,...

逻辑回归

1.功能

做二分类(1/0)任务,并给出相应概率

是否是 逻辑回归讲的是分类问题

二分类可以扩展到多分类问题

2.灵感过程

1.做分类问题从简单的二分类开始

2.标签是(1/0)

3.可使用最简单的单位阶跃函数

u ( t ) = { 1 , z > 0 0.5 , z = 0 0 , z < 0 u(t)=\left\{\begin{matrix} 1,z>0 \\ 0.5,z=0\\ 0,z<0\end{matrix}\right. u(t)=1,z>00.5,z=00,z<0

4.但是阶跃函数不连续,因此使用logistics function代替(因为形状为s型,因此也叫作sigmoid function)让他连续且可导,logistics function函数为

y = 1 1 + e − z y=\frac{1}{1+e^{-z} } y=1+ez1

横坐标z纵坐标y定义域为负无穷到正无穷,值域是0-1,
机器学习之逻辑回归-逻辑回归的原理及python代码实现

ps: 逻辑回归为什么是分类而不是回归

1.逻辑指的是logistics function

2.回归来源于线性回归的Z=XW,使用线性回归去拟合逼近一个“界”,使得按照这个界进行数据分类后得到的cost最小。以概率0.5为分界线,将数据分为正例和反例。把横坐标分为正和负,把纵坐标分为靠近1的和靠近0的,使得z>0,对应于正例,(趋近于概率1),z<0对应于反例(趋近于概率0)。因此是使用了回归的思想去解决分类的问题。

核心:求解最优的边界函数z=XW(即求当z=0的时候的分界点)

核心:求解Z=XW=w0+w1x1+w2x2

机器学习之逻辑回归-逻辑回归的原理及python代码实现

h m o d e l = 1 1 + e − z h_{model} =\frac{1}{1+e^{-z} } hmodel=1+ez1
这里我们将传统的xy轴换成了x1,x2轴,其实我们要求解的就是z=0时的这条边界直线,这时概率也达到了分界线0.5(根据h(model)函数,当h=0.5达到分界线的时候,z取0,同样的当z取0的时候,h也达到了0.5),其实就是函数w1x1+w2x2+w0(截距)=0.

机器学习之逻辑回归-逻辑回归的原理及python代码实现

我们想做的就是让损失函数cost最小,这里我们在原函数上加上log是为了更方便的计算,由于我们需要0-1之间的数据,但是log在0-1之间的值小于0,所以我们在这里取-,让损失函数在我们需要的范围里面始终为+。在这里也称为对数拟合函数。为了方便计算我们对两部分数据的代价函数进行整合,这样当我们分类为1的时候后一项就成为0保留前半段的代价函数,分类为0的时候保留后半段的代价函数,前半段成为0.

5.求解过程

5.1目的:求最优的决策边界:

z = w 0 + w 1 x 1 + w 2 x 2 = [ 1 x 1 x 2 ] [ w 0 w 1 w 2 ] z=w0+w1x1+w2x2=\begin{bmatrix} 1&x1 &x2 \end{bmatrix}\begin{bmatrix} w0\\ w1\\ w2 \end{bmatrix} z=w0+w1x1+w2x2=[1x1x2]w0w1w2

即Z=XW,其中X的维度是(10,3)因为是10组数据,w的维度是(3,1),所以Z的维度就是(10,1),又因为
h m o d e l = 1 1 + e − z h_{model}=\frac{1}{1+e^{-z} } hmodel=1+ez1
所以
H = 1 1 + e − X W H=\frac{1}{1+e^{-XW} } H=1+eXW1
H维度与Z等同,也是(10,1)
h z ′ = ( 1 1 + e − z ) ′ = h ( 1 − h ) h_{z} '=(\frac{1}{1+e^{-z} } )'=h(1-h) hz=(1+ez1)=h(1h)
cost= - Y *log (H) - (1-Y *) log (1-H),cost维度也是(10,1)

其中 costhz~XW 而我们需要做的就是通过迭代去不断改进w的取值
d C o s t d W = d C o s t d H ∗ d H d Z ∗ d Z d W = X T ( H − Y ∗ ) \frac{\mathrm{d} Cost}{\mathrm{d} W} =\frac{\mathrm{d} Cost}{\mathrm{d} H} *\frac{\mathrm{d} H}{\mathrm{d} Z} *\frac{\mathrm{d} Z}{\mathrm{d} W}=X^{T}(H-Y^{*} ) dWdCost=dHdCostdZdHdWdZ=XT(HY)

d C d W = X T ( 1 1 + e − X W − Y ∗ ) 维 度 是 ( 3 , 1 ) \frac{\mathrm{d} C}{\mathrm{d} W} =X^{T} (\frac{1}{1+e^{-XW} }-Y^{*} )维度是(3,1) dWdC=XT(1+eXW1Y)3,1

5.2使用梯度下降法迭代求最优的W:

5.2.1.初始化W
5.2.2.更新W:

W = − a l p h a ∗ d C d W W=-alpha*\frac{\mathrm{d}C}{\mathrm{d}W} W=alphadWdC

5.3.3.迭代到一定次数或到一定阈值

机器学习之逻辑回归-逻辑回归的原理及python代码实现

5.3W求解之后画出决策边界

z=w0+w1x1+w2x2

上边式子中 x1对应于横坐标,x2对应于纵坐标

决策边界z=0,所以0=w0+w1x1+w2x2

所以
x 2 = − w 0 w 2 − w 1 w 2 x 1 x2=-\frac{w0}{w2}-\frac{w1}{w2}x1 x2=w2w0w2w1x1

3.python代码实现

3.1 ps:

1.Python strip()函数

Python strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。

**注意:**该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。语法如下:

str.strip([chars]);

2.split 函数

split的英文翻译为分裂。 Python中split()就是将一个字符串分裂成多个字符串,并以列表的形式返回。

语法:str.split(str="", num=string.count(str)),参数:str – 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等;num – 分割次数。默认为 -1, 即分隔所有。换句话说,split()当不带参数时以空格进行分割,当代参数时,以该参数进行分割。

3.numpy.random.randn()用法

3.1 numpy.random.rand(d0,d1,…,dn)
  • rand函数根据给定维度生成[0,1)之间的数据,包含0,不包含1
  • dn表示每个维度
  • 返回值为指定维度的array
np.random.rand(4,2)
array([[ 0.02173903,  0.44376568],
       [ 0.25309942,  0.85259262],
       [ 0.56465709,  0.95135013],
       [ 0.14145746,  0.55389458]])
3.2 numpy.random.randn(d0,d1,…,dn)
  • randn函数返回一个或一组样本,具有标准正态分布。
  • dn表格每个维度
  • 返回值为指定维度的array
np.random.randn(2,4)
array([[ 0.27795239, -2.57882503,  0.3817649 ,  1.42367345],
       [-1.16724625, -0.22408299,  0.63006614, -0.41714538]])
3.3 numpy.random.randint(low, high=None, size=None, dtype=’l’)
  • 返回随机整数,范围区间为[low,high),包含low,不包含high
  • 参数:low为最小值,high为最大值,size为数组维度大小,dtype为数据类型,默认的数据类型是np.int
  • high没有填写时,默认生成随机数的范围是[0,low)
np.random.randint(-5,5,size=(2,2))
array([[ 2, -1],
       [ 2,  0]])
3.4 生成 [0,1) 之间的随机浮点数
  • numpy.random.random_sample(size=None)
  • numpy.random.random(size=None)
  • numpy.random.ranf(size=None)
  • numpy.random.sample(size=None)

4.plt.scatter

绘制散点图 语法如下:

scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, hold=None, data=None, **kwargs)
  • x, y → 散点的坐标

  • s → 散点的面积

  • c → 散点的颜色(默认值为蓝色,‘b’,其余颜色同plt.plot( ))

  • marker → 散点样式(默认值为实心圆,‘o’,其余样式同plt.plot( ))

  • alpha → 散点透明度([0, 1]之间的数,0表示完全透明,1则表示完全不透明)

  • linewidths →散点的边缘线宽

  • edgecolors → 散点的边缘颜色

  • cmap → 指的是matplotlib.colors.Colormap,相当于多个调色盘的合集

  • norm、vmin、vmax → 散点颜色亮度设置

5.plt.grid()

显示网格线 1=True=默认显示;0=False=不显示

6.plt.legend

用于给图像加图例

图例是集中于地图一角或一侧的地图上各种符号和颜色所代表内容与指标的说明,有助于更好的认识地图。

7.np.arange

参数np.arange(start,stop, step,dtype=None)

arange函数用于创建等差数组 包含起点 不包含终点

start:可忽略不写,默认从0开始;起始值
stop:结束值;生成的元素不包括结束值
step:可忽略不写,默认步长为1;步长
dtype:默认为None,设置显示元素的数据类型

3.2代码部分

1.常规导入

导入我们需要的numpy和matplotlib包

# import lib常规导入
import numpy as np
import matplotlib.pyplot as plt

2.提供读取数据的接口

定义读取数据的函数,并将数据进行处理分割

# def loaddata  #将数据读入 并进行分割,得到x和y的矩阵
def loaddata(filename):      #定义一个function,用来读取我们写好的数据。
    file = open(filename)    #打开文件 存放于file中 
    x=[]
    y=[]  #将x,y定义为list格式
    for line in file.readlines(): #将每一行数据都读取出来
            line = line.strip().split()     #把分一条数据都分割成三部分 strip去除首尾空格,split按照中间的空格进行分割 返回列表
            x.append([1,float(line[0]),float(line[1])]) #将第一二两列也就是x1,x2两列加进x列表中,第一列为1,组成(10,3)矩阵 并将数据转换成float格式
            y.append(float(line[2]))  
    xmat = np.mat(x)
    ymat = np.mat(y).T  #将x,y转换成矩阵形式 方便计算对y进行转置
    file.close()   #关闭文件 解释内存
    return xmat,ymat    

3.梯度下降迭代求最优W,返回W

# w calc梯度下降法迭代求最优w 
def w_calc(xmat,ymat,alpha=0.001,maxItem=10000):   #学习率,最高迭代次数
    #w init
    W=np.mat(np.random.randn(3,1)) #初始化W,因为我们的w是(3,1)的矩阵,所以我们利用random函数随机生成一个(3,1)的矩阵,为了防止W变为0,我们使用randn函数生成正态分布的矩阵
    #w update #迭代更新W
    for i in range(maxItem):
        H = 1/(1+np.exp(-xmat*W))
        dw = xmat.T*(H-ymat) #维度(3,1)
        W -= alpha*dw #更新W 每迭代一次更新一次直至最高迭代次数maxItem
    return W

4.提供接口

# implement
xmat,ymat = loaddata("logistics.txt")   #文件是一个(10,3)的矩阵,前两列是x1,x2,第三列是标签,做二分类。
#print(xmat,xmat.shape)  #x为(10,2)矩阵
#print(ymat,ymat.shape)  #y为(10,1)矩阵
W=w_calc(xmat,ymat,0.001,20000)
print('W=',W)

5.展示结果

# show
w0 = W[0,0]
w1 = W[1,0]
w2 = W[2,0] #W是(3,1)矩阵
plotx1 = np.arange(1,7,0.01)
plotx2 = -w0/w2-w1/w2*plotx1
plt.plot(plotx1,plotx2,c='r',label='decision boundary')
plt.scatter(xmat[:,1][ymat==0].A,xmat[:,2][ymat==0].A,marker='*',s=150,label='label=0') #将x第一列x1作为横坐标(因为第0列是1 我们需要后两列x1x2),x第二列作为纵坐标
plt.scatter(xmat[:,1][ymat==1].A,xmat[:,2][ymat==1].A,marker='^',s=150,label='label=1') #把x1x2中y标签是0的算一种颜色,标签是1的算另一种颜色
plt.grid()
plt.legend()
plt.show()

本文地址:https://blog.csdn.net/qq_42504905/article/details/109856460