全连接神经网络

这里写目录标题

  • 全连接神经网络vs前馈神经网络
  • 基于全连接神经网络的手写数字识别
    • 使用Pytorch实现
    • 纯Python实现
  • 全连接神经网络的局限

端到端学习
深度学习有时也称为端到端机器学习(end-to-end machine learning)。这里所说的端到端是指从一端到另一端的意思,也就是从原始数据(输入)中获得目标结果(输出)的意思。

数据驱动
神经网络的性能依赖于大量的数据,通过训练数据来学习模式和特征。

大模型解决运筹优化问题中,一种端到端的方式是,输入问题描述,直接生成模型。而不需要经过中间的参数提取,结构化建模信息

全连接神经网络vs前馈神经网络

前馈神经网络是一类广义的神经网络架构,其中信号从输入层经过一系列隐藏层最终到达输出层,且信号只向前传播,不存在反馈连接。全连接神经网络是前馈神经网络的一种特殊形式。

全连接神经网络是一种特殊的前馈神经网络,其中每一层的每一个神经元都与下一层的每一个神经元相连。这意味着每个节点都接收来自前一层所有节点的输入,并对这些输入进行加权求和,然后通过激活函数输出。

z ( l ) = X W ( l ) ( ) z^{(l)} = XW^{(l)}() z(l)=XW(l)()

基于全连接神经网络的手写数字识别

mini-batch学习(小批量学习)
MNIST数据集的训练数据有60000个,如果以全部数据为对象求损失函数的和,则计算过程需要花费较长的时间。再者,如果遇到大数据,数据量会有几百万、几千万之多,这种情况下以全部数据为对象计算损失函数是不现实的。因此,我们从全部数据中选出一部分,作为全部数据的“近似”。神经网络的学习也是从训练数据中选出一批数据(称为mini-batch,小批量),然后对每个mini-batch进行学习。比如,从60000个训练数据中随机选择100笔,再用这100笔数据进行学习。这种学习方式称为mini-batch学习。

计算电视收视率时,并不会统计所有家庭的电视机,而是仅以那些被选中的家庭为统计对象。比如,通过从关东地区随机选择 1000个家庭计算收视率,可以近似地求得关东地区整体的收视率。这 1000个家庭的收视率,虽然严格上不等于整体的收视率,但可以作为整体的一个近似值。和收视率一样,mini-batch的损失函数也是利用一部分样本数据来近似地计算整体。也就是说,用随机选择的小批量数据(mini-batch)作为全体训练数据的近似值。

损失函数
交叉熵损失(Cross-Entropy Loss)在分类任务中非常常用,尤其是多分类问题。交叉熵损失的公式如下:
L ( Y , Y ^ ) = − 1 m ∑ i = 1 m ∑ j = 1 C Y i j log ⁡ ( Y ^ i j ) L(Y, \hat{Y})= -\frac{1}{m} \sum_{i=1}^{m} \sum_{j=1}^{C} Y_{ij} \log(\hat Y_{ij}) L(Y,Y^)=m1i=1mj=1CYijlog(Y^ij)

其中:

  • Y Y Y 是真实标签(one-hot编码形式), Y ^ \hat{Y} Y^ 是模型预测的概率分布。
  • m m m 是样本数量。
  • C C C 是类别数量。
  • Y i j Y_{ij} Yij是第 i i i 个样本在第 j j j 类的真实标签(1或0)。
  • Y ^ i j \hat{Y}_{ij} Y^ij是第 i i i 个样本在第 j j j 类的预测概率。

使用Pytorch实现

步骤

  1. 数据预处理:
    • 使用 transforms.ToTensor() 将图像转换为张量。
    • 使用 transforms.Normalize() 进行归一化处理。
  2. 加载数据集:
    • 使用 torchvision.datasets.MNIST 加载MNIST数据集。
    • 使用 torch.utils.data.DataLoader 创建数据加载器。
  3. 定义神经网络模型:
    • 使用 nn.Module 定义一个简单的全连接神经网络(FCNN)。
    • 包含三个全连接层和ReLU激活函数。
  4. 定义损失函数和优化器:
  5. 使用 nn.CrossEntropyLoss 作为损失函数。使用 optim.Adam 作为优化器。
  6. 训练模型:进行前向传播、计算损失、反向传播和参数更新。
  7. 测试模型。在测试数据集上评估模型性能,计算准确率。

完整代码

