逻辑回归python实现

对线性函数进行逻辑回归用python实现

前面主要是用octave实现了逻辑回归的算法,但是觉得在实际开发过程中用到octave的并不多,因此还是需要学习python,希望能通过这两天的学习把算法流程搞清楚,需要做什么事情。也使用了sklearn这个库,可以直接调用方法实现,因此缺点是不能看到一些算法的实现过程。

先介绍一下使用python的基本包的作用:

matplotlib帮助画图,numpy处理数值型的数组,pandas处理很多类型的数据。

matplotlib能够将数据可视化,使数据更加客观,更具有说服力,他是用python实现,是最流行的python底层绘图库,主要做数据可视化图表。

plt.xticks()函数设置x轴的刻度

numpy帮助我们处理数值型数据,用于大型、多维数组上执行数值运算

下面这个是进行逻辑回归使用的数据集的展示:

代码如下:

import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize as opt
from sklearn.metrics import classification_report
import pandas as pd


def raw_data(path):
    """
       从文件中读取数据,并把每一列存储到一个列表中,那么存储完之后就如上图所示    
    """

    data=pd.read_csv(path,names=['exam1','exam2','admit'])
    return data


def draw_data(data):
    """
       我的理解是把admit那一列中值为1的那一行数据存储到列表accept中,同理refuse,其中1代表样本是正的(被接纳),0代表样本是负的(未被接纳),并把这两种数据点在图中标注出来,被接纳的用绿色表示,不被接纳的用红色表示
    """

    accept=data[data['admit'].isin([1])]
    refuse=data[data['admit'].isin([0])]
     plt.scatter(accept['exam1'],accept['exam2'],c='g',label='admit')
    plt.scatter(refuse['exam1'],refuse['exam2'],c='r',label='not admit')
    plt.title('admission')
    plt.xlabel('score1')
    plt.ylabel('score2')
    return plt

def sigmoid(z):
    """
       根据公式定义sigmoid函数    
    """
    return 1/(1+np.exp(-z))

def cost_function(theta,x,y):
    """
        百度查了查,发现shape[0]就是读取矩阵第一维度的长度,在这里m就是样本的数量   
a.dot(b) 与 np.dot(a,b)效果相同,都是计算两个矩阵相乘
但需注意,矩阵积计算不遵循交换律,np.dot(a,b) 和 np.dot(b,a) 得到的结果是不一样的

    """
    m=x.shape[0]
    j=(y.dot(np.log(sigmoid(x.dot(theta))))+(1-y).dot(np.log(1-sigmoid(x.dot(theta)))))/(-m)
    return j



def gradient_descent(theta,x,y):
    """
       计算偏导数也就是梯度下降法求最优值 
    """

    return ((sigmoid(x.dot(theta))-y).T).dot(x)

def predict(theta,x):
    """
       这个是根据sigmoid函数的图像得出的结论 
    """
    h=sigmoid(x.dot(theta))
    return [1 if x>=0.5 else 0 for x in h]

def boundary(theta,data):
    """
       绘制出边界曲线
    """
    x1=data['exam1']
    x2=(theta[0]+theta[1]*x1)/-theta[2]
    plt=draw_data(data)
    plt.title('boundary')
    plt.plot(x1,x2)
    plt.show()


def main():
    data=raw_data('venv/lib/dataset/ex2data1.txt')
    x1=data['exam1']
    x2=data['exam2']

    """
       np.c_中的c是column(列)的缩写,是按列叠加两个矩阵的意思,
       也可以说是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等
    
    """
    x=np.c_[np.ones(x1.shape[0]),x1,x2]
    y=data['admit']
    theta=np.zeros(x.shape[1])
      theta=opt.minimize(fun=cost_function,x0=theta,args=(x,y),method='tnc',jac=gradient_descent)
    theta=theta.x
    print(classification_report(predict(theta,x),y))
    boundary(theta,data)

main()

其中有些代码不会查了查,总结如下:

Q(1)x2=(theta[0]+theta[1]*x1)/-theta[2] 什么意思?

