【机器学习笔记4】逻辑回归模型

目录

什么是逻辑回归?

Sigmoid函数

决策边界

逻辑回归的损失函数

为什么平方误差模型不可行?

对数损失函数

单个样例损失:

整体损失函数

梯度下降算法

补充:F1-score评价指标

F1-Score简介

相关概念

F-Score

示例及代码:

问题描述:

数据预处理

特征缩放(Z-score标准化)

实现逻辑回归

sigmoid函数

损失函数

梯度计算函数(求偏导)

梯度迭代函数

训练数据集,绘制拟合决策边界

模型预测和评价

补充:现在将特征集扩大到所有

补充:使用sklearn完成逻辑回归


请确保你已学会了前几个线性回归的内容。之前涉及的相关概念在此文章不会再提及。

什么是逻辑回归?

逻辑回归是一种广义的线性回归模型,主要用于解决二分类问题。所谓二分类问题,就是比如判断一个邮件是否是垃圾邮件、根据某些特征判断肿瘤是否为恶性肿瘤等问题,我们可以将是/否表示为1/0。简单的二分类数据图如下:

(注:左图为只有一个特征的数据模拟图,右图为有两个特征的数据模拟图。)

以仅有一个特征的二分类(左图)为例,如果我们模拟传统线性回归f(x) = \vec w\cdot \vec x+b,并选择0.5作为阈值:当y \geq 0.5时我们认为它是种类1,当y<0.5时,我们认为它是种类0,那么可以得到以下图像:

 但是,当我们再加一些数据,它就会模拟成这样:

很明显能看出,这样的预测并不准确。

所以当对二分类问题进行回归分析时,采用传统的线性回归函数进行拟合并不是一个好的方案。于是我们将使用另一种函数——Sigmoid函数

Sigmoid函数

Sigmoid函数又称为Logistic函数(逻辑函数),Sigmoid函数输出值在(0,1)之间,而且可以解决离群点对拟合线性回归的影响,Sigmoid函数在诸多领域都有涉及,这里不再拓展。

Sigmoid函数表达式:g(z) = \frac{1}{1+e^{-z}}

函数图像:

现在使用sigmoid函数拟合上面的例子,当g(z)\geq 0.5时,我们认为它属于种类1,当g(z)<0.5时,我们认为它属于种类0,于是可以得到下面的图像:

(注:橙色的线为决策边界,后面会详细解释。)

很明显看出该函数拟合的很好。

决策边界

上面提到,我们使用sigmoid函数进行预测时,当g(z) \geq 0.5,我们认为是种类1,当g(z)<0.5时,我们认为是种类0。那么,什么时候g(z)等于0.5呢?观察sigmoid函数的图像,当z等于0时,g(z) = 0.5。所以我们令z = f_{\vec w,b}(\vec x) = \vec w\cdot\vec x+b,决策边界即f_{\vec w,b}(\vec x) = 0

以上述右图为例(即以有两个特征的二分类为例),决策边界最终求出的函数为f(x) = x_0+x_1 -3。当f(x) \geq 0,属于种类1;当f(x)<0.5,属于种类0。决策边界图像为:

可以看到决策边界将两个不同的种类分开了。

又比如,当f_{\vec w,b}(\vec x)为更复杂的多项式时,可以画出以下图像:

逻辑回归的损失函数

为什么平方误差模型不可行?

在之前的线性回归中,我们使用平方误差作为我们的代价函数(损失函数):

J(\vec w,b) = \frac 1 {2m}\sum_{i = 0}^{m-1}(\hat y^{(i)}-y^{(i)})^2 =\frac 1 {2m}\sum_{i = 0}^{m-1}(f_{\vec w,b}(\vec x^{(i)})-y^{(i)})^2

其中,(i)为样例序号。

那时f_{\vec w,b}(\vec x) = \vec w\cdot\vec x+b,平方误差代价函数可以平滑下降直到一个最低点。

下图是一元一次线性回归f(x) = wx+b的代价函数图像:

但是逻辑回归的函数为sigmoid(\vec w\cdot\vec x+b) = \frac{1}{1+e^{-z}},其中,z = \vec w\cdot\vec x+b

