机器学习实验----逻辑回归实现二分类

news2024/12/23 10:37:22

目录

一、介绍

二、sigmoid函数

(1)公式:

(2)sigmoid函数的输入

预测函数:

以下是sigmoid函数代码:

三、梯度上升

(1)似然函数

公式:

概念:

对数平均似然函数公式:

对数似然函数代码:

代码解释:

梯度上升

学习率:

学习率的选取:

参数更新:

 梯度上升代码:

 代码解释:

四、打印散点图和线性回归图像及数据集处理

1.数据集处理

(1)代码思路

(2)代码展现

2.散点图

思路解析:

代码展现:

 运行结果截图:

3.逻辑回归曲线

代码解析:

代码展现:

运行截图:

五、利用逻辑回归进行分类

代码思路:

代码展现:

运行截图:

六、实验中遇到的问题

七、逻辑回归的优缺点

优点:

缺点:

八、实验的改进

九、总代码


一、介绍

逻辑回归是机器学习中的一种分类模型,逻辑回归是一种分类算法,虽然名字中带有回归。由于算法的简单和高效,在实际中应用非常广泛。

二、sigmoid函数

(1)公式:

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

z取值为负无穷到正无穷,g(z)的取值为[0, 1]。他将一个任意的值映射到[0, 1]区间上,我们从线性回归中得到一个预测值,并将该值映射到sigmoid函数中,因为是二分类,所以我们就可以把这个函数看成预测为正类的概率,我们给定一个阈值,如果大于该阈值就判断为正类,如果小于就预测为负类,以此达到分类的效果。

举个例子:当我们抽奖的时候,假设有60%的概率会中奖,当我们线性回归预测得到的预测值代入sigmoid函数的时候值大等于60%,就预测中奖,否则预测为不中奖。

(2)sigmoid函数的输入

预测函数:

h(x)=g(\theta ^{T} x)=\frac{1}{e^{-\theta ^{T}x}}

其中\theta ^{T}x=\sum_{i=1}^{n}\theta _{i}x_{i}=\theta _{0}x_{0}+\theta _{1}x_{1}+....+\theta _{n}x_{n}

按照上面所说,我们用h(x)来表示预测为正类的概率那么预测为负类的概率就为1-h(x)

当二分类的时候就用1来表示正类用0来表示负类,那么我们就可以得到公式:

p(y|x,\theta )=h(x)^{y}(1-h(x))^{1-y}

这样使得y取值为0和1都能表示为预测为y的概率。

以下是sigmoid函数代码:

其中np.exp()也就是e

 def sigmoid(z):
        return 1 / (1 + np.exp(-z))

三、梯度上升

(1)似然函数

公式:

L(\theta )=\prod_{i=1}^{m}P(y_{i}|x_{i};\theta )=\prod_{i=1}^{m}h(x_{i})^{y}(1-h(x_{i}))^{1-y}

概念:

似然函数是一种衡量参数与观测数据之间关系的函数,通过最大化似然函数来估计参数的取值,从而使模型更好地拟合观测数据。

 也就是说我们要使得这个似然函数的值尽可能大,才能使得这个函数拟合效果好。

这时候我们就需要求导求出这个函数的极值。但是由于这个函数求导计算量大,所以我们可以对这个函数取对数,得到对数似然函数。

对数平均似然函数公式:

我们对L(θ)除以m得到平均似然函数,当然可除可不除。

l(\theta)=\frac{1}{m}lnL(\theta)=\frac{1}{m}\sum_{i=1}^{m}(y_{i}ln h(x_{i})+(1-y_{i})ln(1-h(x_{i})))

转化为对数似然将原来的累乘转化为累加使得通过导数求极值的计算量得到减少。

对数似然函数代码:
def srhs(X, y, theta):
    m = len(y)
    h = sigmoid(X.dot(theta))
    res = (1/m) * (y.dot(np.log(h)) + (1-y).dot(np.log(1-h)))
    return res
代码解释:

m是y的样本数量,theta是以数组存储的θ,也就是上面说的θ1到θn,也就是sigmoid的输入,线性回归方程。h得到的也是一个列向量,是数据集x中每个样本点代入到sigmoid函数中的值。因为是累加的,所以我们最后结果就可以直接将其分为两部分用矩阵相乘计算。最后返回一个浮点型的值。

梯度上升

因为我们是求似然函数的最大值,所以我们用梯度上升来求解。当然还有一个算法是梯度下降,求损失函数的最小值,损失函数公式就是我们的平均似然函数乘以-1的结果。本质上来看其实算法原理都一样,只是表示的内容不一样。

学习率:

决定了模型在训练过程中更新权重参数的速度与方向

再梯度上升中就是表示每次对θ值梯度上升的步长,就有点像微积分中某点的导数来估计这个点在一个范围为t内的的导数, t取尽可能小来减少误差。这里的t也就是θ步长。

学习率的选取:

1.选取的太大大,那么在每一步迭代中,模型参数可能会跨过最优解,导致震荡或者发散,这被称为“振荡现象”或“不稳定性”。

2.如果学习率设置得太小,模型收敛到最优解的速度将会非常慢,而且可能会陷入局部极小点,而不是全局最优解。

普通梯度上升和随机梯度上升的区别也就在学习率的选取上,随机梯度上升的学习率不是固定的,更新时通常使用较小的学习率,并且这个学习率可以自适应地调整。

接下来是对似然函数求导以求极大值

在网上查阅资料得到以下求导公式:

\frac{\delta}{\delta_{\theta _{j}}}h(x_{i})=-\frac{e^{\theta _{0}x_{0}+....+\theta _{n}x_{n}}}{(1+e^{\theta _{0}x_{0}+....+\theta _{n}x_{n}})^{2}}x_{i}^{j}=h(x_{i})(1-h(x_{i}))x_{i}^{j}

\frac{\delta }{\delta _{\theta _{j}}}J(\theta )=\frac{1}{m}\sum_{i=1}^{m}(y_{i}\frac{1}{h(x_{i})} \frac{\delta}{\delta_{\theta _{j}}}h(x_{i})-(1-y_{i})\frac{1}{1-h(x_{i})}\frac{\delta}{\delta_{\theta _{j}}}h(x_{i}))

=\frac{1}{m}\sum_{i=1}^{m}(y_{i}\frac{1}{h(x_{i})} -(1-y_{i})\frac{1}{1-h(x_{i})})\frac{\delta}{\delta_{\theta _{j}}}h(x_{i})

=\frac{1}{m}\sum_{i=1}^{m}(y_{i}(1-h(x_{i}))-(1-y_{i})h(x_{i}))x_{i}^j

=\frac{1}{m}\sum_{i=1}^{m}(y_{i}-h(x_{i}))x^j_{i}

 其中的xij就表示对应的θj的那一列。

 那我们就求得了

参数更新:

\theta _{j}:=\theta _{j}+\alpha \frac{1}{m}\sum_{i=1}^{m}(y_{i}-h(x_{i}))x_{i}^{j}

 梯度上升代码:
def gradient_ascent(X, y, num, alpha):
    m, n = X.shape
    theta = np.zeros(n)
    for i in range(num_):
        h = sigmoid(np.dot(X, theta))

        for j in range(n):
            theta[j] += alpha*(np.sum((y - h) * X[:, j]) / m)
    return theta
 代码解释:

按照上面的思路,我们先假设一个\theta _{0}x_{0}+\theta _{1}x_{1}+....+\theta _{n}x_{n},我们用数组theta来存储θ。我们初始值都赋值为0,从0开始使用梯度上升函数对其进行修改。

第一个for循环表示的是总共的迭代次数,也就是进行梯度上升的次数。内层循环遍历就是对θ中的每个值进行修改。theta[j] += alpha*(np.sum((y - h) * X[:, j]) / m)就是套用上面给定的参数更新公式进行迭代。

四、打印散点图和线性回归图像及数据集处理

1.数据集处理

(1)代码思路

数据集使用的是鸢尾花数据集,因为还不会多维的在图像上表示,所以我取的是鸢尾花数据集的"Sepal.Length" "Sepal.Width" 两列来代表二维坐标轴的横纵坐标。

