神经网络代码入门解析

server/2025/3/3 10:12:53/

神经网络代码入门解析

import torch
import matplotlib.pyplot as pltimport randomdef create_data(w, b, data_num):  # 数据生成x = torch.normal(0, 1, (data_num, len(w)))y = torch.matmul(x, w) + b  # 矩阵相乘再加bnoise = torch.normal(0, 0.01, y.shape)  # 为y添加噪声y += noisereturn x, ynum = 500true_w = torch.tensor([8.1, 2, 2, 4])
true_b = 1.1X, Y = create_data(true_w, true_b, num)# plt.scatter(X[:, 3], Y, 1)  # 画散点图 对X取全部的行的第三列,标签Y,点大小
# plt.show()def data_provider(data, label, batchsize):  # 每次取batchsize个数据length = len(label)indices = list(range(length))# 这里需要把数据打乱random.shuffle(indices)for each in range(0, length, batchsize):get_indices = indices[each: each+batchsize]get_data = data[get_indices]get_label = label[get_indices]yield get_data, get_label  # 有存档点的returnbatchsize = 16
# for batch_x, batch_y in data_provider(X, Y, batchsize):
#     print(batch_x, batch_y)
#     break# 定义模型
def fun(x, w, b):pred_y = torch.matmul(x, w) + breturn pred_y# 定义loss
def maeLoss(pre_y, y):return torch.sum(abs(pre_y-y))/len(y)# sgd(梯度下降)
def sgd(paras, lr):with torch.no_grad():  # 这部分代码不计算梯度for para in paras:para -= para.grad * lr  # 不能写成 para = para - paras.grad * lr !!!! 这句相当于要创建一个新的para,会导致报错para.grad.zero_()  # 将使用过的梯度归零lr = 0.01
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True)
b_0 = torch.tensor(0.01, requires_grad=True)
print(w_0, b_0)epochs = 50
for epoch in range(epochs):data_loss = 0for batch_x, batch_y in data_provider(X, Y, batchsize):pred_y = fun(batch_x, w_0, b_0)loss = maeLoss(pred_y, batch_y)loss.backward()sgd([w_0, b_0], lr)data_loss += lossprint("epoch %03d: loss: %.6f" % (epoch, data_loss))print("真实函数值:", true_w, true_b)
print("训练得到的函数值:", w_0, b_0)idx = 0
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy()*w_0[idx].detach().numpy()+b_0.detach().numpy())
plt.scatter(X[:, idx].detach().numpy(), Y, 1)
plt.show()

逐步分析代码

1.数据生成

image-20250301120222530

首先设计一个函数create_data,提供我们所需要的数据集的x与y

def create_data(w, b, data_num):  # 数据生成x = torch.normal(0, 1, (data_num, len(w)))  # 生成特征数据,形状为 (data_num, len(w))y = torch.matmul(x, w) + b  # 计算目标值 y = x * w + bnoise = torch.normal(0, 0.01, y.shape)  # 生成噪声,形状与 y 相同y += noise  # 为 y 添加噪声,模拟真实数据中的随机误差return x, y
  • torch.normal() 生成一个张量

    • torch.normal(0, 1, (data_num, len(w))):生成一个形状为 (data_num, len(w)) 的张量,其中的元素是从均值为 0、标准差为 1 的正态分布中随机采样的。
  • torch.matmul() 让矩阵相乘

    matmul: matrix multiply

  • 再使用torch.normal()生成一个张量,添加到y上,相当于为y添加了随机的噪声

    噪声的引入是为了模拟真实数据中的随机误差,使生成的数据更接近现实场景。

2.设计一个数据加载器

def data_provider(data, label, batchsize):  # 每次取 batchsize 个数据length = len(label)indices = list(range(length))random.shuffle(indices)  # 打乱数据顺序,避免模型学习到顺序特征for each in range(0, length, batchsize):get_indices = indices[each: each+batchsize]  # 获取当前批次的索引get_data = data[get_indices]  # 获取当前批次的数据get_label = label[get_indices]  # 获取当前批次的标签yield get_data, get_label  # 返回当前批次的数据和标签

data_provider可以分批提供数据,并通过yield来返回已实现记忆功能

首先把list y顺序打乱,这样就相当于从生成的训练集y中随机读取,若不打乱数据,可能造成训练结果的不理想

打乱数据可以避免模型在训练过程中学习到数据的顺序特征,从而提高模型的泛化能力。

之后分段遍历打乱的y,返回对应的局部的数据集来给神经网络进行训练

3.定义模型函数

image-20250301122853184

def fun(x, w, b):pred_y = torch.matmul(x, w) + b  # 计算预测值 y = x * w + breturn pred_y

fun(x, w, b) 是一个线性模型,形式为 y = x * w + b,其中 x 是输入特征,w 是权重,b 是偏置。

4.定义Loss函数

image-20250301122958888

def maeLoss(pre_y, y):return torch.sum(abs(pre_y - y)) / len(y)  # 计算平均绝对误差 (MAE)
  • maeLoss 是平均绝对误差(Mean Absolute Error, MAE),它计算预测值 pre_y 和真实值 y 之间的绝对误差的平均值。
  • 公式为:MAE = (1/n) * Σ|pre_y - y|,其中 n 是样本数量。

5.梯度下降sgd函数