如果再使用平方误差作为代价函数,它的图像将会是凹凸不平的:

 这意味着梯度下降算法很可能无法找到最低点,会卡在某个极小值点。

 为了解决这个问题,我们将使用另一种模型作为我们的代价函数:

对数损失函数

为什么使用对数损失函数作为逻辑回归的损失函数而不使用其他函数?

使用对数损失函数作为逻辑回归的损失函数是由极大似然估计推导所得,这里不进行拓展。

单个样例损失:

L(\hat y,y) = \left\{ \begin{aligned} -log(\hat y) if\quad y = 1\\ -log(1-\hat y) if\quad y = 0\\ \end{aligned} \right.

其中,\hat y = g_{\vec w,b}(\vec x) = sigmoid(\vec w\cdot \vec x+b), \hat y \in (0,1)

解释一下含义:

当真实值为1时,图像为:

可以看出,在真实值y为1的情况下:当预测值\hat y接近1时,计算出的损失很小;而当\hat y接近0时,计算出的损失很大很大。换成人话,就是比如说某人真实情况是“很胖”,但是预测出的却是“很廋”,这时预测值和真实值的差距就很大很大。

同理,当真实值为0时,图像为:

 在真实值y为0的情况下:当预测值\hat y接近0时,计算出的损失很小;而当\hat y接近0时,计算出的损失很大很大。

化简L(\hat y,y),可得L(\hat y,y) = -y*log(\hat y)-(1-y)*log(1-\hat y)

整体损失函数

上式求和即可得:

公式:J(\vec w,b) = \frac 1 m \sum_{i=0}^{m-1}L(g_{\vec w,b}(\vec x),y)

让我们用这个新的代价函数模拟一下最开始左图的代价函数模型:

 现在这个图像很适合使用梯度下降算法来找到它的最低点。

梯度下降算法

步骤与线性回归相同,同时进行以下直到收敛:

w_j = w_j - a\frac{\partial J(\vec w,b)}{\partial w_j},\quad j = 0,1,...,n-1

b = b - a\frac{\partial J(\vec w,b)}{\partial b}

其中,

\frac{\partial J(\vec w,b)}{\partial w_j} = \frac{1}{m}\sum_{i=0}^{m-1}(g_{\vec w,b}(\vec x^{(i)})-y^{(i)})x_j^{(i)}

\frac{\partial J(\vec w,b)}{\partial b} = \frac{1}{m}\sum_{i=0}^{m-1}(g_{\vec w,b}(\vec x^{(i)})-y^{(i)})

这两个偏导求出来的公式和线性回归的几乎长得一样,但是并不代表他们一样。

这里g_{\vec w,b}(x) = sigmoid(\vec w\cdot \vec x+b)

求导过程请参考文章:逻辑回归梯度下降法

现在只需要利用该算法求得\vec w,b即可。 

关于多分类问题:

softmax多分类现已更新。


补充:F1-score评价指标

关于

混淆矩阵与F1-score详解现已更新。详细介绍请见文章:

【机器学习笔记15】多分类混淆矩阵、F1-score指标详解与代码实现(含数据)_Twilight Sparkle.的博客-CSDN博客

F1-Score简介

F1分数(F1 Score),是统计学中用来衡量二分类模型精确度的一种指标。它同时兼顾了分类模型的精确率和召回率。F1分数可以看作是模型精确率和召回率的一种加权平均,它的最大值是1,最小值是0。

相关概念

下面先介绍几个概念:

  • TP(rue Positive):正样本被判定为正样本

  • FP(False Positive):负样本被判定为正样本

  • TN(True Negative):负样本被判定为负样本

  • FN(False Negative):正样本被判定为负样本

精确度/查准率:指分类器预测为正例中正样本所占比重:

Precision = \frac {TP} {TP+FP}

召回率/查全率:指预测为正例占总正例比重:

Recall = \frac {TP}{TP+FN}

F-Score算法将同时使用以上两个公式,此外,介绍另一种常用的准确率概念:

准确率,指分类器判断正确的占总样本的比重:

Accuracy = \frac {TP+TN}{TP+TN+FP+FN}

F-Score

具体来源等等就不拓展了,有兴趣可以自查。

F-Score是可以综合考虑精确度(Precision)和召回率(Recall)的调和值,公式如下:

F Score = (1+\beta^2)*\frac{Precision*Recall}{\beta^2Precision+Recall}

\beta=1时,被称为F1-Score或F1-Measure。此时精确度和召回率权重相同。

当我们认为精确度更重要,调整\beta<1

当我们认为召回率更重要,调整\beta>1

示例及代码:

数据来源:Pumpkin Seeds Dataset | Kaggle

问题描述:

现在有两类南瓜种子(CERCEVELIK, URGUP_SIVRISI)以及它们的一些特征:

@ATTRIBUTE Area    INTEGER
@ATTRIBUTE Perimeter    REAL
@ATTRIBUTE Major_Axis_Length    REAL
@ATTRIBUTE Minor_Axis_Length    REAL
@ATTRIBUTE Convex_Area    INTEGER
@ATTRIBUTE Equiv_Diameter    REAL
@ATTRIBUTE Eccentricity    REAL
@ATTRIBUTE Solidity    REAL
@ATTRIBUTE Extent    REAL
@ATTRIBUTE Roundness    REAL
@ATTRIBUTE Aspect_Ration    REAL
@ATTRIBUTE Compactness    REAL

现在请根据已知数据集对这两类南瓜种子进行(逻辑回归)分类并判断准确率。

代码说明:会使用sklearn进行数据分割以及评价模型(F1-score),逻辑回归部分全部自主实现。

 所需要的包

import pandas as pd
import numpy as np
import math,copy
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

数据预处理

为了可视化,这里只选择其中两个特征作为特征集(Major_Axis_Length、Minor_Axis_Length)。

导入和提取数据、拆分训练集和数据集:

    # 导入数据
    data = pd.read_excel(r'.\Pumpkin_Seeds_Dataset\Pumpkin_Seeds_Dataset.xlsx',0)
    df = pd.DataFrame(data)

    # 转换数据
    color = []
    label = []
    for i in df['Class']:
        if i == 'Çerçevelik':
            label.append(0)
        elif i == 'Ürgüp Sivrisi':
            label.append(1)

    # 提取所需数据
    x_1 = np.array(df['Major_Axis_Length']).reshape(-1,1)
    x_2 = np.array(df['Minor_Axis_Length']).reshape(-1, 1)
    X_features = np.c_[x_1,x_2]
    Y_target = np.array(label)

    # 拆分训练集和测试集
    X_train,X_test,y_train,y_test = train_test_split(X_features,Y_target,train_size=0.5,random_state=45)

特征缩放(Z-score标准化)

注意:特征缩放一定要用对地方,应该在拆分完训练集和测试集后,仅对训练集使用,不应该把训练集和测试集放在一起标准化,对测试集的操作应该是在对训练集标准化后,使用通过训练集标准化时计算得到的平均值、方差等进行标准化。

这里使用Z-score标准化进行特征缩放。

# Z-score标准化
def Zscore(X):
    '''x是(m,n)的矩阵,m为样本个数,n为特征数目'''
    # 找每列(特征)均值
    mu = np.mean(X,axis=0)
    # 找每列(特征)标准差
    sigma = np.std(X,axis=0)
    X_norm = (X - mu) / sigma

    return X_norm,mu,sigma
    # 标准化特征集
    X_train,mu,sigma = Zscore(X_train)
    # 绘制训练集
    for i in y_train:
         if i == 1:
             color.append("blue")
         else:
             color.append("orange")
    plt.scatter(X_train[:,0],X_train[:,1],color = color)
    plt.xlabel('Major_Axis_Length')
    plt.ylabel('Minor_Axis_Length')
    plt.show()

 标准化后的训练集:

 注:橘色为Çerçevelik种类,蓝色为Ürgüp Sivrisi种类。

实现逻辑回归

sigmoid函数

公式:g(z) = \frac{1}{1+e^{-z}}

def sigmoid(z):
    '''

    :param z: 标量
    :return: 标量
    '''
    g = 1 / (1 + np.exp(-z))
    return g

损失函数

公式:J(\vec w,b) = \frac 1 m \sum_{i=0}^{m-1}L(g_{\vec w,b}(\vec x),y)

# 逻辑回归损失函数
def compute_cost_logistic(X, y, w, b):
    '''

    :param X: 特征集,矩阵
    :param y: 目标值,列表
    :param w: 向量
    :param b: 标量
    :return: 对数损失值,标量
    '''

    m = X.shape[0]
    cost = 0.0
    for i in range(m):
        z_i = np.dot(X[i],w)+b
        g_wb_i = sigmoid(z_i)
        cost += -y[i]*np.log(g_wb_i) - (1-y[i])*np.log(1-g_wb_i)
    cost = cost/m
    return cost

梯度计算函数(求偏导)

公式:

\frac{\partial J(\vec w,b)}{\partial w_j} = \frac{1}{m}\sum_{i=0}^{m-1}(g_{\vec w,b}(\vec x^{(i)})-y^{(i)})x_j^{(i)}

\frac{\partial J(\vec w,b)}{\partial b} = \frac{1}{m}\sum_{i=0}^{m-1}(g_{\vec w,b}(\vec x^{(i)})-y^{(i)})

其中,g_{\vec w,b}(x) = sigmoid(\vec w\cdot \vec x+b)

def compute_gradient_logistic(X, y, w, b):
    '''

    :param X: 特征集,矩阵
    :param y: 目标值,列表
    :param w: 向量
    :param b: 标量
    :return:
        dj_dw: 对数损失函数对向量w的偏导
        dj_db: 对数损失函数对b的偏导
    '''
    m,n = X.shape
    dj_dw = np.zeros((n,))
    dj_db = 0.0

    for i in range(m):
        g_wb_x = sigmoid(np.dot(X[i],w)+b)
        dj_db = dj_db + g_wb_x - y[i]
        for j in range(n):
            dj_dw[j] = dj_dw[j] + (g_wb_x - y[i])*X[i,j]
    dj_dw = dj_dw/m
    dj_db = dj_db/m

    return dj_dw,dj_db

梯度迭代函数

公式:重复以下直到收敛

w_j = w_j - a\frac{\partial J(\vec w,b)}{\partial w_j},\quad j = 0,1,...,n-1

b = b - a\frac{\partial J(\vec w,b)}{\partial b}

def logistic_regression(X_train,y_train,alpha,num_iters):
    '''

    :param X_train: 特征集,矩阵
    :param y_train: 目标值,列表
    :param alpha: 学习率,标量
    :param num_iters: 训练次数,标量
    :return:
        w: 训练得出的w,向量
        b: 训练得出的b,标量
    '''
    m,n = X_train.shape
    init_w = np.zeros((n,)) # n个特征,所以w有n个
    init_b = 0
    w = copy.deepcopy(init_w)
    b = init_b
    for i in range(num_iters):
        if i%100 == 0:
            print(i)
        dj_dw,dj_db = compute_gradient_logistic(X_train,y_train,w,b)
        w = w - alpha*dj_dw
        b = b - alpha*dj_db

    return w,b

训练数据集,绘制拟合决策边界

    model_w,model_b = logistic_regression(X_train,y_train,alpha=0.4,num_iters=10000)
    x_line = np.c_[np.arange(-4,4,0.1).reshape(-1,1),np.arange(-4,4,0.1).reshape(-1,1)]
    print(model_w)
    y_line = np.dot(x_line,model_w)+model_b

    plt.plot(x_line,y_line,label = 'Predicted Value')
    plt.show()

这是当训练次数为10000时得出的决策边界:

模型预测和评价

算出\vec w,b后,代入sigmoid(\vec w\cdot\vec x+b),阈值为0.5。大于等于0.5为1类,小于0.5为0类。

注意预测之前要先将特征测试集标准化。

这里使用F1-Score(F1分数)进行评价。

# 模型预测
def  model_predict(X,w,b):
    '''

    :param X: 测试集
    :param w: 向量
    :param b: 标量
    :return: 预测值(列表)
    '''
    y = []
    for i in X:
        if sigmoid(np.dot(i,w)+b) >= 0.5:
            y.append(1)
        else:
            y.append(0)
    return y

    # 模型预测
    X_test = (X_test - mu) / sigma
    y_predict = model_predict(X_test,model_w,model_b)
    f1_score = f1_score(y_test,y_predict,average='binary')
    print(f"F1分数为:{round(f1_score,2)}")

 结果:

补充:现在将特征集扩大到所有

直接上结果:

稍微比原来准确了一丢丢。

补充:使用sklearn完成逻辑回归

前面讲了一大堆,实际上sklearn几行代码搞定~

泪目

还是刚才那个数据(扩大到所有特征后的),直接上代码!

import pandas as pd
import numpy as np
import math,copy
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

data = pd.read_excel(r'.\Pumpkin_Seeds_Dataset\Pumpkin_Seeds_Dataset.xlsx', 0)
df = pd.DataFrame(data)
label = []
for i in df['Class']:
    if i == 'Çerçevelik':
        label.append(0)
    elif i == 'Ürgüp Sivrisi':
        label.append(1)

X_features_bk = np.array(df)
X_features = X_features_bk[:,:-1]
X_features = np.float32(X_features)
Y_target = np.array(label)

# 拆分训练集和测试集
X_train,X_test,y_train,y_test = train_test_split(X_features,Y_target,train_size=0.5,random_state=45)

# 使用sklearn进行Z-score标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)  # 标准化训练集X

# 绘制训练集
color = []
for i in y_train:
    if i == 1:
        color.append("blue")
    else:
        color.append("orange")
plt.scatter(X_train[:, 2], X_train[:, 3], color=color)
plt.xlabel('Major_Axis_Length')
plt.ylabel('Minor_Axis_Length')
plt.show()

# 训练逻辑回归模型
lr_model = LogisticRegression()
lr_model.fit(X_train,y_train)

# 标准化测试集x
# 只有训练集才fit_transform,测试集是transform,原因上面自己写代码的时候说过了
X_test = scaler.transform(X_test)
# 预测
y_pred = lr_model.predict(X_test)
# F1-Score评估
f1_score = f1_score(y_test,y_pred,average='binary')
print(f"F1分数为:{round(f1_score,2)}")

 中间我们拿出之前那两列来画了下图,这个图是同样的随机种子,采用sklearn的Z-score标准化后得出的图像:

对比我们之前自己处理的数据,只能说,完全一致好吧。

然后来看看结果:

甚至比我们自己写的差了这么一丢丢。导致这个的原因是它的学习率和训练次数和我们选的不一样,不过计算速度比我们快很多,我估计它训练次数选的比较少。如果我们调整自己的参数,也可以达到同样的效果!

  • 41
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
机器学习中的二分类逻辑回归是一种用于解决二分类问题的算法。它的基本思路是通过构建一个逻辑回归模型,将输入的特征映射到一个概率值,然后根据这个概率值进行分类。 逻辑回归使用sigmoid函数来处理hθ(x),这是因为sigmoid函数的取值范围在0到1之间,可以将线性回归的输出转化为一个概率值。通过sigmoid函数处理后,我们可以将概率值大于等于0.5的样本划分为正类,概率值小于0.5的样本划分为负类。这使得逻辑回归可以用于二分类问题。 代价函数的推导和偏导数的推导是为了求解逻辑回归模型中的参数θ。通过最小化代价函数,我们可以得到最优的参数θ,使得模型的预测结果与真实标签最接近。 在正则化逻辑回归中,我们引入正则化项的目的是为了避免过拟合。正则化项可以惩罚模型中的参数,使得参数的值趋向于较小的数值,从而降低模型的复杂度。在正则化逻辑回归中,一般不对θ1进行正则化,这是因为θ1对应的是截距项,它影响模型在原点的位置,不参与特征的权重调整。 综上所述,机器学习中的二分类逻辑回归是一种通过构建逻辑回归模型,利用sigmoid函数将线性回归的输出转化为概率值,并通过最小化代价函数求解参数θ的算法。正则化逻辑回归则是在逻辑回归的基础上引入正则化项,避免过拟合问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [吴恩达机器学习逻辑回归(二分类)](https://blog.csdn.net/q642634743/article/details/118831665)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [机器学习笔记——逻辑回归之二分类](https://blog.csdn.net/dzc_go/article/details/108855689)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Twilight Sparkle.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值