脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Python - PyTorch和NumPy深度比较!!!

PyTorch和NumPy深度比较!!!

2024-01-11 16:13DOWHAT小壮 Python

很多人对pytorch和numpy的边界感是模糊的,咱们今儿就从几方面进行整理和详细的说明。

嗨,我是小壮!

太多人催着让更新pytorch的内容了,我们最近总结了不少东西。

包括实用的一些操作,还有一些总结性的内容。

很多人对pytorch和numpy的边界感是模糊的,咱们今儿就从几方面进行整理和详细的说明。

每块知识点从简单对比到实际代码的对比,值得收藏起来慢慢看~

PyTorch和NumPy深度比较!!!

所有的内容,咱们从下面几个要点进行了对比:

  • 深度学习支持: PyTorch专注于深度学习任务,提供了动态计算图和内置的神经网络接口,而NumPy主要用于传统的科学计算,缺深度学习模块。
  • 自动微分: PyTorch具有自动微分功能,使得在构建和训练神经网络时更加灵活,而NumPy需要手动计算导数。
  • GPU加速: PyTorch内置GPU支持,使得在GPU上进行张量计算和模型训练更为便捷,而NumPy需要额外的库(如CuPy)才能实现GPU加速。
  • 模型部署: PyTorch提供了TorchScript和ONNX等工具,便于模型导出和部署,而NumPy通常需要额外的库和手动工作来实现模型的导出和部署。

总之,最显著的一点,就是NumPy主要负责数据的计算,而PyTorch更适用于深度学习任务,提供了更丰富的工具和接口。

具体分为 6 大部分,涉及到:

  • 张量计算
  • 自动微分
  • 深度学习支持
  • GPU加速
  • 模型部署
  • 代码风格

PyTorch和NumPy深度比较!!!

来吧,一起看看~

一、张量计算

  • NumPy: 主要用于数组操作,不提供专门的张量计算功能。NumPy数组是静态的,不支持自动微分。
  • PyTorch: 提供了动态计算图和自动微分,使其更适合深度学习任务。PyTorch的张量计算功能更灵活,可以轻松构建神经网络模型。

张量计算是PyTorch和NumPy的一个关键方面,因为两者都涉及对多维数组(张量)进行操作。

1. 张量的创建

NumPy:

import numpy as np

# 创建NumPy数组
np_array = np.array([[1, 2, 3], [4, 5, 6]])

# 查看数组属性
print("NumPy Array:")
print(np_array)
print("Shape:", np_array.shape)

PyTorch:

import torch

# 创建PyTorch张量
torch_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])

# 查看张量属性
print("PyTorch Tensor:")
print(torch_tensor)
print("Shape:", torch_tensor.shape)

2. 张量的运算

NumPy:

# NumPy数组运算
np_array1 = np.array([[1, 2, 3], [4, 5, 6]])
np_array2 = np.array([[7, 8, 9], [10, 11, 12]])

result_np = np_array1 + np_array2  # 或者使用 np.add(np_array1, np_array2)
print("NumPy Array Addition:")
print(result_np)

PyTorch:

# PyTorch张量运算
torch_tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
torch_tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])

result_torch = torch_tensor1 + torch_tensor2  # 或者使用 torch.add(torch_tensor1, torch_tensor2)
print("PyTorch Tensor Addition:")
print(result_torch)

3. 自动微分

NumPy:

# NumPy不支持自动微分,需要手动计算导数
x_np = np.array([2.0], dtype=float)
y_np = x_np**2
dy_dx_np = 2 * x_np
print("NumPy Manual Differentiation:")
print("Input:", x_np)
print("Output:", y_np)
print("Derivative:", dy_dx_np)

PyTorch:

# PyTorch支持自动微分
x_torch = torch.tensor([2.0], requires_grad=True)
y_torch = x_torch**2
y_torch.backward()
dy_dx_torch = x_torch.grad
print("PyTorch Autograd:")
print("Input:", x_torch)
print("Output:", y_torch)
print("Derivative:", dy_dx_torch)

4. GPU加速

NumPy:

# NumPy需要额外的库(如CuPy)才能实现GPU加速

PyTorch:

# PyTorch内置GPU支持
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
torch_tensor = torch_tensor.to(device)

