深度学习_15_过拟合欠拟合

过拟合和欠拟合
在这里插入图片描述
过拟合和欠拟合是训练模型中常会发生的事,如所要识别手势过于复杂,如五角星手势,那就需要更改高级更复杂的模型去训练,若用比较简单模型去训练,就会导致模型未能抓住手势的全部特征,那简单模型估计只能抓住五角星的其中一个角做特征,那么这个简单模型很可能就会将三角形与五角星混淆,这就是所谓欠拟合

若用识别五角星的复杂模型去识别三角形也是不行的,模型会过拟合,即学习了过多不重要的部分,可能会把三角形每条边所画的时间也当作学习的内容,即便我们人知道什么时候画哪条边都无所谓。

过拟合和欠拟合的表现都是模型的识别精度不够,所以要想判断模型是过拟合还是欠拟合,除了理论还是要多调试

如:
在这里插入图片描述
合适的模型应该是抛物线,上述左边是欠拟合,右边是过拟合

在这里插入图片描述
训练集和测试集

值得注意的是训练集和测试集必须是分开的,训练模型用训练集,一定不能让测试集污染模型

模型过拟的特征即对见过的数据集表现非常好,而对从未见过的模型表现非常差,若不把训练,测试集完全分开,最后的模型过拟合将无法被发现

实例:

完整代码:

import math
import torch
from torch import nn
from d2l import torch as d2l
import matplotlib.pyplot as plt# 生成随机的数据集
max_degree = 20  # 多项式的最大阶数
n_train, n_test = 100, 100  # 训练和测试数据集大小
true_w = torch.zeros(max_degree)
true_w[0:4] = torch.Tensor([5, 1.2, -3.4, 5.6])# 生成特征
features = torch.randn((n_train + n_test, 1))
permutation_indices = torch.randperm(features.size(0))
# 使用随机排列的索引来打乱features张量(原地修改)
features = features[permutation_indices]
poly_features = torch.pow(features, torch.arange(max_degree).reshape(1, -1))
for i in range(max_degree):poly_features[:, i] /= math.gamma(i + 1)# 生成标签
labels = torch.matmul(poly_features, true_w)
labels += torch.normal(0, 0.1, size=labels.shape)# 以下是你原来的训练函数,没有修改
def evaluate_loss(net, data_iter, loss):metric = d2l.Accumulator(2)for X, y in data_iter:out = net(X)y = y.reshape(out.shape)l = loss(out, y)metric.add(l.sum(), l.numel())return metric[0] / metric[1]def train(train_features, test_features, train_labels, test_labels,num_epochs=400):loss = nn.MSELoss()input_shape = train_features.shape[-1]net = nn.Sequential(nn.Linear(input_shape, 1, bias=False))batch_size = min(10, train_labels.shape[0])train_iter = d2l.load_array((train_features, train_labels.reshape(-1, 1)),batch_size)test_iter = d2l.load_array((test_features, test_labels.reshape(-1, 1)),batch_size, is_train=False)trainer = torch.optim.SGD(net.parameters(), lr=0.01)# 用于存储训练和测试损失的列表train_losses = []test_losses = []for epoch in range(num_epochs):train_loss, train_acc = d2l.train_epoch_ch3(net, train_iter, loss, trainer)test_loss = evaluate_loss(net, test_iter, loss)# 将当前的损失值添加到列表中train_losses.append(train_loss)test_losses.append(test_loss)print(f"Epoch {epoch + 1}/{num_epochs}:")print(f"  训练损失: {train_loss:.4f}, 测试损失: {test_loss:.4f}")print(net[0].weight)# 假设 train_losses 和 test_losses 是已经计算出的损失值列表plt.figure(figsize=(10, 6))plt.plot(train_losses, label='train', color='blue', linestyle='-', marker='.')plt.plot(test_losses, label='test', color='purple', linestyle='--', marker='.')plt.xlabel('epoch')plt.ylabel('loss')plt.title('Loss over Epochs')plt.legend()plt.grid(True)plt.ylim(0, 100)  # 设置y轴的范围从0.01到100plt.show()# 选择多项式特征中的前4个维度
train(poly_features[:n_train, :4], poly_features[n_train:, :4],labels[:n_train], labels[n_train:])

分部讲解如下:

问题实例:
在这里插入图片描述

产生高斯分布随机数x并按上述式子生成训练集和验证集y,并对生成的y再添加一些杂音处理
注意:训练集一定要打乱,不要排序,排序会让训练效果大打折扣,如果训练数据是按照某种特定顺序排列的,那么模型可能会学习到这种顺序并在这个过程中引入偏差,导致模型在未见过的新数据上的泛化能力下降,打乱训练集的目的通常是为了防止模型学习到训练数据中的任何顺序依赖性,这样可以提高模型在随机或未见过的新数据上的泛化能力。

