机器学习 - logistic回归

统计机器学习有两种常见的机器学习算法:logistic回归和SVM,这两种算法都涉及到优化问题,是非常重要的两种机器学习算法,尤其是logistic回归可能是工程上用的最广泛的机器学习算法了。在logistic回归中训练分类器就是寻找最佳拟合参数,使用的是最简单常见优化算法 - 梯度下降法。

logistic回归的核心是给每个特征xi训练出一个最佳回归系数wi,得到W'X,带入到sigmoid函数,然后sigmoid函数输出的值与0.5作比较,进行分类,而最佳回归系数的确定就是两部分:极大似然估计,梯度下降


此处仅仅写了大概过程,详细的推导过程,见本人总结的文档:http://download.csdn.net/detail/zk_j1994/9899047

1. 极大似然估计

极大似然估计是一种参数估计方法,在logistic回归中被用来估计模型的参数W。简单的讲就是每个样本的概率密度连乘积最大。


2. 梯度下降

梯度下降用来优化参数,使模型最优。


3. 向量化

将梯度下降的过程向量化,就很容易实现logistic算法。


4. 梯度下降的优化 - SGD

在梯度下降中,哪怕更新一个回归系数,所有的样本也得参与运算, 因此我们每次迭代只选择一个样本或者一个bitch(当然label与之保持一致)来参与运算。收敛速度会大大提升。


5. logistic回归的优缺点

优点:

1)本质上是线性模型,计算简单,训练速度快。

2)引入了sigmoid函数来进行分类,因此能够近似的把输出结果看做一个概率(当然绝对不是概率),因此其输出结果比较直观。

缺点:

1)线性,分类精度简单,容易欠拟合。


6. 实现logistic回归

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import time
import random

random.seed

def timing(f):
    """ 装饰器计时, 梯度下降和随机梯度下降的时间 """
    def fun(*args, **kwargs):
        begin = time.clock()
        returnVal = f(*args, **kwargs)
        print("{0}运行时间为: {1}".format(f.__name__, time.clock() - begin))
        return returnVal
    return fun

def load_data():
    """ 1. 导入testSet.txt的数据 """
    train_data = []
    with open("testSet.txt", "r") as f:
        for line in f.readlines():
            train_data.append(line.strip().split("\t"))
    train_data = np.array(train_data, np.float)
    train_x = np.concatenate((np.ones((len(train_data),1)), train_data[:, 0:2]), axis=1)
    train_y = train_data[:, 2].astype(int)
    return train_x, train_y


def sigmoid(x):
    """ 计算sigmoid(x)的值, numpy的exp能够直接操作矩阵 """
    return 1 / (1 + np.exp(-x))

@timing
def gradientAscent(train_x, train_y, max_iter, step = 0.001):
    """ 2. 梯度下降进行训练 """
    train_x = np.mat(train_x)
    train_y = np.mat(train_y).T
    rows, cols = train_x.shape
    weights = np.ones((cols,1))
    for i in range(max_iter):
        # 内部每个样本都参与了计算
        value = sigmoid(train_x * weights)
        error = train_y - value
        weights = weights + step * train_x.T * error
    return weights

@timing
def randomGradientAscent(train_x, train_y, max_iter, initStep = 0.001, batchSize = 10):
    """ 3. 随机梯度下降训练 """
    rows, cols = train_x.shape
    weights = np.ones((cols, ))
    length = len(train_x)
    for i in range(max_iter):
        # 选取一个batch进行迭代
        sampleIndex = random.sample(range(length), batchSize)
        step = initStep + 2 / (i + 1)
        value = sigmoid(np.dot(train_x[sampleIndex], weights))
        error = train_y[sampleIndex] - value
        weights = weights + step * np.dot(train_x[sampleIndex].T, error)
    return weights


def drawResult(train_x, train_y, weigths, title):
    """ 4. 绘制分类结果 """
    weigths = np.array(weigths).reshape((len(weigths),))
    plt.figure()
    class_0 = train_x[train_y == 0]
    class_1 = train_x[train_y == 1]
    plt.scatter(class_0[:,1], class_0[:, 2],color="red", alpha=1.0)
    plt.scatter(class_1[:,1], class_1[:, 2],color="blue", alpha=0.5)
    x = list(range(-3,4,1))
    y = [ -(weigths[0] + weigths[1]*i) / weigths[2] for i in x ]
    plt.plot(x, y)
    plt.title(title)
    return plt
        
        
if __name__ == "__main__":
    train_x, train_y = load_data()
    
    weights = gradientAscent(train_x, train_y, 500, 0.001)
    drawResult(train_x, train_y, weights, "gradient ascent").show()

    weights = randomGradientAscent(train_x, train_y, 50, 0.001, 10)
    drawResult(train_x, train_y, weights, "random gradient ascent").show()


机器学习 - logistic回归_第1张图片 机器学习 - logistic回归_第2张图片

7. 注意

1)logistic回归使用之前要对特征进行归一化,最好使其满足0均值,单位方差。处理方式是对每一维特征减去均值除以方差。

2)可以将标准线性回归改为ridge,lasso形式,再应用到sigmoid函数。


参考书籍:《机器学习实战》,《统计学习方法》

http://blog.csdn.net/ariessurfer/article/details/41310525

http://blog.csdn.net/dongtingzhizi/article/details/15962797

你可能感兴趣的:(机器学习,数据挖掘,机器学习与数据挖掘,机器学习,logistic回归)