scikit-learn学习笔记(五)Logistic regression(逻辑回归)

逻辑函数(logistic function)

为了更好地解释逻辑回归,让我们首先了解一下逻辑函数。逻辑函数由于它的S形,有时也被称为sigmoid函数。

现在我要引入比值比(odds ratio)的概念,它可以被写成 p(1p) ,其中的 p 代表正事件(positive event)的概率,正事件并不是代表好的方面的概率,而是代表我们想要预测的事件。比如:病人患有某种疾病的概率。我们把正事件的类标签设置为1。比值比的对数称为Logit函数,它可以写成如下形式:

logit(p)=logp(1p)

它的函数图像如下:

Logit函数

从图像上我们可以看出,logit函数输入0到1的值并把它们转换为整个实数范围内的值。上面的 p 代表正事件的概率,因此在给定特征向量 x 的条件下,类别 y=1 的概率可以写成 P(y=1|x) 。大家都知道概率的范围为0到1,如果我把这个概率传递给logit函数那么它的输出范围是整个实数,因此如果我用某些合适的权重向量 w 参数化特征向量 x 后,可以有如下等式:

logit(P(y=1|x))=w0x0+w1x1++wnxn=i=0nwixi

但是在实际应用中,我们更想求的是 P(y=1|x) ,因此,我们需要找到logit函数的反函数,通过输入用权重向量 w 来参数化的 x ,来输出我们想要知道的正事件的概率,即 P(y=1|x) 。而这个反函数就是我们的sigmoid函数,它可以写成 S(h)=11+eh ,公式中的 h 为样本特征和权重的线性组合,即, w0x0+w1x1++wnxn 。下面我们来画出这个函数图像的样子:

import matplotlib.pyplot as plt
import numpy as np

def sigmoid(h):
    return 1.0 / (1.0 + np.exp(-h))

h = np.arange(-10, 10, 0.1) # 定义x的范围,像素为0.1
s_h = sigmoid(h) # sigmoid为上面定义的函数
plt.plot(h, s_h)
plt.axvline(0.0, color='k') # 在坐标轴上加一条竖直的线,0.0为竖直线在坐标轴上的位置
plt.axhspan(0.0, 1.0, facecolor='1.0', alpha=1.0, ls='dotted') # 加水平间距通过坐标轴
plt.axhline(y=0.5, ls='dotted', color='k') # 加水线通过坐标轴
plt.yticks([0.0, 0.5, 1.0]) # 加y轴刻度
plt.ylim(-0.1, 1.1) # 加y轴范围
plt.xlabel('h')
plt.ylabel('$S(h)$')
plt.show()

sigmoid函数

从上图我们可以看出,函数接收整个实数范围的输入,输出0到1之间的数。

因此 S(w0x0+w1x1++wnxn)=P(y=1|x;w)

这个概率我们可以解释成:给定用权重 w 参数化后的特征 x ,样本属于类别1的概率。通过阶跃函数(step function),我们可以得到如下公式:


f(n)={1,0,if S(h) 0.5otherwise

还有一个等价的公式如下:

f(n)={1,0,if h 0.0otherwise


实际上,很多应用不只仅仅是想得到一个类标签,而是算出属于某个类别的概率。比如逻辑回归就是这样的,它不仅仅是告诉你是否患有疾病,而是告诉你有多大概率患有这个疾病。

在上面的例子当中,我们一直都看到权重 w 的出现,那么我们如何学习出最佳的权重 w 呢?在告诉你答案之前,让我们先复习一下最大似然估计(maximum likelihood)的概念。

最大似然估计(maximum likelihood)

这个方法的本质就是:选择最佳的参数值 w ,来最大化我们样本数据的可能性。

假设我们给定样本 X1,X2,X3,,Xn ,那么我可以写出一个关于参数 w 的可能性函数,如下:


lik(w)=f(X1,X2,X3,,Xn
|w)

实际上,可能性函数就是样本数据作为参数 w 的函数的概率。

如果 X1,X2,X3,,Xn 相互之间是独立的,可能性函数可以简化成如下形式:


lik(w)=1nf(Xi|w)


但是,如果我们有很多的样本数据呢?这时,你就会乘上很多项,这些项通常都很小,可能性函数就会变得很小。因此,你应该采用log可能性函数。第一,如果在可能性很小的时候它可以防止潜在的数值下溢;第二,我们把乘积转换为求和,这可以使我们更加容易求得函数的导数。第三,log函数是单调的,最大化可能性函数的值也就是最大化log可能性函数的值。log可能性函数公式如下:


l(w)=log(lik(w))=inlog(f(Xi|w))


下面,我举2个例子来应用一下这个强大的工具:

1、假设你口袋里有2枚硬币,1枚硬币出现正面的概率为 p=0.5 ,另1枚硬币出现正面的概率为 p=0.8 ,现在你从口袋里随机拿出一枚硬币(你并不知道拿的是哪枚硬币),然后随机投掷4次,出现3次正面,1次反面。你觉得你拿出的是哪枚硬币?或者哪枚硬币的最大似然估计更大?


答:通过问题我们可以得出这个是属于二项分布。它的概率为 P(x|n,p)=(nx)px(1p)nx .现在,我们来写出log可能性函数:



l(p)=log((43)p3(1p))


由于我们已经给出了p的值只能为0.5或0.8,因此,我们不必求导来算出 p 的值最大化可能性。这里我们只需要把两个 p 值代入就行了,分别得出如下结果:
l(0.5)=0.6021
l(0.8)=0.3876
因此当 p 为0.8时,使可能性函数更大,所以我更可能拿出的是正面概率为 p=0.8 的硬币。

2、假设 XiN(μ,σ2) ,并且相互之间是独立的。求出最佳参数?


答:log可能性函数如下:



l(μ,σ2)=i=1nlog[1σ2πexp((Xiμ2)2σ2)]=i=1nlog(σ)i=1nlog(2π)i=1n[(Xiμ)22σ2]=nlog(σ)nlog(2π)12σ2i=1n(Xiμ)2



因为我们想找到参数 μσ 使得可能性函数最大,因此我们需要找到它们的偏导:


l(μ,σ2)μ=μ(nlog(σ)nlog(2π)


12σ2i=1n(Xiμ)2)
=1σ2i=1n(Xiμ)









l(μ,σ2)σ2=σ2(n2log(σ2)nlog(2π)12(σ2)1i=1n(Xiμ)2)=n2σ2+12(σ2)2i=1n(Xiμ)2



让两个偏导都等于0,然后求出最佳参数。

μ=1ni=1nXi=X¯





σ2=1ni=1n(Xiμ)2

掌握了最大似然估计,现在你就可以知道逻辑回归cost函数的由来了。

逻辑回归的cost函数

现在,我们可以用可能性函数来定义上面的权重 w 了。公式如下:



L(w)=i=1nP(y(i)|x(i);w)=i=1nS(h(i))y(i)(1S(h(i)))1y(i)


上面公式中的h为假设函数 w0x0+w1x1++wnxn ,把上面的函数加上对数,公式如下:



l(w)=log(L(w))=i=1ny(i)log(S(h(i)))+(1y(i))log(1S(h(i)))


现在,我们的目的是最大化log可能性函数,找到一个最佳的权重 w 。我们可以在上面的log可能性函数前加上负号,用梯度下降算法来最小化这个函数。现在,我得到了逻辑回归的cost函数如下:


J(w)=i=1ny(i)log(S(h(i)))+(1y(i))log(1S(h(i)))
  • n :训练集样本总数
  • S :sigmoid函数
  • h :假设函数

假设我们只有一个样本,现在我们可以把上面的cost函数拆分成分段函数如下:




J(w)=log(S(h)),log(1S(h)),if y = 1if y = 0

Logistic regression cost function

我们把逻辑回归的cost函数做成了图像如上。当实际类别为1时,如果我们预测为1则需要很小的cost,如果我们预测为0则需要很大的cost;反过来,当实际类别为0时,如果我们预测为0则需要很小的cost,如果我们预测为1则需要很大的cost。

Iris数据集概述

首先,我们取得数据,下面这个链接中有数据的详细介绍,并可以下载数据集。

https://archive.ics.uci.edu/ml/datasets/Iris

从数据的说明上,我们可以看到Iris有4个特征,3个类别。但是,我们为了数据的可视化,我们只保留2个特征(sepal length和petal length)。让我们先看看数据集的散点图吧!

下面,我们进入Ipython命令行。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None) # 加载Iris数据集作为DataFrame对象
X = df.iloc[:, [0, 2]].values # 取出2个特征,并把它们用Numpy数组表示

plt.scatter(X[:50, 0], X[:50, 1],color='red', marker='o', label='setosa') # 前50个样本的散点图
plt.scatter(X[50:100, 0], X[50:100, 1],color='blue', marker='x', label='versicolor') # 中间50个样本的散点图
plt.scatter(X[100:, 0], X[100:, 1],color='green', marker='+', label='Virginica') # 后50个样本的散点图
plt.xlabel('petal length')
plt.ylabel('sepal length')
plt.legend(loc=2) # 把说明放在左上角,具体请参考官方文档
plt.show()

Iris数据集实例

从上图我们可以看出,数据集是线性可分的。为了更好地演示效果,我只用setosa和versicolor这两个类别。

接下来,我们要用强大的scikit-learn来拟合模型。

下面,我将用scikit-learn来训练一个逻辑回归模型:

from sklearn import datasets
import numpy as np
from sklearn.cross_validation import train_test_split

iris = datasets.load_iris()
X = iris.data[:, [2, 3]]
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

X_combined_std = np.vstack((X_train_std, X_test_std))
y_combined = np.hstack((y_train, y_test))

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=1000.0, random_state=0)
lr.fit(X_train_std, y_train)
lr.predict_proba(X_test_std[0,:]) # 查看第一个测试样本属于各个类别的概率
plot_decision_regions(X_combined_std, y_combined, classifier=lr, test_idx=range(105,150))
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.legend(loc='upper left')
plt.show()

scikit-learn实现逻辑回归

从上图我们看到逻辑回归模型把类别很好地分开了。


已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付 39.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值