打印一下我的数据:

因为实验是二分类,所以我挑选的是鸢尾花数据集中的setosa和versicolor类别。为了方便我将versicolor赋值为0,setosa赋值为1.最后得到整合的数据。

对迭代次数赋值为1000,步长alafa赋值为0.01。

(2)代码展现

data = pd.read_csv(r"C:\\Users\\李烨\\Desktop\\ljhg.txt", sep=' ')

X = data.iloc[:, :2].values 
y1 = data.iloc[:, -1].values 

#print(X);
len1=len(y1);
y=np.zeros(len1);
for i in range(len1):
    if y1[i] == 'setosa':
        y[i]=1
    if y1[i] == 'versicolor':
        y[i]=0

#print(y)
X = np.c_[np.ones(X.shape[0]), X]
num = 1000  
alafa = 0.1  

2.散点图

思路解析:

用plt.rcParams['font.sans-serif'] = ['SimHei']使得图像上面可以正常显示中文。

用plt.scatter将数据中的点都画到图上

代码展现:

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.scatter(X[:, 1], X[:, 2], c=y, cmap='viridis')
plt.xlabel('Sepal.Length')
plt.ylabel('Sepal.Width')
plt.title('散点图')
plt.show()

 运行结果截图:

3.逻辑回归曲线

代码解析:

因为我们要连接这一条直线,直线其实是很多的点连接起来的,我们就在x的范围内平均取100个点,因为我们的特征只有两个,我们的线性回归方程为\theta _{0}x_{0}+\theta _{1}x_{1}+....+\theta _{n}x_{n}=0。所以第二个特征的解析式x2的取值就为代码所示。然后就是把点代入得到直线。

当然我们看到总共代码有一些和散点图中的重复。但是还得再敲一遍代码,因为plt.show()会把当前的图像打印出来,并不会保留。

代码展现:
xi = np.linspace(np.min(X[:, 1]), np.max(X[:, 1]), 100)
yi = -(theta[0] + theta[1] * xi) / theta[2]

plt.scatter(X[:, 1], X[:, 2], c=y, cmap='viridis')
plt.plot(xi, yi, "r-", label='线性回归曲线')
plt.xlabel('Sepal.Length')
plt.ylabel('Sepal.Width')
plt.title('鸢尾花数据集二分类')
plt.legend()
plt.show()
运行截图:

五、利用逻辑回归进行分类

代码思路:

导入测试集,处理一下数据。

将每一个数据代入到线性回归方程上,得到一个值,这个值的取值就是负无穷到正无穷,代入到sigmoid函数上映射到0,1上,如果大等于0.5就将其分类为正类,否则就是分类为负类,如果分类正确就记录下来。以此得到准确率

代码展现:

test_data = pd.read_csv("C:\\Users\\李烨\\Desktop\\ljhgtest.txt", sep='\s+')
X_test = test_data[["Sepal.Length", "Sepal.Width"]].values
y_test = test_data["Species"].values
cnt=len(y_test)
#print(X_test[1][0])
num=0
for i in range(cnt):
    t = theta[0] + theta[1] * X_test[i][0] + theta[2] * X_test[i][1]

    res1 = res1 = sigmoid(t)
    print(X_test[i],end=' ')
    flag=0
    if res1 >= 0.5 :
        flag=1
        print(f"预测类型为setosa",end=' ')
    else :
        print(f"预测类型为versicolor",end=' ')
    print("实际结果为",y_test[i])
    if flag==1 and y_test[i]=='setosa':
        num=num+1
    if flag==0 and y_test[i]=='versicolor':
        num=num+1

print("准确率为",num/cnt)

运行截图:

六、实验中遇到的问题

(1)本来以为逻辑回归这是简单的线性回归加上sigmoid函数,但是逻辑回归中得到的线和线性回归中得到的不太一样,线性回归中得到的好像是只有一个类别的拟合函数,而逻辑回归得到的是将多个类别分开的曲线,二者的性质不太一样。

