【pytorch深度学习——小样本学习策略】网格搜索和遗传算法混合优化支持向量机的小样本学习策略进行预测

news2024/9/24 9:20:48

最近需要根据心率血氧数据来预测疲劳度,但是由于心率血氧开源数据量较少,所以在训练模型时面临着样本数量小的问题,需要对疲劳程度进行多分类,属于小样本,高维度问题。在有限样本的条件之下,必须要需要选择合适的深度学习算法同时满足模型的泛化能力和学习精度。其次,由于小样本学习的前提,不可避免的问题就是过拟合,因此在选择和训练模型的过程中要尽量规避过拟合的问题。再次,如何对于数据进行预处理直接影响了模型的输入层的设计甚至模型整体,特别是在小样本学习的条件下,要充分利用有限样本数据进行预处理。最后,模型的参数优化问题决定了模型的表现,好的参数设定往往可以大幅提升模型的性能。

于是我们采用了网格搜索和遗传算法混合优化支持向量机的小样本学习策略来构建模型。

首先进行了相关论文的查阅

  1. 疲劳检测与血氧饱和度的关系:
    1. 郭稳等在《基于多源生理信号的装备操作人员穿戴式疲劳检测方法研究》论文中给出了模拟实验的方法和结论,疲劳分数和血氧饱和度之间有着显著的负相关关系。
    2. 李雨等在《基于多生理信息融合的运动疲劳检测系统的搭建》论文中测试并概述了随着疲劳等级的加深,血氧饱和度是趋于下降的趋势。
  2. 疲劳检测与心率的关系。
    1. 郭稳等在《基于多源生理信号的装备操作人员穿戴式疲劳检测方法研究》论文中证明了疲劳会使心率的波动程度有一定的变化。
    2. 李雨等在《基于多生理信息融合的运动疲劳检测系统的搭建》论文中测试并概述了随着疲劳等级的加深,心率的最大值最小值之差、心率的标准差这两个特征值没有较为规律的趋势,相反心率最大值、心率最小值、心率平均值具有明显的规律,即这三个特征值随着疲劳等级的加深均呈明显的上升趋势。

所以我们选用心率血氧两个指标作为疲劳度预测模型的输入,其中在小样本的条件之下,要想满足机器学习方法的泛化能力和学习精度,拟选择支持向量机(SVM)这种机器学习的理论方法。不选择神经网络是因为它对于有限样本的学习能力很强容易出现过学习的现象导致模型的泛化能力很差,不选择贝叶斯网络的原因是本项目特征值之间并非独立关系,不选择决策树的原因是容易出现过拟合已经不能很好表征数据之间的相关性。

遗传算法和网格搜索混合算法通过遗传算法适用于非线性和非凸问题弥补了网格搜索不适用于非凸优化问题的缺点,同时混合算法结合了两者的优点,具有更强的全面搜索能力确保可以找到最佳函数参数g和惩罚参数c,可以一定程度上弥补有限样本参数难以优化的缺点。

具体的结构框图如下:

具体的代码及注释如下:

 

# 在小样本的条件之下,要想满足机器学习方法的泛化能力和学习精度,拟选择支持向量机(SVM)这种机器学习的理论方法。不选择神经网络是因为它对于有限样本的学习能力很强容易出现过学习的现象导致模型的泛化能力很差,不选择贝叶斯网络的原因是本项目特征值之间并非独立关系,不选择决策树的原因是容易出现过拟合已经不能很好表征数据之间的相关性。
# 遗传算法和网格搜索混合算法通过遗传算法适用于非线性和非凸问题弥补了网格搜索不适用于非凸优化问题的缺点,同时混合算法结合了两者的优点,具有更强的全面搜索能力确保可以找到最佳函数参数g和惩罚参数c,可以一定程度上弥补有限样本参数难以优化的缺点。

import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import StandardScaler
import random

# 数据:定义一个字典,包含心率、血氧和疲劳度的数据
data = {
    'heart_rate': [50, 40, 70, 75, 80, 85, 90, 60, 65, 78, 82, 88, 72, 77, 83, 87, 91, 62, 67, 79, 84, 89, 74, 76, 81,
                   86, 92,
                   61, 66, 69, 73, 95, 150, 140],
    'blood_oxygen': [75, 70, 98, 97, 95, 94, 93, 99, 98, 96, 95, 92, 97, 96, 94, 93, 92, 100, 99, 97, 95, 91, 96, 97,
                     93, 94,
                     90, 98, 97, 96, 94, 89, 80, 82],
    'fatigue_level': [0.92, 0.9, 0.2, 0.3, 0.5, 0.6, 0.7, 0.1, 0.15, 0.4, 0.55, 0.65, 0.25, 0.35, 0.52, 0.63, 0.72,
                      0.12, 0.18,
                      0.45, 0.57, 0.67, 0.27, 0.37, 0.48, 0.58, 0.75, 0.22, 0.33, 0.44, 0.54, 0.78, 0.93, 0.90]
}