# 生成随机的数据集
max_degree = 20  # 多项式的最大阶数
n_train, n_test = 100, 100  # 训练和测试数据集大小
true_w = torch.zeros(max_degree)
true_w[0:4] = torch.Tensor([5, 1.2, -3.4, 5.6])# 生成特征
features = torch.randn((n_train + n_test, 1))
permutation_indices = torch.randperm(features.size(0))
# 使用随机排列的索引来打乱features张量(原地修改)
features = features[permutation_indices]
poly_features = torch.pow(features, torch.arange(max_degree).reshape(1, -1))
for i in range(max_degree):poly_features[:, i] /= math.gamma(i + 1)# 生成标签
labels = torch.matmul(poly_features, true_w)
labels += torch.normal(0, 0.1, size=labels.shape)

计算损失函数,并不会更新迭代模型,所以用他来测试模型测试集损失

def evaluate_loss(net, data_iter, loss):metric = d2l.Accumulator(2)for X, y in data_iter:out = net(X)y = y.reshape(out.shape)l = loss(out, y)metric.add(l.sum(), l.numel())return metric[0] / metric[1]

训练函数,将X和对应y放在一起,即是进行模型迭代更新,又能计算模型训练损失,测试损失并绘制相应图形

def train(train_features, test_features, train_labels, test_labels,num_epochs=400):loss = nn.MSELoss()  # 默认取平均损失input_shape = train_features.shape[-1]  # 模型大小取train_features最后一项大小net = nn.Sequential(nn.Linear(input_shape, 1, bias=False))batch_size = min(10, train_labels.shape[0])  # 整体数据集分成<= 10批次train_iter = d2l.load_array((train_features, train_labels.reshape(-1, 1)),batch_size)test_iter = d2l.load_array((test_features, test_labels.reshape(-1, 1)),batch_size, is_train=False)trainer = torch.optim.SGD(net.parameters(), lr=0.01)  # 梯度下降算法# 用于存储训练和测试损失的列表train_losses = []test_losses = []for epoch in range(num_epochs):train_loss, train_acc = d2l.train_epoch_ch3(net, train_iter, loss, trainer)  # 训练迭代模型test_loss = evaluate_loss(net, test_iter, loss)# 将当前的损失值添加到列表中train_losses.append(train_loss)test_losses.append(test_loss)print(f"Epoch {epoch + 1}/{num_epochs}:")print(f"  训练损失: {train_loss:.4f}, 测试损失: {test_loss:.4f}")print(net[0].weight)  # 输出训练好的模型# 假设 train_losses 和 test_losses 是已经计算出的损失值列表plt.figure(figsize=(10, 6))plt.plot(train_losses, label='train', color='blue', linestyle='-', marker='.')plt.plot(test_losses, label='test', color='purple', linestyle='--', marker='.')plt.xlabel('epoch')plt.ylabel('loss')plt.title('Loss over Epochs')plt.legend()plt.grid(True)plt.ylim(0, 100)  # 设置y轴的范围从0.01到100plt.show()

主函数

# 选择多项式特征中的前4个维度
train(poly_features[:n_train, :4], poly_features[n_train:, :4],labels[:n_train], labels[n_train:])

利用上述实例验证欠拟合和过拟合以及正常拟合

在这里插入图片描述
上述函数对应真正的模型为:

true_w[0:4] = torch.Tensor([5, 1.2, -3.4, 5.6])

当然还有一些杂质,可忽略

那么可知预训练模型取四个维度就能做到正常拟合,而取二十个维度就是过拟合,取四个以下维度就是欠拟合

过拟合即取二十维度效果:

在这里插入图片描述
可以看出损失在下降到最低点的时候还会有上升
在这里插入图片描述
这是因为学完主要四个维度后又将本应是0的维度也学习了,也就是学习了无用的杂质。
在这里插入图片描述

欠拟合二维度模型效果:

在这里插入图片描述
损失很大,这也是没办法,毕竟还有很多重要维度没有学习上,本质上是模型过小

正常拟合四维度模型效果:

在这里插入图片描述
正常拟合的模型在损失到达最低点后便不再上升,训练出来的模型与真实数据也及其接近

在这里插入图片描述
正常拟合才是我们训练模型的期望状态

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

了解游戏中的数据同步

