机器学习_逻辑回归

XDU机器学习第二次作业


 目录

XDU机器学习第二次作业

一、逻辑回归

数据可视化

热身练习:Sigmoid函数

代价函数与梯度

预测函数

使用scipy.optimize.fmin_cg学习模型参数

 二、正则化的逻辑回归:

数据可视化

特征变换

代价函数与梯度

模型训练


一、逻辑回归

        本次作业的目的是建立一个逻辑回归模型,用于预测一个学生是否应该被大学录取。

简单起见,大学通过两次考试的成绩来确定一个学生是否应该录取。你有以前数届考生的成绩,可以做为训练集学习逻辑回归模型。每个训练样本包括了考生两次考试的成绩和对应的录取决定。

你的任务是建立一个分类模型,根据两次考试的成绩来估计考生被录取的概率。 本次实验需要实现的函数


# 导入需要用到的库
import numpy as np
import scipy.optimize as op
import matplotlib.pyplot as plt

数据可视化

        在实现机器学习算法前,可视化的显示数据以观察其规律通常是有益的。本次作业中,你需要实现 plot_data 函数,用于绘制所给数据的散点图。你绘制的图像应如下图所示,两坐标轴分别为两次考试的成绩,正负样本分别使用不同的标记显示。

def plot_data(X, y):
    """This function plots the data points X and y into a new figure.
    It plots the data points with red + for the positive examples,
    and blue o the negative examples. X is assumed to be a Mx2 matrix.
    
    X: shape:nx2 
    y: shape:nx1
    """

    plt.figure()
    # ====================== YOUR CODE HERE ======================
    ax = list()
    ay = list()
    bx = list()
    by = list()
    for i in range(len(y)):
        if y[i] == 0:
            ax.append(X[i][0])
            ay.append(X[i][1])
        else:
            bx.append(X[i][0])
            by.append(X[i][1])
    plt.plot(ax, ay, 'r+', label="Not admitted")
    plt.plot(bx, by, 'bo', label='Admitted')
    # ============================================================

    plt.xlabel("Exam 1 Score")
    plt.ylabel("Exam 2 Score")
    plt.legend(loc='upper right')

调用 plot_data,可视化第一个文件LR_data1数据。绘制的图像如下:

# 加载数据 注意使用 !ls 或 !find 命令确定数据文件所在的目录 dataXXXX 。
data = np.loadtxt("LR_data1.txt", delimiter=",")
X, y = data[:, :2], data[:, 2]

# 可视化数据
# ====================== YOUR CODE HERE ================
plot_data(X, y)
# ======================================================
plt.show()

 运行结果:

       

绘制分类面:

def plot_decision_boundary(theta, X, y):
    """绘制分类面。"""
    plot_data(X[:, 1:], y)

    _, d = X.shape

    if d <= 3:
        plot_x = np.array([np.min(X[:, 1])-2, np.max(X[:, 1])+2])
        plot_y = -1.0 / theta[2]*(theta[1]*plot_x + theta[0])
        plt.plot(plot_x, plot_y, 'm-', label="Decision Boundary")

        plt.xlim([30, 100])
        plt.ylim([30, 100])
    else:
        n_grid = 50
        u = np.linspace(-1, 1.5, n_grid)
        v = np.linspace(-1, 1.5, n_grid)

        z = np.zeros((n_grid, n_grid))

        for i in range(n_grid):
            for j in range(n_grid):
                uu, vv = np.array([u[i]]), np.array([v[j]])
                z[i, j] = np.dot(map_feature(uu, vv), theta)

        z = z.T

        CS = plt.contour(u, v, z, linewidths=2, levels=[0.0], colors=['m'])
        CS.collections[0].set_label('Decision boundary')

    plt.legend()

热身练习:Sigmoid函数

        逻辑回归的假设模型为:

         其中函数 g(⋅)g(\cdot)g(⋅) 是Sigmoid函数,定义为:

         本练习中第一步需要你实现 Sigmoid 函数。在实现该函数后,你需要确认其功能正确。对于输入为矩阵和向量的情况,你实现的函数应当对每一个元素执行Sigmoid 函数。

def sigmoid(z):
    """Compute sigmoid function"""

    z = np.asarray(z)
    g = np.zeros_like(z)

    # ====================== YOUR CODE HERE ======================
    g = 1/(1+np.exp(-z))
    # ============================================================

    return g
# 测试 sigmoid 函数
z = np.array([-10.0, -5.0, 0.0, 5.0, 10.0])
g = sigmoid(z)
print("Value of sigmoid at [-10, -5, 0, 5, 10] are:\n", g)

 运行结果:


