python torch exp_一个简单而强大的深度学习库—PyTorch

每过一段时间,总会有一个python库被开发出来,改变深度学习领域。而PyTorch就是这样一个库。

在过去的几周里,我一直在尝试使用PyTorch。我发现它非常好上手。迄今为止,在我所有的各种深度学习库中,PyTorch一直是最灵活和容易的。

在本文中,我们将探索PyTorch的实际应用,其中包括基础知识和案例研究。我们还将比较使用numpy和PyTorch构建的神经网络,以查看它们在实现中的相似之处。

PyTorch概述

PyTorch的创作者说他们信奉的道理是 - 解决当务之急。这意味着我们立即运行我们的计算。这恰好适合python的编程方法,因为我们不必等待所有代码都写完才能知道它是否有效。我们可以运行部分代码并实时检查它。对于我,一个神经网络调试器来说,这无意是一个福音!

PyTorch是一个基于python的库,旨在提供灵活的深度学习开发平台。PyTorch的工作流程很可能接近python的科学计算库 - numpy。

那么,为什么我们要使用PyTorch来构建深度学习模型?:

易于使用的API - 如Python一样简单。

Python支持 - 如上所述,PyTorch平滑地与Python数据科学堆栈结合。它与numpy非常相似,你甚至很难注意到他们的差异。

动态计算图 - PyTorch并没有为特定功能预定义图形,而是为我们提供了一个框架,可以随时随地构建计算图,甚至在运行时更改计算图。我们不知道创建一个神经网络需要多少内存时,这非常有用。

使用PyTorch的还有其他的优点,它能够支持multiGPU,自定义数据加载和简化的预处理程序。

自2016年1月初发布以来,许多研究人员已将其作为一种实现库,因为它易于构建新颖甚至非常复杂的计算图。话虽如此,PyTorch仍然需要一段时间才能被大多数数据科学从业者所采用,因为它是新的并且正在建设中。

在深入细节之前,让我们了解PyTorch的工作流程。

PyTorch使用命令式/热切式范式。也就是说,构建图形的每行代码都定义了该图的一个组件。即使在图形完全构建之前,我们也可以独立地对这些组件进行计算。这被称为运行时定义(define-by-run)法。

安装PyTorch非常简单。您可以按照它的官方文档操作,并根据自己的系统规格运行命令。例如,下面是我根据我的情况使用的命令:

conda install pytorch torchvision cuda91 -c pytorch

我们在开始使用PyTorch时应该了解的主要元素是:

PyTorch张量

数学运算

Autograd模块

Optim模块

nn模块

PyTorch张量

张量不过是多维数组。PyTorch中的张量与numpy的ndarray相似,张量也可以在GPU上使用。PyTorch支持很多类型的张量。

你可以定义一个简单的一维矩阵如下:

# import pytorch

import torch

# define a tensor

torch.FloatTensor([2])

2

[torch.FloatTensor of size 1]

数学运算

与numpy一样,科学计算库需要高效的实现数学函数。PyTorch提供了一个相似的接口,可以使用超过200多种数学运算。

以下是PyTorch中一个简单加法操作的例子:

a = torch.FloatTensor([2])

b = torch.FloatTensor([3])

a + b

5

[torch.FloatTensor of size 1]

这看起来不像是一种quinessential python方法吗?我们也可以对我们定义的PyTorch张量执行各种矩阵运算。例如,我们将转置一个二维矩阵:

matrix = torch.randn(3, 3)

matrix

-1.3531 -0.5394  0.8934

1.7457 -0.6291 -0.0484

-1.3502 -0.6439 -1.5652

[torch.FloatTensor of size 3x3]

matrix.t()

-2.1139  1.8278  0.1976

0.6236  0.3525  0.2660

-1.4604  0.8982  0.0428

[torch.FloatTensor of size 3x3]

Autograd模块

PyTorch使用一种称为自动微分(automatic differentiation)的技术。也就是说,有一个记录我们所执行的操作的记录器,然后它会反向回放以计算我们的梯度。这种技术在建立神经网络时尤为有效,因为我们可以通过计算正向传递过程中参数的微分来节省一个周期的时间。

