1. Pytorch介绍

常见深度学习框架

近几年深度学习崛起,它的崛起背后最大的功臣-深度学习框架。如果没有这些深度学习框架,深度学习绝对不会像现在一样“平民化”,很多人可能陷入在茫茫的数学深渊中。有了可方便使用的深度学习

框架,我们可以把所有精力花在如何设计模型本身上,而不用再去关注模型优化的细节,所有的事情均由框架来负责,极大降低了深度学习使用的门槛。这也是为什么现在只要经过短期有效训练的开发

工程师也可以在使用深度学习模型身上得心应手的主要原因。

深度学习框架的发展也经历了超过10年的时间,从早期比较流行的theano到现在比较火爆的框架如Pytorch, Tensorflow,经历了几个阶段的发展和迭代。

pytorch 模型 推理 pytorch 推理框架_pytorch 模型 推理

图中展示了几个比较有代表性的深度学习框架,是不同时代的产物。比如图里的Caffe来源于伯克利的一位博士生,框架本身效率高,但需要编写比较繁琐的配置文件。在配置文件中会设置网络的层次、

每一层的参数等所有细节,目前在工业界仍然是一个比较受欢迎的深度学习框架。另外,Keras的使用也比较广泛。它一开始是建立在Tensorflow之上的,并封装了很多的模块,让使用者可以更低门槛地

去设计深度学习模型,目前也有大量的使用者。但缺点是,由于做了进一步的封装,如果想做一些改动,灵活性上相比Tensorflow要差一些。

从这些框架中,如果让我们选择目前最火爆的,大多数人可能会毫无犹豫地选出Pytorch和TensorFlow。究其原因,还是因为他们的高效、灵活性以及低门槛的使用。Tensorflow作为Google公司一个重要

的产品,在性能方面的表现也是可圈可点的。另一方面,Pytorch作为新的框架,这几年展现出了超高的人气和增长,主要源于它的低门槛且特别容易上手。 

pytorch框架崛起

TensorFlow与Pytorch两个框架的发展历史以及趋势,分别从搜索热度、学术界的欢迎度等角度来剖析。之所以选择这两个框架,一方面的原因在于确实这俩是目前最火爆的框架,另外一方面的原因是也

比较适合刚步入AI领域的人士去接触和学习。

pytorch 模型 推理 pytorch 推理框架_数据_02

 

图里展示的是Google搜索引擎上的搜索热度,代表有多少人去搜索这两个框架。从图中可以很清楚地看到,17年的时候TensorFlow仍然占据着完全主导性的地位,但随着时间的推移,Pytorch的增长越来

越快,到了20年初基本上逼近了Tensorflow的热度,而且这种增长趋势仍在持续。

pytorch 模型 推理 pytorch 推理框架_python_03

 

 

 

pytorch 模型 推理 pytorch 推理框架_pytorch 模型 推理_04

以上两幅图表示的是Pytorch和TensorFlow在学术界的使用情况,分别算出了每一年顶会中有多少篇文章的实验用这两个工具来做的。我们很容易发现,在学术界里Pytorch的优势更加明显,显示出强势的

增长。那为什么会出现这种趋势呢? 主要还是Pytorch用起来简单,而且效率也不差。对于之前没有接触过深度学习框架的人,Pytorch无疑是首选,特别适合入门。

Pytorch与Tensorflow多方位比较

pytorch 模型 推理 pytorch 推理框架_python_05

以上图中给出了两个框架之间具体的差异,其中最重要的差别在于Pytorch采用了命令式编程,TensorFlow则采用了符号式编程(symbolic programming),实际上这是两种完全不同的编程方式。命令式编

程其实就是我们最熟悉的编程方式,比如使用Python, Java等等。然而,符号式编程就不一样了,首选需要构建计算图,然后再把数据灌到图里做计算。

为了理解上述观点,简单看一下给出的几行代码。 左边展示的是Pytorch框架下的程序,跟我们日常编写的程序没什么差异。为了计算pytorch 模型 推理 pytorch 推理框架_数据_06

pytorch 模型 推理 pytorch 推理框架_深度学习_07pytorch 模型 推理 pytorch 推理框架_python_08

定义好静态计算图之后,我们就可以把数据输入给计算图了。输入数据接着会通过预先定义好的步骤最后能算出结果。