# 转换为DataFrame:将字典数据转换为Pandas的DataFrame格式,方便数据处理
df = pd.DataFrame(data)

# 准备数据:从DataFrame中提取特征和目标变量
X = df[['heart_rate', 'blood_oxygen']].values
y = df['fatigue_level'].values

# 标准化数据:对特征数据进行标准化处理,使其均值为0,方差为1
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 划分训练和测试集:将数据划分为训练集和测试集,比例为80%训练集,20%测试集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

# 转换为PyTorch张量:将训练和测试数据转换为PyTorch张量
X_train_tensor = torch.tensor(X_train, dtype=torch.float32)
y_train_tensor = torch.tensor(y_train, dtype=torch.float32).unsqueeze(1)  # 目标变量需转为二维
X_test_tensor = torch.tensor(X_test, dtype=torch.float32)
y_test_tensor = torch.tensor(y_test, dtype=torch.float32).unsqueeze(1)

# 自定义SVM模型:定义一个简单的SVM模型,使用线性层模拟SVM
class SVM(nn.Module):
    def __init__(self, input_dim):
        super(SVM, self).__init__()
        self.fc = nn.Linear(input_dim, 1)  # 定义线性层
        self.fc.weight.data.fill_(0.0)  # 初始化权重为0
        self.fc.bias.data.fill_(0.0)  # 初始化偏置为0

    def forward(self, x):
        return self.fc(x)  # 前向传播

# 遗传算法适应度函数:定义适应度函数,用于评估每个个体的性能
def fitness(individual):
    model = SVM(input_dim=2)
    # 转换个体为PyTorch张量,并进行必要的形状调整
    weights = torch.tensor(np.array(individual[:2]).reshape(1, 2), dtype=torch.float32)
    bias = torch.tensor([individual[2]], dtype=torch.float32)

    model.fc.weight = nn.Parameter(weights)  # 设置模型权重
    model.fc.bias = nn.Parameter(bias)  # 设置模型偏置

    criterion = nn.MSELoss()  # 损失函数:均方误差
    optimizer = optim.SGD(model.parameters(), lr=0.01)  # 优化器:随机梯度下降

    num_epochs = 100  # 训练轮次
    for epoch in range(num_epochs):
        model.train()  # 训练模式
        optimizer.zero_grad()  # 清除梯度
        outputs = model(X_train_tensor)  # 前向传播
        loss = criterion(outputs, y_train_tensor)  # 计算损失
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数

    model.eval()  # 测试模式
    with torch.no_grad():
        predictions = model(X_test_tensor)  # 预测
        mse = mean_squared_error(y_test_tensor.numpy(), predictions.numpy())  # 计算均方误差

    return mse

# 初始化种群:生成初始种群,每个个体包含2个权重和1个偏置
def initialize_population(size):
    population = []
    for _ in range(size):
        individual = np.random.uniform(-1, 1, 3).tolist()  # 随机生成个体
        population.append(individual)
    return population

# 遗传算法选择函数:根据适应度选择个体
def select(population, fitnesses, num):
    selected = random.choices(population, weights=[1 / f for f in fitnesses], k=num)
    return selected

# 遗传算法交叉函数:生成子代个体
def crossover(parent1, parent2):
    point = random.randint(1, len(parent1) - 1)  # 随机选择交叉点
    child1 = parent1[:point] + parent2[point:]  # 生成第一个子代
    child2 = parent2[:point] + parent1[point:]  # 生成第二个子代
    return child1, child2

# 遗传算法变异函数:对个体进行变异
def mutate(individual, rate=0.01):
    for i in range(len(individual)):
        if random.random() < rate:  # 根据变异率决定是否变异
            individual[i] = np.random.uniform(-1, 1)  # 变异
    return individual

