pandazjd 2018-03-25
TensorFlow最初是由Google Brain Team的研究人员和工程师开发的。其目的是面向深度神经网络和机器智能研究。自2015年底以来,该图书馆在GitHub上正式开源。TensorFlow对于快速进行基于图形的计算非常有用。灵活的TensorFlow API可以通过其支持GPU的体系结构在多个设备上部署模型。
简而言之,TensorFlow生态系统有三个主要组成部分:
用C ++编写的TensorFlow API包含用于定义模型和使用数据训练模型的API。它也有一个用户友好的Python界面。
TensorBoard是一个可视化工具包,可帮助分析,可视化和调试TensorFlow图形。
TensorFlow Serving是一种灵活的高性能服务系统,用于在生产环境中部署预先训练好的机器学习模型。也可以用C ++编写并可通过Python界面访问,Serving可以即时从旧模式切换到新模式。
TensorFlow已被广泛应用于学术研究和工业应用。一些值得注意的当前用途包括Deep Speech,RankBrain,SmartReply和设备计算机视觉。您可以在此GitHub仓库中查看一些最佳官方用途,研究模型,样本和TensorFlow教程。
我们来看一个正在运行的示例。在这里,我在随机数据上训练一个2层ReLU网络.
import numpy as np
import tensorflow as tf
# Batch size = 32, Input Dimension = 500, Hidden Dimension = 50
# Define computational graph
# Create placeholders
x = tf.placeholder(tf.float32, shape=(32, 500))
y = tf.placeholder(tf.float32, shape=(32, 500))
w1 = tf.placeholer(tf.float32, shape=(500, 50))
w2 = tf.placeholder(tf.float32, shape=(50, 500))
# Forward pass
h = tf.maximum(tf.matmul(x, w1), 0)
y_pred = tf.matmul(h, w2)
diff = y_pred - y
# Use predefined common losses
loss = tf.losses.mean_squared_error(y_pred, y)
# Compute loss of gradient
grad_w1, grad_w2 = tf.gradients(loss, [w1, w2])
# Run the graph multiple times
with tf.Session() as sess:
# Create numpy arrays
values = {x: np.random.randn(32, 500),
w1: np.random.randn(500, 50),
w2: np.random.randn(50, 500),
y: np.random.randn(32, 500)}
# Train the network
learning_rate = 1e-5
# Run the graph in a loop
for t in range(20):
out = sess.run([loss, grad_w1, grad_w2], feed_dict=values)
loss_val, grad_w1_val, grad_w2_val = out
values[w1] -= learning_rate * grad_w1_val
values[w2] -= learning_rate * grad_w2_val
这个代码有两个主要组件:定义计算图并多次运行这个图。在定义图形时,我为输入x,权重w1和w2以及目标y创建占位符。然后,在正向通过期间,我计算目标y和损失变量的预测值,这是y和y_pred之间的L2距离。最后,我告诉TensorFlow计算相对于w1和w2的梯度损失。完成构建图之后,我输入一个会话来运行图。在这里我创建了numpy数组,它将填充上面的占位符,将它们提供给x,y,w1,w2。为了训练网络,我反复运行图形,使用渐变来更新权重并获得numpy阵列的损失grad_w1和grad_w2。
Keras:高级包装
深度学习框架在两个抽象级别 上运行:低级 - 实现数学运算和神经网络基元(TensorFlow,Theano,PyTorch等)和高级别 - 使用低级基元来实现神经网络抽象,例如模型和层(Keras)。
Keras是其后端库的包装,可以是TensorFlow或Theano - 这意味着如果您将Keras与TensorFlow后端结合使用,则可以运行TensorFlow代码。Keras为您提供了许多细节信息,因为它针对神经网络技术消费者,非常适合那些练习数据科学的人。它允许简单快速的原型设计,支持多种神经网络体系结构,并可在CPU / GPU上无缝运行。
import keras
import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import SGD
# Batch size = 32, Input Dimension = 500, Hidden Dimension = 50
# Create the model
model = Sequential()
model.add(Dense(input_dim=500, output_dim=50))
model.add(Activation('relu'))
model.add(Dense(input_dim=50, output_dim=500))
# Define optimizer object
optimizer = SGD(lr=1e0)
# Compile the model
model.compile(loss='mean_squared_error', optimizer=optimizer)
# Randomize data
x = np.random.randn(32, 500)
y = np.random.randn(32, 500)
# Fit the model
model.fit(x, y, epochs=50, batch_size=64, verbose=0)
Theano是另一个用于快速数值计算的Python库,可以在CPU或GPU上运行。它是蒙特利尔大学蒙特利尔学习算法小组开发的一个开源项目。它的一些最突出的特性包括GPU的透明使用,与NumPy的紧密集成,高效的符号差异化,速度/稳定性优化以及广泛的单元测试。
遗憾的是,Youshua Bengio(MILA实验室负责人)在2017年11月宣布他们将不再积极维护或开发Theano。原因在于Theano多年来推出的大部分创新技术现在已被其他框架所采用和完善。如果有兴趣,你仍然可以贡献它的开源库。
Theano在许多方面与TensorFlow相似。那么让我们来看看另一个使用相同批量和输入/输出尺寸的代码示例来训练神经网络:
import theano
import theano.tensor as T
# Batch size = 32, Input Dimension = 500, Hidden Dimension = 50, Number of Classes = 5
# Define symbolic variables
x = T.matrix('x')
y = T.vector('y', dtype='int64')
w1 = T.matrix('w1')
w2 = T.matrix('w2')
# Forward pass: compute scores
a = x.dot(w1)
a_relu = T.nnet.relu(a)
scores = a_relu.dot(w2)
# Forward pass: compute softmax loss
probs = T.nnet.softmax(scores)
loss = T.nnet.categorical_crossentropy(probs, y).mean()
# Backward pass: compute gradients
dw1, dw2 = T.grad(loss, [w1, w2])
# Compile function
f = theano.function(
inputs = [x, y, w1, w2],
outputs = [loss, scores, dw1, dw2],
)
# Run the function
xx = np.random.rand(32, 500)
yy = np.random.randint(5, size=32)
ww1 = 1e-2 * np.random.randn(500, 50)
ww2 = 1e-2 * np.random.randn(50, 5)
learning_rate = 1e-1
for t in xrange(20):
loss, scores, dww1, dww2 = f(xx, yy, ww1, ww2)
print loss
ww1 -= learning_rate * dww1
ww2 -= learning_rate * dww2
我首先定义了Theano符号变量。对于正向传球,我计算预测和损失; 对于后向传球,我计算梯度。然后我编译一个函数,根据数据和权重计算损失,分数和渐变。最后,我多次运行这个功能来训练网络。
PyTorch是一个相对较新的深度学习框架,正迅速在研究人员中流行起来。Facebook人工智能研究团队开发该应用软件,以应对前任图书馆Torch的挑战。由于编程语言Lua的普及程度不高,Torch永远无法体验Google TensorFlow的发展。因此,PyTorch采用了本地Python命令式编程风格,这已经为许多研究人员,开发人员和数据科学家所熟悉。它还支持动态计算图,这一特性使得它对使用时间序列和自然语言处理数据的研究人员和工程师很有吸引力。
最好采用迄今来自尤伯杯,其中已建成火法 -用PyTorch作为其后端通用概率编程语言。PyTorch的动态执行差异化和构建梯度的能力对于概率模型中的随机操作非常有价值。
PyTorch的3个抽象层次:
张量:势在必行ndarray,但在GPU上运行
变量:计算图中的节点; 存储数据和渐变
模块:神经网络层; 可以存储状态或可学习权重
在这里我将关注张量抽象层次。PyTorch张量就像numpy数组,但是它们可以在GPU上运行。没有内置的计算图形或梯度或深度学习的概念。在这里,我们使用PyTorch Tensors拟合一个2层网络:
import torch
# Batch Size = 32, Input Dimension = 500, Hidden Dimension = 50, Output Dimension = 5
dtype = torch.FloatTensor
# Create random tensors for data and weights
x = torch.randn(32, 500).type(dtype)
y = torch.randn(32, 5).type(dtype)
w1 = torch.randn(500, 50).type(dtype)
w2 = torch.randn(50, 5).type(dtype)
learning_rate = 1e-6
for t in range(250):
# Forward pass: Compute predictions and loss
h = x.mm(w1)
h_relu = h.clamp(min=0)
y_pred = h_relu.mm(w2)
loss = (y_pred - y).pow(2).sum()
# Backward pass: Compute gradients
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.t().mm(grad_y_pred)
grad_h_relu = grad_y_pred.mm(w2.t())
grad_h = grad_h_relu.clone()
grad_h[h < 0] = 0
grad_w1 = x.t().mm(grad_h)
# Gradient descent step on weights
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
正如你所看到的,我首先为数据和权重创建随机张量。然后我计算正向通过期间的预测和损失,并在反向通过期间手动计算梯度。我也为每个重量添加渐变下降步骤。最后,我通过多次运行该功能来训练网络。
我们来谈谈Torch。它是Facebook的开源机器学习库,科学计算框架和基于Lua编程语言的脚本语言。它提供了广泛的深度学习算法,并已被Facebook,IBM,Yandex和其他公司用于解决数据流的硬件问题。
作为PyTorch的直接祖先,Torch分享了很多C后端。与具有3个抽象级别的PyTorch不同,火炬只有2个:张量和模块。让我们使用Torch's张量探索一个代码教程培训2层网络:
require 'torch'
require 'nn'
require 'optim'
-- Build a model as a sequence of layers, and a loss function
local model = nn.Sequential()
model:add(nn.Linear(500, 50))
model:add(nn.ReLU())
model:add(nn.Linear(50, 5))
local loss_fn = nn.CrossEntropyCriterion()
local x = torch.randn(32, 500)
local y = torch.Tensor(32):random(5)
local weights, grad_weights = model:getParameters()
-- Define callback
local function f(w)
assert(w == weights)
-- Forward Pass
local stores = model:forward(x)
local loss = loss_fn:forward(scores, y)
-- Backward Pass
grad_weights:zero()
local grad_scores = loss_fn:backward(scores,y)
local grad_x = model:backward(x, grad_scores)
return loss, grad_weights
end
-- Pass callback to optimizer
local state = {learningRate=1e-3}
for t = 1, 25 do
optim.adam(f, weights, state)
end
最初,我建立了一个模型作为一系列图层,以及一个损失函数。接下来,我定义一个回调函数,输入权重并在权重上产生损失/梯度。在函数内部,我计算向前传球中的预测和损失,以及向后传球中的渐变。最后,我一遍又一遍地将这个回调函数传递给优化器。
Caffe是一个深思熟虑的表达,速度和模块化的深度学习框架。它由伯克利人工智能研究小组和伯克利视觉和学习中心开发。虽然其核心是用C ++编写的,但Caffe有Python和Matlab绑定。这对训练或微调前馈分类模型非常有用。虽然它在研究中使用得并不多,但它仍然很受部署模型的欢迎,正如社区贡献者所证明的那样。
为了使用Caffe训练和微调神经网络,您需要经过4个步骤:
转换数据:我们读取数据文件,然后清理并以Caffe可以使用的格式存储它们。我们将编写一个处理数据预处理和存储的Python脚本。
定义模型:模型定义了神经网络的结构。我们选择一个CNN体系结构,并在带扩展名的配置文件中定义它的参数 .prototxt。
定义求解器:求解器负责模型优化,定义所有关于如何进行梯度下降的信息。我们在带扩展名的配置文件中定义求解器参数 .prototxt。
训练模型:一旦我们准备好模型和解算器,我们就通过caffe从终端调用二进制来训练模型。训练好模型后,我们将训练好的模型放入带扩展名的文件中 .caffemodel。
我不会为Caffe做代码漫游,但是您可以在Caffe的主页上查看一个教程。总的来说,Caffe对于前馈网络和微调现有网络非常有用。您可以轻松地训练模型而无需编写任何代码。它的Python接口非常有用,因为您可以在不使用Python代码的情况下部署模型。不利的一面是,您需要为每个新的GPU图层编写核心C ++代码(在Caffe下)。因此,大网络(AlexNet,VGG,GoogLeNet,ResNet等)非常麻烦。
随着Theano不再被开发,Torch以不熟悉的语言Lua编写,而Caffe处于其早熟状态,TensorFlow和PyTorch成为大多数深度学习实践者的首选框架。虽然这两个框架都使用Python,但它们之间存在一些差异:
PyTorch有一个更清洁的界面,更易于使用,特别适合初学者。编写代码(大部分)感觉直观,而不是与图书馆进行战斗。另一方面,TensorFlow在如此众多的小型,模糊的图书馆中更为繁琐。
然而,TensorFlow配备了更多的支持和一个非常庞大,充满活力和乐于助人的社区。这意味着TensorFlow的在线课程,代码教程,文档和博客帖子多于PyTorch。
也就是说,PyTorch作为一个新平台,有许多有趣的功能尚未实现。PyTorch在短短一年多时间内取得了惊人的成绩。
TensorFlow更具可扩展性,并且与分布式执行非常兼容。它支持从单个GPU到大量系统的所有内容,这些系统涉及大量的分布式强化学习和实时试验和错误。
最重要的是,TensorFlow是“Define-and-Run”,可以在图形结构中定义条件和迭代,然后运行它。另一方面,PyTorch是“按运行定义”,其中图形结构在正向计算过程中被即时定义。换句话说,TensorFlow使用静态计算图,而PyTorch使用动态计算图。基于动态图的方法为复杂体系结构(如动态神经网络)提供了更简单的可调试性和更强的处理能力。基于静态图的方法可以更方便地部署到移动设备,更容易部署到更具异国情调的体系结构,以及提前编译技术的能力。
因此,PyTorch更适合于爱好者和小型项目的快速原型开发,而TensorFlow更适合大规模部署,尤其是在考虑跨平台和嵌入式部署时。TensorFlow经受了时间的考验,并且仍然被广泛使用。它对大型项目具有更多功能和更好的可扩展性。PyTorch越来越容易学习,但它并没有相同的整合。这对于需要快速完成的小型项目非常有用,但对于产品部署并不是最佳选择。