如果对上述概念比较难理解,你也可以想象一个这样的场景。有一家公司现在试着去构建从城市A到B的管道,用来运输一定量的石油。

一种解决思路是,提前把管道全部制作完成,然后把石油输入到管道中,之后通过一系列运输过程最终可能会到达B城市。

另外一种解决思路是,我们一边制作管道,一边运输石油,在这种情况下管道的设计可以动态地改变,比如我们发现某个路径不对劲,就可以换成另外一个路径。

在这里例子中,前者对应的是符号式编程,后者对应的是命令式编程。

简答来讲,前者是静态的,后者是动态的。动态的好处是灵活,但缺点是效率会低一些;相反,前者是静态的,必须要提前准备好完整的计算图(管道),之后才能使用,这种优势在于使用时的效率高,

但缺点是不好理解和debug。

建议刚步入AI领域的人士使用Pytorch,会大大降低学习成本。

 

2. Tensors

Tensor的概念及相关的运算操作。详细参看Pytorch官网。

Tensor的创建

首先需要理解Tensor这个关键词,这是Pytorch中最基础的数据结构,就类似于Numpy库中的array, matrix一样。但在Pytorch我们把这些统一定义为Tensor。数据的表现形式通常为标量(scalar)、向量

(vector)、矩阵(matrix)、张量(Tensor)。 其中标量可以看作是0维的张量、向量看作是1维的张量、矩阵看作是2维的张量,依次类推。所以,最终我们可以

把Tensor作为这些数据结构的统称,这也是为什么像TensorFlow这种框架里包含Tensor关键词的主要原因。

在Pytorch中,Tensor的使用非常类似于Numpy的用法,但区别于Numpy的数据,Tensor数据可以用在GPU等设备上去跑,可以大大提高算法运行的效率。

Tensor库的导入

为了使用Pytorch的数据结构与功能,首先需要导入相应的库。这类似于当使用Numpy的时候导入numpy库一样。对于Pytorch,我们可以导入torch库。

import torch
import numpy as np

```为了使用Pytorch的数据结构与功能,首先需要导入相应的库。这类似于当使用Numpy的时候导入numpy库一样。对于Pytorch,我们可以导入torch库。
```python

import torch
import numpy as np

从已有数据直接构建Tensor 

第一步是构建Tensor类型的数据,其中一个方法是直接利用已有的数据来初始化Tensor,如下所示:

data = [[1,3],[3,4]]
t_data = torch.tensor(data)

```第一步是构建Tensor类型的数据,其中一个方法是直接利用已有的数据来初始化Tensor,如下所示:
```python

data = [[1,3],[3,4]]
t_data = torch.tensor(data)

把Numpy数据转换成Tensor类型

如果数据已经表示为Numpy类型,我们也可以直接把它转换为Tensor类型的数据,这种操作在实际项目中非常实用。

np_data = np.array(data)
t_data = torch.from_numpy(np_array)

```如果数据已经表示为Numpy类型,我们也可以直接把它转换为Tensor类型的数据,这种操作在实际项目中非常实用。
```python

np_data = np.array(data)
t_data = torch.from_numpy(np_array)

直接利用Tensor库来创建Tensor数据

另外一种方式是直接使用Tensor所提供的方法来构造Tensor数据,这类似于我们调用numpy。zeors()函数来创建numpy型数据一样。请看如下几行代码:

shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

```另外一种方式是直接使用Tensor所提供的方法来构造Tensor数据,这类似于我们调用<span class="study-main-color7">numpy。zeors()</span>函数来创建numpy型数据一样。请看如下几行代码:
```python

shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

Tensor的属性(attributes)

构建好Tensor之后,我们可以查看它的一些属性如大小、类型、以及存放在cpu还是在gpu等信息。以上属性依次通过shape, dtype, device关键词来获取。 请运行下方的代码并查看输出结果。

import torch
import numpy as np
data = torch.rand(3,4)
print(f"Shape of data: {data.shape}")
print(f"Datatype of data: {data.dtype}")
print(f"Device data is stored on: {data.device}")

结果如下所示:

Initialize directly from data: 
 tensor([[1, 3],
        [3, 4]]) 

Initialize from numpy data: 
 tensor([[1, 3],
        [3, 4]]) 

