机器学习算法(1)——Logistic Regression

1、二项逻辑回归模型

二项回归模型是一种二分类模型,由条件概率分布 P(Y|X) 表示,形式为参数化的逻辑分布。这里的随机变量 X 取值为实数,随机变量 Y 取值为 1或0 ,通过监督学习的方法来估计模型参数。

定义1:二项逻辑回归模型是如下的条件概率分布:

\large P(Y=1|x)=\frac{exp(wx+b)}{1+exp(wx+b)}

\large P(Y=0|x)=\frac{1}{1+exp(wx+b)}

这里x为输入,y为{0,1}输出,w为权值参数向量,b为偏置向量,wx为w和x的内积。

2、模型参数的估计

逻辑回归模型学习时,对于给定的数据集 T={(x1,y1),(x2,y2),...,(xn,yn)} 其中x属于R,yi属于{0,1},可以用极大似然估计法估计模型参数,从而得到逻辑回归模型:

设:P(Y=1|x) = h(x),  P(Y=0|x) = 1-h(x),其似然函数为:

                  \large \prod_{i=1}^{N}[\pi (x_{i})]^{y_{i}}[1-\pi(x_{i})]^{y_{i}}

\large L(w)=\sum_{i=1}^{N}[y_{i}log\pi (x_{i})+(1-y_i)log(1-\pi(x_i))]

         \large \sum_{i=1}^{N}[y_{i}log\frac{\pi(x_i)}{1-\pi(x_i)}+log(1-\pi(x_i))]

         \large \sum_{i=1}^{N}[y_{i}(w\cdot x_{i})+log(1+\exp(w\cdot x_i))]

对L(w)函数求极大值,就可以得到w的估计值。

这样,问题就变成了以对数似然函数为目标函数的最优化问题。逻辑回归学习中通常采用的方法是梯度下降法以及牛顿法,下文使用梯度下降法。

假设w的极大似然估计值是w^,那么学到的逻辑回归模型为:

\large P(Y=1|x)=\frac{exp(\hat{w}x+b)}{1+exp(\hat{w}x+b)}

\large P(Y=0|x)=\frac{1}{1+exp(\hat{w}x+b)}

3、利用梯度下降法训练获取逻辑回归模型的参数