代价函数与梯度

        现在你需要实现逻辑回归的代价函数及其梯度。补充完整cost_function函数,使其返回正确的代价。补充完整cost_gradient函数,使其返回正确的梯度。

逻辑回归的代价函数为:

 对应的梯度向量各分量为:

def cost_function(theta, X, y):
    """逻辑回归的代价函数,无正则项。"""

    J = 0.0
    # ====================== YOUR CODE HERE ======================
    
    J = (-y*np.log(sigmoid(np.dot(X,theta.T))) - (1-y)*np.log(1-sigmoid(np.dot(X,theta.T))))
    J = np.mean(J, axis=0)
    # ============================================================

    return J

预测函数

        在获得模型参数后,你就可以使用模型预测一个学生能够被大学录取。如果某学生考试一的 成绩为45,考试二的成绩为85,你应该能够得到其录取概率约为0.776。

你需要完成 predict 函数,该函数输出“1”或“0”。通过计算分类正确的样本百分数, 我们可以得到训练集上的正确率。

def predict(theta, X):
    """Predict whether the label is 0 or 1
    using learned logistic regression parameters theta.
    input: theta:model's parameters
            X: input samples
    output:0 or 1
    """
    m, _ = X.shape
    pred = np.zeros((m, 1), dtype=np.bool)

    # ====================== YOUR CODE HERE ======================
    pred = (np.dot(X, theta.T) > 0.5)
    # ============================================================

    return pred

使用scipy.optimize.fmin_cg学习模型参数

        在本次作业中,希望你使用 scipy.optimize.fmin_cg 函数实现代价函数 J(θ)J(\theta)J(θ) 的优化,得到最佳参数 θ∗\theta^{*}θ∗ 。

使用该优化函数的代码已经在程序中实现,调用方式示例如下:

         其中cost_function为代价函数, theta 为需要优化的参数初值, fprime=cost_gradient 给出了代价函数的梯度, args=(X, y) 给出了需要优化的函数与对应的梯度计算所需要的其他参数, maxiter=400 给出了最大迭代次数, full_output=True 则指明该函数除了输出优化得到的参数 theta_opt 外,还会返回最小的代价函数值 cost_min 等内容。

对第一组参数,得到的代价约为 0.203 (cost_min)。

def logistic_regression():
    """针对第一组数据建立逻辑回归模型。"""

    # 加载数据
    data = np.loadtxt("LR_data1.txt", delimiter=",")
    X, y = data[:, :2], data[:, 2]

    # 计算代价与梯度
    m, _ = X.shape
    X = np.hstack((np.ones((m, 1)), X))

    # 初始化参数
    theta_initial = np.zeros_like(X[0])

    # 计算并打印初始参数对应的代价与梯度
    cost = cost_function(theta_initial, X, y)
    grad = cost_gradient(theta_initial, X, y)
    print("Cost at initial theta (zeros): ", cost)
    print("Gradient at initial theta (zeros): \n", grad)

    # 使用 scipy.optimize.fmin_cg 优化模型参数
    args = (X, y)
    maxiter = 200
    # ====================== YOUR CODE HERE ======================


    ret = op.fmin_cg(cost_function,
                 theta_initial,
                 fprime=cost_gradient,
                 args=(X, y),
                 maxiter=400,
                 full_output=True)

    
    # ============================================================
    theta_opt, cost_min, _, _, _ = ret
    print("Cost at theta found by fmin_cg: ", cost_min)
    print("theta_op: \n", theta_opt)

    # 绘制分类面
    plot_decision_boundary(theta_opt, X, y)
    plt.show()

    # 预测考试一得45分,考试二得85分的学生的录取概率
    x_test = np.array([1, 45, 85.0])
    prob = sigmoid(np.dot(theta_opt, x_test))
    print('For a student with scores 45 and 85, we predict an admission probability of: ', prob)

    # 计算在训练集上的分类正确率
    p = predict(theta_opt, X)
    print("Train Accuracy: ", np.mean(p == y)*100.)
   
logistic_regression()

运行结果:


 二、正则化的逻辑回归:


数据可视化

        调用函数plot_data可视化第二组数据 LR_data2.txt 。 正确的输出如下:

# 加载数据
data = np.loadtxt("LR_data2.txt", delimiter=",")
X, y = data[:, :2], data[:, 2]

# 可视化数据
# ====================== YOUR CODE HERE ================
plot_data(X, y)
# ======================================================
plt.show()

运行结果:


特征变换

        创建更多的特征是充分挖掘数据中的信息的一种有效手段。在函数 map_feature 中,我们将数据映射为其六阶多项式的所有项。