initialize directly from tensor: rand_tensor: 
 tensor([[0.7906, 0.8896, 0.0645],
        [0.8684, 0.3434, 0.0600]]) 

Initialize from numpy data: ones_tensor: 
 tensor([[1., 1., 1.],
        [1., 1., 1.]]) 

Initialize from numpy data: zeros_tensor: 
 tensor([[0., 0., 0.],
        [0., 0., 0.]])

 

Tensor的操作

Tensor也像Numpy array支持各种各样的运算操作,比如矩阵乘法、加法、采样等等,而且这些运算均可以在GPU上进行。如果想把 Tensor在GPU做计算,需要把它先挪到GPU内存中,通过以下几行代

码就可以实现:

if torch.cuda.is_available():
tensor = tensor.to('cuda')
```Tensor也像Numpy array支持各种各样的运算操作,比如矩阵乘法、加法、采样等等,而且这些运算均可以在GPU上进行。如果想把 Tensor在GPU做计算,需要把它先挪到GPU内存中,通过以下几行代码就可以实现:
```python

if torch.cuda.is_available():
tensor = tensor.to('cuda')

Tensor的索引

对于Tensor, 我们可以很方便的提取它的某一行、某一列、或者多行、多列,使用方法跟numpy几乎一模一样。

data = torch.ones(4,4)
data[:,1] = 0
```对于Tensor, 我们可以很方便的提取它的某一行、某一列、或者多行、多列,使用方法跟numpy几乎一模一样。

```python

data = torch。ones(4,4)
data[:,1] = 0

多个Tensor的拼接

很多时候,我们需要把多个Tensor做拼接,并转换为更大的Tensor。 这种操作可以通过自带的torch。cat()来完成,具体以哪个方向做拼接由dim参数来设定。

t1 = torch.cat([data, data, data], dim =1)

```很多时候,我们需要把多个Tensor做拼接,并转换为更大的Tensor。 这种操作可以通过自带的<span class="study-main-color7">torch。cat()</span>来完成,
具体以哪个方向做拼接由<span class="study-main-color7">dim</span>参数来设定。
```python

t1 = torch。cat([data, data, data], dim =1)

Tensor的乘法

给定两个Tensor也可以方便地完成乘法运算。这里需要注意的一点是,一种乘法运算可以是我们所熟知的正常的矩阵乘法运算,另外一种乘法运算是按照每一个位置的乘法运算(element-wise

multiplication)

data1 = torch.ones(2,2)
data2 = torch.ones(2,2)
mul_res1 = torch.matmul(data1, data2)
mul_res2 = data1 * data2

```给定两个Tensor也可以方便地完成乘法运算。这里需要注意的一点是,一种乘法运算可以是我们所熟知的正常的矩阵乘法运算,另外一种乘法运算是按照每一个位置的乘法运算(element-wise multiplication)

```python

data1 = torch.ones(2,2)
data2 = torch.ones(2,2)
mul_res1 = torch.matmul(data1, data2)
mul_res2 = data1 * data2

 

import torch
import numpy as np
# index tensor array
data = torch.ones(4,4)
data[:,1] = 0
print(f"Slicing example: \n {data} \n ")
# concatenate 3 tensors
data = torch.rand(3,3)
t1 = torch.cat([data, data, data], dim =1)
print(f"Concatenation of tensor example before: \n  {data} \n ")
print(f"Concatenation of tensor example after: \n  {t1} \n ")
# multiply tensors
data1 = torch.ones(2,2)
data2 = torch.ones(2,2)
mul_res1 = torch.matmul(data1, data2)  # normal multiplication
mul_res2 = data1 * data2  # element-wise multiplication
print(f"normal multiplication example: data1: \n  {mul_res1} \n ")
print(f"normal multiplication example: data2: \n  {mul_res1} \n ")
print(f"normal multiplication example: mul_res1: \n  {mul_res1} \n ")
print(f"element-wise multiplication example: mul_res2 \n  {mul_res2} \n ")

Tensor与Numpy的转换

从Tensor到Numpy

在CPU上,Tensor和Numpy变量可以共享一个内存空间,改变其中一个会自动改变另外一个。从Tensor到numpy类型的转化通过函数numpy()即可以实现。