# sgd(梯度下降)
def sgd(paras, lr):with torch.no_grad():  # 这部分代码不计算梯度for para in paras:para -= para.grad * lr  # 不能写成 para = para - paras.grad * lr !!!! 这句相当于要创建一个新的para,会导致报错para.grad.zero_()  # 将使用过的梯度归零

这里需要使用torch.no_grad()来避免重复计算梯度

image-20250301123531781

在前向过程中已经累计过一次梯度了,如果在梯度下降过程中又累计了梯度,那么就会造成不必要的麻烦

PyTorch 会累积梯度,如果不手动清零,梯度会不断累积,导致参数更新错误。

para -= para.grad * lr就是将参数w修正的过程(w=w-(dy^/dw)*learningRate)

torch.no_grad() 是一个上下文管理器,用于禁用梯度计算。在参数更新时,禁用梯度计算可以避免不必要的计算和内存占用。

5.开始训练

epochs = 50
for epoch in range(epochs):data_loss = 0num_batches = len(Y) // batchsize  # 计算批次数量for batch_x, batch_y in data_provider(X, Y, batchsize):pred_y = fun(batch_x, w_0, b_0)  # 前向传播loss = maeLoss(pred_y, batch_y)  # 计算损失loss.backward()  # 反向传播sgd([w_0, b_0], lr)  # 更新参数data_loss += loss.item()  # 累积损失print("epoch %03d: loss: %.6f" % (epoch, data_loss / num_batches))  # 打印平均损失

先定义一个训练轮次epochs=50,表示训练50轮

在每轮训练中将loss记录下来,以此评价训练的效果

首先用data_provider来获取数据集中随机的一部分

接着传入相应数据给模型函数,通过前向传播获得预测y值pred_y

调用Loss计算函数,获取这次的loss,再通过反向传播loss.backward()计算梯度

loss.backward() 是反向传播的核心步骤,用于计算损失函数对模型参数的梯度。

再通过梯度下降sgd([w_0, b_0], lr)来更新模型的参数

最终将这组数据的loss累加到这轮数据的loss中

6.结果绘制

idx = 0
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy() * w_0[idx].detach().numpy() + b_0.detach().numpy())  # 绘制预测直线
plt.scatter(X[:, idx].detach().numpy(), Y, 1)  # 绘制真实数据点
plt.show()

http://www.ppmy.cn/server/172029.html

相关文章

目前主流 AI 大模型体系全解析:架构、特点与应用

大家好,我是大 F,深耕AI算法十余年,互联网大厂技术岗。分享AI算法干货、技术心得。 欢迎关注《大模型理论和实战》、《DeepSeek技术解析和实战》,一起探索技术的无限可能! 阅读完本文,您将知道:目前主流的大模型体系有哪些?及其架构的特点。 前言 在自然语言处理(NL…

微服务测试

微服务架构是一种将应用程序设计为一组小型、独立服务的方法,每个服务实现特定的业务功能,并通过定义良好的 API 进行通信。由于微服务架构的复杂性,测试微服务变得尤为重要。以下是一些微服务测试的实践和策略: 微服务测试的挑战 服务间的依赖:微服务之间存在复杂的依赖…

【机器学习chp10】降维——(核化)PCA + MDS + lsomap + 拉普拉斯特征映射 + t-NSE + UMAP

目录 一、降维的意义与本质 1、意义 2、本质 3、常见降维方法 (1)线性降维 (2)非线性降维 二、基于重构的降维 1、PCA 2、核化PCA (1)实现过程 步骤一:数据映射与核函数定义 步骤二…

SEO长尾词优化进阶法则

内容概要 本文系统梳理SEO长尾词优化的全流程进阶策略,聚焦从关键词价值挖掘到可持续流量增长的完整闭环。核心模块包括长尾关键词的精准定位、用户搜索意图的深度解析、语义关联布局的技术实现,以及内容与算法的动态适配机制。通过七个关键维度构建方法…

TrustRAG:通过配置化模块化的检索增强生成(RAG)框架提高生成结果的可靠性和可追溯性

TrustRAG旨在风险感知的信息检索场景中提高生成内容的一致性和可信度。用户可以利用私有语料库构建自己的RAG应用程序,研究库中的RAG组件,并使用定制模块进行实验。论文展示了TrustRAG系统在摘要问答任务中的应用,并通过案例研究验证了其有效…

新民主主义革命的道路和基本经验

新民主主义革命的道路和基本经验是中国共产党在长期革命实践中形成的核心理论与实践总结,其内涵可从以下两方面系统阐述: 一、新民主主义革命的道路:农村包围城市、武装夺取政权 提出背景与理论发展 1927年大革命失败后,毛泽东基…

蓝桥杯web第三天

展开扇子题目, #box:hover #item1 { transform:rotate(-60deg); } 当悬浮在父盒子,子元素旋转 webkit display: -webkit-box:将元素设置为弹性伸缩盒子模型。-webkit-box-orient: vertical:设置伸缩盒子的子元素排列方…

AVR 单片机硬件供电处理

摘自AVR 单片机应用笔记:AN2519 - AVR Microcontroller Hardware Design Considerations。 2. 供电 供电设计是任何硬件设计的关键一环,直接影响到系统的性能。在设计供电时,有两个重要的方面需要考虑:ESD 防护和噪声干扰。这些内…