(2)对似然函数的求导化简过程需要先取对数减少计算量,靠查阅资料得到化简后的函数,进而得到参数更新的公式。

(3)学习率的选取上需要选择合适的数据,太大太小都会影响程序的准确率。

(4)对于实验数据的选择,实验实现二分类,如果样本特征太多的话,就会导致在坐标轴上无法正确画出图像,我在实验运行选取的是在二维上,所以只选取两个特征。当然我的程序是可以分类多特征值的算法,公式\theta _{0}x_{0}+\theta _{1}x_{1}+....+\theta _{n}x_{n}就可以保证我的算法可以解决多特征值的算法,但是特征太多就无法正确映射到坐标轴上。

七、逻辑回归的优缺点

优点:

  1. 输出值自然地落在0到1之间,类比到概率
  2. 参数代表每个特征对输出的影响
  3. 时间空间复杂度低,计算量小

缺点:

  1. 因为它本质上是一个线性的分类器,所以处理不好特征之间相关的情况。
  2. 容易欠拟合,精度不高

八、实验的改进

(1)实验中可以实现从二分类到多分类的算法,

(2)实验中的梯度上升可以升级为随机梯度上升

随机梯度和梯度的区别主要是在梯度上升每次迭代使用整个训练集计算梯度,然后更新参数;而随机梯度上升每次迭代只使用一个样本数据计算梯度,并更新参数。

修改我的代码改为随机梯度上升只需要修改td函数,两个函数大差不差。

def sgd(X, y, num, alpha):
    m, n = X.shape
    theta = np.zeros(n)
    for j in range(num):
        for i in range(m):
            pos = np.random.randint(0, m)
            h = sigmoid(np.dot(X[pos], theta))
            theta += alpha * (y[pos] - h) * X[pos]
            
    return theta

 与梯度上升相比随机梯度上升的优缺点:

随机梯度上升在每次迭代中只需要计算一个样本数据的梯度,因此通常比梯度上升更快。但是由于每次只用一个样本就会导致曲线的效果没那么好。

九、总代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def sigmoid(z):
    return 1.00 / (1.00 + np.exp(-z))

def sr(X, y, theta):
    m = len(y)
    h = sigmoid(X.dot(theta))
    res = (1 / m) * (y.dot(np.log(h)) + (1 - y).dot(np.log(1 - h)))
    return res

def td(X, y, num_iterations, alpha):
    m, n = X.shape
    theta = np.zeros(n)
    for iteration in range(num_iterations):
        h = sigmoid(np.dot(X, theta))

        for j in range(n):
            theta[j] += alpha*(np.sum((y - h) * X[:, j]) / m)
    return theta


data = pd.read_csv(r"C:\\Users\\李烨\\Desktop\\ljhg.txt", sep=' ')

X = data.iloc[:, :2].values
y1 = data.iloc[:, -1].values

#print(X)
len1 = len(y1)
y=np.zeros(len1)
for i in range(len1):
    if y1[i] == 'setosa':
        y[i]=1
    if y1[i] == 'versicolor':
        y[i]=0
#print(y)
X = np.c_[np.ones(X.shape[0]), X]
num = 1000
alafa = 0.1

theta = td(X, y, num, alafa)
print("线性回归曲线 theta:", theta)

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.scatter(X[:, 1], X[:, 2], c=y, cmap='viridis')
plt.xlabel('Sepal.Length')
plt.ylabel('Sepal.Width')
plt.title('散点图')
plt.show()

xi = np.linspace(np.min(X[:, 1]), np.max(X[:, 1]), 100)
yi = -(theta[0] + theta[1] * xi) / theta[2]

plt.scatter(X[:, 1], X[:, 2], c=y, cmap='viridis')
plt.plot(xi, yi, "r-", label='线性回归曲线')
plt.xlabel('Sepal.Length')
plt.ylabel('Sepal.Width')
plt.title('鸢尾花数据集二分类')
plt.legend()
plt.show()

