来自 科技 2020-04-11 16:12 的文章

PyTorch教程:如何使用Python开发深度学习模型(建

深度学习的预测建模是现在的开发人员必须要了解的一项技能。

PyTorch是由Facebook开发和维护的主要的开源深度学习框架。

PyTorch的核心是一个数学库,可让你在基于图形的模型上执行高效的计算和自动微分。直接实现这一点是具有挑战性的,尽管值得庆幸的是,现代的PyTorch API提供了类和习语,使你可以轻松开发一套深度学习模型。

在本教程中,你将找到在PyTorch中开发深度学习模型的分步指南。

完成本教程后,你将知道:

Torch和PyTorch之间的区别以及如何安装和确认PyTorch是否正常工作;PyTorch模型的五步生命周期以及如何定义,拟合和评估模型;如何为回归,分类和预测建模任务开发PyTorch深度学习模型。

让我们开始吧:

PyTorch教程概述

本教程的重点是将PyTorch API用于常见的深度学习模型开发任务。在此,我们不会深入研究深度学习的数学和理论。

学习python深度学习的最好方法是实践,然后不断深入学习。看完本文后,你可以回头了解更多的理论。

我将每个代码示例设计为使用最佳实践,并且是独立的,以便你可以将其直接复制并粘贴到项目中,并使其适应你的特定需要。这将是一个很好的开始,而不是试图从官方文档单独找出API。

这是一个大型教程,因此分为三个部,他们是:

1.如何安装PyTorch?

什么是Torch和PyTorch?如何安装PyTorch?如何确认已安装好的PyTorch?

2.PyTorch深度学习模型生命周期步骤

第一步:准备资料步骤第二步:定义模型步骤第三步:训练模型步骤第四步:评估模型步骤第五步:做出预测

3.如何开发PyTorch深度学习模型?

如何开发用于二进制分类的MLP如何开发用于多类分类的MLP如何为回归开发MLP如何开发用于图像分类的CNN你可以使用Python进行深度学习!

最多需要60分钟,你就能学习完成本教程!

你不需要了解所有内容(至少现在还不了解)。你的目标是端对端地完成本教程并获得结果,你无需在第一遍就了解所有内容。如果你在学习中遇到了很多问题,可以参考官方API​​文档,以了解你需要用到的功能。

你不需要先了解数学。数学是描述算法工作方式的一种紧凑方式,特别是线性代数,概率和微积分的工具。这些并不是你可以用来学习算法工作方式的唯一工具。你还可以使用代码并探索具有不同输入和输出的算法行为。了解数学不会告诉你选择哪种算法或如何对其进行最佳配置。你只能通过精心控制的实验来发现这一点。

你不需知道算法的工作原理。了解限制以及如何配置深度学习算法非常重要。但是学习算法可能会在以后出现。你需要在很长一段时间内慢慢地建立这种算法知识。今天,从熟悉该平台开始。

你不需成为Python程序员。如果你是Python语言的新手,它的语法可能很直观。就像其他语言一样,专注于函数调用(例如function())和赋值(例如a =“ b”)。这将为你提供大部分帮助。你是开发人员,你知道如何快速掌握语言的基础知识。

你不需成为深度学习专家。你可以了解各种算法的优点和局限性,并且可以阅读大量教程来深入学习深度学习项目的步骤。


1.如何安装PyTorch

在本节中,您将发现什么是PyTorch,如何安装以及如何确认PyTorch已正确安装。

1.1.什么是Torch和PyTorch?

PyTorch是由Facebook开发和维护的用于深度学习的开源Python库。

该项目于2016年开始,并迅速成为开发人员和研究人员的流行框架。

Torch(Torch7)是一个用C编写的用于深度学习的开源项目,通常通过Lua界面使用。这是PyTorch的前期项目,不再积极开发。PyTorch 在名称中包含“ Torch ”,以“ Py ”前缀表示先前的炬管库,该前缀表示新项目的Python焦点。

PyTorch API简单灵活,使其成为学者和研究人员在开发新的深度学习模型和应用程序时的最爱。广泛使用已导致针对特定应用程序(例如文本,计算机视觉和音频数据)进行了许多扩展,并且可能预先训练了可直接使用的模型。因此,它可能是学者使用的最受欢迎的库。

PyTorch的灵活性是以易用性为代价,特别是对于初学者来说,相比于诸如简化接口Keras。选择使用PyTorch而不是Keras会放弃一些易用性,更陡峭的学习曲线以及更多的代码以提供更大的灵活性,并且可能会使学术界更加活跃。

1.2.如何安装PyTorch

在安装PyTorch之前,请确保已安装Python,例如Python 3.6或更高版本。

如果你没有安装Python,则可以使用Anaconda安装它。本教程将向你展示如何:

如何使用Anaconda设置Python环境进行机器学习

有很多方法可以安装PyTorch开源深度学习库。

在你的工作站上安装PyTorch的最常见,也许是最简单的方法是使用pip。

例如,在命令行上,你可以输入:

sudo pip install torch

深度学习最流行的应用也许是用于计算机视觉,而PyTorch计算机视觉软件包被称为“ torchvision”。

强烈建议安装torchvision,它可以按以下方式安装:

sudo pip install torchvision

如果您更喜欢使用特定于平台或软件包管理器的安装方法,则可以在下方链接查看安装说明的完整列表:

PyTorch安装指南(https://pytorch.org/get-started/locally/)

现在无需设置GPU。

本教程中的所有示例都可以在现代CPU上正常工作,如果要为GPU配置PyTorch,则可以在完成本教程后进行操作。

1.3.如何确认已安装PyTorch

一旦安装了PyTorch,重要的是确认该库已成功安装并且可以开始使用它。

不要跳过此步骤。

如果未正确安装PyTorch或在此步骤上引发错误,则以后将无法运行示例。

创建一个名为versions.py的新文件,并将以下代码复制并粘贴到该文件中。

# 检查 pytorch 版本
import torch
print(torch.__version__)

保存文件,然后打开命令行并将目录更改为保存文件的位置。

然后输入:

python versions.py

然后,你应该看到如下输出:

1.3.1

这确认PyTorch已正确安装,并且我们都使用相同的版本。

这也向你展示了如何从命令行运行Python脚本,我建议以这种方式从命令行运行所有代码,而不是从笔记本或IDE运行。


2. PyTorch深度学习模型生命周期

在本部分中,你将发现深度学习模型的生命周期以及可用于定义模型的PyTorch API。

模型具有生命周期,这一非常简单的知识为建模数据集和理解PyTorch API提供了基础。

生命周期中的五个步骤如下:

1.准备数据。2.定义模型。3.训练模型。4.评估模型。5.做出预测。

让我们依次仔细研究每个步骤。

注意:这是最简单,最常见或最惯用的方法,此外,还有很多其他方法可以使用PyTorch API来完成每个步骤。

步骤1:准备资料

第一步是加载并准备数据。

神经网络模型需要数字输入数据和数字输出数据。

你可以使用标准的Python库来加载和准备表格数据,例如CSV文件。例如,Pandas可用于加载CSV文件,而scikit-learn的工具可用于编码分类数据,例如类标签。

PyTorch提供了Dataset类,你可以扩展该类并对其进行自定义以加载数据集。

例如,你的数据集对象的构造函数可以加载你的数据文件(例如CSV文件)。然后,你可以覆盖用于获取数据集长度(行或样本数)的__len __()函数,以及用于通过索引获取特定样本的__getitem __()函数。

加载数据集时,你还可以执行任何必需的转换,例如缩放或编码。

下面提供了自定义数据集类的框架。

# dataset definition
class CSVDataset(Dataset):
# load the dataset
def __init__(self, path):
# store the inputs and outputs
self.X = ...
self.y = ...

# number of rows in the dataset
def __len__(self):
return len(self.X)

# get a row at an index
def __getitem__(self, idx):
return [self.X[idx], self.y[idx]]

加载后,PyTorch将提供DataLoader类以在模型的训练和评估期间导航数据集实例。

可以为训练数据集,测试数据集甚至验证数据集创建一个DataLoader实例。

所述random_split()函数可以被用于将数据集分裂成训练集和测试集。拆分后,可以将数据集中的行的选择以及批处理大小以及是否应在每个时期重新整理数据,提供给DataLoader。

例如,我们可以通过传入数据集中行的选定样本来定义DataLoader。

...
# create the dataset
dataset = CSVDataset(...)
# select rows from the dataset
train, test = random_split(dataset, [[...], [...]])
# create a data loader for train and test sets
train_dl = DataLoader(train, batch_size=32, shuffle=True)
test_dl = DataLoader(test, batch_size=1024, shuffle=False)

定义后,就可以枚举DataLoader,每次迭代产生一批样品。

...
# train the model
for i, (inputs, targets) in enumerate(train_dl):
...
步骤2:定义模型

下一步是定义模型。

在PyTorch中定义模型的习惯用法涉及定义扩展Module类的类。

您的类的构造函数定义模型的各层,而forward()函数则是重写,它定义了如何通过模型的已定义各层转发输入。

许多层是可用的,诸如线性为完全连接层,Conv2d卷积层,并且MaxPool2d为汇集层。

激活函数也可以定义为层,例如ReLU,Softmax和Sigmoid。

下面是一个具有一层的简单MLP模型的示例。

# model definition
class MLP(Module):
# define model elements
def __init__(self, n_inputs):
super(MLP, self).__init__()
self.layer = Linear(n_inputs, 1)
self.activation = Sigmoid()

# forward propagate input
def forward(self, X):
X = self.layer(X)
X = self.activation(X)
return X

给定图层的权重也可以在构造函数中定义该图层之后进行初始化。

常见示例包括Xavier和He权重初始化方案。例如:

...
xavier_uniform_(self.layer.weight)
步骤3:训练模型

训练过程要求您定义损失函数和优化算法。

常见的损失函数包括:

BCELoss:二进制分类的二进制交叉熵损失。CrossEntropyLoss:用于多类分类的分类交叉熵损失。MSELoss:回归的均方损失。

有关一般损失函数的更多信息,可通过下方链接查看:

训练深度学习神经网络的损耗函数(https://machinelearningmastery.com/loss-and-loss-functions-for-training-deep-learning-neural-networks/)

随机梯度下降用于优化,标准算法由SGD类提供,尽管该算法的其他版本也可用,例如Adam。

# define the optimization
criterion = MSELoss()
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)

训练模型涉及枚举训练数据集的DataLoader。

首先,需要训练次数的循环。然后,对于微型批次,需要一个内部回路来进行随机梯度下降。

...
# enumerate epochs
for epoch in range(100):
# enumerate mini batches
for i, (inputs, targets) in enumerate(train_dl):
...

对模型的每次更新都涉及相同的常规模式,其中包括:

清除最后的误差梯度。输入通过模型的正向传递。计算模型输出的损失。通过模型反向传播错误。更新模型以减少损失。

例如:

...
# clear the gradients
optimizer.zero_grad()
# compute the model output
yhat = model(inputs)
# calculate loss
loss = criterion(yhat, targets)
# credit assignment
loss.backward()
# update model weights
optimizer.step()
步骤4:评估模型

一旦模型适合,就可以在测试数据集上对其进行评估。

这可以通过将DataLoader用于测试数据集并收集测试集的预测,然后将预测与测试集的期望值进行比较并计算性能指标来实现。

...
for i, (inputs, targets) in enumerate(test_dl):
# evaluate the model on the test set
yhat = model(inputs)
...
步骤5:做出预测

拟合模型可用于对新数据进行预测。

例如,你可能只有一张图像或一行数据,并且想要进行预测。

这要求你将数据包装在PyTorch Tensor数据结构中。

张量只是NumPy数组的PyTorch版本,用于保存数据。它还允许你在模型图中执行自动微分任务,例如在训练模型时调用back()。

预测也将是张量,尽管你可以通过从自动微分图中分离张量并调用NumPy函数来检索NumPy数组。

...
# convert row to data
row = Variable(Tensor([row]).float())
# make prediction
yhat = model(row)
# retrieve numpy array
yhat = yhat.detach().numpy()

既然我们已经从高层次上熟悉了PyTorch API和模型生命周期,那么让我们看一下如何从头开始开发一些标准的深度学习模型。


3.如何开发PyTorch深度学习模型

在本节中,你将发现如何使用标准的深度学习模型(包括多层感知器(MLP)和卷积神经网络(CNN))来开发,评估和做出预测。

多层感知器模型(简称MLP)是标准的全连接神经网络模型。

它由节点层组成,其中每个节点连接到上一层的所有输出,每个节点的输出连接到下一层节点的所有输入。

MLP是具有一个或多个完全连接的层的模型。此模型适用于表格数据,即表格或电子表格中的数据,每个变量一列,每个变量一行。你可能需要使用MLP探索三个预测建模问题:二进制分类、多分类、回归。

让我们针对每种情况在真实数据集上拟合模型。

注意:本节中的模型有效,但未优化,看看是否可以改善他们的表现。

3.1.如何开发用于二进制分类的MLP

我们将使用电离层二进制(两类)分类数据集来演示用于二进制分类的MLP。

该数据集涉及预测大气层中是否存在某种结构或是否具有给定的雷达回波。

数据集将使用Pandas自动下载,更多信息可以通过下方链接查看。

电离层数据集(csv)(https://raw.githubusercontent.com/jbrownlee/Datasets/master/ionosphere.csv);电离层数据集描述(https://raw.githubusercontent.com/jbrownlee/Datasets/master/ionosphere.names)。

我们将使用LabelEncoder将字符串标签编码为整数值0和1。该模型将适合67%的数据,其余的33%将用于评估,请使用train_test_split()函数进行拆分。

将“ relu ”激活与“ He Uniform ”权重初始化一起使用是一个好习惯。在训练深度神经网络模型时,这种组合可以大大克服梯度消失的问题。有关ReLU的更多信息,可通过下方链接查看教程:

整流线性单元(ReLU)的简要介绍(https://machinelearningmastery.com/rectified-linear-activation-function-for-deep-learning-neural-networks/)

该模型预测1类的可能性,并使用S型激活函数。该模型使用随机梯度下降法进行了优化,旨在最大程度地减少二进制交叉熵损失。

下面列出了完整的示例。

# pytorch mlp for binary classification
from numpy import vstack
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch import Tensor
from torch.nn import Linear
from torch.nn import ReLU
from torch.nn import Sigmoid
from torch.nn import Module
from torch.optim import SGD
from torch.nn import BCELoss
from torch.nn.init import kaiming_uniform_
from torch.nn.init import xavier_uniform_

# dataset definition
class CSVDataset(Dataset):
# load the dataset
def __init__(self, path):
# load the csv file as a dataframe
df = read_csv(path, header=None)
# store the inputs and outputs
self.X = df.values[:, :-1]
self.y = df.values[:, -1]
# ensure input data is floats
self.X = self.X.astype('float32')
# label encode target and ensure the values are floats
self.y = LabelEncoder().fit_transform(self.y)
self.y = self.y.astype('float32')
self.y = self.y.reshape((len(self.y), 1))

# number of rows in the dataset
def __len__(self):
return len(self.X)

# get a row at an index
def __getitem__(self, idx):
return [self.X[idx], self.y[idx]]

# get indexes for train and test rows
def get_splits(self, n_test=0.33):
# determine sizes
test_size = round(n_test * len(self.X))
train_size = len(self.X) - test_size
# calculate the split
return random_split(self, [train_size, test_size])

# model definition
class MLP(Module):
# define model elements
def __init__(self, n_inputs):
super(MLP, self).__init__()
# input to first hidden layer
self.hidden1 = Linear(n_inputs, 10)
kaiming_uniform_(self.hidden1.weight, nonlinearity='relu')
self.act1 = ReLU()
# second hidden layer
self.hidden2 = Linear(10, 8)
kaiming_uniform_(self.hidden2.weight, nonlinearity='relu')
self.act2 = ReLU()
# third hidden layer and output
self.hidden3 = Linear(8, 1)
xavier_uniform_(self.hidden3.weight)
self.act3 = Sigmoid()

# forward propagate input
def forward(self, X):
# input to first hidden layer
X = self.hidden1(X)
X = self.act1(X)
# second hidden layer
X = self.hidden2(X)
X = self.act2(X)
# third hidden layer and output
X = self.hidden3(X)
X = self.act3(X)
return X

# prepare the dataset
def prepare_data(path):
# load the dataset
dataset = CSVDataset(path)
# calculate split
train, test = dataset.get_splits()
# prepare data loaders
train_dl = DataLoader(train, batch_size=32, shuffle=True)
test_dl = DataLoader(test, batch_size=1024, shuffle=False)
return train_dl, test_dl

# train the model
def train_model(train_dl, model):
# define the optimization
criterion = BCELoss()
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
# enumerate epochs
for epoch in range(100):
# enumerate mini batches
for i, (inputs, targets) in enumerate(train_dl):
# clear the gradients
optimizer.zero_grad()
# compute the model output
yhat = model(inputs)
# calculate loss
loss = criterion(yhat, targets)
# credit assignment
loss.backward()
# update model weights
optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
predictions, actuals = list(), list()
for i, (inputs, targets) in enumerate(test_dl):
# evaluate the model on the test set
yhat = model(inputs)
# retrieve numpy array
yhat = yhat.detach().numpy()
actual = targets.numpy()
actual = actual.reshape((len(actual), 1))
# round to class values
yhat = yhat.round()
# store
predictions.append(yhat)
actuals.append(actual)
predictions, actuals = vstack(predictions), vstack(actuals)
# calculate accuracy
acc = accuracy_score(actuals, predictions)
return acc

# make a class prediction for one row of data
def predict(row, model):
# convert row to data
row = Tensor([row])
# make prediction
yhat = model(row)
# retrieve numpy array
yhat = yhat.detach().numpy()
return yhat

# prepare the data
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/ionosphere.csv'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = MLP(34)
# train the model
train_model(train_dl, model)
# evaluate the model
acc = evaluate_model(test_dl, model)
print('Accuracy: %.3f' % acc)
# make a single prediction (expect class=1)
row = [1,0,0.99539,-0.05889,0.85243,0.02306,0.83398,-0.37708,1,0.03760,0.85243,-0.17755,0.59755,-0.44945,0.60536,-0.38223,0.84356,-0.38542,0.58212,-0.32192,0.56971,-0.29674,0.36946,-0.47357,0.56811,-0.51171,0.41078,-0.46168,0.21266,-0.34090,0.42267,-0.54487,0.18641,-0.45300]
yhat = predict(row, model)
print('Predicted: %.3f (class=%d)' % (yhat, yhat.round()))

运行示例首先报告训练和测试数据集的形状,然后拟合模型并在测试数据集上对其进行评估。最后,对单行数据进行预测。

鉴于学习算法的随机性,你的具体结果会有所不同,可以尝试运行该示例几次。

在这种情况下,我们可以看到该模型实现了约94%的分类准确度,然后预测单行数据属于1类的概率为0.99。

235 116
Accuracy: 0.948
Predicted: 0.998 (class=1)
3.2.如何开发用于多类分类的MLP

我们将使用鸢尾花多类分类数据集来演示用于多类分类的MLP。

该问题涉及在给定花的度量的情况下预测鸢尾花的种类。

数据集将使用Pandas自动下载,但您可以在此处了解更多信息。

虹膜数据集(csv):https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv;虹膜数据集描述:https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.names。

鉴于它是一个多类分类,因此该模型在输出层中的每个类必须具有一个节点,并使用softmax激活函数。损失函数是交叉熵,它适合于整数编码的类标签(例如,一个类为0,下一类为1,等等)。

下面列出了在鸢尾花数据集上拟合和评估MLP的完整示例。

# pytorch mlp for multiclass classification
from numpy import vstack
from numpy import argmax
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score
from torch import Tensor
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch.nn import Linear
from torch.nn import ReLU
from torch.nn import Softmax
from torch.nn import Module
from torch.optim import SGD
from torch.nn import CrossEntropyLoss
from torch.nn.init import kaiming_uniform_
from torch.nn.init import xavier_uniform_

# dataset definition
class CSVDataset(Dataset):
# load the dataset
def __init__(self, path):
# load the csv file as a dataframe
df = read_csv(path, header=None)
# store the inputs and outputs
self.X = df.values[:, :-1]
self.y = df.values[:, -1]
# ensure input data is floats
self.X = self.X.astype('float32')
# label encode target and ensure the values are floats
self.y = LabelEncoder().fit_transform(self.y)

# number of rows in the dataset
def __len__(self):
return len(self.X)

# get a row at an index
def __getitem__(self, idx):
return [self.X[idx], self.y[idx]]

# get indexes for train and test rows
def get_splits(self, n_test=0.33):
# determine sizes
test_size = round(n_test * len(self.X))
train_size = len(self.X) - test_size
# calculate the split
return random_split(self, [train_size, test_size])

# model definition
class MLP(Module):
# define model elements
def __init__(self, n_inputs):
super(MLP, self).__init__()
# input to first hidden layer
self.hidden1 = Linear(n_inputs, 10)
kaiming_uniform_(self.hidden1.weight, nonlinearity='relu')
self.act1 = ReLU()
# second hidden layer
self.hidden2 = Linear(10, 8)
kaiming_uniform_(self.hidden2.weight, nonlinearity='relu')
self.act2 = ReLU()
# third hidden layer and output
self.hidden3 = Linear(8, 3)
xavier_uniform_(self.hidden3.weight)
self.act3 = Softmax(dim=1)

# forward propagate input
def forward(self, X):
# input to first hidden layer
X = self.hidden1(X)
X = self.act1(X)
# second hidden layer
X = self.hidden2(X)
X = self.act2(X)
# output layer
X = self.hidden3(X)
X = self.act3(X)
return X

# prepare the dataset
def prepare_data(path):
# load the dataset
dataset = CSVDataset(path)
# calculate split
train, test = dataset.get_splits()
# prepare data loaders
train_dl = DataLoader(train, batch_size=32, shuffle=True)
test_dl = DataLoader(test, batch_size=1024, shuffle=False)
return train_dl, test_dl

# train the model
def train_model(train_dl, model):
# define the optimization
criterion = CrossEntropyLoss()
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
# enumerate epochs
for epoch in range(500):
# enumerate mini batches
for i, (inputs, targets) in enumerate(train_dl):
# clear the gradients
optimizer.zero_grad()
# compute the model output
yhat = model(inputs)
# calculate loss
loss = criterion(yhat, targets)
# credit assignment
loss.backward()
# update model weights
optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
predictions, actuals = list(), list()
for i, (inputs, targets) in enumerate(test_dl):
# evaluate the model on the test set
yhat = model(inputs)
# retrieve numpy array
yhat = yhat.detach().numpy()
actual = targets.numpy()
# convert to class labels
yhat = argmax(yhat, axis=1)
# reshape for stacking
actual = actual.reshape((len(actual), 1))
yhat = yhat.reshape((len(yhat), 1))
# store
predictions.append(yhat)
actuals.append(actual)
predictions, actuals = vstack(predictions), vstack(actuals)
# calculate accuracy
acc = accuracy_score(actuals, predictions)
return acc

# make a class prediction for one row of data
def predict(row, model):
# convert row to data
row = Tensor([row])
# make prediction
yhat = model(row)
# retrieve numpy array
yhat = yhat.detach().numpy()
return yhat

# prepare the data
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = MLP(4)
# train the model
train_model(train_dl, model)
# evaluate the model
acc = evaluate_model(test_dl, model)
print('Accuracy: %.3f' % acc)
# make a single prediction
row = [5.1,3.5,1.4,0.2]
yhat = predict(row, model)
print('Predicted: %s (class=%d)' % (yhat, argmax(yhat)))

运行示例首先报告训练和测试数据集的形状,然后拟合模型并在测试数据集上对其进行评估。最后,对单行数据进行预测。

在这种情况下,我们可以看到该模型实现了约98%的分类精度,然后预测了属于每个类别的一行数据的概率,尽管类别0的概率最高。

100 50
Accuracy: 0.980
Predicted: [[9.5524162e-01 4.4516966e-02 2.4138369e-04]] (class=0)
3.3.如何为回归开发MLP

我们将使用波士顿住房回归数据集来演示用于回归预测建模的MLP。

这个问题涉及根据房屋和邻里的属性来预测房屋价值。

数据集将使用Pandas自动下载,你可以通过下方链接了解更多数据集信息。

波士顿住房数据集(csv):https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv波士顿房屋数据集描述:https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.names

这是一个回归问题,涉及预测单个数值。因此,输出层具有单个节点,并使用默认或线性激活函数(无激活函数)。拟合模型时,均方误差(mse)损失最小。

回想一下,这是回归,而不是分类;因此,我们无法计算分类准确性。

机器学习中分类和回归之间的差异:https://machinelearningmastery.com/classification-versus-regression-in-machine-learning/

下面列出了在波士顿住房数据集中拟合和评估MLP的完整示例。

# pytorch mlp for regression
from numpy import vstack
from numpy import sqrt
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch import Tensor
from torch.nn import Linear
from torch.nn import Sigmoid
from torch.nn import Module
from torch.optim import SGD
from torch.nn import MSELoss
from torch.nn.init import xavier_uniform_

# dataset definition
class CSVDataset(Dataset):
# load the dataset
def __init__(self, path):
# load the csv file as a dataframe
df = read_csv(path, header=None)
# store the inputs and outputs
self.X = df.values[:, :-1].astype('float32')
self.y = df.values[:, -1].astype('float32')
# ensure target has the right shape
self.y = self.y.reshape((len(self.y), 1))

# number of rows in the dataset
def __len__(self):
return len(self.X)

# get a row at an index
def __getitem__(self, idx):
return [self.X[idx], self.y[idx]]

# get indexes for train and test rows
def get_splits(self, n_test=0.33):
# determine sizes
test_size = round(n_test * len(self.X))
train_size = len(self.X) - test_size
# calculate the split
return random_split(self, [train_size, test_size])

# model definition
class MLP(Module):
# define model elements
def __init__(self, n_inputs):
super(MLP, self).__init__()
# input to first hidden layer
self.hidden1 = Linear(n_inputs, 10)
xavier_uniform_(self.hidden1.weight)
self.act1 = Sigmoid()
# second hidden layer
self.hidden2 = Linear(10, 8)
xavier_uniform_(self.hidden2.weight)
self.act2 = Sigmoid()
# third hidden layer and output
self.hidden3 = Linear(8, 1)
xavier_uniform_(self.hidden3.weight)

# forward propagate input
def forward(self, X):
# input to first hidden layer
X = self.hidden1(X)
X = self.act1(X)
# second hidden layer
X = self.hidden2(X)
X = self.act2(X)
# third hidden layer and output
X = self.hidden3(X)
return X

# prepare the dataset
def prepare_data(path):
# load the dataset
dataset = CSVDataset(path)
# calculate split
train, test = dataset.get_splits()
# prepare data loaders
train_dl = DataLoader(train, batch_size=32, shuffle=True)
test_dl = DataLoader(test, batch_size=1024, shuffle=False)
return train_dl, test_dl

# train the model
def train_model(train_dl, model):
# define the optimization
criterion = MSELoss()
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
# enumerate epochs
for epoch in range(100):
# enumerate mini batches
for i, (inputs, targets) in enumerate(train_dl):
# clear the gradients
optimizer.zero_grad()
# compute the model output
yhat = model(inputs)
# calculate loss
loss = criterion(yhat, targets)
# credit assignment
loss.backward()
# update model weights
optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
predictions, actuals = list(), list()
for i, (inputs, targets) in enumerate(test_dl):
# evaluate the model on the test set
yhat = model(inputs)
# retrieve numpy array
yhat = yhat.detach().numpy()
actual = targets.numpy()
actual = actual.reshape((len(actual), 1))
# store
predictions.append(yhat)
actuals.append(actual)
predictions, actuals = vstack(predictions), vstack(actuals)
# calculate mse
mse = mean_squared_error(actuals, predictions)
return mse

# make a class prediction for one row of data
def predict(row, model):
# convert row to data
row = Tensor([row])
# make prediction
yhat = model(row)
# retrieve numpy array
yhat = yhat.detach().numpy()
return yhat

# prepare the data
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = MLP(13)
# train the model
train_model(train_dl, model)
# evaluate the model
mse = evaluate_model(test_dl, model)
print('MSE: %.3f, RMSE: %.3f' % (mse, sqrt(mse)))
# make a single prediction (expect class=1)
row = [0.00632,18.00,2.310,0,0.5380,6.5750,65.20,4.0900,1,296.0,15.30,396.90,4.98]
yhat = predict(row, model)
print('Predicted: %.3f' % yhat)

运行示例首先报告训练和测试数据集的形状,然后拟合模型并在测试数据集上对其进行评估。最后,对单行数据进行预测。

在这种情况下,我们可以看到该模型的MSE约为82,即RMSE约为9(单位为千美元)。然后,针对单个示例预测值为21。

339 167
MSE: 82.576, RMSE: 9.087
Predicted: 21.909
3.4.如何开发用于图像分类的CNN

卷积神经网络(简称CNN)是一种专为图像输入而设计的网络。

它们由具有卷积层的模型组成,这些卷积层提取特征(称为特征图),并汇集将特征分解为最显着元素的层。

尽管CNN可以用于将图像作为输入的各种任务,但它们最适合图像分类任务。

流行的图像分类任务是MNIST手写数字分类。它涉及成千上万个手写数字,必须将其分类为0到9之间的数字。

torchvision API提供了便捷功能,可以直接下载和加载此数据集。

下面的示例加载数据集并绘制前几张图像。

# load mnist dataset in pytorch
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision.transforms import Compose
from torchvision.transforms import ToTensor
from matplotlib import pyplot
# define location to save or load the dataset
path = '~/.torch/datasets/mnist'
# define the transforms to apply to the data
trans = Compose([ToTensor()])
# download and define the datasets
train = MNIST(path, train=True, download=True, transform=trans)
test = MNIST(path, train=False, download=True, transform=trans)
# define how to enumerate the datasets
train_dl = DataLoader(train, batch_size=32, shuffle=True)
test_dl = DataLoader(test, batch_size=32, shuffle=True)
# get one batch of images
i, (inputs, targets) = next(enumerate(train_dl))
# plot some images
for i in range(25):
# define subplot
pyplot.subplot(5, 5, i+1)
# plot raw pixel data
pyplot.imshow(inputs[i][0], cmap='gray')
# show the figure
pyplot.show()

运行示例将加载MNIST数据集,然后汇总默认的训练和测试数据集。

Train: X=(60000, 28, 28), y=(60000,)
Test: X=(10000, 28, 28), y=(10000,)

然后创建一个图,显示训练数据集中的手写图像示例网格。

PyTorch教程:如何使用Python开发深度学习模型(建

MNIST数据集中的手写数字图

我们可以训练CNN模型对MNIST数据集中的图像进行分类。

请注意,图像是灰度像素数据的数组,因此,在将图像用作模型的输入之前,必须向数据添加通道尺寸。

最好将像素值从默认范围0-255缩放为零平均值,标准偏差为1。有关缩放像素值的更多信息,可通过下方链接了解:

如何手动缩放图像像素数据以进行深度学习:https://machinelearningmastery.com/how-to-manually-scale-image-pixel-data-for-deep-learning/

下面列出了在MNIST数据集上拟合和评估CNN模型的完整示例。

# pytorch cnn for multiclass classification
from numpy import vstack
from numpy import argmax
from pandas import read_csv
from sklearn.metrics import accuracy_score
from torchvision.datasets import MNIST
from torchvision.transforms import Compose
from torchvision.transforms import ToTensor
from torchvision.transforms import Normalize
from torch.utils.data import DataLoader
from torch.nn import Conv2d
from torch.nn import MaxPool2d
from torch.nn import Linear
from torch.nn import ReLU
from torch.nn import Softmax
from torch.nn import Module
from torch.optim import SGD
from torch.nn import CrossEntropyLoss
from torch.nn.init import kaiming_uniform_
from torch.nn.init import xavier_uniform_

# model definition
class CNN(Module):
# define model elements
def __init__(self, n_channels):
super(CNN, self).__init__()
# input to first hidden layer
self.hidden1 = Conv2d(n_channels, 32, (3,3))
kaiming_uniform_(self.hidden1.weight, nonlinearity='relu')
self.act1 = ReLU()
# first pooling layer
self.pool1 = MaxPool2d((2,2), stride=(2,2))
# second hidden layer
self.hidden2 = Conv2d(32, 32, (3,3))
kaiming_uniform_(self.hidden2.weight, nonlinearity='relu')
self.act2 = ReLU()
# second pooling layer
self.pool2 = MaxPool2d((2,2), stride=(2,2))
# fully connected layer
self.hidden3 = Linear(5*5*32, 100)
kaiming_uniform_(self.hidden3.weight, nonlinearity='relu')
self.act3 = ReLU()
# output layer
self.hidden4 = Linear(100, 10)
xavier_uniform_(self.hidden4.weight)
self.act4 = Softmax(dim=1)

# forward propagate input
def forward(self, X):
# input to first hidden layer
X = self.hidden1(X)
X = self.act1(X)
X = self.pool1(X)
# second hidden layer
X = self.hidden2(X)
X = self.act2(X)
X = self.pool2(X)
# flatten
X = X.view(-1, 4*4*50)
# third hidden layer
X = self.hidden3(X)
X = self.act3(X)
# output layer
X = self.hidden4(X)
X = self.act4(X)
return X

# prepare the dataset
def prepare_data(path):
# define standardization
trans = Compose([ToTensor(), Normalize((0.1307,), (0.3081,))])
# load dataset
train = MNIST(path, train=True, download=True, transform=trans)
test = MNIST(path, train=False, download=True, transform=trans)
# prepare data loaders
train_dl = DataLoader(train, batch_size=64, shuffle=True)
test_dl = DataLoader(test, batch_size=1024, shuffle=False)
return train_dl, test_dl

# train the model
def train_model(train_dl, model):
# define the optimization
criterion = CrossEntropyLoss()
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
# enumerate epochs
for epoch in range(10):
# enumerate mini batches
for i, (inputs, targets) in enumerate(train_dl):
# clear the gradients
optimizer.zero_grad()
# compute the model output
yhat = model(inputs)
# calculate loss
loss = criterion(yhat, targets)
# credit assignment
loss.backward()
# update model weights
optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
predictions, actuals = list(), list()
for i, (inputs, targets) in enumerate(test_dl):
# evaluate the model on the test set
yhat = model(inputs)
# retrieve numpy array
yhat = yhat.detach().numpy()
actual = targets.numpy()
# convert to class labels
yhat = argmax(yhat, axis=1)
# reshape for stacking
actual = actual.reshape((len(actual), 1))
yhat = yhat.reshape((len(yhat), 1))
# store
predictions.append(yhat)
actuals.append(actual)
predictions, actuals = vstack(predictions), vstack(actuals)
# calculate accuracy
acc = accuracy_score(actuals, predictions)
return acc

# prepare the data
path = '~/.torch/datasets/mnist'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = CNN(1)
# # train the model
train_model(train_dl, model)
# evaluate the model
acc = evaluate_model(test_dl, model)
print('Accuracy: %.3f' % acc)

运行示例首先报告训练和测试数据集的形状,然后拟合模型并在测试数据集上对其进行评估。

在这种情况下,我们可以看到该模型在测试数据集上实现了约98%的分类精度。然后我们可以看到该模型预测了训练集中的第一幅图像的5类。

60000 10000
Accuracy: 0.985
最后

实践出真知,深度学习模型创建是一个需要仔细钻研的过程,自己动手做才能了解到其中的奥义。这里介绍了利用Python创建深度学习模型的详细教程,整个过程需要至少一个小时以上,沉下心来,慢慢学习吧!希望对你们有用!

--END--

翻译:未艾信息(www.weainfo.net)

查看更多最新资讯,欢迎大家点击阅读原文登录我们的AI社区。

以及关注我们的公众号:为AI呐喊(weainahan)