头像

Cyan

四川成都

深度强化学习炼丹师

机器学习笔记(六)——Logistic回归

机器学习笔记(六)——Logistic回归

2022-04-27 · 146次阅读 · 原创 · 人工智能

1 模型描述

逻辑斯谛回归(Logistic regression)是机器学习中的一种经典的 分类 算法,虽然名字中带有 回归 ,但其并不是 回归 算法,这是由于历史上命名原因造成的。

1.1 模型假设

给定一个包含两种类别的数据集:

T={(x1,y1),(x2,y2),,(xm,ym)}T = \{(x_1, y_1),(x_2, y_2),\cdots, (x_m, y_m)\}

在线性可分的二分类问题中,要将两个类别区分开来,一般是寻找一个由 ww (权重)和 bb (偏置)决定的最优超平面(决策边界):wx+b=0w\cdot x + b=0,两种类别的样本分别处在该超平面的两侧。

感知机模型中,使用的是符号函数确定样本类别(作为激活函数),将两种样本类别分别记为 1,+1-1,+1 两类,对于超平面 ww 的样本 (xi,yi)(x_i,y_i),认为其为反例样本(-1),而 ww 的样本 (xi,yi)(x_i,y_i),认为其为正例样本(+1)

而在 LogisticLogistic 回归中,我们则使用 sigmoid函数确定样本类别(作为激活函数),将两种类别分别记为 0,10,1 两类,而 sigmoid函数将 ww 的结果映射到区间 (0,1)(0, 1),当 ww 时,sigmoid(wxi+b)(0,0.5)sigmoid(w\cdot x_i+b) \in(0,0.5) ;而当ww 时,sigmoid(wxi+b)[0.5,1)sigmoid(w\cdot x_i+b) \in[0.5,1)

sigmoid函数映射的数值表示其为类别 1 的概率,越接近 1 ,为类别 1 的概率越大,则判定其为类别 1;反之,结果越接近 0, 则说明为类别1 的概率越小,可判断其为类别 0。则可以认为,当映射数值在 (0,0.5)(0, 0.5) 则其为 0 类,而在 (0.5,1)(0.5, 1) 则判定其为 1 类。

为方便与课程推导对应,将权值向量 ww 替换为 θ\theta ,则可以得出其 LogsiticLogsitic 回归的二分类模型的假设函数为:

hθ(xi)=g(θTxi+b)h_{\theta}(x_i) = g(\theta^{T}x_i+b)

参数说明如下:

  1. mmnn 代表样本数量特征种类数量
  2. xiRnx_i \in R^n,代表第 ii 个样本的特征空间xi,jx_{i,j} 代表第 ii 个样本的 第 jj 个特征,其中 i=1,2,,m. j=1,2,,ni=1,2,\cdots,m.\ j=1,2,\cdots,n
  3. yi{0,1}y_i\in\{0, 1\} 代表第 ii 个样本的类别;
  4. ggsigmoidsigmoid 函数,即为:

g(z)=11+ezg(z)=\frac{1}{1 + e^{-z}}

  1. θRn\theta\in R^n 为超平面的法向量,同时也为 LogisticLogistic 回归模型的参数,代表权值向量(weight vector)θT\theta^{T} 代表 θ\theta 的转置,θi,i=1,2,,n\theta_i,i=1,2,\cdots,n 代表第 ii 个权值参数的值;
  2. bRb\in R 也为超平面的截距,同时也为 LogisticLogistic 回归模型的参数,代表偏置(bias)

为了方便简化计算,我们给每个样本的特征加上 xi,0=1x_{i,0} = 1 这个特征,让偏置 bb 加到权值向量 θ\theta 中成为 θ0\theta_0 ,让假设函数变为如下简化形式:

hθ(xi)=g(θ0xi,0+θ1xi,1+θ2xi,2++θnxi,n)=g(θTxi)=11+eθTxi\begin{aligned} h_\theta(x_i)&=g(\theta_0x_{i,0}+\theta_1x_{i,1}+\theta_2x_{i,2}+\cdots+\theta_nx_{i,n})\\ &=g(\theta^Tx_i)\\ &=\frac{1}{1+e^{-\theta^Tx_i}} \end{aligned}

1.2 代价函数

在线性回归中,我们选取的是平方误差函数作为代价函数,但若应用在 LogisticLogistic 回归的假设函数中作为代价函数,可以发现其并不是一个凸函数,存在局部最优解,在使用梯度下降的过程中可能会在局部最小值处停止,而无法达到全局最小值。因此不能使用其作为代价函数。

合理的 LogisticLogistic 回归的代价函数如下:

J(θ)=1mi=1mCost(hθ(xi),yi)J(\theta) = \frac{1}{m}\sum_{i=1}^{m}Cost(h_\theta(x_i), y_i)

