共计 8058 个字符,预计需要花费 21 分钟才能阅读完成。
TensorFlow 和 PyTorch 是两个最受欢迎的开源深度学习框架,这两个框架都为构建和训练深度学习模型提供了宽泛的性能,并已被研发社区宽泛采纳。然而作为用户,咱们始终想晓得哪种框架最适宜咱们本人特定我的项目,所以在本文与其余文章的个性的比照不同,咱们将以理论利用登程,从性能、可伸缩性和其余高级个性方面比拟 TensorFlow 和 PyTorch。
性能
在抉择深度学习框架时,一个要害的思考因素是你构建和训练的模型的性能。
TensorFlow 和 PyTorch 都进行了性能优化,这两个框架都提供了大量的工具和技术来进步模型的速度。
就原始性能而言,TensorFlow 比 PyTorch 更好一些。这两个框架之间的一个要害区别是应用动态计算图而不是动静计算图。在 TensorFlow 中,在模型训练之前,计算图是动态结构的。这使得 TensorFlow 能够通过剖析图并利用各种优化技术来更无效地优化图的性能。
而 PyTorch 应用动静计算图,这意味着图是在训练模型时动静构建的。尽管这可能更灵便,更容易应用,但在某些状况下也可能效率较低。
然而记住这一点很重要
TensorFlow 和 PyTorch 之间的性能差别相十分小,这是因为这两个框架都对性能进行了优化,并提供了许多工具和办法来进步模型的速度,在很多状况下基本发现不了他们的区别。
除了应用动态与动静计算图之外,还有许多其余因素会影响模型的性能。这些因素包含硬件和软件环境的抉择、模型的复杂性以及数据集的大小。通过思考这些因素并依据须要利用优化技术,能够应用 TensorFlow 或 PyTorch 构建和训练高性能模型。
除了原始性能,TensorFlow 和 PyTorch 都提供了大量的工具和办法来进步模型的速度:
TensorFlow 提供了多种优化办法,能够极大地提高模型的性能,例如主动混合精度和 XLA。
XLA(减速线性代数):TensorFlow 包含一个称为 XLA 的即时 (JIT) 编译器,它能够通过利用多种优化技术来优化模型的性能,包含常数折叠、代数简化和循环交融。要启用 XLA,能够应用 tf.config.optimizer.set_jit 函数。
TFX (TensorFlow Extended): TFX 是一套用于构建和部署机器学习管道的库和工具,包含用于数据处理、模型训练和模型服务的工具。TFX 能够通过自动化所波及的许多步骤,更无效地构建和部署机器学习模型。
tf.function 函数装璜器能够将 TensorFlow 函数编译成一个图,这可能比强制执行函数更快,能够利用 TensorFlow 的优化技术来进步模型的性能。
PyTorch 通过应用 torch.autograd 和 torch.jit 等提供了优化模型的办法,它进步模型的有效性
torch.autograd.profiler:通过跟踪 PyTorch 模型的各种元素应用的工夫和内存量,能够帮忙找到瓶颈和代码中须要改良的中央。
torch.nn.DataParallel:torch.nn.DataParallel 类可跨多个设施(例如 GPU)并行训练 PyTorch 模型。通过应用 DataParallel,能够利用多个设施来减少模型的推理效率。
torch.jit:应用即时 (JIT) 编译器优化 PyTorch 模型。torch.jit 将模型编译成动态计算图,与动态图相比能够更无效地进行优化。
动态与动静计算图定义的编码示例:
如前所述,TensorFlow 在原始性能方面比 PyTorch 略有劣势,这是因为它的动态计算图。
上面是一个在 TensorFlow 中构建前馈神经网络的简略例子:
importtensorflowastf
# Define the model
model=tf.keras.Sequential([tf.keras.layers.Dense(64, activation='relu', input_shape=(64,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# Compile the model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# Fit the model
model.fit(x_train, y_train, epochs=5)
上面是在 PyTorch 中实现和训练的雷同模型:
importtorch
importtorch.nnasnn
importtorch.optimasoptim
# Define the model
classNet(nn.Module):
def__init__(self):
super(Net, self).__init__()
self.fc1=nn.Linear(64, 64)
self.fc2=nn.Linear(64, 64)
self.fc3=nn.Linear(64, 10)
defforward(self, x):
x=self.fc1(x)
x=self.fc2(x)
x=self.fc3(x)
returnx
# Create the model instance
model=Net()
# Define the loss function and optimizer
criterion=nn.CrossEntropyLoss()
optimizer=optim.Adam(model.parameters())
# Training loop
forepochinrange(5):
# Forward pass
output=model(x_train)
loss=criterion(output, y_train)
# Backward pass and optimization step
optimizer.zero_grad()
loss.backward()
optimizer.step()
这两个例子都展现了如何构建和训练一个简略的前馈神经网络,尽管办法不同然而他们的性能根本却雷同。对于性能的比照,目前来说两个框架基本相同,差别能够忽略不计。
可伸缩性
在抉择深度学习框架时,另一个重要思考因素是可伸缩性。随着模型的复杂性和规模的增长,须要一个可能解决一直增长的计算需要的框架。
这两个框架都提供了扩大模型的策略,但它们解决问题的形式略有不同。
TensorFlow 在设计时思考了可伸缩性,并提供了许多用于分布式训练和部署的工具。
例如,TensorFlow 的 tf. distribute API 能够轻松地跨多个设施和服务器散发训练,而 TensorFlow Serving 能够将经过训练的模型部署到生产环境。
PyTorch 也提供用于分布式培训和部署的工具,但重点更多地放在钻研和开发上,而不是生产环境。
PyTorch 的 torch.nn.DataParallel 和 torch.nn.parallel.DistributedDataParallel 类能够跨多个设施并行训练,而 PyTorch Lightning 库(非官方)为分布式训练和部署提供了一个高级接口。
TensorFlow
- tf.distribute.Strategy:tf.distribute.Strategy API 可跨多个设施和机器并行训练 TensorFlow 模型。有许多不同的策略可用,包含 tf.distribute.MirroredStrategy,它反对在单台机器上的多个 GPU 上进行训练,以及 tf.distribute.experimental.MultiWorkerMirroredStrategy,它在具备多个 GPU 的多台机器上提供训练。
- tf.data.Dataset:能够为训练构建了高效且高度并行化的数据管道。通过应用 tf.data.Dataset,能够轻松地并行加载和预处理大型数据集,这能够模型扩大到更大的数据集。
- tf.keras.layers.Normalization:tf.keras.layers.Normalization 层实时规范化输出数据,这可能有助于进步模型的性能。利用归一化能够缩小大输出值的影响,这能够帮忙模型更快地收敛并取得更好的性能。
- tf.data.Dataset.interleave:通过对数据并行利用函数,再次并行处理输出数据。这对于数据预处理等工作十分有用,在这些工作中您须要对数据利用大量转换。
Pytorch
- torch.nn.parallel.DistributedDataParallel:torch.nn.parallel.DistributedDataParallel 类在多个设施和机器上并行训练 PyTorch 模型。然而须要应用 torch.nn.parallel.DistributedDataParallel.init_process_group 设置分布式训练环境。
- torch.utils.data.DataLoader:创立一个数据迭代器,用于并行处理数据的加载和预处理。
- torch.utils.data.distributed.DistributedSampler:相似于 torch.utils.data.DistributedSampler,但设计用于与 DistributedDataParallel 类一起应用。通过应用 DistributedSampler,能够确保在应用 DistributedDataParallel 进行训练时,每个设施都会收到均衡的数据样本。
通过利用这些函数和类,能够将 TensorFlow 和 PyTorch 模型扩大到更大的数据集和更弱小的硬件,构建更精确、更弱小的模型。
上面介绍了进步可伸缩性的两种不同办法。
TensorFlow 的第一个例子应用了 tf.distribute. mirrredstrategy:
importtensorflowastf
# Define the model
model=tf.keras.Sequential([tf.keras.layers.Dense(64, activation='relu', input_shape=(64,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# Compile the model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# Define the distribution strategy
strategy=tf.distribute.MirroredStrategy()
# Load the dataset
dataset=tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(64)
# Define the training loop
withstrategy.scope():
forepochinrange(5):
forx_batch, y_batchindataset:
model.fit(x_batch, y_batch)
在 PyTorch 应用 torch.nn.DataParallel :
importtorch
importtorch.nnasnn
importtorch.optimasoptim
# Define the model
classNet(nn.Module):
def__init__(self):
super(Net, self).__init__()
self.fc1=nn.Linear(64, 64)
self.fc2=nn.Linear(64, 64)
self.fc3=nn.Linear(64, 10)
defforward(self, x):
x=self.fc1(x)
x=self.fc2(x)
x=self.fc3(x)
returnx
# Create the model instance and wrap it in DataParallel
model=nn.DataParallel(Net())
# Define the loss function and optimizer
criterion=nn.CrossEntropyLoss()
optimizer=optim.Adam(model.parameters())
# Training loop
forepochinrange(5):
# Forward pass
output=model(x_train)
loss=criterion(output, y_train)
# Backward pass and optimization step
optimizer.zero_grad()
loss.backward()
optimizer.step()
这两个例子都展现了如何在多个设施上并行训练,但 TensorFlow 对于分布式训练的反对要比 Pytorch 更好一些。
高级的个性
除了性能和可伸缩性之外,这两个框架还提供了许多我的项目相干的高级个性。
例如,TensorFlow 领有弱小的工具和库生态系统,包含用于可视化的 TensorBoard 和用于模型部署和服务的 TensorFlow Extended。
PyTorch 也多个高级个性,个别都会命名为 torchXXX,比方 torchvision,torchaudio 等等
咱们以 TensorBoard 为例介绍两个库的应用,尽管 TensorBoard 是 TensorFlow 的一部分,然而 Pytorch 也通过代码局部兼容了数据局部的发送,也就是说应用 Pytorch 也能够往 TensorBoard 写入数据,而后通过 TensorBoard 进行查看。
TensorFlow 在训练时应用 TensorBoard 的 callback 能够主动写入。
importtensorflowastf
# Define the model
model=tf.keras.Sequential([tf.keras.layers.Dense(64, activation='relu', input_shape=(64,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# Compile the model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# Define a TensorBoard callback
tensorboard_callback=tf.keras.callbacks.TensorBoard(log_dir='logs')
# Fit the model
model.fit(x_train, y_train, epochs=5, callbacks=[tensorboard_callback])
Pytorch 须要自行代码写入:
importnumpyasnp
fromtorch.utils.tensorboardimportSummaryWriter
writer=SummaryWriter(comment='test_tensorboard')
forxinrange(100):
writer.add_scalar('y=2x', x*2, x)
writer.add_scalar('y=pow(2, x)', 2**x, x)
writer.add_scalars('data/scalar_group', {"xsinx": x*np.sin(x),
"xcosx": x*np.cos(x),
"arctanx": np.arctan(x)}, x)
writer.close()
在高级个性中我感觉最次要的就是 TensorFlow 中引入了 Keras,这样只须要几行代码就能够实现残缺的模型训练
# Compile the model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
而 Pytorch 还要手动进行损失计算,反向流传
output=model(x_train)
loss=criterion(output, y_train)
# Backward pass and optimization step
optimizer.zero_grad()
loss.backward()
optimizer.step()
尽管这样灵活性很高,然而应该有一个像 Keras 这样的通用办法(TensorFlow 也能够手动指定计算过程,并不是没有),所以在这一部分中我感觉 TensorFlow 要比 Pytorch 好很多。
当然也有一些第三方的库来简化 Pytorch 的训练过程比方 PyTorch Lightning、TorchHandle 等然而究竟不是官网的库。
最初总结
最适宜你的深度学习框架将取决于你的具体需要和要求
TensorFlow 和 PyTorch 都提供了宽泛的性能和高级个性,并且这两个框架都已被研发社区宽泛采纳。作为高级用户,我的集体倡议是深刻学习一个库,另外一个库代码基本上是相似的,根底到了基本上做到能看懂就能够了,比方
classDNNModel(nn.Module):
def__init__(self):
super(DNNModel, self).__init__()
self.fc1=nn.Linear(2,4)
self.fc2=nn.Linear(4,8)
self.fc3=nn.Linear(8,1)
# 正向流传
defforward(self,x):
x=F.relu(self.fc1(x))
x=F.relu(self.fc2(x))
y=nn.Sigmoid()(self.fc3(x))
returny
################
classDNNModel(models.Model):
def__init__(self):
super(DNNModel, self).__init__()
defbuild(self,input_shape):
self.dense1=layers.Dense(4,activation="relu",name="dense1")
self.dense2=layers.Dense(8,activation="relu",name="dense2")
self.dense3=layers.Dense(1,activation="sigmoid",name="dense3")
super(DNNModel,self).build(input_shape)
# 正向流传
@tf.function(input_signature=[tf.TensorSpec(shape= [None,2], dtype=tf.float32)])
defcall(self,x):
x=self.dense1(x)
x=self.dense2(x)
y=self.dense3(x)
returny
看看下面代码的两个类它们的区别并不大,对吧。
上面是 google trends 的趋势比照,咱们能够看到显著的区别
该学那个本人看吧
https://avoid.overfit.cn/post/786849900e314953a64565e5feb5076e
作者:Jan Marcel Kezmann