5. 模型构建

NumPy:

# NumPy通常用于传统的科学计算,没有专门的深度学习模块

PyTorch:

# PyTorch提供了高级的神经网络构建接口
import torch.nn as nn

class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = nn.Linear(3, 1)

    def forward(self, x):
        return self.fc(x)

model = SimpleModel()

这些示例突显了PyTorch在深度学习任务中的优势,特别是在自动微分和GPU加速方面。然而,在传统科学计算任务中,NumPy仍然是一种非常强大和广泛使用的工具。

二、自动微分

  • NumPy: 不具备自动微分功能,需要手动计算导数。
  • PyTorch: 提供了动态计算图和自动微分,使得在神经网络中反向传播更加容易和直观。

自动微分允许计算图中的变量自动计算梯度。在这方面,PyTorch和NumPy有着显著的差异。

大家可以从基本操作方面进行对比,numpy只能是手动微分。

1. 自动微分

  • NumPy: NumPy不具备内建的自动微分功能。如果想要计算梯度,需要手动进行导数计算或者使用数值方法,例如有限差分。
  • PyTorch: PyTorch使用动态计算图来实现自动微分。每当执行一个操作时,PyTorch会在后台构建计算图,并且可以通过反向传播来自动计算梯度。

2. NumPy中的手动微分

import numpy as np

# NumPy中的手动微分
x_np = np.array([2.0], dtype=float)
y_np = x_np**2
dy_dx_np = 2 * x_np
print("NumPy Manual Differentiation:")
print("Input:", x_np)
print("Output:", y_np)
print("Derivative:", dy_dx_np)

在NumPy中,需要手动计算导数。上述示例演示了对函数 y=x^2 进行手动微分的过程。

3. PyTorch中的自动微分

import torch

# PyTorch中的自动微分
x_torch = torch.tensor([2.0], requires_grad=True)
y_torch = x_torch**2
y_torch.backward()
dy_dx_torch = x_torch.grad
print("PyTorch Autograd:")
print("Input:", x_torch)
print("Output:", y_torch)
print("Derivative:", dy_dx_torch)

在PyTorch中,只需将requires_grad设置为True,然后执行前向计算和backward()即可自动计算梯度。grad属性保存了计算得到的梯度。

4. 动态计算图

  • NumPy: NumPy使用静态计算图,因为它在计算之前需要完全定义好操作。
  • PyTorch: PyTorch使用动态计算图,这意味着计算图是在运行时构建的,可以根据需要进行灵活的更改。

5. 更复杂的示例 - 梯度下降

# PyTorch中使用梯度下降
learning_rate = 0.1
num_iterations = 100

x_torch = torch.tensor([2.0], requires_grad=True)

for _ in range(num_iterations):
    y_torch = x_torch**2
    y_torch.backward()
    
    # 使用梯度下降更新参数
    x_torch.data = x_torch.data - learning_rate * x_torch.grad.data
    
    # 梯度清零
    x_torch.grad.zero_()

print("Final Result after Gradient Descent:", x_torch.data)

这个示例演示了如何使用梯度下降优化一个简单的函数(y=x^2)的参数。PyTorch通过自动微分提供了方便的方式来计算和应用梯度。在每次迭代中,backward()计算梯度,然后通过梯度下降更新参数。

三、深度学习支持

  • NumPy: 主要用于传统的科学计算,没有专门的深度学习模块。
  • PyTorch: 专注于深度学习任务,提供了高级的神经网络构建和训练接口,如torch.nn和torch.optim等。

PyTorch专注于深度学习任务,提供了高级的神经网络构建和训练接口,而NumPy则更适用于传统的科学计算。

1. 神经网络构建

NumPy主要用于数组操作和科学计算,没有内建的深度学习模块。构建神经网络需要手动实现网络层和激活函数。 PyTorch提供了torch.nn模块,其中包含了各种预定义的网络层和激活函数。

import torch
import torch.nn as nn

# 定义神经网络
class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc1 = nn.Linear(10, 5)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(5, 1)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 创建模型实例
model = SimpleNet()

2. 损失函数和优化器

