windows tensorflow 输入输出节点 查找_深度学习在花椒直播的应用:TensorFlow原理篇...

825e40e23ad41efd054f9760a9bb9539.png

本文转载自公众号:花椒技术,点击查看原文。深度学习的应用

d306b336c1b3a33368cd68c2e087d52b.png

花椒直播的深度学习使用
  • 使用Spark进行数据清洗,构建用户画像和物品画像,挖掘数据特征,形成数据集存储在HDFS。

  • 使用TensorFlow作为深度学习计算框架,通过Hbox调度深度学习作业,使用集群分布式训练。训练模型使用TF Serving部署,封装成TF-Web对内提供预测接口,线上使用Go Server提供推荐服务。

d8bd3d9c98cc74850be8fff496295c6e.png TensorFlow和TensorSlowTensorFlow是Google在2015年开源的深度学习框架,是目前最主流的深度学习计算框架。代码库本身有高达100万+的代码量,分为前端代码和后端代码。如此庞大的代码量造成了很多人不理解TensorFlow到底如何工作。为此,GitHub上有个名为TensorSlow的项目,使用纯Python的方式重构了TensorFlow底层。该项目旨在帮助理解TensorFlow的工作机制而不在意效率,所以取名TensorSlow。本文就以TensorSlow项目为基础,向大家梳理一下TensorFlow底层到底干了哪些事,对理解深度学习框架底层原理大有裨益。深度学习简介

d306b336c1b3a33368cd68c2e087d52b.png

深度学习是机器学习的重要分支,是为了研究深层神经网络的结构和有效训练而演化来的一系列方法。 神经网络概念:常见的深度模型使用的是前馈神经网络(多层感知机),它使用一个映射函数: f3db3691d338d3b138d59a95d6b27d12.png来定义模型,其中为输入,θ为模型参数。由于模型函数可以和一个有向无环图(DAG)等价,所以被称为网络。隐藏层:映射函数通常是多层的复合函数,例如: 578545749c061e01f459871a9067135f.png输入x是输入层,中间函数对应于隐藏层,输出y是输出层。代价函数:衡量模型函数和数据集之间的距离的函数(最大似然)。它是模型参数θ的函数,记为J(θ)。梯度下降:选择模型参数能使代价函数J(θ)最小化的优化方法。以梯度下降为代表的一系列优化方法,通过向参数θ的负梯度方向迭代,来寻找最优的参数θ。数量级:参数的数量通常有几十万到数百亿不等。 611c78089dbdcb63624488a8b346ec2f.png 前向传播当神经网络接收到输入层x后,经过网络不断向前流动,经过每一个隐藏层,最后传播到输出层y的过程,称为前向传播。在监督学习中,通常输出层y还会进一步得到代价函数J(θ)。 反向传播从代价函数J(θ)出发,经过网络向后流动,传播到每一个参数上,计算出J(θ)对该参数θ的梯度的过程,称为方向传播。之后,可以通过梯度下降等优化方法,得到模型的最优参数。TensorFlow做了什么?

d306b336c1b3a33368cd68c2e087d52b.png

计算图(Computational Graph)深度学习模型的落地离不开计算图,计算图可以认为是深度模型的描述语言,是神经网络计算的函数描述。计算图被定义为有向图(DAG),其中的节点对应于变量。通过计算图,可以方便的表达复杂计算。 ec516850874cc7b369536004d93d7836.png上面的图例展示了一个简单的计算图,它对应于这么一个仿射变换: e1e9f5474b16995d906b3ad964756d94.png其中x是输入节点,A,b 是模型参数。 节点(Vertex)在计算图中,节点用来表示一个变量。节点的输入和输出称为Tensor(它可以是标量,向量,矩阵或者更高维的)。根据输入输出的不同,节点可以分为以下三类:Placeholder节点:整个计算图的输入节点。节点只有输出值,传递给它的子节点consumers。

class placeholder:

def __init__(self):

self.consumers = []

_default_graph.placeholders.append(self)

Variable节点:计算图中表示模型参数的节点。Variable节点拥有初始值value,将输出传递给它的子节点consumers。

class Variable:

def __init__(self, initial_value = None):

self.value = initial_value

self.consumers = []

_default_graph.variables.append(self)

Operation节点:使用Variable节点或Placeholder节点来组成简单的函数,可以通过复合Operation节点来建立复杂网络。它具有输入和输出,输入由父节点input_nodes传递,输出传递到子节点consumers中。而compute方法需要继承,用来表述Operation节点所表示的函数计算。

class Operation:

def __init__(self, input_nodes=[]):

self.input_nodes = input_nodes

