3.3 PyTorch基础:


更新于 2025-02-16
推荐镜像 :Basic Image:bohrium-notebook:2023-04-07
推荐机型 :c2_m4_cpu
赞 1
目录
[ ]
代码
文本
双击即可修改
代码
文本
3.3.3 PyTorch安装与导入
代码
文本
在玻尔科研空间站,安装过程可以省去,直接使用对应镜像即可
代码
文本
[1]
import torch
import torch.nn as nn
代码
文本
3.3.4 PyTorch基础:Tensor与简单计算
代码
文本
[2]
import torch
import numpy as np
# 从 Python 列表创建 Tensor
tensor_from_list = torch.tensor([1, 2, 3, 4])
# 从 NumPy 数组创建 Tensor
numpy_array = np.array([1, 2, 3, 4])
tensor_from_numpy = torch.tensor(numpy_array)
zero_tensor = torch.zeros(2, 3) # 创建一个 2x3 的全零 Tensor
one_tensor = torch.ones(3, 3) # 创建一个 3x3 的全一 Tensor
random_tensor = torch.randn(2, 3) # 创建一个 2x3 的随机 Tensor(符合正态分布)
代码
文本
[3]
# 创建两个简单的 Tensor
tensor1 = torch.tensor([1, 2, 3, 4])
tensor2 = torch.tensor([5, 6, 7, 8])
# 加法:对应元素相加
result_add = tensor1 + tensor2
print("加法结果:", result_add)
# 乘法:对应元素相乘
result_mul = tensor1 * tensor2
print("乘法结果:", result_mul)
# 访问元素:访问第一个元素
first_element = tensor1[0]
print("tensor1 第一个元素:", first_element)
# 切片操作:访问第二到第四个元素
sub_tensor = tensor1[1:4]
print("tensor1 从第二到第四个元素:", sub_tensor)
# 修改元素:将 tensor1 的第三个元素改为 10
tensor1[2] = 10
print("修改后的 tensor1:", tensor1)
加法结果: tensor([ 6, 8, 10, 12]) 乘法结果: tensor([ 5, 12, 21, 32]) tensor1 第一个元素: tensor(1) tensor1 从第二到第四个元素: tensor([2, 3, 4]) 修改后的 tensor1: tensor([ 1, 2, 10, 4])
代码
文本
3.3.6 使用PyTorch构建多层感知机
代码
文本
3.3.6.2 多层感知机构建的常规做法
代码
文本
[4]
import torch
import torch.nn as nn
import torch.nn.functional as F
# 定义一个简单的多层感知机
class SimpleMLP(nn.Module):
# __init__函数对模型进行初始化
def __init__(self, input_size, hidden_size, output_size):
super().__init__()
self.fc1 = nn.Linear(input_size, hidden_size) # 第一层
self.fc2 = nn.Linear(hidden_size, output_size) # 输出层
# forward函数定义如何进行前向传播
def forward(self, x):
x = self.fc1(x) # 经过第一个全连接层
x = F.relu(x) # 使用 F.relu 进行激活
x = self.fc2(x) # 经过输出层
return x
代码
文本
[5]
# 设置参数
input_size = 3 # 输入特征数
hidden_size = 4 # 隐藏层神经元数
output_size = 1 # 输出结果
# 创建模型实例
model = SimpleMLP(input_size, hidden_size, output_size)
# 打印模型结构
print(model)
# 前向传播
x = torch.randn(3) # 生成随机输入数据
output = model(x)
print("模型输出:", output)
print(output.shape) # 结果:torch.Size([2])
SimpleMLP( (fc1): Linear(in_features=3, out_features=4, bias=True) (fc2): Linear(in_features=4, out_features=1, bias=True) ) 模型输出: tensor([0.3716], grad_fn=<AddBackward0>) torch.Size([1])
代码
文本
3.3.6.3 使用nn.Sequential
快速构建网络
代码
文本
[6]
# 使用 nn.Sequential 快速构建多层感知机
model_seq = nn.Sequential(
nn.Linear(3, 4), # 第一层全连接层:输入特征数3,输出隐藏层神经元数4
nn.ReLU(), # ReLU 激活函数
nn.Linear(4, 1) # 第二层全连接层:从隐藏层到输出层,输出神经元数2
)
print("\n使用 nn.Sequential 构建的多层感知机模型:")
print(model_seq)
使用 nn.Sequential 构建的多层感知机模型: Sequential( (0): Linear(in_features=3, out_features=4, bias=True) (1): ReLU() (2): Linear(in_features=4, out_features=1, bias=True) )
代码
文本
[7]
# 依然使用之前的数据集
# 生成随机输入数据,维度为input_size
x2 = torch.randn(3)
# 前向传播,最终输出维度为output_size
output2 = model_seq(x2)
print("模型输出:", output2)
print(output2.shape) # 结果:torch.Size([2])
模型输出: tensor([-0.0187], grad_fn=<AddBackward0>) torch.Size([1])
代码
文本
3.3.7 数据集构建与加载
代码
文本
3.3.7.1 使用Dataset类自定义数据集
代码
文本
[8]
import torch
from torch.utils.data import Dataset
import numpy as np
# 定义一个自定义数据集类,继承自 torch.utils.data.Dataset
class MyDataset(Dataset):
def __init__(self, data, labels): # 初始化数据集
self.data = data
self.labels = labels
def __len__(self): # 返回数据集样本总数
return len(self.data)
def __getitem__(self, idx): # 根据索引返回对应数据和标签
sample = self.data[idx]
label = self.labels[idx]
return sample, label
代码
文本
[9]
# 构造100个样本,每个样本3个特征
data = np.random.randn(100, 3).astype(np.float32)
# 构造对应的结果,假设结果就是简单求和
labels = data.sum(axis = -1) + 2
# 将 NumPy 数组转换为 PyTorch 的 Tensor
data_tensor = torch.tensor(data)
labels_tensor = torch.tensor(labels)
# 创建数据集实例
dataset = MyDataset(data_tensor, labels_tensor)
print("数据集样本数:", len(dataset))
# 查看某具体样本
tmpData, tmpLabel = dataset[0]
print("第一个样本的数据是:" + str(tmpData))
print("第一个样本的标签是:" + str(tmpLabel))
数据集样本数: 100 第一个样本的数据是:tensor([-1.1504, -1.6199, -0.2337]) 第一个样本的标签是:tensor(-1.0040)
代码
文本
3.3.7.2 使用DataLoader类进行数据加载
代码
文本
[10]
from torch.utils.data import DataLoader
# 创建 DataLoader 对象,设置每个批次加载32个样本,并在每个 epoch 时打乱数据
dataloader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=0)
# 遍历 DataLoader,获取每个批次的数据和标签
for batch_idx, (batch_data, batch_labels) in enumerate(dataloader):
print(f"批次 {batch_idx}:")
print("数据尺寸:", batch_data.size())
print("标签尺寸:", batch_labels.size())
# 在这里可以进一步处理 batch_data 和 batch_labels,如送入模型训练
批次 0: 数据尺寸: torch.Size([32, 3]) 标签尺寸: torch.Size([32]) 批次 1: 数据尺寸: torch.Size([32, 3]) 标签尺寸: torch.Size([32]) 批次 2: 数据尺寸: torch.Size([32, 3]) 标签尺寸: torch.Size([32]) 批次 3: 数据尺寸: torch.Size([4, 3]) 标签尺寸: torch.Size([4])
代码
文本
3.3.8 训练网络
代码
文本
3.3.8.1 选择损失函数
代码
文本
[11]
criterion = nn.MSELoss()
代码
文本
3.3.8.2 选择优化器
代码
文本
[12]
import torch.optim as optim
# 选择 SGD 优化器,模型参数由 model.parameters() 返回
optimizer = optim.SGD(model.parameters(), lr=0.01)
代码
文本
3.3.8.3 训练网络
代码
文本
[13]
num_epochs = 100 # 训练的总 epoch 数
loss_list = []
for epoch in range(num_epochs):
running_loss = 0.0 # 用于累计本 epoch 的总损失
# 遍历每个批次
for batch_idx, (inputs, labels) in enumerate(dataloader):
# 前向传播:计算预测输出
outputs = model(inputs).squeeze(-1) # 保证输出和标签形状一致
# 计算当前批次的损失
loss = criterion(outputs, labels)
# 在反向传播前清零梯度,防止梯度累加
optimizer.zero_grad()
# 反向传播:自动计算梯度
loss.backward()
# 更新参数:依据梯度信息调整模型参数
optimizer.step()
# 累计当前批次损失
running_loss += loss.item()
# 计算本 epoch 的平均损失
avg_loss = running_loss / len(dataloader)
loss_list.append(avg_loss)
print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}")
Epoch [1/100], Loss: 5.7042 Epoch [2/100], Loss: 4.5726 Epoch [3/100], Loss: 4.1831 Epoch [4/100], Loss: 5.9128 Epoch [5/100], Loss: 3.3498 Epoch [6/100], Loss: 3.8564 Epoch [7/100], Loss: 2.7457 Epoch [8/100], Loss: 1.8149 Epoch [9/100], Loss: 2.0803 Epoch [10/100], Loss: 1.4319 Epoch [11/100], Loss: 1.4462 Epoch [12/100], Loss: 1.0616 Epoch [13/100], Loss: 0.8244 Epoch [14/100], Loss: 1.0793 Epoch [15/100], Loss: 0.8297 Epoch [16/100], Loss: 0.5428 Epoch [17/100], Loss: 0.5329 Epoch [18/100], Loss: 0.4181 Epoch [19/100], Loss: 0.4500 Epoch [20/100], Loss: 0.3665 Epoch [21/100], Loss: 0.2837 Epoch [22/100], Loss: 0.5459 Epoch [23/100], Loss: 0.2329 Epoch [24/100], Loss: 0.2378 Epoch [25/100], Loss: 0.3651 Epoch [26/100], Loss: 0.2033 Epoch [27/100], Loss: 0.1914 Epoch [28/100], Loss: 0.1758 Epoch [29/100], Loss: 0.3979 Epoch [30/100], Loss: 0.1552 Epoch [31/100], Loss: 0.1546 Epoch [32/100], Loss: 0.1760 Epoch [33/100], Loss: 0.1655 Epoch [34/100], Loss: 0.3349 Epoch [35/100], Loss: 0.2340 Epoch [36/100], Loss: 0.3066 Epoch [37/100], Loss: 0.1282 Epoch [38/100], Loss: 0.1079 Epoch [39/100], Loss: 0.1200 Epoch [40/100], Loss: 0.1229 Epoch [41/100], Loss: 0.1081 Epoch [42/100], Loss: 0.1056 Epoch [43/100], Loss: 0.1132 Epoch [44/100], Loss: 0.2413 Epoch [45/100], Loss: 0.1003 Epoch [46/100], Loss: 0.1002 Epoch [47/100], Loss: 0.0973 Epoch [48/100], Loss: 0.1034 Epoch [49/100], Loss: 0.0914 Epoch [50/100], Loss: 0.0936 Epoch [51/100], Loss: 0.0830 Epoch [52/100], Loss: 0.0826 Epoch [53/100], Loss: 0.0840 Epoch [54/100], Loss: 0.1883 Epoch [55/100], Loss: 0.0731 Epoch [56/100], Loss: 0.0716 Epoch [57/100], Loss: 0.0685 Epoch [58/100], Loss: 0.0736 Epoch [59/100], Loss: 0.0728 Epoch [60/100], Loss: 0.0690 Epoch [61/100], Loss: 0.1696 Epoch [62/100], Loss: 0.0679 Epoch [63/100], Loss: 0.0745 Epoch [64/100], Loss: 0.0724 Epoch [65/100], Loss: 0.0613 Epoch [66/100], Loss: 0.1108 Epoch [67/100], Loss: 0.0577 Epoch [68/100], Loss: 0.0571 Epoch [69/100], Loss: 0.0603 Epoch [70/100], Loss: 0.0584 Epoch [71/100], Loss: 0.0582 Epoch [72/100], Loss: 0.0568 Epoch [73/100], Loss: 0.0643 Epoch [74/100], Loss: 0.1383 Epoch [75/100], Loss: 0.0612 Epoch [76/100], Loss: 0.0554 Epoch [77/100], Loss: 0.0517 Epoch [78/100], Loss: 0.0604 Epoch [79/100], Loss: 0.0519 Epoch [80/100], Loss: 0.0514 Epoch [81/100], Loss: 0.0554 Epoch [82/100], Loss: 0.0494 Epoch [83/100], Loss: 0.0523 Epoch [84/100], Loss: 0.0578 Epoch [85/100], Loss: 0.0775 Epoch [86/100], Loss: 0.0521 Epoch [87/100], Loss: 0.0483 Epoch [88/100], Loss: 0.0800 Epoch [89/100], Loss: 0.0460 Epoch [90/100], Loss: 0.1395 Epoch [91/100], Loss: 0.0470 Epoch [92/100], Loss: 0.0625 Epoch [93/100], Loss: 0.0492 Epoch [94/100], Loss: 0.0525 Epoch [95/100], Loss: 0.0433 Epoch [96/100], Loss: 0.0655 Epoch [97/100], Loss: 0.0677 Epoch [98/100], Loss: 0.0416 Epoch [99/100], Loss: 0.0688 Epoch [100/100], Loss: 0.0591
代码
文本
[21]
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 6))
plt.plot(loss_list, label='Training Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Loss Curve During Training')
plt.legend()
plt.grid('True')
plt.show()
代码
文本
3.3.9 使用GPU
代码
文本
[15]
# 检查是否有可用的 GPU
if torch.cuda.is_available():
device = torch.device("cuda")
print("GPU 可用,使用 GPU 进行训练。")
else:
device = torch.device("cpu")
print("GPU 不可用,使用 CPU 进行训练。")
GPU 不可用,使用 CPU 进行训练。
代码
文本
[16]
# 将模型移动到指定设备上(通常是 GPU)
model = model.to(device)
代码
文本
[17]
num_epochs = 20 # 训练的总 epoch 数
for epoch in range(num_epochs):
running_loss = 0.0 # 用于累计本 epoch 的总损失
# 遍历每个批次
for batch_idx, (inputs, labels) in enumerate(dataloader):
# 将数据移动到GPU
inputs = inputs.to(device)
labels = labels.to(device)
# 前向传播:计算预测输出
outputs = model(inputs).squeeze(-1) # 保证输出和标签形状一致
# 计算当前批次的损失
loss = criterion(outputs, labels)
# 在反向传播前清零梯度,防止梯度累加
optimizer.zero_grad()
# 反向传播:自动计算梯度
loss.backward()
# 更新参数:依据梯度信息调整模型参数
optimizer.step()
# 累计当前批次损失
running_loss += loss.item()
# 计算本 epoch 的平均损失
avg_loss = running_loss / len(dataloader)
print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}")
Epoch [1/20], Loss: 0.0437 Epoch [2/20], Loss: 0.0416 Epoch [3/20], Loss: 0.0463 Epoch [4/20], Loss: 0.0407 Epoch [5/20], Loss: 0.0385 Epoch [6/20], Loss: 0.0390 Epoch [7/20], Loss: 0.0387 Epoch [8/20], Loss: 0.0392 Epoch [9/20], Loss: 0.0385 Epoch [10/20], Loss: 0.0551 Epoch [11/20], Loss: 0.0407 Epoch [12/20], Loss: 0.0406 Epoch [13/20], Loss: 0.0406 Epoch [14/20], Loss: 0.0357 Epoch [15/20], Loss: 0.0494 Epoch [16/20], Loss: 0.0391 Epoch [17/20], Loss: 0.0405 Epoch [18/20], Loss: 0.0355 Epoch [19/20], Loss: 0.0367 Epoch [20/20], Loss: 0.0365
代码
文本
已赞1
本文被以下合集收录
机器学习辅助材料设计教材

爱学习的王一博

更新于 2025-02-16
1 篇0 人关注