# 下载数据集
from torchvision import datasets, transforms
import torchvision
import torch
import torch.nn as nn  # torch.nn 模块包含了构建和训练神经网络所需的各种类和函数
import torch.optim as optim  # torch.optim 模块包含了各种优化算法import matplotlib.pyplot as pltbatch_size = 256  # 一次处理图片的数量
# Data set
train_dataset = torchvision.datasets.MNIST(root="./data",  # 数据集下载位置train=True,  # 是否作为训练集download=True,  # =True为从网络下载数据集,若已经下载,则不会再次下载transform=transforms.ToTensor(),  # 一般来说,下载的是numpy格式,要转为tensor
)test_dataset = torchvision.datasets.MNIST(root="./data", train=False, transform=transforms.ToTensor()
)# Data loader
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True
)test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False
)
print(train_dataset)
print(test_dataset)
print(train_loader, type(train_loader), len(train_loader))
print(test_loader)# train_loader 是一个 DataLoader 对象,它实现了迭代器协议,因此可以在 for 循环中使用。每次迭代时,train_loader 会返回一个批次的数据和对应的标签。fig, axes = plt.subplots(16, 16)
for batch_idx, (data, target) in enumerate(train_loader):print(f"batch index : {batch_idx}")print(f"data shape: {data.shape}")print(f"target shape :{target.shape}")for batch_index in range(16):for j in range(16):index = batch_index * 16 + jimage = data[index].numpy().squeeze()axes[batch_index][j].imshow(image, cmap="gray")axes[batch_index][j].set_title(f"{target[index]}", fontsize=12)axes[batch_index][j].axis("off")  # 隐藏每个子图的坐标轴,移除子图的坐标轴线、刻度和刻度标签fig.tight_layout(pad=0.2, w_pad=0, h_pad=0)plt.show()break# 定义全连接神经网络模型
class FCNN(nn.Module):# 这里定义了一个名为 FCNN 的类,继承自 nn.Module。nn.Module 是所有神经网络模块的基类。"""这个网络是一个简单的三层全连接神经网络,用于处理MNIST手写数字识别任务。MNIST数据集中的每张图像是28x28像素的灰度图像,表示0到9的手写数字。"""def __init__(self):super(FCNN, self).__init__() # 调用父类 nn.Module 的初始化方法。self.fc1 = nn.Linear(28 * 28, 512) # 定义第一个全连接层(线性层),输入大小为28x28(784个像素),输出大小为512个神经元。self.fc2 = nn.Linear(512, 256) # 定义第二个全连接层,输入大小为512个神经元,输出大小为256个神经元。self.fc3 = nn.Linear(256, 10) # 定义第三个全连接层,输入大小为256个神经元,输出大小为10个神经元(对应0到9的10个类别)。def forward(self, x):x = x.view(-1, 28 * 28)  # 将输入展平x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return xmodel = FCNN()# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss() #  PyTorch 中用于多分类任务的损失函数
"""
optim.Adam 是 PyTorch 中的 Adam 优化器,它是一种自适应学习率优化算法,结合了 AdaGrad 和 RMSProp 的优点。
model.parameters() 返回模型中所有需要优化的参数(即权重和偏置)
lr=0.001 设置了优化器的学习率,学习率决定了每次参数更新的步长
"""
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练模型
num_epochs = 5
loss_list = []
for epoch in range(num_epochs):running_loss = 0.0for batch_index, data in enumerate(train_loader, 0):inputs, labels = dataoptimizer.zero_grad() # 清除梯度缓存outputs = model(inputs) # 前向传播loss = criterion(outputs, labels) #  计算损失loss.backward() # 反向传播optimizer.step() # 更新模型参数running_loss += loss.item() # 累积损失if batch_index % 100 == 99:  # 每100个批次打印一次损失avg_loss = running_loss / 100loss_list.append(avg_loss)print(f"Epoch {epoch + 1}, Batch {batch_index + 1}, Loss: {running_loss / 100:.3f}")running_loss = 0.0print("Finished Training")# 测试模型
correct = 0
total = 0with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f"Accuracy of the network on the 10000 test images: {100 * correct / total:.2f}%")

在这里插入图片描述

纯Python实现

