1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| import os import pandas as pd import numpy as np from PIL import Image import torch from torch.utils.data import Dataset from torchvision import transforms import torch.nn as nn
class MnistDataset(Dataset): def __init__(self, image_path, image_label, transform=None): super(MnistDataset, self).__init__() self.image_path = image_path self.image_label = image_label self.transform = transform
def __getitem__(self, index): """ 获取对应index的图像,并视情况进行数据增强 """ image = Image.open(self.image_path[index]) image = np.array(image) label = int(self.image_label[index])
if self.transform is not None: image = self.transform(image)
return image, torch.tensor(label)
def __len__(self): return len(self.image_path)
def get_path_label(img_root, label_file_path): """ 获取数字图像的路径和标签并返回对应列表 @para: img_root: 保存图像的根目录 @para:label_file_path: 保存图像标签数据的文件路径 .csv 或 .txt 分隔符为',' @return: 图像的路径列表和对应标签列表 """ data = pd.read_csv(label_file_path, names=["img", "label"]) data["img"] = data["img"].apply(lambda x: img_root + x) return data["img"].tolist(), data["label"].tolist()
dir_path = os.path.dirname(__file__) train_data_root = dir_path + "/mnist_data/train/" train_label = dir_path + "/mnist_data/train.txt" train_img_list, train_label_list = get_path_label(train_data_root, train_label)
train_dataset = MnistDataset( train_img_list, train_label_list, transform=transforms.Compose([transforms.ToTensor()]), )
test_data_root = dir_path + "/mnist_data/test/" test_label = dir_path + "/mnist_data/test.txt" test_img_list, test_label_list = get_path_label(test_data_root, test_label)
test_dataset = MnistDataset( test_img_list, test_label_list, transform=transforms.Compose([transforms.ToTensor()]), )
num_epochs = 5 num_classes = 10 batch_size = 10 learning_rate = 0.001
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 )
class ConvNet(nn.Module): def __init__(self, num_classes=10): super(ConvNet, self).__init__() self.layer1 = nn.Sequential( nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2), nn.BatchNorm2d(16), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2), ) self.layer2 = nn.Sequential( nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2), nn.BatchNorm2d(32), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2), ) self.fc = nn.Linear(7 * 7 * 32, num_classes)
def forward(self, x): out = self.layer1(x) out = self.layer2(out) out = out.reshape(out.size(0), -1) out = self.fc(out) return out
model = ConvNet(num_classes)
criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
total_step = len(train_loader) for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): images = images labels = labels
outputs = model(images) loss = criterion(outputs, labels)
optimizer.zero_grad() loss.backward() optimizer.step() print( "Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}".format( epoch + 1, num_epochs, i + 1, total_step, loss.item() ) )
|