目录 数据同步 通过比较来看状态同步和帧同步 状态同步 帧同步 帧同步实现需要的条件 两者相比较 数据同步 在联机游戏中&#xff0c;我的操作和数据要同步给同一局游戏中其他所有玩家&#xff0c;其他玩家的操作和数据也会同步给我。这叫做数据同步&#xff0c;目前数据…

《TCP/IP详解 卷一》第10章 UDP 和 IP 分片

目录 10.1 引言 10.2 UDP 头部 10.3 UDP校验和 10.4 例子 10.5 UDP 和 IPv6 10.6 UDP-Lite 10.7 IP分片 10.7.1 例子&#xff1a;IPV4 UDP分片 10.7.2 重组超时 10.8 采用UDP的路径MTU发现 10.9 IP分片和ARP/ND之间的交互 10.10 最大UDP数据报长度 10.11 UDP服务器…

代码随想录Day66 | 图的DFS与BFS

代码随想录Day66 | 图的DFS与BFS DFS797.所有可能的路径无向图和有向图的处理 BFS200.岛屿数量 DFS 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a; 状态 本质上就是回溯算法。 void dfs(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本节点所连接的…

猴子吃桃问题(python版)

文章预览&#xff1a; 题目python解法一&#xff1a;运行结果 python解法二&#xff1a;运行结果 python解法三&#xff1a;运行结果 题目 猴子吃桃问题&#xff1a;猴子第一天摘下若干个桃子&#xff0c;当即吃了一半&#xff0c;还不过瘾&#xff0c;又多吃了一个。 第二天早…

超全面!Linux学习资料大合集,21套从入门到进阶,看这篇就够了

本文将为那些渴望学习Linux&#xff0c;但又缺乏相应资料和方向的朋友&#xff0c;提供21套Linux优质资料&#xff0c;包含入门到进阶&#xff0c;希望能对大家有所帮助。 此合集内容及其丰富&#xff0c;涉及方面颇多&#xff0c;不仅适合Linux入门学习的朋友&#xff0c;运维…

水电站数字孪生:水力发电在可视化领域的应用

自水轮机的早期发明被用于农业灌溉&#xff0c;到 18 世纪末期的工业革命促使水轮机技术的改良&#xff0c;再到 19 世纪末水利发电的崛起&#xff0c;直至今日&#xff0c;智慧水电站数字孪生技术正处于蓬勃发展之中。通过整合物联网、大数据、云计算等现代信息技术&#xff0…

【Zookeeper】ZooKeeper的一些重要功能和作用

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 结语 我的其他博客 前言 随着分布式系统的普及和应用场景的不断增加&#xff0c;构建可靠、高效的分布式系统变得愈发重要。然…

开短路测试

一、介绍 连接性测试&#xff0c;可以叫开短路测试&#xff0c;也可叫接触性测试&#xff0c;英文为Continuity Test或Open & Short Test&#xff0c;主要用来检验测试过程中电学连接是否良好&#xff0c;包括测试设备本身、测试设备与Loadboard、DUT本身等等&#xff0c;是…

SpringBoot接口防抖(防重复提交)的一些实现方案

前言 啥是防抖 思路解析 分布式部署下如何做接口防抖&#xff1f; 具体实现 请求锁 唯一key生成 重复提交判断 前言 作为一名老码农&#xff0c;在开发后端Java业务系统&#xff0c;包括各种管理后台和小程序等。在这些项目中&#xff0c;我设计过单/多租户体系系统&a…

一文梳理LIN协议与应用

目录 一、LIN是什么&#xff1f;有什么用&#xff1f;二、LIN概要描述2.1 特点2.1.1 低成本2.1.2 易扩展2.1.3 速率一般&#xff0c;不高 2.2 网络形态2.3 架构分层 三、应用层 4 大功能3.1 配置3.2 识别&#xff08;查询功能&#xff09;3.3 信号处理3.4 诊断 四、协议层介绍4…

深入理解Docker自定义网络:构建高效的容器网络环境

文章目录 一、docker自定义网络介绍1.1 docker自定义网络介绍1.2 使用技术的优势1.3 基本使用流程 二、实战操作2.1 模式理论介绍bridge模式(默认模式)host模式 2.2 模式特点查看桥接模式的特点查看仅主机模式的特点 2.3 实战操作bridge模式host模式自定义网络 一、docker自定义…

傻瓜式——Kibana 作图指北

背景&#xff1a;比较重要的功能即将上线&#xff0c;需要观测一些项目运行指标&#xff0c;项目周边用了kibana ,想用Kibana 简单做一些图。 难者不会&#xff0c;会者不难—— 在Kibana 中找到这个标签页——可视化 2. 新增可视化图 3. 可以选取自己需要的图样式&#xff…