import torch
import torchvision
import torchvision.transforms as transforms
import numpy as np# 定义数据转换
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))
])# 加载训练和测试数据集
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False)# 定义神经网络模型
class SimpleNN:def __init__(self, input_size, hidden_size, output_size):# 初始化权重和偏置"""使用标准正态分布生成随机权重是一种常见的初始化方法,原因如下:用标准正态分布(均值为0,标准差为1)生成随机权重,可以帮助保持每层的激活值的方差稳定。具体来说:如果权重初始化得太大,激活值可能会爆炸(变得非常大),导致梯度爆炸问题。如果权重初始化得太小,激活值可能会消失(变得非常小),导致梯度消失问题。通过使用标准正态分布生成随机权重,可以在一定程度上避免这些问题,使得激活值在合理的范围内变化,从而有助于稳定训练过程。"""self.W1 = np.random.randn(input_size, hidden_size) * 0.01 # 这样做的目的是将权重初始化为较小的值,避免初始权重过大导致的梯度爆炸问题。self.b1 = np.zeros((1, hidden_size))self.W2 = np.random.randn(hidden_size, output_size) * 0.01self.b2 = np.zeros((1, output_size))def relu(self, Z):return np.maximum(0, Z)def relu_derivative(self, Z):return Z > 0def softmax(self, Z):expZ = np.exp(Z - np.max(Z, axis=1, keepdims=True))return expZ / np.sum(expZ, axis=1, keepdims=True)def forward(self, X):# 前向传播self.Z1 = np.dot(X, self.W1) + self.b1self.A1 = self.relu(self.Z1)self.Z2 = np.dot(self.A1, self.W2) + self.b2self.A2 = self.softmax(self.Z2)return self.A2def compute_loss(self, Y, Y_hat):# 计算交叉熵损失m = Y.shape[0]log_likelihood = -np.log(Y_hat[range(m), Y])loss = np.sum(log_likelihood) / mreturn lossdef backward(self, X, Y, Y_hat):# 反向传播m = X.shape[0]dZ2 = Y_hatdZ2[range(m), Y] -= 1dZ2 /= mself.dW2 = np.dot(self.A1.T, dZ2)self.db2 = np.sum(dZ2, axis=0, keepdims=True)dA1 = np.dot(dZ2, self.W2.T)dZ1 = dA1 * self.relu_derivative(self.Z1)self.dW1 = np.dot(X.T, dZ1)self.db1 = np.sum(dZ1, axis=0, keepdims=True)def update_parameters(self, learning_rate):# 更新参数self.W1 -= learning_rate * self.dW1self.b1 -= learning_rate * self.db1self.W2 -= learning_rate * self.dW2self.b2 -= learning_rate * self.db2# 训练模型
def train(model, trainloader, epochs, learning_rate):for epoch in range(epochs):running_loss = 0.0for i, data in enumerate(trainloader, 0):print("batch index", i)inputs, labels = datainputs = inputs.view(inputs.size(0), -1).numpy()  # 展平输入labels = labels.numpy()# 前向传播Y_hat = model.forward(inputs)# 计算损失loss = model.compute_loss(labels, Y_hat)# 反向传播model.backward(inputs, labels, Y_hat)# 更新参数model.update_parameters(learning_rate)running_loss += lossif i % 100 == 99:  # 每100个批次打印一次损失avg_loss = running_loss / 100print(f'Epoch {epoch + 1}, Batch {i + 1}, Loss: {avg_loss:.3f}')running_loss = 0.0# 初始化模型
"""
input_size  在全连接神经网络中,输入层的神经元数量应与输入数据的特征数量相同
hidden_size 藏层的神经元数量是一个超参数,需要通过实验进行调整。隐藏层的神经元数量决定了网络的容量和复杂度。更多的神经元可以捕捉到更复杂的特征,但也可能导致过拟合和计算开销增加。128个神经元是一个合理的起点,可以在实际应用中根据需要进行调整。
输出层(output_size = 10):与分类任务的类别数量相同,MNIST数据集有10个类别,因此输出层的神经元数量为10。
"""
input_size = 784  # 28x28
hidden_size = 128
output_size = 10
model = SimpleNN(input_size, hidden_size, output_size)# 训练模型
epochs = 5
learning_rate = 0.1
train(model, trainloader, epochs, learning_rate)# 测试模型
def predict(model, testloader):correct = 0total = 0for data in testloader:inputs, labels = datainputs = inputs.view(inputs.size(0), -1).numpy()  # 展平输入labels = labels.numpy()Y_hat = model.forward(inputs)predictions = np.argmax(Y_hat, axis=1)total += labels.sizecorrect += (predictions == labels).sum()accuracy = correct / totalprint(f'Accuracy: {accuracy * 100:.2f}%')predict(model, testloader)

全连接神经网络的局限

全连接的神经网络中使用了全连接层(Affine层)。在全连接层中,相邻层的神经元全部连接在一起,输出的数量可以任意决定。这会有一个问题:那就是数据的形状被忽视了。

