Logistic回归算法

今天的文章看一下《机器学习实战》中提到的Logistic回归算法。虽然是名称是回归,但Logistic算法并不用来进行拟合,主要用来处理分类问题。


对于二分类问题,我们假设正类的标签值为1,反类的标签值为0,我们可以寻找一个函数,在给定输入(样本特征值)下,可以输出0或者1。最好的函数应该是单位阶跃函数,如图所示:


但是,单位阶跃函数存在一个问题,在0处,函数不连续,这会给我们的后续的数学运算带来很多问题。所以,我们可以找到一个替代的函数,那就是sigmoid函数:


函数的图像为


可以看出,0.5是我们正类和反类的分界值。结合我们的分类问题:


其中,x是一条样本数据的特征值向量,w是每一个特征值的权重向量。所以,现在问题就转化为,我们如何确定一组最合适的特征值权重,使得我们训练集的样本数据能够很好地满足sigmoid函数,基于这样的一组权重,当有新的数据需要分类时,我们就可以按照上式,求取z值并代入sigmoid函数,从而完成分类。


那么如何确定权重呢?这里我们使用极大似然估计,可以从网上看看相关的文章,简单来说,根据极大似然估计,我们需要求下面式子的最大值:


其中yi代表第i条样本数据的标签,xi代表第i条样本数据中的特征值组成的向量。为求取L(w)的最大值,我们使用梯度上升法:


这里wj代表第j个特征对应的权重值。而上式中L(w)的相对于w的偏导数为:


其中xji代表第j个特征在第i条样本数据中的值,ei代表第i条训练样本数据的真实标签值和估计标签值之间的误差。上面就是基本的理论介绍,下面看看代码实现,可能就会更加直观。

首先是sigmoid函数:

def sigmoid(in_x, scale=0.01):
    return 1.0 / (1 + np.exp(-in_x * scale))

梯度上升法:

def grad_ascent(data_in_mat, class_labels):
    data_matrix = np.mat(data_in_mat)
    label_mat = np.mat(class_labels).T

    m, n = np.shape(data_matrix)
    alpha = 0.001
    max_cycle = 500
    weights = np.ones((n, 1))
    for k in range(max_cycle):
        h = sigmoid(data_matrix * weights)
        error = label_mat - h
        weights = weights + alpha * data_matrix.T * error

    return weights

输入参数为训练样本数据以及对应的标签。程序中循环500次,初始的weights全为1,调用sigmoid函数计算预估值,之后与标签计算误差,最后根据梯度上升法更新weights。


我们需要一个函数来进行分类:

def classify_vector(in_x, weights):
    prob = sigmoid(sum(in_x * weights))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0

将待测数据和梯度上升获得的weights传入该函数,该函数会调用sigmoid函数,之后按照值是否大于0.5对其进行分类。


下面写一个例子,使用上面的三个函数:

def classify_test(in_x):
    data_mat = np.mat([[1, 2, 7], [1, 4, 5], [6, 2, 2],
                       [3, 1, 6], [2, 2, 6], [1, 7, 2]])
    labels_mat = np.mat([0.0, 1.0, 1.0, 0.0, 0.0, 1.0])
    weights = grad_ascent(data_mat, labels_mat)
    return classify_vector(in_x, weights)


if __name__ == '__main__':
    test_mat = [[2, 7, 1], [5, 2, 3], [2, 2, 6], [1, 1, 8]]
    test_result = []
    for i in test_mat:
        test_result.append(classify_test(i))
    print(test_result)

我们人为构造了一些数据,三个数均大于0,和不会超过10,前两个数的和大于等于5时,标签为1,否则为0。然后我们测试了四条样本数据,这四条样本数据,按照我们的规则,标签应为[1.0, 1.0,0.0,.0.0]。


我们运行一下程序,看看输出结果:

[1.0, 1.0, 0.0, 0.0]


和我们的完全吻合,当然,毕竟我们的训练样本数据偏少,因此存在欠拟合的问题,尝试修改测试数据,会出现预测失败的情况。


猜你喜欢

转载自blog.csdn.net/yjp19871013/article/details/79652507