NumPy中,需要手动实现损失函数和优化器。通常需要使用梯度下降等优化算法。PyTorch提供了各种内建的损失函数和优化器,使得训练过程更加简单。

以下是一个简单的训练过程的例子:

import torch.optim as optim

# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练过程
for epoch in range(num_epochs):
    # 前向传播
    outputs = model(inputs)
    loss = criterion(outputs, targets)

    # 反向传播和优化
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

3. 自动微分和反向传播

NumPy不支持自动微分和反向传播。需要手动计算梯度并实现反向传播过程。PyTorch的动态计算图和自动微分使得反向传播变得简单。在上述示例中,通过loss.backward()即可自动计算梯度并进行反向传播。

4. GPU加速

NumPy需要额外的库(如CuPy)才能实现GPU加速。PyTorch内置GPU支持,可以直接在GPU上执行张量计算和模型训练。以下是将模型移动到GPU的例子:

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

5. 模型保存和加载

  • NumPy: 保存和加载模型需要手动实现,通常使用NumPy的np.save和np.load。
  • PyTorch: PyTorch提供了方便的模型保存和加载接口。以下是一个保存和加载模型的例子:
# 保存模型
torch.save(model.state_dict(), 'model.pth')

# 加载模型
model.load_state_dict(torch.load('model.pth'))

四、GPU加速

  • NumPy: 原生NumPy不支持GPU加速,但可以通过一些扩展库如CuPy来实现。
  • PyTorch: 内置GPU支持,可以直接在GPU上执行张量计算,提高深度学习模型的训练速度。

GPU加速是在深度学习中提高计算速度的重要因素之一。在这方面,PyTorch和NumPy有一些显著的差异。

以下是关于GPU加速的详细阐述和代码比较:

1. GPU加速概念

  • NumPy: NumPy本身不支持GPU加速。如果需要在GPU上执行操作,可能需要使用额外的库,如CuPy,来替代NumPy数组。
  • PyTorch: PyTorch内置了对CUDA(NVIDIA GPU加速)的支持,可以直接在GPU上执行张量计算和模型训练。

2. 在PyTorch中使用GPU

import torch

# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 创建张量并将其移动到GPU
tensor_on_cpu = torch.tensor([1, 2, 3])
tensor_on_gpu = tensor_on_cpu.to(device)

上述代码演示了如何检查GPU是否可用,并将PyTorch张量移动到GPU上。这是使用PyTorch进行GPU加速的基本步骤。

3. 在NumPy中使用GPU(使用CuPy)

import cupy as np  # 使用CuPy代替NumPy

# 创建CuPy数组
array_on_gpu = np.array([1, 2, 3])

在NumPy的情况下,可以通过使用CuPy来实现GPU加速。CuPy提供了与NumPy相似的接口,但在GPU上执行相应的操作。

4. PyTorch中的GPU加速训练

import torch
import torch.nn as nn
import torch.optim as optim

# 创建模型和数据
model = nn.Linear(5, 1)
data = torch.randn((100, 5)).to(device)
target = torch.randn((100, 1)).to(device)

# 将模型和数据移动到GPU
model.to(device)

# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 在GPU上进行训练
for epoch in range(num_epochs):
    outputs = model(data)
    loss = criterion(outputs, target)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

上述代码演示了如何在PyTorch中进行GPU加速的训练。在这个例子中,模型、输入数据和目标数据都被移动到GPU上。

5. NumPy与PyTorch GPU加速性能比较

在涉及大规模数据和复杂模型的深度学习任务中,PyTorch的GPU加速通常更为方便且性能更好。这主要是因为PyTorch在设计时就考虑了深度学习任务的需求,而NumPy更专注于通用科学计算。

五、模型部署

  • NumPy: 针对模型的部署可能需要将代码转换为其他框架或使用专门的工具。
  • PyTorch: 提供了一些工具(如TorchScript),可以将模型导出为可在不同环境中运行的形式,便于部署。

模型部署是将训练好的深度学习模型应用于实际生产环境的过程。在这方面,PyTorch和NumPy有一些区别,尤其是在模型导出和部署上。

以下是关于模型部署的详细阐述和代码比较:

1. PyTorch中的模型保存和加载

在PyTorch中,可以使用torch.save和torch.load来保存和加载整个模型或者模型的参数。

