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