zoukankan      html  css  js  c++  java
  • Logistic 回归

    Logistic回归是目前最常用的一种分类算法。之前讨论了线性回归 http://www.cnblogs.com/futurehau/p/6105011.html,采用线性回归是不能解决或者说不能很好解决分类问题的,很直观的一个解释如下图所示,这里介绍Logistic回归。

    一、Logistic 回归模型

    1.1 概率:

    1.2 ML准则推导代价函数

    1.2.1 y取1 0

    似然函数:

    对数似然函数及其求导:

    1.2.2 y取 +1 -1

    考虑到 1 - h(x) = h(-x)

    似然函数可以表示为:

    取对数变换可得:

    最后得到:

    1.3 代价函数:

    在线性回归中,我们得到代价函数,但是在Logistic 回归中,由于h(x)是一个复杂的非线性函数,这就导致J(theta)变为一个非凸函数,梯度下降算法不能收敛到它的全局最小值,所以这里我们需要重新引入别的代价函数。

    我们上文推到了似然函数为,那么我们这里取代价函数为似然函数的负,这样对于代价函数的最小化就相当于似然函数的最大化。我们不难得到下面的代价函数:

    我们拆分开来看看是什么样子:

    画出图来可以分析。如果 y= 1, 那么你预测 h(x) = 0 的代价就会非常高,预测h(x) = 1的代价就是 0。y = 0的情况同理。

    二、Logistic回归的求解

    2.1 梯度下降算法求解 Logistic

    线性回归中我们提出两种方法来求解theta,解析法和梯度下降算法。在Logistic回归中,没有解析解,我们使用梯度下降算法来求解。

    注意到这里是加号。其实上式既可以看为似然函数的正梯度上升,也可以把括号里面的负号拿出来之后变为损失函数的梯度下降。

    2.2 梯度下降算法求解 Logistic 回归和求解线性回归的区别与联系。

    我们发现,梯度下降算法求解Logistic回归和求解线性回归的梯度下降的式子形式上式一样的,区别在于两者的h(x)是不同的,那么这之中隐含什么东西呢?

    我们现在考虑这样一个概念:

    几率:一个事件的几率,是指该事件发生的概率与该事件不发生的概率的比值。

    对数几率:几率取对数

    所以,我们求几率如下:

    我们发现,Logistic的对数是线性的,这就相当于Logistic回归是一个广义的线性回归。对数线性模型。

    三、决策边界

    当h(x) 大于 0.5时,我们判决为1,小于0.5时,我们判决为假。接下来我们看看这意味着什么。

    h(x) > 0.5 需要 theta * x > 0。当theta确定之后,这会得到关于x1,x2(只考虑二维)的一条曲线,把整个平面分为两部分,满足theta * x > 0的部分就取为1。

    我们引入 theta * x = 0 为决策边界。决策边界和训练集没有关系,训练集是用来拟合参数theta的,theta确定之后,决策边界就确定了。

    四、多元分类问题

    4.1 使用多个二元 Logistic 回归分类器实现。

      多次one Vs all,分别训练每个h(x),分类的时候找出最大的那个h(x)。

    4.2 SoftMax

    理解还不是很清楚,关于这部分的一个解释:http://deeplearning.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92

    4.3 多个二元分类 Vs SoftMax

    如果你在开发一个音乐分类的应用,需要对k种类型的音乐进行识别,那么是选择使用 softmax 分类器呢,还是使用 logistic 回归算法建立 k 个独立的二元分类器呢?

    这一选择取决于你的类别之间是否互斥,例如,如果你有四个类别的音乐,分别为:古典音乐、乡村音乐、摇滚乐和爵士乐,那么你可以假设每个训练样本只会被打上一个标签(即:一首歌只能属于这四种音乐类型的其中一种),此时你应该使用类别数 k = 4 的softmax回归。(如果在你的数据集中,有的歌曲不属于以上四类的其中任何一类,那么你可以添加一个“其他类”,并将类别数 k 设为5。)

    如果你的四个类别如下:人声音乐、舞曲、影视原声、流行歌曲,那么这些类别之间并不是互斥的。例如:一首歌曲可以来源于影视原声,同时也包含人声 。这种情况下,使用4个二分类的 logistic 回归分类器更为合适。这样,对于每个新的音乐作品 ,我们的算法可以分别判断它是否属于各个类别。

    现在我们来看一个计算视觉领域的例子,你的任务是将图像分到三个不同类别中。(i) 假设这三个类别分别是:室内场景、户外城区场景、户外荒野场景。你会使用sofmax回归还是 3个logistic 回归分类器呢? (ii) 现在假设这三个类别分别是室内场景、黑白图片、包含人物的图片,你又会选择 softmax 回归还是多个 logistic 回归分类器呢?

    在第一个例子中,三个类别是互斥的,因此更适于选择softmax回归分类器 。而在第二个例子中,建立三个独立的 logistic回归分类器更加合适。

    鸢尾花lr代码

      1 #!/usr/bin/python
      2 # -*- coding:utf-8 -*-
      3 
      4 import numpy as np
      5 from sklearn.linear_model import LogisticRegression
      6 import matplotlib.pyplot as plt
      7 import matplotlib as mpl
      8 from sklearn import preprocessing
      9 import pandas as pd
     10 from sklearn.preprocessing import StandardScaler
     11 from sklearn.pipeline import Pipeline
     12 
     13 
     14 def iris_type(s):
     15     it = {'Iris-setosa': 0, 'Iris-versicolor': 1, 'Iris-virginica': 2}
     16     return it[s]
     17 
     18 
     19 if __name__ == "__main__":
     20     path = u'8.iris.data'  # 数据文件路径
     21 
     22     # # 手写读取数据
     23     # f = file(path)
     24     # x = []
     25     # y = []
     26     # for d in f:
     27     #     d = d.strip()
     28     #     if d:
     29     #         d = d.split(',')
     30     #         y.append(d[-1])
     31     #         x.append(map(float, d[:-1]))
     32     # print '原始数据X:
    ', x
     33     # print '原始数据Y:
    ', y
     34     # x = np.array(x)
     35     # print 'Numpy格式X:
    ', x
     36     # y = np.array(y)
     37     # print 'Numpy格式Y - 1:
    ', y
     38     # y[y == 'Iris-setosa'] = 0
     39     # y[y == 'Iris-versicolor'] = 1
     40     # y[y == 'Iris-virginica'] = 2
     41     # print 'Numpy格式Y - 2:
    ', y
     42     # y = y.astype(dtype = np.int)
     43     # print 'Numpy格式Y - 3:
    ', y
     44     #
     45     # # 使用sklearn的数据预处理
     46     # df = pd.read_csv(path, header=0)
     47     # x = df.values[:, :-1]
     48     # y = df.values[:, -1]
     49     # print 'x = 
    ', x
     50     # print 'y = 
    ', y
     51     #
     52     #
     53     # le = preprocessing.LabelEncoder()
     54     # le.fit(['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'])
     55     #
     56     #
     57     # print le.classes_
     58     # y = le.transform(y)
     59     # print 'Last Version, y = 
    ', y
     60     #
     61     # # 路径,浮点型数据,逗号分隔,第4列使用函数iris_type单独处理
     62     data = np.loadtxt(path, dtype=float, delimiter=',', converters={4: iris_type})
     63     print data
     64     # 将数据的0到3列组成x,第4列得到y
     65     x, y = np.split(data, (4,), axis=1)
     66 
     67     # 为了可视化,仅使用前两列特征
     68     x = x[:, (2,3)]
     69     #
     70     print x
     71     print y
     72     #
     73     # x = StandardScaler().fit_transform(x) # 每一列数据标准化
     74     # lr = LogisticRegression()   # Logistic回归模型
     75     #     lr.fit(x, y.ravel())        # 根据数据[x,y],计算回归参数
     76     #
     77     # 等价形式
     78     lr = Pipeline([('sc', StandardScaler()),
     79                         ('clf', LogisticRegression()) ])
     80     lr.fit(x, y.ravel()) # 转置
     81 
     82     # 画图
     83     N, M = 500, 500     # 横纵各采样多少个值
     84     x1_min, x1_max = x[:, 0].min(), x[:, 0].max()   # 第0列的范围
     85     x2_min, x2_max = x[:, 1].min(), x[:, 1].max()   # 第1列的范围
     86     t1 = np.linspace(x1_min, x1_max, N)
     87     t2 = np.linspace(x2_min, x2_max, M)
     88     x1, x2 = np.meshgrid(t1, t2)                    # 生成网格采样点
     89     x_test = np.stack((x1.flat, x2.flat), axis=1)   # 测试点
     90 
     91     # 无意义,只是为了凑另外两个维度
     92     # x3 = np.ones(x1.size) * np.average(x[:, 2])
     93     # x4 = np.ones(x1.size) * np.average(x[:, 3])
     94     # x_test = np.stack((x1.flat, x2.flat, x3, x4), axis=1)  # 测试点
     95 
     96     cm_light = mpl.colors.ListedColormap(['#77E0A0', '#FF8080', '#A0A0FF'])
     97     cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
     98     y_hat = lr.predict(x_test)                  # 预测值
     99     y_hat = y_hat.reshape(x1.shape)                 # 使之与输入的形状相同
    100     plt.pcolormesh(x1, x2, y_hat, cmap=cm_light)     # 预测值的显示
    101     plt.scatter(x[:, 0], x[:, 1], c=y, edgecolors='k', s=50, cmap=cm_dark)    # 样本的显示
    102     plt.xlabel('petal length')
    103     plt.ylabel('petal width')
    104     plt.xlim(x1_min, x1_max)
    105     plt.ylim(x2_min, x2_max)
    106     plt.grid()
    107     plt.savefig('2.png')
    108     plt.show()
    109 
    110     # 训练集上的预测结果
    111     y_hat = lr.predict(x)
    112     y = y.reshape(-1)
    113     result = y_hat == y
    114     print y_hat
    115     print result
    116     acc = np.mean(result)
    117     print '准确度: %.2f%%' % (100 * acc)
    View Code

     SGD BGD:

     1 # -*- coding: cp936 -*-
     2 import numpy as np
     3 import matplotlib.pyplot as plt
     4 import math
     5 def logestic_regression_SGD(x, y, alpha, lamda):
     6     m = np.alen(x)
     7     ones = np.ones(m)
     8     x = np.column_stack((ones, x))
     9     n = np.alen(x[0])
    10     theta = np.ones(n)
    11     for j in range(1, m):
    12         hypothesis = getHypothesis(x[j], theta)
    13 
    14         loss = hypothesis - y[j]
    15         print np.sum(loss ** 2)
    16         gradient = np.dot(loss, x[j])
    17         theta = theta - alpha * gradient
    18     return theta
    19 
    20 def logestic_regression_BGD(x, y, alpha, lamda):
    21     m = np.alen(x)
    22     ones = np.ones(m)
    23     x = np.column_stack((ones, x))
    24     n = np.alen(x[0])
    25     theta = np.ones(n)
    26     x_traverse = np.transpose(x)
    27 
    28     for i in range(100000):
    29         hypothesis = getHypothesis(x, theta)
    30         loss = hypothesis - y
    31         # print np.sum(loss ** 2)
    32         gradient = np.dot(x_traverse, loss)
    33         theta = theta - alpha * gradient
    34     return theta
    35 
    36 def getHypothesis(x, theta):
    37     return 1 / (1 + pow(math.e, -np.dot(x, theta)))
    38 
    39 
    40 def generateData():
    41     x1 = (np.random.random_sample(500) - 0.5) * 2
    42     x2 = (np.random.random_sample(500) - 0.5) * 2
    43     y = (x1 ** 2 + x2 ** 2) <= 0.25
    44     x1_pos = []
    45     x1_neg = []
    46     x2_pos = []
    47     x2_neg = []
    48     len = np.alen(y)
    49     for i in range(len):
    50         if y[i]:
    51             x1_pos.append(x1[i])
    52             x2_pos.append(x2[i])
    53         else:
    54             x1_neg.append(x1[i])
    55             x2_neg.append(x2[i])
    56     plt.plot(x1_neg, x2_neg, 'rx')
    57     plt.plot(x1_pos, x2_pos, 'bo')
    58     plt.show()
    59     x1 = np.column_stack((x1, x1 * x1))
    60     x2 = np.column_stack((x2, x2 * x2))
    61     return [x1, x2, y]
    62 if __name__ == '__main__':
    63     [x1, x2, y] = generateData()
    64     x = np.column_stack((x1, x2))
    65     theta = logestic_regression_SGD(x, y, 0.001, 0.01)
    66     print theta
    67     theta = logestic_regression_BGD(x, y, 0.01, 0.01)
    68     print theta
    View Code
  • 相关阅读:
    如何阅读大型代码库?
    发现一个时隐时现的bug!
    写给开发者:记录日志的10个建议
    教你一眼认出英语单词的意思
    为什么我要使用一个20年前的IBM老键盘
    有了screen,妈妈再也不用担心我的学习啦
    一次优秀的代码提交应该包含什么?
    你需要的不是重构,而是理清业务逻辑
    Android中监听ListView滑动到底部
    Android中的Handler,Looper,Message机制
  • 原文地址:https://www.cnblogs.com/futurehau/p/6107113.html
Copyright © 2011-2022 走看看