import torch
import torch.nn as nn

# 定义一个简单的模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)

model = SimpleModel()

# 保存整个模型
torch.save(model, 'model.pth')

# 或者只保存模型的参数
torch.save(model.state_dict(), 'model_params.pth')

# 加载模型
loaded_model = torch.load('model.pth')
loaded_model_params = SimpleModel()
loaded_model_params.load_state_dict(torch.load('model_params.pth'))

2. NumPy中的模型保存和加载

在NumPy中,可以使用numpy.save和numpy.load来保存和加载NumPy数组,但对于模型保存,通常需要使用其他库,如Joblib。

import numpy as np
from sklearn.externals import joblib

# 使用Joblib保存和加载模型
model = ...  # 的模型
joblib.dump(model, 'model.joblib')

loaded_model = joblib.load('model.joblib')

3. TorchScript

PyTorch引入了TorchScript,它允许将PyTorch模型导出为一种中间表示形式,可以在不同的环境中运行。这对于模型的部署提供了更灵活的选择。

import torch

# 定义并导出模型为TorchScript
class SimpleModel(torch.jit.ScriptModule):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = torch.nn.Linear(10, 1)

    @torch.jit.script_method
    def forward(self, x):
        return self.fc(x)

model = SimpleModel()
traced_model = torch.jit.trace(model, torch.rand(1, 10))

# 保存TorchScript模型
traced_model.save("traced_model.pt")

# 加载TorchScript模型
loaded_model = torch.jit.load("traced_model.pt")

4. ONNX

ONNX(Open Neural Network Exchange)是一种开放标准,允许在不同深度学习框架之间共享模型。PyTorch可以将模型导出为ONNX格式。

import torch
import torch.onnx

# 定义并导出模型为ONNX
class SimpleModel(torch.nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = torch.nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)

model = SimpleModel()
dummy_input = torch.randn(1, 10)

# 导出模型为ONNX
torch.onnx.export(model, dummy_input, "model.onnx", verbose=True)

# 可以使用ONNX Runtime或其他支持ONNX的库来部署模型

5. 部署时的注意事项

  • 依赖项: 确保部署环境中安装了正确的依赖项,包括PyTorch或NumPy。
  • 硬件兼容性: 确保部署环境的硬件兼容于模型。例如,如果模型在GPU上训练,确保部署环境中有相应的GPU。
  • 推理速度: 对于大规模部署,考虑使用模型量化、剪枝等技术以减小模型大小和提高推理速度。

总之,PyTorch提供了更多用于模型导出和部署的工具和库,使得在不同环境中更容易进行部署。NumPy在这方面相对更为基础,通常需要额外的工作来实现模型的导出和部署。

六、代码风格

  • NumPy: 通常使用面向过程的编程风格。
  • PyTorch: 更加面向对象,利用PyTorch的torch.nn模块进行模型构建。

代码风格是编写可读性强、易于维护的代码的一种约定。在深度学习中,PyTorch和NumPy在代码风格上有一些区别。以下是关于代码风格的详细阐述和比较:

1. 代码布局

  • NumPy: NumPy通常使用面向过程的编程风格。代码布局可能更接近传统的科学计算脚本,其中数组操作和数学运算在主程序中展开。
import numpy as np

# NumPy数组操作
array_a = np.array([1, 2, 3])
array_b = np.array([4, 5, 6])
result = array_a + array_b
print(result)
  • PyTorch: PyTorch更加面向对象,尤其是在构建神经网络时,使用torch.nn模块。代码通常包含模型定义、训练循环和评估等阶段。
import torch
import torch.nn as nn

# PyTorch神经网络
class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc = nn.Linear(3, 1)

    def forward(self, x):
        return self.fc(x)

# 使用模型
model = SimpleNet()
input_data = torch.randn((10, 3))
output = model(input_data)
print(output)

2. 变量和张量命名

  • NumPy: 变量命名通常采用小写字母和下划线,例如array_a。
  • PyTorch: 张量和模型参数通常采用驼峰式命名,例如inputData或modelParameters。