self.consumers = []

for input_node in input_nodes:

input_node.consumers.append(self)

_default_graph.operations.append(self)

def compute(self):

pass

Addition Operation的具体写法:

class add(Operation):

def __init__(self, x, y):

super().__init__([x, y])

def compute(self, x_value, y_value):

self.inputs = [x_value, y_value]

return x_value + y_value

图(Graph)使用一个Graph类来绑定计算图中的所有节点(opeartions、placeholders和varaibles)。当创建新的graph的时候,可以调用asdefault方法来设置为这张图的default_graph,这样不用显式地将节点绑定到图中。

class Graph:

def __init__(self):

"""Construct Graph"""

self.operations = []

self.placeholders = []

self.variables = []

def as_default(self):

global _default_graph

_default_graph = self

会话(Session)完成了图定义,如何执行图?在TensorFlow中,通过定义Session实例,Client将计算图传递给后端,通过Session.run方法传递给master执行。计算图的输出是特定的Operation节点。而输出节点的计算依赖其他中间节点,必须保证operations是按拓扑顺序执行的,计算节点o之前,节点o的所有输入节点已经完成计算。比如,要计算z节点必须先计算出中间节点y。这里通过反向的后序遍历来完成拓扑排序。类似的,Session可以这么定义:

class Session:

def run(self, operation, feed_dict = {}):

"""Computes the output of an operation

"""

...

def traverse_postorder(operation):

nodes_postorder = []

def recurse(node):

if isinstance(node, Operation):

for input_node in node.input_nodes:

recurse(input_node)

nodes_postorder.append(node)

recurse(operation)

return nodes_postorder

session.run方法首先对节点进行拓扑排序,并根据排序结果依次计算节点输出,完成图的执行。 前向传递算法再回顾这张计算图: ec516850874cc7b369536004d93d7836.png它对应的放射变换可以用线性变换的方式写出,可以通过之前定义的代码完成前向传递的计算。 18dfd1570e41f5777a47e8f551d7f5be.png

# Create a new graph

Graph().as_default()

# Create variables

A = Variable([[1, 0], [0, -1]])

b = Variable([1, 1])

# Create placeholder

x = placeholder()

# Create hidden node y

y = matmul(A, x)

# Create output node z

z = add(y, b)

session = Session()

output = session.run(z, {x: [1, 2]})

print(output)

可以得到结果:

[ 2 -1]

构建损失函数深度学习中,分类任务通常使用交叉熵作为损失函数,它的公式如下: cee40a2cd7e79fc35d2379b7797d14f3.png其中c是数据集中的真实分类标签。损失函数的Operation节点J由许多基础Operation来构建。将输入和参数向量化,并添加节点J,改写后的计算图如下: 4136f218947916d1e8fcc5c636c6d043.png

# Create a new graph

Graph().as_default()

X = placeholder()

c = placeholder()

W = Variable([[1, -1],

[1, -1]])

b = Variable([0, 0])

p = softmax( add(matmul(X, W), b) )

# Cross-entropy loss

J = negative(reduce_sum(reduce_sum(multiply(c, log(p)), axis=1)))

session = Session()

print(session.run(J, {

X: np.concatenate((blue_points, red_points)),

c:

[[1, 0]] * len(blue_points)

+ [[0, 1]] * len(red_points)}))

梯度下降优化算法通过使用梯度下降方法来最小化代价函数,流程如下:
  1. 模型参数W和b设置随机初始值。

  2. 计算代价函数J对W和b的梯度。

  3. 分别在其负梯度的方向上下降一小步(使用learning_rate控制步长大小)。

  4. 回到步骤2,继续执行。

class GradientDescentOptimizer:

def __init__(self, learning_rate):

self.learning_rate = learning_rate

def minimize(self, loss):

learning_rate = self.learning_rate

class MinimizationOperation(Operation):

def compute(self):

# Compute gradients

grad_table = compute_gradients(loss)

for node in grad_table:

if type(node) == Variable:

grad = grad_table[node]

node.value -= learning_rate * grad

return MinimizationOperation()

computegradients函数通过反向传递算法计算梯度,gradtable字典存放了代价函数J节点对计算图中所有variable节点的当前梯度。 反向传递算法链式法则是计算梯度的基本法则。下图和公式显示了e对a的梯度计算: 3559cf3eddd3986a6c1c1f41a07c443f.png  b1092e40f9ccb491cc45c243721953c6.png反向传递的算法用链式法则来计算节点n的梯度:
  1. J节点自身的梯度为1。

  2. 对任意节点z的所有子节点consumer,计算子节点的梯度。

  3. 将子节点的梯度乘以节点z本身的梯度得到J节点对任意节点z的梯度。

