赞
踩
欢迎关注 “小白玩转Python”,发现更多 “有趣”
引言
本文提供了一个使用PyTorch构建一个非常基本的 Logistic模型的简单步骤,并将其应用于猴子图像的分类。
首先我们可以从下面的网址下载用于模型训练和测试的数据集:
https://www.kaggle.com/slothkong/10-monkey-species
这个数据集包含了10种猴子的图片,包括:
n0 — alouattapalliata
n1 — erythrocebuspatas
n2 — cacajaocalvus
n3 — macacafuscata
n4 — cebuellapygmea
n5 — cebuscapucinus
n6 — micoargentatus
n7 — saimirisciureus
n8 — aotusnigriceps
n9 — trachypithecusjohnii
在数据集中有两个文件: 训练文件和验证文件。训练和验证文件都包含10个标记为 n0-n9的子文件夹,如上所述,它们各代表一种猴子。每个猴子的图像至少是400x300像素。训练文件中可用的总图像为1096,验证文件夹中可用的总图像为272个图像。训练图像将用于训练和验证模型,而验证图像将用作测试图像,以报告模型的最终准确性。
第一步: 加载和查看数据
构建任何机器学习模型的第一步是理解基础数据。让我们首先读取图像数据,查看其中的一些图像,并将图像数据转换为张量。
导入相关库:
- # Import relevant libraries
-
-
- import torch
- import jovian
- import torchvision
- import torchvision.transforms as transforms
- import torch.nn as nn
- import pandas as pd
- import numpy as np
- import matplotlib
- import matplotlib.pyplot as plt
- import seaborn as sns
- import torch.nn.functional as F
- from torchvision.datasets.utils import download_url
- from torch.utils.data import DataLoader, TensorDataset, random_split
-
-
- from PIL import Image
- import glob

设置超参数:
- # Hyperparameters
- batch_size = 16
- learning_rate = 1e-3
-
-
- jovian.reset()
- jovian.log_hyperparams(batch_size=batch_size, learning_rate=learning_rate)
载入图像(包括训练图像和测试图像)并将图像转换为 float32类型的张量:
- # Load image and convert image to multidimensional array
- def image_to_array(images_folder):
- dataset = []
- for i in range(10):
- for filename in glob.glob(images_folder + "/n{}/*.jpg".format(i)):
- im = Image.open(filename)
- im = im.resize((400,300))
- pixels = np.asarray(im).astype('float32')
- pixels /= 255.0
- pixels = torch.from_numpy(pixels)
- dataset.append((pixels, i))
- return dataset
- # Load Training Data
- train_dataset = image_to_array("monkey_species/training/training")
-
-
- # Load Test Data
- test_dataset = image_to_array("monkey_species/validation/validation")
查看示例图片:
- # View a sample Image
- img_tensor, label = train_dataset[0]
- print(img_tensor.shape)
-
-
- plt.imshow(img_tensor)
- print('Label:', label)
第二步:为训练准备数据
上面已经将图像数据转换为张量,我们可以开始准备用于模型训练,验证和测试的数据了。
训练数据——将用于训练模型(通过计算交叉熵损失和使用梯度下降法调整模型的权重)。
验证数据——将用于在训练时评估模型,并调整超参数(学习率和批量大小)。
测试数据——将用于计算模型的准确度。
从训练数据集创建验证集(20%的训练数据将用于验证)。同时生成批量的训练、验证和测试数据:
- # Training and Validation dataset
- val_size = round(0.2*len(train_dataset))
- train_size = len(train_dataset) - val_size
- train_ds, val_ds = random_split(train_dataset, [train_size, val_size])
-
-
- # Dataloaders
- train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True)
- val_loader = DataLoader(val_ds, batch_size=batch_size)
- test_loader = DataLoader(test_dataset, batch_size=batch_size)
- # Verify batch
- for xb, yb in train_loader:
- print("inputs:", xb)
- print("targets:", yb)
- break
第三步:训练模型
现在我们已经为训练、验证和测试准备好了数据。我们可以使用训练数据集开始训练模型,并使用验证集对其进行验证。
为了进行训练,让我们创建一个自定义模型类和一些实用程序函数,如下所示:
- input_size = 300*400*3
- num_classes = len(label_dict)
- print("Input Size: ", input_size, "\nNumber of Classes: ", num_classes)
- class MonkeyClassificationModel(nn.Module):
- def __init__(self):
- super().__init__()
- self.linear = nn.Linear(input_size, num_classes)
-
- def forward(self, xb):
- xb = xb.reshape(-1, input_size)
- out = self.linear(xb)
- return out
-
- def training_step(self, batch):
- images, labels = batch
- out = self(images) # Generate predictions
- loss = F.cross_entropy(out, labels) # Calculate loss
- return loss
-
- def validation_step(self, batch):
- images, labels = batch
- out = self(images) # Generate predictions
- loss = F.cross_entropy(out, labels) # Calculate loss
- acc = accuracy(out, labels) # Calculate accuracy
- return {'val_loss': loss.detach(), 'val_acc': acc.detach()}
-
- def validation_epoch_end(self, outputs):
- batch_losses = [x['val_loss'] for x in outputs]
- epoch_loss = torch.stack(batch_losses).mean() # Combine losses
- batch_accs = [x['val_acc'] for x in outputs]
- epoch_acc = torch.stack(batch_accs).mean() # Combine accuracies
- return {'val_loss': epoch_loss.item(), 'val_acc': epoch_acc.item()}
-
- def epoch_end(self, epoch, result):
- print("Epoch [{}], val_loss: {:.4f}, val_acc: {:.4f}".format(epoch, result['val_loss'], result['val_acc']))
-
- model = MonkeyClassificationModel()
- list(model.parameters())