from torch.autograd import Variable

x = Variable(train_x)

y = Variable(train_y, requires_grad=False)

Optim模块

torch.optim 是一个实现构建神经网络的各种优化算法的模块。大多数常用的方法已经被支持,因此我们不必从头开始构建它们(除非你乐意这么做)。

以下是使用Adam优化的代码:

optimizer = torch.optim.Adam(model.parameters(),lr = learning_rate)

nn模块

PyTorch的autograd模块可以很容易地定义计算图和梯度,但是默认的autograd对于定义复杂的神经网络可能有些低级。这时就要用到nn模块。

nn包定义了一组模块,我们可以将其视为一个神经网络层,它可以从输入生成输出,并且具有一些可训练的权重。

您可以将一个nn模块视为PyTorch 的keras!

import torch

# define model

model = torch.nn.Sequential(

torch.nn.Linear(input_num_units, hidden_num_units),

torch.nn.ReLU(),

torch.nn.Linear(hidden_num_units, output_num_units),

)

loss_fn = torch.nn.CrossEntropyLoss()

在Numpy与PyTorch建立一个神经网络的对比

我之前提到PyTorch和Numpy非常相似。那么,我们来看看为什么,一个简单的神经网络的实现来解决二元分类问题。使用Numpy如下:

## Neural network in numpy

import numpy as np

#Input array

X=np.array([[1,0,1,0],[1,0,1,1],[0,1,0,1]])

#Output

y=np.array([[1],[1],[0]])

#Sigmoid Function

def sigmoid (x):

return 1/(1 + np.exp(-x))

#Derivative of Sigmoid Function

def derivatives_sigmoid(x):

return x * (1 - x)

#Variable initialization

epoch=5000 #Setting training iterations

lr=0.1 #Setting learning rate

inputlayer_neurons = X.shape[1] #number of features in data set

hiddenlayer_neurons = 3 #number of hidden layers neurons

output_neurons = 1 #number of neurons at output layer

#weight and bias initialization

wh=np.random.uniform(size=(inputlayer_neurons,hiddenlayer_neurons))

bh=np.random.uniform(size=(1,hiddenlayer_neurons))

wout=np.random.uniform(size=(hiddenlayer_neurons,output_neurons))

bout=np.random.uniform(size=(1,output_neurons))

for i in range(epoch):

#Forward Propogation

hidden_layer_input1=np.dot(X,wh)

hidden_layer_input=hidden_layer_input1 + bh

hiddenlayer_activations = sigmoid(hidden_layer_input)

output_layer_input1=np.dot(hiddenlayer_activations,wout)

output_layer_input= output_layer_input1+ bout

output = sigmoid(output_layer_input)

#Backpropagation

E = y-output

slope_output_layer = derivatives_sigmoid(output)

slope_hidden_layer = derivatives_sigmoid(hiddenlayer_activations)

d_output = E * slope_output_layer

Error_at_hidden_layer = d_output.dot(wout.T)

d_hiddenlayer = Error_at_hidden_layer * slope_hidden_layer

wout += hiddenlayer_activations.T.dot(d_output) *lr

bout += np.sum(d_output, axis=0,keepdims=True) *lr

wh += X.T.dot(d_hiddenlayer) *lr

bh += np.sum(d_hiddenlayer, axis=0,keepdims=True) *lr

print('actual :\n', y, '\n')

print('predicted :\n', output)

使用PyTorch如下(下面的代码中用粗体表示差异):

