机器学习基础练习题(1)逻辑回归

作业题目

设想你是某门课程的教师,想通过学生平时和期末两次的评定成绩,来决定他们是否通过这门课程。现在你拥有之前学生的可以用于训练逻辑回归的训练样本集logistic_regression_data-1.txt。对于每一个训练样本,你有他们平时和期末评分及最后是通过课程的结果(1为通过,0为不通过)。由此建立逻辑回归分类器。

问题概述

逻辑回归(Logistic Regression)是一种用于解决二分类(0 or 1)问题的机器学习方法,用于估计某种事物的可能性。本次作业需要通过编写python程序实现一个逻辑回归分类器,通过一个学生两次考试的成绩,判断他们是否可以通过此次课程。

代价函数

构造代价函数如下图所示:
L o s s ( h θ ( x ) , y ) = ∑ − y ∗ l o g ( h θ ( x ) ) − ( 1 − y ) ∗ l o g ( 1 − h θ ( x ) ) Loss(h_\theta(x),y)=\sum -y*log(h_\theta(x))-(1-y)*log(1-h_\theta(x)) Loss(hθ(x),y)=ylog(hθ(x))(1y)log(1hθ(x))
在上式中
h θ ( x ) = 1 1 + e ( − θ T x ) h_\theta(x)=\frac{1}{1+e^(-\theta^Tx)} hθ(x)=1+e(θTx)1
Python代码为:

def Loss(W)
	loss = 0.0
    for i in range(N):
        loss += -Y[i]*np.log(sig(np.inner(W,X[i]))) - (1 - Y[i])*np.log(1 - sig(np.inner(W,X[i])))
    return loss

求解最优化问题

梯度下降法

梯度下降法的下降方向在每次迭代时都指向梯度下降最快的方向。这种方法在远离最优解时下降速度很快,但越靠近最优解收敛速度越慢,所以很难收敛。
梯度下降法示意图
同时,梯度下降法的学习率参数不能指定过大,否则可能出现np.log函数无法正常计算的问题。在循环中还需要加上最大迭代次数,避免因为不收敛而无法跳出循环。

牛顿法

牛顿法算法
牛顿法可以直接以全局的最优解为方向优化问题,而不依靠局部的梯度方向,所以牛顿法更容易收敛。牛顿法需要计算出代价函数的Hessian矩阵,前提是该矩阵必须正定,如果矩阵非正定则需要使用拟牛顿法,构造校正矩阵代替Hessian阵。
牛顿法可以很快收敛得到优化问题的最优解。通过以上两种方法可以求得决策边界的系数。

结果验证

在这里插入图片描述
通过运算得到了决策边界的系数(分别对应w0+w1x1+w2w2=0的三个系数),以及运算结果与最优值的误差值,以及迭代次数。可以发现梯度下降法迭代到了设置的最大次数(10000次),而牛顿法迭代两次就得到了最优解。
在这里插入图片描述

上图中,绿色边界为牛顿法得到的边界,而蓝色边界为梯度下降法得到的结果,可见最速下降法还远远没有迭代结束。
在这里插入图片描述
在这里插入图片描述
由上图可以看出牛顿法的决策边界基本正确,有个别散点落在了其他区域,但整体来说,边界是正确的。对于训练数据来说,该模型的准确率可以达到:90/100=90%。

作业代码

import numpy as np
import matplotlib.pyplot as plt

def readData():
    X = []
    Y = []     
    with open ('logistic_regression_data-1.txt','r') as file:
        for line in file.readlines():
            cur_line = line.strip().split(',')
            X.append([1.0, float(cur_line[0]),float(cur_line[1])])
            Y.append(float(cur_line[-1]))
    X = np.asarray(X, dtype=np.double)
    N = X.shape[0]
    Y = np.asarray(Y, dtype=np.double)
    return N,X,Y

def sig(x):
    return 1/(1 + np.exp(-x))

def Loss(W):

    loss = 0.0
    for i in range(N):
        loss += -Y[i]*np.log(sig(np.inner(W,X[i]))) - (1 - Y[i])*np.log(1 - sig(np.inner(W,X[i])))
    return loss