- def accuracy(outputs, labels):
- _, preds = torch.max(outputs, dim=1)
- return torch.tensor(torch.sum(preds == labels).item() / len(preds))
-
-
- def evaluate(model, val_loader):
- outputs = [model.validation_step(batch) for batch in val_loader]
- return model.validation_epoch_end(outputs)
-
-
- def fit(epochs, lr, model, train_loader, val_loader, opt_func=torch.optim.SGD):
- history = []
- optimizer = opt_func(model.parameters(), lr)
- for epoch in range(epochs):
- # Training Phase
- for batch in train_loader:
- loss = model.training_step(batch)
- loss.backward()
- optimizer.step()
- optimizer.zero_grad()
- # Validation phase
- result = evaluate(model, val_loader)
- model.epoch_end(epoch, result)
- history.append(result)
- return history

- history1 = fit(100, learning_rate, model, train_loader, val_loader)
- history2 = fit(100, learning_rate/10, model, train_loader, val_loader)
- history3 = fit(100, learning_rate/10, model, train_loader, val_loader)
- history4 = fit(100, learning_rate/100, model, train_loader, val_loader)
- history5 = fit(100, learning_rate/1000, model, train_loader, val_loader)
-
-
- history = history1 + history2 + history3 + history4 + history5
-
-
- accuracies = [r['val_acc'] for r in history]
- plt.plot(accuracies, '-x')
- plt.xlabel('epoch')
- plt.ylabel('accuracy')
- plt.title('Accuracy vs. No. of epochs')
- # Evaluate on test dataset
- result = evaluate(model, test_loader)
- result
第四步: 使用训练后的模型进行预测
模型经过训练后,我们可以使用该模型来预测,即对测试图像进行分类。让我们定义一个分类图片的函数:
- def predict_image(input_img, model):
- inputs = input_img.unsqueeze(0)
- predictions = model(inputs)
- _, preds = torch.max(predictions, dim=1)
- return preds[0].item()
- label_dict = {0:"alouattapalliata", 1:"erythrocebuspatas", 2:"cacajaocalvus", 3:"macacafuscata",
- 4:"cebuellapygmea", 5:"cebuscapucinus", 6:"micoargentatus", 7:"saimirisciureus",
- 8:"aotusnigriceps", 9:"trachypithecusjohnii"}
部分测试结果如下:
预测正确
预测错误
保存模型:
- # Save
- torch.save(model.state_dict(), 'monkey_classification.pth')
模型精度及提高精度的思路
使用测试数据集计算模型的准确率约为56.6%。使用这个相当简单的 Logistic模型模型得到的准确度很差。因此,对于这个特定的数据集,需要考虑一个更复杂的机器学习或者深度学习模型。相信使用卷积神经网络(CNN)或深层神经网络(DNN)可以获得更好的分类精度。
可以通过以下策略进一步提高模型的准确性:
1. 增加数据
2. 使用CNN模型
3. 更改优化函数
结束语
尽管 Logistic模型的准确性很差,但本篇文章展示了如何使用 PyTorch 构建一个简单的 Logistic模型。类似的步骤可以应用于任何简单的线性分类问题。
· END ·
HAPPY LIFE
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。