def map_feature(X1, X2, degree=6):
    """Feature mapping function to polynomial features."""
    m = len(X1)
    assert len(X1) == len(X2)
    n = int((degree+2)*(degree+1)/2)

    out = np.zeros((m, n))

    idx = 0
    for i in range(degree+1):
        for j in range(i+1):
            # print i-j, j, idx
            out[:, idx] = np.power(X1, i-j)*np.power(X2, j)
            idx += 1

    return out

代价函数与梯度

       逻辑回归的代价函数为:

        对应的梯度向量各分量为:

完成以下函数:

  • cost_function_reg()
  • cost_gradient_reg()
    def cost_function_reg(theta, X, y, lmb):
        """逻辑回归的代价函数,有正则项。"""
        m = 1.0*len(y)
        J = 0
        # ====================== YOUR CODE HERE ======================
        hx = np.log(sigmoid(np.dot(X,theta.T)))   
        
        J = np.mean(-y*np.log(hx) - (1-y)*np.log(1-hx)) + \
            lmb/(2*m) * (theta**2).sum()
        # ============================================================
        return J
    
    def cost_gradient_reg(theta, X, y, lmb):
        """逻辑回归的代价函数的梯度,有正则项。"""
    
        m = 1.0*len(y)
        grad = np.zeros_like(theta)
        # ====================== YOUR CODE HERE ======================
        hx = np.log(sigmoid(np.dot(X,theta.T)))  
        theta[0] = np.mean((hx-y)*X[:,0])
        temp = theta[1:]
        temp = temp.reshape(len(theta)-1,1)
        #print(np.mean((hx-y)*X[:,1:]).shape)
        a = hx-y
        a = a.reshape(len(a),1)
        '''
        print('a',a.shape)
        print('temp',temp.shape)
        print('lmb/',(lmb/m*temp).shape)
        print('X[:,1:]',X[:,1:].shape)
        print('np.mean(a*X[:,1:])',np.mean(a*X[:,1:]).shape)
        print((a*X[:,1:]).shape)
        '''
        ccc = (np.mean(a*X[:,1:]) + lmb/m*temp).reshape((temp.shape[0]))
        #print('ccc',ccc.shape)
        #theta[1:] = np.mean(a*X[:,1:]) + lmb/m*temp
        theta[1:] = ccc
        # ============================================================
    
        return grad

    模型训练

        如果将参数θ\thetaθ 初始化为全零值,相应的代价函数约为 0.693。可以使用与前述无正则化项类似的方法实现梯度下降, 获得优化后的参数 θ∗\theta^{*}θ∗ 。 你可以调用 plot_decision_boundary 函数来查看最终得到的分类面。建议你调整正则化项的系数,分析正则化对分类面的影响!

参考输出图像:

def logistic_regression_reg(lmb=1.0):
    """针对第二组数据建立逻辑回归模型。"""

    # 加载数据
    data = np.loadtxt("LR_data2.txt", delimiter=",")
    X, y = data[:, :2], data[:, 2]

    # 计算具有正则项的代价与梯度

    # 注意map_feature会自动加入一列 1
    X = map_feature(X[:, 0], X[:, 1])
    print(X.shape)
    # 初始化参数
    theta_initial = np.zeros_like(X[0, :])

    # 计算并打印初始参数对应的代价与梯度
    cost = cost_function_reg(theta_initial, X, y, lmb=lmb)
    grad = cost_gradient_reg(theta_initial, X, y, lmb=lmb)
    print("Cost at initial theta (zeros): ", cost)
    print("Gradient at initial theta (zeros): \n", grad)

    # 使用 scipy.optimize.fmin_cg 优化模型参数
    args = (X, y, lmb)
    maxiter = 200
    # ====================== YOUR CODE HERE ======================

    ret = op.fmin_cg(cost_function,
                 theta_initial,
                 fprime=cost_gradient,
                 args=(X, y),
                 maxiter=500,
                 full_output=True)

    # ============================================================
    theta_opt, cost_min, _, _, _ = ret
    print("Cost at theta found by fmin_cg: ", cost_min)
    print("theta_op: \n", theta_opt)

    # 绘制分类面
    plot_decision_boundary(theta_opt, X, y)
    plt.title("lambda = " + str(lmb))
    plt.show()

    # 计算在训练集上的分类正确率
    pred = predict(theta_opt, X)
    print("Train Accuracy: ", np.mean(pred == y)*100)
# 可选:尝试不同正则化系数lmb = 0.0, 1.0, 10.0, 100.0对分类面的影响
logistic_regression_reg(lmb=1.0) 

运行结果:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值