比如,输入数据是图像时,图像通常是高、长、通道方向上的3维形状。但是,向全连接层输入时,需要将3维数据拉平为1维数据。实际上,前面提到的使用了MNIST数据集的例子中,输入图像就是1通道、高28像素、长28像素的(1, 28, 28)形状,但却被排成1列,以784个数据的形式输入到最开始的Affine层。

图像是3维形状,这个形状中应该含有重要的空间信息。比如,空间上邻近的像素为相似的值、RGB的各个通道之间分别有密切的关联性、相距较远的像素之间没有什么关联等,3维形状中可能隐藏有值得提取的本质模式。但是,因为全连接层会忽视形状,将全部的输入数据作为相同的神经元(同一维度的神经元)处理,所以无法利用与形状相关的信息。

而卷积层可以保持形状不变。当输入数据是图像时,卷积层会以3维数据的形式接收输入数据,并同样以3维数据的形式输出至下一层。因此,在CNN中,可以(有可能)正确理解图像等具有形状的数据。

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

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

相关文章

David律所代理Jose Martin幽默水果版权首发维权,尚未TRO

案件基本情况:起诉时间:2024/9/18案件号:2024-cv-08484原告:Jose Martin原告律所:David起诉地:伊利诺伊州北部法院涉案商标/版权:原告品牌简介:西班牙的卓越艺术家Jose Martin以他非…

网络原理之IP协议(网络层)

目录 前言 什么是IP协议? IP协议的协议头格式 16位总长度(字节数) 16位标识、3位标志位和13位片偏移 8位生存时间 IP地址管理 1.动态分配IP 2.NAT机制(网络地址转换) NAT机制是如何工作的 NAT机制的优缺点…

Nginx反向代理配置支持websocket

一、官方文档 WebSocket proxying 为了将客户端和服务器之间的连接从HTTP/1.1转换为WebSocket,使用了HTTP/1.1中可用的协议切换机制(RFC 2616: Hypertext Transfer Protocol – HTTP/1.1)。 然而,这里有一个微妙之处:由于“升级”…

论文阅读:A Generalization of Transformer Networks to Graphs