```在CPU上,Tensor和Numpy变量可以共享一个内存空间,改变其中一个会自动改变另外一个。从Tensor到numpy类型的转化通过函数<span class="study-main-color7">numpy()</span>即可以实现。

```python

从Numpy到Tensor的转换

另一个方向的转换也极其简单,可通过from_numpy()函数来完成。这种情况下两个变量会共享一个内存,改变其中一个也会改变另外一个变量,这一点需要留意一下。

```另一个方向的转换也极其简单,可通过<span class="study-main-color7">from_numpy()</span>函数来完成。这种情况下两个变量会共享一个内存,改变其中一个也会改变另外一个变量,这一点需要留意一下。

```python
import torch
import numpy as np
# from torch to numpy
t = torch.ones(5)
print(f"t: {t}")
n = t.numpy()
# change one will change another
t.add_(1)
print(f"t: {t}")
print(f"n: {n}")
# from numpy to torch
n = np.ones(5)
t = torch.from_numpy(n)
# change one will change another
np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")

3. Autograd

Pytorch中Autograd模块的作用以及用法。

模型中的前向传播和反向传播

对于神经网络的优化,一般分为两个步骤: 第一步为前向传播,也就是给定训练数据,通过前向传播计算出模型中每个节点的输出; 第二步则为反向传播,通过这一步计算出每一个参数的梯度,最后做参

数的更新。实际上,Pytorch中的autograd模块就是替我们完成这些事情!

下面,我们来看一个具体的例子。首先,导入已经训练好的restnet模型,同时也构建一个随机样本。这个样本为一张64*64的图片且每一个像素由RGB来表示,对应的标签为一个整数。

```下面,我们来看一个具体的例子。首先,导入已经训练好的<span >restnet</span>模型,同时也构建一个随机样本。这个样本为一张64*64的图片且每一个像素由RGB来表示,对应的标签为一个整数。

```python
import torch, torchvision

model = torchvision.models.resnet18(pretrained=True)
data = torch.rand(1, 3, 64, 64)
labels = torch.rand(1, 1000)
for itr in range(10):
    prediction = model(data)  # forward pass
    loss = torch.abs(prediction - labels).sum()
    loss.backward()  # backward pass
    optim = torch.optim.SGD(model.parameters(), lr=1e-3, momentum=0.9)
    optim.step()  # gradient descent

    print(loss)

利用autograd计算梯度

对于autograd再看一个例子,用来加深对它的理解。假如有两个Tensor分别为a和b, 同时设置requires_grad=True, 这样的结果就是autograd会保存对于相应变量的操作。

```对于<span class="study-main-color7">autograd</span>再看一个例子,用来加深对它的理解。假如有两个Tensor分别为a和b, 同时设置<span class="study-main-color7">requires_grad=True</span>, 
这样的结果就是<span class="study-main-color7">autograd</span>会保存对于相应变量的操作。
```python
import torch
a = torch.tensor(3.0, requires_grad=True)
b = torch.tensor(6.0, requires_grad=True)
l = 3*a**3-b**2
l.backward()
print (9*a**2 == a.grad)
print (-2*b == b.grad)

4. 构建神经网络模型

使用Pytorch从零搭建一个神经网络模型,并做训练。

搭建的过程主要分为以下几步:

  • 1. 数据的构造,这部分一般需要通过一些处理,跟之前的做法没什么区别。如果有区别,就是需要把数据做成Tensor类型。
  • 2. 模型的构造,这是核心,也是Pytorch提供给我们的便捷的地方。
  • 3. 优化相关的设置,这一块主要设置optimizer的选择以及配置等信息。
  • 4. 训练模型,这一部分需要循环我们的训练数据,并一步步通过optimizer来优化模型的参数。

数据的构造

数据的构造

至于数据这块,为了简单期间,先用一个模拟的数据来代替,而且这并不影响我们对后续环节的理解。

# make fake data
n_data = torch.ones(100, 2)
x0 = torch.normal(2*n_data, 1)      # class0 x data (tensor), shape=(100, 2)
y0 = torch.zeros(100)               # class0 y data (tensor), shape=(100, 1)
x1 = torch.normal(-2*n_data, 1)     # class1 x data (tensor), shape=(100, 2)
y1 = torch.ones(100)                # class1 y data (tensor), shape=(100, 1)