把上述中的似然函数作为模型参数估计的损失函数,通过梯度下降法对其进行求解,其梯度为:

     \large L(w)=\sum_{i=1}^{N}[y_{i}(w\cdot x_{i})+log(1+\exp(w\cdot x_i))]

     \large L^{'}(w)=\sum_{i=1}^{N}[y_{i} x_{i}+\frac{x_i\exp(w\cdot x_i)}{1+\exp(w\cdot x_i)}]
    \large h_{W,b}(X_i)=\frac{\exp(w\cdot x_i)}{1+\exp(w\cdot x_i)}
    \large L^{'}(w)=\sum_{i=1}^{N}[y_{i}+h_{W,b}(X_i)]x_i

于是得到更新公式:

                                                      \large W_{j}=W_{j}+\alpha\cdot \frac{1}{N}\cdot \L^{'}(w)


模型估计似然函数——损失函数的Python实现:

# 定义损失函数
def error_rate(h, label):
    '''计算当前的损失函数值
    input:  h(mat):预测值
            label(mat):实际值
    output: err/m(float):错误率
    '''
    m = np.shape(h)[0]
    sum_err = 0.0
    for i in range(m):
        if h[i, 0] > 0 and (1 - h[i, 0]) > 0:
            sum_err -= (label[i, 0] * np.log(h[i, 0]) + (1 - label[i, 0]) * np.log(1 - h[i, 0]))
        else:
            sum_err -= 0
    return sum_err / m

梯度下降法算法的Python实现:

# 定义 BGD 梯度下降法
def lr_train_bgd(feature, label, maxCycle, alpha):
    n = np.shape(feature)[1]    # 特征的个数
    w = np.mat(np.ones((n, 1)))   # 初始化权重
    i = 0
    while i <= maxCycle:
        i += 1
        h = Sigmoid(feature * w)
        error = label - h
        if i % 100 == 0:
            print('\t 迭代次数为=:' + str(i) + ',训练误差率为:' + str(error_rate(h, label)))
        w = w + alpha * feature.T * error
    return w

权值保存函数的Python实现:

# 保存最终的模型参数
def save_model(filename, w):
    m = np.shape(w)[0]
    f_w = open(filename, 'w')
    w_array = []
    for i in range(m):
        w_array.append(str(w[i, 0]))
    f_w.write('\t'.join(w_array))
    f_w.close()

Logistic Regression算法实践完整Python代码:

# -*- coding: utf-8 -*-
# @Time    : 2019-1-8 18:27
# @Author  : Chaucer_Gxm
# @Email   : [email protected]
# @File    : Logsitic_Regression.py
# @GitHub  : https://github.com/Chaucergit/Code-and-Algorithm
# @blog    : https://blog.csdn.net/qq_24819773
# @Software: PyCharm
import numpy as np


# 定义 Sigmoid 函数
def Sigmoid(x):
    return 1.0 / (1 + np.exp(-x))


# 定义损失函数
def error_rate(h, label):
    '''计算当前的损失函数值
    input:  h(mat):预测值
            label(mat):实际值
    output: err/m(float):错误率
    '''
    m = np.shape(h)[0]
    sum_err = 0.0
    for i in range(m):
        if h[i, 0] > 0 and (1 - h[i, 0]) > 0:
            sum_err -= (label[i, 0] * np.log(h[i, 0]) + (1 - label[i, 0]) * np.log(1 - h[i, 0]))
        else:
            sum_err -= 0
    return sum_err / m


# 定义 BGD 梯度下降法
def lr_train_bgd(feature, label, maxCycle, alpha):
    n = np.shape(feature)[1]    # 特征的个数
    w = np.mat(np.ones((n, 1)))   # 初始化权重
    i = 0
    while i <= maxCycle:
        i += 1
        h = Sigmoid(feature * w)
        error = label - h
        if i % 100 == 0:
            print('\t 迭代次数为=:' + str(i) + ',训练误差率为:' + str(error_rate(h, label)))
        w = w + alpha * feature.T * error
    return w


def load_data(file_name):
    f = open(file_name)  # 打开文件
    feature_data = []
    label_data = []
    for line in f.readlines():
        feature_tmp = []
        lable_tmp = []
        lines = line.strip().split("\t")
        feature_tmp.append(1)  # 偏置项
        for i in range(len(lines) - 1):
            feature_tmp.append(float(lines[i]))
        lable_tmp.append(float(lines[-1]))

        feature_data.append(feature_tmp)
        label_data.append(lable_tmp)
    f.close()  # 关闭文件
    return np.mat(feature_data), np.mat(label_data)


# 保持最终的模型
def save_model(filename, w):
    m = np.shape(w)[0]
    f_w = open(filename, 'w')
    w_array = []
    for i in range(m):
        w_array.append(str(w[i, 0]))
    f_w.write('\t'.join(w_array))
    f_w.close()


def main():
    print('***************** 导入模型 *****************')
    features, labels = load_data('data.txt')
    print('***************** 训练模型 *****************')
    w = lr_train_bgd(features, labels, 1000, 0.01)
    print('***************** 保存模型 *****************')
    save_model('weights', w)


if __name__ == '__main__':
    main()

训练结果:

>>>权值输出为:1.3941777508748279	4.527177129107412	-4.793981623770905

完整程序(训练程序+测试程序)与数据集地址:

https://github.com/Chaucergit/Code-and-Algorithm/tree/master/ML/1-Logistic%20Regression


参考书目:

[1].统计方法.李航

[2].Python机器学习算法.赵志勇

[3].利用Python进行数据分析.WesKinney著,唐学韬等译

猜你喜欢

转载自blog.csdn.net/qq_24819773/article/details/86177464