Cost(xi,yi)={log(hθ(xi)),yi=1log(1hθ(xi)),yi=0Cost(x_i,y_i) = \begin{cases} -log(h_\theta(x_i)), &y_i=1\\ -log(1-h_\theta(x_i)), &y_i=0 \end{cases}

将上式简化得到:

J(θ)=1mi=1m(yilog(hθ(xi))(1yi)log(1hθ(xi)))=1mi=1m(yilog(hθ(xi))+(1yi)log(1hθ(xi)))\begin{aligned} J(\theta) &= \frac{1}{m}\sum_{i=1}^{m}(-y_i\log(h_\theta(x_i))-(1-y_i)\log(1-h_\theta(x_i)))\\ &= -\frac{1}{m}\sum_{i=1}^{m}(y_i\log(h_\theta(x_i))+(1-y_i)\log(1-h_\theta(x_i))) \end{aligned}

1.3 梯度计算

1.2 节 中我们已经我们已经得到了 LogisticLogistic 回归模型的代价函数,我们的目标时找到一组最优的参数 θ\theta ,使代价函数达到最小化,即:

argminθJ(θ)arg\,\min_{\theta}J(\theta)

则我们使用梯度下降进行寻优,其在第 jj 个参数的梯度为:

θj=J(θ)θj=1mi=1m(hθ(xi)yi)xi,j\begin{aligned} \nabla_{\theta_j} &= \frac{\partial J(\theta)}{\partial \theta_j}\\ &=\frac{1}{m}\sum_{i=1}^{m}(h_\theta(x_i) - y_i)x_{i,j} \end{aligned}

则每次更新梯度的公式为:

θj:=θjαmi=1m(hθ(xi)yi)xi,j\theta_j := \theta_j - \frac{\alpha}{m}\sum_{i=1}^{m}(h_\theta(x_i) - y_i)x_{i,j}

其中 α\alpha 为学习率。


2 案例实现

采用的数据集为吴恩达课后作业 ex2 中的 ex2data1.txt下载地址

数据有两种特征,分别为课程1的分数课程2的分数,类别有两种,类别0 代表被录取,类别1 代表未被录取。

需要我们判断两门课程分别为多少时,其能被录取。

2.1 代码实现

import numpy as np import matplotlib.pyplot as plt import time class Model: """ 二分类逻辑斯特回归 使用梯度下降法 """ def sigmoid(self, z): """ 假设函数 h :param x: 传入特征 :return: 特征 x 在此假设函数下的映射 """ return 1. / (1 + np.exp(-z)) def __J(self): """ 代价函数 :return: """ eps = 1e-6 hx = self.sigmoid(self.x.dot(self.theta)) # h_theta(x) 的值 J = -(np.inner(np.log(hx + eps), self.y) + np.inner(np.log(1 - hx + eps), 1 - self.y)) / self.m return J def __init__(self, alpha=0.01, eps=1e-5, iters=10000): """ 构造函数 :param alpha: 学习步长 :param eps: 精度 """ self.alpha = alpha self.eps = eps self.iters = iters def fit(self, x, y): """ 进行训练 :param x: 特征向量 :param y: 标签 """ self.m, self.n = x.shape[0], x.shape[1] + 1 self.y = y c = np.ones(shape=(self.m, 1)) self.x = np.concatenate((c, x), axis=1) # 初始化参数 theta 为0 self.theta = np.ones(self.n) self.j_list = [self.__J()] for i in range(self.iters): # 进行迭代 hx = self.sigmoid(self.x.dot(self.theta)).flatten() sub = hx - self.y self.theta -= self.alpha * (np.dot(self.x.T, sub).flatten()) / self.m tj = self.__J() self.j_list.append(tj) if abs(tj - 0) <= 1e-6: print("Well done in step %i! ", i) return print("Not completed!") def get_param(self): """ 获取拟合最优的参数 :return: theta """ return self.theta def predict(self, x): """ 预测 :param x: 要预测的特征 :return: 预测的结果 """ c = np.ones(shape=(x.shape[0], 1)) x = np.concatenate((c, x), axis=1) # 将特征的第一维添加1,方便计算 return self.sigmoid(x).flatten() def plot_cost_change(self): """绘制损失函数的变化趋势""" plt.figure() plt.plot(self.j_list, linewidth=".4") plt.xlabel("iter") plt.ylabel("cost") plt.title("代价函数值随迭代次数增加的变化趋势") plt.show() # 导入数据集 data = np.loadtxt("./AndrewNg/ex2/ex2data1.txt", delimiter=',') # print(data) # 数据提取 X = data[:, :2] # 取前100样本的前两种特征 y = data[:, 2] model = Model(alpha=0.003, iters=2000000) st = time.time() model.fit(X, y) ed = time.time() print("耗时:%.3fs" % (ed - st)) model.plot_cost_change() theta = model.theta print(theta) xx = np.arange(X[:, 0].min(), X[:, 0].max(), 1) yy = -(theta[1] * xx + theta[0]) / theta[2] # 绘制结果 plt.figure(2) plt.plot(xx, yy, c='blue') plt.scatter(X[y == 0, 0], X[y == 0, 1], label='Not admitted', c="none", marker='o', edgecolors='r') plt.scatter(X[y == 1, 0], X[y == 1, 1], label='Admitted', c="black", marker='+') plt.legend() plt.xlabel("Exam 1 score") plt.ylabel("Exam 2 score") plt.title("两种类别的划分结果") plt.show()

2.2 结果输出

Not completed!
耗时:56.725s
[-24.05743837   0.19740346   0.19253832]

其代价函数的变化为:

figure1

其超平面的分割图像如下:

figure2

可以看到,超平面大致能分割出两种类别,但却不是最优。使用scipy.optimize.minimize 优化函数进行寻优的话运算速度极快,但也只能同梯度下降的划分结果相近 θ=[25.16130062,0.20623142,0.20147143]\theta = [-25.16130062, 0.20623142, 0.20147143],与梯度下降的结果差别不大。

想要更合理的划分两种类别,可以考虑添加高次项的特征如 x12,x22,x1x2,x_1^2, x_2^2, x_1x_2,\cdots ,再引入 正则化项 进行梯度下降找到更好的超平面。


标题: 机器学习笔记(六)——Logistic回归
链接: https://www.fightingok.cn/detail/229
更新: 2022-09-18 22:50:02
版权: 本文采用 CC BY-NC-SA 3.0 CN 协议进行许可