x = torch.cat((x0, x1), 0).type(torch.FloatTensor)  # shape (200, 2) FloatTensor = 32-bit floating
y = torch.cat((y0, y1), ).type(torch.LongTensor)    # shape (200,) LongTensor = 64-bit integer

```至于数据这块,为了简单期间,先用一个模拟的数据来代替,而且这并不影响我们对后续环节的理解。

```python

# make fake data
n_data = torch。ones(100, 2)
x0 = torch。normal(2*n_data, 1)      # class0 x data (tensor), shape=(100, 2)
y0 = torch。zeros(100)               # class0 y data (tensor), shape=(100, 1)

x1 = torch。normal(-2*n_data, 1)     # class1 x data (tensor), shape=(100, 2)
y1 = torch。ones(100)                # class1 y data (tensor), shape=(100, 1)

x = torch。cat((x0, x1), 0)。type(torch。FloatTensor)  # shape (200, 2) FloatTensor = 32-bit floating
y = torch。cat((y0, y1), )。type(torch。LongTensor)    # shape (200,) LongTensor = 64-bit integer

模型的构造

模型的构造

对于模型这部分,我们需要设计的是前向传播部分(forward),因为这部分其实决定了整个模型的细节,比如一个数据x进入模型之后,如何一步步转换成最终的输出。转换细节实际上就是模型的细节。 在构建模型时,我们通常会创建一个新的类(class),并起一个合适的名字给到神经网络,之后在初始化阶段定义模型中所使用的参数和部件,接着在forward()函数中设计输入到输出中所经历的所有的过程

class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden)   # hidden layer
self.out = torch.nn.Linear(n_hidden, n_output)   # output layer

def forward(self, x):
x = F.relu(self.hidden(x))      # activation function for hidden layer
x = self.out(x)
return x

net = Net(n_feature=2, n_hidden=10, n_output=2)     # define the network

```对于模型这部分,我们需要设计的是前向传播部分(forward),因为这部分其实决定了整个模型的细节,比如一个数据x进入模型之后,如何一步步转换成最终的输出。转换细节实际上就是模型的细节。 在构建模型时,我们通常会创建一个新的类(class),并起一个合适的名字给到神经网络,之后在初始化阶段定义模型中所使用的参数和部件,接着在<span class="study-main-color7">forward()</span>函数中设计输入到输出中所经历的所有的过程。

```python

class Net(torch。nn。Module):

def __init__(self, n_feature, n_hidden, n_output):
super(Net, self)。__init__()
self。hidden = torch。nn。Linear(n_feature, n_hidden)   # hidden layer

self。out = torch。nn。Linear(n_hidden, n_output)   # output layer

def forward(self, x):
x = F。relu(self。hidden(x))      # activation function for hidden layer
x = self。out(x)

return x

net = Net(n_feature=2, n_hidden=10, n_output=2)     # define the network

 

优化器选择和配置

设计好了模型之后,剩下的工作就是设计loss和配置优化器。在模型中我们定义了forward()函数内容,通过这个函数就可以得到对于输入的预测。有了预测就可以跟真实值做比较来计算损失了。所以首先要定义

损失函数的形态,是使用MSE还是交叉熵损失,还是Hinge Loss? 当然,这些取决于问题本身。在上述例子中,由于问题是二分类问题,我们决定选择交叉熵损失(entropy loss)。

loss_func = torch.nn.CrossEntropyLoss()  # the target label is NOT an one-hotted

```设计好了模型之后,剩下的工作就是设计loss和配置优化器。在模型中我们定义了<span class="study-main-color7">forward()</span>函数内容,通过这个函数就可以得到对于输入的预测。
有了预测就可以跟真实值做比较来计算损失了。所以首先要定义损失函数的形态,是使用<span class="study-main-color6">MSE</span>还是<span class="study-main-color6">交叉熵损失</span>,
还是<span class="study-main-color6">Hinge Loss</span>? 当然,这些取决于问题本身。在上述例子中,由于问题是二分类问题,
我们决定选择<span class="study-main-color6">交叉熵损失(entropy loss)</span>。

```python

loss_func = torch。nn。CrossEntropyLoss()  # the target label is NOT an one-hotted

 

主函数

完成了所有上述步骤之后,剩下的就是主函数部分了。在这里需要定义要循环多少次(epoch),如何保存中间结果,如何输出准确率等内容。

