详解:Tensorflow、Pytorch、Keras(搭建自己的深度学习网络)
由Google开发使用静态计算图广泛应用于生产环境有较为完善的部署工具由Facebook开发使用动态计算图更加灵活,适合研究和快速原型开发相对更加直观和易于调试最初是一个独立的高级API,现已成为TensorFlow的一部分提供更简单、更用户友好的接口可以使用TensorFlow或Theano作为后端适合快速实验和原型开发。
这是一个专门对Tensorflow、Pytorch、Keras三个主流DL框架的一个详解和对比分析
一、何为深度学习框架?
你可以理解为一个工具帮你构建一个深度学习网络,调用里面的各种方法就能自行构建任意层,diy你想要的DNN,而且任意指定学习器和优化器等,非常的方便!
二、Tensorflow
1.发展历史
TensorFlow由Google智能机器研究部门Google Brain团队研发的;TensorFlow编程接口支持Python和C++。随着1.0版本的公布,相继支持了Java、Go、R和Haskell API的alpha版本。
在2017年,Tensorflow独占鳌头,处于深度学习框架的领先地位;但截至目前已经和Pytorch不争上下。
注意,Tensorflow目前主要在工业级领域处于领先地位。参考至博客(38 封私信 / 16 条消息) 为什么说学术上用pytorch,工业上用tensorflow? - 知乎 (zhihu.com)
但说句实话,这个问题过于宏观,每个人都有自己的观点,最好还是自己实际两者都使用之后,再来说最适合自己的是哪一个吧。(并且tensoeflow和pytorch两者都一直在发展,后期有可能就不分伯仲啦!)
三、Pytorch
Pytorch目前是由Facebook人工智能学院提供支持服务的。
Pytorch目前主要在学术研究方向领域处于领先地位。
其优点在于:PyTorch可以使用强大的GPU加速的Tensor计算(比如:Numpy的使用)以及可以构建带有autograd的深度神经网络。
同时,PyTorch 的代码很简洁、易于使用、支持计算过程中的动态图而且内存使用很高效
四、Keras
本来是一个独立的高级API,现在已经成为Tensorflow的一部分
接口简单友好,使用tensorflow作为后端,适合快速实验和原型开发。
五、区别
主要区别:
-
计算图:
- TensorFlow使用静态计算图,需要先定义后运行
- PyTorch使用动态计算图,更灵活,可以边定义边运行
-
易用性:
- Keras通常被认为是最容易上手的
- PyTorch的API设计更加直观
- TensorFlow相对复杂一些,但提供更多底层控制
-
性能和部署:
- TensorFlow在大规模部署和性能优化方面较为成熟
- PyTorch在研究和实验阶段更受欢迎
- Keras作为高级API,性能可能略低,但开发速度快
-
社区和生态系统:
- TensorFlow拥有最大的社区和最广泛的工具支持
- PyTorch在学术界更受欢迎,增长迅速
- Keras作为TensorFlow的一部分,也有很好的社区支持
六、总结
-
TensorFlow:
- 由Google开发
- 使用静态计算图
- 广泛应用于生产环境
- 有较为完善的部署工具
-
PyTorch:
- 由Facebook开发
- 使用动态计算图
- 更加灵活,适合研究和快速原型开发
- 相对更加直观和易于调试
-
Keras:
- 最初是一个独立的高级API,现已成为TensorFlow的一部分
- 提供更简单、更用户友好的接口
- 可以使用TensorFlow或Theano作为后端
- 适合快速实验和原型开发
六、代码实现以及对比(key😍)
选择哪个框架通常取决于项目需求、个人偏好和团队经验。对于初学者,Keras可能是最好的起点;对于需要更多控制和自定义的高级用户,PyTorch或TensorFlow的低级API可能更合适。
使用TensorFlow、PyTorch和Keras分别搭建一个简单的深度神经网络的例子。这些例子都将创建一个简单的前馈神经网络用于MNIST手写数字分类任务。
1.TensorFlow 2.x 示例:(这里用的是低级API,没用tf.keras的高级API)
- 丰富的低级操作:允许对计算过程进行精细控制。
- 强大的性能优化:特别是在分布式和大规模部署方面。
- 全面的工具生态系统:包括TensorBoard、TFLite等工具。
- 灵活的模型部署:支持多种平台和设备。
- 静态图支持:虽然2.x版本默认使用动态图,但仍支持静态图,有利于某些优化。
同时下面这个例子展示了TensorFlow低级API的几个关键特性:
-
手动定义模型参数(W1, b1, W2, b2)作为tf.Variable。
-
使用函数定义模型结构,而不是使用Keras的Sequential或Functional API。
-
自定义损失函数。
-
使用tf.GradientTape来计算梯度。
-
手动应用梯度到优化器。
-
使用@tf.function装饰器来将Python函数转换为TensorFlow图,以提高性能。
-
手动实现训练循环和评估过程。
-
使用tf.data.Dataset API来处理数据。
import tensorflow as tf
import numpy as np
# 加载MNIST数据集
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# 将数据转换为适当的形状和类型
x_train = x_train.reshape(-1, 784).astype(np.float32)
x_test = x_test.reshape(-1, 784).astype(np.float32)
y_train = y_train.astype(np.int32)
y_test = y_test.astype(np.int32)
# 创建数据集
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(32)
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
# 定义模型参数
W1 = tf.Variable(tf.random.normal([784, 128], stddev=0.1))
b1 = tf.Variable(tf.zeros([128]))
W2 = tf.Variable(tf.random.normal([128, 10], stddev=0.1))
b2 = tf.Variable(tf.zeros([10]))
# 定义模型函数
def model(x):
layer1 = tf.nn.relu(tf.matmul(x, W1) + b1)
return tf.matmul(layer1, W2) + b2
# 定义损失函数
def loss_fn(predictions, labels):
return tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=predictions))
# 定义优化器
optimizer = tf.optimizers.Adam(learning_rate=0.001)
# 定义训练步骤
@tf.function
def train_step(x, y):
with tf.GradientTape() as tape:
predictions = model(x)
loss = loss_fn(predictions, y)
gradients = tape.gradient(loss, [W1, b1, W2, b2])
optimizer.apply_gradients(zip(gradients, [W1, b1, W2, b2]))
return loss
# 定义测试步骤
@tf.function
def test_step(x, y):
predictions = model(x)
loss = loss_fn(predictions, y)
accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(predictions, axis=1), y), tf.float32))
return loss, accuracy
# 训练循环
epochs = 5
for epoch in range(epochs):
total_loss = 0.0
num_batches = 0
for x_batch, y_batch in train_dataset:
loss = train_step(x_batch, y_batch)
total_loss += loss
num_batches += 1
avg_loss = total_loss / num_batches
# 在测试集上评估
test_loss = 0.0
test_accuracy = 0.0
num_test_batches = 0
for x_test_batch, y_test_batch in test_dataset:
batch_loss, batch_accuracy = test_step(x_test_batch, y_test_batch)
test_loss += batch_loss
test_accuracy += batch_accuracy
num_test_batches += 1
avg_test_loss = test_loss / num_test_batches
avg_test_accuracy = test_accuracy / num_test_batches
print(f"Epoch {epoch+1}/{epochs}")
print(f"Train Loss: {avg_loss:.4f}, Test Loss: {avg_test_loss:.4f}, Test Accuracy: {avg_test_accuracy:.4f}")
# 最终模型评估
final_test_loss = 0.0
final_test_accuracy = 0.0
num_final_batches = 0
for x_test_batch, y_test_batch in test_dataset:
batch_loss, batch_accuracy = test_step(x_test_batch, y_test_batch)
final_test_loss += batch_loss
final_test_accuracy += batch_accuracy
num_final_batches += 1
final_avg_test_loss = final_test_loss / num_final_batches
final_avg_test_accuracy = final_test_accuracy / num_final_batches
print("\nFinal Test Results:")
print(f"Test Loss: {final_avg_test_loss:.4f}, Test Accuracy: {final_avg_test_accuracy:.4f}")
2. PyTorch示例(复杂但可操作性强)
PyTorch的API设计更加直观,其实就跟python的编程一样,类似嵌套在python里面一样,类似从底层构建的一个深度学习网络,这虽然有一点点复杂,但是这使得整个搭建过程透明化可操作性极强,适合做研究的人,进行细节优化(魔改),进行底层控制。(复杂但可操作性强)
- 类似Python的编程风格:使用动态计算图,编码感觉更像普通Python编程。
- 面向对象的设计:模型定义为类,更符合Python用户的习惯。
- 即时执行:可以立即看到每一步的结果,便于调试。
- 灵活性:易于处理动态网络结构和复杂的研究型模型。
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
# 加载数据
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=1000, shuffle=False)
# 定义模型
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.flatten = nn.Flatten()
self.fc1 = nn.Linear(28 * 28, 128)
self.fc2 = nn.Linear(128, 10)
self.dropout = nn.Dropout(0.2)
def forward(self, x):
x = self.flatten(x)
x = torch.relu(self.fc1(x))
x = self.dropout(x)
x = self.fc2(x)
return x
model = Net()
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters())
# 训练模型
def train(model, device, train_loader, optimizer, epoch):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
# 运行训练
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
for epoch in range(1, 6):
train(model, device, train_loader, optimizer, epoch)
# 评估模型
model.eval()
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
pred = output.argmax(dim=1, keepdim=True)
correct += pred.eq(target.view_as(pred)).sum().item()
print(f'Accuracy: {correct / len(test_loader.dataset)}')
3. Keras示例(简单但没有什么可操作性)
- 高级API:Keras提供了非常简洁和直观的API,隐藏了许多底层复杂性。
- 模块化设计:可以轻松堆叠层来构建模型,如model.add(layer)。
- 内置常用模型:提供了许多预定义的架构,如Sequential模型。
- 一致的接口:无论后端如何(TensorFlow、Theano等),接口保持一致。
- 详细文档:有优秀的文档和大量教程。
比较简单,加载数据---构建模型(tf.keras自己叠就行)---编译模型(定义模型在训练过程中如何学习,使用什么优化器,使用什么损失函数评估模型性能,以及监控指标等)---训练模型---评估模型。
是不是非常的简单,结构清洗明了,确实在工程上是非常的适合的,搭建快速,便于部署
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.datasets import mnist
# 加载数据
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# 构建模型
model = keras.Sequential([
layers.Flatten(input_shape=(28, 28)),
layers.Dense(128, activation='relu'),
layers.Dropout(0.2),
layers.Dense(10, activation='softmax')
])
# 编译模型
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(x_train, y_train, epochs=5)
# 评估模型
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
print(f'Test accuracy: {test_acc}')
很明显:
- Keras适合快速原型设计和简单项目,学习曲线最平缓。
- PyTorch在研究和复杂模型开发中很受欢迎,因为它的直观性和灵活性。
- TensorFlow提供了从高级(Keras API)到低级的全方位控制,适合各种规模的项目,尤其是大规模部署。
这些示例展示了使用不同框架构建简单神经网络的基本步骤。每个框架都有其独特的语法和风格,但基本概念是相似的:
- 加载和预处理数据
- 定义模型结构
- 指定损失函数和优化器
- 训练模型
- 评估模型性能
需要注意的是,Keras现在是TensorFlow的一部分,所以TensorFlow和Keras的例子看起来非常相似。结合了keras的TensorFlow搭建DNN非常的简单(哥们当年用的LSTM就是用的TensorFlow搭建的),PyTorch的例子稍微复杂一些,因为它提供了更多的底层控制。(比如那个transformer的搭建就是依赖的PyTorch,比较复杂)
Final:个人eassy
对于我个人来讲,使用基于tensorflow的keras搭建我的网络确实是非常的简单便捷,这也比较适合我所做的研究方向,偏重于深度学习网络的应用研究,而不是执着于优化网络或者优化一些算法!哥们就是单纯一个套用别人开发的网络,然后自定义几层,设置一下优化器,损失函数啥的,调调参数,训练一下,出了效果,就行了。对优化这件事,哥们我是一点也不敢碰瓷的呀兄弟,这都是研究内容外的拓展学习了!!!也是我的小个人发展路径和能力提升的路子吧!
更多推荐
所有评论(0)