digit = train_loader.dataset.train_data[0]
在这段代码中,train_loader
是一个数据加载器对象,train_loader.dataset
是该加载器对应的数据集对象。train_data
是数据集对象中的一个属性,它代表训练数据。
train_loader.dataset.train_data[0]
表示访问训练数据集中的第一个样本。这里假设 train_data
是一个包含训练数据的数组或张量对象。
通过这行代码,将训练数据集中的第一个样本赋值给变量 digit
。你可以在后续的代码中使用 digit
来处理或分析该样本的数据。
请同学们尝试修改以下代码,如修改网络结构、优化器、损失函数、学习率等,提升模型评估准确率,要求精度达到0.985。 In [2] # 定义模型结构 import paddle.nn.functional as F from paddle.nn import Conv2D, MaxPool2D, Linear # 多层卷积神经网络实现(可修改,例如加深网络层级) class MNIST(paddle.nn.Layer): def init(self): super(MNIST, self).init() #
修改后的代码
import paddle.nn.functional as F import paddle.nn as nn from paddle.nn import Conv2D, MaxPool2D, Linear
class MNIST(paddle.nn.Layer): def init(self): super(MNIST, self).init() self.conv1 = Conv2D(in_channels=1, out_channels=32, kernel_size=3, stride=1) self.max_pool1 = MaxPool2D(kernel_size=2, stride=2) self.conv2 = Conv2D(in_channels=32, out_channels=64, kernel_size=3, stride=1) self.max_pool2 = MaxPool2D(kernel_size=2, stride=2) self.fc1 = Linear(in_features=6455, out_features=512) self.fc2 = Linear(in_features=512, out_features=10)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.max_pool1(x)
x = self.conv2(x)
x = F.relu(x)
x = self.max_pool2(x)
x = paddle.flatten(x, start_axis=1, stop_axis=-1)
x = self.fc1(x)
x = F.relu(x)
x = F.dropout(x, p=0.5)
x = self.fc2(x)
return x
定义训练函数
def train(model): model.train() epoch_loss = 0 for batch_id, data in enumerate(train_loader()): x_data = data[0] y_data = data[1] predicts = model(x_data) loss = F.cross_entropy(predicts, y_data) loss.backward() optimizer.step() optimizer.clear_grad() epoch_loss += loss.numpy()[0] return epoch_loss / len(train_loader())
定义测试函数
def test(model): model.eval() accuracies = [] for batch_id, data in enumerate(test_loader()): x_data = data[0] y_data = data[1] predicts = model(x_data) acc = paddle.metric.accuracy(predicts, y_data) accuracies.append(acc.numpy()[0]) return np.mean(accuracies)
定义优化器
optimizer = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
训练模型
EPOCH_NUM = 20 model = MNIST() train_loader = paddle.batch(paddle.dataset.mnist.train(), batch_size=64, drop_last=True) test_loader = paddle.batch(paddle.dataset.mnist.test(), batch_size=64, drop_last=True) for epoch_id in range(EPOCH_NUM): train_loss = train(model) test_acc = test(model) print("epoch_id: {}, train_loss: {}, test_acc: {}".format(epoch_id+1, train_loss, test_acc))
测试模型
acc = test(model) print("Final test acc: {}".format(acc))
预测样例
params_file_path = 'mnist.pdparams' model_dict = paddle.load(params_file_path) model.load_dict(model_dict) model.eval()
data = paddle.dataset.mnist.test()[0][0] label = paddle.dataset.mnist.test()[0][1] result = model(paddle.to_tensor(data)) print("Predict digit {}, label is {}".format(np.argmax(result.numpy()), label))
python实现1.将手写体图像数据集进行切割,然后按照数字进行分类,构建手写体数字的分类数据集。 阿拉伯数字和中文数字分别建立独立的数据集。 2.以人为单位,当70%同学的手写体数字作为训练集,剩余30%同学的作为测试集。 3.构建Pytorch的数据加载器,进行Batch方式的数据生成。
- 实现手写体图像数据集切割、分类
下面是一个简单的 Python 实现,可以将手写数字图像数据集按照数字进行分类,并保存到相应的文件夹中:
import os
import shutil
from PIL import Image
data_dir = '/path/to/handwritten_digits_dataset'
output_dir = '/path/to/classified_dataset'
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for filename in os.listdir(data_dir):
if filename.endswith('.png'):
img = Image.open(os.path.join(data_dir, filename))
digit = filename.split('.')[0][-1] # 获取图像文件名中的数字
if digit.isdigit():
output_subdir = os.path.join(output_dir, digit)
if not os.path.exists(output_subdir):
os.makedirs(output_subdir)
output_path = os.path.join(output_subdir, filename)
shutil.copyfile(os.path.join(data_dir, filename), output_path)
- 划分训练集和测试集
下面是一个简单的 Python 实现,可以将手写数字数据集划分为训练集和测试集,比例为 7:3:
import os
import random
import shutil
data_dir = '/path/to/classified_dataset'
train_dir = '/path/to/train_dataset'
test_dir = '/path/to/test_dataset'
if not os.path.exists(train_dir):
os.makedirs(train_dir)
if not os.path.exists(test_dir):
os.makedirs(test_dir)
for digit_dir in os.listdir(data_dir):
digit_path = os.path.join(data_dir, digit_dir)
digit_files = os.listdir(digit_path)
random.shuffle(digit_files)
num_train = int(len(digit_files) * 0.7)
train_files = digit_files[:num_train]
test_files = digit_files[num_train:]
for filename in train_files:
input_path = os.path.join(digit_path, filename)
output_path = os.path.join(train_dir, filename)
shutil.copyfile(input_path, output_path)
for filename in test_files:
input_path = os.path.join(digit_path, filename)
output_path = os.path.join(test_dir, filename)
shutil.copyfile(input_path, output_path)
- 构建 Pytorch 数据加载器
下面是一个简单的 Pytorch 数据加载器实现,可以对手写数字训练集和测试集进行 Batch 方式的数据生成:
import os
from PIL import Image
import torch
from torch.utils.data import Dataset, DataLoader
class HandwrittenDigitsDataset(Dataset):
def __init__(self, data_dir):
self.data_dir = data_dir
self.digit_filenames = []
for digit_dir in os.listdir(data_dir):
digit_path = os.path.join(data_dir, digit_dir)
digit_filenames = os.listdir(digit_path)
self.digit_filenames += [(os.path.join(digit_path, filename), int(digit_dir)) for filename in digit_filenames]
def __len__(self):
return len(self.digit_filenames)
def __getitem__(self, index):
filename, digit = self.digit_filenames[index]
img = Image.open(filename)
img = img.convert('L') # 转换为灰度图像
img = img.resize((28, 28)) # 调整图像大小
img = torch.tensor(img, dtype=torch.float32).unsqueeze(0) / 255.0 # 转换为张量,并进行归一化
return img, digit
train_dataset = HandwrittenDigitsDataset('/path/to/train_dataset')
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_dataset = HandwrittenDigitsDataset('/path/to/test_dataset')
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
这里的 HandwrittenDigitsDataset
类实现了 Pytorch 的 Dataset
接口,可以在 Pytorch 的数据加载器中使用。在 __init__
方法中,我们遍历了训练集或测试集文件夹中的所有文件,并保存了文件路径和对应的数字标签。在 __getitem__
方法中,我们读取了图像文件,并将其转换为灰度图像、调整大小、转换为张量、进行归一化等操作。在数据加载器中,我们可以指定每个 Batch 的大小、是否随机打乱数据等参数。