# 遗传算法主函数:运行遗传算法以寻找最优个体
def genetic_algorithm(pop_size, generations, crossover_rate=0.7, mutation_rate=0.01):
    population = initialize_population(pop_size)  # 初始化种群
    for generation in range(generations):
        fitnesses = [fitness(individual) for individual in population]  # 计算适应度
        new_population = []
        for _ in range(pop_size // 2):
            parents = select(population, fitnesses, 2)  # 选择父代
            if random.random() < crossover_rate:
                child1, child2 = crossover(parents[0], parents[1])  # 交叉
            else:
                child1, child2 = parents[0], parents[1]  # 保持父代不变
            child1 = mutate(child1, mutation_rate)  # 变异
            child2 = mutate(child2, mutation_rate)  # 变异
            new_population.extend([child1, child2])  # 更新种群
        population = new_population

    best_individual = min(population, key=fitness)  # 选择最优个体
    return best_individual

# 使用遗传算法优化SVM的超参数
best_params = genetic_algorithm(pop_size=50, generations=100)

# 使用优化后的参数训练最终模型
model = SVM(input_dim=2)
model.fc.weight = nn.Parameter(torch.tensor(np.array(best_params[:2]).reshape(1, 2), dtype=torch.float32))  # 设置最佳权重
model.fc.bias = nn.Parameter(torch.tensor([best_params[2]], dtype=torch.float32))  # 设置最佳偏置

criterion = nn.MSELoss()  # 损失函数:均方误差
optimizer = optim.SGD(model.parameters(), lr=0.01)  # 优化器:随机梯度下降

num_epochs = 1000  # 训练轮次
for epoch in range(num_epochs):
    model.train()  # 训练模式
    optimizer.zero_grad()  # 清除梯度
    outputs = model(X_train_tensor)  # 前向传播
    loss = criterion(outputs, y_train_tensor)  # 计算损失
    loss.backward()  # 反向传播
    optimizer.step()  # 更新参数

model.eval()  # 测试模式
with torch.no_grad():
    predictions = model(X_test_tensor)  # 预测
    mse = mean_squared_error(y_test_tensor.numpy(), predictions.numpy())  # 计算均方误差
    print(f'测试集均方误差: {mse}')  # 输出测试集均方误差

# 保存模型:可以取消注释以保存模型
# torch.save(model.state_dict(), 'svm_fatigue_model.pth')

# 使用训练好的模型进行疲劳度预测
new_data = torch.tensor(scaler.transform([[90, 88]]), dtype=torch.float32)  # 标准化新的数据
with torch.no_grad():
    new_predictions = model(new_data)  # 预测
    print(f'新的疲劳度预测: {new_predictions.item()}')  # 输出新的疲劳度预测

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

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

相关文章

游戏开发设计模式之责任链模式

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许将请求沿着处理者链进行发送。每个处理者对象都有机会处理该请求&#xff0c;直到某个处理者决定处理该请求为止。 概念与定义 责任链模式的核心思想是将多个处理器…

vue3路由使用createWebHistory部署访问404问题 vite部署访问404问题

vue3路由使用createWebHistory部署访问404问题 vite部署访问404问题 开始createWebHistory() H5路由模式修改vite.config.js修改 router/index.js 路由模式修改Nginx配置1配置2配置3 createWebHashHistory() 哈希模式修改vite.config.js修改 router/index.js 路由模式Nginx配置…

文件IO和多路复用IO

目录 前言 一、文件 I/O 1.基本文件 I/O 操作 1.1打开文件 1.2读取文件内容 (read) 1.3写入文件 (write) 1.4关闭文件 (close) 2.文件指针 二、多路复用 I/O 1.常用的多路复用 I/O 模型 1.1select 1.2poll 1.3epoll 2.使用 select、poll 和 epoll 进行简单的 I/O…

基于vue框架的北城招聘管理平台题目7lly3(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,企业,企业信息,职位类型,职位信息,简历信息,职位应聘,求职意愿,面试信息,录取信息,实习信息,冻结信息,解冻信息 开题报告内容 基于Vue框架的北城招聘管理平台 开题报告 一、引言 随着互联网的飞速发展和企业对人才需求的不断增…

无人机之如何利用无人机进行地形测绘

一、无人机的选择 多旋翼无人机&#xff1a;多旋翼无人机具有较好的稳定性和悬停能力&#xff0c;适用于复杂地形和需要高精度影像测绘任务。 固定翼无人机&#xff1a;固定翼无人机飞行速度快&#xff0c;续航能力强&#xff0c;更适合大面积的地形测绘工作。 消费级无人机…

python怎么删除模块

1、用命令行删除 安装pip $ wget https://bootstrap.pypa.io/get-pip.py $ python get-pip.py 删除指定的模块或者包&#xff1a; pip uninstall xxx 2、手动删除 去Python的第三方模块或包的存放位置进行手工删除文件和文件夹&#xff0c;然后删除easy-install.pth文件中的相…

Canvas实现电子签名功能

实现代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Canvas实现手写板</t…

开发指南056-定时任务

业务场景中定时任务很常见。平台实现定时任务的原则如下&#xff1a; 1、定时任务的定义在业务库&#xff08;没必要集中到核心库&#xff0c;另外定时任务的服务要访问业务库&#xff09;。 2、定时任务的服务为独立微服务。 平台的定时任务基于&#xff1a; <dependenc…

20240824 每日AI必读资讯

谷歌搜索引擎全面揭秘&#xff01;近百份文档泄露&#xff0c;博主爆肝数周逆向工程 - 继5月的文件泄露事件后&#xff0c;谷歌的搜索引擎又被掀了个底朝天。 - DeepMind发论文解释了Vizier系统的机制&#xff0c;博客作者Mario Fischer还对近百份文档做了彻底的调研分析&…

单位信息宣传考核投稿方法不对让我尝尽了苦头

自从我担任单位的信息宣传员以来,便深刻体会到“信息宣传”四个字背后的重量。每月的信息宣传考核任务就像一座大山,压在我心头。起初,我像大多数同行一样,习惯于通过电子邮件向各大媒体投稿,但这种方式让我尝尽了苦头。 记得开始尝试通过邮箱投稿时,我满怀信心地将精心准备的文…

C语言-内存管

内存区间 全局/静态存储区 不仅仅包含全局变量&#xff0c;还包含静态变量&#xff08;包括在函数内部定义的静态局部变量&#xff09;、字符串常量以及main函数开始执行之前就被初始化的所有其他数据。这些数据的生命周期贯穿整个程序执行期间。 对于一个C语言程序而言&…

SQL-DQL-数据查询语言

数据查询语言 1、基础查询 2、条件查询 3、聚合函数 4、分组查询 5、分页查询 6、案例 7、执行顺序 select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表 having 分组后条件列表 order by 排序字段列表 limit 分页参数1、基础查询 select 字段1[as 别…

OpenCV与AI深度学习 | 基于改进YOLOv8的景区行人检测算法

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;基于改进YOLOv8的景区行人检测算法 作者&#xff1a;贵向泉&#xff0c;刘世清&#xff0c;李立等 来源&#xff1a;《计算机工程》期刊 编…

Linux 命令集合

1. linux 系统版本 1.1 linux系统的分类 linux系统&#xff0c;主要分Debian系和RedHat系&#xff0c;还有其它自由的发布版本。 1、Debian系主要有Debian&#xff0c;Ubuntu&#xff0c;Mint等及其衍生版本&#xff1b; 2、RedHat系主要有RedHat&#xff0c;Fedora&#xf…

AI可预测地震,科技的“预知未来”?

在科幻小说和电影中&#xff0c;预知未来的能力总是让人向往。而在现实世界中&#xff0c;科学家们正利用人工智能&#xff08;AI&#xff09;技术&#xff0c;向着预测自然灾害这一“未来”的目标迈进。 近日&#xff0c;德州大学奥斯汀分校&#xff08;UT Austin&#xff09;…

【C++】C++的模板初识

目录 思维导图大纲&#xff1a; 1. 什么是模板&#xff1f; 2. 模板的分类 区别&#xff1a;函数模版和模版函数 / 类模版和模版类 2.1 函数模板 2.1.1 用法 2.1.2 原理 2.1.3 函数模板的实例化 2.1.4 模板参数的匹配原则 2.2 类模板 2.2.1 用法 2.2.2 原理 …

Linux--gdb的常用命令

目录 前言 一、gdb是什么&#xff1f; 二、常用命令 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 对于程序有两个版本&#xff0c;一个是debug版和release版&#xff0c;要想进行调试必须使用debug版本&#xff0c;再Linux上进行调试就要用到调试器…

660高数刷题

1 周期函数的周期等于上下限的差值则值相等 2 3 4 5 6 泰勒公式要展开到多少阶

快速幂算法【算法 08】

快速幂算法详解 在计算机编程中&#xff0c;快速幂算法是一种高效计算大整数幂次的算法。相较于直接的暴力计算&#xff0c;快速幂能够在对数级别的时间复杂度下完成运算&#xff0c;因此它在许多算法和问题中&#xff08;如数论、组合数学、密码学等&#xff09;都有广泛的应用…

web常见漏洞之——SSRF

ssrf 概述工具环境实验一 概述 SSRF(Server-Side Request Forgery)叫做服务器请求伪造&#xff0c;因为服务器提供了从其他服务器应用获取数据的功能且没有对目标地址进行过滤和限制导致黑客可以对服务器请求的地址进行伪造。 ssrf漏洞的主要用处就是对服务器进行资源扫描&am…