3. 自动微分和梯度更新

  • NumPy: NumPy不支持自动微分和梯度更新。在手动计算导数时,变量和操作通常都在同一个块中。
  • PyTorch: PyTorch的自动微分使得梯度更新更为直观,通常涉及backward()和优化器的使用。
import torch

# PyTorch自动微分
x = torch.tensor([2.0], requires_grad=True)
y = x**2
y.backward()
print(x.grad)

4. 异常处理

  • NumPy: 异常处理可能采用传统的try和except语句。
import numpy as np

# NumPy异常处理
try:
    result = np.divide(1, 0)
except ZeroDivisionError as e:
    print("Error:", e)
  • PyTorch: PyTorch通常使用torch.nn.Module中的异常来处理模型参数等问题。
import torch
import torch.nn as nn

# PyTorch异常处理
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.fc = nn.Linear(3, 1)

model = MyModel()

try:
    output = model(torch.tensor([1, 2, 3]))
except nn.modules.module.ModuleAttributeError as e:
    print("Error:", e)

5. 代码注释

  • NumPy: 注释通常用于解释复杂的算法或特殊的操作。
  • PyTorch: 由于深度学习中涉及许多独特的操作,注释用于解释模型结构、训练步骤以及梯度更新等。
import torch
import torch.nn as nn

# PyTorch代码注释
class SimpleNet(nn.Module):
    def __init__(self):
        """
        构造函数,定义神经网络结构。
        """
        super(SimpleNet, self).__init__()
        self.fc = nn.Linear(3, 1)

    def forward(self, x):
        """
        前向传播函数,定义数据如何在网络中传播。
        """
        return self.fc(x)

# 使用模型
model = SimpleNet()
input_data = torch.randn((10, 3))
output = model(input_data)

总体而言,NumPy和PyTorch在代码风格上有些许不同,因为它们分别用于传统的科学计算和深度学习。

原文地址:https://mp.weixin.qq.com/s?__biz=MzkyNzM4NzE0OA==&mid=2247484031&idx=1&sn=e62c396653b66a2a194b4fad0662ceaa

延伸 · 阅读

精彩推荐
  • PythonPython列表推导式与生成器表达式用法示例

    Python列表推导式与生成器表达式用法示例

    这篇文章主要介绍了Python列表推导式与生成器表达式用法,简单描述了Python列表推导式与生成器表达式的概念、功能,并结合具体实例形式分析了Python列表推...

    Rangethan10662021-01-13
  • Pythonpython 日期操作类代码

    python 日期操作类代码

    这篇文章主要介绍了python 日期操作类代码,里面涉及了python日期操作的一些基础知识,需要的朋友可以参考下...

    左眼神威4942021-02-18
  • Pythonpython数据可视化JupyterLab实用扩展程序Mito

    python数据可视化JupyterLab实用扩展程序Mito

    这篇文章主要为大家介绍了python数据可视化JupyterLab实用扩展程序Mito的功能应用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助...

    Python学习与数据挖掘4142022-03-04
  • Python通俗讲解python 装饰器

    通俗讲解python 装饰器

    这篇文章主要介绍了python 装饰器的相关资料,帮助大家更好的理解和学习python装饰器的相关知识,感兴趣的朋友可以了解下 ...

    把苹果v咬哭4732020-09-08
  • PythonPython wxPython库使用wx.ListBox创建列表框示例

    Python wxPython库使用wx.ListBox创建列表框示例

    这篇文章主要介绍了Python wxPython库使用wx.ListBox创建列表框,结合实例形式分析了wxPython库使用wx.ListBox创建列表框的简单实现方法及ListBox函数相关选项的功能...

    烈风8932021-03-31
  • Pythonpython for循环内输出和外输出方式

    python for循环内输出和外输出方式

    这篇文章主要介绍了python for循环内输出和外输出方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    脚本之家9162021-09-27
  • Python使用python为mysql实现restful接口

    使用python为mysql实现restful接口

    这篇文章主要介绍了使用python为mysql实现restful接口的相关资料,需要的朋友可以参考下...

    uml12422021-01-01
  • PythonPython计算一个点到所有点的欧式距离实现方法

    Python计算一个点到所有点的欧式距离实现方法

    今天小编就为大家分享一篇Python计算一个点到所有点的欧式距离实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    DiamondTan7982021-08-01