def GD(X,Y,eta,tol):

    W = np.array([0.0,0.0,0.0])
    error = 10   
    steps = 0
    stepL = []
    errorL = []
    max_cycle = 10000
    while((error > tol)&(steps<max_cycle)):
        l1 = Loss(W)
        steps += 1
        deltaW = 0 
        deltaW += gradL(X,Y,W)
        W = W - eta*deltaW  
        l2 = Loss(W)
        error = np.abs(l2 - l1)
        stepL.append(steps)
        errorL.append(error)
    plt.scatter(stepL,errorL)
    plt.show()
    return W,error,steps    

def gradL(X,Y,W):

    Y = np.squeeze(Y)
    D = sig(np.inner(W,X)) - Y      
    G = np.inner(X.T,D)
    return G

def hessian(X,N,W):

    h_w = []
    for i in range(N):    
        h_w += [sig(np.inner(W,X[i]))*(1 - sig(np.inner(W,X[i])))] 
    
    h_w = np.asarray(h_w)
    B = np.diag(h_w)
    H = np.dot(X.T,np.dot(B,X))
    return H
    
def Newton(X,Y,tol):

    W = np.array([0.0,0.0,0.0])
    error = 10
    steps = 0
    stepL = []
    errorL = []
    while(error > tol):
        l1 = Loss(W)
        steps += 1
        for i in range(N):
            H = hessian(X,N,W)
            G = gradL(X,Y,W)
            W = W - np.dot(np.linalg.pinv(H),G)
        l2 = Loss(W) 
        error = np.abs(l2 - l1)
        stepL.append(steps)
        errorL.append(error)
    plt.scatter(stepL,errorL)
    plt.show()
    return W,error,steps  

if __name__ == '__main__':  
    
    N,X,Y = readData()   
    W, error,steps = GD(X,Y,0.00001,10**(-4))
    print("\nGradient Descent\n", W, "\nError: ", error, " Steps: ", steps)
    
    W2, error,steps = Newton(X,Y,10**(-5))
    print("\nNewton's\n", W2, "\nError: ", error, " Steps: ", steps)

    X1_0 = []
    X2_0 = []
    X1_1 = []
    X2_1 = []
    for i,t in enumerate(Y):
        if(t == 0):
            
            X1_0 += [X[:,1][i]]
            X2_0 += [X[:,2][i]]
        else:
            X1_1 += [X[:,1][i]]
            X2_1 += [X[:,2][i]]
                   
    plt.scatter(X1_0,X2_0, s=30, c='red', marker='s')
    plt.scatter(X1_1,X2_1, s=30, c='green')
    X1 = X[:,1]
    #T1 = - W[1]/W[2]*X1
    #T2 = [-W[0]/W[2] for i in range(X.shape[0])]
    #Y1 = T2 + T1

    T1 = - W2[1]/W2[2]*X1
    T2 = [-W2[0]/W2[2] for i in range(X.shape[0])]
    Y2 = T2 + T1
        
    #plt.plot(X1,Y1,'-')
    plt.plot(X1,Y2,'-.')
    plt.xlabel('1st Exam Score')
    plt.ylabel('2nd Enam Score')
    plt.show()

逻辑回归是一种常用的机器学习算法,用于解决二分类问题。它基于线性回归模型,通过对输出进行逻辑函数(如sigmoid函数)的转换,将输出限制在0和1之间,从而实现对样本的分类。 以下是一些关于逻辑回归理论的习题及其答案: 1. 什么是逻辑回归? 答:逻辑回归是一种用于解决二分类问题的机器学习算法。它通过对线性回归模型的输出进行逻辑函数转换,将输出限制在0和1之间,从而实现对样本的分类。 2. 逻辑回归的损失函数是什么? 答:逻辑回归使用的损失函数是对数损失函数(log loss),也称为交叉熵损失函数。它衡量了模型预测结果与真实标签之间的差异。 3. 逻辑回归的优化算法有哪些? 答:逻辑回归的优化算法包括梯度下降法(包括批量梯度下降、随机梯度下降和小批量梯度下降)、牛顿法和拟牛顿法(如L-BFGS)等。 4. 逻辑回归如何处理多分类问题? 答:逻辑回归本身是二分类算法,但可以通过一对多(One-vs-Rest)或一对一(One-vs-One)的方式来处理多分类问题。一对多方法将每个类别与其他类别进行二分类,得到多个二分类模型;一对一方法则将每两个类别之间进行二分类,得到多个二分类模型。 5. 逻辑回归有哪些优点和缺点? 答:逻辑回归的优点包括模型简单、计算效率高、可解释性强等;缺点包括对特征的线性关系假设较强、容易受到异常值的影响等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值