Compare commits

...
4 Commits
Author SHA1 Message Date
wonder b92b867583 📝Docs: [Lab-2] Completed 2025-11-02 19:57:12 +08:00
wonder 9b90328262 🔄Update: [Lab-2] 模型训练与测试 2025-11-02 19:55:20 +08:00
wonder 1b58da9a47 🔄Update: [Lab-2] 数据处理变换 2025-11-02 19:44:48 +08:00
wonder d9d2293999 🔄Update: [Lab-2] 数据装载 2025-11-02 19:37:12 +08:00
5 changed files with 295 additions and 1 deletions
View File
+67
View File
@@ -0,0 +1,67 @@
import torch
import torchvision
import matplotlib.pyplot as plt
from torchvision import transforms
from torch.utils.data import random_split, DataLoader
def load_and_preview_mnist(data_size=100, batch_size=16, seed=42, root='../data'):
"""
加载并预览 MNIST 数据集。
Parameters:
- data_size (int): 加载的数据条目数。
- batch_size (int): 每批次处理的数据数量。
- seed (int): 随机种子,用于保证数据切割的可重复性。
- root (str): 数据集保存的路径。
"""
# 数据预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
# 载入数据集
train_dataset = torchvision.datasets.MNIST(
root=root,
train=True,
download=True,
transform=transform
)
# 截取指定数量的数据
data_train, _ = random_split(
dataset=train_dataset,
lengths=[data_size, len(train_dataset) - data_size],
generator=torch.Generator().manual_seed(seed)
)
# 加载数据集
train_loader = DataLoader(
dataset=data_train,
batch_size=batch_size,
shuffle=True
)
# 数据预览
images, labels = next(iter(train_loader))
# 将图像拼接为网格
img_grid = torchvision.utils.make_grid(images, nrow=batch_size // 4)
img = img_grid.numpy().transpose(1, 2, 0)
std = [0.5]
mean = [0.5]
img = img * std + mean
# 显示图像
print([labels[i] for i in range(batch_size)])
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.show()
if __name__ == '__main__':
# 使用默认参数调用函数
load_and_preview_mnist()
# 或者使用自定义参数
# load_and_preview_mnist(data_size=200, batch_size=8, seed=123, root='./data')
+89
View File
@@ -0,0 +1,89 @@
import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader, random_split
def get_transform():
"""
返回 torchvision.transforms.Compose 对象,包含数据预处理变换操作。
Returns:
- transform (torchvision.transforms.Compose): 包含数据预处理变换的 Compose 对象。
"""
return transforms.Compose([
transforms.ToTensor(), # 将输入数据类型转换为 Tensor
transforms.Normalize((0.5,), (0.5,)) # 对数据进行标准化处理,均值和标准差均为 0.5
])
def load_mnist(data_size=100, batch_size=16, seed=42, root='../data', train=True):
"""
加载 MNIST 数据集。
Parameters:
- data_size (int): 加载的数据条目数。
- batch_size (int): 每批次处理的数据数量。
- seed (int): 随机种子,用于保证数据切割的可重复性。
- root (str): 数据集保存的路径。
- train (bool): 是否加载训练集。
Returns:
- DataLoader: 数据加载器。
"""
transform = get_transform()
dataset = torchvision.datasets.MNIST(
root=root,
train=train,
download=True,
transform=transform
)
data_subset, _ = random_split(
dataset=dataset,
lengths=[data_size, len(dataset) - data_size],
generator=torch.Generator().manual_seed(seed)
)
data_loader = DataLoader(
dataset=data_subset,
batch_size=batch_size,
shuffle=True
)
return data_loader
def load_and_preview_mnist(data_size=100, batch_size=16, seed=42, root='../data'):
"""
加载并预览 MNIST 数据集。
Parameters:
- data_size (int): 加载的数据条目数。
- batch_size (int): 每批次处理的数据数量。
- seed (int): 随机种子,用于保证数据切割的可重复性。
- root (str): 数据集保存的路径。
"""
train_loader = load_mnist(data_size=data_size, batch_size=batch_size, seed=seed, root=root, train=True)
images, labels = next(iter(train_loader))
img_grid = torchvision.utils.make_grid(images, nrow=batch_size // 4)
img = img_grid.numpy().transpose(1, 2, 0)
mean = [0.5]
std = [0.5]
img = img * std + mean
print([labels[i] for i in range(batch_size)])
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.show()
if __name__ == '__main__':
load_and_preview_mnist()
# Or use custom parameters:
# load_and_preview_mnist(data_size=200, batch_size=8, seed=123, root='./data')
+116
View File
@@ -0,0 +1,116 @@
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from data_transform import load_mnist, load_and_preview_mnist
import matplotlib.pyplot as plt
import torchvision.utils as vutils
# 定义卷积神经网络模型
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv1 = nn.Sequential(
nn.Conv2d(1, 64, kernel_size=3, stride=2, padding=1),
nn.ReLU(),
nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1),
nn.ReLU(),
# nn.MaxPool2d(stride=2, kernel_size=2)
)
self.dense = nn.Sequential(
nn.Linear(7 * 7 * 128, 512),
nn.ReLU(),
nn.Dropout(p=0.8),
nn.Linear(512, 10)
)
def forward(self, x):
x = self.conv1(x) # 卷积处理
x = x.view(-1, 7 * 7 * 128) # 对参数实行扁平化处理
x = self.dense(x)
return x
# 加载和预览数据集
def main():
# 参数设置
data_size = 1000
batch_size = 4
seed = 42
root = '../data'
epochs_n = 5
learning_rate = 0.001
# 加载数据加载器
train_loader = load_mnist(data_size=data_size, batch_size=batch_size, seed=seed, root=root, train=True)
test_loader = load_mnist(data_size=data_size, batch_size=batch_size, seed=seed, root=root, train=False)
# 预览数据集(可选)
load_and_preview_mnist(data_size=data_size, batch_size=batch_size, seed=seed, root=root)
# 初始化模型
model = Model()
cost = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# 训练模型
for epoch in range(epochs_n):
model.train()
running_loss = 0.0
running_correct = 0
print(f"Epoch {epoch + 1}/{epochs_n}")
print("-" * 10)
for data in train_loader:
images, labels = data
optimizer.zero_grad()
outputs = model(images)
_, preds = torch.max(outputs.data, 1)
loss = cost(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
running_correct += (preds == labels).sum().item()
epoch_loss = running_loss / len(train_loader.dataset)
epoch_acc = 100 * running_correct / len(train_loader.dataset)
print(f"Loss: {epoch_loss:.4f}, Train Accuracy: {epoch_acc:.4f}%")
# 测试模型
model.eval()
testing_correct = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
outputs = model(images)
_, preds = torch.max(outputs.data, 1)
testing_correct += (preds == labels).sum().item()
test_acc = 100 * testing_correct / len(test_loader.dataset)
print(f"Test Accuracy: {test_acc:.4f}%")
# 测试数据可视化
X_test, y_test = next(iter(test_loader))
with torch.no_grad():
pred = model(X_test)
_, predicted_labels = torch.max(pred, 1)
print("Predicted Labels:", [i.item() for i in predicted_labels])
print("True Labels:", [i.item() for i in y_test])
# 显示图像
img_grid = vutils.make_grid(X_test, nrow=batch_size // 4)
img = img_grid.numpy().transpose(1, 2, 0)
mean = [0.5]
std = [0.5]
img = img * std + mean
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.show()
if __name__ == '__main__':
main()
+23 -1
View File
@@ -22,4 +22,26 @@
### RGB三通道分离并显示。
`Lab-1/src/rgb_img.py`
`Lab-1/src/rgb_img.py`
## 基于PyTorch的Minist数据集分类
### 数据预览测试和数据装载;
`Lab-2/src/data_load.py`
### 进行数据处理变换操作;
`Lab-2/src/data_transform.py`
### 模型搭建和参数优化;
`Lab-2/src/model_training.py`
### 基于pytorch卷积神经网络的模型训练;
`Lab-2/src/model_training.py`
### 基于pytorch卷积神经网络的模型测试。
`Lab-2/src/model_training.py`