论文阅读:A Generalization of Transformer Networks to Graphs 论文地址1 摘要2 贡献Graph TransformerOn Graph Sparsity(图稀疏)On Positional Encodings(位置编码)3 Graph Transformer Architecture(架…

C++:日期类的实现

目录 一、前言 二、头文件 三、各个函数的实现 打印、检查日期及获取日期 、、-、-、 、<、<、>、>、 &#xff01; 日期-日期 >>、<< 一、前言 前面几篇讲了关于类和对象的一些知识&#xff0c;本篇就来实现一下前面用到的日期类。 二、头文…

市面第一款 C++ 版本的U盘装机软件(即将上线)

市面大部分U盘装机软件&#xff0c;都是采用Au3脚本开发&#xff0c;而且有各种捆绑&#xff0c;闲来无聊&#xff0c;采用Qt C制作一款CU盘装机软件&#xff0c;从此告别Au3脚本&#xff0c;各种炫酷界面随便换&#xff0c;敬请期待 另外两个界面暂时不公布&#xff0c;防止Au…

uni-app页面调用接口和路由(四)

文章目录 一、路由二、页面调用接口二、路由跳转1.uni.navigateTo(OBJECT)2.uni.redirectTo(OBJECT)3.uni.reLaunch(OBJECT)4.uni.switchTab(OBJECT)5.uni.navigateBack(OBJECT) 总结 一、路由 路由配置 uni-app页面路由为框架统一管理&#xff0c;开发者需要在pages.json里配…

Linux —— Socket编程(一)

一、本篇重点 1. 认识IP地址、端口号、网络字节序等网络编程中的基本概念 2. 学习Socket api的基本用法 3. 能够实现一个简单的udp客户端/服务器 二、基本概念 1. 理解源IP地址和目的IP地址 简单的理解&#xff0c;IP地址是用于标识一台机器的&#xff0c;我们通过IP地址去…

Springboot常见问题(bean找不到)

如图错误显示userMapper bean没有找到。 解决方案&#xff1a; mapper包位置有问题&#xff1a;因为SpringBoot默认的包扫描机制会扫描启动类所在的包同级文件和子包下的文件。注解问题&#xff1a; 比如没有加mapper注解 然而无论是UserMapper所在的包位置还是Mapper注解都是…

大数据Hologres(一):Hologres 简单介绍

文章目录 Hologres 简单介绍 一、什么是实时数仓 Hologres 二、产品优势 1、专注实时场景 2、亚秒级交互式分析 3、统一数据服务出口 4、开放生态 5、MaxCompute查询加速 6、计算存储分离架构 三、应用场景 搭建实时数仓 四、产品架构 1、Shared Disk/Storage &am…

ER 图 Entity-Relationship (ER) diagram 101 电子商城 数据库设计

起因&#xff0c; 目的: 客户需求, 就是要设计一个数据库。 过程&#xff0c; 关于工具: UI 设计&#xff0c;我最喜欢的工具其实是 Canva, 但是 Canva 没有合适的模板。我用的是 draw.io, 使用感受是&#xff0c;很垃圾。 各种快捷键不适应&#xff0c;箭头就是点不住&…

OpenCV4.8 开发实战系列专栏之 01- 环境搭建与图像读写

大家好&#xff0c;欢迎大家学习OpenCV4.8 开发实战专栏&#xff0c;长期更新&#xff0c;不断分享源码。 专栏代码全部基于C 与Python双语演示&#xff0c;专栏答疑群 请联系微信 OpenCVXueTang_Asst 本文关键知识点&#xff1a; 开发环境搭建、读取图像与显示图像,读取图像…

【笔记篇】一篇文章搞定Spring框架

文章目录 前言一、Spring框架的优势 二、 Spring的使用流程Spring的依赖注入bean后处理器容器后处理器FileSystemResource类Spring的AOP机制AOP基础知识AOP应用案例Spring的事务管理事务控制参数事务的隔离级别 总结 前言 学习完了Spring框架&#xff0c;总结回顾一下。 一、…

使用vite+react+ts+Ant Design开发后台管理项目(三)

前言 本文将引导开发者从零基础开始&#xff0c;运用vite、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈&#xff0c;构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导&#xff0c;文章旨在为开发者揭示如何利用这些技术…

工程师 - Windows下打开PowerShell和CMD Prompt的若干方法

打开PowerShell 在Windows中&#xff0c;你可以通过以下几种方式来打开PowerShell&#xff1a; 1. 开始菜单&#xff08;Start Menu&#xff09;&#xff1a;点击“开始”按钮&#xff0c;然后在搜索栏中输入“PowerShell”。在搜索结果中&#xff0c;选择“Windows PowerShell…

夹耳式蓝牙耳机哪个牌子最好?夹耳式耳机推荐性价比排行榜

耳夹式耳机既不堵耳孔、也不需要包覆耳廓&#xff0c;佩戴时看起来更像是一个“耳环”&#xff0c;固定方式也类似“夹耳朵”。不过&#xff0c;它并不是真的夹住了耳朵肉&#xff0c;而是半夹、半挂——依靠耳廓边缘厚、里面薄&#xff0c;且有一定的弯折面的特殊构造&#xf…

网络层协议 —— IP协议

目录 0.前言 1.IP协议的格式 2.IP地址 2.1IP地址的划分 国际间IP地址的划分 公有IP 私有IP 特殊的IP地址 国内IP地址的划分 2.2IP地址不足问题 2.3IP地址的功能 2.4如何使用IP地址 2.5IP地址的构成 3.网段划分 以前的方案 现在的方案 4.认识宏观网络 5.路由 …

边缘智能-大模型架构初探

R2Cloud接口 机器人注册 请求和应答 注册是一个简单的 HTTP 接口&#xff0c;根据机器人/用户信息注册&#xff0c;创建一个新机器人。 请求 URL URLhttp://ip/robot/regTypePOSTHTTP Version1.1Content-Typeapplication/json 请求参数 Param含义Rule是否必须缺省roboti…

[vulnhub] Hackademic.RTB1

第一次打靶机&#xff0c;思路看的红队笔记 https://www.vulnhub.com/entry/hackademic-rtb1,17/ 环境&#xff1a;kali Linux - 192.168.75.131&#xff0c;靶机 - 192.168.75.132 主机发现和端口扫描 扫描整个网络有哪台机子在线&#xff0c;不进行端口扫描 nmap -sP 192.16…

竹云赋能“中国·贵州”全省统一移动应用平台建设,打造政务服务“新引擎”

近日&#xff0c;2024中国国际大数据产业博览会在贵州贵阳圆满落幕。会上&#xff0c;由贵州省政府办公厅牵头建设的“中国贵州”全省统一移动应用平台正式发布&#xff0c;聚焦民生办事、政务公开、政民互动、扁平高效、数据赋能五大模块&#xff0c;旨在打造公平普惠的服务平…