## neural network in pytorchimport torch#Input arrayX =torch.Tensor([[1,0,1,0],[1,0,1,1],[0,1,0,1]])#Outputy =torch.Tensor([[1],[1],[0]])#Sigmoid Functiondef sigmoid (x):  return 1/(1 +torch.exp(-x))#Derivative of Sigmoid Functiondef derivatives_sigmoid(x):  return x * (1 - x)#Variable initializationepoch=5000 #Setting training iterationslr=0.1 #Setting learning rateinputlayer_neurons = X.shape[1] #number of features in data sethiddenlayer_neurons = 3 #number of hidden layers neuronsoutput_neurons = 1 #number of neurons at output layer#weight and bias initializationwh=torch.randn(inputlayer_neurons, hiddenlayer_neurons).type(torch.FloatTensor)bh=torch.randn(1, hiddenlayer_neurons).type(torch.FloatTensor)wout=torch.randn(hiddenlayer_neurons, output_neurons)bout=torch.randn(1, output_neurons)for i in range(epoch):  #Forward Propogation  hidden_layer_input1 =torch.mm(X, wh)  hidden_layer_input = hidden_layer_input1 + bh  hidden_layer_activations = sigmoid(hidden_layer_input)  output_layer_input1 =torch.mm(hidden_layer_activations, wout)  output_layer_input = output_layer_input1 + bout  output = sigmoid(output_layer_input1)  #Backpropagation  E = y-output  slope_output_layer = derivatives_sigmoid(output)  slope_hidden_layer = derivatives_sigmoid(hidden_layer_activations)  d_output = E * slope_output_layer  Error_at_hidden_layer =torch.mm(d_output, wout.t())  d_hiddenlayer = Error_at_hidden_layer * slope_hidden_layer  wout +=torch.mm(hidden_layer_activations.t(), d_output) *lr  bout += d_output.sum() *lr  wh +=torch.mm(X.t(), d_hiddenlayer) *lr  bh += d_output.sum() *lr print('actual :\n', y, '\n')print('predicted :\n', output)

与其他深度学习库比较

在一个基准脚本中,PyTorch 在训练LSTM方面表现优于所有其他主要的深度学习库,每个周期的中位时间最低(参见下图)。

在PyTorch中用于数据加载的API设计良好。接口在数据集,采样器和数据加载器中指定。

在比较TensorFlow中的数据加载工具(readers,queues,等)时,我发现PyTorch的数据加载模块非常好用。另外,PyTorch可以无缝的构建神经网络,我们不必依赖像keras这样的第三方高级库。

另一方面,我不会推荐使用PyTorch进行部署。PyTorch还在发展中。正如PyTorch开发人员所说:“我们看到的是,用户首先创建了一个PyTorch模型。当他们准备将他们的模型部署到生产环境中时,他们只需将其转换为Caffe 2模型,然后将其发布到移动平台或其他平台中。“

案例研究 - 解决PyTorch中的图像识别问题

为了熟悉PyTorch,我们将解决分析方面的深度学习实践问题 - 识别数字。

我们的要做的是一个图像识别问题,从一个给定的28×28像素的图像中识别数字。我们有一部分图像用于训练,其余部分用于测试我们的模型。

首先,下载训练集与测试集。数据集包含所有图像的压缩文件,并且train.csv和test.csv都具有相应训练和测试图像的名称。数据集中不提供任何额外特征,图片为.png格式。

第0步:准备工作

a)导入所有需要用到的库

# import modules

%pylab inline

import os

import numpy as np

import pandas as pd

from scipy.misc import imread

from sklearn.metrics import accuracy_score

b)让我们设置seed值,以便我们可以控制模型的随机性

# To stop potential randomness

seed = 128

rng = np.random.RandomState(seed)

c)第一步是设置目录路径,以便妥善保存!

root_dir = os.path.abspath('.')

data_dir = os.path.join(root_dir, 'data')

# check for existence

os.path.exists(root_dir), os.path.exists(data_dir)

第1步:数据加载和预处理

a)现在让我们读取数据集。

# load dataset

train = pd.read_csv(os.path.join(data_dir, 'Train', 'train.csv'))

test = pd.read_csv(os.path.join(data_dir, 'Test.csv'))

sample_submission = pd.read_csv(os.path.join(data_dir, 'Sample_Submission.csv'))

train.head()

b)让我们看看我们的数据是什么样的。我们阅读我们的图像并显示它。

# print an image

img_name = rng.choice(train.filename)

filepath = os.path.join(data_dir, 'Train', 'Images', 'train', img_name)

img = imread(filepath, flatten=True)

pylab.imshow(img, cmap='gray')

pylab.axis('off')

pylab.show()

d)为了便于数据处理,让我们将所有图像存储为numpy数组

# load images to create train and test set

temp = []