按照这种方式,直到反向传递到节点n。如果节点J经过多个路径方向传递到该节点,那么对该节点来自不同路径的梯度求和。compute_gradients方法从J节点开始,使用BFS的方式执行上面的流程。它会先计算所有子节点的梯度,然后计算当前节点的梯度,直到传递到输出节点。

from queue import Queue

def compute_gradients(loss):

# grad_table[node] will contain the gradient of the loss w.r.t. the node's output

...

return grad_table

节点自身的梯度Operation的自身梯度通过预先定义,使用RegisterGradient注册到全局变量gradientregistry中。以sigmoid函数为例:

@RegisterGradient("sigmoid")

def _sigmoid_gradient(op, grad):

sigmoid = op.output

return grad * sigmoid * (1-sigmoid)

实践:搭建MLP

d306b336c1b3a33368cd68c2e087d52b.png

MLP是经典的神经网络,在深度学习中广泛使用。MLP由多个节点层组成,每一层全连接到下一层。除了输入节点,每个节点都是一个带有非线性激活函数的神经元。下面构建了一个含有3个隐层的MLP来进行分类任务: ef4059539c5597620ae67b038caccdeb.png

# Create a new graph

ts.Graph().as_default()

# Create training input placeholder

X = ts.placeholder()

# Create placeholder for the training classes

c = ts.placeholder()

# Build a hidden layer

W_hidden1 = ts.Variable(np.random.randn(2, 4))

b_hidden1 = ts.Variable(np.random.randn(4))

p_hidden1 = ts.sigmoid(ts.add(ts.matmul(X, W_hidden1), b_hidden1))

# Build a hidden layer

W_hidden2 = ts.Variable(np.random.randn(4, 8))

b_hidden2 = ts.Variable(np.random.randn(8))

p_hidden2 = ts.sigmoid(ts.add(ts.matmul(p_hidden1, W_hidden2), b_hidden2))

# Build a hidden layer

W_hidden3 = ts.Variable(np.random.randn(8, 2))

b_hidden3 = ts.Variable(np.random.randn(2))

p_hidden3 = ts.sigmoid(ts.add(ts.matmul(p_hidden2, W_hidden3), b_hidden3))

# Build the output layer

W_output = ts.Variable(np.random.randn(2, 2))

b_output = ts.Variable(np.random.randn(2))

p_output = ts.softmax(ts.add(ts.matmul(p_hidden3, W_output), b_output))

# Build cross-entropy loss

J = ts.negative(ts.reduce_sum(ts.reduce_sum(ts.multiply(c, ts.log(p_output)), axis=1)))

# Build minimization op

minimization_op = ts.train.GradientDescentOptimizer(learning_rate=0.03).minimize(J)

# Build placeholder inputs

feed_dict = {

X: np.concatenate((blue_points, red_points)),

c:

[[1, 0]] * len(blue_points)

+ [[0, 1]] * len(red_points)

}

# Create session

session = ts.Session()

# Perform 100 gradient descent steps

for step in range(2000):

J_value = session.run(J, feed_dict)

if step % 100 == 0:

print("Step:", step, " Loss:", J_value)

session.run(minimization_op, feed_dict)

通过可视化决策边界,可以发现模型学习到了比较复杂的非线性关系。 f377c15a4f14aa1da7584649d04c1a3b.png联系TensorFlow

d306b336c1b3a33368cd68c2e087d52b.png

  1. TensorSlow简单深刻的展示了深度学习框架底层的一般原理,加深理解生产使用的TensorFlow。

  2. TensorFlow后端使用C++高效实现。

  3. TensroFlow优化了算法过程,比如公共表达式消除,常量折叠。

  4. TensorFlow支持分布式,支持GPU等硬件设备。

  5. TensorFlow提供生产化的一系列工具。

基于Kubernetes的DevOps实战培训

5f5cf1d0ad5567563b1d5b1cbaf61765.png

基于Kubernetes的DevOps战培训将于2019年7月26日在上海开课,3天时间带你系统掌握Kubernetes,学习效果不好可以继续学习。本次培训包括:容器特性、镜像、网络;Kubernetes架构、核心组件、基本功能;Kubernetes设计理念、架构设计、基本功能、常用对象、设计原则;Kubernetes的数据库、运行时、网络、插件已经落地经验;微服务架构、组件、监控方案等, 点击下方图片或者阅读原文链接查看详情。儿聊下怎么样?做一个规模不大的封闭沙龙,定向邀请一些业内玩家在一起聊个半天? 93d33b87c49a620806bb748b5a1ea856.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值