Python Logistic回归分类

1.Logistic回归

人们将已知存在的数据点利用一条直线进行拟合(该直线被称为最佳拟合直线)的过程称为回归。
而今天介绍的Logistic回归分类的主要思想就是依据现有已分类的数据样本建立回归公式,以此进行分类。
“回归”源于最佳拟合,而Logistic回归中训练分类器的做法就是利用一些最优算法寻找符合最佳拟合的拟合参数。

1.1 Logistic分布

X是连续的随机变量,且具有如下的分布函数和密度函数:

![](http://latex.codecogs.com/svg.latex? \Large $$ F(X) = P(X\leq{x}) = \frac{1}{1+\exp^{-\frac{(x-\mu)}{\gamma}}}$$)

![](http://latex.codecogs.com/svg.latex? \Large $$ f(X) = F'(X) = \frac{\exp{-\frac{x-\mu}{\gamma}}}{\gamma(1+\exp{-\frac{x-\mu}{\gamma}})^2}$$)

其中μ为位置参数,γ > 0为形状参数。

下图是F(X),f(X)的大致图像,人们又把F(X)函数成为sigmoid函数(以后会经常见到它)。

import matplotlib.pyplot as plt
import numpy as np
import scipy

x = np.linspace(-5, 5)
y1 = 1/(1 + np.exp(- x))
y2 = np.exp(- x)/(1 + np.exp(- x))**2
fig1 = plt.figure()
plt.xlabel('x')
plt.ylabel('F(x)')
plt.plot(x, y1, linewidth = 2.0)
fig2 = plt.figure()
plt.xlabel('x')
plt.ylabel('f(x)')
plt.plot(x, y2, linewidth = 2.0)
plt.show()

1.2 二项式Logistic回归

从以上的Logistic分布定义中引申出一种分类模型,就是下面要介绍的二项式Logistic回归模型。
在上述X中,将其分为0、1两类。即随机变量X的取值为实数,其分类变量定义为Y,每个x所属类别可以通过条件概率分布P(Y|X)进行表示。
条件概率分布如下:

![](http://latex.codecogs.com/svg.latex? \Large $$P(Y=1\mid x) = \frac{\exp(\omega \cdot x+b)}{1+\exp(\omega \cdot x+b)}$$)

![](http://latex.codecogs.com/svg.latex? \Large $$P(Y=0\mid x) = \frac{1}{1+\exp(\omega \cdot x+b)}$$)

xRn是输入,Y∈ {0, 1}是输出,ωRn为权值向量,bR为偏置,ω·xωx的内积。

这里将ωx进行扩充,即![](http://latex.codecogs.com/svg.latex? \Large $\omega = {\omega ^{(1)},\omega ^{(2)},...,\omega ^{(n)},b }$)和![](http://latex.codecogs.com/svg.latex? \Large $x = {x{(1)},x{(2)},...,x^{(n)},1}$)

此时的Logistic回归模型如下:

![](http://latex.codecogs.com/svg.latex? \Large $$P(Y=1\mid x) = \frac{\exp(\omega \cdot x)}{1+\exp(\omega \cdot x)}$$)

![](http://latex.codecogs.com/svg.latex? \Large $$P(Y=0\mid x) = \frac{1}{1+\exp(\omega \cdot x)}$$)

在考虑一个事件发生为p,则不发生的概率为1-p,那么这个事件发生的几率(odds)为p/(1-p)。对数几率(log odds)为

![](http://latex.codecogs.com/svg.latex? \Large $$logit(p) = \log{\frac{p}{1-p}}$$)

将上述Logistic回归模型代入其中可以得到:

![](http://latex.codecogs.com/svg.latex? \Large $$\log{\frac{P(Y = 1\mid x)}{1-P(Y = 1\mid x)}} = \omega \cdot x$$)

可以看出输出Y = 1的对数几率是输入x的线性函数,即Y可以用x的线性函数表示。自然地,在Logistic回归模型中,x的线性函数值ω·x越接近于+∞,其概率越接近于1,反之,ω·x越接近于-∞,其概率越接近于0。

1.3 参数估计

假设给定训练数据集![](http://latex.codecogs.com/svg.latex? \Large $T = {(x_1,y_1),(x_2,y_2),...,(x_N,y_N)}$)
其中,xiRnyi ∈ {0,1},利用极大似然估计法估计模型参数。

设![](http://latex.codecogs.com/svg.latex? \Large $P(Y=1\mid x) =\pi (x)$,则$P(Y=0\mid x) =1-\pi (x)$)

似然函数为:![](http://latex.codecogs.com/svg.latex? \Large $$\prod_{i=1}^{N} [\pi(x_i)]{y_i}[1-\pi(x_i)]{1-y_i}$$)

对数似然函数为:

此时对L(ω)求最大值,即得到ω的估计值。
为此,后续利用梯度下降法或者拟牛顿法进行该值的求解。

假设ω的极大似然估计值为ω',那么Logistic模型为:

![](http://latex.codecogs.com/svg.latex? \Large $$P(Y=1\mid x) = \frac{\exp(\omega' \cdot x)}{1+\exp(\omega' \cdot x)}$$)

![](http://latex.codecogs.com/svg.latex? \Large $$P(Y=0\mid x) = \frac{1}{1+\exp(\omega' \cdot x)}$$)

1.4 梯度法求解估计值

对上述L(ω)中的ω求导,得到:

令L(ω) = 0,可以求得其最大的L(ω)对应的ω',但由于无法直接求解,故采用梯度下降法进行求解。

由上求导过程可以知道,L(ω) 的梯度为

![](http://latex.codecogs.com/svg.latex? \Large $$\triangledown_{\omega}L(\omega) =\sum_{i=1}^{N}{y_i - \pi(x_i)}x_i$$)

故迭代公式(此处为梯度上升算法)为

![](http://latex.codecogs.com/svg.latex? \Large $$\omega = \omega + \alpha \sum_{i=1}^{N}{y_i - \pi(x_i)}x_i$$)

其中α为步长,当![](http://latex.codecogs.com/svg.latex? \Large $\mid\mid \triangledown_{\omega}L(\omega) \mid\mid < \varepsilon$) 即可求得最大的ωε为误差。

2、Logistic分类器实现

仍然使用这份数据进行算法实现

以下列数据集为例,进行Logistic分类器的设计。

编号 色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖率 好瓜
1 青绿 蜷缩 浊响 清晰 凹陷 硬滑 0.697 0.460
2 乌黑 蜷缩 沉闷 清晰 凹陷 硬滑 0.774 0.376
3 乌黑 蜷缩 浊响 清晰 凹陷 硬滑 0.634 0.264
4 青绿 蜷缩 沉闷 清晰 凹陷 硬滑 0.608 0.318
5 浅白 蜷缩 浊响 清晰 凹陷 硬滑 0.556 0.215
6 青绿 稍蜷 浊响 清晰 稍凹 软粘 0.403 0.237
7 乌黑 稍蜷 浊响 稍糊 稍凹 软粘 0.481 0.149
8 乌黑 稍蜷 浊响 清晰 稍凹 硬滑 0.437 0.211
9 乌黑 稍蜷 沉闷 稍糊 稍凹 硬滑 0.666 0.091
10 青绿 硬挺 清脆 清晰 平坦 软粘 0.243 0.267
11 浅白 硬挺 清脆 模糊 平坦 硬滑 0.245 0.057
12 浅白 蜷缩 浊响 模糊 平坦 软粘 0.343 0.099
13 青绿 稍蜷 浊响 稍糊 凹陷 硬滑 0.639 0.161
14 浅白 稍蜷 沉闷 稍糊 凹陷 硬滑 0.657 0.198
15 乌黑 稍蜷 浊响 清晰 稍凹 软粘 0.360 0.37
16 浅白 蜷缩 浊响 模糊 平坦 硬滑 0.593 0.042
17 青绿 蜷缩 沉闷 稍糊 稍凹 硬滑 0.719 0.103

2.1 解析数据文件

上一篇的《朴素贝叶斯法》已经利用了Pandas对读入的数据文件进行解析并进行哑变量处理,下面即封装好的解析代码:

#导入numpy和pandas库
import numpy as np
import pandas as pd
#解析数据文件
def loadDataSet(filename):
    dataSet = pd.read_csv(filename, sep = '\t', index_col = '编号')

    #哑变量处理
    featureDict = []
    new_dataSet = pd.DataFrame()
    for i in range(len(dataSet.columns)):
        featureList = dataSet[dataSet.columns[i]]
        classSet = list(set(featureList))
        count = 0
        for feature in classSet:
            d = dict()
            if isinstance(feature, float):#判断是否为连续变量
                continue
            else:
                featureList[featureList == feature] = count
                d[feature] = count
                count += 1
            featureDict.append(d)
        new_dataSet = pd.concat([new_dataSet, featureList], axis = 1)

    dataMat = [list(new_dataSet.loc[i][:-1]) for i in range(1,len(new_dataSet) + 1)]
    labelMat = list(new_dataSet[new_dataSet.columns[-1]])
    return dataMat, labelMat
filename = 'data.txt'
dataMat, labelMat = loadDataSet(filename)

import pprint
pprint.pprint(dataMat)
pprint.pprint(labelMat)
[[1, 1, 2, 2, 0, 0, 0.69700000000000006, 0.46000000000000002],
 [0, 1, 1, 2, 0, 0, 0.77400000000000002, 0.376],
 [0, 1, 2, 2, 0, 0, 0.63400000000000001, 0.26400000000000001],
 [1, 1, 1, 2, 0, 0, 0.60799999999999998, 0.318],
 [2, 1, 2, 2, 0, 0, 0.55600000000000005, 0.215],
 [1, 2, 2, 2, 1, 1, 0.40299999999999997, 0.23699999999999999],
 [0, 2, 2, 0, 1, 1, 0.48100000000000004, 0.14899999999999999],
 [0, 2, 2, 2, 1, 0, 0.43700000000000006, 0.21100000000000002],
 [0, 2, 1, 0, 1, 0, 0.66599999999999993, 0.090999999999999998],
 [1, 0, 0, 2, 2, 1, 0.24299999999999999, 0.26700000000000002],
 [2, 0, 0, 1, 2, 0, 0.245, 0.057000000000000002],
 [2, 1, 2, 1, 2, 1, 0.34299999999999997, 0.099000000000000005],
 [1, 2, 2, 0, 0, 0, 0.63900000000000001, 0.161],
 [2, 2, 1, 0, 0, 0, 0.65700000000000003, 0.19800000000000001],
 [0, 2, 2, 2, 1, 1, 0.35999999999999999, 0.37],
 [2, 1, 2, 1, 2, 0, 0.59299999999999997, 0.042000000000000003],
 [1, 1, 1, 0, 1, 0, 0.71900000000000008, 0.10300000000000001]]
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

可以看到,该操作将字符串型的分类变量解析成为了数值型的分类变量,从而方便了将要进行的数值运算。

2.2 利用梯度上升法求最佳回归系数

在前面的定义中,Logistic分布函数$F(X)$又被称为sigmoid函数,其对数几率为

![](http://latex.codecogs.com/svg.latex? \Large $$\log{\frac{P(Y = 1\mid x)}{1-P(Y = 1\mid x)}} = \omega \cdot x$$)

即将sigmoid函数的输入可以看作是:

![](http://latex.codecogs.com/svg.latex? \Large $$z = \omega {(1)}x{(1)}+\omega {(2)}x{(2)}+,...,+\omega {(n)}x{(n)} = \omega^{T} \cdot x$$)

由此,定义下面的代码进行梯度上升法的实现:

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

#随机的梯度上升法
def gradAscent(dataMatIn, classLabels, numIter = 150):
    #获得行数和列数,即样本数和特征数
    m, n = np.shape(dataMatIn)
    #权重初始化
    weights = np.ones(n)
    for j in range(numIter):
        dataIndex = range(m)
        for i in range(m):
            alpha = 4/(1.0 + j + i) + 0.01
            randIndex = int(np.random.uniform(0, len(dataIndex)))
            h = sigmoid(sum(dataMatIn[randIndex] * weights))
            error = classLabels[randIndex] - h
            weights = weights + np.dot(alpha * error, dataMatIn[randIndex])
    return weights
weights = gradAscent(dataMat, labelMat)
print(weights)
[-1.91739131 -2.37320272  3.30085298  1.32020706 -2.30328752  0.58413608
  0.84630395 -0.63702599]

2.3 分类器设计

由上,求出了相应的输入特征对应权重,利用对数几率公式,可以简单实现分类的效果,相关设计代码如下:

def classfy(testdir, weights):
    dataMat, labelMat = loadDataSet(testdir)
    dataMat = np.mat(dataMat)
    weights = np.mat(weights)
    h = sigmoid(dataMat * weights.transpose())
    h = h.tolist()
    m = len(h)
    error = 0.0
    for i in range(m):
        if h[i][0] > 0.5:
            print(int(labelMat[i]),'is classfied as: 1')
            if int(labelMat[i])!=1:
                error += 1
                print('error')
        else:
            print(int(labelMat[i]),'is classfied as: 0')
            if int(labelMat[i])!=0:
                error += 1
                print('error')
    print('error rate is:','%.4f' %(error/m))
classfy(filename, weights)
1 is classfied as: 1
1 is classfied as: 1
1 is classfied as: 1
1 is classfied as: 1
1 is classfied as: 1
1 is classfied as: 1
1 is classfied as: 1
1 is classfied as: 1
0 is classfied as: 0
0 is classfied as: 0
0 is classfied as: 0
0 is classfied as: 0
0 is classfied as: 1
error
0 is classfied as: 0
0 is classfied as: 1
error
0 is classfied as: 0
0 is classfied as: 0
error rate is: 0.1176

将训练的数据样本进行测试,可以看出上述分类中,只有两个样本被分类错误了,准确度达到了88.24%,分类效果不错。

2.4 Scikit - Learn库简单实现Logistic分类

下面的代码是简单通过Scikit - Learn库实现Logistic的分类:

from sklearn.linear_model import LogisticRegression

X, Y = loadDataSet(filename)

clf = LogisticRegression()
clf.fit(X, Y)
y_pred = clf.predict(X)
accuracy = np.mean(Y == y_pred)
print('准确度为:', accuracy)
准确度为: 0.882352941176

可以看出,上述实现的准确度与设计的分类器的准确度基本一样,效果不错。

3、总结

Logist回归分类的优缺点:

  • 优点:计算代价低,易于理解和实现;
  • 缺点:易欠拟合,分类精度普遍不高。

本文实现过程中使用的数据样本量较少,结果也较为单一,后续可以通过训练和测试较多样本量的数据,来感受其作用。

4、 参考文献

[1] 李航. 统计学习方法.清华大学出版社,2012
[2] Peter Harrington. 机器学习实战. 人民邮电出版社,2013
[3] http://blog.csdn.net/lsldd/article/details/41551797

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容