for img_name in train.filename:

image_path = os.path.join(data_dir, 'Train', 'Images', 'train', img_name)

img = imread(image_path, flatten=True)

img = img.astype('float32')

temp.append(img)

train_x = np.stack(temp)

train_x /= 255.0

train_x = train_x.reshape(-1, 784).astype('float32')

temp = []

for img_name in test.filename:

image_path = os.path.join(data_dir, 'Train', 'Images', 'test', img_name)

img = imread(image_path, flatten=True)

img = img.astype('float32')

temp.append(img)

test_x = np.stack(temp)

test_x /= 255.0

test_x = test_x.reshape(-1, 784).astype('float32')

train_y = train.label.values

e)这是一个典型的机器学习问题,为了测试我们模型的是否正常运行,我们创建一个验证集。我们分离他们的比例为70:30(验证集为30)。

# create validation set

split_size = int(train_x.shape[0]*0.7)

train_x, val_x = train_x[:split_size], train_x[split_size:]

train_y, val_y = train_y[:split_size], train_y[split_size:]

第2步:建立模型

a)下面,我们定义神经网络架构。我们定义了一个3个层(输入,隐藏和输出)的神经网络。输入和输出中神经元的数量是固定的,因为输入是我们图像28×28,并且输出是代表类的10×1向量(即每个像素对应一个输入神经元,每个类为一个输出)。我们在隐藏层中采用50个神经元。在这里,我们使用Adam作为我们的优化算法,它是梯度下降算法的一个不错的变种。

import torch

from torch.autograd import Variable

# number of neurons in each layer

input_num_units = 28*28

hidden_num_units = 500

output_num_units = 10

# set remaining variables

epochs = 5

batch_size = 128

learning_rate = 0.001

b)训练模型

# define model

model = torch.nn.Sequential(

torch.nn.Linear(input_num_units, hidden_num_units),

torch.nn.ReLU(),

torch.nn.Linear(hidden_num_units, output_num_units),

)

loss_fn = torch.nn.CrossEntropyLoss()

# define optimization algorithm

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

## helper functions

# preprocess a batch of dataset

def preproc(unclean_batch_x):

"""Convert values to range 0-1"""

temp_batch = unclean_batch_x / unclean_batch_x.max()

return temp_batch

# create a batch

def batch_creator(batch_size):

dataset_name = 'train'

dataset_length = train_x.shape[0]

batch_mask = rng.choice(dataset_length, batch_size)

batch_x = eval(dataset_name + '_x')[batch_mask]

batch_x = preproc(batch_x)

if dataset_name == 'train':

batch_y = eval(dataset_name).ix[batch_mask, 'label'].values

return batch_x, batch_y

# train network

total_batch = int(train.shape[0]/batch_size)

for epoch in range(epochs):

avg_cost = 0

for i in range(total_batch):

# create batch

batch_x, batch_y = batch_creator(batch_size)

# pass that batch for training

x, y = Variable(torch.from_numpy(batch_x)), Variable(torch.from_numpy(batch_y), requires_grad=False)

pred = model(x)

# get loss

loss = loss_fn(pred, y)

# perform backpropagation

loss.backward()

optimizer.step()

avg_cost += loss.data[0]/total_batch

print(epoch, avg_cost)

# get training accuracy

x, y = Variable(torch.from_numpy(preproc(train_x))), Variable(torch.from_numpy(train_y), requires_grad=False)

pred = model(x)

final_pred = np.argmax(pred.data.numpy(), axis=1)

accuracy_score(train_y, final_pred)

# get validation accuracy

x, y = Variable(torch.from_numpy(preproc(val_x))), Variable(torch.from_numpy(val_y), requires_grad=False)

pred = model(x)

final_pred = np.argmax(pred.data.numpy(), axis=1)

accuracy_score(val_y, final_pred)

训练分数是:

0.8779008746355685

验证分数是:

0.867482993197279

这个分数相当的高,我们才训练这个简单的神经网络五个周期而已。

关于人工智能,如果想了解更多,可关注微信公众号:atyun_com或者网站AiTechYun(http://www.atyun.com/),最快获得第一手信息。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值