A:我把线性回归和逻辑回归给弄混了,线性回归是线性的,只有x0和x1两个特征。其中x0=1。而逻辑回归是分类问题,他需要拟合这两类数据画一条直线,因此其实有x0,x1,x2这三个特征,其中x0=1。那么h(x)=0时,就会变成一个线性函数,x1和x2充当了坐标轴,用来拟合数据,因此正好可以得到上面的式子。

Q(2)我定义了代价函数和梯度下降函数,怎么来最小化目标函数呢?

A:我认为优化的过程是要先求出theta的值,然后把theta带入代价函数中计算,经过很多次的迭代下降,最后使J的值最小。在具体实现时利用了这个函数theta=opt.minimize(fun=cost_function,x0=theta,args=(x,y),method='tnc',jac=gradient_descent),那么这个函数会返回优化问题的目标数组x,因此再调用theta=theta.x得到优化的对象theta。

代码测试结果如下:

对非线性函数进行逻辑回归用python实现

这个数据集的展示:

代码如下:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn import linear_model
import scipy.optimize as opt
from sklearn.metrics import classification_report


def raw_data(path):

    """
          调用这个函数读取文件中的数据,然后以上图的格式存储到列表中 
    """

    data=pd.read_csv(path,names=['test1','test2','accept'])
    return data


def draw_data(data):
    accept=data[data['accept'].isin(['1'])]
    reject=data[data['accept'].isin(['0'])]
    plt.scatter(accept['test1'],accept['test2'],c='g')
    plt.scatter(reject['test1'],reject['test2'],c='r')
    plt.title('raw_data')
    plt.xlabel('test1')
    plt.ylabel('test2')
    return plt

def feature_mapping(x1,x2,power):
    """
          这个函数还不太懂 
    """

    datamap={}
    for i in range(power+1):
        for j in range(i+1):
            datamap["f{}{}".format(j,i-j)]=np.power(x1,j)*np.power(x2,i-j)
    return pd.DataFrame(datamap)


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


def regularized_cost_function(theta,x,y,lam):
    """
          先获取样本的数量m,然后写出吴老师讲的公式
penalty就是偏置项用来正则化
    """

    m=x.shape[0]
    j=((y.dot(np.log(sigmoid(x.dot(theta)))))+((1-y).dot(np.log(1-sigmoid(x.dot(theta))))))/-m
    penalty=lam*(theta.dot(theta))/(2*m)
    return j+penalty


def regularized_gradient_descent(theta,x,y,lam):
    m=x.shape[0]
    partial_j=((sigmoid(x.dot(theta))-y).T).dot(x)/m
    partial_penalty=lam*theta/m
    partial_penalty[0]=0
    return partial_j+partial_penalty


def predict(theta,x):
    h=x.dot(theta)
    return [1 if x>=0.5 else 0 for x in h]


def boundary(theta,data):

    """
          这个函数还不太懂 
    """

    x = np.linspace(-1, 1.5, 200)
    x1, x2 = np.meshgrid(x, x)
    z = feature_mapping(x1.ravel(), x2.ravel(), 6).values
    z = z.dot(theta)
    z = z.reshape(x1.shape)
    plt=draw_data(data)
    plt.contour(x1,x2,z,0)
    plt.title('boundary')
    plt.show()


def main():
    rawdata=raw_data('venv/lib/dataset/ex2data2.txt')
        data=feature_mapping(rawdata['test1'],rawdata['test2'],power=6)
    
    x=data.values
    y=rawdata['accept']
    theta=np.zeros(x.shape[1])
        theta=opt.minimize(fun=regularized_cost_function,x0=theta,args=(x,y,1),method='tnc',jac=regularized_gradient_descent).x
    boundary(theta,rawdata)


main()

Q(1)feature_mapping(x1,x2,power)这个函数的是干嘛的?

A:这个函数是构建多项式特征值,应该是h(x)=1+x1+x2+x^2+x1x2+x^2+...

那么这个是6次的,因此会很长,就是创建这样的假设函数,然后带入代价函数和梯度函数求最小化的目标值theta,最后使用画图把图画出来。

部分参考此篇博客链接https://blog.youkuaiyun.com/zy1337602899/article/details/84777396

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值