for t in range(50):
out = net(x)
loss = loss_func(out, y)
optimizer.zero_grad()   # clear gradients for next train

loss.backward()         # backpropagation, compute gradients
optimizer.step()        # apply gradients

if t % 2 == 0:

prediction = torch.max(out, 1)[1]

pred_y = prediction.data.numpy()

target_y = y.data.numpy()

accuracy = float((pred_y == target_y).astype(int).sum()) / float(target_y.size)

print ('Accuracy=%.2f' % accuracy)

plt.pause(0.1)

```完成了所有上述步骤之后,剩下的就是主函数部分了。在这里需要定义要循环多少次(epoch),如何保存中间结果,如何输出准确率等内容。

```python
for t in range(50):

out = net(x)

loss = loss_func(out, y)

optimizer.zero_grad()   # clear gradients for next train

loss.backward()         # backpropagation, compute gradients

optimizer.step()        # apply gradients

if t % 2 == 0:

prediction = torch。max(out, 1)[1]

pred_y = prediction.data.numpy()

target_y = y.data.numpy()

accuracy = float((pred_y == target_y).astype(int).sum()) / float(target_y.size)

print ('Accuracy=%.2f' % accuracy)

plt.pause(0.1)

完整代码如下:

"""
View more, visit my tutorial page: https://mofanpy.com/tutorials/
My Youtube Channel: https://www.youtube.com/user/MorvanZhou
Dependencies:
torch: 0.4
matplotlib
"""
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt

# torch.manual_seed(1)    # reproducible

# make fake data
n_data = torch.ones(100, 2)
x0 = torch.normal(2*n_data, 1)      # class0 x data (tensor), shape=(100, 2)
y0 = torch.zeros(100)               # class0 y data (tensor), shape=(100, 1)
x1 = torch.normal(-2*n_data, 1)     # class1 x data (tensor), shape=(100, 2)
y1 = torch.ones(100)                # class1 y data (tensor), shape=(100, 1)
x = torch.cat((x0, x1), 0).type(torch.FloatTensor)  # shape (200, 2) FloatTensor = 32-bit floating
y = torch.cat((y0, y1), ).type(torch.LongTensor)    # shape (200,) LongTensor = 64-bit integer

# The code below is deprecated in Pytorch 0.4. Now, autograd directly supports tensors
# x, y = Variable(x), Variable(y)

# plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn')
# plt.show()


class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)   # hidden layer
        self.out = torch.nn.Linear(n_hidden, n_output)   # output layer

    def forward(self, x):
        x = F.relu(self.hidden(x))      # activation function for hidden layer
        x = self.out(x)
        return x

net = Net(n_feature=2, n_hidden=10, n_output=2)     # define the network
print(net)  # net architecture

optimizer = torch.optim.SGD(net.parameters(), lr=0.02)
loss_func = torch.nn.CrossEntropyLoss()  # the target label is NOT an one-hotted

#plt.ion()   # something about plotting

for t in range(20):
    out = net(x)                 # input x and predict based on x
    loss = loss_func(out, y)     # must be (1. nn output, 2. target), the target label is NOT one-hotted

    optimizer.zero_grad()   # clear gradients for next train
    loss.backward()         # backpropagation, compute gradients
    optimizer.step()        # apply gradients

    if t % 2 == 0:
        # plot and show learning process
        #plt.cla()
        prediction = torch.max(out, 1)[1]
        pred_y = prediction.data.numpy()
        target_y = y.data.numpy()
        #plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=pred_y, s=100, lw=0, cmap='RdYlGn')
        accuracy = float((pred_y == target_y).astype(int).sum()) / float(target_y.size)
        #plt.text(1.5, -4, 'Accuracy=%.2f' % accuracy, fontdict={'size': 20, 'color':  'red'})
        print ('Accuracy=%.2f' % accuracy)
        plt.pause(0.1)

plt.show()

运行数据如下:

Net(
  (hidden): Linear(in_features=2, out_features=10, bias=True)
  (out): Linear(in_features=10, out_features=2, bias=True)
)
Accuracy=0.49
Accuracy=0.54
Accuracy=0.65
Accuracy=0.88
Accuracy=0.99
Accuracy=0.99
Accuracy=1.00
Accuracy=1.00
Accuracy=1.00
Accuracy=1.00