test_data = pd.read_csv("C:\\Users\\李烨\\Desktop\\ljhgtest.txt", sep='\s+')
X_test = test_data[["Sepal.Length", "Sepal.Width"]].values
y_test = test_data["Species"].values
cnt=len(y_test)
#print(X_test[1][0])
num=0
for i in range(cnt):
    t = theta[0] + theta[1] * X_test[i][0] + theta[2] * X_test[i][1]

    res1 = sigmoid(t)
    print(X_test[i],end=' ')
    flag=0
    if res1 >= 0.5 :
        flag=1
        print(f"预测类型为setosa",end=' ')
    else :
        print(f"预测类型为versicolor",end=' ')
    print("实际结果为",y_test[i])
    if flag==1 and y_test[i]=='setosa':
        num=num+1
    if flag==0 and y_test[i]=='versicolor':
        num=num+1

print("准确率为",num/cnt)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1705038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android存储系统成长记

用心坚持输出易读、有趣、有深度、高质量、体系化的技术文章 本文概要 您一定使用过Context的getFileStreamPath方法或者Environment的getExternalStoragePublicDirectory方法,甚至还有别的方法把数据存储到文件中,这些都是存储系统提供的服务&#x…

【代码随想录——回溯算法——三周目】

1. 子集2 这题需要先进行排序,和候选人那题类似。防止出现重复的子集。 func subsetsWithDup(nums []int) [][]int {path : make([]int, 0)res : make([][]int, 0)sort.Ints(nums)var dfs func(nums []int, start int)dfs func(nums []int, start int) {res app…

08Django项目--用户管理系统--查(前后端)

对应视频链接点击直达 TOC 一些朋友加我Q反馈,希望有每个阶段的完整项目代码,那从今天开始,我会上传完整的项目代码。 用户管理,简而言之就是用户的增删改查。 08项目点击下载,可直接运行(含数据库&…

1967python多媒体素材管理系统mysql数据库Django结构layUI布局计算机软件工程网页

一、源码特点 python Django多媒体素材管理系统是一套完善的web设计系统mysql数据库 ,对理解python编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 开发环境pycharm mysql 5.0 到5.5 依赖包 Dj…

推荐丨 IP地址如何申请SSL证书实现https

为IP地址申请SSL证书可以让用户通过HTTPS协议安全地访问直接绑定到IP地址的网站或服务。以下是申请IP地址SSL证书的一般步骤: 1 选择支持IP证书的CA:直接为IP地址颁发SSL/TLS证书并不常见,国内厂商JoySSL有提供IP证书,登录其官网…

东莞MES管理系统在电子工厂的益处

东莞MES管理系统对东莞电子企业带来了许多好处,包括但不限于以下几点: 提高生产效率:MES系统可以优化生产计划、监控生产过程,提高生产效率,减少生产中的浪费和停机时间,提高产能利用率。 优化库存管理&a…

R可视化:另类的柱状图

介绍 方格状态的柱状图 加载R包 knitr::opts_chunk$set(echo TRUE, message FALSE, warning FALSE) library(patternplot) library(png) library(ggplot2) library(gridExtra)rm(list ls()) options(stringsAsFactors F)导入数据 data <- read.csv(system.file(&qu…

M00238-固定翼无人机集群飞行仿真平台MATLAB完整代码含效果

一个小型无人机集群仿真演示平台&#xff0c;使用matlab和simulink搭建。 给出的例子是5架的&#xff0c;当然如果你愿意花时间&#xff0c;也可以把它扩展到10架&#xff0c;20架甚至更多。 输入&#xff1a;5架飞机的规划路径 输出&#xff1a;每架无人机每个时刻的13个状态量…

如何将天猫内容保存为PDF格式?详细步骤与实战解析

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;保存天猫内容的重要性 二、环境准备与工具安装 1. 安装必要的Python包…

2024年电工杯高校数学建模竞赛(B题) 建模解析| 大学生平衡膳食食谱的优化设计

问题重述及方法概述 问题1&#xff1a;膳食食谱的营养分析评价及调整 数学方法&#xff1a;线性规划模型、营养素评价模型、比较分析 可视化数据图&#xff1a;营养素含量表、营养素摄入量对比图、营养素缺乏情况图 问题2&#xff1a;基于附件3的日平衡膳食食谱的优化设计 数…

idea 中配置 Java 注释模板

引言&#xff1a; 在软件工程中&#xff0c;良好的代码注释习惯对于项目的可维护性和可读性至关重要。IntelliJ IDEA&#xff0c;作为一款强大的Java开发IDE&#xff0c;提供了灵活的注释模板配置功能&#xff0c;帮助开发者快速生成规范的代码注释。本文将详细介绍如何在Inte…

2024年上半年信息系统项目管理师下午真题及答案(第二批)

试题一 某项目计划工期为10个月&#xff0c;预算210万元&#xff0c;第7个月结束时&#xff0c;项目经理进行了绩效评估&#xff0c;发现实际完成了总计划进度的70%。项目的实际数据如表所示&#xff1a; 单击下面头像图片领取更多软考独家资料

【Ambari】Docker 安装Ambari 大数据单机版本

目录 一、前期准备 1.1 部署 docker 1.2 部署 docker-compose 1.3 版本说明 二 、镜像构建启动 2.1 系统镜像构建 2.2 安装包源镜像构建 2.3 kdc镜像构建 2.4 集群安装 2.5 容器导出为镜像 三、Ubuntu环境安装测试 3.1 环境准备 3.2 集群容器启动 一、前期准备 1.…

【C++题解】1125. 删除字符串中间的*

问题&#xff1a;1125. 删除字符串中间的* 类型&#xff1a;字符串 题目描述&#xff1a; 输入一个字符串&#xff0c;将串前和串后的*保留&#xff0c;而将中间的 * 删除。 输入&#xff1a; 一个含*的字符串。 输出&#xff1a; 删除了串中的*的字符串。 样例&#xf…

夏日防晒笔记

1 防晒霜 使用方法&#xff1a;使用前上下摇晃瓶身4至5次&#xff0c;在距离肌肤10至15cm处均匀喷上。如在面部使用&#xff0c;请先喷在掌心再均匀涂抹于面部。排汗量较多时或擦拭肌肤后&#xff0c;请重复涂抹以确保防晒效果。卸除时使用普通洁肤产品洗净即可。

C++:STL容器的学习-->string

C:STL容器的学习-->string 1. 构造方法2. string的赋值操作3. string字符串的拼接4. string 查找和替换5. string字符串的比较6. string字符存取7. string 插入和删除8. string截取 需要添加头文件#include <string> 1. 构造方法 string() 创建空的字符串 string(c…

kafka3.6.1版本学习

kafka目录结构 bin linux系统下可执行脚本文件 bin/windows windows系统下可执行脚本文件 config 配置文件 libs 依赖类库 licenses 许可信息 site-docs 文档 logs 服务日志 启动ZooKeeper 进入Kafka解压缩文件夹的config目录&#xff0c;修改zookeeper.properties配置文件 #t…

深度学习模型在OCR中的可解释性问题与提升探讨

摘要&#xff1a; 随着深度学习技术在光学字符识别&#xff08;OCR&#xff09;领域的广泛应用&#xff0c;人们对深度学习模型的可解释性问题日益关注。本文将探讨OCR中深度学习模型的可解释性概念及其作用&#xff0c;以及如何提高可解释性&#xff0c;使其在实际应用中更可…

企业微信hook接口协议,ipad协议http,语音转文字

语音转文字 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信msgid是int要转文字的语音消息id 请求示例 {"uuid":"a4ea6a39-4b3a-4098-a250-2a07bef57355","msgid":1063645 } 返回示例 {"data&…

App Inventor 2 Encrypt.Security 安全性扩展:MD5哈希,SHA/AES/RSA/BASE64

这是关于App Inventor和Thunkable安全性的扩展&#xff0c;它提供MD5哈希&#xff0c;SHA1和SHA256哈希&#xff0c;AES加密/解密&#xff0c;RSA加密/解密&#xff0c;BASE64编码/解码方法。 权限 此扩展程序不需要任何权限。 事件 OnErrorOccured 抛出任何异常时将触发此事件…